Annotation of XNU/iokit/Drivers/network/drvPPCBMac/BMacEnet.cpp, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * The contents of this file constitute Original Code as defined in and
        !             7:  * are subject to the Apple Public Source License Version 1.1 (the
        !             8:  * "License").  You may not use this file except in compliance with the
        !             9:  * License.  Please obtain a copy of the License at
        !            10:  * http://www.apple.com/publicsource and read it before using this file.
        !            11:  * 
        !            12:  * This Original Code and all software distributed under the License are
        !            13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            17:  * License for the specific language governing rights and limitations
        !            18:  * under the License.
        !            19:  * 
        !            20:  * @APPLE_LICENSE_HEADER_END@
        !            21:  */
        !            22: /*
        !            23:  * Copyright (c) 1998-1999 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.