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

unix.superglobalmegacorp.com

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