|
|
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) 1999 Apple Computer, Inc. All rights reserved.
24: *
25: * IONetworkController.cpp
26: *
27: * HISTORY
28: * 9-Dec-1998 Joe Liu (jliu) created.
29: *
30: */
31:
32: #include <IOKit/assert.h>
33: #include <IOKit/IOCommandGate.h>
34: #include <IOKit/network/IONetworkController.h>
35: #include <IOKit/network/IOOutputQueue.h>
36: #include <IOKit/network/IONetworkMedium.h>
37:
38: // IONetworkController needs to know about mbufs, but it shall have no
39: // other dependencies on BSD networking.
40: //
41: extern "C" {
42: #include <sys/param.h> // mbuf limits defined here.
43: #include <sys/mbuf.h>
44: //
45: // osfmk/kern/spl.h - Need splimp for mbuf macros.
46: //
47: typedef unsigned spl_t;
48: extern spl_t (splimp)(void);
49: }
50:
51: //-------------------------------------------------------------------------
52: // Macros.
53:
54: #define super IOService
55:
56: OSDefineMetaClass( IONetworkController, IOService )
57: OSDefineAbstractStructors( IONetworkController, IOService )
58:
59: // Define SYNC_REQ macro to simplify syncRequest() calls.
60: //
61: #define SYNC_REQ(sender, action, ret, args...) \
62: syncRequest(sender, this, (IONetworkAction) action, (UInt32 *) ret, \
63: ## args)
64:
65: #define DO_SYNC_REQ(action, args...) \
66: { \
67: IOReturn ret = kIOReturnNotReady; \
68: syncRequest(client, this, \
69: (RequestAction) &IONetworkController:: ## action, \
70: (UInt32 *) &ret, ## args); \
71: return ret; \
72: }
73:
74: static bool isPowerOfTwo(UInt num)
75: {
76: return (num == (num & ~(num - 1)));
77: }
78:
79: #ifndef MAX
80: #define MAX(a, b) (((a)>(b))?(a):(b))
81: #endif
82:
83: #define MEDIUM_LOCK IOTakeLock(_mediumLock);
84: #define MEDIUM_UNLOCK IOUnlock(_mediumLock);
85:
86: #ifdef DEBUG
87: #define DLOG(fmt, args...) IOLog(fmt, ## args)
88: #else
89: #define DLOG
90: #endif
91:
92: // OSSymbols for frequently used keys.
93: //
94: static const OSSymbol * gIOActiveMediumKey;
95: static const OSSymbol * gIOCurrentMediumKey;
96:
97: //---------------------------------------------------------------------------
98: // Class initializer for IONetworkController. Create OSSymbol objects
99: // ahead of time that are used as keys. This method is called explicitly
100: // by a line in IOStartIOKit.cpp and not by the OSDefineMetaClassAndInit()
101: // mechanism, since the OSSymbol class is not guaranteed to be initialized
102: // first, thus its OSSymbol pool may not be setup.
103:
104: void IONetworkController::initialize()
105: {
106: gIOActiveMediumKey = OSSymbol::withCStringNoCopy(kIOActiveMedium);
107: gIOCurrentMediumKey = OSSymbol::withCStringNoCopy(kIOCurrentMedium);
108:
109: assert(gIOActiveMediumKey && gIOCurrentMediumKey);
110:
111: IONetworkData::initialize();
112: }
113:
114: //---------------------------------------------------------------------------
115: // Initialize the IONetworkController instance. Instance variables are
116: // initialized to their default values, and the init() method in superclass
117: // is called.
118: //
119: // properties: A property table.
120: //
121: // Returns true on success, false otherwise.
122:
123: bool IONetworkController::init(OSDictionary * properties)
124: {
125: // Initialize instance variables.
126: //
127: _workLoop = 0;
128: _cmdGate = 0;
129: _outputQueue = 0;
130: _clientSet = 0;
131: _reqClient = 0;
132: _requestEnabled = true;
133: _handleReady = true;
134: _mediumLock = 0;
135: _linkData = 0;
136:
137: if (!super::init(properties))
138: {
139: DLOG("IONetworkController: super::init() failed\n");
140: return false;
141: }
142: return true;
143: }
144:
145: //-------------------------------------------------------------------------
146: // Called when the controller was matched to a provider and
147: // has been selected to start running. IONetworkController will allocate
148: // resources and gather the controller's properties. No I/O will be
149: // triggered until the subclass attaches a client object from its own
150: // start method. Subclasses must override this method and call
151: // super::start() at the beginning of its implementation. They should
152: // also check the return value to make sure their superclass was
153: // started successfully. The resources allocated
154: // by IONetworkController are:
155: //
156: // - An IOWorkLoop object.
157: // - An IOCommandGate object to handle synchronous requests.
158: // - An OSSet to track our clients.
159: // - An optional IOOutputQueue object for output queueing.
160: //
161: // Tasks that are usually performed by a typical network driver in start
162: // include:
163: //
164: // - Resource allocation
165: // - Hardware initialization
166: // - Allocation of IOEventSources and attaching them to an IOWorkLoop object.
167: // - Publishing a medium dictionary.
168: // - And finally, attaching an interface object when the driver is ready
169: // to handle client requests.
170: //
171: // provider: The provider that the controller was matched
172: // (and attached) to.
173: //
174: // Returns true on success, false otherwise.
175:
176: bool IONetworkController::start(IOService * provider)
177: {
178: // Most drivers will probably want to wait for BSD due to their
179: // dependency on mbufs, which is not available until BSD is
180: // initialized.
181: //
182: if ((getFeatureSet() & kIONetworkFeatureNoBSDWait) == 0)
183: waitForService(resourceMatching( "IOBSD" ));
184:
185: // Start our superclass.
186: //
187: if (!super::start(provider))
188: return false;
189:
190: // Create an OSSet to store our clients.
191: //
192: _clientSet = OSSet::withCapacity(2);
193: if (!_clientSet)
194: return false;
195:
196: // Initialize link status properties.
197: //
198: setMediumProperty(gIOActiveMediumKey, 0, &_activeMedium, true);
199: setMediumProperty(gIOCurrentMediumKey, 0, &_currentMedium, true);
200: setLink32Property(kIOLinkStatus, 0, &_linkStatus, true);
201: setLink64Property(kIOLinkSpeed, 0, &_linkSpeed, true);
202:
203: // Allocate a mutex lock to serialize access to the medium dictionary.
204: //
205: _mediumLock = IOLockAlloc();
206: if (!_mediumLock)
207: return false;
208: IOLockInitWithState(_mediumLock, kIOLockStateUnlocked);
209:
210: // Allocate and initialize the default IOWorkLoop object.
211: //
212: _workLoop = IOWorkLoop::workLoop();
213: if (!_workLoop)
214: {
215: DLOG("%s: IOWorkLoop allocation failed\n", getName());
216: return false;
217: }
218:
219: // Create a 'private' IOCommandGate object and attach it to
220: // our workloop created above. This is used by the syncRequest()
221: // function.
222: //
223: _cmdGate = IOCommandGate::commandGate(this);
224: if (!_cmdGate ||
225: (_workLoop->addEventSource(_cmdGate) != kIOReturnSuccess))
226: {
227: DLOG("%s: IOCommandGate initialization failed\n", getName());
228: return false;
229: }
230:
231: // Try to allocate an IOOutputQueue instance. This is optional and
232: // _outputQueue may be 0.
233: //
234: _outputQueue = createOutputQueue();
235:
236: // Remove this when allocateOutputQueue is deleted.
237: if (!_outputQueue)
238: _outputQueue = allocateOutputQueue();
239:
240: // Query the controller's mbuf buffer restrictions.
241: //
242: IOPacketBufferConstraints constraints;
243: getPacketBufferConstraints(&constraints);
244: if ((constraints.alignStart > kIOPacketBufferAlign32) ||
245: (constraints.alignLength > kIOPacketBufferAlign32) ||
246: !isPowerOfTwo(constraints.alignStart) ||
247: !isPowerOfTwo(constraints.alignLength))
248: {
249: IOLog("%s: Invalid alignment: start:%ld, length:%ld\n",
250: getName(),
251: constraints.alignStart,
252: constraints.alignLength);
253: return false;
254: }
255:
256: // Make it easier to satisfy both constraints.
257: //
258: if (constraints.alignStart < constraints.alignLength)
259: constraints.alignStart = constraints.alignLength;
260:
261: // Convert to alignment masks.
262: //
263: _alignStart = (constraints.alignStart) ? constraints.alignStart - 1 : 0;
264: _alignLength = (constraints.alignLength) ? constraints.alignLength - 1 : 0;
265: _alignPadding = _alignStart + _alignLength;
266:
267: // Starts the power manager
268: //
269: PMinit(); // initialize superclass power management variables
270: provider->joinPMtree(this); // attach into the power management hierarchy
271:
272: return true;
273: }
274:
275: //---------------------------------------------------------------------------
276: // The opposite of start(). The controller has been instructed to stop running.
277: // This method should release resources and undo actions performed by start().
278: // Subclasses must override this method and call super::stop() at the end of
279: // its implementation.
280: //
281: // provider: The provider that the controller was matched
282: // (and attached) to.
283:
284: void IONetworkController::stop(IOService * provider)
285: {
286: // Free the memory allocated by PMInit:
287: PMstop();
288:
289: super::stop(provider);
290: }
291:
292: //---------------------------------------------------------------------------
293: // Get the IOWorkLoop object created by IONetworkController.
294: // An IOWorkLoop object is created by the start() method. Drivers can call
295: // getWorkLoop() to obtain a reference to the IOWorkLoop object, and attach
296: // their event sources, such as IOTimerEventSource or IOInterruptEventSource.
297: // See IOWorkLoop.
298: //
299: // Returns the IOWorkLoop object created by IONetworkController.
300:
301: IOWorkLoop * IONetworkController::getWorkLoop() const
302: {
303: return _workLoop;
304: }
305:
306: //---------------------------------------------------------------------------
307: // Get the IOCommandGate object created by IONetworkController.
308: // An IOCommandGate is created and attached to an IOWorkLoop by the start().
309: // method This IOCommandGate object is used to handle client requests issued
310: // through the syncRequest() method. Subclasses that need an IOCommandGate
311: // should try to use the object returned by this method, rather than creating
312: // a new instance.
313: // See IOCommandGate.
314: //
315: // Returns the IOCommandGate object created by IONetworkController.
316:
317: IOCommandGate * IONetworkController::getCommandGate() const
318: {
319: return _cmdGate;
320: }
321:
322: //---------------------------------------------------------------------------
323: // Get the address of the method designated to handle output packets.
324: //
325: // Returns the address of the outputPacket() method.
326:
327: IOOutputAction IONetworkController::getOutputHandler() const
328: {
329: return (IOOutputAction) &IONetworkController::outputPacket;
330: }
331:
332: //---------------------------------------------------------------------------
333: // Create a new interface client object and attach it
334: // to the controller. The createInterface() method is called to
335: // perform the allocation and initialization, followed by a call to
336: // configureInterface() to configure the interface. Both of these
337: // methods can be overridden by subclasses to customize the
338: // interface client attached. Drivers must call attachInterface()
339: // from its start() method, after it is ready to service client requests.
340: //
341: // interfaceP: If successful (return value is true), then the interface
342: // object will be written to the handle provided.
343: //
344: // doRegister: If true, then registerService() is called to register
345: // the interface, which will trigger the matching process,
346: // and cause the interface to become registered with the network
347: // layer. For drivers that wish to delay the registration, and
348: // hold off servicing requests and data packets from the network
349: // layer, set doRegister to false and call registerService() on
350: // the interface client when the controller becomes ready.
351: //
352: // Returns true on success, false otherwise.
353:
354: bool
355: IONetworkController::attachInterface(IONetworkInterface ** interfaceP,
356: bool doRegister = true)
357: {
358: IONetworkInterface * netif;
359: bool initOk = false;
360:
361: *interfaceP = 0;
362:
363: // We delay some initialization until the first time that
364: // attachInterface() is called by the subclass.
365: //
366: SYNC_REQ(this, &IONetworkController::_controllerIsReady, &initOk);
367: if (!initOk)
368: return false;
369:
370: do {
371: // Allocate a concrete subclass of IONetworkInterface
372: // by calling createInterface().
373: //
374: netif = createInterface();
375: if (!netif)
376: break;
377:
378: // Configure the interface instance by calling
379: // configureInterface(), then attach it as our client.
380: //
381: if (!configureInterface(netif) ||
382: !configureNetworkInterface(netif) ||
383: !netif->attach(this))
384: {
385: netif->release();
386: break;
387: }
388:
389: *interfaceP = netif;
390:
391: // Register the interface nub. Spawns a matching thread.
392: //
393: if (doRegister)
394: netif->registerService();
395:
396: return true;
397: }
398: while (0);
399:
400: return false; // failed
401: }
402:
403: //---------------------------------------------------------------------------
404: // Detach the interface object. This method will check that
405: // the object provided is indeed an IONetworkInterface, and if so its
406: // terminate() method is called. The interface object will close and detach
407: // from its controller only after the network layer has removed all references
408: // to the data structures exposed by the interface.
409: //
410: // interface: An interface object to be detached.
411: // sync: If true, the interface is terminated synchronously.
412: // Note that this may cause detachInterface() to block
413: // for an indefinite period of time.
414:
415: void
416: IONetworkController::detachInterface(IONetworkInterface * interface,
417: bool sync = false)
418: {
419: IOOptionBits options = kIOServiceRequired;
420:
421: if (OSDynamicCast(IONetworkInterface, interface) == 0)
422: return;
423:
424: if (sync)
425: options |= kIOServiceSynchronous;
426:
427: interface->terminate(options);
428: }
429:
430: //---------------------------------------------------------------------------
431: // This method is called the first time that a controller driver calls
432: // attachInterface() or attachDebuggerClient(), which is an indication that
433: // the driver has been started and is ready to service client requests.
434: // IONetworkController uses this method to complete its initialization
435: // before any client objects are attached.
436: //
437: // provider: The controller's provider.
438: //
439: // Returns true on success, false otherwise.
440:
441: bool IONetworkController::ready(IOService * provider)
442: {
443: return publishCapabilities();
444: }
445:
446: //---------------------------------------------------------------------------
447: // Called when the controller is ready to handle client requests.
448: // Returns true to indicate success, false otherwise.
449:
450: bool IONetworkController::_controllerIsReady()
451: {
452: if (!_handleReady)
453: return true;
454:
455: if (!ready(getProvider())) // Call ready().
456: return false;
457:
458: _handleReady = false;
459: return true;
460: }
461:
462: //---------------------------------------------------------------------------
463: // Handle a client open on the controller object. IOService calls this method
464: // with the arbitration lock held. Subclasses are not expected to override
465: // this method.
466: //
467: // client: The client that is trying to open the controller.
468: // options: See IOService.
469: // argument: See IOService.
470: //
471: // Returns true to accept the client open, false to refuse the open.
472:
473: bool IONetworkController::handleOpen(IOService * client,
474: IOOptionBits options,
475: void * argument)
476: {
477: bool ok;
478:
479: assert(client);
480:
481: ok = _clientSet->setObject(client);
482: if (ok && OSDynamicCast(IOKernelDebugger, client))
483: {
484: ok = (doEnable(client) == kIOReturnSuccess);
485: if (!ok)
486: _clientSet->removeObject(client);
487: }
488: return ok;
489: }
490:
491: //---------------------------------------------------------------------------
492: // Handle a close from one of our client objects. IOService calls this method
493: // with the arbitration lock held. Subclasses are not expected to override this
494: // method.
495: //
496: // client: The client that has closed the controller.
497: // options: See IOService.
498:
499: void IONetworkController::handleClose(IOService * client, IOOptionBits options)
500: {
501: _clientSet->removeObject(client);
502:
503: if (OSDynamicCast(IOKernelDebugger, client))
504: doDisable(client);
505: }
506:
507: //---------------------------------------------------------------------------
508: // This method is always called by IOService with the arbitration lock held.
509: // Subclasses should not override this method.
510: //
511: // Returns true if the specified client, or any client if none is
512: // specified, presently has an open on this object.
513:
514: bool IONetworkController::handleIsOpen(const IOService * client) const
515: {
516: if (client)
517: return _clientSet->containsObject(client);
518: else
519: return (_clientSet->getCount() > 0);
520: }
521:
522: //---------------------------------------------------------------------------
523: // Free the IONetworkController instance and all allocated resources,
524: // then call super::free().
525:
526: void IONetworkController::free()
527: {
528: if (_outputQueue)
529: _outputQueue->release();
530:
531: if (_cmdGate)
532: _cmdGate->release();
533:
534: if (_workLoop)
535: _workLoop->release();
536:
537: if (_clientSet)
538: {
539: // We should have no clients at this point. If we do,
540: // then something is very wrong! It means that a client
541: // has an open on us, and yet we are going away.
542: //
543: assert(_clientSet->getCount() == 0);
544: _clientSet->release();
545: }
546:
547: if (_mediumLock)
548: IOLockFree(_mediumLock);
549:
550: super::free();
551: }
552:
553: //---------------------------------------------------------------------------
554: // Handle an enable request from a client. The client's class
555: // is typecasted using OSDynamicCast, and if the client is an
556: // IOKernelDebugger or an IONetworkInterface, an overloaded enable
557: // method that takes a more specific argument is called. If the client
558: // matches neither type, a kIOReturnBadArgument is returned.
559: // A driver has the option of override this generic enable method,
560: // or the derived version.
561: //
562: // client: The client object requesting the enable.
563: //
564: // The return value from the derived enable method, or
565: // kIOReturnBadArgument if the client's type is unknown.
566:
567: IOReturn IONetworkController::enable(IOService * client)
568: {
569: if (OSDynamicCast(IONetworkInterface, client))
570: return enable((IONetworkInterface *) client);
571:
572: if (OSDynamicCast(IOKernelDebugger, client))
573: return enable((IOKernelDebugger *) client);
574:
575: IOLog("%s::%s Unknown client type\n", getName(), __FUNCTION__);
576: return kIOReturnBadArgument;
577: }
578:
579: //---------------------------------------------------------------------------
580: // Handle an enable request from a client. The client
581: // object is typecasted using OSDynamicCast, and if the client is an
582: // IOKernelDebugger or an IONetworkInterface, then an overloaded disable
583: // method that takes a more specific argument is called. If the client
584: // matches neither type, a kIOReturnBadArgument is returned.
585: // A driver has the option of override this generic enable method,
586: // or the derived version.
587: //
588: // client: The client object requesting the disable.
589: //
590: // The return from the derived disable method, or
591: // kIOReturnBadArgument if the client's type is unknown
592:
593: IOReturn IONetworkController::disable(IOService * client)
594: {
595: if (OSDynamicCast(IONetworkInterface, client))
596: return disable((IONetworkInterface *) client);
597:
598: if (OSDynamicCast(IOKernelDebugger, client))
599: return disable((IOKernelDebugger *) client);
600:
601: IOLog("%s::%s Unknown client type\n", getName(), __FUNCTION__);
602: return kIOReturnBadArgument;
603: }
604:
605: //---------------------------------------------------------------------------
606: // Called by an interface client to enable the controller.
607: // This method must bring up the hardware and enable event sources
608: // to prepare for packet transmission and reception. A driver should
609: // delay the allocation of most runtime resources until this method is
610: // called to conserve shared system resources.
611: //
612: // interface: The interface object that requested the enable.
613: //
614: // Returns kIOReturnUnsupported. Driver may override this method and
615: // return kIOReturnSuccess on success, or an error code otherwise.
616:
617: IOReturn IONetworkController::enable(IONetworkInterface * interface)
618: {
619: IOLog("IONetworkController::%s called\n", __FUNCTION__);
620: return kIOReturnUnsupported;
621: }
622:
623: //---------------------------------------------------------------------------
624: // Called by an interface object to disable the controller.
625: // This method should quiesce the hardware and disable event sources.
626: // Any resources allocated in enable() should also be deallocated.
627: //
628: // interface: The interface object that requested the disable.
629: //
630: // Returns kIOReturnUnsupported. Driver may override this method and
631: // return kIOReturnSuccess on success, or an error code otherwise.
632:
633: IOReturn IONetworkController::disable(IONetworkInterface * interface)
634: {
635: IOLog("IONetworkController::%s called\n", __FUNCTION__);
636: return kIOReturnUnsupported;
637: }
638:
639: //---------------------------------------------------------------------------
640: // With the various overloaded forms of enable() and disable(), what does it
641: // mean when one does &IONetworkController::enable, to get the address of the
642: // member function?
643: // Instead, these private functions are registered which then calls the
644: // correct functions.
645:
646: IOReturn IONetworkController::_enable(IOService * client)
647: {
648: return enable(client);
649: };
650:
651: IOReturn IONetworkController::_disable(IOService * client)
652: {
653: return disable(client);
654: };
655:
656: //---------------------------------------------------------------------------
657: // Discover and publish controller capabilities to the property table.
658: // This method is called by ready().
659: //
660: // Returns true if all capabilities were discovered and published
661: // successfully, false otherwise. Returning false will prevent client
662: // objects from attaching to the controller since a property that
663: // a client depends on may be missing
664:
665: bool IONetworkController::publishCapabilities()
666: {
667: bool ret = true;
668: OSString * string;
669: UInt32 index;
670:
671: string = OSString::withCString(getVendorString());
672: if (string) {
673: ret = setProperty(kIOVendor, string) && ret;
674: string->release();
675: }
676:
677: string = OSString::withCString(getModelString());
678: if (string) {
679: ret = setProperty(kIOModel, string) && ret;
680: string->release();
681: }
682:
683: string = OSString::withCString(getRevisionString());
684: if (string) {
685: ret = setProperty(kIORevision, string) && ret;
686: string->release();
687: }
688:
689: string = OSString::withCString(getInfoString());
690: if (string) {
691: ret = setProperty(kIOInfo, string) && ret;
692: string->release();
693: }
694:
695: // Set OSNumber properties.
696: //
697: ret = (getControllerIndex(&index) == kIOReturnSuccess) && ret;
698: ret = setProperty(kIOControllerIndex, index, 32) && ret;
699: ret = setProperty(kIOFeatureSet, getFeatureSet(), 32) && ret;
700: ret = setProperty(kIOFamilyFeatureSet, getFamilyFeatureSet(), 32) && ret;
701:
702: if (getPacketFilters(&index) == kIOReturnSuccess) {
703: ret = setProperty(kIOPacketFilters, index, 32) && ret;
704: }
705: else {
706: ret = false;
707: }
708:
709: if (!ret)
710: DLOG("IONetworkController::%s error\n", __FUNCTION__);
711:
712: return ret;
713: }
714:
715: //---------------------------------------------------------------------------
716: // Broadcast a network event to all attached interface objects.
717: // This is equivalent to calling the IONetworkInterface::inputEvent()
718: // function for each interface client.
719: //
720: // IONetworkController uses this method to broadcast link and media
721: // events. Drivers will usually call the inputEvent() method directly
722: // since it is more efficient, and most drivers will only attach a
723: // single interface client.
724: //
725: // type: Event type.
726: // arg: Event argument.
727: //
728: // Returns true if the event was delivered, false if an error occurred
729: // (unable to perform object allocation) and the event was not delivered
730:
731: bool IONetworkController::broadcastEvent(UInt32 type, void * arg = 0)
732: {
733: IONetworkInterface * netif;
734: OSCollectionIterator * iter = 0;
735: OSSet * clientSet;
736:
737: lockForArbitration(); // locks open/close/state changes.
738:
739: if (_clientSet->getCount()) {
740: clientSet = OSSet::withSet(_clientSet, _clientSet->getCount());
741: if (clientSet) {
742: iter = OSCollectionIterator::withCollection(clientSet);
743: clientSet->release();
744: }
745: }
746:
747: unlockForArbitration();
748:
749: if (!iter)
750: return false;
751:
752: // Send the event to all attached interface objects.
753: //
754: while ((netif = (IONetworkInterface *) iter->getNextObject())) {
755: if (OSDynamicCast(IONetworkInterface, netif) == 0)
756: continue; // only send events to IONetworkInterface subclasses.
757: netif->inputEvent(type, arg);
758: }
759:
760: iter->release();
761:
762: return true;
763: }
764:
765: //---------------------------------------------------------------------------
766: // A client request for the controller to switch to a new MTU size.
767: //
768: // mtu: The new MTU size requested.
769: //
770: // Returns kIOReturnUnsupported. Drivers may override this method
771: // and return either kIOReturnSuccess to indicate that the new MTU size
772: // was accepted and is in effect, or an error to indicate failure.
773:
774: IOReturn IONetworkController::setMaxTransferUnit(UInt32 mtu)
775: {
776: return kIOReturnUnsupported;
777: }
778:
779: //---------------------------------------------------------------------------
780: // A client request for the driver to perform hardware
781: // diagnostics and return the test result after completion.
782: //
783: // resultCodeP: In addition to the return code, drivers may return
784: // a hardware specific failure code.
785: //
786: // Return kIOReturnSuccess if the hardware passed all test, or an
787: // appropriate error code otherwise. The default return is always
788: // kIOReturnUnsupported.
789:
790: IOReturn IONetworkController::performDiagnostics(UInt32 * resultCodeP)
791: {
792: return kIOReturnUnsupported;
793: }
794:
795: //---------------------------------------------------------------------------
796: // Transmit a packet mbuf. If an IOOutputQueue was allocated and returned by
797: // createOutputQueue(), then this method will be called by the queue object.
798: // Otherwise, an interface object will call this method directly upon
799: // receiving an output packet from the network layer. When a queue object
800: // is not present, this method must be safe from multiple client threads,
801: // each pushing a packet to be sent on the wire.
802: //
803: // There is no upper limit on the number of mbufs, hence the number of
804: // memory fragments, in the mbuf chain provided. Drivers must be able to
805: // handle cases when the chain might exceed the limit supported by their
806: // DMA engines, and perform coalescing to copy the various memory fragments
807: // into a lesser number of fragments. This complexity can be hidden from
808: // a driver when an IOMBufMemoryCursor is used, which is able to convert
809: // a mbuf chain into a physical address scatter-gather list that will not
810: // exceed a specified number of physically contiguous memory segments.
811: // See IOMBufMemoryCursor.
812: //
813: // Packets may also be chained to form a packet chain. Although the
814: // network layer, through the interface object, will currently only
815: // send a single mbuf packet to the controller for each outputPacket()
816: // call, it is possible for this to change. When a queue object is used,
817: // the queue will automatically accept a single packet or a packet chain,
818: // but it will call outputPacket() for each packet removed from the queue.
819: //
820: // The implementation in IONetworkController performs no useful action
821: // and will drop all packets. A driver must always override this method.
822: //
823: // m: The packet mbuf.
824: //
825: // Returns a return code defined by the caller.
826:
827: UInt32 IONetworkController::outputPacket(struct mbuf * m)
828: {
829: // The implementation here is simply a sink-hole, all packets are
830: // dropped.
831: //
832: if (m) freePacket(m);
833: return 0;
834: }
835:
836: //---------------------------------------------------------------------------
837: // A client request to adjust the capacity of the driver's output queue
838: // (number of packets the queue can hold). If a driver does not override
839: // this method, then the default action is to forward the request to
840: // an IOOutputQueue object if it was created. Otherwise return
841: // kIOReturnUnsupported.
842: //
843: // capacity: The new capacity of the output queue.
844: //
845: // Returns kIOReturnSuccess on success, kIOReturnBadArgument if the
846: // specified capacity is invalid, or kIOReturnUnsupported if the
847: // function is not supported.
848:
849: IOReturn IONetworkController::setOutputQueueCapacity(UInt32 capacity)
850: {
851: if (_outputQueue)
852: return _outputQueue->setCapacity(capacity) ?
853: kIOReturnSuccess : kIOReturnBadArgument;
854: else
855: return kIOReturnUnsupported;
856: }
857:
858: //---------------------------------------------------------------------------
859: // A client request to get the capacity of the output queue. If a driver
860: // does not override this method, then the default action is to forward the
861: // request to an IOOutputQueue object if it was created. Otherwise return
862: // kIOReturnUnsupported.
863: //
864: // capacityP: Address of an integer where the capacity
865: // shall be written to.
866: //
867: // Returns kIOReturnSuccess on success, or kIOReturnUnsupported if an
868: // IOOutputQueue object was not created.
869:
870: IOReturn IONetworkController::getOutputQueueCapacity(UInt32 * capacityP) const
871: {
872: if (_outputQueue) {
873: *capacityP = _outputQueue->getCapacity();
874: return kIOReturnSuccess;
875: }
876: return kIOReturnUnsupported;
877: }
878:
879: //---------------------------------------------------------------------------
880: // A client request to fetch the number of packets currently held by the
881: // queue. If a driver does not override this method, then the default action
882: // is to forward the request to an IOOutputQueue object if it was created.
883: // Otherwise return kIOReturnUnsupported.
884: //
885: // sizeP: Address of an integer where the size shall be written to.
886: //
887: // Returns kIOReturnSuccess on success, or kIOReturnUnsupported if an
888: // IOOutputQueue object was not created.
889:
890: IOReturn IONetworkController::getOutputQueueSize(UInt32 * sizeP) const
891: {
892: if (_outputQueue) {
893: *sizeP = _outputQueue->getSize();
894: return kIOReturnSuccess;
895: }
896: return kIOReturnUnsupported;
897: }
898:
899: //---------------------------------------------------------------------------
900: // A client request to flush all packets currently held by the queue,
901: // and return the number of packets discarded. If a driver does not
902: // override this method, then the default action is to forward the
903: // request to an IOOutputQueue object if it was created.
904: // Otherwise return kIOReturnUnsupported.
905: //
906: // flushCountP: Address of an integer where the number of packets
907: // discarded shall be written to.
908: //
909: // Returns kIOReturnSuccess on success, or kIOReturnUnsupported if an
910: // IOOutputQueue object was not created.
911:
912: IOReturn IONetworkController::flushOutputQueue(UInt32 * flushCountP)
913: {
914: if (_outputQueue) {
915: *flushCountP = _outputQueue->flush();
916: return kIOReturnSuccess;
917: }
918: return kIOReturnUnsupported;
919: }
920:
921: //---------------------------------------------------------------------------
922: // Report features supported by the controller.
923: //
924: // Returns 0. Drivers may override this method and return a mask
925: // containing all supported feature bits.
926:
927: UInt32 IONetworkController::getFeatureSet() const
928: {
929: return 0;
930: }
931:
932: //---------------------------------------------------------------------------
933: // Return a string describing the revision level of the controller.
934:
935: const char * IONetworkController::getRevisionString() const
936: {
937: return 0;
938: }
939:
940: //---------------------------------------------------------------------------
941: // Return a string containing any additional information about the controller
942: // and/or driver.
943:
944: const char * IONetworkController::getInfoString() const
945: {
946: return 0;
947: }
948:
949: //---------------------------------------------------------------------------
950: // Return an ordinal number for multiport network adapters.
951: // The implementation in IONetworkController will work for PCI controllers
952: // behind a PCI-PCI bridge. This method exists solely to support the
953: // current interface naming scheme, and is likely to
954: // undergo changes or may disappear in the future.
955: //
956: // indexP: The oridinal number should be written to the
957: // integer at this address.
958: //
959: // Returns kIOReturnSuccess.
960:
961: IOReturn IONetworkController::getControllerIndex(UInt32 * index) const
962: {
963: IOService * provider = getProvider();
964:
965: *index = 0;
966:
967: if (provider) {
968: OSNumber * offset = OSDynamicCast(OSNumber,
969: provider->getProperty("IOChildIndex"));
970: if (offset)
971: *index = offset->unsigned32BitValue();
972: }
973: return kIOReturnSuccess;
974: }
975:
976: //---------------------------------------------------------------------------
977: // Encodes a request received by syncRequest. This command structure is then
978: // submitted to commandHandler() through the IOCommandGate::runAction().
979:
980: struct cmdStruct {
981: OSObject * client;
982: OSObject * target;
983: IONetworkController::RequestAction action;
984: void * arg0;
985: void * arg1;
986: void * arg2;
987: void * arg3;
988: };
989:
990: //---------------------------------------------------------------------------
991: // Execute the request received by syncRequest() and encoded onto
992: // a cmdStruct structure. This method is called by IOCommandGate's
993: // runAction() method.
994:
995: void IONetworkController::commandHandler(void * arg0,
996: void * arg1,
997: void * arg2,
998: void * /*arg3*/)
999: {
1000: cmdStruct * cmd = (cmdStruct *) arg0; // cmdStruct
1001: UInt32 * actRetP = (UInt32 *) arg1; // action return
1002: IOReturn * cmdRetP = (IOReturn *) arg2; // commandHandler return
1003: OSObject * oldClient = _reqClient;
1004: bool accept = true;
1005:
1006: assert(cmd && actRetP && cmdRetP);
1007:
1008: if (cmd->client != this)
1009: {
1010: // Filter the client request.
1011:
1012: accept = syncRequestFilter(cmd->client,
1013: cmd->target,
1014: cmd->action,
1015: cmd->arg0,
1016: cmd->arg1,
1017: cmd->arg2,
1018: cmd->arg3);
1019: }
1020:
1021: if (accept) {
1022: _reqClient = cmd->client;
1023:
1024: *actRetP = ((cmd->target)->*(cmd->action))(cmd->arg0,
1025: cmd->arg1,
1026: cmd->arg2,
1027: cmd->arg3);
1028:
1029: _reqClient = oldClient;
1030:
1031: *cmdRetP = kIOReturnSuccess;
1032: }
1033: else {
1034: // actRetP is not set if the request was rejected by the filter.
1035: *cmdRetP = kIOReturnNotReady;
1036: }
1037: }
1038:
1039: //---------------------------------------------------------------------------
1040: // Perform a request action synchronously. Used both internally and also by
1041: // clients to execute an arbitrary request action using the IOCommandGate's
1042: // runAction() method. For client requests, where the client field is not
1043: // equal to 'this', the request is filtered by calling syncRequestFilter()
1044: // to qualify the client request. This filter function must return true
1045: // in order for the request to be accepted and the request action called.
1046: //
1047: // client: The client (caller) of the synchronous request.
1048: // target: The target object that implements the request action.
1049: // action: The action to perform.
1050: // ret: The return value from the action is written to the
1051: // integer with the provided address. The result is
1052: // not written if the request was rejected by the request filter.
1053: // arg0: Optional action argument.
1054: // arg1: Optional action argument.
1055: // arg2: Optional action argument.
1056: // arg3: Optional action argument.
1057: //
1058: // kIOReturnNotReady if the client request was rejected by the filter.
1059: // Otherwise kIOReturnSuccess is returned.
1060:
1061: IOReturn IONetworkController::syncRequest(OSObject * sender,
1062: OSObject * target,
1063: RequestAction action,
1064: UInt32 * ret = 0,
1065: void * arg0 = 0,
1066: void * arg1 = 0,
1067: void * arg2 = 0,
1068: void * arg3 = 0)
1069: {
1070: cmdStruct cmd;
1071: IOReturn rc;
1072: UInt32 ra;
1073:
1074: // bzero(&cmd, sizeof(cmd));
1075:
1076: cmd.client = sender; // request client.
1077: cmd.target = target; // target object.
1078: cmd.action = action; // target action.
1079: cmd.arg0 = arg0; // action arguments.
1080: cmd.arg1 = arg1;
1081: cmd.arg2 = arg2;
1082: cmd.arg3 = arg3;
1083:
1084: _cmdGate->runAction( (IOCommandGate::Action)
1085: &IONetworkController::commandHandler, /* Action */
1086: (void *) &cmd, /* arg0 - cmdStruct */
1087: (void *) &ra, /* arg1 - action return */
1088: (void *) &rc ); /* arg2 - commandHandler return */
1089:
1090: if ((rc == kIOReturnSuccess) && ret)
1091: *ret = ra;
1092:
1093: return rc;
1094: }
1095:
1096: //---------------------------------------------------------------------------
1097: // This method is called to qualify all client requests
1098: // sent to syncRequest(). This implementation will either allow or
1099: // refuse all requests, and this behavior is set by calling the
1100: // enableSyncRequest() or disableSyncRequest() methods. By default,
1101: // all requests are allowed.
1102: //
1103: // client: The client of the synchronous request.
1104: // target: The target object that implements the request action.
1105: // action: The action to perform.
1106: // arg0: Action argument.
1107: // arg1: Action argument.
1108: // arg2: Action argument.
1109: // arg3: Action argument.
1110: //
1111: // Returns true to accept the request and allow the request action to be
1112: // called, or false to refuse it.
1113:
1114: bool IONetworkController::syncRequestFilter(OSObject * client,
1115: OSObject * target,
1116: RequestAction action,
1117: void * arg0,
1118: void * arg1,
1119: void * arg2,
1120: void * arg3)
1121: {
1122: // If _requestEnabled ifs true, allow the request, otherwise refuse it.
1123:
1124: return _requestEnabled;
1125: }
1126:
1127: //---------------------------------------------------------------------------
1128: // A static member function to control the default syncRequestFilter()
1129: // filter function.
1130:
1131: void IONetworkController::_enableSyncRequestFilter(IONetworkController * ctlr,
1132: bool enabled)
1133: {
1134: ctlr->_requestEnabled = enabled;
1135: }
1136:
1137: //---------------------------------------------------------------------------
1138: // Enable all client requests sent to the syncRequest() method.
1139: // Don't use this method if the driver overrides syncRequestFilter().
1140:
1141: void IONetworkController::enableSyncRequest()
1142: {
1143: _cmdGate->runAction( (IOCommandGate::Action)
1144: &IONetworkController::_enableSyncRequestFilter,
1145: (void *) true );
1146: }
1147:
1148: //---------------------------------------------------------------------------
1149: // Disable all client requests sent to the syncRequest() method.
1150: // Don't use this method if the driver overrides syncRequestFilter().
1151:
1152: void IONetworkController::disableSyncRequest()
1153: {
1154: _cmdGate->runAction( (IOCommandGate::Action)
1155: &IONetworkController::_enableSyncRequestFilter,
1156: (void *) false );
1157: }
1158:
1159: //---------------------------------------------------------------------------
1160: // Get request client. Methods that are called by syncRequest() can call this
1161: // to get the client object which initiated the request.
1162: //
1163: // Returns the request client. If the caller's context does not indicate
1164: // that it is running through syncRequest(), then 0 is returned.
1165:
1166: OSObject * IONetworkController::getSyncRequestClient() const
1167: {
1168: return ( _workLoop->inGate() ? _reqClient : 0 );
1169: }
1170:
1171: //---------------------------------------------------------------------------
1172: // Configure an interface object created through
1173: // createInterface(). IONetworkController will register
1174: // its output handler with the interface object provided.
1175: // Subclasses may override this method to customize the interface object.
1176: // Once the interface is registered and opened by a client, it will
1177: // refuse changes to its properties. And since this method is called
1178: // before the interface has become registered, this is a final
1179: // opportunity for the controller to configure the interface.
1180: //
1181: // interface: The interface object to be configured.
1182: //
1183: // Returns true if configuration was successful, false otherwise (this
1184: // will cause attachInterface() to fail).
1185:
1186: bool IONetworkController::configureInterface(IONetworkInterface * interface)
1187: {
1188: IOOutputAction handler;
1189: OSObject * target;
1190: bool ret;
1191: IONetworkData * stats;
1192:
1193: if (!OSDynamicCast(IONetworkInterface, interface))
1194: return false;
1195:
1196: IOOutputQueue * outQueue = getOutputQueue();
1197:
1198: // Must register an output handler with the interface object.
1199: // The interface will send output packets, and requests (commands)
1200: // to its registered output handler. If we allocated an output
1201: // queue, then we register the queue as the output handler,
1202: // otherwise, we become the output handler.
1203:
1204: if (outQueue)
1205: {
1206: target = outQueue;
1207: handler = outQueue->getOutputHandler();
1208:
1209: stats = outQueue->getStatisticsData();
1210: interface->addNetworkData(stats);
1211: }
1212: else
1213: {
1214: target = this;
1215: handler = getOutputHandler();
1216: }
1217: ret = interface->registerOutputHandler(target, handler);
1218:
1219: return ret;
1220: }
1221:
1222: bool
1223: IONetworkController::configureNetworkInterface(IONetworkInterface * interface)
1224: {
1225: return true;
1226: }
1227:
1228: //---------------------------------------------------------------------------
1229: // Called by start() to create an optional IOOutputQueue instance to handle
1230: // output queueing. The default implementation will always return 0, hence
1231: // no output queue will be created. A driver may override this method and
1232: // return a subclass of IOOutputQueue. IONetworkController will keep a
1233: // reference to the queue created, and will release the object when
1234: // IONetworkController is freed. Also see getOutputQueue().
1235: //
1236: // Returns a newly allocated and initialized IOOutputQueue instance.
1237:
1238: IOOutputQueue * IONetworkController::createOutputQueue()
1239: {
1240: return 0;
1241: }
1242:
1243: IOOutputQueue * IONetworkController::allocateOutputQueue()
1244: {
1245: return 0;
1246: }
1247:
1248: //---------------------------------------------------------------------------
1249: // Return the output queue allocated though createOutputQueue().
1250:
1251: IOOutputQueue * IONetworkController::getOutputQueue() const
1252: {
1253: return _outputQueue;
1254: }
1255:
1256: //---------------------------------------------------------------------------
1257: // Called by start() to obtain the constraints on the memory buffer
1258: // associated with each mbuf allocated through allocatePacket().
1259: // Drivers can override this method to specify their buffer constraints
1260: // imposed by their bus master hardware. Note that outbound packets,
1261: // those that originate from the network stack, are not subject
1262: // to the constraints reported here.
1263: //
1264: // constraintsP: A pointer to an IOPacketBufferConstraints structure
1265: // that that this method is expected to initialize.
1266: // See IOPacketBufferConstraints structure definition.
1267:
1268: void IONetworkController::getPacketBufferConstraints(
1269: IOPacketBufferConstraints * constraintsP) const
1270: {
1271: assert(constraintsP);
1272: constraintsP->alignStart = kIOPacketBufferAlign1;
1273: constraintsP->alignLength = kIOPacketBufferAlign1;
1274: }
1275:
1276: //---------------------------------------------------------------------------
1277: // Allocates a mbuf chain. Each mbuf in the chain is aligned according to
1278: // the constraints from IONetworkController::getPacketBufferConstraints().
1279: // The last mbuf in the chain will be guaranteed to be length aligned if
1280: // the 'size' argument is a multiple of the length alignment.
1281: //
1282: // The m->m_len and m->pkthdr.len fields are updated by this function.
1283: // This allows the driver to pass the mbuf chain obtained through this
1284: // function to the IOMbufMemoryCursor object directly.
1285: //
1286: // If (size + alignments) is smaller than MCLBYTES, then this function
1287: // will always return a single mbuf header or cluster.
1288: //
1289: // The allocation is guaranteed not to block. If a packet cannot be
1290: // allocated, this function will return NULL.
1291:
1292: static inline UInt IO_ALIGN_MBUF(
1293: struct mbuf * m,
1294: UInt size,
1295: UInt alignStart,
1296: UInt alignLength)
1297: {
1298: assert(m);
1299: UInt not_aligned = mtod(m, UInt) & alignStart;
1300:
1301: // Align starting address.
1302: //
1303: if (not_aligned) {
1304: not_aligned = alignStart - not_aligned + 1;
1305: m->m_data += not_aligned;
1306: size -= not_aligned;
1307: }
1308:
1309: // Align buffer length.
1310: //
1311: if ((not_aligned = size & alignLength))
1312: size -= not_aligned;
1313:
1314: return size;
1315: }
1316:
1317: #define IO_APPEND_MBUF(head, tail, m) { \
1318: if (tail) { \
1319: (tail)->m_next = (m); \
1320: (tail) = (m); \
1321: } \
1322: else { \
1323: (head) = (tail) = (m); \
1324: (head)->m_pkthdr.len = 0; \
1325: } \
1326: }
1327:
1328: struct mbuf * IONetworkController::allocatePacket(UInt size)
1329: {
1330: struct mbuf * head = 0;
1331: struct mbuf * tail = 0;
1332:
1333: while (size) {
1334: UInt mbufSize;
1335: struct mbuf * m;
1336:
1337: // Allocate a mbuf, for the initial mbuf segment, allocate a
1338: // mbuf header, otherwise a 'normal' mbuf will do.
1339:
1340: if (head) {
1341: MGET(m, M_DONTWAIT, MT_DATA);
1342: mbufSize = MLEN;
1343: }
1344: else {
1345: MGETHDR(m, M_DONTWAIT, MT_DATA);
1346: mbufSize = MHLEN;
1347: }
1348:
1349: if (!m) goto error;
1350:
1351: // Append the new mbuf to our chain.
1352:
1353: IO_APPEND_MBUF(head, tail, m);
1354:
1355: // If the remaining size exceed the buffer size of a normal mbuf,
1356: // then attach a cluster to our mbuf. Currently, the cluster size
1357: // is fixed, and the allocated memory is always MCLBYTES in size.
1358:
1359: if ((size + _alignPadding) > mbufSize) {
1360: MCLGET(m, M_DONTWAIT);
1361: if ((m->m_flags & M_EXT) == 0) goto error;
1362: mbufSize = MCLBYTES;
1363: }
1364:
1365: // mbufSize shall contain the (reduced) capacity of the mbuf after
1366: // alignment.
1367: //
1368: mbufSize = IO_ALIGN_MBUF(m, mbufSize, _alignStart, _alignLength);
1369:
1370: if (mbufSize > size) {
1371: // If we wanted to force all mbufs in the chain to be aligned,
1372: // including the last one, then do the following.
1373: //
1374: // mbufSize -= (mbufSize - size) & ~_alignLength;
1375:
1376: mbufSize = size;
1377: size = 0;
1378: }
1379: else
1380: size -= mbufSize; // decrement the remaining size
1381:
1382: m->m_len = mbufSize; // update the length for this mbuf
1383: head->m_pkthdr.len += mbufSize; // increment the total length
1384: }
1385:
1386: return head;
1387:
1388: error:
1389: if (head) m_freem(head);
1390: return 0;
1391: }
1392:
1393: //---------------------------------------------------------------------------
1394: // Release the mbuf back to the free pool.
1395:
1396: void IONetworkController::freePacket(struct mbuf * m)
1397: {
1398: assert(m);
1399: while (m) m = m_free(m);
1400: }
1401:
1402: static inline bool IO_COPY_MBUF(
1403: const struct mbuf * src,
1404: struct mbuf * dst,
1405: int length)
1406: {
1407: caddr_t src_dat, dst_dat;
1408: int dst_len, src_len;
1409:
1410: assert(src && dst);
1411:
1412: dst_len = dst->m_len;
1413: dst_dat = dst->m_data;
1414:
1415: while (src) {
1416:
1417: src_len = src->m_len;
1418: src_dat = src->m_data;
1419:
1420: if (src_len > length)
1421: src_len = length;
1422:
1423: while (src_len) {
1424:
1425: if (dst_len >= src_len) {
1426: // copy entire src mbuf to dst mbuf.
1427:
1428: bcopy(src_dat, dst_dat, src_len);
1429: length -= src_len;
1430: dst_len -= src_len;
1431: dst_dat += src_len;
1432: src_len = 0;
1433: }
1434: else {
1435: // fill up dst mbuf with some portion of the data in
1436: // the src mbuf.
1437:
1438: bcopy(src_dat, dst_dat, dst_len); // dst_len = 0?
1439: length -= dst_len;
1440: dst_len = 0;
1441: src_len -= dst_len;
1442: }
1443:
1444: // Go to the next destination mbuf segment.
1445:
1446: if (dst_len == 0) {
1447: if (!(dst = dst->m_next))
1448: return (length == 0);
1449: dst_len = dst->m_len;
1450: dst_dat = dst->m_data;
1451: }
1452:
1453: } /* while (src_len) */
1454:
1455: src = src->m_next;
1456:
1457: } /* while (src) */
1458:
1459: return (length == 0); // returns true on success.
1460: }
1461:
1462: //---------------------------------------------------------------------------
1463: // Replace the mbuf pointed by the given pointer with another mbuf.
1464: // Drivers can call this method to replace a mbuf before passing the
1465: // original mbuf, which contains a received frame, to the network layer.
1466: //
1467: // mp: A pointer to the original mbuf that shall be updated by this
1468: // method to point to the new mbuf.
1469: // size: If size is 0, then the new mbuf shall have the same size
1470: // as the original mbuf that is being replaced. Otherwise, the new
1471: // mbuf shall have the size specified here.
1472: //
1473: // If mbuf allocation was successful, then the replacement will
1474: // take place and the original mbuf will be returned. Otherwise,
1475: // a NULL is returned.
1476:
1477: struct mbuf * IONetworkController::replacePacket(struct mbuf ** mp,
1478: UInt size = 0)
1479: {
1480: assert((mp != NULL) && (*mp != NULL));
1481:
1482: struct mbuf * m = *mp;
1483:
1484: // If size is zero, then size is taken from the source mbuf.
1485: //
1486: if (size == 0)
1487: size = m->m_pkthdr.len;
1488:
1489: // Allocate a new packet to replace the current packet.
1490: //
1491: if (!(*mp = allocatePacket(size)))
1492: {
1493: *mp = m; m = 0;
1494: }
1495:
1496: return m;
1497: }
1498:
1499: //---------------------------------------------------------------------------
1500: // Make a copy of a mbuf, and return the copy. The source mbuf is not modified.
1501: //
1502: // m: The source mbuf.
1503: // size: The number of bytes to copy. If set to 0, then the entire
1504: // source mbuf is copied.
1505: //
1506: // Returns a new mbuf created from the source packet.
1507:
1508: struct mbuf * IONetworkController::copyPacket(const struct mbuf * m,
1509: UInt size = 0)
1510: {
1511: struct mbuf * mn;
1512:
1513: assert(m != NULL);
1514:
1515: // If size is zero, then size is taken from the source mbuf.
1516: //
1517: if (size == 0)
1518: size = m->m_pkthdr.len;
1519:
1520: // Copy the current mbuf to the new mbuf, and return the new mbuf.
1521: // The input mbuf is left intact.
1522: //
1523: if (!(mn = allocatePacket(size)))
1524: return 0;
1525:
1526: if (!IO_COPY_MBUF(m, mn, size))
1527: {
1528: IOLog("IONetworkController: copyPacket failure\n");
1529: freePacket(mn);
1530: mn = 0;
1531: }
1532:
1533: return mn;
1534: }
1535:
1536: //---------------------------------------------------------------------------
1537: // Either replace or copy the source mbuf given depending on the amount of
1538: // data in the source mbuf. This method will either perform a copy or replace
1539: // the source mbuf, whichever is more time efficient. If replaced, then the
1540: // original mbuf is returned, and a new mbuf is allocated to take its place.
1541: // If copied, the source mbuf is left intact, while a copy is returned that
1542: // is just big enough to hold all the data from the source mbuf.
1543: //
1544: // mp: A pointer to the source mbuf that may be updated by this
1545: // method to point to the new mbuf if replaced.
1546: // rcvlen: The number of data bytes in the source mbuf.
1547: // replacedP: Pointer to a bool that is set to true if the
1548: // source mbuf was replaced, or set to false if the
1549: // source mbuf was copied.
1550: //
1551: // Returns a replacement or a copy of the source mbuf, 0 if mbuf
1552: // allocation failed.
1553:
1554: struct mbuf * IONetworkController::replaceOrCopyPacket(struct mbuf ** mp,
1555: UInt rcvlen,
1556: bool * replacedP)
1557: {
1558: struct mbuf * m;
1559:
1560: if ((rcvlen + _alignPadding) > MHLEN)
1561: {
1562: // Large packet, it is more efficient to allocate a new mbuf
1563: // to replace the original mbuf than to make a copy. The new
1564: // packet shall have the same size as the original mbuf being
1565: // replaced.
1566: //
1567: m = replacePacket(mp);
1568: *replacedP = true;
1569: }
1570: else {
1571: // The copy will fit within a header mbuf. Fine, make a copy
1572: // of the original mbuf instead of replacing it. We only copy
1573: // the rcvlen bytes, not the entire source mbuf.
1574: //
1575: assert((mp != NULL) && (*mp != NULL));
1576: m = copyPacket(*mp, rcvlen);
1577: *replacedP = false;
1578: }
1579:
1580: return m;
1581: }
1582:
1583: //---------------------------------------------------------------------------
1584: // Used for debugging only. Log the mbuf header.
1585:
1586: void IONetworkController::_logMbuf(struct mbuf * m)
1587: {
1588: if (!m) {
1589: IOLog("logMbuf: NULL mbuf\n");
1590: return;
1591: }
1592:
1593: while (m) {
1594: IOLog("m_next : %08x\n", (UInt) m->m_next);
1595: IOLog("m_nextpkt: %08x\n", (UInt) m->m_nextpkt);
1596: IOLog("m_len : %d\n", (UInt) m->m_len);
1597: IOLog("m_data : %08x\n", (UInt) m->m_data);
1598: IOLog("m_type : %08x\n", (UInt) m->m_type);
1599: IOLog("m_flags : %08x\n", (UInt) m->m_flags);
1600:
1601: if (m->m_flags & M_PKTHDR)
1602: IOLog("m_pkthdr.len : %d\n", (UInt) m->m_pkthdr.len);
1603:
1604: if (m->m_flags & M_EXT) {
1605: IOLog("m_ext.ext_buf : %08x\n", (UInt) m->m_ext.ext_buf);
1606: IOLog("m_ext.ext_size: %d\n", (UInt) m->m_ext.ext_size);
1607: }
1608:
1609: m = m->m_next;
1610: }
1611: IOLog("\n");
1612: }
1613:
1614: //---------------------------------------------------------------------------
1615: // Allocate and attache a new IOKernelDebugger client object.
1616: //
1617: // debuggerP: An IOKernelDebugger handle that is updated by this method
1618: // to contain the allocated IOKernelDebugger instance.
1619: //
1620: // Returns true on success, false otherwise.
1621:
1622: bool IONetworkController::attachDebuggerClient(IOKernelDebugger ** debugger)
1623: {
1624: IOKernelDebugger * client;
1625: OSString * debuggerString;
1626: bool ret = false;
1627: bool initOk = false;
1628:
1629: // We delay some initialization until the first time that
1630: // attachInterface() is called by the subclass.
1631: //
1632: SYNC_REQ(this, &IONetworkController::_controllerIsReady, &initOk);
1633: if (!initOk)
1634: return false;
1635:
1636: // Refuse to attach a debugger client if the controller's kIOEnableDebugger
1637: // property set to No (first letter starts with 'n' or 'N').
1638:
1639: debuggerString = OSDynamicCast(OSString, getProperty(kIOEnableDebugger));
1640: if (!debuggerString ||
1641: (debuggerString->getChar(0) == 'N') ||
1642: (debuggerString->getChar(0) == 'n'))
1643: return false;
1644:
1645: // Create a debugger client nub and register the static
1646: // member functions as the polled-mode handlers.
1647: //
1648: client = IOKernelDebugger::debugger(this,
1649: &debugTxHandler,
1650: &debugRxHandler);
1651:
1652: *debugger = client;
1653:
1654: if (client && !client->attach(this))
1655: {
1656: // Unable to attach the client object.
1657: *debugger = 0;
1658: client->detach(this);
1659: client->release();
1660: }
1661:
1662: if (*debugger)
1663: {
1664: IOLog("%s: Debugger client attached\n", getName());
1665: publishResource("kdp");
1666: ret = true;
1667: }
1668:
1669: return ret;
1670: }
1671:
1672: //---------------------------------------------------------------------------
1673: // Detach and terminate the IOKernelDebugger client object provided.
1674: // A synchronous termination is issued, and this method returns after
1675: // the client has been terminated.
1676: //
1677: // debugger: The IOKernelDebugger instance to be detached and terminated.
1678: // If the argument provided is NULL or is not an IOKernelDebugger,
1679: // this method will return immediately.
1680:
1681: void IONetworkController::detachDebuggerClient(IOKernelDebugger * debugger)
1682: {
1683: if (OSDynamicCast(IOKernelDebugger, debugger) == 0)
1684: return;
1685:
1686: // Terminate the debugger client and return after the client has
1687: // been terminated. Since the debugger has no IOKit clients of
1688: // its own, this should be fast.
1689:
1690: debugger->terminate(kIOServiceRequired | kIOServiceSynchronous);
1691: }
1692:
1693: //---------------------------------------------------------------------------
1694: // An enable request from an IOKernelDebugger client. This method is called
1695: // when an open is received from an IOKernelDebugger client. Drivers that
1696: // wish to provide debugging services must override this method and setup
1697: // the hardware to support the polled-mode send and receive methods;
1698: // receivePacket() and sendPacket(). Debug capable drivers may also override
1699: // the more generic enable/disable calls that take an IOService argument.
1700: //
1701: // debugger: The IOKernelDebugger client that issued the open.
1702: //
1703: // Returns kIOReturnSuccess. The driver method must return kIOReturnSuccess
1704: // to allow the debugger open, anything else will cause the debugger open
1705: // to fail and the attachDebuggerClient() method will return false.
1706:
1707: IOReturn IONetworkController::enable(IOKernelDebugger * debugger)
1708: {
1709: return handleDebuggerOpen(debugger);
1710: }
1711:
1712: IOReturn IONetworkController::handleDebuggerOpen(IOKernelDebugger * debugger)
1713: {
1714: return kIOReturnSuccess;
1715: }
1716:
1717: //---------------------------------------------------------------------------
1718: // A disable request from an IOKernelDebugger client. This method is called
1719: // when a close is received from an IOKernelDebugger client. A driver which
1720: // implements enable(IOKernelDebugger *) should also implement this method
1721: // to disable hardware support for the polled-mode send and receive methods.
1722: //
1723: // debugger: The IOKernelDebugger client that issued the close.
1724: //
1725: // Returns kIOReturnSuccess. The driver method should return a status
1726: // from the disable operation.
1727:
1728: IOReturn IONetworkController::disable(IOKernelDebugger * debugger)
1729: {
1730: return handleDebuggerClose(debugger);
1731: }
1732:
1733: IOReturn IONetworkController::handleDebuggerClose(IOKernelDebugger * debugger)
1734: {
1735: return kIOReturnSuccess;
1736: }
1737:
1738: //---------------------------------------------------------------------------
1739: // Take and release the debugger lock.
1740:
1741: void IONetworkController::reserveDebuggerLock()
1742: {
1743: _debugLockState = IODebuggerLock(this);
1744: }
1745:
1746: void IONetworkController::releaseDebuggerLock()
1747: {
1748: IODebuggerUnlock(_debugLockState);
1749: }
1750:
1751: //---------------------------------------------------------------------------
1752: // This static C++ member function is registered by attachDebuggerClient()
1753: // as the debugger receive handler. IOKernelDebugger will call this
1754: // function when KDP is polling for a received packet. This function will
1755: // in turn will call the receivePacket() member function implemented by
1756: // a driver with debugger support.
1757:
1758: void IONetworkController::debugRxHandler(IOService * handler,
1759: void * buffer,
1760: UInt * length,
1761: UInt timeout)
1762: {
1763: ((IONetworkController *) handler)->receivePacket(buffer,
1764: length,
1765: timeout);
1766: }
1767:
1768: //---------------------------------------------------------------------------
1769: // This static C++ member function is registered by attachDebuggerClient()
1770: // as the debugger transmit handler. IOKernelDebugger will call this
1771: // function when KDP sends an outgoing packet. This function will in turn
1772: // call the sendPacket() member function implemented by a driver with
1773: // debugger support.
1774:
1775: void IONetworkController::debugTxHandler(IOService * handler,
1776: void * buffer,
1777: UInt length)
1778: {
1779: ((IONetworkController *) handler)->sendPacket(buffer, length);
1780: }
1781:
1782: //---------------------------------------------------------------------------
1783: // Debugger polled-mode receive handler. This method must be implemented
1784: // by a driver that supports kernel debugging. After a debugger client is
1785: // attached through attachDebuggerClient(), this method will be called by
1786: // the debugger object to poll for a incoming packet when the debugger is
1787: // active. This method can be called from an interrupt context, and the
1788: // driver must never block or perform any memory allocation. The
1789: // receivePacket() method in IONetworkController is used as a placeholder
1790: // and should never be called. A driver that attaches a debugger client
1791: // must override this method.
1792: //
1793: // pkt: Pointer to a receive buffer where the received packet should
1794: // be stored to. The buffer has room for 1518 bytes.
1795: // pkt_len: The length of the received packet must be written to the
1796: // integer pointed by pkt_len.
1797: // timeout: The maximum amount of time in milliseconds to poll for
1798: // a packet to arrive before this method must return.
1799:
1800: void IONetworkController::receivePacket(void * /*pkt*/,
1801: UInt * /*pkt_len*/,
1802: UInt /*timeout*/)
1803: {
1804: IOLog("IONetworkController::%s()\n", __FUNCTION__);
1805: }
1806:
1807: //---------------------------------------------------------------------------
1808: // Debugger polled-mode transmit handler. This method must be implemented
1809: // by a driver that supports kernel debugging. After a debugger client is
1810: // attached through attachDebuggerClient(), this method will be called by
1811: // the debugger object to send an outbound packet generated by the debugger.
1812: // This method can be called from an interrupt context, and the
1813: // driver must never block or perform any memory allocation. The
1814: // sendPacket() method in IONetworkController is used as a placeholder
1815: // and should never be called. A driver that attaches a debugger client
1816: // must override this method.
1817: //
1818: // pkt: Pointer to a transmit buffer containing the packet to be sent.
1819: // pkt_len: The amount of data in the transmit buffer.
1820:
1821: void IONetworkController::sendPacket(void * /*pkt*/, UInt /*pkt_len*/)
1822: {
1823: IOLog("IONetworkController::%s()\n", __FUNCTION__);
1824: }
1825:
1826: //---------------------------------------------------------------------------
1827: // Report the link status and the active medium. Update the link status
1828: // parameters published by the controller. Drivers should call this method
1829: // whenever the link status changes. Never call this method from interrupt
1830: // context since this method may block. An event will be sent to all attached
1831: // interface objects when a change is detected.
1832: //
1833: // status: Link status bits. See IONetworkMedium.h for defined link
1834: // status bits.
1835: // speed: Link speed in units of bits per second.
1836: // activeMedium: A medium entry in the published medium dictionary
1837: // where the link was established. This may not be the
1838: // same as the current medium.
1839: // data: An OSData containing any additional link information.
1840: //
1841: // Returns true if all link properties were successfully updated,
1842: // false otherwise.
1843:
1844: bool IONetworkController::setLinkStatus(UInt32 status,
1845: UInt64 speed,
1846: const IONetworkMedium * activeMedium,
1847: OSData * data = 0)
1848: {
1849: bool ret;
1850: bool changed = false;
1851:
1852: MEDIUM_LOCK;
1853:
1854: ret = setMediumProperty(gIOActiveMediumKey,
1855: activeMedium,
1856: &_activeMedium,
1857: false,
1858: &changed);
1859:
1860: ret = setLink32Property(kIOLinkStatus,
1861: status,
1862: &_linkStatus,
1863: false,
1864: &changed) && ret;
1865:
1866: ret = setLink64Property(kIOLinkSpeed,
1867: speed,
1868: &_linkSpeed,
1869: false,
1870: &changed) && ret;
1871:
1872: if (data) {
1873: if (_linkData != data) {
1874: ret = setProperty(kIOLinkData, data) && ret;
1875: _linkData = data;
1876: changed = true;
1877: }
1878: }
1879: else if (_linkData) {
1880: _linkData = 0;
1881: removeProperty(kIOLinkData);
1882: changed = true;
1883: }
1884:
1885: MEDIUM_UNLOCK;
1886:
1887: if (changed)
1888: broadcastEvent(kIONetworkEventLinkChange);
1889:
1890: return ret;
1891: }
1892:
1893: //---------------------------------------------------------------------------
1894: // Returns the medium dictionary published by the driver through
1895: // publishMediumDictionary(). Use copyMediumDictionary() to get a copy
1896: // of the medium dictionary.
1897: //
1898: // Returns the published medium dictionary, or 0 if the driver has not
1899: // yet published a medium dictionary using publishMediumDictionary().
1900:
1901: const OSDictionary * IONetworkController::getMediumDictionary() const
1902: {
1903: return OSDynamicCast(OSDictionary, getProperty(kIOMediumDictionary));
1904: }
1905:
1906: //---------------------------------------------------------------------------
1907: // Returns a.copy of the medium dictionary published by the driver.
1908: // The caller is responsible for releasing the dictionary object returned.
1909: // Use getMediumDictionary() to get a reference to the published medium
1910: // dictionary instead of creating a copy.
1911: //
1912: // Returns a copy of the medium dictionary, or 0 if the driver has not
1913: // published a medium dictionary using publishMediumDictionary().
1914:
1915: OSDictionary * IONetworkController::copyMediumDictionary() const
1916: {
1917: OSDictionary * newMediumDict = 0;
1918:
1919: MEDIUM_LOCK;
1920:
1921: if (getMediumDictionary()) {
1922: newMediumDict = OSDictionary::withDictionary(getMediumDictionary(),
1923: getMediumDictionary()->getCount());
1924: }
1925:
1926: MEDIUM_UNLOCK;
1927:
1928: return newMediumDict;
1929: }
1930:
1931: //---------------------------------------------------------------------------
1932: // A client request for the controller to change the selected medium.
1933: // Drivers may override this method and provide an implementation
1934: // appropriate for its hardware, then call setCurrentMedium() to update
1935: // the current medium property if a change occurred.
1936: //
1937: // medium: An entry in the published medium dictionary.
1938: //
1939: // Return kIOReturnUnsupported. Drivers may override this method and
1940: // return kIOReturnSuccess if the selected medium was activated,
1941: // or an error code otherwise.
1942:
1943: IOReturn IONetworkController::selectMedium(const IONetworkMedium * medium)
1944: {
1945: return kIOReturnUnsupported;
1946: }
1947:
1948: //---------------------------------------------------------------------------
1949: // Private function to lookup a key in the medium dictionary and call
1950: // setMedium() if a match is found. This function is called by our
1951: // clients to change the medium by passing a name for the desired medium.
1952:
1953: IOReturn IONetworkController::selectMediumWithName(const OSSymbol * mediumName)
1954: {
1955: OSSymbol * currentMediumName;
1956: IONetworkMedium * newMedium = 0;
1957: bool doChange = true;
1958: IOReturn ret = kIOReturnSuccess;
1959:
1960: if (OSDynamicCast(OSSymbol, mediumName) == 0)
1961: return kIOReturnBadArgument;
1962:
1963: MEDIUM_LOCK;
1964:
1965: do {
1966: const OSDictionary * mediumDict = getMediumDictionary();
1967: if (!mediumDict) { // no medium dictionary, bail out.
1968: ret = kIOReturnUnsupported;
1969: break;
1970: }
1971:
1972: // Lookup the new medium in the dictionary.
1973: //
1974: newMedium = OSDynamicCast(IONetworkMedium,
1975: mediumDict->getObject(mediumName));
1976: if (!newMedium) {
1977: ret = kIOReturnBadArgument;
1978: break; // not found, invalid mediumName.
1979: }
1980:
1981: newMedium->retain();
1982:
1983: // Lookup the current medium key to avoid unnecessary
1984: // medium changes.
1985: //
1986: currentMediumName = (OSSymbol *) getProperty(gIOCurrentMediumKey);
1987:
1988: // Is change necessary?
1989: //
1990: if (currentMediumName && mediumName->isEqualTo(currentMediumName))
1991: doChange = false;
1992: }
1993: while (0);
1994:
1995: MEDIUM_UNLOCK;
1996:
1997: if (newMedium)
1998: {
1999: // Call the driver's selectMedium() without holding the medium lock.
2000:
2001: if (doChange)
2002: ret = selectMedium(newMedium);
2003:
2004: // offset the earlier retain count increment.
2005: //
2006: newMedium->release();
2007: }
2008:
2009: return ret;
2010: }
2011:
2012: //---------------------------------------------------------------------------
2013: // Private function to add/replace/remove a medium property in the
2014: // property table. Returns true if the medium property was successfully
2015: // added to the property table. The medium lock should be held before
2016: // calling this function.
2017:
2018: bool IONetworkController::setMediumProperty(const OSSymbol * key,
2019: const IONetworkMedium * medium,
2020: const IONetworkMedium ** cache,
2021: bool force,
2022: bool * changed)
2023: {
2024: bool ret = false;
2025:
2026: do {
2027: if (!force && (*cache == medium))
2028: {
2029: ret = true;
2030: break;
2031: }
2032:
2033: if (medium == 0)
2034: {
2035: removeProperty(key);
2036: if (changed) *changed = true;
2037: *cache = 0;
2038: ret = true;
2039: break;
2040: }
2041:
2042: const OSDictionary * mediumDict = getMediumDictionary();
2043: if (!mediumDict)
2044: break; // no medium dictionary, bail out.
2045:
2046: if (OSDynamicCast(IONetworkMedium, medium) == 0)
2047: break; // not a valid IONetworkMedium.
2048:
2049: // Make sure the medium given is an entry in the medium dictionary.
2050: //
2051: if (mediumDict->getObject(medium->getName()) != (OSObject *) medium)
2052: break; // not a member of dictionary.
2053:
2054: // Update property table.
2055: //
2056: if ((ret = setProperty(key, (OSSymbol *) medium->getName())))
2057: {
2058: if (changed) *changed = true;
2059: *cache = medium;
2060: }
2061: }
2062: while (0);
2063:
2064: return ret;
2065: }
2066:
2067: bool IONetworkController::setLink64Property(const char * key,
2068: UInt64 value,
2069: UInt64 * cache,
2070: bool force = false,
2071: bool * changed = 0)
2072: {
2073: if (!force && (*cache == value))
2074: return true;
2075:
2076: if (setProperty(key, value, 64))
2077: {
2078: if (changed) *changed = true;
2079: *cache = value;
2080: return true;
2081: }
2082:
2083: return false;
2084: }
2085:
2086: bool IONetworkController::setLink32Property(const char * key,
2087: UInt32 value,
2088: UInt32 * cache,
2089: bool force = false,
2090: bool * changed = 0)
2091: {
2092: if (!force && (*cache == value))
2093: return true;
2094:
2095: if (setProperty(key, value, 32))
2096: {
2097: if (changed) *changed = true;
2098: *cache = value;
2099: return true;
2100: }
2101:
2102: return false;
2103: }
2104:
2105: //---------------------------------------------------------------------------
2106: // From the set of medium objects in the medium dictionary published by the
2107: // driver, one of them can be designated as the currently selected medium.
2108: // Drivers should call this method whenever their media selection changes.
2109: // An entry in the driver's property table is updated to advertise the
2110: // current medium.
2111: //
2112: // A media change event will be broadcasted to all attached interface
2113: // clients when the current medium property changes.
2114: //
2115: // medium: A medium object to promote as the current medium.
2116: //
2117: // Returns true if the medium dictionary exists, the medium object
2118: // provided matches an entry in this dictionary, and the property
2119: // table update was successful, false otherwise.
2120:
2121: bool IONetworkController::setCurrentMedium(const IONetworkMedium * medium)
2122: {
2123: bool ret, changed;
2124:
2125: MEDIUM_LOCK;
2126: ret = setMediumProperty(gIOCurrentMediumKey,
2127: medium,
2128: &_currentMedium,
2129: false,
2130: &changed);
2131: MEDIUM_UNLOCK;
2132:
2133: if (changed)
2134: broadcastEvent(kIONetworkEventMediumChange);
2135:
2136: return ret;
2137: }
2138:
2139: //---------------------------------------------------------------------------
2140: // Returns the currently selected medium object. If the driver has yet to
2141: // assign an entry in its medium dictionary as the current medium using the
2142: // setCurrentMedium() method, then the driver's property table is consulted
2143: // and a default medium property (can be set by the user), is looked
2144: // up and the corresponding entry in the medium dictionary is returned.
2145: // Therefore, drivers can always call getCurrentMedium() to either get
2146: // the current medium selected by the driver, or the default
2147: // medium chosen by the user.
2148: //
2149: // Returns the current medium entry from the medium dictionary, or 0
2150: // if a matching entry was not found.
2151:
2152: const IONetworkMedium * IONetworkController::getCurrentMedium() const
2153: {
2154: IONetworkMedium * currentMedium = 0;
2155: OSString * currentMediumName = 0;
2156:
2157: MEDIUM_LOCK;
2158:
2159: do {
2160: const OSDictionary * mediumDict = getMediumDictionary();
2161: if (!mediumDict) // no medium dictionary, bail out.
2162: break;
2163:
2164: // Fetch the current medium name from the property table.
2165: //
2166: currentMediumName = OSDynamicCast(OSString,
2167: getProperty(gIOCurrentMediumKey));
2168:
2169: // Make sure the current medium name points to an entry in
2170: // the medium dictionary.
2171: //
2172: if (currentMediumName && !mediumDict->getObject(currentMediumName))
2173: currentMediumName = 0;
2174:
2175: if (currentMediumName == 0) {
2176: OSString * defaultMediumName;
2177:
2178: // No (valid) current medium name, try the default medium name.
2179: //
2180: defaultMediumName = OSDynamicCast(OSString,
2181: getProperty(kIODefaultMedium));
2182:
2183: // If there is a default medium name, and it points to a
2184: // valid entry in the medium dictionary, then make it
2185: // current.
2186: //
2187: if (defaultMediumName &&
2188: mediumDict->getObject(defaultMediumName))
2189: {
2190: // setProperty(kIOCurrentMedium, defaultMediumKey);
2191: currentMediumName = defaultMediumName;
2192: }
2193: }
2194:
2195: if (currentMediumName)
2196: currentMedium = OSDynamicCast(IONetworkMedium,
2197: mediumDict->getObject(currentMediumName));
2198: }
2199: while (0);
2200:
2201: MEDIUM_UNLOCK;
2202:
2203: return currentMedium;
2204: }
2205:
2206: //---------------------------------------------------------------------------
2207: // A private function to verify a medium dictionary. Returns true if the
2208: // dictionary is OK.
2209:
2210: bool IONetworkController::verifyMediumDictionary(
2211: const OSDictionary * mediumDict)
2212: {
2213: OSCollectionIterator * iter;
2214: bool verifyOk = true;
2215: OSSymbol * key;
2216:
2217: if (!OSDynamicCast(OSDictionary, mediumDict))
2218: return false; // invalid argument
2219:
2220: if (mediumDict->getCount() == 0)
2221: return false; // empty dictionary
2222:
2223: iter = OSCollectionIterator::withCollection((OSDictionary *) mediumDict);
2224: if (!iter)
2225: return false; // cannot allocate iterator
2226:
2227: while ((key = (OSSymbol *) iter->getNextObject()))
2228: {
2229: if ( !OSDynamicCast(IONetworkMedium, mediumDict->getObject(key)) )
2230: {
2231: verifyOk = false; // non-medium object in dictionary
2232: break;
2233: }
2234: }
2235:
2236: iter->release();
2237:
2238: return verifyOk;
2239: }
2240:
2241: //---------------------------------------------------------------------------
2242: // Called by drivers to publish their medium dictionary.
2243: // The dictionary consist of IONetworkMedium entries that represent
2244: // the entire media selection supported by the hardware. This method
2245: // will make a copy of the provided dictionary, then add the copy to
2246: // the driver's property table. The dictionary provided can be
2247: // released after this call returns. It is permissible to call
2248: // this method multiple times, which may be necessary if the hardware's
2249: // media capability changes dynamically. However, if this were not
2250: // so, then drivers will typically call this method from its start()
2251: // implementation, after the hardware capability is discovered.
2252: //
2253: // Several methods depend on the presence of a medium dictionary.
2254: // They should be called after the dictionary has been published.
2255: // Those are:
2256: // selectMedium()
2257: // setCurrentMedium()
2258: // getCurrentMedium()
2259: // getMediumDictionary()
2260: // copyMediumDictionary()
2261: //
2262: // Calling publishMediumDictionary() will cause a media change event
2263: // to be delivered to all attached interface clients.
2264: //
2265: // Returns true if the dictionary is valid, and was successfully
2266: // added to the property table, false otherwise.
2267:
2268: bool
2269: IONetworkController::publishMediumDictionary(const OSDictionary * mediumDict)
2270: {
2271: OSDictionary * cloneDict;
2272: bool ret = false;
2273:
2274: if (!verifyMediumDictionary(mediumDict))
2275: return false; // invalid dictionary
2276:
2277: // Create a clone of the source dictionary. This prevents the driver
2278: // from adding/removing entries after the medium dictionary is added
2279: // to the property table.
2280: //
2281: cloneDict = OSDictionary::withDictionary(mediumDict,
2282: mediumDict->getCount());
2283: if (!cloneDict)
2284: return false; // unable to create a copy
2285:
2286: MEDIUM_LOCK;
2287:
2288: // Add the dictionary to the property table.
2289: //
2290: if (setProperty(kIOMediumDictionary, cloneDict))
2291: {
2292: const OSSymbol * mediumName;
2293: IONetworkMedium * medium;
2294:
2295: mediumName = (OSSymbol *) getProperty(gIOCurrentMediumKey);
2296: medium = mediumName ?
2297: (IONetworkMedium *) cloneDict->getObject(mediumName) : 0;
2298: setMediumProperty(gIOCurrentMediumKey, medium, &_currentMedium, true);
2299:
2300: mediumName = (OSSymbol *) getProperty(gIOActiveMediumKey);
2301: medium = mediumName ?
2302: (IONetworkMedium *) cloneDict->getObject(mediumName) : 0;
2303: setMediumProperty(gIOActiveMediumKey, medium, &_activeMedium, true);
2304:
2305: ret = true;
2306: }
2307:
2308: MEDIUM_UNLOCK;
2309:
2310: // Retained by the property table. drop our retain count.
2311: //
2312: cloneDict->release();
2313:
2314: // Broadcast a medium change event.
2315: //
2316: broadcastEvent(kIONetworkEventMediumChange);
2317:
2318: return ret;
2319: }
2320:
2321: //---------------------------------------------------------------------------
2322: // Call enablePacketFilters() through syncRequest(). See enablePacketFilters().
2323:
2324: IOReturn IONetworkController::doEnablePacketFilters(IOService * client,
2325: UInt32 newFilters,
2326: UInt32 * activeFiltersP)
2327: {
2328: IOReturn ret = kIOReturnNotReady;
2329: UInt32 dummy;
2330: UInt32 * activeP = activeFiltersP ? activeFiltersP : &dummy;
2331:
2332: *activeP = 0;
2333:
2334: if (SYNC_REQ(client, &IONetworkController::enablePacketFilters,
2335: &ret,
2336: (void *) newFilters, (void *) activeP) == kIOReturnSuccess)
2337: {
2338: // Update the registry.
2339: //
2340: setProperty(kIOActivePacketFilters, *activeP, 32);
2341: }
2342:
2343: return ret;
2344: }
2345:
2346: //---------------------------------------------------------------------------
2347: // Calls getPacketFilters() through syncRequest(). See getPacketFilters().
2348:
2349: IOReturn IONetworkController::doGetPacketFilters(IOService * client,
2350: UInt32 * filtersP)
2351: {
2352: DO_SYNC_REQ(getPacketFilters, (void *) filtersP)
2353: }
2354:
2355: //---------------------------------------------------------------------------
2356: // Call enable(IOService *) through syncRequest(). See enable().
2357:
2358: IOReturn IONetworkController:: doEnable(IOService * client)
2359: {
2360: DO_SYNC_REQ(_enable, (void *) client)
2361: }
2362:
2363: //---------------------------------------------------------------------------
2364: // Call disable(IOService *) through syncRequest(). See disable().
2365:
2366: IOReturn IONetworkController:: doDisable(IOService * client)
2367: {
2368: DO_SYNC_REQ(_disable, (void *) client)
2369: }
2370:
2371: //---------------------------------------------------------------------------
2372: // Call getControllerIndex() through syncRequest(). See getControllerIndex().
2373:
2374: IOReturn IONetworkController::doGetControllerIndex(IOService * client,
2375: UInt32 * index)
2376: {
2377: DO_SYNC_REQ(getControllerIndex, (void *) index)
2378: }
2379:
2380: //---------------------------------------------------------------------------
2381: // Call setMaxTransferUnit() through syncRequest(). See setMaxTransferUnit().
2382:
2383: IOReturn IONetworkController::doSetMaxTransferUnit(IOService * client,
2384: UInt32 mtu)
2385: {
2386: DO_SYNC_REQ(setMaxTransferUnit, (void *) mtu)
2387: }
2388:
2389: //---------------------------------------------------------------------------
2390: // Call selectMedium() through syncRequest(). See selectMedium().
2391:
2392: IOReturn IONetworkController::doSelectMedium(IOService * client,
2393: const OSSymbol * mediumName)
2394: {
2395: DO_SYNC_REQ(selectMediumWithName, (void *) mediumName)
2396: }
2397:
2398: //---------------------------------------------------------------------------
2399: // Call setOutputQueueCapacity() through syncRequest().
2400: // See setOutputQueueCapacity().
2401:
2402: IOReturn IONetworkController::doSetOutputQueueCapacity(IOService * client,
2403: UInt32 capacity)
2404: {
2405: DO_SYNC_REQ(setOutputQueueCapacity, (void *) capacity)
2406: }
2407:
2408: //---------------------------------------------------------------------------
2409: // Call getOutputQueueCapacity() through syncRequest().
2410: // See getOutputQueueCapacity().
2411:
2412: IOReturn
2413: IONetworkController::doGetOutputQueueCapacity(IOService * client,
2414: UInt32 * capacityP)
2415: {
2416: DO_SYNC_REQ(getOutputQueueCapacity, (void *) capacityP)
2417: }
2418:
2419: //---------------------------------------------------------------------------
2420: // Call getOutputQueueSize() through syncRequest().
2421: // See getOutputQueueSize().
2422:
2423: IOReturn
2424: IONetworkController::doGetOutputQueueSize(IOService * client,
2425: UInt32 * sizeP)
2426: {
2427: DO_SYNC_REQ(getOutputQueueSize, (void *) sizeP)
2428: }
2429:
2430: //---------------------------------------------------------------------------
2431: // Call flushOutputQueue() through syncRequest(). See flushOutputQueue().
2432:
2433: IOReturn
2434: IONetworkController::doFlushOutputQueue(IOService * client,
2435: UInt32 * flushCountP)
2436: {
2437: DO_SYNC_REQ(flushOutputQueue, (void *) flushCountP)
2438: }
2439:
2440: //---------------------------------------------------------------------------
2441: // Call performDiagnostics() through syncRequest().
2442: // See performDiagnostics().
2443:
2444: IOReturn
2445: IONetworkController::doPerformDiagnostics(IOService * client,
2446: UInt32 * failureCode)
2447: {
2448: DO_SYNC_REQ(performDiagnostics, (void *) failureCode)
2449: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.