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