ARM的嵌入式Linux移植体验之设备驱动
case WRITE: // Do the write end_req: static volatile int leaving = 0; int mtdblock_thread(void *dummy) #define RQFUNC_ARG request_queue_t *q static void mtdblock_request(RQFUNC_ARG) static int mtdblock_ioctl(struct inode * inode, struct file * file, case BLKFLSBUF: static struct block_device_operations mtd_fops = static void mtd_notify_add(struct mtd_info* mtd) static void mtd_notify_remove(struct mtd_info* mtd) devfs_unregister(devfs_rw_handle[mtd->index]); int __init init_mtdblock(void) spin_lock_init(mtdblks_lock); #ifdef CONFIG_DEVFS_FS devfs_dir_handle = devfs_mk_dir(NULL, DEVICE_NAME, NULL); /* We fill it in at open() time. */ BLK_INIT_QUEUE(BLK_DEFAULT_QUEUE(MAJOR_NR), mtdblock_request, mtdblock_lock); kernel_thread (mtdblock_thread, NULL, CLONE_FS|CLONE_FILES|CLONE_SIGHAND); static void __exit cleanup_mtdblock(void) module_init(init_mtdblock); 从上述源代码中我们发现,块设备也以与字符设备register_chrdev、unregister_ chrdev 函数类似的方法进行设备的注册与释放: int register
// Read only device
if ( !(mtdblk->mtd->flags MTD_WRITEABLE) )
break;
down(mtdblk->cache_sem);
err = do_cached_write (mtdblk, req->sector 9,req->current_nr_sectors 9, req->buffer);
up(mtdblk->cache_sem);
if (!err)
res = 1;
break;
}
spin_lock_irq(QUEUE_LOCK(QUEUE));
end_request(res);
}
}
static DECLARE_MUTEX_LOCKED(thread_sem);
static DECLARE_WAIT_QUEUE_HEAD(thr_wq);
{
…
}
{
/* Don't do anything, except wake the thread if necESSary */
wake_up(thr_wq);
}
unsigned int CMd, unsigned long arg)
{
struct mtdblk_dev *mtdblk;
mtdblk = mtdblks[minor(inode->i_rdev)];
switch (cMD) {
case BLKGETSIZE: /* Return device size */
return put_user((mtdblk->mtd->size >> 9), (unsigned long *) arg);
if(!capable(CAP_SYS_ADMIN))
return -EACCES;
fsync_dev(inode->i_rdev);
invalidate_buffers(inode->i_rdev);
down(mtdblk->cache_sem);
write_cached_data(mtdblk);
up(mtdblk->cache_sem);
if (mtdblk->mtd->sync)
mtdblk->mtd->sync(mtdblk->mtd);
return 0;
default:
return -EINVAL;
}
}
{
owner: THIS_MODULE,
open: mtdblock_open,
release: mtdblock_release,
ioctl: mtdblock_ioctl
};
{
…
}
{
if (!mtd || mtd->type == MTD_ABSENT)
return;
}
{
int i;
/* this lock is used just in kernels >= 2.5.x */
spin_lock_init(mtdblock_lock);
if (devfs_register_blkdev(MTD_BLOCK_MAJOR, DEVICE_NAME, mtd_fops))
{
printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices./n",
MTD_BLOCK_MAJOR);
return -EAGAIN;
}
register_mtd_user(notifier);
#else
if (register_blkdev(MAJOR_NR,DEVICE_NAME,mtd_fops)) {
printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices./n",
MTD_BLOCK_MAJOR);
return -EAGAIN;
}
#endif
for (i=0; i MAX_MTD_DEVICES; i++) {
mtd_sizes[i] = 0;
mtd_blksizes[i] = BLOCK_SIZE;
}
init_waitqueue_head(thr_wq);
/* Allow the block size to default to BLOCK_SIZE. */
blksize_size[MAJOR_NR] = mtd_blksizes;
blk_size[MAJOR_NR] = mtd_sizes;
return 0;
}
{
leaving = 1;
wake_up(thr_wq);
down(thread_sem);
#ifdef CONFIG_DEVFS_FS
unregister_mtd_user(notifier);
devfs_unregister(devfs_dir_handle);
devfs_unregister_blkdev(MTD_BLOCK_MAJOR, DEVICE_NAME);
#else
unregister_blkdev(MAJOR_NR,DEVICE_NAME);
#endif
blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
blksize_size[MAJOR_NR] = NULL;
blk_size[MAJOR_NR] = NULL;
}
module_exit(cleanup_mtdblock);
- Linux嵌入式系统开发平台选型探讨(11-09)
- 基于ARM体系的嵌入式系统BSP的程序设计方案(04-11)
- 在Ubuntu上建立Arm Linux 开发环境(04-23)
- 达芬奇数字媒体片上系统的架构和Linux启动过程(06-02)
- SQLite嵌入式数据库系统的研究与实现(02-20)
- 革新2410D开发板试用手记(04-21)
