|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * Copyright (c) 1998-1999 Apple Computer ! 24: * ! 25: * Implementation for hardware dependent (relatively) code ! 26: * for the Sun GEM Ethernet controller. ! 27: * ! 28: * HISTORY ! 29: * ! 30: * 10-Sept-97 ! 31: * Created. ! 32: * ! 33: */ ! 34: #include "UniNEnetPrivate.h" ! 35: ! 36: extern void *kernel_pmap; ! 37: ! 38: /* ! 39: * Private functions ! 40: */ ! 41: bool UniNEnet::allocateMemory() ! 42: { ! 43: UInt32 rxRingSize, txRingSize; ! 44: UInt32 i, n; ! 45: UInt8 *virtAddr; ! 46: UInt32 physBase; ! 47: UInt32 physAddr; ! 48: TxQueueElement *txElement; ! 49: ! 50: /* ! 51: * Calculate total space for DMA channel commands ! 52: */ ! 53: txRingSize = (TX_RING_LENGTH * sizeof(enet_txdma_cmd_t) + 2048 - 1) & ~(2048-1); ! 54: rxRingSize = (RX_RING_LENGTH * sizeof(enet_dma_cmd_t) + 2048 - 1) & ~(2048-1); ! 55: ! 56: dmaCommandsSize = round_page( txRingSize + rxRingSize ); ! 57: /* ! 58: * Allocate required memory ! 59: */ ! 60: if ( !dmaCommands ) ! 61: { ! 62: dmaCommands = (UInt8 *)IOMallocContiguous( dmaCommandsSize, PAGE_SIZE, 0 ); ! 63: ! 64: if ( dmaCommands == 0 ) ! 65: { ! 66: IOLog( "Ethernet(UniN): Cant allocate channel dma commands\n\r" ); ! 67: return false; ! 68: } ! 69: } ! 70: ! 71: /* ! 72: * If we needed more than one page, then make sure we received contiguous memory. ! 73: */ ! 74: n = (dmaCommandsSize - PAGE_SIZE) / PAGE_SIZE; ! 75: physBase = pmap_extract(kernel_pmap, (vm_address_t) dmaCommands); ! 76: ! 77: virtAddr = (UInt8 *) dmaCommands; ! 78: for( i=0; i < n; i++, virtAddr += PAGE_SIZE ) ! 79: { ! 80: physAddr = pmap_extract(kernel_pmap, (vm_address_t) virtAddr); ! 81: if (physAddr != (physBase + i * PAGE_SIZE) ) ! 82: { ! 83: IOLog( "Ethernet(UniN): Cant allocate contiguous memory for dma commands\n\r" ); ! 84: return false; ! 85: } ! 86: } ! 87: ! 88: /* ! 89: * Setup the receive ring pointers ! 90: */ ! 91: rxDMACommands = (enet_dma_cmd_t *)dmaCommands; ! 92: rxMaxCommand = RX_RING_LENGTH; ! 93: ! 94: /* ! 95: * Setup the transmit ring pointers ! 96: */ ! 97: txDMACommands = (enet_txdma_cmd_t *)(dmaCommands + rxRingSize); ! 98: txMaxCommand = TX_RING_LENGTH; ! 99: ! 100: ! 101: queue_init( &txActiveQueue ); ! 102: queue_init( &txFreeQueue ); ! 103: ! 104: for ( i=0; i < TX_MAX_MBUFS; i++ ) ! 105: { ! 106: txElement = (TxQueueElement *)IOMalloc( sizeof(TxQueueElement) ); ! 107: if ( txElement == 0 ) ! 108: { ! 109: return false; ! 110: } ! 111: ! 112: bzero( txElement, sizeof(TxQueueElement) ); ! 113: ! 114: releaseTxElement( txElement ); ! 115: } ! 116: ! 117: return true; ! 118: } ! 119: ! 120: /*------------------------------------------------------------------------- ! 121: * ! 122: * Setup the Transmit Ring ! 123: * ----------------------- ! 124: * Each transmit ring entry consists of two words to transmit data from buffer ! 125: * segments (possibly) spanning a page boundary. This is followed by two DMA commands ! 126: * which read transmit frame status and interrupt status from the UniN chip. The last ! 127: * DMA command in each transmit ring entry generates a host interrupt. ! 128: * The last entry in the ring is followed by a DMA branch to the first ! 129: * entry. ! 130: *-------------------------------------------------------------------------*/ ! 131: ! 132: bool UniNEnet::initTxRing() ! 133: { ! 134: TxQueueElement *txElement; ! 135: UInt32 i; ! 136: ! 137: /* ! 138: * Clear the transmit DMA command memory ! 139: */ ! 140: bzero( (void *)txDMACommands, sizeof(enet_txdma_cmd_t) * txMaxCommand); ! 141: txCommandHead = 0; ! 142: txCommandTail = 0; ! 143: ! 144: ! 145: txDMACommandsPhys = pmap_extract(kernel_pmap, (vm_address_t) txDMACommands); ! 146: ! 147: if ( txDMACommandsPhys == 0 ) ! 148: { ! 149: IOLog( "Ethernet(UniN): Bad dma command buf - %08x\n\r", (int)txDMACommands ); ! 150: } ! 151: ! 152: for ( i=0; i < TX_RING_LENGTH; i++ ) ! 153: { ! 154: txElement = txElementPtrs[i]; ! 155: ! 156: if ( (txElement != 0) && (txElement->list != &txFreeQueue) ) ! 157: { ! 158: if ( txElement->mbuf != 0 ) ! 159: { ! 160: freePacket( txElement->mbuf ); ! 161: } ! 162: bzero( txElement, sizeof(TxQueueElement) ); ! 163: releaseTxElement( txElement ); ! 164: } ! 165: ! 166: txElementPtrs[i] = 0; ! 167: } ! 168: ! 169: txCommandsAvail = txMaxCommand - 1; ! 170: ! 171: return true; ! 172: } ! 173: ! 174: /*------------------------------------------------------------------------- ! 175: * ! 176: * Setup the Receive ring ! 177: * ---------------------- ! 178: * Each receive ring entry consists of two DMA commands to receive data ! 179: * into a network buffer (possibly) spanning a page boundary. The second ! 180: * DMA command in each entry generates a host interrupt. ! 181: * The last entry in the ring is followed by a DMA branch to the first ! 182: * entry. ! 183: * ! 184: *-------------------------------------------------------------------------*/ ! 185: ! 186: bool UniNEnet::initRxRing() ! 187: { ! 188: UInt32 i; ! 189: bool status; ! 190: ! 191: /* ! 192: * Clear the receive DMA command memory ! 193: */ ! 194: bzero( (void *)rxDMACommands, sizeof(enet_dma_cmd_t) * rxMaxCommand); ! 195: ! 196: rxDMACommandsPhys = pmap_extract(kernel_pmap, (vm_address_t) rxDMACommands); ! 197: if ( rxDMACommandsPhys == 0 ) ! 198: { ! 199: IOLog( "Ethernet(UniN): Bad dma command buf - %08x\n\r", (int)rxDMACommands ); ! 200: return false; ! 201: } ! 202: ! 203: /* ! 204: * Allocate a receive buffer for each entry in the Receive ring ! 205: */ ! 206: for (i = 0; i < rxMaxCommand; i++) ! 207: { ! 208: if (rxMbuf[i] == NULL) ! 209: { ! 210: rxMbuf[i] = allocatePacket(NETWORK_BUFSIZE); ! 211: if (rxMbuf[i] == NULL) ! 212: { ! 213: IOLog("Ethernet(UniN): allocateMbuf returned NULL in _initRxRing\n\r"); ! 214: return false; ! 215: } ! 216: } ! 217: ! 218: /* ! 219: * Set the DMA commands for the ring entry to transfer data to the Mbuf. ! 220: */ ! 221: status = updateDescriptorFromMbuf(rxMbuf[i], &rxDMACommands[i], true); ! 222: if (status == false) ! 223: { ! 224: IOLog("Ethernet(UniN): cant map mbuf to physical memory in initRxRing\n\r"); ! 225: return false; ! 226: } ! 227: } ! 228: ! 229: /* ! 230: * Set the receive queue head to point to the first entry in the ring. Set the ! 231: * receive queue tail to point to a DMA Stop command after the last ring entry ! 232: */ ! 233: i-=4; ! 234: rxCommandHead = 0; ! 235: rxCommandTail = i; ! 236: ! 237: return true; ! 238: } ! 239: ! 240: /*------------------------------------------------------------------------- ! 241: * ! 242: * ! 243: * ! 244: *-------------------------------------------------------------------------*/ ! 245: ! 246: void UniNEnet::startChip() ! 247: { ! 248: UInt32 gemReg; ! 249: ! 250: // dumpRegisters(); ! 251: ! 252: gemReg = ReadUniNRegister( ioBaseEnet, kGEMTxConfig ); ! 253: gemReg |= kGEMTxConfig_TxDMAEnable; ! 254: WriteUniNRegister( ioBaseEnet, kGEMTxConfig, gemReg ); ! 255: ! 256: IOSleep(20); ! 257: ! 258: gemReg = ReadUniNRegister( ioBaseEnet, kGEMRxConfig ); ! 259: gemReg |= kGEMRxConfig_RxDMAEnable; ! 260: WriteUniNRegister( ioBaseEnet, kGEMRxConfig, gemReg ); ! 261: ! 262: IOSleep(20); ! 263: ! 264: gemReg = ReadUniNRegister( ioBaseEnet, kGEMMacTxMacConfig ); ! 265: gemReg |= kGEMMacTxMacConfig_TxMacEnable; ! 266: WriteUniNRegister( ioBaseEnet, kGEMMacTxMacConfig, gemReg ); ! 267: ! 268: IOSleep(20); ! 269: ! 270: gemReg = ReadUniNRegister( ioBaseEnet, kGEMMacRxMacConfig ); ! 271: gemReg |= kGEMMacRxMacConfig_RxMacEnable; ! 272: WriteUniNRegister( ioBaseEnet, kGEMMacRxMacConfig, gemReg ); ! 273: ! 274: // dumpRegisters(); ! 275: ! 276: } ! 277: ! 278: /*------------------------------------------------------------------------- ! 279: * ! 280: * ! 281: * ! 282: *-------------------------------------------------------------------------*/ ! 283: ! 284: void UniNEnet::stopChip() ! 285: { ! 286: UInt32 gemReg; ! 287: ! 288: gemReg = ReadUniNRegister( ioBaseEnet, kGEMTxConfig ); ! 289: gemReg &= ~kGEMTxConfig_TxDMAEnable; ! 290: WriteUniNRegister( ioBaseEnet, kGEMTxConfig, gemReg ); ! 291: ! 292: IOSleep(20); ! 293: ! 294: gemReg = ReadUniNRegister( ioBaseEnet, kGEMRxConfig ); ! 295: gemReg &= ~kGEMRxConfig_RxDMAEnable; ! 296: WriteUniNRegister( ioBaseEnet, kGEMRxConfig, gemReg ); ! 297: ! 298: IOSleep(20); ! 299: ! 300: gemReg = ReadUniNRegister( ioBaseEnet, kGEMMacTxMacConfig ); ! 301: gemReg &= ~kGEMMacTxMacConfig_TxMacEnable; ! 302: WriteUniNRegister( ioBaseEnet, kGEMMacTxMacConfig, gemReg ); ! 303: ! 304: IOSleep(20); ! 305: ! 306: gemReg = ReadUniNRegister( ioBaseEnet, kGEMMacRxMacConfig ); ! 307: gemReg &= ~kGEMMacRxMacConfig_RxMacEnable; ! 308: WriteUniNRegister( ioBaseEnet, kGEMMacRxMacConfig, gemReg ); ! 309: } ! 310: ! 311: ! 312: ! 313: /*------------------------------------------------------------------------- ! 314: * ! 315: * ! 316: * ! 317: *-------------------------------------------------------------------------*/ ! 318: ! 319: bool UniNEnet::resetChip() ! 320: { ! 321: UInt8 resetReg; ! 322: UInt16 *pPhyType; ! 323: UInt16 phyWord; ! 324: ! 325: ! 326: WriteUniNRegister( ioBaseEnet, kGEMSoftwareReset, kGEMSoftwareReset_TxReset | kGEMSoftwareReset_RxReset ); ! 327: ! 328: do ! 329: { ! 330: resetReg = ReadUniNRegister( ioBaseEnet, kGEMSoftwareReset ); ! 331: } ! 332: while( resetReg & (kGEMSoftwareReset_TxReset | kGEMSoftwareReset_RxReset) ); ! 333: ! 334: /* ! 335: * Determine if PHY chip is configured. Reset and enable it (if present). ! 336: */ ! 337: if ( phyId == 0xff ) ! 338: { ! 339: if ( miiFindPHY(&phyId) == true ) ! 340: { ! 341: miiResetPHY( phyId ); ! 342: ! 343: pPhyType = (UInt16 *)&phyType; ! 344: miiReadWord( pPhyType, MII_ID0, phyId ); ! 345: miiReadWord( pPhyType+1, MII_ID1, phyId ); ! 346: ! 347: if ( (phyType & MII_BCM5400_MASK) == MII_BCM5400_ID ) ! 348: { ! 349: miiReadWord( &phyWord, MII_BCM5400_AUXCONTROL, phyId ); ! 350: phyWord |= MII_BCM5400_AUXCONTROL_PWR10BASET; ! 351: miiWriteWord( phyWord, MII_BCM5400_AUXCONTROL, phyId ); ! 352: ! 353: miiReadWord( &phyWord, MII_BCM5400_1000BASETCONTROL, phyId ); ! 354: phyWord |= MII_BCM5400_1000BASETCONTROL_FULLDUPLEXCAP; ! 355: miiWriteWord( phyWord, MII_BCM5400_1000BASETCONTROL, phyId ); ! 356: ! 357: IODelay(100); ! 358: ! 359: miiResetPHY( 0x1F ); ! 360: ! 361: miiReadWord( &phyWord, MII_BCM5201_MULTIPHY, 0x1F ); ! 362: phyWord |= MII_BCM5201_MULTIPHY_SERIALMODE; ! 363: miiWriteWord( phyWord, MII_BCM5201_MULTIPHY, 0x1F ); ! 364: ! 365: miiReadWord( &phyWord, MII_BCM5400_AUXCONTROL, phyId ); ! 366: phyWord &= ~MII_BCM5400_AUXCONTROL_PWR10BASET; ! 367: miiWriteWord( phyWord, MII_BCM5400_AUXCONTROL, phyId ); ! 368: ! 369: } ! 370: } ! 371: } ! 372: ! 373: return true; ! 374: } ! 375: ! 376: /*------------------------------------------------------------------------- ! 377: * ! 378: * ! 379: * ! 380: *-------------------------------------------------------------------------*/ ! 381: ! 382: bool UniNEnet::initChip() ! 383: { ! 384: UInt32 i, j; ! 385: mach_timespec_t timeStamp; ! 386: UInt32 rxFifoSize; ! 387: UInt32 rxOff; ! 388: UInt32 rxOn; ! 389: u_int16_t *p16; ! 390: ! 391: if ( phyId == 0xff ) ! 392: { ! 393: WriteUniNRegister( ioBaseEnet, kGEMPCSDatapathMode, kGEMPCSDatapathMode_ExtSERDESMode ); ! 394: ! 395: WriteUniNRegister( ioBaseEnet, kGEMPCSSerdesControl, kGEMPCSSerdesControl_DisableLoopback | ! 396: kGEMPCSSerdesControl_EnableSyncDet ); ! 397: ! 398: WriteUniNRegister( ioBaseEnet, kGEMPCSAdvert, kGEMPCSAdvert_FullDuplexCap | ! 399: kGEMPCSAdvert_SymPauseCap ); ! 400: ! 401: WriteUniNRegister( ioBaseEnet, kGEMPCSControl, kGEMPCSControl_EnableAutoNegot | ! 402: kGEMPCSControl_RestartAutoNegot ); ! 403: ! 404: WriteUniNRegister( ioBaseEnet, kGEMPCSConfig, kGEMPCSConfig_Enable ); ! 405: ! 406: WriteUniNRegister( ioBaseEnet, kGEMMacXIFConfig, kGEMMacXIFConfig_TxMIIOutputEnable | ! 407: kGEMMacXIFConfig_GMIIMode | ! 408: kGEMMacXIFConfig_FullDuplexLed ); ! 409: } ! 410: else ! 411: { ! 412: WriteUniNRegister( ioBaseEnet, kGEMPCSDatapathMode, kGEMPCSDatapathMode_GMIIMode ); ! 413: ! 414: WriteUniNRegister( ioBaseEnet, kGEMMacXIFConfig, kGEMMacXIFConfig_TxMIIOutputEnable | ! 415: kGEMMacXIFConfig_FullDuplexLed ); ! 416: } ! 417: ! 418: WriteUniNRegister( ioBaseEnet, kGEMMacSendPauseCmd, kGEMMacSendPauseCmd_Bit * kGEMMacSendPauseCmd_Default ); ! 419: ! 420: WriteUniNRegister( ioBaseEnet, kGEMMacControlConfig, kGEMMacControlConfig_ReceivePauseEnable ); ! 421: ! 422: WriteUniNRegister( ioBaseEnet, kGEMInterruptMask, 0xffffffff ); ! 423: ! 424: WriteUniNRegister( ioBaseEnet, kGEMMacTxMask, kGEMMacTxMaskDefault ); ! 425: ! 426: WriteUniNRegister( ioBaseEnet, kGEMMacRxMask, kGEMMacRxMaskDefault ); ! 427: ! 428: WriteUniNRegister( ioBaseEnet, kGEMMacControlMask, kGEMMacControlMaskDefault ); ! 429: ! 430: WriteUniNRegister( ioBaseEnet, kGEMConfig, 31*kGEMConfig_TxDMALimitBit | ! 431: 31*kGEMConfig_RxDMALimitBit | ! 432: kGEMConfig_InfiniteBurst); ! 433: ! 434: WriteUniNRegister( ioBaseEnet, kGEMMacInterPktGap0, kGEMMacInterPktGap0_Default ); ! 435: WriteUniNRegister( ioBaseEnet, kGEMMacInterPktGap1, kGEMMacInterPktGap1_Default ); ! 436: WriteUniNRegister( ioBaseEnet, kGEMMacInterPktGap2, kGEMMacInterPktGap2_Default ); ! 437: ! 438: WriteUniNRegister( ioBaseEnet, kGEMMacSlotTime, kGEMMacSlotTime_Default ); ! 439: ! 440: WriteUniNRegister( ioBaseEnet, kGEMMacMinFrameSize, kGEMMacMinFrameSize_Default ); ! 441: WriteUniNRegister( ioBaseEnet, kGEMMacMaxFrameSize, kGEMMacMaxFrameSize_Default ); ! 442: ! 443: WriteUniNRegister( ioBaseEnet, kGEMMacPASize, kGEMMacPASize_Default ); ! 444: ! 445: WriteUniNRegister( ioBaseEnet, kGEMMacJamSize, kGEMMacJamSize_Default ); ! 446: ! 447: WriteUniNRegister( ioBaseEnet, kGEMMacAttemptLimit, kGEMMacAttemptLimit_Default ); ! 448: ! 449: WriteUniNRegister( ioBaseEnet, kGEMMacTypeControl, kGEMMacTypeControl_Default ); ! 450: ! 451: /* ! 452: * ! 453: */ ! 454: p16 = (u_int16_t *) myAddress.ea_byte; ! 455: for ( i=0; i < sizeof(enet_addr_t) / 2; i++ ) ! 456: { ! 457: WriteUniNRegister( ioBaseEnet, kGEMMacAddr + i * 4, p16[2-i] ); ! 458: } ! 459: ! 460: for ( i=0; i < 3; i ++ ) ! 461: { ! 462: WriteUniNRegister( ioBaseEnet, kGEMMacAddr + (i+3) * 4, 0 ); ! 463: WriteUniNRegister( ioBaseEnet, kGEMMacAddrFilter + (i+0) * 4, 0 ); ! 464: } ! 465: ! 466: WriteUniNRegister( ioBaseEnet, kGEMMacAddr + (6*4), kGEMMacAddr6_Default ); ! 467: WriteUniNRegister( ioBaseEnet, kGEMMacAddr + (7*4), kGEMMacAddr7_Default ); ! 468: WriteUniNRegister( ioBaseEnet, kGEMMacAddr + (8*4), kGEMMacAddr8_Default ); ! 469: ! 470: WriteUniNRegister( ioBaseEnet, kGEMMacAddrFilterMask1, 0 ); ! 471: WriteUniNRegister( ioBaseEnet, kGEMMacAddrFilterMask0, 0 ); ! 472: ! 473: for ( i=0; i < 16; i++ ) ! 474: { ! 475: WriteUniNRegister( ioBaseEnet, kGEMMacHashTable + i * 4, 0 ); ! 476: } ! 477: ! 478: /* ! 479: * ! 480: */ ! 481: for ( i = kGEMMacCollisions; i <= kGEMMacRxCodeErrors; i+=4 ); ! 482: { ! 483: WriteUniNRegister( ioBaseEnet, i, 0 ); ! 484: } ! 485: ! 486: IOGetTime(&timeStamp); ! 487: WriteUniNRegister( ioBaseEnet, kGEMMacRandomSeed, (u_int16_t) timeStamp.tv_nsec ); ! 488: ! 489: /* ! 490: * ! 491: */ ! 492: WriteUniNRegister( ioBaseEnet, kGEMTxDescBaseLo, txDMACommandsPhys ); ! 493: WriteUniNRegister( ioBaseEnet, kGEMTxDescBaseHi, 0 ); ! 494: ! 495: for ( i=0, j=TX_RING_LENGTH / kGEMTxConfig_TxRingSizeMin - 1; ! 496: (i < 13) && j; ! 497: i++, j >>= 1 ) ! 498: ; ! 499: ! 500: WriteUniNRegister( ioBaseEnet, kGEMTxConfig, (i * kGEMTxConfig_TxDescRingSizeBit) | ! 501: (kGEMTxConfig_TxFIFOThresholdDefault * kGEMTxConfig_TxFIFOThresholdBit) ); ! 502: ! 503: WriteUniNRegister( ioBaseEnet, kGEMMacTxMacConfig, 0 ); ! 504: ! 505: setDuplexMode( (phyId == 0xff) ? true : false ); ! 506: ! 507: /* ! 508: * ! 509: */ ! 510: WriteUniNRegister( ioBaseEnet, kGEMRxDescBaseLo, rxDMACommandsPhys ); ! 511: WriteUniNRegister( ioBaseEnet, kGEMRxDescBaseHi, 0 ); ! 512: ! 513: WriteUniNRegister( ioBaseEnet, kGEMRxKick, RX_RING_LENGTH-4 ); ! 514: ! 515: for ( i=0, j=RX_RING_LENGTH / kGEMRxConfig_RxRingSizeMin - 1; ! 516: (i < 13) && j; ! 517: i++, j >>= 1 ) ! 518: ; ! 519: ! 520: WriteUniNRegister( ioBaseEnet, kGEMRxConfig, (i * kGEMRxConfig_RxDescRingSizeBit) | ! 521: (kGEMRxConfig_RxDMAThresholdDefault * kGEMRxConfig_RxDMAThresholdBit) ! 522: ); ! 523: ! 524: WriteUniNRegister( ioBaseEnet, kGEMMacRxMacConfig, 0 ); ! 525: ! 526: rxFifoSize = ReadUniNRegister( ioBaseEnet, kGEMRxFIFOSize ); ! 527: ! 528: rxOff = rxFifoSize - ((kGEMMacMaxFrameSize_Aligned + 8) * 2 / kGEMRxPauseThresholds_Units); ! 529: rxOn = rxFifoSize - ((kGEMMacMaxFrameSize_Aligned + 8) * 3 / kGEMRxPauseThresholds_Units); ! 530: ! 531: WriteUniNRegister( ioBaseEnet, kGEMRxPauseThresholds, (rxOff * kGEMRxPauseThresholds_OffBit) | ! 532: (rxOn * kGEMRxPauseThresholds_OnBit) ); ! 533: ! 534: i = (ReadUniNRegister(ioBaseEnet, kGEMBIFConfig) & kGEMBIFConfig_66Mhz) ? PCI_PERIOD_66MHz : PCI_PERIOD_33MHz; ! 535: i = (RX_INT_LATENCY_uS * 1000) / (2048 * i); ! 536: ! 537: WriteUniNRegister( ioBaseEnet, kGEMRxIntBlanking, i*kGEMRxIntBlanking_TimeBit | 5*kGEMRxIntBlanking_NumPktBit ); ! 538: ! 539: return true; ! 540: } ! 541: ! 542: /*------------------------------------------------------------------------- ! 543: * ! 544: * ! 545: * ! 546: *-------------------------------------------------------------------------*/ ! 547: ! 548: void UniNEnet::disableAdapterInterrupts() ! 549: { ! 550: ! 551: WriteUniNRegister( ioBaseEnet, kGEMInterruptMask, 0xffffffff ); ! 552: } ! 553: ! 554: /*------------------------------------------------------------------------- ! 555: * ! 556: * ! 557: * ! 558: *-------------------------------------------------------------------------*/ ! 559: ! 560: void UniNEnet::enableAdapterInterrupts() ! 561: { ! 562: UInt32 gemReg; ! 563: ! 564: gemReg = ReadUniNRegister( ioBaseEnet, kGEMInterruptMask ); ! 565: gemReg &= ~(kGEMInterruptMask_TxInt | kGEMInterruptMask_RxDone | kGEMInterruptStatus_RxMacInt); ! 566: WriteUniNRegister( ioBaseEnet, kGEMInterruptMask, gemReg ); ! 567: } ! 568: ! 569: /*------------------------------------------------------------------------- ! 570: * ! 571: * ! 572: * ! 573: *-------------------------------------------------------------------------*/ ! 574: ! 575: void UniNEnet::setDuplexMode( bool duplexMode ) ! 576: { ! 577: UInt16 txMacConfig; ! 578: UInt16 xifConfig; ! 579: ! 580: isFullDuplex = duplexMode; ! 581: ! 582: txMacConfig = ReadUniNRegister( ioBaseEnet, kGEMMacTxMacConfig ); ! 583: ! 584: WriteUniNRegister( ioBaseEnet, kGEMMacTxMacConfig, txMacConfig & ~kGEMMacTxMacConfig_TxMacEnable ); ! 585: while( ReadUniNRegister(ioBaseEnet, kGEMMacTxMacConfig) & kGEMMacTxMacConfig_TxMacEnable ) ! 586: ; ! 587: ! 588: xifConfig = ReadUniNRegister( ioBaseEnet, kGEMMacXIFConfig ); ! 589: ! 590: if ( isFullDuplex ) ! 591: { ! 592: txMacConfig |= (kGEMMacTxMacConfig_IgnoreCollsn | kGEMMacTxMacConfig_IgnoreCarrierSense); ! 593: xifConfig &= ~kGEMMacXIFConfig_DisableEcho; ! 594: } ! 595: else ! 596: { ! 597: txMacConfig &= ~(kGEMMacTxMacConfig_IgnoreCollsn | kGEMMacTxMacConfig_IgnoreCarrierSense); ! 598: xifConfig |= kGEMMacXIFConfig_DisableEcho; ! 599: } ! 600: ! 601: WriteUniNRegister( ioBaseEnet, kGEMMacTxMacConfig, txMacConfig ); ! 602: WriteUniNRegister( ioBaseEnet, kGEMMacXIFConfig, xifConfig ); ! 603: } ! 604: ! 605: ! 606: /*------------------------------------------------------------------------- ! 607: * ! 608: * ! 609: * ! 610: *-------------------------------------------------------------------------*/ ! 611: ! 612: void UniNEnet::restartTransmitter() ! 613: { ! 614: } ! 615: ! 616: /*------------------------------------------------------------------------- ! 617: * ! 618: * ! 619: * ! 620: *-------------------------------------------------------------------------*/ ! 621: ! 622: void UniNEnet::restartReceiver() ! 623: { ! 624: } ! 625: ! 626: /*------------------------------------------------------------------------- ! 627: * ! 628: * Orderly stop of receive DMA. ! 629: * ! 630: * ! 631: *-------------------------------------------------------------------------*/ ! 632: ! 633: void UniNEnet::stopReceiveDMA() ! 634: { ! 635: } ! 636: ! 637: /*------------------------------------------------------------------------- ! 638: * ! 639: * ! 640: * ! 641: *-------------------------------------------------------------------------*/ ! 642: ! 643: void UniNEnet::stopTransmitDMA() ! 644: { ! 645: } ! 646: ! 647: /*------------------------------------------------------------------------- ! 648: * ! 649: * ! 650: * ! 651: *-------------------------------------------------------------------------*/ ! 652: ! 653: bool UniNEnet::transmitPacket(struct mbuf *packet) ! 654: { ! 655: UInt32 i,j,k; ! 656: struct mbuf *m; ! 657: TxQueueElement *txElement; ! 658: UInt32 dataPhys; ! 659: ! 660: ! 661: for ( m = packet, i=1; m->m_next; m=m->m_next, i++ ) ! 662: ; ! 663: ! 664: ! 665: if ( i > txCommandsAvail ) ! 666: { ! 667: transmitInterruptOccurred(); ! 668: ! 669: if ( i > txCommandsAvail ) ! 670: { ! 671: return false; ! 672: } ! 673: } ! 674: ! 675: ! 676: if ( (txElement=getTxElement()) == 0 ) ! 677: { ! 678: transmitInterruptOccurred(); ! 679: ! 680: if ( (txElement=getTxElement()) == 0 ) ! 681: { ! 682: return false; ! 683: } ! 684: } ! 685: ! 686: j = txCommandTail; ! 687: ! 688: txElement->mbuf = packet; ! 689: txElement->slot = j; ! 690: txElement->count = i; ! 691: ! 692: txCommandsAvail -= i; ! 693: ! 694: m = packet; ! 695: ! 696: do ! 697: { ! 698: k = j; ! 699: ! 700: txElementPtrs[j] = txElement; ! 701: ! 702: dataPhys = (UInt32)mcl_to_paddr( mtod(m, char *) ); ! 703: if ( dataPhys == 0 ) ! 704: { ! 705: dataPhys = pmap_extract( kernel_pmap, mtod(m, vm_offset_t)); ! 706: } ! 707: ! 708: txDMACommands[j].desc_seg[0].bufferAddrLo = EndianSwap32(dataPhys); ! 709: txDMACommands[j].desc_seg[0].flags0 = EndianSwap32(kGEMTxDescFlags0_BufferSizeBit * m->m_len); ! 710: ! 711: j++; ! 712: if ( j >= txMaxCommand ) j = 0; ! 713: } ! 714: while ( (m=m->m_next) != 0 ); ! 715: ! 716: txDMACommands[k].desc_seg[0].flags0 |= EndianSwap32(kGEMTxDescFlags0_EndOfFrame); ! 717: txDMACommands[txCommandTail].desc_seg[0].flags0 |= EndianSwap32(kGEMTxDescFlags0_StartOfFrame); ! 718: ! 719: txCommandTail = j; ! 720: ! 721: WriteUniNRegister( ioBaseEnet, kGEMTxKick, j ); ! 722: ! 723: return true; ! 724: } ! 725: ! 726: ! 727: /*------------------------------------------------------------------------- ! 728: * _receivePacket ! 729: * -------------- ! 730: * This routine runs the receiver in polled-mode (yuk!) for the kernel debugger. ! 731: * Don't mess with the interrupt source here that can deadlock in the debugger ! 732: * ! 733: * The _receivePackets allocate MBufs and pass them up the stack. The kernel ! 734: * debugger interface passes a buffer into us. To reconsile the two interfaces, ! 735: * we allow the receive routine to continue to allocate its own buffers and ! 736: * transfer any received data to the passed-in buffer. This is handled by ! 737: * _receivePacket calling _packetToDebugger. ! 738: *-------------------------------------------------------------------------*/ ! 739: ! 740: void UniNEnet::receivePacket( void *pkt, unsigned int *pkt_len, unsigned int timeout ) ! 741: { ! 742: mach_timespec_t startTime; ! 743: mach_timespec_t currentTime; ! 744: UInt32 elapsedTimeMS; ! 745: ! 746: *pkt_len = 0; ! 747: ! 748: if (ready == false) ! 749: return; ! 750: ! 751: debuggerPkt = pkt; ! 752: debuggerPktSize = 0; ! 753: ! 754: IOGetTime(&startTime); ! 755: do ! 756: { ! 757: receivePackets( true ); ! 758: IOGetTime( ¤tTime ); ! 759: elapsedTimeMS = (currentTime.tv_nsec - startTime.tv_nsec) / (1000*1000); ! 760: } ! 761: while ( (debuggerPktSize == 0) && (elapsedTimeMS < timeout) ); ! 762: ! 763: *pkt_len = debuggerPktSize; ! 764: ! 765: return; ! 766: } ! 767: ! 768: /*------------------------------------------------------------------------- ! 769: * _packetToDebugger ! 770: * ----------------- ! 771: * This is called by _receivePackets when we are polling for kernel debugger ! 772: * packets. It copies the MBuf contents to the buffer passed by the debugger. ! 773: * It also sets the var debuggerPktSize which will break the polling loop. ! 774: *-------------------------------------------------------------------------*/ ! 775: ! 776: void UniNEnet::packetToDebugger( struct mbuf * packet, u_int size ) ! 777: { ! 778: debuggerPktSize = size; ! 779: bcopy( mtod(packet, char *), debuggerPkt, size ); ! 780: } ! 781: ! 782: /*------------------------------------------------------------------------- ! 783: * _sendPacket ! 784: * ----------- ! 785: * ! 786: * This routine runs the transmitter in polled-mode (yuk!) for the kernel debugger. ! 787: * Don't mess with the interrupt source here that can deadlock in the debugger ! 788: * ! 789: *-------------------------------------------------------------------------*/ ! 790: ! 791: void UniNEnet::sendPacket( void *pkt, unsigned int pkt_len ) ! 792: { ! 793: mach_timespec_t startTime; ! 794: mach_timespec_t currentTime; ! 795: UInt32 elapsedTimeMS; ! 796: ! 797: if (!ready || !pkt || (pkt_len > ETHERMAXPACKET)) ! 798: { ! 799: return; ! 800: } ! 801: ! 802: /* ! 803: * Wait for the transmit ring to empty ! 804: */ ! 805: IOGetTime(&startTime); ! 806: do ! 807: { ! 808: debugTransmitInterruptOccurred(); ! 809: IOGetTime(¤tTime); ! 810: elapsedTimeMS = (currentTime.tv_nsec - startTime.tv_nsec) / (1000*1000); ! 811: } ! 812: while ( (txCommandHead != txCommandTail) && (elapsedTimeMS < TX_KDB_TIMEOUT) ); ! 813: ! 814: if ( txCommandHead != txCommandTail ) ! 815: { ! 816: IOLog( "Ethernet(UniN): Polled tranmit timeout - 1\n\r"); ! 817: return; ! 818: } ! 819: ! 820: /* ! 821: * Allocate a MBuf and copy the debugger transmit data into it. ! 822: * ! 823: * jliu - no allocation, just recycle the same buffer dedicated to ! 824: * KDB transmit. ! 825: */ ! 826: txDebuggerPkt->m_next = 0; ! 827: txDebuggerPkt->m_data = (caddr_t) pkt; ! 828: txDebuggerPkt->m_pkthdr.len = txDebuggerPkt->m_len = pkt_len; ! 829: ! 830: /* ! 831: * Send the debugger packet. txDebuggerPkt must not be freed by ! 832: * the transmit routine. ! 833: */ ! 834: transmitPacket(txDebuggerPkt); ! 835: ! 836: /* ! 837: * Poll waiting for the transmit ring to empty again ! 838: */ ! 839: do ! 840: { ! 841: debugTransmitInterruptOccurred(); ! 842: IOGetTime(¤tTime); ! 843: elapsedTimeMS = (currentTime.tv_nsec - startTime.tv_nsec) / (1000*1000); ! 844: } ! 845: while ( (txCommandHead != txCommandTail) && ! 846: (elapsedTimeMS < TX_KDB_TIMEOUT) ); ! 847: ! 848: if ( txCommandHead != txCommandTail ) ! 849: { ! 850: IOLog( "Ethernet(UniN): Polled tranmit timeout - 2\n\r"); ! 851: } ! 852: ! 853: return; ! 854: } ! 855: ! 856: /*------------------------------------------------------------------------- ! 857: * _sendDummyPacket ! 858: * ---------------- ! 859: * The UniN receiver seems to be locked until we send our first packet. ! 860: * ! 861: *-------------------------------------------------------------------------*/ ! 862: void UniNEnet::sendDummyPacket() ! 863: { ! 864: union ! 865: { ! 866: UInt8 bytes[64]; ! 867: enet_addr_t enet_addr[2]; ! 868: } dummyPacket; ! 869: ! 870: bzero( &dummyPacket, sizeof(dummyPacket) ); ! 871: ! 872: ! 873: dummyPacket.enet_addr[0] = myAddress; ! 874: dummyPacket.enet_addr[1] = myAddress; ! 875: ! 876: sendPacket((void *)dummyPacket.bytes, (unsigned int)sizeof(dummyPacket)); ! 877: } ! 878: ! 879: ! 880: ! 881: /*------------------------------------------------------------------------- ! 882: * ! 883: * ! 884: * ! 885: *-------------------------------------------------------------------------*/ ! 886: ! 887: bool UniNEnet::receiveInterruptOccurred() ! 888: { ! 889: return receivePackets(false); ! 890: } ! 891: ! 892: /*------------------------------------------------------------------------- ! 893: * ! 894: * ! 895: * ! 896: *-------------------------------------------------------------------------*/ ! 897: ! 898: bool UniNEnet::receivePackets( bool fDebugger ) ! 899: { ! 900: struct mbuf *packet; ! 901: UInt32 i,last; ! 902: int receivedFrameSize = 0; ! 903: UInt16 dmaFlags; ! 904: UInt32 rxPktStatus = 0; ! 905: UInt32 badFrameCount; ! 906: bool passPacketUp; ! 907: bool reusePkt; ! 908: bool status; ! 909: bool useNetif = !fDebugger && netifClient; ! 910: bool packetsQueued = false; ! 911: ! 912: ! 913: last = (UInt32)-1; ! 914: i = rxCommandHead; ! 915: ! 916: while ( 1 ) ! 917: { ! 918: passPacketUp = false; ! 919: reusePkt = false; ! 920: ! 921: dmaFlags = EndianSwap16(rxDMACommands[i].desc_seg[0].frameDataSize); ! 922: ! 923: /* ! 924: * If the current entry has not been written, then stop at this entry ! 925: */ ! 926: if ( dmaFlags & kGEMRxDescFrameSize_Own ) ! 927: { ! 928: break; ! 929: } ! 930: ! 931: ! 932: receivedFrameSize = dmaFlags & kGEMRxDescFrameSize_Mask; ! 933: rxPktStatus = EndianSwap32(rxDMACommands[i].desc_seg[0].flags); ! 934: ! 935: ! 936: /* ! 937: * Reject packets that are runts or that have other mutations. ! 938: */ ! 939: if ( receivedFrameSize < (ETHERMINPACKET - ETHERCRC) || ! 940: receivedFrameSize > (ETHERMAXPACKET + ETHERCRC) || ! 941: rxPktStatus & kGEMRxDescFlags_BadCRC ) ! 942: { ! 943: if (useNetif) netStats->inputErrors++; ! 944: reusePkt = true; ! 945: } ! 946: else if ( useNetif == false ) ! 947: { ! 948: /* ! 949: * Always reuse packets in debugger mode. We also refuse to ! 950: * pass anything up the stack unless the driver is open. The ! 951: * hardware is enabled before the stack has opened us, to ! 952: * allow earlier debug interface registration. But we must ! 953: * not pass any packets up. ! 954: */ ! 955: reusePkt = true; ! 956: if (fDebugger) ! 957: { ! 958: packetToDebugger(rxMbuf[i], receivedFrameSize); ! 959: } ! 960: } ! 961: ! 962: ! 963: /* ! 964: * Before we pass this packet up the networking stack. Make sure we ! 965: * can get a replacement. Otherwise, hold on to the current packet and ! 966: * increment the input error count. ! 967: * Thanks Justin! ! 968: */ ! 969: ! 970: packet = 0; ! 971: ! 972: if ( reusePkt == false ) ! 973: { ! 974: bool replaced; ! 975: ! 976: packet = replaceOrCopyPacket(&rxMbuf[i], receivedFrameSize, &replaced); ! 977: ! 978: reusePkt = true; ! 979: ! 980: if (packet && replaced) ! 981: { ! 982: status = updateDescriptorFromMbuf(rxMbuf[i], &rxDMACommands[i], true); ! 983: ! 984: if (status) ! 985: { ! 986: reusePkt = false; ! 987: } ! 988: else ! 989: { ! 990: // Assume descriptor has not been corrupted. ! 991: freePacket(rxMbuf[i]); // release new packet. ! 992: rxMbuf[i] = packet; // get the old packet back. ! 993: packet = 0; // pass up nothing. ! 994: IOLog("Ethernet(UniN): updateDescriptorFromMbuf error\n"); ! 995: } ! 996: } ! 997: ! 998: if (packet == 0) ! 999: netStats->inputErrors++; ! 1000: } ! 1001: ! 1002: /* ! 1003: * Install the new MBuf for the one we're about to pass to the network stack ! 1004: */ ! 1005: ! 1006: if ( reusePkt == true ) ! 1007: { ! 1008: rxDMACommands[i].desc_seg[0].frameDataSize = EndianSwap16(NETWORK_BUFSIZE | kGEMRxDescFrameSize_Own); ! 1009: rxDMACommands[i].desc_seg[0].flags = 0; ! 1010: } ! 1011: ! 1012: /* ! 1013: * Keep track of the last receive descriptor processed ! 1014: */ ! 1015: last = i; ! 1016: ! 1017: /* ! 1018: * Implement ring wrap-around ! 1019: */ ! 1020: if (++i >= rxMaxCommand) i = 0; ! 1021: ! 1022: if (fDebugger) ! 1023: { ! 1024: break; ! 1025: } ! 1026: ! 1027: /* ! 1028: * Transfer received packet to network ! 1029: */ ! 1030: if (packet) ! 1031: { ! 1032: KERNEL_DEBUG(DBG_UniN_RXCOMPLETE | DBG_FUNC_NONE, (int) packet, ! 1033: (int)receivedFrameSize, 0, 0, 0 ); ! 1034: ! 1035: networkInterface->inputPacket(packet, receivedFrameSize, true); ! 1036: netStats->inputPackets++; ! 1037: packetsQueued = true; ! 1038: } ! 1039: } ! 1040: ! 1041: /* ! 1042: * ! 1043: * ! 1044: */ ! 1045: #if 0 ! 1046: IOLog( "Ethernet(UniN): Prev - Rx Head = %2d Rx Tail = %2d Rx Last = %2d\n\r", rxCommandHead, rxCommandTail, last ); ! 1047: #endif ! 1048: ! 1049: if ( last != (UInt32)-1 ) ! 1050: { ! 1051: rxCommandTail = last; ! 1052: rxCommandHead = i; ! 1053: } ! 1054: ! 1055: /* ! 1056: * Tap the DMA to wake it up ! 1057: */ ! 1058: WriteUniNRegister(ioBaseEnet, kGEMRxKick, rxCommandTail & ~(4-1)); ! 1059: ! 1060: ! 1061: /* ! 1062: * Update receive error statistics ! 1063: */ ! 1064: ! 1065: badFrameCount = ReadUniNRegister(ioBaseEnet, kGEMMacRxLengthErrors) ! 1066: + ReadUniNRegister(ioBaseEnet, kGEMMacRxFCSErrors); ! 1067: ! 1068: /* ! 1069: * Clear Hardware counters ! 1070: */ ! 1071: WriteUniNRegister(ioBaseEnet, kGEMMacRxLengthErrors, 0); ! 1072: WriteUniNRegister(ioBaseEnet, kGEMMacRxFCSErrors, 0); ! 1073: ! 1074: if (useNetif) netStats->inputErrors += badFrameCount; ! 1075: ! 1076: ! 1077: return packetsQueued; ! 1078: } ! 1079: ! 1080: /*------------------------------------------------------------------------- ! 1081: * ! 1082: * ! 1083: * ! 1084: *-------------------------------------------------------------------------*/ ! 1085: ! 1086: bool UniNEnet::transmitInterruptOccurred() ! 1087: { ! 1088: UInt32 i; ! 1089: bool fServiced = false; ! 1090: UInt32 txHeadOrig, txCompOrig; ! 1091: TxQueueElement *txElement; ! 1092: ! 1093: i = ReadUniNRegister( ioBaseEnet, kGEMTxCompletion ); ! 1094: ! 1095: txHeadOrig = txCommandHead; ! 1096: txCompOrig = i; ! 1097: ! 1098: while ( i != txCommandHead ) ! 1099: { ! 1100: /* ! 1101: * Free the MBuf we just transmitted ! 1102: */ ! 1103: txElement = txElementPtrs[txCommandHead]; ! 1104: ! 1105: KERNEL_DEBUG(DBG_UniN_TXCOMPLETE | DBG_FUNC_NONE, (int) txElement->mbuf, 0, 0, 0, 0 ); ! 1106: ! 1107: txElementPtrs[txCommandHead] = 0; ! 1108: txCommandsAvail++; ! 1109: ! 1110: if ( --txElement->count == 0 ) ! 1111: { ! 1112: freePacket( txElement->mbuf ); ! 1113: releaseTxElement( txElement ); ! 1114: if (netifClient) netStats->outputPackets++; ! 1115: } ! 1116: ! 1117: if ( ++txCommandHead >= txMaxCommand ) txCommandHead = 0; ! 1118: ! 1119: i = ReadUniNRegister( ioBaseEnet, kGEMTxCompletion ); ! 1120: ! 1121: fServiced = true; ! 1122: } ! 1123: ! 1124: return fServiced; ! 1125: } ! 1126: ! 1127: /*------------------------------------------------------------------------- ! 1128: * ! 1129: * ! 1130: * ! 1131: *-------------------------------------------------------------------------*/ ! 1132: ! 1133: bool UniNEnet::debugTransmitInterruptOccurred() ! 1134: { ! 1135: bool fServiced = false; ! 1136: UInt32 i; ! 1137: TxQueueElement *txElement; ! 1138: ! 1139: // Set the debugTxPoll flag to indicate the debugger was active ! 1140: // and some cleanup may be needed when the driver returns to ! 1141: // normal operation. ! 1142: // ! 1143: debugTxPoll = true; ! 1144: ! 1145: i = ReadUniNRegister( ioBaseEnet, kGEMTxCompletion ); ! 1146: ! 1147: while ( i != txCommandHead ) ! 1148: { ! 1149: fServiced = true; ! 1150: ! 1151: /* ! 1152: * Free the mbuf we just transmitted. ! 1153: * ! 1154: * If it is the debugger packet, just remove it from the ring. ! 1155: * and reuse the same packet for the next sendPacket() request. ! 1156: */ ! 1157: ! 1158: /* ! 1159: * While in debugger mode, do not touch the mbuf pool. ! 1160: * Queue any used mbufs to a local queue. This queue ! 1161: * will get flushed after we exit from debugger mode. ! 1162: * ! 1163: * During continuous debugger transmission and ! 1164: * interrupt polling, we expect only the txDebuggerPkt ! 1165: * to show up on the transmit mbuf ring. ! 1166: */ ! 1167: txElement = txElementPtrs[txCommandHead]; ! 1168: txElementPtrs[txCommandHead] = 0; ! 1169: txCommandsAvail++; ! 1170: ! 1171: KERNEL_DEBUG(DBG_UniN_TXCOMPLETE | DBG_FUNC_NONE, ! 1172: (int)txElement->mbuf, ! 1173: (int)txElement->mbuf->m_pkthdr.len, 0, 0, 0 ); ! 1174: ! 1175: if ( --txElement->count == 0 ) ! 1176: { ! 1177: if (txElement->mbuf != txDebuggerPkt) ! 1178: { ! 1179: debugQueue->enqueue( txElement->mbuf ); ! 1180: } ! 1181: releaseTxElement( txElement ); ! 1182: } ! 1183: ! 1184: if ( ++(txCommandHead) >= txMaxCommand ) ! 1185: txCommandHead = 0; ! 1186: } ! 1187: ! 1188: return fServiced; ! 1189: } ! 1190: ! 1191: /*------------------------------------------------------------------------- ! 1192: * ! 1193: * ! 1194: * ! 1195: *-------------------------------------------------------------------------*/ ! 1196: ! 1197: void UniNEnet::debugTransmitCleanup() ! 1198: { ! 1199: // Debugger was active, clear all packets in the debugQueue, and ! 1200: // issue a start(), just in case the debugger became active while the ! 1201: // ring was full and the output queue stopped. Since the debugger ! 1202: // does not restart the output queue, to avoid calling ! 1203: // semaphore_signal() which may reenable interrupts, we need to ! 1204: // make sure the output queue is not stalled after the debugger has ! 1205: // flushed the ring. ! 1206: ! 1207: debugQueue->flush(); ! 1208: ! 1209: transmitQueue->start(); ! 1210: } ! 1211: ! 1212: ! 1213: /*------------------------------------------------------------------------- ! 1214: * ! 1215: * ! 1216: * ! 1217: *-------------------------------------------------------------------------*/ ! 1218: ! 1219: static UInt32 txCnt = 1; ! 1220: ! 1221: bool UniNEnet::updateDescriptorFromMbuf(struct mbuf * m, enet_dma_cmd_t *desc, bool isReceive) ! 1222: { ! 1223: struct IOPhysicalSegment segVector[1]; ! 1224: UInt32 segments; ! 1225: ! 1226: segments = mbufCursor->getPhysicalSegmentsWithCoalesce(m, segVector); ! 1227: ! 1228: if ( segments == 0 || segments > 1 ) ! 1229: { ! 1230: IOLog("Ethernet(UniN): updateDescriptorFromMbuf error, %d segments\n", (int)segments); ! 1231: return false; ! 1232: } ! 1233: ! 1234: if ( isReceive ) ! 1235: { ! 1236: enet_dma_cmd_t *rxCmd = (enet_dma_cmd_t *)desc; ! 1237: ! 1238: rxCmd->desc_seg[0].bufferAddrLo = EndianSwap32(segVector[0].location); ! 1239: rxCmd->desc_seg[0].frameDataSize = EndianSwap16(segVector[0].length | kGEMRxDescFrameSize_Own); ! 1240: rxCmd->desc_seg[0].flags = 0; ! 1241: } ! 1242: else ! 1243: { ! 1244: enet_txdma_cmd_t *txCmd = (enet_txdma_cmd_t *)desc; ! 1245: ! 1246: txCmd->desc_seg[0].bufferAddrLo = EndianSwap32(segVector[0].location); ! 1247: txCmd->desc_seg[0].flags0 = EndianSwap32( kGEMTxDescFlags0_BufferSizeBit * segVector[0].length | ! 1248: kGEMTxDescFlags0_StartOfFrame | ! 1249: kGEMTxDescFlags0_EndOfFrame ); ! 1250: ! 1251: txCmd->desc_seg[0].flags1 = ((txCnt++ % 64) == 0) ? EndianSwap32(kGEMTxDescFlags1_Int) : 0; ! 1252: } ! 1253: ! 1254: return true; ! 1255: } ! 1256: ! 1257: /*------------------------------------------------------------------------- ! 1258: * ! 1259: * ! 1260: * ! 1261: *-------------------------------------------------------------------------*/ ! 1262: ! 1263: TxQueueElement *UniNEnet::getTxElement() ! 1264: { ! 1265: TxQueueElement *txElement = 0; ! 1266: ! 1267: if ( queue_empty( &txFreeQueue ) == false ) ! 1268: { ! 1269: queue_remove_first( &txFreeQueue, txElement, TxQueueElement *, next ); ! 1270: ! 1271: txElement->list = &txActiveQueue; ! 1272: ! 1273: queue_enter( txElement->list, txElement, TxQueueElement *, next ); ! 1274: } ! 1275: ! 1276: return txElement; ! 1277: } ! 1278: ! 1279: /*------------------------------------------------------------------------- ! 1280: * ! 1281: * ! 1282: * ! 1283: *-------------------------------------------------------------------------*/ ! 1284: ! 1285: void UniNEnet::releaseTxElement(TxQueueElement *txElement) ! 1286: { ! 1287: if ( txElement->list != 0 ) ! 1288: { ! 1289: queue_remove( txElement->list, txElement, TxQueueElement *, next ); ! 1290: } ! 1291: ! 1292: txElement->list = &txFreeQueue; ! 1293: ! 1294: queue_enter( txElement->list, txElement, TxQueueElement *, next); ! 1295: } ! 1296: ! 1297: /*------------------------------------------------------------------------- ! 1298: * ! 1299: * ! 1300: * ! 1301: *-------------------------------------------------------------------------*/ ! 1302: ! 1303: void UniNEnet::monitorLinkStatus() ! 1304: { ! 1305: UInt16 phyStatus; ! 1306: UInt16 linkStatus; ! 1307: UInt16 linkMode; ! 1308: UInt16 lpAbility; ! 1309: UInt16 gemReg; ! 1310: UInt16 phyStatusChange; ! 1311: bool fullDuplex = false; ! 1312: UInt8 *linkSpeedTxt; ! 1313: ! 1314: if ( phyId == 0xff ) ! 1315: { ! 1316: phyStatus = ReadUniNRegister( ioBaseEnet, kGEMPCSStatus ); ! 1317: lpAbility = ReadUniNRegister( ioBaseEnet, kGEMPCSLPAbility ); ! 1318: } ! 1319: else ! 1320: { ! 1321: if ( miiReadWord( &phyStatus, MII_STATUS, phyId) != true ) ! 1322: { ! 1323: return; ! 1324: } ! 1325: miiReadWord( &lpAbility, MII_STATUS, phyId); ! 1326: } ! 1327: ! 1328: phyStatusChange = (phyStatusPrev ^ phyStatus) & (MII_STATUS_LINK_STATUS | MII_STATUS_NEGOTIATION_COMPLETE); ! 1329: if ( phyStatusChange ) ! 1330: { ! 1331: gemReg = ReadUniNRegister( ioBaseEnet, kGEMMacControlConfig ); ! 1332: if ( lpAbility & MII_LPAR_PAUSE ) ! 1333: { ! 1334: gemReg |= kGEMMacControlConfig_SendPauseEnable; ! 1335: } ! 1336: else ! 1337: { ! 1338: gemReg &= ~kGEMMacControlConfig_SendPauseEnable; ! 1339: } ! 1340: WriteUniNRegister( ioBaseEnet, kGEMMacControlConfig, gemReg ); ! 1341: ! 1342: if ( (phyStatus & MII_STATUS_LINK_STATUS) && (phyStatus & MII_STATUS_NEGOTIATION_COMPLETE ) ) ! 1343: { ! 1344: if ( phyId == 0xff ) ! 1345: { ! 1346: IOLog( "Ethernet(UniN): Link is up at 1Gb - Full Duplex\n\r" ); ! 1347: fullDuplex = true; ! 1348: } ! 1349: else if ( (phyType & MII_BCM5201_MASK) == MII_BCM5201_ID ) ! 1350: { ! 1351: miiReadWord( &linkStatus, MII_BCM5201_AUXSTATUS, phyId ); ! 1352: ! 1353: fullDuplex = (linkStatus & MII_BCM5201_AUXSTATUS_DUPLEX) ? true : false; ! 1354: ! 1355: IOLog( "Ethernet(UniN): Link is up at %sMb - %s Duplex\n\r", ! 1356: (linkStatus & MII_BCM5201_AUXSTATUS_SPEED) ? "100" : "10", ! 1357: (fullDuplex) ? "Full" : "Half" ); ! 1358: ! 1359: } ! 1360: else if ( (phyType & MII_BCM5400_MASK) == MII_BCM5400_ID ) ! 1361: { ! 1362: miiReadWord( &linkStatus, MII_BCM5400_AUXSTATUS, phyId ); ! 1363: ! 1364: linkMode = (linkStatus & MII_BCM5400_AUXSTATUS_LINKMODE_MASK) / MII_BCM5400_AUXSTATUS_LINKMODE_BIT; ! 1365: ! 1366: gemReg = ReadUniNRegister( ioBaseEnet, kGEMMacXIFConfig ); ! 1367: if ( linkMode < 6 ) ! 1368: { ! 1369: gemReg &= ~kGEMMacXIFConfig_GMIIMode; ! 1370: } ! 1371: else ! 1372: { ! 1373: gemReg |= kGEMMacXIFConfig_GMIIMode; ! 1374: } ! 1375: WriteUniNRegister( ioBaseEnet, kGEMMacXIFConfig, gemReg ); ! 1376: ! 1377: if ( linkMode == 0 ) ! 1378: { ! 1379: linkSpeedTxt = NULL; ! 1380: } ! 1381: else if ( linkMode < 3 ) ! 1382: { ! 1383: linkSpeedTxt = (UInt8 *)"10Mb"; ! 1384: fullDuplex = ( linkMode < 2 ) ? false : true; ! 1385: ! 1386: } ! 1387: else if ( linkMode < 6 ) ! 1388: { ! 1389: linkSpeedTxt = (UInt8 *)"100Mb"; ! 1390: fullDuplex = ( linkMode < 5 ) ? false : true; ! 1391: } ! 1392: else ! 1393: { ! 1394: linkSpeedTxt = (UInt8 *)"1Gb"; ! 1395: fullDuplex = true; ! 1396: } ! 1397: ! 1398: if ( linkSpeedTxt ) ! 1399: { ! 1400: IOLog( "Ethernet(UniN): Link is up at %s - %s Duplex\n\r", ! 1401: linkSpeedTxt, ! 1402: (fullDuplex) ? "Full" : "Half" ); ! 1403: } ! 1404: else ! 1405: { ! 1406: IOLog( "Ethernet(UniN): Link is up\n\r" ); ! 1407: } ! 1408: ! 1409: } ! 1410: ! 1411: if ( fullDuplex != isFullDuplex ) ! 1412: { ! 1413: setDuplexMode( fullDuplex ); ! 1414: } ! 1415: ! 1416: if ( ready == true ) ! 1417: { ! 1418: startChip(); ! 1419: } ! 1420: ! 1421: linkStatusPrev = true; ! 1422: } ! 1423: else ! 1424: { ! 1425: if ( linkStatusPrev == true ) ! 1426: { ! 1427: stopChip(); ! 1428: IOLog( "Ethernet(UniN): Link is down.\n\r" ); ! 1429: } ! 1430: linkStatusPrev = false; ! 1431: } ! 1432: phyStatusPrev = phyStatus; ! 1433: } ! 1434: } ! 1435: ! 1436: ! 1437: /*------------------------------------------------------------------------- ! 1438: * ! 1439: * ! 1440: * ! 1441: *-------------------------------------------------------------------------*/ ! 1442: ! 1443: void UniNEnet::dumpRegisters() ! 1444: { ! 1445: UInt32 i; ! 1446: ! 1447: struct _regtable ! 1448: { ! 1449: UInt32 reg; ! 1450: char *text; ! 1451: } ! 1452: regtable[] = ! 1453: { ! 1454: { kGEMSEBState ,"SEBState" }, ! 1455: { kGEMConfig ,"Config" }, ! 1456: { kGEMInterruptStatus ,"InterruptStatus" }, ! 1457: { kGEMInterruptMask ,"InterruptMask" }, ! 1458: { kGEMInterruptAck ,"InterruptAck" }, ! 1459: { kGEMInterruptAltStatus ,"InterruptAltStatus" }, ! 1460: { kGEMPCIErrorStatus ,"PCIErrorStatus" }, ! 1461: { kGEMPCIErrorMask ,"PCIErrorMask" }, ! 1462: { kGEMBIFConfig ,"BIFConfig" }, ! 1463: { kGEMBIFDiagnostic ,"BIFDiagnostic" }, ! 1464: { kGEMSoftwareReset ,"SoftwareReset" }, ! 1465: { kGEMTxKick ,"TxKick" }, ! 1466: { kGEMTxConfig ,"TxConfig" }, ! 1467: { kGEMTxDescBaseLo ,"TxDescBaseLo" }, ! 1468: { kGEMTxDescBaseHi ,"TxDescBaseHi" }, ! 1469: { kGEMTxFIFOWritePtr ,"TxFIFOWritePtr" }, ! 1470: { kGEMTxFIFOShadowWritePtr ,"TxFIFOShadowWritePtr" }, ! 1471: { kGEMTxFIFOReadPtr ,"TxFIFOReadPtr" }, ! 1472: { kGEMTxFIFOShadowReadPtr ,"TxFIFOShadowReadPtr" }, ! 1473: { kGEMTxFIFOPktCounter ,"TxFIFOPktCounter" }, ! 1474: { kGEMTxStateMachine ,"TxStateMachine" }, ! 1475: { kGEMTxDataPtrLo ,"TxDataPtrLo" }, ! 1476: { kGEMTxDataPtrHi ,"TxDataPtrHi" }, ! 1477: { kGEMTxCompletion ,"TxCompletion" }, ! 1478: { kGEMTxFIFOAddr ,"TxFIFOAddr" }, ! 1479: { kGEMTxFIFOTag ,"TxFIFOTag" }, ! 1480: { kGEMTxFIFODataLo ,"TxFIFODataLo" }, ! 1481: { kGEMTxFIFODataHiTag1 ,"TxFIFODataHiTag1" }, ! 1482: { kGEMTxFIFODataHiTag0 ,"TxFIFODataHiTag0" }, ! 1483: { kGEMTxFIFOSize ,"TxFIFOSize" }, ! 1484: { kGEMRxConfig ,"RxConfig" }, ! 1485: { kGEMRxDescBaseLo ,"RxDescBaseLo" }, ! 1486: { kGEMRxDescBaseHi ,"RxDescBaseHi" }, ! 1487: { kGEMRxFIFOWritePtr ,"RxFIFOWritePtr" }, ! 1488: { kGEMRxFIFOShadowWritePtr ,"RxFIFOShadowWritePtr" }, ! 1489: { kGEMRxFIFOReadPtr ,"RxFIFOReadPtr" }, ! 1490: { kGEMRxFIFOPktCounter ,"RxFIFOPktCounter" }, ! 1491: { kGEMRxStateMachine ,"RxStateMachine" }, ! 1492: { kGEMRxPauseThresholds ,"RxPauseThresholds" }, ! 1493: { kGEMRxDataPtrLo ,"RxDataPtrLo" }, ! 1494: { kGEMRxDataPtrHi ,"RxDataPtrHi" }, ! 1495: { kGEMRxKick ,"RxKick" }, ! 1496: { kGEMRxCompletion ,"RxCompletion" }, ! 1497: { kGEMRxIntBlanking ,"RxIntBlanking" }, ! 1498: { kGEMRxFIFOAddr ,"RxFIFOAddr" }, ! 1499: { kGEMRxFIFOTag ,"RxFIFOTag" }, ! 1500: { kGEMRxDataLo ,"RxDataLo" }, ! 1501: { kGEMRxDataHiTag0 ,"RxDataHiTag0" }, ! 1502: { kGEMRxDataHiTag1 ,"RxDataHiTag1" }, ! 1503: { kGEMRxFIFOSize ,"RxFIFOSize" }, ! 1504: { kGEMMacTxResetCmd ,"MacTxResetCmd" }, ! 1505: { kGEMMacRxResetCmd ,"MacRxResetCmd" }, ! 1506: { kGEMMacSendPauseCmd ,"MacSendPauseCmd" }, ! 1507: { kGEMMacTxStatus ,"MacTxStatus" }, ! 1508: { kGEMMacRxStatus ,"MacRxStatus" }, ! 1509: { kGEMMacControlStatus ,"MacControlStatus" }, ! 1510: { kGEMMacTxMask ,"MacTxMask" }, ! 1511: { kGEMMacRxMask ,"MacRxMask" }, ! 1512: { kGEMMacControlMask ,"MacControlMask" }, ! 1513: { kGEMMacTxMacConfig ,"MacTxMacConfig" }, ! 1514: { kGEMMacRxMacConfig ,"MacRxMacConfig" }, ! 1515: { kGEMMacControlConfig ,"MacControlConfig" }, ! 1516: { kGEMMacXIFConfig ,"MacXIFConfig" }, ! 1517: { kGEMMacInterPktGap0 ,"MacInterPktGap0" }, ! 1518: { kGEMMacInterPktGap1 ,"MacInterPktGap1" }, ! 1519: { kGEMMacInterPktGap2 ,"MacInterPktGap2" }, ! 1520: { kGEMMacSlotTime ,"MacSlotTime" }, ! 1521: { kGEMMacMinFrameSize ,"MacMinFrameSize" }, ! 1522: { kGEMMacMaxFrameSize ,"MacMaxFrameSize" }, ! 1523: { kGEMMacPASize ,"MacPASize" }, ! 1524: { kGEMMacJamSize ,"MacJamSize" }, ! 1525: { kGEMMacAttemptLimit ,"MacAttemptLimit" }, ! 1526: { kGEMMacTypeControl ,"MacTypeControl" }, ! 1527: { kGEMMacAddr ,"MacAddr" }, ! 1528: { kGEMMacAddrFilter ,"MacAddrFilter" }, ! 1529: { kGEMMacAddrFilterMask1 ,"MacAddrFilterMask1" }, ! 1530: { kGEMMacAddrFilterMask0 ,"MacAddrFilterMask0" }, ! 1531: { kGEMMacHashTable ,"MacHashTable" }, ! 1532: { kGEMMacCollisions ,"MacCollisions" }, ! 1533: { kGEMMacSingleCollision ,"MacSingleCollision" }, ! 1534: { kGEMMacExcessCollisions ,"MacExcessCollisions" }, ! 1535: { kGEMMacLateCollisions ,"MacLateCollisions" }, ! 1536: { kGEMMacDeferTimer ,"MacDeferTimer" }, ! 1537: { kGEMMacPeakAttempts ,"MacPeakAttempts" }, ! 1538: { kGEMMacRxFrameCounter ,"MacRxFrameCounter" }, ! 1539: { kGEMMacRxLengthErrors ,"MacRxLengthErrors" }, ! 1540: { kGEMMacRxAlignErrors ,"MacRxAlignErrors" }, ! 1541: { kGEMMacRxFCSErrors ,"MacRxFCSErrors" }, ! 1542: { kGEMMacRxCodeErrors ,"MacRxCodeErrors" }, ! 1543: { kGEMMacRandomSeed ,"MacRandomSeed" }, ! 1544: { kGEMMacStateMachine ,"MacStateMachine" }, ! 1545: { kGEMMIFCLock ,"MIFCLock" }, ! 1546: { kGEMMIFData ,"MIFData" }, ! 1547: { kGEMMIFOutputEnable ,"MIFOutputEnable" }, ! 1548: { kGEMMIFFrame ,"MIFFrame" }, ! 1549: { kGEMMIFConfig ,"MIFConfig" }, ! 1550: { kGEMMIFMask ,"MIFMask" }, ! 1551: { kGEMMIFStatus ,"MIFStatus" }, ! 1552: { kGEMMIFStateMachine ,"MIFStateMachine" }, ! 1553: { kGEMPCSControl ,"PCSControl" }, ! 1554: { kGEMPCSStatus ,"PCSStatus" }, ! 1555: { kGEMPCSAdvert ,"PCSAdvert" }, ! 1556: { kGEMPCSLPAbility ,"PCSLPAbility" }, ! 1557: { kGEMPCSConfig ,"PCSConfig" }, ! 1558: { kGEMPCSStateMachine ,"PCSStateMachine" }, ! 1559: { kGEMPCSInterruptStatus ,"PCSInterruptStatus" }, ! 1560: { kGEMPCSDatapathMode ,"PCSDatapathMode" }, ! 1561: { kGEMPCSSerdesControl ,"PCSSerdesControl" }, ! 1562: { kGEMPCSSerdesOutputSelect ,"PCSSerdesOutputSelect"}, ! 1563: { kGEMPCSSerdesState ,"PCSSerdesState" } ! 1564: }; ! 1565: ! 1566: IOLog("\nEthernet(UniN): IO Address = %08x\n\r", (int)ioBaseEnet ); ! 1567: ! 1568: for ( i=0; i < sizeof(regtable)/sizeof(regtable[0]); i++ ) ! 1569: { ! 1570: switch ( regtable[i].reg >> 16 ) ! 1571: { ! 1572: case 1: ! 1573: IOLog( "Ethernet(UniN): %04x: %s = %02x\n\r", ! 1574: (int)regtable[i].reg & 0xffff, ! 1575: regtable[i].text, ! 1576: ReadUniNRegister( ioBaseEnet, regtable[i].reg ) ); ! 1577: break; ! 1578: case 2: ! 1579: IOLog( "Ethernet(UniN): %04x: %s = %04x\n\r", ! 1580: (int)regtable[i].reg & 0xffff, ! 1581: regtable[i].text, ! 1582: ReadUniNRegister( ioBaseEnet, regtable[i].reg ) ); ! 1583: break; ! 1584: case 4: ! 1585: IOLog( "Ethernet(UniN): %04x: %s = %08x\n\r", ! 1586: (int)regtable[i].reg & 0xffff, ! 1587: regtable[i].text, ! 1588: ReadUniNRegister( ioBaseEnet, regtable[i].reg ) ); ! 1589: break; ! 1590: } ! 1591: } ! 1592: } ! 1593: ! 1594: ! 1595: /*------------------------------------------------------------------------- ! 1596: * ! 1597: * ! 1598: * ! 1599: *-------------------------------------------------------------------------*/ ! 1600: ! 1601: IOReturn UniNEnet::getHardwareAddress(enet_addr_t *ea) ! 1602: { ! 1603: UInt32 i; ! 1604: OSData *macEntry; ! 1605: UInt8 *macAddress; ! 1606: UInt32 len; ! 1607: ! 1608: macEntry = OSDynamicCast( OSData, nub->getProperty( "local-mac-address" ) ); ! 1609: if ( macEntry == 0 ) ! 1610: { ! 1611: return kIOReturnError; ! 1612: } ! 1613: ! 1614: macAddress = (UInt8 *)macEntry->getBytesNoCopy(); ! 1615: if ( macAddress == 0 ) ! 1616: { ! 1617: return kIOReturnError; ! 1618: } ! 1619: ! 1620: len = macEntry->getLength(); ! 1621: if ( len != 6 ) ! 1622: { ! 1623: return kIOReturnError; ! 1624: } ! 1625: ! 1626: for (i = 0; i < sizeof(*ea); i++) ! 1627: { ! 1628: ea->ea_byte[i] = macAddress[i]; ! 1629: } ! 1630: return kIOReturnSuccess; ! 1631: } ! 1632: ! 1633: /*------------------------------------------------------------------------- ! 1634: * ! 1635: * ! 1636: * ! 1637: *-------------------------------------------------------------------------*/ ! 1638: ! 1639: #define ENET_CRCPOLY 0x04c11db7 ! 1640: ! 1641: static UInt32 crc416(UInt32 current, UInt16 nxtval ) ! 1642: { ! 1643: register UInt32 counter; ! 1644: register int highCRCBitSet, lowDataBitSet; ! 1645: ! 1646: /* Swap bytes */ ! 1647: nxtval = ((nxtval & 0x00FF) << 8) | (nxtval >> 8); ! 1648: ! 1649: /* Compute bit-by-bit */ ! 1650: for (counter = 0; counter != 16; ++counter) ! 1651: { /* is high CRC bit set? */ ! 1652: if ((current & 0x80000000) == 0) ! 1653: highCRCBitSet = 0; ! 1654: else ! 1655: highCRCBitSet = 1; ! 1656: ! 1657: current = current << 1; ! 1658: ! 1659: if ((nxtval & 0x0001) == 0) ! 1660: lowDataBitSet = 0; ! 1661: else ! 1662: lowDataBitSet = 1; ! 1663: ! 1664: nxtval = nxtval >> 1; ! 1665: ! 1666: /* do the XOR */ ! 1667: if (highCRCBitSet ^ lowDataBitSet) ! 1668: current = current ^ ENET_CRCPOLY; ! 1669: } ! 1670: return current; ! 1671: } ! 1672: ! 1673: /*------------------------------------------------------------------------- ! 1674: * ! 1675: * ! 1676: * ! 1677: *-------------------------------------------------------------------------*/ ! 1678: ! 1679: static UInt32 mace_crc(UInt16 *address) ! 1680: { ! 1681: register UInt32 newcrc; ! 1682: ! 1683: newcrc = crc416(0xffffffff, *address); /* address bits 47 - 32 */ ! 1684: newcrc = crc416(newcrc, address[1]); /* address bits 31 - 16 */ ! 1685: newcrc = crc416(newcrc, address[2]); /* address bits 15 - 0 */ ! 1686: ! 1687: return(newcrc); ! 1688: } ! 1689: ! 1690: /*------------------------------------------------------------------------- ! 1691: * ! 1692: * ! 1693: * ! 1694: *-------------------------------------------------------------------------*/ ! 1695: ! 1696: /* ! 1697: * Add requested mcast addr to UniN's hash table filter. ! 1698: * ! 1699: */ ! 1700: void UniNEnet::addToHashTableMask(UInt8 *addr) ! 1701: { ! 1702: UInt32 i,j; ! 1703: UInt32 crcBitIndex; ! 1704: UInt16 mask; ! 1705: ! 1706: j = mace_crc((UInt16 *)addr) & 0xFF; /* Big-endian alert! */ ! 1707: ! 1708: for ( crcBitIndex = i = 0; i < 8; i++ ) ! 1709: { ! 1710: crcBitIndex >>= 1; ! 1711: crcBitIndex |= (j & 0x80); ! 1712: j <<= 1; ! 1713: } ! 1714: ! 1715: crcBitIndex ^= 0xFF; ! 1716: ! 1717: if (hashTableUseCount[crcBitIndex]++) ! 1718: return; /* This bit is already set */ ! 1719: mask = crcBitIndex % 16; ! 1720: mask = 1 << mask; ! 1721: hashTableMask[crcBitIndex/16] |= mask; ! 1722: } ! 1723: ! 1724: /*------------------------------------------------------------------------- ! 1725: * ! 1726: * ! 1727: * ! 1728: *-------------------------------------------------------------------------*/ ! 1729: ! 1730: void UniNEnet::resetHashTableMask() ! 1731: { ! 1732: bzero(hashTableUseCount, sizeof(hashTableUseCount)); ! 1733: bzero(hashTableMask, sizeof(hashTableMask)); ! 1734: } ! 1735: ! 1736: /*------------------------------------------------------------------------- ! 1737: * ! 1738: * ! 1739: * ! 1740: *-------------------------------------------------------------------------*/ ! 1741: ! 1742: /* ! 1743: * Sync the adapter with the software copy of the multicast mask ! 1744: * (logical address filter). ! 1745: */ ! 1746: void UniNEnet::updateHashTableMask() ! 1747: { ! 1748: UInt32 i; ! 1749: UInt16 rxCFGReg; ! 1750: ! 1751: rxCFGReg = ReadUniNRegister(ioBaseEnet, kGEMMacRxMacConfig); ! 1752: WriteUniNRegister(ioBaseEnet, kGEMMacRxMacConfig, rxCFGReg & ~(kGEMMacRxMacConfig_RxMacEnable | ! 1753: kGEMMacRxMacConfig_HashFilterEnable) ); ! 1754: ! 1755: while ( ReadUniNRegister(ioBaseEnet, kGEMMacRxMacConfig) & (kGEMMacRxMacConfig_RxMacEnable | ! 1756: kGEMMacRxMacConfig_HashFilterEnable) ) ! 1757: ; ! 1758: for (i=0; i<16; i++ ) ! 1759: { ! 1760: WriteUniNRegister( ioBaseEnet, kGEMMacHashTable + i*4, hashTableMask[15-i] ); ! 1761: } ! 1762: ! 1763: rxCFGReg |= kGEMMacRxMacConfig_HashFilterEnable; ! 1764: WriteUniNRegister(ioBaseEnet, kGEMMacRxMacConfig, rxCFGReg ); ! 1765: } ! 1766: ! 1767:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.