www.pudn.com > 9054Src.rar > Dispatch.c


/******************************************************************************* 
 * Copyright (c) 2006 PLX Technology, Inc. 
 * 
 * PLX Technology Inc. licenses this software under specific terms and 
 * conditions.  Use of any of the software or derviatives thereof in any 
 * product without a PLX Technology chip is strictly prohibited. 
 * 
 * PLX Technology, Inc. provides this software AS IS, WITHOUT ANY WARRANTY, 
 * EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, ANY WARRANTY OF 
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  PLX makes no guarantee 
 * or representations regarding the use of, or the results of the use of, 
 * the software and documentation in terms of correctness, accuracy, 
 * reliability, currentness, or otherwise; and you rely on the software, 
 * documentation and results solely at your own risk. 
 * 
 * IN NO EVENT SHALL PLX BE LIABLE FOR ANY LOSS OF USE, LOSS OF BUSINESS, 
 * LOSS OF PROFITS, INDIRECT, INCIDENTAL, SPECIAL OR CONSEQUENTIAL DAMAGES 
 * OF ANY KIND.  IN NO EVENT SHALL PLX'S TOTAL LIABILITY EXCEED THE SUM 
 * PAID TO PLX FOR THE PRODUCT LICENSED HEREUNDER. 
 * 
 ******************************************************************************/ 
 
/****************************************************************************** 
 * 
 * File Name: 
 * 
 *      Dispatch.c 
 * 
 * Description: 
 * 
 *      This file routes incoming I/O Request packets 
 * 
 * Revision History: 
 * 
 *      02-01-06 : PCI SDK v4.40 
 * 
 ******************************************************************************/ 
 
 
#include "ApiFunctions.h" 
#include "CommonApi.h" 
#include "Dispatch.h" 
#include "GlobalVars.h" 
#include "PciSupport.h" 
#include "PlxIoctl.h" 
#include "SupportFunc.h" 
 
#if defined(PLX_WDM_DRIVER) 
    #include "Driver.h" 
#endif 
 
 
 
 
/****************************************************************************** 
 * 
 * Function   :  Dispatch_Create 
 * 
 * Description:  Handle IRP_MJ_CREATE, which allows applications to open handles 
 *               to our device 
 * 
 ******************************************************************************/ 
NTSTATUS 
Dispatch_Create( 
    PDEVICE_OBJECT fdo, 
    PIRP           pIrp 
    ) 
{ 
    DebugPrintf_NoInfo(("\n")); 
    DebugPrintf(( 
        "Received message (IRP=0x%p) ===> IRP_MJ_CREATE\n", 
        pIrp 
        )); 
 
    return PlxCompleteIrpWithInformation( 
               pIrp, 
               STATUS_SUCCESS, 
               0 
               ); 
} 
 
 
 
 
/****************************************************************************** 
 * 
 * Function   :  Dispatch_Cleanup 
 * 
 * Description:  Handle the IRP_MJ_CLEANUP IRP 
 * 
 ******************************************************************************/ 
NTSTATUS 
Dispatch_Cleanup( 
    PDEVICE_OBJECT fdo, 
    PIRP           pIrp 
    ) 
{ 
    PIO_STACK_LOCATION pStack; 
 
 
    DebugPrintf_NoInfo(("\n")); 
    DebugPrintf(( 
        "Received message (IRP=0x%p) ===> IRP_MJ_CLEANUP\n", 
        pIrp 
        )); 
 
    pStack = 
        IoGetCurrentIrpStackLocation( 
            pIrp 
            ); 
 
    // Release any pending notifications owned by proccess 
    PlxNotificationCancel( 
        fdo->DeviceExtension, 
        NULL, 
        pStack->FileObject 
        ); 
 
    // Close DMA channels owned by the process 
    PlxDmaChannelCleanup( 
        fdo->DeviceExtension, 
        pStack->FileObject 
        ); 
 
    // Unmap any mappings to PCI BAR spaces owned by process 
    PlxPciBarSpaceUnmapAll_ByOwner( 
        fdo->DeviceExtension, 
        pStack->FileObject 
        ); 
 
    // Unmap any mappings to the common buffer owned by process 
    PlxPciPhysicalMemoryUnmapAll_ByOwner( 
        fdo->DeviceExtension, 
        pGbl_CommonBuffer, 
        pStack->FileObject 
        ); 
 
    // Unmap and deallocate any physical memory owned by process 
    PlxPciPhysicalMemoryFreeAll_ByOwner( 
        fdo->DeviceExtension, 
        pStack->FileObject 
        ); 
 
    return PlxCompleteIrpWithInformation( 
               pIrp, 
               STATUS_SUCCESS, 
               0 
               ); 
} 
 
 
 
 
/****************************************************************************** 
 * 
 * Function   :  Dispatch_Close 
 * 
 * Description:  Handle IRP_MJ_CLOSE, which allows applications to close handles 
 *               to our device 
 * 
 ******************************************************************************/ 
