xref: /reactos/drivers/usb/usbuhci/roothub.c (revision 177ae91b)
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
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
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
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
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
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         DPRINT("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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
467 UhciRHDisableIrq(IN PVOID uhciExtension)
468 {
469     /* Do nothing */
470     return;
471 }
472 
473 VOID
474 NTAPI
475 UhciRHEnableIrq(IN PVOID uhciExtension)
476 {
477     /* Do nothing */
478     return;
479 }
480 
481