Annotation of XNU/iokit/Drivers/network/drvPPCUniN/UniNEnet.cpp, revision 1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.