3 * Copyright (c) 2002 Osamu Tomita
5 * Based on the work of:
6 * James Banks Matthew Dillon
7 * David Giller Nathan Laredo
8 * Linus Torvalds Johan Myreen
9 * Cliff Matthews Philip Blundell
10 * Russell King Vojtech Pavlik
14 * NEC PC-9801 Bus Mouse Driver for Linux
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version.
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
34 #include <linux/config.h>
35 #include <linux/module.h>
36 #include <linux/moduleparam.h>
37 #include <linux/delay.h>
38 #include <linux/ioport.h>
39 #include <linux/init.h>
40 #include <linux/input.h>
41 #include <linux/interrupt.h>
46 MODULE_AUTHOR("Osamu Tomita <tomita@cinet.co.jp>");
47 MODULE_DESCRIPTION("PC-9801 busmouse driver");
48 MODULE_LICENSE("GPL");
50 #define PC98BM_BASE 0x7fd9
51 #define PC98BM_DATA_PORT PC98BM_BASE + 0
52 /* PC98BM_SIGNATURE_PORT does not exist */
53 #define PC98BM_CONTROL_PORT PC98BM_BASE + 4
54 /* PC98BM_INTERRUPT_PORT does not exist */
55 #define PC98BM_CONFIG_PORT PC98BM_BASE + 6
57 #define PC98BM_ENABLE_IRQ 0x00
58 #define PC98BM_DISABLE_IRQ 0x10
59 #define PC98BM_READ_X_LOW 0x80
60 #define PC98BM_READ_X_HIGH 0xa0
61 #define PC98BM_READ_Y_LOW 0xc0
62 #define PC98BM_READ_Y_HIGH 0xe0
64 #define PC98BM_DEFAULT_MODE 0x93
65 /* PC98BM_CONFIG_BYTE is not used */
66 /* PC98BM_SIGNATURE_BYTE is not used */
68 #define PC98BM_TIMER_PORT 0xbfdb
69 #define PC98BM_DEFAULT_TIMER_VAL 0x00
73 static int pc98bm_irq = PC98BM_IRQ;
74 module_param_named(irq, pc98bm_irq, uint, 0);
75 MODULE_PARM_DESC(irq, "IRQ number (13=default)");
77 __obsolete_setup("pc98bm_irq=");
79 static int pc98bm_used = 0;
81 static irqreturn_t pc98bm_interrupt(int irq, void *dev_id, struct pt_regs *regs);
83 static int pc98bm_open(struct input_dev *dev)
87 if (request_irq(pc98bm_irq, pc98bm_interrupt, 0, "98busmouse", NULL)) {
89 printk(KERN_ERR "98busmouse.c: Can't allocate irq %d\n", pc98bm_irq);
92 outb(PC98BM_ENABLE_IRQ, PC98BM_CONTROL_PORT);
96 static void pc98bm_close(struct input_dev *dev)
100 outb(PC98BM_DISABLE_IRQ, PC98BM_CONTROL_PORT);
101 free_irq(pc98bm_irq, NULL);
104 static struct input_dev pc98bm_dev = {
105 .evbit = { BIT(EV_KEY) | BIT(EV_REL) },
106 .keybit = { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT) },
107 .relbit = { BIT(REL_X) | BIT(REL_Y) },
109 .close = pc98bm_close,
110 .name = "PC-9801 bus mouse",
111 .phys = "isa7fd9/input0",
120 static irqreturn_t pc98bm_interrupt(int irq, void *dev_id, struct pt_regs *regs)
123 unsigned char buttons;
125 outb(PC98BM_READ_X_LOW, PC98BM_CONTROL_PORT);
126 dx = (inb(PC98BM_DATA_PORT) & 0xf);
127 outb(PC98BM_READ_X_HIGH, PC98BM_CONTROL_PORT);
128 dx |= (inb(PC98BM_DATA_PORT) & 0xf) << 4;
129 outb(PC98BM_READ_Y_LOW, PC98BM_CONTROL_PORT);
130 dy = (inb(PC98BM_DATA_PORT) & 0xf);
131 outb(PC98BM_READ_Y_HIGH, PC98BM_CONTROL_PORT);
132 buttons = inb(PC98BM_DATA_PORT);
133 dy |= (buttons & 0xf) << 4;
134 buttons = ~buttons >> 5;
136 input_report_rel(&pc98bm_dev, REL_X, dx);
137 input_report_rel(&pc98bm_dev, REL_Y, dy);
138 input_report_key(&pc98bm_dev, BTN_RIGHT, buttons & 1);
139 input_report_key(&pc98bm_dev, BTN_MIDDLE, buttons & 2);
140 input_report_key(&pc98bm_dev, BTN_LEFT, buttons & 4);
141 input_sync(&pc98bm_dev);
143 outb(PC98BM_ENABLE_IRQ, PC98BM_CONTROL_PORT);
148 static int __init pc98bm_init(void)
152 for (i = 0; i <= 6; i += 2) {
153 if (!request_region(PC98BM_BASE + i, 1, "98busmouse")) {
154 printk(KERN_ERR "98busmouse.c: Can't allocate ports at %#x\n", PC98BM_BASE + i);
157 release_region(PC98BM_BASE + i, 1);
165 if (!request_region(PC98BM_TIMER_PORT, 1, "98busmouse")) {
166 printk(KERN_ERR "98busmouse.c: Can't allocate ports at %#x\n", PC98BM_TIMER_PORT);
167 for (i = 0; i <= 6; i += 2)
168 release_region(PC98BM_BASE + i, 1);
173 outb(PC98BM_DEFAULT_MODE, PC98BM_CONFIG_PORT);
174 outb(PC98BM_DISABLE_IRQ, PC98BM_CONTROL_PORT);
176 outb(PC98BM_DEFAULT_TIMER_VAL, PC98BM_TIMER_PORT);
178 input_register_device(&pc98bm_dev);
180 printk(KERN_INFO "input: PC-9801 bus mouse at %#x irq %d\n", PC98BM_BASE, pc98bm_irq);
185 static void __exit pc98bm_exit(void)
189 input_unregister_device(&pc98bm_dev);
190 for (i = 0; i <= 6; i += 2)
191 release_region(PC98BM_BASE + i, 1);
193 release_region(PC98BM_TIMER_PORT, 1);
196 module_init(pc98bm_init);
197 module_exit(pc98bm_exit);