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
11 // config and include core/hcd.h, for hc_device struct
12 #include "../usb_wrapper.h"
13 #include "../core/hcd.h"
15 #include "../host/ohci_main.h"
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
[];
27 // This should be removed, but for testing purposes it's here
29 //struct pci_device_id *dev_id;
31 #define USB_UHCI_TAG TAG('u','s','b','u')
34 AddDevice(PDRIVER_OBJECT DriverObject
, PDEVICE_OBJECT pdo
)
38 WCHAR DeviceBuffer
[20];
39 UNICODE_STRING DeviceName
;
40 POHCI_DRIVER_EXTENSION DriverExtension
;
41 POHCI_DEVICE_EXTENSION DeviceExtension
;
42 ULONG Size
, DeviceNumber
;
44 DPRINT1("uhci: AddDevice called\n");
46 // Allocate driver extension now
47 DriverExtension
= IoGetDriverObjectExtension(DriverObject
, DriverObject
);
48 if (DriverExtension
== NULL
)
50 Status
= IoAllocateDriverObjectExtension(
53 sizeof(OHCI_DRIVER_EXTENSION
),
54 (PVOID
*)&DriverExtension
);
56 if (!NT_SUCCESS(Status
))
58 DPRINT1("Allocating DriverObjectExtension failed.\n");
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
);
68 Status
= IoCreateDevice(DriverObject
,
69 sizeof(OHCI_DEVICE_EXTENSION
),
70 /* + DriverExtension->InitializationData.HwDeviceExtensionSize*/
72 FILE_DEVICE_CONTROLLER
,
77 if (!NT_SUCCESS(Status
))
79 DPRINT1("IoCreateDevice call failed with status 0x%08x\n", Status
);
83 // zerofill device extension
84 DeviceExtension
= (POHCI_DEVICE_EXTENSION
)pdo
->DeviceExtension
;
85 RtlZeroMemory(DeviceExtension
, sizeof(OHCI_DEVICE_EXTENSION
));
86 DeviceExtension
->NextDeviceObject
= IoAttachDeviceToDeviceStack(fdo
, pdo
);
88 fdo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
90 // Initialize device extension
91 DeviceExtension
->DeviceNumber
= DeviceNumber
;
92 DeviceExtension
->PhysicalDeviceObject
= pdo
;
93 DeviceExtension
->FunctionalDeviceObject
= fdo
;
94 DeviceExtension
->DriverExtension
= DriverExtension
;
96 /* Get bus number from the upper level bus driver. */
98 /* Status = IoGetDeviceProperty(
100 DevicePropertyBusNumber,
102 &DeviceExtension->SystemIoBusNumber,
105 if (!NT_SUCCESS(Status))
107 DPRINT1("Couldn't get an information from bus driver. Panic!!!\n");
111 DPRINT1("Done AddDevice\n");
112 return STATUS_SUCCESS
;
116 DriverUnload(PDRIVER_OBJECT DriverObject
)
118 DPRINT1("DriverUnload()\n");
123 // Remove device (ohci_pci_driver.remove)
124 uhci_pci_driver
.remove(dev
);
126 ExFreePool(dev
->slot_name
);
129 // Perform some cleanup
134 InitLinuxWrapper(PDEVICE_OBJECT DeviceObject
)
137 POHCI_DEVICE_EXTENSION DeviceExtension
= (POHCI_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
139 // Fill generic linux structs
140 dev
= ExAllocatePoolWithTag(PagedPool
, sizeof(struct pci_dev
), USB_UHCI_TAG
);
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
147 strcpy(dev
->dev
.name
, "UnivHCI PCI-USB Controller");
148 strcpy(dev
->slot_name
, "UHCD PCI Slot");
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
157 // Probe device with real id now
158 uhci_pci_driver
.probe(dev
, uhci_pci_ids
);
160 DPRINT1("InitLinuxWrapper() done\n");
162 return STATUS_SUCCESS
;
166 OHCD_PnPStartDevice(IN PDEVICE_OBJECT DeviceObject
,
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
;
176 * Get the initialization data we saved in VideoPortInitialize.
178 DriverObject
= DeviceObject
->DriverObject
;
179 DriverExtension
= IoGetDriverObjectExtension(DriverObject
, DriverObject
);
180 DeviceExtension
= (POHCI_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
183 * Store some resources in the DeviceExtension.
185 AllocatedResources
= Stack
->Parameters
.StartDevice
.AllocatedResources
;
186 if (AllocatedResources
!= NULL
)
188 CM_FULL_RESOURCE_DESCRIPTOR
*FullList
;
189 CM_PARTIAL_RESOURCE_DESCRIPTOR
*Descriptor
;
191 ULONG ResourceListSize
;
193 /* Save the resource list */
194 ResourceCount
= AllocatedResources
->List
[0].PartialResourceList
.Count
;
196 FIELD_OFFSET(CM_RESOURCE_LIST
, List
[0].PartialResourceList
.
197 PartialDescriptors
[ResourceCount
]);
198 DeviceExtension
->AllocatedResources
= ExAllocatePool(PagedPool
, ResourceListSize
);
199 if (DeviceExtension
->AllocatedResources
== NULL
)
201 return STATUS_INSUFFICIENT_RESOURCES
;
204 RtlCopyMemory(DeviceExtension
->AllocatedResources
,
208 /* Get the interrupt level/vector - needed by HwFindAdapter sometimes */
209 for (FullList
= AllocatedResources
->List
;
210 FullList
< AllocatedResources
->List
+ AllocatedResources
->Count
;
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
);
221 for (Descriptor
= FullList
->PartialResourceList
.PartialDescriptors
;
222 Descriptor
< FullList
->PartialResourceList
.PartialDescriptors
+ FullList
->PartialResourceList
.Count
;
225 if (Descriptor
->Type
== CmResourceTypeInterrupt
)
227 DeviceExtension
->InterruptLevel
= Descriptor
->u
.Interrupt
.Level
;
228 DeviceExtension
->InterruptVector
= Descriptor
->u
.Interrupt
.Vector
;
230 DPRINT1("Interrupt level: 0x%x Interrupt Vector: 0x%x\n",
231 DeviceExtension
->InterruptLevel
,
232 DeviceExtension
->InterruptVector
);
234 else if (Descriptor
->Type
== CmResourceTypePort
)
236 DeviceExtension
->BaseAddress
= Descriptor
->u
.Port
.Start
;
237 DeviceExtension
->BaseAddrLength
= Descriptor
->u
.Port
.Length
;
238 DeviceExtension
->Flags
= Descriptor
->Flags
;
240 ((struct hc_driver
*)uhci_pci_ids
->driver_data
)->flags
&= ~HCD_MEMORY
;
242 DPRINT1("I/O resource: start=0x%x, length=0x%x\n",
243 DeviceExtension
->BaseAddress
.u
.LowPart
, DeviceExtension
->BaseAddrLength
);
245 else if (Descriptor
->Type
== CmResourceTypeMemory
)
247 DeviceExtension
->BaseAddress
= Descriptor
->u
.Memory
.Start
;
248 DeviceExtension
->BaseAddrLength
= Descriptor
->u
.Memory
.Length
;
249 DeviceExtension
->Flags
= Descriptor
->Flags
;
251 ((struct hc_driver
*)uhci_pci_ids
->driver_data
)->flags
|= HCD_MEMORY
;
253 DPRINT1("Memory resource: start=0x%x, length=0x%x\n",
254 DeviceExtension
->BaseAddress
.u
.LowPart
, DeviceExtension
->BaseAddrLength
);
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
);
265 * Init wrapper with this object
267 return InitLinuxWrapper(DeviceObject
);
272 DispatchPnp(PDEVICE_OBJECT DeviceObject
, PIRP Irp
)
274 PIO_STACK_LOCATION IrpSp
;
277 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
279 switch (IrpSp
->MinorFunction
)
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
);
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
:
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
);
304 IoDeleteDevice(DeviceObject
); // just delete device for now
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
);
316 return STATUS_NOT_IMPLEMENTED
;
324 DispatchPower(PDEVICE_OBJECT fido
, PIRP Irp
)
326 DbgPrint("IRP_MJ_POWER dispatch\n");
327 return STATUS_SUCCESS
;
332 * Standard DriverEntry method.
335 DriverEntry(IN PDRIVER_OBJECT DriverObject
, IN PUNICODE_STRING RegPath
)
338 DPRINT1("******************** Cromwell UHCI ********************\n");
340 DriverObject
->DriverUnload
= DriverUnload
;
341 DriverObject
->DriverExtension
->AddDevice
= AddDevice
;
343 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = DispatchPnp
;
344 DriverObject
->MajorFunction
[IRP_MJ_POWER
] = DispatchPower
;
346 return STATUS_SUCCESS
;