|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: /* ! 26: * Copyright (c) 1998-1999 by Apple Computer, Inc., All rights reserved. ! 27: * ! 28: * Implementation for hardware dependent (relatively) code ! 29: * for the BMac Ethernet controller. ! 30: * ! 31: * HISTORY ! 32: * ! 33: */ ! 34: #import "BMacEnetPrivate.h" ! 35: #import <mach/vm_param.h> // page alignment macros ! 36: ! 37: extern void *kernel_map; ! 38: extern kern_return_t kmem_alloc_wired(); ! 39: ! 40: static IODBDMADescriptor dbdmaCmd_Nop; ! 41: static IODBDMADescriptor dbdmaCmd_NopWInt; ! 42: static IODBDMADescriptor dbdmaCmd_LoadInt; ! 43: static IODBDMADescriptor dbdmaCmd_LoadIntWInt; ! 44: static IODBDMADescriptor dbdmaCmd_Stop; ! 45: static IODBDMADescriptor dbdmaCmd_Branch; ! 46: ! 47: static u_int8_t reverseBitOrder(u_int8_t data ) ! 48: { ! 49: u_int8_t val = 0; ! 50: int i; ! 51: ! 52: for ( i=0; i < 8; i++ ) ! 53: { ! 54: val <<= 1; ! 55: if (data & 1) val |= 1; ! 56: data >>= 1; ! 57: } ! 58: return( val ); ! 59: } ! 60: ! 61: ! 62: @implementation BMacEnet (Private) ! 63: ! 64: ! 65: /* ! 66: * Private functions ! 67: */ ! 68: - (BOOL)_allocateMemory ! 69: { ! 70: u_int32_t dbdmaSize; ! 71: u_int32_t i, n; ! 72: unsigned char * virtAddr; ! 73: u_int32_t physBase; ! 74: u_int32_t physAddr; ! 75: IOReturn kr; ! 76: ! 77: /* ! 78: * Calculate total space for DMA channel commands ! 79: */ ! 80: dbdmaSize = round_page( RX_RING_LENGTH * sizeof(enet_dma_cmd_t) + TX_RING_LENGTH * sizeof(enet_txdma_cmd_t) ! 81: + 2 * sizeof(IODBDMADescriptor) ); ! 82: /* ! 83: * Allocate required memory ! 84: */ ! 85: if ( !dmaCommands ) ! 86: { ! 87: kr = kmem_alloc_wired(kernel_map, (vm_offset_t *) &dmaCommands, dbdmaSize ); ! 88: ! 89: if ( kr != KERN_SUCCESS ) ! 90: { ! 91: IOLog( "Ethernet(BMac): Cant allocate channel DBDMA commands\n\r" ); ! 92: return NO; ! 93: } ! 94: } ! 95: ! 96: /* ! 97: * If we needed more than one page, then make sure we received contiguous memory. ! 98: */ ! 99: n = (dbdmaSize - PAGE_SIZE) / PAGE_SIZE; ! 100: IOPhysicalFromVirtual( (vm_task_t) kernel_map, (vm_address_t) dmaCommands, &physBase ); ! 101: ! 102: virtAddr = (unsigned char *) dmaCommands; ! 103: for( i=0; i < n; i++, virtAddr += PAGE_SIZE ) ! 104: { ! 105: IOPhysicalFromVirtual( (vm_task_t) kernel_map, (vm_address_t) virtAddr, &physAddr ); ! 106: if (physAddr != (physBase + i * PAGE_SIZE) ) ! 107: { ! 108: IOLog( "Ethernet(BMac): Cant allocate contiguous memory for DBDMA commands\n\r" ); ! 109: return NO; ! 110: } ! 111: } ! 112: ! 113: /* ! 114: * Setup the receive ring pointers ! 115: */ ! 116: rxDMACommands = (enet_dma_cmd_t *)dmaCommands; ! 117: rxMaxCommand = RX_RING_LENGTH; ! 118: ! 119: /* ! 120: * Setup the transmit ring pointers ! 121: */ ! 122: txDMACommands = (enet_txdma_cmd_t *)(dmaCommands + RX_RING_LENGTH * sizeof(enet_dma_cmd_t) + sizeof(IODBDMADescriptor)); ! 123: txMaxCommand = TX_RING_LENGTH; ! 124: ! 125: /* ! 126: * Setup pre-initialized DBDMA commands ! 127: */ ! 128: IOMakeDBDMADescriptor( (&dbdmaCmd_Nop), ! 129: kdbdmaNop, ! 130: kdbdmaKeyStream0, ! 131: kdbdmaIntNever, ! 132: kdbdmaBranchNever, ! 133: kdbdmaWaitNever, ! 134: 0, ! 135: 0 ); ! 136: ! 137: IOMakeDBDMADescriptor( (&dbdmaCmd_NopWInt), ! 138: kdbdmaNop, ! 139: kdbdmaKeyStream0, ! 140: kdbdmaIntAlways, ! 141: kdbdmaBranchNever, ! 142: kdbdmaWaitNever, ! 143: 0, ! 144: 0 ); ! 145: ! 146: IOMakeDBDMADescriptor( (&dbdmaCmd_LoadInt), ! 147: kdbdmaLoadQuad, ! 148: kdbdmaKeySystem, ! 149: kdbdmaIntNever, ! 150: kdbdmaBranchNever, ! 151: kdbdmaWaitNever, ! 152: 2, ! 153: ((int)ioBaseEnet + kSTAT) ); ! 154: ! 155: IOMakeDBDMADescriptor( (&dbdmaCmd_LoadIntWInt), ! 156: kdbdmaLoadQuad, ! 157: kdbdmaKeySystem, ! 158: kdbdmaIntAlways, ! 159: kdbdmaBranchNever, ! 160: kdbdmaWaitNever, ! 161: 2, ! 162: ((int)ioBaseEnet + kSTAT) ); ! 163: ! 164: IOMakeDBDMADescriptor( (&dbdmaCmd_Stop), ! 165: kdbdmaStop, ! 166: kdbdmaKeyStream0, ! 167: kdbdmaIntNever, ! 168: kdbdmaBranchNever, ! 169: kdbdmaWaitNever, ! 170: 0, ! 171: 0 ); ! 172: ! 173: IOMakeDBDMADescriptor( (&dbdmaCmd_Branch), ! 174: kdbdmaNop, ! 175: kdbdmaKeyStream0, ! 176: kdbdmaIntNever, ! 177: kdbdmaBranchAlways, ! 178: kdbdmaWaitNever, ! 179: 0, ! 180: 0 ); ! 181: ! 182: return YES; ! 183: } ! 184: ! 185: /*------------------------------------------------------------------------- ! 186: * ! 187: * Setup the Transmit Ring ! 188: * ----------------------- ! 189: * Each transmit ring entry consists of two words to transmit data from buffer ! 190: * segments (possibly) spanning a page boundary. This is followed by two DMA commands ! 191: * which read transmit frame status and interrupt status from the Bmac chip. The last ! 192: * DMA command in each transmit ring entry generates a host interrupt. ! 193: * The last entry in the ring is followed by a DMA branch to the first ! 194: * entry. ! 195: *-------------------------------------------------------------------------*/ ! 196: ! 197: - (BOOL)_initTxRing ! 198: { ! 199: BOOL kr; ! 200: u_int32_t i; ! 201: IODBDMADescriptor dbdmaCmd, dbdmaCmdInt; ! 202: ! 203: /* ! 204: * Clear the transmit DMA command memory ! 205: */ ! 206: bzero( (void *)txDMACommands, sizeof(enet_txdma_cmd_t) * txMaxCommand); ! 207: txCommandHead = 0; ! 208: txCommandTail = 0; ! 209: ! 210: /* ! 211: * Init the transmit queue. ! 212: */ ! 213: if (transmitQueue) ! 214: { ! 215: [transmitQueue free]; ! 216: } ! 217: ! 218: transmitQueue = [[IONetbufQueue alloc] initWithMaxCount:TRANSMIT_QUEUE_SIZE]; ! 219: if (!transmitQueue) ! 220: { ! 221: IOLog("Ethernet(BMac): Cant allocate transmit queue\n\r"); ! 222: return NO; ! 223: } ! 224: ! 225: /* ! 226: * DMA Channel commands 2 are the same for all DBDMA entries on transmit. ! 227: * Initialize them now. ! 228: */ ! 229: ! 230: dbdmaCmd = ( chipId >= kCHIPID_PaddingtonXmitStreaming ) ? dbdmaCmd_Nop : dbdmaCmd_LoadInt; ! 231: dbdmaCmdInt = ( chipId >= kCHIPID_PaddingtonXmitStreaming ) ? dbdmaCmd_NopWInt : dbdmaCmd_LoadIntWInt; ! 232: ! 233: for( i=0; i < txMaxCommand; i++ ) ! 234: { ! 235: txDMACommands[i].desc_seg[2] = ( (i+1) % TX_PKTS_PER_INT ) ? dbdmaCmd : dbdmaCmdInt; ! 236: } ! 237: ! 238: /* ! 239: * Put a DMA Branch command after the last entry in the transmit ring. Set the branch address ! 240: * to the physical address of the start of the transmit ring. ! 241: */ ! 242: txDMACommands[txMaxCommand].desc_seg[0] = dbdmaCmd_Branch; ! 243: ! 244: kr = IOPhysicalFromVirtual( (vm_task_t) IOVmTaskSelf(), (vm_address_t) txDMACommands, (u_int32_t *)&txDMACommandsPhys ); ! 245: if ( kr != IO_R_SUCCESS ) ! 246: { ! 247: IOLog( "Ethernet(BMac): Bad DBDMA command buf - %08x\n\r", (u_int32_t)txDMACommands ); ! 248: } ! 249: IOSetCCCmdDep( &txDMACommands[txMaxCommand].desc_seg[0], txDMACommandsPhys ); ! 250: ! 251: /* ! 252: * Set the Transmit DMA Channel pointer to the first entry in the transmit ring. ! 253: */ ! 254: IOSetDBDMACommandPtr( ioBaseEnetTxDMA, txDMACommandsPhys ); ! 255: ! 256: return YES; ! 257: } ! 258: ! 259: /*------------------------------------------------------------------------- ! 260: * ! 261: * Setup the Receive ring ! 262: * ---------------------- ! 263: * Each receive ring entry consists of two DMA commands to receive data ! 264: * into a network buffer (possibly) spanning a page boundary. The second ! 265: * DMA command in each entry generates a host interrupt. ! 266: * The last entry in the ring is followed by a DMA branch to the first ! 267: * entry. ! 268: * ! 269: *-------------------------------------------------------------------------*/ ! 270: ! 271: - (BOOL)_initRxRing ! 272: { ! 273: u_int32_t i; ! 274: BOOL status; ! 275: IOReturn kr; ! 276: ! 277: /* ! 278: * Clear the receive DMA command memory ! 279: */ ! 280: bzero( (void *)rxDMACommands, sizeof(enet_dma_cmd_t) * rxMaxCommand); ! 281: ! 282: kr = IOPhysicalFromVirtual( (vm_task_t) IOVmTaskSelf(), (vm_address_t) rxDMACommands, (u_int32_t *)&rxDMACommandsPhys ); ! 283: if ( kr != IO_R_SUCCESS ) ! 284: { ! 285: IOLog( "Ethernet(BMac): Bad DBDMA command buf - %08x\n\r", (u_int32_t)rxDMACommands ); ! 286: return NO; ! 287: } ! 288: ! 289: /* ! 290: * Allocate a receive buffer for each entry in the Receive ring ! 291: */ ! 292: for (i = 0; i < rxMaxCommand-1; i++) ! 293: { ! 294: if (rxNetbuf[i] == NULL) ! 295: { ! 296: rxNetbuf[i] = [self allocateNetbuf]; ! 297: if (rxNetbuf[i] == NULL) ! 298: { ! 299: IOLog("Ethernet(BMac): allocateNetbuf returned NULL in _initRxRing\n\r"); ! 300: return NO; ! 301: } ! 302: } ! 303: /* ! 304: * Set the DMA commands for the ring entry to transfer data to the NetBuf. ! 305: */ ! 306: status = [self _updateDescriptorFromNetBuf:rxNetbuf[i] Desc:(void *)&rxDMACommands[i] ReceiveFlag:YES ]; ! 307: if (status == NO) ! 308: { ! 309: IOLog("Ethernet(BMac): cant map Netbuf to physical memory in _initRxRing\n\r"); ! 310: return NO; ! 311: } ! 312: } ! 313: ! 314: /* ! 315: * Set the receive queue head to point to the first entry in the ring. Set the ! 316: * receive queue tail to point to a DMA Stop command after the last ring entry ! 317: */ ! 318: rxCommandHead = 0; ! 319: rxCommandTail = i; ! 320: ! 321: rxDMACommands[i].desc_seg[0] = dbdmaCmd_Stop; ! 322: rxDMACommands[i].desc_seg[1] = dbdmaCmd_Nop; ! 323: ! 324: /* ! 325: * Setup a DMA branch command after the stop command ! 326: */ ! 327: i++; ! 328: rxDMACommands[i].desc_seg[0] = dbdmaCmd_Branch; ! 329: ! 330: IOSetCCCmdDep( &rxDMACommands[i].desc_seg[0], rxDMACommandsPhys ); ! 331: ! 332: /* ! 333: * Set DMA command pointer to first receive entry ! 334: */ ! 335: IOSetDBDMACommandPtr (ioBaseEnetRxDMA, rxDMACommandsPhys); ! 336: ! 337: return YES; ! 338: } ! 339: ! 340: /*------------------------------------------------------------------------- ! 341: * ! 342: * ! 343: * ! 344: *-------------------------------------------------------------------------*/ ! 345: ! 346: - (void)_startChip ! 347: { ! 348: u_int16_t oldConfig; ! 349: ! 350: IODBDMAContinue( ioBaseEnetRxDMA ); ! 351: ! 352: // turn on rx plus any other bits already on (promiscuous possibly) ! 353: oldConfig = ReadBigMacRegister(ioBaseEnet, kRXCFG); ! 354: WriteBigMacRegister(ioBaseEnet, kRXCFG, oldConfig | kRxMACEnable ); ! 355: ! 356: oldConfig = ReadBigMacRegister(ioBaseEnet, kTXCFG); ! 357: WriteBigMacRegister(ioBaseEnet, kTXCFG, oldConfig | kTxMACEnable ); ! 358: } ! 359: ! 360: /*------------------------------------------------------------------------- ! 361: * ! 362: * ! 363: * ! 364: *-------------------------------------------------------------------------*/ ! 365: ! 366: - (void)_resetChip ! 367: { ! 368: volatile u_int32_t *heathrowFCR; ! 369: u_int32_t fcrValue; ! 370: u_int16_t *pPhyType; ! 371: ! 372: IODBDMAReset( ioBaseEnetRxDMA ); ! 373: IODBDMAReset( ioBaseEnetTxDMA ); ! 374: ! 375: IOSetDBDMAWaitSelect( ioBaseEnetTxDMA, IOSetDBDMAChannelControlBits( kdbdmaS5 ) ); ! 376: ! 377: IOSetDBDMABranchSelect( ioBaseEnetRxDMA, IOSetDBDMAChannelControlBits( kdbdmaS6 ) ); ! 378: IOSetDBDMAInterruptSelect( ioBaseEnetRxDMA, IOSetDBDMAChannelControlBits( kdbdmaS6 ) ); ! 379: ! 380: heathrowFCR = (u_int32_t *)((u_int8_t *)ioBaseHeathrow + kHeathrowFCR); ! 381: ! 382: fcrValue = *heathrowFCR; ! 383: eieio(); ! 384: ! 385: fcrValue = ReadSwap32( &fcrValue, 0 ); ! 386: ! 387: /* ! 388: * Enable the ethernet transceiver/clocks ! 389: */ ! 390: fcrValue |= kEnetEnabledBits; ! 391: fcrValue &= ~kResetEnetCell; ! 392: ! 393: *heathrowFCR = ReadSwap32( &fcrValue, 0 ); ! 394: eieio(); ! 395: IOSleep( 100 ); ! 396: ! 397: /* ! 398: * Determine if PHY chip is configured. Reset and enable it (if present). ! 399: */ ! 400: if ( phyId == 0xff ) ! 401: { ! 402: phyMIIDelay = 20; ! 403: if ( [self miiFindPHY:&phyId] == YES ) ! 404: { ! 405: [self miiResetPHY:phyId]; ! 406: ! 407: pPhyType = (u_int16_t *)&phyType; ! 408: [self miiReadWord: pPhyType reg: MII_ID0 phy:phyId]; ! 409: [self miiReadWord: pPhyType+1 reg: MII_ID1 phy:phyId]; ! 410: ! 411: if ( (phyType & MII_ST10040_MASK) == MII_ST10040_ID ) ! 412: { ! 413: phyMIIDelay = MII_ST10040_DELAY; ! 414: } ! 415: else if ( (phyType & MII_DP83843_MASK) == MII_DP83843_ID ) ! 416: { ! 417: phyMIIDelay = MII_DP83843_DELAY; ! 418: } ! 419: } ! 420: } ! 421: ! 422: /* ! 423: * Reset the reset the ethernet cell ! 424: */ ! 425: fcrValue |= kResetEnetCell; ! 426: *heathrowFCR = ReadSwap32( &fcrValue, 0 ); ! 427: eieio(); ! 428: IOSleep( 10 ); ! 429: ! 430: fcrValue &= ~kResetEnetCell; ! 431: *heathrowFCR = ReadSwap32( &fcrValue, 0 ); ! 432: eieio(); ! 433: IOSleep( 10 ); ! 434: ! 435: chipId = ReadBigMacRegister(ioBaseEnet, kCHIPID) & 0xFF; ! 436: ! 437: } ! 438: ! 439: /*------------------------------------------------------------------------- ! 440: * ! 441: * ! 442: * ! 443: *-------------------------------------------------------------------------*/ ! 444: ! 445: - (BOOL) _initChip ! 446: { ! 447: volatile u_int16_t regValue; ! 448: ns_time_t timeStamp; ! 449: u_int16_t *pWord16; ! 450: ! 451: WriteBigMacRegister(ioBaseEnet, kTXRST, kTxResetBit); ! 452: ! 453: do ! 454: { ! 455: regValue = ReadBigMacRegister(ioBaseEnet, kTXRST); // wait for reset to clear..acknowledge ! 456: } ! 457: while( regValue & kTxResetBit ); ! 458: ! 459: WriteBigMacRegister(ioBaseEnet, kRXRST, kRxResetValue); ! 460: ! 461: if ( phyId == 0xff ) ! 462: { ! 463: WriteBigMacRegister(ioBaseEnet, kXCVRIF, kClkBit | kSerialMode | kCOLActiveLow); ! 464: } ! 465: ! 466: IOGetTimestamp(&timeStamp); ! 467: WriteBigMacRegister(ioBaseEnet, kRSEED, (u_int16_t) timeStamp ); ! 468: ! 469: regValue = ReadBigMacRegister(ioBaseEnet, kXIFC); ! 470: regValue |= kTxOutputEnable; ! 471: WriteBigMacRegister(ioBaseEnet, kXIFC, regValue); ! 472: ! 473: ReadBigMacRegister(ioBaseEnet, kPAREG); ! 474: ! 475: // set collision counters to 0 ! 476: WriteBigMacRegister(ioBaseEnet, kNCCNT, 0); ! 477: WriteBigMacRegister(ioBaseEnet, kNTCNT, 0); ! 478: WriteBigMacRegister(ioBaseEnet, kEXCNT, 0); ! 479: WriteBigMacRegister(ioBaseEnet, kLTCNT, 0); ! 480: ! 481: // set rx counters to 0 ! 482: WriteBigMacRegister(ioBaseEnet, kFRCNT, 0); ! 483: WriteBigMacRegister(ioBaseEnet, kLECNT, 0); ! 484: WriteBigMacRegister(ioBaseEnet, kAECNT, 0); ! 485: WriteBigMacRegister(ioBaseEnet, kFECNT, 0); ! 486: WriteBigMacRegister(ioBaseEnet, kRXCV, 0); ! 487: ! 488: // set tx fifo information ! 489: WriteBigMacRegister(ioBaseEnet, kTXTH, 0xff); // 255 octets before tx starts ! 490: ! 491: WriteBigMacRegister(ioBaseEnet, kTXFIFOCSR, 0); // first disable txFIFO ! 492: WriteBigMacRegister(ioBaseEnet, kTXFIFOCSR, kTxFIFOEnable ); ! 493: ! 494: // set rx fifo information ! 495: WriteBigMacRegister(ioBaseEnet, kRXFIFOCSR, 0); // first disable rxFIFO ! 496: WriteBigMacRegister(ioBaseEnet, kRXFIFOCSR, kRxFIFOEnable ); ! 497: ! 498: //WriteBigMacRegister(ioBaseEnet, kTXCFG, kTxMACEnable); // kTxNeverGiveUp maybe later ! 499: ReadBigMacRegister(ioBaseEnet, kSTAT); // read it just to clear it ! 500: ! 501: // zero out the chip Hash Filter registers ! 502: WriteBigMacRegister(ioBaseEnet, kHASH3, hashTableMask[0]); // bits 15 - 0 ! 503: WriteBigMacRegister(ioBaseEnet, kHASH2, hashTableMask[1]); // bits 31 - 16 ! 504: WriteBigMacRegister(ioBaseEnet, kHASH1, hashTableMask[2]); // bits 47 - 32 ! 505: WriteBigMacRegister(ioBaseEnet, kHASH0, hashTableMask[3]); // bits 63 - 48 ! 506: ! 507: pWord16 = (u_int16_t *)&myAddress.ea_byte[0]; ! 508: WriteBigMacRegister(ioBaseEnet, kMADD0, *pWord16++); ! 509: WriteBigMacRegister(ioBaseEnet, kMADD1, *pWord16++); ! 510: WriteBigMacRegister(ioBaseEnet, kMADD2, *pWord16); ! 511: ! 512: WriteBigMacRegister(ioBaseEnet, kRXCFG, kRxCRCEnable | kRxHashFilterEnable | kRxRejectOwnPackets); ! 513: ! 514: return YES; ! 515: } ! 516: ! 517: /*------------------------------------------------------------------------- ! 518: * ! 519: * ! 520: * ! 521: *-------------------------------------------------------------------------*/ ! 522: ! 523: - (void) _disableAdapterInterrupts ! 524: { ! 525: WriteBigMacRegister( ioBaseEnet, kINTDISABLE, kNoEventsMask ); ! 526: } ! 527: ! 528: /*------------------------------------------------------------------------- ! 529: * ! 530: * ! 531: * ! 532: *-------------------------------------------------------------------------*/ ! 533: ! 534: - (void) _enableAdapterInterrupts ! 535: { ! 536: WriteBigMacRegister( ioBaseEnet, ! 537: kINTDISABLE, ! 538: ( chipId >= kCHIPID_PaddingtonXmitStreaming ) ? kNoEventsMask: kNormalIntEvents ); ! 539: } ! 540: ! 541: /*------------------------------------------------------------------------- ! 542: * ! 543: * ! 544: * ! 545: *-------------------------------------------------------------------------*/ ! 546: ! 547: - (void) _setDuplexMode: (BOOL) duplexMode ! 548: { ! 549: u_int16_t txCFGVal; ! 550: ! 551: isFullDuplex = duplexMode; ! 552: ! 553: txCFGVal = ReadBigMacRegister( ioBaseEnet, kTXCFG); ! 554: ! 555: WriteBigMacRegister( ioBaseEnet, kTXCFG, txCFGVal & ~kTxMACEnable ); ! 556: while( ReadBigMacRegister(ioBaseEnet, kTXCFG) & kTxMACEnable ) ! 557: ; ! 558: ! 559: if ( isFullDuplex ) ! 560: { ! 561: txCFGVal |= (kTxIgnoreCollision | kTxFullDuplex); ! 562: } ! 563: else ! 564: { ! 565: txCFGVal &= ~(kTxIgnoreCollision | kTxFullDuplex); ! 566: } ! 567: ! 568: WriteBigMacRegister( ioBaseEnet, kTXCFG, txCFGVal ); ! 569: } ! 570: ! 571: /*------------------------------------------------------------------------- ! 572: * ! 573: * ! 574: * ! 575: *-------------------------------------------------------------------------*/ ! 576: ! 577: - (void) _restartTransmitter ! 578: { ! 579: u_int16_t regValue; ! 580: ! 581: /* ! 582: * Shutdown DMA channel ! 583: */ ! 584: [self _stopTransmitDMA]; ! 585: ! 586: /* ! 587: * Get the silicon's attention ! 588: */ ! 589: WriteBigMacRegister( ioBaseEnet, kTXFIFOCSR, 0 ); ! 590: WriteBigMacRegister( ioBaseEnet, kTXFIFOCSR, kTxFIFOEnable ); ! 591: ! 592: ReadBigMacRegister( ioBaseEnet, kSTAT ); ! 593: ! 594: regValue = ReadBigMacRegister(ioBaseEnet, kTXCFG); ! 595: WriteBigMacRegister(ioBaseEnet, kTXCFG, regValue | kTxMACEnable ); ! 596: ! 597: /* ! 598: * Restart transmit DMA ! 599: */ ! 600: IODBDMAContinue( ioBaseEnetTxDMA ); ! 601: } ! 602: ! 603: /*------------------------------------------------------------------------- ! 604: * ! 605: * ! 606: * ! 607: *-------------------------------------------------------------------------*/ ! 608: ! 609: - (void) _restartReceiver ! 610: { ! 611: u_int16_t oldConfig; ! 612: ! 613: /* ! 614: * Shutdown DMA channel ! 615: */ ! 616: [self _stopReceiveDMA]; ! 617: ! 618: /* ! 619: * Get the silicon's attention ! 620: */ ! 621: WriteBigMacRegister( ioBaseEnet, kRXFIFOCSR, 0 ); ! 622: WriteBigMacRegister( ioBaseEnet, kRXFIFOCSR, kRxFIFOEnable ); ! 623: ! 624: oldConfig = ReadBigMacRegister(ioBaseEnet, kRXCFG); ! 625: WriteBigMacRegister(ioBaseEnet, kRXCFG, oldConfig | kRxMACEnable ); ! 626: ! 627: /* ! 628: * Restart receive DMA ! 629: */ ! 630: IODBDMAContinue( ioBaseEnetRxDMA ); ! 631: } ! 632: ! 633: /*------------------------------------------------------------------------- ! 634: * ! 635: * Orderly stop of receive DMA. ! 636: * ! 637: * ! 638: *-------------------------------------------------------------------------*/ ! 639: ! 640: - (void) _stopReceiveDMA ! 641: { ! 642: u_int32_t dmaCmdPtr; ! 643: u_int8_t rxCFGVal; ! 644: ! 645: /* ! 646: * Stop the receiver and allow any frame receive in progress to complete ! 647: */ ! 648: rxCFGVal = ReadBigMacRegister(ioBaseEnet, kRXCFG); ! 649: WriteBigMacRegister(ioBaseEnet, kRXCFG, rxCFGVal & ~kRxMACEnable ); ! 650: IODelay( RECEIVE_QUIESCE_uS * 1000 ); ! 651: ! 652: IODBDMAReset( ioBaseEnetRxDMA ); ! 653: ! 654: dmaCmdPtr = rxDMACommandsPhys + rxCommandHead * sizeof(enet_dma_cmd_t); ! 655: IOSetDBDMACommandPtr( ioBaseEnetRxDMA, dmaCmdPtr ); ! 656: } ! 657: ! 658: /*------------------------------------------------------------------------- ! 659: * ! 660: * ! 661: * ! 662: *-------------------------------------------------------------------------*/ ! 663: ! 664: - (void) _stopTransmitDMA ! 665: { ! 666: u_int32_t dmaCmdPtr; ! 667: u_int8_t txCFGVal; ! 668: ! 669: /* ! 670: * Stop the transmitter and allow any frame transmit in progress to abort ! 671: */ ! 672: txCFGVal = ReadBigMacRegister(ioBaseEnet, kTXCFG); ! 673: WriteBigMacRegister(ioBaseEnet, kTXCFG, txCFGVal & ~kTxMACEnable ); ! 674: ! 675: IODelay( TRANSMIT_QUIESCE_uS * 1000 ); ! 676: ! 677: IODBDMAReset( ioBaseEnetTxDMA ); ! 678: ! 679: dmaCmdPtr = txDMACommandsPhys + txCommandHead * sizeof(enet_txdma_cmd_t); ! 680: IOSetDBDMACommandPtr( ioBaseEnetTxDMA, dmaCmdPtr ); ! 681: } ! 682: ! 683: /*------------------------------------------------------------------------- ! 684: * ! 685: * ! 686: * ! 687: *-------------------------------------------------------------------------*/ ! 688: ! 689: - (BOOL)_transmitPacket:(netbuf_t)packet ! 690: { ! 691: enet_dma_cmd_t tmpCommand; ! 692: u_int32_t i; ! 693: ! 694: [self performLoopback:packet]; ! 695: ! 696: /* ! 697: * Check for room on the transmit ring. There should always be space since it is ! 698: * the responsibility of the caller to verify this before calling _transmitPacket. ! 699: */ ! 700: i = txCommandTail + 1; ! 701: if ( i >= txMaxCommand ) i = 0; ! 702: if ( i == txCommandHead ) ! 703: { ! 704: IOLog("Ethernet(BMac): Freeing transmit packet eh?\n\r"); ! 705: nb_free(packet); ! 706: return NO; ! 707: } ! 708: ! 709: /* ! 710: * txCommandTail points to the current DMA Stop command for the channel. We are ! 711: * now creating a new DMA Stop command in the next slot in the transmit ring. The ! 712: * previous DMA Stop command will be overwritten with the DMA commands to ! 713: * transfer the new NetBuf. ! 714: */ ! 715: txDMACommands[i].desc_seg[0] = dbdmaCmd_Stop; ! 716: txDMACommands[i].desc_seg[1] = dbdmaCmd_Nop; ! 717: ! 718: /* ! 719: * Get a copy of the DMA transfer commands in a temporary buffer. ! 720: * The new DMA command is written into the channel program so that the command ! 721: * word for the old Stop command is overwritten last. This prevents the DMA ! 722: * engine from executing a partially written channel command. ! 723: */ ! 724: [self _updateDescriptorFromNetBuf:packet Desc:&tmpCommand ReceiveFlag:NO]; ! 725: ! 726: bcopy( ((u_int32_t *)&tmpCommand)+1, ! 727: ((u_int32_t *)&txDMACommands[txCommandTail])+1, ! 728: sizeof(enet_dma_cmd_t)-sizeof(u_int32_t) ); ! 729: ! 730: txNetbuf[txCommandTail] = packet; ! 731: txDMACommands[txCommandTail].desc_seg[0].operation = tmpCommand.desc_seg[0].operation; ! 732: ! 733: /* ! 734: * Set the transmit tail to the new stop command. ! 735: */ ! 736: txCommandTail = i; ! 737: ! 738: /* ! 739: * Tap the DMA channel to wake it up ! 740: */ ! 741: IODBDMAContinue( ioBaseEnetTxDMA ); ! 742: ! 743: return YES; ! 744: } ! 745: ! 746: /*------------------------------------------------------------------------- ! 747: * _receivePacket ! 748: * -------------- ! 749: * This routine runs the receiver in polled-mode (yuk!) for the kernel debugger. ! 750: * ! 751: * The _receivePackets allocate NetBufs and pass them up the stack. The kernel ! 752: * debugger interface passes a buffer into us. To reconsile the two interfaces, ! 753: * we allow the receive routine to continue to allocate its own buffers and ! 754: * transfer any received data to the passed-in buffer. This is handled by ! 755: * _receivePacket calling _packetToDebugger. ! 756: *-------------------------------------------------------------------------*/ ! 757: ! 758: - (void)_receivePacket:(void *)pkt length:(unsigned int *)pkt_len timeout:(unsigned int)timeout ! 759: { ! 760: ns_time_t startTime; ! 761: ns_time_t currentTime; ! 762: u_int32_t elapsedTimeMS; ! 763: ! 764: *pkt_len = 0; ! 765: ! 766: if (resetAndEnabled == NO) ! 767: return; ! 768: ! 769: [self disableAllInterrupts]; ! 770: ! 771: debuggerPkt = pkt; ! 772: debuggerPktSize = 0; ! 773: ! 774: IOGetTimestamp(&startTime); ! 775: do ! 776: { ! 777: [self _receivePackets:YES]; ! 778: IOGetTimestamp(¤tTime); ! 779: elapsedTimeMS = (currentTime - startTime) / (1000*1000); ! 780: } ! 781: while ( (debuggerPktSize == 0) && (elapsedTimeMS < timeout) ); ! 782: ! 783: *pkt_len = debuggerPktSize; ! 784: ! 785: [self enableAllInterrupts]; ! 786: ! 787: return; ! 788: } ! 789: ! 790: /*------------------------------------------------------------------------- ! 791: * _packetToDebugger ! 792: * ----------------- ! 793: * This is called by _receivePackets when we are polling for kernel debugger ! 794: * packets. It copies the NetBuf contents to the buffer passed by the debugger. ! 795: * It also sets the var debuggerPktSize which will break the polling loop. ! 796: *-------------------------------------------------------------------------*/ ! 797: ! 798: -(void) _packetToDebugger: (netbuf_t) packet ! 799: { ! 800: debuggerPktSize = nb_size(packet); ! 801: bcopy( nb_map(packet), debuggerPkt, debuggerPktSize ); ! 802: ! 803: nb_free( packet ); ! 804: } ! 805: ! 806: /*------------------------------------------------------------------------- ! 807: * _sendPacket ! 808: * ----------- ! 809: * ! 810: * This routine runs the transmitter in polled-mode (yuk!) for the kernel debugger. ! 811: * ! 812: *-------------------------------------------------------------------------*/ ! 813: ! 814: - (void)_sendPacket:(void *)pkt length:(unsigned int)pkt_len ! 815: { ! 816: ns_time_t startTime; ! 817: ns_time_t currentTime; ! 818: u_int32_t elapsedTimeMS; ! 819: int size; ! 820: ! 821: if (resetAndEnabled == NO) ! 822: return; ! 823: ! 824: [self disableAllInterrupts]; ! 825: ! 826: /* ! 827: * Wait for the transmit ring to empty ! 828: */ ! 829: IOGetTimestamp(&startTime); ! 830: do ! 831: { ! 832: [self _transmitInterruptOccurred]; ! 833: IOGetTimestamp(¤tTime); ! 834: elapsedTimeMS = (currentTime - startTime) / (1000*1000); ! 835: } ! 836: while ( (txCommandHead != txCommandTail) && (elapsedTimeMS < TX_KDB_TIMEOUT) ); ! 837: ! 838: if ( txCommandHead != txCommandTail ) ! 839: { ! 840: IOLog( "Ethernet(BMac): Polled tranmit timeout - 1\n\r"); ! 841: return; ! 842: } ! 843: ! 844: /* ! 845: * Allocate a NetBuf and copy the debugger transmit data into it ! 846: */ ! 847: debuggerPkt = [self allocateNetbuf]; ! 848: bcopy(pkt, nb_map(debuggerPkt), pkt_len); ! 849: size = nb_size(debuggerPkt); ! 850: nb_shrink_bot(debuggerPkt, size - pkt_len); ! 851: ! 852: /* ! 853: * Send the debugger packet. _transmitPacket will free the Netbuf we allocated ! 854: * above. ! 855: */ ! 856: [self _transmitPacket: debuggerPkt]; ! 857: ! 858: /* ! 859: * Poll waiting for the transmit ring to empty again ! 860: */ ! 861: do ! 862: { ! 863: [self _transmitInterruptOccurred]; ! 864: IOGetTimestamp(¤tTime); ! 865: elapsedTimeMS = (currentTime - startTime) / (1000*1000); ! 866: } ! 867: while ( (txCommandHead != txCommandTail) && (elapsedTimeMS < TX_KDB_TIMEOUT) ); ! 868: ! 869: if ( txCommandHead != txCommandTail ) ! 870: { ! 871: IOLog( "Ethernet(BMac): Polled tranmit timeout - 2\n\r"); ! 872: } ! 873: ! 874: [self enableAllInterrupts]; ! 875: ! 876: return; ! 877: } ! 878: ! 879: /*------------------------------------------------------------------------- ! 880: * _sendDummyPacket ! 881: * ---------------- ! 882: * The BMac receiver seems to be locked until we send our first packet. ! 883: * ! 884: *-------------------------------------------------------------------------*/ ! 885: - (void) _sendDummyPacket ! 886: { ! 887: union ! 888: { ! 889: u_int8_t bytes[64]; ! 890: enet_addr_t enet_addr[2]; ! 891: } dummyPacket; ! 892: ! 893: bzero( &dummyPacket, sizeof(dummyPacket) ); ! 894: dummyPacket.enet_addr[0] = myAddress; ! 895: dummyPacket.enet_addr[1] = myAddress; ! 896: [self _sendPacket:(void *)&dummyPacket length:sizeof(dummyPacket)]; ! 897: } ! 898: ! 899: ! 900: ! 901: /*------------------------------------------------------------------------- ! 902: * ! 903: * ! 904: * ! 905: *-------------------------------------------------------------------------*/ ! 906: ! 907: - (BOOL)_receiveInterruptOccurred ! 908: { ! 909: [self _receivePackets:NO]; ! 910: ! 911: return YES; ! 912: } ! 913: ! 914: /*------------------------------------------------------------------------- ! 915: * ! 916: * ! 917: * ! 918: *-------------------------------------------------------------------------*/ ! 919: ! 920: - (BOOL)_receivePackets:(BOOL)fDebugger ! 921: { ! 922: enet_dma_cmd_t tmpCommand; ! 923: netbuf_t packet, newPacket; ! 924: u_int32_t i,j,last; ! 925: int receivedFrameSize = 0; ! 926: u_int32_t dmaCount[2], dmaResid[2], dmaStatus[2]; ! 927: u_int32_t dmaChnlStatus; ! 928: u_int16_t rxPktStatus = 0; ! 929: u_int32_t badFrameCount; ! 930: BOOL passPacketUp; ! 931: BOOL reusePkt; ! 932: BOOL status; ! 933: u_int32_t nextDesc; ! 934: ! 935: last = -1; ! 936: i = rxCommandHead; ! 937: ! 938: while ( 1 ) ! 939: { ! 940: passPacketUp = NO; ! 941: reusePkt = NO; ! 942: ! 943: /* ! 944: * Collect the DMA residual counts/status for the two buffer segments. ! 945: */ ! 946: for ( j = 0; j < 2; j++ ) ! 947: { ! 948: dmaResid[j] = IOGetCCResult( &rxDMACommands[i].desc_seg[j] ); ! 949: dmaStatus[j] = dmaResid[j] >> 16; ! 950: dmaResid[j] &= 0x0000ffff; ! 951: dmaCount[j] = IOGetCCOperation( &rxDMACommands[i].desc_seg[j] ) & kdbdmaReqCountMask; ! 952: } ! 953: ! 954: #if 0 ! 955: IOLog("Ethernet(BMac): Rx NetBuf[%2d] = %08x Resid[0] = %04x Status[0] = %04x Resid[1] = %04x Status[1] = %04x\n\r", ! 956: i, (int)nb_map(rxNetbuf[i]), dmaResid[0], dmaStatus[0], dmaResid[1], dmaStatus[1] ); ! 957: #endif ! 958: ! 959: /* ! 960: * If the current entry has not been written, then stop at this entry ! 961: */ ! 962: if ( !((dmaStatus[0] & kdbdmaBt) || (dmaStatus[1] & kdbdmaActive)) ) ! 963: { ! 964: break; ! 965: } ! 966: ! 967: /* ! 968: * The BMac Ethernet controller appends two bytes to each receive buffer containing the buffer ! 969: * size and receive frame status. ! 970: * We locate these bytes by using the DMA residual counts. ! 971: */ ! 972: receivedFrameSize = dmaCount[0] - dmaResid[0] + dmaCount[1] - ((dmaStatus[0] & kdbdmaBt) ? dmaCount[1] : dmaResid[1]); ! 973: ! 974: if ( receivedFrameSize >= 2 ) ! 975: { ! 976: /* ! 977: * Get the receive frame size as reported by the BMac controller ! 978: */ ! 979: rxPktStatus = *(u_int16_t *)((u_int32_t)nb_map(rxNetbuf[i]) + receivedFrameSize - 2); ! 980: receivedFrameSize = rxPktStatus & kRxLengthMask; ! 981: } ! 982: ! 983: /* ! 984: * Reject packets that are runts or that have other mutations. ! 985: */ ! 986: if ( receivedFrameSize < (ETHERMINPACKET - ETHERCRC) || ! 987: receivedFrameSize > (ETHERMAXPACKET + ETHERCRC) || ! 988: rxPktStatus & kRxAbortBit ) ! 989: { ! 990: reusePkt = YES; ! 991: } ! 992: ! 993: packet = rxNetbuf[i]; ! 994: ! 995: /* ! 996: * If we are not accepting all packets, then check for multicast packets that got past the ! 997: * logical address filter but were not wanted. ! 998: */ ! 999: if ( !isPromiscuous && [super isUnwantedMulticastPacket: (ether_header_t *)nb_map(packet)] == YES ) ! 1000: { ! 1001: reusePkt = YES; ! 1002: } ! 1003: ! 1004: /* ! 1005: * Before we pass this packet up the networking stack. Make sure we can get a replacement. ! 1006: * Otherwise, hold on to the current packet and increment the input error count. ! 1007: * Thanks Justin! ! 1008: */ ! 1009: if ( reusePkt == NO ) ! 1010: { ! 1011: newPacket = [self allocateNetbuf]; ! 1012: if ( newPacket == NULL ) ! 1013: { ! 1014: reusePkt = YES; ! 1015: [networkInterface incrementInputErrors]; ! 1016: } ! 1017: } ! 1018: ! 1019: /* ! 1020: * Install the new Netbuf for the one we're about to pass to the network stack ! 1021: */ ! 1022: ! 1023: if ( reusePkt == NO ) ! 1024: { ! 1025: rxNetbuf[i] = newPacket; ! 1026: passPacketUp = YES; ! 1027: status = [self _updateDescriptorFromNetBuf:rxNetbuf[i] Desc:(void *)&rxDMACommands[i] ReceiveFlag:YES]; ! 1028: if (status == NO) ! 1029: { ! 1030: IOLog("Ethernet(BMac): _updateDescriptorFromNetBuf failed for receive\n"); ! 1031: } ! 1032: /* Adjust to size received */ ! 1033: nb_shrink_bot(packet, nb_size(packet) - receivedFrameSize); ! 1034: } ! 1035: /* ! 1036: * If we are reusing the existing Netbuf, then refurbish the existing DMA command \ ! 1037: * descriptors by clearing the status/residual count fields. ! 1038: */ ! 1039: else ! 1040: { ! 1041: for ( j=0; j < sizeof(enet_dma_cmd_t)/sizeof(IODBDMADescriptor); j++ ) ! 1042: { ! 1043: IOSetCCResult( &rxDMACommands[i].desc_seg[j], 0 ); ! 1044: } ! 1045: } ! 1046: ! 1047: /* ! 1048: * Keep track of the last receive descriptor processed ! 1049: */ ! 1050: last = i; ! 1051: ! 1052: /* ! 1053: * Implement ring wrap-around ! 1054: */ ! 1055: if (++i >= rxMaxCommand) i = 0; ! 1056: ! 1057: /* ! 1058: * Transfer received packet to debugger or network ! 1059: */ ! 1060: if (passPacketUp) ! 1061: { ! 1062: if ( fDebugger == NO ) ! 1063: { ! 1064: // IOLog("Ethernet(Bmac): Packet from network - %08x %d\n", (int) packet, (int)nb_size(packet) ); ! 1065: KERNEL_DEBUG(DBG_BMAC_RXCOMPLETE | DBG_FUNC_NONE, (int) packet, (int)nb_size(packet), 0, 0, 0 ); ! 1066: [networkInterface handleInputPacket:packet extra:0]; ! 1067: } ! 1068: else ! 1069: { ! 1070: // IOLog("Ethernet(BMac): Packet to debugger - %08x %d\n", (int) packet, (int)nb_size(packet) ); ! 1071: [self _packetToDebugger: packet]; ! 1072: break; ! 1073: } ! 1074: } ! 1075: } ! 1076: ! 1077: /* ! 1078: * OK...this is a little messy ! 1079: * ! 1080: * We just processed a bunch of DMA receive descriptors. We are going to exchange the ! 1081: * current DMA stop command (rxCommandTail) with the last receive descriptor we ! 1082: * processed (last). This will make these list of descriptors we just processed available. ! 1083: * If we processed no receive descriptors on this call then skip this exchange. ! 1084: */ ! 1085: ! 1086: #if 0 ! 1087: IOLog( "Ethernet(BMac): Prev - Rx Head = %2d Rx Tail = %2d Rx Last = %2d\n\r", rxCommandHead, rxCommandTail, last ); ! 1088: #endif ! 1089: ! 1090: if ( last != -1 ) ! 1091: { ! 1092: /* ! 1093: * Save the contents of the last receive descriptor processed. ! 1094: */ ! 1095: newPacket = rxNetbuf[last]; ! 1096: tmpCommand = rxDMACommands[last]; ! 1097: ! 1098: /* ! 1099: * Write a DMA stop command into this descriptor slot ! 1100: */ ! 1101: rxDMACommands[last].desc_seg[0] = dbdmaCmd_Stop; ! 1102: rxDMACommands[last].desc_seg[1] = dbdmaCmd_Nop; ! 1103: rxNetbuf[last] = 0; ! 1104: ! 1105: /* ! 1106: * Replace the previous DMA stop command with the last receive descriptor processed. ! 1107: * ! 1108: * The new DMA command is written into the channel program so that the command ! 1109: * word for the old Stop command is overwritten last. This prevents the DMA ! 1110: * engine from executing a partially written channel command. ! 1111: * ! 1112: * Note: When relocating the descriptor, we must update its branch field to reflect its ! 1113: * new location. ! 1114: */ ! 1115: nextDesc = rxDMACommandsPhys + (int)&rxDMACommands[rxCommandTail+1] - (int)rxDMACommands; ! 1116: IOSetCCCmdDep( &tmpCommand.desc_seg[0], nextDesc ); ! 1117: ! 1118: ! 1119: bcopy( (u_int32_t *)&tmpCommand+1, ! 1120: (u_int32_t *)&rxDMACommands[rxCommandTail]+1, ! 1121: sizeof(enet_dma_cmd_t)-sizeof(u_int32_t) ); ! 1122: ! 1123: rxNetbuf[rxCommandTail] = newPacket; ! 1124: ! 1125: rxDMACommands[rxCommandTail].desc_seg[0].operation = tmpCommand.desc_seg[0].operation; ! 1126: ! 1127: /* ! 1128: * Update rxCommmandTail to point to the new Stop command. Update rxCommandHead to point to ! 1129: * the next slot in the ring past the Stop command ! 1130: */ ! 1131: rxCommandTail = last; ! 1132: rxCommandHead = i; ! 1133: } ! 1134: ! 1135: /* ! 1136: * Update receive error statistics ! 1137: */ ! 1138: badFrameCount = ReadBigMacRegister(ioBaseEnet, kFECNT) ! 1139: + ReadBigMacRegister(ioBaseEnet, kAECNT) ! 1140: + ReadBigMacRegister(ioBaseEnet, kLECNT); ! 1141: /* ! 1142: * Clear Hardware counters ! 1143: */ ! 1144: WriteBigMacRegister(ioBaseEnet, kFECNT, 0); ! 1145: WriteBigMacRegister(ioBaseEnet, kAECNT, 0); ! 1146: WriteBigMacRegister(ioBaseEnet, kLECNT, 0); ! 1147: ! 1148: [networkInterface incrementInputErrorsBy: badFrameCount]; ! 1149: ! 1150: /* ! 1151: * Check for error conditions that may cause the receiver to stall ! 1152: */ ! 1153: dmaChnlStatus = IOGetDBDMAChannelStatus( ioBaseEnetRxDMA ); ! 1154: ! 1155: if ( dmaChnlStatus & kdbdmaDead ) ! 1156: { ! 1157: ! 1158: [networkInterface incrementInputErrors]; ! 1159: ! 1160: IOLog( "Ethernet(Bmac): Rx DMA Error - Status = %04x\n\r", dmaChnlStatus ); ! 1161: [self _restartReceiver]; ! 1162: } ! 1163: else ! 1164: { ! 1165: /* ! 1166: * Tap the DMA to wake it up ! 1167: */ ! 1168: IODBDMAContinue( ioBaseEnetRxDMA ); ! 1169: } ! 1170: #if 0 ! 1171: IOLog( "Ethernet(Mace): New - Rx Head = %2d Rx Tail = %2d\n\r", rxCommandHead, rxCommandTail ); ! 1172: #endif ! 1173: ! 1174: ! 1175: return YES; ! 1176: } ! 1177: ! 1178: /*------------------------------------------------------------------------- ! 1179: * ! 1180: * ! 1181: * ! 1182: *-------------------------------------------------------------------------*/ ! 1183: ! 1184: - (BOOL)_transmitInterruptOccurred ! 1185: { ! 1186: u_int32_t dmaStatus; ! 1187: u_int32_t badFrameCount; ! 1188: BOOL fServiced = NO; ! 1189: ! 1190: while ( 1 ) ! 1191: { ! 1192: /* ! 1193: * Check the status of the last descriptor in this entry to see if the DMA engine completed ! 1194: * this entry. ! 1195: */ ! 1196: dmaStatus = IOGetCCResult( &txDMACommands[txCommandHead].desc_seg[1] ) >> 16; ! 1197: if ( !(dmaStatus & kdbdmaActive) ) ! 1198: { ! 1199: break; ! 1200: } ! 1201: ! 1202: [networkInterface incrementOutputPackets]; ! 1203: ! 1204: fServiced = YES; ! 1205: ! 1206: /* ! 1207: * Free the Netbuf we just transmitted ! 1208: */ ! 1209: KERNEL_DEBUG(DBG_BMAC_TXCOMPLETE | DBG_FUNC_NONE, (int) txNetbuf[txCommandHead], (int) nb_size(txNetbuf[txCommandHead]), 0, 0, 0 ); ! 1210: nb_free( txNetbuf[txCommandHead] ); ! 1211: txNetbuf[txCommandHead] = NULL; ! 1212: ! 1213: if ( ++txCommandHead >= txMaxCommand ) txCommandHead = 0; ! 1214: } ! 1215: ! 1216: /* ! 1217: * Increment transmit error statistics ! 1218: */ ! 1219: badFrameCount = ReadBigMacRegister(ioBaseEnet, kNCCNT ); ! 1220: ! 1221: WriteBigMacRegister( ioBaseEnet, kNCCNT, 0 ); ! 1222: ! 1223: [networkInterface incrementCollisionsBy: badFrameCount]; ! 1224: ! 1225: badFrameCount = ReadBigMacRegister(ioBaseEnet, kEXCNT ) ! 1226: + ReadBigMacRegister(ioBaseEnet, kLTCNT ); ! 1227: ! 1228: WriteBigMacRegister( ioBaseEnet, kEXCNT, 0 ); ! 1229: WriteBigMacRegister( ioBaseEnet, kLTCNT, 0 ); ! 1230: ! 1231: [networkInterface incrementOutputErrorsBy: badFrameCount]; ! 1232: ! 1233: /* ! 1234: * Check for error conditions that may cause the transmitter to stall ! 1235: */ ! 1236: dmaStatus = IOGetDBDMAChannelStatus( ioBaseEnetTxDMA ); ! 1237: ! 1238: if ( dmaStatus & kdbdmaDead ) ! 1239: { ! 1240: [networkInterface incrementOutputErrors]; ! 1241: ! 1242: IOLog( "Ethernet(Bmac): Tx DMA Error - Status = %04x\n\r", dmaStatus ); ! 1243: [self _restartTransmitter]; ! 1244: ! 1245: fServiced = YES; ! 1246: } ! 1247: ! 1248: return fServiced; ! 1249: } ! 1250: ! 1251: /* ! 1252: * Breaks up an ethernet data buffer into two physical chunks. We know that ! 1253: * the buffer can't straddle more than two pages. If the content of paddr2 is ! 1254: * zero this means that all of the buffer lies in one physical page. Note ! 1255: * that we use the fact that tx and rx descriptors have the same size and ! 1256: * same layout of relevent fields (data address and count). ! 1257: */ ! 1258: ! 1259: -(BOOL) _updateDescriptorFromNetBuf:(netbuf_t)nb Desc:(enet_dma_cmd_t *)desc ReceiveFlag:(BOOL)isReceive ! 1260: { ! 1261: IOReturn result; ! 1262: vm_address_t pageBreak; ! 1263: vm_address_t vaddr; ! 1264: u_int32_t paddr[2]; ! 1265: u_int32_t len[2]; ! 1266: u_int32_t size; ! 1267: u_int32_t nextDesc = 0; ! 1268: u_int32_t waitMask = 0; ! 1269: ! 1270: size = isReceive ? NETWORK_BUFSIZE : nb_size(nb); ! 1271: vaddr = (vm_address_t)nb_map(nb); ! 1272: ! 1273: result = IOPhysicalFromVirtual(IOVmTaskSelf(), vaddr, &paddr[0]); ! 1274: if (result != IO_R_SUCCESS) ! 1275: { ! 1276: return NO; ! 1277: } ! 1278: ! 1279: /* ! 1280: * Now check if this memory block crosses a page boundary. ! 1281: */ ! 1282: if (trunc_page(vaddr) != trunc_page(vaddr+size-1)) ! 1283: { ! 1284: /* Nice try... */ ! 1285: pageBreak = round_page(vaddr); ! 1286: len[0] = pageBreak - vaddr; ! 1287: len[1] = size - (pageBreak - vaddr); ! 1288: ! 1289: result = IOPhysicalFromVirtual(IOVmTaskSelf(), pageBreak, &paddr[1]); ! 1290: if (result != IO_R_SUCCESS) ! 1291: { ! 1292: return NO; ! 1293: } ! 1294: } ! 1295: else ! 1296: { ! 1297: paddr[1] = 0; ! 1298: len[0] = size; ! 1299: len[1] = 0; ! 1300: } ! 1301: ! 1302: if ( isReceive || chipId >= kCHIPID_PaddingtonXmitStreaming ) ! 1303: { ! 1304: waitMask = kdbdmaWaitNever; ! 1305: } ! 1306: else ! 1307: { ! 1308: waitMask = kdbdmaWaitIfFalse; ! 1309: } ! 1310: ! 1311: if ( !len[1] ) ! 1312: { ! 1313: IOMakeDBDMADescriptor( (&desc->desc_seg[0]), ! 1314: ((isReceive) ? kdbdmaInputLast : kdbdmaOutputLast), ! 1315: (kdbdmaKeyStream0), ! 1316: (kdbdmaIntNever), ! 1317: (kdbdmaBranchNever), ! 1318: (waitMask), ! 1319: (len[0]), ! 1320: (paddr[0]) ); ! 1321: ! 1322: desc->desc_seg[1] = (isReceive) ? dbdmaCmd_NopWInt : dbdmaCmd_Nop; ! 1323: } ! 1324: else ! 1325: { ! 1326: if ( isReceive ) ! 1327: { ! 1328: nextDesc = rxDMACommandsPhys + (int)desc - (int)rxDMACommands + sizeof(enet_dma_cmd_t); ! 1329: } ! 1330: ! 1331: IOMakeDBDMADescriptorDep( (&desc->desc_seg[0]), ! 1332: ((isReceive) ? kdbdmaInputMore : kdbdmaOutputMore), ! 1333: (kdbdmaKeyStream0), ! 1334: ((isReceive) ? kdbdmaIntIfTrue : kdbdmaIntNever), ! 1335: ((isReceive) ? kdbdmaBranchIfTrue : kdbdmaBranchNever), ! 1336: (kdbdmaWaitNever), ! 1337: (len[0]), ! 1338: (paddr[0]), ! 1339: nextDesc ); ! 1340: ! 1341: IOMakeDBDMADescriptor( (&desc->desc_seg[1]), ! 1342: ((isReceive) ? kdbdmaInputLast : kdbdmaOutputLast), ! 1343: (kdbdmaKeyStream0), ! 1344: ((isReceive) ? kdbdmaIntAlways : kdbdmaIntNever), ! 1345: (kdbdmaBranchNever), ! 1346: (waitMask), ! 1347: (len[1]), ! 1348: (paddr[1]) ); ! 1349: } ! 1350: ! 1351: return YES; ! 1352: } ! 1353: ! 1354: #ifdef DEBUG ! 1355: /* ! 1356: * Useful for testing. ! 1357: */ ! 1358: - (void)_dump_srom ! 1359: { ! 1360: unsigned short data; ! 1361: int i; ! 1362: ! 1363: for (i = 0; i < 128; i++) ! 1364: { ! 1365: reset_and_select_srom(ioBaseEnet); ! 1366: data = read_srom(ioBaseEnet, i, sromAddressBits); ! 1367: IOLog("Ethernet(BMac): %x = %x ", i, data); ! 1368: if (i % 10 == 0) IOLog("\n"); ! 1369: } ! 1370: } ! 1371: ! 1372: - (void)_dumpDesc:(void *)addr Size:(u_int32_t)size ! 1373: { ! 1374: u_int32_t i; ! 1375: unsigned long *p; ! 1376: vm_offset_t paddr; ! 1377: ! 1378: IOPhysicalFromVirtual( IOVmTaskSelf(), (vm_offset_t) addr, (vm_offset_t *)&paddr ); ! 1379: ! 1380: p = (unsigned long *)addr; ! 1381: ! 1382: for ( i=0; i < size/sizeof(IODBDMADescriptor); i++, p+=4, paddr+=sizeof(IODBDMADescriptor) ) ! 1383: { ! 1384: IOLog("Ethernet(BMac): %08x(v) %08x(p): %08x %08x %08x %08x\n\r", ! 1385: (int)p, ! 1386: (int)paddr, ! 1387: (int)ReadSwap32(p, 0), (int)ReadSwap32(p, 4), ! 1388: (int)ReadSwap32(p, 8), (int)ReadSwap32(p, 12) ); ! 1389: } ! 1390: } ! 1391: ! 1392: - (void)_dumpRegisters ! 1393: { ! 1394: u_int16_t dataValue; ! 1395: ! 1396: IOLog("\nEthernet(BMac): IO Address = %08x", (int)ioBaseEnet ); ! 1397: ! 1398: dataValue = ReadBigMacRegister(ioBaseEnet, kXIFC); ! 1399: IOLog("\nEthernet(BMac): Read Register %04x Transceiver I/F = %04x", kXIFC, dataValue ); ! 1400: ! 1401: dataValue = ReadBigMacRegister(ioBaseEnet, kSTAT); ! 1402: IOLog("\nEthernet(BMac): Read Register %04x Int Events = %04x", kSTAT, dataValue ); ! 1403: ! 1404: dataValue = ReadBigMacRegister(ioBaseEnet, kINTDISABLE); ! 1405: IOLog("\nEthernet(BMac): Read Register %04x Int Disable = %04x", kINTDISABLE, dataValue ); ! 1406: ! 1407: dataValue = ReadBigMacRegister(ioBaseEnet, kTXRST); ! 1408: IOLog("\nEthernet(BMac): Read Register %04x Tx Reset = %04x", kTXRST, dataValue ); ! 1409: ! 1410: dataValue = ReadBigMacRegister(ioBaseEnet, kTXCFG); ! 1411: IOLog("\nEthernet(BMac): Read Register %04x Tx Config = %04x", kTXCFG, dataValue ); ! 1412: IOLog("\nEthernet(BMac): -------------------------------------------------------" ); ! 1413: ! 1414: dataValue = ReadBigMacRegister(ioBaseEnet, kIPG1); ! 1415: IOLog("\nEthernet(BMac): Read Register %04x IPG1 = %04x", kIPG1, dataValue ); ! 1416: ! 1417: dataValue = ReadBigMacRegister(ioBaseEnet, kIPG2); ! 1418: IOLog("\nEthernet(BMac): Read Register %04x IPG2 = %04x", kIPG2, dataValue ); ! 1419: ! 1420: dataValue = ReadBigMacRegister(ioBaseEnet, kALIMIT); ! 1421: IOLog("\nEthernet(BMac): Read Register %04x Attempt Limit = %04x", kALIMIT, dataValue ); ! 1422: ! 1423: dataValue = ReadBigMacRegister(ioBaseEnet, kSLOT); ! 1424: IOLog("\nEthernet(BMac): Read Register %04x Slot Time = %04x", kSLOT, dataValue ); ! 1425: ! 1426: dataValue = ReadBigMacRegister(ioBaseEnet, kPALEN); ! 1427: IOLog("\nEthernet(BMac): Read Register %04x Preamble Length = %04x", kPALEN, dataValue ); ! 1428: ! 1429: IOLog("\nEthernet(BMac): -------------------------------------------------------" ); ! 1430: dataValue = ReadBigMacRegister(ioBaseEnet, kPAPAT); ! 1431: IOLog("\nEthernet(BMac): Read Register %04x Preamble Pattern = %04x", kPAPAT, dataValue ); ! 1432: ! 1433: dataValue = ReadBigMacRegister(ioBaseEnet, kTXSFD); ! 1434: IOLog("\nEthernet(BMac): Read Register %04x Tx Start Frame Delimeter = %04x", kTXSFD, dataValue ); ! 1435: ! 1436: dataValue = ReadBigMacRegister(ioBaseEnet, kJAM); ! 1437: IOLog("\nEthernet(BMac): Read Register %04x Jam Size = %04x", kJAM, dataValue ); ! 1438: ! 1439: dataValue = ReadBigMacRegister(ioBaseEnet, kTXMAX); ! 1440: IOLog("\nEthernet(BMac): Read Register %04x Tx Max Size = %04x", kTXMAX, dataValue ); ! 1441: ! 1442: dataValue = ReadBigMacRegister(ioBaseEnet, kTXMIN); ! 1443: IOLog("\nEthernet(BMac): Read Register %04x Tx Min Size = %04x", kTXMIN, dataValue ); ! 1444: IOLog("\nEthernet(BMac): -------------------------------------------------------" ); ! 1445: ! 1446: dataValue = ReadBigMacRegister(ioBaseEnet, kPAREG); ! 1447: IOLog("\nEthernet(BMac): Read Register %04x Peak Attempts = %04x", kPAREG, dataValue ); ! 1448: ! 1449: dataValue = ReadBigMacRegister(ioBaseEnet, kDCNT); ! 1450: IOLog("\nEthernet(BMac): Read Register %04x Defer Timer = %04x", kDCNT, dataValue ); ! 1451: ! 1452: dataValue = ReadBigMacRegister(ioBaseEnet, kNCCNT); ! 1453: IOLog("\nEthernet(BMac): Read Register %04x Normal Collision Count = %04x", kNCCNT, dataValue ); ! 1454: ! 1455: dataValue = ReadBigMacRegister(ioBaseEnet, kNTCNT); ! 1456: IOLog("\nEthernet(BMac): Read Register %04x Network Collision Count = %04x", kNTCNT, dataValue ); ! 1457: ! 1458: dataValue = ReadBigMacRegister(ioBaseEnet, kEXCNT); ! 1459: IOLog("\nEthernet(BMac): Read Register %04x Excessive Coll Count = %04x", kEXCNT, dataValue ); ! 1460: IOLog("\nEthernet(BMac): -------------------------------------------------------" ); ! 1461: ! 1462: dataValue = ReadBigMacRegister(ioBaseEnet, kLTCNT); ! 1463: IOLog("\nEthernet(BMac): Read Register %04x Late Collision Count = %04x", kLTCNT, dataValue ); ! 1464: ! 1465: dataValue = ReadBigMacRegister(ioBaseEnet, kRSEED); ! 1466: IOLog("\nEthernet(BMac): Read Register %04x Random Seed = %04x", kRSEED, dataValue ); ! 1467: ! 1468: dataValue = ReadBigMacRegister(ioBaseEnet, kTXSM); ! 1469: IOLog("\nEthernet(BMac): Read Register %04x Tx State Machine = %04x", kTXSM, dataValue ); ! 1470: ! 1471: dataValue = ReadBigMacRegister(ioBaseEnet, kRXRST); ! 1472: IOLog("\nEthernet(BMac): Read Register %04x Rx Reset = %04x", kRXRST, dataValue ); ! 1473: ! 1474: dataValue = ReadBigMacRegister(ioBaseEnet, kRXCFG); ! 1475: IOLog("\nEthernet(BMac): Read Register %04x Rx Config = %04x", kRXCFG, dataValue ); ! 1476: IOLog("\nEthernet(BMac): -------------------------------------------------------" ); ! 1477: ! 1478: dataValue = ReadBigMacRegister(ioBaseEnet, kRXMAX); ! 1479: IOLog("\nEthernet(BMac): Read Register %04x Rx Max Size = %04x", kRXMAX, dataValue ); ! 1480: ! 1481: dataValue = ReadBigMacRegister(ioBaseEnet, kRXMIN); ! 1482: IOLog("\nEthernet(BMac): Read Register %04x Rx Min Size = %04x", kRXMIN, dataValue ); ! 1483: ! 1484: dataValue = ReadBigMacRegister(ioBaseEnet, kMADD2); ! 1485: IOLog("\nEthernet(BMac): Read Register %04x Mac Address 2 = %04x", kMADD2, dataValue ); ! 1486: ! 1487: dataValue = ReadBigMacRegister(ioBaseEnet, kMADD1); ! 1488: IOLog("\nEthernet(BMac): Read Register %04x Mac Address 1 = %04x", kMADD1, dataValue ); ! 1489: ! 1490: dataValue = ReadBigMacRegister(ioBaseEnet, kMADD0); ! 1491: IOLog("\nEthernet(BMac): Read Register %04x Mac Address 0 = %04x", kMADD0, dataValue ); ! 1492: IOLog("\nEthernet(BMac): -------------------------------------------------------" ); ! 1493: ! 1494: dataValue = ReadBigMacRegister(ioBaseEnet, kFRCNT); ! 1495: IOLog("\nEthernet(BMac): Read Register %04x Rx Frame Counter = %04x", kFRCNT, dataValue ); ! 1496: ! 1497: dataValue = ReadBigMacRegister(ioBaseEnet, kLECNT); ! 1498: IOLog("\nEthernet(BMac): Read Register %04x Rx Length Error Cnt = %04x", kLECNT, dataValue ); ! 1499: ! 1500: dataValue = ReadBigMacRegister(ioBaseEnet, kAECNT); ! 1501: IOLog("\nEthernet(BMac): Read Register %04x Alignment Error Cnt = %04x", kAECNT, dataValue ); ! 1502: ! 1503: dataValue = ReadBigMacRegister(ioBaseEnet, kFECNT); ! 1504: IOLog("\nEthernet(BMac): Read Register %04x FCS Error Cnt = %04x", kFECNT, dataValue ); ! 1505: ! 1506: dataValue = ReadBigMacRegister(ioBaseEnet, kRXSM); ! 1507: IOLog("\nEthernet(BMac): Read Register %04x Rx State Machine = %04x", kRXSM, dataValue ); ! 1508: IOLog("\nEthernet(BMac): -------------------------------------------------------" ); ! 1509: ! 1510: dataValue = ReadBigMacRegister(ioBaseEnet, kRXCV); ! 1511: IOLog("\nEthernet(BMac): Read Register %04x Rx Code Violation = %04x", kRXCV, dataValue ); ! 1512: ! 1513: dataValue = ReadBigMacRegister(ioBaseEnet, kHASH3); ! 1514: IOLog("\nEthernet(BMac): Read Register %04x Hash 3 = %04x", kHASH3, dataValue ); ! 1515: ! 1516: dataValue = ReadBigMacRegister(ioBaseEnet, kHASH2); ! 1517: IOLog("\nEthernet(BMac): Read Register %04x Hash 2 = %04x", kHASH2, dataValue ); ! 1518: ! 1519: dataValue = ReadBigMacRegister(ioBaseEnet, kHASH1); ! 1520: IOLog("\nEthernet(BMac): Read Register %04x Hash 1 = %04x", kHASH1, dataValue ); ! 1521: ! 1522: dataValue = ReadBigMacRegister(ioBaseEnet, kHASH0); ! 1523: IOLog("\nEthernet(BMac): Read Register %04x Hash 0 = %04x", kHASH0, dataValue ); ! 1524: IOLog("\n-------------------------------------------------------" ); ! 1525: ! 1526: dataValue = ReadBigMacRegister(ioBaseEnet, kAFR2); ! 1527: IOLog("\nEthernet(BMac): Read Register %04x Address Filter 2 = %04x", kAFR2, dataValue ); ! 1528: ! 1529: dataValue = ReadBigMacRegister(ioBaseEnet, kAFR1); ! 1530: IOLog("\nEthernet(BMac): Read Register %04x Address Filter 1 = %04x", kAFR1, dataValue ); ! 1531: ! 1532: dataValue = ReadBigMacRegister(ioBaseEnet, kAFR0); ! 1533: IOLog("\nEthernet(BMac): Read Register %04x Address Filter 0 = %04x", kAFR0, dataValue ); ! 1534: ! 1535: dataValue = ReadBigMacRegister(ioBaseEnet, kAFCR); ! 1536: IOLog("\nEthernet(BMac): Read Register %04x Adress Filter Mask = %04x", kAFCR, dataValue ); ! 1537: ! 1538: dataValue = ReadBigMacRegister(ioBaseEnet, kTXFIFOCSR); ! 1539: IOLog("\nEthernet(BMac): Read Register %04x Tx FIFO CSR = %04x", kTXFIFOCSR, dataValue ); ! 1540: IOLog("\n-------------------------------------------------------" ); ! 1541: ! 1542: dataValue = ReadBigMacRegister(ioBaseEnet, kTXTH); ! 1543: IOLog("\nEthernet(BMac): Read Register %04x Tx Threshold = %04x", kTXTH, dataValue ); ! 1544: ! 1545: dataValue = ReadBigMacRegister(ioBaseEnet, kRXFIFOCSR); ! 1546: IOLog("\nEthernet(BMac): Read Register %04x Rx FIFO CSR = %04x", kRXFIFOCSR, dataValue ); ! 1547: ! 1548: dataValue = ReadBigMacRegister(ioBaseEnet, kMEMADD); ! 1549: IOLog("\nEthernet(BMac): Read Register %04x Mem Addr = %04x", kMEMADD, dataValue ); ! 1550: ! 1551: dataValue = ReadBigMacRegister(ioBaseEnet, kMEMDATAHI); ! 1552: IOLog("\nEthernet(BMac): Read Register %04x Mem Data High = %04x", kMEMDATAHI, dataValue ); ! 1553: ! 1554: dataValue = ReadBigMacRegister(ioBaseEnet, kMEMDATALO); ! 1555: IOLog("\nEthernet(BMac): Read Register %04x Mem Data Low = %04x", kMEMDATALO, dataValue ); ! 1556: IOLog("\n-------------------------------------------------------" ); ! 1557: ! 1558: dataValue = ReadBigMacRegister(ioBaseEnet, kXCVRIF); ! 1559: IOLog("\nEthernet(BMac): Read Register %04x Transceiver IF Control = %04x", kXCVRIF, dataValue ); ! 1560: ! 1561: dataValue = ReadBigMacRegister(ioBaseEnet, kCHIPID); ! 1562: IOLog("\nEthernet(BMac): Read Register %04x Chip ID = %04x", kCHIPID, dataValue ); ! 1563: ! 1564: dataValue = ReadBigMacRegister(ioBaseEnet, kMIFCSR); ! 1565: IOLog("\nEthernet(BMac): Read Register %04x MII CSR = %04x", kMIFCSR, dataValue ); ! 1566: ! 1567: dataValue = ReadBigMacRegister(ioBaseEnet, kSROMCSR); ! 1568: IOLog("\nEthernet(BMac): Read Register %04x SROM CSR = %04x", kSROMCSR, dataValue ); ! 1569: ! 1570: dataValue = ReadBigMacRegister(ioBaseEnet, kTXPNTR); ! 1571: IOLog("\nEthernet(BMac): Read Register %04x Tx Pointer = %04x", kTXPNTR, dataValue ); ! 1572: ! 1573: dataValue = ReadBigMacRegister(ioBaseEnet, kRXPNTR); ! 1574: IOLog("\nEthernet(BMac): Read Register %04x Rx Pointer = %04x", kRXPNTR, dataValue ); ! 1575: IOLog("\nEthernet(BMac): -------------------------------------------------------\n" ); ! 1576: } ! 1577: #endif DEBUG ! 1578: ! 1579: ! 1580: /*------------------------------------------------------------------------- ! 1581: * ! 1582: * ! 1583: * ! 1584: *-------------------------------------------------------------------------*/ ! 1585: ! 1586: - (void)_getStationAddress:(enet_addr_t *)ea ! 1587: { ! 1588: int i; ! 1589: unsigned short data; ! 1590: ! 1591: for (i = 0; i < sizeof(*ea)/2; i++) ! 1592: { ! 1593: reset_and_select_srom(ioBaseEnet); ! 1594: data = read_srom(ioBaseEnet, i + enetAddressOffset/2, sromAddressBits); ! 1595: ea->ea_byte[2*i] = reverseBitOrder(data & 0x0ff); ! 1596: ea->ea_byte[2*i+1] = reverseBitOrder((data >> 8) & 0x0ff); ! 1597: } ! 1598: } ! 1599: ! 1600: ! 1601: ! 1602: /*------------------------------------------------------------------------- ! 1603: * ! 1604: * ! 1605: * ! 1606: *-------------------------------------------------------------------------*/ ! 1607: ! 1608: #define ENET_CRCPOLY 0x04c11db7 ! 1609: ! 1610: /* Real fast bit-reversal algorithm, 6-bit values */ ! 1611: static int reverse6[] = ! 1612: { 0x0,0x20,0x10,0x30,0x8,0x28,0x18,0x38, ! 1613: 0x4,0x24,0x14,0x34,0xc,0x2c,0x1c,0x3c, ! 1614: 0x2,0x22,0x12,0x32,0xa,0x2a,0x1a,0x3a, ! 1615: 0x6,0x26,0x16,0x36,0xe,0x2e,0x1e,0x3e, ! 1616: 0x1,0x21,0x11,0x31,0x9,0x29,0x19,0x39, ! 1617: 0x5,0x25,0x15,0x35,0xd,0x2d,0x1d,0x3d, ! 1618: 0x3,0x23,0x13,0x33,0xb,0x2b,0x1b,0x3b, ! 1619: 0x7,0x27,0x17,0x37,0xf,0x2f,0x1f,0x3f ! 1620: }; ! 1621: ! 1622: static u_int32_t crc416(unsigned int current, unsigned short nxtval ) ! 1623: { ! 1624: register unsigned int counter; ! 1625: register int highCRCBitSet, lowDataBitSet; ! 1626: ! 1627: /* Swap bytes */ ! 1628: nxtval = ((nxtval & 0x00FF) << 8) | (nxtval >> 8); ! 1629: ! 1630: /* Compute bit-by-bit */ ! 1631: for (counter = 0; counter != 16; ++counter) ! 1632: { /* is high CRC bit set? */ ! 1633: if ((current & 0x80000000) == 0) ! 1634: highCRCBitSet = 0; ! 1635: else ! 1636: highCRCBitSet = 1; ! 1637: ! 1638: current = current << 1; ! 1639: ! 1640: if ((nxtval & 0x0001) == 0) ! 1641: lowDataBitSet = 0; ! 1642: else ! 1643: lowDataBitSet = 1; ! 1644: ! 1645: nxtval = nxtval >> 1; ! 1646: ! 1647: /* do the XOR */ ! 1648: if (highCRCBitSet ^ lowDataBitSet) ! 1649: current = current ^ ENET_CRCPOLY; ! 1650: } ! 1651: return current; ! 1652: } ! 1653: ! 1654: /*------------------------------------------------------------------------- ! 1655: * ! 1656: * ! 1657: * ! 1658: *-------------------------------------------------------------------------*/ ! 1659: ! 1660: static u_int32_t mace_crc(unsigned short *address) ! 1661: { ! 1662: register u_int32_t newcrc; ! 1663: ! 1664: newcrc = crc416(0xffffffff, *address); /* address bits 47 - 32 */ ! 1665: newcrc = crc416(newcrc, address[1]); /* address bits 31 - 16 */ ! 1666: newcrc = crc416(newcrc, address[2]); /* address bits 15 - 0 */ ! 1667: ! 1668: return(newcrc); ! 1669: } ! 1670: ! 1671: /* ! 1672: * Add requested mcast addr to BMac's hash table filter. ! 1673: * ! 1674: */ ! 1675: -(void) _addToHashTableMask:(u_int8_t *)addr ! 1676: { ! 1677: u_int32_t crc; ! 1678: u_int16_t mask; ! 1679: ! 1680: crc = mace_crc((unsigned short *)addr)&0x3f; /* Big-endian alert! */ ! 1681: crc = reverse6[crc]; /* Hyperfast bit-reversing algorithm */ ! 1682: if (hashTableUseCount[crc]++) ! 1683: return; /* This bit is already set */ ! 1684: mask = crc % 16; ! 1685: mask = (unsigned short)1 << mask; ! 1686: hashTableMask[crc/16] |= mask; ! 1687: } ! 1688: ! 1689: /*------------------------------------------------------------------------- ! 1690: * ! 1691: * ! 1692: * ! 1693: *-------------------------------------------------------------------------*/ ! 1694: ! 1695: -(void) _removeFromHashTableMask:(u_int8_t *)addr ! 1696: { ! 1697: unsigned int crc; ! 1698: u_int16_t mask; ! 1699: ! 1700: /* Now, delete the address from the filter copy, as indicated */ ! 1701: crc = mace_crc((unsigned short *)addr)&0x3f; /* Big-endian alert! */ ! 1702: crc = reverse6[crc]; /* Hyperfast bit-reversing algorithm */ ! 1703: if (hashTableUseCount[crc] == 0) ! 1704: return; /* That bit wasn't in use! */ ! 1705: ! 1706: if (--hashTableUseCount[crc]) ! 1707: return; /* That bit is still in use */ ! 1708: ! 1709: mask = crc % 16; ! 1710: mask = (u_int16_t)1 << mask; /* To turn off bit */ ! 1711: hashTableMask[crc/16] &= ~mask; ! 1712: } ! 1713: ! 1714: /* ! 1715: * Sync the adapter with the software copy of the multicast mask ! 1716: * (logical address filter). ! 1717: */ ! 1718: -(void) _updateBMacHashTableMask ! 1719: { ! 1720: u_int16_t rxCFGReg; ! 1721: ! 1722: rxCFGReg = ReadBigMacRegister(ioBaseEnet, kRXCFG); ! 1723: WriteBigMacRegister(ioBaseEnet, kRXCFG, rxCFGReg & ~(kRxMACEnable | kRxHashFilterEnable) ); ! 1724: ! 1725: while ( ReadBigMacRegister(ioBaseEnet, kRXCFG) & (kRxMACEnable | kRxHashFilterEnable) ) ! 1726: ; ! 1727: ! 1728: WriteBigMacRegister(ioBaseEnet, kHASH0, hashTableMask[0]); // bits 15 - 0 ! 1729: WriteBigMacRegister(ioBaseEnet, kHASH1, hashTableMask[1]); // bits 31 - 16 ! 1730: WriteBigMacRegister(ioBaseEnet, kHASH2, hashTableMask[2]); // bits 47 - 32 ! 1731: WriteBigMacRegister(ioBaseEnet, kHASH3, hashTableMask[3]); // bits 63 - 48 ! 1732: ! 1733: rxCFGReg |= kRxHashFilterEnable; ! 1734: WriteBigMacRegister(ioBaseEnet, kRXCFG, rxCFGReg ); ! 1735: } ! 1736: ! 1737: @end ! 1738:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.