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