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