Annotation of XNU/iokit/Drivers/network/drvPPCUniN/UniNEnetPrivate.cpp, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * The contents of this file constitute Original Code as defined in and
                      7:  * are subject to the Apple Public Source License Version 1.1 (the
                      8:  * "License").  You may not use this file except in compliance with the
                      9:  * License.  Please obtain a copy of the License at
                     10:  * http://www.apple.com/publicsource and read it before using this file.
                     11:  * 
                     12:  * This Original Code and all software distributed under the License are
                     13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     17:  * License for the specific language governing rights and limitations
                     18:  * under the License.
                     19:  * 
                     20:  * @APPLE_LICENSE_HEADER_END@
                     21:  */
                     22: /*
                     23:  * Copyright (c) 1998-1999 Apple Computer
                     24:  *
                     25:  * Implementation for hardware dependent (relatively) code 
                     26:  * for the Sun GEM Ethernet controller. 
                     27:  *
                     28:  * HISTORY
                     29:  *
                     30:  * 10-Sept-97        
                     31:  *  Created.
                     32:  *
                     33:  */
                     34: #include "UniNEnetPrivate.h"
                     35: 
                     36: extern void             *kernel_pmap;
                     37: 
                     38: /*
                     39:  * Private functions
                     40:  */
                     41: bool UniNEnet::allocateMemory()
                     42: {
                     43:     UInt32              rxRingSize, txRingSize;
                     44:     UInt32              i, n;
                     45:     UInt8               *virtAddr;
                     46:     UInt32              physBase;
                     47:     UInt32              physAddr;
                     48:     TxQueueElement      *txElement;
                     49:  
                     50:     /* 
                     51:      * Calculate total space for DMA channel commands
                     52:      */
                     53:     txRingSize = (TX_RING_LENGTH * sizeof(enet_txdma_cmd_t) + 2048 - 1) & ~(2048-1);
                     54:     rxRingSize = (RX_RING_LENGTH * sizeof(enet_dma_cmd_t)   + 2048 - 1) & ~(2048-1);
                     55:      
                     56:     dmaCommandsSize = round_page( txRingSize + rxRingSize ); 
                     57:     /*
                     58:      * Allocate required memory
                     59:      */
                     60:     if ( !dmaCommands )
                     61:     {
                     62:       dmaCommands = (UInt8 *)IOMallocContiguous( dmaCommandsSize, PAGE_SIZE, 0 );
                     63: 
                     64:       if ( dmaCommands == 0  )
                     65:       {
                     66:           IOLog( "Ethernet(UniN): Cant allocate channel dma commands\n\r" );
                     67:           return false;
                     68:       }
                     69:     }
                     70: 
                     71:     /*
                     72:      * If we needed more than one page, then make sure we received contiguous memory.
                     73:      */
                     74:     n = (dmaCommandsSize - PAGE_SIZE) / PAGE_SIZE;
                     75:     physBase = pmap_extract(kernel_pmap, (vm_address_t) dmaCommands);
                     76: 
                     77:     virtAddr = (UInt8 *) dmaCommands;
                     78:     for( i=0; i < n; i++, virtAddr += PAGE_SIZE )
                     79:     {
                     80:         physAddr =  pmap_extract(kernel_pmap, (vm_address_t) virtAddr);      
                     81:         if (physAddr != (physBase + i * PAGE_SIZE) )
                     82:         {
                     83:             IOLog( "Ethernet(UniN): Cant allocate contiguous memory for dma commands\n\r" );
                     84:             return false;
                     85:         }
                     86:     }           
                     87: 
                     88:     /* 
                     89:      * Setup the receive ring pointers
                     90:      */
                     91:     rxDMACommands = (enet_dma_cmd_t *)dmaCommands;
                     92:     rxMaxCommand  = RX_RING_LENGTH;
                     93: 
                     94:     /*
                     95:      * Setup the transmit ring pointers
                     96:      */
                     97:     txDMACommands = (enet_txdma_cmd_t *)(dmaCommands + rxRingSize);
                     98:     txMaxCommand  = TX_RING_LENGTH;
                     99:     
                    100:     
                    101:     queue_init( &txActiveQueue );
                    102:     queue_init( &txFreeQueue );
                    103:     
                    104:     for ( i=0; i < TX_MAX_MBUFS; i++ )
                    105:     {
                    106:         txElement = (TxQueueElement *)IOMalloc( sizeof(TxQueueElement) );        
                    107:         if ( txElement == 0 )
                    108:         {
                    109:             return false;
                    110:         }
                    111:             
                    112:         bzero( txElement, sizeof(TxQueueElement) );
                    113:          
                    114:         releaseTxElement( txElement );
                    115:     }     
                    116:  
                    117:     return true;
                    118: }
                    119: 
                    120: /*-------------------------------------------------------------------------
                    121:  *
                    122:  * Setup the Transmit Ring
                    123:  * -----------------------
                    124:  * Each transmit ring entry consists of two words to transmit data from buffer
                    125:  * segments (possibly) spanning a page boundary. This is followed by two DMA commands 
                    126:  * which read transmit frame status and interrupt status from the UniN chip. The last
                    127:  * DMA command in each transmit ring entry generates a host interrupt.
                    128:  * The last entry in the ring is followed by a DMA branch to the first
                    129:  * entry.
                    130:  *-------------------------------------------------------------------------*/
                    131: 
                    132: bool UniNEnet::initTxRing()
                    133: {
                    134:     TxQueueElement      *txElement;
                    135:     UInt32             i;
                    136: 
                    137:     /*
                    138:      * Clear the transmit DMA command memory
                    139:      */  
                    140:     bzero( (void *)txDMACommands, sizeof(enet_txdma_cmd_t) * txMaxCommand);
                    141:     txCommandHead = 0;
                    142:     txCommandTail = 0;
                    143:     
                    144:     
                    145:     txDMACommandsPhys = pmap_extract(kernel_pmap, (vm_address_t) txDMACommands);
                    146: 
                    147:     if ( txDMACommandsPhys == 0 )
                    148:     {
                    149:         IOLog( "Ethernet(UniN): Bad dma command buf - %08x\n\r", (int)txDMACommands );
                    150:     }
                    151:  
                    152:     for ( i=0; i < TX_RING_LENGTH; i++ )
                    153:     {  
                    154:         txElement = txElementPtrs[i];
                    155: 
                    156:         if ( (txElement != 0) && (txElement->list != &txFreeQueue) )
                    157:         {
                    158:             if ( txElement->mbuf != 0 )
                    159:             {
                    160:                 freePacket( txElement->mbuf );
                    161:             }
                    162:             bzero( txElement, sizeof(TxQueueElement) );
                    163:             releaseTxElement( txElement );
                    164:         }
                    165: 
                    166:         txElementPtrs[i] = 0;
                    167:     }
                    168: 
                    169:     txCommandsAvail = txMaxCommand - 1; 
                    170: 
                    171:     return true;
                    172: }
                    173: 
                    174: /*-------------------------------------------------------------------------
                    175:  *
                    176:  * Setup the Receive ring
                    177:  * ----------------------
                    178:  * Each receive ring entry consists of two DMA commands to receive data
                    179:  * into a network buffer (possibly) spanning a page boundary. The second
                    180:  * DMA command in each entry generates a host interrupt.
                    181:  * The last entry in the ring is followed by a DMA branch to the first
                    182:  * entry. 
                    183:  *
                    184:  *-------------------------------------------------------------------------*/
                    185: 
                    186: bool UniNEnet::initRxRing()
                    187: {
                    188:     UInt32      i;
                    189:     bool        status;
                    190:     
                    191:     /*
                    192:      * Clear the receive DMA command memory
                    193:      */
                    194:     bzero( (void *)rxDMACommands, sizeof(enet_dma_cmd_t) * rxMaxCommand);
                    195: 
                    196:     rxDMACommandsPhys = pmap_extract(kernel_pmap, (vm_address_t) rxDMACommands);
                    197:     if ( rxDMACommandsPhys == 0 )
                    198:     {
                    199:         IOLog( "Ethernet(UniN): Bad dma command buf - %08x\n\r",  (int)rxDMACommands );
                    200:         return false;
                    201:     }
                    202: 
                    203:     /*
                    204:      * Allocate a receive buffer for each entry in the Receive ring
                    205:      */
                    206:     for (i = 0; i < rxMaxCommand; i++) 
                    207:     {
                    208:         if (rxMbuf[i] == NULL)    
                    209:         {
                    210:             rxMbuf[i] = allocatePacket(NETWORK_BUFSIZE);
                    211:             if (rxMbuf[i] == NULL)    
                    212:         {
                    213:                 IOLog("Ethernet(UniN): allocateMbuf returned NULL in _initRxRing\n\r");
                    214:                 return false;
                    215:         }
                    216:       }
                    217:       
                    218:       /* 
                    219:        * Set the DMA commands for the ring entry to transfer data to the Mbuf.
                    220:        */
                    221:         status = updateDescriptorFromMbuf(rxMbuf[i], &rxDMACommands[i], true);
                    222:         if (status == false)
                    223:         {    
                    224:             IOLog("Ethernet(UniN): cant map mbuf to physical memory in initRxRing\n\r");
                    225:             return false;
                    226:         }
                    227:     }
                    228: 
                    229:     /*
                    230:      * Set the receive queue head to point to the first entry in the ring. Set the
                    231:      * receive queue tail to point to a DMA Stop command after the last ring entry
                    232:      */    
                    233:     i-=4;
                    234:     rxCommandHead = 0;
                    235:     rxCommandTail = i;
                    236: 
                    237:     return true;
                    238: }
                    239: 
                    240: /*-------------------------------------------------------------------------
                    241:  *
                    242:  *
                    243:  *
                    244:  *-------------------------------------------------------------------------*/
                    245: 
                    246: void UniNEnet::startChip()
                    247: {
                    248:     UInt32  gemReg;
                    249:   
                    250: //    dumpRegisters();
                    251: 
                    252:     gemReg  = ReadUniNRegister( ioBaseEnet, kGEMTxConfig );
                    253:     gemReg |= kGEMTxConfig_TxDMAEnable;
                    254:     WriteUniNRegister( ioBaseEnet, kGEMTxConfig, gemReg );
                    255: 
                    256:     IOSleep(20);
                    257: 
                    258:     gemReg  = ReadUniNRegister( ioBaseEnet, kGEMRxConfig );
                    259:     gemReg |= kGEMRxConfig_RxDMAEnable;
                    260:     WriteUniNRegister( ioBaseEnet, kGEMRxConfig, gemReg  );
                    261: 
                    262:     IOSleep(20);
                    263: 
                    264:     gemReg  = ReadUniNRegister( ioBaseEnet, kGEMMacTxMacConfig );
                    265:     gemReg |= kGEMMacTxMacConfig_TxMacEnable;    
                    266:     WriteUniNRegister( ioBaseEnet, kGEMMacTxMacConfig, gemReg  );
                    267: 
                    268:     IOSleep(20);
                    269: 
                    270:     gemReg  = ReadUniNRegister( ioBaseEnet, kGEMMacRxMacConfig );
                    271:     gemReg |= kGEMMacRxMacConfig_RxMacEnable;    
                    272:     WriteUniNRegister( ioBaseEnet, kGEMMacRxMacConfig, gemReg  );
                    273: 
                    274: //  dumpRegisters();
                    275: 
                    276: }
                    277: 
                    278: /*-------------------------------------------------------------------------
                    279:  *
                    280:  *
                    281:  *
                    282:  *-------------------------------------------------------------------------*/
                    283: 
                    284: void UniNEnet::stopChip()
                    285: {
                    286:     UInt32     gemReg;
                    287:   
                    288:     gemReg  = ReadUniNRegister( ioBaseEnet, kGEMTxConfig );
                    289:     gemReg &= ~kGEMTxConfig_TxDMAEnable;
                    290:     WriteUniNRegister( ioBaseEnet, kGEMTxConfig, gemReg );
                    291: 
                    292:     IOSleep(20);
                    293: 
                    294:     gemReg  = ReadUniNRegister( ioBaseEnet, kGEMRxConfig );
                    295:     gemReg &= ~kGEMRxConfig_RxDMAEnable;
                    296:     WriteUniNRegister( ioBaseEnet, kGEMRxConfig, gemReg  );
                    297: 
                    298:     IOSleep(20);
                    299: 
                    300:     gemReg  = ReadUniNRegister( ioBaseEnet, kGEMMacTxMacConfig );
                    301:     gemReg &= ~kGEMMacTxMacConfig_TxMacEnable;    
                    302:     WriteUniNRegister( ioBaseEnet, kGEMMacTxMacConfig, gemReg  );
                    303: 
                    304:     IOSleep(20);
                    305: 
                    306:     gemReg  = ReadUniNRegister( ioBaseEnet, kGEMMacRxMacConfig );
                    307:     gemReg &= ~kGEMMacRxMacConfig_RxMacEnable;    
                    308:     WriteUniNRegister( ioBaseEnet, kGEMMacRxMacConfig, gemReg  );
                    309: }
                    310: 
                    311: 
                    312: 
                    313: /*-------------------------------------------------------------------------
                    314:  *
                    315:  *
                    316:  *
                    317:  *-------------------------------------------------------------------------*/
                    318: 
                    319: bool UniNEnet::resetChip()
                    320: {
                    321:     UInt8       resetReg;
                    322:     UInt16      *pPhyType;
                    323:     UInt16      phyWord;
                    324: 
                    325: 
                    326:     WriteUniNRegister( ioBaseEnet, kGEMSoftwareReset, kGEMSoftwareReset_TxReset | kGEMSoftwareReset_RxReset );
                    327: 
                    328:     do
                    329:     {
                    330:         resetReg = ReadUniNRegister( ioBaseEnet, kGEMSoftwareReset );
                    331:     } 
                    332:     while( resetReg & (kGEMSoftwareReset_TxReset | kGEMSoftwareReset_RxReset) );
                    333: 
                    334:     /*
                    335:      * Determine if PHY chip is configured. Reset and enable it (if present).
                    336:      */
                    337:     if ( phyId == 0xff )
                    338:     {
                    339:         if ( miiFindPHY(&phyId) == true )
                    340:         {
                    341:             miiResetPHY( phyId );
                    342: 
                    343:             pPhyType = (UInt16 *)&phyType;
                    344:             miiReadWord( pPhyType,   MII_ID0, phyId );
                    345:             miiReadWord( pPhyType+1, MII_ID1, phyId );
                    346: 
                    347:             if ( (phyType & MII_BCM5400_MASK) == MII_BCM5400_ID )
                    348:             {
                    349:                 miiReadWord( &phyWord, MII_BCM5400_AUXCONTROL, phyId );
                    350:                 phyWord |= MII_BCM5400_AUXCONTROL_PWR10BASET;
                    351:                 miiWriteWord( phyWord, MII_BCM5400_AUXCONTROL, phyId );
                    352:               
                    353:                 miiReadWord( &phyWord, MII_BCM5400_1000BASETCONTROL, phyId );
                    354:                 phyWord |= MII_BCM5400_1000BASETCONTROL_FULLDUPLEXCAP;
                    355:                 miiWriteWord( phyWord, MII_BCM5400_1000BASETCONTROL, phyId );
                    356: 
                    357:                 IODelay(100);   
                    358:                             
                    359:                 miiResetPHY( 0x1F );
                    360: 
                    361:                 miiReadWord( &phyWord, MII_BCM5201_MULTIPHY, 0x1F );
                    362:                 phyWord |= MII_BCM5201_MULTIPHY_SERIALMODE;
                    363:                 miiWriteWord( phyWord, MII_BCM5201_MULTIPHY, 0x1F );
                    364: 
                    365:                 miiReadWord( &phyWord, MII_BCM5400_AUXCONTROL, phyId );
                    366:                 phyWord &= ~MII_BCM5400_AUXCONTROL_PWR10BASET;
                    367:                 miiWriteWord( phyWord, MII_BCM5400_AUXCONTROL, phyId );
                    368: 
                    369:             }              
                    370:         }
                    371:     }
                    372:  
                    373:     return true;
                    374: }    
                    375:     
                    376: /*-------------------------------------------------------------------------
                    377:  *
                    378:  *
                    379:  *
                    380:  *-------------------------------------------------------------------------*/
                    381: 
                    382: bool UniNEnet::initChip()
                    383: {
                    384:     UInt32             i, j;
                    385:     mach_timespec_t    timeStamp;
                    386:     UInt32             rxFifoSize;
                    387:     UInt32             rxOff;
                    388:     UInt32             rxOn;
                    389:     u_int16_t          *p16;
                    390: 
                    391:     if ( phyId == 0xff )
                    392:     {
                    393:         WriteUniNRegister( ioBaseEnet, kGEMPCSDatapathMode, kGEMPCSDatapathMode_ExtSERDESMode );
                    394: 
                    395:         WriteUniNRegister( ioBaseEnet, kGEMPCSSerdesControl, kGEMPCSSerdesControl_DisableLoopback | 
                    396:                                                              kGEMPCSSerdesControl_EnableSyncDet     );
                    397: 
                    398:         WriteUniNRegister( ioBaseEnet, kGEMPCSAdvert, kGEMPCSAdvert_FullDuplexCap |
                    399:                                                       kGEMPCSAdvert_SymPauseCap     );    
                    400: 
                    401:         WriteUniNRegister( ioBaseEnet, kGEMPCSControl, kGEMPCSControl_EnableAutoNegot |
                    402:                                                        kGEMPCSControl_RestartAutoNegot    );    
                    403: 
                    404:         WriteUniNRegister( ioBaseEnet, kGEMPCSConfig, kGEMPCSConfig_Enable );  
                    405: 
                    406:         WriteUniNRegister( ioBaseEnet, kGEMMacXIFConfig, kGEMMacXIFConfig_TxMIIOutputEnable    |
                    407:                                                          kGEMMacXIFConfig_GMIIMode             |
                    408:                                                          kGEMMacXIFConfig_FullDuplexLed );
                    409:     }
                    410:     else
                    411:     {
                    412:         WriteUniNRegister( ioBaseEnet, kGEMPCSDatapathMode, kGEMPCSDatapathMode_GMIIMode );
                    413: 
                    414:         WriteUniNRegister( ioBaseEnet, kGEMMacXIFConfig, kGEMMacXIFConfig_TxMIIOutputEnable    |
                    415:                                                          kGEMMacXIFConfig_FullDuplexLed );
                    416:    }
                    417: 
                    418:     WriteUniNRegister( ioBaseEnet, kGEMMacSendPauseCmd, kGEMMacSendPauseCmd_Bit * kGEMMacSendPauseCmd_Default );
                    419: 
                    420:     WriteUniNRegister( ioBaseEnet, kGEMMacControlConfig, kGEMMacControlConfig_ReceivePauseEnable );
                    421: 
                    422:     WriteUniNRegister( ioBaseEnet, kGEMInterruptMask,  0xffffffff );
                    423: 
                    424:     WriteUniNRegister( ioBaseEnet, kGEMMacTxMask, kGEMMacTxMaskDefault );
                    425: 
                    426:     WriteUniNRegister( ioBaseEnet, kGEMMacRxMask, kGEMMacRxMaskDefault );  
                    427: 
                    428:     WriteUniNRegister( ioBaseEnet, kGEMMacControlMask, kGEMMacControlMaskDefault );
                    429: 
                    430:     WriteUniNRegister( ioBaseEnet, kGEMConfig,  31*kGEMConfig_TxDMALimitBit | 
                    431:                                                31*kGEMConfig_RxDMALimitBit | 
                    432:                                                kGEMConfig_InfiniteBurst);
                    433: 
                    434:     WriteUniNRegister( ioBaseEnet, kGEMMacInterPktGap0, kGEMMacInterPktGap0_Default );
                    435:     WriteUniNRegister( ioBaseEnet, kGEMMacInterPktGap1, kGEMMacInterPktGap1_Default );
                    436:     WriteUniNRegister( ioBaseEnet, kGEMMacInterPktGap2, kGEMMacInterPktGap2_Default );
                    437: 
                    438:     WriteUniNRegister( ioBaseEnet, kGEMMacSlotTime, kGEMMacSlotTime_Default );
                    439: 
                    440:     WriteUniNRegister( ioBaseEnet, kGEMMacMinFrameSize, kGEMMacMinFrameSize_Default );
                    441:     WriteUniNRegister( ioBaseEnet, kGEMMacMaxFrameSize, kGEMMacMaxFrameSize_Default );
                    442: 
                    443:     WriteUniNRegister( ioBaseEnet, kGEMMacPASize, kGEMMacPASize_Default );
                    444: 
                    445:     WriteUniNRegister( ioBaseEnet, kGEMMacJamSize, kGEMMacJamSize_Default );
                    446: 
                    447:     WriteUniNRegister( ioBaseEnet, kGEMMacAttemptLimit, kGEMMacAttemptLimit_Default );
                    448: 
                    449:     WriteUniNRegister( ioBaseEnet, kGEMMacTypeControl, kGEMMacTypeControl_Default );
                    450: 
                    451:     /*
                    452:      *
                    453:      */
                    454:     p16 = (u_int16_t *) myAddress.ea_byte;
                    455:     for ( i=0; i < sizeof(enet_addr_t) / 2; i++ )
                    456:     {
                    457:         WriteUniNRegister( ioBaseEnet, kGEMMacAddr + i * 4, p16[2-i] );
                    458:     }
                    459: 
                    460:     for ( i=0; i < 3; i ++ )
                    461:     {
                    462:         WriteUniNRegister( ioBaseEnet, kGEMMacAddr       + (i+3) * 4, 0 );
                    463:         WriteUniNRegister( ioBaseEnet, kGEMMacAddrFilter + (i+0) * 4, 0 );
                    464:     }
                    465: 
                    466:     WriteUniNRegister( ioBaseEnet, kGEMMacAddr + (6*4), kGEMMacAddr6_Default );
                    467:     WriteUniNRegister( ioBaseEnet, kGEMMacAddr + (7*4), kGEMMacAddr7_Default );
                    468:     WriteUniNRegister( ioBaseEnet, kGEMMacAddr + (8*4), kGEMMacAddr8_Default );
                    469: 
                    470:     WriteUniNRegister( ioBaseEnet, kGEMMacAddrFilterMask1, 0 );
                    471:     WriteUniNRegister( ioBaseEnet, kGEMMacAddrFilterMask0, 0 );
                    472: 
                    473:     for ( i=0; i < 16; i++ )
                    474:     {
                    475:         WriteUniNRegister( ioBaseEnet, kGEMMacHashTable + i * 4, 0 );
                    476:     }
                    477: 
                    478:     /*
                    479:      *
                    480:      */
                    481:     for ( i = kGEMMacCollisions; i <= kGEMMacRxCodeErrors; i+=4 );
                    482:     {
                    483:         WriteUniNRegister( ioBaseEnet, i, 0 );
                    484:     }
                    485: 
                    486:     IOGetTime(&timeStamp); 
                    487:     WriteUniNRegister( ioBaseEnet, kGEMMacRandomSeed, (u_int16_t) timeStamp.tv_nsec );      
                    488: 
                    489:     /*
                    490:      *
                    491:      */
                    492:     WriteUniNRegister( ioBaseEnet, kGEMTxDescBaseLo, txDMACommandsPhys );
                    493:     WriteUniNRegister( ioBaseEnet, kGEMTxDescBaseHi, 0 );
                    494: 
                    495:     for ( i=0, j=TX_RING_LENGTH / kGEMTxConfig_TxRingSizeMin - 1; 
                    496:          (i < 13) && j; 
                    497:          i++, j >>= 1 )
                    498:             ;
                    499: 
                    500:     WriteUniNRegister( ioBaseEnet, kGEMTxConfig, (i                                   * kGEMTxConfig_TxDescRingSizeBit) | 
                    501:                                                  (kGEMTxConfig_TxFIFOThresholdDefault * kGEMTxConfig_TxFIFOThresholdBit) );
                    502: 
                    503:     WriteUniNRegister( ioBaseEnet, kGEMMacTxMacConfig, 0 );
                    504: 
                    505:     setDuplexMode( (phyId == 0xff) ? true : false );
                    506:    
                    507:     /*
                    508:      *
                    509:      */
                    510:     WriteUniNRegister( ioBaseEnet, kGEMRxDescBaseLo, rxDMACommandsPhys );
                    511:     WriteUniNRegister( ioBaseEnet, kGEMRxDescBaseHi, 0 );
                    512: 
                    513:     WriteUniNRegister( ioBaseEnet, kGEMRxKick, RX_RING_LENGTH-4 );
                    514: 
                    515:     for ( i=0, j=RX_RING_LENGTH / kGEMRxConfig_RxRingSizeMin - 1;
                    516:           (i < 13) && j; 
                    517:           i++, j >>= 1 )
                    518:              ;
                    519: 
                    520:     WriteUniNRegister( ioBaseEnet, kGEMRxConfig, (i                                  * kGEMRxConfig_RxDescRingSizeBit) | 
                    521:                                                  (kGEMRxConfig_RxDMAThresholdDefault * kGEMRxConfig_RxDMAThresholdBit) 
                    522:                                                         );
                    523: 
                    524:     WriteUniNRegister( ioBaseEnet, kGEMMacRxMacConfig,  0 );
                    525: 
                    526:     rxFifoSize  = ReadUniNRegister( ioBaseEnet, kGEMRxFIFOSize );
                    527: 
                    528:     rxOff  = rxFifoSize - ((kGEMMacMaxFrameSize_Aligned + 8) * 2 / kGEMRxPauseThresholds_Units);
                    529:     rxOn   = rxFifoSize - ((kGEMMacMaxFrameSize_Aligned + 8) * 3 / kGEMRxPauseThresholds_Units);
                    530: 
                    531:     WriteUniNRegister( ioBaseEnet, kGEMRxPauseThresholds, (rxOff * kGEMRxPauseThresholds_OffBit) | 
                    532:                                                           (rxOn  * kGEMRxPauseThresholds_OnBit) );
                    533: 
                    534:     i = (ReadUniNRegister(ioBaseEnet, kGEMBIFConfig) & kGEMBIFConfig_66Mhz) ? PCI_PERIOD_66MHz : PCI_PERIOD_33MHz;
                    535:     i = (RX_INT_LATENCY_uS * 1000) / (2048 * i);
                    536:     
                    537:     WriteUniNRegister( ioBaseEnet, kGEMRxIntBlanking, i*kGEMRxIntBlanking_TimeBit | 5*kGEMRxIntBlanking_NumPktBit );
                    538: 
                    539:     return true;
                    540: }
                    541: 
                    542: /*-------------------------------------------------------------------------
                    543:  *
                    544:  *
                    545:  *
                    546:  *-------------------------------------------------------------------------*/
                    547: 
                    548: void UniNEnet::disableAdapterInterrupts()
                    549: {
                    550: 
                    551:     WriteUniNRegister( ioBaseEnet, kGEMInterruptMask, 0xffffffff );
                    552: }
                    553: 
                    554: /*-------------------------------------------------------------------------
                    555:  *
                    556:  *
                    557:  *
                    558:  *-------------------------------------------------------------------------*/
                    559: 
                    560: void UniNEnet::enableAdapterInterrupts()
                    561: {
                    562:     UInt32             gemReg;
                    563: 
                    564:     gemReg = ReadUniNRegister( ioBaseEnet, kGEMInterruptMask );
                    565:     gemReg &= ~(kGEMInterruptMask_TxInt | kGEMInterruptMask_RxDone |  kGEMInterruptStatus_RxMacInt);
                    566:     WriteUniNRegister( ioBaseEnet, kGEMInterruptMask, gemReg );
                    567: }
                    568: 
                    569: /*-------------------------------------------------------------------------
                    570:  *
                    571:  *
                    572:  *
                    573:  *-------------------------------------------------------------------------*/
                    574: 
                    575: void UniNEnet::setDuplexMode( bool duplexMode )
                    576: {
                    577:     UInt16      txMacConfig;
                    578:     UInt16      xifConfig;
                    579: 
                    580:     isFullDuplex = duplexMode;
                    581: 
                    582:     txMacConfig = ReadUniNRegister( ioBaseEnet, kGEMMacTxMacConfig );
                    583: 
                    584:     WriteUniNRegister( ioBaseEnet, kGEMMacTxMacConfig, txMacConfig & ~kGEMMacTxMacConfig_TxMacEnable );
                    585:     while( ReadUniNRegister(ioBaseEnet, kGEMMacTxMacConfig) & kGEMMacTxMacConfig_TxMacEnable )
                    586:       ;
                    587: 
                    588:     xifConfig = ReadUniNRegister( ioBaseEnet, kGEMMacXIFConfig );
                    589: 
                    590:     if ( isFullDuplex )
                    591:     {
                    592:         txMacConfig |= (kGEMMacTxMacConfig_IgnoreCollsn | kGEMMacTxMacConfig_IgnoreCarrierSense);
                    593:         xifConfig   &= ~kGEMMacXIFConfig_DisableEcho;
                    594:     }
                    595:     else
                    596:     {
                    597:         txMacConfig &= ~(kGEMMacTxMacConfig_IgnoreCollsn | kGEMMacTxMacConfig_IgnoreCarrierSense);
                    598:         xifConfig   |= kGEMMacXIFConfig_DisableEcho;
                    599:     }
                    600: 
                    601:     WriteUniNRegister( ioBaseEnet, kGEMMacTxMacConfig, txMacConfig );
                    602:     WriteUniNRegister( ioBaseEnet, kGEMMacXIFConfig,   xifConfig );
                    603: }    
                    604: 
                    605: 
                    606: /*-------------------------------------------------------------------------
                    607:  *
                    608:  *
                    609:  *
                    610:  *-------------------------------------------------------------------------*/
                    611: 
                    612: void UniNEnet::restartTransmitter()
                    613: {
                    614: }
                    615: 
                    616: /*-------------------------------------------------------------------------
                    617:  *
                    618:  *
                    619:  *
                    620:  *-------------------------------------------------------------------------*/
                    621: 
                    622: void UniNEnet::restartReceiver()
                    623: {
                    624: }
                    625: 
                    626: /*-------------------------------------------------------------------------
                    627:  *
                    628:  * Orderly stop of receive DMA.
                    629:  *
                    630:  *
                    631:  *-------------------------------------------------------------------------*/
                    632: 
                    633: void UniNEnet::stopReceiveDMA()
                    634: {
                    635: }    
                    636: 
                    637: /*-------------------------------------------------------------------------
                    638:  *
                    639:  *
                    640:  *
                    641:  *-------------------------------------------------------------------------*/
                    642: 
                    643: void UniNEnet::stopTransmitDMA()
                    644: {
                    645: }
                    646: 
                    647: /*-------------------------------------------------------------------------
                    648:  *
                    649:  *
                    650:  *
                    651:  *-------------------------------------------------------------------------*/
                    652: 
                    653: bool UniNEnet::transmitPacket(struct mbuf *packet)
                    654: {
                    655:     UInt32              i,j,k;
                    656:     struct mbuf         *m;
                    657:     TxQueueElement      *txElement;
                    658:     UInt32              dataPhys;
                    659:     
                    660:     
                    661:     for ( m = packet, i=1; m->m_next; m=m->m_next, i++ )
                    662:       ;
                    663:       
                    664:     
                    665:     if ( i > txCommandsAvail )  
                    666:     {
                    667:         transmitInterruptOccurred();
                    668:         
                    669:         if ( i > txCommandsAvail )
                    670:         {
                    671:             return false;
                    672:         } 
                    673:     }    
                    674: 
                    675:     
                    676:     if ( (txElement=getTxElement()) == 0 )
                    677:     {
                    678:         transmitInterruptOccurred();
                    679:         
                    680:         if ( (txElement=getTxElement()) == 0 )
                    681:         {
                    682:             return false;
                    683:         } 
                    684:     }    
                    685:     
                    686:     j = txCommandTail;
                    687:         
                    688:     txElement->mbuf      = packet;
                    689:     txElement->slot      = j;
                    690:     txElement->count     = i;
                    691:     
                    692:     txCommandsAvail     -= i;    
                    693: 
                    694:     m = packet;
                    695: 
                    696:     do
                    697:     {        
                    698:         k = j; 
                    699:     
                    700:         txElementPtrs[j] = txElement;
                    701:         
                    702:         dataPhys = (UInt32)mcl_to_paddr( mtod(m, char *) );
                    703:         if ( dataPhys == 0 )
                    704:         {
                    705:             dataPhys = pmap_extract( kernel_pmap, mtod(m, vm_offset_t));
                    706:         }    
                    707:         
                    708:         txDMACommands[j].desc_seg[0].bufferAddrLo  = EndianSwap32(dataPhys);
                    709:         txDMACommands[j].desc_seg[0].flags0        = EndianSwap32(kGEMTxDescFlags0_BufferSizeBit * m->m_len);
                    710:                
                    711:         j++;   
                    712:         if ( j >= txMaxCommand ) j = 0;               
                    713:     }
                    714:     while ( (m=m->m_next) != 0 );
                    715: 
                    716:     txDMACommands[k].desc_seg[0].flags0             |= EndianSwap32(kGEMTxDescFlags0_EndOfFrame);
                    717:     txDMACommands[txCommandTail].desc_seg[0].flags0 |= EndianSwap32(kGEMTxDescFlags0_StartOfFrame);
                    718:      
                    719:     txCommandTail = j;
                    720:           
                    721:     WriteUniNRegister( ioBaseEnet, kGEMTxKick, j );
                    722:      
                    723:     return true;          
                    724: }          
                    725: 
                    726: 
                    727: /*-------------------------------------------------------------------------
                    728:  * _receivePacket
                    729:  * --------------
                    730:  * This routine runs the receiver in polled-mode (yuk!) for the kernel debugger.
                    731:  * Don't mess with the interrupt source here that can deadlock in the debugger
                    732:  *
                    733:  * The _receivePackets allocate MBufs and pass them up the stack. The kernel
                    734:  * debugger interface passes a buffer into us. To reconsile the two interfaces,
                    735:  * we allow the receive routine to continue to allocate its own buffers and
                    736:  * transfer any received data to the passed-in buffer. This is handled by 
                    737:  * _receivePacket calling _packetToDebugger.
                    738:  *-------------------------------------------------------------------------*/
                    739: 
                    740: void UniNEnet::receivePacket( void *pkt, unsigned int *pkt_len, unsigned int timeout )
                    741: {
                    742:     mach_timespec_t    startTime;
                    743:     mach_timespec_t    currentTime;
                    744:     UInt32             elapsedTimeMS;
                    745: 
                    746:     *pkt_len = 0;
                    747: 
                    748:     if (ready == false)
                    749:       return;
                    750: 
                    751:     debuggerPkt     = pkt;
                    752:     debuggerPktSize = 0;
                    753: 
                    754:     IOGetTime(&startTime);
                    755:     do
                    756:     {
                    757:       receivePackets( true );
                    758:       IOGetTime( &currentTime );
                    759:       elapsedTimeMS = (currentTime.tv_nsec - startTime.tv_nsec) / (1000*1000);
                    760:     } 
                    761:     while ( (debuggerPktSize == 0) && (elapsedTimeMS < timeout) );
                    762: 
                    763:     *pkt_len = debuggerPktSize;
                    764: 
                    765:     return;
                    766: }
                    767: 
                    768: /*-------------------------------------------------------------------------
                    769:  * _packetToDebugger
                    770:  * -----------------
                    771:  * This is called by _receivePackets when we are polling for kernel debugger
                    772:  * packets. It copies the MBuf contents to the buffer passed by the debugger.
                    773:  * It also sets the var debuggerPktSize which will break the polling loop.
                    774:  *-------------------------------------------------------------------------*/
                    775: 
                    776: void UniNEnet::packetToDebugger( struct mbuf * packet, u_int size )
                    777: {
                    778:     debuggerPktSize = size;
                    779:     bcopy( mtod(packet, char *), debuggerPkt, size );
                    780: }
                    781: 
                    782: /*-------------------------------------------------------------------------
                    783:  * _sendPacket
                    784:  * -----------
                    785:  *
                    786:  * This routine runs the transmitter in polled-mode (yuk!) for the kernel debugger.
                    787:  * Don't mess with the interrupt source here that can deadlock in the debugger
                    788:  *
                    789:  *-------------------------------------------------------------------------*/
                    790: 
                    791: void UniNEnet::sendPacket( void *pkt, unsigned int pkt_len )
                    792: {
                    793:     mach_timespec_t    startTime;
                    794:     mach_timespec_t    currentTime;
                    795:     UInt32             elapsedTimeMS;
                    796: 
                    797:     if (!ready || !pkt || (pkt_len > ETHERMAXPACKET))
                    798:     {
                    799:         return;
                    800:     }
                    801: 
                    802:     /*
                    803:      * Wait for the transmit ring to empty
                    804:      */
                    805:     IOGetTime(&startTime); 
                    806:     do
                    807:     {   
                    808:       debugTransmitInterruptOccurred();
                    809:       IOGetTime(&currentTime);
                    810:       elapsedTimeMS = (currentTime.tv_nsec - startTime.tv_nsec) / (1000*1000);
                    811:     }
                    812:     while ( (txCommandHead != txCommandTail) && (elapsedTimeMS < TX_KDB_TIMEOUT) ); 
                    813:     
                    814:     if ( txCommandHead != txCommandTail )
                    815:     {
                    816:       IOLog( "Ethernet(UniN): Polled tranmit timeout - 1\n\r");
                    817:       return;
                    818:     }
                    819: 
                    820:     /*
                    821:      * Allocate a MBuf and copy the debugger transmit data into it.
                    822:      *
                    823:      * jliu - no allocation, just recycle the same buffer dedicated to
                    824:      * KDB transmit.
                    825:      */
                    826:     txDebuggerPkt->m_next = 0;
                    827:     txDebuggerPkt->m_data = (caddr_t) pkt;
                    828:     txDebuggerPkt->m_pkthdr.len = txDebuggerPkt->m_len = pkt_len;
                    829: 
                    830:     /*
                    831:      * Send the debugger packet. txDebuggerPkt must not be freed by
                    832:      * the transmit routine.
                    833:      */
                    834:     transmitPacket(txDebuggerPkt);
                    835: 
                    836:     /*
                    837:      * Poll waiting for the transmit ring to empty again
                    838:      */
                    839:     do 
                    840:     {
                    841:         debugTransmitInterruptOccurred();
                    842:         IOGetTime(&currentTime);
                    843:         elapsedTimeMS = (currentTime.tv_nsec - startTime.tv_nsec) / (1000*1000);
                    844:     }
                    845:     while ( (txCommandHead != txCommandTail) &&
                    846:             (elapsedTimeMS < TX_KDB_TIMEOUT) ); 
                    847: 
                    848:     if ( txCommandHead != txCommandTail )
                    849:     {
                    850:         IOLog( "Ethernet(UniN): Polled tranmit timeout - 2\n\r");
                    851:     }
                    852: 
                    853:     return;
                    854: }
                    855: 
                    856: /*-------------------------------------------------------------------------
                    857:  * _sendDummyPacket
                    858:  * ----------------
                    859:  * The UniN receiver seems to be locked until we send our first packet.
                    860:  *
                    861:  *-------------------------------------------------------------------------*/
                    862: void UniNEnet::sendDummyPacket()
                    863: {
                    864:     union
                    865:     {
                    866:         UInt8           bytes[64];
                    867:         enet_addr_t     enet_addr[2];
                    868:     } dummyPacket;
                    869: 
                    870:     bzero( &dummyPacket, sizeof(dummyPacket) );
                    871: 
                    872: 
                    873:     dummyPacket.enet_addr[0] = myAddress;   
                    874:     dummyPacket.enet_addr[1] = myAddress;
                    875: 
                    876:     sendPacket((void *)dummyPacket.bytes, (unsigned int)sizeof(dummyPacket));
                    877: }
                    878: 
                    879: 
                    880: 
                    881: /*-------------------------------------------------------------------------
                    882:  *
                    883:  *
                    884:  *
                    885:  *-------------------------------------------------------------------------*/
                    886: 
                    887: bool UniNEnet::receiveInterruptOccurred()
                    888: {
                    889:     return receivePackets(false);
                    890: }
                    891: 
                    892: /*-------------------------------------------------------------------------
                    893:  *
                    894:  *
                    895:  *
                    896:  *-------------------------------------------------------------------------*/
                    897: 
                    898: bool UniNEnet::receivePackets( bool fDebugger )
                    899: {
                    900:     struct mbuf     *packet;
                    901:     UInt32          i,last;
                    902:     int             receivedFrameSize = 0;
                    903:     UInt16          dmaFlags;
                    904:     UInt32          rxPktStatus = 0;
                    905:     UInt32          badFrameCount;
                    906:     bool            passPacketUp;
                    907:     bool            reusePkt;
                    908:     bool            status;
                    909:     bool           useNetif = !fDebugger && netifClient;
                    910:     bool            packetsQueued = false;
                    911: 
                    912:    
                    913:     last      = (UInt32)-1;  
                    914:     i         = rxCommandHead;
                    915: 
                    916:     while ( 1 )
                    917:     {
                    918:         passPacketUp = false;
                    919:         reusePkt     = false;
                    920: 
                    921:         dmaFlags = EndianSwap16(rxDMACommands[i].desc_seg[0].frameDataSize);
                    922: 
                    923:         /* 
                    924:          * If the current entry has not been written, then stop at this entry
                    925:          */
                    926:         if ( dmaFlags & kGEMRxDescFrameSize_Own )
                    927:         {
                    928:             break;
                    929:         }
                    930: 
                    931: 
                    932:         receivedFrameSize = dmaFlags & kGEMRxDescFrameSize_Mask;
                    933:         rxPktStatus       = EndianSwap32(rxDMACommands[i].desc_seg[0].flags);
                    934: 
                    935: 
                    936:         /*
                    937:          * Reject packets that are runts or that have other mutations.
                    938:          */
                    939:         if ( receivedFrameSize < (ETHERMINPACKET - ETHERCRC) || 
                    940:                      receivedFrameSize > (ETHERMAXPACKET + ETHERCRC) ||
                    941:                          rxPktStatus & kGEMRxDescFlags_BadCRC )
                    942:         {
                    943:             if (useNetif) netStats->inputErrors++;
                    944:             reusePkt = true;
                    945:         }
                    946:         else if ( useNetif == false )
                    947:         {
                    948:             /*
                    949:              * Always reuse packets in debugger mode. We also refuse to
                    950:              * pass anything up the stack unless the driver is open. The
                    951:              * hardware is enabled before the stack has opened us, to
                    952:              * allow earlier debug interface registration. But we must
                    953:              * not pass any packets up.
                    954:              */
                    955:             reusePkt = true;
                    956:             if (fDebugger)
                    957:             {
                    958:                 packetToDebugger(rxMbuf[i], receivedFrameSize);
                    959:             }
                    960:         }
                    961:         
                    962:  
                    963:         /*
                    964:          * Before we pass this packet up the networking stack. Make sure we
                    965:          * can get a replacement. Otherwise, hold on to the current packet and
                    966:          * increment the input error count.
                    967:          * Thanks Justin!
                    968:          */
                    969: 
                    970:         packet = 0;
                    971: 
                    972:         if ( reusePkt == false )
                    973:         {
                    974:             bool replaced;
                    975:         
                    976:             packet = replaceOrCopyPacket(&rxMbuf[i], receivedFrameSize, &replaced);
                    977: 
                    978:             reusePkt = true;
                    979: 
                    980:             if (packet && replaced)
                    981:             {
                    982:                 status = updateDescriptorFromMbuf(rxMbuf[i], &rxDMACommands[i], true);
                    983: 
                    984:                 if (status)
                    985:                 {
                    986:                     reusePkt = false;
                    987:                 }
                    988:                 else
                    989:                 {
                    990:                     // Assume descriptor has not been corrupted.
                    991:                     freePacket(rxMbuf[i]);  // release new packet.
                    992:                     rxMbuf[i] = packet;     // get the old packet back.
                    993:                     packet = 0;             // pass up nothing.
                    994:                     IOLog("Ethernet(UniN): updateDescriptorFromMbuf error\n");
                    995:                 }
                    996:             }
                    997:             
                    998:             if (packet == 0)
                    999:                 netStats->inputErrors++;
                   1000:         }
                   1001: 
                   1002:         /*
                   1003:          * Install the new MBuf for the one we're about to pass to the network stack
                   1004:          */
                   1005: 
                   1006:         if ( reusePkt == true )
                   1007:         {
                   1008:             rxDMACommands[i].desc_seg[0].frameDataSize = EndianSwap16(NETWORK_BUFSIZE | kGEMRxDescFrameSize_Own);
                   1009:             rxDMACommands[i].desc_seg[0].flags         = 0;
                   1010:         }
                   1011: 
                   1012:         /*
                   1013:          * Keep track of the last receive descriptor processed
                   1014:          */            
                   1015:         last = i;
                   1016: 
                   1017:         /*
                   1018:          * Implement ring wrap-around
                   1019:          */
                   1020:         if (++i >= rxMaxCommand) i = 0;
                   1021: 
                   1022:         if (fDebugger)
                   1023:         {
                   1024:             break;
                   1025:         }
                   1026: 
                   1027:         /*
                   1028:          * Transfer received packet to network
                   1029:          */
                   1030:         if (packet)
                   1031:         {
                   1032:             KERNEL_DEBUG(DBG_UniN_RXCOMPLETE | DBG_FUNC_NONE, (int) packet, 
                   1033:                 (int)receivedFrameSize, 0, 0, 0 );
                   1034: 
                   1035:             networkInterface->inputPacket(packet, receivedFrameSize, true);
                   1036:             netStats->inputPackets++;
                   1037:                        packetsQueued = true;
                   1038:         }
                   1039:     }
                   1040: 
                   1041:     /*
                   1042:      *
                   1043:      *
                   1044:      */
                   1045: #if 0
                   1046:     IOLog( "Ethernet(UniN): Prev - Rx Head = %2d Rx Tail = %2d Rx Last = %2d\n\r", rxCommandHead, rxCommandTail, last );
                   1047: #endif
                   1048: 
                   1049:     if ( last != (UInt32)-1 )
                   1050:     {
                   1051:         rxCommandTail = last;
                   1052:         rxCommandHead = i;
                   1053:     }
                   1054: 
                   1055:     /*
                   1056:      * Tap the DMA to wake it up
                   1057:      */
                   1058:     WriteUniNRegister(ioBaseEnet, kGEMRxKick, rxCommandTail & ~(4-1));
                   1059: 
                   1060: 
                   1061:     /*
                   1062:      * Update receive error statistics
                   1063:      */
                   1064: 
                   1065:     badFrameCount =    ReadUniNRegister(ioBaseEnet, kGEMMacRxLengthErrors)
                   1066:                      + ReadUniNRegister(ioBaseEnet, kGEMMacRxFCSErrors);
                   1067: 
                   1068:     /*
                   1069:      * Clear Hardware counters
                   1070:      */
                   1071:     WriteUniNRegister(ioBaseEnet, kGEMMacRxLengthErrors,   0);
                   1072:     WriteUniNRegister(ioBaseEnet, kGEMMacRxFCSErrors,      0);
                   1073:     
                   1074:     if (useNetif) netStats->inputErrors += badFrameCount;
                   1075: 
                   1076: 
                   1077:     return packetsQueued;
                   1078: }
                   1079:  
                   1080: /*-------------------------------------------------------------------------
                   1081:  *
                   1082:  *
                   1083:  *
                   1084:  *-------------------------------------------------------------------------*/
                   1085: 
                   1086: bool UniNEnet::transmitInterruptOccurred()
                   1087: {
                   1088:     UInt32             i;
                   1089:     bool               fServiced = false;
                   1090:     UInt32             txHeadOrig, txCompOrig;
                   1091:     TxQueueElement      *txElement;
                   1092: 
                   1093:     i = ReadUniNRegister( ioBaseEnet, kGEMTxCompletion );
                   1094: 
                   1095:     txHeadOrig = txCommandHead;
                   1096:     txCompOrig = i;
                   1097:     
                   1098:     while ( i != txCommandHead )
                   1099:     {
                   1100:         /*
                   1101:          * Free the MBuf we just transmitted
                   1102:          */
                   1103:         txElement = txElementPtrs[txCommandHead];         
                   1104:          
                   1105:         KERNEL_DEBUG(DBG_UniN_TXCOMPLETE | DBG_FUNC_NONE, (int) txElement->mbuf, 0, 0, 0, 0 );
                   1106: 
                   1107:         txElementPtrs[txCommandHead] = 0;
                   1108:         txCommandsAvail++;
                   1109: 
                   1110:         if ( --txElement->count == 0 )
                   1111:         {
                   1112:             freePacket( txElement->mbuf );
                   1113:             releaseTxElement( txElement );   
                   1114:             if (netifClient) netStats->outputPackets++;     
                   1115:         }    
                   1116:         
                   1117:         if ( ++txCommandHead >= txMaxCommand ) txCommandHead = 0;
                   1118: 
                   1119:         i = ReadUniNRegister( ioBaseEnet, kGEMTxCompletion );
                   1120: 
                   1121:         fServiced = true;
                   1122:     }
                   1123: 
                   1124:     return fServiced;
                   1125: }
                   1126: 
                   1127: /*-------------------------------------------------------------------------
                   1128:  *
                   1129:  *
                   1130:  *
                   1131:  *-------------------------------------------------------------------------*/
                   1132: 
                   1133: bool UniNEnet::debugTransmitInterruptOccurred()
                   1134: {
                   1135:     bool               fServiced = false;
                   1136:     UInt32             i;
                   1137:     TxQueueElement      *txElement;
                   1138: 
                   1139:     // Set the debugTxPoll flag to indicate the debugger was active
                   1140:     // and some cleanup may be needed when the driver returns to
                   1141:     // normal operation.
                   1142:     //
                   1143:     debugTxPoll = true;
                   1144: 
                   1145:     i = ReadUniNRegister( ioBaseEnet, kGEMTxCompletion );
                   1146: 
                   1147:     while ( i != txCommandHead )
                   1148:     {
                   1149:         fServiced = true;
                   1150: 
                   1151:         /*
                   1152:          * Free the mbuf we just transmitted.
                   1153:          *
                   1154:          * If it is the debugger packet, just remove it from the ring.
                   1155:          * and reuse the same packet for the next sendPacket() request.
                   1156:          */
                   1157:          
                   1158:         /*
                   1159:          * While in debugger mode, do not touch the mbuf pool.
                   1160:          * Queue any used mbufs to a local queue. This queue
                   1161:          * will get flushed after we exit from debugger mode.
                   1162:          *
                   1163:          * During continuous debugger transmission and
                   1164:          * interrupt polling, we expect only the txDebuggerPkt
                   1165:          * to show up on the transmit mbuf ring.
                   1166:          */
                   1167:         txElement = txElementPtrs[txCommandHead];
                   1168:         txElementPtrs[txCommandHead] = 0;
                   1169:         txCommandsAvail++;
                   1170:         
                   1171:         KERNEL_DEBUG(DBG_UniN_TXCOMPLETE | DBG_FUNC_NONE,
                   1172:             (int)txElement->mbuf,
                   1173:             (int)txElement->mbuf->m_pkthdr.len, 0, 0, 0 );
                   1174: 
                   1175:         if ( --txElement->count == 0 )
                   1176:         {
                   1177:             if (txElement->mbuf != txDebuggerPkt) 
                   1178:             {
                   1179:                 debugQueue->enqueue( txElement->mbuf );
                   1180:             }    
                   1181:             releaseTxElement( txElement );            
                   1182:         }                 
                   1183: 
                   1184:         if ( ++(txCommandHead) >= txMaxCommand )
                   1185:             txCommandHead = 0;
                   1186:     }
                   1187: 
                   1188:     return fServiced;
                   1189: }
                   1190: 
                   1191: /*-------------------------------------------------------------------------
                   1192:  *
                   1193:  *
                   1194:  *
                   1195:  *-------------------------------------------------------------------------*/
                   1196: 
                   1197: void UniNEnet::debugTransmitCleanup()
                   1198: {
                   1199:     // Debugger was active, clear all packets in the debugQueue, and
                   1200:     // issue a start(), just in case the debugger became active while the
                   1201:     // ring was full and the output queue stopped. Since the debugger
                   1202:     // does not restart the output queue, to avoid calling
                   1203:     // semaphore_signal() which may reenable interrupts, we need to
                   1204:     // make sure the output queue is not stalled after the debugger has
                   1205:     // flushed the ring.
                   1206:     
                   1207:     debugQueue->flush();
                   1208: 
                   1209:     transmitQueue->start();
                   1210: }
                   1211: 
                   1212: 
                   1213: /*-------------------------------------------------------------------------
                   1214:  *
                   1215:  *
                   1216:  *
                   1217:  *-------------------------------------------------------------------------*/
                   1218: 
                   1219: static UInt32 txCnt = 1;
                   1220: 
                   1221: bool UniNEnet::updateDescriptorFromMbuf(struct mbuf * m,  enet_dma_cmd_t *desc, bool isReceive)
                   1222: {
                   1223:     struct IOPhysicalSegment           segVector[1];
                   1224:     UInt32                     segments;
                   1225: 
                   1226:     segments = mbufCursor->getPhysicalSegmentsWithCoalesce(m, segVector);
                   1227:     
                   1228:     if ( segments == 0 || segments > 1 )
                   1229:     {
                   1230:         IOLog("Ethernet(UniN): updateDescriptorFromMbuf error, %d segments\n", (int)segments);
                   1231:         return false;
                   1232:     }    
                   1233:     
                   1234:     if ( isReceive )
                   1235:     {
                   1236:         enet_dma_cmd_t      *rxCmd = (enet_dma_cmd_t *)desc;
                   1237: 
                   1238:         rxCmd->desc_seg[0].bufferAddrLo   = EndianSwap32(segVector[0].location);
                   1239:         rxCmd->desc_seg[0].frameDataSize  = EndianSwap16(segVector[0].length | kGEMRxDescFrameSize_Own); 
                   1240:         rxCmd->desc_seg[0].flags          = 0; 
                   1241:     }
                   1242:     else
                   1243:     {
                   1244:         enet_txdma_cmd_t    *txCmd = (enet_txdma_cmd_t *)desc;
                   1245: 
                   1246:         txCmd->desc_seg[0].bufferAddrLo  = EndianSwap32(segVector[0].location);
                   1247:         txCmd->desc_seg[0].flags0        = EndianSwap32( kGEMTxDescFlags0_BufferSizeBit * segVector[0].length   |
                   1248:                                                          kGEMTxDescFlags0_StartOfFrame      |
                   1249:                                      kGEMTxDescFlags0_EndOfFrame );
                   1250:             
                   1251:         txCmd->desc_seg[0].flags1        = ((txCnt++ % 64) == 0) ? EndianSwap32(kGEMTxDescFlags1_Int) : 0;
                   1252:     }                                          
                   1253: 
                   1254:     return true;
                   1255: }
                   1256: 
                   1257: /*-------------------------------------------------------------------------
                   1258:  *
                   1259:  *
                   1260:  *
                   1261:  *-------------------------------------------------------------------------*/
                   1262: 
                   1263: TxQueueElement *UniNEnet::getTxElement()
                   1264: {
                   1265:     TxQueueElement              *txElement = 0;
                   1266: 
                   1267:     if ( queue_empty( &txFreeQueue ) == false )
                   1268:     {
                   1269:         queue_remove_first( &txFreeQueue, txElement, TxQueueElement *, next );
                   1270:         
                   1271:         txElement->list = &txActiveQueue;
                   1272:         
                   1273:         queue_enter( txElement->list, txElement, TxQueueElement *, next );
                   1274:     }
                   1275:     
                   1276:     return txElement;
                   1277: }
                   1278: 
                   1279: /*-------------------------------------------------------------------------
                   1280:  *
                   1281:  *
                   1282:  *
                   1283:  *-------------------------------------------------------------------------*/
                   1284: 
                   1285: void UniNEnet::releaseTxElement(TxQueueElement *txElement)
                   1286: {
                   1287:     if ( txElement->list != 0 )
                   1288:     {
                   1289:         queue_remove( txElement->list, txElement, TxQueueElement *, next );
                   1290:     }
                   1291:     
                   1292:     txElement->list = &txFreeQueue;   
                   1293: 
                   1294:     queue_enter(  txElement->list, txElement, TxQueueElement *, next);
                   1295: }
                   1296: 
                   1297: /*-------------------------------------------------------------------------
                   1298:  *
                   1299:  *
                   1300:  *
                   1301:  *-------------------------------------------------------------------------*/
                   1302: 
                   1303: void UniNEnet::monitorLinkStatus()
                   1304: {
                   1305:     UInt16          phyStatus;
                   1306:     UInt16          linkStatus;
                   1307:     UInt16          linkMode;
                   1308:     UInt16          lpAbility;
                   1309:     UInt16          gemReg;
                   1310:     UInt16          phyStatusChange;
                   1311:     bool            fullDuplex = false;
                   1312:     UInt8           *linkSpeedTxt;
                   1313: 
                   1314:     if ( phyId == 0xff )
                   1315:     {
                   1316:         phyStatus = ReadUniNRegister( ioBaseEnet, kGEMPCSStatus );
                   1317:         lpAbility =  ReadUniNRegister( ioBaseEnet, kGEMPCSLPAbility );
                   1318:     }
                   1319:     else 
                   1320:     {
                   1321:         if ( miiReadWord( &phyStatus, MII_STATUS, phyId) != true )
                   1322:         {
                   1323:             return;
                   1324:         }
                   1325:        miiReadWord( &lpAbility, MII_STATUS, phyId);
                   1326:     }
                   1327: 
                   1328:     phyStatusChange = (phyStatusPrev ^ phyStatus) & (MII_STATUS_LINK_STATUS | MII_STATUS_NEGOTIATION_COMPLETE);
                   1329:     if ( phyStatusChange )
                   1330:     {
                   1331:         gemReg = ReadUniNRegister( ioBaseEnet, kGEMMacControlConfig );
                   1332:         if ( lpAbility & MII_LPAR_PAUSE )
                   1333:         {
                   1334:             gemReg |= kGEMMacControlConfig_SendPauseEnable;
                   1335:         }
                   1336:         else
                   1337:         {
                   1338:             gemReg &= ~kGEMMacControlConfig_SendPauseEnable;
                   1339:         }
                   1340:         WriteUniNRegister( ioBaseEnet, kGEMMacControlConfig, gemReg );
                   1341:     
                   1342:         if ( (phyStatus & MII_STATUS_LINK_STATUS) && (phyStatus & MII_STATUS_NEGOTIATION_COMPLETE ) )
                   1343:         {
                   1344:             if ( phyId == 0xff )
                   1345:             {
                   1346:                 IOLog( "Ethernet(UniN): Link is up at 1Gb - Full Duplex\n\r" );
                   1347:                 fullDuplex = true;
                   1348:             }
                   1349:             else if ( (phyType & MII_BCM5201_MASK) == MII_BCM5201_ID )
                   1350:             {
                   1351:                 miiReadWord( &linkStatus, MII_BCM5201_AUXSTATUS, phyId );
                   1352: 
                   1353:                 fullDuplex =  (linkStatus & MII_BCM5201_AUXSTATUS_DUPLEX) ? true : false;
                   1354: 
                   1355:                 IOLog( "Ethernet(UniN): Link is up at %sMb - %s Duplex\n\r",
                   1356:                        (linkStatus & MII_BCM5201_AUXSTATUS_SPEED)  ? "100" : "10",
                   1357:                        (fullDuplex)                                ? "Full" : "Half" );                        
                   1358: 
                   1359:             }  
                   1360:             else if ( (phyType & MII_BCM5400_MASK) == MII_BCM5400_ID )
                   1361:             {
                   1362:                 miiReadWord( &linkStatus, MII_BCM5400_AUXSTATUS, phyId );
                   1363: 
                   1364:                 linkMode = (linkStatus & MII_BCM5400_AUXSTATUS_LINKMODE_MASK) / MII_BCM5400_AUXSTATUS_LINKMODE_BIT;
                   1365: 
                   1366:                 gemReg = ReadUniNRegister( ioBaseEnet, kGEMMacXIFConfig );
                   1367:                 if ( linkMode < 6 )
                   1368:                 {
                   1369:                     gemReg &= ~kGEMMacXIFConfig_GMIIMode;
                   1370:                 }
                   1371:                 else
                   1372:                 {
                   1373:                     gemReg |= kGEMMacXIFConfig_GMIIMode;
                   1374:                 }
                   1375:                 WriteUniNRegister( ioBaseEnet, kGEMMacXIFConfig, gemReg );
                   1376: 
                   1377:                 if ( linkMode == 0 )
                   1378:                 {
                   1379:                     linkSpeedTxt = NULL;
                   1380:                 }
                   1381:                 else if ( linkMode < 3 )
                   1382:                 {
                   1383:                     linkSpeedTxt = (UInt8 *)"10Mb";
                   1384:                     fullDuplex =  ( linkMode < 2 ) ? false : true;                    
                   1385: 
                   1386:                 }
                   1387:                 else if ( linkMode < 6 )
                   1388:                 {
                   1389:                     linkSpeedTxt = (UInt8 *)"100Mb";
                   1390:                     fullDuplex =  ( linkMode < 5 ) ? false : true;                                        
                   1391:                 }
                   1392:                 else
                   1393:                 {
                   1394:                     linkSpeedTxt = (UInt8 *)"1Gb";
                   1395:                     fullDuplex = true;
                   1396:                 }                    
                   1397: 
                   1398:                 if ( linkSpeedTxt )
                   1399:                 {
                   1400:                     IOLog( "Ethernet(UniN): Link is up at %s - %s Duplex\n\r",
                   1401:                             linkSpeedTxt,
                   1402:                            (fullDuplex) ? "Full" : "Half" );                        
                   1403:                 }
                   1404:                 else
                   1405:                 {
                   1406:                     IOLog( "Ethernet(UniN): Link is up\n\r" );
                   1407:                 }
                   1408: 
                   1409:             }
                   1410: 
                   1411:             if ( fullDuplex != isFullDuplex )
                   1412:             {
                   1413:                 setDuplexMode( fullDuplex );    
                   1414:             }
                   1415: 
                   1416:             if ( ready == true )
                   1417:             {
                   1418:                 startChip();
                   1419:             }
                   1420: 
                   1421:             linkStatusPrev = true;
                   1422:         }
                   1423:         else
                   1424:         {
                   1425:             if ( linkStatusPrev == true )
                   1426:             {
                   1427:                 stopChip();
                   1428:                 IOLog( "Ethernet(UniN): Link is down.\n\r" );
                   1429:             }
                   1430:             linkStatusPrev = false;
                   1431:         }
                   1432:         phyStatusPrev = phyStatus;
                   1433:     }
                   1434: }
                   1435: 
                   1436: 
                   1437: /*-------------------------------------------------------------------------
                   1438:  *
                   1439:  *
                   1440:  *
                   1441:  *-------------------------------------------------------------------------*/
                   1442: 
                   1443: void UniNEnet::dumpRegisters()
                   1444: {
                   1445:     UInt32      i;
                   1446: 
                   1447:     struct _regtable
                   1448:     {
                   1449:         UInt32      reg;
                   1450:         char        *text;
                   1451:     } 
                   1452:     regtable[] =
                   1453:     {
                   1454:         { kGEMSEBState                  ,"SEBState"         },
                   1455:         { kGEMConfig                    ,"Config"       },
                   1456:         { kGEMInterruptStatus           ,"InterruptStatus"  },
                   1457:         { kGEMInterruptMask             ,"InterruptMask"    },
                   1458:         { kGEMInterruptAck              ,"InterruptAck"     },
                   1459:         { kGEMInterruptAltStatus        ,"InterruptAltStatus"   },
                   1460:         { kGEMPCIErrorStatus            ,"PCIErrorStatus"   },
                   1461:         { kGEMPCIErrorMask              ,"PCIErrorMask"     },
                   1462:         { kGEMBIFConfig                 ,"BIFConfig"        },
                   1463:         { kGEMBIFDiagnostic             ,"BIFDiagnostic"    },
                   1464:         { kGEMSoftwareReset             ,"SoftwareReset"    },
                   1465:         { kGEMTxKick                    ,"TxKick"       },
                   1466:         { kGEMTxConfig                  ,"TxConfig"         },
                   1467:         { kGEMTxDescBaseLo              ,"TxDescBaseLo"     },
                   1468:         { kGEMTxDescBaseHi              ,"TxDescBaseHi"     },
                   1469:         { kGEMTxFIFOWritePtr            ,"TxFIFOWritePtr"   },
                   1470:         { kGEMTxFIFOShadowWritePtr      ,"TxFIFOShadowWritePtr" },
                   1471:         { kGEMTxFIFOReadPtr             ,"TxFIFOReadPtr"    },
                   1472:         { kGEMTxFIFOShadowReadPtr       ,"TxFIFOShadowReadPtr"  },
                   1473:         { kGEMTxFIFOPktCounter          ,"TxFIFOPktCounter"     },
                   1474:         { kGEMTxStateMachine            ,"TxStateMachine"   },
                   1475:         { kGEMTxDataPtrLo               ,"TxDataPtrLo"      },
                   1476:         { kGEMTxDataPtrHi               ,"TxDataPtrHi"      },
                   1477:         { kGEMTxCompletion              ,"TxCompletion"     },
                   1478:         { kGEMTxFIFOAddr                ,"TxFIFOAddr"       },
                   1479:         { kGEMTxFIFOTag                 ,"TxFIFOTag"        },
                   1480:         { kGEMTxFIFODataLo              ,"TxFIFODataLo"     },
                   1481:         { kGEMTxFIFODataHiTag1          ,"TxFIFODataHiTag1"     },
                   1482:         { kGEMTxFIFODataHiTag0          ,"TxFIFODataHiTag0"     },
                   1483:         { kGEMTxFIFOSize                ,"TxFIFOSize"       },
                   1484:         { kGEMRxConfig                  ,"RxConfig"         },
                   1485:         { kGEMRxDescBaseLo              ,"RxDescBaseLo"     },
                   1486:         { kGEMRxDescBaseHi              ,"RxDescBaseHi"     },
                   1487:         { kGEMRxFIFOWritePtr            ,"RxFIFOWritePtr"   },
                   1488:         { kGEMRxFIFOShadowWritePtr      ,"RxFIFOShadowWritePtr" },
                   1489:         { kGEMRxFIFOReadPtr             ,"RxFIFOReadPtr"    },
                   1490:         { kGEMRxFIFOPktCounter          ,"RxFIFOPktCounter"     },
                   1491:         { kGEMRxStateMachine            ,"RxStateMachine"   },
                   1492:         { kGEMRxPauseThresholds         ,"RxPauseThresholds"    },
                   1493:         { kGEMRxDataPtrLo               ,"RxDataPtrLo"      },
                   1494:         { kGEMRxDataPtrHi               ,"RxDataPtrHi"      },
                   1495:         { kGEMRxKick                    ,"RxKick"       },
                   1496:         { kGEMRxCompletion              ,"RxCompletion"     },
                   1497:         { kGEMRxIntBlanking             ,"RxIntBlanking"    },
                   1498:         { kGEMRxFIFOAddr                ,"RxFIFOAddr"       },
                   1499:         { kGEMRxFIFOTag                 ,"RxFIFOTag"        },
                   1500:         { kGEMRxDataLo                  ,"RxDataLo"         },
                   1501:         { kGEMRxDataHiTag0              ,"RxDataHiTag0"     },
                   1502:         { kGEMRxDataHiTag1              ,"RxDataHiTag1"     },
                   1503:         { kGEMRxFIFOSize                ,"RxFIFOSize"       },
                   1504:         { kGEMMacTxResetCmd             ,"MacTxResetCmd"    },
                   1505:         { kGEMMacRxResetCmd             ,"MacRxResetCmd"    },
                   1506:         { kGEMMacSendPauseCmd           ,"MacSendPauseCmd"  },
                   1507:         { kGEMMacTxStatus               ,"MacTxStatus"      },
                   1508:         { kGEMMacRxStatus               ,"MacRxStatus"      },
                   1509:         { kGEMMacControlStatus          ,"MacControlStatus"     },
                   1510:         { kGEMMacTxMask                 ,"MacTxMask"        },
                   1511:         { kGEMMacRxMask                 ,"MacRxMask"        },
                   1512:         { kGEMMacControlMask            ,"MacControlMask"   },
                   1513:         { kGEMMacTxMacConfig            ,"MacTxMacConfig"   },
                   1514:         { kGEMMacRxMacConfig            ,"MacRxMacConfig"   },
                   1515:         { kGEMMacControlConfig          ,"MacControlConfig"     },
                   1516:         { kGEMMacXIFConfig              ,"MacXIFConfig"     },
                   1517:         { kGEMMacInterPktGap0           ,"MacInterPktGap0"  },
                   1518:         { kGEMMacInterPktGap1           ,"MacInterPktGap1"  },
                   1519:         { kGEMMacInterPktGap2           ,"MacInterPktGap2"  },
                   1520:         { kGEMMacSlotTime               ,"MacSlotTime"      },
                   1521:         { kGEMMacMinFrameSize           ,"MacMinFrameSize"  },
                   1522:         { kGEMMacMaxFrameSize           ,"MacMaxFrameSize"  },
                   1523:         { kGEMMacPASize                 ,"MacPASize"        },
                   1524:         { kGEMMacJamSize                ,"MacJamSize"       },
                   1525:         { kGEMMacAttemptLimit           ,"MacAttemptLimit"  },
                   1526:         { kGEMMacTypeControl            ,"MacTypeControl"   },
                   1527:         { kGEMMacAddr                   ,"MacAddr"      },
                   1528:         { kGEMMacAddrFilter             ,"MacAddrFilter"    },
                   1529:         { kGEMMacAddrFilterMask1        ,"MacAddrFilterMask1"   },
                   1530:         { kGEMMacAddrFilterMask0        ,"MacAddrFilterMask0"   },
                   1531:         { kGEMMacHashTable              ,"MacHashTable"     },
                   1532:         { kGEMMacCollisions             ,"MacCollisions"    },
                   1533:         { kGEMMacSingleCollision        ,"MacSingleCollision"   },
                   1534:         { kGEMMacExcessCollisions       ,"MacExcessCollisions"  },
                   1535:         { kGEMMacLateCollisions         ,"MacLateCollisions"    },
                   1536:         { kGEMMacDeferTimer             ,"MacDeferTimer"    },
                   1537:         { kGEMMacPeakAttempts           ,"MacPeakAttempts"  },
                   1538:         { kGEMMacRxFrameCounter         ,"MacRxFrameCounter"    },
                   1539:         { kGEMMacRxLengthErrors         ,"MacRxLengthErrors"    },
                   1540:         { kGEMMacRxAlignErrors          ,"MacRxAlignErrors"     },
                   1541:         { kGEMMacRxFCSErrors            ,"MacRxFCSErrors"   },
                   1542:         { kGEMMacRxCodeErrors           ,"MacRxCodeErrors"  },
                   1543:         { kGEMMacRandomSeed             ,"MacRandomSeed"    },
                   1544:         { kGEMMacStateMachine           ,"MacStateMachine"  },
                   1545:         { kGEMMIFCLock                  ,"MIFCLock"         },
                   1546:         { kGEMMIFData                   ,"MIFData"      },
                   1547:         { kGEMMIFOutputEnable           ,"MIFOutputEnable"  },
                   1548:         { kGEMMIFFrame                  ,"MIFFrame"         },
                   1549:         { kGEMMIFConfig                 ,"MIFConfig"        },
                   1550:         { kGEMMIFMask                   ,"MIFMask"      },  
                   1551:         { kGEMMIFStatus                 ,"MIFStatus"        },
                   1552:         { kGEMMIFStateMachine           ,"MIFStateMachine"  },
                   1553:         { kGEMPCSControl                ,"PCSControl"       },
                   1554:         { kGEMPCSStatus                 ,"PCSStatus"        },
                   1555:         { kGEMPCSAdvert                 ,"PCSAdvert"        },
                   1556:         { kGEMPCSLPAbility              ,"PCSLPAbility"     },
                   1557:         { kGEMPCSConfig                 ,"PCSConfig"        },
                   1558:         { kGEMPCSStateMachine           ,"PCSStateMachine"  },
                   1559:         { kGEMPCSInterruptStatus        ,"PCSInterruptStatus"   },
                   1560:         { kGEMPCSDatapathMode           ,"PCSDatapathMode"  },
                   1561:         { kGEMPCSSerdesControl          ,"PCSSerdesControl"     },
                   1562:         { kGEMPCSSerdesOutputSelect     ,"PCSSerdesOutputSelect"},
                   1563:         { kGEMPCSSerdesState            ,"PCSSerdesState"   }
                   1564:     };
                   1565: 
                   1566:     IOLog("\nEthernet(UniN): IO Address = %08x\n\r", (int)ioBaseEnet );
                   1567: 
                   1568:     for ( i=0; i < sizeof(regtable)/sizeof(regtable[0]); i++ )
                   1569:     {
                   1570:         switch ( regtable[i].reg >> 16 )
                   1571:         {
                   1572:             case 1:
                   1573:                 IOLog( "Ethernet(UniN): %04x: %s = %02x\n\r", 
                   1574:                   (int)regtable[i].reg & 0xffff,
                   1575:                        regtable[i].text,
                   1576:                        ReadUniNRegister( ioBaseEnet, regtable[i].reg ) );
                   1577:                 break;
                   1578:             case 2:
                   1579:                 IOLog( "Ethernet(UniN): %04x: %s = %04x\n\r", 
                   1580:                   (int)regtable[i].reg & 0xffff,
                   1581:                        regtable[i].text,
                   1582:                        ReadUniNRegister( ioBaseEnet, regtable[i].reg ) );
                   1583:                 break;
                   1584:             case 4:
                   1585:                 IOLog( "Ethernet(UniN): %04x: %s = %08x\n\r", 
                   1586:                   (int)regtable[i].reg & 0xffff,
                   1587:                        regtable[i].text,
                   1588:                        ReadUniNRegister( ioBaseEnet, regtable[i].reg ) );
                   1589:                 break;
                   1590:         }
                   1591:     }
                   1592: }
                   1593: 
                   1594: 
                   1595: /*-------------------------------------------------------------------------
                   1596:  *
                   1597:  *
                   1598:  *
                   1599:  *-------------------------------------------------------------------------*/
                   1600: 
                   1601: IOReturn UniNEnet::getHardwareAddress(enet_addr_t *ea)
                   1602: {
                   1603:     UInt32      i;
                   1604:     OSData     *macEntry;
                   1605:     UInt8       *macAddress;
                   1606:     UInt32      len;
                   1607: 
                   1608:     macEntry    = OSDynamicCast( OSData, nub->getProperty( "local-mac-address" ) );
                   1609:     if ( macEntry == 0 )
                   1610:     {
                   1611:         return kIOReturnError;
                   1612:     }
                   1613: 
                   1614:     macAddress  = (UInt8 *)macEntry->getBytesNoCopy();
                   1615:     if ( macAddress == 0 )
                   1616:     {
                   1617:         return kIOReturnError;
                   1618:     }
                   1619: 
                   1620:     len = macEntry->getLength();
                   1621:     if ( len != 6 )
                   1622:     {
                   1623:         return kIOReturnError;
                   1624:     }
                   1625:    
                   1626:     for (i = 0; i < sizeof(*ea); i++)   
                   1627:     {
                   1628:         ea->ea_byte[i] = macAddress[i];
                   1629:     }
                   1630:     return kIOReturnSuccess;
                   1631: }
                   1632: 
                   1633: /*-------------------------------------------------------------------------
                   1634:  *
                   1635:  *
                   1636:  *
                   1637:  *-------------------------------------------------------------------------*/
                   1638: 
                   1639: #define ENET_CRCPOLY 0x04c11db7
                   1640: 
                   1641: static UInt32 crc416(UInt32 current, UInt16 nxtval )
                   1642: {
                   1643:     register UInt32 counter;
                   1644:     register int highCRCBitSet, lowDataBitSet;
                   1645: 
                   1646:     /* Swap bytes */
                   1647:     nxtval = ((nxtval & 0x00FF) << 8) | (nxtval >> 8);
                   1648: 
                   1649:     /* Compute bit-by-bit */
                   1650:     for (counter = 0; counter != 16; ++counter)
                   1651:     {   /* is high CRC bit set? */
                   1652:       if ((current & 0x80000000) == 0)  
                   1653:         highCRCBitSet = 0;
                   1654:       else
                   1655:         highCRCBitSet = 1;
                   1656:         
                   1657:       current = current << 1;
                   1658:     
                   1659:       if ((nxtval & 0x0001) == 0)
                   1660:         lowDataBitSet = 0;
                   1661:       else
                   1662:     lowDataBitSet = 1;
                   1663: 
                   1664:       nxtval = nxtval >> 1;
                   1665:     
                   1666:       /* do the XOR */
                   1667:       if (highCRCBitSet ^ lowDataBitSet)
                   1668:         current = current ^ ENET_CRCPOLY;
                   1669:     }
                   1670:     return current;
                   1671: }
                   1672: 
                   1673: /*-------------------------------------------------------------------------
                   1674:  *
                   1675:  *
                   1676:  *
                   1677:  *-------------------------------------------------------------------------*/
                   1678: 
                   1679: static UInt32 mace_crc(UInt16 *address)
                   1680: {   
                   1681:     register UInt32 newcrc;
                   1682: 
                   1683:     newcrc = crc416(0xffffffff, *address);  /* address bits 47 - 32 */
                   1684:     newcrc = crc416(newcrc, address[1]);    /* address bits 31 - 16 */
                   1685:     newcrc = crc416(newcrc, address[2]);    /* address bits 15 - 0  */
                   1686: 
                   1687:     return(newcrc);
                   1688: }
                   1689: 
                   1690: /*-------------------------------------------------------------------------
                   1691:  *
                   1692:  *
                   1693:  *
                   1694:  *-------------------------------------------------------------------------*/
                   1695: 
                   1696: /*
                   1697:  * Add requested mcast addr to UniN's hash table filter.  
                   1698:  *  
                   1699:  */
                   1700: void UniNEnet::addToHashTableMask(UInt8 *addr)
                   1701: {   
                   1702:     UInt32   i,j;
                   1703:     UInt32   crcBitIndex;
                   1704:     UInt16   mask;
                   1705: 
                   1706:     j = mace_crc((UInt16 *)addr) & 0xFF; /* Big-endian alert! */
                   1707:    
                   1708:     for ( crcBitIndex = i = 0; i < 8; i++ )
                   1709:     {
                   1710:         crcBitIndex >>= 1;
                   1711:         crcBitIndex  |= (j & 0x80);
                   1712:         j           <<= 1;
                   1713:     }
                   1714:      
                   1715:     crcBitIndex ^= 0xFF;
                   1716:             
                   1717:     if (hashTableUseCount[crcBitIndex]++)   
                   1718:       return;           /* This bit is already set */
                   1719:     mask = crcBitIndex % 16;
                   1720:     mask = 1 << mask;
                   1721:     hashTableMask[crcBitIndex/16] |= mask;
                   1722: }
                   1723: 
                   1724: /*-------------------------------------------------------------------------
                   1725:  *
                   1726:  *
                   1727:  *
                   1728:  *-------------------------------------------------------------------------*/
                   1729: 
                   1730: void UniNEnet::resetHashTableMask()
                   1731: {
                   1732:     bzero(hashTableUseCount, sizeof(hashTableUseCount));
                   1733:     bzero(hashTableMask, sizeof(hashTableMask));
                   1734: }
                   1735: 
                   1736: /*-------------------------------------------------------------------------
                   1737:  *
                   1738:  *
                   1739:  *
                   1740:  *-------------------------------------------------------------------------*/
                   1741: 
                   1742: /*
                   1743:  * Sync the adapter with the software copy of the multicast mask
                   1744:  *  (logical address filter).
                   1745:  */
                   1746: void UniNEnet::updateHashTableMask()
                   1747: {
                   1748:     UInt32      i;
                   1749:     UInt16      rxCFGReg;
                   1750: 
                   1751:     rxCFGReg = ReadUniNRegister(ioBaseEnet, kGEMMacRxMacConfig);
                   1752:     WriteUniNRegister(ioBaseEnet, kGEMMacRxMacConfig, rxCFGReg & ~(kGEMMacRxMacConfig_RxMacEnable | 
                   1753:                                                                   kGEMMacRxMacConfig_HashFilterEnable) );
                   1754: 
                   1755:     while ( ReadUniNRegister(ioBaseEnet, kGEMMacRxMacConfig) & (kGEMMacRxMacConfig_RxMacEnable | 
                   1756:                                                                kGEMMacRxMacConfig_HashFilterEnable) )
                   1757:       ;
                   1758:     for (i=0; i<16; i++ )
                   1759:     {
                   1760:         WriteUniNRegister( ioBaseEnet, kGEMMacHashTable + i*4, hashTableMask[15-i] );
                   1761:     }
                   1762: 
                   1763:     rxCFGReg |= kGEMMacRxMacConfig_HashFilterEnable;
                   1764:     WriteUniNRegister(ioBaseEnet, kGEMMacRxMacConfig, rxCFGReg );
                   1765: }
                   1766: 
                   1767: 

unix.superglobalmegacorp.com

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