MOXA linux-2.6.x / linux-2.6.9-uc0 from sdlinux-moxaart.tgz
[linux-2.6.9-moxart.git] / drivers / input / serio / parkbd.c
bloba859df676487a9ee9879eda05c802ae3311d74c4
1 /*
2 * $Id: parkbd.c,v 1.10 2002/03/13 10:09:20 vojtech Exp $
4 * Copyright (c) 1999-2001 Vojtech Pavlik
5 */
7 /*
8 * Parallel port to Keyboard port adapter driver for Linux
9 */
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 * Should you need to contact me, the author, you can do so either by
27 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
28 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
31 #include <linux/module.h>
32 #include <linux/parport.h>
33 #include <linux/init.h>
34 #include <linux/serio.h>
36 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
37 MODULE_DESCRIPTION("Parallel port to Keyboard port adapter driver");
38 MODULE_LICENSE("GPL");
40 MODULE_PARM(parkbd, "1i");
41 MODULE_PARM(parkbd_mode, "1i");
43 #define PARKBD_CLOCK 0x01 /* Strobe & Ack */
44 #define PARKBD_DATA 0x02 /* AutoFd & Busy */
46 static int parkbd;
47 static int parkbd_mode = SERIO_8042;
49 static int parkbd_buffer;
50 static int parkbd_counter;
51 static unsigned long parkbd_last;
52 static int parkbd_writing;
53 static unsigned long parkbd_start;
55 static struct pardevice *parkbd_dev;
56 static struct serio *parkbd_port;
58 static int parkbd_readlines(void)
60 return (parport_read_status(parkbd_dev->port) >> 6) ^ 2;
63 static void parkbd_writelines(int data)
65 parport_write_control(parkbd_dev->port, (~data & 3) | 0x10);
68 static int parkbd_write(struct serio *port, unsigned char c)
70 unsigned char p;
72 if (!parkbd_mode) return -1;
74 p = c ^ (c >> 4);
75 p = p ^ (p >> 2);
76 p = p ^ (p >> 1);
78 parkbd_counter = 0;
79 parkbd_writing = 1;
80 parkbd_buffer = c | (((int) (~p & 1)) << 8) | 0x600;
82 parkbd_writelines(2);
84 return 0;
87 static void parkbd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
90 if (parkbd_writing) {
92 if (parkbd_counter && ((parkbd_counter == 11) || time_after(jiffies, parkbd_last + HZ/100))) {
93 parkbd_counter = 0;
94 parkbd_buffer = 0;
95 parkbd_writing = 0;
96 parkbd_writelines(3);
97 return;
100 parkbd_writelines(((parkbd_buffer >> parkbd_counter++) & 1) | 2);
102 if (parkbd_counter == 11) {
103 parkbd_counter = 0;
104 parkbd_buffer = 0;
105 parkbd_writing = 0;
106 parkbd_writelines(3);
109 } else {
111 if ((parkbd_counter == parkbd_mode + 10) || time_after(jiffies, parkbd_last + HZ/100)) {
112 parkbd_counter = 0;
113 parkbd_buffer = 0;
116 parkbd_buffer |= (parkbd_readlines() >> 1) << parkbd_counter++;
118 if (parkbd_counter == parkbd_mode + 10)
119 serio_interrupt(parkbd_port, (parkbd_buffer >> (2 - parkbd_mode)) & 0xff, 0, regs);
122 parkbd_last = jiffies;
125 static int parkbd_getport(void)
127 struct parport *pp;
129 if (parkbd < 0) {
130 printk(KERN_ERR "parkbd: no port specified\n");
131 return -ENODEV;
134 pp = parport_find_number(parkbd);
136 if (pp == NULL) {
137 printk(KERN_ERR "parkbd: no such parport\n");
138 return -ENODEV;
141 parkbd_dev = parport_register_device(pp, "parkbd", NULL, NULL, parkbd_interrupt, PARPORT_DEV_EXCL, NULL);
142 parport_put_port(pp);
144 if (!parkbd_dev)
145 return -ENODEV;
147 if (parport_claim(parkbd_dev)) {
148 parport_unregister_device(parkbd_dev);
149 return -EBUSY;
152 parkbd_start = jiffies;
154 return 0;
157 static struct serio * __init parkbd_allocate_serio(void)
159 struct serio *serio;
161 serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
162 if (serio) {
163 memset(serio, 0, sizeof(struct serio));
164 serio->type = parkbd_mode;
165 serio->write = parkbd_write,
166 strlcpy(serio->name, "PARKBD AT/XT keyboard adapter", sizeof(serio->name));
167 snprintf(serio->phys, sizeof(serio->phys), "%s/serio0", parkbd_dev->port->name);
170 return serio;
173 int __init parkbd_init(void)
175 int err;
177 err = parkbd_getport();
178 if (err)
179 return err;
181 parkbd_port = parkbd_allocate_serio();
182 if (!parkbd_port) {
183 parport_release(parkbd_dev);
184 return -ENOMEM;
187 parkbd_writelines(3);
189 serio_register_port(parkbd_port);
191 printk(KERN_INFO "serio: PARKBD %s adapter on %s\n",
192 parkbd_mode ? "AT" : "XT", parkbd_dev->port->name);
194 return 0;
197 void __exit parkbd_exit(void)
199 parport_release(parkbd_dev);
200 serio_unregister_port(parkbd_port);
201 parport_unregister_device(parkbd_dev);
204 module_init(parkbd_init);
205 module_exit(parkbd_exit);