|
|
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 DECchip 2104x ! 29: * ! 30: * HISTORY ! 31: * ! 32: * 26-Apr-95 Rakesh Dubey (rdubey) at NeXT ! 33: * Created. ! 34: * 11-Oct-95 Dieter Siegmund (dieter) at NeXT ! 35: * Added performance hooks; changed transmit interrupt ! 36: * to only interrupt every N / 2 times, where N is the ! 37: * number of transmit descriptors. This reduces the ! 38: * number of interrupts taken, and the amount of CPU ! 39: * used by the driver. ! 40: * Removed timeout mechanism. ! 41: * 02-Nov-95 Rakesh Dubey (rdubey) at NeXT ! 42: * Added support for 21041 based adapters. ! 43: * -- serial ROM for station address ! 44: * -- new network interface selection scheme ! 45: * 11-Dec-95 Dieter Siegmund (dieter) at NeXT ! 46: * Re-named 2104x.m, split out 21040 and 21041 personalities. ! 47: * 07-Feb-96 Dieter Siegmund (dieter) at NeXT ! 48: * Fixed multicast. ! 49: * 25-Jun-96 Dieter Siegmund (dieter) at NeXT ! 50: * Added kernel debugger support. ! 51: * 05-Aug-97 Joe Liu at Apple ! 52: * Made kernel debugger support more robust. ! 53: */ ! 54: ! 55: #import "DECchip2104x.h" ! 56: #import "DECchip2104xPrivate.h" ! 57: ! 58: ! 59: //#define DEBUG ! 60: ! 61: #import "DECchip2104xInline.h" ! 62: ! 63: @implementation DECchip2104x ! 64: ! 65: /* ! 66: * Public Factory Methods ! 67: */ ! 68: ! 69: + (BOOL)probe:(IOPCIDevice *)devDesc ! 70: { ! 71: DECchip2104x *dev; ! 72: ! 73: IOLog("%s: PCI Dev: %d Func: %d Bus: %d\n", [self name], ! 74: devDesc->deviceNum, devDesc->functionNum, devDesc->busNum); ! 75: ! 76: // Veryfy the corect number of memory ranges ! 77: // Range 0 is I/O Space access to CSR's ! 78: // Range 1 is Memory Space access to Expansion ROM ! 79: // Range 2 is Memory Space access to CSR's ! 80: if ([devDesc numMemoryRanges] != 3) { ! 81: IOLog("%s: Incorrect number of memory ranges -> %d\n", ! 82: [self name], [devDesc numMemoryRanges]); ! 83: return NO; ! 84: } ! 85: ! 86: dev = [self alloc]; ! 87: if (dev == nil) { ! 88: IOLog("%s: Failed to alloc instance\n", [self name]); ! 89: return NO; ! 90: } ! 91: ! 92: return [dev initFromDeviceDescription:devDesc] != nil; ! 93: } ! 94: ! 95: /* ! 96: * Public Instance Methods ! 97: */ ! 98: - initFromDeviceDescription:(IODeviceDescription *)devDesc ! 99: { ! 100: if ([super initFromDeviceDescription:devDesc] == nil) { ! 101: [self free]; ! 102: return nil; ! 103: } ! 104: KDB_txBuf = [self allocateNetbuf]; ! 105: if (KDB_txBuf == NULL) { ! 106: IOLog("%s: couldn't allocate KDB netbuf\n", [self name]); ! 107: [self free]; ! 108: return nil; ! 109: } ! 110: resetAndEnabled = NO; ! 111: return self; ! 112: } ! 113: ! 114: - free ! 115: { ! 116: int i; ! 117: ! 118: [self clearTimeout]; ! 119: ! 120: [self _resetChip]; ! 121: ! 122: if (networkInterface) ! 123: [networkInterface free]; ! 124: ! 125: for (i = 0; i < DEC_21X40_RX_RING_LENGTH; i++) ! 126: if (rxNetbuf[i]) ! 127: nb_free(rxNetbuf[i]); ! 128: for (i = 0; i < DEC_21X40_TX_RING_LENGTH; i++) ! 129: if (txNetbuf[i]) ! 130: nb_free(txNetbuf[i]); ! 131: ! 132: ! 133: // if (memoryPtr) { ! 134: // IOFree(memoryPtr, memorySize); ! 135: // } ! 136: // [self enableAllInterrupts]; ! 137: ! 138: return [super free]; ! 139: } ! 140: ! 141: - (void) enableAdapterInterrupts ! 142: { ! 143: ! 144: //kprintf("[DECchip2104x enableAdapterInterrupts]\n"); ! 145: ! 146: writeCsr(ioBase, DEC_21X40_CSR7, interruptMask.data); ! 147: } ! 148: ! 149: - (void) disableAdapterInterrupts ! 150: { ! 151: ! 152: //kprintf("[DECchip2104x disableAdapterInterrupts]\n"); ! 153: ! 154: writeCsr(ioBase, DEC_21X40_CSR7, 0); ! 155: } ! 156: ! 157: - (BOOL)resetAndEnable:(BOOL)enable ! 158: { ! 159: ! 160: //kprintf("[DECchip2104x resetAndEnable]\n"); ! 161: ! 162: resetAndEnabled = NO; ! 163: [self clearTimeout]; ! 164: [self disableAdapterInterrupts]; ! 165: ! 166: [self _resetChip]; ! 167: ! 168: if (enable) { ! 169: ! 170: if (![self _initRxRing] || ![self _initTxRing]) { ! 171: return NO; ! 172: } ! 173: ! 174: if ([self _initChip] == NO) { ! 175: [self setRunning:NO]; ! 176: return NO; ! 177: } ! 178: ! 179: [self _startTransmit]; ! 180: [self _startReceive]; ! 181: ! 182: if ([self enableAllInterrupts] != IO_R_SUCCESS) { ! 183: [self setRunning:NO]; ! 184: return NO; ! 185: } ! 186: [self enableAdapterInterrupts]; ! 187: } ! 188: ! 189: [self setRunning:enable]; ! 190: ! 191: resetAndEnabled = YES; ! 192: return YES; ! 193: } ! 194: ! 195: ! 196: - (void)interruptOccurred ! 197: { ! 198: csrRegUnion interruptReg; ! 199: ! 200: //kprintf("[DECchip2104x interruptOccurred]\n"); ! 201: ! 202: #ifdef PERF ! 203: if (perfQ) { ! 204: ev_p.eventId = PERF_INTR_ENTER_ID; ! 205: perfEvent(perfQ, &ev_p); ! 206: } ! 207: #endif PERF ! 208: ! 209: while (1) { ! 210: ! 211: [self reserveDebuggerLock]; ! 212: interruptReg.data = readCsr(ioBase, DEC_21X40_CSR5); ! 213: writeCsr(ioBase, DEC_21X40_CSR5, interruptReg.data); ! 214: [self releaseDebuggerLock]; ! 215: #ifdef DEBUG ! 216: IOLog("%s: interruptOccurred: status %x\n", [self name], ! 217: interruptReg.data); ! 218: #endif DEBUG ! 219: ! 220: if (!interruptReg.csr5.ti && !interruptReg.csr5.ri && ! 221: !interruptReg.csr5.tjt) { ! 222: #ifdef DEBUG ! 223: IOLog("%s: BOGUS interrupt: status %x\n", [self name], ! 224: interruptReg.data); ! 225: #endif DEBUG ! 226: break; ! 227: } ! 228: ! 229: if (interruptReg.csr5.ri) { ! 230: [self _receiveInterruptOccurred]; ! 231: } ! 232: if (interruptReg.csr5.ti) { ! 233: [self reserveDebuggerLock]; ! 234: [self _transmitInterruptOccurred]; ! 235: [self releaseDebuggerLock]; ! 236: [self serviceTransmitQueue]; ! 237: } ! 238: if (interruptReg.csr5.tjt) { ! 239: //[self _jabberInterruptOccurred]; ! 240: } ! 241: } ! 242: [self enableAllInterrupts]; ! 243: #ifdef PERF ! 244: if (perfQ) { ! 245: ev_p.eventId = PERF_INTR_EXIT_ID; ! 246: perfEvent(perfQ, &ev_p); ! 247: } ! 248: #endif PERF ! 249: } ! 250: ! 251: - (void) serviceTransmitQueue ! 252: { ! 253: netbuf_t packet; ! 254: ! 255: //kprintf("[DECchip2104x serviceTransmitQueue]\n"); ! 256: ! 257: ! 258: while (txNumFree && [transmitQueue count] > 0 ! 259: && (packet = [transmitQueue dequeue])) ! 260: [self _transmitPacket:packet]; ! 261: } ! 262: ! 263: - (void)transmit:(netbuf_t)pkt ! 264: { ! 265: ! 266: //kprintf("[DECchip2104x transmit]\n"); ! 267: ! 268: if (!pkt) { ! 269: IOLog("%s: transmit: received NULL netbuf\n", [self name]); ! 270: return; ! 271: } ! 272: ! 273: if (![self isRunning]) { ! 274: nb_free(pkt); ! 275: return; ! 276: } ! 277: ! 278: [self reserveDebuggerLock]; ! 279: [self _transmitInterruptOccurred]; /* check for tx completions */ ! 280: [self releaseDebuggerLock]; ! 281: ! 282: /* ! 283: * Queue the packet if we're out of transmit descriptors ! 284: */ ! 285: [self serviceTransmitQueue]; ! 286: if (txNumFree == 0 || [transmitQueue count] > 0) ! 287: [transmitQueue enqueue:pkt]; ! 288: else ! 289: [self _transmitPacket:pkt]; ! 290: ! 291: } ! 292: ! 293: - (int) transmitQueueSize ! 294: { ! 295: //kprintf("[DECchip2104x transmitQueueSize]\n"); ! 296: ! 297: ! 298: return (TRANSMIT_QUEUE_SIZE); ! 299: } ! 300: ! 301: - (int) transmitQueueCount ! 302: { ! 303: //kprintf("[DECchip2104x transmitQueueCount]\n"); ! 304: ! 305: ! 306: return ([transmitQueue count]); ! 307: } ! 308: ! 309: - (int) pendingTransmitCount ! 310: { ! 311: ! 312: //kprintf("[DECchip2104x pendingTransmitCount]\n"); ! 313: ! 314: return ([transmitQueue count] + (DEC_21X40_TX_RING_LENGTH - txNumFree)); ! 315: } ! 316: ! 317: - (void)timeoutOccurred ! 318: { ! 319: //kprintf("[DECchip2104x timeoutOccurred]\n"); ! 320: ! 321: #ifdef PERF ! 322: if (perfQ) { ! 323: ev_p.eventId = PERF_INTR_ENTER_ID; ! 324: perfEvent(perfQ, &ev_p); ! 325: } ! 326: #endif PERF ! 327: ! 328: #ifdef DEBUG ! 329: IOLog("tx timeout: txPutIndex=%d, txDoneIndex=%d, txNumFree=%d\n", ! 330: txPutIndex, txDoneIndex, txNumFree); ! 331: #endif DEBUG ! 332: ! 333: if ([self isRunning]) { ! 334: [self reserveDebuggerLock]; ! 335: [self _transmitInterruptOccurred]; ! 336: [self releaseDebuggerLock]; ! 337: [self serviceTransmitQueue]; ! 338: } ! 339: #ifdef PERF ! 340: if (perfQ) { ! 341: ev_p.eventId = PERF_INTR_EXIT_ID; ! 342: perfEvent(perfQ, &ev_p); ! 343: } ! 344: #endif PERF ! 345: } ! 346: ! 347: - (netbuf_t)allocateNetbuf ! 348: { ! 349: netbuf_t packet; ! 350: unsigned int packetAlignment; ! 351: ! 352: //kprintf("[DECchip2104x allocateNetbuf]\n"); ! 353: ! 354: packet = nb_alloc(NETWORK_BUFSIZE + NETWORK_BUFALIGNMENT); ! 355: if (packet) { ! 356: packetAlignment = ! 357: (unsigned)nb_map(packet) & (NETWORK_BUFALIGNMENT - 1); ! 358: if (packetAlignment) ! 359: nb_shrink_top(packet, NETWORK_BUFALIGNMENT - packetAlignment); ! 360: nb_shrink_bot(packet, nb_size(packet) - ETHERMAXPACKET); ! 361: } ! 362: #ifdef DEBUG ! 363: else { ! 364: IOLog("%s: nb_alloc() returned NULL\n", [self name]); ! 365: // IOBreakToDebugger(); ! 366: } ! 367: #endif DEBUG ! 368: ! 369: return packet; ! 370: } ! 371: ! 372: - (BOOL)enablePromiscuousMode ! 373: { ! 374: csrRegUnion reg; ! 375: ! 376: //kprintf("[DECchip2104x enablePromiscuousMode]\n"); ! 377: ! 378: isPromiscuous = YES; ! 379: ! 380: [self reserveDebuggerLock]; ! 381: reg.data = readCsr(ioBase, DEC_21X40_CSR6); ! 382: reg.csr6.pr = 1; ! 383: writeCsr(ioBase, DEC_21X40_CSR6, reg.data); ! 384: [self releaseDebuggerLock]; ! 385: ! 386: return YES; ! 387: } ! 388: ! 389: - (void)disablePromiscuousMode ! 390: { ! 391: csrRegUnion reg; ! 392: ! 393: //kprintf("[DECchip2104x disablePromiscuousMode]\n"); ! 394: ! 395: isPromiscuous = NO; ! 396: ! 397: [self reserveDebuggerLock]; ! 398: reg.data = readCsr(ioBase, DEC_21X40_CSR6); ! 399: reg.csr6.pr = 0; ! 400: writeCsr(ioBase, DEC_21X40_CSR6, reg.data); ! 401: [self releaseDebuggerLock]; ! 402: ! 403: return; ! 404: } ! 405: ! 406: - (BOOL)enableMulticastMode ! 407: { ! 408: ! 409: //kprintf("[DECchip2104x enableMulticastMode]\n"); ! 410: ! 411: multicastEnabled = YES; ! 412: return YES; ! 413: } ! 414: ! 415: - (void)disableMulticastMode ! 416: { ! 417: ! 418: //kprintf("[DECchip2104x disableMulticastMode]\n"); ! 419: ! 420: /* ! 421: * Clear out any current addresses ! 422: */ ! 423: if (multicastEnabled) { ! 424: [self reserveDebuggerLock]; ! 425: if (![self _setAddressFiltering:NO]) ! 426: IOLog("%s: disable multicast mode failed\n",[self name]); ! 427: [self releaseDebuggerLock]; ! 428: } ! 429: multicastEnabled = NO; ! 430: } ! 431: ! 432: - (void)addMulticastAddress:(enet_addr_t *)addr ! 433: { ! 434: ! 435: //kprintf("[DECchip2104x addMulticastAddress: %x:%x:%x:%x:%x:%x]\n", ! 436: // addr->ea_byte[0],addr->ea_byte[1],addr->ea_byte[2], ! 437: // addr->ea_byte[3],addr->ea_byte[4],addr->ea_byte[5]); ! 438: ! 439: multicastEnabled = YES; ! 440: [self reserveDebuggerLock]; ! 441: if (![self _setAddressFiltering:NO]) ! 442: IOLog("%s: add multicast address failed\n",[self name]); ! 443: [self releaseDebuggerLock]; ! 444: } ! 445: ! 446: - (void)removeMulticastAddress:(enet_addr_t *)addr ! 447: { ! 448: ! 449: //kprintf("[DECchip2104x removeMulticastAddress]\n"); ! 450: ! 451: [self reserveDebuggerLock]; ! 452: if (![self _setAddressFiltering:NO]) ! 453: IOLog("%s: remove multicast address failed\n",[self name]); ! 454: [self releaseDebuggerLock]; ! 455: } ! 456: ! 457: /* ! 458: * Power management methods. ! 459: */ ! 460: - (IOReturn)getPowerState:(PMPowerState *)state_p ! 461: { ! 462: return IO_R_UNSUPPORTED; ! 463: } ! 464: ! 465: - (IOReturn)setPowerState:(PMPowerState)state ! 466: { ! 467: if (state == PM_OFF) { ! 468: resetAndEnabled = NO; ! 469: [self _resetChip]; ! 470: return IO_R_SUCCESS; ! 471: } ! 472: return IO_R_UNSUPPORTED; ! 473: } ! 474: ! 475: - (IOReturn)getPowerManagement:(PMPowerManagementState *)state_p ! 476: { ! 477: return IO_R_UNSUPPORTED; ! 478: } ! 479: ! 480: - (IOReturn)setPowerManagement:(PMPowerManagementState)state ! 481: { ! 482: return IO_R_UNSUPPORTED; ! 483: } ! 484: ! 485: - (void)getStationAddress:(enet_addr_t *)ea ! 486: { ! 487: ! 488: //kprintf("[DECchip2104x getStationAddress]\n"); ! 489: ! 490: return; ! 491: } ! 492: ! 493: - (void)selectInterface ! 494: { ! 495: //kprintf("[DECchip2104x selectInterface]\n"); ! 496: ! 497: return; ! 498: } ! 499: ! 500: ! 501: @end ! 502:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.