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