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