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