⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 read_write.c

📁 PCI驱动编程实例
💻 C
📖 第 1 页 / 共 3 页
字号:

///////////////////////////////////////////////////////////////////////////////
//
//  OsrStartWriteIrp
//
//    This is routine is called by the OsrWrite and DpcForIsr routine to
//    start a new Write operation.  The request started is the IRP located
//    at the head of the write queue.
//
//  INPUTS:
//
//      DeviceObject - Address of the DEVICE_OBJECT for our device.
//  
//      Irp - Address of the IRP representing the IRP_MJ_WRITE call.
//
//  OUTPUTS:
//
//      None.
//
//  RETURNS:
//
//      None.
//
//  IRQL:
//
//      This routine is called at IRQL_DISPATCH_LEVEL.
//
//  NOTES:
//      *** Called (and returns) with the WriteQueueLock held.
//
///////////////////////////////////////////////////////////////////////////////
VOID
OsrStartWriteIrp(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
    POSR_DEVICE_EXT devExt = DeviceObject->DeviceExtension;
    PIO_STACK_LOCATION ioStack;
    ULONG mapRegsNeeded;
    
    ioStack = IoGetCurrentIrpStackLocation(Irp);

    //
    // In progress IRPs cannot be cancelled
    //
    IoSetCancelRoutine(Irp, NULL);

#if DBG
    DbgPrint("OsrWrite: Transfer length %d.\n",
                                ioStack->Parameters.Write.Length);
#endif

    //
    // We're starting a request... therefore, we clear the StopEvent
    // flag.
    //
    KeClearEvent(&devExt->StopEvent);

    //
    // There is no in-progress request.  Start this request on the
    // device.
    //
    devExt->CurrentWriteIrp = Irp;

    devExt->WriteTotalLength = ioStack->Parameters.Write.Length;

    devExt->WriteSoFar = 0;

    devExt->WriteStartingOffset = 0;

    //
    // Start the watchdog timer on this IRP
    //
    (ULONG)Irp->Tail.Overlay.DriverContext[0] = OSR_WATCHDOG_INTERVAL;

    //
    // Since we're about to initiate a DMA operation, ensure the user's data
    // buffer is flushed from the cache back into memory, on processors that
    // are non-DMA cache coherent.
    //
    KeFlushIoBuffers(Irp->MdlAddress, FALSE, TRUE);

    //
    // Determine the number of map registers we'll need for this transfer
    //
    mapRegsNeeded = 
        ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(Irp->MdlAddress),
                                        ioStack->Parameters.Write.Length);
        
#if DBG
    DbgPrint("StartWrite: %d. map regs needed\n", mapRegsNeeded);
#endif

    //
    // If the number of map registers required for this transfer exceeds the
    // maximum we're allowed to use (as reported to us from HalGetAdapter() ),
    // we'll need to limit ourselves to the maximum we're allowed.
    //
    devExt->MapRegsThisWrite = ((mapRegsNeeded > devExt->WriteMapRegsGot) ? 
                              devExt->WriteMapRegsGot : mapRegsNeeded);

#if DBG
    DbgPrint("StartWrite: %d. map regs this xfer\n", devExt->MapRegsThisWrite);
#endif

    //
    // Ready to GO! Allocate the appropriate Adapter Object and map registers.
    //
    IoAllocateAdapterChannel(devExt->WriteAdapter,
                             DeviceObject, 
                             devExt->MapRegsThisWrite,
                             OsrAdapterControlWrite,
                             Irp);
}


