Annotation of kernel/bsd/dev/ppc/drvMaceEnet/MaceEnetPrivate.m, revision 1.1

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

unix.superglobalmegacorp.com

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