|
|
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: uslUtility.c
27:
28: Contains: xxx put contents here xxx
29:
30: Version: xxx put version here xxx
31:
32: Copyright: � 1998 by Apple Computer, Inc., all rights reserved.
33:
34: File Ownership:
35:
36: DRI: xxx put dri here xxx
37:
38: Other Contact: xxx put other contact here xxx
39:
40: Technology: xxx put technology here xxx
41:
42: Writers:
43:
44: (TC) Tom Clark
45: (DF) David Ferguson
46: (DKF) David Ferguson
47: (BT) Barry Twycross
48:
49: Change History (most recent first):
50:
51: <USB33> 10/29/98 BT Close old configurations on reset or reconfiguration.
52: <USB32> 10/7/98 BT Fix callback at task time.
53: <USB31> 10/7/98 BT Add 32bit endian functions
54: <USB30> 9/29/98 BT Use real frame timing
55: <USB29> 9/28/98 BT Add device reset function
56: <USB28> 8/24/98 BT Eliminate old checkPB version, add new one for Isoc
57: <USB27> 8/13/98 BT Add multibus support
58: <USB26> 8/12/98 BT Move root hub into UIM again
59: <USB25> 7/28/98 BT Dev zero is valid ref
60: <USB24> 7/10/98 TC Essentially take out <USB19>.
61: <USB23> 7/9/98 BT Clean up queues when device deleted. Merge in branch
62: <USB22> 7/2/98 BT Fix dealloc mem to zero buffer ptr.
63: <USB21> 7/2/98 BT Use UIM time for internal timing
64: <USB20> 7/2/98 BT Return the right framenumber from USBDelay. Let framecount take
65: kNoCallBack.
66: <USB19> 6/30/98 BT Move Root hub sim into UIM
67: <USB18> 6/15/98 DF Remove compiler build problem. It didn't like passing a pointer
68: to a struct pointer that was declared volatile.
69: <USB17> 6/14/98 DF Cancel InterruptTimer when being replaced.
70: <USB16> 6/5/98 BT DeallocMem will work immediatlty
71: <USB15> 6/5/98 BT Use UIM time
72: <USB14> 4/30/98 BT Add real interrupt driven timer
73: <USB13> 4/23/98 BT Add hub watchdog function
74: <USB12> 4/16/98 BT Eliminate debugger
75: <USB11> 4/10/98 BT add USB to host word
76: <USB10> 4/9/98 BT Use USB.h
77: <9> 4/8/98 BT More error checking
78: <8> 4/2/98 BT Error checking for nil call backs. Also Ferg's Use DSL Timing
79: Services directly
80: <7> 3/11/98 BT Give time to root hub int sim
81: <6> 3/2/98 BT Back out timer changes
82: <5> 2/24/98 BT Change timer to non-persistant
83: <4> 2/19/98 BT Make timer non task time.
84: <3> 2/16/98 BT Fix calling processdone queue and timer too often.
85: <USB2> 2/9/98 DKF add USBIdleTask for handling events that need file I/O safe
86: time.
87: <1> 1/29/98 BT first checked in
88: */
89:
90: #include "../driverservices.h"
91: #include "../USB.h"
92: #include "../USBpriv.h"
93: #include "uslpriv.h"
94: #include "../uimpriv.h"
95: #import <sys/callout.h>
96: #import <kernserv/ns_timer.h>
97:
98:
99: static QHdrPtr delayQueue;
100: static QHdrPtr notifyQueue;
101: static QHdrPtr memoryQueue;
102: static unsigned long notifyFlag = 0;
103: volatile TimerID curTimerID;
104:
105: static UInt32 idled;
106: #define ONE_MILLI_SECOND 1000000ULL /* nanoseconds/10**6 */
107: void timerHandler(void *p1); //naga
108: static SInt32 interruptPriority;
109:
110:
111: void uslCleanAQueue(QHdrPtr queue, USBDeviceRef ref)
112: { // This is assuming its called at secondary interrupt time.
113: USBPB *pb, *pbNext;
114:
115: if(CurrentExecutionLevel() != kSecondaryInterruptLevel)
116: {
117: USBExpertStatus(0, "USL - clean Q call at wrong time", ref);
118: return;
119: }
120:
121: if(queue == nil)
122: {
123: return;
124: }
125: pb = (void *)queue->qHead;
126:
127: while(pb != nil)
128: {
129: pbNext = (void *)pb->qlink;
130: if(isSameDevice(pb->usbReference, ref))
131: {
132: USBExpertStatus(0, "USL - killing Q element", ref);
133: PBDequeue((void *)pb, queue); // unqueue it an forget it
134: }
135: pb = pbNext;
136: }
137: }
138:
139: void uslCleanDelayQueue(USBDeviceRef ref)
140: { // This is assuming its called at secondary interrupt time.
141: uslCleanAQueue(delayQueue, ref);
142: }
143:
144:
145: void uslCleanNotifyQueue(USBDeviceRef ref)
146: { // This is assuming its called at secondary interrupt time.
147: uslCleanAQueue(notifyQueue, ref);
148: }
149:
150:
151: void uslCleanMemQueue(USBDeviceRef ref)
152: { // This is assuming its called at secondary interrupt time.
153: uslCleanAQueue(memoryQueue, ref);
154: }
155:
156:
157:
158:
159:
160: void uslInterruptPriority(UInt32 delta)
161: {
162: AddAtomic(delta, &interruptPriority);
163: if(interruptPriority < 0)
164: {
165: USBExpertStatus(0, "USL - interrrupt prority gone negative", interruptPriority);
166: }
167: }
168:
169:
170: OSStatus USBResetDevice(USBPB *pb)
171: {
172: // --> usbReference device/interface/endpoint - which device.
173: usbDevice *dev;
174: pipe *p;
175: OSStatus err;
176:
177: if(!checkPBVersion(pb, kUSBPowerReset))
178: {
179: return(pb->usbStatus);
180: }
181:
182: dev = getDevicePtr(pb->usbReference);
183: if(dev == nil)
184: {
185: err = findPipe(pb->usbReference, &p);
186: if(p != nil)
187: {
188: dev = getDevicePtr(p->devIntfRef);
189: }
190: }
191: if(dev == nil)
192: {
193: pb->usbStatus = kUSBUnknownDeviceErr;
194: return(pb->usbStatus);
195: }
196:
197: uslUnconfigureDevice(dev);
198:
199: pb->usbStatus = kUSBPending;
200: pb->usb.hub.Request = kUSBHubPortResetRequest;
201: err = USBExpertNotifyParentMsg(dev->ID, pb);
202: if(err != noErr)
203: {
204: pb->usbStatus = err;
205: return(err);
206: }
207: else
208: {
209: return(kUSBPending);
210: }
211: }
212:
213:
214: OSStatus USBGetFrameNumberImmediate(USBPB *pb)
215: {
216: // --> usbReference device/interface/endpoint. Specifies which bus
217: // --> usbReqCount size of buffer (should be 0 or sizeof(UInt64)
218: // --> usbBuffer nil/point to UInt64 structure for full count
219: // <-- usbActCount size of data returned.
220: // <-- usbFrame low 32 bits of current frame number.
221: union{
222: UInt64 u;
223: UnsignedWide s;
224: }frame;
225: Boolean nocallBack = false;
226: UInt32 bus;
227:
228: // Oops, forgot to validate this
229: pb->usbStatus = validateRef(pb->usbReference, &bus);
230: if(pb->usbStatus != noErr)
231: {
232: return(pb->usbStatus);
233: }
234:
235: if(pb->usbCompletion == kUSBNoCallBack)
236: {
237: nocallBack = true;
238: pb->usbCompletion = (void *)-2;
239: }
240: if(!checkPBVersion(pb, 0))
241: {
242: return(pb->usbStatus);
243: }
244: if(nocallBack)
245: {
246: pb->usbCompletion = kUSBNoCallBack;
247: }
248: frame.u = UIMGetCurrentFrame(bus);
249: pb->usbFrame = frame.s.lo;
250: if( (pb->usbBuffer != nil) && (pb->usbReqCount != 0) )
251: {
252: pb->usbActCount = pb->usbReqCount;
253: if(pb->usbActCount > sizeof(frame))
254: {
255: pb->usbActCount = sizeof(frame);
256: }
257: usb_BlockMoveData(&frame, pb->usbBuffer, pb->usbActCount);
258: }
259: return(noErr);
260:
261: }
262:
263: UInt32 deltaFrames(UInt32 previous, UInt32 bus)
264: {
265: union{
266: UInt64 u;
267: UnsignedWide s;
268: }frame;
269:
270: frame.u = UIMGetCurrentFrame(bus);
271: if(previous > frame.s.lo)
272: {
273: previous -= frame.s.lo;
274: return(~previous+1);
275: }
276: else
277: {
278: return(frame.s.lo - previous);
279: }
280: }
281:
282:
283: void finaliseNotifications(void)
284: {
285: AbsoluteTime wastedTime;
286:
287: PBQueueDelete(notifyQueue);
288: PBQueueDelete(memoryQueue);
289: while (curTimerID) {
290: if (CancelTimer(curTimerID, &wastedTime) == noErr)
291: curTimerID = 0;
292: }
293: }
294:
295: void initialiseNotifications(void)
296: {
297: if( (PBQueueCreate(¬ifyQueue) != noErr) ||
298: (PBQueueInit(notifyQueue) != noErr) )
299: {
300: /* Panic */
301: USBExpertStatus(0,"USL - failed to initialise notification queue", 0);
302: }
303: if( (PBQueueCreate(&memoryQueue) != noErr) ||
304: (PBQueueInit(memoryQueue) != noErr) )
305: {
306: /* Panic */
307: USBExpertStatus(0,"USL - failed to initialise memory queue", 0);
308: }
309:
310: idled = 0;
311: timerHandler(0);
312:
313: }
314:
315: static void taskTimeDoMemory(USBPB *pb)
316: {
317: Boolean dealloc;
318: dealloc = (pb->usbFlags & (1 << kUSLTTMemDeAllocFlagShift)) != 0;
319: pb->usbFlags &= ~(1 << kUSLTTMemDeAllocFlagShift);
320:
321: if(dealloc)
322: {
323: pb->usbStatus = PoolDeallocate(pb->usbBuffer);
324: pb->usbBuffer = nil;
325: }
326: else
327: {
328: pb->usbBuffer = PoolAllocateResident(pb->usbReqCount, true /*Boolean clear*/);
329: if(pb->usbBuffer != nil)
330: {
331: pb->usbActCount = pb->usbReqCount;
332: pb->usbStatus = noErr;
333: }
334: else
335: {
336: pb->usbActCount = 0;
337: pb->usbStatus = memFullErr; /* How do you find the right error code???? */
338: }
339: }
340: (pb->usbCompletion)(pb);
341: }
342:
343: static void NotifyHandlerProc( )
344: {
345: USBPB *pb;
346:
347: notifyFlag = false; /* Queue Processed */
348:
349: /* Note these don't use interrupt priority, they do not happen at int time */
350: while(PBDequeueFirst(notifyQueue, (void *)&pb) == noErr)
351: {
352: pb->usbStatus = noErr; /* Call back with right error status */
353: (pb->usbCompletion)(pb);
354: }
355: while(PBDequeueFirst(memoryQueue, (void *)&pb) == noErr)
356: {
357: taskTimeDoMemory(pb);
358: }
359:
360: }
361:
362: static void startNotifier(void)
363: {
364: notifyFlag = true;
365: }
366:
367: static OSStatus uslTTCallBack(USBPB *pb)
368: {
369: pb->usbStatus = PBEnqueueLast((void *)pb, notifyQueue);
370: startNotifier();
371: return(pb->usbStatus); /* safe, this is synchronised */
372: }
373:
374: static OSStatus uslTTmem(USBPB *pb)
375: {
376: pb->usbStatus = PBEnqueueLast((void *)pb, memoryQueue);
377: startNotifier();
378: return(pb->usbStatus); /* safe, this is synchronised */
379: }
380:
381: OSStatus uslAllocMem(USBPB *pb)
382: {
383: pb->usbFlags &= ~(1 << kUSLTTMemDeAllocFlagShift);
384: return(uslTTmem(pb));
385: }
386:
387: OSStatus USBAllocMem(USBPB *pb)
388: {
389: pb->usbStatus = validateRef(pb->usbReference, nil);
390: if(pb->usbStatus != noErr)
391: {
392: return(pb->usbStatus);
393: }
394:
395: if(!checkPBVersion(pb, kUSBTaskTimeFlag))
396: {
397: return(pb->usbStatus);
398: }
399:
400: return(uslAllocMem(pb));
401: }
402:
403: OSStatus uslDeallocMem(USBPB *pb)
404: {
405: pb->usbFlags |= (1 << kUSLTTMemDeAllocFlagShift);
406: return(uslTTmem(pb));
407: }
408:
409: OSStatus USBDeallocMem(USBPB *pb)
410: {
411: Boolean nocallBack = false;
412:
413: if(pb->usbCompletion == kUSBNoCallBack)
414: {
415: nocallBack = true;
416: pb->usbCompletion = (void *)-2;
417: }
418: else
419: {
420: pb->usbStatus = validateRef(pb->usbReference, nil);
421: if(pb->usbStatus != noErr)
422: {
423: return(pb->usbStatus);
424: }
425: }
426: if(!checkPBVersion(pb, kUSBTaskTimeFlag))
427: {
428: return(pb->usbStatus);
429: }
430: if(nocallBack)
431: {
432: void *buffer;
433: if(CurrentExecutionLevel() != kTaskLevel)
434: {
435: return(kUSBCompletionError);
436: }
437: pb->usbCompletion = kUSBNoCallBack;
438: buffer = pb->usbBuffer;
439: pb->usbBuffer = nil; // BT 2Jun98, don't forget to zero this, its in the spec
440: return(PoolDeallocate(buffer));
441: }
442: return(uslDeallocMem(pb));
443: }
444:
445: void initialiseDelays(void)
446: {
447: if( (PBQueueCreate(&delayQueue) != noErr) ||
448: (PBQueueInit(delayQueue) != noErr) )
449: {
450: /* Panic */
451: USBExpertStatus(0,"USL - failed to initialise delay queue", 0);
452: }
453: }
454:
455: void finaliseDelays(void)
456: {
457: PBQueueDelete(delayQueue);
458: }
459:
460: static OSStatus uslDelay(USBPB *pb, UInt32 bus)
461: {
462: OSStatus err = noErr;
463:
464: /* waits the specified number of frames then calls the handler */
465: /* length (soon to be usbReqCount) - required frame count to delay */
466: if( (delayQueue == nil) || (notifyQueue == nil) )
467: {
468: pb->usbStatus = kUSBInternalErr;
469: return(kUSBInternalErr);
470: }
471:
472: pb->usbActCount = pb->usbReqCount + deltaFrames(0, bus);
473: pb->qType = kUSBDelayQType;
474: pb->usbStatus = kUSBPending;
475:
476: err = PBEnqueueLast((void *)pb, delayQueue);
477: uslInterruptPriority(+1);
478:
479: if(err != noErr)
480: {
481: pb->usbStatus = err;
482: }
483: else
484: {
485: err = kUSBPending;
486: }
487: return(err);
488: }
489:
490: OSStatus USBDelay(USBPB *pb)
491: {
492: OSStatus err = noErr;
493: UInt32 bus;
494:
495: pb->usbStatus = validateRef(pb->usbReference, &bus);
496: if(pb->usbStatus != noErr)
497: {
498: return(pb->usbStatus);
499: }
500:
501: /* waits the specified number of frames then calls the handler */
502: /* length (soon to be usbReqCount) - required frame count to delay */
503: if(delayQueue == nil)
504: {
505: return(kUSBInternalErr);
506: }
507:
508: if(!checkPBVersion(pb, kUSBTaskTimeFlag))
509: {
510: return(pb->usbStatus);
511: }
512: return(uslDelay(pb, bus));
513: }
514:
515: static void processDelayQ( Duration currentDuration)
516: {
517: USBPB *pb, *pbNext;
518: UInt32 bus=0;
519:
520: if(delayQueue == nil)
521: {
522: return;
523: }
524: /* Walk the que, safe, we're the only thing to take elements off */
525:
526: pb = (void *)delayQueue->qHead;
527:
528: while(pb != nil)
529: {
530: pbNext = (void *)pb->qlink;
531:
532: if(pb->usbActCount <= currentDuration)
533: {
534: if(PBDequeue((void *)pb, delayQueue) == noErr)
535: {
536: if( ( (pb->usbFlags & kUSBTaskTimeFlag) != 0) &&
537: (CurrentExecutionLevel() != kTaskLevel) )
538: {
539: uslTTCallBack(pb);
540: }
541: else
542: {
543: uslInterruptPriority(-1);
544: pb->usbStatus = noErr;
545: (*pb->usbCompletion)(pb);
546: }
547: }
548: }
549:
550: pb = pbNext;
551: }
552:
553: }
554:
555: static Boolean uslInterruptSafeIdle(UInt32 currFrame)
556: {
557: static UInt32 nextRootHub, lastRootHub;
558: static UInt32 lastDone = 0;
559:
560: if(currFrame != lastDone) // don't run more than once per millisecond.
561: {
562:
563: lastDone = currFrame;
564: //UIMProcessDoneQueue(); /* Note this is simulated only */
565:
566: if( (currFrame > nextRootHub) || (currFrame < lastRootHub) )
567: {
568: UIMPollRootHubSim();
569: uslHubWatchDog(currFrame);
570: lastRootHub = currFrame;
571: nextRootHub = currFrame + 50;
572: }
573: processDelayQ(currFrame);
574: return(true);
575: }
576: return(false);
577: }
578:
579: void USBIdleTask(void)
580: {
581: UInt32 currentFrame;
582: idled = 0;
583:
584: currentFrame = UIMGetAFrame();
585:
586: if(uslInterruptSafeIdle(currentFrame) && notifyFlag)
587: {
588: NotifyHandlerProc();
589: }
590:
591: }
592:
593:
594: void timerHandler(void *p1) //naga it used to be void *p1,void *p2)
595: {
596: TimerID timerID;
597: Duration currentFrame, delay;
598: AbsoluteTime expirationTime;
599: AbsoluteTime currentTime = UpTime();
600:
601: p1 = 0;
602: // p2 = 0;
603:
604: if(idled != 0)
605: {
606: //USBExpertStatus(0, "USL - Interrupt task idle", idled);
607: currentFrame = UIMGetAFrame();
608: uslInterruptSafeIdle(currentFrame);
609: if(idled > 18)
610: {
611: idled = 18;
612: }
613: }
614:
615: if(interruptPriority > 0)
616: {
617: //USBExpertStatus(0, "USL - interruptPriority:", interruptPriority);
618: delay = 20 - idled; // milliseconds
619: idled++;
620: }
621: else
622: {
623: delay = 100;
624: }
625: expirationTime = AddAbsoluteToAbsolute(currentTime,
626: DurationToAbsolute(delay));
627: //kprintf("***timerhandler:Setting timerHandler delay=%d\n",delay);
628: ns_timeout(timerHandler,p1,delay*ONE_MILLI_SECOND,CALLOUT_PRI_SOFTINT0);
629: // SetInterruptTimer(&expirationTime, timerHandler, nil, &timerID);
630: curTimerID = timerID;
631: return(0);
632: }
633:
634:
635:
636:
637:
638:
639: /* ************* Endianisms ************* */
640:
641: UInt16 HostToUSBWord(UInt16 value)
642: {
643: return( (value << 8) | (value >> 8) );
644: }
645:
646: /* This is identical to above, but can't make defining it language independant */
647: UInt16 USBToHostWord(UInt16 value)
648: {
649: return( (value << 8) | (value >> 8) );
650: }
651:
652: UInt32 HostToUSBLong(UInt32 value)
653: {
654: return(
655: (((UInt32) value) >> 24) |
656: ((((UInt32) value) >> 8) & 0xFF00) |
657: ((((UInt32) value) << 8) & 0xFF0000) |
658: (((UInt32) value) << 24)
659: );
660:
661: }
662:
663: UInt32 USBToHostLong(UInt32 value)
664: {
665: return(
666: (((UInt32) value) >> 24) |
667: ((((UInt32) value) >> 8) & 0xFF00) |
668: ((((UInt32) value) << 8) & 0xFF0000) |
669: (((UInt32) value) << 24)
670: );
671:
672: }
673:
674:
675: Boolean immediateError(OSStatus err)
676: {
677: return((err != kUSBPending) && (err != noErr) );
678: }
679:
680:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.