///////////////////////////////////////////////////////////////////////////////
//
//  OsrStartReadIrp
//
//    This is routine is called by the OsrRead and Dpc routine in order to
//    begin a new Read operation.
//
//  INPUTS:
//
//      DeviceObject - Address of the DEVICE_OBJECT for our device.
//  
//      Irp - Address of the IRP representing the IRP_MJ_READ call.
//
//  OUTPUTS:
//
//      None.
//
//  RETURNS:
//
//      None.
//
//  IRQL:
//
//      This routine is called at IRQL_DISPATCH_LEVEL.
//
//  NOTES:
//      *** Called (and returns) with the WriteQueueLock held.
//
///////////////////////////////////////////////////////////////////////////////
VOID
OsrStartReadIrp(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
    POSR_DEVICE_EXT devExt = DeviceObject->DeviceExtension;
    PIO_STACK_LOCATION ioStack;
    ULONG mapRegsNeeded;

    ioStack = IoGetCurrentIrpStackLocation(Irp);

    //
    // In progress IRPs cannot be cancelled
    //
    IoSetCancelRoutine(Irp, NULL);

#if DBG
    DbgPrint("OsrRead: Transfer length %d.\n",
                                ioStack->Parameters.Read.Length);
#endif

    //
    // We're starting a request... therefore, we clear the StopEvent
    // flag.
    //
    KeClearEvent(&devExt->StopEvent);

    //
    // There is no in-progress request.  Start this request on the
    // device.
    //
    devExt->CurrentReadIrp = Irp;

    devExt->ReadTotalLength = ioStack->Parameters.Read.Length;

    devExt->ReadSoFar = 0;

    devExt->ReadStartingOffset = 0;

    //
    // Start the watchdog timer on this IRP
    //
    (ULONG)Irp->Tail.Overlay.DriverContext[0] = OSR_WATCHDOG_INTERVAL;

    //
    // Flush the requestor's buffer back from cache on non-dma coherent
    // machines.
    //
    KeFlushIoBuffers(Irp->MdlAddress, TRUE, TRUE);

    //
    // Determine number of map registers required by this read
    //
    mapRegsNeeded = 
        ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(Irp->MdlAddress),
                                        ioStack->Parameters.Read.Length);
        
#if DBG
    DbgPrint("StartReadIrp: %d. map regs needed\n", mapRegsNeeded);
#endif

    //
    // Limit the number of map registers used to the maximum allowed by the
    // HAL.  We determined this max when we called HalGetAdapter() during
    // our DriverEntry processing.
    //
    devExt->MapRegsThisRead = ((mapRegsNeeded > devExt->ReadMapRegsGot) ? 
                              devExt->ReadMapRegsGot : mapRegsNeeded);

#if DBG
    DbgPrint("StartReadIrp: %d. map regs this xfer\n", devExt->MapRegsThisRead);
#endif

    IoAllocateAdapterChannel(devExt->ReadAdapter,
                             DeviceObject, 
                             devExt->MapRegsThisRead,
                             OsrAdapterControlRead,
                             Irp);


}

