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

📄 pnp.c

📁 PCI驱动编程实例
💻 C
📖 第 1 页 / 共 4 页
字号:
    //
    RtlZeroMemory(deviceDescription, sizeof(DEVICE_DESCRIPTION));

    deviceDescription->Version = DEVICE_DESCRIPTION_VERSION;
    deviceDescription->Master = TRUE;
    deviceDescription->ScatterGather = FALSE;
    deviceDescription->Dma32BitAddresses = TRUE;
    deviceDescription->InterfaceType = PCIBus;

    //
    // Maximum size of transfer that we support on this device.  Choose
    // anything you like, really.
    //
    deviceDescription->MaximumLength = OSR_PCI_MAX_TXFER;

    //
    // Allocate one Adapter for WRITE
    //
    DevExt->WriteAdapter = IoGetDmaAdapter(DevExt->PhysicalDeviceObject,
                                          deviceDescription,
                                          &DevExt->WriteMapRegsGot);

    if(!DevExt->WriteAdapter)  {

#if DBG
        DbgPrint("IoGetDmaAdapter for WRITE FAILED!!\n");    
#endif
        //
        // Clean up the mess
        //
        ExFreePool(deviceDescription);

        //OsrUnload(DriverObj);

        return(STATUS_UNSUCCESSFUL);
    }

#if DBG
    DbgPrint("Max Map Regs for WRITE = %d.\n", DevExt->WriteMapRegsGot);
#endif

    //
    // And then another for READ
    //
    DevExt->ReadAdapter = IoGetDmaAdapter(DevExt->PhysicalDeviceObject,
                                          deviceDescription,
                                          &DevExt->ReadMapRegsGot);

    if(!DevExt->ReadAdapter)  {

#if DBG
        DbgPrint("IoGetDmaAdapter for READ FAILED!!\n");    
#endif
        //
        // Clean up the mess
        //
        ExFreePool(deviceDescription);

        //OsrUnload(DriverObj);

        return(STATUS_UNSUCCESSFUL);
    }

#if DBG
    DbgPrint("Max Map Regs for READ = %d.\n", DevExt->ReadMapRegsGot);
#endif

   //
    // Return the memory allocated from pool during initialization
    //
    ExFreePool(deviceDescription);    

    return STATUS_SUCCESS;
}


///////////////////////////////////////////////////////////////////////////////
//
// OsrCanStopDevice
//
//      This routine determines if the device cab be safely stopped.  In
//      our case we'll assume you can always stop the device.  A device
//      might not be able to be stopped, for example, if it doesn't have
//      a queue for incoming requests or if it was notified that it is
//      in the paging path.
//
//  INPUTS:
//
//      devExt  - Address of our device extension.
//      Irp         - Address of the input IRP.
//
//  OUTPUTS:
//
//      None.
//
//  RETURNS:
//
//    STATUS_SUCCESS;
//
//  IRQL:
//
//
//  NOTES:
//
//
///////////////////////////////////////////////////////////////////////////////
NTSTATUS OsrCanStopDevice(POSR_DEVICE_EXT devExt, PIRP Irp)
{
    UNREFERENCED_PARAMETER(devExt);
    UNREFERENCED_PARAMETER(Irp);

    return STATUS_SUCCESS;
}

///////////////////////////////////////////////////////////////////////////////
//
// OsrCanRemoveDevice
//
//      This routine determines if the device cab be safely removed.  In our case
//      we'll assume you can always remove the device.  A device might note be able to
//      be removed, for example, if it has opened handles or removing the device would
//      result in the lost of data.
//
//  INPUTS:
//
//      devExt  - Address of our device extension.
//      Irp         - Address of the input IRP.
//
//  OUTPUTS:
//
//      None.
//
//  RETURNS:
//
//    STATUS_SUCCESS;
//
//  IRQL:
//
//
//  NOTES:
//
//
///////////////////////////////////////////////////////////////////////////////
NTSTATUS OsrCanRemoveDevice(POSR_DEVICE_EXT devExt, PIRP Irp)
{
    UNREFERENCED_PARAMETER(devExt);
    UNREFERENCED_PARAMETER(Irp);

    return STATUS_SUCCESS;
}