NTSTATUS 
Dispatch_Close( 
    PDEVICE_OBJECT fdo, 
    PIRP           pIrp 
    ) 
{ 
    DebugPrintf_NoInfo(("\n")); 
    DebugPrintf(( 
        "Received message (IRP=0x%p) ===> IRP_MJ_CLOSE\n", 
        pIrp 
        )); 
 
    return PlxCompleteIrpWithInformation( 
               pIrp, 
               STATUS_SUCCESS, 
               0 
               ); 
} 
 
 
 
 
#if defined(PLX_WDM_DRIVER) 
/****************************************************************************** 
 * 
 * Function   :  Dispatch_SystemControl 
 * 
 * Description:  The dispatch routine for WMI IRPs.  It does nothing except 
 *               forward the IRP to the next device in the stack. 
 * 
 * Note       :  This routine is required or DriverVerifier will bug check 
 * 
 ******************************************************************************/ 
NTSTATUS 
Dispatch_SystemControl( 
    PDEVICE_OBJECT fdo, 
    PIRP           pIrp 
    ) 
{ 
    DebugPrintf_NoInfo(("\n")); 
    DebugPrintf(( 
        "Received WMI message (IRP=0x%p) ===> IRP_MJ_SYSTEM_CONTROL\n", 
        pIrp 
        )); 
 
    DebugPrintf(("Forwarded IRP to next lower driver\n")); 
 
    IoSkipCurrentIrpStackLocation( 
        pIrp 
        ); 
 
    return IoCallDriver( 
               ((DEVICE_EXTENSION *)fdo->DeviceExtension)->pLowerDeviceObject, 
               pIrp 
               ); 
} 
#endif 
 
 
 
 
/****************************************************************************** 
 * 
 * Function   :  Dispatch_IoControl 
 * 
 * Description:  Processes the IOCTL messages sent to this device 
 * 
 ******************************************************************************/ 
