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 * Hardware independent (relatively) code for the BMac Ethernet Controller
33 * Converted to IOKit/C++.
37 #include "BMacEnetPrivate.h"
39 #include <IOKit/IORegistryEntry.h>
40 #include <IOKit/IODeviceTreeSupport.h>
41 #include <IOKit/platform/AppleMacIODevice.h>
42 #include <IOKit/assert.h>
44 // #define DEBUG_JOE 1
46 //------------------------------------------------------------------------
48 #define super IOEthernetController
50 OSDefineMetaClassAndStructors( BMacEnet
, IOEthernetController
)
52 //------------------------------------------------------------------------
54 #define PROVIDER_DEV 0
55 #define PROVIDER_DMA_TX 1
56 #define PROVIDER_DMA_RX 2
59 * Public Instance Methods
62 /*-------------------------------------------------------------------------
66 *-------------------------------------------------------------------------*/
68 bool BMacEnet::init(OSDictionary
* properties
= 0)
70 if ( super::init(properties
) == false )
74 * Initialize my ivars.
77 phyMIIDelay
= MII_DEFAULT_DELAY
;
79 enetAddressOffset
= 20;
85 bool BMacEnet::start(IOService
* provider
)
87 AppleMacIODevice
*nub
= OSDynamicCast(AppleMacIODevice
, provider
);
88 IOInterruptEventSource
*intES
;
90 if (!nub
|| !super::start(provider
))
93 transmitQueue
= OSDynamicCast(IOGatedOutputQueue
, getOutputQueue());
95 IOLog("BMac: output queue initialization failed\n");
98 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);
112 // Allocate a IOMbufBigMemoryCursor instance. Currently, the maximum
113 // number of segments is set to 2. The maximum length for each segment
114 // is set to the maximum ethernet frame size (plus padding).
116 mbufCursor
= IOMbufBigMemoryCursor::withSpecification(NETWORK_BUFSIZE
, 2);
118 IOLog("Ethernet(BMac): IOMbufBigMemoryCursor allocation failure\n");
123 // Our provider is the nub representing the BMacEnet hardware
124 // controller. We will query it for our resource information.
127 for (int i
= 0; i
< MEMORY_MAP_HEATHROW_INDEX
; i
++) {
130 map
= provider
->mapDeviceMemoryWithIndex(i
);
134 IOLog("map %d: Phys:%08x Virt:%08x len:%d\n",
136 (unsigned) map
->getPhysicalAddress(),
137 (unsigned) map
->getVirtualAddress(),
138 (unsigned) map
->getLength());
142 case MEMORY_MAP_ENET_INDEX
:
143 ioBaseEnet
= (IOPPCAddress
) map
->getVirtualAddress();
146 case MEMORY_MAP_TXDMA_INDEX
:
147 ioBaseEnetTxDMA
= (IODBDMAChannelRegisters
*)
148 map
->getVirtualAddress();
151 case MEMORY_MAP_RXDMA_INDEX
:
152 ioBaseEnetRxDMA
= (IODBDMAChannelRegisters
*)
153 map
->getVirtualAddress();
161 IOLog("ioBaseEnet: 0x%08x\n", ioBaseEnet
);
162 IOLog("ioBaseEnetTxDMA: 0x%08x\n", ioBaseEnetTxDMA
);
163 IOLog("ioBaseEnetRxDMA: 0x%08x\n", ioBaseEnetRxDMA
);
167 // We need to get the I/O address for the Heathrow controller.
168 // We ask the provider (bmac) for its device tree parent.
171 if (!(heathrow
= OSDynamicCast(IOService
,
172 provider
->getParentEntry( gIODTPlane
))))
175 // Check whether the hardware is susceptible to the broken unicast
179 devIDData
= OSDynamicCast(OSData
, heathrow
->getProperty("device-id"));
182 useUnicastFilter
= ( *((UInt32
*) devIDData
->getBytesNoCopy()) ==
184 if (useUnicastFilter
)
185 IOLog("%s: Enabling workaround for broken unicast filter\n",
189 IOMemoryMap
* map
= heathrow
->mapDeviceMemoryWithIndex(0);
193 IOLog("Heathrow: Phys:%08x Virt:%08x len:%d\n",
194 (unsigned) map
->getPhysicalAddress(),
195 (unsigned) map
->getVirtualAddress(),
196 (unsigned) map
->getLength());
198 ioBaseHeathrow
= (IOPPCAddress
) map
->getVirtualAddress();
200 maps
[MEMORY_MAP_HEATHROW_INDEX
] = map
;
207 // Get a reference to the IOWorkLoop in our superclass.
209 IOWorkLoop
* myWorkLoop
= getWorkLoop();
213 // Allocate three IOInterruptEventSources.
215 rxIntSrc
= IOInterruptEventSource::interruptEventSource
217 (IOInterruptEventAction
) &BMacEnet::interruptOccurredForSource
,
218 provider
, PROVIDER_DMA_RX
);
220 || (myWorkLoop
->addEventSource(rxIntSrc
) != kIOReturnSuccess
)) {
221 IOLog("Ethernet(BMac): rxIntSrc init failure\n");
225 intES
= IOInterruptEventSource::interruptEventSource
227 (IOInterruptEventAction
) &BMacEnet::interruptOccurredForSource
,
228 provider
, PROVIDER_DMA_TX
);
230 bool res
= (myWorkLoop
->addEventSource(intES
) != kIOReturnSuccess
);
233 IOLog("Ethernet(BMac): PROVIDER_DMA_TX add failure\n");
238 IOLog("Mace: PROVIDER_DMA_TX init failure\n");
242 intES
= IOInterruptEventSource::interruptEventSource
244 (IOInterruptEventAction
) &BMacEnet::interruptOccurredForSource
,
245 provider
, PROVIDER_DEV
);
247 bool res
= (myWorkLoop
->addEventSource(intES
) != kIOReturnSuccess
);
250 IOLog("Ethernet(BMac): PROVIDER_DEV add failure\n");
255 IOLog("Ethernet(BMac): PROVIDER_DEV init failure\n");
259 timerSrc
= IOTimerEventSource::timerEventSource
260 (this, (IOTimerEventSource::Action
) &BMacEnet::timeoutOccurred
);
262 || (myWorkLoop
->addEventSource(timerSrc
) != kIOReturnSuccess
)) {
263 IOLog("Ethernet(BMac): timerSrc init failure\n");
267 MGETHDR(txDebuggerPkt
, M_DONTWAIT
, MT_DATA
);
268 if (!txDebuggerPkt
) {
269 IOLog("Ethernet(BMac): Couldn't allocate KDB buffer\n");
274 // Enable the interrupt event sources. The hardware interrupts
275 // sources remain disabled until _resetAndEnable(true) is called.
277 // myWorkLoop->enableAllInterrupts();
280 // Perform a hardware reset.
282 if ( !_resetAndEnable(false) )
287 // Cache my MAC address.
289 getHardwareAddress(&myAddress
);
291 // Allocate memory for ring buffers.
293 if (_allocateMemory() == false)
298 // Create a table of supported media types.
300 if ( !createMediumTables() )
303 // Attach an IOEthernetInterface client.
305 if ( !attachInterface((IONetworkInterface
**) &networkInterface
, false) )
308 // Attach a kernel debugger client.
310 attachDebuggerClient(&debugger
);
312 // Ready to service interface requests.
314 networkInterface
->registerService();
319 /*-------------------------------------------------------------------------
323 *-------------------------------------------------------------------------*/
325 void BMacEnet::free()
329 _resetAndEnable(false);
335 getWorkLoop()->disableAllEventSources();
344 freePacket(txDebuggerPkt
);
347 transmitQueue
->release();
350 debugQueue
->release();
352 if (networkInterface
)
353 networkInterface
->release();
356 mbufCursor
->release();
359 mediumDict
->release();
361 for (i
= 0; i
< rxMaxCommand
; i
++)
362 if (rxMbuf
[i
]) freePacket(rxMbuf
[i
]);
364 for (i
= 0; i
< txMaxCommand
; i
++)
365 if (txMbuf
[i
]) freePacket(txMbuf
[i
]);
367 for (i
= 0; i
< MEMORY_MAP_COUNT
; i
++)
368 if (maps
[i
]) maps
[i
]->release();
372 IOFree(dmaMemory
.ptrReal
, dmaMemory
.sizeReal
);
385 /*-------------------------------------------------------------------------
386 * Override IONetworkController::createWorkLoop() method and create
389 *-------------------------------------------------------------------------*/
391 bool BMacEnet::createWorkLoop()
393 workLoop
= IOWorkLoop::workLoop();
395 return ( workLoop
!= 0 );
398 /*-------------------------------------------------------------------------
399 * Override IOService::getWorkLoop() method to return our workloop.
402 *-------------------------------------------------------------------------*/
404 IOWorkLoop
* BMacEnet::getWorkLoop() const
409 /*-------------------------------------------------------------------------
413 *-------------------------------------------------------------------------*/
415 void BMacEnet::interruptOccurredForSource(IOInterruptEventSource
*src
,
418 bool doFlushQueue
= false;
419 bool doService
= false;
421 reserveDebuggerLock();
423 statReg
= ReadBigMacRegister( ioBaseEnet
, kSTAT
);
425 if (src
== rxIntSrc
) {
426 KERNEL_DEBUG(DBG_BMAC_RXIRQ
| DBG_FUNC_START
, 0, 0, 0, 0, 0 );
427 doFlushQueue
= _receiveInterruptOccurred();
428 KERNEL_DEBUG(DBG_BMAC_RXIRQ
| DBG_FUNC_END
, 0, 0, 0, 0, 0 );
432 * On the transmit side, we use the chipset interrupt. Using the
433 * transmit DMA interrupt (or having multiple transmit DMA entries)
434 * would allows us to send the next frame to the chipset prior the
435 * transmit fifo going empty.
436 * However, this aggrevates a BMac chipset bug where the next frame going
437 * out gets corrupted (first two bytes lost) if the chipset had to retry
438 * the previous frame.
441 KERNEL_DEBUG(DBG_BMAC_TXIRQ
| DBG_FUNC_START
, 0, 0, 0, 0, 0 );
442 doService
= _transmitInterruptOccurred();
443 KERNEL_DEBUG(DBG_BMAC_TXIRQ
| DBG_FUNC_END
, 0, 0, 0, 0, 0 );
446 releaseDebuggerLock();
449 * Submit all received packets queued up by _receiveInterruptOccurred()
450 * to the network stack. The up call is performed without holding the
454 networkInterface
->flushInputQueue();
457 * Unstall the output queue if some space was made available.
459 if ( doService
&& netifEnabled
)
460 transmitQueue
->service();
463 /*-------------------------------------------------------------------------
467 *-------------------------------------------------------------------------*/
469 UInt32
BMacEnet::outputPacket(struct mbuf
* pkt
, void * param
)
472 UInt32 ret
= kIOReturnOutputSuccess
;
474 KERNEL_DEBUG(DBG_BMAC_TXQUEUE
| DBG_FUNC_NONE
, (int) pkt
,
475 (int) pkt
->m_pkthdr
.len
, 0, 0, 0 );
478 * Hold the debugger lock so the debugger can't interrupt us
480 reserveDebuggerLock();
485 * Preliminary sanity checks
487 assert( pkt
&& netifEnabled
);
491 * Remove any completed packets from the Tx ring
493 if ( chipId
>= kCHIPID_PaddingtonXmitStreaming
)
495 _transmitInterruptOccurred();
499 i
= txCommandTail
+ 1;
500 if ( i
>= txMaxCommand
) i
= 0;
501 if ( i
== txCommandHead
)
504 * Ring buffer is full. Disable the dequeueing process.
505 * We reenable it when an entry is made available by the
506 * transmit interrupt handler, or if a timeout occurs.
508 ret
= kIOReturnOutputStall
;
513 * If there is space on the Tx ring, add the packet directly to the
516 _transmitPacket(pkt
);
520 releaseDebuggerLock();
525 /*-------------------------------------------------------------------------
529 *-------------------------------------------------------------------------*/
531 bool BMacEnet::_resetAndEnable(bool enable
)
535 // reserveDebuggerLock();
539 if (timerSrc
) timerSrc
->cancelTimeout();
541 _disableAdapterInterrupts();
542 if (getWorkLoop()) getWorkLoop()->disableAllInterrupts();
551 // Initialize the link status.
554 setLinkStatus( 0, 0 );
558 if (!_initRxRing() || !_initTxRing())
566 miiInitializePHY(phyId
);
569 if (_initChip() == false)
577 timerSrc
->setTimeoutMS(WATCHDOG_TIMER_MS
);
579 if (getWorkLoop()) getWorkLoop()->enableAllInterrupts();
580 _enableAdapterInterrupts();
586 monitorLinkStatus( true );
591 // releaseDebuggerLock();
596 /*-------------------------------------------------------------------------
597 * Grab a pointer to the statistics counters.
600 *-------------------------------------------------------------------------*/
602 bool BMacEnet::configureInterface( IONetworkInterface
* netif
)
606 if ( super::configureInterface( netif
) == false )
610 * Grab a pointer to the statistics structure in the interface.
612 nd
= netif
->getNetworkData( kIONetworkStatsKey
);
614 if ( !nd
|| !(netStats
= (IONetworkStats
*) nd
->getBuffer()) )
616 IOLog("EtherNet(BMac): invalid network statistics\n");
623 /*-------------------------------------------------------------------------
624 * Called by IOEthernetInterface client to enable the controller.
625 * This method is always called while running on the default workloop
627 *-------------------------------------------------------------------------*/
629 IOReturn
BMacEnet::enable(IONetworkInterface
* netif
)
631 // If an interface client has previously enabled us,
632 // and we know there can only be one interface client
633 // for this driver, then simply return true.
637 IOLog("EtherNet(BMac): already enabled\n");
638 return kIOReturnSuccess
;
641 if ( (ready
== false) && !_resetAndEnable(true) )
642 return kIOReturnIOError
;
644 // Record the interface as an active client.
648 // Start our IOOutputQueue object.
650 transmitQueue
->setCapacity(TRANSMIT_QUEUE_SIZE
);
651 transmitQueue
->start();
653 return kIOReturnSuccess
;
656 /*-------------------------------------------------------------------------
657 * Called by IOEthernetInterface client to disable the controller.
658 * This method is always called while running on the default workloop
660 *-------------------------------------------------------------------------*/
662 IOReturn
BMacEnet::disable(IONetworkInterface
* /*netif*/)
664 // Disable our IOOutputQueue object. This will prevent the
665 // outputPacket() method from being called.
667 transmitQueue
->stop();
669 // Flush all packets currently in the output queue.
671 transmitQueue
->setCapacity(0);
672 transmitQueue
->flush();
674 // If we have no active clients, then disable the controller.
676 if ( debugEnabled
== false )
678 _resetAndEnable(false);
681 netifEnabled
= false;
683 return kIOReturnSuccess
;
686 /*-------------------------------------------------------------------------
687 * This method is called by our debugger client to bring up the controller
688 * just before the controller is registered as the debugger device. The
689 * debugger client is attached in response to the attachDebuggerClient()
692 * This method is always called while running on the default workloop
694 *-------------------------------------------------------------------------*/
696 IOReturn
BMacEnet::enable(IOKernelDebugger
*debugger
)
698 // Enable hardware and make it ready to support the debugger client.
700 if ( (ready
== false) && !_resetAndEnable(true) )
702 return kIOReturnIOError
;
705 // Record the debugger as an active client of ours.
709 return kIOReturnSuccess
;
712 /*-------------------------------------------------------------------------
713 * This method is called by our debugger client to stop the controller.
714 * The debugger will call this method when we issue a detachDebuggerClient().
716 * This method is always called while running on the default workloop
718 *-------------------------------------------------------------------------*/
720 IOReturn
BMacEnet::disable(IOKernelDebugger
* /*debugger*/)
722 debugEnabled
= false;
724 // If we have no active clients, then disable the controller.
726 if ( netifEnabled
== false )
728 _resetAndEnable(false);
731 return kIOReturnSuccess
;
734 /*-------------------------------------------------------------------------
738 *-------------------------------------------------------------------------*/
740 void BMacEnet::timeoutOccurred(IOTimerEventSource
* /*timer*/)
743 bool doFlushQueue
= false;
744 bool doService
= false;
746 if ( ready
== false )
751 // IOLog("Ethernet(BMac): watchdog timer\n");
753 reserveDebuggerLock();
756 * Check for DMA shutdown on receive channel
758 dmaStatus
= IOGetDBDMAChannelStatus( ioBaseEnetRxDMA
);
759 if ( !(dmaStatus
& kdbdmaActive
) )
762 IOLog( "Ethernet(BMac): Timeout check - RxHead = %d RxTail = %d\n",
763 rxCommandHead
, rxCommandTail
);
765 IOLog( "Ethernet(BMac): Rx Commands = %08x(p) Rx DMA Ptr = %08x(p)\n\r", rxDMACommandsPhys
, IOGetDBDMACommandPtr(ioBaseEnetRxDMA
) );
766 [self _dumpDesc
:(void *)rxDMACommands Size
:rxMaxCommand
* sizeof(enet_dma_cmd_t
)];
769 doFlushQueue
= _receiveInterruptOccurred();
773 * If there are pending entries on the Tx ring
775 if ( txCommandHead
!= txCommandTail
)
778 * If we did not service the Tx ring during the last timeout interval,
779 * then force servicing of the Tx ring
781 if ( txWDInterrupts
== 0 )
783 if ( txWDCount
++ > 0 )
785 if (_transmitInterruptOccurred() == false)
788 IOLog( "Ethernet(BMac): Timeout check - TxHead = %d TxTail = %d\n",
789 txCommandHead
, txCommandTail
);
791 _restartTransmitter();
808 // Poll link status periodically.
812 // Clean-up after the debugger if the debugger was active.
821 releaseDebuggerLock();
824 * Submit all received packets queued up by _receiveInterruptOccurred()
825 * to the network stack. This call is performed without holding the
830 networkInterface
->flushInputQueue();
834 * Make sure the output queue is not stalled.
836 if ( doService
&& netifEnabled
)
838 transmitQueue
->service();
842 * Restart the watchdog timer
844 timerSrc
->setTimeoutMS(WATCHDOG_TIMER_MS
);
847 /*-------------------------------------------------------------------------
851 *-------------------------------------------------------------------------*/
853 void BMacEnet::monitorLinkStatus( bool firstPoll
)
857 u_int16_t phyStatusChange
;
859 bool reportLinkStatus
= false;
865 // For implementations without a PHY, query the link status bit from
866 // the transceiver control register (kXCVRIF).
868 phyStatus
= ReadBigMacRegister(ioBaseEnet
, kXCVRIF
);
870 if ( ( ( phyStatus
^ phyStatusPrev
) & kLinkStatus
) || firstPoll
)
872 linkStatus
= kIONetworkLinkValid
;
875 reportLinkStatus
= true;
877 if ( ( phyStatus
& kLinkStatus
) == 0 )
880 linkStatus
|= kIONetworkLinkActive
;
883 phyStatusPrev
= phyStatus
;
886 else if ( miiReadWord(&phyStatus
, MII_STATUS
, phyId
) == true )
888 phyStatusChange
= ( phyStatusPrev
^ phyStatus
) &
889 ( MII_STATUS_LINK_STATUS
|
890 MII_STATUS_NEGOTIATION_COMPLETE
);
892 if ( phyStatusChange
|| firstPoll
)
896 // For the initial link status poll, wait a bit, then
897 // re-read the status register to clear any latched bits.
898 // Why wait? Well, the debugger can kick in shortly after
899 // this function returns, and we want the duplex setting
900 // on the MAC to match the PHY.
902 miiWaitForAutoNegotiation( phyId
);
903 miiReadWord(&phyStatus
, MII_STATUS
, phyId
);
904 miiReadWord(&phyStatus
, MII_STATUS
, phyId
);
907 if ( (phyStatus
& MII_STATUS_LINK_STATUS
) &&
908 (firstPoll
|| (phyStatus
& MII_STATUS_NEGOTIATION_COMPLETE
)) )
910 if ( (phyType
& MII_ST10040_MASK
) == MII_ST10040_ID
)
912 miiReadWord(&phyReg
, MII_ST10040_CHIPST
, phyId
);
913 linkSpeed
= (phyReg
& MII_ST10040_CHIPST_SPEED
) ?
915 fullDuplex
= (phyReg
& MII_ST10040_CHIPST_DUPLEX
) ?
918 else if ( (phyType
& MII_DP83843_MASK
) == MII_DP83843_ID
)
920 miiReadWord(&phyReg
, MII_DP83843_PHYSTS
, phyId
);
921 linkSpeed
= (phyReg
& MII_DP83843_PHYSTS_SPEED10
) ?
923 fullDuplex
= (phyReg
& MII_DP83843_PHYSTS_DUPLEX
) ?
932 if ( fullDuplex
!= isFullDuplex
)
934 _setDuplexMode(fullDuplex
);
937 linkStatus
= kIONetworkLinkActive
| kIONetworkLinkValid
;
941 linkStatus
= kIONetworkLinkValid
;
946 reportLinkStatus
= true;
947 phyStatusPrev
= phyStatus
;
951 if ( reportLinkStatus
)
953 IONetworkMedium
* medium
;
954 IOMediumType mediumType
;
959 mediumType
= kIOMediumEthernet10BaseT
;
960 mediumType
|= (fullDuplex
== true) ?
961 kIOMediumOptionFullDuplex
:
962 kIOMediumOptionHalfDuplex
;
965 mediumType
= kIOMediumEthernet100BaseTX
;
966 mediumType
|= (fullDuplex
== true) ?
967 kIOMediumOptionFullDuplex
:
968 kIOMediumOptionHalfDuplex
;
971 mediumType
= kIOMediumEthernetNone
;
975 medium
= IONetworkMedium::getMediumWithType(mediumDict
, mediumType
);
977 setLinkStatus( linkStatus
, medium
, linkSpeed
* 1000000 );
979 if ( linkStatus
& kIONetworkLinkActive
)
980 IOLog( "Ethernet(BMac): Link up at %ld Mbps - %s Duplex\n",
981 linkSpeed
, (fullDuplex
) ? "Full" : "Half" );
983 IOLog( "Ethernet(BMac): Link down\n" );
987 /*-------------------------------------------------------------------------
991 *-------------------------------------------------------------------------*/
993 const OSString
* BMacEnet::newVendorString() const
995 return OSString::withCString("Apple");
998 const OSString
* BMacEnet::newModelString() const
1000 return OSString::withCString("BMac");
1003 const OSString
* BMacEnet::newRevisionString() const
1005 return OSString::withCString("");
1008 /*-------------------------------------------------------------------------
1012 *-------------------------------------------------------------------------*/
1014 IOReturn
BMacEnet::setPromiscuousMode(IOEnetPromiscuousMode mode
)
1018 reserveDebuggerLock();
1021 * Turn off the receiver and wait for the chipset to acknowledge
1023 rxCFGVal
= ReadBigMacRegister(ioBaseEnet
, kRXCFG
);
1024 WriteBigMacRegister(ioBaseEnet
, kRXCFG
, rxCFGVal
& ~kRxMACEnable
);
1025 while( ReadBigMacRegister(ioBaseEnet
, kRXCFG
) & kRxMACEnable
)
1029 * Set or reset promiscuous mode and restore receiver state
1031 if (mode
== kIOEnetPromiscuousModeOff
) {
1032 rxCFGVal
&= ~kRxPromiscEnable
;
1033 isPromiscuous
= false;
1036 rxCFGVal
|= kRxPromiscEnable
;
1037 isPromiscuous
= true;
1040 WriteBigMacRegister( ioBaseEnet
, kRXCFG
, rxCFGVal
);
1042 releaseDebuggerLock();
1044 return kIOReturnSuccess
;
1047 IOReturn
BMacEnet::setMulticastMode(IOEnetMulticastMode mode
)
1049 multicastEnabled
= (mode
== kIOEnetMulticastModeOff
) ? false : true;
1051 return kIOReturnSuccess
;
1054 IOReturn
BMacEnet::setMulticastList(IOEthernetAddress
*addrs
, UInt32 count
)
1056 reserveDebuggerLock();
1057 _resetHashTableMask();
1058 for (UInt32 i
= 0; i
< count
; i
++) {
1059 _addToHashTableMask(addrs
->bytes
);
1062 _updateBMacHashTableMask();
1063 releaseDebuggerLock();
1064 return kIOReturnSuccess
;
1067 /*-------------------------------------------------------------------------
1071 *-------------------------------------------------------------------------*/
1073 static struct MediumTable
1080 { kIOMediumEthernetNone
, 0 },
1081 { kIOMediumEthernetAuto
, 0 },
1082 { kIOMediumEthernet10BaseT
| kIOMediumOptionHalfDuplex
, 10 },
1083 { kIOMediumEthernet10BaseT
| kIOMediumOptionFullDuplex
, 10 },
1084 { kIOMediumEthernet100BaseTX
| kIOMediumOptionHalfDuplex
, 100 },
1085 { kIOMediumEthernet100BaseTX
| kIOMediumOptionFullDuplex
, 100 },
1089 bool BMacEnet::createMediumTables()
1091 IONetworkMedium
*medium
;
1094 mediumDict
= OSDictionary::withCapacity( sizeof(mediumTable
)/sizeof(mediumTable
[0]) );
1095 if ( mediumDict
== 0 ) return false;
1097 for ( i
=0; i
< sizeof(mediumTable
)/sizeof(mediumTable
[0]); i
++ )
1099 medium
= IONetworkMedium::medium( mediumTable
[i
].type
, mediumTable
[i
].speed
);
1102 IONetworkMedium::addMedium( mediumDict
, medium
);
1107 if ( publishMediumDictionary( mediumDict
) != true )
1112 medium
= IONetworkMedium::getMediumWithType( mediumDict
,
1113 kIOMediumEthernetAuto
);
1115 setCurrentMedium( medium
);
1120 /*-------------------------------------------------------------------------
1124 *-------------------------------------------------------------------------*/
1127 * Kernel Debugger Support
1129 void BMacEnet::sendPacket( void * pkt
, UInt32 pkt_len
)
1131 _sendPacket(pkt
, pkt_len
);
1134 void BMacEnet::receivePacket( void * pkt
,
1138 _receivePacket(pkt
, (UInt
*) pkt_len
, timeout
);
1142 * Create a WorkLoop serialized output queue object.
1144 IOOutputQueue
* BMacEnet::createOutputQueue()
1146 return IOGatedOutputQueue::withTarget( this,
1148 TRANSMIT_QUEUE_SIZE
);
1152 * Power management methods.
1155 IOReturn
BMacEnet::registerWithPolicyMaker(IOService
* policyMaker
)
1157 #define number_of_power_states 2
1159 static IOPMPowerState ourPowerStates
[number_of_power_states
] = {
1160 {1,0,0,0,0,0,0,0,0,0,0,0},
1161 {1,IOPMDeviceUsable
,IOPMPowerOn
,IOPMPowerOn
,0,0,0,0,0,0,0,0}
1164 currentPowerState
= 1;
1166 return policyMaker
->registerPowerDriver( this,
1168 number_of_power_states
);
1171 IOReturn
BMacEnet::setPowerState( unsigned long powerStateOrdinal
,
1172 IOService
* whatDevice
)
1174 IOReturn ret
= IOPMAckImplied
;
1176 // kprintf("Ethernet(BMac): setPowerState %d\n", powerStateOrdinal);
1178 if ( currentPowerState
== powerStateOrdinal
)
1179 return IOPMAckImplied
;
1181 switch ( powerStateOrdinal
)
1184 kprintf("Ethernet(BMac): powering off\n");
1185 currentPowerState
= powerStateOrdinal
;
1189 kprintf("Ethernet(BMac): powering on\n");
1190 currentPowerState
= powerStateOrdinal
;
1194 ret
= IOPMNoSuchState
;