Annotation of XNU/iokit/Drivers/network/drvPPCBMac/BMacEnet.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 by Apple Computer, Inc., All rights reserved.
                     24:  *
                     25:  * Hardware independent (relatively) code for the BMac Ethernet Controller 
                     26:  *
                     27:  * HISTORY
                     28:  *
                     29:  * dd-mmm-yy    
                     30:  *     Created.
                     31:  *
                     32:  * Dec 10, 1998                jliu
                     33:  *  Converted to IOKit/C++.
                     34:  */
                     35: 
                     36: #include "BMacEnet.h"
                     37: #include "BMacEnetPrivate.h"
                     38: 
                     39: #include <IOKit/IORegistryEntry.h>
                     40: #include <IOKit/IODeviceTreeSupport.h>
                     41: #include <IOKit/platform/AppleMacIODevice.h>
                     42: #include <IOKit/assert.h>
                     43: 
                     44: // #define DEBUG_JOE   1
                     45: 
                     46: //------------------------------------------------------------------------
                     47: 
                     48: #define super IOEthernetController
                     49: 
                     50: OSDefineMetaClassAndStructors( BMacEnet, IOEthernetController )
                     51: 
                     52: //------------------------------------------------------------------------
                     53: 
                     54: #define PROVIDER_DEV   0
                     55: #define        PROVIDER_DMA_TX 1
                     56: #define        PROVIDER_DMA_RX 2
                     57: 
                     58: /*
                     59:  * Public Instance Methods
                     60:  */
                     61: 
                     62: /*-------------------------------------------------------------------------
                     63:  *
                     64:  *
                     65:  *
                     66:  *-------------------------------------------------------------------------*/
                     67: 
                     68: bool BMacEnet::init(OSDictionary * properties = 0)
                     69: {
                     70:        /*
                     71:         * Initialize my ivars.
                     72:         */
                     73:        networkInterface  = 0;
                     74:        transmitQueue     = 0;
                     75:        debugQueue        = 0;
                     76:        debugger          = 0;
                     77:        rxIntSrc          = 0;
                     78:        txDebuggerPkt     = 0;
                     79:        phyId             = 0xff;
                     80:        phyMIIDelay           = MII_DEFAULT_DELAY;
                     81:     sromAddressBits   = 6;
                     82:     enetAddressOffset = 20;
                     83:        phyStatusPrev     = 0;
                     84:        ready             = false;
                     85:        debugClient       = false;
                     86:        debugTxPoll       = false;
                     87:        netifClient       = false;
                     88:     isPromiscuous        = false;
                     89:     multicastEnabled  = false;
                     90: 
                     91:        if (!super::init(properties))
                     92:                return false;
                     93: 
                     94:        /*
                     95:         * Clear the mbuf rings.
                     96:         */
                     97:        for (int i = 0; i < TX_RING_LENGTH; i++)
                     98:                txMbuf[i] = 0;
                     99:        for (int i = 0; i < RX_RING_LENGTH; i++)
                    100:                rxMbuf[i] = 0;
                    101: 
                    102:        /*
                    103:         * Clear the memory map objects.
                    104:         */
                    105:        for (int i = 0; i < MEMORY_MAP_COUNT; i++)
                    106:                maps[i] = 0;
                    107: 
                    108:        return true;
                    109: }
                    110: 
                    111: bool BMacEnet::start(IOService * provider)
                    112: {
                    113:        AppleMacIODevice *nub = OSDynamicCast(AppleMacIODevice, provider);
                    114:        IOInterruptEventSource *intES;
                    115: 
                    116:        if (!nub || !super::start(provider))
                    117:                return false;
                    118: 
                    119:        transmitQueue = OSDynamicCast(IOOQGateFIFOQueue, getOutputQueue());
                    120:        if (!transmitQueue) {
                    121:                IOLog("BMac: output queue initialization failed\n");
                    122:                return false;
                    123:        }
                    124:        transmitQueue->retain();
                    125: 
                    126:        // Allocate debug queue. This stores packets retired from the TX ring
                    127:        // by the polling routine. We cannot call freePacket() or m_free() within
                    128:        // the debugger context.
                    129:        //
                    130:        // The capacity of the queue is set at maximum to prevent the queue from
                    131:        // calling m_free() due to over-capacity. But we don't expect the size
                    132:        // of the queue to grow too large.
                    133:        //
                    134:        debugQueue = IOPacketQueue::withCapacity((UInt) -1);
                    135:        if (!debugQueue)
                    136:                return false;
                    137: 
                    138:        // Allocate a IOMBufDBDMAMemoryCursor instance. Currently, the maximum
                    139:        // number of segments is set to 2. The maximum length for each segment
                    140:        // is set to the maximum ethernet frame size (plus padding).
                    141: 
                    142:        mbufCursor = IOMBufBigMemoryCursor::withSpecification(NETWORK_BUFSIZE, 2);
                    143:        if (!mbufCursor) {
                    144:                IOLog("Ethernet(BMac): IOMBufDBDMAMemoryCursor allocation failure\n");
                    145:                return false;
                    146:        }
                    147: 
                    148:        //
                    149:        // Our provider is the nub representing the BMacEnet hardware
                    150:        // controller. We will query it for our resource information.
                    151:        //
                    152: 
                    153:        for (int i = 0; i < MEMORY_MAP_HEATHROW_INDEX; i++) {
                    154:                IOMemoryMap *           map;
                    155:                
                    156:                map = provider->mapDeviceMemoryWithIndex(i);
                    157:                if (!map)
                    158:                        return false;
                    159: #ifdef DEBUG_JOE
                    160:                IOLog("map %d: Phys:%08x Virt:%08x len:%d\n",
                    161:                        i,
                    162:                        (unsigned) map->getPhysicalAddress(),
                    163:                        (unsigned) map->getVirtualAddress(),
                    164:                        (unsigned) map->getLength());
                    165: #endif DEBUG_JOE
                    166: 
                    167:                switch (i) {
                    168:                        case MEMORY_MAP_ENET_INDEX:
                    169:                                ioBaseEnet = (IOPPCAddress) map->getVirtualAddress();
                    170:                                break;
                    171:                        
                    172:                        case MEMORY_MAP_TXDMA_INDEX:
                    173:                                ioBaseEnetTxDMA = (IODBDMAChannelRegisters *)
                    174:                                        map->getVirtualAddress();
                    175:                                break;
                    176:                        
                    177:                        case MEMORY_MAP_RXDMA_INDEX:
                    178:                                ioBaseEnetRxDMA = (IODBDMAChannelRegisters *)
                    179:                                        map->getVirtualAddress();
                    180:                                break;
                    181:                }
                    182:                
                    183:                maps[i] = map;
                    184:        }
                    185: 
                    186: #ifdef DEBUG_JOE
                    187:        IOLog("ioBaseEnet:      0x%08x\n", ioBaseEnet);
                    188:        IOLog("ioBaseEnetTxDMA: 0x%08x\n", ioBaseEnetTxDMA);
                    189:        IOLog("ioBaseEnetRxDMA: 0x%08x\n", ioBaseEnetRxDMA);
                    190: #endif DEBUG_JOE
                    191: 
                    192:        //
                    193:        // We need to get the I/O address for the Heathrow controller.
                    194:        // We ask the provider (bmac) for its device tree parent.
                    195:        //
                    196:        IOService *heathrow;
                    197:        if (!(heathrow = OSDynamicCast(IOService,
                    198:                             provider->getParentEntry( gIODTPlane ))))
                    199:                return false;
                    200: 
                    201:        // Check whether the hardware is susceptible to the broken unicast
                    202:        // filter problem.
                    203:        //
                    204:        OSData * devIDData;
                    205:        devIDData = OSDynamicCast(OSData, heathrow->getProperty("device-id"));
                    206: 
                    207:        if (devIDData) {
                    208:                useUnicastFilter = ( *((UInt32 *) devIDData->getBytesNoCopy()) ==
                    209:                              0x10 );
                    210:                if (useUnicastFilter)
                    211:                        IOLog("%s: Enabling workaround for broken unicast filter\n", 
                    212:                                getName());
                    213:        }
                    214: 
                    215:        IOMemoryMap *           map = heathrow->mapDeviceMemoryWithIndex(0);
                    216:        if (map)
                    217:        {
                    218: #ifdef DEBUG_JOE
                    219:                IOLog("Heathrow: Phys:%08x Virt:%08x len:%d\n",
                    220:                        (unsigned) map->getPhysicalAddress(),
                    221:                        (unsigned) map->getVirtualAddress(),
                    222:                        (unsigned) map->getLength());
                    223: #endif DEBUG_JOE
                    224:                ioBaseHeathrow = (IOPPCAddress) map->getVirtualAddress();
                    225:                
                    226:                maps[MEMORY_MAP_HEATHROW_INDEX] = map;
                    227:        }
                    228:        else {
                    229:                return false;
                    230:        }
                    231: 
                    232:        //
                    233:        // Get a reference to the IOWorkLoop in our superclass.
                    234:        //
                    235:        IOWorkLoop * myWorkLoop = getWorkLoop();
                    236:        assert(myWorkLoop);
                    237: 
                    238:        //
                    239:        // Allocate three IOInterruptEventSources.
                    240:        //
                    241:        rxIntSrc = IOInterruptEventSource::interruptEventSource
                    242:             (this,
                    243:              (IOInterruptEventAction) &BMacEnet::interruptOccurredForSource,
                    244:              provider, PROVIDER_DMA_RX);
                    245:         if (!rxIntSrc
                    246:         || (myWorkLoop->addEventSource(rxIntSrc) != kIOReturnSuccess)) {
                    247:                IOLog("Ethernet(BMac): rxIntSrc init failure\n");
                    248:                return false;
                    249:        }
                    250: 
                    251:        intES = IOInterruptEventSource::interruptEventSource
                    252:             (this,
                    253:              (IOInterruptEventAction) &BMacEnet::interruptOccurredForSource,
                    254:              provider, PROVIDER_DMA_TX);
                    255:         if (intES) {
                    256:             bool res = (myWorkLoop->addEventSource(intES) != kIOReturnSuccess);
                    257:             intES->release();
                    258:             if (res) {
                    259:                IOLog("Ethernet(BMac): PROVIDER_DMA_TX add failure\n");
                    260:                 return false;
                    261:             }
                    262:         }
                    263:         else {
                    264:                IOLog("Mace: PROVIDER_DMA_TX init failure\n");
                    265:                return false;
                    266:        }
                    267:        
                    268:        intES = IOInterruptEventSource::interruptEventSource
                    269:             (this,
                    270:              (IOInterruptEventAction) &BMacEnet::interruptOccurredForSource,   
                    271:             provider, PROVIDER_DEV);   
                    272:        if (intES) {    
                    273:            bool res = (myWorkLoop->addEventSource(intES) != kIOReturnSuccess); 
                    274:            intES->release();   
                    275:            if (res) {
                    276:                IOLog("Ethernet(BMac): PROVIDER_DEV add failure\n");    
                    277:                return false;   
                    278:            }   
                    279:        }       
                    280:        else {
                    281:                IOLog("Ethernet(BMac): PROVIDER_DEV init failure\n");
                    282:                return false;
                    283:        }
                    284:        
                    285:        timerSrc = IOTimerEventSource::timerEventSource
                    286:             (this, (IOTimerEventSource::Action) &BMacEnet::timeoutOccurred);
                    287:        if (!timerSrc
                    288:        || (myWorkLoop->addEventSource(timerSrc) != kIOReturnSuccess)) {
                    289:                IOLog("Ethernet(BMac): timerSrc init failure\n");
                    290:                return false;
                    291:        }
                    292: 
                    293:        MGETHDR(txDebuggerPkt, M_DONTWAIT, MT_DATA);
                    294:        if (!txDebuggerPkt) {
                    295:                IOLog("Ethernet(BMac): Couldn't allocate KDB buffer\n");
                    296:                return false;
                    297:        }
                    298: 
                    299: #if 0
                    300:        // Enable the interrupt event sources. The hardware interrupts
                    301:        // sources remain disabled until _resetAndEnable(true) is called.
                    302:        //
                    303:        // myWorkLoop->enableAllInterrupts();
                    304: #endif
                    305: 
                    306:        //
                    307:        // Perform a hardware reset.
                    308:        //
                    309:     if ( !_resetAndEnable(false) ) 
                    310:     {
                    311:                return false;
                    312:     }
                    313: 
                    314:        //
                    315:        // Cache my MAC address.
                    316:        //
                    317:        getHardwareAddress(&myAddress);
                    318: 
                    319:        //
                    320:        // Allocate memory for ring buffers.
                    321:        //
                    322:     if (_allocateMemory() == false) 
                    323:     {
                    324:                return false;
                    325:     }
                    326: 
                    327:        //
                    328:        // Attach a kernel debugger client.
                    329:        //
                    330:        attachDebuggerClient(&debugger);
                    331: 
                    332:        //
                    333:        // Attach an IOEthernetInterface client.
                    334:        //
                    335:        if (!attachNetworkInterface((IONetworkInterface **) &networkInterface))
                    336:                return false;
                    337: 
                    338:        return true;
                    339: }
                    340: 
                    341: /*-------------------------------------------------------------------------
                    342:  *
                    343:  *
                    344:  *
                    345:  *-------------------------------------------------------------------------*/
                    346: 
                    347: void BMacEnet::free()
                    348: {
                    349:     UInt i;
                    350: 
                    351:        _resetAndEnable(false);
                    352: 
                    353:        if (debugger)
                    354:                debugger->release();
                    355: 
                    356:        if (getWorkLoop())
                    357:                getWorkLoop()->disableAllEventSources();
                    358: 
                    359:        if (timerSrc)
                    360:                timerSrc->release();
                    361: 
                    362:        if (rxIntSrc)
                    363:                rxIntSrc->release();
                    364: 
                    365:        if (txDebuggerPkt)
                    366:                freePacket(txDebuggerPkt);
                    367: 
                    368:        if (transmitQueue)
                    369:                transmitQueue->release();
                    370: 
                    371:        if (debugQueue)
                    372:                debugQueue->release();
                    373: 
                    374:     if (networkInterface)
                    375:                networkInterface->release();
                    376: 
                    377:        if (mbufCursor)
                    378:                mbufCursor->release();
                    379: 
                    380:     for (i = 0; i < rxMaxCommand; i++)
                    381:        if (rxMbuf[i]) freePacket(rxMbuf[i]);
                    382: 
                    383:     for (i = 0; i < txMaxCommand; i++)
                    384:        if (txMbuf[i]) freePacket(txMbuf[i]);
                    385: 
                    386:        for (i = 0; i < MEMORY_MAP_COUNT; i++)
                    387:                if (maps[i]) maps[i]->release();
                    388: 
                    389:        if (dmaMemory.ptr)
                    390:        {
                    391:                IOFree(dmaMemory.ptrReal, dmaMemory.sizeReal);
                    392:                dmaMemory.ptr = 0;
                    393:        }
                    394: 
                    395:        super::free();
                    396: }
                    397: 
                    398: /*-------------------------------------------------------------------------
                    399:  *
                    400:  *
                    401:  *
                    402:  *-------------------------------------------------------------------------*/
                    403: 
                    404: void BMacEnet::interruptOccurredForSource(IOInterruptEventSource *src,
                    405:                 int /*count*/)
                    406: {
                    407:        bool doFlushQueue = false;
                    408:        bool doService    = false;
                    409: 
                    410:        reserveDebuggerLock();
                    411: 
                    412:     statReg = ReadBigMacRegister( ioBaseEnet, kSTAT );
                    413: 
                    414:        if (src == rxIntSrc) {  
                    415:                KERNEL_DEBUG(DBG_BMAC_RXIRQ | DBG_FUNC_START, 0, 0, 0, 0, 0 );          
                    416:                doFlushQueue = _receiveInterruptOccurred();     
                    417:                KERNEL_DEBUG(DBG_BMAC_RXIRQ | DBG_FUNC_END,   0, 0, 0, 0, 0 );  
                    418:        }
                    419:        else {                  
                    420:       /*
                    421:        * On the transmit side, we use the chipset interrupt. Using the
                    422:           * transmit DMA interrupt (or having multiple transmit DMA entries)
                    423:           * would allows us to send the next frame to the chipset prior the 
                    424:           * transmit fifo going empty. 
                    425:        * However, this aggrevates a BMac chipset bug where the next frame going
                    426:           * out gets corrupted (first two bytes lost) if the chipset had to retry 
                    427:           * the previous frame.
                    428:        */ 
                    429:         txWDInterrupts++;
                    430:         KERNEL_DEBUG(DBG_BMAC_TXIRQ | DBG_FUNC_START, 0, 0, 0, 0, 0 );
                    431:                doService = _transmitInterruptOccurred();
                    432:         KERNEL_DEBUG(DBG_BMAC_TXIRQ | DBG_FUNC_END,   0, 0, 0, 0, 0 );
                    433:        }
                    434: 
                    435:        releaseDebuggerLock();
                    436: 
                    437:        /*
                    438:         * Submit all received packets queued up by _receiveInterruptOccurred()
                    439:         * to the network stack. The up call is performed without holding the
                    440:         * debugger lock.
                    441:         */
                    442:        if (doFlushQueue)
                    443:                networkInterface->flushInputQueue();
                    444: 
                    445:        /*
                    446:         * Unstall the output queue if some space was made available.
                    447:         */
                    448:        if (doService && netifClient)
                    449:                transmitQueue->service();
                    450: }
                    451: 
                    452: /*-------------------------------------------------------------------------
                    453:  *
                    454:  *
                    455:  *
                    456:  *-------------------------------------------------------------------------*/
                    457: 
                    458: UInt32 BMacEnet::outputPacket(struct mbuf * pkt)
                    459: {
                    460:        u_int32_t       i;
                    461:        UInt32      ret = kIOOQReturnSuccess;
                    462: 
                    463:     KERNEL_DEBUG(DBG_BMAC_TXQUEUE | DBG_FUNC_NONE, (int) pkt,
                    464:                (int) pkt->m_pkthdr.len, 0, 0, 0 );
                    465: 
                    466:     /*
                    467:      * Hold the debugger lock so the debugger can't interrupt us
                    468:      */
                    469:        reserveDebuggerLock();
                    470:  
                    471:     do
                    472:     {
                    473:                /* 
                    474:                 * Preliminary sanity checks
                    475:                 */
                    476:                assert(pkt && netifClient);
                    477: 
                    478: #if 0
                    479:                /*
                    480:                 * Remove any completed packets from the Tx ring 
                    481:                 */
                    482:                if ( chipId >= kCHIPID_PaddingtonXmitStreaming )
                    483:                {
                    484:                        _transmitInterruptOccurred(); 
                    485:                }
                    486: #endif
                    487: 
                    488:                i = txCommandTail + 1;
                    489:                if ( i >= txMaxCommand ) i = 0;
                    490:                if ( i == txCommandHead )
                    491:                {
                    492:                        /*
                    493:                         * Ring buffer is full. Disable the dequeueing process.
                    494:                         * We reenable it when an entry is made available by the
                    495:                         * transmit interrupt handler, or if a timeout occurs.
                    496:                         */
                    497:                        ret = kIOOQReturnStall;
                    498:                        continue;
                    499:                }
                    500: 
                    501:                /*
                    502:                 * If there is space on the Tx ring, add the packet directly to the
                    503:                 * ring.
                    504:                 */
                    505:                _transmitPacket(pkt);
                    506:     }
                    507:     while ( 0 );
                    508: 
                    509:        releaseDebuggerLock();
                    510: 
                    511:        return ret;
                    512: }
                    513: 
                    514: /*-------------------------------------------------------------------------
                    515:  *
                    516:  *
                    517:  *
                    518:  *-------------------------------------------------------------------------*/
                    519: 
                    520: bool BMacEnet::_resetAndEnable(bool enable)
                    521: {
                    522:        bool ret = true;
                    523: 
                    524: //     reserveDebuggerLock();
                    525: 
                    526:        ready = false;
                    527: 
                    528:        if (timerSrc) timerSrc->cancelTimeout();
                    529: 
                    530:        _disableAdapterInterrupts();
                    531:        if (getWorkLoop()) getWorkLoop()->disableAllInterrupts();
                    532: 
                    533:        _resetChip();
                    534:     
                    535:        while (enable)
                    536:        {
                    537:                if (!_initRxRing() || !_initTxRing())   
                    538:                {
                    539:                        ret = false;
                    540:                        break;
                    541:                }
                    542: 
                    543:                if ( phyId != 0xff )
                    544:                {
                    545:                        miiInitializePHY(phyId);
                    546:                }
                    547: 
                    548:                if (_initChip() == false)
                    549:                {
                    550:                        ret = false;
                    551:                        break;
                    552:                }
                    553: 
                    554:                _startChip();
                    555: 
                    556:                timerSrc->setTimeoutMS(WATCHDOG_TIMER_MS);
                    557: 
                    558:                if (getWorkLoop()) getWorkLoop()->enableAllInterrupts();
                    559:                _enableAdapterInterrupts();
                    560: 
                    561:                ready = true;
                    562: 
                    563:                _sendDummyPacket();
                    564: 
                    565:                break;
                    566:        }
                    567:        
                    568: //     releaseDebuggerLock();
                    569: 
                    570:     return ret;
                    571: }
                    572: 
                    573: /*-------------------------------------------------------------------------
                    574:  * Called by IOEthernetInterface client to enable the controller.
                    575:  * This method is always called while running on the default workloop
                    576:  * thread.
                    577:  *-------------------------------------------------------------------------*/
                    578: 
                    579: IOReturn BMacEnet::enable(IONetworkInterface * netif)
                    580: {
                    581:        IONetworkParameter * param;
                    582: 
                    583:        // If an interface client has previously enabled us,
                    584:        // and we know there can only be one interface client
                    585:        // for this driver, then simply return true.
                    586:        //
                    587:        if (netifClient) {
                    588:                IOLog("EtherNet(BMac): already enabled\n");
                    589:                return kIOReturnSuccess;
                    590:        }
                    591: 
                    592:        // Grab a pointer to the statistics structure in the interface.
                    593:        //
                    594:        param = netif->getParameter(kIONetworkStatsKey);
                    595:        if (!param || !(netStats = (IONetworkStats *) param->getBuffer()))
                    596:        {
                    597:                IOLog("EtherNet(BMac): invalid network statistics\n");
                    598:                return kIOReturnError;
                    599:        }
                    600: 
                    601:        if ((ready == false) && !_resetAndEnable(true))
                    602:                return kIOReturnIOError;
                    603: 
                    604:        // Record the interface as an active client.
                    605:        //
                    606:        netifClient = true;
                    607: 
                    608:        // Start our IOOutputQueue object.
                    609:        //
                    610:        transmitQueue->setCapacity(TRANSMIT_QUEUE_SIZE);
                    611:        transmitQueue->start();
                    612: 
                    613:        return kIOReturnSuccess;
                    614: }
                    615: 
                    616: /*-------------------------------------------------------------------------
                    617:  * Called by IOEthernetInterface client to disable the controller.
                    618:  * This method is always called while running on the default workloop
                    619:  * thread.
                    620:  *-------------------------------------------------------------------------*/
                    621:  
                    622: IOReturn BMacEnet::disable(IONetworkInterface * /*netif*/)
                    623: {
                    624:        // If we have no active clients, then disable the controller.
                    625:        //
                    626:        if (debugClient == false)
                    627:                _resetAndEnable(false);
                    628: 
                    629:        // Disable our IOOutputQueue object. This will prevent the
                    630:        // outputPacket() method from being called.
                    631:        //
                    632:        transmitQueue->stop();
                    633: 
                    634:        // Flush all packets currently in the output queue.
                    635:        //
                    636:        transmitQueue->setCapacity(0);
                    637:        transmitQueue->flush();
                    638:        
                    639:        netifClient = false;
                    640: 
                    641:        return kIOReturnSuccess;
                    642: }
                    643: 
                    644: /*-------------------------------------------------------------------------
                    645:  * This method is called by our debugger client to bring up the controller
                    646:  * just before the controller is registered as the debugger device. The
                    647:  * debugger client is attached in response to the attachDebuggerClient()
                    648:  * call.
                    649:  *
                    650:  * This method is always called while running on the default workloop
                    651:  * thread.
                    652:  *-------------------------------------------------------------------------*/
                    653: 
                    654: IOReturn BMacEnet::handleDebuggerOpen(IOKernelDebugger * /*debugger*/)
                    655: {
                    656:        // Enable hardware and make it ready to support the debugger client.
                    657:        //
                    658:        if ((ready == false) && !_resetAndEnable(true))
                    659:                return kIOReturnIOError;
                    660: 
                    661:        // Record the debugger as an active client of ours.
                    662:        //
                    663:        debugClient = true;
                    664: 
                    665:        // Returning true will allow the kdp registration to continue.
                    666:        // If we return false, then we will not be registered as the
                    667:        // debugger device, and the attachDebuggerClient() call will
                    668:        // return NULL.
                    669:        //
                    670:        return kIOReturnSuccess;
                    671: }
                    672: 
                    673: /*-------------------------------------------------------------------------
                    674:  * This method is called by our debugger client to stop the controller.
                    675:  * The debugger will call this method when we issue a detachDebuggerClient().
                    676:  *
                    677:  * This method is always called while running on the default workloop
                    678:  * thread.
                    679:  *-------------------------------------------------------------------------*/
                    680: 
                    681: IOReturn BMacEnet::handleDebuggerClose(IOKernelDebugger * /*debugger*/)
                    682: {
                    683:        debugClient = false;
                    684: 
                    685:        // If we have no active clients, then disable the controller.
                    686:        //
                    687:        if (netifClient == false)
                    688:                _resetAndEnable(false);
                    689: 
                    690:        return kIOReturnSuccess;
                    691: }
                    692: 
                    693: /*-------------------------------------------------------------------------
                    694:  *
                    695:  *
                    696:  *
                    697:  *-------------------------------------------------------------------------*/
                    698: 
                    699: void BMacEnet::timeoutOccurred(IOTimerEventSource * /*timer*/)
                    700: {
                    701:     u_int32_t          dmaStatus;
                    702:     u_int16_t          phyStatus;
                    703:     u_int16_t          linkStatus;
                    704:     u_int16_t          phyStatusChange;
                    705:        bool                    fullDuplex   = false;
                    706:        bool                    doFlushQueue = false;
                    707:        bool                    doService    = false;
                    708: 
                    709:        // IOLog("Ethernet(BMac): watchdog timer\n");
                    710: 
                    711:        reserveDebuggerLock();
                    712:        
                    713:     /*
                    714:      * Check for DMA shutdown on receive channel
                    715:      */
                    716:     dmaStatus = IOGetDBDMAChannelStatus( ioBaseEnetRxDMA );
                    717:     if ( !(dmaStatus & kdbdmaActive) )
                    718:     {
                    719: #if 0
                    720:                IOLog( "Ethernet(BMac): Timeout check - RxHead = %d RxTail = %d\n", 
                    721:                        rxCommandHead, rxCommandTail);
                    722: 
                    723:       IOLog( "Ethernet(BMac): Rx Commands = %08x(p) Rx DMA Ptr = %08x(p)\n\r", rxDMACommandsPhys, IOGetDBDMACommandPtr(ioBaseEnetRxDMA) ); 
                    724:       [self _dumpDesc:(void *)rxDMACommands Size:rxMaxCommand * sizeof(enet_dma_cmd_t)];
                    725: #endif
                    726: 
                    727:                doFlushQueue = _receiveInterruptOccurred();
                    728:        }
                    729: 
                    730:     /*
                    731:      * If there are pending entries on the Tx ring
                    732:      */
                    733:     if ( txCommandHead != txCommandTail )
                    734:     {
                    735:                /* 
                    736:                 * If we did not service the Tx ring during the last timeout interval,
                    737:                 * then force servicing of the Tx ring
                    738:                 */
                    739:                if ( txWDInterrupts == 0 )
                    740:                {
                    741:                        if ( txWDCount++ > 0 )
                    742:                        {
                    743:                                if (_transmitInterruptOccurred() == false)
                    744:                                {
                    745: #if 0
                    746:                                        IOLog( "Ethernet(BMac): Timeout check - TxHead = %d TxTail = %d\n", 
                    747:                                                txCommandHead, txCommandTail);
                    748: #endif
                    749:                                        _restartTransmitter();
                    750:                                }
                    751:                                doService = true;
                    752:                        }
                    753:                }
                    754:                else
                    755:                {
                    756:                        txWDInterrupts   = 0;
                    757:                        txWDCount        = 0;
                    758:                }
                    759:        }
                    760:     else
                    761:        {
                    762:                txWDInterrupts   = 0;
                    763:                txWDCount        = 0;
                    764:        }
                    765: 
                    766:     if ( phyId != 0xff )
                    767:     {
                    768:         if ( miiReadWord(&phyStatus, MII_STATUS, phyId) == true )
                    769:         {
                    770:             phyStatusChange = (phyStatusPrev ^ phyStatus) & 
                    771:                                (MII_STATUS_LINK_STATUS | MII_STATUS_NEGOTIATION_COMPLETE);
                    772:             if ( phyStatusChange )
                    773:             {
                    774:                 if ( (phyStatus & MII_STATUS_LINK_STATUS) &&
                    775:                                         (phyStatus & MII_STATUS_NEGOTIATION_COMPLETE ) )
                    776:                 {
                    777:                                        if ( (phyType & MII_ST10040_MASK) == MII_ST10040_ID )
                    778:                                        {
                    779:                                                miiReadWord(&linkStatus, MII_ST10040_CHIPST, phyId);
                    780:        
                    781:                                                fullDuplex =  (linkStatus & MII_ST10040_CHIPST_DUPLEX) ? true : false;
                    782:        
                    783:                                                IOLog( "Ethernet(BMac): Link is up at %sMb - %s Duplex\n\r",
                    784:                                                                (linkStatus & MII_ST10040_CHIPST_SPEED)  ? "100" : "10",
                    785:                                                                (fullDuplex)                             ? "Full" : "Half" );                        
                    786:                                        }
                    787:                                        else if ( (phyType & MII_DP83843_MASK) == MII_DP83843_ID )
                    788:                                        {
                    789:                                                miiReadWord(&linkStatus, MII_DP83843_PHYSTS, phyId);
                    790:        
                    791:                                                fullDuplex =  (linkStatus & MII_DP83843_PHYSTS_DUPLEX) ? true : false;
                    792:        
                    793:                                                IOLog( "Ethernet(BMac): Link is up at %sMb - %s Duplex\n\r",
                    794:                                                                (linkStatus & MII_DP83843_PHYSTS_SPEED10) ? "10" : "100",
                    795:                                                                (fullDuplex)                              ? "Full" : "Half" );           
                    796:                                        }  
                    797:                                        else
                    798:                                        {
                    799:                                                fullDuplex = false ;
                    800:                                                IOLog( "Ethernet(BMac): Link is up\n\r" );
                    801:                                        }
                    802:        
                    803:                                        if ( fullDuplex != isFullDuplex )
                    804:                                        {                                                       
                    805:                                                        _setDuplexMode(fullDuplex);
                    806:                                        }
                    807:                                }
                    808:                 else
                    809:                 {
                    810:                     IOLog( "Ethernet(BMac): Link is down.\n\r" );
                    811:                 }
                    812:                 phyStatusPrev = phyStatus;
                    813:             }
                    814:         }
                    815:     }
                    816: 
                    817:        // Clean-up after the debugger if the debugger was active.
                    818:        //
                    819:        if (debugTxPoll)
                    820:        {
                    821:                debugQueue->flush();
                    822:                debugTxPoll = false;
                    823:                releaseDebuggerLock();
                    824:                doService = true;
                    825:        }
                    826:        else
                    827:        {
                    828:                releaseDebuggerLock();
                    829:        }
                    830: 
                    831:        /*
                    832:         * Submit all received packets queued up by _receiveInterruptOccurred()
                    833:         * to the network stack. The up call is performed without holding the
                    834:         * debugger lock.
                    835:         */
                    836:        if (doFlushQueue)
                    837:        {
                    838:                networkInterface->flushInputQueue();
                    839:        }
                    840: 
                    841:        /*
                    842:         * Make sure the output queue is not stalled.
                    843:         */
                    844:        if (doService && netifClient)
                    845:        {
                    846:                transmitQueue->service();
                    847:        }
                    848: 
                    849:     /*
                    850:      * Restart the watchdog timer
                    851:      */
                    852:        timerSrc->setTimeoutMS(WATCHDOG_TIMER_MS);
                    853: }
                    854: 
                    855: /*-------------------------------------------------------------------------
                    856:  *
                    857:  *
                    858:  *
                    859:  *-------------------------------------------------------------------------*/
                    860: 
                    861: const char * BMacEnet::getVendorString() const
                    862: {
                    863:        return ("Apple");
                    864: }
                    865: 
                    866: const char * BMacEnet::getModelString() const
                    867: {
                    868:        return ("BMac");
                    869: }
                    870: 
                    871: const char * BMacEnet::getRevisionString() const
                    872: {
                    873:        return ("");
                    874: }
                    875: 
                    876: /*-------------------------------------------------------------------------
                    877:  *
                    878:  *
                    879:  *
                    880:  *-------------------------------------------------------------------------*/
                    881: 
                    882: IOReturn BMacEnet::setPromiscuousMode(IOEnetPromiscuousMode mode)
                    883: {
                    884:     u_int16_t          rxCFGVal;
                    885:     
                    886:        reserveDebuggerLock();
                    887: 
                    888:     /*
                    889:      * Turn off the receiver and wait for the chipset to acknowledge
                    890:      */
                    891:     rxCFGVal = ReadBigMacRegister(ioBaseEnet, kRXCFG);
                    892:     WriteBigMacRegister(ioBaseEnet, kRXCFG, rxCFGVal & ~kRxMACEnable );
                    893:     while( ReadBigMacRegister(ioBaseEnet, kRXCFG) & kRxMACEnable )
                    894:                ;
                    895: 
                    896:     /*
                    897:      * Set or reset promiscuous mode and restore receiver state
                    898:      */
                    899:        if (mode == kIOEnetPromiscuousModeOff) {
                    900:                rxCFGVal &= ~kRxPromiscEnable;
                    901:                isPromiscuous = false;
                    902:        }
                    903:        else {
                    904:                rxCFGVal |= kRxPromiscEnable;
                    905:                isPromiscuous = true;
                    906:        }
                    907: 
                    908:     WriteBigMacRegister( ioBaseEnet, kRXCFG, rxCFGVal );               
                    909: 
                    910:        releaseDebuggerLock();
                    911:     
                    912:     return kIOReturnSuccess;
                    913: }
                    914: 
                    915: IOReturn BMacEnet::setMulticastMode(IOEnetMulticastMode mode)
                    916: {
                    917:        multicastEnabled = (mode == kIOEnetMulticastModeOff) ? false : true;
                    918: 
                    919:        return kIOReturnSuccess;
                    920: }
                    921: 
                    922: IOReturn BMacEnet::setMulticastList(enet_addr_t *addrs, UInt count)
                    923: {
                    924:        reserveDebuggerLock();
                    925:        _resetHashTableMask();
                    926:        for (UInt i = 0; i < count; i++) {
                    927:                _addToHashTableMask(addrs->ea_byte);
                    928:                addrs++;
                    929:        }
                    930:        _updateBMacHashTableMask();
                    931:        releaseDebuggerLock();
                    932:        return kIOReturnSuccess;
                    933: }
                    934: 
                    935: /*
                    936:  * Kernel Debugger Support 
                    937:  */
                    938: void BMacEnet::sendPacket(void *pkt, unsigned int pkt_len)
                    939: {
                    940:        _sendPacket(pkt, pkt_len);
                    941: }
                    942: 
                    943: void BMacEnet::receivePacket(void *pkt, unsigned int *pkt_len,
                    944:        unsigned int timeout)
                    945: {
                    946:     _receivePacket(pkt, pkt_len, timeout);
                    947: }
                    948: 
                    949: /*
                    950:  * Allocate a WorkLoop serialized output queue object.
                    951:  */
                    952: IOOutputQueue * BMacEnet::allocateOutputQueue()
                    953: {
                    954:        return IOOQGateFIFOQueue::withTarget( this,
                    955:                                              getWorkLoop(), 
                    956:                                              TRANSMIT_QUEUE_SIZE );
                    957: }
                    958: 
                    959: #ifdef PM_SUPPORT
                    960: /*
                    961:  * Power management methods. 
                    962:  */
                    963: - (IOReturn)getPowerState:(PMPowerState *)state_p
                    964: {
                    965:     return kIOReturnUnsupported;
                    966: }
                    967: 
                    968: - (IOReturn)setPowerState:(PMPowerState)state
                    969: {
                    970:     if (state == PM_OFF) {
                    971:        resetAndEnabled = NO;
                    972:         [self _resetChip];
                    973:        return kIOReturnSuccess;
                    974:     }
                    975:     return kIOReturnUnsupported;
                    976: }
                    977: 
                    978: - (IOReturn)getPowerManagement:(PMPowerManagementState *)state_p
                    979: {
                    980:     return kIOReturnUnsupported;
                    981: }
                    982: 
                    983: - (IOReturn)setPowerManagement:(PMPowerManagementState)state
                    984: {
                    985:     return kIOReturnUnsupported;
                    986: }
                    987: #endif PM_SUPPORT

unix.superglobalmegacorp.com

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