Annotation of XNU/iokit/Drivers/network/drvMaceEnet/MaceEnetPrivate.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) 1995-1996 NeXT Software, Inc.
                     24:  *
                     25:  * Implementation for hardware dependent (relatively) code 
                     26:  * for the Mace Ethernet controller. 
                     27:  *
                     28:  * HISTORY
                     29:  *
                     30:  * 10-Sept-97           
                     31:  *     Created.
                     32:  *
                     33:  */
                     34: 
                     35: #include <IOKit/assert.h>
                     36: #include <IOKit/system.h>
                     37: #include <IOKit/IOLib.h>
                     38: #include "MaceEnetPrivate.h"
                     39: 
                     40: 
                     41: /*****************************************************************************
                     42:  *
                     43:  * Hacks.
                     44:  */
                     45: 
                     46: typedef        unsigned long long      ns_time_t;      /* nanoseconds! */
                     47: 
                     48: #define NSEC_PER_SEC   1000000000
                     49: 
                     50: static void
                     51: _IOGetTimestamp(ns_time_t *nsp)
                     52: {
                     53:        mach_timespec_t         now;
                     54: 
                     55:        IOGetTime(&now);
                     56:        *nsp = ((ns_time_t)now.tv_sec * NSEC_PER_SEC) + now.tv_nsec;
                     57: }
                     58: 
                     59: /*
                     60:  * Find a physical address (if any) for the specified virtual address.
                     61:  *
                     62:  * Note: what about vm_offset_t kvtophys(vm_offset_t va) 
                     63:  */
                     64: static IOReturn _IOPhysicalFromVirtual(
                     65:        vm_address_t virtualAddress,
                     66:        unsigned *physicalAddress)
                     67: {
                     68:        *physicalAddress = pmap_extract(kernel_pmap, virtualAddress);
                     69:        if(*physicalAddress == 0) {
                     70:                return kIOReturnBadArgument;
                     71:        }
                     72:        else {
                     73:                return kIOReturnSuccess;
                     74:        }
                     75: }
                     76: 
                     77: // From osfmk/ppc/pmap.h
                     78: //
                     79: extern "C" {
                     80: extern void invalidate_dcache(vm_offset_t va, unsigned length, boolean_t phys);
                     81: extern void flush_dcache(vm_offset_t va, unsigned length, boolean_t phys);
                     82: }
                     83: 
                     84: static inline void 
                     85: invalidate_cache_v(vm_offset_t va, unsigned length)
                     86: {
                     87:        invalidate_dcache(va, length, 0);
                     88: }
                     89: 
                     90: static inline void
                     91: flush_cache_v(vm_offset_t va, unsigned length)
                     92: {
                     93:        flush_dcache(va, length, 0);
                     94: }
                     95: 
                     96: /****************************************************************************/
                     97: 
                     98: static IODBDMADescriptor               dbdmaCmd_Nop;
                     99: static IODBDMADescriptor       dbdmaCmd_NopWInt;
                    100: static IODBDMADescriptor       dbdmaCmd_LoadXFS;
                    101: static IODBDMADescriptor        dbdmaCmd_LoadIntwInt;          
                    102: static IODBDMADescriptor               dbdmaCmd_Stop;
                    103: static IODBDMADescriptor               dbdmaCmd_Branch;
                    104: 
                    105: 
                    106: static u_int8_t reverseBitOrder(u_int8_t data )
                    107: {
                    108:     u_int8_t   val = 0;
                    109:     int                        i;
                    110: 
                    111:     for ( i=0; i < 8; i++ )
                    112:     {
                    113:       val <<= 1;
                    114:       if (data & 1) val |= 1;
                    115:       data >>= 1;
                    116:     }
                    117:     return( val );
                    118: }      
                    119: 
                    120: /*
                    121:  * Function: IOMallocPage
                    122:  *
                    123:  * Purpose:
                    124:  *   Returns a pointer to a page-aligned memory block of size >= PAGE_SIZE
                    125:  *
                    126:  * Return:
                    127:  *   Actual pointer and size of block returned in actual_ptr and actual_size.
                    128:  *   Use these as arguments to kfree: kfree(*actual_ptr, *actual_size);
                    129:  */
                    130: static void *
                    131: IOMallocPage(int request_size, void ** actual_ptr, u_int * actual_size)
                    132: {
                    133:     void * mem_ptr;
                    134:     
                    135:        *actual_size = round_page(request_size) + PAGE_SIZE;
                    136:        mem_ptr = IOMalloc(*actual_size);
                    137:        if (mem_ptr == NULL)
                    138:                return NULL;
                    139:        *actual_ptr = mem_ptr;
                    140:        return ((void *)round_page(mem_ptr));
                    141: }
                    142: 
                    143: /*
                    144:  * Private functions
                    145:  */
                    146: bool MaceEnet::_allocateMemory()
                    147: {
                    148:     u_int32_t                  i, n;
                    149:     unsigned char *            virtAddr;
                    150:     u_int32_t                  physBase;
                    151:     u_int32_t                  physAddr;
                    152:        u_int32_t                       dbdmaSize;
                    153: 
                    154:     /* 
                    155:      * Calculate total space for DMA channel commands
                    156:      */
                    157:     dbdmaSize = round_page(
                    158:                RX_RING_LENGTH * sizeof(enet_dma_cmd_t) +
                    159:                TX_RING_LENGTH * sizeof(enet_txdma_cmd_t) +
                    160:                2 * sizeof(IODBDMADescriptor) );
                    161: 
                    162:     /*
                    163:      * Allocate required memory
                    164:      */
                    165:        dmaMemory.size = dbdmaSize;
                    166:        dmaMemory.ptr = (void *)IOMallocPage(
                    167:                                 dmaMemory.size,
                    168:                                 &dmaMemory.ptrReal,
                    169:                                 &dmaMemory.sizeReal
                    170:                                 );
                    171: 
                    172:        dmaCommands = (unsigned char *) dmaMemory.ptr;
                    173:        if (!dmaCommands) {
                    174:                IOLog( "Mace: Cant allocate channel DBDMA commands\n\r" );
                    175:                return false;
                    176:        }
                    177: 
                    178:     /*
                    179:      * If we needed more than one page, then make sure we received
                    180:         * contiguous memory.
                    181:      */
                    182:     n = (dbdmaSize - PAGE_SIZE) / PAGE_SIZE;
                    183:     _IOPhysicalFromVirtual((vm_address_t) dmaCommands, &physBase );
                    184: 
                    185:     virtAddr = (unsigned char *) dmaCommands;
                    186:     for( i=0; i < n; i++, virtAddr += PAGE_SIZE )
                    187:     {
                    188:                _IOPhysicalFromVirtual( (vm_address_t) virtAddr, &physAddr );
                    189:                if (physAddr != (physBase + i * PAGE_SIZE) )
                    190:                {
                    191:                        IOLog("Mace: Cannot allocate contiguous memory for DBDMA "
                    192:                                "commands\n");
                    193:                        return false;
                    194:                }
                    195:        }           
                    196: 
                    197:     /* 
                    198:      * Setup the receive ring pointers
                    199:      */
                    200:     rxDMACommands = (enet_dma_cmd_t *)dmaCommands;
                    201:     rxMaxCommand  = RX_RING_LENGTH;
                    202: 
                    203:     /*
                    204:      * Setup the transmit ring pointers
                    205:      */
                    206:     txDMACommands = (enet_txdma_cmd_t *)(
                    207:                dmaCommands + 
                    208:                RX_RING_LENGTH * sizeof(enet_dma_cmd_t) +
                    209:                sizeof(IODBDMADescriptor));
                    210: 
                    211:     txMaxCommand  = TX_RING_LENGTH;
                    212: 
                    213:     /*
                    214:      * Setup pre-initialized DBDMA commands 
                    215:      */
                    216:     IOMakeDBDMADescriptor( (&dbdmaCmd_Nop),
                    217:                             kdbdmaNop,
                    218:                             kdbdmaKeyStream0,
                    219:                             kdbdmaIntNever,
                    220:                             kdbdmaBranchNever,
                    221:                             kdbdmaWaitNever,
                    222:                             0,
                    223:                             0 );
                    224: 
                    225:     IOMakeDBDMADescriptor( (&dbdmaCmd_NopWInt),
                    226:                             kdbdmaNop,
                    227:                             kdbdmaKeyStream0,
                    228:                             kdbdmaIntAlways,
                    229:                             kdbdmaBranchNever,
                    230:                             kdbdmaWaitNever,
                    231:                             0,
                    232:                             0 );
                    233: 
                    234:        UInt32 ioBaseEnetPhys = maps[MEMORY_MAP_ENET_INDEX]->getPhysicalAddress();
                    235: 
                    236:     IOMakeDBDMADescriptor( (&dbdmaCmd_LoadXFS),
                    237:                             kdbdmaLoadQuad,
                    238:                             kdbdmaKeySystem,
                    239:                             kdbdmaIntNever,
                    240:                             kdbdmaBranchNever,
                    241:                             kdbdmaWaitNever,
                    242:                             1,
                    243:                             ((int)ioBaseEnetPhys +  kXmtFS) );
                    244: 
                    245:     IOMakeDBDMADescriptor( (&dbdmaCmd_LoadIntwInt),
                    246:                             kdbdmaLoadQuad,
                    247:                             kdbdmaKeySystem,
                    248:                             kdbdmaIntAlways,
                    249:                             kdbdmaBranchNever,
                    250:                             kdbdmaWaitNever,
                    251:                             1,
                    252:                             ((int)ioBaseEnetPhys +  kIntReg) );
                    253: 
                    254:     IOMakeDBDMADescriptor( (&dbdmaCmd_Stop),
                    255:                             kdbdmaStop,
                    256:                             kdbdmaKeyStream0,
                    257:                             kdbdmaIntNever,
                    258:                             kdbdmaBranchNever,
                    259:                             kdbdmaWaitNever,
                    260:                             0,
                    261:                             0 );
                    262: 
                    263:     IOMakeDBDMADescriptor( (&dbdmaCmd_Branch),
                    264:                             kdbdmaNop,
                    265:                             kdbdmaKeyStream0,
                    266:                             kdbdmaIntNever,
                    267:                             kdbdmaBranchAlways,
                    268:                             kdbdmaWaitNever,
                    269:                             0,
                    270:                             0 );
                    271: 
                    272:     return true;
                    273: }
                    274: 
                    275: /*-------------------------------------------------------------------------
                    276:  *
                    277:  * Setup the Transmit Ring
                    278:  * -----------------------
                    279:  * Each transmit ring entry consists of two words to transmit data from buffer
                    280:  * segments (possibly) spanning a page boundary. This is followed by two DMA 
                    281:  * commands which read transmit frame status and interrupt status from the Mace 
                    282:  * chip. The last DMA command in each transmit ring entry generates a host 
                    283:  * interrupt. The last entry in the ring is followed by a DMA branch to the 
                    284:  * first entry.
                    285:  *-------------------------------------------------------------------------*/
                    286: 
                    287: bool MaceEnet::_initTxRing()
                    288: {
                    289:     bool                       kr;
                    290:     u_int32_t          i;
                    291: 
                    292:     /*
                    293:      * Clear the transmit DMA command memory
                    294:      */
                    295:     bzero( (void *)txDMACommands, sizeof(enet_txdma_cmd_t) * txMaxCommand);
                    296:     txCommandHead = 0;
                    297:     txCommandTail = 0;
                    298: 
                    299:     /*
                    300:      * DMA Channel commands 2,3 are the same for all DBDMA entries on transmit. 
                    301:      * Initialize them now.
                    302:      */
                    303:     for( i=0; i < txMaxCommand; i++ )
                    304:     {
                    305:                txDMACommands[i].desc_seg[2] = dbdmaCmd_LoadXFS;
                    306:                txDMACommands[i].desc_seg[3] = dbdmaCmd_LoadIntwInt;
                    307:     }
                    308: 
                    309:     /* 
                    310:      * Put a DMA Branch command after the last entry in the transmit ring.
                    311:         * Set the branch address to the physical address of the start of the 
                    312:         * transmit ring.
                    313:      */
                    314:     txDMACommands[txMaxCommand].desc_seg[0] = dbdmaCmd_Branch; 
                    315: 
                    316:     kr = _IOPhysicalFromVirtual( (vm_address_t) txDMACommands,
                    317:                (u_int32_t *)&txDMACommandsPhys );
                    318:     if ( kr != kIOReturnSuccess )
                    319:     {
                    320:                IOLog("Mace: Bad Tx DBDMA command buf - %08x\n\r",
                    321:                        (u_int32_t)txDMACommands );
                    322:     }
                    323:     IOSetCCCmdDep( &txDMACommands[txMaxCommand].desc_seg[0],
                    324:                txDMACommandsPhys );
                    325: 
                    326:     /* 
                    327:      * Set the Transmit DMA Channel pointer to the first entry in the
                    328:         * transmit ring.
                    329:      */
                    330:     IOSetDBDMACommandPtr( ioBaseEnetTxDMA, txDMACommandsPhys );
                    331: 
                    332:     /*
                    333:      * Push the DMA channel words into physical memory.
                    334:      */
                    335:     flush_cache_v( (vm_offset_t)txDMACommands, 
                    336:                txMaxCommand*sizeof(enet_txdma_cmd_t) + sizeof(IODBDMADescriptor));
                    337: 
                    338:     return true;
                    339: }
                    340: 
                    341: /*-------------------------------------------------------------------------
                    342:  *
                    343:  * Setup the Receive ring
                    344:  * ----------------------
                    345:  * Each receive ring entry consists of two DMA commands to receive data
                    346:  * into a network buffer (possibly) spanning a page boundary. The second
                    347:  * DMA command in each entry generates a host interrupt.
                    348:  * The last entry in the ring is followed by a DMA branch to the first
                    349:  * entry. 
                    350:  *
                    351:  *-------------------------------------------------------------------------*/
                    352: 
                    353: bool MaceEnet::_initRxRing()
                    354: {
                    355:     u_int32_t                  i;
                    356:     bool                               status;
                    357:     IOReturn                   kr;
                    358: 
                    359:     /*
                    360:      * Clear the receive DMA command memory
                    361:      */
                    362:     bzero( (void *)rxDMACommands, sizeof(enet_dma_cmd_t) * rxMaxCommand);
                    363: 
                    364:     kr = _IOPhysicalFromVirtual( (vm_address_t) rxDMACommands,
                    365:                (u_int32_t *)&rxDMACommandsPhys );
                    366:     if ( kr != kIOReturnSuccess )
                    367:     {
                    368:                IOLog("Mace: Bad Rx DBDMA command buf - %08x\n\r",  
                    369:                        (u_int32_t)rxDMACommands );
                    370:                return false;
                    371:     }
                    372: 
                    373:     /*
                    374:      * Allocate a receive buffer for each entry in the Receive ring
                    375:      */
                    376:     for (i = 0; i < rxMaxCommand-1; i++) 
                    377:     {
                    378:                if (rxMbuf[i] == 0)     
                    379:                {
                    380:                rxMbuf[i] = allocatePacket(NETWORK_BUFSIZE);
                    381: 
                    382:                        if (!rxMbuf[i]) 
                    383:                        {
                    384:                                IOLog("Mace: allocatePacket failed in _initRxRing()\n\r");
                    385:                        return false;
                    386:                        }
                    387:                }
                    388:                
                    389:                /* 
                    390:                 * Set the DMA commands for the ring entry to transfer data to the 
                    391:                 * mbuf.
                    392:                 */
                    393:                status = _updateDescriptorFromMbuf(rxMbuf[i], &rxDMACommands[i], true);
                    394:                if (status == false)
                    395:                {    
                    396:                        IOLog("Mace: Cant map mbuf to physical memory in _initRxRing\n\r");
                    397:                        return false;
                    398:                }
                    399:     }
                    400:     
                    401:     /*
                    402:      * Set the receive queue head to point to the first entry in the ring.
                    403:         * Set the receive queue tail to point to a DMA Stop command after the
                    404:         * last ring entry
                    405:      */
                    406:     rxCommandHead = 0;
                    407:     rxCommandTail = i;
                    408: 
                    409:     rxDMACommands[i].desc_seg[0] = dbdmaCmd_Stop; 
                    410:     rxDMACommands[i].desc_seg[1] = dbdmaCmd_Nop;
                    411: 
                    412:     /*
                    413:      * Setup a DMA branch command after the stop command
                    414:      */
                    415:     i++;
                    416:     rxDMACommands[i].desc_seg[0] = dbdmaCmd_Branch; 
                    417: 
                    418:     IOSetCCCmdDep( &rxDMACommands[i].desc_seg[0], rxDMACommandsPhys );
                    419: 
                    420:     /*
                    421:      * Set DMA command pointer to first receive entry
                    422:      */ 
                    423:     IOSetDBDMACommandPtr( ioBaseEnetRxDMA, rxDMACommandsPhys );
                    424: 
                    425:     /*
                    426:      * Push DMA commands to physical memory
                    427:      */
                    428:     flush_cache_v( (vm_offset_t)&rxDMACommands[rxCommandTail], 
                    429:                2 * sizeof(enet_dma_cmd_t) );
                    430: 
                    431:     return true;
                    432: }
                    433: 
                    434: /*-------------------------------------------------------------------------
                    435:  *
                    436:  *
                    437:  *
                    438:  *-------------------------------------------------------------------------*/
                    439: 
                    440: void MaceEnet::_startChip()
                    441: {
                    442:     WriteMaceRegister( ioBaseEnet, kMacCC, kMacCCEnXmt | kMacCCEnRcv );
                    443: 
                    444:     // enable rx dma channel
                    445:     IODBDMAContinue( ioBaseEnetRxDMA );
                    446: }
                    447: 
                    448: /*-------------------------------------------------------------------------
                    449:  *
                    450:  *
                    451:  *
                    452:  *-------------------------------------------------------------------------*/
                    453: 
                    454: void MaceEnet::_resetChip()
                    455: {
                    456:     u_int8_t                   regValue;
                    457: 
                    458:     /*
                    459:      * Mace errata - chip reset does not clear pending interrupts
                    460:      */
                    461:     ReadMaceRegister( ioBaseEnet, kIntReg );
                    462: 
                    463:     IODBDMAReset( ioBaseEnetRxDMA );  
                    464:     IODBDMAReset( ioBaseEnetTxDMA );  
                    465: 
                    466:     IOSetDBDMAWaitSelect( ioBaseEnetTxDMA,
                    467:                IOSetDBDMAChannelControlBits( kdbdmaS5 ) );
                    468: 
                    469:     IOSetDBDMABranchSelect( ioBaseEnetRxDMA,
                    470:                IOSetDBDMAChannelControlBits( kdbdmaS6 ) );
                    471: 
                    472:     IOSetDBDMAInterruptSelect( ioBaseEnetRxDMA,
                    473:                IOSetDBDMAChannelControlBits( kdbdmaS6 ) );
                    474: 
                    475:     WriteMaceRegister( ioBaseEnet, kBIUCC, kBIUCCSWRst );
                    476:     do
                    477:     {
                    478:                regValue = ReadMaceRegister( ioBaseEnet, kBIUCC );
                    479:     }
                    480:     while( regValue & kBIUCCSWRst );
                    481: }
                    482: 
                    483: /*-------------------------------------------------------------------------
                    484:  *
                    485:  *
                    486:  *
                    487:  *-------------------------------------------------------------------------*/
                    488: 
                    489: bool MaceEnet::_initChip()
                    490: {
                    491:     volatile u_int16_t regValue;
                    492:     u_int32_t                  i;
                    493: 
                    494:        _disableAdapterInterrupts();
                    495: 
                    496:     chipId  = ReadMaceRegister( ioBaseEnet, kMaceChipId0 );
                    497:     chipId |= ReadMaceRegister( ioBaseEnet, kMaceChipId1 ) << 8;
                    498: 
                    499:     /*
                    500:      * Turn off ethernet header stripping
                    501:      */
                    502:     regValue  = ReadMaceRegister( ioBaseEnet, kRcvFC );
                    503:     regValue &= ~kRcvFCAStrpRcv;
                    504:     WriteMaceRegister( ioBaseEnet, kRcvFC, regValue );
                    505: 
                    506:     /*
                    507:      * Set Mace destination address. 
                    508:      */
                    509:     if ( chipId != kMaceRevisionA2 )
                    510:     { 
                    511:                WriteMaceRegister( ioBaseEnet, kIAC, kIACAddrChg | kIACPhyAddr );
                    512:                do
                    513:                {
                    514:                        regValue = ReadMaceRegister( ioBaseEnet, kIAC );
                    515:                }
                    516:                while( regValue & kIACAddrChg );
                    517:        }
                    518:        else
                    519:        {
                    520:                WriteMaceRegister( ioBaseEnet, kIAC, kIACPhyAddr );
                    521:     }
                    522: 
                    523:     for (i=0; i < sizeof(enet_addr_t); i++ )
                    524:        {
                    525:                WriteMaceRegister( ioBaseEnet, kPADR,
                    526:                        reverseBitOrder(((unsigned char *)ioBaseEnetROM)[i<<4]) );
                    527:     }
                    528: 
                    529:     /*
                    530:      * Clear logical address (multicast) filter
                    531:      */
                    532:     if ( chipId != kMaceRevisionA2 )
                    533:     { 
                    534:                WriteMaceRegister( ioBaseEnet, kIAC, kIACAddrChg | kIACLogAddr );
                    535:                do
                    536:                {
                    537:                        regValue = ReadMaceRegister( ioBaseEnet, kIAC );
                    538:                }
                    539:                while( regValue & kIACAddrChg );
                    540:     }
                    541:     else
                    542:     {
                    543:                WriteMaceRegister( ioBaseEnet, kIAC, kIACLogAddr );
                    544:     }
                    545: 
                    546:     for (i = 0; i < 8; i++ )
                    547:     {
                    548:                WriteMaceRegister( ioBaseEnet, kLADRF, 0 );
                    549:     }
                    550: 
                    551:     /* 
                    552:      * Enable ethernet transceiver 
                    553:      */
                    554:     WriteMaceRegister( ioBaseEnet, kPLSCC, kPLSCCPortSelGPSI | kPLSCCEnSts );
                    555: 
                    556:     return true;
                    557: }
                    558: 
                    559: 
                    560: /*-------------------------------------------------------------------------
                    561:  *
                    562:  *
                    563:  *
                    564:  *-------------------------------------------------------------------------*/
                    565: 
                    566: void MaceEnet::_restartChip()
                    567: {
                    568:     /*
                    569:      * Shutdown DMA channels
                    570:      */
                    571:        _stopReceiveDMA();
                    572:        _stopTransmitDMA();
                    573: 
                    574:     /*
                    575:      * Get the silicon's attention
                    576:      */
                    577:        _resetChip();
                    578:        _initChip();
                    579: 
                    580:     /*
                    581:      * Restore multicast settings
                    582:      */
                    583:        _updateHashTableMask();
                    584: 
                    585:     if ( isPromiscuous )
                    586:     {
                    587:                _setPromiscuousMode(kIOEnetPromiscuousModeOn);
                    588:     }
                    589: 
                    590:     /*
                    591:      * Enable receiver and transmitter
                    592:      */
                    593:        _startChip();
                    594:        _enableAdapterInterrupts(); 
                    595: 
                    596:     /*
                    597:      * Restart transmit DMA
                    598:      */
                    599:     IODBDMAContinue( ioBaseEnetTxDMA );
                    600: }
                    601: 
                    602: /*-------------------------------------------------------------------------
                    603:  *
                    604:  * Orderly stop of receive DMA.
                    605:  *
                    606:  *
                    607:  *-------------------------------------------------------------------------*/
                    608: 
                    609: void MaceEnet::_stopReceiveDMA()
                    610: {
                    611:     u_int32_t          dmaStatus;
                    612:     u_int32_t          dmaCmdPtr;
                    613:     u_int32_t          dmaIndex;
                    614:     u_int8_t           tmpBuf[16];
                    615:     u_int8_t           *p = 0;
                    616:     u_int8_t           MacCCReg;
                    617: 
                    618:     /* 
                    619:      * Stop the receiver and allow any frame receive in progress to complete
                    620:      */
                    621:     MacCCReg = ReadMaceRegister( ioBaseEnet, kMacCC );
                    622:     WriteMaceRegister( ioBaseEnet, kMacCC, MacCCReg & ~kMacCCEnRcv );
                    623:     IODelay( RECEIVE_QUIESCE_uS );
                    624: 
                    625:     /* 
                    626:      * Capture channel status and pause the dma channel.
                    627:      */
                    628:     dmaStatus = IOGetDBDMAChannelStatus( ioBaseEnetRxDMA );
                    629:     IODBDMAPause( ioBaseEnetRxDMA );
                    630: 
                    631:     /*
                    632:      * Read the command pointer and convert it to a byte offset into the
                    633:         * DMA program.
                    634:      */
                    635:     dmaCmdPtr = IOGetDBDMACommandPtr( ioBaseEnetRxDMA );
                    636:     dmaIndex  = (dmaCmdPtr - rxDMACommandsPhys);
                    637: 
                    638:     /*
                    639:      * If the channel status is DEAD, the DMA pointer is pointing to the
                    640:         * next command
                    641:      */
                    642:     if ( dmaStatus & kdbdmaDead )
                    643:     {
                    644:                dmaIndex -= sizeof(IODBDMADescriptor);
                    645:     }
                    646: 
                    647:     /*
                    648:      * Convert channel program offset to command index
                    649:      */
                    650:     dmaIndex = dmaIndex / sizeof(enet_dma_cmd_t);
                    651:     if ( dmaIndex >= rxMaxCommand ) dmaIndex = 0;
                    652:       
                    653:     /*
                    654:      * The DMA controller doesnt like being stopped before transferring any 
                    655:         * data. 
                    656:      *
                    657:      * When we do so it pollutes up to 16-bytes aligned to the nearest (lower) 
                    658:         * 16-byte boundary. This corruption can be outside the data transfer area 
                    659:         * of the mbuf, so we capture and then restore these bytes after stopping 
                    660:         * the channel. 
                    661:      *
                    662:      */
                    663:     if ( rxMbuf[dmaIndex] )
                    664:     {
                    665:                p = mtod(rxMbuf[dmaIndex], u_int8_t *);
                    666:     }
                    667: 
                    668:     (u_int32_t)p &= ~0x0f;
                    669: 
                    670:     if ( p )
                    671:     {
                    672:                bcopy( p, tmpBuf, 16 );
                    673:     }
                    674: 
                    675:     IODBDMAReset( ioBaseEnetRxDMA );
                    676: 
                    677:     if ( p )
                    678:     {
                    679:                bcopy( tmpBuf, p, 16 );
                    680:     }
                    681: 
                    682:     /*
                    683:      * Reset the dma channel pointer to the nearest command index
                    684:      */
                    685:     dmaCmdPtr = rxDMACommandsPhys + sizeof(enet_dma_cmd_t) * dmaIndex;
                    686:     IOSetDBDMACommandPtr( ioBaseEnetRxDMA, dmaCmdPtr);
                    687: }    
                    688: 
                    689: /*-------------------------------------------------------------------------
                    690:  *
                    691:  *
                    692:  *
                    693:  *-------------------------------------------------------------------------*/
                    694: 
                    695: void MaceEnet::_stopTransmitDMA()
                    696: {
                    697:     u_int32_t          dmaStatus;
                    698:     u_int32_t          dmaCmdPtr;
                    699:     u_int32_t          dmaIndex;
                    700:     u_int8_t           MacCCReg;
                    701: 
                    702:     /* 
                    703:      * Stop the transmitter and allow any frame transmit in progress to abort
                    704:      */
                    705:     MacCCReg = ReadMaceRegister( ioBaseEnet, kMacCC );
                    706:     WriteMaceRegister( ioBaseEnet, kMacCC, MacCCReg & ~kMacCCEnXmt );
                    707:     IODelay( TRANSMIT_QUIESCE_uS );
                    708: 
                    709:     /* 
                    710:      * Capture channel status and pause the dma channel.
                    711:      */
                    712:     dmaStatus = IOGetDBDMAChannelStatus( ioBaseEnetTxDMA );
                    713:     IODBDMAPause( ioBaseEnetTxDMA );
                    714: 
                    715:     /*
                    716:      * Read the command pointer and convert it to a byte offset into the
                    717:         * DMA program.
                    718:      */
                    719:     dmaCmdPtr = IOGetDBDMACommandPtr( ioBaseEnetTxDMA );
                    720:     dmaIndex  = (dmaCmdPtr - txDMACommandsPhys);
                    721: 
                    722:     /*
                    723:      * If the channel status is DEAD, the DMA pointer is pointing to the
                    724:         * next command
                    725:      */
                    726:     if ( dmaStatus & kdbdmaDead )
                    727:     {
                    728:       dmaIndex -= sizeof(IODBDMADescriptor);
                    729:     }
                    730:  
                    731:     /*
                    732:      * Convert channel program offset to command index
                    733:      */
                    734:     dmaIndex = dmaIndex / sizeof(enet_txdma_cmd_t);
                    735:     if ( dmaIndex >= txMaxCommand ) dmaIndex = 0;
                    736: 
                    737:     IODBDMAReset( ioBaseEnetTxDMA );
                    738: 
                    739:     /*
                    740:      * Reset the dma channel pointer to the nearest command index
                    741:      */
                    742:     dmaCmdPtr = txDMACommandsPhys + sizeof(enet_txdma_cmd_t) * dmaIndex;
                    743:     IOSetDBDMACommandPtr( ioBaseEnetTxDMA, dmaCmdPtr );
                    744: }
                    745: 
                    746: /*-------------------------------------------------------------------------
                    747:  *
                    748:  *
                    749:  *
                    750:  *-------------------------------------------------------------------------*/
                    751: 
                    752: void MaceEnet::_disableAdapterInterrupts()
                    753: {
                    754:     WriteMaceRegister( ioBaseEnet, kIntMask, 0xFF );
                    755: }
                    756: 
                    757: /*-------------------------------------------------------------------------
                    758:  *
                    759:  * _enableAdapterInterrupts
                    760:  *
                    761:  * It appears to make the Mace chip work properly with the DBDMA channel
                    762:  * we need to leave the transmit interrupt unmasked at the chip. This
                    763:  * is weird, but that's what happens when you try to glue a chip that
                    764:  * wasn't intended to work with a DMA engine on to a DMA. 
                    765:  *
                    766:  *-------------------------------------------------------------------------*/
                    767: 
                    768: void MaceEnet::_enableAdapterInterrupts()
                    769: {
                    770:     u_int8_t           regValue;
                    771: 
                    772:     regValue = ReadMaceRegister( ioBaseEnet, kIntMask );
                    773:     regValue &= ~kIntMaskXmtInt;
                    774:     WriteMaceRegister( ioBaseEnet, kIntMask, regValue );
                    775:     IODelay(500); 
                    776:     ReadMaceRegister( ioBaseEnet, kXmtFS );
                    777:     ReadMaceRegister( ioBaseEnet, kIntReg );
                    778: }
                    779: 
                    780: /*-------------------------------------------------------------------------
                    781:  *
                    782:  *
                    783:  *
                    784:  *-------------------------------------------------------------------------*/
                    785: 
                    786: bool MaceEnet::_transmitPacket(struct mbuf * packet)
                    787: {
                    788:     enet_dma_cmd_t     tmpCommand;
                    789:     u_int32_t          i;
                    790: 
                    791:     /*
                    792:      * Check for room on the transmit ring. There should always be space 
                    793:         * since it is the responsibility of the caller to verify this before 
                    794:         * calling _transmitPacket.
                    795:      *
                    796:      * Get a copy of the DMA transfer commands in a temporary buffer. 
                    797:      * The new DMA command is written into the channel program so that the 
                    798:         * command word for the old Stop command is overwritten last. This prevents 
                    799:         * the DMA engine from executing a partially written channel command.
                    800:      */
                    801:     i = txCommandTail + 1;
                    802:     if ( i >= txMaxCommand ) i = 0;
                    803: 
                    804:     if ( (i == txCommandHead) ||
                    805:                !_updateDescriptorFromMbuf(packet, &tmpCommand, false))
                    806:     {
                    807:                IOLog("Mace: Freeing transmit packet eh?\n\r");
                    808:                if (packet != txDebuggerPkt)
                    809:                        freePacket(packet);
                    810:                return false;
                    811:     }
                    812: 
                    813:     /*
                    814:      * txCommandTail points to the current DMA Stop command for the channel.
                    815:         * We are now creating a new DMA Stop command in the next slot in the 
                    816:         * transmit ring. The previous DMA Stop command will be overwritten with 
                    817:         * the DMA commands to transfer the new mbuf.
                    818:      */
                    819:     txDMACommands[i].desc_seg[0] = dbdmaCmd_Stop;
                    820:     txDMACommands[i].desc_seg[1] = dbdmaCmd_Nop;
                    821: 
                    822:     flush_cache_v( (vm_offset_t)&txDMACommands[i], sizeof(enet_dma_cmd_t) );
                    823: 
                    824:     bcopy( ((u_int32_t *)&tmpCommand)+1,
                    825:            ((u_int32_t *)&txDMACommands[txCommandTail])+1,
                    826:            sizeof(enet_dma_cmd_t)-sizeof(u_int32_t) );
                    827: 
                    828:     flush_cache_v( (vm_offset_t)&txDMACommands[txCommandTail], 
                    829:                sizeof(enet_dma_cmd_t) );
                    830: 
                    831:     txMbuf[txCommandTail] = packet;
                    832:     txDMACommands[txCommandTail].desc_seg[0].operation = 
                    833:                tmpCommand.desc_seg[0].operation;
                    834: 
                    835:     flush_cache_v( (vm_offset_t)&txDMACommands[txCommandTail], 
                    836:                sizeof(enet_dma_cmd_t) );
                    837: 
                    838:     /*
                    839:      * Set the transmit tail to the new stop command.
                    840:      */
                    841:     txCommandTail = i;
                    842:        
                    843:     /*
                    844:      * Tap the DMA channel to wake it up
                    845:      */
                    846:     IODBDMAContinue( ioBaseEnetTxDMA );
                    847: 
                    848:     return true;
                    849: }      
                    850: 
                    851: /*-------------------------------------------------------------------------
                    852:  * _receivePacket
                    853:  * --------------
                    854:  * This routine runs the receiver in polled-mode (yuk!) for the kernel 
                    855:  * debugger.
                    856:  *
                    857:  * The _receivePackets allocate mbufs and pass them up the stack. The kernel
                    858:  * debugger interface passes a buffer into us. To reconcile the two interfaces,
                    859:  * we allow the receive routine to continue to allocate its own buffers and
                    860:  * transfer any received data to the passed-in buffer. This is handled by 
                    861:  * _receivePacket calling _packetToDebugger.
                    862:  *-------------------------------------------------------------------------*/
                    863: 
                    864: void MaceEnet::_receivePacket(void *pkt, unsigned int *pkt_len,
                    865:                unsigned int timeout)
                    866: {
                    867:     ns_time_t          startTime;
                    868:     ns_time_t          currentTime;
                    869:     u_int32_t          elapsedTimeMS;
                    870: 
                    871:     if (!ready || !pkt || !pkt_len)
                    872:       return;
                    873: 
                    874:     *pkt_len = 0;
                    875: 
                    876:     debuggerPkt     = pkt;
                    877:     debuggerPktSize = 0;
                    878: 
                    879:     _IOGetTimestamp(&startTime);
                    880:     do
                    881:     {
                    882:                _receivePackets(true);
                    883:                _IOGetTimestamp(&currentTime);
                    884:                elapsedTimeMS = (currentTime - startTime) / (1000*1000);
                    885:     } 
                    886:     while ( (debuggerPktSize == 0) && (elapsedTimeMS < timeout) );
                    887: 
                    888:     *pkt_len = debuggerPktSize;
                    889: 
                    890:     return;
                    891: }
                    892: 
                    893: /*-------------------------------------------------------------------------
                    894:  * _packetToDebugger
                    895:  * -----------------
                    896:  * This is called by _receivePackets when we are polling for kernel debugger
                    897:  * packets. It copies the mbuf contents to the buffer passed by the debugger.
                    898:  * It also sets the var debuggerPktSize which will break the polling loop.
                    899:  *-------------------------------------------------------------------------*/
                    900: 
                    901: void MaceEnet::_packetToDebugger(struct mbuf * packet, u_int size)
                    902: {
                    903:     debuggerPktSize = size;
                    904:     bcopy( mtod(packet, char *), debuggerPkt, size );
                    905: }
                    906: 
                    907: /*-------------------------------------------------------------------------
                    908:  * _sendPacket
                    909:  * -----------
                    910:  *
                    911:  * This routine runs the transmitter in polled-mode (yuk!) for the
                    912:  * kernel debugger.
                    913:  *
                    914:  *-------------------------------------------------------------------------*/
                    915: 
                    916: void MaceEnet::_sendPacket(void *pkt, unsigned int pkt_len)
                    917: {
                    918:     ns_time_t          startTime;
                    919:     ns_time_t          currentTime;
                    920:     u_int32_t          elapsedTimeMS;
                    921: 
                    922:     if ( !ready || !pkt || (pkt_len > ETHERMAXPACKET))
                    923:                return; 
                    924: 
                    925:     /*
                    926:      * Wait for the transmit ring to empty
                    927:      */
                    928:     _IOGetTimestamp(&startTime); 
                    929:     do
                    930:     {  
                    931:                _transmitInterruptOccurred(true);
                    932:                _IOGetTimestamp(&currentTime);
                    933:                elapsedTimeMS = (currentTime - startTime) / (1000*1000);
                    934:     }
                    935:     while ( (txCommandHead != txCommandTail) &&
                    936:                        (elapsedTimeMS < TX_KDB_TIMEOUT) ); 
                    937:        
                    938:     if ( txCommandHead != txCommandTail )
                    939:     {
                    940:                IOLog( "Mace: Polled tranmit timeout - 1\n\r");
                    941:                return;
                    942:     }
                    943: 
                    944:        txDebuggerPkt->m_next = 0;
                    945:        txDebuggerPkt->m_data = (caddr_t) pkt;
                    946:        txDebuggerPkt->m_pkthdr.len = txDebuggerPkt->m_len = pkt_len;
                    947: 
                    948:     /*
                    949:      * Send the debugger packet. txDebuggerPkt must not be freed by
                    950:         * the transmit routine.
                    951:      */
                    952:        _transmitPacket(txDebuggerPkt);
                    953: 
                    954:     /*
                    955:      * Poll waiting for the transmit ring to empty again
                    956:      */ 
                    957:     do
                    958:     {
                    959:                _transmitInterruptOccurred(true);
                    960:                _IOGetTimestamp(&currentTime);
                    961:                elapsedTimeMS = (currentTime - startTime) / (1000*1000);
                    962:     }
                    963:     while ( (txCommandHead != txCommandTail) &&
                    964:                        (elapsedTimeMS < TX_KDB_TIMEOUT) ); 
                    965: 
                    966:     if ( txCommandHead != txCommandTail )
                    967:     {
                    968:                IOLog("Mace: Polled transmit timeout - 2\n\r");
                    969:     }
                    970: 
                    971:     return;
                    972: }
                    973: 
                    974: /*-------------------------------------------------------------------------
                    975:  *
                    976:  *
                    977:  *
                    978:  *-------------------------------------------------------------------------*/
                    979: 
                    980: bool MaceEnet::_receiveInterruptOccurred()
                    981: {
                    982:        return _receivePackets(false);
                    983: }
                    984: 
                    985: /*-------------------------------------------------------------------------
                    986:  *
                    987:  *
                    988:  *
                    989:  *-------------------------------------------------------------------------*/
                    990: 
                    991: bool MaceEnet::_receivePackets(bool fDebugger)
                    992: {
                    993:     enet_dma_cmd_t      tmpCommand;
                    994:     struct mbuf *              packet;
                    995:     u_int32_t           i,j,last;
                    996:     u_int32_t                  dmaChnlStatus;
                    997:     int                                        receivedFrameSize = 0;
                    998:     u_int32_t           dmaCount[2], dmaResid[2], dmaStatus[2];
                    999:     bool                               reusePkt;
                   1000:     bool                               status;
                   1001:        bool                            useNetif = !fDebugger && netifClient;
                   1002:        bool                packetsQueued = false;
                   1003:     u_int8_t                   *rxFS = NULL;      
                   1004:     u_int32_t                  nextDesc; 
                   1005:        static const u_int32_t          lastResetValue = (u_int32_t)(-1);
                   1006: 
                   1007:     last      = lastResetValue;  
                   1008:     i         = rxCommandHead;
                   1009: 
                   1010:     while ( 1 )
                   1011:     {
                   1012:                reusePkt     = false;
                   1013: 
                   1014:                /* 
                   1015:                 * Purge cache references for the DBDMA entry we are about to look at.
                   1016:                 */
                   1017:                invalidate_cache_v((vm_offset_t)&rxDMACommands[i], 
                   1018:                        sizeof(enet_dma_cmd_t));
                   1019: 
                   1020:                /*
                   1021:                 * Collect the DMA residual counts/status for the two buffer segments.
                   1022:                 */ 
                   1023:                for ( j = 0; j < 2; j++ )
                   1024:                {
                   1025:                        dmaResid[j]   = IOGetCCResult( &rxDMACommands[i].desc_seg[j] );
                   1026:                        dmaStatus[j]  = dmaResid[j] >> 16;
                   1027:                        dmaResid[j]  &= 0x0000ffff;
                   1028:                        dmaCount[j]   = IOGetCCOperation( &rxDMACommands[i].desc_seg[j] ) & 
                   1029:                                kdbdmaReqCountMask;
                   1030:                }
                   1031: 
                   1032: #if 0
                   1033:       IOLog("Ethernet(Mace): Rx NetBuf[%2d] = %08x Resid[0] = %04x Status[0] = %04x Resid[1] = %04x Status[1] = %04x\n\r",
                   1034:                 i, (int)nb_map(rxNetbuf[i]), dmaResid[0], dmaStatus[0], dmaResid[1], dmaStatus[1] );      
                   1035: #endif 
                   1036: 
                   1037:                /* 
                   1038:                 * If the current entry has not been written, then stop at this entry
                   1039:                 */
                   1040:                if (  !((dmaStatus[0] & kdbdmaBt) || (dmaStatus[1] & kdbdmaActive)) )
                   1041:                {
                   1042:                        break;
                   1043:                }
                   1044: 
                   1045:                /*
                   1046:                 * The Mace Ethernet controller appends four bytes to each receive 
                   1047:                 * buffer containing the buffer size and receive frame status.
                   1048:                 * We locate these bytes by using the DMA residual counts.
                   1049:                 */ 
                   1050:                receivedFrameSize = dmaCount[0] - dmaResid[0] + dmaCount[1] - 
                   1051:                        ((dmaStatus[0] & kdbdmaBt) ? dmaCount[1] : dmaResid[1]);
                   1052: 
                   1053:                if ( ( receivedFrameSize >= 4 ) &&
                   1054:                         ( receivedFrameSize <= NETWORK_BUFSIZE ) )
                   1055:                {
                   1056:                        /*
                   1057:                         * Get the receive frame size as reported by the Mace controller
                   1058:                         */
                   1059: 
                   1060:                        rxFS = mtod(rxMbuf[i], u_int8_t *) + receivedFrameSize - 4;
                   1061: 
                   1062:                        receivedFrameSize =  (u_int16_t) rxFS[0] | 
                   1063:                                (rxFS[1] & kRcvFS1RcvCnt) << 8;
                   1064:                }
                   1065: 
                   1066:                /*
                   1067:                 * Reject packets that are runts or that have other mutations.
                   1068:                 */
                   1069:                if ( receivedFrameSize < (ETHERMINPACKET - ETHERCRC) || 
                   1070:              receivedFrameSize > (ETHERMAXPACKET + ETHERCRC) || 
                   1071:              (rxFS[1] & (kRcvFS1OFlo | kRcvFS1Clsn | kRcvFS1Fram | kRcvFS1FCS)) 
                   1072:                         )
                   1073:                {
                   1074:                        if (useNetif) netStats->inputErrors++;
                   1075:                        reusePkt = true;
                   1076:                }      
                   1077:                else if ( useNetif == false )
                   1078:                {
                   1079:                        /*
                   1080:                         * Always reuse packets in debugger mode.
                   1081:                         */
                   1082:                        reusePkt = true;
                   1083:                        if (fDebugger)
                   1084:                                _packetToDebugger(rxMbuf[i], receivedFrameSize);
                   1085:                }
                   1086: 
                   1087:                /*
                   1088:                 * Before we pass this packet up the networking stack. Make sure we
                   1089:                 * can get a replacement. Otherwise, hold on to the current packet and
                   1090:                 * increment the input error count.
                   1091:                 * Thanks Justin!
                   1092:                 */
                   1093: 
                   1094:                packet = 0;
                   1095: 
                   1096:                if ( reusePkt == false )
                   1097:                {
                   1098:                        bool replaced;
                   1099:                
                   1100:                        packet = replaceOrCopyPacket(&rxMbuf[i], receivedFrameSize, 
                   1101:                                          &replaced);
                   1102: 
                   1103:                        reusePkt = true;
                   1104: 
                   1105:                        if (packet && replaced)
                   1106:                        {
                   1107:                                status = _updateDescriptorFromMbuf(rxMbuf[i], 
                   1108:                                        &rxDMACommands[i], true);
                   1109: 
                   1110:                                if (status)
                   1111:                                {
                   1112:                                        reusePkt = false;
                   1113:                                }
                   1114:                                else
                   1115:                                {
                   1116:                                        // Assume descriptor has not been corrupted.
                   1117:                                        freePacket(rxMbuf[i]);  // release new packet.
                   1118:                                        rxMbuf[i] = packet;             // get the old packet back.
                   1119:                                        packet = 0;                             // pass up nothing.
                   1120:                                        IOLog("Mace: _updateDescriptorFromMbuf error\n");
                   1121:                                }
                   1122:                        }
                   1123: 
                   1124:                        if (packet == 0)
                   1125:                                netStats->inputErrors++;
                   1126:                }
                   1127: 
                   1128:                /*
                   1129:                 * If we are reusing the existing mbuf, then refurbish the existing 
                   1130:                 * DMA command \ descriptors by clearing the status/residual count 
                   1131:                 * fields.
                   1132:                 */
                   1133: 
                   1134:                if ( reusePkt == true )
                   1135:                {
                   1136:                        for ( j=0; j < sizeof(enet_dma_cmd_t)/sizeof(IODBDMADescriptor); 
                   1137:                                  j++ )
                   1138:                        {
                   1139:                                IOSetCCResult( &rxDMACommands[i].desc_seg[j], 0 );
                   1140:                        }
                   1141:                        flush_cache_v( (vm_offset_t)&rxDMACommands[i], 
                   1142:                                sizeof(enet_dma_cmd_t) );
                   1143:                }
                   1144: 
                   1145:                /*
                   1146:                 * Keep track of the last receive descriptor processed
                   1147:                 */
                   1148:                last = i;
                   1149: 
                   1150:                /*
                   1151:                 * Implement ring wrap-around
                   1152:                 */
                   1153:                if (++i >= rxMaxCommand) i = 0;
                   1154: 
                   1155:                /*
                   1156:                 * Early exit in debugger mode.
                   1157:                 */
                   1158:                if (fDebugger)
                   1159:                {
                   1160:                        break;
                   1161:                }
                   1162: 
                   1163:                /*
                   1164:                 * Transfer received to network stack.
                   1165:                 */
                   1166:                if (packet)
                   1167:                {
                   1168:                        KERNEL_DEBUG(DBG_MACE_RXCOMPLETE | DBG_FUNC_NONE, (int) packet, 
                   1169:                                (int)receivedFrameSize, 0, 0, 0 );
                   1170: 
                   1171:                        /*
                   1172:                         * The KDB lock must be held before calling this function.
                   1173:                         */
                   1174:                        networkInterface->inputPacket(packet, receivedFrameSize, true);
                   1175:                        netStats->inputPackets++;
                   1176:                        packetsQueued = true;
                   1177:                }
                   1178:     }
                   1179: 
                   1180:     /*
                   1181:      * OK...this is a little messy
                   1182:      *
                   1183:      * We just processed a bunch of DMA receive descriptors. We are going to 
                   1184:         * exchange the current DMA stop command (rxCommandTail) with the last 
                   1185:         * receive descriptor we processed (last). This will make these list of 
                   1186:         * descriptors we just processed available. If we processed no receive 
                   1187:         * descriptors on this call then skip this exchange.
                   1188:      */
                   1189:    
                   1190: #if 0
                   1191:     IOLog("Mace: Prev - Rx Head = %2d Rx Tail = %2d Rx Last = %2d\n\r", 
                   1192:                rxCommandHead, rxCommandTail, last );
                   1193: #endif
                   1194: 
                   1195:     if ( last != lastResetValue )
                   1196:     {
                   1197:                /*
                   1198:                 * Save the contents of the last receive descriptor processed.
                   1199:                 */
                   1200:                packet      = rxMbuf[last];
                   1201:                tmpCommand      = rxDMACommands[last];
                   1202: 
                   1203:                /*
                   1204:                 * Write a DMA stop command into this descriptor slot
                   1205:                 */
                   1206:                rxDMACommands[last].desc_seg[0] = dbdmaCmd_Stop;
                   1207:                rxDMACommands[last].desc_seg[1] = dbdmaCmd_Nop;  
                   1208:                rxMbuf[last]      = 0;
                   1209: 
                   1210:                flush_cache_v( (vm_offset_t)&rxDMACommands[last], 
                   1211:                        sizeof(enet_dma_cmd_t) );
                   1212: 
                   1213:                /*
                   1214:                 * Replace the previous DMA stop command with the last receive 
                   1215:                 * descriptor processed.
                   1216:                 * 
                   1217:                 * The new DMA command is written into the channel program so that the
                   1218:                 * command word for the old Stop command is overwritten last. This 
                   1219:                 * prevents the DMA engine from executing a partially written channel 
                   1220:                 * command.
                   1221:                 * 
                   1222:                 * Note: When relocating the descriptor, we must update its branch 
                   1223:                 * field to reflect its new location.
                   1224:                 */
                   1225:                nextDesc = rxDMACommandsPhys + (int)&rxDMACommands[rxCommandTail+1] - 
                   1226:                        (int)rxDMACommands;
                   1227:                IOSetCCCmdDep( &tmpCommand.desc_seg[0], nextDesc );
                   1228: 
                   1229:                bcopy( (u_int32_t *)&tmpCommand+1,
                   1230:                (u_int32_t *)&rxDMACommands[rxCommandTail]+1,
                   1231:                sizeof(enet_dma_cmd_t)-sizeof(u_int32_t) );
                   1232: 
                   1233:                flush_cache_v( (vm_offset_t)&rxDMACommands[rxCommandTail], 
                   1234:                        sizeof(enet_dma_cmd_t) );
                   1235: 
                   1236:                rxMbuf[rxCommandTail] = packet;
                   1237: 
                   1238:                rxDMACommands[rxCommandTail].desc_seg[0].operation = 
                   1239:                        tmpCommand.desc_seg[0].operation;
                   1240: 
                   1241:                flush_cache_v( (vm_offset_t)&rxDMACommands[rxCommandTail], 
                   1242:                        sizeof(IODBDMADescriptor) );
                   1243: 
                   1244:                /*
                   1245:                 * Update rxCommmandTail to point to the new Stop command. Update 
                   1246:                 * rxCommandHead to point to the next slot in the ring past the Stop 
                   1247:                 * command 
                   1248:                 */
                   1249:                rxCommandTail = last;
                   1250:                rxCommandHead = i;
                   1251:        }
                   1252: 
                   1253:        /*
                   1254:         * The DMA channel has a nasty habit of shutting down when there is a 
                   1255:         * non-recoverable error on receive. We get no interrupt for this since
                   1256:         * the channel shuts down before the  descriptor that causes the host 
                   1257:         * interrupt is executed.
                   1258:      * 
                   1259:      * We check if the channel is DEAD by checking the channel status reg. 
                   1260:         * Also, the watchdog  timer can force receiver interrupt servicing based 
                   1261:         * on detecting that the receive DMA is DEAD.
                   1262:      */
                   1263:     dmaChnlStatus = IOGetDBDMAChannelStatus( ioBaseEnetRxDMA );
                   1264:     if ( dmaChnlStatus & kdbdmaDead )
                   1265:     {
                   1266:                /*
                   1267:                 * Read log error
                   1268:                 */
                   1269:                if (useNetif) netStats->inputErrors++;
                   1270:                IOLog( "Mace: Rx DMA Error - Status = %04x\n", dmaChnlStatus );
                   1271:   
                   1272:                /*
                   1273:                 * Reset and reinitialize chip
                   1274:                 */
                   1275:                _restartChip();         // This must not block in debugger mode.
                   1276:     }   
                   1277:     else
                   1278:     {
                   1279:                /*
                   1280:                 * Tap the DMA to wake it up
                   1281:                 */
                   1282:                IODBDMAContinue( ioBaseEnetRxDMA );
                   1283:     }
                   1284: 
                   1285: #if 0
                   1286:     IOLog( "Mace: New  - Rx Head = %2d Rx Tail = %2d\n\r",
                   1287:                rxCommandHead, rxCommandTail );
                   1288: #endif
                   1289: 
                   1290:     return packetsQueued;
                   1291: }
                   1292:  
                   1293: /*-------------------------------------------------------------------------
                   1294:  *
                   1295:  *
                   1296:  *
                   1297:  *-------------------------------------------------------------------------*/
                   1298: 
                   1299: bool MaceEnet::_transmitInterruptOccurred(bool fDebugger = false)
                   1300: {
                   1301:     u_int32_t                  dmaStatus;
                   1302:     u_int32_t           xmtFS;
                   1303:        bool                            fServiced = false;
                   1304:        bool                            useNetif = !fDebugger && netifClient;
                   1305: 
                   1306:        // Set the debugTxPoll flag to indicate the debugger was active
                   1307:        // and some cleanup may be needed when the driver returns to
                   1308:        // normal operation.
                   1309:        //
                   1310:        if (fDebugger)
                   1311:                debugTxPoll = true;
                   1312: 
                   1313:     while ( 1 )
                   1314:     {
                   1315:                /* 
                   1316:                 * Purge cache references for the DBDMA entry we are about to look at.
                   1317:                 */
                   1318:                invalidate_cache_v((vm_offset_t)&txDMACommands[txCommandHead], 
                   1319:                        sizeof(enet_txdma_cmd_t));
                   1320: 
                   1321:                /*
                   1322:                 * Check the status of the last descriptor in this entry to see if
                   1323:                 * the DMA engine completed this entry.
                   1324:                 */
                   1325:                dmaStatus = IOGetCCResult(
                   1326:                        &txDMACommands[txCommandHead].desc_seg[3] ) >> 16;
                   1327: 
                   1328:                if ( !(dmaStatus & kdbdmaActive) )
                   1329:                {
                   1330:                        break;
                   1331:                }
                   1332: 
                   1333:                fServiced = true;
                   1334: 
                   1335:                /* 
                   1336:                 * Reset the status word for the entry we are about to process
                   1337:                 */     
                   1338:                IOSetCCResult( &txDMACommands[txCommandHead].desc_seg[3], 0 );
                   1339: 
                   1340:                flush_cache_v( (vm_offset_t) &txDMACommands[txCommandHead].desc_seg[3], 
                   1341:                        sizeof(IODBDMADescriptor) );
                   1342: 
                   1343:                /*
                   1344:                 * This DMA descriptor read the transmit frame status. See what it has
                   1345:                 * to tell us.
                   1346:                 */
                   1347:                xmtFS = IOGetCCCmdDep( &txDMACommands[txCommandHead].desc_seg[2] );
                   1348:                if ( useNetif && (xmtFS & kXmtFSXmtSV) )
                   1349:                {
                   1350:                        if (xmtFS & (kXmtFSUFlo | kXmtFSLCol | kXmtFSRtry | kXmtFSLCar) )
                   1351:                        {
                   1352:                                netStats->outputErrors++;
                   1353:                        }
                   1354:                        else
                   1355:                        {
                   1356:                                netStats->outputPackets++;
                   1357:                        }
                   1358:        
                   1359:                        if (xmtFS & (kXmtFSOne | kXmtFSMore) )
                   1360:                        {
                   1361:                                netStats->collisions++;
                   1362:                        }
                   1363:                }  
                   1364: 
                   1365:                /*
                   1366:                 * Free the mbuf we just transmitted.
                   1367:                 */
                   1368:                KERNEL_DEBUG(DBG_MACE_TXCOMPLETE | DBG_FUNC_NONE,
                   1369:                        (int) txMbuf[txCommandHead],
                   1370:                        (int) txMbuf[txCommandHead]->m_pkthdr.len, 0, 0, 0 );
                   1371: 
                   1372:                if (txMbuf[txCommandHead] != txDebuggerPkt)
                   1373:                {
                   1374:                        if ( fDebugger )
                   1375:                        {
                   1376:                                //
                   1377:                                // While in debugger mode, do not touch the mbuf pool.
                   1378:                                // Queue any used mbufs to a local queue. This queue
                   1379:                                // will get flushed after we exit from debugger mode.
                   1380:                                //
                   1381:                                // During continuous debugger transmission and
                   1382:                                // interrupt polling, we expect only the txDebuggerPkt
                   1383:                                // to show up on the transmit mbuf ring.
                   1384:                                //
                   1385:                                debugQueue->enqueue( txMbuf[txCommandHead] );
                   1386:                        }
                   1387:                        else
                   1388:                        {
                   1389:                                freePacket( txMbuf[txCommandHead] );
                   1390:                        }
                   1391:                }
                   1392: 
                   1393:                txMbuf[txCommandHead] = 0;
                   1394: 
                   1395:                if ( ++txCommandHead >= txMaxCommand ) txCommandHead = 0;
                   1396:        }
                   1397: 
                   1398:     /*
                   1399:      * The DMA channel has a nasty habit of shutting down when there is 
                   1400:         * non-recoverable error on transmit. We get no interrupt for this since 
                   1401:         * the channel shuts down before the descriptor that causes the host 
                   1402:         * interrupt is executed.
                   1403:      * 
                   1404:      * We check if the channel is DEAD by checking the channel status reg. 
                   1405:         * Also, the watchdog  timer can force a transmitter reset if it sees no 
                   1406:         * interrupt activity for to consecutive timeout intervals.
                   1407:      */
                   1408:  
                   1409:     dmaStatus = IOGetDBDMAChannelStatus( ioBaseEnetTxDMA );
                   1410:     if ( (dmaStatus & kdbdmaDead) || (txWDForceReset == true) )
                   1411:     {
                   1412:                /*
                   1413:                 * Read the transmit frame status and log error
                   1414:                 */
                   1415:                xmtFS = ReadMaceRegister( ioBaseEnet, kXmtFS );
                   1416:                if (useNetif) netStats->outputErrors++;
                   1417:                IOLog( "Mace: Tx DMA Error - Status = %04x FS = %02x\n\r",
                   1418:                        dmaStatus, xmtFS);
                   1419:   
                   1420:                /*
                   1421:                 * Reset and reinitialize chip
                   1422:                 */
                   1423:                _restartChip();
                   1424:   
                   1425:                txWDForceReset = false;
                   1426:                fServiced = true;
                   1427:     }
                   1428: 
                   1429:     return fServiced;
                   1430: }
                   1431: 
                   1432: /*-------------------------------------------------------------------------
                   1433:  *
                   1434:  *
                   1435:  *
                   1436:  *-------------------------------------------------------------------------*/
                   1437: 
                   1438: /*
                   1439:  * Breaks up an ethernet data buffer into two physical chunks. We know that
                   1440:  * the buffer can't straddle more than two pages. If the content of paddr2 is
                   1441:  * zero this means that all of the buffer lies in one physical page. Note
                   1442:  * that we use the fact that tx and rx descriptors have the same size and
                   1443:  * same layout of relevent fields (data address and count). 
                   1444:  */
                   1445: bool
                   1446: MaceEnet::_updateDescriptorFromMbuf(struct mbuf * m,  enet_dma_cmd_t *desc,
                   1447:                bool isReceive)
                   1448: {
                   1449:     u_int32_t          nextDesc = 0; 
                   1450:        int                     segments;
                   1451:        struct IOPhysicalSegment segVector[2];
                   1452:        
                   1453:        /*
                   1454:         * Although coalescing is always enabled, it cannot occur
                   1455:         * while the driver is in debugger mode.
                   1456:         */
                   1457:        segments = mbufCursor->getPhysicalSegmentsWithCoalesce(m, segVector);
                   1458:        
                   1459:        if ((!segments) || (segments > 2)) {
                   1460:                IOLog("Mace: _updateDescriptorFromMbuf error, %d segments\n", 
                   1461:                        segments);
                   1462:                return false;
                   1463:        }
                   1464: 
                   1465:     if ( segments == 1 )
                   1466:     {
                   1467:                IOMakeDBDMADescriptor( (&desc->desc_seg[0]),
                   1468:                                                        ((isReceive) ? kdbdmaInputLast : kdbdmaOutputLast), 
                   1469:                                                        (kdbdmaKeyStream0),
                   1470:                                                        (kdbdmaIntNever),
                   1471:                                                        (kdbdmaBranchNever),
                   1472:                                                        ((isReceive) ? kdbdmaWaitNever :
                   1473:                                                                kdbdmaWaitIfFalse),
                   1474:                                                        (segVector[0].length),
                   1475:                                                        (segVector[0].location)  );
                   1476:   
                   1477:                desc->desc_seg[1] = (isReceive) ? dbdmaCmd_NopWInt : dbdmaCmd_Nop;
                   1478:        }
                   1479:        else
                   1480:        {
                   1481:                if ( isReceive ) 
                   1482:                {
                   1483:                        nextDesc = rxDMACommandsPhys + (int)desc - (int)rxDMACommands + 
                   1484:                                sizeof(enet_dma_cmd_t);
                   1485:                }
                   1486: 
                   1487:                IOMakeDBDMADescriptorDep( (&desc->desc_seg[0]),
                   1488:                                                        ((isReceive) ? kdbdmaInputMore : kdbdmaOutputMore), 
                   1489:                                                        (kdbdmaKeyStream0),
                   1490:                                                        ((isReceive) ? kdbdmaIntIfTrue : kdbdmaIntNever),
                   1491:                                                        ((isReceive) ? kdbdmaBranchIfTrue : 
                   1492:                                                                kdbdmaBranchNever),
                   1493:                                                        (kdbdmaWaitNever),
                   1494:                                                        (segVector[0].length),
                   1495:                                                        (segVector[0].location),  
                   1496:                                                        nextDesc   ); 
                   1497: 
                   1498:       IOMakeDBDMADescriptor( (&desc->desc_seg[1]),
                   1499:                                                        ((isReceive) ? kdbdmaInputLast : kdbdmaOutputLast), 
                   1500:                                                        (kdbdmaKeyStream0),
                   1501:                                                        ((isReceive) ? kdbdmaIntAlways : kdbdmaIntNever),
                   1502:                                                        (kdbdmaBranchNever),
                   1503:                                                        ((isReceive) ? kdbdmaWaitNever : 
                   1504:                                                                kdbdmaWaitIfFalse),
                   1505:                                                        (segVector[1].length),
                   1506:                                                        (segVector[1].location)  );
                   1507:     }
                   1508: 
                   1509:     flush_cache_v( (vm_offset_t)desc, sizeof(enet_dma_cmd_t) );
                   1510: 
                   1511:     return true;
                   1512: }
                   1513: 
                   1514:  
                   1515: #ifdef DEBUG
                   1516: /*
                   1517:  * Useful for testing. 
                   1518:  */
                   1519: 
                   1520: void MaceEnet::_dumpDesc(void * addr, u_int32_t size)
                   1521: {
                   1522:     u_int32_t          i;
                   1523:     unsigned long      *p;
                   1524:     vm_offset_t                paddr;
                   1525: 
                   1526:     _IOPhysicalFromVirtual( (vm_offset_t) addr, (vm_offset_t *)&paddr );
                   1527: 
                   1528:        p = (unsigned long *)addr;
                   1529: 
                   1530:        for ( i=0; i < size/sizeof(IODBDMADescriptor); i++, p+=4, 
                   1531:                paddr+=sizeof(IODBDMADescriptor) )
                   1532:        {    
                   1533:                IOLog("Ethernet(Mace): %08x(v) %08x(p):  %08x %08x %08x %08x\n", 
                   1534:               (int)p, 
                   1535:               (int)paddr,
                   1536:               (int)OSReadSwapInt32(p, 0),   (int)OSReadSwapInt32(p, 4),
                   1537:               (int)OSReadSwapInt32(p, 8),   (int)OSReadSwapInt32(p, 12) );
                   1538:     }
                   1539:        IOLog("\n");
                   1540: }
                   1541: 
                   1542: void MaceEnet::_dumpRegisters()
                   1543: {
                   1544:     u_int8_t   dataValue;
                   1545: 
                   1546:     IOLog("\nEthernet(Mace): IO Address = %08x", (int)ioBaseEnet );
                   1547:  
                   1548:     dataValue = ReadMaceRegister(ioBaseEnet, kXmtFC);
                   1549:     IOLog("\nEthernet(Mace): Read Register %04x Transmit Frame Control     = %02x", kXmtFC, dataValue );
                   1550: 
                   1551:     dataValue = ReadMaceRegister(ioBaseEnet, kXmtFS);
                   1552:     IOLog("\nEthernet(Mace): Read Register %04x Transmit Frame Status      = %02x", kXmtFS, dataValue );
                   1553: 
                   1554:     dataValue = ReadMaceRegister(ioBaseEnet, kXmtRC);
                   1555:     IOLog("\nEthernet(Mace): Read Register %04x Transmit Retry Count       = %02x", kXmtRC, dataValue );
                   1556: 
                   1557:     dataValue = ReadMaceRegister(ioBaseEnet, kRcvFC);
                   1558:     IOLog("\nEthernet(Mace): Read Register %04x Receive Frame Control      = %02x", kRcvFC, dataValue );
                   1559: 
                   1560:     dataValue = ReadMaceRegister(ioBaseEnet, kRcvFS0);
                   1561:     IOLog("\nEthernet(Mace): Read Register %04x Receive Frame Status 0     = %02x", kRcvFS0, dataValue );
                   1562:     dataValue = ReadMaceRegister(ioBaseEnet, kRcvFS1);
                   1563:     IOLog("\nEthernet(Mace): Read Register %04x Receive Frame Status 1     = %02x", kRcvFS1, dataValue );
                   1564:     dataValue = ReadMaceRegister(ioBaseEnet, kRcvFS2);
                   1565:     IOLog("\nEthernet(Mace): Read Register %04x Receive Frame Status 2     = %02x", kRcvFS2, dataValue );
                   1566:     dataValue = ReadMaceRegister(ioBaseEnet, kRcvFS3);
                   1567:     IOLog("\nEthernet(Mace): Read Register %04x Receive Frame Status 3     = %02x", kRcvFS3, dataValue );
                   1568: 
                   1569:     dataValue = ReadMaceRegister(ioBaseEnet, kFifoFC);
                   1570:     IOLog("\nEthernet(Mace): Read Register %04x FIFO Frame Count           = %02x", kFifoFC, dataValue );
                   1571: 
                   1572:     dataValue = ReadMaceRegister(ioBaseEnet, kIntReg);
                   1573:     IOLog("\nEthernet(Mace): Read Register %04x Interrupt Register         = %02x", kIntReg, dataValue );
                   1574: 
                   1575:     dataValue = ReadMaceRegister(ioBaseEnet, kIntMask);
                   1576:     IOLog("\nEthernet(Mace): Read Register %04x Interrupt Mask Register    = %02x", kIntMask, dataValue );
                   1577: 
                   1578:     dataValue = ReadMaceRegister(ioBaseEnet, kPollReg);
                   1579:     IOLog("\nEthernet(Mace): Read Register %04x Poll Register              = %02x", kPollReg, dataValue );
                   1580: 
                   1581:     dataValue = ReadMaceRegister(ioBaseEnet, kBIUCC);
                   1582:     IOLog("\nEthernet(Mace): Read Register %04x BUI Configuration Control  = %02x", kBIUCC, dataValue );
                   1583: 
                   1584:     dataValue = ReadMaceRegister(ioBaseEnet, kFifoCC);
                   1585:     IOLog("\nEthernet(Mace): Read Register %04x FIFO Configuration Control = %02x", kFifoCC, dataValue );
                   1586: 
                   1587:     dataValue = ReadMaceRegister(ioBaseEnet, kMacCC);
                   1588:     IOLog("\nEthernet(Mace): Read Register %04x MAC Configuration Control  = %02x", kMacCC, dataValue );
                   1589: 
                   1590:     dataValue = ReadMaceRegister(ioBaseEnet, kPLSCC);
                   1591:     IOLog("\nEthernet(Mace): Read Register %04x PLS Configuration Contro   = %02x", kPLSCC, dataValue );
                   1592: 
                   1593:     dataValue = ReadMaceRegister(ioBaseEnet, kPHYCC);
                   1594:     IOLog("\nEthernet(Mace): Read Register %04x PHY Configuration Control  = %02x", kPHYCC, dataValue );
                   1595: 
                   1596:     dataValue = ReadMaceRegister(ioBaseEnet, kMaceChipId0);
                   1597:     IOLog("\nEthernet(Mace): Read Register %04x MACE ChipID Register 7:0   = %02x", kMaceChipId0, dataValue );
                   1598: 
                   1599:     dataValue = ReadMaceRegister(ioBaseEnet, kMaceChipId1);
                   1600:     IOLog("\nEthernet(Mace): Read Register %04x MACE ChipID Register 15:8  = %02x", kMaceChipId1, dataValue );
                   1601: 
                   1602:     dataValue = ReadMaceRegister(ioBaseEnet, kMPC);
                   1603:     IOLog("\nEthernet(Mace): Read Register %04x Missed Packet Count        = %02x", kMPC, dataValue );
                   1604: 
                   1605:     dataValue = ReadMaceRegister(ioBaseEnet, kUTR);
                   1606:     IOLog("\nEthernet(Mace): Read Register %04x User Test Register         = %02x", kUTR, dataValue );
                   1607:     IOLog("\nEthernet(Mace): -------------------------------------------------------\n" );
                   1608: }
                   1609: #endif DEBUG
                   1610: 
                   1611: 
                   1612: /*-------------------------------------------------------------------------
                   1613:  *
                   1614:  *
                   1615:  *
                   1616:  *-------------------------------------------------------------------------*/
                   1617: 
                   1618: IOReturn MaceEnet::getHardwareAddress(enet_addr_t *ea)
                   1619: {
                   1620:     unsigned char data;
                   1621: 
                   1622:     for (UInt i = 0; i < sizeof(*ea); i++)     
                   1623:     {
                   1624:                data = ((unsigned char *)ioBaseEnetROM)[i << 4];
                   1625:                ea->ea_byte[i]   = reverseBitOrder(data);
                   1626:     }
                   1627:        
                   1628:        return kIOReturnSuccess;
                   1629: }
                   1630: 
                   1631: /*-------------------------------------------------------------------------
                   1632:  *
                   1633:  *
                   1634:  *
                   1635:  *-------------------------------------------------------------------------*/
                   1636: 
                   1637: #define ENET_CRCPOLY 0x04c11db7
                   1638: 
                   1639: /* Real fast bit-reversal algorithm, 6-bit values */
                   1640: static int reverse6[] = 
                   1641: {      0x0,0x20,0x10,0x30,0x8,0x28,0x18,0x38,
                   1642:        0x4,0x24,0x14,0x34,0xc,0x2c,0x1c,0x3c,
                   1643:        0x2,0x22,0x12,0x32,0xa,0x2a,0x1a,0x3a,
                   1644:        0x6,0x26,0x16,0x36,0xe,0x2e,0x1e,0x3e,
                   1645:        0x1,0x21,0x11,0x31,0x9,0x29,0x19,0x39,
                   1646:        0x5,0x25,0x15,0x35,0xd,0x2d,0x1d,0x3d,
                   1647:        0x3,0x23,0x13,0x33,0xb,0x2b,0x1b,0x3b,
                   1648:        0x7,0x27,0x17,0x37,0xf,0x2f,0x1f,0x3f
                   1649: };
                   1650: 
                   1651: static u_int32_t crc416(unsigned int current, unsigned short nxtval )
                   1652: {
                   1653:        register unsigned int counter;
                   1654:        register int highCRCBitSet, lowDataBitSet;
                   1655: 
                   1656:        /* Swap bytes */
                   1657:        nxtval = ((nxtval & 0x00FF) << 8) | (nxtval >> 8);
                   1658: 
                   1659:        /* Compute bit-by-bit */
                   1660:        for (counter = 0; counter != 16; ++counter)
                   1661:        {       /* is high CRC bit set? */
                   1662:                if ((current & 0x80000000) == 0)        
                   1663:                        highCRCBitSet = 0;
                   1664:                else
                   1665:                        highCRCBitSet = 1;
                   1666:                
                   1667:                current = current << 1;
                   1668:        
                   1669:                if ((nxtval & 0x0001) == 0)
                   1670:                        lowDataBitSet = 0;
                   1671:                else
                   1672:                        lowDataBitSet = 1;
                   1673: 
                   1674:                nxtval = nxtval >> 1;
                   1675:        
                   1676:                /* do the XOR */
                   1677:                if (highCRCBitSet ^ lowDataBitSet)
                   1678:                        current = current ^ ENET_CRCPOLY;
                   1679:        }
                   1680:        return current;
                   1681: }
                   1682: 
                   1683: /*-------------------------------------------------------------------------
                   1684:  *
                   1685:  *
                   1686:  *
                   1687:  *-------------------------------------------------------------------------*/
                   1688: 
                   1689: static u_int32_t mace_crc(unsigned short *address)
                   1690: {      
                   1691:     register u_int32_t newcrc;
                   1692: 
                   1693:        newcrc = crc416(0xffffffff, *address);  /* address bits 47 - 32 */
                   1694:     newcrc = crc416(newcrc, address[1]);       /* address bits 31 - 16 */
                   1695:     newcrc = crc416(newcrc, address[2]);       /* address bits 15 - 0  */
                   1696: 
                   1697:     return (newcrc);
                   1698: }
                   1699: 
                   1700: /*
                   1701:  * Clear the hash table filter.  
                   1702:  *  
                   1703:  */
                   1704: void MaceEnet::_resetHashTableMask()
                   1705: {
                   1706:        bzero(hashTableUseCount, sizeof(hashTableUseCount));
                   1707:        bzero(hashTableMask, sizeof(hashTableMask));
                   1708: }
                   1709: 
                   1710: /*
                   1711:  * Add requested mcast addr to Mace's hash table filter.  
                   1712:  *  
                   1713:  */
                   1714: void MaceEnet::_addToHashTableMask(u_int8_t *addr)
                   1715: {      
                   1716:     u_int32_t   crc;
                   1717:     u_int8_t    mask;
                   1718: 
                   1719:     crc = mace_crc((unsigned short *)addr)&0x3f; /* Big-endian alert! */
                   1720:     crc = reverse6[crc];       /* Hyperfast bit-reversing algorithm */
                   1721:     if (hashTableUseCount[crc]++)      
                   1722:                return;                 /* This bit is already set */
                   1723:     mask = crc % 8;
                   1724:     mask = (unsigned char) 1 << mask;
                   1725:     hashTableMask[crc/8] |= mask;
                   1726: }
                   1727: 
                   1728: /*-------------------------------------------------------------------------
                   1729:  *
                   1730:  *
                   1731:  *
                   1732:  *-------------------------------------------------------------------------*/
                   1733: 
                   1734: void MaceEnet::_removeFromHashTableMask(u_int8_t *addr)
                   1735: {      
                   1736:     unsigned int crc;
                   1737:     unsigned char mask;
                   1738: 
                   1739:     /* Now, delete the address from the filter copy, as indicated */
                   1740:     crc = mace_crc((unsigned short *)addr)&0x3f; /* Big-endian alert! */
                   1741:     crc = reverse6[crc];       /* Hyperfast bit-reversing algorithm */
                   1742:        if (hashTableUseCount[crc] == 0)
                   1743:                return;                 /* That bit wasn't in use! */
                   1744: 
                   1745:     if (--hashTableUseCount[crc])
                   1746:                return;                 /* That bit is still in use */
                   1747: 
                   1748:     mask = crc % 8;
                   1749:     mask = ((unsigned char)1 << mask) ^ 0xffff; /* To turn off bit */
                   1750:     hashTableMask[crc/8] &= mask;
                   1751: }
                   1752: 
                   1753: /*
                   1754:  * Sync the adapter with the software copy of the multicast mask
                   1755:  *  (logical address filter).
                   1756:  */
                   1757: void MaceEnet::_updateHashTableMask()
                   1758: {
                   1759:        u_int8_t                status;
                   1760:        u_int32_t               i;
                   1761:        u_int8_t                *p;
                   1762:        u_int8_t                MacCCReg;
                   1763:        
                   1764:        // Stop the receiver before changing the filter.
                   1765:        //
                   1766:        MacCCReg = ReadMaceRegister( ioBaseEnet, kMacCC );
                   1767:     WriteMaceRegister( ioBaseEnet, kMacCC, MacCCReg & ~kMacCCEnRcv );
                   1768:        IODelay( RECEIVE_QUIESCE_uS );
                   1769:        
                   1770:        if ( chipId != kMaceRevisionA2 )
                   1771:        { 
                   1772:                WriteMaceRegister( ioBaseEnet, kIAC, kIACAddrChg | kIACLogAddr );
                   1773:                do
                   1774:                {
                   1775:                        status = ReadMaceRegister( ioBaseEnet, kIAC );
                   1776:                }
                   1777:                while( status & kIACAddrChg );
                   1778:        }
                   1779:        else
                   1780:     {
                   1781:                WriteMaceRegister( ioBaseEnet, kIAC, kIACLogAddr );
                   1782:     }
                   1783: 
                   1784:     p = (u_int8_t *) hashTableMask;
                   1785:     for (i = 0; i < 8; i++, p++ )
                   1786:     {
                   1787:                WriteMaceRegister( ioBaseEnet, kLADRF, *p );
                   1788:     }
                   1789:        
                   1790:        // Restore the engine's state.
                   1791:        //
                   1792:        WriteMaceRegister( ioBaseEnet, kMacCC, MacCCReg );
                   1793: }

unix.superglobalmegacorp.com

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