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