Only issue responses if we aren;t already blocked
[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() || getState() != Running)
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() || getState() != Running)
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 void
1291 Device::resume()
1292 {
1293 SimObject::resume();
1294
1295 // During drain we could have left the state machines in a waiting state and
1296 // they wouldn't get out until some other event occured to kick them.
1297 // This way they'll get out immediately
1298 txKick();
1299 rxKick();
1300 }
1301
1302 //=====================================================================
1303 //
1304 //
1305 void
1306 Base::serialize(std::ostream &os)
1307 {
1308 // Serialize the PciDev base class
1309 PciDev::serialize(os);
1310
1311 SERIALIZE_SCALAR(rxEnable);
1312 SERIALIZE_SCALAR(txEnable);
1313 SERIALIZE_SCALAR(cpuIntrEnable);
1314
1315 /*
1316 * Keep track of pending interrupt status.
1317 */
1318 SERIALIZE_SCALAR(intrTick);
1319 SERIALIZE_SCALAR(cpuPendingIntr);
1320 Tick intrEventTick = 0;
1321 if (intrEvent)
1322 intrEventTick = intrEvent->when();
1323 SERIALIZE_SCALAR(intrEventTick);
1324 }
1325
1326 void
1327 Base::unserialize(Checkpoint *cp, const std::string &section)
1328 {
1329 // Unserialize the PciDev base class
1330 PciDev::unserialize(cp, section);
1331
1332 UNSERIALIZE_SCALAR(rxEnable);
1333 UNSERIALIZE_SCALAR(txEnable);
1334 UNSERIALIZE_SCALAR(cpuIntrEnable);
1335
1336 /*
1337 * Keep track of pending interrupt status.
1338 */
1339 UNSERIALIZE_SCALAR(intrTick);
1340 UNSERIALIZE_SCALAR(cpuPendingIntr);
1341 Tick intrEventTick;
1342 UNSERIALIZE_SCALAR(intrEventTick);
1343 if (intrEventTick) {
1344 intrEvent = new IntrEvent(this, true);
1345 intrEvent->schedule(intrEventTick);
1346 }
1347 }
1348
1349 void
1350 Device::serialize(std::ostream &os)
1351 {
1352 int count;
1353
1354 // Serialize the PciDev base class
1355 Base::serialize(os);
1356
1357 if (rxState == rxCopy)
1358 panic("can't serialize with an in flight dma request rxState=%s",
1359 RxStateStrings[rxState]);
1360
1361 if (txState == txCopy)
1362 panic("can't serialize with an in flight dma request txState=%s",
1363 TxStateStrings[txState]);
1364
1365 /*
1366 * Serialize the device registers
1367 */
1368 SERIALIZE_SCALAR(regs.Config);
1369 SERIALIZE_SCALAR(regs.IntrStatus);
1370 SERIALIZE_SCALAR(regs.IntrMask);
1371 SERIALIZE_SCALAR(regs.RxMaxCopy);
1372 SERIALIZE_SCALAR(regs.TxMaxCopy);
1373 SERIALIZE_SCALAR(regs.RxMaxIntr);
1374 SERIALIZE_SCALAR(regs.VirtualCount);
1375 SERIALIZE_SCALAR(regs.RxData);
1376 SERIALIZE_SCALAR(regs.RxDone);
1377 SERIALIZE_SCALAR(regs.TxData);
1378 SERIALIZE_SCALAR(regs.TxDone);
1379
1380 /*
1381 * Serialize the virtual nic state
1382 */
1383 int virtualRegsSize = virtualRegs.size();
1384 SERIALIZE_SCALAR(virtualRegsSize);
1385 for (int i = 0; i < virtualRegsSize; ++i) {
1386 VirtualReg *vnic = &virtualRegs[i];
1387
1388 std::string reg = csprintf("vnic%d", i);
1389 paramOut(os, reg + ".RxData", vnic->RxData);
1390 paramOut(os, reg + ".RxDone", vnic->RxDone);
1391 paramOut(os, reg + ".TxData", vnic->TxData);
1392 paramOut(os, reg + ".TxDone", vnic->TxDone);
1393
1394 bool rxPacketExists = vnic->rxPacket != rxFifo.end();
1395 paramOut(os, reg + ".rxPacketExists", rxPacketExists);
1396 if (rxPacketExists) {
1397 int rxPacket = 0;
1398 PacketFifo::iterator i = rxFifo.begin();
1399 while (i != vnic->rxPacket) {
1400 assert(i != rxFifo.end());
1401 ++i;
1402 ++rxPacket;
1403 }
1404
1405 paramOut(os, reg + ".rxPacket", rxPacket);
1406 paramOut(os, reg + ".rxPacketOffset", vnic->rxPacketOffset);
1407 paramOut(os, reg + ".rxPacketBytes", vnic->rxPacketBytes);
1408 }
1409 paramOut(os, reg + ".rxDoneData", vnic->rxDoneData);
1410 }
1411
1412 int rxFifoPtr = rxFifo.countPacketsBefore(this->rxFifoPtr);
1413 SERIALIZE_SCALAR(rxFifoPtr);
1414
1415 SERIALIZE_SCALAR(rxActive);
1416
1417 VirtualList::iterator i, end;
1418 for (count = 0, i = rxList.begin(), end = rxList.end(); i != end; ++i)
1419 paramOut(os, csprintf("rxList%d", count++), *i);
1420 int rxListSize = count;
1421 SERIALIZE_SCALAR(rxListSize);
1422
1423 for (count = 0, i = rxBusy.begin(), end = rxBusy.end(); i != end; ++i)
1424 paramOut(os, csprintf("rxBusy%d", count++), *i);
1425 int rxBusySize = count;
1426 SERIALIZE_SCALAR(rxBusySize);
1427
1428 for (count = 0, i = txList.begin(), end = txList.end(); i != end; ++i)
1429 paramOut(os, csprintf("txList%d", count++), *i);
1430 int txListSize = count;
1431 SERIALIZE_SCALAR(txListSize);
1432
1433 /*
1434 * Serialize rx state machine
1435 */
1436 int rxState = this->rxState;
1437 SERIALIZE_SCALAR(rxState);
1438 SERIALIZE_SCALAR(rxEmpty);
1439 SERIALIZE_SCALAR(rxLow);
1440 rxFifo.serialize("rxFifo", os);
1441
1442 /*
1443 * Serialize tx state machine
1444 */
1445 int txState = this->txState;
1446 SERIALIZE_SCALAR(txState);
1447 SERIALIZE_SCALAR(txFull);
1448 txFifo.serialize("txFifo", os);
1449 bool txPacketExists = txPacket;
1450 SERIALIZE_SCALAR(txPacketExists);
1451 if (txPacketExists) {
1452 txPacket->serialize("txPacket", os);
1453 SERIALIZE_SCALAR(txPacketOffset);
1454 SERIALIZE_SCALAR(txPacketBytes);
1455 }
1456
1457 /*
1458 * If there's a pending transmit, store the time so we can
1459 * reschedule it later
1460 */
1461 Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick : 0;
1462 SERIALIZE_SCALAR(transmitTick);
1463 }
1464
1465 void
1466 Device::unserialize(Checkpoint *cp, const std::string &section)
1467 {
1468 // Unserialize the PciDev base class
1469 Base::unserialize(cp, section);
1470
1471 /*
1472 * Unserialize the device registers
1473 */
1474 UNSERIALIZE_SCALAR(regs.Config);
1475 UNSERIALIZE_SCALAR(regs.IntrStatus);
1476 UNSERIALIZE_SCALAR(regs.IntrMask);
1477 UNSERIALIZE_SCALAR(regs.RxMaxCopy);
1478 UNSERIALIZE_SCALAR(regs.TxMaxCopy);
1479 UNSERIALIZE_SCALAR(regs.RxMaxIntr);
1480 UNSERIALIZE_SCALAR(regs.VirtualCount);
1481 UNSERIALIZE_SCALAR(regs.RxData);
1482 UNSERIALIZE_SCALAR(regs.RxDone);
1483 UNSERIALIZE_SCALAR(regs.TxData);
1484 UNSERIALIZE_SCALAR(regs.TxDone);
1485
1486 UNSERIALIZE_SCALAR(rxActive);
1487
1488 int rxListSize;
1489 UNSERIALIZE_SCALAR(rxListSize);
1490 rxList.clear();
1491 for (int i = 0; i < rxListSize; ++i) {
1492 int value;
1493 paramIn(cp, section, csprintf("rxList%d", i), value);
1494 rxList.push_back(value);
1495 }
1496
1497 int rxBusySize;
1498 UNSERIALIZE_SCALAR(rxBusySize);
1499 rxBusy.clear();
1500 for (int i = 0; i < rxBusySize; ++i) {
1501 int value;
1502 paramIn(cp, section, csprintf("rxBusy%d", i), value);
1503 rxBusy.push_back(value);
1504 }
1505
1506 int txListSize;
1507 UNSERIALIZE_SCALAR(txListSize);
1508 txList.clear();
1509 for (int i = 0; i < txListSize; ++i) {
1510 int value;
1511 paramIn(cp, section, csprintf("txList%d", i), value);
1512 txList.push_back(value);
1513 }
1514
1515 /*
1516 * Unserialize rx state machine
1517 */
1518 int rxState;
1519 UNSERIALIZE_SCALAR(rxState);
1520 UNSERIALIZE_SCALAR(rxEmpty);
1521 UNSERIALIZE_SCALAR(rxLow);
1522 this->rxState = (RxState) rxState;
1523 rxFifo.unserialize("rxFifo", cp, section);
1524
1525 int rxFifoPtr;
1526 UNSERIALIZE_SCALAR(rxFifoPtr);
1527 this->rxFifoPtr = rxFifo.begin();
1528 for (int i = 0; i < rxFifoPtr; ++i)
1529 ++this->rxFifoPtr;
1530
1531 /*
1532 * Unserialize tx state machine
1533 */
1534 int txState;
1535 UNSERIALIZE_SCALAR(txState);
1536 UNSERIALIZE_SCALAR(txFull);
1537 this->txState = (TxState) txState;
1538 txFifo.unserialize("txFifo", cp, section);
1539 bool txPacketExists;
1540 UNSERIALIZE_SCALAR(txPacketExists);
1541 txPacket = 0;
1542 if (txPacketExists) {
1543 txPacket = new EthPacketData(16384);
1544 txPacket->unserialize("txPacket", cp, section);
1545 UNSERIALIZE_SCALAR(txPacketOffset);
1546 UNSERIALIZE_SCALAR(txPacketBytes);
1547 }
1548
1549 /*
1550 * unserialize the virtual nic registers/state
1551 *
1552 * this must be done after the unserialization of the rxFifo
1553 * because the packet iterators depend on the fifo being populated
1554 */
1555 int virtualRegsSize;
1556 UNSERIALIZE_SCALAR(virtualRegsSize);
1557 virtualRegs.clear();
1558 virtualRegs.resize(virtualRegsSize);
1559 for (int i = 0; i < virtualRegsSize; ++i) {
1560 VirtualReg *vnic = &virtualRegs[i];
1561 std::string reg = csprintf("vnic%d", i);
1562
1563 paramIn(cp, section, reg + ".RxData", vnic->RxData);
1564 paramIn(cp, section, reg + ".RxDone", vnic->RxDone);
1565 paramIn(cp, section, reg + ".TxData", vnic->TxData);
1566 paramIn(cp, section, reg + ".TxDone", vnic->TxDone);
1567
1568 vnic->rxUnique = rxUnique++;
1569 vnic->txUnique = txUnique++;
1570
1571 bool rxPacketExists;
1572 paramIn(cp, section, reg + ".rxPacketExists", rxPacketExists);
1573 if (rxPacketExists) {
1574 int rxPacket;
1575 paramIn(cp, section, reg + ".rxPacket", rxPacket);
1576 vnic->rxPacket = rxFifo.begin();
1577 while (rxPacket--)
1578 ++vnic->rxPacket;
1579
1580 paramIn(cp, section, reg + ".rxPacketOffset",
1581 vnic->rxPacketOffset);
1582 paramIn(cp, section, reg + ".rxPacketBytes", vnic->rxPacketBytes);
1583 } else {
1584 vnic->rxPacket = rxFifo.end();
1585 }
1586 paramIn(cp, section, reg + ".rxDoneData", vnic->rxDoneData);
1587 }
1588
1589 /*
1590 * If there's a pending transmit, reschedule it now
1591 */
1592 Tick transmitTick;
1593 UNSERIALIZE_SCALAR(transmitTick);
1594 if (transmitTick)
1595 txEvent.schedule(curTick + transmitTick);
1596
1597 pioPort->sendStatusChange(Port::RangeChange);
1598
1599 }
1600
1601 /* namespace Sinic */ }
1602
1603 BEGIN_DECLARE_SIM_OBJECT_PARAMS_WNS(Sinic, SinicInterface)
1604
1605 SimObjectParam<EtherInt *> peer;
1606 SimObjectParam<Sinic::Device *> device;
1607 END_DECLARE_SIM_OBJECT_PARAMS_WNS(Sinic, SinicInterface)
1608
1609 BEGIN_INIT_SIM_OBJECT_PARAMS_WNS(Sinic, SinicInterface)
1610
1611 INIT_PARAM_DFLT(peer, "peer interface", NULL),
1612 INIT_PARAM(device, "Ethernet device of this interface")
1613
1614 END_INIT_SIM_OBJECT_PARAMS_WNS(Sinic, SinicInterface)
1615
1616 CREATE_SIM_OBJECT_WNS(Sinic, SinicInterface)
1617 {
1618 Sinic::Interface *dev_int = new Sinic::Interface(getInstanceName(), device);
1619
1620 EtherInt *p = (EtherInt *)peer;
1621 if (p) {
1622 dev_int->setPeer(p);
1623 p->setPeer(dev_int);
1624 }
1625
1626 return dev_int;
1627 }
1628
1629 REGISTER_SIM_OBJECT_WNS(Sinic, "SinicInt", SinicInterface)
1630
1631
1632 BEGIN_DECLARE_SIM_OBJECT_PARAMS_WNS(Sinic, SinicDevice)
1633
1634
1635 SimObjectParam<System *> system;
1636 SimObjectParam<Platform *> platform;
1637 SimObjectParam<PciConfigData *> configdata;
1638 Param<uint32_t> pci_bus;
1639 Param<uint32_t> pci_dev;
1640 Param<uint32_t> pci_func;
1641 Param<Tick> pio_latency;
1642 Param<Tick> config_latency;
1643 Param<Tick> intr_delay;
1644
1645 Param<Tick> clock;
1646 Param<Tick> dma_read_delay;
1647 Param<Tick> dma_read_factor;
1648 Param<Tick> dma_write_delay;
1649 Param<Tick> dma_write_factor;
1650
1651 Param<Tick> rx_delay;
1652 Param<Tick> tx_delay;
1653 Param<uint32_t> rx_max_copy;
1654 Param<uint32_t> tx_max_copy;
1655 Param<uint32_t> rx_max_intr;
1656 Param<uint32_t> rx_fifo_size;
1657 Param<uint32_t> tx_fifo_size;
1658 Param<uint32_t> rx_fifo_threshold;
1659 Param<uint32_t> rx_fifo_low_mark;
1660 Param<uint32_t> tx_fifo_high_mark;
1661 Param<uint32_t> tx_fifo_threshold;
1662
1663 Param<bool> rx_filter;
1664 Param<std::string> hardware_address;
1665 Param<bool> rx_thread;
1666 Param<bool> tx_thread;
1667 Param<bool> rss;
1668 Param<uint32_t> virtual_count;
1669 Param<bool> zero_copy;
1670 Param<bool> delay_copy;
1671 Param<bool> virtual_addr;
1672
1673 END_DECLARE_SIM_OBJECT_PARAMS_WNS(Sinic, SinicDevice)
1674
1675 BEGIN_INIT_SIM_OBJECT_PARAMS_WNS(Sinic, SinicDevice)
1676
1677
1678 INIT_PARAM(system, "System pointer"),
1679 INIT_PARAM(platform, "Platform pointer"),
1680 INIT_PARAM(configdata, "PCI Config data"),
1681 INIT_PARAM(pci_bus, "PCI bus ID"),
1682 INIT_PARAM(pci_dev, "PCI device number"),
1683 INIT_PARAM(pci_func, "PCI function code"),
1684 INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1),
1685 INIT_PARAM(config_latency, "Number of cycles for a config read or write"),
1686 INIT_PARAM(intr_delay, "Interrupt Delay"),
1687 INIT_PARAM(clock, "State machine cycle time"),
1688
1689 INIT_PARAM(dma_read_delay, "fixed delay for dma reads"),
1690 INIT_PARAM(dma_read_factor, "multiplier for dma reads"),
1691 INIT_PARAM(dma_write_delay, "fixed delay for dma writes"),
1692 INIT_PARAM(dma_write_factor, "multiplier for dma writes"),
1693
1694 INIT_PARAM(rx_delay, "Receive Delay"),
1695 INIT_PARAM(tx_delay, "Transmit Delay"),
1696 INIT_PARAM(rx_max_copy, "rx max copy"),
1697 INIT_PARAM(tx_max_copy, "rx max copy"),
1698 INIT_PARAM(rx_max_intr, "rx max intr"),
1699 INIT_PARAM(rx_fifo_size, "max size in bytes of rxFifo"),
1700 INIT_PARAM(tx_fifo_size, "max size in bytes of txFifo"),
1701 INIT_PARAM(rx_fifo_threshold, "max size in bytes of rxFifo"),
1702 INIT_PARAM(rx_fifo_low_mark, "max size in bytes of rxFifo"),
1703 INIT_PARAM(tx_fifo_high_mark, "max size in bytes of txFifo"),
1704 INIT_PARAM(tx_fifo_threshold, "max size in bytes of txFifo"),
1705
1706 INIT_PARAM(rx_filter, "Enable Receive Filter"),
1707 INIT_PARAM(hardware_address, "Ethernet Hardware Address"),
1708 INIT_PARAM(rx_thread, ""),
1709 INIT_PARAM(tx_thread, ""),
1710 INIT_PARAM(rss, ""),
1711 INIT_PARAM(virtual_count, ""),
1712 INIT_PARAM(zero_copy, ""),
1713 INIT_PARAM(delay_copy, ""),
1714 INIT_PARAM(virtual_addr, "")
1715
1716 END_INIT_SIM_OBJECT_PARAMS_WNS(Sinic, SinicDevice)
1717
1718
1719 CREATE_SIM_OBJECT_WNS(Sinic, SinicDevice)
1720 {
1721 Sinic::Sinic::Device::Params *params = new Device::Params;
1722 params->name = getInstanceName();
1723 params->platform = platform;
1724 params->system = system;
1725 params->configData = configdata;
1726 params->busNum = pci_bus;
1727 params->deviceNum = pci_dev;
1728 params->functionNum = pci_func;
1729 params->pio_delay = pio_latency;
1730 params->config_delay = config_latency;
1731 params->intr_delay = intr_delay;
1732 params->clock = clock;
1733
1734 params->dma_read_delay = dma_read_delay;
1735 params->dma_read_factor = dma_read_factor;
1736 params->dma_write_delay = dma_write_delay;
1737 params->dma_write_factor = dma_write_factor;
1738
1739 params->tx_delay = tx_delay;
1740 params->rx_delay = rx_delay;
1741 params->rx_max_copy = rx_max_copy;
1742 params->tx_max_copy = tx_max_copy;
1743 params->rx_max_intr = rx_max_intr;
1744 params->rx_fifo_size = rx_fifo_size;
1745 params->tx_fifo_size = tx_fifo_size;
1746 params->rx_fifo_threshold = rx_fifo_threshold;
1747 params->rx_fifo_low_mark = rx_fifo_low_mark;
1748 params->tx_fifo_high_mark = tx_fifo_high_mark;
1749 params->tx_fifo_threshold = tx_fifo_threshold;
1750
1751 params->rx_filter = rx_filter;
1752 params->eaddr = hardware_address;
1753 params->rx_thread = rx_thread;
1754 params->tx_thread = tx_thread;
1755 params->rss = rss;
1756 params->virtual_count = virtual_count;
1757 params->zero_copy = zero_copy;
1758 params->delay_copy = delay_copy;
1759 params->virtual_addr = virtual_addr;
1760
1761 return new Sinic::Device(params);
1762 }
1763
1764 REGISTER_SIM_OBJECT_WNS(Sinic, "Sinic", SinicDevice)
1765