|
|
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:
30: #include <libkern/OSByteOrder.h>
31:
32: #include "AppleOHCI.h"
33: #include <IOKit/IOMemoryDescriptor.h>
34: #include <IOKit/IOMemoryCursor.h>
35:
36: #define DEBUGGING_LEVEL 0 // 1 = low; 2 = high; 3 = extreme
37: #define DEBUGLOG IOLog
38: #define nil (0)
39: #define kP_UIMName ""
40:
41: #if DEBUGGING_LEVEL > 0
42: #define USBExpertStatusLevel(a, b, c, d) DEBUGLOG("UIM: %s 0x%lx\n", c, (UInt32)(d))
43: #else
44: #define USBExpertStatusLevel(a, b, c, d)
45: #endif
46:
47: #define super IOUSBController
48:
49: void print_td(OHCIGeneralTransferDescriptorPtr x);
50: void print_itd(OHCIIsochTransferDescriptorPtr x);
51: void print_ed(OHCIEndpointDescriptorPtr x);
52: void print_isoc_ed(OHCIEndpointDescriptorPtr x);
53: void print_list(OHCIEndpointDescriptorPtr pListHead,
54: OHCIEndpointDescriptorPtr pListTail);
55: void print_control_list(OHCIUIMDataPtr pData);
56: void print_bulk_list(OHCIUIMDataPtr pData);
57: void print_int_list(OHCIUIMDataPtr pData);
58:
59: static inline OHCIEDFormat
60: GetEDType(OHCIEndpointDescriptorPtr pED)
61: {
62: return ((OSReadLittleInt32(&pED->flags, 0) & kOHCIEDControl_F) >>
63: kOHCIEDControl_FPhase);
64: }
65:
66: IOReturn AppleOHCI::UIMCreateGeneralTransfer(
67: OHCIEndpointDescriptorPtr queue,
68: IOUSBCompletion completion,
69: IOMemoryDescriptor * CBP,
70: UInt32 bufferSize,
71: UInt32 flags,
72: UInt32 type,
73: UInt32 kickBits)
74: {
75: OHCIRegistersPtr pOHCIRegisters;
76: OHCIGeneralTransferDescriptorPtr pOHCIGeneralTransferDescriptor,
77: newOHCIGeneralTransferDescriptor;
78: IOReturn status = kIOReturnSuccess;
79: IOPhysicalSegment physicalAddresses[2];
80: IOByteCount transferOffset;
81: UInt32 pageSize;
82: UInt32 pageCount;
83:
84: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
85: pageSize = pOHCIUIMData->pageSize;
86:
87: // Handy for debugging transfer lists
88: flags |= (kOHCIGTDConditionNotAccessed << kOHCIGTDControl_CCPhase);
89:
90: // FERG DEBUG
91: // uncomment the next line to force the data to be put in TD list, but not be processed
92: // this is handy for using USBProber/Macsbug to look at TD's to see if they're OK.
93: // pEDQueue->dWord0 |= OSSwapInt32 (kOHCIEDControl_K);
94: // FERG DEBUG
95: if (bufferSize != 0)
96: {
97: transferOffset = 0;
98: while (transferOffset < bufferSize)
99: {
100: if(pOHCIUIMData->errataBits & kErrataOnlySinglePageTransfers)
101: pageCount = _genCursor->getPhysicalSegments(CBP, transferOffset, physicalAddresses, 1);
102: else
103: pageCount = _genCursor->getPhysicalSegments(CBP, transferOffset, physicalAddresses, 2);
104: newOHCIGeneralTransferDescriptor = OHCIUIMAllocateTD();
105: if (newOHCIGeneralTransferDescriptor == nil) {
106: status = kIOReturnNoMemory;
107: break;
108: }
109: pOHCIGeneralTransferDescriptor =
110: (OHCIGeneralTransferDescriptorPtr)queue->pLogicalTailP;
111: OSWriteLittleInt32(&pOHCIGeneralTransferDescriptor->flags, 0, flags);
112: OSWriteLittleInt32(&pOHCIGeneralTransferDescriptor->currentBufferPtr, 0,
113: physicalAddresses[0].location);
114: OSWriteLittleInt32(&pOHCIGeneralTransferDescriptor->nextTD, 0,
115: newOHCIGeneralTransferDescriptor->pPhysical);
116: if (pageCount == 2) {
117: OSWriteLittleInt32(&pOHCIGeneralTransferDescriptor->bufferEnd, 0,
118: physicalAddresses[1].location + physicalAddresses[1].length - 1);
119: transferOffset += physicalAddresses[1].length;
120: }
121: else
122: OSWriteLittleInt32(&pOHCIGeneralTransferDescriptor->bufferEnd, 0,
123: physicalAddresses[0].location + physicalAddresses[0].length - 1);
124:
125: pOHCIGeneralTransferDescriptor->pLogicalNext =
126: newOHCIGeneralTransferDescriptor;
127: pOHCIGeneralTransferDescriptor->pEndpoint = queue;
128: pOHCIGeneralTransferDescriptor->pType = type;
129: transferOffset += physicalAddresses[0].length;
130:
131: // only supply a callback when the entire buffer has been
132: // transfered.
133: if (transferOffset >= bufferSize)
134: pOHCIGeneralTransferDescriptor->completion = completion;
135: else
136: pOHCIGeneralTransferDescriptor->completion.action = nil;
137: queue->tdQueueTailPtr = pOHCIGeneralTransferDescriptor->nextTD;
138: queue->pLogicalTailP =
139: newOHCIGeneralTransferDescriptor;
140: OSWriteLittleInt32(&pOHCIRegisters->hcCommandStatus, 0, kickBits);
141: }
142: }
143: else
144: {
145: newOHCIGeneralTransferDescriptor = OHCIUIMAllocateTD();
146: // last in queue is dummy descriptor. Fill it in then add new dummy
147: pOHCIGeneralTransferDescriptor =
148: (OHCIGeneralTransferDescriptorPtr) queue->pLogicalTailP;
149:
150: OSWriteLittleInt32(&pOHCIGeneralTransferDescriptor->flags, 0, flags);
151: OSWriteLittleInt32(&pOHCIGeneralTransferDescriptor->nextTD, 0,
152: newOHCIGeneralTransferDescriptor->pPhysical);
153: pOHCIGeneralTransferDescriptor->pLogicalNext =
154: newOHCIGeneralTransferDescriptor;
155: pOHCIGeneralTransferDescriptor->pEndpoint = queue;
156: pOHCIGeneralTransferDescriptor->pType = type;
157:
158: /* for zero sized buffers */
159: pOHCIGeneralTransferDescriptor->currentBufferPtr = 0;
160: pOHCIGeneralTransferDescriptor->bufferEnd = 0;
161: pOHCIGeneralTransferDescriptor->completion = completion;
162:
163: /* Make new descriptor the tail */
164: queue->tdQueueTailPtr = pOHCIGeneralTransferDescriptor->nextTD;
165: queue->pLogicalTailP = newOHCIGeneralTransferDescriptor;
166: OSWriteLittleInt32(&pOHCIRegisters->hcCommandStatus, 0, kickBits);
167: }
168:
169: #if (DEBUGGING_LEVEL > 0)
170: print_td(pOHCIGeneralTransferDescriptor);
171: DEBUGLOG("UIMCreateGeneralTransfer: returning status=%d\n", status);
172: #endif
173: return (status);
174: }
175:
176: IOReturn AppleOHCI::UIMCreateControlEndpoint(
177: UInt8 functionAddress,
178: UInt8 endpointNumber,
179: UInt16 maxPacketSize,
180: UInt8 speed)
181: {
182: OHCIEndpointDescriptorPtr pOHCIEndpointDescriptor, pED;
183:
184: #if (DEBUGGING_LEVEL > 0)
185: DEBUGLOG("%s: UIMCreateControlEndpoint(%d, %d, %d, %d)\n", getName(),
186: functionAddress, endpointNumber, maxPacketSize, speed);
187: #endif
188: if (pOHCIUIMData->rootHubFuncAddress == functionAddress)
189: {
190: return(kIOReturnSuccess);
191: }
192:
193: pED = (OHCIEndpointDescriptorPtr) pOHCIUIMData->pControlHead;
194: if ((speed == kOHCIEDSpeedFull) && pOHCIUIMData->OptiOn)
195: pED = (OHCIEndpointDescriptorPtr) pOHCIUIMData->pBulkHead;
196:
197: pOHCIEndpointDescriptor = AddEmptyEndPoint(functionAddress,
198: endpointNumber,
199: maxPacketSize,
200: speed,
201: kOHCIEDDirectionTD,
202: pED,
203: kOHCIEDFormatGeneralTD);
204:
205: #if (DEBUGGING_LEVEL > 2)
206: if ((speed == kOHCIEDSpeedFull) && pOHCIUIMData->OptiOn)
207: print_bulk_list(pOHCIUIMData);
208: else
209: print_control_list(pOHCIUIMData);
210: #endif
211:
212: if (pOHCIEndpointDescriptor == nil)
213: return(-1); //FIXME
214: return (kIOReturnSuccess);
215: }
216:
217:
218: IOReturn AppleOHCI::UIMCreateControlTransfer(
219: short functionAddress,
220: short endpointNumber,
221: IOUSBCompletion completion,
222: IOMemoryDescriptor * CBP,
223: bool bufferRounding,
224: UInt32 bufferSize,
225: short direction)
226: {
227: UInt32 myBufferRounding;
228: UInt32 myDirection;
229: UInt32 myToggle;
230: OHCIEndpointDescriptorPtr pEDQueue, pEDDummy;
231: IOReturn status;
232:
233: #if (DEBUGGING_LEVEL > 0)
234: DEBUGLOG("\tCrntlTx: adr=%d:%d cbp=%lx:%lx br=%s cback=[%lx:%lx] dir=%d)\n",
235: functionAddress, endpointNumber, CBP, bufferSize,
236: bufferRounding?"YES":"NO",
237: (UInt32)completion.target, (UInt32)completion.parameter, direction);
238: #endif
239:
240: if (direction == kUSBOut)
241: {
242: direction = kOHCIGTDPIDOut;
243: }
244: else if (direction == kUSBIn)
245: {
246: direction = kOHCIGTDPIDIn;
247: }
248: else
249: {
250: direction = kOHCIGTDPIDSetup;
251: }
252: // search for endpoint descriptor
253:
254: pEDQueue = FindControlEndpoint(functionAddress, endpointNumber, &pEDDummy);
255: if (pEDQueue == nil)
256: {
257: IOLog("UIMCreateControlTransfer: Could not find endpoint\n");
258: return(kIOUSBEndpointNotFound);
259: }
260: myBufferRounding = (UInt32) bufferRounding << kOHCIBufferRoundingOffset;
261: myDirection = (UInt32) direction << kOHCIDirectionOffset;
262: myToggle = kOHCIBit25; /* Take data toggle from TD */
263: if (direction != 0)
264: {
265: /* Setup uses Data 0, data status use Data1 */
266: myToggle |= kOHCIBit24; /* use Data1 */
267: }
268:
269: status = UIMCreateGeneralTransfer(pEDQueue, completion, CBP, bufferSize,
270: myBufferRounding | myDirection | myToggle, kOHCIControlSetupType, kOHCIHcCommandStatus_CLF);
271:
272: #if (DEBUGGING_LEVEL > 2)
273: print_ed(pEDQueue);
274: #endif
275:
276: return (status);
277: }
278:
279: IOReturn AppleOHCI::UIMCreateControlTransfer(
280: short functionAddress,
281: short endpointNumber,
282: IOUSBCompletion completion,
283: void * CBP,
284: bool bufferRounding,
285: UInt32 bufferSize,
286: short direction)
287: {
288: IOMemoryDescriptor * desc = NULL;
289: IODirection descDirection;
290: IOReturn status;
291:
292: #if (DEBUGGING_LEVEL > 0)
293: DEBUGLOG("\tCrntlTx: adr=%d:%d cbp=%lx:%lx br=%s cback=[%lx:%lx] dir=%d)\n",
294: functionAddress, endpointNumber, CBP, bufferSize,
295: bufferRounding?"YES":"NO",
296: (UInt32)completion.target, (UInt32)completion.parameter, direction);
297: #endif
298: if (direction == kUSBOut)
299: {
300: descDirection = kIODirectionOut;
301: }
302: else if (direction == kUSBIn)
303: {
304: descDirection = kIODirectionIn;
305: }
306: else
307: {
308: descDirection = kIODirectionOut;
309: }
310: if(bufferSize != 0) {
311: desc = IOMemoryDescriptor::withAddress(CBP, bufferSize, descDirection);
312: if(!desc)
313: return(kIOReturnNoMemory);
314: }
315:
316: status = UIMCreateControlTransfer(functionAddress, endpointNumber, completion,
317: desc, bufferRounding, bufferSize, direction);
318:
319: if(desc)
320: desc->release();
321:
322: return (status);
323: }
324:
325: /* Not implemented - use UIMAbortEndpoint
326: IOReturn AppleOHCI::UIMAbortControlEndpoint(void);
327: IOReturn AppleOHCI::UIMEnableControlEndpoint(void);
328: IOReturn AppleOHCI::UIMDisableControlEndpoint(void);
329: */
330:
331: // Bulk
332: IOReturn AppleOHCI::UIMCreateBulkEndpoint(
333: UInt8 functionAddress,
334: UInt8 endpointNumber,
335: UInt8 direction,
336: UInt8 speed,
337: UInt8 maxPacketSize)
338: {
339: OHCIEndpointDescriptorPtr pOHCIEndpointDescriptor, pED;
340:
341:
342: #if (DEBUGGING_LEVEL > 0)
343: DEBUGLOG("%s: UIMCreateBulkEndpoint(adr=%d:%d, max=%d, dir=%d)\n", getName(),
344: functionAddress, endpointNumber, maxPacketSize, direction);
345: #endif
346:
347: if (direction == kUSBOut)
348: direction = kOHCIEDDirectionOut;
349: else if (direction == kUSBIn)
350: direction = kOHCIEDDirectionIn;
351: else
352: direction = kOHCIEDDirectionTD;
353:
354: pED = (OHCIEndpointDescriptorPtr) pOHCIUIMData->pBulkHead;
355: pOHCIEndpointDescriptor = AddEmptyEndPoint (functionAddress,
356: endpointNumber,
357: maxPacketSize,
358: speed,
359: direction,
360: pED,
361: kOHCIEDFormatGeneralTD);
362: if (pOHCIEndpointDescriptor == nil)
363: return(kIOReturnNoMemory);
364:
365: return (kIOReturnSuccess);
366: }
367:
368: IOReturn AppleOHCI::UIMCreateBulkTransfer(
369: short functionAddress,
370: short endpointNumber,
371: IOUSBCompletion completion,
372: IOMemoryDescriptor * CBP,
373: bool bufferRounding,
374: UInt32 bufferSize,
375: short direction)
376: {
377: IOReturn status = kIOReturnSuccess;
378: UInt32 myBufferRounding;
379: UInt32 TDDirection;
380: UInt32 kickBits;
381: OHCIEndpointDescriptorPtr pEDQueue, pEDDummy;
382:
383: #if (DEBUGGING_LEVEL > 0)
384: DEBUGLOG("\tBulkTx: adr=%d:%d cbp=%lx:%x br=%s cback=[%lx:%lx:%lx] dir=%d)\n",
385: functionAddress, endpointNumber, CBP, bufferSize, bufferRounding?"YES":"NO",
386: (UInt32)completion.action, (UInt32)completion.target, (UInt32)completion.parameter, direction);
387: #endif
388:
389: if (direction == kUSBOut)
390: direction = kOHCIEDDirectionOut;
391: else if (direction == kUSBIn)
392: direction = kOHCIEDDirectionIn;
393: else
394: direction = kOHCIEDDirectionTD;
395:
396: // search for endpoint descriptor
397: pEDQueue =
398: FindBulkEndpoint(functionAddress, endpointNumber, direction, &pEDDummy);
399:
400: if (!pEDQueue)
401: {
402: IOLog("UIMCreateBulkTransfer: Could not find endpoint\n");
403: return (kIOUSBEndpointNotFound);
404: }
405:
406: myBufferRounding = (UInt32) bufferRounding << kOHCIBufferRoundingOffset;
407: TDDirection = (UInt32) direction << kOHCIDirectionOffset;
408: kickBits = kOHCIHcCommandStatus_BLF;
409: if ( pOHCIUIMData->OptiOn)
410: kickBits |= kOHCIHcCommandStatus_CLF;
411:
412: status = UIMCreateGeneralTransfer(pEDQueue, completion, CBP, bufferSize,
413: myBufferRounding | TDDirection, kOHCIBulkTransferOutType, kickBits);
414:
415: #if (DEBUGGING_LEVEL > 2)
416: print_bulk_list(pOHCIUIMData);
417: #endif
418:
419: return (status);
420: }
421:
422: // Interrupt
423: IOReturn AppleOHCI::UIMCreateInterruptEndpoint(
424: short functionAddress,
425: short endpointNumber,
426: UInt8 direction,
427: short speed,
428: UInt16 maxPacketSize,
429: short pollingRate)
430: {
431: OHCIEndpointDescriptorPtr pOHCIEndpointDescriptor;
432: OHCIEndpointDescriptorPtr pED;
433: OHCIIntHeadPtr pInterruptHead;
434: int offset;
435:
436:
437: #if (DEBUGGING_LEVEL > 0)
438: DEBUGLOG("%s: UIMCreateInterruptEndpoint (%d, %d, %s, %d, %d)\n", getName(),
439: functionAddress, endpointNumber, speed ? "lo" : "hi", maxPacketSize,
440: pollingRate);
441: #endif
442:
443: if (pOHCIUIMData->rootHubFuncAddress == functionAddress)
444: {
445: return(kIOReturnSuccess);
446: }
447:
448: if (direction == kUSBOut)
449: direction = kOHCIEDDirectionOut;
450: else if (direction == kUSBIn)
451: direction = kOHCIEDDirectionIn;
452: else
453: direction = kOHCIEDDirectionTD;
454:
455: pInterruptHead = pOHCIUIMData->pInterruptHead;
456:
457: ///ZZZZz opti bug fix!!!!
458: if (pOHCIUIMData->OptiOn)
459: if (speed == kOHCIEDSpeedFull)
460: if (pollingRate >= 8)
461: pollingRate = 7;
462:
463: // Do we have room?? if so return with offset equal to location
464: if (DetermineInterruptOffset(pollingRate, maxPacketSize, &offset) == false)
465: return(kIOReturnNoBandwidth);
466:
467: #if (DEBUGGING_LEVEL > 0)
468: DEBUGLOG("%s: UIMCreateInterruptEndpoint: offset = %d\n", getName(), offset);
469: #endif
470: pED = (OHCIEndpointDescriptorPtr) pInterruptHead[offset].pHead;
471: pOHCIEndpointDescriptor = AddEmptyEndPoint (functionAddress, endpointNumber,
472: maxPacketSize, speed, direction, pED, kOHCIEDFormatGeneralTD);
473: if (nil == pOHCIEndpointDescriptor)
474: return(-1);
475:
476: pInterruptHead[offset].nodeBandwidth += maxPacketSize;
477:
478: #if (DEBUGGING_LEVEL > 2)
479: print_int_list(pOHCIUIMData);
480: #endif
481:
482: return (kIOReturnSuccess);
483: }
484:
485: IOReturn AppleOHCI::UIMCreateInterruptTransfer(
486: short functionAddress,
487: short endpointNumber,
488: IOUSBCompletion completion,
489: IOMemoryDescriptor * CBP,
490: bool bufferRounding,
491: UInt32 bufferSize,
492: short direction)
493: {
494: IOReturn status = kIOReturnSuccess;
495: UInt32 myBufferRounding;
496: UInt32 myDirection;
497: UInt32 myToggle;
498: OHCIEndpointDescriptorPtr pEDQueue, temp;
499: OHCIIntHeadPtr pInterruptHead;
500:
501: #if (DEBUGGING_LEVEL > 0)
502: DEBUGLOG("\tIntTx: adr=%d:%d cbp=%lx:%lx br=%s cback=[%lx:%lx:%lx])\n", functionAddress, endpointNumber, CBP, bufferSize, bufferRounding?"YES":"NO", (UInt32)completion.action, (UInt32)completion.target, (UInt32)completion.parameter);
503: #endif
504:
505: if (pOHCIUIMData->rootHubFuncAddress == functionAddress)
506: {
507: SimulateRootHubInt(endpointNumber, CBP, bufferSize, completion);
508: return(kIOReturnSuccess);
509: }
510:
511: if (direction == kUSBOut)
512: direction = kOHCIEDDirectionOut;
513: else if (direction == kUSBIn)
514: direction = kOHCIEDDirectionIn;
515: else
516: direction = kOHCIEDDirectionTD;
517:
518: pInterruptHead = pOHCIUIMData->pInterruptHead;
519:
520: pEDQueue = FindInterruptEndpoint(functionAddress, endpointNumber,
521: direction,&temp);
522: if (pEDQueue != nil)
523: {
524: myBufferRounding = (UInt32) bufferRounding << kOHCIBufferRoundingOffset;
525: myToggle = 0; /* Take data toggle from Endpoint Descriptor */
526:
527: myDirection = (UInt32) direction << kOHCIDirectionOffset;
528:
529: status = UIMCreateGeneralTransfer(pEDQueue, completion, CBP, bufferSize,
530: myBufferRounding | myDirection | myToggle, kOHCIInterruptInType, 0);
531: }
532: else
533: {
534: IOLog("UIMCreateInterruptTransfer: Could not find endpoint\n");
535: status = kIOUSBEndpointNotFound;
536: }
537: #if (DEBUGGING_LEVEL > 0)
538: DEBUGLOG("UIMCreateInterruptTransfer: returning status=%d\n", status);
539: #endif
540: return (status);
541: }
542:
543: // Isoch
544: IOReturn AppleOHCI::UIMCreateIsochEndpoint(
545: short functionAddress,
546: short endpointNumber,
547: UInt32 maxPacketSize,
548: UInt8 direction)
549: {
550: OHCIEndpointDescriptorPtr pOHCIEndpointDescriptor, pED;
551: UInt32 curMaxPacketSize;
552: UInt32 xtraRequest;
553: UInt32 edFlags;
554:
555:
556: if (direction == kUSBOut)
557: direction = kOHCIEDDirectionOut;
558: else if (direction == kUSBIn)
559: direction = kOHCIEDDirectionIn;
560: else
561: direction = kOHCIEDDirectionTD;
562:
563: pED = FindIsochronousEndpoint(functionAddress, endpointNumber, direction, nil);
564: if (pED) {
565: // this is the case where we have already created this endpoint, and now we are adjusting the maxPacketSize
566: USBExpertStatusLevel (3, 123456789,
567: kP_UIMName"IsochEDCreate- Endpoint already exists, checking maxPacketSize ",
568: maxPacketSize);
569: edFlags = OSReadLittleInt32(&pED->flags, 0);
570: curMaxPacketSize = ( edFlags & kOHCIEDControl_MPS) >> kOHCIEDControl_MPSPhase;
571: if (maxPacketSize == curMaxPacketSize) {
572: USBExpertStatusLevel (3, 123456789,
573: kP_UIMName"IsochEDCreate- maxPacketSize the same, no change ",
574: maxPacketSize);
575: return kIOReturnSuccess;
576: }
577: if (maxPacketSize > curMaxPacketSize) {
578: // client is trying to get more bandwidth
579: xtraRequest = maxPacketSize - curMaxPacketSize;
580: if (xtraRequest > pOHCIUIMData->isochBandwidthAvail)
581: {
582: USBExpertStatusLevel (3, 123456789,
583: kP_UIMName"IsochEDCreate- out of bandwidth, request (extra) = ",
584: xtraRequest);
585: USBExpertStatusLevel (3, 123456789,
586: kP_UIMName"IsochEDCreate- available = ",
587: pOHCIUIMData->isochBandwidthAvail);
588: return kIOReturnNoBandwidth;
589: }
590: pOHCIUIMData->isochBandwidthAvail -= xtraRequest;
591: }
592: else {
593: // client is trying to return some bandwidth
594: xtraRequest = curMaxPacketSize - maxPacketSize;
595: USBExpertStatusLevel (3, 123456789,
596: kP_UIMName"IsochEDCreate- returning some bandwidth: ",
597: xtraRequest);
598: pOHCIUIMData->isochBandwidthAvail += xtraRequest;
599: USBExpertStatusLevel (3, 123456789,
600: kP_UIMName"IsochEDCreate- new available = ",
601: pOHCIUIMData->isochBandwidthAvail);
602: }
603: // update the maxPacketSize field in the endpoint
604: edFlags &= ~kOHCIEDControl_MPS; // strip out old MPS
605: edFlags |= (maxPacketSize << kOHCIEDControl_MPSPhase);
606: OSWriteLittleInt32(&pED->flags, 0, edFlags);
607: return kIOReturnSuccess;
608: }
609:
610: if (maxPacketSize > pOHCIUIMData->isochBandwidthAvail) {
611: USBExpertStatusLevel (3, 123456789,
612: kP_UIMName"Isoch Endpoint create- no bandwidth, request = ",
613: maxPacketSize);
614: USBExpertStatusLevel (3, 123456789,
615: kP_UIMName"Isoch Endpoint create- available = ",
616: pOHCIUIMData->isochBandwidthAvail);
617: return kIOReturnNoBandwidth;
618: }
619:
620: pOHCIUIMData->isochBandwidthAvail -= maxPacketSize;
621: pED = pOHCIUIMData->pIsochHead;
622: pOHCIEndpointDescriptor = AddEmptyEndPoint(functionAddress, endpointNumber,
623: maxPacketSize, kOHCIEDSpeedFull, direction, pED, kOHCIEDFormatIsochronousTD);
624: if (pOHCIEndpointDescriptor == nil) {
625: pOHCIUIMData->isochBandwidthAvail += maxPacketSize;
626: return(kIOReturnNoMemory);
627: }
628:
629: USBExpertStatusLevel (5, 123456789,
630: kP_UIMName"Isoch Endpoint create- success, bandwidth used = ",
631: maxPacketSize);
632: USBExpertStatusLevel (5, 123456789,
633: kP_UIMName"Isoch Endpoint create- success, new available = ",
634: pOHCIUIMData->isochBandwidthAvail);
635: return (kIOReturnSuccess);
636: }
637:
638:
639: IOReturn AppleOHCI::UIMCreateIsochTransfer(
640: short functionAddress,
641: short endpointNumber,
642: IOUSBIsocCompletion completion,
643: UInt8 direction,
644: UInt64 frameNumberStart,
645: IOMemoryDescriptor * pBuffer,
646: UInt32 frameCount,
647: IOUSBIsocFrame *pFrames)
648: {
649: IOReturn status = kIOReturnSuccess;
650: OHCIIsochTransferDescriptorPtr pTailITD = nil;
651: OHCIIsochTransferDescriptorPtr pNewITD = nil;
652: OHCIIsochTransferDescriptorPtr pTempITD = nil;
653: UInt32 i;
654: UInt32 curFrameInRequest = 0;
655: UInt32 bufferSize = 0;
656: UInt32 pageOffset = 0;
657: UInt32 curFrameLength;
658: UInt32 lastPhysical = 0;
659: OHCIEndpointDescriptorPtr pED;
660: UInt32 curFrameInTD = 0;
661: UInt16 frameNumber = (UInt16) frameNumberStart;
662: UInt64 curFrameNumber = GetFrameNumber();
663: UInt64 frameDiff;
664: UInt64 maxOffset = (UInt64)(0x00007FF0);
665: UInt32 diff32;
666:
667: UInt32 itdFlags = 0;
668: UInt32 numSegs = 0;
669: UInt32 physPageStart = 0;
670: UInt32 physPageEnd = 0;
671: UInt32 pageSelectMask = 0;
672: bool needNewITD;
673: IOPhysicalSegment segs[2];
674: UInt32 tdType;
675: IOByteCount transferOffset;
676: #if 0
677: AbsoluteTime startTime = UpTime();
678: Duration elapsedTime;
679: #endif
680:
681: if ((frameCount == 0) || (frameCount > 1000))
682: {
683: USBExpertStatusLevel (3, 123456789, kP_UIMName"Isoch transfer- bad frameCount", kIOReturnBadArgument);
684: return kIOReturnBadArgument;
685: }
686:
687: if (direction == kUSBOut) {
688: direction = kOHCIEDDirectionOut;
689: tdType = kOHCIIsochronousOutType;
690: }
691: else if (direction == kUSBIn) {
692: direction = kOHCIEDDirectionIn;
693: tdType = kOHCIIsochronousInType;
694: }
695: else
696: return kIOReturnInternalError;
697:
698: pED = FindIsochronousEndpoint(functionAddress, endpointNumber, direction, nil);
699:
700: if (!pED)
701: {
702: USBExpertStatusLevel (3, 123456789, kP_UIMName"Isoch transfer- endpoint not found, err:", kIOUSBEndpointNotFound);
703: return kIOUSBEndpointNotFound;
704: }
705:
706: if (frameNumberStart <= curFrameNumber)
707: {
708: if (frameNumberStart < (curFrameNumber - maxOffset))
709: {
710: USBExpertStatusLevel (3, 123456789, kP_UIMName"Isoch transfer- frameNumberStart:", (UInt32)frameNumberStart);
711: USBExpertStatusLevel (3, 123456789, kP_UIMName"Isoch transfer- curFrameNumber:", (UInt32)curFrameNumber);
712: USBExpertStatusLevel (3, 123456789, kP_UIMName"Isoch transfer- request frame WAY too old, err:", kIOReturnIsoTooOld);
713: return kIOReturnIsoTooOld;
714: }
715: USBExpertStatusLevel (3, 123456789, kP_UIMName"Isoch transfer- WARNING! curframe later than requested, expect some notSent errors!", 0);
716: USBExpertStatusLevel (3, 123456789, kP_UIMName"Isoch transfer- frameNumberStart:", (UInt32)frameNumberStart);
717: USBExpertStatusLevel (3, 123456789, kP_UIMName"Isoch transfer- curFrameNumber:", (UInt32)curFrameNumber);
718: USBExpertStatusLevel (3, 123456789, kP_UIMName"USBIsocFrame Ptr:", (UInt32)pFrames);
719: USBExpertStatusLevel (3, 123456789, kP_UIMName"Isoch transfer- First ITD:", (UInt32)pED->pLogicalTailP);
720: } else { // frameNumberStart > curFrameNumber
721: if (frameNumberStart > (curFrameNumber + maxOffset))
722: {
723: USBExpertStatusLevel (3, 123456789, kP_UIMName"Isoch transfer- frameNumberStart:", (UInt32)frameNumberStart);
724: USBExpertStatusLevel (3, 123456789, kP_UIMName"Isoch transfer- curFrameNumber:", (UInt32)curFrameNumber);
725: USBExpertStatusLevel (3, 123456789, kP_UIMName"Isoch transfer- request frame too far ahead, err:", kIOReturnIsoTooNew);
726: return kIOReturnIsoTooNew;
727: }
728: frameDiff = frameNumberStart - curFrameNumber;
729: diff32 = (UInt32)frameDiff;
730: if (diff32 < 2)
731: {
732: USBExpertStatusLevel (5, 123456789, kP_UIMName"Isoch transfer- WARNING! - frameNumberStart less than 2 ms.", diff32);
733: USBExpertStatusLevel (5, 123456789, kP_UIMName"Isoch transfer- frameNumberStart:", (UInt32)frameNumberStart);
734: USBExpertStatusLevel (5, 123456789, kP_UIMName"Isoch transfer- curFrameNumber:", (UInt32)curFrameNumber);
735: }
736: }
737:
738: //
739: // Get the total size of buffer
740: //
741: for ( i = 0; i< frameCount; i++)
742: {
743: if (pFrames[i].frReqCount > kUSBMaxIsocFrameReqCount)
744: {
745: USBExpertStatusLevel (3, 123456789, kP_UIMName"Isoch frame too big:", pFrames[i].frReqCount);
746: return kIOReturnBadArgument;
747: }
748: bufferSize += pFrames[i].frReqCount;
749: }
750:
751: if (direction == kOHCIEDDirectionIn)
752: USBExpertStatusLevel (5, 123456789, kP_UIMName"Isoch transfer in, buffer:",
753: (UInt32)pBuffer);
754: else
755: USBExpertStatusLevel (5, 123456789, kP_UIMName"Isoch transfer out, buffer:",
756: (UInt32)pBuffer);
757: USBExpertStatusLevel (5, 123456789, kP_UIMName"Isoch transfer total length:",
758: bufferSize);
759:
760: //
761: // go ahead and make sure we can grab at least ONE TD, before we lock the buffer
762: //
763: pNewITD = OHCIUIMAllocateITD();
764: if (pNewITD == nil)
765: {
766: return kIOReturnNoMemory;
767: }
768:
769: if (!bufferSize) {
770: // Set up suitable dummy info
771: numSegs = 1;
772: segs[0].location = segs[0].length = 0;
773: pageOffset = 0;
774: }
775: pTailITD = (OHCIIsochTransferDescriptorPtr)pED->pLogicalTailP; // start with the unused TD on the tail of the list
776: OSWriteLittleInt32(&pTailITD->nextTD, 0, pNewITD->pPhysical); // link in the new ITD
777: pTailITD->pLogicalNext = pNewITD;
778:
779: needNewITD = false;
780: transferOffset = 0;
781: while (curFrameInRequest < frameCount) {
782: // Get physical segments for next frame
783: if(!needNewITD && bufferSize) {
784: numSegs = _isoCursor->getPhysicalSegments(pBuffer, transferOffset,
785: segs, 2, pFrames[curFrameInRequest].frReqCount);
786: #if 0
787: IOLog("F%ld (%d): numSegs = %ld, (0x%lx, 0x%lx), (0x%lx, 0x%lx)\n", curFrameInRequest,
788: pFrames[curFrameInRequest].frReqCount, numSegs, segs[0].location, segs[0].length,
789: segs[1].location, segs[1].length);
790: #endif
791: pageOffset = segs[0].location & kOHCIPageOffsetMask;
792: transferOffset += segs[0].length;
793: if(numSegs == 2)
794: transferOffset += segs[1].length;
795: }
796:
797: if (curFrameInTD == 0) {
798: // set up counters which get reinitialized with each TD
799: physPageStart = segs[0].location & kOHCIPageMask; // for calculating real 13 bit offsets
800: pageSelectMask = 0; // First frame always starts on first page
801: needNewITD = false;
802:
803: // set up the header of the TD - itdFlags will be stored into flags later
804: itdFlags = (UInt16)(curFrameInRequest + frameNumber);
805: pTailITD->pIsocFrame = pFrames; // so we can get back to our info later
806: pTailITD->frameNum = curFrameInRequest; // our own index into the above array
807: pTailITD->pType = tdType; // So interrupt handler knows TD type.
808: OSWriteLittleInt32(&pTailITD->bufferPage0, 0, physPageStart);
809: }
810: else if ((segs[0].location & kOHCIPageMask) != physPageStart) {
811: // pageSelectMask is set if we've already used our one allowed page cross.
812: if(pageSelectMask &&
813: (((segs[0].location & kOHCIPageMask) != physPageEnd) || numSegs == 2)) {
814: // Need new ITD for this
815: needNewITD = true;
816: continue;
817: }
818: pageSelectMask = kOHCIPageSize; // ie. set bit 13
819: physPageEnd = segs[numSegs-1].location & kOHCIPageMask;
820: }
821: curFrameLength = pFrames[curFrameInRequest].frReqCount;
822: if ((curFrameInTD > 7) || needNewITD) {
823: // we need to start a new TD
824: needNewITD = true; // To simplify test at top of loop.
825: itdFlags |= (curFrameInTD-1) << kOHCIITDControl_FCPhase;
826: OSWriteLittleInt32(&pTailITD->bufferEnd, 0, lastPhysical);
827: curFrameInTD = 0;
828: pNewITD = OHCIUIMAllocateITD();
829: if (pNewITD == nil) {
830: status = kIOReturnNoMemory;
831: break;
832: }
833: // Handy for debugging transfer lists
834: itdFlags |= (kOHCIGTDConditionNotAccessed << kOHCIGTDControl_CCPhase);
835: OSWriteLittleInt32(&pTailITD->flags, 0, itdFlags);
836: pTailITD->completion.action = NULL;
837: pTailITD = pTailITD->pLogicalNext; // this is the "old" pNewTD
838: OSWriteLittleInt32(&pTailITD->nextTD, 0, pNewITD->pPhysical); // link to the "new" pNewTD
839: pTailITD->pLogicalNext = pNewITD;
840: continue; // start over
841: }
842: //
843: // at this point we know we have a frame which will fit into the current TD
844: //
845: // calculate the buffer offset for the beginning of this frame
846: OSWriteLittleInt16(&pTailITD->offset[curFrameInTD], 0,
847: pageOffset | // offset
848: pageSelectMask | // offset from BP0 or BufferEnd
849: (kOHCIITDOffsetConditionNotAccessed << kOHCIITDOffset_CCPhase)); // mark as unused
850:
851: // adjust counters and calculate the physical offset of the end of the frame for the next time around the loop
852: curFrameInRequest++;
853: curFrameInTD++;
854: lastPhysical = segs[numSegs-1].location + segs[numSegs-1].length - 1;
855: }
856:
857: if (status != kIOReturnSuccess)
858: {
859: // unlink the TDs, unlock the buffer, and return the status
860: pNewITD = pTailITD->pLogicalNext; // point to the "old" pNewTD, which will also get deallocated
861: pTempITD = (OHCIIsochTransferDescriptorPtr)pED->pLogicalTailP;
862: pTailITD = pTempITD->pLogicalNext; // don't deallocate the real tail!
863: pTempITD->pLogicalNext = nil; // just to make sure
864: pTempITD->nextTD = nil; // just to make sure
865: while (pTailITD != pNewITD)
866: {
867: pTempITD = pTailITD;
868: pTailITD = pTailITD->pLogicalNext;
869: OHCIUIMDeallocateITD(pTempITD);
870: }
871: }
872: else
873: {
874: // we have good status, so let's kick off the machine
875: // we need to tidy up the last TD, which is not yet complete
876: itdFlags |= (curFrameInTD-1) << kOHCIITDControl_FCPhase;
877: OSWriteLittleInt32(&pTailITD->flags, 0, itdFlags);
878: OSWriteLittleInt32(&pTailITD->bufferEnd, 0, lastPhysical);
879: pTailITD->completion = completion;
880: //print_itd(pTailITD);
881: // Make new descriptor the tail
882: pED->pLogicalTailP = pNewITD;
883: OSWriteLittleInt32(&pED->tdQueueTailPtr, 0, pNewITD->pPhysical);
884: }
885:
886: #if 0
887: elapsedTime = AbsoluteDeltaToDuration(UpTime(), startTime);
888: if ((elapsedTime > 0) || (elapsedTime < -700)) // measured in milliseconds or more than 700 microseconds to queue everything
889: {
890: USBExpertStatusLevel (4, 123456789, kP_UIMName"Isoch WARNING! > 1 ms (or getting close): ", elapsedTime);
891: USBExpertStatusLevel (4, 123456789, kP_UIMName"Isoch transfer frame count: ", frameCount);
892: USBExpertStatusLevel (4, 123456789, kP_UIMName"Isoch transfer buffer size: ", bufferSize);
893: }
894: #endif
895: //print_isoc_ed(pED);
896:
897: return status;
898:
899: }
900:
901: IOReturn AppleOHCI::UIMAbortEndpoint(
902: short functionAddress,
903: short endpointNumber,
904: short direction)
905: {
906: OHCIRegistersPtr pOHCIRegisters;
907: OHCIEndpointDescriptorPtr pED;
908: OHCIEndpointDescriptorPtr pEDQueueBack;
909: UInt32 something, controlMask;
910:
911: if (functionAddress == 0)
912: {
913: IOLog("UIMAbortEndpoint: Error: operation on root hub\n");
914: return(kIOReturnSuccess);
915: }
916:
917: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
918:
919: if (direction == kUSBOut)
920: direction = kOHCIEDDirectionOut;
921: else if (direction == kUSBIn)
922: direction = kOHCIEDDirectionIn;
923: else
924: direction = kOHCIEDDirectionTD;
925:
926: //search for endpoint descriptor
927: pED = FindEndpoint (functionAddress,
928: endpointNumber,
929: direction,
930: &pEDQueueBack,
931: &controlMask);
932: if (!pED)
933: {
934: IOLog("UIMAbortEndpoint: Error: Could not find endpoint\n");
935: return (kIOUSBEndpointNotFound);
936: }
937:
938: pED->flags |= OSSwapInt32(kOHCIEDControl_K); // mark the ED as skipped
939:
940: // poll for interrupt zzzzz turn into real interrupt
941: pOHCIRegisters->hcInterruptStatus = OSSwapInt32(kOHCIHcInterrupt_SF);
942: IOSleep(1);
943: something = OSSwapInt32(pOHCIRegisters->hcInterruptStatus)
944: & kOHCIInterruptSOFMask;
945:
946: if (!something)
947: {
948: /* This should have been set, just in case wait another ms */
949: IOSleep(1);
950: }
951:
952: RemoveTDs(pED);
953:
954: pED->flags &= ~OSSwapInt32(kOHCIEDControl_K); // activate ED again
955:
956:
957: return (kIOReturnSuccess);
958: }
959:
960: IOReturn AppleOHCI::UIMDeleteEndpoint(
961: short functionAddress,
962: short endpointNumber,
963: short direction)
964: {
965: OHCIRegistersPtr pOHCIRegisters;
966: OHCIEndpointDescriptorPtr pED;
967: OHCIEndpointDescriptorPtr pEDQueueBack;
968: UInt32 hcControl;
969: UInt32 something, controlMask;
970: // UInt32 edDirection;
971:
972:
973: #if 0
974: if (functionAddress == 0)
975: {
976: IOLog("UIMDeleteEndpoint: Error: operation on root hub\n");
977: return(kIOReturnSuccess);
978: }
979: #endif
980:
981: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
982:
983: if (direction == kUSBOut)
984: direction = kOHCIEDDirectionOut;
985: else if (direction == kUSBIn)
986: direction = kOHCIEDDirectionIn;
987: else
988: direction = kOHCIEDDirectionTD;
989:
990: //search for endpoint descriptor
991: pED = FindEndpoint (functionAddress,
992: endpointNumber,
993: direction,
994: &pEDQueueBack,
995: &controlMask);
996: if (!pED)
997: {
998: DEBUGLOG("UIMDeleteEndpoint: Error: Could not find endpoint\n");
999: return (kIOUSBEndpointNotFound);
1000: }
1001:
1002: // Remove Endpoint
1003: //mark sKipped
1004: pED->flags |= OSSwapInt32(kOHCIEDControl_K);
1005: // edDirection = OSSwapInt32(pED->dWord0) & kOHCIEndpointDirectionMask;
1006: // remove pointer wraps
1007: pEDQueueBack->nextED = pED->nextED;
1008: pEDQueueBack->pLogicalNext = pED->pLogicalNext;
1009:
1010: // clear some bit in hcControl
1011: hcControl = OSSwapInt32(pOHCIRegisters->hcControl);
1012: hcControl &= ~controlMask;
1013: hcControl &= OHCIBitRange(0, 10);
1014:
1015: pOHCIRegisters->hcControl = OSSwapInt32(hcControl);
1016:
1017: // poll for interrupt zzzzz turn into real interrupt
1018: pOHCIRegisters->hcInterruptStatus = OSSwapInt32(kOHCIHcInterrupt_SF);
1019: IOSleep(1);
1020: something = OSSwapInt32(pOHCIRegisters->hcInterruptStatus)
1021: & kOHCIInterruptSOFMask;
1022: if (!something)
1023: {
1024: /* This should have been set, just in case wait another ms */
1025: IOSleep(1);
1026: }
1027: // restart hcControl
1028: hcControl |= controlMask;
1029: pOHCIRegisters->hcControl = OSSwapInt32(hcControl);
1030:
1031: #if (DEBUGGING_LEVEL > 0)
1032: DEBUGLOG("UIMDeleteEndpoint: pED=%lx hcControl=%lx SOF int?=%s\n",
1033: (UInt32)pED, hcControl, something?"yes":"no");
1034: #endif
1035: if (GetEDType(pED) == kOHCIEDFormatIsochronousTD)
1036: {
1037: UInt32 maxPacketSize = (OSReadLittleInt32(&pED->flags, 0) & kOHCIEDControl_MPS) >>
1038: kOHCIEDControl_MPSPhase;
1039: pOHCIUIMData->isochBandwidthAvail += maxPacketSize;
1040: USBExpertStatusLevel (5, 123456789,
1041: kP_UIMName"Isoch Endpoint delete- bandwidth returned = ", maxPacketSize);
1042: USBExpertStatusLevel (5, 123456789,
1043: kP_UIMName"Isoch Endpoint delete- new available = ", pOHCIUIMData->isochBandwidthAvail);
1044: }
1045: RemoveAllTDs(pED);
1046:
1047: pED->nextED = nil;
1048:
1049: //deallocate ED
1050: OHCIUIMDeallocateED(pED);
1051: #if (DEBUGGING_LEVEL > 2)
1052: print_bulk_list(pOHCIUIMData);
1053: print_control_list(pOHCIUIMData);
1054: #endif
1055: return (kIOReturnSuccess);
1056: }
1057:
1058: void AppleOHCI::ReturnTransactions(
1059: OHCIGeneralTransferDescriptor *transaction,
1060: UInt32 tail)
1061: {
1062: UInt32 physicalAddress;
1063: OHCIGeneralTransferDescriptor *nextTransaction;
1064:
1065: while(transaction->pPhysical != tail)
1066: {
1067: if (transaction->completion.action != nil) {
1068: IOUSBCompletion completion;
1069: // zero out callback first then call it
1070: completion = transaction->completion;
1071: transaction->completion.action = nil;
1072: complete(completion, kIOUSBPipeStalled, 0);
1073: }
1074: /* walk the physically-addressed list */
1075: physicalAddress =
1076: OSSwapInt32(transaction->nextTD) & kOHCIHeadPMask;
1077: nextTransaction = (OHCIGeneralTransferDescriptorPtr)
1078: OHCIUIMGetLogicalAddress (physicalAddress);
1079: OHCIUIMDeallocateTD(transaction);
1080: transaction = nextTransaction;
1081: if(transaction == nil)
1082: {
1083: IOLog("returnTransactions: Return queue broken");
1084: break;
1085: }
1086: }
1087: }
1088:
1089: IOReturn AppleOHCI::UIMClearEndpointStall(
1090: short functionAddress,
1091: short endpointNumber,
1092: short direction)
1093: {
1094: OHCIRegistersPtr pOHCIRegisters;
1095: OHCIEndpointDescriptorPtr pEDQueueBack, pED;
1096: OHCIGeneralTransferDescriptor *transaction;
1097: UInt32 tail, controlMask;
1098:
1099:
1100: #if DEBUGGING_LEVEL > 0
1101: DEBUGLOG("%s: clearing endpoint %d:%d stall\n", getName(), functionAddress, endpointNumber);
1102: #endif
1103:
1104: if (pOHCIUIMData->rootHubFuncAddress == functionAddress)
1105: {
1106: IOLog("UIMDeleteEndpoint: Error: operation on root hub\n");
1107: return(kIOReturnSuccess);
1108: }
1109:
1110: if (direction == kUSBOut)
1111: direction = kOHCIEDDirectionOut;
1112: else if (direction == kUSBIn)
1113: direction = kOHCIEDDirectionIn;
1114: else
1115: direction = kOHCIEDDirectionTD;
1116:
1117: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
1118:
1119: transaction = nil;
1120: tail = nil;
1121: //search for endpoint descriptor
1122: pED = FindEndpoint (functionAddress,
1123: endpointNumber,
1124: direction,
1125: &pEDQueueBack,
1126: &controlMask);
1127: if (!pED)
1128: {
1129: IOLog("UIMDeleteEndpoint: Error: Could not find endpoint\n");
1130: return (kIOUSBEndpointNotFound);
1131: }
1132:
1133: if (pED != nil)
1134: {
1135: tail = OSSwapInt32(pED->tdQueueTailPtr);
1136: transaction = (OHCIGeneralTransferDescriptor *)
1137: OHCIUIMGetLogicalAddress(OSSwapInt32(pED->tdQueueHeadPtr) & kOHCIHeadPMask);
1138: /* unlink all transactions at once (this also clears the halted bit) */
1139: pED->tdQueueHeadPtr = pED->tdQueueTailPtr;
1140: pED->pLogicalHeadP = pED->pLogicalTailP;
1141: }
1142:
1143: if (transaction != nil)
1144: {
1145: ReturnTransactions(transaction, tail);
1146: }
1147: return (kIOReturnSuccess);
1148: }
1149:
1150: OHCIEndpointDescriptorPtr AppleOHCI::AddEmptyEndPoint(
1151: UInt8 functionAddress,
1152: UInt8 endpointNumber,
1153: UInt16 maxPacketSize,
1154: UInt8 speed,
1155: UInt8 direction,
1156: OHCIEndpointDescriptorPtr pED,
1157: OHCIEDFormat format)
1158: {
1159: UInt32 myFunctionAddress,
1160: myEndpointNumber,
1161: myEndpointDirection,
1162: myMaxPacketSize,
1163: mySpeed,
1164: myFormat;
1165: OHCIEndpointDescriptorPtr pOHCIEndpointDescriptor;
1166: OHCIGeneralTransferDescriptorPtr pOHCIGeneralTransferDescriptor;
1167: OHCIIsochTransferDescriptorPtr pITD;
1168:
1169:
1170: pOHCIEndpointDescriptor = (OHCIEndpointDescriptorPtr) OHCIUIMAllocateED();
1171: myFunctionAddress = ((UInt32) functionAddress) << kOHCIEDControl_FAPhase;
1172: myEndpointNumber = ((UInt32) endpointNumber) << kOHCIEDControl_ENPhase;
1173: myEndpointDirection = ((UInt32) direction) << kOHCIEDControl_DPhase;
1174: mySpeed = ((UInt32) speed) << kOHCIEDControl_SPhase;
1175: myMaxPacketSize = ((UInt32) maxPacketSize) << kOHCIEDControl_MPSPhase;
1176: myFormat = ((UInt32) format) << kOHCIEDControl_FPhase;
1177: pOHCIEndpointDescriptor->flags =
1178: OSSwapInt32(myFunctionAddress
1179: | myEndpointNumber
1180: | myEndpointDirection
1181: | myMaxPacketSize
1182: | mySpeed
1183: | myFormat);
1184:
1185: if (format == kOHCIEDFormatGeneralTD)
1186: {
1187: pOHCIGeneralTransferDescriptor = OHCIUIMAllocateTD();
1188:
1189: /* These were previously nil */
1190: pOHCIEndpointDescriptor->tdQueueTailPtr =
1191: OSSwapInt32( pOHCIGeneralTransferDescriptor->pPhysical);
1192: pOHCIEndpointDescriptor->tdQueueHeadPtr =
1193: OSSwapInt32( pOHCIGeneralTransferDescriptor->pPhysical);
1194: pOHCIEndpointDescriptor->pLogicalTailP =
1195: pOHCIGeneralTransferDescriptor;
1196: pOHCIEndpointDescriptor->pLogicalHeadP =
1197: pOHCIGeneralTransferDescriptor;
1198: }
1199: else
1200: {
1201: pITD = OHCIUIMAllocateITD();
1202:
1203: /* These were previously nil */
1204: pOHCIEndpointDescriptor->tdQueueTailPtr =
1205: OSSwapInt32( pITD->pPhysical);
1206: pOHCIEndpointDescriptor->tdQueueHeadPtr =
1207: OSSwapInt32( pITD->pPhysical);
1208: pOHCIEndpointDescriptor->pLogicalTailP = pITD;
1209: pOHCIEndpointDescriptor->pLogicalHeadP = pITD;
1210:
1211: }
1212:
1213: pOHCIEndpointDescriptor->nextED = pED->nextED;
1214: pOHCIEndpointDescriptor->pLogicalNext = pED->pLogicalNext;
1215: pED->pLogicalNext = pOHCIEndpointDescriptor;
1216: pED->nextED = OSSwapInt32(pOHCIEndpointDescriptor->pPhysical);
1217:
1218: return (pOHCIEndpointDescriptor);
1219: }
1220:
1221: OHCIEndpointDescriptorPtr AppleOHCI::FindControlEndpoint (
1222: short functionNumber,
1223: short endpointNumber,
1224: OHCIEndpointDescriptorPtr *pEDBack)
1225: {
1226: UInt32 unique;
1227: OHCIEndpointDescriptorPtr pEDQueue;
1228: OHCIEndpointDescriptorPtr pEDQueueBack;
1229:
1230:
1231: // search for endpoint descriptor
1232: unique = (UInt32) ((((UInt32) endpointNumber) << kOHCIEndpointNumberOffset)
1233: | ((UInt32) functionNumber));
1234: pEDQueueBack = (OHCIEndpointDescriptorPtr) pOHCIUIMData->pControlHead;
1235: pEDQueue = (OHCIEndpointDescriptorPtr) pEDQueueBack->pLogicalNext;
1236:
1237: while ((UInt32) pEDQueue != pOHCIUIMData->pControlTail)
1238: {
1239: if ((OSSwapInt32(pEDQueue->flags) & kUniqueNumNoDirMask) == unique)
1240: {
1241: *pEDBack = pEDQueueBack;
1242: return (pEDQueue);
1243: }
1244: else
1245: {
1246: pEDQueueBack = pEDQueue;
1247: pEDQueue = (OHCIEndpointDescriptorPtr) pEDQueue->pLogicalNext;
1248: }
1249: }
1250: if (pOHCIUIMData->OptiOn)
1251: {
1252: pEDQueue = FindBulkEndpoint (functionNumber, endpointNumber,
1253: kOHCIEDDirectionTD, &pEDQueueBack);
1254: *pEDBack = pEDQueueBack;
1255: return (pEDQueue);
1256: }
1257: return (nil);
1258: }
1259:
1260:
1261: OHCIEndpointDescriptorPtr AppleOHCI::FindBulkEndpoint (
1262: short functionNumber,
1263: short endpointNumber,
1264: short direction,
1265: OHCIEndpointDescriptorPtr *pEDBack)
1266: {
1267:
1268: UInt32 unique;
1269: UInt32 myEndpointDirection;
1270: OHCIEndpointDescriptorPtr pEDQueue;
1271: OHCIEndpointDescriptorPtr pEDQueueBack;
1272:
1273:
1274: // search for endpoint descriptor
1275: myEndpointDirection = ((UInt32) direction) << kOHCIEndpointDirectionOffset;
1276: unique = (UInt32) ((((UInt32) endpointNumber) << kOHCIEndpointNumberOffset)
1277: | ((UInt32) functionNumber) | myEndpointDirection);
1278: pEDQueueBack = (OHCIEndpointDescriptorPtr) pOHCIUIMData->pBulkHead;
1279: pEDQueue = (OHCIEndpointDescriptorPtr) pEDQueueBack->pLogicalNext;
1280:
1281: while (((UInt32) pEDQueue) != pOHCIUIMData->pBulkTail )
1282: {
1283: if ((OSSwapInt32(pEDQueue->flags) & kUniqueNumMask) == unique)
1284: {
1285: *pEDBack = pEDQueueBack;
1286: return (pEDQueue);
1287: }
1288: else
1289: {
1290: pEDQueueBack = pEDQueue;
1291: pEDQueue = (OHCIEndpointDescriptorPtr) pEDQueue->pLogicalNext;
1292: }
1293: }
1294: return (nil);
1295: }
1296:
1297:
1298: OHCIEndpointDescriptorPtr AppleOHCI::FindEndpoint (
1299: short functionNumber,
1300: short endpointNumber,
1301: short direction,
1302: OHCIEndpointDescriptorPtr *pEDQueueBack,
1303: UInt32 *controlMask)
1304: {
1305: OHCIEndpointDescriptorPtr pED, pEDBack;
1306:
1307: pED = FindControlEndpoint (functionNumber, endpointNumber, &pEDBack);
1308: if (pED != nil)
1309: {
1310: *pEDQueueBack = pEDBack;
1311: *controlMask = kOHCIHcControl_CLE;
1312: return (pED);
1313: }
1314:
1315: pED = FindBulkEndpoint(functionNumber, endpointNumber, direction, &pEDBack);
1316: if (pED != nil)
1317: {
1318: *pEDQueueBack = pEDBack;
1319:
1320: *controlMask = kOHCIHcControl_BLE;
1321: //zzzz Opti Bug
1322: if(pOHCIUIMData->OptiOn)
1323: *controlMask = kOHCIHcControl_CLE;
1324: return (pED);
1325: }
1326:
1327: pED = FindInterruptEndpoint(functionNumber, endpointNumber, direction,
1328: &pEDBack);
1329: if (pED != nil)
1330: {
1331: *pEDQueueBack = pEDBack;
1332: *controlMask = 0;
1333: return (pED);
1334: }
1335:
1336: pED = FindIsochronousEndpoint(functionNumber, endpointNumber,
1337: direction, &pEDBack);
1338: *pEDQueueBack = pEDBack;
1339: *controlMask = 0;
1340: return (pED);
1341: }
1342:
1343:
1344: OHCIEndpointDescriptorPtr AppleOHCI::FindIsochronousEndpoint(
1345: short functionNumber,
1346: short endpointNumber,
1347: short direction,
1348: OHCIEndpointDescriptorPtr *pEDBack)
1349: {
1350: UInt32 myEndpointDirection;
1351: UInt32 unique;
1352: OHCIEndpointDescriptorPtr pEDQueue, pEDQueueBack;
1353:
1354: // search for endpoint descriptor
1355: myEndpointDirection = ((UInt32) direction) << kOHCIEndpointDirectionOffset;
1356: unique = (UInt32) ((((UInt32) endpointNumber) << kOHCIEndpointNumberOffset)
1357: | ((UInt32) functionNumber) | myEndpointDirection);
1358:
1359: pEDQueueBack = (OHCIEndpointDescriptorPtr) pOHCIUIMData->pIsochHead;
1360: pEDQueue = (OHCIEndpointDescriptorPtr) pEDQueueBack->pLogicalNext;
1361: while (((UInt32) pEDQueue) != pOHCIUIMData->pIsochTail )
1362: {
1363: if ((OSSwapInt32(pEDQueue->flags) & kUniqueNumMask) == unique)
1364: {
1365: if(pEDBack)
1366: *pEDBack = pEDQueueBack;
1367: return (pEDQueue);
1368: }
1369: else
1370: {
1371: pEDQueueBack = pEDQueue;
1372: pEDQueue = (OHCIEndpointDescriptorPtr) pEDQueue->pLogicalNext;
1373: }
1374: }
1375: return (nil);
1376: }
1377:
1378:
1379: OHCIEndpointDescriptorPtr AppleOHCI::FindInterruptEndpoint(
1380: short functionNumber,
1381: short endpointNumber,
1382: short direction,
1383: OHCIEndpointDescriptorPtr *pEDBack)
1384: {
1385: OHCIRegistersPtr pOHCIRegisters;
1386: UInt32 myEndpointDirection;
1387: UInt32 unique;
1388: OHCIEndpointDescriptorPtr pEDQueue;
1389: OHCIIntHeadPtr pInterruptHead;
1390: int i;
1391: UInt32 temp;
1392:
1393: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
1394: pInterruptHead = pOHCIUIMData->pInterruptHead;
1395:
1396: //search for endpoint descriptor
1397: myEndpointDirection = ((UInt32) direction) << kOHCIEndpointDirectionOffset;
1398: unique = (UInt32) ((((UInt32) endpointNumber) << kOHCIEDControl_ENPhase)
1399: | (((UInt32) functionNumber) << kOHCIEDControl_FAPhase)
1400: | myEndpointDirection);
1401:
1402: for (i = 0; i < 63; i++)
1403: {
1404: pEDQueue = pInterruptHead[i].pHead;
1405: *pEDBack = pEDQueue;
1406: // BT do this first, or you find the dummy endpoint
1407: // all this is hanging off. It matches 0,0
1408: pEDQueue = (OHCIEndpointDescriptorPtr) pEDQueue->pLogicalNext;
1409: while (pEDQueue != pInterruptHead[i].pTail)
1410: {
1411: temp = (OSSwapInt32(pEDQueue->flags)) & kUniqueNumMask;
1412:
1413: if ( temp == unique)
1414: {
1415: return(pEDQueue);
1416: }
1417: *pEDBack = pEDQueue;
1418: pEDQueue = (OHCIEndpointDescriptorPtr) pEDQueue->pLogicalNext;
1419: }
1420: }
1421: return(nil);
1422: }
1423:
1424: bool AppleOHCI::DetermineInterruptOffset(
1425: UInt32 pollingRate,
1426: UInt32 /* reserveBandwidth */,
1427: int *offset)
1428: {
1429: int num;
1430: OHCIRegistersPtr pOHCIRegisters;
1431:
1432: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
1433:
1434: num = OSSwapInt32(pOHCIRegisters->hcFmNumber)&kOHCIFmNumberMask;
1435: if (pollingRate < 1)
1436: //error condition
1437: return(false);
1438: else if(pollingRate < 2)
1439: *offset = 62;
1440: else if(pollingRate < 4)
1441: *offset = (num%2) + 60;
1442: else if(pollingRate < 8)
1443: *offset = (num%4) + 56;
1444: else if(pollingRate < 16)
1445: *offset = (num%8) + 48;
1446: else if(pollingRate < 32)
1447: *offset = (num%16) + 32;
1448: else
1449: *offset = (num%32) + 0;
1450: return (true);
1451: }
1452:
1453: static char *cc_errors[] = {
1454: "NO ERROR", /* 0 */
1455: "CRC", /* 0 */
1456: "BIT STUFFING", /* 0 */
1457: "DATA TOGGLE MISMATCH", /* 0 */
1458: "STALL", /* 0 */
1459: "DEVICE NOT RESPONDING", /* 0 */
1460: "PID CHECK FAILURE", /* 0 */
1461: "UNEXPECTED PID", /* 0 */
1462: "DATA OVERRUN", /* 0 */
1463: "DATA UNDERRUN", /* 0 */
1464: "??", /* reserved */
1465: "??", /* reserved */
1466: "BUFFER OVERRUN", /* 0 */
1467: "BUFFER UNDERRUN", /* 0 */
1468: "NOT ACCESSED A", /* not processed yet */
1469: "NOT ACCESSED B" /* not processed yet */
1470: };
1471:
1472: void print_td(OHCIGeneralTransferDescriptorPtr pTD)
1473: {
1474: UInt32 w0, dir, err;
1475:
1476: if (pTD == 0) return;
1477:
1478: w0 = OSSwapInt32(pTD->flags);
1479: dir = (w0 & kOHCIGTDControl_DP) >> kOHCIGTDControl_DPPhase;
1480: err = (w0 & kOHCIGTDControl_CC) >> kOHCIGTDControl_CCPhase;
1481: DEBUGLOG("\tTD(0x%08lx->0x%08lx) dir=%s cc=%s errc=%ld t=%ld rd=%s: c=0x%08lx cbp=0x%08lx, next=0x%08lx, bend=0x%08lx\n",
1482: (UInt32)pTD, pTD->pPhysical,
1483: dir == 0 ? "SETUP" : (dir==2?"IN":"OUT"),
1484: cc_errors[err],
1485: (w0 & kOHCIGTDControl_EC) >> kOHCIGTDControl_ECPhase,
1486: (w0 & kOHCIGTDControl_T) >> kOHCIGTDControl_TPhase,
1487: (w0 & kOHCIGTDControl_R)?"yes":"no",
1488: OSSwapInt32(pTD->flags),
1489: OSSwapInt32(pTD->currentBufferPtr),
1490: OSSwapInt32(pTD->nextTD),
1491: OSSwapInt32(pTD->bufferEnd));
1492: }
1493:
1494: void print_itd(OHCIIsochTransferDescriptorPtr pTD)
1495: {
1496: UInt32 w0, err;
1497: int i;
1498: if (pTD == 0) return;
1499:
1500: w0 = OSReadLittleInt32(&pTD->flags, 0);
1501: err = (w0 & kOHCIITDControl_CC) >> kOHCIITDControl_CCPhase;
1502: DEBUGLOG("\tTD(0x%08lx->0x%08lx) cc=%s fc=%ld sf=0x%lx c=0x%08lx bp0=0x%08lx, next=0x%08lx, bend=0x%08lx\n",
1503: (UInt32)pTD, pTD->pPhysical,
1504: cc_errors[err],
1505: (w0 & kOHCIITDControl_FC) >> kOHCIITDControl_FCPhase,
1506: (w0 & kOHCIITDControl_SF) >> kOHCIITDControl_SFPhase,
1507: w0,
1508: OSSwapInt32(pTD->bufferPage0),
1509: OSSwapInt32(pTD->nextTD),
1510: OSSwapInt32(pTD->bufferEnd));
1511: for(i=0; i<8; i++) {
1512: DEBUGLOG("Offset/PSW %d = 0x%x\n", i, OSReadLittleInt16(&pTD->offset[i], 0));
1513: }
1514: DEBUGLOG("frames = 0x%lx, FrameNumber %ld\n", (UInt32)pTD->pIsocFrame, pTD->frameNum);
1515: }
1516:
1517: void print_ed(OHCIEndpointDescriptorPtr pED)
1518: {
1519: OHCIGeneralTransferDescriptorPtr pTD;
1520: UInt32 w0;
1521:
1522:
1523: if (pED == 0) {
1524: kprintf("Null ED\n");
1525: return;
1526: }
1527: w0 = OSSwapInt32(pED->flags);
1528:
1529: if ((w0 & kOHCIEDControl_K) == 0 /*noskip*/)
1530: {
1531: DEBUGLOG("ED(0x%08lx->0x%08lx) %ld:%ld d=%ld s=%s sk=%s i=%s max=%ld : c=0x%08lx tail=0x%08lx, head=0x%08lx, next=0x%08lx\n",
1532: (UInt32)pED, (UInt32)pED->pPhysical,
1533: (w0 & kOHCIEDControl_FA) >> kOHCIEDControl_FAPhase,
1534: (w0 & kOHCIEDControl_EN) >> kOHCIEDControl_ENPhase,
1535: (w0 & kOHCIEDControl_D) >> kOHCIEDControl_DPhase,
1536: w0 & kOHCIEDControl_S?"low":"hi",
1537: w0 & kOHCIEDControl_K?"yes":"no",
1538: w0 & kOHCIEDControl_F?"yes":"no",
1539: (w0 & kOHCIEDControl_MPS) >> kOHCIEDControl_MPSPhase,
1540: OSSwapInt32(pED->flags),
1541: OSSwapInt32(pED->tdQueueTailPtr),
1542: OSSwapInt32(pED->tdQueueHeadPtr),
1543: OSSwapInt32(pED->nextED));
1544:
1545: //pTD = (OHCIGeneralTransferDescriptorPtr) pED->pVirtualHeadP;
1546: pTD = (OHCIGeneralTransferDescriptorPtr)
1547: (OSSwapInt32(pED->tdQueueHeadPtr) & kOHCINextEndpointDescriptor_nextED);
1548:
1549: while (pTD != 0)
1550: {
1551: DEBUGLOG("\t");
1552: print_td(pTD);
1553: pTD = pTD->pLogicalNext;
1554: }
1555: }
1556: }
1557:
1558: void print_isoc_ed(OHCIEndpointDescriptorPtr pED)
1559: {
1560: OHCIIsochTransferDescriptorPtr pTD;
1561: UInt32 w0;
1562:
1563:
1564: if (pED == 0) {
1565: kprintf("Null ED\n");
1566: return;
1567: }
1568: w0 = OSSwapInt32(pED->flags);
1569:
1570: if ((w0 & kOHCIEDControl_K) == 0 /*noskip*/)
1571: {
1572: DEBUGLOG("ED(0x%08lx->0x%08lx) %ld:%ld d=%ld s=%s sk=%s i=%s max=%ld : c=0x%08lx tail=0x%08lx, head=0x%08lx, next=0x%08lx\n",
1573: (UInt32)pED, (UInt32)pED->pPhysical,
1574: (w0 & kOHCIEDControl_FA) >> kOHCIEDControl_FAPhase,
1575: (w0 & kOHCIEDControl_EN) >> kOHCIEDControl_ENPhase,
1576: (w0 & kOHCIEDControl_D) >> kOHCIEDControl_DPhase,
1577: w0 & kOHCIEDControl_S?"low":"hi",
1578: w0 & kOHCIEDControl_K?"yes":"no",
1579: w0 & kOHCIEDControl_F?"yes":"no",
1580: (w0 & kOHCIEDControl_MPS) >> kOHCIEDControl_MPSPhase,
1581: OSSwapInt32(pED->flags),
1582: OSSwapInt32(pED->tdQueueTailPtr),
1583: OSSwapInt32(pED->tdQueueHeadPtr),
1584: OSSwapInt32(pED->nextED));
1585:
1586: pTD = (OHCIIsochTransferDescriptorPtr) pED->pLogicalHeadP;
1587: while (pTD != 0)
1588: {
1589: DEBUGLOG("\t");
1590: print_itd(pTD);
1591: pTD = pTD->pLogicalNext;
1592: }
1593: }
1594: }
1595:
1596: void print_list(OHCIEndpointDescriptorPtr pListHead,
1597: OHCIEndpointDescriptorPtr pListTail)
1598: {
1599: OHCIEndpointDescriptorPtr pED, pEDTail;
1600:
1601:
1602: pED = (OHCIEndpointDescriptorPtr) pListHead;
1603: pEDTail = (OHCIEndpointDescriptorPtr) pListTail;
1604:
1605: while (pED != pEDTail)
1606: {
1607: print_ed(pED);
1608: pED = (OHCIEndpointDescriptorPtr) pED->pLogicalNext;
1609: }
1610: print_ed(pEDTail);
1611: }
1612:
1613: void print_control_list(OHCIUIMDataPtr pData)
1614: {
1615: DEBUGLOG("Control List: h/w head = 0x%lx\n",
1616: OSReadLittleInt32(&pData->pOHCIRegisters->hcControlHeadED, 0));
1617: print_list((OHCIEndpointDescriptorPtr) pData->pControlHead,
1618: (OHCIEndpointDescriptorPtr) pData->pControlTail);
1619: }
1620:
1621: void print_bulk_list(OHCIUIMDataPtr pData)
1622: {
1623: DEBUGLOG("Bulk List:\n");
1624: DEBUGLOG("Bulk List: h/w head = 0x%lx\n",
1625: OSReadLittleInt32(&pData->pOHCIRegisters->hcBulkHeadED, 0));
1626: print_list((OHCIEndpointDescriptorPtr) pData->pBulkHead,
1627: (OHCIEndpointDescriptorPtr) pData->pBulkTail);
1628: }
1629:
1630: void print_int_list(OHCIUIMDataPtr pData)
1631: {
1632: OHCIIntHeadPtr pInterruptHead = pData->pInterruptHead;
1633: int i;
1634: UInt32 w0;
1635: OHCIEndpointDescriptorPtr pED;
1636:
1637:
1638: DEBUGLOG("Interrupt List:\n");
1639: for (i = 0; i < 63; i++)
1640: {
1641: pED = (OHCIEndpointDescriptorPtr) pInterruptHead[i].pHead->pLogicalNext;
1642: w0 = OSSwapInt32(pED->flags);
1643:
1644: if ((w0 & kOHCIEDControl_K) == 0 /*noskip*/)
1645: {
1646: DEBUGLOG("%d:", i);
1647: print_ed(pED);
1648: }
1649: }
1650: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.