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