|
|
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: * Hardware independent (relatively) code for the Mace Ethernet Controller ! 29: * ! 30: * HISTORY ! 31: * ! 32: * dd-mmm-yy ! 33: * Created. ! 34: * ! 35: */ ! 36: ! 37: #import "MaceEnetPrivate.h" ! 38: ! 39: @implementation MaceEnet ! 40: ! 41: /* ! 42: * Public Factory Methods ! 43: */ ! 44: ! 45: + (BOOL)probe:(IODeviceDescription *)devDesc ! 46: { ! 47: MaceEnet *MaceEnetInstance; ! 48: extern int kdp_flag; ! 49: ! 50: /* ! 51: * If bootargs: kdp bit 0 using in-kernel mace driver for early debugging, ! 52: * Don't probe this driver. ! 53: */ ! 54: if( kdp_flag & 1) ! 55: { ! 56: return nil; ! 57: } ! 58: ! 59: MaceEnetInstance = [self alloc]; ! 60: return [MaceEnetInstance initFromDeviceDescription:devDesc] != nil; ! 61: } ! 62: ! 63: /* ! 64: * Public Instance Methods ! 65: */ ! 66: ! 67: /*------------------------------------------------------------------------- ! 68: * ! 69: * ! 70: * ! 71: *-------------------------------------------------------------------------*/ ! 72: ! 73: - initFromDeviceDescription:(IOTreeDevice *)devDesc ! 74: { ! 75: IORange *ioRangeMace; ! 76: ! 77: if ([super initFromDeviceDescription:devDesc] == nil) ! 78: { ! 79: IOLog( "Ethernet(Mace): [super initFromDeviceDescription] failed\n"); ! 80: return nil; ! 81: } ! 82: ! 83: if ( [devDesc numMemoryRanges] < 3 ) ! 84: { ! 85: IOLog( "Ethernet(Mace): Incorrect deviceDescription - 1\n\r"); ! 86: return nil; ! 87: } ! 88: ! 89: ioRangeMace = [devDesc memoryRangeList]; ! 90: ! 91: ioBaseEnet = (IOPPCAddress) ioRangeMace[0].start; ! 92: ioBaseEnetTxDMA = (IOPPCAddress) ioRangeMace[1].start; ! 93: ioBaseEnetRxDMA = (IOPPCAddress) ioRangeMace[2].start; ! 94: ! 95: ioBaseEnetROM = (IOPPCAddress) (((unsigned int) ioBaseEnet & ~0xffff) | kControllerROMOffset); ! 96: ! 97: if ( ![self resetAndEnable:NO] ) ! 98: { ! 99: [self free]; ! 100: return nil; ! 101: } ! 102: ! 103: [self _getStationAddress:&myAddress]; ! 104: ! 105: if ([self _allocateMemory] == NO) ! 106: { ! 107: [self free]; ! 108: return nil; ! 109: } ! 110: ! 111: if ( ![self resetAndEnable:YES] ) ! 112: { ! 113: [self free]; ! 114: return nil; ! 115: } ! 116: ! 117: isPromiscuous = NO; ! 118: multicastEnabled = NO; ! 119: ! 120: networkInterface = [super attachToNetworkWithAddress:myAddress]; ! 121: ! 122: return self; ! 123: } ! 124: ! 125: ! 126: /*------------------------------------------------------------------------- ! 127: * ! 128: * ! 129: * ! 130: *-------------------------------------------------------------------------*/ ! 131: ! 132: - free ! 133: { ! 134: int i; ! 135: ! 136: [self clearTimeout]; ! 137: ! 138: [self _resetChip]; ! 139: ! 140: if (networkInterface) ! 141: [networkInterface free]; ! 142: ! 143: for (i = 0; i < rxMaxCommand; i++) ! 144: if (rxNetbuf[i]) nb_free(rxNetbuf[i]); ! 145: ! 146: for (i = 0; i < txMaxCommand; i++) ! 147: if (txNetbuf[i]) nb_free(txNetbuf[i]); ! 148: ! 149: return [super free]; ! 150: } ! 151: ! 152: /*------------------------------------------------------------------------- ! 153: * ! 154: * ! 155: * ! 156: *-------------------------------------------------------------------------*/ ! 157: - (void) interruptOccurredAt:(int)irqNum ! 158: { ! 159: ! 160: [self reserveDebuggerLock]; ! 161: ! 162: // kprintf("IRQ = %d\n",irqNum ); ! 163: ! 164: switch ( irqNum ) ! 165: { ! 166: case kIRQEnetTxDMA: ! 167: txWDInterrupts++; ! 168: KERNEL_DEBUG(DBG_MACE_TXIRQ | DBG_FUNC_START, 0, 0, 0, 0, 0 ); ! 169: [self _transmitInterruptOccurred]; ! 170: KERNEL_DEBUG(DBG_MACE_TXIRQ | DBG_FUNC_END, 0, 0, 0, 0, 0 ); ! 171: [self enableInterrupt:kIRQEnetTxDMA]; ! 172: [self serviceTransmitQueue]; ! 173: break; ! 174: case kIRQEnetRxDMA: ! 175: KERNEL_DEBUG(DBG_MACE_RXIRQ | DBG_FUNC_START, 0, 0, 0, 0, 0 ); ! 176: [self _receiveInterruptOccurred]; ! 177: KERNEL_DEBUG(DBG_MACE_RXIRQ | DBG_FUNC_END, 0, 0, 0, 0, 0 ); ! 178: [self enableInterrupt:kIRQEnetRxDMA]; ! 179: break; ! 180: } ! 181: ! 182: [self releaseDebuggerLock]; ! 183: } ! 184: ! 185: ! 186: /*------------------------------------------------------------------------- ! 187: * ! 188: * ! 189: * ! 190: *-------------------------------------------------------------------------*/ ! 191: ! 192: - (void) serviceTransmitQueue ! 193: { ! 194: netbuf_t packet; ! 195: u_int32_t i; ! 196: ! 197: while ( 1 ) ! 198: { ! 199: if ( ![transmitQueue count] ) ! 200: { ! 201: break; ! 202: } ! 203: ! 204: i = txCommandTail + 1; ! 205: if ( i >= txMaxCommand ) i = 0; ! 206: if ( i == txCommandHead ) ! 207: { ! 208: break; ! 209: } ! 210: packet = [transmitQueue dequeue]; ! 211: [self _transmitPacket:packet]; ! 212: } ! 213: ! 214: } ! 215: ! 216: /*------------------------------------------------------------------------- ! 217: * ! 218: * ! 219: * ! 220: *-------------------------------------------------------------------------*/ ! 221: ! 222: - (void)transmit:(netbuf_t)pkt ! 223: { ! 224: u_int32_t i; ! 225: u_int32_t n; ! 226: u_int8_t regValue; ! 227: ! 228: KERNEL_DEBUG(DBG_MACE_TXQUEUE | DBG_FUNC_NONE, (int) pkt, (int) nb_size(pkt), 0, 0, 0 ); ! 229: ! 230: /* ! 231: * Hold the debugger lock so the debugger can't interrupt us ! 232: */ ! 233: [self reserveDebuggerLock]; ! 234: ! 235: do ! 236: { ! 237: /* ! 238: * Someone is turning off the receiver before the first transmit. ! 239: * Dont know who yet! ! 240: */ ! 241: regValue = ReadMaceRegister( ioBaseEnet, kMacCC ); ! 242: regValue |= kMacCCEnRcv; ! 243: WriteMaceRegister( ioBaseEnet, kMacCC, regValue ); ! 244: ! 245: /* ! 246: * Preliminary sanity checks ! 247: */ ! 248: if (!pkt) ! 249: { ! 250: IOLog("EtherNet(Mace): transmit received NULL netbuf\n"); ! 251: continue; ! 252: } ! 253: if ( ![self isRunning] ) ! 254: { ! 255: nb_free(pkt); ! 256: continue; ! 257: } ! 258: ! 259: /* ! 260: * Remove any completed packets from the Tx ring ! 261: */ ! 262: [self _transmitInterruptOccurred]; ! 263: ! 264: /* ! 265: * Refill the Tx ring from the Transmit waiting list ! 266: */ ! 267: [self serviceTransmitQueue]; ! 268: ! 269: /* ! 270: * If the Transmit waiting list is not empty or the Tx ring is ! 271: * full, add the new packet to the waiting list. ! 272: */ ! 273: n = [transmitQueue count]; ! 274: if ( n > 0 ) ! 275: { ! 276: if ( n >= [transmitQueue maxCount] ) ! 277: { ! 278: IOLog("Ethernet(Mace) Transmit queue overflow\n"); ! 279: } ! 280: ! 281: [transmitQueue enqueue:pkt]; ! 282: continue; ! 283: } ! 284: i = txCommandTail + 1; ! 285: if ( i >= txMaxCommand ) i = 0; ! 286: if ( i == txCommandHead ) ! 287: { ! 288: [transmitQueue enqueue:pkt]; ! 289: continue; ! 290: } ! 291: ! 292: /* ! 293: * If there is space on the Tx ring, add the packet directly to the ! 294: * ring ! 295: */ ! 296: [self _transmitPacket:pkt]; ! 297: } ! 298: while( 0 ); ! 299: ! 300: [self releaseDebuggerLock]; ! 301: ! 302: } ! 303: ! 304: /*------------------------------------------------------------------------- ! 305: * ! 306: * ! 307: * ! 308: *-------------------------------------------------------------------------*/ ! 309: ! 310: - (int) transmitQueueSize ! 311: { ! 312: return (TRANSMIT_QUEUE_SIZE); ! 313: } ! 314: ! 315: - (int) transmitQueueCount ! 316: { ! 317: return ([transmitQueue count]); ! 318: } ! 319: /*------------------------------------------------------------------------- ! 320: * ! 321: * ! 322: * ! 323: *-------------------------------------------------------------------------*/ ! 324: ! 325: - (BOOL)resetAndEnable:(BOOL)enable ! 326: { ! 327: resetAndEnabled = NO; ! 328: [self clearTimeout]; ! 329: [self disableAllInterrupts]; ! 330: [self _resetChip]; ! 331: ! 332: if (enable) ! 333: { ! 334: if ( ![self _initRxRing] || ![self _initTxRing] || ![self _initChip] ) ! 335: { ! 336: [self setRunning:NO]; ! 337: return NO; ! 338: } ! 339: ! 340: [self _startChip]; ! 341: ! 342: [self setRelativeTimeout: WATCHDOG_TIMER_MS]; ! 343: ! 344: [self enableInterrupt:kIRQEnetRxDMA]; ! 345: [self enableInterrupt:kIRQEnetTxDMA]; ! 346: [self _enableAdapterInterrupts]; ! 347: ! 348: resetAndEnabled = YES; ! 349: } ! 350: ! 351: [self setRunning:enable]; ! 352: ! 353: return YES; ! 354: } ! 355: ! 356: /*------------------------------------------------------------------------- ! 357: * ! 358: * ! 359: * ! 360: *-------------------------------------------------------------------------*/ ! 361: ! 362: - (void)timeoutOccurred ! 363: { ! 364: u_int32_t dmaStatus; ! 365: ! 366: if ( ![self isRunning] ) ! 367: { ! 368: return; ! 369: } ! 370: ! 371: [self reserveDebuggerLock]; ! 372: ! 373: /* ! 374: * Check for DMA shutdown on receive channel ! 375: */ ! 376: dmaStatus = IOGetDBDMAChannelStatus( ioBaseEnetRxDMA ); ! 377: if ( !(dmaStatus & kdbdmaActive) ) ! 378: { ! 379: IOLog( "Ethernet(Mace): Checking for timeout - RxHead = %d RxTail = %d\n\r", rxCommandHead, rxCommandTail); ! 380: #if 0 ! 381: IOLog( "Ethernet(Mace): Rx Commands = %08x(p) Rx DMA Ptr = %08x(p)\n\r", rxDMACommandsPhys, IOGetDBDMACommandPtr(ioBaseEnetRxDMA) ); ! 382: [self _dumpDesc:(void *)rxDMACommands Size:rxMaxCommand * sizeof(enet_dma_cmd_t)]; ! 383: #endif ! 384: [self _receiveInterruptOccurred]; ! 385: } ! 386: ! 387: /* ! 388: * If there are pending entries on the Tx ring ! 389: */ ! 390: if ( txCommandHead != txCommandTail ) ! 391: { ! 392: /* ! 393: * If we did not service the Tx ring during the last timeout interval, ! 394: * then force servicing of the Tx ring. ! 395: * If we have more than one timeout interval without any transmit interrupts, ! 396: * then force the transmitter to reset. ! 397: */ ! 398: if ( txWDInterrupts == 0 ) ! 399: { ! 400: if ( ++txWDTimeouts > 1 ) txWDForceReset = YES; ! 401: ! 402: IOLog( "Ethernet(Mace): Checking for timeout - TxHead = %d TxTail = %d\n\r", txCommandHead, txCommandTail); ! 403: [self _transmitInterruptOccurred]; ! 404: } ! 405: else ! 406: { ! 407: txWDTimeouts = 0; ! 408: txWDInterrupts = 0; ! 409: } ! 410: } ! 411: else ! 412: { ! 413: txWDTimeouts = 0; ! 414: txWDInterrupts = 0; ! 415: } ! 416: ! 417: /* ! 418: * Restart the watchdog timer ! 419: */ ! 420: [self setRelativeTimeout: WATCHDOG_TIMER_MS]; ! 421: ! 422: [self releaseDebuggerLock]; ! 423: ! 424: } ! 425: ! 426: /*------------------------------------------------------------------------- ! 427: * ! 428: * ! 429: * ! 430: *-------------------------------------------------------------------------*/ ! 431: ! 432: - (netbuf_t)allocateNetbuf ! 433: { ! 434: netbuf_t packet; ! 435: ! 436: packet = nb_alloc(NETWORK_BUFSIZE); ! 437: if (!packet) ! 438: { ! 439: IOLog("nb_alloc() returned NULL\n"); ! 440: } ! 441: ! 442: return packet; ! 443: } ! 444: ! 445: /*------------------------------------------------------------------------- ! 446: * ! 447: * ! 448: * ! 449: *-------------------------------------------------------------------------*/ ! 450: ! 451: - (BOOL)enablePromiscuousMode ! 452: { ! 453: u_int8_t regVal; ! 454: ! 455: isPromiscuous = YES; ! 456: ! 457: [self reserveDebuggerLock]; ! 458: ! 459: regVal = ReadMaceRegister( ioBaseEnet, kMacCC ); ! 460: WriteMaceRegister( ioBaseEnet, kMacCC, regVal & ~kMacCCEnRcv ); ! 461: regVal |= kMacCCProm; ! 462: WriteMaceRegister( ioBaseEnet, kMacCC, regVal ); ! 463: ! 464: [self releaseDebuggerLock]; ! 465: ! 466: return YES; ! 467: } ! 468: ! 469: - (void)disablePromiscuousMode ! 470: { ! 471: u_int8_t regVal; ! 472: ! 473: isPromiscuous = NO; ! 474: ! 475: [self reserveDebuggerLock]; ! 476: ! 477: regVal = ReadMaceRegister(ioBaseEnet, kMacCC); ! 478: WriteMaceRegister( ioBaseEnet, kMacCC, regVal & ~kMacCCEnRcv ); ! 479: regVal &= ~kMacCCProm; ! 480: WriteMaceRegister( ioBaseEnet, kMacCC, regVal ); ! 481: ! 482: [self releaseDebuggerLock]; ! 483: ! 484: } ! 485: ! 486: - (BOOL)enableMulticastMode ! 487: { ! 488: multicastEnabled = YES; ! 489: return YES; ! 490: } ! 491: ! 492: - (void)disableMulticastMode ! 493: { ! 494: multicastEnabled = NO; ! 495: } ! 496: ! 497: - (void)addMulticastAddress:(enet_addr_t *)addr ! 498: { ! 499: multicastEnabled = YES; ! 500: [self reserveDebuggerLock]; ! 501: [self _addToHashTableMask:addr->ea_byte]; ! 502: [self _updateHashTableMask]; ! 503: [self releaseDebuggerLock]; ! 504: } ! 505: ! 506: - (void)removeMulticastAddress:(enet_addr_t *)addr ! 507: { ! 508: [self reserveDebuggerLock]; ! 509: [self _removeFromHashTableMask:addr->ea_byte]; ! 510: [self _updateHashTableMask]; ! 511: [self releaseDebuggerLock]; ! 512: } ! 513: ! 514: /* ! 515: * Kernel Debugger Support ! 516: */ ! 517: - (void)sendPacket:(void *)pkt length:(unsigned int)pkt_len ! 518: { ! 519: [self _sendPacket:(void *)pkt length:(unsigned int)pkt_len]; ! 520: } ! 521: ! 522: - (void)receivePacket:(void *)pkt length:(unsigned int *)pkt_len timeout:(unsigned int)timeout ! 523: { ! 524: [self _receivePacket:(void *)pkt length:(unsigned int *)pkt_len timeout:(unsigned int)timeout]; ! 525: } ! 526: ! 527: /* ! 528: * Power management methods. ! 529: */ ! 530: - (IOReturn)getPowerState:(PMPowerState *)state_p ! 531: { ! 532: return IO_R_UNSUPPORTED; ! 533: } ! 534: ! 535: - (IOReturn)setPowerState:(PMPowerState)state ! 536: { ! 537: if (state == PM_OFF) { ! 538: resetAndEnabled = NO; ! 539: [self _resetChip]; ! 540: return IO_R_SUCCESS; ! 541: } ! 542: return IO_R_UNSUPPORTED; ! 543: } ! 544: ! 545: - (IOReturn)getPowerManagement:(PMPowerManagementState *)state_p ! 546: { ! 547: return IO_R_UNSUPPORTED; ! 548: } ! 549: ! 550: - (IOReturn)setPowerManagement:(PMPowerManagementState)state ! 551: { ! 552: return IO_R_UNSUPPORTED; ! 553: } ! 554: ! 555: @end ! 556: ! 557: ! 558: ! 559: ! 560: ! 561: ! 562: ! 563: ! 564: ! 565: ! 566: ! 567: ! 568: ! 569: ! 570:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.