Annotation of XNU/iokit/Families/IONetworking/IONetworkController.cpp, revision 1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.