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) 1996 NeXT Software, Inc. All rights reserved.
29 * 22-Jan-96 Dieter Siegmund (dieter) at NeXT
32 * 03-May-96 Dieter Siegmund (dieter) at NeXT
33 * Added a real ISR to improve performance.
35 * 10-June-96 Dieter Siegmund (dieter) at NeXT
36 * Added support for Splash 3 (10 Base-T only card).
38 * 18-June-96 Dieter Siegmund (dieter) at NeXT
39 * Keep the transmit queue draining by interrupting every
40 * N / 2 transmits (where N is the size of the hardware queue).
42 * 15-Dec-97 Joe Liu (jliu) at Apple
43 * Updated PHY programming to be 82558 aware.
44 * Misc changes to conform to new 82558 register flags.
45 * Changed RNR interrupt handler to restart RU instead of a reset.
46 * Interrupt handler now does a thread_call_func() to do most of its work.
47 * Interrupts are disabled until the thread callout finishes its work.
48 * Increased the size of TX/RX rings.
49 * buffer object removed, we use cluster mbufs to back up the receive ring.
51 * 29-May-98 Joe Liu (jliu) at Apple
52 * Updated _setupPhy method to take advantage of parallel detection whenever
53 * possible in order to detect the proper link speed.
55 * 17-Aug-98 Joe Liu (jliu) at Apple
56 * Re-enabled the setting of txready_sel PHY (PCS) bit for DP83840.
57 * Simplified interrupt handling, resulting in RCV performance improvements.
58 * Receive packets are sent upstream via a cached function pointer.
63 #define ONE_SECOND_TICKS 1000
64 #define LOAD_STATISTICS_INTERVAL (4 * ONE_SECOND_TICKS)
66 #define super IOEthernetController
67 OSDefineMetaClassAndStructors( Intel82557
, IOEthernetController
)
69 //---------------------------------------------------------------------------
70 // Function: pciConfigInit
72 // Update PCI command register to enable the memory-mapped range,
73 // and bus-master interface.
75 bool Intel82557::pciConfigInit(IOPCIDevice
* provider
)
79 reg
= provider
->configRead32( kIOPCIConfigCommand
);
81 reg
|= ( kIOPCICommandBusMaster
|
82 kIOPCICommandMemorySpace
|
83 kIOPCICommandMemWrInvalidate
);
85 reg
&= ~kIOPCICommandIOSpace
; // disable I/O space
87 provider
->configWrite32( kIOPCIConfigCommand
, reg
);
92 //---------------------------------------------------------------------------
93 // Function: initDriver
95 // Create and initialize driver objects before the hardware is
98 // Returns true on sucess, and false if initialization failed.
100 bool Intel82557::initDriver(IOService
* provider
)
102 currentMediumType
= MEDIUM_TYPE_INVALID
;
104 // This driver will allocate and use an IOGatedOutputQueue.
106 transmitQueue
= getOutputQueue();
107 if ( transmitQueue
== 0 ) return false;
109 // Allocate two IOMbufLittleMemoryCursor instances. One for transmit and
110 // the other for receive.
112 rxMbufCursor
= IOMbufLittleMemoryCursor::withSpecification(MAX_BUF_SIZE
,1);
113 txMbufCursor
= IOMbufLittleMemoryCursor::withSpecification(MAX_BUF_SIZE
,
115 if (!rxMbufCursor
|| !txMbufCursor
)
118 // Get a handle to our superclass' workloop.
120 IOWorkLoop
* myWorkLoop
= (IOWorkLoop
*) getWorkLoop();
124 // Create and register an interrupt event source. The provider will
125 // take care of the low-level interrupt registration stuff.
128 IOInterruptEventSource::interruptEventSource(this,
129 (IOInterruptEventAction
) &Intel82557::interruptOccurred
,
133 (myWorkLoop
->addEventSource(interruptSrc
) != kIOReturnSuccess
))
136 // Register a timer event source. This is used as a watchdog timer.
138 timerSrc
= IOTimerEventSource::timerEventSource( this,
139 (IOTimerEventSource::Action
) &Intel82557::timeoutOccurred
);
141 (myWorkLoop
->addEventSource(timerSrc
) != kIOReturnSuccess
))
144 // Create a dictionary to hold IONetworkMedium objects.
146 mediumDict
= OSDictionary::withCapacity(5);
153 //---------------------------------------------------------------------------
154 // Function: getDefaultSettings
156 // Get the default driver settings chosen by the user. The properties
157 // are all stored in our property table (an OSDictionary).
159 bool Intel82557::getDefaultSettings()
164 // Check for PHY address override.
166 phyAddr
= PHY_ADDRESS_DEFAULT
;
167 numObj
= OSDynamicCast( OSNumber
, getProperty("PHY Address") );
170 phyAddr
= numObj
->unsigned32BitValue();
173 // Check for Verbose flag.
176 boolObj
= OSDynamicCast( OSBoolean
, getProperty("Verbose") );
177 if ( boolObj
&& boolObj
->isTrue() )
179 IOLog("%s: verbose mode enabled\n", getName());
183 // Check for Flow-Control enable flag.
186 boolObj
= OSDynamicCast( OSBoolean
, getProperty("Flow Control") );
187 if ( boolObj
&& boolObj
->isTrue() )
189 IOLog("%s: 802.3x flow control enabled\n", getName());
196 //---------------------------------------------------------------------------
197 // Function: start <IOService>
199 // Hardware was detected and initialized, start the driver.
201 bool Intel82557::start( IOService
* provider
)
206 // Start our superclass first.
208 if ( super::start(provider
) == false )
211 // Cache our provider to an instance variable.
213 pciNub
= OSDynamicCast(IOPCIDevice
, provider
);
214 if ( pciNub
== 0 ) break;
216 // Retain provider, released in free().
220 // Open our provider.
222 if ( pciNub
->open(this) == false ) break;
224 // Initialize the driver's event sources and other support objects.
226 if ( initDriver(provider
) == false ) break;
228 // Get the virtual address mapping of CSR registers located at
229 // Base Address Range 0 (0x10). The size of this range is 4K.
231 csrMap
= pciNub
->mapDeviceMemoryWithRegister( kIOPCIConfigBaseAddress0
);
232 if ( csrMap
== 0 ) break;
234 CSR_p
= (CSR_t
*) csrMap
->getVirtualAddress();
236 // Setup our PCI config space.
238 if ( pciConfigInit(pciNub
) == false ) break;
240 // Create the EEPROM object.
242 eeprom
= i82557eeprom::withAddress(&CSR_p
->eepromControl
);
245 IOLog("%s: couldn't allocate eeprom object", getName());
249 // Get default driver settings (stored in property table).
251 if ( getDefaultSettings() == false ) break;
253 if ( verbose
) eeprom
->dumpContents();
255 // Execute one-time initialization code.
257 if ( coldInit() == false )
259 IOLog("%s: coldInit failed\n", getName());
263 if ( hwInit() == false )
265 IOLog("%s: hwInit failed\n", getName());
269 // Publish our media capabilities.
272 if ( publishMediumDictionary(mediumDict
) == false )
274 IOLog("%s: publishMediumDictionary failed\n", getName());
279 // Announce the basic hardware configuration info.
280 IOLog("%s: Memory 0x%lx irq %d\n", getName(),
281 csrMap
->getPhysicalAddress(), 0);
288 // Close our provider, it will be re-opened on demand when
289 // our enable() is called.
291 if ( pciNub
) pciNub
->close(this);
294 if ( ret
== false ) break;
298 // Allocate and attach an IOEthernetInterface instance to this driver
301 if ( attachInterface((IONetworkInterface
**) &netif
, false) == false )
304 // Attach a kernel debugger client. This is not an essential service,
305 // and the return is not checked.
307 attachDebuggerClient(&debugger
);
309 // Start matching for clients of IONetworkInterface.
311 netif
->registerService();
320 //---------------------------------------------------------------------------
321 // Function: stop <IOService>
323 // Stop all activities and prepare for termination.
325 void Intel82557::stop(IOService
* provider
)
327 super::stop(provider
);
330 //---------------------------------------------------------------------------
331 // Function: createWorkLoop <IONetworkController>
333 // Override IONetworkController::createWorkLoop() method to create a workloop.
335 bool Intel82557::createWorkLoop()
337 workLoop
= IOWorkLoop::workLoop();
339 return ( workLoop
!= 0 );
342 //---------------------------------------------------------------------------
343 // Function: getWorkLoop <IOService>
345 // Override IOService::getWorkLoop() method to return our workloop.
347 IOWorkLoop
* Intel82557::getWorkLoop() const
352 //---------------------------------------------------------------------------
353 // Function: configureInterface <IONetworkController>
355 // Configure a newly instantiated IONetworkInterface object.
357 bool Intel82557::configureInterface(IONetworkInterface
* netif
)
359 IONetworkData
* data
;
361 if ( super::configureInterface(netif
) == false )
364 // Get the generic network statistics structure.
366 data
= netif
->getParameter(kIONetworkStatsKey
);
367 if (!data
|| !(netStats
= (IONetworkStats
*) data
->getBuffer())) {
371 // Get the Ethernet statistics structure.
373 data
= netif
->getParameter(kIOEthernetStatsKey
);
374 if (!data
|| !(etherStats
= (IOEthernetStats
*) data
->getBuffer())) {
381 //---------------------------------------------------------------------------
382 // Function: free <IOService>
384 // Deallocate all resources and destroy the instance.
386 void Intel82557::free()
388 if (debugger
) { debugger
->release(); debugger
= 0; }
389 if (netif
) { netif
->release(); netif
= 0; }
390 if (interruptSrc
) { interruptSrc
->release(); interruptSrc
= 0; }
391 if (timerSrc
) { timerSrc
->release(); timerSrc
= 0; }
392 if (rxMbufCursor
) { rxMbufCursor
->release(); rxMbufCursor
= 0; }
393 if (txMbufCursor
) { txMbufCursor
->release(); txMbufCursor
= 0; }
394 if (csrMap
) { csrMap
->release(); csrMap
= 0; }
395 if (eeprom
) { eeprom
->release(); eeprom
= 0; }
396 if (mediumDict
) { mediumDict
->release(); mediumDict
= 0; }
397 if ( pciNub
) { pciNub
->release(); pciNub
= 0; }
398 if ( workLoop
) { workLoop
->release(); workLoop
= 0; }
400 _freeMemPage( &shared
);
401 _freeMemPage( &txRing
);
402 _freeMemPage( &rxRing
);
404 super::free(); // pass it to our superclass
407 //---------------------------------------------------------------------------
408 // Function: enableAdapter
410 // Enables the adapter & driver to the given level of support.
412 bool Intel82557::enableAdapter(UInt32 level
)
416 // IOLog("%s::%s enabling level %ld\n", getName(), __FUNCTION__, level);
419 case kActivationLevel1
:
423 if ( ( pciNub
== 0 ) || ( pciNub
->open(this) == false ) )
428 if (!_initRingBuffers())
431 if (!_startReceive()) {
436 // Set current medium.
438 if (setMedium(getCurrentMedium()) != kIOReturnSuccess
)
439 IOLog("%s: setMedium error\n", getName());
441 // Start the watchdog timer.
443 timerSrc
->setTimeoutMS(LOAD_STATISTICS_INTERVAL
);
445 // Enable interrupt event sources and hardware interrupts.
448 getWorkLoop()->enableAllInterrupts();
449 enableAdapterInterrupts();
451 // Force PHY to report link status.
453 _phyReportLinkStatus(true);
458 case kActivationLevel2
:
459 // Issue a dump statistics command.
463 // Start our IOOutputQueue object.
465 transmitQueue
->setCapacity(TRANSMIT_QUEUE_SIZE
);
466 transmitQueue
->start();
473 IOLog("%s::%s error in level %ld\n", getName(), __FUNCTION__
, level
);
478 //---------------------------------------------------------------------------
479 // Function: disableAdapter
481 // Disables the adapter & driver to the given level of support.
483 bool Intel82557::disableAdapter(UInt32 level
)
487 // IOLog("%s::%s disabling level %ld\n", getName(), __FUNCTION__, level);
490 case kActivationLevel1
:
491 // Disable interrupt handling and hardware interrupt sources.
493 disableAdapterInterrupts();
495 getWorkLoop()->disableAllInterrupts();
497 // Stop the timer event source, and initialize the watchdog state.
499 timerSrc
->cancelTimeout();
500 packetsReceived
= true; // assume we're getting packets
501 packetsTransmitted
= false;
504 // Reset the hardware engine.
508 // Clear the descriptor rings after the hardware is idle.
512 // Report link status: unknown.
516 // Flush all packets held in the queue and prevent it
517 // from accumulating any additional packets.
519 transmitQueue
->setCapacity(0);
520 transmitQueue
->flush();
531 case kActivationLevel2
:
532 // Stop the transmit queue. outputPacket() will not get called
535 transmitQueue
->stop();
542 IOLog("%s::%s error in level %ld\n", getName(), __FUNCTION__
, level
);
547 //---------------------------------------------------------------------------
548 // Function: setActivationLevel
550 // Sets the adapter's activation level.
552 // kActivationLevel0 - Adapter is disabled.
553 // kActivationLevel1 - Adapter is brought up just enough to support debugging.
554 // kActivationLevel2 - Adapter is completely up.
556 bool Intel82557::setActivationLevel(UInt32 level
)
561 // IOLog("---> DESIRED LEVEL : %d\n", level);
563 if (currentLevel
== level
) return true;
565 for ( ; currentLevel
> level
; currentLevel
--)
567 if ( (ret
= disableAdapter(currentLevel
)) == false )
571 for ( nextLevel
= currentLevel
+ 1;
572 currentLevel
< level
;
573 currentLevel
++, nextLevel
++ )
575 if ( (ret
= enableAdapter(nextLevel
)) == false )
579 // IOLog("---> PRESENT LEVEL : %d\n\n", currentLevel);
584 //---------------------------------------------------------------------------
585 // Function: enable <IONetworkController>
587 // A request from our interface client to enable the adapter.
589 IOReturn
Intel82557::enable(IONetworkInterface
* /*netif*/)
591 if ( enabledForNetif
) return kIOReturnSuccess
;
593 enabledForNetif
= setActivationLevel( kActivationLevel2
);
595 return ( enabledForNetif
? kIOReturnSuccess
: kIOReturnIOError
);
598 //---------------------------------------------------------------------------
599 // Function: disable <IONetworkController>
601 // A request from our interface client to disable the adapter.
603 IOReturn
Intel82557::disable(IONetworkInterface
* /*netif*/)
605 enabledForNetif
= false;
607 setActivationLevel( enabledForDebugger
?
608 kActivationLevel1
: kActivationLevel0
);
610 return kIOReturnSuccess
;
613 //---------------------------------------------------------------------------
614 // Function: enable <IONetworkController>
616 // A request from our debugger client to enable the adapter.
618 IOReturn
Intel82557::enable(IOKernelDebugger
* /*debugger*/)
620 if ( enabledForDebugger
|| enabledForNetif
)
622 enabledForDebugger
= true;
623 return kIOReturnSuccess
;
626 enabledForDebugger
= setActivationLevel( kActivationLevel1
);
628 return ( enabledForDebugger
? kIOReturnSuccess
: kIOReturnIOError
);
631 //---------------------------------------------------------------------------
632 // Function: disable <IONetworkController>
634 // A request from our debugger client to disable the adapter.
636 IOReturn
Intel82557::disable(IOKernelDebugger
* /*debugger*/)
638 enabledForDebugger
= false;
640 if ( enabledForNetif
== false )
641 setActivationLevel( kActivationLevel0
);
643 return kIOReturnSuccess
;
646 //---------------------------------------------------------------------------
647 // Function: timeoutOccurred
649 // Periodic timer that monitors the receiver status, updates error
650 // and collision statistics, and update the current link status.
652 void Intel82557::timeoutOccurred(IOTimerEventSource
* /*timer*/)
654 if ( (packetsReceived
== false) && (packetsTransmitted
== true) )
657 * The B-step of the i82557 requires that an mcsetup command be
658 * issued if the receiver stops receiving. This is a documented
663 packetsReceived
= packetsTransmitted
= false;
667 _phyReportLinkStatus();
669 timerSrc
->setTimeoutMS(LOAD_STATISTICS_INTERVAL
);
672 //---------------------------------------------------------------------------
673 // Function: setPromiscuousMode <IOEthernetController>
675 IOReturn
Intel82557::setPromiscuousMode(IOEnetPromiscuousMode mode
)
678 promiscuousEnabled
= (mode
== kIOEnetPromiscuousModeOff
) ? false : true;
679 reserveDebuggerLock();
681 releaseDebuggerLock();
682 return (rv
? kIOReturnSuccess
: kIOReturnIOError
);
685 //---------------------------------------------------------------------------
686 // Function: setMulticastMode <IOEthernetController>
688 IOReturn
Intel82557::setMulticastMode(IOEnetMulticastMode mode
)
690 multicastEnabled
= (mode
== kIOEnetMulticastModeOff
) ? false : true;
691 return kIOReturnSuccess
;
694 //---------------------------------------------------------------------------
695 // Function: setMulticastList <IOEthernetController>
697 IOReturn
Intel82557::setMulticastList(IOEthernetAddress
* addrs
, UInt32 count
)
699 IOReturn ret
= kIOReturnSuccess
;
701 if ( mcSetup(addrs
, count
) == false )
703 IOLog("%s: set multicast list failed\n", getName());
704 ret
= kIOReturnIOError
;
709 //---------------------------------------------------------------------------
710 // Function: getPacketBufferConstraints <IONetworkController>
712 // Return our driver's packet alignment requirements.
715 Intel82557::getPacketBufferConstraints(IOPacketBufferConstraints
* constraints
) const
717 constraints
->alignStart
= kIOPacketBufferAlign2
; // even word aligned.
718 constraints
->alignLength
= kIOPacketBufferAlign1
; // no restriction.
721 //---------------------------------------------------------------------------
722 // Function: getHardwareAddress <IOEthernetController>
724 // Return the adapter's hardware/Ethernet address.
726 IOReturn
Intel82557::getHardwareAddress(IOEthernetAddress
* addrs
)
728 bcopy(&myAddress
, addrs
, sizeof(*addrs
));
729 return kIOReturnSuccess
;
732 //---------------------------------------------------------------------------
733 // Function: createOutputQueue <IONetworkController>
735 // Allocate an IOGatedOutputQueue instance.
737 IOOutputQueue
* Intel82557::createOutputQueue()
739 return IOGatedOutputQueue::withTarget(this, getWorkLoop());
742 //---------------------------------------------------------------------------
743 // Function: setMedium <IONetworkController>
745 // Transition the controller/PHY to use a new medium. Note that
746 // this function can be called my the driver, or by our client.
748 IOReturn
Intel82557::setMedium(const IONetworkMedium
* medium
)
752 if ( OSDynamicCast(IONetworkMedium
, medium
) == 0 )
755 medium
= _phyGetMediumWithType( MEDIUM_TYPE_AUTO
);
756 if ( medium
== 0 ) return kIOReturnError
;
760 IOLog("%s: setMedium -> %s\n", getName(),
761 medium
->getName()->getCStringNoCopy());
764 // Program PHY to select the desired medium.
766 r
= _phySetMedium( (mediumType_t
) medium
->getIndex() );
768 // Update the current medium property.
770 if ( r
&& !setCurrentMedium(medium
) )
771 IOLog("%s: setCurrentMedium error\n", getName());
773 return ( r
? kIOReturnSuccess
: kIOReturnIOError
);
776 //---------------------------------------------------------------------------
777 // Function: newVendorString(), newModelString()
778 // <IONetworkController>
780 // Report human readable hardware information strings.
782 const OSString
* Intel82557::newVendorString() const
784 return OSString::withCString("Intel");
787 const OSString
* Intel82557::newModelString() const
789 const char * model
= 0;
791 assert( eeprom
&& eeprom
->getContents() );
793 switch ( eeprom
->getContents()->controllerType
)
795 case I82558_CONTROLLER_TYPE
:
798 case I82557_CONTROLLER_TYPE
:
803 return OSString::withCString(model
);
806 //---------------------------------------------------------------------------
807 // Kernel debugger entry points.
809 // KDP driven polling routines to send and transmit a frame.
810 // Remember, no memory allocation! Not even mbufs are safe.
812 void Intel82557::sendPacket(void * pkt
, UInt32 pkt_len
)
814 _sendPacket(pkt
, pkt_len
);
817 void Intel82557::receivePacket(void * pkt
, UInt32
* pkt_len
, UInt32 timeout
)
819 _receivePacket(pkt
, (UInt
*) pkt_len
, timeout
);