www.pudn.com > PlxSdk.rar > Dispatch.c
/******************************************************************************* * Copyright (c) 2007 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-07 : PLX SDK v5.00 * ******************************************************************************/ #include#include #include #include "ApiFunctions.h" #include "Dispatch.h" #include "Driver.h" #include "PciSupport.h" #include "PlxIoctl.h" #include "SupportFunc.h" /****************************************************************************** * * Function : Dispatch_open * * Description: Handle open() which allows applications to create a * connection to the driver * ******************************************************************************/ int Dispatch_open( struct inode *inode, struct file *filp ) { int rc; U8 i; DEVICE_OBJECT *fdo; DebugPrintf_NoInfo(("\n")); DebugPrintf(("Received message ==> OPEN_DEVICE\n")); if (iminor(inode) == PLX_MNGMT_INTERFACE) { DebugPrintf(("Opening Management interface...\n")); // Store the driver object in the private data filp->private_data = pGbl_DriverObject; } else { // Select desired device from device list i = iminor(inode); fdo = pGbl_DriverObject->DeviceObject; while (i-- && fdo != NULL) fdo = fdo->NextDevice; if (fdo == NULL) { ErrorPrintf(("WARNING - Attempt to open non-existent device\n")); return (-ENODEV); } DebugPrintf(( "Opening device (%s)...\n", fdo->DeviceExtension->LinkName )); // Acquire Open lock spin_lock( &(fdo->DeviceExtension->Lock_DeviceOpen) ); // Attempt to start the device rc = StartDevice( fdo ); if (rc != 0) { // Release Open lock spin_unlock( &(fdo->DeviceExtension->Lock_DeviceOpen) ); return rc; } // Increment open count for this device fdo->DeviceExtension->OpenCount++; // Release Open lock spin_unlock( &(fdo->DeviceExtension->Lock_DeviceOpen) ); // Store device object for future calls filp->private_data = fdo; } DebugPrintf(("...device opened\n")); return 0; } /****************************************************************************** * * Function : Dispatch_release * * Description: Handle close() call, which closes the connection between the * application and drivers. * ******************************************************************************/ int Dispatch_release( struct inode *inode, struct file *filp ) { DEVICE_OBJECT *fdo; DebugPrintf_NoInfo(("\n")); DebugPrintf(("Received message ==> CLOSE_DEVICE\n")); if (iminor(inode) == PLX_MNGMT_INTERFACE) { DebugPrintf(("Closing Management interface...\n")); // Clear the driver object from the private data filp->private_data = NULL; } else { // Get the device object fdo = (DEVICE_OBJECT *)(filp->private_data); DebugPrintf(( "Closing device (%s)...\n", fdo->DeviceExtension->LinkName )); // Release any pending notifications owned by proccess PlxNotificationCancel( fdo->DeviceExtension, NULL, filp ); // Release any physical memory allocated by process PlxPciPhysicalMemoryFreeAll_ByOwner( fdo->DeviceExtension, filp ); // Decrement open count for this device spin_lock( &(fdo->DeviceExtension->Lock_DeviceOpen) ); fdo->DeviceExtension->OpenCount--; // Stop the device if no longer used if (fdo->DeviceExtension->OpenCount == 0) { StopDevice( fdo ); } spin_unlock( &(fdo->DeviceExtension->Lock_DeviceOpen) ); } DebugPrintf(("...device closed\n")); return 0; } /****************************************************************************** * * Function : Dispatch_mmap * * Description: Maps a PCI space into user virtual space * ******************************************************************************/ int Dispatch_mmap( struct file *filp, struct vm_area_struct *vma ) { int rc; off_t offset; BOOLEAN bDeviceMem; PLX_UINT_PTR AddressToMap; DEVICE_EXTENSION *pdx; DebugPrintf_NoInfo(("\n")); DebugPrintf(("Received message ===> MMAP\n")); // Get device extension pdx = ((DEVICE_OBJECT*)(filp->private_data))->DeviceExtension; // Get the supplied offset offset = vma->vm_pgoff; // Determine if mapping to a PCI BAR or system memory switch (offset) { case 0: case 1: case 2: case 3: case 4: case 5: // Verify space is not I/O if (pdx->PciBar[offset].Properties.bIoSpace) { DebugPrintf(( "ERROR - PCI BAR %d is an I/O space, cannot map to user space\n", (U8)offset )); return -ENODEV; } DebugPrintf(( "Mapping PCI BAR %d...\n", (U8)offset )); // Use the BAR physical address for the mapping AddressToMap = (PLX_UINT_PTR)pdx->PciBar[offset].Properties.Physical; // Flag that the mapping is to IO memory bDeviceMem = TRUE; break; default: // Use provided offset as CPU physical address for mapping AddressToMap = (PLX_UINT_PTR)offset << PAGE_SHIFT; // Flag that the mapping is to system memory bDeviceMem = FALSE; break; } // Verify physical address if (AddressToMap == 0) { DebugPrintf(( "ERROR - Invalid physical (0x%08lx), cannot map to user space\n", AddressToMap )); return -ENODEV; } /*********************************************************** * Attempt to map the region * * NOTE: * * Due to variations in the remap function between kernel releases * and distributions, a PLX macro is used to simplify code * readability. For additional information about the macro * expansions, refer to the file "Plx_sysdep.h". **********************************************************/ // Set the region as page-locked vma->vm_flags |= VM_RESERVED; if (bDeviceMem) { // Set flag for I/O resource vma->vm_flags |= VM_IO; // The region must be marked as non-cached vma->vm_page_prot = pgprot_noncached( vma->vm_page_prot ); // Map device memory rc = Plx_io_remap_pfn_range( vma, vma->vm_start, AddressToMap >> PAGE_SHIFT, vma->vm_end - vma->vm_start, vma->vm_page_prot ); } else { // Map system memory rc = Plx_remap_pfn_range( vma, vma->vm_start, AddressToMap >> PAGE_SHIFT, vma->vm_end - vma->vm_start, vma->vm_page_prot ); } if (rc != 0) { DebugPrintf(( "ERROR - Unable to map Physical (0x%08lx) ==> User space\n", AddressToMap )); } else { DebugPrintf(( "Mapped Phys (0x%08lx) ==> User VA (0x%08lx)\n", AddressToMap, vma->vm_start )); } DebugPrintf(("...Completed message\n")); return rc; } /****************************************************************************** * * Function : Dispatch_IoControl * * Description: Processes the IOCTL messages sent to this device * ******************************************************************************/ int Dispatch_IoControl( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long args ) { int status; VOID *pOwner; PLX_PARAMS IoBuffer; PLX_PARAMS *pIoBuffer; DEVICE_EXTENSION *pdx; DebugPrintf_NoInfo(("\n")); // Get the device extension if (iminor(inode) == PLX_MNGMT_INTERFACE) { // Management interface node only supports some IOCTLS pdx = NULL; } else { pdx = ((DEVICE_OBJECT*)(filp->private_data))->DeviceExtension; } // Copy the I/O Control message from user space status = copy_from_user( &IoBuffer, (PLX_PARAMS*)args, sizeof(PLX_PARAMS) ); if (status != 0) { ErrorPrintf(( "ERROR - Unable to copy user I/O message data\n" )); return (-EFAULT); } // Track the owner pOwner = filp; pIoBuffer = &IoBuffer; DebugPrintf(("Received PLX message ===> ")); // Handle the PLX specific message switch (cmd) { /****************************************** * Driver Query Functions *****************************************/ case PLX_IOCTL_PCI_DEVICE_FIND: DebugPrintf_NoInfo(("PLX_IOCTL_PCI_DEVICE_FIND\n")); pIoBuffer->ReturnCode = PlxDeviceFind( pdx, &(pIoBuffer->Key), (U8*)&(pIoBuffer->value[0]) ); break; case PLX_IOCTL_DRIVER_VERSION: DebugPrintf_NoInfo(("PLX_IOCTL_DRIVER_VERSION\n")); pIoBuffer->value[0] = (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")); pIoBuffer->ReturnCode = PlxChipTypeGet( pdx, &(pIoBuffer->Key), (U32*)&(pIoBuffer->value[0]), (U8*)&(pIoBuffer->value[1]) ); break; case PLX_IOCTL_CHIP_TYPE_SET: DebugPrintf_NoInfo(("PLX_IOCTL_CHIP_TYPE_SET\n")); pIoBuffer->ReturnCode = PlxChipTypeSet( pdx, &(pIoBuffer->Key), (U32)pIoBuffer->value[0], (U8)pIoBuffer->value[1] ); break; case PLX_IOCTL_GET_PORT_PROPERTIES: DebugPrintf_NoInfo(("PLX_IOCTL_GET_PORT_PROPERTIES\n")); pIoBuffer->ReturnCode = PlxGetPortProperties( pdx, &(pIoBuffer->Key), &(pIoBuffer->u.PortProp) ); break; /****************************************** * Device Control Functions *****************************************/ case PLX_IOCTL_PCI_BOARD_RESET: DebugPrintf_NoInfo(("PLX_IOCTL_PCI_BOARD_RESET\n")); pIoBuffer->ReturnCode = PlxPciBoardReset( pdx, &(pIoBuffer->Key) ); break; /****************************************** * PCI Register Access Functions *****************************************/ case PLX_IOCTL_PCI_REGISTER_READ: DebugPrintf_NoInfo(("PLX_IOCTL_PCI_REGISTER_READ\n")); pIoBuffer->ReturnCode = PlxPciRegisterRead( pIoBuffer->Key.bus, pIoBuffer->Key.slot, pIoBuffer->Key.function, (U16)pIoBuffer->value[0], (U32*)&(pIoBuffer->value[1]) ); DebugPrintf(( "PCI Reg %03X = %08X\n", (U16)pIoBuffer->value[0], (U32)pIoBuffer->value[1] )); break; case PLX_IOCTL_PCI_REGISTER_WRITE: DebugPrintf_NoInfo(("PLX_IOCTL_PCI_REGISTER_WRITE\n")); pIoBuffer->ReturnCode = PlxPciRegisterWrite( pIoBuffer->Key.bus, pIoBuffer->Key.slot, pIoBuffer->Key.function, (U16)pIoBuffer->value[0], (U32)pIoBuffer->value[1] ); DebugPrintf(( "Wrote %08X to PCI Reg %03X\n", (U32)pIoBuffer->value[1], (U16)pIoBuffer->value[0] )); break; case PLX_IOCTL_PCI_REG_READ_UNSUPPORTED: DebugPrintf_NoInfo(("PLX_IOCTL_PCI_REG_READ_UNSUPPORTED\n")); pIoBuffer->ReturnCode = PlxPciRegisterRead_Unsupported( pIoBuffer->Key.bus, pIoBuffer->Key.slot, pIoBuffer->Key.function, (U16)pIoBuffer->value[0], (U32*)&(pIoBuffer->value[1]) ); break; case PLX_IOCTL_PCI_REG_WRITE_UNSUPPORTED: DebugPrintf_NoInfo(("PLX_IOCTL_PCI_REG_WRITE_UNSUPPORTED\n")); pIoBuffer->ReturnCode = PlxPciRegisterWrite_Unsupported( pIoBuffer->Key.bus, pIoBuffer->Key.slot, pIoBuffer->Key.function, (U16)pIoBuffer->value[0], (U32)pIoBuffer->value[1] ); break; /****************************************** * PLX-specific Register Access Functions *****************************************/ case PLX_IOCTL_REGISTER_READ: DebugPrintf_NoInfo(("PLX_IOCTL_REGISTER_READ\n")); pIoBuffer->value[1] = PlxRegisterRead( pdx, &(pIoBuffer->Key), (U32)pIoBuffer->value[0], &(pIoBuffer->ReturnCode), TRUE // Adjust offset based on port ); DebugPrintf(( "PLX Reg %03X = %08X\n", (U32)pIoBuffer->value[0], (U32)pIoBuffer->value[1] )); break; case PLX_IOCTL_REGISTER_WRITE: DebugPrintf_NoInfo(("PLX_IOCTL_REGISTER_WRITE\n")); pIoBuffer->ReturnCode = PlxRegisterWrite( pdx, &(pIoBuffer->Key), (U32)pIoBuffer->value[0], (U32)pIoBuffer->value[1], TRUE // Adjust offset based on port ); DebugPrintf(( "Wrote %08X to PLX Reg %03X\n", (U32)pIoBuffer->value[1], (U32)pIoBuffer->value[0] )); break; case PLX_IOCTL_MAPPED_REGISTER_READ: DebugPrintf_NoInfo(("PLX_IOCTL_MAPPED_REGISTER_READ\n")); pIoBuffer->value[1] = PlxRegisterRead( pdx, &(pIoBuffer->Key), (U32)pIoBuffer->value[0], &(pIoBuffer->ReturnCode), FALSE // Don't adjust offset based on port ); DebugPrintf(( "PLX Mapped Reg %03X = %08X\n", (U32)pIoBuffer->value[0], (U32)pIoBuffer->value[1] )); break; case PLX_IOCTL_MAPPED_REGISTER_WRITE: DebugPrintf_NoInfo(("PLX_IOCTL_MAPPED_REGISTER_WRITE\n")); pIoBuffer->ReturnCode = PlxRegisterWrite( pdx, &(pIoBuffer->Key), (U32)pIoBuffer->value[0], (U32)pIoBuffer->value[1], FALSE // Don't adjust offset based on port ); DebugPrintf(( "Wrote %08X to PLX Mapped Reg %03X\n", (U32)pIoBuffer->value[1], (U32)pIoBuffer->value[0] )); break; /****************************************** * PCI Mapping Functions *****************************************/ case PLX_IOCTL_PCI_BAR_PROPERTIES: DebugPrintf_NoInfo(("PLX_IOCTL_PCI_BAR_PROPERTIES\n")); pIoBuffer->ReturnCode = PlxPciBarProperties( pdx, &(pIoBuffer->Key), (U8)(pIoBuffer->value[0]), &(pIoBuffer->u.BarProp) ); break; case PLX_IOCTL_PCI_BAR_MAP: DebugPrintf_NoInfo(("PLX_IOCTL_PCI_BAR_MAP\n")); pIoBuffer->ReturnCode = PlxPciBarMap( pdx, &(pIoBuffer->Key), (U8)(pIoBuffer->value[0]), &(pIoBuffer->value[1]), pOwner ); break; case PLX_IOCTL_PCI_BAR_UNMAP: DebugPrintf_NoInfo(("PLX_IOCTL_PCI_BAR_UNMAP\n")); pIoBuffer->ReturnCode = PlxPciBarUnmap( pdx, &(pIoBuffer->Key), PLX_INT_TO_PTR(pIoBuffer->value[1]), pOwner ); break; /****************************************** * Serial EEPROM Access Functions *****************************************/ case PLX_IOCTL_EEPROM_PRESENT: DebugPrintf_NoInfo(("PLX_IOCTL_EEPROM_PRESENT\n")); pIoBuffer->ReturnCode = PlxEepromPresent( pdx, &(pIoBuffer->Key), (PLX_EEPROM_STATUS*)&(pIoBuffer->value[0]) ); break; case PLX_IOCTL_EEPROM_PROBE: DebugPrintf_NoInfo(("PLX_IOCTL_EEPROM_PROBE\n")); pIoBuffer->ReturnCode = PlxEepromProbe( pdx, &(pIoBuffer->Key), (BOOLEAN*)&(pIoBuffer->value[0]) ); break; case PLX_IOCTL_EEPROM_CRC_GET: DebugPrintf_NoInfo(("PLX_IOCTL_EEPROM_CRC_GET\n")); pIoBuffer->ReturnCode = PlxEepromCrcGet( pdx, &(pIoBuffer->Key), (U32*)&(pIoBuffer->value[0]), (U8*)&(pIoBuffer->value[1]) ); break; case PLX_IOCTL_EEPROM_CRC_UPDATE: DebugPrintf_NoInfo(("PLX_IOCTL_EEPROM_CRC_UPDATE\n")); pIoBuffer->ReturnCode = PlxEepromCrcUpdate( pdx, &(pIoBuffer->Key), (U32*)&(pIoBuffer->value[0]), (BOOLEAN)pIoBuffer->value[1] ); break; case PLX_IOCTL_EEPROM_READ_BY_OFFSET: DebugPrintf_NoInfo(("PLX_IOCTL_EEPROM_READ_BY_OFFSET\n")); pIoBuffer->ReturnCode = PlxEepromReadByOffset( pdx, &(pIoBuffer->Key), (U16)pIoBuffer->value[0], (U32*)&(pIoBuffer->value[1]) ); DebugPrintf(( "EEPROM Offset %02X = %08X\n", (U16)pIoBuffer->value[0], (U32)pIoBuffer->value[1] )); break; case PLX_IOCTL_EEPROM_WRITE_BY_OFFSET: DebugPrintf_NoInfo(("PLX_IOCTL_EEPROM_WRITE_BY_OFFSET\n")); pIoBuffer->ReturnCode = PlxEepromWriteByOffset( pdx, &(pIoBuffer->Key), (U16)pIoBuffer->value[0], (U32)pIoBuffer->value[1] ); DebugPrintf(( "Wrote %08X to EEPROM Offset %02X\n", (U32)pIoBuffer->value[1], (U16)pIoBuffer->value[0] )); break; case PLX_IOCTL_EEPROM_READ_BY_OFFSET_16: DebugPrintf_NoInfo(("PLX_IOCTL_EEPROM_READ_BY_OFFSET_16\n")); pIoBuffer->ReturnCode = PlxEepromReadByOffset_16( pdx, &(pIoBuffer->Key), (U16)pIoBuffer->value[0], (U16*)&(pIoBuffer->value[1]) ); DebugPrintf(( "EEPROM Offset %02X = %04X\n", (U16)pIoBuffer->value[0], (U16)pIoBuffer->value[1] )); break; case PLX_IOCTL_EEPROM_WRITE_BY_OFFSET_16: DebugPrintf_NoInfo(("PLX_IOCTL_EEPROM_WRITE_BY_OFFSET_16\n")); pIoBuffer->ReturnCode = PlxEepromWriteByOffset_16( pdx, &(pIoBuffer->Key), (U16)pIoBuffer->value[0], (U16)pIoBuffer->value[1] ); DebugPrintf(( "Wrote %04X to EEPROM Offset %02X\n", (U16)pIoBuffer->value[1], (U16)pIoBuffer->value[0] )); break; /****************************************** * I/O Port Access Functions *****************************************/ case PLX_IOCTL_IO_PORT_READ: DebugPrintf_NoInfo(("PLX_IOCTL_IO_PORT_READ\n")); pIoBuffer->ReturnCode = PlxPciIoPortTransfer( pIoBuffer->value[0], PLX_INT_TO_PTR(pIoBuffer->u.TxParams.u.UserVa), pIoBuffer->u.TxParams.ByteCount, (PLX_ACCESS_TYPE)pIoBuffer->value[1], TRUE // Specify read operation ); break; case PLX_IOCTL_IO_PORT_WRITE: DebugPrintf_NoInfo(("PLX_IOCTL_IO_PORT_WRITE\n")); pIoBuffer->ReturnCode = PlxPciIoPortTransfer( pIoBuffer->value[0], PLX_INT_TO_PTR(pIoBuffer->u.TxParams.u.UserVa), pIoBuffer->u.TxParams.ByteCount, (PLX_ACCESS_TYPE)pIoBuffer->value[1], FALSE // Specify write operation ); break; /****************************************** * Physical Memory Functions *****************************************/ case PLX_IOCTL_PHYSICAL_MEM_ALLOCATE: DebugPrintf_NoInfo(("PLX_IOCTL_PHYSICAL_MEM_ALLOCATE\n")); pIoBuffer->ReturnCode = PlxPciPhysicalMemoryAllocate( pdx, &(pIoBuffer->u.PciMemory), (BOOLEAN)(pIoBuffer->value[0]), pOwner ); break; case PLX_IOCTL_PHYSICAL_MEM_FREE: DebugPrintf_NoInfo(("PLX_IOCTL_PHYSICAL_MEM_FREE\n")); pIoBuffer->ReturnCode = PlxPciPhysicalMemoryFree( pdx, &(pIoBuffer->u.PciMemory) ); break; case PLX_IOCTL_PHYSICAL_MEM_MAP: DebugPrintf_NoInfo(("PLX_IOCTL_PHYSICAL_MEM_MAP\n")); pIoBuffer->ReturnCode = PlxPciPhysicalMemoryMap( pdx, &(pIoBuffer->u.PciMemory), pOwner ); break; case PLX_IOCTL_PHYSICAL_MEM_UNMAP: DebugPrintf_NoInfo(("PLX_IOCTL_PHYSICAL_MEM_UNMAP\n")); pIoBuffer->ReturnCode = PlxPciPhysicalMemoryUnmap( pdx, &(pIoBuffer->u.PciMemory), pOwner ); break; case PLX_IOCTL_COMMON_BUFFER_PROPERTIES: DebugPrintf_NoInfo(("PLX_IOCTL_COMMON_BUFFER_PROPERTIES\n")); pIoBuffer->ReturnCode = ApiSuccess; // Return buffer information pIoBuffer->u.PciMemory.PhysicalAddr = pGbl_DriverObject->CommonBuffer.BusPhysical; pIoBuffer->u.PciMemory.CpuPhysical = pGbl_DriverObject->CommonBuffer.CpuPhysical; pIoBuffer->u.PciMemory.Size = pGbl_DriverObject->CommonBuffer.Size; break; /****************************************** * Interrupt Support Functions *****************************************/ case PLX_IOCTL_INTR_ENABLE: DebugPrintf_NoInfo(("PLX_IOCTL_INTR_ENABLE\n")); pIoBuffer->ReturnCode = PlxInterruptEnable( pdx, &(pIoBuffer->u.PlxIntr) ); break; case PLX_IOCTL_INTR_DISABLE: DebugPrintf_NoInfo(("PLX_IOCTL_INTR_DISABLE\n")); pIoBuffer->ReturnCode = PlxInterruptDisable( pdx, &(pIoBuffer->u.PlxIntr) ); break; case PLX_IOCTL_NOTIFICATION_REGISTER_FOR: DebugPrintf_NoInfo(("PLX_IOCTL_NOTIFICATION_REGISTER_FOR\n")); pIoBuffer->ReturnCode = PlxNotificationRegisterFor( pdx, &(pIoBuffer->u.PlxIntr), (VOID**)&(pIoBuffer->value[0]), pOwner ); break; case PLX_IOCTL_NOTIFICATION_WAIT: DebugPrintf_NoInfo(("PLX_IOCTL_NOTIFICATION_WAIT\n")); pIoBuffer->ReturnCode = PlxNotificationWait( pdx, PLX_INT_TO_PTR(pIoBuffer->value[0]), (PLX_UINT_PTR)pIoBuffer->value[1] ); break; case PLX_IOCTL_NOTIFICATION_STATUS: DebugPrintf_NoInfo(("PLX_IOCTL_NOTIFICATION_STATUS\n")); pIoBuffer->ReturnCode = PlxNotificationStatus( pdx, PLX_INT_TO_PTR(pIoBuffer->value[0]), &(pIoBuffer->u.PlxIntr) ); break; case PLX_IOCTL_NOTIFICATION_CANCEL: DebugPrintf_NoInfo(("PLX_IOCTL_NOTIFICATION_CANCEL\n")); pIoBuffer->ReturnCode = PlxNotificationCancel( pdx, PLX_INT_TO_PTR(pIoBuffer->value[0]), pOwner ); break; /****************************************** * Unsupported Messages *****************************************/ default: DebugPrintf_NoInfo(( "Unsupported PLX_IOCTL_Xxx (%02d)\n", _IOC_NR(cmd) )); pIoBuffer->ReturnCode = ApiUnsupportedFunction; break; } DebugPrintf(("...Completed message\n")); status = copy_to_user( (PLX_PARAMS*)args, pIoBuffer, sizeof(PLX_PARAMS) ); return status; }