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

📄 read_write.c

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

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

    baseVa = MmGetMdlVirtualAddress(irp->MdlAddress);

    devExt->WriteStartingOffset =  devExt->WriteSoFar;

    //
    // Get the base address and length of the segment to write.
    //
    devExt->WritePaToDevice = IoMapTransfer(devExt->WriteAdapter,
                                   irp->MdlAddress,
                                   MapRegisterBase,
                                   baseVa+(devExt->WriteSoFar),
                                   &devExt->WriteLength,
                                   TRUE);      // WriteToDevice

    //
    // Update the length transfered so far
    //
    devExt->WriteSoFar += devExt->WriteLength;

    //
    // Put the request on the device
    //
    (VOID)KeSynchronizeExecution(devExt->InterruptObject,
                            OsrStartWriteOnDevice,
                            DeviceObject);

    return(DeallocateObjectKeepRegisters);
}        


///////////////////////////////////////////////////////////////////////////////
//
//  OsrStartReadOnDevice
//
//      This function performs all the actual hardware manipulation to initiate
//      a new read request on the AMCC device.  When called, all resources
//      (mapping registers) have been allocated for the operation, and we have
//      a base address and length of a buffer fragment to be DMA'ed.
//
//  INPUTS:
//
//      DeviceObject - Address of the DEVICE_OBJECT for our device.
//  
//      BaseAddress  - Logical base address of the requestor's buffer fragment
//                      to be used as the base address of the transfer
//
//      Length - Length in bytes of this fragment to be transfered.
//
//  OUTPUTS:
//
//      None.
//
//  RETURNS:
//
//      None.
//
//  IRQL:
//
//      This routine is called at IRQL_DISPATCH_LEVEL.
//
//  NOTES:
//
//      When this routine is called, no other Read operations are in progress on
//      the device.
//
///////////////////////////////////////////////////////////////////////////////
BOOLEAN
OsrStartReadOnDevice(IN PVOID SynchronizeContext)
{
    ULONG temp;
    PDEVICE_OBJECT deviceObject = (PDEVICE_OBJECT)SynchronizeContext;
    PHYSICAL_ADDRESS baseAddress;
    ULONG length;
    POSR_DEVICE_EXT devExt = deviceObject->DeviceExtension;

    baseAddress = devExt->ReadPaToDevice;
    length = devExt->ReadLength;

#if DBG
    DbgPrint("StartReadOnDev: Reading BA = 0x%0x, Length = %d.\n",
                        baseAddress.LowPart, length);
#endif

    //
    // Pass the device the Physical Base Address of the buffer
    //
    ASSERT(!baseAddress.HighPart);

    WRITE_PORT_ULONG(devExt->AmccBaseRegisterAddress+MWAR_OFF,
                     baseAddress.LowPart);

    //
    // ...and the length of the read
    //
    WRITE_PORT_ULONG(devExt->AmccBaseRegisterAddress+MWTC_OFF, length);

    //
    // Tell the device to interrupt when the read is complete.
    //
    // NOTE: In this particular device, "read" operations from the
    // device are called "WRITE" operations... since they write to
    // MEMORY.  Thus, we set the INT_ON_WRITE bit in the Interrupt
    // CSR.
    //
    temp = READ_PORT_ULONG(devExt->AmccBaseRegisterAddress+ICSR_OFF);

#if DBG
    DbgPrint("StartDmaRead: Current INTCSR State:\n");
    OsrPrintIntcsr(temp);
#endif

    temp &= ~AMCC_INT_ACK_BITS;
    temp |= AMCC_INT_INT_ON_WRITE;
    
    WRITE_PORT_ULONG(devExt->AmccBaseRegisterAddress+ICSR_OFF, temp);

    //
    // Yeeeeha!  Start the request by settting the "Write Enable"
    // bit in the master CSR
    //
    temp = READ_PORT_ULONG(devExt->AmccBaseRegisterAddress+MCSR_OFF);
    temp &= (AMCC_MCSR_READ_ENABLE        |
                AMCC_MCSR_READ_FIFO_MGMT  |
                AMCC_MCSR_READ_PRIORITY   |
                AMCC_MCSR_WRITE_ENABLE    |
                AMCC_MCSR_WRITE_FIFO_MGMT |
                AMCC_MCSR_WRITE_PRIORITY);

    temp |= AMCC_MCSR_WRITE_ENABLE;

    WRITE_PORT_ULONG(devExt->AmccBaseRegisterAddress+MCSR_OFF, temp); 

    return(TRUE);
}    

