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