2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/multimedia/portcls/adapter.c
5 * PURPOSE: Port Class driver / DriverEntry and IRP handlers
6 * PROGRAMMER: Andrew Greenwood
17 This is called from DriverEntry so that PortCls can take care of some
18 IRPs and map some others to the main KS driver. In most cases this will
19 be the first function called by an audio driver.
21 First 2 parameters are from DriverEntry.
23 The AddDevice parameter is a driver-supplied pointer to a function which
24 typically then calls PcAddAdapterDevice (see below.)
27 PcInitializeAdapterDriver(
28 IN PDRIVER_OBJECT DriverObject
,
29 IN PUNICODE_STRING RegistryPathName
,
30 IN PDRIVER_ADD_DEVICE AddDevice
)
33 (* = implement here, otherwise KS default)
43 * IRP_MJ_SYSTEM_CONTROL
50 DPRINT1("PcInitializeAdapterDriver\n");
53 /* Set default stub - is this a good idea? */
54 DPRINT1("Setting IRP stub\n");
55 for ( i
= 0; i
<= IRP_MJ_MAXIMUM_FUNCTION
; i
++ )
57 DriverObject
->MajorFunction
[i
] = IrpStub
;
61 /* Our IRP handlers */
62 DPRINT1("Setting IRP handlers\n");
63 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = PcDispatchIrp
;
64 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = PcDispatchIrp
;
65 DriverObject
->MajorFunction
[IRP_MJ_POWER
] = PcDispatchIrp
;
66 DriverObject
->MajorFunction
[IRP_MJ_SYSTEM_CONTROL
] = PcDispatchIrp
;
68 /* The driver-supplied AddDevice */
69 DriverObject
->DriverExtension
->AddDevice
= AddDevice
;
71 /* KS handles these */
72 DPRINT1("Setting KS function handlers\n");
73 KsSetMajorFunctionHandler(DriverObject
, IRP_MJ_CLOSE
);
74 KsSetMajorFunctionHandler(DriverObject
, IRP_MJ_DEVICE_CONTROL
);
75 KsSetMajorFunctionHandler(DriverObject
, IRP_MJ_FLUSH_BUFFERS
);
76 KsSetMajorFunctionHandler(DriverObject
, IRP_MJ_QUERY_SECURITY
);
77 KsSetMajorFunctionHandler(DriverObject
, IRP_MJ_READ
);
78 KsSetMajorFunctionHandler(DriverObject
, IRP_MJ_SET_SECURITY
);
79 KsSetMajorFunctionHandler(DriverObject
, IRP_MJ_WRITE
);
81 DPRINT1("PortCls has finished initializing the adapter driver\n");
83 return STATUS_SUCCESS
;
87 Typically called by a driver's AddDevice function, which is set when
88 calling PcInitializeAdapterDriver. This performs some common driver
89 operations, such as creating a device extension.
91 The StartDevice parameter is a driver-supplied function which gets
92 called in response to IRP_MJ_PNP / IRP_MN_START_DEVICE.
96 IN PDRIVER_OBJECT DriverObject
,
97 IN PDEVICE_OBJECT PhysicalDeviceObject
,
98 IN PCPFNSTARTDEVICE StartDevice
,
100 IN ULONG DeviceExtensionSize
)
102 NTSTATUS status
= STATUS_UNSUCCESSFUL
;
103 PDEVICE_OBJECT fdo
= NULL
;
104 PDEVICE_OBJECT PrevDeviceObject
;
105 PCExtension
* portcls_ext
;
107 DPRINT1("PcAddAdapterDevice called\n");
109 if (!DriverObject
|| !PhysicalDeviceObject
|| !StartDevice
)
111 return STATUS_INVALID_PARAMETER
;
114 /* check if the DeviceExtensionSize is provided */
115 if ( DeviceExtensionSize
< PORT_CLASS_DEVICE_EXTENSION_SIZE
)
117 /* driver does not need a device extension */
118 if ( DeviceExtensionSize
!= 0 )
120 /* DeviceExtensionSize must be zero*/
121 return STATUS_INVALID_PARAMETER
;
123 /* set size to our extension size */
124 DeviceExtensionSize
= PORT_CLASS_DEVICE_EXTENSION_SIZE
;
127 /* create the device */
128 status
= IoCreateDevice(DriverObject
,
132 FILE_AUTOGENERATED_DEVICE_NAME
| FILE_DEVICE_SECURE_OPEN
,
136 if (!NT_SUCCESS(status
))
138 DPRINT("IoCreateDevice() failed with status 0x%08lx\n", status
);
142 /* Obtain the new device extension */
143 portcls_ext
= (PCExtension
*) fdo
->DeviceExtension
;
144 /* initialize the device extension */
145 RtlZeroMemory(portcls_ext
, DeviceExtensionSize
);
146 /* allocate create item */
147 portcls_ext
->CreateItems
= AllocateItem(NonPagedPool
, MaxObjects
* sizeof(KSOBJECT_CREATE_ITEM
), TAG_PORTCLASS
);
149 /* store the physical device object */
150 portcls_ext
->PhysicalDeviceObject
= PhysicalDeviceObject
;
151 /* set up the start device function */
152 portcls_ext
->StartDevice
= StartDevice
;
153 /* prepare the subdevice list */
154 InitializeListHead(&portcls_ext
->SubDeviceList
);
155 /* prepare the physical connection list */
156 InitializeListHead(&portcls_ext
->PhysicalConnectionList
);
159 fdo
->Flags
|= DO_DIRECT_IO
| DO_POWER_PAGABLE
;
160 /* clear initializing flag */
161 fdo
->Flags
&= ~ DO_DEVICE_INITIALIZING
;
163 /* allocate the device header */
164 status
= KsAllocateDeviceHeader(&portcls_ext
->KsDeviceHeader
, MaxObjects
, portcls_ext
->CreateItems
);
166 if (!NT_SUCCESS(status
))
168 /* free previously allocated create items */
169 FreeItem(portcls_ext
->CreateItems
, TAG_PORTCLASS
);
170 /* delete created fdo */
172 /* return error code */
176 /* attach device to device stack */
177 PrevDeviceObject
= IoAttachDeviceToDeviceStack(fdo
, PhysicalDeviceObject
);
179 if (PrevDeviceObject
)
181 /* store the device object in the device header */
182 //KsSetDevicePnpBaseObject(portcls_ext->KsDeviceHeader, PrevDeviceObject, fdo);
183 portcls_ext
->PrevDeviceObject
= PrevDeviceObject
;
187 /* free the device header */
188 KsFreeDeviceHeader(portcls_ext
->KsDeviceHeader
);
189 /* free previously allocated create items */
190 FreeItem(portcls_ext
->CreateItems
, TAG_PORTCLASS
);
191 /* delete created fdo */
193 /* return error code */
194 return STATUS_UNSUCCESSFUL
;
205 IN PDEVICE_OBJECT DeviceObject
,
210 ISubdevice
* SubDevice
;
211 PCExtension
* DeviceExt
;
212 SUBDEVICE_ENTRY
* Entry
;
213 KSDISPATCH_TABLE DispatchTable
;
215 DPRINT1("PortClsSysControl called\n");
217 SubDevice
= (ISubdevice
*)Irp
->Tail
.Overlay
.DriverContext
[3];
218 DeviceExt
= (PCExtension
*)DeviceObject
->DeviceExtension
;
220 if (!SubDevice
|| !DeviceExt
)
222 return STATUS_UNSUCCESSFUL
;
225 Entry
= AllocateItem(NonPagedPool
, sizeof(SUBDEVICE_ENTRY
), TAG_PORTCLASS
);
227 return STATUS_INSUFFICIENT_RESOURCES
;
229 /* initialize DispatchTable */
230 RtlZeroMemory(&DispatchTable
, sizeof(KSDISPATCH_TABLE
));
232 * initialize DispatchTable pointer
233 * which call in turn ISubDevice
237 Status
= KsAllocateObjectHeader(&Entry
->ObjectHeader
, 1, NULL
, Irp
, &DispatchTable
);
238 if (!NT_SUCCESS(Status
))
240 FreeItem(Entry
, TAG_PORTCLASS
);
245 InsertTailList(&DeviceExt
->SubDeviceList
, &Entry
->Entry
);
247 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
248 Irp
->IoStatus
.Information
= 0;
249 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
251 return STATUS_SUCCESS
;
256 IN PDEVICE_OBJECT DeviceObject
,
260 PCExtension
* DeviceExt
;
262 ISubdevice
*SubDevice
;
263 UNICODE_STRING ReferenceString
;
264 UNICODE_STRING SymbolicLinkName
;
266 DPRINT1("PcRegisterSubdevice DeviceObject %p Name %S Unknown %p\n", DeviceObject
, Name
, Unknown
);
268 if (!DeviceObject
|| !Name
|| !Unknown
)
270 DPRINT("PcRegisterSubdevice invalid parameter\n");
271 return STATUS_INVALID_PARAMETER
;
274 DeviceExt
= (PCExtension
*)DeviceObject
->DeviceExtension
;
276 return STATUS_UNSUCCESSFUL
;
278 Status
= Unknown
->lpVtbl
->QueryInterface(Unknown
, &IID_ISubdevice
, (LPVOID
)&SubDevice
);
279 if (!NT_SUCCESS(Status
))
281 DPRINT1("No ISubdevice interface\n");
282 /* the provided port driver doesnt support ISubdevice */
283 return STATUS_INVALID_PARAMETER
;
286 Status
= KsAddObjectCreateItemToDeviceHeader(DeviceExt
->KsDeviceHeader
, PciDriverDispatch
, (PVOID
)SubDevice
, Name
, NULL
);
287 if (!NT_SUCCESS(Status
))
289 /* failed to attach */
290 SubDevice
->lpVtbl
->Release(SubDevice
);
291 DPRINT1("KsAddObjectCreateItemToDeviceHeader failed with %x\n", Status
);
296 /* FIXME retrieve guid from subdescriptor */
298 RtlInitUnicodeString(&ReferenceString
, Name
);
299 /* register device interface */
300 Status
= IoRegisterDeviceInterface(DeviceExt
->PhysicalDeviceObject
,
301 &GUID_DEVCLASS_SOUND
, //FIXME
304 if (NT_SUCCESS(Status
))
306 Status
= IoSetDeviceInterfaceState(&SymbolicLinkName
, TRUE
);
307 RtlFreeUnicodeString(&SymbolicLinkName
);
310 DPRINT1("PcRegisterSubdevice Status %x\n", Status
);
313 /// IoRegisterDeviceInterface fails with
314 /// STATUS_OBJECT_PATH_NOT_FOUND
316 return STATUS_SUCCESS
;