///////////////////////////////////////////////////////////////////////////////
//
//  OsrStartWriteOnDevice
//
//      This function performs all the actual hardware manipulation to initiate
//      a new read request on the AMCC device.  When called, all resources
//      (mapping registers) have been allocated for the operation, and we have
//      a base address and length of a buffer fragment to be DMA'ed.
//
//  INPUTS:
//
//      DeviceObject - Address of the DEVICE_OBJECT for our device.
//  
//      BaseAddress  - Logical base address of the requestor's buffer fragment
//                      to be used as the base address of the transfer
//
//      Length - Length in bytes of this fragment to be transfered.
//
//  OUTPUTS:
//
//      None.
//
//  RETURNS:
//
//    None.
//
//  IRQL:
//
//    This routine is called at IRQL_DISPATCH_LEVEL.
//
//  NOTES:
//
//    When this routine is called, no other Write operations are in progress on
//    the device.
//
///////////////////////////////////////////////////////////////////////////////
BOOLEAN
OsrStartWriteOnDevice(IN PVOID SynchronizeContext)
{
    ULONG temp;
    PDEVICE_OBJECT deviceObject = (PDEVICE_OBJECT)SynchronizeContext;
    PHYSICAL_ADDRESS baseAddress;
    ULONG length;
    POSR_DEVICE_EXT devExt = deviceObject->DeviceExtension;

    baseAddress = devExt->WritePaToDevice;
    length = devExt->WriteLength;

#if DBG
    DbgPrint("StartWriteOnDev: Writing BA = 0x%0x, Length = %d.\n",
                        baseAddress.LowPart, length);
#endif

    //
    // Pass the device the Physical Base Address of the buffer...
    //
    ASSERT(!baseAddress.HighPart);

    WRITE_PORT_ULONG(devExt->AmccBaseRegisterAddress+MRAR_OFF,
                     baseAddress.LowPart);

    //
    // ...and the length of the write operation
    //
    WRITE_PORT_ULONG(devExt->AmccBaseRegisterAddress+MRTC_OFF, length);

    //
    // Request the device interrupt when the write operation is complete
    //
    temp = READ_PORT_ULONG(devExt->AmccBaseRegisterAddress+ICSR_OFF);

#if DBG
    DbgPrint("StartWriteOnDev: Current INTCSR State:\n");
    OsrPrintIntcsr(temp);
#endif

    temp &= ~AMCC_INT_ACK_BITS;
    temp |= AMCC_INT_INT_ON_READ;
    WRITE_PORT_ULONG(devExt->AmccBaseRegisterAddress+ICSR_OFF, temp);

    //
    // Yeeeeha!  Start the request by setting the appropriate enable bit.
    //
    temp = READ_PORT_ULONG(devExt->AmccBaseRegisterAddress+MCSR_OFF);
    temp &= (AMCC_MCSR_READ_ENABLE|
                AMCC_MCSR_READ_FIFO_MGMT|
                AMCC_MCSR_READ_PRIORITY|
                AMCC_MCSR_WRITE_ENABLE|
                AMCC_MCSR_WRITE_FIFO_MGMT|
                AMCC_MCSR_WRITE_PRIORITY);

    temp |= AMCC_MCSR_READ_ENABLE;

    WRITE_PORT_ULONG(devExt->AmccBaseRegisterAddress+MCSR_OFF, temp); 

    return(TRUE);
}    


