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