|
|
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) 1995-1996 NeXT Software, Inc. ! 27: * ! 28: * Implementation for hardware dependent (relatively) code ! 29: * for the Mace Ethernet controller. ! 30: * ! 31: * HISTORY ! 32: * ! 33: * 10-Sept-97 ! 34: * Created. ! 35: * ! 36: */ ! 37: #import "MaceEnetPrivate.h" ! 38: #import <mach/vm_param.h> // PAGE_SIZE ! 39: ! 40: extern void *kernel_map; ! 41: extern kern_return_t kmem_alloc_wired(); ! 42: ! 43: static IODBDMADescriptor dbdmaCmd_Nop; ! 44: static IODBDMADescriptor dbdmaCmd_NopWInt; ! 45: static IODBDMADescriptor dbdmaCmd_LoadXFS; ! 46: static IODBDMADescriptor dbdmaCmd_LoadIntwInt; ! 47: static IODBDMADescriptor dbdmaCmd_Stop; ! 48: static IODBDMADescriptor dbdmaCmd_Branch; ! 49: ! 50: ! 51: static u_int8_t reverseBitOrder(u_int8_t data ) ! 52: { ! 53: u_int8_t val = 0; ! 54: int i; ! 55: ! 56: for ( i=0; i < 8; i++ ) ! 57: { ! 58: val <<= 1; ! 59: if (data & 1) val |= 1; ! 60: data >>= 1; ! 61: } ! 62: return( val ); ! 63: } ! 64: ! 65: ! 66: @implementation MaceEnet(Private) ! 67: ! 68: ! 69: /* ! 70: * Private functions ! 71: */ ! 72: - (BOOL)_allocateMemory ! 73: { ! 74: u_int32_t dbdmaSize; ! 75: u_int32_t i, n; ! 76: unsigned char * virtAddr; ! 77: u_int32_t physBase; ! 78: u_int32_t physAddr; ! 79: IOReturn kr; ! 80: ! 81: /* ! 82: * Calculate total space for DMA channel commands ! 83: */ ! 84: dbdmaSize = round_page( RX_RING_LENGTH * sizeof(enet_dma_cmd_t) + TX_RING_LENGTH * sizeof(enet_txdma_cmd_t) ! 85: + 2 * sizeof(IODBDMADescriptor) ); ! 86: /* ! 87: * Allocate required memory ! 88: */ ! 89: if ( !dmaCommands ) ! 90: { ! 91: kr = kmem_alloc_wired(kernel_map, (vm_offset_t *) &dmaCommands, dbdmaSize ); ! 92: ! 93: if ( kr != KERN_SUCCESS ) ! 94: { ! 95: IOLog( "Ethernet(Mace): Cant allocate channel DBDMA commands\n\r" ); ! 96: return NO; ! 97: } ! 98: } ! 99: ! 100: /* ! 101: * If we needed more than one page, then make sure we received contiguous memory. ! 102: */ ! 103: n = (dbdmaSize - PAGE_SIZE) / PAGE_SIZE; ! 104: IOPhysicalFromVirtual( (vm_task_t) kernel_map, (vm_address_t) dmaCommands, &physBase ); ! 105: ! 106: virtAddr = (unsigned char *) dmaCommands; ! 107: for( i=0; i < n; i++, virtAddr += PAGE_SIZE ) ! 108: { ! 109: IOPhysicalFromVirtual( (vm_task_t) kernel_map, (vm_address_t) virtAddr, &physAddr ); ! 110: if (physAddr != (physBase + i * PAGE_SIZE) ) ! 111: { ! 112: IOLog( "Ethernet(Mace): Cant allocate contiguous memory for DBDMA commands\n\r" ); ! 113: return NO; ! 114: } ! 115: } ! 116: ! 117: /* ! 118: * Setup the receive ring pointers ! 119: */ ! 120: rxDMACommands = (enet_dma_cmd_t *)dmaCommands; ! 121: rxMaxCommand = RX_RING_LENGTH; ! 122: ! 123: /* ! 124: * Setup the transmit ring pointers ! 125: */ ! 126: txDMACommands = (enet_txdma_cmd_t *)(dmaCommands + RX_RING_LENGTH * sizeof(enet_dma_cmd_t) + sizeof(IODBDMADescriptor)); ! 127: txMaxCommand = TX_RING_LENGTH; ! 128: ! 129: ! 130: /* ! 131: * Setup pre-initialized DBDMA commands ! 132: */ ! 133: IOMakeDBDMADescriptor( (&dbdmaCmd_Nop), ! 134: kdbdmaNop, ! 135: kdbdmaKeyStream0, ! 136: kdbdmaIntNever, ! 137: kdbdmaBranchNever, ! 138: kdbdmaWaitNever, ! 139: 0, ! 140: 0 ); ! 141: ! 142: IOMakeDBDMADescriptor( (&dbdmaCmd_NopWInt), ! 143: kdbdmaNop, ! 144: kdbdmaKeyStream0, ! 145: kdbdmaIntAlways, ! 146: kdbdmaBranchNever, ! 147: kdbdmaWaitNever, ! 148: 0, ! 149: 0 ); ! 150: ! 151: IOMakeDBDMADescriptor( (&dbdmaCmd_LoadXFS), ! 152: kdbdmaLoadQuad, ! 153: kdbdmaKeySystem, ! 154: kdbdmaIntNever, ! 155: kdbdmaBranchNever, ! 156: kdbdmaWaitNever, ! 157: 1, ! 158: ((int)ioBaseEnet + kXmtFS) ); ! 159: ! 160: IOMakeDBDMADescriptor( (&dbdmaCmd_LoadIntwInt), ! 161: kdbdmaLoadQuad, ! 162: kdbdmaKeySystem, ! 163: kdbdmaIntAlways, ! 164: kdbdmaBranchNever, ! 165: kdbdmaWaitNever, ! 166: 1, ! 167: ((int)ioBaseEnet + kIntReg) ); ! 168: ! 169: IOMakeDBDMADescriptor( (&dbdmaCmd_Stop), ! 170: kdbdmaStop, ! 171: kdbdmaKeyStream0, ! 172: kdbdmaIntNever, ! 173: kdbdmaBranchNever, ! 174: kdbdmaWaitNever, ! 175: 0, ! 176: 0 ); ! 177: ! 178: IOMakeDBDMADescriptor( (&dbdmaCmd_Branch), ! 179: kdbdmaNop, ! 180: kdbdmaKeyStream0, ! 181: kdbdmaIntNever, ! 182: kdbdmaBranchAlways, ! 183: kdbdmaWaitNever, ! 184: 0, ! 185: 0 ); ! 186: ! 187: return YES; ! 188: } ! 189: ! 190: /*------------------------------------------------------------------------- ! 191: * ! 192: * Setup the Transmit Ring ! 193: * ----------------------- ! 194: * Each transmit ring entry consists of two words to transmit data from buffer ! 195: * segments (possibly) spanning a page boundary. This is followed by two DMA commands ! 196: * which read transmit frame status and interrupt status from the Mace chip. The last ! 197: * DMA command in each transmit ring entry generates a host interrupt. ! 198: * The last entry in the ring is followed by a DMA branch to the first ! 199: * entry. ! 200: *-------------------------------------------------------------------------*/ ! 201: ! 202: - (BOOL)_initTxRing ! 203: { ! 204: BOOL kr; ! 205: u_int32_t i; ! 206: ! 207: /* ! 208: * Clear the transmit DMA command memory ! 209: */ ! 210: bzero( (void *)txDMACommands, sizeof(enet_txdma_cmd_t) * txMaxCommand); ! 211: txCommandHead = 0; ! 212: txCommandTail = 0; ! 213: ! 214: /* ! 215: * Init the transmit queue. ! 216: */ ! 217: if (transmitQueue) ! 218: { ! 219: [transmitQueue free]; ! 220: } ! 221: ! 222: transmitQueue = [[IONetbufQueue alloc] initWithMaxCount:TRANSMIT_QUEUE_SIZE]; ! 223: if (!transmitQueue) ! 224: { ! 225: IOLog("Ethernet(Mace): Cant allocate transmit queue\n\r"); ! 226: return NO; ! 227: } ! 228: ! 229: /* ! 230: * DMA Channel commands 2,3 are the same for all DBDMA entries on transmit. ! 231: * Initialize them now. ! 232: */ ! 233: for( i=0; i < txMaxCommand; i++ ) ! 234: { ! 235: txDMACommands[i].desc_seg[2] = dbdmaCmd_LoadXFS; ! 236: txDMACommands[i].desc_seg[3] = dbdmaCmd_LoadIntwInt; ! 237: } ! 238: ! 239: /* ! 240: * Put a DMA Branch command after the last entry in the transmit ring. Set the branch address ! 241: * to the physical address of the start of the transmit ring. ! 242: */ ! 243: txDMACommands[txMaxCommand].desc_seg[0] = dbdmaCmd_Branch; ! 244: ! 245: kr = IOPhysicalFromVirtual( (vm_task_t) IOVmTaskSelf(), (vm_address_t) txDMACommands, (u_int32_t *)&txDMACommandsPhys ); ! 246: if ( kr != IO_R_SUCCESS ) ! 247: { ! 248: IOLog( "Ethernet(Mace): Bad Tx DBDMA command buf - %08x\n\r", (u_int32_t)txDMACommands ); ! 249: } ! 250: IOSetCCCmdDep( &txDMACommands[txMaxCommand].desc_seg[0], txDMACommandsPhys ); ! 251: ! 252: /* ! 253: * Set the Transmit DMA Channel pointer to the first entry in the transmit ring. ! 254: */ ! 255: IOSetDBDMACommandPtr( ioBaseEnetTxDMA, txDMACommandsPhys ); ! 256: ! 257: /* ! 258: * Push the DMA channel words into physical memory. ! 259: */ ! 260: flush_cache_v( (vm_offset_t)txDMACommands, txMaxCommand*sizeof(enet_txdma_cmd_t) + sizeof(IODBDMADescriptor)); ! 261: ! 262: return YES; ! 263: } ! 264: ! 265: /*------------------------------------------------------------------------- ! 266: * ! 267: * Setup the Receive ring ! 268: * ---------------------- ! 269: * Each receive ring entry consists of two DMA commands to receive data ! 270: * into a network buffer (possibly) spanning a page boundary. The second ! 271: * DMA command in each entry generates a host interrupt. ! 272: * The last entry in the ring is followed by a DMA branch to the first ! 273: * entry. ! 274: * ! 275: *-------------------------------------------------------------------------*/ ! 276: ! 277: - (BOOL)_initRxRing ! 278: { ! 279: u_int32_t i; ! 280: BOOL status; ! 281: IOReturn kr; ! 282: ! 283: /* ! 284: * Clear the receive DMA command memory ! 285: */ ! 286: bzero( (void *)rxDMACommands, sizeof(enet_dma_cmd_t) * rxMaxCommand); ! 287: ! 288: kr = IOPhysicalFromVirtual( (vm_task_t) IOVmTaskSelf(), (vm_address_t) rxDMACommands, (u_int32_t *)&rxDMACommandsPhys ); ! 289: if ( kr != IO_R_SUCCESS ) ! 290: { ! 291: IOLog( "Ethernet(Mace): Bad Rx DBDMA command buf - %08x\n\r", (u_int32_t)rxDMACommands ); ! 292: return NO; ! 293: } ! 294: ! 295: /* ! 296: * Allocate a receive buffer for each entry in the Receive ring ! 297: */ ! 298: for (i = 0; i < rxMaxCommand-1; i++) ! 299: { ! 300: if (rxNetbuf[i] == NULL) ! 301: { ! 302: rxNetbuf[i] = [self allocateNetbuf]; ! 303: if (rxNetbuf[i] == NULL) ! 304: { ! 305: IOLog("Ethernet(Mace): allocateNetbuf returned NULL in _initRxRing\n\r"); ! 306: return NO; ! 307: } ! 308: } ! 309: /* ! 310: * Set the DMA commands for the ring entry to transfer data to the NetBuf. ! 311: */ ! 312: status = [self _updateDescriptorFromNetBuf:rxNetbuf[i] Desc:(void *)&rxDMACommands[i] ReceiveFlag:YES ]; ! 313: if (status == NO) ! 314: { ! 315: IOLog("Ethernet(Mace): Cant map Netbuf to physical memory in _initRxRing\n\r"); ! 316: return NO; ! 317: } ! 318: } ! 319: ! 320: /* ! 321: * Set the receive queue head to point to the first entry in the ring. Set the ! 322: * receive queue tail to point to a DMA Stop command after the last ring entry ! 323: */ ! 324: rxCommandHead = 0; ! 325: rxCommandTail = i; ! 326: ! 327: rxDMACommands[i].desc_seg[0] = dbdmaCmd_Stop; ! 328: rxDMACommands[i].desc_seg[1] = dbdmaCmd_Nop; ! 329: ! 330: /* ! 331: * Setup a DMA branch command after the stop command ! 332: */ ! 333: i++; ! 334: rxDMACommands[i].desc_seg[0] = dbdmaCmd_Branch; ! 335: ! 336: IOSetCCCmdDep( &rxDMACommands[i].desc_seg[0], rxDMACommandsPhys ); ! 337: ! 338: /* ! 339: * Set DMA command pointer to first receive entry ! 340: */ ! 341: IOSetDBDMACommandPtr( ioBaseEnetRxDMA, rxDMACommandsPhys ); ! 342: ! 343: /* ! 344: * Push DMA commands to physical memory ! 345: */ ! 346: flush_cache_v( (vm_offset_t)&rxDMACommands[rxCommandTail], 2 * sizeof(enet_dma_cmd_t) ); ! 347: ! 348: return YES; ! 349: } ! 350: ! 351: /*------------------------------------------------------------------------- ! 352: * ! 353: * ! 354: * ! 355: *-------------------------------------------------------------------------*/ ! 356: ! 357: - (void)_startChip ! 358: { ! 359: WriteMaceRegister( ioBaseEnet, kMacCC, kMacCCEnXmt | kMacCCEnRcv ); ! 360: ! 361: // enable rx dma channel ! 362: IODBDMAContinue( ioBaseEnetRxDMA ); ! 363: ! 364: } ! 365: ! 366: ! 367: ! 368: /*------------------------------------------------------------------------- ! 369: * ! 370: * ! 371: * ! 372: *-------------------------------------------------------------------------*/ ! 373: ! 374: - (void)_resetChip ! 375: { ! 376: u_int8_t regValue; ! 377: ! 378: /* ! 379: * Mace errata - chip reset does not clear pending interrupts ! 380: */ ! 381: ReadMaceRegister( ioBaseEnet, kIntReg ); ! 382: ! 383: IODBDMAReset( ioBaseEnetRxDMA ); ! 384: IODBDMAReset( ioBaseEnetTxDMA ); ! 385: ! 386: IOSetDBDMAWaitSelect( ioBaseEnetTxDMA, IOSetDBDMAChannelControlBits( kdbdmaS5 ) ); ! 387: ! 388: IOSetDBDMABranchSelect( ioBaseEnetRxDMA, IOSetDBDMAChannelControlBits( kdbdmaS6 ) ); ! 389: IOSetDBDMAInterruptSelect( ioBaseEnetRxDMA, IOSetDBDMAChannelControlBits( kdbdmaS6 ) ); ! 390: ! 391: WriteMaceRegister( ioBaseEnet, kBIUCC, kBIUCCSWRst ); ! 392: do ! 393: { ! 394: regValue = ReadMaceRegister( ioBaseEnet, kBIUCC ); ! 395: } ! 396: while( regValue & kBIUCCSWRst ); ! 397: } ! 398: ! 399: /*------------------------------------------------------------------------- ! 400: * ! 401: * ! 402: * ! 403: *-------------------------------------------------------------------------*/ ! 404: ! 405: - (BOOL)_initChip ! 406: { ! 407: volatile u_int16_t regValue; ! 408: u_int32_t i; ! 409: ! 410: [self _disableAdapterInterrupts]; ! 411: ! 412: chipId = ReadMaceRegister( ioBaseEnet, kMaceChipId0 ); ! 413: chipId |= ReadMaceRegister( ioBaseEnet, kMaceChipId1 ) << 8; ! 414: ! 415: /* ! 416: * Turn off ethernet header stripping ! 417: */ ! 418: regValue = ReadMaceRegister( ioBaseEnet, kRcvFC ); ! 419: regValue &= ~kRcvFCAStrpRcv; ! 420: WriteMaceRegister( ioBaseEnet, kRcvFC, regValue ); ! 421: ! 422: /* ! 423: * Set Mace destination address. ! 424: */ ! 425: if ( chipId != kMaceRevisionA2 ) ! 426: { ! 427: WriteMaceRegister( ioBaseEnet, kIAC, kIACAddrChg | kIACPhyAddr ); ! 428: do ! 429: { ! 430: regValue = ReadMaceRegister( ioBaseEnet, kIAC ); ! 431: } ! 432: while( regValue & kIACAddrChg ); ! 433: } ! 434: else ! 435: { ! 436: WriteMaceRegister( ioBaseEnet, kIAC, kIACPhyAddr ); ! 437: } ! 438: ! 439: for (i=0; i < sizeof(enet_addr_t); i++ ) ! 440: { ! 441: WriteMaceRegister( ioBaseEnet, kPADR, reverseBitOrder(((unsigned char *)ioBaseEnetROM)[i<<4]) ); ! 442: } ! 443: ! 444: /* ! 445: * Clear logical address (multicast) filter ! 446: */ ! 447: if ( chipId != kMaceRevisionA2 ) ! 448: { ! 449: WriteMaceRegister( ioBaseEnet, kIAC, kIACAddrChg | kIACLogAddr ); ! 450: do ! 451: { ! 452: regValue = ReadMaceRegister( ioBaseEnet, kIAC ); ! 453: } ! 454: while( regValue & kIACAddrChg ); ! 455: } ! 456: else ! 457: { ! 458: WriteMaceRegister( ioBaseEnet, kIAC, kIACLogAddr ); ! 459: } ! 460: ! 461: for (i = 0; i < 8; i++ ) ! 462: { ! 463: WriteMaceRegister( ioBaseEnet, kLADRF, 0 ); ! 464: } ! 465: ! 466: /* ! 467: * Enable ethernet transceiver ! 468: */ ! 469: WriteMaceRegister( ioBaseEnet, kPLSCC, kPLSCCPortSelGPSI | kPLSCCEnSts ); ! 470: ! 471: return YES; ! 472: } ! 473: ! 474: ! 475: /*------------------------------------------------------------------------- ! 476: * ! 477: * ! 478: * ! 479: *-------------------------------------------------------------------------*/ ! 480: ! 481: - (void) _restartChip ! 482: { ! 483: /* ! 484: * Shutdown DMA channels ! 485: */ ! 486: [self _stopReceiveDMA]; ! 487: [self _stopTransmitDMA]; ! 488: ! 489: /* ! 490: * Get the silicon's attention ! 491: */ ! 492: [self _resetChip]; ! 493: [self _initChip]; ! 494: ! 495: /* ! 496: * Restore multicast settings ! 497: */ ! 498: [self _updateHashTableMask]; ! 499: ! 500: if ( isPromiscuous ) ! 501: { ! 502: [self enablePromiscuousMode]; ! 503: } ! 504: ! 505: /* ! 506: * Enable receiver and transmitter ! 507: */ ! 508: [self _startChip]; ! 509: [self _enableAdapterInterrupts]; ! 510: ! 511: /* ! 512: * Restart transmit DMA ! 513: */ ! 514: IODBDMAContinue( ioBaseEnetTxDMA ); ! 515: ! 516: } ! 517: ! 518: /*------------------------------------------------------------------------- ! 519: * ! 520: * Orderly stop of receive DMA. ! 521: * ! 522: * ! 523: *-------------------------------------------------------------------------*/ ! 524: ! 525: - (void) _stopReceiveDMA ! 526: { ! 527: u_int32_t dmaStatus; ! 528: u_int32_t dmaCmdPtr; ! 529: u_int32_t dmaIndex; ! 530: u_int8_t tmpBuf[16]; ! 531: u_int8_t *p = 0; ! 532: u_int8_t MacCCReg; ! 533: ! 534: /* ! 535: * Stop the receiver and allow any frame receive in progress to complete ! 536: */ ! 537: MacCCReg = ReadMaceRegister( ioBaseEnet, kMacCC ); ! 538: WriteMaceRegister( ioBaseEnet, kMacCC, MacCCReg & ~kMacCCEnRcv ); ! 539: IODelay( RECEIVE_QUIESCE_uS * 1000 ); ! 540: ! 541: /* ! 542: * Capture channel status and pause the dma channel. ! 543: */ ! 544: dmaStatus = IOGetDBDMAChannelStatus( ioBaseEnetRxDMA ); ! 545: IODBDMAPause( ioBaseEnetRxDMA ); ! 546: ! 547: /* ! 548: * Read the command pointer and convert it to a byte offset into the DMA program. ! 549: */ ! 550: dmaCmdPtr = IOGetDBDMACommandPtr( ioBaseEnetRxDMA ); ! 551: dmaIndex = (dmaCmdPtr - rxDMACommandsPhys); ! 552: ! 553: /* ! 554: * If the channel status is DEAD, the DMA pointer is pointing to the next command ! 555: */ ! 556: if ( dmaStatus & kdbdmaDead ) ! 557: { ! 558: dmaIndex -= sizeof(IODBDMADescriptor); ! 559: } ! 560: ! 561: /* ! 562: * Convert channel program offset to command index ! 563: */ ! 564: dmaIndex = dmaIndex / sizeof(enet_dma_cmd_t); ! 565: if ( dmaIndex >= rxMaxCommand ) dmaIndex = 0; ! 566: ! 567: /* ! 568: * The DMA controller doesnt like being stopped before transferring any data. ! 569: * ! 570: * When we do so it pollutes up to 16-bytes aligned to the nearest (lower) 16-byte ! 571: * boundary. This corruption can be outside the data transfer area of the Netbuf, so we ! 572: * capture and then restore these bytes after stopping the channel. ! 573: * ! 574: */ ! 575: if ( rxNetbuf[dmaIndex] ) ! 576: { ! 577: p = (u_int8_t *)nb_map( rxNetbuf[dmaIndex] ); ! 578: } ! 579: ! 580: (u_int32_t)p &= ~0x0f; ! 581: ! 582: if ( p ) ! 583: { ! 584: bcopy( p, tmpBuf, 16 ); ! 585: } ! 586: ! 587: IODBDMAReset( ioBaseEnetRxDMA ); ! 588: ! 589: if ( p ) ! 590: { ! 591: bcopy( tmpBuf, p, 16 ); ! 592: } ! 593: ! 594: /* ! 595: * Reset the dma channel pointer to the nearest command index ! 596: */ ! 597: dmaCmdPtr = rxDMACommandsPhys + sizeof(enet_dma_cmd_t) * dmaIndex; ! 598: IOSetDBDMACommandPtr( ioBaseEnetRxDMA, dmaCmdPtr); ! 599: ! 600: } ! 601: ! 602: /*------------------------------------------------------------------------- ! 603: * ! 604: * ! 605: * ! 606: *-------------------------------------------------------------------------*/ ! 607: ! 608: - (void) _stopTransmitDMA ! 609: { ! 610: u_int32_t dmaStatus; ! 611: u_int32_t dmaCmdPtr; ! 612: u_int32_t dmaIndex; ! 613: u_int8_t MacCCReg; ! 614: ! 615: /* ! 616: * Stop the transmitter and allow any frame transmit in progress to abort ! 617: */ ! 618: MacCCReg = ReadMaceRegister( ioBaseEnet, kMacCC ); ! 619: WriteMaceRegister( ioBaseEnet, kMacCC, MacCCReg & ~kMacCCEnXmt ); ! 620: IODelay( TRANSMIT_QUIESCE_uS * 1000 ); ! 621: ! 622: /* ! 623: * Capture channel status and pause the dma channel. ! 624: */ ! 625: dmaStatus = IOGetDBDMAChannelStatus( ioBaseEnetTxDMA ); ! 626: IODBDMAPause( ioBaseEnetTxDMA ); ! 627: ! 628: /* ! 629: * Read the command pointer and convert it to a byte offset into the DMA program. ! 630: */ ! 631: dmaCmdPtr = IOGetDBDMACommandPtr( ioBaseEnetTxDMA ); ! 632: dmaIndex = (dmaCmdPtr - txDMACommandsPhys); ! 633: ! 634: /* ! 635: * If the channel status is DEAD, the DMA pointer is pointing to the next command ! 636: */ ! 637: if ( dmaStatus & kdbdmaDead ) ! 638: { ! 639: dmaIndex -= sizeof(IODBDMADescriptor); ! 640: } ! 641: ! 642: /* ! 643: * Convert channel program offset to command index ! 644: */ ! 645: dmaIndex = dmaIndex / sizeof(enet_txdma_cmd_t); ! 646: if ( dmaIndex >= txMaxCommand ) dmaIndex = 0; ! 647: ! 648: IODBDMAReset( ioBaseEnetTxDMA ); ! 649: ! 650: /* ! 651: * Reset the dma channel pointer to the nearest command index ! 652: */ ! 653: dmaCmdPtr = txDMACommandsPhys + sizeof(enet_txdma_cmd_t) * dmaIndex; ! 654: IOSetDBDMACommandPtr( ioBaseEnetTxDMA, dmaCmdPtr ); ! 655: } ! 656: ! 657: ! 658: ! 659: /*------------------------------------------------------------------------- ! 660: * ! 661: * ! 662: * ! 663: *-------------------------------------------------------------------------*/ ! 664: ! 665: - (void) _disableAdapterInterrupts ! 666: { ! 667: WriteMaceRegister( ioBaseEnet, kIntMask, 0xFF ); ! 668: } ! 669: ! 670: /*------------------------------------------------------------------------- ! 671: * ! 672: * _enableAdapterInterrupts ! 673: * ! 674: * It appears to make the Mace chip work properly with the DBDMA channel ! 675: * we need to leave the transmit interrupt unmasked at the chip. This ! 676: * is weird, but that's what happens when you try to glue a chip that ! 677: * wasn't intended to work with a DMA engine on to a DMA. ! 678: * ! 679: *-------------------------------------------------------------------------*/ ! 680: ! 681: - (void) _enableAdapterInterrupts ! 682: { ! 683: u_int8_t regValue; ! 684: ! 685: regValue = ReadMaceRegister( ioBaseEnet, kIntMask ); ! 686: regValue &= ~kIntMaskXmtInt; ! 687: WriteMaceRegister( ioBaseEnet, kIntMask, regValue ); ! 688: IODelay(500); ! 689: ReadMaceRegister( ioBaseEnet, kXmtFS ); ! 690: ReadMaceRegister( ioBaseEnet, kIntReg ); ! 691: } ! 692: ! 693: /*------------------------------------------------------------------------- ! 694: * ! 695: * ! 696: * ! 697: *-------------------------------------------------------------------------*/ ! 698: ! 699: - (BOOL)_transmitPacket:(netbuf_t)packet ! 700: { ! 701: enet_dma_cmd_t tmpCommand; ! 702: u_int32_t i; ! 703: ! 704: ! 705: /* ! 706: * Not sure we need this. Only required if Mace disables receiption of transmit packets ! 707: * addressed to itself. ! 708: */ ! 709: [self performLoopback:packet]; ! 710: ! 711: /* ! 712: * Check for room on the transmit ring. There should always be space since it is ! 713: * the responsibility of the caller to verify this before calling _transmitPacket. ! 714: */ ! 715: i = txCommandTail + 1; ! 716: if ( i >= txMaxCommand ) i = 0; ! 717: if ( i == txCommandHead ) ! 718: { ! 719: IOLog("Ethernet(Mace): Freeing transmit packet eh?\n\r"); ! 720: nb_free(packet); ! 721: return NO; ! 722: } ! 723: ! 724: /* ! 725: * txCommandTail points to the current DMA Stop command for the channel. We are ! 726: * now creating a new DMA Stop command in the next slot in the transmit ring. The ! 727: * previous DMA Stop command will be overwritten with the DMA commands to ! 728: * transfer the new NetBuf. ! 729: */ ! 730: txDMACommands[i].desc_seg[0] = dbdmaCmd_Stop; ! 731: txDMACommands[i].desc_seg[1] = dbdmaCmd_Nop; ! 732: ! 733: flush_cache_v( (vm_offset_t)&txDMACommands[i], sizeof(enet_dma_cmd_t) ); ! 734: ! 735: /* ! 736: * Get a copy of the DMA transfer commands in a temporary buffer. ! 737: * The new DMA command is written into the channel program so that the command ! 738: * word for the old Stop command is overwritten last. This prevents the DMA ! 739: * engine from executing a partially written channel command. ! 740: */ ! 741: [self _updateDescriptorFromNetBuf:packet Desc:&tmpCommand ReceiveFlag:NO]; ! 742: ! 743: bcopy( ((u_int32_t *)&tmpCommand)+1, ! 744: ((u_int32_t *)&txDMACommands[txCommandTail])+1, ! 745: sizeof(enet_dma_cmd_t)-sizeof(u_int32_t) ); ! 746: ! 747: flush_cache_v( (vm_offset_t)&txDMACommands[txCommandTail], sizeof(enet_dma_cmd_t) ); ! 748: ! 749: txNetbuf[txCommandTail] = packet; ! 750: txDMACommands[txCommandTail].desc_seg[0].operation = tmpCommand.desc_seg[0].operation; ! 751: ! 752: flush_cache_v( (vm_offset_t)&txDMACommands[txCommandTail], sizeof(enet_dma_cmd_t) ); ! 753: ! 754: /* ! 755: * Set the transmit tail to the new stop command. ! 756: */ ! 757: txCommandTail = i; ! 758: ! 759: /* ! 760: * Tap the DMA channel to wake it up ! 761: */ ! 762: IODBDMAContinue( ioBaseEnetTxDMA ); ! 763: ! 764: return YES; ! 765: } ! 766: ! 767: /*------------------------------------------------------------------------- ! 768: * _receivePacket ! 769: * -------------- ! 770: * This routine runs the receiver in polled-mode (yuk!) for the kernel debugger. ! 771: * ! 772: * The _receivePackets allocate NetBufs and pass them up the stack. The kernel ! 773: * debugger interface passes a buffer into us. To reconsile the two interfaces, ! 774: * we allow the receive routine to continue to allocate its own buffers and ! 775: * transfer any received data to the passed-in buffer. This is handled by ! 776: * _receivePacket calling _packetToDebugger. ! 777: *-------------------------------------------------------------------------*/ ! 778: ! 779: - (void)_receivePacket:(void *)pkt length:(unsigned int *)pkt_len timeout:(unsigned int)timeout ! 780: { ! 781: ns_time_t startTime; ! 782: ns_time_t currentTime; ! 783: u_int32_t elapsedTimeMS; ! 784: ! 785: *pkt_len = 0; ! 786: ! 787: if (resetAndEnabled == NO) ! 788: return; ! 789: ! 790: debuggerPkt = pkt; ! 791: debuggerPktSize = 0; ! 792: ! 793: IOGetTimestamp(&startTime); ! 794: do ! 795: { ! 796: [self _receivePackets:YES]; ! 797: IOGetTimestamp(¤tTime); ! 798: elapsedTimeMS = (currentTime - startTime) / (1000*1000); ! 799: } ! 800: while ( (debuggerPktSize == 0) && (elapsedTimeMS < timeout) ); ! 801: ! 802: *pkt_len = debuggerPktSize; ! 803: ! 804: return; ! 805: } ! 806: ! 807: /*------------------------------------------------------------------------- ! 808: * _packetToDebugger ! 809: * ----------------- ! 810: * This is called by _receivePackets when we are polling for kernel debugger ! 811: * packets. It copies the NetBuf contents to the buffer passed by the debugger. ! 812: * It also sets the var debuggerPktSize which will break the polling loop. ! 813: *-------------------------------------------------------------------------*/ ! 814: ! 815: -(void) _packetToDebugger: (netbuf_t) packet ! 816: { ! 817: debuggerPktSize = nb_size(packet); ! 818: bcopy( nb_map(packet), debuggerPkt, debuggerPktSize ); ! 819: ! 820: nb_free( packet ); ! 821: } ! 822: ! 823: /*------------------------------------------------------------------------- ! 824: * _sendPacket ! 825: * ----------- ! 826: * ! 827: * This routine runs the transmitter in polled-mode (yuk!) for the kernel debugger. ! 828: * ! 829: *-------------------------------------------------------------------------*/ ! 830: ! 831: - (void)_sendPacket:(void *)pkt length:(unsigned int)pkt_len ! 832: { ! 833: ns_time_t startTime; ! 834: ns_time_t currentTime; ! 835: u_int32_t elapsedTimeMS; ! 836: int size; ! 837: ! 838: if (resetAndEnabled == NO) ! 839: return; ! 840: ! 841: /* ! 842: * Wait for the transmit ring to empty ! 843: */ ! 844: IOGetTimestamp(&startTime); ! 845: do ! 846: { ! 847: [self _transmitInterruptOccurred]; ! 848: IOGetTimestamp(¤tTime); ! 849: elapsedTimeMS = (currentTime - startTime) / (1000*1000); ! 850: } ! 851: while ( (txCommandHead != txCommandTail) && (elapsedTimeMS < TX_KDB_TIMEOUT) ); ! 852: ! 853: if ( txCommandHead != txCommandTail ) ! 854: { ! 855: IOLog( "Ethernet(Mace): Polled tranmit timeout - 1\n\r"); ! 856: return; ! 857: } ! 858: ! 859: /* ! 860: * Allocate a NetBuf and copy the debugger transmit data into it ! 861: */ ! 862: debuggerPkt = [self allocateNetbuf]; ! 863: bcopy(pkt, nb_map(debuggerPkt), pkt_len); ! 864: size = nb_size(debuggerPkt); ! 865: nb_shrink_bot(debuggerPkt, size - pkt_len); ! 866: ! 867: /* ! 868: * Send the debugger packet. _transmitPacket will free the Netbuf we allocated ! 869: * above. ! 870: */ ! 871: [self _transmitPacket: debuggerPkt]; ! 872: ! 873: /* ! 874: * Poll waiting for the transmit ring to empty again ! 875: */ ! 876: do ! 877: { ! 878: [self _transmitInterruptOccurred]; ! 879: IOGetTimestamp(¤tTime); ! 880: elapsedTimeMS = (currentTime - startTime) / (1000*1000); ! 881: } ! 882: while ( (txCommandHead != txCommandTail) && (elapsedTimeMS < TX_KDB_TIMEOUT) ); ! 883: ! 884: if ( txCommandHead != txCommandTail ) ! 885: { ! 886: IOLog( "Ethernet(Mace): Polled tranmit timeout - 2\n\r"); ! 887: return; ! 888: } ! 889: ! 890: return; ! 891: } ! 892: ! 893: /*------------------------------------------------------------------------- ! 894: * ! 895: * ! 896: * ! 897: *-------------------------------------------------------------------------*/ ! 898: ! 899: - (BOOL)_receiveInterruptOccurred ! 900: { ! 901: [self _receivePackets:NO]; ! 902: ! 903: return YES; ! 904: } ! 905: ! 906: /*------------------------------------------------------------------------- ! 907: * ! 908: * ! 909: * ! 910: *-------------------------------------------------------------------------*/ ! 911: ! 912: - (BOOL)_receivePackets:(BOOL)fDebugger ! 913: { ! 914: enet_dma_cmd_t tmpCommand; ! 915: netbuf_t packet, newPacket; ! 916: u_int32_t i,j,last; ! 917: u_int32_t dmaChnlStatus; ! 918: int receivedFrameSize = 0; ! 919: u_int32_t dmaCount[2], dmaResid[2], dmaStatus[2]; ! 920: BOOL passPacketUp; ! 921: BOOL reusePkt; ! 922: BOOL status; ! 923: u_int8_t *rxFS = NULL; ! 924: u_int32_t nextDesc; ! 925: ! 926: ! 927: last = -1; ! 928: i = rxCommandHead; ! 929: ! 930: while ( 1 ) ! 931: { ! 932: passPacketUp = NO; ! 933: reusePkt = NO; ! 934: ! 935: /* ! 936: * Purge cache references for the DBDMA entry we are about to look at. ! 937: */ ! 938: invalidate_cache_v((vm_offset_t)&rxDMACommands[i], sizeof(enet_dma_cmd_t)); ! 939: ! 940: /* ! 941: * Collect the DMA residual counts/status for the two buffer segments. ! 942: */ ! 943: for ( j = 0; j < 2; j++ ) ! 944: { ! 945: dmaResid[j] = IOGetCCResult( &rxDMACommands[i].desc_seg[j] ); ! 946: dmaStatus[j] = dmaResid[j] >> 16; ! 947: dmaResid[j] &= 0x0000ffff; ! 948: dmaCount[j] = IOGetCCOperation( &rxDMACommands[i].desc_seg[j] ) & kdbdmaReqCountMask; ! 949: } ! 950: ! 951: #if 0 ! 952: IOLog("Ethernet(Mace): Rx NetBuf[%2d] = %08x Resid[0] = %04x Status[0] = %04x Resid[1] = %04x Status[1] = %04x\n\r", ! 953: i, (int)nb_map(rxNetbuf[i]), dmaResid[0], dmaStatus[0], dmaResid[1], dmaStatus[1] ); ! 954: #endif ! 955: /* ! 956: * If the current entry has not been written, then stop at this entry ! 957: */ ! 958: if ( !((dmaStatus[0] & kdbdmaBt) || (dmaStatus[1] & kdbdmaActive)) ) ! 959: { ! 960: break; ! 961: } ! 962: ! 963: /* ! 964: * The Mace Ethernet controller appends four bytes to each receive buffer containing the buffer ! 965: * size and receive frame status. ! 966: * We locate these bytes by using the DMA residual counts. ! 967: */ ! 968: receivedFrameSize = dmaCount[0] - dmaResid[0] + dmaCount[1] - ((dmaStatus[0] & kdbdmaBt) ? dmaCount[1] : dmaResid[1]); ! 969: ! 970: if ( receivedFrameSize >= 4 ) ! 971: { ! 972: /* ! 973: * Get the receive frame size as reported by the Mace controller ! 974: */ ! 975: rxFS = (u_int8_t *)nb_map(rxNetbuf[i]) + receivedFrameSize - 4; ! 976: receivedFrameSize = (u_int16_t) rxFS[0] | (rxFS[1] & kRcvFS1RcvCnt) << 8; ! 977: } ! 978: ! 979: /* ! 980: * Reject packets that are runts or that have other mutations. ! 981: */ ! 982: if ( receivedFrameSize < (ETHERMINPACKET - ETHERCRC) || ! 983: receivedFrameSize > (ETHERMAXPACKET + ETHERCRC) || ! 984: (rxFS[1] & (kRcvFS1OFlo | kRcvFS1Clsn | kRcvFS1Fram | kRcvFS1FCS)) ) ! 985: { ! 986: [networkInterface incrementInputErrors]; ! 987: reusePkt = YES; ! 988: } ! 989: ! 990: packet = rxNetbuf[i]; ! 991: ! 992: /* ! 993: * If we are not accepting all packets, then check for multicast packets that got past the ! 994: * logical address filter but were not wanted. ! 995: */ ! 996: if ( !isPromiscuous && [super isUnwantedMulticastPacket: (ether_header_t *)nb_map(packet)] == YES ) ! 997: { ! 998: reusePkt = YES; ! 999: } ! 1000: ! 1001: /* ! 1002: * Before we pass this packet up the networking stack. Make sure we can get a replacement. ! 1003: * Otherwise, hold on to the current packet and increment the input error count. ! 1004: * Thanks Justin! ! 1005: */ ! 1006: if ( reusePkt == NO ) ! 1007: { ! 1008: newPacket = [self allocateNetbuf]; ! 1009: if ( newPacket == NULL ) ! 1010: { ! 1011: reusePkt = YES; ! 1012: [networkInterface incrementInputErrors]; ! 1013: } ! 1014: } ! 1015: ! 1016: /* ! 1017: * Install the new Netbuf for the one we're about to pass to the network stack ! 1018: */ ! 1019: if ( reusePkt == NO ) ! 1020: { ! 1021: rxNetbuf[i] = newPacket; ! 1022: passPacketUp = YES; ! 1023: status = [self _updateDescriptorFromNetBuf:rxNetbuf[i] Desc:(void *)&rxDMACommands[i] ReceiveFlag:YES] ; ! 1024: if (status == NO) ! 1025: { ! 1026: IOLog("Ethernet(Mace): _updateDescriptorFromNetBuf failed for receive\n"); ! 1027: } ! 1028: /* Adjust to size received */ ! 1029: nb_shrink_bot(packet, nb_size(packet) - receivedFrameSize); ! 1030: } ! 1031: /* ! 1032: * If we are reusing the existing Netbuf, then refurbish the existing DMA command \ ! 1033: * descriptors by clearing the status/residual count fields. ! 1034: */ ! 1035: else ! 1036: { ! 1037: for ( j=0; j < sizeof(enet_dma_cmd_t)/sizeof(IODBDMADescriptor); j++ ) ! 1038: { ! 1039: IOSetCCResult( &rxDMACommands[i].desc_seg[j], 0 ); ! 1040: } ! 1041: flush_cache_v( (vm_offset_t)&rxDMACommands[i], sizeof(enet_dma_cmd_t) ); ! 1042: } ! 1043: ! 1044: /* ! 1045: * Keep track of the last receive descriptor processed ! 1046: */ ! 1047: last = i; ! 1048: ! 1049: /* ! 1050: * Implement ring wrap-around ! 1051: */ ! 1052: if (++i >= rxMaxCommand) i = 0; ! 1053: ! 1054: /* ! 1055: * Transfer received packet to debugger or network ! 1056: */ ! 1057: if (passPacketUp) ! 1058: { ! 1059: if ( fDebugger == NO ) ! 1060: { ! 1061: // IOLog("Ethernet(Mace): Packet from network - %08x %d\n", (int) packet, (int)nb_size(packet) ); ! 1062: KERNEL_DEBUG(DBG_MACE_RXCOMPLETE | DBG_FUNC_NONE, (int) packet, (int)nb_size(packet), 0, 0, 0 ); ! 1063: [networkInterface handleInputPacket:packet extra:0]; ! 1064: } ! 1065: else ! 1066: { ! 1067: // IOLog("Ethernet(Mace): Packet to debugger - %08x %d\n", (int) packet, (int)nb_size(packet) ); ! 1068: [self _packetToDebugger: packet]; ! 1069: break; ! 1070: } ! 1071: } ! 1072: } ! 1073: ! 1074: /* ! 1075: * OK...this is a little messy ! 1076: * ! 1077: * We just processed a bunch of DMA receive descriptors. We are going to exchange the ! 1078: * current DMA stop command (rxCommandTail) with the last receive descriptor we ! 1079: * processed (last). This will make these list of descriptors we just processed available. ! 1080: * If we processed no receive descriptors on this call then skip this exchange. ! 1081: */ ! 1082: ! 1083: #if 0 ! 1084: IOLog( "Ethernet(Mace): Prev - Rx Head = %2d Rx Tail = %2d Rx Last = %2d\n\r", rxCommandHead, rxCommandTail, last ); ! 1085: #endif ! 1086: ! 1087: if ( last != -1 ) ! 1088: { ! 1089: /* ! 1090: * Save the contents of the last receive descriptor processed. ! 1091: */ ! 1092: newPacket = rxNetbuf[last]; ! 1093: tmpCommand = rxDMACommands[last]; ! 1094: ! 1095: /* ! 1096: * Write a DMA stop command into this descriptor slot ! 1097: */ ! 1098: rxDMACommands[last].desc_seg[0] = dbdmaCmd_Stop; ! 1099: rxDMACommands[last].desc_seg[1] = dbdmaCmd_Nop; ! 1100: rxNetbuf[last] = 0; ! 1101: ! 1102: flush_cache_v( (vm_offset_t)&rxDMACommands[last], sizeof(enet_dma_cmd_t) ); ! 1103: ! 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: bcopy( (u_int32_t *)&tmpCommand+1, ! 1119: (u_int32_t *)&rxDMACommands[rxCommandTail]+1, ! 1120: sizeof(enet_dma_cmd_t)-sizeof(u_int32_t) ); ! 1121: ! 1122: flush_cache_v( (vm_offset_t)&rxDMACommands[rxCommandTail], sizeof(enet_dma_cmd_t) ); ! 1123: ! 1124: ! 1125: rxNetbuf[rxCommandTail] = newPacket; ! 1126: ! 1127: rxDMACommands[rxCommandTail].desc_seg[0].operation = tmpCommand.desc_seg[0].operation; ! 1128: ! 1129: flush_cache_v( (vm_offset_t)&rxDMACommands[rxCommandTail], sizeof(IODBDMADescriptor) ); ! 1130: ! 1131: /* ! 1132: * Update rxCommmandTail to point to the new Stop command. Update rxCommandHead to point to ! 1133: * the next slot in the ring past the Stop command ! 1134: */ ! 1135: rxCommandTail = last; ! 1136: rxCommandHead = i; ! 1137: } ! 1138: ! 1139: /* ! 1140: * The DMA channel has a nasty habit of shutting down when there is a non-recoverable error ! 1141: * on receive. We get no interrupt for this since the channel shuts down before the ! 1142: * descriptor that causes the host interrupt is executed. ! 1143: * ! 1144: * We check if the channel is DEAD by checking the channel status reg. Also, the watchdog ! 1145: * timer can force receiver interrupt servicing based on detecting that the receive DMA is DEAD. ! 1146: */ ! 1147: dmaChnlStatus = IOGetDBDMAChannelStatus( ioBaseEnetRxDMA ); ! 1148: if ( dmaChnlStatus & kdbdmaDead ) ! 1149: { ! 1150: /* ! 1151: * Read log error ! 1152: */ ! 1153: [networkInterface incrementInputErrors]; ! 1154: IOLog( "Ethernet(Mace): Rx DMA Error - Status = %04x\n", dmaChnlStatus ); ! 1155: ! 1156: /* ! 1157: * Reset and reinitialize chip ! 1158: */ ! 1159: [self _restartChip]; ! 1160: } ! 1161: else ! 1162: { ! 1163: /* ! 1164: * Tap the DMA to wake it up ! 1165: */ ! 1166: IODBDMAContinue( ioBaseEnetRxDMA ); ! 1167: } ! 1168: ! 1169: #if 0 ! 1170: IOLog( "Ethernet(Mace): New - Rx Head = %2d Rx Tail = %2d\n\r", rxCommandHead, rxCommandTail ); ! 1171: #endif ! 1172: ! 1173: return YES; ! 1174: } ! 1175: ! 1176: /*------------------------------------------------------------------------- ! 1177: * ! 1178: * ! 1179: * ! 1180: *-------------------------------------------------------------------------*/ ! 1181: ! 1182: - (BOOL)_transmitInterruptOccurred ! 1183: { ! 1184: u_int32_t dmaStatus; ! 1185: u_int32_t xmtFS; ! 1186: ! 1187: while ( 1 ) ! 1188: { ! 1189: /* ! 1190: * Purge cache references for the DBDMA entry we are about to look at. ! 1191: */ ! 1192: invalidate_cache_v((vm_offset_t)&txDMACommands[txCommandHead], sizeof(enet_txdma_cmd_t)); ! 1193: ! 1194: /* ! 1195: * Check the status of the last descriptor in this entry to see if the DMA engine completed ! 1196: * this entry. ! 1197: */ ! 1198: dmaStatus = IOGetCCResult( &txDMACommands[txCommandHead].desc_seg[3] ) >> 16; ! 1199: if ( !(dmaStatus & kdbdmaActive) ) ! 1200: { ! 1201: break; ! 1202: } ! 1203: ! 1204: /* ! 1205: * Reset the status word for the entry we are about to process ! 1206: */ ! 1207: IOSetCCResult( &txDMACommands[txCommandHead].desc_seg[3], 0 ); ! 1208: flush_cache_v( (vm_offset_t) &txDMACommands[txCommandHead].desc_seg[3], sizeof(IODBDMADescriptor) ); ! 1209: ! 1210: ! 1211: /* ! 1212: * This DMA descriptor read the transmit frame status. See what it has to tell us. ! 1213: */ ! 1214: xmtFS = IOGetCCCmdDep( &txDMACommands[txCommandHead].desc_seg[2] ); ! 1215: if ( xmtFS & kXmtFSXmtSV ) ! 1216: { ! 1217: if (xmtFS & (kXmtFSUFlo | kXmtFSLCol | kXmtFSRtry | kXmtFSLCar) ) ! 1218: { ! 1219: [networkInterface incrementOutputErrors]; ! 1220: } ! 1221: else ! 1222: { ! 1223: [networkInterface incrementOutputPackets]; ! 1224: } ! 1225: ! 1226: if (xmtFS & kXmtFSOne ) ! 1227: { ! 1228: [networkInterface incrementCollisions]; ! 1229: } ! 1230: if ( xmtFS & kXmtFSMore ) ! 1231: { ! 1232: [networkInterface incrementCollisions]; ! 1233: } ! 1234: } ! 1235: ! 1236: /* ! 1237: * Free the Netbuf we just transmitted ! 1238: */ ! 1239: KERNEL_DEBUG(DBG_MACE_TXCOMPLETE | DBG_FUNC_NONE, (int) txNetbuf[txCommandHead], (int) nb_size(txNetbuf[txCommandHead]), 0, 0, 0 ); ! 1240: nb_free( txNetbuf[txCommandHead] ); ! 1241: txNetbuf[txCommandHead] = NULL; ! 1242: ! 1243: if ( ++txCommandHead >= txMaxCommand ) txCommandHead = 0; ! 1244: ! 1245: } ! 1246: ! 1247: /* ! 1248: * The DMA channel has a nasty habit of shutting down when there is non-recoverable error ! 1249: * on transmit. We get no interrupt for this since the channel shuts down before the ! 1250: * descriptor that causes the host interrupt is executed. ! 1251: * ! 1252: * We check if the channel is DEAD by checking the channel status reg. Also, the watchdog ! 1253: * timer can force a transmitter reset if it sees no interrupt activity for to consecutive ! 1254: * timeout intervals. ! 1255: */ ! 1256: ! 1257: dmaStatus = IOGetDBDMAChannelStatus( ioBaseEnetTxDMA ); ! 1258: if ( dmaStatus & kdbdmaDead || txWDForceReset == YES ) ! 1259: { ! 1260: /* ! 1261: * Read the transmit frame status and log error ! 1262: */ ! 1263: xmtFS = ReadMaceRegister( ioBaseEnet, kXmtFS ); ! 1264: [networkInterface incrementOutputErrors]; ! 1265: IOLog( "Ethernet(Mace): Tx DMA Error - Status = %04x FS = %02x\n\r", dmaStatus, xmtFS); ! 1266: ! 1267: /* ! 1268: * Reset and reinitialize chip ! 1269: */ ! 1270: [self _restartChip]; ! 1271: ! 1272: txWDForceReset = NO; ! 1273: } ! 1274: ! 1275: return YES; ! 1276: } ! 1277: ! 1278: ! 1279: /* ! 1280: * Breaks up an ethernet data buffer into two physical chunks. We know that ! 1281: * the buffer can't straddle more than two pages. If the content of paddr2 is ! 1282: * zero this means that all of the buffer lies in one physical page. Note ! 1283: * that we use the fact that tx and rx descriptors have the same size and ! 1284: * same layout of relevent fields (data address and count). ! 1285: */ ! 1286: ! 1287: -(BOOL) _updateDescriptorFromNetBuf:(netbuf_t)nb Desc:(enet_dma_cmd_t *)desc ReceiveFlag:(BOOL)isReceive ! 1288: { ! 1289: IOReturn result; ! 1290: vm_address_t pageBreak; ! 1291: vm_address_t vaddr; ! 1292: u_int32_t paddr[2]; ! 1293: u_int32_t len[2]; ! 1294: u_int32_t size; ! 1295: u_int32_t nextDesc = 0; ! 1296: ! 1297: size = isReceive ? NETWORK_BUFSIZE : nb_size(nb); ! 1298: vaddr = (vm_address_t)nb_map(nb); ! 1299: ! 1300: result = IOPhysicalFromVirtual(IOVmTaskSelf(), vaddr, &paddr[0]); ! 1301: if (result != IO_R_SUCCESS) ! 1302: { ! 1303: return NO; ! 1304: } ! 1305: ! 1306: /* ! 1307: * Now check if this memory block crosses a page boundary. ! 1308: */ ! 1309: if (trunc_page(vaddr) != trunc_page(vaddr+size-1)) ! 1310: { ! 1311: /* Nice try... */ ! 1312: pageBreak = round_page(vaddr); ! 1313: len[0] = pageBreak - vaddr; ! 1314: len[1] = size - (pageBreak - vaddr); ! 1315: ! 1316: result = IOPhysicalFromVirtual(IOVmTaskSelf(), pageBreak, &paddr[1]); ! 1317: if (result != IO_R_SUCCESS) ! 1318: { ! 1319: return NO; ! 1320: } ! 1321: } ! 1322: else ! 1323: { ! 1324: paddr[1] = 0; ! 1325: len[0] = size; ! 1326: len[1] = 0; ! 1327: } ! 1328: ! 1329: if ( !len[1] ) ! 1330: { ! 1331: IOMakeDBDMADescriptor( (&desc->desc_seg[0]), ! 1332: ((isReceive) ? kdbdmaInputLast : kdbdmaOutputLast), ! 1333: (kdbdmaKeyStream0), ! 1334: (kdbdmaIntNever), ! 1335: (kdbdmaBranchNever), ! 1336: ((isReceive) ? kdbdmaWaitNever : kdbdmaWaitIfFalse), ! 1337: (len[0]), ! 1338: (paddr[0]) ); ! 1339: ! 1340: desc->desc_seg[1] = (isReceive) ? dbdmaCmd_NopWInt : dbdmaCmd_Nop; ! 1341: } ! 1342: else ! 1343: { ! 1344: if ( isReceive ) ! 1345: { ! 1346: nextDesc = rxDMACommandsPhys + (int)desc - (int)rxDMACommands + sizeof(enet_dma_cmd_t); ! 1347: } ! 1348: ! 1349: IOMakeDBDMADescriptorDep( (&desc->desc_seg[0]), ! 1350: ((isReceive) ? kdbdmaInputMore : kdbdmaOutputMore), ! 1351: (kdbdmaKeyStream0), ! 1352: ((isReceive) ? kdbdmaIntIfTrue : kdbdmaIntNever), ! 1353: ((isReceive) ? kdbdmaBranchIfTrue : kdbdmaBranchNever), ! 1354: (kdbdmaWaitNever), ! 1355: (len[0]), ! 1356: (paddr[0]), ! 1357: nextDesc ); ! 1358: ! 1359: IOMakeDBDMADescriptor( (&desc->desc_seg[1]), ! 1360: ((isReceive) ? kdbdmaInputLast : kdbdmaOutputLast), ! 1361: (kdbdmaKeyStream0), ! 1362: ((isReceive) ? kdbdmaIntAlways : kdbdmaIntNever), ! 1363: (kdbdmaBranchNever), ! 1364: ((isReceive) ? kdbdmaWaitNever : kdbdmaWaitIfFalse), ! 1365: (len[1]), ! 1366: (paddr[1]) ); ! 1367: } ! 1368: ! 1369: flush_cache_v( (vm_offset_t)desc, sizeof(enet_dma_cmd_t) ); ! 1370: ! 1371: return YES; ! 1372: } ! 1373: ! 1374: ! 1375: #ifdef DEBUG ! 1376: /* ! 1377: * Useful for testing. ! 1378: */ ! 1379: - (void)_dumpDesc:(void *)addr Size:(u_int32_t)size ! 1380: { ! 1381: u_int32_t i; ! 1382: unsigned long *p; ! 1383: vm_offset_t paddr; ! 1384: ! 1385: IOPhysicalFromVirtual( IOVmTaskSelf(), (vm_offset_t) addr, (vm_offset_t *)&paddr ); ! 1386: ! 1387: p = (unsigned long *)addr; ! 1388: ! 1389: for ( i=0; i < size/sizeof(IODBDMADescriptor); i++, p+=4, paddr+=sizeof(IODBDMADescriptor) ) ! 1390: { ! 1391: IOLog("Ethernet(Mace): %08x(v) %0x08(p): %08x %08x %08x %08x\n", ! 1392: (int)p, ! 1393: (int)paddr, ! 1394: (int)ReadSwap32(p, 0), (int)ReadSwap32(p, 4), ! 1395: (int)ReadSwap32(p, 8), (int)ReadSwap32(p, 12) ); ! 1396: } ! 1397: IOLog("\n"); ! 1398: } ! 1399: ! 1400: - (void)_dumpRegisters ! 1401: { ! 1402: u_int8_t dataValue; ! 1403: ! 1404: IOLog("\nEthernet(Mace): IO Address = %08x", (int)ioBaseEnet ); ! 1405: ! 1406: dataValue = ReadMaceRegister(ioBaseEnet, kXmtFC); ! 1407: IOLog("\nEthernet(Mace): Read Register %04x Transmit Frame Control = %02x", kXmtFC, dataValue ); ! 1408: ! 1409: dataValue = ReadMaceRegister(ioBaseEnet, kXmtFS); ! 1410: IOLog("\nEthernet(Mace): Read Register %04x Transmit Frame Status = %02x", kXmtFS, dataValue ); ! 1411: ! 1412: dataValue = ReadMaceRegister(ioBaseEnet, kXmtRC); ! 1413: IOLog("\nEthernet(Mace): Read Register %04x Transmit Retry Count = %02x", kXmtRC, dataValue ); ! 1414: ! 1415: dataValue = ReadMaceRegister(ioBaseEnet, kRcvFC); ! 1416: IOLog("\nEthernet(Mace): Read Register %04x Receive Frame Control = %02x", kRcvFC, dataValue ); ! 1417: ! 1418: dataValue = ReadMaceRegister(ioBaseEnet, kRcvFS0); ! 1419: IOLog("\nEthernet(Mace): Read Register %04x Receive Frame Status 0 = %02x", kRcvFS0, dataValue ); ! 1420: dataValue = ReadMaceRegister(ioBaseEnet, kRcvFS1); ! 1421: IOLog("\nEthernet(Mace): Read Register %04x Receive Frame Status 1 = %02x", kRcvFS1, dataValue ); ! 1422: dataValue = ReadMaceRegister(ioBaseEnet, kRcvFS2); ! 1423: IOLog("\nEthernet(Mace): Read Register %04x Receive Frame Status 2 = %02x", kRcvFS2, dataValue ); ! 1424: dataValue = ReadMaceRegister(ioBaseEnet, kRcvFS3); ! 1425: IOLog("\nEthernet(Mace): Read Register %04x Receive Frame Status 3 = %02x", kRcvFS3, dataValue ); ! 1426: ! 1427: dataValue = ReadMaceRegister(ioBaseEnet, kFifoFC); ! 1428: IOLog("\nEthernet(Mace): Read Register %04x FIFO Frame Count = %02x", kFifoFC, dataValue ); ! 1429: ! 1430: dataValue = ReadMaceRegister(ioBaseEnet, kIntReg); ! 1431: IOLog("\nEthernet(Mace): Read Register %04x Interrupt Register = %02x", kIntReg, dataValue ); ! 1432: ! 1433: dataValue = ReadMaceRegister(ioBaseEnet, kIntMask); ! 1434: IOLog("\nEthernet(Mace): Read Register %04x Interrupt Mask Register = %02x", kIntMask, dataValue ); ! 1435: ! 1436: dataValue = ReadMaceRegister(ioBaseEnet, kPollReg); ! 1437: IOLog("\nEthernet(Mace): Read Register %04x Poll Register = %02x", kPollReg, dataValue ); ! 1438: ! 1439: dataValue = ReadMaceRegister(ioBaseEnet, kBIUCC); ! 1440: IOLog("\nEthernet(Mace): Read Register %04x BUI Configuration Control = %02x", kBIUCC, dataValue ); ! 1441: ! 1442: dataValue = ReadMaceRegister(ioBaseEnet, kFifoCC); ! 1443: IOLog("\nEthernet(Mace): Read Register %04x FIFO Configuration Control = %02x", kFifoCC, dataValue ); ! 1444: ! 1445: dataValue = ReadMaceRegister(ioBaseEnet, kMacCC); ! 1446: IOLog("\nEthernet(Mace): Read Register %04x MAC Configuration Control = %02x", kMacCC, dataValue ); ! 1447: ! 1448: dataValue = ReadMaceRegister(ioBaseEnet, kPLSCC); ! 1449: IOLog("\nEthernet(Mace): Read Register %04x PLS Configuration Contro = %02x", kPLSCC, dataValue ); ! 1450: ! 1451: dataValue = ReadMaceRegister(ioBaseEnet, kPHYCC); ! 1452: IOLog("\nEthernet(Mace): Read Register %04x PHY Configuration Control = %02x", kPHYCC, dataValue ); ! 1453: ! 1454: dataValue = ReadMaceRegister(ioBaseEnet, kMaceChipId0); ! 1455: IOLog("\nEthernet(Mace): Read Register %04x MACE ChipID Register 7:0 = %02x", kMaceChipId0, dataValue ); ! 1456: ! 1457: dataValue = ReadMaceRegister(ioBaseEnet, kMaceChipId1); ! 1458: IOLog("\nEthernet(Mace): Read Register %04x MACE ChipID Register 15:8 = %02x", kMaceChipId1, dataValue ); ! 1459: ! 1460: dataValue = ReadMaceRegister(ioBaseEnet, kMPC); ! 1461: IOLog("\nEthernet(Mace): Read Register %04x Missed Packet Count = %02x", kMPC, dataValue ); ! 1462: ! 1463: dataValue = ReadMaceRegister(ioBaseEnet, kUTR); ! 1464: IOLog("\nEthernet(Mace): Read Register %04x User Test Register = %02x", kUTR, dataValue ); ! 1465: IOLog("\nEthernet(Mace): -------------------------------------------------------\n" ); ! 1466: } ! 1467: #endif DEBUG ! 1468: ! 1469: ! 1470: /*------------------------------------------------------------------------- ! 1471: * ! 1472: * ! 1473: * ! 1474: *-------------------------------------------------------------------------*/ ! 1475: ! 1476: - (void)_getStationAddress:(enet_addr_t *)ea ! 1477: { ! 1478: int i; ! 1479: unsigned char data; ! 1480: ! 1481: for (i = 0; i < sizeof(*ea); i++) ! 1482: { ! 1483: data = ((unsigned char *)ioBaseEnetROM)[i << 4]; ! 1484: ea->ea_byte[i] = reverseBitOrder(data); ! 1485: } ! 1486: } ! 1487: ! 1488: ! 1489: ! 1490: /*------------------------------------------------------------------------- ! 1491: * ! 1492: * ! 1493: * ! 1494: *-------------------------------------------------------------------------*/ ! 1495: ! 1496: #define ENET_CRCPOLY 0x04c11db7 ! 1497: ! 1498: /* Real fast bit-reversal algorithm, 6-bit values */ ! 1499: static int reverse6[] = ! 1500: { 0x0,0x20,0x10,0x30,0x8,0x28,0x18,0x38, ! 1501: 0x4,0x24,0x14,0x34,0xc,0x2c,0x1c,0x3c, ! 1502: 0x2,0x22,0x12,0x32,0xa,0x2a,0x1a,0x3a, ! 1503: 0x6,0x26,0x16,0x36,0xe,0x2e,0x1e,0x3e, ! 1504: 0x1,0x21,0x11,0x31,0x9,0x29,0x19,0x39, ! 1505: 0x5,0x25,0x15,0x35,0xd,0x2d,0x1d,0x3d, ! 1506: 0x3,0x23,0x13,0x33,0xb,0x2b,0x1b,0x3b, ! 1507: 0x7,0x27,0x17,0x37,0xf,0x2f,0x1f,0x3f ! 1508: }; ! 1509: ! 1510: static u_int32_t crc416(unsigned int current, unsigned short nxtval ) ! 1511: { ! 1512: register unsigned int counter; ! 1513: register int highCRCBitSet, lowDataBitSet; ! 1514: ! 1515: /* Swap bytes */ ! 1516: nxtval = ((nxtval & 0x00FF) << 8) | (nxtval >> 8); ! 1517: ! 1518: /* Compute bit-by-bit */ ! 1519: for (counter = 0; counter != 16; ++counter) ! 1520: { /* is high CRC bit set? */ ! 1521: if ((current & 0x80000000) == 0) ! 1522: highCRCBitSet = 0; ! 1523: else ! 1524: highCRCBitSet = 1; ! 1525: ! 1526: current = current << 1; ! 1527: ! 1528: if ((nxtval & 0x0001) == 0) ! 1529: lowDataBitSet = 0; ! 1530: else ! 1531: lowDataBitSet = 1; ! 1532: ! 1533: nxtval = nxtval >> 1; ! 1534: ! 1535: /* do the XOR */ ! 1536: if (highCRCBitSet ^ lowDataBitSet) ! 1537: current = current ^ ENET_CRCPOLY; ! 1538: } ! 1539: return current; ! 1540: } ! 1541: ! 1542: /*------------------------------------------------------------------------- ! 1543: * ! 1544: * ! 1545: * ! 1546: *-------------------------------------------------------------------------*/ ! 1547: ! 1548: static u_int32_t mace_crc(unsigned short *address) ! 1549: { ! 1550: register u_int32_t newcrc; ! 1551: ! 1552: newcrc = crc416(0xffffffff, *address); /* address bits 47 - 32 */ ! 1553: newcrc = crc416(newcrc, address[1]); /* address bits 31 - 16 */ ! 1554: newcrc = crc416(newcrc, address[2]); /* address bits 15 - 0 */ ! 1555: ! 1556: return(newcrc); ! 1557: } ! 1558: ! 1559: /* ! 1560: * Add requested mcast addr to Mace's hash table filter. ! 1561: * ! 1562: */ ! 1563: -(void) _addToHashTableMask:(u_int8_t *)addr ! 1564: { ! 1565: u_int32_t crc; ! 1566: u_int8_t mask; ! 1567: ! 1568: crc = mace_crc((unsigned short *)addr)&0x3f; /* Big-endian alert! */ ! 1569: crc = reverse6[crc]; /* Hyperfast bit-reversing algorithm */ ! 1570: if (hashTableUseCount[crc]++) ! 1571: return; /* This bit is already set */ ! 1572: mask = crc % 8; ! 1573: mask = (unsigned char) 1 << mask; ! 1574: hashTableMask[crc/8] |= mask; ! 1575: } ! 1576: ! 1577: /*------------------------------------------------------------------------- ! 1578: * ! 1579: * ! 1580: * ! 1581: *-------------------------------------------------------------------------*/ ! 1582: ! 1583: -(void) _removeFromHashTableMask:(u_int8_t *)addr ! 1584: { ! 1585: unsigned int crc; ! 1586: unsigned char mask; ! 1587: ! 1588: /* Now, delete the address from the filter copy, as indicated */ ! 1589: crc = mace_crc((unsigned short *)addr)&0x3f; /* Big-endian alert! */ ! 1590: crc = reverse6[crc]; /* Hyperfast bit-reversing algorithm */ ! 1591: if (hashTableUseCount[crc] == 0) ! 1592: return; /* That bit wasn't in use! */ ! 1593: ! 1594: if (--hashTableUseCount[crc]) ! 1595: return; /* That bit is still in use */ ! 1596: ! 1597: mask = crc % 8; ! 1598: mask = ((unsigned char)1 << mask) ^ 0xffff; /* To turn off bit */ ! 1599: hashTableMask[crc/8] &= mask; ! 1600: } ! 1601: ! 1602: /* ! 1603: * Sync the adapter with the software copy of the multicast mask ! 1604: * (logical address filter). ! 1605: */ ! 1606: -(void) _updateHashTableMask ! 1607: { ! 1608: u_int8_t status; ! 1609: u_int32_t i; ! 1610: u_int8_t *p; ! 1611: ! 1612: if ( chipId != kMaceRevisionA2 ) ! 1613: { ! 1614: WriteMaceRegister( ioBaseEnet, kIAC, kIACAddrChg | kIACLogAddr ); ! 1615: do ! 1616: { ! 1617: status = ReadMaceRegister( ioBaseEnet, kIAC ); ! 1618: } ! 1619: while( status & kIACAddrChg ); ! 1620: } ! 1621: else ! 1622: { ! 1623: WriteMaceRegister( ioBaseEnet, kIAC, kIACLogAddr ); ! 1624: } ! 1625: ! 1626: p = (u_int8_t *) hashTableMask; ! 1627: for (i = 0; i < 8; i++, p++ ) ! 1628: { ! 1629: WriteMaceRegister( ioBaseEnet, kLADRF, *p ); ! 1630: } ! 1631: } ! 1632: ! 1633: @end ! 1634:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.