gio.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. /*
  2. * arch/sh/boards/landisk/gio.c - driver for landisk
  3. *
  4. * This driver will also support the I-O DATA Device, Inc. LANDISK Board.
  5. * LANDISK and USL-5P Button, LED and GIO driver drive function.
  6. *
  7. * Copylight (C) 2006 kogiidena
  8. * Copylight (C) 2002 Atom Create Engineering Co., Ltd. *
  9. *
  10. * This file is subject to the terms and conditions of the GNU General Public
  11. * License. See the file "COPYING" in the main directory of this archive
  12. * for more details.
  13. *
  14. */
  15. #include <linux/module.h>
  16. #include <linux/init.h>
  17. #include <linux/kdev_t.h>
  18. #include <linux/cdev.h>
  19. #include <linux/fs.h>
  20. #include <asm/io.h>
  21. #include <asm/uaccess.h>
  22. #include <mach-landisk/mach/gio.h>
  23. #include <mach-landisk/mach/iodata_landisk.h>
  24. #define DEVCOUNT 4
  25. #define GIO_MINOR 2 /* GIO minor no. */
  26. static dev_t dev;
  27. static struct cdev *cdev_p;
  28. static int openCnt;
  29. static int gio_open(struct inode *inode, struct file *filp)
  30. {
  31. int minor;
  32. int ret = -ENOENT;
  33. preempt_disable();
  34. minor = MINOR(inode->i_rdev);
  35. if (minor < DEVCOUNT) {
  36. if (openCnt > 0) {
  37. ret = -EALREADY;
  38. } else {
  39. openCnt++;
  40. ret = 0;
  41. }
  42. }
  43. preempt_enable();
  44. return ret;
  45. }
  46. static int gio_close(struct inode *inode, struct file *filp)
  47. {
  48. int minor;
  49. minor = MINOR(inode->i_rdev);
  50. if (minor < DEVCOUNT) {
  51. openCnt--;
  52. }
  53. return 0;
  54. }
  55. static long gio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
  56. {
  57. unsigned int data;
  58. static unsigned int addr = 0;
  59. if (cmd & 0x01) { /* write */
  60. if (copy_from_user(&data, (int *)arg, sizeof(int))) {
  61. return -EFAULT;
  62. }
  63. }
  64. switch (cmd) {
  65. case GIODRV_IOCSGIOSETADDR: /* address set */
  66. addr = data;
  67. break;
  68. case GIODRV_IOCSGIODATA1: /* write byte */
  69. __raw_writeb((unsigned char)(0x0ff & data), addr);
  70. break;
  71. case GIODRV_IOCSGIODATA2: /* write word */
  72. if (addr & 0x01) {
  73. return -EFAULT;
  74. }
  75. __raw_writew((unsigned short int)(0x0ffff & data), addr);
  76. break;
  77. case GIODRV_IOCSGIODATA4: /* write long */
  78. if (addr & 0x03) {
  79. return -EFAULT;
  80. }
  81. __raw_writel(data, addr);
  82. break;
  83. case GIODRV_IOCGGIODATA1: /* read byte */
  84. data = __raw_readb(addr);
  85. break;
  86. case GIODRV_IOCGGIODATA2: /* read word */
  87. if (addr & 0x01) {
  88. return -EFAULT;
  89. }
  90. data = __raw_readw(addr);
  91. break;
  92. case GIODRV_IOCGGIODATA4: /* read long */
  93. if (addr & 0x03) {
  94. return -EFAULT;
  95. }
  96. data = __raw_readl(addr);
  97. break;
  98. default:
  99. return -EFAULT;
  100. break;
  101. }
  102. if ((cmd & 0x01) == 0) { /* read */
  103. if (copy_to_user((int *)arg, &data, sizeof(int))) {
  104. return -EFAULT;
  105. }
  106. }
  107. return 0;
  108. }
  109. static const struct file_operations gio_fops = {
  110. .owner = THIS_MODULE,
  111. .open = gio_open, /* open */
  112. .release = gio_close, /* release */
  113. .unlocked_ioctl = gio_ioctl,
  114. .llseek = noop_llseek,
  115. };
  116. static int __init gio_init(void)
  117. {
  118. int error;
  119. printk(KERN_INFO "gio: driver initialized\n");
  120. openCnt = 0;
  121. if ((error = alloc_chrdev_region(&dev, 0, DEVCOUNT, "gio")) < 0) {
  122. printk(KERN_ERR
  123. "gio: Couldn't alloc_chrdev_region, error=%d\n",
  124. error);
  125. return 1;
  126. }
  127. cdev_p = cdev_alloc();
  128. cdev_p->ops = &gio_fops;
  129. error = cdev_add(cdev_p, dev, DEVCOUNT);
  130. if (error) {
  131. printk(KERN_ERR
  132. "gio: Couldn't cdev_add, error=%d\n", error);
  133. return 1;
  134. }
  135. return 0;
  136. }
  137. static void __exit gio_exit(void)
  138. {
  139. cdev_del(cdev_p);
  140. unregister_chrdev_region(dev, DEVCOUNT);
  141. }
  142. module_init(gio_init);
  143. module_exit(gio_exit);
  144. MODULE_LICENSE("GPL");