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