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 by Apple Computer, Inc., All rights reserved.
25 * Implementation for hardware dependent (relatively) code
26 * for the BMac Ethernet controller.
32 #include <IOKit/assert.h>
33 #include <IOKit/system.h>
35 #include "BMacEnetPrivate.h"
36 #include <IOKit/IOLib.h>
38 /*****************************************************************************
43 typedef unsigned long long ns_time_t
; /* nanoseconds! */
45 #define NSEC_PER_SEC 1000000000
48 _IOGetTimestamp(ns_time_t
*nsp
)
53 *nsp
= ((ns_time_t
)now
.tv_sec
* NSEC_PER_SEC
) + now
.tv_nsec
;
57 * Find a physical address (if any) for the specified virtual address.
59 * Note: what about vm_offset_t kvtophys(vm_offset_t va)
61 static IOReturn
_IOPhysicalFromVirtual(
62 vm_address_t virtualAddress
,
63 unsigned *physicalAddress
)
65 *physicalAddress
= pmap_extract(kernel_pmap
, virtualAddress
);
66 if(*physicalAddress
== 0) {
67 return kIOReturnBadArgument
;
70 return kIOReturnSuccess
;
74 /****************************************************************************/
77 extern kern_return_t
kmem_alloc_wired();
79 static IODBDMADescriptor dbdmaCmd_Nop
;
80 static IODBDMADescriptor dbdmaCmd_NopWInt
;
81 static IODBDMADescriptor dbdmaCmd_LoadInt
;
82 static IODBDMADescriptor dbdmaCmd_LoadIntWInt
;
83 static IODBDMADescriptor dbdmaCmd_Stop
;
84 static IODBDMADescriptor dbdmaCmd_Branch
;
86 static u_int8_t
reverseBitOrder(u_int8_t data
)
91 for ( i
=0; i
< 8; i
++ )
94 if (data
& 1) val
|= 1;
101 * Function: IOMallocPage
104 * Returns a pointer to a page-aligned memory block of size >= PAGE_SIZE
107 * Actual pointer and size of block returned in actual_ptr and actual_size.
108 * Use these as arguments to kfree: kfree(*actual_ptr, *actual_size);
111 IOMallocPage(int request_size
, void ** actual_ptr
, u_int
* actual_size
)
115 *actual_size
= round_page(request_size
) + PAGE_SIZE
;
116 mem_ptr
= IOMalloc(*actual_size
);
119 *actual_ptr
= mem_ptr
;
120 return ((void *)round_page(mem_ptr
));
126 bool BMacEnet::_allocateMemory()
129 unsigned char * virtAddr
;
135 * Calculate total space for DMA channel commands
137 dbdmaSize
= round_page(
138 RX_RING_LENGTH
* sizeof(enet_dma_cmd_t
) +
139 TX_RING_LENGTH
* sizeof(enet_txdma_cmd_t
) +
140 2 * sizeof(IODBDMADescriptor
) );
143 * Allocate required memory
145 dmaMemory
.size
= dbdmaSize
;
146 dmaMemory
.ptr
= (void *)IOMallocPage(
152 dmaCommands
= (unsigned char *) dmaMemory
.ptr
;
153 if (dmaCommands
== NULL
) {
154 IOLog( "Ethernet(BMac): Cant allocate channel DBDMA commands\n\r" );
159 * If we needed more than one page, then make sure we received
162 n
= (dbdmaSize
- PAGE_SIZE
) / PAGE_SIZE
;
163 _IOPhysicalFromVirtual( (vm_address_t
) dmaCommands
, &physBase
);
165 virtAddr
= (unsigned char *) dmaCommands
;
166 for( i
=0; i
< n
; i
++, virtAddr
+= PAGE_SIZE
)
168 _IOPhysicalFromVirtual( (vm_address_t
) virtAddr
, &physAddr
);
169 if (physAddr
!= (physBase
+ i
* PAGE_SIZE
) )
171 IOLog( "Ethernet(BMac): Cannot allocate contiguous memory"
172 " for DBDMA commands\n\r" );
178 * Setup the receive ring pointers
180 rxDMACommands
= (enet_dma_cmd_t
*)dmaCommands
;
181 rxMaxCommand
= RX_RING_LENGTH
;
184 * Setup the transmit ring pointers
186 txDMACommands
= (enet_txdma_cmd_t
*)(dmaCommands
+
187 RX_RING_LENGTH
* sizeof(enet_dma_cmd_t
) + sizeof(IODBDMADescriptor
));
188 txMaxCommand
= TX_RING_LENGTH
;
191 * Setup pre-initialized DBDMA commands
193 IOMakeDBDMADescriptor( (&dbdmaCmd_Nop
),
202 IOMakeDBDMADescriptor( (&dbdmaCmd_NopWInt
),
211 UInt32 ioBaseEnetPhys
= maps
[MEMORY_MAP_ENET_INDEX
]->getPhysicalAddress();
213 IOMakeDBDMADescriptor( (&dbdmaCmd_LoadInt
),
220 ((int)ioBaseEnetPhys
+ kSTAT
) );
222 IOMakeDBDMADescriptor( (&dbdmaCmd_LoadIntWInt
),
229 ((int)ioBaseEnetPhys
+ kSTAT
) );
231 IOMakeDBDMADescriptor( (&dbdmaCmd_Stop
),
240 IOMakeDBDMADescriptor( (&dbdmaCmd_Branch
),
252 /*-------------------------------------------------------------------------
254 * Setup the Transmit Ring
255 * -----------------------
256 * Each transmit ring entry consists of two words to transmit data from buffer
257 * segments (possibly) spanning a page boundary. This is followed by two DMA
258 * commands which read transmit frame status and interrupt status from the Bmac
259 * chip. The last DMA command in each transmit ring entry generates a host
260 * interrupt. The last entry in the ring is followed by a DMA branch to the
262 *-------------------------------------------------------------------------*/
264 bool BMacEnet::_initTxRing()
268 IODBDMADescriptor dbdmaCmd
, dbdmaCmdInt
;
271 * Clear mbufs from TX ring.
273 for ( i
= 0; i
< txMaxCommand
; i
++ )
277 freePacket( txMbuf
[i
] );
283 * Clear the transmit DMA command memory
285 bzero( (void *)txDMACommands
, sizeof(enet_txdma_cmd_t
) * txMaxCommand
);
290 * DMA Channel commands 2 are the same for all DBDMA entries on transmit.
291 * Initialize them now.
294 dbdmaCmd
= ( chipId
>= kCHIPID_PaddingtonXmitStreaming
) ? dbdmaCmd_Nop
: dbdmaCmd_LoadInt
;
295 dbdmaCmdInt
= ( chipId
>= kCHIPID_PaddingtonXmitStreaming
) ? dbdmaCmd_NopWInt
: dbdmaCmd_LoadIntWInt
;
297 for( i
=0; i
< txMaxCommand
; i
++ )
299 txDMACommands
[i
].desc_seg
[2] = ( (i
+1) % TX_PKTS_PER_INT
) ? dbdmaCmd
: dbdmaCmdInt
;
303 * Put a DMA Branch command after the last entry in the transmit ring.
304 * Set the branch address to the physical address of the start of the
307 txDMACommands
[txMaxCommand
].desc_seg
[0] = dbdmaCmd_Branch
;
309 kr
= _IOPhysicalFromVirtual( (vm_address_t
) txDMACommands
,
310 (u_int32_t
*)&txDMACommandsPhys
);
311 if ( kr
!= kIOReturnSuccess
)
313 IOLog( "Ethernet(BMac): Bad DBDMA command buf - %08x\n\r",
314 (u_int32_t
)txDMACommands
);
316 IOSetCCCmdDep( &txDMACommands
[txMaxCommand
].desc_seg
[0],
320 * Set the Transmit DMA Channel pointer to the first entry in the
323 IOSetDBDMACommandPtr( ioBaseEnetTxDMA
, txDMACommandsPhys
);
328 /*-------------------------------------------------------------------------
330 * Setup the Receive ring
331 * ----------------------
332 * Each receive ring entry consists of two DMA commands to receive data
333 * into a network buffer (possibly) spanning a page boundary. The second
334 * DMA command in each entry generates a host interrupt.
335 * The last entry in the ring is followed by a DMA branch to the first
338 *-------------------------------------------------------------------------*/
340 bool BMacEnet::_initRxRing()
347 * Clear the receive DMA command memory
349 bzero((void *)rxDMACommands
, sizeof(enet_dma_cmd_t
) * rxMaxCommand
);
351 kr
= _IOPhysicalFromVirtual( (vm_address_t
) rxDMACommands
,
352 (u_int32_t
*)&rxDMACommandsPhys
);
353 if ( kr
!= kIOReturnSuccess
)
355 IOLog( "Ethernet(BMac): Bad DBDMA command buf - %08x\n\r",
356 (u_int32_t
)rxDMACommands
);
361 * Allocate a receive buffer for each entry in the Receive ring
363 for (i
= 0; i
< rxMaxCommand
-1; i
++)
365 if (rxMbuf
[i
] == NULL
)
367 rxMbuf
[i
] = allocatePacket(NETWORK_BUFSIZE
);
370 IOLog("Ethernet(BMac): allocatePacket failed\n");
376 * Set the DMA commands for the ring entry to transfer data to the
379 status
= _updateDescriptorFromMbuf(rxMbuf
[i
], &rxDMACommands
[i
], true);
382 IOLog("Ethernet(BMac): cannot map mbuf to physical memory in"
389 * Set the receive queue head to point to the first entry in the ring.
390 * Set the receive queue tail to point to a DMA Stop command after the
396 rxDMACommands
[i
].desc_seg
[0] = dbdmaCmd_Stop
;
397 rxDMACommands
[i
].desc_seg
[1] = dbdmaCmd_Nop
;
400 * Setup a DMA branch command after the stop command
403 rxDMACommands
[i
].desc_seg
[0] = dbdmaCmd_Branch
;
405 IOSetCCCmdDep( &rxDMACommands
[i
].desc_seg
[0], rxDMACommandsPhys
);
408 * Set DMA command pointer to first receive entry
410 IOSetDBDMACommandPtr (ioBaseEnetRxDMA
, rxDMACommandsPhys
);
415 /*-------------------------------------------------------------------------
419 *-------------------------------------------------------------------------*/
421 void BMacEnet::_startChip()
425 IODBDMAContinue( ioBaseEnetRxDMA
);
427 // turn on rx plus any other bits already on (promiscuous possibly)
428 oldConfig
= ReadBigMacRegister(ioBaseEnet
, kRXCFG
);
429 WriteBigMacRegister(ioBaseEnet
, kRXCFG
, oldConfig
| kRxMACEnable
);
431 oldConfig
= ReadBigMacRegister(ioBaseEnet
, kTXCFG
);
432 WriteBigMacRegister(ioBaseEnet
, kTXCFG
, oldConfig
| kTxMACEnable
);
435 /*-------------------------------------------------------------------------
439 *-------------------------------------------------------------------------*/
441 void BMacEnet::_resetChip()
443 volatile u_int32_t
*heathrowFCR
;
447 IODBDMAReset( ioBaseEnetRxDMA
);
448 IODBDMAReset( ioBaseEnetTxDMA
);
450 IOSetDBDMAWaitSelect( ioBaseEnetTxDMA
,
451 IOSetDBDMAChannelControlBits( kdbdmaS5
) );
453 IOSetDBDMABranchSelect( ioBaseEnetRxDMA
,
454 IOSetDBDMAChannelControlBits( kdbdmaS6
) );
456 IOSetDBDMAInterruptSelect( ioBaseEnetRxDMA
,
457 IOSetDBDMAChannelControlBits( kdbdmaS6
) );
459 heathrowFCR
= (u_int32_t
*)((u_int8_t
*)ioBaseHeathrow
+ kHeathrowFCR
);
461 fcrValue
= *heathrowFCR
;
464 fcrValue
= OSReadSwapInt32( &fcrValue
, 0 );
467 * Enable the ethernet transceiver/clocks
469 fcrValue
|= kEnetEnabledBits
;
470 fcrValue
&= ~kResetEnetCell
;
472 *heathrowFCR
= OSReadSwapInt32( &fcrValue
, 0 );
477 * Determine if PHY chip is configured. Reset and enable it (if present).
482 if ( miiFindPHY(&phyId
) == true )
486 pPhyType
= (u_int16_t
*)&phyType
;
487 miiReadWord(pPhyType
, MII_ID0
, phyId
);
488 miiReadWord(pPhyType
+1, MII_ID1
, phyId
);
490 if ( (phyType
& MII_ST10040_MASK
) == MII_ST10040_ID
)
492 phyMIIDelay
= MII_ST10040_DELAY
;
494 else if ( (phyType
& MII_DP83843_MASK
) == MII_DP83843_ID
)
496 phyMIIDelay
= MII_DP83843_DELAY
;
499 kprintf("Ethernet(BMac): PHY id = %d\n", phyId
);
504 * Reset the reset the ethernet cell
506 fcrValue
|= kResetEnetCell
;
507 *heathrowFCR
= OSReadSwapInt32( &fcrValue
, 0 );
511 fcrValue
&= ~kResetEnetCell
;
512 *heathrowFCR
= OSReadSwapInt32( &fcrValue
, 0 );
516 chipId
= ReadBigMacRegister(ioBaseEnet
, kCHIPID
) & 0xFF;
519 /*-------------------------------------------------------------------------
523 *-------------------------------------------------------------------------*/
525 bool BMacEnet::_initChip()
527 volatile u_int16_t regValue
;
531 WriteBigMacRegister(ioBaseEnet
, kTXRST
, kTxResetBit
);
535 // wait for reset to clear..acknowledge
536 regValue
= ReadBigMacRegister(ioBaseEnet
, kTXRST
);
538 while( regValue
& kTxResetBit
);
540 WriteBigMacRegister(ioBaseEnet
, kRXRST
, kRxResetValue
);
544 WriteBigMacRegister(ioBaseEnet
, kXCVRIF
,
545 kClkBit
| kSerialMode
| kCOLActiveLow
);
548 _IOGetTimestamp(&timeStamp
);
549 WriteBigMacRegister(ioBaseEnet
, kRSEED
, (u_int16_t
) timeStamp
);
551 regValue
= ReadBigMacRegister(ioBaseEnet
, kXIFC
);
552 regValue
|= kTxOutputEnable
;
553 WriteBigMacRegister(ioBaseEnet
, kXIFC
, regValue
);
555 ReadBigMacRegister(ioBaseEnet
, kPAREG
);
557 // set collision counters to 0
558 WriteBigMacRegister(ioBaseEnet
, kNCCNT
, 0);
559 WriteBigMacRegister(ioBaseEnet
, kNTCNT
, 0);
560 WriteBigMacRegister(ioBaseEnet
, kEXCNT
, 0);
561 WriteBigMacRegister(ioBaseEnet
, kLTCNT
, 0);
563 // set rx counters to 0
564 WriteBigMacRegister(ioBaseEnet
, kFRCNT
, 0);
565 WriteBigMacRegister(ioBaseEnet
, kLECNT
, 0);
566 WriteBigMacRegister(ioBaseEnet
, kAECNT
, 0);
567 WriteBigMacRegister(ioBaseEnet
, kFECNT
, 0);
568 WriteBigMacRegister(ioBaseEnet
, kRXCV
, 0);
570 // set tx fifo information
571 // 255 octets before tx starts
572 WriteBigMacRegister(ioBaseEnet
, kTXTH
, 0xff);
574 // first disable txFIFO
575 WriteBigMacRegister(ioBaseEnet
, kTXFIFOCSR
, 0);
576 WriteBigMacRegister(ioBaseEnet
, kTXFIFOCSR
, kTxFIFOEnable
);
578 // set rx fifo information
579 // first disable rxFIFO
580 WriteBigMacRegister(ioBaseEnet
, kRXFIFOCSR
, 0);
581 WriteBigMacRegister(ioBaseEnet
, kRXFIFOCSR
, kRxFIFOEnable
);
583 // kTxNeverGiveUp maybe later
584 //WriteBigMacRegister(ioBaseEnet, kTXCFG, kTxMACEnable);
585 ReadBigMacRegister(ioBaseEnet
, kSTAT
); // read it just to clear it
587 // zero out the chip Hash Filter registers
588 WriteBigMacRegister(ioBaseEnet
, kHASH3
, hashTableMask
[0]); // bits 15 - 0
589 WriteBigMacRegister(ioBaseEnet
, kHASH2
, hashTableMask
[1]); // bits 31 - 16
590 WriteBigMacRegister(ioBaseEnet
, kHASH1
, hashTableMask
[2]); // bits 47 - 32
591 WriteBigMacRegister(ioBaseEnet
, kHASH0
, hashTableMask
[3]); // bits 63 - 48
593 pWord16
= (u_int16_t
*)&myAddress
.bytes
[0];
594 WriteBigMacRegister(ioBaseEnet
, kMADD0
, *pWord16
++);
595 WriteBigMacRegister(ioBaseEnet
, kMADD1
, *pWord16
++);
596 WriteBigMacRegister(ioBaseEnet
, kMADD2
, *pWord16
);
598 WriteBigMacRegister(ioBaseEnet
, kRXCFG
,
599 kRxCRCEnable
| kRxHashFilterEnable
| kRxRejectOwnPackets
);
604 /*-------------------------------------------------------------------------
608 *-------------------------------------------------------------------------*/
610 void BMacEnet::_disableAdapterInterrupts()
612 WriteBigMacRegister( ioBaseEnet
, kINTDISABLE
, kNoEventsMask
);
615 /*-------------------------------------------------------------------------
619 *-------------------------------------------------------------------------*/
621 void BMacEnet::_enableAdapterInterrupts()
623 WriteBigMacRegister( ioBaseEnet
,
625 ( chipId
>= kCHIPID_PaddingtonXmitStreaming
) ?
626 kNoEventsMask
: kNormalIntEvents
);
629 /*-------------------------------------------------------------------------
633 *-------------------------------------------------------------------------*/
635 void BMacEnet::_setDuplexMode(bool duplexMode
)
639 isFullDuplex
= duplexMode
;
641 txCFGVal
= ReadBigMacRegister( ioBaseEnet
, kTXCFG
);
643 WriteBigMacRegister( ioBaseEnet
, kTXCFG
, txCFGVal
& ~kTxMACEnable
);
644 while( ReadBigMacRegister(ioBaseEnet
, kTXCFG
) & kTxMACEnable
)
649 txCFGVal
|= (kTxIgnoreCollision
| kTxFullDuplex
);
653 txCFGVal
&= ~(kTxIgnoreCollision
| kTxFullDuplex
);
656 WriteBigMacRegister( ioBaseEnet
, kTXCFG
, txCFGVal
);
659 /*-------------------------------------------------------------------------
663 *-------------------------------------------------------------------------*/
665 void BMacEnet::_restartTransmitter()
670 * Shutdown DMA channel
675 * Get the silicon's attention
677 WriteBigMacRegister( ioBaseEnet
, kTXFIFOCSR
, 0 );
678 WriteBigMacRegister( ioBaseEnet
, kTXFIFOCSR
, kTxFIFOEnable
);
680 ReadBigMacRegister( ioBaseEnet
, kSTAT
);
682 regValue
= ReadBigMacRegister(ioBaseEnet
, kTXCFG
);
683 WriteBigMacRegister(ioBaseEnet
, kTXCFG
, regValue
| kTxMACEnable
);
686 * Restart transmit DMA
688 IODBDMAContinue( ioBaseEnetTxDMA
);
691 /*-------------------------------------------------------------------------
695 *-------------------------------------------------------------------------*/
697 void BMacEnet::_restartReceiver()
702 * Shutdown DMA channel
707 * Get the silicon's attention
709 WriteBigMacRegister( ioBaseEnet
, kRXFIFOCSR
, 0 );
710 WriteBigMacRegister( ioBaseEnet
, kRXFIFOCSR
, kRxFIFOEnable
);
712 oldConfig
= ReadBigMacRegister(ioBaseEnet
, kRXCFG
);
713 WriteBigMacRegister(ioBaseEnet
, kRXCFG
, oldConfig
| kRxMACEnable
);
716 * Restart receive DMA
718 IODBDMAContinue( ioBaseEnetRxDMA
);
721 /*-------------------------------------------------------------------------
723 * Orderly stop of receive DMA.
726 *-------------------------------------------------------------------------*/
728 void BMacEnet::_stopReceiveDMA()
734 * Stop the receiver and allow any frame receive in progress to complete.
736 rxCFGVal
= ReadBigMacRegister(ioBaseEnet
, kRXCFG
);
737 WriteBigMacRegister(ioBaseEnet
, kRXCFG
, rxCFGVal
& ~kRxMACEnable
);
738 IODelay( RECEIVE_QUIESCE_uS
);
740 IODBDMAReset( ioBaseEnetRxDMA
);
742 dmaCmdPtr
= rxDMACommandsPhys
+ rxCommandHead
* sizeof(enet_dma_cmd_t
);
743 IOSetDBDMACommandPtr( ioBaseEnetRxDMA
, dmaCmdPtr
);
746 /*-------------------------------------------------------------------------
750 *-------------------------------------------------------------------------*/
752 void BMacEnet::_stopTransmitDMA()
758 * Stop the transmitter and allow any frame transmit in progress to abort
760 txCFGVal
= ReadBigMacRegister(ioBaseEnet
, kTXCFG
);
761 WriteBigMacRegister(ioBaseEnet
, kTXCFG
, txCFGVal
& ~kTxMACEnable
);
763 IODelay( TRANSMIT_QUIESCE_uS
);
765 IODBDMAReset( ioBaseEnetTxDMA
);
767 dmaCmdPtr
= txDMACommandsPhys
+ txCommandHead
* sizeof(enet_txdma_cmd_t
);
768 IOSetDBDMACommandPtr( ioBaseEnetTxDMA
, dmaCmdPtr
);
771 /*-------------------------------------------------------------------------
775 *-------------------------------------------------------------------------*/
777 bool BMacEnet::_transmitPacket(struct mbuf
*packet
)
779 enet_dma_cmd_t tmpCommand
;
783 * Check for room on the transmit ring. There should always be space
784 * since it is the responsibility of the caller to verify this before
785 * calling _transmitPacket.
787 * Get a copy of the DMA transfer commands in a temporary buffer.
788 * The new DMA command is written into the channel program so that the
789 * command word for the old Stop command is overwritten last. This prevents
790 * the DMA engine from executing a partially written channel command.
792 i
= txCommandTail
+ 1;
793 if ( i
>= txMaxCommand
) i
= 0;
795 if ( (i
== txCommandHead
) ||
796 !_updateDescriptorFromMbuf(packet
, &tmpCommand
, false) )
798 IOLog("Ethernet(BMac): Freeing transmit packet eh?\n\r");
799 if (packet
!= txDebuggerPkt
)
805 * txCommandTail points to the current DMA Stop command for the channel.
806 * We are now creating a new DMA Stop command in the next slot in the
807 * transmit ring. The previous DMA Stop command will be overwritten with
808 * the DMA commands to transfer the new mbuf.
810 txDMACommands
[i
].desc_seg
[0] = dbdmaCmd_Stop
;
811 txDMACommands
[i
].desc_seg
[1] = dbdmaCmd_Nop
;
813 bcopy( ((u_int32_t
*)&tmpCommand
)+1,
814 ((u_int32_t
*)&txDMACommands
[txCommandTail
])+1,
815 sizeof(enet_dma_cmd_t
)-sizeof(u_int32_t
) );
817 txMbuf
[txCommandTail
] = packet
;
818 txDMACommands
[txCommandTail
].desc_seg
[0].operation
=
819 tmpCommand
.desc_seg
[0].operation
;
822 * Set the transmit tail to the new stop command.
827 * Tap the DMA channel to wake it up
829 IODBDMAContinue( ioBaseEnetTxDMA
);
834 /*-------------------------------------------------------------------------
837 * This routine runs the receiver in polled-mode (yuk!) for the kernel debugger.
839 * The _receivePackets allocate NetBufs and pass them up the stack. The kernel
840 * debugger interface passes a buffer into us. To reconsile the two interfaces,
841 * we allow the receive routine to continue to allocate its own buffers and
842 * transfer any received data to the passed-in buffer. This is handled by
843 * _receivePacket calling _packetToDebugger.
844 *-------------------------------------------------------------------------*/
846 void BMacEnet::_receivePacket(void *pkt
, unsigned int *pkt_len
,
847 unsigned int timeout
)
850 ns_time_t currentTime
;
851 u_int32_t elapsedTimeMS
;
853 if (!ready
|| !pkt
|| !pkt_len
)
861 _IOGetTimestamp(&startTime
);
864 _receivePackets(true);
865 _IOGetTimestamp(¤tTime
);
866 elapsedTimeMS
= (currentTime
- startTime
) / (1000*1000);
868 while ( (debuggerPktSize
== 0) && (elapsedTimeMS
< timeout
) );
870 *pkt_len
= debuggerPktSize
;
873 /*-------------------------------------------------------------------------
876 * This is called by _receivePackets when we are polling for kernel debugger
877 * packets. It copies the NetBuf contents to the buffer passed by the debugger.
878 * It also sets the var debuggerPktSize which will break the polling loop.
879 *-------------------------------------------------------------------------*/
881 void BMacEnet::_packetToDebugger(struct mbuf
* packet
, u_int size
)
883 debuggerPktSize
= size
;
884 bcopy( mtod(packet
, char *), debuggerPkt
, size
);
887 /*-------------------------------------------------------------------------
891 * This routine runs the transmitter in polled-mode (yuk!) for the kernel debugger.
893 *-------------------------------------------------------------------------*/
895 void BMacEnet::_sendPacket(void *pkt
, unsigned int pkt_len
)
898 ns_time_t currentTime
;
899 u_int32_t elapsedTimeMS
;
901 if (!ready
|| !pkt
|| (pkt_len
> ETHERMAXPACKET
))
905 * Wait for the transmit ring to empty
907 _IOGetTimestamp(&startTime
);
910 _debugTransmitInterruptOccurred();
911 _IOGetTimestamp(¤tTime
);
912 elapsedTimeMS
= (currentTime
- startTime
) / (1000*1000);
914 while ( (txCommandHead
!= txCommandTail
) &&
915 (elapsedTimeMS
< TX_KDB_TIMEOUT
) );
917 if ( txCommandHead
!= txCommandTail
)
919 IOLog( "Ethernet(BMac): Polled tranmit timeout - 1\n\r");
924 * Allocate a NetBuf and copy the debugger transmit data into it.
926 * jliu - no allocation, just recycle the same buffer dedicated to
929 txDebuggerPkt
->m_next
= 0;
930 txDebuggerPkt
->m_data
= (caddr_t
) pkt
;
931 txDebuggerPkt
->m_pkthdr
.len
= txDebuggerPkt
->m_len
= pkt_len
;
934 * Send the debugger packet. txDebuggerPkt must not be freed by
935 * the transmit routine.
937 _transmitPacket(txDebuggerPkt
);
940 * Poll waiting for the transmit ring to empty again
944 _debugTransmitInterruptOccurred();
945 _IOGetTimestamp(¤tTime
);
946 elapsedTimeMS
= (currentTime
- startTime
) / (1000*1000);
948 while ( (txCommandHead
!= txCommandTail
) &&
949 (elapsedTimeMS
< TX_KDB_TIMEOUT
) );
951 if ( txCommandHead
!= txCommandTail
)
953 IOLog( "Ethernet(BMac): Polled tranmit timeout - 2\n\r");
959 /*-------------------------------------------------------------------------
962 * The BMac receiver seems to be locked until we send our first packet.
964 *-------------------------------------------------------------------------*/
965 void BMacEnet::_sendDummyPacket()
970 IOEthernetAddress enet_addr
[2];
973 bzero( &dummyPacket
, sizeof(dummyPacket
) );
974 dummyPacket
.enet_addr
[0] = myAddress
;
975 dummyPacket
.enet_addr
[1] = myAddress
;
976 _sendPacket((void *)dummyPacket
.bytes
, sizeof(dummyPacket
));
980 /*-------------------------------------------------------------------------
984 *-------------------------------------------------------------------------*/
986 bool BMacEnet::_receiveInterruptOccurred()
988 return _receivePackets(false);
991 /*-------------------------------------------------------------------------
992 * Work around a hardware bug where the controller will receive
993 * unicast packets not directed to the station. The hardware is
994 * erroneously using the hash table to qualify the unicast address.
995 * This routine will check that the packet is unicast, and if so,
996 * makes sure that the unicast address matches the station's address.
997 * Thus function returns true if the packet should be rejected.
998 *-------------------------------------------------------------------------*/
1000 bool BMacEnet::_rejectBadUnicastPacket(ether_header_t
* etherHeader
)
1002 bool rejectPacket
= false;
1004 if ( useUnicastFilter
&& (isPromiscuous
== false) &&
1005 (etherHeader
->ether_dhost
[EA_GROUP_BYTE
] & EA_GROUP_BIT
) == 0) {
1007 // Destination Ethernet address is not multicast nor broadcast.
1008 // Then it must be addresses to the station MAC address,
1009 // otherwise reject the packet.
1011 if (bcmp(etherHeader
->ether_dhost
, &myAddress
, NUM_EN_ADDR_BYTES
) != 0)
1012 rejectPacket
= true;
1015 return rejectPacket
;
1018 /*-------------------------------------------------------------------------
1022 *-------------------------------------------------------------------------*/
1024 bool BMacEnet::_receivePackets(bool fDebugger
)
1026 enet_dma_cmd_t tmpCommand
;
1027 struct mbuf
* packet
;
1028 u_int32_t i
, j
, last
;
1029 int receivedFrameSize
= 0;
1030 u_int32_t dmaCount
[2], dmaResid
[2], dmaStatus
[2];
1031 u_int32_t dmaChnlStatus
;
1032 u_int16_t rxPktStatus
= 0;
1033 u_int32_t badFrameCount
;
1036 bool useNetif
= !fDebugger
&& netifEnabled
;
1037 bool doFlushQueue
= false;
1039 static const u_int32_t lastResetValue
= (u_int32_t
)(-1);
1041 last
= lastResetValue
;
1049 * Collect the DMA residual counts/status for the two
1052 for ( j
= 0; j
< 2; j
++ )
1054 dmaResid
[j
] = IOGetCCResult( &rxDMACommands
[i
].desc_seg
[j
] );
1055 dmaStatus
[j
] = dmaResid
[j
] >> 16;
1056 dmaResid
[j
] &= 0x0000ffff;
1057 dmaCount
[j
] = IOGetCCOperation( &rxDMACommands
[i
].desc_seg
[j
] )
1058 & kdbdmaReqCountMask
;
1062 IOLog("Ethernet(BMac): Rx NetBuf[%2d] = %08x Resid[0] = %04x Status[0] = %04x Resid[1] = %04x Status[1] = %04x\n\r",
1063 i
, (int)nb_map(rxNetbuf
[i
]), dmaResid
[0], dmaStatus
[0], dmaResid
[1], dmaStatus
[1] );
1067 * If the current entry has not been written, then stop at this entry
1069 if ( !((dmaStatus
[0] & kdbdmaBt
) || (dmaStatus
[1] & kdbdmaActive
)) )
1075 * The BMac Ethernet controller appends two bytes to each receive
1076 * buffer containing the buffer
1077 * size and receive frame status.
1078 * We locate these bytes by using the DMA residual counts.
1080 receivedFrameSize
= dmaCount
[0] - dmaResid
[0] + dmaCount
[1] -
1081 ((dmaStatus
[0] & kdbdmaBt
) ? dmaCount
[1] : dmaResid
[1]);
1083 if ( ( receivedFrameSize
>= 2 ) &&
1084 ( receivedFrameSize
<= NETWORK_BUFSIZE
) )
1087 * Get the receive frame size as reported by the BMac controller
1089 rxPktStatus
= *(u_int16_t
*)(mtod(rxMbuf
[i
], u_int32_t
) +
1090 receivedFrameSize
- 2);
1091 receivedFrameSize
= rxPktStatus
& kRxLengthMask
;
1095 * Reject packets that are runts or that have other mutations.
1097 if ( receivedFrameSize
< (ETHERMINPACKET
- ETHERCRC
) ||
1098 receivedFrameSize
> (ETHERMAXPACKET
+ ETHERCRC
) ||
1099 rxPktStatus
& kRxAbortBit
||
1100 _rejectBadUnicastPacket(mtod(rxMbuf
[i
], ether_header_t
*))
1103 if (useNetif
) netStats
->inputErrors
++;
1106 else if ( useNetif
== false )
1109 * Always reuse packets in debugger mode. We also refuse to
1110 * pass anything up the stack unless the driver is open. The
1111 * hardware is enabled before the stack has opened us, to
1112 * allow earlier debug interface registration. But we must
1113 * not pass any packets up.
1117 _packetToDebugger(rxMbuf
[i
], receivedFrameSize
);
1121 * Before we pass this packet up the networking stack. Make sure we
1122 * can get a replacement. Otherwise, hold on to the current packet and
1123 * increment the input error count.
1129 if ( reusePkt
== false )
1133 packet
= replaceOrCopyPacket(&rxMbuf
[i
], receivedFrameSize
,
1138 if (packet
&& replaced
)
1140 status
= _updateDescriptorFromMbuf(rxMbuf
[i
],
1141 &rxDMACommands
[i
], true);
1149 // Assume descriptor has not been corrupted.
1150 freePacket(rxMbuf
[i
]); // release new packet.
1151 rxMbuf
[i
] = packet
; // get the old packet back.
1152 packet
= 0; // pass up nothing.
1153 IOLog("Ethernet(BMac): _updateDescriptorFromMbuf error\n");
1158 netStats
->inputErrors
++;
1162 * If we are reusing the existing mbuf, then refurbish the existing
1163 * DMA command \ descriptors by clearing the status/residual count
1168 for ( j
=0; j
< sizeof(enet_dma_cmd_t
)/sizeof(IODBDMADescriptor
);
1171 IOSetCCResult( &rxDMACommands
[i
].desc_seg
[j
], 0 );
1176 * Keep track of the last receive descriptor processed
1181 * Implement ring wrap-around
1183 if (++i
>= rxMaxCommand
) i
= 0;
1191 * Transfer received packet to network
1195 KERNEL_DEBUG(DBG_BMAC_RXCOMPLETE
| DBG_FUNC_NONE
, (int) packet
,
1196 (int)receivedFrameSize
, 0, 0, 0 );
1198 networkInterface
->inputPacket(packet
, receivedFrameSize
, true);
1199 doFlushQueue
= true;
1200 netStats
->inputPackets
++;
1205 * OK...this is a little messy
1207 * We just processed a bunch of DMA receive descriptors. We are going to
1208 * exchange the current DMA stop command (rxCommandTail) with the last
1209 * receive descriptor we processed (last). This will make these list of
1210 * descriptors we just processed available. If we processed no receive
1211 * descriptors on this call then skip this exchange.
1215 IOLog( "Ethernet(BMac): Prev - Rx Head = %2d Rx Tail = %2d Rx Last = %2d\n\r", rxCommandHead
, rxCommandTail
, last
);
1218 if ( last
!= lastResetValue
)
1221 * Save the contents of the last receive descriptor processed.
1223 packet
= rxMbuf
[last
];
1224 tmpCommand
= rxDMACommands
[last
];
1227 * Write a DMA stop command into this descriptor slot
1229 rxDMACommands
[last
].desc_seg
[0] = dbdmaCmd_Stop
;
1230 rxDMACommands
[last
].desc_seg
[1] = dbdmaCmd_Nop
;
1234 * Replace the previous DMA stop command with the last receive
1235 * descriptor processed.
1237 * The new DMA command is written into the channel program so that the
1238 * command word for the old Stop command is overwritten last. This
1239 * prevents the DMA engine from executing a partially written channel
1242 * Note: When relocating the descriptor, we must update its branch
1243 * field to reflect its new location.
1245 nextDesc
= rxDMACommandsPhys
+
1246 (int) &rxDMACommands
[rxCommandTail
+ 1] - (int)rxDMACommands
;
1247 IOSetCCCmdDep( &tmpCommand
.desc_seg
[0], nextDesc
);
1249 bcopy( (u_int32_t
*) &tmpCommand
+ 1,
1250 (u_int32_t
*) &rxDMACommands
[rxCommandTail
] + 1,
1251 sizeof(enet_dma_cmd_t
) - sizeof(u_int32_t
) );
1253 rxMbuf
[rxCommandTail
] = packet
;
1255 rxDMACommands
[rxCommandTail
].desc_seg
[0].operation
=
1256 tmpCommand
.desc_seg
[0].operation
;
1259 * Update rxCommmandTail to point to the new Stop command. Update
1260 * rxCommandHead to point to the next slot in the ring past the Stop
1263 rxCommandTail
= last
;
1268 * Update receive error statistics
1270 badFrameCount
= ReadBigMacRegister(ioBaseEnet
, kFECNT
)
1271 + ReadBigMacRegister(ioBaseEnet
, kAECNT
)
1272 + ReadBigMacRegister(ioBaseEnet
, kLECNT
);
1275 * Clear Hardware counters
1277 WriteBigMacRegister(ioBaseEnet
, kFECNT
, 0);
1278 WriteBigMacRegister(ioBaseEnet
, kAECNT
, 0);
1279 WriteBigMacRegister(ioBaseEnet
, kLECNT
, 0);
1281 if (badFrameCount
&& useNetif
)
1282 netStats
->inputErrors
+= badFrameCount
;
1285 * Check for error conditions that may cause the receiver to stall
1287 dmaChnlStatus
= IOGetDBDMAChannelStatus( ioBaseEnetRxDMA
);
1289 if ( dmaChnlStatus
& kdbdmaDead
)
1291 if (useNetif
) netStats
->inputErrors
++;
1292 IOLog( "Ethernet(BMac): Rx DMA Error - Status = %04x\n\r",
1299 * Tap the DMA to wake it up
1301 IODBDMAContinue( ioBaseEnetRxDMA
);
1305 IOLog( "Ethernet(BMac): New - Rx Head = %2d Rx Tail = %2d\n\r", rxCommandHead
, rxCommandTail
);
1308 return doFlushQueue
;
1311 /*-------------------------------------------------------------------------
1315 *-------------------------------------------------------------------------*/
1317 bool BMacEnet::_transmitInterruptOccurred()
1319 u_int32_t dmaStatus
;
1320 u_int32_t collisionCount
;
1321 u_int32_t badFrameCount
;
1322 bool fServiced
= false;
1327 * Check the status of the last descriptor in this entry to see if
1328 * the DMA engine completed this entry.
1330 dmaStatus
= IOGetCCResult(
1331 &(txDMACommands
[txCommandHead
].desc_seg
[1])) >> 16;
1333 if ( !(dmaStatus
& kdbdmaActive
) )
1338 if (netifEnabled
) netStats
->outputPackets
++;
1342 KERNEL_DEBUG(DBG_BMAC_TXCOMPLETE
| DBG_FUNC_NONE
,
1343 (int)txMbuf
[txCommandHead
],
1344 (int)txMbuf
[txCommandHead
]->m_pkthdr
.len
, 0, 0, 0 );
1347 * Free the mbuf we just transmitted.
1349 * If it is the debugger packet, just remove it from the ring.
1350 * and reuse the same packet for the next sendPacket() request.
1352 if (txMbuf
[txCommandHead
] != txDebuggerPkt
)
1354 freePacket( txMbuf
[txCommandHead
] );
1356 txMbuf
[txCommandHead
] = NULL
;
1358 if ( ++(txCommandHead
) >= txMaxCommand
)
1363 * Increment transmit error statistics
1365 collisionCount
= ReadBigMacRegister(ioBaseEnet
, kNCCNT
);
1367 WriteBigMacRegister( ioBaseEnet
, kNCCNT
, 0 );
1369 badFrameCount
= ReadBigMacRegister(ioBaseEnet
, kEXCNT
)
1370 + ReadBigMacRegister(ioBaseEnet
, kLTCNT
);
1372 WriteBigMacRegister( ioBaseEnet
, kEXCNT
, 0 );
1373 WriteBigMacRegister( ioBaseEnet
, kLTCNT
, 0 );
1376 netStats
->collisions
+= collisionCount
;
1377 netStats
->outputErrors
+= badFrameCount
;
1381 * Check for error conditions that may cause the transmitter to stall
1383 dmaStatus
= IOGetDBDMAChannelStatus( ioBaseEnetTxDMA
);
1385 if ( dmaStatus
& kdbdmaDead
)
1387 if (netifEnabled
) netStats
->outputErrors
++;
1388 IOLog( "Ethernet(BMac): Tx DMA Error - Status = %04x\n\r", dmaStatus
);
1389 _restartTransmitter();
1396 /*-------------------------------------------------------------------------
1400 *-------------------------------------------------------------------------*/
1402 bool BMacEnet::_debugTransmitInterruptOccurred()
1404 u_int32_t dmaStatus
;
1405 u_int32_t badFrameCount
;
1406 bool fServiced
= false;
1408 // Set the debugTxPoll flag to indicate the debugger was active
1409 // and some cleanup may be needed when the driver returns to
1410 // normal operation.
1417 * Check the status of the last descriptor in this entry to see if
1418 * the DMA engine completed this entry.
1420 dmaStatus
= IOGetCCResult(
1421 &(txDMACommands
[txCommandHead
].desc_seg
[1])) >> 16;
1423 if ( !(dmaStatus
& kdbdmaActive
) )
1430 KERNEL_DEBUG(DBG_BMAC_TXCOMPLETE
| DBG_FUNC_NONE
,
1431 (int)txMbuf
[txCommandHead
],
1432 (int)txMbuf
[txCommandHead
]->m_pkthdr
.len
, 0, 0, 0 );
1435 * Free the mbuf we just transmitted.
1437 * If it is the debugger packet, just remove it from the ring.
1438 * and reuse the same packet for the next sendPacket() request.
1440 if (txMbuf
[txCommandHead
] != txDebuggerPkt
) {
1442 // While in debugger mode, do not touch the mbuf pool.
1443 // Queue any used mbufs to a local queue. This queue
1444 // will get flushed after we exit from debugger mode.
1446 // During continuous debugger transmission and
1447 // interrupt polling, we expect only the txDebuggerPkt
1448 // to show up on the transmit mbuf ring.
1450 debugQueue
->enqueue( txMbuf
[txCommandHead
] );
1452 txMbuf
[txCommandHead
] = NULL
;
1454 if ( ++(txCommandHead
) >= txMaxCommand
)
1459 * Clear transmit error statistics
1461 badFrameCount
= ReadBigMacRegister(ioBaseEnet
, kNCCNT
);
1462 WriteBigMacRegister( ioBaseEnet
, kNCCNT
, 0 );
1464 badFrameCount
= ReadBigMacRegister(ioBaseEnet
, kEXCNT
)
1465 + ReadBigMacRegister(ioBaseEnet
, kLTCNT
);
1466 WriteBigMacRegister( ioBaseEnet
, kEXCNT
, 0 );
1467 WriteBigMacRegister( ioBaseEnet
, kLTCNT
, 0 );
1470 * Check for error conditions that may cause the transmitter to stall
1472 dmaStatus
= IOGetDBDMAChannelStatus( ioBaseEnetTxDMA
);
1474 if ( dmaStatus
& kdbdmaDead
)
1476 IOLog( "Ethernet(BMac): Tx DMA Error - Status = %04x\n\r", dmaStatus
);
1477 _restartTransmitter();
1484 /*-------------------------------------------------------------------------
1488 *-------------------------------------------------------------------------*/
1491 BMacEnet::_updateDescriptorFromMbuf(struct mbuf
* m
, enet_dma_cmd_t
*desc
,
1494 u_int32_t nextDesc
= 0;
1495 u_int32_t waitMask
= 0;
1497 struct IOPhysicalSegment segVector
[2];
1499 segments
= mbufCursor
->getPhysicalSegmentsWithCoalesce(m
, segVector
);
1501 if ((!segments
) || (segments
> 2)) {
1502 IOLog("BMac: _updateDescriptorFromMbuf error, %d segments\n",
1507 // IOLog("segments: %d\n", segments);
1509 if ( isReceive
|| chipId
>= kCHIPID_PaddingtonXmitStreaming
)
1511 waitMask
= kdbdmaWaitNever
;
1515 waitMask
= kdbdmaWaitIfFalse
;
1518 if ( segments
== 1 )
1520 IOMakeDBDMADescriptor( (&desc
->desc_seg
[0]),
1521 ((isReceive
) ? kdbdmaInputLast
: kdbdmaOutputLast
),
1524 (kdbdmaBranchNever
),
1526 (segVector
[0].length
),
1527 (segVector
[0].location
) );
1529 desc
->desc_seg
[1] = (isReceive
) ? dbdmaCmd_NopWInt
: dbdmaCmd_Nop
;
1535 nextDesc
= rxDMACommandsPhys
+ (int)desc
- (int)rxDMACommands
+
1536 sizeof(enet_dma_cmd_t
);
1539 IOMakeDBDMADescriptorDep( (&desc
->desc_seg
[0]),
1540 ((isReceive
) ? kdbdmaInputMore
: kdbdmaOutputMore
),
1542 ((isReceive
) ? kdbdmaIntIfTrue
: kdbdmaIntNever
),
1543 ((isReceive
) ? kdbdmaBranchIfTrue
:
1546 (segVector
[0].length
),
1547 (segVector
[0].location
),
1550 IOMakeDBDMADescriptor( (&desc
->desc_seg
[1]),
1551 ((isReceive
) ? kdbdmaInputLast
: kdbdmaOutputLast
),
1553 ((isReceive
) ? kdbdmaIntAlways
: kdbdmaIntNever
),
1554 (kdbdmaBranchNever
),
1556 (segVector
[1].length
),
1557 (segVector
[1].location
) );
1565 * Useful for testing.
1567 void BMacEnet::_dump_srom()
1569 unsigned short data
;
1572 for (i
= 0; i
< 128; i
++)
1574 reset_and_select_srom(ioBaseEnet
);
1575 data
= read_srom(ioBaseEnet
, i
, sromAddressBits
);
1576 IOLog("Ethernet(BMac): %x = %x ", i
, data
);
1577 if (i
% 10 == 0) IOLog("\n");
1581 void BMacEnet::_dumpDesc(void * addr
, u_int32_t size
)
1587 _IOPhysicalFromVirtual( (vm_offset_t
) addr
, (vm_offset_t
*)&paddr
);
1589 p
= (unsigned long *)addr
;
1591 for ( i
=0; i
< size
/sizeof(IODBDMADescriptor
); i
++, p
+=4,
1592 paddr
+=sizeof(IODBDMADescriptor
) )
1594 IOLog("Ethernet(BMac): %08x(v) %08x(p): %08x %08x %08x %08x\n\r",
1597 (int)OSReadSwapInt32(p
, 0), (int)OSReadSwapInt32(p
, 4),
1598 (int)OSReadSwapInt32(p
, 8), (int)OSReadSwapInt32(p
, 12) );
1602 void BMacEnet::_dumpRegisters()
1604 u_int16_t dataValue
;
1606 IOLog("\nEthernet(BMac): IO Address = %08x", (int)ioBaseEnet
);
1608 dataValue
= ReadBigMacRegister(ioBaseEnet
, kXIFC
);
1609 IOLog("\nEthernet(BMac): Read Register %04x Transceiver I/F = %04x", kXIFC
, dataValue
);
1611 dataValue
= ReadBigMacRegister(ioBaseEnet
, kSTAT
);
1612 IOLog("\nEthernet(BMac): Read Register %04x Int Events = %04x", kSTAT
, dataValue
);
1614 dataValue
= ReadBigMacRegister(ioBaseEnet
, kINTDISABLE
);
1615 IOLog("\nEthernet(BMac): Read Register %04x Int Disable = %04x", kINTDISABLE
, dataValue
);
1617 dataValue
= ReadBigMacRegister(ioBaseEnet
, kTXRST
);
1618 IOLog("\nEthernet(BMac): Read Register %04x Tx Reset = %04x", kTXRST
, dataValue
);
1620 dataValue
= ReadBigMacRegister(ioBaseEnet
, kTXCFG
);
1621 IOLog("\nEthernet(BMac): Read Register %04x Tx Config = %04x", kTXCFG
, dataValue
);
1622 IOLog("\nEthernet(BMac): -------------------------------------------------------" );
1624 dataValue
= ReadBigMacRegister(ioBaseEnet
, kIPG1
);
1625 IOLog("\nEthernet(BMac): Read Register %04x IPG1 = %04x", kIPG1
, dataValue
);
1627 dataValue
= ReadBigMacRegister(ioBaseEnet
, kIPG2
);
1628 IOLog("\nEthernet(BMac): Read Register %04x IPG2 = %04x", kIPG2
, dataValue
);
1630 dataValue
= ReadBigMacRegister(ioBaseEnet
, kALIMIT
);
1631 IOLog("\nEthernet(BMac): Read Register %04x Attempt Limit = %04x", kALIMIT
, dataValue
);
1633 dataValue
= ReadBigMacRegister(ioBaseEnet
, kSLOT
);
1634 IOLog("\nEthernet(BMac): Read Register %04x Slot Time = %04x", kSLOT
, dataValue
);
1636 dataValue
= ReadBigMacRegister(ioBaseEnet
, kPALEN
);
1637 IOLog("\nEthernet(BMac): Read Register %04x Preamble Length = %04x", kPALEN
, dataValue
);
1639 IOLog("\nEthernet(BMac): -------------------------------------------------------" );
1640 dataValue
= ReadBigMacRegister(ioBaseEnet
, kPAPAT
);
1641 IOLog("\nEthernet(BMac): Read Register %04x Preamble Pattern = %04x", kPAPAT
, dataValue
);
1643 dataValue
= ReadBigMacRegister(ioBaseEnet
, kTXSFD
);
1644 IOLog("\nEthernet(BMac): Read Register %04x Tx Start Frame Delimeter = %04x", kTXSFD
, dataValue
);
1646 dataValue
= ReadBigMacRegister(ioBaseEnet
, kJAM
);
1647 IOLog("\nEthernet(BMac): Read Register %04x Jam Size = %04x", kJAM
, dataValue
);
1649 dataValue
= ReadBigMacRegister(ioBaseEnet
, kTXMAX
);
1650 IOLog("\nEthernet(BMac): Read Register %04x Tx Max Size = %04x", kTXMAX
, dataValue
);
1652 dataValue
= ReadBigMacRegister(ioBaseEnet
, kTXMIN
);
1653 IOLog("\nEthernet(BMac): Read Register %04x Tx Min Size = %04x", kTXMIN
, dataValue
);
1654 IOLog("\nEthernet(BMac): -------------------------------------------------------" );
1656 dataValue
= ReadBigMacRegister(ioBaseEnet
, kPAREG
);
1657 IOLog("\nEthernet(BMac): Read Register %04x Peak Attempts = %04x", kPAREG
, dataValue
);
1659 dataValue
= ReadBigMacRegister(ioBaseEnet
, kDCNT
);
1660 IOLog("\nEthernet(BMac): Read Register %04x Defer Timer = %04x", kDCNT
, dataValue
);
1662 dataValue
= ReadBigMacRegister(ioBaseEnet
, kNCCNT
);
1663 IOLog("\nEthernet(BMac): Read Register %04x Normal Collision Count = %04x", kNCCNT
, dataValue
);
1665 dataValue
= ReadBigMacRegister(ioBaseEnet
, kNTCNT
);
1666 IOLog("\nEthernet(BMac): Read Register %04x Network Collision Count = %04x", kNTCNT
, dataValue
);
1668 dataValue
= ReadBigMacRegister(ioBaseEnet
, kEXCNT
);
1669 IOLog("\nEthernet(BMac): Read Register %04x Excessive Coll Count = %04x", kEXCNT
, dataValue
);
1670 IOLog("\nEthernet(BMac): -------------------------------------------------------" );
1672 dataValue
= ReadBigMacRegister(ioBaseEnet
, kLTCNT
);
1673 IOLog("\nEthernet(BMac): Read Register %04x Late Collision Count = %04x", kLTCNT
, dataValue
);
1675 dataValue
= ReadBigMacRegister(ioBaseEnet
, kRSEED
);
1676 IOLog("\nEthernet(BMac): Read Register %04x Random Seed = %04x", kRSEED
, dataValue
);
1678 dataValue
= ReadBigMacRegister(ioBaseEnet
, kTXSM
);
1679 IOLog("\nEthernet(BMac): Read Register %04x Tx State Machine = %04x", kTXSM
, dataValue
);
1681 dataValue
= ReadBigMacRegister(ioBaseEnet
, kRXRST
);
1682 IOLog("\nEthernet(BMac): Read Register %04x Rx Reset = %04x", kRXRST
, dataValue
);
1684 dataValue
= ReadBigMacRegister(ioBaseEnet
, kRXCFG
);
1685 IOLog("\nEthernet(BMac): Read Register %04x Rx Config = %04x", kRXCFG
, dataValue
);
1686 IOLog("\nEthernet(BMac): -------------------------------------------------------" );
1688 dataValue
= ReadBigMacRegister(ioBaseEnet
, kRXMAX
);
1689 IOLog("\nEthernet(BMac): Read Register %04x Rx Max Size = %04x", kRXMAX
, dataValue
);
1691 dataValue
= ReadBigMacRegister(ioBaseEnet
, kRXMIN
);
1692 IOLog("\nEthernet(BMac): Read Register %04x Rx Min Size = %04x", kRXMIN
, dataValue
);
1694 dataValue
= ReadBigMacRegister(ioBaseEnet
, kMADD2
);
1695 IOLog("\nEthernet(BMac): Read Register %04x Mac Address 2 = %04x", kMADD2
, dataValue
);
1697 dataValue
= ReadBigMacRegister(ioBaseEnet
, kMADD1
);
1698 IOLog("\nEthernet(BMac): Read Register %04x Mac Address 1 = %04x", kMADD1
, dataValue
);
1700 dataValue
= ReadBigMacRegister(ioBaseEnet
, kMADD0
);
1701 IOLog("\nEthernet(BMac): Read Register %04x Mac Address 0 = %04x", kMADD0
, dataValue
);
1702 IOLog("\nEthernet(BMac): -------------------------------------------------------" );
1704 dataValue
= ReadBigMacRegister(ioBaseEnet
, kFRCNT
);
1705 IOLog("\nEthernet(BMac): Read Register %04x Rx Frame Counter = %04x", kFRCNT
, dataValue
);
1707 dataValue
= ReadBigMacRegister(ioBaseEnet
, kLECNT
);
1708 IOLog("\nEthernet(BMac): Read Register %04x Rx Length Error Cnt = %04x", kLECNT
, dataValue
);
1710 dataValue
= ReadBigMacRegister(ioBaseEnet
, kAECNT
);
1711 IOLog("\nEthernet(BMac): Read Register %04x Alignment Error Cnt = %04x", kAECNT
, dataValue
);
1713 dataValue
= ReadBigMacRegister(ioBaseEnet
, kFECNT
);
1714 IOLog("\nEthernet(BMac): Read Register %04x FCS Error Cnt = %04x", kFECNT
, dataValue
);
1716 dataValue
= ReadBigMacRegister(ioBaseEnet
, kRXSM
);
1717 IOLog("\nEthernet(BMac): Read Register %04x Rx State Machine = %04x", kRXSM
, dataValue
);
1718 IOLog("\nEthernet(BMac): -------------------------------------------------------" );
1720 dataValue
= ReadBigMacRegister(ioBaseEnet
, kRXCV
);
1721 IOLog("\nEthernet(BMac): Read Register %04x Rx Code Violation = %04x", kRXCV
, dataValue
);
1723 dataValue
= ReadBigMacRegister(ioBaseEnet
, kHASH3
);
1724 IOLog("\nEthernet(BMac): Read Register %04x Hash 3 = %04x", kHASH3
, dataValue
);
1726 dataValue
= ReadBigMacRegister(ioBaseEnet
, kHASH2
);
1727 IOLog("\nEthernet(BMac): Read Register %04x Hash 2 = %04x", kHASH2
, dataValue
);
1729 dataValue
= ReadBigMacRegister(ioBaseEnet
, kHASH1
);
1730 IOLog("\nEthernet(BMac): Read Register %04x Hash 1 = %04x", kHASH1
, dataValue
);
1732 dataValue
= ReadBigMacRegister(ioBaseEnet
, kHASH0
);
1733 IOLog("\nEthernet(BMac): Read Register %04x Hash 0 = %04x", kHASH0
, dataValue
);
1734 IOLog("\n-------------------------------------------------------" );
1736 dataValue
= ReadBigMacRegister(ioBaseEnet
, kAFR2
);
1737 IOLog("\nEthernet(BMac): Read Register %04x Address Filter 2 = %04x", kAFR2
, dataValue
);
1739 dataValue
= ReadBigMacRegister(ioBaseEnet
, kAFR1
);
1740 IOLog("\nEthernet(BMac): Read Register %04x Address Filter 1 = %04x", kAFR1
, dataValue
);
1742 dataValue
= ReadBigMacRegister(ioBaseEnet
, kAFR0
);
1743 IOLog("\nEthernet(BMac): Read Register %04x Address Filter 0 = %04x", kAFR0
, dataValue
);
1745 dataValue
= ReadBigMacRegister(ioBaseEnet
, kAFCR
);
1746 IOLog("\nEthernet(BMac): Read Register %04x Adress Filter Mask = %04x", kAFCR
, dataValue
);
1748 dataValue
= ReadBigMacRegister(ioBaseEnet
, kTXFIFOCSR
);
1749 IOLog("\nEthernet(BMac): Read Register %04x Tx FIFO CSR = %04x", kTXFIFOCSR
, dataValue
);
1750 IOLog("\n-------------------------------------------------------" );
1752 dataValue
= ReadBigMacRegister(ioBaseEnet
, kTXTH
);
1753 IOLog("\nEthernet(BMac): Read Register %04x Tx Threshold = %04x", kTXTH
, dataValue
);
1755 dataValue
= ReadBigMacRegister(ioBaseEnet
, kRXFIFOCSR
);
1756 IOLog("\nEthernet(BMac): Read Register %04x Rx FIFO CSR = %04x", kRXFIFOCSR
, dataValue
);
1758 dataValue
= ReadBigMacRegister(ioBaseEnet
, kMEMADD
);
1759 IOLog("\nEthernet(BMac): Read Register %04x Mem Addr = %04x", kMEMADD
, dataValue
);
1761 dataValue
= ReadBigMacRegister(ioBaseEnet
, kMEMDATAHI
);
1762 IOLog("\nEthernet(BMac): Read Register %04x Mem Data High = %04x", kMEMDATAHI
, dataValue
);
1764 dataValue
= ReadBigMacRegister(ioBaseEnet
, kMEMDATALO
);
1765 IOLog("\nEthernet(BMac): Read Register %04x Mem Data Low = %04x", kMEMDATALO
, dataValue
);
1766 IOLog("\n-------------------------------------------------------" );
1768 dataValue
= ReadBigMacRegister(ioBaseEnet
, kXCVRIF
);
1769 IOLog("\nEthernet(BMac): Read Register %04x Transceiver IF Control = %04x", kXCVRIF
, dataValue
);
1771 dataValue
= ReadBigMacRegister(ioBaseEnet
, kCHIPID
);
1772 IOLog("\nEthernet(BMac): Read Register %04x Chip ID = %04x", kCHIPID
, dataValue
);
1774 dataValue
= ReadBigMacRegister(ioBaseEnet
, kMIFCSR
);
1775 IOLog("\nEthernet(BMac): Read Register %04x MII CSR = %04x", kMIFCSR
, dataValue
);
1777 dataValue
= ReadBigMacRegister(ioBaseEnet
, kSROMCSR
);
1778 IOLog("\nEthernet(BMac): Read Register %04x SROM CSR = %04x", kSROMCSR
, dataValue
);
1780 dataValue
= ReadBigMacRegister(ioBaseEnet
, kTXPNTR
);
1781 IOLog("\nEthernet(BMac): Read Register %04x Tx Pointer = %04x", kTXPNTR
, dataValue
);
1783 dataValue
= ReadBigMacRegister(ioBaseEnet
, kRXPNTR
);
1784 IOLog("\nEthernet(BMac): Read Register %04x Rx Pointer = %04x", kRXPNTR
, dataValue
);
1785 IOLog("\nEthernet(BMac): -------------------------------------------------------\n" );
1790 /*-------------------------------------------------------------------------
1794 *-------------------------------------------------------------------------*/
1796 IOReturn
BMacEnet::getHardwareAddress(IOEthernetAddress
*ea
)
1799 unsigned short data
;
1801 for (i
= 0; i
< (unsigned short)sizeof(*ea
)/2; i
++)
1803 reset_and_select_srom(ioBaseEnet
);
1804 data
= read_srom(ioBaseEnet
, i
+ enetAddressOffset
/2, sromAddressBits
);
1805 ea
->bytes
[2*i
] = reverseBitOrder(data
& 0x0ff);
1806 ea
->bytes
[2*i
+1] = reverseBitOrder((data
>> 8) & 0x0ff);
1809 return kIOReturnSuccess
;
1812 /*-------------------------------------------------------------------------
1816 *-------------------------------------------------------------------------*/
1818 #define ENET_CRCPOLY 0x04c11db7
1820 /* Real fast bit-reversal algorithm, 6-bit values */
1821 static int reverse6
[] =
1822 { 0x0,0x20,0x10,0x30,0x8,0x28,0x18,0x38,
1823 0x4,0x24,0x14,0x34,0xc,0x2c,0x1c,0x3c,
1824 0x2,0x22,0x12,0x32,0xa,0x2a,0x1a,0x3a,
1825 0x6,0x26,0x16,0x36,0xe,0x2e,0x1e,0x3e,
1826 0x1,0x21,0x11,0x31,0x9,0x29,0x19,0x39,
1827 0x5,0x25,0x15,0x35,0xd,0x2d,0x1d,0x3d,
1828 0x3,0x23,0x13,0x33,0xb,0x2b,0x1b,0x3b,
1829 0x7,0x27,0x17,0x37,0xf,0x2f,0x1f,0x3f
1832 static u_int32_t
crc416(unsigned int current
, unsigned short nxtval
)
1834 register unsigned int counter
;
1835 register int highCRCBitSet
, lowDataBitSet
;
1838 nxtval
= ((nxtval
& 0x00FF) << 8) | (nxtval
>> 8);
1840 /* Compute bit-by-bit */
1841 for (counter
= 0; counter
!= 16; ++counter
)
1842 { /* is high CRC bit set? */
1843 if ((current
& 0x80000000) == 0)
1848 current
= current
<< 1;
1850 if ((nxtval
& 0x0001) == 0)
1855 nxtval
= nxtval
>> 1;
1858 if (highCRCBitSet
^ lowDataBitSet
)
1859 current
= current
^ ENET_CRCPOLY
;
1865 /*-------------------------------------------------------------------------
1869 *-------------------------------------------------------------------------*/
1871 static u_int32_t
mace_crc(unsigned short *address
)
1873 register u_int32_t newcrc
;
1875 newcrc
= crc416(0xffffffff, *address
); /* address bits 47 - 32 */
1876 newcrc
= crc416(newcrc
, address
[1]); /* address bits 31 - 16 */
1877 newcrc
= crc416(newcrc
, address
[2]); /* address bits 15 - 0 */
1883 * Clear the hash table filter.
1886 void BMacEnet::_resetHashTableMask()
1888 bzero(hashTableUseCount
, sizeof(hashTableUseCount
));
1889 bzero(hashTableMask
, sizeof(hashTableMask
));
1893 * Add requested mcast addr to BMac's hash table filter.
1896 void BMacEnet::_addToHashTableMask(u_int8_t
*addr
)
1901 crc
= mace_crc((unsigned short *)addr
)&0x3f; /* Big-endian alert! */
1902 crc
= reverse6
[crc
]; /* Hyperfast bit-reversing algorithm */
1903 if (hashTableUseCount
[crc
]++)
1904 return; /* This bit is already set */
1906 mask
= (unsigned short)1 << mask
;
1907 hashTableMask
[crc
/16] |= mask
;
1910 /*-------------------------------------------------------------------------
1914 *-------------------------------------------------------------------------*/
1916 void BMacEnet::_removeFromHashTableMask(u_int8_t
*addr
)
1921 /* Now, delete the address from the filter copy, as indicated */
1922 crc
= mace_crc((unsigned short *)addr
)&0x3f; /* Big-endian alert! */
1923 crc
= reverse6
[crc
]; /* Hyperfast bit-reversing algorithm */
1924 if (hashTableUseCount
[crc
] == 0)
1925 return; /* That bit wasn't in use! */
1927 if (--hashTableUseCount
[crc
])
1928 return; /* That bit is still in use */
1931 mask
= (u_int16_t
)1 << mask
; /* To turn off bit */
1932 hashTableMask
[crc
/16] &= ~mask
;
1936 * Sync the adapter with the software copy of the multicast mask
1937 * (logical address filter).
1939 void BMacEnet::_updateBMacHashTableMask()
1943 rxCFGReg
= ReadBigMacRegister(ioBaseEnet
, kRXCFG
);
1944 WriteBigMacRegister(ioBaseEnet
, kRXCFG
,
1945 rxCFGReg
& ~(kRxMACEnable
| kRxHashFilterEnable
) );
1947 while ( ReadBigMacRegister(ioBaseEnet
, kRXCFG
) &
1948 (kRxMACEnable
| kRxHashFilterEnable
) )
1951 WriteBigMacRegister(ioBaseEnet
, kHASH0
, hashTableMask
[0]); // bits 15 - 0
1952 WriteBigMacRegister(ioBaseEnet
, kHASH1
, hashTableMask
[1]); // bits 31 - 16
1953 WriteBigMacRegister(ioBaseEnet
, kHASH2
, hashTableMask
[2]); // bits 47 - 32
1954 WriteBigMacRegister(ioBaseEnet
, kHASH3
, hashTableMask
[3]); // bits 63 - 48
1956 rxCFGReg
|= kRxHashFilterEnable
;
1957 WriteBigMacRegister(ioBaseEnet
, kRXCFG
, rxCFGReg
);