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