2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright (c) 1998-1999 Apple Computer
25 * Implementation for hardware dependent (relatively) code
26 * for the Sun GEM Ethernet controller.
34 #include "UniNEnetPrivate.h"
36 extern void *kernel_pmap
;
41 bool UniNEnet::allocateMemory()
43 UInt32 rxRingSize
, txRingSize
;
48 TxQueueElement
*txElement
;
51 * Calculate total space for DMA channel commands
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);
56 dmaCommandsSize
= round_page( txRingSize
+ rxRingSize
);
58 * Allocate required memory
62 dmaCommands
= (UInt8
*)IOMallocContiguous( dmaCommandsSize
, PAGE_SIZE
, 0 );
64 if ( dmaCommands
== 0 )
66 IOLog( "Ethernet(UniN): Cant allocate channel dma commands\n\r" );
72 * If we needed more than one page, then make sure we received contiguous memory.
74 n
= (dmaCommandsSize
- PAGE_SIZE
) / PAGE_SIZE
;
75 physBase
= pmap_extract(kernel_pmap
, (vm_address_t
) dmaCommands
);
77 virtAddr
= (UInt8
*) dmaCommands
;
78 for( i
=0; i
< n
; i
++, virtAddr
+= PAGE_SIZE
)
80 physAddr
= pmap_extract(kernel_pmap
, (vm_address_t
) virtAddr
);
81 if (physAddr
!= (physBase
+ i
* PAGE_SIZE
) )
83 IOLog( "Ethernet(UniN): Cant allocate contiguous memory for dma commands\n\r" );
88 /* Setup the receive ring pointer */
89 rxDMACommands
= (enet_dma_cmd_t
*)dmaCommands
;
91 /* Setup the transmit ring pointer */
92 txDMACommands
= (enet_txdma_cmd_t
*)(dmaCommands
+ rxRingSize
);
95 queue_init( &txActiveQueue
);
96 queue_init( &txFreeQueue
);
98 for ( i
= 0; i
< TX_MAX_MBUFS
; i
++ )
100 txElement
= (TxQueueElement
*)IOMalloc( sizeof(TxQueueElement
) );
101 if ( txElement
== 0 )
106 bzero( txElement
, sizeof(TxQueueElement
) );
108 releaseTxElement( txElement
);
114 /*-------------------------------------------------------------------------
116 * Setup the Transmit Ring
117 * -----------------------
118 * Each transmit ring entry consists of two words to transmit data from buffer
119 * segments (possibly) spanning a page boundary. This is followed by two DMA commands
120 * which read transmit frame status and interrupt status from the UniN chip. The last
121 * DMA command in each transmit ring entry generates a host interrupt.
122 * The last entry in the ring is followed by a DMA branch to the first
124 *-------------------------------------------------------------------------*/
126 bool UniNEnet::initTxRing()
128 TxQueueElement
* txElement
;
132 * Clear the transmit DMA command memory
134 bzero( (void *)txDMACommands
, sizeof(enet_txdma_cmd_t
) * TX_RING_LENGTH
);
138 txDMACommandsPhys
= pmap_extract(kernel_pmap
, (vm_address_t
) txDMACommands
);
140 if ( txDMACommandsPhys
== 0 )
142 IOLog( "Ethernet(UniN): Bad dma command buf - %08x\n\r",
143 (int)txDMACommands
);
146 for ( i
=0; i
< TX_RING_LENGTH
; i
++ )
148 txElement
= txElementPtrs
[i
];
150 if ( txElement
&& ( --txElement
->count
== 0 ) )
152 freePacket( txElement
->mbuf
);
153 releaseTxElement( txElement
);
156 txElementPtrs
[i
] = 0;
159 txCommandsAvail
= TX_RING_LENGTH
- 1;
167 /*-------------------------------------------------------------------------
169 * Setup the Receive ring
170 * ----------------------
171 * Each receive ring entry consists of two DMA commands to receive data
172 * into a network buffer (possibly) spanning a page boundary. The second
173 * DMA command in each entry generates a host interrupt.
174 * The last entry in the ring is followed by a DMA branch to the first
177 *-------------------------------------------------------------------------*/
179 bool UniNEnet::initRxRing()
184 /* Clear the receive DMA command memory */
185 bzero( (void*)rxDMACommands
, sizeof( enet_dma_cmd_t
) * RX_RING_LENGTH
);
187 rxDMACommandsPhys
= pmap_extract(kernel_pmap
, (vm_address_t
) rxDMACommands
);
188 if ( rxDMACommandsPhys
== 0 )
190 IOLog( "Ethernet(UniN): Bad dma command buf - %08x\n\r",
191 (int) rxDMACommands
);
195 /* Allocate a receive buffer for each entry in the Receive ring */
196 for ( i
= 0; i
< RX_RING_LENGTH
; i
++ )
198 if (rxMbuf
[i
] == NULL
)
200 rxMbuf
[i
] = allocatePacket(NETWORK_BUFSIZE
);
201 if (rxMbuf
[i
] == NULL
)
203 IOLog("Ethernet(UniN): NULL packet in initRxRing\n");
209 * Set the DMA commands for the ring entry to transfer data to the Mbuf.
211 status
= updateDescriptorFromMbuf(rxMbuf
[i
], &rxDMACommands
[i
], true);
214 IOLog("Ethernet(UniN): updateDescriptorFromMbuf error in "
221 * Set the receive queue head to point to the first entry in the ring.
222 * Set the receive queue tail to point to a DMA Stop command after the
232 /*-------------------------------------------------------------------------
236 *-------------------------------------------------------------------------*/
238 void UniNEnet::flushRings()
240 // Free all mbufs from the receive ring:
242 for ( UInt32 i
= 0; i
< RX_RING_LENGTH
; i
++ )
246 freePacket( rxMbuf
[i
] );
251 // Free all mbufs from the transmit ring.
252 // The TxElement is moved back to the free list.
254 for ( UInt32 i
= 0; i
< TX_RING_LENGTH
; i
++ )
256 TxQueueElement
* txElement
= txElementPtrs
[i
];
257 txElementPtrs
[i
] = 0;
259 if ( txElement
&& ( --txElement
->count
== 0 ) )
261 freePacket( txElement
->mbuf
);
262 releaseTxElement( txElement
);
267 /*-------------------------------------------------------------------------
271 *-------------------------------------------------------------------------*/
273 void UniNEnet::startChip()
279 gemReg
= READ_REGISTER( TxConfiguration
);
280 gemReg
|= kTxConfiguration_Tx_DMA_Enable
;
281 WRITE_REGISTER( TxConfiguration
, gemReg
);
285 gemReg
= READ_REGISTER( RxConfiguration
);
286 /// gemReg |= kRxConfiguration_Rx_DMA_Enable | kRxConfiguration_Batch_Disable;
287 gemReg
|= kRxConfiguration_Rx_DMA_Enable
;
288 WRITE_REGISTER( RxConfiguration
, gemReg
);
292 gemReg
= READ_REGISTER( TxMACConfiguration
);
293 gemReg
|= kTxMACConfiguration_TxMac_Enable
;
294 WRITE_REGISTER( TxMACConfiguration
, gemReg
);
298 rxMacConfigReg
= READ_REGISTER( RxMACConfiguration
);
299 rxMacConfigReg
|= kRxMACConfiguration_Rx_Mac_Enable
;
300 WRITE_REGISTER( RxMACConfiguration
, rxMacConfigReg
);
305 /*-------------------------------------------------------------------------
309 *-------------------------------------------------------------------------*/
311 void UniNEnet::stopChip()
315 gemReg
= READ_REGISTER( TxConfiguration
);
316 gemReg
&= ~kTxConfiguration_Tx_DMA_Enable
;
317 WRITE_REGISTER( TxConfiguration
, gemReg
);
321 gemReg
= READ_REGISTER( RxConfiguration
);
322 gemReg
&= ~kRxConfiguration_Rx_DMA_Enable
;
323 WRITE_REGISTER( RxConfiguration
, gemReg
);
327 gemReg
= READ_REGISTER( TxMACConfiguration
);
328 gemReg
&= ~kTxMACConfiguration_TxMac_Enable
;
329 WRITE_REGISTER( TxMACConfiguration
, gemReg
);
333 rxMacConfigReg
= READ_REGISTER( RxMACConfiguration
);
334 rxMacConfigReg
&= ~kRxMACConfiguration_Rx_Mac_Enable
;
335 WRITE_REGISTER( RxMACConfiguration
, rxMacConfigReg
);
342 /*-------------------------------------------------------------------------
346 *-------------------------------------------------------------------------*/
348 bool UniNEnet::resetChip()
354 WRITE_REGISTER( SoftwareReset
, kSoftwareReset_TX
| kSoftwareReset_RX
);
357 resetReg
= READ_REGISTER( SoftwareReset
);
359 while( resetReg
& (kSoftwareReset_TX
| kSoftwareReset_RX
) );
362 * Determine if PHY chip is configured. Reset and enable it (if present).
367 * Generate a hardware PHY reset.
371 if ( miiFindPHY(&phyId
) == true )
373 miiResetPHY( phyId
);
375 pPhyType
= (UInt16
*)&phyType
;
376 miiReadWord( pPhyType
, MII_ID0
, phyId
);
377 miiReadWord( pPhyType
+1, MII_ID1
, phyId
);
378 if ( ((phyType
& MII_BCM5400_MASK
) == MII_BCM5400_ID
)
379 || (((phyType
& MII_BCM5400_MASK
) == MII_BCM5401_ID
)) ) /// mlj temporary quick fix
383 miiReadWord( &phyWord
, MII_BCM5400_AUXCONTROL
, phyId
);
384 phyWord
|= MII_BCM5400_AUXCONTROL_PWR10BASET
;
385 miiWriteWord( phyWord
, MII_BCM5400_AUXCONTROL
, phyId
);
387 miiReadWord( &phyWord
, MII_BCM5400_1000BASETCONTROL
, phyId
);
388 phyWord
|= MII_BCM5400_1000BASETCONTROL_FULLDUPLEXCAP
;
389 miiWriteWord( phyWord
, MII_BCM5400_1000BASETCONTROL
, phyId
);
395 miiReadWord( &phyWord
, MII_BCM5201_MULTIPHY
, 0x1F );
396 phyWord
|= MII_BCM5201_MULTIPHY_SERIALMODE
;
397 miiWriteWord( phyWord
, MII_BCM5201_MULTIPHY
, 0x1F );
399 miiReadWord( &phyWord
, MII_BCM5400_AUXCONTROL
, phyId
);
400 phyWord
&= ~MII_BCM5400_AUXCONTROL_PWR10BASET
;
401 miiWriteWord( phyWord
, MII_BCM5400_AUXCONTROL
, phyId
);
404 else if ( (phyType
& MII_BCM5201_MASK
) == MII_BCM5201_ID
)
412 // IOLog("DEBUG:UniNEnet: phy type = %d\n", phyBCMType);
419 /*-------------------------------------------------------------------------
423 *-------------------------------------------------------------------------*/
425 bool UniNEnet::initChip()
428 mach_timespec_t timeStamp
;
436 WRITE_REGISTER( DatapathMode
, kDatapathMode_ExtSERDESMode
);
437 WRITE_REGISTER( SerialinkControl
, kSerialinkControl_DisableLoopback
438 | kSerialinkControl_EnableSyncDet
);
439 WRITE_REGISTER( Advertisement
, kAdvertisement_Full_Duplex
440 | kAdvertisement_PAUSE
);
441 WRITE_REGISTER( PCSMIIControl
, kPCSMIIControl_Auto_Negotiation_Enable
442 | kPCSMIIControl_Restart_Auto_Negotiation
);
443 WRITE_REGISTER( PCSConfiguration
, kPCSConfiguration_Enable
);
444 WRITE_REGISTER( XIFConfiguration
, kXIFConfiguration_Tx_MII_OE
445 | kXIFConfiguration_GMIIMODE
446 | kXIFConfiguration_FDPLXLED
);
450 WRITE_REGISTER( DatapathMode
, kDatapathMode_GMIIMode
);
451 WRITE_REGISTER( XIFConfiguration
, kXIFConfiguration_Tx_MII_OE
452 | kXIFConfiguration_FDPLXLED
);
455 WRITE_REGISTER( SendPauseCommand
, kSendPauseCommand_default
);
456 WRITE_REGISTER( MACControlConfiguration
,kMACControlConfiguration_Receive_Pause_Enable
);
457 WRITE_REGISTER( InterruptMask
, kInterruptMask_None
);
458 WRITE_REGISTER( TxMACMask
, kTxMACMask_default
);
459 WRITE_REGISTER( RxMACMask
, kRxMACMask_default
);
460 WRITE_REGISTER( MACControlMask
, kMACControlMask_default
);
461 WRITE_REGISTER( Configuration
, kConfiguration_TX_DMA_Limit
462 | kConfiguration_RX_DMA_Limit
463 | kConfiguration_Infinite_Burst
);
465 WRITE_REGISTER( InterPacketGap0
, kInterPacketGap0_default
);
466 WRITE_REGISTER( InterPacketGap1
, kInterPacketGap1_default
);
467 WRITE_REGISTER( InterPacketGap2
, kInterPacketGap2_default
);
468 WRITE_REGISTER( SlotTime
, kSlotTime_default
);
469 WRITE_REGISTER( MinFrameSize
, kMinFrameSize_default
);
470 WRITE_REGISTER( MaxFrameSize
, kMaxFrameSize_default
);
471 WRITE_REGISTER( PASize
, kPASize_default
);
472 WRITE_REGISTER( JamSize
, kJamSize_default
);
473 WRITE_REGISTER( AttemptLimit
, kAttemptLimit_default
);
474 WRITE_REGISTER( MACControlType
, kMACControlType_default
);
476 p16
= (u_int16_t
*) myAddress
.bytes
;
477 for ( i
=0; i
< sizeof(IOEthernetAddress
) / 2; i
++ )
478 WRITE_REGISTER( MACAddress
[ i
], p16
[ 2 - i
] );
480 for ( i
=0; i
< 3; i
++ )
482 WRITE_REGISTER( MACAddress
[ i
+ 3 ], 0 );
483 WRITE_REGISTER( AddressFilter
[ i
], 0 );
486 WRITE_REGISTER( MACAddress
[ 6 ], kMACAddress_default_6
);
487 WRITE_REGISTER( MACAddress
[ 7 ], kMACAddress_default_7
);
488 WRITE_REGISTER( MACAddress
[ 8 ], kMACAddress_default_8
);
490 WRITE_REGISTER( AddressFilter2_1Mask
, 0 );
491 WRITE_REGISTER( AddressFilter0Mask
, 0 );
493 for ( i
=0; i
< 16; i
++ )
494 WRITE_REGISTER( HashTable
[ i
], 0 );
496 WRITE_REGISTER( NormalCollisionCounter
, 0 );
497 WRITE_REGISTER( FirstAttemptSuccessfulCollisionCounter
, 0 );
498 WRITE_REGISTER( ExcessiveCollisionCounter
, 0 );
499 WRITE_REGISTER( LateCollisionCounter
, 0 );
500 WRITE_REGISTER( DeferTimer
, 0 );
501 WRITE_REGISTER( PeakAttempts
, 0 );
502 WRITE_REGISTER( ReceiveFrameCounter
, 0 );
503 WRITE_REGISTER( LengthErrorCounter
, 0 );
504 WRITE_REGISTER( AlignmentErrorCounter
, 0 );
505 WRITE_REGISTER( FCSErrorCounter
, 0 );
506 WRITE_REGISTER( RxCodeViolationErrorCounter
, 0 );
508 IOGetTime(&timeStamp
);
509 WRITE_REGISTER( RandomNumberSeed
, timeStamp
.tv_nsec
& 0xFFFF );
511 WRITE_REGISTER( TxDescriptorBaseLow
, txDMACommandsPhys
);
512 WRITE_REGISTER( TxDescriptorBaseHigh
, 0 );
514 temp
= kTxConfiguration_TxFIFO_Threshold
515 | TX_RING_LENGTH_FACTOR
<< kTxConfiguration_Tx_Desc_Ring_Size_Shift
;
516 WRITE_REGISTER( TxConfiguration
, temp
);
518 WRITE_REGISTER( TxMACConfiguration
, 0 );
520 setDuplexMode( (phyId
== 0xff) ? true : false );
522 WRITE_REGISTER( RxDescriptorBaseLow
, rxDMACommandsPhys
);
523 WRITE_REGISTER( RxDescriptorBaseHigh
, 0 );
525 WRITE_REGISTER( RxKick
, RX_RING_LENGTH
- 4 );
527 temp
= kRxConfiguration_RX_DMA_Threshold
528 /// | kRxConfiguration_Batch_Disable may cause 4x primary interrupts
529 | RX_RING_LENGTH_FACTOR
<< kRxConfiguration_Rx_Desc_Ring_Size_Shift
;
530 WRITE_REGISTER( RxConfiguration
, temp
);
533 WRITE_REGISTER( RxMACConfiguration
, rxMacConfigReg
);
535 rxFifoSize
= READ_REGISTER( RxFIFOSize
);
537 rxOff
= rxFifoSize
- ((kGEMMacMaxFrameSize_Aligned
+ 8) * 2 / kPauseThresholds_Factor
);
538 rxOn
= rxFifoSize
- ((kGEMMacMaxFrameSize_Aligned
+ 8) * 3 / kPauseThresholds_Factor
);
540 WRITE_REGISTER( PauseThresholds
,
541 (rxOff
<< kPauseThresholds_OFF_Threshold_Shift
)
542 | (rxOn
<< kPauseThresholds_ON_Threshold_Shift
) );
544 temp
= READ_REGISTER( BIFConfiguration
);
545 if ( temp
& kBIFConfiguration_M66EN
)
546 temp
= kRxBlanking_default_66
;
547 else temp
= kRxBlanking_default_33
;
548 WRITE_REGISTER( RxBlanking
, temp
);
553 /*-------------------------------------------------------------------------
557 *-------------------------------------------------------------------------*/
559 void UniNEnet::disableAdapterInterrupts()
562 WRITE_REGISTER( InterruptMask
, kInterruptMask_None
);
566 /*-------------------------------------------------------------------------
570 *-------------------------------------------------------------------------*/
572 void UniNEnet::enableAdapterInterrupts()
577 gemReg
= READ_REGISTER( InterruptMask
);
578 gemReg
&= ~( kStatus_TX_INT_ME
| kStatus_RX_DONE
);
579 WRITE_REGISTER( InterruptMask
, gemReg
);
583 /*-------------------------------------------------------------------------
587 *-------------------------------------------------------------------------*/
589 void UniNEnet::setDuplexMode( bool duplexMode
)
595 isFullDuplex
= duplexMode
;
596 txMacConfig
= READ_REGISTER( TxMACConfiguration
);
598 WRITE_REGISTER( TxMACConfiguration
, txMacConfig
& ~kTxMACConfiguration_TxMac_Enable
);
599 while( READ_REGISTER( TxMACConfiguration
) & kTxMACConfiguration_TxMac_Enable
)
602 xifConfig
= READ_REGISTER( XIFConfiguration
);
606 txMacConfig
|= (kTxMACConfiguration_Ignore_Collisions
| kTxMACConfiguration_Ignore_Carrier_Sense
);
607 xifConfig
&= ~kXIFConfiguration_Disable_Echo
;
611 txMacConfig
&= ~(kTxMACConfiguration_Ignore_Collisions
| kTxMACConfiguration_Ignore_Carrier_Sense
);
612 xifConfig
|= kXIFConfiguration_Disable_Echo
;
615 WRITE_REGISTER( TxMACConfiguration
, txMacConfig
);
616 WRITE_REGISTER( XIFConfiguration
, xifConfig
);
621 /*-------------------------------------------------------------------------
625 *-------------------------------------------------------------------------*/
627 void UniNEnet::restartTransmitter()
631 /*-------------------------------------------------------------------------
635 *-------------------------------------------------------------------------*/
637 void UniNEnet::restartReceiver()
639 // Perform a software reset to the logic in the RX MAC.
640 // The MAC config register should be re-programmed following
641 // the reset. Everything else *should* be unaffected.
643 WRITE_REGISTER( RxMACSoftwareResetCommand
, kRxMACSoftwareResetCommand_Reset
);
645 // Poll until the reset bit is cleared by the hardware.
647 for ( int i
= 0; i
< 5000; i
++ )
649 if ( ( READ_REGISTER( RxMACSoftwareResetCommand
)
650 & kRxMACSoftwareResetCommand_Reset
) == 0 )
652 break; // 'i' is always 0 or 1
657 // Update the MAC Config register. Watch out for the programming
658 // restrictions documented in the GEM specification!!!
660 // Disable MAC before setting any other bits in the MAC config
663 WRITE_REGISTER( RxMACConfiguration
, 0 );
665 for ( int i
= 0; i
< 5000; i
++ )
667 if ( ( READ_REGISTER( RxMACConfiguration
)
668 & kRxMACConfiguration_Rx_Mac_Enable
) == 0 )
670 break; // 'i' is always 0
675 // Update MAC config register.
677 WRITE_REGISTER( RxMACConfiguration
, rxMacConfigReg
);
679 }/* end restartReceiver */
682 /*-------------------------------------------------------------------------
684 * Orderly stop of receive DMA.
687 *-------------------------------------------------------------------------*/
689 void UniNEnet::stopReceiveDMA()
693 /*-------------------------------------------------------------------------
697 *-------------------------------------------------------------------------*/
699 void UniNEnet::stopTransmitDMA()
703 /*-------------------------------------------------------------------------
707 *-------------------------------------------------------------------------*/
709 bool UniNEnet::transmitPacket(struct mbuf
*packet
)
711 GEMTxDescriptor
*dp
; // descriptor pointer
714 TxQueueElement
*txElement
;
718 for ( m
= packet
, i
=1; m
->m_next
; m
=m
->m_next
, i
++ )
722 if ( i
> txCommandsAvail
)
727 if ( (txElement
=getTxElement()) == 0 )
734 txElement
->mbuf
= packet
;
736 txElement
->count
= i
;
738 OSAddAtomic( -i
, (SInt32
*)&txCommandsAvail
);
746 txElementPtrs
[j
] = txElement
;
748 dataPhys
= (UInt32
)mcl_to_paddr( mtod(m
, char *) );
750 dataPhys
= pmap_extract( kernel_pmap
, mtod(m
, vm_offset_t
) );
752 dp
= &txDMACommands
[ j
].desc_seg
[ 0 ];
753 OSWriteLittleInt32( &dp
->bufferAddrLo
, 0, dataPhys
);
754 OSWriteLittleInt32( &dp
->flags0
, 0, m
->m_len
);
757 j
= (j
+ 1) & TX_RING_WRAP_MASK
;
759 while ( (m
=m
->m_next
) != 0 );
761 txDMACommands
[ k
].desc_seg
[ 0 ].flags0
|= OSSwapHostToLittleConstInt32( kGEMTxDescFlags0_EndOfFrame
);
762 txDMACommands
[ txCommandTail
].desc_seg
[ 0 ].flags0
|= OSSwapHostToLittleConstInt32( kGEMTxDescFlags0_StartOfFrame
);
763 if ( txIntCnt
>= TX_DESC_PER_INT
)
765 txDMACommands
[ txCommandTail
].desc_seg
[ 0 ].flags1
|= OSSwapHostToLittleConstInt32( kGEMTxDescFlags1_Int
);
766 txIntCnt
= txIntCnt
% TX_DESC_PER_INT
;
770 WRITE_REGISTER( TxKick
, j
);
773 }/* end transmitPacket */
776 /*-------------------------------------------------------------------------
779 * This routine runs the receiver in polled-mode (yuk!) for the kernel debugger.
780 * Don't mess with the interrupt source here that can deadlock in the debugger
782 * The _receivePackets allocate MBufs and pass them up the stack. The kernel
783 * debugger interface passes a buffer into us. To reconsile the two interfaces,
784 * we allow the receive routine to continue to allocate its own buffers and
785 * transfer any received data to the passed-in buffer. This is handled by
786 * _receivePacket calling _packetToDebugger.
787 *-------------------------------------------------------------------------*/
789 void UniNEnet::receivePacket( void * pkt
,
793 mach_timespec_t startTime
;
794 mach_timespec_t currentTime
;
795 UInt32 elapsedTimeMS
;
807 IOGetTime(&startTime
);
810 receivePackets( true );
811 IOGetTime( ¤tTime
);
812 elapsedTimeMS
= (currentTime
.tv_nsec
- startTime
.tv_nsec
) / (1000*1000);
814 while ( (debuggerPktSize
== 0) && (elapsedTimeMS
< timeout
) );
816 *pkt_len
= debuggerPktSize
;
821 /*-------------------------------------------------------------------------
824 * This is called by _receivePackets when we are polling for kernel debugger
825 * packets. It copies the MBuf contents to the buffer passed by the debugger.
826 * It also sets the var debuggerPktSize which will break the polling loop.
827 *-------------------------------------------------------------------------*/
829 void UniNEnet::packetToDebugger( struct mbuf
* packet
, u_int size
)
831 debuggerPktSize
= size
;
832 bcopy( mtod(packet
, char *), debuggerPkt
, size
);
835 /*-------------------------------------------------------------------------
839 * This routine runs the transmitter in polled-mode (yuk!) for the kernel debugger.
840 * Don't mess with the interrupt source here that can deadlock in the debugger
842 *-------------------------------------------------------------------------*/
844 void UniNEnet::sendPacket( void *pkt
, UInt32 pkt_len
)
846 mach_timespec_t startTime
;
847 mach_timespec_t currentTime
;
848 UInt32 elapsedTimeMS
;
850 if (!ready
|| !pkt
|| (pkt_len
> ETHERMAXPACKET
))
856 * Wait for the transmit ring to empty
858 IOGetTime(&startTime
);
861 debugTransmitInterruptOccurred();
862 IOGetTime(¤tTime
);
863 elapsedTimeMS
= (currentTime
.tv_nsec
- startTime
.tv_nsec
) / (1000*1000);
865 while ( (txCommandHead
!= txCommandTail
) && (elapsedTimeMS
< TX_KDB_TIMEOUT
) );
867 if ( txCommandHead
!= txCommandTail
)
869 IOLog( "Ethernet(UniN): Polled tranmit timeout - 1\n\r");
874 * Allocate a MBuf and copy the debugger transmit data into it.
876 * jliu - no allocation, just recycle the same buffer dedicated to
879 txDebuggerPkt
->m_next
= 0;
880 txDebuggerPkt
->m_data
= (caddr_t
) pkt
;
881 txDebuggerPkt
->m_pkthdr
.len
= txDebuggerPkt
->m_len
= pkt_len
;
884 * Send the debugger packet. txDebuggerPkt must not be freed by
885 * the transmit routine.
887 transmitPacket(txDebuggerPkt
);
890 * Poll waiting for the transmit ring to empty again
894 debugTransmitInterruptOccurred();
895 IOGetTime(¤tTime
);
896 elapsedTimeMS
= (currentTime
.tv_nsec
- startTime
.tv_nsec
) / (1000*1000);
898 while ( (txCommandHead
!= txCommandTail
) &&
899 (elapsedTimeMS
< TX_KDB_TIMEOUT
) );
901 if ( txCommandHead
!= txCommandTail
)
903 IOLog( "Ethernet(UniN): Polled tranmit timeout - 2\n\r");
909 /*-------------------------------------------------------------------------
912 * The UniN receiver seems to be locked until we send our first packet.
914 *-------------------------------------------------------------------------*/
915 void UniNEnet::sendDummyPacket()
920 IOEthernetAddress enet_addr
[2];
923 bzero( &dummyPacket
, sizeof(dummyPacket
) );
926 dummyPacket
.enet_addr
[0] = myAddress
;
927 dummyPacket
.enet_addr
[1] = myAddress
;
929 sendPacket((void *)dummyPacket
.bytes
, (unsigned int)sizeof(dummyPacket
));
934 /*-------------------------------------------------------------------------
938 *-------------------------------------------------------------------------*/
940 bool UniNEnet::receiveInterruptOccurred()
942 return receivePackets(false);
945 /*-------------------------------------------------------------------------
949 *-------------------------------------------------------------------------*/
951 bool UniNEnet::receivePackets( bool fDebugger
)
953 struct mbuf
* packet
;
955 int receivedFrameSize
= 0;
957 UInt32 rxPktStatus
= 0;
961 bool useNetif
= !fDebugger
&& netifEnabled
;
962 bool packetsQueued
= false;
970 passPacketUp
= false;
973 dmaFlags
= OSReadLittleInt16( &rxDMACommands
[ i
].desc_seg
[ 0 ].frameDataSize
, 0 );
976 * If the current entry has not been written, then stop at this entry
978 if ( dmaFlags
& kGEMRxDescFrameSize_Own
)
984 receivedFrameSize
= dmaFlags
& kGEMRxDescFrameSize_Mask
;
985 rxPktStatus
= OSReadLittleInt32( &rxDMACommands
[ i
].desc_seg
[ 0 ].flags
, 0 );
989 * Reject packets that are runts or that have other mutations.
991 if ( receivedFrameSize
< (ETHERMINPACKET
- ETHERCRC
) ||
992 receivedFrameSize
> (ETHERMAXPACKET
+ ETHERCRC
) ||
993 rxPktStatus
& kGEMRxDescFlags_BadCRC
)
996 NETWORK_STAT_ADD( inputErrors
);
997 if ( receivedFrameSize
< (ETHERMINPACKET
- ETHERCRC
) )
998 ETHERNET_STAT_ADD( dot3RxExtraEntry
.frameTooShorts
);
999 else ETHERNET_STAT_ADD( dot3StatsEntry
.frameTooLongs
);
1001 else if ( useNetif
== false )
1004 * Always reuse packets in debugger mode. We also refuse to
1005 * pass anything up the stack unless the driver is open. The
1006 * hardware is enabled before the stack has opened us, to
1007 * allow earlier debug interface registration. But we must
1008 * not pass any packets up.
1013 packetToDebugger(rxMbuf
[i
], receivedFrameSize
);
1019 * Before we pass this packet up the networking stack. Make sure we
1020 * can get a replacement. Otherwise, hold on to the current packet and
1021 * increment the input error count.
1027 if ( reusePkt
== false )
1031 packet
= replaceOrCopyPacket(&rxMbuf
[i
], receivedFrameSize
, &replaced
);
1035 if (packet
&& replaced
)
1037 status
= updateDescriptorFromMbuf(rxMbuf
[i
], &rxDMACommands
[i
], true);
1045 // Assume descriptor has not been corrupted.
1046 freePacket(rxMbuf
[i
]); // release new packet.
1047 rxMbuf
[i
] = packet
; // get the old packet back.
1048 packet
= 0; // pass up nothing.
1049 IOLog("Ethernet(UniN): updateDescriptorFromMbuf error\n");
1054 NETWORK_STAT_ADD( inputErrors
);
1058 * Install the new MBuf for the one we're about to pass to the network stack
1061 if ( reusePkt
== true )
1063 rxDMACommands
[i
].desc_seg
[0].flags
= 0;
1064 rxDMACommands
[i
].desc_seg
[0].frameDataSize
= OSSwapHostToLittleConstInt16( NETWORK_BUFSIZE
| kGEMRxDescFrameSize_Own
);
1067 last
= i
; /* Keep track of the last receive descriptor processed */
1068 i
= (i
+ 1) & RX_RING_WRAP_MASK
;
1070 if ( (i
& 3) == 0 ) // only kick modulo 4
1072 WRITE_REGISTER( RxKick
, (i
- 4) & RX_RING_WRAP_MASK
);
1081 * Transfer received packet to network
1085 KERNEL_DEBUG(DBG_UniN_RXCOMPLETE
| DBG_FUNC_NONE
, (int) packet
,
1086 (int)receivedFrameSize
, 0, 0, 0 );
1088 networkInterface
->inputPacket(packet
, receivedFrameSize
, true);
1089 NETWORK_STAT_ADD( inputPackets
);
1090 packetsQueued
= true;
1094 if ( last
!= (UInt32
)-1 )
1096 rxCommandTail
= last
;
1100 return packetsQueued
;
1101 }/* end receivePackets */
1104 /*-------------------------------------------------------------------------
1108 *-------------------------------------------------------------------------*/
1110 bool UniNEnet::transmitInterruptOccurred()
1113 bool serviced
= false;
1114 TxQueueElement
*txElement
;
1117 i
= READ_REGISTER( TxCompletion
);
1119 while ( i
!= txCommandHead
) // i and txCommandHead race each other
1121 do // This DO reduces READ_REGISTER calls which access the PCI bus
1122 { /* Free the MBuf we just transmitted */
1124 txElement
= txElementPtrs
[ txCommandHead
];
1126 KERNEL_DEBUG( DBG_UniN_TXCOMPLETE
| DBG_FUNC_NONE
,
1127 (int)txElement
->mbuf
, 0, 0, 0, 0 );
1129 txElementPtrs
[ txCommandHead
] = 0;
1130 OSIncrementAtomic( (SInt32
*)&txCommandsAvail
);
1132 if ( --txElement
->count
== 0 )
1134 freePacket( txElement
->mbuf
, kDelayFree
);
1135 releaseTxElement( txElement
);
1136 NETWORK_STAT_ADD( outputPackets
);
1139 txCommandHead
= (txCommandHead
+ 1) & TX_RING_WRAP_MASK
;
1141 } while ( i
!= txCommandHead
); // loop til txCommandHead catches i
1144 i
= READ_REGISTER( TxCompletion
); // see if i advanced during last batch
1147 // Release all packets in the free queue.
1148 releaseFreePackets();
1150 }/* end transmitInterruptOccurred */
1153 /*-------------------------------------------------------------------------
1157 *-------------------------------------------------------------------------*/
1159 bool UniNEnet::debugTransmitInterruptOccurred()
1161 bool fServiced
= false;
1163 TxQueueElement
* txElement
;
1165 // Set the debugTxPoll flag to indicate the debugger was active
1166 // and some cleanup may be needed when the driver returns to
1167 // normal operation.
1171 i
= READ_REGISTER( TxCompletion
);
1173 while ( i
!= txCommandHead
)
1178 * Free the mbuf we just transmitted.
1180 * If it is the debugger packet, just remove it from the ring.
1181 * and reuse the same packet for the next sendPacket() request.
1185 * While in debugger mode, do not touch the mbuf pool.
1186 * Queue any used mbufs to a local queue. This queue
1187 * will get flushed after we exit from debugger mode.
1189 * During continuous debugger transmission and
1190 * interrupt polling, we expect only the txDebuggerPkt
1191 * to show up on the transmit mbuf ring.
1193 txElement
= txElementPtrs
[txCommandHead
];
1194 txElementPtrs
[txCommandHead
] = 0;
1195 OSIncrementAtomic( (SInt32
*)&txCommandsAvail
);
1197 KERNEL_DEBUG( DBG_UniN_TXCOMPLETE
| DBG_FUNC_NONE
,
1198 (int) txElement
->mbuf
,
1199 (int) txElement
->mbuf
->m_pkthdr
.len
, 0, 0, 0 );
1201 if ( --txElement
->count
== 0 )
1203 if (txElement
->mbuf
!= txDebuggerPkt
)
1205 debugQueue
->enqueue( txElement
->mbuf
);
1207 releaseTxElement( txElement
);
1210 txCommandHead
= (txCommandHead
+ 1) & TX_RING_WRAP_MASK
;
1216 /*-------------------------------------------------------------------------
1220 *-------------------------------------------------------------------------*/
1222 void UniNEnet::debugTransmitCleanup()
1224 // Debugger was active, clear all packets in the debugQueue, and
1225 // issue a start(), just in case the debugger became active while the
1226 // ring was full and the output queue stopped. Since the debugger
1227 // does not restart the output queue, to avoid calling
1228 // semaphore_signal() which may reenable interrupts, we need to
1229 // make sure the output queue is not stalled after the debugger has
1230 // flushed the ring.
1232 debugQueue
->flush();
1234 transmitQueue
->start();
1238 /*-------------------------------------------------------------------------
1242 *-------------------------------------------------------------------------*/
1244 bool UniNEnet::updateDescriptorFromMbuf(struct mbuf
* m
, enet_dma_cmd_t
*desc
, bool isReceive
)
1246 struct IOPhysicalSegment segVector
[1];
1249 segments
= mbufCursor
->getPhysicalSegmentsWithCoalesce(m
, segVector
);
1251 if ( segments
== 0 || segments
> 1 )
1253 IOLog("Ethernet(UniN): updateDescriptorFromMbuf error, %d segments\n", (int)segments
);
1259 enet_dma_cmd_t
*rxCmd
= (enet_dma_cmd_t
*)desc
;
1261 OSWriteLittleInt32( &rxCmd
->desc_seg
[0].bufferAddrLo
, 0, segVector
[0].location
);
1262 OSWriteLittleInt16( &rxCmd
->desc_seg
[0].frameDataSize
, 0, segVector
[0].length
| kGEMRxDescFrameSize_Own
);
1263 rxCmd
->desc_seg
[0].flags
= 0;
1267 enet_txdma_cmd_t
*txCmd
= (enet_txdma_cmd_t
*)desc
;
1269 OSWriteLittleInt32( &txCmd
->desc_seg
[0].bufferAddrLo
, 0, segVector
[0].location
);
1270 OSWriteLittleInt32( &txCmd
->desc_seg
[0].flags0
, 0, segVector
[0].length
1271 | kGEMTxDescFlags0_StartOfFrame
1272 | kGEMTxDescFlags0_EndOfFrame
);
1274 txCmd
->desc_seg
[0].flags1
= 0;
1276 if ( (txIntCnt
% TX_DESC_PER_INT
) == 0 ) /// Divide???
1277 txCmd
->desc_seg
[0].flags1
= OSSwapHostToLittleConstInt32( kGEMTxDescFlags1_Int
);
1281 }/* end updateDescriptorFromMbuf */
1283 /*-------------------------------------------------------------------------
1287 *-------------------------------------------------------------------------*/
1289 TxQueueElement
* UniNEnet::getTxElement()
1291 TxQueueElement
* txElement
= 0;
1293 IOSimpleLockLock( txQueueLock
);
1295 if ( queue_empty( &txFreeQueue
) == false )
1297 queue_remove_first( &txFreeQueue
, txElement
, TxQueueElement
*, next
);
1299 txElement
->list
= &txActiveQueue
;
1301 queue_enter( txElement
->list
, txElement
, TxQueueElement
*, next
);
1304 IOSimpleLockUnlock( txQueueLock
);
1309 /*-------------------------------------------------------------------------
1313 *-------------------------------------------------------------------------*/
1315 void UniNEnet::releaseTxElement(TxQueueElement
* txElement
)
1317 IOSimpleLockLock( txQueueLock
);
1319 if ( txElement
->list
!= 0 )
1321 queue_remove( txElement
->list
, txElement
, TxQueueElement
*, next
);
1324 txElement
->list
= &txFreeQueue
;
1326 queue_enter( txElement
->list
, txElement
, TxQueueElement
*, next
);
1328 IOSimpleLockUnlock( txQueueLock
);
1331 /*-------------------------------------------------------------------------
1335 *-------------------------------------------------------------------------*/
1337 void UniNEnet::monitorLinkStatus( bool firstPoll
)
1344 UInt16 phyStatusChange
;
1345 bool fullDuplex
= false;
1346 UInt32 linkSpeed
= 0;
1347 IOMediumType mediumType
= kIOMediumEthernetNone
;
1348 IONetworkMedium
*medium
;
1354 linkStatusPrev
= kLinkStatusUnknown
;
1357 if ( phyId
== 0xff )
1359 phyStatus
= READ_REGISTER( PCSMIIStatus
) & 0x0000FFFF;
1360 lpAbility
= READ_REGISTER( PCSMIILinkPartnerAbility
) & 0x0000FFFF;
1364 if ( miiReadWord( &phyStatus
, MII_STATUS
, phyId
) != true )
1368 miiReadWord( &lpAbility
, MII_STATUS
, phyId
);
1371 phyStatusChange
= (phyStatusPrev
^ phyStatus
) &
1372 ( MII_STATUS_LINK_STATUS
|
1373 MII_STATUS_NEGOTIATION_COMPLETE
);
1375 if ( phyStatusChange
|| firstPoll
)
1379 // For the initial link status poll, wait a bit, then
1380 // re-read the status register to clear any latched bits.
1381 // Why wait? Well, the debugger can kick in shortly after
1382 // this function returns, and we want the duplex setting
1383 // on the MAC to match the PHY.
1385 miiWaitForAutoNegotiation( phyId
);
1386 miiReadWord(&phyStatus
, MII_STATUS
, phyId
);
1387 miiReadWord(&phyStatus
, MII_STATUS
, phyId
);
1390 gemReg
= READ_REGISTER( MACControlConfiguration
);
1391 if ( lpAbility
& MII_LPAR_PAUSE
)
1392 gemReg
|= kMACControlConfiguration_Send_Pause_Enable
;
1393 else gemReg
&= ~kMACControlConfiguration_Send_Pause_Enable
;
1394 WRITE_REGISTER( MACControlConfiguration
, gemReg
);
1396 if ( (phyStatus
& MII_STATUS_LINK_STATUS
) &&
1397 ( firstPoll
|| (phyStatus
& MII_STATUS_NEGOTIATION_COMPLETE
) ) )
1399 if ( phyId
== 0xff )
1403 mediumType
= kIOMediumEthernet1000BaseSX
;
1405 else if ( (phyType
& MII_LXT971_MASK
) == MII_LXT971_ID
)
1407 miiReadWord( &linkStatus
, MII_LXT971_STATUS_2
, phyId
);
1408 linkSpeed
= (linkStatus
& MII_LXT971_STATUS_2_SPEED
) ?
1410 fullDuplex
= (linkStatus
& MII_LXT971_STATUS_2_DUPLEX
) ?
1412 mediumType
= (linkSpeed
== 10) ? kIOMediumEthernet10BaseT
:
1413 kIOMediumEthernet100BaseTX
;
1415 else if ( (phyType
& MII_BCM5201_MASK
) == MII_BCM5201_ID
)
1417 miiReadWord( &linkStatus
, MII_BCM5201_AUXSTATUS
, phyId
);
1418 linkSpeed
= (linkStatus
& MII_BCM5201_AUXSTATUS_SPEED
) ?
1420 fullDuplex
= (linkStatus
& MII_BCM5201_AUXSTATUS_DUPLEX
) ?
1422 mediumType
= (linkSpeed
== 10) ? kIOMediumEthernet10BaseT
:
1423 kIOMediumEthernet100BaseTX
;
1425 else if ( ((phyType
& MII_BCM5400_MASK
) == MII_BCM5400_ID
)
1426 || ((phyType
& MII_BCM5400_MASK
) == MII_BCM5401_ID
) ) /// mlj temporary quick fix
1428 miiReadWord( &linkStatus
, MII_BCM5400_AUXSTATUS
, phyId
);
1430 linkMode
= (linkStatus
& MII_BCM5400_AUXSTATUS_LINKMODE_MASK
) /
1431 MII_BCM5400_AUXSTATUS_LINKMODE_BIT
;
1433 gemReg
= READ_REGISTER( XIFConfiguration
);
1435 gemReg
&= ~kXIFConfiguration_GMIIMODE
;
1436 else gemReg
|= kXIFConfiguration_GMIIMODE
;
1437 WRITE_REGISTER( XIFConfiguration
, gemReg
);
1439 if ( linkMode
== 0 )
1443 else if ( linkMode
< 3 )
1446 fullDuplex
= ( linkMode
< 2 ) ? false : true;
1447 mediumType
= kIOMediumEthernet10BaseT
;
1449 else if ( linkMode
< 6 )
1452 fullDuplex
= ( linkMode
< 5 ) ? false : true;
1453 mediumType
= kIOMediumEthernet100BaseTX
;
1459 mediumType
= kIOMediumEthernet1000BaseTX
;
1463 if ( fullDuplex
!= isFullDuplex
)
1465 setDuplexMode( fullDuplex
);
1468 if ( ready
== true )
1473 if ( linkSpeed
!= 0 )
1475 mediumType
|= (fullDuplex
== true) ?
1476 kIOMediumOptionFullDuplex
:
1477 kIOMediumOptionHalfDuplex
;
1480 medium
= IONetworkMedium::getMediumWithType( mediumDict
,
1483 setLinkStatus( kIONetworkLinkActive
| kIONetworkLinkValid
,
1485 linkSpeed
* 1000000 );
1487 IOLog( "Ethernet(UniN): Link is up at %ld Mbps - %s Duplex\n\r",
1489 (fullDuplex
) ? "Full" : "Half" );
1491 linkStatusPrev
= kLinkStatusUp
;
1495 if ( (linkStatusPrev
== kLinkStatusUp
) ||
1496 (linkStatusPrev
== kLinkStatusUnknown
) )
1500 medium
= IONetworkMedium::getMediumWithType( mediumDict
,
1503 setLinkStatus( kIONetworkLinkValid
,
1507 if ( linkStatusPrev
!= kLinkStatusUnknown
)
1509 IOLog( "Ethernet(UniN): Link is down.\n\r" );
1514 if ( txCommandHead
!= txCommandTail
)
1518 txCommandHead
= READ_REGISTER( TxCompletion
);
1519 txCommandTail
= txCommandHead
;
1523 linkStatusPrev
= kLinkStatusDown
;
1526 phyStatusPrev
= phyStatus
;
1532 /*-------------------------------------------------------------------------
1536 *-------------------------------------------------------------------------*/
1538 IOReturn
UniNEnet::getHardwareAddress(IOEthernetAddress
*ea
)
1545 macEntry
= OSDynamicCast( OSData
, nub
->getProperty( "local-mac-address" ) );
1546 if ( macEntry
== 0 )
1548 return kIOReturnError
;
1551 macAddress
= (UInt8
*)macEntry
->getBytesNoCopy();
1552 if ( macAddress
== 0 )
1554 return kIOReturnError
;
1557 len
= macEntry
->getLength();
1560 return kIOReturnError
;
1563 for (i
= 0; i
< sizeof(*ea
); i
++)
1565 ea
->bytes
[i
] = macAddress
[i
];
1567 return kIOReturnSuccess
;
1570 /*-------------------------------------------------------------------------
1574 *-------------------------------------------------------------------------*/
1576 #define ENET_CRCPOLY 0x04c11db7
1578 static UInt32
crc416(UInt32 current
, UInt16 nxtval
)
1580 register UInt32 counter
;
1581 register int highCRCBitSet
, lowDataBitSet
;
1584 nxtval
= ((nxtval
& 0x00FF) << 8) | (nxtval
>> 8);
1586 /* Compute bit-by-bit */
1587 for (counter
= 0; counter
!= 16; ++counter
)
1588 { /* is high CRC bit set? */
1589 if ((current
& 0x80000000) == 0)
1594 current
= current
<< 1;
1596 if ((nxtval
& 0x0001) == 0)
1601 nxtval
= nxtval
>> 1;
1604 if (highCRCBitSet
^ lowDataBitSet
)
1605 current
= current
^ ENET_CRCPOLY
;
1610 /*-------------------------------------------------------------------------
1614 *-------------------------------------------------------------------------*/
1616 static UInt32
mace_crc(UInt16
*address
)
1618 register UInt32 newcrc
;
1620 newcrc
= crc416(0xffffffff, *address
); /* address bits 47 - 32 */
1621 newcrc
= crc416(newcrc
, address
[1]); /* address bits 31 - 16 */
1622 newcrc
= crc416(newcrc
, address
[2]); /* address bits 15 - 0 */
1627 /*-------------------------------------------------------------------------
1631 *-------------------------------------------------------------------------*/
1634 * Add requested mcast addr to UniN's hash table filter.
1637 void UniNEnet::addToHashTableMask(UInt8
*addr
)
1643 j
= mace_crc((UInt16
*)addr
) & 0xFF; /* Big-endian alert! */
1645 for ( crcBitIndex
= i
= 0; i
< 8; i
++ )
1648 crcBitIndex
|= (j
& 0x80);
1652 crcBitIndex
^= 0xFF;
1654 if (hashTableUseCount
[crcBitIndex
]++)
1655 return; /* This bit is already set */
1656 mask
= crcBitIndex
% 16;
1658 hashTableMask
[crcBitIndex
/16] |= mask
;
1661 /*-------------------------------------------------------------------------
1665 *-------------------------------------------------------------------------*/
1667 void UniNEnet::resetHashTableMask()
1669 bzero(hashTableUseCount
, sizeof(hashTableUseCount
));
1670 bzero(hashTableMask
, sizeof(hashTableMask
));
1673 /*-------------------------------------------------------------------------
1677 *-------------------------------------------------------------------------*/
1680 * Sync the adapter with the software copy of the multicast mask
1681 * (logical address filter).
1683 void UniNEnet::updateHashTableMask()
1687 rxMacConfigReg
= READ_REGISTER( RxMACConfiguration
);
1688 WRITE_REGISTER( RxMACConfiguration
,
1689 rxMacConfigReg
& ~(kRxMACConfiguration_Rx_Mac_Enable
1690 | kRxMACConfiguration_Hash_Filter_Enable
) );
1692 while ( READ_REGISTER( RxMACConfiguration
) & (kRxMACConfiguration_Rx_Mac_Enable
1693 | kRxMACConfiguration_Hash_Filter_Enable
) )
1696 for ( i
= 0; i
< 16; i
++ )
1697 WRITE_REGISTER( HashTable
[ i
], hashTableMask
[ 15 - i
] );
1699 rxMacConfigReg
|= kRxMACConfiguration_Hash_Filter_Enable
;
1700 WRITE_REGISTER( RxMACConfiguration
, rxMacConfigReg
);