Merge ktlim@zizzer:/bk/newmem
[gem5.git] / src / 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 * Authors: Nathan Binkert
29 */
30
31 #include <deque>
32 #include <limits>
33 #include <string>
34
35 #include "base/inet.hh"
36 #include "cpu/thread_context.hh"
37 #include "cpu/intr_control.hh"
38 #include "dev/etherlink.hh"
39 #include "dev/sinic.hh"
40 #include "mem/packet.hh"
41 #include "sim/builder.hh"
42 #include "sim/debug.hh"
43 #include "sim/eventq.hh"
44 #include "sim/host.hh"
45 #include "sim/stats.hh"
46 #include "arch/vtophys.hh"
47
48 using namespace Net;
49 using namespace TheISA;
50
51 namespace Sinic {
52
53 const char *RxStateStrings[] =
54 {
55 "rxIdle",
56 "rxFifoBlock",
57 "rxBeginCopy",
58 "rxCopy",
59 "rxCopyDone"
60 };
61
62 const char *TxStateStrings[] =
63 {
64 "txIdle",
65 "txFifoBlock",
66 "txBeginCopy",
67 "txCopy",
68 "txCopyDone"
69 };
70
71
72 ///////////////////////////////////////////////////////////////////////
73 //
74 // Sinic PCI Device
75 //
76 Base::Base(Params *p)
77 : PciDev(p), rxEnable(false), txEnable(false), clock(p->clock),
78 intrDelay(p->intr_delay), intrTick(0), cpuIntrEnable(false),
79 cpuPendingIntr(false), intrEvent(0), interface(NULL)
80 {
81 }
82
83 Device::Device(Params *p)
84 : Base(p), rxUnique(0), txUnique(0),
85 virtualRegs(p->virtual_count < 1 ? 1 : p->virtual_count),
86 rxFifo(p->rx_fifo_size), txFifo(p->tx_fifo_size),
87 rxKickTick(0), txKickTick(0),
88 txEvent(this), rxDmaEvent(this), txDmaEvent(this),
89 dmaReadDelay(p->dma_read_delay), dmaReadFactor(p->dma_read_factor),
90 dmaWriteDelay(p->dma_write_delay), dmaWriteFactor(p->dma_write_factor)
91 {
92 reset();
93
94 }
95
96 Device::~Device()
97 {}
98
99 void
100 Device::regStats()
101 {
102 rxBytes
103 .name(name() + ".rxBytes")
104 .desc("Bytes Received")
105 .prereq(rxBytes)
106 ;
107
108 rxBandwidth
109 .name(name() + ".rxBandwidth")
110 .desc("Receive Bandwidth (bits/s)")
111 .precision(0)
112 .prereq(rxBytes)
113 ;
114
115 rxPackets
116 .name(name() + ".rxPackets")
117 .desc("Number of Packets Received")
118 .prereq(rxBytes)
119 ;
120
121 rxPacketRate
122 .name(name() + ".rxPPS")
123 .desc("Packet Reception Rate (packets/s)")
124 .precision(0)
125 .prereq(rxBytes)
126 ;
127
128 rxIpPackets
129 .name(name() + ".rxIpPackets")
130 .desc("Number of IP Packets Received")
131 .prereq(rxBytes)
132 ;
133
134 rxTcpPackets
135 .name(name() + ".rxTcpPackets")
136 .desc("Number of Packets Received")
137 .prereq(rxBytes)
138 ;
139
140 rxUdpPackets
141 .name(name() + ".rxUdpPackets")
142 .desc("Number of UDP Packets Received")
143 .prereq(rxBytes)
144 ;
145
146 rxIpChecksums
147 .name(name() + ".rxIpChecksums")
148 .desc("Number of rx IP Checksums done by device")
149 .precision(0)
150 .prereq(rxBytes)
151 ;
152
153 rxTcpChecksums
154 .name(name() + ".rxTcpChecksums")
155 .desc("Number of rx TCP Checksums done by device")
156 .precision(0)
157 .prereq(rxBytes)
158 ;
159
160 rxUdpChecksums
161 .name(name() + ".rxUdpChecksums")
162 .desc("Number of rx UDP Checksums done by device")
163 .precision(0)
164 .prereq(rxBytes)
165 ;
166
167 totBandwidth
168 .name(name() + ".totBandwidth")
169 .desc("Total Bandwidth (bits/s)")
170 .precision(0)
171 .prereq(totBytes)
172 ;
173
174 totPackets
175 .name(name() + ".totPackets")
176 .desc("Total Packets")
177 .precision(0)
178 .prereq(totBytes)
179 ;
180
181 totBytes
182 .name(name() + ".totBytes")
183 .desc("Total Bytes")
184 .precision(0)
185 .prereq(totBytes)
186 ;
187
188 totPacketRate
189 .name(name() + ".totPPS")
190 .desc("Total Tranmission Rate (packets/s)")
191 .precision(0)
192 .prereq(totBytes)
193 ;
194
195 txBytes
196 .name(name() + ".txBytes")
197 .desc("Bytes Transmitted")
198 .prereq(txBytes)
199 ;
200
201 txBandwidth
202 .name(name() + ".txBandwidth")
203 .desc("Transmit Bandwidth (bits/s)")
204 .precision(0)
205 .prereq(txBytes)
206 ;
207
208 txPackets
209 .name(name() + ".txPackets")
210 .desc("Number of Packets Transmitted")
211 .prereq(txBytes)
212 ;
213
214 txPacketRate
215 .name(name() + ".txPPS")
216 .desc("Packet Tranmission Rate (packets/s)")
217 .precision(0)
218 .prereq(txBytes)
219 ;
220
221 txIpPackets
222 .name(name() + ".txIpPackets")
223 .desc("Number of IP Packets Transmitted")
224 .prereq(txBytes)
225 ;
226
227 txTcpPackets
228 .name(name() + ".txTcpPackets")
229 .desc("Number of TCP Packets Transmitted")
230 .prereq(txBytes)
231 ;
232
233 txUdpPackets
234 .name(name() + ".txUdpPackets")
235 .desc("Number of Packets Transmitted")
236 .prereq(txBytes)
237 ;
238
239 txIpChecksums
240 .name(name() + ".txIpChecksums")
241 .desc("Number of tx IP Checksums done by device")
242 .precision(0)
243 .prereq(txBytes)
244 ;
245
246 txTcpChecksums
247 .name(name() + ".txTcpChecksums")
248 .desc("Number of tx TCP Checksums done by device")
249 .precision(0)
250 .prereq(txBytes)
251 ;
252
253 txUdpChecksums
254 .name(name() + ".txUdpChecksums")
255 .desc("Number of tx UDP Checksums done by device")
256 .precision(0)
257 .prereq(txBytes)
258 ;
259
260 txBandwidth = txBytes * Stats::constant(8) / simSeconds;
261 rxBandwidth = rxBytes * Stats::constant(8) / simSeconds;
262 totBandwidth = txBandwidth + rxBandwidth;
263 totBytes = txBytes + rxBytes;
264 totPackets = txPackets + rxPackets;
265 txPacketRate = txPackets / simSeconds;
266 rxPacketRate = rxPackets / simSeconds;
267 }
268
269 void
270 Device::prepareIO(int cpu, int index)
271 {
272 int size = virtualRegs.size();
273 if (index > size)
274 panic("Trying to access a vnic that doesn't exist %d > %d\n",
275 index, size);
276 }
277
278 void
279 Device::prepareRead(int cpu, int index)
280 {
281 using namespace Regs;
282 prepareIO(cpu, index);
283
284 VirtualReg &vnic = virtualRegs[index];
285
286 // update rx registers
287 uint64_t rxdone = vnic.RxDone;
288 rxdone = set_RxDone_Packets(rxdone, rxFifo.countPacketsAfter(rxFifoPtr));
289 rxdone = set_RxDone_Empty(rxdone, rxFifo.empty());
290 rxdone = set_RxDone_High(rxdone, rxFifo.size() > regs.RxFifoMark);
291 rxdone = set_RxDone_NotHigh(rxdone, rxLow);
292 regs.RxData = vnic.RxData;
293 regs.RxDone = rxdone;
294 regs.RxWait = rxdone;
295
296 // update tx regsiters
297 uint64_t txdone = vnic.TxDone;
298 txdone = set_TxDone_Packets(txdone, txFifo.packets());
299 txdone = set_TxDone_Full(txdone, txFifo.avail() < regs.TxMaxCopy);
300 txdone = set_TxDone_Low(txdone, txFifo.size() < regs.TxFifoMark);
301 regs.TxData = vnic.TxData;
302 regs.TxDone = txdone;
303 regs.TxWait = txdone;
304 }
305
306 void
307 Device::prepareWrite(int cpu, int index)
308 {
309 prepareIO(cpu, index);
310 }
311
312 /**
313 * I/O read of device register
314 */
315 Tick
316 Device::read(Packet *pkt)
317 {
318 assert(config.command & PCI_CMD_MSE);
319 assert(pkt->getAddr() >= BARAddrs[0] && pkt->getSize() < BARSize[0]);
320
321 int cpu = pkt->req->getCpuNum();
322 Addr daddr = pkt->getAddr() - BARAddrs[0];
323 Addr index = daddr >> Regs::VirtualShift;
324 Addr raddr = daddr & Regs::VirtualMask;
325
326 pkt->allocate();
327
328 if (!regValid(raddr))
329 panic("invalid register: cpu=%d vnic=%d da=%#x pa=%#x size=%d",
330 cpu, index, daddr, pkt->getAddr(), pkt->getSize());
331
332 const Regs::Info &info = regInfo(raddr);
333 if (!info.read)
334 panic("read %s (write only): "
335 "cpu=%d vnic=%d da=%#x pa=%#x size=%d",
336 info.name, cpu, index, daddr, pkt->getAddr(), pkt->getSize());
337
338 panic("read %s (invalid size): "
339 "cpu=%d vnic=%d da=%#x pa=%#x size=%d",
340 info.name, cpu, index, daddr, pkt->getAddr(), pkt->getSize());
341
342 prepareRead(cpu, index);
343
344 uint64_t value = 0;
345 if (pkt->getSize() == 4) {
346 uint32_t reg = regData32(raddr);
347 pkt->set(reg);
348 value = reg;
349 }
350
351 if (pkt->getSize() == 8) {
352 uint64_t reg = regData64(raddr);
353 pkt->set(reg);
354 value = reg;
355 }
356
357 DPRINTF(EthernetPIO,
358 "read %s: cpu=%d vnic=%d da=%#x pa=%#x size=%d val=%#x\n",
359 info.name, cpu, index, daddr, pkt->getAddr(), pkt->getSize(), value);
360
361 // reading the interrupt status register has the side effect of
362 // clearing it
363 if (raddr == Regs::IntrStatus)
364 devIntrClear();
365
366 return pioDelay;
367 }
368
369 /**
370 * IPR read of device register
371
372 Fault
373 Device::iprRead(Addr daddr, int cpu, uint64_t &result)
374 {
375 if (!regValid(daddr))
376 panic("invalid address: da=%#x", daddr);
377
378 const Regs::Info &info = regInfo(daddr);
379 if (!info.read)
380 panic("reading %s (write only): cpu=%d da=%#x", info.name, cpu, daddr);
381
382 DPRINTF(EthernetPIO, "IPR read %s: cpu=%d da=%#x\n",
383 info.name, cpu, daddr);
384
385 prepareRead(cpu, 0);
386
387 if (info.size == 4)
388 result = regData32(daddr);
389
390 if (info.size == 8)
391 result = regData64(daddr);
392
393 DPRINTF(EthernetPIO, "IPR read %s: cpu=%s da=%#x val=%#x\n",
394 info.name, cpu, result);
395
396 return NoFault;
397 }
398 */
399 /**
400 * I/O write of device register
401 */
402 Tick
403 Device::write(Packet *pkt)
404 {
405 assert(config.command & PCI_CMD_MSE);
406 assert(pkt->getAddr() >= BARAddrs[0] && pkt->getSize() < BARSize[0]);
407
408 int cpu = pkt->req->getCpuNum();
409 Addr daddr = pkt->getAddr() - BARAddrs[0];
410 Addr index = daddr >> Regs::VirtualShift;
411 Addr raddr = daddr & Regs::VirtualMask;
412
413 if (!regValid(raddr))
414 panic("invalid register: cpu=%d, da=%#x pa=%#x size=%d",
415 cpu, daddr, pkt->getAddr(), pkt->getSize());
416
417 const Regs::Info &info = regInfo(raddr);
418 if (!info.write)
419 panic("write %s (read only): "
420 "cpu=%d vnic=%d da=%#x pa=%#x size=%d",
421 info.name, cpu, index, daddr, pkt->getAddr(), pkt->getSize());
422
423 if (pkt->getSize() != info.size)
424 panic("write %s (invalid size): "
425 "cpu=%d vnic=%d da=%#x pa=%#x size=%d",
426 info.name, cpu, index, daddr, pkt->getAddr(), pkt->getSize());
427
428 VirtualReg &vnic = virtualRegs[index];
429
430 DPRINTF(EthernetPIO,
431 "write %s vnic %d: cpu=%d val=%#x da=%#x pa=%#x size=%d\n",
432 info.name, index, cpu, info.size == 4 ? pkt->get<uint32_t>() :
433 pkt->get<uint64_t>(), daddr, pkt->getAddr(), pkt->getSize());
434
435 prepareWrite(cpu, index);
436
437 switch (raddr) {
438 case Regs::Config:
439 changeConfig(pkt->get<uint32_t>());
440 break;
441
442 case Regs::Command:
443 command(pkt->get<uint32_t>());
444 break;
445
446 case Regs::IntrStatus:
447 devIntrClear(regs.IntrStatus & pkt->get<uint32_t>());
448 break;
449
450 case Regs::IntrMask:
451 devIntrChangeMask(pkt->get<uint32_t>());
452 break;
453
454 case Regs::RxData:
455 if (Regs::get_RxDone_Busy(vnic.RxDone))
456 panic("receive machine busy with another request! rxState=%s",
457 RxStateStrings[rxState]);
458
459 vnic.rxUnique = rxUnique++;
460 vnic.RxDone = Regs::RxDone_Busy;
461 vnic.RxData = pkt->get<uint64_t>();
462
463 if (Regs::get_RxData_Vaddr(pkt->get<uint64_t>())) {
464 panic("vtophys not implemented in newmem");
465 /* Addr vaddr = Regs::get_RxData_Addr(reg64);
466 Addr paddr = vtophys(req->xc, vaddr);
467 DPRINTF(EthernetPIO, "write RxData vnic %d (rxunique %d): "
468 "vaddr=%#x, paddr=%#x\n",
469 index, vnic.rxUnique, vaddr, paddr);
470
471 vnic.RxData = Regs::set_RxData_Addr(vnic.RxData, paddr);*/
472 } else {
473 DPRINTF(EthernetPIO, "write RxData vnic %d (rxunique %d)\n",
474 index, vnic.rxUnique);
475 }
476
477 if (vnic.rxPacket == rxFifo.end()) {
478 DPRINTF(EthernetPIO, "request new packet...appending to rxList\n");
479 rxList.push_back(index);
480 } else {
481 DPRINTF(EthernetPIO, "packet exists...appending to rxBusy\n");
482 rxBusy.push_back(index);
483 }
484
485 if (rxEnable && (rxState == rxIdle || rxState == rxFifoBlock)) {
486 rxState = rxFifoBlock;
487 rxKick();
488 }
489 break;
490
491 case Regs::TxData:
492 if (Regs::get_TxDone_Busy(vnic.TxDone))
493 panic("transmit machine busy with another request! txState=%s",
494 TxStateStrings[txState]);
495
496 vnic.txUnique = txUnique++;
497 vnic.TxDone = Regs::TxDone_Busy;
498
499 if (Regs::get_TxData_Vaddr(pkt->get<uint64_t>())) {
500 panic("vtophys won't work here in newmem.\n");
501 /*Addr vaddr = Regs::get_TxData_Addr(reg64);
502 Addr paddr = vtophys(req->xc, vaddr);
503 DPRINTF(EthernetPIO, "write TxData vnic %d (rxunique %d): "
504 "vaddr=%#x, paddr=%#x\n",
505 index, vnic.txUnique, vaddr, paddr);
506
507 vnic.TxData = Regs::set_TxData_Addr(vnic.TxData, paddr);*/
508 } else {
509 DPRINTF(EthernetPIO, "write TxData vnic %d (rxunique %d)\n",
510 index, vnic.txUnique);
511 }
512
513 if (txList.empty() || txList.front() != index)
514 txList.push_back(index);
515 if (txEnable && txState == txIdle && txList.front() == index) {
516 txState = txFifoBlock;
517 txKick();
518 }
519 break;
520 }
521
522 return pioDelay;
523 }
524
525 void
526 Device::devIntrPost(uint32_t interrupts)
527 {
528 if ((interrupts & Regs::Intr_Res))
529 panic("Cannot set a reserved interrupt");
530
531 regs.IntrStatus |= interrupts;
532
533 DPRINTF(EthernetIntr,
534 "interrupt written to intStatus: intr=%#x status=%#x mask=%#x\n",
535 interrupts, regs.IntrStatus, regs.IntrMask);
536
537 interrupts = regs.IntrStatus & regs.IntrMask;
538
539 // Intr_RxHigh is special, we only signal it if we've emptied the fifo
540 // and then filled it above the high watermark
541 if (rxEmpty)
542 rxEmpty = false;
543 else
544 interrupts &= ~Regs::Intr_RxHigh;
545
546 // Intr_TxLow is special, we only signal it if we've filled up the fifo
547 // and then dropped below the low watermark
548 if (txFull)
549 txFull = false;
550 else
551 interrupts &= ~Regs::Intr_TxLow;
552
553 if (interrupts) {
554 Tick when = curTick;
555 if ((interrupts & Regs::Intr_NoDelay) == 0)
556 when += intrDelay;
557 cpuIntrPost(when);
558 }
559 }
560
561 void
562 Device::devIntrClear(uint32_t interrupts)
563 {
564 if ((interrupts & Regs::Intr_Res))
565 panic("Cannot clear a reserved interrupt");
566
567 regs.IntrStatus &= ~interrupts;
568
569 DPRINTF(EthernetIntr,
570 "interrupt cleared from intStatus: intr=%x status=%x mask=%x\n",
571 interrupts, regs.IntrStatus, regs.IntrMask);
572
573 if (!(regs.IntrStatus & regs.IntrMask))
574 cpuIntrClear();
575 }
576
577 void
578 Device::devIntrChangeMask(uint32_t newmask)
579 {
580 if (regs.IntrMask == newmask)
581 return;
582
583 regs.IntrMask = newmask;
584
585 DPRINTF(EthernetIntr,
586 "interrupt mask changed: intStatus=%x intMask=%x masked=%x\n",
587 regs.IntrStatus, regs.IntrMask, regs.IntrStatus & regs.IntrMask);
588
589 if (regs.IntrStatus & regs.IntrMask)
590 cpuIntrPost(curTick);
591 else
592 cpuIntrClear();
593 }
594
595 void
596 Base::cpuIntrPost(Tick when)
597 {
598 // If the interrupt you want to post is later than an interrupt
599 // already scheduled, just let it post in the coming one and don't
600 // schedule another.
601 // HOWEVER, must be sure that the scheduled intrTick is in the
602 // future (this was formerly the source of a bug)
603 /**
604 * @todo this warning should be removed and the intrTick code should
605 * be fixed.
606 */
607 assert(when >= curTick);
608 assert(intrTick >= curTick || intrTick == 0);
609 if (!cpuIntrEnable) {
610 DPRINTF(EthernetIntr, "interrupts not enabled.\n",
611 intrTick);
612 return;
613 }
614
615 if (when > intrTick && intrTick != 0) {
616 DPRINTF(EthernetIntr, "don't need to schedule event...intrTick=%d\n",
617 intrTick);
618 return;
619 }
620
621 intrTick = when;
622 if (intrTick < curTick) {
623 debug_break();
624 intrTick = curTick;
625 }
626
627 DPRINTF(EthernetIntr, "going to schedule an interrupt for intrTick=%d\n",
628 intrTick);
629
630 if (intrEvent)
631 intrEvent->squash();
632 intrEvent = new IntrEvent(this, true);
633 intrEvent->schedule(intrTick);
634 }
635
636 void
637 Base::cpuInterrupt()
638 {
639 assert(intrTick == curTick);
640
641 // Whether or not there's a pending interrupt, we don't care about
642 // it anymore
643 intrEvent = 0;
644 intrTick = 0;
645
646 // Don't send an interrupt if there's already one
647 if (cpuPendingIntr) {
648 DPRINTF(EthernetIntr,
649 "would send an interrupt now, but there's already pending\n");
650 } else {
651 // Send interrupt
652 cpuPendingIntr = true;
653
654 DPRINTF(EthernetIntr, "posting interrupt\n");
655 intrPost();
656 }
657 }
658
659 void
660 Base::cpuIntrClear()
661 {
662 if (!cpuPendingIntr)
663 return;
664
665 if (intrEvent) {
666 intrEvent->squash();
667 intrEvent = 0;
668 }
669
670 intrTick = 0;
671
672 cpuPendingIntr = false;
673
674 DPRINTF(EthernetIntr, "clearing cchip interrupt\n");
675 intrClear();
676 }
677
678 bool
679 Base::cpuIntrPending() const
680 { return cpuPendingIntr; }
681
682 void
683 Device::changeConfig(uint32_t newconf)
684 {
685 uint32_t changed = regs.Config ^ newconf;
686 if (!changed)
687 return;
688
689 regs.Config = newconf;
690
691 if ((changed & Regs::Config_IntEn)) {
692 cpuIntrEnable = regs.Config & Regs::Config_IntEn;
693 if (cpuIntrEnable) {
694 if (regs.IntrStatus & regs.IntrMask)
695 cpuIntrPost(curTick);
696 } else {
697 cpuIntrClear();
698 }
699 }
700
701 if ((changed & Regs::Config_TxEn)) {
702 txEnable = regs.Config & Regs::Config_TxEn;
703 if (txEnable)
704 txKick();
705 }
706
707 if ((changed & Regs::Config_RxEn)) {
708 rxEnable = regs.Config & Regs::Config_RxEn;
709 if (rxEnable)
710 rxKick();
711 }
712 }
713
714 void
715 Device::command(uint32_t command)
716 {
717 if (command & Regs::Command_Intr)
718 devIntrPost(Regs::Intr_Soft);
719
720 if (command & Regs::Command_Reset)
721 reset();
722 }
723
724 void
725 Device::reset()
726 {
727 using namespace Regs;
728
729 memset(&regs, 0, sizeof(regs));
730
731 regs.Config = 0;
732 if (params()->rx_thread)
733 regs.Config |= Config_RxThread;
734 if (params()->tx_thread)
735 regs.Config |= Config_TxThread;
736 if (params()->rss)
737 regs.Config |= Config_RSS;
738 if (params()->zero_copy)
739 regs.Config |= Config_ZeroCopy;
740 if (params()->delay_copy)
741 regs.Config |= Config_DelayCopy;
742 if (params()->virtual_addr)
743 regs.Config |= Config_Vaddr;
744
745 if (params()->delay_copy && params()->zero_copy)
746 panic("Can't delay copy and zero copy");
747
748 regs.IntrMask = Intr_Soft | Intr_RxHigh | Intr_RxPacket | Intr_TxLow;
749 regs.RxMaxCopy = params()->rx_max_copy;
750 regs.TxMaxCopy = params()->tx_max_copy;
751 regs.RxMaxIntr = params()->rx_max_intr;
752 regs.VirtualCount = params()->virtual_count;
753 regs.RxFifoSize = params()->rx_fifo_size;
754 regs.TxFifoSize = params()->tx_fifo_size;
755 regs.RxFifoMark = params()->rx_fifo_threshold;
756 regs.TxFifoMark = params()->tx_fifo_threshold;
757 regs.HwAddr = params()->eaddr;
758
759 rxList.clear();
760 rxBusy.clear();
761 rxActive = -1;
762 txList.clear();
763
764 rxState = rxIdle;
765 txState = txIdle;
766
767 rxFifo.clear();
768 rxFifoPtr = rxFifo.end();
769 txFifo.clear();
770 rxEmpty = false;
771 rxLow = true;
772 txFull = false;
773
774 int size = virtualRegs.size();
775 virtualRegs.clear();
776 virtualRegs.resize(size);
777 for (int i = 0; i < size; ++i)
778 virtualRegs[i].rxPacket = rxFifo.end();
779 }
780
781 void
782 Device::rxDmaDone()
783 {
784 assert(rxState == rxCopy);
785 rxState = rxCopyDone;
786 DPRINTF(EthernetDMA, "end rx dma write paddr=%#x len=%d\n",
787 rxDmaAddr, rxDmaLen);
788 DDUMP(EthernetData, rxDmaData, rxDmaLen);
789
790 // If the transmit state machine has a pending DMA, let it go first
791 if (txState == txBeginCopy)
792 txKick();
793
794 rxKick();
795 }
796
797 void
798 Device::rxKick()
799 {
800 VirtualReg *vnic = NULL;
801
802 DPRINTF(EthernetSM, "rxKick: rxState=%s (rxFifo.size=%d)\n",
803 RxStateStrings[rxState], rxFifo.size());
804
805 if (rxKickTick > curTick) {
806 DPRINTF(EthernetSM, "rxKick: exiting, can't run till %d\n",
807 rxKickTick);
808 return;
809 }
810
811 next:
812 if (rxState == rxIdle)
813 goto exit;
814
815 if (rxActive == -1) {
816 if (rxState != rxFifoBlock)
817 panic("no active vnic while in state %s", RxStateStrings[rxState]);
818
819 DPRINTF(EthernetSM, "processing rxState=%s\n",
820 RxStateStrings[rxState]);
821 } else {
822 vnic = &virtualRegs[rxActive];
823 DPRINTF(EthernetSM,
824 "processing rxState=%s for vnic %d (rxunique %d)\n",
825 RxStateStrings[rxState], rxActive, vnic->rxUnique);
826 }
827
828 switch (rxState) {
829 case rxFifoBlock:
830 if (DTRACE(EthernetSM)) {
831 PacketFifo::iterator end = rxFifo.end();
832 int size = virtualRegs.size();
833 for (int i = 0; i < size; ++i) {
834 VirtualReg *vn = &virtualRegs[i];
835 if (vn->rxPacket != end &&
836 !Regs::get_RxDone_Busy(vn->RxDone)) {
837 DPRINTF(EthernetSM,
838 "vnic %d (rxunique %d), has outstanding packet %d\n",
839 i, vn->rxUnique,
840 rxFifo.countPacketsBefore(vn->rxPacket));
841 }
842 }
843 }
844
845 if (!rxBusy.empty()) {
846 rxActive = rxBusy.front();
847 rxBusy.pop_front();
848 vnic = &virtualRegs[rxActive];
849
850 if (vnic->rxPacket == rxFifo.end())
851 panic("continuing vnic without packet\n");
852
853 DPRINTF(EthernetSM,
854 "continue processing for vnic %d (rxunique %d)\n",
855 rxActive, vnic->rxUnique);
856
857 rxState = rxBeginCopy;
858
859 break;
860 }
861
862 if (rxFifoPtr == rxFifo.end()) {
863 DPRINTF(EthernetSM, "receive waiting for data. Nothing to do.\n");
864 goto exit;
865 }
866
867 if (rxList.empty())
868 panic("Not idle, but nothing to do!");
869
870 assert(!rxFifo.empty());
871
872 rxActive = rxList.front();
873 rxList.pop_front();
874 vnic = &virtualRegs[rxActive];
875
876 DPRINTF(EthernetSM,
877 "processing new packet for vnic %d (rxunique %d)\n",
878 rxActive, vnic->rxUnique);
879
880 // Grab a new packet from the fifo.
881 vnic->rxPacket = rxFifoPtr++;
882 vnic->rxPacketOffset = 0;
883 vnic->rxPacketBytes = (*vnic->rxPacket)->length;
884 assert(vnic->rxPacketBytes);
885
886 vnic->rxDoneData = 0;
887 /* scope for variables */ {
888 IpPtr ip(*vnic->rxPacket);
889 if (ip) {
890 DPRINTF(Ethernet, "ID is %d\n", ip->id());
891 vnic->rxDoneData |= Regs::RxDone_IpPacket;
892 rxIpChecksums++;
893 if (cksum(ip) != 0) {
894 DPRINTF(EthernetCksum, "Rx IP Checksum Error\n");
895 vnic->rxDoneData |= Regs::RxDone_IpError;
896 }
897 TcpPtr tcp(ip);
898 UdpPtr udp(ip);
899 if (tcp) {
900 DPRINTF(Ethernet,
901 "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
902 tcp->sport(), tcp->dport(), tcp->seq(),
903 tcp->ack());
904 vnic->rxDoneData |= Regs::RxDone_TcpPacket;
905 rxTcpChecksums++;
906 if (cksum(tcp) != 0) {
907 DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n");
908 vnic->rxDoneData |= Regs::RxDone_TcpError;
909 }
910 } else if (udp) {
911 vnic->rxDoneData |= Regs::RxDone_UdpPacket;
912 rxUdpChecksums++;
913 if (cksum(udp) != 0) {
914 DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n");
915 vnic->rxDoneData |= Regs::RxDone_UdpError;
916 }
917 }
918 }
919 }
920 rxState = rxBeginCopy;
921 break;
922
923 case rxBeginCopy:
924 if (dmaPending())
925 goto exit;
926
927 rxDmaAddr = params()->platform->pciToDma(
928 Regs::get_RxData_Addr(vnic->RxData));
929 rxDmaLen = std::min<int>(Regs::get_RxData_Len(vnic->RxData),
930 vnic->rxPacketBytes);
931 rxDmaData = (*vnic->rxPacket)->data + vnic->rxPacketOffset;
932 rxState = rxCopy;
933 if (rxDmaAddr == 1LL) {
934 rxState = rxCopyDone;
935 break;
936 }
937
938
939 dmaWrite(rxDmaAddr, rxDmaLen, &rxDmaEvent, rxDmaData);
940 break;
941
942 case rxCopy:
943 DPRINTF(EthernetSM, "receive machine still copying\n");
944 goto exit;
945
946 case rxCopyDone:
947 vnic->RxDone = vnic->rxDoneData;
948 vnic->RxDone |= Regs::RxDone_Complete;
949
950 if (vnic->rxPacketBytes == rxDmaLen) {
951 // Packet is complete. Indicate how many bytes were copied
952 vnic->RxDone = Regs::set_RxDone_CopyLen(vnic->RxDone, rxDmaLen);
953
954 DPRINTF(EthernetSM,
955 "rxKick: packet complete on vnic %d (rxunique %d)\n",
956 rxActive, vnic->rxUnique);
957 rxFifo.remove(vnic->rxPacket);
958 vnic->rxPacket = rxFifo.end();
959 } else {
960 vnic->rxPacketBytes -= rxDmaLen;
961 vnic->rxPacketOffset += rxDmaLen;
962 vnic->RxDone |= Regs::RxDone_More;
963 vnic->RxDone = Regs::set_RxDone_CopyLen(vnic->RxDone,
964 vnic->rxPacketBytes);
965 DPRINTF(EthernetSM,
966 "rxKick: packet not complete on vnic %d (rxunique %d): "
967 "%d bytes left\n",
968 rxActive, vnic->rxUnique, vnic->rxPacketBytes);
969 }
970
971 rxActive = -1;
972 rxState = rxBusy.empty() && rxList.empty() ? rxIdle : rxFifoBlock;
973
974 if (rxFifo.empty()) {
975 devIntrPost(Regs::Intr_RxEmpty);
976 rxEmpty = true;
977 }
978
979 if (rxFifo.size() < params()->rx_fifo_low_mark)
980 rxLow = true;
981
982 if (rxFifo.size() > params()->rx_fifo_threshold)
983 rxLow = false;
984
985 devIntrPost(Regs::Intr_RxDMA);
986 break;
987
988 default:
989 panic("Invalid rxState!");
990 }
991
992 DPRINTF(EthernetSM, "entering next rxState=%s\n",
993 RxStateStrings[rxState]);
994
995 goto next;
996
997 exit:
998 /**
999 * @todo do we want to schedule a future kick?
1000 */
1001 DPRINTF(EthernetSM, "rx state machine exited rxState=%s\n",
1002 RxStateStrings[rxState]);
1003 }
1004
1005 void
1006 Device::txDmaDone()
1007 {
1008 assert(txState == txCopy);
1009 txState = txCopyDone;
1010 DPRINTF(EthernetDMA, "tx dma read paddr=%#x len=%d\n",
1011 txDmaAddr, txDmaLen);
1012 DDUMP(EthernetData, txDmaData, txDmaLen);
1013
1014 // If the receive state machine has a pending DMA, let it go first
1015 if (rxState == rxBeginCopy)
1016 rxKick();
1017
1018 txKick();
1019 }
1020
1021 void
1022 Device::transmit()
1023 {
1024 if (txFifo.empty()) {
1025 DPRINTF(Ethernet, "nothing to transmit\n");
1026 return;
1027 }
1028
1029 uint32_t interrupts;
1030 EthPacketPtr packet = txFifo.front();
1031 if (!interface->sendPacket(packet)) {
1032 DPRINTF(Ethernet, "Packet Transmit: failed txFifo available %d\n",
1033 txFifo.avail());
1034 goto reschedule;
1035 }
1036
1037 txFifo.pop();
1038 #if TRACING_ON
1039 if (DTRACE(Ethernet)) {
1040 IpPtr ip(packet);
1041 if (ip) {
1042 DPRINTF(Ethernet, "ID is %d\n", ip->id());
1043 TcpPtr tcp(ip);
1044 if (tcp) {
1045 DPRINTF(Ethernet,
1046 "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n",
1047 tcp->sport(), tcp->dport(), tcp->seq(),
1048 tcp->ack());
1049 }
1050 }
1051 }
1052 #endif
1053
1054 DDUMP(EthernetData, packet->data, packet->length);
1055 txBytes += packet->length;
1056 txPackets++;
1057
1058 DPRINTF(Ethernet, "Packet Transmit: successful txFifo Available %d\n",
1059 txFifo.avail());
1060
1061 interrupts = Regs::Intr_TxPacket;
1062 if (txFifo.size() < regs.TxFifoMark)
1063 interrupts |= Regs::Intr_TxLow;
1064 devIntrPost(interrupts);
1065
1066 reschedule:
1067 if (!txFifo.empty() && !txEvent.scheduled()) {
1068 DPRINTF(Ethernet, "reschedule transmit\n");
1069 txEvent.schedule(curTick + retryTime);
1070 }
1071 }
1072
1073 void
1074 Device::txKick()
1075 {
1076 VirtualReg *vnic;
1077 DPRINTF(EthernetSM, "txKick: txState=%s (txFifo.size=%d)\n",
1078 TxStateStrings[txState], txFifo.size());
1079
1080 if (txKickTick > curTick) {
1081 DPRINTF(EthernetSM, "txKick: exiting, can't run till %d\n",
1082 txKickTick);
1083 return;
1084 }
1085
1086 next:
1087 if (txState == txIdle)
1088 goto exit;
1089
1090 assert(!txList.empty());
1091 vnic = &virtualRegs[txList.front()];
1092
1093 switch (txState) {
1094 case txFifoBlock:
1095 assert(Regs::get_TxDone_Busy(vnic->TxDone));
1096 if (!txPacket) {
1097 // Grab a new packet from the fifo.
1098 txPacket = new EthPacketData(16384);
1099 txPacketOffset = 0;
1100 }
1101
1102 if (txFifo.avail() - txPacket->length <
1103 Regs::get_TxData_Len(vnic->TxData)) {
1104 DPRINTF(EthernetSM, "transmit fifo full. Nothing to do.\n");
1105 goto exit;
1106 }
1107
1108 txState = txBeginCopy;
1109 break;
1110
1111 case txBeginCopy:
1112 if (dmaPending())
1113 goto exit;
1114
1115 txDmaAddr = params()->platform->pciToDma(
1116 Regs::get_TxData_Addr(vnic->TxData));
1117 txDmaLen = Regs::get_TxData_Len(vnic->TxData);
1118 txDmaData = txPacket->data + txPacketOffset;
1119 txState = txCopy;
1120
1121 dmaRead(txDmaAddr, txDmaLen, &txDmaEvent, txDmaData);
1122 break;
1123
1124 case txCopy:
1125 DPRINTF(EthernetSM, "transmit machine still copying\n");
1126 goto exit;
1127
1128 case txCopyDone:
1129 vnic->TxDone = txDmaLen | Regs::TxDone_Complete;
1130 txPacket->length += txDmaLen;
1131 if ((vnic->TxData & Regs::TxData_More)) {
1132 txPacketOffset += txDmaLen;
1133 txState = txIdle;
1134 devIntrPost(Regs::Intr_TxDMA);
1135 break;
1136 }
1137
1138 assert(txPacket->length <= txFifo.avail());
1139 if ((vnic->TxData & Regs::TxData_Checksum)) {
1140 IpPtr ip(txPacket);
1141 if (ip) {
1142 TcpPtr tcp(ip);
1143 if (tcp) {
1144 tcp->sum(0);
1145 tcp->sum(cksum(tcp));
1146 txTcpChecksums++;
1147 }
1148
1149 UdpPtr udp(ip);
1150 if (udp) {
1151 udp->sum(0);
1152 udp->sum(cksum(udp));
1153 txUdpChecksums++;
1154 }
1155
1156 ip->sum(0);
1157 ip->sum(cksum(ip));
1158 txIpChecksums++;
1159 }
1160 }
1161
1162 txFifo.push(txPacket);
1163 if (txFifo.avail() < regs.TxMaxCopy) {
1164 devIntrPost(Regs::Intr_TxFull);
1165 txFull = true;
1166 }
1167 txPacket = 0;
1168 transmit();
1169 txList.pop_front();
1170 txState = txList.empty() ? txIdle : txFifoBlock;
1171 devIntrPost(Regs::Intr_TxDMA);
1172 break;
1173
1174 default:
1175 panic("Invalid txState!");
1176 }
1177
1178 DPRINTF(EthernetSM, "entering next txState=%s\n",
1179 TxStateStrings[txState]);
1180
1181 goto next;
1182
1183 exit:
1184 /**
1185 * @todo do we want to schedule a future kick?
1186 */
1187 DPRINTF(EthernetSM, "tx state machine exited txState=%s\n",
1188 TxStateStrings[txState]);
1189 }
1190
1191 void
1192 Device::transferDone()
1193 {
1194 if (txFifo.empty()) {
1195 DPRINTF(Ethernet, "transfer complete: txFifo empty...nothing to do\n");
1196 return;
1197 }
1198
1199 DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n");
1200
1201 if (txEvent.scheduled())
1202 txEvent.reschedule(curTick + cycles(1));
1203 else
1204 txEvent.schedule(curTick + cycles(1));
1205 }
1206
1207 bool
1208 Device::rxFilter(const EthPacketPtr &packet)
1209 {
1210 if (!Regs::get_Config_Filter(regs.Config))
1211 return false;
1212
1213 panic("receive filter not implemented\n");
1214 bool drop = true;
1215
1216 #if 0
1217 string type;
1218
1219 EthHdr *eth = packet->eth();
1220 if (eth->unicast()) {
1221 // If we're accepting all unicast addresses
1222 if (acceptUnicast)
1223 drop = false;
1224
1225 // If we make a perfect match
1226 if (acceptPerfect && params->eaddr == eth.dst())
1227 drop = false;
1228
1229 if (acceptArp && eth->type() == ETH_TYPE_ARP)
1230 drop = false;
1231
1232 } else if (eth->broadcast()) {
1233 // if we're accepting broadcasts
1234 if (acceptBroadcast)
1235 drop = false;
1236
1237 } else if (eth->multicast()) {
1238 // if we're accepting all multicasts
1239 if (acceptMulticast)
1240 drop = false;
1241
1242 }
1243
1244 if (drop) {
1245 DPRINTF(Ethernet, "rxFilter drop\n");
1246 DDUMP(EthernetData, packet->data, packet->length);
1247 }
1248 #endif
1249 return drop;
1250 }
1251
1252 bool
1253 Device::recvPacket(EthPacketPtr packet)
1254 {
1255 rxBytes += packet->length;
1256 rxPackets++;
1257
1258 DPRINTF(Ethernet, "Receiving packet from wire, rxFifo Available is %d\n",
1259 rxFifo.avail());
1260
1261 if (!rxEnable) {
1262 DPRINTF(Ethernet, "receive disabled...packet dropped\n");
1263 return true;
1264 }
1265
1266 if (rxFilter(packet)) {
1267 DPRINTF(Ethernet, "packet filtered...dropped\n");
1268 return true;
1269 }
1270
1271 if (rxFifo.size() >= regs.RxFifoMark)
1272 devIntrPost(Regs::Intr_RxHigh);
1273
1274 if (!rxFifo.push(packet)) {
1275 DPRINTF(Ethernet,
1276 "packet will not fit in receive buffer...packet dropped\n");
1277 return false;
1278 }
1279
1280 // If we were at the last element, back up one ot go to the new
1281 // last element of the list.
1282 if (rxFifoPtr == rxFifo.end())
1283 --rxFifoPtr;
1284
1285 devIntrPost(Regs::Intr_RxPacket);
1286 rxKick();
1287 return true;
1288 }
1289
1290 //=====================================================================
1291 //
1292 //
1293 void
1294 Base::serialize(std::ostream &os)
1295 {
1296 // Serialize the PciDev base class
1297 PciDev::serialize(os);
1298
1299 SERIALIZE_SCALAR(rxEnable);
1300 SERIALIZE_SCALAR(txEnable);
1301 SERIALIZE_SCALAR(cpuIntrEnable);
1302
1303 /*
1304 * Keep track of pending interrupt status.
1305 */
1306 SERIALIZE_SCALAR(intrTick);
1307 SERIALIZE_SCALAR(cpuPendingIntr);
1308 Tick intrEventTick = 0;
1309 if (intrEvent)
1310 intrEventTick = intrEvent->when();
1311 SERIALIZE_SCALAR(intrEventTick);
1312 }
1313
1314 void
1315 Base::unserialize(Checkpoint *cp, const std::string &section)
1316 {
1317 // Unserialize the PciDev base class
1318 PciDev::unserialize(cp, section);
1319
1320 UNSERIALIZE_SCALAR(rxEnable);
1321 UNSERIALIZE_SCALAR(txEnable);
1322 UNSERIALIZE_SCALAR(cpuIntrEnable);
1323
1324 /*
1325 * Keep track of pending interrupt status.
1326 */
1327 UNSERIALIZE_SCALAR(intrTick);
1328 UNSERIALIZE_SCALAR(cpuPendingIntr);
1329 Tick intrEventTick;
1330 UNSERIALIZE_SCALAR(intrEventTick);
1331 if (intrEventTick) {
1332 intrEvent = new IntrEvent(this, true);
1333 intrEvent->schedule(intrEventTick);
1334 }
1335 }
1336
1337 void
1338 Device::serialize(std::ostream &os)
1339 {
1340 int count;
1341
1342 // Serialize the PciDev base class
1343 Base::serialize(os);
1344
1345 if (rxState == rxCopy)
1346 panic("can't serialize with an in flight dma request rxState=%s",
1347 RxStateStrings[rxState]);
1348
1349 if (txState == txCopy)
1350 panic("can't serialize with an in flight dma request txState=%s",
1351 TxStateStrings[txState]);
1352
1353 /*
1354 * Serialize the device registers
1355 */
1356 SERIALIZE_SCALAR(regs.Config);
1357 SERIALIZE_SCALAR(regs.IntrStatus);
1358 SERIALIZE_SCALAR(regs.IntrMask);
1359 SERIALIZE_SCALAR(regs.RxMaxCopy);
1360 SERIALIZE_SCALAR(regs.TxMaxCopy);
1361 SERIALIZE_SCALAR(regs.RxMaxIntr);
1362 SERIALIZE_SCALAR(regs.VirtualCount);
1363 SERIALIZE_SCALAR(regs.RxData);
1364 SERIALIZE_SCALAR(regs.RxDone);
1365 SERIALIZE_SCALAR(regs.TxData);
1366 SERIALIZE_SCALAR(regs.TxDone);
1367
1368 /*
1369 * Serialize the virtual nic state
1370 */
1371 int virtualRegsSize = virtualRegs.size();
1372 SERIALIZE_SCALAR(virtualRegsSize);
1373 for (int i = 0; i < virtualRegsSize; ++i) {
1374 VirtualReg *vnic = &virtualRegs[i];
1375
1376 std::string reg = csprintf("vnic%d", i);
1377 paramOut(os, reg + ".RxData", vnic->RxData);
1378 paramOut(os, reg + ".RxDone", vnic->RxDone);
1379 paramOut(os, reg + ".TxData", vnic->TxData);
1380 paramOut(os, reg + ".TxDone", vnic->TxDone);
1381
1382 bool rxPacketExists = vnic->rxPacket != rxFifo.end();
1383 paramOut(os, reg + ".rxPacketExists", rxPacketExists);
1384 if (rxPacketExists) {
1385 int rxPacket = 0;
1386 PacketFifo::iterator i = rxFifo.begin();
1387 while (i != vnic->rxPacket) {
1388 assert(i != rxFifo.end());
1389 ++i;
1390 ++rxPacket;
1391 }
1392
1393 paramOut(os, reg + ".rxPacket", rxPacket);
1394 paramOut(os, reg + ".rxPacketOffset", vnic->rxPacketOffset);
1395 paramOut(os, reg + ".rxPacketBytes", vnic->rxPacketBytes);
1396 }
1397 paramOut(os, reg + ".rxDoneData", vnic->rxDoneData);
1398 }
1399
1400 int rxFifoPtr = rxFifo.countPacketsBefore(this->rxFifoPtr);
1401 SERIALIZE_SCALAR(rxFifoPtr);
1402
1403 SERIALIZE_SCALAR(rxActive);
1404
1405 VirtualList::iterator i, end;
1406 for (count = 0, i = rxList.begin(), end = rxList.end(); i != end; ++i)
1407 paramOut(os, csprintf("rxList%d", count++), *i);
1408 int rxListSize = count;
1409 SERIALIZE_SCALAR(rxListSize);
1410
1411 for (count = 0, i = rxBusy.begin(), end = rxBusy.end(); i != end; ++i)
1412 paramOut(os, csprintf("rxBusy%d", count++), *i);
1413 int rxBusySize = count;
1414 SERIALIZE_SCALAR(rxBusySize);
1415
1416 for (count = 0, i = txList.begin(), end = txList.end(); i != end; ++i)
1417 paramOut(os, csprintf("txList%d", count++), *i);
1418 int txListSize = count;
1419 SERIALIZE_SCALAR(txListSize);
1420
1421 /*
1422 * Serialize rx state machine
1423 */
1424 int rxState = this->rxState;
1425 SERIALIZE_SCALAR(rxState);
1426 SERIALIZE_SCALAR(rxEmpty);
1427 SERIALIZE_SCALAR(rxLow);
1428 rxFifo.serialize("rxFifo", os);
1429
1430 /*
1431 * Serialize tx state machine
1432 */
1433 int txState = this->txState;
1434 SERIALIZE_SCALAR(txState);
1435 SERIALIZE_SCALAR(txFull);
1436 txFifo.serialize("txFifo", os);
1437 bool txPacketExists = txPacket;
1438 SERIALIZE_SCALAR(txPacketExists);
1439 if (txPacketExists) {
1440 txPacket->serialize("txPacket", os);
1441 SERIALIZE_SCALAR(txPacketOffset);
1442 SERIALIZE_SCALAR(txPacketBytes);
1443 }
1444
1445 /*
1446 * If there's a pending transmit, store the time so we can
1447 * reschedule it later
1448 */
1449 Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick : 0;
1450 SERIALIZE_SCALAR(transmitTick);
1451 }
1452
1453 void
1454 Device::unserialize(Checkpoint *cp, const std::string &section)
1455 {
1456 // Unserialize the PciDev base class
1457 Base::unserialize(cp, section);
1458
1459 /*
1460 * Unserialize the device registers
1461 */
1462 UNSERIALIZE_SCALAR(regs.Config);
1463 UNSERIALIZE_SCALAR(regs.IntrStatus);
1464 UNSERIALIZE_SCALAR(regs.IntrMask);
1465 UNSERIALIZE_SCALAR(regs.RxMaxCopy);
1466 UNSERIALIZE_SCALAR(regs.TxMaxCopy);
1467 UNSERIALIZE_SCALAR(regs.RxMaxIntr);
1468 UNSERIALIZE_SCALAR(regs.VirtualCount);
1469 UNSERIALIZE_SCALAR(regs.RxData);
1470 UNSERIALIZE_SCALAR(regs.RxDone);
1471 UNSERIALIZE_SCALAR(regs.TxData);
1472 UNSERIALIZE_SCALAR(regs.TxDone);
1473
1474 UNSERIALIZE_SCALAR(rxActive);
1475
1476 int rxListSize;
1477 UNSERIALIZE_SCALAR(rxListSize);
1478 rxList.clear();
1479 for (int i = 0; i < rxListSize; ++i) {
1480 int value;
1481 paramIn(cp, section, csprintf("rxList%d", i), value);
1482 rxList.push_back(value);
1483 }
1484
1485 int rxBusySize;
1486 UNSERIALIZE_SCALAR(rxBusySize);
1487 rxBusy.clear();
1488 for (int i = 0; i < rxBusySize; ++i) {
1489 int value;
1490 paramIn(cp, section, csprintf("rxBusy%d", i), value);
1491 rxBusy.push_back(value);
1492 }
1493
1494 int txListSize;
1495 UNSERIALIZE_SCALAR(txListSize);
1496 txList.clear();
1497 for (int i = 0; i < txListSize; ++i) {
1498 int value;
1499 paramIn(cp, section, csprintf("txList%d", i), value);
1500 txList.push_back(value);
1501 }
1502
1503 /*
1504 * Unserialize rx state machine
1505 */
1506 int rxState;
1507 UNSERIALIZE_SCALAR(rxState);
1508 UNSERIALIZE_SCALAR(rxEmpty);
1509 UNSERIALIZE_SCALAR(rxLow);
1510 this->rxState = (RxState) rxState;
1511 rxFifo.unserialize("rxFifo", cp, section);
1512
1513 int rxFifoPtr;
1514 UNSERIALIZE_SCALAR(rxFifoPtr);
1515 this->rxFifoPtr = rxFifo.begin();
1516 for (int i = 0; i < rxFifoPtr; ++i)
1517 ++this->rxFifoPtr;
1518
1519 /*
1520 * Unserialize tx state machine
1521 */
1522 int txState;
1523 UNSERIALIZE_SCALAR(txState);
1524 UNSERIALIZE_SCALAR(txFull);
1525 this->txState = (TxState) txState;
1526 txFifo.unserialize("txFifo", cp, section);
1527 bool txPacketExists;
1528 UNSERIALIZE_SCALAR(txPacketExists);
1529 txPacket = 0;
1530 if (txPacketExists) {
1531 txPacket = new EthPacketData(16384);
1532 txPacket->unserialize("txPacket", cp, section);
1533 UNSERIALIZE_SCALAR(txPacketOffset);
1534 UNSERIALIZE_SCALAR(txPacketBytes);
1535 }
1536
1537 /*
1538 * unserialize the virtual nic registers/state
1539 *
1540 * this must be done after the unserialization of the rxFifo
1541 * because the packet iterators depend on the fifo being populated
1542 */
1543 int virtualRegsSize;
1544 UNSERIALIZE_SCALAR(virtualRegsSize);
1545 virtualRegs.clear();
1546 virtualRegs.resize(virtualRegsSize);
1547 for (int i = 0; i < virtualRegsSize; ++i) {
1548 VirtualReg *vnic = &virtualRegs[i];
1549 std::string reg = csprintf("vnic%d", i);
1550
1551 paramIn(cp, section, reg + ".RxData", vnic->RxData);
1552 paramIn(cp, section, reg + ".RxDone", vnic->RxDone);
1553 paramIn(cp, section, reg + ".TxData", vnic->TxData);
1554 paramIn(cp, section, reg + ".TxDone", vnic->TxDone);
1555
1556 vnic->rxUnique = rxUnique++;
1557 vnic->txUnique = txUnique++;
1558
1559 bool rxPacketExists;
1560 paramIn(cp, section, reg + ".rxPacketExists", rxPacketExists);
1561 if (rxPacketExists) {
1562 int rxPacket;
1563 paramIn(cp, section, reg + ".rxPacket", rxPacket);
1564 vnic->rxPacket = rxFifo.begin();
1565 while (rxPacket--)
1566 ++vnic->rxPacket;
1567
1568 paramIn(cp, section, reg + ".rxPacketOffset",
1569 vnic->rxPacketOffset);
1570 paramIn(cp, section, reg + ".rxPacketBytes", vnic->rxPacketBytes);
1571 } else {
1572 vnic->rxPacket = rxFifo.end();
1573 }
1574 paramIn(cp, section, reg + ".rxDoneData", vnic->rxDoneData);
1575 }
1576
1577 /*
1578 * If there's a pending transmit, reschedule it now
1579 */
1580 Tick transmitTick;
1581 UNSERIALIZE_SCALAR(transmitTick);
1582 if (transmitTick)
1583 txEvent.schedule(curTick + transmitTick);
1584
1585 pioPort->sendStatusChange(Port::RangeChange);
1586
1587 }
1588
1589
1590 BEGIN_DECLARE_SIM_OBJECT_PARAMS(Interface)
1591
1592 SimObjectParam<EtherInt *> peer;
1593 SimObjectParam<Device *> device;
1594
1595 END_DECLARE_SIM_OBJECT_PARAMS(Interface)
1596
1597 BEGIN_INIT_SIM_OBJECT_PARAMS(Interface)
1598
1599 INIT_PARAM_DFLT(peer, "peer interface", NULL),
1600 INIT_PARAM(device, "Ethernet device of this interface")
1601
1602 END_INIT_SIM_OBJECT_PARAMS(Interface)
1603
1604 CREATE_SIM_OBJECT(Interface)
1605 {
1606 Interface *dev_int = new Interface(getInstanceName(), device);
1607
1608 EtherInt *p = (EtherInt *)peer;
1609 if (p) {
1610 dev_int->setPeer(p);
1611 p->setPeer(dev_int);
1612 }
1613
1614 return dev_int;
1615 }
1616
1617 REGISTER_SIM_OBJECT("SinicInt", Interface)
1618
1619
1620 BEGIN_DECLARE_SIM_OBJECT_PARAMS(Device)
1621
1622
1623 SimObjectParam<System *> system;
1624 SimObjectParam<Platform *> platform;
1625 SimObjectParam<PciConfigData *> configdata;
1626 Param<uint32_t> pci_bus;
1627 Param<uint32_t> pci_dev;
1628 Param<uint32_t> pci_func;
1629 Param<Tick> pio_latency;
1630 Param<Tick> intr_delay;
1631
1632 Param<Tick> clock;
1633 Param<Tick> dma_read_delay;
1634 Param<Tick> dma_read_factor;
1635 Param<Tick> dma_write_delay;
1636 Param<Tick> dma_write_factor;
1637
1638 Param<Tick> rx_delay;
1639 Param<Tick> tx_delay;
1640 Param<uint32_t> rx_max_copy;
1641 Param<uint32_t> tx_max_copy;
1642 Param<uint32_t> rx_max_intr;
1643 Param<uint32_t> rx_fifo_size;
1644 Param<uint32_t> tx_fifo_size;
1645 Param<uint32_t> rx_fifo_threshold;
1646 Param<uint32_t> rx_fifo_low_mark;
1647 Param<uint32_t> tx_fifo_high_mark;
1648 Param<uint32_t> tx_fifo_threshold;
1649
1650 Param<bool> rx_filter;
1651 Param<std::string> hardware_address;
1652 Param<bool> rx_thread;
1653 Param<bool> tx_thread;
1654 Param<bool> rss;
1655 Param<uint32_t> virtual_count;
1656 Param<bool> zero_copy;
1657 Param<bool> delay_copy;
1658 Param<bool> virtual_addr;
1659
1660 END_DECLARE_SIM_OBJECT_PARAMS(Device)
1661
1662 BEGIN_INIT_SIM_OBJECT_PARAMS(Device)
1663
1664
1665 INIT_PARAM(system, "System pointer"),
1666 INIT_PARAM(platform, "Platform pointer"),
1667 INIT_PARAM(configdata, "PCI Config data"),
1668 INIT_PARAM(pci_bus, "PCI bus ID"),
1669 INIT_PARAM(pci_dev, "PCI device number"),
1670 INIT_PARAM(pci_func, "PCI function code"),
1671 INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1),
1672 INIT_PARAM(intr_delay, "Interrupt Delay"),
1673 INIT_PARAM(clock, "State machine cycle time"),
1674
1675 INIT_PARAM(dma_read_delay, "fixed delay for dma reads"),
1676 INIT_PARAM(dma_read_factor, "multiplier for dma reads"),
1677 INIT_PARAM(dma_write_delay, "fixed delay for dma writes"),
1678 INIT_PARAM(dma_write_factor, "multiplier for dma writes"),
1679
1680 INIT_PARAM(rx_delay, "Receive Delay"),
1681 INIT_PARAM(tx_delay, "Transmit Delay"),
1682 INIT_PARAM(rx_max_copy, "rx max copy"),
1683 INIT_PARAM(tx_max_copy, "rx max copy"),
1684 INIT_PARAM(rx_max_intr, "rx max intr"),
1685 INIT_PARAM(rx_fifo_size, "max size in bytes of rxFifo"),
1686 INIT_PARAM(tx_fifo_size, "max size in bytes of txFifo"),
1687 INIT_PARAM(rx_fifo_threshold, "max size in bytes of rxFifo"),
1688 INIT_PARAM(rx_fifo_low_mark, "max size in bytes of rxFifo"),
1689 INIT_PARAM(tx_fifo_high_mark, "max size in bytes of txFifo"),
1690 INIT_PARAM(tx_fifo_threshold, "max size in bytes of txFifo"),
1691
1692 INIT_PARAM(rx_filter, "Enable Receive Filter"),
1693 INIT_PARAM(hardware_address, "Ethernet Hardware Address"),
1694 INIT_PARAM(rx_thread, ""),
1695 INIT_PARAM(tx_thread, ""),
1696 INIT_PARAM(rss, ""),
1697 INIT_PARAM(virtual_count, ""),
1698 INIT_PARAM(zero_copy, ""),
1699 INIT_PARAM(delay_copy, ""),
1700 INIT_PARAM(virtual_addr, "")
1701
1702 END_INIT_SIM_OBJECT_PARAMS(Device)
1703
1704
1705 CREATE_SIM_OBJECT(Device)
1706 {
1707 Device::Params *params = new Device::Params;
1708 params->name = getInstanceName();
1709 params->platform = platform;
1710 params->system = system;
1711 params->configData = configdata;
1712 params->busNum = pci_bus;
1713 params->deviceNum = pci_dev;
1714 params->functionNum = pci_func;
1715 params->pio_delay = pio_latency;
1716 params->intr_delay = intr_delay;
1717 params->clock = clock;
1718
1719 params->dma_read_delay = dma_read_delay;
1720 params->dma_read_factor = dma_read_factor;
1721 params->dma_write_delay = dma_write_delay;
1722 params->dma_write_factor = dma_write_factor;
1723
1724 params->tx_delay = tx_delay;
1725 params->rx_delay = rx_delay;
1726 params->rx_max_copy = rx_max_copy;
1727 params->tx_max_copy = tx_max_copy;
1728 params->rx_max_intr = rx_max_intr;
1729 params->rx_fifo_size = rx_fifo_size;
1730 params->tx_fifo_size = tx_fifo_size;
1731 params->rx_fifo_threshold = rx_fifo_threshold;
1732 params->rx_fifo_low_mark = rx_fifo_low_mark;
1733 params->tx_fifo_high_mark = tx_fifo_high_mark;
1734 params->tx_fifo_threshold = tx_fifo_threshold;
1735
1736 params->rx_filter = rx_filter;
1737 params->eaddr = hardware_address;
1738 params->rx_thread = rx_thread;
1739 params->tx_thread = tx_thread;
1740 params->rss = rss;
1741 params->virtual_count = virtual_count;
1742 params->zero_copy = zero_copy;
1743 params->delay_copy = delay_copy;
1744 params->virtual_addr = virtual_addr;
1745
1746 return new Device(params);
1747 }
1748
1749 REGISTER_SIM_OBJECT("Sinic", Device)
1750
1751 /* namespace Sinic */ }