|
|
1.1 root 1: /*
2: * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /*
23: * Copyright (c) 1998 Apple Computer, Inc. All rights reserved.
24: *
25: * HISTORY
26: *
27: */
28:
29: #include <libkern/OSByteOrder.h>
30: #include <IOKit/IOMemoryCursor.h>
31:
32: #include "AppleOHCI.h"
33: #include <IOKit/usb/USB.h>
34:
35: #define DEBUGGING_LEVEL 0 // 1 = low; 2 = high; 3 = extreme
36: #define DEBUGLOG kprintf
37: #define nil (0)
38:
39: #define super IOUSBController
40: #define self this
41:
42: #define NUM_BUFFER_PAGES 9 // 54
43: #define NUM_TDS 255 // 1500
44: #define NUM_EDS 256 // 1500
45: #define NUM_ITDS 192 // 1300
46:
47: // TDs per page == 85
48: // EDs per page == 128
49: // ITDs per page == 64
50:
51: static int GetEDType(OHCIEndpointDescriptorPtr pED);
52: static void ProcessCompletedITD (OHCIIsochTransferDescriptorPtr pITD, IOReturn status);
53: extern void print_td(OHCIGeneralTransferDescriptorPtr pTD);
54: extern void print_itd(OHCIIsochTransferDescriptorPtr x);
55:
56: static IOReturn TranslateStatusToUSBError(UInt32 status);
57:
58: OSDefineMetaClassAndStructors(AppleOHCI, IOUSBController)
59:
60: bool AppleOHCI::init(OSDictionary * propTable)
61: {
62: if (!super::init(propTable)) return false;
63:
64: _intLock = IOLockAlloc();
65: if (!_intLock)
66: return(false);
67:
68: pOHCIUIMData = (OHCIUIMDataPtr) IOMalloc(sizeof(OHCIUIMData));
69: if (!pOHCIUIMData)
70: {
71: IOLog("%s: Unable to allocate memory (1)\n", getName());
72: return(false);
73: }
74: bzero( pOHCIUIMData, sizeof(OHCIUIMData));
75:
76: return (true);
77: }
78:
79: void AppleOHCI::SetVendorInfo(void)
80: {
81: OSData *vendProp, *deviceProp, *revisionProp;
82:
83: // get this chips vendID, deviceID, revisionID
84: vendProp = (OSData *) _device->getProperty( "vendor-id" );
85: if (vendProp)
86: _vendorID = *((UInt32 *) vendProp->getBytesNoCopy());
87: deviceProp = (OSData *) _device->getProperty( "device-id" );
88: if (deviceProp)
89: _deviceID = *((UInt32 *) deviceProp->getBytesNoCopy());
90: revisionProp = (OSData *) _device->getProperty( "revision-id" );
91: if (revisionProp)
92: _revisionID = *((UInt32 *) revisionProp->getBytesNoCopy());
93: }
94:
95: IOReturn AppleOHCI::UIMInitialize(IOService * provider)
96: {
97: /* UInt16 ivalue, ivalue2; */
98: IOReturn err = 0;
99: OHCIRegistersPtr pOHCIRegisters;
100: UInt32 lvalue;
101:
102: #if (DEBUGGING_LEVEL > 0)
103: IOLog("%s: initializing UIM\n", getName());
104: #endif
105:
106: _device = OSDynamicCast(IOPCIDevice, provider);
107: if(_device == NULL)
108: return kIOReturnBadArgument;
109:
110: do {
111:
112: if (!(_deviceBase = provider->mapDeviceMemoryWithIndex(0)))
113: {
114: IOLog("%s: unable to get device memory\n", getName());
115: break;
116: }
117:
118: IOLog("%s: config @ %lx (%lx)\n", getName(),
119: _deviceBase->getVirtualAddress(),
120: _deviceBase->getPhysicalAddress());
121:
122: SetVendorInfo();
123:
124: interruptSource = IOInterruptEventSource::
125: interruptEventSource(this, &OHCIUIMInterruptHandler, _device);
126: if (!interruptSource
127: || (_workLoop->addEventSource(interruptSource) != kIOReturnSuccess))
128: continue;
129:
130: _genCursor =
131: IONaturalMemoryCursor::withSpecification(PAGE_SIZE, PAGE_SIZE);
132: if(!_genCursor)
133: continue;
134:
135: _isoCursor =
136: IONaturalMemoryCursor::withSpecification(kUSBMaxIsocFrameReqCount,
137: kUSBMaxIsocFrameReqCount);
138: if(!_isoCursor)
139: continue;
140:
141: /*
142: * Initialize my data and the hardware
143: */
144: pOHCIUIMData->errataBits = GetErrataBits(_vendorID, _deviceID, _revisionID);
145:
146: #if (DEBUGGING_LEVEL > 0)
147: IOLog("%s: errata bits=%lx\n", getName(), pOHCIUIMData->errataBits);
148: #endif
149: pOHCIUIMData->pageSize = PAGE_SIZE;
150: pOHCIUIMData->pOHCIRegisters = pOHCIRegisters =
151: (OHCIRegistersPtr) _deviceBase->getVirtualAddress();
152:
153: #if (DEBUGGING_LEVEL > 2)
154: dumpRegs();
155: #endif
156:
157: // enable the card
158: lvalue = _device->configRead32(cwCommand);
159: _device->configWrite32(cwCommand, (lvalue & 0xffff0000) |
160: (cwCommandEnableBusMaster |
161: cwCommandEnableMemorySpace));
162:
163: // Allocate TDs, EDs; FIXME get real numbers to use, CPU specific.
164: if ((err = OHCIUIMAllocateMemory(NUM_TDS, NUM_EDS, NUM_ITDS)))
165: continue;
166:
167: pOHCIRegisters->hcControlCurrentED = 0;
168: pOHCIRegisters->hcControlHeadED = 0;
169: pOHCIRegisters->hcDoneHead = 0;
170: IOSync();
171:
172: // Set up HCCA.
173: IOPhysicalAddress physAddr;
174: pOHCIUIMData->pHCCA = (Ptr) IOMallocContiguous(kHCCAsize, kHCCAalignment, &physAddr);
175: if (!pOHCIUIMData->pHCCA)
176: {
177: IOLog("%s: Unable to allocate memory (2)\n", getName());
178: err = kIOReturnNoMemory;
179: continue;
180: }
181:
182: OSWriteLittleInt32(&pOHCIRegisters->hcHCCA, 0, physAddr);
183: IOSync();
184:
185: // Set the HC to write the donehead to the HCCA, and enable interrupts
186: pOHCIRegisters->hcInterruptStatus = OSSwapInt32(kOHCIHcInterrupt_WDH);
187: IOSync();
188:
189: // Enable the interrupt delivery.
190: _workLoop->enableAllInterrupts();
191:
192: // Initialize the Root Hub registers
193: OHCIRootHubPower(1 /* kOn */);
194: IOSync();
195: pOHCIUIMData->rootHubFuncAddress = 1;
196:
197: // set up Interrupt transfer tree
198: if ((err = OHCIUIMIsochronousInitialize())) continue;
199: if ((err = OHCIUIMInterruptInitialize())) continue;
200: if ((err = OHCIUIMBulkInitialize())) continue;
201: if ((err = OHCIUIMControlInitialize())) continue;
202:
203: // Set up hcFmInterval.
204: UInt32 hcFSMPS; // in register hcFmInterval
205: UInt32 hcFI; // in register hcFmInterval
206: UInt32 hcPS; // in register hcPeriodicStart
207:
208: hcFI = OSReadLittleInt32(&pOHCIRegisters->hcFmInterval, 0) & kOHCIHcFmInterval_FI;
209: // this formula is from the OHCI spec, section 5.4
210: hcFSMPS = ((((hcFI-kOHCIMax_OverHead) * 6)/7) << kOHCIHcFmInterval_FSMPSPhase);
211: hcPS = (hcFI * 9) / 10; // per spec- 90%
212: OSWriteLittleInt32(&pOHCIRegisters->hcFmInterval, 0, hcFI | hcFSMPS);
213: OSWriteLittleInt32(&pOHCIRegisters->hcPeriodicStart, 0, hcPS);
214:
215: IOSync();
216:
217:
218: // Just so we all start from the same place, reset the OHCI.
219: pOHCIRegisters->hcControl =
220: OSSwapInt32 ((kOHCIFunctionalState_Reset
221: << kOHCIHcControl_HCFSPhase));
222: IOSync();
223:
224: // Set OHCI to operational state and enable processing of control list.
225: pOHCIRegisters->hcControl =
226: OSSwapInt32 ((kOHCIFunctionalState_Operational
227: << kOHCIHcControl_HCFSPhase)
228: | kOHCIHcControl_CLE | kOHCIHcControl_BLE
229: | kOHCIHcControl_PLE | kOHCIHcControl_IE);
230: IOSync();
231:
232: pOHCIRegisters->hcInterruptEnable =
233: OSSwapInt32 (kOHCIHcInterrupt_MIE | kOHCIDefaultInterrupts);
234: IOSync();
235:
236: if (pOHCIUIMData->errataBits & kErrataLSHSOpti)
237: OptiLSHSFix();
238:
239: //naga (*pOHCIUIMData->interruptEnabler)(pOHCIUIMData->interruptSetMember, nil);
240:
241: return(kIOReturnSuccess);
242:
243: } while (false);
244:
245: IOLog("%s: Error occurred (%d)\n", getName(), err);
246: UIMFinalize();
247:
248: if (interruptSource) interruptSource->release();
249:
250: return(err);
251: }
252:
253: IOReturn AppleOHCI::UIMFinalize(void)
254: {
255: OHCIRegistersPtr pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
256:
257:
258: IOLog ("UIMFinalize (shutting down HW)\n");
259:
260: // Disable All OHCI Interrupts
261: pOHCIRegisters->hcInterruptDisable = kOHCIHcInterrupt_MIE;
262: IOSync();
263:
264: // Place the USB bus into the Reset State
265: pOHCIRegisters->hcControl = OSSwapInt32((kOHCIFunctionalState_Reset
266: << kOHCIHcControl_HCFSPhase));
267: IOSync();
268:
269: // need to wait at least 1ms here
270: IOSleep(2);
271:
272: // Take away the controllers ability be a bus master.
273: _device->configWrite32(cwCommand, cwCommandEnableMemorySpace);
274:
275: // Clear all Processing Registers
276: pOHCIRegisters->hcHCCA = 0;
277: pOHCIRegisters->hcPeriodCurrentED = 0;
278: pOHCIRegisters->hcControlHeadED = 0;
279: pOHCIRegisters->hcControlCurrentED = 0;
280: pOHCIRegisters->hcBulkHeadED = 0;
281: pOHCIRegisters->hcBulkCurrentED = 0;
282: pOHCIRegisters->hcDoneHead = 0;
283: IOSync();
284:
285: // turn off the global power
286: // FIXME check for per-port vs. Global power control
287: OHCIRootHubPower(0 /* kOff */);
288: IOSync();
289:
290: //status = OHCIUIMFinalizeOHCIUIMData ((OHCIUIMDataPtr) pOHCIUIMData);
291:
292: IOLog("OHCIUIMFinalize Exit\n");
293:
294: return(kIOReturnSuccess);
295: }
296:
297: /*
298: * got an error on a TD with no completion routine.
299: * Search for a later TD on the same end point which does have one,
300: * so we can tell upper layes of the error.
301: */
302: void AppleOHCI::doCallback(OHCIGeneralTransferDescriptorPtr nextTD,
303: UInt32 transferStatus,
304: UInt32 bufferSizeRemaining)
305: {
306: OHCIGeneralTransferDescriptorPtr pCurrentTD;
307: OHCIEndpointDescriptorPtr pED;
308: UInt32 PhysAddr;
309:
310: pED = (OHCIEndpointDescriptorPtr) nextTD->pEndpoint;
311:
312: PhysAddr = (UInt32) OSSwapInt32(pED->tdQueueHeadPtr) & kOHCIHeadPMask;
313: nextTD = (OHCIGeneralTransferDescriptorPtr) OHCIUIMGetLogicalAddress(PhysAddr);
314:
315: pCurrentTD = nextTD;
316: if(pCurrentTD == nil) {
317: IOLog("No transfer descriptors in AppleOHCI::doCallback!\n");
318: return;
319: }
320: while (pCurrentTD->pLogicalNext != nil)
321: {
322: bufferSizeRemaining += findBufferRemaining (pCurrentTD);
323:
324: // make sure this TD won't be added to any future buffer
325: // remaining calculations
326: pCurrentTD->currentBufferPtr = 0;
327:
328: //ERICif (pCurrentTD->preparationID)
329: //ERIC CheckpointIO(pCurrentTD->preparationID, nil);
330: // make sure we don't try to do another CheckpointIO later
331: //ERICpCurrentTD->preparationID = nil;
332:
333: if (pCurrentTD->completion.action != nil)
334: {
335: IOUSBCompletion completion;
336: // zero out callback first then call it
337: completion = pCurrentTD->completion;
338: pCurrentTD->completion.action = nil;
339: complete(completion,
340: TranslateStatusToUSBError(transferStatus),
341: bufferSizeRemaining);
342: bufferSizeRemaining = 0;
343: return;
344: }
345:
346: pCurrentTD = pCurrentTD->pLogicalNext;
347: }
348: }
349:
350: // FIXME add page size to param list
351: UInt32 AppleOHCI::findBufferRemaining (OHCIGeneralTransferDescriptorPtr pCurrentTD)
352: {
353: UInt32 pageSize;
354: UInt32 pageMask;
355: UInt32 bufferSizeRemaining;
356:
357:
358: pageSize = pOHCIUIMData->pageSize;
359: pageMask = ~(pageSize - 1);
360:
361: if (pCurrentTD->currentBufferPtr == 0)
362: {
363: bufferSizeRemaining = 0;
364: }
365: else if ((OSSwapInt32(pCurrentTD->bufferEnd) & (pageMask)) ==
366: (OSSwapInt32(pCurrentTD->currentBufferPtr)& (pageMask)))
367: {
368: // we're on the same page
369: bufferSizeRemaining =
370: (OSSwapInt32 (pCurrentTD->bufferEnd) & ~pageMask) -
371: (OSSwapInt32 (pCurrentTD->currentBufferPtr) & ~pageMask) + 1;
372: }
373: else
374: {
375: bufferSizeRemaining =
376: ((OSSwapInt32(pCurrentTD->bufferEnd) & ~pageMask) + 1) +
377: (pageSize - (OSSwapInt32(pCurrentTD->currentBufferPtr) & ~pageMask));
378: }
379:
380: return (bufferSizeRemaining);
381: }
382:
383:
384: IOReturn AppleOHCI::OHCIUIMControlInitialize(void)
385: {
386: OHCIRegistersPtr pOHCIRegisters;
387: OHCIEndpointDescriptorPtr pED, pED2;
388:
389:
390: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
391:
392: // Create ED mark it skipped and assign it to ControlTail
393: pED = OHCIUIMAllocateED();
394: pED->flags = OSSwapInt32 (kOHCIEDControl_K);
395: pED->nextED = 0; // End of list
396:
397: pOHCIUIMData->pControlTail = (UInt32) pED;
398:
399: // Create ED mark it skipped and assign it to control head
400: pED2 = OHCIUIMAllocateED();
401: pED2->flags = OSSwapInt32 (kOHCIEDControl_K);
402: pOHCIUIMData->pControlHead = (UInt32) pED2;
403: pOHCIRegisters->hcControlHeadED = OSSwapInt32 ((UInt32) pED2->pPhysical);
404:
405: // have bulk head ED point to Control tail ED
406: pED2->nextED = OSSwapInt32 ((UInt32) pED->pPhysical);
407: pED2->pLogicalNext = pED;
408: return (kIOReturnSuccess);
409: }
410:
411: IOReturn AppleOHCI::OHCIUIMBulkInitialize (void)
412: {
413: OHCIRegistersPtr pOHCIRegisters;
414: OHCIEndpointDescriptorPtr pED, pED2;
415:
416: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
417:
418: // Create ED mark it skipped and assign it to bulkTail
419: pED = OHCIUIMAllocateED();
420: pED->flags = OSSwapInt32 (kOHCIEDControl_K);
421: pED->nextED = 0; // End of list
422: pOHCIUIMData->pBulkTail = (UInt32) pED;
423:
424: // Create ED mark it skipped and assign it to bulk head
425: pED2 = OHCIUIMAllocateED();
426: pED2->flags = OSSwapInt32 (kOHCIEDControl_K);
427: pOHCIUIMData->pBulkHead = (UInt32) pED2;
428: pOHCIRegisters->hcBulkHeadED = OSSwapInt32 ((UInt32) pED2->pPhysical);
429:
430: // have bulk head ED point to Bulk tail ED
431: pED2->nextED = OSSwapInt32 ((UInt32) pED->pPhysical);
432: pED2->pLogicalNext = pED;
433: return (kIOReturnSuccess);
434:
435: }
436:
437: IOReturn AppleOHCI::OHCIUIMIsochronousInitialize(void)
438: {
439: OHCIRegistersPtr pOHCIRegisters;
440: OHCIEndpointDescriptorPtr pED, pED2;
441:
442:
443: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
444:
445: // Create ED mark it skipped and assign it to isoch Tail
446: pED = OHCIUIMAllocateED();
447: pED->flags = OSSwapInt32 (kOHCIEDControl_K);
448: pED->nextED = 0; // End of list
449: pOHCIUIMData->pIsochTail = (UInt32) pED;
450:
451: // Create ED mark it skipped and assign it to isoch head
452: pED2 = OHCIUIMAllocateED();
453: pED2->flags = OSSwapInt32 (kOHCIEDControl_K);
454: pOHCIUIMData->pIsochHead = (UInt32) pED2;
455:
456:
457: // have iso head ED point to iso tail ED
458: pED2->nextED = OSSwapInt32 ((UInt32) pED->pPhysical);
459: pED2->pLogicalNext = pED;
460: pOHCIUIMData->isochBandwidthAvail = kUSBMaxIsocFrameReqCount;
461:
462: return (kIOReturnSuccess);
463: }
464:
465: //Initializes the HCCA Interrupt list with statically
466: //disabled ED's to form the Interrupt polling queues
467: IOReturn AppleOHCI::OHCIUIMInterruptInitialize (void)
468: {
469: OHCIRegistersPtr pOHCIRegisters;
470: OHCIIntHeadPtr pInterruptHead;
471: IOReturn status = 0;
472: UInt32 dummyControl;
473: int i, p, q, z;
474: OHCIEndpointDescriptorPtr pED, pIsochHead;
475:
476:
477: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
478: pInterruptHead = pOHCIUIMData->pInterruptHead;
479:
480: // create UInt32 with same dword0 for use with searching and
481: // tracking, skip should be set, and open area should be marked
482: dummyControl = kOHCIEDControl_K;
483: dummyControl |= 0; //should be kOHCIFakeED
484: dummyControl = OSSwapInt32 (dummyControl);
485: pIsochHead = (OHCIEndpointDescriptorPtr) pOHCIUIMData->pIsochHead;
486:
487: // do 31 times
488: // change to 65 and make isoch head the last one.?????
489: for (i = 0; i < 63; i++)
490: {
491: // allocate Endpoint descriptor
492: pED = OHCIUIMAllocateED();
493: if (pED == nil)
494: {
495: return (kIOReturnNoMemory);
496: }
497: // mark skipped,some how mark as a False endpoint zzzzz
498: else
499: {
500: pED->flags = dummyControl;
501: pED->nextED = 0; // End of list
502: pInterruptHead[i].pHead = pED;
503: pInterruptHead[i].pHeadPhysical = pED->pPhysical;
504: pInterruptHead[i].nodeBandwidth = 0;
505: }
506:
507: if (i < 32)
508: ((UInt32 *)pOHCIUIMData->pHCCA)[i] =
509: (UInt32) OSSwapInt32 ((UInt32) pInterruptHead[i].pHeadPhysical);
510: }
511:
512: p = 0;
513: q = 32;
514: // FIXME? ERIC
515: for (i = 0; i < (32 +16 + 8 + 4 + 2); i++)
516: {
517: if (i < q/2+p)
518: z = i + q;
519: else
520: z = i + q/2;
521: if (i == p+q-1)
522: {
523: p = p + q;
524: q = q/2;
525: }
526: // point endpoint descriptor to corresponding 8ms descriptor
527: pED = pInterruptHead[i].pHead;
528: pED->nextED = OSSwapInt32 (pInterruptHead[z].pHeadPhysical);
529: pED->pLogicalNext = pInterruptHead[z].pHead;
530: pInterruptHead[i].pTail = (OHCIEndpointDescriptorPtr) pED->pLogicalNext;
531: }
532: i = 62;
533: pED = pInterruptHead[i].pHead;
534: pED->nextED = OSSwapInt32 (pIsochHead->pPhysical);
535: pED->pLogicalNext = pOHCIUIMData->pIsochHead;
536: pInterruptHead[i].pTail = (OHCIEndpointDescriptorPtr) pED->pLogicalNext;
537:
538: // point Isochronous head to last endpoint
539: return (status);
540: }
541:
542: ////////////////////////////////////////////////////////////////////////////////
543: //
544: // UInt32 OHCIUIMGetLogicalAddress
545: // Given the physical address, return the virtual address
546: //
547:
548: UInt32 AppleOHCI::OHCIUIMGetLogicalAddress (UInt32 pPhysicalAddress)
549: {
550: OHCIPhysicalLogicalPtr pPhysicalLogical;
551: UInt32 LogicalAddress = nil;
552:
553: if (pPhysicalAddress == 0)
554: return(0);
555:
556: pPhysicalLogical = pOHCIUIMData->pPhysicalLogical;
557:
558: while (pPhysicalLogical != nil) {
559: if (pPhysicalAddress <= pPhysicalLogical->PhysicalEnd
560: && pPhysicalAddress >= pPhysicalLogical->PhysicalStart)
561: {
562: LogicalAddress = pPhysicalLogical->LogicalStart +
563: (pPhysicalAddress - pPhysicalLogical->PhysicalStart);
564: pPhysicalLogical = nil;
565: } else {
566: pPhysicalLogical = (OHCIPhysicalLogicalPtr) pPhysicalLogical->pNext;
567: }
568: }
569:
570: if ( LogicalAddress == nil)
571: IOLog("OHCIUIM: LogicalAddress(0x%lx) == nil !\n", pPhysicalAddress);
572:
573: return (LogicalAddress);
574:
575: }
576:
577:
578: UInt32 AppleOHCI::OHCIUIMGetPhysicalAddress(UInt32 LogicalAddress,
579: UInt32 count)
580: {
581: OHCIPhysicalLogicalPtr pPhysicalLogical;
582: UInt32 PhysicalAddress = nil;
583:
584: if (LogicalAddress == 0)
585: return(0);
586:
587: pPhysicalLogical = pOHCIUIMData->pPhysicalLogical;
588:
589: while (pPhysicalLogical != nil) {
590: if (LogicalAddress <= pPhysicalLogical->LogicalEnd
591: && LogicalAddress >= pPhysicalLogical->LogicalStart)
592: {
593: PhysicalAddress = pPhysicalLogical->PhysicalStart
594: + (LogicalAddress - pPhysicalLogical->LogicalStart);
595: pPhysicalLogical = nil;
596: } else {
597: pPhysicalLogical = pPhysicalLogical->pNext;
598: }
599: }
600:
601: if (PhysicalAddress == nil)
602: PhysicalAddress = OHCIUIMCreatePhysicalAddress(LogicalAddress, count);
603:
604: return (PhysicalAddress);
605: }
606:
607: /*
608: * OHCIUIMCreatePhysicalAddress:
609: * Currently this function only creates a one entry OHCIPhysicalLogical
610: * entry. This is because it is assuming contiguous memory.
611: *
612: */
613: UInt32 AppleOHCI::OHCIUIMCreatePhysicalAddress(UInt32 pLogicalAddress,
614: UInt32 count)
615:
616: {
617: UInt32 pageSize;
618: OHCIPhysicalLogicalPtr pPhysicalLogical;
619: OHCIPhysicalLogicalPtr p;
620:
621: pPhysicalLogical = pOHCIUIMData->pPhysicalLogical;
622: pageSize = pOHCIUIMData->pageSize;
623:
624: // zzz do we deallocate this?
625: p = (OHCIPhysicalLogicalPtr) IOMalloc(sizeof (OHCIPhysicalLogical));
626:
627: p->LogicalStart = pLogicalAddress;
628: p->PhysicalStart = kvtophys((vm_offset_t)pLogicalAddress);
629: p->LogicalEnd = p->LogicalStart + count * pageSize-1;
630: p->PhysicalEnd = p->PhysicalStart + count * pageSize-1;
631: p->pNext = pOHCIUIMData->pPhysicalLogical;
632:
633: pOHCIUIMData->pPhysicalLogical = p;
634:
635: return (p->PhysicalStart);
636: }
637:
638: //Allocate
639: IOReturn AppleOHCI::OHCIUIMAllocateMemory (int num_of_TDs,
640: int num_of_EDs,
641: int num_of_ITDs)
642: {
643: Ptr p;
644: UInt32 physical;
645: int tdsPerPage, pagesTD,
646: edsPerPage, pagesED,
647: itdsPerPage, pagesITD;
648: UInt32 pageSize;
649: OHCIEndpointDescriptorPtr FreeED, FreeEDCurrent;
650: OHCIGeneralTransferDescriptorPtr FreeTD, FreeTDCurrent;
651: OHCIIsochTransferDescriptorPtr FreeITD, FreeITDCurrent;
652: int i,j;
653:
654:
655: pageSize = pOHCIUIMData->pageSize;
656:
657: tdsPerPage = pageSize / sizeof (OHCIGeneralTransferDescriptor);
658: pagesTD = (num_of_TDs + (tdsPerPage - 1)) / tdsPerPage;
659: edsPerPage = pageSize / sizeof (OHCIEndpointDescriptor);
660: pagesED = (num_of_EDs + (edsPerPage - 1)) / edsPerPage;
661: itdsPerPage = pageSize / sizeof (OHCIIsochTransferDescriptor);
662: pagesITD = (num_of_ITDs + (itdsPerPage - 1)) / itdsPerPage;
663:
664: p = (Ptr)IOMalloc( (pagesED + pagesTD + pagesITD + 1) * pageSize);
665:
666: if (!p)
667: return(kIOReturnNoMemory);
668:
669: for(i=0; i<(pagesED + pagesTD + pagesITD + 1) * pageSize/4; i++)
670: ((UInt32 *)p)[i] = 0x12345678;
671: // bzero(p, ((pagesED + pagesTD + pagesITD + 1) * pageSize));
672:
673: pOHCIUIMData->pDataAllocation = p;
674: // page align and 16 byte align (page align automagically
675: // makes it 16 byte aligned)
676: p = (Ptr) (((UInt32) p + (pageSize - 1)) & ~(pageSize - 1));
677: //bzero(p, ((pagesED) * pageSize));
678:
679:
680: // create a list of unused ED's, filling in Virtual address,
681: // physicaladdress and virtual next physical next.
682: FreeED = (OHCIEndpointDescriptorPtr) p;
683: FreeEDCurrent = FreeED;
684: pOHCIUIMData->pFreeED = FreeED;
685:
686: for (i = 0 ; i < pagesED ; i++)
687: {
688: physical = kvtophys(FreeEDCurrent);
689: for (j = 0; j < edsPerPage; j++)
690: {
691: // create EDs
692: FreeEDCurrent[j].pPhysical =
693: physical + (j * sizeof (OHCIEndpointDescriptor));
694: FreeEDCurrent[j].pLogicalNext = (&FreeEDCurrent[j+1]);
695: }
696: if (i != (pagesED - 1))
697: {
698: FreeEDCurrent[j-1].pLogicalNext = ((UInt32) FreeEDCurrent + pageSize);
699: }
700: else
701: {
702: FreeEDCurrent[j-1].pLogicalNext = nil;
703: pOHCIUIMData->pLastFreeED = &FreeEDCurrent[j-1];
704: }
705:
706: // goto next page
707: FreeEDCurrent = (OHCIEndpointDescriptorPtr)
708: ((UInt32) FreeEDCurrent + pageSize);
709: //physical += pageSize;
710: }
711:
712: FreeTD = (OHCIGeneralTransferDescriptorPtr) FreeEDCurrent;
713: FreeTDCurrent = FreeTD;
714: pOHCIUIMData->pFreeTD = FreeTD;
715: for (i = 0; i < pagesTD; i++)
716: {
717: physical = OHCIUIMGetPhysicalAddress((UInt32) FreeTDCurrent, 1);
718: for (j = 0; j < tdsPerPage; j++)
719: {
720: //create TDs
721: FreeTDCurrent[j].pPhysical =
722: physical + (j * sizeof (OHCIGeneralTransferDescriptor));
723: FreeTDCurrent[j].pLogicalNext = (UInt32) (&FreeTDCurrent[j+1]);
724: }
725: if (i != (pagesTD - 1))
726: {
727: FreeTDCurrent[j-1].pLogicalNext = ((UInt32) FreeTDCurrent + pageSize);
728: }
729: else
730: {
731: FreeTDCurrent[j-1].pLogicalNext = nil;
732: pOHCIUIMData->pLastFreeTD = &FreeTDCurrent[j-1];
733: }
734:
735: // goto next page
736: FreeTDCurrent = (OHCIGeneralTransferDescriptorPtr)
737: ((UInt32) FreeTDCurrent + pageSize);
738: //physical += pageSize;
739: }
740:
741: // set up freeitd queue
742: FreeITD = (OHCIIsochTransferDescriptorPtr) FreeTDCurrent;
743: FreeITDCurrent = FreeITD;
744: pOHCIUIMData->pFreeITD = FreeITD;
745: for (i = 0; i < pagesITD; i++)
746: {
747: //physical = kvtophys(FreeITDCurrent);
748: physical = OHCIUIMGetPhysicalAddress((UInt32) FreeITDCurrent, 1);
749: for (j = 0; j < itdsPerPage; j++)
750: {
751: // create TDs
752: FreeITDCurrent[j].pPhysical =
753: physical + (j * sizeof (OHCIIsochTransferDescriptor));
754: FreeITDCurrent[j].pLogicalNext = (&FreeITDCurrent[j+1]);
755: }
756: if (i != (pagesITD - 1))
757: {
758: FreeITDCurrent[j-1].pLogicalNext =
759: (OHCIIsochTransferDescriptorPtr)((UInt32) FreeITDCurrent + pageSize);
760: }
761: else
762: {
763: FreeITDCurrent[j-1].pLogicalNext = nil;
764: pOHCIUIMData->pLastFreeITD = &FreeITDCurrent[j-1];
765: }
766:
767: // goto next page
768: FreeITDCurrent = (OHCIIsochTransferDescriptorPtr)
769: ((UInt32) FreeITDCurrent + pageSize);
770: //physical += pageSize;
771: }
772:
773: // create a list of unused buffers?????
774:
775: return (kIOReturnSuccess);
776: }
777:
778: OHCIIsochTransferDescriptorPtr AppleOHCI::OHCIUIMAllocateITD(void)
779: {
780: OHCIIsochTransferDescriptorPtr temp;
781:
782: // pop a TD off of FreeTD list
783: // if FreeTD == NIL return nil
784: // should we check if ED is full and if not access that????
785: temp = pOHCIUIMData->pFreeITD;
786:
787: if (temp != nil)
788: {
789: pOHCIUIMData->pFreeITD = temp->pLogicalNext;
790: }
791: else
792: {
793: IOLog("%s: Out of Isoch Transfer Descriptors!\n", getName());
794: return nil;
795: }
796:
797: temp->pLogicalNext = nil;
798:
799: return (temp);
800: }
801:
802: OHCIGeneralTransferDescriptorPtr AppleOHCI::OHCIUIMAllocateTD(void)
803:
804: {
805: OHCIGeneralTransferDescriptorPtr freeTD;
806:
807: // pop a TD off of FreeTD list
808: //if FreeTD == NIL return nil
809: // should we check if ED is full and if not access that????
810: freeTD = pOHCIUIMData->pFreeTD;
811:
812: if (freeTD == nil)
813: {
814: int j;
815: int tdsPerPage;
816: UInt32 physical;
817: OHCIGeneralTransferDescriptorPtr FreeTDCurrent;
818: UInt8 * p = (UInt8 *)IOMallocAligned(pOHCIUIMData->pageSize,
819: pOHCIUIMData->pageSize);
820: if(p == NULL) {
821: IOLog("%s: Out of Transfer Descriptors!\n", getName());
822: return NULL;
823: }
824:
825: //bzero(p, pOHCIUIMData->pageSize);
826:
827: tdsPerPage = pOHCIUIMData->pageSize / sizeof (OHCIGeneralTransferDescriptor);
828: pOHCIUIMData->pFreeTD = FreeTDCurrent = (OHCIGeneralTransferDescriptorPtr)p;
829: physical = OHCIUIMGetPhysicalAddress((UInt32) FreeTDCurrent, 1);
830: for (j = 0; j < tdsPerPage-1; j++)
831: {
832: //create TDs
833: FreeTDCurrent[j].pPhysical =
834: physical + (j * sizeof (OHCIGeneralTransferDescriptor));
835: FreeTDCurrent[j].pLogicalNext = &FreeTDCurrent[j+1];
836: }
837: FreeTDCurrent[j].pPhysical =
838: physical + (j * sizeof (OHCIGeneralTransferDescriptor));
839: FreeTDCurrent[j].pLogicalNext = nil;
840: pOHCIUIMData->pLastFreeTD = &FreeTDCurrent[j];
841: freeTD = pOHCIUIMData->pFreeTD;
842: }
843: pOHCIUIMData->pFreeTD = freeTD->pLogicalNext;
844: freeTD->pLogicalNext = nil;
845: return (freeTD);
846: }
847:
848: OHCIEndpointDescriptorPtr AppleOHCI::OHCIUIMAllocateED(void)
849: {
850: OHCIEndpointDescriptorPtr freeED;
851:
852: // Pop a ED off the FreeED list
853: // If FreeED == nil return Error
854: freeED = pOHCIUIMData->pFreeED;
855:
856: if (freeED == nil)
857: {
858: int j;
859: int edsPerPage;
860: UInt32 physical;
861: OHCIEndpointDescriptorPtr FreeEDCurrent;
862: UInt8 * p = (UInt8 *)IOMallocAligned(pOHCIUIMData->pageSize,
863: pOHCIUIMData->pageSize);
864: if(p == NULL)
865: {
866: IOLog("%s: Out of Endpoint Descriptors!\n", getName());
867: return NULL;
868: }
869:
870: //bzero(p, pOHCIUIMData->pageSize);
871:
872: edsPerPage = pOHCIUIMData->pageSize / sizeof (OHCIEndpointDescriptor);
873: physical = kvtophys((vm_offset_t)p);
874: pOHCIUIMData->pFreeED = FreeEDCurrent = (OHCIEndpointDescriptorPtr)p;
875: for (j = 0; j < edsPerPage-1; j++)
876: {
877: // create EDs
878: FreeEDCurrent[j].pPhysical =
879: physical + (j * sizeof (OHCIEndpointDescriptor));
880: FreeEDCurrent[j].pLogicalNext = (&FreeEDCurrent[j+1]);
881: }
882: FreeEDCurrent[j].pPhysical =
883: physical + (j * sizeof (OHCIEndpointDescriptor));
884: FreeEDCurrent[j].pLogicalNext = nil;
885: pOHCIUIMData->pLastFreeED = &FreeEDCurrent[j];
886: freeED = pOHCIUIMData->pFreeED;
887: }
888: pOHCIUIMData->pFreeED = (OHCIEndpointDescriptorPtr) freeED->pLogicalNext;
889: freeED->pLogicalNext = nil;
890: return (freeED);
891: }
892:
893: IOReturn AppleOHCI::OHCIUIMDeallocateITD (OHCIIsochTransferDescriptorPtr pTD)
894: {
895: UInt32 physical;
896:
897: // zero out all unnecessary fields
898: physical = pTD->pPhysical;
899: //bzero(pTD, sizeof(*pTD));
900: pTD->pLogicalNext = NULL;
901: pTD->pPhysical = physical;
902: if (pOHCIUIMData->pFreeITD)
903: {
904: pOHCIUIMData->pLastFreeITD->pLogicalNext = pTD;
905: pOHCIUIMData->pLastFreeITD = pTD;
906: }
907: else
908: {
909: // list is currently empty
910: pOHCIUIMData->pLastFreeITD = pTD;
911: pOHCIUIMData->pFreeITD = pTD;
912: }
913: return (kIOReturnSuccess);
914: }
915:
916:
917: IOReturn AppleOHCI::OHCIUIMDeallocateTD (OHCIGeneralTransferDescriptorPtr pTD)
918: {
919: UInt32 physical;
920:
921: //zero out all unnecessary fields
922: physical = pTD->pPhysical;
923: //bzero(pTD, sizeof(*pTD));
924: pTD->pLogicalNext = nil;
925: pTD->pPhysical = physical;
926:
927: if (pOHCIUIMData->pFreeTD){
928: pOHCIUIMData->pLastFreeTD->pLogicalNext = pTD;
929: pOHCIUIMData->pLastFreeTD = pTD;
930: } else {
931: // list is currently empty
932: pOHCIUIMData->pLastFreeTD = pTD;
933: pOHCIUIMData->pFreeTD = pTD;
934: }
935: return (kIOReturnSuccess);
936: }
937:
938: IOReturn AppleOHCI::OHCIUIMDeallocateED (OHCIEndpointDescriptorPtr pED)
939: {
940: UInt32 physical;
941:
942: //zero out all unnecessary fields
943: physical = pED->pPhysical;
944: //bzero(pED, sizeof(*pED));
945: pED->pPhysical = physical;
946: pED->pLogicalNext = nil;
947:
948: if (pOHCIUIMData->pFreeED){
949: pOHCIUIMData->pLastFreeED->pLogicalNext = pED;
950: pOHCIUIMData->pLastFreeED = pED;
951: } else {
952: // list is currently empty
953: pOHCIUIMData->pLastFreeED = pED;
954: pOHCIUIMData->pFreeED = pED;
955: }
956: return (kIOReturnSuccess);
957: }
958:
959: int GetEDType(OHCIEndpointDescriptorPtr pED)
960: {
961: return ((OSSwapInt32(pED->flags) & kOHCIEDControl_F)
962: >> kOHCIEDControl_FPhase);
963: }
964:
965:
966: IOReturn AppleOHCI::RemoveAllTDs (OHCIEndpointDescriptorPtr pED)
967: {
968: RemoveTDs(pED);
969:
970: if (GetEDType(pED) == kOHCIEDFormatGeneralTD) {
971: // remove the last "dummy" TD
972: OHCIUIMDeallocateTD(
973: (OHCIGeneralTransferDescriptorPtr) pED->pLogicalTailP);
974: }
975: else
976: {
977: OHCIUIMDeallocateITD(
978: (OHCIIsochTransferDescriptorPtr) pED->pLogicalTailP);
979: }
980: pED->pLogicalTailP = nil;
981:
982: return (0);
983: }
984:
985:
986: //removes all but the last of the TDs
987: IOReturn AppleOHCI::RemoveTDs(OHCIEndpointDescriptorPtr pED)
988: {
989: OHCIGeneralTransferDescriptorPtr pCurrentTD, lastTD;
990: UInt32 bufferSizeRemaining = 0;
991: OHCIIsochTransferDescriptorPtr pITD, pITDLast;
992:
993: if (GetEDType(pED) == kOHCIEDFormatGeneralTD)
994: {
995: //process and deallocate GTD's
996: pCurrentTD = (OHCIGeneralTransferDescriptorPtr)
997: (OSSwapInt32(pED->tdQueueHeadPtr) & kOHCIHeadPMask);
998: pCurrentTD = (OHCIGeneralTransferDescriptorPtr)
999: OHCIUIMGetLogicalAddress ((UInt32) pCurrentTD);
1000:
1001: lastTD = (OHCIGeneralTransferDescriptorPtr) pED->pLogicalTailP;
1002: pED->pLogicalHeadP = pED->pLogicalTailP;
1003:
1004: while (pCurrentTD != lastTD)
1005: {
1006: if (pCurrentTD == nil)
1007: return (-1);
1008:
1009: //take out TD from list
1010: pED->tdQueueHeadPtr = pCurrentTD->nextTD;
1011: pED->pLogicalHeadP = pCurrentTD->pLogicalNext;
1012:
1013: bufferSizeRemaining += findBufferRemaining(pCurrentTD);
1014:
1015: if (pCurrentTD->completion.action != nil)
1016: {
1017: IOUSBCompletion completion;
1018: // zero out callback first then call it
1019: completion = pCurrentTD->completion;
1020: pCurrentTD->completion.action = nil;
1021: complete(completion,
1022: kIOReturnAborted,
1023: bufferSizeRemaining);
1024: bufferSizeRemaining = 0;
1025: }
1026:
1027: OHCIUIMDeallocateTD(pCurrentTD);
1028: pCurrentTD = (OHCIGeneralTransferDescriptorPtr) pED->pLogicalHeadP;
1029: }
1030: }
1031: else
1032: {
1033: UInt32 phys;
1034: phys = (OSReadLittleInt32(&pED->tdQueueHeadPtr, 0) & kOHCIHeadPMask);
1035: pITD = (OHCIIsochTransferDescriptorPtr)
1036: OHCIUIMGetLogicalAddress (phys);
1037: pITDLast = (OHCIIsochTransferDescriptorPtr)pED->pLogicalTailP;
1038:
1039: while (pITD != pITDLast)
1040: {
1041: OHCIIsochTransferDescriptorPtr pPrevITD;
1042: if (pITD == nil)
1043: return (-1);
1044: ProcessCompletedITD (pITD, kIOReturnAborted);
1045: pPrevITD = pITD;
1046: pITD = pITD->pLogicalNext;
1047: // deallocate td
1048: OHCIUIMDeallocateITD(pPrevITD);
1049: }
1050: }
1051:
1052: return (0);
1053: }
1054:
1055: void ProcessCompletedITD (OHCIIsochTransferDescriptorPtr pITD, IOReturn status)
1056: {
1057:
1058: IOUSBIsocFrame * pFrames;
1059: int i;
1060: int frameCount;
1061:
1062: //print_itd(pITD);
1063: pFrames = pITD->pIsocFrame;
1064: frameCount = (OSReadLittleInt32(&pITD->flags, 0) & kOHCIITDControl_FC) >>
1065: kOHCIITDControl_FCPhase;
1066: for (i=0; i <= frameCount; i++)
1067: {
1068: UInt16 offset = OSReadLittleInt16(&pITD->offset[i], 0);
1069: if ( ((offset & kOHCIITDPSW_CCNA) >> kOHCIITDPSW_CCNAPhase) ==
1070: kOHCIITDOffsetConditionNotAccessed)
1071: {
1072: pFrames[pITD->frameNum + i].frActCount = 0;
1073: pFrames[pITD->frameNum + i].frStatus =
1074: kOHCIITDConditionNotAccessedReturn;
1075: }
1076: else
1077: {
1078: pFrames[pITD->frameNum + i].frStatus =
1079: (offset & kOHCIITDPSW_CC) >> kOHCIITDOffset_CCPhase;
1080: // Successful isoch transmit sets the size field to zero,
1081: // successful receive sets size to actual packet size received.
1082: if(kIOReturnSuccess == pFrames[pITD->frameNum + i].frStatus &&
1083: pITD->pType == kOHCIIsochronousOutType)
1084: pFrames[pITD->frameNum + i].frActCount =
1085: pFrames[pITD->frameNum + i].frReqCount;
1086: else
1087: pFrames[pITD->frameNum + i].frActCount =
1088: offset & kOHCIITDPSW_Size;
1089: }
1090: }
1091: // call callback
1092: if (pITD->completion.action)
1093: {
1094: IOUSBIsocCompletionAction pHandler;
1095: pHandler = pITD->completion.action;
1096: pITD->completion.action = nil;
1097: //zero out handler first than call it
1098: (*pHandler) (pITD->completion.target, pITD->completion.parameter,
1099: status, pFrames);
1100: }
1101: }
1102:
1103:
1104: IOReturn
1105: AppleOHCI::DoDoneQueueProcessing(OHCIGeneralTransferDescriptorPtr pHCDoneTD,
1106: IOUSBCompletionAction safeAction)
1107: {
1108: UInt32 control, transferStatus;
1109: long bufferSizeRemaining;
1110: OHCIGeneralTransferDescriptorPtr prevTD, nextTD;
1111: UInt32 PhysAddr;
1112: UInt32 pageSize;
1113: UInt32 pageMask;
1114: OHCIEndpointDescriptorPtr tempED;
1115: OHCIRegistersPtr pOHCIRegisters;
1116: OHCIIsochTransferDescriptorPtr pITD;
1117:
1118: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
1119:
1120: if(pHCDoneTD == nil)
1121: /* This should not happen */
1122: return(kIOReturnSuccess);
1123:
1124: pageSize = pOHCIUIMData->pageSize;
1125: pageMask = ~(pageSize - 1);
1126:
1127: /* Reverse the done queue use only the virtual Address fields */
1128: prevTD = 0;
1129: while (pHCDoneTD != nil)
1130: {
1131: PhysAddr = OSSwapInt32(pHCDoneTD->nextTD) & kOHCIHeadPMask;
1132: nextTD = (OHCIGeneralTransferDescriptorPtr) OHCIUIMGetLogicalAddress(PhysAddr);
1133: pHCDoneTD->pLogicalNext = prevTD;
1134: prevTD = pHCDoneTD;
1135: pHCDoneTD = nextTD;
1136: }
1137: pHCDoneTD = prevTD; /* New qHead */
1138:
1139: while (pHCDoneTD != nil)
1140: {
1141: #if (DEBUGGING_LEVEL > 2)
1142: DEBUGLOG("\tdone queue: processing..."); print_td(pHCDoneTD);
1143: #endif
1144: IOReturn errStatus;
1145: // find the next one
1146: nextTD = pHCDoneTD->pLogicalNext;
1147:
1148: control = OSSwapInt32(pHCDoneTD->flags);
1149: transferStatus = (control & kOHCIGTDControl_CC)
1150: >> kOHCIGTDControl_CCPhase;
1151: errStatus = TranslateStatusToUSBError(transferStatus);
1152: if (pOHCIUIMData->OptiOn && (pHCDoneTD->pType == kOHCIOptiLSBug))
1153: {
1154: // clear any bad errors
1155: tempED = (OHCIEndpointDescriptorPtr) pHCDoneTD->pEndpoint;
1156: pHCDoneTD->flags = pHCDoneTD->flags
1157: & OSSwapInt32(kOHCIGTDClearErrorMask);
1158: tempED->tdQueueHeadPtr &= OSSwapInt32(kOHCIHeadPMask);
1159: pHCDoneTD->nextTD = tempED->tdQueueTailPtr & OSSwapInt32(kOHCIHeadPMask);
1160: tempED->tdQueueTailPtr = OSSwapInt32(pHCDoneTD->pPhysical);
1161: pOHCIRegisters->hcCommandStatus =
1162: OSSwapInt32 (kOHCIHcCommandStatus_CLF);
1163:
1164: // For CMD Buffer Underrun Errata
1165: }
1166: else if ((transferStatus == kOHCIGTDConditionBufferUnderrun) &&
1167: (pHCDoneTD->pType == kOHCIBulkTransferOutType) &&
1168: (pOHCIUIMData->errataBits & kErrataRetryBufferUnderruns))
1169: {
1170: tempED = (OHCIEndpointDescriptorPtr) pHCDoneTD->pEndpoint;
1171: pHCDoneTD->flags = pHCDoneTD->flags
1172: & OSSwapInt32(kOHCIGTDClearErrorMask);
1173: pHCDoneTD->nextTD = tempED->tdQueueHeadPtr & OSSwapInt32(kOHCIHeadPMask);
1174: pHCDoneTD->pLogicalNext = (OHCIGeneralTransferDescriptorPtr)
1175: OHCIUIMGetLogicalAddress (OSSwapInt32(tempED->tdQueueHeadPtr)
1176: & kOHCIHeadPMask);
1177:
1178: tempED->tdQueueHeadPtr = OSSwapInt32(pHCDoneTD->pPhysical)
1179: | (tempED->tdQueueHeadPtr & OSSwapInt32( kOHCIEDToggleBitMask));
1180: pOHCIRegisters->hcCommandStatus =
1181: OSSwapInt32(kOHCIHcCommandStatus_BLF);
1182:
1183: }
1184: else if (pHCDoneTD->pType == kOHCIIsochronousInType ||
1185: pHCDoneTD->pType == kOHCIIsochronousOutType)
1186: {
1187: // cast to a isoc type
1188: pITD = (OHCIIsochTransferDescriptorPtr) pHCDoneTD;
1189: ProcessCompletedITD(pITD, errStatus);
1190: // deallocate td
1191: OHCIUIMDeallocateITD(pITD);
1192: }
1193: else
1194: {
1195: bufferSizeRemaining = findBufferRemaining (pHCDoneTD);
1196: if (pHCDoneTD->completion.action != nil)
1197: {
1198: IOUSBCompletion completion;
1199: completion = pHCDoneTD->completion;
1200: if(!safeAction || (safeAction == completion.action)) {
1201: // zero out callback first then call it
1202: pHCDoneTD->completion.action = nil;
1203: complete(completion, errStatus, bufferSizeRemaining);
1204: OHCIUIMDeallocateTD(pHCDoneTD);
1205: }
1206: else {
1207: if(_pendingHead)
1208: _pendingTail->pLogicalNext = pHCDoneTD;
1209: else
1210: _pendingHead = pHCDoneTD;
1211: _pendingTail = pHCDoneTD;
1212: }
1213: }
1214: else if (errStatus != kIOReturnSuccess) {
1215: doCallback(pHCDoneTD, errStatus, bufferSizeRemaining);
1216: OHCIUIMDeallocateTD(pHCDoneTD);
1217: }
1218: }
1219: pHCDoneTD = nextTD; /* New qHead */
1220: }
1221:
1222: return(kIOReturnSuccess);
1223: }
1224:
1225:
1226:
1227:
1228: void AppleOHCI::UIMProcessDoneQueue(IOUSBCompletionAction safeAction)
1229: {
1230: OHCIRegistersPtr pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
1231: UInt32 interruptStatus;
1232: UInt32 PhysAddr;
1233: OHCIGeneralTransferDescriptorPtr pHCDoneTD;
1234:
1235:
1236: // check if the OHCI has written the DoneHead yet
1237: interruptStatus = OSSwapInt32(pOHCIRegisters->hcInterruptStatus);
1238: if( (interruptStatus & kOHCIHcInterrupt_WDH) == 0)
1239: {
1240: return;
1241: }
1242:
1243: // get the pointer to the list (logical address)
1244: PhysAddr = (UInt32) OSSwapInt32(*(UInt32 *)(pOHCIUIMData->pHCCA + 0x84));
1245: PhysAddr &= kOHCIHeadPMask; // mask off interrupt bits
1246: pHCDoneTD = (OHCIGeneralTransferDescriptorPtr) OHCIUIMGetLogicalAddress(PhysAddr);
1247: // write to 0 to the HCCA DoneHead ptr so we won't look at it anymore.
1248: *(UInt32 *)(pOHCIUIMData->pHCCA + 0x84) = 0L;
1249:
1250: // Since we have a copy of the queue to process, we can let the host update it again.
1251: pOHCIRegisters->hcInterruptStatus = OSSwapInt32(kOHCIHcInterrupt_WDH);
1252:
1253: DoDoneQueueProcessing(pHCDoneTD, safeAction);
1254: return;
1255: }
1256:
1257: void AppleOHCI::finishPending()
1258: {
1259: while(_pendingHead) {
1260: OHCIGeneralTransferDescriptorPtr next = _pendingHead->pLogicalNext;
1261: long bufferSizeRemaining = findBufferRemaining (_pendingHead);
1262: UInt32 transferStatus = (OSReadLittleInt32(&_pendingHead->flags, 0) &
1263: kOHCIGTDControl_CC) >> kOHCIGTDControl_CCPhase;
1264:
1265: IOUSBCompletion completion;
1266: // zero out callback first then call it
1267: completion = _pendingHead->completion;
1268: _pendingHead->completion.action = nil;
1269: complete(completion,
1270: TranslateStatusToUSBError(transferStatus),
1271: bufferSizeRemaining);
1272: OHCIUIMDeallocateTD(_pendingHead);
1273: _pendingHead = next;
1274: }
1275: }
1276:
1277: UInt32 AppleOHCI::GetBandwidthAvailable()
1278: {
1279: return pOHCIUIMData->isochBandwidthAvail;
1280: }
1281:
1282: UInt64 AppleOHCI::GetFrameNumber()
1283: {
1284:
1285: UInt64 bigFrameNumber;
1286: UInt16 framenumber16;
1287:
1288: framenumber16 = OSReadLittleInt16(pOHCIUIMData->pHCCA, 0x80);
1289: bigFrameNumber = pOHCIUIMData->frameNumber + framenumber16;
1290: return bigFrameNumber;
1291: }
1292:
1293: UInt32 AppleOHCI::GetFrameNumber32()
1294: {
1295: UInt16 framenumber16;
1296: UInt32 largishFrameNumber;
1297: framenumber16 = OSReadLittleInt16(pOHCIUIMData->pHCCA, 0x80);
1298: largishFrameNumber = ((UInt32)pOHCIUIMData->frameNumber) + framenumber16;
1299: return largishFrameNumber;
1300: }
1301:
1302:
1303: // #ifdef DEBUG
1304: void AppleOHCI::dumpRegs(void)
1305: {
1306: UInt32 lvalue;
1307:
1308: #if 0
1309: /*device->*/configRead16(cwVendorID, &ivalue);
1310: /*device->*/configRead16(cwDeviceID, &ivalue);
1311: IOLog("OHCI: cwVendorID=%x cwDeviceID=%x\n", ivalue, ivalue2);
1312: #else
1313: lvalue = _device->configRead32(cwVendorID);
1314: IOLog("OHCI: cwVendorID=%lx\n", lvalue);
1315: #endif
1316: lvalue = _device->configRead32(clClassCodeAndRevID);
1317: IOLog("OHCI: clClassCodeAndRevID=%lx\n", lvalue);
1318: lvalue = _device->configRead32(clHeaderAndLatency);
1319: IOLog("OHCI: clHeaderAndLatency=%lx\n", lvalue);
1320: lvalue = _device->configRead32(clBaseAddressZero);
1321: IOLog("OHCI: clBaseAddressZero=%lx\n", lvalue);
1322: lvalue = _device->configRead32(clBaseAddressOne);
1323: IOLog("OHCI: clBaseAddressOne=%lx\n", lvalue);
1324: lvalue = _device->configRead32(clExpansionRomAddr);
1325: IOLog("OHCI: clExpansionRomAddr=%lx\n", lvalue);
1326: lvalue = _device->configRead32(clLatGntIntPinLine);
1327: IOLog("OHCI: clLatGntIntPinLine=%lx\n", lvalue);
1328: lvalue = _device->configRead32(clLatGntIntPinLine+4);
1329: IOLog("OHCI: clLatGntIntPinLine+4=%lx\n", lvalue);
1330: lvalue = _device->configRead32(cwCommand);
1331: IOLog("OHCI: cwCommand=%lx\n", lvalue & 0x0000ffff);
1332: IOLog("OHCI: cwStatus=%lx\n", lvalue & 0xffff0000);
1333:
1334: lvalue = _device->configRead32(cwCommand);
1335: _device->configWrite32(cwCommand, lvalue);
1336: _device->configWrite32(cwCommand, (lvalue & 0xffff0000) |
1337: (cwCommandEnableBusMaster |
1338: cwCommandEnableMemorySpace));
1339: lvalue = _device->configRead32(cwCommand);
1340: IOLog("OHCI: cwCommand=%lx\n", lvalue & 0x0000ffff);
1341: IOLog("OHCI: cwStatus=%lx\n", lvalue & 0xffff0000);
1342:
1343: IOLog("OHCI: HcRevision=%lx\n",
1344: OSSwapInt32((pOHCIUIMData->pOHCIRegisters)->hcRevision));
1345: IOLog(" HcControl=%lx\n",
1346: OSSwapInt32((pOHCIUIMData->pOHCIRegisters)->hcControl));
1347: IOLog(" HcFmInterval=%lx\n",
1348: OSSwapInt32((pOHCIUIMData->pOHCIRegisters)->hcFmInterval));
1349: IOLog(" hcRhDescriptorA=%lx\n",
1350: OSSwapInt32((pOHCIUIMData->pOHCIRegisters)->hcRhDescriptorA));
1351: IOLog(" hcRhDescriptorB=%lx\n",
1352: OSSwapInt32((pOHCIUIMData->pOHCIRegisters)->hcRhDescriptorB));
1353: }
1354: // #endif /* DEBUG */
1355:
1356: IOReturn TranslateStatusToUSBError(UInt32 status)
1357: {
1358: static const UInt32 statusToErrorMap[] = {
1359: /* OHCI Error */ /* USB Error */
1360: /* 0 */ kIOReturnSuccess,
1361: /* 1 */ kIOUSBPipeStalled, //kUSBCRCErr,
1362: /* 2 */ kIOUSBPipeStalled, //kUSBBitstufErr,
1363: /* 3 */ kIOUSBPipeStalled, //kUSBDataToggleErr,
1364: /* 4 */ kIOUSBPipeStalled, //kUSBEndpointStallErr,
1365: /* 5 */ kIOReturnNotResponding, //kUSBNotRespondingErr,
1366: /* 6 */ kIOUSBPipeStalled, //kUSBPIDCheckErr,
1367: /* 7 */ kIOUSBPipeStalled, //kUSBWrongPIDErr,
1368: /* 8 */ kIOReturnOverrun,
1369: /* 9 */ kIOReturnUnderrun,
1370: /* 10 */ kIOReturnError, //kUSBRes1Err,
1371: /* 11 */ kIOReturnError, //kUSBRes2Err,
1372: /* 12 */ kIOReturnDMAError, //kUSBBufOvrRunErr,
1373: /* 13 */ kIOReturnDMAError, //kUSBBufUnderRunErr
1374: };
1375:
1376: if (status > 13) return(kIOReturnInternalError);
1377: return(statusToErrorMap[status]);
1378: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.