ns_gige.cc revision 2107
19020Sgblack@eecs.umich.edu/* 29020Sgblack@eecs.umich.edu * Copyright (c) 2004-2005 The Regents of The University of Michigan 39020Sgblack@eecs.umich.edu * All rights reserved. 49020Sgblack@eecs.umich.edu * 59020Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 69020Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 79020Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 89020Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 99020Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 109020Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 119020Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 129020Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 139020Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 149020Sgblack@eecs.umich.edu * this software without specific prior written permission. 159020Sgblack@eecs.umich.edu * 169020Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 179020Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 189020Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 199020Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 209020Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 219020Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 229020Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 239020Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 249020Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 259020Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 269020Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 279020Sgblack@eecs.umich.edu */ 289020Sgblack@eecs.umich.edu 299020Sgblack@eecs.umich.edu/** @file 309020Sgblack@eecs.umich.edu * Device module for modelling the National Semiconductor 319020Sgblack@eecs.umich.edu * DP83820 ethernet controller. Does not support priority queueing 329020Sgblack@eecs.umich.edu */ 339020Sgblack@eecs.umich.edu#include <cstdio> 349023Sgblack@eecs.umich.edu#include <deque> 359022Sgblack@eecs.umich.edu#include <string> 369022Sgblack@eecs.umich.edu 379022Sgblack@eecs.umich.edu#include "base/inet.hh" 389023Sgblack@eecs.umich.edu#include "cpu/exec_context.hh" 399023Sgblack@eecs.umich.edu#include "dev/etherlink.hh" 409023Sgblack@eecs.umich.edu#include "dev/ns_gige.hh" 419020Sgblack@eecs.umich.edu#include "dev/pciconfigall.hh" 429020Sgblack@eecs.umich.edu#include "mem/bus/bus.hh" 439020Sgblack@eecs.umich.edu#include "mem/bus/dma_interface.hh" 449020Sgblack@eecs.umich.edu#include "mem/bus/pio_interface.hh" 459022Sgblack@eecs.umich.edu#include "mem/bus/pio_interface_impl.hh" 469022Sgblack@eecs.umich.edu#include "mem/functional/memory_control.hh" 479022Sgblack@eecs.umich.edu#include "mem/functional/physical.hh" 489023Sgblack@eecs.umich.edu#include "sim/builder.hh" 499023Sgblack@eecs.umich.edu#include "sim/debug.hh" 509023Sgblack@eecs.umich.edu#include "sim/host.hh" 519023Sgblack@eecs.umich.edu#include "sim/stats.hh" 529023Sgblack@eecs.umich.edu#include "targetarch/vtophys.hh" 539023Sgblack@eecs.umich.edu 549023Sgblack@eecs.umich.educonst char *NsRxStateStrings[] = 559023Sgblack@eecs.umich.edu{ 569023Sgblack@eecs.umich.edu "rxIdle", 579023Sgblack@eecs.umich.edu "rxDescRefr", 589023Sgblack@eecs.umich.edu "rxDescRead", 599023Sgblack@eecs.umich.edu "rxFifoBlock", 609023Sgblack@eecs.umich.edu "rxFragWrite", 619023Sgblack@eecs.umich.edu "rxDescWrite", 629023Sgblack@eecs.umich.edu "rxAdvance" 639023Sgblack@eecs.umich.edu}; 649023Sgblack@eecs.umich.edu 659023Sgblack@eecs.umich.educonst char *NsTxStateStrings[] = 669023Sgblack@eecs.umich.edu{ 679023Sgblack@eecs.umich.edu "txIdle", 689023Sgblack@eecs.umich.edu "txDescRefr", 699023Sgblack@eecs.umich.edu "txDescRead", 709023Sgblack@eecs.umich.edu "txFifoBlock", 719023Sgblack@eecs.umich.edu "txFragRead", 729023Sgblack@eecs.umich.edu "txDescWrite", 739023Sgblack@eecs.umich.edu "txAdvance" 749023Sgblack@eecs.umich.edu}; 759023Sgblack@eecs.umich.edu 769023Sgblack@eecs.umich.educonst char *NsDmaState[] = 779023Sgblack@eecs.umich.edu{ 789023Sgblack@eecs.umich.edu "dmaIdle", 799023Sgblack@eecs.umich.edu "dmaReading", 809023Sgblack@eecs.umich.edu "dmaWriting", 819023Sgblack@eecs.umich.edu "dmaReadWaiting", 829023Sgblack@eecs.umich.edu "dmaWriteWaiting" 839023Sgblack@eecs.umich.edu}; 849023Sgblack@eecs.umich.edu 859023Sgblack@eecs.umich.eduusing namespace std; 869023Sgblack@eecs.umich.eduusing namespace Net; 879023Sgblack@eecs.umich.eduusing namespace TheISA; 889023Sgblack@eecs.umich.edu 899023Sgblack@eecs.umich.edu/////////////////////////////////////////////////////////////////////// 909023Sgblack@eecs.umich.edu// 919023Sgblack@eecs.umich.edu// NSGigE PCI Device 929023Sgblack@eecs.umich.edu// 939023Sgblack@eecs.umich.eduNSGigE::NSGigE(Params *p) 949023Sgblack@eecs.umich.edu : PciDev(p), ioEnable(false), 959023Sgblack@eecs.umich.edu txFifo(p->tx_fifo_size), rxFifo(p->rx_fifo_size), 969023Sgblack@eecs.umich.edu txPacket(0), rxPacket(0), txPacketBufPtr(NULL), rxPacketBufPtr(NULL), 979023Sgblack@eecs.umich.edu txXferLen(0), rxXferLen(0), clock(p->clock), 989023Sgblack@eecs.umich.edu txState(txIdle), txEnable(false), CTDD(false), 999023Sgblack@eecs.umich.edu txFragPtr(0), txDescCnt(0), txDmaState(dmaIdle), rxState(rxIdle), 1009023Sgblack@eecs.umich.edu rxEnable(false), CRDD(false), rxPktBytes(0), 1019023Sgblack@eecs.umich.edu rxFragPtr(0), rxDescCnt(0), rxDmaState(dmaIdle), extstsEnable(false), 1029023Sgblack@eecs.umich.edu eepromState(eepromStart), rxDmaReadEvent(this), rxDmaWriteEvent(this), 1039023Sgblack@eecs.umich.edu txDmaReadEvent(this), txDmaWriteEvent(this), 1049023Sgblack@eecs.umich.edu dmaDescFree(p->dma_desc_free), dmaDataFree(p->dma_data_free), 1059023Sgblack@eecs.umich.edu txDelay(p->tx_delay), rxDelay(p->rx_delay), 1069023Sgblack@eecs.umich.edu rxKickTick(0), rxKickEvent(this), txKickTick(0), txKickEvent(this), 1079023Sgblack@eecs.umich.edu txEvent(this), rxFilterEnable(p->rx_filter), acceptBroadcast(false), 1089023Sgblack@eecs.umich.edu acceptMulticast(false), acceptUnicast(false), 1099023Sgblack@eecs.umich.edu acceptPerfect(false), acceptArp(false), multicastHashEnable(false), 1109023Sgblack@eecs.umich.edu physmem(p->pmem), intrTick(0), cpuPendingIntr(false), 1119022Sgblack@eecs.umich.edu intrEvent(0), interface(0) 1129022Sgblack@eecs.umich.edu{ 1139022Sgblack@eecs.umich.edu if (p->pio_bus) { 1149022Sgblack@eecs.umich.edu pioInterface = newPioInterface(name() + ".pio", p->hier, 1159022Sgblack@eecs.umich.edu p->pio_bus, this, 1169022Sgblack@eecs.umich.edu &NSGigE::cacheAccess); 1179022Sgblack@eecs.umich.edu pioLatency = p->pio_latency * p->pio_bus->clockRate; 1189022Sgblack@eecs.umich.edu } 1199022Sgblack@eecs.umich.edu 1209022Sgblack@eecs.umich.edu if (p->header_bus) { 1219022Sgblack@eecs.umich.edu if (p->payload_bus) 1229022Sgblack@eecs.umich.edu dmaInterface = new DMAInterface<Bus>(name() + ".dma", 1239022Sgblack@eecs.umich.edu p->header_bus, 1249022Sgblack@eecs.umich.edu p->payload_bus, 1, 1259023Sgblack@eecs.umich.edu p->dma_no_allocate); 1269023Sgblack@eecs.umich.edu else 1279023Sgblack@eecs.umich.edu dmaInterface = new DMAInterface<Bus>(name() + ".dma", 1289023Sgblack@eecs.umich.edu p->header_bus, 1299023Sgblack@eecs.umich.edu p->header_bus, 1, 1309023Sgblack@eecs.umich.edu p->dma_no_allocate); 1319023Sgblack@eecs.umich.edu } else if (p->payload_bus) 1329023Sgblack@eecs.umich.edu panic("Must define a header bus if defining a payload bus"); 1339023Sgblack@eecs.umich.edu 1349022Sgblack@eecs.umich.edu pioDelayWrite = p->pio_delay_write && pioInterface; 1359020Sgblack@eecs.umich.edu 1369020Sgblack@eecs.umich.edu intrDelay = p->intr_delay; 1379020Sgblack@eecs.umich.edu dmaReadDelay = p->dma_read_delay; 1389020Sgblack@eecs.umich.edu dmaWriteDelay = p->dma_write_delay; 139 dmaReadFactor = p->dma_read_factor; 140 dmaWriteFactor = p->dma_write_factor; 141 142 regsReset(); 143 memcpy(&rom.perfectMatch, p->eaddr.bytes(), ETH_ADDR_LEN); 144 145 memset(&rxDesc32, 0, sizeof(rxDesc32)); 146 memset(&txDesc32, 0, sizeof(txDesc32)); 147 memset(&rxDesc64, 0, sizeof(rxDesc64)); 148 memset(&txDesc64, 0, sizeof(txDesc64)); 149} 150 151NSGigE::~NSGigE() 152{} 153 154void 155NSGigE::regStats() 156{ 157 txBytes 158 .name(name() + ".txBytes") 159 .desc("Bytes Transmitted") 160 .prereq(txBytes) 161 ; 162 163 rxBytes 164 .name(name() + ".rxBytes") 165 .desc("Bytes Received") 166 .prereq(rxBytes) 167 ; 168 169 txPackets 170 .name(name() + ".txPackets") 171 .desc("Number of Packets Transmitted") 172 .prereq(txBytes) 173 ; 174 175 rxPackets 176 .name(name() + ".rxPackets") 177 .desc("Number of Packets Received") 178 .prereq(rxBytes) 179 ; 180 181 txIpChecksums 182 .name(name() + ".txIpChecksums") 183 .desc("Number of tx IP Checksums done by device") 184 .precision(0) 185 .prereq(txBytes) 186 ; 187 188 rxIpChecksums 189 .name(name() + ".rxIpChecksums") 190 .desc("Number of rx IP Checksums done by device") 191 .precision(0) 192 .prereq(rxBytes) 193 ; 194 195 txTcpChecksums 196 .name(name() + ".txTcpChecksums") 197 .desc("Number of tx TCP Checksums done by device") 198 .precision(0) 199 .prereq(txBytes) 200 ; 201 202 rxTcpChecksums 203 .name(name() + ".rxTcpChecksums") 204 .desc("Number of rx TCP Checksums done by device") 205 .precision(0) 206 .prereq(rxBytes) 207 ; 208 209 txUdpChecksums 210 .name(name() + ".txUdpChecksums") 211 .desc("Number of tx UDP Checksums done by device") 212 .precision(0) 213 .prereq(txBytes) 214 ; 215 216 rxUdpChecksums 217 .name(name() + ".rxUdpChecksums") 218 .desc("Number of rx UDP Checksums done by device") 219 .precision(0) 220 .prereq(rxBytes) 221 ; 222 223 descDmaReads 224 .name(name() + ".descDMAReads") 225 .desc("Number of descriptors the device read w/ DMA") 226 .precision(0) 227 ; 228 229 descDmaWrites 230 .name(name() + ".descDMAWrites") 231 .desc("Number of descriptors the device wrote w/ DMA") 232 .precision(0) 233 ; 234 235 descDmaRdBytes 236 .name(name() + ".descDmaReadBytes") 237 .desc("number of descriptor bytes read w/ DMA") 238 .precision(0) 239 ; 240 241 descDmaWrBytes 242 .name(name() + ".descDmaWriteBytes") 243 .desc("number of descriptor bytes write w/ DMA") 244 .precision(0) 245 ; 246 247 txBandwidth 248 .name(name() + ".txBandwidth") 249 .desc("Transmit Bandwidth (bits/s)") 250 .precision(0) 251 .prereq(txBytes) 252 ; 253 254 rxBandwidth 255 .name(name() + ".rxBandwidth") 256 .desc("Receive Bandwidth (bits/s)") 257 .precision(0) 258 .prereq(rxBytes) 259 ; 260 261 totBandwidth 262 .name(name() + ".totBandwidth") 263 .desc("Total Bandwidth (bits/s)") 264 .precision(0) 265 .prereq(totBytes) 266 ; 267 268 totPackets 269 .name(name() + ".totPackets") 270 .desc("Total Packets") 271 .precision(0) 272 .prereq(totBytes) 273 ; 274 275 totBytes 276 .name(name() + ".totBytes") 277 .desc("Total Bytes") 278 .precision(0) 279 .prereq(totBytes) 280 ; 281 282 totPacketRate 283 .name(name() + ".totPPS") 284 .desc("Total Tranmission Rate (packets/s)") 285 .precision(0) 286 .prereq(totBytes) 287 ; 288 289 txPacketRate 290 .name(name() + ".txPPS") 291 .desc("Packet Tranmission Rate (packets/s)") 292 .precision(0) 293 .prereq(txBytes) 294 ; 295 296 rxPacketRate 297 .name(name() + ".rxPPS") 298 .desc("Packet Reception Rate (packets/s)") 299 .precision(0) 300 .prereq(rxBytes) 301 ; 302 303 postedSwi 304 .name(name() + ".postedSwi") 305 .desc("number of software interrupts posted to CPU") 306 .precision(0) 307 ; 308 309 totalSwi 310 .name(name() + ".totalSwi") 311 .desc("total number of Swi written to ISR") 312 .precision(0) 313 ; 314 315 coalescedSwi 316 .name(name() + ".coalescedSwi") 317 .desc("average number of Swi's coalesced into each post") 318 .precision(0) 319 ; 320 321 postedRxIdle 322 .name(name() + ".postedRxIdle") 323 .desc("number of rxIdle interrupts posted to CPU") 324 .precision(0) 325 ; 326 327 totalRxIdle 328 .name(name() + ".totalRxIdle") 329 .desc("total number of RxIdle written to ISR") 330 .precision(0) 331 ; 332 333 coalescedRxIdle 334 .name(name() + ".coalescedRxIdle") 335 .desc("average number of RxIdle's coalesced into each post") 336 .precision(0) 337 ; 338 339 postedRxOk 340 .name(name() + ".postedRxOk") 341 .desc("number of RxOk interrupts posted to CPU") 342 .precision(0) 343 ; 344 345 totalRxOk 346 .name(name() + ".totalRxOk") 347 .desc("total number of RxOk written to ISR") 348 .precision(0) 349 ; 350 351 coalescedRxOk 352 .name(name() + ".coalescedRxOk") 353 .desc("average number of RxOk's coalesced into each post") 354 .precision(0) 355 ; 356 357 postedRxDesc 358 .name(name() + ".postedRxDesc") 359 .desc("number of RxDesc interrupts posted to CPU") 360 .precision(0) 361 ; 362 363 totalRxDesc 364 .name(name() + ".totalRxDesc") 365 .desc("total number of RxDesc written to ISR") 366 .precision(0) 367 ; 368 369 coalescedRxDesc 370 .name(name() + ".coalescedRxDesc") 371 .desc("average number of RxDesc's coalesced into each post") 372 .precision(0) 373 ; 374 375 postedTxOk 376 .name(name() + ".postedTxOk") 377 .desc("number of TxOk interrupts posted to CPU") 378 .precision(0) 379 ; 380 381 totalTxOk 382 .name(name() + ".totalTxOk") 383 .desc("total number of TxOk written to ISR") 384 .precision(0) 385 ; 386 387 coalescedTxOk 388 .name(name() + ".coalescedTxOk") 389 .desc("average number of TxOk's coalesced into each post") 390 .precision(0) 391 ; 392 393 postedTxIdle 394 .name(name() + ".postedTxIdle") 395 .desc("number of TxIdle interrupts posted to CPU") 396 .precision(0) 397 ; 398 399 totalTxIdle 400 .name(name() + ".totalTxIdle") 401 .desc("total number of TxIdle written to ISR") 402 .precision(0) 403 ; 404 405 coalescedTxIdle 406 .name(name() + ".coalescedTxIdle") 407 .desc("average number of TxIdle's coalesced into each post") 408 .precision(0) 409 ; 410 411 postedTxDesc 412 .name(name() + ".postedTxDesc") 413 .desc("number of TxDesc interrupts posted to CPU") 414 .precision(0) 415 ; 416 417 totalTxDesc 418 .name(name() + ".totalTxDesc") 419 .desc("total number of TxDesc written to ISR") 420 .precision(0) 421 ; 422 423 coalescedTxDesc 424 .name(name() + ".coalescedTxDesc") 425 .desc("average number of TxDesc's coalesced into each post") 426 .precision(0) 427 ; 428 429 postedRxOrn 430 .name(name() + ".postedRxOrn") 431 .desc("number of RxOrn posted to CPU") 432 .precision(0) 433 ; 434 435 totalRxOrn 436 .name(name() + ".totalRxOrn") 437 .desc("total number of RxOrn written to ISR") 438 .precision(0) 439 ; 440 441 coalescedRxOrn 442 .name(name() + ".coalescedRxOrn") 443 .desc("average number of RxOrn's coalesced into each post") 444 .precision(0) 445 ; 446 447 coalescedTotal 448 .name(name() + ".coalescedTotal") 449 .desc("average number of interrupts coalesced into each post") 450 .precision(0) 451 ; 452 453 postedInterrupts 454 .name(name() + ".postedInterrupts") 455 .desc("number of posts to CPU") 456 .precision(0) 457 ; 458 459 droppedPackets 460 .name(name() + ".droppedPackets") 461 .desc("number of packets dropped") 462 .precision(0) 463 ; 464 465 coalescedSwi = totalSwi / postedInterrupts; 466 coalescedRxIdle = totalRxIdle / postedInterrupts; 467 coalescedRxOk = totalRxOk / postedInterrupts; 468 coalescedRxDesc = totalRxDesc / postedInterrupts; 469 coalescedTxOk = totalTxOk / postedInterrupts; 470 coalescedTxIdle = totalTxIdle / postedInterrupts; 471 coalescedTxDesc = totalTxDesc / postedInterrupts; 472 coalescedRxOrn = totalRxOrn / postedInterrupts; 473 474 coalescedTotal = (totalSwi + totalRxIdle + totalRxOk + totalRxDesc + 475 totalTxOk + totalTxIdle + totalTxDesc + 476 totalRxOrn) / postedInterrupts; 477 478 txBandwidth = txBytes * Stats::constant(8) / simSeconds; 479 rxBandwidth = rxBytes * Stats::constant(8) / simSeconds; 480 totBandwidth = txBandwidth + rxBandwidth; 481 totBytes = txBytes + rxBytes; 482 totPackets = txPackets + rxPackets; 483 484 txPacketRate = txPackets / simSeconds; 485 rxPacketRate = rxPackets / simSeconds; 486} 487 488/** 489 * This is to read the PCI general configuration registers 490 */ 491void 492NSGigE::readConfig(int offset, int size, uint8_t *data) 493{ 494 if (offset < PCI_DEVICE_SPECIFIC) 495 PciDev::readConfig(offset, size, data); 496 else 497 panic("Device specific PCI config space not implemented!\n"); 498} 499 500/** 501 * This is to write to the PCI general configuration registers 502 */ 503void 504NSGigE::writeConfig(int offset, int size, const uint8_t* data) 505{ 506 if (offset < PCI_DEVICE_SPECIFIC) 507 PciDev::writeConfig(offset, size, data); 508 else 509 panic("Device specific PCI config space not implemented!\n"); 510 511 // Need to catch writes to BARs to update the PIO interface 512 switch (offset) { 513 // seems to work fine without all these PCI settings, but i 514 // put in the IO to double check, an assertion will fail if we 515 // need to properly implement it 516 case PCI_COMMAND: 517 if (config.data[offset] & PCI_CMD_IOSE) 518 ioEnable = true; 519 else 520 ioEnable = false; 521 522#if 0 523 if (config.data[offset] & PCI_CMD_BME) { 524 bmEnabled = true; 525 } 526 else { 527 bmEnabled = false; 528 } 529 530 if (config.data[offset] & PCI_CMD_MSE) { 531 memEnable = true; 532 } 533 else { 534 memEnable = false; 535 } 536#endif 537 break; 538 539 case PCI0_BASE_ADDR0: 540 if (BARAddrs[0] != 0) { 541 if (pioInterface) 542 pioInterface->addAddrRange(RangeSize(BARAddrs[0], BARSize[0])); 543 544 BARAddrs[0] &= EV5::PAddrUncachedMask; 545 } 546 break; 547 case PCI0_BASE_ADDR1: 548 if (BARAddrs[1] != 0) { 549 if (pioInterface) 550 pioInterface->addAddrRange(RangeSize(BARAddrs[1], BARSize[1])); 551 552 BARAddrs[1] &= EV5::PAddrUncachedMask; 553 } 554 break; 555 } 556} 557 558/** 559 * This reads the device registers, which are detailed in the NS83820 560 * spec sheet 561 */ 562Fault * 563NSGigE::read(MemReqPtr &req, uint8_t *data) 564{ 565 assert(ioEnable); 566 567 //The mask is to give you only the offset into the device register file 568 Addr daddr = req->paddr & 0xfff; 569 DPRINTF(EthernetPIO, "read da=%#x pa=%#x va=%#x size=%d\n", 570 daddr, req->paddr, req->vaddr, req->size); 571 572 573 // there are some reserved registers, you can see ns_gige_reg.h and 574 // the spec sheet for details 575 if (daddr > LAST && daddr <= RESERVED) { 576 panic("Accessing reserved register"); 577 } else if (daddr > RESERVED && daddr <= 0x3FC) { 578 readConfig(daddr & 0xff, req->size, data); 579 return NoFault; 580 } else if (daddr >= MIB_START && daddr <= MIB_END) { 581 // don't implement all the MIB's. hopefully the kernel 582 // doesn't actually DEPEND upon their values 583 // MIB are just hardware stats keepers 584 uint32_t ® = *(uint32_t *) data; 585 reg = 0; 586 return NoFault; 587 } else if (daddr > 0x3FC) 588 panic("Something is messed up!\n"); 589 590 switch (req->size) { 591 case sizeof(uint32_t): 592 { 593 uint32_t ® = *(uint32_t *)data; 594 uint16_t rfaddr; 595 596 switch (daddr) { 597 case CR: 598 reg = regs.command; 599 //these are supposed to be cleared on a read 600 reg &= ~(CR_RXD | CR_TXD | CR_TXR | CR_RXR); 601 break; 602 603 case CFGR: 604 reg = regs.config; 605 break; 606 607 case MEAR: 608 reg = regs.mear; 609 break; 610 611 case PTSCR: 612 reg = regs.ptscr; 613 break; 614 615 case ISR: 616 reg = regs.isr; 617 devIntrClear(ISR_ALL); 618 break; 619 620 case IMR: 621 reg = regs.imr; 622 break; 623 624 case IER: 625 reg = regs.ier; 626 break; 627 628 case IHR: 629 reg = regs.ihr; 630 break; 631 632 case TXDP: 633 reg = regs.txdp; 634 break; 635 636 case TXDP_HI: 637 reg = regs.txdp_hi; 638 break; 639 640 case TX_CFG: 641 reg = regs.txcfg; 642 break; 643 644 case GPIOR: 645 reg = regs.gpior; 646 break; 647 648 case RXDP: 649 reg = regs.rxdp; 650 break; 651 652 case RXDP_HI: 653 reg = regs.rxdp_hi; 654 break; 655 656 case RX_CFG: 657 reg = regs.rxcfg; 658 break; 659 660 case PQCR: 661 reg = regs.pqcr; 662 break; 663 664 case WCSR: 665 reg = regs.wcsr; 666 break; 667 668 case PCR: 669 reg = regs.pcr; 670 break; 671 672 // see the spec sheet for how RFCR and RFDR work 673 // basically, you write to RFCR to tell the machine 674 // what you want to do next, then you act upon RFDR, 675 // and the device will be prepared b/c of what you 676 // wrote to RFCR 677 case RFCR: 678 reg = regs.rfcr; 679 break; 680 681 case RFDR: 682 rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR); 683 switch (rfaddr) { 684 // Read from perfect match ROM octets 685 case 0x000: 686 reg = rom.perfectMatch[1]; 687 reg = reg << 8; 688 reg += rom.perfectMatch[0]; 689 break; 690 case 0x002: 691 reg = rom.perfectMatch[3] << 8; 692 reg += rom.perfectMatch[2]; 693 break; 694 case 0x004: 695 reg = rom.perfectMatch[5] << 8; 696 reg += rom.perfectMatch[4]; 697 break; 698 default: 699 // Read filter hash table 700 if (rfaddr >= FHASH_ADDR && 701 rfaddr < FHASH_ADDR + FHASH_SIZE) { 702 703 // Only word-aligned reads supported 704 if (rfaddr % 2) 705 panic("unaligned read from filter hash table!"); 706 707 reg = rom.filterHash[rfaddr - FHASH_ADDR + 1] << 8; 708 reg += rom.filterHash[rfaddr - FHASH_ADDR]; 709 break; 710 } 711 712 panic("reading RFDR for something other than pattern" 713 " matching or hashing! %#x\n", rfaddr); 714 } 715 break; 716 717 case SRR: 718 reg = regs.srr; 719 break; 720 721 case MIBC: 722 reg = regs.mibc; 723 reg &= ~(MIBC_MIBS | MIBC_ACLR); 724 break; 725 726 case VRCR: 727 reg = regs.vrcr; 728 break; 729 730 case VTCR: 731 reg = regs.vtcr; 732 break; 733 734 case VDR: 735 reg = regs.vdr; 736 break; 737 738 case CCSR: 739 reg = regs.ccsr; 740 break; 741 742 case TBICR: 743 reg = regs.tbicr; 744 break; 745 746 case TBISR: 747 reg = regs.tbisr; 748 break; 749 750 case TANAR: 751 reg = regs.tanar; 752 break; 753 754 case TANLPAR: 755 reg = regs.tanlpar; 756 break; 757 758 case TANER: 759 reg = regs.taner; 760 break; 761 762 case TESR: 763 reg = regs.tesr; 764 break; 765 766 case M5REG: 767 reg = 0; 768 if (params()->rx_thread) 769 reg |= M5REG_RX_THREAD; 770 if (params()->tx_thread) 771 reg |= M5REG_TX_THREAD; 772 break; 773 774 default: 775 panic("reading unimplemented register: addr=%#x", daddr); 776 } 777 778 DPRINTF(EthernetPIO, "read from %#x: data=%d data=%#x\n", 779 daddr, reg, reg); 780 } 781 break; 782 783 default: 784 panic("accessing register with invalid size: addr=%#x, size=%d", 785 daddr, req->size); 786 } 787 788 return NoFault; 789} 790 791Fault * 792NSGigE::write(MemReqPtr &req, const uint8_t *data) 793{ 794 assert(ioEnable); 795 796 Addr daddr = req->paddr & 0xfff; 797 DPRINTF(EthernetPIO, "write da=%#x pa=%#x va=%#x size=%d\n", 798 daddr, req->paddr, req->vaddr, req->size); 799 800 if (daddr > LAST && daddr <= RESERVED) { 801 panic("Accessing reserved register"); 802 } else if (daddr > RESERVED && daddr <= 0x3FC) { 803 writeConfig(daddr & 0xff, req->size, data); 804 return NoFault; 805 } else if (daddr > 0x3FC) 806 panic("Something is messed up!\n"); 807 808 if (pioDelayWrite) { 809 int cpu = (req->xc->regs.ipr[TheISA::IPR_PALtemp16] >> 8) & 0xff; 810 if (cpu >= writeQueue.size()) 811 writeQueue.resize(cpu + 1); 812 writeQueue[cpu].push_back(RegWriteData(daddr, *(uint32_t *)data)); 813 } 814 815 if (req->size == sizeof(uint32_t)) { 816 uint32_t reg = *(uint32_t *)data; 817 uint16_t rfaddr; 818 819 DPRINTF(EthernetPIO, "write data=%d data=%#x\n", reg, reg); 820 821 switch (daddr) { 822 case CR: 823 regs.command = reg; 824 if (reg & CR_TXD) { 825 txEnable = false; 826 } else if (reg & CR_TXE) { 827 if (!pioDelayWrite) { 828 txEnable = true; 829 830 // the kernel is enabling the transmit machine 831 if (txState == txIdle) 832 txKick(); 833 } 834 } 835 836 if (reg & CR_RXD) { 837 rxEnable = false; 838 } else if (reg & CR_RXE) { 839 if (!pioDelayWrite) { 840 rxEnable = true; 841 842 if (rxState == rxIdle) 843 rxKick(); 844 } 845 } 846 847 if (reg & CR_TXR) 848 txReset(); 849 850 if (reg & CR_RXR) 851 rxReset(); 852 853 if (reg & CR_SWI) 854 devIntrPost(ISR_SWI); 855 856 if (reg & CR_RST) { 857 txReset(); 858 rxReset(); 859 860 regsReset(); 861 } 862 break; 863 864 case CFGR: 865 if (reg & CFGR_LNKSTS || 866 reg & CFGR_SPDSTS || 867 reg & CFGR_DUPSTS || 868 reg & CFGR_RESERVED || 869 reg & CFGR_T64ADDR || 870 reg & CFGR_PCI64_DET) 871 872 // First clear all writable bits 873 regs.config &= CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS | 874 CFGR_RESERVED | CFGR_T64ADDR | 875 CFGR_PCI64_DET; 876 // Now set the appropriate writable bits 877 regs.config |= reg & ~(CFGR_LNKSTS | CFGR_SPDSTS | CFGR_DUPSTS | 878 CFGR_RESERVED | CFGR_T64ADDR | 879 CFGR_PCI64_DET); 880 881// all these #if 0's are because i don't THINK the kernel needs to 882// have these implemented. if there is a problem relating to one of 883// these, you may need to add functionality in. 884 if (reg & CFGR_TBI_EN) ; 885 if (reg & CFGR_MODE_1000) ; 886 887 if (reg & CFGR_AUTO_1000) 888 panic("CFGR_AUTO_1000 not implemented!\n"); 889 890 if (reg & CFGR_PINT_DUPSTS || 891 reg & CFGR_PINT_LNKSTS || 892 reg & CFGR_PINT_SPDSTS) 893 ; 894 895 if (reg & CFGR_TMRTEST) ; 896 if (reg & CFGR_MRM_DIS) ; 897 if (reg & CFGR_MWI_DIS) ; 898 899 if (reg & CFGR_T64ADDR) ; 900 // panic("CFGR_T64ADDR is read only register!\n"); 901 902 if (reg & CFGR_PCI64_DET) 903 panic("CFGR_PCI64_DET is read only register!\n"); 904 905 if (reg & CFGR_DATA64_EN) ; 906 if (reg & CFGR_M64ADDR) ; 907 if (reg & CFGR_PHY_RST) ; 908 if (reg & CFGR_PHY_DIS) ; 909 910 if (reg & CFGR_EXTSTS_EN) 911 extstsEnable = true; 912 else 913 extstsEnable = false; 914 915 if (reg & CFGR_REQALG) ; 916 if (reg & CFGR_SB) ; 917 if (reg & CFGR_POW) ; 918 if (reg & CFGR_EXD) ; 919 if (reg & CFGR_PESEL) ; 920 if (reg & CFGR_BROM_DIS) ; 921 if (reg & CFGR_EXT_125) ; 922 if (reg & CFGR_BEM) ; 923 break; 924 925 case MEAR: 926 // Clear writable bits 927 regs.mear &= MEAR_EEDO; 928 // Set appropriate writable bits 929 regs.mear |= reg & ~MEAR_EEDO; 930 931 // FreeBSD uses the EEPROM to read PMATCH (for the MAC address) 932 // even though it could get it through RFDR 933 if (reg & MEAR_EESEL) { 934 // Rising edge of clock 935 if (reg & MEAR_EECLK && !eepromClk) 936 eepromKick(); 937 } 938 else { 939 eepromState = eepromStart; 940 regs.mear &= ~MEAR_EEDI; 941 } 942 943 eepromClk = reg & MEAR_EECLK; 944 945 // since phy is completely faked, MEAR_MD* don't matter 946 if (reg & MEAR_MDIO) ; 947 if (reg & MEAR_MDDIR) ; 948 if (reg & MEAR_MDC) ; 949 break; 950 951 case PTSCR: 952 regs.ptscr = reg & ~(PTSCR_RBIST_RDONLY); 953 // these control BISTs for various parts of chip - we 954 // don't care or do just fake that the BIST is done 955 if (reg & PTSCR_RBIST_EN) 956 regs.ptscr |= PTSCR_RBIST_DONE; 957 if (reg & PTSCR_EEBIST_EN) 958 regs.ptscr &= ~PTSCR_EEBIST_EN; 959 if (reg & PTSCR_EELOAD_EN) 960 regs.ptscr &= ~PTSCR_EELOAD_EN; 961 break; 962 963 case ISR: /* writing to the ISR has no effect */ 964 panic("ISR is a read only register!\n"); 965 966 case IMR: 967 regs.imr = reg; 968 devIntrChangeMask(); 969 break; 970 971 case IER: 972 regs.ier = reg; 973 break; 974 975 case IHR: 976 regs.ihr = reg; 977 /* not going to implement real interrupt holdoff */ 978 break; 979 980 case TXDP: 981 regs.txdp = (reg & 0xFFFFFFFC); 982 assert(txState == txIdle); 983 CTDD = false; 984 break; 985 986 case TXDP_HI: 987 regs.txdp_hi = reg; 988 break; 989 990 case TX_CFG: 991 regs.txcfg = reg; 992#if 0 993 if (reg & TX_CFG_CSI) ; 994 if (reg & TX_CFG_HBI) ; 995 if (reg & TX_CFG_MLB) ; 996 if (reg & TX_CFG_ATP) ; 997 if (reg & TX_CFG_ECRETRY) { 998 /* 999 * this could easily be implemented, but considering 1000 * the network is just a fake pipe, wouldn't make 1001 * sense to do this 1002 */ 1003 } 1004 1005 if (reg & TX_CFG_BRST_DIS) ; 1006#endif 1007 1008#if 0 1009 /* we handle our own DMA, ignore the kernel's exhortations */ 1010 if (reg & TX_CFG_MXDMA) ; 1011#endif 1012 1013 // also, we currently don't care about fill/drain 1014 // thresholds though this may change in the future with 1015 // more realistic networks or a driver which changes it 1016 // according to feedback 1017 1018 break; 1019 1020 case GPIOR: 1021 // Only write writable bits 1022 regs.gpior &= GPIOR_UNUSED | GPIOR_GP5_IN | GPIOR_GP4_IN 1023 | GPIOR_GP3_IN | GPIOR_GP2_IN | GPIOR_GP1_IN; 1024 regs.gpior |= reg & ~(GPIOR_UNUSED | GPIOR_GP5_IN | GPIOR_GP4_IN 1025 | GPIOR_GP3_IN | GPIOR_GP2_IN | GPIOR_GP1_IN); 1026 /* these just control general purpose i/o pins, don't matter */ 1027 break; 1028 1029 case RXDP: 1030 regs.rxdp = reg; 1031 CRDD = false; 1032 break; 1033 1034 case RXDP_HI: 1035 regs.rxdp_hi = reg; 1036 break; 1037 1038 case RX_CFG: 1039 regs.rxcfg = reg; 1040#if 0 1041 if (reg & RX_CFG_AEP) ; 1042 if (reg & RX_CFG_ARP) ; 1043 if (reg & RX_CFG_STRIPCRC) ; 1044 if (reg & RX_CFG_RX_RD) ; 1045 if (reg & RX_CFG_ALP) ; 1046 if (reg & RX_CFG_AIRL) ; 1047 1048 /* we handle our own DMA, ignore what kernel says about it */ 1049 if (reg & RX_CFG_MXDMA) ; 1050 1051 //also, we currently don't care about fill/drain thresholds 1052 //though this may change in the future with more realistic 1053 //networks or a driver which changes it according to feedback 1054 if (reg & (RX_CFG_DRTH | RX_CFG_DRTH0)) ; 1055#endif 1056 break; 1057 1058 case PQCR: 1059 /* there is no priority queueing used in the linux 2.6 driver */ 1060 regs.pqcr = reg; 1061 break; 1062 1063 case WCSR: 1064 /* not going to implement wake on LAN */ 1065 regs.wcsr = reg; 1066 break; 1067 1068 case PCR: 1069 /* not going to implement pause control */ 1070 regs.pcr = reg; 1071 break; 1072 1073 case RFCR: 1074 regs.rfcr = reg; 1075 1076 rxFilterEnable = (reg & RFCR_RFEN) ? true : false; 1077 acceptBroadcast = (reg & RFCR_AAB) ? true : false; 1078 acceptMulticast = (reg & RFCR_AAM) ? true : false; 1079 acceptUnicast = (reg & RFCR_AAU) ? true : false; 1080 acceptPerfect = (reg & RFCR_APM) ? true : false; 1081 acceptArp = (reg & RFCR_AARP) ? true : false; 1082 multicastHashEnable = (reg & RFCR_MHEN) ? true : false; 1083 1084#if 0 1085 if (reg & RFCR_APAT) 1086 panic("RFCR_APAT not implemented!\n"); 1087#endif 1088 if (reg & RFCR_UHEN) 1089 panic("Unicast hash filtering not used by drivers!\n"); 1090 1091 if (reg & RFCR_ULM) 1092 panic("RFCR_ULM not implemented!\n"); 1093 1094 break; 1095 1096 case RFDR: 1097 rfaddr = (uint16_t)(regs.rfcr & RFCR_RFADDR); 1098 switch (rfaddr) { 1099 case 0x000: 1100 rom.perfectMatch[0] = (uint8_t)reg; 1101 rom.perfectMatch[1] = (uint8_t)(reg >> 8); 1102 break; 1103 case 0x002: 1104 rom.perfectMatch[2] = (uint8_t)reg; 1105 rom.perfectMatch[3] = (uint8_t)(reg >> 8); 1106 break; 1107 case 0x004: 1108 rom.perfectMatch[4] = (uint8_t)reg; 1109 rom.perfectMatch[5] = (uint8_t)(reg >> 8); 1110 break; 1111 default: 1112 1113 if (rfaddr >= FHASH_ADDR && 1114 rfaddr < FHASH_ADDR + FHASH_SIZE) { 1115 1116 // Only word-aligned writes supported 1117 if (rfaddr % 2) 1118 panic("unaligned write to filter hash table!"); 1119 1120 rom.filterHash[rfaddr - FHASH_ADDR] = (uint8_t)reg; 1121 rom.filterHash[rfaddr - FHASH_ADDR + 1] 1122 = (uint8_t)(reg >> 8); 1123 break; 1124 } 1125 panic("writing RFDR for something other than pattern matching\ 1126 or hashing! %#x\n", rfaddr); 1127 } 1128 1129 case BRAR: 1130 regs.brar = reg; 1131 break; 1132 1133 case BRDR: 1134 panic("the driver never uses BRDR, something is wrong!\n"); 1135 1136 case SRR: 1137 panic("SRR is read only register!\n"); 1138 1139 case MIBC: 1140 panic("the driver never uses MIBC, something is wrong!\n"); 1141 1142 case VRCR: 1143 regs.vrcr = reg; 1144 break; 1145 1146 case VTCR: 1147 regs.vtcr = reg; 1148 break; 1149 1150 case VDR: 1151 panic("the driver never uses VDR, something is wrong!\n"); 1152 1153 case CCSR: 1154 /* not going to implement clockrun stuff */ 1155 regs.ccsr = reg; 1156 break; 1157 1158 case TBICR: 1159 regs.tbicr = reg; 1160 if (reg & TBICR_MR_LOOPBACK) 1161 panic("TBICR_MR_LOOPBACK never used, something wrong!\n"); 1162 1163 if (reg & TBICR_MR_AN_ENABLE) { 1164 regs.tanlpar = regs.tanar; 1165 regs.tbisr |= (TBISR_MR_AN_COMPLETE | TBISR_MR_LINK_STATUS); 1166 } 1167 1168#if 0 1169 if (reg & TBICR_MR_RESTART_AN) ; 1170#endif 1171 1172 break; 1173 1174 case TBISR: 1175 panic("TBISR is read only register!\n"); 1176 1177 case TANAR: 1178 // Only write the writable bits 1179 regs.tanar &= TANAR_RF1 | TANAR_RF2 | TANAR_UNUSED; 1180 regs.tanar |= reg & ~(TANAR_RF1 | TANAR_RF2 | TANAR_UNUSED); 1181 1182 // Pause capability unimplemented 1183#if 0 1184 if (reg & TANAR_PS2) ; 1185 if (reg & TANAR_PS1) ; 1186#endif 1187 1188 break; 1189 1190 case TANLPAR: 1191 panic("this should only be written to by the fake phy!\n"); 1192 1193 case TANER: 1194 panic("TANER is read only register!\n"); 1195 1196 case TESR: 1197 regs.tesr = reg; 1198 break; 1199 1200 default: 1201 panic("invalid register access daddr=%#x", daddr); 1202 } 1203 } else { 1204 panic("Invalid Request Size"); 1205 } 1206 1207 return NoFault; 1208} 1209 1210void 1211NSGigE::devIntrPost(uint32_t interrupts) 1212{ 1213 if (interrupts & ISR_RESERVE) 1214 panic("Cannot set a reserved interrupt"); 1215 1216 if (interrupts & ISR_NOIMPL) 1217 warn("interrupt not implemented %#x\n", interrupts); 1218 1219 interrupts &= ISR_IMPL; 1220 regs.isr |= interrupts; 1221 1222 if (interrupts & regs.imr) { 1223 if (interrupts & ISR_SWI) { 1224 totalSwi++; 1225 } 1226 if (interrupts & ISR_RXIDLE) { 1227 totalRxIdle++; 1228 } 1229 if (interrupts & ISR_RXOK) { 1230 totalRxOk++; 1231 } 1232 if (interrupts & ISR_RXDESC) { 1233 totalRxDesc++; 1234 } 1235 if (interrupts & ISR_TXOK) { 1236 totalTxOk++; 1237 } 1238 if (interrupts & ISR_TXIDLE) { 1239 totalTxIdle++; 1240 } 1241 if (interrupts & ISR_TXDESC) { 1242 totalTxDesc++; 1243 } 1244 if (interrupts & ISR_RXORN) { 1245 totalRxOrn++; 1246 } 1247 } 1248 1249 DPRINTF(EthernetIntr, 1250 "interrupt written to ISR: intr=%#x isr=%#x imr=%#x\n", 1251 interrupts, regs.isr, regs.imr); 1252 1253 if ((regs.isr & regs.imr)) { 1254 Tick when = curTick; 1255 if ((regs.isr & regs.imr & ISR_NODELAY) == 0) 1256 when += intrDelay; 1257 cpuIntrPost(when); 1258 } 1259} 1260 1261/* writing this interrupt counting stats inside this means that this function 1262 is now limited to being used to clear all interrupts upon the kernel 1263 reading isr and servicing. just telling you in case you were thinking 1264 of expanding use. 1265*/ 1266void 1267NSGigE::devIntrClear(uint32_t interrupts) 1268{ 1269 if (interrupts & ISR_RESERVE) 1270 panic("Cannot clear a reserved interrupt"); 1271 1272 if (regs.isr & regs.imr & ISR_SWI) { 1273 postedSwi++; 1274 } 1275 if (regs.isr & regs.imr & ISR_RXIDLE) { 1276 postedRxIdle++; 1277 } 1278 if (regs.isr & regs.imr & ISR_RXOK) { 1279 postedRxOk++; 1280 } 1281 if (regs.isr & regs.imr & ISR_RXDESC) { 1282 postedRxDesc++; 1283 } 1284 if (regs.isr & regs.imr & ISR_TXOK) { 1285 postedTxOk++; 1286 } 1287 if (regs.isr & regs.imr & ISR_TXIDLE) { 1288 postedTxIdle++; 1289 } 1290 if (regs.isr & regs.imr & ISR_TXDESC) { 1291 postedTxDesc++; 1292 } 1293 if (regs.isr & regs.imr & ISR_RXORN) { 1294 postedRxOrn++; 1295 } 1296 1297 if (regs.isr & regs.imr & ISR_IMPL) 1298 postedInterrupts++; 1299 1300 interrupts &= ~ISR_NOIMPL; 1301 regs.isr &= ~interrupts; 1302 1303 DPRINTF(EthernetIntr, 1304 "interrupt cleared from ISR: intr=%x isr=%x imr=%x\n", 1305 interrupts, regs.isr, regs.imr); 1306 1307 if (!(regs.isr & regs.imr)) 1308 cpuIntrClear(); 1309} 1310 1311void 1312NSGigE::devIntrChangeMask() 1313{ 1314 DPRINTF(EthernetIntr, "interrupt mask changed: isr=%x imr=%x masked=%x\n", 1315 regs.isr, regs.imr, regs.isr & regs.imr); 1316 1317 if (regs.isr & regs.imr) 1318 cpuIntrPost(curTick); 1319 else 1320 cpuIntrClear(); 1321} 1322 1323void 1324NSGigE::cpuIntrPost(Tick when) 1325{ 1326 // If the interrupt you want to post is later than an interrupt 1327 // already scheduled, just let it post in the coming one and don't 1328 // schedule another. 1329 // HOWEVER, must be sure that the scheduled intrTick is in the 1330 // future (this was formerly the source of a bug) 1331 /** 1332 * @todo this warning should be removed and the intrTick code should 1333 * be fixed. 1334 */ 1335 assert(when >= curTick); 1336 assert(intrTick >= curTick || intrTick == 0); 1337 if (when > intrTick && intrTick != 0) { 1338 DPRINTF(EthernetIntr, "don't need to schedule event...intrTick=%d\n", 1339 intrTick); 1340 return; 1341 } 1342 1343 intrTick = when; 1344 if (intrTick < curTick) { 1345 debug_break(); 1346 intrTick = curTick; 1347 } 1348 1349 DPRINTF(EthernetIntr, "going to schedule an interrupt for intrTick=%d\n", 1350 intrTick); 1351 1352 if (intrEvent) 1353 intrEvent->squash(); 1354 intrEvent = new IntrEvent(this, true); 1355 intrEvent->schedule(intrTick); 1356} 1357 1358void 1359NSGigE::cpuInterrupt() 1360{ 1361 assert(intrTick == curTick); 1362 1363 // Whether or not there's a pending interrupt, we don't care about 1364 // it anymore 1365 intrEvent = 0; 1366 intrTick = 0; 1367 1368 // Don't send an interrupt if there's already one 1369 if (cpuPendingIntr) { 1370 DPRINTF(EthernetIntr, 1371 "would send an interrupt now, but there's already pending\n"); 1372 } else { 1373 // Send interrupt 1374 cpuPendingIntr = true; 1375 1376 DPRINTF(EthernetIntr, "posting interrupt\n"); 1377 intrPost(); 1378 } 1379} 1380 1381void 1382NSGigE::cpuIntrClear() 1383{ 1384 if (!cpuPendingIntr) 1385 return; 1386 1387 if (intrEvent) { 1388 intrEvent->squash(); 1389 intrEvent = 0; 1390 } 1391 1392 intrTick = 0; 1393 1394 cpuPendingIntr = false; 1395 1396 DPRINTF(EthernetIntr, "clearing interrupt\n"); 1397 intrClear(); 1398} 1399 1400bool 1401NSGigE::cpuIntrPending() const 1402{ return cpuPendingIntr; } 1403 1404void 1405NSGigE::txReset() 1406{ 1407 1408 DPRINTF(Ethernet, "transmit reset\n"); 1409 1410 CTDD = false; 1411 txEnable = false;; 1412 txFragPtr = 0; 1413 assert(txDescCnt == 0); 1414 txFifo.clear(); 1415 txState = txIdle; 1416 assert(txDmaState == dmaIdle); 1417} 1418 1419void 1420NSGigE::rxReset() 1421{ 1422 DPRINTF(Ethernet, "receive reset\n"); 1423 1424 CRDD = false; 1425 assert(rxPktBytes == 0); 1426 rxEnable = false; 1427 rxFragPtr = 0; 1428 assert(rxDescCnt == 0); 1429 assert(rxDmaState == dmaIdle); 1430 rxFifo.clear(); 1431 rxState = rxIdle; 1432} 1433 1434void 1435NSGigE::regsReset() 1436{ 1437 memset(®s, 0, sizeof(regs)); 1438 regs.config = (CFGR_LNKSTS | CFGR_TBI_EN | CFGR_MODE_1000); 1439 regs.mear = 0x12; 1440 regs.txcfg = 0x120; // set drain threshold to 1024 bytes and 1441 // fill threshold to 32 bytes 1442 regs.rxcfg = 0x4; // set drain threshold to 16 bytes 1443 regs.srr = 0x0103; // set the silicon revision to rev B or 0x103 1444 regs.mibc = MIBC_FRZ; 1445 regs.vdr = 0x81; // set the vlan tag type to 802.1q 1446 regs.tesr = 0xc000; // TBI capable of both full and half duplex 1447 regs.brar = 0xffffffff; 1448 1449 extstsEnable = false; 1450 acceptBroadcast = false; 1451 acceptMulticast = false; 1452 acceptUnicast = false; 1453 acceptPerfect = false; 1454 acceptArp = false; 1455} 1456 1457void 1458NSGigE::rxDmaReadCopy() 1459{ 1460 assert(rxDmaState == dmaReading); 1461 1462 physmem->dma_read((uint8_t *)rxDmaData, rxDmaAddr, rxDmaLen); 1463 rxDmaState = dmaIdle; 1464 1465 DPRINTF(EthernetDMA, "rx dma read paddr=%#x len=%d\n", 1466 rxDmaAddr, rxDmaLen); 1467 DDUMP(EthernetDMA, rxDmaData, rxDmaLen); 1468} 1469 1470bool 1471NSGigE::doRxDmaRead() 1472{ 1473 assert(rxDmaState == dmaIdle || rxDmaState == dmaReadWaiting); 1474 rxDmaState = dmaReading; 1475 1476 if (dmaInterface && !rxDmaFree) { 1477 if (dmaInterface->busy()) 1478 rxDmaState = dmaReadWaiting; 1479 else 1480 dmaInterface->doDMA(Read, rxDmaAddr, rxDmaLen, curTick, 1481 &rxDmaReadEvent, true); 1482 return true; 1483 } 1484 1485 if (dmaReadDelay == 0 && dmaReadFactor == 0) { 1486 rxDmaReadCopy(); 1487 return false; 1488 } 1489 1490 Tick factor = ((rxDmaLen + ULL(63)) >> ULL(6)) * dmaReadFactor; 1491 Tick start = curTick + dmaReadDelay + factor; 1492 rxDmaReadEvent.schedule(start); 1493 return true; 1494} 1495 1496void 1497NSGigE::rxDmaReadDone() 1498{ 1499 assert(rxDmaState == dmaReading); 1500 rxDmaReadCopy(); 1501 1502 // If the transmit state machine has a pending DMA, let it go first 1503 if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting) 1504 txKick(); 1505 1506 rxKick(); 1507} 1508 1509void 1510NSGigE::rxDmaWriteCopy() 1511{ 1512 assert(rxDmaState == dmaWriting); 1513 1514 physmem->dma_write(rxDmaAddr, (uint8_t *)rxDmaData, rxDmaLen); 1515 rxDmaState = dmaIdle; 1516 1517 DPRINTF(EthernetDMA, "rx dma write paddr=%#x len=%d\n", 1518 rxDmaAddr, rxDmaLen); 1519 DDUMP(EthernetDMA, rxDmaData, rxDmaLen); 1520} 1521 1522bool 1523NSGigE::doRxDmaWrite() 1524{ 1525 assert(rxDmaState == dmaIdle || rxDmaState == dmaWriteWaiting); 1526 rxDmaState = dmaWriting; 1527 1528 if (dmaInterface && !rxDmaFree) { 1529 if (dmaInterface->busy()) 1530 rxDmaState = dmaWriteWaiting; 1531 else 1532 dmaInterface->doDMA(WriteInvalidate, rxDmaAddr, rxDmaLen, curTick, 1533 &rxDmaWriteEvent, true); 1534 return true; 1535 } 1536 1537 if (dmaWriteDelay == 0 && dmaWriteFactor == 0) { 1538 rxDmaWriteCopy(); 1539 return false; 1540 } 1541 1542 Tick factor = ((rxDmaLen + ULL(63)) >> ULL(6)) * dmaWriteFactor; 1543 Tick start = curTick + dmaWriteDelay + factor; 1544 rxDmaWriteEvent.schedule(start); 1545 return true; 1546} 1547 1548void 1549NSGigE::rxDmaWriteDone() 1550{ 1551 assert(rxDmaState == dmaWriting); 1552 rxDmaWriteCopy(); 1553 1554 // If the transmit state machine has a pending DMA, let it go first 1555 if (txDmaState == dmaReadWaiting || txDmaState == dmaWriteWaiting) 1556 txKick(); 1557 1558 rxKick(); 1559} 1560 1561void 1562NSGigE::rxKick() 1563{ 1564 bool is64bit = (bool)(regs.config & CFGR_M64ADDR); 1565 1566 DPRINTF(EthernetSM, 1567 "receive kick rxState=%s (rxBuf.size=%d) %d-bit\n", 1568 NsRxStateStrings[rxState], rxFifo.size(), is64bit ? 64 : 32); 1569 1570 Addr link, bufptr; 1571 uint32_t &cmdsts = is64bit ? rxDesc64.cmdsts : rxDesc32.cmdsts; 1572 uint32_t &extsts = is64bit ? rxDesc64.extsts : rxDesc32.extsts; 1573 1574 next: 1575 if (clock) { 1576 if (rxKickTick > curTick) { 1577 DPRINTF(EthernetSM, "receive kick exiting, can't run till %d\n", 1578 rxKickTick); 1579 1580 goto exit; 1581 } 1582 1583 // Go to the next state machine clock tick. 1584 rxKickTick = curTick + cycles(1); 1585 } 1586 1587 switch(rxDmaState) { 1588 case dmaReadWaiting: 1589 if (doRxDmaRead()) 1590 goto exit; 1591 break; 1592 case dmaWriteWaiting: 1593 if (doRxDmaWrite()) 1594 goto exit; 1595 break; 1596 default: 1597 break; 1598 } 1599 1600 link = is64bit ? (Addr)rxDesc64.link : (Addr)rxDesc32.link; 1601 bufptr = is64bit ? (Addr)rxDesc64.bufptr : (Addr)rxDesc32.bufptr; 1602 1603 // see state machine from spec for details 1604 // the way this works is, if you finish work on one state and can 1605 // go directly to another, you do that through jumping to the 1606 // label "next". however, if you have intermediate work, like DMA 1607 // so that you can't go to the next state yet, you go to exit and 1608 // exit the loop. however, when the DMA is done it will trigger 1609 // an event and come back to this loop. 1610 switch (rxState) { 1611 case rxIdle: 1612 if (!rxEnable) { 1613 DPRINTF(EthernetSM, "Receive Disabled! Nothing to do.\n"); 1614 goto exit; 1615 } 1616 1617 if (CRDD) { 1618 rxState = rxDescRefr; 1619 1620 rxDmaAddr = regs.rxdp & 0x3fffffff; 1621 rxDmaData = 1622 is64bit ? (void *)&rxDesc64.link : (void *)&rxDesc32.link; 1623 rxDmaLen = is64bit ? sizeof(rxDesc64.link) : sizeof(rxDesc32.link); 1624 rxDmaFree = dmaDescFree; 1625 1626 descDmaReads++; 1627 descDmaRdBytes += rxDmaLen; 1628 1629 if (doRxDmaRead()) 1630 goto exit; 1631 } else { 1632 rxState = rxDescRead; 1633 1634 rxDmaAddr = regs.rxdp & 0x3fffffff; 1635 rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32; 1636 rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32); 1637 rxDmaFree = dmaDescFree; 1638 1639 descDmaReads++; 1640 descDmaRdBytes += rxDmaLen; 1641 1642 if (doRxDmaRead()) 1643 goto exit; 1644 } 1645 break; 1646 1647 case rxDescRefr: 1648 if (rxDmaState != dmaIdle) 1649 goto exit; 1650 1651 rxState = rxAdvance; 1652 break; 1653 1654 case rxDescRead: 1655 if (rxDmaState != dmaIdle) 1656 goto exit; 1657 1658 DPRINTF(EthernetDesc, "rxDesc: addr=%08x read descriptor\n", 1659 regs.rxdp & 0x3fffffff); 1660 DPRINTF(EthernetDesc, 1661 "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n", 1662 link, bufptr, cmdsts, extsts); 1663 1664 if (cmdsts & CMDSTS_OWN) { 1665 devIntrPost(ISR_RXIDLE); 1666 rxState = rxIdle; 1667 goto exit; 1668 } else { 1669 rxState = rxFifoBlock; 1670 rxFragPtr = bufptr; 1671 rxDescCnt = cmdsts & CMDSTS_LEN_MASK; 1672 } 1673 break; 1674 1675 case rxFifoBlock: 1676 if (!rxPacket) { 1677 /** 1678 * @todo in reality, we should be able to start processing 1679 * the packet as it arrives, and not have to wait for the 1680 * full packet ot be in the receive fifo. 1681 */ 1682 if (rxFifo.empty()) 1683 goto exit; 1684 1685 DPRINTF(EthernetSM, "****processing receive of new packet****\n"); 1686 1687 // If we don't have a packet, grab a new one from the fifo. 1688 rxPacket = rxFifo.front(); 1689 rxPktBytes = rxPacket->length; 1690 rxPacketBufPtr = rxPacket->data; 1691 1692#if TRACING_ON 1693 if (DTRACE(Ethernet)) { 1694 IpPtr ip(rxPacket); 1695 if (ip) { 1696 DPRINTF(Ethernet, "ID is %d\n", ip->id()); 1697 TcpPtr tcp(ip); 1698 if (tcp) { 1699 DPRINTF(Ethernet, 1700 "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n", 1701 tcp->sport(), tcp->dport(), tcp->seq(), 1702 tcp->ack()); 1703 } 1704 } 1705 } 1706#endif 1707 1708 // sanity check - i think the driver behaves like this 1709 assert(rxDescCnt >= rxPktBytes); 1710 rxFifo.pop(); 1711 } 1712 1713 1714 // dont' need the && rxDescCnt > 0 if driver sanity check 1715 // above holds 1716 if (rxPktBytes > 0) { 1717 rxState = rxFragWrite; 1718 // don't need min<>(rxPktBytes,rxDescCnt) if above sanity 1719 // check holds 1720 rxXferLen = rxPktBytes; 1721 1722 rxDmaAddr = rxFragPtr & 0x3fffffff; 1723 rxDmaData = rxPacketBufPtr; 1724 rxDmaLen = rxXferLen; 1725 rxDmaFree = dmaDataFree; 1726 1727 if (doRxDmaWrite()) 1728 goto exit; 1729 1730 } else { 1731 rxState = rxDescWrite; 1732 1733 //if (rxPktBytes == 0) { /* packet is done */ 1734 assert(rxPktBytes == 0); 1735 DPRINTF(EthernetSM, "done with receiving packet\n"); 1736 1737 cmdsts |= CMDSTS_OWN; 1738 cmdsts &= ~CMDSTS_MORE; 1739 cmdsts |= CMDSTS_OK; 1740 cmdsts &= 0xffff0000; 1741 cmdsts += rxPacket->length; //i.e. set CMDSTS_SIZE 1742 1743#if 0 1744 /* 1745 * all the driver uses these are for its own stats keeping 1746 * which we don't care about, aren't necessary for 1747 * functionality and doing this would just slow us down. 1748 * if they end up using this in a later version for 1749 * functional purposes, just undef 1750 */ 1751 if (rxFilterEnable) { 1752 cmdsts &= ~CMDSTS_DEST_MASK; 1753 const EthAddr &dst = rxFifoFront()->dst(); 1754 if (dst->unicast()) 1755 cmdsts |= CMDSTS_DEST_SELF; 1756 if (dst->multicast()) 1757 cmdsts |= CMDSTS_DEST_MULTI; 1758 if (dst->broadcast()) 1759 cmdsts |= CMDSTS_DEST_MASK; 1760 } 1761#endif 1762 1763 IpPtr ip(rxPacket); 1764 if (extstsEnable && ip) { 1765 extsts |= EXTSTS_IPPKT; 1766 rxIpChecksums++; 1767 if (cksum(ip) != 0) { 1768 DPRINTF(EthernetCksum, "Rx IP Checksum Error\n"); 1769 extsts |= EXTSTS_IPERR; 1770 } 1771 TcpPtr tcp(ip); 1772 UdpPtr udp(ip); 1773 if (tcp) { 1774 extsts |= EXTSTS_TCPPKT; 1775 rxTcpChecksums++; 1776 if (cksum(tcp) != 0) { 1777 DPRINTF(EthernetCksum, "Rx TCP Checksum Error\n"); 1778 extsts |= EXTSTS_TCPERR; 1779 1780 } 1781 } else if (udp) { 1782 extsts |= EXTSTS_UDPPKT; 1783 rxUdpChecksums++; 1784 if (cksum(udp) != 0) { 1785 DPRINTF(EthernetCksum, "Rx UDP Checksum Error\n"); 1786 extsts |= EXTSTS_UDPERR; 1787 } 1788 } 1789 } 1790 rxPacket = 0; 1791 1792 /* 1793 * the driver seems to always receive into desc buffers 1794 * of size 1514, so you never have a pkt that is split 1795 * into multiple descriptors on the receive side, so 1796 * i don't implement that case, hence the assert above. 1797 */ 1798 1799 DPRINTF(EthernetDesc, 1800 "rxDesc: addr=%08x writeback cmdsts extsts\n", 1801 regs.rxdp & 0x3fffffff); 1802 DPRINTF(EthernetDesc, 1803 "rxDesc: link=%#x bufptr=%#x cmdsts=%08x extsts=%08x\n", 1804 link, bufptr, cmdsts, extsts); 1805 1806 rxDmaAddr = regs.rxdp & 0x3fffffff; 1807 rxDmaData = &cmdsts; 1808 if (is64bit) { 1809 rxDmaAddr += offsetof(ns_desc64, cmdsts); 1810 rxDmaLen = sizeof(rxDesc64.cmdsts) + sizeof(rxDesc64.extsts); 1811 } else { 1812 rxDmaAddr += offsetof(ns_desc32, cmdsts); 1813 rxDmaLen = sizeof(rxDesc32.cmdsts) + sizeof(rxDesc32.extsts); 1814 } 1815 rxDmaFree = dmaDescFree; 1816 1817 descDmaWrites++; 1818 descDmaWrBytes += rxDmaLen; 1819 1820 if (doRxDmaWrite()) 1821 goto exit; 1822 } 1823 break; 1824 1825 case rxFragWrite: 1826 if (rxDmaState != dmaIdle) 1827 goto exit; 1828 1829 rxPacketBufPtr += rxXferLen; 1830 rxFragPtr += rxXferLen; 1831 rxPktBytes -= rxXferLen; 1832 1833 rxState = rxFifoBlock; 1834 break; 1835 1836 case rxDescWrite: 1837 if (rxDmaState != dmaIdle) 1838 goto exit; 1839 1840 assert(cmdsts & CMDSTS_OWN); 1841 1842 assert(rxPacket == 0); 1843 devIntrPost(ISR_RXOK); 1844 1845 if (cmdsts & CMDSTS_INTR) 1846 devIntrPost(ISR_RXDESC); 1847 1848 if (!rxEnable) { 1849 DPRINTF(EthernetSM, "Halting the RX state machine\n"); 1850 rxState = rxIdle; 1851 goto exit; 1852 } else 1853 rxState = rxAdvance; 1854 break; 1855 1856 case rxAdvance: 1857 if (link == 0) { 1858 devIntrPost(ISR_RXIDLE); 1859 rxState = rxIdle; 1860 CRDD = true; 1861 goto exit; 1862 } else { 1863 if (rxDmaState != dmaIdle) 1864 goto exit; 1865 rxState = rxDescRead; 1866 regs.rxdp = link; 1867 CRDD = false; 1868 1869 rxDmaAddr = regs.rxdp & 0x3fffffff; 1870 rxDmaData = is64bit ? (void *)&rxDesc64 : (void *)&rxDesc32; 1871 rxDmaLen = is64bit ? sizeof(rxDesc64) : sizeof(rxDesc32); 1872 rxDmaFree = dmaDescFree; 1873 1874 if (doRxDmaRead()) 1875 goto exit; 1876 } 1877 break; 1878 1879 default: 1880 panic("Invalid rxState!"); 1881 } 1882 1883 DPRINTF(EthernetSM, "entering next rxState=%s\n", 1884 NsRxStateStrings[rxState]); 1885 goto next; 1886 1887 exit: 1888 /** 1889 * @todo do we want to schedule a future kick? 1890 */ 1891 DPRINTF(EthernetSM, "rx state machine exited rxState=%s\n", 1892 NsRxStateStrings[rxState]); 1893 1894 if (clock && !rxKickEvent.scheduled()) 1895 rxKickEvent.schedule(rxKickTick); 1896} 1897 1898void 1899NSGigE::transmit() 1900{ 1901 if (txFifo.empty()) { 1902 DPRINTF(Ethernet, "nothing to transmit\n"); 1903 return; 1904 } 1905 1906 DPRINTF(Ethernet, "Attempt Pkt Transmit: txFifo length=%d\n", 1907 txFifo.size()); 1908 if (interface->sendPacket(txFifo.front())) { 1909#if TRACING_ON 1910 if (DTRACE(Ethernet)) { 1911 IpPtr ip(txFifo.front()); 1912 if (ip) { 1913 DPRINTF(Ethernet, "ID is %d\n", ip->id()); 1914 TcpPtr tcp(ip); 1915 if (tcp) { 1916 DPRINTF(Ethernet, 1917 "Src Port=%d, Dest Port=%d, Seq=%d, Ack=%d\n", 1918 tcp->sport(), tcp->dport(), tcp->seq(), 1919 tcp->ack()); 1920 } 1921 } 1922 } 1923#endif 1924 1925 DDUMP(EthernetData, txFifo.front()->data, txFifo.front()->length); 1926 txBytes += txFifo.front()->length; 1927 txPackets++; 1928 1929 DPRINTF(Ethernet, "Successful Xmit! now txFifoAvail is %d\n", 1930 txFifo.avail()); 1931 txFifo.pop(); 1932 1933 /* 1934 * normally do a writeback of the descriptor here, and ONLY 1935 * after that is done, send this interrupt. but since our 1936 * stuff never actually fails, just do this interrupt here, 1937 * otherwise the code has to stray from this nice format. 1938 * besides, it's functionally the same. 1939 */ 1940 devIntrPost(ISR_TXOK); 1941 } 1942 1943 if (!txFifo.empty() && !txEvent.scheduled()) { 1944 DPRINTF(Ethernet, "reschedule transmit\n"); 1945 txEvent.schedule(curTick + retryTime); 1946 } 1947} 1948 1949void 1950NSGigE::txDmaReadCopy() 1951{ 1952 assert(txDmaState == dmaReading); 1953 1954 physmem->dma_read((uint8_t *)txDmaData, txDmaAddr, txDmaLen); 1955 txDmaState = dmaIdle; 1956 1957 DPRINTF(EthernetDMA, "tx dma read paddr=%#x len=%d\n", 1958 txDmaAddr, txDmaLen); 1959 DDUMP(EthernetDMA, txDmaData, txDmaLen); 1960} 1961 1962bool 1963NSGigE::doTxDmaRead() 1964{ 1965 assert(txDmaState == dmaIdle || txDmaState == dmaReadWaiting); 1966 txDmaState = dmaReading; 1967 1968 if (dmaInterface && !txDmaFree) { 1969 if (dmaInterface->busy()) 1970 txDmaState = dmaReadWaiting; 1971 else 1972 dmaInterface->doDMA(Read, txDmaAddr, txDmaLen, curTick, 1973 &txDmaReadEvent, true); 1974 return true; 1975 } 1976 1977 if (dmaReadDelay == 0 && dmaReadFactor == 0.0) { 1978 txDmaReadCopy(); 1979 return false; 1980 } 1981 1982 Tick factor = ((txDmaLen + ULL(63)) >> ULL(6)) * dmaReadFactor; 1983 Tick start = curTick + dmaReadDelay + factor; 1984 txDmaReadEvent.schedule(start); 1985 return true; 1986} 1987 1988void 1989NSGigE::txDmaReadDone() 1990{ 1991 assert(txDmaState == dmaReading); 1992 txDmaReadCopy(); 1993 1994 // If the receive state machine has a pending DMA, let it go first 1995 if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting) 1996 rxKick(); 1997 1998 txKick(); 1999} 2000 2001void 2002NSGigE::txDmaWriteCopy() 2003{ 2004 assert(txDmaState == dmaWriting); 2005 2006 physmem->dma_write(txDmaAddr, (uint8_t *)txDmaData, txDmaLen); 2007 txDmaState = dmaIdle; 2008 2009 DPRINTF(EthernetDMA, "tx dma write paddr=%#x len=%d\n", 2010 txDmaAddr, txDmaLen); 2011 DDUMP(EthernetDMA, txDmaData, txDmaLen); 2012} 2013 2014bool 2015NSGigE::doTxDmaWrite() 2016{ 2017 assert(txDmaState == dmaIdle || txDmaState == dmaWriteWaiting); 2018 txDmaState = dmaWriting; 2019 2020 if (dmaInterface && !txDmaFree) { 2021 if (dmaInterface->busy()) 2022 txDmaState = dmaWriteWaiting; 2023 else 2024 dmaInterface->doDMA(WriteInvalidate, txDmaAddr, txDmaLen, curTick, 2025 &txDmaWriteEvent, true); 2026 return true; 2027 } 2028 2029 if (dmaWriteDelay == 0 && dmaWriteFactor == 0.0) { 2030 txDmaWriteCopy(); 2031 return false; 2032 } 2033 2034 Tick factor = ((txDmaLen + ULL(63)) >> ULL(6)) * dmaWriteFactor; 2035 Tick start = curTick + dmaWriteDelay + factor; 2036 txDmaWriteEvent.schedule(start); 2037 return true; 2038} 2039 2040void 2041NSGigE::txDmaWriteDone() 2042{ 2043 assert(txDmaState == dmaWriting); 2044 txDmaWriteCopy(); 2045 2046 // If the receive state machine has a pending DMA, let it go first 2047 if (rxDmaState == dmaReadWaiting || rxDmaState == dmaWriteWaiting) 2048 rxKick(); 2049 2050 txKick(); 2051} 2052 2053void 2054NSGigE::txKick() 2055{ 2056 bool is64bit = (bool)(regs.config & CFGR_M64ADDR); 2057 2058 DPRINTF(EthernetSM, "transmit kick txState=%s %d-bit\n", 2059 NsTxStateStrings[txState], is64bit ? 64 : 32); 2060 2061 Addr link, bufptr; 2062 uint32_t &cmdsts = is64bit ? txDesc64.cmdsts : txDesc32.cmdsts; 2063 uint32_t &extsts = is64bit ? txDesc64.extsts : txDesc32.extsts; 2064 2065 next: 2066 if (clock) { 2067 if (txKickTick > curTick) { 2068 DPRINTF(EthernetSM, "transmit kick exiting, can't run till %d\n", 2069 txKickTick); 2070 goto exit; 2071 } 2072 2073 // Go to the next state machine clock tick. 2074 txKickTick = curTick + cycles(1); 2075 } 2076 2077 switch(txDmaState) { 2078 case dmaReadWaiting: 2079 if (doTxDmaRead()) 2080 goto exit; 2081 break; 2082 case dmaWriteWaiting: 2083 if (doTxDmaWrite()) 2084 goto exit; 2085 break; 2086 default: 2087 break; 2088 } 2089 2090 link = is64bit ? (Addr)txDesc64.link : (Addr)txDesc32.link; 2091 bufptr = is64bit ? (Addr)txDesc64.bufptr : (Addr)txDesc32.bufptr; 2092 switch (txState) { 2093 case txIdle: 2094 if (!txEnable) { 2095 DPRINTF(EthernetSM, "Transmit disabled. Nothing to do.\n"); 2096 goto exit; 2097 } 2098 2099 if (CTDD) { 2100 txState = txDescRefr; 2101 2102 txDmaAddr = regs.txdp & 0x3fffffff; 2103 txDmaData = 2104 is64bit ? (void *)&txDesc64.link : (void *)&txDesc32.link; 2105 txDmaLen = is64bit ? sizeof(txDesc64.link) : sizeof(txDesc32.link); 2106 txDmaFree = dmaDescFree; 2107 2108 descDmaReads++; 2109 descDmaRdBytes += txDmaLen; 2110 2111 if (doTxDmaRead()) 2112 goto exit; 2113 2114 } else { 2115 txState = txDescRead; 2116 2117 txDmaAddr = regs.txdp & 0x3fffffff; 2118 txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32; 2119 txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32); 2120 txDmaFree = dmaDescFree; 2121 2122 descDmaReads++; 2123 descDmaRdBytes += txDmaLen; 2124 2125 if (doTxDmaRead()) 2126 goto exit; 2127 } 2128 break; 2129 2130 case txDescRefr: 2131 if (txDmaState != dmaIdle) 2132 goto exit; 2133 2134 txState = txAdvance; 2135 break; 2136 2137 case txDescRead: 2138 if (txDmaState != dmaIdle) 2139 goto exit; 2140 2141 DPRINTF(EthernetDesc, "txDesc: addr=%08x read descriptor\n", 2142 regs.txdp & 0x3fffffff); 2143 DPRINTF(EthernetDesc, 2144 "txDesc: link=%#x bufptr=%#x cmdsts=%#08x extsts=%#08x\n", 2145 link, bufptr, cmdsts, extsts); 2146 2147 if (cmdsts & CMDSTS_OWN) { 2148 txState = txFifoBlock; 2149 txFragPtr = bufptr; 2150 txDescCnt = cmdsts & CMDSTS_LEN_MASK; 2151 } else { 2152 devIntrPost(ISR_TXIDLE); 2153 txState = txIdle; 2154 goto exit; 2155 } 2156 break; 2157 2158 case txFifoBlock: 2159 if (!txPacket) { 2160 DPRINTF(EthernetSM, "****starting the tx of a new packet****\n"); 2161 txPacket = new PacketData(16384); 2162 txPacketBufPtr = txPacket->data; 2163 } 2164 2165 if (txDescCnt == 0) { 2166 DPRINTF(EthernetSM, "the txDescCnt == 0, done with descriptor\n"); 2167 if (cmdsts & CMDSTS_MORE) { 2168 DPRINTF(EthernetSM, "there are more descriptors to come\n"); 2169 txState = txDescWrite; 2170 2171 cmdsts &= ~CMDSTS_OWN; 2172 2173 txDmaAddr = regs.txdp & 0x3fffffff; 2174 txDmaData = &cmdsts; 2175 if (is64bit) { 2176 txDmaAddr += offsetof(ns_desc64, cmdsts); 2177 txDmaLen = sizeof(txDesc64.cmdsts); 2178 } else { 2179 txDmaAddr += offsetof(ns_desc32, cmdsts); 2180 txDmaLen = sizeof(txDesc32.cmdsts); 2181 } 2182 txDmaFree = dmaDescFree; 2183 2184 if (doTxDmaWrite()) 2185 goto exit; 2186 2187 } else { /* this packet is totally done */ 2188 DPRINTF(EthernetSM, "This packet is done, let's wrap it up\n"); 2189 /* deal with the the packet that just finished */ 2190 if ((regs.vtcr & VTCR_PPCHK) && extstsEnable) { 2191 IpPtr ip(txPacket); 2192 if (extsts & EXTSTS_UDPPKT) { 2193 UdpPtr udp(ip); 2194 udp->sum(0); 2195 udp->sum(cksum(udp)); 2196 txUdpChecksums++; 2197 } else if (extsts & EXTSTS_TCPPKT) { 2198 TcpPtr tcp(ip); 2199 tcp->sum(0); 2200 tcp->sum(cksum(tcp)); 2201 txTcpChecksums++; 2202 } 2203 if (extsts & EXTSTS_IPPKT) { 2204 ip->sum(0); 2205 ip->sum(cksum(ip)); 2206 txIpChecksums++; 2207 } 2208 } 2209 2210 txPacket->length = txPacketBufPtr - txPacket->data; 2211 // this is just because the receive can't handle a 2212 // packet bigger want to make sure 2213 if (txPacket->length > 1514) 2214 panic("transmit packet too large, %s > 1514\n", 2215 txPacket->length); 2216 2217#ifndef NDEBUG 2218 bool success = 2219#endif 2220 txFifo.push(txPacket); 2221 assert(success); 2222 2223 /* 2224 * this following section is not tqo spec, but 2225 * functionally shouldn't be any different. normally, 2226 * the chip will wait til the transmit has occurred 2227 * before writing back the descriptor because it has 2228 * to wait to see that it was successfully transmitted 2229 * to decide whether to set CMDSTS_OK or not. 2230 * however, in the simulator since it is always 2231 * successfully transmitted, and writing it exactly to 2232 * spec would complicate the code, we just do it here 2233 */ 2234 2235 cmdsts &= ~CMDSTS_OWN; 2236 cmdsts |= CMDSTS_OK; 2237 2238 DPRINTF(EthernetDesc, 2239 "txDesc writeback: cmdsts=%08x extsts=%08x\n", 2240 cmdsts, extsts); 2241 2242 txDmaFree = dmaDescFree; 2243 txDmaAddr = regs.txdp & 0x3fffffff; 2244 txDmaData = &cmdsts; 2245 if (is64bit) { 2246 txDmaAddr += offsetof(ns_desc64, cmdsts); 2247 txDmaLen = 2248 sizeof(txDesc64.cmdsts) + sizeof(txDesc64.extsts); 2249 } else { 2250 txDmaAddr += offsetof(ns_desc32, cmdsts); 2251 txDmaLen = 2252 sizeof(txDesc32.cmdsts) + sizeof(txDesc32.extsts); 2253 } 2254 2255 descDmaWrites++; 2256 descDmaWrBytes += txDmaLen; 2257 2258 transmit(); 2259 txPacket = 0; 2260 2261 if (!txEnable) { 2262 DPRINTF(EthernetSM, "halting TX state machine\n"); 2263 txState = txIdle; 2264 goto exit; 2265 } else 2266 txState = txAdvance; 2267 2268 if (doTxDmaWrite()) 2269 goto exit; 2270 } 2271 } else { 2272 DPRINTF(EthernetSM, "this descriptor isn't done yet\n"); 2273 if (!txFifo.full()) { 2274 txState = txFragRead; 2275 2276 /* 2277 * The number of bytes transferred is either whatever 2278 * is left in the descriptor (txDescCnt), or if there 2279 * is not enough room in the fifo, just whatever room 2280 * is left in the fifo 2281 */ 2282 txXferLen = min<uint32_t>(txDescCnt, txFifo.avail()); 2283 2284 txDmaAddr = txFragPtr & 0x3fffffff; 2285 txDmaData = txPacketBufPtr; 2286 txDmaLen = txXferLen; 2287 txDmaFree = dmaDataFree; 2288 2289 if (doTxDmaRead()) 2290 goto exit; 2291 } else { 2292 txState = txFifoBlock; 2293 transmit(); 2294 2295 goto exit; 2296 } 2297 2298 } 2299 break; 2300 2301 case txFragRead: 2302 if (txDmaState != dmaIdle) 2303 goto exit; 2304 2305 txPacketBufPtr += txXferLen; 2306 txFragPtr += txXferLen; 2307 txDescCnt -= txXferLen; 2308 txFifo.reserve(txXferLen); 2309 2310 txState = txFifoBlock; 2311 break; 2312 2313 case txDescWrite: 2314 if (txDmaState != dmaIdle) 2315 goto exit; 2316 2317 if (cmdsts & CMDSTS_INTR) 2318 devIntrPost(ISR_TXDESC); 2319 2320 if (!txEnable) { 2321 DPRINTF(EthernetSM, "halting TX state machine\n"); 2322 txState = txIdle; 2323 goto exit; 2324 } else 2325 txState = txAdvance; 2326 break; 2327 2328 case txAdvance: 2329 if (link == 0) { 2330 devIntrPost(ISR_TXIDLE); 2331 txState = txIdle; 2332 goto exit; 2333 } else { 2334 if (txDmaState != dmaIdle) 2335 goto exit; 2336 txState = txDescRead; 2337 regs.txdp = link; 2338 CTDD = false; 2339 2340 txDmaAddr = link & 0x3fffffff; 2341 txDmaData = is64bit ? (void *)&txDesc64 : (void *)&txDesc32; 2342 txDmaLen = is64bit ? sizeof(txDesc64) : sizeof(txDesc32); 2343 txDmaFree = dmaDescFree; 2344 2345 if (doTxDmaRead()) 2346 goto exit; 2347 } 2348 break; 2349 2350 default: 2351 panic("invalid state"); 2352 } 2353 2354 DPRINTF(EthernetSM, "entering next txState=%s\n", 2355 NsTxStateStrings[txState]); 2356 goto next; 2357 2358 exit: 2359 /** 2360 * @todo do we want to schedule a future kick? 2361 */ 2362 DPRINTF(EthernetSM, "tx state machine exited txState=%s\n", 2363 NsTxStateStrings[txState]); 2364 2365 if (clock && !txKickEvent.scheduled()) 2366 txKickEvent.schedule(txKickTick); 2367} 2368 2369/** 2370 * Advance the EEPROM state machine 2371 * Called on rising edge of EEPROM clock bit in MEAR 2372 */ 2373void 2374NSGigE::eepromKick() 2375{ 2376 switch (eepromState) { 2377 2378 case eepromStart: 2379 2380 // Wait for start bit 2381 if (regs.mear & MEAR_EEDI) { 2382 // Set up to get 2 opcode bits 2383 eepromState = eepromGetOpcode; 2384 eepromBitsToRx = 2; 2385 eepromOpcode = 0; 2386 } 2387 break; 2388 2389 case eepromGetOpcode: 2390 eepromOpcode <<= 1; 2391 eepromOpcode += (regs.mear & MEAR_EEDI) ? 1 : 0; 2392 --eepromBitsToRx; 2393 2394 // Done getting opcode 2395 if (eepromBitsToRx == 0) { 2396 if (eepromOpcode != EEPROM_READ) 2397 panic("only EEPROM reads are implemented!"); 2398 2399 // Set up to get address 2400 eepromState = eepromGetAddress; 2401 eepromBitsToRx = 6; 2402 eepromAddress = 0; 2403 } 2404 break; 2405 2406 case eepromGetAddress: 2407 eepromAddress <<= 1; 2408 eepromAddress += (regs.mear & MEAR_EEDI) ? 1 : 0; 2409 --eepromBitsToRx; 2410 2411 // Done getting address 2412 if (eepromBitsToRx == 0) { 2413 2414 if (eepromAddress >= EEPROM_SIZE) 2415 panic("EEPROM read access out of range!"); 2416 2417 switch (eepromAddress) { 2418 2419 case EEPROM_PMATCH2_ADDR: 2420 eepromData = rom.perfectMatch[5]; 2421 eepromData <<= 8; 2422 eepromData += rom.perfectMatch[4]; 2423 break; 2424 2425 case EEPROM_PMATCH1_ADDR: 2426 eepromData = rom.perfectMatch[3]; 2427 eepromData <<= 8; 2428 eepromData += rom.perfectMatch[2]; 2429 break; 2430 2431 case EEPROM_PMATCH0_ADDR: 2432 eepromData = rom.perfectMatch[1]; 2433 eepromData <<= 8; 2434 eepromData += rom.perfectMatch[0]; 2435 break; 2436 2437 default: 2438 panic("FreeBSD driver only uses EEPROM to read PMATCH!"); 2439 } 2440 // Set up to read data 2441 eepromState = eepromRead; 2442 eepromBitsToRx = 16; 2443 2444 // Clear data in bit 2445 regs.mear &= ~MEAR_EEDI; 2446 } 2447 break; 2448 2449 case eepromRead: 2450 // Clear Data Out bit 2451 regs.mear &= ~MEAR_EEDO; 2452 // Set bit to value of current EEPROM bit 2453 regs.mear |= (eepromData & 0x8000) ? MEAR_EEDO : 0x0; 2454 2455 eepromData <<= 1; 2456 --eepromBitsToRx; 2457 2458 // All done 2459 if (eepromBitsToRx == 0) { 2460 eepromState = eepromStart; 2461 } 2462 break; 2463 2464 default: 2465 panic("invalid EEPROM state"); 2466 } 2467 2468} 2469 2470void 2471NSGigE::transferDone() 2472{ 2473 if (txFifo.empty()) { 2474 DPRINTF(Ethernet, "transfer complete: txFifo empty...nothing to do\n"); 2475 return; 2476 } 2477 2478 DPRINTF(Ethernet, "transfer complete: data in txFifo...schedule xmit\n"); 2479 2480 if (txEvent.scheduled()) 2481 txEvent.reschedule(curTick + cycles(1)); 2482 else 2483 txEvent.schedule(curTick + cycles(1)); 2484} 2485 2486bool 2487NSGigE::rxFilter(const PacketPtr &packet) 2488{ 2489 EthPtr eth = packet; 2490 bool drop = true; 2491 string type; 2492 2493 const EthAddr &dst = eth->dst(); 2494 if (dst.unicast()) { 2495 // If we're accepting all unicast addresses 2496 if (acceptUnicast) 2497 drop = false; 2498 2499 // If we make a perfect match 2500 if (acceptPerfect && dst == rom.perfectMatch) 2501 drop = false; 2502 2503 if (acceptArp && eth->type() == ETH_TYPE_ARP) 2504 drop = false; 2505 2506 } else if (dst.broadcast()) { 2507 // if we're accepting broadcasts 2508 if (acceptBroadcast) 2509 drop = false; 2510 2511 } else if (dst.multicast()) { 2512 // if we're accepting all multicasts 2513 if (acceptMulticast) 2514 drop = false; 2515 2516 // Multicast hashing faked - all packets accepted 2517 if (multicastHashEnable) 2518 drop = false; 2519 } 2520 2521 if (drop) { 2522 DPRINTF(Ethernet, "rxFilter drop\n"); 2523 DDUMP(EthernetData, packet->data, packet->length); 2524 } 2525 2526 return drop; 2527} 2528 2529bool 2530NSGigE::recvPacket(PacketPtr packet) 2531{ 2532 rxBytes += packet->length; 2533 rxPackets++; 2534 2535 DPRINTF(Ethernet, "Receiving packet from wire, rxFifoAvail=%d\n", 2536 rxFifo.avail()); 2537 2538 if (!rxEnable) { 2539 DPRINTF(Ethernet, "receive disabled...packet dropped\n"); 2540 return true; 2541 } 2542 2543 if (!rxFilterEnable) { 2544 DPRINTF(Ethernet, 2545 "receive packet filtering disabled . . . packet dropped\n"); 2546 return true; 2547 } 2548 2549 if (rxFilter(packet)) { 2550 DPRINTF(Ethernet, "packet filtered...dropped\n"); 2551 return true; 2552 } 2553 2554 if (rxFifo.avail() < packet->length) { 2555#if TRACING_ON 2556 IpPtr ip(packet); 2557 TcpPtr tcp(ip); 2558 if (ip) { 2559 DPRINTF(Ethernet, 2560 "packet won't fit in receive buffer...pkt ID %d dropped\n", 2561 ip->id()); 2562 if (tcp) { 2563 DPRINTF(Ethernet, "Seq=%d\n", tcp->seq()); 2564 } 2565 } 2566#endif 2567 droppedPackets++; 2568 devIntrPost(ISR_RXORN); 2569 return false; 2570 } 2571 2572 rxFifo.push(packet); 2573 2574 rxKick(); 2575 return true; 2576} 2577 2578//===================================================================== 2579// 2580// 2581void 2582NSGigE::serialize(ostream &os) 2583{ 2584 // Serialize the PciDev base class 2585 PciDev::serialize(os); 2586 2587 /* 2588 * Finalize any DMA events now. 2589 */ 2590 if (rxDmaReadEvent.scheduled()) 2591 rxDmaReadCopy(); 2592 if (rxDmaWriteEvent.scheduled()) 2593 rxDmaWriteCopy(); 2594 if (txDmaReadEvent.scheduled()) 2595 txDmaReadCopy(); 2596 if (txDmaWriteEvent.scheduled()) 2597 txDmaWriteCopy(); 2598 2599 /* 2600 * Serialize the device registers 2601 */ 2602 SERIALIZE_SCALAR(regs.command); 2603 SERIALIZE_SCALAR(regs.config); 2604 SERIALIZE_SCALAR(regs.mear); 2605 SERIALIZE_SCALAR(regs.ptscr); 2606 SERIALIZE_SCALAR(regs.isr); 2607 SERIALIZE_SCALAR(regs.imr); 2608 SERIALIZE_SCALAR(regs.ier); 2609 SERIALIZE_SCALAR(regs.ihr); 2610 SERIALIZE_SCALAR(regs.txdp); 2611 SERIALIZE_SCALAR(regs.txdp_hi); 2612 SERIALIZE_SCALAR(regs.txcfg); 2613 SERIALIZE_SCALAR(regs.gpior); 2614 SERIALIZE_SCALAR(regs.rxdp); 2615 SERIALIZE_SCALAR(regs.rxdp_hi); 2616 SERIALIZE_SCALAR(regs.rxcfg); 2617 SERIALIZE_SCALAR(regs.pqcr); 2618 SERIALIZE_SCALAR(regs.wcsr); 2619 SERIALIZE_SCALAR(regs.pcr); 2620 SERIALIZE_SCALAR(regs.rfcr); 2621 SERIALIZE_SCALAR(regs.rfdr); 2622 SERIALIZE_SCALAR(regs.brar); 2623 SERIALIZE_SCALAR(regs.brdr); 2624 SERIALIZE_SCALAR(regs.srr); 2625 SERIALIZE_SCALAR(regs.mibc); 2626 SERIALIZE_SCALAR(regs.vrcr); 2627 SERIALIZE_SCALAR(regs.vtcr); 2628 SERIALIZE_SCALAR(regs.vdr); 2629 SERIALIZE_SCALAR(regs.ccsr); 2630 SERIALIZE_SCALAR(regs.tbicr); 2631 SERIALIZE_SCALAR(regs.tbisr); 2632 SERIALIZE_SCALAR(regs.tanar); 2633 SERIALIZE_SCALAR(regs.tanlpar); 2634 SERIALIZE_SCALAR(regs.taner); 2635 SERIALIZE_SCALAR(regs.tesr); 2636 2637 SERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN); 2638 SERIALIZE_ARRAY(rom.filterHash, FHASH_SIZE); 2639 2640 SERIALIZE_SCALAR(ioEnable); 2641 2642 /* 2643 * Serialize the data Fifos 2644 */ 2645 rxFifo.serialize("rxFifo", os); 2646 txFifo.serialize("txFifo", os); 2647 2648 /* 2649 * Serialize the various helper variables 2650 */ 2651 bool txPacketExists = txPacket; 2652 SERIALIZE_SCALAR(txPacketExists); 2653 if (txPacketExists) { 2654 txPacket->length = txPacketBufPtr - txPacket->data; 2655 txPacket->serialize("txPacket", os); 2656 uint32_t txPktBufPtr = (uint32_t) (txPacketBufPtr - txPacket->data); 2657 SERIALIZE_SCALAR(txPktBufPtr); 2658 } 2659 2660 bool rxPacketExists = rxPacket; 2661 SERIALIZE_SCALAR(rxPacketExists); 2662 if (rxPacketExists) { 2663 rxPacket->serialize("rxPacket", os); 2664 uint32_t rxPktBufPtr = (uint32_t) (rxPacketBufPtr - rxPacket->data); 2665 SERIALIZE_SCALAR(rxPktBufPtr); 2666 } 2667 2668 SERIALIZE_SCALAR(txXferLen); 2669 SERIALIZE_SCALAR(rxXferLen); 2670 2671 /* 2672 * Serialize Cached Descriptors 2673 */ 2674 SERIALIZE_SCALAR(rxDesc64.link); 2675 SERIALIZE_SCALAR(rxDesc64.bufptr); 2676 SERIALIZE_SCALAR(rxDesc64.cmdsts); 2677 SERIALIZE_SCALAR(rxDesc64.extsts); 2678 SERIALIZE_SCALAR(txDesc64.link); 2679 SERIALIZE_SCALAR(txDesc64.bufptr); 2680 SERIALIZE_SCALAR(txDesc64.cmdsts); 2681 SERIALIZE_SCALAR(txDesc64.extsts); 2682 SERIALIZE_SCALAR(rxDesc32.link); 2683 SERIALIZE_SCALAR(rxDesc32.bufptr); 2684 SERIALIZE_SCALAR(rxDesc32.cmdsts); 2685 SERIALIZE_SCALAR(rxDesc32.extsts); 2686 SERIALIZE_SCALAR(txDesc32.link); 2687 SERIALIZE_SCALAR(txDesc32.bufptr); 2688 SERIALIZE_SCALAR(txDesc32.cmdsts); 2689 SERIALIZE_SCALAR(txDesc32.extsts); 2690 SERIALIZE_SCALAR(extstsEnable); 2691 2692 /* 2693 * Serialize tx state machine 2694 */ 2695 int txState = this->txState; 2696 SERIALIZE_SCALAR(txState); 2697 SERIALIZE_SCALAR(txEnable); 2698 SERIALIZE_SCALAR(CTDD); 2699 SERIALIZE_SCALAR(txFragPtr); 2700 SERIALIZE_SCALAR(txDescCnt); 2701 int txDmaState = this->txDmaState; 2702 SERIALIZE_SCALAR(txDmaState); 2703 SERIALIZE_SCALAR(txKickTick); 2704 2705 /* 2706 * Serialize rx state machine 2707 */ 2708 int rxState = this->rxState; 2709 SERIALIZE_SCALAR(rxState); 2710 SERIALIZE_SCALAR(rxEnable); 2711 SERIALIZE_SCALAR(CRDD); 2712 SERIALIZE_SCALAR(rxPktBytes); 2713 SERIALIZE_SCALAR(rxFragPtr); 2714 SERIALIZE_SCALAR(rxDescCnt); 2715 int rxDmaState = this->rxDmaState; 2716 SERIALIZE_SCALAR(rxDmaState); 2717 SERIALIZE_SCALAR(rxKickTick); 2718 2719 /* 2720 * Serialize EEPROM state machine 2721 */ 2722 int eepromState = this->eepromState; 2723 SERIALIZE_SCALAR(eepromState); 2724 SERIALIZE_SCALAR(eepromClk); 2725 SERIALIZE_SCALAR(eepromBitsToRx); 2726 SERIALIZE_SCALAR(eepromOpcode); 2727 SERIALIZE_SCALAR(eepromAddress); 2728 SERIALIZE_SCALAR(eepromData); 2729 2730 /* 2731 * If there's a pending transmit, store the time so we can 2732 * reschedule it later 2733 */ 2734 Tick transmitTick = txEvent.scheduled() ? txEvent.when() - curTick : 0; 2735 SERIALIZE_SCALAR(transmitTick); 2736 2737 /* 2738 * receive address filter settings 2739 */ 2740 SERIALIZE_SCALAR(rxFilterEnable); 2741 SERIALIZE_SCALAR(acceptBroadcast); 2742 SERIALIZE_SCALAR(acceptMulticast); 2743 SERIALIZE_SCALAR(acceptUnicast); 2744 SERIALIZE_SCALAR(acceptPerfect); 2745 SERIALIZE_SCALAR(acceptArp); 2746 SERIALIZE_SCALAR(multicastHashEnable); 2747 2748 /* 2749 * Keep track of pending interrupt status. 2750 */ 2751 SERIALIZE_SCALAR(intrTick); 2752 SERIALIZE_SCALAR(cpuPendingIntr); 2753 Tick intrEventTick = 0; 2754 if (intrEvent) 2755 intrEventTick = intrEvent->when(); 2756 SERIALIZE_SCALAR(intrEventTick); 2757 2758} 2759 2760void 2761NSGigE::unserialize(Checkpoint *cp, const std::string §ion) 2762{ 2763 // Unserialize the PciDev base class 2764 PciDev::unserialize(cp, section); 2765 2766 UNSERIALIZE_SCALAR(regs.command); 2767 UNSERIALIZE_SCALAR(regs.config); 2768 UNSERIALIZE_SCALAR(regs.mear); 2769 UNSERIALIZE_SCALAR(regs.ptscr); 2770 UNSERIALIZE_SCALAR(regs.isr); 2771 UNSERIALIZE_SCALAR(regs.imr); 2772 UNSERIALIZE_SCALAR(regs.ier); 2773 UNSERIALIZE_SCALAR(regs.ihr); 2774 UNSERIALIZE_SCALAR(regs.txdp); 2775 UNSERIALIZE_SCALAR(regs.txdp_hi); 2776 UNSERIALIZE_SCALAR(regs.txcfg); 2777 UNSERIALIZE_SCALAR(regs.gpior); 2778 UNSERIALIZE_SCALAR(regs.rxdp); 2779 UNSERIALIZE_SCALAR(regs.rxdp_hi); 2780 UNSERIALIZE_SCALAR(regs.rxcfg); 2781 UNSERIALIZE_SCALAR(regs.pqcr); 2782 UNSERIALIZE_SCALAR(regs.wcsr); 2783 UNSERIALIZE_SCALAR(regs.pcr); 2784 UNSERIALIZE_SCALAR(regs.rfcr); 2785 UNSERIALIZE_SCALAR(regs.rfdr); 2786 UNSERIALIZE_SCALAR(regs.brar); 2787 UNSERIALIZE_SCALAR(regs.brdr); 2788 UNSERIALIZE_SCALAR(regs.srr); 2789 UNSERIALIZE_SCALAR(regs.mibc); 2790 UNSERIALIZE_SCALAR(regs.vrcr); 2791 UNSERIALIZE_SCALAR(regs.vtcr); 2792 UNSERIALIZE_SCALAR(regs.vdr); 2793 UNSERIALIZE_SCALAR(regs.ccsr); 2794 UNSERIALIZE_SCALAR(regs.tbicr); 2795 UNSERIALIZE_SCALAR(regs.tbisr); 2796 UNSERIALIZE_SCALAR(regs.tanar); 2797 UNSERIALIZE_SCALAR(regs.tanlpar); 2798 UNSERIALIZE_SCALAR(regs.taner); 2799 UNSERIALIZE_SCALAR(regs.tesr); 2800 2801 UNSERIALIZE_ARRAY(rom.perfectMatch, ETH_ADDR_LEN); 2802 UNSERIALIZE_ARRAY(rom.filterHash, FHASH_SIZE); 2803 2804 UNSERIALIZE_SCALAR(ioEnable); 2805 2806 /* 2807 * unserialize the data fifos 2808 */ 2809 rxFifo.unserialize("rxFifo", cp, section); 2810 txFifo.unserialize("txFifo", cp, section); 2811 2812 /* 2813 * unserialize the various helper variables 2814 */ 2815 bool txPacketExists; 2816 UNSERIALIZE_SCALAR(txPacketExists); 2817 if (txPacketExists) { 2818 txPacket = new PacketData(16384); 2819 txPacket->unserialize("txPacket", cp, section); 2820 uint32_t txPktBufPtr; 2821 UNSERIALIZE_SCALAR(txPktBufPtr); 2822 txPacketBufPtr = (uint8_t *) txPacket->data + txPktBufPtr; 2823 } else 2824 txPacket = 0; 2825 2826 bool rxPacketExists; 2827 UNSERIALIZE_SCALAR(rxPacketExists); 2828 rxPacket = 0; 2829 if (rxPacketExists) { 2830 rxPacket = new PacketData(16384); 2831 rxPacket->unserialize("rxPacket", cp, section); 2832 uint32_t rxPktBufPtr; 2833 UNSERIALIZE_SCALAR(rxPktBufPtr); 2834 rxPacketBufPtr = (uint8_t *) rxPacket->data + rxPktBufPtr; 2835 } else 2836 rxPacket = 0; 2837 2838 UNSERIALIZE_SCALAR(txXferLen); 2839 UNSERIALIZE_SCALAR(rxXferLen); 2840 2841 /* 2842 * Unserialize Cached Descriptors 2843 */ 2844 UNSERIALIZE_SCALAR(rxDesc64.link); 2845 UNSERIALIZE_SCALAR(rxDesc64.bufptr); 2846 UNSERIALIZE_SCALAR(rxDesc64.cmdsts); 2847 UNSERIALIZE_SCALAR(rxDesc64.extsts); 2848 UNSERIALIZE_SCALAR(txDesc64.link); 2849 UNSERIALIZE_SCALAR(txDesc64.bufptr); 2850 UNSERIALIZE_SCALAR(txDesc64.cmdsts); 2851 UNSERIALIZE_SCALAR(txDesc64.extsts); 2852 UNSERIALIZE_SCALAR(rxDesc32.link); 2853 UNSERIALIZE_SCALAR(rxDesc32.bufptr); 2854 UNSERIALIZE_SCALAR(rxDesc32.cmdsts); 2855 UNSERIALIZE_SCALAR(rxDesc32.extsts); 2856 UNSERIALIZE_SCALAR(txDesc32.link); 2857 UNSERIALIZE_SCALAR(txDesc32.bufptr); 2858 UNSERIALIZE_SCALAR(txDesc32.cmdsts); 2859 UNSERIALIZE_SCALAR(txDesc32.extsts); 2860 UNSERIALIZE_SCALAR(extstsEnable); 2861 2862 /* 2863 * unserialize tx state machine 2864 */ 2865 int txState; 2866 UNSERIALIZE_SCALAR(txState); 2867 this->txState = (TxState) txState; 2868 UNSERIALIZE_SCALAR(txEnable); 2869 UNSERIALIZE_SCALAR(CTDD); 2870 UNSERIALIZE_SCALAR(txFragPtr); 2871 UNSERIALIZE_SCALAR(txDescCnt); 2872 int txDmaState; 2873 UNSERIALIZE_SCALAR(txDmaState); 2874 this->txDmaState = (DmaState) txDmaState; 2875 UNSERIALIZE_SCALAR(txKickTick); 2876 if (txKickTick) 2877 txKickEvent.schedule(txKickTick); 2878 2879 /* 2880 * unserialize rx state machine 2881 */ 2882 int rxState; 2883 UNSERIALIZE_SCALAR(rxState); 2884 this->rxState = (RxState) rxState; 2885 UNSERIALIZE_SCALAR(rxEnable); 2886 UNSERIALIZE_SCALAR(CRDD); 2887 UNSERIALIZE_SCALAR(rxPktBytes); 2888 UNSERIALIZE_SCALAR(rxFragPtr); 2889 UNSERIALIZE_SCALAR(rxDescCnt); 2890 int rxDmaState; 2891 UNSERIALIZE_SCALAR(rxDmaState); 2892 this->rxDmaState = (DmaState) rxDmaState; 2893 UNSERIALIZE_SCALAR(rxKickTick); 2894 if (rxKickTick) 2895 rxKickEvent.schedule(rxKickTick); 2896 2897 /* 2898 * Unserialize EEPROM state machine 2899 */ 2900 int eepromState; 2901 UNSERIALIZE_SCALAR(eepromState); 2902 this->eepromState = (EEPROMState) eepromState; 2903 UNSERIALIZE_SCALAR(eepromClk); 2904 UNSERIALIZE_SCALAR(eepromBitsToRx); 2905 UNSERIALIZE_SCALAR(eepromOpcode); 2906 UNSERIALIZE_SCALAR(eepromAddress); 2907 UNSERIALIZE_SCALAR(eepromData); 2908 2909 /* 2910 * If there's a pending transmit, reschedule it now 2911 */ 2912 Tick transmitTick; 2913 UNSERIALIZE_SCALAR(transmitTick); 2914 if (transmitTick) 2915 txEvent.schedule(curTick + transmitTick); 2916 2917 /* 2918 * unserialize receive address filter settings 2919 */ 2920 UNSERIALIZE_SCALAR(rxFilterEnable); 2921 UNSERIALIZE_SCALAR(acceptBroadcast); 2922 UNSERIALIZE_SCALAR(acceptMulticast); 2923 UNSERIALIZE_SCALAR(acceptUnicast); 2924 UNSERIALIZE_SCALAR(acceptPerfect); 2925 UNSERIALIZE_SCALAR(acceptArp); 2926 UNSERIALIZE_SCALAR(multicastHashEnable); 2927 2928 /* 2929 * Keep track of pending interrupt status. 2930 */ 2931 UNSERIALIZE_SCALAR(intrTick); 2932 UNSERIALIZE_SCALAR(cpuPendingIntr); 2933 Tick intrEventTick; 2934 UNSERIALIZE_SCALAR(intrEventTick); 2935 if (intrEventTick) { 2936 intrEvent = new IntrEvent(this, true); 2937 intrEvent->schedule(intrEventTick); 2938 } 2939 2940 /* 2941 * re-add addrRanges to bus bridges 2942 */ 2943 if (pioInterface) { 2944 pioInterface->addAddrRange(RangeSize(BARAddrs[0], BARSize[0])); 2945 pioInterface->addAddrRange(RangeSize(BARAddrs[1], BARSize[1])); 2946 } 2947} 2948 2949Tick 2950NSGigE::cacheAccess(MemReqPtr &req) 2951{ 2952 Addr daddr = req->paddr & 0xfff; 2953 DPRINTF(EthernetPIO, "timing access to paddr=%#x (daddr=%#x)\n", 2954 req->paddr, daddr); 2955 2956 if (!pioDelayWrite || !req->cmd.isWrite()) 2957 return curTick + pioLatency; 2958 2959 int cpu = (req->xc->regs.ipr[TheISA::IPR_PALtemp16] >> 8) & 0xff; 2960 std::list<RegWriteData> &wq = writeQueue[cpu]; 2961 if (wq.empty()) 2962 panic("WriteQueue for cpu %d empty timing daddr=%#x", cpu, daddr); 2963 2964 const RegWriteData &data = wq.front(); 2965 if (data.daddr != daddr) 2966 panic("read mismatch on cpu %d, daddr functional=%#x timing=%#x", 2967 cpu, data.daddr, daddr); 2968 2969 if (daddr == CR) { 2970 if ((data.value & (CR_TXD | CR_TXE)) == CR_TXE) { 2971 txEnable = true; 2972 if (txState == txIdle) 2973 txKick(); 2974 } 2975 2976 if ((data.value & (CR_RXD | CR_RXE)) == CR_RXE) { 2977 rxEnable = true; 2978 if (rxState == rxIdle) 2979 rxKick(); 2980 } 2981 } 2982 2983 wq.pop_front(); 2984 return curTick + pioLatency; 2985} 2986 2987BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt) 2988 2989 SimObjectParam<EtherInt *> peer; 2990 SimObjectParam<NSGigE *> device; 2991 2992END_DECLARE_SIM_OBJECT_PARAMS(NSGigEInt) 2993 2994BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigEInt) 2995 2996 INIT_PARAM_DFLT(peer, "peer interface", NULL), 2997 INIT_PARAM(device, "Ethernet device of this interface") 2998 2999END_INIT_SIM_OBJECT_PARAMS(NSGigEInt) 3000 3001CREATE_SIM_OBJECT(NSGigEInt) 3002{ 3003 NSGigEInt *dev_int = new NSGigEInt(getInstanceName(), device); 3004 3005 EtherInt *p = (EtherInt *)peer; 3006 if (p) { 3007 dev_int->setPeer(p); 3008 p->setPeer(dev_int); 3009 } 3010 3011 return dev_int; 3012} 3013 3014REGISTER_SIM_OBJECT("NSGigEInt", NSGigEInt) 3015 3016 3017BEGIN_DECLARE_SIM_OBJECT_PARAMS(NSGigE) 3018 3019 Param<Tick> clock; 3020 3021 Param<Addr> addr; 3022 SimObjectParam<MemoryController *> mmu; 3023 SimObjectParam<PhysicalMemory *> physmem; 3024 SimObjectParam<PciConfigAll *> configspace; 3025 SimObjectParam<PciConfigData *> configdata; 3026 SimObjectParam<Platform *> platform; 3027 Param<uint32_t> pci_bus; 3028 Param<uint32_t> pci_dev; 3029 Param<uint32_t> pci_func; 3030 3031 SimObjectParam<HierParams *> hier; 3032 SimObjectParam<Bus*> pio_bus; 3033 SimObjectParam<Bus*> dma_bus; 3034 SimObjectParam<Bus*> payload_bus; 3035 Param<bool> dma_desc_free; 3036 Param<bool> dma_data_free; 3037 Param<Tick> dma_read_delay; 3038 Param<Tick> dma_write_delay; 3039 Param<Tick> dma_read_factor; 3040 Param<Tick> dma_write_factor; 3041 Param<bool> dma_no_allocate; 3042 Param<Tick> pio_latency; 3043 Param<bool> pio_delay_write; 3044 Param<Tick> intr_delay; 3045 3046 Param<Tick> rx_delay; 3047 Param<Tick> tx_delay; 3048 Param<uint32_t> rx_fifo_size; 3049 Param<uint32_t> tx_fifo_size; 3050 3051 Param<bool> rx_filter; 3052 Param<string> hardware_address; 3053 Param<bool> rx_thread; 3054 Param<bool> tx_thread; 3055 3056END_DECLARE_SIM_OBJECT_PARAMS(NSGigE) 3057 3058BEGIN_INIT_SIM_OBJECT_PARAMS(NSGigE) 3059 3060 INIT_PARAM(clock, "State machine processor frequency"), 3061 3062 INIT_PARAM(addr, "Device Address"), 3063 INIT_PARAM(mmu, "Memory Controller"), 3064 INIT_PARAM(physmem, "Physical Memory"), 3065 INIT_PARAM(configspace, "PCI Configspace"), 3066 INIT_PARAM(configdata, "PCI Config data"), 3067 INIT_PARAM(platform, "Platform"), 3068 INIT_PARAM(pci_bus, "PCI bus"), 3069 INIT_PARAM(pci_dev, "PCI device number"), 3070 INIT_PARAM(pci_func, "PCI function code"), 3071 3072 INIT_PARAM(hier, "Hierarchy global variables"), 3073 INIT_PARAM(pio_bus, ""), 3074 INIT_PARAM(dma_bus, ""), 3075 INIT_PARAM(payload_bus, "The IO Bus to attach to for payload"), 3076 INIT_PARAM(dma_desc_free, "DMA of Descriptors is free"), 3077 INIT_PARAM(dma_data_free, "DMA of Data is free"), 3078 INIT_PARAM(dma_read_delay, "fixed delay for dma reads"), 3079 INIT_PARAM(dma_write_delay, "fixed delay for dma writes"), 3080 INIT_PARAM(dma_read_factor, "multiplier for dma reads"), 3081 INIT_PARAM(dma_write_factor, "multiplier for dma writes"), 3082 INIT_PARAM(dma_no_allocate, "Should DMA reads allocate cache lines"), 3083 INIT_PARAM(pio_latency, "Programmed IO latency in bus cycles"), 3084 INIT_PARAM(pio_delay_write, ""), 3085 INIT_PARAM(intr_delay, "Interrupt Delay in microseconds"), 3086 3087 INIT_PARAM(rx_delay, "Receive Delay"), 3088 INIT_PARAM(tx_delay, "Transmit Delay"), 3089 INIT_PARAM(rx_fifo_size, "max size in bytes of rxFifo"), 3090 INIT_PARAM(tx_fifo_size, "max size in bytes of txFifo"), 3091 3092 INIT_PARAM(rx_filter, "Enable Receive Filter"), 3093 INIT_PARAM(hardware_address, "Ethernet Hardware Address"), 3094 INIT_PARAM(rx_thread, ""), 3095 INIT_PARAM(tx_thread, "") 3096 3097END_INIT_SIM_OBJECT_PARAMS(NSGigE) 3098 3099 3100CREATE_SIM_OBJECT(NSGigE) 3101{ 3102 NSGigE::Params *params = new NSGigE::Params; 3103 3104 params->name = getInstanceName(); 3105 3106 params->clock = clock; 3107 3108 params->mmu = mmu; 3109 params->pmem = physmem; 3110 params->configSpace = configspace; 3111 params->configData = configdata; 3112 params->plat = platform; 3113 params->busNum = pci_bus; 3114 params->deviceNum = pci_dev; 3115 params->functionNum = pci_func; 3116 3117 params->hier = hier; 3118 params->pio_bus = pio_bus; 3119 params->header_bus = dma_bus; 3120 params->payload_bus = payload_bus; 3121 params->dma_desc_free = dma_desc_free; 3122 params->dma_data_free = dma_data_free; 3123 params->dma_read_delay = dma_read_delay; 3124 params->dma_write_delay = dma_write_delay; 3125 params->dma_read_factor = dma_read_factor; 3126 params->dma_write_factor = dma_write_factor; 3127 params->dma_no_allocate = dma_no_allocate; 3128 params->pio_latency = pio_latency; 3129 params->pio_delay_write = pio_delay_write; 3130 params->intr_delay = intr_delay; 3131 3132 params->rx_delay = rx_delay; 3133 params->tx_delay = tx_delay; 3134 params->rx_fifo_size = rx_fifo_size; 3135 params->tx_fifo_size = tx_fifo_size; 3136 3137 params->rx_filter = rx_filter; 3138 params->eaddr = hardware_address; 3139 params->rx_thread = rx_thread; 3140 params->tx_thread = tx_thread; 3141 3142 return new NSGigE(params); 3143} 3144 3145REGISTER_SIM_OBJECT("NSGigE", NSGigE) 3146