raw.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:8k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * linux/drivers/char/raw.c
  3.  *
  4.  * Front-end raw character devices.  These can be bound to any block
  5.  * devices to provide genuine Unix raw character device semantics.
  6.  *
  7.  * We reserve minor number 0 for a control interface.  ioctl()s on this
  8.  * device are used to bind the other minor numbers to block devices.
  9.  */
  10. #include <linux/fs.h>
  11. #include <linux/iobuf.h>
  12. #include <linux/major.h>
  13. #include <linux/blkdev.h>
  14. #include <linux/raw.h>
  15. #include <linux/capability.h>
  16. #include <linux/smp_lock.h>
  17. #include <asm/uaccess.h>
  18. #define dprintk(x...) 
  19. typedef struct raw_device_data_s {
  20. struct block_device *binding;
  21. int inuse, sector_size, sector_bits;
  22. struct semaphore mutex;
  23. } raw_device_data_t;
  24. static raw_device_data_t raw_devices[256];
  25. static ssize_t rw_raw_dev(int rw, struct file *, char *, size_t, loff_t *);
  26. ssize_t raw_read(struct file *, char *, size_t, loff_t *);
  27. ssize_t raw_write(struct file *, const char *, size_t, loff_t *);
  28. int raw_open(struct inode *, struct file *);
  29. int raw_release(struct inode *, struct file *);
  30. int raw_ctl_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
  31. static struct file_operations raw_fops = {
  32. read: raw_read,
  33. write: raw_write,
  34. open: raw_open,
  35. release: raw_release,
  36. };
  37. static struct file_operations raw_ctl_fops = {
  38. ioctl: raw_ctl_ioctl,
  39. open: raw_open,
  40. };
  41. static int __init raw_init(void)
  42. {
  43. int i;
  44. register_chrdev(RAW_MAJOR, "raw", &raw_fops);
  45. for (i = 0; i < 256; i++)
  46. init_MUTEX(&raw_devices[i].mutex);
  47. return 0;
  48. }
  49. __initcall(raw_init);
  50. /* 
  51.  * Open/close code for raw IO.
  52.  */
  53. int raw_open(struct inode *inode, struct file *filp)
  54. {
  55. int minor;
  56. struct block_device * bdev;
  57. kdev_t rdev; /* it should eventually go away */
  58. int err;
  59. int sector_size;
  60. int sector_bits;
  61. minor = MINOR(inode->i_rdev);
  62. /* 
  63.  * Is it the control device? 
  64.  */
  65. if (minor == 0) {
  66. filp->f_op = &raw_ctl_fops;
  67. return 0;
  68. }
  69. if (!filp->f_iobuf) {
  70. err = alloc_kiovec(1, &filp->f_iobuf);
  71. if (err)
  72. return err;
  73. }
  74. down(&raw_devices[minor].mutex);
  75. /*
  76.  * No, it is a normal raw device.  All we need to do on open is
  77.  * to check that the device is bound, and force the underlying
  78.  * block device to a sector-size blocksize. 
  79.  */
  80. bdev = raw_devices[minor].binding;
  81. err = -ENODEV;
  82. if (!bdev)
  83. goto out;
  84. atomic_inc(&bdev->bd_count);
  85. rdev = to_kdev_t(bdev->bd_dev);
  86. err = blkdev_get(bdev, filp->f_mode, 0, BDEV_RAW);
  87. if (err)
  88. goto out;
  89. /*
  90.  * Don't change the blocksize if we already have users using
  91.  * this device 
  92.  */
  93. if (raw_devices[minor].inuse++)
  94. goto out;
  95. /* 
  96.  * Don't interfere with mounted devices: we cannot safely set
  97.  * the blocksize on a device which is already mounted.  
  98.  */
  99. sector_size = 512;
  100. if (is_mounted(rdev)) {
  101. if (blksize_size[MAJOR(rdev)])
  102. sector_size = blksize_size[MAJOR(rdev)][MINOR(rdev)];
  103. } else {
  104. if (hardsect_size[MAJOR(rdev)])
  105. sector_size = hardsect_size[MAJOR(rdev)][MINOR(rdev)];
  106. }
  107. set_blocksize(rdev, sector_size);
  108. raw_devices[minor].sector_size = sector_size;
  109. for (sector_bits = 0; !(sector_size & 1); )
  110. sector_size>>=1, sector_bits++;
  111. raw_devices[minor].sector_bits = sector_bits;
  112.  out:
  113. up(&raw_devices[minor].mutex);
  114. return err;
  115. }
  116. int raw_release(struct inode *inode, struct file *filp)
  117. {
  118. int minor;
  119. struct block_device *bdev;
  120. minor = MINOR(inode->i_rdev);
  121. down(&raw_devices[minor].mutex);
  122. bdev = raw_devices[minor].binding;
  123. raw_devices[minor].inuse--;
  124. up(&raw_devices[minor].mutex);
  125. blkdev_put(bdev, BDEV_RAW);
  126. return 0;
  127. }
  128. /*
  129.  * Deal with ioctls against the raw-device control interface, to bind
  130.  * and unbind other raw devices.  
  131.  */
  132. int raw_ctl_ioctl(struct inode *inode, 
  133.   struct file *flip,
  134.   unsigned int command, 
  135.   unsigned long arg)
  136. {
  137. struct raw_config_request rq;
  138. int err = 0;
  139. int minor;
  140. switch (command) {
  141. case RAW_SETBIND:
  142. case RAW_GETBIND:
  143. /* First, find out which raw minor we want */
  144. err = copy_from_user(&rq, (void *) arg, sizeof(rq));
  145. if (err)
  146. break;
  147. minor = rq.raw_minor;
  148. if (minor <= 0 || minor > MINORMASK) {
  149. err = -EINVAL;
  150. break;
  151. }
  152. if (command == RAW_SETBIND) {
  153. /*
  154.  * This is like making block devices, so demand the
  155.  * same capability
  156.  */
  157. if (!capable(CAP_SYS_ADMIN)) {
  158. err = -EPERM;
  159. break;
  160. }
  161. /* 
  162.  * For now, we don't need to check that the underlying
  163.  * block device is present or not: we can do that when
  164.  * the raw device is opened.  Just check that the
  165.  * major/minor numbers make sense. 
  166.  */
  167. if ((rq.block_major == NODEV && 
  168.      rq.block_minor != NODEV) ||
  169.     rq.block_major > MAX_BLKDEV ||
  170.     rq.block_minor > MINORMASK) {
  171. err = -EINVAL;
  172. break;
  173. }
  174. down(&raw_devices[minor].mutex);
  175. if (raw_devices[minor].inuse) {
  176. up(&raw_devices[minor].mutex);
  177. err = -EBUSY;
  178. break;
  179. }
  180. if (raw_devices[minor].binding)
  181. bdput(raw_devices[minor].binding);
  182. raw_devices[minor].binding = 
  183. bdget(kdev_t_to_nr(MKDEV(rq.block_major, rq.block_minor)));
  184. up(&raw_devices[minor].mutex);
  185. } else {
  186. struct block_device *bdev;
  187. kdev_t dev;
  188. bdev = raw_devices[minor].binding;
  189. if (bdev) {
  190. dev = to_kdev_t(bdev->bd_dev);
  191. rq.block_major = MAJOR(dev);
  192. rq.block_minor = MINOR(dev);
  193. } else {
  194. rq.block_major = rq.block_minor = 0;
  195. }
  196. err = copy_to_user((void *) arg, &rq, sizeof(rq));
  197. }
  198. break;
  199. default:
  200. err = -EINVAL;
  201. }
  202. return err;
  203. }
  204. ssize_t raw_read(struct file *filp, char * buf, 
  205.  size_t size, loff_t *offp)
  206. {
  207. return rw_raw_dev(READ, filp, buf, size, offp);
  208. }
  209. ssize_t raw_write(struct file *filp, const char *buf, 
  210.   size_t size, loff_t *offp)
  211. {
  212. return rw_raw_dev(WRITE, filp, (char *) buf, size, offp);
  213. }
  214. #define SECTOR_BITS 9
  215. #define SECTOR_SIZE (1U << SECTOR_BITS)
  216. #define SECTOR_MASK (SECTOR_SIZE - 1)
  217. ssize_t rw_raw_dev(int rw, struct file *filp, char *buf, 
  218.    size_t size, loff_t *offp)
  219. {
  220. struct kiobuf * iobuf;
  221. int new_iobuf;
  222. int err = 0;
  223. unsigned long blocknr, blocks;
  224. size_t transferred;
  225. int iosize;
  226. int i;
  227. int minor;
  228. kdev_t dev;
  229. unsigned long limit;
  230. int sector_size, sector_bits, sector_mask;
  231. int max_sectors;
  232. /*
  233.  * First, a few checks on device size limits 
  234.  */
  235. minor = MINOR(filp->f_dentry->d_inode->i_rdev);
  236. new_iobuf = 0;
  237. iobuf = filp->f_iobuf;
  238. if (test_and_set_bit(0, &filp->f_iobuf_lock)) {
  239. /*
  240.  * A parallel read/write is using the preallocated iobuf
  241.  * so just run slow and allocate a new one.
  242.  */
  243. err = alloc_kiovec(1, &iobuf);
  244. if (err)
  245. goto out;
  246. new_iobuf = 1;
  247. }
  248. dev = to_kdev_t(raw_devices[minor].binding->bd_dev);
  249. sector_size = raw_devices[minor].sector_size;
  250. sector_bits = raw_devices[minor].sector_bits;
  251. sector_mask = sector_size- 1;
  252. max_sectors = KIO_MAX_SECTORS >> (sector_bits - 9);
  253. if (blk_size[MAJOR(dev)])
  254. limit = (((loff_t) blk_size[MAJOR(dev)][MINOR(dev)]) << BLOCK_SIZE_BITS) >> sector_bits;
  255. else
  256. limit = INT_MAX;
  257. dprintk ("rw_raw_dev: dev %d:%d (+%d)n",
  258.  MAJOR(dev), MINOR(dev), limit);
  259. err = -EINVAL;
  260. if ((*offp & sector_mask) || (size & sector_mask))
  261. goto out_free;
  262. err = 0;
  263. if (size)
  264. err = -ENXIO;
  265. if ((*offp >> sector_bits) >= limit)
  266. goto out_free;
  267. /*
  268.  * Split the IO into KIO_MAX_SECTORS chunks, mapping and
  269.  * unmapping the single kiobuf as we go to perform each chunk of
  270.  * IO.  
  271.  */
  272. transferred = 0;
  273. blocknr = *offp >> sector_bits;
  274. while (size > 0) {
  275. blocks = size >> sector_bits;
  276. if (blocks > max_sectors)
  277. blocks = max_sectors;
  278. if (blocks > limit - blocknr)
  279. blocks = limit - blocknr;
  280. if (!blocks)
  281. break;
  282. iosize = blocks << sector_bits;
  283. err = map_user_kiobuf(rw, iobuf, (unsigned long) buf, iosize);
  284. if (err)
  285. break;
  286. for (i=0; i < blocks; i++) 
  287. iobuf->blocks[i] = blocknr++;
  288. err = brw_kiovec(rw, 1, &iobuf, dev, iobuf->blocks, sector_size);
  289. if (rw == READ && err > 0)
  290. mark_dirty_kiobuf(iobuf, err);
  291. if (err >= 0) {
  292. transferred += err;
  293. size -= err;
  294. buf += err;
  295. }
  296. unmap_kiobuf(iobuf);
  297. if (err != iosize)
  298. break;
  299. }
  300. if (transferred) {
  301. *offp += transferred;
  302. err = transferred;
  303. }
  304.  out_free:
  305. if (!new_iobuf)
  306. clear_bit(0, &filp->f_iobuf_lock);
  307. else
  308. free_kiovec(1, &iobuf);
  309.  out:
  310. return err;
  311. }