1 /*
2 * PROJECT: ReactOS USB UHCI Miniport Driver
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: USBUHCI root hub functions
5 * COPYRIGHT: Copyright 2017-2018 Vadim Galyant <vgal@rambler.ru>
6 */
7
8 #include "usbuhci.h"
9
10 #define NDEBUG
11 #include <debug.h>
12
13 VOID
14 NTAPI
UhciRHGetRootHubData(IN PVOID uhciExtension,IN PVOID rootHubData)15 UhciRHGetRootHubData(IN PVOID uhciExtension,
16 IN PVOID rootHubData)
17 {
18 PUHCI_EXTENSION UhciExtension = uhciExtension;
19 PUSBPORT_ROOT_HUB_DATA RootHubData = rootHubData;
20 USBPORT_HUB_11_CHARACTERISTICS HubCharacteristics;
21
22 DPRINT("UhciRHGetRootHubData: ...\n");
23
24 HubCharacteristics.AsUSHORT = 0;
25 HubCharacteristics.PowerControlMode = 1;
26 HubCharacteristics.NoPowerSwitching = 1;
27 HubCharacteristics.OverCurrentProtectionMode = 1;
28
29 if (UhciExtension->HcFlavor != UHCI_Piix4)
30 HubCharacteristics.NoOverCurrentProtection = 1;
31
32 RootHubData->NumberOfPorts = UHCI_NUM_ROOT_HUB_PORTS;
33 RootHubData->HubCharacteristics.Usb11HubCharacteristics = HubCharacteristics;
34 RootHubData->PowerOnToPowerGood = 1;
35 RootHubData->HubControlCurrent = 0;
36 }
37
38 MPSTATUS
39 NTAPI
UhciRHGetStatus(IN PVOID uhciExtension,IN PUSHORT Status)40 UhciRHGetStatus(IN PVOID uhciExtension,
41 IN PUSHORT Status)
42 {
43 DPRINT("UhciRHGetStatus: ...\n");
44 *Status = USB_GETSTATUS_SELF_POWERED;
45 return MP_STATUS_SUCCESS;
46 }
47
48 MPSTATUS
49 NTAPI
UhciRHGetPortStatus(IN PVOID uhciExtension,IN USHORT Port,IN PUSB_PORT_STATUS_AND_CHANGE PortStatus)50 UhciRHGetPortStatus(IN PVOID uhciExtension,
51 IN USHORT Port,
52 IN PUSB_PORT_STATUS_AND_CHANGE PortStatus)
53 {
54 PUHCI_EXTENSION UhciExtension = uhciExtension;
55 PUHCI_HW_REGISTERS BaseRegister;
56 PUSHORT PortControlRegister;
57 UHCI_PORT_STATUS_CONTROL PortControl;
58 ULONG PortBit;
59 USB_20_PORT_STATUS portStatus;
60 USB_20_PORT_CHANGE portChange;
61
62 //DPRINT("UhciRHGetPortStatus: ...\n");
63
64 ASSERT(Port);
65
66 BaseRegister = UhciExtension->BaseRegister;
67 PortControlRegister = &BaseRegister->PortControl[Port-1].AsUSHORT;
68 PortControl.AsUSHORT = READ_PORT_USHORT(PortControlRegister);
69
70 portStatus.AsUshort16 = 0;
71 portChange.AsUshort16 = 0;
72
73 portStatus.CurrentConnectStatus = PortControl.CurrentConnectStatus;
74 portStatus.PortEnabledDisabled = PortControl.PortEnabledDisabled;
75
76 if (PortControl.Suspend == 1 &&
77 PortControl.PortEnabledDisabled == 1)
78 {
79 portStatus.Suspend = 1;
80 }
81 else
82 {
83 portStatus.Suspend = 0;
84 }
85
86 //if (UhciExtension->HcFlavor == UHCI_Piix4) // check will work after supporting HcFlavor in usbport.
87 if (TRUE)
88 {
89 portStatus.OverCurrent = PortControl.Reserved2 & 1;
90 portStatus.PortPower = (~PortControl.Reserved2 & 1);
91 portChange.OverCurrentIndicatorChange = (PortControl.Reserved2 & 2) != 0;
92 }
93 else
94 {
95 portStatus.OverCurrent = 0;
96 portStatus.PortPower = 1;
97 portChange.OverCurrentIndicatorChange = 0;
98 }
99
100 portStatus.HighSpeedDeviceAttached = 0;
101
102 portStatus.Reset = PortControl.PortReset;
103 portStatus.LowSpeedDeviceAttached = PortControl.LowSpeedDevice;
104 portChange.ConnectStatusChange = PortControl.ConnectStatusChange;
105
106 PortBit = 1 << (Port - 1);
107
108 if (UhciExtension->ResetPortMask & PortBit)
109 {
110 portChange.ConnectStatusChange = 0;
111 portChange.PortEnableDisableChange = 0;
112 }
113 else
114 {
115 portChange.PortEnableDisableChange = PortControl.PortEnableDisableChange;
116 }
117
118 if (UhciExtension->SuspendChangePortMask & PortBit)
119 portChange.SuspendChange = 1;
120
121 if (UhciExtension->ResetChangePortMask & PortBit)
122 portChange.ResetChange = 1;
123
124 PortStatus->PortStatus.Usb20PortStatus = portStatus;
125 PortStatus->PortChange.Usb20PortChange = portChange;
126
127 //DPRINT("UhciRHGetPortStatus: PortControl.AsUSHORT[%x] - %X, PortStatus - %X\n",
128 // Port,
129 // PortControl.AsUSHORT,
130 // PortStatus->AsUlong32);
131
132 return MP_STATUS_SUCCESS;
133 }
134
135 MPSTATUS
136 NTAPI
UhciRHGetHubStatus(IN PVOID uhciExtension,IN PUSB_HUB_STATUS_AND_CHANGE HubStatus)137 UhciRHGetHubStatus(IN PVOID uhciExtension,
138 IN PUSB_HUB_STATUS_AND_CHANGE HubStatus)
139 {
140 //DPRINT("UhciRHGetHubStatus: ...\n");
141 HubStatus->AsUlong32 = 0;
142 return MP_STATUS_SUCCESS;
143 }
144
145 VOID
146 NTAPI
UhciRHPortResetComplete(IN PVOID uhciExtension,IN PVOID pPort)147 UhciRHPortResetComplete(IN PVOID uhciExtension,
148 IN PVOID pPort)
149 {
150 PUHCI_EXTENSION UhciExtension = uhciExtension;
151 ULONG ix;
152 PUHCI_HW_REGISTERS BaseRegister;
153 PUSHORT PortControlRegister;
154 UHCI_PORT_STATUS_CONTROL PortControl;
155 USHORT Port;
156
157 DPRINT("UhciRHPortResetComplete: ...\n");
158
159 BaseRegister = UhciExtension->BaseRegister;
160
161 Port = *(PUSHORT)pPort;
162 ASSERT(Port);
163
164 PortControlRegister = &BaseRegister->PortControl[Port - 1].AsUSHORT;
165 PortControl.AsUSHORT = READ_PORT_USHORT(PortControlRegister);
166
167 PortControl.ConnectStatusChange = 0;
168 PortControl.PortEnableDisableChange = 0;
169 PortControl.PortReset = 0;
170
171 WRITE_PORT_USHORT(PortControlRegister, PortControl.AsUSHORT);
172
173 while (UhciHardwarePresent(UhciExtension))
174 {
175 PortControl.AsUSHORT = READ_PORT_USHORT(PortControlRegister);
176
177 if (PortControl.PortReset == 0)
178 break;
179 }
180
181 for (ix = 0; ix < 10; ++ix)
182 {
183 KeStallExecutionProcessor(50);
184
185 PortControl.AsUSHORT = READ_PORT_USHORT(PortControlRegister);
186
187 if (PortControl.PortEnabledDisabled == 1)
188 break;
189
190 PortControl.PortEnabledDisabled = 1;
191 WRITE_PORT_USHORT(PortControlRegister, PortControl.AsUSHORT);
192 }
193
194 PortControl.ConnectStatusChange = 1;
195 PortControl.PortEnableDisableChange = 1;
196 WRITE_PORT_USHORT(PortControlRegister, PortControl.AsUSHORT);
197
198 if (UhciExtension->HcFlavor == UHCI_VIA ||
199 UhciExtension->HcFlavor == UHCI_VIA_x01 ||
200 UhciExtension->HcFlavor == UHCI_VIA_x02 ||
201 UhciExtension->HcFlavor == UHCI_VIA_x03 ||
202 UhciExtension->HcFlavor == UHCI_VIA_x04)
203 {
204 DPRINT1("UhciRHPortResetComplete: Via chip. FIXME\n");
205 DbgBreakPoint();
206 return;
207 }
208
209 UhciExtension->ResetChangePortMask |= (1 << (Port - 1));
210 UhciExtension->ResetPortMask &= ~(1 << (Port - 1));
211
212 RegPacket.UsbPortInvalidateRootHub(UhciExtension);
213 }
214
215 VOID
216 NTAPI
UhciRHSetFeaturePortResetWorker(IN PUHCI_EXTENSION UhciExtension,IN PUSHORT pPort)217 UhciRHSetFeaturePortResetWorker(IN PUHCI_EXTENSION UhciExtension,
218 IN PUSHORT pPort)
219 {
220 PUHCI_HW_REGISTERS BaseRegister;
221 PUSHORT PortControlRegister;
222 UHCI_PORT_STATUS_CONTROL PortControl;
223 USHORT Port;
224
225 DPRINT("UhciRHSetFeaturePortResetWorker: ...\n");
226
227 BaseRegister = UhciExtension->BaseRegister;
228
229 Port = *(PUSHORT)pPort;
230 ASSERT(Port);
231
232 PortControlRegister = &BaseRegister->PortControl[Port - 1].AsUSHORT;
233 PortControl.AsUSHORT = READ_PORT_USHORT(PortControlRegister);
234
235 PortControl.ConnectStatusChange = 0;
236 PortControl.PortEnableDisableChange = 0;
237 PortControl.PortReset = 1;
238
239 WRITE_PORT_USHORT(PortControlRegister, PortControl.AsUSHORT);
240
241 RegPacket.UsbPortRequestAsyncCallback(UhciExtension,
242 10, // TimerValue
243 pPort,
244 sizeof(*pPort),
245 UhciRHPortResetComplete);
246 }
247
248 MPSTATUS
249 NTAPI
UhciRHSetFeaturePortReset(IN PVOID uhciExtension,IN USHORT Port)250 UhciRHSetFeaturePortReset(IN PVOID uhciExtension,
251 IN USHORT Port)
252 {
253 PUHCI_EXTENSION UhciExtension = uhciExtension;
254 ULONG ResetPortMask;
255 ULONG PortBit;
256
257 DPRINT("UhciRHSetFeaturePortReset: ...\n");
258
259 ASSERT(Port);
260
261 ResetPortMask = UhciExtension->ResetPortMask;
262 PortBit = 1 << (Port - 1);
263
264 if (ResetPortMask & PortBit)
265 return MP_STATUS_FAILURE;
266
267 UhciExtension->ResetPortMask = ResetPortMask | PortBit;
268
269 if (UhciExtension->HcFlavor == UHCI_VIA ||
270 UhciExtension->HcFlavor == UHCI_VIA_x01 ||
271 UhciExtension->HcFlavor == UHCI_VIA_x02 ||
272 UhciExtension->HcFlavor == UHCI_VIA_x03 ||
273 UhciExtension->HcFlavor == UHCI_VIA_x04)
274 {
275 DPRINT1("UhciRHSetFeaturePortReset: Via chip. FIXME\n");
276 return MP_STATUS_SUCCESS;
277 }
278
279 UhciRHSetFeaturePortResetWorker(UhciExtension, &Port);
280
281 return MP_STATUS_SUCCESS;
282 }
283
284 MPSTATUS
285 NTAPI
UhciRHSetFeaturePortPower(IN PVOID uhciExtension,IN USHORT Port)286 UhciRHSetFeaturePortPower(IN PVOID uhciExtension,
287 IN USHORT Port)
288 {
289 DPRINT("UhciRHSetFeaturePortPower: ...\n");
290 ASSERT(Port);
291 return MP_STATUS_SUCCESS;
292 }
293
294 MPSTATUS
295 NTAPI
UhciRHPortEnable(IN PVOID uhciExtension,IN USHORT Port,IN BOOLEAN IsSet)296 UhciRHPortEnable(IN PVOID uhciExtension,
297 IN USHORT Port,
298 IN BOOLEAN IsSet)
299 {
300 PUHCI_EXTENSION UhciExtension = uhciExtension;
301 PUHCI_HW_REGISTERS BaseRegister;
302 PUSHORT PortControlRegister;
303 UHCI_PORT_STATUS_CONTROL PortControl;
304
305 DPRINT("UhciRHPortEnable: ...\n");
306
307 ASSERT(Port);
308
309 BaseRegister = UhciExtension->BaseRegister;
310 PortControlRegister = &BaseRegister->PortControl[Port-1].AsUSHORT;
311
312 PortControl.AsUSHORT = READ_PORT_USHORT(PortControlRegister);
313
314 PortControl.ConnectStatusChange = 0;
315 PortControl.PortEnableDisableChange = 0;
316
317 if (IsSet)
318 PortControl.PortEnabledDisabled = 1;
319 else
320 PortControl.PortEnabledDisabled = 0;
321
322 WRITE_PORT_USHORT(PortControlRegister, PortControl.AsUSHORT);
323
324 return MP_STATUS_SUCCESS;
325 }
326
327 MPSTATUS
328 NTAPI
UhciRHSetFeaturePortEnable(IN PVOID uhciExtension,IN USHORT Port)329 UhciRHSetFeaturePortEnable(IN PVOID uhciExtension,
330 IN USHORT Port)
331 {
332 PUHCI_EXTENSION UhciExtension = uhciExtension;
333 DPRINT("UhciRHSetFeaturePortEnable: ...\n");
334 ASSERT(Port);
335 return UhciRHPortEnable(UhciExtension, Port, TRUE);
336 }
337
338 MPSTATUS
339 NTAPI
UhciRHSetFeaturePortSuspend(IN PVOID uhciExtension,IN USHORT Port)340 UhciRHSetFeaturePortSuspend(IN PVOID uhciExtension,
341 IN USHORT Port)
342 {
343 DPRINT("UhciRHSetFeaturePortSuspend: UNIMPLEMENTED. FIXME\n");
344 ASSERT(Port);
345 return MP_STATUS_SUCCESS;
346 }
347
348 MPSTATUS
349 NTAPI
UhciRHClearFeaturePortEnable(IN PVOID uhciExtension,IN USHORT Port)350 UhciRHClearFeaturePortEnable(IN PVOID uhciExtension,
351 IN USHORT Port)
352 {
353 PUHCI_EXTENSION UhciExtension = uhciExtension;
354 DPRINT("UhciRHClearFeaturePortEnable: ...\n");
355 ASSERT(Port);
356 return UhciRHPortEnable(UhciExtension, Port, FALSE);
357 }
358
359 MPSTATUS
360 NTAPI
UhciRHClearFeaturePortPower(IN PVOID uhciExtension,IN USHORT Port)361 UhciRHClearFeaturePortPower(IN PVOID uhciExtension,
362 IN USHORT Port)
363 {
364 DPRINT("UhciRHClearFeaturePortPower: UNIMPLEMENTED. FIXME\n");
365 ASSERT(Port);
366 return MP_STATUS_SUCCESS;
367 }
368
369 MPSTATUS
370 NTAPI
UhciRHClearFeaturePortSuspend(IN PVOID uhciExtension,IN USHORT Port)371 UhciRHClearFeaturePortSuspend(IN PVOID uhciExtension,
372 IN USHORT Port)
373 {
374 DPRINT("UhciRHClearFeaturePortSuspend: UNIMPLEMENTED. FIXME\n");
375 ASSERT(Port);
376 return MP_STATUS_SUCCESS;
377 }
378
379 MPSTATUS
380 NTAPI
UhciRHClearFeaturePortEnableChange(IN PVOID uhciExtension,IN USHORT Port)381 UhciRHClearFeaturePortEnableChange(IN PVOID uhciExtension,
382 IN USHORT Port)
383 {
384 PUHCI_EXTENSION UhciExtension = uhciExtension;
385 PUHCI_HW_REGISTERS BaseRegister;
386 PUSHORT PortControlRegister;
387 UHCI_PORT_STATUS_CONTROL PortControl;
388
389 DPRINT("UhciRHClearFeaturePortEnableChange: ...\n");
390
391 ASSERT(Port);
392
393 BaseRegister = UhciExtension->BaseRegister;
394 PortControlRegister = (PUSHORT)&BaseRegister->PortControl[Port - 1];
395 PortControl.AsUSHORT = READ_PORT_USHORT(PortControlRegister);
396
397 PortControl.ConnectStatusChange = 0;
398 PortControl.PortEnableDisableChange = 1;
399 WRITE_PORT_USHORT(PortControlRegister, PortControl.AsUSHORT);
400
401 return MP_STATUS_SUCCESS;
402 }
403
404 MPSTATUS
405 NTAPI
UhciRHClearFeaturePortConnectChange(IN PVOID uhciExtension,IN USHORT Port)406 UhciRHClearFeaturePortConnectChange(IN PVOID uhciExtension,
407 IN USHORT Port)
408 {
409 PUHCI_EXTENSION UhciExtension = uhciExtension;
410 PUHCI_HW_REGISTERS BaseRegister;
411 PUSHORT PortControlRegister;
412 UHCI_PORT_STATUS_CONTROL PortControl;
413
414 DPRINT("UhciRHClearFeaturePortConnectChange: Port - %04X\n", Port);
415
416 ASSERT(Port);
417
418 BaseRegister = UhciExtension->BaseRegister;
419 PortControlRegister = (PUSHORT)&BaseRegister->PortControl[Port - 1];
420 PortControl.AsUSHORT = READ_PORT_USHORT(PortControlRegister);
421
422 if (PortControl.ConnectStatusChange == 1)
423 {
424 /* WC (Write Clear) bits */
425 PortControl.PortEnableDisableChange = 0;
426 PortControl.ConnectStatusChange = 1;
427 WRITE_PORT_USHORT(PortControlRegister, PortControl.AsUSHORT);
428 }
429
430 return MP_STATUS_SUCCESS;
431 }
432
433 MPSTATUS
434 NTAPI
UhciRHClearFeaturePortResetChange(IN PVOID uhciExtension,IN USHORT Port)435 UhciRHClearFeaturePortResetChange(IN PVOID uhciExtension,
436 IN USHORT Port)
437 {
438 PUHCI_EXTENSION UhciExtension = uhciExtension;
439 DPRINT("UhciRHClearFeaturePortResetChange: ...\n");
440 ASSERT(Port);
441 UhciExtension->ResetChangePortMask &= ~(1 << (Port - 1));
442 return MP_STATUS_SUCCESS;
443 }
444
445 MPSTATUS
446 NTAPI
UhciRHClearFeaturePortSuspendChange(IN PVOID uhciExtension,IN USHORT Port)447 UhciRHClearFeaturePortSuspendChange(IN PVOID uhciExtension,
448 IN USHORT Port)
449 {
450 DPRINT("UhciRHClearFeaturePortSuspendChange: UNIMPLEMENTED. FIXME\n");
451 ASSERT(Port);
452 return MP_STATUS_SUCCESS;
453 }
454
455 MPSTATUS
456 NTAPI
UhciRHClearFeaturePortOvercurrentChange(IN PVOID uhciExtension,IN USHORT Port)457 UhciRHClearFeaturePortOvercurrentChange(IN PVOID uhciExtension,
458 IN USHORT Port)
459 {
460 DPRINT("UhciRHClearFeaturePortOvercurrentChange: UNIMPLEMENTED. FIXME\n");
461 ASSERT(Port);
462 return MP_STATUS_SUCCESS;
463 }
464
465 VOID
466 NTAPI
UhciRHDisableIrq(IN PVOID uhciExtension)467 UhciRHDisableIrq(IN PVOID uhciExtension)
468 {
469 /* Do nothing */
470 return;
471 }
472
473 VOID
474 NTAPI
UhciRHEnableIrq(IN PVOID uhciExtension)475 UhciRHEnableIrq(IN PVOID uhciExtension)
476 {
477 /* Do nothing */
478 return;
479 }
480
481