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

📄 tffsdrv26.c

📁 H3 M-system NAND flash driver in Linux OS, M-DOC driver
💻 C
📖 第 1 页 / 共 5 页
字号:
                 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 + -