sinic.cc revision 1817
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), cycleTime(p->cycle_time), 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->io_bus) { 97 pioInterface = newPioInterface(p->name, p->hier, p->io_bus, this, 98 &Device::cacheAccess); 99 100 pioLatency = p->pio_latency * p->io_bus->clockRate; 101 102 if (p->payload_bus) 103 dmaInterface = new DMAInterface<Bus>(p->name + ".dma", p->io_bus, 104 p->payload_bus, 1, 105 p->dma_no_allocate); 106 else 107 dmaInterface = new DMAInterface<Bus>(p->name + ".dma", p->io_bus, 108 p->io_bus, 1, 109 p->dma_no_allocate); 110 } else if (p->payload_bus) { 111 pioInterface = newPioInterface(p->name, p->hier, p->payload_bus, this, 112 &Device::cacheAccess); 113 114 pioLatency = p->pio_latency * p->payload_bus->clockRate; 115 116 dmaInterface = new DMAInterface<Bus>(p->name + ".dma", p->payload_bus, 117 p->payload_bus, 1, 118 p->dma_no_allocate); 119 } 120} 121 122Device::~Device() 123{} 124 125void 126Device::regStats() 127{ 128 rxBytes 129 .name(name() + ".rxBytes") 130 .desc("Bytes Received") 131 .prereq(rxBytes) 132 ; 133 134 rxBandwidth 135 .name(name() + ".rxBandwidth") 136 .desc("Receive Bandwidth (bits/s)") 137 .precision(0) 138 .prereq(rxBytes) 139 ; 140 141 rxPackets 142 .name(name() + ".rxPackets") 143 .desc("Number of Packets Received") 144 .prereq(rxBytes) 145 ; 146 147 rxPacketRate 148 .name(name() + ".rxPPS") 149 .desc("Packet Reception Rate (packets/s)") 150 .precision(0) 151 .prereq(rxBytes) 152 ; 153 154 rxIpPackets 155 .name(name() + ".rxIpPackets") 156 .desc("Number of IP Packets Received") 157 .prereq(rxBytes) 158 ; 159 160 rxTcpPackets 161 .name(name() + ".rxTcpPackets") 162 .desc("Number of Packets Received") 163 .prereq(rxBytes) 164 ; 165 166 rxUdpPackets 167 .name(name() + ".rxUdpPackets") 168 .desc("Number of UDP Packets Received") 169 .prereq(rxBytes) 170 ; 171 172 rxIpChecksums 173 .name(name() + ".rxIpChecksums") 174 .desc("Number of rx IP Checksums done by device") 175 .precision(0) 176 .prereq(rxBytes) 177 ; 178 179 rxTcpChecksums 180 .name(name() + ".rxTcpChecksums") 181 .desc("Number of rx TCP Checksums done by device") 182 .precision(0) 183 .prereq(rxBytes) 184 ; 185 186 rxUdpChecksums 187 .name(name() + ".rxUdpChecksums") 188 .desc("Number of rx UDP Checksums done by device") 189 .precision(0) 190 .prereq(rxBytes) 191 ; 192 193 totBandwidth 194 .name(name() + ".totBandwidth") 195 .desc("Total Bandwidth (bits/s)") 196 .precision(0) 197 .prereq(totBytes) 198 ; 199 200 totPackets 201 .name(name() + ".totPackets") 202 .desc("Total Packets") 203 .precision(0) 204 .prereq(totBytes) 205 ; 206 207 totBytes 208 .name(name() + ".totBytes") 209 .desc("Total Bytes") 210 .precision(0) 211 .prereq(totBytes) 212 ; 213 214 totPacketRate 215 .name(name() + ".totPPS") 216 .desc("Total Tranmission Rate (packets/s)") 217 .precision(0) 218 .prereq(totBytes) 219 ; 220 221 txBytes 222 .name(name() + ".txBytes") 223 .desc("Bytes Transmitted") 224 .prereq(txBytes) 225 ; 226 227 txBandwidth 228 .name(name() + ".txBandwidth") 229 .desc("Transmit Bandwidth (bits/s)") 230 .precision(0) 231 .prereq(txBytes) 232 ; 233 234 txPackets 235 .name(name() + ".txPackets") 236 .desc("Number of Packets Transmitted") 237 .prereq(txBytes) 238 ; 239 240 txPacketRate 241 .name(name() + ".txPPS") 242 .desc("Packet Tranmission Rate (packets/s)") 243 .precision(0) 244 .prereq(txBytes) 245 ; 246 247 txIpPackets 248 .name(name() + ".txIpPackets") 249 .desc("Number of IP Packets Transmitted") 250 .prereq(txBytes) 251 ; 252 253 txTcpPackets 254 .name(name() + ".txTcpPackets") 255 .desc("Number of TCP Packets Transmitted") 256 .prereq(txBytes) 257 ; 258 259 txUdpPackets 260 .name(name() + ".txUdpPackets") 261 .desc("Number of Packets Transmitted") 262 .prereq(txBytes) 263 ; 264 265 txIpChecksums 266 .name(name() + ".txIpChecksums") 267 .desc("Number of tx IP Checksums done by device") 268 .precision(0) 269 .prereq(txBytes) 270 ; 271 272 txTcpChecksums 273 .name(name() + ".txTcpChecksums") 274 .desc("Number of tx TCP Checksums done by device") 275 .precision(0) 276 .prereq(txBytes) 277 ; 278 279 txUdpChecksums 280 .name(name() + ".txUdpChecksums") 281 .desc("Number of tx UDP Checksums done by device") 282 .precision(0) 283 .prereq(txBytes) 284 ; 285 286 txBandwidth = txBytes * Stats::constant(8) / simSeconds; 287 rxBandwidth = rxBytes * Stats::constant(8) / simSeconds; 288 totBandwidth = txBandwidth + rxBandwidth; 289 totBytes = txBytes + rxBytes; 290 totPackets = txPackets + rxPackets; 291 txPacketRate = txPackets / simSeconds; 292 rxPacketRate = rxPackets / simSeconds; 293} 294 295/** 296 * This is to write to the PCI general configuration registers 297 */ 298void 299Device::writeConfig(int offset, int size, const uint8_t *data) 300{ 301 switch (offset) { 302 case PCI0_BASE_ADDR0: 303 // Need to catch writes to BARs to update the PIO interface 304 PciDev::writeConfig(offset, size, data); 305 if (BARAddrs[0] != 0) { 306 if (pioInterface) 307 pioInterface->addAddrRange(RangeSize(BARAddrs[0], BARSize[0])); 308 309 BARAddrs[0] &= EV5::PAddrUncachedMask; 310 } 311 break; 312 313 default: 314 PciDev::writeConfig(offset, size, data); 315 } 316} 317 318/** 319 * This reads the device registers, which are detailed in the NS83820 320 * spec sheet 321 */ 322Fault 323Device::read(MemReqPtr &req, uint8_t *data) 324{ 325 assert(config.command & PCI_CMD_MSE); 326 327 //The mask is to give you only the offset into the device register file 328 Addr daddr = req->paddr & 0xfff; 329 330 if (Regs::regSize(daddr) == 0) 331 panic("invalid address: da=%#x pa=%#x va=%#x size=%d", 332 daddr, req->paddr, req->vaddr, req->size); 333 334 if (req->size != Regs::regSize(daddr)) 335 panic("invalid size for reg %s: da=%#x pa=%#x va=%#x size=%d", 336 Regs::regName(daddr), daddr, req->paddr, req->vaddr, req->size); 337 338 DPRINTF(EthernetPIO, "read reg=%s da=%#x pa=%#x va=%#x size=%d\n", 339 Regs::regName(daddr), daddr, req->paddr, req->vaddr, req->size); 340 341 uint32_t ®32 = *(uint32_t *)data; 342 uint64_t ®64 = *(uint64_t *)data; 343 344 switch (daddr) { 345 case Regs::Config: 346 reg32 = regs.Config; 347 break; 348 349 case Regs::RxMaxCopy: 350 reg32 = regs.RxMaxCopy; 351 break; 352 353 case Regs::TxMaxCopy: 354 reg32 = regs.TxMaxCopy; 355 break; 356 357 case Regs::RxThreshold: 358 reg32 = regs.RxThreshold; 359 break; 360 361 case Regs::TxThreshold: 362 reg32 = regs.TxThreshold; 363 break; 364 365 case Regs::IntrStatus: 366 reg32 = regs.IntrStatus; 367 devIntrClear(); 368 break; 369 370 case Regs::IntrMask: 371 reg32 = regs.IntrMask; 372 break; 373 374 case Regs::RxData: 375 reg64 = regs.RxData; 376 break; 377 378 case Regs::RxDone: 379 case Regs::RxWait: 380 reg64 = Regs::set_RxDone_FifoLen(regs.RxDone, 381 min(rxFifo.packets(), 255)); 382 break; 383 384 case Regs::TxData: 385 reg64 = regs.TxData; 386 break; 387 388 case Regs::TxDone: 389 case Regs::TxWait: 390 reg64 = Regs::set_TxDone_FifoLen(regs.TxDone, 391 min(txFifo.packets(), 255)); 392 break; 393 394 case Regs::HwAddr: 395 reg64 = params()->eaddr; 396 break; 397 398 default: 399 panic("reading write only register %s: da=%#x pa=%#x va=%#x size=%d", 400 Regs::regName(daddr), daddr, req->paddr, req->vaddr, req->size); 401 } 402 403 DPRINTF(EthernetPIO, "read reg=%s done val=%#x\n", Regs::regName(daddr), 404 Regs::regSize(daddr) == 4 ? reg32 : reg64); 405 406 return No_Fault; 407} 408 409Fault 410Device::write(MemReqPtr &req, const uint8_t *data) 411{ 412 assert(config.command & PCI_CMD_MSE); 413 Addr daddr = req->paddr & 0xfff; 414 415 if (Regs::regSize(daddr) == 0) 416 panic("invalid address: da=%#x pa=%#x va=%#x size=%d", 417 daddr, req->paddr, req->vaddr, req->size); 418 419 if (req->size != Regs::regSize(daddr)) 420 panic("invalid size: reg=%s da=%#x pa=%#x va=%#x size=%d", 421 Regs::regName(daddr), daddr, req->paddr, req->vaddr, req->size); 422 423 uint32_t reg32 = *(uint32_t *)data; 424 uint64_t reg64 = *(uint64_t *)data; 425 426 DPRINTF(EthernetPIO, "write reg=%s val=%#x da=%#x pa=%#x va=%#x size=%d\n", 427 Regs::regName(daddr), Regs::regSize(daddr) == 4 ? reg32 : reg64, 428 daddr, req->paddr, req->vaddr, req->size); 429 430 431 switch (daddr) { 432 case Regs::Config: 433 changeConfig(reg32); 434 break; 435 436 case Regs::RxThreshold: 437 regs.RxThreshold = reg32; 438 break; 439 440 case Regs::TxThreshold: 441 regs.TxThreshold = reg32; 442 break; 443 444 case Regs::IntrMask: 445 devIntrChangeMask(reg32); 446 break; 447 448 case Regs::RxData: 449 if (rxState != rxIdle) 450 panic("receive machine busy with another request!"); 451 452 regs.RxDone = 0; 453 regs.RxData = reg64; 454 if (rxEnable) { 455 rxState = rxFifoBlock; 456 rxKick(); 457 } 458 break; 459 460 case Regs::TxData: 461 if (txState != txIdle) 462 panic("transmit machine busy with another request!"); 463 464 regs.TxDone = 0; 465 regs.TxData = reg64; 466 if (txEnable) { 467 txState = txFifoBlock; 468 txKick(); 469 } 470 break; 471 472 default: 473 panic("writing read only register %s: da=%#x pa=%#x va=%#x size=%d", 474 Regs::regName(daddr), daddr, req->paddr, req->vaddr, req->size); 475 } 476 477 return No_Fault; 478} 479 480void 481Device::devIntrPost(uint32_t interrupts) 482{ 483 if ((interrupts & Regs::Intr_Res)) 484 panic("Cannot set a reserved interrupt"); 485 486 regs.IntrStatus |= interrupts; 487 488 DPRINTF(EthernetIntr, 489 "interrupt written to intStatus: intr=%#x status=%#x mask=%#x\n", 490 interrupts, regs.IntrStatus, regs.IntrMask); 491 492 if ((regs.IntrStatus & regs.IntrMask)) { 493 Tick when = curTick; 494 if ((regs.IntrStatus & regs.IntrMask & Regs::Intr_NoDelay) == 0) 495 when += intrDelay; 496 cpuIntrPost(when); 497 } 498} 499 500void 501Device::devIntrClear(uint32_t interrupts) 502{ 503 if ((interrupts & Regs::Intr_Res)) 504 panic("Cannot clear a reserved interrupt"); 505 506 regs.IntrStatus &= ~interrupts; 507 508 DPRINTF(EthernetIntr, 509 "interrupt cleared from intStatus: intr=%x status=%x mask=%x\n", 510 interrupts, regs.IntrStatus, regs.IntrMask); 511 512 if (!(regs.IntrStatus & regs.IntrMask)) 513 cpuIntrClear(); 514} 515 516void 517Device::devIntrChangeMask(uint32_t newmask) 518{ 519 if (regs.IntrMask == newmask) 520 return; 521 522 regs.IntrMask = newmask; 523 524 DPRINTF(EthernetIntr, 525 "interrupt mask changed: intStatus=%x intMask=%x masked=%x\n", 526 regs.IntrStatus, regs.IntrMask, regs.IntrStatus & regs.IntrMask); 527 528 if (regs.IntrStatus & regs.IntrMask) 529 cpuIntrPost(curTick); 530 else 531 cpuIntrClear(); 532} 533 534void 535Base::cpuIntrPost(Tick when) 536{ 537 // If the interrupt you want to post is later than an interrupt 538 // already scheduled, just let it post in the coming one and don't 539 // schedule another. 540 // HOWEVER, must be sure that the scheduled intrTick is in the 541 // future (this was formerly the source of a bug) 542 /** 543 * @todo this warning should be removed and the intrTick code should 544 * be fixed. 545 */ 546 assert(when >= curTick); 547 assert(intrTick >= curTick || intrTick == 0); 548 if (!cpuIntrEnable) { 549 DPRINTF(EthernetIntr, "interrupts not enabled.\n", 550 intrTick); 551 return; 552 } 553 554 if (when > intrTick && intrTick != 0) { 555 DPRINTF(EthernetIntr, "don't need to schedule event...intrTick=%d\n", 556 intrTick); 557 return; 558 } 559 560 intrTick = when; 561 if (intrTick < curTick) { 562 debug_break(); 563 intrTick = curTick; 564 } 565 566 DPRINTF(EthernetIntr, "going to schedule an interrupt for intrTick=%d\n", 567 intrTick); 568 569 if (intrEvent) 570 intrEvent->squash(); 571 intrEvent = new IntrEvent(this, true); 572 intrEvent->schedule(intrTick); 573} 574 575void 576Base::cpuInterrupt() 577{ 578 assert(intrTick == curTick); 579 580 // Whether or not there's a pending interrupt, we don't care about 581 // it anymore 582 intrEvent = 0; 583 intrTick = 0; 584 585 // Don't send an interrupt if there's already one 586 if (cpuPendingIntr) { 587 DPRINTF(EthernetIntr, 588 "would send an interrupt now, but there's already pending\n"); 589 } else { 590 // Send interrupt 591 cpuPendingIntr = true; 592 593 DPRINTF(EthernetIntr, "posting interrupt\n"); 594 intrPost(); 595 } 596} 597 598void 599Base::cpuIntrClear() 600{ 601 if (!cpuPendingIntr) 602 return; 603 604 if (intrEvent) { 605 intrEvent->squash(); 606 intrEvent = 0; 607 } 608 609 intrTick = 0; 610 611 cpuPendingIntr = false; 612 613 DPRINTF(EthernetIntr, "clearing cchip interrupt\n"); 614 intrClear(); 615} 616 617bool 618Base::cpuIntrPending() const 619{ return cpuPendingIntr; } 620 621void 622Device::changeConfig(uint32_t newconf) 623{ 624 uint32_t changed = regs.Config ^ newconf; 625 if (!changed) 626 return; 627 628 regs.Config = newconf; 629 630 if ((changed & Regs::Config_Reset)) { 631 assert(regs.Config & Regs::Config_Reset); 632 reset(); 633 regs.Config &= ~Regs::Config_Reset; 634 } 635 636 if ((changed & Regs::Config_IntEn)) { 637 cpuIntrEnable = regs.Config & Regs::Config_IntEn; 638 if (cpuIntrEnable) { 639 if (regs.IntrStatus & regs.IntrMask) 640 cpuIntrPost(curTick); 641 } else { 642 cpuIntrClear(); 643 } 644 } 645 646 if ((changed & Regs::Config_TxEn)) { 647 txEnable = regs.Config & Regs::Config_TxEn; 648 if (txEnable) 649 txKick(); 650 } 651 652 if ((changed & Regs::Config_RxEn)) { 653 rxEnable = regs.Config & Regs::Config_RxEn; 654 if (rxEnable) 655 rxKick(); 656 } 657} 658 659void 660Device::reset() 661{ 662 using namespace Regs; 663 memset(®s, 0, sizeof(regs)); 664 regs.RxMaxCopy = params()->rx_max_copy; 665 regs.TxMaxCopy = params()->tx_max_copy; 666 regs.IntrMask = Intr_TxFifo | Intr_RxFifo | Intr_RxData; 667 668 rxState = rxIdle; 669 txState = txIdle; 670 671 rxFifo.clear(); 672 txFifo.clear(); 673} 674 675void 676Device::rxDmaCopy() 677{ 678 assert(rxState == rxCopy); 679 rxState = rxCopyDone; 680 physmem->dma_write(rxDmaAddr, (uint8_t *)rxDmaData, rxDmaLen); 681 DPRINTF(EthernetDMA, "rx dma write paddr=%#x len=%d\n", 682 rxDmaAddr, rxDmaLen); 683 DDUMP(EthernetDMA, rxDmaData, rxDmaLen); 684} 685 686void 687Device::rxDmaDone() 688{ 689 rxDmaCopy(); 690 rxKick(); 691} 692 693void 694Device::rxKick() 695{ 696 DPRINTF(EthernetSM, "receive kick rxState=%s (rxFifo.size=%d)\n", 697 RxStateStrings[rxState], rxFifo.size()); 698 699 if (rxKickTick > curTick) { 700 DPRINTF(EthernetSM, "receive kick exiting, can't run till %d\n", 701 rxKickTick); 702 return; 703 } 704 705 next: 706 switch (rxState) { 707 case rxIdle: 708 if (rxPioRequest) { 709 pioInterface->respond(rxPioRequest, curTick); 710 rxPioRequest = 0; 711 } 712 goto exit; 713 714 case rxFifoBlock: 715 if (rxPacket) { 716 rxState = rxBeginCopy; 717 break; 718 } 719 720 if (rxFifo.empty()) { 721 DPRINTF(EthernetSM, "receive waiting for data. Nothing to do.\n"); 722 goto exit; 723 } 724 725 // Grab a new packet from the fifo. 726 rxPacket = rxFifo.front(); 727 rxPacketBufPtr = rxPacket->data; 728 rxPktBytes = rxPacket->length; 729 assert(rxPktBytes); 730 731 rxDoneData = 0; 732 /* scope for variables */ { 733 IpPtr ip(rxPacket); 734 if (ip) { 735 rxDoneData |= Regs::RxDone_IpPacket; 736 rxIpChecksums++; 737 if (cksum(ip) != 0) { 738 DPRINTF(EthernetCksum, "Rx IP Checksum Error\n"); 739 rxDoneData |= Regs::RxDone_IpError; 740 } 741 TcpPtr tcp(ip); 742 UdpPtr udp(ip); 743 if (tcp) { 744 rxDoneData |= Regs::RxDone_TcpPacket; 745 rxTcpChecksums++; 746 if (cksum(tcp) != 0) { 747 DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n"); 748 rxDoneData |= Regs::RxDone_TcpError; 749 } 750 } else if (udp) { 751 rxDoneData |= Regs::RxDone_UdpPacket; 752 rxUdpChecksums++; 753 if (cksum(udp) != 0) { 754 DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n"); 755 rxDoneData |= Regs::RxDone_UdpError; 756 } 757 } 758 } 759 } 760 rxState = rxBeginCopy; 761 break; 762 763 case rxBeginCopy: 764 rxDmaAddr = plat->pciToDma(Regs::get_RxData_Addr(regs.RxData)); 765 rxDmaLen = min<int>(Regs::get_RxData_Len(regs.RxData), rxPktBytes); 766 rxDmaData = rxPacketBufPtr; 767 768 if (dmaInterface) { 769 if (!dmaInterface->busy()) { 770 dmaInterface->doDMA(WriteInvalidate, rxDmaAddr, rxDmaLen, 771 curTick, &rxDmaEvent, true); 772 rxState = rxCopy; 773 } 774 goto exit; 775 } 776 777 rxState = rxCopy; 778 if (dmaWriteDelay != 0 || dmaWriteFactor != 0) { 779 Tick factor = ((rxDmaLen + ULL(63)) >> ULL(6)) * dmaWriteFactor; 780 Tick start = curTick + dmaWriteDelay + factor; 781 rxDmaEvent.schedule(start); 782 goto exit; 783 } 784 785 rxDmaCopy(); 786 break; 787 788 case rxCopy: 789 DPRINTF(EthernetSM, "receive machine still copying\n"); 790 goto exit; 791 792 case rxCopyDone: 793 regs.RxDone = rxDoneData | rxDmaLen; 794 795 if (rxPktBytes == rxDmaLen) { 796 rxPacket = NULL; 797 rxFifo.pop(); 798 } else { 799 regs.RxDone |= Regs::RxDone_More; 800 rxPktBytes -= rxDmaLen; 801 rxPacketBufPtr += rxDmaLen; 802 } 803 804 regs.RxDone |= Regs::RxDone_Complete; 805 devIntrPost(Regs::Intr_RxData); 806 rxState = rxIdle; 807 break; 808 809 default: 810 panic("Invalid rxState!"); 811 } 812 813 DPRINTF(EthernetSM, "entering next rxState=%s\n", 814 RxStateStrings[rxState]); 815 816 goto next; 817 818 exit: 819 /** 820 * @todo do we want to schedule a future kick? 821 */ 822 DPRINTF(EthernetSM, "rx state machine exited rxState=%s\n", 823 RxStateStrings[rxState]); 824} 825 826void 827Device::txDmaCopy() 828{ 829 assert(txState == txCopy); 830 txState = txCopyDone; 831 physmem->dma_read((uint8_t *)txDmaData, txDmaAddr, txDmaLen); 832 DPRINTF(EthernetDMA, "tx dma read paddr=%#x len=%d\n", 833 txDmaAddr, txDmaLen); 834 DDUMP(EthernetDMA, txDmaData, txDmaLen); 835} 836 837void 838Device::txDmaDone() 839{ 840 txDmaCopy(); 841 txKick(); 842} 843 844void 845Device::transmit() 846{ 847 if (txFifo.empty()) { 848 DPRINTF(Ethernet, "nothing to transmit\n"); 849 return; 850 } 851 852 PacketPtr packet = txFifo.front(); 853 if (!interface->sendPacket(packet)) { 854 DPRINTF(Ethernet, "Packet Transmit: failed txFifo available %d\n", 855 txFifo.avail()); 856 goto reschedule; 857 } 858 859 txFifo.pop(); 860 861#if TRACING_ON 862 if (DTRACE(Ethernet)) { 863 IpPtr ip(packet); 864 if (ip) { 865 DPRINTF(Ethernet, "ID is %d\n", ip->id()); 866 TcpPtr tcp(ip); 867 if (tcp) { 868 DPRINTF(Ethernet, "Src Port=%d, Dest Port=%d\n", 869 tcp->sport(), tcp->dport()); 870 } 871 } 872 } 873#endif 874 875 DDUMP(Ethernet, packet->data, packet->length); 876 txBytes += packet->length; 877 txPackets++; 878 879 DPRINTF(Ethernet, "Packet Transmit: successful txFifo Available %d\n", 880 txFifo.avail()); 881 882 if (txFifo.size() <= params()->tx_fifo_threshold) 883 devIntrPost(Regs::Intr_TxFifo); 884 885 devIntrPost(Regs::Intr_TxDone); 886 887 reschedule: 888 if (!txFifo.empty() && !txEvent.scheduled()) { 889 DPRINTF(Ethernet, "reschedule transmit\n"); 890 txEvent.schedule(curTick + retryTime); 891 } 892} 893 894void 895Device::txKick() 896{ 897 DPRINTF(EthernetSM, "transmit kick txState=%s (txFifo.size=%d)\n", 898 TxStateStrings[txState], txFifo.size()); 899 900 if (txKickTick > curTick) { 901 DPRINTF(EthernetSM, "transmit kick exiting, can't run till %d\n", 902 txKickTick); 903 return; 904 } 905 906 next: 907 switch (txState) { 908 case txIdle: 909 if (txPioRequest) { 910 pioInterface->respond(txPioRequest, curTick + pioLatency); 911 txPioRequest = 0; 912 } 913 goto exit; 914 915 case txFifoBlock: 916 if (!txPacket) { 917 // Grab a new packet from the fifo. 918 txPacket = new PacketData(16384); 919 txPacketBufPtr = txPacket->data; 920 } 921 922 if (txFifo.avail() - txPacket->length < 923 Regs::get_TxData_Len(regs.TxData)) { 924 DPRINTF(EthernetSM, "transmit fifo full. Nothing to do.\n"); 925 goto exit; 926 } 927 928 txState = txBeginCopy; 929 break; 930 931 case txBeginCopy: 932 txDmaAddr = plat->pciToDma(Regs::get_TxData_Addr(regs.TxData)); 933 txDmaLen = Regs::get_TxData_Len(regs.TxData); 934 txDmaData = txPacketBufPtr; 935 936 if (dmaInterface) { 937 if (!dmaInterface->busy()) { 938 dmaInterface->doDMA(Read, txDmaAddr, txDmaLen, 939 curTick, &txDmaEvent, true); 940 txState = txCopy; 941 } 942 943 goto exit; 944 } 945 946 txState = txCopy; 947 if (dmaReadDelay != 0 || dmaReadFactor != 0) { 948 Tick factor = ((txDmaLen + ULL(63)) >> ULL(6)) * dmaReadFactor; 949 Tick start = curTick + dmaReadDelay + factor; 950 txDmaEvent.schedule(start); 951 goto exit; 952 } 953 954 txDmaCopy(); 955 break; 956 957 case txCopy: 958 DPRINTF(EthernetSM, "transmit machine still copying\n"); 959 goto exit; 960 961 case txCopyDone: 962 txPacket->length += txDmaLen; 963 if ((regs.TxData & Regs::TxData_More)) { 964 txPacketBufPtr += txDmaLen; 965 } else { 966 assert(txPacket->length <= txFifo.avail()); 967 if ((regs.TxData & Regs::TxData_Checksum)) { 968 IpPtr ip(txPacket); 969 if (ip) { 970 TcpPtr tcp(ip); 971 if (tcp) { 972 tcp->sum(0); 973 tcp->sum(cksum(tcp)); 974 txTcpChecksums++; 975 } 976 977 UdpPtr udp(ip); 978 if (udp) { 979 udp->sum(0); 980 udp->sum(cksum(udp)); 981 txUdpChecksums++; 982 } 983 984 ip->sum(0); 985 ip->sum(cksum(ip)); 986 txIpChecksums++; 987 } 988 } 989 txFifo.push(txPacket); 990 txPacket = 0; 991 transmit(); 992 } 993 994 regs.TxDone = txDmaLen | Regs::TxDone_Complete; 995 devIntrPost(Regs::Intr_TxData); 996 txState = txIdle; 997 break; 998 999 default: 1000 panic("Invalid txState!"); 1001 } 1002 1003 DPRINTF(EthernetSM, "entering next txState=%s\n", 1004 TxStateStrings[txState]); 1005 1006 goto next; 1007 1008 exit: 1009 /** 1010 * @todo do we want to schedule a future kick? 1011 */ 1012 DPRINTF(EthernetSM, "tx state machine exited txState=%s\n", 1013 TxStateStrings[txState]); 1014} 1015 1016void 1017Device::transferDone() 1018{ 1019 if (txFifo.empty()) { 1020 DPRINTF(Ethernet, "transfer complete: txFifo empty...nothing to do\n"); 1021 return; 1022 } 1023 1024 DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n"); 1025 1026 if (txEvent.scheduled()) 1027 txEvent.reschedule(curTick + cycles(1)); 1028 else 1029 txEvent.schedule(curTick + cycles(1)); 1030} 1031 1032bool 1033Device::rxFilter(const PacketPtr &packet) 1034{ 1035 if (!Regs::get_Config_Filter(regs.Config)) 1036 return false; 1037 1038 panic("receive filter not implemented\n"); 1039 bool drop = true; 1040 1041#if 0 1042 string type; 1043 1044 EthHdr *eth = packet->eth(); 1045 if (eth->unicast()) { 1046 // If we're accepting all unicast addresses 1047 if (acceptUnicast) 1048 drop = false; 1049 1050 // If we make a perfect match 1051 if (acceptPerfect && params->eaddr == eth.dst()) 1052 drop = false; 1053 1054 if (acceptArp && eth->type() == ETH_TYPE_ARP) 1055 drop = false; 1056 1057 } else if (eth->broadcast()) { 1058 // if we're accepting broadcasts 1059 if (acceptBroadcast) 1060 drop = false; 1061 1062 } else if (eth->multicast()) { 1063 // if we're accepting all multicasts 1064 if (acceptMulticast) 1065 drop = false; 1066 1067 } 1068 1069 if (drop) { 1070 DPRINTF(Ethernet, "rxFilter drop\n"); 1071 DDUMP(EthernetData, packet->data, packet->length); 1072 } 1073#endif 1074 return drop; 1075} 1076 1077bool 1078Device::recvPacket(PacketPtr packet) 1079{ 1080 rxBytes += packet->length; 1081 rxPackets++; 1082 1083 DPRINTF(Ethernet, "Receiving packet from wire, rxFifo Available is %d\n", 1084 rxFifo.avail()); 1085 1086 if (!rxEnable) { 1087 DPRINTF(Ethernet, "receive disabled...packet dropped\n"); 1088 interface->recvDone(); 1089 return true; 1090 } 1091 1092 if (rxFilter(packet)) { 1093 DPRINTF(Ethernet, "packet filtered...dropped\n"); 1094 interface->recvDone(); 1095 return true; 1096 } 1097 1098 if (rxFifo.size() >= params()->rx_fifo_threshold) 1099 devIntrPost(Regs::Intr_RxFifo); 1100 1101 if (!rxFifo.push(packet)) { 1102 DPRINTF(Ethernet, 1103 "packet will not fit in receive buffer...packet dropped\n"); 1104 return false; 1105 } 1106 1107 interface->recvDone(); 1108 devIntrPost(Regs::Intr_RxDone); 1109 rxKick(); 1110 return true; 1111} 1112 1113//===================================================================== 1114// 1115// 1116void 1117Base::serialize(ostream &os) 1118{ 1119 // Serialize the PciDev base class 1120 PciDev::serialize(os); 1121 1122 SERIALIZE_SCALAR(rxEnable); 1123 SERIALIZE_SCALAR(txEnable); 1124 SERIALIZE_SCALAR(cpuIntrEnable); 1125 1126 /* 1127 * Keep track of pending interrupt status. 1128 */ 1129 SERIALIZE_SCALAR(intrTick); 1130 SERIALIZE_SCALAR(cpuPendingIntr); 1131 Tick intrEventTick = 0; 1132 if (intrEvent) 1133 intrEventTick = intrEvent->when(); 1134 SERIALIZE_SCALAR(intrEventTick); 1135} 1136 1137void 1138Base::unserialize(Checkpoint *cp, const std::string §ion) 1139{ 1140 // Unserialize the PciDev base class 1141 PciDev::unserialize(cp, section); 1142 1143 UNSERIALIZE_SCALAR(rxEnable); 1144 UNSERIALIZE_SCALAR(txEnable); 1145 UNSERIALIZE_SCALAR(cpuIntrEnable); 1146 1147 /* 1148 * Keep track of pending interrupt status. 1149 */ 1150 UNSERIALIZE_SCALAR(intrTick); 1151 UNSERIALIZE_SCALAR(cpuPendingIntr); 1152 Tick intrEventTick; 1153 UNSERIALIZE_SCALAR(intrEventTick); 1154 if (intrEventTick) { 1155 intrEvent = new IntrEvent(this, true); 1156 intrEvent->schedule(intrEventTick); 1157 } 1158} 1159 1160void 1161Device::serialize(ostream &os) 1162{ 1163 // Serialize the PciDev base class 1164 Base::serialize(os); 1165 1166 if (rxDmaEvent.scheduled()) 1167 rxDmaCopy(); 1168 1169 if (txDmaEvent.scheduled()) 1170 txDmaCopy(); 1171 1172 /* 1173 * Serialize the device registers 1174 */ 1175 SERIALIZE_SCALAR(regs.Config); 1176 SERIALIZE_SCALAR(regs.RxMaxCopy); 1177 SERIALIZE_SCALAR(regs.TxMaxCopy); 1178 SERIALIZE_SCALAR(regs.RxThreshold); 1179 SERIALIZE_SCALAR(regs.TxThreshold); 1180 SERIALIZE_SCALAR(regs.IntrStatus); 1181 SERIALIZE_SCALAR(regs.IntrMask); 1182 SERIALIZE_SCALAR(regs.RxData); 1183 SERIALIZE_SCALAR(regs.RxDone); 1184 SERIALIZE_SCALAR(regs.TxData); 1185 SERIALIZE_SCALAR(regs.TxDone); 1186 1187 /* 1188 * Serialize rx state machine 1189 */ 1190 int rxState = this->rxState; 1191 SERIALIZE_SCALAR(rxState); 1192 rxFifo.serialize("rxFifo", os); 1193 bool rxPacketExists = rxPacket; 1194 SERIALIZE_SCALAR(rxPacketExists); 1195 if (rxPacketExists) { 1196 rxPacket->serialize("rxPacket", os); 1197 uint32_t rxPktBufPtr = (uint32_t) (rxPacketBufPtr - rxPacket->data); 1198 SERIALIZE_SCALAR(rxPktBufPtr); 1199 SERIALIZE_SCALAR(rxPktBytes); 1200 } 1201 SERIALIZE_SCALAR(rxDoneData); 1202 1203 /* 1204 * Serialize tx state machine 1205 */ 1206 int txState = this->txState; 1207 SERIALIZE_SCALAR(txState); 1208 txFifo.serialize("txFifo", os); 1209 bool txPacketExists = txPacket; 1210 SERIALIZE_SCALAR(txPacketExists); 1211 if (txPacketExists) { 1212 txPacket->serialize("txPacket", os); 1213 uint32_t txPktBufPtr = (uint32_t) (txPacketBufPtr - txPacket->data); 1214 SERIALIZE_SCALAR(txPktBufPtr); 1215 SERIALIZE_SCALAR(txPktBytes); 1216 } 1217 1218 /* 1219 * If there's a pending transmit, store the time so we can 1220 * reschedule it later 1221 */ 1222 Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick : 0; 1223 SERIALIZE_SCALAR(transmitTick); 1224} 1225 1226void 1227Device::unserialize(Checkpoint *cp, const std::string §ion) 1228{ 1229 // Unserialize the PciDev base class 1230 Base::unserialize(cp, section); 1231 1232 /* 1233 * Unserialize the device registers 1234 */ 1235 UNSERIALIZE_SCALAR(regs.Config); 1236 UNSERIALIZE_SCALAR(regs.RxMaxCopy); 1237 UNSERIALIZE_SCALAR(regs.TxMaxCopy); 1238 UNSERIALIZE_SCALAR(regs.RxThreshold); 1239 UNSERIALIZE_SCALAR(regs.TxThreshold); 1240 UNSERIALIZE_SCALAR(regs.IntrStatus); 1241 UNSERIALIZE_SCALAR(regs.IntrMask); 1242 UNSERIALIZE_SCALAR(regs.RxData); 1243 UNSERIALIZE_SCALAR(regs.RxDone); 1244 UNSERIALIZE_SCALAR(regs.TxData); 1245 UNSERIALIZE_SCALAR(regs.TxDone); 1246 1247 /* 1248 * Unserialize rx state machine 1249 */ 1250 int rxState; 1251 UNSERIALIZE_SCALAR(rxState); 1252 this->rxState = (RxState) rxState; 1253 rxFifo.unserialize("rxFifo", cp, section); 1254 bool rxPacketExists; 1255 UNSERIALIZE_SCALAR(rxPacketExists); 1256 rxPacket = 0; 1257 if (rxPacketExists) { 1258 rxPacket = new PacketData(16384); 1259 rxPacket->unserialize("rxPacket", cp, section); 1260 uint32_t rxPktBufPtr; 1261 UNSERIALIZE_SCALAR(rxPktBufPtr); 1262 this->rxPacketBufPtr = (uint8_t *) rxPacket->data + rxPktBufPtr; 1263 UNSERIALIZE_SCALAR(rxPktBytes); 1264 } 1265 UNSERIALIZE_SCALAR(rxDoneData); 1266 1267 /* 1268 * Unserialize tx state machine 1269 */ 1270 int txState; 1271 UNSERIALIZE_SCALAR(txState); 1272 this->txState = (TxState) txState; 1273 txFifo.unserialize("txFifo", cp, section); 1274 bool txPacketExists; 1275 UNSERIALIZE_SCALAR(txPacketExists); 1276 txPacket = 0; 1277 if (txPacketExists) { 1278 txPacket = new PacketData(16384); 1279 txPacket->unserialize("txPacket", cp, section); 1280 uint32_t txPktBufPtr; 1281 UNSERIALIZE_SCALAR(txPktBufPtr); 1282 this->txPacketBufPtr = (uint8_t *) txPacket->data + txPktBufPtr; 1283 UNSERIALIZE_SCALAR(txPktBytes); 1284 } 1285 1286 /* 1287 * If there's a pending transmit, reschedule it now 1288 */ 1289 Tick transmitTick; 1290 UNSERIALIZE_SCALAR(transmitTick); 1291 if (transmitTick) 1292 txEvent.schedule(curTick + transmitTick); 1293 1294 /* 1295 * re-add addrRanges to bus bridges 1296 */ 1297 if (pioInterface) 1298 pioInterface->addAddrRange(RangeSize(BARAddrs[0], BARSize[0])); 1299} 1300 1301Tick 1302Device::cacheAccess(MemReqPtr &req) 1303{ 1304 //The mask is to give you only the offset into the device register file 1305 Addr daddr = req->paddr - addr; 1306 1307 DPRINTF(EthernetPIO, "timing access to paddr=%#x (daddr=%#x)\n", 1308 req->paddr, daddr); 1309 1310 Tick when = curTick + pioLatency; 1311 1312 switch (daddr) { 1313 case Regs::RxDone: 1314 if (rxState != rxIdle) { 1315 rxPioRequest = req; 1316 when = 0; 1317 } 1318 break; 1319 1320 case Regs::TxDone: 1321 if (txState != txIdle) { 1322 txPioRequest = req; 1323 when = 0; 1324 } 1325 break; 1326 } 1327 1328 return when; 1329} 1330 1331BEGIN_DECLARE_SIM_OBJECT_PARAMS(Interface) 1332 1333 SimObjectParam<EtherInt *> peer; 1334 SimObjectParam<Device *> device; 1335 1336END_DECLARE_SIM_OBJECT_PARAMS(Interface) 1337 1338BEGIN_INIT_SIM_OBJECT_PARAMS(Interface) 1339 1340 INIT_PARAM_DFLT(peer, "peer interface", NULL), 1341 INIT_PARAM(device, "Ethernet device of this interface") 1342 1343END_INIT_SIM_OBJECT_PARAMS(Interface) 1344 1345CREATE_SIM_OBJECT(Interface) 1346{ 1347 Interface *dev_int = new Interface(getInstanceName(), device); 1348 1349 EtherInt *p = (EtherInt *)peer; 1350 if (p) { 1351 dev_int->setPeer(p); 1352 p->setPeer(dev_int); 1353 } 1354 1355 return dev_int; 1356} 1357 1358REGISTER_SIM_OBJECT("SinicInt", Interface) 1359 1360 1361BEGIN_DECLARE_SIM_OBJECT_PARAMS(Device) 1362 1363 Param<Addr> addr; 1364 Param<Tick> cycle_time; 1365 Param<Tick> tx_delay; 1366 Param<Tick> rx_delay; 1367 Param<Tick> intr_delay; 1368 SimObjectParam<MemoryController *> mmu; 1369 SimObjectParam<PhysicalMemory *> physmem; 1370 Param<bool> rx_filter; 1371 Param<string> hardware_address; 1372 SimObjectParam<Bus*> io_bus; 1373 SimObjectParam<Bus*> payload_bus; 1374 SimObjectParam<HierParams *> hier; 1375 Param<Tick> pio_latency; 1376 SimObjectParam<PciConfigAll *> configspace; 1377 SimObjectParam<PciConfigData *> configdata; 1378 SimObjectParam<Platform *> platform; 1379 Param<uint32_t> pci_bus; 1380 Param<uint32_t> pci_dev; 1381 Param<uint32_t> pci_func; 1382 Param<uint32_t> rx_max_copy; 1383 Param<uint32_t> tx_max_copy; 1384 Param<uint32_t> rx_fifo_size; 1385 Param<uint32_t> tx_fifo_size; 1386 Param<uint32_t> rx_fifo_threshold; 1387 Param<uint32_t> tx_fifo_threshold; 1388 Param<Tick> dma_read_delay; 1389 Param<Tick> dma_read_factor; 1390 Param<Tick> dma_write_delay; 1391 Param<Tick> dma_write_factor; 1392 Param<bool> dma_no_allocate; 1393 1394END_DECLARE_SIM_OBJECT_PARAMS(Device) 1395 1396BEGIN_INIT_SIM_OBJECT_PARAMS(Device) 1397 1398 INIT_PARAM(addr, "Device Address"), 1399 INIT_PARAM(cycle_time, "State machine cycle time"), 1400 INIT_PARAM_DFLT(tx_delay, "Transmit Delay", 1000), 1401 INIT_PARAM_DFLT(rx_delay, "Receive Delay", 1000), 1402 INIT_PARAM_DFLT(intr_delay, "Interrupt Delay in microseconds", 0), 1403 INIT_PARAM(mmu, "Memory Controller"), 1404 INIT_PARAM(physmem, "Physical Memory"), 1405 INIT_PARAM_DFLT(rx_filter, "Enable Receive Filter", true), 1406 INIT_PARAM_DFLT(hardware_address, "Ethernet Hardware Address", 1407 "00:99:00:00:00:01"), 1408 INIT_PARAM_DFLT(io_bus, "The IO Bus to attach to for headers", NULL), 1409 INIT_PARAM_DFLT(payload_bus, "The IO Bus to attach to for payload", NULL), 1410 INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams), 1411 INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), 1412 INIT_PARAM(configspace, "PCI Configspace"), 1413 INIT_PARAM(configdata, "PCI Config data"), 1414 INIT_PARAM(platform, "Platform"), 1415 INIT_PARAM(pci_bus, "PCI bus"), 1416 INIT_PARAM(pci_dev, "PCI device number"), 1417 INIT_PARAM(pci_func, "PCI function code"), 1418 INIT_PARAM_DFLT(rx_max_copy, "rx max copy", 16*1024), 1419 INIT_PARAM_DFLT(tx_max_copy, "rx max copy", 16*1024), 1420 INIT_PARAM_DFLT(rx_fifo_size, "max size in bytes of rxFifo", 64*1024), 1421 INIT_PARAM_DFLT(tx_fifo_size, "max size in bytes of txFifo", 64*1024), 1422 INIT_PARAM_DFLT(rx_fifo_threshold, "max size in bytes of rxFifo", 48*1024), 1423 INIT_PARAM_DFLT(tx_fifo_threshold, "max size in bytes of txFifo", 16*1024), 1424 INIT_PARAM_DFLT(dma_read_delay, "fixed delay for dma reads", 0), 1425 INIT_PARAM_DFLT(dma_read_factor, "multiplier for dma reads", 0), 1426 INIT_PARAM_DFLT(dma_write_delay, "fixed delay for dma writes", 0), 1427 INIT_PARAM_DFLT(dma_write_factor, "multiplier for dma writes", 0), 1428 INIT_PARAM_DFLT(dma_no_allocate, "Should we allocat on read in cache", true) 1429 1430END_INIT_SIM_OBJECT_PARAMS(Device) 1431 1432 1433CREATE_SIM_OBJECT(Device) 1434{ 1435 Device::Params *params = new Device::Params; 1436 params->name = getInstanceName(); 1437 params->intr_delay = intr_delay; 1438 params->physmem = physmem; 1439 params->cycle_time = cycle_time; 1440 params->tx_delay = tx_delay; 1441 params->rx_delay = rx_delay; 1442 params->mmu = mmu; 1443 params->hier = hier; 1444 params->io_bus = io_bus; 1445 params->payload_bus = payload_bus; 1446 params->pio_latency = pio_latency; 1447 params->configSpace = configspace; 1448 params->configData = configdata; 1449 params->plat = platform; 1450 params->busNum = pci_bus; 1451 params->deviceNum = pci_dev; 1452 params->functionNum = pci_func; 1453 params->rx_filter = rx_filter; 1454 params->eaddr = hardware_address; 1455 params->rx_max_copy = rx_max_copy; 1456 params->tx_max_copy = tx_max_copy; 1457 params->rx_fifo_size = rx_fifo_size; 1458 params->tx_fifo_size = tx_fifo_size; 1459 params->rx_fifo_threshold = rx_fifo_threshold; 1460 params->tx_fifo_threshold = tx_fifo_threshold; 1461 params->dma_read_delay = dma_read_delay; 1462 params->dma_read_factor = dma_read_factor; 1463 params->dma_write_delay = dma_write_delay; 1464 params->dma_write_factor = dma_write_factor; 1465 params->dma_no_allocate = dma_no_allocate; 1466 return new Device(params); 1467} 1468 1469REGISTER_SIM_OBJECT("Sinic", Device) 1470 1471/* namespace Sinic */ } 1472