ARM的嵌入式Linux移植体验之设备驱动
static int erase_write (struct mtd_info *mtd, unsigned long pos, /* init_waitqueue_head(wait_q); set_current_state(TASK_INTERRUPTIBLE); ret = MTD_ERASE(mtd, erase); schedule(); /* Wait for erase to finish. */ /* ret = MTD_WRITE (mtd, pos, len, retlen, buf); static int write_cached_data (struct mtdblk_dev *mtdblk) if (mtdblk->cache_state != STATE_DIRTY) DEBUG(MTD_DEBUG_LEVEL2, "mtdblock: writing cached data for /"%s/" " ret = erase_write (mtd, mtdblk->cache_offset, mtdblk->cache_state = STATE_EMPTY; static int do_cached_write (struct mtdblk_dev *mtdblk, unsigned long pos, static int do_cached_read (struct mtdblk_dev *mtdblk, unsigned long pos, static int mtdblock_open(struct inode *inode, struct file *file) static release_t mtdblock_release(struct inode *inode, struct file *file) if (inode == NULL) dev = minor(inode->i_rdev); down(mtdblk->cache_sem); spin_lock(mtdblks_lock); DEBUG(MTD_DEBUG_LEVEL1, "ok/n"); /* for (;;) { if (minor(req->rq_dev) >= MAX_MTD_DEVICES) if (!IS_REQ_CMD(req)) if ((req->sector + req->current_nr_sectors) > (mtdblk->mtd->size >> 9)) // Handle the request case READ:
int len, const char *buf)
{
struct erase_info erase;
DECLARE_WAITQUEUE(wait, current);
wait_queue_head_t wait_q;
size_t retlen;
int ret;
* First, let's erase the flash block.
*/
erase.mtd = mtd;
erase.callback = erase_callback;
erase.addr = pos;
erase.len = len;
erase.priv = (u_long)wait_q;
add_wait_queue(wait_q, wait);
if (ret) {
set_current_state(TASK_RUNNING);
remove_wait_queue(wait_q, wait);
printk (KERN_WARNING "mtdblock: erase of region [0x%lx, 0x%x] " "on /"%s/" failed/n",
pos, len, mtd->name);
return ret;
}
remove_wait_queue(wait_q, wait);
* Next, writhe data to flash.
*/
if (ret)
return ret;
if (retlen != len)
return -EIO;
return 0;
}
{
struct mtd_info *mtd = mtdblk->mtd;
int ret;
return 0;
"at 0x%lx, size 0x%x/n", mtd->name,
mtdblk->cache_offset, mtdblk->cache_size);
mtdblk->cache_size, mtdblk->cache_data);
if (ret)
return ret;
return 0;
}
int len, const char *buf)
{
…
}
int len, char *buf)
{
…
}
{
…
}
{
int dev;
struct mtdblk_dev *mtdblk;
DEBUG(MTD_DEBUG_LEVEL1, "mtdblock_release/n");
release_return(-ENODEV);
mtdblk = mtdblks[dev];
write_cached_data(mtdblk);
up(mtdblk->cache_sem);
if (!--mtdblk->count) {
/* It was the last usage. Free the device */
mtdblks[dev] = NULL;
spin_unlock(mtdblks_lock);
if (mtdblk->mtd->sync)
mtdblk->mtd->sync(mtdblk->mtd);
put_mtd_device(mtdblk->mtd);
vfree(mtdblk->cache_data);
kfree(mtdblk);
} else {
spin_unlock(mtdblks_lock);
}
BLK_DEC_USE_COUNT;
release_return(0);
}
* This is a special request_fn because it is executed in a process context
* to be able to sleep independently of the caller. The
* io_request_lock (for 2.5) or queue_lock (for >=2.5) is held upon entry
* and exit. The head of our request queue is considered active so there is
* no need to dequeue requests before we are done.
*/
static void handle_mtdblock_request(void)
{
struct request *req;
struct mtdblk_dev *mtdblk;
unsigned int res;
INIT_REQUEST;
req = CURRENT;
spin_unlock_irq(QUEUE_LOCK(QUEUE));
mtdblk = mtdblks[minor(req->rq_dev)];
res = 0;
panic("%s : minor out of bound", __FUNCTION__);
goto end_req;
goto end_req;
switch (rq_data_dir(req))
{
int err;
down(mtdblk->cache_sem);
err = do_cached_read (mtdblk, req->sector 9,
req->current_nr_sectors 9,
req->buffer);
up(mtdblk->cache_sem);
if (!err)
res = 1;
break;
- Linux嵌入式系统开发平台选型探讨(11-09)
- 基于ARM体系的嵌入式系统BSP的程序设计方案(04-11)
- 在Ubuntu上建立Arm Linux 开发环境(04-23)
- 达芬奇数字媒体片上系统的架构和Linux启动过程(06-02)
- SQLite嵌入式数据库系统的研究与实现(02-20)
- 革新2410D开发板试用手记(04-21)
