微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > ARM的嵌入式Linux移植体验之设备驱动

ARM的嵌入式Linux移植体验之设备驱动

时间:11-13 来源:互联网 点击:

case WRITE:
    // Read only device
    if ( !(mtdblk->mtd->flags MTD_WRITEABLE) )
     break;

    // Do the write
    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;
  }

 end_req:
 spin_lock_irq(QUEUE_LOCK(QUEUE));
 end_request(res);
}
}

static volatile int leaving = 0;
static DECLARE_MUTEX_LOCKED(thread_sem);
static DECLARE_WAIT_QUEUE_HEAD(thr_wq);

int mtdblock_thread(void *dummy)
{
 …
}

#define RQFUNC_ARG request_queue_t *q

static void mtdblock_request(RQFUNC_ARG)
{
 /* Don't do anything, except wake the thread if necESSary */
 wake_up(thr_wq);
}

static int mtdblock_ioctl(struct inode * inode, struct file * file,
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);

  case BLKFLSBUF:
   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;
 }
}

static struct block_device_operations mtd_fops =
{
 owner: THIS_MODULE,
 open: mtdblock_open,
 release: mtdblock_release,
 ioctl: mtdblock_ioctl
};

static void mtd_notify_add(struct mtd_info* mtd)
{
 …
}

static void mtd_notify_remove(struct mtd_info* mtd)
{
 if (!mtd || mtd->type == MTD_ABSENT)
  return;

 devfs_unregister(devfs_rw_handle[mtd->index]);
}

int __init init_mtdblock(void)
{
 int i;

 spin_lock_init(mtdblks_lock);
 /* this lock is used just in kernels >= 2.5.x */
 spin_lock_init(mtdblock_lock);

 #ifdef CONFIG_DEVFS_FS
 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;
 }

 devfs_dir_handle = devfs_mk_dir(NULL, DEVICE_NAME, NULL);
 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

/* We fill it in at open() time. */
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;

BLK_INIT_QUEUE(BLK_DEFAULT_QUEUE(MAJOR_NR), mtdblock_request, mtdblock_lock);

kernel_thread (mtdblock_thread, NULL, CLONE_FS|CLONE_FILES|CLONE_SIGHAND);
return 0;
}

static void __exit cleanup_mtdblock(void)
{
 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_init(init_mtdblock);
module_exit(cleanup_mtdblock);

  从上述源代码中我们发现,块设备也以与字符设备register_chrdev、unregister_ chrdev 函数类似的方法进行设备的注册与释放:

int register

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top