///////////////////////////////////////////////////////////////////////////////
//
//  OsrProcessQueuedRequests
//
//      This interface checks the current state of the read and write
//      queues, and starts requests on the device if either are not
//      busy.
//
//  INPUTS:
//
//      devExt - Pointer to device extension of device to start
//
//  OUTPUTS:
//
//      None.
//
//  RETURNS:
//
//    None.
//
//  IRQL:
//
//
//  NOTES:
//
///////////////////////////////////////////////////////////////////////////////
VOID OsrProcessQueuedRequests(IN OUT POSR_DEVICE_EXT devExt)
{
    PVOID entry;
    PIRP irp;
    KIRQL oldIrql;

    //
    // See if there's something to start on the WRITE queue
    //
    KeAcquireSpinLock(&devExt->WriteQueueLock, &oldIrql);

    while ( !devExt->CurrentWriteIrp &&
            !IsListEmpty(&devExt->WriteQueue) ) {

        entry = RemoveHeadList(&devExt->WriteQueue);

        irp =  CONTAINING_RECORD(entry, IRP, Tail.Overlay.ListEntry);
#if DBG
        DbgPrint("OsrProcessQueued: IRP removed from WRITE queue = 0x%0x\n",irp);
#endif
        //
        // If this IRP is cancelled, cancel it now, without
        // initiating it on the device
        //
        if (irp->Cancel) {
#if DBG
            DbgPrint("OsrProcessQueued: CANCEL flag set in READ IRP removed from queue 0x%0x\n",irp);
#endif
            irp->IoStatus.Status = STATUS_CANCELLED;
            irp->IoStatus.Information = 0;

            //
            // Complete the request now
            //
            IoCompleteRequest(irp, IO_NO_INCREMENT);    

        } else {

            //
            // Since we do not cancel in-progress requests
            // on this device, we will reset the cancel
            // routine in the IRP to NULL.
            //
            IoSetCancelRoutine(irp, NULL);

            //
            // Make this IRP the current write IRP, and
            // start the request on the device.  This routine
            // sets devExt->CurrentWriteIrp
            //
            OsrStartWriteIrp(devExt->FunctionalDeviceObject, irp);                
        }

    }   // while (!devExt->CurrentWriteIrp && 
        //        !IsListEmpty(devExt->WriteQueue) )

    //
    // Drop the lock
    //
    KeReleaseSpinLock(&devExt->WriteQueueLock, oldIrql);

    //
    // See if there's something to start on the READ queue
    //
    KeAcquireSpinLock(&devExt->ReadQueueLock, &oldIrql);

    while ( !devExt->CurrentReadIrp &&
            !IsListEmpty(&devExt->ReadQueue) ) {

        entry = RemoveHeadList(&devExt->ReadQueue);

        irp =  CONTAINING_RECORD(entry, IRP, Tail.Overlay.ListEntry);
#if DBG
        DbgPrint("OsrProcessQueued: IRP removed from READ queue = 0x%0x\n",irp);
#endif
        //
        // If this IRP is cancelled, cancel it now, without
        // initiating it on the device
        //
        if (irp->Cancel) {
#if DBG
            DbgPrint("OsrProcessQueued: CANCEL flag set in READ IRP removed from queue 0x%0x\n",irp);
#endif
            irp->IoStatus.Status = STATUS_CANCELLED;
            irp->IoStatus.Information = 0;

            //
            // Complete the request now
            //
            IoCompleteRequest(irp, IO_NO_INCREMENT);    

        } else {

            //
            // Since we do not cancel in-progress requests
            // on this device, we will reset the cancel
            // routine in the IRP to NULL.
            //
            IoSetCancelRoutine(irp, NULL);

            //
            // Make this IRP the current read IRP, and
            // start the request on the device.  This routine
            // sets devExt->CurrentReadIrp
            //
            OsrStartReadIrp(devExt->FunctionalDeviceObject, irp);                
        }

    }   // while (!devExt->CurrentReadIrp && 
        //        !IsListEmpty(devExt->ReadQueue) )

    //
    // Drop the lock
    //
    KeReleaseSpinLock(&devExt->ReadQueueLock, oldIrql);


}

⌨️ 快捷键说明

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