bbd4e7e5f339fec39bca4f163ffef4f116602305
[reactos.git] / drivers / usb / usbohci_new / roothub.c
1 #include "usbohci.h"
2
3 #define NDEBUG
4 #include <debug.h>
5
6 OHCI_REG_RH_DESCRIPTORA
7 NTAPI
8 OHCI_ReadRhDescriptorA(IN POHCI_EXTENSION OhciExtension)
9 {
10 POHCI_OPERATIONAL_REGISTERS OperationalRegs;
11 OHCI_REG_RH_DESCRIPTORA DescriptorA;
12 PULONG DescriptorAReg;
13 ULONG ix;
14
15 OperationalRegs = OhciExtension->OperationalRegs;
16 DescriptorAReg = (PULONG)&OperationalRegs->HcRhDescriptorA;
17
18 DPRINT("OHCI_ReadRhDescriptorA: OhciExtension - %p\n", OhciExtension);
19
20 for (ix = 0; ix < 10; ix++)
21 {
22 DescriptorA.AsULONG = READ_REGISTER_ULONG(DescriptorAReg);
23
24 if (DescriptorA.AsULONG != 0 &&
25 DescriptorA.Reserved == 0 &&
26 DescriptorA.NumberDownstreamPorts <= OHCI_MAX_PORT_COUNT)
27 {
28 break;
29 }
30
31 DPRINT1("OHCI_ReadRhDescriptorA: DescriptorA - %lX, ix - %d\n",
32 DescriptorA.AsULONG, ix);
33
34 KeStallExecutionProcessor(5);
35 }
36
37 return DescriptorA;
38 }
39
40 VOID
41 NTAPI
42 OHCI_RH_GetRootHubData(IN PVOID ohciExtension,
43 IN PVOID rootHubData)
44 {
45 POHCI_EXTENSION OhciExtension;
46 PUSBPORT_ROOT_HUB_DATA RootHubData;
47 OHCI_REG_RH_DESCRIPTORA DescriptorA;
48 UCHAR PowerOnToPowerGoodTime;
49 USBPORT_HUB_11_CHARACTERISTICS HubCharacteristics;
50
51 OhciExtension = ohciExtension;
52
53 DPRINT("OHCI_RH_GetRootHubData: OhciExtension - %p, rootHubData - %p\n",
54 OhciExtension,
55 rootHubData);
56
57 RootHubData = rootHubData;
58 DescriptorA = OHCI_ReadRhDescriptorA(OhciExtension);
59
60 RootHubData->NumberOfPorts = DescriptorA.NumberDownstreamPorts;
61
62 /* Waiting time (in 2 ms intervals) */
63 PowerOnToPowerGoodTime = DescriptorA.PowerOnToPowerGoodTime;
64 if (PowerOnToPowerGoodTime <= OHCI_MINIMAL_POTPGT)
65 PowerOnToPowerGoodTime = OHCI_MINIMAL_POTPGT;
66 RootHubData->PowerOnToPowerGood = PowerOnToPowerGoodTime;
67
68 HubCharacteristics.AsUSHORT = 0;
69
70 if (DescriptorA.PowerSwitchingMode)
71 {
72 /* Individual port power switching */
73 HubCharacteristics.PowerControlMode = 1;
74 }
75 else
76 {
77 /* Ganged power switching */
78 HubCharacteristics.PowerControlMode = 0;
79 }
80
81 HubCharacteristics.NoPowerSwitching = 0;
82
83 /* always 0 (OHCI RH is not a compound device) */
84 ASSERT(DescriptorA.DeviceType == 0);
85 HubCharacteristics.PartOfCompoundDevice = DescriptorA.DeviceType;
86
87 HubCharacteristics.OverCurrentProtectionMode = DescriptorA.OverCurrentProtectionMode;
88 HubCharacteristics.NoOverCurrentProtection = DescriptorA.NoOverCurrentProtection;
89
90 RootHubData->HubCharacteristics.Usb11HubCharacteristics = HubCharacteristics;
91 RootHubData->HubControlCurrent = 0;
92 }
93
94 MPSTATUS
95 NTAPI
96 OHCI_RH_GetStatus(IN PVOID ohciExtension,
97 IN PUSHORT Status)
98 {
99 DPRINT("OHCI_RH_GetStatus: \n");
100 *Status = OHCI_RH_STATUS_GOOD;
101 return MP_STATUS_SUCCESS;
102 }
103
104 MPSTATUS
105 NTAPI
106 OHCI_RH_GetPortStatus(IN PVOID ohciExtension,
107 IN USHORT Port,
108 IN PUSB_PORT_STATUS_AND_CHANGE PortStatus)
109 {
110 POHCI_EXTENSION OhciExtension;
111 POHCI_OPERATIONAL_REGISTERS OperationalRegs;
112 PULONG PortStatusReg;
113 OHCI_REG_RH_PORT_STATUS OhciPortStatus;
114 ULONG ix;
115 ULONG Reserved;
116
117 OhciExtension = ohciExtension;
118
119 DPRINT("OHCI_RH_GetPortStatus: OhciExtension - %p, Port - %x, PortStatus - %lX\n",
120 OhciExtension,
121 Port,
122 PortStatus->AsUlong32);
123
124 ASSERT(Port > 0);
125
126 OperationalRegs = OhciExtension->OperationalRegs;
127 PortStatusReg = (PULONG)&OperationalRegs->HcRhPortStatus[Port-1];
128
129 for (ix = 0; ix < 10; ix++)
130 {
131 OhciPortStatus.AsULONG = READ_REGISTER_ULONG(PortStatusReg);
132
133 Reserved = OhciPortStatus.Reserved1r |
134 OhciPortStatus.Reserved2r |
135 OhciPortStatus.Reserved3;
136
137 if (OhciPortStatus.AsULONG && !Reserved)
138 break;
139
140 DPRINT("OHCI_RH_GetPortStatus: OhciPortStatus - %X\n", OhciPortStatus.AsULONG);
141
142 KeStallExecutionProcessor(5);
143 }
144
145 PortStatus->AsUlong32 = OhciPortStatus.AsULONG;
146
147 return MP_STATUS_SUCCESS;
148 }
149
150 MPSTATUS
151 NTAPI
152 OHCI_RH_GetHubStatus(IN PVOID ohciExtension,
153 IN PUSB_HUB_STATUS_AND_CHANGE HubStatus)
154 {
155 POHCI_EXTENSION OhciExtension;
156 POHCI_OPERATIONAL_REGISTERS OperationalRegs;
157 PULONG RhStatusReg;
158 OHCI_REG_RH_STATUS HcRhStatus;
159
160 OhciExtension = ohciExtension;
161
162 DPRINT("OHCI_RH_GetHubStatus: ohciExtension - %p, HubStatus - %lX\n",
163 ohciExtension,
164 HubStatus->AsUlong32);
165
166 OperationalRegs = OhciExtension->OperationalRegs;
167 RhStatusReg = (PULONG)&OperationalRegs->HcRhStatus;
168
169 HcRhStatus.AsULONG = READ_REGISTER_ULONG(RhStatusReg);
170
171 HubStatus->HubStatus.LocalPowerLost = HcRhStatus.LocalPowerStatus;
172 HubStatus->HubChange.LocalPowerChange = HcRhStatus.LocalPowerStatusChange;
173
174 HubStatus->HubStatus.OverCurrent = HcRhStatus.OverCurrentIndicator;
175 HubStatus->HubChange.OverCurrentChange = HcRhStatus.OverCurrentIndicatorChangeR;
176
177 return MP_STATUS_SUCCESS;
178 }
179
180 MPSTATUS
181 NTAPI
182 OHCI_RH_SetFeaturePortReset(IN PVOID ohciExtension,
183 IN USHORT Port)
184 {
185 POHCI_EXTENSION OhciExtension;
186 POHCI_OPERATIONAL_REGISTERS OperationalRegs;
187 PULONG PortStatusReg;
188 OHCI_REG_RH_PORT_STATUS PortStatus;
189
190 OhciExtension = ohciExtension;
191
192 DPRINT("OHCI_RH_SetFeaturePortReset: OhciExtension - %p, Port - %x\n",
193 OhciExtension,
194 Port);
195
196 ASSERT(Port > 0);
197
198 OperationalRegs = OhciExtension->OperationalRegs;
199 PortStatusReg = (PULONG)&OperationalRegs->HcRhPortStatus[Port-1];
200
201 PortStatus.AsULONG = 0;
202 PortStatus.SetPortReset = 1;
203
204 WRITE_REGISTER_ULONG(PortStatusReg, PortStatus.AsULONG);
205
206 return MP_STATUS_SUCCESS;
207 }
208
209 MPSTATUS
210 NTAPI
211 OHCI_RH_SetFeaturePortPower(IN PVOID ohciExtension,
212 IN USHORT Port)
213 {
214 POHCI_EXTENSION OhciExtension;
215 POHCI_OPERATIONAL_REGISTERS OperationalRegs;
216 PULONG PortStatusReg;
217 OHCI_REG_RH_PORT_STATUS PortStatus;
218
219 OhciExtension = ohciExtension;
220
221 DPRINT("OHCI_RH_SetFeaturePortPower: OhciExtension - %p, Port - %x\n",
222 OhciExtension,
223 Port);
224
225 ASSERT(Port > 0);
226
227 OperationalRegs = OhciExtension->OperationalRegs;
228 PortStatusReg = (PULONG)&OperationalRegs->HcRhPortStatus[Port-1];
229
230 PortStatus.AsULONG = 0;
231 PortStatus.SetPortPower = 1;
232
233 WRITE_REGISTER_ULONG(PortStatusReg, PortStatus.AsULONG);
234
235 return MP_STATUS_SUCCESS;
236 }
237
238 MPSTATUS
239 NTAPI
240 OHCI_RH_SetFeaturePortEnable(IN PVOID ohciExtension,
241 IN USHORT Port)
242 {
243 POHCI_EXTENSION OhciExtension;
244 POHCI_OPERATIONAL_REGISTERS OperationalRegs;
245 PULONG PortStatusReg;
246 OHCI_REG_RH_PORT_STATUS PortStatus;
247
248 OhciExtension = ohciExtension;
249
250 DPRINT("OHCI_RH_SetFeaturePortEnable: OhciExtension - %p, Port - %x\n",
251 OhciExtension,
252 Port);
253
254 ASSERT(Port > 0);
255
256 OperationalRegs = OhciExtension->OperationalRegs;
257 PortStatusReg = (PULONG)&OperationalRegs->HcRhPortStatus[Port-1];
258
259 PortStatus.AsULONG = 0;
260 PortStatus.SetPortEnable = 1;
261
262 WRITE_REGISTER_ULONG(PortStatusReg, PortStatus.AsULONG);
263
264 return MP_STATUS_SUCCESS;
265 }
266
267 MPSTATUS
268 NTAPI
269 OHCI_RH_SetFeaturePortSuspend(IN PVOID ohciExtension,
270 IN USHORT Port)
271 {
272 POHCI_EXTENSION OhciExtension;
273 POHCI_OPERATIONAL_REGISTERS OperationalRegs;
274 PULONG PortStatusReg;
275 OHCI_REG_RH_PORT_STATUS PortStatus;
276
277 OhciExtension = ohciExtension;
278
279 DPRINT("OHCI_RH_SetFeaturePortSuspend: OhciExtension - %p, Port - %x\n",
280 OhciExtension,
281 Port);
282
283 ASSERT(Port > 0);
284
285 OperationalRegs = OhciExtension->OperationalRegs;
286 PortStatusReg = (PULONG)&OperationalRegs->HcRhPortStatus[Port-1];
287
288 PortStatus.AsULONG = 0;
289 PortStatus.SetPortSuspend = 1;
290
291 WRITE_REGISTER_ULONG(PortStatusReg, PortStatus.AsULONG);
292
293 return MP_STATUS_SUCCESS;
294 }
295
296 MPSTATUS
297 NTAPI
298 OHCI_RH_ClearFeaturePortEnable(IN PVOID ohciExtension,
299 IN USHORT Port)
300 {
301 POHCI_EXTENSION OhciExtension;
302 POHCI_OPERATIONAL_REGISTERS OperationalRegs;
303 PULONG PortStatusReg;
304 OHCI_REG_RH_PORT_STATUS PortStatus;
305
306 OhciExtension = ohciExtension;
307
308 DPRINT("OHCI_RH_ClearFeaturePortEnable: OhciExtension - %p, Port - %x\n",
309 OhciExtension,
310 Port);
311
312 ASSERT(Port > 0);
313
314 OperationalRegs = OhciExtension->OperationalRegs;
315 PortStatusReg = (PULONG)&OperationalRegs->HcRhPortStatus[Port-1];
316
317 PortStatus.AsULONG = 0;
318 PortStatus.ClearPortEnable = 1;
319
320 WRITE_REGISTER_ULONG(PortStatusReg, PortStatus.AsULONG);
321
322 return MP_STATUS_SUCCESS;
323 }
324
325 MPSTATUS
326 NTAPI
327 OHCI_RH_ClearFeaturePortPower(IN PVOID ohciExtension,
328 IN USHORT Port)
329 {
330 POHCI_EXTENSION OhciExtension;
331 POHCI_OPERATIONAL_REGISTERS OperationalRegs;
332 PULONG PortStatusReg;
333 OHCI_REG_RH_PORT_STATUS PortStatus;
334
335 OhciExtension = ohciExtension;
336
337 DPRINT("OHCI_RH_ClearFeaturePortPower: OhciExtension - %p, Port - %x\n",
338 OhciExtension,
339 Port);
340
341 ASSERT(Port > 0);
342
343 OperationalRegs = OhciExtension->OperationalRegs;
344 PortStatusReg = (PULONG)&OperationalRegs->HcRhPortStatus[Port-1];
345
346 PortStatus.AsULONG = 0;
347 PortStatus.ClearPortPower = 1;
348
349 WRITE_REGISTER_ULONG(PortStatusReg, PortStatus.AsULONG);
350
351 return MP_STATUS_SUCCESS;
352 }
353
354 MPSTATUS
355 NTAPI
356 OHCI_RH_ClearFeaturePortSuspend(IN PVOID ohciExtension,
357 IN USHORT Port)
358 {
359 POHCI_EXTENSION OhciExtension;
360 POHCI_OPERATIONAL_REGISTERS OperationalRegs;
361 PULONG PortStatusReg;
362 OHCI_REG_RH_PORT_STATUS PortStatus;
363
364 OhciExtension = ohciExtension;
365
366 DPRINT("OHCI_RH_ClearFeaturePortSuspend: OhciExtension - %p, Port - %x\n",
367 OhciExtension,
368 Port);
369
370 ASSERT(Port > 0);
371
372 OperationalRegs = OhciExtension->OperationalRegs;
373 PortStatusReg = (PULONG)&OperationalRegs->HcRhPortStatus[Port-1];
374
375 PortStatus.AsULONG = 0;
376 PortStatus.ClearSuspendStatus = 1;
377
378 WRITE_REGISTER_ULONG(PortStatusReg, PortStatus.AsULONG);
379
380 return MP_STATUS_SUCCESS;
381 }
382
383 MPSTATUS
384 NTAPI
385 OHCI_RH_ClearFeaturePortEnableChange(IN PVOID ohciExtension,
386 IN USHORT Port)
387 {
388 POHCI_EXTENSION OhciExtension;
389 POHCI_OPERATIONAL_REGISTERS OperationalRegs;
390 PULONG PortStatusReg;
391 OHCI_REG_RH_PORT_STATUS PortStatus;
392
393 OhciExtension = ohciExtension;
394
395 DPRINT("OHCI_RH_ClearFeaturePortEnableChange: ohciExtension - %p, Port - %x\n",
396 ohciExtension,
397 Port);
398
399 ASSERT(Port > 0);
400
401 OperationalRegs = OhciExtension->OperationalRegs;
402 PortStatusReg = (PULONG)&OperationalRegs->HcRhPortStatus[Port-1];
403
404 PortStatus.AsULONG = 0;
405 PortStatus.PortEnableStatusChange = 1;
406
407 WRITE_REGISTER_ULONG(PortStatusReg, PortStatus.AsULONG);
408
409 return MP_STATUS_SUCCESS;
410 }
411
412 MPSTATUS
413 NTAPI
414 OHCI_RH_ClearFeaturePortConnectChange(IN PVOID ohciExtension,
415 IN USHORT Port)
416 {
417 POHCI_EXTENSION OhciExtension;
418 POHCI_OPERATIONAL_REGISTERS OperationalRegs;
419 PULONG PortStatusReg;
420 OHCI_REG_RH_PORT_STATUS PortStatus;
421
422 OhciExtension = ohciExtension;
423
424 DPRINT("OHCI_RH_ClearFeaturePortConnectChange: OhciExtension - %p, Port - %x\n",
425 OhciExtension,
426 Port);
427
428 ASSERT(Port > 0);
429
430 OperationalRegs = OhciExtension->OperationalRegs;
431 PortStatusReg = (PULONG)&OperationalRegs->HcRhPortStatus[Port-1];
432
433 PortStatus.AsULONG = 0;
434 PortStatus.ConnectStatusChange = 1;
435
436 WRITE_REGISTER_ULONG(PortStatusReg, PortStatus.AsULONG);
437
438 return MP_STATUS_SUCCESS;
439 }
440
441 MPSTATUS
442 NTAPI
443 OHCI_RH_ClearFeaturePortResetChange(IN PVOID ohciExtension,
444 IN USHORT Port)
445 {
446 POHCI_EXTENSION OhciExtension;
447 POHCI_OPERATIONAL_REGISTERS OperationalRegs;
448 PULONG PortStatusReg;
449 OHCI_REG_RH_PORT_STATUS PortStatus;
450
451 OhciExtension = ohciExtension;
452
453 DPRINT("OHCI_RH_ClearFeaturePortResetChange: OhciExtension - %p, Port - %x\n",
454 OhciExtension,
455 Port);
456
457 ASSERT(Port > 0);
458
459 OperationalRegs = OhciExtension->OperationalRegs;
460 PortStatusReg = (PULONG)&OperationalRegs->HcRhPortStatus[Port-1];
461
462 PortStatus.AsULONG = 0;
463 PortStatus.PortResetStatusChange = 1;
464
465 WRITE_REGISTER_ULONG(PortStatusReg, PortStatus.AsULONG);
466
467 return MP_STATUS_SUCCESS;
468 }
469
470 MPSTATUS
471 NTAPI
472 OHCI_RH_ClearFeaturePortSuspendChange(IN PVOID ohciExtension,
473 IN USHORT Port)
474 {
475 POHCI_EXTENSION OhciExtension;
476 POHCI_OPERATIONAL_REGISTERS OperationalRegs;
477 PULONG PortStatusReg;
478 OHCI_REG_RH_PORT_STATUS PortStatus;
479
480 OhciExtension = ohciExtension;
481
482 DPRINT("OHCI_RH_ClearFeaturePortSuspendChange: OhciExtension - %p, Port - %x\n",
483 OhciExtension,
484 Port);
485
486 ASSERT(Port > 0);
487
488 OperationalRegs = OhciExtension->OperationalRegs;
489 PortStatusReg = (PULONG)&OperationalRegs->HcRhPortStatus[Port-1];
490
491 PortStatus.AsULONG = 0;
492 PortStatus.PortSuspendStatusChange = 1;
493
494 WRITE_REGISTER_ULONG(PortStatusReg, PortStatus.AsULONG);
495
496 return MP_STATUS_SUCCESS;
497 }
498
499 MPSTATUS
500 NTAPI
501 OHCI_RH_ClearFeaturePortOvercurrentChange(IN PVOID ohciExtension,
502 IN USHORT Port)
503 {
504 POHCI_EXTENSION OhciExtension;
505 POHCI_OPERATIONAL_REGISTERS OperationalRegs;
506 PULONG PortStatusReg;
507 PULONG RhStatusReg;
508 OHCI_REG_RH_PORT_STATUS PortStatus;
509 OHCI_REG_RH_STATUS RhStatus;
510
511 OhciExtension = ohciExtension;
512
513 DPRINT("OHCI_RH_ClearFeaturePortOvercurrentChange: OhciExtension - %p, Port - %x\n",
514 OhciExtension,
515 Port);
516
517 OperationalRegs = OhciExtension->OperationalRegs;
518
519 if (Port)
520 {
521 /* USBPORT_RECIPIENT_PORT */
522 PortStatus.AsULONG = 0;
523 PortStatus.PortOverCurrentIndicatorChange = 1;
524
525 PortStatusReg = (PULONG)&OperationalRegs->HcRhPortStatus[Port-1];
526 WRITE_REGISTER_ULONG(PortStatusReg, PortStatus.AsULONG);
527 }
528 else
529 {
530 /* USBPORT_RECIPIENT_HUB */
531 RhStatus.AsULONG = 0;
532 RhStatus.OverCurrentIndicatorChangeW = 1;
533
534 RhStatusReg = (PULONG)&OperationalRegs->HcRhStatus;
535 WRITE_REGISTER_ULONG(RhStatusReg, RhStatus.AsULONG);
536 }
537
538 return MP_STATUS_SUCCESS;
539 }
540
541 VOID
542 NTAPI
543 OHCI_RH_DisableIrq(IN PVOID ohciExtension)
544 {
545 POHCI_EXTENSION OhciExtension = ohciExtension;
546 POHCI_OPERATIONAL_REGISTERS OperationalRegs;
547 PULONG InterruptDisableReg;
548 OHCI_REG_INTERRUPT_ENABLE_DISABLE InterruptDisable;
549
550 DPRINT("OHCI_RH_DisableIrq: OhciExtension - %p\n", OhciExtension);
551
552 OperationalRegs = OhciExtension->OperationalRegs;
553 InterruptDisableReg = (PULONG)&OperationalRegs->HcInterruptDisable;
554
555 InterruptDisable.AsULONG = 0;
556 InterruptDisable.RootHubStatusChange = 1;
557
558 WRITE_REGISTER_ULONG(InterruptDisableReg, InterruptDisable.AsULONG);
559 }
560
561 VOID
562 NTAPI
563 OHCI_RH_EnableIrq(IN PVOID ohciExtension)
564 {
565 POHCI_EXTENSION OhciExtension = ohciExtension;
566 POHCI_OPERATIONAL_REGISTERS OperationalRegs;
567 PULONG InterruptEnableReg;
568 OHCI_REG_INTERRUPT_ENABLE_DISABLE InterruptEnable;
569
570 DPRINT("OHCI_RH_EnableIrq: OhciExtension - %p\n", OhciExtension);
571
572 OperationalRegs = OhciExtension->OperationalRegs;
573 InterruptEnableReg = (PULONG)&OperationalRegs->HcInterruptEnable;
574
575 InterruptEnable.AsULONG = 0;
576 InterruptEnable.RootHubStatusChange = 1;
577
578 WRITE_REGISTER_ULONG(InterruptEnableReg, InterruptEnable.AsULONG);
579 }