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