2 * LASI PS/2 keyboard/psaux driver for HP-PARISC workstations
4 * (c) Copyright 1999 The Puffin Group Inc.
5 * by Alex deVries <adevries@thepuffingroup.com>
6 * Copyright 1999, 2000 Philipp Rumpf <prumpf@tux.org>
8 * 2000/10/26 Debacker Xavier (debackex@esiee.fr)
9 * implemented the psaux and controlled the mouse scancode based on pc_keyb.c
10 * Marteau Thomas (marteaut@esiee.fr)
13 * 2001/12/17 Marteau Thomas (marteaut@esiee.fr)
14 * get nice initialisation procedure
17 #include <linux/config.h>
19 #include <linux/types.h>
20 #include <linux/ptrace.h> /* interrupt.h wants struct pt_regs defined */
21 #include <linux/interrupt.h>
22 #include <linux/sched.h> /* for request_irq/free_irq */
23 #include <linux/ioport.h>
24 #include <linux/kernel.h>
25 #include <linux/wait.h>
26 #include <linux/delay.h>
27 #include <linux/errno.h>
28 #include <linux/init.h>
29 #include <linux/module.h>
30 #include <linux/pc_keyb.h>
31 #include <linux/kbd_kern.h>
34 #include <linux/miscdevice.h>
35 #include <linux/slab.h>
36 #include <linux/random.h>
37 #include <linux/spinlock.h>
38 #include <linux/smp_lock.h>
39 #include <linux/poll.h>
41 #include <asm/hardware.h>
42 #include <asm/keyboard.h>
44 #include <asm/uaccess.h>
46 /* HP specific LASI PS/2 keyboard and psaux constants */
47 #define AUX_REPLY_ACK 0xFA /* Command byte ACK. */
48 #define AUX_RESEND 0xFE /* Sent by the keyb. Asking for resending the last command. */
49 #define AUX_RECONNECT 0xAA /* scancode when ps2 device is plugged (back) in */
51 #define LASI_PSAUX_OFFSET 0x0100 /* offset from keyboard to psaux port */
53 #define LASI_ID 0x00 /* ID and reset port offsets */
54 #define LASI_RESET 0x00
55 #define LASI_RCVDATA 0x04 /* receive and transmit port offsets */
56 #define LASI_XMTDATA 0x04
57 #define LASI_CONTROL 0x08 /* see: control register bits */
58 #define LASI_STATUS 0x0C /* see: status register bits */
60 /* control register bits */
61 #define LASI_CTRL_ENBL 0x01 /* enable interface */
62 #define LASI_CTRL_LPBXR 0x02 /* loopback operation */
63 #define LASI_CTRL_DIAG 0x20 /* directly control clock/data line */
64 #define LASI_CTRL_DATDIR 0x40 /* data line direct control */
65 #define LASI_CTRL_CLKDIR 0x80 /* clock line direct control */
67 /* status register bits */
68 #define LASI_STAT_RBNE 0x01
69 #define LASI_STAT_TBNE 0x02
70 #define LASI_STAT_TERR 0x04
71 #define LASI_STAT_PERR 0x08
72 #define LASI_STAT_CMPINTR 0x10
73 #define LASI_STAT_DATSHD 0x40
74 #define LASI_STAT_CLKSHD 0x80
76 static spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED;
77 static unsigned long lasikbd_hpa;
79 static volatile int cmd_status;
81 static inline u8 read_input(unsigned long hpa)
83 return gsc_readb(hpa+LASI_RCVDATA);
86 static inline u8 read_control(unsigned long hpa)
88 return gsc_readb(hpa+LASI_CONTROL);
91 static inline void write_control(u8 val, unsigned long hpa)
93 gsc_writeb(val, hpa+LASI_CONTROL);
96 static inline u8 read_status(unsigned long hpa)
98 return gsc_readb(hpa+LASI_STATUS);
101 /* XXX should this grab the spinlock? */
103 static int write_output(u8 val, unsigned long hpa)
107 while (read_status(hpa) & LASI_STAT_TBNE) {
113 gsc_writeb(val, hpa+LASI_XMTDATA);
118 /* XXX should this grab the spinlock? */
120 static u8 wait_input(unsigned long hpa)
124 while (!(read_status(hpa) & LASI_STAT_RBNE)) {
130 return read_input(hpa);
133 /* This function is the PA-RISC adaptation of i386 source */
135 static inline int aux_write_ack(u8 val)
137 return write_output(val, lasikbd_hpa+LASI_PSAUX_OFFSET);
140 /* This is wrong, should do something like the pc driver, which sends
141 * the command up to 3 times at 1 second intervals, checking once
142 * per millisecond for an acknowledge.
145 static void lasikbd_leds(unsigned char leds)
153 while (cmd_status!=0 && --loop > 0) {
154 write_output(KBD_CMD_SET_LEDS, lasikbd_hpa);
159 while (cmd_status!=0 && --loop > 0) {
160 write_output(leds, lasikbd_hpa);
165 while (cmd_status!=0 && --loop > 0) {
166 write_output(KBD_CMD_ENABLE, lasikbd_hpa);
170 printk("lasikbd_leds: timeout\n");
174 /* this might become useful again at some point. not now -prumpf */
175 int lasi_ps2_test(void *hpa)
180 control = read_control(hpa);
181 write_control(control | LASI_CTRL_LPBXR | LASI_CTRL_ENBL, hpa);
183 for (i=0; i<256; i++) {
184 write_output(i, hpa);
186 while (!(read_status(hpa) & LASI_STAT_RBNE))
194 write_control(control, hpa);
200 static int init_keyb(unsigned long hpa)
205 spin_lock_irqsave(&kbd_controller_lock, flags);
207 if (write_output(KBD_CMD_SET_LEDS, hpa) &&
208 wait_input(hpa) == AUX_REPLY_ACK &&
209 write_output(0, hpa) &&
210 wait_input(hpa) == AUX_REPLY_ACK &&
211 write_output(KBD_CMD_ENABLE, hpa) &&
212 wait_input(hpa) == AUX_REPLY_ACK)
215 spin_unlock_irqrestore(&kbd_controller_lock, flags);
221 static void __init lasi_ps2_reset(unsigned long hpa)
225 /* reset the interface */
226 gsc_writeb(0xff, hpa+LASI_RESET);
227 gsc_writeb(0x0 , hpa+LASI_RESET);
230 control = read_control(hpa);
231 write_control(control | LASI_CTRL_ENBL, hpa);
234 /* Greatly inspired by pc_keyb.c */
237 * Wait for keyboard controller input buffer to drain.
239 * Don't use 'jiffies' so that we don't depend on
242 * Quote from PS/2 System Reference Manual:
244 * "Address hex 0060 and address hex 0064 should be written only when
245 * the input-buffer-full bit and output-buffer-full bit in the
246 * Controller Status register are set 0."
248 #ifdef CONFIG_PSMOUSE
250 static struct aux_queue *queue;
251 static unsigned char mouse_reply_expected;
252 static int aux_count;
254 static int fasync_aux(int fd, struct file *filp, int on)
258 retval = fasync_helper(fd, filp, on, &queue->fasync);
267 static inline void handle_mouse_scancode(unsigned char scancode)
269 if (mouse_reply_expected) {
270 if (scancode == AUX_REPLY_ACK) {
271 mouse_reply_expected--;
274 mouse_reply_expected = 0;
276 else if (scancode == AUX_RECONNECT) {
277 queue->head = queue->tail = 0; /* Flush input queue */
281 add_mouse_randomness(scancode);
283 int head = queue->head;
285 queue->buf[head] = scancode;
286 head = (head + 1) & (AUX_BUF_SIZE-1);
288 if (head != queue->tail) {
290 kill_fasync(&queue->fasync, SIGIO, POLL_IN);
291 wake_up_interruptible(&queue->proc_list);
296 static inline int queue_empty(void)
298 return queue->head == queue->tail;
301 static unsigned char get_from_queue(void)
303 unsigned char result;
306 spin_lock_irqsave(&kbd_controller_lock, flags);
307 result = queue->buf[queue->tail];
308 queue->tail = (queue->tail + 1) & (AUX_BUF_SIZE-1);
309 spin_unlock_irqrestore(&kbd_controller_lock, flags);
316 * Write to the aux device.
319 static ssize_t write_aux(struct file * file, const char * buffer,
320 size_t count, loff_t *ppos)
328 count = 32; /* Limit to 32 bytes. */
331 get_user(c, buffer++);
337 file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
346 static ssize_t read_aux(struct file * file, char * buffer,
347 size_t count, loff_t *ppos)
349 DECLARE_WAITQUEUE(wait, current);
354 if (file->f_flags & O_NONBLOCK)
356 add_wait_queue(&queue->proc_list, &wait);
358 set_current_state(TASK_INTERRUPTIBLE);
359 if (queue_empty() && !signal_pending(current)) {
363 current->state = TASK_RUNNING;
364 remove_wait_queue(&queue->proc_list, &wait);
366 while (i > 0 && !queue_empty()) {
367 c = get_from_queue();
368 put_user(c, buffer++);
372 file->f_dentry->d_inode->i_atime = CURRENT_TIME;
375 if (signal_pending(current))
381 static int open_aux(struct inode * inode, struct file * file)
386 queue->head = queue->tail = 0; /* Flush input queue */
388 aux_write_ack(AUX_ENABLE_DEV); /* Enable aux device */
394 /* No kernel lock held - fine */
395 static unsigned int aux_poll(struct file *file, poll_table * wait)
398 poll_wait(file, &queue->proc_list, wait);
400 return POLLIN | POLLRDNORM;
405 static int release_aux(struct inode * inode, struct file * file)
408 fasync_aux(-1, file, 0);
417 static struct file_operations psaux_fops = {
422 release: release_aux,
426 static struct miscdevice psaux_mouse = {
427 minor: PSMOUSE_MINOR,
432 #endif /* CONFIG_PSMOUSE */
435 /* This function is looking at the PS2 controller and empty the two buffers */
437 static u8 handle_lasikbd_event(unsigned long hpa)
439 u8 status_keyb,status_mouse,scancode,id;
440 extern void handle_at_scancode(int); /* in drivers/char/keyb_at.c */
442 /* Mask to get the base address of the PS/2 controller */
443 id = gsc_readb(hpa+LASI_ID) & 0x0f;
446 hpa -= LASI_PSAUX_OFFSET;
448 status_keyb = read_status(hpa);
449 status_mouse = read_status(hpa+LASI_PSAUX_OFFSET);
451 while ((status_keyb|status_mouse) & LASI_STAT_RBNE){
453 while (status_keyb & LASI_STAT_RBNE) {
455 scancode = read_input(hpa);
457 /* XXX don't know if this is a valid fix, but filtering
458 * 0xfa avoids 'unknown scancode' errors on, eg, capslock
462 if (scancode == AUX_REPLY_ACK)
465 else if (scancode == AUX_RESEND)
468 handle_at_scancode(scancode);
470 status_keyb =read_status(hpa);
473 #ifdef CONFIG_PSMOUSE
474 while (status_mouse & LASI_STAT_RBNE) {
475 scancode = read_input(hpa+LASI_PSAUX_OFFSET);
476 handle_mouse_scancode(scancode);
477 status_mouse = read_status(hpa+LASI_PSAUX_OFFSET);
479 status_mouse = read_status(hpa+LASI_PSAUX_OFFSET);
480 #endif /* CONFIG_PSMOUSE */
481 status_keyb = read_status(hpa);
484 tasklet_schedule(&keyboard_tasklet);
485 return (status_keyb|status_mouse);
488 extern struct pt_regs *kbd_pt_regs;
490 static void lasikbd_interrupt(int irq, void *dev, struct pt_regs *regs)
493 handle_lasikbd_event((unsigned long) dev);
496 extern int pckbd_translate(unsigned char, unsigned char *, char);
497 extern int pckbd_setkeycode(unsigned int, unsigned int);
498 extern int pckbd_getkeycode(unsigned int);
500 static struct kbd_ops gsc_ps2_kbd_ops = {
501 setkeycode: pckbd_setkeycode,
502 getkeycode: pckbd_getkeycode,
503 translate: pckbd_translate,
505 #ifdef CONFIG_MAGIC_SYSRQ
507 sysrq_xlate: hp_ps2kbd_sysrq_xlate,
515 * remove this function and the call in hil_kbd.c
516 * if hp_psaux.c/hp_keyb.c is converted to the input layer... */
517 int register_ps2_keybfuncs(void)
519 gsc_ps2_kbd_ops.leds = NULL;
520 register_kbd_ops(&gsc_ps2_kbd_ops);
522 EXPORT_SYMBOL(register_ps2_keybfuncs);
527 lasi_ps2_register(struct parisc_device *dev)
529 unsigned long hpa = dev->hpa;
531 int device_found = 0;
534 id = gsc_readb(hpa+LASI_ID) & 0x0f;
539 lasikbd_hpa = hpa; /* save "hpa" for lasikbd_leds() */
545 printk(KERN_WARNING "%s: Unknown PS/2 port (id=%d) - ignored.\n",
550 /* reset the PS/2 port */
555 device_found = init_keyb(hpa);
556 if (device_found) register_kbd_ops(&gsc_ps2_kbd_ops);
559 #ifdef CONFIG_PSMOUSE
560 queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL);
564 memset(queue, 0, sizeof(*queue));
565 queue->head = queue->tail = 0;
566 init_waitqueue_head(&queue->proc_list);
568 misc_register(&psaux_mouse);
570 aux_write_ack(AUX_ENABLE_DEV);
571 /* try it a second time, this will give status if the device is
573 device_found = aux_write_ack(AUX_ENABLE_DEV);
576 /* return without printing any unnecessary and misleading info */
582 /* Here we claim only if we have a device attached */
583 /* allocate the irq and memory region for that device */
587 if (request_irq(dev->irq, lasikbd_interrupt, 0, name, (void *)hpa))
590 if (!request_mem_region(hpa, LASI_STATUS + 4, name))
594 printk(KERN_INFO "PS/2 %s port at 0x%08lx (irq %d) found, "
595 "%sdevice attached.\n",
596 name, hpa, dev->irq, device_found ? "":"no ");
601 static struct parisc_device_id lasi_psaux_tbl[] = {
602 { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00084 },
603 { 0, } /* 0 terminated list */
606 MODULE_DEVICE_TABLE(parisc, lasi_psaux_tbl);
608 static struct parisc_driver lasi_psaux_driver = {
610 id_table: lasi_psaux_tbl,
611 probe: lasi_ps2_register,
614 static int __init gsc_ps2_init(void)
616 return register_parisc_driver(&lasi_psaux_driver);
619 module_init(gsc_ps2_init);