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