- Start implementing the stream class driver

- Implemented StreamClassRegisterAdapter, StreamClassReenumerateStreams, StreamClassDebugAssert, StreamClassDebugPrint, StreamClassGetDmaBuffer
- Drivers using stream class driver should now be able to initialize

svn path=/trunk/; revision=41662
This commit is contained in:
Johannes Anderwald 2009-06-28 13:58:47 +00:00
parent 593091354a
commit 4a0debf9c8
11 changed files with 1289 additions and 0 deletions

View file

@ -4,4 +4,8 @@
<directory name="wdmaud">
<xi:include href="wdmaud/wdmaud.rbuild" />
</directory>
<directory name="stream">
<xi:include href="stream/stream.rbuild" />
</directory>
</group>

View file

@ -0,0 +1,71 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/legacy/stream/dll.c
* PURPOSE: kernel mode driver initialization
* PROGRAMMER: Johannes Anderwald
*/
#include "stream.h"
NTSTATUS
NTAPI
StreamClassPower(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
StreamClassSystemControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
StreamClassCleanup(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
StreamClassFlushBuffers(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
StreamClassDeviceControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}

View file

@ -0,0 +1,30 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/legacy/stream/dll.c
* PURPOSE: kernel mode driver initialization
* PROGRAMMER: Johannes Anderwald
*/
#include "stream.h"
/*
* @implemented
*/
ULONG
NTAPI
DllInitialize(ULONG Unknown)
{
return 0;
}
/*
* @implemented
*/
ULONG
NTAPI
DllUnload(VOID)
{
return 0;
}

View file

@ -0,0 +1,299 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/legacy/stream/driver.c
* PURPOSE: WDM Codec Class Driver
* PROGRAMMER: Johannes Anderwald
*/
#include "stream.h"
NTSTATUS
NTAPI
StreamClassAddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject)
{
PSTREAM_CLASS_DRIVER_EXTENSION DriverObjectExtension;
PDEVICE_OBJECT DeviceObject, LowerDeviceObject;
PSTREAM_DEVICE_EXTENSION DeviceExtension;
PKSOBJECT_CREATE_ITEM ItemList;
NTSTATUS Status;
/* Fetch driver object extension */
DriverObjectExtension = IoGetDriverObjectExtension(DriverObject, (PVOID)StreamClassAddDevice);
if (!DriverObjectExtension)
{
/* Failed to get driver extension */
return STATUS_DEVICE_DOES_NOT_EXIST;
}
/* Allocate Create Item */
ItemList = ExAllocatePool(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM));
if (!ItemList)
{
/* Failed to allocated Create Item */
return STATUS_INSUFFICIENT_RESOURCES;
}
/* Create the FDO */
Status = IoCreateDevice(DriverObject, DriverObjectExtension->Data.DeviceExtensionSize + sizeof(STREAM_DEVICE_EXTENSION), NULL, FILE_DEVICE_KS, FILE_AUTOGENERATED_DEVICE_NAME | FILE_DEVICE_SECURE_OPEN, 0, &DeviceObject);
if (!NT_SUCCESS(Status))
{
/* Failed to create the FDO */
ExFreePool(ItemList);
return Status;
}
/* Attach to device stack */
LowerDeviceObject = IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject);
if (!LowerDeviceObject)
{
/* Failed to attach */
IoDeleteDevice(DeviceObject);
return STATUS_UNSUCCESSFUL;
}
/* Zero Create item */
RtlZeroMemory(ItemList, sizeof(KSOBJECT_CREATE_ITEM));
/* Setup object class */
RtlInitUnicodeString(&ItemList->ObjectClass, L"STREAMCLASS");
/* Setup CreateDispatch routine */
ItemList->Create = StreamClassCreateFilter;
/* Get device extension */
DeviceExtension = (PSTREAM_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
/* Zero device extension */
RtlZeroMemory(DeviceExtension, sizeof(STREAM_DEVICE_EXTENSION));
/* Initialize Ks streaming */
Status = KsAllocateDeviceHeader(&DeviceExtension->Header, 1, ItemList);
if (!NT_SUCCESS(Status))
{
/* Cleanup resources */
IoDetachDevice(LowerDeviceObject);
IoDeleteDevice(DeviceObject);
ExFreePool(ItemList);
return Status;
}
/* Store lower device object */
DeviceExtension->LowerDeviceObject = LowerDeviceObject;
/* Store physical device object */
DeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject;
/* Store driver object extension */
DeviceExtension->DriverExtension = DriverObjectExtension;
/* Initialize memory list */
InitializeListHead(&DeviceExtension->MemoryResourceList);
/* Setup device extension */
DeviceExtension->DeviceExtension = (PVOID) (DeviceExtension + 1);
/* Init interrupt dpc */
KeInitializeDpc(&DeviceExtension->InterruptDpc, StreamClassInterruptDpc, (PVOID)DeviceExtension);
/* Set device transfer method */
DeviceObject->Flags |= DO_DIRECT_IO | DO_POWER_PAGABLE;
/* Clear init flag */
DeviceObject->Flags &= ~ DO_DEVICE_INITIALIZING;
return Status;
}
/*
*@implemented
*/
NTSTATUS
STREAMAPI
StreamClassRegisterAdapter(
IN PVOID Argument1,
IN PVOID Argument2,
IN PHW_INITIALIZATION_DATA HwInitializationData)
{
NTSTATUS Status;
PSTREAM_CLASS_DRIVER_EXTENSION DriverObjectExtension;
PDRIVER_OBJECT DriverObject = (PDRIVER_OBJECT)Argument1;
/* Allocate driver extension */
Status = IoAllocateDriverObjectExtension(DriverObject, (PVOID)StreamClassAddDevice, sizeof(STREAM_CLASS_DRIVER_EXTENSION), (PVOID*)&DriverObjectExtension);
if (!NT_SUCCESS(Status))
{
/* Failed to allocate */
return STATUS_INSUFFICIENT_RESOURCES;
}
/* Zero driver object extension */
RtlZeroMemory(DriverObjectExtension, sizeof(STREAM_CLASS_DRIVER_EXTENSION));
/* copy HwInitializationData */
RtlCopyMemory(&DriverObjectExtension->Data, HwInitializationData, sizeof(HW_INITIALIZATION_DATA));
/* Setup device init methods */
DriverObject->DriverExtension->AddDevice = StreamClassAddDevice;
DriverObject->DriverUnload = KsNullDriverUnload;
/* Setup irp handlers */
DriverObject->MajorFunction[IRP_MJ_PNP] = StreamClassPnp;
DriverObject->MajorFunction[IRP_MJ_POWER] = StreamClassPower;
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = StreamClassSystemControl;
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = StreamClassCleanup;
DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = StreamClassFlushBuffers;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = StreamClassDeviceControl;
/* Let Ks handle these */
KsSetMajorFunctionHandler(DriverObject, IRP_MJ_CREATE);
KsSetMajorFunctionHandler(DriverObject, IRP_MJ_CLOSE);
return STATUS_SUCCESS;
}
/*
*@implemented
*/
VOID
NTAPI
StreamClassReenumerateStreams(
IN PVOID HwDeviceExtension,
IN ULONG StreamDescriptorSize)
{
HW_STREAM_REQUEST_BLOCK_EXT RequestBlock;
PSTREAM_DEVICE_EXTENSION DeviceExtension;
PHW_STREAM_DESCRIPTOR StreamDescriptor;
if (!HwDeviceExtension || !StreamDescriptorSize)
return;
StreamDescriptor = ExAllocatePool(NonPagedPool, StreamDescriptorSize);
if (!StreamDescriptor)
return;
/* Zero stream descriptor */
RtlZeroMemory(StreamDescriptor, StreamDescriptorSize);
/* Get our DeviceExtension */
DeviceExtension = (PSTREAM_DEVICE_EXTENSION) ((ULONG_PTR)HwDeviceExtension - sizeof(STREAM_DEVICE_EXTENSION));
ASSERT(DeviceExtension->DeviceExtension == HwDeviceExtension);
/* Zero RequestBlock */
RtlZeroMemory(&RequestBlock, sizeof(HW_STREAM_REQUEST_BLOCK_EXT));
/* Setup get stream info struct */
RequestBlock.Block.SizeOfThisPacket = sizeof(HW_STREAM_REQUEST_BLOCK);
RequestBlock.Block.Command = SRB_GET_STREAM_INFO;
RequestBlock.Block.CommandData.StreamBuffer = StreamDescriptor;
KeInitializeEvent(&RequestBlock.Event, SynchronizationEvent, FALSE);
/* FIXME SYNCHRONIZATION */
/* Send the request */
DeviceExtension->DriverExtension->Data.HwReceivePacket ((PHW_STREAM_REQUEST_BLOCK)&RequestBlock);
/* Is the device already completed? */
if (RequestBlock.Block.Status == STATUS_PENDING)
{
/* Request is pending, wait for result */
KeWaitForSingleObject(&RequestBlock.Event, Executive, KernelMode, FALSE, NULL);
}
if (!NT_SUCCESS(RequestBlock.Block.Status))
{
/* Release Stream descriptor */
ExFreePool(StreamDescriptor);
}
else
{
if (DeviceExtension->StreamDescriptor)
{
/* Release old stream descriptor */
ExFreePool(DeviceExtension->StreamDescriptor);
}
/* Store stream descriptor */
DeviceExtension->StreamDescriptor = StreamDescriptor;
DeviceExtension->StreamDescriptorSize = StreamDescriptorSize;
}
}
/*
*@implemented
*/
VOID
NTAPI
StreamClassDebugAssert(
IN PCHAR File,
IN ULONG Line,
IN PCHAR AssertText,
IN ULONG AssertValue)
{
#ifdef DBG
DbgBreakPoint();
#endif
}
/*
*@implemented
*/
VOID
__cdecl
StreamClassDebugPrint(
IN STREAM_DEBUG_LEVEL DebugPrintLevel,
IN PCCHAR DebugMessage,
...)
{
#ifdef DBG
va_list ap;
if (DebugPrintLevel <=STREAMDEBUG_LEVEL)
{
va_start(ap, DebugMessage);
DbgPrint(DebugMessage, ap);
va_end(ap);
}
#endif
}
/*
*@unimplemented
*/
VOID
__cdecl
StreamClassDeviceNotification(
IN STREAM_MINIDRIVER_DEVICE_NOTIFICATION_TYPE NotificationType,
IN PVOID HwDeviceExtension,
IN PHW_STREAM_REQUEST_BLOCK pSrb,
IN PKSEVENT_ENTRY EventEntry,
IN GUID *EventSet,
IN ULONG EventId)
{
PHW_STREAM_REQUEST_BLOCK_EXT RequestBlock;
if (NotificationType == DeviceRequestComplete)
{
RequestBlock = (PHW_STREAM_REQUEST_BLOCK_EXT)pSrb;
KeSetEvent(&RequestBlock->Event, 0, FALSE);
return;
}
UNIMPLEMENTED
}
/*
*@implemented
*/
PVOID
STREAMAPI
StreamClassGetDmaBuffer(
IN PVOID HwDeviceExtension)
{
PSTREAM_DEVICE_EXTENSION DeviceExtension;
/* Get our DeviceExtension */
DeviceExtension = (PSTREAM_DEVICE_EXTENSION) ((ULONG_PTR)HwDeviceExtension - sizeof(STREAM_DEVICE_EXTENSION));
ASSERT(DeviceExtension->DeviceExtension == HwDeviceExtension);
return DeviceExtension->DmaCommonBuffer;
}

View file

@ -0,0 +1,194 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/legacy/stream/filter.c
* PURPOSE: filter instance handling
* PROGRAMMER: Johannes Anderwald
*/
#include "stream.h"
NTSTATUS
NTAPI
FilterDispatch_fnDeviceIoControl(
PDEVICE_OBJECT DeviceObject,
PIRP Irp)
{
DPRINT1("FilterDispatch Called\n");
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
FilterDispatch_fnClose(
PDEVICE_OBJECT DeviceObject,
PIRP Irp)
{
NTSTATUS Status = STATUS_SUCCESS;
PSTREAM_DEVICE_EXTENSION DeviceExtension;
HW_STREAM_REQUEST_BLOCK_EXT RequestBlock;
/* Get device extension */
DeviceExtension = (PSTREAM_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
if (!DeviceExtension->DriverExtension->Data.FilterInstanceExtensionSize)
{
/* driver supports only one instance */
if (DeviceExtension->InstanceCount)
{
/* there is already one instance open */
return STATUS_UNSUCCESSFUL;
}
}
else
{
/* driver supports more than one filter instance */
RtlZeroMemory(&RequestBlock, sizeof(HW_STREAM_REQUEST_BLOCK_EXT));
/* set up request block */
RequestBlock.Block.Command = SRB_CLOSE_DEVICE_INSTANCE;
RequestBlock.Block.HwDeviceExtension = DeviceExtension->DeviceExtension;
RequestBlock.Block.Irp = Irp;
KeInitializeEvent(&RequestBlock.Event, SynchronizationEvent, FALSE);
/*FIXME SYNCHRONIZATION */
/* Send the request */
DeviceExtension->DriverExtension->Data.HwReceivePacket((PHW_STREAM_REQUEST_BLOCK)&RequestBlock);
if (RequestBlock.Block.Status == STATUS_PENDING)
{
/* Wait for the request */
KeWaitForSingleObject(&RequestBlock.Event, Executive, KernelMode, FALSE, NULL);
}
}
/* Increment total instance count */
InterlockedDecrement(&DeviceExtension->InstanceCount);
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
static KSDISPATCH_TABLE DispatchTable =
{
FilterDispatch_fnDeviceIoControl,
KsDispatchInvalidDeviceRequest,
KsDispatchInvalidDeviceRequest,
KsDispatchInvalidDeviceRequest,
FilterDispatch_fnClose,
NULL,
NULL,
NULL,
NULL,
NULL
};
NTSTATUS
InitializeFilterWithKs(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
NTSTATUS Status;
PSTREAM_DEVICE_EXTENSION DeviceExtension;
KSOBJECT_HEADER ObjectHeader;
PKSOBJECT_CREATE_ITEM CreateItem;
PIO_STACK_LOCATION IoStack;
HW_STREAM_REQUEST_BLOCK_EXT RequestBlock;
/* Get device extension */
DeviceExtension = (PSTREAM_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
if (!DeviceExtension->DriverExtension->Data.FilterInstanceExtensionSize)
{
/* driver supports only one instance */
if (DeviceExtension->InstanceCount)
{
/* there is already one instance open */
return STATUS_UNSUCCESSFUL;
}
}
else
{
/* driver supports more than one filter instance */
RtlZeroMemory(&RequestBlock, sizeof(HW_STREAM_REQUEST_BLOCK_EXT));
/* set up request block */
RequestBlock.Block.Command = SRB_OPEN_DEVICE_INSTANCE;
RequestBlock.Block.HwDeviceExtension = DeviceExtension->DeviceExtension;
RequestBlock.Block.Irp = Irp;
KeInitializeEvent(&RequestBlock.Event, SynchronizationEvent, FALSE);
/*FIXME SYNCHRONIZATION */
/* Send the request */
DeviceExtension->DriverExtension->Data.HwReceivePacket((PHW_STREAM_REQUEST_BLOCK)&RequestBlock);
if (RequestBlock.Block.Status == STATUS_PENDING)
{
/* Wait for the request */
KeWaitForSingleObject(&RequestBlock.Event, Executive, KernelMode, FALSE, NULL);
}
/* Check for success */
if (!NT_SUCCESS(RequestBlock.Block.Status))
{
/* Resource is not available */
return RequestBlock.Block.Status;
}
}
/* Allocate create item */
CreateItem = ExAllocatePool(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM));
if (!CreateItem)
{
/* not enough memory */
return STATUS_INSUFFICIENT_RESOURCES;
}
/* Zero create item */
RtlZeroMemory(CreateItem, sizeof(KSOBJECT_CREATE_ITEM));
/* Set item class */
RtlInitUnicodeString(&CreateItem->ObjectClass, L"STREAMCLASS");
/* Get current irp stack location */
IoStack = IoGetCurrentIrpStackLocation(Irp);
/* Create Ks streaming object header */
Status = KsAllocateObjectHeader(&ObjectHeader, 1, CreateItem, Irp, &DispatchTable);
if (!NT_SUCCESS(Status))
{
/* Failed to create header */
ExFreePool(CreateItem);
return Status;
}
/* Increment total instance count */
InterlockedIncrement(&DeviceExtension->InstanceCount);
/* Return result */
return Status;
}
NTSTATUS
NTAPI
StreamClassCreateFilter(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
NTSTATUS Status;
DPRINT1("StreamClassCreateFilter Called\n");
/* FIXME Support Pins/Clocks */
/* Init filter */
Status = InitializeFilterWithKs(DeviceObject, Irp);
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}

View file

@ -0,0 +1,56 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/legacy/stream/helper.c
* PURPOSE: irp helper routines
* PROGRAMMER: Johannes Anderwald
*/
#include "stream.h"
NTSTATUS
NTAPI
CompletionRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context)
{
if (Irp->PendingReturned == TRUE)
{
KeSetEvent ((PKEVENT) Context, IO_NO_INCREMENT, FALSE);
}
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS
NTAPI
ForwardIrpSynchronous(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
KEVENT Event;
PSTREAM_DEVICE_EXTENSION DeviceExt;
NTSTATUS Status;
DeviceExt = (PSTREAM_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
/* initialize the notification event */
KeInitializeEvent(&Event, NotificationEvent, FALSE);
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp, CompletionRoutine, (PVOID)&Event, TRUE, TRUE, TRUE);
/* now call the driver */
Status = IoCallDriver(DeviceExt->LowerDeviceObject, Irp);
/* did the request complete yet */
if (Status == STATUS_PENDING)
{
/* not yet, lets wait a bit */
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
Status = Irp->IoStatus.Status;
}
return Status;
}

View file

@ -0,0 +1,465 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/legacy/stream/pnp.c
* PURPOSE: pnp handling
* PROGRAMMER: Johannes Anderwald
*/
#include "stream.h"
VOID
CompleteIrp(
IN PIRP Irp,
IN NTSTATUS Status,
IN ULONG_PTR Information)
{
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = Information;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
VOID
NTAPI
StreamClassReleaseResources(
IN PDEVICE_OBJECT DeviceObject)
{
PSTREAM_DEVICE_EXTENSION DeviceExtension;
PLIST_ENTRY Entry;
PMEMORY_RESOURCE_LIST Mem;
/* Get device extension */
DeviceExtension = (PSTREAM_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
/* Disconnect interrupt */
if (DeviceExtension->Interrupt)
{
IoDisconnectInterrupt(DeviceExtension->Interrupt);
DeviceExtension->Interrupt = NULL;
}
/* Release DmaAdapter */
if (DeviceExtension->DmaAdapter)
{
DeviceExtension->DmaAdapter->DmaOperations->PutDmaAdapter(DeviceExtension->DmaAdapter);
DeviceExtension->DmaAdapter = NULL;
}
/* Release mem mapped I/O */
while(!IsListEmpty(&DeviceExtension->MemoryResourceList))
{
Entry = RemoveHeadList(&DeviceExtension->MemoryResourceList);
Mem = (PMEMORY_RESOURCE_LIST)CONTAINING_RECORD(Entry, MEMORY_RESOURCE_LIST, Entry);
MmUnmapIoSpace(Mem->Start, Mem->Length);
ExFreePool(Entry);
}
}
BOOLEAN
NTAPI
StreamClassSynchronize(
IN PKINTERRUPT Interrupt,
IN PKSYNCHRONIZE_ROUTINE SynchronizeRoutine,
IN PVOID SynchronizeContext)
{
/* This function is used when the driver either implements synchronization on its own
* or if there is no interrupt assigned
*/
return SynchronizeRoutine(SynchronizeContext);
}
VOID
NTAPI
StreamClassInterruptDpc(
IN PKDPC Dpc,
IN PVOID DeferredContext,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2)
{
//TODO
//read/write data
}
BOOLEAN
NTAPI
StreamClassInterruptRoutine(
IN PKINTERRUPT Interrupt,
IN PVOID ServiceContext)
{
BOOLEAN Ret = FALSE;
PSTREAM_DEVICE_EXTENSION DeviceExtension = (PSTREAM_DEVICE_EXTENSION)ServiceContext;
/* Does the driver implement HwInterrupt routine */
if (DeviceExtension->DriverExtension->Data.HwInterrupt)
{
/* Check if the interrupt was coming from this device */
Ret = DeviceExtension->DriverExtension->Data.HwInterrupt(DeviceExtension->DeviceExtension);
if (Ret)
{
/* Interrupt has from this device, schedule a Dpc for us */
KeInsertQueueDpc(&DeviceExtension->InterruptDpc, NULL, NULL);
}
}
/* Return result */
return Ret;
}
NTSTATUS
NTAPI
StreamClassStartDevice(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PHW_STREAM_REQUEST_BLOCK_EXT RequestBlock;
PPORT_CONFIGURATION_INFORMATION Config;
PSTREAM_DEVICE_EXTENSION DeviceExtension;
PIO_STACK_LOCATION IoStack;
PCM_RESOURCE_LIST List;
PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
PSTREAM_CLASS_DRIVER_EXTENSION DriverObjectExtension;
PDMA_ADAPTER Adapter;
DEVICE_DESCRIPTION DeviceDesc;
NTSTATUS Status = STATUS_SUCCESS;
ULONG ResultLength, Index;
BOOLEAN bUseDMA, bUseInterrupt;
ULONG MapRegisters;
KAFFINITY Affinity = 0;
PHW_STREAM_DESCRIPTOR StreamDescriptor;
PACCESS_RANGE Range;
PVOID MappedAddr;
PMEMORY_RESOURCE_LIST Mem;
/* Get current stack location */
IoStack = IoGetCurrentIrpStackLocation(Irp);
/* Get resource list */
List = IoStack->Parameters.StartDevice.AllocatedResourcesTranslated;
/* Calculate request length */
ResultLength = sizeof(HW_STREAM_REQUEST_BLOCK_EXT) + sizeof(PPORT_CONFIGURATION_INFORMATION) + List->List[0].PartialResourceList.Count * sizeof(ACCESS_RANGE);
/* Allocate Request Block */
RequestBlock = ExAllocatePool(NonPagedPool, ResultLength);
if (!RequestBlock)
{
/* Not enough memory */
CompleteIrp(Irp, STATUS_INSUFFICIENT_RESOURCES, 0);
return STATUS_INSUFFICIENT_RESOURCES;
}
/* Get device extension */
DeviceExtension = (PSTREAM_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
/* Get driver object extension */
DriverObjectExtension = IoGetDriverObjectExtension(DeviceObject->DriverObject, (PVOID)StreamClassAddDevice);
/* Zero request block */
RtlZeroMemory(RequestBlock, ResultLength);
/* Locate Config struct */
Config = (PPORT_CONFIGURATION_INFORMATION) (RequestBlock + 1);
Range = (PACCESS_RANGE) (Config + 1);
/* Initialize Request */
RequestBlock->Block.SizeOfThisPacket = sizeof(HW_STREAM_REQUEST_BLOCK);
RequestBlock->Block.Command = SRB_INITIALIZE_DEVICE;
RequestBlock->Block.CommandData.ConfigInfo = Config;
KeInitializeEvent(&RequestBlock->Event, SynchronizationEvent, FALSE);
Config->SizeOfThisPacket = sizeof(PPORT_CONFIGURATION_INFORMATION);
Config->HwDeviceExtension = (PVOID) (DeviceExtension + 1);
Config->ClassDeviceObject = DeviceObject;
Config->PhysicalDeviceObject = DeviceExtension->LowerDeviceObject;
Config->RealPhysicalDeviceObject = DeviceExtension->PhysicalDeviceObject;
Config->AccessRanges = Range;
IoGetDeviceProperty(DeviceObject, DevicePropertyBusNumber, sizeof(ULONG), (PVOID)&Config->SystemIoBusNumber, &ResultLength);
IoGetDeviceProperty(DeviceObject, DevicePropertyLegacyBusType, sizeof(INTERFACE_TYPE), (PVOID)&Config->AdapterInterfaceType, &ResultLength);
/* Get resource list */
List = IoStack->Parameters.StartDevice.AllocatedResourcesTranslated;
/* Scan the translated resources */
bUseDMA = FALSE;
bUseInterrupt = FALSE;
Range = (PACCESS_RANGE) (Config + 1);
for(Index = 0; Index < List->List[0].PartialResourceList.Count; Index++)
{
/* Locate partial descriptor */
Descriptor = &List->List[0].PartialResourceList.PartialDescriptors[Index];
switch(Descriptor->Type)
{
case CmResourceTypePort:
{
/* Store resource information in AccessRange struct */
Range[Config->NumberOfAccessRanges].RangeLength = Descriptor->u.Port.Length;
Range[Config->NumberOfAccessRanges].RangeStart.QuadPart = Descriptor->u.Port.Start.QuadPart;
Range[Config->NumberOfAccessRanges].RangeInMemory = FALSE;
Config->NumberOfAccessRanges++;
break;
}
case CmResourceTypeInterrupt:
{
/* Store resource information */
Config->BusInterruptLevel = Descriptor->u.Interrupt.Level;
Config->BusInterruptVector = Descriptor->u.Interrupt.Vector;
Config->InterruptMode = Descriptor->Flags;
Affinity = Descriptor->u.Interrupt.Affinity;
bUseInterrupt = TRUE;
break;
}
case CmResourceTypeMemory:
{
Mem = ExAllocatePool(NonPagedPool, sizeof(MEMORY_RESOURCE_LIST));
MappedAddr = MmMapIoSpace(Descriptor->u.Memory.Start, Descriptor->u.Memory.Length, MmNonCached);
if (!MappedAddr || !Mem)
{
if (Mem)
{
/* Release Memory resource descriptor */
ExFreePool(Mem);
}
if (MappedAddr)
{
/* Release mem mapped I/O */
MmUnmapIoSpace(MappedAddr, Descriptor->u.Memory.Length);
}
/* Release resources */
StreamClassReleaseResources(DeviceObject);
/* Complete irp */
CompleteIrp(Irp, STATUS_INSUFFICIENT_RESOURCES, 0);
ExFreePool(RequestBlock);
return STATUS_INSUFFICIENT_RESOURCES;
}
/* Store range for driver */
Range[Config->NumberOfAccessRanges].RangeLength = Descriptor->u.Memory.Length;
Range[Config->NumberOfAccessRanges].RangeStart.QuadPart = Descriptor->u.Memory.Start.QuadPart;
Range[Config->NumberOfAccessRanges].RangeInMemory = TRUE;
Config->NumberOfAccessRanges++;
/* Initialize Memory resource descriptor */
Mem->Length = Descriptor->u.Memory.Length;
Mem->Start = MappedAddr;
InsertTailList(&DeviceExtension->MemoryResourceList, &Mem->Entry);
break;
}
case CmResourceTypeDma:
{
bUseDMA = TRUE;
Config->DmaChannel = Descriptor->u.Dma.Channel;
break;
}
}
}
if (!!bUseInterrupt || DriverObjectExtension->Data.HwInterrupt == NULL || Config->BusInterruptLevel == 0 || Config->BusInterruptVector == 0)
{
/* requirements not satisfied */
DeviceExtension->SynchronizeFunction = StreamClassSynchronize;
}
else
{
/* use real sync routine */
DeviceExtension->SynchronizeFunction = KeSynchronizeExecution;
/* connect interrupt */
Status = IoConnectInterrupt(&DeviceExtension->Interrupt,
StreamClassInterruptRoutine,
(PVOID)DeviceExtension,
NULL,
Config->BusInterruptVector,
Config->BusInterruptLevel,
Config->BusInterruptLevel,
Config->InterruptMode,
TRUE,
Affinity,
FALSE);
if (!NT_SUCCESS(Status))
{
/* Release resources */
StreamClassReleaseResources(DeviceObject);
/* Failed to connect interrupt */
CompleteIrp(Irp, Status, 0);
/* Release request block */
ExFreePool(RequestBlock);
return Status;
}
/* store interrupt object */
Config->InterruptObject = DeviceExtension->Interrupt;
}
/* does the device use DMA */
if (bUseDMA && DriverObjectExtension->Data.BusMasterDMA)
{
/* Zero device description */
RtlZeroMemory(&DeviceDesc, sizeof(DEVICE_DESCRIPTION));
DeviceDesc.Version = DEVICE_DESCRIPTION_VERSION;
DeviceDesc.Master = TRUE;
DeviceDesc.ScatterGather = TRUE;
DeviceDesc.AutoInitialize = FALSE;
DeviceDesc.DmaChannel = Config->DmaChannel;
DeviceDesc.InterfaceType = Config->AdapterInterfaceType;
DeviceDesc.DmaWidth = Width32Bits;
DeviceDesc.DmaSpeed = Compatible;
DeviceDesc.MaximumLength = (ULONG)-1;
DeviceDesc.Dma32BitAddresses = DriverObjectExtension->Data.Dma24BitAddresses;
Adapter = IoGetDmaAdapter(DeviceExtension->PhysicalDeviceObject, &DeviceDesc, &MapRegisters);
if (!Adapter)
{
/* Failed to claim DMA Adapter */
CompleteIrp(Irp, Status, 0);
/* Release resources */
StreamClassReleaseResources(DeviceObject);
/* Release request block */
ExFreePool(RequestBlock);
return Status;
}
if (DeviceExtension->DriverExtension->Data.DmaBufferSize)
{
DeviceExtension->DmaCommonBuffer = Adapter->DmaOperations->AllocateCommonBuffer(Adapter, DeviceExtension->DriverExtension->Data.DmaBufferSize, &DeviceExtension->DmaPhysicalAddress, FALSE);
if (!DeviceExtension->DmaCommonBuffer)
{
/* Failed to allocate a common buffer */
CompleteIrp(Irp, Status, 0);
/* Release resources */
StreamClassReleaseResources(DeviceObject);
/* Release request block */
ExFreePool(RequestBlock);
return Status;
}
}
DeviceExtension->MapRegisters = MapRegisters;
DeviceExtension->DmaAdapter = Adapter;
Config->DmaAdapterObject = (PADAPTER_OBJECT)Adapter;
}
/* First forward the request to lower attached device object */
Status = ForwardIrpSynchronous(DeviceObject, Irp);
if (!NT_SUCCESS(Status))
{
/* Failed to start lower devices */
CompleteIrp(Irp, Status, 0);
/* Release resources */
StreamClassReleaseResources(DeviceObject);
/* Release request block */
ExFreePool(RequestBlock);
return Status;
}
Config->Irp = Irp;
/* FIXME SYNCHRONIZATION */
/* Send the request */
DriverObjectExtension->Data.HwReceivePacket((PHW_STREAM_REQUEST_BLOCK)RequestBlock);
if (RequestBlock->Block.Status == STATUS_PENDING)
{
/* Request is pending, wait for result */
KeWaitForSingleObject(&RequestBlock->Event, Executive, KernelMode, FALSE, NULL);
/* Get final status code */
Status = RequestBlock->Block.Status;
}
/* Copy stream descriptor size */
DeviceExtension->StreamDescriptorSize = Config->StreamDescriptorSize;
/* check if the request has succeeded or if stream size is valid*/
if (!NT_SUCCESS(Status)|| !Config->StreamDescriptorSize)
{
/* Failed to start device */
CompleteIrp(Irp, Status, 0);
/* Release resources */
StreamClassReleaseResources(DeviceObject);
/* Release request block */
ExFreePool(RequestBlock);
return Status;
}
/* Allocate a stream Descriptor */
StreamDescriptor = ExAllocatePool(NonPagedPool, DeviceExtension->StreamDescriptorSize);
if (!StreamDescriptor)
{
/* Not enough memory */
CompleteIrp(Irp, STATUS_INSUFFICIENT_RESOURCES, 0);
/* Release resources */
StreamClassReleaseResources(DeviceObject);
/* Release request block */
ExFreePool(RequestBlock);
return STATUS_INSUFFICIENT_RESOURCES;
}
/* Zero stream descriptor */
RtlZeroMemory(StreamDescriptor, DeviceExtension->StreamDescriptorSize);
/* Setup get stream info struct */
RequestBlock->Block.Command = SRB_GET_STREAM_INFO;
RequestBlock->Block.CommandData.StreamBuffer = StreamDescriptor;
KeResetEvent(&RequestBlock->Event);
/* send the request */
DriverObjectExtension->Data.HwReceivePacket((PHW_STREAM_REQUEST_BLOCK)RequestBlock);
if (RequestBlock->Block.Status == STATUS_PENDING)
{
/* Request is pending, wait for result */
KeWaitForSingleObject(&RequestBlock->Event, Executive, KernelMode, FALSE, NULL);
/* Get final status code */
Status = RequestBlock->Block.Status;
}
if (NT_SUCCESS(Status))
{
/* store stream descriptor */
DeviceExtension->StreamDescriptor = StreamDescriptor;
}
else
{
/* cleanup resources */
ExFreePool(StreamDescriptor);
}
ExFreePool(RequestBlock);
/* Complete Irp */
CompleteIrp(Irp, Status, 0);
/* Return result */
return Status;
}
NTSTATUS
NTAPI
StreamClassPnp(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PIO_STACK_LOCATION IoStack;
/* Get current irp stack location */
IoStack = IoGetCurrentIrpStackLocation(Irp);
switch (IoStack->MinorFunction)
{
case IRP_MN_START_DEVICE:
{
return StreamClassStartDevice(DeviceObject, Irp);
}
}
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_NOT_SUPPORTED;
}

View file

@ -0,0 +1,140 @@
#ifndef STREAM_H__
#define STREAM_H__
#include <strmini.h>
#define YDEBUG
#include <debug.h>
#define STREAMDEBUG_LEVEL DebugLevelMaximum
typedef BOOLEAN (NTAPI *SYNCHRONIZE_FUNC) (IN PKINTERRUPT Interrupt, IN PKSYNCHRONIZE_ROUTINE SynchronizeRoutine, IN PVOID SynchronizeContext);
typedef struct
{
HW_INITIALIZATION_DATA Data;
}STREAM_CLASS_DRIVER_EXTENSION, *PSTREAM_CLASS_DRIVER_EXTENSION;
typedef struct
{
LIST_ENTRY Entry;
PVOID Start;
ULONG Length;
}MEMORY_RESOURCE_LIST, *PMEMORY_RESOURCE_LIST;
typedef struct
{
KSDEVICE_HEADER Header;
PDEVICE_OBJECT LowerDeviceObject;
PDEVICE_OBJECT PhysicalDeviceObject;
SYNCHRONIZE_FUNC SynchronizeFunction;
ULONG MapRegisters;
PDMA_ADAPTER DmaAdapter;
PVOID DmaCommonBuffer;
PHYSICAL_ADDRESS DmaPhysicalAddress;
PKINTERRUPT Interrupt;
KDPC InterruptDpc;
LIST_ENTRY MemoryResourceList;
ULONG StreamDescriptorSize;
PHW_STREAM_DESCRIPTOR StreamDescriptor;
PSTREAM_CLASS_DRIVER_EXTENSION DriverExtension;
PVOID DeviceExtension;
LONG InstanceCount;
}STREAM_DEVICE_EXTENSION, *PSTREAM_DEVICE_EXTENSION;
typedef struct
{
HW_STREAM_REQUEST_BLOCK Block;
KEVENT Event;
}HW_STREAM_REQUEST_BLOCK_EXT, *PHW_STREAM_REQUEST_BLOCK_EXT;
NTSTATUS
NTAPI
StreamClassCreateFilter(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS
NTAPI
StreamClassPnp(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS
NTAPI
StreamClassPower(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS
NTAPI
StreamClassSystemControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS
NTAPI
StreamClassCleanup(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS
NTAPI
StreamClassFlushBuffers(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS
NTAPI
StreamClassDeviceControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS
NTAPI
StreamClassAddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject);
NTSTATUS
NTAPI
ForwardIrpSynchronous(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
BOOLEAN
NTAPI
StreamClassSynchronize(
IN PKINTERRUPT Interrupt,
IN PKSYNCHRONIZE_ROUTINE SynchronizeRoutine,
IN PVOID SynchronizeContext);
BOOLEAN
NTAPI
StreamClassInterruptRoutine(
IN PKINTERRUPT Interrupt,
IN PVOID ServiceContext);
VOID
NTAPI
StreamClassInterruptDpc(
IN PKDPC Dpc,
IN PVOID DeferredContext,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2);
VOID
CompleteIrp(
IN PIRP Irp,
IN NTSTATUS Status,
IN ULONG_PTR Information);
#endif

View file

@ -0,0 +1,17 @@
<?xml version="1.0"?>
<!DOCTYPE module SYSTEM "../../../../../tools/rbuild/project.dtd">
<module name="stream" type="kernelmodedriver" installbase="system32/drivers" installname="stream.sys" entrypoint="0">
<include base="stream">.</include>
<define name="_COMDDK_" />
<importlibrary definition="stream.spec" />
<library>ntoskrnl</library>
<library>ks</library>
<library>pseh</library>
<file>control.c</file>
<file>driver.c</file>
<file>dll.c</file>
<file>filter.c</file>
<file>helper.c</file>
<file>pnp.c</file>
<file>stream.rc</file>
</module>

View file

@ -0,0 +1,5 @@
#define REACTOS_VERSION_DLL
#define REACTOS_STR_FILE_DESCRIPTION "WDM CODEC Class Device Driver 2.0\0"
#define REACTOS_STR_INTERNAL_NAME "stream.sys\0"
#define REACTOS_STR_ORIGINAL_FILENAME "stream.sys\0"
#include <reactos/version.rc>

View file

@ -0,0 +1,8 @@
@ stdcall DllInitialize(long)
@ stdcall DllUnload()
@ stdcall StreamClassRegisterAdapter(ptr ptr ptr)
@ stdcall StreamClassReenumerateStreams(ptr long)
@ stdcall StreamClassDebugAssert(long long ptr long)
@ cdecl StreamClassDebugPrint (long str)
@ cdecl StreamClassDeviceNotification(long ptr)
@ stdcall StreamClassGetDmaBuffer(ptr)