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

📄 tffsarch.c

📁 H3 M-system NAND flash driver in Linux OS, M-DOC driver
💻 C
📖 第 1 页 / 共 5 页
字号:
        tffsInfo.dma_buf_size = 0;        if ((tffs_dma_mode >= 1)#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) || !defined(PXA27X_DCACHE_BUG_WORKAROUND)                                 && (tffs_dma_mode <= 3)#endif           )        {            /* allocate intermediate DMA buffer (we assume one MMU page will be enough) */            tffsInfo.dma_buf_size = PAGE_SIZE;            tffsInfo.dma_buf_vptr = #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)                consistent_alloc ((GFP_KERNEL | GFP_DMA), tffsInfo.dma_buf_size,                                         &tffsInfo.dma_buf_paddr);#else                dma_alloc_coherent (NULL, tffsInfo.dma_buf_size,                                         &tffsInfo.dma_buf_paddr, (GFP_KERNEL | GFP_DMA));#endif            if (tffsInfo.dma_buf_vptr == NULL)            {                /* failed to allocate intermediate DMA buffer, won't use DMA */                tffs_dma_mode = 0;                pxa_free_dma (tffsInfo.channel);                tffsInfo.channel      = -1;                tffsInfo.dma_buf_size = 0;                PrintkError ("can't alloc DMA buffer, won't use DMA");            }        }    }}/*-----------------------------------------------------------------------* *                                                                       * *                    t f f s _ d m a _ r e l e a s e                    * *                                                                       * * Release all previously allocated DMA resources (channel, intermediate * * DMA buffer etc.). For Intel PXA27x (Mainstone) board.                 * *                                                                       * *-----------------------------------------------------------------------*/static void tffs_dma_release(void){    /* if previously was allocated, release DMA channel */    if (tffsInfo.channel >= 0)    {        pxa_free_dma (tffsInfo.channel);        tffsInfo.channel = -1;    }    /* if previously was allocated, release intermediate DMA buffer */    if (tffsInfo.dma_buf_vptr != NULL)    {#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)        consistent_free (tffsInfo.dma_buf_vptr, PAGE_SIZE, tffsInfo.dma_buf_paddr);#else        dma_free_coherent (NULL, PAGE_SIZE, tffsInfo.dma_buf_vptr, tffsInfo.dma_buf_paddr);#endif        tffsInfo.dma_buf_vptr = NULL;    }}/*-----------------------------------------------------------------------* *                                                                       * *                    _ _ d m a s w _ b r e a d                          * *                                                                       * * Transfer data from DiskOnChip's I/O reguster to RAM buffer.           * * Example implementation For Intel PXA27x (Mainstone) board.            * *                                                                       * * Parameters:                                                           * *      off            offset of DiskOnChip's I/O register from the base * *                     of DiskOnChip window                              * *      vbuf           virtual address of RAM buffer                     * *      bytes          bytes to transfer                                 * *                                                                       * *-----------------------------------------------------------------------*/staticvoid __dmasw_bread ( int            off,                     void         * vbuf,                      unsigned int   bytes ){    int           chan = tffsInfo.channel;    u_int         tmp;    register int  waiting;    register int  direct_dma;    profiling[2]++;    direct_dma = ((tffs_dma_mode & 4) ? TRUE : FALSE);    /* Due to a bug in kernel routine blk_dma_inv_range_harvard()     * (arch/arm/mm/blockops.c), we allow direct DMA to destination     * buffer 'vbuf' only when it's aligned at CPU's cache line boundary.     */#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) && defined(PXA27X_DCACHE_BUG_WORKAROUND)    if ((u32)vbuf & 31)        direct_dma = FALSE;#endif    /* Set source physical address for DMA transfer (this would be DiskOnChip's     * I/O register which is located at offset 'off' from the DiskOnChip's     * base address as specified by tffs_addr[0]).     */    DSADR(chan) = tffs_addr[0] + off;    /* Set target physical address for DMA transfer.     * This would be physical address of intermediate DMA buffer (for     * DMA modes 1/2/3), or physical address of the destination buffer     * (for DMA modes 5/6/7).     */    if (direct_dma == TRUE) /* do DMA transfer directly into 'vbuf' */    {         if (virt_addr_valid((unsigned long)vbuf)) /* 'vbuf' is in low memory */        {            DTADR(chan) = __pa (vbuf);        }        else                                      /* 'vbuf' is in high memory */        {            char * k_vbuf = (char *) page_address(vmalloc_to_page(vbuf)) +                                          ((unsigned long)vbuf & (PAGE_SIZE - 1));            if (k_vbuf == NULL)            {                 PrintkError ("error, DMA requested on high memory page");                return;            }            DTADR(chan) = __pa (k_vbuf);            /* andrayk Nov 22 2006: possible bug. Routine consistent_alloc()             * (arch/arm/mm/consistent.c) applies __pa() macro to it's 'vbuf'              * argument (see below). This might cause CPU exception.             */        }        /* Write (if dirty) and purge contents of 'vbuf' from CPU cache(s) */        /* Possible options:         *   consistent_sync(vbuf, bytes, DMA_FROM_DEVICE);            ARM/SH         *   dma_cache_inv((unsigned long)vbuf, (unsigned long)bytes); MIPS/PPC/x86         */#ifdef PXA27X_DCACHE_BUG_WORKAROUND        /* Routine blk_dma_inv_range_harvard() (arch/arm/mm/blockops.c) appears         * to be buggy: it seems to constantly shoot past the end of the address         * range [vbuf..vbuf+bytes] by 32 bytes. It also appears to write some         * bogus data into this RAM address range while invalidating it in D-cache.          */        consistent_sync (vbuf, bytes - 1, DMA_FROM_DEVICE);#else        consistent_sync (vbuf, bytes, DMA_FROM_DEVICE);#endif    }    else /* transfer into intermediate DMA buffer */    {        DTADR(chan) = tffsInfo.dma_buf_paddr;    }    /* specify parameters of DMA transfer */    tmp = DCMD_INCTRGADDR |     /* increment target address */          DCMD_WIDTH2     |     /* 16-bit data path */       /* DCMD_ENDIRQEN   | */  /* don't generate interrupt at the end of transfer */          bytes;    if ((bytes & 31) == 0)        tmp |= DCMD_BURST32;    /* 32-bytes burst */    DCMD(chan) = tmp;    /* clear all status bits, and start DMA transfer */    DCSR(chan) = (DCSR_RUN | DCSR_NODESC | DCSR_ENDINTR | DCSR_STOPSTATE | DCSR_BUSERR);    /* poll DMA channel's status register for end of DMA transfer */    for (waiting = 100000; waiting > 0; waiting--) /* hope this is long enough ... */    {        /* read Channel Status Register to find out status of DMA transfer */        tmp = DCSR (chan);        if (tmp & (DCSR_STOPSTATE | DCSR_BUSERR))        {            if ((tmp & DCSR_BUSERR) == 0)            {                /* DMA transfer completed, move data from the intermediate DMA                 * buffer to the destination buffer (in case it was used).                 */                if (direct_dma == FALSE)                    memcpy (vbuf, tffsInfo.dma_buf_vptr, bytes);            }            else            {                 PrintkError ("Bus error, DMA transfer failed");                /* andrayk Mar 24 2006: DMA transfer failed, find way to let MTD know this */            }            return;        }    }    PrintkError ("DMA transfer timed out");}/*-----------------------------------------------------------------------* *                                                                       * *                    _ _ d m a s w _ b w r i t e                        * *                                                                       * * Transfer data from RAM buffer to DiskOnChip's I/O reguster.           * * Example implementation for Intel PXA27x (Mainstone) board.            * *                                                                       * * Parameters:                                                           * *      off            offset of DiskOnChip's I/O register from the base * *                     of DiskOnChip window                              * *      vbuf           virtual address of RAM buffer                     * *      bytes          bytes to transfer                                 * *                                                                       * *-----------------------------------------------------------------------*/staticvoid __dmasw_bwrite ( int            off,                      void         * vbuf,                       unsigned int   bytes ){    int           chan = tffsInfo.channel;    u_int         tmp;    register int  waiting;    profiling[3]++;    /* Set target physical address for DMA transfer (this would be DiskOnChip's     * I/O register which is located at offset 'off' from the DiskOnChip's     * base address as specified by tffs_addr[0]).     */    DTADR(chan) = tffs_addr[0] + off;    /* set source physical address for DMA transfer */    if (tffs_dma_mode & 4) /* do DMA transfer directly from 'vbuf' */    {        /* Write (if dirty) contents of 'vbuf' from CPU D-cache to RAM.         * Possible options:         *   consistent_sync(vbuf, bytes, DMA_TO_DEVICE);                ARM/SH         *   dma_cache_wback((unsigned long)vbuf, (unsigned long)bytes); MIPS/PPC/x86         */        consistent_sync (vbuf, bytes, DMA_TO_DEVICE);        if (virt_addr_valid((unsigned long)vbuf)) /* 'vbuf' is in low memory */        {            DSADR(chan) = __pa (vbuf);        }        else                                      /* 'vbuf' is in high memory */        {            char * k_vbuf = (char *) page_address(vmalloc_to_page(vbuf)) +                                          ((unsigned long)vbuf & (PAGE_SIZE - 1));            if (k_vbuf == NULL)            {                 PrintkError ("error, DMA requested on high memory page");                return;            }            DSADR(chan) = __pa (k_vbuf);        }    }    else                   /* use intermediate DMA buffer */    {        /* move data from RAM buffer to the intermediate DMA buffer */        memcpy (tffsInfo.dma_buf_vptr, vbuf, bytes);        DSADR(chan) = tffsInfo.dma_buf_paddr;    }    /* specify parameters of DMA transfer */    tmp = DCMD_INCSRCADDR |     /* increment source address */          DCMD_WIDTH2     |     /* 16-bit data path */       /* DCMD_ENDIRQEN   | */  /* don't generate interrupt at the end of transfer */          bytes;    if ((bytes & 31) == 0)        tmp |= DCMD_BURST32;    /* 32-bytes burst */    DCMD(chan) = tmp;    /* clear all status bits, and start DMA transfer */    DCSR(chan) = (DCSR_RUN | DCSR_NODESC | DCSR_ENDINTR | DCSR_STOPSTATE | DCSR_BUSERR);    /* poll DMA channel's status register for end of DMA transfer */    for (waiting = 100000; waiting > 0; waiting--) /* hope this is long enough ... */    {        /* read Channel Status Register to find out status of DMA transfer */        tmp = DCSR (chan);        if (tmp & (DCSR_STOPSTATE | DCSR_BUSERR))        {            if (tmp & DCSR_BUSERR)            {                 PrintkError ("Bus error, DMA transfer failed");                /* andrayk Mar 24 2006: DMA transfer failed, find way to let MTD know this */            }            else            {                /* DMA transfer successful */             }            return;        }    }    PrintkError ("DMA transfer timed out");}/*-----------------------------------------------------------------------* *                                                                       *

⌨️ 快捷键说明

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