///////////////////////////////////////////////////////////////////////////////
//
//  OsrAdapterControlRead
//
//    This is routine is called by the I/O Manager when the Adapter resources
//    (such as map registers) requested by the OsrStartReadIrp function are
//    available for our use.
//
//  INPUTS:
//
//      DeviceObject - Address of the DEVICE_OBJECT for our device.
//  
//      MapRegisterBase - Base address of the Map registers that have been
//                        reserved for us use.
//
//       Context - address of the Read Irp for the operation to be started
//
//  OUTPUTS:
//
//      None.
//
//  RETURNS:
//
//    DeallocateObjectKeepRegisters - indicates that the Mapping Registers that
//              were allocated to us should not be deallocated at this time.  We
//              will deallocate them from the DpcForIsr when the Read completes.
//
//  IRQL:
//
//    This routine is called at IRQL_DISPATCH_LEVEL.
//
//  NOTES:
//
///////////////////////////////////////////////////////////////////////////////
IO_ALLOCATION_ACTION 
OsrAdapterControlRead(IN PDEVICE_OBJECT DeviceObject, IN PIRP NotUsed, 
                                  IN PVOID MapRegisterBase, IN PVOID Context)
{
    PIRP irp = (PIRP) Context;
    PIO_STACK_LOCATION ioStack;
    POSR_DEVICE_EXT devExt;
    PUCHAR baseVa;

#if DBG
    DbgPrint("AdapterControlRead: Irp = 0x%0x\n", irp);
    DbgPrint("AdapterControlRead: Map Register Base = 0x%0x\n", MapRegisterBase);
#endif

    devExt = DeviceObject->DeviceExtension;
    
    ioStack = IoGetCurrentIrpStackLocation(irp);

    devExt->ReadLength = ioStack->Parameters.Read.Length - devExt->ReadSoFar;

#if DBG
    DbgPrint("AdapterControlRead: Length remaining = %d. \n", devExt->ReadLength);
#endif

    //
    // Get set-up for the transfer
    //
    devExt->ReadMapRegBase = MapRegisterBase;

    devExt->ReadStartingOffset =  devExt->ReadSoFar;

    //
    // Get requestor's virtual address of the buffer.  This is used by
    // IoMapTransfer() as an index into the buffer to track the progress
    // of the map operation.
    //
    baseVa = MmGetMdlVirtualAddress(irp->MdlAddress);

    //
    // Get the logical base address and length of a fragment of the 
    // requestor's buffer.
    //
    // Even though we are a Busmaster device, our device does not support
    // scatter/gather.  Thus, we can only use a single base address and length
    // at a time.  If the requestor's buffer has more fragments, we will
    // do additional DMA operations (one for each fragment) until the entire
    // transfer has been completed.
    //
    devExt->ReadPaToDevice = IoMapTransfer(devExt->ReadAdapter,
                                   irp->MdlAddress,
                                   MapRegisterBase,
                                   baseVa+(devExt->ReadSoFar),
                                   &devExt->ReadLength,
                                   FALSE);  // FALSE = READ from device


    //
    // Track the length of the requestor's buffer we've read so far.
    //
    devExt->ReadSoFar += devExt->ReadLength;

    //
    // Start the request on the device -- Base Address and Length
    // of this fragment are stored in the device extension
    //
    (VOID)KeSynchronizeExecution(devExt->InterruptObject,
                            OsrStartReadOnDevice,
                            DeviceObject);

    return(DeallocateObjectKeepRegisters);
}        


///////////////////////////////////////////////////////////////////////////////
//
//  OsrAdapterControlWrite
//
//    This is routine is called by the I/O Manager when the Adapter resources
//    (such as map registers) requested by the OsrStartWriteIrp function are
//    available for our use.
//
//  INPUTS:
//
//      DeviceObject - Address of the DEVICE_OBJECT for our device.
//  
//      MapRegisterBase - Base address of the Map registers that have been
//                      reserved by the I/O Manager and HAL for our use.
//
//      Context - address of the Write Irp for the operation to be started on the 
//              device.
//
//  OUTPUTS:
//
//      None.
//
//  RETURNS:
//
//    DeallocateObjectKeepRegisters - indicates that the map registers that
//            were allocated to us should not be deallocated at this time.
//            We will deallocate them with the Read operation completes.
//
//  IRQL:
//
//    This routine is called at IRQL_DISPATCH_LEVEL.
//
//  NOTES:
//
///////////////////////////////////////////////////////////////////////////////
IO_ALLOCATION_ACTION 
OsrAdapterControlWrite(IN PDEVICE_OBJECT DeviceObject, IN PIRP NotUsed, 
                                  IN PVOID MapRegisterBase, IN PVOID Context)
{
    PIRP irp = (PIRP) Context;
    PIO_STACK_LOCATION ioStack;
    POSR_DEVICE_EXT devExt;
    PUCHAR baseVa;

#if DBG
    DbgPrint("AdapterControlWrite: Irp = 0x%0x\n", irp);
#endif

    devExt = DeviceObject->DeviceExtension;

    ioStack = IoGetCurrentIrpStackLocation(irp);

    devExt->WriteLength = ioStack->Parameters.Write.Length - devExt->WriteSoFar;

#if DBG
    DbgPrint("AdapterControlWrite: Length remaining = %d. \n", devExt->WriteLength);
#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -