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