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