Annotation of kernel/bsd/dev/ppc/drvMaceEnet/MaceEnetPrivate.m, revision 1.1.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.