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

📄 tffsdrv26.c

📁 H3 M-system NAND flash driver in Linux OS, M-DOC driver
💻 C
📖 第 1 页 / 共 5 页
字号:
 *******************************************************************************/staticint socket_io_thread (void * arg) {    SocketInfo * psoc = (SocketInfo *) arg;    char         name[32];    current->flags |= (PF_MEMALLOC | PF_NOFREEZE);    sprintf (name, "%s%c", tffs_str, '0' + (char)psoc->bHandle);    daemonize (name);    /* we don't want to receive any signals */    spin_lock_irq (&current->sighand->siglock);    sigfillset (&current->blocked);    recalc_sigpending ();    spin_unlock_irq (&current->sighand->siglock);    /* adjist thread's priority if necessary */    if (tffs_prio != 0)        set_user_nice (current, tffs_prio);    /* initially socket's request list is empty */    spin_lock_init (&psoc->request_list_lock);    INIT_LIST_HEAD (&psoc->requestsList);    /* If somebody is waiting for socket's I/O thread to start up and      * get ready for processing I/O requests, let them know that we did.     */    if (psoc->io_thread_state == 2)        up (&psoc->threadSemaphore);    /* socket's I/O thread is ready to receive I/O requests */    psoc->io_thread_state = 1;    while (psoc->io_thread_state == 1)    {        /* wait 5 clock ticks for I/O requests to arrive */        wait_event_interruptible_timeout (psoc->waitQueueHead, requests_to_do(psoc), 5);        /* handle all I/O requests (if any) in socket's request ist */        do_requests_list (psoc);    }    /* If somebody is waiting for socket's I/O thread to terminate,      * let them know that it did.     */    if (psoc->io_thread_state == 2)        up (&psoc->threadSemaphore);    /* socket's I/O thread terminated */    psoc->io_thread_state = 0;    return 0;}/******************************************************************************* *                                                                             * *                      d o _ r e q u e s t s _ l i s t                        * *                                                                             * *  This routine handles all requests in socket's request list.                * *                                                                             * *  Parameters:                                                                * *      psoc        socket pointer                                             * *                                                                             * *******************************************************************************/staticvoid  do_requests_list ( SocketInfo * psoc ){    struct request * r;    struct gendisk * gd;    DeviceInfo     * pdisk;    unsigned long    flags;    /* lock socket's request list */    spin_lock_irqsave (&psoc->request_list_lock, flags);    /* if socket's request list isn't empty, process all requests there */    while( !(list_empty(&psoc->requestsList)) )    {        /* take next request off socket's request list */        r = list_entry_rq (psoc->requestsList.next);        list_del_init (&r->queuelist);        /* unlock socket's request list */        spin_unlock_irqrestore (&psoc->request_list_lock, flags);        /* Mark all non-filesystem request, and those filesystem requests         * that don't pass sanity check, as not-uptodate (i.e. failed).         */        if( !blk_fs_request(r)                                ||            ((gd = r->rq_disk) == NULL)                       ||            ((pdisk = gd->private_data) == NULL)              ||            (pdisk->gd != gd)                                 ||            (r->sector + r->nr_sectors > pdisk->dwSize)          )        {            end_that_request_first (r, /* failed */ 0, r->hard_cur_sectors);        }        else  /* legitimate filesystem request; handle it */        {            if (rq_data_dir(r) == WRITE)            {                write_requests++;                do_write_request (r);            }            else  /* READ request */            {                do_read_request (r);            }        }        /* mark this request as done */        spin_lock (&pdisk->rq_lock);        end_that_request_last (r);        spin_unlock (&pdisk->rq_lock);        /* lock socket's request list */        spin_lock_irqsave (&psoc->request_list_lock, flags);    }    /* unlock socket's request list */    spin_unlock_irqrestore (&psoc->request_list_lock, flags);}/******************************************************************************* *                                                                             * *                       d o _ w r i t e _ r e q u e s t                       * *                                                                             * *  This routine handles single WRITE request.                                 * *                                                                             * *  Parameters:                                                                * *      psoc        socket pointer                                             * *                                                                             * *  Returns:                                                                   * *      zero if I/O error was encountered, otherwise '1'.                      * *                                                                             * *******************************************************************************/staticint  do_write_request ( struct request  * r ){    DeviceInfo     * pdisk = (DeviceInfo *) r->rq_disk->private_data;    struct bio     * bio;    struct gather_t  gather;    unsigned long    total_sectors = r->nr_sectors;    int              success = 1;    /* in case we are going to use gather buffer, mark it as empty */    if ((tffs_sg_bufsize > 0) && (tffs_sg_write != FALSE))    {        gather.buf          =         gather.free         = pdisk->pSocket->pCache;        gather.size         =        gather.free_bytes   = tffs_sg_bufsize;        /* first disk sector # for this request */        gather.start_sector = r->sector;    }    /* do all bio's of this request */    rq_for_each_bio (bio, r)    {        if( write_bio(bio, &gather, pdisk) < 0)            success = 0;     /* I/O error */    }    /* flush remaining data (if any) from gather buffer to disk */        if ((tffs_sg_bufsize > 0) && (tffs_sg_write != FALSE)                              && (gather.free > gather.buf))    {        int ns = ((gather.free - gather.buf) >> 9); /* remaining sectors in buf */        if( TffsWrite (pdisk, gather.buf, gather.start_sector, ns) == 0 )            success = 0;    /* I/O error */    }    /* Note that if we encountered I/O error in the middle of      * request processing, we mark the entire request as failed.     * Not very smart but hopefully will do for now ...     */    end_that_request_first (r, success, total_sectors);    return success;}/******************************************************************************* *                                                                             * *                       d o _ r e a d  _ r e q u e s t                        * *                                                                             * *  This routine handles single READ request.                                  * *                                                                             * *  Parameters:                                                                * *      psoc        socket pointer                                             * *                                                                             * *  Returns:                                                                   * *      zero if I/O error was encountered, otherwise '1'.                      * *                                                                             * *******************************************************************************/staticint  do_read_request ( struct request  * r ){    DeviceInfo      * pdisk = (DeviceInfo *) r->rq_disk->private_data;    struct bio      * bio;    struct scatter_t  scatter;    unsigned long     total_sectors = r->nr_sectors;    int               success = 1;    /* read in data from disk into scatter buffer */    if ((tffs_sg_bufsize > 0) && (tffs_sg_read != FALSE))    {        int  ns = _MIN(r->nr_sectors, (tffs_sg_bufsize >> 9));        scatter.buf  = pdisk->pSocket->pCache;        scatter.size = tffs_sg_bufsize;        if( TffsRead (pdisk, scatter.buf, r->sector, ns) == 0 )        {            success = 0;   /* I/O error */            goto out;        }        scatter.pcurrent        = scatter.buf;        scatter.remaining_bytes = (ns << 9);        scatter.sectors         = r->nr_sectors - ns;        scatter.start_sector    = r->sector + ns;    }    /* do all bio's of this request */    rq_for_each_bio (bio, r)    {        if( read_bio(bio, &scatter, pdisk) < 0)            success = 0;    /* I/O error */    }out:    /* Note that if we encountered I/O error in the middle of      * request processing, we mark the entire request as failed.     * Not very smart but hopefully will do for now ...     */    end_that_request_first (r, success, total_sectors);    return success;}/******************************************************************************* *                                                                             * *                             w r i t e _ b i o                               * *                                                                             * *  This routine handles single 'struct bio' WRITE operation using gather      * *  buffer.                                                                    * *                                                                             * *  Parameters:                                                                * *      bio          pointer to 'struct bio' to WRITE                          * *      gather       pointer to gather buffer                                  * *      pdisk        disk pointer                                              * *                                                                             * *  Returns:                                                                   * *      zero if success otherwise -EIO negative error code                     * *                                                                             * *******************************************************************************/staticint  write_bio ( struct bio      * bio,                  struct gather_t * gather,                  DeviceInfo      * pdisk ){    struct bio_vec * bv;    int              i, rc = 0;    if ((tffs_sg_bufsize == 0) || (tffs_sg_write == FALSE))    {        /* we don't use gather buffer; do one I/O segment at a time */        rc = rw_bio_no_sg (bio, pdisk, WRITE);    }    else /* use gather buffer */    {        bio_for_each_segment (bv, bio, i)        {            unsigned int   n  = bv->bv_len; /* bytes in this I/O segment */            char         * p, * p2;            /* If segment's data resides in high memory, bounce it              * down into the temporary low memory buffer.             */            p2 = p = __bio_kmap_atomic (bio, i, KM_USER0);            for (; n >= gather->free_bytes; )            {                /* This I/O segment won't fit into the remaining space in                 * gather buffer. Copy the part that does fit into gather                 * buffer (making it full), then flush entire gather buffer                 * to disk.                 */                if (gather->free_bytes > 0)                {                    memcpy (gather->free, p, gather->free_bytes);                    p += gather->free_bytes;                    n -= gather->free_bytes;                }                /* flush entire gather buffer to disk */                if( TffsWrite (pdisk, gather->buf, gather->start_sector,                                                     (gather->size >> 9)) == 0 )                    rc = -EIO;    /* I/O error */                /* gather buffer is empty */                gather->free          = gather->buf;                gather->free_bytes    = gather->size;                gather->start_sector += (gather->size >> 9);            }            /* remaining part of this segment fits into gather buffer */            if (n > 0)            {                memcpy (gather->free, p, n);                gather->free       += n;                gather->free_bytes -= n;            }            __bio_kunmap_atomic (p2, KM_USER0);        }    }    return rc;}

⌨️ 快捷键说明

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