|
|
1.1 root 1: /*
2: * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
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.
11: *
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
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /*
23: * Copyright (c) 1998-1999 by Apple Computer, Inc., All rights reserved.
24: *
25: * Hardware independent (relatively) code for the BMac Ethernet Controller
26: *
27: * HISTORY
28: *
29: * dd-mmm-yy
30: * Created.
31: *
32: * Dec 10, 1998 jliu
33: * Converted to IOKit/C++.
34: */
35:
36: #include "BMacEnet.h"
37: #include "BMacEnetPrivate.h"
38:
39: #include <IOKit/IORegistryEntry.h>
40: #include <IOKit/IODeviceTreeSupport.h>
41: #include <IOKit/platform/AppleMacIODevice.h>
42: #include <IOKit/assert.h>
43:
44: // #define DEBUG_JOE 1
45:
46: //------------------------------------------------------------------------
47:
48: #define super IOEthernetController
49:
50: OSDefineMetaClassAndStructors( BMacEnet, IOEthernetController )
51:
52: //------------------------------------------------------------------------
53:
54: #define PROVIDER_DEV 0
55: #define PROVIDER_DMA_TX 1
56: #define PROVIDER_DMA_RX 2
57:
58: /*
59: * Public Instance Methods
60: */
61:
62: /*-------------------------------------------------------------------------
63: *
64: *
65: *
66: *-------------------------------------------------------------------------*/
67:
68: bool BMacEnet::init(OSDictionary * properties = 0)
69: {
70: /*
71: * Initialize my ivars.
72: */
73: networkInterface = 0;
74: transmitQueue = 0;
75: debugQueue = 0;
76: debugger = 0;
77: rxIntSrc = 0;
78: txDebuggerPkt = 0;
79: phyId = 0xff;
80: phyMIIDelay = MII_DEFAULT_DELAY;
81: sromAddressBits = 6;
82: enetAddressOffset = 20;
83: phyStatusPrev = 0;
84: ready = false;
85: debugClient = false;
86: debugTxPoll = false;
87: netifClient = false;
88: isPromiscuous = false;
89: multicastEnabled = false;
90:
91: if (!super::init(properties))
92: return false;
93:
94: /*
95: * Clear the mbuf rings.
96: */
97: for (int i = 0; i < TX_RING_LENGTH; i++)
98: txMbuf[i] = 0;
99: for (int i = 0; i < RX_RING_LENGTH; i++)
100: rxMbuf[i] = 0;
101:
102: /*
103: * Clear the memory map objects.
104: */
105: for (int i = 0; i < MEMORY_MAP_COUNT; i++)
106: maps[i] = 0;
107:
108: return true;
109: }
110:
111: bool BMacEnet::start(IOService * provider)
112: {
113: AppleMacIODevice *nub = OSDynamicCast(AppleMacIODevice, provider);
114: IOInterruptEventSource *intES;
115:
116: if (!nub || !super::start(provider))
117: return false;
118:
119: transmitQueue = OSDynamicCast(IOOQGateFIFOQueue, getOutputQueue());
120: if (!transmitQueue) {
121: IOLog("BMac: output queue initialization failed\n");
122: return false;
123: }
124: transmitQueue->retain();
125:
126: // Allocate debug queue. This stores packets retired from the TX ring
127: // by the polling routine. We cannot call freePacket() or m_free() within
128: // the debugger context.
129: //
130: // The capacity of the queue is set at maximum to prevent the queue from
131: // calling m_free() due to over-capacity. But we don't expect the size
132: // of the queue to grow too large.
133: //
134: debugQueue = IOPacketQueue::withCapacity((UInt) -1);
135: if (!debugQueue)
136: return false;
137:
138: // Allocate a IOMBufDBDMAMemoryCursor instance. Currently, the maximum
139: // number of segments is set to 2. The maximum length for each segment
140: // is set to the maximum ethernet frame size (plus padding).
141:
142: mbufCursor = IOMBufBigMemoryCursor::withSpecification(NETWORK_BUFSIZE, 2);
143: if (!mbufCursor) {
144: IOLog("Ethernet(BMac): IOMBufDBDMAMemoryCursor allocation failure\n");
145: return false;
146: }
147:
148: //
149: // Our provider is the nub representing the BMacEnet hardware
150: // controller. We will query it for our resource information.
151: //
152:
153: for (int i = 0; i < MEMORY_MAP_HEATHROW_INDEX; i++) {
154: IOMemoryMap * map;
155:
156: map = provider->mapDeviceMemoryWithIndex(i);
157: if (!map)
158: return false;
159: #ifdef DEBUG_JOE
160: IOLog("map %d: Phys:%08x Virt:%08x len:%d\n",
161: i,
162: (unsigned) map->getPhysicalAddress(),
163: (unsigned) map->getVirtualAddress(),
164: (unsigned) map->getLength());
165: #endif DEBUG_JOE
166:
167: switch (i) {
168: case MEMORY_MAP_ENET_INDEX:
169: ioBaseEnet = (IOPPCAddress) map->getVirtualAddress();
170: break;
171:
172: case MEMORY_MAP_TXDMA_INDEX:
173: ioBaseEnetTxDMA = (IODBDMAChannelRegisters *)
174: map->getVirtualAddress();
175: break;
176:
177: case MEMORY_MAP_RXDMA_INDEX:
178: ioBaseEnetRxDMA = (IODBDMAChannelRegisters *)
179: map->getVirtualAddress();
180: break;
181: }
182:
183: maps[i] = map;
184: }
185:
186: #ifdef DEBUG_JOE
187: IOLog("ioBaseEnet: 0x%08x\n", ioBaseEnet);
188: IOLog("ioBaseEnetTxDMA: 0x%08x\n", ioBaseEnetTxDMA);
189: IOLog("ioBaseEnetRxDMA: 0x%08x\n", ioBaseEnetRxDMA);
190: #endif DEBUG_JOE
191:
192: //
193: // We need to get the I/O address for the Heathrow controller.
194: // We ask the provider (bmac) for its device tree parent.
195: //
196: IOService *heathrow;
197: if (!(heathrow = OSDynamicCast(IOService,
198: provider->getParentEntry( gIODTPlane ))))
199: return false;
200:
201: // Check whether the hardware is susceptible to the broken unicast
202: // filter problem.
203: //
204: OSData * devIDData;
205: devIDData = OSDynamicCast(OSData, heathrow->getProperty("device-id"));
206:
207: if (devIDData) {
208: useUnicastFilter = ( *((UInt32 *) devIDData->getBytesNoCopy()) ==
209: 0x10 );
210: if (useUnicastFilter)
211: IOLog("%s: Enabling workaround for broken unicast filter\n",
212: getName());
213: }
214:
215: IOMemoryMap * map = heathrow->mapDeviceMemoryWithIndex(0);
216: if (map)
217: {
218: #ifdef DEBUG_JOE
219: IOLog("Heathrow: Phys:%08x Virt:%08x len:%d\n",
220: (unsigned) map->getPhysicalAddress(),
221: (unsigned) map->getVirtualAddress(),
222: (unsigned) map->getLength());
223: #endif DEBUG_JOE
224: ioBaseHeathrow = (IOPPCAddress) map->getVirtualAddress();
225:
226: maps[MEMORY_MAP_HEATHROW_INDEX] = map;
227: }
228: else {
229: return false;
230: }
231:
232: //
233: // Get a reference to the IOWorkLoop in our superclass.
234: //
235: IOWorkLoop * myWorkLoop = getWorkLoop();
236: assert(myWorkLoop);
237:
238: //
239: // Allocate three IOInterruptEventSources.
240: //
241: rxIntSrc = IOInterruptEventSource::interruptEventSource
242: (this,
243: (IOInterruptEventAction) &BMacEnet::interruptOccurredForSource,
244: provider, PROVIDER_DMA_RX);
245: if (!rxIntSrc
246: || (myWorkLoop->addEventSource(rxIntSrc) != kIOReturnSuccess)) {
247: IOLog("Ethernet(BMac): rxIntSrc init failure\n");
248: return false;
249: }
250:
251: intES = IOInterruptEventSource::interruptEventSource
252: (this,
253: (IOInterruptEventAction) &BMacEnet::interruptOccurredForSource,
254: provider, PROVIDER_DMA_TX);
255: if (intES) {
256: bool res = (myWorkLoop->addEventSource(intES) != kIOReturnSuccess);
257: intES->release();
258: if (res) {
259: IOLog("Ethernet(BMac): PROVIDER_DMA_TX add failure\n");
260: return false;
261: }
262: }
263: else {
264: IOLog("Mace: PROVIDER_DMA_TX init failure\n");
265: return false;
266: }
267:
268: intES = IOInterruptEventSource::interruptEventSource
269: (this,
270: (IOInterruptEventAction) &BMacEnet::interruptOccurredForSource,
271: provider, PROVIDER_DEV);
272: if (intES) {
273: bool res = (myWorkLoop->addEventSource(intES) != kIOReturnSuccess);
274: intES->release();
275: if (res) {
276: IOLog("Ethernet(BMac): PROVIDER_DEV add failure\n");
277: return false;
278: }
279: }
280: else {
281: IOLog("Ethernet(BMac): PROVIDER_DEV init failure\n");
282: return false;
283: }
284:
285: timerSrc = IOTimerEventSource::timerEventSource
286: (this, (IOTimerEventSource::Action) &BMacEnet::timeoutOccurred);
287: if (!timerSrc
288: || (myWorkLoop->addEventSource(timerSrc) != kIOReturnSuccess)) {
289: IOLog("Ethernet(BMac): timerSrc init failure\n");
290: return false;
291: }
292:
293: MGETHDR(txDebuggerPkt, M_DONTWAIT, MT_DATA);
294: if (!txDebuggerPkt) {
295: IOLog("Ethernet(BMac): Couldn't allocate KDB buffer\n");
296: return false;
297: }
298:
299: #if 0
300: // Enable the interrupt event sources. The hardware interrupts
301: // sources remain disabled until _resetAndEnable(true) is called.
302: //
303: // myWorkLoop->enableAllInterrupts();
304: #endif
305:
306: //
307: // Perform a hardware reset.
308: //
309: if ( !_resetAndEnable(false) )
310: {
311: return false;
312: }
313:
314: //
315: // Cache my MAC address.
316: //
317: getHardwareAddress(&myAddress);
318:
319: //
320: // Allocate memory for ring buffers.
321: //
322: if (_allocateMemory() == false)
323: {
324: return false;
325: }
326:
327: //
328: // Attach a kernel debugger client.
329: //
330: attachDebuggerClient(&debugger);
331:
332: //
333: // Attach an IOEthernetInterface client.
334: //
335: if (!attachNetworkInterface((IONetworkInterface **) &networkInterface))
336: return false;
337:
338: return true;
339: }
340:
341: /*-------------------------------------------------------------------------
342: *
343: *
344: *
345: *-------------------------------------------------------------------------*/
346:
347: void BMacEnet::free()
348: {
349: UInt i;
350:
351: _resetAndEnable(false);
352:
353: if (debugger)
354: debugger->release();
355:
356: if (getWorkLoop())
357: getWorkLoop()->disableAllEventSources();
358:
359: if (timerSrc)
360: timerSrc->release();
361:
362: if (rxIntSrc)
363: rxIntSrc->release();
364:
365: if (txDebuggerPkt)
366: freePacket(txDebuggerPkt);
367:
368: if (transmitQueue)
369: transmitQueue->release();
370:
371: if (debugQueue)
372: debugQueue->release();
373:
374: if (networkInterface)
375: networkInterface->release();
376:
377: if (mbufCursor)
378: mbufCursor->release();
379:
380: for (i = 0; i < rxMaxCommand; i++)
381: if (rxMbuf[i]) freePacket(rxMbuf[i]);
382:
383: for (i = 0; i < txMaxCommand; i++)
384: if (txMbuf[i]) freePacket(txMbuf[i]);
385:
386: for (i = 0; i < MEMORY_MAP_COUNT; i++)
387: if (maps[i]) maps[i]->release();
388:
389: if (dmaMemory.ptr)
390: {
391: IOFree(dmaMemory.ptrReal, dmaMemory.sizeReal);
392: dmaMemory.ptr = 0;
393: }
394:
395: super::free();
396: }
397:
398: /*-------------------------------------------------------------------------
399: *
400: *
401: *
402: *-------------------------------------------------------------------------*/
403:
404: void BMacEnet::interruptOccurredForSource(IOInterruptEventSource *src,
405: int /*count*/)
406: {
407: bool doFlushQueue = false;
408: bool doService = false;
409:
410: reserveDebuggerLock();
411:
412: statReg = ReadBigMacRegister( ioBaseEnet, kSTAT );
413:
414: if (src == rxIntSrc) {
415: KERNEL_DEBUG(DBG_BMAC_RXIRQ | DBG_FUNC_START, 0, 0, 0, 0, 0 );
416: doFlushQueue = _receiveInterruptOccurred();
417: KERNEL_DEBUG(DBG_BMAC_RXIRQ | DBG_FUNC_END, 0, 0, 0, 0, 0 );
418: }
419: else {
420: /*
421: * On the transmit side, we use the chipset interrupt. Using the
422: * transmit DMA interrupt (or having multiple transmit DMA entries)
423: * would allows us to send the next frame to the chipset prior the
424: * transmit fifo going empty.
425: * However, this aggrevates a BMac chipset bug where the next frame going
426: * out gets corrupted (first two bytes lost) if the chipset had to retry
427: * the previous frame.
428: */
429: txWDInterrupts++;
430: KERNEL_DEBUG(DBG_BMAC_TXIRQ | DBG_FUNC_START, 0, 0, 0, 0, 0 );
431: doService = _transmitInterruptOccurred();
432: KERNEL_DEBUG(DBG_BMAC_TXIRQ | DBG_FUNC_END, 0, 0, 0, 0, 0 );
433: }
434:
435: releaseDebuggerLock();
436:
437: /*
438: * Submit all received packets queued up by _receiveInterruptOccurred()
439: * to the network stack. The up call is performed without holding the
440: * debugger lock.
441: */
442: if (doFlushQueue)
443: networkInterface->flushInputQueue();
444:
445: /*
446: * Unstall the output queue if some space was made available.
447: */
448: if (doService && netifClient)
449: transmitQueue->service();
450: }
451:
452: /*-------------------------------------------------------------------------
453: *
454: *
455: *
456: *-------------------------------------------------------------------------*/
457:
458: UInt32 BMacEnet::outputPacket(struct mbuf * pkt)
459: {
460: u_int32_t i;
461: UInt32 ret = kIOOQReturnSuccess;
462:
463: KERNEL_DEBUG(DBG_BMAC_TXQUEUE | DBG_FUNC_NONE, (int) pkt,
464: (int) pkt->m_pkthdr.len, 0, 0, 0 );
465:
466: /*
467: * Hold the debugger lock so the debugger can't interrupt us
468: */
469: reserveDebuggerLock();
470:
471: do
472: {
473: /*
474: * Preliminary sanity checks
475: */
476: assert(pkt && netifClient);
477:
478: #if 0
479: /*
480: * Remove any completed packets from the Tx ring
481: */
482: if ( chipId >= kCHIPID_PaddingtonXmitStreaming )
483: {
484: _transmitInterruptOccurred();
485: }
486: #endif
487:
488: i = txCommandTail + 1;
489: if ( i >= txMaxCommand ) i = 0;
490: if ( i == txCommandHead )
491: {
492: /*
493: * Ring buffer is full. Disable the dequeueing process.
494: * We reenable it when an entry is made available by the
495: * transmit interrupt handler, or if a timeout occurs.
496: */
497: ret = kIOOQReturnStall;
498: continue;
499: }
500:
501: /*
502: * If there is space on the Tx ring, add the packet directly to the
503: * ring.
504: */
505: _transmitPacket(pkt);
506: }
507: while ( 0 );
508:
509: releaseDebuggerLock();
510:
511: return ret;
512: }
513:
514: /*-------------------------------------------------------------------------
515: *
516: *
517: *
518: *-------------------------------------------------------------------------*/
519:
520: bool BMacEnet::_resetAndEnable(bool enable)
521: {
522: bool ret = true;
523:
524: // reserveDebuggerLock();
525:
526: ready = false;
527:
528: if (timerSrc) timerSrc->cancelTimeout();
529:
530: _disableAdapterInterrupts();
531: if (getWorkLoop()) getWorkLoop()->disableAllInterrupts();
532:
533: _resetChip();
534:
535: while (enable)
536: {
537: if (!_initRxRing() || !_initTxRing())
538: {
539: ret = false;
540: break;
541: }
542:
543: if ( phyId != 0xff )
544: {
545: miiInitializePHY(phyId);
546: }
547:
548: if (_initChip() == false)
549: {
550: ret = false;
551: break;
552: }
553:
554: _startChip();
555:
556: timerSrc->setTimeoutMS(WATCHDOG_TIMER_MS);
557:
558: if (getWorkLoop()) getWorkLoop()->enableAllInterrupts();
559: _enableAdapterInterrupts();
560:
561: ready = true;
562:
563: _sendDummyPacket();
564:
565: break;
566: }
567:
568: // releaseDebuggerLock();
569:
570: return ret;
571: }
572:
573: /*-------------------------------------------------------------------------
574: * Called by IOEthernetInterface client to enable the controller.
575: * This method is always called while running on the default workloop
576: * thread.
577: *-------------------------------------------------------------------------*/
578:
579: IOReturn BMacEnet::enable(IONetworkInterface * netif)
580: {
581: IONetworkParameter * param;
582:
583: // If an interface client has previously enabled us,
584: // and we know there can only be one interface client
585: // for this driver, then simply return true.
586: //
587: if (netifClient) {
588: IOLog("EtherNet(BMac): already enabled\n");
589: return kIOReturnSuccess;
590: }
591:
592: // Grab a pointer to the statistics structure in the interface.
593: //
594: param = netif->getParameter(kIONetworkStatsKey);
595: if (!param || !(netStats = (IONetworkStats *) param->getBuffer()))
596: {
597: IOLog("EtherNet(BMac): invalid network statistics\n");
598: return kIOReturnError;
599: }
600:
601: if ((ready == false) && !_resetAndEnable(true))
602: return kIOReturnIOError;
603:
604: // Record the interface as an active client.
605: //
606: netifClient = true;
607:
608: // Start our IOOutputQueue object.
609: //
610: transmitQueue->setCapacity(TRANSMIT_QUEUE_SIZE);
611: transmitQueue->start();
612:
613: return kIOReturnSuccess;
614: }
615:
616: /*-------------------------------------------------------------------------
617: * Called by IOEthernetInterface client to disable the controller.
618: * This method is always called while running on the default workloop
619: * thread.
620: *-------------------------------------------------------------------------*/
621:
622: IOReturn BMacEnet::disable(IONetworkInterface * /*netif*/)
623: {
624: // If we have no active clients, then disable the controller.
625: //
626: if (debugClient == false)
627: _resetAndEnable(false);
628:
629: // Disable our IOOutputQueue object. This will prevent the
630: // outputPacket() method from being called.
631: //
632: transmitQueue->stop();
633:
634: // Flush all packets currently in the output queue.
635: //
636: transmitQueue->setCapacity(0);
637: transmitQueue->flush();
638:
639: netifClient = false;
640:
641: return kIOReturnSuccess;
642: }
643:
644: /*-------------------------------------------------------------------------
645: * This method is called by our debugger client to bring up the controller
646: * just before the controller is registered as the debugger device. The
647: * debugger client is attached in response to the attachDebuggerClient()
648: * call.
649: *
650: * This method is always called while running on the default workloop
651: * thread.
652: *-------------------------------------------------------------------------*/
653:
654: IOReturn BMacEnet::handleDebuggerOpen(IOKernelDebugger * /*debugger*/)
655: {
656: // Enable hardware and make it ready to support the debugger client.
657: //
658: if ((ready == false) && !_resetAndEnable(true))
659: return kIOReturnIOError;
660:
661: // Record the debugger as an active client of ours.
662: //
663: debugClient = true;
664:
665: // Returning true will allow the kdp registration to continue.
666: // If we return false, then we will not be registered as the
667: // debugger device, and the attachDebuggerClient() call will
668: // return NULL.
669: //
670: return kIOReturnSuccess;
671: }
672:
673: /*-------------------------------------------------------------------------
674: * This method is called by our debugger client to stop the controller.
675: * The debugger will call this method when we issue a detachDebuggerClient().
676: *
677: * This method is always called while running on the default workloop
678: * thread.
679: *-------------------------------------------------------------------------*/
680:
681: IOReturn BMacEnet::handleDebuggerClose(IOKernelDebugger * /*debugger*/)
682: {
683: debugClient = false;
684:
685: // If we have no active clients, then disable the controller.
686: //
687: if (netifClient == false)
688: _resetAndEnable(false);
689:
690: return kIOReturnSuccess;
691: }
692:
693: /*-------------------------------------------------------------------------
694: *
695: *
696: *
697: *-------------------------------------------------------------------------*/
698:
699: void BMacEnet::timeoutOccurred(IOTimerEventSource * /*timer*/)
700: {
701: u_int32_t dmaStatus;
702: u_int16_t phyStatus;
703: u_int16_t linkStatus;
704: u_int16_t phyStatusChange;
705: bool fullDuplex = false;
706: bool doFlushQueue = false;
707: bool doService = false;
708:
709: // IOLog("Ethernet(BMac): watchdog timer\n");
710:
711: reserveDebuggerLock();
712:
713: /*
714: * Check for DMA shutdown on receive channel
715: */
716: dmaStatus = IOGetDBDMAChannelStatus( ioBaseEnetRxDMA );
717: if ( !(dmaStatus & kdbdmaActive) )
718: {
719: #if 0
720: IOLog( "Ethernet(BMac): Timeout check - RxHead = %d RxTail = %d\n",
721: rxCommandHead, rxCommandTail);
722:
723: IOLog( "Ethernet(BMac): Rx Commands = %08x(p) Rx DMA Ptr = %08x(p)\n\r", rxDMACommandsPhys, IOGetDBDMACommandPtr(ioBaseEnetRxDMA) );
724: [self _dumpDesc:(void *)rxDMACommands Size:rxMaxCommand * sizeof(enet_dma_cmd_t)];
725: #endif
726:
727: doFlushQueue = _receiveInterruptOccurred();
728: }
729:
730: /*
731: * If there are pending entries on the Tx ring
732: */
733: if ( txCommandHead != txCommandTail )
734: {
735: /*
736: * If we did not service the Tx ring during the last timeout interval,
737: * then force servicing of the Tx ring
738: */
739: if ( txWDInterrupts == 0 )
740: {
741: if ( txWDCount++ > 0 )
742: {
743: if (_transmitInterruptOccurred() == false)
744: {
745: #if 0
746: IOLog( "Ethernet(BMac): Timeout check - TxHead = %d TxTail = %d\n",
747: txCommandHead, txCommandTail);
748: #endif
749: _restartTransmitter();
750: }
751: doService = true;
752: }
753: }
754: else
755: {
756: txWDInterrupts = 0;
757: txWDCount = 0;
758: }
759: }
760: else
761: {
762: txWDInterrupts = 0;
763: txWDCount = 0;
764: }
765:
766: if ( phyId != 0xff )
767: {
768: if ( miiReadWord(&phyStatus, MII_STATUS, phyId) == true )
769: {
770: phyStatusChange = (phyStatusPrev ^ phyStatus) &
771: (MII_STATUS_LINK_STATUS | MII_STATUS_NEGOTIATION_COMPLETE);
772: if ( phyStatusChange )
773: {
774: if ( (phyStatus & MII_STATUS_LINK_STATUS) &&
775: (phyStatus & MII_STATUS_NEGOTIATION_COMPLETE ) )
776: {
777: if ( (phyType & MII_ST10040_MASK) == MII_ST10040_ID )
778: {
779: miiReadWord(&linkStatus, MII_ST10040_CHIPST, phyId);
780:
781: fullDuplex = (linkStatus & MII_ST10040_CHIPST_DUPLEX) ? true : false;
782:
783: IOLog( "Ethernet(BMac): Link is up at %sMb - %s Duplex\n\r",
784: (linkStatus & MII_ST10040_CHIPST_SPEED) ? "100" : "10",
785: (fullDuplex) ? "Full" : "Half" );
786: }
787: else if ( (phyType & MII_DP83843_MASK) == MII_DP83843_ID )
788: {
789: miiReadWord(&linkStatus, MII_DP83843_PHYSTS, phyId);
790:
791: fullDuplex = (linkStatus & MII_DP83843_PHYSTS_DUPLEX) ? true : false;
792:
793: IOLog( "Ethernet(BMac): Link is up at %sMb - %s Duplex\n\r",
794: (linkStatus & MII_DP83843_PHYSTS_SPEED10) ? "10" : "100",
795: (fullDuplex) ? "Full" : "Half" );
796: }
797: else
798: {
799: fullDuplex = false ;
800: IOLog( "Ethernet(BMac): Link is up\n\r" );
801: }
802:
803: if ( fullDuplex != isFullDuplex )
804: {
805: _setDuplexMode(fullDuplex);
806: }
807: }
808: else
809: {
810: IOLog( "Ethernet(BMac): Link is down.\n\r" );
811: }
812: phyStatusPrev = phyStatus;
813: }
814: }
815: }
816:
817: // Clean-up after the debugger if the debugger was active.
818: //
819: if (debugTxPoll)
820: {
821: debugQueue->flush();
822: debugTxPoll = false;
823: releaseDebuggerLock();
824: doService = true;
825: }
826: else
827: {
828: releaseDebuggerLock();
829: }
830:
831: /*
832: * Submit all received packets queued up by _receiveInterruptOccurred()
833: * to the network stack. The up call is performed without holding the
834: * debugger lock.
835: */
836: if (doFlushQueue)
837: {
838: networkInterface->flushInputQueue();
839: }
840:
841: /*
842: * Make sure the output queue is not stalled.
843: */
844: if (doService && netifClient)
845: {
846: transmitQueue->service();
847: }
848:
849: /*
850: * Restart the watchdog timer
851: */
852: timerSrc->setTimeoutMS(WATCHDOG_TIMER_MS);
853: }
854:
855: /*-------------------------------------------------------------------------
856: *
857: *
858: *
859: *-------------------------------------------------------------------------*/
860:
861: const char * BMacEnet::getVendorString() const
862: {
863: return ("Apple");
864: }
865:
866: const char * BMacEnet::getModelString() const
867: {
868: return ("BMac");
869: }
870:
871: const char * BMacEnet::getRevisionString() const
872: {
873: return ("");
874: }
875:
876: /*-------------------------------------------------------------------------
877: *
878: *
879: *
880: *-------------------------------------------------------------------------*/
881:
882: IOReturn BMacEnet::setPromiscuousMode(IOEnetPromiscuousMode mode)
883: {
884: u_int16_t rxCFGVal;
885:
886: reserveDebuggerLock();
887:
888: /*
889: * Turn off the receiver and wait for the chipset to acknowledge
890: */
891: rxCFGVal = ReadBigMacRegister(ioBaseEnet, kRXCFG);
892: WriteBigMacRegister(ioBaseEnet, kRXCFG, rxCFGVal & ~kRxMACEnable );
893: while( ReadBigMacRegister(ioBaseEnet, kRXCFG) & kRxMACEnable )
894: ;
895:
896: /*
897: * Set or reset promiscuous mode and restore receiver state
898: */
899: if (mode == kIOEnetPromiscuousModeOff) {
900: rxCFGVal &= ~kRxPromiscEnable;
901: isPromiscuous = false;
902: }
903: else {
904: rxCFGVal |= kRxPromiscEnable;
905: isPromiscuous = true;
906: }
907:
908: WriteBigMacRegister( ioBaseEnet, kRXCFG, rxCFGVal );
909:
910: releaseDebuggerLock();
911:
912: return kIOReturnSuccess;
913: }
914:
915: IOReturn BMacEnet::setMulticastMode(IOEnetMulticastMode mode)
916: {
917: multicastEnabled = (mode == kIOEnetMulticastModeOff) ? false : true;
918:
919: return kIOReturnSuccess;
920: }
921:
922: IOReturn BMacEnet::setMulticastList(enet_addr_t *addrs, UInt count)
923: {
924: reserveDebuggerLock();
925: _resetHashTableMask();
926: for (UInt i = 0; i < count; i++) {
927: _addToHashTableMask(addrs->ea_byte);
928: addrs++;
929: }
930: _updateBMacHashTableMask();
931: releaseDebuggerLock();
932: return kIOReturnSuccess;
933: }
934:
935: /*
936: * Kernel Debugger Support
937: */
938: void BMacEnet::sendPacket(void *pkt, unsigned int pkt_len)
939: {
940: _sendPacket(pkt, pkt_len);
941: }
942:
943: void BMacEnet::receivePacket(void *pkt, unsigned int *pkt_len,
944: unsigned int timeout)
945: {
946: _receivePacket(pkt, pkt_len, timeout);
947: }
948:
949: /*
950: * Allocate a WorkLoop serialized output queue object.
951: */
952: IOOutputQueue * BMacEnet::allocateOutputQueue()
953: {
954: return IOOQGateFIFOQueue::withTarget( this,
955: getWorkLoop(),
956: TRANSMIT_QUEUE_SIZE );
957: }
958:
959: #ifdef PM_SUPPORT
960: /*
961: * Power management methods.
962: */
963: - (IOReturn)getPowerState:(PMPowerState *)state_p
964: {
965: return kIOReturnUnsupported;
966: }
967:
968: - (IOReturn)setPowerState:(PMPowerState)state
969: {
970: if (state == PM_OFF) {
971: resetAndEnabled = NO;
972: [self _resetChip];
973: return kIOReturnSuccess;
974: }
975: return kIOReturnUnsupported;
976: }
977:
978: - (IOReturn)getPowerManagement:(PMPowerManagementState *)state_p
979: {
980: return kIOReturnUnsupported;
981: }
982:
983: - (IOReturn)setPowerManagement:(PMPowerManagementState)state
984: {
985: return kIOReturnUnsupported;
986: }
987: #endif PM_SUPPORT
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.