ns_gige.cc (11299:72046b9b3323) ns_gige.cc (11701:5e7599457b97)
1/*
2 * Copyright (c) 2004-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Nathan Binkert
29 * Lisa Hsu
30 */
31
32/** @file
33 * Device module for modelling the National Semiconductor
34 * DP83820 ethernet controller. Does not support priority queueing
35 */
36
37#include "dev/net/ns_gige.hh"
38
39#include <deque>
40#include <memory>
41#include <string>
42
43#include "base/debug.hh"
44#include "base/inet.hh"
45#include "base/types.hh"
46#include "config/the_isa.hh"
47#include "debug/EthernetAll.hh"
48#include "dev/net/etherlink.hh"
49#include "mem/packet.hh"
50#include "mem/packet_access.hh"
51#include "params/NSGigE.hh"
52#include "sim/system.hh"
53
54// clang complains about std::set being overloaded with Packet::set if
55// we open up the entire namespace std
56using std::make_shared;
57using std::min;
58using std::ostream;
59using std::string;
60
61const char *NsRxStateStrings[] =
62{
63 "rxIdle",
64 "rxDescRefr",
65 "rxDescRead",
66 "rxFifoBlock",
67 "rxFragWrite",
68 "rxDescWrite",
69 "rxAdvance"
70};
71
72const char *NsTxStateStrings[] =
73{
74 "txIdle",
75 "txDescRefr",
76 "txDescRead",
77 "txFifoBlock",
78 "txFragRead",
79 "txDescWrite",
80 "txAdvance"
81};
82
83const char *NsDmaState[] =
84{
85 "dmaIdle",
86 "dmaReading",
87 "dmaWriting",
88 "dmaReadWaiting",
89 "dmaWriteWaiting"
90};
91
92using namespace Net;
93using namespace TheISA;
94
95///////////////////////////////////////////////////////////////////////
96//
97// NSGigE PCI Device
98//
99NSGigE::NSGigE(Params *p)
100 : EtherDevBase(p), ioEnable(false),
101 txFifo(p->tx_fifo_size), rxFifo(p->rx_fifo_size),
102 txPacket(0), rxPacket(0), txPacketBufPtr(NULL), rxPacketBufPtr(NULL),
103 txXferLen(0), rxXferLen(0), rxDmaFree(false), txDmaFree(false),
104 txState(txIdle), txEnable(false), CTDD(false), txHalt(false),
105 txFragPtr(0), txDescCnt(0), txDmaState(dmaIdle), rxState(rxIdle),
106 rxEnable(false), CRDD(false), rxPktBytes(0), rxHalt(false),
107 rxFragPtr(0), rxDescCnt(0), rxDmaState(dmaIdle), extstsEnable(false),
108 eepromState(eepromStart), eepromClk(false), eepromBitsToRx(0),
109 eepromOpcode(0), eepromAddress(0), eepromData(0),
110 dmaReadDelay(p->dma_read_delay), dmaWriteDelay(p->dma_write_delay),
111 dmaReadFactor(p->dma_read_factor), dmaWriteFactor(p->dma_write_factor),
112 rxDmaData(NULL), rxDmaAddr(0), rxDmaLen(0),
113 txDmaData(NULL), txDmaAddr(0), txDmaLen(0),
114 rxDmaReadEvent(this), rxDmaWriteEvent(this),
115 txDmaReadEvent(this), txDmaWriteEvent(this),
116 dmaDescFree(p->dma_desc_free), dmaDataFree(p->dma_data_free),
117 txDelay(p->tx_delay), rxDelay(p->rx_delay),
118 rxKickTick(0), rxKickEvent(this), txKickTick(0), txKickEvent(this),
119 txEvent(this), rxFilterEnable(p->rx_filter),
120 acceptBroadcast(false), acceptMulticast(false), acceptUnicast(false),
121 acceptPerfect(false), acceptArp(false), multicastHashEnable(false),
122 intrDelay(p->intr_delay), intrTick(0), cpuPendingIntr(false),
123 intrEvent(0), interface(0)
124{
125
126
127 interface = new NSGigEInt(name() + ".int0", this);
128
129 regsReset();
130 memcpy(&rom.perfectMatch, p->hardware_address.bytes(), ETH_ADDR_LEN);
131
132 memset(&rxDesc32, 0, sizeof(rxDesc32));
133 memset(&txDesc32, 0, sizeof(txDesc32));
134 memset(&rxDesc64, 0, sizeof(rxDesc64));
135 memset(&txDesc64, 0, sizeof(txDesc64));
136}
137
138NSGigE::~NSGigE()
139{
140 delete interface;
141}
142
143/**
144 * This is to write to the PCI general configuration registers
145 */
146Tick
147NSGigE::writeConfig(PacketPtr pkt)
148{
149 int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
150 if (offset < PCI_DEVICE_SPECIFIC)
151 PciDevice::writeConfig(pkt);
152 else
153 panic("Device specific PCI config space not implemented!\n");
154
155 switch (offset) {
156 // seems to work fine without all these PCI settings, but i
157 // put in the IO to double check, an assertion will fail if we
158 // need to properly implement it
159 case PCI_COMMAND:
160 if (config.data[offset] & PCI_CMD_IOSE)
161 ioEnable = true;
162 else
163 ioEnable = false;
164 break;
165 }
166
167 return configDelay;
168}
169
170EtherInt*
171NSGigE::getEthPort(const std::string &if_name, int idx)
172{
173 if (if_name == "interface") {
174 if (interface->getPeer())
175 panic("interface already connected to\n");
176 return interface;
177 }
178 return NULL;
179}
180
181/**
182 * This reads the device registers, which are detailed in the NS83820
183 * spec sheet
184 */
185Tick
186NSGigE::read(PacketPtr pkt)
187{
188 assert(ioEnable);
189
190 //The mask is to give you only the offset into the device register file
191 Addr daddr = pkt->getAddr() & 0xfff;
192 DPRINTF(EthernetPIO, "read da=%#x pa=%#x size=%d\n",
193 daddr, pkt->getAddr(), pkt->getSize());
194
195
196 // there are some reserved registers, you can see ns_gige_reg.h and
197 // the spec sheet for details
198 if (daddr > LAST && daddr <= RESERVED) {
199 panic("Accessing reserved register");
200 } else if (daddr > RESERVED && daddr <= 0x3FC) {
201 return readConfig(pkt);
202 } else if (daddr >= MIB_START && daddr <= MIB_END) {
203 // don't implement all the MIB's. hopefully the kernel
204 // doesn't actually DEPEND upon their values
205 // MIB are just hardware stats keepers
206 pkt->set<uint32_t>(0);
207 pkt->makeAtomicResponse();
208 return pioDelay;
209 } else if (daddr > 0x3FC)
210 panic("Something is messed up!\n");
211
212 assert(pkt->getSize() == sizeof(uint32_t));
213 uint32_t &reg = *pkt->getPtr<uint32_t>();
214 uint16_t rfaddr;
215
216 switch (daddr) {
217 case CR:
218 reg = regs.command;
219 //these are supposed to be cleared on a read
220 reg &= ~(CR_RXD | CR_TXD | CR_TXR | CR_RXR);
221 break;
222
223 case CFGR:
224 reg = regs.config;
225 break;
226
227 case MEAR:
228 reg = regs.mear;
229 break;
230
231 case PTSCR:
232 reg = regs.ptscr;
233 break;
234
235 case ISR:
236 reg = regs.isr;
237 devIntrClear(ISR_ALL);
238 break;
239
240 case IMR:
241 reg = regs.imr;
242 break;
243
244 case IER:
245 reg = regs.ier;
246 break;
247
248 case IHR:
249 reg = regs.ihr;
250 break;
251
252 case TXDP:
253 reg = regs.txdp;
254 break;
255
256 case TXDP_HI:
257 reg = regs.txdp_hi;
258 break;
259
260 case TX_CFG:
261 reg = regs.txcfg;
262 break;
263
264 case GPIOR:
265 reg = regs.gpior;
266 break;
267
268 case RXDP:
269 reg = regs.rxdp;
270 break;
271
272 case RXDP_HI:
273 reg = regs.rxdp_hi;
274 break;
275
276 case RX_CFG:
277 reg = regs.rxcfg;
278 break;
279
280 case PQCR:
281 reg = regs.pqcr;
282 break;
283
284 case WCSR:
285 reg = regs.wcsr;
286 break;
287
288 case PCR:
289 reg = regs.pcr;
290 break;
291
292 // see the spec sheet for how RFCR and RFDR work
293 // basically, you write to RFCR to tell the machine
294 // what you want to do next, then you act upon RFDR,
295 // and the device will be prepared b/c of what you
296 // wrote to RFCR
297 case RFCR:
298 reg = regs.rfcr;
299 break;
300
301 case RFDR:
302 rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR);
303 switch (rfaddr) {
304 // Read from perfect match ROM octets
305 case 0x000:
306 reg = rom.perfectMatch[1];
307 reg = reg << 8;
308 reg += rom.perfectMatch[0];
309 break;
310 case 0x002:
311 reg = rom.perfectMatch[3] << 8;
312 reg += rom.perfectMatch[2];
313 break;
314 case 0x004:
315 reg = rom.perfectMatch[5] << 8;
316 reg += rom.perfectMatch[4];
317 break;
318 default:
319 // Read filter hash table
320 if (rfaddr >= FHASH_ADDR &&
321 rfaddr < FHASH_ADDR + FHASH_SIZE) {
322
323 // Only word-aligned reads supported
324 if (rfaddr % 2)
325 panic("unaligned read from filter hash table!");
326
327 reg = rom.filterHash[rfaddr - FHASH_ADDR + 1] << 8;
328 reg += rom.filterHash[rfaddr - FHASH_ADDR];
329 break;
330 }
331
332 panic("reading RFDR for something other than pattern"
333 " matching or hashing! %#x\n", rfaddr);
334 }
335 break;
336
337 case SRR:
338 reg = regs.srr;
339 break;
340
341 case MIBC:
342 reg = regs.mibc;
343 reg &= ~(MIBC_MIBS | MIBC_ACLR);
344 break;
345
346 case VRCR:
347 reg = regs.vrcr;
348 break;
349
350 case VTCR:
351 reg = regs.vtcr;
352 break;
353
354 case VDR:
355 reg = regs.vdr;
356 break;
357
358 case CCSR:
359 reg = regs.ccsr;
360 break;
361
362 case TBICR:
363 reg = regs.tbicr;
364 break;
365
366 case TBISR:
367 reg = regs.tbisr;
368 break;
369
370 case TANAR:
371 reg = regs.tanar;
372 break;
373
374 case TANLPAR:
375 reg = regs.tanlpar;
376 break;
377
378 case TANER:
379 reg = regs.taner;
380 break;
381
382 case TESR:
383 reg = regs.tesr;
384 break;
385
386 case M5REG:
387 reg = 0;
388 if (params()->rx_thread)
389 reg |= M5REG_RX_THREAD;
390 if (params()->tx_thread)
391 reg |= M5REG_TX_THREAD;
392 if (params()->rss)
393 reg |= M5REG_RSS;
394 break;
395
396 default:
397 panic("reading unimplemented register: addr=%#x", daddr);
398 }
399
400 DPRINTF(EthernetPIO, "read from %#x: data=%d data=%#x\n",
401 daddr, reg, reg);
402
403 pkt->makeAtomicResponse();
404 return pioDelay;
405}
406
407Tick
408NSGigE::write(PacketPtr pkt)
409{
410 assert(ioEnable);
411
412 Addr daddr = pkt->getAddr() & 0xfff;
413 DPRINTF(EthernetPIO, "write da=%#x pa=%#x size=%d\n",
414 daddr, pkt->getAddr(), pkt->getSize());
415
416 if (daddr > LAST && daddr <= RESERVED) {
417 panic("Accessing reserved register");
418 } else if (daddr > RESERVED && daddr <= 0x3FC) {
419 return writeConfig(pkt);
420 } else if (daddr > 0x3FC)
421 panic("Something is messed up!\n");
422
423 if (pkt->getSize() == sizeof(uint32_t)) {
424 uint32_t reg = pkt->get<uint32_t>();
425 uint16_t rfaddr;
426
427 DPRINTF(EthernetPIO, "write data=%d data=%#x\n", reg, reg);
428
429 switch (daddr) {
430 case CR:
431 regs.command = reg;
432 if (reg & CR_TXD) {
433 txEnable = false;
434 } else if (reg & CR_TXE) {
435 txEnable = true;
436
437 // the kernel is enabling the transmit machine
438 if (txState == txIdle)
439 txKick();
440 }
441
442 if (reg & CR_RXD) {
443 rxEnable = false;
444 } else if (reg & CR_RXE) {
445 rxEnable = true;
446
447 if (rxState == rxIdle)
448 rxKick();
449 }
450
451 if (reg & CR_TXR)
452 txReset();
453
454 if (reg & CR_RXR)
455 rxReset();
456
457 if (reg & CR_SWI)
458 devIntrPost(ISR_SWI);
459
460 if (reg & CR_RST) {
461 txReset();
462 rxReset();
463
464 regsReset();
465 }
466 break;
467
468 case CFGR:
469 if (reg & CFGR_LNKSTS ||
470 reg & CFGR_SPDSTS ||
471 reg & CFGR_DUPSTS ||
472 reg & CFGR_RESERVED ||
473 reg & CFGR_T64ADDR ||
474 reg & CFGR_PCI64_DET) {
475 // First clear all writable bits
476 regs.config &= CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS |
477 CFGR_RESERVED | CFGR_T64ADDR |
478 CFGR_PCI64_DET;
479 // Now set the appropriate writable bits
480 regs.config |= reg & ~(CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS |
481 CFGR_RESERVED | CFGR_T64ADDR |
482 CFGR_PCI64_DET);
483 }
484
485// all these #if 0's are because i don't THINK the kernel needs to
486// have these implemented. if there is a problem relating to one of
487// these, you may need to add functionality in.
488
489// grouped together and #if 0'ed to avoid empty if body and make clang happy
490#if 0
491 if (reg & CFGR_TBI_EN) ;
492 if (reg & CFGR_MODE_1000) ;
493
494 if (reg & CFGR_PINT_DUPSTS ||
495 reg & CFGR_PINT_LNKSTS ||
496 reg & CFGR_PINT_SPDSTS)
497 ;
498
499 if (reg & CFGR_TMRTEST) ;
500 if (reg & CFGR_MRM_DIS) ;
501 if (reg & CFGR_MWI_DIS) ;
502
503 if (reg & CFGR_DATA64_EN) ;
504 if (reg & CFGR_M64ADDR) ;
505 if (reg & CFGR_PHY_RST) ;
506 if (reg & CFGR_PHY_DIS) ;
507
508 if (reg & CFGR_REQALG) ;
509 if (reg & CFGR_SB) ;
510 if (reg & CFGR_POW) ;
511 if (reg & CFGR_EXD) ;
512 if (reg & CFGR_PESEL) ;
513 if (reg & CFGR_BROM_DIS) ;
514 if (reg & CFGR_EXT_125) ;
515 if (reg & CFGR_BEM) ;
516
517 if (reg & CFGR_T64ADDR) ;
518 // panic("CFGR_T64ADDR is read only register!\n");
519#endif
520 if (reg & CFGR_AUTO_1000)
521 panic("CFGR_AUTO_1000 not implemented!\n");
522
523 if (reg & CFGR_PCI64_DET)
524 panic("CFGR_PCI64_DET is read only register!\n");
525
526 if (reg & CFGR_EXTSTS_EN)
527 extstsEnable = true;
528 else
529 extstsEnable = false;
530 break;
531
532 case MEAR:
533 // Clear writable bits
534 regs.mear &= MEAR_EEDO;
535 // Set appropriate writable bits
536 regs.mear |= reg & ~MEAR_EEDO;
537
538 // FreeBSD uses the EEPROM to read PMATCH (for the MAC address)
539 // even though it could get it through RFDR
540 if (reg & MEAR_EESEL) {
541 // Rising edge of clock
542 if (reg & MEAR_EECLK && !eepromClk)
543 eepromKick();
544 }
545 else {
546 eepromState = eepromStart;
547 regs.mear &= ~MEAR_EEDI;
548 }
549
550 eepromClk = reg & MEAR_EECLK;
551
552 // since phy is completely faked, MEAR_MD* don't matter
553
554// grouped together and #if 0'ed to avoid empty if body and make clang happy
555#if 0
556 if (reg & MEAR_MDIO) ;
557 if (reg & MEAR_MDDIR) ;
558 if (reg & MEAR_MDC) ;
559#endif
560 break;
561
562 case PTSCR:
563 regs.ptscr = reg & ~(PTSCR_RBIST_RDONLY);
564 // these control BISTs for various parts of chip - we
565 // don't care or do just fake that the BIST is done
566 if (reg & PTSCR_RBIST_EN)
567 regs.ptscr |= PTSCR_RBIST_DONE;
568 if (reg & PTSCR_EEBIST_EN)
569 regs.ptscr &= ~PTSCR_EEBIST_EN;
570 if (reg & PTSCR_EELOAD_EN)
571 regs.ptscr &= ~PTSCR_EELOAD_EN;
572 break;
573
574 case ISR: /* writing to the ISR has no effect */
575 panic("ISR is a read only register!\n");
576
577 case IMR:
578 regs.imr = reg;
579 devIntrChangeMask();
580 break;
581
582 case IER:
583 regs.ier = reg;
584 break;
585
586 case IHR:
587 regs.ihr = reg;
588 /* not going to implement real interrupt holdoff */
589 break;
590
591 case TXDP:
592 regs.txdp = (reg & 0xFFFFFFFC);
593 assert(txState == txIdle);
594 CTDD = false;
595 break;
596
597 case TXDP_HI:
598 regs.txdp_hi = reg;
599 break;
600
601 case TX_CFG:
602 regs.txcfg = reg;
603#if 0
604 if (reg & TX_CFG_CSI) ;
605 if (reg & TX_CFG_HBI) ;
606 if (reg & TX_CFG_MLB) ;
607 if (reg & TX_CFG_ATP) ;
608 if (reg & TX_CFG_ECRETRY) {
609 /*
610 * this could easily be implemented, but considering
611 * the network is just a fake pipe, wouldn't make
612 * sense to do this
613 */
614 }
615
616 if (reg & TX_CFG_BRST_DIS) ;
617#endif
618
619#if 0
620 /* we handle our own DMA, ignore the kernel's exhortations */
621 if (reg & TX_CFG_MXDMA) ;
622#endif
623
624 // also, we currently don't care about fill/drain
625 // thresholds though this may change in the future with
626 // more realistic networks or a driver which changes it
627 // according to feedback
628
629 break;
630
631 case GPIOR:
632 // Only write writable bits
633 regs.gpior &= GPIOR_UNUSED | GPIOR_GP5_IN | GPIOR_GP4_IN
634 | GPIOR_GP3_IN | GPIOR_GP2_IN | GPIOR_GP1_IN;
635 regs.gpior |= reg & ~(GPIOR_UNUSED | GPIOR_GP5_IN | GPIOR_GP4_IN
636 | GPIOR_GP3_IN | GPIOR_GP2_IN | GPIOR_GP1_IN);
637 /* these just control general purpose i/o pins, don't matter */
638 break;
639
640 case RXDP:
641 regs.rxdp = reg;
642 CRDD = false;
643 break;
644
645 case RXDP_HI:
646 regs.rxdp_hi = reg;
647 break;
648
649 case RX_CFG:
650 regs.rxcfg = reg;
651#if 0
652 if (reg & RX_CFG_AEP) ;
653 if (reg & RX_CFG_ARP) ;
654 if (reg & RX_CFG_STRIPCRC) ;
655 if (reg & RX_CFG_RX_RD) ;
656 if (reg & RX_CFG_ALP) ;
657 if (reg & RX_CFG_AIRL) ;
658
659 /* we handle our own DMA, ignore what kernel says about it */
660 if (reg & RX_CFG_MXDMA) ;
661
662 //also, we currently don't care about fill/drain thresholds
663 //though this may change in the future with more realistic
664 //networks or a driver which changes it according to feedback
665 if (reg & (RX_CFG_DRTH | RX_CFG_DRTH0)) ;
666#endif
667 break;
668
669 case PQCR:
670 /* there is no priority queueing used in the linux 2.6 driver */
671 regs.pqcr = reg;
672 break;
673
674 case WCSR:
675 /* not going to implement wake on LAN */
676 regs.wcsr = reg;
677 break;
678
679 case PCR:
680 /* not going to implement pause control */
681 regs.pcr = reg;
682 break;
683
684 case RFCR:
685 regs.rfcr = reg;
686
687 rxFilterEnable = (reg & RFCR_RFEN) ? true : false;
688 acceptBroadcast = (reg & RFCR_AAB) ? true : false;
689 acceptMulticast = (reg & RFCR_AAM) ? true : false;
690 acceptUnicast = (reg & RFCR_AAU) ? true : false;
691 acceptPerfect = (reg & RFCR_APM) ? true : false;
692 acceptArp = (reg & RFCR_AARP) ? true : false;
693 multicastHashEnable = (reg & RFCR_MHEN) ? true : false;
694
695#if 0
696 if (reg & RFCR_APAT)
697 panic("RFCR_APAT not implemented!\n");
698#endif
699 if (reg & RFCR_UHEN)
700 panic("Unicast hash filtering not used by drivers!\n");
701
702 if (reg & RFCR_ULM)
703 panic("RFCR_ULM not implemented!\n");
704
705 break;
706
707 case RFDR:
708 rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR);
709 switch (rfaddr) {
710 case 0x000:
711 rom.perfectMatch[0] = (uint8_t)reg;
712 rom.perfectMatch[1] = (uint8_t)(reg >> 8);
713 break;
714 case 0x002:
715 rom.perfectMatch[2] = (uint8_t)reg;
716 rom.perfectMatch[3] = (uint8_t)(reg >> 8);
717 break;
718 case 0x004:
719 rom.perfectMatch[4] = (uint8_t)reg;
720 rom.perfectMatch[5] = (uint8_t)(reg >> 8);
721 break;
722 default:
723
724 if (rfaddr >= FHASH_ADDR &&
725 rfaddr < FHASH_ADDR + FHASH_SIZE) {
726
727 // Only word-aligned writes supported
728 if (rfaddr % 2)
729 panic("unaligned write to filter hash table!");
730
731 rom.filterHash[rfaddr - FHASH_ADDR] = (uint8_t)reg;
732 rom.filterHash[rfaddr - FHASH_ADDR + 1]
733 = (uint8_t)(reg >> 8);
734 break;
735 }
736 panic("writing RFDR for something other than pattern matching "
737 "or hashing! %#x\n", rfaddr);
738 }
739
740 case BRAR:
741 regs.brar = reg;
742 break;
743
744 case BRDR:
745 panic("the driver never uses BRDR, something is wrong!\n");
746
747 case SRR:
748 panic("SRR is read only register!\n");
749
750 case MIBC:
751 panic("the driver never uses MIBC, something is wrong!\n");
752
753 case VRCR:
754 regs.vrcr = reg;
755 break;
756
757 case VTCR:
758 regs.vtcr = reg;
759 break;
760
761 case VDR:
762 panic("the driver never uses VDR, something is wrong!\n");
763
764 case CCSR:
765 /* not going to implement clockrun stuff */
766 regs.ccsr = reg;
767 break;
768
769 case TBICR:
770 regs.tbicr = reg;
771 if (reg & TBICR_MR_LOOPBACK)
772 panic("TBICR_MR_LOOPBACK never used, something wrong!\n");
773
774 if (reg & TBICR_MR_AN_ENABLE) {
775 regs.tanlpar = regs.tanar;
776 regs.tbisr |= (TBISR_MR_AN_COMPLETE | TBISR_MR_LINK_STATUS);
777 }
778
779#if 0
780 if (reg & TBICR_MR_RESTART_AN) ;
781#endif
782
783 break;
784
785 case TBISR:
786 panic("TBISR is read only register!\n");
787
788 case TANAR:
789 // Only write the writable bits
790 regs.tanar &= TANAR_RF1 | TANAR_RF2 | TANAR_UNUSED;
791 regs.tanar |= reg & ~(TANAR_RF1 | TANAR_RF2 | TANAR_UNUSED);
792
793 // Pause capability unimplemented
794#if 0
795 if (reg & TANAR_PS2) ;
796 if (reg & TANAR_PS1) ;
797#endif
798
799 break;
800
801 case TANLPAR:
802 panic("this should only be written to by the fake phy!\n");
803
804 case TANER:
805 panic("TANER is read only register!\n");
806
807 case TESR:
808 regs.tesr = reg;
809 break;
810
811 default:
812 panic("invalid register access daddr=%#x", daddr);
813 }
814 } else {
815 panic("Invalid Request Size");
816 }
817 pkt->makeAtomicResponse();
818 return pioDelay;
819}
820
821void
822NSGigE::devIntrPost(uint32_t interrupts)
823{
824 if (interrupts & ISR_RESERVE)
825 panic("Cannot set a reserved interrupt");
826
827 if (interrupts & ISR_NOIMPL)
828 warn("interrupt not implemented %#x\n", interrupts);
829
830 interrupts &= ISR_IMPL;
831 regs.isr |= interrupts;
832
833 if (interrupts & regs.imr) {
834 if (interrupts & ISR_SWI) {
835 totalSwi++;
836 }
837 if (interrupts & ISR_RXIDLE) {
838 totalRxIdle++;
839 }
840 if (interrupts & ISR_RXOK) {
841 totalRxOk++;
842 }
843 if (interrupts & ISR_RXDESC) {
844 totalRxDesc++;
845 }
846 if (interrupts & ISR_TXOK) {
847 totalTxOk++;
848 }
849 if (interrupts & ISR_TXIDLE) {
850 totalTxIdle++;
851 }
852 if (interrupts & ISR_TXDESC) {
853 totalTxDesc++;
854 }
855 if (interrupts & ISR_RXORN) {
856 totalRxOrn++;
857 }
858 }
859
860 DPRINTF(EthernetIntr,
861 "interrupt written to ISR: intr=%#x isr=%#x imr=%#x\n",
862 interrupts, regs.isr, regs.imr);
863
864 if ((regs.isr & regs.imr)) {
865 Tick when = curTick();
866 if ((regs.isr & regs.imr & ISR_NODELAY) == 0)
867 when += intrDelay;
868 postedInterrupts++;
869 cpuIntrPost(when);
870 }
871}
872
873/* writing this interrupt counting stats inside this means that this function
874 is now limited to being used to clear all interrupts upon the kernel
875 reading isr and servicing. just telling you in case you were thinking
876 of expanding use.
877*/
878void
879NSGigE::devIntrClear(uint32_t interrupts)
880{
881 if (interrupts & ISR_RESERVE)
882 panic("Cannot clear a reserved interrupt");
883
884 if (regs.isr & regs.imr & ISR_SWI) {
885 postedSwi++;
886 }
887 if (regs.isr & regs.imr & ISR_RXIDLE) {
888 postedRxIdle++;
889 }
890 if (regs.isr & regs.imr & ISR_RXOK) {
891 postedRxOk++;
892 }
893 if (regs.isr & regs.imr & ISR_RXDESC) {
894 postedRxDesc++;
895 }
896 if (regs.isr & regs.imr & ISR_TXOK) {
897 postedTxOk++;
898 }
899 if (regs.isr & regs.imr & ISR_TXIDLE) {
900 postedTxIdle++;
901 }
902 if (regs.isr & regs.imr & ISR_TXDESC) {
903 postedTxDesc++;
904 }
905 if (regs.isr & regs.imr & ISR_RXORN) {
906 postedRxOrn++;
907 }
908
909 interrupts &= ~ISR_NOIMPL;
910 regs.isr &= ~interrupts;
911
912 DPRINTF(EthernetIntr,
913 "interrupt cleared from ISR: intr=%x isr=%x imr=%x\n",
914 interrupts, regs.isr, regs.imr);
915
916 if (!(regs.isr & regs.imr))
917 cpuIntrClear();
918}
919
920void
921NSGigE::devIntrChangeMask()
922{
923 DPRINTF(EthernetIntr, "interrupt mask changed: isr=%x imr=%x masked=%x\n",
924 regs.isr, regs.imr, regs.isr & regs.imr);
925
926 if (regs.isr & regs.imr)
927 cpuIntrPost(curTick());
928 else
929 cpuIntrClear();
930}
931
932void
933NSGigE::cpuIntrPost(Tick when)
934{
935 // If the interrupt you want to post is later than an interrupt
936 // already scheduled, just let it post in the coming one and don't
937 // schedule another.
938 // HOWEVER, must be sure that the scheduled intrTick is in the
939 // future (this was formerly the source of a bug)
940 /**
941 * @todo this warning should be removed and the intrTick code should
942 * be fixed.
943 */
944 assert(when >= curTick());
945 assert(intrTick >= curTick() || intrTick == 0);
946 if (when > intrTick && intrTick != 0) {
947 DPRINTF(EthernetIntr, "don't need to schedule event...intrTick=%d\n",
948 intrTick);
949 return;
950 }
951
952 intrTick = when;
953 if (intrTick < curTick()) {
954 intrTick = curTick();
955 }
956
957 DPRINTF(EthernetIntr, "going to schedule an interrupt for intrTick=%d\n",
958 intrTick);
959
960 if (intrEvent)
961 intrEvent->squash();
962 intrEvent = new IntrEvent(this, true);
963 schedule(intrEvent, intrTick);
964}
965
966void
967NSGigE::cpuInterrupt()
968{
969 assert(intrTick == curTick());
970
971 // Whether or not there's a pending interrupt, we don't care about
972 // it anymore
973 intrEvent = 0;
974 intrTick = 0;
975
976 // Don't send an interrupt if there's already one
977 if (cpuPendingIntr) {
978 DPRINTF(EthernetIntr,
979 "would send an interrupt now, but there's already pending\n");
980 } else {
981 // Send interrupt
982 cpuPendingIntr = true;
983
984 DPRINTF(EthernetIntr, "posting interrupt\n");
985 intrPost();
986 }
987}
988
989void
990NSGigE::cpuIntrClear()
991{
992 if (!cpuPendingIntr)
993 return;
994
995 if (intrEvent) {
996 intrEvent->squash();
997 intrEvent = 0;
998 }
999
1000 intrTick = 0;
1001
1002 cpuPendingIntr = false;
1003
1004 DPRINTF(EthernetIntr, "clearing interrupt\n");
1005 intrClear();
1006}
1007
1008bool
1009NSGigE::cpuIntrPending() const
1010{ return cpuPendingIntr; }
1011
1012void
1013NSGigE::txReset()
1014{
1015
1016 DPRINTF(Ethernet, "transmit reset\n");
1017
1018 CTDD = false;
1019 txEnable = false;;
1020 txFragPtr = 0;
1021 assert(txDescCnt == 0);
1022 txFifo.clear();
1023 txState = txIdle;
1024 assert(txDmaState == dmaIdle);
1025}
1026
1027void
1028NSGigE::rxReset()
1029{
1030 DPRINTF(Ethernet, "receive reset\n");
1031
1032 CRDD = false;
1033 assert(rxPktBytes == 0);
1034 rxEnable = false;
1035 rxFragPtr = 0;
1036 assert(rxDescCnt == 0);
1037 assert(rxDmaState == dmaIdle);
1038 rxFifo.clear();
1039 rxState = rxIdle;
1040}
1041
1042void
1043NSGigE::regsReset()
1044{
1045 memset(&regs, 0, sizeof(regs));
1046 regs.config = (CFGR_LNKSTS | CFGR_TBI_EN | CFGR_MODE_1000);
1047 regs.mear = 0x12;
1048 regs.txcfg = 0x120; // set drain threshold to 1024 bytes and
1049 // fill threshold to 32 bytes
1050 regs.rxcfg = 0x4; // set drain threshold to 16 bytes
1051 regs.srr = 0x0103; // set the silicon revision to rev B or 0x103
1052 regs.mibc = MIBC_FRZ;
1053 regs.vdr = 0x81; // set the vlan tag type to 802.1q
1054 regs.tesr = 0xc000; // TBI capable of both full and half duplex
1055 regs.brar = 0xffffffff;
1056
1057 extstsEnable = false;
1058 acceptBroadcast = false;
1059 acceptMulticast = false;
1060 acceptUnicast = false;
1061 acceptPerfect = false;
1062 acceptArp = false;
1063}
1064
1065bool
1066NSGigE::doRxDmaRead()
1067{
1068 assert(rxDmaState == dmaIdle || rxDmaState == dmaReadWaiting);
1069 rxDmaState = dmaReading;
1070
1071 if (dmaPending() || drainState() != DrainState::Running)
1072 rxDmaState = dmaReadWaiting;
1073 else
1074 dmaRead(rxDmaAddr, rxDmaLen, &rxDmaReadEvent, (uint8_t*)rxDmaData);
1075
1076 return true;
1077}
1078
1079void
1080NSGigE::rxDmaReadDone()
1081{
1082 assert(rxDmaState == dmaReading);
1083 rxDmaState = dmaIdle;
1084
1085 DPRINTF(EthernetDMA, "rx dma read paddr=%#x len=%d\n",
1086 rxDmaAddr, rxDmaLen);
1087 DDUMP(EthernetDMA, rxDmaData, rxDmaLen);
1088
1089 // If the transmit state machine has a pending DMA, let it go first
1090 if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting)
1091 txKick();
1092
1093 rxKick();
1094}
1095
1096bool
1097NSGigE::doRxDmaWrite()
1098{
1099 assert(rxDmaState == dmaIdle || rxDmaState == dmaWriteWaiting);
1100 rxDmaState = dmaWriting;
1101
1102 if (dmaPending() || drainState() != DrainState::Running)
1103 rxDmaState = dmaWriteWaiting;
1104 else
1105 dmaWrite(rxDmaAddr, rxDmaLen, &rxDmaWriteEvent, (uint8_t*)rxDmaData);
1106 return true;
1107}
1108
1109void
1110NSGigE::rxDmaWriteDone()
1111{
1112 assert(rxDmaState == dmaWriting);
1113 rxDmaState = dmaIdle;
1114
1115 DPRINTF(EthernetDMA, "rx dma write paddr=%#x len=%d\n",
1116 rxDmaAddr, rxDmaLen);
1117 DDUMP(EthernetDMA, rxDmaData, rxDmaLen);
1118
1119 // If the transmit state machine has a pending DMA, let it go first
1120 if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting)
1121 txKick();
1122
1123 rxKick();
1124}
1125
1126void
1127NSGigE::rxKick()
1128{
1129 bool is64bit = (bool)(regs.config & CFGR_M64ADDR);
1130
1131 DPRINTF(EthernetSM,
1132 "receive kick rxState=%s (rxBuf.size=%d) %d-bit\n",
1133 NsRxStateStrings[rxState], rxFifo.size(), is64bit ? 64 : 32);
1134
1135 Addr link, bufptr;
1136 uint32_t &cmdsts = is64bit ? rxDesc64.cmdsts : rxDesc32.cmdsts;
1137 uint32_t &extsts = is64bit ? rxDesc64.extsts : rxDesc32.extsts;
1138
1139 next:
1140 if (rxKickTick > curTick()) {
1141 DPRINTF(EthernetSM, "receive kick exiting, can't run till %d\n",
1142 rxKickTick);
1143
1144 goto exit;
1145 }
1146
1147 // Go to the next state machine clock tick.
1148 rxKickTick = clockEdge(Cycles(1));
1149
1150 switch(rxDmaState) {
1151 case dmaReadWaiting:
1152 if (doRxDmaRead())
1153 goto exit;
1154 break;
1155 case dmaWriteWaiting:
1156 if (doRxDmaWrite())
1157 goto exit;
1158 break;
1159 default:
1160 break;
1161 }
1162
1163 link = is64bit ? (Addr)rxDesc64.link : (Addr)rxDesc32.link;
1164 bufptr = is64bit ? (Addr)rxDesc64.bufptr : (Addr)rxDesc32.bufptr;
1165
1166 // see state machine from spec for details
1167 // the way this works is, if you finish work on one state and can
1168 // go directly to another, you do that through jumping to the
1169 // label "next". however, if you have intermediate work, like DMA
1170 // so that you can't go to the next state yet, you go to exit and
1171 // exit the loop. however, when the DMA is done it will trigger
1172 // an event and come back to this loop.
1173 switch (rxState) {
1174 case rxIdle:
1175 if (!rxEnable) {
1176 DPRINTF(EthernetSM, "Receive Disabled! Nothing to do.\n");
1177 goto exit;
1178 }
1179
1180 if (CRDD) {
1181 rxState = rxDescRefr;
1182
1183 rxDmaAddr = regs.rxdp & 0x3fffffff;
1184 rxDmaData =
1185 is64bit ? (void *)&rxDesc64.link : (void *)&rxDesc32.link;
1186 rxDmaLen = is64bit ? sizeof(rxDesc64.link) : sizeof(rxDesc32.link);
1187 rxDmaFree = dmaDescFree;
1188
1189 descDmaReads++;
1190 descDmaRdBytes += rxDmaLen;
1191
1192 if (doRxDmaRead())
1193 goto exit;
1194 } else {
1195 rxState = rxDescRead;
1196
1197 rxDmaAddr = regs.rxdp & 0x3fffffff;
1198 rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32;
1199 rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32);
1200 rxDmaFree = dmaDescFree;
1201
1202 descDmaReads++;
1203 descDmaRdBytes += rxDmaLen;
1204
1205 if (doRxDmaRead())
1206 goto exit;
1207 }
1208 break;
1209
1210 case rxDescRefr:
1211 if (rxDmaState != dmaIdle)
1212 goto exit;
1213
1214 rxState = rxAdvance;
1215 break;
1216
1217 case rxDescRead:
1218 if (rxDmaState != dmaIdle)
1219 goto exit;
1220
1221 DPRINTF(EthernetDesc, "rxDesc: addr=%08x read descriptor\n",
1222 regs.rxdp & 0x3fffffff);
1223 DPRINTF(EthernetDesc,
1224 "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n",
1225 link, bufptr, cmdsts, extsts);
1226
1227 if (cmdsts & CMDSTS_OWN) {
1228 devIntrPost(ISR_RXIDLE);
1229 rxState = rxIdle;
1230 goto exit;
1231 } else {
1232 rxState = rxFifoBlock;
1233 rxFragPtr = bufptr;
1234 rxDescCnt = cmdsts & CMDSTS_LEN_MASK;
1235 }
1236 break;
1237
1238 case rxFifoBlock:
1239 if (!rxPacket) {
1240 /**
1241 * @todo in reality, we should be able to start processing
1242 * the packet as it arrives, and not have to wait for the
1243 * full packet ot be in the receive fifo.
1244 */
1245 if (rxFifo.empty())
1246 goto exit;
1247
1248 DPRINTF(EthernetSM, "****processing receive of new packet****\n");
1249
1250 // If we don't have a packet, grab a new one from the fifo.
1251 rxPacket = rxFifo.front();
1252 rxPktBytes = rxPacket->length;
1253 rxPacketBufPtr = rxPacket->data;
1254
1255#if TRACING_ON
1256 if (DTRACE(Ethernet)) {
1257 IpPtr ip(rxPacket);
1258 if (ip) {
1259 DPRINTF(Ethernet, "ID is %d\n", ip->id());
1260 TcpPtr tcp(ip);
1261 if (tcp) {
1262 DPRINTF(Ethernet,
1263 "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
1264 tcp->sport(), tcp->dport(), tcp->seq(),
1265 tcp->ack());
1266 }
1267 }
1268 }
1269#endif
1270
1271 // sanity check - i think the driver behaves like this
1272 assert(rxDescCnt >= rxPktBytes);
1273 rxFifo.pop();
1274 }
1275
1276
1277 // dont' need the && rxDescCnt > 0 if driver sanity check
1278 // above holds
1279 if (rxPktBytes > 0) {
1280 rxState = rxFragWrite;
1281 // don't need min<>(rxPktBytes,rxDescCnt) if above sanity
1282 // check holds
1283 rxXferLen = rxPktBytes;
1284
1285 rxDmaAddr = rxFragPtr & 0x3fffffff;
1286 rxDmaData = rxPacketBufPtr;
1287 rxDmaLen = rxXferLen;
1288 rxDmaFree = dmaDataFree;
1289
1290 if (doRxDmaWrite())
1291 goto exit;
1292
1293 } else {
1294 rxState = rxDescWrite;
1295
1296 //if (rxPktBytes == 0) { /* packet is done */
1297 assert(rxPktBytes == 0);
1298 DPRINTF(EthernetSM, "done with receiving packet\n");
1299
1300 cmdsts |= CMDSTS_OWN;
1301 cmdsts &= ~CMDSTS_MORE;
1302 cmdsts |= CMDSTS_OK;
1303 cmdsts &= 0xffff0000;
1304 cmdsts += rxPacket->length; //i.e. set CMDSTS_SIZE
1305
1306#if 0
1307 /*
1308 * all the driver uses these are for its own stats keeping
1309 * which we don't care about, aren't necessary for
1310 * functionality and doing this would just slow us down.
1311 * if they end up using this in a later version for
1312 * functional purposes, just undef
1313 */
1314 if (rxFilterEnable) {
1315 cmdsts &= ~CMDSTS_DEST_MASK;
1316 const EthAddr &dst = rxFifoFront()->dst();
1317 if (dst->unicast())
1318 cmdsts |= CMDSTS_DEST_SELF;
1319 if (dst->multicast())
1320 cmdsts |= CMDSTS_DEST_MULTI;
1321 if (dst->broadcast())
1322 cmdsts |= CMDSTS_DEST_MASK;
1323 }
1324#endif
1325
1326 IpPtr ip(rxPacket);
1327 if (extstsEnable && ip) {
1328 extsts |= EXTSTS_IPPKT;
1329 rxIpChecksums++;
1330 if (cksum(ip) != 0) {
1331 DPRINTF(EthernetCksum, "Rx IP Checksum Error\n");
1332 extsts |= EXTSTS_IPERR;
1333 }
1334 TcpPtr tcp(ip);
1335 UdpPtr udp(ip);
1336 if (tcp) {
1337 extsts |= EXTSTS_TCPPKT;
1338 rxTcpChecksums++;
1339 if (cksum(tcp) != 0) {
1340 DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n");
1341 extsts |= EXTSTS_TCPERR;
1342
1343 }
1344 } else if (udp) {
1345 extsts |= EXTSTS_UDPPKT;
1346 rxUdpChecksums++;
1347 if (cksum(udp) != 0) {
1348 DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n");
1349 extsts |= EXTSTS_UDPERR;
1350 }
1351 }
1352 }
1353 rxPacket = 0;
1354
1355 /*
1356 * the driver seems to always receive into desc buffers
1357 * of size 1514, so you never have a pkt that is split
1358 * into multiple descriptors on the receive side, so
1359 * i don't implement that case, hence the assert above.
1360 */
1361
1362 DPRINTF(EthernetDesc,
1363 "rxDesc: addr=%08x writeback cmdsts extsts\n",
1364 regs.rxdp & 0x3fffffff);
1365 DPRINTF(EthernetDesc,
1366 "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n",
1367 link, bufptr, cmdsts, extsts);
1368
1369 rxDmaAddr = regs.rxdp & 0x3fffffff;
1370 rxDmaData = &cmdsts;
1371 if (is64bit) {
1372 rxDmaAddr += offsetof(ns_desc64, cmdsts);
1373 rxDmaLen = sizeof(rxDesc64.cmdsts) + sizeof(rxDesc64.extsts);
1374 } else {
1375 rxDmaAddr += offsetof(ns_desc32, cmdsts);
1376 rxDmaLen = sizeof(rxDesc32.cmdsts) + sizeof(rxDesc32.extsts);
1377 }
1378 rxDmaFree = dmaDescFree;
1379
1380 descDmaWrites++;
1381 descDmaWrBytes += rxDmaLen;
1382
1383 if (doRxDmaWrite())
1384 goto exit;
1385 }
1386 break;
1387
1388 case rxFragWrite:
1389 if (rxDmaState != dmaIdle)
1390 goto exit;
1391
1392 rxPacketBufPtr += rxXferLen;
1393 rxFragPtr += rxXferLen;
1394 rxPktBytes -= rxXferLen;
1395
1396 rxState = rxFifoBlock;
1397 break;
1398
1399 case rxDescWrite:
1400 if (rxDmaState != dmaIdle)
1401 goto exit;
1402
1403 assert(cmdsts & CMDSTS_OWN);
1404
1405 assert(rxPacket == 0);
1406 devIntrPost(ISR_RXOK);
1407
1408 if (cmdsts & CMDSTS_INTR)
1409 devIntrPost(ISR_RXDESC);
1410
1411 if (!rxEnable) {
1412 DPRINTF(EthernetSM, "Halting the RX state machine\n");
1413 rxState = rxIdle;
1414 goto exit;
1415 } else
1416 rxState = rxAdvance;
1417 break;
1418
1419 case rxAdvance:
1420 if (link == 0) {
1421 devIntrPost(ISR_RXIDLE);
1422 rxState = rxIdle;
1423 CRDD = true;
1424 goto exit;
1425 } else {
1426 if (rxDmaState != dmaIdle)
1427 goto exit;
1428 rxState = rxDescRead;
1429 regs.rxdp = link;
1430 CRDD = false;
1431
1432 rxDmaAddr = regs.rxdp & 0x3fffffff;
1433 rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32;
1434 rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32);
1435 rxDmaFree = dmaDescFree;
1436
1437 if (doRxDmaRead())
1438 goto exit;
1439 }
1440 break;
1441
1442 default:
1443 panic("Invalid rxState!");
1444 }
1445
1446 DPRINTF(EthernetSM, "entering next rxState=%s\n",
1447 NsRxStateStrings[rxState]);
1448 goto next;
1449
1450 exit:
1451 /**
1452 * @todo do we want to schedule a future kick?
1453 */
1454 DPRINTF(EthernetSM, "rx state machine exited rxState=%s\n",
1455 NsRxStateStrings[rxState]);
1456
1457 if (!rxKickEvent.scheduled())
1458 schedule(rxKickEvent, rxKickTick);
1459}
1460
1461void
1462NSGigE::transmit()
1463{
1464 if (txFifo.empty()) {
1465 DPRINTF(Ethernet, "nothing to transmit\n");
1466 return;
1467 }
1468
1469 DPRINTF(Ethernet, "Attempt Pkt Transmit: txFifo length=%d\n",
1470 txFifo.size());
1471 if (interface->sendPacket(txFifo.front())) {
1472#if TRACING_ON
1473 if (DTRACE(Ethernet)) {
1474 IpPtr ip(txFifo.front());
1475 if (ip) {
1476 DPRINTF(Ethernet, "ID is %d\n", ip->id());
1477 TcpPtr tcp(ip);
1478 if (tcp) {
1479 DPRINTF(Ethernet,
1480 "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
1481 tcp->sport(), tcp->dport(), tcp->seq(),
1482 tcp->ack());
1483 }
1484 }
1485 }
1486#endif
1487
1488 DDUMP(EthernetData, txFifo.front()->data, txFifo.front()->length);
1489 txBytes += txFifo.front()->length;
1490 txPackets++;
1491
1492 DPRINTF(Ethernet, "Successful Xmit! now txFifoAvail is %d\n",
1493 txFifo.avail());
1494 txFifo.pop();
1495
1496 /*
1497 * normally do a writeback of the descriptor here, and ONLY
1498 * after that is done, send this interrupt. but since our
1499 * stuff never actually fails, just do this interrupt here,
1500 * otherwise the code has to stray from this nice format.
1501 * besides, it's functionally the same.
1502 */
1503 devIntrPost(ISR_TXOK);
1504 }
1505
1506 if (!txFifo.empty() && !txEvent.scheduled()) {
1507 DPRINTF(Ethernet, "reschedule transmit\n");
1508 schedule(txEvent, curTick() + retryTime);
1509 }
1510}
1511
1512bool
1513NSGigE::doTxDmaRead()
1514{
1515 assert(txDmaState == dmaIdle || txDmaState == dmaReadWaiting);
1516 txDmaState = dmaReading;
1517
1518 if (dmaPending() || drainState() != DrainState::Running)
1519 txDmaState = dmaReadWaiting;
1520 else
1521 dmaRead(txDmaAddr, txDmaLen, &txDmaReadEvent, (uint8_t*)txDmaData);
1522
1523 return true;
1524}
1525
1526void
1527NSGigE::txDmaReadDone()
1528{
1529 assert(txDmaState == dmaReading);
1530 txDmaState = dmaIdle;
1531
1532 DPRINTF(EthernetDMA, "tx dma read paddr=%#x len=%d\n",
1533 txDmaAddr, txDmaLen);
1534 DDUMP(EthernetDMA, txDmaData, txDmaLen);
1535
1536 // If the receive state machine has a pending DMA, let it go first
1537 if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting)
1538 rxKick();
1539
1540 txKick();
1541}
1542
1543bool
1544NSGigE::doTxDmaWrite()
1545{
1546 assert(txDmaState == dmaIdle || txDmaState == dmaWriteWaiting);
1547 txDmaState = dmaWriting;
1548
1549 if (dmaPending() || drainState() != DrainState::Running)
1550 txDmaState = dmaWriteWaiting;
1551 else
1552 dmaWrite(txDmaAddr, txDmaLen, &txDmaWriteEvent, (uint8_t*)txDmaData);
1553 return true;
1554}
1555
1556void
1557NSGigE::txDmaWriteDone()
1558{
1559 assert(txDmaState == dmaWriting);
1560 txDmaState = dmaIdle;
1561
1562 DPRINTF(EthernetDMA, "tx dma write paddr=%#x len=%d\n",
1563 txDmaAddr, txDmaLen);
1564 DDUMP(EthernetDMA, txDmaData, txDmaLen);
1565
1566 // If the receive state machine has a pending DMA, let it go first
1567 if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting)
1568 rxKick();
1569
1570 txKick();
1571}
1572
1573void
1574NSGigE::txKick()
1575{
1576 bool is64bit = (bool)(regs.config & CFGR_M64ADDR);
1577
1578 DPRINTF(EthernetSM, "transmit kick txState=%s %d-bit\n",
1579 NsTxStateStrings[txState], is64bit ? 64 : 32);
1580
1581 Addr link, bufptr;
1582 uint32_t &cmdsts = is64bit ? txDesc64.cmdsts : txDesc32.cmdsts;
1583 uint32_t &extsts = is64bit ? txDesc64.extsts : txDesc32.extsts;
1584
1585 next:
1586 if (txKickTick > curTick()) {
1587 DPRINTF(EthernetSM, "transmit kick exiting, can't run till %d\n",
1588 txKickTick);
1589 goto exit;
1590 }
1591
1592 // Go to the next state machine clock tick.
1593 txKickTick = clockEdge(Cycles(1));
1594
1595 switch(txDmaState) {
1596 case dmaReadWaiting:
1597 if (doTxDmaRead())
1598 goto exit;
1599 break;
1600 case dmaWriteWaiting:
1601 if (doTxDmaWrite())
1602 goto exit;
1603 break;
1604 default:
1605 break;
1606 }
1607
1608 link = is64bit ? (Addr)txDesc64.link : (Addr)txDesc32.link;
1609 bufptr = is64bit ? (Addr)txDesc64.bufptr : (Addr)txDesc32.bufptr;
1610 switch (txState) {
1611 case txIdle:
1612 if (!txEnable) {
1613 DPRINTF(EthernetSM, "Transmit disabled. Nothing to do.\n");
1614 goto exit;
1615 }
1616
1617 if (CTDD) {
1618 txState = txDescRefr;
1619
1620 txDmaAddr = regs.txdp & 0x3fffffff;
1621 txDmaData =
1622 is64bit ? (void *)&txDesc64.link : (void *)&txDesc32.link;
1623 txDmaLen = is64bit ? sizeof(txDesc64.link) : sizeof(txDesc32.link);
1624 txDmaFree = dmaDescFree;
1625
1626 descDmaReads++;
1627 descDmaRdBytes += txDmaLen;
1628
1629 if (doTxDmaRead())
1630 goto exit;
1631
1632 } else {
1633 txState = txDescRead;
1634
1635 txDmaAddr = regs.txdp & 0x3fffffff;
1636 txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32;
1637 txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32);
1638 txDmaFree = dmaDescFree;
1639
1640 descDmaReads++;
1641 descDmaRdBytes += txDmaLen;
1642
1643 if (doTxDmaRead())
1644 goto exit;
1645 }
1646 break;
1647
1648 case txDescRefr:
1649 if (txDmaState != dmaIdle)
1650 goto exit;
1651
1652 txState = txAdvance;
1653 break;
1654
1655 case txDescRead:
1656 if (txDmaState != dmaIdle)
1657 goto exit;
1658
1659 DPRINTF(EthernetDesc, "txDesc: addr=%08x read descriptor\n",
1660 regs.txdp & 0x3fffffff);
1661 DPRINTF(EthernetDesc,
1662 "txDesc: link=%#x bufptr=%#x cmdsts=%#08x extsts=%#08x\n",
1663 link, bufptr, cmdsts, extsts);
1664
1665 if (cmdsts & CMDSTS_OWN) {
1666 txState = txFifoBlock;
1667 txFragPtr = bufptr;
1668 txDescCnt = cmdsts & CMDSTS_LEN_MASK;
1669 } else {
1670 devIntrPost(ISR_TXIDLE);
1671 txState = txIdle;
1672 goto exit;
1673 }
1674 break;
1675
1676 case txFifoBlock:
1677 if (!txPacket) {
1678 DPRINTF(EthernetSM, "****starting the tx of a new packet****\n");
1679 txPacket = make_shared<EthPacketData>(16384);
1680 txPacketBufPtr = txPacket->data;
1681 }
1682
1683 if (txDescCnt == 0) {
1684 DPRINTF(EthernetSM, "the txDescCnt == 0, done with descriptor\n");
1685 if (cmdsts & CMDSTS_MORE) {
1686 DPRINTF(EthernetSM, "there are more descriptors to come\n");
1687 txState = txDescWrite;
1688
1689 cmdsts &= ~CMDSTS_OWN;
1690
1691 txDmaAddr = regs.txdp & 0x3fffffff;
1692 txDmaData = &cmdsts;
1693 if (is64bit) {
1694 txDmaAddr += offsetof(ns_desc64, cmdsts);
1695 txDmaLen = sizeof(txDesc64.cmdsts);
1696 } else {
1697 txDmaAddr += offsetof(ns_desc32, cmdsts);
1698 txDmaLen = sizeof(txDesc32.cmdsts);
1699 }
1700 txDmaFree = dmaDescFree;
1701
1702 if (doTxDmaWrite())
1703 goto exit;
1704
1705 } else { /* this packet is totally done */
1706 DPRINTF(EthernetSM, "This packet is done, let's wrap it up\n");
1707 /* deal with the the packet that just finished */
1708 if ((regs.vtcr & VTCR_PPCHK) && extstsEnable) {
1709 IpPtr ip(txPacket);
1710 if (extsts & EXTSTS_UDPPKT) {
1711 UdpPtr udp(ip);
1712 if (udp) {
1713 udp->sum(0);
1714 udp->sum(cksum(udp));
1715 txUdpChecksums++;
1716 } else {
1717 Debug::breakpoint();
1718 warn_once("UDPPKT set, but not UDP!\n");
1719 }
1720 } else if (extsts & EXTSTS_TCPPKT) {
1721 TcpPtr tcp(ip);
1722 if (tcp) {
1723 tcp->sum(0);
1724 tcp->sum(cksum(tcp));
1725 txTcpChecksums++;
1726 } else {
1727 warn_once("TCPPKT set, but not UDP!\n");
1728 }
1729 }
1730 if (extsts & EXTSTS_IPPKT) {
1731 if (ip) {
1732 ip->sum(0);
1733 ip->sum(cksum(ip));
1734 txIpChecksums++;
1735 } else {
1736 warn_once("IPPKT set, but not UDP!\n");
1737 }
1738 }
1739 }
1740
1/*
2 * Copyright (c) 2004-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Nathan Binkert
29 * Lisa Hsu
30 */
31
32/** @file
33 * Device module for modelling the National Semiconductor
34 * DP83820 ethernet controller. Does not support priority queueing
35 */
36
37#include "dev/net/ns_gige.hh"
38
39#include <deque>
40#include <memory>
41#include <string>
42
43#include "base/debug.hh"
44#include "base/inet.hh"
45#include "base/types.hh"
46#include "config/the_isa.hh"
47#include "debug/EthernetAll.hh"
48#include "dev/net/etherlink.hh"
49#include "mem/packet.hh"
50#include "mem/packet_access.hh"
51#include "params/NSGigE.hh"
52#include "sim/system.hh"
53
54// clang complains about std::set being overloaded with Packet::set if
55// we open up the entire namespace std
56using std::make_shared;
57using std::min;
58using std::ostream;
59using std::string;
60
61const char *NsRxStateStrings[] =
62{
63 "rxIdle",
64 "rxDescRefr",
65 "rxDescRead",
66 "rxFifoBlock",
67 "rxFragWrite",
68 "rxDescWrite",
69 "rxAdvance"
70};
71
72const char *NsTxStateStrings[] =
73{
74 "txIdle",
75 "txDescRefr",
76 "txDescRead",
77 "txFifoBlock",
78 "txFragRead",
79 "txDescWrite",
80 "txAdvance"
81};
82
83const char *NsDmaState[] =
84{
85 "dmaIdle",
86 "dmaReading",
87 "dmaWriting",
88 "dmaReadWaiting",
89 "dmaWriteWaiting"
90};
91
92using namespace Net;
93using namespace TheISA;
94
95///////////////////////////////////////////////////////////////////////
96//
97// NSGigE PCI Device
98//
99NSGigE::NSGigE(Params *p)
100 : EtherDevBase(p), ioEnable(false),
101 txFifo(p->tx_fifo_size), rxFifo(p->rx_fifo_size),
102 txPacket(0), rxPacket(0), txPacketBufPtr(NULL), rxPacketBufPtr(NULL),
103 txXferLen(0), rxXferLen(0), rxDmaFree(false), txDmaFree(false),
104 txState(txIdle), txEnable(false), CTDD(false), txHalt(false),
105 txFragPtr(0), txDescCnt(0), txDmaState(dmaIdle), rxState(rxIdle),
106 rxEnable(false), CRDD(false), rxPktBytes(0), rxHalt(false),
107 rxFragPtr(0), rxDescCnt(0), rxDmaState(dmaIdle), extstsEnable(false),
108 eepromState(eepromStart), eepromClk(false), eepromBitsToRx(0),
109 eepromOpcode(0), eepromAddress(0), eepromData(0),
110 dmaReadDelay(p->dma_read_delay), dmaWriteDelay(p->dma_write_delay),
111 dmaReadFactor(p->dma_read_factor), dmaWriteFactor(p->dma_write_factor),
112 rxDmaData(NULL), rxDmaAddr(0), rxDmaLen(0),
113 txDmaData(NULL), txDmaAddr(0), txDmaLen(0),
114 rxDmaReadEvent(this), rxDmaWriteEvent(this),
115 txDmaReadEvent(this), txDmaWriteEvent(this),
116 dmaDescFree(p->dma_desc_free), dmaDataFree(p->dma_data_free),
117 txDelay(p->tx_delay), rxDelay(p->rx_delay),
118 rxKickTick(0), rxKickEvent(this), txKickTick(0), txKickEvent(this),
119 txEvent(this), rxFilterEnable(p->rx_filter),
120 acceptBroadcast(false), acceptMulticast(false), acceptUnicast(false),
121 acceptPerfect(false), acceptArp(false), multicastHashEnable(false),
122 intrDelay(p->intr_delay), intrTick(0), cpuPendingIntr(false),
123 intrEvent(0), interface(0)
124{
125
126
127 interface = new NSGigEInt(name() + ".int0", this);
128
129 regsReset();
130 memcpy(&rom.perfectMatch, p->hardware_address.bytes(), ETH_ADDR_LEN);
131
132 memset(&rxDesc32, 0, sizeof(rxDesc32));
133 memset(&txDesc32, 0, sizeof(txDesc32));
134 memset(&rxDesc64, 0, sizeof(rxDesc64));
135 memset(&txDesc64, 0, sizeof(txDesc64));
136}
137
138NSGigE::~NSGigE()
139{
140 delete interface;
141}
142
143/**
144 * This is to write to the PCI general configuration registers
145 */
146Tick
147NSGigE::writeConfig(PacketPtr pkt)
148{
149 int offset = pkt->getAddr() & PCI_CONFIG_SIZE;
150 if (offset < PCI_DEVICE_SPECIFIC)
151 PciDevice::writeConfig(pkt);
152 else
153 panic("Device specific PCI config space not implemented!\n");
154
155 switch (offset) {
156 // seems to work fine without all these PCI settings, but i
157 // put in the IO to double check, an assertion will fail if we
158 // need to properly implement it
159 case PCI_COMMAND:
160 if (config.data[offset] & PCI_CMD_IOSE)
161 ioEnable = true;
162 else
163 ioEnable = false;
164 break;
165 }
166
167 return configDelay;
168}
169
170EtherInt*
171NSGigE::getEthPort(const std::string &if_name, int idx)
172{
173 if (if_name == "interface") {
174 if (interface->getPeer())
175 panic("interface already connected to\n");
176 return interface;
177 }
178 return NULL;
179}
180
181/**
182 * This reads the device registers, which are detailed in the NS83820
183 * spec sheet
184 */
185Tick
186NSGigE::read(PacketPtr pkt)
187{
188 assert(ioEnable);
189
190 //The mask is to give you only the offset into the device register file
191 Addr daddr = pkt->getAddr() & 0xfff;
192 DPRINTF(EthernetPIO, "read da=%#x pa=%#x size=%d\n",
193 daddr, pkt->getAddr(), pkt->getSize());
194
195
196 // there are some reserved registers, you can see ns_gige_reg.h and
197 // the spec sheet for details
198 if (daddr > LAST && daddr <= RESERVED) {
199 panic("Accessing reserved register");
200 } else if (daddr > RESERVED && daddr <= 0x3FC) {
201 return readConfig(pkt);
202 } else if (daddr >= MIB_START && daddr <= MIB_END) {
203 // don't implement all the MIB's. hopefully the kernel
204 // doesn't actually DEPEND upon their values
205 // MIB are just hardware stats keepers
206 pkt->set<uint32_t>(0);
207 pkt->makeAtomicResponse();
208 return pioDelay;
209 } else if (daddr > 0x3FC)
210 panic("Something is messed up!\n");
211
212 assert(pkt->getSize() == sizeof(uint32_t));
213 uint32_t &reg = *pkt->getPtr<uint32_t>();
214 uint16_t rfaddr;
215
216 switch (daddr) {
217 case CR:
218 reg = regs.command;
219 //these are supposed to be cleared on a read
220 reg &= ~(CR_RXD | CR_TXD | CR_TXR | CR_RXR);
221 break;
222
223 case CFGR:
224 reg = regs.config;
225 break;
226
227 case MEAR:
228 reg = regs.mear;
229 break;
230
231 case PTSCR:
232 reg = regs.ptscr;
233 break;
234
235 case ISR:
236 reg = regs.isr;
237 devIntrClear(ISR_ALL);
238 break;
239
240 case IMR:
241 reg = regs.imr;
242 break;
243
244 case IER:
245 reg = regs.ier;
246 break;
247
248 case IHR:
249 reg = regs.ihr;
250 break;
251
252 case TXDP:
253 reg = regs.txdp;
254 break;
255
256 case TXDP_HI:
257 reg = regs.txdp_hi;
258 break;
259
260 case TX_CFG:
261 reg = regs.txcfg;
262 break;
263
264 case GPIOR:
265 reg = regs.gpior;
266 break;
267
268 case RXDP:
269 reg = regs.rxdp;
270 break;
271
272 case RXDP_HI:
273 reg = regs.rxdp_hi;
274 break;
275
276 case RX_CFG:
277 reg = regs.rxcfg;
278 break;
279
280 case PQCR:
281 reg = regs.pqcr;
282 break;
283
284 case WCSR:
285 reg = regs.wcsr;
286 break;
287
288 case PCR:
289 reg = regs.pcr;
290 break;
291
292 // see the spec sheet for how RFCR and RFDR work
293 // basically, you write to RFCR to tell the machine
294 // what you want to do next, then you act upon RFDR,
295 // and the device will be prepared b/c of what you
296 // wrote to RFCR
297 case RFCR:
298 reg = regs.rfcr;
299 break;
300
301 case RFDR:
302 rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR);
303 switch (rfaddr) {
304 // Read from perfect match ROM octets
305 case 0x000:
306 reg = rom.perfectMatch[1];
307 reg = reg << 8;
308 reg += rom.perfectMatch[0];
309 break;
310 case 0x002:
311 reg = rom.perfectMatch[3] << 8;
312 reg += rom.perfectMatch[2];
313 break;
314 case 0x004:
315 reg = rom.perfectMatch[5] << 8;
316 reg += rom.perfectMatch[4];
317 break;
318 default:
319 // Read filter hash table
320 if (rfaddr >= FHASH_ADDR &&
321 rfaddr < FHASH_ADDR + FHASH_SIZE) {
322
323 // Only word-aligned reads supported
324 if (rfaddr % 2)
325 panic("unaligned read from filter hash table!");
326
327 reg = rom.filterHash[rfaddr - FHASH_ADDR + 1] << 8;
328 reg += rom.filterHash[rfaddr - FHASH_ADDR];
329 break;
330 }
331
332 panic("reading RFDR for something other than pattern"
333 " matching or hashing! %#x\n", rfaddr);
334 }
335 break;
336
337 case SRR:
338 reg = regs.srr;
339 break;
340
341 case MIBC:
342 reg = regs.mibc;
343 reg &= ~(MIBC_MIBS | MIBC_ACLR);
344 break;
345
346 case VRCR:
347 reg = regs.vrcr;
348 break;
349
350 case VTCR:
351 reg = regs.vtcr;
352 break;
353
354 case VDR:
355 reg = regs.vdr;
356 break;
357
358 case CCSR:
359 reg = regs.ccsr;
360 break;
361
362 case TBICR:
363 reg = regs.tbicr;
364 break;
365
366 case TBISR:
367 reg = regs.tbisr;
368 break;
369
370 case TANAR:
371 reg = regs.tanar;
372 break;
373
374 case TANLPAR:
375 reg = regs.tanlpar;
376 break;
377
378 case TANER:
379 reg = regs.taner;
380 break;
381
382 case TESR:
383 reg = regs.tesr;
384 break;
385
386 case M5REG:
387 reg = 0;
388 if (params()->rx_thread)
389 reg |= M5REG_RX_THREAD;
390 if (params()->tx_thread)
391 reg |= M5REG_TX_THREAD;
392 if (params()->rss)
393 reg |= M5REG_RSS;
394 break;
395
396 default:
397 panic("reading unimplemented register: addr=%#x", daddr);
398 }
399
400 DPRINTF(EthernetPIO, "read from %#x: data=%d data=%#x\n",
401 daddr, reg, reg);
402
403 pkt->makeAtomicResponse();
404 return pioDelay;
405}
406
407Tick
408NSGigE::write(PacketPtr pkt)
409{
410 assert(ioEnable);
411
412 Addr daddr = pkt->getAddr() & 0xfff;
413 DPRINTF(EthernetPIO, "write da=%#x pa=%#x size=%d\n",
414 daddr, pkt->getAddr(), pkt->getSize());
415
416 if (daddr > LAST && daddr <= RESERVED) {
417 panic("Accessing reserved register");
418 } else if (daddr > RESERVED && daddr <= 0x3FC) {
419 return writeConfig(pkt);
420 } else if (daddr > 0x3FC)
421 panic("Something is messed up!\n");
422
423 if (pkt->getSize() == sizeof(uint32_t)) {
424 uint32_t reg = pkt->get<uint32_t>();
425 uint16_t rfaddr;
426
427 DPRINTF(EthernetPIO, "write data=%d data=%#x\n", reg, reg);
428
429 switch (daddr) {
430 case CR:
431 regs.command = reg;
432 if (reg & CR_TXD) {
433 txEnable = false;
434 } else if (reg & CR_TXE) {
435 txEnable = true;
436
437 // the kernel is enabling the transmit machine
438 if (txState == txIdle)
439 txKick();
440 }
441
442 if (reg & CR_RXD) {
443 rxEnable = false;
444 } else if (reg & CR_RXE) {
445 rxEnable = true;
446
447 if (rxState == rxIdle)
448 rxKick();
449 }
450
451 if (reg & CR_TXR)
452 txReset();
453
454 if (reg & CR_RXR)
455 rxReset();
456
457 if (reg & CR_SWI)
458 devIntrPost(ISR_SWI);
459
460 if (reg & CR_RST) {
461 txReset();
462 rxReset();
463
464 regsReset();
465 }
466 break;
467
468 case CFGR:
469 if (reg & CFGR_LNKSTS ||
470 reg & CFGR_SPDSTS ||
471 reg & CFGR_DUPSTS ||
472 reg & CFGR_RESERVED ||
473 reg & CFGR_T64ADDR ||
474 reg & CFGR_PCI64_DET) {
475 // First clear all writable bits
476 regs.config &= CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS |
477 CFGR_RESERVED | CFGR_T64ADDR |
478 CFGR_PCI64_DET;
479 // Now set the appropriate writable bits
480 regs.config |= reg & ~(CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS |
481 CFGR_RESERVED | CFGR_T64ADDR |
482 CFGR_PCI64_DET);
483 }
484
485// all these #if 0's are because i don't THINK the kernel needs to
486// have these implemented. if there is a problem relating to one of
487// these, you may need to add functionality in.
488
489// grouped together and #if 0'ed to avoid empty if body and make clang happy
490#if 0
491 if (reg & CFGR_TBI_EN) ;
492 if (reg & CFGR_MODE_1000) ;
493
494 if (reg & CFGR_PINT_DUPSTS ||
495 reg & CFGR_PINT_LNKSTS ||
496 reg & CFGR_PINT_SPDSTS)
497 ;
498
499 if (reg & CFGR_TMRTEST) ;
500 if (reg & CFGR_MRM_DIS) ;
501 if (reg & CFGR_MWI_DIS) ;
502
503 if (reg & CFGR_DATA64_EN) ;
504 if (reg & CFGR_M64ADDR) ;
505 if (reg & CFGR_PHY_RST) ;
506 if (reg & CFGR_PHY_DIS) ;
507
508 if (reg & CFGR_REQALG) ;
509 if (reg & CFGR_SB) ;
510 if (reg & CFGR_POW) ;
511 if (reg & CFGR_EXD) ;
512 if (reg & CFGR_PESEL) ;
513 if (reg & CFGR_BROM_DIS) ;
514 if (reg & CFGR_EXT_125) ;
515 if (reg & CFGR_BEM) ;
516
517 if (reg & CFGR_T64ADDR) ;
518 // panic("CFGR_T64ADDR is read only register!\n");
519#endif
520 if (reg & CFGR_AUTO_1000)
521 panic("CFGR_AUTO_1000 not implemented!\n");
522
523 if (reg & CFGR_PCI64_DET)
524 panic("CFGR_PCI64_DET is read only register!\n");
525
526 if (reg & CFGR_EXTSTS_EN)
527 extstsEnable = true;
528 else
529 extstsEnable = false;
530 break;
531
532 case MEAR:
533 // Clear writable bits
534 regs.mear &= MEAR_EEDO;
535 // Set appropriate writable bits
536 regs.mear |= reg & ~MEAR_EEDO;
537
538 // FreeBSD uses the EEPROM to read PMATCH (for the MAC address)
539 // even though it could get it through RFDR
540 if (reg & MEAR_EESEL) {
541 // Rising edge of clock
542 if (reg & MEAR_EECLK && !eepromClk)
543 eepromKick();
544 }
545 else {
546 eepromState = eepromStart;
547 regs.mear &= ~MEAR_EEDI;
548 }
549
550 eepromClk = reg & MEAR_EECLK;
551
552 // since phy is completely faked, MEAR_MD* don't matter
553
554// grouped together and #if 0'ed to avoid empty if body and make clang happy
555#if 0
556 if (reg & MEAR_MDIO) ;
557 if (reg & MEAR_MDDIR) ;
558 if (reg & MEAR_MDC) ;
559#endif
560 break;
561
562 case PTSCR:
563 regs.ptscr = reg & ~(PTSCR_RBIST_RDONLY);
564 // these control BISTs for various parts of chip - we
565 // don't care or do just fake that the BIST is done
566 if (reg & PTSCR_RBIST_EN)
567 regs.ptscr |= PTSCR_RBIST_DONE;
568 if (reg & PTSCR_EEBIST_EN)
569 regs.ptscr &= ~PTSCR_EEBIST_EN;
570 if (reg & PTSCR_EELOAD_EN)
571 regs.ptscr &= ~PTSCR_EELOAD_EN;
572 break;
573
574 case ISR: /* writing to the ISR has no effect */
575 panic("ISR is a read only register!\n");
576
577 case IMR:
578 regs.imr = reg;
579 devIntrChangeMask();
580 break;
581
582 case IER:
583 regs.ier = reg;
584 break;
585
586 case IHR:
587 regs.ihr = reg;
588 /* not going to implement real interrupt holdoff */
589 break;
590
591 case TXDP:
592 regs.txdp = (reg & 0xFFFFFFFC);
593 assert(txState == txIdle);
594 CTDD = false;
595 break;
596
597 case TXDP_HI:
598 regs.txdp_hi = reg;
599 break;
600
601 case TX_CFG:
602 regs.txcfg = reg;
603#if 0
604 if (reg & TX_CFG_CSI) ;
605 if (reg & TX_CFG_HBI) ;
606 if (reg & TX_CFG_MLB) ;
607 if (reg & TX_CFG_ATP) ;
608 if (reg & TX_CFG_ECRETRY) {
609 /*
610 * this could easily be implemented, but considering
611 * the network is just a fake pipe, wouldn't make
612 * sense to do this
613 */
614 }
615
616 if (reg & TX_CFG_BRST_DIS) ;
617#endif
618
619#if 0
620 /* we handle our own DMA, ignore the kernel's exhortations */
621 if (reg & TX_CFG_MXDMA) ;
622#endif
623
624 // also, we currently don't care about fill/drain
625 // thresholds though this may change in the future with
626 // more realistic networks or a driver which changes it
627 // according to feedback
628
629 break;
630
631 case GPIOR:
632 // Only write writable bits
633 regs.gpior &= GPIOR_UNUSED | GPIOR_GP5_IN | GPIOR_GP4_IN
634 | GPIOR_GP3_IN | GPIOR_GP2_IN | GPIOR_GP1_IN;
635 regs.gpior |= reg & ~(GPIOR_UNUSED | GPIOR_GP5_IN | GPIOR_GP4_IN
636 | GPIOR_GP3_IN | GPIOR_GP2_IN | GPIOR_GP1_IN);
637 /* these just control general purpose i/o pins, don't matter */
638 break;
639
640 case RXDP:
641 regs.rxdp = reg;
642 CRDD = false;
643 break;
644
645 case RXDP_HI:
646 regs.rxdp_hi = reg;
647 break;
648
649 case RX_CFG:
650 regs.rxcfg = reg;
651#if 0
652 if (reg & RX_CFG_AEP) ;
653 if (reg & RX_CFG_ARP) ;
654 if (reg & RX_CFG_STRIPCRC) ;
655 if (reg & RX_CFG_RX_RD) ;
656 if (reg & RX_CFG_ALP) ;
657 if (reg & RX_CFG_AIRL) ;
658
659 /* we handle our own DMA, ignore what kernel says about it */
660 if (reg & RX_CFG_MXDMA) ;
661
662 //also, we currently don't care about fill/drain thresholds
663 //though this may change in the future with more realistic
664 //networks or a driver which changes it according to feedback
665 if (reg & (RX_CFG_DRTH | RX_CFG_DRTH0)) ;
666#endif
667 break;
668
669 case PQCR:
670 /* there is no priority queueing used in the linux 2.6 driver */
671 regs.pqcr = reg;
672 break;
673
674 case WCSR:
675 /* not going to implement wake on LAN */
676 regs.wcsr = reg;
677 break;
678
679 case PCR:
680 /* not going to implement pause control */
681 regs.pcr = reg;
682 break;
683
684 case RFCR:
685 regs.rfcr = reg;
686
687 rxFilterEnable = (reg & RFCR_RFEN) ? true : false;
688 acceptBroadcast = (reg & RFCR_AAB) ? true : false;
689 acceptMulticast = (reg & RFCR_AAM) ? true : false;
690 acceptUnicast = (reg & RFCR_AAU) ? true : false;
691 acceptPerfect = (reg & RFCR_APM) ? true : false;
692 acceptArp = (reg & RFCR_AARP) ? true : false;
693 multicastHashEnable = (reg & RFCR_MHEN) ? true : false;
694
695#if 0
696 if (reg & RFCR_APAT)
697 panic("RFCR_APAT not implemented!\n");
698#endif
699 if (reg & RFCR_UHEN)
700 panic("Unicast hash filtering not used by drivers!\n");
701
702 if (reg & RFCR_ULM)
703 panic("RFCR_ULM not implemented!\n");
704
705 break;
706
707 case RFDR:
708 rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR);
709 switch (rfaddr) {
710 case 0x000:
711 rom.perfectMatch[0] = (uint8_t)reg;
712 rom.perfectMatch[1] = (uint8_t)(reg >> 8);
713 break;
714 case 0x002:
715 rom.perfectMatch[2] = (uint8_t)reg;
716 rom.perfectMatch[3] = (uint8_t)(reg >> 8);
717 break;
718 case 0x004:
719 rom.perfectMatch[4] = (uint8_t)reg;
720 rom.perfectMatch[5] = (uint8_t)(reg >> 8);
721 break;
722 default:
723
724 if (rfaddr >= FHASH_ADDR &&
725 rfaddr < FHASH_ADDR + FHASH_SIZE) {
726
727 // Only word-aligned writes supported
728 if (rfaddr % 2)
729 panic("unaligned write to filter hash table!");
730
731 rom.filterHash[rfaddr - FHASH_ADDR] = (uint8_t)reg;
732 rom.filterHash[rfaddr - FHASH_ADDR + 1]
733 = (uint8_t)(reg >> 8);
734 break;
735 }
736 panic("writing RFDR for something other than pattern matching "
737 "or hashing! %#x\n", rfaddr);
738 }
739
740 case BRAR:
741 regs.brar = reg;
742 break;
743
744 case BRDR:
745 panic("the driver never uses BRDR, something is wrong!\n");
746
747 case SRR:
748 panic("SRR is read only register!\n");
749
750 case MIBC:
751 panic("the driver never uses MIBC, something is wrong!\n");
752
753 case VRCR:
754 regs.vrcr = reg;
755 break;
756
757 case VTCR:
758 regs.vtcr = reg;
759 break;
760
761 case VDR:
762 panic("the driver never uses VDR, something is wrong!\n");
763
764 case CCSR:
765 /* not going to implement clockrun stuff */
766 regs.ccsr = reg;
767 break;
768
769 case TBICR:
770 regs.tbicr = reg;
771 if (reg & TBICR_MR_LOOPBACK)
772 panic("TBICR_MR_LOOPBACK never used, something wrong!\n");
773
774 if (reg & TBICR_MR_AN_ENABLE) {
775 regs.tanlpar = regs.tanar;
776 regs.tbisr |= (TBISR_MR_AN_COMPLETE | TBISR_MR_LINK_STATUS);
777 }
778
779#if 0
780 if (reg & TBICR_MR_RESTART_AN) ;
781#endif
782
783 break;
784
785 case TBISR:
786 panic("TBISR is read only register!\n");
787
788 case TANAR:
789 // Only write the writable bits
790 regs.tanar &= TANAR_RF1 | TANAR_RF2 | TANAR_UNUSED;
791 regs.tanar |= reg & ~(TANAR_RF1 | TANAR_RF2 | TANAR_UNUSED);
792
793 // Pause capability unimplemented
794#if 0
795 if (reg & TANAR_PS2) ;
796 if (reg & TANAR_PS1) ;
797#endif
798
799 break;
800
801 case TANLPAR:
802 panic("this should only be written to by the fake phy!\n");
803
804 case TANER:
805 panic("TANER is read only register!\n");
806
807 case TESR:
808 regs.tesr = reg;
809 break;
810
811 default:
812 panic("invalid register access daddr=%#x", daddr);
813 }
814 } else {
815 panic("Invalid Request Size");
816 }
817 pkt->makeAtomicResponse();
818 return pioDelay;
819}
820
821void
822NSGigE::devIntrPost(uint32_t interrupts)
823{
824 if (interrupts & ISR_RESERVE)
825 panic("Cannot set a reserved interrupt");
826
827 if (interrupts & ISR_NOIMPL)
828 warn("interrupt not implemented %#x\n", interrupts);
829
830 interrupts &= ISR_IMPL;
831 regs.isr |= interrupts;
832
833 if (interrupts & regs.imr) {
834 if (interrupts & ISR_SWI) {
835 totalSwi++;
836 }
837 if (interrupts & ISR_RXIDLE) {
838 totalRxIdle++;
839 }
840 if (interrupts & ISR_RXOK) {
841 totalRxOk++;
842 }
843 if (interrupts & ISR_RXDESC) {
844 totalRxDesc++;
845 }
846 if (interrupts & ISR_TXOK) {
847 totalTxOk++;
848 }
849 if (interrupts & ISR_TXIDLE) {
850 totalTxIdle++;
851 }
852 if (interrupts & ISR_TXDESC) {
853 totalTxDesc++;
854 }
855 if (interrupts & ISR_RXORN) {
856 totalRxOrn++;
857 }
858 }
859
860 DPRINTF(EthernetIntr,
861 "interrupt written to ISR: intr=%#x isr=%#x imr=%#x\n",
862 interrupts, regs.isr, regs.imr);
863
864 if ((regs.isr & regs.imr)) {
865 Tick when = curTick();
866 if ((regs.isr & regs.imr & ISR_NODELAY) == 0)
867 when += intrDelay;
868 postedInterrupts++;
869 cpuIntrPost(when);
870 }
871}
872
873/* writing this interrupt counting stats inside this means that this function
874 is now limited to being used to clear all interrupts upon the kernel
875 reading isr and servicing. just telling you in case you were thinking
876 of expanding use.
877*/
878void
879NSGigE::devIntrClear(uint32_t interrupts)
880{
881 if (interrupts & ISR_RESERVE)
882 panic("Cannot clear a reserved interrupt");
883
884 if (regs.isr & regs.imr & ISR_SWI) {
885 postedSwi++;
886 }
887 if (regs.isr & regs.imr & ISR_RXIDLE) {
888 postedRxIdle++;
889 }
890 if (regs.isr & regs.imr & ISR_RXOK) {
891 postedRxOk++;
892 }
893 if (regs.isr & regs.imr & ISR_RXDESC) {
894 postedRxDesc++;
895 }
896 if (regs.isr & regs.imr & ISR_TXOK) {
897 postedTxOk++;
898 }
899 if (regs.isr & regs.imr & ISR_TXIDLE) {
900 postedTxIdle++;
901 }
902 if (regs.isr & regs.imr & ISR_TXDESC) {
903 postedTxDesc++;
904 }
905 if (regs.isr & regs.imr & ISR_RXORN) {
906 postedRxOrn++;
907 }
908
909 interrupts &= ~ISR_NOIMPL;
910 regs.isr &= ~interrupts;
911
912 DPRINTF(EthernetIntr,
913 "interrupt cleared from ISR: intr=%x isr=%x imr=%x\n",
914 interrupts, regs.isr, regs.imr);
915
916 if (!(regs.isr & regs.imr))
917 cpuIntrClear();
918}
919
920void
921NSGigE::devIntrChangeMask()
922{
923 DPRINTF(EthernetIntr, "interrupt mask changed: isr=%x imr=%x masked=%x\n",
924 regs.isr, regs.imr, regs.isr & regs.imr);
925
926 if (regs.isr & regs.imr)
927 cpuIntrPost(curTick());
928 else
929 cpuIntrClear();
930}
931
932void
933NSGigE::cpuIntrPost(Tick when)
934{
935 // If the interrupt you want to post is later than an interrupt
936 // already scheduled, just let it post in the coming one and don't
937 // schedule another.
938 // HOWEVER, must be sure that the scheduled intrTick is in the
939 // future (this was formerly the source of a bug)
940 /**
941 * @todo this warning should be removed and the intrTick code should
942 * be fixed.
943 */
944 assert(when >= curTick());
945 assert(intrTick >= curTick() || intrTick == 0);
946 if (when > intrTick && intrTick != 0) {
947 DPRINTF(EthernetIntr, "don't need to schedule event...intrTick=%d\n",
948 intrTick);
949 return;
950 }
951
952 intrTick = when;
953 if (intrTick < curTick()) {
954 intrTick = curTick();
955 }
956
957 DPRINTF(EthernetIntr, "going to schedule an interrupt for intrTick=%d\n",
958 intrTick);
959
960 if (intrEvent)
961 intrEvent->squash();
962 intrEvent = new IntrEvent(this, true);
963 schedule(intrEvent, intrTick);
964}
965
966void
967NSGigE::cpuInterrupt()
968{
969 assert(intrTick == curTick());
970
971 // Whether or not there's a pending interrupt, we don't care about
972 // it anymore
973 intrEvent = 0;
974 intrTick = 0;
975
976 // Don't send an interrupt if there's already one
977 if (cpuPendingIntr) {
978 DPRINTF(EthernetIntr,
979 "would send an interrupt now, but there's already pending\n");
980 } else {
981 // Send interrupt
982 cpuPendingIntr = true;
983
984 DPRINTF(EthernetIntr, "posting interrupt\n");
985 intrPost();
986 }
987}
988
989void
990NSGigE::cpuIntrClear()
991{
992 if (!cpuPendingIntr)
993 return;
994
995 if (intrEvent) {
996 intrEvent->squash();
997 intrEvent = 0;
998 }
999
1000 intrTick = 0;
1001
1002 cpuPendingIntr = false;
1003
1004 DPRINTF(EthernetIntr, "clearing interrupt\n");
1005 intrClear();
1006}
1007
1008bool
1009NSGigE::cpuIntrPending() const
1010{ return cpuPendingIntr; }
1011
1012void
1013NSGigE::txReset()
1014{
1015
1016 DPRINTF(Ethernet, "transmit reset\n");
1017
1018 CTDD = false;
1019 txEnable = false;;
1020 txFragPtr = 0;
1021 assert(txDescCnt == 0);
1022 txFifo.clear();
1023 txState = txIdle;
1024 assert(txDmaState == dmaIdle);
1025}
1026
1027void
1028NSGigE::rxReset()
1029{
1030 DPRINTF(Ethernet, "receive reset\n");
1031
1032 CRDD = false;
1033 assert(rxPktBytes == 0);
1034 rxEnable = false;
1035 rxFragPtr = 0;
1036 assert(rxDescCnt == 0);
1037 assert(rxDmaState == dmaIdle);
1038 rxFifo.clear();
1039 rxState = rxIdle;
1040}
1041
1042void
1043NSGigE::regsReset()
1044{
1045 memset(&regs, 0, sizeof(regs));
1046 regs.config = (CFGR_LNKSTS | CFGR_TBI_EN | CFGR_MODE_1000);
1047 regs.mear = 0x12;
1048 regs.txcfg = 0x120; // set drain threshold to 1024 bytes and
1049 // fill threshold to 32 bytes
1050 regs.rxcfg = 0x4; // set drain threshold to 16 bytes
1051 regs.srr = 0x0103; // set the silicon revision to rev B or 0x103
1052 regs.mibc = MIBC_FRZ;
1053 regs.vdr = 0x81; // set the vlan tag type to 802.1q
1054 regs.tesr = 0xc000; // TBI capable of both full and half duplex
1055 regs.brar = 0xffffffff;
1056
1057 extstsEnable = false;
1058 acceptBroadcast = false;
1059 acceptMulticast = false;
1060 acceptUnicast = false;
1061 acceptPerfect = false;
1062 acceptArp = false;
1063}
1064
1065bool
1066NSGigE::doRxDmaRead()
1067{
1068 assert(rxDmaState == dmaIdle || rxDmaState == dmaReadWaiting);
1069 rxDmaState = dmaReading;
1070
1071 if (dmaPending() || drainState() != DrainState::Running)
1072 rxDmaState = dmaReadWaiting;
1073 else
1074 dmaRead(rxDmaAddr, rxDmaLen, &rxDmaReadEvent, (uint8_t*)rxDmaData);
1075
1076 return true;
1077}
1078
1079void
1080NSGigE::rxDmaReadDone()
1081{
1082 assert(rxDmaState == dmaReading);
1083 rxDmaState = dmaIdle;
1084
1085 DPRINTF(EthernetDMA, "rx dma read paddr=%#x len=%d\n",
1086 rxDmaAddr, rxDmaLen);
1087 DDUMP(EthernetDMA, rxDmaData, rxDmaLen);
1088
1089 // If the transmit state machine has a pending DMA, let it go first
1090 if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting)
1091 txKick();
1092
1093 rxKick();
1094}
1095
1096bool
1097NSGigE::doRxDmaWrite()
1098{
1099 assert(rxDmaState == dmaIdle || rxDmaState == dmaWriteWaiting);
1100 rxDmaState = dmaWriting;
1101
1102 if (dmaPending() || drainState() != DrainState::Running)
1103 rxDmaState = dmaWriteWaiting;
1104 else
1105 dmaWrite(rxDmaAddr, rxDmaLen, &rxDmaWriteEvent, (uint8_t*)rxDmaData);
1106 return true;
1107}
1108
1109void
1110NSGigE::rxDmaWriteDone()
1111{
1112 assert(rxDmaState == dmaWriting);
1113 rxDmaState = dmaIdle;
1114
1115 DPRINTF(EthernetDMA, "rx dma write paddr=%#x len=%d\n",
1116 rxDmaAddr, rxDmaLen);
1117 DDUMP(EthernetDMA, rxDmaData, rxDmaLen);
1118
1119 // If the transmit state machine has a pending DMA, let it go first
1120 if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting)
1121 txKick();
1122
1123 rxKick();
1124}
1125
1126void
1127NSGigE::rxKick()
1128{
1129 bool is64bit = (bool)(regs.config & CFGR_M64ADDR);
1130
1131 DPRINTF(EthernetSM,
1132 "receive kick rxState=%s (rxBuf.size=%d) %d-bit\n",
1133 NsRxStateStrings[rxState], rxFifo.size(), is64bit ? 64 : 32);
1134
1135 Addr link, bufptr;
1136 uint32_t &cmdsts = is64bit ? rxDesc64.cmdsts : rxDesc32.cmdsts;
1137 uint32_t &extsts = is64bit ? rxDesc64.extsts : rxDesc32.extsts;
1138
1139 next:
1140 if (rxKickTick > curTick()) {
1141 DPRINTF(EthernetSM, "receive kick exiting, can't run till %d\n",
1142 rxKickTick);
1143
1144 goto exit;
1145 }
1146
1147 // Go to the next state machine clock tick.
1148 rxKickTick = clockEdge(Cycles(1));
1149
1150 switch(rxDmaState) {
1151 case dmaReadWaiting:
1152 if (doRxDmaRead())
1153 goto exit;
1154 break;
1155 case dmaWriteWaiting:
1156 if (doRxDmaWrite())
1157 goto exit;
1158 break;
1159 default:
1160 break;
1161 }
1162
1163 link = is64bit ? (Addr)rxDesc64.link : (Addr)rxDesc32.link;
1164 bufptr = is64bit ? (Addr)rxDesc64.bufptr : (Addr)rxDesc32.bufptr;
1165
1166 // see state machine from spec for details
1167 // the way this works is, if you finish work on one state and can
1168 // go directly to another, you do that through jumping to the
1169 // label "next". however, if you have intermediate work, like DMA
1170 // so that you can't go to the next state yet, you go to exit and
1171 // exit the loop. however, when the DMA is done it will trigger
1172 // an event and come back to this loop.
1173 switch (rxState) {
1174 case rxIdle:
1175 if (!rxEnable) {
1176 DPRINTF(EthernetSM, "Receive Disabled! Nothing to do.\n");
1177 goto exit;
1178 }
1179
1180 if (CRDD) {
1181 rxState = rxDescRefr;
1182
1183 rxDmaAddr = regs.rxdp & 0x3fffffff;
1184 rxDmaData =
1185 is64bit ? (void *)&rxDesc64.link : (void *)&rxDesc32.link;
1186 rxDmaLen = is64bit ? sizeof(rxDesc64.link) : sizeof(rxDesc32.link);
1187 rxDmaFree = dmaDescFree;
1188
1189 descDmaReads++;
1190 descDmaRdBytes += rxDmaLen;
1191
1192 if (doRxDmaRead())
1193 goto exit;
1194 } else {
1195 rxState = rxDescRead;
1196
1197 rxDmaAddr = regs.rxdp & 0x3fffffff;
1198 rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32;
1199 rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32);
1200 rxDmaFree = dmaDescFree;
1201
1202 descDmaReads++;
1203 descDmaRdBytes += rxDmaLen;
1204
1205 if (doRxDmaRead())
1206 goto exit;
1207 }
1208 break;
1209
1210 case rxDescRefr:
1211 if (rxDmaState != dmaIdle)
1212 goto exit;
1213
1214 rxState = rxAdvance;
1215 break;
1216
1217 case rxDescRead:
1218 if (rxDmaState != dmaIdle)
1219 goto exit;
1220
1221 DPRINTF(EthernetDesc, "rxDesc: addr=%08x read descriptor\n",
1222 regs.rxdp & 0x3fffffff);
1223 DPRINTF(EthernetDesc,
1224 "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n",
1225 link, bufptr, cmdsts, extsts);
1226
1227 if (cmdsts & CMDSTS_OWN) {
1228 devIntrPost(ISR_RXIDLE);
1229 rxState = rxIdle;
1230 goto exit;
1231 } else {
1232 rxState = rxFifoBlock;
1233 rxFragPtr = bufptr;
1234 rxDescCnt = cmdsts & CMDSTS_LEN_MASK;
1235 }
1236 break;
1237
1238 case rxFifoBlock:
1239 if (!rxPacket) {
1240 /**
1241 * @todo in reality, we should be able to start processing
1242 * the packet as it arrives, and not have to wait for the
1243 * full packet ot be in the receive fifo.
1244 */
1245 if (rxFifo.empty())
1246 goto exit;
1247
1248 DPRINTF(EthernetSM, "****processing receive of new packet****\n");
1249
1250 // If we don't have a packet, grab a new one from the fifo.
1251 rxPacket = rxFifo.front();
1252 rxPktBytes = rxPacket->length;
1253 rxPacketBufPtr = rxPacket->data;
1254
1255#if TRACING_ON
1256 if (DTRACE(Ethernet)) {
1257 IpPtr ip(rxPacket);
1258 if (ip) {
1259 DPRINTF(Ethernet, "ID is %d\n", ip->id());
1260 TcpPtr tcp(ip);
1261 if (tcp) {
1262 DPRINTF(Ethernet,
1263 "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
1264 tcp->sport(), tcp->dport(), tcp->seq(),
1265 tcp->ack());
1266 }
1267 }
1268 }
1269#endif
1270
1271 // sanity check - i think the driver behaves like this
1272 assert(rxDescCnt >= rxPktBytes);
1273 rxFifo.pop();
1274 }
1275
1276
1277 // dont' need the && rxDescCnt > 0 if driver sanity check
1278 // above holds
1279 if (rxPktBytes > 0) {
1280 rxState = rxFragWrite;
1281 // don't need min<>(rxPktBytes,rxDescCnt) if above sanity
1282 // check holds
1283 rxXferLen = rxPktBytes;
1284
1285 rxDmaAddr = rxFragPtr & 0x3fffffff;
1286 rxDmaData = rxPacketBufPtr;
1287 rxDmaLen = rxXferLen;
1288 rxDmaFree = dmaDataFree;
1289
1290 if (doRxDmaWrite())
1291 goto exit;
1292
1293 } else {
1294 rxState = rxDescWrite;
1295
1296 //if (rxPktBytes == 0) { /* packet is done */
1297 assert(rxPktBytes == 0);
1298 DPRINTF(EthernetSM, "done with receiving packet\n");
1299
1300 cmdsts |= CMDSTS_OWN;
1301 cmdsts &= ~CMDSTS_MORE;
1302 cmdsts |= CMDSTS_OK;
1303 cmdsts &= 0xffff0000;
1304 cmdsts += rxPacket->length; //i.e. set CMDSTS_SIZE
1305
1306#if 0
1307 /*
1308 * all the driver uses these are for its own stats keeping
1309 * which we don't care about, aren't necessary for
1310 * functionality and doing this would just slow us down.
1311 * if they end up using this in a later version for
1312 * functional purposes, just undef
1313 */
1314 if (rxFilterEnable) {
1315 cmdsts &= ~CMDSTS_DEST_MASK;
1316 const EthAddr &dst = rxFifoFront()->dst();
1317 if (dst->unicast())
1318 cmdsts |= CMDSTS_DEST_SELF;
1319 if (dst->multicast())
1320 cmdsts |= CMDSTS_DEST_MULTI;
1321 if (dst->broadcast())
1322 cmdsts |= CMDSTS_DEST_MASK;
1323 }
1324#endif
1325
1326 IpPtr ip(rxPacket);
1327 if (extstsEnable && ip) {
1328 extsts |= EXTSTS_IPPKT;
1329 rxIpChecksums++;
1330 if (cksum(ip) != 0) {
1331 DPRINTF(EthernetCksum, "Rx IP Checksum Error\n");
1332 extsts |= EXTSTS_IPERR;
1333 }
1334 TcpPtr tcp(ip);
1335 UdpPtr udp(ip);
1336 if (tcp) {
1337 extsts |= EXTSTS_TCPPKT;
1338 rxTcpChecksums++;
1339 if (cksum(tcp) != 0) {
1340 DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n");
1341 extsts |= EXTSTS_TCPERR;
1342
1343 }
1344 } else if (udp) {
1345 extsts |= EXTSTS_UDPPKT;
1346 rxUdpChecksums++;
1347 if (cksum(udp) != 0) {
1348 DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n");
1349 extsts |= EXTSTS_UDPERR;
1350 }
1351 }
1352 }
1353 rxPacket = 0;
1354
1355 /*
1356 * the driver seems to always receive into desc buffers
1357 * of size 1514, so you never have a pkt that is split
1358 * into multiple descriptors on the receive side, so
1359 * i don't implement that case, hence the assert above.
1360 */
1361
1362 DPRINTF(EthernetDesc,
1363 "rxDesc: addr=%08x writeback cmdsts extsts\n",
1364 regs.rxdp & 0x3fffffff);
1365 DPRINTF(EthernetDesc,
1366 "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n",
1367 link, bufptr, cmdsts, extsts);
1368
1369 rxDmaAddr = regs.rxdp & 0x3fffffff;
1370 rxDmaData = &cmdsts;
1371 if (is64bit) {
1372 rxDmaAddr += offsetof(ns_desc64, cmdsts);
1373 rxDmaLen = sizeof(rxDesc64.cmdsts) + sizeof(rxDesc64.extsts);
1374 } else {
1375 rxDmaAddr += offsetof(ns_desc32, cmdsts);
1376 rxDmaLen = sizeof(rxDesc32.cmdsts) + sizeof(rxDesc32.extsts);
1377 }
1378 rxDmaFree = dmaDescFree;
1379
1380 descDmaWrites++;
1381 descDmaWrBytes += rxDmaLen;
1382
1383 if (doRxDmaWrite())
1384 goto exit;
1385 }
1386 break;
1387
1388 case rxFragWrite:
1389 if (rxDmaState != dmaIdle)
1390 goto exit;
1391
1392 rxPacketBufPtr += rxXferLen;
1393 rxFragPtr += rxXferLen;
1394 rxPktBytes -= rxXferLen;
1395
1396 rxState = rxFifoBlock;
1397 break;
1398
1399 case rxDescWrite:
1400 if (rxDmaState != dmaIdle)
1401 goto exit;
1402
1403 assert(cmdsts & CMDSTS_OWN);
1404
1405 assert(rxPacket == 0);
1406 devIntrPost(ISR_RXOK);
1407
1408 if (cmdsts & CMDSTS_INTR)
1409 devIntrPost(ISR_RXDESC);
1410
1411 if (!rxEnable) {
1412 DPRINTF(EthernetSM, "Halting the RX state machine\n");
1413 rxState = rxIdle;
1414 goto exit;
1415 } else
1416 rxState = rxAdvance;
1417 break;
1418
1419 case rxAdvance:
1420 if (link == 0) {
1421 devIntrPost(ISR_RXIDLE);
1422 rxState = rxIdle;
1423 CRDD = true;
1424 goto exit;
1425 } else {
1426 if (rxDmaState != dmaIdle)
1427 goto exit;
1428 rxState = rxDescRead;
1429 regs.rxdp = link;
1430 CRDD = false;
1431
1432 rxDmaAddr = regs.rxdp & 0x3fffffff;
1433 rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32;
1434 rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32);
1435 rxDmaFree = dmaDescFree;
1436
1437 if (doRxDmaRead())
1438 goto exit;
1439 }
1440 break;
1441
1442 default:
1443 panic("Invalid rxState!");
1444 }
1445
1446 DPRINTF(EthernetSM, "entering next rxState=%s\n",
1447 NsRxStateStrings[rxState]);
1448 goto next;
1449
1450 exit:
1451 /**
1452 * @todo do we want to schedule a future kick?
1453 */
1454 DPRINTF(EthernetSM, "rx state machine exited rxState=%s\n",
1455 NsRxStateStrings[rxState]);
1456
1457 if (!rxKickEvent.scheduled())
1458 schedule(rxKickEvent, rxKickTick);
1459}
1460
1461void
1462NSGigE::transmit()
1463{
1464 if (txFifo.empty()) {
1465 DPRINTF(Ethernet, "nothing to transmit\n");
1466 return;
1467 }
1468
1469 DPRINTF(Ethernet, "Attempt Pkt Transmit: txFifo length=%d\n",
1470 txFifo.size());
1471 if (interface->sendPacket(txFifo.front())) {
1472#if TRACING_ON
1473 if (DTRACE(Ethernet)) {
1474 IpPtr ip(txFifo.front());
1475 if (ip) {
1476 DPRINTF(Ethernet, "ID is %d\n", ip->id());
1477 TcpPtr tcp(ip);
1478 if (tcp) {
1479 DPRINTF(Ethernet,
1480 "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
1481 tcp->sport(), tcp->dport(), tcp->seq(),
1482 tcp->ack());
1483 }
1484 }
1485 }
1486#endif
1487
1488 DDUMP(EthernetData, txFifo.front()->data, txFifo.front()->length);
1489 txBytes += txFifo.front()->length;
1490 txPackets++;
1491
1492 DPRINTF(Ethernet, "Successful Xmit! now txFifoAvail is %d\n",
1493 txFifo.avail());
1494 txFifo.pop();
1495
1496 /*
1497 * normally do a writeback of the descriptor here, and ONLY
1498 * after that is done, send this interrupt. but since our
1499 * stuff never actually fails, just do this interrupt here,
1500 * otherwise the code has to stray from this nice format.
1501 * besides, it's functionally the same.
1502 */
1503 devIntrPost(ISR_TXOK);
1504 }
1505
1506 if (!txFifo.empty() && !txEvent.scheduled()) {
1507 DPRINTF(Ethernet, "reschedule transmit\n");
1508 schedule(txEvent, curTick() + retryTime);
1509 }
1510}
1511
1512bool
1513NSGigE::doTxDmaRead()
1514{
1515 assert(txDmaState == dmaIdle || txDmaState == dmaReadWaiting);
1516 txDmaState = dmaReading;
1517
1518 if (dmaPending() || drainState() != DrainState::Running)
1519 txDmaState = dmaReadWaiting;
1520 else
1521 dmaRead(txDmaAddr, txDmaLen, &txDmaReadEvent, (uint8_t*)txDmaData);
1522
1523 return true;
1524}
1525
1526void
1527NSGigE::txDmaReadDone()
1528{
1529 assert(txDmaState == dmaReading);
1530 txDmaState = dmaIdle;
1531
1532 DPRINTF(EthernetDMA, "tx dma read paddr=%#x len=%d\n",
1533 txDmaAddr, txDmaLen);
1534 DDUMP(EthernetDMA, txDmaData, txDmaLen);
1535
1536 // If the receive state machine has a pending DMA, let it go first
1537 if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting)
1538 rxKick();
1539
1540 txKick();
1541}
1542
1543bool
1544NSGigE::doTxDmaWrite()
1545{
1546 assert(txDmaState == dmaIdle || txDmaState == dmaWriteWaiting);
1547 txDmaState = dmaWriting;
1548
1549 if (dmaPending() || drainState() != DrainState::Running)
1550 txDmaState = dmaWriteWaiting;
1551 else
1552 dmaWrite(txDmaAddr, txDmaLen, &txDmaWriteEvent, (uint8_t*)txDmaData);
1553 return true;
1554}
1555
1556void
1557NSGigE::txDmaWriteDone()
1558{
1559 assert(txDmaState == dmaWriting);
1560 txDmaState = dmaIdle;
1561
1562 DPRINTF(EthernetDMA, "tx dma write paddr=%#x len=%d\n",
1563 txDmaAddr, txDmaLen);
1564 DDUMP(EthernetDMA, txDmaData, txDmaLen);
1565
1566 // If the receive state machine has a pending DMA, let it go first
1567 if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting)
1568 rxKick();
1569
1570 txKick();
1571}
1572
1573void
1574NSGigE::txKick()
1575{
1576 bool is64bit = (bool)(regs.config & CFGR_M64ADDR);
1577
1578 DPRINTF(EthernetSM, "transmit kick txState=%s %d-bit\n",
1579 NsTxStateStrings[txState], is64bit ? 64 : 32);
1580
1581 Addr link, bufptr;
1582 uint32_t &cmdsts = is64bit ? txDesc64.cmdsts : txDesc32.cmdsts;
1583 uint32_t &extsts = is64bit ? txDesc64.extsts : txDesc32.extsts;
1584
1585 next:
1586 if (txKickTick > curTick()) {
1587 DPRINTF(EthernetSM, "transmit kick exiting, can't run till %d\n",
1588 txKickTick);
1589 goto exit;
1590 }
1591
1592 // Go to the next state machine clock tick.
1593 txKickTick = clockEdge(Cycles(1));
1594
1595 switch(txDmaState) {
1596 case dmaReadWaiting:
1597 if (doTxDmaRead())
1598 goto exit;
1599 break;
1600 case dmaWriteWaiting:
1601 if (doTxDmaWrite())
1602 goto exit;
1603 break;
1604 default:
1605 break;
1606 }
1607
1608 link = is64bit ? (Addr)txDesc64.link : (Addr)txDesc32.link;
1609 bufptr = is64bit ? (Addr)txDesc64.bufptr : (Addr)txDesc32.bufptr;
1610 switch (txState) {
1611 case txIdle:
1612 if (!txEnable) {
1613 DPRINTF(EthernetSM, "Transmit disabled. Nothing to do.\n");
1614 goto exit;
1615 }
1616
1617 if (CTDD) {
1618 txState = txDescRefr;
1619
1620 txDmaAddr = regs.txdp & 0x3fffffff;
1621 txDmaData =
1622 is64bit ? (void *)&txDesc64.link : (void *)&txDesc32.link;
1623 txDmaLen = is64bit ? sizeof(txDesc64.link) : sizeof(txDesc32.link);
1624 txDmaFree = dmaDescFree;
1625
1626 descDmaReads++;
1627 descDmaRdBytes += txDmaLen;
1628
1629 if (doTxDmaRead())
1630 goto exit;
1631
1632 } else {
1633 txState = txDescRead;
1634
1635 txDmaAddr = regs.txdp & 0x3fffffff;
1636 txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32;
1637 txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32);
1638 txDmaFree = dmaDescFree;
1639
1640 descDmaReads++;
1641 descDmaRdBytes += txDmaLen;
1642
1643 if (doTxDmaRead())
1644 goto exit;
1645 }
1646 break;
1647
1648 case txDescRefr:
1649 if (txDmaState != dmaIdle)
1650 goto exit;
1651
1652 txState = txAdvance;
1653 break;
1654
1655 case txDescRead:
1656 if (txDmaState != dmaIdle)
1657 goto exit;
1658
1659 DPRINTF(EthernetDesc, "txDesc: addr=%08x read descriptor\n",
1660 regs.txdp & 0x3fffffff);
1661 DPRINTF(EthernetDesc,
1662 "txDesc: link=%#x bufptr=%#x cmdsts=%#08x extsts=%#08x\n",
1663 link, bufptr, cmdsts, extsts);
1664
1665 if (cmdsts & CMDSTS_OWN) {
1666 txState = txFifoBlock;
1667 txFragPtr = bufptr;
1668 txDescCnt = cmdsts & CMDSTS_LEN_MASK;
1669 } else {
1670 devIntrPost(ISR_TXIDLE);
1671 txState = txIdle;
1672 goto exit;
1673 }
1674 break;
1675
1676 case txFifoBlock:
1677 if (!txPacket) {
1678 DPRINTF(EthernetSM, "****starting the tx of a new packet****\n");
1679 txPacket = make_shared<EthPacketData>(16384);
1680 txPacketBufPtr = txPacket->data;
1681 }
1682
1683 if (txDescCnt == 0) {
1684 DPRINTF(EthernetSM, "the txDescCnt == 0, done with descriptor\n");
1685 if (cmdsts & CMDSTS_MORE) {
1686 DPRINTF(EthernetSM, "there are more descriptors to come\n");
1687 txState = txDescWrite;
1688
1689 cmdsts &= ~CMDSTS_OWN;
1690
1691 txDmaAddr = regs.txdp & 0x3fffffff;
1692 txDmaData = &cmdsts;
1693 if (is64bit) {
1694 txDmaAddr += offsetof(ns_desc64, cmdsts);
1695 txDmaLen = sizeof(txDesc64.cmdsts);
1696 } else {
1697 txDmaAddr += offsetof(ns_desc32, cmdsts);
1698 txDmaLen = sizeof(txDesc32.cmdsts);
1699 }
1700 txDmaFree = dmaDescFree;
1701
1702 if (doTxDmaWrite())
1703 goto exit;
1704
1705 } else { /* this packet is totally done */
1706 DPRINTF(EthernetSM, "This packet is done, let's wrap it up\n");
1707 /* deal with the the packet that just finished */
1708 if ((regs.vtcr & VTCR_PPCHK) && extstsEnable) {
1709 IpPtr ip(txPacket);
1710 if (extsts & EXTSTS_UDPPKT) {
1711 UdpPtr udp(ip);
1712 if (udp) {
1713 udp->sum(0);
1714 udp->sum(cksum(udp));
1715 txUdpChecksums++;
1716 } else {
1717 Debug::breakpoint();
1718 warn_once("UDPPKT set, but not UDP!\n");
1719 }
1720 } else if (extsts & EXTSTS_TCPPKT) {
1721 TcpPtr tcp(ip);
1722 if (tcp) {
1723 tcp->sum(0);
1724 tcp->sum(cksum(tcp));
1725 txTcpChecksums++;
1726 } else {
1727 warn_once("TCPPKT set, but not UDP!\n");
1728 }
1729 }
1730 if (extsts & EXTSTS_IPPKT) {
1731 if (ip) {
1732 ip->sum(0);
1733 ip->sum(cksum(ip));
1734 txIpChecksums++;
1735 } else {
1736 warn_once("IPPKT set, but not UDP!\n");
1737 }
1738 }
1739 }
1740
1741 txPacket->simLength = txPacketBufPtr - txPacket->data;
1741 txPacket->length = txPacketBufPtr - txPacket->data;
1742 // this is just because the receive can't handle a
1743 // packet bigger want to make sure
1744 if (txPacket->length > 1514)
1745 panic("transmit packet too large, %s > 1514\n",
1746 txPacket->length);
1747
1748#ifndef NDEBUG
1749 bool success =
1750#endif
1751 txFifo.push(txPacket);
1752 assert(success);
1753
1754 /*
1755 * this following section is not tqo spec, but
1756 * functionally shouldn't be any different. normally,
1757 * the chip will wait til the transmit has occurred
1758 * before writing back the descriptor because it has
1759 * to wait to see that it was successfully transmitted
1760 * to decide whether to set CMDSTS_OK or not.
1761 * however, in the simulator since it is always
1762 * successfully transmitted, and writing it exactly to
1763 * spec would complicate the code, we just do it here
1764 */
1765
1766 cmdsts &= ~CMDSTS_OWN;
1767 cmdsts |= CMDSTS_OK;
1768
1769 DPRINTF(EthernetDesc,
1770 "txDesc writeback: cmdsts=%08x extsts=%08x\n",
1771 cmdsts, extsts);
1772
1773 txDmaFree = dmaDescFree;
1774 txDmaAddr = regs.txdp & 0x3fffffff;
1775 txDmaData = &cmdsts;
1776 if (is64bit) {
1777 txDmaAddr += offsetof(ns_desc64, cmdsts);
1778 txDmaLen =
1779 sizeof(txDesc64.cmdsts) + sizeof(txDesc64.extsts);
1780 } else {
1781 txDmaAddr += offsetof(ns_desc32, cmdsts);
1782 txDmaLen =
1783 sizeof(txDesc32.cmdsts) + sizeof(txDesc32.extsts);
1784 }
1785
1786 descDmaWrites++;
1787 descDmaWrBytes += txDmaLen;
1788
1789 transmit();
1790 txPacket = 0;
1791
1792 if (!txEnable) {
1793 DPRINTF(EthernetSM, "halting TX state machine\n");
1794 txState = txIdle;
1795 goto exit;
1796 } else
1797 txState = txAdvance;
1798
1799 if (doTxDmaWrite())
1800 goto exit;
1801 }
1802 } else {
1803 DPRINTF(EthernetSM, "this descriptor isn't done yet\n");
1804 if (!txFifo.full()) {
1805 txState = txFragRead;
1806
1807 /*
1808 * The number of bytes transferred is either whatever
1809 * is left in the descriptor (txDescCnt), or if there
1810 * is not enough room in the fifo, just whatever room
1811 * is left in the fifo
1812 */
1813 txXferLen = min<uint32_t>(txDescCnt, txFifo.avail());
1814
1815 txDmaAddr = txFragPtr & 0x3fffffff;
1816 txDmaData = txPacketBufPtr;
1817 txDmaLen = txXferLen;
1818 txDmaFree = dmaDataFree;
1819
1820 if (doTxDmaRead())
1821 goto exit;
1822 } else {
1823 txState = txFifoBlock;
1824 transmit();
1825
1826 goto exit;
1827 }
1828
1829 }
1830 break;
1831
1832 case txFragRead:
1833 if (txDmaState != dmaIdle)
1834 goto exit;
1835
1836 txPacketBufPtr += txXferLen;
1837 txFragPtr += txXferLen;
1838 txDescCnt -= txXferLen;
1839 txFifo.reserve(txXferLen);
1840
1841 txState = txFifoBlock;
1842 break;
1843
1844 case txDescWrite:
1845 if (txDmaState != dmaIdle)
1846 goto exit;
1847
1848 if (cmdsts & CMDSTS_INTR)
1849 devIntrPost(ISR_TXDESC);
1850
1851 if (!txEnable) {
1852 DPRINTF(EthernetSM, "halting TX state machine\n");
1853 txState = txIdle;
1854 goto exit;
1855 } else
1856 txState = txAdvance;
1857 break;
1858
1859 case txAdvance:
1860 if (link == 0) {
1861 devIntrPost(ISR_TXIDLE);
1862 txState = txIdle;
1863 goto exit;
1864 } else {
1865 if (txDmaState != dmaIdle)
1866 goto exit;
1867 txState = txDescRead;
1868 regs.txdp = link;
1869 CTDD = false;
1870
1871 txDmaAddr = link & 0x3fffffff;
1872 txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32;
1873 txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32);
1874 txDmaFree = dmaDescFree;
1875
1876 if (doTxDmaRead())
1877 goto exit;
1878 }
1879 break;
1880
1881 default:
1882 panic("invalid state");
1883 }
1884
1885 DPRINTF(EthernetSM, "entering next txState=%s\n",
1886 NsTxStateStrings[txState]);
1887 goto next;
1888
1889 exit:
1890 /**
1891 * @todo do we want to schedule a future kick?
1892 */
1893 DPRINTF(EthernetSM, "tx state machine exited txState=%s\n",
1894 NsTxStateStrings[txState]);
1895
1896 if (!txKickEvent.scheduled())
1897 schedule(txKickEvent, txKickTick);
1898}
1899
1900/**
1901 * Advance the EEPROM state machine
1902 * Called on rising edge of EEPROM clock bit in MEAR
1903 */
1904void
1905NSGigE::eepromKick()
1906{
1907 switch (eepromState) {
1908
1909 case eepromStart:
1910
1911 // Wait for start bit
1912 if (regs.mear & MEAR_EEDI) {
1913 // Set up to get 2 opcode bits
1914 eepromState = eepromGetOpcode;
1915 eepromBitsToRx = 2;
1916 eepromOpcode = 0;
1917 }
1918 break;
1919
1920 case eepromGetOpcode:
1921 eepromOpcode <<= 1;
1922 eepromOpcode += (regs.mear & MEAR_EEDI) ? 1 : 0;
1923 --eepromBitsToRx;
1924
1925 // Done getting opcode
1926 if (eepromBitsToRx == 0) {
1927 if (eepromOpcode != EEPROM_READ)
1928 panic("only EEPROM reads are implemented!");
1929
1930 // Set up to get address
1931 eepromState = eepromGetAddress;
1932 eepromBitsToRx = 6;
1933 eepromAddress = 0;
1934 }
1935 break;
1936
1937 case eepromGetAddress:
1938 eepromAddress <<= 1;
1939 eepromAddress += (regs.mear & MEAR_EEDI) ? 1 : 0;
1940 --eepromBitsToRx;
1941
1942 // Done getting address
1943 if (eepromBitsToRx == 0) {
1944
1945 if (eepromAddress >= EEPROM_SIZE)
1946 panic("EEPROM read access out of range!");
1947
1948 switch (eepromAddress) {
1949
1950 case EEPROM_PMATCH2_ADDR:
1951 eepromData = rom.perfectMatch[5];
1952 eepromData <<= 8;
1953 eepromData += rom.perfectMatch[4];
1954 break;
1955
1956 case EEPROM_PMATCH1_ADDR:
1957 eepromData = rom.perfectMatch[3];
1958 eepromData <<= 8;
1959 eepromData += rom.perfectMatch[2];
1960 break;
1961
1962 case EEPROM_PMATCH0_ADDR:
1963 eepromData = rom.perfectMatch[1];
1964 eepromData <<= 8;
1965 eepromData += rom.perfectMatch[0];
1966 break;
1967
1968 default:
1969 panic("FreeBSD driver only uses EEPROM to read PMATCH!");
1970 }
1971 // Set up to read data
1972 eepromState = eepromRead;
1973 eepromBitsToRx = 16;
1974
1975 // Clear data in bit
1976 regs.mear &= ~MEAR_EEDI;
1977 }
1978 break;
1979
1980 case eepromRead:
1981 // Clear Data Out bit
1982 regs.mear &= ~MEAR_EEDO;
1983 // Set bit to value of current EEPROM bit
1984 regs.mear |= (eepromData & 0x8000) ? MEAR_EEDO : 0x0;
1985
1986 eepromData <<= 1;
1987 --eepromBitsToRx;
1988
1989 // All done
1990 if (eepromBitsToRx == 0) {
1991 eepromState = eepromStart;
1992 }
1993 break;
1994
1995 default:
1996 panic("invalid EEPROM state");
1997 }
1998
1999}
2000
2001void
2002NSGigE::transferDone()
2003{
2004 if (txFifo.empty()) {
2005 DPRINTF(Ethernet, "transfer complete: txFifo empty...nothing to do\n");
2006 return;
2007 }
2008
2009 DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n");
2010
2011 reschedule(txEvent, clockEdge(Cycles(1)), true);
2012}
2013
2014bool
2015NSGigE::rxFilter(const EthPacketPtr &packet)
2016{
2017 EthPtr eth = packet;
2018 bool drop = true;
2019 string type;
2020
2021 const EthAddr &dst = eth->dst();
2022 if (dst.unicast()) {
2023 // If we're accepting all unicast addresses
2024 if (acceptUnicast)
2025 drop = false;
2026
2027 // If we make a perfect match
2028 if (acceptPerfect && dst == rom.perfectMatch)
2029 drop = false;
2030
2031 if (acceptArp && eth->type() == ETH_TYPE_ARP)
2032 drop = false;
2033
2034 } else if (dst.broadcast()) {
2035 // if we're accepting broadcasts
2036 if (acceptBroadcast)
2037 drop = false;
2038
2039 } else if (dst.multicast()) {
2040 // if we're accepting all multicasts
2041 if (acceptMulticast)
2042 drop = false;
2043
2044 // Multicast hashing faked - all packets accepted
2045 if (multicastHashEnable)
2046 drop = false;
2047 }
2048
2049 if (drop) {
2050 DPRINTF(Ethernet, "rxFilter drop\n");
2051 DDUMP(EthernetData, packet->data, packet->length);
2052 }
2053
2054 return drop;
2055}
2056
2057bool
2058NSGigE::recvPacket(EthPacketPtr packet)
2059{
2060 rxBytes += packet->length;
2061 rxPackets++;
2062
2063 DPRINTF(Ethernet, "Receiving packet from wire, rxFifoAvail=%d\n",
2064 rxFifo.avail());
2065
2066 if (!rxEnable) {
2067 DPRINTF(Ethernet, "receive disabled...packet dropped\n");
2068 return true;
2069 }
2070
2071 if (!rxFilterEnable) {
2072 DPRINTF(Ethernet,
2073 "receive packet filtering disabled . . . packet dropped\n");
2074 return true;
2075 }
2076
2077 if (rxFilter(packet)) {
2078 DPRINTF(Ethernet, "packet filtered...dropped\n");
2079 return true;
2080 }
2081
2082 if (rxFifo.avail() < packet->length) {
2083#if TRACING_ON
2084 IpPtr ip(packet);
2085 TcpPtr tcp(ip);
2086 if (ip) {
2087 DPRINTF(Ethernet,
2088 "packet won't fit in receive buffer...pkt ID %d dropped\n",
2089 ip->id());
2090 if (tcp) {
2091 DPRINTF(Ethernet, "Seq=%d\n", tcp->seq());
2092 }
2093 }
2094#endif
2095 droppedPackets++;
2096 devIntrPost(ISR_RXORN);
2097 return false;
2098 }
2099
2100 rxFifo.push(packet);
2101
2102 rxKick();
2103 return true;
2104}
2105
2106
2107void
2108NSGigE::drainResume()
2109{
2110 Drainable::drainResume();
2111
2112 // During drain we could have left the state machines in a waiting state and
2113 // they wouldn't get out until some other event occured to kick them.
2114 // This way they'll get out immediately
2115 txKick();
2116 rxKick();
2117}
2118
2119
2120//=====================================================================
2121//
2122//
2123void
2124NSGigE::serialize(CheckpointOut &cp) const
2125{
2126 // Serialize the PciDevice base class
2127 PciDevice::serialize(cp);
2128
2129 /*
2130 * Finalize any DMA events now.
2131 */
2132 // @todo will mem system save pending dma?
2133
2134 /*
2135 * Serialize the device registers
2136 */
2137 SERIALIZE_SCALAR(regs.command);
2138 SERIALIZE_SCALAR(regs.config);
2139 SERIALIZE_SCALAR(regs.mear);
2140 SERIALIZE_SCALAR(regs.ptscr);
2141 SERIALIZE_SCALAR(regs.isr);
2142 SERIALIZE_SCALAR(regs.imr);
2143 SERIALIZE_SCALAR(regs.ier);
2144 SERIALIZE_SCALAR(regs.ihr);
2145 SERIALIZE_SCALAR(regs.txdp);
2146 SERIALIZE_SCALAR(regs.txdp_hi);
2147 SERIALIZE_SCALAR(regs.txcfg);
2148 SERIALIZE_SCALAR(regs.gpior);
2149 SERIALIZE_SCALAR(regs.rxdp);
2150 SERIALIZE_SCALAR(regs.rxdp_hi);
2151 SERIALIZE_SCALAR(regs.rxcfg);
2152 SERIALIZE_SCALAR(regs.pqcr);
2153 SERIALIZE_SCALAR(regs.wcsr);
2154 SERIALIZE_SCALAR(regs.pcr);
2155 SERIALIZE_SCALAR(regs.rfcr);
2156 SERIALIZE_SCALAR(regs.rfdr);
2157 SERIALIZE_SCALAR(regs.brar);
2158 SERIALIZE_SCALAR(regs.brdr);
2159 SERIALIZE_SCALAR(regs.srr);
2160 SERIALIZE_SCALAR(regs.mibc);
2161 SERIALIZE_SCALAR(regs.vrcr);
2162 SERIALIZE_SCALAR(regs.vtcr);
2163 SERIALIZE_SCALAR(regs.vdr);
2164 SERIALIZE_SCALAR(regs.ccsr);
2165 SERIALIZE_SCALAR(regs.tbicr);
2166 SERIALIZE_SCALAR(regs.tbisr);
2167 SERIALIZE_SCALAR(regs.tanar);
2168 SERIALIZE_SCALAR(regs.tanlpar);
2169 SERIALIZE_SCALAR(regs.taner);
2170 SERIALIZE_SCALAR(regs.tesr);
2171
2172 SERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN);
2173 SERIALIZE_ARRAY(rom.filterHash, FHASH_SIZE);
2174
2175 SERIALIZE_SCALAR(ioEnable);
2176
2177 /*
2178 * Serialize the data Fifos
2179 */
2180 rxFifo.serialize("rxFifo", cp);
2181 txFifo.serialize("txFifo", cp);
2182
2183 /*
2184 * Serialize the various helper variables
2185 */
2186 bool txPacketExists = txPacket != nullptr;
2187 SERIALIZE_SCALAR(txPacketExists);
2188 if (txPacketExists) {
1742 txPacket->length = txPacketBufPtr - txPacket->data;
1743 // this is just because the receive can't handle a
1744 // packet bigger want to make sure
1745 if (txPacket->length > 1514)
1746 panic("transmit packet too large, %s > 1514\n",
1747 txPacket->length);
1748
1749#ifndef NDEBUG
1750 bool success =
1751#endif
1752 txFifo.push(txPacket);
1753 assert(success);
1754
1755 /*
1756 * this following section is not tqo spec, but
1757 * functionally shouldn't be any different. normally,
1758 * the chip will wait til the transmit has occurred
1759 * before writing back the descriptor because it has
1760 * to wait to see that it was successfully transmitted
1761 * to decide whether to set CMDSTS_OK or not.
1762 * however, in the simulator since it is always
1763 * successfully transmitted, and writing it exactly to
1764 * spec would complicate the code, we just do it here
1765 */
1766
1767 cmdsts &= ~CMDSTS_OWN;
1768 cmdsts |= CMDSTS_OK;
1769
1770 DPRINTF(EthernetDesc,
1771 "txDesc writeback: cmdsts=%08x extsts=%08x\n",
1772 cmdsts, extsts);
1773
1774 txDmaFree = dmaDescFree;
1775 txDmaAddr = regs.txdp & 0x3fffffff;
1776 txDmaData = &cmdsts;
1777 if (is64bit) {
1778 txDmaAddr += offsetof(ns_desc64, cmdsts);
1779 txDmaLen =
1780 sizeof(txDesc64.cmdsts) + sizeof(txDesc64.extsts);
1781 } else {
1782 txDmaAddr += offsetof(ns_desc32, cmdsts);
1783 txDmaLen =
1784 sizeof(txDesc32.cmdsts) + sizeof(txDesc32.extsts);
1785 }
1786
1787 descDmaWrites++;
1788 descDmaWrBytes += txDmaLen;
1789
1790 transmit();
1791 txPacket = 0;
1792
1793 if (!txEnable) {
1794 DPRINTF(EthernetSM, "halting TX state machine\n");
1795 txState = txIdle;
1796 goto exit;
1797 } else
1798 txState = txAdvance;
1799
1800 if (doTxDmaWrite())
1801 goto exit;
1802 }
1803 } else {
1804 DPRINTF(EthernetSM, "this descriptor isn't done yet\n");
1805 if (!txFifo.full()) {
1806 txState = txFragRead;
1807
1808 /*
1809 * The number of bytes transferred is either whatever
1810 * is left in the descriptor (txDescCnt), or if there
1811 * is not enough room in the fifo, just whatever room
1812 * is left in the fifo
1813 */
1814 txXferLen = min<uint32_t>(txDescCnt, txFifo.avail());
1815
1816 txDmaAddr = txFragPtr & 0x3fffffff;
1817 txDmaData = txPacketBufPtr;
1818 txDmaLen = txXferLen;
1819 txDmaFree = dmaDataFree;
1820
1821 if (doTxDmaRead())
1822 goto exit;
1823 } else {
1824 txState = txFifoBlock;
1825 transmit();
1826
1827 goto exit;
1828 }
1829
1830 }
1831 break;
1832
1833 case txFragRead:
1834 if (txDmaState != dmaIdle)
1835 goto exit;
1836
1837 txPacketBufPtr += txXferLen;
1838 txFragPtr += txXferLen;
1839 txDescCnt -= txXferLen;
1840 txFifo.reserve(txXferLen);
1841
1842 txState = txFifoBlock;
1843 break;
1844
1845 case txDescWrite:
1846 if (txDmaState != dmaIdle)
1847 goto exit;
1848
1849 if (cmdsts & CMDSTS_INTR)
1850 devIntrPost(ISR_TXDESC);
1851
1852 if (!txEnable) {
1853 DPRINTF(EthernetSM, "halting TX state machine\n");
1854 txState = txIdle;
1855 goto exit;
1856 } else
1857 txState = txAdvance;
1858 break;
1859
1860 case txAdvance:
1861 if (link == 0) {
1862 devIntrPost(ISR_TXIDLE);
1863 txState = txIdle;
1864 goto exit;
1865 } else {
1866 if (txDmaState != dmaIdle)
1867 goto exit;
1868 txState = txDescRead;
1869 regs.txdp = link;
1870 CTDD = false;
1871
1872 txDmaAddr = link & 0x3fffffff;
1873 txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32;
1874 txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32);
1875 txDmaFree = dmaDescFree;
1876
1877 if (doTxDmaRead())
1878 goto exit;
1879 }
1880 break;
1881
1882 default:
1883 panic("invalid state");
1884 }
1885
1886 DPRINTF(EthernetSM, "entering next txState=%s\n",
1887 NsTxStateStrings[txState]);
1888 goto next;
1889
1890 exit:
1891 /**
1892 * @todo do we want to schedule a future kick?
1893 */
1894 DPRINTF(EthernetSM, "tx state machine exited txState=%s\n",
1895 NsTxStateStrings[txState]);
1896
1897 if (!txKickEvent.scheduled())
1898 schedule(txKickEvent, txKickTick);
1899}
1900
1901/**
1902 * Advance the EEPROM state machine
1903 * Called on rising edge of EEPROM clock bit in MEAR
1904 */
1905void
1906NSGigE::eepromKick()
1907{
1908 switch (eepromState) {
1909
1910 case eepromStart:
1911
1912 // Wait for start bit
1913 if (regs.mear & MEAR_EEDI) {
1914 // Set up to get 2 opcode bits
1915 eepromState = eepromGetOpcode;
1916 eepromBitsToRx = 2;
1917 eepromOpcode = 0;
1918 }
1919 break;
1920
1921 case eepromGetOpcode:
1922 eepromOpcode <<= 1;
1923 eepromOpcode += (regs.mear & MEAR_EEDI) ? 1 : 0;
1924 --eepromBitsToRx;
1925
1926 // Done getting opcode
1927 if (eepromBitsToRx == 0) {
1928 if (eepromOpcode != EEPROM_READ)
1929 panic("only EEPROM reads are implemented!");
1930
1931 // Set up to get address
1932 eepromState = eepromGetAddress;
1933 eepromBitsToRx = 6;
1934 eepromAddress = 0;
1935 }
1936 break;
1937
1938 case eepromGetAddress:
1939 eepromAddress <<= 1;
1940 eepromAddress += (regs.mear & MEAR_EEDI) ? 1 : 0;
1941 --eepromBitsToRx;
1942
1943 // Done getting address
1944 if (eepromBitsToRx == 0) {
1945
1946 if (eepromAddress >= EEPROM_SIZE)
1947 panic("EEPROM read access out of range!");
1948
1949 switch (eepromAddress) {
1950
1951 case EEPROM_PMATCH2_ADDR:
1952 eepromData = rom.perfectMatch[5];
1953 eepromData <<= 8;
1954 eepromData += rom.perfectMatch[4];
1955 break;
1956
1957 case EEPROM_PMATCH1_ADDR:
1958 eepromData = rom.perfectMatch[3];
1959 eepromData <<= 8;
1960 eepromData += rom.perfectMatch[2];
1961 break;
1962
1963 case EEPROM_PMATCH0_ADDR:
1964 eepromData = rom.perfectMatch[1];
1965 eepromData <<= 8;
1966 eepromData += rom.perfectMatch[0];
1967 break;
1968
1969 default:
1970 panic("FreeBSD driver only uses EEPROM to read PMATCH!");
1971 }
1972 // Set up to read data
1973 eepromState = eepromRead;
1974 eepromBitsToRx = 16;
1975
1976 // Clear data in bit
1977 regs.mear &= ~MEAR_EEDI;
1978 }
1979 break;
1980
1981 case eepromRead:
1982 // Clear Data Out bit
1983 regs.mear &= ~MEAR_EEDO;
1984 // Set bit to value of current EEPROM bit
1985 regs.mear |= (eepromData & 0x8000) ? MEAR_EEDO : 0x0;
1986
1987 eepromData <<= 1;
1988 --eepromBitsToRx;
1989
1990 // All done
1991 if (eepromBitsToRx == 0) {
1992 eepromState = eepromStart;
1993 }
1994 break;
1995
1996 default:
1997 panic("invalid EEPROM state");
1998 }
1999
2000}
2001
2002void
2003NSGigE::transferDone()
2004{
2005 if (txFifo.empty()) {
2006 DPRINTF(Ethernet, "transfer complete: txFifo empty...nothing to do\n");
2007 return;
2008 }
2009
2010 DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n");
2011
2012 reschedule(txEvent, clockEdge(Cycles(1)), true);
2013}
2014
2015bool
2016NSGigE::rxFilter(const EthPacketPtr &packet)
2017{
2018 EthPtr eth = packet;
2019 bool drop = true;
2020 string type;
2021
2022 const EthAddr &dst = eth->dst();
2023 if (dst.unicast()) {
2024 // If we're accepting all unicast addresses
2025 if (acceptUnicast)
2026 drop = false;
2027
2028 // If we make a perfect match
2029 if (acceptPerfect && dst == rom.perfectMatch)
2030 drop = false;
2031
2032 if (acceptArp && eth->type() == ETH_TYPE_ARP)
2033 drop = false;
2034
2035 } else if (dst.broadcast()) {
2036 // if we're accepting broadcasts
2037 if (acceptBroadcast)
2038 drop = false;
2039
2040 } else if (dst.multicast()) {
2041 // if we're accepting all multicasts
2042 if (acceptMulticast)
2043 drop = false;
2044
2045 // Multicast hashing faked - all packets accepted
2046 if (multicastHashEnable)
2047 drop = false;
2048 }
2049
2050 if (drop) {
2051 DPRINTF(Ethernet, "rxFilter drop\n");
2052 DDUMP(EthernetData, packet->data, packet->length);
2053 }
2054
2055 return drop;
2056}
2057
2058bool
2059NSGigE::recvPacket(EthPacketPtr packet)
2060{
2061 rxBytes += packet->length;
2062 rxPackets++;
2063
2064 DPRINTF(Ethernet, "Receiving packet from wire, rxFifoAvail=%d\n",
2065 rxFifo.avail());
2066
2067 if (!rxEnable) {
2068 DPRINTF(Ethernet, "receive disabled...packet dropped\n");
2069 return true;
2070 }
2071
2072 if (!rxFilterEnable) {
2073 DPRINTF(Ethernet,
2074 "receive packet filtering disabled . . . packet dropped\n");
2075 return true;
2076 }
2077
2078 if (rxFilter(packet)) {
2079 DPRINTF(Ethernet, "packet filtered...dropped\n");
2080 return true;
2081 }
2082
2083 if (rxFifo.avail() < packet->length) {
2084#if TRACING_ON
2085 IpPtr ip(packet);
2086 TcpPtr tcp(ip);
2087 if (ip) {
2088 DPRINTF(Ethernet,
2089 "packet won't fit in receive buffer...pkt ID %d dropped\n",
2090 ip->id());
2091 if (tcp) {
2092 DPRINTF(Ethernet, "Seq=%d\n", tcp->seq());
2093 }
2094 }
2095#endif
2096 droppedPackets++;
2097 devIntrPost(ISR_RXORN);
2098 return false;
2099 }
2100
2101 rxFifo.push(packet);
2102
2103 rxKick();
2104 return true;
2105}
2106
2107
2108void
2109NSGigE::drainResume()
2110{
2111 Drainable::drainResume();
2112
2113 // During drain we could have left the state machines in a waiting state and
2114 // they wouldn't get out until some other event occured to kick them.
2115 // This way they'll get out immediately
2116 txKick();
2117 rxKick();
2118}
2119
2120
2121//=====================================================================
2122//
2123//
2124void
2125NSGigE::serialize(CheckpointOut &cp) const
2126{
2127 // Serialize the PciDevice base class
2128 PciDevice::serialize(cp);
2129
2130 /*
2131 * Finalize any DMA events now.
2132 */
2133 // @todo will mem system save pending dma?
2134
2135 /*
2136 * Serialize the device registers
2137 */
2138 SERIALIZE_SCALAR(regs.command);
2139 SERIALIZE_SCALAR(regs.config);
2140 SERIALIZE_SCALAR(regs.mear);
2141 SERIALIZE_SCALAR(regs.ptscr);
2142 SERIALIZE_SCALAR(regs.isr);
2143 SERIALIZE_SCALAR(regs.imr);
2144 SERIALIZE_SCALAR(regs.ier);
2145 SERIALIZE_SCALAR(regs.ihr);
2146 SERIALIZE_SCALAR(regs.txdp);
2147 SERIALIZE_SCALAR(regs.txdp_hi);
2148 SERIALIZE_SCALAR(regs.txcfg);
2149 SERIALIZE_SCALAR(regs.gpior);
2150 SERIALIZE_SCALAR(regs.rxdp);
2151 SERIALIZE_SCALAR(regs.rxdp_hi);
2152 SERIALIZE_SCALAR(regs.rxcfg);
2153 SERIALIZE_SCALAR(regs.pqcr);
2154 SERIALIZE_SCALAR(regs.wcsr);
2155 SERIALIZE_SCALAR(regs.pcr);
2156 SERIALIZE_SCALAR(regs.rfcr);
2157 SERIALIZE_SCALAR(regs.rfdr);
2158 SERIALIZE_SCALAR(regs.brar);
2159 SERIALIZE_SCALAR(regs.brdr);
2160 SERIALIZE_SCALAR(regs.srr);
2161 SERIALIZE_SCALAR(regs.mibc);
2162 SERIALIZE_SCALAR(regs.vrcr);
2163 SERIALIZE_SCALAR(regs.vtcr);
2164 SERIALIZE_SCALAR(regs.vdr);
2165 SERIALIZE_SCALAR(regs.ccsr);
2166 SERIALIZE_SCALAR(regs.tbicr);
2167 SERIALIZE_SCALAR(regs.tbisr);
2168 SERIALIZE_SCALAR(regs.tanar);
2169 SERIALIZE_SCALAR(regs.tanlpar);
2170 SERIALIZE_SCALAR(regs.taner);
2171 SERIALIZE_SCALAR(regs.tesr);
2172
2173 SERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN);
2174 SERIALIZE_ARRAY(rom.filterHash, FHASH_SIZE);
2175
2176 SERIALIZE_SCALAR(ioEnable);
2177
2178 /*
2179 * Serialize the data Fifos
2180 */
2181 rxFifo.serialize("rxFifo", cp);
2182 txFifo.serialize("txFifo", cp);
2183
2184 /*
2185 * Serialize the various helper variables
2186 */
2187 bool txPacketExists = txPacket != nullptr;
2188 SERIALIZE_SCALAR(txPacketExists);
2189 if (txPacketExists) {
2190 txPacket->simLength = txPacketBufPtr - txPacket->data;
2189 txPacket->length = txPacketBufPtr - txPacket->data;
2190 txPacket->serialize("txPacket", cp);
2191 uint32_t txPktBufPtr = (uint32_t) (txPacketBufPtr - txPacket->data);
2192 SERIALIZE_SCALAR(txPktBufPtr);
2193 }
2194
2195 bool rxPacketExists = rxPacket != nullptr;
2196 SERIALIZE_SCALAR(rxPacketExists);
2197 if (rxPacketExists) {
2198 rxPacket->serialize("rxPacket", cp);
2199 uint32_t rxPktBufPtr = (uint32_t) (rxPacketBufPtr - rxPacket->data);
2200 SERIALIZE_SCALAR(rxPktBufPtr);
2201 }
2202
2203 SERIALIZE_SCALAR(txXferLen);
2204 SERIALIZE_SCALAR(rxXferLen);
2205
2206 /*
2207 * Serialize Cached Descriptors
2208 */
2209 SERIALIZE_SCALAR(rxDesc64.link);
2210 SERIALIZE_SCALAR(rxDesc64.bufptr);
2211 SERIALIZE_SCALAR(rxDesc64.cmdsts);
2212 SERIALIZE_SCALAR(rxDesc64.extsts);
2213 SERIALIZE_SCALAR(txDesc64.link);
2214 SERIALIZE_SCALAR(txDesc64.bufptr);
2215 SERIALIZE_SCALAR(txDesc64.cmdsts);
2216 SERIALIZE_SCALAR(txDesc64.extsts);
2217 SERIALIZE_SCALAR(rxDesc32.link);
2218 SERIALIZE_SCALAR(rxDesc32.bufptr);
2219 SERIALIZE_SCALAR(rxDesc32.cmdsts);
2220 SERIALIZE_SCALAR(rxDesc32.extsts);
2221 SERIALIZE_SCALAR(txDesc32.link);
2222 SERIALIZE_SCALAR(txDesc32.bufptr);
2223 SERIALIZE_SCALAR(txDesc32.cmdsts);
2224 SERIALIZE_SCALAR(txDesc32.extsts);
2225 SERIALIZE_SCALAR(extstsEnable);
2226
2227 /*
2228 * Serialize tx state machine
2229 */
2230 int txState = this->txState;
2231 SERIALIZE_SCALAR(txState);
2232 SERIALIZE_SCALAR(txEnable);
2233 SERIALIZE_SCALAR(CTDD);
2234 SERIALIZE_SCALAR(txFragPtr);
2235 SERIALIZE_SCALAR(txDescCnt);
2236 int txDmaState = this->txDmaState;
2237 SERIALIZE_SCALAR(txDmaState);
2238 SERIALIZE_SCALAR(txKickTick);
2239
2240 /*
2241 * Serialize rx state machine
2242 */
2243 int rxState = this->rxState;
2244 SERIALIZE_SCALAR(rxState);
2245 SERIALIZE_SCALAR(rxEnable);
2246 SERIALIZE_SCALAR(CRDD);
2247 SERIALIZE_SCALAR(rxPktBytes);
2248 SERIALIZE_SCALAR(rxFragPtr);
2249 SERIALIZE_SCALAR(rxDescCnt);
2250 int rxDmaState = this->rxDmaState;
2251 SERIALIZE_SCALAR(rxDmaState);
2252 SERIALIZE_SCALAR(rxKickTick);
2253
2254 /*
2255 * Serialize EEPROM state machine
2256 */
2257 int eepromState = this->eepromState;
2258 SERIALIZE_SCALAR(eepromState);
2259 SERIALIZE_SCALAR(eepromClk);
2260 SERIALIZE_SCALAR(eepromBitsToRx);
2261 SERIALIZE_SCALAR(eepromOpcode);
2262 SERIALIZE_SCALAR(eepromAddress);
2263 SERIALIZE_SCALAR(eepromData);
2264
2265 /*
2266 * If there's a pending transmit, store the time so we can
2267 * reschedule it later
2268 */
2269 Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick() : 0;
2270 SERIALIZE_SCALAR(transmitTick);
2271
2272 /*
2273 * receive address filter settings
2274 */
2275 SERIALIZE_SCALAR(rxFilterEnable);
2276 SERIALIZE_SCALAR(acceptBroadcast);
2277 SERIALIZE_SCALAR(acceptMulticast);
2278 SERIALIZE_SCALAR(acceptUnicast);
2279 SERIALIZE_SCALAR(acceptPerfect);
2280 SERIALIZE_SCALAR(acceptArp);
2281 SERIALIZE_SCALAR(multicastHashEnable);
2282
2283 /*
2284 * Keep track of pending interrupt status.
2285 */
2286 SERIALIZE_SCALAR(intrTick);
2287 SERIALIZE_SCALAR(cpuPendingIntr);
2288 Tick intrEventTick = 0;
2289 if (intrEvent)
2290 intrEventTick = intrEvent->when();
2291 SERIALIZE_SCALAR(intrEventTick);
2292
2293}
2294
2295void
2296NSGigE::unserialize(CheckpointIn &cp)
2297{
2298 // Unserialize the PciDevice base class
2299 PciDevice::unserialize(cp);
2300
2301 UNSERIALIZE_SCALAR(regs.command);
2302 UNSERIALIZE_SCALAR(regs.config);
2303 UNSERIALIZE_SCALAR(regs.mear);
2304 UNSERIALIZE_SCALAR(regs.ptscr);
2305 UNSERIALIZE_SCALAR(regs.isr);
2306 UNSERIALIZE_SCALAR(regs.imr);
2307 UNSERIALIZE_SCALAR(regs.ier);
2308 UNSERIALIZE_SCALAR(regs.ihr);
2309 UNSERIALIZE_SCALAR(regs.txdp);
2310 UNSERIALIZE_SCALAR(regs.txdp_hi);
2311 UNSERIALIZE_SCALAR(regs.txcfg);
2312 UNSERIALIZE_SCALAR(regs.gpior);
2313 UNSERIALIZE_SCALAR(regs.rxdp);
2314 UNSERIALIZE_SCALAR(regs.rxdp_hi);
2315 UNSERIALIZE_SCALAR(regs.rxcfg);
2316 UNSERIALIZE_SCALAR(regs.pqcr);
2317 UNSERIALIZE_SCALAR(regs.wcsr);
2318 UNSERIALIZE_SCALAR(regs.pcr);
2319 UNSERIALIZE_SCALAR(regs.rfcr);
2320 UNSERIALIZE_SCALAR(regs.rfdr);
2321 UNSERIALIZE_SCALAR(regs.brar);
2322 UNSERIALIZE_SCALAR(regs.brdr);
2323 UNSERIALIZE_SCALAR(regs.srr);
2324 UNSERIALIZE_SCALAR(regs.mibc);
2325 UNSERIALIZE_SCALAR(regs.vrcr);
2326 UNSERIALIZE_SCALAR(regs.vtcr);
2327 UNSERIALIZE_SCALAR(regs.vdr);
2328 UNSERIALIZE_SCALAR(regs.ccsr);
2329 UNSERIALIZE_SCALAR(regs.tbicr);
2330 UNSERIALIZE_SCALAR(regs.tbisr);
2331 UNSERIALIZE_SCALAR(regs.tanar);
2332 UNSERIALIZE_SCALAR(regs.tanlpar);
2333 UNSERIALIZE_SCALAR(regs.taner);
2334 UNSERIALIZE_SCALAR(regs.tesr);
2335
2336 UNSERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN);
2337 UNSERIALIZE_ARRAY(rom.filterHash, FHASH_SIZE);
2338
2339 UNSERIALIZE_SCALAR(ioEnable);
2340
2341 /*
2342 * unserialize the data fifos
2343 */
2344 rxFifo.unserialize("rxFifo", cp);
2345 txFifo.unserialize("txFifo", cp);
2346
2347 /*
2348 * unserialize the various helper variables
2349 */
2350 bool txPacketExists;
2351 UNSERIALIZE_SCALAR(txPacketExists);
2352 if (txPacketExists) {
2191 txPacket->length = txPacketBufPtr - txPacket->data;
2192 txPacket->serialize("txPacket", cp);
2193 uint32_t txPktBufPtr = (uint32_t) (txPacketBufPtr - txPacket->data);
2194 SERIALIZE_SCALAR(txPktBufPtr);
2195 }
2196
2197 bool rxPacketExists = rxPacket != nullptr;
2198 SERIALIZE_SCALAR(rxPacketExists);
2199 if (rxPacketExists) {
2200 rxPacket->serialize("rxPacket", cp);
2201 uint32_t rxPktBufPtr = (uint32_t) (rxPacketBufPtr - rxPacket->data);
2202 SERIALIZE_SCALAR(rxPktBufPtr);
2203 }
2204
2205 SERIALIZE_SCALAR(txXferLen);
2206 SERIALIZE_SCALAR(rxXferLen);
2207
2208 /*
2209 * Serialize Cached Descriptors
2210 */
2211 SERIALIZE_SCALAR(rxDesc64.link);
2212 SERIALIZE_SCALAR(rxDesc64.bufptr);
2213 SERIALIZE_SCALAR(rxDesc64.cmdsts);
2214 SERIALIZE_SCALAR(rxDesc64.extsts);
2215 SERIALIZE_SCALAR(txDesc64.link);
2216 SERIALIZE_SCALAR(txDesc64.bufptr);
2217 SERIALIZE_SCALAR(txDesc64.cmdsts);
2218 SERIALIZE_SCALAR(txDesc64.extsts);
2219 SERIALIZE_SCALAR(rxDesc32.link);
2220 SERIALIZE_SCALAR(rxDesc32.bufptr);
2221 SERIALIZE_SCALAR(rxDesc32.cmdsts);
2222 SERIALIZE_SCALAR(rxDesc32.extsts);
2223 SERIALIZE_SCALAR(txDesc32.link);
2224 SERIALIZE_SCALAR(txDesc32.bufptr);
2225 SERIALIZE_SCALAR(txDesc32.cmdsts);
2226 SERIALIZE_SCALAR(txDesc32.extsts);
2227 SERIALIZE_SCALAR(extstsEnable);
2228
2229 /*
2230 * Serialize tx state machine
2231 */
2232 int txState = this->txState;
2233 SERIALIZE_SCALAR(txState);
2234 SERIALIZE_SCALAR(txEnable);
2235 SERIALIZE_SCALAR(CTDD);
2236 SERIALIZE_SCALAR(txFragPtr);
2237 SERIALIZE_SCALAR(txDescCnt);
2238 int txDmaState = this->txDmaState;
2239 SERIALIZE_SCALAR(txDmaState);
2240 SERIALIZE_SCALAR(txKickTick);
2241
2242 /*
2243 * Serialize rx state machine
2244 */
2245 int rxState = this->rxState;
2246 SERIALIZE_SCALAR(rxState);
2247 SERIALIZE_SCALAR(rxEnable);
2248 SERIALIZE_SCALAR(CRDD);
2249 SERIALIZE_SCALAR(rxPktBytes);
2250 SERIALIZE_SCALAR(rxFragPtr);
2251 SERIALIZE_SCALAR(rxDescCnt);
2252 int rxDmaState = this->rxDmaState;
2253 SERIALIZE_SCALAR(rxDmaState);
2254 SERIALIZE_SCALAR(rxKickTick);
2255
2256 /*
2257 * Serialize EEPROM state machine
2258 */
2259 int eepromState = this->eepromState;
2260 SERIALIZE_SCALAR(eepromState);
2261 SERIALIZE_SCALAR(eepromClk);
2262 SERIALIZE_SCALAR(eepromBitsToRx);
2263 SERIALIZE_SCALAR(eepromOpcode);
2264 SERIALIZE_SCALAR(eepromAddress);
2265 SERIALIZE_SCALAR(eepromData);
2266
2267 /*
2268 * If there's a pending transmit, store the time so we can
2269 * reschedule it later
2270 */
2271 Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick() : 0;
2272 SERIALIZE_SCALAR(transmitTick);
2273
2274 /*
2275 * receive address filter settings
2276 */
2277 SERIALIZE_SCALAR(rxFilterEnable);
2278 SERIALIZE_SCALAR(acceptBroadcast);
2279 SERIALIZE_SCALAR(acceptMulticast);
2280 SERIALIZE_SCALAR(acceptUnicast);
2281 SERIALIZE_SCALAR(acceptPerfect);
2282 SERIALIZE_SCALAR(acceptArp);
2283 SERIALIZE_SCALAR(multicastHashEnable);
2284
2285 /*
2286 * Keep track of pending interrupt status.
2287 */
2288 SERIALIZE_SCALAR(intrTick);
2289 SERIALIZE_SCALAR(cpuPendingIntr);
2290 Tick intrEventTick = 0;
2291 if (intrEvent)
2292 intrEventTick = intrEvent->when();
2293 SERIALIZE_SCALAR(intrEventTick);
2294
2295}
2296
2297void
2298NSGigE::unserialize(CheckpointIn &cp)
2299{
2300 // Unserialize the PciDevice base class
2301 PciDevice::unserialize(cp);
2302
2303 UNSERIALIZE_SCALAR(regs.command);
2304 UNSERIALIZE_SCALAR(regs.config);
2305 UNSERIALIZE_SCALAR(regs.mear);
2306 UNSERIALIZE_SCALAR(regs.ptscr);
2307 UNSERIALIZE_SCALAR(regs.isr);
2308 UNSERIALIZE_SCALAR(regs.imr);
2309 UNSERIALIZE_SCALAR(regs.ier);
2310 UNSERIALIZE_SCALAR(regs.ihr);
2311 UNSERIALIZE_SCALAR(regs.txdp);
2312 UNSERIALIZE_SCALAR(regs.txdp_hi);
2313 UNSERIALIZE_SCALAR(regs.txcfg);
2314 UNSERIALIZE_SCALAR(regs.gpior);
2315 UNSERIALIZE_SCALAR(regs.rxdp);
2316 UNSERIALIZE_SCALAR(regs.rxdp_hi);
2317 UNSERIALIZE_SCALAR(regs.rxcfg);
2318 UNSERIALIZE_SCALAR(regs.pqcr);
2319 UNSERIALIZE_SCALAR(regs.wcsr);
2320 UNSERIALIZE_SCALAR(regs.pcr);
2321 UNSERIALIZE_SCALAR(regs.rfcr);
2322 UNSERIALIZE_SCALAR(regs.rfdr);
2323 UNSERIALIZE_SCALAR(regs.brar);
2324 UNSERIALIZE_SCALAR(regs.brdr);
2325 UNSERIALIZE_SCALAR(regs.srr);
2326 UNSERIALIZE_SCALAR(regs.mibc);
2327 UNSERIALIZE_SCALAR(regs.vrcr);
2328 UNSERIALIZE_SCALAR(regs.vtcr);
2329 UNSERIALIZE_SCALAR(regs.vdr);
2330 UNSERIALIZE_SCALAR(regs.ccsr);
2331 UNSERIALIZE_SCALAR(regs.tbicr);
2332 UNSERIALIZE_SCALAR(regs.tbisr);
2333 UNSERIALIZE_SCALAR(regs.tanar);
2334 UNSERIALIZE_SCALAR(regs.tanlpar);
2335 UNSERIALIZE_SCALAR(regs.taner);
2336 UNSERIALIZE_SCALAR(regs.tesr);
2337
2338 UNSERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN);
2339 UNSERIALIZE_ARRAY(rom.filterHash, FHASH_SIZE);
2340
2341 UNSERIALIZE_SCALAR(ioEnable);
2342
2343 /*
2344 * unserialize the data fifos
2345 */
2346 rxFifo.unserialize("rxFifo", cp);
2347 txFifo.unserialize("txFifo", cp);
2348
2349 /*
2350 * unserialize the various helper variables
2351 */
2352 bool txPacketExists;
2353 UNSERIALIZE_SCALAR(txPacketExists);
2354 if (txPacketExists) {
2353 txPacket = make_shared<EthPacketData>(16384);
2355 txPacket = make_shared();
2354 txPacket->unserialize("txPacket", cp);
2355 uint32_t txPktBufPtr;
2356 UNSERIALIZE_SCALAR(txPktBufPtr);
2357 txPacketBufPtr = (uint8_t *) txPacket->data + txPktBufPtr;
2358 } else
2359 txPacket = 0;
2360
2361 bool rxPacketExists;
2362 UNSERIALIZE_SCALAR(rxPacketExists);
2363 rxPacket = 0;
2364 if (rxPacketExists) {
2356 txPacket->unserialize("txPacket", cp);
2357 uint32_t txPktBufPtr;
2358 UNSERIALIZE_SCALAR(txPktBufPtr);
2359 txPacketBufPtr = (uint8_t *) txPacket->data + txPktBufPtr;
2360 } else
2361 txPacket = 0;
2362
2363 bool rxPacketExists;
2364 UNSERIALIZE_SCALAR(rxPacketExists);
2365 rxPacket = 0;
2366 if (rxPacketExists) {
2365 rxPacket = make_shared<EthPacketData>(16384);
2367 rxPacket = make_shared();
2366 rxPacket->unserialize("rxPacket", cp);
2367 uint32_t rxPktBufPtr;
2368 UNSERIALIZE_SCALAR(rxPktBufPtr);
2369 rxPacketBufPtr = (uint8_t *) rxPacket->data + rxPktBufPtr;
2370 } else
2371 rxPacket = 0;
2372
2373 UNSERIALIZE_SCALAR(txXferLen);
2374 UNSERIALIZE_SCALAR(rxXferLen);
2375
2376 /*
2377 * Unserialize Cached Descriptors
2378 */
2379 UNSERIALIZE_SCALAR(rxDesc64.link);
2380 UNSERIALIZE_SCALAR(rxDesc64.bufptr);
2381 UNSERIALIZE_SCALAR(rxDesc64.cmdsts);
2382 UNSERIALIZE_SCALAR(rxDesc64.extsts);
2383 UNSERIALIZE_SCALAR(txDesc64.link);
2384 UNSERIALIZE_SCALAR(txDesc64.bufptr);
2385 UNSERIALIZE_SCALAR(txDesc64.cmdsts);
2386 UNSERIALIZE_SCALAR(txDesc64.extsts);
2387 UNSERIALIZE_SCALAR(rxDesc32.link);
2388 UNSERIALIZE_SCALAR(rxDesc32.bufptr);
2389 UNSERIALIZE_SCALAR(rxDesc32.cmdsts);
2390 UNSERIALIZE_SCALAR(rxDesc32.extsts);
2391 UNSERIALIZE_SCALAR(txDesc32.link);
2392 UNSERIALIZE_SCALAR(txDesc32.bufptr);
2393 UNSERIALIZE_SCALAR(txDesc32.cmdsts);
2394 UNSERIALIZE_SCALAR(txDesc32.extsts);
2395 UNSERIALIZE_SCALAR(extstsEnable);
2396
2397 /*
2398 * unserialize tx state machine
2399 */
2400 int txState;
2401 UNSERIALIZE_SCALAR(txState);
2402 this->txState = (TxState) txState;
2403 UNSERIALIZE_SCALAR(txEnable);
2404 UNSERIALIZE_SCALAR(CTDD);
2405 UNSERIALIZE_SCALAR(txFragPtr);
2406 UNSERIALIZE_SCALAR(txDescCnt);
2407 int txDmaState;
2408 UNSERIALIZE_SCALAR(txDmaState);
2409 this->txDmaState = (DmaState) txDmaState;
2410 UNSERIALIZE_SCALAR(txKickTick);
2411 if (txKickTick)
2412 schedule(txKickEvent, txKickTick);
2413
2414 /*
2415 * unserialize rx state machine
2416 */
2417 int rxState;
2418 UNSERIALIZE_SCALAR(rxState);
2419 this->rxState = (RxState) rxState;
2420 UNSERIALIZE_SCALAR(rxEnable);
2421 UNSERIALIZE_SCALAR(CRDD);
2422 UNSERIALIZE_SCALAR(rxPktBytes);
2423 UNSERIALIZE_SCALAR(rxFragPtr);
2424 UNSERIALIZE_SCALAR(rxDescCnt);
2425 int rxDmaState;
2426 UNSERIALIZE_SCALAR(rxDmaState);
2427 this->rxDmaState = (DmaState) rxDmaState;
2428 UNSERIALIZE_SCALAR(rxKickTick);
2429 if (rxKickTick)
2430 schedule(rxKickEvent, rxKickTick);
2431
2432 /*
2433 * Unserialize EEPROM state machine
2434 */
2435 int eepromState;
2436 UNSERIALIZE_SCALAR(eepromState);
2437 this->eepromState = (EEPROMState) eepromState;
2438 UNSERIALIZE_SCALAR(eepromClk);
2439 UNSERIALIZE_SCALAR(eepromBitsToRx);
2440 UNSERIALIZE_SCALAR(eepromOpcode);
2441 UNSERIALIZE_SCALAR(eepromAddress);
2442 UNSERIALIZE_SCALAR(eepromData);
2443
2444 /*
2445 * If there's a pending transmit, reschedule it now
2446 */
2447 Tick transmitTick;
2448 UNSERIALIZE_SCALAR(transmitTick);
2449 if (transmitTick)
2450 schedule(txEvent, curTick() + transmitTick);
2451
2452 /*
2453 * unserialize receive address filter settings
2454 */
2455 UNSERIALIZE_SCALAR(rxFilterEnable);
2456 UNSERIALIZE_SCALAR(acceptBroadcast);
2457 UNSERIALIZE_SCALAR(acceptMulticast);
2458 UNSERIALIZE_SCALAR(acceptUnicast);
2459 UNSERIALIZE_SCALAR(acceptPerfect);
2460 UNSERIALIZE_SCALAR(acceptArp);
2461 UNSERIALIZE_SCALAR(multicastHashEnable);
2462
2463 /*
2464 * Keep track of pending interrupt status.
2465 */
2466 UNSERIALIZE_SCALAR(intrTick);
2467 UNSERIALIZE_SCALAR(cpuPendingIntr);
2468 Tick intrEventTick;
2469 UNSERIALIZE_SCALAR(intrEventTick);
2470 if (intrEventTick) {
2471 intrEvent = new IntrEvent(this, true);
2472 schedule(intrEvent, intrEventTick);
2473 }
2474}
2475
2476NSGigE *
2477NSGigEParams::create()
2478{
2479 return new NSGigE(this);
2480}
2368 rxPacket->unserialize("rxPacket", cp);
2369 uint32_t rxPktBufPtr;
2370 UNSERIALIZE_SCALAR(rxPktBufPtr);
2371 rxPacketBufPtr = (uint8_t *) rxPacket->data + rxPktBufPtr;
2372 } else
2373 rxPacket = 0;
2374
2375 UNSERIALIZE_SCALAR(txXferLen);
2376 UNSERIALIZE_SCALAR(rxXferLen);
2377
2378 /*
2379 * Unserialize Cached Descriptors
2380 */
2381 UNSERIALIZE_SCALAR(rxDesc64.link);
2382 UNSERIALIZE_SCALAR(rxDesc64.bufptr);
2383 UNSERIALIZE_SCALAR(rxDesc64.cmdsts);
2384 UNSERIALIZE_SCALAR(rxDesc64.extsts);
2385 UNSERIALIZE_SCALAR(txDesc64.link);
2386 UNSERIALIZE_SCALAR(txDesc64.bufptr);
2387 UNSERIALIZE_SCALAR(txDesc64.cmdsts);
2388 UNSERIALIZE_SCALAR(txDesc64.extsts);
2389 UNSERIALIZE_SCALAR(rxDesc32.link);
2390 UNSERIALIZE_SCALAR(rxDesc32.bufptr);
2391 UNSERIALIZE_SCALAR(rxDesc32.cmdsts);
2392 UNSERIALIZE_SCALAR(rxDesc32.extsts);
2393 UNSERIALIZE_SCALAR(txDesc32.link);
2394 UNSERIALIZE_SCALAR(txDesc32.bufptr);
2395 UNSERIALIZE_SCALAR(txDesc32.cmdsts);
2396 UNSERIALIZE_SCALAR(txDesc32.extsts);
2397 UNSERIALIZE_SCALAR(extstsEnable);
2398
2399 /*
2400 * unserialize tx state machine
2401 */
2402 int txState;
2403 UNSERIALIZE_SCALAR(txState);
2404 this->txState = (TxState) txState;
2405 UNSERIALIZE_SCALAR(txEnable);
2406 UNSERIALIZE_SCALAR(CTDD);
2407 UNSERIALIZE_SCALAR(txFragPtr);
2408 UNSERIALIZE_SCALAR(txDescCnt);
2409 int txDmaState;
2410 UNSERIALIZE_SCALAR(txDmaState);
2411 this->txDmaState = (DmaState) txDmaState;
2412 UNSERIALIZE_SCALAR(txKickTick);
2413 if (txKickTick)
2414 schedule(txKickEvent, txKickTick);
2415
2416 /*
2417 * unserialize rx state machine
2418 */
2419 int rxState;
2420 UNSERIALIZE_SCALAR(rxState);
2421 this->rxState = (RxState) rxState;
2422 UNSERIALIZE_SCALAR(rxEnable);
2423 UNSERIALIZE_SCALAR(CRDD);
2424 UNSERIALIZE_SCALAR(rxPktBytes);
2425 UNSERIALIZE_SCALAR(rxFragPtr);
2426 UNSERIALIZE_SCALAR(rxDescCnt);
2427 int rxDmaState;
2428 UNSERIALIZE_SCALAR(rxDmaState);
2429 this->rxDmaState = (DmaState) rxDmaState;
2430 UNSERIALIZE_SCALAR(rxKickTick);
2431 if (rxKickTick)
2432 schedule(rxKickEvent, rxKickTick);
2433
2434 /*
2435 * Unserialize EEPROM state machine
2436 */
2437 int eepromState;
2438 UNSERIALIZE_SCALAR(eepromState);
2439 this->eepromState = (EEPROMState) eepromState;
2440 UNSERIALIZE_SCALAR(eepromClk);
2441 UNSERIALIZE_SCALAR(eepromBitsToRx);
2442 UNSERIALIZE_SCALAR(eepromOpcode);
2443 UNSERIALIZE_SCALAR(eepromAddress);
2444 UNSERIALIZE_SCALAR(eepromData);
2445
2446 /*
2447 * If there's a pending transmit, reschedule it now
2448 */
2449 Tick transmitTick;
2450 UNSERIALIZE_SCALAR(transmitTick);
2451 if (transmitTick)
2452 schedule(txEvent, curTick() + transmitTick);
2453
2454 /*
2455 * unserialize receive address filter settings
2456 */
2457 UNSERIALIZE_SCALAR(rxFilterEnable);
2458 UNSERIALIZE_SCALAR(acceptBroadcast);
2459 UNSERIALIZE_SCALAR(acceptMulticast);
2460 UNSERIALIZE_SCALAR(acceptUnicast);
2461 UNSERIALIZE_SCALAR(acceptPerfect);
2462 UNSERIALIZE_SCALAR(acceptArp);
2463 UNSERIALIZE_SCALAR(multicastHashEnable);
2464
2465 /*
2466 * Keep track of pending interrupt status.
2467 */
2468 UNSERIALIZE_SCALAR(intrTick);
2469 UNSERIALIZE_SCALAR(cpuPendingIntr);
2470 Tick intrEventTick;
2471 UNSERIALIZE_SCALAR(intrEventTick);
2472 if (intrEventTick) {
2473 intrEvent = new IntrEvent(this, true);
2474 schedule(intrEvent, intrEventTick);
2475 }
2476}
2477
2478NSGigE *
2479NSGigEParams::create()
2480{
2481 return new NSGigE(this);
2482}