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