|
|
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: OHCIUIM.c
27:
28: Contains: OHCI implementation of USB Hal for Neptune Project
29:
30: Version: xxx put version here xxx
31:
32: Written by: Guillermo Gallegos
33:
34: Copyright: � 1997-1998 by Apple Computer, Inc., all rights reserved.
35:
36: File Ownership:
37:
38: DRI: xxx put dri here xxx
39:
40: Other Contact: xxx put other contact here xxx
41:
42: Technology: xxx put technology here xxx
43:
44: Writers:
45:
46: (TC) Tom Clark
47: (DRF) Dave Falkenburg
48: (DF) David Ferguson
49: (GG) Guillermo Gallegos
50: (BT) Barry Twycross
51: (CJK) Craig Keithley
52:
53: Change History (most recent first):
54:
55: <USB89> 11/20/98 GG [2287626] Fixed bug where I was instantiating the same callback
56: twice, which was causing a crash with the Imation Drive.
57: <USB88> 11/18/98 GG [2283557] Changed the calculation of the frame number to
58: account for use of bit 15 of the frame number register as a
59: toggle overflow. Should fix bug where the framenumber was too
60: high.
61: <USB87> 11/16/98 GG Fixed off by one error in isochronous transfers and cleaned up
62: finalize routines memory deallocations.
63: <USB86> 11/12/98 GG Fixed memory leaks in descriptor allocation, PCI allocatio and
64: pphysical to virtual allocations.
65: <USB85> 11/11/98 GG Fixed how ischronous tranfers get the end of there buffer
66: calculated for each TD.
67: <USB84> 11/9/98 CJK Back out some changes to rev 80. Should make bulk work again.
68: <USB83> 11/5/98 GG Fix bug where Bulk didnt work due to bug introduced in 81. Also
69: cleaned up a little.
70: <USB82> 10/24/98 GG Changed power on of root hub to call rootHubPower, instead of
71: tripping the bit directly. Also added a function to find out
72: what machine we are on.
73: <USB81> 10/22/98 GG Fixed bug where pages needed would be mis calculated if the the
74: buffer ended on the first byte of a page.
75: <USB80> 9/14/98 GG Fix Isoch bug where Isochronous was being disabled when Opti
76: errata fix was being implemented.
77: <USB79> 9/9/98 BT Fix Isoc
78: <USB78> 9/9/98 BT Fix size of Isoc refcon
79: <USB77> 9/5/98 GG Some more Isoch fixes.
80: <USB76> 9/4/98 GG Fix page used calcualation and internal loop condition.
81: <USB75> 9/3/98 GG Add Isochronous Suppurt for Create, Abort, Delete endpoint and
82: create transfers. Also rolled in earlier branch fix to TOT, the
83: off by 2 bug.
84: <USB74> 8/12/98 GG Initialize pointer in zero length bulk transfer condition.
85: <USB73> 8/12/98 BT Move root hub into UIM again.
86: <USB72> 8/11/98 GG Fixed the original Compiles and works with symbols, but compiles
87: but not works without symbols. Turns out to be an uninitialized
88: pointer to the register set.
89: <USB71> 8/11/98 GG Commented out a for(j=0;j<0;j++) loop that the compiler did not
90: know how to optimize, with symbols on it worked, symbols off it
91: didnt.
92: <USB70> 8/11/98 GG stuff
93: <USB69> 8/7/98 GG Fixed Opti data corruption problem. Also fixed bug where an
94: aborted transfer would return wrong value for pending data.
95: Tweaked interface to USL to be consistent with direction
96: parameter.
97: <USB68> 7/28/98 GG Merged to TOT: <USB62a2> 7/15/98 GG Fixed bug that was caused by
98: previous checkin where transfer setup would try to use data
99: outsided the preparememforio physical data block. <USB62a1>
100: 7/14/98 GG [2252282] <TC> Fixed Bulk to not generate short
101: packets in the middle of a tranfer, both read and write. This
102: was caused when the data buffer was not aligned in memory to max
103: packet size. The fix was to check for unalignment and to
104: generate 4k or less Transfer Descriptors.
105: <USB67> 7/23/98 BT fix fix
106: <USB66> 7/23/98 BT Fix Endpoint Delete to not hose bulk and control queues
107: <USB65> 7/10/98 TC Back out <USB63>
108: <USB64> 6/30/98 BT Tidy up
109: <USB63> 6/30/98 BT Move Root hub sim into UIM
110: <USB62> 6/24/98 GG Changed PeriodStart Register to static value instead of
111: calculating it.
112: <USB61> 6/23/98 DF [2238756, 2243961] always reset the endpoint virtual head when
113: deleting TDs.
114: <USB60> 6/15/98 DF Turn off power when finializing the UIM
115: <USB59> 6/14/98 DF Remove unused variable that was causing a warning
116: <USB58> 6/14/98 DF Shutdown the OHCI controller when Finalize function is called.
117: <USB57> 6/13/98 BT Stop hanging is we don't see a start of frame interrupt.
118: <USB56> 6/4/98 DF turn off debugstrs and other clean up
119: <USB55> 6/4/98 DRF In UIMInitialize & UIMFinalize, add a Ptr to facilitate
120: handing-off global state when performing replacement. NOTE:
121: These routines still to be changed to do the additional work.
122: <USB54> 6/3/98 GG Changed UInt64 operations to use macros from Math64.h. Made
123: interrupts go to their requested period and randomly generated
124: slot with given period.
125: <USB53> 6/3/98 GG Checked if UInt64 is a structure or integer.
126: <USB52> 6/3/98 DF [2240506] clear skipped bit when aborting transfers, also
127: slight tweek to the frame number stuff to work with the
128: compilers used when building in SuperMario.
129: <USB51> 6/2/98 GG Add interfaces IsochEndpointCreate, and IsochTransfer. Also
130: added a getFrameCount function.
131: <USB50> 6/2/98 DRF Added params to UIMInitialize & UIMFinalize for replacement. Use
132: them later
133: <USB49> 5/16/98 DF For now, always call CheckPointIO after getting the physical
134: address of transfer buffers. PrepareMemoryForIO and
135: CheckpointIO are not implemented as advertised that's why we are
136: having so much trouble with them. The real solution is to carry
137: a copy of the ioPreparation table with each active transfer
138: descriptor.
139: <USB48> 5/15/98 DF make the bus operational following an unrecoverable error
140: interrupt, fix TD leak in bulk transfers, turn back on the
141: CheckpointIOs, misc cleanups.
142: <USB47> 5/14/98 GG Added BufferUnderrun Errata Fix for CMD KAB4 and KAB4 revA.
143: Also increased memory usage and added some checks for out of
144: memory cases. Took out CheckpointIO usage for now.
145: <USB46> 5/14/98 DF Initialize the root hub status register
146: <USB45> 5/8/98 DF Make sure interrupt transfer descriptors use the endpoint for
147: the data toggle carry.
148: <USB44> 5/7/98 BT Hack find interrupt endpoint so it never finds control endpoint
149: for (0,0).
150: <USB43> 5/5/98 GG Change Buffersize from short to unsigned long in BulkTransfer.
151: <USB42> 5/4/98 GG Another fix for Bulk transfers in done Q processing.
152: <USB41> 5/4/98 GG Fixed Done Queue Processing to do error recovery.
153: <USB40> 5/4/98 DF fix errata test, and check the Bulk list when clearing endpoint
154: stalls
155: <USB39> 5/2/98 DF fix bulk transfers, add errata checks, remove VooDoo, add
156: CheckPointIO() calls when TDs are released.
157: <USB38> 4/29/98 BT Fix returned errors, hasck in FSMPS
158: <USB37> 4/29/98 GG Added calculation of FSMPS based on FMInterval.
159: <USB36> 4/27/98 DF Initialize the Control & Bulk Current Pointers
160: <USB35> 4/24/98 GG Added support for bulk transfers greater than 4k. Added fix to
161: support to clear an endpoint stall.
162: <USB34> 4/22/98 DF Mask off low-order interrupt bits when reading the hccaDoneHead.
163: Also change to match pci class code instead of a specific
164: vendor's chip.
165: <USB33> 4/16/98 BT Fix codewarrior incompatabilities
166: <USB32> 4/14/98 DF make ProcessDoneQueue do something useful
167: <USB31> 4/9/98 BT Use USB.h
168: <30> 4/8/98 GG Modified OHCIUIMEndpointDelete to not be static.
169: <29> 4/7/98 GG Added support for OF generic driver. Added suypport for UHCI to
170: OHCI mode.
171: <28> 4/7/98 GG Added Abort and Delete Apis.
172: <27> 3/19/98 BT Split UIM into UIM and root hub parts
173: <26> 3/18/98 BT Add reset enable change to root hub.
174: <25> 3/11/98 BT Root hub interrupt transaction simulation support
175: <24> 2/25/98 GG Re enabled queue processing.
176: <23> 2/25/98 GG Modified Interrupt transfer to call a separate troutine to find
177: an enpoint.
178: <22> 2/24/98 GG Calculated Periodic Start using Frame Interval. Changed
179: calculation of Interrupt tree.
180: <21> 2/23/98 GG Added checks for task time. Changed Interrupt heads to be an
181: array of structs. Changed the value of hcPeriodicStart register
182: to spec static value. Corrected interrupt tree structure.
183: <20> 2/20/98 GG Fixed compile problem.
184: <19> 2/20/98 GG Changed DelayFor to DelayForHardware, modifed
185: InterruptInitialize.
186: <18> 2/20/98 GG Changed to CMD from Opti.
187: <17> 2/20/98 GG Enabled periodic endpoint processing.
188: <16> 2/20/98 GG Added Interrupt Transfer Support. Modified Interrupt Endpoint
189: Creation.
190: <15> 2/19/98 GG Added endpoint creation functonality.
191: <USB14> 2/17/98 DF Add HW Interrupt handling, and a few changes related to getting
192: operation in a VM environment working.
193: <13> 2/13/98 GG Comment out debug strings
194: <12> 2/13/98 GG Comment out debug strings
195: <11> 2/12/98 GG Added Rom in Ram memory offset support. Overwrote #10 and 9
196: Checkins.
197: <USB10> 2/12/98 DF Detect unrecoverable error at initialize time, and try to
198: recover by resetting
199: <USB9> 2/12/98 DF Add more error checking on memory allocations
200: <8> 2/2/98 BT Add bulk stuff
201: <7> 1/26/98 BT Add unstall endpoint
202: <6> 12/19/97 BT Temp hack, Make it a shared lib
203: <5> 12/18/97 BT Add in my changes so this works with multiple endpoints
204: <4> 11/30/97 BT Various mods to get perliminary USL running
205: <3*> 11/20/97 GG Add callback parameter to bulk and control creators.
206: <3> 11/20/97 GG Initial check in has minimal support for Root Hub, Control and
207: Bulk transfers.
208: <2> 11/20/97 GG Filled in Contains Field.
209: <1> 11/20/97 GG first checked in
210:
211: */
212:
213: #import <mach/mach_types.h>
214: #import <architecture/arch_types.h>
215: #import <machdep/ppc/interrupts.h>
216: #import <kernserv/prototypes.h>
217: #import <kernserv/clock_timer.h>
218: #import <kernserv/ns_timer.h>
219: #import <sys/time.h>
220: #import <sys/callout.h>
221: #include <bsd/sys/systm.h>
222: #import <sys/proc.h> // prototypes for sleep,wakeup
223: #import <sys/fcntl.h>
224: #include <vm/vm_kern.h>
225: #import <driverkit/generalFuncs.h>
226:
227: #include "driverservices.h"
228: #include "USB.h"
229: #include "USBpriv.h"
230: #include "OHCIUIM.h"
231: #include "OHCIRootHub.h"
232: #include "pci.h"
233:
234: #define ProgressDebugStr(s) kprintf(s) /* SysDebugStr(s) */
235: #define MemoryDebugStr(s) kprintf(s) /* SysDebugStr(s) */
236: #define AssertDebugStr(s) kprintf(s) /* SysDebugStr(s) */
237: #define FailureDebugStr(s) kprintf(s) /* SysDebugStr(s) */
238:
239: void IOSync(void);
240: simple_lock_t usb_slock;
241: char Desc_Buffer_Usb[54*4096]; //naga
242: extern OHCIUIMDataPtr pOHCIUIMData;
243: #define KBD_UNIQUE_ADDRESS 10
244: #define MOUSE_UNIQUE_ADDRESS 0x61
245:
246:
247:
248:
249: static OSStatus OHCIUIMFinalizeOHCIUIMData(
250: OHCIUIMDataPtr pOHCIUIMData);
251:
252: static OSStatus OHCIUIMGetRegisterBaseAddress (
253: RegEntryIDPtr pOHCIRegEntryID,
254: OHCIRegistersPtr *ppOHCIRegisters);
255:
256: UInt32 OHCIUIMCreatePhysicalAddress(
257: UInt32 LogicalAddress,
258: UInt32 count);
259:
260: UInt32 OHCIUIMGetPhysicalAddress(
261: UInt32 LogicalAddress,
262: UInt32 count);
263:
264: UInt32 OHCIUIMGetLogicalAddress (
265: UInt32 pPhysicalAddress);
266:
267: OSStatus OHCIUIMAllocateBuffer();
268:
269: OSStatus OHCIUIMDeallocateED (
270: OHCIEndpointDescriptorPtr pED);
271:
272: OSStatus OHCIUIMDeallocateTD (
273: OHCIGeneralTransferDescriptorPtr pTD);
274:
275: OSStatus OHCIUIMDeallocateITD (
276: OHCIIsochTransferDescriptorPtr pTD);
277:
278: OHCIEndpointDescriptorPtr OHCIUIMAllocateED();
279:
280: OHCIGeneralTransferDescriptorPtr OHCIUIMAllocateTD();
281:
282: OHCIIsochTransferDescriptorPtr OHCIUIMAllocateITD();
283:
284: OSStatus OHCIUIMAllocateMemory (
285: int num_of_TDs,
286: int num_of_EDs,
287: int num_of_ITDs);
288:
289: OSStatus OHCIUIMInterruptFindED();
290:
291: OSStatus OHCIUIMInterruptBandwidthCheck();
292:
293: OSStatus OHCIUIMInterruptfits();
294:
295: OSStatus OHCIUIMInterruptschedule();
296:
297: OSStatus OHCIUIMIsochronousInitialize();
298: OSStatus OHCIUIMInterruptInitialize ();
299: OSStatus OHCIUIMBulkInitialize ();
300: OSStatus OHCIUIMControlInitialize ();
301:
302: OSStatus OHCIUIMInstallInterruptHandler();
303:
304: OSStatus OHCIUIMInterruptHandler (InterruptSetMember member, void *refCon, UInt32 interruptCount);
305:
306: OSStatus DoDoneQueueProcessing(OHCIGeneralTransferDescriptorPtr pHCDoneTD, Boolean immediateFlag);
307:
308: Boolean BandwidthAvailable(
309: UInt32 pollingRate,
310: UInt32 reserveBandwidth,
311: int *offset);
312:
313: OHCIEndpointDescriptorPtr FindEndpoint (
314: short functionNumber,
315: short endpointNumber,
316: short direction,
317: OHCIEndpointDescriptorPtr *pEDQueueBack,
318: UInt32 *controlMask);
319:
320:
321: OHCIEndpointDescriptorPtr FindInterruptEndpoint(
322: short functionNumber,
323: short endpointNumber,
324: OHCIEndpointDescriptorPtr *pEDBack);
325:
326: OHCIEndpointDescriptorPtr FindBulkEndpoint (
327: short functionNumber,
328: short endpointNumber,
329: short direction,
330: OHCIEndpointDescriptorPtr *pEDBack);
331:
332: OHCIEndpointDescriptorPtr FindControlEndpoint (
333: short functionNumber,
334: short endpointNumber,
335: OHCIEndpointDescriptorPtr *pEDBack);
336:
337: OHCIEndpointDescriptorPtr FindIsochronousEndpoint(
338: short functionNumber,
339: short endpointNumber,
340: short direction,
341: OHCIEndpointDescriptorPtr *pEDBack);
342:
343: static OSStatus RemoveTDs (OHCIEndpointDescriptorPtr pED);
344:
345: static OSStatus RemoveAllTDs (OHCIEndpointDescriptorPtr pED);
346:
347: static UInt32 GetErrataBits (RegEntryIDPtr);
348:
349: void doCallback(
350: OHCIGeneralTransferDescriptorPtr nextTD,
351: UInt32 transferStatus,
352: UInt32 bufferSizeRemaining);
353:
354: OHCIEndpointDescriptorPtr AddEmptyEndPoint(
355: UInt8 functionAddress,
356: UInt8 endpointNumber,
357: UInt16 maxPacketSize,
358: UInt8 speed,
359: UInt8 direction,
360: OHCIEndpointDescriptorPtr pED,
361: int isoch);
362:
363: OHCIIsochTransferDescriptorPtr QueueITD (
364: OHCIIsochTransferDescriptorPtr pITD,
365: OHCIEndpointDescriptorPtr pED);
366:
367: void SwapIsoc(OHCIIsochTransferDescriptorPtr pITD);
368:
369: UInt32 findBufferRemaining (OHCIGeneralTransferDescriptorPtr pCurrentTD);
370:
371: void DoOptiFix(OHCIEndpointDescriptorPtr pIsochHead);
372:
373: void trivialSwap( UInt32 *thing);
374:
375: int GetEDType(
376: OHCIEndpointDescriptorPtr pED);
377:
378: void ProcessCompletedITD (OHCIIsochTransferDescriptorPtr pITD);
379:
380: OSStatus OptiLSHSFix();
381:
382: Boolean AmIThisMachine(Str255 inMachineNameStr);
383:
384: OSStatus OHCIResetRootHub(uslBusRef bus);
385: OSStatus OHCIRootHubPortEnable( uslBusRef bus, short port, Boolean on);
386:
387: void Get_Config_Info(void);
388: void enable_intr();
389: void ReadConfigVal(UInt32 ctl, UInt32 *val);
390: void WriteConfigVal(UInt32 ctl, UInt32 val);
391:
392: typedef struct{
393: UInt8 len;
394: UInt8 type;
395: UInt16 totalLen;
396: char rest_data[34]; /* = totalLen for mouse naga needs change later */
397: } configHeader;
398: //configHeader usbConfDesc;
399:
400: char usb_data_buffer[8]; /* General purpose buffer */
401: int usb_task_level = kKernelLevel;
402:
403: void usb_iodone_wakeup(long lParam, OSStatus status, short s16Param);
404: int usb_iodone = 1;
405: char ports_connected[2] = {0,0};
406: usbControlBits usbConfig; /* 8 bytes */
407: USBDeviceDescriptor usbDesc; /* 18 bytes */
408: struct usbConfDesc
409: {
410: USBConfigurationDescriptor header;
411: USBInterfaceDescriptor interface;
412: USBEndPointDescriptor endpoint;
413: char rest_data[29];
414: } usbConfDesc;
415: void usb_donone(char *x,...)
416: {
417: }
418: void fill_usbDesc()
419: {
420: int i;
421: for(i=0;i<18;++i)
422: {
423: char *x = (char *)&usbDesc;
424: *x++ = 0xbc;
425: }
426: }
427: void print_usbDesc(char *usbDesc,int size)
428: {
429: int i;
430:
431: for(i=1;i<=size;++i)
432: {
433: kprintf("0x%02x ",(int) *usbDesc++);
434: if(i%10 == 0)kprintf("\n");
435: }
436: kprintf("\n");
437: }
438:
439: void print_td(OHCIGeneralTransferDescriptorPtr x)
440: {
441: // kprintf("TD(0x%08x):w0=0x%08x,w1(cbp)=0x%08x,w2=0x%08x,w3=0x%08x\n",x,EndianSwap32Bit(x->dWord0),EndianSwap32Bit(x->dWord1),EndianSwap32Bit(x->dWord2),EndianSwap32Bit(x->dWord3));
442: }
443:
444: void print_ed(OHCIEndpointDescriptorPtr x)
445: {
446: //kprintf("ED(0x%08x):w0=0x%08x,w1(cbp)=0x%08x,w2=0x%08x,w3=0x%08x\n",x,EndianSwap32Bit(x->dWord0),EndianSwap32Bit(x->dWord1),EndianSwap32Bit(x->dWord2),EndianSwap32Bit(x->dWord3));
447: }
448:
449: void usbAddBus()
450: {
451: extern struct UIMPluginDispatchTable ThePluginDispatchTable;
452: USBAddBus(0,&ThePluginDispatchTable,1);
453: }
454: UInt16 EndianSwap16Bit(UInt16 x)
455: {
456: UInt16 byte1,byte2;
457: byte1 = x & 0xFF;
458: byte2 = (x>>8) & 0xFF;
459: return (byte1<<8) | byte2;
460: }
461: UInt32 EndianSwap32Bit(UInt32 x)
462: {
463: UInt32 byte1,byte2,byte3,byte4;
464: UInt32 result;
465:
466: byte1 = x & 0xFF;
467: byte2 = (x>>8) & 0xFF;
468: byte3 = (x>>16) & 0xFF;
469: byte4 = (x>>24) & 0xFF;
470: result = (byte1<<24) | (byte2<<16) | (byte3<<8) | byte4;
471: return result;
472: }
473: void dump_regs(volatile UInt32 *x)
474: {
475: int i;
476: printf("Regs:\n");
477: for(i=0;i<23;++i)
478: {
479: printf("offset %2x: 0x%x\n",4*i,EndianSwap32Bit(*x++));
480: IOSync();
481: }
482: printf("End Regs\n");
483: }
484:
485: OSStatus CheckpointIO(IOPreparationID theIOPreparation, IOCheckpointOptions options)
486: {
487: return 0;
488: }
489: OSStatus DelayForHardware (AbsoluteTime absoluteTime)
490: {
491: int x = (int)((AbsoluteTime)1000*absoluteTime);
492: // delay((int)((AbsoluteTime)1000*absoluteTime));
493: kprintf("***Delaying for %d microseconds***\n",x);
494: delay(x);
495: return 0;
496: }
497: AbsoluteTime DurationToAbsolute(Duration duration)
498: {
499: AbsoluteTime x = (AbsoluteTime)duration; //naga
500: return x;
501: }
502:
503: AbsoluteTime UpTime(void)
504: {
505: static long r=67;
506: AbsoluteTime x ;
507: r= (r+12061999)%1389; //Random number better replace by std random fn
508: x = (AbsoluteTime)r;
509: return x;
510: }
511:
512: ExecutionLevel CurrentExecutionLevel()
513: {
514: return usb_task_level;
515: }
516:
517: LogicalAddress PoolAllocateResident(ByteCount byteSize, Boolean flag)
518: {
519: return (LogicalAddress)kalloc(byteSize);
520: }
521: OSStatus PoolDeallocate(LogicalAddress address)
522: {
523: //naga kfree(address,size??);
524: return 0;
525: }
526:
527: OSStatus QueueSecondaryInterruptHandler(SecondaryInterruptHandler2 theHandler, ExceptionHandler exceptionHandler, void *p1, void *p2)
528: {
529: (*theHandler)(p1,p2);
530: return 0;
531: }
532:
533: OSStatus CallSecondaryInterruptHandler2(SecondaryInterruptHandler2 theHandler, ExceptionHandler exceptionHandler, void *p1, void *p2)
534: {
535: (*theHandler)(p1,p2);
536: return 0;
537: }
538:
539:
540:
541: void BlockCopy(const void *src, void *tgt, Size len)
542: {
543: bcopy(src,tgt,len);
544: }
545: void usb_BlockMoveData(void *src, void *tgt, UInt32 len)
546: {
547: bcopy(src,tgt,len);
548: }
549: OSStatus CompareAndSwap(UInt32 old, UInt32 new, UInt32 *adr)
550: {
551: simple_lock(usb_slock);
552: if(*adr == old)
553: {
554: *adr = new;
555: simple_unlock(usb_slock);
556: return true;
557: }
558: simple_unlock(usb_slock);
559: return false;
560: }
561:
562: UInt16 Disable68kInterrupts(void)
563: {
564: return 0;
565: }
566: void Restore68kInterrupts(UInt16 a)
567: {
568: }
569:
570: /* See Page 276 of Writing drivers for PCI cards */
571: SInt32 AddAtomic(SInt32 amount, SInt32 *value)
572: {
573: simple_lock(usb_slock);
574: *value += amount;
575: simple_unlock(usb_slock);
576: return (*value);
577: }
578:
579: /* see pg. 271 */
580: AbsoluteTime AddAbsoluteToAbsolute(AbsoluteTime a, AbsoluteTime b)
581: {
582: AbsoluteTime c;
583:
584: simple_lock(usb_slock);
585: c = a+b;
586: simple_unlock(usb_slock);
587: return c;
588: }
589: void SysDebugStr(ConstStr255Param str)
590: {
591: kprintf("SysDebugStr: Not implemented yet\n");
592: }
593:
594: OSStatus CancelTimer (TimerID theTimer, AbsoluteTime *timeRemaining)
595: {
596: kprintf("***CancelTimer not yet implemented***\n");
597: return 0;
598: }
599: /*
600: OSStatus SetInterruptTimer (const AbsoluteTime *expirationTime, SecondaryInterruptHandler2 handler, void *p1, TimerID *theTimer)
601: {
602: kprintf("*** SetInterruptTimer not yet implemented***\n");
603: IOSchduleFunc((IOThreadFunc)handler, p1,1)
604: return 0;
605: }
606: */
607: OSStatus PrepareMemoryForIO(IOPreparationTable *ioPrep)
608: {
609: return 0;
610: }
611:
612: void BlockZero(void *ptr, int size)
613: {
614: bzero(ptr,size);
615: }
616: OSStatus RegistryEntryIDDispose (RegEntryID *foundEntry)
617: {
618: kprintf("***RegistryEntryIDDispose:Not yet Implemented***\n");
619: return noErr;
620: }
621:
622: OSStatus RegistryCStrEntryLookup(const RegEntryID *searchPointID, const RegCStrPathName *pathName, RegEntryID *foundEntry)
623: {
624: kprintf("***RegistryCStrEntryLookupisposePtr:Not yet Implemented***\n");
625: return noErr;
626: }
627:
628: Ptr usb_NewPtr(RegPropertyValueSize propertySize)
629: {
630: return (Ptr)kalloc(propertySize);
631: }
632: void usb_DisposePtr(Ptr modelNamePropertyStrPtr )
633: {
634: kprintf("usb_DisposePtr:Not yet Implemented\n");
635: }
636: void c2pstr(Ptr modelNamePropertyStrPtr )
637: {
638: kprintf("c2pstr:Not yet Implemented\n");
639: }
640: OSStatus CompareString(Str255 inMachineNameStr, Str255 MacMachineName, char *ignore_null)
641: {
642: return strcmp((char *)inMachineNameStr, (char *) MacMachineName);
643: }
644: OSStatus RegistryPropertyGetSize(const RegEntryID *entryID, const RegPropertyName *propertyName, RegPropertyValueSize *propertySize)
645: {
646: kprintf("RegistryPropertyGetSize not implemented\n");
647: return 0;
648: }
649: void USBDemoKeyIn(UInt32 refcon, void *theData)
650: {
651: kprintf("USBDemoKeyIn:Not yet Implemented\n");
652: }
653:
654:
655: UInt64 usb_U64Add(UInt64 a, UInt64 b)
656: {
657: return a+b;
658: }
659:
660: UInt64 U64SetU(UInt32 a)
661: {
662: return (UInt64) a;
663: }
664: UInt32 U32SetU(UInt64 a)
665: {
666: return (UInt32) a;
667: }
668:
669: /* Barry - Silly routine to stop unused paramter warnings */
670:
671: static void parameterNotUsed(UInt32 notUsed)
672: {
673: notUsed = 0;
674: }
675: void usb_iodone_wakeup(long lParam, OSStatus status, short s16Param)
676: {
677: usb_iodone = 1;
678: }
679: void wait_usbio()
680: {
681: #if 0
682: while(usb_iodone == 0)
683: {
684: timeout((timeout_fcn_t)wakeup,&usb_iodone,(100*HZ+999)/1000);
685: sleep((char *)&usb_iodone,PZERO);
686: }
687: #endif
688: }
689:
690:
691: ////////////////////////////////////////////////////////////////////////////////
692: ////////////////////////////////////////////////////////////////////////////////
693: //
694: // UIM interface routines.
695: //
696: ////////////////////////////////////////////////////////////////////////////////
697: ////////////////////////////////////////////////////////////////////////////////
698:
699: /* This is here so the UIM knows what its address is and can shunt those off to the sim */
700: Boolean OHCISetOurAddress(uslBusRef bus, UInt16 addr)
701: {
702: pOHCIUIMData->rootHubFuncAddress = addr;
703: bus = 0; // not used
704: return(false);
705: }
706:
707:
708: ////////////////////////////////////////////////////////////////////////////////
709: //
710: // OHCIUIMInitialize
711: //
712: // This is the UIM initialization procedure.
713: //
714:
715:
716: int OHCIUIMInitialize(unsigned long ioBase)
717: {
718: RegEntryIDPtr pUIMRegEntryID;
719: OHCIRegistersPtr pOHCIRegisters;
720: UInt32 hccaAlignment;
721: Ptr pHCCAAllocation;
722: UInt32 hcFmInterval;
723: OSStatus status = noErr;
724:
725: pOHCIUIMData = (OHCIUIMDataPtr)kalloc (sizeof (OHCIUIMData));
726: if (pOHCIUIMData == NULL)
727: return 1;
728: BlockZero(pOHCIUIMData,sizeof(OHCIUIMData));
729: pOHCIUIMData->errataBits = GetErrataBits(pUIMRegEntryID);
730: pOHCIUIMData->pageSize = PAGE_SIZE;
731:
732: //Allocate TDs, EDs;need to find out real numbers to use, CPU specific.
733: OHCIUIMAllocateMemory(1500,1500, 1300);
734: //OHCIUIMAllocateMemory(40,40, 100);
735: pOHCIUIMData->pOHCIRegisters = pOHCIRegisters = ioBase; //Should be 3519000 on PowerSurge
736: dump_regs((volatile UInt32 *)ioBase);
737: // is this a goofy CMD chip that is using UHCI-style test mode? If so, make it behave like an OHCI controller.
738: kprintf("errata bits=0x%x,mask=0x%x\n",pOHCIUIMData->errataBits,kErrataCMDDisableTestMode);
739: if (pOHCIUIMData->errataBits & kErrataCMDDisableTestMode)
740: {
741: UInt32 registerVal;
742: kprintf("fixing errata bits for cmd\n");
743: // see CMD 670 documentation, appendix A for rev KAB-4 parts
744: ReadConfigVal(0x4C,®isterVal);
745: //[deviceDescription configReadLong:0x4C value:®isterVal];
746: registerVal &= ~2;
747: // [deviceDescription configWriteLong:0x4C value:registerVal];
748: WriteConfigVal(0x4C,registerVal);
749: }
750: WriteConfigVal(cwCommand,(cwCommandEnableBusMaster | cwCommandEnableMemorySpace));
751: //[deviceDescription configWriteLong:cwCommand value:(cwCommandEnableBusMaster | cwCommandEnableMemorySpace)];
752: pOHCIRegisters->hcControlCurrentED = pOHCIRegisters->hcControlHeadED = pOHCIRegisters->hcDoneHead = 0;
753: IOSync();
754: // Set up HCCA.
755: if (status == noErr)
756: {
757: // Compute alignment of HCCA. zzz do for real
758: hccaAlignment = 256;
759: kprintf("settingup HCCA\n");
760: // Allocate HCCA.
761: pHCCAAllocation = kalloc (2 * hccaAlignment);
762: if (pHCCAAllocation != nil)
763: {
764: //Needs to be the physical Address
765: pOHCIUIMData->pHCCAAllocation = pHCCAAllocation;
766: pOHCIUIMData->pHCCA = (Ptr) (((UInt32) pHCCAAllocation + hccaAlignment) & ~(hccaAlignment - 1));
767: pOHCIRegisters->hcHCCA = EndianSwap32Bit((UInt32)kvtophys((vm_offset_t) pOHCIUIMData->pHCCA));
768: IOSync();
769: kprintf("pHCCAAllocation=0x%x,aligned logical=0x%x,phy=0x%x\n",pHCCAAllocation,pOHCIUIMData->pHCCA,pOHCIRegisters->hcHCCA);
770: /* Set the HC to write the donehead to the HCCA, and enable interrupts */
771: pOHCIRegisters->hcInterruptStatus = EndianSwap32Bit(kOHCIHcInterrupt_WDH);
772: IOSync();
773:
774: }
775: else
776: {
777: kprintf("kalloc failed!!\n");
778: status = 1; // memory full
779: }
780:
781: }
782:
783: // Initialize the Root Hub registers
784: if (status == noErr)
785: {
786: pOHCIRegisters->hcRhStatus = EndianSwap32Bit (/*kOHCIHcRhStatus_LPSC |*/kOHCIHcRhStatus_OCIC | kOHCIHcRhStatus_CRWE);
787: OHCIResetRootHub(0);
788: IOSync();
789: }
790:
791: // set up Interrupt transfer tree
792: if (status == noErr)
793: {
794: status = OHCIUIMIsochronousInitialize();
795: status = OHCIUIMInterruptInitialize();
796: status = OHCIUIMBulkInitialize();
797: status = OHCIUIMControlInitialize();
798: pOHCIUIMData->rootHubFuncAddress = 0;
799: }
800:
801: kprintf("over interrupt transfer tree,status=%d\n",status);
802: // Set up hcFmInterval.
803: //zzz what would be a good number for FSMPS?
804: if (status == noErr)
805: {
806: UInt32 hcFSMPS;
807: hcFmInterval = 11999;
808: // hcFSMPS = (((hcFmInterval & kOHCIHcFmInterval_FI)-kOHCIMax_OverHead) * 6)/7;
809: hcFSMPS = 10100; // Barry fix undefineds.
810: hcFmInterval = (hcFmInterval & ~kOHCIHcFmInterval_FSMPS) |
811: (hcFSMPS << kOHCIHcFmInterval_FSMPSPhase);
812: pOHCIRegisters->hcFmInterval = EndianSwap32Bit (hcFmInterval);
813: IOSync();
814: }
815:
816: // Set up OHCI periodic start to determine time to start processing periodic values,
817: // use hcfminterval and get 90% of that, can use simple integer math, since frame interval
818: // is no more than 14 bits.
819: hcFmInterval = EndianSwap32Bit (pOHCIRegisters->hcFmInterval);
820: IOSync();
821: hcFmInterval &= kOHCIHcFmInterval_FIPhase;
822: pOHCIRegisters->hcPeriodicStart = EndianSwap32Bit (10800);
823: IOSync();
824: // pOHCIRegisters->hcPeriodicStart = EndianSwap32Bit (( hcFmInterval*9)/10);
825:
826: // Set OHCI to operational state and enable processing of control list.
827: if (status == noErr)
828: {
829: kprintf("Setting up usb operational\n");
830: pOHCIRegisters->hcControl = EndianSwapImm32Bit ((kOHCIFunctionalState_Operational << kOHCIHcControl_HCFSPhase) |
831: kOHCIHcControl_CLE | kOHCIHcControl_BLE | kOHCIHcControl_PLE | kOHCIHcControl_IE);
832: IOSync();
833: }
834:
835: if (status == noErr)
836: {
837: kprintf("enabling interrupts\n");
838: pOHCIRegisters->hcInterruptEnable = EndianSwap32Bit (kOHCIHcInterrupt_MIE | kOHCIDefaultInterrupts);
839: IOSync();
840: kprintf("After Enabling regs=:\n");
841: dump_regs((volatile UInt32 *)ioBase);
842: enable_intr();
843: //naga (*pOHCIUIMData->interruptEnabler)(pOHCIUIMData->interruptSetMember, nil);
844: }
845:
846: if (pOHCIUIMData->errataBits & kErrataLSHSOpti)
847: status = OptiLSHSFix();
848:
849: // Clean up on error.
850: if (status != noErr)
851: {
852: kprintf("OHCIUIMFinalize called!!!!\n");
853: if (pOHCIUIMData != nil)
854: OHCIUIMFinalizeOHCIUIMData (pOHCIUIMData);
855: }
856: //naga
857: usb_slock = simple_lock_alloc();
858: simple_lock_init(usb_slock);
859: return (status);
860: }
861:
862: ////////////////////////////////////////////////////////////////////////////////
863: //
864: // OHCIUIMFinalize
865: //
866: // This is the UIM finalization procedure.
867: //
868:
869:
870: OSStatus OHCIUIMFinalize(
871: Boolean beingReplaced,
872: Ptr * savedStatePtr)
873: {
874: OHCIRegistersPtr pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
875: OSStatus status = noErr;
876:
877:
878: if (!beingReplaced) {
879: ProgressDebugStr ((ConstStr255Param) "OHCIUIMFinalize (shutting down HW)");
880:
881: // Disable All OHCI Interrupts
882: (*pOHCIUIMData->interruptDisabler)(pOHCIUIMData->interruptSetMember, nil);
883: pOHCIRegisters->hcInterruptDisable = kOHCIHcInterrupt_MIE;
884: /*naga
885: // restore interrupt set
886: status = InstallInterruptFunctions
887: (pOHCIUIMData->interruptSetMember.setID, pOHCIUIMData->interruptSetMember.member,
888: pOHCIUIMData->oldInterruptRefCon, pOHCIUIMData->oldInterruptHandler,
889: pOHCIUIMData->interruptEnabler, pOHCIUIMData->interruptDisabler);
890: */
891:
892: // Place the USB bus into the Reset State
893: pOHCIRegisters->hcControl = EndianSwapImm32Bit ((kOHCIFunctionalState_Reset << kOHCIHcControl_HCFSPhase));
894:
895: // Take away the controllers ability be a bus master.
896: //naga status = ExpMgrConfigWriteWord(&pOHCIUIMData->ohciRegEntryID,(LogicalAddress) cwCommand, cwCommandEnableMemorySpace); // turn off busmastering,
897: WriteConfigVal(cwCommand,cwCommandEnableMemorySpace);
898: // Clear all Processing Registers
899: pOHCIRegisters->hcHCCA = nil;
900: pOHCIRegisters->hcPeriodCurrentED = nil;
901: pOHCIRegisters->hcControlHeadED = nil;
902: pOHCIRegisters->hcControlCurrentED = nil;
903: pOHCIRegisters->hcBulkHeadED = nil;
904: pOHCIRegisters->hcBulkCurrentED = nil;
905: pOHCIRegisters->hcDoneHead = nil;
906:
907: OHCIRootHubPower( 0, 0); // turn off the global power zzzzz - check for per-port vs. Global power control
908:
909: status = OHCIUIMFinalizeOHCIUIMData ((OHCIUIMDataPtr) pOHCIUIMData);
910: } else {
911: ProgressDebugStr ((ConstStr255Param) "OHCIUIMFinalize (being replaced)");
912: pOHCIRegisters->hcInterruptDisable = kOHCIHcInterrupt_MIE;
913: /*naga
914: // restore interrupt set
915: status = InstallInterruptFunctions
916: (pOHCIUIMData->interruptSetMember.setID, pOHCIUIMData->interruptSetMember.member,
917: pOHCIUIMData->oldInterruptRefCon, pOHCIUIMData->oldInterruptHandler,
918: pOHCIUIMData->interruptEnabler, pOHCIUIMData->interruptDisabler);
919: */
920: *savedStatePtr = (Ptr) pOHCIUIMData;
921: }
922:
923: ProgressDebugStr ((ConstStr255Param) "OHCIUIMFinalize Exit");
924:
925:
926: return (status);
927: }
928: static OSStatus OHCIUIMFinalizeOHCIUIMData(
929: OHCIUIMDataPtr pOHCIUIMData)
930: {
931: OSStatus status = noErr;
932: ProgressDebugStr ((ConstStr255Param) "OHCIUIMfinalize");
933:
934: if (pOHCIUIMData != nil)
935: {
936: // Deallocate HCCA.
937: if (pOHCIUIMData->pHCCAAllocation != nil){
938: PoolDeallocate (pOHCIUIMData->pHCCAAllocation);
939: pOHCIUIMData->pHCCAAllocation = nil;
940: }
941: //nagaif (pOHCIUIMData->pDataAllocation)
942: //naga MemDeallocatePhysicallyContiguous(pOHCIUIMData->pDataAllocation);
943:
944: if (pOHCIUIMData->pPhysicalLogical)
945: PoolDeallocate (pOHCIUIMData->pPhysicalLogical);
946:
947: // Deallocate UIM data record.
948: PoolDeallocate ((Ptr) pOHCIUIMData);
949: pOHCIUIMData = nil;
950: }
951:
952: return (status);
953: }
954:
955: // Barry set frame interrupt on. This will be disabled by the service routine, so this is one shot
956:
957: void OHCISetFrameInterrupt(void)
958: {
959: #if 0
960: OHCIRegistersPtr pOHCIRegisters;
961: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
962: pOHCIRegisters->hcInterruptEnable = EndianSwap32Bit(kOHCIHcInterrupt_SF);
963: #endif
964: }
965:
966:
967:
968: // What needs to be done?
969: // Need to figure out an efficient way of keeping track of callbackroutines for when a transaction completes.
970: // what to do with control transaction which are really three transactions, must call callback only after
971: // status transaction completes, but must also keep track of what happens to setup and bulk transactions.
972: // hmmmmmmmmmm...its guaranteed that they will finish inorder, but if setup or bulk fails will the HC disable
973: // the endpoint until I clean up or will the it continue on til the next one.
974:
975:
976:
977: OHCIEndpointDescriptorPtr AddEmptyEndPoint(
978: UInt8 functionAddress,
979: UInt8 endpointNumber,
980: UInt16 maxPacketSize,
981: UInt8 speed,
982: UInt8 direction,
983: OHCIEndpointDescriptorPtr pED,
984: int isoch)
985:
986: {
987: UInt32 myFunctionAddress, myEndPointNumber,myEndPointDirection,myMaxPacketSize, mySpeed, myIsoch;
988: OHCIEndpointDescriptorPtr pOHCIEndpointDescriptor;
989: OHCIGeneralTransferDescriptorPtr pOHCIGeneralTransferDescriptor;
990: OHCIIsochTransferDescriptorPtr pITD;
991:
992: pOHCIEndpointDescriptor = (OHCIEndpointDescriptorPtr) OHCIUIMAllocateED();
993: myFunctionAddress = ((UInt32) functionAddress) << kOHCIEDControl_FAPhase;
994: myEndPointNumber = ((UInt32) endpointNumber) << kOHCIEDControl_ENPhase;
995:
996: myEndPointDirection = ((UInt32) direction) << kOHCIEDControl_DPhase;
997:
998: mySpeed = ((UInt32) speed) << kOHCIEDControl_SPhase;
999:
1000: myMaxPacketSize = ((UInt32) maxPacketSize) << kOHCIEDControl_MPSPhase;
1001:
1002: myIsoch = ((UInt32) isoch) << kOHCIEDControl_FPhase;
1003: pOHCIEndpointDescriptor->dWord0 = EndianSwap32Bit(myFunctionAddress | myEndPointNumber
1004: | myEndPointDirection | myMaxPacketSize |mySpeed | myIsoch);
1005: if (isoch == kOHCIEDFormatGeneralTD) {
1006: pOHCIGeneralTransferDescriptor = OHCIUIMAllocateTD();
1007:
1008: /* These were previously nil */
1009: pOHCIEndpointDescriptor->dWord1 = EndianSwap32Bit( (UInt32) pOHCIGeneralTransferDescriptor->pPhysical);
1010: pOHCIEndpointDescriptor->dWord2 = EndianSwap32Bit( (UInt32) pOHCIGeneralTransferDescriptor->pPhysical);
1011: pOHCIEndpointDescriptor->pVirtualTailP = (UInt32) pOHCIGeneralTransferDescriptor;
1012: pOHCIEndpointDescriptor->pVirtualHeadP = (UInt32) pOHCIGeneralTransferDescriptor;
1013:
1014: } else {
1015: pITD = OHCIUIMAllocateITD();
1016:
1017: /* These were previously nil */
1018: pOHCIEndpointDescriptor->dWord1 = EndianSwap32Bit( (UInt32) pITD->pPhysical);
1019: pOHCIEndpointDescriptor->dWord2 = EndianSwap32Bit( (UInt32) pITD->pPhysical);
1020: pOHCIEndpointDescriptor->pVirtualTailP = (UInt32) pITD;
1021: pOHCIEndpointDescriptor->pVirtualHeadP = (UInt32) pITD;
1022:
1023: }
1024:
1025: pOHCIEndpointDescriptor->dWord3 = pED->dWord3;
1026: pOHCIEndpointDescriptor->pVirtualNext = pED->pVirtualNext;
1027: pED->pVirtualNext = (UInt32) pOHCIEndpointDescriptor;
1028: pED->dWord3 = EndianSwap32Bit (pOHCIEndpointDescriptor->pPhysical);
1029:
1030:
1031: return (pOHCIEndpointDescriptor);
1032:
1033: }
1034:
1035: OSStatus OHCIUIMControlEDCreate(
1036: UInt8 functionAddress,
1037: UInt8 endpointNumber,
1038: UInt16 maxPacketSize,
1039: UInt8 speed)
1040: {
1041: OHCIEndpointDescriptorPtr pOHCIEndpointDescriptor, pED;
1042: OSStatus status = noErr;
1043:
1044: #if 0
1045: /* BT - Let the set address command do this */
1046: if ((pOHCIUIMData->rootHubFuncAddress == 0) && (functionAddress == 0))
1047: {
1048: return(status);
1049: }
1050: if (pOHCIUIMData->rootHubFuncAddress == 0){
1051: pOHCIUIMData->rootHubFuncAddress = functionAddress;
1052: return(status);
1053: }
1054: #endif
1055:
1056: kprintf("OHCIUIMControlEDCreate: fn=%d,ep=%d\n",functionAddress,endpointNumber);
1057: if (pOHCIUIMData->rootHubFuncAddress == functionAddress)
1058: return (status);
1059:
1060: pED = (OHCIEndpointDescriptorPtr) pOHCIUIMData->pControlHead;
1061: if ((speed == kOHCIEDSpeedFull) && pOHCIUIMData->OptiOn)
1062: pED = (OHCIEndpointDescriptorPtr) pOHCIUIMData->pBulkHead;
1063:
1064: pOHCIEndpointDescriptor = AddEmptyEndPoint (
1065: functionAddress, endpointNumber, maxPacketSize, speed, kOHCIEDDirectionTD, pED, kOHCIEDFormatGeneralTD);
1066:
1067: if (pOHCIEndpointDescriptor == nil)
1068: return(-1);
1069: return (status);
1070: }
1071:
1072:
1073:
1074: OSStatus OHCIUIMControlTransfer(
1075: UInt32 refcon,
1076: CallBackFuncPtr handler,
1077: UInt32 CBP,
1078: Boolean bufferRounding,
1079: short functionNumber,
1080: short endpointNumber,
1081: short bufferSize,
1082: short direction)
1083: {
1084: OHCIRegistersPtr pOHCIRegisters;
1085: OHCIGeneralTransferDescriptorPtr
1086: pOHCIGeneralTransferDescriptor,
1087: newOHCIGeneralTransferDescriptor;
1088: OSStatus status = noErr;
1089: UInt32 myBufferRounding;
1090: UInt32 myDirection;
1091: UInt32 myToggle;
1092: UInt32 CBPPhysical;
1093:
1094: OHCIEndpointDescriptorPtr pEDQueue, pEDDummy;
1095:
1096:
1097:
1098: if (pOHCIUIMData->rootHubFuncAddress == functionNumber)
1099: {
1100: //kprintf("OHCIUIMControlTransfer:Calling UIMSimulateRootHubStages\n");
1101: return(UIMSimulateRootHubStages(refcon, handler, CBP, bufferRounding,
1102: endpointNumber, bufferSize, direction));
1103: }
1104: //kprintf("Cntl Tx:roothubfuncaddr=0x%x,fnumb=0x%x;calling FindControlEndpoint\n",pOHCIUIMData->rootHubFuncAddress , functionNumber);
1105: if (direction == kUSBOut)
1106: direction = kOHCIGTDPIDOut;
1107: else if (direction == kUSBIn)
1108: direction = kOHCIGTDPIDIn;
1109: else
1110: direction = kOHCIGTDPIDSetup;
1111:
1112:
1113: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
1114: //search for endpoint descriptor
1115:
1116: pEDQueue = FindControlEndpoint(functionNumber, endpointNumber, &pEDDummy);
1117: if (pEDQueue == nil){
1118: kprintf("OHCIUIMControlTransfer: Couldnot find endpoint\n");
1119: status = kUSBNotFound;
1120: return(status);
1121: }
1122: myBufferRounding = (UInt32) bufferRounding << kOHCIBufferRoundingOffset;
1123: myDirection = (UInt32) direction << kOHCIDirectionOffset;
1124: myToggle = kOHCIBit25; /* Take data toggle from TD */
1125: if(direction !=0)
1126: { /* Setup uses Data 0, data status use Data1 */
1127: myToggle |= kOHCIBit24; /* use Data1 */
1128: }
1129:
1130: // setup transfer descriptor
1131: newOHCIGeneralTransferDescriptor = OHCIUIMAllocateTD();
1132: if (newOHCIGeneralTransferDescriptor == nil)
1133: {
1134: kprintf("Kalloc TD failed\n");
1135: return (-1);
1136: }
1137:
1138: /* Last in queue is a dummy descriptor. Fill it in then add new dummy */
1139: pOHCIGeneralTransferDescriptor = (OHCIGeneralTransferDescriptorPtr) pEDQueue->pVirtualTailP;
1140: pOHCIGeneralTransferDescriptor->pEndpoint = (UInt32) pEDQueue; //naga added for our reference
1141: pOHCIGeneralTransferDescriptor->dWord0 = EndianSwap32Bit (myBufferRounding | myDirection | myToggle);
1142: //kprintf("dword0=0x%x,round=0x%x,dir=0x%x,toggle=0x%x\n",EndianSwap32Bit (pOHCIGeneralTransferDescriptor->dWord0),myBufferRounding,myDirection,myToggle);
1143: pOHCIGeneralTransferDescriptor->dWord2 = EndianSwap32Bit ((UInt32)newOHCIGeneralTransferDescriptor->pPhysical);
1144: pOHCIGeneralTransferDescriptor->pVirtualNext = (UInt32)newOHCIGeneralTransferDescriptor;
1145:
1146: if (bufferSize != 0)
1147: {
1148: CBPPhysical = kvtophys((vm_offset_t) CBP);
1149: pOHCIGeneralTransferDescriptor->dWord1 = EndianSwap32Bit (CBPPhysical);
1150: pOHCIGeneralTransferDescriptor->dWord3 = EndianSwap32Bit (CBPPhysical + bufferSize-1);
1151: }
1152: else
1153: {
1154: pOHCIGeneralTransferDescriptor->dWord1 = 0;
1155: pOHCIGeneralTransferDescriptor->dWord3 = 0;
1156: }
1157: pOHCIGeneralTransferDescriptor->CallBack = handler;
1158: pOHCIGeneralTransferDescriptor->refcon = refcon;
1159:
1160: /* Make new descriptor the tail */
1161: pEDQueue->dWord1 = pOHCIGeneralTransferDescriptor->dWord2;
1162: pEDQueue->pVirtualTailP = (UInt32) newOHCIGeneralTransferDescriptor;
1163:
1164: print_ed(pEDQueue);
1165: print_td(pOHCIGeneralTransferDescriptor);
1166: pOHCIRegisters->hcCommandStatus = EndianSwap32Bit (kOHCIHcCommandStatus_CLF);
1167: IOSync();
1168: return (status);
1169: }
1170: OSStatus OHCIUIMControlEDDelete(
1171: short functionNumber,
1172: short endpointNumber)
1173: {
1174: OSStatus status = noErr;
1175:
1176: if (pOHCIUIMData->rootHubFuncAddress == functionNumber)
1177: return (status);
1178: kprintf("OHCIUIMControlEDDelete: calling OHCIUIMEndpointDelete if fn=ep fn=%d,ep=%d\n",functionNumber,endpointNumber);
1179: status = OHCIUIMEndpointDelete(functionNumber, endpointNumber, 3);
1180:
1181: return (status);
1182: }
1183:
1184: OSStatus OHCIUIMBulkEDCreate(
1185: UInt8 functionAddress,
1186: UInt8 endpointNumber,
1187: UInt8 direction,
1188: UInt8 maxPacketSize)
1189: {
1190: OHCIEndpointDescriptorPtr pOHCIEndpointDescriptor, pED;
1191: OSStatus status = noErr;
1192: if (direction == kUSBOut)
1193: direction = kOHCIEDDirectionOut;
1194: else if (direction == kUSBIn)
1195: direction = kOHCIEDDirectionIn;
1196: else
1197: direction = kOHCIEDDirectionTD;
1198:
1199: pED = (OHCIEndpointDescriptorPtr) pOHCIUIMData->pBulkHead;
1200: pOHCIEndpointDescriptor = AddEmptyEndPoint (
1201: functionAddress, endpointNumber, maxPacketSize, kOHCIEDSpeedFull, direction, pED, kOHCIEDFormatGeneralTD);
1202: if (pOHCIEndpointDescriptor == nil)
1203: return(-1);
1204: return (status);
1205:
1206: }
1207:
1208: /* Naga This function needs to be edited to replace prepareMemoryforio with kvtophys -- see OHCIUIMInterruptTransfer for cut/paste */
1209: OSStatus OHCIUIMBulkTransfer(
1210: UInt32 refcon,
1211: CallBackFuncPtr handler,
1212: UInt32 CBP,
1213: Boolean bufferRounding,
1214: short functionNumber,
1215: short endpointNumber,
1216: UInt32 bufferSize,
1217: short direction)
1218: {
1219: OHCIRegistersPtr pOHCIRegisters;
1220: OHCIGeneralTransferDescriptorPtr
1221: pOHCIGeneralTransferDescriptor,
1222: newOHCIGeneralTransferDescriptor;
1223: OSStatus status = noErr;
1224: UInt32 myBufferRounding;
1225: UInt32 endPtDirection;
1226: UInt32 TDDirection;
1227: OHCIEndpointDescriptorPtr pEDQueue, pEDDummy;
1228: IOPreparationTable *ioPrep;
1229: IOPreparationTable IOPrep;
1230: UInt32 physicalAddresses[kOHCIMaxPages];
1231: UInt32 numPages, firstCount, lastCount;
1232: IOPreparationID preparationID;
1233: UInt32 pageSize, pageOffsetMask;
1234: int i;
1235: UInt32 alignment, pageOffset, pageMask, pageCount;
1236:
1237: // DebugStr("OHCIUIM: InSide Bulk TD setup");
1238:
1239: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
1240: pageSize = pOHCIUIMData->pageSize;
1241: ioPrep = &IOPrep;
1242:
1243: if (direction == kUSBOut)
1244: direction = kOHCIEDDirectionOut;
1245: else if (direction == kUSBIn)
1246: direction = kOHCIEDDirectionIn;
1247: else
1248: direction = kOHCIEDDirectionTD;
1249:
1250: //search for endpoint descriptor
1251: pEDQueue = FindBulkEndpoint (functionNumber, endpointNumber, direction, &pEDDummy);
1252:
1253: if (!pEDQueue){
1254: FailureDebugStr("UIMBulkTransfer: Couldnot find endpoint");
1255: status = kUSBNotFound;
1256: return (status);
1257: }
1258:
1259:
1260: pageOffsetMask = pageSize - 1;
1261: pageMask = ~pageOffsetMask;
1262:
1263: myBufferRounding = (UInt32) bufferRounding << kOHCIBufferRoundingOffset;
1264: endPtDirection = (UInt32) direction << kOHCIEndpointDirectionOffset;
1265: TDDirection = (UInt32) direction << kOHCIDirectionOffset;
1266:
1267: // FERG DEBUG
1268: // uncomment the next line to force the data to be put in TD list, but not be processed
1269: // this is handy for using USBProber/Macsbug to look at TD's to see if they're OK.
1270: // pEDQueue->dWord0 |= EndianSwap32Bit (kOHCIEDControl_K);
1271: // FERG DEBUG
1272: alignment = CBP % ((EndianSwap32Bit (pEDQueue->dWord0)
1273: & kOHCIEDControl_MPS) >> kOHCIEDControl_MPSPhase);
1274: if(alignment != 0)
1275: {
1276: // DebugStr("OHCIUIM: determining pageOffset");
1277:
1278: pageOffset = CBP & pageOffsetMask;
1279: }
1280: if (bufferSize != 0)
1281: {
1282: while ((status == noErr) && (bufferSize > 0)) {
1283:
1284: firstCount = pageSize - (CBP & pageOffsetMask);
1285: if (bufferSize <= firstCount){
1286: lastCount = 0;
1287: numPages = 1;
1288: firstCount = bufferSize;
1289: } else {
1290: lastCount = (CBP + bufferSize) & pageOffsetMask;
1291: numPages = (bufferSize - firstCount - lastCount)/pageSize;
1292: if (firstCount) numPages++;
1293: if (lastCount) numPages++;
1294: }
1295:
1296: // Prepare for IO and get physical address
1297: ioPrep->options = kIOLogicalRanges | kIOIsInput | kIOIsOutput;
1298: ioPrep->addressSpace = kCurrentAddressSpaceID; // default
1299: ioPrep->granularity = 0; // do it all now
1300: ioPrep->firstPrepared = 0;
1301: ioPrep->mappingEntryCount = MIN (numPages, kOHCIMaxPages) ; // # of pages we will use
1302: ioPrep->logicalMapping = 0;
1303: ioPrep->physicalMapping = (PhysicalMappingTablePtr) physicalAddresses; // return list of phys addrs
1304: ioPrep->rangeInfo.range.base = (void *) CBP;
1305: ioPrep->rangeInfo.range.length = bufferSize;
1306:
1307: status = PrepareMemoryForIO (ioPrep);
1308: if (status == noErr){
1309: preparationID = ioPrep->preparationID;
1310: pageCount = ioPrep->mappingEntryCount;
1311: if ((alignment != 0) && (ioPrep->mappingEntryCount == kOHCIMaxPages))
1312: pageCount--;
1313: for (i = 0; i< pageCount; i++) {
1314: newOHCIGeneralTransferDescriptor = OHCIUIMAllocateTD();
1315: if (newOHCIGeneralTransferDescriptor == nil) {
1316: return (-1);
1317: }
1318: pOHCIGeneralTransferDescriptor = (OHCIGeneralTransferDescriptorPtr) pEDQueue->pVirtualTailP;
1319: pOHCIGeneralTransferDescriptor->dWord0 = EndianSwap32Bit (myBufferRounding | TDDirection);
1320: pOHCIGeneralTransferDescriptor->dWord2 = EndianSwap32Bit ((UInt32)newOHCIGeneralTransferDescriptor->pPhysical);
1321: pOHCIGeneralTransferDescriptor->pVirtualNext = (UInt32)newOHCIGeneralTransferDescriptor;
1322: pOHCIGeneralTransferDescriptor->dWord1 = EndianSwap32Bit (physicalAddresses[i]);
1323: pOHCIGeneralTransferDescriptor->pEndpoint = (UInt32) pEDQueue;
1324: // zzzzzz - really should check the direction to specify IN or OUT type.
1325: pOHCIGeneralTransferDescriptor->pType = (UInt32) kOHCIBulkTransferOutType;
1326: firstCount = pageSize - (CBP & pageOffsetMask);
1327: // if an IN and not aligned
1328: if(alignment != 0) {
1329: // DebugStr("OHCIUIM: unaligned in buffer");
1330: pOHCIGeneralTransferDescriptor->dWord1 = EndianSwap32Bit (
1331: (physicalAddresses[i] & pageMask) + pageOffset);
1332: if ( bufferSize > pageSize)
1333: pOHCIGeneralTransferDescriptor->dWord3 = EndianSwap32Bit (
1334: physicalAddresses[i+1] + pageOffset -1);
1335: else if (bufferSize >= (pageSize - pageOffset))
1336: pOHCIGeneralTransferDescriptor->dWord3 = EndianSwap32Bit (
1337: physicalAddresses[++i] + bufferSize - (pageSize - pageOffset) -1);
1338: else
1339: pOHCIGeneralTransferDescriptor->dWord3 = EndianSwap32Bit ((physicalAddresses[i]& pageMask)
1340: + bufferSize + pageOffset - 1);
1341:
1342: lastCount = MIN(pageSize, bufferSize);
1343: firstCount = 0;
1344: }else if ((firstCount >= bufferSize)
1345: || (i+1 == ioPrep->mappingEntryCount) // this is really the last (non-full) block to be transferred
1346: || pOHCIUIMData->errataBits & kErrataOnlySinglePageTransfers){ // only do a max of one page per transfer descriptor
1347: lastCount = 0;
1348: firstCount = MIN(firstCount, bufferSize);
1349: pOHCIGeneralTransferDescriptor->dWord3 = EndianSwap32Bit (physicalAddresses[i] + firstCount - 1);
1350: } else {
1351: i++;
1352: lastCount = MIN (bufferSize - firstCount, pageSize);
1353: pOHCIGeneralTransferDescriptor->dWord3 = EndianSwap32Bit (physicalAddresses[i] + lastCount - 1);
1354: }
1355: bufferSize -= (firstCount + lastCount);
1356: // only supply a callback when the entire buffer has been transfered.
1357: pOHCIGeneralTransferDescriptor->CallBack = (bufferSize <= 0) ? handler : nil;
1358: pOHCIGeneralTransferDescriptor->refcon = refcon;
1359: // supply a preparationID at the end of each prepared range
1360: // pOHCIGeneralTransferDescriptor->preparationID = (i+1 == ioPrep->mappingEntryCount) ? preparationID : nil;
1361: CBP += (firstCount + lastCount);
1362: pEDQueue->dWord1 = pOHCIGeneralTransferDescriptor->dWord2;
1363: pEDQueue->pVirtualTailP = (UInt32) newOHCIGeneralTransferDescriptor;
1364: pOHCIRegisters->hcCommandStatus = EndianSwap32Bit (kOHCIHcCommandStatus_BLF);
1365: }
1366: CheckpointIO(ioPrep->preparationID, nil); // zzzz - Ferg - keep from overflowing the locked page count
1367:
1368: } else {
1369: AssertDebugStr("OHCIUIM: PrepareMemoryForIO failed!");
1370: }
1371: }
1372:
1373: }
1374: else
1375: {
1376: newOHCIGeneralTransferDescriptor = OHCIUIMAllocateTD();
1377: /* last in queue is dummy descriptor. Fill it in then add new dummy */
1378: pOHCIGeneralTransferDescriptor = (OHCIGeneralTransferDescriptorPtr) pEDQueue->pVirtualTailP;
1379:
1380: pOHCIGeneralTransferDescriptor->dWord0 = EndianSwap32Bit (myBufferRounding | TDDirection);
1381: pOHCIGeneralTransferDescriptor->dWord2 = EndianSwap32Bit ((UInt32)newOHCIGeneralTransferDescriptor->pPhysical);
1382: pOHCIGeneralTransferDescriptor->pVirtualNext = (UInt32)newOHCIGeneralTransferDescriptor;
1383:
1384: /*for zero sized buffers */
1385: pOHCIGeneralTransferDescriptor->dWord1 = 0;
1386: pOHCIGeneralTransferDescriptor->dWord3 = 0;
1387: pOHCIGeneralTransferDescriptor->CallBack = handler;
1388: pOHCIGeneralTransferDescriptor->refcon = refcon;
1389:
1390: /* Make new descriptor the tail */
1391: pEDQueue->dWord1 = pOHCIGeneralTransferDescriptor->dWord2;
1392: pEDQueue->pVirtualTailP = (UInt32) newOHCIGeneralTransferDescriptor;
1393: }
1394: pOHCIRegisters->hcCommandStatus = EndianSwap32Bit (kOHCIHcCommandStatus_BLF);
1395: if ( pOHCIUIMData->OptiOn)
1396: pOHCIRegisters->hcCommandStatus = EndianSwap32Bit (kOHCIHcCommandStatus_CLF);
1397:
1398: return (status);
1399: }
1400:
1401: OSStatus OHCIUIMBulkEDDelete(
1402: short functionNumber,
1403: short endpointNumber,
1404: short direction)
1405: {
1406: OSStatus status = noErr;
1407:
1408: kprintf("OHCIUIMBulkDelete: calling OHCIUIMEndpointDelete for fn=%d,ep=%d\n",functionNumber,endpointNumber);
1409: status = OHCIUIMEndpointDelete(functionNumber, endpointNumber, direction);
1410:
1411: return (status);
1412: }
1413:
1414: Boolean BandwidthAvailable(
1415: UInt32 pollingRate,
1416: UInt32 reserveBandwidth,
1417: int *offset)
1418: {
1419: int num;
1420: OHCIRegistersPtr pOHCIRegisters;
1421:
1422: #pragma unused reserveBandwidth
1423: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
1424:
1425: num = EndianSwap32Bit(pOHCIRegisters->hcFmNumber)&kOHCIFmNumberMask;
1426: if (pollingRate < 1)
1427: //error condition
1428: return(false);
1429: else if(pollingRate < 2)
1430: *offset = 62;
1431: else if(pollingRate < 4)
1432: *offset = (num%2) + 60;
1433: else if(pollingRate < 8)
1434: *offset = (num%4) + 56;
1435: else if(pollingRate < 16)
1436: *offset = (num%8) + 48;
1437: else if(pollingRate < 32)
1438: *offset = (num%16) + 32;
1439: else
1440: *offset = (num%32) + 0;
1441: return (true);
1442: }
1443:
1444:
1445: OSStatus OHCIUIMInterruptEDCreate(
1446: short functionAddress,
1447: short endpointNumber,
1448: short speed,
1449: UInt16 maxPacketSize,
1450: short pollingRate,
1451: UInt32 reserveBandwidth)
1452: {
1453: OHCIRegistersPtr pOHCIRegisters;
1454: OHCIEndpointDescriptorPtr pOHCIEndpointDescriptor;
1455: OHCIEndpointDescriptorPtr pED;
1456: UInt32 myFunctionAddress;
1457: UInt32 myEndpointNumber;
1458: UInt32 myMaxPacketSize, myEndPointDirection;
1459: UInt32 mySpeed;
1460: OHCIGeneralTransferDescriptorPtr
1461: pOHCIGeneralTransferDescriptor;
1462: OSStatus status = noErr;
1463: OHCIIntHeadPtr pInterruptHead;
1464: int offset;
1465:
1466: if (pOHCIUIMData->rootHubFuncAddress == functionAddress)
1467: return (status);
1468:
1469: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
1470: pInterruptHead = pOHCIUIMData->pInterruptHead;
1471:
1472:
1473: ///ZZZZz opti bug fix!!!!
1474: if (pOHCIUIMData->OptiOn)
1475: if (speed == kOHCIEDSpeedFull)
1476: if (pollingRate >= 8)
1477: pollingRate = 7;
1478:
1479:
1480: // Do we have room?? if so return with offset equal to location
1481: if((Boolean) BandwidthAvailable(pollingRate, reserveBandwidth, &offset) == false)
1482: return(bandWidthFullErr);
1483:
1484: // Allocate Endpoint Descripter
1485: pOHCIEndpointDescriptor = (OHCIEndpointDescriptorPtr) OHCIUIMAllocateED();
1486:
1487: // Fill in necessary data for descriptor
1488: myFunctionAddress = ((UInt32) functionAddress) << kOHCIEDControl_FAPhase;
1489: myEndpointNumber = ((UInt32) endpointNumber) << kOHCIEndpointNumberOffset;
1490: myMaxPacketSize = (UInt32) maxPacketSize << kOHCIMaxPacketSizeOffset;
1491: mySpeed = (UInt32) speed << kOHCISpeedOffset;
1492: myEndPointDirection = ((UInt32) 2) << kOHCIEndpointDirectionOffset;
1493:
1494:
1495: pOHCIEndpointDescriptor->dWord0 = EndianSwap32Bit(myFunctionAddress | myEndpointNumber | myMaxPacketSize
1496: | mySpeed | myEndPointDirection);
1497:
1498: pOHCIGeneralTransferDescriptor = OHCIUIMAllocateTD();
1499: if (pOHCIGeneralTransferDescriptor == nil) {
1500: return (-1);
1501: }
1502:
1503:
1504: /* These were previously nil */
1505: pOHCIEndpointDescriptor->dWord1 = EndianSwap32Bit( (UInt32) pOHCIGeneralTransferDescriptor->pPhysical);
1506: pOHCIEndpointDescriptor->dWord2 = EndianSwap32Bit( (UInt32) pOHCIGeneralTransferDescriptor->pPhysical);
1507: pOHCIEndpointDescriptor->pVirtualTailP = (UInt32) pOHCIGeneralTransferDescriptor;
1508: pOHCIEndpointDescriptor->pVirtualHeadP = (UInt32) pOHCIGeneralTransferDescriptor;
1509:
1510: // Add to Queue
1511: pED = pInterruptHead[offset].pHead;
1512: pOHCIEndpointDescriptor->dWord3 = pED->dWord3;
1513: pED->dWord3 = EndianSwap32Bit ((UInt32) pOHCIEndpointDescriptor->pPhysical);
1514: pOHCIEndpointDescriptor->pVirtualNext = pED->pVirtualNext;
1515: pED->pVirtualNext = (UInt32) pOHCIEndpointDescriptor;
1516:
1517: /// will never happen???
1518: if (pInterruptHead[offset].pHead == pInterruptHead[offset].pTail)
1519: pInterruptHead[offset].pTail = pOHCIEndpointDescriptor;
1520:
1521: pInterruptHead[offset].nodeBandwidth += reserveBandwidth;
1522:
1523: return (status);
1524: }
1525:
1526:
1527: OSStatus OHCIUIMInterruptTransfer(
1528: short functionNumber,
1529: short endpointNumber,
1530: UInt32 refcon,
1531: CallBackFuncPtr handler,
1532: UInt32 CBP,
1533: Boolean bufferRounding,
1534: short bufferSize)
1535: {
1536: OHCIRegistersPtr pOHCIRegisters;
1537: OHCIGeneralTransferDescriptorPtr
1538: pOHCIGeneralTransferDescriptor,
1539: newOHCIGeneralTransferDescriptor;
1540: OSStatus status = noErr;
1541: UInt32 myBufferRounding;
1542: UInt32 myDirection;
1543: UInt32 myToggle;
1544: OHCIEndpointDescriptorPtr pEDQueue, temp;
1545: OHCIIntHeadPtr pInterruptHead;
1546: IOPreparationTable *ioPrep;
1547: IOPreparationTable IOPrep;
1548: UInt32 CBPPhysical;
1549: Boolean done = false;
1550:
1551: kprintf("OHCIUIMInterruptTransfer:functionNumber=%d,roothubfn=%d\n",functionNumber,pOHCIUIMData->rootHubFuncAddress);
1552: if (pOHCIUIMData->rootHubFuncAddress == functionNumber)
1553: {
1554: SimulateRootHubInt(endpointNumber, (void *)CBP, bufferSize, handler, refcon);
1555: return(noErr);
1556: }
1557:
1558: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
1559: pInterruptHead = pOHCIUIMData->pInterruptHead;
1560:
1561: pEDQueue = FindInterruptEndpoint(functionNumber, endpointNumber, &temp);
1562: if ( pEDQueue != nil)
1563: {
1564: newOHCIGeneralTransferDescriptor = OHCIUIMAllocateTD();
1565: if (newOHCIGeneralTransferDescriptor == nil) {
1566: return (-1);
1567: }
1568:
1569: myBufferRounding = (UInt32) bufferRounding << kOHCIBufferRoundingOffset;
1570: myToggle = 0; /* Take data toggle from Endpoint Descriptor */
1571:
1572:
1573: /* Last in queue is a dummy descriptor. Fill it in then add new dummy */
1574: pOHCIGeneralTransferDescriptor = (OHCIGeneralTransferDescriptorPtr) pEDQueue->pVirtualTailP;
1575:
1576: myDirection = kOHCIBit20; // Barry - This was undefined, make it IN. Should be in endpoint anyway
1577:
1578: pOHCIGeneralTransferDescriptor->dWord0 = EndianSwap32Bit (myBufferRounding | myDirection | myToggle);
1579: pOHCIGeneralTransferDescriptor->dWord2 = EndianSwap32Bit ((UInt32)newOHCIGeneralTransferDescriptor->pPhysical);
1580: pOHCIGeneralTransferDescriptor->pVirtualNext = (UInt32)newOHCIGeneralTransferDescriptor;
1581:
1582: if (bufferSize != 0)
1583: {
1584: CBPPhysical = kvtophys((vm_offset_t) CBP);
1585: pOHCIGeneralTransferDescriptor->dWord1 = EndianSwap32Bit (CBPPhysical);
1586: pOHCIGeneralTransferDescriptor->dWord3 = EndianSwap32Bit (CBPPhysical + bufferSize-1);
1587:
1588: } else {
1589: pOHCIGeneralTransferDescriptor->dWord1 = 0;
1590: pOHCIGeneralTransferDescriptor->dWord3 = 0;
1591: }
1592: pOHCIGeneralTransferDescriptor->CallBack = handler;
1593: pOHCIGeneralTransferDescriptor->refcon = refcon;
1594:
1595: /* Make new descriptor the tail */
1596: pEDQueue->dWord1 = pOHCIGeneralTransferDescriptor->dWord2;
1597: pEDQueue->pVirtualTailP = (UInt32) newOHCIGeneralTransferDescriptor;
1598: } else {
1599: FailureDebugStr("UIMInterruptTransfer: Couldnot find endpoint");
1600: status = kUSBNotFound;
1601: }
1602: kprintf("OHCIUIMInterruptTransfer: returning status=%d\n",status);
1603: return ( status);
1604: }
1605:
1606:
1607: OSStatus OHCIUIMEndpointDelete(
1608: short functionNumber,
1609: short endpointNumber,
1610: short direction)
1611: {
1612: OHCIRegistersPtr pOHCIRegisters;
1613: OSStatus status = noErr;
1614: OHCIEndpointDescriptorPtr pED;
1615: OHCIEndpointDescriptorPtr pEDQueueBack;
1616: UInt32 hcControl;
1617: UInt32 something, controlMask;
1618: // UInt32 edDirection;
1619:
1620:
1621: if (pOHCIUIMData->rootHubFuncAddress == functionNumber)
1622: return (status);
1623:
1624: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
1625:
1626: //search for endpoint descriptor
1627: if (direction == kUSBOut)
1628: direction = kOHCIEDDirectionOut;
1629: else if (direction == kUSBIn)
1630: direction = kOHCIEDDirectionIn;
1631: else
1632: direction = kOHCIEDDirectionTD;
1633:
1634: kprintf("OHCIUIMEndpointDelete: calling FindEndpoint\n");
1635: if((pED = FindEndpoint (functionNumber, endpointNumber, direction, &pEDQueueBack, &controlMask)) == nil)
1636: {
1637: FailureDebugStr("UIMEndpointDelete: Couldnot find endpoint\n");
1638: return (kUSBNotFound);
1639: }
1640:
1641: // Remove Endpoint
1642: //mark sKipped
1643: pED->dWord0 |= EndianSwap32Bit (kOHCIEDControl_K);
1644: // edDirection = EndianSwap32Bit(pED->dWord0) & kOHCIEndpointDirectionMask;
1645: // remove pointer wraps
1646: pEDQueueBack->dWord3 = pED->dWord3;
1647: pEDQueueBack->pVirtualNext = pED->pVirtualNext;
1648:
1649:
1650: // clear some bit in hcControl
1651: hcControl = EndianSwap32Bit (pOHCIRegisters->hcControl);
1652: hcControl &= ~controlMask;
1653: hcControl &= OHCIBitRange(0, 10);
1654:
1655: pOHCIRegisters->hcControl = EndianSwap32Bit (hcControl);
1656:
1657: // poll for interrupt zzzzz turn into real interrupt
1658: pOHCIRegisters->hcInterruptStatus = EndianSwap32Bit(kOHCIBit2);
1659: DelayForHardware(DurationToAbsolute(1*durationMillisecond));
1660: something = EndianSwap32Bit(pOHCIRegisters->hcInterruptStatus) & kOHCIInterruptSOFMask;
1661: #if 1
1662: if(!something)
1663: { /* This should have been set, just in case wait another ms */
1664: DelayForHardware(DurationToAbsolute(1*durationMillisecond));
1665: }
1666: #else
1667: /* BT - 13Jun98, this was hanging, the grey screen with andromeda hub */
1668: while (!something) {
1669: DelayForHardware(DurationToAbsolute(1*durationMillisecond));
1670: something = EndianSwap32Bit(pOHCIRegisters->hcInterruptStatus) & kOHCIHcInterrupt_SF;
1671: }
1672: #endif
1673: //restart hcControl
1674: hcControl |= controlMask;
1675: pOHCIRegisters->hcControl = EndianSwap32Bit (hcControl);
1676:
1677: RemoveAllTDs(pED);
1678:
1679: pED->dWord3 = nil;
1680:
1681: //deallocate ED
1682: OHCIUIMDeallocateED(pED);
1683: return (status);
1684: }
1685:
1686:
1687: OSStatus OHCIUIMAbortEndpoint(
1688: short functionNumber,
1689: short endpointNumber,
1690: short direction)
1691: {
1692: OHCIRegistersPtr pOHCIRegisters;
1693: OSStatus status = noErr;
1694: OHCIEndpointDescriptorPtr pED;
1695: OHCIEndpointDescriptorPtr pEDQueueBack;
1696: UInt32 hcControl;
1697: UInt32 something, controlMask;
1698:
1699: if (pOHCIUIMData->rootHubFuncAddress == functionNumber)
1700: return (status);
1701:
1702: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
1703:
1704: if (direction == kUSBOut)
1705: direction = kOHCIEDDirectionOut;
1706: else if (direction == kUSBIn)
1707: direction = kOHCIEDDirectionIn;
1708: else
1709: direction = kOHCIEDDirectionTD;
1710:
1711: //search for endpoint descriptor
1712: kprintf("OHCIUIMAbort EP:calling FindEndpoint\n");
1713: if((pED = FindEndpoint (functionNumber, endpointNumber, direction, &pEDQueueBack, &controlMask)) == nil)
1714: return(kUSBNotFound);
1715:
1716:
1717: pED->dWord0 |= EndianSwap32Bit (kOHCIEDControl_K);
1718: hcControl = EndianSwap32Bit (pOHCIRegisters->hcControl);
1719: hcControl &= ~controlMask;
1720: hcControl &= OHCIBitRange(0, 10);
1721:
1722: pOHCIRegisters->hcControl = EndianSwap32Bit (hcControl);
1723:
1724: // poll for interrupt zzzzz turn into real interrupt
1725: pOHCIRegisters->hcInterruptStatus = EndianSwap32Bit(kOHCIBit2);
1726: DelayForHardware(DurationToAbsolute(1*durationMillisecond));
1727: something = EndianSwap32Bit(pOHCIRegisters->hcInterruptStatus) & kOHCIInterruptSOFMask;
1728: #if 1
1729: if(!something)
1730: { /* This should have been set, just in case wait another ms */
1731: DelayForHardware(DurationToAbsolute(1*durationMillisecond));
1732: }
1733: #else
1734: /* BT - 13Jun98, this was hanging, the grey screen with andromeda hub */
1735: while (!something) {
1736: DelayForHardware(DurationToAbsolute(1*durationMillisecond));
1737: something = EndianSwap32Bit(pOHCIRegisters->hcInterruptStatus) & kOHCIHcInterrupt_SF;
1738: }
1739: #endif
1740: //restart hcBulk
1741: hcControl |= controlMask;
1742: pOHCIRegisters->hcControl = EndianSwap32Bit (hcControl);
1743:
1744: RemoveTDs(pED);
1745:
1746: pED->dWord0 &= ~EndianSwap32Bit (kOHCIEDControl_K);
1747:
1748: return (0);
1749:
1750: }
1751:
1752: UInt64 OHCIUIMGetCurrentFrameNumber(void)
1753: {
1754:
1755: UInt64 time;
1756: OHCIRegistersPtr pOHCIRegisters;
1757:
1758: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
1759: time = usb_U64Add (pOHCIUIMData->frameNumber, U64SetU(EndianSwap32Bit(pOHCIRegisters->hcFmNumber)&kOHCIFmNumberMask));
1760: return (time);
1761:
1762: }
1763:
1764:
1765:
1766: ////////////////////////////////////////////////////////////////////////////////
1767: ////////////////////////////////////////////////////////////////////////////////
1768: //
1769: // Internal routines.
1770: //
1771: ////////////////////////////////////////////////////////////////////////////////
1772: ////////////////////////////////////////////////////////////////////////////////
1773:
1774:
1775:
1776: ////////////////////////////////////////////////////////////////////////////////
1777: //
1778: // OHCIUIMGetRegisterBaseAddress
1779: //
1780: // This proc uses the name registry to find the base address of the registers.
1781: //
1782:
1783: #if 0 //naga
1784: static OSStatus OHCIUIMGetRegisterBaseAddress(
1785: RegEntryIDPtr pOHCIRegEntryID,
1786: OHCIRegistersPtr *ppOHCIRegisters)
1787: {
1788: PCIAssignedAddressPtr pPCIAssignedAddresses = nil;
1789: DeviceLogicalAddressPtr pDeviceLogicalAddresses = nil;
1790: RegPropertyValueSize propSize;
1791: UInt32 addressSpaceFlags;
1792: UInt32 registerNumber;
1793: OHCIRegistersPtr pOHCIRegisters;
1794: UInt32 numAddresses,
1795: addressNum;
1796: Boolean done;
1797: OSStatus status = noErr;
1798:
1799: // Get assigned addresses property.
1800: status = RegistryPropertyGetSize
1801: (pOHCIRegEntryID,
1802: (RegPropertyNamePtr) kPCIAssignedAddressProperty,
1803: &propSize);
1804:
1805: if (status == noErr)
1806: {
1807: if (CurrentExecutionLevel() != kTaskLevel){
1808: MemoryDebugStr("OHCIUIM: Allocating memory (3) at non-task time, report stack trace please; sc");
1809: }
1810: // zzzz do we deallocate this?
1811: pPCIAssignedAddresses =
1812: (PCIAssignedAddressPtr) PoolAllocateResident (propSize, false);
1813: if (pPCIAssignedAddresses == nil)
1814: status = memFullErr;
1815: }
1816:
1817: if (status == noErr)
1818: {
1819: status = RegistryPropertyGet
1820: (pOHCIRegEntryID,
1821: (RegPropertyNamePtr) kPCIAssignedAddressProperty,
1822: pPCIAssignedAddresses,
1823: &propSize);
1824: if (status == noErr)
1825: numAddresses = propSize / sizeof (PCIAssignedAddress);
1826: }
1827:
1828: // Get logical addresses property.
1829: if (status == noErr)
1830: {
1831: status = RegistryPropertyGetSize
1832: (pOHCIRegEntryID,
1833: (RegPropertyNamePtr) kAAPLDeviceLogicalAddress,
1834: &propSize);
1835: }
1836:
1837: if (status == noErr)
1838: {
1839: // zzzzz do we dealocate this?
1840: pDeviceLogicalAddresses =
1841: (DeviceLogicalAddressPtr) PoolAllocateResident (propSize, false);
1842: if (pDeviceLogicalAddresses == nil)
1843: status = memFullErr;
1844: }
1845:
1846: if (status == noErr)
1847: {
1848: status = RegistryPropertyGet
1849: (pOHCIRegEntryID,
1850: (RegPropertyNamePtr) kAAPLDeviceLogicalAddress,
1851: pDeviceLogicalAddresses,
1852: &propSize);
1853: }
1854:
1855: // Get main memory mapped register file base address.
1856: if (status == noErr)
1857: {
1858: done = false;
1859: for (addressNum = 0; ((addressNum < numAddresses) && (!done)); addressNum++)
1860: {
1861: addressSpaceFlags = pPCIAssignedAddresses[addressNum].addressSpaceFlags;
1862: registerNumber = pPCIAssignedAddresses[addressNum].registerNumber;
1863: if ((registerNumber == kOHCIConfigRegBaseAddressRegisterNumber) &&
1864: (addressSpaceFlags & kPCI32BitMemorySpace))
1865: {
1866: pOHCIRegisters = pDeviceLogicalAddresses[addressNum];
1867: done = true;
1868: }
1869: }
1870:
1871: if (!done)
1872: //zzzz
1873: status = -4161;
1874: // status = notFoundErr;
1875: }
1876:
1877: // Clean up.
1878: if (pDeviceLogicalAddresses != nil)
1879: PoolDeallocate ((Ptr) pDeviceLogicalAddresses);
1880: if (pPCIAssignedAddresses != nil)
1881: PoolDeallocate ((Ptr) pPCIAssignedAddresses);
1882:
1883: // Return results.
1884: if (status == noErr)
1885: *ppOHCIRegisters = pOHCIRegisters;
1886: else
1887: *ppOHCIRegisters = nil;
1888:
1889: return (status);
1890: }
1891:
1892:
1893: OSStatus OHCIUIMInstallInterruptHandler ()
1894:
1895: {
1896: RegEntryIDPtr pOHCIRegEntryID = &(pOHCIUIMData->ohciRegEntryID);
1897: ISTProperty interruptSets;
1898: InterruptSetID interruptSetID;
1899: InterruptMemberNumber interruptMemberNumber;
1900: void *oldInterruptRefCon;
1901: InterruptHandler oldInterruptHandler;
1902: InterruptEnabler oldInterruptEnabler;
1903: InterruptDisabler oldInterruptDisabler;
1904: RegPropertyValueSize propSize;
1905: OSStatus status = noErr;
1906:
1907:
1908: // Get our interrupt set from the name registry.
1909: propSize = sizeof (ISTProperty);
1910: status = RegistryPropertyGet (pOHCIRegEntryID, kISTPropertyName,
1911: &interruptSets, &propSize);
1912: interruptSetID = interruptSets[kISTChipInterruptSource].setID;
1913: interruptMemberNumber = interruptSets[kISTChipInterruptSource].member;
1914:
1915: // Get the interrupt enabler and disabler for our chip interrupt set.
1916: if (status == noErr)
1917: {
1918: status = GetInterruptFunctions
1919: (interruptSetID, interruptMemberNumber,
1920: &oldInterruptRefCon, &oldInterruptHandler,
1921: &oldInterruptEnabler, &oldInterruptDisabler);
1922: }
1923:
1924: // Install the refCon and interrupt handler for our chip interrupt set.
1925: if (status == noErr)
1926: {
1927: status = InstallInterruptFunctions
1928: (interruptSetID, interruptMemberNumber,
1929: pOHCIUIMData, (InterruptHandler) OHCIUIMInterruptHandler,
1930: nil, nil);
1931: }
1932:
1933: // Add info to our UIM Data record.
1934: if (status == noErr)
1935: {
1936: pOHCIUIMData->interruptSetMember.setID = interruptSetID;
1937: pOHCIUIMData->interruptSetMember.member = interruptMemberNumber;
1938: pOHCIUIMData->oldInterruptRefCon = oldInterruptRefCon;
1939: pOHCIUIMData->oldInterruptHandler = oldInterruptHandler;
1940: pOHCIUIMData->interruptEnabler = oldInterruptEnabler;
1941: pOHCIUIMData->interruptDisabler = oldInterruptDisabler;
1942: }
1943:
1944: return (status);
1945: }
1946: #endif 0
1947:
1948: OSStatus OHCIUIMInterruptHandler (InterruptSetMember member, void *refCon, UInt32 interruptCount)
1949: {
1950: register OHCIRegistersPtr pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
1951: register UInt32 activeInterrupts, interruptEnable;
1952: UInt32 PhysAddr;
1953: OHCIGeneralTransferDescriptorPtr pHCDoneTD;
1954:
1955: #pragma unused member
1956: #pragma unused refCon
1957: #pragma unused interruptCount
1958:
1959: usb_task_level = kSecondaryInterruptLevel;
1960: interruptEnable = EndianSwap32Bit(pOHCIRegisters->hcInterruptEnable);
1961:
1962: activeInterrupts = interruptEnable & EndianSwap32Bit(pOHCIRegisters->hcInterruptStatus);
1963:
1964: if ((interruptEnable & kOHCIHcInterrupt_MIE) && (activeInterrupts != 0)){
1965:
1966: if (activeInterrupts & kOHCIHcInterrupt_SO){ // SchedulingOverrun Interrupt
1967: pOHCIUIMData->errors.scheduleOverrun++;
1968: pOHCIRegisters->hcInterruptStatus = EndianSwap32Bit(kOHCIHcInterrupt_SO);
1969: }
1970: if (activeInterrupts & kOHCIHcInterrupt_WDH){ // WritebackDoneHead Interrupt
1971: PhysAddr = (UInt32) EndianSwap32Bit(*(UInt32 *)(pOHCIUIMData->pHCCA + 0x84));
1972: PhysAddr &= kOHCIHeadPMask; // mask off interrupt bits
1973: pHCDoneTD = (OHCIGeneralTransferDescriptorPtr) OHCIUIMGetLogicalAddress (PhysAddr);
1974: // write to 0 to the HCCA DoneHead ptr so we won't look at it anymore.
1975: *(UInt32 *)(pOHCIUIMData->pHCCA + 0x84) = 0L;
1976: QueueSecondaryInterruptHandler((SecondaryInterruptHandler2)DoDoneQueueProcessing,
1977: nil, (void *)pHCDoneTD, (void *)false);
1978: pOHCIRegisters->hcInterruptStatus = EndianSwap32Bit(kOHCIHcInterrupt_WDH);
1979: }
1980: if (activeInterrupts & kOHCIHcInterrupt_SF){ // StartofFrame Interrupt
1981: // does USL have SF notification set?
1982: // if so, tell them now's the time!
1983:
1984: // Clear the interrrupt
1985: pOHCIRegisters->hcInterruptStatus = EndianSwap32Bit(kOHCIHcInterrupt_SF);
1986:
1987: // and mask it off so it doesn't happen again.
1988: // will have to be turned on manually to happen again.
1989: pOHCIRegisters->hcInterruptDisable = EndianSwap32Bit(kOHCIHcInterrupt_SF);
1990: SysDebugStr("Frame Interrupt");
1991: QueueSecondaryInterruptHandler(RootHubFrame, nil, nil, nil);
1992:
1993: }
1994: if (activeInterrupts & kOHCIHcInterrupt_RD){ // ResumeDetected Interrupt
1995: // does USL have SF notification set?
1996: // if so, tell them now's the time to resume!
1997: pOHCIRegisters->hcInterruptStatus = EndianSwap32Bit(kOHCIHcInterrupt_RD);
1998: }
1999: if (activeInterrupts & kOHCIHcInterrupt_UE){ // Unrecoverable Error Interrupt
2000: pOHCIUIMData->errors.unrecoverableError++;
2001: // Let's do a SW reset to recover from this condition. We could make sure all
2002: // OCHI registers and in-memory data structures are valid, too.
2003: pOHCIRegisters->hcCommandStatus = EndianSwap32Bit(kOHCIHcCommandStatus_HCR);
2004: DelayForHardware(DurationToAbsolute(10*durationMicrosecond));
2005: pOHCIRegisters->hcInterruptStatus = EndianSwap32Bit(kOHCIHcInterrupt_UE);
2006: // zzzz - note I'm leaving the Control/Bulk list processing off for now.
2007: pOHCIRegisters->hcControl = EndianSwapImm32Bit((kOHCIFunctionalState_Operational << kOHCIHcControl_HCFSPhase) | kOHCIHcControl_PLE);
2008: }
2009: if (activeInterrupts & kOHCIHcInterrupt_FNO){ // FrameNumberOverflow Interrupt
2010: // not really an error, but close enough
2011: pOHCIUIMData->errors.frameNumberOverflow++;
2012: if ((EndianSwap32Bit(pOHCIRegisters->hcFmNumber)&kOHCIFmNumberMask) < kOHCIBit15)
2013: pOHCIUIMData->frameNumber = usb_U64Add (pOHCIUIMData->frameNumber, U64SetU(kOHCIFrameOverflowBit));
2014:
2015: pOHCIRegisters->hcInterruptStatus = EndianSwap32Bit(kOHCIHcInterrupt_FNO);
2016: }
2017: if (activeInterrupts & kOHCIHcInterrupt_RHSC){ // RootHubStatusChange Interrupt
2018:
2019: // Clear status change.
2020: pOHCIRegisters->hcInterruptStatus = EndianSwap32Bit(kOHCIHcInterrupt_RHSC);
2021: SysDebugStr("RHSC Interrupt");
2022: // QueueSecondaryInterruptHandler(RootHubStatusChange, nil, nil, nil);
2023: }
2024: if (activeInterrupts & kOHCIHcInterrupt_OC){ // OwnershipChange Interrupt
2025: // well, we certainly weren't expecting this!
2026: pOHCIUIMData->errors.ownershipChange++;
2027: // Let the USL know about the status change?
2028: pOHCIRegisters->hcInterruptStatus = EndianSwap32Bit(kOHCIHcInterrupt_OC);
2029: }
2030:
2031: } else {
2032: usb_task_level = kKernelLevel;
2033: return(kIsrIsNotComplete); // wasn't our interrupt
2034: }
2035: usb_task_level = kKernelLevel;
2036: return(kIsrIsComplete);
2037: }
2038:
2039:
2040: OSStatus OHCIProcessDoneQueue (void)
2041: {
2042: OHCIRegistersPtr pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
2043: OSStatus status = noErr;
2044: UInt32 interruptStatus;
2045: UInt32 PhysAddr;
2046: OHCIGeneralTransferDescriptorPtr pHCDoneTD;
2047:
2048: // DebugStr ((ConstStr255Param) "OHCIProcessDoneQueue");
2049:
2050: // check if the OHCI has written the DoneHead yet
2051: interruptStatus = EndianSwap32Bit(pOHCIRegisters->hcInterruptStatus);
2052: if( (interruptStatus & kOHCIHcInterrupt_WDH) == 0)
2053: {
2054: return(noErr);
2055: }
2056:
2057: // get the pointer to the list (logical address)
2058: PhysAddr = (UInt32) EndianSwap32Bit(*(UInt32 *)(pOHCIUIMData->pHCCA + 0x84));
2059: PhysAddr &= kOHCIHeadPMask; // mask off interrupt bits
2060: pHCDoneTD = (OHCIGeneralTransferDescriptorPtr) OHCIUIMGetLogicalAddress (PhysAddr);
2061: // write to 0 to the HCCA DoneHead ptr so we won't look at it anymore.
2062: *(UInt32 *)(pOHCIUIMData->pHCCA + 0x84) = 0L;
2063:
2064: // Since we have a copy of the queue to process, we can let the host update it again.
2065: pOHCIRegisters->hcInterruptStatus = EndianSwap32Bit(kOHCIHcInterrupt_WDH);
2066:
2067: DoDoneQueueProcessing(pHCDoneTD, true);
2068: return(true);
2069: }
2070:
2071:
2072: OSStatus OHCIUIMIsochEDCreate(
2073: short functionAddress,
2074: short endpointNumber,
2075: UInt32 maxPacketSize,
2076: UInt8 direction)
2077:
2078: {
2079: OHCIEndpointDescriptorPtr pOHCIEndpointDescriptor, pED;
2080: OSStatus status = noErr;
2081: if (direction == kUSBOut)
2082: direction = kOHCIEDDirectionOut;
2083: else if (direction == kUSBIn)
2084: direction = kOHCIEDDirectionIn;
2085: else
2086: direction = kOHCIEDDirectionTD;
2087:
2088: pED = (OHCIEndpointDescriptorPtr) pOHCIUIMData->pIsochHead;
2089: pOHCIEndpointDescriptor = AddEmptyEndPoint (
2090: functionAddress, endpointNumber, maxPacketSize, kOHCIEDSpeedFull, direction, pED, kOHCIEDFormatIsochronousTD);
2091: if (pOHCIEndpointDescriptor == nil)
2092: return(-1);
2093: return (status);
2094: }
2095:
2096: OSStatus OHCIUIMIsochTransfer(
2097: short functionAddress,
2098: short endpointNumber,
2099: UInt32 refcon,
2100: UInt8 direction,
2101: IsocCallBackFuncPtr pIsochHandler,
2102: UInt64 frameNumberStart,
2103: UInt32 pBufferStart,
2104: UInt32 frameCount,
2105: USBIsocFrame *pFrames)
2106: {
2107:
2108: OHCIIsochTransferDescriptorPtr pITD;
2109: int i;
2110: UInt32 currentFrame;
2111: UInt32 numOfPages;
2112: UInt32 bufferSize;
2113: OHCIEndpointDescriptorPtr pED, temp;
2114: UInt32 pageSize, pageMask;
2115: OSStatus status = noErr;
2116: IOPreparationTable *ioPrep;
2117: IOPreparationTable IOPrep;
2118: UInt32 physicalAddresses[kOHCIMaxPages];
2119: UInt32 frameTD, pagesUsed;
2120: UInt32 alreadyCrossed = kOHCIITDConditionNotCrossPage;
2121: UInt16 frameNumber;
2122: UInt32 firstCount, lastCount, pageOffsetMask;
2123: // DebugStr("ISOC check write to 0");
2124:
2125:
2126: if (direction == kUSBOut)
2127: direction = kOHCIEDDirectionOut;
2128: else if (direction == kUSBIn)
2129: direction = kOHCIEDDirectionIn;
2130: else
2131: direction = kOHCIEDDirectionTD;
2132:
2133: pED = FindIsochronousEndpoint(functionAddress, endpointNumber, direction, &temp);
2134:
2135: if (!pED){
2136: FailureDebugStr("UIMIsochTransfer: Couldnot find endpoint");
2137: status = kUSBNotFound;
2138: return (status);
2139: }
2140: frameNumber = (UInt16) U32SetU (frameNumberStart);
2141: ioPrep = &IOPrep;
2142: pageSize = pOHCIUIMData->pageSize;
2143: pageMask = ~(pageSize - 1);
2144: frameTD = 0;
2145: pageOffsetMask = pageSize - 1;
2146: // Get the total size of buffer
2147: bufferSize = 0;
2148: for ( i = 0; i< frameCount; i++)
2149: bufferSize += pFrames[i].frReqCount;
2150:
2151: currentFrame = 0;
2152: while (currentFrame < frameCount -1) {
2153:
2154: firstCount = pageSize - (pBufferStart & pageOffsetMask);
2155: if (bufferSize <= firstCount){
2156: lastCount = 0;
2157: numOfPages = 1;
2158: } else {
2159: lastCount = (pBufferStart + bufferSize) & pageOffsetMask;
2160: numOfPages = (bufferSize - firstCount - lastCount)/pageSize;
2161: if (firstCount) numOfPages++;
2162: if (lastCount) numOfPages++;
2163: }
2164: // Prepare for IO and get physical address
2165: ioPrep->options = kIOLogicalRanges | kIOIsInput | kIOIsOutput;
2166: ioPrep->addressSpace = kCurrentAddressSpaceID; // default
2167: ioPrep->granularity = 0; // do it all now
2168: ioPrep->firstPrepared = 0;
2169: ioPrep->mappingEntryCount = MIN (numOfPages, kOHCIMaxPages); // # of pages we will use
2170: ioPrep->logicalMapping = 0;
2171: ioPrep->physicalMapping = (PhysicalMappingTablePtr) physicalAddresses; // return list of phys addrs
2172: ioPrep->rangeInfo.range.base = (void *) pBufferStart;
2173: ioPrep->rangeInfo.range.length = MIN (numOfPages, kOHCIMaxPages) * pageSize;
2174:
2175: status = PrepareMemoryForIO (ioPrep);
2176: pITD = (OHCIIsochTransferDescriptorPtr) pED->pVirtualTailP;
2177: pagesUsed = 0;
2178: while (((pagesUsed < kOHCIMaxPages -1) || (pagesUsed == numOfPages-1)) && (currentFrame < frameCount-1))
2179: {
2180: if (frameTD == 8){
2181: // make current ITD = 7 frames
2182: pITD->dWord0 |= (frameTD-1) << kOHCIITDControl_FCPhase;
2183:
2184: pITD->dWord3 = physicalAddresses[pagesUsed] + ((pBufferStart-1) & ~pageMask);
2185: // queue another pITD
2186: pITD = QueueITD(pITD, pED);
2187: frameTD = 0;
2188: alreadyCrossed = kOHCIITDConditionNotCrossPage;
2189: }
2190: // check if buffer crosses page
2191: if ((pBufferStart & pageMask) != ((pBufferStart + pFrames[currentFrame].frReqCount) & pageMask)) {
2192: if (alreadyCrossed == kOHCIITDConditionCrossPage) {
2193: // fill in value for number of frames
2194: pITD->dWord0 |= (frameTD-1) << kOHCIITDControl_FCPhase;
2195:
2196: pITD->dWord3 = physicalAddresses[pagesUsed] + ((pBufferStart-1) & ~pageMask);
2197: // queue another ITD
2198: pITD = QueueITD(pITD, pED);
2199: frameTD = 0;
2200: }
2201: pagesUsed++;
2202: alreadyCrossed = kOHCIITDConditionCrossPage;
2203: }
2204: if (frameTD == 0) {
2205: pITD->offset[frameTD] = (pBufferStart & ~pageMask) |
2206: kOHCIITDConditionNotAccessed << kOHCIITDOffset_CCPhase |
2207: alreadyCrossed << kOHCIITDOffset_PCPhase;
2208: if (alreadyCrossed == kOHCIITDConditionCrossPage)
2209: pITD->dWord1 = physicalAddresses[pagesUsed-1] & pageMask;
2210: else
2211: pITD->dWord1 = physicalAddresses[pagesUsed] & pageMask;
2212: pITD->dWord0 |= frameNumber;
2213: pITD->pIsocFrame = (UInt32) pFrames;
2214: pITD->frameNum = currentFrame;
2215: frameTD++;
2216: }
2217: // fill in normally, if alreadycrossed = true, make the 12th bit a 1
2218: pITD->offset[frameTD] = kOHCIITDConditionNotAccessed << kOHCIITDOffset_CCPhase |
2219: alreadyCrossed << kOHCIITDOffset_PCPhase |
2220: ((pBufferStart+pFrames[currentFrame].frReqCount) & ~pageMask)
2221: + (physicalAddresses[pagesUsed] & ~pageMask);
2222: frameTD++;
2223: frameNumber++;
2224: bufferSize -= pFrames[currentFrame].frReqCount;
2225: pBufferStart += pFrames[currentFrame].frReqCount;
2226: currentFrame++;
2227: }
2228:
2229: CheckpointIO(ioPrep->preparationID, nil);
2230: }
2231:
2232: pITD->dWord0 |= (frameTD-1) << kOHCIITDControl_FCPhase;
2233: // barry stuff
2234: // pITD->dWord3 = physicalAddresses[pagesUsed] + 2*pFrames[currentFrame].frReqCount - 1;
2235: pBufferStart += pFrames[currentFrame].frReqCount;
2236: pITD->dWord3 = physicalAddresses[pagesUsed] + ((pBufferStart-1) & ~pageMask);
2237: pITD->refcon = refcon;
2238: pITD->handler = pIsochHandler;
2239: QueueITD(pITD, pED);
2240: // DebugStr("ISOC check write to 0");
2241: return(0);
2242:
2243: }
2244:
2245: OHCIIsochTransferDescriptorPtr QueueITD (
2246: OHCIIsochTransferDescriptorPtr pITD,
2247: OHCIEndpointDescriptorPtr pED)
2248: {
2249: OHCIIsochTransferDescriptorPtr pITDTemp;
2250:
2251: pITDTemp = OHCIUIMAllocateITD();
2252: pITD->dWord2 = pITDTemp->pPhysical; // assign pitdnext to pitdtemp
2253: pED->pVirtualTailP = pITD->pVirtualNext = (UInt32) pITDTemp;
2254: SwapIsoc(pITD);
2255: pED->dWord1 = pITD->dWord2; // assign tail pointer to pitd next
2256: return (pITDTemp);
2257: }
2258:
2259:
2260: void SwapIsoc(OHCIIsochTransferDescriptorPtr pITD)
2261: {
2262: pITD->dWord0= EndianSwap32Bit(pITD->dWord0);
2263: pITD->dWord1= EndianSwap32Bit(pITD->dWord1);
2264: pITD->dWord2= EndianSwap32Bit(pITD->dWord2);
2265: pITD->dWord3= EndianSwap32Bit(pITD->dWord3);
2266:
2267: /* barry stuff BT 16bit words in right order, but each is swapped */
2268: pITD->offset[0] = EndianSwap16Bit(pITD->offset[0]);
2269: pITD->offset[1] = EndianSwap16Bit(pITD->offset[1]);
2270: pITD->offset[2] = EndianSwap16Bit(pITD->offset[2]);
2271: pITD->offset[3] = EndianSwap16Bit(pITD->offset[3]);
2272: pITD->offset[4] = EndianSwap16Bit(pITD->offset[4]);
2273: pITD->offset[5] = EndianSwap16Bit(pITD->offset[5]);
2274: pITD->offset[6] = EndianSwap16Bit(pITD->offset[6]);
2275: pITD->offset[7] = EndianSwap16Bit(pITD->offset[7]);
2276: }
2277:
2278: void trivialSwap( UInt32 *thing) {
2279:
2280: *thing = EndianSwap32Bit (*thing);
2281: }
2282:
2283:
2284:
2285:
2286: OSStatus
2287: DoDoneQueueProcessing(OHCIGeneralTransferDescriptorPtr pHCDoneTD, Boolean immediateFlag)
2288: {
2289: UInt32 control, transferStatus;
2290: long bufferSizeRemaining;
2291: OHCIGeneralTransferDescriptorPtr
2292: prevTD, nextTD;
2293: UInt32 PhysAddr;
2294: UInt32 pageSize;
2295: UInt32 pageMask;
2296: OHCIEndpointDescriptorPtr tempED;
2297: OHCIRegistersPtr pOHCIRegisters;
2298: OHCIIsochTransferDescriptorPtr pITD;
2299:
2300: #pragma unused immediateFlag
2301: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
2302:
2303: if(pHCDoneTD == nil)
2304: { /* This should not happen */
2305: return(noErr);
2306: }
2307: // DebugStr ((ConstStr255Param) "DoDoneQueueProcessing");
2308:
2309: pageSize = pOHCIUIMData->pageSize;
2310: pageMask = ~(pageSize - 1);
2311:
2312: /* Reverse the done queue use only the virtual Address fields */
2313: prevTD = 0;
2314: while(pHCDoneTD != nil)
2315: {
2316: PhysAddr = (UInt32) EndianSwap32Bit(pHCDoneTD->dWord2) & kOHCIHeadPMask;
2317: nextTD = (OHCIGeneralTransferDescriptorPtr) OHCIUIMGetLogicalAddress (PhysAddr);
2318: pHCDoneTD->pVirtualNext = (UInt32)prevTD;
2319: prevTD = pHCDoneTD;
2320: pHCDoneTD = nextTD;
2321: }
2322: // DebugStr ((ConstStr255Param) "DoDoneQueueProcessing queue reversed");
2323:
2324: pHCDoneTD = prevTD; /* New qHead */
2325:
2326: while (pHCDoneTD != nil)
2327: {
2328: // find the next one
2329: nextTD = (void *)pHCDoneTD->pVirtualNext;
2330:
2331: control = EndianSwap32Bit(pHCDoneTD->dWord0);
2332: transferStatus = (control & kOHCIGTDControl_CC) >> kOHCIGTDControl_CCPhase;
2333: if (pOHCIUIMData->OptiOn && (pHCDoneTD->pType == kOHCIOptiLSBug)) {
2334: // clear any bad errors
2335: tempED = (OHCIEndpointDescriptorPtr) pHCDoneTD->pEndpoint;
2336: pHCDoneTD->dWord0 = pHCDoneTD->dWord0 & EndianSwap32Bit (kOHCIGTDClearErrorMask);
2337: tempED->dWord2 &= EndianSwap32Bit (kOHCIHeadPMask);
2338: pHCDoneTD->dWord2 = tempED->dWord1 & EndianSwap32Bit (kOHCIHeadPMask);
2339: tempED->dWord1 = EndianSwap32Bit (pHCDoneTD->pPhysical);
2340: pOHCIRegisters->hcCommandStatus = EndianSwap32Bit (kOHCIHcCommandStatus_CLF);
2341:
2342: // For CMD Buffer Underrun Errata
2343: } else if ((transferStatus == kOHCIGTDConditionBufferUnderrun) &&
2344: (pHCDoneTD->pType == kOHCIBulkTransferOutType) &&
2345: (pOHCIUIMData->errataBits & kErrataRetryBufferUnderruns)) {
2346:
2347:
2348: tempED = (OHCIEndpointDescriptorPtr) pHCDoneTD->pEndpoint;
2349: pHCDoneTD->dWord0 = pHCDoneTD->dWord0 & EndianSwap32Bit (kOHCIGTDClearErrorMask);
2350: pHCDoneTD->dWord2 = tempED->dWord2 & EndianSwap32Bit (kOHCIHeadPMask);
2351: pHCDoneTD->pVirtualNext = OHCIUIMGetLogicalAddress (EndianSwap32Bit (tempED->dWord3) & kOHCIHeadPMask);
2352:
2353: tempED->dWord2 = EndianSwap32Bit (pHCDoneTD->pPhysical) |
2354: (tempED->dWord2 & EndianSwap32Bit( kOHCIEDToggleBitMask));
2355: pOHCIRegisters->hcCommandStatus = EndianSwap32Bit (kOHCIHcCommandStatus_BLF);
2356:
2357:
2358:
2359: } else if (pHCDoneTD->pType == kOHCIIsochronousType) {
2360: // cast to a isoc type
2361: pITD = (OHCIIsochTransferDescriptorPtr) pHCDoneTD;
2362: ProcessCompletedITD(pITD);
2363: // deallocate td
2364: OHCIUIMDeallocateITD(pITD);
2365:
2366: } else {
2367:
2368: if (pHCDoneTD->preparationID)
2369: CheckpointIO(pHCDoneTD->preparationID, nil);
2370: pHCDoneTD->preparationID = nil;
2371:
2372: bufferSizeRemaining = findBufferRemaining (pHCDoneTD);
2373: if (pHCDoneTD->CallBack){
2374: CallBackFuncPtr pCallBack;
2375: // zero out callback first than call it
2376: pCallBack = pHCDoneTD->CallBack;
2377: pHCDoneTD->CallBack = nil;
2378: (*pCallBack) (pHCDoneTD->refcon, transferStatus, bufferSizeRemaining);
2379: } else if (transferStatus != nil)
2380: doCallback(pHCDoneTD, transferStatus, bufferSizeRemaining);
2381:
2382: OHCIUIMDeallocateTD(pHCDoneTD);
2383: }
2384: pHCDoneTD = nextTD; /* New qHead */
2385: }
2386:
2387: return(noErr);
2388: }
2389:
2390:
2391:
2392: void doCallback(
2393: OHCIGeneralTransferDescriptorPtr nextTD,
2394: UInt32 transferStatus,
2395: UInt32 bufferSizeRemaining)
2396: {
2397: OHCIGeneralTransferDescriptorPtr pCurrentTD;
2398: OHCIEndpointDescriptorPtr pED;
2399: UInt32 PhysAddr;
2400:
2401: pED = (OHCIEndpointDescriptorPtr) nextTD->pEndpoint;
2402:
2403: PhysAddr = (UInt32) EndianSwap32Bit(pED->dWord2) & kOHCIHeadPMask;
2404: nextTD = (OHCIGeneralTransferDescriptorPtr) OHCIUIMGetLogicalAddress (PhysAddr);
2405:
2406: pCurrentTD = (OHCIGeneralTransferDescriptorPtr) nextTD;
2407: while (pCurrentTD->pVirtualNext != nil)
2408: {
2409:
2410: bufferSizeRemaining += findBufferRemaining (pCurrentTD);
2411: pCurrentTD->dWord1 = 0; // make sure this TD won't be added to any future buffer remaining calculations
2412:
2413: if (pCurrentTD->preparationID)
2414: CheckpointIO(pCurrentTD->preparationID, nil);
2415: pCurrentTD->preparationID = nil; // make sure we don't try to do another CheckpointIO later
2416:
2417: if (pCurrentTD->CallBack!=nil) {
2418: CallBackFuncPtr pCallBack;
2419: // zero out callback first than call it
2420: pCallBack = pCurrentTD->CallBack;
2421: pCurrentTD->CallBack = nil;
2422: (*pCallBack) (pCurrentTD->refcon, transferStatus, bufferSizeRemaining);
2423: bufferSizeRemaining = nil;
2424: return;
2425: }
2426:
2427: pCurrentTD = (OHCIGeneralTransferDescriptorPtr) pCurrentTD->pVirtualNext;
2428: }
2429: }
2430:
2431:
2432: UInt32 findBufferRemaining (OHCIGeneralTransferDescriptorPtr pCurrentTD)
2433: {
2434: UInt32 pageSize;
2435: UInt32 pageMask;
2436: UInt32 bufferSizeRemaining;
2437: pageSize = pOHCIUIMData->pageSize;
2438: pageMask = ~(pageSize - 1);
2439:
2440: if (pCurrentTD->dWord1 == 0){
2441: bufferSizeRemaining = 0;
2442: }else if ((EndianSwap32Bit(pCurrentTD->dWord3) & (pageMask)) ==
2443: (EndianSwap32Bit(pCurrentTD->dWord1)& (pageMask))) {
2444: // we're on the same page
2445: bufferSizeRemaining = (EndianSwap32Bit (pCurrentTD->dWord3) & ~pageMask) -
2446: (EndianSwap32Bit (pCurrentTD->dWord1) & ~pageMask) + 1;
2447: } else {
2448: bufferSizeRemaining = ((EndianSwap32Bit(pCurrentTD->dWord3) & ~pageMask) + 1) +
2449: (pageSize - (EndianSwap32Bit(pCurrentTD->dWord1) & ~pageMask));
2450: }
2451:
2452: return (bufferSizeRemaining);
2453: }
2454:
2455:
2456: OSStatus OHCIUIMControlInitialize ()
2457: {
2458: OHCIRegistersPtr pOHCIRegisters;
2459: OHCIEndpointDescriptorPtr pED, pED2;
2460:
2461:
2462: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
2463:
2464: // Create ED mark it skipped and assign it to ControlTail
2465: pED = OHCIUIMAllocateED();
2466: pED->dWord0 = EndianSwap32Bit (kOHCIEDControl_K);
2467: pOHCIUIMData->pControlTail = (UInt32) pED;
2468: //kprintf("OHCIUIMControlInitialize:pOHCIUIMData->pControlTail=0x%x\n",pED);
2469: // Create ED mark it skipped and assign it to control head
2470: pED2 = OHCIUIMAllocateED();
2471: pED2->dWord0 = EndianSwap32Bit (kOHCIEDControl_K);
2472: pOHCIUIMData->pControlHead = (UInt32) pED2;
2473: //kprintf("OHCIUIMControlInitialize:pOHCIUIMData->pControlHead=0x%x\n",pED2);
2474: pOHCIRegisters->hcControlHeadED = EndianSwap32Bit ((UInt32) pED2->pPhysical);
2475:
2476: // have bulk head ED point to Control tail ED
2477: pED2->dWord3 = EndianSwap32Bit ((UInt32) pED->pPhysical);
2478: pED2->pVirtualNext = (UInt32) pED;
2479: //kprintf("OHCIUIMControlInitialize:pOHCIUIMData->pControlHead->pVirtualNext=0x%x\n",pED);
2480: return (0);
2481: }
2482:
2483:
2484: OSStatus OHCIUIMBulkInitialize (){
2485:
2486: OHCIRegistersPtr pOHCIRegisters;
2487: OHCIEndpointDescriptorPtr pED, pED2;
2488:
2489:
2490: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
2491:
2492: // Create ED mark it skipped and assign it to bulkTail
2493: pED = OHCIUIMAllocateED();
2494: pED->dWord0 = EndianSwap32Bit (kOHCIEDControl_K);
2495: pOHCIUIMData->pBulkTail = (UInt32) pED;
2496:
2497: // Create ED mark it skipped and assign it to bulk head
2498: pED2 = OHCIUIMAllocateED();
2499: pED2->dWord0 = EndianSwap32Bit (kOHCIEDControl_K);
2500: pOHCIUIMData->pBulkHead = (UInt32) pED2;
2501: pOHCIRegisters->hcBulkHeadED = EndianSwap32Bit ((UInt32) pED2->pPhysical);
2502:
2503: // have bulk head ED point to Bulk tail ED
2504: pED2->dWord3 = EndianSwap32Bit ((UInt32) pED->pPhysical);
2505: pED2->pVirtualNext = (UInt32) pED;
2506: return (0);
2507:
2508: }
2509:
2510: OSStatus OHCIUIMIsochronousInitialize()
2511: {
2512:
2513: OHCIRegistersPtr pOHCIRegisters;
2514: OHCIEndpointDescriptorPtr pED, pED2;
2515:
2516:
2517: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
2518:
2519: // Create ED mark it skipped and assign it to bulkTail
2520: pED = OHCIUIMAllocateED();
2521: pED->dWord0 = EndianSwap32Bit (kOHCIEDControl_K);
2522: pOHCIUIMData->pIsochTail = (UInt32) pED;
2523:
2524: // Create ED mark it skipped and assign it to bulk head
2525: pED2 = OHCIUIMAllocateED();
2526: pED2->dWord0 = EndianSwap32Bit (kOHCIEDControl_K);
2527: pOHCIUIMData->pIsochHead = (UInt32) pED2;
2528:
2529:
2530: // have bulk head ED point to Bulk tail ED
2531: pED2->dWord3 = EndianSwap32Bit ((UInt32) pED->pPhysical);
2532: pED2->pVirtualNext = (UInt32) pED;
2533: return (0);
2534:
2535: }
2536:
2537: //Initializes the HCCA Interrupt list with statically
2538: //disabled ED's to form the Interrupt polling queues
2539: OSStatus OHCIUIMInterruptInitialize ()
2540: {
2541:
2542: OHCIRegistersPtr pOHCIRegisters;
2543: OHCIIntHeadPtr pInterruptHead;
2544: OSStatus status = 0;
2545: UInt32 dummyControl;
2546: int i, p, q, z;
2547: OHCIEndpointDescriptorPtr pED, pIsochHead;
2548:
2549:
2550: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
2551: pInterruptHead = pOHCIUIMData->pInterruptHead;
2552:
2553: // create UInt32 with same dword0 for use with searching and tracking, skip should be set, and open area shouldbe marked
2554: dummyControl = kOHCIEDControl_K;
2555: dummyControl |= 0; //should be kOHCIFakeED
2556: dummyControl = EndianSwap32Bit (dummyControl);
2557: pIsochHead = (OHCIEndpointDescriptorPtr) pOHCIUIMData->pIsochHead;
2558:
2559: //do 31 times
2560: // change to 65 and make isoch head the last one.?????
2561: for (i = 0; i < 63; i++)
2562: {
2563: //allocate Endpoint descriptor
2564: pED = OHCIUIMAllocateED();
2565: if (pED == nil){
2566: status = -1;
2567: return (status);
2568: }
2569: //mark skipped,some how mark as a False endpoint zzzzz
2570: else {
2571:
2572: pED->dWord0 = dummyControl;
2573: pInterruptHead[i].pHead = pED;
2574: pInterruptHead[i].pHeadPhysical = pED->pPhysical;
2575: pInterruptHead[i].nodeBandwidth = 0;
2576: }
2577: if ( i < 32)
2578: ((UInt32 *)pOHCIUIMData->pHCCA)[i] = (UInt32) EndianSwap32Bit ((UInt32) pInterruptHead[i].pHeadPhysical);
2579:
2580: }
2581:
2582: p = 0;
2583: q = 32;
2584: //
2585: for (i = 0; i < (32 +16 + 8 + 4 + 2); i++)
2586: {
2587: if (i < q/2+p)
2588: z = i + q;
2589: else
2590: z = i + q/2;
2591: if (i == p+q-1)
2592: {
2593: p = p + q;
2594: q = q/2;
2595: }
2596: //point endpoint descriptor to corresponding 8ms descriptor
2597: pED = pInterruptHead[i].pHead;
2598: pED->dWord3 = EndianSwap32Bit (pInterruptHead[z].pHeadPhysical);
2599: pED->pVirtualNext = (UInt32) pInterruptHead[z].pHead;
2600: pInterruptHead[i].pTail = (OHCIEndpointDescriptorPtr) pED->pVirtualNext;
2601:
2602: }
2603: i = 62;
2604: pED = pInterruptHead[i].pHead;
2605: pED->dWord3 = EndianSwap32Bit (pIsochHead->pPhysical);
2606: pED->pVirtualNext = (UInt32) pOHCIUIMData->pIsochHead;
2607: pInterruptHead[i].pTail = (OHCIEndpointDescriptorPtr) pED->pVirtualNext;
2608:
2609: // point Isochronous head to last endpoint
2610:
2611:
2612: return (status);
2613: }
2614:
2615: /*
2616: // determines the best fit for the interrupt ED
2617: OSStatus OHCIUIMInterruptschedule()
2618: {
2619: }
2620:
2621:
2622: //determines whether or not the ED can fit
2623: OSStatus OHCIUIMInterruptfits()
2624: {
2625: }
2626:
2627: // determines the worst and best bandwidth
2628: // for use with scheduling periodic ed's
2629: OSStatus OHCIUIMInterruptBandwidthCheck()
2630:
2631: {
2632: }
2633:
2634: //Finds an ED in the interrupt queue
2635: OSStatus OHCIUIMInterruptFindED()
2636: {
2637: }
2638: */
2639: //Allocate
2640: OSStatus OHCIUIMAllocateMemory (
2641: int num_of_TDs,
2642: int num_of_EDs,
2643: int num_of_ITDs)
2644: {
2645: OSStatus status;
2646: Ptr p;
2647: UInt32 physical;
2648: int tdsPage,pagesTD,edsPage,pagesED, itdsPage, pagesITD;
2649: UInt32 pageSize;
2650: OHCIEndpointDescriptorPtr FreeED, FreeEDCurrent;
2651: OHCIGeneralTransferDescriptorPtr FreeTD, FreeTDCurrent;
2652: OHCIIsochTransferDescriptorPtr FreeITD, FreeITDCurrent;
2653: int i,j;
2654:
2655:
2656: pageSize = pOHCIUIMData->pageSize;
2657: kprintf("pgsize=%d,sizes=%d,%d,%d\n",pageSize,sizeof(OHCIGeneralTransferDescriptor),sizeof(OHCIEndpointDescriptor),sizeof(OHCIIsochTransferDescriptor));
2658:
2659:
2660: tdsPage = pageSize/sizeof (OHCIGeneralTransferDescriptor);
2661: pagesTD = num_of_TDs /tdsPage +1;
2662: edsPage = pageSize/sizeof (OHCIEndpointDescriptor);
2663: pagesED = num_of_EDs/edsPage +1;
2664: itdsPage = pageSize/sizeof (OHCIIsochTransferDescriptor);
2665: pagesITD = num_of_ITDs /itdsPage +1;
2666:
2667: // use pool allocate to allocate a large sum of memory zzzzz why plus 3???
2668:
2669: kprintf("trying to allocate %d+%d+%d+1 * %d\n",pagesED,pagesTD,pagesITD,pageSize);
2670: p = Desc_Buffer_Usb;
2671:
2672: kprintf("kalloc p=0x%x\n",p);
2673:
2674: //naga pOHCIUIMData->pDataAllocation = p;
2675: //page align and 16 byte align(page align automagically makes it 16 byte aligned)
2676: p = (Ptr) (((UInt32) p + (pageSize - 1)) & ~(pageSize - 1)); // page-align
2677:
2678: // use prepare mem for IO to find physical address
2679: physical = OHCIUIMGetPhysicalAddress((UInt32) p, pagesED+pagesTD+pagesITD);
2680:
2681: // create a list of unused ED's, filling in Virtual address, physicaladdress and virtual next
2682: // physical next.
2683: FreeED = (OHCIEndpointDescriptorPtr) p;
2684: FreeEDCurrent = FreeED;
2685: pOHCIUIMData->pFreeED = FreeED;
2686:
2687:
2688: for (i = 0;i<pagesED;i++)
2689: {
2690: for (j = 0; j < edsPage; j++)
2691: {
2692: //create EDs
2693: FreeEDCurrent[j].pPhysical = physical + (j *sizeof (OHCIEndpointDescriptor));
2694: FreeEDCurrent[j].pVirtualNext = (UInt32) (&FreeEDCurrent[j+1]);
2695: }
2696: if (i != (pagesED - 1)){
2697: FreeEDCurrent[j-1].pVirtualNext = ((UInt32) FreeEDCurrent + pageSize);
2698: } else {
2699: FreeEDCurrent[j-1].pVirtualNext = nil;
2700: pOHCIUIMData->pLastFreeED = &FreeEDCurrent[j-1];
2701: }
2702:
2703: // goto next page
2704: FreeEDCurrent = (OHCIEndpointDescriptorPtr) ((UInt32) FreeEDCurrent + pageSize);
2705: physical += pageSize;
2706: }
2707: FreeTD = (OHCIGeneralTransferDescriptorPtr) FreeEDCurrent;
2708: FreeTDCurrent = FreeTD;
2709: pOHCIUIMData->pFreeTD = FreeTD;
2710: for (i = 0;i<pagesTD;i++)
2711: {
2712: for (j = 0; j < tdsPage; j++)
2713: {
2714: //create TDs
2715: FreeTDCurrent[j].pPhysical = physical + (j * sizeof (OHCIGeneralTransferDescriptor));
2716: FreeTDCurrent[j].pVirtualNext = (UInt32) (&FreeTDCurrent[j+1]);
2717:
2718: }
2719: if (i != (pagesTD - 1)){
2720: FreeTDCurrent[j-1].pVirtualNext = ((UInt32) FreeTDCurrent + pageSize);
2721: } else {
2722: FreeTDCurrent[j-1].pVirtualNext = nil;
2723: pOHCIUIMData->pLastFreeTD = &FreeTDCurrent[j-1];
2724: }
2725:
2726: // goto next page
2727: FreeTDCurrent = (OHCIGeneralTransferDescriptorPtr) ((UInt32) FreeTDCurrent + pageSize);
2728: physical += pageSize;
2729:
2730: }
2731:
2732:
2733: // set up freeitd queue
2734: FreeITD = (OHCIIsochTransferDescriptorPtr) FreeTDCurrent;
2735: FreeITDCurrent = FreeITD;
2736: pOHCIUIMData->pFreeITD = FreeITD;
2737: for (i = 0;i<pagesTD;i++)
2738: {
2739: for (j = 0; j < tdsPage; j++)
2740: {
2741: //create TDs
2742: FreeITDCurrent[j].pPhysical = physical + (j * sizeof (OHCIIsochTransferDescriptor));
2743: FreeITDCurrent[j].pVirtualNext = (UInt32) (&FreeITDCurrent[j+1]);
2744:
2745: }
2746: if (i != (pagesITD - 1)){
2747: FreeITDCurrent[j-1].pVirtualNext = ((UInt32) FreeITDCurrent + pageSize);
2748: } else {
2749: FreeITDCurrent[j-1].pVirtualNext = nil;
2750: pOHCIUIMData->pLastFreeITD = &FreeITDCurrent[j-1];
2751: }
2752:
2753: // goto next page
2754: FreeITDCurrent = (OHCIIsochTransferDescriptorPtr) ((UInt32) FreeITDCurrent + pageSize);
2755: physical += pageSize;
2756:
2757: }
2758:
2759: // create a list of unused buffers?????
2760:
2761: return (status);
2762:
2763: }
2764:
2765: OHCIIsochTransferDescriptorPtr OHCIUIMAllocateITD()
2766:
2767: {
2768: OHCIIsochTransferDescriptorPtr temp, FreeTD;
2769:
2770: // pop a TD off of FreeTD list
2771: //if FreeTD == NIL return nil
2772: // should we check if ED is full and if not access that????
2773: temp = FreeTD = pOHCIUIMData->pFreeITD;
2774:
2775: if (FreeTD != nil)
2776: {
2777: pOHCIUIMData->pFreeITD = (OHCIIsochTransferDescriptorPtr) FreeTD->pVirtualNext;
2778: } else {
2779: AssertDebugStr("OHCIUIM: Out of Transfer Descriptors! ");
2780: }
2781:
2782: /* BT, I think I need to do this here */
2783: temp->pType = kOHCIIsochronousType;
2784:
2785: return (temp);
2786:
2787: }
2788:
2789: OHCIGeneralTransferDescriptorPtr OHCIUIMAllocateTD()
2790:
2791: {
2792: OHCIGeneralTransferDescriptorPtr temp, FreeTD;
2793:
2794: // pop a TD off of FreeTD list
2795: //if FreeTD == NIL return nil
2796: // should we check if ED is full and if not access that????
2797: temp = FreeTD = pOHCIUIMData->pFreeTD;
2798:
2799: if (FreeTD != nil)
2800: {
2801: pOHCIUIMData->pFreeTD = (OHCIGeneralTransferDescriptorPtr) FreeTD->pVirtualNext;
2802: temp->pVirtualNext = nil;
2803: } else {
2804: AssertDebugStr("OHCIUIM: Out of Transfer Descriptors! ");
2805: }
2806: return (temp);
2807:
2808: }
2809:
2810: OHCIEndpointDescriptorPtr OHCIUIMAllocateED()
2811: {
2812: OHCIEndpointDescriptorPtr temp, FreeED;
2813:
2814:
2815: // Pop a ED off the FreeED list
2816: // If FreeED == nil return Error
2817: temp = FreeED = (OHCIEndpointDescriptorPtr) pOHCIUIMData->pFreeED;
2818:
2819: if (pOHCIUIMData->pFreeED != nil)
2820: {
2821: pOHCIUIMData->pFreeED = (OHCIEndpointDescriptorPtr) FreeED->pVirtualNext;
2822: temp->pVirtualNext = nil;
2823: } else {
2824: AssertDebugStr("OHCIUIM: Out of Endpoint Descriptors! ");
2825: }
2826: return (temp);
2827: }
2828:
2829: OSStatus OHCIUIMDeallocateITD (
2830: OHCIIsochTransferDescriptorPtr pTD)
2831: {
2832: UInt32 physical;
2833:
2834: //zero out all unnecessary fields
2835: physical = pTD->pPhysical;
2836: BlockZero(pTD, sizeof(*pTD));
2837: pTD->pPhysical = physical;
2838: pTD->pType = kOHCIIsochronousType;
2839: if (pOHCIUIMData->pFreeITD){
2840: pOHCIUIMData->pLastFreeITD->pVirtualNext = (UInt32)pTD;
2841: pOHCIUIMData->pLastFreeITD = pTD;
2842: } else {
2843: // list is currently empty
2844: pOHCIUIMData->pLastFreeITD = pTD;
2845: pOHCIUIMData->pFreeITD = pTD;
2846: }
2847: return (0);
2848: }
2849:
2850:
2851: OSStatus OHCIUIMDeallocateTD (
2852: OHCIGeneralTransferDescriptorPtr pTD)
2853: {
2854: UInt32 physical;
2855:
2856: //zero out all unnecessary fields
2857: physical = pTD->pPhysical;
2858: BlockZero(pTD, sizeof(*pTD));
2859: pTD->pPhysical = physical;
2860:
2861: if (pOHCIUIMData->pFreeTD){
2862: pOHCIUIMData->pLastFreeTD->pVirtualNext = (UInt32)pTD;
2863: pOHCIUIMData->pLastFreeTD = pTD;
2864: } else {
2865: // list is currently empty
2866: pOHCIUIMData->pLastFreeTD = pTD;
2867: pOHCIUIMData->pFreeTD = pTD;
2868: }
2869: return (0);
2870: }
2871:
2872: OSStatus OHCIUIMDeallocateED (
2873: OHCIEndpointDescriptorPtr pED)
2874: {
2875: UInt32 physical;
2876:
2877: //zero out all unnecessary fields
2878: physical = pED->pPhysical;
2879: BlockZero(pED, sizeof(*pED));
2880: pED->pPhysical = physical;
2881:
2882: if (pOHCIUIMData->pFreeED){
2883: pOHCIUIMData->pLastFreeED->pVirtualNext = (UInt32)pED;
2884: pOHCIUIMData->pLastFreeED = pED;
2885: } else {
2886: // list is currently empty
2887: pOHCIUIMData->pLastFreeED = pED;
2888: pOHCIUIMData->pFreeED = pED;
2889: }
2890: return (0);
2891: }
2892: /*
2893:
2894: OSStatus OHCIUIMAllocateBuffer()
2895: {}
2896: */
2897:
2898:
2899: ////////////////////////////////////////////////////////////////////////////////
2900: //
2901: // UInt32 OHCIUIMGetLogicalAddress
2902: // Given the physical address, return the virtual address
2903: //
2904:
2905: UInt32 OHCIUIMGetLogicalAddress (
2906: UInt32 pPhysicalAddress)
2907: {
2908: OHCIPhysicalLogicalPtr pPhysicalLogical;
2909: UInt32 LogicalAddress = nil;
2910:
2911: if (pPhysicalAddress == 0)
2912: return(0);
2913:
2914: pPhysicalLogical = pOHCIUIMData->pPhysicalLogical;
2915:
2916: while (pPhysicalLogical != nil) {
2917: if (pPhysicalAddress <= pPhysicalLogical->PhysicalEnd
2918: && pPhysicalAddress >= pPhysicalLogical->PhysicalStart)
2919: {
2920: LogicalAddress = pPhysicalLogical->LogicalStart + (pPhysicalAddress - pPhysicalLogical->PhysicalStart);
2921: pPhysicalLogical = nil;
2922: } else {
2923: pPhysicalLogical = (OHCIPhysicalLogicalPtr) pPhysicalLogical->pNext;
2924: }
2925: }
2926:
2927: if ( LogicalAddress == nil)
2928: AssertDebugStr("OHCIUIM: LogicalAddress == nil !");
2929:
2930: return (LogicalAddress);
2931:
2932: }
2933:
2934:
2935: UInt32 OHCIUIMGetPhysicalAddress(
2936: UInt32 LogicalAddress,
2937: UInt32 count)
2938: {
2939: OHCIPhysicalLogicalPtr pPhysicalLogical;
2940: UInt32 PhysicalAddress = nil;
2941:
2942: if (LogicalAddress == 0)
2943: return(0);
2944:
2945: pPhysicalLogical = pOHCIUIMData->pPhysicalLogical;
2946:
2947: while (pPhysicalLogical != nil) {
2948: if (LogicalAddress <= pPhysicalLogical->LogicalEnd
2949: && LogicalAddress >= pPhysicalLogical->LogicalStart)
2950: {
2951: PhysicalAddress = pPhysicalLogical->PhysicalStart + (LogicalAddress - pPhysicalLogical->LogicalStart);
2952: pPhysicalLogical = nil;
2953: } else {
2954: pPhysicalLogical = (OHCIPhysicalLogicalPtr) pPhysicalLogical->pNext;
2955: }
2956: }
2957:
2958: if (PhysicalAddress == nil)
2959: PhysicalAddress = OHCIUIMCreatePhysicalAddress(LogicalAddress, count);
2960:
2961: return (PhysicalAddress);
2962: }
2963:
2964: UInt32 OHCIUIMCreatePhysicalAddress(
2965: UInt32 pLogicalAddress,
2966: UInt32 count)
2967:
2968: {
2969: UInt32 pageSize;
2970: PhysicalMappingTablePtr physicalAddressTable;
2971: OHCIPhysicalLogicalPtr pPhysicalLogical;
2972: IOPreparationTable *ioPrep;
2973: IOPreparationTable IOPrep;
2974: OSStatus status;
2975: OHCIPhysicalLogicalPtr p;
2976:
2977: pPhysicalLogical = pOHCIUIMData->pPhysicalLogical;
2978: pageSize = pOHCIUIMData->pageSize;
2979:
2980: // zzzzz - revisit this regarding the size of the table do we deallocate this?
2981: physicalAddressTable = (PhysicalMappingTablePtr)PoolAllocateResident((count)*sizeof(UInt32), false);
2982:
2983: // zzz do we deallocate this?
2984: p = (OHCIPhysicalLogicalPtr) PoolAllocateResident (sizeof (OHCIPhysicalLogical), true);
2985:
2986: p->LogicalStart = pLogicalAddress;
2987: p->PhysicalStart = kvtophys((vm_offset_t)pLogicalAddress);
2988: p->LogicalEnd = p->LogicalStart + count*pageSize-1;
2989: p->PhysicalEnd = p->PhysicalStart + count*pageSize-1;
2990: p->pNext = nil;
2991:
2992: //now put it all in a table
2993: if (pPhysicalLogical == nil)
2994: {
2995: pPhysicalLogical = p;
2996: } else {
2997: //traverse Queue
2998: while (pPhysicalLogical->pNext != nil)
2999: {
3000: pPhysicalLogical = (OHCIPhysicalLogicalPtr) pPhysicalLogical->pNext;
3001: }
3002: pPhysicalLogical->pNext = (UInt32) p;
3003: }
3004: pOHCIUIMData->pPhysicalLogical = pPhysicalLogical;
3005:
3006: return (p->PhysicalStart);
3007: }
3008:
3009:
3010:
3011: static void returnTransactions(OHCIGeneralTransferDescriptor *transaction, UInt32 tail)
3012: {
3013: UInt32 physicalAddress;
3014: OHCIGeneralTransferDescriptor *nextTransaction;
3015:
3016: while(transaction->pPhysical != tail)
3017: {
3018: if(transaction == nil)
3019: {
3020: AssertDebugStr("Return queue broken");
3021: break;
3022: }
3023: else
3024: {
3025: if (transaction->preparationID)
3026: CheckpointIO(transaction->preparationID, nil);
3027: transaction->preparationID = nil;
3028:
3029: if (transaction->CallBack) {
3030: CallBackFuncPtr pCallBack;
3031: // zero out callback first than call it
3032: pCallBack = transaction->CallBack;
3033: transaction->CallBack = nil;
3034: (*pCallBack) (transaction->refcon, returnedErr, 0);
3035: }
3036: /* walk the physically-addressed list */
3037: physicalAddress = (UInt32) EndianSwap32Bit(transaction->dWord2) & kOHCIHeadPMask;
3038: nextTransaction = (OHCIGeneralTransferDescriptorPtr) OHCIUIMGetLogicalAddress (physicalAddress);
3039: OHCIUIMDeallocateTD(transaction);
3040: transaction = nextTransaction;
3041: }
3042: }
3043: }
3044:
3045:
3046: OSStatus OHCIUIMClearEndPointStall(
3047: short functionNumber,
3048: short endpointNumber,
3049: short direction)
3050: {
3051: OHCIRegistersPtr pOHCIRegisters;
3052: OSStatus status = noErr;
3053: OHCIEndpointDescriptorPtr pEDQueueBack, pED;
3054: OHCIGeneralTransferDescriptor *transaction;
3055: UInt32 tail, controlMask;
3056:
3057:
3058: if (pOHCIUIMData->rootHubFuncAddress == functionNumber)
3059: return (status);
3060:
3061: if (direction == kUSBOut)
3062: direction = kOHCIEDDirectionOut;
3063: else if (direction == kUSBIn)
3064: direction = kOHCIEDDirectionIn;
3065: else
3066: direction = kOHCIEDDirectionTD;
3067:
3068: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
3069:
3070: transaction = nil;
3071: tail = nil;
3072: kprintf("OHCIUIMClear EPS:calling FindEndpoint\n");
3073: if((pED = FindEndpoint (functionNumber, endpointNumber, direction, &pEDQueueBack, &controlMask)) == nil)
3074: return(kUSBNotFound);
3075:
3076: if (pED != nil) {
3077: tail = EndianSwap32Bit(pED->dWord1);
3078: transaction = (void *)OHCIUIMGetLogicalAddress(EndianSwap32Bit(pED->dWord2) & kOHCIHeadPMask);
3079: pED->dWord2 = pED->dWord1; /* unlink all transactions at once (this also clears the halted bit) */
3080: pED->pVirtualHeadP = pED->pVirtualTailP;
3081: }
3082:
3083: if (transaction != nil){
3084: returnTransactions(transaction, tail);
3085: }
3086: return (status);
3087: }
3088:
3089: OHCIEndpointDescriptorPtr FindControlEndpoint (
3090: short functionNumber,
3091: short endpointNumber,
3092: OHCIEndpointDescriptorPtr *pEDBack)
3093: {
3094: UInt32 unique;
3095: OHCIEndpointDescriptorPtr pEDQueue;
3096: OHCIEndpointDescriptorPtr pEDQueueBack;
3097:
3098:
3099: //search for endpoint descriptor
3100: unique = (UInt32) ((((UInt32) endpointNumber) << kOHCIEndpointNumberOffset) | ((UInt32) functionNumber));
3101: pEDQueueBack = (OHCIEndpointDescriptorPtr) pOHCIUIMData->pControlHead;
3102: pEDQueue = (OHCIEndpointDescriptorPtr) pEDQueueBack->pVirtualNext;
3103: //kprintf("FindControlEp:pOHCIUIMData->pControlHead=0x%x,pEDQ=pOHCIUIMData->pControlHead->pVirtualNext=0x%x,pOHCIUIMData->pControlTail=0x%x\n",pEDQueueBack,pEDQueue,pOHCIUIMData->pControlTail);
3104:
3105: while ((UInt32) pEDQueue != pOHCIUIMData->pControlTail)
3106: {
3107: //kprintf("FindControlEp:searching for %d(unique),dword0=%d\n",unique, (EndianSwap32Bit(pEDQueue->dWord0) & kUniqueNumNoDirMask));
3108: if ( (EndianSwap32Bit(pEDQueue->dWord0) & kUniqueNumNoDirMask) == unique) {
3109: *pEDBack = pEDQueueBack;
3110: return (pEDQueue);
3111: } else {
3112: pEDQueueBack = pEDQueue;
3113: pEDQueue = (OHCIEndpointDescriptorPtr) pEDQueue->pVirtualNext;
3114: }
3115: }
3116: if (pOHCIUIMData->OptiOn) {
3117: pEDQueue = FindBulkEndpoint (functionNumber, endpointNumber, kOHCIEDDirectionTD, &pEDQueueBack);
3118: *pEDBack = pEDQueueBack;
3119: return (pEDQueue);
3120: }
3121: return (nil);
3122: }
3123:
3124:
3125: OHCIEndpointDescriptorPtr FindBulkEndpoint (
3126: short functionNumber,
3127: short endpointNumber,
3128: short direction,
3129: OHCIEndpointDescriptorPtr *pEDBack)
3130: {
3131:
3132: UInt32 unique;
3133: UInt32 myEndPointDirection;
3134: OHCIEndpointDescriptorPtr pEDQueue;
3135: OHCIEndpointDescriptorPtr pEDQueueBack;
3136:
3137:
3138: //search for endpoint descriptor
3139: myEndPointDirection = ((UInt32) direction) << kOHCIEndpointDirectionOffset;
3140: unique = (UInt32) ((((UInt32) endpointNumber) << kOHCIEndpointNumberOffset) | ((UInt32) functionNumber)
3141: | myEndPointDirection);
3142: pEDQueueBack = (OHCIEndpointDescriptorPtr) pOHCIUIMData->pBulkHead;
3143: pEDQueue = (OHCIEndpointDescriptorPtr) pEDQueueBack->pVirtualNext;
3144: while (((UInt32) pEDQueue) != pOHCIUIMData->pBulkTail ) {
3145: if ( (EndianSwap32Bit(pEDQueue->dWord0) & kUniqueNumMask) == unique) {
3146: *pEDBack = pEDQueueBack;
3147: return (pEDQueue);
3148: } else {
3149: pEDQueueBack = pEDQueue;
3150: pEDQueue = (OHCIEndpointDescriptorPtr) pEDQueue->pVirtualNext;
3151:
3152: }
3153: }
3154: return (nil);
3155:
3156: }
3157:
3158:
3159: OHCIEndpointDescriptorPtr FindEndpoint (
3160: short functionNumber,
3161: short endpointNumber,
3162: short direction,
3163: OHCIEndpointDescriptorPtr *pEDQueueBack,
3164: UInt32 *controlMask)
3165: {
3166: OHCIEndpointDescriptorPtr pED, pEDBack;
3167:
3168: // DebugStr("OHCIUIM: FindEndpoint");
3169: kprintf("FindEndPoint:Calling FindControlEndpoint fn=%d,ep=%d\n",functionNumber,endpointNumber);
3170: if ((pED = FindControlEndpoint (functionNumber, endpointNumber, &pEDBack)) != nil)
3171: {
3172: *pEDQueueBack = pEDBack;
3173: *controlMask = kOHCIHcControl_CLE;
3174: return (pED);
3175: }
3176: if ((pED = FindBulkEndpoint (functionNumber, endpointNumber, direction, &pEDBack)) != nil)
3177: {
3178: *pEDQueueBack = pEDBack;
3179:
3180: *controlMask = kOHCIHcControl_BLE;
3181: //zzzz Opti Bug
3182: if(pOHCIUIMData->OptiOn)
3183: *controlMask = kOHCIHcControl_CLE;
3184: return (pED);
3185: }
3186:
3187: if ((pED = FindInterruptEndpoint (functionNumber, endpointNumber, &pEDBack)) != nil)
3188: {
3189: *pEDQueueBack = pEDBack;
3190: *controlMask = 0;
3191: return (pED);
3192: }
3193:
3194: pED = FindIsochronousEndpoint(functionNumber, endpointNumber, direction, &pEDBack);
3195: *pEDQueueBack = pEDBack;
3196: *controlMask = 0;
3197: return (pED);
3198: }
3199:
3200:
3201: OHCIEndpointDescriptorPtr FindIsochronousEndpoint(
3202: short functionNumber,
3203: short endpointNumber,
3204: short direction,
3205: OHCIEndpointDescriptorPtr *pEDBack)
3206: {
3207: UInt32 myEndPointDirection;
3208: UInt32 unique;
3209: OHCIEndpointDescriptorPtr pEDQueue, pEDQueueBack;
3210:
3211: //search for endpoint descriptor
3212: myEndPointDirection = ((UInt32) direction) << kOHCIEndpointDirectionOffset;
3213: unique = (UInt32) ((((UInt32) endpointNumber) << kOHCIEndpointNumberOffset) | ((UInt32) functionNumber)
3214: | myEndPointDirection);
3215:
3216: pEDQueueBack = (OHCIEndpointDescriptorPtr) pOHCIUIMData->pIsochHead;
3217: pEDQueue = (OHCIEndpointDescriptorPtr) pEDQueueBack->pVirtualNext;
3218: while (((UInt32) pEDQueue) != pOHCIUIMData->pIsochTail ) {
3219: if ( (EndianSwap32Bit(pEDQueue->dWord0) & kUniqueNumMask) == unique) {
3220: *pEDBack = pEDQueueBack;
3221: return (pEDQueue);
3222: } else {
3223: pEDQueueBack = pEDQueue;
3224: pEDQueue = (OHCIEndpointDescriptorPtr) pEDQueue->pVirtualNext;
3225:
3226: }
3227: }
3228: return (nil);
3229:
3230: }
3231:
3232:
3233: OHCIEndpointDescriptorPtr FindInterruptEndpoint(
3234: short functionNumber,
3235: short endpointNumber,
3236: OHCIEndpointDescriptorPtr *pEDBack)
3237: {
3238: OHCIRegistersPtr pOHCIRegisters;
3239: UInt32 unique;
3240: OHCIEndpointDescriptorPtr pEDQueue;
3241: OHCIIntHeadPtr pInterruptHead;
3242: int i;
3243: UInt32 temp;
3244:
3245:
3246:
3247: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
3248: pInterruptHead = pOHCIUIMData->pInterruptHead;
3249:
3250: //search for endpoint descriptor
3251: unique = (UInt32) ((((UInt32) endpointNumber) << kOHCIEDControl_ENPhase) | (((UInt32) functionNumber) << kOHCIEDControl_FAPhase));
3252: // sprintf (debugStr, "FindInterruptEndpoint unique %d", unique);
3253: // DebugStr ((ConstStr255Param) c2pstr (debugStr));
3254:
3255:
3256: for (i = 0; i < 63; i++)
3257: {
3258: pEDQueue = pInterruptHead[i].pHead;
3259: *pEDBack = pEDQueue;
3260: /* BT do this first, or you find the dummy endpoint all this is hanging off. It matches 0,0 */
3261: pEDQueue = (OHCIEndpointDescriptorPtr) pEDQueue->pVirtualNext;
3262: while (pEDQueue != pInterruptHead[i].pTail)
3263: {
3264: temp = (EndianSwap32Bit (pEDQueue->dWord0)) & kUniqueNumNoDirMask;
3265:
3266: if ( temp == unique)
3267: {
3268: return(pEDQueue);
3269: }
3270: *pEDBack = pEDQueue;
3271: pEDQueue = (OHCIEndpointDescriptorPtr) pEDQueue->pVirtualNext;
3272: }
3273: }
3274: return(nil);
3275:
3276: }
3277:
3278: int GetEDType(
3279: OHCIEndpointDescriptorPtr pED)
3280: {
3281: return ((EndianSwap32Bit(pED->dWord0) & kOHCIEDControl_F) >> kOHCIEDControl_FPhase);
3282: }
3283:
3284:
3285: static OSStatus RemoveAllTDs (OHCIEndpointDescriptorPtr pED)
3286: {
3287: RemoveTDs(pED);
3288:
3289: if (GetEDType(pED) == kOHCIEDFormatGeneralTD) {
3290: // remove the last "dummy" TD
3291: OHCIUIMDeallocateTD((OHCIGeneralTransferDescriptorPtr) pED->pVirtualTailP);
3292: } else {
3293: OHCIUIMDeallocateITD((OHCIIsochTransferDescriptorPtr) pED->pVirtualTailP);
3294: }
3295: pED->pVirtualHeadP = nil;
3296:
3297: return (0);
3298: }
3299:
3300:
3301: //removes all but the last of the TDs
3302: static OSStatus RemoveTDs (OHCIEndpointDescriptorPtr pED)
3303: {
3304: OHCIGeneralTransferDescriptorPtr pCurrentTD, lastTD;
3305: UInt32 bufferSizeRemaining = 0;
3306: OHCIIsochTransferDescriptorPtr pITD, pITDLast;
3307:
3308: if (GetEDType(pED) == kOHCIEDFormatGeneralTD) {
3309: //process and deallocate GTD's
3310: pCurrentTD = (OHCIGeneralTransferDescriptorPtr) (EndianSwap32Bit(pED->dWord2) & kOHCIHeadPMask);
3311: pCurrentTD = (OHCIGeneralTransferDescriptorPtr) OHCIUIMGetLogicalAddress ((UInt32) pCurrentTD);
3312:
3313: lastTD = (OHCIGeneralTransferDescriptorPtr) pED->pVirtualTailP;
3314: pED->pVirtualHeadP = pED->pVirtualTailP;
3315:
3316: while (pCurrentTD != lastTD)
3317: {
3318: if (pCurrentTD == nil)
3319: return (-1);
3320:
3321: //take out TD from list
3322: pED->dWord2 = pCurrentTD->dWord2;
3323: pED->pVirtualHeadP = pCurrentTD->pVirtualNext;
3324:
3325: if (pCurrentTD->preparationID)
3326: CheckpointIO(pCurrentTD->preparationID, nil);
3327: pCurrentTD->preparationID = nil;
3328:
3329: bufferSizeRemaining += findBufferRemaining(pCurrentTD);
3330:
3331: if (pCurrentTD->CallBack){
3332: CallBackFuncPtr pCallBack;
3333: // zero out callback first than call it
3334: pCallBack = pCurrentTD->CallBack;
3335: pCurrentTD->CallBack = nil;
3336: (*pCallBack) (pCurrentTD->refcon, EDDeleteErr, bufferSizeRemaining);
3337: bufferSizeRemaining = 0;
3338: }
3339:
3340: OHCIUIMDeallocateTD(pCurrentTD);
3341: pCurrentTD = (OHCIGeneralTransferDescriptorPtr) pED->pVirtualHeadP;
3342: }
3343: } else {
3344: pITD = (OHCIIsochTransferDescriptorPtr) (EndianSwap32Bit(pED->dWord2) & kOHCIHeadPMask);
3345: pITD = (OHCIIsochTransferDescriptorPtr) OHCIUIMGetLogicalAddress ((UInt32) pITD);
3346: pITDLast = (OHCIIsochTransferDescriptorPtr) pED->pVirtualTailP;
3347:
3348: while (pITD != pITDLast) {
3349: if (pITD == nil)
3350: return (-1);
3351: ProcessCompletedITD (pITD);
3352: pITD = (OHCIIsochTransferDescriptorPtr) pITD->pVirtualNext;
3353: }
3354: }
3355:
3356: return (0);
3357: }
3358:
3359: void ProcessCompletedITD (OHCIIsochTransferDescriptorPtr pITD) {
3360:
3361: USBIsocFrame *pFrames;
3362: int i;
3363:
3364: SwapIsoc (pITD);
3365: pFrames = (USBIsocFrame *) pITD->pIsocFrame;
3366:
3367: for (i=0; i <= ((pITD->dWord0 & kOHCIITDControl_FC) >> kOHCIITDControl_FCPhase); i++) {
3368: if ( ((pITD->offset[i] & kOHCIITDPSW_CCNA) >> kOHCIITDPSW_CCNAPhase) == kOHCIITDConditionNotAccessed) {
3369: pFrames[pITD->frameNum + i].frActCount = 0;
3370: pFrames[pITD->frameNum + i].frStatus = kOHCIITDConditionNotAccessedReturn;
3371: } else {
3372: pFrames[pITD->frameNum + i].frStatus =
3373: (pITD->offset[i] & kOHCIITDPSW_CC) >> kOHCIITDOffset_CCPhase;
3374: pFrames[pITD->frameNum + i].frActCount = pITD->offset[i] & kOHCIITDPSW_Size;
3375: }
3376: }
3377: // call callback
3378: if (pITD->handler){
3379: IsocCallBackFuncPtr pHandler;
3380: pHandler = pITD->handler;
3381: pITD->handler = nil;
3382: //zero out handler first than call it
3383: (*pHandler) (pITD->refcon, noErr, pFrames);
3384: }
3385: }
3386:
3387: /*
3388: This table contains the list of errata that are necessary for known problems with particular silicon
3389: The format is vendorID, revisionID, lowest revisionID needing errata, highest rev needing errata, errataBits
3390: The result of all matches is ORed together, so more than one entry may match. Typically for a given errata a
3391: list of chips revisions that this applies to is supplied.
3392: */
3393: static ErrataListEntry errataList[] = {
3394: {0x1095, 0x670, 0, 0xffff, kErrataCMDDisableTestMode | kErrataOnlySinglePageTransfers | kErrataRetryBufferUnderruns}, // CMD 670
3395: {0x1045, 0xc861, 0, 0xffff, kErrataLSHSOpti}, // Opti 1045
3396: };
3397:
3398: #define errataListLength (sizeof(errataList)/sizeof(ErrataListEntry))
3399:
3400: static UInt32 GetErrataBits (RegEntryIDPtr regEntryIDPtr)
3401: {
3402: UInt32 vendID, deviceID, revisionID;
3403: UInt32 vLen = sizeof(vendID), dLen = sizeof(deviceID), rLen = sizeof(revisionID);
3404: ErrataListEntry *entryPtr;
3405: UInt32 i, errata = 0;
3406:
3407: extern int cmd_pci_errata; //global needed to fix errata for Caps Lock
3408: //LED support. In usbcmd.m.
3409:
3410: if (cmd_pci_errata == 1)
3411: {
3412: return 0; //This allows PowerSurge with CMD card to work with Caps Lock LED
3413: }
3414:
3415: // get this chips vendID, deviceID, revisionID
3416: RegistryPropertyGet(regEntryIDPtr, "vendor-id", &vendID, &vLen);
3417: RegistryPropertyGet(regEntryIDPtr, "device-id", &deviceID, &dLen);
3418: RegistryPropertyGet(regEntryIDPtr, "revision-id", &revisionID, &rLen);
3419: for(i=0, entryPtr = errataList; i<errataListLength; i++, entryPtr++){
3420: if (vendID == entryPtr->vendID && deviceID == entryPtr->deviceID &&
3421: revisionID >= entryPtr->revisionLo && revisionID <= entryPtr->revisionHi){
3422: errata |= entryPtr->errata; // we match, add this errata to our list
3423: }
3424: }
3425: return(errata);
3426: }
3427:
3428:
3429: void DoOptiFix(OHCIEndpointDescriptorPtr pIsochHead)
3430: {
3431: OHCIEndpointDescriptorPtr pED;
3432: OHCIGeneralTransferDescriptorPtr pTD;
3433: int i = 0;
3434: int j = 0;
3435:
3436: // DebugStr ((ConstStr255Param) "DoOptiFix");
3437:
3438: for (i=0; i<20; i++) {
3439: // allocate ED
3440: pED = OHCIUIMAllocateED();
3441: pED->pVirtualNext = nil;
3442: // make ED and FA = 0
3443: pTD = OHCIUIMAllocateTD();
3444: pED->dWord2 = EndianSwap32Bit ((UInt32) pTD->pPhysical);
3445: pTD->dWord2 = pED->dWord1;
3446: pTD->pEndpoint = (UInt32) pED;
3447: pTD->pType = kOHCIOptiLSBug;
3448: pED->dWord1 = EndianSwap32Bit ((UInt32) pTD->pPhysical);
3449:
3450: /*
3451: for (j=0; j<0; j++) {
3452: // allocate 4 TDs
3453: pTD = OHCIUIMAllocateTD();
3454: pTD->dWord2 = pED->dWord2;
3455: pED->dWord2 = EndianSwap32Bit ((UInt32) pTD->pPhysical);
3456: // leave 1 all zeros
3457: // make other all zeros except next TD
3458: // mark each to indicate that its this type
3459: pTD->pType = kOHCIOptiLSBug;
3460: }
3461: */
3462: pED->dWord3 = pIsochHead->dWord3;
3463: pIsochHead->dWord3 = EndianSwap32Bit((UInt32) pED->pPhysical);
3464: pIsochHead = pED;
3465: }
3466: }
3467:
3468:
3469:
3470: OSStatus OptiLSHSFix()
3471: {
3472:
3473: // Do Opti Errata stuff here!!!!!!
3474: int i;
3475: OHCIIntHeadPtr pInterruptHead;
3476: OHCIEndpointDescriptorPtr pControlED;
3477: OHCIRegistersPtr pOHCIRegisters;
3478: OSStatus status = noErr;
3479:
3480: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
3481:
3482: pOHCIUIMData->OptiOn = 1;
3483:
3484: //Turn off list processing
3485: pOHCIRegisters->hcControl =
3486: EndianSwapImm32Bit
3487: (kOHCIFunctionalState_Operational << kOHCIHcControl_HCFSPhase);
3488:
3489: // wait a millisecond
3490: DelayForHardware(DurationToAbsolute(1*durationMillisecond));
3491:
3492: pInterruptHead = pOHCIUIMData->pInterruptHead;
3493:
3494: // add dummy EDs to 8ms interrupts
3495: for ( i = 0; i< 8; i++)
3496: DoOptiFix(pInterruptHead[48 + i].pHead);
3497: // DoOptiFix((OHCIEndpointDescriptorPtr) pOHCIUIMData->pIsochHead);
3498:
3499: //Assign Tail of Control to point to head of Bulk
3500:
3501: pControlED = (OHCIEndpointDescriptorPtr) pOHCIUIMData->pControlTail;
3502: pControlED->dWord3 = pOHCIRegisters->hcBulkHeadED;
3503:
3504: // add dummy EDs to end of Control
3505: DoOptiFix( (OHCIEndpointDescriptorPtr) pOHCIUIMData->pControlTail);
3506:
3507: // turn on only control and periodic
3508: pOHCIRegisters->hcControl =
3509: EndianSwapImm32Bit
3510: ((kOHCIFunctionalState_Operational << kOHCIHcControl_HCFSPhase) |
3511: kOHCIHcControl_CLE | kOHCIHcControl_PLE | kOHCIHcControl_IE);
3512:
3513: //End of Opti Fix
3514: return (status);
3515: }
3516:
3517:
3518:
3519:
3520:
3521:
3522: /*******************************************************************
3523: Function: AmIThisMachine()
3524: Purpose: check to see if we're the machine that's name is passed in
3525: Params: Name of computer to check for
3526: Returns: Returns back true if this machine's name is that which is
3527: passed in.
3528: *******************************************************************/
3529: Boolean AmIThisMachine(Str255 inMachineNameStr)
3530: {
3531: RegEntryID foundEntry;
3532: RegPropertyName* propertyName = "model";
3533: RegPropertyName* realPropertyName = "compatible";
3534: Str31 kiMacMachineName = "iMac,1";
3535: RegPropertyValueSize propertySize;
3536: Ptr modelNamePropertyStrPtr;
3537: OSStatus result;
3538: long nameRegistryVersion;
3539: OSErr theErr;
3540: Boolean isThatMachine = false;
3541:
3542:
3543:
3544: // Does the name registry exist?
3545: //naga theErr = Gestalt(gestaltNameRegistryVersion, &nameRegistryVersion);
3546: if( theErr == noErr )
3547: {
3548: // Can we find the "root" node of the device-tree?
3549: theErr = RegistryCStrEntryLookup(nil, "Devices:device-tree",
3550: &foundEntry);
3551: }
3552:
3553: if( theErr == noErr )
3554: {
3555: if( CompareString(inMachineNameStr, kiMacMachineName, NULL) == 0 )
3556: {
3557: // Does the "model" property exist? And if so, how big is it?
3558: result = RegistryPropertyGetSize(&foundEntry, propertyName, &propertySize);
3559:
3560: if( result == noErr )
3561: {
3562: modelNamePropertyStrPtr = usb_NewPtr(propertySize);
3563: if( modelNamePropertyStrPtr )
3564: {
3565: result = RegistryPropertyGet(&foundEntry, propertyName,
3566: modelNamePropertyStrPtr, &propertySize);
3567:
3568: if( result == noErr )
3569: {
3570: c2pstr( modelNamePropertyStrPtr );
3571: if( CompareString( inMachineNameStr, (unsigned char
3572: *)modelNamePropertyStrPtr, NULL ) == 0 )
3573: isThatMachine = true;
3574: }
3575: usb_DisposePtr( modelNamePropertyStrPtr );
3576: }
3577: }
3578: }
3579: else
3580: {
3581:
3582: // Does the "compatible" property exist? And if so, how big is it?
3583: result = RegistryPropertyGetSize(&foundEntry, realPropertyName, &propertySize);
3584:
3585: if( result == noErr )
3586: {
3587: modelNamePropertyStrPtr = usb_NewPtr(propertySize);
3588: if( modelNamePropertyStrPtr )
3589: {
3590: result = RegistryPropertyGet(&foundEntry, realPropertyName, modelNamePropertyStrPtr, &propertySize);
3591:
3592: if( result == noErr )
3593: {
3594: c2pstr( modelNamePropertyStrPtr );
3595: if( CompareString( inMachineNameStr, (unsigned char *)modelNamePropertyStrPtr, NULL ) == 0 )
3596: isThatMachine = true;
3597: else
3598: {
3599: UInt16 modelNameLength = modelNamePropertyStrPtr[0];
3600: c2pstr( &(modelNamePropertyStrPtr[++modelNameLength]) );
3601: if( modelNamePropertyStrPtr[modelNameLength] != 0 )
3602: if( CompareString( inMachineNameStr, (unsigned char *)&(modelNamePropertyStrPtr[ modelNameLength ]), NULL ) == 0 )
3603: isThatMachine = true;
3604: }
3605: }
3606: usb_DisposePtr( modelNamePropertyStrPtr );
3607: }
3608: }
3609: }
3610:
3611:
3612: if ((result = RegistryEntryIDDispose(&foundEntry)) != noErr)
3613: return(false);
3614: }
3615:
3616: return(isThatMachine);
3617: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.