Annotation of XNU/iokit/Drivers/network/drvPPCUniN/UniNEnet.cpp, revision 1.1.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.