ns_gige.cc revision 1035
16145SN/A/* 26386SN/A * Copyright (c) 2004 The Regents of The University of Michigan 37553SN/A * All rights reserved. 46386SN/A * 56386SN/A * Redistribution and use in source and binary forms, with or without 66386SN/A * modification, are permitted provided that the following conditions are 76386SN/A * met: redistributions of source code must retain the above copyright 86386SN/A * notice, this list of conditions and the following disclaimer; 96386SN/A * redistributions in binary form must reproduce the above copyright 106386SN/A * notice, this list of conditions and the following disclaimer in the 116386SN/A * documentation and/or other materials provided with the distribution; 126386SN/A * neither the name of the copyright holders nor the names of its 136386SN/A * contributors may be used to endorse or promote products derived from 146386SN/A * this software without specific prior written permission. 156386SN/A * 166386SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176386SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186386SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196386SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206386SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216386SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226386SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236386SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246386SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256386SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266386SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276386SN/A */ 286386SN/A 296145SN/A/* @file 307632SBrad.Beckmann@amd.com * Device module for modelling the National Semiconductor 317632SBrad.Beckmann@amd.com * DP83820 ethernet controller. Does not support priority queueing 327632SBrad.Beckmann@amd.com */ 338232Snate@binkert.org#include <cstdio> 346145SN/A#include <deque> 357553SN/A#include <string> 367553SN/A 376145SN/A#include "base/inet.hh" 387553SN/A#include "cpu/exec_context.hh" 397553SN/A#include "cpu/intr_control.hh" 407553SN/A#include "dev/dma.hh" 417553SN/A#include "dev/etherlink.hh" 427553SN/A#include "dev/ns_gige.hh" 436145SN/A#include "dev/pciconfigall.hh" 446145SN/A#include "dev/tsunami_cchip.hh" 457553SN/A#include "mem/bus/bus.hh" 466145SN/A#include "mem/bus/dma_interface.hh" 476145SN/A#include "mem/bus/pio_interface.hh" 486145SN/A#include "mem/bus/pio_interface_impl.hh" 497553SN/A#include "mem/functional_mem/memory_control.hh" 507553SN/A#include "mem/functional_mem/physical_memory.hh" 516145SN/A#include "sim/builder.hh" 527553SN/A#include "sim/host.hh" 537553SN/A#include "sim/sim_stats.hh" 546145SN/A#include "targetarch/vtophys.hh" 558950Sandreas.hansson@arm.com 567553SN/Aconst char *NsRxStateStrings[] = 577553SN/A{ 587553SN/A "rxIdle", 597553SN/A "rxDescRefr", 608832SAli.Saidi@ARM.com "rxDescRead", 617553SN/A "rxFifoBlock", 627553SN/A "rxFragWrite", 637553SN/A "rxDescWrite", 647553SN/A "rxAdvance" 657553SN/A}; 667553SN/A 676145SN/Aconst char *NsTxStateStrings[] = 688949Sandreas.hansson@arm.com{ 697553SN/A "txIdle", 707553SN/A "txDescRefr", 717553SN/A "txDescRead", 726145SN/A "txFifoBlock", 738975Sandreas.hansson@arm.com "txFragRead", 747553SN/A "txDescWrite", 757553SN/A "txAdvance" 767553SN/A}; 777553SN/A 787553SN/Aconst char *NsDmaState[] = 797553SN/A{ 807553SN/A "dmaIdle", 817553SN/A "dmaReading", 827553SN/A "dmaWriting", 837553SN/A "dmaReadWaiting", 847553SN/A "dmaWriteWaiting" 857553SN/A}; 867553SN/A 876145SN/Ausing namespace std; 886145SN/A 897553SN/A// helper function declarations 908655Sandreas.hansson@arm.com// These functions reverse Endianness so we can evaluate network data 916145SN/A// correctly 927553SN/Auint16_t reverseEnd16(uint16_t); 937553SN/Auint32_t reverseEnd32(uint32_t); 947553SN/A 956145SN/A/////////////////////////////////////////////////////////////////////// 967553SN/A// 977553SN/A// NSGigE PCI Device 987553SN/A// 997553SN/ANSGigE::NSGigE(const std::string &name, IntrControl *i, Tick intr_delay, 1007553SN/A PhysicalMemory *pmem, Tick tx_delay, Tick rx_delay, 1017553SN/A MemoryController *mmu, HierParams *hier, Bus *header_bus, 1027553SN/A Bus *payload_bus, Tick pio_latency, bool dma_desc_free, 1037553SN/A bool dma_data_free, Tick dma_read_delay, Tick dma_write_delay, 1047553SN/A Tick dma_read_factor, Tick dma_write_factor, PciConfigAll *cf, 1057553SN/A PciConfigData *cd, Tsunami *t, uint32_t bus, uint32_t dev, 1067553SN/A uint32_t func, bool rx_filter, const int eaddr[6], 1076145SN/A uint32_t tx_fifo_size, uint32_t rx_fifo_size) 1086145SN/A : PciDev(name, mmu, cf, cd, bus, dev, func), tsunami(t), ioEnable(false), 1097553SN/A maxTxFifoSize(tx_fifo_size), maxRxFifoSize(rx_fifo_size), 1107553SN/A txPacket(0), rxPacket(0), txPacketBufPtr(NULL), rxPacketBufPtr(NULL), 1116145SN/A txXferLen(0), rxXferLen(0), txState(txIdle), txEnable(false), 1127553SN/A CTDD(false), txFifoAvail(tx_fifo_size), 1136145SN/A txFragPtr(0), txDescCnt(0), txDmaState(dmaIdle), rxState(rxIdle), 114 rxEnable(false), CRDD(false), rxPktBytes(0), rxFifoCnt(0), 115 rxFragPtr(0), rxDescCnt(0), rxDmaState(dmaIdle), extstsEnable(false), 116 rxDmaReadEvent(this), rxDmaWriteEvent(this), 117 txDmaReadEvent(this), txDmaWriteEvent(this), 118 dmaDescFree(dma_desc_free), dmaDataFree(dma_data_free), 119 txDelay(tx_delay), rxDelay(rx_delay), rxKickTick(0), txKickTick(0), 120 txEvent(this), rxFilterEnable(rx_filter), acceptBroadcast(false), 121 acceptMulticast(false), acceptUnicast(false), 122 acceptPerfect(false), acceptArp(false), 123 physmem(pmem), intctrl(i), intrTick(0), cpuPendingIntr(false), 124 intrEvent(0), interface(0) 125{ 126 tsunami->ethernet = this; 127 128 if (header_bus) { 129 pioInterface = newPioInterface(name, hier, header_bus, this, 130 &NSGigE::cacheAccess); 131 132 pioLatency = pio_latency * header_bus->clockRatio; 133 134 if (payload_bus) 135 dmaInterface = new DMAInterface<Bus>(name + ".dma", 136 header_bus, payload_bus, 1); 137 else 138 dmaInterface = new DMAInterface<Bus>(name + ".dma", 139 header_bus, header_bus, 1); 140 } else if (payload_bus) { 141 pioInterface = newPioInterface(name, hier, payload_bus, this, 142 &NSGigE::cacheAccess); 143 144 pioLatency = pio_latency * payload_bus->clockRatio; 145 146 dmaInterface = new DMAInterface<Bus>(name + ".dma", payload_bus, 147 payload_bus, 1); 148 } 149 150 151 intrDelay = US2Ticks(intr_delay); 152 dmaReadDelay = dma_read_delay; 153 dmaWriteDelay = dma_write_delay; 154 dmaReadFactor = dma_read_factor; 155 dmaWriteFactor = dma_write_factor; 156 157 regsReset(); 158 rom.perfectMatch[0] = eaddr[0]; 159 rom.perfectMatch[1] = eaddr[1]; 160 rom.perfectMatch[2] = eaddr[2]; 161 rom.perfectMatch[3] = eaddr[3]; 162 rom.perfectMatch[4] = eaddr[4]; 163 rom.perfectMatch[5] = eaddr[5]; 164} 165 166NSGigE::~NSGigE() 167{} 168 169void 170NSGigE::regStats() 171{ 172 txBytes 173 .name(name() + ".txBytes") 174 .desc("Bytes Transmitted") 175 .prereq(txBytes) 176 ; 177 178 rxBytes 179 .name(name() + ".rxBytes") 180 .desc("Bytes Received") 181 .prereq(rxBytes) 182 ; 183 184 txPackets 185 .name(name() + ".txPackets") 186 .desc("Number of Packets Transmitted") 187 .prereq(txBytes) 188 ; 189 190 rxPackets 191 .name(name() + ".rxPackets") 192 .desc("Number of Packets Received") 193 .prereq(rxBytes) 194 ; 195 196 txIPChecksums 197 .name(name() + ".txIPChecksums") 198 .desc("Number of tx IP Checksums done by device") 199 .precision(0) 200 .prereq(txBytes) 201 ; 202 203 rxIPChecksums 204 .name(name() + ".rxIPChecksums") 205 .desc("Number of rx IP Checksums done by device") 206 .precision(0) 207 .prereq(rxBytes) 208 ; 209 210 txTCPChecksums 211 .name(name() + ".txTCPChecksums") 212 .desc("Number of tx TCP Checksums done by device") 213 .precision(0) 214 .prereq(txBytes) 215 ; 216 217 rxTCPChecksums 218 .name(name() + ".rxTCPChecksums") 219 .desc("Number of rx TCP Checksums done by device") 220 .precision(0) 221 .prereq(rxBytes) 222 ; 223 224 descDmaReads 225 .name(name() + ".descDMAReads") 226 .desc("Number of descriptors the device read w/ DMA") 227 .precision(0) 228 ; 229 230 descDmaWrites 231 .name(name() + ".descDMAWrites") 232 .desc("Number of descriptors the device wrote w/ DMA") 233 .precision(0) 234 ; 235 236 descDmaRdBytes 237 .name(name() + ".descDmaReadBytes") 238 .desc("number of descriptor bytes read w/ DMA") 239 .precision(0) 240 ; 241 242 descDmaWrBytes 243 .name(name() + ".descDmaWriteBytes") 244 .desc("number of descriptor bytes write w/ DMA") 245 .precision(0) 246 ; 247 248 249 txBandwidth 250 .name(name() + ".txBandwidth") 251 .desc("Transmit Bandwidth (bits/s)") 252 .precision(0) 253 .prereq(txBytes) 254 ; 255 256 rxBandwidth 257 .name(name() + ".rxBandwidth") 258 .desc("Receive Bandwidth (bits/s)") 259 .precision(0) 260 .prereq(rxBytes) 261 ; 262 263 txPacketRate 264 .name(name() + ".txPPS") 265 .desc("Packet Tranmission Rate (packets/s)") 266 .precision(0) 267 .prereq(txBytes) 268 ; 269 270 rxPacketRate 271 .name(name() + ".rxPPS") 272 .desc("Packet Reception Rate (packets/s)") 273 .precision(0) 274 .prereq(rxBytes) 275 ; 276 277 txBandwidth = txBytes * Stats::constant(8) / simSeconds; 278 rxBandwidth = rxBytes * Stats::constant(8) / simSeconds; 279 txPacketRate = txPackets / simSeconds; 280 rxPacketRate = rxPackets / simSeconds; 281} 282 283/** 284 * This is to read the PCI general configuration registers 285 */ 286void 287NSGigE::ReadConfig(int offset, int size, uint8_t *data) 288{ 289 if (offset < PCI_DEVICE_SPECIFIC) 290 PciDev::ReadConfig(offset, size, data); 291 else 292 panic("Device specific PCI config space not implemented!\n"); 293} 294 295/** 296 * This is to write to the PCI general configuration registers 297 */ 298void 299NSGigE::WriteConfig(int offset, int size, uint32_t data) 300{ 301 if (offset < PCI_DEVICE_SPECIFIC) 302 PciDev::WriteConfig(offset, size, data); 303 else 304 panic("Device specific PCI config space not implemented!\n"); 305 306 // Need to catch writes to BARs to update the PIO interface 307 switch (offset) { 308 // seems to work fine without all these PCI settings, but i 309 // put in the IO to double check, an assertion will fail if we 310 // need to properly implement it 311 case PCI_COMMAND: 312 if (config.data[offset] & PCI_CMD_IOSE) 313 ioEnable = true; 314 else 315 ioEnable = false; 316 317#if 0 318 if (config.data[offset] & PCI_CMD_BME) { 319 bmEnabled = true; 320 } 321 else { 322 bmEnabled = false; 323 } 324 325 if (config.data[offset] & PCI_CMD_MSE) { 326 memEnable = true; 327 } 328 else { 329 memEnable = false; 330 } 331#endif 332 break; 333 334 case PCI0_BASE_ADDR0: 335 if (BARAddrs[0] != 0) { 336 if (pioInterface) 337 pioInterface->addAddrRange(BARAddrs[0], 338 BARAddrs[0] + BARSize[0] - 1); 339 340 BARAddrs[0] &= PA_UNCACHED_MASK; 341 } 342 break; 343 case PCI0_BASE_ADDR1: 344 if (BARAddrs[1] != 0) { 345 if (pioInterface) 346 pioInterface->addAddrRange(BARAddrs[1], 347 BARAddrs[1] + BARSize[1] - 1); 348 349 BARAddrs[1] &= PA_UNCACHED_MASK; 350 } 351 break; 352 } 353} 354 355/** 356 * This reads the device registers, which are detailed in the NS83820 357 * spec sheet 358 */ 359Fault 360NSGigE::read(MemReqPtr &req, uint8_t *data) 361{ 362 assert(ioEnable); 363 364 //The mask is to give you only the offset into the device register file 365 Addr daddr = req->paddr & 0xfff; 366 DPRINTF(EthernetPIO, "read da=%#x pa=%#x va=%#x size=%d\n", 367 daddr, req->paddr, req->vaddr, req->size); 368 369 370 // there are some reserved registers, you can see ns_gige_reg.h and 371 // the spec sheet for details 372 if (daddr > LAST && daddr <= RESERVED) { 373 panic("Accessing reserved register"); 374 } else if (daddr > RESERVED && daddr <= 0x3FC) { 375 ReadConfig(daddr & 0xff, req->size, data); 376 return No_Fault; 377 } else if (daddr >= MIB_START && daddr <= MIB_END) { 378 // don't implement all the MIB's. hopefully the kernel 379 // doesn't actually DEPEND upon their values 380 // MIB are just hardware stats keepers 381 uint32_t ® = *(uint32_t *) data; 382 reg = 0; 383 return No_Fault; 384 } else if (daddr > 0x3FC) 385 panic("Something is messed up!\n"); 386 387 switch (req->size) { 388 case sizeof(uint32_t): 389 { 390 uint32_t ® = *(uint32_t *)data; 391 392 switch (daddr) { 393 case CR: 394 reg = regs.command; 395 //these are supposed to be cleared on a read 396 reg &= ~(CR_RXD | CR_TXD | CR_TXR | CR_RXR); 397 break; 398 399 case CFG: 400 reg = regs.config; 401 break; 402 403 case MEAR: 404 reg = regs.mear; 405 break; 406 407 case PTSCR: 408 reg = regs.ptscr; 409 break; 410 411 case ISR: 412 reg = regs.isr; 413 devIntrClear(ISR_ALL); 414 break; 415 416 case IMR: 417 reg = regs.imr; 418 break; 419 420 case IER: 421 reg = regs.ier; 422 break; 423 424 case IHR: 425 reg = regs.ihr; 426 break; 427 428 case TXDP: 429 reg = regs.txdp; 430 break; 431 432 case TXDP_HI: 433 reg = regs.txdp_hi; 434 break; 435 436 case TXCFG: 437 reg = regs.txcfg; 438 break; 439 440 case GPIOR: 441 reg = regs.gpior; 442 break; 443 444 case RXDP: 445 reg = regs.rxdp; 446 break; 447 448 case RXDP_HI: 449 reg = regs.rxdp_hi; 450 break; 451 452 case RXCFG: 453 reg = regs.rxcfg; 454 break; 455 456 case PQCR: 457 reg = regs.pqcr; 458 break; 459 460 case WCSR: 461 reg = regs.wcsr; 462 break; 463 464 case PCR: 465 reg = regs.pcr; 466 break; 467 468 // see the spec sheet for how RFCR and RFDR work 469 // basically, you write to RFCR to tell the machine 470 // what you want to do next, then you act upon RFDR, 471 // and the device will be prepared b/c of what you 472 // wrote to RFCR 473 case RFCR: 474 reg = regs.rfcr; 475 break; 476 477 case RFDR: 478 switch (regs.rfcr & RFCR_RFADDR) { 479 case 0x000: 480 reg = rom.perfectMatch[1]; 481 reg = reg << 8; 482 reg += rom.perfectMatch[0]; 483 break; 484 case 0x002: 485 reg = rom.perfectMatch[3] << 8; 486 reg += rom.perfectMatch[2]; 487 break; 488 case 0x004: 489 reg = rom.perfectMatch[5] << 8; 490 reg += rom.perfectMatch[4]; 491 break; 492 default: 493 panic("reading RFDR for something other than PMATCH!\n"); 494 // didn't implement other RFDR functionality b/c 495 // driver didn't use it 496 } 497 break; 498 499 case SRR: 500 reg = regs.srr; 501 break; 502 503 case MIBC: 504 reg = regs.mibc; 505 reg &= ~(MIBC_MIBS | MIBC_ACLR); 506 break; 507 508 case VRCR: 509 reg = regs.vrcr; 510 break; 511 512 case VTCR: 513 reg = regs.vtcr; 514 break; 515 516 case VDR: 517 reg = regs.vdr; 518 break; 519 520 case CCSR: 521 reg = regs.ccsr; 522 break; 523 524 case TBICR: 525 reg = regs.tbicr; 526 break; 527 528 case TBISR: 529 reg = regs.tbisr; 530 break; 531 532 case TANAR: 533 reg = regs.tanar; 534 break; 535 536 case TANLPAR: 537 reg = regs.tanlpar; 538 break; 539 540 case TANER: 541 reg = regs.taner; 542 break; 543 544 case TESR: 545 reg = regs.tesr; 546 break; 547 548 default: 549 panic("reading unimplemented register: addr = %#x", daddr); 550 } 551 552 DPRINTF(EthernetPIO, "read from %#x: data=%d data=%#x\n", 553 daddr, reg, reg); 554 } 555 break; 556 557 default: 558 panic("accessing register with invalid size: addr=%#x, size=%d", 559 daddr, req->size); 560 } 561 562 return No_Fault; 563} 564 565Fault 566NSGigE::write(MemReqPtr &req, const uint8_t *data) 567{ 568 assert(ioEnable); 569 570 Addr daddr = req->paddr & 0xfff; 571 DPRINTF(EthernetPIO, "write da=%#x pa=%#x va=%#x size=%d\n", 572 daddr, req->paddr, req->vaddr, req->size); 573 574 if (daddr > LAST && daddr <= RESERVED) { 575 panic("Accessing reserved register"); 576 } else if (daddr > RESERVED && daddr <= 0x3FC) { 577 WriteConfig(daddr & 0xff, req->size, *(uint32_t *)data); 578 return No_Fault; 579 } else if (daddr > 0x3FC) 580 panic("Something is messed up!\n"); 581 582 if (req->size == sizeof(uint32_t)) { 583 uint32_t reg = *(uint32_t *)data; 584 DPRINTF(EthernetPIO, "write data=%d data=%#x\n", reg, reg); 585 586 switch (daddr) { 587 case CR: 588 regs.command = reg; 589 if (reg & CR_TXD) { 590 txEnable = false; 591 } else if (reg & CR_TXE) { 592 txEnable = true; 593 594 // the kernel is enabling the transmit machine 595 if (txState == txIdle) 596 txKick(); 597 } 598 599 if (reg & CR_RXD) { 600 rxEnable = false; 601 } else if (reg & CR_RXE) { 602 rxEnable = true; 603 604 if (rxState == rxIdle) 605 rxKick(); 606 } 607 608 if (reg & CR_TXR) 609 txReset(); 610 611 if (reg & CR_RXR) 612 rxReset(); 613 614 if (reg & CR_SWI) 615 devIntrPost(ISR_SWI); 616 617 if (reg & CR_RST) { 618 txReset(); 619 rxReset(); 620 621 regsReset(); 622 } 623 break; 624 625 case CFG: 626 if (reg & CFG_LNKSTS || 627 reg & CFG_SPDSTS || 628 reg & CFG_DUPSTS || 629 reg & CFG_RESERVED || 630 reg & CFG_T64ADDR || 631 reg & CFG_PCI64_DET) 632 panic("writing to read-only or reserved CFG bits!\n"); 633 634 regs.config |= reg & ~(CFG_LNKSTS | CFG_SPDSTS | CFG_DUPSTS | 635 CFG_RESERVED | CFG_T64ADDR | CFG_PCI64_DET); 636 637// all these #if 0's are because i don't THINK the kernel needs to 638// have these implemented. if there is a problem relating to one of 639// these, you may need to add functionality in. 640#if 0 641 if (reg & CFG_TBI_EN) ; 642 if (reg & CFG_MODE_1000) ; 643#endif 644 645 if (reg & CFG_AUTO_1000) 646 panic("CFG_AUTO_1000 not implemented!\n"); 647 648#if 0 649 if (reg & CFG_PINT_DUPSTS || 650 reg & CFG_PINT_LNKSTS || 651 reg & CFG_PINT_SPDSTS) 652 ; 653 654 if (reg & CFG_TMRTEST) ; 655 if (reg & CFG_MRM_DIS) ; 656 if (reg & CFG_MWI_DIS) ; 657 658 if (reg & CFG_T64ADDR) 659 panic("CFG_T64ADDR is read only register!\n"); 660 661 if (reg & CFG_PCI64_DET) 662 panic("CFG_PCI64_DET is read only register!\n"); 663 664 if (reg & CFG_DATA64_EN) ; 665 if (reg & CFG_M64ADDR) ; 666 if (reg & CFG_PHY_RST) ; 667 if (reg & CFG_PHY_DIS) ; 668#endif 669 670 if (reg & CFG_EXTSTS_EN) 671 extstsEnable = true; 672 else 673 extstsEnable = false; 674 675#if 0 676 if (reg & CFG_REQALG) ; 677 if (reg & CFG_SB) ; 678 if (reg & CFG_POW) ; 679 if (reg & CFG_EXD) ; 680 if (reg & CFG_PESEL) ; 681 if (reg & CFG_BROM_DIS) ; 682 if (reg & CFG_EXT_125) ; 683 if (reg & CFG_BEM) ; 684#endif 685 break; 686 687 case MEAR: 688 regs.mear = reg; 689 // since phy is completely faked, MEAR_MD* don't matter 690 // and since the driver never uses MEAR_EE*, they don't 691 // matter 692#if 0 693 if (reg & MEAR_EEDI) ; 694 if (reg & MEAR_EEDO) ; // this one is read only 695 if (reg & MEAR_EECLK) ; 696 if (reg & MEAR_EESEL) ; 697 if (reg & MEAR_MDIO) ; 698 if (reg & MEAR_MDDIR) ; 699 if (reg & MEAR_MDC) ; 700#endif 701 break; 702 703 case PTSCR: 704 regs.ptscr = reg & ~(PTSCR_RBIST_RDONLY); 705 // these control BISTs for various parts of chip - we 706 // don't care or do just fake that the BIST is done 707 if (reg & PTSCR_RBIST_EN) 708 regs.ptscr |= PTSCR_RBIST_DONE; 709 if (reg & PTSCR_EEBIST_EN) 710 regs.ptscr &= ~PTSCR_EEBIST_EN; 711 if (reg & PTSCR_EELOAD_EN) 712 regs.ptscr &= ~PTSCR_EELOAD_EN; 713 break; 714 715 case ISR: /* writing to the ISR has no effect */ 716 panic("ISR is a read only register!\n"); 717 718 case IMR: 719 regs.imr = reg; 720 devIntrChangeMask(); 721 break; 722 723 case IER: 724 regs.ier = reg; 725 break; 726 727 case IHR: 728 regs.ihr = reg; 729 /* not going to implement real interrupt holdoff */ 730 break; 731 732 case TXDP: 733 regs.txdp = (reg & 0xFFFFFFFC); 734 assert(txState == txIdle); 735 CTDD = false; 736 break; 737 738 case TXDP_HI: 739 regs.txdp_hi = reg; 740 break; 741 742 case TXCFG: 743 regs.txcfg = reg; 744#if 0 745 if (reg & TXCFG_CSI) ; 746 if (reg & TXCFG_HBI) ; 747 if (reg & TXCFG_MLB) ; 748 if (reg & TXCFG_ATP) ; 749 if (reg & TXCFG_ECRETRY) { 750 /* 751 * this could easily be implemented, but considering 752 * the network is just a fake pipe, wouldn't make 753 * sense to do this 754 */ 755 } 756 757 if (reg & TXCFG_BRST_DIS) ; 758#endif 759 760#if 0 761 /* we handle our own DMA, ignore the kernel's exhortations */ 762 if (reg & TXCFG_MXDMA) ; 763#endif 764 765 // also, we currently don't care about fill/drain 766 // thresholds though this may change in the future with 767 // more realistic networks or a driver which changes it 768 // according to feedback 769 770 break; 771 772 case GPIOR: 773 regs.gpior = reg; 774 /* these just control general purpose i/o pins, don't matter */ 775 break; 776 777 case RXDP: 778 regs.rxdp = reg; 779 CRDD = false; 780 break; 781 782 case RXDP_HI: 783 regs.rxdp_hi = reg; 784 break; 785 786 case RXCFG: 787 regs.rxcfg = reg; 788#if 0 789 if (reg & RXCFG_AEP) ; 790 if (reg & RXCFG_ARP) ; 791 if (reg & RXCFG_STRIPCRC) ; 792 if (reg & RXCFG_RX_RD) ; 793 if (reg & RXCFG_ALP) ; 794 if (reg & RXCFG_AIRL) ; 795 796 /* we handle our own DMA, ignore what kernel says about it */ 797 if (reg & RXCFG_MXDMA) ; 798 799 //also, we currently don't care about fill/drain thresholds 800 //though this may change in the future with more realistic 801 //networks or a driver which changes it according to feedback 802 if (reg & (RXCFG_DRTH | RXCFG_DRTH0)) ; 803#endif 804 break; 805 806 case PQCR: 807 /* there is no priority queueing used in the linux 2.6 driver */ 808 regs.pqcr = reg; 809 break; 810 811 case WCSR: 812 /* not going to implement wake on LAN */ 813 regs.wcsr = reg; 814 break; 815 816 case PCR: 817 /* not going to implement pause control */ 818 regs.pcr = reg; 819 break; 820 821 case RFCR: 822 regs.rfcr = reg; 823 824 rxFilterEnable = (reg & RFCR_RFEN) ? true : false; 825 acceptBroadcast = (reg & RFCR_AAB) ? true : false; 826 acceptMulticast = (reg & RFCR_AAM) ? true : false; 827 acceptUnicast = (reg & RFCR_AAU) ? true : false; 828 acceptPerfect = (reg & RFCR_APM) ? true : false; 829 acceptArp = (reg & RFCR_AARP) ? true : false; 830 831#if 0 832 if (reg & RFCR_APAT) 833 panic("RFCR_APAT not implemented!\n"); 834#endif 835 836 if (reg & RFCR_MHEN || reg & RFCR_UHEN) 837 panic("hash filtering not implemented!\n"); 838 839 if (reg & RFCR_ULM) 840 panic("RFCR_ULM not implemented!\n"); 841 842 break; 843 844 case RFDR: 845 panic("the driver never writes to RFDR, something is wrong!\n"); 846 847 case BRAR: 848 panic("the driver never uses BRAR, something is wrong!\n"); 849 850 case BRDR: 851 panic("the driver never uses BRDR, something is wrong!\n"); 852 853 case SRR: 854 panic("SRR is read only register!\n"); 855 856 case MIBC: 857 panic("the driver never uses MIBC, something is wrong!\n"); 858 859 case VRCR: 860 regs.vrcr = reg; 861 break; 862 863 case VTCR: 864 regs.vtcr = reg; 865 break; 866 867 case VDR: 868 panic("the driver never uses VDR, something is wrong!\n"); 869 break; 870 871 case CCSR: 872 /* not going to implement clockrun stuff */ 873 regs.ccsr = reg; 874 break; 875 876 case TBICR: 877 regs.tbicr = reg; 878 if (reg & TBICR_MR_LOOPBACK) 879 panic("TBICR_MR_LOOPBACK never used, something wrong!\n"); 880 881 if (reg & TBICR_MR_AN_ENABLE) { 882 regs.tanlpar = regs.tanar; 883 regs.tbisr |= (TBISR_MR_AN_COMPLETE | TBISR_MR_LINK_STATUS); 884 } 885 886#if 0 887 if (reg & TBICR_MR_RESTART_AN) ; 888#endif 889 890 break; 891 892 case TBISR: 893 panic("TBISR is read only register!\n"); 894 895 case TANAR: 896 regs.tanar = reg; 897 if (reg & TANAR_PS2) 898 panic("this isn't used in driver, something wrong!\n"); 899 900 if (reg & TANAR_PS1) 901 panic("this isn't used in driver, something wrong!\n"); 902 break; 903 904 case TANLPAR: 905 panic("this should only be written to by the fake phy!\n"); 906 907 case TANER: 908 panic("TANER is read only register!\n"); 909 910 case TESR: 911 regs.tesr = reg; 912 break; 913 914 default: 915 panic("invalid register access daddr=%#x", daddr); 916 } 917 } else { 918 panic("Invalid Request Size"); 919 } 920 921 return No_Fault; 922} 923 924void 925NSGigE::devIntrPost(uint32_t interrupts) 926{ 927 bool delay = false; 928 929 if (interrupts & ISR_RESERVE) 930 panic("Cannot set a reserved interrupt"); 931 932 if (interrupts & ISR_TXRCMP) 933 regs.isr |= ISR_TXRCMP; 934 935 if (interrupts & ISR_RXRCMP) 936 regs.isr |= ISR_RXRCMP; 937 938//ISR_DPERR not implemented 939//ISR_SSERR not implemented 940//ISR_RMABT not implemented 941//ISR_RXSOVR not implemented 942//ISR_HIBINT not implemented 943//ISR_PHY not implemented 944//ISR_PME not implemented 945 946 if (interrupts & ISR_SWI) 947 regs.isr |= ISR_SWI; 948 949//ISR_MIB not implemented 950//ISR_TXURN not implemented 951 952 if (interrupts & ISR_TXIDLE) 953 regs.isr |= ISR_TXIDLE; 954 955 if (interrupts & ISR_TXERR) 956 regs.isr |= ISR_TXERR; 957 958 if (interrupts & ISR_TXDESC) 959 regs.isr |= ISR_TXDESC; 960 961 if (interrupts & ISR_TXOK) { 962 regs.isr |= ISR_TXOK; 963 delay = true; 964 } 965 966 if (interrupts & ISR_RXORN) 967 regs.isr |= ISR_RXORN; 968 969 if (interrupts & ISR_RXIDLE) 970 regs.isr |= ISR_RXIDLE; 971 972//ISR_RXEARLY not implemented 973 974 if (interrupts & ISR_RXERR) 975 regs.isr |= ISR_RXERR; 976 977 if (interrupts & ISR_RXDESC) 978 regs.isr |= ISR_RXDESC; 979 980 if (interrupts & ISR_RXOK) { 981 delay = true; 982 regs.isr |= ISR_RXOK; 983 } 984 985 if ((regs.isr & regs.imr)) { 986 Tick when = curTick; 987 if (delay) 988 when += intrDelay; 989 cpuIntrPost(when); 990 } 991 992 DPRINTF(EthernetIntr, 993 "interrupt written to ISR: intr=%#x isr=%#x imr=%#x\n", 994 interrupts, regs.isr, regs.imr); 995} 996 997void 998NSGigE::devIntrClear(uint32_t interrupts) 999{ 1000 if (interrupts & ISR_RESERVE) 1001 panic("Cannot clear a reserved interrupt"); 1002 1003 if (interrupts & ISR_TXRCMP) 1004 regs.isr &= ~ISR_TXRCMP; 1005 1006 if (interrupts & ISR_RXRCMP) 1007 regs.isr &= ~ISR_RXRCMP; 1008 1009//ISR_DPERR not implemented 1010//ISR_SSERR not implemented 1011//ISR_RMABT not implemented 1012//ISR_RXSOVR not implemented 1013//ISR_HIBINT not implemented 1014//ISR_PHY not implemented 1015//ISR_PME not implemented 1016 1017 if (interrupts & ISR_SWI) 1018 regs.isr &= ~ISR_SWI; 1019 1020//ISR_MIB not implemented 1021//ISR_TXURN not implemented 1022 1023 if (interrupts & ISR_TXIDLE) 1024 regs.isr &= ~ISR_TXIDLE; 1025 1026 if (interrupts & ISR_TXERR) 1027 regs.isr &= ~ISR_TXERR; 1028 1029 if (interrupts & ISR_TXDESC) 1030 regs.isr &= ~ISR_TXDESC; 1031 1032 if (interrupts & ISR_TXOK) 1033 regs.isr &= ~ISR_TXOK; 1034 1035 if (interrupts & ISR_RXORN) 1036 regs.isr &= ~ISR_RXORN; 1037 1038 if (interrupts & ISR_RXIDLE) 1039 regs.isr &= ~ISR_RXIDLE; 1040 1041//ISR_RXEARLY not implemented 1042 1043 if (interrupts & ISR_RXERR) 1044 regs.isr &= ~ISR_RXERR; 1045 1046 if (interrupts & ISR_RXDESC) 1047 regs.isr &= ~ISR_RXDESC; 1048 1049 if (interrupts & ISR_RXOK) 1050 regs.isr &= ~ISR_RXOK; 1051 1052 if (!(regs.isr & regs.imr)) 1053 cpuIntrClear(); 1054 1055 DPRINTF(EthernetIntr, 1056 "interrupt cleared from ISR: intr=%x isr=%x imr=%x\n", 1057 interrupts, regs.isr, regs.imr); 1058} 1059 1060void 1061NSGigE::devIntrChangeMask() 1062{ 1063 DPRINTF(EthernetIntr, "interrupt mask changed\n"); 1064 1065 if (regs.isr & regs.imr) 1066 cpuIntrPost(curTick); 1067 else 1068 cpuIntrClear(); 1069} 1070 1071void 1072NSGigE::cpuIntrPost(Tick when) 1073{ 1074 // If the interrupt you want to post is later than an interrupt 1075 // already scheduled, just let it post in the coming one and don't 1076 // schedule another. 1077 // HOWEVER, must be sure that the scheduled intrTick is in the 1078 // future (this was formerly the source of a bug) 1079 /** 1080 * @todo this warning should be removed and the intrTick code should 1081 * be fixed. 1082 */ 1083 if (intrTick < curTick && intrTick != 0) { 1084 warn("intrTick < curTick !!! intrTick=%d curTick=%d\n", 1085 intrTick, curTick); 1086 intrTick = 0; 1087 } 1088 assert((intrTick >= curTick) || (intrTick == 0)); 1089 if (when > intrTick && intrTick != 0) 1090 return; 1091 1092 intrTick = when; 1093 1094 if (intrEvent) { 1095 intrEvent->squash(); 1096 intrEvent = 0; 1097 } 1098 1099 if (when < curTick) { 1100 cpuInterrupt(); 1101 } else { 1102 DPRINTF(EthernetIntr, 1103 "going to schedule an interrupt for intrTick=%d\n", 1104 intrTick); 1105 intrEvent = new IntrEvent(this, true); 1106 intrEvent->schedule(intrTick); 1107 } 1108} 1109 1110void 1111NSGigE::cpuInterrupt() 1112{ 1113 // Don't send an interrupt if there's already one 1114 if (cpuPendingIntr) { 1115 DPRINTF(EthernetIntr, 1116 "would send an interrupt now, but there's already pending\n"); 1117 intrTick = 0; 1118 return; 1119 } 1120 // Don't send an interrupt if it's supposed to be delayed 1121 if (intrTick > curTick) { 1122 DPRINTF(EthernetIntr, 1123 "an interrupt is scheduled for %d, wait til then\n", 1124 intrTick); 1125 return; 1126 } 1127 1128 // Whether or not there's a pending interrupt, we don't care about 1129 // it anymore 1130 intrEvent = 0; 1131 intrTick = 0; 1132 1133 // Send interrupt 1134 cpuPendingIntr = true; 1135 /** @todo rework the intctrl to be tsunami ok */ 1136 //intctrl->post(TheISA::INTLEVEL_IRQ1, TheISA::INTINDEX_ETHERNET); 1137 DPRINTF(EthernetIntr, "Posting interrupts to cchip!\n"); 1138 tsunami->cchip->postDRIR(configData->config.hdr.pci0.interruptLine); 1139} 1140 1141void 1142NSGigE::cpuIntrClear() 1143{ 1144 if (!cpuPendingIntr) 1145 return; 1146 1147 cpuPendingIntr = false; 1148 /** @todo rework the intctrl to be tsunami ok */ 1149 //intctrl->clear(TheISA::INTLEVEL_IRQ1, TheISA::INTINDEX_ETHERNET); 1150 DPRINTF(EthernetIntr, "clearing all interrupts from cchip\n"); 1151 tsunami->cchip->clearDRIR(configData->config.hdr.pci0.interruptLine); 1152} 1153 1154bool 1155NSGigE::cpuIntrPending() const 1156{ return cpuPendingIntr; } 1157 1158void 1159NSGigE::txReset() 1160{ 1161 1162 DPRINTF(Ethernet, "transmit reset\n"); 1163 1164 CTDD = false; 1165 txFifoAvail = maxTxFifoSize; 1166 txEnable = false;; 1167 txFragPtr = 0; 1168 assert(txDescCnt == 0); 1169 txFifo.clear(); 1170 txState = txIdle; 1171 assert(txDmaState == dmaIdle); 1172} 1173 1174void 1175NSGigE::rxReset() 1176{ 1177 DPRINTF(Ethernet, "receive reset\n"); 1178 1179 CRDD = false; 1180 assert(rxPktBytes == 0); 1181 rxFifoCnt = 0; 1182 rxEnable = false; 1183 rxFragPtr = 0; 1184 assert(rxDescCnt == 0); 1185 assert(rxDmaState == dmaIdle); 1186 rxFifo.clear(); 1187 rxState = rxIdle; 1188} 1189 1190void NSGigE::regsReset() 1191{ 1192 memset(®s, 0, sizeof(regs)); 1193 regs.config = 0x80000000; 1194 regs.mear = 0x12; 1195 regs.isr = 0x00608000; 1196 regs.txcfg = 0x120; 1197 regs.rxcfg = 0x4; 1198 regs.srr = 0x0103; 1199 regs.mibc = 0x2; 1200 regs.vdr = 0x81; 1201 regs.tesr = 0xc000; 1202 1203 extstsEnable = false; 1204 acceptBroadcast = false; 1205 acceptMulticast = false; 1206 acceptUnicast = false; 1207 acceptPerfect = false; 1208 acceptArp = false; 1209} 1210 1211void 1212NSGigE::rxDmaReadCopy() 1213{ 1214 assert(rxDmaState == dmaReading); 1215 1216 physmem->dma_read((uint8_t *)rxDmaData, rxDmaAddr, rxDmaLen); 1217 rxDmaState = dmaIdle; 1218 1219 DPRINTF(EthernetDMA, "rx dma read paddr=%#x len=%d\n", 1220 rxDmaAddr, rxDmaLen); 1221 DDUMP(EthernetDMA, rxDmaData, rxDmaLen); 1222} 1223 1224bool 1225NSGigE::doRxDmaRead() 1226{ 1227 assert(rxDmaState == dmaIdle || rxDmaState == dmaReadWaiting); 1228 rxDmaState = dmaReading; 1229 1230 if (dmaInterface && !rxDmaFree) { 1231 if (dmaInterface->busy()) 1232 rxDmaState = dmaReadWaiting; 1233 else 1234 dmaInterface->doDMA(Read, rxDmaAddr, rxDmaLen, curTick, 1235 &rxDmaReadEvent, true); 1236 return true; 1237 } 1238 1239 if (dmaReadDelay == 0 && dmaReadFactor == 0) { 1240 rxDmaReadCopy(); 1241 return false; 1242 } 1243 1244 Tick factor = ((rxDmaLen + ULL(63)) >> ULL(6)) * dmaReadFactor; 1245 Tick start = curTick + dmaReadDelay + factor; 1246 rxDmaReadEvent.schedule(start); 1247 return true; 1248} 1249 1250void 1251NSGigE::rxDmaReadDone() 1252{ 1253 assert(rxDmaState == dmaReading); 1254 rxDmaReadCopy(); 1255 1256 // If the transmit state machine has a pending DMA, let it go first 1257 if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting) 1258 txKick(); 1259 1260 rxKick(); 1261} 1262 1263void 1264NSGigE::rxDmaWriteCopy() 1265{ 1266 assert(rxDmaState == dmaWriting); 1267 1268 physmem->dma_write(rxDmaAddr, (uint8_t *)rxDmaData, rxDmaLen); 1269 rxDmaState = dmaIdle; 1270 1271 DPRINTF(EthernetDMA, "rx dma write paddr=%#x len=%d\n", 1272 rxDmaAddr, rxDmaLen); 1273 DDUMP(EthernetDMA, rxDmaData, rxDmaLen); 1274} 1275 1276bool 1277NSGigE::doRxDmaWrite() 1278{ 1279 assert(rxDmaState == dmaIdle || rxDmaState == dmaWriteWaiting); 1280 rxDmaState = dmaWriting; 1281 1282 if (dmaInterface && !rxDmaFree) { 1283 if (dmaInterface->busy()) 1284 rxDmaState = dmaWriteWaiting; 1285 else 1286 dmaInterface->doDMA(WriteInvalidate, rxDmaAddr, rxDmaLen, curTick, 1287 &rxDmaWriteEvent, true); 1288 return true; 1289 } 1290 1291 if (dmaWriteDelay == 0 && dmaWriteFactor == 0) { 1292 rxDmaWriteCopy(); 1293 return false; 1294 } 1295 1296 Tick factor = ((rxDmaLen + ULL(63)) >> ULL(6)) * dmaWriteFactor; 1297 Tick start = curTick + dmaWriteDelay + factor; 1298 rxDmaWriteEvent.schedule(start); 1299 return true; 1300} 1301 1302void 1303NSGigE::rxDmaWriteDone() 1304{ 1305 assert(rxDmaState == dmaWriting); 1306 rxDmaWriteCopy(); 1307 1308 // If the transmit state machine has a pending DMA, let it go first 1309 if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting) 1310 txKick(); 1311 1312 rxKick(); 1313} 1314 1315void 1316NSGigE::rxKick() 1317{ 1318 DPRINTF(EthernetSM, "receive kick state=%s (rxBuf.size=%d)\n", 1319 NsRxStateStrings[rxState], rxFifo.size()); 1320 1321 if (rxKickTick > curTick) { 1322 DPRINTF(EthernetSM, "receive kick exiting, can't run till %d\n", 1323 rxKickTick); 1324 return; 1325 } 1326 1327 next: 1328 switch(rxDmaState) { 1329 case dmaReadWaiting: 1330 if (doRxDmaRead()) 1331 goto exit; 1332 break; 1333 case dmaWriteWaiting: 1334 if (doRxDmaWrite()) 1335 goto exit; 1336 break; 1337 default: 1338 break; 1339 } 1340 1341 // see state machine from spec for details 1342 // the way this works is, if you finish work on one state and can 1343 // go directly to another, you do that through jumping to the 1344 // label "next". however, if you have intermediate work, like DMA 1345 // so that you can't go to the next state yet, you go to exit and 1346 // exit the loop. however, when the DMA is done it will trigger 1347 // an event and come back to this loop. 1348 switch (rxState) { 1349 case rxIdle: 1350 if (!rxEnable) { 1351 DPRINTF(EthernetSM, "Receive Disabled! Nothing to do.\n"); 1352 goto exit; 1353 } 1354 1355 if (CRDD) { 1356 rxState = rxDescRefr; 1357 1358 rxDmaAddr = regs.rxdp & 0x3fffffff; 1359 rxDmaData = &rxDescCache + offsetof(ns_desc, link); 1360 rxDmaLen = sizeof(rxDescCache.link); 1361 rxDmaFree = dmaDescFree; 1362 1363 descDmaReads++; 1364 descDmaRdBytes += rxDmaLen; 1365 1366 if (doRxDmaRead()) 1367 goto exit; 1368 } else { 1369 rxState = rxDescRead; 1370 1371 rxDmaAddr = regs.rxdp & 0x3fffffff; 1372 rxDmaData = &rxDescCache; 1373 rxDmaLen = sizeof(ns_desc); 1374 rxDmaFree = dmaDescFree; 1375 1376 descDmaReads++; 1377 descDmaRdBytes += rxDmaLen; 1378 1379 if (doRxDmaRead()) 1380 goto exit; 1381 } 1382 break; 1383 1384 case rxDescRefr: 1385 if (rxDmaState != dmaIdle) 1386 goto exit; 1387 1388 rxState = rxAdvance; 1389 break; 1390 1391 case rxDescRead: 1392 if (rxDmaState != dmaIdle) 1393 goto exit; 1394 1395 DPRINTF(EthernetDesc, 1396 "rxDescCache:\n" 1397 "\tlink=%08x\n" 1398 "\tbufptr=%08x\n" 1399 "\tcmdsts=%08x\n" 1400 "\textsts=%08x\n", 1401 rxDescCache.link, rxDescCache.bufptr, rxDescCache.cmdsts, 1402 rxDescCache.extsts); 1403 1404 if (rxDescCache.cmdsts & CMDSTS_OWN) { 1405 devIntrPost(ISR_RXIDLE); 1406 rxState = rxIdle; 1407 goto exit; 1408 } else { 1409 rxState = rxFifoBlock; 1410 rxFragPtr = rxDescCache.bufptr; 1411 rxDescCnt = rxDescCache.cmdsts & CMDSTS_LEN_MASK; 1412 } 1413 break; 1414 1415 case rxFifoBlock: 1416 if (!rxPacket) { 1417 /** 1418 * @todo in reality, we should be able to start processing 1419 * the packet as it arrives, and not have to wait for the 1420 * full packet ot be in the receive fifo. 1421 */ 1422 if (rxFifo.empty()) 1423 goto exit; 1424 1425 DPRINTF(EthernetSM, "\n\n*****processing receive of new packet\n"); 1426 1427 // If we don't have a packet, grab a new one from the fifo. 1428 rxPacket = rxFifo.front(); 1429 rxPktBytes = rxPacket->length; 1430 rxPacketBufPtr = rxPacket->data; 1431 1432#if TRACING_ON 1433 if (DTRACE(Ethernet)) { 1434 if (rxPacket->isIpPkt()) { 1435 ip_header *ip = rxPacket->getIpHdr(); 1436 DPRINTF(Ethernet, "ID is %d\n", reverseEnd16(ip->ID)); 1437 if (rxPacket->isTcpPkt()) { 1438 tcp_header *tcp = rxPacket->getTcpHdr(ip); 1439 DPRINTF(Ethernet, "Src Port = %d, Dest Port = %d\n", 1440 reverseEnd16(tcp->src_port_num), 1441 reverseEnd16(tcp->dest_port_num)); 1442 } 1443 } 1444 } 1445#endif 1446 1447 // sanity check - i think the driver behaves like this 1448 assert(rxDescCnt >= rxPktBytes); 1449 1450 // Must clear the value before popping to decrement the 1451 // reference count 1452 rxFifo.front() = NULL; 1453 rxFifo.pop_front(); 1454 rxFifoCnt -= rxPacket->length; 1455 } 1456 1457 1458 // dont' need the && rxDescCnt > 0 if driver sanity check 1459 // above holds 1460 if (rxPktBytes > 0) { 1461 rxState = rxFragWrite; 1462 // don't need min<>(rxPktBytes,rxDescCnt) if above sanity 1463 // check holds 1464 rxXferLen = rxPktBytes; 1465 1466 rxDmaAddr = rxFragPtr & 0x3fffffff; 1467 rxDmaData = rxPacketBufPtr; 1468 rxDmaLen = rxXferLen; 1469 rxDmaFree = dmaDataFree; 1470 1471 if (doRxDmaWrite()) 1472 goto exit; 1473 1474 } else { 1475 rxState = rxDescWrite; 1476 1477 //if (rxPktBytes == 0) { /* packet is done */ 1478 assert(rxPktBytes == 0); 1479 DPRINTF(EthernetSM, "done with receiving packet\n"); 1480 1481 rxDescCache.cmdsts |= CMDSTS_OWN; 1482 rxDescCache.cmdsts &= ~CMDSTS_MORE; 1483 rxDescCache.cmdsts |= CMDSTS_OK; 1484 rxDescCache.cmdsts &= 0xffff0000; 1485 rxDescCache.cmdsts += rxPacket->length; //i.e. set CMDSTS_SIZE 1486 1487#if 0 1488 /* 1489 * all the driver uses these are for its own stats keeping 1490 * which we don't care about, aren't necessary for 1491 * functionality and doing this would just slow us down. 1492 * if they end up using this in a later version for 1493 * functional purposes, just undef 1494 */ 1495 if (rxFilterEnable) { 1496 rxDescCache.cmdsts &= ~CMDSTS_DEST_MASK; 1497 if (rxFifo.front()->IsUnicast()) 1498 rxDescCache.cmdsts |= CMDSTS_DEST_SELF; 1499 if (rxFifo.front()->IsMulticast()) 1500 rxDescCache.cmdsts |= CMDSTS_DEST_MULTI; 1501 if (rxFifo.front()->IsBroadcast()) 1502 rxDescCache.cmdsts |= CMDSTS_DEST_MASK; 1503 } 1504#endif 1505 1506 if (rxPacket->isIpPkt() && extstsEnable) { 1507 rxDescCache.extsts |= EXTSTS_IPPKT; 1508 rxIPChecksums++; 1509 if (!ipChecksum(rxPacket, false)) { 1510 DPRINTF(EthernetCksum, "Rx IP Checksum Error\n"); 1511 rxDescCache.extsts |= EXTSTS_IPERR; 1512 } 1513 if (rxPacket->isTcpPkt()) { 1514 rxDescCache.extsts |= EXTSTS_TCPPKT; 1515 rxTCPChecksums++; 1516 if (!tcpChecksum(rxPacket, false)) { 1517 DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n"); 1518 rxDescCache.extsts |= EXTSTS_TCPERR; 1519 1520 } 1521 } else if (rxPacket->isUdpPkt()) { 1522 rxDescCache.extsts |= EXTSTS_UDPPKT; 1523 if (!udpChecksum(rxPacket, false)) { 1524 DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n"); 1525 rxDescCache.extsts |= EXTSTS_UDPERR; 1526 } 1527 } 1528 } 1529 rxPacket = 0; 1530 1531 /* 1532 * the driver seems to always receive into desc buffers 1533 * of size 1514, so you never have a pkt that is split 1534 * into multiple descriptors on the receive side, so 1535 * i don't implement that case, hence the assert above. 1536 */ 1537 1538 DPRINTF(EthernetDesc, 1539 "rxDesc writeback:\n\tcmdsts=%08x\n\textsts=%08x\n", 1540 rxDescCache.cmdsts, rxDescCache.extsts); 1541 1542 rxDmaAddr = (regs.rxdp + offsetof(ns_desc, cmdsts)) & 0x3fffffff; 1543 rxDmaData = &(rxDescCache.cmdsts); 1544 rxDmaLen = sizeof(rxDescCache.cmdsts) + sizeof(rxDescCache.extsts); 1545 rxDmaFree = dmaDescFree; 1546 1547 descDmaWrites++; 1548 descDmaWrBytes += rxDmaLen; 1549 1550 if (doRxDmaWrite()) 1551 goto exit; 1552 } 1553 break; 1554 1555 case rxFragWrite: 1556 if (rxDmaState != dmaIdle) 1557 goto exit; 1558 1559 rxPacketBufPtr += rxXferLen; 1560 rxFragPtr += rxXferLen; 1561 rxPktBytes -= rxXferLen; 1562 1563 rxState = rxFifoBlock; 1564 break; 1565 1566 case rxDescWrite: 1567 if (rxDmaState != dmaIdle) 1568 goto exit; 1569 1570 assert(rxDescCache.cmdsts & CMDSTS_OWN); 1571 1572 assert(rxPacket == 0); 1573 devIntrPost(ISR_RXOK); 1574 1575 if (rxDescCache.cmdsts & CMDSTS_INTR) 1576 devIntrPost(ISR_RXDESC); 1577 1578 if (!rxEnable) { 1579 DPRINTF(EthernetSM, "Halting the RX state machine\n"); 1580 rxState = rxIdle; 1581 goto exit; 1582 } else 1583 rxState = rxAdvance; 1584 break; 1585 1586 case rxAdvance: 1587 if (rxDescCache.link == 0) { 1588 devIntrPost(ISR_RXIDLE); 1589 rxState = rxIdle; 1590 CRDD = true; 1591 goto exit; 1592 } else { 1593 rxState = rxDescRead; 1594 regs.rxdp = rxDescCache.link; 1595 CRDD = false; 1596 1597 rxDmaAddr = regs.rxdp & 0x3fffffff; 1598 rxDmaData = &rxDescCache; 1599 rxDmaLen = sizeof(ns_desc); 1600 rxDmaFree = dmaDescFree; 1601 1602 if (doRxDmaRead()) 1603 goto exit; 1604 } 1605 break; 1606 1607 default: 1608 panic("Invalid rxState!"); 1609 } 1610 1611 1612 DPRINTF(EthernetSM, "entering next rx state = %s\n", 1613 NsRxStateStrings[rxState]); 1614 1615 goto next; 1616 1617 exit: 1618 /** 1619 * @todo do we want to schedule a future kick? 1620 */ 1621 DPRINTF(EthernetSM, "rx state machine exited state=%s\n", 1622 NsRxStateStrings[rxState]); 1623} 1624 1625void 1626NSGigE::transmit() 1627{ 1628 if (txFifo.empty()) { 1629 DPRINTF(Ethernet, "nothing to transmit\n"); 1630 return; 1631 } 1632 1633 DPRINTF(Ethernet, "\n\nAttempt Pkt Transmit: txFifo length = %d\n", 1634 maxTxFifoSize - txFifoAvail); 1635 if (interface->sendPacket(txFifo.front())) { 1636#if TRACING_ON 1637 if (DTRACE(Ethernet)) { 1638 if (txFifo.front()->isIpPkt()) { 1639 ip_header *ip = txFifo.front()->getIpHdr(); 1640 DPRINTF(Ethernet, "ID is %d\n", reverseEnd16(ip->ID)); 1641 if (txFifo.front()->isTcpPkt()) { 1642 tcp_header *tcp = txFifo.front()->getTcpHdr(ip); 1643 DPRINTF(Ethernet, "Src Port = %d, Dest Port = %d\n", 1644 reverseEnd16(tcp->src_port_num), 1645 reverseEnd16(tcp->dest_port_num)); 1646 } 1647 } 1648 } 1649#endif 1650 1651 DDUMP(Ethernet, txFifo.front()->data, txFifo.front()->length); 1652 txBytes += txFifo.front()->length; 1653 txPackets++; 1654 1655 txFifoAvail += txFifo.front()->length; 1656 1657 DPRINTF(Ethernet, "Successful Xmit! now txFifoAvail is %d\n", 1658 txFifoAvail); 1659 txFifo.front() = NULL; 1660 txFifo.pop_front(); 1661 1662 /* 1663 * normally do a writeback of the descriptor here, and ONLY 1664 * after that is done, send this interrupt. but since our 1665 * stuff never actually fails, just do this interrupt here, 1666 * otherwise the code has to stray from this nice format. 1667 * besides, it's functionally the same. 1668 */ 1669 devIntrPost(ISR_TXOK); 1670 } else { 1671 DPRINTF(Ethernet, 1672 "May need to rethink always sending the descriptors back?\n"); 1673 } 1674 1675 if (!txFifo.empty() && !txEvent.scheduled()) { 1676 DPRINTF(Ethernet, "reschedule transmit\n"); 1677 txEvent.schedule(curTick + 1000); 1678 } 1679} 1680 1681void 1682NSGigE::txDmaReadCopy() 1683{ 1684 assert(txDmaState == dmaReading); 1685 1686 physmem->dma_read((uint8_t *)txDmaData, txDmaAddr, txDmaLen); 1687 txDmaState = dmaIdle; 1688 1689 DPRINTF(EthernetDMA, "tx dma read paddr=%#x len=%d\n", 1690 txDmaAddr, txDmaLen); 1691 DDUMP(EthernetDMA, txDmaData, txDmaLen); 1692} 1693 1694bool 1695NSGigE::doTxDmaRead() 1696{ 1697 assert(txDmaState == dmaIdle || txDmaState == dmaReadWaiting); 1698 txDmaState = dmaReading; 1699 1700 if (dmaInterface && !txDmaFree) { 1701 if (dmaInterface->busy()) 1702 txDmaState = dmaReadWaiting; 1703 else 1704 dmaInterface->doDMA(Read, txDmaAddr, txDmaLen, curTick, 1705 &txDmaReadEvent, true); 1706 return true; 1707 } 1708 1709 if (dmaReadDelay == 0 && dmaReadFactor == 0.0) { 1710 txDmaReadCopy(); 1711 return false; 1712 } 1713 1714 Tick factor = ((txDmaLen + ULL(63)) >> ULL(6)) * dmaReadFactor; 1715 Tick start = curTick + dmaReadDelay + factor; 1716 txDmaReadEvent.schedule(start); 1717 return true; 1718} 1719 1720void 1721NSGigE::txDmaReadDone() 1722{ 1723 assert(txDmaState == dmaReading); 1724 txDmaReadCopy(); 1725 1726 // If the receive state machine has a pending DMA, let it go first 1727 if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting) 1728 rxKick(); 1729 1730 txKick(); 1731} 1732 1733void 1734NSGigE::txDmaWriteCopy() 1735{ 1736 assert(txDmaState == dmaWriting); 1737 1738 physmem->dma_write(txDmaAddr, (uint8_t *)txDmaData, txDmaLen); 1739 txDmaState = dmaIdle; 1740 1741 DPRINTF(EthernetDMA, "tx dma write paddr=%#x len=%d\n", 1742 txDmaAddr, txDmaLen); 1743 DDUMP(EthernetDMA, txDmaData, txDmaLen); 1744} 1745 1746bool 1747NSGigE::doTxDmaWrite() 1748{ 1749 assert(txDmaState == dmaIdle || txDmaState == dmaWriteWaiting); 1750 txDmaState = dmaWriting; 1751 1752 if (dmaInterface && !txDmaFree) { 1753 if (dmaInterface->busy()) 1754 txDmaState = dmaWriteWaiting; 1755 else 1756 dmaInterface->doDMA(WriteInvalidate, txDmaAddr, txDmaLen, curTick, 1757 &txDmaWriteEvent, true); 1758 return true; 1759 } 1760 1761 if (dmaWriteDelay == 0 && dmaWriteFactor == 0.0) { 1762 txDmaWriteCopy(); 1763 return false; 1764 } 1765 1766 Tick factor = ((txDmaLen + ULL(63)) >> ULL(6)) * dmaWriteFactor; 1767 Tick start = curTick + dmaWriteDelay + factor; 1768 txDmaWriteEvent.schedule(start); 1769 return true; 1770} 1771 1772void 1773NSGigE::txDmaWriteDone() 1774{ 1775 assert(txDmaState == dmaWriting); 1776 txDmaWriteCopy(); 1777 1778 // If the receive state machine has a pending DMA, let it go first 1779 if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting) 1780 rxKick(); 1781 1782 txKick(); 1783} 1784 1785void 1786NSGigE::txKick() 1787{ 1788 DPRINTF(EthernetSM, "transmit kick state=%s\n", NsTxStateStrings[txState]); 1789 1790 if (txKickTick > curTick) { 1791 DPRINTF(EthernetSM, "transmit kick exiting, can't run till %d\n", 1792 txKickTick); 1793 1794 return; 1795 } 1796 1797 next: 1798 switch(txDmaState) { 1799 case dmaReadWaiting: 1800 if (doTxDmaRead()) 1801 goto exit; 1802 break; 1803 case dmaWriteWaiting: 1804 if (doTxDmaWrite()) 1805 goto exit; 1806 break; 1807 default: 1808 break; 1809 } 1810 1811 switch (txState) { 1812 case txIdle: 1813 if (!txEnable) { 1814 DPRINTF(EthernetSM, "Transmit disabled. Nothing to do.\n"); 1815 goto exit; 1816 } 1817 1818 if (CTDD) { 1819 txState = txDescRefr; 1820 1821 txDmaAddr = regs.txdp & 0x3fffffff; 1822 txDmaData = &txDescCache + offsetof(ns_desc, link); 1823 txDmaLen = sizeof(txDescCache.link); 1824 txDmaFree = dmaDescFree; 1825 1826 descDmaReads++; 1827 descDmaRdBytes += txDmaLen; 1828 1829 if (doTxDmaRead()) 1830 goto exit; 1831 1832 } else { 1833 txState = txDescRead; 1834 1835 txDmaAddr = regs.txdp & 0x3fffffff; 1836 txDmaData = &txDescCache; 1837 txDmaLen = sizeof(ns_desc); 1838 txDmaFree = dmaDescFree; 1839 1840 descDmaReads++; 1841 descDmaRdBytes += txDmaLen; 1842 1843 if (doTxDmaRead()) 1844 goto exit; 1845 } 1846 break; 1847 1848 case txDescRefr: 1849 if (txDmaState != dmaIdle) 1850 goto exit; 1851 1852 txState = txAdvance; 1853 break; 1854 1855 case txDescRead: 1856 if (txDmaState != dmaIdle) 1857 goto exit; 1858 1859 DPRINTF(EthernetDesc, 1860 "txDescCache data:\n" 1861 "\tlink=%08x\n" 1862 "\tbufptr=%08x\n" 1863 "\tcmdsts=%08x\n" 1864 "\textsts=%08x\n", 1865 txDescCache.link, txDescCache.bufptr, txDescCache.cmdsts, 1866 txDescCache.extsts); 1867 1868 if (txDescCache.cmdsts & CMDSTS_OWN) { 1869 txState = txFifoBlock; 1870 txFragPtr = txDescCache.bufptr; 1871 txDescCnt = txDescCache.cmdsts & CMDSTS_LEN_MASK; 1872 } else { 1873 devIntrPost(ISR_TXIDLE); 1874 txState = txIdle; 1875 goto exit; 1876 } 1877 break; 1878 1879 case txFifoBlock: 1880 if (!txPacket) { 1881 DPRINTF(EthernetSM, "\n\n*****starting the tx of a new packet\n"); 1882 txPacket = new EtherPacket; 1883 txPacket->data = new uint8_t[16384]; 1884 txPacketBufPtr = txPacket->data; 1885 } 1886 1887 if (txDescCnt == 0) { 1888 DPRINTF(EthernetSM, "the txDescCnt == 0, done with descriptor\n"); 1889 if (txDescCache.cmdsts & CMDSTS_MORE) { 1890 DPRINTF(EthernetSM, "there are more descriptors to come\n"); 1891 txState = txDescWrite; 1892 1893 txDescCache.cmdsts &= ~CMDSTS_OWN; 1894 1895 txDmaAddr = regs.txdp + offsetof(ns_desc, cmdsts); 1896 txDmaAddr &= 0x3fffffff; 1897 txDmaData = &(txDescCache.cmdsts); 1898 txDmaLen = sizeof(txDescCache.cmdsts); 1899 txDmaFree = dmaDescFree; 1900 1901 if (doTxDmaWrite()) 1902 goto exit; 1903 1904 } else { /* this packet is totally done */ 1905 DPRINTF(EthernetSM, "This packet is done, let's wrap it up\n"); 1906 /* deal with the the packet that just finished */ 1907 if ((regs.vtcr & VTCR_PPCHK) && extstsEnable) { 1908 if (txDescCache.extsts & EXTSTS_UDPPKT) { 1909 udpChecksum(txPacket, true); 1910 } else if (txDescCache.extsts & EXTSTS_TCPPKT) { 1911 tcpChecksum(txPacket, true); 1912 txTCPChecksums++; 1913 } 1914 if (txDescCache.extsts & EXTSTS_IPPKT) { 1915 ipChecksum(txPacket, true); 1916 txIPChecksums++; 1917 } 1918 } 1919 1920 txPacket->length = txPacketBufPtr - txPacket->data; 1921 // this is just because the receive can't handle a 1922 // packet bigger want to make sure 1923 assert(txPacket->length <= 1514); 1924 txFifo.push_back(txPacket); 1925 1926 /* 1927 * this following section is not tqo spec, but 1928 * functionally shouldn't be any different. normally, 1929 * the chip will wait til the transmit has occurred 1930 * before writing back the descriptor because it has 1931 * to wait to see that it was successfully transmitted 1932 * to decide whether to set CMDSTS_OK or not. 1933 * however, in the simulator since it is always 1934 * successfully transmitted, and writing it exactly to 1935 * spec would complicate the code, we just do it here 1936 */ 1937 1938 txDescCache.cmdsts &= ~CMDSTS_OWN; 1939 txDescCache.cmdsts |= CMDSTS_OK; 1940 1941 DPRINTF(EthernetDesc, 1942 "txDesc writeback:\n\tcmdsts=%08x\n\textsts=%08x\n", 1943 txDescCache.cmdsts, txDescCache.extsts); 1944 1945 txDmaAddr = regs.txdp + offsetof(ns_desc, cmdsts); 1946 txDmaAddr &= 0x3fffffff; 1947 txDmaData = &(txDescCache.cmdsts); 1948 txDmaLen = sizeof(txDescCache.cmdsts) + 1949 sizeof(txDescCache.extsts); 1950 txDmaFree = dmaDescFree; 1951 1952 descDmaWrites++; 1953 descDmaWrBytes += txDmaLen; 1954 1955 transmit(); 1956 txPacket = 0; 1957 1958 if (!txEnable) { 1959 DPRINTF(EthernetSM, "halting TX state machine\n"); 1960 txState = txIdle; 1961 goto exit; 1962 } else 1963 txState = txAdvance; 1964 1965 if (doTxDmaWrite()) 1966 goto exit; 1967 } 1968 } else { 1969 DPRINTF(EthernetSM, "this descriptor isn't done yet\n"); 1970 if (txFifoAvail) { 1971 txState = txFragRead; 1972 1973 /* 1974 * The number of bytes transferred is either whatever 1975 * is left in the descriptor (txDescCnt), or if there 1976 * is not enough room in the fifo, just whatever room 1977 * is left in the fifo 1978 */ 1979 txXferLen = min<uint32_t>(txDescCnt, txFifoAvail); 1980 1981 txDmaAddr = txFragPtr & 0x3fffffff; 1982 txDmaData = txPacketBufPtr; 1983 txDmaLen = txXferLen; 1984 txDmaFree = dmaDataFree; 1985 1986 if (doTxDmaRead()) 1987 goto exit; 1988 } else { 1989 txState = txFifoBlock; 1990 transmit(); 1991 1992 goto exit; 1993 } 1994 1995 } 1996 break; 1997 1998 case txFragRead: 1999 if (txDmaState != dmaIdle) 2000 goto exit; 2001 2002 txPacketBufPtr += txXferLen; 2003 txFragPtr += txXferLen; 2004 txDescCnt -= txXferLen; 2005 txFifoAvail -= txXferLen; 2006 2007 txState = txFifoBlock; 2008 break; 2009 2010 case txDescWrite: 2011 if (txDmaState != dmaIdle) 2012 goto exit; 2013 2014 if (txDescCache.cmdsts & CMDSTS_INTR) 2015 devIntrPost(ISR_TXDESC); 2016 2017 txState = txAdvance; 2018 break; 2019 2020 case txAdvance: 2021 if (txDescCache.link == 0) { 2022 devIntrPost(ISR_TXIDLE); 2023 txState = txIdle; 2024 goto exit; 2025 } else { 2026 txState = txDescRead; 2027 regs.txdp = txDescCache.link; 2028 CTDD = false; 2029 2030 txDmaAddr = txDescCache.link & 0x3fffffff; 2031 txDmaData = &txDescCache; 2032 txDmaLen = sizeof(ns_desc); 2033 txDmaFree = dmaDescFree; 2034 2035 if (doTxDmaRead()) 2036 goto exit; 2037 } 2038 break; 2039 2040 default: 2041 panic("invalid state"); 2042 } 2043 2044 DPRINTF(EthernetSM, "entering next tx state=%s\n", 2045 NsTxStateStrings[txState]); 2046 2047 goto next; 2048 2049 exit: 2050 /** 2051 * @todo do we want to schedule a future kick? 2052 */ 2053 DPRINTF(EthernetSM, "tx state machine exited state=%s\n", 2054 NsTxStateStrings[txState]); 2055} 2056 2057void 2058NSGigE::transferDone() 2059{ 2060 if (txFifo.empty()) 2061 return; 2062 2063 if (txEvent.scheduled()) 2064 txEvent.reschedule(curTick + 1); 2065 else 2066 txEvent.schedule(curTick + 1); 2067} 2068 2069bool 2070NSGigE::rxFilter(PacketPtr packet) 2071{ 2072 bool drop = true; 2073 string type; 2074 2075 if (packet->IsUnicast()) { 2076 type = "unicast"; 2077 2078 // If we're accepting all unicast addresses 2079 if (acceptUnicast) 2080 drop = false; 2081 2082 // If we make a perfect match 2083 if (acceptPerfect && 2084 memcmp(rom.perfectMatch, packet->data, EADDR_LEN) == 0) 2085 drop = false; 2086 2087 eth_header *eth = (eth_header *) packet->data; 2088 if ((acceptArp) && (eth->type == 0x608)) 2089 drop = false; 2090 2091 } else if (packet->IsBroadcast()) { 2092 type = "broadcast"; 2093 2094 // if we're accepting broadcasts 2095 if (acceptBroadcast) 2096 drop = false; 2097 2098 } else if (packet->IsMulticast()) { 2099 type = "multicast"; 2100 2101 // if we're accepting all multicasts 2102 if (acceptMulticast) 2103 drop = false; 2104 2105 } else { 2106 type = "unknown"; 2107 2108 // oh well, punt on this one 2109 } 2110 2111 if (drop) { 2112 DPRINTF(Ethernet, "rxFilter drop\n"); 2113 DDUMP(EthernetData, packet->data, packet->length); 2114 } 2115 2116 return drop; 2117} 2118 2119bool 2120NSGigE::recvPacket(PacketPtr packet) 2121{ 2122 rxBytes += packet->length; 2123 rxPackets++; 2124 2125 DPRINTF(Ethernet, "\n\nReceiving packet from wire, rxFifoAvail=%d\n", 2126 maxRxFifoSize - rxFifoCnt); 2127 2128 if (!rxEnable) { 2129 DPRINTF(Ethernet, "receive disabled...packet dropped\n"); 2130 interface->recvDone(); 2131 return true; 2132 } 2133 2134 if (rxFilterEnable && rxFilter(packet)) { 2135 DPRINTF(Ethernet, "packet filtered...dropped\n"); 2136 interface->recvDone(); 2137 return true; 2138 } 2139 2140 if ((rxFifoCnt + packet->length) >= maxRxFifoSize) { 2141 DPRINTF(Ethernet, 2142 "packet will not fit in receive buffer...packet dropped\n"); 2143 devIntrPost(ISR_RXORN); 2144 return false; 2145 } 2146 2147 rxFifo.push_back(packet); 2148 rxFifoCnt += packet->length; 2149 interface->recvDone(); 2150 2151 rxKick(); 2152 return true; 2153} 2154 2155/** 2156 * does a udp checksum. if gen is true, then it generates it and puts 2157 * it in the right place else, it just checks what it calculates 2158 * against the value in the header in packet 2159 */ 2160bool 2161NSGigE::udpChecksum(PacketPtr packet, bool gen) 2162{ 2163 ip_header *ip = packet->getIpHdr(); 2164 udp_header *hdr = packet->getUdpHdr(ip); 2165 2166 pseudo_header *pseudo = new pseudo_header; 2167 2168 pseudo->src_ip_addr = ip->src_ip_addr; 2169 pseudo->dest_ip_addr = ip->dest_ip_addr; 2170 pseudo->protocol = ip->protocol; 2171 pseudo->len = hdr->len; 2172 2173 uint16_t cksum = checksumCalc((uint16_t *) pseudo, (uint16_t *) hdr, 2174 (uint32_t) hdr->len); 2175 2176 delete pseudo; 2177 if (gen) 2178 hdr->chksum = cksum; 2179 else 2180 if (cksum != 0) 2181 return false; 2182 2183 return true; 2184} 2185 2186bool 2187NSGigE::tcpChecksum(PacketPtr packet, bool gen) 2188{ 2189 ip_header *ip = packet->getIpHdr(); 2190 tcp_header *hdr = packet->getTcpHdr(ip); 2191 2192 uint16_t cksum; 2193 pseudo_header *pseudo = new pseudo_header; 2194 if (!gen) { 2195 pseudo->src_ip_addr = ip->src_ip_addr; 2196 pseudo->dest_ip_addr = ip->dest_ip_addr; 2197 pseudo->protocol = reverseEnd16(ip->protocol); 2198 pseudo->len = reverseEnd16(reverseEnd16(ip->dgram_len) - 2199 (ip->vers_len & 0xf)*4); 2200 2201 cksum = checksumCalc((uint16_t *) pseudo, (uint16_t *) hdr, 2202 (uint32_t) reverseEnd16(pseudo->len)); 2203 } else { 2204 pseudo->src_ip_addr = 0; 2205 pseudo->dest_ip_addr = 0; 2206 pseudo->protocol = hdr->chksum; 2207 pseudo->len = 0; 2208 hdr->chksum = 0; 2209 cksum = checksumCalc((uint16_t *) pseudo, (uint16_t *) hdr, 2210 (uint32_t) (reverseEnd16(ip->dgram_len) - 2211 (ip->vers_len & 0xf)*4)); 2212 } 2213 2214 delete pseudo; 2215 if (gen) 2216 hdr->chksum = cksum; 2217 else 2218 if (cksum != 0) 2219 return false; 2220 2221 return true; 2222} 2223 2224bool 2225NSGigE::ipChecksum(PacketPtr packet, bool gen) 2226{ 2227 ip_header *hdr = packet->getIpHdr(); 2228 2229 uint16_t cksum = checksumCalc(NULL, (uint16_t *) hdr, 2230 (hdr->vers_len & 0xf)*4); 2231 2232 if (gen) { 2233 DPRINTF(EthernetCksum, "generated checksum: %#x\n", cksum); 2234 hdr->hdr_chksum = cksum; 2235 } 2236 else 2237 if (cksum != 0) 2238 return false; 2239 2240 return true; 2241} 2242 2243uint16_t 2244NSGigE::checksumCalc(uint16_t *pseudo, uint16_t *buf, uint32_t len) 2245{ 2246 uint32_t sum = 0; 2247 2248 uint16_t last_pad = 0; 2249 if (len & 1) { 2250 last_pad = buf[len/2] & 0xff; 2251 len--; 2252 sum += last_pad; 2253 } 2254 2255 if (pseudo) { 2256 sum = pseudo[0] + pseudo[1] + pseudo[2] + 2257 pseudo[3] + pseudo[4] + pseudo[5]; 2258 } 2259 2260 for (int i=0; i < (len/2); ++i) { 2261 sum += buf[i]; 2262 } 2263 2264 while (sum >> 16) 2265 sum = (sum >> 16) + (sum & 0xffff); 2266 2267 return ~sum; 2268} 2269 2270//===================================================================== 2271// 2272// 2273void 2274NSGigE::serialize(ostream &os) 2275{ 2276 // Serialize the PciDev base class 2277 PciDev::serialize(os); 2278 2279 /* 2280 * Finalize any DMA events now. 2281 */ 2282 if (rxDmaReadEvent.scheduled()) 2283 rxDmaReadCopy(); 2284 if (rxDmaWriteEvent.scheduled()) 2285 rxDmaWriteCopy(); 2286 if (txDmaReadEvent.scheduled()) 2287 txDmaReadCopy(); 2288 if (txDmaWriteEvent.scheduled()) 2289 txDmaWriteCopy(); 2290 2291 /* 2292 * Serialize the device registers 2293 */ 2294 SERIALIZE_SCALAR(regs.command); 2295 SERIALIZE_SCALAR(regs.config); 2296 SERIALIZE_SCALAR(regs.mear); 2297 SERIALIZE_SCALAR(regs.ptscr); 2298 SERIALIZE_SCALAR(regs.isr); 2299 SERIALIZE_SCALAR(regs.imr); 2300 SERIALIZE_SCALAR(regs.ier); 2301 SERIALIZE_SCALAR(regs.ihr); 2302 SERIALIZE_SCALAR(regs.txdp); 2303 SERIALIZE_SCALAR(regs.txdp_hi); 2304 SERIALIZE_SCALAR(regs.txcfg); 2305 SERIALIZE_SCALAR(regs.gpior); 2306 SERIALIZE_SCALAR(regs.rxdp); 2307 SERIALIZE_SCALAR(regs.rxdp_hi); 2308 SERIALIZE_SCALAR(regs.rxcfg); 2309 SERIALIZE_SCALAR(regs.pqcr); 2310 SERIALIZE_SCALAR(regs.wcsr); 2311 SERIALIZE_SCALAR(regs.pcr); 2312 SERIALIZE_SCALAR(regs.rfcr); 2313 SERIALIZE_SCALAR(regs.rfdr); 2314 SERIALIZE_SCALAR(regs.srr); 2315 SERIALIZE_SCALAR(regs.mibc); 2316 SERIALIZE_SCALAR(regs.vrcr); 2317 SERIALIZE_SCALAR(regs.vtcr); 2318 SERIALIZE_SCALAR(regs.vdr); 2319 SERIALIZE_SCALAR(regs.ccsr); 2320 SERIALIZE_SCALAR(regs.tbicr); 2321 SERIALIZE_SCALAR(regs.tbisr); 2322 SERIALIZE_SCALAR(regs.tanar); 2323 SERIALIZE_SCALAR(regs.tanlpar); 2324 SERIALIZE_SCALAR(regs.taner); 2325 SERIALIZE_SCALAR(regs.tesr); 2326 2327 SERIALIZE_ARRAY(rom.perfectMatch, EADDR_LEN); 2328 2329 SERIALIZE_SCALAR(ioEnable); 2330 2331 /* 2332 * Serialize the data Fifos 2333 */ 2334 int txNumPkts = txFifo.size(); 2335 SERIALIZE_SCALAR(txNumPkts); 2336 int i = 0; 2337 pktiter_t end = txFifo.end(); 2338 for (pktiter_t p = txFifo.begin(); p != end; ++p) { 2339 nameOut(os, csprintf("%s.txFifo%d", name(), i++)); 2340 (*p)->serialize(os); 2341 } 2342 2343 int rxNumPkts = rxFifo.size(); 2344 SERIALIZE_SCALAR(rxNumPkts); 2345 i = 0; 2346 end = rxFifo.end(); 2347 for (pktiter_t p = rxFifo.begin(); p != end; ++p) { 2348 nameOut(os, csprintf("%s.rxFifo%d", name(), i++)); 2349 (*p)->serialize(os); 2350 } 2351 2352 /* 2353 * Serialize the various helper variables 2354 */ 2355 bool txPacketExists = txPacket; 2356 SERIALIZE_SCALAR(txPacketExists); 2357 if (txPacketExists) { 2358 nameOut(os, csprintf("%s.txPacket", name())); 2359 txPacket->serialize(os); 2360 uint32_t txPktBufPtr = (uint32_t) (txPacketBufPtr - txPacket->data); 2361 SERIALIZE_SCALAR(txPktBufPtr); 2362 } 2363 2364 bool rxPacketExists = rxPacket; 2365 SERIALIZE_SCALAR(rxPacketExists); 2366 if (rxPacketExists) { 2367 nameOut(os, csprintf("%s.rxPacket", name())); 2368 rxPacket->serialize(os); 2369 uint32_t rxPktBufPtr = (uint32_t) (rxPacketBufPtr - rxPacket->data); 2370 SERIALIZE_SCALAR(rxPktBufPtr); 2371 } 2372 2373 SERIALIZE_SCALAR(txXferLen); 2374 SERIALIZE_SCALAR(rxXferLen); 2375 2376 /* 2377 * Serialize DescCaches 2378 */ 2379 SERIALIZE_SCALAR(txDescCache.link); 2380 SERIALIZE_SCALAR(txDescCache.bufptr); 2381 SERIALIZE_SCALAR(txDescCache.cmdsts); 2382 SERIALIZE_SCALAR(txDescCache.extsts); 2383 SERIALIZE_SCALAR(rxDescCache.link); 2384 SERIALIZE_SCALAR(rxDescCache.bufptr); 2385 SERIALIZE_SCALAR(rxDescCache.cmdsts); 2386 SERIALIZE_SCALAR(rxDescCache.extsts); 2387 2388 /* 2389 * Serialize tx state machine 2390 */ 2391 int txState = this->txState; 2392 SERIALIZE_SCALAR(txState); 2393 SERIALIZE_SCALAR(txEnable); 2394 SERIALIZE_SCALAR(CTDD); 2395 SERIALIZE_SCALAR(txFifoAvail); 2396 SERIALIZE_SCALAR(txFragPtr); 2397 SERIALIZE_SCALAR(txDescCnt); 2398 int txDmaState = this->txDmaState; 2399 SERIALIZE_SCALAR(txDmaState); 2400 2401 /* 2402 * Serialize rx state machine 2403 */ 2404 int rxState = this->rxState; 2405 SERIALIZE_SCALAR(rxState); 2406 SERIALIZE_SCALAR(rxEnable); 2407 SERIALIZE_SCALAR(CRDD); 2408 SERIALIZE_SCALAR(rxPktBytes); 2409 SERIALIZE_SCALAR(rxFifoCnt); 2410 SERIALIZE_SCALAR(rxDescCnt); 2411 int rxDmaState = this->rxDmaState; 2412 SERIALIZE_SCALAR(rxDmaState); 2413 2414 SERIALIZE_SCALAR(extstsEnable); 2415 2416 /* 2417 * If there's a pending transmit, store the time so we can 2418 * reschedule it later 2419 */ 2420 Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick : 0; 2421 SERIALIZE_SCALAR(transmitTick); 2422 2423 /* 2424 * receive address filter settings 2425 */ 2426 SERIALIZE_SCALAR(rxFilterEnable); 2427 SERIALIZE_SCALAR(acceptBroadcast); 2428 SERIALIZE_SCALAR(acceptMulticast); 2429 SERIALIZE_SCALAR(acceptUnicast); 2430 SERIALIZE_SCALAR(acceptPerfect); 2431 SERIALIZE_SCALAR(acceptArp); 2432 2433 /* 2434 * Keep track of pending interrupt status. 2435 */ 2436 SERIALIZE_SCALAR(intrTick); 2437 SERIALIZE_SCALAR(cpuPendingIntr); 2438 Tick intrEventTick = 0; 2439 if (intrEvent) 2440 intrEventTick = intrEvent->when(); 2441 SERIALIZE_SCALAR(intrEventTick); 2442 2443} 2444 2445void 2446NSGigE::unserialize(Checkpoint *cp, const std::string §ion) 2447{ 2448 // Unserialize the PciDev base class 2449 PciDev::unserialize(cp, section); 2450 2451 UNSERIALIZE_SCALAR(regs.command); 2452 UNSERIALIZE_SCALAR(regs.config); 2453 UNSERIALIZE_SCALAR(regs.mear); 2454 UNSERIALIZE_SCALAR(regs.ptscr); 2455 UNSERIALIZE_SCALAR(regs.isr); 2456 UNSERIALIZE_SCALAR(regs.imr); 2457 UNSERIALIZE_SCALAR(regs.ier); 2458 UNSERIALIZE_SCALAR(regs.ihr); 2459 UNSERIALIZE_SCALAR(regs.txdp); 2460 UNSERIALIZE_SCALAR(regs.txdp_hi); 2461 UNSERIALIZE_SCALAR(regs.txcfg); 2462 UNSERIALIZE_SCALAR(regs.gpior); 2463 UNSERIALIZE_SCALAR(regs.rxdp); 2464 UNSERIALIZE_SCALAR(regs.rxdp_hi); 2465 UNSERIALIZE_SCALAR(regs.rxcfg); 2466 UNSERIALIZE_SCALAR(regs.pqcr); 2467 UNSERIALIZE_SCALAR(regs.wcsr); 2468 UNSERIALIZE_SCALAR(regs.pcr); 2469 UNSERIALIZE_SCALAR(regs.rfcr); 2470 UNSERIALIZE_SCALAR(regs.rfdr); 2471 UNSERIALIZE_SCALAR(regs.srr); 2472 UNSERIALIZE_SCALAR(regs.mibc); 2473 UNSERIALIZE_SCALAR(regs.vrcr); 2474 UNSERIALIZE_SCALAR(regs.vtcr); 2475 UNSERIALIZE_SCALAR(regs.vdr); 2476 UNSERIALIZE_SCALAR(regs.ccsr); 2477 UNSERIALIZE_SCALAR(regs.tbicr); 2478 UNSERIALIZE_SCALAR(regs.tbisr); 2479 UNSERIALIZE_SCALAR(regs.tanar); 2480 UNSERIALIZE_SCALAR(regs.tanlpar); 2481 UNSERIALIZE_SCALAR(regs.taner); 2482 UNSERIALIZE_SCALAR(regs.tesr); 2483 2484 UNSERIALIZE_ARRAY(rom.perfectMatch, EADDR_LEN); 2485 2486 UNSERIALIZE_SCALAR(ioEnable); 2487 2488 /* 2489 * unserialize the data fifos 2490 */ 2491 int txNumPkts; 2492 UNSERIALIZE_SCALAR(txNumPkts); 2493 int i; 2494 for (i = 0; i < txNumPkts; ++i) { 2495 PacketPtr p = new EtherPacket; 2496 p->unserialize(cp, csprintf("%s.rxFifo%d", section, i)); 2497 txFifo.push_back(p); 2498 } 2499 2500 int rxNumPkts; 2501 UNSERIALIZE_SCALAR(rxNumPkts); 2502 for (i = 0; i < rxNumPkts; ++i) { 2503 PacketPtr p = new EtherPacket; 2504 p->unserialize(cp, csprintf("%s.rxFifo%d", section, i)); 2505 rxFifo.push_back(p); 2506 } 2507 2508 /* 2509 * unserialize the various helper variables 2510 */ 2511 bool txPacketExists; 2512 UNSERIALIZE_SCALAR(txPacketExists); 2513 if (txPacketExists) { 2514 txPacket = new EtherPacket; 2515 txPacket->unserialize(cp, csprintf("%s.txPacket", section)); 2516 uint32_t txPktBufPtr; 2517 UNSERIALIZE_SCALAR(txPktBufPtr); 2518 txPacketBufPtr = (uint8_t *) txPacket->data + txPktBufPtr; 2519 } else 2520 txPacket = 0; 2521 2522 bool rxPacketExists; 2523 UNSERIALIZE_SCALAR(rxPacketExists); 2524 rxPacket = 0; 2525 if (rxPacketExists) { 2526 rxPacket = new EtherPacket; 2527 rxPacket->unserialize(cp, csprintf("%s.rxPacket", section)); 2528 uint32_t rxPktBufPtr; 2529 UNSERIALIZE_SCALAR(rxPktBufPtr); 2530 rxPacketBufPtr = (uint8_t *) rxPacket->data + rxPktBufPtr; 2531 } else 2532 rxPacket = 0; 2533 2534 UNSERIALIZE_SCALAR(txXferLen); 2535 UNSERIALIZE_SCALAR(rxXferLen); 2536 2537 /* 2538 * Unserialize DescCaches 2539 */ 2540 UNSERIALIZE_SCALAR(txDescCache.link); 2541 UNSERIALIZE_SCALAR(txDescCache.bufptr); 2542 UNSERIALIZE_SCALAR(txDescCache.cmdsts); 2543 UNSERIALIZE_SCALAR(txDescCache.extsts); 2544 UNSERIALIZE_SCALAR(rxDescCache.link); 2545 UNSERIALIZE_SCALAR(rxDescCache.bufptr); 2546 UNSERIALIZE_SCALAR(rxDescCache.cmdsts); 2547 UNSERIALIZE_SCALAR(rxDescCache.extsts); 2548 2549 /* 2550 * unserialize tx state machine 2551 */ 2552 int txState; 2553 UNSERIALIZE_SCALAR(txState); 2554 this->txState = (TxState) txState; 2555 UNSERIALIZE_SCALAR(txEnable); 2556 UNSERIALIZE_SCALAR(CTDD); 2557 UNSERIALIZE_SCALAR(txFifoAvail); 2558 UNSERIALIZE_SCALAR(txFragPtr); 2559 UNSERIALIZE_SCALAR(txDescCnt); 2560 int txDmaState; 2561 UNSERIALIZE_SCALAR(txDmaState); 2562 this->txDmaState = (DmaState) txDmaState; 2563 2564 /* 2565 * unserialize rx state machine 2566 */ 2567 int rxState; 2568 UNSERIALIZE_SCALAR(rxState); 2569 this->rxState = (RxState) rxState; 2570 UNSERIALIZE_SCALAR(rxEnable); 2571 UNSERIALIZE_SCALAR(CRDD); 2572 UNSERIALIZE_SCALAR(rxPktBytes); 2573 UNSERIALIZE_SCALAR(rxFifoCnt); 2574 UNSERIALIZE_SCALAR(rxDescCnt); 2575 int rxDmaState; 2576 UNSERIALIZE_SCALAR(rxDmaState); 2577 this->rxDmaState = (DmaState) rxDmaState; 2578 2579 UNSERIALIZE_SCALAR(extstsEnable); 2580 2581 /* 2582 * If there's a pending transmit, reschedule it now 2583 */ 2584 Tick transmitTick; 2585 UNSERIALIZE_SCALAR(transmitTick); 2586 if (transmitTick) 2587 txEvent.schedule(curTick + transmitTick); 2588 2589 /* 2590 * unserialize receive address filter settings 2591 */ 2592 UNSERIALIZE_SCALAR(rxFilterEnable); 2593 UNSERIALIZE_SCALAR(acceptBroadcast); 2594 UNSERIALIZE_SCALAR(acceptMulticast); 2595 UNSERIALIZE_SCALAR(acceptUnicast); 2596 UNSERIALIZE_SCALAR(acceptPerfect); 2597 UNSERIALIZE_SCALAR(acceptArp); 2598 2599 /* 2600 * Keep track of pending interrupt status. 2601 */ 2602 UNSERIALIZE_SCALAR(intrTick); 2603 UNSERIALIZE_SCALAR(cpuPendingIntr); 2604 Tick intrEventTick; 2605 UNSERIALIZE_SCALAR(intrEventTick); 2606 if (intrEventTick) { 2607 intrEvent = new IntrEvent(this, true); 2608 intrEvent->schedule(intrEventTick); 2609 } 2610 2611 /* 2612 * re-add addrRanges to bus bridges 2613 */ 2614 if (pioInterface) { 2615 pioInterface->addAddrRange(BARAddrs[0], BARAddrs[0] + BARSize[0] - 1); 2616 pioInterface->addAddrRange(BARAddrs[1], BARAddrs[1] + BARSize[1] - 1); 2617 } 2618} 2619 2620Tick 2621NSGigE::cacheAccess(MemReqPtr &req) 2622{ 2623 DPRINTF(EthernetPIO, "timing access to paddr=%#x (daddr=%#x)\n", 2624 req->paddr, req->paddr - addr); 2625 return curTick + pioLatency; 2626} 2627//===================================================================== 2628 2629 2630//********** helper functions****************************************** 2631 2632uint16_t reverseEnd16(uint16_t num) 2633{ 2634 uint16_t reverse = (num & 0xff)<<8; 2635 reverse += ((num & 0xff00) >> 8); 2636 return reverse; 2637} 2638 2639uint32_t reverseEnd32(uint32_t num) 2640{ 2641 uint32_t reverse = (reverseEnd16(num & 0xffff)) << 16; 2642 reverse += reverseEnd16((uint16_t) ((num & 0xffff0000) >> 8)); 2643 return reverse; 2644} 2645 2646 2647 2648//===================================================================== 2649 2650BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt) 2651 2652 SimObjectParam<EtherInt *> peer; 2653 SimObjectParam<NSGigE *> device; 2654 2655END_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt) 2656 2657BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigEInt) 2658 2659 INIT_PARAM_DFLT(peer, "peer interface", NULL), 2660 INIT_PARAM(device, "Ethernet device of this interface") 2661 2662END_INIT_SIM_OBJECT_PARAMS(NSGigEInt) 2663 2664CREATE_SIM_OBJECT(NSGigEInt) 2665{ 2666 NSGigEInt *dev_int = new NSGigEInt(getInstanceName(), device); 2667 2668 EtherInt *p = (EtherInt *)peer; 2669 if (p) { 2670 dev_int->setPeer(p); 2671 p->setPeer(dev_int); 2672 } 2673 2674 return dev_int; 2675} 2676 2677REGISTER_SIM_OBJECT("NSGigEInt", NSGigEInt) 2678 2679 2680BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE) 2681 2682 Param<Tick> tx_delay; 2683 Param<Tick> rx_delay; 2684 SimObjectParam<IntrControl *> intr_ctrl; 2685 Param<Tick> intr_delay; 2686 SimObjectParam<MemoryController *> mmu; 2687 SimObjectParam<PhysicalMemory *> physmem; 2688 Param<bool> rx_filter; 2689 Param<string> hardware_address; 2690 SimObjectParam<Bus*> header_bus; 2691 SimObjectParam<Bus*> payload_bus; 2692 SimObjectParam<HierParams *> hier; 2693 Param<Tick> pio_latency; 2694 Param<bool> dma_desc_free; 2695 Param<bool> dma_data_free; 2696 Param<Tick> dma_read_delay; 2697 Param<Tick> dma_write_delay; 2698 Param<Tick> dma_read_factor; 2699 Param<Tick> dma_write_factor; 2700 SimObjectParam<PciConfigAll *> configspace; 2701 SimObjectParam<PciConfigData *> configdata; 2702 SimObjectParam<Tsunami *> tsunami; 2703 Param<uint32_t> pci_bus; 2704 Param<uint32_t> pci_dev; 2705 Param<uint32_t> pci_func; 2706 Param<uint32_t> tx_fifo_size; 2707 Param<uint32_t> rx_fifo_size; 2708 2709END_DECLARE_SIM_OBJECT_PARAMS(NSGigE) 2710 2711BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE) 2712 2713 INIT_PARAM_DFLT(tx_delay, "Transmit Delay", 1000), 2714 INIT_PARAM_DFLT(rx_delay, "Receive Delay", 1000), 2715 INIT_PARAM(intr_ctrl, "Interrupt Controller"), 2716 INIT_PARAM_DFLT(intr_delay, "Interrupt Delay in microseconds", 0), 2717 INIT_PARAM(mmu, "Memory Controller"), 2718 INIT_PARAM(physmem, "Physical Memory"), 2719 INIT_PARAM_DFLT(rx_filter, "Enable Receive Filter", true), 2720 INIT_PARAM_DFLT(hardware_address, "Ethernet Hardware Address", 2721 "00:99:00:00:00:01"), 2722 INIT_PARAM_DFLT(header_bus, "The IO Bus to attach to for headers", NULL), 2723 INIT_PARAM_DFLT(payload_bus, "The IO Bus to attach to for payload", NULL), 2724 INIT_PARAM_DFLT(hier, "Hierarchy global variables", &defaultHierParams), 2725 INIT_PARAM_DFLT(pio_latency, "Programmed IO latency in bus cycles", 1), 2726 INIT_PARAM_DFLT(dma_desc_free, "DMA of Descriptors is free", false), 2727 INIT_PARAM_DFLT(dma_data_free, "DMA of Data is free", false), 2728 INIT_PARAM_DFLT(dma_read_delay, "fixed delay for dma reads", 0), 2729 INIT_PARAM_DFLT(dma_write_delay, "fixed delay for dma writes", 0), 2730 INIT_PARAM_DFLT(dma_read_factor, "multiplier for dma reads", 0), 2731 INIT_PARAM_DFLT(dma_write_factor, "multiplier for dma writes", 0), 2732 INIT_PARAM(configspace, "PCI Configspace"), 2733 INIT_PARAM(configdata, "PCI Config data"), 2734 INIT_PARAM(tsunami, "Tsunami"), 2735 INIT_PARAM(pci_bus, "PCI bus"), 2736 INIT_PARAM(pci_dev, "PCI device number"), 2737 INIT_PARAM(pci_func, "PCI function code"), 2738 INIT_PARAM_DFLT(tx_fifo_size, "max size in bytes of txFifo", 131072), 2739 INIT_PARAM_DFLT(rx_fifo_size, "max size in bytes of rxFifo", 131072) 2740 2741END_INIT_SIM_OBJECT_PARAMS(NSGigE) 2742 2743 2744CREATE_SIM_OBJECT(NSGigE) 2745{ 2746 int eaddr[6]; 2747 sscanf(((string)hardware_address).c_str(), "%x:%x:%x:%x:%x:%x", 2748 &eaddr[0], &eaddr[1], &eaddr[2], &eaddr[3], &eaddr[4], &eaddr[5]); 2749 2750 return new NSGigE(getInstanceName(), intr_ctrl, intr_delay, 2751 physmem, tx_delay, rx_delay, mmu, hier, header_bus, 2752 payload_bus, pio_latency, dma_desc_free, dma_data_free, 2753 dma_read_delay, dma_write_delay, dma_read_factor, 2754 dma_write_factor, configspace, configdata, 2755 tsunami, pci_bus, pci_dev, pci_func, rx_filter, eaddr, 2756 tx_fifo_size, rx_fifo_size); 2757} 2758 2759REGISTER_SIM_OBJECT("NSGigE", NSGigE) 2760