patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / drivers / input / serio / 98kbd-io.c
1 /*
2  *  NEC PC-9801 keyboard controller driver for Linux
3  *
4  *  Copyright (c) 1999-2002 Osamu Tomita <tomita@cinet.co.jp>
5  *    Based on i8042.c written by Vojtech Pavlik
6  */
7
8 /*
9  * This program is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU General Public License version 2 as published by
11  * the Free Software Foundation.
12  */
13
14 #include <linux/config.h>
15 #include <linux/delay.h>
16 #include <linux/module.h>
17 #include <linux/interrupt.h>
18 #include <linux/ioport.h>
19 #include <linux/init.h>
20 #include <linux/serio.h>
21 #include <linux/sched.h>
22
23 #include <asm/io.h>
24
25 MODULE_AUTHOR("Osamu Tomita <tomita@cinet.co.jp>");
26 MODULE_DESCRIPTION("NEC PC-9801 keyboard controller driver");
27 MODULE_LICENSE("GPL");
28
29 /*
30  * Names.
31  */
32
33 #define KBD98_PHYS_DESC "isa0041/serio0"
34
35 /*
36  * IRQs.
37  */
38
39 #define KBD98_IRQ       1
40
41 /*
42  * Register numbers.
43  */
44
45 #define KBD98_COMMAND_REG       0x43
46 #define KBD98_STATUS_REG        0x43
47 #define KBD98_DATA_REG          0x41
48
49 spinlock_t kbd98io_lock = SPIN_LOCK_UNLOCKED;
50
51 static struct serio kbd98_port;
52 extern struct pt_regs *kbd_pt_regs;
53
54 static irqreturn_t kbd98io_interrupt(int irq, void *dev_id, struct pt_regs *regs);
55
56 /*
57  * kbd98_flush() flushes all data that may be in the keyboard buffers
58  */
59
60 static int kbd98_flush(void)
61 {
62         unsigned long flags;
63
64         spin_lock_irqsave(&kbd98io_lock, flags);
65
66         while (inb(KBD98_STATUS_REG) & 0x02) /* RxRDY */
67                 inb(KBD98_DATA_REG);
68
69         if (inb(KBD98_STATUS_REG) & 0x38)
70                 printk("98kbd-io: Keyboard error!\n");
71
72         spin_unlock_irqrestore(&kbd98io_lock, flags);
73
74         return 0;
75 }
76
77 /*
78  * kbd98_write() sends a byte out through the keyboard interface.
79  */
80
81 static int kbd98_write(struct serio *port, unsigned char c)
82 {
83         unsigned long flags;
84
85         spin_lock_irqsave(&kbd98io_lock, flags);
86
87         outb(0, 0x5f);                  /* wait */
88         outb(0x17, KBD98_COMMAND_REG);  /* enable send command */
89         outb(0, 0x5f);                  /* wait */
90         outb(c, KBD98_DATA_REG);
91         outb(0, 0x5f);                  /* wait */
92         outb(0x16, KBD98_COMMAND_REG);  /* disable send command */
93         outb(0, 0x5f);                  /* wait */
94
95         spin_unlock_irqrestore(&kbd98io_lock, flags);
96
97         return 0;
98 }
99
100 /*
101  * kbd98_open() is called when a port is open by the higher layer.
102  * It allocates the interrupt and enables in in the chip.
103  */
104
105 static int kbd98_open(struct serio *port)
106 {
107         kbd98_flush();
108
109         if (request_irq(KBD98_IRQ, kbd98io_interrupt, 0, "kbd98", NULL)) {
110                 printk(KERN_ERR "98kbd-io.c: Can't get irq %d for %s, unregistering the port.\n", KBD98_IRQ, "KBD");
111                 serio_unregister_port(port);
112                 return -1;
113         }
114
115         return 0;
116 }
117
118 static void kbd98_close(struct serio *port)
119 {
120         free_irq(KBD98_IRQ, NULL);
121
122         kbd98_flush();
123 }
124
125 /*
126  * Structures for registering the devices in the serio.c module.
127  */
128
129 static struct serio kbd98_port =
130 {
131         .type =         SERIO_PC9800,
132         .write =        kbd98_write,
133         .open =         kbd98_open,
134         .close =        kbd98_close,
135         .driver =       NULL,
136         .name =         "PC-9801 Kbd Port",
137         .phys =         KBD98_PHYS_DESC,
138 };
139
140 /*
141  * kbd98io_interrupt() is the most important function in this driver -
142  * it handles the interrupts from keyboard, and sends incoming bytes
143  * to the upper layers.
144  */
145
146 static irqreturn_t kbd98io_interrupt(int irq, void *dev_id, struct pt_regs *regs)
147 {
148         unsigned long flags;
149         unsigned char data;
150
151         spin_lock_irqsave(&kbd98io_lock, flags);
152
153         data = inb(KBD98_DATA_REG);
154         spin_unlock_irqrestore(&kbd98io_lock, flags);
155         serio_interrupt(&kbd98_port, data, 0, regs);
156
157         return IRQ_HANDLED;
158 }
159
160 int __init kbd98io_init(void)
161 {
162         serio_register_port(&kbd98_port);
163
164         printk(KERN_INFO "serio: PC-9801 %s port at %#lx,%#lx irq %d\n",
165                "KBD",
166                (unsigned long) KBD98_DATA_REG,
167                (unsigned long) KBD98_COMMAND_REG,
168                KBD98_IRQ);
169
170         return 0;
171 }
172
173 void __exit kbd98io_exit(void)
174 {
175         serio_unregister_port(&kbd98_port);
176 }
177
178 module_init(kbd98io_init);
179 module_exit(kbd98io_exit);