#include <linux/fs.h>
#include <linux/delay.h>
#include <linux/spinlock.h>
-//#include <linux/smp_lock.h>
-//#include <linux/mutex.h>
-
#include <linux/mm.h>
#include <linux/pagemap.h>
#include <linux/highmem.h>
#define pexor_dbg( args... ) ;
#endif
-
#define pexor_msg( args... ) \
printk( args );
unsigned long bases[6]; /* contains pci resource bases */
unsigned long reglen[6]; /* contains pci resource length */
void* iomem[6]; /* points to mapped io memory of the bars */
- struct semaphore sem; /* lock semaphore */
- spinlock_t dma_lock; /* protects DMA Buffer */
+ struct semaphore sem_buf; /* lock semaphore for DMA buffer */
+ struct semaphore sem_ioctl; /* lock semaphore for ioctl operations */
+ spinlock_t spin_lock0; /* Spin Lock #0 */
struct pexor_dma dma; /* dma buffer */
u32* memwrite_buffer; /* buffer for register_write_mem */
static unsigned char get_pci_revision(struct pci_dev* dev);
#endif
-ssize_t pexor_sysfs_codeversion_show(struct device* dev,
- struct device_attribute* attr,
- char* buf);
+static ssize_t pexor_sysfs_codeversion_show(struct device* dev,
+ struct device_attribute* attr,
+ char* buf
+ );
-void test_pci(struct pci_dev* dev);
+static void test_pci(struct pci_dev* dev);
-void cleanup_device(struct pexor_privdata* priv);
+static void cleanup_device(struct pexor_privdata* priv);
struct pexor_privdata* get_privdata(struct file* filp);
-void set_pexor(struct dev_pexor* pg,
- void* membase,
- unsigned long bar);
+static void set_pexor(struct dev_pexor* pg,
+ void* membase,
+ unsigned long bar
+ );
static int probe(struct pci_dev* dev,
- const struct pci_device_id* id);
+ const struct pci_device_id* id
+ );
-int pexor_open(struct inode* inode,
- struct file* filp);
+static int pexor_open(struct inode* inode,
+ struct file* filp);
-int pexor_release(struct inode* inode,
- struct file* filp);
+static int pexor_release(struct inode* inode,
+ struct file* filp
+ );
-ssize_t pexor_read(struct file* filp,
- char __user * buf,
- size_t count,
- loff_t* f_pos);
+static ssize_t pexor_read(struct file* filp,
+ char __user * buf,
+ size_t count,
+ loff_t* f_pos
+ );
-ssize_t pexor_write(struct file* filp,
- const char __user * buf,
- size_t count,
- loff_t* f_pos);
+static ssize_t pexor_write(struct file* filp,
+ const char __user * buf,
+ size_t count,
+ loff_t* f_pos
+ );
-loff_t pexor_llseek(struct file* filp,
- loff_t off,
- int whence);
+static loff_t pexor_llseek(struct file* filp,
+ loff_t off,
+ int whence
+ );
-int pexor_mmap(struct file* filp,
- struct vm_area_struct* vma);
+static int pexor_mmap(struct file* filp,
+ struct vm_area_struct* vma
+ );
-int pexor_ioctl_read_register(struct pexor_privdata* priv,
- unsigned long arg);
-int pexor_ioctl_write_register(struct pexor_privdata* priv,
- unsigned long arg);
+static int pexor_ioctl(struct inode* inode,
+ struct file* filp,
+ unsigned int cmd,
+ unsigned long arg
+ );
-int pexor_ioctl_trbnet_request(struct pexor_privdata* priv,
- unsigned long arg);
+static int pexor_ioctl_read_register(struct pexor_privdata* priv,
+ unsigned long arg
+ );
-int pexor_ioctl(struct inode* inode,
- struct file* filp,
- unsigned int cmd,
- unsigned long arg);
+static int pexor_ioctl_write_register(struct pexor_privdata* priv,
+ unsigned long arg
+ );
+
+static int pexor_ioctl_trbnet_request(struct pexor_privdata* priv,
+ unsigned long arg
+ );
static void remove(struct pci_dev* dev);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
long pexor_unlocked_ioctl(struct file* filp,
unsigned int cmd,
- unsigned long arg);
+ unsigned long arg
+ );
#endif
static int pexor_alloc_dma_buffer(struct pexor_privdata* priv,
- size_t size);
+ size_t size
+ );
static int pexor_free_dma_buffer(struct pexor_privdata* priv);
struct pexor_privdata* get_privdata(struct file* filp)
{
- struct pexor_privdata* privdata;
- privdata = (struct pexor_privdata*)filp->private_data;
- if (privdata->pexor.init_done == 0) {
+ struct pexor_privdata* priv = (struct pexor_privdata*)filp->private_data;
+ if (priv->pexor.init_done == 0) {
pexor_dbg(KERN_ERR "*** PEXOR structure was not initialized!\n");
return NULL;
}
- return privdata;
+ return priv;
}
#ifdef PEXOR_DEBUGPRINT
(long unsigned int)pg);
}
-static int probe(struct pci_dev* dev,
- const struct pci_device_id* id)
+int probe(struct pci_dev* dev,
+ const struct pci_device_id* id)
{
int err = 0, ix = 0;
- struct pexor_privdata* privdata;
+ struct pexor_privdata* priv;
pexor_msg(KERN_NOTICE "PEXOR pci driver starts probe...\n");
if ((err = pci_enable_device(dev)) != 0) {
pexor_msg(KERN_ERR
test_pci(dev);
/* Allocate and initialize the private data for this device */
- privdata = kmalloc(sizeof(struct pexor_privdata), GFP_KERNEL);
- if (privdata == NULL) {
- cleanup_device(privdata);
+ priv = kmalloc(sizeof(struct pexor_privdata), GFP_KERNEL);
+ if (priv == NULL) {
+ cleanup_device(priv);
return -ENOMEM;
}
- memset(privdata, 0, sizeof(struct pexor_privdata));
- pci_set_drvdata(dev, privdata);
- privdata->pdev = dev;
- privdata->magic = PEXOR_DEVICE_ID; /* for IRQ test TODO: what if multiple
- pexors share same irq? */
+ memset(priv, 0, sizeof(struct pexor_privdata));
+ pci_set_drvdata(dev, priv);
+ priv->pdev = dev;
+ priv->magic = PEXOR_DEVICE_ID; /* for IRQ test TODO: what if multiple
+ pexors share same irq? */
- atomic_set(&(privdata->state), PEXOR_STATE_STOPPED);
+ atomic_set(&(priv->state), PEXOR_STATE_STOPPED);
for (ix = 0; ix < 6; ix++) {
- privdata->bases[ix] = pci_resource_start(dev, ix);
- privdata->reglen[ix] = pci_resource_len(dev, ix);
- if (privdata->bases[ix] == 0)
+ priv->bases[ix] = pci_resource_start(dev, ix);
+ priv->reglen[ix] = pci_resource_len(dev, ix);
+ if (priv->bases[ix] == 0) {
continue;
+ }
if ((pci_resource_flags(dev, ix) & IORESOURCE_IO)) {
printk(KERN_NOTICE " - Requesting io ports for bar %d\n", ix);
- if (request_region(privdata->bases[ix], privdata->reglen[ix],
+ if (request_region(priv->bases[ix], priv->reglen[ix],
dev->dev.kobj.name) == NULL) {
printk(KERN_ERR
"I/O address conflict at bar %d for device \"%s\"\n", ix,
dev->dev.kobj.name);
- cleanup_device(privdata);
+ cleanup_device(priv);
return -EIO;
}
printk("requested ioport at %lx with length %lx\n",
- privdata->bases[ix], privdata->reglen[ix]);
+ priv->bases[ix], priv->reglen[ix]);
} else if ((pci_resource_flags(dev, ix) & IORESOURCE_MEM)) {
printk(KERN_NOTICE " - Requesting memory region for bar %d\n", ix);
- if (request_mem_region(privdata->bases[ix], privdata->reglen[ix],
+ if (request_mem_region(priv->bases[ix], priv->reglen[ix],
dev->dev.kobj.name) == NULL) {
printk(KERN_ERR
"Memory address conflict at bar %d for device \"%s\"\n", ix,
dev->dev.kobj.name);
- cleanup_device(privdata);
+ cleanup_device(priv);
return -EIO;
}
printk("requested memory at %lx with length %lx\n",
- privdata->bases[ix], privdata->reglen[ix]);
- privdata->iomem[ix] =
- ioremap_nocache(privdata->bases[ix], privdata->reglen[ix]);
- if (privdata->iomem[ix] == NULL) {
+ priv->bases[ix], priv->reglen[ix]);
+ priv->iomem[ix] =
+ ioremap_nocache(priv->bases[ix], priv->reglen[ix]);
+ if (priv->iomem[ix] == NULL) {
printk(KERN_ERR
"Could not remap memory at bar %d for device \"%s\"\n", ix,
dev->dev.kobj.name);
- cleanup_device(privdata);
+ cleanup_device(priv);
return -EIO;
}
printk("remapped memory to %lx with length %lx\n",
- (unsigned long)privdata->iomem[ix], privdata->reglen[ix]);
+ (unsigned long)priv->iomem[ix], priv->reglen[ix]);
}
} //for
- set_pexor(&(privdata->pexor), privdata->iomem[0], privdata->bases[0]);
+ set_pexor(&(priv->pexor), priv->iomem[0], priv->bases[0]);
- sema_init(&(privdata->sem), 1);
- spin_lock_init(&(privdata->dma_lock));
- /* TODO may use rw semaphore instead? init_rwsem(struct
- rw_semaphore* sem); */
+ /* Initialize Semaphore Locks */
+ sema_init(&(priv->sem_buf), 1);
+ sema_init(&(priv->sem_ioctl), 1);
+
+ /* Initialize Spin Locks, not needed at the moment */
+ spin_lock_init(&(priv->spin_lock0));
////////////////// here chardev registering
- privdata->devid = atomic_inc_return(&pexor_numdevs) - 1;
- if (privdata->devid >= PEXOR_MAX_DEVS) {
+ priv->devid = atomic_inc_return(&pexor_numdevs) - 1;
+ if (priv->devid >= PEXOR_MAX_DEVS) {
pexor_msg(KERN_ERR
"Maximum number of devices reached! Increase MAXDEVICES.\n");
- cleanup_device(privdata);
+ cleanup_device(priv);
return -ENOMSG;
}
- privdata->devno
- = MKDEV(MAJOR(pexor_devt), MINOR(pexor_devt) + privdata->devid);
+ priv->devno = MKDEV(MAJOR(pexor_devt), MINOR(pexor_devt) + priv->devid);
/* Register character device */
- cdev_init(&(privdata->cdev), &pexor_fops);
- privdata->cdev.owner = THIS_MODULE;
- privdata->cdev.ops = &pexor_fops;
- err = cdev_add(&privdata->cdev, privdata->devno, 1);
+ cdev_init(&(priv->cdev), &pexor_fops);
+ priv->cdev.owner = THIS_MODULE;
+ priv->cdev.ops = &pexor_fops;
+ err = cdev_add(&priv->cdev, priv->devno, 1);
if (err) {
pexor_msg("Couldn't add character device.\n");
- cleanup_device(privdata);
+ cleanup_device(priv);
return err;
}
if (!IS_ERR(pexor_class)) {
/* driver init had successfully created class, now we create device: */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
- privdata->class_dev = device_create(pexor_class, NULL, privdata->devno,
- privdata, PEXOR_NAME_FMT,
- MINOR(pexor_devt) + privdata->devid);
+ priv->class_dev = device_create(pexor_class, NULL, priv->devno,
+ priv, PEXOR_NAME_FMT,
+ MINOR(pexor_devt) + priv->devid);
#else
- privdata->class_dev = device_create(pexor_class, NULL, privdata->devno,
- PEXOR_NAME_FMT,
- MINOR(pexor_devt) + privdata->devid);
+ priv->class_dev = device_create(pexor_class, NULL, priv->devno,
+ PEXOR_NAME_FMT,
+ MINOR(pexor_devt) + priv->devid);
#endif
- dev_set_drvdata(privdata->class_dev, privdata);
+ dev_set_drvdata(priv->class_dev, priv);
pexor_msg(KERN_NOTICE "Added PEXOR device: %s-%d\n",
- PEXOR_NAME, MINOR(pexor_devt) + privdata->devid);
+ PEXOR_NAME, MINOR(pexor_devt) + priv->devid);
- if (device_create_file(privdata->class_dev, &dev_attr_codeversion) != 0) {
+ if (device_create_file(priv->class_dev, &dev_attr_codeversion) != 0) {
pexor_msg(KERN_ERR
"Could not add device file node for code version.\n");
}
}
/* init pexor_dma buffer */
- if (pexor_alloc_dma_buffer(privdata, DMA_BUFFER_NUM_PAGES * PAGE_SIZE) != 0) {
+ if (pexor_alloc_dma_buffer(priv, DMA_BUFFER_NUM_PAGES * PAGE_SIZE) != 0) {
pexor_msg(KERN_ERR "ERROR> probe init dma failed\n");
return -EFAULT;
}
/* allocate memwrite_buffer */
- privdata->memwrite_buffer = vmalloc_32_user(PEXOR_MEMWRITE_SIZE * 4);
- if (privdata->memwrite_buffer == NULL) {
+ priv->memwrite_buffer = vmalloc_32_user(PEXOR_MEMWRITE_SIZE * 4);
+ if (priv->memwrite_buffer == NULL) {
pexor_msg(KERN_ERR "ERROR> probe allocate memwrite_buffer failed\n");
return -ENOMEM;
}
int pexor_open(struct inode* inode, struct file* filp)
{
- struct pexor_privdata* privdata;
+ struct pexor_privdata* priv = NULL;
+
pexor_dbg(KERN_NOTICE "** starting pexor_open...\n");
+
/* Set the private data area for the file */
- privdata = container_of(inode->i_cdev, struct pexor_privdata, cdev);
- filp->private_data = privdata;
+ priv = container_of(inode->i_cdev, struct pexor_privdata, cdev);
+ filp->private_data = priv;
return 0;
}
int pexor_release(struct inode* inode, struct file* filp)
{
- printk(KERN_NOTICE "** starting pexor_release...\n");
+ pexor_dbg(KERN_NOTICE "** starting pexor_release...\n");
+
return 0;
}
size_t count,
loff_t* f_pos)
{
+
/* here we read from dma buffer */
- struct pexor_privdata* privdata;
+ struct pexor_privdata* priv = NULL;
ssize_t retval = 0;
-
+
/* u32 kbuf[lcount]; */
pexor_dbg(KERN_NOTICE "** starting pexor_read for f_pos=%d count=%d\n",
(int)*f_pos, (int)count);
- privdata = get_privdata(filp);
- if (privdata == NULL) {
- return -EFAULT;
+
+ /* Request Semaphore */
+ if (down_interruptible(&priv->sem_buf) != 0) {
+ printk(KERN_ERR "pexor_read: could not get Semaphore sem_buf\n");
+ return -ERESTARTSYS;
+ }
+
+ priv = get_privdata(filp);
+ if (priv == NULL) {
+ retval= -EFAULT;
+ goto out_read;
}
- if (count > privdata->dma.size * PAGE_SIZE) {
+
+ if (count > priv->dma.size * PAGE_SIZE) {
pexor_msg(KERN_ERR "ERROR> pexor_read: requested count (%d) > Max: %d\n",
- (int)(count / 4), (int)privdata->dma.size);
- return -EFAULT;
+ (int)(count / 4), (int)priv->dma.size);
+ retval = -EFAULT;
+ goto out_read;
}
+
if (count > pexor_read_buffer_ctr) {
pexor_msg(KERN_ERR "ERROR> pexor_read: requested count (%d) > "
"Buffer: %d\n",
(int)count, (int)pexor_read_buffer_ctr);
- return -EFAULT;
+ retval = -EFAULT;
+ goto out_read;
}
pexor_read_buffer_ctr -= count;
-
- if (down_interruptible(&privdata->sem) != 0) {
- return -ERESTARTSYS;
- }
- if (copy_to_user(buf, privdata->dma.buffer, count)) {
+
+ if (copy_to_user(buf, priv->dma.buffer, count)) {
pexor_msg(KERN_ERR "ERROR> pexor_read: copy_to_user failed\n");
retval = -EFAULT;
goto out_read;
retval = count;
out_read:
- up(&privdata->sem);
+ up(&priv->sem_buf);
return retval;
}
loff_t* f_pos)
{
/* here we read from dma buffer */
- struct pexor_privdata* privdata;
+ struct pexor_privdata* priv = NULL;
ssize_t retval = 0;
- /* u32 kbuf[lcount]; */
pexor_dbg(KERN_NOTICE "** starting pexor_write for f_pos=%d count=%d\n",
(int)*f_pos, (int)count);
- privdata = get_privdata(filp);
- if (privdata == NULL) {
- return -EFAULT;
+
+ /* Request Semaphore */
+ if (down_interruptible(&priv->sem_buf) != 0) {
+ printk(KERN_ERR "pexor_write: could not get Semaphore sem_buf\n");
+ return -ERESTARTSYS;
}
+
+ /* u32 kbuf[lcount]; */
+ priv = get_privdata(filp);
+ if (priv == NULL) {
+ retval = -EFAULT;
+ goto out_write;
+ }
+
if (count > 4 * PEXOR_MEMWRITE_SIZE) {
- return -EFAULT;
+ retval = -EFAULT;
+ goto out_write;
}
- if (down_interruptible(&privdata->sem) != 0) {
- return -ERESTARTSYS;
- }
- if (copy_from_user((void* )privdata->memwrite_buffer, buf, count)) {
+
+ if (copy_from_user((void* )priv->memwrite_buffer, buf, count)) {
retval = -EFAULT;
- goto out_read;
+ goto out_write;
}
*f_pos += count;
retval = count;
- out_read:
- up(&privdata->sem);
+ out_write:
+ up(&priv->sem_buf);
return retval;
}
int pexor_mmap(struct file* filp,
struct vm_area_struct* vma)
{
- struct pexor_privdata* privdata;
+#ifdef PEXOR_MMAP_ENABLED
+ struct pexor_privdata* priv;
char* vmalloc_area_ptr = NULL;
unsigned long size;
unsigned long start;
unsigned long pfn;
int ret = 0;
- privdata = get_privdata(filp);
+ priv = get_privdata(filp);
pexor_dbg(KERN_NOTICE "** starting pexor_mmap...\n");
- if (privdata == NULL)
+ if (priv == NULL)
return -EFAULT;
- vmalloc_area_ptr = privdata->dma.buffer;
+ vmalloc_area_ptr = priv->dma.buffer;
start = vma->vm_start;
size = (vma->vm_end - vma->vm_start);
"** starting pexor_mmap for s:%lx e:%lx size=%ld\n",
vma->vm_start, vma->vm_end, size);
- if (size > privdata->dma.size) {
+ if (size > priv->dma.size) {
return -EFAULT;
}
pfn = vmalloc_to_pfn(vmalloc_area_ptr);
if ((ret = remap_pfn_range(vma, start, pfn, PAGE_SIZE, PAGE_SHARED)) < 0) {
pexor_dbg(KERN_ERR "kmem remap failed: %d (%p)\n",
- ret, privdata->dma.buffer);
+ ret, priv->dma.buffer);
return ret;
}
start += PAGE_SIZE;
vmalloc_area_ptr += PAGE_SIZE;
size -= PAGE_SIZE;
}
+
+ return 0;
-#if 0
- /* map kernel addresses to vma */
- // vma->vm_flags |= (VM_RESERVED); /* TODO: do we need this?*/
- /* der scheiss geht nicht!!! */
- ret = remap_vmalloc_range(vma, privdata->dma.buffer, 0);
+#else
+ /* MMAP is not suppoprted and needed up to now */
+ return EFAULT;
#endif
-
- return 0;
}
+/* ---------------------------------------------------------------------- */
+/* -- PEXOR PCI Handler Processes */
+/* ---------------------------------------------------------------------- */
#define iowrite32_mb( args... ) \
iowrite32( args ); wmb();
int bar = 0;
struct pexor_reg_io descriptor;
- spin_lock((&(priv->dma_lock)));
-
+ /* Request Semaphore */
+ if (down_interruptible(&priv->sem_ioctl) != 0) {
+ printk(KERN_ERR
+ "pexor_ioctl_read_register: could not get Semaphore sem_buf\n");
+ return -ERESTARTSYS;
+ }
+
retval = copy_from_user(&descriptor, (void __user *)arg,
sizeof(struct pexor_reg_io));
if (retval != 0) {
retval = copy_to_user((void __user *)arg, &descriptor,
sizeof(struct pexor_reg_io));
OUT_READ_REG:
- spin_unlock((&(priv->dma_lock)));
+ up(&priv->sem_ioctl);
return retval;
}
u32 val = 0;
int bar = 0;
struct pexor_reg_io descriptor;
-
- spin_lock((&(priv->dma_lock)));
- retval =
- copy_from_user(&descriptor, (void __user *)arg,
- sizeof(struct pexor_reg_io));
+ /* Request Semaphore */
+ if (down_interruptible(&priv->sem_ioctl) != 0) {
+ printk(KERN_ERR
+ "pexor_ioctl_write_register: could not get Semaphore sem_buf\n");
+ return -ERESTARTSYS;
+ }
+
+ retval = copy_from_user(&descriptor, (void __user *)arg,
+ sizeof(struct pexor_reg_io));
if (retval != 0) {
goto OUT_WRITE_REG;
}
udelay(UDELAY_TIME);
OUT_WRITE_REG:
- spin_unlock((&(priv->dma_lock)));
+ up(&priv->sem_ioctl);
return retval;
}
-
DEFINE_MUTEX(fs_mutex);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
unsigned int cmd,
unsigned long arg)
{
- struct pexor_privdata* privdata;
+ struct pexor_privdata* priv;
/* here validity check for magic number etc. */
- privdata = get_privdata(filp);
- if (!privdata)
+ priv = get_privdata(filp);
+ if (!priv) {
return -EFAULT;
+ }
+
/* Select the appropiate command */
switch (cmd) {
-
+
/* first all common ioctls: */
-
case PEXOR_IOC_WRITE_REGISTER:
pexor_dbg(KERN_NOTICE "** pexor_ioctl write register\n");
- return pexor_ioctl_write_register(privdata, arg);
- break;
-
+ return pexor_ioctl_write_register(priv, arg);
+
case PEXOR_IOC_READ_REGISTER:
pexor_dbg(KERN_NOTICE "** pexor_ioctl read register\n");
- return pexor_ioctl_read_register(privdata, arg);
- break;
-
-
+ return pexor_ioctl_read_register(priv, arg);
+
/* special ioctls for different protocol implementations: */
-
case PEXOR_IOC_TRBNET_REQUEST:
pexor_dbg(KERN_NOTICE "** pexor_ioctl trbnet request \n");
- return pexor_ioctl_trbnet_request(privdata, arg);
- break;
-
+ return pexor_ioctl_trbnet_request(priv, arg);
+
default:
return -ENOTTY;
}
+
return -ENOTTY;
}
-static int __init pexor_init(void)
+int __init pexor_init(void)
{
int result;
/* ------ TRBNet Specific ----------------------------------------------- */
-static int pexor_free_dma_buffer(struct pexor_privdata* priv)
+int pexor_free_dma_buffer(struct pexor_privdata* priv)
{
/* free sglist */
if (priv->dma.sglist != NULL) {
return 0;
}
-static int pexor_alloc_dma_buffer(struct pexor_privdata* priv,
- size_t size)
+int pexor_alloc_dma_buffer(struct pexor_privdata* priv,
+ size_t size)
{
struct page* pg = NULL;
unsigned long uaddr = 0;
#define MASK_HEADER_TYPE (0x0007 << SHIFT_HEADER_TYPE)
#define HEADER_TRM 0x0003
-static int pexor_copy_fifo_to_dma(struct pexor_privdata* priv,
- unsigned int channel)
+int pexor_copy_fifo_to_dma(struct pexor_privdata* priv,
+ unsigned int channel)
{
unsigned int sg_ctr;
unsigned int sg_length;
unsigned int dmaSize = 0;
struct pexor_trbnet_io descriptor;
- spin_lock((&(priv->dma_lock)));
+ /* Request Semaphore */
+ if (down_interruptible(&priv->sem_ioctl) != 0) {
+ printk(KERN_ERR
+ "pexor_ioctl_trbnet_request: could not get Semaphore sem_buf\n");
+ return -ERESTARTSYS;
+ }
if (copy_from_user(&descriptor,
(void __user *)arg, sizeof(struct pexor_trbnet_io))) {
}
OUT_IOCTL:
- spin_unlock((&(priv->dma_lock)));
+ up(&priv->sem_ioctl);
return status;
}