2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/wdm/audio/legacy/stream/pnp.c
5 * PURPOSE: pnp handling
6 * PROGRAMMER: Johannes Anderwald
15 IN ULONG_PTR Information
)
17 Irp
->IoStatus
.Status
= Status
;
18 Irp
->IoStatus
.Information
= Information
;
19 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
24 StreamClassReleaseResources(
25 IN PDEVICE_OBJECT DeviceObject
)
27 PSTREAM_DEVICE_EXTENSION DeviceExtension
;
29 PMEMORY_RESOURCE_LIST Mem
;
31 /* Get device extension */
32 DeviceExtension
= (PSTREAM_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
34 /* Disconnect interrupt */
35 if (DeviceExtension
->Interrupt
)
37 IoDisconnectInterrupt(DeviceExtension
->Interrupt
);
38 DeviceExtension
->Interrupt
= NULL
;
41 /* Release DmaAdapter */
42 if (DeviceExtension
->DmaAdapter
)
44 DeviceExtension
->DmaAdapter
->DmaOperations
->PutDmaAdapter(DeviceExtension
->DmaAdapter
);
45 DeviceExtension
->DmaAdapter
= NULL
;
48 /* Release mem mapped I/O */
49 while(!IsListEmpty(&DeviceExtension
->MemoryResourceList
))
51 Entry
= RemoveHeadList(&DeviceExtension
->MemoryResourceList
);
52 Mem
= (PMEMORY_RESOURCE_LIST
)CONTAINING_RECORD(Entry
, MEMORY_RESOURCE_LIST
, Entry
);
54 MmUnmapIoSpace(Mem
->Start
, Mem
->Length
);
61 StreamClassSynchronize(
62 IN PKINTERRUPT Interrupt
,
63 IN PKSYNCHRONIZE_ROUTINE SynchronizeRoutine
,
64 IN PVOID SynchronizeContext
)
66 /* This function is used when the driver either implements synchronization on its own
67 * or if there is no interrupt assigned
69 return SynchronizeRoutine(SynchronizeContext
);
74 StreamClassInterruptDpc(
76 IN PVOID DeferredContext
,
77 IN PVOID SystemArgument1
,
78 IN PVOID SystemArgument2
)
87 StreamClassInterruptRoutine(
88 IN PKINTERRUPT Interrupt
,
89 IN PVOID ServiceContext
)
92 PSTREAM_DEVICE_EXTENSION DeviceExtension
= (PSTREAM_DEVICE_EXTENSION
)ServiceContext
;
94 /* Does the driver implement HwInterrupt routine */
95 if (DeviceExtension
->DriverExtension
->Data
.HwInterrupt
)
97 /* Check if the interrupt was coming from this device */
98 Ret
= DeviceExtension
->DriverExtension
->Data
.HwInterrupt(DeviceExtension
->DeviceExtension
);
101 /* Interrupt has from this device, schedule a Dpc for us */
102 KeInsertQueueDpc(&DeviceExtension
->InterruptDpc
, NULL
, NULL
);
113 StreamClassStartDevice(
114 IN PDEVICE_OBJECT DeviceObject
,
117 PHW_STREAM_REQUEST_BLOCK_EXT RequestBlock
;
118 PPORT_CONFIGURATION_INFORMATION Config
;
119 PSTREAM_DEVICE_EXTENSION DeviceExtension
;
120 PIO_STACK_LOCATION IoStack
;
121 PCM_RESOURCE_LIST List
;
122 PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor
;
123 PSTREAM_CLASS_DRIVER_EXTENSION DriverObjectExtension
;
124 PDMA_ADAPTER Adapter
;
125 DEVICE_DESCRIPTION DeviceDesc
;
126 NTSTATUS Status
= STATUS_SUCCESS
;
127 ULONG ResultLength
, Index
;
128 BOOLEAN bUseDMA
, bUseInterrupt
;
130 KAFFINITY Affinity
= 0;
131 PHW_STREAM_DESCRIPTOR StreamDescriptor
;
134 PMEMORY_RESOURCE_LIST Mem
;
136 /* Get current stack location */
137 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
139 /* Get resource list */
140 List
= IoStack
->Parameters
.StartDevice
.AllocatedResourcesTranslated
;
141 /* Calculate request length */
142 ResultLength
= sizeof(HW_STREAM_REQUEST_BLOCK_EXT
) + sizeof(PPORT_CONFIGURATION_INFORMATION
) + List
->List
[0].PartialResourceList
.Count
* sizeof(ACCESS_RANGE
);
144 /* Allocate Request Block */
145 RequestBlock
= ExAllocatePool(NonPagedPool
, ResultLength
);
149 /* Not enough memory */
150 CompleteIrp(Irp
, STATUS_INSUFFICIENT_RESOURCES
, 0);
151 return STATUS_INSUFFICIENT_RESOURCES
;
154 /* Get device extension */
155 DeviceExtension
= (PSTREAM_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
157 /* Get driver object extension */
158 DriverObjectExtension
= IoGetDriverObjectExtension(DeviceObject
->DriverObject
, (PVOID
)StreamClassAddDevice
);
161 ASSERT(DeviceExtension
);
162 ASSERT(DriverObjectExtension
);
164 /* Zero request block */
165 RtlZeroMemory(RequestBlock
, ResultLength
);
167 /* Locate Config struct */
168 Config
= (PPORT_CONFIGURATION_INFORMATION
) (RequestBlock
+ 1);
169 Range
= (PACCESS_RANGE
) (Config
+ 1);
171 /* Initialize Request */
172 RequestBlock
->Block
.SizeOfThisPacket
= sizeof(HW_STREAM_REQUEST_BLOCK
);
173 RequestBlock
->Block
.Command
= SRB_INITIALIZE_DEVICE
;
174 RequestBlock
->Block
.CommandData
.ConfigInfo
= Config
;
175 KeInitializeEvent(&RequestBlock
->Event
, SynchronizationEvent
, FALSE
);
177 Config
->SizeOfThisPacket
= sizeof(PPORT_CONFIGURATION_INFORMATION
);
178 Config
->HwDeviceExtension
= (PVOID
) (DeviceExtension
+ 1);
179 Config
->ClassDeviceObject
= DeviceObject
;
180 Config
->PhysicalDeviceObject
= DeviceExtension
->LowerDeviceObject
;
181 Config
->RealPhysicalDeviceObject
= DeviceExtension
->PhysicalDeviceObject
;
182 Config
->AccessRanges
= Range
;
184 IoGetDeviceProperty(DeviceObject
, DevicePropertyBusNumber
, sizeof(ULONG
), (PVOID
)&Config
->SystemIoBusNumber
, &ResultLength
);
185 IoGetDeviceProperty(DeviceObject
, DevicePropertyLegacyBusType
, sizeof(INTERFACE_TYPE
), (PVOID
)&Config
->AdapterInterfaceType
, &ResultLength
);
187 /* Get resource list */
188 List
= IoStack
->Parameters
.StartDevice
.AllocatedResourcesTranslated
;
190 /* Scan the translated resources */
192 bUseInterrupt
= FALSE
;
194 Range
= (PACCESS_RANGE
) (Config
+ 1);
196 for(Index
= 0; Index
< List
->List
[0].PartialResourceList
.Count
; Index
++)
198 /* Locate partial descriptor */
199 Descriptor
= &List
->List
[0].PartialResourceList
.PartialDescriptors
[Index
];
201 switch(Descriptor
->Type
)
203 case CmResourceTypePort
:
205 /* Store resource information in AccessRange struct */
206 Range
[Config
->NumberOfAccessRanges
].RangeLength
= Descriptor
->u
.Port
.Length
;
207 Range
[Config
->NumberOfAccessRanges
].RangeStart
.QuadPart
= Descriptor
->u
.Port
.Start
.QuadPart
;
208 Range
[Config
->NumberOfAccessRanges
].RangeInMemory
= FALSE
;
209 Config
->NumberOfAccessRanges
++;
212 case CmResourceTypeInterrupt
:
214 /* Store resource information */
215 Config
->BusInterruptLevel
= Descriptor
->u
.Interrupt
.Level
;
216 Config
->BusInterruptVector
= Descriptor
->u
.Interrupt
.Vector
;
217 Config
->InterruptMode
= Descriptor
->Flags
;
218 Affinity
= Descriptor
->u
.Interrupt
.Affinity
;
219 bUseInterrupt
= TRUE
;
222 case CmResourceTypeMemory
:
224 Mem
= ExAllocatePool(NonPagedPool
, sizeof(MEMORY_RESOURCE_LIST
));
225 MappedAddr
= MmMapIoSpace(Descriptor
->u
.Memory
.Start
, Descriptor
->u
.Memory
.Length
, MmNonCached
);
226 if (!MappedAddr
|| !Mem
)
230 /* Release Memory resource descriptor */
236 /* Release mem mapped I/O */
237 MmUnmapIoSpace(MappedAddr
, Descriptor
->u
.Memory
.Length
);
240 /* Release resources */
241 StreamClassReleaseResources(DeviceObject
);
243 CompleteIrp(Irp
, STATUS_INSUFFICIENT_RESOURCES
, 0);
244 ExFreePool(RequestBlock
);
245 return STATUS_INSUFFICIENT_RESOURCES
;
247 /* Store range for driver */
248 Range
[Config
->NumberOfAccessRanges
].RangeLength
= Descriptor
->u
.Memory
.Length
;
249 Range
[Config
->NumberOfAccessRanges
].RangeStart
.QuadPart
= Descriptor
->u
.Memory
.Start
.QuadPart
;
250 Range
[Config
->NumberOfAccessRanges
].RangeInMemory
= TRUE
;
251 Config
->NumberOfAccessRanges
++;
252 /* Initialize Memory resource descriptor */
253 Mem
->Length
= Descriptor
->u
.Memory
.Length
;
254 Mem
->Start
= MappedAddr
;
255 InsertTailList(&DeviceExtension
->MemoryResourceList
, &Mem
->Entry
);
258 case CmResourceTypeDma
:
261 Config
->DmaChannel
= Descriptor
->u
.Dma
.Channel
;
267 if (!bUseInterrupt
|| DriverObjectExtension
->Data
.HwInterrupt
== NULL
|| Config
->BusInterruptLevel
== 0 || Config
->BusInterruptVector
== 0)
269 /* requirements not satisfied */
270 DeviceExtension
->SynchronizeFunction
= StreamClassSynchronize
;
274 /* use real sync routine */
275 DeviceExtension
->SynchronizeFunction
= KeSynchronizeExecution
;
277 /* connect interrupt */
278 Status
= IoConnectInterrupt(&DeviceExtension
->Interrupt
,
279 StreamClassInterruptRoutine
,
280 (PVOID
)DeviceExtension
,
282 Config
->BusInterruptVector
,
283 Config
->BusInterruptLevel
,
284 Config
->BusInterruptLevel
,
285 Config
->InterruptMode
,
289 if (!NT_SUCCESS(Status
))
291 /* Release resources */
292 StreamClassReleaseResources(DeviceObject
);
293 /* Failed to connect interrupt */
294 CompleteIrp(Irp
, Status
, 0);
295 /* Release request block */
296 ExFreePool(RequestBlock
);
300 /* store interrupt object */
301 Config
->InterruptObject
= DeviceExtension
->Interrupt
;
304 /* does the device use DMA */
305 if (bUseDMA
&& DriverObjectExtension
->Data
.BusMasterDMA
)
307 /* Zero device description */
308 RtlZeroMemory(&DeviceDesc
, sizeof(DEVICE_DESCRIPTION
));
310 DeviceDesc
.Version
= DEVICE_DESCRIPTION_VERSION
;
311 DeviceDesc
.Master
= TRUE
;
312 DeviceDesc
.ScatterGather
= TRUE
;
313 DeviceDesc
.AutoInitialize
= FALSE
;
314 DeviceDesc
.DmaChannel
= Config
->DmaChannel
;
315 DeviceDesc
.InterfaceType
= Config
->AdapterInterfaceType
;
316 DeviceDesc
.DmaWidth
= Width32Bits
;
317 DeviceDesc
.DmaSpeed
= Compatible
;
318 DeviceDesc
.MaximumLength
= MAXULONG
;
319 DeviceDesc
.Dma32BitAddresses
= DriverObjectExtension
->Data
.Dma24BitAddresses
;
321 Adapter
= IoGetDmaAdapter(DeviceExtension
->PhysicalDeviceObject
, &DeviceDesc
, &MapRegisters
);
324 /* Failed to claim DMA Adapter */
325 CompleteIrp(Irp
, Status
, 0);
326 /* Release resources */
327 StreamClassReleaseResources(DeviceObject
);
328 /* Release request block */
329 ExFreePool(RequestBlock
);
333 if (DeviceExtension
->DriverExtension
->Data
.DmaBufferSize
)
335 DeviceExtension
->DmaCommonBuffer
= Adapter
->DmaOperations
->AllocateCommonBuffer(Adapter
, DeviceExtension
->DriverExtension
->Data
.DmaBufferSize
, &DeviceExtension
->DmaPhysicalAddress
, FALSE
);
336 if (!DeviceExtension
->DmaCommonBuffer
)
338 /* Failed to allocate a common buffer */
339 CompleteIrp(Irp
, Status
, 0);
340 /* Release resources */
341 StreamClassReleaseResources(DeviceObject
);
342 /* Release request block */
343 ExFreePool(RequestBlock
);
349 DeviceExtension
->MapRegisters
= MapRegisters
;
350 DeviceExtension
->DmaAdapter
= Adapter
;
351 Config
->DmaAdapterObject
= (PADAPTER_OBJECT
)Adapter
;
355 /* First forward the request to lower attached device object */
356 Status
= ForwardIrpSynchronous(DeviceObject
, Irp
);
357 if (!NT_SUCCESS(Status
))
359 /* Failed to start lower devices */
360 CompleteIrp(Irp
, Status
, 0);
361 /* Release resources */
362 StreamClassReleaseResources(DeviceObject
);
363 /* Release request block */
364 ExFreePool(RequestBlock
);
370 /* FIXME SYNCHRONIZATION */
372 /* Send the request */
373 DriverObjectExtension
->Data
.HwReceivePacket((PHW_STREAM_REQUEST_BLOCK
)RequestBlock
);
374 if (RequestBlock
->Block
.Status
== STATUS_PENDING
)
376 /* Request is pending, wait for result */
377 KeWaitForSingleObject(&RequestBlock
->Event
, Executive
, KernelMode
, FALSE
, NULL
);
378 /* Get final status code */
379 Status
= RequestBlock
->Block
.Status
;
382 /* Copy stream descriptor size */
383 DeviceExtension
->StreamDescriptorSize
= Config
->StreamDescriptorSize
;
385 /* check if the request has succeeded or if stream size is valid*/
386 if (!NT_SUCCESS(Status
)|| !Config
->StreamDescriptorSize
)
388 /* Failed to start device */
389 CompleteIrp(Irp
, Status
, 0);
390 /* Release resources */
391 StreamClassReleaseResources(DeviceObject
);
392 /* Release request block */
393 ExFreePool(RequestBlock
);
397 /* Allocate a stream Descriptor */
398 StreamDescriptor
= ExAllocatePool(NonPagedPool
, DeviceExtension
->StreamDescriptorSize
);
399 if (!StreamDescriptor
)
401 /* Not enough memory */
402 CompleteIrp(Irp
, STATUS_INSUFFICIENT_RESOURCES
, 0);
403 /* Release resources */
404 StreamClassReleaseResources(DeviceObject
);
405 /* Release request block */
406 ExFreePool(RequestBlock
);
407 return STATUS_INSUFFICIENT_RESOURCES
;
410 /* Zero stream descriptor */
411 RtlZeroMemory(StreamDescriptor
, DeviceExtension
->StreamDescriptorSize
);
413 /* Setup get stream info struct */
414 RequestBlock
->Block
.Command
= SRB_GET_STREAM_INFO
;
415 RequestBlock
->Block
.CommandData
.StreamBuffer
= StreamDescriptor
;
416 KeResetEvent(&RequestBlock
->Event
);
418 /* send the request */
419 DriverObjectExtension
->Data
.HwReceivePacket((PHW_STREAM_REQUEST_BLOCK
)RequestBlock
);
420 if (RequestBlock
->Block
.Status
== STATUS_PENDING
)
422 /* Request is pending, wait for result */
423 KeWaitForSingleObject(&RequestBlock
->Event
, Executive
, KernelMode
, FALSE
, NULL
);
424 /* Get final status code */
425 Status
= RequestBlock
->Block
.Status
;
428 if (NT_SUCCESS(Status
))
430 /* store stream descriptor */
431 DeviceExtension
->StreamDescriptor
= StreamDescriptor
;
435 /* cleanup resources */
436 ExFreePool(StreamDescriptor
);
439 ExFreePool(RequestBlock
);
441 CompleteIrp(Irp
, Status
, 0);
449 IN PDEVICE_OBJECT DeviceObject
,
452 PIO_STACK_LOCATION IoStack
;
454 /* Get current irp stack location */
455 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
457 switch (IoStack
->MinorFunction
)
459 case IRP_MN_START_DEVICE
:
461 return StreamClassStartDevice(DeviceObject
, Irp
);
465 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
466 return STATUS_NOT_SUPPORTED
;