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 * IONetworkInterface.cpp
24 *
25 * HISTORY
26 * 8-Jan-1999       Joe Liu (jliu) created.
27 *
28 */
29
30extern "C" {
31#include <sys/param.h>
32#include <sys/systm.h>
33#include <sys/mbuf.h>
34#include <sys/socket.h>
35#include <sys/sockio.h>
36#include <net/bpf.h>
37#include <net/if.h>
38#include <net/if_media.h>
39#include <net/dlil.h>
40#include <net/if_dl.h>
41#include <net/kpi_interface.h>
42#include <sys/kern_event.h>
43
44#define _IP_VHL
45
46#include <netinet/ip.h>
47#include <netinet/ip_icmp.h>
48}
49
50#include <IOKit/assert.h>
51#include <IOKit/IOLib.h>
52#include <IOKit/IOBSD.h>
53#include <IOKit/network/IONetworkInterface.h>
54#include <IOKit/network/IONetworkController.h>
55#include "IONetworkUserClient.h"
56#include "IONetworkStack.h"
57#include "IONetworkTypesPrivate.h"
58#include "IONetworkControllerPrivate.h"
59#include "IONetworkDebug.h"
60#include "IOMbufQueue.h"
61
62#include <TargetConditionals.h>
63
64//------------------------------------------------------------------------------
65
66#define super IOService
67
68OSDefineMetaClassAndAbstractStructors( IONetworkInterface, IOService )
69OSMetaClassDefineReservedUsed( IONetworkInterface,  5);
70OSMetaClassDefineReservedUsed( IONetworkInterface,  6);
71OSMetaClassDefineReservedUsed( IONetworkInterface,  7);
72OSMetaClassDefineReservedUsed( IONetworkInterface,  8);
73OSMetaClassDefineReservedUsed( IONetworkInterface,  9);
74OSMetaClassDefineReservedUsed( IONetworkInterface, 10);
75OSMetaClassDefineReservedUnused( IONetworkInterface, 11);
76OSMetaClassDefineReservedUnused( IONetworkInterface, 12);
77OSMetaClassDefineReservedUnused( IONetworkInterface, 13);
78OSMetaClassDefineReservedUnused( IONetworkInterface, 14);
79OSMetaClassDefineReservedUnused( IONetworkInterface, 15);
80
81//------------------------------------------------------------------------------
82// Macros
83
84#define IFNET_TO_THIS(x)        ((IONetworkInterface *) ifnet_softc(ifp))
85
86#define WAITING_FOR_DETACH(n)   ((n)->_clientVar[1])
87
88#define _unit                   _reserved->unit
89#define _type                   _reserved->type
90#define _mtu                    _reserved->mtu
91#define _flags                  _reserved->flags
92#define _eflags                 _reserved->eflags
93#define _addrlen                _reserved->addrlen
94#define _hdrlen                 _reserved->hdrlen
95#define _loggingLevel           _reserved->loggingLevel
96#define _outputQueueModel       _reserved->outputQueueModel
97#define _inputDeltas            _reserved->inputDeltas
98#define _driverStats            _reserved->driverStats
99#define _lastDriverStats        _reserved->lastDriverStats
100#define _publicLock             _reserved->publicLock
101#define _remote_NMI_pattern     _reserved->remote_NMI_pattern
102#define _remote_NMI_len         _reserved->remote_NMI_len
103#define _controller             _reserved->controller
104#define _configFlags            _reserved->configFlags
105#define _txRingSize             _reserved->txRingSize
106#define _txPullOptions          _reserved->txPullOptions
107#define _txQueueSize            _reserved->txQueueSize
108#define _txSchedulingModel      _reserved->txSchedulingModel
109#define _txThreadState          _reserved->txThreadState
110#define _txThreadFlags          _reserved->txThreadFlags
111#define _txThreadSignal         _reserved->txThreadSignal
112#define _txThreadSignalLast     _reserved->txThreadSignalLast
113#define _txStartThread          _reserved->txStartThread
114#define _txStartAction          _reserved->txStartAction
115#define _txWorkLoop             _reserved->txWorkLoop
116#define _rxRingSize             _reserved->rxRingSize
117#define _rxPollOptions          _reserved->rxPollOptions
118#define _rxPollModel            _reserved->rxPollModel
119#define _rxPollAction           _reserved->rxPollAction
120#define _rxCtlAction            _reserved->rxCtlAction
121#define _rxPollEmpty            _reserved->rxPollEmpty
122#define _rxPollTotal            _reserved->rxPollTotal
123#define _peqHandler             _reserved->peqHandler
124#define _peqTarget              _reserved->peqTarget
125#define _peqRefcon              _reserved->peqRefcon
126#define _subType                _reserved->subType
127
128#define kRemoteNMI                  "remote_nmi"
129#define REMOTE_NMI_PATTERN_LEN      32
130
131// _txThreadState
132#define kTxThreadStateInit          0x00000001  // initial state
133#define kTxThreadStateStop          0x00000100  // temporarily disable
134#define kTxThreadStateDetach        0x00000200  // permanently disable
135#define kTxThreadStateHalted        0x00000800  // stop confirmation
136#define kTxThreadStatePurge         0x00001000  // purge new packets
137
138// _txThreadFlags
139#define kTxThreadWakeupEnable       0x00000001  // enable ifnet_start call
140#define kTxThreadWakeupSignal       0x00000002  // driver signaled
141#define kTxThreadWakeupMask         0x00000003  // wakeup bits
142
143enum {
144    kConfigFrozen       = 0x01,
145    kConfigTxPull       = 0x02,
146    kConfigRxPoll       = 0x04,
147    kConfigDataRates    = 0x08,
148    kConfigPreEnqueue   = 0x10
149};
150
151//------------------------------------------------------------------------------
152// Initialize an IONetworkInterface instance.
153//
154// Returns true if initialized successfully, false otherwise.
155
156bool IONetworkInterface::init( IONetworkController * controller )
157{
158    IONetworkData * nd;
159#if TARGET_OS_EMBEDDED
160	OSString *      networkType;
161#endif
162
163    // Propagate the init() call to our superclass.
164
165    if ( super::init() == false )
166        goto fail;
167
168	// A non-null value at this point means the subclass is pre-kpi
169    // and allocated its ifnet/arpcom itself.
170	// We can't work with such a sublcass but at least we can fail gracefully.
171
172    if (getIfnet())
173	{
174		IOLog("\33[00m\33[31m%s: IONetworkingFamily interface KPIs do not support IONetworkInterface subclasses that use ifnets\n\33[00m", getName());
175		goto fail;
176	}
177
178    // The controller object provided must be valid.
179
180    if ( OSDynamicCast(IONetworkController, controller) == 0 )
181        goto fail;
182
183    _driver = controller;
184    _driver->retain();
185
186    // Allocate memory for the ExpansionData structure.
187
188    _reserved = IONew( ExpansionData, 1 );
189    if ( _reserved == 0 )
190        goto fail;
191
192    // Initialize the fields in the ExpansionData structure.
193
194    bzero(_reserved, sizeof(ExpansionData));
195
196	_privateLock = IOLockAlloc();
197	if ( _privateLock == 0)
198		goto fail;
199
200    _publicLock = IORecursiveLockAlloc();
201    if ( _publicLock == 0 )
202        goto fail;
203
204    _controller = controller;
205    _rxPollModel = IFNET_MODEL_INPUT_POLL_OFF;
206
207    _inputPushQueue = IONew(IOMbufQueue, 1);
208    bzero(_inputPushQueue, sizeof(*_inputPushQueue));
209
210    // Set initial queue state before attaching to network stack.
211    _txThreadState = kTxThreadStateInit | kTxThreadStateHalted;
212
213    // Create an OSNumber to store interface state bits.
214
215    _stateBits = OSNumber::withNumber((UInt64) 0, 32);
216    if ( _stateBits == 0 )
217        goto fail;
218    setProperty( kIOInterfaceState, _stateBits );
219
220    // Create an OSSet to store client objects. Initial capacity
221    // (which can grow) is set at 2 clients.
222
223    _clientSet = OSSet::withCapacity(2);
224    if ( _clientSet == 0 )
225        goto fail;
226
227    // Dictionary to store network data.
228
229    if ( (_dataDict = OSDictionary::withCapacity(5)) == 0 )
230        goto fail;
231
232    nd = IONetworkData::withExternalBuffer(
233                            kIONetworkStatsKey,
234                            sizeof(IONetworkStats),
235                            &_driverStats);
236    if ( nd )
237    {
238        addNetworkData(nd);
239        nd->release();
240    }
241
242    // Register default output handler (not used for pull transmit model)
243
244    if (!registerOutputHandler(controller, controller->getOutputHandler()))
245        goto fail;
246
247    // Set the kIOInterfaceNamePrefix and kIOPrimaryInterface properties.
248    // These may be used by an user space agent as hints when assigning a
249    // BSD name for the interface.
250
251    setProperty( kIOInterfaceNamePrefix, getNamePrefix() );
252
253#if TARGET_OS_EMBEDDED
254    networkType = OSDynamicCast(OSString, controller->getProperty( "IONetworkRootType" ));
255    if (networkType)
256		setProperty( "IONetworkRootType", networkType );
257#endif /* TARGET_OS_EMBEDDED */
258
259    if (IOService *provider = controller->getProvider())
260    {
261        bool        gotLocation = false;
262        OSData *    locationAsData;
263        OSData *    locationAsCstr;
264        OSString *  locationAsString;
265
266        setProperty(kIOBuiltin, (bool)(provider->getProperty("built-in")));
267
268        if ((locationAsData = OSDynamicCast(OSData, provider->getProperty("location"))))
269        {
270			// the data may be null terminated...but to be on the safe side,
271            // let's assume it's not, and add a null...
272            // create a copy that we can convert to C string
273			if ((locationAsCstr = OSData::withData(locationAsData)))
274            {
275                locationAsCstr->appendByte(0, 1);
276                // now create the OSString
277                if ((locationAsString = OSString::withCString(
278                     (const char *) locationAsCstr->getBytesNoCopy())))
279                {
280                    gotLocation = true;
281                    setProperty(kIOLocation, locationAsString);
282                    locationAsString->release(); //setProperty took a ref
283                }
284                locationAsCstr->release();
285            }
286        }
287        if (!gotLocation)
288            setProperty(kIOLocation, "");
289    }
290
291    DLOG("IONetworkInterface::init(%p, %s)\n", this, controller->getName());
292    return true;
293
294fail:
295    LOG("IONetworkInterface::init(%p, %s) failed\n", this, controller->getName());
296    return false;
297}
298
299//------------------------------------------------------------------------------
300// Destroy the interface. Release all allocated resources.
301
302void IONetworkInterface::free( void )
303{
304    DLOG("IONetworkInterface::free(%p)\n", this);
305
306    if (_driver)
307    {
308        _driver->release();
309        _driver = 0;
310    }
311
312    if ( _clientSet )
313    {
314        // Should not have any clients.
315        assert(_clientSet->getCount() == 0);
316        _clientSet->release();
317        _clientSet = 0;
318    }
319
320    if ( _dataDict  )
321    {
322        _dataDict->release();
323        _dataDict = 0;
324    }
325
326    if ( _stateBits )
327    {
328        _stateBits->release();
329        _stateBits = 0;
330    }
331
332    if ( _inputPushQueue )
333    {
334		clearInputQueue();
335        IODelete(_inputPushQueue, IOMbufQueue, 1);
336        _inputPushQueue = 0;
337    }
338
339    if ( _privateLock )
340    {
341        IOLockFree(_privateLock);
342        _privateLock = 0;
343    }
344
345    if (_backingIfnet)
346    {
347        ifnet_release(_backingIfnet);
348        _backingIfnet = 0;
349    }
350
351    // Free resources referenced through fields in the ExpansionData
352    // structure, and also the structure itself.
353
354    if ( _reserved )
355    {
356        if ( _publicLock )
357        {
358            IORecursiveLockFree(_publicLock);
359            _publicLock = 0;
360        }
361
362        if (_remote_NMI_pattern) {
363            IOFree(_remote_NMI_pattern, _remote_NMI_len);
364        }
365
366        if (_txWorkLoop)
367            _txWorkLoop->release();
368
369        memset(_reserved, 0, sizeof(ExpansionData));
370        IODelete(_reserved, ExpansionData, 1);
371        _reserved = 0;
372    }
373
374    super::free();
375}
376
377//------------------------------------------------------------------------------
378// Returns true if the receiver of this method is the system's primary
379// network interface.
380
381bool IONetworkInterface::isPrimaryInterface() const
382{
383    IOService * provider  = _driver;
384    bool        isPrimary = false;
385
386    if ( provider ) provider = provider->getProvider();
387
388    // Look for the built-in property in the ethernet entry.
389
390    if ( provider && provider->getProperty("built-in") && getUnitNumber() == 0)
391    {
392        isPrimary = true;
393    }
394
395    return isPrimary;
396}
397
398//------------------------------------------------------------------------------
399
400IONetworkController * IONetworkInterface::getController( void ) const
401{
402    return _controller;
403}
404
405//------------------------------------------------------------------------------
406// Get the value that should be set in the hwassist field in the ifnet
407// structure. Currently, this field is solely used for advertising the
408// hardware checksumming support.
409
410static UInt32 getIfnetHardwareAssistValue(
411    IONetworkController * driver )
412{
413    UInt32  input;
414    UInt32  output;
415    UInt32  hwassist = 0;
416    UInt32  driverFeatures = driver->getFeatures();
417
418    do {
419        if ( driver->getChecksumSupport(
420                     &input,
421                     IONetworkController::kChecksumFamilyTCPIP,
422                     false ) != kIOReturnSuccess ) break;
423
424        if ( driver->getChecksumSupport(
425                     &output,
426                     IONetworkController::kChecksumFamilyTCPIP,
427                     true ) != kIOReturnSuccess ) break;
428
429        if ( input & output & IONetworkController::kChecksumIP )
430        {
431            hwassist |= IFNET_CSUM_IP;
432        }
433
434        if ( ( input  & ( IONetworkController::kChecksumTCP |
435                          IONetworkController::kChecksumTCPNoPseudoHeader ) )
436        &&   ( output & ( IONetworkController::kChecksumTCP ) ) )
437        {
438            hwassist |= IFNET_CSUM_TCP;
439        }
440
441        if ( ( input  & ( IONetworkController::kChecksumUDP |
442                          IONetworkController::kChecksumUDPNoPseudoHeader ) )
443        &&   ( output & ( IONetworkController::kChecksumUDP ) ) )
444        {
445            hwassist |= IFNET_CSUM_UDP;
446        }
447
448        if ( input & output & IONetworkController::kChecksumTCPSum16 )
449        {
450            hwassist |= ( IFNET_CSUM_SUM16 | IFNET_CSUM_TCP | IFNET_CSUM_UDP );
451        }
452
453        if ( input & output & IONetworkController::kChecksumTCPIPv6 )
454        {
455            hwassist |= IFNET_CSUM_TCPIPV6;
456        }
457        if ( input & output & IONetworkController::kChecksumUDPIPv6 )
458        {
459            hwassist |= IFNET_CSUM_UDPIPV6;
460        }
461    }
462    while ( false );
463
464	if( driverFeatures & kIONetworkFeatureHardwareVlan)
465		hwassist |= IFNET_VLAN_TAGGING;
466
467	if( driverFeatures & kIONetworkFeatureSoftwareVlan)
468		hwassist |= IFNET_VLAN_MTU;
469
470	if( driverFeatures & kIONetworkFeatureMultiPages)
471		hwassist |= IFNET_MULTIPAGES;
472
473	if( driverFeatures & kIONetworkFeatureTSOIPv4)
474		hwassist |= IFNET_TSO_IPV4;
475
476	if( driverFeatures & kIONetworkFeatureTSOIPv6)
477		hwassist |= IFNET_TSO_IPV6;
478
479    if (driverFeatures & kIONetworkFeatureTransmitCompletionStatus)
480        hwassist |= IFNET_TX_STATUS;
481
482    return hwassist;
483}
484
485//------------------------------------------------------------------------------
486// Initialize the ifnet structure.
487
488bool IONetworkInterface::initIfnet( struct ifnet * ifp )
489{
490	return false;   // deprecated - replaced by initIfnetParams()
491}
492
493OSMetaClassDefineReservedUsed(IONetworkInterface, 4);
494
495bool IONetworkInterface::initIfnetParams( struct ifnet_init_params *params )
496{
497    // Register our 'shim' functions. These function pointers
498    // points to static member functions inside this class.
499	params->name		= (char *) getNamePrefix();
500	params->type		= _type;
501	params->unit		= _unit;
502	params->output		= if_output;
503	params->ioctl		= if_ioctl;
504	params->set_bpf_tap = if_set_bpf_tap;
505	params->detach		= if_detach;
506	params->softc		= this;
507
508    return true;
509}
510
511//------------------------------------------------------------------------------
512// Take/release the interface lock.
513
514void IONetworkInterface::lock()
515{
516    IORecursiveLockLock(_publicLock);
517}
518
519void IONetworkInterface::unlock()
520{
521    IORecursiveLockUnlock(_publicLock);
522}
523
524//------------------------------------------------------------------------------
525// Inspect the controller after it has been opened.
526
527bool IONetworkInterface::controllerDidOpen( IONetworkController * controller )
528{
529    return true;   // by default, always accept the controller open.
530}
531
532//------------------------------------------------------------------------------
533// Perform cleanup before the controller is closed.
534
535void IONetworkInterface::controllerWillClose( IONetworkController * controller )
536{
537}
538
539//------------------------------------------------------------------------------
540// Handle a client open on the interface (IONetworkStack or user client)
541
542bool IONetworkInterface::handleOpen( IOService *  client,
543                                     IOOptionBits options,
544                                     void *       argument )
545{
546    bool  accept         = false;
547    bool  controllerOpen = false;
548
549    do {
550        // Was this object already registered as our client?
551
552        if ( _clientSet->containsObject(client) )
553        {
554            DLOG("%s: rejected open from existing client %s\n",
555                getName(), client->getName());
556            accept = true;
557            break;
558        }
559
560        // If the interface has not received a client open, which also
561        // implies that the interface has not yet opened the controller,
562        // then open the controller upon receiving the first open from
563        // a client. If the controller open fails, the client open will
564        // be rejected.
565
566        if (( getInterfaceState() & kIONetworkInterfaceOpenedState ) == 0)
567        {
568            if (!_driver ||
569                 ((controllerOpen = _driver->open(this)) == false) ||
570                 (controllerDidOpen(_driver) == false))
571                break;
572        }
573
574        // Allow subclasses to intercept.
575
576        if ( handleClientOpen(client, options, argument) == false )
577            break;
578
579        // Add the new client object to our client set.
580
581        if ( _clientSet->setObject(client) == false )
582        {
583            handleClientClose(client, 0);
584            break;
585        }
586
587        accept = true;
588    }
589    while (false);
590
591    // If provider was opened above, but an error has caused us to refuse
592    // the client open, then close our provider.
593
594    if ( controllerOpen )
595    {
596        if (accept)
597        {
598            setInterfaceState( kIONetworkInterfaceOpenedState );
599            _driver->registerInterestedDriver( this );
600        }
601        else
602        {
603            controllerWillClose(_driver);
604            _driver->close(this);
605        }
606    }
607
608    return accept;
609}
610
611//------------------------------------------------------------------------------
612// Handle a client close on the interface.
613
614void IONetworkInterface::handleClose( IOService * client, IOOptionBits options )
615{
616    if ( _clientSet->containsObject(client) )
617    {
618        // Call handleClientClose() for subclass to handle the client close.
619
620        handleClientClose( client, options );
621
622        // Close our provider on last client close.
623
624        if ( _clientSet->getCount() == 1 )
625        {
626            _driver->deRegisterInterestedDriver( this );
627            controllerWillClose( _driver );
628            _driver->close( this );
629            setInterfaceState( 0, kIONetworkInterfaceOpenedState );
630
631            // Closed by IONetworkStack after detaching interface,
632            // drop the driver retain from init().
633
634            if (!isRegistered())
635            {
636                _driver->release();
637                _driver = 0;
638            }
639        }
640        _clientSet->removeObject(client);
641    }
642}
643
644//------------------------------------------------------------------------------
645// Query whether a client has an open on the interface.
646
647bool IONetworkInterface::handleIsOpen( const IOService * client ) const
648{
649    if (client)
650        return _clientSet->containsObject(client);
651    else
652        return (_clientSet->getCount() > 0);
653}
654
655//------------------------------------------------------------------------------
656// Handle a client open on the interface.
657
658bool IONetworkInterface::handleClientOpen(IOService *  client,
659                                          IOOptionBits options,
660                                          void *       argument)
661{
662    return true;
663}
664
665//------------------------------------------------------------------------------
666// Handle a client close on the interface.
667
668void IONetworkInterface::handleClientClose(IOService *  client,
669                                           IOOptionBits options)
670{
671}
672
673//------------------------------------------------------------------------------
674// Register the output packet handler.
675
676bool IONetworkInterface::registerOutputHandler(OSObject *      target,
677                                               IOOutputAction  action)
678{
679    IOLockLock(_privateLock);
680
681    // Sanity check the arguments.
682
683    if ( (getInterfaceState() & kIONetworkInterfaceOpenedState) ||
684         !target || !action )
685    {
686        IOLockUnlock(_privateLock);
687        return false;
688    }
689
690    _outTarget = target;
691    _outAction = action;
692
693    IOLockUnlock(_privateLock);
694
695    return true;
696}
697
698//------------------------------------------------------------------------------
699// Feed packets to the input/output BPF packet filter taps.
700
701OSMetaClassDefineReservedUsed(IONetworkInterface, 2);
702
703void IONetworkInterface::feedPacketInputTap(mbuf_t  m)
704{
705    // PR3662433 we're not protected from this getting changed out from under us
706    // so use a local ptr and double check for NULL to avoid the race
707	bpf_packet_func inFilter = _inputFilterFunc;
708	if (inFilter)
709		inFilter(_backingIfnet, m);
710}
711
712OSMetaClassDefineReservedUsed(IONetworkInterface, 3);
713
714void IONetworkInterface::feedPacketOutputTap(mbuf_t m)
715{
716    // see comment in feedPacketInputTap
717	bpf_packet_func outFilter = _outputFilterFunc;
718	if (outFilter)
719		outFilter(_backingIfnet, m);
720}
721
722//------------------------------------------------------------------------------
723
724#define ABS(a)  ((a) < 0 ? -(a) : (a))
725
726void IONetworkInterface::pushInputQueue( IOMbufQueue * queue )
727{
728    uint32_t    temp;
729    int         delta;
730
731    _inputDeltas.packets_in = queue->count;
732    _inputDeltas.bytes_in   = queue->bytes;
733
734    // Report our packet count rather than rely on the driver stats.
735    // ifnet_input_extended() requires the count to be accurate.
736
737    temp = _driverStats.inputErrors;
738    delta =  temp - _lastDriverStats.inputErrors;
739    _inputDeltas.errors_in = ABS(delta);
740    _lastDriverStats.inputErrors = temp;
741
742    temp = _driverStats.collisions;
743    delta = temp - _lastDriverStats.collisions;
744    _inputDeltas.collisions = ABS(delta);
745    _lastDriverStats.collisions = temp;
746
747    ifnet_input_extended(_backingIfnet, queue->head, queue->tail, &_inputDeltas);
748    IOMbufQueueInit(queue);
749}
750
751void IONetworkInterface::pushInputPacket( mbuf_t packet, uint32_t length )
752{
753    uint32_t    temp;
754    int         delta;
755
756    _inputDeltas.packets_in = 1;
757    _inputDeltas.bytes_in   = length;
758
759    // Report our packet count rather than rely on the driver stats.
760    // ifnet_input_extended() requires the count to be accurate.
761
762    temp = _driverStats.inputErrors;
763    delta =  temp - _lastDriverStats.inputErrors;
764    _inputDeltas.errors_in = ABS(delta);
765    _lastDriverStats.inputErrors = temp;
766
767    temp = _driverStats.collisions;
768    delta = temp - _lastDriverStats.collisions;
769    _inputDeltas.collisions = ABS(delta);
770    _lastDriverStats.collisions = temp;
771
772    ifnet_input_extended(_backingIfnet, packet, packet, &_inputDeltas);
773}
774
775UInt32 IONetworkInterface::flushInputQueue( void )
776{
777    UInt32 count = _inputPushQueue->count;
778
779    if (count)
780    {
781        //DLOG("push pkt cnt %u\n", count);
782        pushInputQueue(_inputPushQueue);
783    }
784
785    return count;
786}
787
788UInt32 IONetworkInterface::clearInputQueue( void )
789{
790    UInt32 count = _inputPushQueue->count;
791
792    if (count)
793        mbuf_freem_list(_inputPushQueue->head);
794
795    IOMbufQueueInit(_inputPushQueue);
796    return count;
797}
798
799inline static const char *get_icmp_data(mbuf_t *pkt, int hdrlen, int datalen)
800{
801    struct ip   *ip;
802    struct icmp *icmp;
803    int hlen, icmplen;
804
805    icmplen = sizeof(*icmp) + sizeof(struct timeval);
806
807    /* make sure hdrlen is sane with respect to mbuf */
808    if (mbuf_len(*pkt) < (sizeof(*ip) + hdrlen))
809        goto error;
810
811    /* only work for IPv4 packets */
812    ip = (struct ip *) ((char *) mbuf_data(*pkt) + hdrlen);
813    if (IP_VHL_V(ip->ip_vhl) != IPVERSION)
814        goto error;
815
816    hlen = IP_VHL_HL(ip->ip_vhl) << 2;
817
818    /* make sure header and data is contiguous */
819    if (mbuf_pullup(pkt, hlen + icmplen) != 0)
820        goto error;
821
822    /* refresh the pointer and hlen in case buffer was shifted */
823    ip = (struct ip *) ((char *) mbuf_data(*pkt) + hdrlen);
824        hlen = IP_VHL_HL(ip->ip_vhl) << 2;
825
826    if (ip->ip_p != IPPROTO_ICMP)
827        goto error;
828
829    if (ip->ip_len < (icmplen + datalen))
830        goto error;
831
832    icmp = (struct icmp *) (((char *) mbuf_data(*pkt) + hdrlen) + hlen);
833    if (icmp->icmp_type != ICMP_ECHO)
834        goto error;
835
836    return (const char *) (((char *) mbuf_data(*pkt) + hdrlen) + icmplen);
837
838error:
839    return NULL;
840}
841
842UInt32 IONetworkInterface::inputPacket( mbuf_t          packet,
843                                        UInt32          length,
844                                        IOOptionBits    options,
845                                        void *          param )
846{
847	const UInt32    hdrlen = _hdrlen;
848    UInt32          count;
849    void *          mdata;
850
851    assert(packet);
852    assert(_backingIfnet);
853    if (!packet || !_backingIfnet)
854        return 0;
855
856    assert((mbuf_flags(packet) & MBUF_PKTHDR));
857    assert((mbuf_nextpkt(packet) == 0));
858
859	mbuf_pkthdr_setrcvif(packet, _backingIfnet);
860
861    if (length)
862    {
863        // Driver wants interface to set the mbuf length.
864        if (mbuf_next(packet) == 0)
865        {
866            mbuf_pkthdr_setlen(packet, length);
867			mbuf_setlen(packet, length);
868        }
869        else
870        {
871            // rare case of single packet but multiple mbufs.
872            mbuf_t      m = packet;
873            uint32_t    remain = length;
874            mbuf_pkthdr_setlen(packet, remain);
875            do {
876                if (remain < (UInt32) mbuf_len(m))
877                    mbuf_setlen(m, remain);
878                remain -= mbuf_len(m);
879            } while ((m = mbuf_next(m)));
880            assert(remain == 0);
881        }
882    }
883    else
884    {
885        length = mbuf_pkthdr_len(packet);
886    }
887
888    // check for special debugger packet
889    if (_remote_NMI_len) {
890       const char *data = get_icmp_data(&packet, hdrlen, _remote_NMI_len);
891
892       if (data && (memcmp(data, _remote_NMI_pattern, _remote_NMI_len) == 0)) {
893           IOKernelDebugger::signalDebugger();
894       }
895    }
896
897    // input BPF tap
898	if (_inputFilterFunc)
899		feedPacketInputTap(packet);
900
901    // frame header at start of mbuf data
902    mdata = mbuf_data(packet);
903	mbuf_pkthdr_setheader(packet, mdata);
904
905    // packet length does not include the frame header
906    mbuf_pkthdr_setlen(packet, length - hdrlen);
907
908    // adjust the mbuf data and length to skip over the frame header
909    mbuf_setdata(packet, (char *)mdata + hdrlen, mbuf_len(packet) - hdrlen);
910
911    if ( options & kInputOptionQueuePacket )
912    {
913        IOMbufQueueTailAdd(_inputPushQueue, packet, length);
914        count = 0;
915    }
916    else
917    {
918        if (!IOMbufQueueIsEmpty(_inputPushQueue))
919        {
920            IOMbufQueueTailAdd(_inputPushQueue, packet, length);
921            count = _inputPushQueue->count;
922            pushInputQueue(_inputPushQueue);
923        }
924        else
925        {
926            pushInputPacket(packet, length);
927            count = 1;
928        }
929    }
930
931    return count;
932}
933
934//------------------------------------------------------------------------------
935// Deliver an event to the network layer.
936
937bool IONetworkInterface::inputEvent(UInt32 type, void * data)
938{
939    bool      success = true;
940
941    struct {
942        kern_event_msg  header;
943        uint32_t        unit;
944        char            if_name[IFNAMSIZ];
945    } event;
946
947    const IONetworkLinkEventData * linkData;
948
949    switch (type)
950    {
951        // Deliver an IOKit defined event.
952
953        case kIONetworkEventTypeLinkUp:
954        case kIONetworkEventTypeLinkDown:
955        case kIONetworkEventTypeLinkSpeedChange:
956            // Send an event only if DLIL has a reference to this
957            // interface.
958            linkData = (const IONetworkLinkEventData *) data;
959            if (!_backingIfnet || !linkData)
960                break;
961
962            // Use link speed to report bandwidth for legacy drivers
963            if ((_configFlags & kConfigDataRates) == 0)
964            {
965                if_bandwidths_t bw;
966
967                bw.max_bw = linkData->linkSpeed;
968                bw.eff_bw = linkData->linkSpeed;
969                ifnet_set_bandwidths(_backingIfnet, &bw, &bw);
970            }
971
972            if ((type == kIONetworkEventTypeLinkUp) ||
973                (type == kIONetworkEventTypeLinkDown))
974            {
975				bzero(&event, sizeof(event));
976                event.header.total_size    = sizeof(event);
977                event.header.vendor_code   = KEV_VENDOR_APPLE;
978                event.header.kev_class     = KEV_NETWORK_CLASS;
979                event.header.kev_subclass  = KEV_DL_SUBCLASS;
980                event.header.event_code    = (type == kIONetworkEventTypeLinkUp) ?
981                                             KEV_DL_LINK_ON : KEV_DL_LINK_OFF;
982				event.header.event_data[0] = ifnet_family(_backingIfnet);
983                event.unit                 = ifnet_unit(_backingIfnet);
984                strncpy(&event.if_name[0], ifnet_name(_backingIfnet), IFNAMSIZ);
985
986                ifnet_event(_backingIfnet, &event.header);
987            }
988            break;
989
990        // Deliver a raw kernel event to DLIL.
991        // The data argument must point to a kern_event_msg structure.
992
993        case kIONetworkEventTypeDLIL:
994            ifnet_event(_backingIfnet, (struct kern_event_msg *) data);
995            break;
996
997        case kIONetworkEventWakeOnLANSupportChanged:
998            break;
999
1000        default:
1001            IOLog("IONetworkInterface: unknown event type %x\n", (uint32_t) type);
1002            success = false;
1003            break;
1004    }
1005
1006    return success;
1007}
1008
1009//------------------------------------------------------------------------------
1010// SIOCSIFMTU (set interface MTU) ioctl handler.
1011
1012SInt32 IONetworkInterface::syncSIOCSIFMTU(IONetworkController * ctr,
1013                                          struct ifreq *        ifr)
1014{
1015    SInt32  error;
1016    UInt32  newMTU = ifr->ifr_mtu;
1017
1018    // If change is not necessary, return success without getting the
1019    // controller involved.
1020
1021    if ( getMaxTransferUnit() == newMTU )
1022        return 0;
1023
1024    // Request the controller to switch MTU size.
1025
1026    error = errnoFromReturn( ctr->setMaxPacketSize(newMTU) );
1027
1028    if ( error == 0 )
1029    {
1030        // Controller reports success. Update the interface MTU size
1031        // property.
1032
1033        setMaxTransferUnit(newMTU);
1034    }
1035
1036    return error;
1037}
1038
1039//------------------------------------------------------------------------------
1040// SIOCSIFMEDIA (SET interface media) ioctl handler.
1041
1042SInt32 IONetworkInterface::syncSIOCSIFMEDIA(IONetworkController * ctr,
1043                                            struct ifreq *        ifr)
1044{
1045    OSDictionary *    mediumDict;
1046    IONetworkMedium * medium;
1047    SInt32            error;
1048
1049    mediumDict = ctr->copyMediumDictionary();  // creates a copy
1050    if ( mediumDict == 0 )
1051    {
1052        // unable to allocate memory, or no medium dictionary.
1053        return EOPNOTSUPP;
1054    }
1055
1056    do {
1057        // Look for an exact match on the media type.
1058
1059        medium = IONetworkMedium::getMediumWithType(
1060                                  mediumDict,
1061                                  ifr->ifr_media );
1062        if ( medium ) break;
1063
1064        // Try a partial match. ifconfig tool sets the media type and media
1065        // options separately. When media options are changed, the options
1066        // bits are set or cleared based on the current media selection.
1067
1068        OSSymbol * selMediumName = (OSSymbol *)
1069                                   ctr->copyProperty( kIOSelectedMedium );
1070        if ( selMediumName )
1071        {
1072            UInt32            modMediumBits;
1073            IONetworkMedium * selMedium = (IONetworkMedium *)
1074                              mediumDict->getObject( selMediumName );
1075
1076            if ( selMedium &&
1077                (modMediumBits = selMedium->getType() ^ ifr->ifr_media) )
1078            {
1079                medium = IONetworkMedium::getMediumWithType(
1080                                  mediumDict,
1081                                  ifr->ifr_media,
1082                                  ~( IFM_TMASK | IFM_NMASK | modMediumBits));
1083            }
1084
1085            selMediumName->release();
1086        }
1087        if ( medium ) break;
1088
1089        // Still no match, look for a medium that matches the network type
1090        // and sub-type.
1091
1092        medium = IONetworkMedium::getMediumWithType(
1093                                  mediumDict,
1094                                  ifr->ifr_media,
1095                                  ~( IFM_TMASK | IFM_NMASK ));
1096    } while ( false );
1097
1098    // It may be possible for the controller to update the medium
1099    // dictionary and perhaps delete the medium entry that we have
1100    // selected from our copy of the stale dictionary. This is
1101    // harmless since IONetworkController will filter out invalid
1102    // selections before calling the driver.
1103
1104    if ( medium )
1105        error = errnoFromReturn(
1106                ctr->selectMediumWithName(medium->getName()) );
1107    else
1108        error = EINVAL;
1109
1110    mediumDict->release();
1111
1112    return error;
1113}
1114
1115//------------------------------------------------------------------------------
1116// SIOCGIFMEDIA (GET interface media) ioctl handler.
1117
1118SInt32 IONetworkInterface::syncSIOCGIFMEDIA(IONetworkController * ctr,
1119                                            struct ifreq *        ifr,
1120                                            unsigned long         cmd)
1121{
1122    OSDictionary *          mediumDict  = 0;
1123    UInt                    mediumCount = 0;
1124    UInt                    maxCount;
1125    OSCollectionIterator *  iter = 0;
1126    UInt32 *                typeList;
1127    UInt                    typeListSize;
1128    OSSymbol *              keyObject;
1129    SInt32                  error = 0;
1130    struct ifmediareq *     ifmr = (struct ifmediareq *) ifr;
1131
1132    if (ifmr->ifm_count < 0)
1133        return EINVAL;
1134
1135    do {
1136        mediumDict = ctr->copyMediumDictionary();  // creates a copy
1137        if (mediumDict == 0)
1138        {
1139            error = EOPNOTSUPP;
1140            break;  // unable to allocate memory, or no medium dictionary.
1141        }
1142
1143        if ((mediumCount = mediumDict->getCount()) == 0)
1144        {
1145            error = EOPNOTSUPP;
1146            break;  // no medium in the medium dictionary
1147        }
1148
1149        // Maximum number of medium types that the caller will accept.
1150        //
1151        maxCount = ifmr->ifm_count;
1152        if (maxCount == 0)
1153            break;  //  caller is only probing for support and media count.
1154
1155        if (maxCount > mediumCount)
1156        {
1157            maxCount = mediumCount;
1158        }
1159        else if (maxCount < mediumCount)
1160        {
1161            // user buffer is too small to hold all medium entries.
1162            error = E2BIG;
1163
1164            // Proceed with partial copy on E2BIG. This follows the
1165            // SIOCGIFMEDIA handling practice in bsd/net/if_media.c.
1166            //
1167            // break;
1168        }
1169
1170        // Create an iterator to loop through the medium entries in the
1171        // dictionary.
1172        //
1173        iter = OSCollectionIterator::withCollection(mediumDict);
1174        if (!iter)
1175        {
1176            error = ENOMEM;
1177            break;
1178        }
1179
1180        // Allocate memory for the copyout buffer.
1181        //
1182        typeListSize = maxCount * sizeof(UInt32);
1183        typeList = (UInt32 *) IOMalloc(typeListSize);
1184        if (!typeList)
1185        {
1186            error = ENOMEM;
1187            break;
1188        }
1189        bzero(typeList, typeListSize);
1190
1191        // Iterate through the medium dictionary and copy the type of
1192        // each medium entry to typeList[].
1193        //
1194        mediumCount = 0;
1195        while ( (keyObject = (OSSymbol *) iter->getNextObject()) &&
1196                (mediumCount < maxCount) )
1197        {
1198            IONetworkMedium * medium = (IONetworkMedium *)
1199                                       mediumDict->getObject(keyObject);
1200            if (!medium)
1201                continue;   // should not happen!
1202
1203            typeList[mediumCount++] = medium->getType();
1204        }
1205
1206        if (mediumCount)
1207        {
1208            user_addr_t srcaddr;
1209
1210            // here's where the difference in ioctls needs to be accounted for.
1211            srcaddr = (cmd == SIOCGIFMEDIA64) ?
1212                ((struct ifmediareq64 *)ifmr)->ifmu_ulist :
1213            CAST_USER_ADDR_T(((struct ifmediareq32 *)ifmr)->ifmu_ulist);
1214            if (srcaddr != USER_ADDR_NULL) {
1215                    error = copyout((caddr_t) typeList, srcaddr, typeListSize);
1216            }
1217        }
1218
1219        IOFree(typeList, typeListSize);
1220    }
1221    while (0);
1222
1223    ifmr->ifm_active = ifmr->ifm_current = IFM_NONE;
1224    ifmr->ifm_status = 0;
1225    ifmr->ifm_count  = mediumCount;
1226
1227    // Get a copy of the controller's property table and read the
1228    // link status, current, and active medium.
1229
1230    OSDictionary * pTable = ctr->dictionaryWithProperties();
1231    if (pTable)
1232    {
1233        OSNumber * linkStatus = (OSNumber *)
1234                                pTable->getObject(kIOLinkStatus);
1235        if (linkStatus)
1236            ifmr->ifm_status = linkStatus->unsigned32BitValue();
1237
1238        if (mediumDict)
1239        {
1240            IONetworkMedium * medium;
1241            OSSymbol *        mediumName;
1242
1243            if ((mediumName = (OSSymbol *) pTable->getObject(kIOSelectedMedium))
1244               && (medium = (IONetworkMedium *)
1245                            mediumDict->getObject(mediumName)))
1246            {
1247                ifmr->ifm_current = medium->getType();
1248            }
1249
1250            if ((mediumName = (OSSymbol *) pTable->getObject(kIOActiveMedium))
1251               && (medium = (IONetworkMedium *)
1252                            mediumDict->getObject(mediumName)))
1253            {
1254                ifmr->ifm_active = medium->getType();
1255            }
1256        }
1257        pTable->release();
1258    }
1259
1260    if (iter)
1261        iter->release();
1262
1263    if (mediumDict)
1264        mediumDict->release();
1265
1266    return error;
1267}
1268
1269//------------------------------------------------------------------------------
1270// Handle ioctl commands sent to the network interface.
1271
1272SInt32 IONetworkInterface::performCommand(IONetworkController * ctr,
1273                                          unsigned long         cmd,
1274                                          void *                arg0,
1275                                          void *                arg1)
1276{
1277    struct ifreq *  ifr = (struct ifreq *) arg1;
1278    SInt32          ret = EOPNOTSUPP;
1279
1280    if ( (ifr == 0) || (ctr == 0) )
1281        return EINVAL;
1282
1283    switch ( cmd )
1284    {
1285        // Get interface MTU.
1286
1287        case SIOCGIFMTU:
1288            ifr->ifr_mtu = getMaxTransferUnit();
1289            ret = 0;    // no error
1290            break;
1291
1292        // Get interface media type and status.
1293
1294        case SIOCGIFMEDIA32:
1295        case SIOCGIFMEDIA64:
1296            ret = syncSIOCGIFMEDIA(ctr, ifr, cmd);
1297            break;
1298
1299        case SIOCSIFMTU:
1300        case SIOCSIFMEDIA:
1301        case SIOCSIFLLADDR:
1302            ret = (int) ctr->executeCommand(
1303                             this,            /* client */
1304                             (IONetworkController::Action)
1305                                &IONetworkInterface::performGatedCommand,
1306                             this,            /* target */
1307                             ctr,             /* param0 */
1308                             (void *) cmd,    /* param1 */
1309                             arg0,            /* param2 */
1310                             arg1 );          /* param3 */
1311            break;
1312
1313        default:
1314            // DLOG(%s: command not handled (%08lx), getName(), cmd);
1315            break;
1316    }
1317
1318    return ret;
1319}
1320
1321//------------------------------------------------------------------------------
1322// Perform an ioctl command on the controller's workloop context.
1323
1324int IONetworkInterface::performGatedCommand(void * target,
1325                                            void * arg1_ctr,
1326                                            void * arg2_cmd,
1327                                            void * arg3_0,
1328                                            void * arg4_1)
1329{
1330    IONetworkInterface *  self = (IONetworkInterface *)  target;
1331    IONetworkController * ctr  = (IONetworkController *) arg1_ctr;
1332    struct ifreq *        ifr  = (struct ifreq *) arg4_1;
1333    SInt32                ret  = EOPNOTSUPP;
1334
1335    // Refuse to issue I/O to the controller if it is in a power state
1336    // that renders it "unusable".
1337
1338    if ( self->getInterfaceState() & kIONetworkInterfaceDisabledState )
1339        return EPWROFF;
1340
1341    switch ( (uintptr_t) arg2_cmd )
1342    {
1343        // Set interface MTU.
1344
1345        case SIOCSIFMTU:
1346            ret = self->syncSIOCSIFMTU(ctr, ifr);
1347            break;
1348
1349        // Set interface (controller) media type.
1350
1351        case SIOCSIFMEDIA:
1352            ret = self->syncSIOCSIFMEDIA(ctr, ifr);
1353            break;
1354
1355        // Set link layer address.
1356
1357        case SIOCSIFLLADDR:
1358            ret = ctr->errnoFromReturn(
1359                  ctr->setHardwareAddress( ifr->ifr_addr.sa_data,
1360                                           ifr->ifr_addr.sa_len ) );
1361            break;
1362    }
1363
1364    return ret;
1365}
1366
1367//------------------------------------------------------------------------------
1368// if_ioctl() handler - Calls performCommand() when we receive an ioctl
1369// from DLIL.
1370
1371errno_t
1372IONetworkInterface::if_ioctl( ifnet_t ifp, unsigned long cmd, void * data )
1373{
1374	IONetworkInterface *    self = IFNET_TO_THIS(ifp);
1375    IONetworkController *   driver;
1376    errno_t                 err;
1377
1378    if (!self || self->isInactive())
1379    {
1380        return EOPNOTSUPP;
1381    }
1382
1383    driver = self->_driver;
1384    if (!driver)
1385    {
1386        return EINVAL;
1387    }
1388
1389    assert(ifp == self->_backingIfnet);
1390
1391    err = self->performCommand( driver, cmd, (void *) ifp, data );
1392    return err;
1393}
1394
1395//------------------------------------------------------------------------------
1396// if_output() handler.
1397//
1398// Handle a call from the network stack to transmit the given mbuf.
1399// For now, we can assume that the mbuf is singular, and never chained.
1400
1401int IONetworkInterface::if_output( ifnet_t ifp, mbuf_t m )
1402{
1403	UInt32      noraceTemp;
1404	int         delta;
1405	u_int32_t   outPackets, outErrors;
1406
1407	IONetworkInterface * self = IFNET_TO_THIS(ifp);
1408
1409    assert(ifp == self->_backingIfnet);
1410
1411    if ( m == 0 )
1412    {
1413        DLOG("%s: NULL output mbuf\n", self->getName());
1414        return EINVAL;
1415    }
1416
1417    if ( (mbuf_flags(m) & MBUF_PKTHDR) == 0 )
1418    {
1419        DLOG("%s: MBUF_PKTHDR bit not set\n", self->getName());
1420        mbuf_freem(m);
1421        return EINVAL;
1422    }
1423
1424    // Increment output related statistics.
1425	// update the stats that the driver maintains
1426	noraceTemp = self->_driverStats.outputErrors;
1427	delta = noraceTemp - self->_lastDriverStats.outputErrors;
1428	outErrors = ABS(delta);
1429	self->_lastDriverStats.outputErrors = noraceTemp;
1430
1431	noraceTemp = self->_driverStats.outputPackets;
1432	delta = noraceTemp - self->_lastDriverStats.outputPackets;
1433	outPackets = ABS(delta);
1434	self->_lastDriverStats.outputPackets = noraceTemp;
1435
1436	// update the stats in the interface
1437	ifnet_stat_increment_out(self->getIfnet(), outPackets, mbuf_pkthdr_len(m), outErrors);
1438
1439    // Feed the output filter tap.
1440	if(self->_outputFilterFunc)
1441		self->feedPacketOutputTap(m);
1442
1443	// Forward the packet to the registered output packet handler.
1444	return ((self->_outTarget)->*(self->_outAction))(m, 0);
1445}
1446
1447//------------------------------------------------------------------------------
1448// if_set_bpf_tap() handler. Handles request from the DLIL to enable or
1449// disable the input/output filter taps.
1450
1451errno_t IONetworkInterface::if_set_bpf_tap(
1452    ifnet_t             ifp,
1453    bpf_tap_mode        mode,
1454    bpf_packet_func     func )
1455{
1456	IONetworkInterface * self = IFNET_TO_THIS(ifp);
1457    bool changed = false;
1458
1459    assert(ifp == self->_backingIfnet);
1460    if (self->isInactive())
1461    {
1462        return 0;
1463    }
1464
1465    IOLockLock(self->_privateLock);
1466
1467    switch ( mode )
1468    {
1469        case BPF_TAP_DISABLE:
1470            changed = (self->_inputFilterFunc != 0);
1471            self->_inputFilterFunc = self->_outputFilterFunc = 0;
1472            break;
1473
1474        case BPF_TAP_INPUT:
1475            assert(func);
1476            changed = (self->_inputFilterFunc == 0);
1477            self->_inputFilterFunc = func;
1478            break;
1479
1480        case BPF_TAP_OUTPUT:
1481            assert(func);
1482            self->_outputFilterFunc = func;
1483            break;
1484
1485        case BPF_TAP_INPUT_OUTPUT:
1486            assert(func);
1487            changed = (self->_inputFilterFunc == 0);
1488            self->_inputFilterFunc = self->_outputFilterFunc = func;
1489            break;
1490
1491        default:
1492            DLOG("%s: Unknown BPF tap mode %d\n", self->getName(), mode);
1493            break;
1494    }
1495
1496    IOLockUnlock(self->_privateLock);
1497
1498    if (changed)
1499        self->notifyDriver(kIONetworkNotificationBPFTapStateChange, 0);
1500
1501    return 0;
1502}
1503
1504//------------------------------------------------------------------------------
1505
1506void IONetworkInterface::if_detach( ifnet_t ifp )
1507{
1508	IONetworkInterface * self = IFNET_TO_THIS(ifp);
1509
1510    assert(WAITING_FOR_DETACH(self) == 1);
1511    self->retain();
1512	IOLockLock(self->_privateLock);
1513	WAITING_FOR_DETACH(self) = 0;
1514	thread_wakeup((void *) self);
1515	IOLockUnlock(self->_privateLock);
1516    self->release();
1517}
1518
1519//------------------------------------------------------------------------------
1520// ifnet field (and property table) getter/setter.
1521
1522#define IO_IFNET_GET(func, type, field, kpi)                    \
1523type IONetworkInterface::func(void) const                       \
1524{                                                               \
1525    type val = (_backingIfnet != NULL) ?                        \
1526               kpi(_backingIfnet) : _##field;                   \
1527	return val;                                                 \
1528}
1529
1530#define IO_IFNET_SET(func, type, field, kpi)                    \
1531bool IONetworkInterface::func(type value)                       \
1532{                                                               \
1533    if (_backingIfnet)                                          \
1534        kpi(_backingIfnet, value);                              \
1535    else                                                        \
1536        _##field = value;                                       \
1537	return true;                                                \
1538}
1539
1540#define IO_IFNET_RMW(func, type, field, kpi)                    \
1541bool IONetworkInterface::func(type set, type clear)             \
1542{                                                               \
1543    if (_backingIfnet)                                          \
1544        kpi(_backingIfnet, set, set | clear);                   \
1545    else                                                        \
1546        _##field = (_##field & ~clear) | set;                   \
1547	return true;                                                \
1548}
1549
1550//------------------------------------------------------------------------------
1551// Interface type accessors (ifp->if_type). The list of interface types is
1552// defined in <bsd/net/if_types.h>.
1553
1554bool IONetworkInterface::setInterfaceType(UInt8 type)
1555{
1556	// once attached to dlil, we can't change the interface type
1557	if (_backingIfnet)
1558		return false;
1559	else
1560		_type = type;
1561	return true;
1562}
1563
1564UInt8 IONetworkInterface::getInterfaceType(void) const
1565{
1566    return _type;
1567}
1568
1569IO_IFNET_SET(setMaxTransferUnit, UInt32, mtu, ifnet_set_mtu)
1570IO_IFNET_GET(getMaxTransferUnit, UInt32, mtu, ifnet_mtu)
1571
1572IO_IFNET_RMW(setFlags, UInt16, flags, ifnet_set_flags)
1573IO_IFNET_GET(getFlags, UInt16, flags, ifnet_flags)
1574
1575bool IONetworkInterface::setExtraFlags( UInt32 set, UInt32 clear )
1576{
1577    _eflags = (_eflags & ~clear) | set;
1578    return true;
1579}
1580
1581IO_IFNET_GET(getExtraFlags, UInt32, eflags, ifnet_eflags)
1582
1583IO_IFNET_SET(setMediaAddressLength, UInt8, addrlen, ifnet_set_addrlen)
1584IO_IFNET_GET(getMediaAddressLength, UInt8, addrlen, ifnet_addrlen)
1585
1586IO_IFNET_SET(setMediaHeaderLength, UInt8, hdrlen, ifnet_set_hdrlen)
1587IO_IFNET_GET(getMediaHeaderLength, UInt8, hdrlen, ifnet_hdrlen)
1588
1589IO_IFNET_GET(getUnitNumber, UInt16, unit, ifnet_unit)
1590
1591bool IONetworkInterface::setUnitNumber( UInt16 value )
1592{
1593    // once we've attached to dlil, unit can't be changed
1594	if (_backingIfnet)
1595		return false;
1596
1597    if (setProperty( kIOInterfaceUnit, value, 32 ))
1598    {
1599        char name[128];
1600
1601        _unit = value;
1602		setProperty( kIOPrimaryInterface, isPrimaryInterface() );
1603        snprintf(name, sizeof(name), "%s%u", getNamePrefix(), _unit);
1604        setName(name);
1605        return true;
1606    }
1607    else
1608        return false;
1609}
1610
1611bool IONetworkInterface::setInterfaceSubType( uint32_t subType )
1612{
1613	// once attached to dlil, we can't change the interface sub-type
1614	if (_backingIfnet)
1615		return false;
1616	else
1617		_subType = subType;
1618	return true;
1619}
1620
1621//------------------------------------------------------------------------------
1622// Return true if the interface has been registered with the network layer,
1623// false otherwise.
1624
1625bool IONetworkInterface::isRegistered() const
1626{
1627    return (bool)(getInterfaceState() & kIONetworkInterfaceRegisteredState);
1628}
1629
1630//------------------------------------------------------------------------------
1631// serialize
1632
1633bool IONetworkInterface::serializeProperties( OSSerialize * s ) const
1634{
1635    IONetworkInterface * self = (IONetworkInterface *) this;
1636
1637    self->setProperty( kIOInterfaceType,       getInterfaceType(),       8 );
1638    self->setProperty( kIOMaxTransferUnit,     getMaxTransferUnit(),    32 );
1639    self->setProperty( kIOInterfaceFlags,      getFlags(),              16 );
1640    self->setProperty( kIOInterfaceExtraFlags, getExtraFlags(),         32 );
1641    self->setProperty( kIOMediaAddressLength,  getMediaAddressLength(),  8 );
1642    self->setProperty( kIOMediaHeaderLength,   getMediaHeaderLength(),   8 );
1643
1644    return super::serializeProperties( s );
1645}
1646
1647//------------------------------------------------------------------------------
1648// Return the interface state flags.
1649
1650UInt32 IONetworkInterface::getInterfaceState() const
1651{
1652    return _stateBits->unsigned32BitValue();
1653}
1654
1655//------------------------------------------------------------------------------
1656// Set (or clear) the interface state flags.
1657
1658UInt32 IONetworkInterface::setInterfaceState( UInt32 set,
1659                                              UInt32 clear )
1660{
1661    UInt32  val;
1662
1663    assert( _stateBits );
1664
1665    IOLockLock(_privateLock);
1666
1667    val = ( _stateBits->unsigned32BitValue() | set ) & ~clear;
1668    _stateBits->setValue( val );
1669
1670    IOLockUnlock(_privateLock);
1671
1672    return val;
1673}
1674
1675//------------------------------------------------------------------------------
1676// Perform a lookup of the dictionary kept by the interface,
1677// and return an entry that matches the specified string key.
1678//
1679// key: Search for an IONetworkData entry with this key.
1680//
1681// Returns the matching entry, or 0 if no match was found.
1682
1683IONetworkData * IONetworkInterface::getNetworkData(const OSSymbol * key) const
1684{
1685    return OSDynamicCast(IONetworkData, _dataDict->getObject(key));
1686}
1687
1688IONetworkData * IONetworkInterface::getNetworkData(const char * key) const
1689{
1690    return OSDynamicCast(IONetworkData, _dataDict->getObject(key));
1691}
1692
1693//------------------------------------------------------------------------------
1694// A private function to copy the data dictionary to the property table.
1695
1696bool IONetworkInterface::_syncNetworkDataDict()
1697{
1698    OSDictionary * aCopy = OSDictionary::withDictionary(_dataDict);
1699    bool           ret   = false;
1700
1701    if (aCopy) {
1702        ret = setProperty(kIONetworkData, aCopy);
1703        aCopy->release();
1704    }
1705
1706    return ret;
1707}
1708
1709//------------------------------------------------------------------------------
1710// Remove an entry from the IONetworkData dictionary managed by the interface.
1711// The removed object is released.
1712
1713bool IONetworkInterface::removeNetworkData(const OSSymbol * aKey)
1714{
1715    bool ret;
1716
1717    IOLockLock(_privateLock);
1718    _dataDict->removeObject(aKey);
1719    ret = _syncNetworkDataDict();
1720    IOLockUnlock(_privateLock);
1721    return ret;
1722}
1723
1724bool IONetworkInterface::removeNetworkData(const char * aKey)
1725{
1726    bool ret;
1727
1728    IOLockLock(_privateLock);
1729    _dataDict->removeObject(aKey);
1730    ret = _syncNetworkDataDict();
1731    IOLockUnlock(_privateLock);
1732    return ret;
1733}
1734
1735//------------------------------------------------------------------------------
1736// Add an IONetworkData object to a dictionary managed by the interface.
1737
1738bool IONetworkInterface::addNetworkData(IONetworkData * aData)
1739{
1740    bool ret = false;
1741
1742    if (OSDynamicCast(IONetworkData, aData) == 0)
1743        return false;
1744
1745    IOLockLock(_privateLock);
1746    if (_dataDict->setObject(aData->getKey(), aData))
1747        ret = _syncNetworkDataDict();
1748    IOLockUnlock(_privateLock);
1749    return ret;
1750}
1751
1752//------------------------------------------------------------------------------
1753// Create a new IOUserClient to handle client requests. The default
1754// implementation will create an IONetworkUserClient instance if
1755// the type given is kIONetworkUserClientTypeID.
1756
1757IOReturn IONetworkInterface::newUserClient(task_t           owningTask,
1758                                           void *         /*security_id*/,
1759                                           UInt32           type,
1760                                           IOUserClient **  handler)
1761{
1762    IOReturn              err = kIOReturnSuccess;
1763    IONetworkUserClient * client;
1764
1765    if (type != kIONetworkUserClientTypeID)
1766        return kIOReturnBadArgument;
1767
1768    client = IONetworkUserClient::withTask(owningTask);
1769
1770    if (!client || !client->attach(this) || !client->start(this))
1771    {
1772        if (client)
1773        {
1774            client->detach(this);
1775            client->release();
1776            client = 0;
1777        }
1778        err = kIOReturnNoMemory;
1779    }
1780
1781    *handler = client;
1782
1783    return err;
1784}
1785
1786//------------------------------------------------------------------------------
1787// Power change notices are posted by the controller's policy-maker to
1788// inform the interface that the controller is changing power states.
1789// There are two notifications for each state change, delivered prior
1790// to the state change, and after the state change has occurred.
1791
1792struct IONetworkPowerChangeNotice {
1793    IOService *    policyMaker;
1794    IOPMPowerFlags powerFlags;
1795    uint32_t       stateNumber;
1796    uint32_t       phase;
1797};
1798
1799enum {
1800    kPhasePowerStateWillChange = 0x01,
1801    kPhasePowerStateDidChange  = 0x02
1802};
1803
1804//------------------------------------------------------------------------------
1805// Handle controller's power state transitions.
1806
1807IOReturn
1808IONetworkInterface::controllerWillChangePowerState(
1809                              IONetworkController * controller,
1810                              IOPMPowerFlags        flags,
1811                              UInt32                stateNumber,
1812                              IOService *           policyMaker )
1813{
1814    if ( ( flags & IOPMDeviceUsable ) == 0 )
1815    {
1816        setInterfaceState( kIONetworkInterfaceDisabledState );
1817    }
1818    return kIOReturnSuccess;
1819}
1820
1821IOReturn
1822IONetworkInterface::controllerDidChangePowerState(
1823                              IONetworkController * controller,
1824                              IOPMPowerFlags        flags,
1825                              UInt32                stateNumber,
1826                              IOService *           policyMaker )
1827{
1828    if ( flags & IOPMDeviceUsable )
1829    {
1830        setInterfaceState( 0, kIONetworkInterfaceDisabledState );
1831    }
1832    return kIOReturnSuccess;
1833}
1834
1835//------------------------------------------------------------------------------
1836// Static member functions called by power-management notification handlers.
1837// Act as stub functions that will simply forward the call to virtual member
1838// functions.
1839
1840void
1841IONetworkInterface::powerChangeHandler( void * target,
1842                                        void * param0,
1843                                        void * param1  )
1844{
1845    IONetworkInterface * self = (IONetworkInterface *) target;
1846	IONetworkPowerChangeNotice * notice;
1847
1848    assert( self );
1849    if (!self->_driver)
1850        return;
1851
1852    if ( param1 == 0 )
1853    {
1854        // Issue a call to this same function synchronized with the
1855        // work loop thread.
1856
1857        self->_driver->executeCommand(
1858              /* client */ self,
1859              /* action */ (IONetworkController::Action) &powerChangeHandler,
1860              /* target */ self,
1861              /* param0 */ param0,
1862              /* param1 */ (void *) true );
1863
1864        return;
1865    }
1866
1867    notice = (IONetworkPowerChangeNotice *) param0;
1868    assert( notice );
1869
1870    DLOG("%s: power change flags:%08x state:%d from:%p phase:%d\n",
1871         self->getName(), (uint32_t) notice->powerFlags,
1872         notice->stateNumber, notice->policyMaker, notice->phase );
1873
1874    if ( notice->phase == kPhasePowerStateWillChange )
1875    {
1876        self->controllerWillChangePowerState(
1877              self->_driver,
1878              notice->powerFlags,
1879              notice->stateNumber,
1880              notice->policyMaker );
1881    }
1882    else if ( notice->phase == kPhasePowerStateDidChange )
1883    {
1884        self->controllerDidChangePowerState(
1885              self->_driver,
1886              notice->powerFlags,
1887              notice->stateNumber,
1888              notice->policyMaker );
1889    }
1890}
1891
1892//------------------------------------------------------------------------------
1893// Handle notitifications triggered by controller's power state change.
1894
1895IOReturn
1896IONetworkInterface::powerStateWillChangeTo( IOPMPowerFlags  powerFlags,
1897                                            unsigned long   stateNumber,
1898                                            IOService *     policyMaker )
1899{
1900    IONetworkPowerChangeNotice  notice;
1901
1902    notice.policyMaker = policyMaker;
1903    notice.powerFlags  = powerFlags;
1904    notice.stateNumber = stateNumber;
1905    notice.phase       = kPhasePowerStateWillChange;
1906
1907    powerChangeHandler( (void *) this, (void *) &notice,
1908                        /* param1: inside gate */ (void *) false );
1909    return kIOPMAckImplied;
1910}
1911
1912IOReturn
1913IONetworkInterface::powerStateDidChangeTo( IOPMPowerFlags  powerFlags,
1914                                           unsigned long   stateNumber,
1915                                           IOService *     policyMaker )
1916{
1917    IONetworkPowerChangeNotice  notice;
1918
1919    notice.policyMaker = policyMaker;
1920    notice.powerFlags  = powerFlags;
1921    notice.stateNumber = stateNumber;
1922    notice.phase       = kPhasePowerStateDidChange;
1923
1924    powerChangeHandler( (void *) this, (void *) &notice,
1925                        /* param1: inside gate */ (void *) false );
1926    return kIOPMAckImplied;
1927}
1928
1929//------------------------------------------------------------------------------
1930
1931IOReturn IONetworkInterface::message( UInt32 type, IOService * provider,
1932                                      void * argument )
1933{
1934    if (kMessageControllerWillShutdown == type)
1935    {
1936        // Handle system shutdown or restarts. Handle this by performing the
1937        // same work when driver is transitioning to an unusable power state.
1938
1939        DLOG("%s: kMessageControllerWillShutdown\n", getName());
1940        haltOutputThread( kTxThreadStateDetach );
1941        powerStateWillChangeTo( 0, 0, NULL );
1942        return kIOReturnSuccess;
1943    }
1944
1945    return super::message( type, provider, argument );
1946}
1947
1948//------------------------------------------------------------------------------
1949// Termination
1950
1951bool IONetworkInterface::requestTerminate(
1952    IOService *     provider,
1953    IOOptionBits    options )
1954{
1955#if EVALUATE_FOR_LATER_REMOVAL
1956    // Early indication that provider started termination
1957    if (provider == _driver)
1958    {
1959        // Stop transmit thread before a later disable by the
1960        // driver on work loop context, which can deadlock.
1961
1962        DLOG("%s::requestTerminate(%s)\n",
1963            getName(), provider->getName());
1964        haltOutputThread( kTxThreadStateDetach );
1965    }
1966#endif
1967
1968    return super::requestTerminate(provider, options);
1969}
1970
1971bool IONetworkInterface::willTerminate( IOService *  provider,
1972                                        IOOptionBits options )
1973{
1974    DLOG("%s::%s(%s, 0x%x)\n", getName(), __FUNCTION__,
1975        provider->getName(), (uint32_t) options);
1976
1977    setInterfaceState( kIONetworkInterfaceDisabledState );
1978    return super::willTerminate( provider, options );
1979}
1980
1981//------------------------------------------------------------------------------
1982// Inlined functions pulled from header file to ensure
1983// binary compatibility with drivers built with gcc2.95.
1984
1985IONetworkData * IONetworkInterface::getParameter(const char * aKey) const
1986{ return getNetworkData(aKey); }
1987
1988bool IONetworkInterface::setExtendedFlags(UInt32 flags, UInt32 clear)
1989{ return true; }
1990
1991//------------------------------------------------------------------------------
1992
1993ifnet_t IONetworkInterface::getIfnet( void ) const
1994{
1995	return _backingIfnet;
1996}
1997
1998OSMetaClassDefineReservedUsed(IONetworkInterface, 0);
1999
2000IOReturn IONetworkInterface::attachToDataLinkLayer( IOOptionBits options,
2001                                                    void *       parameter )
2002{
2003    ifnet_init_params       params;
2004    ifnet_init_eparams      eparams;
2005	struct sockaddr_dl *    ll_addr = 0;
2006	char                    buffer[2 * sizeof(struct sockaddr_dl)];
2007    errno_t                 error;
2008    OSObject *              prop;
2009    IOReturn                result = kIOReturnInternalError;
2010
2011    if (!_driver)
2012    {
2013        LOG("%s: BSD attach failed, no driver\n", getName());
2014        goto fail;
2015    }
2016
2017	memset(&params, 0, sizeof(params));
2018    if (!initIfnetParams(&params))
2019    {
2020        LOG("%s: initIfnetParams failed\n", getName());
2021        goto fail;
2022    }
2023
2024    memset(&eparams, 0, sizeof(eparams));
2025
2026    IOLockLock(_privateLock);
2027    _configFlags |= kConfigFrozen;
2028
2029    // Pass ifnet_init_params to subclass which is then converted to
2030    // the new ifnet_init_eparams. All this to avoid burning another
2031    // vtable pad slot, and subclasses don't need to change.
2032
2033    eparams.ver             = IFNET_INIT_CURRENT_VERSION;
2034    eparams.len             = sizeof(eparams);
2035
2036    eparams.uniqueid        = params.uniqueid;
2037    eparams.uniqueid_len    = params.uniqueid_len;
2038    eparams.name            = params.name;
2039    eparams.unit            = params.unit;
2040    eparams.family          = params.family;
2041    eparams.type            = params.type;
2042    eparams.subfamily       = _subType;
2043
2044    eparams.demux           = params.demux;
2045    eparams.add_proto       = params.add_proto;
2046    eparams.del_proto       = params.del_proto;
2047    eparams.check_multi     = params.check_multi;
2048    eparams.framer          = params.framer;
2049    eparams.softc           = params.softc;
2050    eparams.ioctl           = params.ioctl;
2051    eparams.set_bpf_tap     = params.set_bpf_tap;
2052    eparams.detach          = params.detach;
2053    eparams.event           = params.event;
2054    eparams.broadcast_addr  = params.broadcast_addr;
2055    eparams.broadcast_len   = params.broadcast_len;
2056
2057    if (!(_configFlags & kConfigRxPoll) &&
2058        !(_configFlags & kConfigTxPull))
2059    {
2060        eparams.flags       = IFNET_INIT_LEGACY;
2061    }
2062
2063    if (_configFlags & kConfigRxPoll)
2064    {
2065        eparams.flags       = IFNET_INIT_INPUT_POLL;
2066        eparams.input_ctl   = if_input_ctl;
2067        eparams.input_poll  = (_rxPollOptions & kIONetworkWorkLoopSynchronous) ?
2068                              if_input_poll_gated : if_input_poll;
2069
2070        // cache the driver's inputPacketPoll action
2071        _rxPollAction = (void *) OSMemberFunctionCast(
2072            IONetworkController::Action,
2073            _driver, &IONetworkController::pollInputPackets);
2074
2075        _rxCtlAction =  (void *) OSMemberFunctionCast(
2076            IONetworkController::Action,
2077            this, &IONetworkInterface::actionInputCtl);
2078
2079        DLOG("%s: supports input polling\n", getName());
2080    }
2081
2082    if (_configFlags & kConfigTxPull)
2083    {
2084        eparams.sndq_maxlen = _txQueueSize;
2085        if (_txQueueSize)
2086            DLOG("%s: sndq_maxlen = %u\n", getName(), _txQueueSize);
2087
2088        eparams.output_sched_model = _txSchedulingModel;
2089
2090        if (_txPullOptions & kIONetworkWorkLoopSynchronous)
2091        {
2092            eparams.start   = if_start_gated;
2093
2094            // retain work loop for transmitThreadStop()
2095            _txWorkLoop = _driver->getWorkLoop();
2096            if (!_txWorkLoop)
2097            {
2098                IOLockUnlock(_privateLock);
2099                goto fail;
2100            }
2101            _txWorkLoop->retain();
2102
2103            _txStartAction = (void *) OSMemberFunctionCast(
2104                IONetworkController::Action,
2105                this, &IONetworkInterface::drainOutputQueue);
2106        }
2107        else
2108        {
2109            eparams.start   = if_start;
2110        }
2111
2112        if (_configFlags & kConfigPreEnqueue)
2113        {
2114            eparams.pre_enqueue = if_output_pre_enqueue;
2115        }
2116
2117        DLOG("%s: supports %stransmit pull, pre_enqueue %d\n",
2118            getName(), _txWorkLoop ? "gated " : "", (eparams.pre_enqueue != 0));
2119    }
2120    else
2121    {
2122        eparams.output      = params.output;
2123    }
2124
2125    eparams.output_ctl      = if_output_ctl;
2126
2127    // u_int64_t output_bw
2128    // u_int64_t input_bw
2129
2130    IOLockUnlock(_privateLock);
2131
2132    error = ifnet_allocate_extended(&eparams, &_backingIfnet);
2133    if (error)
2134    {
2135        LOG("%s: ifnet_allocate_extended error %d\n", getName(), error);
2136        goto fail;
2137    }
2138
2139	error = ifnet_set_offload(_backingIfnet,
2140            getIfnetHardwareAssistValue(_driver));
2141    if (error)
2142        LOG("%s: ifnet_set_offload error %d\n", getName(), error);
2143
2144    prop = _driver->copyProperty(kIOMACAddress);
2145    if (prop)
2146    {
2147		OSData *    macAddr = OSDynamicCast(OSData, prop);
2148        uint32_t    len;
2149
2150        memset(buffer, 0, sizeof(buffer));
2151        len = sizeof(buffer) - offsetof(struct sockaddr_dl, sdl_data);
2152
2153        if (macAddr && macAddr->getLength() && (macAddr->getLength() <= len))
2154        {
2155            len = macAddr->getLength();
2156            ll_addr = (struct sockaddr_dl *) buffer;
2157            bcopy(macAddr->getBytesNoCopy(), ll_addr->sdl_data, len);
2158            ll_addr->sdl_len = offsetof(struct sockaddr_dl, sdl_data) + len;
2159            ll_addr->sdl_family = AF_LINK;
2160            ll_addr->sdl_alen = len;
2161        }
2162        prop->release();
2163
2164        if (!ll_addr)
2165        {
2166            LOG("%s: BSD attach failed, bad MAC address\n", getName());
2167            goto fail;
2168        }
2169    }
2170
2171	ifnet_set_mtu(_backingIfnet, _mtu);
2172	ifnet_set_flags(_backingIfnet, _flags, 0xffff);
2173	ifnet_set_addrlen(_backingIfnet, _addrlen);
2174	ifnet_set_hdrlen(_backingIfnet, _hdrlen);
2175    if (_configFlags & kConfigRxPoll)
2176        ifnet_set_rcvq_maxlen(_backingIfnet, _rxRingSize);
2177
2178    error = ifnet_attach(_backingIfnet, ll_addr);
2179    if (!error)
2180        result = kIOReturnSuccess;
2181    else
2182        LOG("%s: ifnet_attach error %d\n", getName(), error);
2183
2184fail:
2185    if ((result != kIOReturnSuccess) && _backingIfnet)
2186    {
2187        // attach failed, clean up
2188        ifnet_release(_backingIfnet);
2189        _backingIfnet = NULL;
2190    }
2191
2192    return result;
2193}
2194
2195//------------------------------------------------------------------------------
2196
2197OSMetaClassDefineReservedUsed(IONetworkInterface, 1);
2198
2199void IONetworkInterface::detachFromDataLinkLayer(
2200    IOOptionBits options, void * parameter )
2201{
2202    // Running on thread call context
2203    // Permanently halt the transmit thread before ifnet detach
2204    DLOG("%s: detachFromDataLinkLayer\n", getName());
2205    haltOutputThread( kTxThreadStateDetach );
2206
2207    WAITING_FOR_DETACH(this) = true;
2208
2209    // this will lead to another thread calling if_detach()
2210	ifnet_detach(_backingIfnet);
2211
2212    // protect against if_detach() running before we block
2213	IOLockLock(_privateLock);
2214    while (WAITING_FOR_DETACH(this)) // if false, if_detach is done
2215    {
2216        IOLockSleep(_privateLock, this, THREAD_UNINT);
2217    }
2218	IOLockUnlock(_privateLock);
2219}
2220
2221//------------------------------------------------------------------------------
2222
2223void IONetworkInterface::debuggerRegistered( void )
2224{
2225    char buffer[REMOTE_NMI_PATTERN_LEN + 2];
2226    unsigned int i;
2227
2228    if (_remote_NMI_len)
2229        return;
2230
2231    memset(buffer, 0, sizeof(buffer));
2232    if (!PE_parse_boot_argn(kRemoteNMI, buffer, sizeof(buffer)))
2233        return;
2234
2235    for (i = 0; i < (REMOTE_NMI_PATTERN_LEN >> 1); i++) {
2236        unsigned int val;
2237
2238        if (sscanf(buffer + (i << 1), "%02X", &val) != 1)
2239            break;
2240
2241        buffer[i] = val;
2242    }
2243
2244    _remote_NMI_pattern = (char *) IOMalloc(sizeof(char) * i + 1);
2245    if (!_remote_NMI_pattern)
2246        return;
2247
2248    _remote_NMI_pattern[i] = '\0';
2249    memcpy(_remote_NMI_pattern, buffer, i);
2250    _remote_NMI_len = i;
2251}
2252
2253//------------------------------------------------------------------------------
2254
2255void IONetworkInterface::reportDataTransferRates(
2256    uint64_t    outputRateMax,
2257    uint64_t    inputRateMax,
2258    uint64_t    outputRateEffective,
2259    uint64_t    inputRateEffective )
2260{
2261    if_bandwidths_t bw_out, bw_in;
2262
2263    if ((_configFlags & kConfigDataRates) == 0)
2264    {
2265        IOLockLock(_privateLock);
2266        _configFlags |= kConfigDataRates;
2267        IOLockUnlock(_privateLock);
2268    }
2269
2270    if (!outputRateEffective)
2271        outputRateEffective = outputRateMax;
2272    if (!inputRateEffective)
2273        inputRateEffective = inputRateMax;
2274
2275    bw_out.max_bw = outputRateMax;
2276    bw_out.eff_bw = outputRateEffective;
2277    bw_in.max_bw  = inputRateMax;
2278    bw_in.eff_bw  = inputRateEffective;
2279
2280    if (_backingIfnet)
2281        ifnet_set_bandwidths(_backingIfnet, &bw_out, &bw_in);
2282}
2283
2284//------------------------------------------------------------------------------
2285// Driver-pull output model
2286//------------------------------------------------------------------------------
2287
2288IOReturn IONetworkInterface::configureOutputPullModel(
2289    uint32_t       driverQueueSize,
2290    IOOptionBits   options,
2291    uint32_t       outputQueueSize,
2292    uint32_t       outputSchedulingModel )
2293{
2294    IOReturn ret = kIOReturnError;
2295
2296    IOLockLock(_privateLock);
2297    if ((_configFlags & kConfigFrozen) == 0)
2298    {
2299        _txRingSize         = driverQueueSize;
2300        _txPullOptions      = options;
2301        _txQueueSize        = outputQueueSize;
2302        _txSchedulingModel  = outputSchedulingModel;
2303        _configFlags       |= kConfigTxPull;
2304        ret = kIOReturnSuccess;
2305    }
2306    IOLockUnlock(_privateLock);
2307
2308    return ret;
2309}
2310
2311IOReturn IONetworkInterface::installOutputPreEnqueueHandler(
2312    OutputPreEnqueueHandler handler,
2313    void *                  target,
2314    void *                  refCon )
2315{
2316    IOReturn ret = kIOReturnError;
2317
2318    if (!handler)
2319        return kIOReturnBadArgument;
2320
2321    IOLockLock(_privateLock);
2322    if ((_configFlags & kConfigFrozen) == 0)
2323    {
2324        _peqHandler   = handler;
2325        _peqTarget    = target;
2326        _peqRefcon    = refCon;
2327        _configFlags |= kConfigPreEnqueue;
2328        ret = kIOReturnSuccess;
2329    }
2330    IOLockUnlock(_privateLock);
2331
2332    return ret;
2333}
2334
2335errno_t IONetworkInterface::if_output_pre_enqueue( ifnet_t ifp, mbuf_t packet )
2336{
2337    IONetworkInterface *    me = IFNET_TO_THIS(ifp);
2338    errno_t                 ret;
2339
2340    assert(ifp == me->_backingIfnet);
2341    assert(me->_peqHandler);
2342
2343    ret = me->_peqHandler(me->_peqTarget, me->_peqRefcon, packet);
2344    return ret;
2345}
2346
2347int IONetworkInterface::if_start_precheck( ifnet_t ifp )
2348{
2349    int halted = 0;
2350
2351    if (__builtin_expect((_txThreadState != 0), 0))
2352    {
2353        IOLockLock(_privateLock);
2354        if (_txThreadState & kTxThreadStateInit)
2355        {
2356            // The initial if_start call
2357            assert(_txStartThread == 0);
2358            _txStartThread = current_thread();
2359            _txThreadState &= ~kTxThreadStateInit;
2360        }
2361        if (_txThreadState & (kTxThreadStateStop | kTxThreadStateDetach))
2362        {
2363            // Disable request or interface detached from DLIL
2364            _txThreadState &= ~kTxThreadStateStop;
2365            _txThreadState |=  kTxThreadStateHalted;
2366            thread_wakeup(&_txThreadState);
2367        }
2368        if (_txThreadState & kTxThreadStateHalted)
2369        {
2370            halted = true;
2371        }
2372        IOLockUnlock(_privateLock);
2373
2374        if (halted)
2375        {
2376            // Thread will be halted before we drop our open/retain
2377            // on the controller.
2378            if (_txThreadState & kTxThreadStatePurge)
2379                ifnet_purge(ifp);
2380        }
2381    }
2382
2383    return halted;
2384}
2385
2386void IONetworkInterface::if_start( ifnet_t ifp )
2387{
2388    IONetworkInterface *    me = IFNET_TO_THIS(ifp);
2389    IONetworkController *   driver;
2390
2391    assert(ifp == me->_backingIfnet);
2392    if (me->if_start_precheck(ifp))
2393        return;
2394
2395    driver = me->_driver;
2396    assert(driver);
2397    if (__builtin_expect(!driver, 0))
2398    {
2399        IOLockLock(me->_privateLock);
2400        me->_txThreadState |= kTxThreadStateHalted;
2401        IOLockUnlock(me->_privateLock);
2402        return;
2403    }
2404
2405    me->drainOutputQueue(ifp, driver);
2406}
2407
2408void IONetworkInterface::if_start_gated( ifnet_t ifp )
2409{
2410    IONetworkInterface *    me = IFNET_TO_THIS(ifp);
2411    IONetworkController *   driver;
2412
2413    assert(ifp == me->_backingIfnet);
2414    if (me->if_start_precheck(ifp))
2415        return;
2416
2417    driver = me->_driver;
2418    assert(driver);
2419    if (__builtin_expect(!driver, 0))
2420    {
2421        IOLockLock(me->_privateLock);
2422        me->_txThreadState |= kTxThreadStateHalted;
2423        IOLockUnlock(me->_privateLock);
2424        return;
2425    }
2426
2427    driver->executeCommand(
2428            /* client */ me,
2429            /* action */ (IONetworkController::Action) me->_txStartAction,
2430            /* target */ me,
2431            /* param0 */ ifp,
2432            /* param1 */ driver,
2433            /* param2 */ 0,
2434            /* param3 */ 0 );
2435}
2436
2437//------------------------------------------------------------------------------
2438
2439errno_t IONetworkInterface::enqueueOutputPacket( mbuf_t packet, IOOptionBits options )
2440{
2441    return ifnet_enqueue(_backingIfnet, packet);
2442}
2443
2444//------------------------------------------------------------------------------
2445
2446void IONetworkInterface::drainOutputQueue(
2447    ifnet_t                 ifp,
2448    IONetworkController *   driver )
2449{
2450    uint32_t                count;
2451    IOReturn                status;
2452
2453    while (true)
2454    {
2455        // check for queue empty
2456        if (ifnet_get_sndq_len(ifp, &count) || !count)
2457            break;
2458
2459        _txThreadFlags = 0;
2460        status = driver->outputStart(this, 0);
2461
2462        if (kIOReturnSuccess != status)
2463        {
2464            if (kIOReturnNoResources == status)
2465            {
2466                // Try again on next packet enqueue, or when driver
2467                // calls outputThreadSignal().
2468                // Retry transmit if preempted by outputThreadSignal()
2469
2470                if (OSCompareAndSwap(0, kTxThreadWakeupEnable, &_txThreadFlags))
2471                    break;
2472            }
2473            else
2474            {
2475                // Driver error, or dequeue failed
2476                break;
2477            }
2478        }
2479    }
2480}
2481
2482//------------------------------------------------------------------------------
2483
2484IOReturn IONetworkInterface::dequeueOutputPackets(
2485    uint32_t                maxCount,
2486    mbuf_t *                packetHead,
2487    mbuf_t *                packetTail,
2488    uint32_t *              packetCount,
2489    uint64_t *              packetBytes )
2490{
2491    uint32_t    txByteCount, temp, txPackets = 0, txErrors = 0;
2492    int         delta;
2493    errno_t     error;
2494
2495    if (!maxCount || !packetHead)
2496        return kIOReturnBadArgument;
2497
2498    if (_txThreadState & (kTxThreadStateInit | kTxThreadStateDetach))
2499    {
2500        goto no_frames;
2501    }
2502
2503    assert(_backingIfnet);
2504
2505    if (maxCount == 1)
2506    {
2507        error = ifnet_dequeue(_backingIfnet, packetHead);
2508        if (!error)
2509        {
2510            if (packetTail)
2511                *packetTail = *packetHead;
2512            if (packetCount)
2513                *packetCount = 1;
2514            txByteCount  = mbuf_pkthdr_len(*packetHead);
2515        }
2516    }
2517    else
2518    {
2519        error = ifnet_dequeue_multi(
2520                    _backingIfnet, maxCount,
2521                    packetHead, packetTail, packetCount, &txByteCount);
2522    }
2523    if (error)
2524        goto no_frames;
2525
2526    // feed output tap
2527    if (_outputFilterFunc)
2528    {
2529        mbuf_t  m, n;
2530
2531        m = *packetHead;
2532        assert(m);
2533        assert((mbuf_flags(m) & MBUF_PKTHDR));
2534
2535        for (n = m; n != 0; n = mbuf_nextpkt(n))
2536            feedPacketOutputTap(n);
2537    }
2538
2539    if (_txThreadSignal != _txThreadSignalLast)
2540    {
2541        // Update the stats that the driver maintains
2542        temp = _driverStats.outputErrors;
2543        delta = temp - _lastDriverStats.outputErrors;
2544        if (delta)
2545        {
2546            txErrors = ABS(delta);
2547            _lastDriverStats.outputErrors = temp;
2548        }
2549
2550        temp = _driverStats.outputPackets;
2551        delta = temp - _lastDriverStats.outputPackets;
2552        txPackets = ABS(delta);
2553        _lastDriverStats.outputPackets = temp;
2554        _txThreadSignalLast = _txThreadSignal;
2555    }
2556
2557    // update interface output byte count
2558    ifnet_stat_increment_out(_backingIfnet, txPackets, txByteCount, txErrors);
2559    if (packetBytes)
2560        *packetBytes = txByteCount;
2561
2562    return kIOReturnSuccess;
2563
2564no_frames:
2565    *packetHead  = 0;
2566    if (packetTail)
2567        packetTail = 0;
2568    if (packetCount)
2569        packetCount = 0;
2570    if (packetBytes)
2571        packetBytes = 0;
2572    return kIOReturnNoFrames;
2573}
2574
2575IOReturn IONetworkInterface::dequeueOutputPacketsWithServiceClass(
2576    uint32_t                maxCount,
2577    IOMbufServiceClass      serviceClass,
2578    mbuf_t *                packetHead,
2579    mbuf_t *                packetTail,
2580    uint32_t *              packetCount,
2581    uint64_t *              packetBytes )
2582{
2583    uint32_t            txByteCount, temp, txPackets = 0, txErrors = 0;
2584    int                 delta;
2585    mbuf_svc_class_t    mbufSC;
2586    errno_t             error;
2587
2588    if (!maxCount || !packetHead)
2589        return kIOReturnBadArgument;
2590
2591    if (_txThreadState & (kTxThreadStateInit | kTxThreadStateDetach))
2592    {
2593        goto no_frames;
2594    }
2595
2596    assert(_backingIfnet);
2597
2598    // convert from I/O Kit SC to mbuf SC
2599    switch (serviceClass)
2600    {
2601        case kIOMbufServiceClassBE:    mbufSC = MBUF_SC_BE;  break;
2602        case kIOMbufServiceClassBKSYS: mbufSC = MBUF_SC_BK_SYS; break;
2603        case kIOMbufServiceClassBK:    mbufSC = MBUF_SC_BK;  break;
2604        case kIOMbufServiceClassRD:    mbufSC = MBUF_SC_RD;  break;
2605        case kIOMbufServiceClassOAM:   mbufSC = MBUF_SC_OAM; break;
2606        case kIOMbufServiceClassAV:    mbufSC = MBUF_SC_AV;  break;
2607        case kIOMbufServiceClassRV:    mbufSC = MBUF_SC_RV;  break;
2608        case kIOMbufServiceClassVI:    mbufSC = MBUF_SC_VI;  break;
2609        case kIOMbufServiceClassVO:    mbufSC = MBUF_SC_VO;  break;
2610        case kIOMbufServiceClassCTL:   mbufSC = MBUF_SC_CTL; break;
2611        default:
2612            return kIOReturnBadArgument;
2613    }
2614
2615    if (maxCount == 1)
2616    {
2617        error = ifnet_dequeue_service_class(
2618                    _backingIfnet, mbufSC, packetHead);
2619        if (!error)
2620        {
2621            if (packetTail)
2622                *packetTail = *packetHead;
2623            if (packetCount)
2624                *packetCount = 1;
2625            txByteCount  = mbuf_pkthdr_len(*packetHead);
2626        }
2627    }
2628    else
2629    {
2630        error = ifnet_dequeue_service_class_multi(
2631                    _backingIfnet, mbufSC, maxCount,
2632                    packetHead, packetTail, packetCount, &txByteCount);
2633    }
2634    if (error)
2635        goto no_frames;
2636
2637    // feed output tap
2638    if (_outputFilterFunc)
2639    {
2640        mbuf_t  m, n;
2641
2642        m = *packetHead;
2643        assert(m);
2644        assert((mbuf_flags(m) & MBUF_PKTHDR));
2645
2646        for (n = m; n != 0; n = mbuf_nextpkt(n))
2647            feedPacketOutputTap(n);
2648    }
2649
2650    if (_txThreadSignal != _txThreadSignalLast)
2651    {
2652        // Update the stats that the driver maintains
2653        temp = _driverStats.outputErrors;
2654        delta = temp - _lastDriverStats.outputErrors;
2655        if (delta)
2656        {
2657            txErrors = ABS(delta);
2658            _lastDriverStats.outputErrors = temp;
2659        }
2660
2661        temp = _driverStats.outputPackets;
2662        delta = temp - _lastDriverStats.outputPackets;
2663        txPackets = ABS(delta);
2664        _lastDriverStats.outputPackets = temp;
2665        _txThreadSignalLast = _txThreadSignal;
2666    }
2667
2668    // update interface output byte count
2669    ifnet_stat_increment_out(_backingIfnet, txPackets, txByteCount, txErrors);
2670    if (packetBytes)
2671        *packetBytes = txByteCount;
2672
2673    return kIOReturnSuccess;
2674
2675no_frames:
2676    *packetHead  = 0;
2677    if (packetTail)
2678        packetTail = 0;
2679    if (packetCount)
2680        packetCount = 0;
2681    if (packetBytes)
2682        packetBytes = 0;
2683    return kIOReturnNoFrames;
2684}
2685
2686//------------------------------------------------------------------------------
2687
2688void IONetworkInterface::signalOutputThread( IOOptionBits options )
2689{
2690    // Unconditionally signal completion, to trigger drain loop retry
2691    UInt32 old = OSBitOrAtomic(kTxThreadWakeupSignal, &_txThreadFlags);
2692
2693    // Interface detached from network stack
2694    if (_txThreadState & (kTxThreadStateInit | kTxThreadStateDetach))
2695    {
2696        return;
2697    }
2698
2699    // Only wake if_start thread if drain loop left wakeup enabled
2700    if ((old & kTxThreadWakeupMask) == kTxThreadWakeupEnable)
2701    {
2702        assert(_backingIfnet);
2703        ifnet_start(_backingIfnet);
2704    }
2705
2706    _txThreadSignal++;
2707}
2708
2709//------------------------------------------------------------------------------
2710
2711IOReturn IONetworkInterface::startOutputThread( IOOptionBits options )
2712{
2713    const uint32_t  mask  = (kTxThreadStateHalted | kTxThreadStateStop);
2714    IOReturn        error = kIOReturnUnsupported;
2715    bool            purge = false;
2716
2717    DLOG("%s: %s(0x%x)\n",
2718        getName(), __FUNCTION__, _txThreadState);
2719
2720    IOLockLock(_privateLock);
2721    if (_txThreadState & kTxThreadStateDetach)
2722    {
2723        error = kIOReturnNotAttached;
2724    }
2725    else
2726    {
2727        error = kIOReturnSuccess;
2728        purge = ((_txThreadState & kTxThreadStatePurge) != 0);
2729        _txThreadState &= ~kTxThreadStatePurge;
2730
2731        if (_txThreadState & mask)
2732        {
2733            _txThreadState &= ~mask;
2734
2735            // No need to kick if_start thread if it hasn't called us yet.
2736            // This safety check covers the time before ifnet_attach.
2737
2738            if ((_txThreadState & kTxThreadStateInit) == 0)
2739            {
2740                assert(_backingIfnet);
2741                if (purge)
2742                    ifnet_purge(_backingIfnet);
2743                ifnet_start(_backingIfnet);
2744            }
2745        }
2746    }
2747    IOLockUnlock(_privateLock);
2748
2749    return error;
2750}
2751
2752//------------------------------------------------------------------------------
2753
2754IOReturn IONetworkInterface::haltOutputThread( uint32_t stateBit )
2755{
2756    AbsoluteTime    deadline;
2757    uint32_t        count = 0;
2758    const uint32_t  timeout = 100;
2759    IOReturn        error = kIOReturnSuccess;
2760
2761    DLOG("%s: %s(0x%x, 0x%x)\n",
2762        getName(), __FUNCTION__, _txThreadState, stateBit);
2763
2764    IOLockLock(_privateLock);
2765
2766    do {
2767        // Prevent queue enable while we drop the lock
2768        _txThreadState |= (stateBit & kTxThreadStateDetach);
2769        _txThreadState &= ~kTxThreadStatePurge;
2770
2771        // Already halted, thread may have terminated
2772        if (_txThreadState & kTxThreadStateHalted)
2773            break;
2774
2775        if (!_txStartThread)
2776        {
2777            // Before the initial if_start call. Can update state directly
2778            // since this thread holds the lock that blocks if_start.
2779            _txThreadState |= kTxThreadStateHalted;
2780            break;
2781        }
2782
2783        // if_start thread cannot call us without ifnet attach
2784        assert(_backingIfnet);
2785
2786        if (current_thread() == _txStartThread)
2787        {
2788            // Driver called stop from if_start context
2789            _txThreadState |= kTxThreadStateHalted;
2790            break;
2791        }
2792
2793        if (_txWorkLoop && _txWorkLoop->inGate())
2794        {
2795            // stopped from gated context
2796            _txThreadState |= kTxThreadStateHalted;
2797            break;
2798        }
2799
2800        // Wait for halt confirmation from if_start thread
2801        while ((_txThreadState & kTxThreadStateHalted) == 0)
2802        {
2803            if (count)
2804            {
2805                LOG("%s: %s(0x%x, 0x%x) retry %u\n",
2806                    getName(), __FUNCTION__, _txThreadState, stateBit, count);
2807                if (count >= timeout)
2808                {
2809                    error = kIOReturnTimeout;
2810                    break;
2811                }
2812            }
2813
2814            _txThreadState |= stateBit;
2815            clock_interval_to_deadline(100, kMillisecondScale, &deadline);
2816            ifnet_start(_backingIfnet);
2817            IOLockSleepDeadline(_privateLock, &_txThreadState,
2818                deadline, THREAD_UNINT);
2819            count++;
2820        }
2821    } while (false);
2822
2823    IOLockUnlock(_privateLock);
2824
2825    DLOG("%s: %s(0x%x, 0x%x) done after %u try\n",
2826        getName(), __FUNCTION__, _txThreadState, stateBit, count);
2827
2828    return error;
2829}
2830
2831IOReturn IONetworkInterface::stopOutputThread( IOOptionBits options )
2832{
2833    return haltOutputThread( kTxThreadStateStop );
2834}
2835
2836//------------------------------------------------------------------------------
2837
2838void IONetworkInterface::flushOutputQueue( IOOptionBits options )
2839{
2840    DLOG("%s: %s(0x%x)\n",
2841        getName(), __FUNCTION__, _txThreadState);
2842
2843    IOLockLock(_privateLock);
2844    // synchronized with interface detach
2845    if (_backingIfnet && ((_txThreadState & kTxThreadStateDetach) == 0))
2846    {
2847        // Drop new packets if output thread stopped
2848        if (_txThreadState & kTxThreadStateHalted)
2849            _txThreadState |= kTxThreadStatePurge;
2850
2851        ifnet_purge(_backingIfnet);
2852    }
2853    IOLockUnlock(_privateLock);
2854}
2855
2856//------------------------------------------------------------------------------
2857
2858IOReturn IONetworkInterface::reportTransmitCompletionStatus(
2859    mbuf_t                  packet,
2860    IOReturn                status,
2861    uint32_t                param1  __unused,
2862    uint32_t                param2  __unused,
2863    IOOptionBits            options __unused )
2864{
2865    errno_t error = ifnet_tx_compl_status(getIfnet(), packet, status);
2866    return (error) ? kIOReturnError : kIOReturnSuccess;
2867}
2868
2869//------------------------------------------------------------------------------
2870// Stack-poll input model
2871//------------------------------------------------------------------------------
2872
2873IOReturn IONetworkInterface::configureInputPacketPolling(
2874    uint32_t       driverQueueSize,
2875    IOOptionBits   options )
2876{
2877    IOReturn ret = kIOReturnError;
2878
2879    IOLockLock(_privateLock);
2880    if ((_configFlags & kConfigFrozen) == 0)
2881    {
2882        _rxRingSize    = driverQueueSize;
2883        _rxPollOptions = options;
2884        _configFlags  |= kConfigRxPoll;
2885        ret = kIOReturnSuccess;
2886    }
2887    IOLockUnlock(_privateLock);
2888    return ret;
2889}
2890
2891void IONetworkInterface::if_input_poll(
2892    ifnet_t     ifp,
2893    uint32_t    flags,
2894    uint32_t    max_count,
2895    mbuf_t *    first_packet,
2896    mbuf_t *    last_packet,
2897    uint32_t *  cnt,
2898    uint32_t *  len )
2899{
2900    IONetworkInterface *    me = IFNET_TO_THIS(ifp);
2901    IONetworkController *   driver;
2902    IOMbufQueue             queue;
2903
2904    assert(ifp == me->_backingIfnet);
2905    assert(max_count != 0);
2906
2907    driver = me->_driver;
2908    assert(driver);
2909    if (__builtin_expect(!driver, 0))
2910    {
2911        return;
2912    }
2913
2914    me->_rxPollTotal++;
2915
2916    IOMbufQueueInit(&queue);
2917
2918    driver->pollInputPackets(me, max_count, &queue, 0);
2919
2920    if (!IOMbufQueueIsEmpty(&queue))
2921    {
2922        *first_packet = queue.head;
2923        *last_packet  = queue.tail;
2924        *cnt          = queue.count;
2925        *len          = queue.bytes;
2926    }
2927    else
2928    {
2929        me->_rxPollEmpty++;
2930        *first_packet = 0;
2931        *last_packet  = 0;
2932        *cnt = 0;
2933        *len = 0;
2934    }
2935}
2936
2937void IONetworkInterface::if_input_poll_gated(
2938    ifnet_t     ifp,
2939    uint32_t    flags,
2940    uint32_t    max_count,
2941    mbuf_t *    first_packet,
2942    mbuf_t *    last_packet,
2943    uint32_t *  cnt,
2944    uint32_t *  len )
2945{
2946    IONetworkInterface *    me = IFNET_TO_THIS(ifp);
2947    IONetworkController *   driver;
2948    IOMbufQueue             queue;
2949
2950    assert(ifp == me->_backingIfnet);
2951    assert(max_count != 0);
2952
2953    driver = me->_driver;
2954    assert(driver);
2955    if (__builtin_expect(!driver, 0))
2956    {
2957        return;
2958    }
2959
2960    me->_rxPollTotal++;
2961
2962    IOMbufQueueInit(&queue);
2963
2964    driver->executeCommand(
2965            /* client */ me,
2966            /* action */ (IONetworkController::Action) me->_rxPollAction,
2967            /* target */ driver,
2968            /* param0 */ me,
2969            /* param1 */ (void *)(uintptr_t) max_count,
2970            /* param2 */ &queue,
2971            /* param3 */ 0 );
2972
2973    if (!IOMbufQueueIsEmpty(&queue))
2974    {
2975        *first_packet = queue.head;
2976        *last_packet  = queue.tail;
2977        *cnt          = queue.count;
2978        *len          = queue.bytes;
2979    }
2980    else
2981    {
2982        me->_rxPollEmpty++;
2983        *first_packet = 0;
2984        *last_packet  = 0;
2985        *cnt = 0;
2986        *len = 0;
2987    }
2988}
2989
2990IOReturn IONetworkInterface::setPacketPollingParameters(
2991    const IONetworkPacketPollingParameters * params,
2992    IOOptionBits options )
2993{
2994    struct ifnet_poll_params    ifParams;
2995    errno_t                     error;
2996
2997    if (!params)
2998        return kIOReturnBadArgument;
2999    if (!_backingIfnet)
3000        return kIOReturnNotAttached;
3001
3002    bzero(&ifParams, sizeof(ifParams));
3003    ifParams.flags         = options;
3004    ifParams.packets_limit = params->maxPacketCount;
3005    ifParams.packets_lowat = params->lowThresholdPackets;
3006    ifParams.packets_hiwat = params->highThresholdPackets;
3007    ifParams.bytes_lowat   = params->lowThresholdBytes;
3008    ifParams.bytes_hiwat   = params->highThresholdBytes;
3009    ifParams.interval_time = params->pollIntervalTime;
3010
3011    error = ifnet_set_poll_params(_backingIfnet, &ifParams);
3012    return errnoToIOReturn(error);
3013}
3014
3015//------------------------------------------------------------------------------
3016
3017IOReturn IONetworkInterface::enqueueInputPacket(
3018    mbuf_t              packet,
3019    IOMbufQueue *       queue,
3020    IOOptionBits        options )
3021{
3022	const uint32_t      hdrlen = _hdrlen;
3023    void *              mdata;
3024    uint32_t            length;
3025
3026    assert(packet);
3027    assert(_backingIfnet);
3028
3029    if (!packet)
3030        return kIOReturnBadArgument;
3031
3032    if (!_backingIfnet)
3033    {
3034        mbuf_freem(packet);
3035        return kIOReturnNotAttached;
3036    }
3037
3038    if (!queue)
3039    {
3040        // use the push model queue
3041        queue = _inputPushQueue;
3042    }
3043
3044    assert((mbuf_flags(packet) & MBUF_PKTHDR));
3045    assert((mbuf_nextpkt(packet) == 0));
3046
3047	mbuf_pkthdr_setrcvif(packet, _backingIfnet);
3048
3049    length = mbuf_pkthdr_len(packet);
3050    assert(length != 0);
3051
3052    // check for special debugger packet
3053    if (_remote_NMI_len) {
3054        const char *data = get_icmp_data(&packet, hdrlen, _remote_NMI_len);
3055
3056        if (data && (memcmp(data, _remote_NMI_pattern, _remote_NMI_len) == 0)) {
3057            IOKernelDebugger::signalDebugger();
3058        }
3059    }
3060
3061    // input BPF tap
3062	if (_inputFilterFunc)
3063		feedPacketInputTap(packet);
3064
3065    // frame header at start of mbuf data
3066    mdata = mbuf_data(packet);
3067	mbuf_pkthdr_setheader(packet, mdata);
3068
3069    // packet header length does not include the frame header
3070    mbuf_pkthdr_setlen(packet, length - hdrlen);
3071
3072    // adjust the mbuf data and length to exclude the frame header
3073    mbuf_setdata(packet, (char *)mdata + hdrlen, mbuf_len(packet) - hdrlen);
3074
3075    IOMbufQueueTailAdd(queue, packet, length);
3076    return kIOReturnSuccess;
3077}
3078
3079//------------------------------------------------------------------------------
3080
3081errno_t IONetworkInterface::if_input_ctl( ifnet_t           ifp,
3082                                          ifnet_ctl_cmd_t   cmd,
3083                                          u_int32_t         arglen,
3084                                          void *            arg )
3085{
3086    IONetworkInterface *    me = IFNET_TO_THIS(ifp);
3087    IONetworkController *   driver;
3088
3089    assert(ifp == me->_backingIfnet);
3090
3091    driver = me->_driver;
3092    assert(driver);
3093    if (!driver)
3094    {
3095        return 0;
3096    }
3097
3098    driver->executeCommand(
3099            /* client */ me,
3100            /* action */ (IONetworkController::Action) me->_rxCtlAction,
3101            /* target */ me,
3102            /* param0 */ driver,
3103            /* param1 */ (void *)(uintptr_t) cmd,
3104            /* param2 */ (void *)(uintptr_t) arglen,
3105            /* param3 */ arg );
3106
3107    return 0;
3108}
3109
3110void IONetworkInterface::actionInputCtl( IONetworkController *  driver,
3111                                         ifnet_ctl_cmd_t        cmd,
3112                                         uint32_t               arglen,
3113                                         void *                 arg )
3114{
3115    ifnet_model_params * params = (ifnet_model_params *) arg;
3116
3117    switch (cmd)
3118    {
3119        case IFNET_CTL_SET_INPUT_MODEL:
3120            if (arglen != sizeof(ifnet_model_params))
3121            {
3122                LOG("%s: SET_INPUT_MODEL bad params size %u != %u\n",
3123                    getName(), arglen, (uint32_t) sizeof(ifnet_model_params));
3124            }
3125            else if ((params->model != IFNET_MODEL_INPUT_POLL_OFF) &&
3126                     (params->model != IFNET_MODEL_INPUT_POLL_ON))
3127            {
3128                LOG("%s: SET_INPUT_MODEL unknown model 0x%x\n",
3129                    getName(), params->model);
3130            }
3131            else if (params->model != _rxPollModel)
3132            {
3133                // IFNET_MODEL_INPUT_POLL_OFF
3134                // IFNET_MODEL_INPUT_POLL_ON
3135                _rxPollModel = params->model;
3136                DLOG("%s: SET_INPUT_MODEL 0x%x\n", getName(), _rxPollModel);
3137                DLOG("%s: poll cnt %llu, empty %llu\n", getName(),
3138                    _rxPollTotal, _rxPollEmpty);
3139                _rxPollEmpty = 0;
3140                _rxPollTotal = 0;
3141
3142                driver->setInputPacketPollingEnable(
3143                        this, _rxPollModel == IFNET_MODEL_INPUT_POLL_ON );
3144            }
3145            break;
3146
3147        case IFNET_CTL_GET_INPUT_MODEL:
3148            if (arglen != sizeof(ifnet_model_params))
3149            {
3150                LOG("%s: GET_INPUT_MODEL bad params size %u != %u\n",
3151                    getName(), arglen, (uint32_t) sizeof(ifnet_model_params));
3152            }
3153            else
3154            {
3155                params->model = _rxPollModel;
3156            }
3157            break;
3158
3159        default:
3160            DLOG("%s: if_input_ctl unknown cmd 0x%x\n", getName(), cmd);
3161    }
3162}
3163
3164//------------------------------------------------------------------------------
3165
3166errno_t IONetworkInterface::if_output_ctl( ifnet_t           ifp,
3167                                           ifnet_ctl_cmd_t   cmd,
3168                                           u_int32_t         arglen,
3169                                           void *            arg )
3170{
3171    IONetworkInterface *    me = IFNET_TO_THIS(ifp);
3172    IONetworkController *   driver;
3173    errno_t                 error = ENOTSUP;
3174    bool                    changed = false;
3175
3176    assert(ifp == me->_backingIfnet);
3177
3178    driver = me->_driver;
3179    assert(driver);
3180    if (!driver)
3181    {
3182        return ENODEV;
3183    }
3184
3185    if (cmd == IFNET_CTL_SET_LOG)
3186    {
3187        if (arg && (arglen == sizeof(struct ifnet_log_params)))
3188        {
3189            const struct ifnet_log_params * lp =
3190                (const struct ifnet_log_params *) arg;
3191
3192            IONetworkInterfaceLoggingParameters params;
3193
3194            IOLockLock(me->_privateLock);
3195
3196            if (me->_loggingLevel != lp->level)
3197                changed = true;
3198
3199            me->_loggingLevel = lp->level;
3200
3201            IOLockUnlock(me->_privateLock);
3202            error = 0;
3203
3204            bzero(&params, sizeof(params));
3205            params.level = lp->level;
3206            params.flags = lp->flags;
3207            params.category = lp->category;
3208            params.subCategory = lp->subcategory;
3209            me->notifyDriver(kIONetworkNotificationLoggingParametersChange,
3210                             &params);
3211        }
3212        else
3213        {
3214            error = EINVAL;
3215        }
3216
3217        if (changed)
3218            me->notifyDriver(kIONetworkNotificationLoggingLevelChange, 0);
3219    }
3220    else if (cmd == IFNET_CTL_NOTIFY_ADDRESS)
3221    {
3222        if (arg && (arglen == sizeof(struct ifnet_notify_address_params)))
3223        {
3224            const struct ifnet_notify_address_params * ap =
3225                (const struct ifnet_notify_address_params *) arg;
3226
3227            IONetworkInterfaceAddressChangeParameters params;
3228
3229            bzero(&params, sizeof(params));
3230            params.addressFamily = ap->address_family;
3231            me->notifyDriver(kIONetworkNotificationInterfaceAddressChange,
3232                             &params);
3233        }
3234        else
3235        {
3236            error = EINVAL;
3237        }
3238    }
3239
3240    return error;
3241}
3242
3243//------------------------------------------------------------------------------
3244
3245bool IONetworkInterface::isBPFTapEnabled( IOOptionBits options __unused ) const
3246{
3247    bool enabled;
3248
3249    IOLockLock(_privateLock);
3250    enabled = (_inputFilterFunc != 0);
3251    IOLockUnlock(_privateLock);
3252    return enabled;
3253}
3254
3255int32_t IONetworkInterface::getLoggingLevel( IOOptionBits options __unused ) const
3256{
3257    int32_t level;
3258
3259    IOLockLock(_privateLock);
3260    level = _loggingLevel;
3261    IOLockUnlock(_privateLock);
3262    return level;
3263}
3264
3265void IONetworkInterface::notifyDriver( uint32_t notifyType, void * data )
3266{
3267    if (_driver)
3268        _driver->networkInterfaceNotification(this, notifyType, data);
3269}
3270
3271//------------------------------------------------------------------------------
3272
3273IOReturn IONetworkInterface::errnoToIOReturn( errno_t error )
3274{
3275    switch (error)
3276    {
3277        case 0:
3278            return kIOReturnSuccess;
3279        case EINVAL:
3280            return kIOReturnBadArgument;
3281        case ENOMEM:
3282            return kIOReturnNoMemory;
3283        case EPERM:
3284            return kIOReturnNotPermitted;
3285        case EACCES:
3286            return kIOReturnNotPrivileged;
3287        case ENOTSUP:
3288            return kIOReturnUnsupported;
3289        case EBUSY:
3290            return kIOReturnBusy;
3291        case ETIMEDOUT:
3292            return kIOReturnTimeout;
3293        default:
3294            return kIOReturnError;
3295    }
3296}
3297
3298IOReturn IONetworkInterface::reportDatapathIssue(
3299    IOReturn 	issue,
3300    void * 		data   __unused,
3301    IOByteCount length __unused )
3302{
3303    errno_t error;
3304
3305    // SHA-1 hash of com.apple.iokit.IONetworkingFamily
3306    static const uint8_t modid[DLIL_MODIDLEN] = {
3307        0xe3, 0x26, 0x1e, 0x7d, 0xf2, 0x15, 0xf1, 0x3d, 0x9d, 0x9d,
3308        0xbc, 0x1f, 0x75, 0x4d, 0xa5, 0xa4, 0x1c, 0xac, 0x2a, 0xab };
3309
3310    union {
3311        uint8_t     errorData[ DLIL_MODARGLEN ];
3312        IOReturn    errorCode;
3313    } issueInfo;
3314
3315    bzero(&issueInfo, sizeof(issueInfo));
3316    issueInfo.errorCode = issue;
3317
3318    error = ifnet_report_issues(getIfnet(), (uint8_t *) modid, issueInfo.errorData);
3319
3320    return errnoToIOReturn(error);
3321}
3322