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