gio.c 3.4 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/smp_lock.h>
  18. #include <linux/kdev_t.h>
  19. #include <linux/cdev.h>
  20. #include <linux/fs.h>
  21. #include <asm/io.h>
  22. #include <asm/uaccess.h>
  23. #include <mach-landisk/mach/gio.h>
  24. #include <mach-landisk/mach/iodata_landisk.h>
  25. #define DEVCOUNT 4
  26. #define GIO_MINOR 2 /* GIO minor no. */
  27. static dev_t dev;
  28. static struct cdev *cdev_p;
  29. static int openCnt;
  30. static int gio_open(struct inode *inode, struct file *filp)
  31. {
  32. int minor;
  33. int ret = -ENOENT;
  34. lock_kernel();
  35. minor = MINOR(inode->i_rdev);
  36. if (minor < DEVCOUNT) {
  37. if (openCnt > 0) {
  38. ret = -EALREADY;
  39. } else {
  40. openCnt++;
  41. ret = 0;
  42. }
  43. }
  44. unlock_kernel();
  45. return ret;
  46. }
  47. static int gio_close(struct inode *inode, struct file *filp)
  48. {
  49. int minor;
  50. minor = MINOR(inode->i_rdev);
  51. if (minor < DEVCOUNT) {
  52. openCnt--;
  53. }
  54. return 0;
  55. }
  56. static int gio_ioctl(struct inode *inode, struct file *filp,
  57. unsigned int cmd, unsigned long arg)
  58. {
  59. unsigned int data;
  60. static unsigned int addr = 0;
  61. if (cmd & 0x01) { /* write */
  62. if (copy_from_user(&data, (int *)arg, sizeof(int))) {
  63. return -EFAULT;
  64. }
  65. }
  66. switch (cmd) {
  67. case GIODRV_IOCSGIOSETADDR: /* address set */
  68. addr = data;
  69. break;
  70. case GIODRV_IOCSGIODATA1: /* write byte */
  71. ctrl_outb((unsigned char)(0x0ff & data), addr);
  72. break;
  73. case GIODRV_IOCSGIODATA2: /* write word */
  74. if (addr & 0x01) {
  75. return -EFAULT;
  76. }
  77. ctrl_outw((unsigned short int)(0x0ffff & data), addr);
  78. break;
  79. case GIODRV_IOCSGIODATA4: /* write long */
  80. if (addr & 0x03) {
  81. return -EFAULT;
  82. }
  83. ctrl_outl(data, addr);
  84. break;
  85. case GIODRV_IOCGGIODATA1: /* read byte */
  86. data = ctrl_inb(addr);
  87. break;
  88. case GIODRV_IOCGGIODATA2: /* read word */
  89. if (addr & 0x01) {
  90. return -EFAULT;
  91. }
  92. data = ctrl_inw(addr);
  93. break;
  94. case GIODRV_IOCGGIODATA4: /* read long */
  95. if (addr & 0x03) {
  96. return -EFAULT;
  97. }
  98. data = ctrl_inl(addr);
  99. break;
  100. default:
  101. return -EFAULT;
  102. break;
  103. }
  104. if ((cmd & 0x01) == 0) { /* read */
  105. if (copy_to_user((int *)arg, &data, sizeof(int))) {
  106. return -EFAULT;
  107. }
  108. }
  109. return 0;
  110. }
  111. static const struct file_operations gio_fops = {
  112. .owner = THIS_MODULE,
  113. .open = gio_open, /* open */
  114. .release = gio_close, /* release */
  115. .ioctl = gio_ioctl, /* ioctl */
  116. };
  117. static int __init gio_init(void)
  118. {
  119. int error;
  120. printk(KERN_INFO "gio: driver initialized\n");
  121. openCnt = 0;
  122. if ((error = alloc_chrdev_region(&dev, 0, DEVCOUNT, "gio")) < 0) {
  123. printk(KERN_ERR
  124. "gio: Couldn't alloc_chrdev_region, error=%d\n",
  125. error);
  126. return 1;
  127. }
  128. cdev_p = cdev_alloc();
  129. cdev_p->ops = &gio_fops;
  130. error = cdev_add(cdev_p, dev, DEVCOUNT);
  131. if (error) {
  132. printk(KERN_ERR
  133. "gio: Couldn't cdev_add, error=%d\n", error);
  134. return 1;
  135. }
  136. return 0;
  137. }
  138. static void __exit gio_exit(void)
  139. {
  140. cdev_del(cdev_p);
  141. unregister_chrdev_region(dev, DEVCOUNT);
  142. }
  143. module_init(gio_init);
  144. module_exit(gio_exit);
  145. MODULE_LICENSE("GPL");