gio.c 3.3 KB

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