1/*
2 *
3 * @APPLE_LICENSE_HEADER_START@
4 *
5 * Copyright (c) 1998-2003 Apple Computer, Inc.  All Rights Reserved.
6 *
7 * This file contains Original Code and/or Modifications of Original Code
8 * as defined in and that are subject to the Apple Public Source License
9 * Version 2.0 (the 'License'). You may not use this file except in
10 * compliance with the License. Please obtain a copy of the License at
11 * http://www.opensource.apple.com/apsl/ and read it before using this
12 * file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
19 * Please see the License for the specific language governing rights and
20 * limitations under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24
25#include <machine/limits.h>			/* UINT_MAX */
26#include <libkern/OSByteOrder.h>
27
28#include <IOKit/network/IOEthernetController.h>
29#include <IOKit/network/IOEthernetInterface.h>
30#include <IOKit/network/IOGatedOutputQueue.h>
31
32#include <IOKit/IOTimerEventSource.h>
33#include <IOKit/assert.h>
34#include <IOKit/IOLib.h>
35#include <IOKit/IOService.h>
36#include <IOKit/IOBufferMemoryDescriptor.h>
37#include <IOKit/IOMessage.h>
38
39#include <IOKit/pwr_mgt/RootDomain.h>
40
41#if !TARGET_OS_IPHONE
42#include <IOKit/usb/IOUSBBus.h>
43#endif /* TARGET_OS_IPHONE */
44
45#include <IOKit/usb/IOUSBNub.h>
46#include <IOKit/usb/IOUSBDevice.h>
47#include <IOKit/usb/IOUSBPipe.h>
48#include <IOKit/usb/USB.h>
49#include <IOKit/usb/IOUSBInterface.h>
50
51#include <UserNotification/KUNCUserNotifications.h>
52
53extern "C"
54{
55    #include <sys/param.h>
56    #include <sys/mbuf.h>
57}
58
59#define DEBUG_NAME "AppleUSBCDCEEM"
60
61#include "AppleUSBCDCEEM.h"
62
63#define MIN_BAUD (50 << 1)
64
65static struct MediumTable
66{
67    UInt32	type;
68    UInt32	speed;
69}
70
71mediumTable[] =
72{
73    {kIOMediumEthernetNone,												0},
74    {kIOMediumEthernetAuto,												0},
75    {kIOMediumEthernet10BaseT 	 | kIOMediumOptionHalfDuplex,								10},
76    {kIOMediumEthernet10BaseT 	 | kIOMediumOptionFullDuplex,								10},
77    {kIOMediumEthernet100BaseTX  | kIOMediumOptionHalfDuplex,								100},
78    {kIOMediumEthernet100BaseTX  | kIOMediumOptionFullDuplex,								100}
79};
80
81#define super IOEthernetController
82
83OSDefineMetaClassAndStructors(AppleUSBCDCEEM, IOEthernetController);
84
85/****************************************************************************************************/
86//
87//		Function:	findCDCDriverEED
88//
89//		Inputs:		myDevice - Address of the controlling device
90//				dataAddr - my address
91//				dataInterfaceNum - the data interface number
92//
93//		Outputs:
94//
95//		Desc:		Finds the initiating CDC driver and confirm the interface number
96//
97/****************************************************************************************************/
98
99IOReturn findCDCDriverEED(IOUSBDevice *myDevice, void *dataAddr, UInt8 dataInterfaceNum)
100{
101    AppleUSBCDCEEM	*me = (AppleUSBCDCEEM *)dataAddr;
102    AppleUSBCDC		*CDCDriver = NULL;
103    bool		driverOK = false;
104    OSIterator		*iterator = NULL;
105    OSDictionary	*matchingDictionary = NULL;
106
107    XTRACE(me, 0, 0, "findCDCDriverEED");
108
109        // Get matching dictionary
110
111    matchingDictionary = IOService::serviceMatching("AppleUSBCDC");
112    if (!matchingDictionary)
113    {
114        XTRACE(me, 0, 0, "findCDCDriverEED - Couldn't create a matching dictionary");
115        return kIOReturnError;
116    }
117
118	// Get an iterator
119
120    iterator = IOService::getMatchingServices(matchingDictionary);
121    if (!iterator)
122    {
123        XTRACE(me, 0, 0, "findCDCDriverEED - No AppleUSBCDC driver found!");
124        matchingDictionary->release();
125        return kIOReturnError;
126    }
127
128#if 0
129	// Use iterator to find driver (there's only one so we won't bother to iterate)
130
131    CDCDriver = (AppleUSBCDC *)iterator->getNextObject();
132    if (CDCDriver)
133    {
134        driverOK = CDCDriver->confirmDriver(kUSBEthernetEmulationModel, dataInterfaceNum);
135    }
136#endif
137
138 	// Iterate until we find our matching CDC driver
139
140    CDCDriver = (AppleUSBCDC *)iterator->getNextObject();
141    while (CDCDriver)
142    {
143        XTRACE(me, 0, 0, "findCDCDriverEED - CDC driver candidate");
144
145        if (me->fDataInterface->GetDevice() == CDCDriver->getCDCDevice())
146        {
147            XTRACE(me, 0, 0, "findCDCDriverEED - Found our CDC driver");
148            driverOK = CDCDriver->confirmDriver(kUSBEthernetEmulationModel, dataInterfaceNum);
149            break;
150        }
151        CDCDriver = (AppleUSBCDC *)iterator->getNextObject();
152    }
153
154    matchingDictionary->release();
155    iterator->release();
156
157    if (!CDCDriver)
158    {
159        XTRACE(me, 0, 0, "findCDCDriverEED - CDC driver not found");
160        return kIOReturnError;
161    }
162
163    if (!driverOK)
164    {
165        XTRACE(me, kUSBEthernetEmulationModel, dataInterfaceNum, "findCDCDriverEED - Not my interface");
166        return kIOReturnError;
167    }
168
169    me->fConfigAttributes = CDCDriver->fbmAttributes;
170
171    return kIOReturnSuccess;
172
173}/* end findCDCDriverEED */
174
175#if LOG_DATA
176#define dumplen		32		// Set this to the number of bytes to dump and the rest should work out correct
177
178#define buflen		((dumplen*2)+dumplen)+3
179#define Asciistart	(dumplen*2)+3
180
181/****************************************************************************************************/
182//
183//		Function:	AppleUSBCDCEEM::USBLogData
184//
185//		Inputs:		Dir - direction
186//				Count - number of bytes
187//				buf - the data
188//
189//		Outputs:
190//
191//		Desc:		Puts the data in the log.
192//
193/****************************************************************************************************/
194
195void AppleUSBCDCEEM::USBLogData(UInt8 Dir, SInt32 Count, char *buf)
196{
197    SInt32	wlen;
198    UInt8	tDir = Dir;
199    SInt32	llen, rlen;
200    SInt16	i, Aspnt, Hxpnt;
201    UInt8	wchr;
202    char	LocBuf[buflen+1];
203
204    switch (tDir)
205    {
206        case kDataIn:
207            Log("AppleUSBCDCEEM: USBLogData - Read Complete, address = %8p, size = %8d\n", (void *)buf, (UInt)Count);
208            break;
209        case kDataOut:
210            Log("AppleUSBCDCEEM: USBLogData - Write, address = %8p, size = %8d\n", (void *)buf, (UInt)Count);
211            break;
212        case kDataOther:
213            Log("AppleUSBCDCEEM: USBLogData - Other, address = %8p, size = %8d\n", (void *)buf, (UInt)Count);
214            break;
215        case kDataNone:
216            tDir = kDataOther;
217            break;
218    }
219
220#if DUMPALL
221    wlen = Count;
222#else
223    if (Count > dumplen)
224    {
225        wlen = dumplen;
226    } else {
227        wlen = Count;
228    }
229#endif
230
231    if (wlen == 0)
232    {
233        Log("AppleUSBCDCEEM: USBLogData - No data, Count=0\n");
234        return;
235    }
236
237    rlen = 0;
238    do
239    {
240        memset(LocBuf, 0x20, buflen);
241
242        if (wlen > dumplen)
243        {
244            llen = dumplen;
245            wlen -= dumplen;
246        } else {
247            llen = wlen;
248            wlen = 0;
249        }
250        Aspnt = Asciistart;
251        Hxpnt = 0;
252        for (i=1; i<=llen; i++)
253        {
254            wchr = buf[i-1];
255            LocBuf[Hxpnt++] = Asciify(wchr >> 4);
256            LocBuf[Hxpnt++] = Asciify(wchr);
257            if ((wchr < 0x20) || (wchr > 0x7F)) 		// Non printable characters
258            {
259                LocBuf[Aspnt++] = 0x2E;				// Replace with a period
260            } else {
261                LocBuf[Aspnt++] = wchr;
262            }
263        }
264        LocBuf[Aspnt] = 0x00;
265
266		Log("%s\n", LocBuf);
267#if USE_IOL
268        IOSleep(Sleep_Time);					// Try and keep the log from overflowing
269#endif
270
271        rlen += llen;
272        buf = &buf[rlen];
273    } while (wlen != 0);
274
275}/* end USBLogData */
276
277/****************************************************************************************************/
278//
279//		Function:	AppleUSBCDCEEM::dumpData
280//
281//		Inputs:		buf - the data
282//				size - number of bytes
283//
284//		Outputs:	None
285//
286//		Desc:		Creates formatted data for the log (cannot be used at interrupt time)
287//
288/****************************************************************************************************/
289
290void AppleUSBCDCEEM::dumpData(char *buf, SInt32 size)
291{
292    SInt32	curr, len, dlen;
293
294    Log("AppleUSBCDCEEM: dumpData - Address = %8p, size = %8d\n", (void *)buf, (UInt)size);
295
296    dlen = 0;
297    len = size;
298
299    for (curr=0; curr<size; curr+=dumplen)
300    {
301        if (len > dumplen)
302        {
303            dlen = dumplen;
304        } else {
305            dlen = len;
306        }
307        Log("%8p ", (void *)&buf[curr]);
308        USBLogData(kDataNone, dlen, &buf[curr]);
309        len -= dlen;
310    }
311
312}/* end dumpData */
313#endif
314
315/****************************************************************************************************/
316//
317//		Method:		AppleUSBCDCEEM::dataReadComplete
318//
319//		Inputs:		obj - me
320//					param - pool index
321//					rc - return code
322//					remaining - what's left
323//
324//		Outputs:
325//
326//		Desc:		BulkIn pipe (Data interface) read completion routine
327//
328/****************************************************************************************************/
329
330void AppleUSBCDCEEM::dataReadComplete(void *obj, void *param, IOReturn rc, UInt32 remaining)
331{
332    AppleUSBCDCEEM	*me = (AppleUSBCDCEEM*)obj;
333    IOReturn		ior;
334	pipeInBuffers	*pipeBuf = (pipeInBuffers *)param;
335//    UInt32			poolIndx = (UInt32)param;
336	UInt16			EEMHeader;
337    UInt8			*EEMHeaderAddress = (UInt8 *) &EEMHeader;
338	SInt16			actualLen, dataLen, i = 0;
339	bool			done = false;
340
341    XTRACE(me, 0, pipeBuf->indx, "dataReadComplete");
342
343    if (rc == kIOReturnSuccess)
344    {
345		dataLen = me->fMax_Block_Size - remaining;
346        XTRACE(me, 0, dataLen, "dataReadComplete - data length");
347
348		while (!done)
349		{
350			EEMHeaderAddress[0] = pipeBuf->pipeInBuffer[i];
351			EEMHeaderAddress[1] = pipeBuf->pipeInBuffer[i+1];
352
353			if (EEMHeader & bmTypeCommand)
354			{
355					// Look at the command
356
357				me->processEEMCommand(EEMHeader, pipeBuf->indx, i+2, &actualLen);
358			} else {
359				actualLen = EEMHeader & frameLenMask;
360				meLogData(kDataIn, actualLen+2, &pipeBuf->pipeInBuffer[i]);
361
362					// Move the incoming bytes up the stack
363
364				me->receivePacket(&pipeBuf->pipeInBuffer[i+2], actualLen);
365			}
366			i += actualLen;
367			if (i >= dataLen)
368			{
369				done = true;
370			}
371		}
372    } else {
373        XTRACE(me, 0, rc, "dataReadComplete - Read completion io err");
374        if (rc != kIOReturnAborted)
375        {
376            rc = me->clearPipeStall(me->fInPipe);
377            if (rc != kIOReturnSuccess)
378            {
379                XTRACE(me, 0, rc, "dataReadComplete - clear stall failed (trying to continue)");
380            }
381        }
382    }
383
384        // Queue the next read, only if not aborted
385
386    if (rc != kIOReturnAborted)
387    {
388        ior = me->fInPipe->Read(pipeBuf->pipeInMDP, &pipeBuf->readCompletionInfo, NULL);
389        if (ior != kIOReturnSuccess)
390        {
391            XTRACE(me, 0, ior, "dataReadComplete - Failed to queue read");
392            pipeBuf->dead = true;
393        }
394    } else {
395        XTRACE(me, 0, 0, "dataReadComplete - Read terminated");
396        pipeBuf->dead = true;
397    }
398
399    return;
400
401}/* end dataReadComplete */
402
403/****************************************************************************************************/
404//
405//		Method:		AppleUSBCDCEEM::dataWriteComplete
406//
407//		Inputs:		obj - me
408//				param - pool index
409//				rc - return code
410//				remaining - what's left
411//
412//		Outputs:
413//
414//		Desc:		BulkOut pipe (Data interface) write completion routine
415//
416/****************************************************************************************************/
417
418void AppleUSBCDCEEM::dataWriteComplete(void *obj, void *param, IOReturn rc, UInt32 remaining)
419{
420    AppleUSBCDCEEM	*me = (AppleUSBCDCEEM *)obj;
421    mbuf_t			m;
422    UInt32			pktLen = 0;
423    UInt32			numbufs = 0;
424	pipeOutBuffers	*pipeBuf = (pipeOutBuffers *)param;
425//    UInt32		poolIndx = (UInt32)param;
426
427	XTRACE(me, rc, pipeBuf->indx, "dataWriteComplete");
428
429    if (me->fBufferPoolLock)
430    {
431        IOLockLock(me->fBufferPoolLock);
432    }
433
434    if (rc == kIOReturnSuccess)						// If operation returned ok
435    {
436        if (pipeBuf->m != NULL)						// Null means zero length write or command
437        {
438            m = pipeBuf->m;
439            while (m)
440			{
441				pktLen += mbuf_len(m);
442				numbufs++;
443				m = mbuf_next(m);
444			}
445            me->freePacket(pipeBuf->m);				// Free the mbuf
446            pipeBuf->m = NULL;
447
448            if ((pktLen % me->fOutPacketSize) == 0)			// If it was a multiple of max packet size then we need to do a zero length write
449            {
450                XTRACE(me, rc, pktLen, "dataWriteComplete - writing zero length packet");
451                pipeBuf->pipeOutMDP->setLength(0);
452                pipeBuf->writeCompletionInfo.parameter = (void *)pipeBuf;
453                me->fOutPipe->Write(pipeBuf->pipeOutMDP, &pipeBuf->writeCompletionInfo);
454            } else {
455                pipeBuf->avail = true;
456                if (me->fTxStalled)
457                {
458                    me->fTxStalled = false;
459                    me->fTransmitQueue->service(IOBasicOutputQueue::kServiceAsync);
460                }
461            }
462        } else {
463            pipeBuf->avail = true;					// Make the buffer available again
464            if (me->fTxStalled)
465            {
466                me->fTxStalled = false;
467                me->fTransmitQueue->service(IOBasicOutputQueue::kServiceAsync);
468            }
469        }
470    } else {
471        XTRACE(me, rc, pipeBuf->indx, "dataWriteComplete - IO err");
472
473        if (pipeBuf->m != NULL)
474        {
475            me->freePacket(pipeBuf->m);				// Free the mbuf anyway
476            pipeBuf->m = NULL;
477            pipeBuf->avail = true;
478            if (me->fTxStalled)
479            {
480                me->fTxStalled = false;
481                me->fTransmitQueue->service(IOBasicOutputQueue::kServiceAsync);
482            }
483        }
484        if (rc != kIOReturnAborted)
485        {
486            rc = me->clearPipeStall(me->fOutPipe);
487            if (rc != kIOReturnSuccess)
488            {
489                XTRACE(me, 0, rc, "dataWriteComplete - clear stall failed (trying to continue)");
490            }
491        }
492    }
493
494    if (me->fBufferPoolLock)
495    {
496        IOLockUnlock(me->fBufferPoolLock);
497    }
498
499    return;
500
501}/* end dataWriteComplete */
502
503/****************************************************************************************************/
504//
505//		Method:		AppleUSBCDCEEM::probe
506//
507//		Inputs:		provider - my provider
508//
509//		Outputs:	IOService - from super::probe, score - probe score
510//
511//		Desc:		Modify the probe score if necessary (we don't  at the moment)
512//
513/****************************************************************************************************/
514
515IOService* AppleUSBCDCEEM::probe( IOService *provider, SInt32 *score )
516{
517    IOService   *res;
518
519		// If our IOUSBInterface has a "do not match" property, it means that we should not match and need
520		// to bail.  See rdar://3716623
521
522    OSBoolean *boolObj = OSDynamicCast(OSBoolean, provider->getProperty("kDoNotClassMatchThisInterface"));
523    if (boolObj && boolObj->isTrue())
524    {
525        XTRACE(this, 0, 0, "probe - provider doesn't want us to match");
526        return NULL;
527    }
528
529    res = super::probe(provider, score);
530
531    return res;
532
533}/* end probe */
534
535/****************************************************************************************************/
536//
537//		Method:		AppleUSBCDCEEM::init
538//
539//		Inputs:		properties - data (keys and values) used to match
540//
541//		Outputs:	Return code - true (init successful), false (init failed)
542//
543//		Desc:		Initialize the driver.
544//
545/****************************************************************************************************/
546
547bool AppleUSBCDCEEM::init(OSDictionary *properties)
548{
549    UInt32	i;
550
551    XTRACE(this, 0, 0, "init");
552
553    if (super::init(properties) == false)
554    {
555        XTRACE(this, 0, 0, "init - initialize super failed");
556        return false;
557    }
558
559    for (i=0; i<kMaxOutBufPool; i++)
560    {
561        fPipeOutBuff[i].pipeOutMDP = NULL;
562        fPipeOutBuff[i].pipeOutBuffer = NULL;
563        fPipeOutBuff[i].m = NULL;
564        fPipeOutBuff[i].avail = false;
565        fPipeOutBuff[i].writeCompletionInfo.target = NULL;
566        fPipeOutBuff[i].writeCompletionInfo.action = NULL;
567        fPipeOutBuff[i].writeCompletionInfo.parameter = NULL;
568		fPipeOutBuff[i].indx = i;
569    }
570    fOutPoolIndex = 0;
571
572    for (i=0; i<kMaxInBufPool; i++)
573    {
574        fPipeInBuff[i].pipeInMDP = NULL;
575        fPipeInBuff[i].pipeInBuffer = NULL;
576        fPipeInBuff[i].dead = false;
577        fPipeInBuff[i].readCompletionInfo.target = NULL;
578        fPipeInBuff[i].readCompletionInfo.action = NULL;
579        fPipeInBuff[i].readCompletionInfo.parameter = NULL;
580		fPipeInBuff[i].indx = i;
581    }
582
583    return true;
584
585}/* end init*/
586
587/****************************************************************************************************/
588//
589//		Method:		AppleUSBCDCEEM::start
590//
591//		Inputs:		provider - my provider
592//
593//		Outputs:	Return code - true (it's me), false (sorry it probably was me, but I can't configure it)
594//
595//		Desc:		This is called once it has beed determined I'm probably the best
596//				driver for this device.
597//
598/****************************************************************************************************/
599
600bool AppleUSBCDCEEM::start(IOService *provider)
601{
602    OSNumber		*bufNumber = NULL;
603    UInt16		bufValue = 0;
604
605    XTRACE(this, 0, 0, "start");
606
607	return false;				// Don't load for EEM hardware at this time
608
609    if(!super::start(provider))
610    {
611        ALERT(0, 0, "start - start super failed");
612        return false;
613    }
614
615	// Get my USB provider - the interface
616
617    fDataInterface = OSDynamicCast(IOUSBInterface, provider);
618    if(!fDataInterface)
619    {
620        ALERT(0, 0, "start - provider invalid");
621        return false;
622    }
623
624    fDataInterfaceNumber = fDataInterface->GetInterfaceNumber();
625
626    if (findCDCDriverEED(fDataInterface->GetDevice(), this, fDataInterfaceNumber) != kIOReturnSuccess)
627    {
628        XTRACE(this, 0, 0, "start - Find CDC driver failed");
629		super::stop(provider);
630        return false;
631    }
632
633    fBufferPoolLock = IOLockAlloc();
634    if (!fBufferPoolLock)
635    {
636        ALERT(0, 0, "start - Buffer pool lock allocate failed");
637        return false;
638    }
639
640        // get workloop
641
642    fWorkLoop = getWorkLoop();
643    if (!fWorkLoop)
644    {
645        ALERT(0, 0, "start - getWorkLoop failed");
646        return false;
647    }
648
649    if (!configureData())
650    {
651        ALERT(0, 0, "start - configureData failed");
652        return false;
653    }
654
655		// Check for an input buffer pool override first
656
657	fInBufPool = 0;
658	fOutBufPool = 0;
659
660	bufNumber = (OSNumber *)provider->getProperty(inputTag);
661    if (bufNumber)
662    {
663		bufValue = bufNumber->unsigned16BitValue();
664		XTRACE(this, 0, bufValue, "start - Number of input buffers override value");
665        if (bufValue <= kMaxInBufPool)
666        {
667            fInBufPool = bufValue;
668        } else {
669            fInBufPool = kMaxInBufPool;
670        }
671	} else {
672		fInBufPool = 0;
673	}
674
675		// Now set up the real input buffer pool values (only if not overridden)
676
677	if (fInBufPool == 0)
678	{
679		bufNumber = NULL;
680		bufNumber = (OSNumber *)getProperty(inputTag);
681		if (bufNumber)
682		{
683			bufValue = bufNumber->unsigned16BitValue();
684			XTRACE(this, 0, bufValue, "start - Number of input buffers requested");
685			if (bufValue <= kMaxInBufPool)
686			{
687				fInBufPool = bufValue;
688			} else {
689				fInBufPool = kMaxInBufPool;
690			}
691		} else {
692			fInBufPool = kInBufPool;
693		}
694    }
695
696		// Check for an output buffer pool override
697
698	bufNumber = NULL;
699	bufNumber = (OSNumber *)provider->getProperty(outputTag);
700    if (bufNumber)
701    {
702		bufValue = bufNumber->unsigned16BitValue();
703		XTRACE(this, 0, bufValue, "start - Number of output buffers override value");
704        if (bufValue <= kMaxInBufPool)
705        {
706            fOutBufPool = bufValue;
707        } else {
708            fOutBufPool = kMaxOutBufPool;
709        }
710	} else {
711		fOutBufPool = 0;
712	}
713
714        // Now set up the real output buffer pool values (only if not overridden)
715
716	if (fOutBufPool == 0)
717	{
718		bufNumber = NULL;
719		bufNumber = (OSNumber *)getProperty(outputTag);
720		if (bufNumber)
721		{
722			bufValue = bufNumber->unsigned16BitValue();
723			XTRACE(this, 0, bufValue, "start - Number of output buffers requested");
724			if (bufValue <= kMaxOutBufPool)
725			{
726				fOutBufPool = bufValue;
727			} else {
728				fOutBufPool = kMaxOutBufPool;
729			}
730		} else {
731			fOutBufPool = kOutBufPool;
732		}
733	}
734
735    XTRACE(this, fInBufPool, fOutBufPool, "start - Buffer pools (input, output)");
736
737    if (!createNetworkInterface())
738    {
739        ALERT(0, 0, "start - createNetworkInterface failed");
740        return false;
741    }
742
743         // Looks like we're ok
744
745    fDataInterface->retain();
746    fWorkLoop->retain();
747    fTransmitQueue->retain();
748
749        // Ready to service interface requests
750
751    fNetworkInterface->registerService();
752
753    XTRACE(this, 0, 0, "start - successful");
754	Log(DEBUG_NAME ": Version number - %s, Input buffers %d, Output buffers %d\n", VersionNumber, fInBufPool, fOutBufPool);
755
756    return true;
757
758}/* end start */
759
760/****************************************************************************************************/
761//
762//		Method:		AppleUSBCDCEEM::stop
763//
764//		Inputs:		provider - my provider
765//
766//		Outputs:
767//
768//		Desc:		Stops the driver
769//
770/****************************************************************************************************/
771
772void AppleUSBCDCEEM::stop(IOService *provider)
773{
774
775    XTRACE(this, 0, 0, "stop");
776
777        // Release all resources
778
779    releaseResources();
780
781    if (fDataInterface)
782    {
783        fDataInterface->close(this);
784        fDataInterface->release();
785        fDataInterface = NULL;
786    }
787
788    if (fNetworkInterface)
789    {
790        fNetworkInterface->release();
791        fNetworkInterface = NULL;
792    }
793
794    if (fMediumDict)
795    {
796        fMediumDict->release();
797        fMediumDict = NULL;
798    }
799
800    if (fBufferPoolLock)
801    {
802        IOLockFree(fBufferPoolLock);
803        fBufferPoolLock = NULL;
804    }
805
806    if (fWorkLoop)
807    {
808        fWorkLoop->release();
809        fWorkLoop = NULL;
810    }
811
812    if (fTransmitQueue)
813    {
814        fTransmitQueue->release();
815        fTransmitQueue = NULL;
816    }
817
818    super::stop(provider);
819
820    return;
821
822}/* end stop */
823
824/****************************************************************************************************/
825//
826//		Method:		AppleUSBCDCEEM::configureData
827//
828//		Inputs:
829//
830//		Outputs:	return code - true (configure was successful), false (it failed)
831//
832//		Desc:		Finishes up the rest of the configuration
833//
834/****************************************************************************************************/
835
836bool AppleUSBCDCEEM::configureData()
837{
838    IOUSBFindInterfaceRequest		req;
839    const IOUSBInterfaceDescriptor	*altInterfaceDesc;
840    IOReturn				ior = kIOReturnSuccess;
841    UInt16				numends = 0;
842    UInt16				alt;
843
844    XTRACE(this, 0, 0, "configureData.");
845
846    if (!fDataInterface)
847    {
848        XTRACE(this, 0, 0, "configureData - Data interface is NULL");
849        return false;
850    }
851
852    if (!fDataInterface->open(this))
853    {
854        XTRACE(this, 0, 0, "configureData - open data interface failed");
855        fDataInterface->release();
856        fDataInterface = NULL;
857        return false;
858    }
859
860        // Check we have the correct interface (there maybe an alternate)
861
862    numends = fDataInterface->GetNumEndpoints();
863    if (numends < 2)
864    {
865        req.bInterfaceClass = kUSBDataClass;
866        req.bInterfaceSubClass = 0;
867        req.bInterfaceProtocol = 0;
868        req.bAlternateSetting = kIOUSBFindInterfaceDontCare;
869        altInterfaceDesc = fDataInterface->FindNextAltInterface(NULL, &req);
870        if (!altInterfaceDesc)
871        {
872            XTRACE(this, 0, 0, "configureData - FindNextAltInterface failed");
873            return false;
874        }
875        while (altInterfaceDesc)
876        {
877            numends = altInterfaceDesc->bNumEndpoints;
878            if (numends > 1)
879            {
880                alt = altInterfaceDesc->bAlternateSetting;
881                XTRACE(this, numends, alt, "configureData - Data Class interface (alternate) found");
882                ior = fDataInterface->SetAlternateInterface(this, alt);
883                if (ior == kIOReturnSuccess)
884                {
885                    XTRACE(this, 0, 0, "configureData - Alternate set");
886                    break;
887                } else {
888                    XTRACE(this, 0, 0, "configureData - SetAlternateInterface failed");
889                    return false;
890                }
891            } else {
892                XTRACE(this, 0, 0, "configureData - No endpoints this alternate");
893            }
894            altInterfaceDesc = fDataInterface->FindNextAltInterface(altInterfaceDesc, &req);
895        }
896    }
897
898    if (numends < 2)
899    {
900        XTRACE(this, 0, 0, "configureData - Could not find the correct interface");
901        return false;
902    }
903
904    return true;
905
906}/* end configureData */
907
908/****************************************************************************************************/
909//
910//		Method:		AppleUSBCDCEEM::createNetworkInterface
911//
912//		Inputs:
913//
914//		Outputs:	return Code - true (created and initialilzed ok), false (it failed)
915//
916//		Desc:		Creates and initializes the network interface
917//
918/****************************************************************************************************/
919
920bool AppleUSBCDCEEM::createNetworkInterface()
921{
922
923    XTRACE(this, 0, 0, "createNetworkInterface");
924
925            // Allocate memory for transmit queue
926
927    fTransmitQueue = (IOGatedOutputQueue *)getOutputQueue();
928    if (!fTransmitQueue)
929    {
930        ALERT(0, 0, "createNetworkInterface - Output queue initialization failed");
931        return false;
932    }
933
934        // Attach an IOEthernetInterface client
935
936    XTRACE(this, 0, 0, "createNetworkInterface - attaching and registering interface");
937
938    if (!attachInterface((IONetworkInterface **)&fNetworkInterface, false))
939    {
940        ALERT(0, 0, "createNetworkInterface - attachInterface failed");
941        return false;
942    }
943
944    XTRACE(this, 0, 0, "createNetworkInterface - Exiting, successful");
945
946    return true;
947
948}/* end createNetworkInterface */
949
950/****************************************************************************************************/
951//
952//		Method:		AppleUSBCDCEEM::enable
953//
954//		Inputs:		netif - the interface being enabled
955//
956//		Outputs:	Return code - kIOReturnSuccess or kIOReturnIOError
957//
958//		Desc:		Called by IOEthernetInterface client to enable the controller.
959//				This method is always called while running on the default workloop
960//				thread
961//
962/****************************************************************************************************/
963
964IOReturn AppleUSBCDCEEM::enable(IONetworkInterface *netif)
965{
966    IONetworkMedium	*medium;
967    IOMediumType    	mediumType = kIOMediumEthernet10BaseT | kIOMediumOptionFullDuplex;
968
969    XTRACE(this, 0, 0, "enable");
970
971    IOSleep(5);				// Just in case (to let start finish - on another thread)
972
973        // If an interface client has previously enabled us,
974        // and we know there can only be one interface client
975        // for this driver, then simply return success.
976
977    if (fNetifEnabled)
978    {
979        XTRACE(this, 0, 0, "enable - already enabled");
980        return kIOReturnSuccess;
981    }
982
983    if (!fReady)
984    {
985        if (!wakeUp())
986        {
987            XTRACE(this, 0, fReady, "enable - wakeUp failed");
988            return kIOReturnIOError;
989        }
990    }
991
992        // Mark the controller as enabled by the interface.
993
994    fNetifEnabled = true;
995
996        // Assume an active link (leave this in for now - until we know better)
997        // Should probably use the values returned in the Network Connection notification
998        // that is if we have an interrupt pipe, otherwise default to these
999
1000    fLinkStatus = 1;
1001
1002    medium = IONetworkMedium::getMediumWithType(fMediumDict, mediumType);
1003    XTRACE(this, mediumType, 0, "enable - medium type");
1004    setLinkStatus(kIONetworkLinkActive | kIONetworkLinkValid, medium, 10 * 1000000);
1005    XTRACE(this, 0, 0, "enable - LinkStatus set");
1006
1007        // Start our IOOutputQueue object.
1008
1009    fTransmitQueue->setCapacity(TRANSMIT_QUEUE_SIZE);
1010    XTRACE(this, 0, TRANSMIT_QUEUE_SIZE, "enable - capicity set");
1011    fTransmitQueue->start();
1012    XTRACE(this, 0, 0, "enable - transmit queue started");
1013
1014    return kIOReturnSuccess;
1015
1016}/* end enable */
1017
1018/****************************************************************************************************/
1019//
1020//		Method:		AppleUSBCDCEEM::disable
1021//
1022//		Inputs:		netif - the interface being disabled
1023//
1024//		Outputs:	Return code - kIOReturnSuccess
1025//
1026//		Desc:		Called by IOEthernetInterface client to disable the controller.
1027//				This method is always called while running on the default workloop
1028//				thread
1029//
1030/****************************************************************************************************/
1031
1032IOReturn AppleUSBCDCEEM::disable(IONetworkInterface *netif)
1033{
1034
1035    XTRACE(this, 0, 0, "disable");
1036
1037        // Disable our IOOutputQueue object. This will prevent the
1038        // outputPacket() method from being called
1039
1040    fTransmitQueue->stop();
1041
1042        // Flush all packets currently in the output queue
1043
1044    fTransmitQueue->setCapacity(0);
1045    fTransmitQueue->flush();
1046
1047    putToSleep();
1048
1049    fNetifEnabled = false;
1050    fReady = false;
1051
1052    return kIOReturnSuccess;
1053
1054}/* end disable */
1055
1056/****************************************************************************************************/
1057//
1058//		Method:		AppleUSBCDCEEM::setWakeOnMagicPacket
1059//
1060//		Inputs:		active - true(wake), false(don't)
1061//
1062//		Outputs:	Return code - kIOReturnSuccess
1063//
1064//		Desc:		Set for wake on magic packet
1065//
1066/****************************************************************************************************/
1067
1068IOReturn AppleUSBCDCEEM::setWakeOnMagicPacket(bool active)
1069{
1070    IOUSBDevRequest	devreq;
1071    IOReturn		ior = kIOReturnSuccess;
1072
1073    XTRACE(this, 0, active, "setWakeOnMagicPacket");
1074
1075    fWOL = active;
1076
1077    if (fConfigAttributes & kUSBAtrRemoteWakeup)
1078    {
1079
1080            // Set/Clear the Device Remote Wake feature depending upon the active flag
1081
1082		devreq.bmRequestType = USBmakebmRequestType(kUSBOut, kUSBStandard, kUSBDevice);
1083		if (active)
1084		{
1085			devreq.bRequest = kUSBRqSetFeature;
1086		} else {
1087			devreq.bRequest = kUSBRqClearFeature;
1088		}
1089		devreq.wValue = kUSBFeatureDeviceRemoteWakeup;
1090		devreq.wIndex = 0;
1091		devreq.wLength = 0;
1092		devreq.pData = 0;
1093
1094		ior = fDataInterface->GetDevice()->DeviceRequest(&devreq);
1095		if (ior == kIOReturnSuccess)
1096		{
1097			XTRACE(this, 0, ior, "setWakeOnMagicPacket - Set/Clear remote wake up feature successful");
1098		} else {
1099			XTRACE(this, 0, ior, "setWakeOnMagicPacket - Set/Clear remote wake up feature failed");
1100		}
1101    } else {
1102        XTRACE(this, 0, 0, "setWakeOnMagicPacket - Remote wake up not supported");
1103    }
1104
1105
1106    return kIOReturnSuccess;
1107
1108}/* end setWakeOnMagicPacket */
1109
1110/****************************************************************************************************/
1111//
1112//		Method:		AppleUSBCDCEEM::getPacketFilters
1113//
1114//		Inputs:		group - the filter group
1115//
1116//		Outputs:	Return code - kIOReturnSuccess and others
1117//				filters - the capability
1118//
1119//		Desc:		Set the filter capability for the driver
1120//
1121/****************************************************************************************************/
1122
1123IOReturn AppleUSBCDCEEM::getPacketFilters(const OSSymbol *group, UInt32 *filters) const
1124{
1125    IOReturn	rtn = kIOReturnSuccess;
1126
1127    XTRACE(this, 0, 0, "getPacketFilters");
1128
1129    if (group == gIOEthernetWakeOnLANFilterGroup)
1130    {
1131        if (fConfigAttributes & kUSBAtrRemoteWakeup)
1132        {
1133            *filters = kIOEthernetWakeOnMagicPacket;
1134        } else {
1135            *filters = 0;
1136        }
1137    } else {
1138        if (group == gIONetworkFilterGroup)
1139        {
1140            *filters = kIOPacketFilterUnicast | kIOPacketFilterBroadcast;
1141        } else {
1142            rtn = super::getPacketFilters(group, filters);
1143        }
1144    }
1145
1146    if (rtn != kIOReturnSuccess)
1147    {
1148        XTRACE(this, 0, rtn, "getPacketFilters - failed");
1149    }
1150
1151    return rtn;
1152
1153}/* end getPacketFilters */
1154
1155/****************************************************************************************************/
1156//
1157//		Method:		AppleUSBCDCEEM::selectMedium
1158//
1159//		Inputs:
1160//
1161//		Outputs:
1162//
1163//		Desc:		Lets us know if someone is playing with ifconfig
1164//
1165/****************************************************************************************************/
1166
1167IOReturn AppleUSBCDCEEM::selectMedium(const IONetworkMedium *medium)
1168{
1169
1170    XTRACE(this, 0, 0, "selectMedium");
1171
1172    setSelectedMedium(medium);
1173
1174    return kIOReturnSuccess;
1175
1176}/* end selectMedium */
1177
1178/****************************************************************************************************/
1179//
1180//		Method:		AppleUSBCDCEEM::getHardwareAddress
1181//
1182//		Inputs:
1183//
1184//		Outputs:	Return code - kIOReturnSuccess or kIOReturnError
1185//				ea - the address
1186//
1187//		Desc:		Make up an ethernet address for now
1188//					***** THIS IS TEMPORARY AND MUST BE CHANGED *****
1189//
1190/****************************************************************************************************/
1191
1192IOReturn AppleUSBCDCEEM::getHardwareAddress(IOEthernetAddress *ea)
1193{
1194    UInt32      i;
1195	OSNumber	*location;
1196    UInt32		locVal;
1197	UInt8		*rlocVal;
1198
1199    XTRACE(this, 0, 0, "getHardwareAddress");
1200
1201	location = (OSNumber *)fDataInterface->GetDevice()->getProperty(kUSBDevicePropertyLocationID);
1202	if (location)
1203	{
1204		locVal = location->unsigned32BitValue();
1205		rlocVal = (UInt8*)&locVal;
1206		ea->bytes[0] = 0x00;
1207		ea->bytes[1] = 0x03;
1208		for (i=0; i<4; i++)
1209		{
1210			ea->bytes[i+2] = rlocVal[i];
1211		}
1212	} else {
1213		XTRACE(this, 0, 0, "getHardwareAddress - Get location failed");
1214		return kIOReturnError;
1215	}
1216
1217    return kIOReturnSuccess;
1218
1219}/* end getHardwareAddress */
1220
1221/****************************************************************************************************/
1222//
1223//		Method:		AppleUSBCDCEEM::newVendorString
1224//
1225//		Inputs:
1226//
1227//		Outputs:	Return code - the vendor string
1228//
1229//		Desc:		Identifies the hardware vendor
1230//
1231/****************************************************************************************************/
1232
1233const OSString* AppleUSBCDCEEM::newVendorString() const
1234{
1235
1236    XTRACE(this, 0, 0, "newVendorString");
1237
1238    return OSString::withCString((const char *)defaultName);		// Maybe we should use the descriptors
1239
1240}/* end newVendorString */
1241
1242/****************************************************************************************************/
1243//
1244//		Method:		AppleUSBCDCEEM::newModelString
1245//
1246//		Inputs:
1247//
1248//		Outputs:	Return code - the model string
1249//
1250//		Desc:		Identifies the hardware model
1251//
1252/****************************************************************************************************/
1253
1254const OSString* AppleUSBCDCEEM::newModelString() const
1255{
1256
1257    XTRACE(this, 0, 0, "newModelString");
1258
1259    return OSString::withCString("USB");		// Maybe we should use the descriptors
1260
1261}/* end newModelString */
1262
1263/****************************************************************************************************/
1264//
1265//		Method:		AppleUSBCDCEEM::newRevisionString
1266//
1267//		Inputs:
1268//
1269//		Outputs:	Return code - the revision string
1270//
1271//		Desc:		Identifies the hardware revision
1272//
1273/****************************************************************************************************/
1274
1275const OSString* AppleUSBCDCEEM::newRevisionString() const
1276{
1277
1278    XTRACE(this, 0, 0, "newRevisionString");
1279
1280    return OSString::withCString("");
1281
1282}/* end newRevisionString */
1283
1284/****************************************************************************************************/
1285//
1286//		Method:		AppleUSBCDCEEM::setMulticastMode
1287//
1288//		Inputs:		active - true (set it), false (don't)
1289//
1290//		Outputs:	Return code - kIOReturnSuccess
1291//
1292//		Desc:		Sets multicast mode (not supported in this driver)
1293//
1294/****************************************************************************************************/
1295
1296IOReturn AppleUSBCDCEEM::setMulticastMode(bool active)
1297{
1298
1299    XTRACE(this, 0, active, "setMulticastMode");
1300
1301    return kIOReturnIOError;
1302
1303}/* end setMulticastMode */
1304
1305/****************************************************************************************************/
1306//
1307//		Method:		AppleUSBCDCEEM::setMulticastList
1308//
1309//		Inputs:		addrs - list of addresses
1310//				count - number in the list
1311//
1312//		Outputs:	Return code - kIOReturnSuccess or kIOReturnIOError
1313//
1314//		Desc:		Sets multicast list (not supported in this driver
1315//
1316/****************************************************************************************************/
1317
1318IOReturn AppleUSBCDCEEM::setMulticastList(IOEthernetAddress *addrs, UInt32 count)
1319{
1320//    bool	uStat;
1321
1322    XTRACE(this, 0, count, "setMulticastList");
1323
1324    return kIOReturnIOError;
1325
1326}/* end setMulticastList */
1327
1328/****************************************************************************************************/
1329//
1330//		Method:		AppleUSBCDCEEM::setPromiscuousMode
1331//
1332//		Inputs:		active - true (set it), false (don't)
1333//
1334//		Outputs:	Return code - kIOReturnSuccess
1335//
1336//		Desc:		Sets promiscuous mode (not supported by this driver)
1337//
1338/****************************************************************************************************/
1339
1340IOReturn AppleUSBCDCEEM::setPromiscuousMode(bool active)
1341{
1342
1343    XTRACE(this, 0, active, "setPromiscuousMode");
1344
1345    return kIOReturnIOError;
1346
1347}/* end setPromiscuousMode */
1348
1349/****************************************************************************************************/
1350//
1351//		Method:		AppleUSBCDCEEM::createOutputQueue
1352//
1353//		Inputs:
1354//
1355//		Outputs:	Return code - the output queue
1356//
1357//		Desc:		Creates the output queue
1358//
1359/****************************************************************************************************/
1360
1361IOOutputQueue* AppleUSBCDCEEM::createOutputQueue()
1362{
1363
1364    XTRACE(this, 0, 0, "createOutputQueue");
1365
1366    return IOBasicOutputQueue::withTarget(this, TRANSMIT_QUEUE_SIZE);
1367
1368}/* end createOutputQueue */
1369
1370/****************************************************************************************************/
1371//
1372//		Method:		AppleUSBCDCEEM::outputPacket
1373//
1374//		Inputs:		mbuf - the packet
1375//				param - optional parameter
1376//
1377//		Outputs:	Return code - kIOReturnOutputSuccess or kIOReturnOutputStall
1378//
1379//		Desc:		Packet transmission. The BSD mbuf needs to be formatted correctly
1380//				and transmitted
1381//
1382/****************************************************************************************************/
1383
1384UInt32 AppleUSBCDCEEM::outputPacket(mbuf_t pkt, void *param)
1385{
1386    UInt32	ior = kIOReturnSuccess;
1387
1388    XTRACE(this, 0, 0, "outputPacket");
1389
1390    if (!fLinkStatus)
1391    {
1392        XTRACE(this, 0, fLinkStatus, "outputPacket - link is down");
1393		fpNetStats->outputErrors++;
1394        freePacket(pkt);
1395        return kIOReturnOutputDropped;
1396    }
1397
1398    ior = USBTransmitPacket(pkt);
1399    if (ior != kIOReturnOutputStall)
1400    {
1401        freePacket(pkt);
1402    }
1403
1404    XTRACE(this, 0, ior, "outputPacket - Exit");
1405
1406    return ior;
1407
1408}/* end outputPacket */
1409
1410/****************************************************************************************************/
1411//
1412//		Method:		AppleUSBCDCEEM::configureInterface
1413//
1414//		Inputs:		netif - the interface being configured
1415//
1416//		Outputs:	Return code - true (configured ok), false (not)
1417//
1418//		Desc:		Finish the network interface configuration
1419//
1420/****************************************************************************************************/
1421
1422bool AppleUSBCDCEEM::configureInterface(IONetworkInterface *netif)
1423{
1424    IONetworkData	*nd;
1425
1426    XTRACE(this, 0, 0, "configureInterface");
1427
1428    if (super::configureInterface(netif) == false)
1429    {
1430        ALERT(0, 0, "configureInterface - super failed");
1431        return false;
1432    }
1433
1434        // Get a pointer to the statistics structure in the interface
1435
1436    nd = netif->getNetworkData(kIONetworkStatsKey);
1437    if (!nd || !(fpNetStats = (IONetworkStats *)nd->getBuffer()))
1438    {
1439        ALERT(0, 0, "configureInterface - Invalid network statistics");
1440        return false;
1441    }
1442
1443        // Get the Ethernet statistics structure
1444
1445    nd = netif->getParameter(kIOEthernetStatsKey);
1446    if (!nd || !(fpEtherStats = (IOEthernetStats*)nd->getBuffer()))
1447    {
1448        ALERT(0, 0, "configureInterface - Invalid ethernet statistics\n");
1449        return false;
1450    }
1451
1452    return true;
1453
1454}/* end configureInterface */
1455
1456/****************************************************************************************************/
1457//
1458//		Method:		AppleUSBCDCEEM::wakeUp
1459//
1460//		Inputs:
1461//
1462//		Outputs:	Return Code - true(we're awake), false(failed)
1463//
1464//		Desc:		Resumes the device it it was suspended and then gets all the data
1465//				structures sorted out and all the pipes ready.
1466//
1467/****************************************************************************************************/
1468
1469bool AppleUSBCDCEEM::wakeUp()
1470{
1471    IOReturn 	rtn = kIOReturnSuccess;
1472    UInt32	i;
1473    bool	readOK = false;
1474
1475    XTRACE(this, 0, 0, "wakeUp");
1476
1477    fReady = false;
1478
1479    setLinkStatus(0, 0);				// Initialize the link state
1480
1481    if (!allocateResources())
1482    {
1483        ALERT(0, 0, "wakeUp - allocateResources failed");
1484    	return false;
1485    }
1486
1487        // Kick off the data-in bulk pipe reads
1488
1489    for (i=0; i<fInBufPool; i++)
1490    {
1491        if (fPipeInBuff[i].pipeInMDP)
1492        {
1493            fPipeInBuff[i].readCompletionInfo.parameter = (void *)&fPipeInBuff[i];
1494            rtn = fInPipe->Read(fPipeInBuff[i].pipeInMDP, &fPipeInBuff[i].readCompletionInfo, NULL);
1495            if (rtn == kIOReturnSuccess)
1496            {
1497                readOK = true;
1498            } else {
1499                XTRACE(this, i, rtn, "wakeUp - Read failed");
1500            }
1501        }
1502    }
1503
1504    if (!readOK)
1505    {
1506
1507    	// We failed for some reason
1508
1509        ALERT(0, 0, "wakeUp - Starting the input pipe read(s) failed");
1510        return false;
1511    } else {
1512        if (!fMediumDict)
1513        {
1514            if (!createMediumTables())
1515            {
1516                ALERT(0, 0, "wakeUp - createMediumTables failed");
1517                return false;
1518            }
1519        }
1520
1521        fReady = true;
1522    }
1523
1524    return true;
1525
1526}/* end wakeUp */
1527
1528/****************************************************************************************************/
1529//
1530//		Method:		AppleUSBCDCEEM::putToSleep
1531//
1532//		Inputs:
1533//
1534//		Outputs:	Return Code - true(we're asleep), false(failed)
1535//
1536//		Desc:		Do clean up and suspend the device.
1537//
1538/****************************************************************************************************/
1539
1540void AppleUSBCDCEEM::putToSleep()
1541{
1542
1543    XTRACE(this, 0, 0, "putToSleep");
1544
1545    fReady = false;
1546
1547    setLinkStatus(0, 0);
1548
1549}/* end putToSleep */
1550
1551/****************************************************************************************************/
1552//
1553//		Method:		AppleUSBCDCEEM::createMediumTables
1554//
1555//		Inputs:
1556//
1557//		Outputs:	Return code - true (tables created), false (not created)
1558//
1559//		Desc:		Creates the medium tables
1560//
1561/****************************************************************************************************/
1562
1563bool AppleUSBCDCEEM::createMediumTables()
1564{
1565    IONetworkMedium	*medium;
1566    UInt64		maxSpeed;
1567    UInt32		i;
1568
1569    XTRACE(this, 0, 0, "createMediumTables");
1570
1571    maxSpeed = 100;
1572    fMediumDict = OSDictionary::withCapacity(sizeof(mediumTable) / sizeof(mediumTable[0]));
1573    if (fMediumDict == 0)
1574    {
1575        XTRACE(this, 0, 0, "createMediumTables - create dict. failed");
1576        return false;
1577    }
1578
1579    for (i = 0; i < sizeof(mediumTable) / sizeof(mediumTable[0]); i++)
1580    {
1581        medium = IONetworkMedium::medium(mediumTable[i].type, mediumTable[i].speed);
1582        if (medium && (medium->getSpeed() <= maxSpeed))
1583        {
1584            IONetworkMedium::addMedium(fMediumDict, medium);
1585            medium->release();
1586        }
1587    }
1588
1589    if (publishMediumDictionary(fMediumDict) != true)
1590    {
1591        XTRACE(this, 0, 0, "createMediumTables - publish dict. failed");
1592        return false;
1593    }
1594
1595    medium = IONetworkMedium::getMediumWithType(fMediumDict, kIOMediumEthernetAuto);
1596    setCurrentMedium(medium);
1597
1598    return true;
1599
1600}/* end createMediumTables */
1601
1602/****************************************************************************************************/
1603//
1604//		Method:		AppleUSBCDCEEM::allocateResources
1605//
1606//		Inputs:
1607//
1608//		Outputs:	return code - true (allocate was successful), false (it failed)
1609//
1610//		Desc:		Gets all the endpoints open and buffers allocated etc.
1611//
1612/****************************************************************************************************/
1613
1614bool AppleUSBCDCEEM::allocateResources()
1615{
1616    IOUSBFindEndpointRequest		epReq;
1617    UInt32				i;
1618
1619    XTRACE(this, 0, 0, "allocateResources.");
1620
1621        // Open all the end points
1622
1623    epReq.type = kUSBBulk;
1624    epReq.direction = kUSBIn;
1625    epReq.maxPacketSize	= 0;
1626    epReq.interval = 0;
1627    fInPipe = fDataInterface->FindNextPipe(0, &epReq);
1628    if (!fInPipe)
1629    {
1630        XTRACE(this, 0, 0, "allocateResources - no bulk input pipe.");
1631        return false;
1632    }
1633    XTRACE(this, epReq.maxPacketSize << 16 |epReq.interval, 0, "allocateResources - bulk input pipe.");
1634
1635    epReq.direction = kUSBOut;
1636    fOutPipe = fDataInterface->FindNextPipe(0, &epReq);
1637    if (!fOutPipe)
1638    {
1639        XTRACE(this, 0, 0, "allocateResources - no bulk output pipe.");
1640        return false;
1641    }
1642    fOutPacketSize = epReq.maxPacketSize;
1643    XTRACE(this, epReq.maxPacketSize << 16 |epReq.interval, 0, "allocateResources - bulk output pipe.");
1644
1645        // Allocate Memory Descriptor Pointer with memory for the data-in bulk pipe
1646
1647    for (i=0; i<fInBufPool; i++)
1648    {
1649//		fPipeInBuff[i].pipeInMDP = IOBufferMemoryDescriptor::withCapacity(fMax_Block_Size, kIODirectionIn);
1650        fPipeInBuff[i].pipeInMDP = IOBufferMemoryDescriptor::withOptions(kIODirectionIn | kIOMemoryPhysicallyContiguous, fMax_Block_Size, PAGE_SIZE);
1651        if (!fPipeInBuff[i].pipeInMDP)
1652        {
1653            XTRACE(this, 0, i, "allocateResources - Allocate input descriptor failed");
1654            return false;
1655        }
1656
1657		fPipeInBuff[i].pipeInMDP->setLength(fMax_Block_Size);
1658        fPipeInBuff[i].pipeInBuffer = (UInt8*)fPipeInBuff[i].pipeInMDP->getBytesNoCopy();
1659        XTRACE(this, 0, i, "allocateResources - input buffer");
1660        fPipeInBuff[i].dead = false;
1661        fPipeInBuff[i].readCompletionInfo.target = this;
1662        fPipeInBuff[i].readCompletionInfo.action = dataReadComplete;
1663        fPipeInBuff[i].readCompletionInfo.parameter = NULL;
1664    }
1665
1666        // Allocate Memory Descriptor Pointers with memory for the data-out bulk pipe pool
1667
1668    for (i=0; i<fOutBufPool; i++)
1669    {
1670//		fPipeOutBuff[i].pipeOutMDP = IOBufferMemoryDescriptor::withCapacity(fMax_Block_Size, kIODirectionOut);
1671        fPipeOutBuff[i].pipeOutMDP = IOBufferMemoryDescriptor::withOptions(kIODirectionOut | kIOMemoryPhysicallyContiguous, fMax_Block_Size, PAGE_SIZE);
1672        if (!fPipeOutBuff[i].pipeOutMDP)
1673        {
1674            XTRACE(this, 0, i, "allocateResources - Allocate output descriptor failed");
1675            return false;
1676        }
1677
1678		fPipeOutBuff[i].pipeOutMDP->setLength(fMax_Block_Size);
1679        fPipeOutBuff[i].pipeOutBuffer = (UInt8*)fPipeOutBuff[i].pipeOutMDP->getBytesNoCopy();
1680        XTRACE(this, 0, i, "allocateResources - output buffer");
1681        fPipeOutBuff[i].avail = true;
1682        fPipeOutBuff[i].writeCompletionInfo.target = this;
1683        fPipeOutBuff[i].writeCompletionInfo.action = dataWriteComplete;
1684        fPipeOutBuff[i].writeCompletionInfo.parameter = NULL;				// for now, filled in with pool index when sent
1685    }
1686
1687    return true;
1688
1689}/* end allocateResources */
1690
1691/****************************************************************************************************/
1692//
1693//		Method:		AppleUSBCDCEEM::releaseResources
1694//
1695//		Inputs:
1696//
1697//		Outputs:
1698//
1699//		Desc:		Frees up the resources allocated in allocateResources
1700//
1701/****************************************************************************************************/
1702
1703void AppleUSBCDCEEM::releaseResources()
1704{
1705    UInt32	i;
1706
1707    XTRACE(this, 0, 0, "releaseResources");
1708
1709    for (i=0; i<fOutBufPool; i++)
1710    {
1711        if (fPipeOutBuff[i].pipeOutMDP)
1712        {
1713            fPipeOutBuff[i].pipeOutMDP->release();
1714            fPipeOutBuff[i].pipeOutMDP = NULL;
1715            fPipeOutBuff[i].avail = false;
1716            fPipeOutBuff[i].writeCompletionInfo.target = NULL;
1717            fPipeOutBuff[i].writeCompletionInfo.action = NULL;
1718            fPipeOutBuff[i].writeCompletionInfo.parameter = NULL;
1719        }
1720    }
1721    fOutPoolIndex = 0;
1722
1723    for (i=0; i<fInBufPool; i++)
1724    {
1725        if (fPipeInBuff[i].pipeInMDP)
1726        {
1727            fPipeInBuff[i].pipeInMDP->release();
1728            fPipeInBuff[i].pipeInMDP = NULL;
1729            fPipeInBuff[i].dead = false;
1730            fPipeInBuff[i].readCompletionInfo.target = NULL;
1731            fPipeInBuff[i].readCompletionInfo.action = NULL;
1732            fPipeInBuff[i].readCompletionInfo.parameter = NULL;
1733        }
1734    }
1735
1736}/* end releaseResources */
1737
1738/****************************************************************************************************/
1739//
1740//		Method:		AppleUSBCDCEEM::getOutputBuffer
1741//
1742//		Inputs:		bufIndx - index of an available buffer
1743//
1744//		Outputs:	Return code - True (got one), False (none available)
1745//
1746//		Desc:		Get an available buffer from the output buffer pool
1747//
1748/****************************************************************************************************/
1749
1750bool AppleUSBCDCEEM::getOutputBuffer(UInt32 *bufIndx)
1751{
1752	bool	gotBuffer = false;
1753	UInt32	indx;
1754
1755	XTRACE(this, 0, 0, "getOutputBuffer");
1756
1757	if (fBufferPoolLock)
1758    {
1759        IOLockLock(fBufferPoolLock);
1760    } else {
1761		return false;
1762	}
1763
1764	while (!gotBuffer)
1765	{
1766			// Get an ouput buffer (use the hint first then if that's not available look for one)
1767
1768		indx = fOutPoolIndex;
1769		if (!fPipeOutBuff[indx].avail)
1770		{
1771			for (indx=0; indx<fOutBufPool; indx++)
1772			{
1773				if (fPipeOutBuff[indx].avail)
1774				{
1775					fOutPoolIndex = indx;
1776					gotBuffer = true;
1777					break;
1778				}
1779			}
1780		} else {
1781			gotBuffer = true;
1782		}
1783
1784		if (gotBuffer)
1785		{
1786			fPipeOutBuff[indx].avail = false;
1787			fOutPoolIndex++;
1788			if (fOutPoolIndex >= fOutBufPool)
1789			{
1790				fOutPoolIndex = 0;
1791			}
1792		}
1793        break;
1794    }
1795
1796	IOLockUnlock(fBufferPoolLock);
1797
1798	*bufIndx = indx;
1799
1800	return gotBuffer;
1801
1802}/* end getOutputBuffer */
1803
1804/****************************************************************************************************/
1805//
1806//		Method:		AppleUSBCDCEEM::USBTransmitPacket
1807//
1808//		Inputs:		packet - the packet
1809//
1810//		Outputs:	Return code - kIOReturnSuccess (transmit started), everything else (it didn't)
1811//
1812//		Desc:		Set up and then transmit the packet.
1813//
1814/****************************************************************************************************/
1815
1816IOReturn AppleUSBCDCEEM::USBTransmitPacket(mbuf_t packet)
1817{
1818    UInt32		numbufs = 0;			// number of mbufs for this packet
1819    mbuf_t		m;					// current mbuf
1820    UInt32		total_pkt_length = 0;
1821    UInt32		rTotal = 0;
1822    IOReturn	ior = kIOReturnSuccess;
1823    UInt32		indx;
1824
1825    XTRACE(this, 0, 0, "USBTransmitPacket");
1826
1827        // Count the number of mbufs in this packet
1828
1829    m = packet;
1830    while (m)
1831	{
1832		if (mbuf_len(m) != 0)
1833		{
1834			total_pkt_length += mbuf_len(m);
1835			numbufs++;
1836		}
1837		m = mbuf_next(m);
1838    }
1839
1840    XTRACE(this, total_pkt_length, numbufs, "USBTransmitPacket - Total packet length and Number of mbufs");
1841
1842	if (total_pkt_length > fMax_Block_Size)
1843    {
1844        XTRACE(this, 0, 0, "USBTransmitPacket - Bad packet size");	// Note for now and revisit later
1845		fpNetStats->outputErrors++;
1846        return kIOReturnInternalError;
1847    }
1848
1849    if (!getOutputBuffer(&indx))
1850	{
1851		ALERT(fOutBufPool, fOutPoolIndex, "USBTransmitPacket - Output buffer unavailable");
1852        fTxStalled = true;
1853		return kIOReturnOutputStall;
1854	}
1855
1856        // Start filling in the send buffer
1857
1858	m = packet;							// start with the first mbuf of the packet
1859    rTotal = 0;							// running total
1860    do
1861    {
1862        if (mbuf_len(m) == 0)			// Ignore zero length buffers
1863			continue;
1864
1865        bcopy(mbuf_data(m), &fPipeOutBuff[indx].pipeOutBuffer[rTotal], mbuf_len(m));
1866        rTotal += mbuf_len(m);
1867
1868    } while ((m = mbuf_next(m)) != 0);
1869
1870    LogData(kDataOut, rTotal, fPipeOutBuff[indx].pipeOutBuffer);
1871
1872    fPipeOutBuff[indx].m = packet;
1873    fPipeOutBuff[indx].writeCompletionInfo.parameter = (void *)&fPipeOutBuff[indx];
1874    fPipeOutBuff[indx].pipeOutMDP->setLength(rTotal);
1875    ior = fOutPipe->Write(fPipeOutBuff[indx].pipeOutMDP, &fPipeOutBuff[indx].writeCompletionInfo);
1876    if (ior != kIOReturnSuccess)
1877    {
1878        XTRACE(this, 0, ior, "USBTransmitPacket - Write failed");
1879        if (ior == kIOUSBPipeStalled)
1880        {
1881            fOutPipe->Reset();
1882            ior = fOutPipe->Write(fPipeOutBuff[indx].pipeOutMDP, &fPipeOutBuff[indx].writeCompletionInfo);
1883            if (ior != kIOReturnSuccess)
1884            {
1885                XTRACE(this, 0, ior, "USBTransmitPacket - Write really failed");
1886				fpNetStats->outputErrors++;
1887                return ior;
1888            }
1889        }
1890    }
1891
1892	fpNetStats->outputPackets++;
1893
1894    return ior;
1895
1896}/* end USBTransmitPacket */
1897
1898/****************************************************************************************************/
1899//
1900//		Method:		AppleUSBCDCEEM::USBSendCommand
1901//
1902//		Inputs:		command - the command to be sent
1903//					length - length of any data to be sent
1904//					anyData - any actual data (must be present if length > 0)
1905//
1906//		Outputs:	Return code - kIOReturnSuccess (transmit started), everything else (it didn't)
1907//
1908//		Desc:		Set up and a command packet.
1909//
1910/****************************************************************************************************/
1911
1912IOReturn AppleUSBCDCEEM::USBSendCommand(UInt16 command, UInt16 length, UInt8 *anyData)
1913{
1914	IOReturn	ior = kIOReturnSuccess;
1915    UInt32		indx;
1916    bool		gotBuffer = false;
1917	UInt16		EEMHeader = bmTypeCommand;
1918
1919    XTRACE(this, command, length, "USBSendCommand");
1920
1921	if ((length > 0) && (anyData == NULL))
1922	{
1923		return kIOReturnBadArgument;
1924	}
1925
1926		// Get an ouput buffer (use the hint first then if that's not available look for one)
1927
1928    if (fBufferPoolLock)
1929    {
1930        IOLockLock(fBufferPoolLock);
1931    }
1932
1933    indx = fOutPoolIndex;
1934    if (!fPipeOutBuff[indx].avail)
1935    {
1936        for (indx=0; indx<fOutBufPool; indx++)
1937        {
1938            if (fPipeOutBuff[indx].avail)
1939            {
1940                fOutPoolIndex = indx;
1941                gotBuffer = true;
1942                break;
1943            }
1944        }
1945        if (!gotBuffer)
1946        {
1947            XTRACE(this, fOutBufPool, fOutPoolIndex, "USBSendCommand - Output buffer unavailable");
1948			fpNetStats->outputErrors++;
1949            if (fBufferPoolLock)
1950            {
1951                IOLockUnlock(fBufferPoolLock);
1952            }
1953            return kIOReturnInternalError;
1954        }
1955    }
1956    fOutPoolIndex++;
1957    if (fOutPoolIndex >= fOutBufPool)
1958    {
1959        fOutPoolIndex = 0;
1960    }
1961
1962    if (fBufferPoolLock)
1963    {
1964        IOLockUnlock(fBufferPoolLock);
1965    }
1966
1967		// Now handle the data
1968
1969	EEMHeader |= command;
1970	EEMHeader |= length;
1971
1972	bcopy(&EEMHeader, fPipeOutBuff[indx].pipeOutBuffer, sizeof(EEMHeader));
1973	if (length > 0)
1974	{
1975		bcopy(anyData, &fPipeOutBuff[indx].pipeOutBuffer[2], length);
1976	}
1977
1978    LogData(kDataOut, length+2, fPipeOutBuff[indx].pipeOutBuffer);
1979
1980    fPipeOutBuff[indx].m = NULL;
1981    fPipeOutBuff[indx].writeCompletionInfo.parameter = (void *)indx;
1982    fPipeOutBuff[indx].pipeOutMDP->setLength(length+2);
1983    ior = fOutPipe->Write(fPipeOutBuff[indx].pipeOutMDP, &fPipeOutBuff[indx].writeCompletionInfo);
1984    if (ior != kIOReturnSuccess)
1985    {
1986        XTRACE(this, 0, ior, "USBSendCommand - Write failed");
1987        if (ior == kIOUSBPipeStalled)
1988        {
1989            fOutPipe->Reset();
1990            ior = fOutPipe->Write(fPipeOutBuff[indx].pipeOutMDP, &fPipeOutBuff[indx].writeCompletionInfo);
1991            if (ior != kIOReturnSuccess)
1992            {
1993                XTRACE(this, 0, ior, "USBSendCommand - Write really failed");
1994				fpNetStats->outputErrors++;
1995                return ior;
1996            }
1997        }
1998    }
1999
2000	fpNetStats->outputPackets++;
2001
2002    return ior;
2003
2004}/* end USBSendCommand */
2005
2006/****************************************************************************************************/
2007//
2008//		Method:		AppleUSBCDCEEM::clearPipeStall
2009//
2010//		Inputs:		thePipe - the pipe
2011//
2012//		Outputs:
2013//
2014//		Desc:		Clear a stall on the specified pipe.
2015//
2016/****************************************************************************************************/
2017
2018IOReturn AppleUSBCDCEEM::clearPipeStall(IOUSBPipe *thePipe)
2019{
2020    IOReturn 	rtn = kIOReturnSuccess;
2021
2022    XTRACE(this, 0, 0, "clearPipeStall");
2023
2024    rtn = thePipe->GetPipeStatus();
2025    if (rtn == kIOUSBPipeStalled)
2026    {
2027        rtn = thePipe->ClearPipeStall(true);
2028        if (rtn == kIOReturnSuccess)
2029        {
2030            XTRACE(this, 0, 0, "clearPipeStall - Successful");
2031        } else {
2032            XTRACE(this, 0, rtn, "clearPipeStall - Failed");
2033        }
2034    } else {
2035        XTRACE(this, 0, 0, "clearPipeStall - Pipe not stalled");
2036    }
2037
2038    return rtn;
2039
2040}/* end clearPipeStall */
2041
2042/****************************************************************************************************/
2043//
2044//		Method:		AppleUSBCDCEEM::receivePacket
2045//
2046//		Inputs:		packet - the packet
2047//				size - Number of bytes in the packet
2048//
2049//		Outputs:
2050//
2051//		Desc:		Build the mbufs and then send to the network stack.
2052//
2053/****************************************************************************************************/
2054
2055void AppleUSBCDCEEM::receivePacket(UInt8 *packet, UInt32 size)
2056{
2057    mbuf_t		m;
2058    UInt32		submit;
2059
2060    XTRACE(this, 0, size, "receivePacket");
2061
2062	if (size > fMax_Block_Size)
2063    {
2064        XTRACE(this, 0, 0, "receivePacket - Packet size error, packet dropped");
2065		fpNetStats->inputErrors++;
2066        return;
2067    }
2068
2069    m = allocatePacket(size);
2070    if (m)
2071    {
2072        bcopy(packet, mbuf_data(m), size);
2073        submit = fNetworkInterface->inputPacket(m, size);
2074        XTRACE(this, 0, submit, "receivePacket - Packets submitted");
2075		fpNetStats->inputPackets++;
2076    } else {
2077        XTRACE(this, 0, 0, "receivePacket - Buffer allocation failed, packet dropped");
2078		fpNetStats->inputErrors++;
2079    }
2080
2081}/* end receivePacket */
2082
2083/****************************************************************************************************/
2084//
2085//		Method:		AppleUSBCDCEEM::processEEMCommand
2086//
2087//		Inputs:		EEMHeader - the EEM packet header
2088//					poolIndx - Index into the buffer pool
2089//					dataIndx - Index into the buffer for the current command
2090//
2091//		Outputs:	len - actual length of the command
2092//
2093//		Desc:		Handle the EEM command.
2094//
2095/****************************************************************************************************/
2096
2097void AppleUSBCDCEEM::processEEMCommand(UInt16 EEMHeader, UInt32 poolIndx, SInt16 dataIndx, SInt16 *len)
2098{
2099	IOReturn 	rtn = kIOReturnSuccess;
2100	UInt16		EEMCommand;
2101	UInt16		param;
2102	UInt8		*buff = NULL;
2103
2104    XTRACE(this, EEMHeader, poolIndx, "processEEMCommand");
2105
2106	EEMCommand = EEMHeader & bmEEMCmdMask;
2107	param = EEMHeader & bmEEMCmdParamMask;
2108
2109	switch (EEMCommand)
2110    {
2111        case EEMEcho:
2112			XTRACE(this, EEMCommand, param, "processEEMCommand - Echo");
2113			if (param != 0)
2114			{
2115				buff = &fPipeInBuff[poolIndx].pipeInBuffer[2];
2116			}
2117			rtn = USBSendCommand(EEMEchoResponse, param, buff);
2118			if (rtn != kIOReturnSuccess)
2119			{
2120				XTRACE(this, 0, rtn, "processEEMCommand - Failed to send echo response");
2121			}
2122			*len = param + 2;
2123            break;
2124        case EEMEchoResponse:
2125			XTRACE(this, EEMCommand, param, "processEEMCommand - Echo Response");
2126
2127			*len = param + 2;
2128			break;
2129		case EEMSuspendHint:
2130			XTRACE(this, EEMCommand, param, "processEEMCommand - Suspend Hint");
2131
2132			*len = 2;
2133            break;
2134        case EEMResponseHint:
2135			XTRACE(this, EEMCommand, param, "processEEMCommand - Response Hint");
2136
2137			*len = 2;
2138			break;
2139		case EEMResponseCompleteHint:
2140			XTRACE(this, EEMCommand, param, "processEEMCommand - Response Hint Complete");
2141
2142			*len = 2;
2143            break;
2144        case EEMTickle:
2145			XTRACE(this, EEMCommand, param, "processEEMCommand - Tickle");
2146
2147			*len = 2;
2148			break;
2149		default:
2150            XTRACE(this, EEMCommand, param, "processEEMCommand - unknown command");
2151			*len = 2;
2152            break;
2153    }
2154
2155}/* end processEEMCommand */
2156
2157/****************************************************************************************************/
2158//
2159//		Method:		AppleUSBCDCEEM::message
2160//
2161//		Inputs:		type - message type
2162//				provider - my provider
2163//				argument - additional parameters
2164//
2165//		Outputs:	return Code - kIOReturnSuccess
2166//
2167//		Desc:		Handles IOKit messages.
2168//
2169/****************************************************************************************************/
2170
2171IOReturn AppleUSBCDCEEM::message(UInt32 type, IOService *provider, void *argument)
2172{
2173    UInt16	i;
2174    IOReturn	ior;
2175
2176    XTRACE(this, 0, type, "message");
2177
2178    switch (type)
2179    {
2180        case kIOMessageServiceIsTerminated:
2181            XTRACE(this, fReady, type, "message - kIOMessageServiceIsTerminated");
2182
2183            if (fReady)
2184            {
2185                if (!fTerminate)		// Check if we're already being terminated
2186                {
2187#if 0
2188		    // NOTE! This call below depends on the hard coded path of this KEXT. Make sure
2189		    // that if the KEXT moves, this path is changed!
2190		    KUNCUserNotificationDisplayNotice(
2191			0,		// Timeout in seconds
2192			0,		// Flags (for later usage)
2193			"",		// iconPath (not supported yet)
2194			"",		// soundPath (not supported yet)
2195			"/System/Library/Extensions/IOUSBFamily.kext/Contents/PlugIns/AppleUSBCDCEEM.kext",	// localizationPath
2196			"Unplug Header",		// the header
2197			"Unplug Notice",		// the notice - look in Localizable.strings
2198			"OK");
2199#endif
2200                }
2201            }
2202
2203            releaseResources();
2204            if (fDataInterface)
2205            {
2206                fDataInterface->close(this);
2207                fDataInterface->release();
2208                fDataInterface = NULL;
2209            }
2210            fTerminate = true;		// we're being terminated (unplugged)
2211            fLinkStatus = 0;		// and of course we're offline
2212            return kIOReturnSuccess;
2213        case kIOMessageServiceIsSuspended:
2214            XTRACE(this, 0, type, "message - kIOMessageServiceIsSuspended");
2215            break;
2216        case kIOMessageServiceIsResumed:
2217            XTRACE(this, 0, type, "message - kIOMessageServiceIsResumed");
2218            break;
2219        case kIOMessageServiceIsRequestingClose:
2220            XTRACE(this, 0, type, "message - kIOMessageServiceIsRequestingClose");
2221            break;
2222        case kIOMessageServiceWasClosed:
2223            XTRACE(this, 0, type, "message - kIOMessageServiceWasClosed");
2224            break;
2225        case kIOMessageServiceBusyStateChange:
2226            XTRACE(this, 0, type, "message - kIOMessageServiceBusyStateChange");
2227            break;
2228        case kIOUSBMessagePortHasBeenResumed:
2229            XTRACE(this, 0, type, "message - kIOUSBMessagePortHasBeenResumed");
2230            for (i=0; i<fInBufPool; i++)
2231            {
2232                if (fPipeInBuff[i].dead)			// If it's dead try and resurrect it
2233                {
2234                    ior = fInPipe->Read(fPipeInBuff[i].pipeInMDP, &fPipeInBuff[i].readCompletionInfo, NULL);
2235                    if (ior != kIOReturnSuccess)
2236                    {
2237                        XTRACE(this, 0, ior, "message - Read io error");
2238                    } else {
2239                        fPipeInBuff[i].dead = false;
2240                    }
2241                }
2242            }
2243            return kIOReturnSuccess;
2244        case kIOUSBMessageHubResumePort:
2245            XTRACE(this, 0, type, "message - kIOUSBMessageHubResumePort");
2246            break;
2247        default:
2248            XTRACE(this, 0, type, "message - unknown message");
2249            break;
2250    }
2251
2252    return super::message(type, provider, argument);
2253
2254}/* end message */