Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenpnp.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS Kernel Streaming 00004 * FILE: drivers/wdm/audio/legacy/stream/pnp.c 00005 * PURPOSE: pnp handling 00006 * PROGRAMMER: Johannes Anderwald 00007 */ 00008 00009 #include "stream.h" 00010 00011 VOID 00012 CompleteIrp( 00013 IN PIRP Irp, 00014 IN NTSTATUS Status, 00015 IN ULONG_PTR Information) 00016 { 00017 Irp->IoStatus.Status = Status; 00018 Irp->IoStatus.Information = Information; 00019 IoCompleteRequest(Irp, IO_NO_INCREMENT); 00020 } 00021 00022 VOID 00023 NTAPI 00024 StreamClassReleaseResources( 00025 IN PDEVICE_OBJECT DeviceObject) 00026 { 00027 PSTREAM_DEVICE_EXTENSION DeviceExtension; 00028 PLIST_ENTRY Entry; 00029 PMEMORY_RESOURCE_LIST Mem; 00030 00031 /* Get device extension */ 00032 DeviceExtension = (PSTREAM_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 00033 00034 /* Disconnect interrupt */ 00035 if (DeviceExtension->Interrupt) 00036 { 00037 IoDisconnectInterrupt(DeviceExtension->Interrupt); 00038 DeviceExtension->Interrupt = NULL; 00039 } 00040 00041 /* Release DmaAdapter */ 00042 if (DeviceExtension->DmaAdapter) 00043 { 00044 DeviceExtension->DmaAdapter->DmaOperations->PutDmaAdapter(DeviceExtension->DmaAdapter); 00045 DeviceExtension->DmaAdapter = NULL; 00046 } 00047 00048 /* Release mem mapped I/O */ 00049 while(!IsListEmpty(&DeviceExtension->MemoryResourceList)) 00050 { 00051 Entry = RemoveHeadList(&DeviceExtension->MemoryResourceList); 00052 Mem = (PMEMORY_RESOURCE_LIST)CONTAINING_RECORD(Entry, MEMORY_RESOURCE_LIST, Entry); 00053 00054 MmUnmapIoSpace(Mem->Start, Mem->Length); 00055 ExFreePool(Entry); 00056 } 00057 } 00058 00059 BOOLEAN 00060 NTAPI 00061 StreamClassSynchronize( 00062 IN PKINTERRUPT Interrupt, 00063 IN PKSYNCHRONIZE_ROUTINE SynchronizeRoutine, 00064 IN PVOID SynchronizeContext) 00065 { 00066 /* This function is used when the driver either implements synchronization on its own 00067 * or if there is no interrupt assigned 00068 */ 00069 return SynchronizeRoutine(SynchronizeContext); 00070 } 00071 00072 VOID 00073 NTAPI 00074 StreamClassInterruptDpc( 00075 IN PKDPC Dpc, 00076 IN PVOID DeferredContext, 00077 IN PVOID SystemArgument1, 00078 IN PVOID SystemArgument2) 00079 { 00080 //TODO 00081 //read/write data 00082 } 00083 00084 00085 BOOLEAN 00086 NTAPI 00087 StreamClassInterruptRoutine( 00088 IN PKINTERRUPT Interrupt, 00089 IN PVOID ServiceContext) 00090 { 00091 BOOLEAN Ret = FALSE; 00092 PSTREAM_DEVICE_EXTENSION DeviceExtension = (PSTREAM_DEVICE_EXTENSION)ServiceContext; 00093 00094 /* Does the driver implement HwInterrupt routine */ 00095 if (DeviceExtension->DriverExtension->Data.HwInterrupt) 00096 { 00097 /* Check if the interrupt was coming from this device */ 00098 Ret = DeviceExtension->DriverExtension->Data.HwInterrupt(DeviceExtension->DeviceExtension); 00099 if (Ret) 00100 { 00101 /* Interrupt has from this device, schedule a Dpc for us */ 00102 KeInsertQueueDpc(&DeviceExtension->InterruptDpc, NULL, NULL); 00103 } 00104 } 00105 /* Return result */ 00106 return Ret; 00107 } 00108 00109 00110 00111 NTSTATUS 00112 NTAPI 00113 StreamClassStartDevice( 00114 IN PDEVICE_OBJECT DeviceObject, 00115 IN PIRP Irp) 00116 { 00117 PHW_STREAM_REQUEST_BLOCK_EXT RequestBlock; 00118 PPORT_CONFIGURATION_INFORMATION Config; 00119 PSTREAM_DEVICE_EXTENSION DeviceExtension; 00120 PIO_STACK_LOCATION IoStack; 00121 PCM_RESOURCE_LIST List; 00122 PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor; 00123 PSTREAM_CLASS_DRIVER_EXTENSION DriverObjectExtension; 00124 PDMA_ADAPTER Adapter; 00125 DEVICE_DESCRIPTION DeviceDesc; 00126 NTSTATUS Status = STATUS_SUCCESS; 00127 ULONG ResultLength, Index; 00128 BOOLEAN bUseDMA, bUseInterrupt; 00129 ULONG MapRegisters; 00130 KAFFINITY Affinity = 0; 00131 PHW_STREAM_DESCRIPTOR StreamDescriptor; 00132 PACCESS_RANGE Range; 00133 PVOID MappedAddr; 00134 PMEMORY_RESOURCE_LIST Mem; 00135 00136 /* Get current stack location */ 00137 IoStack = IoGetCurrentIrpStackLocation(Irp); 00138 00139 /* Get resource list */ 00140 List = IoStack->Parameters.StartDevice.AllocatedResourcesTranslated; 00141 /* Calculate request length */ 00142 ResultLength = sizeof(HW_STREAM_REQUEST_BLOCK_EXT) + sizeof(PPORT_CONFIGURATION_INFORMATION) + List->List[0].PartialResourceList.Count * sizeof(ACCESS_RANGE); 00143 00144 /* Allocate Request Block */ 00145 RequestBlock = ExAllocatePool(NonPagedPool, ResultLength); 00146 00147 if (!RequestBlock) 00148 { 00149 /* Not enough memory */ 00150 CompleteIrp(Irp, STATUS_INSUFFICIENT_RESOURCES, 0); 00151 return STATUS_INSUFFICIENT_RESOURCES; 00152 } 00153 00154 /* Get device extension */ 00155 DeviceExtension = (PSTREAM_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 00156 00157 /* Get driver object extension */ 00158 DriverObjectExtension = IoGetDriverObjectExtension(DeviceObject->DriverObject, (PVOID)StreamClassAddDevice); 00159 00160 /* sanity checks */ 00161 ASSERT(DeviceExtension); 00162 ASSERT(DriverObjectExtension); 00163 00164 /* Zero request block */ 00165 RtlZeroMemory(RequestBlock, ResultLength); 00166 00167 /* Locate Config struct */ 00168 Config = (PPORT_CONFIGURATION_INFORMATION) (RequestBlock + 1); 00169 Range = (PACCESS_RANGE) (Config + 1); 00170 00171 /* Initialize Request */ 00172 RequestBlock->Block.SizeOfThisPacket = sizeof(HW_STREAM_REQUEST_BLOCK); 00173 RequestBlock->Block.Command = SRB_INITIALIZE_DEVICE; 00174 RequestBlock->Block.CommandData.ConfigInfo = Config; 00175 KeInitializeEvent(&RequestBlock->Event, SynchronizationEvent, FALSE); 00176 00177 Config->SizeOfThisPacket = sizeof(PPORT_CONFIGURATION_INFORMATION); 00178 Config->HwDeviceExtension = (PVOID) (DeviceExtension + 1); 00179 Config->ClassDeviceObject = DeviceObject; 00180 Config->PhysicalDeviceObject = DeviceExtension->LowerDeviceObject; 00181 Config->RealPhysicalDeviceObject = DeviceExtension->PhysicalDeviceObject; 00182 Config->AccessRanges = Range; 00183 00184 IoGetDeviceProperty(DeviceObject, DevicePropertyBusNumber, sizeof(ULONG), (PVOID)&Config->SystemIoBusNumber, &ResultLength); 00185 IoGetDeviceProperty(DeviceObject, DevicePropertyLegacyBusType, sizeof(INTERFACE_TYPE), (PVOID)&Config->AdapterInterfaceType, &ResultLength); 00186 00187 /* Get resource list */ 00188 List = IoStack->Parameters.StartDevice.AllocatedResourcesTranslated; 00189 00190 /* Scan the translated resources */ 00191 bUseDMA = FALSE; 00192 bUseInterrupt = FALSE; 00193 00194 Range = (PACCESS_RANGE) (Config + 1); 00195 00196 for(Index = 0; Index < List->List[0].PartialResourceList.Count; Index++) 00197 { 00198 /* Locate partial descriptor */ 00199 Descriptor = &List->List[0].PartialResourceList.PartialDescriptors[Index]; 00200 00201 switch(Descriptor->Type) 00202 { 00203 case CmResourceTypePort: 00204 { 00205 /* Store resource information in AccessRange struct */ 00206 Range[Config->NumberOfAccessRanges].RangeLength = Descriptor->u.Port.Length; 00207 Range[Config->NumberOfAccessRanges].RangeStart.QuadPart = Descriptor->u.Port.Start.QuadPart; 00208 Range[Config->NumberOfAccessRanges].RangeInMemory = FALSE; 00209 Config->NumberOfAccessRanges++; 00210 break; 00211 } 00212 case CmResourceTypeInterrupt: 00213 { 00214 /* Store resource information */ 00215 Config->BusInterruptLevel = Descriptor->u.Interrupt.Level; 00216 Config->BusInterruptVector = Descriptor->u.Interrupt.Vector; 00217 Config->InterruptMode = Descriptor->Flags; 00218 Affinity = Descriptor->u.Interrupt.Affinity; 00219 bUseInterrupt = TRUE; 00220 break; 00221 } 00222 case CmResourceTypeMemory: 00223 { 00224 Mem = ExAllocatePool(NonPagedPool, sizeof(MEMORY_RESOURCE_LIST)); 00225 MappedAddr = MmMapIoSpace(Descriptor->u.Memory.Start, Descriptor->u.Memory.Length, MmNonCached); 00226 if (!MappedAddr || !Mem) 00227 { 00228 if (Mem) 00229 { 00230 /* Release Memory resource descriptor */ 00231 ExFreePool(Mem); 00232 } 00233 00234 if (MappedAddr) 00235 { 00236 /* Release mem mapped I/O */ 00237 MmUnmapIoSpace(MappedAddr, Descriptor->u.Memory.Length); 00238 } 00239 00240 /* Release resources */ 00241 StreamClassReleaseResources(DeviceObject); 00242 /* Complete irp */ 00243 CompleteIrp(Irp, STATUS_INSUFFICIENT_RESOURCES, 0); 00244 ExFreePool(RequestBlock); 00245 return STATUS_INSUFFICIENT_RESOURCES; 00246 } 00247 /* Store range for driver */ 00248 Range[Config->NumberOfAccessRanges].RangeLength = Descriptor->u.Memory.Length; 00249 Range[Config->NumberOfAccessRanges].RangeStart.QuadPart = Descriptor->u.Memory.Start.QuadPart; 00250 Range[Config->NumberOfAccessRanges].RangeInMemory = TRUE; 00251 Config->NumberOfAccessRanges++; 00252 /* Initialize Memory resource descriptor */ 00253 Mem->Length = Descriptor->u.Memory.Length; 00254 Mem->Start = MappedAddr; 00255 InsertTailList(&DeviceExtension->MemoryResourceList, &Mem->Entry); 00256 break; 00257 } 00258 case CmResourceTypeDma: 00259 { 00260 bUseDMA = TRUE; 00261 Config->DmaChannel = Descriptor->u.Dma.Channel; 00262 break; 00263 } 00264 } 00265 } 00266 00267 if (!bUseInterrupt || DriverObjectExtension->Data.HwInterrupt == NULL || Config->BusInterruptLevel == 0 || Config->BusInterruptVector == 0) 00268 { 00269 /* requirements not satisfied */ 00270 DeviceExtension->SynchronizeFunction = StreamClassSynchronize; 00271 } 00272 else 00273 { 00274 /* use real sync routine */ 00275 DeviceExtension->SynchronizeFunction = KeSynchronizeExecution; 00276 00277 /* connect interrupt */ 00278 Status = IoConnectInterrupt(&DeviceExtension->Interrupt, 00279 StreamClassInterruptRoutine, 00280 (PVOID)DeviceExtension, 00281 NULL, 00282 Config->BusInterruptVector, 00283 Config->BusInterruptLevel, 00284 Config->BusInterruptLevel, 00285 Config->InterruptMode, 00286 TRUE, 00287 Affinity, 00288 FALSE); 00289 if (!NT_SUCCESS(Status)) 00290 { 00291 /* Release resources */ 00292 StreamClassReleaseResources(DeviceObject); 00293 /* Failed to connect interrupt */ 00294 CompleteIrp(Irp, Status, 0); 00295 /* Release request block */ 00296 ExFreePool(RequestBlock); 00297 return Status; 00298 } 00299 00300 /* store interrupt object */ 00301 Config->InterruptObject = DeviceExtension->Interrupt; 00302 } 00303 00304 /* does the device use DMA */ 00305 if (bUseDMA && DriverObjectExtension->Data.BusMasterDMA) 00306 { 00307 /* Zero device description */ 00308 RtlZeroMemory(&DeviceDesc, sizeof(DEVICE_DESCRIPTION)); 00309 00310 DeviceDesc.Version = DEVICE_DESCRIPTION_VERSION; 00311 DeviceDesc.Master = TRUE; 00312 DeviceDesc.ScatterGather = TRUE; 00313 DeviceDesc.AutoInitialize = FALSE; 00314 DeviceDesc.DmaChannel = Config->DmaChannel; 00315 DeviceDesc.InterfaceType = Config->AdapterInterfaceType; 00316 DeviceDesc.DmaWidth = Width32Bits; 00317 DeviceDesc.DmaSpeed = Compatible; 00318 DeviceDesc.MaximumLength = MAXULONG; 00319 DeviceDesc.Dma32BitAddresses = DriverObjectExtension->Data.Dma24BitAddresses; 00320 00321 Adapter = IoGetDmaAdapter(DeviceExtension->PhysicalDeviceObject, &DeviceDesc, &MapRegisters); 00322 if (!Adapter) 00323 { 00324 /* Failed to claim DMA Adapter */ 00325 CompleteIrp(Irp, Status, 0); 00326 /* Release resources */ 00327 StreamClassReleaseResources(DeviceObject); 00328 /* Release request block */ 00329 ExFreePool(RequestBlock); 00330 return Status; 00331 } 00332 00333 if (DeviceExtension->DriverExtension->Data.DmaBufferSize) 00334 { 00335 DeviceExtension->DmaCommonBuffer = Adapter->DmaOperations->AllocateCommonBuffer(Adapter, DeviceExtension->DriverExtension->Data.DmaBufferSize, &DeviceExtension->DmaPhysicalAddress, FALSE); 00336 if (!DeviceExtension->DmaCommonBuffer) 00337 { 00338 /* Failed to allocate a common buffer */ 00339 CompleteIrp(Irp, Status, 0); 00340 /* Release resources */ 00341 StreamClassReleaseResources(DeviceObject); 00342 /* Release request block */ 00343 ExFreePool(RequestBlock); 00344 return Status; 00345 } 00346 } 00347 00348 00349 DeviceExtension->MapRegisters = MapRegisters; 00350 DeviceExtension->DmaAdapter = Adapter; 00351 Config->DmaAdapterObject = (PADAPTER_OBJECT)Adapter; 00352 } 00353 00354 00355 /* First forward the request to lower attached device object */ 00356 Status = ForwardIrpSynchronous(DeviceObject, Irp); 00357 if (!NT_SUCCESS(Status)) 00358 { 00359 /* Failed to start lower devices */ 00360 CompleteIrp(Irp, Status, 0); 00361 /* Release resources */ 00362 StreamClassReleaseResources(DeviceObject); 00363 /* Release request block */ 00364 ExFreePool(RequestBlock); 00365 return Status; 00366 } 00367 00368 Config->Irp = Irp; 00369 00370 /* FIXME SYNCHRONIZATION */ 00371 00372 /* Send the request */ 00373 DriverObjectExtension->Data.HwReceivePacket((PHW_STREAM_REQUEST_BLOCK)RequestBlock); 00374 if (RequestBlock->Block.Status == STATUS_PENDING) 00375 { 00376 /* Request is pending, wait for result */ 00377 KeWaitForSingleObject(&RequestBlock->Event, Executive, KernelMode, FALSE, NULL); 00378 /* Get final status code */ 00379 Status = RequestBlock->Block.Status; 00380 } 00381 00382 /* Copy stream descriptor size */ 00383 DeviceExtension->StreamDescriptorSize = Config->StreamDescriptorSize; 00384 00385 /* check if the request has succeeded or if stream size is valid*/ 00386 if (!NT_SUCCESS(Status)|| !Config->StreamDescriptorSize) 00387 { 00388 /* Failed to start device */ 00389 CompleteIrp(Irp, Status, 0); 00390 /* Release resources */ 00391 StreamClassReleaseResources(DeviceObject); 00392 /* Release request block */ 00393 ExFreePool(RequestBlock); 00394 return Status; 00395 } 00396 00397 /* Allocate a stream Descriptor */ 00398 StreamDescriptor = ExAllocatePool(NonPagedPool, DeviceExtension->StreamDescriptorSize); 00399 if (!StreamDescriptor) 00400 { 00401 /* Not enough memory */ 00402 CompleteIrp(Irp, STATUS_INSUFFICIENT_RESOURCES, 0); 00403 /* Release resources */ 00404 StreamClassReleaseResources(DeviceObject); 00405 /* Release request block */ 00406 ExFreePool(RequestBlock); 00407 return STATUS_INSUFFICIENT_RESOURCES; 00408 } 00409 00410 /* Zero stream descriptor */ 00411 RtlZeroMemory(StreamDescriptor, DeviceExtension->StreamDescriptorSize); 00412 00413 /* Setup get stream info struct */ 00414 RequestBlock->Block.Command = SRB_GET_STREAM_INFO; 00415 RequestBlock->Block.CommandData.StreamBuffer = StreamDescriptor; 00416 KeResetEvent(&RequestBlock->Event); 00417 00418 /* send the request */ 00419 DriverObjectExtension->Data.HwReceivePacket((PHW_STREAM_REQUEST_BLOCK)RequestBlock); 00420 if (RequestBlock->Block.Status == STATUS_PENDING) 00421 { 00422 /* Request is pending, wait for result */ 00423 KeWaitForSingleObject(&RequestBlock->Event, Executive, KernelMode, FALSE, NULL); 00424 /* Get final status code */ 00425 Status = RequestBlock->Block.Status; 00426 } 00427 00428 if (NT_SUCCESS(Status)) 00429 { 00430 /* store stream descriptor */ 00431 DeviceExtension->StreamDescriptor = StreamDescriptor; 00432 } 00433 else 00434 { 00435 /* cleanup resources */ 00436 ExFreePool(StreamDescriptor); 00437 } 00438 00439 ExFreePool(RequestBlock); 00440 /* Complete Irp */ 00441 CompleteIrp(Irp, Status, 0); 00442 /* Return result */ 00443 return Status; 00444 } 00445 00446 NTSTATUS 00447 NTAPI 00448 StreamClassPnp( 00449 IN PDEVICE_OBJECT DeviceObject, 00450 IN PIRP Irp) 00451 { 00452 PIO_STACK_LOCATION IoStack; 00453 00454 /* Get current irp stack location */ 00455 IoStack = IoGetCurrentIrpStackLocation(Irp); 00456 00457 switch (IoStack->MinorFunction) 00458 { 00459 case IRP_MN_START_DEVICE: 00460 { 00461 return StreamClassStartDevice(DeviceObject, Irp); 00462 } 00463 } 00464 00465 IoCompleteRequest(Irp, IO_NO_INCREMENT); 00466 return STATUS_NOT_SUPPORTED; 00467 } 00468 00469 Generated on Fri May 25 2012 04:15:59 for ReactOS by
1.7.6.1
|