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

📄 tffsdrv26.c

📁 H3 M-system NAND flash driver in Linux OS, M-DOC driver
💻 C
📖 第 1 页 / 共 5 页
字号:
/****************************************************************************** *                                                                            * * Project: DOC Driver for Linux 2.6 Block device driver for mDOC H3  family  * * of devices under Linux kernel 2.6.                                         * *                                                                            * *   Version: 1.0                                                             * *   Email questions to: oemsupport@sandisk.com                               * *   Copyright (C) SanDisk IL Ltd. 1995 - 2007                                * *   SanDisk IL Ltd., 7 Atir Yeda Street, Kfar Saba 44425, Israel             * *                                                                            * ****************************************************************************** *                                                                            * * This program is free software; you can redistribute it and/or modify it    * * under the terms of the GNU General Public License as published by the Free * * Software Foundation; either version 2 of the License, or any later version.* * This program is distributed in the hope that it will be useful, but WITHOUT* * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or      * * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for  * * more details, which is set forth in the readme.txt file.                   * * You should have received a copy of the GNU General Public License along    * * with this program; if not, write to the Free Software Foundation, Inc., 51 * * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA                    * *                                                                            * * This License does not grant you any right to use the trademarks, service   * * marks or logos of SanDisk IL Ltd. or SanDisk Corporation.                  * * Subject to the foregoing, SanDisk IL Ltd., for itself and on behalf of its * * licensors, hereby reserves all intellectual property rights in the program,* * except for the rights expressly granted in this License.                   * *                                                                            * ******************************************************************************//* * $Log$ */#include "tffsdrv.h"#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))#include "tffs2lnx.h"#include "flbase.h"MODULE_AUTHOR("M-Systems");MODULE_DESCRIPTION("TrueFFS driver");MODULE_LICENSE("GPL");MODULE_SUPPORTED_DEVICE(TFFS_SUPPORTED_DEVICE);/*  * module parameters *//* major device # to use */int tffs_major = 100;module_param(tffs_major, int, S_IRUGO);MODULE_PARM_DESC(tffs_major, "major device number, zero to use dynamic.");/* priority of driver's I/O threads */static int tffs_prio = 0;    /* max -20, min 19 */module_param(tffs_prio, int, (S_IRUGO | S_IWUSR));MODULE_PARM_DESC(tffs_prio,"priority of DiskOnChip I/O thread.");/* interrupt line that DiskOnChip's IREQ is connected to */int tffs_irq = TFFS_IRQ;module_param(tffs_irq, int, S_IRUGO);MODULE_PARM_DESC(tffs_irq, "Interrupt line DiskOnChip's IREQ is connected to.");/* DMA mode. Allowed modes are: *      0 (don't use DMA) *      1 (use s/w DMA in read operations only; uses intermediate DMA buffer) *      2 (use s/w DMA in write operations only; uses intermediate DMA buffer) *      3 (combined 1 and 2) *      5 (use s/w DMA for direct transfers from user source buffers) *      6 (use s/w DMA for direct transfers to user dest. buffers) *      7 (combined 5 and 6) * Default is don't use DMA. */int tffs_dma_mode = 0;module_param(tffs_dma_mode, int, S_IRUGO);MODULE_PARM_DESC(tffs_dma_mode, "DMA mode (0, 1, 2, 3, 5, 6 or 7).");/* Automatic Deep PowerDown mode. Allowed modes are 0 (default; disabled), * or 1 (enabled). When enabled, Automatic Deep PowerDown mode will cause * DiskOnChip driver to power down DiskOnChip after completion of every  * read/write operation, and power it up again before starting the next one. */int tffs_auto_dpd = FL_OFF;module_param(tffs_auto_dpd, int, S_IRUGO);MODULE_PARM_DESC(tffs_auto_dpd, "Powerdown DiskOnChip after every operation (1), or don't (0).");/* Upon completion of every read/write access, DiskOnChip H3 devices * immediately switch from the normal mode into the idle mode, and stay * in the idle mode for 'DOCH_DPD_DEFAULT_DPD_TIMEOUT' milliseconds before * switching into deep-power-down mode. */int tffs_dpd_timeout = 1;module_param(tffs_dpd_timeout, int, S_IRUGO);MODULE_PARM_DESC(tffs_dpd_timeout, "Time (in milliseconds) before DiskOnChip automatically powers itself down.");/* Read data from DiskOnChip into scatter/gather buffer, then scatter it to * destination buffers. Allowed values are TRUE (scatter data) or FALSE (don't). */int tffs_sg_read = TRUE;module_param(tffs_sg_read, int, S_IRUGO);MODULE_PARM_DESC(tffs_sg_read, "Use scatter/gather during read operations.");/* Gather data from source buffers into scatter/gather buffer before writing * it to DiskOnChip. Allowed values are TRUE (gather data) or FALSE (don't). */int tffs_sg_write = TRUE;module_param(tffs_sg_write, int, S_IRUGO);MODULE_PARM_DESC(tffs_sg_write, "Use scatter/gather during write operations.");/* size of scatter/gather buffer in bytes; must be multiple of PAGE_SIZE */int tffs_sg_bufsize = (16 * PAGE_SIZE);module_param(tffs_sg_bufsize, int, S_IRUGO);MODULE_PARM_DESC(tffs_sg_bufsize, "Size of scatter/gather buffer, in bytes.");/* * macros */#ifndef _MIN#  define _MIN(a,b)  ((a) < (b) ? (a) : (b))#endif/* * types */struct scatter_t      /* scatter buffer for READ requests */{    char         * buf;                   /* starting address                  */    char         * pcurrent;    unsigned int   size;                  /* size of buffer in bytes           */    unsigned int   remaining_bytes;    sector_t       start_sector;          /* starting disk sector #            */    unsigned int   sectors;               /* remaining sectors in this request */};struct gather_t       /* gather buffer for WRITE requests */{    char         * buf;                   /* starting address              */    char         * free;                  /* free part fo the buffer       */    unsigned int   size;                  /* size of buffer in bytes       */    unsigned int   free_bytes;            /* remaining free space in bytes */    sector_t       start_sector;          /* starting disk sector #        */};/* * global vars */int  write_requests = 0;/* * static routines */static int  /* __init */ __tffs_module_init (void);static void /* __init */ init_socket (SocketInfo *psoc);static void /* __init */ init_disk (DeviceInfo *pdisk);static void /* __exit */ release_socket (SocketInfo *psoc);static void /* __exit */ release_disk (DeviceInfo * pdisk);static void cleanup (int STEP);static void disk_request_queue_handler (request_queue_t *q);static int  socket_io_thread (void *arg);static int  requests_to_do (SocketInfo *psoc);static void do_requests_list (SocketInfo *psoc);static int  do_write_request (struct request *r);static int  do_read_request (struct request *r);static int  rw_bio_no_sg (struct bio *bio, DeviceInfo *pdisk, int rw);static int  write_bio (struct bio *bio, struct gather_t *gather, DeviceInfo *pdisk);static int  read_bio (struct bio *bio, struct scatter_t *scatter, DeviceInfo *pdisk);static int  disk_open (struct inode *inode, struct file *filp);static int  disk_close (struct inode *inode, struct file *filp);static int  disk_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);static irqreturn_t  interrupt_handler (int irq, void *psoc, struct pt_regs *regs);#ifdef CONFIG_PROC_FS  static int /* __init */ procfs_register (DeviceInfo *pdisk);  static int /* __exit */ procfs_unregister (DeviceInfo *pdisk);  static int procfs_write (struct file* file, const char* buffer, unsigned long count, void* data);  static int procfs_read (char* buffer, char** start, off_t offset, int length, int* eof, void* data);#endif/* * static vars */static struct semaphore  open_close_mutex;  /* used to serialize disk open/close calls */static char  tffs_str[] = TFFS_DEVICE_NAME;static struct block_device_operations  tffs_bdev_ops ={    .open    = disk_open,    .release = disk_close,    .ioctl   = disk_ioctl,    .owner   = THIS_MODULE};/* for tracking enabled/disabled state of IRQ that DiskOnChip is connected to */static spinlock_t __irq_lock = SPIN_LOCK_UNLOCKED;#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_MAINSTONE) || defined(CONFIG_MACH_MAINSTONE)  static int __irq_enabled = TRUE;#else  static int __irq_enabled = FALSE;#endif/******************************************************************************* *                                                                             * *                     t f f s _ m o d u l e _ i n i t                         * *                                                                             * *  Module initialization routine.                                             * *                                                                             * *  Parameters: none                                                           * *                                                                             * *  Returns: zero if success, otherwise standard negative error code           * *                                                                             * *******************************************************************************/int  /* __init */ tffs_module_init (void){# ifdef TRACE32   /* needed for section relocation in TRACE32 */    extern int       trace32_data;    extern int       trace32_bss;    extern const int trace32_rodata;    printk ("\n\nTRACE32 section relocation: .data=0x%lx .bss=0x%lx .rodata=0x%lx\n\n",               (long)(&trace32_data), (long)(&trace32_bss), (long)(&trace32_rodata));# endif    return __tffs_module_init();}module_init(tffs_module_init);/******************************************************************************* *                                                                             * *                     t f f s _ m o d u l e _ e x i t                         * *                                                                             * *  Module cleanup and routine; called when module is unloaded.                * *                                                                             * *  Parameters: none                                                           * *                                                                             * *******************************************************************************/void /* __exit */ tffs_module_exit (void){    cleanup (100);}module_exit(tffs_module_exit);/******************************************************************************* *                                                                             * *                    _ _ t f f s _ m o d u l e _ i n i t                      * *                                                                             * *  Initialize DiskOnChip driver.                                              * *                                                                             * *  Parameters: none                                                           * *                                                                             * *  Returns: zero if success, otherwise standard negative error code           * *                                                                             * *******************************************************************************/staticint /* __init */ __tffs_module_init (void){    int  STEP, iSoc, tmp;    STEP = 0;    PrintkInfo ("mDOC driver %s.%d", TrueFFSVersion, TFFS_DRV_VER);    memset (tffsInfo.sockets, 0, sizeof(tffsInfo.sockets));    for (iSoc = 0; iSoc < FL_SOCKETS; iSoc++)    {        sema_init (&tffsInfo.sockets[iSoc].sleep_sem, 0);        init_waitqueue_head (&tffsInfo.sockets[iSoc].waitQueueHead);    }    STEP++;  /* 1 */    /* if requested, install handler for DiskOnChip interrupts */    if (tffs_irq >= 0)    {        if( request_irq(tffs_irq, interrupt_handler, 0 /* SA_INTERRUPT */,                                        tffs_str, &tffsInfo.sockets[0]) == 0 )        {            tffs_irq_disable (TRUE);            PrintkInfo ("use IRQ %d", tffs_irq);        }        else /* can't install interrupt handler, won't use IRQ */        {             PrintkWarning ("failed to get IRQ %d", tffs_irq);            tffs_irq = -1;        }    }    else { PrintkInfo ("will not use IRQ"); }    STEP++;  /* 2 */    /* Find all DiskOnChip sockets, find out how many disks are on     * each socket, and abs.mount each disk.     */    if( TffsInit() <= 0 )    {        PrintkError ("No DiskOnChips found");        return -ENODEV;    }    STEP++;  /* 3 */    if (tffs_irq >= 0)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -