sinic.cc revision 2176
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 "targetarch/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 == MachineCheckFault) { 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 MachineCheckFault; 371 } 372 373 return fault; 374} 375 376Fault 377Device::readBar0(MemReqPtr &req, Addr daddr, uint8_t *data) 378{ 379 int cpu = (req->xc->regs.ipr[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 == MachineCheckFault) { 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 MachineCheckFault; 467 } 468 469 return fault; 470} 471 472Fault 473Device::writeBar0(MemReqPtr &req, Addr daddr, const uint8_t *data) 474{ 475 int cpu = (req->xc->regs.ipr[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, daddr, 499 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 regs.IntrMask = Intr_Soft | Intr_RxHigh | Intr_RxPacket | Intr_TxLow; 765 regs.RxMaxCopy = params()->rx_max_copy; 766 regs.TxMaxCopy = params()->tx_max_copy; 767 regs.RxMaxIntr = params()->rx_max_intr; 768 regs.RxFifoSize = params()->rx_fifo_size; 769 regs.TxFifoSize = params()->tx_fifo_size; 770 regs.RxFifoMark = params()->rx_fifo_threshold; 771 regs.TxFifoMark = params()->tx_fifo_threshold; 772 regs.HwAddr = params()->eaddr; 773 774 rxList.clear(); 775 txList.clear(); 776 777 rxState = rxIdle; 778 txState = txIdle; 779 780 rxFifo.clear(); 781 rxFifoPtr = rxFifo.end(); 782 txFifo.clear(); 783 rxEmpty = false; 784 txFull = false; 785 786 int size = virtualRegs.size(); 787 virtualRegs.clear(); 788 virtualRegs.resize(size); 789 for (int i = 0; i < size; ++i) 790 virtualRegs[i].rxPacket = rxFifo.end(); 791} 792 793void 794Device::rxDmaCopy() 795{ 796 assert(rxState == rxCopy); 797 rxState = rxCopyDone; 798 physmem->dma_write(rxDmaAddr, (uint8_t *)rxDmaData, rxDmaLen); 799 DPRINTF(EthernetDMA, "rx dma write paddr=%#x len=%d\n", 800 rxDmaAddr, rxDmaLen); 801 DDUMP(EthernetData, rxDmaData, rxDmaLen); 802} 803 804void 805Device::rxDmaDone() 806{ 807 rxDmaCopy(); 808 809 // If the transmit state machine has a pending DMA, let it go first 810 if (txState == txBeginCopy) 811 txKick(); 812 813 rxKick(); 814} 815 816void 817Device::rxKick() 818{ 819 VirtualReg *vnic; 820 821 DPRINTF(EthernetSM, "receive kick rxState=%s (rxFifo.size=%d)\n", 822 RxStateStrings[rxState], rxFifo.size()); 823 824 if (rxKickTick > curTick) { 825 DPRINTF(EthernetSM, "receive kick exiting, can't run till %d\n", 826 rxKickTick); 827 return; 828 } 829 830 next: 831 if (rxState == rxIdle) 832 goto exit; 833 834 assert(!rxList.empty()); 835 vnic = &virtualRegs[rxList.front()]; 836 837 DPRINTF(EthernetSM, "processing rxState=%s for virtual nic %d\n", 838 RxStateStrings[rxState], rxList.front()); 839 840 switch (rxState) { 841 case rxFifoBlock: 842 if (vnic->rxPacket != rxFifo.end()) { 843 rxState = rxBeginCopy; 844 break; 845 } 846 847 if (rxFifoPtr == rxFifo.end()) { 848 DPRINTF(EthernetSM, "receive waiting for data. Nothing to do.\n"); 849 goto exit; 850 } 851 852 assert(!rxFifo.empty()); 853 854 // Grab a new packet from the fifo. 855 vnic->rxPacket = rxFifoPtr++; 856 vnic->rxPacketOffset = 0; 857 vnic->rxPacketBytes = (*vnic->rxPacket)->length; 858 assert(vnic->rxPacketBytes); 859 860 vnic->rxDoneData = 0; 861 /* scope for variables */ { 862 IpPtr ip(*vnic->rxPacket); 863 if (ip) { 864 vnic->rxDoneData |= Regs::RxDone_IpPacket; 865 rxIpChecksums++; 866 if (cksum(ip) != 0) { 867 DPRINTF(EthernetCksum, "Rx IP Checksum Error\n"); 868 vnic->rxDoneData |= Regs::RxDone_IpError; 869 } 870 TcpPtr tcp(ip); 871 UdpPtr udp(ip); 872 if (tcp) { 873 vnic->rxDoneData |= Regs::RxDone_TcpPacket; 874 rxTcpChecksums++; 875 if (cksum(tcp) != 0) { 876 DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n"); 877 vnic->rxDoneData |= Regs::RxDone_TcpError; 878 } 879 } else if (udp) { 880 vnic->rxDoneData |= Regs::RxDone_UdpPacket; 881 rxUdpChecksums++; 882 if (cksum(udp) != 0) { 883 DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n"); 884 vnic->rxDoneData |= Regs::RxDone_UdpError; 885 } 886 } 887 } 888 } 889 rxState = rxBeginCopy; 890 break; 891 892 case rxBeginCopy: 893 if (dmaInterface && dmaInterface->busy()) 894 goto exit; 895 896 rxDmaAddr = plat->pciToDma(Regs::get_RxData_Addr(vnic->RxData)); 897 rxDmaLen = min<int>(Regs::get_RxData_Len(vnic->RxData), 898 vnic->rxPacketBytes); 899 rxDmaData = (*vnic->rxPacket)->data + vnic->rxPacketOffset; 900 rxState = rxCopy; 901 902 if (dmaInterface) { 903 dmaInterface->doDMA(WriteInvalidate, rxDmaAddr, rxDmaLen, 904 curTick, &rxDmaEvent, true); 905 goto exit; 906 } 907 908 if (dmaWriteDelay != 0 || dmaWriteFactor != 0) { 909 Tick factor = ((rxDmaLen + ULL(63)) >> ULL(6)) * dmaWriteFactor; 910 Tick start = curTick + dmaWriteDelay + factor; 911 rxDmaEvent.schedule(start); 912 goto exit; 913 } 914 915 rxDmaCopy(); 916 break; 917 918 case rxCopy: 919 DPRINTF(EthernetSM, "receive machine still copying\n"); 920 goto exit; 921 922 case rxCopyDone: 923 vnic->RxDone = vnic->rxDoneData | rxDmaLen; 924 vnic->RxDone |= Regs::RxDone_Complete; 925 926 if (vnic->rxPacketBytes == rxDmaLen) { 927 DPRINTF(EthernetSM, "rxKick: packet complete on vnic %d\n", 928 rxList.front()); 929 rxFifo.remove(vnic->rxPacket); 930 vnic->rxPacket = rxFifo.end(); 931 } else { 932 vnic->RxDone |= Regs::RxDone_More; 933 vnic->rxPacketBytes -= rxDmaLen; 934 vnic->rxPacketOffset += rxDmaLen; 935 DPRINTF(EthernetSM, 936 "rxKick: packet not complete on vnic %d: %d bytes left\n", 937 rxList.front(), vnic->rxPacketBytes); 938 } 939 940 rxList.pop_front(); 941 rxState = rxList.empty() ? rxIdle : rxFifoBlock; 942 943 if (rxFifo.empty()) { 944 devIntrPost(Regs::Intr_RxEmpty); 945 rxEmpty = true; 946 } 947 948 devIntrPost(Regs::Intr_RxDMA); 949 break; 950 951 default: 952 panic("Invalid rxState!"); 953 } 954 955 DPRINTF(EthernetSM, "entering next rxState=%s\n", 956 RxStateStrings[rxState]); 957 958 goto next; 959 960 exit: 961 /** 962 * @todo do we want to schedule a future kick? 963 */ 964 DPRINTF(EthernetSM, "rx state machine exited rxState=%s\n", 965 RxStateStrings[rxState]); 966} 967 968void 969Device::txDmaCopy() 970{ 971 assert(txState == txCopy); 972 txState = txCopyDone; 973 physmem->dma_read((uint8_t *)txDmaData, txDmaAddr, txDmaLen); 974 DPRINTF(EthernetDMA, "tx dma read paddr=%#x len=%d\n", 975 txDmaAddr, txDmaLen); 976 DDUMP(EthernetData, txDmaData, txDmaLen); 977} 978 979void 980Device::txDmaDone() 981{ 982 txDmaCopy(); 983 984 // If the receive state machine has a pending DMA, let it go first 985 if (rxState == rxBeginCopy) 986 rxKick(); 987 988 txKick(); 989} 990 991void 992Device::transmit() 993{ 994 if (txFifo.empty()) { 995 DPRINTF(Ethernet, "nothing to transmit\n"); 996 return; 997 } 998 999 uint32_t interrupts; 1000 PacketPtr packet = txFifo.front(); 1001 if (!interface->sendPacket(packet)) { 1002 DPRINTF(Ethernet, "Packet Transmit: failed txFifo available %d\n", 1003 txFifo.avail()); 1004 goto reschedule; 1005 } 1006 1007 txFifo.pop(); 1008#if TRACING_ON 1009 if (DTRACE(Ethernet)) { 1010 IpPtr ip(packet); 1011 if (ip) { 1012 DPRINTF(Ethernet, "ID is %d\n", ip->id()); 1013 TcpPtr tcp(ip); 1014 if (tcp) { 1015 DPRINTF(Ethernet, "Src Port=%d, Dest Port=%d\n", 1016 tcp->sport(), tcp->dport()); 1017 } 1018 } 1019 } 1020#endif 1021 1022 DDUMP(EthernetData, packet->data, packet->length); 1023 txBytes += packet->length; 1024 txPackets++; 1025 1026 DPRINTF(Ethernet, "Packet Transmit: successful txFifo Available %d\n", 1027 txFifo.avail()); 1028 1029 interrupts = Regs::Intr_TxPacket; 1030 if (txFifo.size() < regs.TxFifoMark) 1031 interrupts |= Regs::Intr_TxLow; 1032 devIntrPost(interrupts); 1033 1034 reschedule: 1035 if (!txFifo.empty() && !txEvent.scheduled()) { 1036 DPRINTF(Ethernet, "reschedule transmit\n"); 1037 txEvent.schedule(curTick + retryTime); 1038 } 1039} 1040 1041void 1042Device::txKick() 1043{ 1044 VirtualReg *vnic; 1045 DPRINTF(EthernetSM, "transmit kick txState=%s (txFifo.size=%d)\n", 1046 TxStateStrings[txState], txFifo.size()); 1047 1048 if (txKickTick > curTick) { 1049 DPRINTF(EthernetSM, "transmit kick exiting, can't run till %d\n", 1050 txKickTick); 1051 return; 1052 } 1053 1054 next: 1055 if (txState == txIdle) 1056 goto exit; 1057 1058 assert(!txList.empty()); 1059 vnic = &virtualRegs[txList.front()]; 1060 1061 switch (txState) { 1062 case txFifoBlock: 1063 assert(Regs::get_TxDone_Busy(vnic->TxData)); 1064 if (!txPacket) { 1065 // Grab a new packet from the fifo. 1066 txPacket = new PacketData(16384); 1067 txPacketOffset = 0; 1068 } 1069 1070 if (txFifo.avail() - txPacket->length < 1071 Regs::get_TxData_Len(vnic->TxData)) { 1072 DPRINTF(EthernetSM, "transmit fifo full. Nothing to do.\n"); 1073 goto exit; 1074 } 1075 1076 txState = txBeginCopy; 1077 break; 1078 1079 case txBeginCopy: 1080 if (dmaInterface && dmaInterface->busy()) 1081 goto exit; 1082 1083 txDmaAddr = plat->pciToDma(Regs::get_TxData_Addr(vnic->TxData)); 1084 txDmaLen = Regs::get_TxData_Len(vnic->TxData); 1085 txDmaData = txPacket->data + txPacketOffset; 1086 txState = txCopy; 1087 1088 if (dmaInterface) { 1089 dmaInterface->doDMA(Read, txDmaAddr, txDmaLen, 1090 curTick, &txDmaEvent, true); 1091 goto exit; 1092 } 1093 1094 if (dmaReadDelay != 0 || dmaReadFactor != 0) { 1095 Tick factor = ((txDmaLen + ULL(63)) >> ULL(6)) * dmaReadFactor; 1096 Tick start = curTick + dmaReadDelay + factor; 1097 txDmaEvent.schedule(start); 1098 goto exit; 1099 } 1100 1101 txDmaCopy(); 1102 break; 1103 1104 case txCopy: 1105 DPRINTF(EthernetSM, "transmit machine still copying\n"); 1106 goto exit; 1107 1108 case txCopyDone: 1109 vnic->TxDone = txDmaLen | Regs::TxDone_Complete; 1110 txPacket->length += txDmaLen; 1111 if ((vnic->TxData & Regs::TxData_More)) { 1112 txPacketOffset += txDmaLen; 1113 txState = txIdle; 1114 devIntrPost(Regs::Intr_TxDMA); 1115 break; 1116 } 1117 1118 assert(txPacket->length <= txFifo.avail()); 1119 if ((vnic->TxData & Regs::TxData_Checksum)) { 1120 IpPtr ip(txPacket); 1121 if (ip) { 1122 TcpPtr tcp(ip); 1123 if (tcp) { 1124 tcp->sum(0); 1125 tcp->sum(cksum(tcp)); 1126 txTcpChecksums++; 1127 } 1128 1129 UdpPtr udp(ip); 1130 if (udp) { 1131 udp->sum(0); 1132 udp->sum(cksum(udp)); 1133 txUdpChecksums++; 1134 } 1135 1136 ip->sum(0); 1137 ip->sum(cksum(ip)); 1138 txIpChecksums++; 1139 } 1140 } 1141 1142 txFifo.push(txPacket); 1143 if (txFifo.avail() < regs.TxMaxCopy) { 1144 devIntrPost(Regs::Intr_TxFull); 1145 txFull = true; 1146 } 1147 txPacket = 0; 1148 transmit(); 1149 txList.pop_front(); 1150 txState = txList.empty() ? txIdle : txFifoBlock; 1151 devIntrPost(Regs::Intr_TxDMA); 1152 break; 1153 1154 default: 1155 panic("Invalid txState!"); 1156 } 1157 1158 DPRINTF(EthernetSM, "entering next txState=%s\n", 1159 TxStateStrings[txState]); 1160 1161 goto next; 1162 1163 exit: 1164 /** 1165 * @todo do we want to schedule a future kick? 1166 */ 1167 DPRINTF(EthernetSM, "tx state machine exited txState=%s\n", 1168 TxStateStrings[txState]); 1169} 1170 1171void 1172Device::transferDone() 1173{ 1174 if (txFifo.empty()) { 1175 DPRINTF(Ethernet, "transfer complete: txFifo empty...nothing to do\n"); 1176 return; 1177 } 1178 1179 DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n"); 1180 1181 if (txEvent.scheduled()) 1182 txEvent.reschedule(curTick + cycles(1)); 1183 else 1184 txEvent.schedule(curTick + cycles(1)); 1185} 1186 1187bool 1188Device::rxFilter(const PacketPtr &packet) 1189{ 1190 if (!Regs::get_Config_Filter(regs.Config)) 1191 return false; 1192 1193 panic("receive filter not implemented\n"); 1194 bool drop = true; 1195 1196#if 0 1197 string type; 1198 1199 EthHdr *eth = packet->eth(); 1200 if (eth->unicast()) { 1201 // If we're accepting all unicast addresses 1202 if (acceptUnicast) 1203 drop = false; 1204 1205 // If we make a perfect match 1206 if (acceptPerfect && params->eaddr == eth.dst()) 1207 drop = false; 1208 1209 if (acceptArp && eth->type() == ETH_TYPE_ARP) 1210 drop = false; 1211 1212 } else if (eth->broadcast()) { 1213 // if we're accepting broadcasts 1214 if (acceptBroadcast) 1215 drop = false; 1216 1217 } else if (eth->multicast()) { 1218 // if we're accepting all multicasts 1219 if (acceptMulticast) 1220 drop = false; 1221 1222 } 1223 1224 if (drop) { 1225 DPRINTF(Ethernet, "rxFilter drop\n"); 1226 DDUMP(EthernetData, packet->data, packet->length); 1227 } 1228#endif 1229 return drop; 1230} 1231 1232bool 1233Device::recvPacket(PacketPtr packet) 1234{ 1235 rxBytes += packet->length; 1236 rxPackets++; 1237 1238 DPRINTF(Ethernet, "Receiving packet from wire, rxFifo Available is %d\n", 1239 rxFifo.avail()); 1240 1241 if (!rxEnable) { 1242 DPRINTF(Ethernet, "receive disabled...packet dropped\n"); 1243 return true; 1244 } 1245 1246 if (rxFilter(packet)) { 1247 DPRINTF(Ethernet, "packet filtered...dropped\n"); 1248 return true; 1249 } 1250 1251 if (rxFifo.size() >= regs.RxFifoMark) 1252 devIntrPost(Regs::Intr_RxHigh); 1253 1254 if (!rxFifo.push(packet)) { 1255 DPRINTF(Ethernet, 1256 "packet will not fit in receive buffer...packet dropped\n"); 1257 return false; 1258 } 1259 1260 // If we were at the last element, back up one ot go to the new 1261 // last element of the list. 1262 if (rxFifoPtr == rxFifo.end()) 1263 --rxFifoPtr; 1264 1265 devIntrPost(Regs::Intr_RxPacket); 1266 rxKick(); 1267 return true; 1268} 1269 1270//===================================================================== 1271// 1272// 1273void 1274Base::serialize(ostream &os) 1275{ 1276 // Serialize the PciDev base class 1277 PciDev::serialize(os); 1278 1279 SERIALIZE_SCALAR(rxEnable); 1280 SERIALIZE_SCALAR(txEnable); 1281 SERIALIZE_SCALAR(cpuIntrEnable); 1282 1283 /* 1284 * Keep track of pending interrupt status. 1285 */ 1286 SERIALIZE_SCALAR(intrTick); 1287 SERIALIZE_SCALAR(cpuPendingIntr); 1288 Tick intrEventTick = 0; 1289 if (intrEvent) 1290 intrEventTick = intrEvent->when(); 1291 SERIALIZE_SCALAR(intrEventTick); 1292} 1293 1294void 1295Base::unserialize(Checkpoint *cp, const std::string §ion) 1296{ 1297 // Unserialize the PciDev base class 1298 PciDev::unserialize(cp, section); 1299 1300 UNSERIALIZE_SCALAR(rxEnable); 1301 UNSERIALIZE_SCALAR(txEnable); 1302 UNSERIALIZE_SCALAR(cpuIntrEnable); 1303 1304 /* 1305 * Keep track of pending interrupt status. 1306 */ 1307 UNSERIALIZE_SCALAR(intrTick); 1308 UNSERIALIZE_SCALAR(cpuPendingIntr); 1309 Tick intrEventTick; 1310 UNSERIALIZE_SCALAR(intrEventTick); 1311 if (intrEventTick) { 1312 intrEvent = new IntrEvent(this, true); 1313 intrEvent->schedule(intrEventTick); 1314 } 1315} 1316 1317void 1318Device::serialize(ostream &os) 1319{ 1320 // Serialize the PciDev base class 1321 Base::serialize(os); 1322 1323 if (rxState == rxCopy) 1324 panic("can't serialize with an in flight dma request rxState=%s", 1325 RxStateStrings[rxState]); 1326 1327 if (txState == txCopy) 1328 panic("can't serialize with an in flight dma request txState=%s", 1329 TxStateStrings[txState]); 1330 1331 /* 1332 * Serialize the device registers 1333 */ 1334 SERIALIZE_SCALAR(regs.Config); 1335 SERIALIZE_SCALAR(regs.IntrStatus); 1336 SERIALIZE_SCALAR(regs.IntrMask); 1337 SERIALIZE_SCALAR(regs.RxMaxCopy); 1338 SERIALIZE_SCALAR(regs.TxMaxCopy); 1339 SERIALIZE_SCALAR(regs.RxMaxIntr); 1340 SERIALIZE_SCALAR(regs.RxData); 1341 SERIALIZE_SCALAR(regs.RxDone); 1342 SERIALIZE_SCALAR(regs.TxData); 1343 SERIALIZE_SCALAR(regs.TxDone); 1344 1345 /* 1346 * Serialize the virtual nic state 1347 */ 1348 int virtualRegsSize = virtualRegs.size(); 1349 SERIALIZE_SCALAR(virtualRegsSize); 1350 for (int i = 0; i < virtualRegsSize; ++i) { 1351 VirtualReg *vnic = &virtualRegs[i]; 1352 1353 string reg = csprintf("vnic%d", i); 1354 paramOut(os, reg + ".RxData", vnic->RxData); 1355 paramOut(os, reg + ".RxDone", vnic->RxDone); 1356 paramOut(os, reg + ".TxData", vnic->TxData); 1357 paramOut(os, reg + ".TxDone", vnic->TxDone); 1358 1359 PacketFifo::iterator rxFifoPtr; 1360 1361 bool rxPacketExists = vnic->rxPacket != rxFifo.end(); 1362 paramOut(os, reg + ".rxPacketExists", rxPacketExists); 1363 if (rxPacketExists) { 1364 int rxPacket = 0; 1365 PacketFifo::iterator i = rxFifo.begin(); 1366 while (i != vnic->rxPacket) { 1367 assert(i != rxFifo.end()); 1368 ++i; 1369 ++rxPacket; 1370 } 1371 1372 paramOut(os, reg + ".rxPacket", rxPacket); 1373 paramOut(os, reg + ".rxPacketOffset", vnic->rxPacketOffset); 1374 paramOut(os, reg + ".rxPacketBytes", vnic->rxPacketBytes); 1375 } 1376 paramOut(os, reg + ".rxDoneData", vnic->rxDoneData); 1377 } 1378 1379 VirtualList::iterator i, end; 1380 int count; 1381 1382 int rxListSize = rxList.size(); 1383 SERIALIZE_SCALAR(rxListSize); 1384 for (count = 0, i = rxList.begin(), end = rxList.end(); i != end; ++i) 1385 paramOut(os, csprintf("rxList%d", count++), *i); 1386 1387 int txListSize = txList.size(); 1388 SERIALIZE_SCALAR(txListSize); 1389 for (count = 0, i = txList.begin(), end = txList.end(); i != end; ++i) 1390 paramOut(os, csprintf("txList%d", count++), *i); 1391 1392 /* 1393 * Serialize rx state machine 1394 */ 1395 int rxState = this->rxState; 1396 SERIALIZE_SCALAR(rxState); 1397 SERIALIZE_SCALAR(rxEmpty); 1398 rxFifo.serialize("rxFifo", os); 1399 1400 /* 1401 * Serialize tx state machine 1402 */ 1403 int txState = this->txState; 1404 SERIALIZE_SCALAR(txState); 1405 SERIALIZE_SCALAR(txFull); 1406 txFifo.serialize("txFifo", os); 1407 bool txPacketExists = txPacket; 1408 SERIALIZE_SCALAR(txPacketExists); 1409 if (txPacketExists) { 1410 txPacket->serialize("txPacket", os); 1411 SERIALIZE_SCALAR(txPacketOffset); 1412 SERIALIZE_SCALAR(txPacketBytes); 1413 } 1414 1415 /* 1416 * If there's a pending transmit, store the time so we can 1417 * reschedule it later 1418 */ 1419 Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick : 0; 1420 SERIALIZE_SCALAR(transmitTick); 1421} 1422 1423void 1424Device::unserialize(Checkpoint *cp, const std::string §ion) 1425{ 1426 // Unserialize the PciDev base class 1427 Base::unserialize(cp, section); 1428 1429 /* 1430 * Unserialize the device registers 1431 */ 1432 UNSERIALIZE_SCALAR(regs.Config); 1433 UNSERIALIZE_SCALAR(regs.IntrStatus); 1434 UNSERIALIZE_SCALAR(regs.IntrMask); 1435 UNSERIALIZE_SCALAR(regs.RxMaxCopy); 1436 UNSERIALIZE_SCALAR(regs.TxMaxCopy); 1437 UNSERIALIZE_SCALAR(regs.RxMaxIntr); 1438 UNSERIALIZE_SCALAR(regs.RxData); 1439 UNSERIALIZE_SCALAR(regs.RxDone); 1440 UNSERIALIZE_SCALAR(regs.TxData); 1441 UNSERIALIZE_SCALAR(regs.TxDone); 1442 1443 int rxListSize; 1444 UNSERIALIZE_SCALAR(rxListSize); 1445 rxList.clear(); 1446 for (int i = 0; i < rxListSize; ++i) { 1447 int value; 1448 paramIn(cp, section, csprintf("rxList%d", i), value); 1449 rxList.push_back(value); 1450 } 1451 1452 int txListSize; 1453 UNSERIALIZE_SCALAR(txListSize); 1454 txList.clear(); 1455 for (int i = 0; i < txListSize; ++i) { 1456 int value; 1457 paramIn(cp, section, csprintf("txList%d", i), value); 1458 txList.push_back(value); 1459 } 1460 1461 /* 1462 * Unserialize rx state machine 1463 */ 1464 int rxState; 1465 UNSERIALIZE_SCALAR(rxState); 1466 UNSERIALIZE_SCALAR(rxEmpty); 1467 this->rxState = (RxState) rxState; 1468 rxFifo.unserialize("rxFifo", cp, section); 1469 1470 /* 1471 * Unserialize tx state machine 1472 */ 1473 int txState; 1474 UNSERIALIZE_SCALAR(txState); 1475 UNSERIALIZE_SCALAR(txFull); 1476 this->txState = (TxState) txState; 1477 txFifo.unserialize("txFifo", cp, section); 1478 bool txPacketExists; 1479 UNSERIALIZE_SCALAR(txPacketExists); 1480 txPacket = 0; 1481 if (txPacketExists) { 1482 txPacket = new PacketData(16384); 1483 txPacket->unserialize("txPacket", cp, section); 1484 UNSERIALIZE_SCALAR(txPacketOffset); 1485 UNSERIALIZE_SCALAR(txPacketBytes); 1486 } 1487 1488 /* 1489 * unserialize the virtual nic registers/state 1490 * 1491 * this must be done after the unserialization of the rxFifo 1492 * because the packet iterators depend on the fifo being populated 1493 */ 1494 int virtualRegsSize; 1495 UNSERIALIZE_SCALAR(virtualRegsSize); 1496 virtualRegs.clear(); 1497 virtualRegs.resize(virtualRegsSize); 1498 for (int i = 0; i < virtualRegsSize; ++i) { 1499 VirtualReg *vnic = &virtualRegs[i]; 1500 string reg = csprintf("vnic%d", i); 1501 1502 paramIn(cp, section, reg + ".RxData", vnic->RxData); 1503 paramIn(cp, section, reg + ".RxDone", vnic->RxDone); 1504 paramIn(cp, section, reg + ".TxData", vnic->TxData); 1505 paramIn(cp, section, reg + ".TxDone", vnic->TxDone); 1506 1507 bool rxPacketExists; 1508 paramIn(cp, section, reg + ".rxPacketExists", rxPacketExists); 1509 if (rxPacketExists) { 1510 int rxPacket; 1511 paramIn(cp, section, reg + ".rxPacket", rxPacket); 1512 vnic->rxPacket = rxFifo.begin(); 1513 while (rxPacket--) 1514 ++vnic->rxPacket; 1515 1516 paramIn(cp, section, reg + ".rxPacketOffset", 1517 vnic->rxPacketOffset); 1518 paramIn(cp, section, reg + ".rxPacketBytes", vnic->rxPacketBytes); 1519 } else { 1520 vnic->rxPacket = rxFifo.end(); 1521 } 1522 paramIn(cp, section, reg + ".rxDoneData", vnic->rxDoneData); 1523 } 1524 1525 /* 1526 * If there's a pending transmit, reschedule it now 1527 */ 1528 Tick transmitTick; 1529 UNSERIALIZE_SCALAR(transmitTick); 1530 if (transmitTick) 1531 txEvent.schedule(curTick + transmitTick); 1532 1533 /* 1534 * re-add addrRanges to bus bridges 1535 */ 1536 if (pioInterface) { 1537 pioInterface->addAddrRange(RangeSize(BARAddrs[0], BARSize[0])); 1538 pioInterface->addAddrRange(RangeSize(BARAddrs[1], BARSize[1])); 1539 } 1540} 1541 1542Tick 1543Device::cacheAccess(MemReqPtr &req) 1544{ 1545 Addr daddr; 1546 int bar; 1547 if (!getBAR(req->paddr, daddr, bar)) 1548 panic("address does not map to a BAR pa=%#x va=%#x size=%d", 1549 req->paddr, req->vaddr, req->size); 1550 1551 DPRINTF(EthernetPIO, "timing %s to paddr=%#x bar=%d daddr=%#x\n", 1552 req->cmd.toString(), req->paddr, bar, daddr); 1553 1554 return curTick + pioLatency; 1555} 1556 1557BEGIN_DECLARE_SIM_OBJECT_PARAMS(Interface) 1558 1559 SimObjectParam<EtherInt *> peer; 1560 SimObjectParam<Device *> device; 1561 1562END_DECLARE_SIM_OBJECT_PARAMS(Interface) 1563 1564BEGIN_INIT_SIM_OBJECT_PARAMS(Interface) 1565 1566 INIT_PARAM_DFLT(peer, "peer interface", NULL), 1567 INIT_PARAM(device, "Ethernet device of this interface") 1568 1569END_INIT_SIM_OBJECT_PARAMS(Interface) 1570 1571CREATE_SIM_OBJECT(Interface) 1572{ 1573 Interface *dev_int = new Interface(getInstanceName(), device); 1574 1575 EtherInt *p = (EtherInt *)peer; 1576 if (p) { 1577 dev_int->setPeer(p); 1578 p->setPeer(dev_int); 1579 } 1580 1581 return dev_int; 1582} 1583 1584REGISTER_SIM_OBJECT("SinicInt", Interface) 1585 1586 1587BEGIN_DECLARE_SIM_OBJECT_PARAMS(Device) 1588 1589 Param<Tick> clock; 1590 1591 Param<Addr> addr; 1592 SimObjectParam<MemoryController *> mmu; 1593 SimObjectParam<PhysicalMemory *> physmem; 1594 SimObjectParam<PciConfigAll *> configspace; 1595 SimObjectParam<PciConfigData *> configdata; 1596 SimObjectParam<Platform *> platform; 1597 Param<uint32_t> pci_bus; 1598 Param<uint32_t> pci_dev; 1599 Param<uint32_t> pci_func; 1600 1601 SimObjectParam<HierParams *> hier; 1602 SimObjectParam<Bus*> pio_bus; 1603 SimObjectParam<Bus*> dma_bus; 1604 SimObjectParam<Bus*> payload_bus; 1605 Param<Tick> dma_read_delay; 1606 Param<Tick> dma_read_factor; 1607 Param<Tick> dma_write_delay; 1608 Param<Tick> dma_write_factor; 1609 Param<bool> dma_no_allocate; 1610 Param<Tick> pio_latency; 1611 Param<Tick> intr_delay; 1612 1613 Param<Tick> rx_delay; 1614 Param<Tick> tx_delay; 1615 Param<uint32_t> rx_max_copy; 1616 Param<uint32_t> tx_max_copy; 1617 Param<uint32_t> rx_max_intr; 1618 Param<uint32_t> rx_fifo_size; 1619 Param<uint32_t> tx_fifo_size; 1620 Param<uint32_t> rx_fifo_threshold; 1621 Param<uint32_t> tx_fifo_threshold; 1622 1623 Param<bool> rx_filter; 1624 Param<string> hardware_address; 1625 Param<bool> rx_thread; 1626 Param<bool> tx_thread; 1627 1628END_DECLARE_SIM_OBJECT_PARAMS(Device) 1629 1630BEGIN_INIT_SIM_OBJECT_PARAMS(Device) 1631 1632 INIT_PARAM(clock, "State machine cycle time"), 1633 1634 INIT_PARAM(addr, "Device Address"), 1635 INIT_PARAM(mmu, "Memory Controller"), 1636 INIT_PARAM(physmem, "Physical Memory"), 1637 INIT_PARAM(configspace, "PCI Configspace"), 1638 INIT_PARAM(configdata, "PCI Config data"), 1639 INIT_PARAM(platform, "Platform"), 1640 INIT_PARAM(pci_bus, "PCI bus"), 1641 INIT_PARAM(pci_dev, "PCI device number"), 1642 INIT_PARAM(pci_func, "PCI function code"), 1643 1644 INIT_PARAM(hier, "Hierarchy global variables"), 1645 INIT_PARAM(pio_bus, ""), 1646 INIT_PARAM(dma_bus, ""), 1647 INIT_PARAM(payload_bus, "The IO Bus to attach to for payload"), 1648 INIT_PARAM(dma_read_delay, "fixed delay for dma reads"), 1649 INIT_PARAM(dma_read_factor, "multiplier for dma reads"), 1650 INIT_PARAM(dma_write_delay, "fixed delay for dma writes"), 1651 INIT_PARAM(dma_write_factor, "multiplier for dma writes"), 1652 INIT_PARAM(dma_no_allocate, "Should we allocat on read in cache"), 1653 INIT_PARAM(pio_latency, "Programmed IO latency in bus cycles"), 1654 INIT_PARAM(intr_delay, "Interrupt Delay"), 1655 1656 INIT_PARAM(rx_delay, "Receive Delay"), 1657 INIT_PARAM(tx_delay, "Transmit Delay"), 1658 INIT_PARAM(rx_max_copy, "rx max copy"), 1659 INIT_PARAM(tx_max_copy, "rx max copy"), 1660 INIT_PARAM(rx_max_intr, "rx max intr"), 1661 INIT_PARAM(rx_fifo_size, "max size in bytes of rxFifo"), 1662 INIT_PARAM(tx_fifo_size, "max size in bytes of txFifo"), 1663 INIT_PARAM(rx_fifo_threshold, "max size in bytes of rxFifo"), 1664 INIT_PARAM(tx_fifo_threshold, "max size in bytes of txFifo"), 1665 1666 INIT_PARAM(rx_filter, "Enable Receive Filter"), 1667 INIT_PARAM(hardware_address, "Ethernet Hardware Address"), 1668 INIT_PARAM(rx_thread, ""), 1669 INIT_PARAM(tx_thread, "") 1670 1671END_INIT_SIM_OBJECT_PARAMS(Device) 1672 1673 1674CREATE_SIM_OBJECT(Device) 1675{ 1676 Device::Params *params = new Device::Params; 1677 1678 params->name = getInstanceName(); 1679 1680 params->clock = clock; 1681 1682 params->mmu = mmu; 1683 params->physmem = physmem; 1684 params->configSpace = configspace; 1685 params->configData = configdata; 1686 params->plat = platform; 1687 params->busNum = pci_bus; 1688 params->deviceNum = pci_dev; 1689 params->functionNum = pci_func; 1690 1691 params->hier = hier; 1692 params->pio_bus = pio_bus; 1693 params->header_bus = dma_bus; 1694 params->payload_bus = payload_bus; 1695 params->dma_read_delay = dma_read_delay; 1696 params->dma_read_factor = dma_read_factor; 1697 params->dma_write_delay = dma_write_delay; 1698 params->dma_write_factor = dma_write_factor; 1699 params->dma_no_allocate = dma_no_allocate; 1700 params->pio_latency = pio_latency; 1701 params->intr_delay = intr_delay; 1702 1703 params->tx_delay = tx_delay; 1704 params->rx_delay = rx_delay; 1705 params->rx_max_copy = rx_max_copy; 1706 params->tx_max_copy = tx_max_copy; 1707 params->rx_max_intr = rx_max_intr; 1708 params->rx_fifo_size = rx_fifo_size; 1709 params->tx_fifo_size = tx_fifo_size; 1710 params->rx_fifo_threshold = rx_fifo_threshold; 1711 params->tx_fifo_threshold = tx_fifo_threshold; 1712 1713 params->rx_filter = rx_filter; 1714 params->eaddr = hardware_address; 1715 params->rx_thread = rx_thread; 1716 params->tx_thread = tx_thread; 1717 1718 return new Device(params); 1719} 1720 1721REGISTER_SIM_OBJECT("Sinic", Device) 1722 1723/* namespace Sinic */ } 1724