📄 flsystem.c
字号:
/****************************************************************************** * * * 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$ *//* * includes */#include "tffsdrv.h"#include "flbase.h"#include "doch_sys.h"#include "hib.h"#ifdef TFFS_MESSAGES_ENABLEDint fl_debug = FL_DEBUG_DEF;module_param(fl_debug, int, (S_IRUGO | S_IWUSR));MODULE_PARM_DESC(fl_debug,"Print TrueFFS debug messages [0-7].");#endif/* For portability reasons, Linux drivers should use macros readXXX/writeXXX * when reading/writing hardware registers and transferring data from * devices. Command line parameter "tffs_memcpy=1" allows DiskOnChip driver * to use memcpy() library routine instead, which often greatly improves * driver's 'read' performance. * * insmod tffs.o tffs_memcpy=1 */int tffs_memcpy = 0;module_param(tffs_memcpy, int, S_IRUGO);MODULE_PARM_DESC(tffs_memcpy, "Use memcpy() for DiskOnChip data transfers.");/* Command line parameter "tffs_addr=<physical_address>" allows user to tell * DiskOnChip driver where to look for DiskOnChip. For example, to instruct * driver to probe for DiskOnChip at physical address 0x14000000: * * insmod tffs.o tffs_addr=0x14000000 */ulong tffs_addr[FL_SOCKETS] = { TFFS_PHYS_ADDR };static int __fl_sockets = FL_SOCKETS; /* just for module_param_array() below */#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,9)) module_param_array(tffs_addr, ulong, __fl_sockets, S_IRUGO);#else module_param_array(tffs_addr, ulong, &__fl_sockets, S_IRUGO);#endifMODULE_PARM_DESC(tffs_addr,"Physical address of DiskOnChip.");/* Command line parameter "tffs_skip_sleeps=<num>" instructs DiskOnChip driver * how often it should yield CPU during DiskOnChip 'write' operations. The * higher the <num>, the less frequently driver yield CPU, thus increasing * it's 'write' performance, but also increasing it's load on CPU. * * insmod tffs.o tffs_skip_sleep=3 */int tffs_skip_sleeps = 5;module_param(tffs_skip_sleeps, int, (S_IRUGO | S_IWUSR));MODULE_PARM_DESC(tffs_skip_sleeps,"How often to yield CPU during write operations.");unsigned int profiling[10] = {0};/* * static routines */static void TffsMapMem (SocketInfo *psoc, unsigned long phys_addr, unsigned long length);static void TffsUnmapMem (SocketInfo *psoc);static void irq_wait_timed_out (unsigned long arg);/* * static vars *//* semaphore used by TrueFFS: one per socket, plus one for dochVol.mutex */static struct semaphore sems [FL_SOCKETS + 1];/* next TrueFFS semaphore to allocate (0..FL_SOCKETS-1) */static int total_sems = 0;/*-----------------------------------------------------------------------* * * * T f f s M a p M e m * * * * Allocate physical memory region, and map it into kernel's address * * space. * * * * Parameters: * * psoc socket pointer * * phys_addr starting address of physical memory region * * length length (in bytes) of this physical memory region * * * *-----------------------------------------------------------------------*/staticvoid TffsMapMem ( SocketInfo * psoc, unsigned long phys_addr, unsigned long length ){ struct resource * rs; /* no memory region has been obtained yet */ psoc->fMemRequested = 0; psoc->dwPhysAddr = 0; psoc->dwMappedLen = 0; psoc->dwVirtAddr = 0; /* request physical memory region that DiskOnChip resides in */ if ((rs = request_mem_region(phys_addr, length, "tffs")) != NULL) { /* map this physical memory region to kernel's virtual addr. space */ if ((psoc->dwVirtAddr = (ulong)ioremap_nocache(phys_addr, length)) != 0) { psoc->fMemRequested = 1; psoc->dwPhysAddr = phys_addr; psoc->dwMappedLen = length; } else { PrintkDebug("ioremap_nocache(0x%lx,0x%lx) failed", phys_addr, length); release_mem_region (phys_addr, length); } } else { PrintkDebug("request_mem_region(0x%lx,0x%lx) failed", phys_addr, length); }}/*-----------------------------------------------------------------------* * * * T f f s U n m a p M e m * * * * Unmap and free memory region previously allocated by TffsMapMem(). * * * * Parameters: * * psoc socket pointer * * * *-----------------------------------------------------------------------*/staticvoid TffsUnmapMem ( SocketInfo * psoc ){ if (psoc->dwVirtAddr != 0) iounmap ((void *)psoc->dwVirtAddr); if (psoc->fMemRequested == 1) release_mem_region (psoc->dwPhysAddr, psoc->dwMappedLen); psoc->fMemRequested = 0; psoc->dwPhysAddr = 0; psoc->dwMappedLen = 0; psoc->dwVirtAddr = 0;}void * TffsMalloc (unsigned long size){ return vmalloc (size + 4);}void TffsFree (void * vptr){ vfree (vptr);}int LnxTffsPrint(const char *fmt, ...){ va_list args; char buf[1024]; /* hopefully enough, kernel/printk.c thinks so */ int i; va_start(args, fmt); i = vsprintf(buf, fmt, args); va_end(args); buf[i] = '\0'; while(i>0) { if(buf[i-1]==0xd || buf[i-1]==0xa) { buf[--i]=0; } else break; } printk(KERN_ERR TFFS_DEVICE_NAME": %s\n",buf); return i;}/*-----------------------------------------------------------------------* * * * t f f s _ r e a d w * * * * This routine transfers data from RAM to DiskOnChip device in cases * * when DMA is not used. * * * * Parameters: * * io_vaddr virtual address of DiskOnChip's data port * * vbuf buffer to transfer data from * * words number of 16-bit short words to transfer * * * *-----------------------------------------------------------------------*/void tffs_readw ( unsigned long io_vaddr, short * vbuf, int words ){ if (tffs_memcpy == 1) /* ugly hack: use memcpy() to transfer data */ { register char * p = (char *) vbuf; register int n; /* DiskOnChip's data port is aliased across 1024-bytes region */ for (words <<= 1; words > 0; words -= n, p += n) { n = ((words <= 1024) ? words : 1024); memcpy (p, (void *)io_vaddr, n); } } else /* standard Linux case: use readw/writew macros for portability */ { while (words--) *vbuf++ = readw (io_vaddr); }}/*-----------------------------------------------------------------------* * * * t f f s _ w r i t e w * * * * This routine transfers data from DiskOnChip device to RAM in cases * * when DMA is not used. * * * * Parameters: * * io_vaddr virtual address of DiskOnChip's data port * * vbuf buffer to transfer data to * * words number of 16-bit short words to transfer * * * *-----------------------------------------------------------------------*/void tffs_writew ( unsigned long io_vaddr, short * vbuf, int words ){ if (tffs_memcpy == 1) /* ugly hack: use memcpy() to transfer data */ { register char * p = (char *) vbuf; register int n; /* DiskOnChip's data port is aliased across 1024-bytes region */ for (words <<= 1; words > 0; words -= n, p += n) { n = ((words <= 1024) ? words : 1024); memcpy ((void *)io_vaddr, p, n); } } else /* standard Linux case: use readw/writew macros for portability */ { while (words--) { writew (*vbuf, io_vaddr); vbuf++; } }}/*-----------------------------------------------------------------------* * * * d o c h b l k _ r e a d * * * * This routine transfers data from DiskOnChip H3 device to RAM. * * * * Parameters: * * vbuf buffer to transfer data to * * sectors number of 512-byte sectors to transfer * * * *-----------------------------------------------------------------------*/int dochblk_read (void * vbuf, unsigned int sectors){ flReadEvenNumberOfBytes ((DOCHFlash), DOCH_DATA_PORT_AREA, vbuf, ((sectors) << 9)); return 0;}/*-----------------------------------------------------------------------* * * * d o c h b l k _ w r i t e * * * * This routine transfers data from RAM to DiskOnChip H3 device. * * * * Parameters: * * vbuf buffer to transfer data from * * sectors number of 512-byte sectors to transfer * * * *-----------------------------------------------------------------------*/int dochblk_write (void * vbuf, unsigned int sectors){ flWriteEvenNumberOfBytes ((DOCHFlash), DOCH_DATA_PORT_AREA, vbuf, ((sectors) << 9)); return 0;}void flSysfunInit ( void ){ register int iSoc; unsigned long win_size; /* size of DiskOnChip window in bytes */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -