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