ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

pnp.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.