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

📄 tffsdrv26.c

📁 H3 M-system NAND flash driver in Linux OS, M-DOC driver
💻 C
📖 第 1 页 / 共 5 页
字号:
/******************************************************************************* *                                                                             * *                             r e a d  _ b i o                                * *                                                                             * *  This routine handles single 'struct bio' READ operation using scatter      * *  buffer.                                                                    * *                                                                             * *  Parameters:                                                                * *      bio          pointer to 'struct bio' to WRITE                          * *      scatter      pointer to scatter buffer                                 * *      pdisk        disk pointer                                              * *                                                                             * *  Returns:                                                                   * *      zero if success otherwise -EIO negative error code                     * *                                                                             * *******************************************************************************/staticint  read_bio ( struct bio       * bio,                 struct scatter_t * scatter,                 DeviceInfo       * pdisk ){    struct bio_vec * bv;    int              i, rc = 0;    if ((tffs_sg_bufsize == 0) || (tffs_sg_read == FALSE))    {        /* we don't use scatter buffer; do one I/O segment at a time */        rc = rw_bio_no_sg (bio, pdisk, READ);    }    else  /* use gather buffer */    {        bio_for_each_segment (bv, bio, i)        {            unsigned int   n  = bv->bv_len; /* bytes in this I/O segment */            unsigned int   ns;            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 >= scatter->remaining_bytes; )            {                /* This I/O segment is larger then number of remaining bytes                 * in scatter buffer. Copy all these remaining bytes (making                 * scatter buffer empty), then re-fill scatter buffer from disk.                 */                if (scatter->remaining_bytes > 0)                {                    memcpy (p, scatter->pcurrent, scatter->remaining_bytes);                    p += scatter->remaining_bytes;                    n -= scatter->remaining_bytes;                }                /* scatter buffer is empty now */                scatter->remaining_bytes = 0;                scatter->pcurrent        = scatter->buf;                /* end of this request ? */                if ((ns = _MIN(scatter->sectors, (tffs_sg_bufsize >> 9))) == 0)                    break;                /* re-fill scatter buffer from disk */                if( TffsRead (pdisk, scatter->buf, scatter->start_sector, ns) == 0 )                    rc = -EIO;    /* I/O error */                scatter->remaining_bytes  = (ns << 9);                scatter->sectors         -= ns;                scatter->start_sector    += ns;            }            /* Remaining part of this segment can be entirely taken             * from the scatter buffer.             */            if (n > 0)            {                memcpy (p, scatter->pcurrent, n);                scatter->pcurrent        += n;                scatter->remaining_bytes -= n;            }            __bio_kunmap_atomic (p2, KM_USER0);        }    }    return rc;}/******************************************************************************* *                                                                             * *                       r w _ b i o _ n o _ s g                               * *                                                                             * *  This routine handles single 'struct bio' without using scatter/gather      * *  buffers. It issues TrueFFS I/O call for each segment of this 'struct bio'. * *                                                                             * *  Parameters:                                                                * *      bio          pointer to 'struct bio' to handle                         * *      pdisk        disk pointer                                              * *      rw           READ or WRITE                                             * *                                                                             * *  Returns:                                                                   * *      zero if success otherwise -EIO negative error code                     * *                                                                             * *******************************************************************************/staticint  rw_bio_no_sg ( struct bio * bio,                     DeviceInfo * pdisk,                    int          rw ){    sector_t         sector = bio->bi_sector;  /* starting disk sector for this bio */    struct bio_vec * bv;    char           * p;    int              i, rc = 0;    unsigned int     ns;    bio_for_each_segment (bv, bio, i)    {        if ((ns = (bv->bv_len >> 9)) > 0)   /* sectors in this segment */        {            /* If segment's data resides in high memory, bounce it              * down into temporary low memory buffer.             */            p = __bio_kmap_atomic (bio, i, KM_USER0);            if (rw == READ)            {                if( TffsRead (pdisk, p, sector, ns) == 0 )                    rc = -EIO;    /* I/O error */            }            else            {                if( TffsWrite (pdisk, p, sector, ns) == 0 )                    rc = -EIO;    /* I/O error */            }            __bio_kunmap_atomic (p, KM_USER0);            sector += ns;        }    }    return rc;}/******************************************************************************* *                                                                             * *                         r e q u e s t s _ t o _ d o                         * *                                                                             * *  This routine checks if there are any requests in socket's request list.    * *                                                                             * *  Parameters:                                                                * *      psoc        socket pointer                                             * *                                                                             * *  Returns:                                                                   * *      FALSE if list is empty, otherwise TRUE                                 * *                                                                             * *******************************************************************************/staticint  requests_to_do ( SocketInfo * psoc ){    unsigned long  flags;    int            rc = FALSE;   /* assume list is empty */    spin_lock_irqsave (&psoc->request_list_lock, flags);    if( !list_empty(&psoc->requestsList) )        rc = TRUE;    spin_unlock_irqrestore (&psoc->request_list_lock, flags);    return rc;}/******************************************************************************* *                                                                             * *                         t f f s _ s u s p e n d                             * *                                                                             * *  This routine is intended to be called by various Linux Power Managers to   * *  power down all DiskOnChip devices when system goes into powerdown mode.    * *                                                                             * *  Parameters:   none                                                         * *                                                                             * *  Returns: void                                                              * *                                                                             * *******************************************************************************/void tffs_suspend (void){    SocketInfo * psoc;    int          i;    for (i = 0; i < FL_SOCKETS; i++)    {        psoc = &tffsInfo.sockets[i];        if (psoc->fFound == 0)            continue;        /* Tell I/O thread to finish all outstanding I/O requests, put         * up psoc->threadSemaphore (we'll wait for it), and exit.         */        psoc->io_thread_state = 2;        /* in case socket's I/O thread is currently sleeping, wake it up */        wake_up (&psoc->waitQueueHead);        /* wait for I/O thread to exit */        down_interruptible (&psoc->threadSemaphore);        /* tell TrueFFS to power down DiskOnChip */        TffsSuspend (psoc);    }    /* disable DiskOnChip interrupts */    if (tffs_irq >= 0)    {        tffs_irq_disable (TRUE);    }}/******************************************************************************* *                                                                             * *                         t f f s _ r e s u m e                               * *                                                                             * *  This routine is intended to be called by various Linux Power Managers to   * *  power up all DiskOnChip devices when system comes up from powerdown mode.  * *                                                                             * *  Parameters:   none                                                         * *                                                                             * *  Returns: void                                                              * *                                                                             * *******************************************************************************/void tffs_resume (void){    SocketInfo * psoc;    int          i;    /* We are doing 'resume' after previous power 'suspend', not      * full scale board initialization, hence TRUE flag below.     */    tffsarch_init (TRUE);    /* enable DiskOnChip interrupts */    if (tffs_irq >= 0)    {        tffs_irq_enable (TRUE);    }    for (i = 0; i < FL_SOCKETS; i++)    {        psoc = &tffsInfo.sockets[i];        if (psoc->fFound == 0)            continue;        /* Tell TrueFFS to power up DiskOnChip. This call takes around 20         * milliseconds (DiskOnChip driver will not yield CPU during this time).         */        TffsResume (psoc);        /* restore multi-sector poleld I/O mode in DiskOnChip h3 devices */        TffsSetPIO (psoc);        /* tell I/O thread to put up psoc->threadSemaphore when it starts */        psoc->io_thread_state = 2;        /* start I/O thread */        kernel_thread (socket_io_thread, (void *)psoc, 0);        /* wait for I/O thread to get running */        down_interruptible (&psoc->threadSemaphore);    }}#ifdef CONFIG_PROC_FS/******************************************************************************* *                                                                             * *                     p r o c f s _ r e g i s t e r                           * *                                                                             * *  Create disk's entry in /proc/<module-name>.                                * *                                                                             * *  Parameters:                                                                * *                                                                             * *       pdisk          disk pointer                                           * *                                                                             * *  Returns: zero if success otherwise negative error code.                    * *                                                                             * *******************************************************************************/staticint  /* __init */ procfs_register ( DeviceInfo * pdisk ){    char name[] = "a";    name[0] += (char)(pdisk->diskNo);    if ((pdisk->pProcFile = create_proc_entry(name, 0, tffsInfo.pProcDir)) == NULL)    {         PrintkWarning("Can't create /proc/tffs/%s", name);        return -EBUSY;    }    pdisk->pProcFile->read_proc  = procfs_read;    pdisk->pProcFile->write_proc = procfs_write;    pdisk->pProcFile->data       = pdisk;    return 0;}/******************************************************************************* *                                                                             * *                     p r o c f s _ u n r e g i s t e r                       * *                                                                             * *  Delete disk's entry in /proc/<module-name>.                                * *                                                                             * *  Parameters:                                                                * *                                                                             * *       pdisk          disk pointer                                           * *                                                                             * *  Returns: always zero (success).                                            * *                                                                             * ***************

⌨️ 快捷键说明

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