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