[USBEHCI_NEW]
[reactos.git] / drivers / usb / usbehci_new / hardware.cpp
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 #define INITGUID
12 #include "usbehci.h"
13
14 class CUSBHardwareDevice : public IUSBHardwareDevice
15 {
16 public:
17 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
18
19 STDMETHODIMP_(ULONG) AddRef()
20 {
21 InterlockedIncrement(&m_Ref);
22 return m_Ref;
23 }
24 STDMETHODIMP_(ULONG) Release()
25 {
26 InterlockedDecrement(&m_Ref);
27
28 if (!m_Ref)
29 {
30 delete this;
31 return 0;
32 }
33 return m_Ref;
34 }
35 // com
36 NTSTATUS Initialize(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT FunctionalDeviceObject, PDEVICE_OBJECT PhysicalDeviceObject, PDEVICE_OBJECT LowerDeviceObject);
37 NTSTATUS PnpStart(PCM_RESOURCE_LIST RawResources, PCM_RESOURCE_LIST TranslatedResources);
38 NTSTATUS PnpStop(void);
39 NTSTATUS HandlePower(PIRP Irp);
40 NTSTATUS GetDeviceDetails(PULONG VendorId, PULONG DeviceId, PULONG NumberOfPorts, PULONG Speed);
41 NTSTATUS GetDmaMemoryManager(OUT struct IDMAMemoryManager **OutMemoryManager);
42 NTSTATUS GetUSBQueue(OUT struct IUSBQueue **OutUsbQueue);
43 NTSTATUS ResetController();
44 NTSTATUS ResetPort(ULONG PortIndex);
45 KIRQL AcquireDeviceLock(void);
46 VOID ReleaseDeviceLock(KIRQL OldLevel);
47 // local
48 BOOLEAN InterruptService();
49
50 // friend function
51 friend BOOLEAN NTAPI InterruptServiceRoutine(IN PKINTERRUPT Interrupt, IN PVOID ServiceContext);
52
53 // constructor / destructor
54 CUSBHardwareDevice(IUnknown *OuterUnknown){}
55 virtual ~CUSBHardwareDevice(){}
56
57 protected:
58 LONG m_Ref;
59 PDRIVER_OBJECT m_DriverObject;
60 PDEVICE_OBJECT m_PhysicalDeviceObject;
61 PDEVICE_OBJECT m_FunctionalDeviceObject;
62 PDEVICE_OBJECT m_NextDeviceObject;
63 KSPIN_LOCK m_Lock;
64 PKINTERRUPT m_Interrupt;
65 PULONG m_Base;
66 PDMA_ADAPTER m_Adapter;
67 ULONG m_MapRegisters;
68 };
69
70 //=================================================================================================
71 // COM
72 //
73 NTSTATUS
74 STDMETHODCALLTYPE
75 CUSBHardwareDevice::QueryInterface(
76 IN REFIID refiid,
77 OUT PVOID* Output)
78 {
79 if (IsEqualGUIDAligned(refiid, IID_IUnknown))
80 {
81 *Output = PVOID(PUNKNOWN(this));
82 PUNKNOWN(*Output)->AddRef();
83 return STATUS_SUCCESS;
84 }
85
86 return STATUS_UNSUCCESSFUL;
87 }
88
89 NTSTATUS
90 CUSBHardwareDevice::Initialize(
91 PDRIVER_OBJECT DriverObject,
92 PDEVICE_OBJECT FunctionalDeviceObject,
93 PDEVICE_OBJECT PhysicalDeviceObject,
94 PDEVICE_OBJECT LowerDeviceObject)
95 {
96
97 DPRINT1("CUSBHardwareDevice::Initialize\n");
98
99 //
100 // store device objects
101 //
102 m_DriverObject = DriverObject;
103 m_FunctionalDeviceObject = FunctionalDeviceObject;
104 m_PhysicalDeviceObject = PhysicalDeviceObject;
105 m_NextDeviceObject = LowerDeviceObject;
106
107 //
108 // initialize device lock
109 //
110 KeInitializeSpinLock(&m_Lock);
111
112 return STATUS_SUCCESS;
113 }
114
115
116 NTSTATUS
117 CUSBHardwareDevice::PnpStart(
118 PCM_RESOURCE_LIST RawResources,
119 PCM_RESOURCE_LIST TranslatedResources)
120 {
121 ULONG Index;
122 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor;
123 DEVICE_DESCRIPTION DeviceDescription;
124 PVOID ResourceBase;
125 NTSTATUS Status;
126
127 DPRINT1("CUSBHardwareDevice::PnpStart\n");
128 for(Index = 0; Index < TranslatedResources->List[0].PartialResourceList.Count; Index++)
129 {
130 //
131 // get resource descriptor
132 //
133 ResourceDescriptor = &TranslatedResources->List[0].PartialResourceList.PartialDescriptors[Index];
134
135 switch(ResourceDescriptor->Type)
136 {
137 case CmResourceTypeInterrupt:
138 {
139 Status = IoConnectInterrupt(&m_Interrupt,
140 InterruptServiceRoutine,
141 (PVOID)this,
142 NULL,
143 ResourceDescriptor->u.Interrupt.Vector,
144 (KIRQL)ResourceDescriptor->u.Interrupt.Level,
145 (KIRQL)ResourceDescriptor->u.Interrupt.Level,
146 (KINTERRUPT_MODE)(ResourceDescriptor->Flags & CM_RESOURCE_INTERRUPT_LATCHED),
147 (ResourceDescriptor->ShareDisposition != CmResourceShareDeviceExclusive),
148 ResourceDescriptor->u.Interrupt.Affinity,
149 FALSE);
150
151 if (!NT_SUCCESS(Status))
152 {
153 //
154 // failed to register interrupt
155 //
156 DPRINT1("IoConnect Interrupt failed with %x\n", Status);
157 return Status;
158 }
159 break;
160 }
161 case CmResourceTypeMemory:
162 {
163 //
164 // get resource base
165 //
166 ResourceBase = MmMapIoSpace(ResourceDescriptor->u.Memory.Start, ResourceDescriptor->u.Memory.Length, MmNonCached);
167 if (!ResourceBase)
168 {
169 //
170 // failed to map registers
171 //
172 DPRINT1("MmMapIoSpace failed\n");
173 return STATUS_INSUFFICIENT_RESOURCES;
174 }
175
176 //
177 //FIXME: query capabilities and update m_Base
178 //
179 break;
180 }
181 }
182 }
183
184
185 //
186 // zero device description
187 //
188 RtlZeroMemory(&DeviceDescription, sizeof(DEVICE_DESCRIPTION));
189
190 //
191 // initialize device description
192 //
193 DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION;
194 DeviceDescription.Master = TRUE;
195 DeviceDescription.ScatterGather = TRUE;
196 DeviceDescription.Dma32BitAddresses = TRUE;
197 DeviceDescription.DmaWidth = Width32Bits;
198 DeviceDescription.InterfaceType = PCIBus;
199 DeviceDescription.MaximumLength = MAXULONG;
200
201 //
202 // get dma adapter
203 //
204 m_Adapter = IoGetDmaAdapter(m_PhysicalDeviceObject, &DeviceDescription, &m_MapRegisters);
205 if (!m_Adapter)
206 {
207 //
208 // failed to get dma adapter
209 //
210 DPRINT1("Failed to acquire dma adapter\n");
211 return STATUS_INSUFFICIENT_RESOURCES;
212 }
213
214 return STATUS_SUCCESS;
215 }
216
217 NTSTATUS
218 CUSBHardwareDevice::PnpStop(void)
219 {
220 UNIMPLEMENTED
221 return STATUS_NOT_IMPLEMENTED;
222 }
223
224 NTSTATUS
225 CUSBHardwareDevice::HandlePower(
226 PIRP Irp)
227 {
228 UNIMPLEMENTED
229 return STATUS_NOT_IMPLEMENTED;
230 }
231
232 NTSTATUS
233 CUSBHardwareDevice::GetDeviceDetails(
234 OUT OPTIONAL PULONG VendorId,
235 OUT OPTIONAL PULONG DeviceId,
236 OUT OPTIONAL PULONG NumberOfPorts,
237 OUT OPTIONAL PULONG Speed)
238 {
239 UNIMPLEMENTED
240 return STATUS_NOT_IMPLEMENTED;
241 }
242
243
244 NTSTATUS
245 CUSBHardwareDevice::GetDmaMemoryManager(
246 OUT struct IDMAMemoryManager **OutMemoryManager)
247 {
248 UNIMPLEMENTED
249 return STATUS_NOT_IMPLEMENTED;
250 }
251
252
253 NTSTATUS
254 CUSBHardwareDevice::GetUSBQueue(
255 OUT struct IUSBQueue **OutUsbQueue)
256 {
257 UNIMPLEMENTED
258 return STATUS_NOT_IMPLEMENTED;
259 }
260
261
262 NTSTATUS
263 CUSBHardwareDevice::ResetController(void)
264 {
265 UNIMPLEMENTED
266 return STATUS_NOT_IMPLEMENTED;
267 }
268
269 NTSTATUS
270 CUSBHardwareDevice::ResetPort(
271 IN ULONG PortIndex)
272 {
273 UNIMPLEMENTED
274 return STATUS_NOT_IMPLEMENTED;
275 }
276
277 KIRQL
278 CUSBHardwareDevice::AcquireDeviceLock(void)
279 {
280 KIRQL OldLevel;
281
282 //
283 // acquire lock
284 //
285 KeAcquireSpinLock(&m_Lock, &OldLevel);
286
287 //
288 // return old irql
289 //
290 return OldLevel;
291 }
292
293
294 VOID
295 CUSBHardwareDevice::ReleaseDeviceLock(
296 KIRQL OldLevel)
297 {
298 KeReleaseSpinLock(&m_Lock, OldLevel);
299 }
300
301 BOOLEAN
302 NTAPI
303 InterruptServiceRoutine(
304 IN PKINTERRUPT Interrupt,
305 IN PVOID ServiceContext)
306 {
307 UNIMPLEMENTED
308 return FALSE;
309 }
310
311 NTSTATUS
312 CreateUSBHardware(
313 PUSBHARDWAREDEVICE *OutHardware)
314 {
315 PUSBHARDWAREDEVICE This;
316
317 This = new(NonPagedPool, 0) CUSBHardwareDevice(0);
318 if (!This)
319 return STATUS_INSUFFICIENT_RESOURCES;
320
321 This->AddRef();
322
323 // return result
324 *OutHardware = (PUSBHARDWAREDEVICE)This;
325
326 return STATUS_SUCCESS;
327 }