|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * Copyright (c) 1998-1999 Apple Computer ! 24: * ! 25: * Hardware independent (relatively) code for the Sun GEM Ethernet Controller ! 26: * ! 27: * HISTORY ! 28: * ! 29: * dd-mmm-yy ! 30: * Created. ! 31: * ! 32: */ ! 33: ! 34: //void call_kdp(void); ! 35: ! 36: #include "UniNEnetPrivate.h" ! 37: ! 38: #define super IOEthernetController ! 39: ! 40: OSDefineMetaClassAndStructors( UniNEnet, IOEthernetController ) ! 41: ! 42: /*------------------------------------------------------------------------- ! 43: * ! 44: * ! 45: * ! 46: *-------------------------------------------------------------------------*/ ! 47: bool UniNEnet::init(OSDictionary * properties = 0) ! 48: { ! 49: /* ! 50: * Initialize my ivars. ! 51: */ ! 52: networkInterface = 0; ! 53: transmitQueue = 0; ! 54: debugQueue = 0; ! 55: debugger = 0; ! 56: interruptSource = 0; ! 57: txDebuggerPkt = 0; ! 58: phyId = 0xff; ! 59: phyStatusPrev = 0; ! 60: ready = false; ! 61: debugClient = false; ! 62: debugTxPoll = false; ! 63: netifClient = false; ! 64: isPromiscuous = false; ! 65: multicastEnabled = false; ! 66: ! 67: if (!super::init(properties)) ! 68: return false; ! 69: ! 70: /* ! 71: * Clear the mbuf rings. ! 72: */ ! 73: for (int i = 0; i < TX_RING_LENGTH; i++) ! 74: { ! 75: txElementPtrs[i] = 0; ! 76: } ! 77: ! 78: for (int i = 0; i < RX_RING_LENGTH; i++) ! 79: { ! 80: rxMbuf[i] = 0; ! 81: ! 82: } ! 83: ! 84: return true; ! 85: } ! 86: ! 87: /*------------------------------------------------------------------------- ! 88: * ! 89: * ! 90: * ! 91: *-------------------------------------------------------------------------*/ ! 92: ! 93: bool UniNEnet::start(IOService * provider) ! 94: { ! 95: volatile UInt32 clockReg; ! 96: OSString *matchEntry; ! 97: ! 98: nub = OSDynamicCast(IOPCIDevice, provider); ! 99: ! 100: if (!nub || !super::start(provider)) ! 101: { ! 102: return false; ! 103: } ! 104: ! 105: transmitQueue = OSDynamicCast(IOOQLockFIFOQueue, getOutputQueue()); ! 106: if (!transmitQueue) ! 107: { ! 108: IOLog("Ethernet(UniN): Output queue initialization failed\n"); ! 109: return false; ! 110: } ! 111: transmitQueue->retain(); ! 112: ! 113: /* ! 114: * Allocate debug queue. This stores packets retired from the TX ring ! 115: * by the polling routine. We cannot call freePacket() or m_free() within ! 116: * the debugger context. ! 117: * ! 118: * The capacity of the queue is set at maximum to prevent the queue from ! 119: * calling m_free() due to over-capacity. But we don't expect the size ! 120: * of the queue to grow too large. ! 121: */ ! 122: debugQueue = IOPacketQueue::withCapacity((UInt) -1); ! 123: if (!debugQueue) ! 124: { ! 125: return false; ! 126: } ! 127: ! 128: /* ! 129: * Allocate a IOMBufDBDMAMemoryCursor instance. Currently, the maximum ! 130: * number of segments is set to 1. The maximum length for each segment ! 131: * is set to the maximum ethernet frame size (plus padding). ! 132: */ ! 133: mbufCursor = IOMBufBigMemoryCursor::withSpecification(NETWORK_BUFSIZE, 1); ! 134: if (!mbufCursor) ! 135: { ! 136: IOLog("Ethernet(UniN): IOMBufDBDMAMemoryCursor allocation failure\n"); ! 137: return false; ! 138: } ! 139: ! 140: matchEntry = OSDynamicCast( OSString, getProperty( gIONameMatchedKey ) ); ! 141: if ( matchEntry == 0 ) ! 142: { ! 143: IOLog("Ethernet(UniN): Cannot obtain matching property.\n"); ! 144: return false; ! 145: } ! 146: ! 147: if ( matchEntry->isEqualTo( "gmac" ) == true ) ! 148: { ! 149: platformNub = OSDynamicCast( Core99PE, getPlatform() ); ! 150: ! 151: if ( platformNub == 0 ) ! 152: { ! 153: IOLog("Ethernet(UniN): Cannot access platform registers.\n"); ! 154: return false; ! 155: } ! 156: ! 157: clockReg = platformNub->readUniNReg( 0x20 ); ! 158: clockReg |= 0x02; ! 159: platformNub->writeUniNReg( 0x20, clockReg ); ! 160: } ! 161: ! 162: /* ! 163: * BUS MASTER, MEM I/O Space, MEM WR & INV ! 164: */ ! 165: nub->configWrite32( 0x04, 0x16 ); ! 166: ! 167: /* ! 168: * set Latency to Max , cache 32 ! 169: */ ! 170: nub->configWrite32( 0x0C, ((2 + (kGEMBurstSize * (0+1)))<< 8) | (CACHE_LINE_SIZE >> 2) ); ! 171: ! 172: ioMapEnet = nub->mapDeviceMemoryWithRegister( 0x10 ); ! 173: if ( ioMapEnet == NULL ) ! 174: { ! 175: return false; ! 176: } ! 177: ioBaseEnet = (volatile IOPPCAddress)ioMapEnet->getVirtualAddress(); ! 178: ! 179: phyId = (UInt8) -1; ! 180: ! 181: /* ! 182: * Get a reference to the IOWorkLoop in our superclass. ! 183: */ ! 184: IOWorkLoop * myWorkLoop = getWorkLoop(); ! 185: ! 186: /* ! 187: * Allocate three IOInterruptEventSources. ! 188: */ ! 189: interruptSource = IOInterruptEventSource::interruptEventSource( ! 190: (OSObject *) this, ! 191: (IOInterruptEventAction) &UniNEnet::interruptOccurred, ! 192: (IOService *) provider, ! 193: (int) 0 ); ! 194: ! 195: if ( interruptSource == NULL ) ! 196: { ! 197: IOLog("Ethernet(UniN): Couldn't allocate Interrupt event source\n"); ! 198: return false; ! 199: } ! 200: ! 201: if ( myWorkLoop->addEventSource( interruptSource ) != kIOReturnSuccess ) ! 202: { ! 203: IOLog("Ethernet(UniN): Couldn't add Interrupt event source\n"); ! 204: return false; ! 205: } ! 206: ! 207: ! 208: timerSource = IOTimerEventSource::timerEventSource ! 209: (this, (IOTimerEventSource::Action) &UniNEnet::timeoutOccurred); ! 210: if ( timerSource == NULL ) ! 211: { ! 212: IOLog("Ethernet(UniN): Couldn't allocate timer event source\n"); ! 213: return false; ! 214: } ! 215: ! 216: if ( myWorkLoop->addEventSource( timerSource ) != kIOReturnSuccess ) ! 217: { ! 218: IOLog("Ethernet(UniN): Couldn't add timer event source\n"); ! 219: return false; ! 220: } ! 221: ! 222: MGETHDR(txDebuggerPkt, M_DONTWAIT, MT_DATA); ! 223: ! 224: if (!txDebuggerPkt) ! 225: { ! 226: IOLog("Ethernet(UniN): Couldn't allocate KDB buffer\n"); ! 227: return false; ! 228: } ! 229: ! 230: /* ! 231: * Perform a hardware reset. ! 232: */ ! 233: if ( resetAndEnable(false) == false ) ! 234: { ! 235: IOLog("Ethernet(UniN): resetAndEnable() failed\n"); ! 236: return false; ! 237: } ! 238: ! 239: /* ! 240: * Cache my MAC address. ! 241: */ ! 242: if ( getHardwareAddress(&myAddress) != kIOReturnSuccess ) ! 243: { ! 244: IOLog("Ethernet(UniN): getHardwareAddress() failed\n"); ! 245: return false; ! 246: } ! 247: ! 248: /* ! 249: * Allocate memory for ring buffers. ! 250: */ ! 251: if ( allocateMemory() == false) ! 252: { ! 253: IOLog("Ethernet(UniN): allocateMemory() failed\n"); ! 254: return false; ! 255: } ! 256: ! 257: /* ! 258: * Attach a kernel debugger client. ! 259: */ ! 260: attachDebuggerClient(&debugger); ! 261: ! 262: /* ! 263: * Attach an IOEthernetInterface client. ! 264: */ ! 265: if ( attachNetworkInterface((IONetworkInterface **) &networkInterface) == false ) ! 266: { ! 267: IOLog("Ethernet(UniN): attachNetworkInterface() failed\n"); ! 268: return false; ! 269: } ! 270: return true; ! 271: } ! 272: ! 273: /*------------------------------------------------------------------------- ! 274: * ! 275: * ! 276: * ! 277: *-------------------------------------------------------------------------*/ ! 278: #if 1 ! 279: bool UniNEnet::configureNetworkInterface(IONetworkInterface * netif) ! 280: { ! 281: if ( super::configureNetworkInterface( netif ) == true ) ! 282: { ! 283: return netif->setExtraFlags(IFEF_DVR_REENTRY_OK); ! 284: } ! 285: return false; ! 286: } ! 287: #endif ! 288: ! 289: /*------------------------------------------------------------------------- ! 290: * ! 291: * ! 292: * ! 293: *-------------------------------------------------------------------------*/ ! 294: ! 295: void UniNEnet::free() ! 296: { ! 297: UInt i; ! 298: TxQueueElement *txElement; ! 299: ! 300: resetAndEnable(false); ! 301: ! 302: if (debugger) ! 303: debugger->release(); ! 304: ! 305: if (getWorkLoop()) ! 306: { ! 307: getWorkLoop()->disableAllEventSources(); ! 308: } ! 309: ! 310: if (timerSource) ! 311: { ! 312: timerSource->release(); ! 313: timerSource = 0; ! 314: } ! 315: ! 316: if (interruptSource) ! 317: { ! 318: interruptSource->release(); ! 319: } ! 320: ! 321: if (txDebuggerPkt) ! 322: { ! 323: freePacket(txDebuggerPkt); ! 324: } ! 325: ! 326: if (transmitQueue) ! 327: { ! 328: transmitQueue->release(); ! 329: } ! 330: ! 331: if (debugQueue) ! 332: { ! 333: debugQueue->release(); ! 334: } ! 335: ! 336: if (networkInterface) ! 337: { ! 338: networkInterface->release(); ! 339: } ! 340: ! 341: if (mbufCursor) ! 342: { ! 343: mbufCursor->release(); ! 344: } ! 345: ! 346: for (i = 0; i < rxMaxCommand; i++) ! 347: { ! 348: if (rxMbuf[i]) ! 349: { ! 350: freePacket(rxMbuf[i]); ! 351: } ! 352: } ! 353: ! 354: for (i = 0; i < txMaxCommand; i++) ! 355: { ! 356: txElement = txElementPtrs[i]; ! 357: txElementPtrs[i] = 0; ! 358: ! 359: if (txElement != 0) ! 360: { ! 361: if ( --txElement->count == 0 ) ! 362: { ! 363: freePacket(txElement->mbuf); ! 364: IOFree( txElement, sizeof(TxQueueElement) ); ! 365: } ! 366: } ! 367: } ! 368: ! 369: if ( ioMapEnet ) ! 370: { ! 371: ioMapEnet->release(); ! 372: } ! 373: ! 374: if ( dmaCommands != 0 ) ! 375: { ! 376: IOFreeContiguous( (void *)dmaCommands, dmaCommandsSize ); ! 377: } ! 378: ! 379: super::free(); ! 380: } ! 381: ! 382: /*------------------------------------------------------------------------- ! 383: * ! 384: * ! 385: * ! 386: *-------------------------------------------------------------------------*/ ! 387: ! 388: void UniNEnet::interruptOccurred(IOInterruptEventSource *src, ! 389: int /*count*/) ! 390: { ! 391: UInt32 interruptStatus; ! 392: bool doFlushQueue; ! 393: bool doService; ! 394: ! 395: do ! 396: { ! 397: reserveDebuggerLock(); ! 398: ! 399: interruptStatus = ReadUniNRegister( ioBaseEnet, kGEMInterruptStatus ) ! 400: & (kGEMInterruptStatus_TxInt | kGEMInterruptStatus_RxDone); ! 401: ! 402: doService = false; ! 403: ! 404: if ( interruptStatus & kGEMInterruptStatus_TxInt ) ! 405: { ! 406: txWDInterrupts++; ! 407: KERNEL_DEBUG(DBG_GEM_TXIRQ | DBG_FUNC_START, 0, 0, 0, 0, 0 ); ! 408: doService = transmitInterruptOccurred(); ! 409: KERNEL_DEBUG(DBG_GEM_TXIRQ | DBG_FUNC_END, 0, 0, 0, 0, 0 ); ! 410: } ! 411: ! 412: doFlushQueue = false; ! 413: ! 414: if ( interruptStatus & kGEMInterruptStatus_RxDone ) ! 415: { ! 416: KERNEL_DEBUG(DBG_GEM_RXIRQ | DBG_FUNC_START, 0, 0, 0, 0, 0 ); ! 417: doFlushQueue = receiveInterruptOccurred(); ! 418: KERNEL_DEBUG(DBG_GEM_RXIRQ | DBG_FUNC_END, 0, 0, 0, 0, 0 ); ! 419: } ! 420: ! 421: releaseDebuggerLock(); ! 422: ! 423: /* ! 424: * Submit all received packets queued up by _receiveInterruptOccurred() ! 425: * to the network stack. The up call is performed without holding the ! 426: * debugger lock. ! 427: */ ! 428: if (doFlushQueue) ! 429: { ! 430: networkInterface->flushInputQueue(); ! 431: } ! 432: ! 433: /* ! 434: * Make sure the output queue is not stalled. ! 435: */ ! 436: if (doService && netifClient) ! 437: { ! 438: transmitQueue->service(); ! 439: } ! 440: } ! 441: while ( interruptStatus ); ! 442: ! 443: interruptSource->enable(); ! 444: ! 445: } ! 446: ! 447: ! 448: /*------------------------------------------------------------------------- ! 449: * ! 450: * ! 451: * ! 452: *-------------------------------------------------------------------------*/ ! 453: ! 454: UInt32 UniNEnet::outputPacket(struct mbuf * pkt) ! 455: { ! 456: UInt32 ret = kIOOQReturnSuccess; ! 457: ! 458: KERNEL_DEBUG(DBG_GEM_TXQUEUE | DBG_FUNC_NONE, (int) pkt, (int) pkt->m_pkthdr.len, 0, 0, 0 ); ! 459: ! 460: /* ! 461: * Hold the debugger lock so the debugger can't interrupt us ! 462: */ ! 463: reserveDebuggerLock(); ! 464: ! 465: if ( transmitPacket(pkt) == false ) ! 466: { ! 467: ret = kIOOQReturnStall; ! 468: } ! 469: ! 470: releaseDebuggerLock(); ! 471: ! 472: return ret; ! 473: } ! 474: ! 475: /*------------------------------------------------------------------------- ! 476: * ! 477: * ! 478: * ! 479: *-------------------------------------------------------------------------*/ ! 480: ! 481: bool UniNEnet::resetAndEnable(bool enable) ! 482: { ! 483: bool ret = true; ! 484: ! 485: reserveDebuggerLock(); ! 486: ! 487: ready = false; ! 488: ! 489: if (timerSource) ! 490: { ! 491: timerSource->cancelTimeout(); ! 492: } ! 493: ! 494: disableAdapterInterrupts(); ! 495: if (getWorkLoop()) ! 496: { ! 497: getWorkLoop()->disableAllInterrupts(); ! 498: } ! 499: ! 500: if ( resetChip() == false ) ! 501: { ! 502: ret = false; ! 503: goto resetAndEnable_exit; ! 504: } ! 505: ! 506: while (enable) ! 507: { ! 508: if (!initRxRing() || !initTxRing()) ! 509: { ! 510: ret = false; ! 511: break; ! 512: } ! 513: ! 514: if ( phyId != 0xff ) ! 515: { ! 516: miiInitializePHY(phyId); ! 517: } ! 518: ! 519: if (initChip() == false) ! 520: { ! 521: ret = false; ! 522: break; ! 523: } ! 524: ! 525: // startChip(); ! 526: ! 527: timerSource->setTimeoutMS(WATCHDOG_TIMER_MS); ! 528: ! 529: if (getWorkLoop()) ! 530: { ! 531: getWorkLoop()->enableAllInterrupts(); ! 532: } ! 533: enableAdapterInterrupts(); ! 534: ! 535: ready = true; ! 536: ! 537: // sendDummyPacket(); ! 538: ! 539: break; ! 540: } ! 541: ! 542: resetAndEnable_exit: ; ! 543: ! 544: releaseDebuggerLock(); ! 545: ! 546: return ret; ! 547: } ! 548: ! 549: /*------------------------------------------------------------------------- ! 550: * Called by IOEthernetInterface client to enable the controller. ! 551: * This method is always called while running on the default workloop ! 552: * thread. ! 553: *-------------------------------------------------------------------------*/ ! 554: ! 555: IOReturn UniNEnet::enable(IONetworkInterface * netif) ! 556: { ! 557: IONetworkParameter * param; ! 558: ! 559: /* ! 560: * If an interface client has previously enabled us, ! 561: * and we know there can only be one interface client ! 562: * for this driver, then simply return true. ! 563: */ ! 564: if (netifClient) ! 565: { ! 566: IOLog("EtherNet(UniN): already enabled\n"); ! 567: return kIOReturnSuccess; ! 568: } ! 569: ! 570: /* ! 571: * Grab a pointer to the statistics structure in the interface. ! 572: */ ! 573: param = netif->getParameter(kIONetworkStatsKey); ! 574: if (!param || !(netStats = (IONetworkStats *) param->getBuffer())) ! 575: { ! 576: IOLog("EtherNet(UniN): invalid network statistics\n"); ! 577: return kIOReturnError; ! 578: } ! 579: ! 580: if ((ready == false) && !resetAndEnable(true)) ! 581: return kIOReturnIOError; ! 582: ! 583: /* ! 584: * Record the interface as an active client. ! 585: */ ! 586: netifClient = true; ! 587: ! 588: /* ! 589: * Start our IOOutputQueue object. ! 590: */ ! 591: transmitQueue->setCapacity(TRANSMIT_QUEUE_SIZE); ! 592: transmitQueue->start(); ! 593: ! 594: return kIOReturnSuccess; ! 595: } ! 596: ! 597: /*------------------------------------------------------------------------- ! 598: * Called by IOEthernetInterface client to disable the controller. ! 599: * This method is always called while running on the default workloop ! 600: * thread. ! 601: *-------------------------------------------------------------------------*/ ! 602: ! 603: IOReturn UniNEnet::disable(IONetworkInterface * /*netif*/) ! 604: { ! 605: /* ! 606: * If we have no active clients, then disable the controller. ! 607: */ ! 608: if (debugClient == false) ! 609: { ! 610: resetAndEnable(false); ! 611: } ! 612: ! 613: /* ! 614: * Disable our IOOutputQueue object. This will prevent the ! 615: * outputPacket() method from being called. ! 616: */ ! 617: transmitQueue->stop(); ! 618: ! 619: /* ! 620: * Flush all packets currently in the output queue. ! 621: */ ! 622: transmitQueue->setCapacity(0); ! 623: transmitQueue->flush(); ! 624: ! 625: netifClient = false; ! 626: ! 627: return kIOReturnSuccess; ! 628: } ! 629: ! 630: /*------------------------------------------------------------------------- ! 631: * This method is called by our debugger client to bring up the controller ! 632: * just before the controller is registered as the debugger device. The ! 633: * debugger client is attached in response to the attachDebuggerClient() ! 634: * call. ! 635: * ! 636: * This method is always called while running on the default workloop ! 637: * thread. ! 638: *-------------------------------------------------------------------------*/ ! 639: ! 640: IOReturn UniNEnet::handleDebuggerOpen(IOKernelDebugger * /*debugger*/) ! 641: { ! 642: /* ! 643: * Enable hardware and make it ready to support the debugger client. ! 644: */ ! 645: if ((ready == false) && !resetAndEnable(true)) ! 646: { ! 647: return kIOReturnIOError; ! 648: } ! 649: ! 650: /* ! 651: * Record the debugger as an active client of ours. ! 652: */ ! 653: debugClient = true; ! 654: ! 655: /* ! 656: * Returning true will allow the kdp registration to continue. ! 657: * If we return false, then we will not be registered as the ! 658: * debugger device, and the attachDebuggerClient() call will ! 659: * return NULL. ! 660: */ ! 661: return kIOReturnSuccess; ! 662: } ! 663: ! 664: /*------------------------------------------------------------------------- ! 665: * This method is called by our debugger client to stop the controller. ! 666: * The debugger will call this method when we issue a detachDebuggerClient(). ! 667: * ! 668: * This method is always called while running on the default workloop ! 669: * thread. ! 670: *-------------------------------------------------------------------------*/ ! 671: ! 672: IOReturn UniNEnet::handleDebuggerClose(IOKernelDebugger * /*debugger*/) ! 673: { ! 674: debugClient = false; ! 675: ! 676: /* ! 677: * If we have no active clients, then disable the controller. ! 678: */ ! 679: if (netifClient == false) ! 680: { ! 681: resetAndEnable(false); ! 682: } ! 683: ! 684: return kIOReturnSuccess; ! 685: } ! 686: ! 687: ! 688: /*------------------------------------------------------------------------- ! 689: * ! 690: * ! 691: * ! 692: *-------------------------------------------------------------------------*/ ! 693: ! 694: void UniNEnet::timeoutOccurred(IOTimerEventSource * /*timer*/) ! 695: { ! 696: bool doService = false; ! 697: UInt32 txRingIndex; ! 698: ! 699: if ( ready == false ) ! 700: { ! 701: IOLog("EtherNet(UniN): Spurious timeout event!!\n"); ! 702: return; ! 703: } ! 704: ! 705: reserveDebuggerLock(); ! 706: ! 707: monitorLinkStatus(); ! 708: ! 709: /* ! 710: * If there are pending entries on the Tx ring ! 711: */ ! 712: if ( txCommandHead != txCommandTail ) ! 713: { ! 714: /* ! 715: * If the hardware tx pointer did not move since the last ! 716: * check, increment the txWDCount. ! 717: */ ! 718: txRingIndex = ReadUniNRegister( ioBaseEnet, kGEMTxCompletion ); ! 719: if ( txRingIndex == txRingIndexLast ) ! 720: { ! 721: txWDCount++; ! 722: } ! 723: else ! 724: { ! 725: txWDCount = 0; ! 726: txRingIndexLast = txRingIndex; ! 727: } ! 728: ! 729: if ( txWDCount > 2 ) ! 730: { ! 731: /* ! 732: * We only take interrupts every 64 tx completions, so we may be here just ! 733: * to do normal clean-up of tx packets. We check if the hardware tx pointer ! 734: * points to the next available tx slot. This indicates that we transmitted all ! 735: * packets that were scheduled vs rather than the hardware tx being stalled. ! 736: */ ! 737: if ( txRingIndex != txCommandTail ) ! 738: { ! 739: UInt32 interruptStatus, compReg, kickReg; ! 740: ! 741: interruptStatus = ReadUniNRegister( ioBaseEnet, kGEMInterruptStatus ); ! 742: compReg = ReadUniNRegister( ioBaseEnet, kGEMTxCompletion ); ! 743: kickReg = ReadUniNRegister( ioBaseEnet, kGEMTxKick ); ! 744: ! 745: //IOLog( "Tx Int Timeout - Comp = %04x Kick = %04x Int = %08x\n\r", (int)compReg, (int)kickReg, (int)interruptStatus ); ! 746: } ! 747: ! 748: // dumpRegisters(); ! 749: ! 750: transmitInterruptOccurred(); ! 751: ! 752: doService = true; ! 753: ! 754: txRingIndexLast = txRingIndex; ! 755: txWDCount = 0; ! 756: } ! 757: } ! 758: else ! 759: { ! 760: txWDCount = 0; ! 761: } ! 762: ! 763: /* ! 764: * Clean-up after the debugger if the debugger was active. ! 765: */ ! 766: if (debugTxPoll) ! 767: { ! 768: debugQueue->flush(); ! 769: debugTxPoll = false; ! 770: releaseDebuggerLock(); ! 771: doService = true; ! 772: } ! 773: else ! 774: { ! 775: releaseDebuggerLock(); ! 776: } ! 777: ! 778: /* ! 779: * Make sure the queue is not stalled. ! 780: */ ! 781: if (doService && netifClient) ! 782: { ! 783: transmitQueue->service(); ! 784: } ! 785: ! 786: /* ! 787: * Restart the watchdog timer ! 788: */ ! 789: timerSource->setTimeoutMS(WATCHDOG_TIMER_MS); ! 790: ! 791: } ! 792: ! 793: /*------------------------------------------------------------------------- ! 794: * ! 795: * ! 796: * ! 797: *-------------------------------------------------------------------------*/ ! 798: ! 799: const char * UniNEnet::getVendorString() const ! 800: { ! 801: return ("Apple"); ! 802: } ! 803: ! 804: const char * UniNEnet::getModelString() const ! 805: { ! 806: return ("gmac+"); ! 807: } ! 808: ! 809: const char * UniNEnet::getRevisionString() const ! 810: { ! 811: return (""); ! 812: } ! 813: ! 814: ! 815: /*------------------------------------------------------------------------- ! 816: * ! 817: * ! 818: * ! 819: *-------------------------------------------------------------------------*/ ! 820: ! 821: IOReturn UniNEnet::setPromiscuousMode(IOEnetPromiscuousMode mode) ! 822: { ! 823: UInt16 addressFilterReg; ! 824: ! 825: ! 826: reserveDebuggerLock(); ! 827: ! 828: addressFilterReg = ReadUniNRegister(ioBaseEnet, kGEMMacRxMacConfig); ! 829: ! 830: if (mode == kIOEnetPromiscuousModeOff) ! 831: { ! 832: addressFilterReg &= ~(kGEMMacRxMacConfig_ReceiveAll); ! 833: isPromiscuous = false; ! 834: ! 835: } ! 836: else ! 837: { ! 838: addressFilterReg |= kGEMMacRxMacConfig_ReceiveAll; ! 839: isPromiscuous = true; ! 840: ! 841: } ! 842: WriteUniNRegister(ioBaseEnet, kGEMMacRxMacConfig, addressFilterReg); ! 843: ! 844: releaseDebuggerLock(); ! 845: ! 846: return kIOReturnSuccess; ! 847: } ! 848: ! 849: /*------------------------------------------------------------------------- ! 850: * ! 851: * ! 852: * ! 853: *-------------------------------------------------------------------------*/ ! 854: ! 855: IOReturn UniNEnet::setMulticastMode(IOEnetMulticastMode mode) ! 856: { ! 857: multicastEnabled = (mode == kIOEnetMulticastModeOff) ? false : true; ! 858: ! 859: return kIOReturnSuccess; ! 860: } ! 861: ! 862: /*------------------------------------------------------------------------- ! 863: * ! 864: * ! 865: * ! 866: *-------------------------------------------------------------------------*/ ! 867: ! 868: IOReturn UniNEnet::setMulticastList(enet_addr_t *addrs, UInt count) ! 869: { ! 870: reserveDebuggerLock(); ! 871: ! 872: resetHashTableMask(); ! 873: for (UInt i = 0; i < count; i++) ! 874: { ! 875: addToHashTableMask(addrs->ea_byte); ! 876: addrs++; ! 877: } ! 878: updateHashTableMask(); ! 879: ! 880: releaseDebuggerLock(); ! 881: return kIOReturnSuccess; ! 882: } ! 883: ! 884: /*------------------------------------------------------------------------- ! 885: * ! 886: * ! 887: * ! 888: *-------------------------------------------------------------------------*/ ! 889: ! 890: IOOutputQueue * UniNEnet::allocateOutputQueue() ! 891: { ! 892: return IOOQLockFIFOQueue::withTarget( this, TRANSMIT_QUEUE_SIZE ); ! 893: } ! 894: ! 895: ! 896: ! 897: ! 898: ! 899: ! 900: ! 901: ! 902: ! 903: ! 904: ! 905: ! 906: ! 907: ! 908: ! 909:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.