📄 tffsdrv26.c
字号:
struct file * filp ){ int rc = 0; /* assume success */ struct gendisk * gd = inode->i_bdev->bd_disk; DeviceInfo * pdisk = (DeviceInfo *) gd->private_data; if (pdisk == NULL) return -ENODEV; /* one Open/Close at a time */ if( down_interruptible(&open_close_mutex) != 0 ) return -ERESTARTSYS; /* wait was interrupted by signal */ /* can't open write-protected disk for writing */ if (filp->f_mode & O_RDWR) {#ifndef TFFS_RO if( TffsIsWriteProtected(pdisk) )#endif { rc = -EROFS; goto quit; } } if (pdisk->in_use == 0) { if( TffsOpenDevice(pdisk) == 0 ) { PrintkError("Open() failed on %s(0x%x)", gd->disk_name, pdisk->bHandle); rc = -ENODEV; goto quit; } } /* success opening this disk */ filp->private_data = pdisk; /* one more user for this device, as well as for DiskOnChip driver */ pdisk->in_use++; quit: /* allow other Open/Close calls to proceed */ up (&open_close_mutex); return rc;}/******************************************************************************* * * * d i s k _ c l o s e * * * * Release disk (i.e. block_device_operations.release()). * * * * Parameters: * * * * inode inode pointer * * filp file pointer (could be NULL) * * * * Returns: zero if success, otherwise negative error code * * * *******************************************************************************/staticint disk_close ( struct inode * inode, struct file * filp ){ struct gendisk * gd = inode->i_bdev->bd_disk; DeviceInfo * pdisk = (DeviceInfo *) gd->private_data; /* one Open/Close at a time */ if( down_interruptible(&open_close_mutex) != 0 ) return -ERESTARTSYS; /* wait was interrupted by signal */ if (--pdisk->in_use == 0) /* last user had just closed this disk */ { if( TffsCloseDevice(pdisk) == 0 ) { PrintkDebug("Release() failed on %s(0x%x)", gd->disk_name, pdisk->bHandle); } } /* allow other Open/Close calls to proceed */ up (&open_close_mutex); return 0;}/******************************************************************************* * * * d i s k _ i o c t l * * * * Handle IOCTLs to disk (i.e. device_operations.ioctl()). * * * * Parameters: * * * * inode inode pointer * * filp file pointer (could be NULL) * * cmd IOCTL command * * arg argument to IOCTL command * * * * Returns: zero if success, otherwise negative error code * * * *******************************************************************************/static int disk_ioctl ( struct inode * inode, struct file * filp, unsigned int cmd, unsigned long arg ){ struct gendisk * gd = inode->i_bdev->bd_disk; DeviceInfo * pdisk = (DeviceInfo *) gd->private_data; int rc = -ENOTTY; /* sanity check */ if ((filp != NULL) && (filp->private_data != pdisk)) return -ENODEV; if (cmd >= SIOCDEVPRIVATE) /* driver specific (TrueFFS) IOCTL code */ { rc = TffsIoctl (pdisk, (cmd - SIOCDEVPRIVATE), arg); if (rc < 0) PrintkError("ioctl=0x%x error=0x%x on %s", cmd, rc, gd->disk_name); if (rc == 1) /* unrecognized TrueFFS IOCTL code */ rc = -ENOTTY; } else /* standard Linux IOCTL code */ { switch (cmd) { case HDIO_GETGEO: { struct hd_geometry geo; geo.heads = pdisk->bHead; geo.sectors = pdisk->bSect; geo.cylinders = pdisk->wCyl; geo.start = get_start_sect (inode->i_bdev); if ((void *)arg == NULL) { rc = -EINVAL; break; } if( !access_ok(VERIFY_WRITE, (void *)arg, sizeof(geo))) { rc = -EFAULT; break; } if( copy_to_user((void *)arg, &geo, sizeof(geo)) != 0 ) { rc = -EFAULT; break; } rc = 0; /* success */ } break; default: /* unknown Linux IOCTL code */ { PrintkError("unknown ioctl=0x%x on %s", cmd, gd->disk_name); } } } return rc;}/******************************************************************************* * * * i n t e r r u p t _ h a n d l e r * * * * DiskOnChip interupt handler. * * * * Parameters: * * * * irq not used * * psoc socket pointer * * regs not used * * * * Returns: always IRQ_HANDLED * * * *******************************************************************************/static irqreturn_t interrupt_handler ( int irq, /* not used */ void * psoc, struct pt_regs * regs ) /* not used */{ tffs_irq_disable (FALSE); profiling[1]++; /* wake up socket's I/O thread */ up (&((SocketInfo *)psoc)->sleep_sem); return IRQ_HANDLED;}/******************************************************************************* * * * t f f s _i r q _ e n a b l e * * * * Enable IRQ that DiskOnChip is connected to. * * * * Parameters: * * * * lock if TRUE, use __irq_lock; otherwise don't * * * *******************************************************************************/void tffs_irq_enable (int lock){ unsigned long flags; if (lock == TRUE) spin_lock_irqsave (&__irq_lock, flags); if (__irq_enabled == FALSE) { __irq_enabled = TRUE; enable_irq (tffs_irq);#ifdef CONFIG_ARCH_OMAP24XX omap24xx_enable_gpio_irq (tffs_irq, TRUE);#endif } if (lock == TRUE) spin_unlock_irqrestore (&__irq_lock, flags);}/******************************************************************************* * * * t f f s _i r q _ d i s a b l e * * * * Disable IRQ that DiskOnChip is connected to. * * * * Parameters: * * * * lock if TRUE, use __irq_lock; otherwise don't * * * *******************************************************************************/void tffs_irq_disable (int lock){ unsigned long flags; if (lock == TRUE) spin_lock_irqsave (&__irq_lock, flags); if (__irq_enabled == TRUE) { __irq_enabled = FALSE;#ifdef CONFIG_ARCH_OMAP24XX omap24xx_enable_gpio_irq (tffs_irq, FALSE);#endif disable_irq (tffs_irq); } if (lock == TRUE) spin_unlock_irqrestore (&__irq_lock, flags);}/******************************************************************************* * * * d i s k _ r e q u e s t _ q u e u e _ h a n d l e r * * * * This routine implements request handling function for per-disk request * * queue. It's called by generic_unplug_device (drivers/block/ll_rw_block.c) * * with request queue's lock held, and both hardware and software interrupts * * disabled (so it must be fast). * * * * Parameters: * * q disk's request queue * * * *******************************************************************************/staticvoid disk_request_queue_handler (request_queue_t * q){ struct request * r; SocketInfo * psoc; DeviceInfo * pdisk; int lock_taken = FALSE; /* we run with hardware and software interrupts disabled */ while ((r = elv_next_request(q)) != NULL) { /* take this request off disk's request queue */ blkdev_dequeue_request (r); if (lock_taken == FALSE) { pdisk = r->rq_disk->private_data; psoc = pdisk->pSocket; spin_lock (&psoc->request_list_lock); lock_taken = TRUE; } /* Append this request to socket's request list. Socket's * I/O thread will take it from there, handle it, and cycle * it back to this queue. */ list_add_tail (&r->queuelist, &psoc->requestsList); } if (lock_taken == TRUE) { spin_unlock (&psoc->request_list_lock); /* in case socket's I/O thread is currently sleeping, wake it up */ wake_up (&psoc->waitQueueHead); }}/******************************************************************************* * * * s o c k e t _ i o _ t h r e a d * * * * This routine implements per-socket I/O thread. It runs as a kernel thread, * * and processes I/O requests that disk_request_queue_handler() put to * * socket's request list. This routine can (and often does) sleep. * * * * Parameters: * * arg socket pointer * * *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -