/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS Kernel Streaming * FILE: drivers/wdm/audio/hdaudbus/hdaudbus.cpp * PURPOSE: HDA Driver Entry * PROGRAMMER: Johannes Anderwald */ #include "hdaudbus.h" DRIVER_DISPATCH HDA_Pnp; DRIVER_ADD_DEVICE HDA_AddDevice; extern "C" DRIVER_INITIALIZE DriverEntry; PVOID AllocateItem( _In_ POOL_TYPE PoolType, _In_ SIZE_T NumberOfBytes) { PVOID Item = ExAllocatePoolWithTag(PoolType, NumberOfBytes, TAG_HDA); if (!Item) return Item; RtlZeroMemory(Item, NumberOfBytes); return Item; } VOID FreeItem( __drv_freesMem(Mem) PVOID Item) { ExFreePool(Item); } NTSTATUS NTAPI HDA_SyncForwardIrpCompletionRoutine( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context) { if (Irp->PendingReturned) { KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE); } return STATUS_MORE_PROCESSING_REQUIRED; } NTSTATUS NTAPI HDA_SyncForwardIrp( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { KEVENT Event; NTSTATUS Status; /* Initialize event */ KeInitializeEvent(&Event, NotificationEvent, FALSE); /* Copy irp stack location */ IoCopyCurrentIrpStackLocationToNext(Irp); /* Set completion routine */ IoSetCompletionRoutine(Irp, HDA_SyncForwardIrpCompletionRoutine, &Event, TRUE, TRUE, TRUE); /* Call driver */ Status = IoCallDriver(DeviceObject, Irp); /* Check if pending */ if (Status == STATUS_PENDING) { /* Wait for the request to finish */ KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); /* Copy status code */ Status = Irp->IoStatus.Status; } /* Done */ return Status; } NTSTATUS HDA_FdoPnp( _In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp) { NTSTATUS Status; PIO_STACK_LOCATION IoStack; PHDA_FDO_DEVICE_EXTENSION FDODeviceExtension; FDODeviceExtension = static_cast(DeviceObject->DeviceExtension); IoStack = IoGetCurrentIrpStackLocation(Irp); switch (IoStack->MinorFunction) { case IRP_MN_START_DEVICE: Status = HDA_FDOStartDevice(DeviceObject, Irp); break; case IRP_MN_QUERY_DEVICE_RELATIONS: /* handle bus device relations */ if (IoStack->Parameters.QueryDeviceRelations.Type == BusRelations) { Status = HDA_FDOQueryBusRelations(DeviceObject, Irp); } else { Status = Irp->IoStatus.Status; } break; default: /* get default status */ Status = Irp->IoStatus.Status; break; } Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return Status; } NTSTATUS HDA_PdoPnp( _In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp) { NTSTATUS Status; PIO_STACK_LOCATION IoStack; PDEVICE_RELATIONS DeviceRelation; IoStack = IoGetCurrentIrpStackLocation(Irp); switch (IoStack->MinorFunction) { case IRP_MN_START_DEVICE: /* no op for pdo */ Status = STATUS_SUCCESS; break; case IRP_MN_QUERY_BUS_INFORMATION: /* query bus information */ Status = HDA_PDOQueryBusInformation(Irp); break; case IRP_MN_QUERY_PNP_DEVICE_STATE: /* query pnp state */ Status = HDA_PDOQueryBusDevicePnpState(Irp); break; case IRP_MN_QUERY_DEVICE_RELATIONS: if (IoStack->Parameters.QueryDeviceRelations.Type == TargetDeviceRelation) { /* handle target device relations */ ASSERT(IoStack->Parameters.QueryDeviceRelations.Type == TargetDeviceRelation); ASSERT(Irp->IoStatus.Information == 0); /* allocate device relation */ DeviceRelation = (PDEVICE_RELATIONS)AllocateItem(PagedPool, sizeof(DEVICE_RELATIONS)); if (DeviceRelation) { DeviceRelation->Count = 1; DeviceRelation->Objects[0] = DeviceObject; /* reference self */ ObReferenceObject(DeviceObject); /* store result */ Irp->IoStatus.Information = (ULONG_PTR)DeviceRelation; /* done */ Status = STATUS_SUCCESS; } else { /* no memory */ Status = STATUS_INSUFFICIENT_RESOURCES; } } break; case IRP_MN_QUERY_CAPABILITIES: /* query capabilities */ Status = HDA_PDOQueryBusDeviceCapabilities(Irp); break; case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: /* no op */ Status = STATUS_SUCCESS; break; case IRP_MN_QUERY_RESOURCES: /* no op */ Status = STATUS_SUCCESS; break; case IRP_MN_QUERY_ID: Status = HDA_PDOQueryId(DeviceObject, Irp); break; case IRP_MN_QUERY_DEVICE_TEXT: Status = HDA_PDOHandleQueryDeviceText(Irp); break; case IRP_MN_QUERY_INTERFACE: Status = HDA_PDOHandleQueryInterface(DeviceObject, Irp); break; default: /* get default status */ Status = Irp->IoStatus.Status; break; } Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return Status; } NTSTATUS NTAPI HDA_Pnp( _In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp) { PHDA_FDO_DEVICE_EXTENSION FDODeviceExtension; FDODeviceExtension = static_cast(DeviceObject->DeviceExtension); if (FDODeviceExtension->IsFDO) { return HDA_FdoPnp(DeviceObject, Irp); } else { return HDA_PdoPnp(DeviceObject, Irp); } } NTSTATUS NTAPI HDA_AddDevice( _In_ PDRIVER_OBJECT DriverObject, _In_ PDEVICE_OBJECT PhysicalDeviceObject) { PDEVICE_OBJECT DeviceObject; PHDA_FDO_DEVICE_EXTENSION DeviceExtension; NTSTATUS Status; /* create device object */ Status = IoCreateDevice(DriverObject, sizeof(HDA_FDO_DEVICE_EXTENSION), NULL, FILE_DEVICE_BUS_EXTENDER, 0, FALSE, &DeviceObject); if (!NT_SUCCESS(Status)) { /* failed */ return Status; } /* get device extension*/ DeviceExtension = (PHDA_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; /* init device extension*/ DeviceExtension->IsFDO = TRUE; DeviceExtension->LowerDevice = IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject); RtlZeroMemory(DeviceExtension->Codecs, sizeof(PHDA_CODEC_ENTRY) * (HDA_MAX_CODECS + 1)); /* set device flags */ DeviceObject->Flags |= DO_POWER_PAGABLE; return Status; } extern "C" { NTSTATUS NTAPI DriverEntry( _In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPathName) { DriverObject->DriverExtension->AddDevice = HDA_AddDevice; DriverObject->MajorFunction[IRP_MJ_PNP] = HDA_Pnp; return STATUS_SUCCESS; } }