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/usbohci/hcd_controller.cpp
5 * PURPOSE: USB OHCI device driver.
7 * Michael Martin (michael.martin@reactos.org)
8 * Johannes Anderwald (johannes.anderwald@reactos.org)
15 typedef VOID __stdcall
HD_INIT_CALLBACK(IN PVOID CallBackContext
);
19 InterruptServiceRoutine(
20 IN PKINTERRUPT Interrupt
,
21 IN PVOID ServiceContext
);
27 IN PVOID DeferredContext
,
28 IN PVOID SystemArgument1
,
29 IN PVOID SystemArgument2
);
33 StatusChangeWorkItemRoutine(PVOID Context
);
35 class CUSBHardwareDevice
: public IUSBHardwareDevice
38 STDMETHODIMP
QueryInterface( REFIID InterfaceId
, PVOID
* Interface
);
40 STDMETHODIMP_(ULONG
) AddRef()
42 InterlockedIncrement(&m_Ref
);
45 STDMETHODIMP_(ULONG
) Release()
47 InterlockedDecrement(&m_Ref
);
57 NTSTATUS
Initialize(PDRIVER_OBJECT DriverObject
, PDEVICE_OBJECT FunctionalDeviceObject
, PDEVICE_OBJECT PhysicalDeviceObject
, PDEVICE_OBJECT LowerDeviceObject
);
58 NTSTATUS
PnpStart(PCM_RESOURCE_LIST RawResources
, PCM_RESOURCE_LIST TranslatedResources
);
59 NTSTATUS
PnpStop(void);
60 NTSTATUS
HandlePower(PIRP Irp
);
61 NTSTATUS
GetDeviceDetails(PUSHORT VendorId
, PUSHORT DeviceId
, PULONG NumberOfPorts
, PULONG Speed
);
62 NTSTATUS
GetDMA(OUT
struct IDMAMemoryManager
**m_DmaManager
);
63 NTSTATUS
GetUSBQueue(OUT
struct IUSBQueue
**OutUsbQueue
);
65 NTSTATUS
StartController();
66 NTSTATUS
StopController();
67 NTSTATUS
ResetController();
68 NTSTATUS
ResetPort(ULONG PortIndex
);
70 NTSTATUS
GetPortStatus(ULONG PortId
, OUT USHORT
*PortStatus
, OUT USHORT
*PortChange
);
71 NTSTATUS
ClearPortStatus(ULONG PortId
, ULONG Status
);
72 NTSTATUS
SetPortFeature(ULONG PortId
, ULONG Feature
);
74 VOID
SetStatusChangeEndpointCallBack(PVOID CallBack
, PVOID Context
);
76 KIRQL
AcquireDeviceLock(void);
77 VOID
ReleaseDeviceLock(KIRQL OldLevel
);
79 BOOLEAN
InterruptService();
80 NTSTATUS
InitializeController();
81 NTSTATUS
AllocateEndpointDescriptor(OUT POHCI_ENDPOINT_DESCRIPTOR
*OutDescriptor
);
84 friend BOOLEAN NTAPI
InterruptServiceRoutine(IN PKINTERRUPT Interrupt
, IN PVOID ServiceContext
);
85 friend VOID NTAPI
EhciDefferedRoutine(IN PKDPC Dpc
, IN PVOID DeferredContext
, IN PVOID SystemArgument1
, IN PVOID SystemArgument2
);
86 friend VOID NTAPI
StatusChangeWorkItemRoutine(PVOID Context
);
87 // constructor / destructor
88 CUSBHardwareDevice(IUnknown
*OuterUnknown
){}
89 virtual ~CUSBHardwareDevice(){}
92 LONG m_Ref
; // reference count
93 PDRIVER_OBJECT m_DriverObject
; // driver object
94 PDEVICE_OBJECT m_PhysicalDeviceObject
; // pdo
95 PDEVICE_OBJECT m_FunctionalDeviceObject
; // fdo (hcd controller)
96 PDEVICE_OBJECT m_NextDeviceObject
; // lower device object
97 KSPIN_LOCK m_Lock
; // hardware lock
98 PKINTERRUPT m_Interrupt
; // interrupt object
99 KDPC m_IntDpcObject
; // dpc object for deferred isr processing
100 PVOID VirtualBase
; // virtual base for memory manager
101 PHYSICAL_ADDRESS PhysicalAddress
; // physical base for memory manager
102 PULONG m_Base
; // OHCI operational port base registers
103 PDMA_ADAPTER m_Adapter
; // dma adapter object
104 ULONG m_MapRegisters
; // map registers count
105 USHORT m_VendorID
; // vendor id
106 USHORT m_DeviceID
; // device id
107 PUSBQUEUE m_UsbQueue
; // usb request queue
108 POHCIHCCA m_HCCA
; // hcca virtual base
109 PHYSICAL_ADDRESS m_HCCAPhysicalAddress
; // hcca physical address
110 POHCI_ENDPOINT_DESCRIPTOR m_ControlEndpointDescriptor
; // dummy control endpoint descriptor
111 POHCI_ENDPOINT_DESCRIPTOR m_BulkEndpointDescriptor
; // dummy control endpoint descriptor
112 POHCI_ENDPOINT_DESCRIPTOR m_IsoEndpointDescriptor
; // iso endpoint descriptor
113 POHCI_ENDPOINT_DESCRIPTOR m_InterruptEndpoints
[OHCI_STATIC_ENDPOINT_COUNT
]; // endpoints for interrupt / iso transfers
114 ULONG m_NumberOfPorts
; // number of ports
115 PDMAMEMORYMANAGER m_MemoryManager
; // memory manager
116 HD_INIT_CALLBACK
* m_SCECallBack
; // status change callback routine
117 PVOID m_SCEContext
; // status change callback routine context
118 BOOLEAN m_DoorBellRingInProgress
; // door bell ring in progress
119 WORK_QUEUE_ITEM m_StatusChangeWorkItem
; // work item for status change callback
120 ULONG m_SyncFramePhysAddr
; // periodic frame list physical address
123 //=================================================================================================
128 CUSBHardwareDevice::QueryInterface(
132 if (IsEqualGUIDAligned(refiid
, IID_IUnknown
))
134 *Output
= PVOID(PUNKNOWN(this));
135 PUNKNOWN(*Output
)->AddRef();
136 return STATUS_SUCCESS
;
139 return STATUS_UNSUCCESSFUL
;
143 CUSBHardwareDevice::Initialize(
144 PDRIVER_OBJECT DriverObject
,
145 PDEVICE_OBJECT FunctionalDeviceObject
,
146 PDEVICE_OBJECT PhysicalDeviceObject
,
147 PDEVICE_OBJECT LowerDeviceObject
)
149 BUS_INTERFACE_STANDARD BusInterface
;
150 PCI_COMMON_CONFIG PciConfig
;
154 DPRINT1("CUSBHardwareDevice::Initialize\n");
157 // Create DMAMemoryManager for use with QueueHeads and Transfer Descriptors.
159 Status
= CreateDMAMemoryManager(&m_MemoryManager
);
160 if (!NT_SUCCESS(Status
))
162 DPRINT1("Failed to create DMAMemoryManager Object\n");
167 // Create the UsbQueue class that will handle the Asynchronous and Periodic Schedules
169 Status
= CreateUSBQueue(&m_UsbQueue
);
170 if (!NT_SUCCESS(Status
))
172 DPRINT1("Failed to create UsbQueue!\n");
177 // store device objects
179 m_DriverObject
= DriverObject
;
180 m_FunctionalDeviceObject
= FunctionalDeviceObject
;
181 m_PhysicalDeviceObject
= PhysicalDeviceObject
;
182 m_NextDeviceObject
= LowerDeviceObject
;
185 // initialize device lock
187 KeInitializeSpinLock(&m_Lock
);
190 // intialize status change work item
192 ExInitializeWorkItem(&m_StatusChangeWorkItem
, StatusChangeWorkItemRoutine
, PVOID(this));
197 Status
= GetBusInterface(PhysicalDeviceObject
, &BusInterface
);
198 if (!NT_SUCCESS(Status
))
200 DPRINT1("Failed to get BusInteface!\n");
204 BytesRead
= (*BusInterface
.GetBusData
)(BusInterface
.Context
,
205 PCI_WHICHSPACE_CONFIG
,
208 PCI_COMMON_HDR_LENGTH
);
210 if (BytesRead
!= PCI_COMMON_HDR_LENGTH
)
212 DPRINT1("Failed to get pci config information!\n");
213 return STATUS_SUCCESS
;
216 if (!(PciConfig
.Command
& PCI_ENABLE_BUS_MASTER
))
218 DPRINT1("PCI Configuration shows this as a non Bus Mastering device!\n");
221 m_VendorID
= PciConfig
.VendorID
;
222 m_DeviceID
= PciConfig
.DeviceID
;
224 return STATUS_SUCCESS
;
228 CUSBHardwareDevice::PnpStart(
229 PCM_RESOURCE_LIST RawResources
,
230 PCM_RESOURCE_LIST TranslatedResources
)
233 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor
;
234 DEVICE_DESCRIPTION DeviceDescription
;
239 DPRINT1("CUSBHardwareDevice::PnpStart\n");
240 for(Index
= 0; Index
< TranslatedResources
->List
[0].PartialResourceList
.Count
; Index
++)
243 // get resource descriptor
245 ResourceDescriptor
= &TranslatedResources
->List
[0].PartialResourceList
.PartialDescriptors
[Index
];
247 switch(ResourceDescriptor
->Type
)
249 case CmResourceTypeInterrupt
:
251 KeInitializeDpc(&m_IntDpcObject
,
255 Status
= IoConnectInterrupt(&m_Interrupt
,
256 InterruptServiceRoutine
,
259 ResourceDescriptor
->u
.Interrupt
.Vector
,
260 (KIRQL
)ResourceDescriptor
->u
.Interrupt
.Level
,
261 (KIRQL
)ResourceDescriptor
->u
.Interrupt
.Level
,
262 (KINTERRUPT_MODE
)(ResourceDescriptor
->Flags
& CM_RESOURCE_INTERRUPT_LATCHED
),
263 (ResourceDescriptor
->ShareDisposition
!= CmResourceShareDeviceExclusive
),
264 ResourceDescriptor
->u
.Interrupt
.Affinity
,
267 if (!NT_SUCCESS(Status
))
270 // failed to register interrupt
272 DPRINT1("IoConnect Interrupt failed with %x\n", Status
);
277 case CmResourceTypeMemory
:
282 ResourceBase
= MmMapIoSpace(ResourceDescriptor
->u
.Memory
.Start
, ResourceDescriptor
->u
.Memory
.Length
, MmNonCached
);
286 // failed to map registers
288 DPRINT1("MmMapIoSpace failed\n");
289 return STATUS_INSUFFICIENT_RESOURCES
;
293 // Get controllers capabilities
295 Version
= READ_REGISTER_ULONG((PULONG
)((ULONG_PTR
)ResourceBase
+ OHCI_REVISION_OFFSET
));
297 DPRINT1("Version %x\n", Version
);
300 // Store Resource base
302 m_Base
= (PULONG
)ResourceBase
;
310 // zero device description
312 RtlZeroMemory(&DeviceDescription
, sizeof(DEVICE_DESCRIPTION
));
315 // initialize device description
317 DeviceDescription
.Version
= DEVICE_DESCRIPTION_VERSION
;
318 DeviceDescription
.Master
= TRUE
;
319 DeviceDescription
.ScatterGather
= TRUE
;
320 DeviceDescription
.Dma32BitAddresses
= TRUE
;
321 DeviceDescription
.DmaWidth
= Width32Bits
;
322 DeviceDescription
.InterfaceType
= PCIBus
;
323 DeviceDescription
.MaximumLength
= MAXULONG
;
328 m_Adapter
= IoGetDmaAdapter(m_PhysicalDeviceObject
, &DeviceDescription
, &m_MapRegisters
);
332 // failed to get dma adapter
334 DPRINT1("Failed to acquire dma adapter\n");
335 return STATUS_INSUFFICIENT_RESOURCES
;
339 // Create Common Buffer
341 VirtualBase
= m_Adapter
->DmaOperations
->AllocateCommonBuffer(m_Adapter
,
347 DPRINT1("Failed to allocate a common buffer\n");
348 return STATUS_INSUFFICIENT_RESOURCES
;
352 // Initialize the DMAMemoryManager
354 Status
= m_MemoryManager
->Initialize(this, &m_Lock
, PAGE_SIZE
* 4, VirtualBase
, PhysicalAddress
, 32);
355 if (!NT_SUCCESS(Status
))
357 DPRINT1("Failed to initialize the DMAMemoryManager\n");
362 // Initialize the UsbQueue now that we have an AdapterObject.
364 Status
= m_UsbQueue
->Initialize(PUSBHARDWAREDEVICE(this), m_Adapter
, m_MemoryManager
, NULL
);
365 if (!NT_SUCCESS(Status
))
367 DPRINT1("Failed to Initialize the UsbQueue\n");
372 // initializes the controller
374 Status
= InitializeController();
375 if (!NT_SUCCESS(Status
))
377 DPRINT1("Failed to Initialize the controller \n");
384 // Stop the controller before modifying schedules
386 Status
= StopController();
387 if (!NT_SUCCESS(Status
))
389 DPRINT1("Failed to stop the controller \n");
396 // Start the controller
398 DPRINT1("Starting Controller\n");
399 Status
= StartController();
408 CUSBHardwareDevice::PnpStop(void)
411 return STATUS_NOT_IMPLEMENTED
;
415 CUSBHardwareDevice::HandlePower(
419 return STATUS_NOT_IMPLEMENTED
;
423 CUSBHardwareDevice::GetDeviceDetails(
424 OUT OPTIONAL PUSHORT VendorId
,
425 OUT OPTIONAL PUSHORT DeviceId
,
426 OUT OPTIONAL PULONG NumberOfPorts
,
427 OUT OPTIONAL PULONG Speed
)
434 *VendorId
= m_VendorID
;
442 *DeviceId
= m_DeviceID
;
448 // get number of ports
450 *NumberOfPorts
= m_NumberOfPorts
;
461 return STATUS_SUCCESS
;
464 NTSTATUS
CUSBHardwareDevice::GetDMA(
465 OUT
struct IDMAMemoryManager
**OutDMAMemoryManager
)
467 if (!m_MemoryManager
)
468 return STATUS_UNSUCCESSFUL
;
469 *OutDMAMemoryManager
= m_MemoryManager
;
470 return STATUS_SUCCESS
;
474 CUSBHardwareDevice::GetUSBQueue(
475 OUT
struct IUSBQueue
**OutUsbQueue
)
478 return STATUS_UNSUCCESSFUL
;
479 *OutUsbQueue
= m_UsbQueue
;
480 return STATUS_SUCCESS
;
485 CUSBHardwareDevice::StartController(void)
487 ULONG Control
, NumberOfPorts
, Index
, Descriptor
;
490 // first write address of HCCA
492 WRITE_REGISTER_ULONG((PULONG
)((PUCHAR
)m_Base
+ OHCI_HCCA_OFFSET
), m_HCCAPhysicalAddress
.LowPart
);
495 // lets write physical address of dummy control endpoint descriptor
497 WRITE_REGISTER_ULONG((PULONG
)((PUCHAR
)m_Base
+ OHCI_CONTROL_HEAD_ED_OFFSET
), m_ControlEndpointDescriptor
->PhysicalAddress
.LowPart
);
500 // lets write physical address of dummy bulk endpoint descriptor
502 WRITE_REGISTER_ULONG((PULONG
)((PUCHAR
)m_Base
+ OHCI_BULK_HEAD_ED_OFFSET
), m_BulkEndpointDescriptor
->PhysicalAddress
.LowPart
);
505 // read control register
507 Control
= READ_REGISTER_ULONG((PULONG
)((PUCHAR
)m_Base
+ OHCI_CONTROL_OFFSET
));
512 Control
&= ~(OHCI_CONTROL_BULK_SERVICE_RATIO_MASK
| OHCI_ENABLE_LIST
| OHCI_HC_FUNCTIONAL_STATE_MASK
| OHCI_INTERRUPT_ROUTING
);
515 // set command status flags
517 Control
|= OHCI_ENABLE_LIST
| OHCI_CONTROL_BULK_RATIO_1_4
| OHCI_HC_FUNCTIONAL_STATE_OPERATIONAL
;
520 // now start the controller
522 WRITE_REGISTER_ULONG((PULONG
)((PUCHAR
)m_Base
+ OHCI_CONTROL_OFFSET
), Control
);
525 // retrieve number of ports
527 for(Index
= 0; Index
< 10; Index
++)
532 KeStallExecutionProcessor(10);
537 Descriptor
= READ_REGISTER_ULONG((PULONG
)((PUCHAR
)m_Base
+ OHCI_RH_DESCRIPTOR_A_OFFSET
));
540 // get number of ports
542 NumberOfPorts
= OHCI_RH_GET_PORT_COUNT(Descriptor
);
545 // check if we have received the ports
554 ASSERT(NumberOfPorts
< OHCI_MAX_PORT_COUNT
);
557 // store number of ports
559 m_NumberOfPorts
= NumberOfPorts
;
562 // print out number ports
564 DPRINT1("NumberOfPorts %lu\n", m_NumberOfPorts
);
569 return STATUS_SUCCESS
;
573 CUSBHardwareDevice::AllocateEndpointDescriptor(
574 OUT POHCI_ENDPOINT_DESCRIPTOR
*OutDescriptor
)
576 POHCI_ENDPOINT_DESCRIPTOR Descriptor
;
577 PHYSICAL_ADDRESS DescriptorAddress
;
581 // allocate descriptor
583 Status
= m_MemoryManager
->Allocate(sizeof(OHCI_ENDPOINT_DESCRIPTOR
), (PVOID
*)&Descriptor
, &DescriptorAddress
);
584 if (!NT_SUCCESS(Status
))
587 // failed to allocate descriptor
593 // intialize descriptor
595 Descriptor
->Flags
= OHCI_ENDPOINT_SKIP
;
596 Descriptor
->HeadPhysicalDescriptor
= 0;
597 Descriptor
->NextPhysicalEndpoint
= 0;
598 Descriptor
->TailPhysicalDescriptor
= 0;
599 Descriptor
->PhysicalAddress
.QuadPart
= DescriptorAddress
.QuadPart
;
604 *OutDescriptor
= Descriptor
;
609 return STATUS_SUCCESS
;
613 CUSBHardwareDevice::InitializeController()
616 ULONG Index
, Interval
, IntervalIndex
, InsertIndex
;
617 POHCI_ENDPOINT_DESCRIPTOR Descriptor
;
620 // first allocate the hcca area
622 Status
= m_MemoryManager
->Allocate(sizeof(OHCIHCCA
), (PVOID
*)&m_HCCA
, &m_HCCAPhysicalAddress
);
623 if (!NT_SUCCESS(Status
))
632 // now allocate an endpoint for control transfers
633 // this endpoint will never be removed
635 Status
= AllocateEndpointDescriptor(&m_ControlEndpointDescriptor
);
636 if (!NT_SUCCESS(Status
))
645 // now allocate an endpoint for bulk transfers
646 // this endpoint will never be removed
648 Status
= AllocateEndpointDescriptor(&m_BulkEndpointDescriptor
);
649 if (!NT_SUCCESS(Status
))
658 // now allocate an endpoint for iso transfers
659 // this endpoint will never be removed
661 Status
= AllocateEndpointDescriptor(&m_IsoEndpointDescriptor
);
662 if (!NT_SUCCESS(Status
))
671 // now allocate endpoint descriptors for iso / interrupt transfers interval is 1,2,4,8,16,32
673 for(Index
= 0; Index
< OHCI_STATIC_ENDPOINT_COUNT
; Index
++)
676 // allocate endpoint descriptor
678 Status
= AllocateEndpointDescriptor(&Descriptor
);
679 if (!NT_SUCCESS(Status
))
690 m_InterruptEndpoints
[Index
] = Descriptor
;
695 // now link the descriptors, taken from Haiku
697 Interval
= OHCI_BIGGEST_INTERVAL
;
698 IntervalIndex
= OHCI_STATIC_ENDPOINT_COUNT
- 1;
701 InsertIndex
= Interval
/ 2;
702 while (InsertIndex
< OHCI_BIGGEST_INTERVAL
)
705 // assign endpoint address
707 m_HCCA
->InterruptTable
[InsertIndex
] = m_InterruptEndpoints
[IntervalIndex
]->PhysicalAddress
.LowPart
;
708 InsertIndex
+= Interval
;
716 // link all endpoint descriptors to first descriptor in array
718 m_HCCA
->InterruptTable
[0] = m_InterruptEndpoints
[0]->PhysicalAddress
.LowPart
;
719 for (Index
= 1; Index
< OHCI_STATIC_ENDPOINT_COUNT
; Index
++)
724 m_InterruptEndpoints
[Index
]->NextPhysicalEndpoint
= m_InterruptEndpoints
[0]->PhysicalAddress
.LowPart
;
728 // Now link the first endpoint to the isochronous endpoint
730 m_InterruptEndpoints
[0]->NextPhysicalEndpoint
= m_IsoEndpointDescriptor
->PhysicalAddress
.LowPart
;
735 return STATUS_SUCCESS
;
739 CUSBHardwareDevice::StopController(void)
741 ULONG Control
, Reset
;
745 // first turn off all interrupts
747 WRITE_REGISTER_ULONG((PULONG
)((PUCHAR
)m_Base
+ OHCI_INTERRUPT_DISABLE_OFFSET
), OHCI_ALL_INTERRUPTS
);
752 Control
= READ_REGISTER_ULONG((PULONG
)((PUCHAR
)m_Base
+ OHCI_CONTROL_OFFSET
));
755 // FIXME: support routing
757 ASSERT((Control
& OHCI_INTERRUPT_ROUTING
) == 0);
762 KeStallExecutionProcessor(100);
765 // some controllers also depend on this
767 WRITE_REGISTER_ULONG((PULONG
)((PUCHAR
)m_Base
+ OHCI_CONTROL_OFFSET
), OHCI_HC_FUNCTIONAL_STATE_RESET
);
772 KeStallExecutionProcessor(100);
775 // now reset controller
777 WRITE_REGISTER_ULONG((PULONG
)((PUCHAR
)m_Base
+ OHCI_COMMAND_STATUS_OFFSET
), OHCI_HOST_CONTROLLER_RESET
);
780 // reset time is 10ms
782 for(Index
= 0; Index
< 10; Index
++)
787 KeStallExecutionProcessor(10);
790 // read command status
792 Reset
= READ_REGISTER_ULONG((PULONG
)((PUCHAR
)m_Base
+ OHCI_COMMAND_STATUS_OFFSET
));
795 // was reset bit cleared
797 if ((Reset
& OHCI_HOST_CONTROLLER_RESET
) == 0)
800 // controller completed reset
802 return STATUS_SUCCESS
;
807 // failed to reset controller
809 return STATUS_UNSUCCESSFUL
;
813 CUSBHardwareDevice::ResetController(void)
816 return STATUS_NOT_IMPLEMENTED
;
820 CUSBHardwareDevice::ResetPort(
825 return STATUS_SUCCESS
;
829 CUSBHardwareDevice::GetPortStatus(
831 OUT USHORT
*PortStatus
,
832 OUT USHORT
*PortChange
)
837 return STATUS_SUCCESS
;
841 CUSBHardwareDevice::ClearPortStatus(
846 return STATUS_SUCCESS
;
851 CUSBHardwareDevice::SetPortFeature(
855 if (Feature
== PORT_ENABLE
)
860 WRITE_REGISTER_ULONG((PULONG
)((PUCHAR
)m_Base
+ OHCI_RH_PORT_STATUS(PortId
)), OHCI_RH_PORTSTATUS_PES
);
861 return STATUS_SUCCESS
;
863 else if (Feature
== PORT_POWER
)
868 WRITE_REGISTER_ULONG((PULONG
)((PUCHAR
)m_Base
+ OHCI_RH_PORT_STATUS(PortId
)), OHCI_RH_PORTSTATUS_PPS
);
869 return STATUS_SUCCESS
;
871 else if (Feature
== PORT_SUSPEND
)
876 WRITE_REGISTER_ULONG((PULONG
)((PUCHAR
)m_Base
+ OHCI_RH_PORT_STATUS(PortId
)), OHCI_RH_PORTSTATUS_PSS
);
877 return STATUS_SUCCESS
;
879 else if (Feature
== PORT_RESET
)
884 WRITE_REGISTER_ULONG((PULONG
)((PUCHAR
)m_Base
+ OHCI_RH_PORT_STATUS(PortId
)), OHCI_RH_PORTSTATUS_PRS
);
887 // is there a status change callback
889 if (m_SCECallBack
!= NULL
)
894 m_SCECallBack(m_SCEContext
);
897 return STATUS_SUCCESS
;
903 CUSBHardwareDevice::SetStatusChangeEndpointCallBack(
907 m_SCECallBack
= (HD_INIT_CALLBACK
*)CallBack
;
908 m_SCEContext
= Context
;
912 CUSBHardwareDevice::AcquireDeviceLock(void)
919 KeAcquireSpinLock(&m_Lock
, &OldLevel
);
929 CUSBHardwareDevice::ReleaseDeviceLock(
932 KeReleaseSpinLock(&m_Lock
, OldLevel
);
937 InterruptServiceRoutine(
938 IN PKINTERRUPT Interrupt
,
939 IN PVOID ServiceContext
)
948 IN PVOID DeferredContext
,
949 IN PVOID SystemArgument1
,
950 IN PVOID SystemArgument2
)
958 StatusChangeWorkItemRoutine(
962 // cast to hardware object
964 CUSBHardwareDevice
* This
= (CUSBHardwareDevice
*)Context
;
967 // is there a callback
969 if (This
->m_SCECallBack
)
974 This
->m_SCECallBack(This
->m_SCEContext
);
981 PUSBHARDWAREDEVICE
*OutHardware
)
983 PUSBHARDWAREDEVICE This
;
985 This
= new(NonPagedPool
, TAG_USBOHCI
) CUSBHardwareDevice(0);
988 return STATUS_INSUFFICIENT_RESOURCES
;
993 *OutHardware
= (PUSBHARDWAREDEVICE
)This
;
995 return STATUS_SUCCESS
;