Annotation of kernel/bsd/dev/ppc/drvUSBCMD/Library/USLhubs.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this 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 OR NON-INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: 
                     25: /*
                     26:        File:           USLhubs.c
                     27: 
                     28:        Contains:       Hub specific functions for the USL (mainly add and subtract devices)
                     29: 
                     30:        Version:        Nepturn 1.0
                     31: 
                     32:        Copyright:      � 1997-1998 by Apple Computer, Inc., all rights reserved.
                     33: 
                     34:        File Ownership:
                     35: 
                     36:                DRI:                            Barry Twycross
                     37: 
                     38:                Other Contact:          xxx put other contact here xxx
                     39: 
                     40:                Technology:                     USB
                     41: 
                     42:        Writers:
                     43: 
                     44:                (DF)    David Ferguson
                     45:                (CJK)   Craig Keithley
                     46:                (BT)    Barry Twycross
                     47:                
                     48:        Change History (most recent first):
                     49: 
                     50:         <USB40>         11/4/98        BT              Comment inobvious zering of refCon
                     51:         <USB39>        10/29/98        BT              Close old configurations on reset or reconfiguration.
                     52:         <USB38>         10/7/98        BT              Fix hub not killing children
                     53:         <USB37>         10/3/98        BT              Add more port reset stuff
                     54:         <USB36>         9/29/98        BT              Use real frame timing
                     55:         <USB35>         9/28/98        BT              Add device reset function
                     56:         <USB34>         9/17/98        BT              1.1 rules for captive devices.
                     57:         <USB33>         8/25/98        BT              Isoc name changes
                     58:         <USB32>         8/24/98        BT              Cope without #define for reserved4
                     59:         <USB31>         8/13/98        BT              Add multibus support
                     60:         <USB30>         7/10/98        BT              DO secondary interrupt right, set address fail returns ref 0.
                     61:         <USB29>          7/9/98        BT              Fix previous fixes. Secondary interrupt does not queue secondary
                     62:                                                                        interrupt
                     63:         <USB28>          7/9/98        BT              Clean up queues when device deleted
                     64:         <USB27>         6/15/98        BT              Cope with 1.1 hubs speed detection
                     65:         <USB26>         6/14/98        DF              Add RemoveRootHub function
                     66:         <USB25>          6/5/98        BT              Pass pb to delete device
                     67:         <USB24>         5/20/98        BT              Version 2 PB new names
                     68:         <USB23>         4/29/98        BT              FIx negative timeout
                     69:         <USB22>         4/26/98        BT              FIx timeout adding dead device
                     70:         <USB21>         4/23/98        BT              Add watchdog
                     71:         <USB20>         4/21/98        BT              Allow requests to device zero, pipe zero.
                     72:         <USB19>         4/16/98        BT              Eliminate debugger
                     73:         <USB18>         4/14/98        BT              Impliment device remove
                     74:         <USB17>         4/10/98        BT              Add device remove
                     75:         <USB16>          4/9/98        CJK             remove uimpriv.h and uslpriv.h
                     76:         <USB15>          4/9/98        BT              Use USB.h
                     77:                <14>      4/8/98        BT              More error checking
                     78:                <13>      4/6/98        BT              Change w names
                     79:                <12>      4/6/98        BT              New param block names
                     80:                <11>      4/2/98        BT              Eliminate obsolete delay function
                     81:                <10>     2/23/98        BT              Only add device if set address was sucessful
                     82:                 <9>      2/4/98        BT              Fix uslControlPacket to have errors. Add more support for
                     83:                                                                        usbProbe
                     84:                 <8>     1/26/98        BT              Mangle names after design review
                     85:                 <7>     1/15/98        CJK             Change include of USL.h to USBServicesLib.h
                     86:                 <6>     1/13/98        BT              Change uslPacket to uslControlPacket
                     87:                 <5>    12/19/97        BT              UIM now a Shared lib
                     88:                 <4>    12/18/97        BT              Fix header dependancies and add expert call back
                     89: */
                     90: 
                     91: #include "../USB.h"
                     92: #include "../USBpriv.h"
                     93:                 
                     94: #include "../uimpriv.h"
                     95: #include "uslpriv.h"   
                     96:                 
                     97: #include "../driverservices.h"
                     98: 
                     99: 
                    100: static QHdrPtr hubAddQueue;
                    101: static unsigned long hubAddFlag = 0;
                    102: static USBDeviceRef deviceZero;
                    103: static UInt32 busZero;
                    104: static Duration lastAdd;
                    105: static USBPB timeout={0,0, sizeof(USBPB), kUSBCurrentPBVersion};
                    106: 
                    107: void initialiseHubs(void)
                    108: {
                    109:        if( (PBQueueCreate(&hubAddQueue) != noErr) ||
                    110:                (PBQueueInit(hubAddQueue) != noErr) )
                    111:        {
                    112:                /* Panic */
                    113:                USBExpertStatus(0,"USL - failed to initialise hub queue", 0);
                    114:        }
                    115: }
                    116: 
                    117: void finaliseHubs(void)
                    118: {
                    119:        // really need to count the busses!
                    120:        //RemoveRootHub(0);     // This should only happen if bus is removed????
                    121:        //PBQueueDelete(hubAddQueue);
                    122: }
                    123: 
                    124: Boolean uslHubValidateDevZero(USBDeviceRef ref, UInt32 *bus)
                    125: {
                    126:        if(bus != nil)
                    127:        {
                    128:                *bus = busZero;
                    129:        }
                    130:        return(ref == deviceZero);
                    131: }
                    132: 
                    133: OSStatus USBHubConfigurePipeZero(USBPB *pb)
                    134: {
                    135: UInt32 bus=0;
                    136:        if(!checkPBVersion(pb, 1))
                    137:        {
                    138:                return(pb->usbStatus);
                    139:        }
                    140:        if(pb->pbVersion == 2)  // v1.00+ only
                    141:        {
                    142:                pb->usbStatus = kUSBPBVersionError;
                    143:                return(pb->usbStatus);
                    144:        }
                    145:        if(!uslHubValidateDevZero(pb->usbReference, &bus))
                    146:        {
                    147:                pb->usbStatus = kUSBUnknownDeviceErr;
                    148:                return(pb->usbStatus);          
                    149:        }
                    150: 
                    151: kprintf("USBHubConfigurePipeZero:calling UIMControlEDCreate\n");
                    152:        pb->usbStatus = UIMControlEDCreate(bus, 0, 0, pb->usb.cntl.WValue, pb->usbFlags);
                    153:        (*pb->usbCompletion)(pb);       
                    154:        return(kUSBPending);
                    155: }
                    156: 
                    157: 
                    158: void uslCleanHubQueue(USBDeviceRef ref)
                    159: {      // This is assuming its called at secondary interrupt time.
                    160:        uslCleanAQueue(hubAddQueue, ref);
                    161: }
                    162: 
                    163: static void processAddQ(void)
                    164: {
                    165: OSStatus err;
                    166: USBPB *pb;
                    167:        if(CompareAndSwap(0, 1, &hubAddFlag))
                    168:        {       /* We now have the queue*/
                    169:                if(PBDequeueFirst(hubAddQueue, (void *)&pb) == noErr)
                    170:                {
                    171: 
                    172:                        // Could validate ref here.
                    173:                        
                    174:                        busZero = pb->usbOther;
                    175:                        lastAdd = deltaFrames(0, busZero);
                    176:                        if(pb->pbVersion == 2)
                    177:                        {
                    178: kprintf("processAddQ:calling UIMControlEDCreate\n");
                    179:                                err = UIMControlEDCreate(busZero, 0, 0, 8, pb->usbFlags);
                    180:                        /* Error checking ??? */
                    181:                        }
                    182:                        
                    183:                        deviceZero = MakeDevRef(busZero, 0);
                    184:                        pb->usbReference = deviceZero;
                    185:                        pb->usbStatus = noErr;
                    186:                        (*pb->usbCompletion)(pb);
                    187:                }
                    188:        }
                    189: }
                    190: 
                    191: /* Takes bus in reference */
                    192: 
                    193: void uslHubAddDevice(USBPB *pb)
                    194: {
                    195:        pb->qType = kUSBHubQType;
                    196:        pb->usbStatus = kUSBPending;
                    197:        PBEnqueueLast((void *)pb, hubAddQueue);
                    198:        processAddQ();
                    199: }
                    200: 
                    201: OSStatus USBHubAddDevice(USBPB *pb)
                    202: {
                    203: UInt32 bus;
                    204: 
                    205:        pb->usbStatus = validateRef(pb->usbReference, &bus);
                    206:        if(pb->usbStatus != noErr)
                    207:        {
                    208:                return(pb->usbStatus);
                    209:        }
                    210: 
                    211:        if(!checkPBVersion(pb, 1))
                    212:        {
                    213:                return(pb->usbStatus);
                    214:        }
                    215: 
                    216:        pb->usbOther = bus;
                    217:        uslHubAddDevice(pb);
                    218:        
                    219:        return(kUSBPending);
                    220: }
                    221: 
                    222: /* Takes bus in reference */
                    223: 
                    224: static void setAddressHandler(USBPB *pb)
                    225: {
                    226: UInt32 bus;
                    227: UInt32 power;
                    228: 
                    229:        bus = busZero;
                    230: 
                    231: //     UIMEDDelete(0, 0, 0);
                    232: kprintf("setAddressHandler: calling UIMControlEDDelete\n");
                    233:        UIMControlEDDelete(bus, 0, 0);
                    234:        deviceZero = 0;
                    235:        lastAdd = 0;
                    236:        
                    237:        if(pb->reserved2 != nil)
                    238:        {       /* real user call back */
                    239:                if(pb->usbStatus == noErr)
                    240:                {
                    241:                        power = ( (pb->usbFlags & kUSBHubPower) != 0)?pb->usbOther:kUSB500mAAvailable;
                    242:                        if((pb->usbFlags & kUSBHubReaddress) == 0)
                    243:                        {
                    244:                                /* Note, this is relying on having usbValue swapped by uiminterface */
                    245:                                pb->usbReference = addNewDevice(bus, pb->usb.cntl.WValue,  pb->usbFlags&1, pb->wValueStash, power);
                    246:                        }
                    247:                }
                    248:                else
                    249:                {
                    250:                        pb->usbReference = 0;
                    251:                        USBExpertStatus(0, "USL - Error setting address:", pb->usbReference);
                    252:                }
                    253:        
                    254:                pb->usbCompletion = (void *)pb->reserved2;
                    255:                (*pb->usbCompletion)(pb);
                    256:        }
                    257:        else
                    258:        {       /* timeout call back */
                    259:        
                    260:                /* This really is refcon, not reference, this is not a bug. */
                    261:                /* This is the call back from the watchdog timer */
                    262:                pb->usbRefcon = 0;
                    263:        }       
                    264:        CompareAndSwap(1, 0, &hubAddFlag);      /* Unlock the queue */
                    265:        
                    266:        if(hubAddQueue->qHead != nil)
                    267:        {
                    268:                processAddQ();
                    269:        }
                    270: }
                    271: 
                    272: 
                    273: 
                    274: static void uslHubSetAddress(USBPB *pb)
                    275: {
                    276: OSStatus err;
                    277:        pb->reserved2 = (UInt32) pb->usbCompletion;
                    278:        pb->usbCompletion = setAddressHandler;
                    279:        pb->wValueStash = pb->usb.cntl.WValue;
                    280: 
                    281:        /* Note this does not have to faff around with */
                    282:        /* pbVersion etc its writing a packet directly */
                    283:        pb->usb.cntl.BMRequestType = 0; /* bmRqTyp = 0, bRq = 5 */
                    284:        pb->usb.cntl.BRequest = kUSBRqSetAddress;       /* bmRqTyp = 0, bRq = 5 */
                    285: 
                    286:        if(pb->usbFlags & kUSBHubReaddress)
                    287:        {
                    288:        usbDevice *d;
                    289:                d = getDevicePtr(pb->usbReference);
                    290:                if(d == nil)
                    291:                {
                    292:                        pb->usbStatus = kUSBUnknownDeviceErr;
                    293:                        setAddressHandler(pb);
                    294:                        return;
                    295:                }
                    296:                pb->usb.cntl.WValue = HostToUSBWord(d->usbAddress);
                    297:        }
                    298:        else
                    299:        {
                    300:                pb->usb.cntl.WValue = HostToUSBWord(getNewAddress());
                    301:        }
                    302:        pb->usb.cntl.WIndex = 0;
                    303:        pb->usb.cntl.reserved4 = 0;                                     /* zero length */
                    304:        
                    305:        pb->usbStatus = kUSBPending;
                    306:        err = usbControlPacket(busZero, pb, 0, 0);
                    307: 
                    308:        if(err != noErr)
                    309:        {       /* Even if error, we need to go through handler */
                    310:                pb->usbStatus = err;
                    311:                setAddressHandler(pb);
                    312:        }
                    313: }
                    314: 
                    315: OSStatus USBHubSetAddress(USBPB *pb)
                    316: {
                    317:        if(!checkPBVersion(pb, 1|kUSBHubPower|kUSBHubReaddress))
                    318:        {
                    319:                return(pb->usbStatus);
                    320:        }
                    321:        
                    322:        if(pb->usbFlags & kUSBHubReaddress)
                    323:        {
                    324:                if(getDevicePtr(pb->usbReference) == nil)
                    325:                {
                    326:                        pb->usbStatus = kUSBUnknownDeviceErr;
                    327:                        return(pb->usbStatus);
                    328:                }
                    329:        }
                    330:        else
                    331:        {       
                    332:                if(!uslHubValidateDevZero(pb->usbReference, nil))
                    333:                {
                    334:                        pb->usbReference = 0;
                    335:                        pb->usbStatus = paramErr;
                    336:                        return(pb->usbStatus);
                    337:                }
                    338:        }
                    339: 
                    340:        uslHubSetAddress(pb);
                    341:        
                    342:        return(kUSBPending);
                    343: }
                    344: 
                    345: static OSStatus secondaryCleanInternalQueues(void *p1, void *p2)
                    346: {      // Any new queues should put an entry in here 
                    347: USBDeviceRef ref;
                    348:        p2=0;
                    349:        ref = (USBDeviceRef)p1;
                    350:        
                    351:        uslCleanHubQueue(ref);
                    352:        uslCleanDelayQueue(ref);
                    353:        uslCleanNotifyQueue(ref);
                    354:        uslCleanMemQueue(ref);
                    355:        
                    356:        return(noErr);  // no one's listening
                    357: }
                    358: 
                    359: static OSStatus uslCleanInternalQueues(USBDeviceRef ref)
                    360: {
                    361:        return(CallSecondaryInterruptHandler2(secondaryCleanInternalQueues, nil, (void *)ref, 0));
                    362: }
                    363: 
                    364: OSStatus USBHubDeviceRemoved(USBPB *pb)
                    365: {
                    366: OSStatus err = kUSBPending;
                    367: usbDevice *deviceP;
                    368: OSStatus retVal = noErr;
                    369: Boolean noCallBack;
                    370: 
                    371:        noCallBack = (pb->usbCompletion == kUSBNoCallBack);
                    372:        if(noCallBack)
                    373:        {
                    374:                pb->usbCompletion = (void *)-2;
                    375:        }
                    376:        if(!checkPBVersion(pb, 0))
                    377:        {
                    378:                return(pb->usbStatus);
                    379:        }
                    380:        if(noCallBack)
                    381:        {
                    382:                pb->usbCompletion = kUSBNoCallBack;
                    383:        }
                    384: 
                    385:        deviceP = getDevicePtr(pb->usbReference);
                    386:        if(deviceP == nil)
                    387:        {
                    388:                pb->usbStatus = kUSBUnknownDeviceErr;
                    389:                return(kUSBUnknownDeviceErr);
                    390:        }
                    391:        
                    392:        // Must do this before pipes are closed.
                    393:        retVal = uslCleanInternalQueues(deviceP->ID);
                    394:        if(retVal != noErr)     // if this returns an erro we're hosed.
                    395:        {
                    396:                return(retVal);
                    397:        }
                    398: 
                    399:        uslClosePipe(deviceP->pipe0);
                    400:        
                    401:        uslCloseNonDefaultPipes(deviceP);
                    402:        
                    403:        return(uslDeleteDevice(pb, deviceP));
                    404: }
                    405: 
                    406: void uslHubWatchDog(Duration currentMilliSec)
                    407: {
                    408: USBReference currDevZero;
                    409: UInt32 bus;
                    410: 
                    411:        if((hubAddQueue->qHead != nil) && (lastAdd != 0) )
                    412:        {
                    413:                currDevZero = deviceZero;
                    414:                bus = deviceZero;
                    415:                if(lastAdd < currentMilliSec - 1000)
                    416:                {       /* Candidate for removal */
                    417:                
                    418:                        if(CompareAndSwap(currDevZero, 0, (void *)&deviceZero))
                    419:                        {       /* if we're here, deviceZero didn't change since we checked the time */
                    420:                                /* We've also just diabled that device zero */
                    421:                                if(timeout.usbRefcon != 0)
                    422:                                {
                    423:                                        USBExpertStatus(0, "USL hubs - force set address timed out", 0);
                    424:                                        /* timeout in use already */
                    425: kprintf("uslHubWatchDog: calling UIMControlEDDelete\n");
                    426:                                        UIMControlEDDelete(bus, 0, 0);
                    427:                                        timeout.usbRefcon = 0;
                    428:                                }
                    429:                                else
                    430:                                {
                    431:                                        USBExpertStatus(0, "USL hubs - timing out add", 0);
                    432:                                        timeout.usbRefcon = 1;
                    433:                                        lastAdd = currentMilliSec + 1000;
                    434:                                        uslHubSetAddress(&timeout);
                    435:                                }
                    436:                        }
                    437:                
                    438:                }
                    439:        }
                    440: }
                    441: 
                    442: 
                    443: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.