1/*
2 * Copyright (c) 1998-2008 Apple 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 * IONetworkController.cpp
24 *
25 * HISTORY
26 * 9-Dec-1998       Joe Liu (jliu) created.
27 *
28 */
29
30#include <IOKit/assert.h>
31#include <IOKit/IOCommandGate.h>
32#include <IOKit/network/IONetworkController.h>
33#include <IOKit/network/IOEthernetController.h>
34#include <IOKit/network/IOOutputQueue.h>
35#include <IOKit/network/IONetworkMedium.h>
36#include <IOKit/IOMessage.h>
37#include "IONetworkControllerPrivate.h"
38#include "IONetworkDebug.h"
39
40// IONetworkController (and its subclasses) needs to know about mbufs,
41// but it shall have no further dependencies on BSD networking.
42//
43extern "C" {
44#include <sys/param.h>  // mbuf limits defined here.
45#include <sys/mbuf.h>
46#include <sys/kdebug.h>
47#include <machine/machine_routines.h>
48}
49
50#ifndef kIOMessageDeviceSignaledWakeup
51#define kIOMessageDeviceSignaledWakeup  iokit_common_msg(0x350)
52#endif
53
54//-------------------------------------------------------------------------
55// Macros.
56
57#define super IOService
58
59OSDefineMetaClassAndAbstractStructors( IONetworkController, IOService )
60OSMetaClassDefineReservedUsed( IONetworkController,  0); // getDebuggerLinkStatus
61OSMetaClassDefineReservedUsed( IONetworkController,  1); // setDebuggerMode
62OSMetaClassDefineReservedUsed( IONetworkController,  2); // outputStart
63OSMetaClassDefineReservedUsed( IONetworkController,  3); // setInputPacketPollingEnable
64OSMetaClassDefineReservedUsed( IONetworkController,  4); // pollInputPackets
65OSMetaClassDefineReservedUsed( IONetworkController,  5); // networkInterfaceNotification
66OSMetaClassDefineReservedUnused( IONetworkController,  6);
67OSMetaClassDefineReservedUnused( IONetworkController,  7);
68OSMetaClassDefineReservedUnused( IONetworkController,  8);
69OSMetaClassDefineReservedUnused( IONetworkController,  9);
70OSMetaClassDefineReservedUnused( IONetworkController, 10);
71OSMetaClassDefineReservedUnused( IONetworkController, 11);
72OSMetaClassDefineReservedUnused( IONetworkController, 12);
73OSMetaClassDefineReservedUnused( IONetworkController, 13);
74OSMetaClassDefineReservedUnused( IONetworkController, 14);
75OSMetaClassDefineReservedUnused( IONetworkController, 15);
76OSMetaClassDefineReservedUnused( IONetworkController, 16);
77OSMetaClassDefineReservedUnused( IONetworkController, 17);
78OSMetaClassDefineReservedUnused( IONetworkController, 18);
79OSMetaClassDefineReservedUnused( IONetworkController, 19);
80OSMetaClassDefineReservedUnused( IONetworkController, 20);
81OSMetaClassDefineReservedUnused( IONetworkController, 21);
82OSMetaClassDefineReservedUnused( IONetworkController, 22);
83OSMetaClassDefineReservedUnused( IONetworkController, 23);
84OSMetaClassDefineReservedUnused( IONetworkController, 24);
85OSMetaClassDefineReservedUnused( IONetworkController, 25);
86OSMetaClassDefineReservedUnused( IONetworkController, 26);
87OSMetaClassDefineReservedUnused( IONetworkController, 27);
88OSMetaClassDefineReservedUnused( IONetworkController, 28);
89OSMetaClassDefineReservedUnused( IONetworkController, 29);
90OSMetaClassDefineReservedUnused( IONetworkController, 30);
91OSMetaClassDefineReservedUnused( IONetworkController, 31);
92
93static bool isPowerOfTwo(UInt32 num)
94{
95    return (num == (num & ~(num - 1)));
96}
97
98#define MEDIUM_LOCK     IOTakeLock(_mediumLock);
99#define MEDIUM_UNLOCK   IOUnlock(_mediumLock);
100
101#define RELEASE(x) do { if (x) { (x)->release(); (x) = 0; } } while (0)
102
103// OSSymbols for frequently used keys.
104//
105static const OSSymbol * gIOActiveMediumKey;
106static const OSSymbol * gIOCurrentMediumKey;
107static const OSSymbol * gIODefaultMediumKey;
108static const OSSymbol * gIONullMediumName;
109static const OSSymbol * gIOLinkDataKey;
110static const OSSymbol * gIOControllerEnabledKey;
111static const OSData   * gIONullLinkData;
112
113// Global symbols.
114//
115const OSSymbol * gIONetworkFilterGroup;
116const OSSymbol * gIOEthernetWakeOnLANFilterGroup;
117const OSSymbol * gIOEthernetDisabledWakeOnLANFilterGroup;
118uint32_t         gIONetworkDebugFlags = 0;
119
120// Constants for handleCommand().
121//
122enum {
123    kCommandEnable       = 1,
124    kCommandDisable      = 2,
125    kCommandPrepare      = 3,
126    kCommandInitDebugger = 4
127};
128
129class IONetworkControllerGlobals
130{
131public:
132    IONetworkControllerGlobals();
133    ~IONetworkControllerGlobals();
134
135    inline bool isValid() const;
136};
137
138static IONetworkControllerGlobals gIONetworkControllerGlobals;
139
140IONetworkControllerGlobals::IONetworkControllerGlobals()
141{
142    gIOActiveMediumKey  = OSSymbol::withCStringNoCopy(kIOActiveMedium);
143    gIOCurrentMediumKey = OSSymbol::withCStringNoCopy(kIOSelectedMedium);
144    gIODefaultMediumKey = OSSymbol::withCStringNoCopy(kIODefaultMedium);
145    gIONullMediumName   = OSSymbol::withCStringNoCopy("");
146    gIOLinkDataKey      = OSSymbol::withCStringNoCopy(kIOLinkData);
147    gIONullLinkData     = OSData::withCapacity(0);
148
149    gIONetworkFilterGroup =
150        OSSymbol::withCStringNoCopy(kIONetworkFilterGroup);
151
152    gIOEthernetWakeOnLANFilterGroup =
153        OSSymbol::withCStringNoCopy(kIOEthernetWakeOnLANFilterGroup);
154
155    gIOEthernetDisabledWakeOnLANFilterGroup =
156        OSSymbol::withCStringNoCopy(kIOEthernetDisabledWakeOnLANFilterGroup);
157
158    gIOControllerEnabledKey =
159        OSSymbol::withCStringNoCopy("IOControllerEnabled");
160
161    uint32_t flags;
162    if (PE_parse_boot_argn("ionetwork_debug", &flags, sizeof(flags)))
163        gIONetworkDebugFlags |= flags;
164}
165
166IONetworkControllerGlobals::~IONetworkControllerGlobals()
167{
168    RELEASE( gIOActiveMediumKey );
169    RELEASE( gIOCurrentMediumKey );
170    RELEASE( gIODefaultMediumKey );
171    RELEASE( gIONullMediumName );
172    RELEASE( gIOLinkDataKey );
173    RELEASE( gIONullLinkData );
174    RELEASE( gIONetworkFilterGroup );
175    RELEASE( gIOEthernetWakeOnLANFilterGroup );
176    RELEASE( gIOEthernetDisabledWakeOnLANFilterGroup );
177    RELEASE( gIOControllerEnabledKey );
178}
179
180bool IONetworkControllerGlobals::isValid() const
181{
182    return ( gIOActiveMediumKey    &&
183             gIOCurrentMediumKey   &&
184             gIODefaultMediumKey   &&
185             gIONullMediumName     &&
186             gIOLinkDataKey        &&
187             gIONullLinkData       &&
188             gIONetworkFilterGroup &&
189             gIOEthernetWakeOnLANFilterGroup &&
190             gIOEthernetDisabledWakeOnLANFilterGroup &&
191             gIOControllerEnabledKey );
192}
193
194//---------------------------------------------------------------------------
195// Initialize the IONetworkController instance. Instance variables are
196// set to their default values, then super::init() is called.
197//
198// properties: A dictionary object containing a property table
199//             associated with this instance.
200//
201// Returns true on success, false otherwise.
202
203bool IONetworkController::init(OSDictionary * properties)
204{
205    // Initialize instance variables.
206    //
207    _workLoop               = 0;
208    _cmdGate                = 0;
209    _outputQueue            = 0;
210    _clientSet              = 0;
211    _clientSetIter          = 0;
212    _cmdClient              = 0;
213    _propertiesPublished    = false;
214    _mediumLock             = 0;
215    _lastLinkData           = gIONullLinkData;
216    _lastActiveMediumName   = gIONullMediumName;
217    _lastCurrentMediumName  = gIONullMediumName;
218
219    if ( super::init(properties) == false )
220    {
221        DLOG("IONetworkController: super::init() failed\n");
222        return false;
223    }
224
225    if ( gIONetworkControllerGlobals.isValid() == false )
226    {
227        return false;
228    }
229
230    return true;
231}
232
233//-------------------------------------------------------------------------
234// Called after the controller driver was successfully matched to a provider,
235// to start running. IONetworkController will allocate resources and gather
236// controller properties. No I/O will be performed until the subclass
237// attaches a client object from its start() method. Subclasses must override
238// this method and call super::start() at the beginning of its implementation.
239// Then check the return value to make sure the superclass was started
240// successfully before continuing. The resources allocated by
241// IONetworkController include:
242//
243// - An IOCommandGate object to handle client commands.
244// - An OSSet to track our clients.
245// - An optional IOOutputQueue object for output queueing.
246//
247// Tasks that are usually performed by a typical network driver in start
248// include:
249//
250// - Resource allocation
251// - Hardware initialization
252// - Allocation of IOEventSources and attaching them to an IOWorkLoop object.
253// - Publishing a medium dictionary.
254// - And finally, attaching an interface object after the driver is ready
255//   to handle client requests.
256//
257// provider: The provider that the controller was matched
258//           (and attached) to.
259//
260// Returns true on success, false otherwise.
261
262bool IONetworkController::start(IOService * provider)
263{
264    // Most drivers will probably want to wait for BSD due to their
265    // dependency on mbufs, which is not available until BSD is
266    // initialized.
267
268    if ((getFeatures() & kIONetworkFeatureNoBSDWait) == 0)
269        waitForService(resourceMatching( "IOBSD" ));
270
271    // Start our superclass.
272
273    if (!super::start(provider))
274        return false;
275
276    // Create an OSSet to store our clients.
277
278    _clientSet = OSSet::withCapacity(2);
279    if (_clientSet == 0)
280        return false;
281
282    _clientSetIter = OSCollectionIterator::withCollection(_clientSet);
283    if (_clientSetIter == 0)
284        return false;
285
286    // Initialize link status properties.
287
288    if (!setProperty(gIOActiveMediumKey, (OSSymbol *) gIONullMediumName) ||
289	    !setProperty(gIOCurrentMediumKey, (OSSymbol *) gIONullMediumName))
290		return false;
291
292    _linkStatus = OSNumber::withNumber((UInt64) 0, 32);
293    if (!_linkStatus || !setProperty(kIOLinkStatus, _linkStatus))
294    {
295    	return false;
296    }
297
298    _linkSpeed = OSNumber::withNumber((UInt64) 0, 64);
299    if (!_linkSpeed || !setProperty(kIOLinkSpeed, _linkSpeed))
300    {
301    	return false;
302    }
303
304    // Allocate a mutex lock to serialize access to the medium dictionary.
305
306    _mediumLock = IOLockAlloc();
307    if (!_mediumLock)
308        return false;
309    IOLockInitWithState(_mediumLock, kIOLockStateUnlocked);
310
311    // Tell the driver that now is the time to create a work loop
312    // (if it wants one).
313
314    if ( createWorkLoop() != true )
315    {
316        DLOG("%s: createWorkLoop() error\n", getName());
317        return false;
318    }
319
320	// Get the workloop.
321
322    _workLoop = getWorkLoop();
323    if ( _workLoop == 0 )
324    {
325        DLOG("%s: IOWorkLoop allocation failed\n", getName());
326        return false;
327    }
328    _workLoop->retain();
329
330    if (_workLoop != provider->getWorkLoop())
331    {
332        ml_thread_policy( _workLoop->getThread(), MACHINE_GROUP,
333                          (MACHINE_NETWORK_GROUP|MACHINE_NETWORK_WORKLOOP) );
334    }
335
336    // Create a 'private' IOCommandGate object and attach it to
337    // our workloop created above. This is used by executeCommand().
338
339    _cmdGate = IOCommandGate::commandGate(this);
340    if (!_cmdGate ||
341        (_workLoop->addEventSource(_cmdGate) != kIOReturnSuccess))
342    {
343        DLOG("%s: IOCommandGate initialization failed\n", getName());
344        return false;
345    }
346
347    // Try to allocate an IOOutputQueue instance. This is optional and
348    // _outputQueue may be 0.
349
350    _outputQueue = createOutputQueue();
351
352    // Query the controller's mbuf buffer restrictions.
353
354    IOPacketBufferConstraints constraints;
355    getPacketBufferConstraints(&constraints);
356    if ((constraints.alignStart  > kIOPacketBufferAlign32) ||
357        (constraints.alignLength > kIOPacketBufferAlign32) ||
358        !isPowerOfTwo(constraints.alignStart) ||
359        !isPowerOfTwo(constraints.alignLength))
360    {
361        IOLog("%s: Invalid alignment: start:%d, length:%d\n",
362            getName(),
363            (uint32_t) constraints.alignStart,
364            (uint32_t) constraints.alignLength);
365        return false;
366    }
367
368    // Make it easier to satisfy both constraints.
369
370    if (constraints.alignStart < constraints.alignLength)
371        constraints.alignStart = constraints.alignLength;
372
373    // Convert to alignment masks.
374
375    _alignStart  = (constraints.alignStart) ? constraints.alignStart - 1 : 0;
376    _alignLength = (constraints.alignLength) ? constraints.alignLength - 1 : 0;
377    _alignPadding = _alignStart + _alignLength;
378
379    // Called by a policy-maker to initialize itself for power-management.
380    // IONetworkController is the policy-maker.
381
382    PMinit();
383
384    // Called by a policy-maker on its nub, to be attached into the
385    // power management hierarchy.
386
387    provider->joinPMtree(this);
388
389    return true;
390}
391
392//---------------------------------------------------------------------------
393// The opposite of start(). The controller has been instructed to stop running.
394// This method should release resources and undo actions performed by start().
395// Subclasses must override this method and call super::stop() at the end of
396// its implementation.
397//
398// provider: The provider that the controller was matched
399//           (and attached) to.
400
401void IONetworkController::stop(IOService * provider)
402{
403    // Called by a policy-maker to resign its responsibilities as the
404    // policy-maker.
405
406    PMstop();
407
408    super::stop(provider);
409}
410
411//---------------------------------------------------------------------------
412// Power-management hooks for subclasses.
413
414IOReturn IONetworkController::registerWithPolicyMaker(IOService * policyMaker)
415{
416    // An opportunity for subclasses to call
417    // policyMaker->registerPowerDriver(...)
418    // and other future PM requirements.
419    return kIOReturnUnsupported;
420}
421
422//---------------------------------------------------------------------------
423// Catch calls to createWorkLoop() for drivers that choose not implement this
424// method.
425
426bool IONetworkController::createWorkLoop()
427{
428    return true;
429}
430
431//---------------------------------------------------------------------------
432// Get the IOCommandGate object created by IONetworkController.
433// An IOCommandGate is created and attached to the internal workloop by
434// the start() method.
435// This IOCommandGate object is used to handle client commands sent to
436// executeCommand(). Subclasses that need an IOCommandGate should use the
437// object returned by this method, rather than creating
438// a new instance. See IOCommandGate.
439//
440// Returns the IOCommandGate object created by IONetworkController.
441
442IOCommandGate * IONetworkController::getCommandGate() const
443{
444    return _cmdGate;
445}
446
447//---------------------------------------------------------------------------
448// Get the address of the method designated to handle output packets.
449//
450// Returns the address of the outputPacket() method.
451
452IOOutputAction IONetworkController::getOutputHandler() const
453{
454    return (IOOutputAction) &IONetworkController::outputPacket;
455}
456
457//---------------------------------------------------------------------------
458// Create a new interface object and attach it to the controller.
459// The createInterface() method is called to perform the allocation and
460// initialization, followed by a call to configureInterface() to configure
461// the interface. Subclasses can override those methods to customize the
462// interface client attached. Drivers will usually call this method from
463// their start() implementation, after they are ready to process client
464// requests.
465//
466// interfaceP: If successful (return value is true), then the interface
467//             object will be written to the handle provided.
468//
469// doRegister: If true, then registerService() is called to register
470//             the interface, which will trigger the matching process,
471//             and cause the interface to become registered with the network
472//             layer. For drivers that wish to delay the registration, and
473//             hold off servicing requests and data packets from the network
474//             layer, set doRegister to false and call registerService() on
475//             the interface object when the controller becomes ready.
476//             This allows the driver to attach an interface but without
477//             making it available to the rest of the system.
478//
479// Returns true on success, false otherwise.
480
481bool
482IONetworkController::attachInterface(IONetworkInterface ** interfaceP,
483                                     bool  doRegister)
484{
485    IONetworkInterface * netif;
486
487    *interfaceP = 0;
488
489    // We delay some initialization until the first time that
490    // attachInterface() is called by the subclass.
491
492    if (executeCommand(this, &IONetworkController::handleCommand,
493                       this, (void *) kCommandPrepare) != kIOReturnSuccess)
494    {
495        return false;
496    }
497
498    do {
499        // Allocate a concrete subclass of IONetworkInterface
500        // by calling createInterface().
501
502        netif = createInterface();
503        if (!netif)
504            break;
505
506        // Configure the interface instance by calling
507        // configureInterface(), then attach it as our client.
508
509        if ( !configureInterface(netif) || !netif->attach(this) )
510        {
511            netif->release();
512            break;
513        }
514
515        *interfaceP = netif;
516
517        // Register the interface nub. Spawns a matching thread.
518
519        if (doRegister)
520            netif->registerService();
521
522        return true;    // success
523    }
524    while (0);
525
526    return false;   // failure
527}
528
529//---------------------------------------------------------------------------
530// Detach the interface object. This method will check that the object
531// provided is indeed an IONetworkInterface, and if so its terminate()
532// method is called. Note that a registered interface object will close
533// and detach from its controller only after the network layer has removed
534// all references to the data structures exposed by the interface.
535//
536// interface: An interface object to be detached.
537// sync:      If true, the interface is terminated synchronously.
538//            Note that this may cause detachInterface() to block
539//            for an indeterminate of time.
540
541void
542IONetworkController::detachInterface(IONetworkInterface * interface,
543                                     bool                 sync)
544{
545    IOOutputQueue * outQueue = getOutputQueue();
546    IOOptionBits    options  = kIOServiceRequired;
547
548    if (OSDynamicCast(IONetworkInterface, interface) == 0)
549        return;
550
551    if (outQueue)
552    {
553        // Remove output queue stats to allow the queue to safely
554        // go away while interface is detaching.
555        IONetworkData * statsData = outQueue->getStatisticsData();
556        if (statsData)
557        {
558            statsData->setNotificationTarget(0, 0);
559            interface->removeNetworkData(statsData->getKey());
560        }
561    }
562
563    if (sync)
564        options |= kIOServiceSynchronous;
565
566    interface->terminate(options);
567}
568
569//---------------------------------------------------------------------------
570// This method is called by attachInterface() or attachDebuggerClient() on
571// the workloop context, to prepare the controller before attaching the client
572// object. This method will call publishProperties() to publish controller
573// capabilities and properties that may be used by client objects. However,
574// publishProperties() will be called only once, even if prepare() is called
575// multiple times.
576//
577// kIOReturnSuccess on success, or an error code otherwise.
578// Returning an error will cause the client attach to fail.
579
580IOReturn IONetworkController::prepare()
581{
582	IOReturn ret = kIOReturnSuccess;
583
584	if ( _propertiesPublished == false )
585	{
586		if ( publishProperties() == true )
587		{
588            _propertiesPublished = true;
589
590            if (pm_vars != 0)
591            {
592                if ( registerWithPolicyMaker( this ) != kIOReturnSuccess )
593                {
594                    // Detach the policy maker from the PM tree.
595                    // For PCI devices, this will prevent the sleep code in
596                    // platform expert from wrongly assuming that the device
597                    // is power managed.
598
599                    PMstop();
600                }
601            }
602        }
603        else
604        {
605            ret = kIOReturnError;
606        }
607	}
608
609	return ret;
610}
611
612//---------------------------------------------------------------------------
613// Handle a client open on the controller object. IOService calls this method
614// with the arbitration lock held. Subclasses are not expected to override
615// this method.
616//
617//   client: The client that is attempting to open the controller.
618//  options: See IOService.
619// argument: See IOService.
620//
621// Returns true to accept the client open, false to refuse it.
622
623bool IONetworkController::handleOpen(IOService *  client,
624                                     IOOptionBits options,
625                                     void *       argument)
626{
627    assert(client);
628    return _clientSet->setObject(client);
629}
630
631//---------------------------------------------------------------------------
632// Handle a close from one of the client objects. IOService calls this method
633// with the arbitration lock held. Subclasses are not expected to override this
634// method.
635//
636//  client: The client that is closing the controller.
637// options: See IOService.
638
639void IONetworkController::handleClose(IOService * client, IOOptionBits options)
640{
641    _clientSet->removeObject(client);
642}
643
644//---------------------------------------------------------------------------
645// This method is always called by IOService with the arbitration lock held.
646// Subclasses should not override this method.
647//
648// Returns true if the specified client, or any client if none is
649// specified, presently has an open on this object.
650
651bool IONetworkController::handleIsOpen(const IOService * client) const
652{
653    if (client)
654        return _clientSet->containsObject(client);
655    else
656        return (_clientSet->getCount() > 0);
657}
658
659//---------------------------------------------------------------------------
660// Free the IONetworkController instance by releasing all allocated resources,
661// then call super::free().
662
663void IONetworkController::free()
664{
665    // We should have no clients at this point. If we do,
666    // then something is very wrong! It means that a client
667    // has an open on us, and yet we are being freed.
668
669    if (_clientSet) assert(_clientSet->getCount() == 0);
670
671    RELEASE( _outputQueue   );
672    if( _cmdGate )
673	{
674		if(_workLoop) _workLoop->removeEventSource(_cmdGate);
675		_cmdGate->release();
676		_cmdGate = 0;
677	}
678    RELEASE( _workLoop      );
679    RELEASE( _clientSetIter );
680    RELEASE( _clientSet     );
681    RELEASE( _linkStatus    );
682    RELEASE( _linkSpeed     );
683
684    if (_mediumLock) { IOLockFree(_mediumLock); _mediumLock = 0; }
685
686    super::free();
687}
688
689//---------------------------------------------------------------------------
690// Handle an enable request from a client.
691
692IOReturn IONetworkController::enable(IOService * client)
693{
694    if (OSDynamicCast(IONetworkInterface, client))
695        return enable((IONetworkInterface *) client);
696
697    if (OSDynamicCast(IOKernelDebugger, client))
698        return enable((IOKernelDebugger *) client);
699
700    IOLog("%s::%s Unknown client type\n", getName(), __FUNCTION__);
701    return kIOReturnBadArgument;
702}
703
704//---------------------------------------------------------------------------
705// Handle a disable request from a client.
706
707IOReturn IONetworkController::disable(IOService * client)
708{
709    if (OSDynamicCast(IONetworkInterface, client))
710        return disable((IONetworkInterface *) client);
711
712    if (OSDynamicCast(IOKernelDebugger, client))
713        return disable((IOKernelDebugger *) client);
714
715    IOLog("%s::%s Unknown client type\n", getName(), __FUNCTION__);
716    return kIOReturnBadArgument;
717}
718
719//---------------------------------------------------------------------------
720// Called by an interface client to enable the controller.
721
722IOReturn IONetworkController::enable(IONetworkInterface * interface)
723{
724    IOLog("IONetworkController::%s\n", __FUNCTION__);
725    return kIOReturnUnsupported;
726}
727
728//---------------------------------------------------------------------------
729// Called by an interface client to disable the controller.
730
731IOReturn IONetworkController::disable(IONetworkInterface * interface)
732{
733    IOLog("IONetworkController::%s\n", __FUNCTION__);
734    return kIOReturnUnsupported;
735}
736
737//---------------------------------------------------------------------------
738// Discover and publish controller capabilities to the property table.
739// This method is called by prepare() on the workloop context.
740//
741// Returns true if all capabilities were discovered and published
742// successfully, false otherwise. Returning false will prevent client
743// objects from attaching to the controller since a vital property that
744// a client requires may be missing.
745
746bool IONetworkController::publishProperties()
747{
748    bool              ret = false;
749    const OSString *  string;
750    UInt32            num;
751    OSDictionary *    dict = 0;
752    OSNumber *        numObj = 0;
753
754    do {
755        bool status;
756
757        string = newVendorString();
758        if (string) {
759            status = setProperty(kIOVendor, (OSObject *) string);
760            string->release();
761            if (status != true) break;
762        }
763
764        string = newModelString();
765        if (string) {
766            status = setProperty(kIOModel, (OSObject *) string);
767            string->release();
768            if (status != true) break;
769        }
770
771        string = newRevisionString();
772        if (string) {
773            status = setProperty(kIORevision, (OSObject *) string);
774            string->release();
775            if (status != true) break;
776        }
777
778        // Publish controller feature flags.
779
780        num = getFeatures();
781        if ( !setProperty(kIOFeatures, num, sizeof(num) * 8) )
782            break;
783
784        // Publish max/min packet size.
785
786        if ( ( getMaxPacketSize(&num) != kIOReturnSuccess ) ||
787             ( !setProperty(kIOMaxPacketSize, num, sizeof(num) * 8) ) )
788            break;
789
790        if ( ( getMinPacketSize(&num) != kIOReturnSuccess ) ||
791             ( !setProperty(kIOMinPacketSize, num, sizeof(num) * 8) ) )
792            break;
793
794        // Publish supported packet filters.
795
796        if (getPacketFilters(gIONetworkFilterGroup, &num) != kIOReturnSuccess)
797            break;
798
799        dict   = OSDictionary::withCapacity(1);
800        numObj = OSNumber::withNumber(num, sizeof(num) * 8);
801        if ( (dict == 0) || (numObj == 0) ) break;
802
803        if ( !dict->setObject(gIONetworkFilterGroup, numObj)  ||
804             !setProperty(kIOPacketFilters, dict) )
805            break;
806
807        ret = true;
808    }
809    while (false);
810
811    if (ret == false) {
812        DLOG("IONetworkController::%s error\n", __FUNCTION__);
813    }
814    if ( dict )   dict->release();
815    if ( numObj ) numObj->release();
816
817    return ret;
818}
819
820//---------------------------------------------------------------------------
821// Send a network event to all attached interface objects.
822
823bool IONetworkController::_broadcastEvent(UInt32 type, void * data)
824{
825    IONetworkInterface * netif;
826
827    lockForArbitration();   // locks open/close/state changes.
828
829    if (_clientSet->getCount())
830    {
831        _clientSetIter->reset();
832
833        while ((netif = (IONetworkInterface *)_clientSetIter->getNextObject()))
834        {
835            if (OSDynamicCast(IONetworkInterface, netif) == 0)
836                continue;   // only send events to IONetworkInterface objects.
837            netif->inputEvent(type, data);
838        }
839    }
840
841    unlockForArbitration();
842
843    return true;
844}
845
846//---------------------------------------------------------------------------
847// A client request for the controller to change to a new MTU size.
848
849IOReturn IONetworkController::setMaxPacketSize(UInt32 maxSize)
850{
851    return kIOReturnUnsupported;
852}
853
854//---------------------------------------------------------------------------
855// Transmit a packet mbuf.
856
857UInt32 IONetworkController::outputPacket(mbuf_t m, void * param)
858{
859    // The implementation here is simply a sink-hole, all packets are
860    // dropped.
861
862    if (m) freePacket(m);
863    return 0;
864}
865
866//---------------------------------------------------------------------------
867// Report features supported by the controller and/or driver.
868
869UInt32 IONetworkController::getFeatures() const
870{
871    return 0;
872}
873
874//---------------------------------------------------------------------------
875// Create default description strings.
876
877const OSString * IONetworkController::newVendorString() const
878{
879    return 0;
880}
881
882const OSString * IONetworkController::newModelString() const
883{
884    return 0;
885}
886
887const OSString * IONetworkController::newRevisionString() const
888{
889    return 0;
890}
891
892//---------------------------------------------------------------------------
893// Encode a client command received by executeCommand().
894
895struct cmdStruct {
896    OSObject *                   client;
897    void *                       target;
898    IONetworkController::Action  action;
899    void *                       param0;
900    void *                       param1;
901    void *                       param2;
902    void *                       param3;
903    IOReturn                     ret;
904};
905
906//---------------------------------------------------------------------------
907// Get the command client object.
908
909OSObject * IONetworkController::getCommandClient() const
910{
911    return ( _workLoop->inGate() ? _cmdClient : 0 );
912}
913
914//---------------------------------------------------------------------------
915// Configure an interface object created through createInterface().
916// IONetworkController will register its output handler with the interface
917// object provided. After the interface is registered and opened by its
918// client, it will refuse requests to change its properties through its
919// public methods. Since this method is called before the interface object
920// is published and registered, subclasses of IONetworkController may override
921// this method to configure and customize the interface object.
922//
923// interface: The interface object to be configured.
924//
925// Returns true if configuration was successful, false otherwise (this
926// will cause attachInterface() to fail).
927
928bool IONetworkController::configureInterface(IONetworkInterface * interface)
929{
930    IOOutputAction  handler;
931    OSObject *      target;
932    bool            ret;
933    IONetworkData * stats;
934
935    if (!OSDynamicCast(IONetworkInterface, interface))
936        return false;
937
938    IOOutputQueue * outQueue = getOutputQueue();
939
940    // Must register an output handler with the interface object.
941    // The interface will send output packets, to its registered
942    // output handler. If we allocated an output queue, then we
943    // register the queue as the output handler, otherwise, we
944    // become the output handler.
945
946    if (outQueue)
947    {
948        target  = outQueue;
949        handler = outQueue->getOutputHandler();
950
951        stats   = outQueue->getStatisticsData();
952        interface->addNetworkData(stats);
953    }
954    else
955    {
956        target  = this;
957        handler = getOutputHandler();
958    }
959    ret = interface->registerOutputHandler(target, handler);
960
961    return ret;
962}
963
964//---------------------------------------------------------------------------
965// Called by start() to create an optional IOOutputQueue instance to handle
966// output queueing. The default implementation will always return 0, hence
967// no output queue will be created. A driver may override this method and
968// return a subclass of IOOutputQueue. IONetworkController will keep a
969// reference to the queue created, and will release the object when
970// IONetworkController is freed. Also see getOutputQueue().
971//
972// Returns a newly allocated and initialized IOOutputQueue instance.
973
974IOOutputQueue * IONetworkController::createOutputQueue()
975{
976    return 0;
977}
978
979//---------------------------------------------------------------------------
980// Return the output queue allocated though createOutputQueue().
981
982IOOutputQueue * IONetworkController::getOutputQueue() const
983{
984    return _outputQueue;
985}
986
987//---------------------------------------------------------------------------
988// Called by start() to obtain the constraints on the memory buffer
989// associated with each mbuf allocated through allocatePacket().
990// Drivers can override this method to specify their buffer constraints
991// imposed by their bus master hardware. Note that outbound packets,
992// those that originate from the network stack, are not subject
993// to the constraints reported here.
994//
995// constraintsP: A pointer to an IOPacketBufferConstraints structure
996//               that that this method is expected to initialize.
997//               See IOPacketBufferConstraints structure definition.
998
999void IONetworkController::getPacketBufferConstraints(
1000                          IOPacketBufferConstraints * constraintsP) const
1001{
1002    assert(constraintsP);
1003    constraintsP->alignStart  = kIOPacketBufferAlign1;
1004    constraintsP->alignLength = kIOPacketBufferAlign1;
1005}
1006
1007static mbuf_t getPacket( UInt32 size,
1008                         UInt32 how,
1009                         UInt32 smask,
1010                         UInt32 lmask )
1011{
1012    mbuf_t          packet;
1013	UInt32          reqSize = size + smask + lmask; 	// we over-request so we can fulfill alignment needs.
1014    const uint32_t  minSize = mbuf_get_minclsize();
1015
1016    //as protection from drivers that incorrectly assume they always get a single-mbuf packet
1017    //we force kernel to give us a cluster instead of chained small mbufs.
1018
1019	if ((reqSize > mbuf_get_mhlen()) && (reqSize <= minSize))
1020		reqSize = minSize + 1;
1021
1022	if( 0 == mbuf_allocpacket(how, reqSize, NULL, &packet))
1023	{
1024		mbuf_t m = packet;
1025		mbuf_pkthdr_setlen(packet, size);
1026		//run the chain and apply alignment
1027
1028		while(size && m)
1029		{
1030			uintptr_t alignedStart, originalStart;
1031
1032			originalStart = (uintptr_t)mbuf_data(m);
1033			alignedStart = (originalStart + smask) & ~((uintptr_t)smask);
1034			mbuf_setdata(m,  (caddr_t)alignedStart, (mbuf_maxlen(m) - (alignedStart - originalStart)) & ~lmask);
1035
1036			if(mbuf_len(m) > size)
1037				mbuf_setlen(m, size); //truncate to remaining portion of packet
1038
1039			size -= mbuf_len(m);
1040			m = mbuf_next(m);
1041		}
1042		return packet;
1043	}
1044	else
1045		return NULL;
1046}
1047
1048mbuf_t IONetworkController::allocatePacket( UInt32 size )
1049{
1050    return getPacket( size, MBUF_WAITOK, _alignStart, _alignLength );
1051}
1052
1053//---------------------------------------------------------------------------
1054// Release the mbuf back to the free pool.
1055
1056void IONetworkController::freePacket(mbuf_t m, IOOptionBits options)
1057{
1058    assert(m);
1059
1060    if ( options & kDelayFree )
1061    {
1062        mbuf_setnextpkt(m, _freeList);
1063        _freeList = m;
1064    }
1065    else
1066    {
1067        mbuf_freem_list(m);
1068    }
1069}
1070
1071UInt32 IONetworkController::releaseFreePackets()
1072{
1073    UInt32 count = 0;
1074
1075	count =	mbuf_freem_list( _freeList );
1076	_freeList = 0;
1077    return count;
1078}
1079
1080static inline bool IO_COPY_MBUF(
1081    mbuf_t src,
1082    mbuf_t       dst,
1083    int                 length)
1084{
1085    caddr_t src_dat, dst_dat;
1086    int dst_len, src_len;
1087
1088    assert(src && dst);
1089
1090	// dupe the header to pick up internal things like csums and vlan tags
1091	mbuf_copy_pkthdr(dst, src);
1092	mbuf_pkthdr_setheader(dst, NULL); //otherwise it could be pointing into src's data
1093
1094    dst_len = mbuf_len(dst);
1095    dst_dat = (caddr_t)mbuf_data(dst);
1096
1097    while (src) {
1098
1099        src_len = mbuf_len( src );
1100        src_dat = (caddr_t)mbuf_data( src );
1101
1102        if (src_len > length)
1103            src_len = length;
1104
1105        while (src_len) {
1106
1107            if (dst_len >= src_len) {
1108                // copy entire src mbuf to dst mbuf.
1109
1110                bcopy(src_dat, dst_dat, src_len);
1111                length -= src_len;
1112                dst_len -= src_len;
1113                dst_dat += src_len;
1114                src_len = 0;
1115            }
1116            else {
1117                // fill up dst mbuf with some portion of the data in
1118                // the src mbuf.
1119
1120                bcopy(src_dat, dst_dat, dst_len);       // dst_len = 0?
1121                length -= dst_len;
1122                dst_len = 0;
1123                src_len -= dst_len;
1124            }
1125
1126            // Go to the next destination mbuf segment.
1127
1128            if (dst_len == 0) {
1129                if (!(dst = mbuf_next(dst)))
1130                    return (length == 0);
1131                dst_len = mbuf_len(dst);
1132                dst_dat = (caddr_t)mbuf_data(dst);
1133            }
1134
1135        } /* while (src_len) */
1136
1137        src = mbuf_next(src);
1138
1139    } /* while (src) */
1140    return (length == 0);   // returns true on success.
1141}
1142
1143//---------------------------------------------------------------------------
1144// Replace the mbuf pointed by the given pointer with another mbuf.
1145// Drivers can call this method to replace a mbuf before passing the
1146// original mbuf, which contains a received frame, to the network layer.
1147//
1148// mp:   A pointer to the original mbuf that shall be updated by this
1149//       method to point to the new mbuf.
1150// size: If size is 0, then the new mbuf shall have the same size
1151//       as the original mbuf that is being replaced. Otherwise, the new
1152//       mbuf shall have the size specified here.
1153//
1154// If mbuf allocation was successful, then the replacement will
1155// take place and the original mbuf will be returned. Otherwise,
1156// a NULL is returned.
1157
1158mbuf_t IONetworkController::replacePacket(mbuf_t * mp,
1159                                                 UInt32 size)
1160{
1161    assert((mp != NULL) && (*mp != NULL));
1162
1163    mbuf_t  m = *mp;
1164
1165    // If size is zero, then size is taken from the source mbuf.
1166
1167    if (size == 0) size = mbuf_pkthdr_len(m);
1168
1169    // Allocate a new packet to replace the current packet.
1170
1171    if ( (*mp = getPacket(size, MBUF_DONTWAIT, _alignStart, _alignLength)) == 0 )
1172    {
1173        *mp = m; m = 0;
1174    }
1175
1176    return m;
1177}
1178
1179//---------------------------------------------------------------------------
1180// Make a copy of a mbuf, and return the copy. The source mbuf is not modified.
1181//
1182// m:    The source mbuf.
1183// size: The number of bytes to copy. If set to 0, then the entire
1184//       source mbuf is copied.
1185//
1186// Returns a new mbuf created from the source packet.
1187
1188mbuf_t IONetworkController::copyPacket(mbuf_t m,
1189                                              UInt32 size)
1190{
1191	mbuf_t mn;
1192
1193    assert(m != NULL);
1194
1195    // If size is zero, then size is taken from the source mbuf.
1196
1197    if (size == 0) size = mbuf_pkthdr_len(m);
1198
1199    // Copy the current mbuf to the new mbuf, and return the new mbuf.
1200    // The input mbuf is left intact.
1201
1202    if ( (mn = getPacket(size, MBUF_DONTWAIT, _alignStart, _alignLength)) == 0 )
1203        return 0;
1204
1205    if (!IO_COPY_MBUF(m, mn, size))
1206    {
1207        freePacket(mn); mn = 0;
1208    }
1209
1210    return mn;
1211}
1212
1213//---------------------------------------------------------------------------
1214// Either replace or copy the source mbuf given depending on the amount of
1215// data in the source mbuf. This method will either perform a copy or replace
1216// the source mbuf, whichever is more time efficient. If replaced, then the
1217// original mbuf is returned, and a new mbuf is allocated to take its place.
1218// If copied, the source mbuf is left intact, while a copy is returned that
1219// is just big enough to hold all the data from the source mbuf.
1220//
1221// mp:        A pointer to the source mbuf that may be updated by this
1222//            method to point to the new mbuf if replaced.
1223// rcvlen:    The number of data bytes in the source mbuf.
1224// replacedP: Pointer to a bool that is set to true if the
1225//            source mbuf was replaced, or set to false if the
1226//            source mbuf was copied.
1227//
1228// Returns a replacement or a copy of the source mbuf, 0 if mbuf
1229// allocation failed.
1230
1231mbuf_t IONetworkController::replaceOrCopyPacket(mbuf_t *mp,
1232                                                       UInt32 rcvlen,
1233                                                       bool * replacedP)
1234{
1235    mbuf_t m;
1236
1237    assert((mp != NULL) && (*mp != NULL));
1238
1239    if ( (rcvlen + _alignPadding) > mbuf_get_mhlen() )
1240    {
1241        // Large packet, it is more efficient to allocate a new mbuf
1242        // to replace the original mbuf than to make a copy. The new
1243        // packet shall have exactly the same size as the original
1244        // mbuf being replaced.
1245
1246        m = *mp;
1247
1248        if ( (*mp = getPacket( mbuf_pkthdr_len(m), MBUF_DONTWAIT,
1249                               _alignStart, _alignLength)) == 0 )
1250        {
1251            *mp = m; m = 0;  // error recovery
1252        }
1253
1254        *replacedP = true;
1255    }
1256    else
1257    {
1258        // The copy will fit within a header mbuf. Fine, make a copy
1259        // of the original mbuf instead of replacing it. We only copy
1260        // the rcvlen bytes, not the entire source mbuf.
1261
1262        if ( (m = getPacket( rcvlen, MBUF_DONTWAIT,
1263                             _alignStart, _alignLength )) == 0 ) return 0;
1264
1265        if (!IO_COPY_MBUF(*mp, m, rcvlen))
1266        {
1267            freePacket(m); m = 0;
1268        }
1269
1270        *replacedP = false;
1271    }
1272
1273    return m;
1274}
1275
1276//---------------------------------------------------------------------------
1277// Get hardware support of network/transport layer checksums.
1278
1279IOReturn
1280IONetworkController::getChecksumSupport( UInt32 * checksumMask,
1281                                         UInt32   checksumFamily,
1282                                         bool     isOutput )
1283{
1284    return kIOReturnUnsupported;
1285}
1286
1287//---------------------------------------------------------------------------
1288// Update a mbuf with the result from the hardware checksum engine.
1289
1290#define kTransportLayerPartialChecksums \
1291        ( kChecksumTCPNoPseudoHeader |  \
1292          kChecksumUDPNoPseudoHeader |  \
1293          kChecksumTCPSum16 )
1294
1295#define kTransportLayerFullChecksums    \
1296        ( kChecksumTCP | kChecksumUDP | kChecksumTCPIPv6 | kChecksumUDPIPv6 )
1297
1298//PWC add kpi version when 3731343 is ready
1299void
1300IONetworkController::getChecksumDemand( const mbuf_t mt,
1301                                        UInt32              checksumFamily,
1302                                        UInt32 *            demandMask,
1303                                        void *              param0,
1304                                        void *              param1 )
1305{
1306    mbuf_csum_request_flags_t request;
1307	u_int32_t value;
1308
1309	*demandMask = 0;
1310
1311
1312	if ( checksumFamily != kChecksumFamilyTCPIP )
1313    {
1314        return;
1315    }
1316
1317	mbuf_get_csum_requested(mt, &request, &value);
1318
1319	// In theory we should be converting bits here from BSD->IOKit, however
1320	// the IONetworkingFamily definitions of checksum bits are the same as BSD's but do not
1321	// have to be.  Previously the family used them interchangeably, although it was not
1322	// technically correct to do so.  Now with KPIs it seems pretty safe to do it since the
1323	// bits have been defined as part of the KPI and can't change- but it's still not
1324	// "correct". (but it avoids a bunch of conversion logic)
1325
1326    *demandMask = request & ( kChecksumIP       |
1327							  kChecksumTCP      |
1328							  kChecksumUDP      |
1329							  kChecksumTCPSum16 |
1330                              kChecksumTCPIPv6  |
1331                              kChecksumUDPIPv6 );
1332
1333    if ( request & kChecksumTCPSum16 )
1334    {
1335        // param0 is start offset  (XXX - range?)
1336        // param1 is stuff offset  (XXX - range?)
1337
1338        if (param0)
1339            *((UInt16 *) param0) = (UInt16) (value);
1340        if (param1)
1341            *((UInt16 *) param1) = (UInt16) (value >> 16);
1342    }
1343}
1344
1345bool
1346IONetworkController::setChecksumResult( mbuf_t mt,
1347                                        UInt32        family,
1348                                        UInt32        result,
1349                                        UInt32        valid,
1350                                        UInt32        param0,
1351                                        UInt32        param1 )
1352{
1353    mbuf_csum_performed_flags_t performed;
1354	u_int32_t value;
1355	// Reporting something that is valid without checking for it
1356    // is forbidden.
1357    valid &= result;
1358
1359    // Initialize checksum result fields in the packet.
1360
1361	performed = value = 0;
1362
1363    if ( family != kChecksumFamilyTCPIP )
1364    {
1365        return false;
1366    }
1367
1368    // Set the result for the network layer (IP) checksum.
1369
1370    if ( result & kChecksumIP )
1371    {
1372        performed |= MBUF_CSUM_DID_IP;
1373        if ( valid & kChecksumIP )
1374            performed |= MBUF_CSUM_IP_GOOD;
1375    }
1376
1377    // Now examine the transport layer checksum flags.
1378
1379	if ( valid & kTransportLayerFullChecksums )
1380	{
1381        // Excellent, hardware did account for the pseudo-header
1382        // and no "partial" checksum value is required.
1383
1384		performed |= ( MBUF_CSUM_DID_DATA | MBUF_CSUM_PSEUDO_HDR );
1385        value = 0xffff; // fake a valid checksum value
1386	}
1387	else if ( result & kTransportLayerPartialChecksums )
1388    {
1389        // Hardware does not account for the pseudo-header.
1390        // Driver must pass up the partial TCP/UDP checksum,
1391        // and the transport layer must adjust for the missing
1392        // 12-byte pseudo-header.
1393
1394        performed |= MBUF_CSUM_DID_DATA;
1395        value   = (UInt16) param0;
1396
1397        if ( result & kChecksumTCPSum16 )
1398        {
1399            // A very simple engine that only computes a ones complement
1400            // sum of 16-bit words (UDP/TCP style checksum), from a fixed
1401            // offset, without the ability to scan for the IP or UDP/TCP
1402            // headers. Must pass up the offset to the packet data where
1403            // the checksum computation started from.
1404            performed |= MBUF_CSUM_TCP_SUM16;
1405			value  |= (((UInt16) param1) << 16);
1406        }
1407    }
1408	mbuf_set_csum_performed(mt, performed, value);
1409    return true;
1410}
1411
1412#if 0
1413//---------------------------------------------------------------------------
1414// Used for debugging only. Log the mbuf fields.
1415
1416static void _logMbuf(struct mbuf * m)
1417{
1418    if (!m) {
1419        IOLog("logMbuf: NULL mbuf\n");
1420        return;
1421    }
1422
1423    while (m) {
1424        IOLog("m_next   : %08x\n", (UInt) m->m_next);
1425        IOLog("m_nextpkt: %08x\n", (UInt) m->m_nextpkt);
1426        IOLog("m_len    : %d\n",   (UInt) m->m_len);
1427        IOLog("m_data   : %08x\n", (UInt) m->m_data);
1428        IOLog("m_type   : %08x\n", (UInt) m->m_type);
1429        IOLog("m_flags  : %08x\n", (UInt) m->m_flags);
1430
1431        if (m->m_flags & MBUF_PKTHDR)
1432            IOLog("m_pkthdr.len  : %d\n", (UInt) m->m_pkthdr.len);
1433
1434        if (m->m_flags & MBUF_EXT) {
1435            IOLog("m_ext.ext_buf : %08x\n", (UInt) m->m_ext.ext_buf);
1436            IOLog("m_ext.ext_size: %d\n", (UInt) m->m_ext.ext_size);
1437        }
1438
1439        m = m->m_next;
1440    }
1441    IOLog("\n");
1442}
1443#endif /* 0 */
1444
1445//---------------------------------------------------------------------------
1446// Allocate and attach a new IOKernelDebugger client object.
1447//
1448// debuggerP: A handle that is updated by this method
1449//            with the allocated IOKernelDebugger instance.
1450//
1451// Returns true on success, false otherwise.
1452
1453bool IONetworkController::attachDebuggerClient(IOKernelDebugger ** debugger)
1454{
1455    IOKernelDebugger * client;
1456    bool               ret = false;
1457	UInt32 debugArg=0;
1458
1459	// don't attach any debugger if kernel debugging isn't even enabled.
1460	PE_parse_boot_argn( "debug", &debugArg, sizeof (debugArg) );
1461	if(debugArg == 0)
1462	{
1463		*debugger = 0;
1464		return false;
1465	}
1466
1467    // Prepare the controller.
1468
1469    if (executeCommand(this, &IONetworkController::handleCommand,
1470                       this, (void *) kCommandPrepare) != kIOReturnSuccess)
1471    {
1472        return false;
1473    }
1474
1475    // Create a debugger client nub and register the static
1476    // member functions as the polled-mode handlers.
1477
1478    client = IOKernelDebugger::debugger( this,
1479                                         &debugTxHandler,
1480                                         &debugRxHandler,
1481                                         &debugLinkStatusHandler,
1482                                         &debugSetModeHandler);
1483
1484    if ( client && !client->attach(this) )
1485    {
1486        // Unable to attach the client object.
1487        client->terminate( kIOServiceRequired | kIOServiceSynchronous );
1488        client->release();
1489        client = 0;
1490    }
1491
1492    *debugger = client;
1493
1494    if ( client )
1495    {
1496        executeCommand( this, &IONetworkController::handleCommand,
1497                        this, (void *) kCommandInitDebugger,
1498                              (void *) client );
1499
1500        client->registerService();
1501        ret = true;
1502    }
1503
1504    return ret;
1505}
1506
1507//---------------------------------------------------------------------------
1508// Detach and terminate the IOKernelDebugger client object provided.
1509// A synchronous termination is issued, and this method returns after
1510// the debugger client has been terminated.
1511//
1512// debugger: The IOKernelDebugger instance to be detached and terminated.
1513//           If the argument provided is NULL or is not an IOKernelDebugger,
1514//           this method will return immediately.
1515
1516void IONetworkController::detachDebuggerClient(IOKernelDebugger * debugger)
1517{
1518    if (OSDynamicCast(IOKernelDebugger, debugger) == 0)
1519        return;
1520
1521    // Terminate the debugger client and return after the client has
1522    // been terminated.
1523
1524    debugger->terminate(kIOServiceRequired | kIOServiceSynchronous);
1525}
1526
1527//---------------------------------------------------------------------------
1528// An enable request from an IOKernelDebugger client.
1529
1530IOReturn IONetworkController::enable(IOKernelDebugger * debugger)
1531{
1532    return kIOReturnSuccess;
1533}
1534
1535//---------------------------------------------------------------------------
1536// A disable request from an IOKernelDebugger client.
1537
1538IOReturn IONetworkController::disable(IOKernelDebugger * debugger)
1539{
1540    return kIOReturnSuccess;
1541}
1542
1543//---------------------------------------------------------------------------
1544// Take and release the debugger lock.
1545
1546void IONetworkController::reserveDebuggerLock()
1547{
1548    if ( _debugLockCount++ == 0 )
1549    {
1550        _debugLockState = IODebuggerLock( this );
1551    }
1552}
1553
1554void IONetworkController::releaseDebuggerLock()
1555{
1556    if ( --_debugLockCount == 0 )
1557    {
1558        IODebuggerUnlock( _debugLockState );
1559    }
1560    assert( _debugLockCount >= 0 );
1561}
1562
1563//---------------------------------------------------------------------------
1564// This static C++ member function is registered by attachDebuggerClient()
1565// as the debugger receive handler. IOKernelDebugger will call this
1566// function when KDP is polling for a received packet. This function will
1567// in turn will call the receivePacket() member function implemented by
1568// a driver with debugger support.
1569
1570void IONetworkController::debugRxHandler(IOService * handler,
1571                                         void *      buffer,
1572                                         UInt32 *    length,
1573                                         UInt32      timeout)
1574{
1575    ((IONetworkController *) handler)->receivePacket(buffer,
1576                                                     length,
1577                                                     timeout);
1578}
1579
1580//---------------------------------------------------------------------------
1581// This static C++ member function is registered by attachDebuggerClient()
1582// as the debugger transmit handler. IOKernelDebugger will call this
1583// function when KDP sends an outgoing packet. This function will in turn
1584// call the sendPacket() member function implemented by a driver with
1585// debugger support.
1586
1587void IONetworkController::debugTxHandler(IOService * handler,
1588                                         void *      buffer,
1589                                         UInt32      length)
1590{
1591    ((IONetworkController *) handler)->sendPacket(buffer, length);
1592}
1593
1594//---------------------------------------------------------------------------
1595// This static C++ member function is registered by attachDebuggerClient()
1596// as the debugger link status handler. IOKernelDebugger will call this
1597// function to check the link status. This function will in turn
1598// call the getDebuggerLinkStatus() member function implemented by a driver with
1599// debugger support.
1600
1601UInt32 IONetworkController::debugLinkStatusHandler(IOService * handler)
1602{
1603    return ((IONetworkController *) handler)->getDebuggerLinkStatus();
1604}
1605
1606//---------------------------------------------------------------------------
1607// This static C++ member function is registered by
1608// attachDebuggerClient() as the debugger set mode
1609// handler. IOKernelDebugger will call this function to inform the
1610// driver whether or not the debugger is active. This function will in
1611// turn call the setDebuggerMode() member function implemented by a
1612// driver with debugger support.
1613bool IONetworkController::debugSetModeHandler(IOService * handler,
1614                                              bool active)
1615{
1616    return ((IONetworkController *) handler)->setDebuggerMode(active);
1617}
1618
1619//---------------------------------------------------------------------------
1620// This method must be implemented by a driver that supports kernel debugging.
1621// After a debugger client is attached through attachDebuggerClient(), this
1622// method will be called by the debugger client to poll for a incoming packet
1623// when the debugger session is active. This method may be called from the
1624// primary interrupt context, implementation must avoid any memory allocation,
1625// and must never block. The receivePacket() method in IONetworkController is
1626// used as a placeholder and should not be called. A driver that attaches
1627// a debugger client must override this method.
1628//
1629// pkt:     Pointer to a receive buffer where the received packet should
1630//          be stored to. The buffer has enough space for 1518 bytes.
1631// pkt_len: The length of the received packet must be written to the
1632//          integer pointed by pkt_len.
1633// timeout: The maximum amount of time in milliseconds to poll for
1634//          a packet to arrive before this method must return.
1635
1636void IONetworkController::receivePacket(void *   /*pkt*/,
1637                                        UInt32 * /*pkt_len*/,
1638                                        UInt32   /*timeout*/)
1639{
1640    IOLog("IONetworkController::%s()\n", __FUNCTION__);
1641}
1642
1643//---------------------------------------------------------------------------
1644// Debugger polled-mode transmit handler. This method must be implemented
1645// by a driver that supports kernel debugging. After a debugger client is
1646// attached through attachDebuggerClient(), this method will be called by the
1647// debugger to send an outbound packet when the kernel debugger is active.
1648// This method may be called from the primary interrupt context, and the
1649// implementation must avoid any memory allocation, and must never block.
1650// sendPacket() method in IONetworkController is used as a placeholder
1651// and should not be called. A driver that attaches a debugger client
1652// must override this method.
1653//
1654// pkt:     Pointer to a transmit buffer containing the packet to be sent.
1655// pkt_len: The amount of data in the transmit buffer.
1656
1657void IONetworkController::sendPacket(void * /*pkt*/, UInt32 /*pkt_len*/)
1658{
1659    IOLog("IONetworkController::%s()\n", __FUNCTION__);
1660}
1661
1662//---------------------------------------------------------------------------
1663// Debugger polled-mode link status handler. This method must be
1664// implemented by a driver that supports early access kernel
1665// debugging. After a debugger client is attached through
1666// attachDebuggerClient(), this method will be called by the debugger
1667// to determine link status when the kernel debugger is active.  This
1668// method may be called from the primary interrupt context, and the
1669// implementation must avoid any memory allocation, must not spin, and
1670// must never block. getDebuggerLinkStatus() method in IONetworkController
1671// is used as a placeholder. A driver that attaches a debugger client and
1672// wishes to enable early kernel debugging should override this method.
1673//
1674UInt32 IONetworkController::getDebuggerLinkStatus(void)
1675{
1676    return _linkStatus->unsigned32BitValue() | kIONetworkLinkValid | kIONetworkLinkActive;
1677}
1678
1679//---------------------------------------------------------------------------
1680// Debugger polled-mode active/inactive handler. After a debugger
1681// client is attached through attachDebuggerClient(), this method will
1682// be called by the debugger to inform the driver whether or not the
1683// kernel debugger is active.  This method may be called from the
1684// primary interrupt context, and the implementation must avoid any
1685// memory allocation, must not spin, and must never block.  The
1686// setDebuggerMode() method in IONetworkController is used as a
1687// placeholder.  A driver that attaches a debugger client and wishes
1688// to enable/disable features dependent upon being in the kernel
1689// debugger should override this method.
1690//
1691// active: true if entering/in KDP. false if leaving KDP.
1692
1693bool IONetworkController::setDebuggerMode(__unused bool active)
1694{
1695    return true;
1696}
1697
1698//---------------------------------------------------------------------------
1699// Report the link status and the active medium.
1700
1701bool IONetworkController::setLinkStatus(
1702    UInt32                  linkStatus,
1703    const IONetworkMedium * activeMedium,
1704    UInt64                  linkSpeed,
1705    OSData *                linkData )
1706{
1707    bool                    success   = true;
1708    UInt32                  linkEvent = 0;
1709    UInt32                  oldLinkStatus;
1710    const OSSymbol *        linkName  = gIONullMediumName;
1711    IONetworkLinkEventData  linkEventData;
1712
1713    if (linkData == 0)
1714        linkData = (OSData *) gIONullLinkData;
1715
1716    bzero(&linkEventData, sizeof(linkEventData));
1717    if (activeMedium)
1718    {
1719        linkName = activeMedium->getName();
1720        linkEventData.linkType = activeMedium->getType();
1721        if (!linkSpeed) linkSpeed = activeMedium->getSpeed();
1722    }
1723
1724    MEDIUM_LOCK;
1725
1726    // Update kIOActiveMedium property.
1727	if (linkName != _lastActiveMediumName)
1728    {
1729        if (setProperty(gIOActiveMediumKey, (OSObject *) linkName))
1730            _lastActiveMediumName = linkName;
1731        else
1732            success = false;
1733    }
1734
1735	// Update kIOLinkData property.
1736    if (linkData != _lastLinkData)
1737    {
1738        if (setProperty(gIOLinkDataKey, linkData))
1739            _lastLinkData = linkData;
1740        else
1741            success = false;
1742    }
1743
1744    // Update kIOLinkSpeed property.
1745	if (linkSpeed != _linkSpeed->unsigned64BitValue())
1746	{
1747		_linkSpeed->setValue(linkSpeed);
1748        linkEvent = kIONetworkEventTypeLinkSpeedChange;
1749        linkEventData.linkSpeed = linkSpeed;
1750    }
1751
1752	// Update kIOLinkStatus property.
1753    oldLinkStatus = _linkStatus->unsigned32BitValue();
1754	if (linkStatus != oldLinkStatus)
1755	{
1756        if ((linkStatus ^ oldLinkStatus) &
1757            (kIONetworkLinkActive | kIONetworkLinkValid |
1758             kIONetworkLinkNoNetworkChange))
1759        {
1760            // Send link UP event when the link is up, or its state is unknown
1761            if ((linkStatus & kIONetworkLinkActive) ||
1762                !(linkStatus & kIONetworkLinkValid))
1763                linkEvent = kIONetworkEventTypeLinkUp;
1764            else
1765                linkEvent = kIONetworkEventTypeLinkDown;
1766
1767            linkEventData.linkStatus = linkStatus;
1768            linkEventData.linkSpeed = _linkSpeed->unsigned64BitValue();
1769        }
1770        DLOG("%s: set link status 0x%x\n", getName(), (uint32_t) linkStatus);
1771        _linkStatus->setValue(linkStatus);
1772	}
1773
1774    MEDIUM_UNLOCK;
1775
1776    // Broadcast a link event to interface objects.
1777    if (linkEvent)
1778        _broadcastEvent(linkEvent, &linkEventData);
1779
1780    return success;
1781}
1782
1783//---------------------------------------------------------------------------
1784// Returns the medium dictionary published by the driver through
1785// publishMediumDictionary(). Use copyMediumDictionary() to get a copy
1786// of the medium dictionary.
1787//
1788// Returns the published medium dictionary, or 0 if the driver has not
1789// yet published a medium dictionary through publishMediumDictionary().
1790
1791const OSDictionary * IONetworkController::getMediumDictionary() const
1792{
1793    return (OSDictionary *) getProperty(kIOMediumDictionary);
1794}
1795
1796//---------------------------------------------------------------------------
1797// Returns a copy of the medium dictionary published by the driver.
1798// The caller is responsible for releasing the dictionary object returned.
1799// Use getMediumDictionary() to get a reference to the published medium
1800// dictionary instead of creating a copy.
1801//
1802// Returns a copy of the medium dictionary, or 0 if the driver has not
1803// published a medium dictionary through publishMediumDictionary().
1804
1805OSDictionary * IONetworkController::copyMediumDictionary() const
1806{
1807    const OSDictionary * mediumDict;
1808    OSDictionary *       copy = 0;
1809
1810    MEDIUM_LOCK;
1811
1812    mediumDict = getMediumDictionary();
1813
1814    if (mediumDict)
1815    {
1816        copy = OSDictionary::withDictionary(mediumDict,
1817                                            mediumDict->getCount());
1818    }
1819
1820    MEDIUM_UNLOCK;
1821
1822    return copy;
1823}
1824
1825//---------------------------------------------------------------------------
1826// A client request to change the media selection.
1827
1828IOReturn IONetworkController::selectMedium(const IONetworkMedium * medium)
1829{
1830    return kIOReturnUnsupported;
1831}
1832
1833//---------------------------------------------------------------------------
1834// Private function to lookup a key in the medium dictionary and call
1835// setMedium() if a match is found. This function is called by our
1836// clients to change the medium selection by passing a name for the desired
1837// medium.
1838
1839IOReturn IONetworkController::selectMediumWithName(const OSSymbol * mediumName)
1840{
1841    OSSymbol *        currentMediumName;
1842    IONetworkMedium * newMedium = 0;
1843    bool              doChange  = true;
1844    IOReturn          ret       = kIOReturnSuccess;
1845
1846    if (OSDynamicCast(OSSymbol, mediumName) == 0)
1847        return kIOReturnBadArgument;
1848
1849    MEDIUM_LOCK;
1850
1851    do {
1852        const OSDictionary * mediumDict = getMediumDictionary();
1853        if (!mediumDict)
1854        {
1855        	// no medium dictionary, bail out.
1856            ret = kIOReturnUnsupported;
1857            break;
1858        }
1859
1860        // Lookup the new medium in the dictionary.
1861
1862        newMedium = (IONetworkMedium *) mediumDict->getObject(mediumName);
1863        if (!newMedium)
1864        {
1865            ret = kIOReturnBadArgument;
1866            break;          // not found, invalid mediumName.
1867        }
1868
1869        newMedium->retain();
1870
1871        // Lookup the current medium key to avoid unnecessary
1872        // medium changes.
1873
1874        currentMediumName = (OSSymbol *) getProperty(gIOCurrentMediumKey);
1875
1876        // Is change necessary?
1877
1878        if (currentMediumName && mediumName->isEqualTo(currentMediumName))
1879            doChange = false;
1880    }
1881    while (0);
1882
1883    MEDIUM_UNLOCK;
1884
1885    if (newMedium)
1886    {
1887        // Call the driver's selectMedium() without holding the medium lock.
1888
1889        if (doChange)
1890            ret = selectMedium(newMedium);
1891
1892        // Remove the earlier retain.
1893
1894        newMedium->release();
1895    }
1896
1897    return ret;
1898}
1899
1900//---------------------------------------------------------------------------
1901// Designate an entry in the published medium dictionary as
1902// the current selected medium.
1903
1904bool IONetworkController::setSelectedMedium(const IONetworkMedium * medium)
1905{
1906    bool  success = true;
1907    bool  changed = false;
1908    const OSSymbol * name = medium ? medium->getName() : gIONullMediumName;
1909
1910    MEDIUM_LOCK;
1911
1912    if (name != _lastCurrentMediumName)
1913	{
1914		if ( setProperty(gIOCurrentMediumKey, (OSSymbol *) name) )
1915	    {
1916			changed                = true;
1917			_lastCurrentMediumName = name;
1918		}
1919		else
1920			success = false;
1921	}
1922
1923    MEDIUM_UNLOCK;
1924
1925#if 0
1926    if (changed)
1927        _broadcastEvent(kIONetworkEventTypeLinkChange);
1928#endif
1929
1930    return success;
1931}
1932
1933//---------------------------------------------------------------------------
1934// Get the current selected medium.
1935
1936const IONetworkMedium * IONetworkController::getSelectedMedium() const
1937{
1938    IONetworkMedium * medium = 0;
1939    OSSymbol *        mediumName;
1940
1941    MEDIUM_LOCK;
1942
1943    do {
1944        const OSDictionary * mediumDict = getMediumDictionary();
1945        if (!mediumDict)    // no medium dictionary, bail out.
1946            break;
1947
1948        // Fetch the current medium name from the property table.
1949
1950        mediumName = (OSSymbol *) getProperty(gIOCurrentMediumKey);
1951
1952        // Make sure the current medium name points to an entry in
1953        // the medium dictionary.
1954
1955        medium = (IONetworkMedium *) mediumDict->getObject(mediumName);
1956
1957        // Invalid current medium, try the default medium.
1958
1959        if ( medium == 0 )
1960        {
1961            OSString * aString;
1962
1963            // This comes from the driver's property list.
1964            // More checking is done to avoid surprises.
1965
1966            aString = OSDynamicCast( OSString,
1967                                     getProperty(gIODefaultMediumKey) );
1968            if ( aString )
1969                medium = (IONetworkMedium *) mediumDict->getObject(aString);
1970        }
1971    }
1972    while (0);
1973
1974    MEDIUM_UNLOCK;
1975
1976    return medium;
1977}
1978
1979//---------------------------------------------------------------------------
1980// A private function to verify a medium dictionary. Returns true if the
1981// dictionary is OK.
1982
1983static bool verifyMediumDictionary(const OSDictionary * mediumDict)
1984{
1985    OSCollectionIterator * iter;
1986    bool                   verifyOk = true;
1987    OSSymbol *             key;
1988
1989    if (!OSDynamicCast(OSDictionary, mediumDict))
1990        return false;   // invalid argument
1991
1992    if (mediumDict->getCount() == 0)
1993        return false;   // empty dictionary
1994
1995    iter = OSCollectionIterator::withCollection((OSDictionary *) mediumDict);
1996    if (!iter)
1997        return false;   // cannot allocate iterator
1998
1999    while ((key = (OSSymbol *) iter->getNextObject()))
2000    {
2001        if ( !OSDynamicCast(IONetworkMedium, mediumDict->getObject(key)) )
2002        {
2003            verifyOk = false;   // non-medium object in dictionary
2004            break;
2005        }
2006    }
2007
2008    iter->release();
2009
2010    return verifyOk;
2011}
2012
2013//---------------------------------------------------------------------------
2014// Publish a dictionary of IONetworkMedium objects.
2015
2016bool
2017IONetworkController::publishMediumDictionary(const OSDictionary * mediumDict)
2018{
2019    OSDictionary *   cloneDict;
2020    bool             ret = false;
2021
2022    if (!verifyMediumDictionary(mediumDict))
2023        return false;   // invalid dictionary
2024
2025    // Create a clone of the source dictionary. This prevents the driver
2026    // from adding/removing entries after the medium dictionary is added
2027    // to the property table.
2028
2029    cloneDict = OSDictionary::withDictionary(mediumDict,
2030                                             mediumDict->getCount());
2031    if (!cloneDict)
2032        return false;  // unable to create a copy
2033
2034    MEDIUM_LOCK;
2035
2036    // Add the dictionary to the property table.
2037
2038    if (setProperty(kIOMediumDictionary, cloneDict))
2039    {
2040        const OSSymbol * mediumName;
2041
2042        // Update kIOSelectedMedium property.
2043
2044        mediumName = (OSSymbol *) getProperty(gIOCurrentMediumKey);
2045        if (cloneDict->getObject(mediumName) == 0)
2046        {
2047            mediumName = gIONullMediumName;
2048        }
2049        setProperty(gIOCurrentMediumKey, (OSSymbol *) mediumName);
2050        _lastCurrentMediumName = mediumName;
2051
2052        // Update kIOActiveMedium property.
2053
2054        mediumName = (OSSymbol *) getProperty(gIOActiveMediumKey);
2055        if (cloneDict->getObject(mediumName) == 0)
2056        {
2057            mediumName = gIONullMediumName;
2058        }
2059        setProperty(gIOActiveMediumKey, (OSSymbol *) mediumName);
2060        _lastActiveMediumName = mediumName;
2061
2062        ret = true;
2063    }
2064
2065    MEDIUM_UNLOCK;
2066
2067    // Retained by the property table. drop our retain count.
2068
2069    cloneDict->release();
2070
2071#if 0
2072    // Broadcast a link change event.
2073
2074    _broadcastEvent(kIONetworkEventTypeLinkChange);
2075#endif
2076
2077    return ret;
2078}
2079
2080//---------------------------------------------------------------------------
2081// Static function called by the internal IOCommandGate object to
2082// handle a runAction() request invoked by executeCommand().
2083
2084IOReturn IONetworkController::executeCommandAction(OSObject * owner,
2085                                                   void *     arg0,
2086                                                   void *  /* arg1 */,
2087                                                   void *  /* arg2 */,
2088                                                   void *  /* arg3 */)
2089{
2090    IONetworkController * self = (IONetworkController *) owner;
2091    cmdStruct *           cmdP = (cmdStruct *) arg0;
2092    IOReturn              ret  = kIOReturnSuccess;
2093    OSObject *            oldClient;
2094
2095    assert(cmdP && self);
2096
2097    oldClient = self->_cmdClient;
2098
2099    self->_cmdClient = cmdP->client;
2100
2101    cmdP->ret = (*cmdP->action)( cmdP->target,
2102                                 cmdP->param0,
2103                                 cmdP->param1,
2104                                 cmdP->param2,
2105                                 cmdP->param3 );
2106
2107    self->_cmdClient = oldClient;
2108
2109    return ret;
2110}
2111
2112//---------------------------------------------------------------------------
2113// Perform an "action" that is synchronized by the command gate.
2114
2115IOReturn IONetworkController::executeCommand(OSObject * client,
2116                                             Action     action,
2117                                             void *     target,
2118                                             void *     param0,
2119                                             void *     param1,
2120                                             void *     param2,
2121                                             void *     param3)
2122{
2123    cmdStruct  cmd;
2124    IOReturn   ret;
2125
2126    cmd.client  = client;
2127    cmd.action  = action;
2128    cmd.target  = target;
2129    cmd.param0  = param0;
2130    cmd.param1  = param1;
2131    cmd.param2  = param2;
2132    cmd.param3  = param3;
2133
2134    // Execute the client command through the command gate. Client commands
2135    // are thus synchronized with the workloop returned by getWorkLoop().
2136
2137    ret = _cmdGate->runAction( (IOCommandGate::Action)
2138                               &IONetworkController::executeCommandAction,
2139                               (void *) &cmd );    /* arg0 - cmdStruct */
2140
2141    // If executeCommandAction() executed successfully, then return the
2142    // status from the client command that was executed.
2143
2144    if (ret == kIOReturnSuccess)
2145        ret = cmd.ret;
2146
2147    return ret;
2148}
2149
2150//---------------------------------------------------------------------------
2151// Called by executeCommand() to handle the client command on the
2152// workloop context.
2153
2154void countBSDEnablesApplier( IOService * client, void * context )
2155{
2156    if ( OSDynamicCast( IONetworkInterface, client ) &&
2157         client->getProperty( gIOControllerEnabledKey ) == kOSBooleanTrue )
2158        (*(UInt32 *)context)++;
2159}
2160
2161IOReturn IONetworkController::handleCommand(void * target,
2162                                            void * param0,
2163                                            void * param1,
2164                                            void * param2,
2165                                            void * param3)
2166{
2167
2168    IONetworkController * self    = (IONetworkController *) target;
2169    UInt32                command = (uintptr_t) param0;
2170    IOService *           client  = (IOService *) param1;
2171    IOReturn              ret     = kIOReturnSuccess;
2172    UInt32                count   = 0;
2173
2174    switch ( command )
2175    {
2176        case kCommandEnable:
2177            if (( ret = self->enable(client) ) == kIOReturnSuccess )
2178            {
2179                // Record the client enable, and send messages to inform
2180                // interested clients.
2181
2182                client->setProperty( gIOControllerEnabledKey, kOSBooleanTrue );
2183                if ( OSDynamicCast( IONetworkInterface, client ) )
2184                {
2185                    self->applyToClients( countBSDEnablesApplier, &count );
2186                    if ( count == 1 )
2187                        self->messageClients(kMessageControllerWasEnabledForBSD);
2188                }
2189                self->messageClients(kMessageControllerWasEnabled, client);
2190            }
2191            break;
2192
2193        case kCommandDisable:
2194            if (( ret = self->disable(client) ) == kIOReturnSuccess )
2195            {
2196                // Record the client disable, and send messages to inform
2197                // interested clients.
2198
2199                client->setProperty( gIOControllerEnabledKey, kOSBooleanFalse );
2200                if ( OSDynamicCast( IONetworkInterface, client ) )
2201                {
2202                    self->applyToClients( countBSDEnablesApplier, &count );
2203                    if ( count == 0 )
2204                        self->messageClients(kMessageControllerWasDisabledForBSD);
2205                }
2206                self->messageClients(kMessageControllerWasDisabled, client);
2207            }
2208            break;
2209
2210        case kCommandPrepare:
2211            ret = self->prepare();
2212            break;
2213
2214        case kCommandInitDebugger:
2215            // Send a message to the debugger to announce the controller's
2216            // enable/disable state when the debugger is first attached as
2217            // a client. This eliminate problems with lost messages if the
2218            // debugger is attached after the BSD client has attached and
2219            // enabled the controller, and early debugging is not active.
2220
2221            self->applyToClients( countBSDEnablesApplier, &count );
2222            if ( count )
2223                client->message( kMessageControllerWasEnabledForBSD, self );
2224            break;
2225
2226        default:
2227            ret = kIOReturnUnsupported;
2228            break;
2229    }
2230
2231    return ret;
2232}
2233
2234//---------------------------------------------------------------------------
2235// Issue an kCommandEnable command to handleCommand().
2236
2237IOReturn IONetworkController::doEnable(IOService * client)
2238{
2239	return executeCommand( client,
2240                           &IONetworkController::handleCommand,
2241                           this,
2242                           (void *) kCommandEnable,
2243                           (void *) client);
2244}
2245
2246//---------------------------------------------------------------------------
2247// Issue an kCommandDisable command to handleCommand().
2248
2249IOReturn IONetworkController::doDisable(IOService * client)
2250{
2251	return executeCommand( client,
2252                           &IONetworkController::handleCommand,
2253                           this,
2254                           (void *) kCommandDisable,
2255                           (void *) client);
2256}
2257
2258//---------------------------------------------------------------------------
2259// Inlined functions pulled from header file to ensure
2260// binary compatibility with drivers built with gcc2.95.
2261
2262const IONetworkMedium * IONetworkController::getCurrentMedium() const
2263{
2264    return getSelectedMedium();
2265}
2266
2267bool IONetworkController::setCurrentMedium(const IONetworkMedium * medium)
2268{
2269    return setSelectedMedium(medium);
2270}
2271
2272//---------------------------------------------------------------------------
2273
2274void IONetworkController::systemWillShutdown( IOOptionBits specifier )
2275{
2276    if (specifier == kIOMessageSystemWillPowerOff ||
2277        specifier == kIOMessageSystemWillRestart)
2278    {
2279        messageClients(kMessageControllerWillShutdown);
2280    }
2281
2282    super::systemWillShutdown(specifier);
2283}
2284
2285//---------------------------------------------------------------------------
2286
2287IOReturn IONetworkController::setAggressiveness(
2288    unsigned long type, unsigned long newLevel )
2289{
2290    // Tell interface object(s) that WOMP support has changed.
2291
2292    if ((kPMEthernetWakeOnLANSettings == type) && _clientSetIter)
2293    {
2294        _broadcastEvent( kIONetworkEventWakeOnLANSupportChanged );
2295    }
2296
2297    return super::setAggressiveness(type, newLevel);
2298}
2299
2300//---------------------------------------------------------------------------
2301
2302IOReturn IONetworkController::message(
2303    UInt32 type, IOService * provider, void * argument )
2304{
2305    if (kIOMessageDeviceSignaledWakeup == type)
2306    {
2307        return provider->callPlatformFunction(
2308                    "IOPlatformDeviceSignaledWakeup",
2309                    false,
2310                    (void *) this, 0, 0, 0);
2311    }
2312
2313    return super::message(type, provider, argument);
2314}
2315
2316//---------------------------------------------------------------------------
2317
2318IOReturn IONetworkController::outputStart(
2319    IONetworkInterface *    interface,
2320    IOOptionBits            options )
2321{
2322    return kIOReturnUnsupported;
2323}
2324
2325IOReturn IONetworkController::setInputPacketPollingEnable(
2326    IONetworkInterface *    interface,
2327    bool                    enabled )
2328{
2329    return kIOReturnUnsupported;
2330}
2331
2332void IONetworkController::pollInputPackets(
2333    IONetworkInterface *    interface,
2334    uint32_t                maxCount,
2335    IOMbufQueue *           pollQueue,
2336    void *                  context )
2337{
2338}
2339
2340//------------------------------------------------------------------------------
2341
2342IOMbufServiceClass IONetworkController::getMbufServiceClass( mbuf_t mbuf )
2343{
2344    mbuf_svc_class_t    mbufSC = mbuf_get_service_class(mbuf);
2345    IOMbufServiceClass  ioSC;
2346
2347    switch (mbufSC)
2348    {
2349        default:
2350        case MBUF_SC_BE:     ioSC = kIOMbufServiceClassBE;  break;
2351        case MBUF_SC_BK_SYS: ioSC = kIOMbufServiceClassBKSYS; break;
2352        case MBUF_SC_BK:     ioSC = kIOMbufServiceClassBK;  break;
2353        case MBUF_SC_RD:     ioSC = kIOMbufServiceClassRD;  break;
2354        case MBUF_SC_OAM:    ioSC = kIOMbufServiceClassOAM; break;
2355        case MBUF_SC_AV:     ioSC = kIOMbufServiceClassAV;  break;
2356        case MBUF_SC_RV:     ioSC = kIOMbufServiceClassRV;  break;
2357        case MBUF_SC_VI:     ioSC = kIOMbufServiceClassVI;  break;
2358        case MBUF_SC_VO:     ioSC = kIOMbufServiceClassVO;  break;
2359        case MBUF_SC_CTL:    ioSC = kIOMbufServiceClassCTL; break;
2360    }
2361
2362    return ioSC;
2363}
2364
2365//------------------------------------------------------------------------------
2366
2367IOReturn IONetworkController::networkInterfaceNotification(
2368    IONetworkInterface *    interface,
2369    uint32_t                type,
2370    void *                  argument )
2371{
2372    return kIOReturnUnsupported;
2373}
2374
2375//------------------------------------------------------------------------------
2376
2377IOReturn IONetworkController::attachAuxiliaryDataToPacket(
2378    mbuf_t          packet,
2379    const void *    data,
2380    IOByteCount     length,
2381    uint32_t        family,
2382    uint32_t        subFamily )
2383{
2384    errno_t error;
2385    void *  data_p = 0;
2386
2387    if (!packet || !data || !length)
2388        return kIOReturnBadArgument;
2389
2390    error = mbuf_add_drvaux(packet, MBUF_WAITOK, family, subFamily,
2391                            (size_t) length, &data_p);
2392    if (error)
2393    {
2394        return IONetworkInterface::errnoToIOReturn(error);
2395    }
2396
2397    if (data_p)
2398        bcopy(data, data_p, length);
2399
2400    return kIOReturnSuccess;
2401}
2402
2403void IONetworkController::removeAuxiliaryDataFromPacket(
2404    mbuf_t      packet )
2405{
2406    mbuf_del_drvaux(packet);
2407}
2408