|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.