d329f5f41894608508750c6f712ad3c3d12ae5dd
[reactos.git] / reactos / drivers / usb / cromwell / uhci / uhci_main.c
1 /*
2 ReactOS specific functions for UHCI module
3 by Aleksey Bragin (aleksey@reactos.com)
4 Some parts of code are inspired (or even just copied) from ReactOS Videoport driver
5 */
6
7 #include <ddk/ntddk.h>
8 #include <debug.h>
9 #include "../linux/linux_wrapper.h"
10 #include "../host/ohci_main.h"
11
12 // declare basic init funcs
13 void init_wrapper(struct pci_dev *probe_dev);
14 int uhci_hcd_init(void);
15 void uhci_hcd_cleanup(void);
16 int STDCALL usb_init(void);
17 void STDCALL usb_exit(void);
18 extern struct pci_driver uhci_pci_driver;
19 extern const struct pci_device_id uhci_pci_ids[];
20
21
22
23 // This should be removed, but for testing purposes it's here
24 struct pci_dev *dev;
25 //struct pci_device_id *dev_id;
26
27
28 #define USB_UHCI_TAG TAG('u','s','b','u')
29
30 NTSTATUS STDCALL AddDevice(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT pdo)
31 {
32 PDEVICE_OBJECT fdo;
33 NTSTATUS Status;
34 WCHAR DeviceBuffer[20];
35 UNICODE_STRING DeviceName;
36 POHCI_DRIVER_EXTENSION DriverExtension;
37 POHCI_DEVICE_EXTENSION DeviceExtension;
38 ULONG Size, DeviceNumber;
39
40 DPRINT1("uhci: AddDevice called\n");
41
42 // Allocate driver extension now
43 DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
44 if (DriverExtension == NULL)
45 {
46 Status = IoAllocateDriverObjectExtension(
47 DriverObject,
48 DriverObject,
49 sizeof(OHCI_DRIVER_EXTENSION),
50 (PVOID *)&DriverExtension);
51
52 if (!NT_SUCCESS(Status))
53 {
54 DPRINT1("Allocating DriverObjectExtension failed.\n");
55 return Status;
56 }
57 }
58
59 // Create a unicode device name
60 DeviceNumber = 0; //TODO: Allocate new device number every time
61 swprintf(DeviceBuffer, L"\\Device\\USBFDO-%lu", DeviceNumber);
62 RtlInitUnicodeString(&DeviceName, DeviceBuffer);
63
64 Status = IoCreateDevice(DriverObject,
65 sizeof(OHCI_DEVICE_EXTENSION)/* + DriverExtension->InitializationData.HwDeviceExtensionSize*/,
66 &DeviceName,
67 FILE_DEVICE_CONTROLLER,
68 0,
69 FALSE,
70 &fdo);
71
72 if (!NT_SUCCESS(Status))
73 {
74 DPRINT("IoCreateDevice call failed with status 0x%08x\n", Status);
75 return Status;
76 }
77
78 // zerofill device extension
79 DeviceExtension = (POHCI_DEVICE_EXTENSION)pdo->DeviceExtension;
80 RtlZeroMemory(DeviceExtension, sizeof(OHCI_DEVICE_EXTENSION));
81 DeviceExtension->NextDeviceObject = IoAttachDeviceToDeviceStack(fdo, pdo);
82
83 fdo->Flags &= ~DO_DEVICE_INITIALIZING;
84
85 // Initialize device extension
86 DeviceExtension->DeviceNumber = DeviceNumber;
87 DeviceExtension->PhysicalDeviceObject = pdo;
88 DeviceExtension->FunctionalDeviceObject = fdo;
89 DeviceExtension->DriverExtension = DriverExtension;
90
91 /* Get bus number from the upper level bus driver. */
92 Size = sizeof(ULONG);
93 Status = IoGetDeviceProperty(
94 pdo,
95 DevicePropertyBusNumber,
96 Size,
97 &DeviceExtension->SystemIoBusNumber,
98 &Size);
99
100 if (!NT_SUCCESS(Status))
101 {
102 DPRINT("Couldn't get an information from bus driver. Panic!!!\n");
103 return Status;
104 }
105
106 DPRINT("Done AddDevice\n");
107 return STATUS_SUCCESS;
108 }
109
110 VOID STDCALL DriverUnload(PDRIVER_OBJECT DriverObject)
111 {
112 DPRINT1("DriverUnload()\n");
113
114 // Exit usb device
115 usb_exit();
116
117 // Remove device (ohci_pci_driver.remove)
118 uhci_pci_driver.remove(dev);
119
120 ExFreePool(dev->slot_name);
121 ExFreePool(dev);
122
123 // Perform some cleanup
124 uhci_hcd_cleanup();
125 }
126
127 NTSTATUS InitLinuxWrapper(PDEVICE_OBJECT DeviceObject)
128 {
129 NTSTATUS Status;
130 POHCI_DEVICE_EXTENSION DeviceExtension = (POHCI_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
131
132 // Fill generic linux structs
133 dev = ExAllocatePoolWithTag(PagedPool, sizeof(struct pci_dev), USB_UHCI_TAG);
134
135 init_wrapper(dev);
136 dev->irq = DeviceExtension->InterruptVector;
137 dev->dev_ext = (PVOID)DeviceExtension;
138 dev->slot_name = ExAllocatePoolWithTag(NonPagedPool, 128, USB_UHCI_TAG); // 128 max len for slot name
139
140 strcpy(dev->dev.name, "UnivHCI PCI-USB Controller");
141 strcpy(dev->slot_name, "UHCD PCI Slot");
142
143 // Init the OHCI HCD. Probe will be called automatically, but will fail because id=NULL
144 Status = uhci_hcd_init();
145 //FIXME: Check status returned value
146
147 // Init core usb
148 usb_init();
149
150 // Probe device with real id now
151 uhci_pci_driver.probe(dev, uhci_pci_ids);
152
153 DPRINT("InitLinuxWrapper() done\n");
154
155 return STATUS_SUCCESS;
156 }
157
158 NTSTATUS STDCALL
159 OHCD_PnPStartDevice(IN PDEVICE_OBJECT DeviceObject,
160 IN PIRP Irp)
161 {
162 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
163 PDRIVER_OBJECT DriverObject;
164 POHCI_DRIVER_EXTENSION DriverExtension;
165 POHCI_DEVICE_EXTENSION DeviceExtension;
166 PCM_RESOURCE_LIST AllocatedResources;
167
168 /*
169 * Get the initialization data we saved in VideoPortInitialize.
170 */
171 DriverObject = DeviceObject->DriverObject;
172 DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
173 DeviceExtension = (POHCI_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
174
175 /*
176 * Store some resources in the DeviceExtension.
177 */
178 AllocatedResources = Stack->Parameters.StartDevice.AllocatedResources;
179 if (AllocatedResources != NULL)
180 {
181 CM_FULL_RESOURCE_DESCRIPTOR *FullList;
182 CM_PARTIAL_RESOURCE_DESCRIPTOR *Descriptor;
183 ULONG ResourceCount;
184 ULONG ResourceListSize;
185
186 /* Save the resource list */
187 ResourceCount = AllocatedResources->List[0].PartialResourceList.Count;
188 ResourceListSize =
189 FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.
190 PartialDescriptors[ResourceCount]);
191 DeviceExtension->AllocatedResources = ExAllocatePool(PagedPool, ResourceListSize);
192 if (DeviceExtension->AllocatedResources == NULL)
193 {
194 return STATUS_INSUFFICIENT_RESOURCES;
195 }
196
197 RtlCopyMemory(DeviceExtension->AllocatedResources,
198 AllocatedResources,
199 ResourceListSize);
200
201 /* Get the interrupt level/vector - needed by HwFindAdapter sometimes */
202 for (FullList = AllocatedResources->List;
203 FullList < AllocatedResources->List + AllocatedResources->Count;
204 FullList++)
205 {
206 /* FIXME: Is this ASSERT ok for resources from the PNP manager? */
207 /*ASSERT(FullList->InterfaceType == PCIBus &&
208 FullList->BusNumber == DeviceExtension->SystemIoBusNumber &&
209 1 == FullList->PartialResourceList.Version &&
210 1 == FullList->PartialResourceList.Revision);*/
211 DPRINT1("AllocRess->Count: %d, PartResList.Count: %d\n",
212 AllocatedResources->Count, FullList->PartialResourceList.Count);
213
214 for (Descriptor = FullList->PartialResourceList.PartialDescriptors;
215 Descriptor < FullList->PartialResourceList.PartialDescriptors + FullList->PartialResourceList.Count;
216 Descriptor++)
217 {
218 if (Descriptor->Type == CmResourceTypeInterrupt)
219 {
220 DeviceExtension->InterruptLevel = Descriptor->u.Interrupt.Level;
221 DeviceExtension->InterruptVector = Descriptor->u.Interrupt.Vector;
222
223 DPRINT1("Interrupt level: 0x%x Interrupt Vector: 0x%x\n",
224 DeviceExtension->InterruptLevel,
225 DeviceExtension->InterruptVector);
226 }
227 else if (Descriptor->Type == CmResourceTypePort)
228 {
229 DeviceExtension->BaseAddress = Descriptor->u.Port.Start;
230 DeviceExtension->BaseAddrLength = Descriptor->u.Port.Length;
231 DeviceExtension->Flags = Descriptor->Flags;
232
233 DPRINT1("I/O resource: start=0x%x, length=0x%x\n",
234 DeviceExtension->BaseAddress.u.LowPart, DeviceExtension->BaseAddrLength);
235 }
236 else
237 DPRINT1("Get resource type: %d, Generic start=0x%x Generic length=0x%x\n",
238 Descriptor->Type, Descriptor->u.Generic.Start.u.LowPart, Descriptor->u.Generic.Length);
239
240 }
241 }
242 }
243
244 /*
245 * Init wrapper with this object
246 */
247 return InitLinuxWrapper(DeviceObject);
248 }
249
250 // Dispatch PNP
251 NTSTATUS STDCALL DispatchPnp(PDEVICE_OBJECT DeviceObject, PIRP Irp)
252 {
253 PIO_STACK_LOCATION IrpSp;
254 NTSTATUS Status;
255
256 IrpSp = IoGetCurrentIrpStackLocation(Irp);
257
258 switch (IrpSp->MinorFunction)
259 {
260 case IRP_MN_START_DEVICE:
261 //Status = IntVideoPortForwardIrpAndWait(DeviceObject, Irp);
262 //if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
263
264 Status = OHCD_PnPStartDevice(DeviceObject, Irp);
265 Irp->IoStatus.Status = Status;
266 Irp->IoStatus.Information = 0;
267 IoCompleteRequest(Irp, IO_NO_INCREMENT);
268 break;
269
270
271 case IRP_MN_REMOVE_DEVICE:
272 case IRP_MN_QUERY_REMOVE_DEVICE:
273 case IRP_MN_CANCEL_REMOVE_DEVICE:
274 case IRP_MN_SURPRISE_REMOVAL:
275
276 case IRP_MN_STOP_DEVICE:
277 //Status = IntVideoPortForwardIrpAndWait(DeviceObject, Irp);
278 //if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
279 Status = STATUS_SUCCESS;
280 Irp->IoStatus.Status = Status;
281 Irp->IoStatus.Information = 0;
282 IoCompleteRequest(Irp, IO_NO_INCREMENT);
283
284 IoDeleteDevice(DeviceObject); // just delete device for now
285 break;
286
287 case IRP_MN_QUERY_STOP_DEVICE:
288 case IRP_MN_CANCEL_STOP_DEVICE:
289 Status = STATUS_SUCCESS;
290 Irp->IoStatus.Status = STATUS_SUCCESS;
291 Irp->IoStatus.Information = 0;
292 IoCompleteRequest(Irp, IO_NO_INCREMENT);
293 break;
294
295 default:
296 return STATUS_NOT_IMPLEMENTED;
297 break;
298 }
299
300 return Status;
301 }
302
303 NTSTATUS STDCALL DispatchPower(PDEVICE_OBJECT fido, PIRP Irp)
304 {
305 DbgPrint("IRP_MJ_POWER dispatch\n");
306 return STATUS_SUCCESS;
307 }
308
309 /*
310 * Standard DriverEntry method.
311 */
312 NTSTATUS STDCALL
313 DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegPath)
314 {
315 DriverObject->DriverUnload = DriverUnload;
316 DriverObject->DriverExtension->AddDevice = AddDevice;
317 DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp;
318 DriverObject->MajorFunction[IRP_MJ_POWER] = DispatchPower;
319
320 return STATUS_SUCCESS;
321 }