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