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