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