///////////////////////////////////////////////////////////////////////////////
//
// OsrReturnResources
//
//      This function is called to return any hardware resources which
//      have been allocated for the device.  In our case, these are
//      the Interrupt Object, and any ports we might have mapped through
//      memory.  Note that we do NOT return our Device Object here.
//
//  INPUTS:
//
//      devExt  - Address of our device extension.
//      Irp         - Address of the input IRP.
//
//  OUTPUTS:
//
//      None.
//
//  RETURNS:
//
//      VOID
//
//  IRQL:
//
//
//  NOTES:
//
//
///////////////////////////////////////////////////////////////////////////////
VOID
OsrReturnResources(POSR_DEVICE_EXT devExt)
{

    //
    // Disconnect from any interrupts
    //
    if (devExt->InterruptObject) {

        //
        // Disconnect from the interrupt
        //
        IoDisconnectInterrupt(devExt->InterruptObject);

        devExt->InterruptObject = NULL;
    }


    //
    // Unmap any ports that were mapped
    //
    if (devExt->MappedPorts) {

        MmUnmapIoSpace(devExt->AmccBaseRegisterAddress, 0x40);

        devExt->MappedPorts = FALSE;
        devExt->AmccBaseRegisterAddress = 0;
        
    }

}


///////////////////////////////////////////////////////////////////////////////
//
// OsrRequestIncrement
// OsrRequestDecrement
//
//      These functions are used to track the number of requests that
//      are presently queued the device indicated by the passed
//      Device Extension.
//
//      This code is based heavily on the PnP Sample Driver in the
//      \General directory of the NTDDK.
//
//  INPUTS:
//
//      devExt  - Address of our device extension.
//
//  OUTPUTS:
//
//      None.
//
//  RETURNS:
//
//    STATUS_SUCCESS;
//
//  IRQL:
//
//
//  NOTES:
//
//
///////////////////////////////////////////////////////////////////////////////
VOID
OsrRequestIncrement(POSR_DEVICE_EXT devExt)
{

    LONG result;
    
    result = InterlockedIncrement(&devExt->OutstandingIO);

    ASSERT(result >= 0);
    
    //
    // Need to clear Remove
    //
    if (result == 1) {

        //
        // The remove event is cleared when the first request is
        // added to the queue.
        //
        KeClearEvent(&devExt->RemoveEvent);
    }

    return;
}

VOID
OsrRequestDecrement(POSR_DEVICE_EXT devExt)
{

    LONG result;
    
    result = InterlockedDecrement(&devExt->OutstandingIO);
    
    ASSERT(result >= 0);

    if (result == 0) {

        //
        // The remove event is set when the queue is totally EMPTY.
        //
        KeSetEvent(&devExt->RemoveEvent, 
                   IO_NO_INCREMENT, 
                   FALSE);
        
    }

}

///////////////////////////////////////////////////////////////////////////////
//
// OsrWaitForStop
//
//      Using the event set by the OsrRequestIncrement() and 
//      OsrRequestDecrement() functions, this function waits until
//      the device can be stopped.
//
//      On our device, STOP implies there are no active requests on
//      the device, even though there are queued requests.
//
//  INPUTS:
//
//      devExt  - Address of our device extension.
//
//  OUTPUTS:
//
//      None.
//
//  RETURNS:
//
//    STATUS_SUCCESS;
//
//  IRQL:
//
//
//  NOTES:
//
//
///////////////////////////////////////////////////////////////////////////////
VOID
OsrWaitForStop(POSR_DEVICE_EXT devExt)
{
    devExt->HoldNewRequests = TRUE;

    ASSERT(devExt->State != STATE_STARTED);

    KeWaitForSingleObject(&devExt->StopEvent,
                           Executive,
                           KernelMode,
                           FALSE,
                           NULL);

}

