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