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 * Hardware independent (relatively) code for the Sun GEM Ethernet Controller
34 //void call_kdp(void);
36 #include "UniNEnetPrivate.h"
38 #define super IOEthernetController
40 OSDefineMetaClassAndStructors( UniNEnet
, IOEthernetController
)
42 /*-------------------------------------------------------------------------
46 *-------------------------------------------------------------------------*/
48 bool UniNEnet::init(OSDictionary
* properties
)
50 if ( super::init(properties
) == false )
54 * Initialize my ivars.
57 linkStatusPrev
= kLinkStatusUnknown
;
62 /*-------------------------------------------------------------------------
66 *-------------------------------------------------------------------------*/
68 bool UniNEnet::start(IOService
* provider
)
72 keyLargo_resetUniNEthernetPhy
= OSSymbol::withCString("keyLargo_resetUniNEthernetPhy");
74 // Wait for KeyLargo to show up.
75 keyLargo
= waitForService(serviceMatching("KeyLargo"));
76 if (keyLargo
== 0) return false;
78 nub
= OSDynamicCast(IOPCIDevice
, provider
);
80 if (!nub
|| !super::start(provider
))
85 // Create spinlock to protect TxElementQueue.
87 txQueueLock
= IOSimpleLockAlloc();
88 if ( txQueueLock
== 0 ) return false;
89 IOSimpleLockInit(txQueueLock
);
91 transmitQueue
= (IOGatedOutputQueue
*) getOutputQueue();
94 IOLog("Ethernet(UniN): Output queue initialization failed\n");
97 transmitQueue
->retain();
100 * Allocate debug queue. This stores packets retired from the TX ring
101 * by the polling routine. We cannot call freePacket() or m_free() within
102 * the debugger context.
104 * The capacity of the queue is set at maximum to prevent the queue from
105 * calling m_free() due to over-capacity. But we don't expect the size
106 * of the queue to grow too large.
108 debugQueue
= IOPacketQueue::withCapacity((UInt
) -1);
115 * Allocate a IOMbufBigMemoryCursor instance. Currently, the maximum
116 * number of segments is set to 1. The maximum length for each segment
117 * is set to the maximum ethernet frame size (plus padding).
119 mbufCursor
= IOMbufBigMemoryCursor::withSpecification(NETWORK_BUFSIZE
, 1);
122 IOLog("Ethernet(UniN): IOMbufBigMemoryCursor allocation failure\n");
126 matchEntry
= OSDynamicCast( OSString
, getProperty( gIONameMatchedKey
) );
127 if ( matchEntry
== 0 )
129 IOLog("Ethernet(UniN): Cannot obtain matching property.\n");
133 if ( matchEntry
->isEqualTo( "gmac" ) == true )
135 callPlatformFunction("EnableUniNEthernetClock", true,
136 (void *)true, 0, 0, 0);
140 * BUS MASTER, MEM I/O Space, MEM WR & INV
142 nub
->configWrite32( 0x04, 0x16 );
145 * set Latency to Max , cache 32
147 nub
->configWrite32( 0x0C, ((2 + (kGEMBurstSize
* (0+1)))<< 8) | (CACHE_LINE_SIZE
>> 2) );
149 ioMapEnet
= nub
->mapDeviceMemoryWithRegister( 0x10 );
150 if ( ioMapEnet
== NULL
)
154 ioBaseEnet
= (volatile IOPPCAddress
)ioMapEnet
->getVirtualAddress();
155 fpRegs
= (GMAC_Registers
*) ioBaseEnet
;
159 * Get a reference to the IOWorkLoop in our superclass.
161 IOWorkLoop
* myWorkLoop
= getWorkLoop();
164 * Allocate three IOInterruptEventSources.
166 interruptSource
= IOInterruptEventSource::interruptEventSource(
168 (IOInterruptEventAction
) &UniNEnet::interruptOccurred
,
169 (IOService
*) provider
,
172 if ( interruptSource
== NULL
)
174 IOLog("Ethernet(UniN): Couldn't allocate Interrupt event source\n");
178 if ( myWorkLoop
->addEventSource( interruptSource
) != kIOReturnSuccess
)
180 IOLog("Ethernet(UniN): Couldn't add Interrupt event source\n");
185 timerSource
= IOTimerEventSource::timerEventSource
186 (this, (IOTimerEventSource::Action
) &UniNEnet::timeoutOccurred
);
187 if ( timerSource
== NULL
)
189 IOLog("Ethernet(UniN): Couldn't allocate timer event source\n");
193 if ( myWorkLoop
->addEventSource( timerSource
) != kIOReturnSuccess
)
195 IOLog("Ethernet(UniN): Couldn't add timer event source\n");
199 MGETHDR(txDebuggerPkt
, M_DONTWAIT
, MT_DATA
);
203 IOLog("Ethernet(UniN): Couldn't allocate KDB buffer\n");
208 * Perform a hardware reset.
210 if ( resetAndEnable(false) == false )
212 IOLog("Ethernet(UniN): resetAndEnable() failed\n");
217 * Cache my MAC address.
219 if ( getHardwareAddress(&myAddress
) != kIOReturnSuccess
)
221 IOLog("Ethernet(UniN): getHardwareAddress() failed\n");
226 * Allocate memory for ring buffers.
228 if ( allocateMemory() == false)
230 IOLog("Ethernet(UniN): allocateMemory() failed\n");
234 if ( createMediumTables() == false )
236 IOLog("Ethernet(UniN): createMediumTables() failed\n");
241 * Attach an IOEthernetInterface client. But don't registers it just yet.
243 if ( !attachInterface((IONetworkInterface
**) &networkInterface
, false) )
245 IOLog("Ethernet(UniN): attachInterface() failed\n");
250 * Attach a kernel debugger client.
252 attachDebuggerClient(&debugger
);
255 * Ready to service interface requests.
257 networkInterface
->registerService();
262 /*-------------------------------------------------------------------------
266 *-------------------------------------------------------------------------*/
268 bool UniNEnet::configureInterface(IONetworkInterface
* netif
)
272 if ( super::configureInterface( netif
) == false )
276 * Grab a pointer to the statistics structure in the interface.
278 nd
= netif
->getNetworkData( kIONetworkStatsKey
);
279 if (!nd
|| !(fpNetStats
= (IONetworkStats
*) nd
->getBuffer()))
281 IOLog("EtherNet(UniN): invalid network statistics\n");
285 // Get the Ethernet statistics structure:
286 nd
= netif
->getParameter( kIOEthernetStatsKey
);
287 if ( !nd
|| !(fpEtherStats
= (IOEthernetStats
*)nd
->getBuffer()) )
289 IOLog("EtherNet(UniN): invalid ethernet statistics\n");
294 * Set the driver/stack reentrancy flag. This is meant to reduce
295 * context switches. May become irrelevant in the future.
298 }/* end configureInterface */
301 /*-------------------------------------------------------------------------
305 *-------------------------------------------------------------------------*/
307 void UniNEnet::free()
309 TxQueueElement
* txElement
;
311 resetAndEnable(false);
318 getWorkLoop()->disableAllEventSources();
323 timerSource
->release();
329 interruptSource
->release();
334 freePacket(txDebuggerPkt
);
339 transmitQueue
->release();
344 debugQueue
->release();
347 if (networkInterface
)
349 networkInterface
->release();
354 mbufCursor
->release();
359 mediumDict
->release();
362 while ( ( txElement
= getTxElement() ) )
364 IOFree( txElement
, sizeof(TxQueueElement
) );
369 ioMapEnet
->release();
372 if ( dmaCommands
!= 0 )
374 IOFreeContiguous( (void *)dmaCommands
, dmaCommandsSize
);
385 IOSimpleLockFree( txQueueLock
);
392 /*-------------------------------------------------------------------------
393 * Override IONetworkController::createWorkLoop() method and create
396 *-------------------------------------------------------------------------*/
398 bool UniNEnet::createWorkLoop()
400 workLoop
= IOWorkLoop::workLoop();
402 return ( workLoop
!= 0 );
405 /*-------------------------------------------------------------------------
406 * Override IOService::getWorkLoop() method to return our workloop.
409 *-------------------------------------------------------------------------*/
411 IOWorkLoop
* UniNEnet::getWorkLoop() const
416 /*-------------------------------------------------------------------------
420 *-------------------------------------------------------------------------*/
422 void UniNEnet::interruptOccurred(IOInterruptEventSource
* src
, int /*count*/)
424 IODebuggerLockState lockState
;
425 UInt32 interruptStatus
;
430 if ( ready
== false ) return;
434 lockState
= IODebuggerLock( this );
436 interruptStatus
= READ_REGISTER( Status
)
437 & ( kStatus_TX_INT_ME
| kStatus_RX_DONE
);
441 if ( interruptStatus
& kStatus_TX_INT_ME
)
444 KERNEL_DEBUG(DBG_GEM_TXIRQ
| DBG_FUNC_START
, 0, 0, 0, 0, 0 );
445 doService
= transmitInterruptOccurred();
446 KERNEL_DEBUG(DBG_GEM_TXIRQ
| DBG_FUNC_END
, 0, 0, 0, 0, 0 );
447 ETHERNET_STAT_ADD( dot3TxExtraEntry
.interrupts
);
450 doFlushQueue
= false;
452 if ( interruptStatus
& kStatus_RX_DONE
)
455 KERNEL_DEBUG(DBG_GEM_RXIRQ
| DBG_FUNC_START
, 0, 0, 0, 0, 0 );
456 doFlushQueue
= receiveInterruptOccurred();
457 KERNEL_DEBUG(DBG_GEM_RXIRQ
| DBG_FUNC_END
, 0, 0, 0, 0, 0 );
458 ETHERNET_STAT_ADD( dot3RxExtraEntry
.interrupts
);
461 IODebuggerUnlock( lockState
);
464 * Submit all received packets queued up by _receiveInterruptOccurred()
465 * to the network stack. The up call is performed without holding the
470 networkInterface
->flushInputQueue();
474 * Make sure the output queue is not stalled.
476 if (doService
&& netifEnabled
)
478 transmitQueue
->service();
481 while ( interruptStatus
);
483 // interruptSource->enable();
485 }/* end interruptOccurred */
488 /*-------------------------------------------------------------------------
492 *-------------------------------------------------------------------------*/
494 UInt32
UniNEnet::outputPacket(struct mbuf
* pkt
, void * param
)
496 UInt32 ret
= kIOReturnOutputSuccess
;
498 KERNEL_DEBUG( DBG_GEM_TXQUEUE
| DBG_FUNC_NONE
,
499 (int) pkt
, (int) pkt
->m_pkthdr
.len
, 0, 0, 0 );
502 * Hold the debugger lock so the debugger can't interrupt us
504 reserveDebuggerLock();
506 if ( linkStatusPrev
!= kLinkStatusUp
)
510 else if ( transmitPacket(pkt
) == false )
512 ret
= kIOReturnOutputStall
;
515 releaseDebuggerLock();
520 /*-------------------------------------------------------------------------
524 *-------------------------------------------------------------------------*/
526 bool UniNEnet::resetAndEnable(bool enable
)
530 reserveDebuggerLock();
536 timerSource
->cancelTimeout();
539 disableAdapterInterrupts();
542 getWorkLoop()->disableAllInterrupts();
550 if ( resetChip() == false )
553 goto resetAndEnable_exit
;
556 // Initialize the link status.
558 setLinkStatus( 0, 0 );
560 // Flush all mbufs from RX and TX rings.
566 if (!initRxRing() || !initTxRing())
574 miiInitializePHY(phyId
);
577 if (initChip() == false)
585 timerSource
->setTimeoutMS(WATCHDOG_TIMER_MS
);
589 getWorkLoop()->enableAllInterrupts();
591 enableAdapterInterrupts();
595 monitorLinkStatus( true );
600 resetAndEnable_exit
: ;
602 releaseDebuggerLock();
607 /*-------------------------------------------------------------------------
608 * Called by IOEthernetInterface client to enable the controller.
609 * This method is always called while running on the default workloop
611 *-------------------------------------------------------------------------*/
613 IOReturn
UniNEnet::enable(IONetworkInterface
* netif
)
616 * If an interface client has previously enabled us,
617 * and we know there can only be one interface client
618 * for this driver, then simply return true.
622 IOLog("EtherNet(UniN): already enabled\n");
623 return kIOReturnSuccess
;
626 if ( (ready
== false) && !resetAndEnable(true) )
627 return kIOReturnIOError
;
630 * Mark the controller as enabled by the interface.
635 * Start our IOOutputQueue object.
637 transmitQueue
->setCapacity( TRANSMIT_QUEUE_SIZE
);
638 transmitQueue
->start();
640 return kIOReturnSuccess
;
643 /*-------------------------------------------------------------------------
644 * Called by IOEthernetInterface client to disable the controller.
645 * This method is always called while running on the default workloop
647 *-------------------------------------------------------------------------*/
649 IOReturn
UniNEnet::disable(IONetworkInterface
* /*netif*/)
652 * Disable our IOOutputQueue object. This will prevent the
653 * outputPacket() method from being called.
655 transmitQueue
->stop();
658 * Flush all packets currently in the output queue.
660 transmitQueue
->setCapacity(0);
661 transmitQueue
->flush();
664 * If we have no active clients, then disable the controller.
666 if ( debugEnabled
== false )
668 resetAndEnable(false);
671 netifEnabled
= false;
673 return kIOReturnSuccess
;
676 /*-------------------------------------------------------------------------
677 * This method is called by our debugger client to bring up the controller
678 * just before the controller is registered as the debugger device. The
679 * debugger client is attached in response to the attachDebuggerClient()
682 * This method is always called while running on the default workloop
684 *-------------------------------------------------------------------------*/
686 IOReturn
UniNEnet::enable(IOKernelDebugger
* /*debugger*/)
689 * Enable hardware and make it ready to support the debugger client.
691 if ( (ready
== false) && !resetAndEnable(true) )
693 return kIOReturnIOError
;
697 * Mark the controller as enabled by the debugger.
702 * Returning true will allow the kdp registration to continue.
703 * If we return false, then we will not be registered as the
704 * debugger device, and the attachDebuggerClient() call will
707 return kIOReturnSuccess
;
710 /*-------------------------------------------------------------------------
711 * This method is called by our debugger client to stop the controller.
712 * The debugger will call this method when we issue a detachDebuggerClient().
714 * This method is always called while running on the default workloop
716 *-------------------------------------------------------------------------*/
718 IOReturn
UniNEnet::disable(IOKernelDebugger
* /*debugger*/)
720 debugEnabled
= false;
723 * If we have no active clients, then disable the controller.
725 if ( netifEnabled
== false )
727 resetAndEnable(false);
730 return kIOReturnSuccess
;
733 /*-------------------------------------------------------------------------
737 *-------------------------------------------------------------------------*/
739 void UniNEnet::timeoutOccurred(IOTimerEventSource
* /*timer*/)
741 IODebuggerLockState lockState
;
742 bool doService
= false;
747 if ( ready
== false )
749 // IOLog("EtherNet(UniN): Spurious timeout event!!\n");
754 /* Update statistics from the GMAC statistics registers: */
756 x
= READ_REGISTER( LengthErrorCounter
);
757 writeRegister( &fpRegs
->LengthErrorCounter
, 0 );
758 fpEtherStats
->dot3StatsEntry
.frameTooLongs
+= x
;
760 x
= READ_REGISTER( AlignmentErrorCounter
);
761 writeRegister( &fpRegs
->AlignmentErrorCounter
, 0 );
762 fpEtherStats
->dot3StatsEntry
.alignmentErrors
+= x
;
764 x
= READ_REGISTER( FCSErrorCounter
);
765 writeRegister( &fpRegs
->FCSErrorCounter
, 0 );
766 fpEtherStats
->dot3StatsEntry
.fcsErrors
+= x
;
768 x
= READ_REGISTER( RxCodeViolationErrorCounter
);
769 writeRegister( &fpRegs
->RxCodeViolationErrorCounter
, 0 );
770 fpEtherStats
->dot3StatsEntry
.internalMacTransmitErrors
+= x
;
772 x
= READ_REGISTER( FirstAttemptSuccessfulCollisionCounter
);
773 writeRegister( &fpRegs
->FirstAttemptSuccessfulCollisionCounter
, 0 );
774 fpEtherStats
->dot3StatsEntry
.singleCollisionFrames
+= x
;
776 x
= READ_REGISTER( ExcessiveCollisionCounter
);
777 writeRegister( &fpRegs
->ExcessiveCollisionCounter
, 0 );
778 fpEtherStats
->dot3StatsEntry
.excessiveCollisions
+= x
;
780 x
= READ_REGISTER( LateCollisionCounter
);
781 writeRegister( &fpRegs
->LateCollisionCounter
, 0 );
782 fpEtherStats
->dot3StatsEntry
.lateCollisions
+= x
;
784 lockState
= IODebuggerLock( this );
789 * If there are pending entries on the Tx ring
791 if ( txCommandHead
!= txCommandTail
)
794 * If the hardware tx pointer did not move since the last
795 * check, increment the txWDCount.
797 txRingIndex
= READ_REGISTER( TxCompletion
);
798 if ( txRingIndex
== txRingIndexLast
)
805 txRingIndexLast
= txRingIndex
;
811 * We only take interrupts every 64 tx completions, so we may be here just
812 * to do normal clean-up of tx packets. We check if the hardware tx pointer
813 * points to the next available tx slot. This indicates that we transmitted all
814 * packets that were scheduled vs rather than the hardware tx being stalled.
816 if ( txRingIndex
!= txCommandTail
)
818 UInt32 interruptStatus
, compReg
, kickReg
;
820 interruptStatus
= READ_REGISTER( Status
);
821 compReg
= READ_REGISTER( TxCompletion
);
822 kickReg
= READ_REGISTER( TxKick
);
824 IOLog( "Tx Int Timeout - Comp = %04x Kick = %04x Int = %08x\n\r", (int)compReg
, (int)kickReg
, (int)interruptStatus
);
829 transmitInterruptOccurred();
833 txRingIndexLast
= txRingIndex
;
842 // Monitor receiver's health.
844 if ( rxWDInterrupts
== 0 )
852 rxWDCount
++; // Extend timeout
856 // We could be less conservative here and restart the
857 // receiver unconditionally.
859 rxMACStatus
= READ_REGISTER( RxMACStatus
);
861 if ( rxMACStatus
& kRX_MAC_Status_Rx_Overflow
)
863 // Bad news, the receiver may be deaf as a result of this
864 // condition, and if so, a RX MAC reset is needed. Note
865 // that reading this register will clear all bits.
869 NETWORK_STAT_ADD( inputErrors
);
870 ETHERNET_STAT_ADD( dot3RxExtraEntry
.watchdogTimeouts
);
884 /* Clean-up after the debugger if the debugger was active: */
892 IODebuggerUnlock( lockState
);
895 * Make sure the queue is not stalled.
897 if (doService
&& netifEnabled
)
899 transmitQueue
->service();
903 * Restart the watchdog timer
905 timerSource
->setTimeoutMS(WATCHDOG_TIMER_MS
);
907 }/* end timeoutOccurred */
910 /*-------------------------------------------------------------------------
914 *-------------------------------------------------------------------------*/
916 const OSString
* UniNEnet::newVendorString() const
918 return OSString::withCString("Apple");
921 const OSString
* UniNEnet::newModelString() const
923 return OSString::withCString("gmac+");
926 const OSString
* UniNEnet::newRevisionString() const
928 return OSString::withCString("");
932 /*-------------------------------------------------------------------------
936 *-------------------------------------------------------------------------*/
938 IOReturn
UniNEnet::setPromiscuousMode(IOEnetPromiscuousMode mode
)
940 reserveDebuggerLock();
942 rxMacConfigReg
= READ_REGISTER( RxMACConfiguration
);
943 if (mode
== kIOEnetPromiscuousModeOff
)
945 rxMacConfigReg
&= ~(kRxMACConfiguration_Promiscuous
);
946 isPromiscuous
= false;
951 rxMacConfigReg
|= kRxMACConfiguration_Promiscuous
;
952 isPromiscuous
= true;
955 WRITE_REGISTER( RxMACConfiguration
, rxMacConfigReg
);
957 releaseDebuggerLock();
959 return kIOReturnSuccess
;
962 /*-------------------------------------------------------------------------
966 *-------------------------------------------------------------------------*/
968 IOReturn
UniNEnet::setMulticastMode(IOEnetMulticastMode mode
)
970 multicastEnabled
= (mode
== kIOEnetMulticastModeOff
) ? false : true;
972 return kIOReturnSuccess
;
975 /*-------------------------------------------------------------------------
979 *-------------------------------------------------------------------------*/
981 IOReturn
UniNEnet::setMulticastList(IOEthernetAddress
*addrs
, UInt32 count
)
983 reserveDebuggerLock();
985 resetHashTableMask();
986 for (UInt32 i
= 0; i
< count
; i
++)
988 addToHashTableMask(addrs
->bytes
);
991 updateHashTableMask();
993 releaseDebuggerLock();
994 return kIOReturnSuccess
;
997 /*-------------------------------------------------------------------------
1001 *-------------------------------------------------------------------------*/
1003 IOOutputQueue
* UniNEnet::createOutputQueue()
1005 return IOBasicOutputQueue::withTarget( this, TRANSMIT_QUEUE_SIZE
);
1006 }/* end createOutputQueue */
1009 /*-------------------------------------------------------------------------
1013 *-------------------------------------------------------------------------*/
1015 static struct MediumTable
1022 { kIOMediumEthernetNone
, 0 },
1023 { kIOMediumEthernetAuto
, 0 },
1024 { kIOMediumEthernet10BaseT
| kIOMediumOptionHalfDuplex
, 10 },
1025 { kIOMediumEthernet10BaseT
| kIOMediumOptionFullDuplex
, 10 },
1026 { kIOMediumEthernet100BaseTX
| kIOMediumOptionHalfDuplex
, 100 },
1027 { kIOMediumEthernet100BaseTX
| kIOMediumOptionFullDuplex
, 100 },
1028 { kIOMediumEthernet1000BaseSX
| kIOMediumOptionFullDuplex
, 1000 },
1029 { kIOMediumEthernet1000BaseTX
| kIOMediumOptionFullDuplex
, 1000 }
1033 bool UniNEnet::createMediumTables()
1035 IONetworkMedium
*medium
;
1038 mediumDict
= OSDictionary::withCapacity( sizeof(mediumTable
)/sizeof(mediumTable
[0]) );
1039 if ( mediumDict
== 0 ) return false;
1041 for ( i
=0; i
< sizeof(mediumTable
)/sizeof(mediumTable
[0]); i
++ )
1043 medium
= IONetworkMedium::medium( mediumTable
[i
].type
, mediumTable
[i
].speed
);
1046 IONetworkMedium::addMedium( mediumDict
, medium
);
1051 if ( publishMediumDictionary( mediumDict
) != true )
1056 medium
= IONetworkMedium::getMediumWithType( mediumDict
,
1057 kIOMediumEthernetAuto
);
1059 setCurrentMedium( medium
);
1065 void UniNEnet::writeRegister( UInt32
*pReg
, UInt32 data
)
1067 /// ELG( data, (UInt32)pReg - (UInt32)fpRegs, 'wReg', "writeRegister" );
1069 OSWriteLittleInt32( pReg
, 0, data
);
1071 }/* end writeRegister */