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