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