2 * $Id: parkbd.c,v 1.10 2002/03/13 10:09:20 vojtech Exp $
4 * Copyright (c) 1999-2001 Vojtech Pavlik
8 * Parallel port to Keyboard port adapter driver for Linux
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 */
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
)
72 if (!parkbd_mode
) return -1;
80 parkbd_buffer
= c
| (((int) (~p
& 1)) << 8) | 0x600;
87 static void parkbd_interrupt(int irq
, void *dev_id
, struct pt_regs
*regs
)
92 if (parkbd_counter
&& ((parkbd_counter
== 11) || time_after(jiffies
, parkbd_last
+ HZ
/100))) {
100 parkbd_writelines(((parkbd_buffer
>> parkbd_counter
++) & 1) | 2);
102 if (parkbd_counter
== 11) {
106 parkbd_writelines(3);
111 if ((parkbd_counter
== parkbd_mode
+ 10) || time_after(jiffies
, parkbd_last
+ HZ
/100)) {
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)
130 printk(KERN_ERR
"parkbd: no port specified\n");
134 pp
= parport_find_number(parkbd
);
137 printk(KERN_ERR
"parkbd: no such parport\n");
141 parkbd_dev
= parport_register_device(pp
, "parkbd", NULL
, NULL
, parkbd_interrupt
, PARPORT_DEV_EXCL
, NULL
);
142 parport_put_port(pp
);
147 if (parport_claim(parkbd_dev
)) {
148 parport_unregister_device(parkbd_dev
);
152 parkbd_start
= jiffies
;
157 static struct serio
* __init
parkbd_allocate_serio(void)
161 serio
= kmalloc(sizeof(struct serio
), GFP_KERNEL
);
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
);
173 int __init
parkbd_init(void)
177 err
= parkbd_getport();
181 parkbd_port
= parkbd_allocate_serio();
183 parport_release(parkbd_dev
);
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
);
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
);