Move drivers to the right location
[reactos.git] / reactos / drivers / usb / miniport / usbuhci / uhci.c
1 /*
2 ReactOS specific functions for UHCI module
3 by Aleksey Bragin (aleksey@reactos.com)
4 and Hervé Poussineau (hpoussin@reactos.com)
5 Some parts of code are inspired (or even just copied) from ReactOS Videoport driver
6 */
7 #define NDEBUG
8 #define INITGUID
9 #include "uhci.h"
10
11 /* declare basic init functions and structures */
12 void uhci_hcd_cleanup(void);
13 void STDCALL usb_exit(void);
14
15 extern struct pci_driver uhci_pci_driver;
16
17 static ULONG DeviceNumber = 0; /* FIXME: what is that? */
18
19 static NTSTATUS
20 CreateRootHubPdo(
21 IN PDRIVER_OBJECT DriverObject,
22 IN PDEVICE_OBJECT Fdo,
23 OUT PDEVICE_OBJECT* pPdo)
24 {
25 PDEVICE_OBJECT Pdo;
26 POHCI_DEVICE_EXTENSION DeviceExtension;
27 NTSTATUS Status;
28
29 DPRINT("UHCI: CreateRootHubPdo()\n");
30
31 Status = IoCreateDevice(
32 DriverObject,
33 sizeof(OHCI_DEVICE_EXTENSION),
34 NULL, /* DeviceName */
35 FILE_DEVICE_BUS_EXTENDER,
36 FILE_DEVICE_SECURE_OPEN | FILE_AUTOGENERATED_DEVICE_NAME,
37 FALSE,
38 &Pdo);
39 if (!NT_SUCCESS(Status))
40 {
41 DPRINT("UHCI: IoCreateDevice() call failed with status 0x%08x\n", Status);
42 return Status;
43 }
44
45 Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;
46 Pdo->Flags |= DO_POWER_PAGABLE;
47
48 // zerofill device extension
49 DeviceExtension = (POHCI_DEVICE_EXTENSION)Pdo->DeviceExtension;
50 RtlZeroMemory(DeviceExtension, sizeof(OHCI_DEVICE_EXTENSION));
51
52 DeviceExtension->IsFDO = FALSE;
53 DeviceExtension->FunctionalDeviceObject = Fdo;
54
55 Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
56
57 *pPdo = Pdo;
58 return STATUS_SUCCESS;
59 }
60
61 NTSTATUS STDCALL
62 AddDevice(
63 IN PDRIVER_OBJECT DriverObject,
64 IN PDEVICE_OBJECT pdo)
65 {
66 PDEVICE_OBJECT fdo;
67 NTSTATUS Status;
68 WCHAR DeviceBuffer[20];
69 WCHAR LinkDeviceBuffer[20];
70 UNICODE_STRING DeviceName;
71 UNICODE_STRING LinkDeviceName;
72 POHCI_DRIVER_EXTENSION DriverExtension;
73 POHCI_DEVICE_EXTENSION DeviceExtension;
74
75 DPRINT("UHCI: AddDevice called\n");
76
77 // Allocate driver extension now
78 DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
79 if (DriverExtension == NULL)
80 {
81 Status = IoAllocateDriverObjectExtension(
82 DriverObject,
83 DriverObject,
84 sizeof(OHCI_DRIVER_EXTENSION),
85 (PVOID *)&DriverExtension);
86
87 if (!NT_SUCCESS(Status))
88 {
89 DPRINT("UHCI: Allocating DriverObjectExtension failed.\n");
90 return Status;
91 }
92 }
93
94 // Create a unicode device name
95 // DeviceNumber = 0; //TODO: Allocate new device number every time
96 swprintf(DeviceBuffer, L"\\Device\\USBFDO-%lu", DeviceNumber);
97 RtlInitUnicodeString(&DeviceName, DeviceBuffer);
98
99 Status = IoCreateDevice(DriverObject,
100 sizeof(OHCI_DEVICE_EXTENSION),
101 &DeviceName,
102 FILE_DEVICE_BUS_EXTENDER,
103 0,
104 FALSE,
105 &fdo);
106
107 if (!NT_SUCCESS(Status))
108 {
109 DPRINT("UHCI: IoCreateDevice call failed with status 0x%08lx\n", Status);
110 return Status;
111 }
112
113 // zerofill device extension
114 DeviceExtension = (POHCI_DEVICE_EXTENSION)fdo->DeviceExtension;
115 RtlZeroMemory(DeviceExtension, sizeof(OHCI_DEVICE_EXTENSION));
116
117 /* Create root hub Pdo */
118 Status = CreateRootHubPdo(DriverObject, fdo, &DeviceExtension->RootHubPdo);
119 if (!NT_SUCCESS(Status))
120 {
121 DPRINT("UHCI: CreateRootHubPdo() failed with status 0x%08lx\n", Status);
122 IoDeleteDevice(fdo);
123 return Status;
124 }
125
126 /* Register device interface for controller */
127 Status = IoRegisterDeviceInterface(
128 pdo,
129 &GUID_DEVINTERFACE_USB_HOST_CONTROLLER,
130 NULL,
131 &DeviceExtension->HcdInterfaceName);
132 if (!NT_SUCCESS(Status))
133 {
134 DPRINT("UHCI: IoRegisterDeviceInterface() failed with status 0x%08lx\n", Status);
135 IoDeleteDevice(DeviceExtension->RootHubPdo);
136 IoDeleteDevice(fdo);
137 return Status;
138 }
139
140 DeviceExtension->NextDeviceObject = IoAttachDeviceToDeviceStack(fdo, pdo);
141
142 fdo->Flags &= ~DO_DEVICE_INITIALIZING;
143
144 // Initialize device extension
145 DeviceExtension->IsFDO = TRUE;
146 DeviceExtension->DeviceNumber = DeviceNumber;
147 DeviceExtension->PhysicalDeviceObject = pdo;
148 DeviceExtension->FunctionalDeviceObject = fdo;
149 DeviceExtension->DriverExtension = DriverExtension;
150
151 /* FIXME: do a loop to find an available number */
152 swprintf(LinkDeviceBuffer, L"\\??\\HCD%lu", 0);
153
154 RtlInitUnicodeString(&LinkDeviceName, LinkDeviceBuffer);
155
156 Status = IoCreateSymbolicLink(&LinkDeviceName, &DeviceName);
157
158 if (!NT_SUCCESS(Status))
159 {
160 DPRINT("UHCI: IoCreateSymbolicLink call failed with status 0x%08x\n", Status);
161 IoDeleteDevice(DeviceExtension->RootHubPdo);
162 IoDeleteDevice(fdo);
163 return Status;
164 }
165
166 return STATUS_SUCCESS;
167 }
168
169 VOID STDCALL
170 DriverUnload(PDRIVER_OBJECT DriverObject)
171 {
172 POHCI_DEVICE_EXTENSION DeviceExtension;
173 PDEVICE_OBJECT DeviceObject;
174 struct pci_dev *dev;
175
176 DeviceObject = DriverObject->DeviceObject;
177 DeviceExtension = (POHCI_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
178
179 dev = DeviceExtension->pdev;
180
181 DPRINT1("UHCI: DriverUnload()\n");
182
183 // Exit usb device
184 usb_exit();
185
186 // Remove device (ohci_pci_driver.remove)
187 uhci_pci_driver.remove(dev);
188
189 ExFreePool(dev->slot_name);
190 ExFreePool(dev);
191
192 // Perform some cleanup
193 uhci_hcd_cleanup();
194 }
195
196 NTSTATUS STDCALL
197 IrpStub(
198 IN PDEVICE_OBJECT DeviceObject,
199 IN PIRP Irp)
200 {
201 NTSTATUS Status = STATUS_NOT_SUPPORTED;
202
203 if (((POHCI_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
204 {
205 DPRINT1("UHCI: FDO stub for major function 0x%lx\n",
206 IoGetCurrentIrpStackLocation(Irp)->MajorFunction);
207 #ifndef NDEBUG
208 DbgBreakPoint();
209 #endif
210 return ForwardIrpAndForget(DeviceObject, Irp);
211 }
212 else
213 {
214 /* We can't forward request to the lower driver, because
215 * we are a Pdo, so we don't have lower driver...
216 */
217 DPRINT1("UHCI: PDO stub for major function 0x%lx\n",
218 IoGetCurrentIrpStackLocation(Irp)->MajorFunction);
219 #ifndef NDEBUG
220 DbgBreakPoint();
221 #endif
222 }
223
224 Status = Irp->IoStatus.Status;
225 IoCompleteRequest(Irp, IO_NO_INCREMENT);
226 return Status;
227 }
228
229 static NTSTATUS STDCALL
230 DispatchCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp)
231 {
232 if (((POHCI_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
233 return UhciCreate(DeviceObject, Irp);
234 else
235 return IrpStub(DeviceObject, Irp);
236 }
237
238 static NTSTATUS STDCALL
239 DispatchClose(PDEVICE_OBJECT DeviceObject, PIRP Irp)
240 {
241 if (((POHCI_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
242 return UhciClose(DeviceObject, Irp);
243 else
244 return IrpStub(DeviceObject, Irp);
245 }
246
247 static NTSTATUS STDCALL
248 DispatchCleanup(PDEVICE_OBJECT DeviceObject, PIRP Irp)
249 {
250 if (((POHCI_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
251 return UhciCleanup(DeviceObject, Irp);
252 else
253 return IrpStub(DeviceObject, Irp);
254 }
255
256 static NTSTATUS STDCALL
257 DispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
258 {
259 if (((POHCI_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
260 return UhciDeviceControlFdo(DeviceObject, Irp);
261 else
262 return UhciDeviceControlPdo(DeviceObject, Irp);
263 }
264
265 static NTSTATUS STDCALL
266 DispatchPnp(PDEVICE_OBJECT DeviceObject, PIRP Irp)
267 {
268 if (((POHCI_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
269 return UhciPnpFdo(DeviceObject, Irp);
270 else
271 return UhciPnpPdo(DeviceObject, Irp);
272 }
273
274 static NTSTATUS STDCALL
275 DispatchPower(PDEVICE_OBJECT fido, PIRP Irp)
276 {
277 DPRINT1("UHCI: IRP_MJ_POWER unimplemented\n");
278 Irp->IoStatus.Information = 0;
279 Irp->IoStatus.Status = STATUS_SUCCESS;
280 IoCompleteRequest(Irp, IO_NO_INCREMENT);
281 return STATUS_SUCCESS;
282 }
283
284 /*
285 * Standard DriverEntry method.
286 */
287 NTSTATUS STDCALL
288 DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegPath)
289 {
290 ULONG i;
291 DPRINT("********* Cromwell UHCI *********\n");
292
293 DriverObject->DriverUnload = DriverUnload;
294 DriverObject->DriverExtension->AddDevice = AddDevice;
295
296 for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
297 DriverObject->MajorFunction[i] = IrpStub;
298
299 DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
300 DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
301 DriverObject->MajorFunction[IRP_MJ_CLEANUP] = DispatchCleanup;
302 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchDeviceControl;
303 DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp;
304 DriverObject->MajorFunction[IRP_MJ_POWER] = DispatchPower;
305
306 return STATUS_SUCCESS;
307 }