inport.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright (c) 1999-2001 Vojtech Pavlik
  4. *
  5. * Based on the work of:
  6. * Teemu Rantanen Derrick Cole
  7. * Peter Cervasio Christoph Niemann
  8. * Philip Blundell Russell King
  9. * Bob Harris
  10. */
  11. /*
  12. * Inport (ATI XL and Microsoft) busmouse driver for Linux
  13. */
  14. /*
  15. */
  16. #include <linux/module.h>
  17. #include <linux/ioport.h>
  18. #include <linux/init.h>
  19. #include <linux/interrupt.h>
  20. #include <linux/input.h>
  21. #include <asm/io.h>
  22. #include <asm/irq.h>
  23. MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
  24. MODULE_DESCRIPTION("Inport (ATI XL and Microsoft) busmouse driver");
  25. MODULE_LICENSE("GPL");
  26. #define INPORT_BASE 0x23c
  27. #define INPORT_EXTENT 4
  28. #define INPORT_CONTROL_PORT INPORT_BASE + 0
  29. #define INPORT_DATA_PORT INPORT_BASE + 1
  30. #define INPORT_SIGNATURE_PORT INPORT_BASE + 2
  31. #define INPORT_REG_BTNS 0x00
  32. #define INPORT_REG_X 0x01
  33. #define INPORT_REG_Y 0x02
  34. #define INPORT_REG_MODE 0x07
  35. #define INPORT_RESET 0x80
  36. #ifdef CONFIG_MOUSE_ATIXL
  37. #define INPORT_NAME "ATI XL Mouse"
  38. #define INPORT_VENDOR 0x0002
  39. #define INPORT_SPEED_30HZ 0x01
  40. #define INPORT_SPEED_50HZ 0x02
  41. #define INPORT_SPEED_100HZ 0x03
  42. #define INPORT_SPEED_200HZ 0x04
  43. #define INPORT_MODE_BASE INPORT_SPEED_100HZ
  44. #define INPORT_MODE_IRQ 0x08
  45. #else
  46. #define INPORT_NAME "Microsoft InPort Mouse"
  47. #define INPORT_VENDOR 0x0001
  48. #define INPORT_MODE_BASE 0x10
  49. #define INPORT_MODE_IRQ 0x01
  50. #endif
  51. #define INPORT_MODE_HOLD 0x20
  52. #define INPORT_IRQ 5
  53. static int inport_irq = INPORT_IRQ;
  54. module_param_hw_named(irq, inport_irq, uint, irq, 0);
  55. MODULE_PARM_DESC(irq, "IRQ number (5=default)");
  56. static struct input_dev *inport_dev;
  57. static irqreturn_t inport_interrupt(int irq, void *dev_id)
  58. {
  59. unsigned char buttons;
  60. outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
  61. outb(INPORT_MODE_HOLD | INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT);
  62. outb(INPORT_REG_X, INPORT_CONTROL_PORT);
  63. input_report_rel(inport_dev, REL_X, inb(INPORT_DATA_PORT));
  64. outb(INPORT_REG_Y, INPORT_CONTROL_PORT);
  65. input_report_rel(inport_dev, REL_Y, inb(INPORT_DATA_PORT));
  66. outb(INPORT_REG_BTNS, INPORT_CONTROL_PORT);
  67. buttons = inb(INPORT_DATA_PORT);
  68. input_report_key(inport_dev, BTN_MIDDLE, buttons & 1);
  69. input_report_key(inport_dev, BTN_LEFT, buttons & 2);
  70. input_report_key(inport_dev, BTN_RIGHT, buttons & 4);
  71. outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
  72. outb(INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT);
  73. input_sync(inport_dev);
  74. return IRQ_HANDLED;
  75. }
  76. static int inport_open(struct input_dev *dev)
  77. {
  78. if (request_irq(inport_irq, inport_interrupt, 0, "inport", NULL))
  79. return -EBUSY;
  80. outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
  81. outb(INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT);
  82. return 0;
  83. }
  84. static void inport_close(struct input_dev *dev)
  85. {
  86. outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
  87. outb(INPORT_MODE_BASE, INPORT_DATA_PORT);
  88. free_irq(inport_irq, NULL);
  89. }
  90. static int __init inport_init(void)
  91. {
  92. unsigned char a, b, c;
  93. int err;
  94. if (!request_region(INPORT_BASE, INPORT_EXTENT, "inport")) {
  95. printk(KERN_ERR "inport.c: Can't allocate ports at %#x\n", INPORT_BASE);
  96. return -EBUSY;
  97. }
  98. a = inb(INPORT_SIGNATURE_PORT);
  99. b = inb(INPORT_SIGNATURE_PORT);
  100. c = inb(INPORT_SIGNATURE_PORT);
  101. if (a == b || a != c) {
  102. printk(KERN_INFO "inport.c: Didn't find InPort mouse at %#x\n", INPORT_BASE);
  103. err = -ENODEV;
  104. goto err_release_region;
  105. }
  106. inport_dev = input_allocate_device();
  107. if (!inport_dev) {
  108. printk(KERN_ERR "inport.c: Not enough memory for input device\n");
  109. err = -ENOMEM;
  110. goto err_release_region;
  111. }
  112. inport_dev->name = INPORT_NAME;
  113. inport_dev->phys = "isa023c/input0";
  114. inport_dev->id.bustype = BUS_ISA;
  115. inport_dev->id.vendor = INPORT_VENDOR;
  116. inport_dev->id.product = 0x0001;
  117. inport_dev->id.version = 0x0100;
  118. inport_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
  119. inport_dev->keybit[BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) |
  120. BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT);
  121. inport_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
  122. inport_dev->open = inport_open;
  123. inport_dev->close = inport_close;
  124. outb(INPORT_RESET, INPORT_CONTROL_PORT);
  125. outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
  126. outb(INPORT_MODE_BASE, INPORT_DATA_PORT);
  127. err = input_register_device(inport_dev);
  128. if (err)
  129. goto err_free_dev;
  130. return 0;
  131. err_free_dev:
  132. input_free_device(inport_dev);
  133. err_release_region:
  134. release_region(INPORT_BASE, INPORT_EXTENT);
  135. return err;
  136. }
  137. static void __exit inport_exit(void)
  138. {
  139. input_unregister_device(inport_dev);
  140. release_region(INPORT_BASE, INPORT_EXTENT);
  141. }
  142. module_init(inport_init);
  143. module_exit(inport_exit);