Merge changes.
[gem5.git] / dev / sinic.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 #include <cstdio>
30 #include <deque>
31 #include <string>
32
33 #include "base/inet.hh"
34 #include "cpu/exec_context.hh"
35 #include "cpu/intr_control.hh"
36 #include "dev/dma.hh"
37 #include "dev/etherlink.hh"
38 #include "dev/sinic.hh"
39 #include "dev/pciconfigall.hh"
40 #include "mem/bus/bus.hh"
41 #include "mem/bus/dma_interface.hh"
42 #include "mem/bus/pio_interface.hh"
43 #include "mem/bus/pio_interface_impl.hh"
44 #include "mem/functional_mem/memory_control.hh"
45 #include "mem/functional_mem/physical_memory.hh"
46 #include "sim/builder.hh"
47 #include "sim/debug.hh"
48 #include "sim/eventq.hh"
49 #include "sim/host.hh"
50 #include "sim/stats.hh"
51 #include "targetarch/vtophys.hh"
52
53 using namespace Net;
54
55 namespace Sinic {
56
57 const char *RxStateStrings[] =
58 {
59 "rxIdle",
60 "rxFifoBlock",
61 "rxBeginCopy",
62 "rxCopy",
63 "rxCopyDone"
64 };
65
66 const char *TxStateStrings[] =
67 {
68 "txIdle",
69 "txFifoBlock",
70 "txBeginCopy",
71 "txCopy",
72 "txCopyDone"
73 };
74
75
76 ///////////////////////////////////////////////////////////////////////
77 //
78 // Sinic PCI Device
79 //
80 Base::Base(Params *p)
81 : PciDev(p), rxEnable(false), txEnable(false),
82 intrDelay(US2Ticks(p->intr_delay)),
83 intrTick(0), cpuIntrEnable(false), cpuPendingIntr(false), intrEvent(0),
84 interface(NULL)
85 {
86 }
87
88 Device::Device(Params *p)
89 : Base(p), plat(p->plat), physmem(p->physmem),
90 rxFifo(p->rx_fifo_size), txFifo(p->tx_fifo_size),
91 rxKickTick(0), txKickTick(0),
92 txEvent(this), rxDmaEvent(this), txDmaEvent(this),
93 dmaReadDelay(p->dma_read_delay), dmaReadFactor(p->dma_read_factor),
94 dmaWriteDelay(p->dma_write_delay), dmaWriteFactor(p->dma_write_factor)
95 {
96 reset();
97
98 if (p->header_bus) {
99 pioInterface = newPioInterface(p->name, p->hier, p->header_bus, this,
100 &Device::cacheAccess);
101
102 pioLatency = p->pio_latency * p->header_bus->clockRatio;
103
104 if (p->payload_bus)
105 dmaInterface = new DMAInterface<Bus>(p->name + ".dma",
106 p->header_bus, p->payload_bus,
107 1);
108 else
109 dmaInterface = new DMAInterface<Bus>(p->name + ".dma",
110 p->header_bus, p->header_bus,
111 1);
112 } else if (p->payload_bus) {
113 pioInterface = newPioInterface(p->name, p->hier, p->payload_bus, this,
114 &Device::cacheAccess);
115
116 pioLatency = p->pio_latency * p->payload_bus->clockRatio;
117
118 dmaInterface = new DMAInterface<Bus>(p->name + ".dma", p->payload_bus,
119 p->payload_bus, 1);
120 }
121 }
122
123 Device::~Device()
124 {}
125
126 void
127 Device::regStats()
128 {
129 rxBytes
130 .name(name() + ".rxBytes")
131 .desc("Bytes Received")
132 .prereq(rxBytes)
133 ;
134
135 rxBandwidth
136 .name(name() + ".rxBandwidth")
137 .desc("Receive Bandwidth (bits/s)")
138 .precision(0)
139 .prereq(rxBytes)
140 ;
141
142 rxPackets
143 .name(name() + ".rxPackets")
144 .desc("Number of Packets Received")
145 .prereq(rxBytes)
146 ;
147
148 rxPacketRate
149 .name(name() + ".rxPPS")
150 .desc("Packet Reception Rate (packets/s)")
151 .precision(0)
152 .prereq(rxBytes)
153 ;
154
155 rxIpPackets
156 .name(name() + ".rxIpPackets")
157 .desc("Number of IP Packets Received")
158 .prereq(rxBytes)
159 ;
160
161 rxTcpPackets
162 .name(name() + ".rxTcpPackets")
163 .desc("Number of Packets Received")
164 .prereq(rxBytes)
165 ;
166
167 rxUdpPackets
168 .name(name() + ".rxUdpPackets")
169 .desc("Number of UDP Packets Received")
170 .prereq(rxBytes)
171 ;
172
173 rxIpChecksums
174 .name(name() + ".rxIpChecksums")
175 .desc("Number of rx IP Checksums done by device")
176 .precision(0)
177 .prereq(rxBytes)
178 ;
179
180 rxTcpChecksums
181 .name(name() + ".rxTcpChecksums")
182 .desc("Number of rx TCP Checksums done by device")
183 .precision(0)
184 .prereq(rxBytes)
185 ;
186
187 rxUdpChecksums
188 .name(name() + ".rxUdpChecksums")
189 .desc("Number of rx UDP Checksums done by device")
190 .precision(0)
191 .prereq(rxBytes)
192 ;
193
194 txBytes
195 .name(name() + ".txBytes")
196 .desc("Bytes Transmitted")
197 .prereq(txBytes)
198 ;
199
200 txBandwidth
201 .name(name() + ".txBandwidth")
202 .desc("Transmit Bandwidth (bits/s)")
203 .precision(0)
204 .prereq(txBytes)
205 ;
206
207 txPackets
208 .name(name() + ".txPackets")
209 .desc("Number of Packets Transmitted")
210 .prereq(txBytes)
211 ;
212
213 txPacketRate
214 .name(name() + ".txPPS")
215 .desc("Packet Tranmission Rate (packets/s)")
216 .precision(0)
217 .prereq(txBytes)
218 ;
219
220 txIpPackets
221 .name(name() + ".txIpPackets")
222 .desc("Number of IP Packets Transmitted")
223 .prereq(txBytes)
224 ;
225
226 txTcpPackets
227 .name(name() + ".txTcpPackets")
228 .desc("Number of TCP Packets Transmitted")
229 .prereq(txBytes)
230 ;
231
232 txUdpPackets
233 .name(name() + ".txUdpPackets")
234 .desc("Number of Packets Transmitted")
235 .prereq(txBytes)
236 ;
237
238 txIpChecksums
239 .name(name() + ".txIpChecksums")
240 .desc("Number of tx IP Checksums done by device")
241 .precision(0)
242 .prereq(txBytes)
243 ;
244
245 txTcpChecksums
246 .name(name() + ".txTcpChecksums")
247 .desc("Number of tx TCP Checksums done by device")
248 .precision(0)
249 .prereq(txBytes)
250 ;
251
252 txUdpChecksums
253 .name(name() + ".txUdpChecksums")
254 .desc("Number of tx UDP Checksums done by device")
255 .precision(0)
256 .prereq(txBytes)
257 ;
258
259 txBandwidth = txBytes * Stats::constant(8) / simSeconds;
260 rxBandwidth = rxBytes * Stats::constant(8) / simSeconds;
261 txPacketRate = txPackets / simSeconds;
262 rxPacketRate = rxPackets / simSeconds;
263 }
264
265 /**
266 * This is to write to the PCI general configuration registers
267 */
268 void
269 Device::WriteConfig(int offset, int size, uint32_t data)
270 {
271 switch (offset) {
272 case PCI0_BASE_ADDR0:
273 // Need to catch writes to BARs to update the PIO interface
274 PciDev::WriteConfig(offset, size, data);
275 if (BARAddrs[0] != 0) {
276 if (pioInterface)
277 pioInterface->addAddrRange(RangeSize(BARAddrs[0], BARSize[0]));
278
279 BARAddrs[0] &= EV5::PAddrUncachedMask;
280 }
281 break;
282
283 default:
284 PciDev::WriteConfig(offset, size, data);
285 }
286 }
287
288 /**
289 * This reads the device registers, which are detailed in the NS83820
290 * spec sheet
291 */
292 Fault
293 Device::read(MemReqPtr &req, uint8_t *data)
294 {
295 assert(config.hdr.command & PCI_CMD_MSE);
296
297 //The mask is to give you only the offset into the device register file
298 Addr daddr = req->paddr & 0xfff;
299
300 if (Regs::regSize(daddr) == 0)
301 panic("invalid address: da=%#x pa=%#x va=%#x size=%d",
302 daddr, req->paddr, req->vaddr, req->size);
303
304 if (req->size != Regs::regSize(daddr))
305 panic("invalid size for reg %s: da=%#x pa=%#x va=%#x size=%d",
306 Regs::regName(daddr), daddr, req->paddr, req->vaddr, req->size);
307
308 DPRINTF(EthernetPIO, "read reg=%s da=%#x pa=%#x va=%#x size=%d\n",
309 Regs::regName(daddr), daddr, req->paddr, req->vaddr, req->size);
310
311 uint32_t &reg32 = *(uint32_t *)data;
312 uint64_t &reg64 = *(uint64_t *)data;
313
314 switch (daddr) {
315 case Regs::Config:
316 reg32 = regs.Config;
317 break;
318
319 case Regs::RxMaxCopy:
320 reg32 = regs.RxMaxCopy;
321 break;
322
323 case Regs::TxMaxCopy:
324 reg32 = regs.TxMaxCopy;
325 break;
326
327 case Regs::RxThreshold:
328 reg32 = regs.RxThreshold;
329 break;
330
331 case Regs::TxThreshold:
332 reg32 = regs.TxThreshold;
333 break;
334
335 case Regs::IntrStatus:
336 reg32 = regs.IntrStatus;
337 devIntrClear();
338 break;
339
340 case Regs::IntrMask:
341 reg32 = regs.IntrMask;
342 break;
343
344 case Regs::RxData:
345 reg64 = regs.RxData;
346 break;
347
348 case Regs::RxDone:
349 case Regs::RxWait:
350 reg64 = Regs::set_RxDone_FifoLen(regs.RxDone,
351 min(rxFifo.packets(), 255));
352 break;
353
354 case Regs::TxData:
355 reg64 = regs.TxData;
356 break;
357
358 case Regs::TxDone:
359 case Regs::TxWait:
360 reg64 = Regs::set_TxDone_FifoLen(regs.TxDone,
361 min(txFifo.packets(), 255));
362 break;
363
364 case Regs::HwAddr:
365 reg64 = params()->eaddr;
366 break;
367
368 default:
369 panic("reading write only register %s: da=%#x pa=%#x va=%#x size=%d",
370 Regs::regName(daddr), daddr, req->paddr, req->vaddr, req->size);
371 }
372
373 DPRINTF(EthernetPIO, "read reg=%s done val=%#x\n", Regs::regName(daddr),
374 Regs::regSize(daddr) == 4 ? reg32 : reg64);
375
376 return No_Fault;
377 }
378
379 Fault
380 Device::write(MemReqPtr &req, const uint8_t *data)
381 {
382 assert(config.hdr.command & PCI_CMD_MSE);
383 Addr daddr = req->paddr & 0xfff;
384
385 if (Regs::regSize(daddr) == 0)
386 panic("invalid address: da=%#x pa=%#x va=%#x size=%d",
387 daddr, req->paddr, req->vaddr, req->size);
388
389 if (req->size != Regs::regSize(daddr))
390 panic("invalid size: reg=%s da=%#x pa=%#x va=%#x size=%d",
391 Regs::regName(daddr), daddr, req->paddr, req->vaddr, req->size);
392
393 uint32_t reg32 = *(uint32_t *)data;
394 uint64_t reg64 = *(uint64_t *)data;
395
396 DPRINTF(EthernetPIO, "write reg=%s val=%#x da=%#x pa=%#x va=%#x size=%d\n",
397 Regs::regName(daddr), Regs::regSize(daddr) == 4 ? reg32 : reg64,
398 daddr, req->paddr, req->vaddr, req->size);
399
400
401 switch (daddr) {
402 case Regs::Config:
403 changeConfig(reg32);
404 break;
405
406 case Regs::RxThreshold:
407 regs.RxThreshold = reg32;
408 break;
409
410 case Regs::TxThreshold:
411 regs.TxThreshold = reg32;
412 break;
413
414 case Regs::IntrMask:
415 devIntrChangeMask(reg32);
416 break;
417
418 case Regs::RxData:
419 if (rxState != rxIdle)
420 panic("receive machine busy with another request!");
421
422 regs.RxDone = 0;
423 regs.RxData = reg64;
424 if (rxEnable) {
425 rxState = rxFifoBlock;
426 rxKick();
427 }
428 break;
429
430 case Regs::TxData:
431 if (txState != txIdle)
432 panic("transmit machine busy with another request!");
433
434 regs.TxDone = 0;
435 regs.TxData = reg64;
436 if (txEnable) {
437 txState = txFifoBlock;
438 txKick();
439 }
440 break;
441
442 default:
443 panic("writing read only register %s: da=%#x pa=%#x va=%#x size=%d",
444 Regs::regName(daddr), daddr, req->paddr, req->vaddr, req->size);
445 }
446
447 return No_Fault;
448 }
449
450 void
451 Device::devIntrPost(uint32_t interrupts)
452 {
453 if ((interrupts & Regs::Intr_Res))
454 panic("Cannot set a reserved interrupt");
455
456 regs.IntrStatus |= interrupts;
457
458 DPRINTF(EthernetIntr,
459 "interrupt written to intStatus: intr=%#x status=%#x mask=%#x\n",
460 interrupts, regs.IntrStatus, regs.IntrMask);
461
462 if ((regs.IntrStatus & regs.IntrMask)) {
463 Tick when = curTick;
464 if ((regs.IntrStatus & regs.IntrMask & Regs::Intr_NoDelay) == 0)
465 when += intrDelay;
466 cpuIntrPost(when);
467 }
468 }
469
470 void
471 Device::devIntrClear(uint32_t interrupts)
472 {
473 if ((interrupts & Regs::Intr_Res))
474 panic("Cannot clear a reserved interrupt");
475
476 regs.IntrStatus &= ~interrupts;
477
478 DPRINTF(EthernetIntr,
479 "interrupt cleared from intStatus: intr=%x status=%x mask=%x\n",
480 interrupts, regs.IntrStatus, regs.IntrMask);
481
482 if (!(regs.IntrStatus & regs.IntrMask))
483 cpuIntrClear();
484 }
485
486 void
487 Device::devIntrChangeMask(uint32_t newmask)
488 {
489 if (regs.IntrMask == newmask)
490 return;
491
492 regs.IntrMask = newmask;
493
494 DPRINTF(EthernetIntr,
495 "interrupt mask changed: intStatus=%x intMask=%x masked=%x\n",
496 regs.IntrStatus, regs.IntrMask, regs.IntrStatus & regs.IntrMask);
497
498 if (regs.IntrStatus & regs.IntrMask)
499 cpuIntrPost(curTick);
500 else
501 cpuIntrClear();
502 }
503
504 void
505 Base::cpuIntrPost(Tick when)
506 {
507 // If the interrupt you want to post is later than an interrupt
508 // already scheduled, just let it post in the coming one and don't
509 // schedule another.
510 // HOWEVER, must be sure that the scheduled intrTick is in the
511 // future (this was formerly the source of a bug)
512 /**
513 * @todo this warning should be removed and the intrTick code should
514 * be fixed.
515 */
516 assert(when >= curTick);
517 assert(intrTick >= curTick || intrTick == 0);
518 if (!cpuIntrEnable) {
519 DPRINTF(EthernetIntr, "interrupts not enabled.\n",
520 intrTick);
521 return;
522 }
523
524 if (when > intrTick && intrTick != 0) {
525 DPRINTF(EthernetIntr, "don't need to schedule event...intrTick=%d\n",
526 intrTick);
527 return;
528 }
529
530 intrTick = when;
531 if (intrTick < curTick) {
532 debug_break();
533 intrTick = curTick;
534 }
535
536 DPRINTF(EthernetIntr, "going to schedule an interrupt for intrTick=%d\n",
537 intrTick);
538
539 if (intrEvent)
540 intrEvent->squash();
541 intrEvent = new IntrEvent(this, true);
542 intrEvent->schedule(intrTick);
543 }
544
545 void
546 Base::cpuInterrupt()
547 {
548 assert(intrTick == curTick);
549
550 // Whether or not there's a pending interrupt, we don't care about
551 // it anymore
552 intrEvent = 0;
553 intrTick = 0;
554
555 // Don't send an interrupt if there's already one
556 if (cpuPendingIntr) {
557 DPRINTF(EthernetIntr,
558 "would send an interrupt now, but there's already pending\n");
559 } else {
560 // Send interrupt
561 cpuPendingIntr = true;
562
563 DPRINTF(EthernetIntr, "posting interrupt\n");
564 intrPost();
565 }
566 }
567
568 void
569 Base::cpuIntrClear()
570 {
571 if (!cpuPendingIntr)
572 return;
573
574 if (intrEvent) {
575 intrEvent->squash();
576 intrEvent = 0;
577 }
578
579 intrTick = 0;
580
581 cpuPendingIntr = false;
582
583 DPRINTF(EthernetIntr, "clearing cchip interrupt\n");
584 intrClear();
585 }
586
587 bool
588 Base::cpuIntrPending() const
589 { return cpuPendingIntr; }
590
591 void
592 Device::changeConfig(uint32_t newconf)
593 {
594 uint32_t changed = regs.Config ^ newconf;
595 if (!changed)
596 return;
597
598 regs.Config = newconf;
599
600 if ((changed & Regs::Config_Reset)) {
601 assert(regs.Config & Regs::Config_Reset);
602 reset();
603 regs.Config &= ~Regs::Config_Reset;
604 }
605
606 if ((changed & Regs::Config_IntEn)) {
607 cpuIntrEnable = regs.Config & Regs::Config_IntEn;
608 if (cpuIntrEnable) {
609 if (regs.IntrStatus & regs.IntrMask)
610 cpuIntrPost(curTick);
611 } else {
612 cpuIntrClear();
613 }
614 }
615
616 if ((changed & Regs::Config_TxEn)) {
617 txEnable = regs.Config & Regs::Config_TxEn;
618 if (txEnable)
619 txKick();
620 }
621
622 if ((changed & Regs::Config_RxEn)) {
623 rxEnable = regs.Config & Regs::Config_RxEn;
624 if (rxEnable)
625 rxKick();
626 }
627 }
628
629 void
630 Device::reset()
631 {
632 using namespace Regs;
633 memset(&regs, 0, sizeof(regs));
634 regs.RxMaxCopy = params()->rx_max_copy;
635 regs.TxMaxCopy = params()->tx_max_copy;
636 regs.IntrMask = Intr_TxFifo | Intr_RxFifo | Intr_RxData;
637
638 rxState = rxIdle;
639 txState = txIdle;
640
641 rxFifo.clear();
642 txFifo.clear();
643 }
644
645 void
646 Device::rxDmaCopy()
647 {
648 assert(rxState == rxCopy);
649 rxState = rxCopyDone;
650 physmem->dma_write(rxDmaAddr, (uint8_t *)rxDmaData, rxDmaLen);
651 DPRINTF(EthernetDMA, "rx dma write paddr=%#x len=%d\n",
652 rxDmaAddr, rxDmaLen);
653 DDUMP(EthernetDMA, rxDmaData, rxDmaLen);
654 }
655
656 void
657 Device::rxDmaDone()
658 {
659 rxDmaCopy();
660 rxKick();
661 }
662
663 void
664 Device::rxKick()
665 {
666 DPRINTF(EthernetSM, "receive kick rxState=%s (rxFifo.size=%d)\n",
667 RxStateStrings[rxState], rxFifo.size());
668
669 if (rxKickTick > curTick) {
670 DPRINTF(EthernetSM, "receive kick exiting, can't run till %d\n",
671 rxKickTick);
672 return;
673 }
674
675 next:
676 switch (rxState) {
677 case rxIdle:
678 if (rxPioRequest) {
679 pioInterface->respond(rxPioRequest, curTick);
680 rxPioRequest = 0;
681 }
682 goto exit;
683
684 case rxFifoBlock:
685 if (rxPacket) {
686 rxState = rxBeginCopy;
687 break;
688 }
689
690 if (rxFifo.empty()) {
691 DPRINTF(EthernetSM, "receive waiting for data. Nothing to do.\n");
692 goto exit;
693 }
694
695 // Grab a new packet from the fifo.
696 rxPacket = rxFifo.front();
697 rxPacketBufPtr = rxPacket->data;
698 rxPktBytes = rxPacket->length;
699 assert(rxPktBytes);
700
701 rxDoneData = 0;
702 /* scope for variables */ {
703 IpPtr ip(rxPacket);
704 if (ip) {
705 rxDoneData |= Regs::RxDone_IpPacket;
706 rxIpChecksums++;
707 if (cksum(ip) != 0) {
708 DPRINTF(EthernetCksum, "Rx IP Checksum Error\n");
709 rxDoneData |= Regs::RxDone_IpError;
710 }
711 TcpPtr tcp(ip);
712 UdpPtr udp(ip);
713 if (tcp) {
714 rxDoneData |= Regs::RxDone_TcpPacket;
715 rxTcpChecksums++;
716 if (cksum(tcp) != 0) {
717 DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n");
718 rxDoneData |= Regs::RxDone_TcpError;
719 }
720 } else if (udp) {
721 rxDoneData |= Regs::RxDone_UdpPacket;
722 rxUdpChecksums++;
723 if (cksum(udp) != 0) {
724 DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n");
725 rxDoneData |= Regs::RxDone_UdpError;
726 }
727 }
728 }
729 }
730 rxState = rxBeginCopy;
731 break;
732
733 case rxBeginCopy:
734 rxDmaAddr = plat->pciToDma(Regs::get_RxData_Addr(regs.RxData));
735 rxDmaLen = min<int>(Regs::get_RxData_Len(regs.RxData), rxPktBytes);
736 rxDmaData = rxPacketBufPtr;
737
738 if (dmaInterface) {
739 if (!dmaInterface->busy()) {
740 dmaInterface->doDMA(WriteInvalidate, rxDmaAddr, rxDmaLen,
741 curTick, &rxDmaEvent, true);
742 rxState = rxCopy;
743 }
744 goto exit;
745 }
746
747 rxState = rxCopy;
748 if (dmaWriteDelay != 0 || dmaWriteFactor != 0) {
749 Tick factor = ((rxDmaLen + ULL(63)) >> ULL(6)) * dmaWriteFactor;
750 Tick start = curTick + dmaWriteDelay + factor;
751 rxDmaEvent.schedule(start);
752 goto exit;
753 }
754
755 rxDmaCopy();
756 break;
757
758 case rxCopy:
759 DPRINTF(EthernetSM, "receive machine still copying\n");
760 goto exit;
761
762 case rxCopyDone:
763 regs.RxDone = rxDoneData | rxDmaLen;
764
765 if (rxPktBytes == rxDmaLen) {
766 rxPacket = NULL;
767 rxFifo.pop();
768 } else {
769 regs.RxDone |= Regs::RxDone_More;
770 rxPktBytes -= rxDmaLen;
771 rxPacketBufPtr += rxDmaLen;
772 }
773
774 regs.RxDone |= Regs::RxDone_Complete;
775 devIntrPost(Regs::Intr_RxData);
776 rxState = rxIdle;
777 break;
778
779 default:
780 panic("Invalid rxState!");
781 }
782
783 DPRINTF(EthernetSM, "entering next rxState=%s\n",
784 RxStateStrings[rxState]);
785
786 goto next;
787
788 exit:
789 /**
790 * @todo do we want to schedule a future kick?
791 */
792 DPRINTF(EthernetSM, "rx state machine exited rxState=%s\n",
793 RxStateStrings[rxState]);
794 }
795
796 void
797 Device::txDmaCopy()
798 {
799 assert(txState == txCopy);
800 txState = txCopyDone;
801 physmem->dma_read((uint8_t *)txDmaData, txDmaAddr, txDmaLen);
802 DPRINTF(EthernetDMA, "tx dma read paddr=%#x len=%d\n",
803 txDmaAddr, txDmaLen);
804 DDUMP(EthernetDMA, txDmaData, txDmaLen);
805 }
806
807 void
808 Device::txDmaDone()
809 {
810 txDmaCopy();
811 txKick();
812 }
813
814 void
815 Device::transmit()
816 {
817 if (txFifo.empty()) {
818 DPRINTF(Ethernet, "nothing to transmit\n");
819 return;
820 }
821
822 PacketPtr packet = txFifo.front();
823 if (!interface->sendPacket(packet)) {
824 DPRINTF(Ethernet, "Packet Transmit: failed txFifo available %d\n",
825 txFifo.avail());
826 goto reschedule;
827 }
828
829 txFifo.pop();
830
831 #if TRACING_ON
832 if (DTRACE(Ethernet)) {
833 IpPtr ip(packet);
834 if (ip) {
835 DPRINTF(Ethernet, "ID is %d\n", ip->id());
836 TcpPtr tcp(ip);
837 if (tcp) {
838 DPRINTF(Ethernet, "Src Port=%d, Dest Port=%d\n",
839 tcp->sport(), tcp->dport());
840 }
841 }
842 }
843 #endif
844
845 DDUMP(Ethernet, packet->data, packet->length);
846 txBytes += packet->length;
847 txPackets++;
848
849 DPRINTF(Ethernet, "Packet Transmit: successful txFifo Available %d\n",
850 txFifo.avail());
851
852 if (txFifo.size() <= params()->tx_fifo_threshold)
853 devIntrPost(Regs::Intr_TxFifo);
854
855 devIntrPost(Regs::Intr_TxDone);
856
857 reschedule:
858 if (!txFifo.empty() && !txEvent.scheduled()) {
859 DPRINTF(Ethernet, "reschedule transmit\n");
860 txEvent.schedule(curTick + 1000);
861 }
862 }
863
864 void
865 Device::txKick()
866 {
867 DPRINTF(EthernetSM, "transmit kick txState=%s (txFifo.size=%d)\n",
868 TxStateStrings[txState], txFifo.size());
869
870 if (txKickTick > curTick) {
871 DPRINTF(EthernetSM, "transmit kick exiting, can't run till %d\n",
872 txKickTick);
873 return;
874 }
875
876 next:
877 switch (txState) {
878 case txIdle:
879 if (txPioRequest) {
880 pioInterface->respond(txPioRequest, curTick + pioLatency);
881 txPioRequest = 0;
882 }
883 goto exit;
884
885 case txFifoBlock:
886 if (!txPacket) {
887 // Grab a new packet from the fifo.
888 txPacket = new PacketData(16384);
889 txPacketBufPtr = txPacket->data;
890 }
891
892 if (txFifo.avail() - txPacket->length <
893 Regs::get_TxData_Len(regs.TxData)) {
894 DPRINTF(EthernetSM, "transmit fifo full. Nothing to do.\n");
895 goto exit;
896 }
897
898 txState = txBeginCopy;
899 break;
900
901 case txBeginCopy:
902 txDmaAddr = plat->pciToDma(Regs::get_TxData_Addr(regs.TxData));
903 txDmaLen = Regs::get_TxData_Len(regs.TxData);
904 txDmaData = txPacketBufPtr;
905
906 if (dmaInterface) {
907 if (!dmaInterface->busy()) {
908 dmaInterface->doDMA(Read, txDmaAddr, txDmaLen,
909 curTick, &txDmaEvent, true);
910 txState = txCopy;
911 }
912
913 goto exit;
914 }
915
916 txState = txCopy;
917 if (dmaReadDelay != 0 || dmaReadFactor != 0) {
918 Tick factor = ((txDmaLen + ULL(63)) >> ULL(6)) * dmaReadFactor;
919 Tick start = curTick + dmaReadDelay + factor;
920 txDmaEvent.schedule(start);
921 goto exit;
922 }
923
924 txDmaCopy();
925 break;
926
927 case txCopy:
928 DPRINTF(EthernetSM, "transmit machine still copying\n");
929 goto exit;
930
931 case txCopyDone:
932 txPacket->length += txDmaLen;
933 if ((regs.TxData & Regs::TxData_More)) {
934 txPacketBufPtr += txDmaLen;
935 } else {
936 assert(txPacket->length <= txFifo.avail());
937 if ((regs.TxData & Regs::TxData_Checksum)) {
938 IpPtr ip(txPacket);
939 if (ip) {
940 TcpPtr tcp(ip);
941 if (tcp) {
942 tcp->sum(0);
943 tcp->sum(cksum(tcp));
944 txTcpChecksums++;
945 }
946
947 UdpPtr udp(ip);
948 if (udp) {
949 udp->sum(0);
950 udp->sum(cksum(udp));
951 txUdpChecksums++;
952 }
953
954 ip->sum(0);
955 ip->sum(cksum(ip));
956 txIpChecksums++;
957 }
958 }
959 txFifo.push(txPacket);
960 txPacket = 0;
961 transmit();
962 }
963
964 regs.TxDone = txDmaLen | Regs::TxDone_Complete;
965 devIntrPost(Regs::Intr_TxData);
966 txState = txIdle;
967 break;
968
969 default:
970 panic("Invalid txState!");
971 }
972
973 DPRINTF(EthernetSM, "entering next txState=%s\n",
974 TxStateStrings[txState]);
975
976 goto next;
977
978 exit:
979 /**
980 * @todo do we want to schedule a future kick?
981 */
982 DPRINTF(EthernetSM, "tx state machine exited txState=%s\n",
983 TxStateStrings[txState]);
984 }
985
986 void
987 Device::transferDone()
988 {
989 if (txFifo.empty()) {
990 DPRINTF(Ethernet, "transfer complete: txFifo empty...nothing to do\n");
991 return;
992 }
993
994 DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n");
995
996 if (txEvent.scheduled())
997 txEvent.reschedule(curTick + 1);
998 else
999 txEvent.schedule(curTick + 1);
1000 }
1001
1002 bool
1003 Device::rxFilter(const PacketPtr &packet)
1004 {
1005 if (!Regs::get_Config_Filter(regs.Config))
1006 return false;
1007
1008 panic("receive filter not implemented\n");
1009 bool drop = true;
1010
1011 #if 0
1012 string type;
1013
1014 EthHdr *eth = packet->eth();
1015 if (eth->unicast()) {
1016 // If we're accepting all unicast addresses
1017 if (acceptUnicast)
1018 drop = false;
1019
1020 // If we make a perfect match
1021 if (acceptPerfect && params->eaddr == eth.dst())
1022 drop = false;
1023
1024 if (acceptArp && eth->type() == ETH_TYPE_ARP)
1025 drop = false;
1026
1027 } else if (eth->broadcast()) {
1028 // if we're accepting broadcasts
1029 if (acceptBroadcast)
1030 drop = false;
1031
1032 } else if (eth->multicast()) {
1033 // if we're accepting all multicasts
1034 if (acceptMulticast)
1035 drop = false;
1036
1037 }
1038
1039 if (drop) {
1040 DPRINTF(Ethernet, "rxFilter drop\n");
1041 DDUMP(EthernetData, packet->data, packet->length);
1042 }
1043 #endif
1044 return drop;
1045 }
1046
1047 bool
1048 Device::recvPacket(PacketPtr packet)
1049 {
1050 rxBytes += packet->length;
1051 rxPackets++;
1052
1053 DPRINTF(Ethernet, "Receiving packet from wire, rxFifo Available is %d\n",
1054 rxFifo.avail());
1055
1056 if (!rxEnable) {
1057 DPRINTF(Ethernet, "receive disabled...packet dropped\n");
1058 interface->recvDone();
1059 return true;
1060 }
1061
1062 if (rxFilter(packet)) {
1063 DPRINTF(Ethernet, "packet filtered...dropped\n");
1064 interface->recvDone();
1065 return true;
1066 }
1067
1068 if (rxFifo.size() >= params()->rx_fifo_threshold)
1069 devIntrPost(Regs::Intr_RxFifo);
1070
1071 if (!rxFifo.push(packet)) {
1072 DPRINTF(Ethernet,
1073 "packet will not fit in receive buffer...packet dropped\n");
1074 return false;
1075 }
1076
1077 interface->recvDone();
1078 devIntrPost(Regs::Intr_RxDone);
1079 rxKick();
1080 return true;
1081 }
1082
1083 //=====================================================================
1084 //
1085 //
1086 void
1087 Base::serialize(ostream &os)
1088 {
1089 // Serialize the PciDev base class
1090 PciDev::serialize(os);
1091
1092 SERIALIZE_SCALAR(rxEnable);
1093 SERIALIZE_SCALAR(txEnable);
1094 SERIALIZE_SCALAR(cpuIntrEnable);
1095
1096 /*
1097 * Keep track of pending interrupt status.
1098 */
1099 SERIALIZE_SCALAR(intrTick);
1100 SERIALIZE_SCALAR(cpuPendingIntr);
1101 Tick intrEventTick = 0;
1102 if (intrEvent)
1103 intrEventTick = intrEvent->when();
1104 SERIALIZE_SCALAR(intrEventTick);
1105 }
1106
1107 void
1108 Base::unserialize(Checkpoint *cp, const std::string &section)
1109 {
1110 // Unserialize the PciDev base class
1111 PciDev::unserialize(cp, section);
1112
1113 UNSERIALIZE_SCALAR(rxEnable);
1114 UNSERIALIZE_SCALAR(txEnable);
1115 UNSERIALIZE_SCALAR(cpuIntrEnable);
1116
1117 /*
1118 * Keep track of pending interrupt status.
1119 */
1120 UNSERIALIZE_SCALAR(intrTick);
1121 UNSERIALIZE_SCALAR(cpuPendingIntr);
1122 Tick intrEventTick;
1123 UNSERIALIZE_SCALAR(intrEventTick);
1124 if (intrEventTick) {
1125 intrEvent = new IntrEvent(this, true);
1126 intrEvent->schedule(intrEventTick);
1127 }
1128 }
1129
1130 void
1131 Device::serialize(ostream &os)
1132 {
1133 // Serialize the PciDev base class
1134 Base::serialize(os);
1135
1136 if (rxDmaEvent.scheduled())
1137 rxDmaCopy();
1138
1139 if (txDmaEvent.scheduled())
1140 txDmaCopy();
1141
1142 /*
1143 * Serialize the device registers
1144 */
1145 SERIALIZE_SCALAR(regs.Config);
1146 SERIALIZE_SCALAR(regs.RxMaxCopy);
1147 SERIALIZE_SCALAR(regs.TxMaxCopy);
1148 SERIALIZE_SCALAR(regs.RxThreshold);
1149 SERIALIZE_SCALAR(regs.TxThreshold);
1150 SERIALIZE_SCALAR(regs.IntrStatus);
1151 SERIALIZE_SCALAR(regs.IntrMask);
1152 SERIALIZE_SCALAR(regs.RxData);
1153 SERIALIZE_SCALAR(regs.RxDone);
1154 SERIALIZE_SCALAR(regs.TxData);
1155 SERIALIZE_SCALAR(regs.TxDone);
1156
1157 /*
1158 * Serialize rx state machine
1159 */
1160 int rxState = this->rxState;
1161 SERIALIZE_SCALAR(rxState);
1162 rxFifo.serialize("rxFifo", os);
1163 bool rxPacketExists = rxPacket;
1164 SERIALIZE_SCALAR(rxPacketExists);
1165 if (rxPacketExists) {
1166 rxPacket->serialize("rxPacket", os);
1167 uint32_t rxPktBufPtr = (uint32_t) (rxPacketBufPtr - rxPacket->data);
1168 SERIALIZE_SCALAR(rxPktBufPtr);
1169 SERIALIZE_SCALAR(rxPktBytes);
1170 }
1171 SERIALIZE_SCALAR(rxDoneData);
1172
1173 /*
1174 * Serialize tx state machine
1175 */
1176 int txState = this->txState;
1177 SERIALIZE_SCALAR(txState);
1178 txFifo.serialize("txFifo", os);
1179 bool txPacketExists = txPacket;
1180 SERIALIZE_SCALAR(txPacketExists);
1181 if (txPacketExists) {
1182 txPacket->serialize("txPacket", os);
1183 uint32_t txPktBufPtr = (uint32_t) (txPacketBufPtr - txPacket->data);
1184 SERIALIZE_SCALAR(txPktBufPtr);
1185 SERIALIZE_SCALAR(txPktBytes);
1186 }
1187
1188 /*
1189 * If there's a pending transmit, store the time so we can
1190 * reschedule it later
1191 */
1192 Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick : 0;
1193 SERIALIZE_SCALAR(transmitTick);
1194 }
1195
1196 void
1197 Device::unserialize(Checkpoint *cp, const std::string &section)
1198 {
1199 // Unserialize the PciDev base class
1200 Base::unserialize(cp, section);
1201
1202 /*
1203 * Unserialize the device registers
1204 */
1205 UNSERIALIZE_SCALAR(regs.Config);
1206 UNSERIALIZE_SCALAR(regs.RxMaxCopy);
1207 UNSERIALIZE_SCALAR(regs.TxMaxCopy);
1208 UNSERIALIZE_SCALAR(regs.RxThreshold);
1209 UNSERIALIZE_SCALAR(regs.TxThreshold);
1210 UNSERIALIZE_SCALAR(regs.IntrStatus);
1211 UNSERIALIZE_SCALAR(regs.IntrMask);
1212 UNSERIALIZE_SCALAR(regs.RxData);
1213 UNSERIALIZE_SCALAR(regs.RxDone);
1214 UNSERIALIZE_SCALAR(regs.TxData);
1215 UNSERIALIZE_SCALAR(regs.TxDone);
1216
1217 /*
1218 * Unserialize rx state machine
1219 */
1220 int rxState;
1221 UNSERIALIZE_SCALAR(rxState);
1222 this->rxState = (RxState) rxState;
1223 rxFifo.unserialize("rxFifo", cp, section);
1224 bool rxPacketExists;
1225 UNSERIALIZE_SCALAR(rxPacketExists);
1226 rxPacket = 0;
1227 if (rxPacketExists) {
1228 rxPacket = new PacketData(16384);
1229 rxPacket->unserialize("rxPacket", cp, section);
1230 uint32_t rxPktBufPtr;
1231 UNSERIALIZE_SCALAR(rxPktBufPtr);
1232 this->rxPacketBufPtr = (uint8_t *) rxPacket->data + rxPktBufPtr;
1233 UNSERIALIZE_SCALAR(rxPktBytes);
1234 }
1235 UNSERIALIZE_SCALAR(rxDoneData);
1236
1237 /*
1238 * Unserialize tx state machine
1239 */
1240 int txState;
1241 UNSERIALIZE_SCALAR(txState);
1242 this->txState = (TxState) txState;
1243 txFifo.unserialize("txFifo", cp, section);
1244 bool txPacketExists;
1245 UNSERIALIZE_SCALAR(txPacketExists);
1246 txPacket = 0;
1247 if (txPacketExists) {
1248 txPacket = new PacketData(16384);
1249 txPacket->unserialize("txPacket", cp, section);
1250 uint32_t txPktBufPtr;
1251 UNSERIALIZE_SCALAR(txPktBufPtr);
1252 this->txPacketBufPtr = (uint8_t *) txPacket->data + txPktBufPtr;
1253 UNSERIALIZE_SCALAR(txPktBytes);
1254 }
1255
1256 /*
1257 * If there's a pending transmit, reschedule it now
1258 */
1259 Tick transmitTick;
1260 UNSERIALIZE_SCALAR(transmitTick);
1261 if (transmitTick)
1262 txEvent.schedule(curTick + transmitTick);
1263
1264 /*
1265 * re-add addrRanges to bus bridges
1266 */
1267 if (pioInterface)
1268 pioInterface->addAddrRange(RangeSize(BARAddrs[0], BARSize[0]));
1269 }
1270
1271 Tick
1272 Device::cacheAccess(MemReqPtr &req)
1273 {
1274 //The mask is to give you only the offset into the device register file
1275 Addr daddr = req->paddr - addr;
1276
1277 DPRINTF(EthernetPIO, "timing access to paddr=%#x (daddr=%#x)\n",
1278 req->paddr, daddr);
1279
1280 Tick when = curTick + pioLatency;
1281
1282 switch (daddr) {
1283 case Regs::RxDone:
1284 if (rxState != rxIdle) {
1285 rxPioRequest = req;
1286 when = 0;
1287 }
1288 break;
1289
1290 case Regs::TxDone:
1291 if (txState != txIdle) {
1292 txPioRequest = req;
1293 when = 0;
1294 }
1295 break;
1296 }
1297
1298 return when;
1299 }
1300
1301 BEGIN_DECLARE_SIM_OBJECT_PARAMS(Interface)
1302
1303 SimObjectParam<EtherInt *> peer;
1304 SimObjectParam<Device *> device;
1305
1306 END_DECLARE_SIM_OBJECT_PARAMS(Interface)
1307
1308 BEGIN_INIT_SIM_OBJECT_PARAMS(Interface)
1309
1310 INIT_PARAM_DFLT(peer, "peer interface", NULL),
1311 INIT_PARAM(device, "Ethernet device of this interface")
1312
1313 END_INIT_SIM_OBJECT_PARAMS(Interface)
1314
1315 CREATE_SIM_OBJECT(Interface)
1316 {
1317 Interface *dev_int = new Interface(getInstanceName(), device);
1318
1319 EtherInt *p = (EtherInt *)peer;
1320 if (p) {
1321 dev_int->setPeer(p);
1322 p->setPeer(dev_int);
1323 }
1324
1325 return dev_int;
1326 }
1327
1328 REGISTER_SIM_OBJECT("SinicInt", Interface)
1329
1330
1331 BEGIN_DECLARE_SIM_OBJECT_PARAMS(Device)
1332
1333 Param<Tick> tx_delay;
1334 Param<Tick> rx_delay;
1335 Param<Tick> intr_delay;
1336 SimObjectParam<MemoryController *> mmu;
1337 SimObjectParam<PhysicalMemory *> physmem;
1338 Param<bool> rx_filter;
1339 Param<string> hardware_address;
1340 SimObjectParam<Bus*> header_bus;
1341 SimObjectParam<Bus*> payload_bus;
1342 SimObjectParam<HierParams *> hier;
1343 Param<Tick> pio_latency;
1344 SimObjectParam<PciConfigAll *> configspace;
1345 SimObjectParam<PciConfigData *> configdata;
1346 SimObjectParam<Platform *> platform;
1347 Param<uint32_t> pci_bus;
1348 Param<uint32_t> pci_dev;
1349 Param<uint32_t> pci_func;
1350 Param<uint32_t> rx_max_copy;
1351 Param<uint32_t> tx_max_copy;
1352 Param<uint32_t> rx_fifo_size;
1353 Param<uint32_t> tx_fifo_size;
1354 Param<uint32_t> rx_fifo_threshold;
1355 Param<uint32_t> tx_fifo_threshold;
1356 Param<Tick> dma_read_delay;
1357 Param<Tick> dma_read_factor;
1358 Param<Tick> dma_write_delay;
1359 Param<Tick> dma_write_factor;
1360
1361 END_DECLARE_SIM_OBJECT_PARAMS(Device)
1362
1363 BEGIN_INIT_SIM_OBJECT_PARAMS(Device)
1364
1365 INIT_PARAM_DFLT(tx_delay, "Transmit Delay", 1000),
1366 INIT_PARAM_DFLT(rx_delay, "Receive Delay", 1000),
1367 INIT_PARAM_DFLT(intr_delay, "Interrupt Delay in microseconds", 0),
1368 INIT_PARAM(mmu, "Memory Controller"),
1369 INIT_PARAM(physmem, "Physical Memory"),
1370 INIT_PARAM_DFLT(rx_filter, "Enable Receive Filter", true),
1371 INIT_PARAM_DFLT(hardware_address, "Ethernet Hardware Address",
1372 "00:99:00:00:00:01"),
1373 INIT_PARAM_DFLT(header_bus, "The IO Bus to attach to for headers", NULL),
1374 INIT_PARAM_DFLT(payload_bus, "The IO Bus to attach to for payload", NULL),
1375 INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams),
1376 INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1),
1377 INIT_PARAM(configspace, "PCI Configspace"),
1378 INIT_PARAM(configdata, "PCI Config data"),
1379 INIT_PARAM(platform, "Platform"),
1380 INIT_PARAM(pci_bus, "PCI bus"),
1381 INIT_PARAM(pci_dev, "PCI device number"),
1382 INIT_PARAM(pci_func, "PCI function code"),
1383 INIT_PARAM_DFLT(rx_max_copy, "rx max copy", 16*1024),
1384 INIT_PARAM_DFLT(tx_max_copy, "rx max copy", 16*1024),
1385 INIT_PARAM_DFLT(rx_fifo_size, "max size in bytes of rxFifo", 64*1024),
1386 INIT_PARAM_DFLT(tx_fifo_size, "max size in bytes of txFifo", 64*1024),
1387 INIT_PARAM_DFLT(rx_fifo_threshold, "max size in bytes of rxFifo", 48*1024),
1388 INIT_PARAM_DFLT(tx_fifo_threshold, "max size in bytes of txFifo", 16*1024),
1389 INIT_PARAM_DFLT(dma_read_delay, "fixed delay for dma reads", 0),
1390 INIT_PARAM_DFLT(dma_read_factor, "multiplier for dma reads", 0),
1391 INIT_PARAM_DFLT(dma_write_delay, "fixed delay for dma writes", 0),
1392 INIT_PARAM_DFLT(dma_write_factor, "multiplier for dma writes", 0)
1393
1394 END_INIT_SIM_OBJECT_PARAMS(Device)
1395
1396
1397 CREATE_SIM_OBJECT(Device)
1398 {
1399 Device::Params *params = new Device::Params;
1400 params->name = getInstanceName();
1401 params->intr_delay = intr_delay;
1402 params->physmem = physmem;
1403 params->tx_delay = tx_delay;
1404 params->rx_delay = rx_delay;
1405 params->mmu = mmu;
1406 params->hier = hier;
1407 params->header_bus = header_bus;
1408 params->payload_bus = payload_bus;
1409 params->pio_latency = pio_latency;
1410 params->configSpace = configspace;
1411 params->configData = configdata;
1412 params->plat = platform;
1413 params->busNum = pci_bus;
1414 params->deviceNum = pci_dev;
1415 params->functionNum = pci_func;
1416 params->rx_filter = rx_filter;
1417 params->eaddr = hardware_address;
1418 params->rx_max_copy = rx_max_copy;
1419 params->tx_max_copy = tx_max_copy;
1420 params->rx_fifo_size = rx_fifo_size;
1421 params->tx_fifo_size = tx_fifo_size;
1422 params->rx_fifo_threshold = rx_fifo_threshold;
1423 params->tx_fifo_threshold = tx_fifo_threshold;
1424 params->dma_read_delay = dma_read_delay;
1425 params->dma_read_factor = dma_read_factor;
1426 params->dma_write_delay = dma_write_delay;
1427 params->dma_write_factor = dma_write_factor;
1428 return new Device(params);
1429 }
1430
1431 REGISTER_SIM_OBJECT("Sinic", Device)
1432
1433 /* namespace Sinic */ }