|
|
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.