ReactOS  0.4.14-dev-49-gfb4591c
hardware.cpp
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
3  * LICENSE: GPL - See COPYING in the top level directory
4  * FILE: drivers/usb/usbehci/hcd_controller.cpp
5  * PURPOSE: USB EHCI device driver.
6  * PROGRAMMERS:
7  * Michael Martin (michael.martin@reactos.org)
8  * Johannes Anderwald (johannes.anderwald@reactos.org)
9  */
10 
11 #include "usbehci.h"
12 
13 #define NDEBUG
14 #include <debug.h>
15 
17 
18 BOOLEAN
19 NTAPI
21  IN PKINTERRUPT Interrupt,
23 
24 VOID
25 NTAPI
27  IN PKDPC Dpc,
31 
32 VOID
33 NTAPI
35 
36 class CUSBHardwareDevice : public IEHCIHardwareDevice
37 {
38 public:
40 
42  {
44  return m_Ref;
45  }
47  {
49 
50  if (!m_Ref)
51  {
52  delete this;
53  return 0;
54  }
55  return m_Ref;
56  }
57  // com
60 
61  // local
67 
68  // friend function
72  // constructor / destructor
73  CUSBHardwareDevice(IUnknown *OuterUnknown){}
74  virtual ~CUSBHardwareDevice(){}
75 
76 protected:
77  LONG m_Ref; // reference count
78  PDRIVER_OBJECT m_DriverObject; // driver object
80  PDEVICE_OBJECT m_FunctionalDeviceObject; // fdo (hcd controller)
81  PDEVICE_OBJECT m_NextDeviceObject; // lower device object
82  KSPIN_LOCK m_Lock; // hardware lock
83  PKINTERRUPT m_Interrupt; // interrupt object
84  KDPC m_IntDpcObject; // dpc object for deferred isr processing
85  PVOID VirtualBase; // virtual base for memory manager
86  PHYSICAL_ADDRESS PhysicalAddress; // physical base for memory manager
87  PULONG m_Base; // EHCI operational port base registers
88  PDMA_ADAPTER m_Adapter; // dma adapter object
89  ULONG m_MapRegisters; // map registers count
90  EHCI_CAPS m_Capabilities; // EHCI caps
91  USHORT m_VendorID; // vendor id
92  USHORT m_DeviceID; // device id
93  PQUEUE_HEAD AsyncQueueHead; // async queue head terminator
94  PEHCIQUEUE m_UsbQueue; // usb request queue
96  HD_INIT_CALLBACK* m_SCECallBack; // status change callback routine
97  PVOID m_SCEContext; // status change callback routine context
98  BOOLEAN m_DoorBellRingInProgress; // door bell ring in progress
99  WORK_QUEUE_ITEM m_StatusChangeWorkItem; // work item for status change callback
100  volatile LONG m_StatusChangeWorkItemStatus; // work item status
101  ULONG m_SyncFramePhysAddr; // periodic frame list physical address
103  BOOLEAN m_PortResetInProgress[0xF]; // stores reset in progress (vbox hack)
104 
105  // read register
107 
108  // write register
110 };
111 
112 //=================================================================================================
113 // COM
114 //
115 NTSTATUS
118  IN REFIID refiid,
119  OUT PVOID* Output)
120 {
121  if (IsEqualGUIDAligned(refiid, IID_IUnknown))
122  {
123  *Output = PVOID(PUNKNOWN(this));
124  PUNKNOWN(*Output)->AddRef();
125  return STATUS_SUCCESS;
126  }
127 
128  return STATUS_UNSUCCESSFUL;
129 }
130 
131 LPCSTR
133 CUSBHardwareDevice::GetUSBType()
134 {
135  return "USBEHCI";
136 }
137 
138 NTSTATUS
145 {
146  PCI_COMMON_CONFIG PciConfig;
149 
150  DPRINT("CUSBHardwareDevice::Initialize\n");
151 
152  //
153  // Create DMAMemoryManager for use with QueueHeads and Transfer Descriptors.
154  //
156  if (!NT_SUCCESS(Status))
157  {
158  DPRINT1("Failed to create DMAMemoryManager Object\n");
159  return Status;
160  }
161 
162  //
163  // Create the UsbQueue class that will handle the Asynchronous and Periodic Schedules
164  //
166  if (!NT_SUCCESS(Status))
167  {
168  DPRINT1("Failed to create UsbQueue!\n");
169  return Status;
170  }
171 
172  //
173  // store device objects
174  //
179 
180  //
181  // initialize device lock
182  //
184 
185  //
186  // initialize status change work item
187  //
189 
190  m_VendorID = 0;
191  m_DeviceID = 0;
192 
194  if (!NT_SUCCESS(Status))
195  {
196  DPRINT1("Failed to get BusInterface!\n");
197  return Status;
198  }
199 
202  &PciConfig,
203  0,
205 
207  {
208  DPRINT1("Failed to get pci config information!\n");
209  return STATUS_SUCCESS;
210  }
211 
212  m_VendorID = PciConfig.VendorID;
213  m_DeviceID = PciConfig.DeviceID;
214 
215  return STATUS_SUCCESS;
216 }
217 
218 VOID
220 CUSBHardwareDevice::SetCommandRegister(PEHCI_USBCMD_CONTENT UsbCmd)
221 {
222  PULONG Register;
223  Register = (PULONG)UsbCmd;
225 }
226 
227 VOID
229 CUSBHardwareDevice::GetCommandRegister(PEHCI_USBCMD_CONTENT UsbCmd)
230 {
231  PULONG Register;
232  Register = (PULONG)UsbCmd;
234 }
235 
236 ULONG
238 {
240 }
241 
242 VOID
244 {
246 }
247 
248 VOID
250 {
252  {
253  DPRINT1("Controller EHCI has Port Power Control\n");
254  }
255 
256  DPRINT1("Controller Port Routing Rules %lu\n", m_Capabilities.HCSParams.PortRouteRules);
257  DPRINT1("Number of Ports per Companion Controller %lu\n", m_Capabilities.HCSParams.PortPerCHC);
258  DPRINT1("Number of Companion Controller %lu\n", m_Capabilities.HCSParams.CHCCount);
259 
261  {
262  DPRINT1("Controller has Port Indicators Support\n");
263  }
264 
266  {
267  DPRINT1("Controller has Debug Port Support At Port %x\n", m_Capabilities.HCSParams.DbgPortNum);
268  }
269 
271  {
272  DPRINT1("Controller has Extended Capabilities Support\n");
273  }
274 
276  {
277  DPRINT1("Controller supports Asynchronous Schedule Park\n");
278  }
279 
281  {
282  DPRINT1("Controller supports Programmable Frame List Size\n");
283  }
284 
286  {
287  DPRINT1("Controller uses 64-Bit Addressing\n");
288  }
289 }
290 
291 NTSTATUS
293 CUSBHardwareDevice::PnpStart(
294  PCM_RESOURCE_LIST RawResources,
295  PCM_RESOURCE_LIST TranslatedResources)
296 {
297  ULONG Index, Count;
298  PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor;
300  PHYSICAL_ADDRESS AsyncPhysicalAddress;
301  PVOID ResourceBase;
303  UCHAR Value;
304  UCHAR PortCount;
305 
306  DPRINT("CUSBHardwareDevice::PnpStart\n");
307  for(Index = 0; Index < TranslatedResources->List[0].PartialResourceList.Count; Index++)
308  {
309  //
310  // get resource descriptor
311  //
312  ResourceDescriptor = &TranslatedResources->List[0].PartialResourceList.PartialDescriptors[Index];
313 
314  switch(ResourceDescriptor->Type)
315  {
317  {
320  this);
321 
324  (PVOID)this,
325  NULL,
326  ResourceDescriptor->u.Interrupt.Vector,
327  (KIRQL)ResourceDescriptor->u.Interrupt.Level,
328  (KIRQL)ResourceDescriptor->u.Interrupt.Level,
329  (KINTERRUPT_MODE)(ResourceDescriptor->Flags & CM_RESOURCE_INTERRUPT_LATCHED),
330  (ResourceDescriptor->ShareDisposition != CmResourceShareDeviceExclusive),
331  ResourceDescriptor->u.Interrupt.Affinity,
332  FALSE);
333 
334  if (!NT_SUCCESS(Status))
335  {
336  //
337  // failed to register interrupt
338  //
339  DPRINT1("IoConnect Interrupt failed with %x\n", Status);
340  return Status;
341  }
342  break;
343  }
345  {
346  //
347  // get resource base
348  //
349  ResourceBase = MmMapIoSpace(ResourceDescriptor->u.Memory.Start, ResourceDescriptor->u.Memory.Length, MmNonCached);
350  if (!ResourceBase)
351  {
352  //
353  // failed to map registers
354  //
355  DPRINT1("MmMapIoSpace failed\n");
357  }
358 
359  //
360  // Get controllers capabilities
361  //
366 
367  DPRINT1("Controller Capabilities Length 0x%x\n", m_Capabilities.Length);
368  DPRINT1("Controller EHCI Version 0x%x\n", m_Capabilities.HCIVersion);
369  DPRINT1("Controller EHCI Caps HCSParamsLong 0x%lx\n", m_Capabilities.HCSParamsLong);
370  DPRINT1("Controller EHCI Caps HCCParamsLong 0x%lx\n", m_Capabilities.HCCParamsLong);
371  DPRINT1("Controller has %lu Ports\n", m_Capabilities.HCSParams.PortCount);
372 
373  //
374  // print capabilities
375  //
377 
379  {
380  Count = 0;
382  do
383  {
384  //
385  // each entry is a 4 bit field EHCI 2.2.5
386  //
388  m_Capabilities.PortRoute[Count*2] = (Value & 0xF0);
389 
390  if ((Count*2) + 1 < m_Capabilities.HCSParams.PortCount)
391  m_Capabilities.PortRoute[(Count*2)+1] = (Value & 0x0F);
392 
393  Count++;
394  } while(Count < PortCount);
395  }
396 
397  //
398  // Set m_Base to the address of Operational Register Space
399  //
400  m_Base = (PULONG)((ULONG_PTR)ResourceBase + m_Capabilities.Length);
401  break;
402  }
403  }
404  }
405 
406 
407  //
408  // zero device description
409  //
411 
412  //
413  // initialize device description
414  //
422 
423  //
424  // get dma adapter
425  //
427  if (!m_Adapter)
428  {
429  //
430  // failed to get dma adapter
431  //
432  DPRINT1("Failed to acquire dma adapter\n");
434  }
435 
436  //
437  // Create Common Buffer
438  //
439  VirtualBase = m_Adapter->DmaOperations->AllocateCommonBuffer(m_Adapter,
440  PAGE_SIZE * 4,
442  FALSE);
443  if (!VirtualBase)
444  {
445  DPRINT1("Failed to allocate a common buffer\n");
447  }
448 
449  //
450  // Initialize the DMAMemoryManager
451  //
452  Status = m_MemoryManager->Initialize(this, &m_Lock, PAGE_SIZE * 4, VirtualBase, PhysicalAddress, 32);
453  if (!NT_SUCCESS(Status))
454  {
455  DPRINT1("Failed to initialize the DMAMemoryManager\n");
456  return Status;
457  }
458 
459  //
460  // Create a queuehead for the Async Register
461  //
462  m_MemoryManager->Allocate(sizeof(QUEUE_HEAD), (PVOID*)&AsyncQueueHead, &AsyncPhysicalAddress);
463 
464  AsyncQueueHead->PhysicalAddr = AsyncPhysicalAddress.LowPart;
469 
473 
475 
476  //
477  // Initialize the UsbQueue now that we have an AdapterObject.
478  //
480  if (!NT_SUCCESS(Status))
481  {
482  DPRINT1("Failed to Initialize the UsbQueue\n");
483  return Status;
484  }
485 
486  //
487  // Start the controller
488  //
489  DPRINT1("Starting Controller\n");
491 
492  //
493  // done
494  //
495  return Status;
496 }
497 
498 NTSTATUS
500 CUSBHardwareDevice::PnpStop(void)
501 {
503  return STATUS_NOT_IMPLEMENTED;
504 }
505 
506 NTSTATUS
508 CUSBHardwareDevice::GetDeviceDetails(
509  OUT OPTIONAL PUSHORT VendorId,
510  OUT OPTIONAL PUSHORT DeviceId,
512  OUT OPTIONAL PULONG Speed)
513 {
514  if (VendorId)
515  *VendorId = m_VendorID;
516  if (DeviceId)
517  *DeviceId = m_DeviceID;
518  if (NumberOfPorts)
520  //FIXME: What to returned here?
521  if (Speed)
522  *Speed = 0x200;
523  return STATUS_SUCCESS;
524 }
525 
526 NTSTATUS
528 CUSBHardwareDevice::GetDMA(
529  OUT struct IDMAMemoryManager **OutDMAMemoryManager)
530 {
531  if (!m_MemoryManager)
532  return STATUS_UNSUCCESSFUL;
533  *OutDMAMemoryManager = m_MemoryManager;
534  return STATUS_SUCCESS;
535 }
536 
537 NTSTATUS
539 CUSBHardwareDevice::GetUSBQueue(
540  OUT struct IUSBQueue **OutUsbQueue)
541 {
542  if (!m_UsbQueue)
543  return STATUS_UNSUCCESSFUL;
544  *OutUsbQueue = m_UsbQueue;
545  return STATUS_SUCCESS;
546 }
547 
548 
549 NTSTATUS
551 {
552  EHCI_USBCMD_CONTENT UsbCmd;
553  ULONG UsbSts, FailSafe, ExtendedCapsSupport, Caps, Index;
554  UCHAR Value;
556 
557  //
558  // are extended caps supported
559  //
560  ExtendedCapsSupport = (m_Capabilities.HCCParamsLong >> EHCI_ECP_SHIFT) & EHCI_ECP_MASK;
561  if (ExtendedCapsSupport)
562  {
563  DPRINT1("[EHCI] Extended Caps Support detected!\n");
564 
565  //
566  // sanity check
567  //
568  ASSERT(ExtendedCapsSupport >= PCI_COMMON_HDR_LENGTH);
569  m_BusInterface.GetBusData(m_BusInterface.Context, PCI_WHICHSPACE_CONFIG, &Caps, ExtendedCapsSupport, sizeof(ULONG));
570 
571  //
572  // OS Handoff Synchronization support capability. EHCI 5.1
573  //
575  {
576  //
577  // is it bios owned
578  //
579  if ((Caps & EHCI_LEGSUP_BIOSOWNED))
580  {
581  DPRINT1("[EHCI] Controller is BIOS owned, acquiring control\n");
582 
583  //
584  // acquire ownership
585  //
586  Value = 1;
588 
589  for(Index = 0; Index < 20; Index++)
590  {
591  //
592  // get status
593  //
594  m_BusInterface.GetBusData(m_BusInterface.Context, PCI_WHICHSPACE_CONFIG, &Caps, ExtendedCapsSupport, sizeof(ULONG));
595  if ((Caps & EHCI_LEGSUP_BIOSOWNED))
596  {
597  //
598  // lets wait a bit
599  //
600  Timeout.QuadPart = 50;
601  DPRINT1("Waiting %lu milliseconds for port reset\n", Timeout.LowPart);
602 
603  //
604  // convert to 100 ns units (absolute)
605  //
606  Timeout.QuadPart *= -10000;
607 
608  //
609  // perform the wait
610  //
612  }
613  }
614  if ((Caps & EHCI_LEGSUP_BIOSOWNED))
615  {
616  //
617  // failed to acquire ownership
618  //
619  DPRINT1("[EHCI] failed to acquire ownership\n");
620  }
621  else if ((Caps & EHCI_LEGSUP_OSOWNED))
622  {
623  //
624  // HC OS Owned Semaphore EHCI 2.1.7
625  //
626  DPRINT1("[EHCI] acquired ownership\n");
627  }
628 #if 0
629  //
630  // explicitly clear the bios owned flag 2.1.7
631  //
632  Value = 0;
634 
635  //
636  // clear SMI interrupt EHCI 2.1.8
637  //
638  Caps = 4;
639  m_BusInterface.SetBusData(m_BusInterface.Context, PCI_WHICHSPACE_CONFIG, &Caps, ExtendedCapsSupport+4, sizeof(ULONG));
640 #endif
641  }
642  }
643  }
644 
645  //
646  // get command register
647  //
648  GetCommandRegister(&UsbCmd);
649 
650  //
651  // disable running schedules
652  //
653  UsbCmd.PeriodicEnable = FALSE;
654  UsbCmd.AsyncEnable = FALSE;
655  SetCommandRegister(&UsbCmd);
656 
657  //
658  // Wait for execution to start
659  //
660  for (FailSafe = 100; FailSafe > 1; FailSafe--)
661  {
664 
665  if (!(UsbSts & EHCI_STS_PSS) && (UsbSts & EHCI_STS_ASS))
666  {
667  break;
668  }
669  }
670 
671  if ((UsbSts & (EHCI_STS_PSS | EHCI_STS_ASS)))
672  {
673  DPRINT1("Failed to stop running schedules %x\n", UsbSts);
674  //ASSERT(FALSE);
675  }
676 
677 
678  //
679  // Stop the controller if its running
680  //
682  if (!(UsbSts & EHCI_STS_HALT))
683  {
684  DPRINT1("Stopping Controller %x\n", UsbSts);
685  StopController();
686  }
687 
688  //
689  // Reset the controller
690  //
691  ResetController();
692 
693  //
694  // check caps
695  //
697  {
698  //
699  // disable 64-bit addressing
700  //
702  }
703 
704  //
705  // Enable Interrupts and start execution
706  //
709 
711 
713 
714  DPRINT1("Interrupt Mask %x\n", Status);
715  ASSERT((Status & Mask) == Mask);
716 
717  //
718  // Assign the SyncList Register
719  //
721 
722  //
723  // Set Schedules to Enable and Interrupt Threshold to 1ms.
724  //
725  RtlZeroMemory(&UsbCmd, sizeof(EHCI_USBCMD_CONTENT));
726 
727  UsbCmd.PeriodicEnable = TRUE;
728  UsbCmd.IntThreshold = 0x8; //1ms
729  UsbCmd.Run = TRUE;
730  UsbCmd.FrameListSize = 0x0; //1024
731 
733  {
734  //
735  // enable async park mode
736  //
737  UsbCmd.AsyncParkEnable = TRUE;
738  UsbCmd.AsyncParkCount = 3;
739  }
740 
741  SetCommandRegister(&UsbCmd);
742 
743 
744  //
745  // Wait for execution to start
746  //
747  for (FailSafe = 100; FailSafe > 1; FailSafe--)
748  {
751 
752  if (!(UsbSts & EHCI_STS_HALT) && (UsbSts & EHCI_STS_PSS))
753  {
754  break;
755  }
756  }
757 
758  if (UsbSts & EHCI_STS_HALT)
759  {
760  DPRINT1("Could not start execution on the controller\n");
761  //ASSERT(FALSE);
762  return STATUS_UNSUCCESSFUL;
763  }
764 
765  if (!(UsbSts & EHCI_STS_PSS))
766  {
767  DPRINT1("Could not enable periodic scheduling\n");
768  //ASSERT(FALSE);
769  return STATUS_UNSUCCESSFUL;
770  }
771 
772  //
773  // Assign the AsyncList Register
774  //
776 
777  //
778  // get command register
779  //
780  GetCommandRegister(&UsbCmd);
781 
782  //
783  // preserve bits
784  //
785  UsbCmd.AsyncEnable = TRUE;
786 
787  //
788  // enable async
789  //
790  SetCommandRegister(&UsbCmd);
791 
792  //
793  // Wait for execution to start
794  //
795  for (FailSafe = 100; FailSafe > 1; FailSafe--)
796  {
799 
800  if ((UsbSts & EHCI_STS_ASS))
801  {
802  break;
803  }
804  }
805 
806  if (!(UsbSts & EHCI_STS_ASS))
807  {
808  DPRINT1("Failed to enable async schedule UsbSts %x\n", UsbSts);
809  //ASSERT(FALSE);
810  return STATUS_UNSUCCESSFUL;
811  }
812 
813  DPRINT1("UsbSts %x\n", UsbSts);
814  GetCommandRegister(&UsbCmd);
815 
816  DPRINT1("UsbCmd.PeriodicEnable %x\n", UsbCmd.PeriodicEnable);
817  DPRINT1("UsbCmd.AsyncEnable %x\n", UsbCmd.AsyncEnable);
818  DPRINT1("UsbCmd.IntThreshold %x\n", UsbCmd.IntThreshold);
819  DPRINT1("UsbCmd.Run %x\n", UsbCmd.Run);
820  DPRINT1("UsbCmd.FrameListSize %x\n", UsbCmd.FrameListSize);
821 
822  //
823  // Set port routing to EHCI controller
824  //
826 
827  DPRINT1("EHCI Started!\n");
828  return STATUS_SUCCESS;
829 }
830 
831 NTSTATUS
833 {
834  EHCI_USBCMD_CONTENT UsbCmd;
835  ULONG UsbSts, FailSafe;
836 
837  //
838  // Disable Interrupts and stop execution
839  //
841 
842  GetCommandRegister(&UsbCmd);
843  UsbCmd.Run = FALSE;
844  SetCommandRegister(&UsbCmd);
845 
846  for (FailSafe = 100; FailSafe > 1; FailSafe--)
847  {
850  if (UsbSts & EHCI_STS_HALT)
851  {
852  break;
853  }
854  }
855 
856  if (!(UsbSts & EHCI_STS_HALT))
857  {
858  DPRINT1("EHCI ERROR: Controller is not responding to Stop request!\n");
859  return STATUS_UNSUCCESSFUL;
860  }
861 
862  return STATUS_SUCCESS;
863 }
864 
865 NTSTATUS
867 {
868  EHCI_USBCMD_CONTENT UsbCmd;
869  ULONG FailSafe;
870 
871  GetCommandRegister(&UsbCmd);
872  UsbCmd.HCReset = TRUE;
873  SetCommandRegister(&UsbCmd);
874 
875  for (FailSafe = 100; FailSafe > 1; FailSafe--)
876  {
878  GetCommandRegister(&UsbCmd);
879  if (!UsbCmd.HCReset)
880  break;
881  }
882 
883  if (UsbCmd.HCReset)
884  {
885  DPRINT1("EHCI ERROR: Controller is not responding to reset request!\n");
886  return STATUS_UNSUCCESSFUL;
887  }
888 
889  return STATUS_SUCCESS;
890 }
891 
892 NTSTATUS
894 CUSBHardwareDevice::ResetPort(
895  IN ULONG PortIndex)
896 {
899 
900  if (PortIndex > m_Capabilities.HCSParams.PortCount)
901  return STATUS_UNSUCCESSFUL;
902 
903  PortStatus = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortIndex));
904 
907 
908  //
909  // Reset and clean enable
910  //
914 
915  //
916  // delay is 50 ms for port reset as per USB 2.0 spec
917  //
918  Timeout.QuadPart = 50;
919  DPRINT1("Waiting %lu milliseconds for port reset\n", Timeout.LowPart);
920 
921  //
922  // convert to 100 ns units (absolute)
923  //
924  Timeout.QuadPart *= -10000;
925 
926  //
927  // perform the wait
928  //
930 
931  return STATUS_SUCCESS;
932 }
933 
934 NTSTATUS
936 CUSBHardwareDevice::GetPortStatus(
937  ULONG PortId,
939  OUT USHORT *PortChange)
940 {
941  ULONG Value;
942  USHORT Status = 0, Change = 0;
943 
944  if (PortId > m_Capabilities.HCSParams.PortCount)
945  return STATUS_UNSUCCESSFUL;
946 
947  //
948  // Get the value of the Port Status and Control Register
949  //
950  Value = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId));
951 
952  //
953  // If the PowerPortControl is 0 then host controller does not have power control switches
955  {
957  }
958  else
959  {
960  // Check the value of PortPower
961  if (Value & EHCI_PRT_POWER)
962  {
964  }
965  }
966 
967  // Get Connected Status
969  {
971 
972  // EHCI only supports high speed
974  }
975 
976  // Get Enabled Status
977  if (Value & EHCI_PRT_ENABLED)
979 
980  // Is it suspended?
981  if (Value & EHCI_PRT_SUSPEND)
983 
984  // a overcurrent is active?
987 
988  // In a reset state?
989  if ((Value & EHCI_PRT_RESET) || m_PortResetInProgress[PortId])
990  {
992  Change |= USB_PORT_STATUS_RESET;
993  }
994 
995  // This indicates a connect or disconnect
997  Change |= USB_PORT_STATUS_CONNECT;
998 
999  // This is set to indicate a critical port error
1001  Change |= USB_PORT_STATUS_ENABLE;
1002 
1003  *PortStatus = Status;
1004  *PortChange = Change;
1005 
1006  return STATUS_SUCCESS;
1007 }
1008 
1009 NTSTATUS
1011 CUSBHardwareDevice::ClearPortStatus(
1012  ULONG PortId,
1013  ULONG Status)
1014 {
1015  ULONG Value;
1017 
1018  DPRINT("CUSBHardwareDevice::ClearPortStatus PortId %x Feature %x\n", PortId, Status);
1019 
1020  if (PortId > m_Capabilities.HCSParams.PortCount)
1021  return STATUS_UNSUCCESSFUL;
1022 
1023  if (Status == C_PORT_RESET)
1024  {
1025  // reset done
1026  m_PortResetInProgress[PortId] = FALSE;
1027 
1028  // Clear reset
1029  Value = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId));
1031  Value &= ~EHCI_PRT_RESET;
1032  EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId), Value);
1033 
1034  //
1035  // wait for reset bit to clear
1036  //
1037  do
1038  {
1039  Value = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId));
1040 
1041  if (!(Value & EHCI_PRT_RESET))
1042  break;
1043 
1045  } while (TRUE);
1046 
1047  //
1048  // delay is 50 ms
1049  //
1050  Timeout.QuadPart = 50;
1051  DPRINT1("Waiting %lu milliseconds for port to recover after reset\n", Timeout.LowPart);
1052 
1053  //
1054  // convert to 100 ns units (absolute)
1055  //
1056  Timeout.QuadPart *= -10000;
1057 
1058  //
1059  // perform the wait
1060  //
1062 
1063  //
1064  // check the port status after reset
1065  //
1066  Value = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId));
1067  if (!(Value & EHCI_PRT_CONNECTED))
1068  {
1069  DPRINT1("No device is here after reset. Bad controller/device?\n");
1070  return STATUS_UNSUCCESSFUL;
1071  }
1072  else if (EHCI_IS_LOW_SPEED(Value))
1073  {
1074  DPRINT1("Low speed device connected. Releasing ownership\n");
1077  }
1078  else if (!(Value & EHCI_PRT_ENABLED))
1079  {
1080  DPRINT1("Full speed device connected. Releasing ownership\n");
1083  }
1084  else
1085  {
1086  DPRINT1("High speed device connected\n");
1087  return STATUS_SUCCESS;
1088  }
1089  }
1090  else if (Status == C_PORT_CONNECTION)
1091  {
1092  //
1093  // reset status change bits
1094  //
1095  Value = EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId));
1096  EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId), Value);
1097 
1098  if (Value & EHCI_PRT_CONNECTED)
1099  {
1100  //
1101  // delay is 100 ms
1102  //
1103  Timeout.QuadPart = 100;
1104  DPRINT1("Waiting %lu milliseconds for port to stabilize after connection\n", Timeout.LowPart);
1105 
1106  //
1107  // convert to 100 ns units (absolute)
1108  //
1109  Timeout.QuadPart *= -10000;
1110 
1111  //
1112  // perform the wait
1113  //
1115  }
1116  }
1117 
1118  return STATUS_SUCCESS;
1119 }
1120 
1121 
1122 NTSTATUS
1125  ULONG PortId,
1126  ULONG Feature)
1127 {
1128  DPRINT("CUSBHardwareDevice::SetPortFeature\n");
1129 
1130  if (PortId > m_Capabilities.HCSParams.PortCount)
1131  return STATUS_UNSUCCESSFUL;
1132 
1133  if (Feature == PORT_ENABLE)
1134  {
1135  //
1136  // FIXME: EHCI Ports can only be disabled via reset
1137  //
1138  DPRINT1("PORT_ENABLE not supported for EHCI\n");
1139  }
1140 
1141  if (Feature == PORT_RESET)
1142  {
1143  //
1144  // call the helper
1145  //
1146  ResetPort(PortId);
1147 
1148  // reset in progress
1149  m_PortResetInProgress[PortId] = TRUE;
1150 
1151  //
1152  // is there a status change callback
1153  //
1154  if (m_SCECallBack != NULL)
1155  {
1156  //
1157  // issue callback
1158  //
1160  }
1161  }
1162 
1163  if (Feature == PORT_POWER)
1164  {
1166  {
1167  ULONG Value;
1169 
1170  //
1171  // enable port power
1172  //
1174  EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * PortId), Value);
1175 
1176  //
1177  // delay is 20 ms
1178  //
1179  Timeout.QuadPart = 20;
1180  DPRINT1("Waiting %lu milliseconds for port power up\n", Timeout.LowPart);
1181 
1182  //
1183  // convert to 100 ns units (absolute)
1184  //
1185  Timeout.QuadPart *= -10000;
1186 
1187  //
1188  // perform the wait
1189  //
1191  }
1192  }
1193  return STATUS_SUCCESS;
1194 }
1195 
1196 VOID
1198 CUSBHardwareDevice::SetAsyncListRegister(
1200 {
1202 }
1203 
1204 VOID
1206 CUSBHardwareDevice::SetPeriodicListRegister(
1208 {
1209  //
1210  // store physical address
1211  //
1213 }
1214 
1215 struct _QUEUE_HEAD *
1217 CUSBHardwareDevice::GetAsyncListQueueHead()
1218 {
1219  return AsyncQueueHead;
1220 }
1221 
1222 ULONG
1224 CUSBHardwareDevice::GetPeriodicListRegister()
1225 {
1226  UNIMPLEMENTED;
1227  return NULL;
1228 }
1229 
1230 VOID
1232 CUSBHardwareDevice::SetStatusChangeEndpointCallBack(
1233  PVOID CallBack,
1234  PVOID Context)
1235 {
1236  m_SCECallBack = (HD_INIT_CALLBACK*)CallBack;
1238 }
1239 
1240 BOOLEAN
1241 NTAPI
1243  IN PKINTERRUPT Interrupt,
1245 {
1247  ULONG CStatus;
1248 
1250  CStatus = This->EHCI_READ_REGISTER_ULONG(EHCI_USBSTS);
1251 
1253  DPRINT("InterruptServiceRoutine CStatus %lx\n", CStatus);
1254 
1255  //
1256  // Check that it belongs to EHCI
1257  //
1258  if (!CStatus)
1259  return FALSE;
1260 
1261  //
1262  // Clear the Status
1263  //
1264  This->EHCI_WRITE_REGISTER_ULONG(EHCI_USBSTS, CStatus);
1265 
1266  if (CStatus & EHCI_STS_FATAL)
1267  {
1268  This->StopController();
1269  DPRINT1("EHCI: Host System Error!\n");
1270  return TRUE;
1271  }
1272 
1273  if (CStatus & EHCI_ERROR_INT)
1274  {
1275  DPRINT1("EHCI Status = 0x%x\n", CStatus);
1276  }
1277 
1278  if (CStatus & EHCI_STS_HALT)
1279  {
1280  DPRINT1("Host Error Unexpected Halt\n");
1281  // FIXME: Reset controller\n");
1282  return TRUE;
1283  }
1284 
1285  KeInsertQueueDpc(&This->m_IntDpcObject, This, UlongToPtr(CStatus));
1286  return TRUE;
1287 }
1288 
1289 VOID NTAPI
1291  IN PKDPC Dpc,
1295 {
1297  ULONG CStatus, PortStatus, PortCount, i, ShouldRingDoorBell, QueueSCEWorkItem;
1299  EHCI_USBCMD_CONTENT UsbCmd;
1300 
1302  CStatus = PtrToUlong(SystemArgument2);
1303 
1304  DPRINT("EhciDeferredRoutine CStatus %lx\n", CStatus);
1305 
1306  //
1307  // check for completion of async schedule
1308  //
1309  if (CStatus & (EHCI_STS_RECL| EHCI_STS_INT | EHCI_ERROR_INT))
1310  {
1311  //
1312  // check if there is a door bell ring in progress
1313  //
1314  if (This->m_DoorBellRingInProgress == FALSE)
1315  {
1316  if (CStatus & EHCI_ERROR_INT)
1317  {
1318  //
1319  // controller reported error
1320  //
1321  DPRINT1("CStatus %lx\n", CStatus);
1322  //ASSERT(FALSE);
1323  }
1324 
1325  //
1326  // inform IUSBQueue of a completed queue head
1327  //
1328  This->m_UsbQueue->InterruptCallback(Status, &ShouldRingDoorBell);
1329 
1330  //
1331  // was a queue head completed?
1332  //
1333  if (ShouldRingDoorBell)
1334  {
1335  //
1336  // set door ring bell in progress status flag
1337  //
1338  This->m_DoorBellRingInProgress = TRUE;
1339 
1340  //
1341  // get command register
1342  //
1343  This->GetCommandRegister(&UsbCmd);
1344 
1345  //
1346  // set door rang bell bit
1347  //
1348  UsbCmd.DoorBell = TRUE;
1349 
1350  //
1351  // update command status
1352  //
1353  This->SetCommandRegister(&UsbCmd);
1354  }
1355  }
1356  }
1357 
1358  //
1359  // check if the controller has acknowledged the door bell
1360  //
1361  if (CStatus & EHCI_STS_IAA)
1362  {
1363  //
1364  // controller has acknowledged, assert we rang the bell
1365  //
1366  PC_ASSERT(This->m_DoorBellRingInProgress == TRUE);
1367 
1368  //
1369  // now notify IUSBQueue that it can free completed requests
1370  //
1371  This->m_UsbQueue->CompleteAsyncRequests();
1372 
1373  //
1374  // door ring bell completed
1375  //
1376  This->m_DoorBellRingInProgress = FALSE;
1377  }
1378 
1379  This->GetDeviceDetails(NULL, NULL, &PortCount, NULL);
1380  if (CStatus & EHCI_STS_PCD)
1381  {
1382  QueueSCEWorkItem = FALSE;
1383  for (i = 0; i < PortCount; i++)
1384  {
1385  PortStatus = This->EHCI_READ_REGISTER_ULONG(EHCI_PORTSC + (4 * i));
1386 
1387  //
1388  // Device connected or removed
1389  //
1391  {
1393  {
1394  DPRINT1("Device connected on port %lu\n", i);
1395 
1396  if (This->m_Capabilities.HCSParams.CHCCount)
1397  {
1399  {
1400  DPRINT1("Misbehaving controller. Port should be disabled at this point\n");
1401  }
1402 
1404  {
1405  DPRINT1("Low speed device connected. Releasing ownership\n");
1406  This->EHCI_WRITE_REGISTER_ULONG(EHCI_PORTSC + (4 * i), PortStatus | EHCI_PRT_RELEASEOWNERSHIP);
1407  continue;
1408  }
1409  }
1410 
1411  //
1412  // work to do
1413  //
1414  QueueSCEWorkItem = TRUE;
1415  }
1416  else
1417  {
1418  DPRINT1("Device disconnected on port %lu\n", i);
1419 
1420  //
1421  // work to do
1422  //
1423  QueueSCEWorkItem = TRUE;
1424  }
1425  }
1426  }
1427 
1428  //
1429  // is there a status change callback and a high speed device connected / disconnected
1430  //
1431  if (QueueSCEWorkItem && This->m_SCECallBack != NULL)
1432  {
1433  if (InterlockedCompareExchange(&This->m_StatusChangeWorkItemStatus, 1, 0) == 0)
1434  {
1435  //
1436  // queue work item for processing
1437  //
1438  ExQueueWorkItem(&This->m_StatusChangeWorkItem, DelayedWorkQueue);
1439  }
1440  }
1441  }
1442  return;
1443 }
1444 
1445 VOID
1446 NTAPI
1448  PVOID Context)
1449 {
1450  //
1451  // cast to hardware object
1452  //
1454 
1455  //
1456  // is there a callback
1457  //
1458  if (This->m_SCECallBack)
1459  {
1460  //
1461  // issue callback
1462  //
1463  This->m_SCECallBack(This->m_SCEContext);
1464  }
1465 
1466  //
1467  // reset active status
1468  //
1469  InterlockedDecrement(&This->m_StatusChangeWorkItemStatus);
1470 }
1471 
1472 NTSTATUS
1473 NTAPI
1475  PUSBHARDWAREDEVICE *OutHardware)
1476 {
1478 
1480 
1481  if (!This)
1483 
1484  This->AddRef();
1485 
1486  // return result
1487  *OutHardware = (PUSBHARDWAREDEVICE)This;
1488 
1489  return STATUS_SUCCESS;
1490 }
_In_opt_ ULONG _Out_ PULONG Value
Definition: rtlfuncs.h:2343
#define EHCI_PORTSC
Definition: hardware.h:35
#define IN
Definition: typedefs.h:38
#define PORT_RESET
Definition: usbhub.h:19
#define max(a, b)
Definition: svc.c:63
#define EHCI_PRT_ENABLED
Definition: hardware.h:69
#define EHCI_CTRLDSSEGMENT
Definition: hardware.h:31
NTKERNELAPI VOID NTAPI WRITE_REGISTER_ULONG(IN PULONG Register, IN ULONG Value)
#define REFIID
Definition: guiddef.h:118
#define TRUE
Definition: types.h:120
#define EHCI_PRT_OVERCURRENTACTIVE
Definition: hardware.h:71
ULONG NumberOfTransactionPerFrame
Definition: hardware.h:186
VOID NTAPI ExQueueWorkItem(IN PWORK_QUEUE_ITEM WorkItem, IN WORK_QUEUE_TYPE QueueType)
Definition: work.c:717
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define C_PORT_CONNECTION
Definition: usbhub.h:22
IN PVOID CallBackContext
Definition: usbmport.h:466
#define USB_PORT_STATUS_ENABLE
Definition: usb200.h:152
#define PC_ASSERT(exp)
Definition: usbehci.h:17
IUSBHardwareDevice * PUSBHARDWAREDEVICE
GLint x0
Definition: linetemp.h:95
_In_ BOOLEAN Release
Definition: classpnp.h:929
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:225
#define EHCI_PRT_ENABLEDSTATUSCHANGE
Definition: hardware.h:70
PDMA_ADAPTER NTAPI IoGetDmaAdapter(IN PDEVICE_OBJECT PhysicalDeviceObject, IN PDEVICE_DESCRIPTION DeviceDescription, IN OUT PULONG NumberOfMapRegisters)
Definition: pnpdma.c:23
#define USB_PORT_STATUS_OVER_CURRENT
Definition: usb200.h:154
WORK_QUEUE_ITEM m_StatusChangeWorkItem
Definition: hardware.cpp:99
CM_FULL_RESOURCE_DESCRIPTOR List[1]
Definition: hwresource.cpp:165
IUnknown * PUNKNOWN
Definition: com_apitest.h:45
ULONG NextPointer
Definition: hardware.h:206
UCHAR Length
Definition: hardware.h:288
END_POINT_CHARACTERISTICS EndPointCharacteristics
Definition: hardware.h:201
unsigned char * PUCHAR
Definition: retypes.h:3
#define EHCI_HCSPARAMS
Definition: hardware.h:8
ULONG PortPowerControl
Definition: hardware.h:263
BOOLEAN NTAPI KeInsertQueueDpc(IN PKDPC Dpc, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
Definition: dpc.c:724
LONG NTSTATUS
Definition: precomp.h:26
NTSTATUS NTAPI CreateUSBHardware(PUSBHARDWAREDEVICE *OutHardware)
Definition: hardware.cpp:1474
static NTSTATUS GetBusInterface(IN PFDO_DEVICE_EXTENSION DeviceExtension)
Definition: fdo.c:18
#define EHCI_PRT_RELEASEOWNERSHIP
Definition: hardware.h:79
#define C_PORT_RESET
Definition: usbhub.h:26
#define InterlockedCompareExchange
Definition: interlocked.h:104
PEHCIQUEUE m_UsbQueue
Definition: hardware.cpp:94
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1015
ULONG HorizontalLinkPointer
Definition: hardware.h:200
struct _CM_PARTIAL_RESOURCE_DESCRIPTOR::@371::@374 Interrupt
KSPIN_LOCK m_Lock
Definition: hardware.cpp:82
#define EHCI_USBINTR_ERR
Definition: hardware.h:41
ULONG PortRouteRules
Definition: hardware.h:265
QETD_TOKEN_BITS Bits
Definition: hardware.h:212
VOID NTAPI StatusChangeWorkItemRoutine(PVOID Context)
Definition: hardware.cpp:1447
PVOID NTAPI MmMapIoSpace(IN PHYSICAL_ADDRESS PhysicalAddress, IN SIZE_T NumberOfBytes, IN MEMORY_CACHING_TYPE CacheType)
Definition: iosup.c:47
ULONG HCCParamsLong
Definition: hardware.h:299
PDEVICE_OBJECT PhysicalDeviceObject
Definition: btrfs_drv.h:1114
NTKERNELAPI ULONG NTAPI READ_REGISTER_ULONG(IN PULONG Register)
#define USB_PORT_STATUS_SUSPEND
Definition: usb200.h:153
NTSTATUS NTAPI CreateDMAMemoryManager(PDMAMEMORYMANAGER *OutMemoryManager)
#define USB_PORT_STATUS_HIGH_SPEED
Definition: usb200.h:158
struct _DMA_OPERATIONS * DmaOperations
Definition: iotypes.h:2187
NTSTATUS StopController()
Definition: hardware.cpp:832
#define DEVICE_DESCRIPTION_VERSION
Definition: iotypes.h:2020
USHORT HCIVersion
Definition: hardware.h:290
#define QH_TYPE_QH
Definition: hardware.h:193
#define IsEqualGUIDAligned(guid1, guid2)
Definition: wdm.template.h:233
uint32_t ULONG_PTR
Definition: typedefs.h:63
struct _CM_PARTIAL_RESOURCE_DESCRIPTOR::@371::@376 Memory
#define IMP_IUSBEHCIHARDWARE
Definition: interfaces.h:28
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define EHCI_STS_PCD
Definition: hardware.h:53
CM_PARTIAL_RESOURCE_LIST PartialResourceList
Definition: hwresource.cpp:160
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define EHCI_HCCPARAMS
Definition: hardware.h:9
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
EHCI_HCS_CONTENT HCSParams
Definition: hardware.h:293
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
long LONG
Definition: pedump.c:60
NTSTATUS NTAPI IoConnectInterrupt(OUT PKINTERRUPT *InterruptObject, IN PKSERVICE_ROUTINE ServiceRoutine, IN PVOID ServiceContext, IN PKSPIN_LOCK SpinLock, IN ULONG Vector, IN KIRQL Irql, IN KIRQL SynchronizeIrql, IN KINTERRUPT_MODE InterruptMode, IN BOOLEAN ShareVector, IN KAFFINITY ProcessorEnableMask, IN BOOLEAN FloatingSave)
Definition: irq.c:22
#define USB_PORT_STATUS_POWER
Definition: usb200.h:156
#define EHCI_LEGSUP_CAPID_MASK
Definition: hardware.h:18
NTSTATUS NTAPI KeDelayExecutionThread(IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Interval OPTIONAL)
Definition: wait.c:283
#define STDMETHODIMP
Definition: basetyps.h:43
CUSBHardwareDevice(IUnknown *OuterUnknown)
Definition: hardware.cpp:73
FORCEINLINE VOID KeInitializeSpinLock(_Out_ PKSPIN_LOCK SpinLock)
Definition: kefuncs.h:251
#define IMP_IUSBHARDWAREDEVICE
#define USB_PORT_STATUS_RESET
Definition: usb200.h:155
#define QH_ENDPOINT_HIGHSPEED
Definition: hardware.h:163
unsigned char BOOLEAN
#define EHCI_STS_FLR
Definition: hardware.h:54
HD_INIT_CALLBACK * m_SCECallBack
Definition: hardware.cpp:96
smooth NULL
Definition: ftsmooth.c:416
union _CM_PARTIAL_RESOURCE_DESCRIPTOR::@371 u
enum _KINTERRUPT_MODE KINTERRUPT_MODE
VOID __stdcall HD_INIT_CALLBACK(IN PVOID CallBackContext)
Definition: hardware.cpp:16
static PDRIVER_OBJECT DriverObject
Definition: template.c:42
#define EHCI_STS_INT
Definition: hardware.h:51
#define EHCI_ASYNCLISTBASE
Definition: hardware.h:33
void DPRINT(...)
Definition: polytest.cpp:61
const char * LPCSTR
Definition: xmlstorage.h:183
void * PVOID
Definition: retypes.h:9
NTSTATUS ResetController()
Definition: hardware.cpp:866
PDEVICE_OBJECT m_FunctionalDeviceObject
Definition: hardware.cpp:80
#define EHCI_ERROR_INT
Definition: hardware.h:62
IMP_IUSBHARDWAREDEVICE IMP_IUSBEHCIHARDWARE BOOLEAN InterruptService()
#define UlongToPtr(u)
Definition: config.h:106
NTSTATUS NTAPI CreateUSBQueue(PUSBQUEUE *OutUsbQueue)
Definition: usb_queue.cpp:1204
friend VOID NTAPI StatusChangeWorkItemRoutine(PVOID Context)
Definition: hardware.cpp:1447
#define PtrToUlong(u)
Definition: config.h:107
BOOLEAN Dma32BitAddresses
Definition: iotypes.h:2030
PDMAMEMORYMANAGER m_MemoryManager
Definition: hardware.cpp:95
#define EHCI_PRT_CONNECTSTATUSCHANGE
Definition: hardware.h:68
#define STATUS_DEVICE_NOT_CONNECTED
Definition: udferr_usr.h:160
PDMA_ADAPTER m_Adapter
Definition: hardware.cpp:88
#define EHCI_STS_ASS
Definition: hardware.h:61
#define PORT_ENABLE
Definition: usbhub.h:16
_In_opt_ PVOID _In_opt_ PVOID SystemArgument1
Definition: ketypes.h:675
_In_ UINT _In_ UINT NumberOfPorts
Definition: ndis.h:5443
_Must_inspect_result_ _In_ PDEVICE_DESCRIPTION DeviceDescription
Definition: iofuncs.h:1015
IN PVOID IN PVOID IN USHORT IN USHORT IN PINTERFACE Interface
Definition: pci.h:359
virtual ~CUSBHardwareDevice()
Definition: hardware.cpp:74
_In_ LARGE_INTEGER _In_opt_ PKDPC Dpc
Definition: kefuncs.h:524
#define ExInitializeWorkItem(Item, Routine, Context)
Definition: exfuncs.h:265
#define EHCI_USBINTR_PC
Definition: hardware.h:42
friend BOOLEAN NTAPI InterruptServiceRoutine(IN PKINTERRUPT Interrupt, IN PVOID ServiceContext)
Definition: hardware.cpp:1242
UCHAR PortRoute[15]
Definition: hardware.h:301
BOOLEAN m_PortResetInProgress[0xF]
Definition: hardware.cpp:103
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
BUS_INTERFACE_STANDARD m_BusInterface
Definition: hardware.cpp:102
#define EHCI_PRT_RESET
Definition: hardware.h:75
VOID NTAPI EhciDeferredRoutine(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
Definition: hardware.cpp:1290
VOID EHCI_WRITE_REGISTER_ULONG(ULONG Offset, ULONG Value)
Definition: hardware.cpp:243
BOOLEAN ScatterGather
Definition: iotypes.h:2027
const GUID IID_IUnknown
#define EHCI_LEGSUP_CAPID
Definition: hardware.h:19
ULONG HCSParamsLong
Definition: hardware.h:294
#define EHCI_PRT_SUSPEND
Definition: hardware.h:74
static const UCHAR Index[8]
Definition: usbohci.c:18
#define STDMETHODCALLTYPE
Definition: bdasup.h:9
#define EHCI_USBINTR_ASYNC
Definition: hardware.h:45
PKINTERRUPT m_Interrupt
Definition: hardware.cpp:83
ULONG m_SyncFramePhysAddr
Definition: hardware.cpp:101
#define __stdcall
Definition: typedefs.h:25
#define EHCI_STS_HALT
Definition: hardware.h:58
#define USB_PORT_STATUS_CONNECT
Definition: usb200.h:151
#define EHCI_IS_LOW_SPEED(x)
Definition: hardware.h:83
_In_ PKSERVICE_ROUTINE _In_opt_ PVOID ServiceContext
Definition: iofuncs.h:798
ULONG AddRef()
DMA_WIDTH DmaWidth
Definition: iotypes.h:2037
PGET_SET_DEVICE_DATA GetBusData
Definition: iotypes.h:884
#define PCI_WHICHSPACE_CONFIG
Definition: iotypes.h:3288
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define PORT_POWER
Definition: usbhub.h:20
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS PhysicalAddress
Definition: iotypes.h:1061
unsigned char UCHAR
Definition: xmlstorage.h:181
CM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptors[1]
Definition: hwresource.cpp:119
#define EHCI_USBINTR_INTE
Definition: hardware.h:40
#define InterlockedDecrement
Definition: armddk.h:52
Definition: ketypes.h:687
Definition: arc.h:85
_In_z_ PCCHAR _In_ PDEVICE_OBJECT LowerDeviceObject
Definition: classpnp.h:789
PDEVICE_OBJECT m_NextDeviceObject
Definition: hardware.cpp:81
ULONG PhysicalAddr
Definition: hardware.h:219
ULONG LowPart
Definition: typedefs.h:104
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define EHCI_LEGSUP_BIOSOWNED
Definition: hardware.h:21
PQUEUE_HEAD AsyncQueueHead
Definition: hardware.cpp:93
#define TERMINATE_POINTER
Definition: hardware.h:87
_Outptr_ PUSB_DEVICE_HANDLE _In_ PUSB_DEVICE_HANDLE _In_ USHORT PortStatus
Definition: hubbusif.h:40
ULONG EHCI_READ_REGISTER_ULONG(ULONG Offset)
Definition: hardware.cpp:237
PGET_SET_DEVICE_DATA SetBusData
Definition: iotypes.h:883
NTKERNELAPI UCHAR NTAPI READ_REGISTER_UCHAR(IN PUCHAR Register)
#define EHCI_USBCMD
Definition: hardware.h:27
#define TAG_USBEHCI
Definition: usbehci.h:12
Status
Definition: gdiplustypes.h:24
_In_opt_ PVOID _In_opt_ PVOID _In_opt_ PVOID SystemArgument2
Definition: ketypes.h:675
#define EHCI_ECP_SHIFT
Definition: hardware.h:16
#define EHCI_PRT_POWER
Definition: hardware.h:78
#define MAXULONG
Definition: typedefs.h:250
#define EHCI_ECP_MASK
Definition: hardware.h:17
static ULONG Timeout
Definition: ping.c:61
#define InterlockedIncrement
Definition: armddk.h:53
#define EHCI_CONFIGFLAG
Definition: hardware.h:34
IUSBQueue * PUSBQUEUE
PHYSICAL_ADDRESS PhysicalAddress
Definition: hardware.cpp:86
ULONG PortIndicator
Definition: hardware.h:268
EHCI_HCC_CONTENT HCCParams
Definition: hardware.h:298
unsigned short USHORT
Definition: pedump.c:61
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
ULONG KSPIN_LOCK
Definition: env_spec_w32.h:72
BOOL Initialize(HINSTANCE hInstance)
Definition: msconfig.c:341
_Inout_opt_ PDEVICE_OBJECT _Inout_opt_ PDEVICE_OBJECT * FunctionalDeviceObject
Definition: ndis.h:4640
STDMETHODIMP_(ULONG) AddRef()
Definition: hardware.cpp:41
unsigned int * PULONG
Definition: retypes.h:1
NTSTATUS StartController()
Definition: hardware.cpp:550
IDMAMemoryManager * PDMAMEMORYMANAGER
static ULONG WINAPI AddRef(IStream *iface)
Definition: clist.c:90
#define CmResourceTypeInterrupt
Definition: hwresource.cpp:124
END_POINT_CAPABILITIES EndPointCapabilities
Definition: hardware.h:202
friend VOID NTAPI EhciDeferredRoutine(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
Definition: hardware.cpp:1290
#define DPRINT1
Definition: precomp.h:8
EHCI_CAPS m_Capabilities
Definition: hardware.cpp:90
#define EHCI_HCIVERSION
Definition: hardware.h:7
union _QUEUE_HEAD::@1286 Token
#define EHCI_USBINTR_HSERR
Definition: hardware.h:44
LIST_ENTRY LinkedQueueHeads
Definition: hardware.h:220
#define OUT
Definition: typedefs.h:39
INTERFACE_TYPE InterfaceType
Definition: iotypes.h:2036
#define CM_RESOURCE_INTERRUPT_LATCHED
Definition: cmtypes.h:144
#define EHCI_PRT_CONNECTED
Definition: hardware.h:67
struct tagContext Context
Definition: acpixf.h:1024
#define EHCI_USBSTS
Definition: hardware.h:28
ULONG VarFrameList
Definition: hardware.h:278
STDMETHODIMP QueryInterface(REFIID InterfaceId, PVOID *Interface)
unsigned int ULONG
Definition: retypes.h:1
NTKERNELAPI USHORT NTAPI READ_REGISTER_USHORT(IN PUSHORT Register)
BOOLEAN NTAPI InterruptServiceRoutine(IN PKINTERRUPT Interrupt, IN PVOID ServiceContext)
Definition: hardware.cpp:1242
#define UNIMPLEMENTED
Definition: debug.h:114
#define EHCI_STS_FATAL
Definition: hardware.h:55
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
BOOLEAN m_DoorBellRingInProgress
Definition: hardware.cpp:98
#define EHCI_PERIODICLISTBASE
Definition: hardware.h:32
PDRIVER_OBJECT m_DriverObject
Definition: hardware.cpp:78
#define EHCI_STS_RECL
Definition: hardware.h:59
#define EHCI_HCSP_PORTROUTE
Definition: hardware.h:10
IEHCIQueue * PEHCIQUEUE
Definition: interfaces.h:147
#define CmResourceTypeMemory
Definition: hwresource.cpp:125
VOID NTAPI KeInitializeDpc(IN PKDPC Dpc, IN PKDEFERRED_ROUTINE DeferredRoutine, IN PVOID DeferredContext)
Definition: dpc.c:711
return STATUS_SUCCESS
Definition: btrfs.c:2966
#define EHCI_PORTSC_DATAMASK
Definition: hardware.h:81
ULONG CurrentLinkPointer
Definition: hardware.h:204
#define EHCI_USBINTR
Definition: hardware.h:29
PDEVICE_OBJECT m_PhysicalDeviceObject
Definition: hardware.cpp:79
#define EHCI_CAPLENGTH
Definition: hardware.h:6
unsigned short * PUSHORT
Definition: retypes.h:2
#define EHCI_STS_IAA
Definition: hardware.h:56
VOID NTAPI KeStallExecutionProcessor(IN ULONG MicroSeconds)
Definition: ntoskrnl.c:99
#define EHCI_STS_PSS
Definition: hardware.h:60
_Must_inspect_result_ _In_ PFILE_OBJECT _In_opt_ PLARGE_INTEGER _In_ ULONG _In_ FLT_IO_OPERATION_FLAGS _Out_opt_ PULONG BytesRead
Definition: fltkernel.h:1255
#define EHCI_LEGSUP_OSOWNED
Definition: hardware.h:20
VOID PrintCapabilities()
Definition: hardware.cpp:249
volatile LONG m_StatusChangeWorkItemStatus
Definition: hardware.cpp:100
NTSTATUS SetPortFeature(IN PDEVICE_OBJECT RootHubDeviceObject, IN ULONG PortId, IN ULONG Feature)
Definition: fdo.c:93
#define PCI_COMMON_HDR_LENGTH
Definition: iotypes.h:3238
STDMETHODIMP_(ULONG) Release()
Definition: hardware.cpp:46
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
_In_opt_ PVOID DeferredContext
Definition: ketypes.h:675