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

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