///////////////////////////////////////////////////////////////////////////////
//
// OsrWaitForRemove
//
//      Using the event set by the OsrRequestIncrement() and 
//      OsrRequestDecrement() functions, this function waits until
//      the device can be removed.
//
//      On our device, REMOVE implies there are no active or queued
//      requests on the device.
//
//  INPUTS:
//
//      devExt  - Address of our device extension.
//
//  OUTPUTS:
//
//      None.
//
//  RETURNS:
//
//    STATUS_SUCCESS;
//
//  IRQL:
//
//
//  NOTES:
//
//
///////////////////////////////////////////////////////////////////////////////
VOID
OsrWaitForRemove(POSR_DEVICE_EXT devExt)
{
#if DBG
    LARGE_INTEGER timeout;
    NTSTATUS status;

    timeout.QuadPart = -5*10*1000*1000;     // 5 seconds
#endif

    devExt->Removed = TRUE;

    ASSERT(devExt->State < STATE_ALL_BELOW_FAIL);

#if DBG

wait_again:

    status = KeWaitForSingleObject(&devExt->RemoveEvent,
                           Executive,
                           KernelMode,
                           FALSE,
                           &timeout);

    if(status == STATUS_TIMEOUT) {
    
        DbgPrint("OsrPci: *** Still Waiting for activity to stop on device??  %d. requests reamin\n", devExt->OutstandingIO);
        goto wait_again;
    }    

    if(status != STATUS_SUCCESS) {

        DbgPrint("OsrPci: *** Wait not ended with success, and not with timeout?? Status = 0x%0x\n", status);
    }

#else

    KeWaitForSingleObject(&devExt->RemoveEvent,
                           Executive,
                           KernelMode,
                           FALSE,
                           NULL);
#endif

}

///////////////////////////////////////////////////////////////////////////////
//
// OsrSystemControl
//
//      This dispatch entry point is used to pass any WMI IRPs that we
//      receive on to the underlying bus driver.
//
//  INPUTS:
//
///     DriverObject - Pointer to driver object.
//      Irp         - Address of the input IRP.
//
//  OUTPUTS:
//
//      None.
//
//  RETURNS:
//
//      VOID
//
//  IRQL:
//
//
//  NOTES:
//
//
///////////////////////////////////////////////////////////////////////////////
NTSTATUS 
OsrSystemControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{

    //
    // Since we don't play WMI, pass this request on down to the
    // driver below us...
    //
    IoSkipCurrentIrpStackLocation(Irp);

    return(IoCallDriver(((POSR_DEVICE_EXT)(DeviceObject->DeviceExtension))->DeviceToSendIrpsTo, Irp));

}



#if DBG

VOID
OsrPrintState(POSR_DEVICE_EXT devExt)
{
    if(devExt->State == STATE_REMOVED) {
        DbgPrint("STATE_REMOVED\n");
        return;
    }

    if(devExt->State == STATE_STARTED) {
        DbgPrint("STATE_STARTED\n");
        return;
    }

    if(devExt->State == STATE_REMOVE_PENDING) {
        DbgPrint("STATE_REMOVE_PENDING\n");
        return;
    }

    if(devExt->State == STATE_SURPRISE_REMOVED) {
        DbgPrint("STATE_SURPRISE_REMOVED\n");
        return;
    }


    if(devExt->State == STATE_STOP_PENDING) {
        DbgPrint("STATE_STOP_PENDING\n");
        return;
    }

    if(devExt->State == STATE_STOPPED) {
        DbgPrint("STATE_STOPPED\n");
        return;
    }

    if(devExt->State == STATE_NEVER_STARTED) {
        DbgPrint("STATE_NEVER_STARTED\n");
        return;
    }

    DbgPrint("*********UNKNOWN STATE Value 0x%0x\n", devExt->State);
}

#endif

⌨️ 快捷键说明

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