|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /*
26: File: OHCIRootHub.c
27:
28: Contains: xxx put contents here xxx
29:
30: Version: xxx put version here xxx
31:
32: Copyright: � 1998 by Apple Computer, Inc., all rights reserved.
33:
34: File Ownership:
35:
36: DRI: xxx put dri here xxx
37:
38: Other Contact: xxx put other contact here xxx
39:
40: Technology: xxx put technology here xxx
41:
42: Writers:
43:
44: (TC) Tom Clark
45: (BT) Barry Twycross
46:
47: Change History (most recent first):
48:
49: <USB8> 8/12/98 BT Move root hub into UIM again
50: <USB7> 7/10/98 TC Back out previous rev.
51: <USB6> 6/30/98 BT Move Root hub sim into UIM
52: <USB5> 6/11/98 BT Fix hub descriptor so it knows about overcurrent and power mode
53: <USB4> 4/23/98 BT Add reset portsuspend change
54: <USB3> 4/16/98 BT Channge to new headers
55: <USB2> 4/15/98 BT Add over current change reset
56: <1> 3/19/98 BT first checked in
57: */
58: #include "USB.h"
59: #include "driverservices.h"
60:
61: #include "OHCIUIM.h"
62: #include "OHCIRootHub.h"
63: #include "pci.h"
64:
65: OHCIUIMDataPtr pOHCIUIMData;
66:
67: void IOSync(void);
68: UInt32 EndianSwap32Bit(UInt32 x);
69: static void parameterNotUsed(UInt32 notUsed)
70: {
71: notUsed = 0;
72: }
73:
74: ////////////////////////////////////////////////////////////////////////////////
75: //
76: // OHCIUIMGetRootHubDescriptor
77: //
78: // This proc returns the root hub descriptor fields.
79: //
80:
81: OSStatus OHCIGetRootDescriptor(
82: uslBusRef bus, /* which hub */
83: uslRootHubDescriptorPtr descr)
84: {
85: OHCIRegistersPtr pOHCIRegisters;
86: UInt32 hcRhDescriptorA;
87: UInt32 hcRhDescriptorB;
88: UInt32 powerSwitching,
89: gangedSwitching,
90: compoundDevice,
91: overCurrent,
92: globalOverCurrent,
93: deviceRemovable,
94: gangedPower;
95: OSStatus status = noErr;
96:
97: parameterNotUsed(bus);
98:
99: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
100: // Read hcRhDescriptorA registers.
101: hcRhDescriptorA = EndianSwap32Bit (pOHCIRegisters->hcRhDescriptorA);
102: hcRhDescriptorB = EndianSwap32Bit (pOHCIRegisters->hcRhDescriptorB);
103:
104:
105: // Copy data from hcRhDescriptorA masking out reserved bit fields.
106: // The hcRhDescriptorA register is the 32 bit byte swap of nbrPorts,
107: // hubCharacteristics, and pwrOn2PwrGood.
108: // could have problem with porting and overwriting of other bytes.
109: hcRhDescriptorA &= kOHCINumPortsMask;
110: descr->numPorts = hcRhDescriptorA;
111:
112:
113: //Now get NPS Field, Power Switching
114: hcRhDescriptorA = EndianSwap32Bit (pOHCIRegisters->hcRhDescriptorA);
115: powerSwitching = (hcRhDescriptorA & kOHCIPowerSwitchingMask) >> kOHCIPowerSwitchingOffset;
116: descr->powerSwitching = !((Boolean) powerSwitching);
117:
118: //Now Get Ganged Switching
119: gangedSwitching = (hcRhDescriptorA & kOHCIGangedSwitchingMask) >> kOHCIGangedSwitchingOffset;
120: descr->gangedSwitching = !(Boolean) gangedSwitching;
121:
122: /*
123: UInt32* myPointer;
124:
125: myPointer = (UInt32 *) &(descr->gangedSwitching);
126:
127: *myPointer = (Boolean) gangedSwitching;
128: */
129:
130:
131:
132: //Is it a Compound device?
133: compoundDevice = (hcRhDescriptorA & kOHCICompoundDeviceMask) >> kOHCICompoundDeviceOffset;
134: descr->compoundDevice = (Boolean) compoundDevice;
135:
136: //Does it allow overcurrent
137: overCurrent = (hcRhDescriptorA & kOHCIOverCurrentMask) >> kOHCIOverCurrentOffset;
138: descr->overCurrent = !(Boolean) overCurrent;
139:
140: //Does it allow Global Over Current?
141: globalOverCurrent = (hcRhDescriptorA & kOHCIGlobalOverCurrentMask) >> kOHCIGlobalOverCurrentOffset;
142: descr->globalOverCurrent = !(Boolean) globalOverCurrent;
143:
144: //Find the device removable and ganged power flags and put into stuffed byte form
145: deviceRemovable = (hcRhDescriptorB & kOHCIDeviceRemovableMask) >> kOHCIDeviceRemovableOffset;
146: descr->portFlags[0] = (UInt8) deviceRemovable;
147: gangedPower = (hcRhDescriptorB & kOHCIGangedPowerMask) >> kOHCIGangedPowerOffset;
148: descr->portFlags[1] = (UInt8) gangedPower;
149:
150:
151: return (status);
152: }
153:
154: OSStatus OHCIGetInterruptStatus(
155: uslBusRef bus,
156: UInt32 *status)
157: {
158: OHCIRegistersPtr pOHCIRegisters;
159:
160: parameterNotUsed(bus);
161:
162: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
163: *status = EndianSwap32Bit (pOHCIRegisters->hcInterruptStatus);
164: return(noErr);
165: }
166:
167:
168: OSStatus OHCIClearInterruptStatus(
169: uslBusRef bus,
170: UInt32 status)
171: {
172: OHCIRegistersPtr pOHCIRegisters;
173:
174: parameterNotUsed(bus);
175:
176: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
177: pOHCIRegisters->hcInterruptStatus = EndianSwap32Bit (status);
178: return(noErr);
179:
180: }
181:
182: OSStatus OHCIGetRhStatus(
183: uslBusRef bus,
184: UInt32 *status)
185: {
186: OHCIRegistersPtr pOHCIRegisters;
187:
188: parameterNotUsed(bus);
189:
190: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
191: *status = EndianSwap32Bit (pOHCIRegisters->hcRhStatus);
192: return(noErr);
193:
194: }
195:
196:
197: OSStatus OHCIRootHubGetPortStatus(
198: uslBusRef bus,
199: short port,
200: uslRootHubPortStatusPtr portStatus)
201: {
202: UInt32 portFlags;
203: UInt32 hcRhPortStatus;
204: OSStatus status = noErr;
205:
206: parameterNotUsed(bus);
207:
208: //adjust port number for array use
209: port--;
210:
211: hcRhPortStatus = EndianSwap32Bit (pOHCIUIMData->pOHCIRegisters->hcRhPortStatus[port]);
212: //zzz
213: // sprintf (debugStr, "OHCIUIMportstatus = %lx", hcRhPortStatus);
214: // DebugStr ((ConstStr255Param) c2pstr (debugStr));
215: //zzz
216: portFlags = hcRhPortStatus & kOHCIPortFlagsMask;
217: portStatus->portFlags = (UInt16) portFlags;
218: portFlags = hcRhPortStatus >> kOHCIportChangeFlagsOffset;
219: portStatus->portChangeFlags = (UInt16) portFlags;
220: return (status);
221:
222: }
223:
224: OSStatus OHCIResetRootHub (
225: uslBusRef bus)
226: {
227: UInt32 rootHubDescriptorA, savedControl;
228: OSStatus status = noErr;
229: OHCIRegistersPtr pOHCIRegisters;
230: UInt16 numDownstreamPorts;
231: UInt16 powerOnToGoodTime;
232:
233: parameterNotUsed(bus);
234:
235: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
236:
237: rootHubDescriptorA = EndianSwap32Bit(pOHCIRegisters->hcRhDescriptorA);
238:
239: numDownstreamPorts = rootHubDescriptorA & kOHCIHcRhDescriptorA_NDP;
240: powerOnToGoodTime = 2 * ((rootHubDescriptorA & kOHCIHcRhDescriptorA_POTPGT) >> kOHCIHcRhDescriptorA_POTPGTPhase);
241: // should we wait for this time here? How about if the ports aren't powered on already?
242: kprintf("POTPGT val=%d\n",powerOnToGoodTime);
243: DelayForHardware(DurationToAbsolute(powerOnToGoodTime*durationMillisecond));
244: // put USB into USB bus-reset state
245: savedControl = EndianSwap32Bit(pOHCIRegisters->hcControl) & ~(kOHCIHcControl_HCFS);
246: pOHCIRegisters->hcControl = EndianSwap32Bit (pOHCIRegisters->hcControl) & ~(kOHCIHcControl_HCFS);
247:
248: DelayForHardware(DurationToAbsolute(10*durationMillisecond));
249:
250: // then go to the operational state
251: pOHCIRegisters->hcControl = EndianSwapImm32Bit((kOHCIFunctionalState_Operational << kOHCIHcControl_HCFSPhase) | savedControl) ;
252:
253: DelayForHardware(DurationToAbsolute(10*durationMillisecond)); // spec requires devices be ready within 10mS
254:
255:
256: ResetRootHubSimulation();
257:
258: return (status);
259: }
260:
261:
262: OSStatus OHCIRootHubPower(
263: uslBusRef bus,
264: Boolean on)
265: {
266: UInt32 value;
267: OSStatus status = noErr;
268: OHCIRegistersPtr pOHCIRegisters;
269:
270: parameterNotUsed(bus);
271:
272: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
273:
274: value = 0;
275: if(on)
276: {
277: value |= kOHCIBit16;/* power on to all ganged ports */
278: }
279: else
280: {
281: value |= kOHCIBit0; /* turn global power off */
282: }
283: // value |= kOHCIBit15;/* remote wakeup enable */
284: // value |= kOHCIBit17;/* clear over current change indicator */
285: // value |= kOHCIBit31;/* remote wakeup disabled */
286:
287: pOHCIRegisters->hcRhStatus = EndianSwap32Bit (value);
288:
289: return (status);
290:
291: }
292:
293: OSStatus OHCIRootHubResetChangeConnection(
294: uslBusRef bus,
295: short port)
296: {
297: UInt32 value;
298: OSStatus status = noErr;
299: OHCIRegistersPtr pOHCIRegisters;
300:
301: parameterNotUsed(bus);
302:
303: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
304: value = 0;
305: value |= kOHCIBit16;/* clear status change */
306:
307: pOHCIRegisters->hcRhPortStatus[port-1] = EndianSwap32Bit (value);
308:
309: return (status);
310: }
311:
312:
313: OSStatus OHCIRootHubResetResetChange(
314: uslBusRef bus,
315: short port)
316: {
317: UInt32 value;
318: OSStatus status = noErr;
319: OHCIRegistersPtr pOHCIRegisters;
320:
321: parameterNotUsed(bus);
322:
323:
324: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
325: value = 0;
326: value |= kOHCIBit20;/* clear reset status change */
327:
328: pOHCIRegisters->hcRhPortStatus[port-1] = EndianSwap32Bit (value);
329:
330: return (status);
331: }
332:
333: OSStatus OHCIRootHubResetSuspendChange(
334: uslBusRef bus,
335: short port)
336: {
337: UInt32 value;
338: OSStatus status = noErr;
339: OHCIRegistersPtr pOHCIRegisters;
340:
341: parameterNotUsed(bus);
342:
343:
344: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
345: value = 0;
346: value |= kOHCIBit18;/* clear suspend status change */
347:
348: pOHCIRegisters->hcRhPortStatus[port-1] = EndianSwap32Bit (value);
349:
350: return (status);
351: }
352:
353: OSStatus OHCIRootHubResetEnableChange(
354: uslBusRef bus,
355: short port)
356: {
357: UInt32 value;
358: OSStatus status = noErr;
359: OHCIRegistersPtr pOHCIRegisters;
360:
361: parameterNotUsed(bus);
362:
363:
364: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
365: value = 0;
366: value |= kOHCIBit17;/* clear enable status change */
367:
368: pOHCIRegisters->hcRhPortStatus[port-1] = EndianSwap32Bit (value);
369:
370: return (status);
371: }
372:
373:
374: OSStatus OHCIRootHubResetOverCurrentChange(
375: uslBusRef bus,
376: short port)
377: {
378: UInt32 value;
379: OSStatus status = noErr;
380: OHCIRegistersPtr pOHCIRegisters;
381:
382: parameterNotUsed(bus);
383:
384:
385: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
386: value = 0;
387: value |= kOHCIBit19;/* clear over current status change */
388:
389: pOHCIRegisters->hcRhPortStatus[port-1] = EndianSwap32Bit (value);
390:
391: return (status);
392: }
393:
394:
395: OSStatus OHCIRootHubResetPort (
396: uslBusRef bus,
397: short port)
398: {
399: OHCIRegistersPtr pOHCIRegisters;
400: OSStatus status = noErr;
401:
402: parameterNotUsed(bus);
403:
404: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
405:
406: //sets Bit 8 in port root hub register
407: pOHCIRegisters->hcRhPortStatus[port-1] = EndianSwap32Bit (kOHCIBit4);
408: IOSync();
409: return (status);
410:
411: }
412:
413: OSStatus OHCIRootHubPortEnable(
414: uslBusRef bus,
415: short port,
416: Boolean on)
417: {
418: UInt32 value;
419: OSStatus status = noErr;
420: OHCIRegistersPtr pOHCIRegisters;
421: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
422:
423: parameterNotUsed(bus);
424:
425: value = 0;
426: if(on)
427: {
428: value |= kOHCIBit1;/* enable port */
429: }
430: else
431: {
432: value |= kOHCIBit0; /* disable port */
433: }
434:
435: pOHCIUIMData->pOHCIRegisters->hcRhPortStatus[port-1] = EndianSwap32Bit (value);
436: IOSync();
437:
438: return (status);
439: }
440:
441: OSStatus OHCIRootHubPortSuspend(
442: uslBusRef bus,
443: short port,
444: Boolean on)
445: {
446: UInt32 value;
447: OSStatus status = noErr;
448: OHCIRegistersPtr pOHCIRegisters;
449:
450: parameterNotUsed(bus);
451:
452: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
453:
454: value = 0;
455: if(on)
456: {
457: value |= kOHCIBit2;/* suspend port */
458: }
459: else
460: {
461: value |= kOHCIBit3; /* resume port */
462: }
463:
464: pOHCIUIMData->pOHCIRegisters->hcRhPortStatus[port-1] = EndianSwap32Bit (value);
465:
466: return (status);
467: }
468:
469: OSStatus OHCIRootHubPortPower(
470: uslBusRef bus,
471: short port,
472: Boolean on)
473: {
474: UInt32 value= 0;
475: OSStatus status = noErr;
476: OHCIRegistersPtr pOHCIRegisters;
477:
478: parameterNotUsed(bus);
479:
480: pOHCIRegisters = pOHCIUIMData->pOHCIRegisters;
481:
482: if(on)
483: {
484: value |= kOHCIBit8;/* enable port power */
485: }
486: else
487: {
488: value |= kOHCIBit9; /* disable port power */
489: }
490:
491: pOHCIUIMData->pOHCIRegisters->hcRhPortStatus[port-1] = EndianSwap32Bit (value);
492:
493: return (status);
494: }
495:
496:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.