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 /* 13 * Inport (ATI XL and Microsoft) busmouse driver for Linux 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 22 #include <asm/io.h> 23 #include <asm/irq.h> 24 25 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); 26 MODULE_DESCRIPTION("Inport (ATI XL and Microsoft) busmouse driver"); 27 MODULE_LICENSE("GPL"); 28 29 #define INPORT_BASE 0x23c 30 #define INPORT_EXTENT 4 31 32 #define INPORT_CONTROL_PORT INPORT_BASE + 0 33 #define INPORT_DATA_PORT INPORT_BASE + 1 34 #define INPORT_SIGNATURE_PORT INPORT_BASE + 2 35 36 #define INPORT_REG_BTNS 0x00 37 #define INPORT_REG_X 0x01 38 #define INPORT_REG_Y 0x02 39 #define INPORT_REG_MODE 0x07 40 #define INPORT_RESET 0x80 41 42 #ifdef CONFIG_MOUSE_ATIXL 43 #define INPORT_NAME "ATI XL Mouse" 44 #define INPORT_VENDOR 0x0002 45 #define INPORT_SPEED_30HZ 0x01 46 #define INPORT_SPEED_50HZ 0x02 47 #define INPORT_SPEED_100HZ 0x03 48 #define INPORT_SPEED_200HZ 0x04 49 #define INPORT_MODE_BASE INPORT_SPEED_100HZ 50 #define INPORT_MODE_IRQ 0x08 51 #else 52 #define INPORT_NAME "Microsoft InPort Mouse" 53 #define INPORT_VENDOR 0x0001 54 #define INPORT_MODE_BASE 0x10 55 #define INPORT_MODE_IRQ 0x01 56 #endif 57 #define INPORT_MODE_HOLD 0x20 58 59 #define INPORT_IRQ 5 60 61 static int inport_irq = INPORT_IRQ; 62 module_param_hw_named(irq, inport_irq, uint, irq, 0); 63 MODULE_PARM_DESC(irq, "IRQ number (5=default)"); 64 65 static struct input_dev *inport_dev; 66 67 static irqreturn_t inport_interrupt(int irq, void *dev_id) 68 { 69 unsigned char buttons; 70 71 outb(INPORT_REG_MODE, INPORT_CONTROL_PORT); 72 outb(INPORT_MODE_HOLD | INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT); 73 74 outb(INPORT_REG_X, INPORT_CONTROL_PORT); 75 input_report_rel(inport_dev, REL_X, inb(INPORT_DATA_PORT)); 76 77 outb(INPORT_REG_Y, INPORT_CONTROL_PORT); 78 input_report_rel(inport_dev, REL_Y, inb(INPORT_DATA_PORT)); 79 80 outb(INPORT_REG_BTNS, INPORT_CONTROL_PORT); 81 buttons = inb(INPORT_DATA_PORT); 82 83 input_report_key(inport_dev, BTN_MIDDLE, buttons & 1); 84 input_report_key(inport_dev, BTN_LEFT, buttons & 2); 85 input_report_key(inport_dev, BTN_RIGHT, buttons & 4); 86 87 outb(INPORT_REG_MODE, INPORT_CONTROL_PORT); 88 outb(INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT); 89 90 input_sync(inport_dev); 91 return IRQ_HANDLED; 92 } 93 94 static int inport_open(struct input_dev *dev) 95 { 96 if (request_irq(inport_irq, inport_interrupt, 0, "inport", NULL)) 97 return -EBUSY; 98 outb(INPORT_REG_MODE, INPORT_CONTROL_PORT); 99 outb(INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT); 100 101 return 0; 102 } 103 104 static void inport_close(struct input_dev *dev) 105 { 106 outb(INPORT_REG_MODE, INPORT_CONTROL_PORT); 107 outb(INPORT_MODE_BASE, INPORT_DATA_PORT); 108 free_irq(inport_irq, NULL); 109 } 110 111 static int __init inport_init(void) 112 { 113 unsigned char a, b, c; 114 int err; 115 116 if (!request_region(INPORT_BASE, INPORT_EXTENT, "inport")) { 117 printk(KERN_ERR "inport.c: Can't allocate ports at %#x\n", INPORT_BASE); 118 return -EBUSY; 119 } 120 121 a = inb(INPORT_SIGNATURE_PORT); 122 b = inb(INPORT_SIGNATURE_PORT); 123 c = inb(INPORT_SIGNATURE_PORT); 124 if (a == b || a != c) { 125 printk(KERN_INFO "inport.c: Didn't find InPort mouse at %#x\n", INPORT_BASE); 126 err = -ENODEV; 127 goto err_release_region; 128 } 129 130 inport_dev = input_allocate_device(); 131 if (!inport_dev) { 132 printk(KERN_ERR "inport.c: Not enough memory for input device\n"); 133 err = -ENOMEM; 134 goto err_release_region; 135 } 136 137 inport_dev->name = INPORT_NAME; 138 inport_dev->phys = "isa023c/input0"; 139 inport_dev->id.bustype = BUS_ISA; 140 inport_dev->id.vendor = INPORT_VENDOR; 141 inport_dev->id.product = 0x0001; 142 inport_dev->id.version = 0x0100; 143 144 inport_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); 145 inport_dev->keybit[BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) | 146 BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT); 147 inport_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y); 148 149 inport_dev->open = inport_open; 150 inport_dev->close = inport_close; 151 152 outb(INPORT_RESET, INPORT_CONTROL_PORT); 153 outb(INPORT_REG_MODE, INPORT_CONTROL_PORT); 154 outb(INPORT_MODE_BASE, INPORT_DATA_PORT); 155 156 err = input_register_device(inport_dev); 157 if (err) 158 goto err_free_dev; 159 160 return 0; 161 162 err_free_dev: 163 input_free_device(inport_dev); 164 err_release_region: 165 release_region(INPORT_BASE, INPORT_EXTENT); 166 167 return err; 168 } 169 170 static void __exit inport_exit(void) 171 { 172 input_unregister_device(inport_dev); 173 release_region(INPORT_BASE, INPORT_EXTENT); 174 } 175 176 module_init(inport_init); 177 module_exit(inport_exit); 178