ns_gige.cc revision 837
1/* 2 * Copyright (c) 2003 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29/* @file 30 * Device module for modelling the National Semiconductor 31 * DP83820 ethernet controller. Does not support priority queueing 32 */ 33#include <cstdio> 34#include <deque> 35#include <string> 36 37#include "base/inet.hh" 38#include "cpu/exec_context.hh" 39#include "cpu/intr_control.hh" 40#include "dev/dma.hh" 41#include "dev/ns_gige.hh" 42#include "dev/etherlink.hh" 43#include "mem/functional_mem/memory_control.hh" 44#include "mem/functional_mem/physical_memory.hh" 45#include "sim/builder.hh" 46#include "sim/host.hh" 47#include "sim/sim_stats.hh" 48#include "targetarch/vtophys.hh" 49 50using namespace std; 51 52/////////////////////////////////////////////////////////////////////// 53// 54// EtherDev PCI Device 55// 56EtherDev::EtherDev(const string &_name, DmaEngine *de, bool use_interface, 57 IntrControl *i, MemoryController *mmu, PhysicalMemory *pmem, 58 PCIConfigAll *cf, PciConfigData *cd, Tsunami *t, uint32_t bus, 59 uint32_t dev, uint32_t func, bool rx_filter, 60 const int eaddr[6], Tick tx_delay, Tick rx_delay, Addr addr, 61 Addr mask) 62 : PciDev(_name, mmu, cf, cd, bus, dev, func), tsunami(t), 63 addr(addr), mask(mask), txPacketLen(0), 64 txPacketBufPtr(NULL), rxPacketBufPtr(NULL), rxDescBufPtr(NULL), 65 fragLen(0), rxCopied(0), txState(txIdle), CTDD(false), txFifoCnt(0), 66 txFifoAvail(MAX_TX_FIFO_SIZE), txHalt(false), txPacketFlag(false), 67 txFragPtr(0), txDescCnt(0), rxState(rxIdle), CRDD(false), 68 rxPktBytes(0), rxFifoCnt(0), rxHalt(false), rxPacketFlag(false), 69 rxFragPtr(0), rxDescCnt(0), extstsEnable(false), maxTxBurst(0), 70 maxRxBurst(0), physmem(pmem), 71 rxDescDoneCB(this), rxDoneCB(this), txDescDoneCB(this), txDoneCB(this), 72 dma(de), readRequest(use_interface), writeRequest(use_interface), 73 readDescRequest(use_interface), writeDescRequest(use_interface), 74 interface(NULL), intctrl(i), txDelay(tx_delay), rxDelay(rx_delay), 75 txEvent(this), cpuPendingIntr(false), rxFilterEnable(rx_filter), 76 acceptBroadcast(false), acceptMulticast(false), acceptUnicast(false), 77 acceptPerfect(false), acceptArp(false) 78{ 79 tsunami->ethernet = this; 80 81 memset(®s, 0, sizeof(regs)); 82 regsReset(); 83 regs.perfectMatch[0] = eaddr[0]; 84 regs.perfectMatch[1] = eaddr[1]; 85 regs.perfectMatch[2] = eaddr[2]; 86 regs.perfectMatch[3] = eaddr[3]; 87 regs.perfectMatch[4] = eaddr[4]; 88 regs.perfectMatch[5] = eaddr[5]; 89 90} 91 92EtherDev::~EtherDev() 93{} 94 95void 96EtherDev::regStats() 97{ 98 txBytes 99 .name(name() + ".txBytes") 100 .desc("Bytes Transmitted") 101 .prereq(txBytes) 102 ; 103 104 rxBytes 105 .name(name() + ".rxBytes") 106 .desc("Bytes Received") 107 .prereq(rxBytes) 108 ; 109 110 txPackets 111 .name(name() + ".txPackets") 112 .desc("Number of Packets Transmitted") 113 .prereq(txBytes) 114 ; 115 116 rxPackets 117 .name(name() + ".rxPackets") 118 .desc("Number of Packets Received") 119 .prereq(rxBytes) 120 ; 121 122 txBandwidth 123 .name(name() + ".txBandwidth") 124 .desc("Transmit Bandwidth (bits/s)") 125 .precision(0) 126 .prereq(txBytes) 127 ; 128 129 rxBandwidth 130 .name(name() + ".rxBandwidth") 131 .desc("Receive Bandwidth (bits/s)") 132 .precision(0) 133 .prereq(rxBytes) 134 ; 135 136 txPacketRate 137 .name(name() + ".txPPS") 138 .desc("Packet Tranmission Rate (packets/s)") 139 .precision(0) 140 .prereq(txBytes) 141 ; 142 143 rxPacketRate 144 .name(name() + ".rxPPS") 145 .desc("Packet Reception Rate (packets/s)") 146 .precision(0) 147 .prereq(rxBytes) 148 ; 149 150 txBandwidth = txBytes * Statistics::constant(8) / simSeconds; 151 rxBandwidth = rxBytes * Statistics::constant(8) / simSeconds; 152 txPacketRate = txPackets / simSeconds; 153 rxPacketRate = rxPackets / simSeconds; 154} 155 156void 157EtherDev::ReadConfig(int offset, int size, uint8_t *data) 158{ 159 if (offset < PCI_DEVICE_SPECIFIC) 160 PciDev::ReadConfig(offset, size, data); 161 else { 162 panic("need to do this\n"); 163 } 164} 165 166void 167EtherDev::WriteConfig(int offset, int size, uint32_t data) 168{ 169 if (offset < PCI_DEVICE_SPECIFIC) 170 PciDev::WriteConfig(offset, size, data); 171 else 172 panic("Need to do that\n"); 173} 174 175Fault 176EtherDev::read(MemReqPtr req, uint8_t *data) 177{ 178 DPRINTF(Ethernet, "read va=%#x size=%d\n", req->vaddr, req->size); 179 180 Addr daddr = req->paddr - addr; 181 182 if (daddr > LAST) 183 panic("Accessing reserved register"); 184 185 switch (req->size) { 186 case sizeof(uint32_t): 187 { 188 uint32_t ® = *(uint32_t *)data; 189 190 switch (daddr) { 191 case CR: 192 reg = regs.command; 193 reg &= ~(CR_RXD | CR_TXD | CR_TXR | CR_RXR); 194 break; 195 196 case CFG: 197 reg = regs.config; 198 break; 199 200 case MEAR: 201 reg = regs.mear; 202 break; 203 204 case PTSCR: 205 reg = regs.ptscr; 206 break; 207 208 case ISR: 209 reg = regs.isr; 210 regs.isr = 0; 211 break; 212 213 case IMR: 214 reg = regs.imr; 215 break; 216 217 case IER: 218 reg = regs.ier; 219 break; 220 221 case IHR: 222 reg = regs.ihr; 223 break; 224 225 case TXDP: 226 reg = regs.txdp; 227 break; 228 229 case TXDP_HI: 230 reg = regs.txdp_hi; 231 break; 232 233 case TXCFG: 234 reg = regs.txcfg; 235 break; 236 237 case GPIOR: 238 reg = regs.gpior; 239 break; 240 241 case RXDP: 242 reg = regs.rxdp; 243 break; 244 245 case RXDP_HI: 246 reg = regs.rxdp_hi; 247 break; 248 249 case RXCFG: 250 reg = regs.rxcfg; 251 break; 252 253 case PQCR: 254 reg = regs.pqcr; 255 break; 256 257 case WCSR: 258 reg = regs.wcsr; 259 break; 260 261 case PCR: 262 reg = regs.pcr; 263 break; 264 265 case RFCR: 266 reg = regs.rfcr; 267 break; 268 269 case RFDR: 270 271 switch (regs.rfcr & RFCR_RFADDR) { 272 case 0x000: 273 reg = regs.perfectMatch[1] << 8; 274 reg += regs.perfectMatch[0]; 275 break; 276 case 0x002: 277 reg = regs.perfectMatch[3] << 8; 278 reg += regs.perfectMatch[2]; 279 break; 280 case 0x004: 281 reg = regs.perfectMatch[5] << 8; 282 reg += regs.perfectMatch[4]; 283 break; 284 default: 285 panic("reading from RFDR for something for other than PMATCH!\n"); 286 //didn't implement other RFDR functionality b/c driver didn't use 287 } 288 break; 289 290 case SRR: 291 reg = regs.srr; 292 break; 293 294 case MIBC: 295 reg = regs.mibc; 296 reg &= ~(MIBC_MIBS | MIBC_ACLR); 297 break; 298 299 case VRCR: 300 reg = regs.vrcr; 301 break; 302 303 case VTCR: 304 reg = regs.vtcr; 305 break; 306 307 case VDR: 308 reg = regs.vdr; 309 break; 310 311 case CCSR: 312 reg = regs.ccsr; 313 break; 314 315 case TBICR: 316 reg = regs.tbicr; 317 break; 318 319 case TBISR: 320 reg = regs.tbisr; 321 break; 322 323 case TANAR: 324 reg = regs.tanar; 325 break; 326 327 case TANLPAR: 328 reg = regs.tanlpar; 329 break; 330 331 case TANER: 332 reg = regs.taner; 333 break; 334 335 case TESR: 336 reg = regs.tesr; 337 break; 338 339 default: 340 panic("reading unimplemented register: addr = %#x", daddr); 341 } 342 343 DPRINTF(Ethernet, "read from %#x: data=%d data=%#x\n", daddr, reg, reg); 344 } 345 break; 346 347 default: 348 panic("accessing register with invalid size: addr=%#x, size=%d", 349 daddr, req->size); 350 } 351 352 return No_Fault; 353} 354 355Fault 356EtherDev::write(MemReqPtr req, const uint8_t *data) 357{ 358 DPRINTF(Ethernet, "write va=%#x size=%d\n", req->vaddr, req->size); 359 360 Addr daddr = req->paddr - addr; 361 362 if (daddr > LAST && daddr <= RESERVED) 363 panic("Accessing reserved register"); 364 365 if (daddr > RESERVED) 366 panic("higher memory accesses not implemented!\n"); 367 368 if (req->size == sizeof(uint32_t)) { 369 uint32_t reg = *(uint32_t *)data; 370 DPRINTF(Ethernet, "write data=%d data=%#x\n", reg, reg); 371 372 switch (daddr) { 373 case CR: 374 regs.command = reg; 375 if ((reg & (CR_TXE | CR_TXD)) == (CR_TXE | CR_TXD)) { 376 txHalt = true; 377 } else if (reg & CR_TXE) { 378 if (txState == txIdle) 379 txKick(); 380 } else if (reg & CR_TXD) { 381 txHalt = true; 382 } 383 384 if ((reg & (CR_RXE | CR_RXD)) == (CR_RXE | CR_RXD)) { 385 rxHalt = true; 386 } else if (reg & CR_RXE) { 387 if (rxState == rxIdle) { 388 rxKick(); 389 } 390 } else if (reg & CR_RXD) { 391 rxHalt = true; 392 } 393 394 if (reg & CR_TXR) 395 txReset(); 396 397 if (reg & CR_RXR) 398 rxReset(); 399 400 if (reg & CR_SWI) 401 devIntrPost(ISR_SWI); 402 403 if (reg & CR_RST) { 404 txReset(); 405 rxReset(); 406 regsReset(); 407 } 408 break; 409 410 case CFG: 411 regs.config = reg; 412 if (reg & CFG_LNKSTS || reg & CFG_SPDSTS || reg & CFG_DUPSTS 413 || reg & CFG_RESERVED || reg & CFG_T64ADDR 414 || reg & CFG_PCI64_DET) 415 panic("writing to read-only or reserved CFG bits!\n"); 416 417#if 0 418 if (reg & CFG_TBI_EN) ; 419 if (reg & CFG_MODE_1000) ; 420#endif 421 422 if (reg & CFG_AUTO_1000) 423 panic("CFG_AUTO_1000 not implemented!\n"); 424 425#if 0 426 if (reg & CFG_PINT_DUPSTS || reg & CFG_PINT_LNKSTS || reg & CFG_PINT_SPDSTS) ; 427 if (reg & CFG_TMRTEST) ; 428 if (reg & CFG_MRM_DIS) ; 429 if (reg & CFG_MWI_DIS) ; 430#endif 431 432 if (reg & CFG_T64ADDR) 433 panic("CFG_T64ADDR is read only register!\n"); 434 435 if (reg & CFG_PCI64_DET) 436 panic("CFG_PCI64_DET is read only register!\n"); 437 438#if 0 439 if (reg & CFG_DATA64_EN) ; 440 if (reg & CFG_M64ADDR) ; 441 if (reg & CFG_PHY_RST) ; 442 if (reg & CFG_PHY_DIS) ; 443#endif 444 445 if (reg & CFG_EXTSTS_EN) 446 extstsEnable = true; 447 else 448 extstsEnable = false; 449 450#if 0 451 if (reg & CFG_REQALG) ; 452 if (reg & CFG_SB) ; 453 if (reg & CFG_POW) ; 454 if (reg & CFG_EXD) ; 455 if (reg & CFG_PESEL) ; 456 if (reg & CFG_BROM_DIS) ; 457 if (reg & CFG_EXT_125) ; 458 if (reg & CFG_BEM) ; 459#endif 460 break; 461 462 case MEAR: 463 regs.mear = reg; 464 /* since phy is completely faked, MEAR_MD* don't matter 465 and since the driver never uses MEAR_EE*, they don't matter */ 466#if 0 467 if (reg & MEAR_EEDI) ; 468 if (reg & MEAR_EEDO) ; //this one is read only 469 if (reg & MEAR_EECLK) ; 470 if (reg & MEAR_EESEL) ; 471 if (reg & MEAR_MDIO) ; 472 if (reg & MEAR_MDDIR) ; 473 if (reg & MEAR_MDC) ; 474#endif 475 break; 476 477 case PTSCR: 478 regs.ptscr = reg; 479 /* these control BISTs for various parts of chip - we don't care or do */ 480 break; 481 482 case ISR: /* writing to the ISR has no effect */ 483 panic("ISR is a read only register!\n"); 484 485 case IMR: 486 regs.imr = reg; 487 devIntrChangeMask(); 488 break; 489 490 case IER: 491 regs.ier = reg; 492 break; 493 494 case IHR: 495 regs.ihr = reg; 496 /* not going to implement real interrupt holdoff */ 497 break; 498 499 case TXDP: 500 regs.txdp = (reg & 0xFFFFFFFC); 501 assert(txState == txIdle); 502 CTDD = false; 503 break; 504 505 case TXDP_HI: 506 regs.txdp_hi = reg; 507 break; 508 509 case TXCFG: 510 regs.txcfg = reg; 511#if 0 512 if (reg & TXCFG_CSI) ; 513 if (reg & TXCFG_HBI) ; 514 if (reg & TXCFG_MLB) ; 515 if (reg & TXCFG_ATP) ; 516 if (reg & TXCFG_ECRETRY) ; /* this could easily be implemented, but 517 considering the network is just a fake 518 pipe, wouldn't make sense to do this */ 519 520 if (reg & TXCFG_BRST_DIS) ; 521#endif 522 523#if 0 /* current 2.6 driver doesn't use these. if we upgrade, may need these */ 524 if (reg & TXCFG_MXDMA1024) 525 maxTxBurst = 1024; 526 527 if (reg & TXCFG_MXDMA8) 528 maxTxBurst = 8; 529 530 if (reg & TXCFG_MXDMA16) 531 maxTxBurst = 16; 532 533 if (reg & TXCFG_MXDMA32) 534 maxTxBurst = 32; 535 536 if (reg & TXCFG_MXDMA64) 537 maxTxBurst = 64; 538 539 if (reg & TXCFG_MXDMA128) 540 maxTxBurst = 128; 541 542 if (reg & TXCFG_MXDMA256) 543 maxTxBurst = 256; 544#endif 545 546 if (reg & TXCFG_MXDMA512) 547 maxTxBurst = 512; 548 549 break; 550 551 case GPIOR: 552 regs.gpior = reg; 553 /* these just control general purpose i/o pins, don't matter */ 554 break; 555 556 case RXCFG: 557 regs.rxcfg = reg; 558#if 0 559 if (reg & RXCFG_AEP) ; 560 if (reg & RXCFG_ARP) ; 561 if (reg & RXCFG_STRIPCRC) ; 562 if (reg & RXCFG_RX_RD) ; 563 if (reg & RXCFG_ALP) ; 564 if (reg & RXCFG_AIRL) ; 565#endif 566 567 if (reg & RXCFG_MXDMA512) 568 maxRxBurst = 512; 569 570#if 0 571 if (reg & (RXCFG_DRTH | RXCFG_DRTH0)) ; 572#endif 573 break; 574 575 case PQCR: 576 /* there is no priority queueing used in the linux 2.6 driver */ 577 regs.pqcr = reg; 578 break; 579 580 case WCSR: 581 /* not going to implement wake on LAN */ 582 regs.wcsr = reg; 583 break; 584 585 case PCR: 586 /* not going to implement pause control */ 587 regs.pcr = reg; 588 break; 589 590 case RFCR: 591 regs.rfcr = reg; 592 rxFilterEnable = (reg & RFCR_RFEN) ? true : false; 593 594 acceptBroadcast = (reg & RFCR_AAB) ? true : false; 595 596 acceptMulticast = (reg & RFCR_AAM) ? true : false; 597 598 acceptUnicast = (reg & RFCR_AAU) ? true : false; 599 600 acceptPerfect = (reg & RFCR_APM) ? true : false; 601 602 acceptArp = (reg & RFCR_AARP) ? true : false; 603 604 if (reg & RFCR_APAT) 605 panic("RFCR_APAT not implemented!\n"); 606 607 if (reg & RFCR_MHEN || reg & RFCR_UHEN) 608 panic("hash filtering not implemented!\n"); 609 610 if (reg & RFCR_ULM) 611 panic("RFCR_ULM not implemented!\n"); 612 613 break; 614 615 case RFDR: 616 panic("the driver never writes to RFDR, something is wrong!\n"); 617 618 case BRAR: 619 panic("the driver never uses BRAR, something is wrong!\n"); 620 621 case BRDR: 622 panic("the driver never uses BRDR, something is wrong!\n"); 623 624 case SRR: 625 panic("SRR is read only register!\n"); 626 627 case MIBC: 628 panic("the driver never uses MIBC, something is wrong!\n"); 629 630 case VRCR: 631 regs.vrcr = reg; 632 break; 633 634 case VTCR: 635 regs.vtcr = reg; 636 break; 637 638 case VDR: 639 panic("the driver never uses VDR, something is wrong!\n"); 640 break; 641 642 case CCSR: 643 /* not going to implement clockrun stuff */ 644 regs.ccsr = reg; 645 break; 646 647 case TBICR: 648 regs.tbicr = reg; 649 if (reg & TBICR_MR_LOOPBACK) 650 panic("TBICR_MR_LOOPBACK never used, something wrong!\n"); 651 652 if (reg & TBICR_MR_AN_ENABLE) { 653 regs.tanlpar = regs.tanar; 654 regs.tbisr |= (TBISR_MR_AN_COMPLETE | TBISR_MR_LINK_STATUS); 655 } 656 657#if 0 658 if (reg & TBICR_MR_RESTART_AN) ; 659#endif 660 661 break; 662 663 case TBISR: 664 panic("TBISR is read only register!\n"); 665 666 case TANAR: 667 regs.tanar = reg; 668 if (reg & TANAR_PS2) 669 panic("this isn't used in driver, something wrong!\n"); 670 671 if (reg & TANAR_PS1) 672 panic("this isn't used in driver, something wrong!\n"); 673 break; 674 675 case TANLPAR: 676 panic("this should only be written to by the fake phy!\n"); 677 678 case TANER: 679 panic("TANER is read only register!\n"); 680 681 case TESR: 682 regs.tesr = reg; 683 break; 684 685 default: 686 panic("thought i covered all the register, what is this? addr=%#x", 687 daddr); 688 } 689 } else 690 panic("Invalid Request Size"); 691 692 return No_Fault; 693} 694 695void 696EtherDev::devIntrPost(uint32_t interrupts) 697{ 698DPRINTF(Ethernet, "interrupt posted intr=%x isr=%x imr=%x\n", 699 interrupts, regs.isr, regs.imr); 700 701if (interrupts & ISR_RESERVE) 702 panic("Cannot set a reserved interrupt"); 703 704if (interrupts & ISR_TXRCMP) 705 regs.isr |= ISR_TXRCMP; 706 707if (interrupts & ISR_RXRCMP) 708 regs.isr |= ISR_RXRCMP; 709 710//ISR_DPERR not implemented 711//ISR_SSERR not implemented 712//ISR_RMABT not implemented 713//ISR_RXSOVR not implemented 714//ISR_HIBINT not implemented 715//ISR_PHY not implemented 716//ISR_PME not implemented 717 718if (interrupts & ISR_SWI) 719 regs.isr |= ISR_SWI; 720 721//ISR_MIB not implemented 722//ISR_TXURN not implemented 723 724 if (interrupts & ISR_TXIDLE) 725 regs.isr |= ISR_TXIDLE; 726 727 if (interrupts & ISR_TXERR) 728 regs.isr |= ISR_TXERR; 729 730 if (interrupts & ISR_TXDESC) 731 regs.isr |= ISR_TXDESC; 732 733 if (interrupts & ISR_TXOK) 734 regs.isr |= ISR_TXOK; 735 736 if (interrupts & ISR_RXORN) 737 regs.isr |= ISR_RXORN; 738 739 if (interrupts & ISR_RXIDLE) 740 regs.isr |= ISR_RXIDLE; 741 742//ISR_RXEARLY not implemented 743 744 if (interrupts & ISR_RXERR) 745 regs.isr |= ISR_RXERR; 746 747 if (interrupts & ISR_RXOK) 748 regs.isr |= ISR_RXOK; 749 750 if ((regs.isr & regs.imr)) 751 cpuIntrPost(); 752} 753 754void 755EtherDev::devIntrClear(uint32_t interrupts) 756{ 757 DPRINTF(Ethernet, "interrupt cleared intr=%x isr=%x imr=%x\n", 758 interrupts, regs.isr, regs.imr); 759 760 if (interrupts & ISR_RESERVE) 761 panic("Cannot clear a reserved interrupt"); 762 763 if (interrupts & ISR_TXRCMP) 764 regs.isr &= ~ISR_TXRCMP; 765 766 if (interrupts & ISR_RXRCMP) 767 regs.isr &= ~ISR_RXRCMP; 768 769//ISR_DPERR not implemented 770//ISR_SSERR not implemented 771//ISR_RMABT not implemented 772//ISR_RXSOVR not implemented 773//ISR_HIBINT not implemented 774//ISR_PHY not implemented 775//ISR_PME not implemented 776 777 if (interrupts & ISR_SWI) 778 regs.isr &= ~ISR_SWI; 779 780//ISR_MIB not implemented 781//ISR_TXURN not implemented 782 783 if (interrupts & ISR_TXIDLE) 784 regs.isr &= ~ISR_TXIDLE; 785 786 if (interrupts & ISR_TXERR) 787 regs.isr &= ~ISR_TXERR; 788 789 if (interrupts & ISR_TXDESC) 790 regs.isr &= ~ISR_TXDESC; 791 792 if (interrupts & ISR_TXOK) 793 regs.isr &= ~ISR_TXOK; 794 795 if (interrupts & ISR_RXORN) 796 regs.isr &= ~ISR_RXORN; 797 798 if (interrupts & ISR_RXIDLE) 799 regs.isr &= ~ISR_RXIDLE; 800 801//ISR_RXEARLY not implemented 802 803 if (interrupts & ISR_RXERR) 804 regs.isr &= ~ISR_RXERR; 805 806 if (interrupts & ISR_RXOK) 807 regs.isr &= ~ISR_RXOK; 808 809 if ((regs.isr & regs.imr)) 810 cpuIntrPost(); 811 812 if (!(regs.isr & regs.imr)) 813 cpuIntrClear(); 814} 815 816void 817EtherDev::devIntrChangeMask() 818{ 819 DPRINTF(Ethernet, "iterrupt mask changed\n"); 820 821 if (regs.isr & regs.imr) 822 cpuIntrPost(); 823 else 824 cpuIntrClear(); 825} 826 827void 828EtherDev::cpuIntrPost() 829{ 830 if (!cpuPendingIntr) { 831 if (regs.ier) { 832 cpuPendingIntr = true; 833 intctrl->post(TheISA::INTLEVEL_IRQ1, TheISA::INTINDEX_ETHERNET); 834 } 835 } 836} 837 838void 839EtherDev::cpuIntrClear() 840{ 841 if (cpuPendingIntr) { 842 cpuPendingIntr = false; 843 intctrl->clear(TheISA::INTLEVEL_IRQ1, TheISA::INTINDEX_ETHERNET); 844 } 845} 846 847bool 848EtherDev::cpuIntrPending() const 849{ return cpuPendingIntr; } 850 851void 852EtherDev::txReset() 853{ 854 855 DPRINTF(Ethernet, "transmit reset\n"); 856 857 txPacketFlag = false; 858 CTDD = false; 859 txFifoCnt = 0; 860 txFifoAvail = 0; 861 txHalt = false; 862 txFifo.clear(); 863 descAddrFifo.clear(); 864 regs.command &= ~CR_TXE; 865 txState = txIdle; 866} 867 868void 869EtherDev::rxReset() 870{ 871 DPRINTF(Ethernet, "receive reset\n"); 872 873 rxPacketFlag = false; 874 CRDD = false; 875 fragLen = 0; 876 rxFifoCnt = 0; 877 rxHalt = false; 878 rxFifo.clear(); 879 regs.command &= ~CR_RXE; 880 rxState = rxIdle; 881} 882 883/** 884 * This sets up a DMA transfer to read one data segment from the rxFifo into 885 * the buffer indicated by rxDescCache.bufptr. Assumes the value of rxFragPtr 886 * is already correctly set. 887 */ 888void 889EtherDev::writeOneFrag() 890{ 891 /* i think there is no need for an "in use" warning here like in old */ 892 fragLen = rxFifo.front()->length; //length of whole packet 893 fragLen = (fragLen < rxDescCnt) ? fragLen : rxDescCnt; 894 895 writePhys.addr = rxFragPtr; 896 writePhys.length = fragLen; 897 898 // Set up DMA request area 899 writeRequest.init(&rxDoneCB, 0, false, &writePhys, 1, fragLen, 900 rxDescBufPtr, fragLen, curTick); 901 902 dma->doTransfer(&readRequest); 903} 904 905void 906EtherDev::rxKick() 907{ 908 DPRINTF(Ethernet, "receive state machine activated!\n"); 909 910 if (CRDD) { 911 rxState = rxDescRefr; 912 readOneDesc(rx, LINK_LEN); 913 } else { 914 rxState = rxDescRead; 915 readOneDesc(rx); 916 } 917} 918 919EtherDev::RxDescDone::RxDescDone(EtherDev *e) 920 : ethernet(e) 921{ 922} 923 924std::string 925EtherDev::RxDescDone::name() const 926{ 927 return ethernet->name() + ".rxDescDoneCB"; 928} 929 930void 931EtherDev::RxDescDone::process() 932{ 933 DPRINTF(Ethernet, "receive descriptor done callback\n"); 934 ethernet->rxDescDone(); 935} 936 937void 938EtherDev::rxDescDone() 939{ 940 if (rxState == rxDescRefr) { 941 if (rxDescCache.link == 0) { 942 rxState = rxIdle; 943 regs.command &= ~CR_RXE; 944 devIntrPost(ISR_RXIDLE); 945 return; 946 } else { 947 rxState = rxDescRead; 948 regs.rxdp = rxDescCache.link; 949 CRDD = false; 950 readOneDesc(rx); 951 } 952 } else if (rxState == rxDescRead) { 953 if (rxDescCache.cmdsts & CMDSTS_OWN) { 954 rxState = rxIdle; 955 regs.command &= ~CR_RXE; 956 devIntrPost(ISR_RXIDLE); 957 } else { 958 rxState = rxFifoBlock; 959 rxFragPtr = rxDescCache.bufptr; 960 rxDescCnt = rxDescCache.cmdsts & CMDSTS_LEN_MASK; 961 962 if (!rxFifo.empty()) { 963 rxState = rxFragWrite; 964 if (!rxPacketFlag) { // reading a new packet 965 rxPacketBufPtr = rxFifo.front()->data; 966 rxPacketBufPtr -= rxDescCnt; 967 rxDescBufPtr = rxPacketBufPtr; 968 rxCopied = 0; 969 } else { 970 rxDescBufPtr = rxPacketBufPtr - rxDescCnt; 971 } 972 writeOneFrag(); 973 } 974 } 975 } else if (rxState == rxDescWrite) { 976 devIntrPost(ISR_RXOK); 977 978 if (rxDescCache.cmdsts & CMDSTS_INTR) 979 devIntrPost(ISR_RXDESC); 980 981 if (rxDescCache.link == 0 || ((rxPktBytes != 0) && rxHalt)) { 982 rxState = rxIdle; 983 regs.command &= ~CR_RXE; 984 devIntrPost(ISR_RXIDLE); 985 rxHalt = false; 986 } else { 987 rxState = rxDescRead; 988 regs.rxdp = rxDescCache.link; 989 CRDD = false; 990 readOneDesc(rx); 991 } 992 } 993} 994 995EtherDev::RxDone::RxDone(EtherDev *e) 996 : ethernet(e) 997{ 998} 999 1000std::string 1001EtherDev::RxDone::name() const 1002{ 1003 return ethernet->name() + ".rxDoneCB"; 1004} 1005 1006void 1007EtherDev::RxDone::process() 1008{ 1009 DPRINTF(Ethernet, "receive done callback\n"); 1010 ethernet->rxDone(); 1011} 1012 1013void 1014EtherDev::rxDone() 1015{ 1016 DPRINTF(Ethernet, "packet received to host memory\n"); 1017 1018 if (!rxDescCache.cmdsts & CMDSTS_OWN) 1019 panic("This descriptor is already owned by the driver!\n"); 1020 1021 rxState = rxFifoBlock; 1022 rxCopied += fragLen; 1023 rxFifoCnt -= fragLen; 1024 1025 if (rxDescCnt) { /* there is still data left in the descriptor */ 1026 rxState = rxFragWrite; 1027 rxDescBufPtr += fragLen; 1028 writeOneFrag(); 1029 } else { 1030 rxState = rxDescWrite; 1031 if (rxPktBytes == 0) { /* packet is done */ 1032 rxDescCache.cmdsts |= CMDSTS_OWN; 1033 rxDescCache.cmdsts &= ~CMDSTS_MORE; 1034 rxDescCache.cmdsts |= CMDSTS_OK; 1035 rxDescCache.cmdsts += rxCopied; //i.e. set CMDSTS_SIZE 1036 1037 rxPacketFlag = false; 1038 if (rxFilterEnable) { 1039 rxDescCache.cmdsts &= ~CMDSTS_DEST_MASK; 1040 if (rxFifo.front()->IsUnicast()) 1041 rxDescCache.cmdsts |= CMDSTS_DEST_SELF; 1042 if (rxFifo.front()->IsMulticast()) 1043 rxDescCache.cmdsts |= CMDSTS_DEST_MULTI; 1044 if (rxFifo.front()->IsBroadcast()) 1045 rxDescCache.cmdsts |= CMDSTS_DEST_MASK; 1046 } 1047 1048 PacketPtr &pkt = rxFifo.front(); 1049 eth_header *eth = (eth_header *) pkt->data; 1050 if (eth->type == 0x800 && extstsEnable) { 1051 rxDescCache.extsts |= EXTSTS_IPPKT; 1052 if (!ipChecksum(pkt, false)) 1053 rxDescCache.extsts |= EXTSTS_IPERR; 1054 ip_header *ip = rxFifo.front()->getIpHdr(); 1055 1056 if (ip->protocol == 6) { 1057 rxDescCache.extsts |= EXTSTS_TCPPKT; 1058 if (!tcpChecksum(pkt, false)) 1059 rxDescCache.extsts |= EXTSTS_TCPERR; 1060 } else if (ip->protocol == 17) { 1061 rxDescCache.extsts |= EXTSTS_UDPPKT; 1062 if (!udpChecksum(pkt, false)) 1063 rxDescCache.extsts |= EXTSTS_UDPERR; 1064 } 1065 } 1066 1067 rxFifo.front() = NULL; 1068 rxFifo.pop_front(); 1069 } else { /* just the descriptor is done */ 1070 rxDescCache.cmdsts |= CMDSTS_OWN; 1071 rxDescCache.cmdsts |= CMDSTS_MORE; 1072 } 1073 writeDescPhys.addr = regs.rxdp + LINK_LEN + BUFPTR_LEN; 1074 writeDescPhys.length = CMDSTS_LEN; 1075 1076 writeDescRequest.init(&rxDescDoneCB, 0, true, &writeDescPhys, 1, 1077 CMDSTS_LEN, (uint8_t *) &rxDescCache.cmdsts, 1078 CMDSTS_LEN, curTick); 1079 } 1080} 1081 1082/** 1083 * This sets up a DMA transfer to read one descriptor into the network device. 1084 */ 1085void 1086EtherDev::readOneDesc(dir_t dir, uint32_t len) { 1087 readDescPhys.addr = (dir == tx) ? regs.txdp : regs.rxdp; 1088 readDescPhys.length = len; 1089 1090 ns_desc *cache = (dir == tx) ? &txDescCache : &rxDescCache; 1091 1092 /* THIS ASSUMES THAT DESC_LEN < regs.txcfg's maxdma value, 1093 which is 512 bytes in the driver, so i'll just hard code it here */ 1094 readDescRequest.init(&txDescDoneCB, 0, false, &readDescPhys, 1, 1095 len, (uint8_t *) cache , len, curTick); 1096 1097 dma->doTransfer(&readDescRequest); 1098} 1099 1100/** 1101 * This sets up a DMA transfer to read one data segment of the descriptor in 1102 * txDescCache. Assumes the value of txFragPtr is already correctly set 1103 */ 1104void 1105EtherDev::readOneFrag() 1106{ 1107 /* i think there is no need for an "in use" warning here like in old */ 1108 fragLen = (txDescCnt < txFifoAvail) ? txDescCnt : txFifoAvail; 1109 readPhys.addr = txFragPtr; 1110 readPhys.length = fragLen; 1111 1112 // Set up DMA request area 1113 readRequest.init(&txDoneCB, 0, false, &readPhys, 1, fragLen, 1114 txPacketBufPtr, fragLen, curTick); 1115 1116 dma->doTransfer(&readRequest); 1117} 1118 1119void 1120EtherDev::transmit() 1121{ 1122 if (txFifo.empty()) { 1123 DPRINTF(Ethernet, "nothing to transmit\n"); 1124 return; 1125 } 1126 1127 if (interface->sendPacket(txFifo.front())) { 1128 DPRINTF(Ethernet, "transmit packet\n"); 1129 txBytes += txFifo.front()->length; 1130 txPackets++; 1131 1132 txFifoCnt -= txFifo.front()->length; 1133 1134 txFifo.front() = NULL; 1135 txFifo.pop_front(); 1136 1137 txDescCache.cmdsts &= ~CMDSTS_OK; 1138 } else { 1139 txDescCache.cmdsts &= ~CMDSTS_ERR; 1140 } 1141 1142 txDescCache.cmdsts &= ~CMDSTS_OWN; 1143 1144 writeDescPhys.addr = descAddrFifo.front() + LINK_LEN + BUFPTR_LEN; 1145 writeDescPhys.length = CMDSTS_LEN; 1146 1147 descAddrFifo.front() = 0; 1148 descAddrFifo.pop_front(); 1149 1150 writeDescRequest.init(&txDescDoneCB, 0, true, &writeDescPhys, 1, 1151 writeDescPhys.length, 1152 (uint8_t *) &(txDescCache.cmdsts), 1153 writeDescPhys.length, curTick); 1154 1155 dma->doTransfer(&writeDescRequest); 1156 1157 transmit(); 1158} 1159 1160void 1161EtherDev::txKick() 1162{ 1163 DPRINTF(Ethernet, "transmit state machine activated\n"); 1164#if 0 1165 if (DTRACE(Ethernet)) 1166 txDump(); 1167#endif 1168 1169 if (CTDD) { 1170 txState = txDescRefr; 1171 readOneDesc(tx, LINK_LEN); 1172 } else { 1173 txState = txDescRead; 1174 readOneDesc(tx); 1175 } 1176} 1177 1178EtherDev::TxDescDone::TxDescDone(EtherDev *e) 1179 : ethernet(e) 1180{ 1181} 1182 1183std::string 1184EtherDev::TxDescDone::name() const 1185{ 1186 return ethernet->name() + ".txDescDoneCB"; 1187} 1188 1189void 1190EtherDev::TxDescDone::process() 1191{ 1192 DPRINTF(Ethernet, "transmit descriptor done callback\n"); 1193 ethernet->txDescDone(); 1194 1195} 1196 1197void 1198EtherDev::txDescDone() 1199{ 1200 if (txState == txFifoBlock) { 1201 if (txDescCache.cmdsts & CMDSTS_OK) { 1202 devIntrPost(ISR_TXOK); 1203 } else if (txDescCache.cmdsts & CMDSTS_ERR) { 1204 devIntrPost(ISR_TXERR); 1205 } 1206 } else if (txState == txDescRefr || txState == txDescWrite) { 1207 1208 if (txState == txDescWrite) { 1209 if (txDescCache.cmdsts & CMDSTS_INTR) { 1210 devIntrPost(ISR_TXDESC); 1211 } 1212 } 1213 1214 if (txDescCache.link == 0) { 1215 txState = txIdle; 1216 regs.command &= ~CR_TXE; 1217 devIntrPost(ISR_TXIDLE); 1218 return; 1219 } else { 1220 txState = txDescRead; 1221 regs.txdp = txDescCache.link; 1222 CTDD = false; 1223 readOneDesc(tx); 1224 } 1225 } else if (txState == txDescRead) { 1226 if (txDescCache.cmdsts & CMDSTS_OWN) { 1227 txState = txFifoBlock; 1228 txFragPtr = txDescCache.bufptr; 1229 txDescCnt = txDescCache.cmdsts & CMDSTS_LEN_MASK; 1230 1231 if (txFifoAvail >= ((regs.txcfg & TXCFG_FLTH_MASK) >> 8)) { 1232 txState = txFragRead; 1233 if (!txPacketFlag) { 1234 txPacketFlag = true; 1235 /* find the total length of this packet */ 1236 txPacketLen = txDescCnt; 1237 bool more = txDescCache.cmdsts & CMDSTS_MORE; 1238 uint8_t *addr = (uint8_t *) regs.txdp; 1239 while (more) { 1240 addr = physmem->dma_addr(((ns_desc *) addr)->link, sizeof(ns_desc)); 1241 /* !!!!!!mask needed? */ 1242 txPacketLen += ((ns_desc *)addr)->cmdsts & CMDSTS_LEN_MASK; 1243 more = ((ns_desc *) addr)->cmdsts & CMDSTS_MORE; 1244 } 1245 PacketPtr &packet = txDoneCB.packet; 1246 packet = new EtherPacket; 1247 packet->length = txPacketLen; 1248 packet->data = new uint8_t[txPacketLen]; 1249 txPacketBufPtr = packet->data; 1250 } 1251 readOneFrag(); 1252 } 1253 } else { 1254 txState = txIdle; 1255 regs.command &= ~CR_TXE; 1256 devIntrPost(ISR_TXIDLE); 1257 } 1258 } 1259} 1260 1261EtherDev::TxDone::TxDone(EtherDev *e) 1262 : ethernet(e) 1263{ 1264} 1265 1266std::string 1267EtherDev::TxDone::name() const 1268{ 1269 return ethernet->name() + ".txDoneCB"; 1270} 1271 1272 1273void 1274EtherDev::TxDone::process() 1275{ 1276 DPRINTF(Ethernet, "transmit done callback\n"); 1277 ethernet->txDone(packet); 1278} 1279 1280void 1281EtherDev::txDone(PacketPtr packet) 1282{ 1283 DPRINTF(Ethernet, "transmit done\n"); 1284 1285 if (!txDescCache.cmdsts & CMDSTS_OWN) 1286 panic("This descriptor is already owned by the driver!\n"); 1287 1288 txState = txFifoBlock; 1289 1290 txPacketBufPtr += fragLen; /* hope this ptr manipulation is right! */ 1291 txDescCnt -= fragLen; 1292 txFifoCnt += fragLen; 1293 1294 if (txFifoCnt >= (regs.txcfg & TXCFG_DRTH_MASK)) { 1295 if (txFifo.empty()) { 1296 txFifoCnt -= (uint32_t) (txPacketBufPtr - packet->data); 1297 } else { 1298 transmit(); 1299 } 1300 } 1301 1302 if (txDescCnt) { /* if there is still more data to go in this desc */ 1303 if (txFifoAvail >= regs.txcfg & TXCFG_FLTH_MASK) { 1304 txState = txFragRead; 1305 readOneFrag(); 1306 } 1307 } else { /* this descriptor is done */ 1308 /* but there is more descriptors for this packet */ 1309 if (txDescCache.cmdsts & CMDSTS_MORE) { 1310 txState = txDescWrite; 1311 txDescCache.cmdsts &= ~CMDSTS_OWN; 1312 writeDescPhys.addr = regs.txdp + LINK_LEN + BUFPTR_LEN; 1313 writeDescPhys.length = CMDSTS_LEN; 1314 1315 writeDescRequest.init(&txDescDoneCB, 0, true, &writeDescPhys, 1, 1316 writeDescPhys.length, 1317 (uint8_t*) &txDescCache.cmdsts, 1318 writeDescPhys.length, curTick); 1319 } else { /* this packet is totally done */ 1320 /* deal with the the packet that just finished */ 1321 if (regs.vtcr & VTCR_PPCHK && extstsEnable) { 1322 if (txDescCache.extsts & EXTSTS_UDPPKT) { 1323 udpChecksum(packet, true); 1324 } else if (txDescCache.extsts & EXTSTS_TCPPKT) { 1325 tcpChecksum(packet, true); 1326 } else if (txDescCache.extsts & EXTSTS_IPPKT) { 1327 ipChecksum(packet, true); 1328 } 1329 } 1330 1331 txFifo.push_back(packet); 1332 transmit(); 1333 txPacketFlag = false; 1334 descAddrFifo.push_back(regs.txdp); 1335 1336 /* if there is not another descriptor ready for reading, go idle */ 1337 if (txDescCache.link == 0 || txHalt) { 1338 txState = txIdle; 1339 devIntrPost(ISR_TXIDLE); 1340 txHalt = false; 1341 } else { /* else go read next descriptor */ 1342 txState = txDescRead; 1343 regs.txdp = txDescCache.link; 1344 CTDD = false; 1345 readOneDesc(tx); 1346 } 1347 } 1348 } 1349} 1350 1351void 1352EtherDev::transferDone() 1353{ 1354 if (txFifo.empty()) 1355 return; 1356 1357 DPRINTF(Ethernet, "schedule transmit\n"); 1358 1359 if (txEvent.scheduled()) 1360 txEvent.reschedule(curTick + 1); 1361 else 1362 txEvent.schedule(curTick + 1); 1363} 1364 1365void 1366EtherDev::txDump() const 1367{ 1368#if 0 1369 int i = tx_ptr; 1370 for (int loop = 0; loop < tx_ring_len; loop++) { 1371 es_desc *desc = &tx_ring[i]; 1372 1373 if (desc->addr) 1374 cprintf("desc[%d]: addr=%#x, len=%d, flags=%#x\n", 1375 i, desc->addr, desc->length, desc->flags); 1376 1377 if (++i >= tx_ring_len) 1378 i = 0; 1379 } 1380#endif 1381} 1382 1383void 1384EtherDev::rxDump() const 1385{ 1386#if 0 1387 int i = rx_ptr; 1388 for (int loop = 0; loop < rx_ring_len; loop++) { 1389 es_desc *desc = &rx_ring[i]; 1390 1391 if (desc->addr) 1392 cprintf("desc[%d]: addr=%#x, len=%d, flags=%#x\n", 1393 i, desc->addr, desc->length, desc->flags); 1394 1395 if (++i >= rx_ring_len) 1396 i = 0; 1397 } 1398#endif 1399} 1400 1401bool 1402EtherDev::rxFilter(PacketPtr packet) 1403{ 1404 bool drop = true; 1405 string type; 1406 1407 if (packet->IsUnicast()) { 1408 type = "unicast"; 1409 1410 // If we're accepting all unicast addresses 1411 if (acceptUnicast) 1412 drop = false; 1413 1414 // If we make a perfect match 1415 if ((acceptPerfect) 1416 && (memcmp(regs.perfectMatch, packet->data, sizeof(regs.perfectMatch)) == 0)) 1417 drop = false; 1418 1419 eth_header *eth = (eth_header *) packet->data; 1420 if ((acceptArp) && (eth->type == 0x806)) 1421 drop = false; 1422 1423 } else if (packet->IsBroadcast()) { 1424 type = "broadcast"; 1425 1426 // if we're accepting broadcasts 1427 if (acceptBroadcast) 1428 drop = false; 1429 1430 } else if (packet->IsMulticast()) { 1431 type = "multicast"; 1432 1433 // if we're accepting all multicasts 1434 if (acceptMulticast) 1435 drop = false; 1436 1437 } else { 1438 type = "unknown"; 1439 1440 // oh well, punt on this one 1441 } 1442 1443 if (drop) { 1444 DPRINTF(Ethernet, "rxFilter drop\n"); 1445 DDUMP(EthernetData, packet->data, packet->length); 1446 } 1447 1448 return drop; 1449} 1450 1451bool 1452EtherDev::recvPacket(PacketPtr packet) 1453{ 1454 rxBytes += packet->length; 1455 rxPackets++; 1456 1457 if (rxState == rxIdle) { 1458 DPRINTF(Ethernet, "receive disabled...packet dropped\n"); 1459 interface->recvDone(); 1460 return true; 1461 } 1462 1463 if (rxFilterEnable && rxFilter(packet)) { 1464 DPRINTF(Ethernet, "packet filtered...dropped\n"); 1465 interface->recvDone(); 1466 return true; 1467 } 1468 1469 if (rxFifoCnt + packet->length >= MAX_RX_FIFO_SIZE) { 1470 DPRINTF(Ethernet, 1471 "packet will not fit in receive buffer...packet dropped\n"); 1472 devIntrPost(ISR_RXORN); 1473 return false; 1474 } 1475 1476 rxFifo.push_back(packet); 1477 rxPktBytes = packet->length; 1478 rxFifoCnt += packet->length; 1479 interface->recvDone(); 1480 1481 return true; 1482} 1483 1484bool 1485EtherDev::udpChecksum(PacketPtr packet, bool gen) 1486{ 1487 udp_header *hdr = (udp_header *) packet->getTransportHdr(); 1488 1489 ip_header *ip = packet->getIpHdr(); 1490 1491 pseudo_header *pseudo = new pseudo_header; 1492 1493 pseudo->src_ip_addr = ip->src_ip_addr; 1494 pseudo->dest_ip_addr = ip->dest_ip_addr; 1495 pseudo->protocol = ip->protocol; 1496 pseudo->len = hdr->len; 1497 1498 uint16_t cksum = checksumCalc((uint16_t *) pseudo, (uint16_t *) hdr, 1499 (uint32_t) hdr->len); 1500 1501 delete pseudo; 1502 if (gen) 1503 hdr->chksum = cksum; 1504 else 1505 if (cksum != 0) 1506 return false; 1507 1508 return true; 1509} 1510 1511bool 1512EtherDev::tcpChecksum(PacketPtr packet, bool gen) 1513{ 1514 tcp_header *hdr = (tcp_header *) packet->getTransportHdr(); 1515 1516 ip_header *ip = packet->getIpHdr(); 1517 1518 pseudo_header *pseudo = new pseudo_header; 1519 1520 pseudo->src_ip_addr = ip->src_ip_addr; 1521 pseudo->dest_ip_addr = ip->dest_ip_addr; 1522 pseudo->protocol = ip->protocol; 1523 pseudo->len = ip->dgram_len - (ip->vers_len & 0xf); 1524 1525 uint16_t cksum = checksumCalc((uint16_t *) pseudo, (uint16_t *) hdr, 1526 (uint32_t) pseudo->len); 1527 1528 delete pseudo; 1529 if (gen) 1530 hdr->chksum = cksum; 1531 else 1532 if (cksum != 0) 1533 return false; 1534 1535 return true; 1536} 1537 1538bool 1539EtherDev::ipChecksum(PacketPtr packet, bool gen) 1540{ 1541 ip_header *hdr = packet->getIpHdr(); 1542 1543 uint16_t cksum = checksumCalc(NULL, (uint16_t *) hdr, (hdr->vers_len & 0xf)); 1544 1545 if (gen) 1546 hdr->hdr_chksum = cksum; 1547 else 1548 if (cksum != 0) 1549 return false; 1550 1551 return true; 1552} 1553 1554uint16_t 1555EtherDev::checksumCalc(uint16_t *pseudo, uint16_t *buf, uint32_t len) 1556{ 1557 uint32_t sum = 0; 1558 1559 uint16_t last_pad = 0; 1560 if (len & 1) { 1561 last_pad = buf[len/2] & 0xff; 1562 len--; 1563 sum += last_pad; 1564 } 1565 1566 if (pseudo) { 1567 sum = pseudo[0] + pseudo[1] + pseudo[2] + 1568 pseudo[3] + pseudo[4] + pseudo[5]; 1569 } 1570 1571 for (int i=0; i < (len/2); ++i) { 1572 sum += buf[i]; 1573 } 1574 1575 while (sum >> 16) 1576 sum = (sum >> 16) + (sum & 0xffff); 1577 1578 return ~sum; 1579} 1580 1581//===================================================================== 1582// 1583// 1584void 1585dp_regs::serialize(ostream &os) 1586{ 1587 SERIALIZE_SCALAR(command); 1588 SERIALIZE_SCALAR(config); 1589 SERIALIZE_SCALAR(isr); 1590 SERIALIZE_SCALAR(imr); 1591} 1592 1593void 1594dp_regs::unserialize(Checkpoint *cp, const std::string §ion) 1595{ 1596 UNSERIALIZE_SCALAR(command); 1597 UNSERIALIZE_SCALAR(config); 1598 UNSERIALIZE_SCALAR(isr); 1599 UNSERIALIZE_SCALAR(imr); 1600#if 0 1601 UNSERIALIZE_SCALAR(tx_ring); 1602 UNSERIALIZE_SCALAR(rx_ring); 1603 UNSERIALIZE_SCALAR(tx_ring_len); 1604 UNSERIALIZE_SCALAR(rx_ring_len); 1605 UNSERIALIZE_SCALAR(rom_addr); 1606 UNSERIALIZE_SCALAR(rom_data); 1607 UNSERIALIZE_SCALAR(rxfilt_ctl); 1608 UNSERIALIZE_SCALAR(rxfilt_data); 1609 1610 UNSERIALIZE_ARRAY(perfect,EADDR_LEN); 1611 UNSERIALIZE_ARRAY(hash_table,ES_HASH_SIZE); 1612 1613 UNSERIALIZE_SCALAR(tx_ring_ptr); 1614 UNSERIALIZE_SCALAR(rx_ring_ptr); 1615#endif 1616} 1617 1618//--------------------------------------- 1619 1620void 1621EtherPacket::serialize(ostream &os) 1622{ 1623 SERIALIZE_SCALAR(length); 1624 SERIALIZE_ARRAY(data, length); 1625} 1626 1627void 1628EtherPacket::unserialize(Checkpoint *cp, const std::string §ion) 1629{ 1630 UNSERIALIZE_SCALAR(length); 1631 data = new uint8_t[length]; 1632 UNSERIALIZE_ARRAY(data, length); 1633} 1634 1635//--------------------------------------- 1636 1637void 1638EtherDev::serialize(ostream &os) 1639{ 1640 1641#if 0 1642 regs.serialize(os); 1643 1644 // tx_ring & rx_ring are contained in the physmem... 1645 SERIALIZE_SCALAR(cpuPendingIntr); 1646 SERIALIZE_SCALAR(tx_ptr); 1647 SERIALIZE_SCALAR(rx_ptr); 1648 1649 SERIALIZE_SCALAR(rxDoneCB.ptr); 1650 SERIALIZE_SCALAR(rxDoneCB.ignore); 1651 1652 SERIALIZE_SCALAR(txDoneCB.ptr); 1653 SERIALIZE_SCALAR(txDoneCB.ignore); 1654 1655 for (int i=0; i<ES_MAX_DMA_SEGS; ++i) { 1656 paramOut(os, csprintf("readPhys%d.addr",i), readPhys[i].addr); 1657 paramOut(os, csprintf("readPhys%d.length",i), readPhys[i].length); 1658 paramOut(os, csprintf("writePhys%d.addr",i), writePhys[i].addr); 1659 paramOut(os, csprintf("writePhys%d.length",i), writePhys[i].length); 1660 } 1661 1662 SERIALIZE_SCALAR(txEnable); 1663 SERIALIZE_SCALAR(rxEnable); 1664 SERIALIZE_SCALAR(txDelay); 1665 SERIALIZE_SCALAR(rxDelay); 1666 1667 SERIALIZE_SCALAR(txbuf_len); 1668 1669 //Calculate the number here, actually dump them at end 1670 int numTxPkts=0; 1671 for (pktiter_t p=txbuf.begin(); p!=txbuf.end(); ++p) { 1672 numTxPkts++; 1673 } 1674 SERIALIZE_SCALAR(numTxPkts); 1675 1676 SERIALIZE_SCALAR(rxbuf_len); 1677 int numRxPkts=0; 1678 for (pktiter_t p=rxbuf.begin(); p!=rxbuf.end(); ++p) { 1679 numRxPkts++; 1680 } 1681 SERIALIZE_SCALAR(numRxPkts); 1682 1683 // output whether the tx and rx packets exist 1684 bool txPacketExists = false; 1685 if (txDoneCB.packet) 1686 txPacketExists = true; 1687 SERIALIZE_SCALAR(txPacketExists); 1688 1689 bool rxPacketExists = false; 1690 if (rxPacket) 1691 rxPacketExists = true; 1692 SERIALIZE_SCALAR(rxPacketExists); 1693 1694 // output the names (unique by pointer) of the read and write requests 1695 paramOut(os, csprintf("readReqName"), readRequest.name()); 1696 paramOut(os, csprintf("writeReqName"), writeRequest.name()); 1697 1698 // Serialize txPacket, because its data is needed for readRequest 1699 if (txPacketExists) { 1700 nameOut(os, csprintf("%s.txPacket", name())); 1701 txDoneCB.packet->serialize(os); 1702 } 1703 1704 // Serialize rxPacket, because its data is needed for writeRequest 1705 if (rxPacketExists) { 1706 nameOut(os, csprintf("%s.rxPacket", name())); 1707 rxPacket->serialize(os); 1708 } 1709 1710 // create a section for the readRequest 1711 nameOut(os, readRequest.name()); 1712 paramOut(os, csprintf("parent"), name()); 1713 paramOut(os, csprintf("id"), 0); 1714 readRequest.serialize(os); 1715 1716 // create a section for the writeRequest 1717 nameOut(os, writeRequest.name()); 1718 paramOut(os, csprintf("parent"), name()); 1719 paramOut(os, csprintf("id"), 1); 1720 writeRequest.serialize(os); 1721 1722 //Redo the buffers, this time outputing them to the file 1723 numTxPkts = 0; 1724 for (pktiter_t p=txbuf.begin(); p!=txbuf.end(); ++p) { 1725 nameOut(os, csprintf("%s.txbuf%d", name(),numTxPkts++)); 1726 (*p)->serialize(os); 1727 } 1728 1729 numRxPkts = 0; 1730 for (pktiter_t p=rxbuf.begin(); p!=rxbuf.end(); ++p) { 1731 nameOut(os, csprintf("%s.rxbuf%d", name(),numRxPkts++)); 1732 (*p)->serialize(os); 1733 } 1734#endif 1735} 1736 1737void 1738EtherDev::unserialize(Checkpoint *cp, const std::string §ion) 1739{ 1740#if 0 1741 regs.unserialize(cp, section); 1742 1743 UNSERIALIZE_SCALAR(cpuPendingIntr); 1744 1745 // initialize the tx_ring 1746 txReset(); 1747 1748 // initialize the rx_ring 1749 rxReset(); 1750 1751 UNSERIALIZE_SCALAR(tx_ptr); 1752 UNSERIALIZE_SCALAR(rx_ptr); 1753 1754 PacketPtr p; 1755 UNSERIALIZE_SCALAR(txbuf_len); 1756 int numTxPkts; 1757 UNSERIALIZE_SCALAR(numTxPkts); 1758 for (int i=0; i<numTxPkts; ++i) { 1759 p = new EtherPacket; 1760 p->unserialize(cp, csprintf("%s.txbuf%d", section, i)); 1761 txbuf.push_back(p); 1762 } 1763 1764 UNSERIALIZE_SCALAR(rxbuf_len); 1765 int numRxPkts; 1766 UNSERIALIZE_SCALAR(numRxPkts); 1767 for (int i=0; i<numRxPkts; ++i) { 1768 p = new EtherPacket; 1769 p->unserialize(cp, csprintf("%s.rxbuf%d", section, i)); 1770 rxbuf.push_back(p); 1771 } 1772 1773 UNSERIALIZE_SCALAR(rxDoneCB.ptr); 1774 UNSERIALIZE_SCALAR(rxDoneCB.ignore); 1775 1776 UNSERIALIZE_SCALAR(txDoneCB.ptr); 1777 UNSERIALIZE_SCALAR(txDoneCB.ignore); 1778 1779 for (int i=0; i<ES_MAX_DMA_SEGS; ++i) { 1780 paramIn(cp, section, csprintf("readPhys%d.addr",i), 1781 readPhys[i].addr); 1782 paramIn(cp, section, csprintf("readPhys%d.length",i), 1783 readPhys[i].length); 1784 paramIn(cp, section, csprintf("writePhys%d.addr",i), 1785 writePhys[i].addr); 1786 paramIn(cp, section, csprintf("writePhys%d.length",i), 1787 writePhys[i].length); 1788 } 1789 1790 UNSERIALIZE_SCALAR(txEnable); 1791 UNSERIALIZE_SCALAR(rxEnable); 1792 UNSERIALIZE_SCALAR(txDelay); 1793 UNSERIALIZE_SCALAR(rxDelay); 1794 1795 // Unserialize the current txPacket 1796 bool txPacketExists; 1797 UNSERIALIZE_SCALAR(txPacketExists); 1798 1799 txDoneCB.packet = NULL; 1800 if (txPacketExists) { 1801 txDoneCB.packet = new EtherPacket; 1802 txDoneCB.packet->unserialize(cp, csprintf("%s.txPacket", section)); 1803 } 1804 1805 // Unserialize the current rxPacket 1806 bool rxPacketExists; 1807 UNSERIALIZE_SCALAR(rxPacketExists); 1808 1809 rxPacket = NULL; 1810 if (rxPacketExists) { 1811 rxPacket = new EtherPacket; 1812 rxPacket->unserialize(cp, csprintf("%s.rxPacket", section)); 1813 } 1814 1815 std::string readReqName, writeReqName; 1816 UNSERIALIZE_SCALAR(readReqName); 1817 UNSERIALIZE_SCALAR(writeReqName); 1818 1819 // Unserialize and fixup the readRequest 1820 readRequest.unserialize(cp, readReqName); 1821 readRequest.phys = readPhys; 1822 readRequest.bufferCB = 0; 1823 readRequest.dmaDoneCB = &txDoneCB; 1824 readRequest.data = NULL; 1825 1826 if (txDoneCB.packet) 1827 readRequest.data = txDoneCB.packet->data; 1828 1829 // Unserialize and fixup the writeRequest 1830 writeRequest.unserialize(cp, writeReqName); 1831 writeRequest.phys = writePhys; 1832 writeRequest.bufferCB = 0; 1833 writeRequest.dmaDoneCB = &rxDoneCB; 1834 writeRequest.data = NULL; 1835 1836 if (rxPacket) 1837 writeRequest.data = rxPacket->data; 1838#endif 1839} 1840 1841 1842//===================================================================== 1843 1844 1845BEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherDevInt) 1846 1847 SimObjectParam<EtherInt *> peer; 1848 SimObjectParam<EtherDev *> device; 1849 1850END_DECLARE_SIM_OBJECT_PARAMS(EtherDevInt) 1851 1852BEGIN_INIT_SIM_OBJECT_PARAMS(EtherDevInt) 1853 1854 INIT_PARAM_DFLT(peer, "peer interface", NULL), 1855 INIT_PARAM(device, "Ethernet device of this interface") 1856 1857END_INIT_SIM_OBJECT_PARAMS(EtherDevInt) 1858 1859CREATE_SIM_OBJECT(EtherDevInt) 1860{ 1861 EtherDevInt *dev_int = new EtherDevInt(getInstanceName(), device); 1862 1863 EtherInt *p = (EtherInt *)peer; 1864 if (p) { 1865 dev_int->setPeer(p); 1866 p->setPeer(dev_int); 1867 } 1868 1869 return dev_int; 1870} 1871 1872REGISTER_SIM_OBJECT("EtherDevInt", EtherDevInt) 1873 1874 1875BEGIN_DECLARE_SIM_OBJECT_PARAMS(EtherDev) 1876 1877 Param<Tick> tx_delay; 1878 Param<Tick> rx_delay; 1879 SimObjectParam<DmaEngine *> engine; 1880 Param<bool> use_interface; 1881 SimObjectParam<IntrControl *> intr_ctrl; 1882 SimObjectParam<MemoryController *> mmu; 1883 SimObjectParam<PhysicalMemory *> physmem; 1884 Param<Addr> addr; 1885 Param<Addr> mask; 1886 Param<bool> rx_filter; 1887 Param<string> hardware_address; 1888 SimObjectParam<PCIConfigAll *> configspace; 1889 SimObjectParam<PciConfigData *> configdata; 1890 SimObjectParam<Tsunami *> tsunami; 1891 Param<uint32_t> pci_bus; 1892 Param<uint32_t> pci_dev; 1893 Param<uint32_t> pci_func; 1894 1895END_DECLARE_SIM_OBJECT_PARAMS(EtherDev) 1896 1897BEGIN_INIT_SIM_OBJECT_PARAMS(EtherDev) 1898 1899 INIT_PARAM_DFLT(tx_delay, "Transmit Delay", 1000), 1900 INIT_PARAM_DFLT(rx_delay, "Receive Delay", 1000), 1901 INIT_PARAM(engine, "DMA Engine"), 1902 INIT_PARAM_DFLT(use_interface, "Use DMA Interface", true), 1903 INIT_PARAM(intr_ctrl, "Interrupt Controller"), 1904 INIT_PARAM(mmu, "Memory Controller"), 1905 INIT_PARAM(physmem, "Physical Memory"), 1906 INIT_PARAM(addr, "Device Address"), 1907 INIT_PARAM(mask, "Address Mask"), 1908 INIT_PARAM_DFLT(rx_filter, "Enable Receive Filter", true), 1909 INIT_PARAM_DFLT(hardware_address, "Ethernet Hardware Address", 1910 "00:99:00:00:00:01"), 1911 INIT_PARAM(configspace, "PCI Configspace"), 1912 INIT_PARAM(configdata, "PCI Config data"), 1913 INIT_PARAM(tsunami, "Tsunami"), 1914 INIT_PARAM(pci_bus, "PCI bus"), 1915 INIT_PARAM(pci_dev, "PCI device number"), 1916 INIT_PARAM(pci_func, "PCI function code") 1917 1918END_INIT_SIM_OBJECT_PARAMS(EtherDev) 1919 1920 1921CREATE_SIM_OBJECT(EtherDev) 1922{ 1923 int eaddr[6]; 1924 sscanf(((string)hardware_address).c_str(), "%x:%x:%x:%x:%x:%x", 1925 &eaddr[0], &eaddr[1], &eaddr[2], &eaddr[3], &eaddr[4], &eaddr[5]); 1926 1927 return new EtherDev(getInstanceName(), engine, use_interface, 1928 intr_ctrl, mmu, physmem, configspace, configdata, 1929 tsunami, pci_bus, pci_dev, pci_func, rx_filter, eaddr, 1930 tx_delay, rx_delay, addr, mask); 1931} 1932 1933REGISTER_SIM_OBJECT("EtherDev", EtherDev) 1934