NTSTATUS 
Dispatch_IoControl( 
    PDEVICE_OBJECT fdo, 
    PIRP           pIrp 
    ) 
{ 
    IOCTLDATA          *pIoBuffer; 
    DEVICE_EXTENSION   *pdx; 
    PIO_STACK_LOCATION  pStack; 
 
 
    pdx = fdo->DeviceExtension; 
 
    pStack = 
        IoGetCurrentIrpStackLocation( 
            pIrp 
            ); 
 
    pIoBuffer                  = pIrp->AssociatedIrp.SystemBuffer; 
    pIrp->IoStatus.Information = sizeof(IOCTLDATA); 
 
    // Lock device to record usage 
    PlxLockDevice( 
        pdx 
        ); 
 
    DebugPrintf(("Received PLX message (IRP=0x%p) ===> ", pIrp)); 
 
    // Handle the PLX specific message 
    switch (pStack->Parameters.DeviceIoControl.IoControlCode) 
    { 
        /*********************************** 
         * PLX device management functions 
         **********************************/ 
        case PLX_IOCTL_DEVICE_INIT: 
            DebugPrintf_NoInfo(("PLX_IOCTL_DEVICE_INIT\n")); 
 
            // Send the device location data back to the API 
            pIoBuffer->u.MgmtData.u.Device = pdx->Device; 
            break; 
 
        case PLX_IOCTL_PCI_DEVICE_FIND: 
            DebugPrintf_NoInfo(("PLX_IOCTL_PCI_DEVICE_FIND\n")); 
 
            pIoBuffer->ReturnCode = 
                PlxDeviceFind( 
                    pdx, 
                    &(pIoBuffer->u.MgmtData.u.Device), 
                    (U32*)&(pIoBuffer->u.MgmtData.value) 
                    ); 
            break; 
 
        case PLX_IOCTL_DRIVER_VERSION: 
            DebugPrintf_NoInfo(("PLX_IOCTL_DRIVER_VERSION\n")); 
 
            pIoBuffer->u.MgmtData.value  = 
                (PLX_SDK_VERSION_MAJOR    << 16) | 
                (PLX_SDK_VERSION_MINOR    <<  8) | 
                (PLX_SDK_VERSION_REVISION <<  0); 
            break; 
 
        case PLX_IOCTL_CHIP_TYPE_GET: 
            DebugPrintf_NoInfo(("PLX_IOCTL_CHIP_TYPE_GET\n")); 
 
            if (pdx->PowerState > MIN_WORKING_POWER_STATE) 
            { 
                pIoBuffer->ReturnCode = ApiPowerDown; 
            } 
            else 
            { 
                pIoBuffer->ReturnCode = ApiSuccess; 
 
                PlxChipTypeGet( 
                    pdx, 
                    (U32*)&(pIoBuffer->u.MiscData.data[0]), 
                    (U8*)&(pIoBuffer->u.MiscData.data[1]) 
                    ); 
            } 
            break; 
 
        case PLX_IOCTL_PCI_BOARD_RESET: 
            DebugPrintf_NoInfo(("PLX_IOCTL_PCI_BOARD_RESET\n")); 
 
            if (pdx->PowerState <= MIN_WORKING_POWER_STATE) 
            { 
                PlxPciBoardReset( 
                    pdx 
                    ); 
            } 
            break; 
 
        case PLX_IOCTL_PCI_BAR_GET: 
            DebugPrintf_NoInfo(("PLX_IOCTL_PCI_BAR_GET\n")); 
 
            pIoBuffer->u.MgmtData.value = 
                         pdx->PciBar[pIoBuffer->u.MgmtData.offset].Physical.QuadPart; 
            pIoBuffer->u.MgmtData.u.bFlag = 
                         pdx->PciBar[pIoBuffer->u.MgmtData.offset].bIsIoSpace; 
            break; 
 
        case PLX_IOCTL_PCI_BAR_RANGE_GET: 
            DebugPrintf_NoInfo(("PLX_IOCTL_PCI_BAR_RANGE_GET\n")); 
 
            pIoBuffer->u.MgmtData.value = 
                         pdx->PciBar[pIoBuffer->u.MgmtData.offset].Size; 
            break; 
 
        case PLX_IOCTL_PCI_BAR_MAP: 
            DebugPrintf_NoInfo(("PLX_IOCTL_PCI_BAR_MAP\n")); 
 
            pIoBuffer->ReturnCode = 
                PlxPciBarMap( 
                    pdx, 
                    (U8)(pIoBuffer->u.MgmtData.offset), 
                    &(pIoBuffer->u.MgmtData.value), 
                    pStack->FileObject 
                    ); 
            break; 
 
        case PLX_IOCTL_PCI_BAR_UNMAP: 
            DebugPrintf_NoInfo(("PLX_IOCTL_PCI_BAR_UNMAP\n")); 
 
            pIoBuffer->ReturnCode = 
                PlxPciBarUnmap( 
                    pdx, 
                    PLX_INT_TO_PTR(pIoBuffer->u.MgmtData.value), 
                    pStack->FileObject 
                    ); 
            break; 
 
        case PLX_IOCTL_PHYSICAL_MEM_ALLOCATE: 
            DebugPrintf_NoInfo(("PLX_IOCTL_PHYSICAL_MEM_ALLOCATE\n")); 
 
            pIoBuffer->ReturnCode = 
                PlxPciPhysicalMemoryAllocate( 
                    pdx, 
                    &(pIoBuffer->u.MiscData.u.PciMemory), 
                    (BOOLEAN)(pIoBuffer->u.MiscData.data[0]), 
                    pStack->FileObject 
                    ); 
            break; 
 
        case PLX_IOCTL_PHYSICAL_MEM_FREE: 
            DebugPrintf_NoInfo(("PLX_IOCTL_PHYSICAL_MEM_FREE\n")); 
 
            pIoBuffer->ReturnCode = 
                PlxPciPhysicalMemoryFree( 
                    pdx, 
                    &(pIoBuffer->u.MiscData.u.PciMemory) 
                    ); 
            break; 
 
        case PLX_IOCTL_PHYSICAL_MEM_MAP: 
            DebugPrintf_NoInfo(("PLX_IOCTL_PHYSICAL_MEM_MAP\n")); 
 
            pIoBuffer->ReturnCode = 
                PlxPciPhysicalMemoryMap( 
                    pdx, 
                    &(pIoBuffer->u.MiscData.u.PciMemory), 
                    (BOOLEAN)pIoBuffer->u.MiscData.data[0], 
                    pStack->FileObject 
                    ); 
            break; 
 
        case PLX_IOCTL_PHYSICAL_MEM_UNMAP: 
            DebugPrintf_NoInfo(("PLX_IOCTL_PHYSICAL_MEM_UNMAP\n")); 
 
            pIoBuffer->ReturnCode = 
                PlxPciPhysicalMemoryUnmap( 
                    pdx, 
                    &(pIoBuffer->u.MiscData.u.PciMemory), 
                    pStack->FileObject 
                    ); 
            break; 
 
        case PLX_IOCTL_COMMON_BUFFER_PROPERTIES: 
            DebugPrintf_NoInfo(("PLX_IOCTL_COMMON_BUFFER_PROPERTIES\n")); 
 
            // Return buffer information 
            if (pGbl_CommonBuffer == NULL) 
            { 
                pIoBuffer->u.MiscData.u.PciMemory.PhysicalAddr = 0; 
                pIoBuffer->u.MiscData.u.PciMemory.CpuPhysical  = 0; 
                pIoBuffer->u.MiscData.u.PciMemory.Size         = 0; 
            } 
            else 
            { 
                pIoBuffer->u.MiscData.u.PciMemory.PhysicalAddr = 
                                      pGbl_CommonBuffer->BusPhysical; 
                pIoBuffer->u.MiscData.u.PciMemory.CpuPhysical = 
                                      pGbl_CommonBuffer->CpuPhysical; 
                pIoBuffer->u.MiscData.u.PciMemory.Size = 
                                      pGbl_CommonBuffer->Size; 
            } 
            break; 
 
 
        /******************************************* 
         * PCI Register Access Functions 
         ******************************************/ 
        case PLX_IOCTL_PCI_REGISTER_READ: 
            DebugPrintf_NoInfo(("PLX_IOCTL_PCI_REGISTER_READ\n")); 
 
            pIoBuffer->u.MgmtData.value = 
                PlxPciRegisterRead( 
                    pdx, 
                    pIoBuffer->u.MgmtData.u.Device.BusNumber, 
                    pIoBuffer->u.MgmtData.u.Device.SlotNumber, 
                    pIoBuffer->u.MgmtData.offset, 
                    &(pIoBuffer->ReturnCode) 
                    ); 
 
            DebugPrintf(( 
                "PCI Reg %03X = %08X\n", 
                pIoBuffer->u.MgmtData.offset, 
                (U32)pIoBuffer->u.MgmtData.value 
                )); 
            break; 
 
        case PLX_IOCTL_PCI_REGISTER_WRITE: 
            DebugPrintf_NoInfo(("PLX_IOCTL_PCI_REGISTER_WRITE\n")); 
 
            pIoBuffer->ReturnCode = 
                PlxPciRegisterWrite( 
                    pdx, 
                    pIoBuffer->u.MgmtData.u.Device.BusNumber, 
                    pIoBuffer->u.MgmtData.u.Device.SlotNumber, 
                    pIoBuffer->u.MgmtData.offset, 
                    (U32)pIoBuffer->u.MgmtData.value 
                    ); 
 
            DebugPrintf(( 
                "Wrote %08X to PCI Reg %03X\n", 
                (U32)pIoBuffer->u.MgmtData.value, 
                pIoBuffer->u.MgmtData.offset 
                )); 
            break; 
 
        case PLX_IOCTL_PCI_REG_READ_UNSUPPORTED: 
            DebugPrintf_NoInfo(("PLX_IOCTL_PCI_REG_READ_UNSUPPORTED\n")); 
 
            pIoBuffer->u.MgmtData.value = 
                PlxPciRegisterRead_Unsupported( 
                    pdx, 
                    pIoBuffer->u.MgmtData.u.Device.BusNumber, 
                    pIoBuffer->u.MgmtData.u.Device.SlotNumber, 
                    pIoBuffer->u.MgmtData.offset, 
                    &(pIoBuffer->ReturnCode) 
                    ); 
            break; 
 
        case PLX_IOCTL_PCI_REG_WRITE_UNSUPPORTED: 
            DebugPrintf_NoInfo(("PLX_IOCTL_PCI_REG_WRITE_UNSUPPORTED\n")); 
 
            pIoBuffer->ReturnCode = 
                PlxPciRegisterWrite_Unsupported( 
                    pdx, 
                    pIoBuffer->u.MgmtData.u.Device.BusNumber, 
                    pIoBuffer->u.MgmtData.u.Device.SlotNumber, 
                    pIoBuffer->u.MgmtData.offset, 
                    (U32)pIoBuffer->u.MgmtData.value 
                    ); 
            break; 
 
 
        /*********************************** 
         * Local Register Access Functions 
         **********************************/ 
        case PLX_IOCTL_REGISTER_READ: 
            DebugPrintf_NoInfo(("PLX_IOCTL_REGISTER_READ\n")); 
 
            if (pdx->PowerState > MIN_WORKING_POWER_STATE) 
            { 
                pIoBuffer->ReturnCode       = ApiPowerDown; 
                pIoBuffer->u.MgmtData.value = (U32)-1; 
            } 
            else 
            { 
                pIoBuffer->ReturnCode = 
                    PlxRegisterRead( 
                        pdx, 
                        pIoBuffer->u.MgmtData.offset, 
                        (U32*)&(pIoBuffer->u.MgmtData.value) 
                        ); 
            } 
            break; 
 
        case PLX_IOCTL_REGISTER_WRITE: 
            DebugPrintf_NoInfo(("PLX_IOCTL_REGISTER_WRITE\n")); 
 
            if (pdx->PowerState > MIN_WORKING_POWER_STATE) 
            { 
                pIoBuffer->ReturnCode = ApiPowerDown; 
            } 
            else 
            { 
                pIoBuffer->ReturnCode = 
                    PlxRegisterWrite( 
                        pdx, 
                        pIoBuffer->u.MgmtData.offset, 
                        (U32)pIoBuffer->u.MgmtData.value 
                        ); 
            } 
            break; 
 
 
        /******************************** 
         * Interrupt Support Functions 
         *******************************/ 
        case PLX_IOCTL_INTR_ENABLE: 
            DebugPrintf_NoInfo(("PLX_IOCTL_INTR_ENABLE\n")); 
 
            if (pdx->PowerState > MIN_WORKING_POWER_STATE) 
            { 
                pIoBuffer->ReturnCode = ApiPowerDown; 
            } 
            else 
            { 
                pIoBuffer->ReturnCode = 
                    PlxPciIntrEnable( 
                        pdx, 
                        &(pIoBuffer->u.MiscData.u.IntrInfo) 
                        ); 
            } 
            break; 
 
        case PLX_IOCTL_INTR_DISABLE: 
            DebugPrintf_NoInfo(("PLX_IOCTL_INTR_DISABLE\n")); 
 
            if (pdx->PowerState > MIN_WORKING_POWER_STATE) 
            { 
                pIoBuffer->ReturnCode = ApiPowerDown; 
            } 
            else 
            { 
                pIoBuffer->ReturnCode = 
                    PlxPciIntrDisable( 
                        pdx, 
                        &(pIoBuffer->u.MiscData.u.IntrInfo) 
                        ); 
            } 
            break; 
 
        case PLX_IOCTL_INTR_STATUS_GET: 
            DebugPrintf_NoInfo(("PLX_IOCTL_INTR_STATUS_GET\n")); 
 
            pIoBuffer->ReturnCode = 
                PlxPciIntrStatusGet( 
                    pdx, 
                    &(pIoBuffer->u.MiscData.u.IntrInfo) 
                    ); 
            break; 
 
        case PLX_IOCTL_NOTIFICATION_REGISTER_FOR: 
            DebugPrintf_NoInfo(("PLX_IOCTL_NOTIFICATION_REGISTER_FOR\n")); 
 
            pIoBuffer->ReturnCode = 
                PlxNotificationRegisterFor( 
                    pdx, 
                    (PLX_INTR*)(pIoBuffer->u.MiscData.data[0]), 
                    (PLX_NOTIFY_OBJECT*)(pIoBuffer->u.MiscData.data[1]), 
                    pStack->FileObject 
                    ); 
            break; 
 
        case PLX_IOCTL_NOTIFICATION_WAIT: 
            DebugPrintf_NoInfo(("PLX_IOCTL_NOTIFICATION_WAIT\n")); 
 
            pIoBuffer->ReturnCode = 
                PlxNotificationWait( 
                    pdx, 
                    (PLX_NOTIFY_OBJECT*)(pIoBuffer->u.MiscData.data[0]), 
                    (U32)pIoBuffer->u.MiscData.data[1] 
                    ); 
            break; 
 
        case PLX_IOCTL_NOTIFICATION_CANCEL: 
            DebugPrintf_NoInfo(("PLX_IOCTL_NOTIFICATION_CANCEL\n")); 
 
            pIoBuffer->ReturnCode = 
                PlxNotificationCancel( 
                    pdx, 
                    (PLX_NOTIFY_OBJECT*)(pIoBuffer->u.MiscData.data[0]), 
                    pStack->FileObject 
                    ); 
            break; 
 
 
        /********************************* 
         * Bus Memory and I/O Functions 
         ********************************/ 
        case PLX_IOCTL_BUS_IOP_READ: 
            DebugPrintf_NoInfo(("PLX_IOCTL_BUS_IOP_READ\n")); 
 
            if (pdx->PowerState > MIN_WORKING_POWER_STATE) 
            { 
                pIoBuffer->ReturnCode = ApiPowerDown; 
            } 
            else 
            { 
                pIoBuffer->ReturnCode = 
                    PlxPciBusMemTransfer( 
                        pdx, 
                        pIoBuffer->u.BusIopData.IopSpace, 
                        (U32)pIoBuffer->u.BusIopData.Address, 
                        pIoBuffer->u.BusIopData.bRemap, 
                        PLX_INT_TO_PTR(pIoBuffer->u.BusIopData.Buffer), 
                        pIoBuffer->u.BusIopData.TransferSize, 
                        pIoBuffer->u.BusIopData.AccessType, 
                        TRUE           // Specify read operation 
                        ); 
            } 
            break; 
 
        case PLX_IOCTL_BUS_IOP_WRITE: 
            DebugPrintf_NoInfo(("PLX_IOCTL_BUS_IOP_WRITE\n")); 
 
            if (pdx->PowerState > MIN_WORKING_POWER_STATE) 
            { 
                pIoBuffer->ReturnCode = ApiPowerDown; 
            } 
            else 
            { 
                pIoBuffer->ReturnCode = 
                    PlxPciBusMemTransfer( 
                        pdx, 
                        pIoBuffer->u.BusIopData.IopSpace, 
                        (U32)pIoBuffer->u.BusIopData.Address, 
                        pIoBuffer->u.BusIopData.bRemap, 
                        PLX_INT_TO_PTR(pIoBuffer->u.BusIopData.Buffer), 
                        pIoBuffer->u.BusIopData.TransferSize, 
                        pIoBuffer->u.BusIopData.AccessType, 
                        FALSE          // Specify write operation 
                        ); 
            } 
            break; 
 
        case PLX_IOCTL_IO_PORT_READ: 
            DebugPrintf_NoInfo(("PLX_IOCTL_IO_PORT_READ\n")); 
 
            if (pdx->PowerState > MIN_WORKING_POWER_STATE) 
            { 
                pIoBuffer->ReturnCode = ApiPowerDown; 
            } 
            else 
            { 
                pIoBuffer->ReturnCode = 
                    PlxPciIoPortTransfer( 
                        pIoBuffer->u.BusIopData.Address, 
                        pIoBuffer->u.BusIopData.AccessType, 
                        (VOID*)&(pIoBuffer->u.BusIopData.Buffer), 
                        TRUE           // Specify read operation 
                        ); 
            } 
            break; 
 
        case PLX_IOCTL_IO_PORT_WRITE: 
            DebugPrintf_NoInfo(("PLX_IOCTL_IO_PORT_WRITE\n")); 
 
            if (pdx->PowerState > MIN_WORKING_POWER_STATE) 
            { 
                pIoBuffer->ReturnCode = ApiPowerDown; 
            } 
            else 
            { 
                pIoBuffer->ReturnCode = 
                    PlxPciIoPortTransfer( 
                        pIoBuffer->u.BusIopData.Address, 
                        pIoBuffer->u.BusIopData.AccessType, 
                        (VOID*)&(pIoBuffer->u.BusIopData.Buffer), 
                        FALSE          // Specify write operation 
                        ); 
            } 
            break; 
 
 
        /******************************* 
         * Power Management Functions 
         ******************************/ 
        case PLX_IOCTL_POWER_LEVEL_SET: 
            DebugPrintf_NoInfo(("PLX_IOCTL_POWER_LEVEL_SET\n")); 
 
            pIoBuffer->ReturnCode = 
                PlxPciPowerLevelSet( 
                    pdx, 
                    (PLX_POWER_LEVEL)(pIoBuffer->u.MgmtData.value) 
                    ); 
 
            if (pIoBuffer->ReturnCode == ApiSuccess) 
                pdx->PowerState = (PLX_POWER_LEVEL)(pIoBuffer->u.MgmtData.value); 
 
            break; 
 
        case PLX_IOCTL_POWER_LEVEL_GET: 
            DebugPrintf_NoInfo(("PLX_IOCTL_POWER_LEVEL_GET\n")); 
 
            pIoBuffer->ReturnCode = 
                PlxPciPowerLevelGet( 
                    pdx, 
                    (PLX_POWER_LEVEL*)&(pIoBuffer->u.MgmtData.value) 
                    ); 
            break; 
 
        case PLX_IOCTL_PM_NCP_READ: 
            DebugPrintf_NoInfo(("PLX_IOCTL_PM_NCP_READ\n")); 
 
            pIoBuffer->ReturnCode = 
                PlxPciPmNcpRead( 
                    pdx, 
                    (U8*)&(pIoBuffer->u.MgmtData.value) 
                    ); 
            break; 
 
 
        /*********************************** 
         *     Hot Swap Functions 
         **********************************/ 
        case PLX_IOCTL_HS_NCP_READ: 
            DebugPrintf_NoInfo(("PLX_IOCTL_HS_NCP_READ\n")); 
 
            pIoBuffer->ReturnCode = 
                PlxPciHotSwapNcpRead( 
                    pdx, 
                    (U8*)&(pIoBuffer->u.MgmtData.value) 
                    ); 
            break; 
 
        case PLX_IOCTL_HS_STATUS: 
            DebugPrintf_NoInfo(("PLX_IOCTL_HS_STATUS\n")); 
 
            pIoBuffer->ReturnCode = 
                PlxPciHotSwapStatus( 
                    pdx, 
                    (U8*)&(pIoBuffer->u.MgmtData.value) 
                    ); 
            break; 
 
 
        /*********************************** 
         *         VPD Functions 
         **********************************/ 
        case PLX_IOCTL_VPD_NCP_READ: 
            DebugPrintf_NoInfo(("PLX_IOCTL_VPD_NCP_READ\n")); 
 
            pIoBuffer->ReturnCode = 
                PlxPciVpdNcpRead( 
                    pdx, 
                    (U8*)&(pIoBuffer->u.MgmtData.value) 
                    ); 
            break; 
 
        case PLX_IOCTL_VPD_READ: 
            DebugPrintf_NoInfo(("PLX_IOCTL_VPD_READ\n")); 
 
            pIoBuffer->ReturnCode = 
                PlxPciVpdRead( 
                    pdx, 
                    pIoBuffer->u.MgmtData.offset, 
                    (U32*)&(pIoBuffer->u.MgmtData.value) 
                    ); 
            break; 
 
        case PLX_IOCTL_VPD_WRITE: 
            DebugPrintf_NoInfo(("PLX_IOCTL_VPD_WRITE\n")); 
 
            pIoBuffer->ReturnCode = 
                PlxPciVpdWrite( 
                    pdx, 
                    pIoBuffer->u.MgmtData.offset, 
                    (U32)pIoBuffer->u.MgmtData.value 
                    ); 
            break; 
 
 
        /*********************************** 
         * Serial EEPROM Access Functions 
         **********************************/ 
        case PLX_IOCTL_EEPROM_PRESENT: 
            DebugPrintf_NoInfo(("PLX_IOCTL_EEPROM_PRESENT\n")); 
 
            if (pdx->PowerState > MIN_WORKING_POWER_STATE) 
            { 
                pIoBuffer->ReturnCode = ApiPowerDown; 
            } 
            else 
            { 
                pIoBuffer->ReturnCode = 
                    PlxEepromPresent( 
                        pdx, 
                        &(pIoBuffer->u.MgmtData.u.bFlag) 
                        ); 
            } 
            break; 
 
        case PLX_IOCTL_EEPROM_READ_BY_OFFSET: 
            DebugPrintf_NoInfo(("PLX_IOCTL_EEPROM_READ_BY_OFFSET\n")); 
 
            if (pdx->PowerState > MIN_WORKING_POWER_STATE) 
            { 
                pIoBuffer->ReturnCode = ApiPowerDown; 
            } 
            else 
            { 
                pIoBuffer->ReturnCode = 
                    PlxEepromReadByOffset( 
                        pdx, 
                        pIoBuffer->u.MgmtData.offset, 
                        (U32*)&(pIoBuffer->u.MgmtData.value) 
                        ); 
            } 
            break; 
 
        case PLX_IOCTL_EEPROM_WRITE_BY_OFFSET: 
            DebugPrintf_NoInfo(("PLX_IOCTL_EEPROM_WRITE_BY_OFFSET\n")); 
 
            if (pdx->PowerState > MIN_WORKING_POWER_STATE) 
            { 
                pIoBuffer->ReturnCode = ApiPowerDown; 
            } 
            else 
            { 
                pIoBuffer->ReturnCode = 
                    PlxEepromWriteByOffset( 
                        pdx, 
                        pIoBuffer->u.MgmtData.offset, 
                        (U32)pIoBuffer->u.MgmtData.value 
                        ); 
            } 
            break; 
 
 
        /************************************************** 
         * Mailbox and Doorbell Register Access Functions 
         **************************************************/ 
        case PLX_IOCTL_MAILBOX_READ: 
            DebugPrintf_NoInfo(("PLX_IOCTL_MAILBOX_READ\n")); 
 
            if (pdx->PowerState > MIN_WORKING_POWER_STATE) 
            { 
                pIoBuffer->ReturnCode       = ApiPowerDown; 
                pIoBuffer->u.MgmtData.value = (U32)-1; 
            } 
            else 
            { 
                pIoBuffer->ReturnCode = 
                    PlxRegisterMailboxRead( 
                        pdx, 
                        pIoBuffer->u.MgmtData.offset, 
                        (U32*)&(pIoBuffer->u.MgmtData.value) 
                        ); 
            } 
            break; 
 
        case PLX_IOCTL_MAILBOX_WRITE: 
            DebugPrintf_NoInfo(("PLX_IOCTL_MAILBOX_WRITE\n")); 
 
            if (pdx->PowerState > MIN_WORKING_POWER_STATE) 
            { 
                pIoBuffer->ReturnCode = ApiPowerDown; 
            } 
            else 
            { 
                pIoBuffer->ReturnCode = 
                    PlxRegisterMailboxWrite( 
                        pdx, 
                        pIoBuffer->u.MgmtData.offset, 
                        (U32)pIoBuffer->u.MgmtData.value 
                        ); 
            } 
            break; 
 
        case PLX_IOCTL_DOORBELL_READ: 
            DebugPrintf_NoInfo(("PLX_IOCTL_DOORBELL_READ\n")); 
 
            if (pdx->PowerState > MIN_WORKING_POWER_STATE) 
            { 
                pIoBuffer->ReturnCode       = ApiPowerDown; 
                pIoBuffer->u.MgmtData.value = -1; 
            } 
            else 
            { 
                pIoBuffer->ReturnCode = 
                    PlxRegisterDoorbellRead( 
                        pdx, 
                        (U32*)&(pIoBuffer->u.MgmtData.value) 
                        ); 
            } 
            break; 
 
        case PLX_IOCTL_DOORBELL_WRITE: 
            DebugPrintf_NoInfo(("PLX_IOCTL_DOORBELL_WRITE\n")); 
 
            if (pdx->PowerState > MIN_WORKING_POWER_STATE) 
            { 
                pIoBuffer->ReturnCode = ApiPowerDown; 
            } 
            else 
            { 
                pIoBuffer->ReturnCode = 
                    PlxRegisterDoorbellWrite( 
                        pdx, 
                        (U32)pIoBuffer->u.MgmtData.value 
                        ); 
            } 
            break; 
 
 
        /**************************** 
         * Messaging Unit Functions 
         ****************************/ 
        case PLX_IOCTL_MU_INBOUND_PORT_READ: 
            DebugPrintf_NoInfo(("PLX_IOCTL_MU_INBOUND_PORT_READ\n")); 
 
            if (pdx->PowerState > MIN_WORKING_POWER_STATE) 
            { 
                pIoBuffer->ReturnCode = ApiPowerDown; 
            } 
            else 
            { 
                pIoBuffer->ReturnCode = 
                    PlxMuInboundPortRead( 
                        pdx, 
                        (U32*)&(pIoBuffer->u.MgmtData.value) 
                        ); 
            } 
            break; 
 
        case PLX_IOCTL_MU_INBOUND_PORT_WRITE: 
            DebugPrintf_NoInfo(("PLX_IOCTL_MU_INBOUND_PORT_WRITE\n")); 
 
            if (pdx->PowerState > MIN_WORKING_POWER_STATE) 
            { 
                pIoBuffer->ReturnCode = ApiPowerDown; 
            } 
            else 
            { 
                pIoBuffer->ReturnCode = 
                    PlxMuInboundPortWrite( 
                        pdx, 
                        (U32)pIoBuffer->u.MgmtData.value 
                        ); 
            } 
            break; 
 
        case PLX_IOCTL_MU_OUTBOUND_PORT_READ: 
            DebugPrintf_NoInfo(("PLX_IOCTL_MU_OUTBOUND_PORT_READ\n")); 
 
            if (pdx->PowerState > MIN_WORKING_POWER_STATE) 
            { 
                pIoBuffer->ReturnCode = ApiPowerDown; 
            } 
            else 
            { 
                pIoBuffer->ReturnCode = 
                    PlxMuOutboundPortRead( 
                        pdx, 
                        (U32*)&(pIoBuffer->u.MgmtData.value) 
                        ); 
            } 
            break; 
 
        case PLX_IOCTL_MU_OUTBOUND_PORT_WRITE: 
            DebugPrintf_NoInfo(("PLX_IOCTL_MU_OUTBOUND_PORT_WRITE\n")); 
 
            if (pdx->PowerState > MIN_WORKING_POWER_STATE) 
            { 
                pIoBuffer->ReturnCode = ApiPowerDown; 
            } 
            else 
            { 
                pIoBuffer->ReturnCode = 
                    PlxMuOutboundPortWrite( 
                        pdx, 
                        (U32)pIoBuffer->u.MgmtData.value 
                        ); 
            } 
            break; 
 
 
        /*********************************** 
         *    DMA Management Functions 
         **********************************/ 
        case PLX_IOCTL_DMA_CONTROL: 
            DebugPrintf_NoInfo(("PLX_IOCTL_DMA_CONTROL\n")); 
 
            if (pdx->PowerState > MIN_WORKING_POWER_STATE) 
            { 
                pIoBuffer->ReturnCode = ApiPowerDown; 
            } 
            else 
            { 
                pIoBuffer->ReturnCode = 
                    PlxDmaControl( 
                        pdx, 
                        pIoBuffer->u.DmaData.channel, 
                        pIoBuffer->u.DmaData.u.command 
                        ); 
            } 
            break; 
 
        case PLX_IOCTL_DMA_STATUS: 
            DebugPrintf_NoInfo(("PLX_IOCTL_DMA_STATUS\n")); 
 
            if (pdx->PowerState > MIN_WORKING_POWER_STATE) 
            { 
                pIoBuffer->ReturnCode = ApiPowerDown; 
            } 
            else 
            { 
                pIoBuffer->ReturnCode = 
                    PlxDmaStatus( 
                        pdx, 
                        pIoBuffer->u.DmaData.channel 
                        ); 
            } 
            break; 
 
 
        /*********************** 
         * Block DMA Functions 
         ***********************/ 
        case PLX_IOCTL_DMA_BLOCK_CHANNEL_OPEN: 
            DebugPrintf_NoInfo(("PLX_IOCTL_DMA_BLOCK_CHANNEL_OPEN\n")); 
 
            if (pdx->PowerState > MIN_WORKING_POWER_STATE) 
            { 
                pIoBuffer->ReturnCode = ApiPowerDown; 
            } 
            else 
            { 
                pIoBuffer->ReturnCode = 
                    PlxDmaBlockChannelOpen( 
                        pdx, 
                        pIoBuffer->u.DmaData.channel, 
                        &(pIoBuffer->u.DmaData.u.desc), 
                        pStack->FileObject 
                        ); 
            } 
            break; 
 
        case PLX_IOCTL_DMA_BLOCK_TRANSFER: 
            DebugPrintf_NoInfo(("PLX_IOCTL_DMA_BLOCK_TRANSFER\n")); 
 
            if (pdx->PowerState > MIN_WORKING_POWER_STATE) 
            { 
                pIoBuffer->ReturnCode = ApiPowerDown; 
            } 
            else 
            { 
                pIoBuffer->ReturnCode = 
                    PlxDmaBlockTransfer( 
                        pdx, 
                        pIoBuffer->u.DmaData.channel, 
                        &(pIoBuffer->u.DmaData.u.TxParams) 
                        ); 
            } 
            break; 
 
        case PLX_IOCTL_DMA_BLOCK_CHANNEL_CLOSE: 
            DebugPrintf_NoInfo(("PLX_IOCTL_DMA_BLOCK_CHANNEL_CLOSE\n")); 
 
            if (pdx->PowerState > MIN_WORKING_POWER_STATE) 
            { 
                pIoBuffer->ReturnCode = ApiPowerDown; 
            } 
            else 
            { 
                pIoBuffer->ReturnCode = 
                    PlxDmaBlockChannelClose( 
                        pdx, 
                        pIoBuffer->u.DmaData.channel, 
                        TRUE 
                        ); 
            } 
            break; 
 
 
        /********************** 
         * SGL DMA Functions 
         *********************/ 
        case PLX_IOCTL_DMA_SGL_OPEN: 
            DebugPrintf_NoInfo(("PLX_IOCTL_DMA_SGL_OPEN\n")); 
 
            if (pdx->PowerState > MIN_WORKING_POWER_STATE) 
            { 
                pIoBuffer->ReturnCode = ApiPowerDown; 
            } 
            else 
            { 
                pIoBuffer->ReturnCode = 
                    PlxDmaSglChannelOpen( 
                        pdx, 
                        pIoBuffer->u.DmaData.channel, 
                        &(pIoBuffer->u.DmaData.u.desc), 
                        pStack->FileObject 
                        ); 
            } 
            break; 
 
        case PLX_IOCTL_DMA_SGL_TRANSFER: 
            DebugPrintf_NoInfo(("PLX_IOCTL_DMA_SGL_TRANSFER\n")); 
 
            if (pdx->PowerState > MIN_WORKING_POWER_STATE) 
            { 
                pIoBuffer->ReturnCode = ApiPowerDown; 
            } 
            else 
            { 
                pIoBuffer->ReturnCode = 
                    PlxDmaSglTransfer( 
                        pdx, 
                        pIoBuffer->u.DmaData.channel, 
                        &(pIoBuffer->u.DmaData.u.TxParams) 
                        ); 
            } 
            break; 
 
        case PLX_IOCTL_DMA_SGL_CLOSE: 
            DebugPrintf_NoInfo(("PLX_IOCTL_DMA_SGL_CLOSE\n")); 
 
            if (pdx->PowerState > MIN_WORKING_POWER_STATE) 
            { 
                pIoBuffer->ReturnCode = ApiPowerDown; 
            } 
            else 
            { 
                pIoBuffer->ReturnCode = 
                    PlxDmaSglChannelClose( 
                        pdx, 
                        pIoBuffer->u.DmaData.channel, 
                        TRUE 
                        ); 
            } 
            break; 
 
 
        /***************************** 
         *   Unsupported Messages 
         ****************************/ 
        default: 
            DebugPrintf_NoInfo(( 
                "Unsupported PLX_IOCTL_Xxx (0x%08x)\n", 
                pStack->Parameters.DeviceIoControl.IoControlCode 
                )); 
 
            pIoBuffer->ReturnCode = ApiUnsupportedFunction; 
            break; 
    } 
 
    PlxUnlockDevice( 
        pdx 
        ); 
 
    return PlxCompleteIrp( 
               pIrp, 
               STATUS_SUCCESS 
               ); 
}