|
|
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) 1995-1996 NeXT Software, Inc. ! 24: * ! 25: * Hardware independent (relatively) code for the Mace Ethernet Controller ! 26: * ! 27: * HISTORY ! 28: * ! 29: * dd-mmm-yy ! 30: * Created. ! 31: * ! 32: */ ! 33: ! 34: #include <IOKit/assert.h> ! 35: #include <IOKit/platform/AppleMacIODevice.h> ! 36: #include "MaceEnetPrivate.h" ! 37: ! 38: //------------------------------------------------------------------------ ! 39: ! 40: #define super IOEthernetController ! 41: ! 42: OSDefineMetaClassAndStructors( MaceEnet, IOEthernetController ) ! 43: ! 44: //------------------------------------------------------------------------ ! 45: ! 46: #define PROVIDER_DEV 0 ! 47: #define PROVIDER_DMA_TX 1 ! 48: #define PROVIDER_DMA_RX 2 ! 49: ! 50: /* ! 51: * Public Instance Methods ! 52: */ ! 53: ! 54: bool MaceEnet::init(OSDictionary * properties) ! 55: { ! 56: if (!super::init(properties)) ! 57: return false; ! 58: ! 59: isPromiscuous = false; ! 60: multicastEnabled = false; ! 61: ready = false; ! 62: debugClient = false; ! 63: debugTxPoll = false; ! 64: netifClient = false; ! 65: ! 66: return true; ! 67: } ! 68: ! 69: MaceEnet * MaceEnet::probe(IOService * /*provider*/, ! 70: unsigned int * /*score*/, ! 71: unsigned int * /*specificity*/) ! 72: { ! 73: #ifdef OLD_CODE ! 74: extern int kdp_flag; ! 75: ! 76: /* ! 77: * If bootargs: kdp bit 0 using in-kernel mace driver for early debugging, ! 78: * Don't probe this driver. ! 79: */ ! 80: if( kdp_flag & 1) ! 81: { ! 82: return 0; ! 83: } ! 84: #endif ! 85: ! 86: return this; ! 87: } ! 88: ! 89: bool MaceEnet::start(IOService * provider) ! 90: { ! 91: AppleMacIODevice *nub = OSDynamicCast(AppleMacIODevice, provider); ! 92: ! 93: if (!nub || !super::start(provider)) ! 94: return false; ! 95: ! 96: transmitQueue = OSDynamicCast(IOOQGateFIFOQueue, getOutputQueue()); ! 97: if (!transmitQueue) ! 98: { ! 99: IOLog("Mace: output queue initialization failed\n"); ! 100: return false; ! 101: } ! 102: transmitQueue->retain(); ! 103: ! 104: // Allocate debug queue. This stores packets retired from the TX ring ! 105: // by the polling routine. We cannot call freePacket() or m_free() within ! 106: // the debugger context. ! 107: // ! 108: // The capacity of the queue is set at maximum to prevent the queue from ! 109: // calling m_free() due to over-capacity. But we don't expect the size ! 110: // of the queue to grow too large. ! 111: // ! 112: debugQueue = IOPacketQueue::withCapacity((UInt) -1); ! 113: if (!debugQueue) ! 114: return false; ! 115: ! 116: // Allocate a IOMBufDBDMAMemoryCursor instance. Currently, the maximum ! 117: // number of segments is set to 2. The maximum length for each segment ! 118: // is set to the maximum ethernet frame size (plus padding). ! 119: ! 120: mbufCursor = IOMBufBigMemoryCursor::withSpecification(NETWORK_BUFSIZE, 2); ! 121: if (!mbufCursor) ! 122: { ! 123: IOLog("Mace: IOMBufMemoryCursor allocation failed\n"); ! 124: return false; ! 125: } ! 126: ! 127: // ! 128: // Our provider is the nub representing the MaceEnet hardware ! 129: // controller. We will query it for our resource information. ! 130: // ! 131: ! 132: for (int i = 0; i < MEMORY_MAP_COUNT; i++) { ! 133: IOMemoryMap * map; ! 134: ! 135: map = provider->mapDeviceMemoryWithIndex(i); ! 136: if (!map) ! 137: return false; ! 138: ! 139: #ifdef DEBUG_XXX ! 140: IOLog("map %d: Phys:%08x Virt:%08x len:%d\n", ! 141: i, ! 142: (UInt) map->getPhysicalAddress(), ! 143: (UInt) map->getVirtualAddress(), ! 144: (UInt) map->getLength()); ! 145: #endif ! 146: ! 147: switch (i) { ! 148: case MEMORY_MAP_ENET_INDEX: ! 149: ioBaseEnet = (IOPPCAddress) map->getVirtualAddress(); ! 150: ioBaseEnetROM = (IOPPCAddress) ((map->getPhysicalAddress() & ! 151: ~0xffff) | kControllerROMOffset); ! 152: break; ! 153: ! 154: case MEMORY_MAP_TXDMA_INDEX: ! 155: ioBaseEnetTxDMA = (IODBDMAChannelRegisters *) ! 156: map->getVirtualAddress(); ! 157: break; ! 158: ! 159: case MEMORY_MAP_RXDMA_INDEX: ! 160: ioBaseEnetRxDMA = (IODBDMAChannelRegisters *) ! 161: map->getVirtualAddress(); ! 162: break; ! 163: } ! 164: ! 165: maps[i] = map; ! 166: } ! 167: ! 168: // Manually create an IODeviceMemory for the ROM memory ! 169: // range. ! 170: // ! 171: IODeviceMemory * romMemory = IODeviceMemory::withRange( ! 172: (UInt) ioBaseEnetROM, 0x1000); ! 173: if (!romMemory) { ! 174: IOLog("Mace: can't create ROM memory object\n"); ! 175: return false; ! 176: } ! 177: ! 178: romMap = romMemory->map(); ! 179: romMemory->release(); ! 180: ! 181: if (!romMap) ! 182: return false; ! 183: ! 184: ioBaseEnetROM = (IOPPCAddress) romMap->getVirtualAddress(); ! 185: ! 186: #ifdef DEBUG_XXX ! 187: IOLog("Mace: ioBaseEnet : %08x\n", (UInt) ioBaseEnet); ! 188: IOLog("Mace: ioBaseEnetTxDMA : %08x\n", (UInt) ioBaseEnetTxDMA); ! 189: IOLog("Mace: ioBaseEnetRxDMA : %08x\n", (UInt) ioBaseEnetRxDMA); ! 190: IOLog("Mace: ioBaseEnetROM : %08x\n", (UInt) ioBaseEnetROM); ! 191: #endif ! 192: ! 193: // ! 194: // Get a reference to the IOWorkLoop in our superclass. ! 195: // ! 196: IOWorkLoop * myWorkLoop = (IOWorkLoop *) getWorkLoop(); ! 197: assert(myWorkLoop); ! 198: ! 199: // ! 200: // Allocate two IOInterruptEventSources. ! 201: // ! 202: txIntSrc = IOInterruptEventSource::interruptEventSource ! 203: (this, ! 204: (IOInterruptEventAction) &MaceEnet::interruptOccurredForSource, ! 205: provider, PROVIDER_DMA_TX); ! 206: if (!txIntSrc ! 207: || (myWorkLoop->addEventSource(txIntSrc) != kIOReturnSuccess)) { ! 208: IOLog("Mace: txIntSrc init failure\n"); ! 209: return false; ! 210: } ! 211: ! 212: rxIntSrc = IOInterruptEventSource::interruptEventSource ! 213: (this, ! 214: (IOInterruptEventAction) &MaceEnet::interruptOccurredForSource, ! 215: provider, PROVIDER_DMA_RX); ! 216: if (!rxIntSrc ! 217: || (myWorkLoop->addEventSource(rxIntSrc) != kIOReturnSuccess)) { ! 218: IOLog("Mace: rxIntSrc init failure\n"); ! 219: return false; ! 220: } ! 221: ! 222: timerSrc = IOTimerEventSource::timerEventSource ! 223: (this, (IOTimerEventSource::Action) &MaceEnet::timeoutOccurred); ! 224: if (!timerSrc ! 225: || (myWorkLoop->addEventSource(timerSrc) != kIOReturnSuccess)) { ! 226: IOLog("Mace: timerSrc init failure\n"); ! 227: return false; ! 228: } ! 229: ! 230: MGETHDR(txDebuggerPkt, M_DONTWAIT, MT_DATA); ! 231: if (!txDebuggerPkt) ! 232: { ! 233: IOLog("Mace: Can't allocate KDB buffer\n"); ! 234: return false; ! 235: } ! 236: ! 237: #if 0 ! 238: // Do not enable interrupt sources until the hardware ! 239: // is enabled. ! 240: ! 241: // Enable the interrupt event sources. ! 242: myWorkLoop->enableAllInterrupts(); ! 243: #endif ! 244: ! 245: #if 0 ! 246: // Do not reset the hardware until we are ready to use it. ! 247: // Otherwise, we would have messed up kdp_mace driver's ! 248: // state. And we won't be able to break into the debugger ! 249: // until we attach our debugger client. ! 250: ! 251: // ! 252: // Perform a hardware reset. ! 253: // ! 254: if ( !resetAndEnable(false) ) ! 255: { ! 256: return false; ! 257: } ! 258: #endif ! 259: ! 260: // Cache my MAC address. ! 261: // ! 262: getHardwareAddress(&myAddress); ! 263: ! 264: // ! 265: // Allocate memory for ring buffers. ! 266: // ! 267: if (_allocateMemory() == false) ! 268: { ! 269: return false; ! 270: } ! 271: ! 272: // ! 273: // Attach a kernel debugger client. ! 274: // ! 275: attachDebuggerClient(&debugger); ! 276: ! 277: // ! 278: // Allocate and initialize an IONetworkInterface object. ! 279: // ! 280: if (!attachNetworkInterface((IONetworkInterface **) &networkInterface)) ! 281: return false; ! 282: ! 283: return true; ! 284: } ! 285: ! 286: /*------------------------------------------------------------------------- ! 287: * ! 288: * ! 289: * ! 290: *-------------------------------------------------------------------------*/ ! 291: ! 292: void MaceEnet::free() ! 293: { ! 294: UInt i; ! 295: ! 296: timerSrc->cancelTimeout(); ! 297: ! 298: _resetChip(); ! 299: ! 300: if (debugger) ! 301: debugger->release(); ! 302: ! 303: if (timerSrc) ! 304: timerSrc->release(); ! 305: ! 306: if (rxIntSrc) ! 307: rxIntSrc->release(); ! 308: ! 309: if (txIntSrc) ! 310: txIntSrc->release(); ! 311: ! 312: if (transmitQueue) ! 313: transmitQueue->release(); ! 314: ! 315: if (debugQueue) ! 316: debugQueue->release(); ! 317: ! 318: if (networkInterface) ! 319: networkInterface->release(); ! 320: ! 321: if (mbufCursor) ! 322: mbufCursor->release(); ! 323: ! 324: if (txDebuggerPkt) ! 325: freePacket(txDebuggerPkt); ! 326: ! 327: for (i = 0; i < rxMaxCommand; i++) ! 328: if (rxMbuf[i]) freePacket(rxMbuf[i]); ! 329: ! 330: for (i = 0; i < txMaxCommand; i++) ! 331: if (txMbuf[i]) freePacket(txMbuf[i]); ! 332: ! 333: if (romMap) romMap->release(); ! 334: ! 335: for (i = 0; i < MEMORY_MAP_COUNT; i++) ! 336: if (maps[i]) maps[i]->release(); ! 337: ! 338: if (dmaMemory.ptr) ! 339: { ! 340: IOFree(dmaMemory.ptrReal, dmaMemory.sizeReal); ! 341: dmaMemory.ptr = 0; ! 342: } ! 343: ! 344: super::free(); ! 345: } ! 346: ! 347: /*------------------------------------------------------------------------- ! 348: * ! 349: * ! 350: * ! 351: *-------------------------------------------------------------------------*/ ! 352: ! 353: void MaceEnet::interruptOccurredForSource(IOInterruptEventSource *src, ! 354: int /*count*/) ! 355: { ! 356: bool doFlushQueue = false; ! 357: bool doService = false; ! 358: ! 359: // IOLog("Mace: interrupt %08x %d\n", (UInt) src, count); ! 360: ! 361: if (!ready) { ! 362: // IOLog("Mace: unexpected interrupt\n"); ! 363: return; ! 364: } ! 365: ! 366: reserveDebuggerLock(); ! 367: ! 368: if (src == txIntSrc) { ! 369: txWDInterrupts++; ! 370: KERNEL_DEBUG(DBG_MACE_TXIRQ | DBG_FUNC_START, 0, 0, 0, 0, 0 ); ! 371: doService = _transmitInterruptOccurred(); ! 372: KERNEL_DEBUG(DBG_MACE_TXIRQ | DBG_FUNC_END, 0, 0, 0, 0, 0 ); ! 373: } ! 374: else { ! 375: KERNEL_DEBUG(DBG_MACE_RXIRQ | DBG_FUNC_START, 0, 0, 0, 0, 0 ); ! 376: doFlushQueue = _receiveInterruptOccurred(); ! 377: KERNEL_DEBUG(DBG_MACE_RXIRQ | DBG_FUNC_END, 0, 0, 0, 0, 0 ); ! 378: } ! 379: ! 380: releaseDebuggerLock(); ! 381: ! 382: /* ! 383: * Submit all received packets queued up by _receiveInterruptOccurred() ! 384: * to the network stack. The up call is performed without holding the ! 385: * debugger lock. ! 386: */ ! 387: if (doFlushQueue) ! 388: networkInterface->flushInputQueue(); ! 389: ! 390: /* ! 391: * Make sure the output queue is not stalled. ! 392: */ ! 393: if (doService && netifClient) ! 394: transmitQueue->service(); ! 395: } ! 396: ! 397: /*------------------------------------------------------------------------- ! 398: * ! 399: * ! 400: * ! 401: *-------------------------------------------------------------------------*/ ! 402: ! 403: UInt32 MaceEnet::outputPacket(struct mbuf *pkt) ! 404: { ! 405: u_int32_t i; ! 406: u_int8_t regValue; ! 407: UInt32 ret = kIOOQReturnSuccess; ! 408: ! 409: // IOLog("Mace: outputPacket %d\n", pkt->m_pkthdr.len); ! 410: ! 411: KERNEL_DEBUG(DBG_MACE_TXQUEUE | DBG_FUNC_NONE, (int) pkt, ! 412: (int) pkt->m_pkthdr.len, 0, 0, 0 ); ! 413: ! 414: /* ! 415: * Hold the debugger lock so the debugger can't interrupt us ! 416: */ ! 417: reserveDebuggerLock(); ! 418: ! 419: do ! 420: { ! 421: /* ! 422: * Someone is turning off the receiver before the first transmit. ! 423: * Dont know who yet! ! 424: */ ! 425: regValue = ReadMaceRegister( ioBaseEnet, kMacCC ); ! 426: regValue |= kMacCCEnRcv; ! 427: WriteMaceRegister( ioBaseEnet, kMacCC, regValue ); ! 428: ! 429: /* ! 430: * Preliminary sanity checks ! 431: */ ! 432: assert(pkt && netifClient); ! 433: ! 434: /* ! 435: * Remove any completed packets from the Tx ring ! 436: */ ! 437: _transmitInterruptOccurred(); ! 438: ! 439: i = txCommandTail + 1; ! 440: if ( i >= txMaxCommand ) i = 0; ! 441: if ( i == txCommandHead ) ! 442: { ! 443: ret = kIOOQReturnStall; ! 444: continue; ! 445: } ! 446: ! 447: /* ! 448: * If there is space on the Tx ring, add the packet directly to the ! 449: * ring ! 450: */ ! 451: _transmitPacket(pkt); ! 452: } ! 453: while ( 0 ); ! 454: ! 455: releaseDebuggerLock(); ! 456: ! 457: return ret; ! 458: } ! 459: ! 460: /*------------------------------------------------------------------------- ! 461: * Called by IOEthernetInterface client to enable the controller. ! 462: * This method is always called while running on the default workloop ! 463: * thread. ! 464: *-------------------------------------------------------------------------*/ ! 465: ! 466: IOReturn MaceEnet::enable(IONetworkInterface * netif) ! 467: { ! 468: IONetworkParameter * param; ! 469: ! 470: // If an interface client has previously enabled us, ! 471: // and we know there can only be one interface client ! 472: // for this driver, then simply return true. ! 473: // ! 474: if (netifClient) { ! 475: IOLog("Mace: already enabled\n"); ! 476: return kIOReturnSuccess; ! 477: } ! 478: ! 479: param = netif->getParameter(kIONetworkStatsKey); ! 480: if (!param || !(netStats = (IONetworkStats *) param->getBuffer())) ! 481: { ! 482: IOLog("Mace: invalid network statistics\n"); ! 483: return kIOReturnError; ! 484: } ! 485: ! 486: if ((ready == false) && !resetAndEnable(true)) ! 487: return kIOReturnIOError; ! 488: ! 489: // Record the interface as an active client. ! 490: // ! 491: netifClient = true; ! 492: ! 493: // Start our IOOutputQueue object. ! 494: // ! 495: transmitQueue->setCapacity(TRANSMIT_QUEUE_SIZE); ! 496: transmitQueue->start(); ! 497: ! 498: return kIOReturnSuccess; ! 499: } ! 500: ! 501: /*------------------------------------------------------------------------- ! 502: * Called by IOEthernetInterface client to disable the controller. ! 503: * This method is always called while running on the default workloop ! 504: * thread. ! 505: *-------------------------------------------------------------------------*/ ! 506: ! 507: IOReturn MaceEnet::disable(IONetworkInterface * /*netif*/) ! 508: { ! 509: // If we have no active clients, then disable the controller. ! 510: // ! 511: if (debugClient == false) ! 512: resetAndEnable(false); ! 513: ! 514: // Disable our IOOutputQueue object. ! 515: // ! 516: transmitQueue->stop(); ! 517: ! 518: // Flush all packets currently in the output queue. ! 519: // ! 520: transmitQueue->setCapacity(0); ! 521: transmitQueue->flush(); ! 522: ! 523: netifClient = false; ! 524: ! 525: return kIOReturnSuccess; ! 526: } ! 527: ! 528: /*------------------------------------------------------------------------- ! 529: * This method is called by our debugger client to bring up the controller ! 530: * just before the controller is registered as the debugger device. The ! 531: * debugger client is attached in response to the attachDebuggerClient() ! 532: * call. ! 533: * ! 534: * This method is always called while running on the default workloop ! 535: * thread. ! 536: *-------------------------------------------------------------------------*/ ! 537: ! 538: IOReturn MaceEnet::handleDebuggerOpen(IOKernelDebugger * /*debugger*/) ! 539: { ! 540: // Enable hardware and make it ready to support the debugger client. ! 541: // ! 542: if ((ready == false) && !resetAndEnable(true)) ! 543: return kIOReturnIOError; ! 544: ! 545: // Record the debugger as an active client of ours. ! 546: // ! 547: debugClient = true; ! 548: ! 549: // Returning true will allow the kdp registration to continue. ! 550: // If we return false, then we will not be registered as the ! 551: // debugger device, and the attachDebuggerClient() call will ! 552: // return NULL. ! 553: // ! 554: return kIOReturnSuccess; ! 555: } ! 556: ! 557: /*------------------------------------------------------------------------- ! 558: * This method is called by our debugger client to stop the controller. ! 559: * The debugger will call this method when we issue a detachDebuggerClient(). ! 560: * ! 561: * This method is always called while running on the default workloop ! 562: * thread. ! 563: *-------------------------------------------------------------------------*/ ! 564: ! 565: IOReturn MaceEnet::handleDebuggerClose(IOKernelDebugger * /*debugger*/) ! 566: { ! 567: debugClient = false; ! 568: ! 569: // If we have no active clients, then disable the controller. ! 570: // ! 571: if (netifClient == false) ! 572: resetAndEnable(false); ! 573: ! 574: return kIOReturnSuccess; ! 575: } ! 576: ! 577: /*------------------------------------------------------------------------- ! 578: * ! 579: * ! 580: * ! 581: *-------------------------------------------------------------------------*/ ! 582: ! 583: bool MaceEnet::resetAndEnable(bool enable) ! 584: { ! 585: bool ret = true; ! 586: ! 587: if (timerSrc) ! 588: timerSrc->cancelTimeout(); ! 589: ! 590: _disableAdapterInterrupts(); ! 591: if (getWorkLoop()) getWorkLoop()->disableAllInterrupts(); ! 592: ! 593: reserveDebuggerLock(); ! 594: ! 595: ready = false; ! 596: ! 597: _resetChip(); ! 598: ! 599: do { ! 600: if (!enable) break; ! 601: ! 602: if ( !_initRxRing() || !_initTxRing() || !_initChip() ) ! 603: { ! 604: ret = false; ! 605: break; ! 606: } ! 607: ! 608: _startChip(); ! 609: ! 610: ready = true; ! 611: ! 612: releaseDebuggerLock(); ! 613: ! 614: timerSrc->setTimeoutMS(WATCHDOG_TIMER_MS); ! 615: ! 616: if (getWorkLoop()) getWorkLoop()->enableAllInterrupts(); ! 617: _enableAdapterInterrupts(); ! 618: ! 619: return true; ! 620: } ! 621: while (0); ! 622: ! 623: releaseDebuggerLock(); ! 624: ! 625: return ret; ! 626: } ! 627: ! 628: /*------------------------------------------------------------------------- ! 629: * ! 630: * ! 631: * ! 632: *-------------------------------------------------------------------------*/ ! 633: ! 634: void MaceEnet::_sendTestPacket() ! 635: { ! 636: // IOOutputPacketStatus ret; ! 637: unsigned char * buf; ! 638: const unsigned int size = 64; ! 639: ! 640: struct mbuf * m = allocatePacket(size); ! 641: if (!m) { ! 642: IOLog("Mace: _sendTestpacket: allocatePacket() failed\n"); ! 643: return; ! 644: } ! 645: ! 646: buf = mtod(m, unsigned char *); ! 647: ! 648: bcopy(&myAddress, buf, NUM_EN_ADDR_BYTES); ! 649: buf += NUM_EN_ADDR_BYTES; ! 650: bcopy(&myAddress, buf, NUM_EN_ADDR_BYTES); ! 651: buf += NUM_EN_ADDR_BYTES; ! 652: *buf++ = 0; ! 653: *buf++ = 0; ! 654: ! 655: outputPacket(m); ! 656: } ! 657: ! 658: /*------------------------------------------------------------------------- ! 659: * ! 660: * ! 661: * ! 662: *-------------------------------------------------------------------------*/ ! 663: ! 664: void MaceEnet::timeoutOccurred(IOTimerEventSource * /*timer*/) ! 665: { ! 666: u_int32_t dmaStatus; ! 667: bool doFlushQueue = false; ! 668: bool doService = false; ! 669: ! 670: reserveDebuggerLock(); ! 671: ! 672: /* ! 673: * Check for DMA shutdown on receive channel ! 674: */ ! 675: dmaStatus = IOGetDBDMAChannelStatus( ioBaseEnetRxDMA ); ! 676: if ( !(dmaStatus & kdbdmaActive) ) ! 677: { ! 678: #if 0 ! 679: IOLog("Mace: Timeout check - RxHead = %d RxTail = %d\n", ! 680: rxCommandHead, rxCommandTail); ! 681: #endif ! 682: ! 683: #if 0 ! 684: IOLog( "Mace: Rx Commands = %08x(p) Rx DMA Ptr = %08x(p)\n\r", rxDMACommandsPhys, IOGetDBDMACommandPtr(ioBaseEnetRxDMA) ); ! 685: [self _dumpDesc:(void *)rxDMACommands Size:rxMaxCommand * sizeof(enet_dma_cmd_t)]; ! 686: #endif ! 687: ! 688: doFlushQueue = _receiveInterruptOccurred(); ! 689: } ! 690: ! 691: /* ! 692: * If there are pending entries on the Tx ring ! 693: */ ! 694: if ( txCommandHead != txCommandTail ) ! 695: { ! 696: /* ! 697: * If we did not service the Tx ring during the last timeout interval, ! 698: * then force servicing of the Tx ring. ! 699: * If we have more than one timeout interval without any transmit ! 700: * interrupts, then force the transmitter to reset. ! 701: */ ! 702: if ( txWDInterrupts == 0 ) ! 703: { ! 704: if ( ++txWDTimeouts > 1 ) txWDForceReset = true; ! 705: ! 706: #if 0 ! 707: IOLog( "Mace: Checking for timeout - TxHead = %d TxTail = %d\n", ! 708: txCommandHead, txCommandTail); ! 709: #endif ! 710: doService = _transmitInterruptOccurred(); ! 711: } ! 712: else ! 713: { ! 714: txWDTimeouts = 0; ! 715: txWDInterrupts = 0; ! 716: } ! 717: } ! 718: else ! 719: { ! 720: txWDTimeouts = 0; ! 721: txWDInterrupts = 0; ! 722: } ! 723: ! 724: // Clean-up after the debugger if the debugger was active. ! 725: // ! 726: if (debugTxPoll) ! 727: { ! 728: debugQueue->flush(); ! 729: debugTxPoll = false; ! 730: releaseDebuggerLock(); ! 731: doService = true; ! 732: } ! 733: else ! 734: { ! 735: releaseDebuggerLock(); ! 736: } ! 737: ! 738: /* ! 739: * Submit all received packets queued up by _receiveInterruptOccurred() ! 740: * to the network stack. The up call is performed without holding the ! 741: * debugger lock. ! 742: */ ! 743: if (doFlushQueue) ! 744: { ! 745: networkInterface->flushInputQueue(); ! 746: } ! 747: ! 748: /* ! 749: * Make sure the output queue is not stalled. ! 750: */ ! 751: if (doService && netifClient) ! 752: { ! 753: transmitQueue->service(); ! 754: } ! 755: ! 756: /* ! 757: * Restart the watchdog timer ! 758: */ ! 759: timerSrc->setTimeoutMS(WATCHDOG_TIMER_MS); ! 760: } ! 761: ! 762: /*------------------------------------------------------------------------- ! 763: * ! 764: * ! 765: * ! 766: *-------------------------------------------------------------------------*/ ! 767: ! 768: const char * MaceEnet::getVendorString() const ! 769: { ! 770: return ("Apple"); ! 771: } ! 772: ! 773: const char * MaceEnet::getModelString() const ! 774: { ! 775: return ("Mace"); ! 776: } ! 777: ! 778: const char * MaceEnet::getRevisionString() const ! 779: { ! 780: return (""); ! 781: } ! 782: ! 783: /*------------------------------------------------------------------------- ! 784: * ! 785: * ! 786: * ! 787: *-------------------------------------------------------------------------*/ ! 788: ! 789: IOReturn MaceEnet::_setPromiscuousMode(IOEnetPromiscuousMode mode) ! 790: { ! 791: u_int8_t regVal; ! 792: ! 793: regVal = ReadMaceRegister( ioBaseEnet, kMacCC ); ! 794: WriteMaceRegister( ioBaseEnet, kMacCC, regVal & ~kMacCCEnRcv ); ! 795: if (mode == kIOEnetPromiscuousModeOff) { ! 796: regVal &= ~kMacCCProm; ! 797: isPromiscuous = false; ! 798: } ! 799: else { ! 800: regVal |= kMacCCProm; ! 801: isPromiscuous = true; ! 802: } ! 803: WriteMaceRegister( ioBaseEnet, kMacCC, regVal ); ! 804: ! 805: return kIOReturnSuccess; ! 806: ! 807: } ! 808: ! 809: IOReturn MaceEnet::setPromiscuousMode(IOEnetPromiscuousMode mode) ! 810: { ! 811: IOReturn ret; ! 812: ! 813: reserveDebuggerLock(); ! 814: ret = _setPromiscuousMode(mode); ! 815: releaseDebuggerLock(); ! 816: ! 817: return ret; ! 818: } ! 819: ! 820: IOReturn MaceEnet::setMulticastMode(IOEnetMulticastMode mode) ! 821: { ! 822: multicastEnabled = (mode == kIOEnetMulticastModeOff) ? false : true; ! 823: return kIOReturnSuccess; ! 824: } ! 825: ! 826: IOReturn MaceEnet::setMulticastList(enet_addr_t *addrs, UInt count) ! 827: { ! 828: reserveDebuggerLock(); ! 829: _resetHashTableMask(); ! 830: for (UInt i = 0; i < count; i++) { ! 831: _addToHashTableMask(addrs->ea_byte); ! 832: addrs++; ! 833: } ! 834: _updateHashTableMask(); ! 835: releaseDebuggerLock(); ! 836: return kIOReturnSuccess; ! 837: } ! 838: ! 839: /* ! 840: * Allocate an IOOutputQueue object. ! 841: */ ! 842: IOOutputQueue * MaceEnet::allocateOutputQueue() ! 843: { ! 844: return IOOQGateFIFOQueue::withTarget( this, getWorkLoop() ); ! 845: } ! 846: ! 847: /* ! 848: * Kernel Debugger Support ! 849: */ ! 850: void MaceEnet::sendPacket(void *pkt, UInt pkt_len) ! 851: { ! 852: _sendPacket(pkt, pkt_len); ! 853: } ! 854: ! 855: void MaceEnet::receivePacket(void *pkt, UInt *pkt_len, UInt timeout) ! 856: { ! 857: _receivePacket(pkt, pkt_len, timeout); ! 858: } ! 859: ! 860: #if 0 // no power management stuff in IOKit yet. ! 861: /* ! 862: * Power management methods. ! 863: */ ! 864: - (IOReturn)getPowerState:(PMPowerState *)state_p ! 865: { ! 866: return kIOReturnUnsupported; ! 867: } ! 868: ! 869: - (IOReturn)setPowerState:(PMPowerState)state ! 870: { ! 871: if (state == PM_OFF) { ! 872: resetAndEnabled = NO; ! 873: [self _resetChip]; ! 874: return kIOReturnSuccess; ! 875: } ! 876: return kIOReturnUnsupported; ! 877: } ! 878: ! 879: - (IOReturn)getPowerManagement:(PMPowerManagementState *)state_p ! 880: { ! 881: return kIOReturnUnsupported; ! 882: } ! 883: ! 884: - (IOReturn)setPowerManagement:(PMPowerManagementState)state ! 885: { ! 886: return kIOReturnUnsupported; ! 887: } ! 888: #endif /* 0 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.