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