* [parisc-linux] PS2 Mouse support
@ 2001-05-11 1:25 Thomas Marteau
0 siblings, 0 replies; only message in thread
From: Thomas Marteau @ 2001-05-11 1:25 UTC (permalink / raw)
To: parisc-linux@parisc-linux.org
[-- Attachment #1: Type: text/plain, Size: 381 bytes --]
Hi all,
I finally released my patch in order to get the PS2 mouse support. It
is working with GPM if you run STI-console with the Deller's frambuffer
available at ftp://people.redhat.com/hdeller/parisc_stifb
This patch can be downloaded from our website
http://www.esiee.fr/puffin
Feedback is always appreciated, Thomas
ESIEE Team
PS: If someone want to commit it, please do!
[-- Attachment #2: mouse.patch --]
[-- Type: text/plain, Size: 14398 bytes --]
diff -Nru linuxbf/drivers/char/hp_keyb.h linux/drivers/char/hp_keyb.h
--- linuxbf/drivers/char/hp_keyb.h Thu Jan 1 01:00:00 1970
+++ linux/drivers/char/hp_keyb.h Fri May 11 02:10:41 2001
@@ -0,0 +1,60 @@
+/*
+ * LASI PS/2 keyboard/psaux header for HP-PARISC workstations
+ *
+ * Copyright 2001 Marteau Thomas <marteaut@esiee.fr>
+ *
+ * This file contains all the data needed by hp_keyb.c and hp_psaux.c
+ *
+ * 2001/05/10 Try to compact the code in the two files
+ *
+ */
+
+/* These defines are not used! */
+#define KBD_ECHO 0xEE /* in/out */
+#define KBD_DEFAULT 0xF6 /* out */
+#define KBD_DIAGFAIL 0xFD /* in */
+
+/* Only in hp_keyb.c */
+#define KBD_BREAK 0xF0 /* in */
+
+/* Standard mouse behaviour parameters */
+
+#define AUX_REPLY_ACK 0xFA /* Command byte ACK. */
+#define AUX_RECONNECT 0xAA /* scancode when ps2 device is plugged (back) in */
+
+/* PA-RISC define */
+#define LASI_OFFSET 0x0100
+
+#define LASI_ID 0x00
+#define LASI_RESET 0x00
+#define LASI_RCVDATA 0x04
+#define LASI_XMTDATA 0x04
+#define LASI_CONTROL 0x08
+#define LASI_STATUS 0x0C
+
+/* Control register bits */
+
+#define LASI_CTRL_ENBL 0x01 /* enable interface */
+#define LASI_CTRL_LPBXR 0x02 /* loopback operation */
+#define LASI_CTRL_DIAG 0x20 /* directly control clock/data line */
+#define LASI_CTRL_DATDIR 0x40 /* data line direct control */
+#define LASI_CTRL_CLKDIR 0x80 /* clock line direct control */
+
+/* Status register bits */
+
+#define LASI_STAT_RBNE 0x01
+#define LASI_STAT_TBNE 0x02
+#define LASI_STAT_TERR 0x04
+#define LASI_STAT_PERR 0x08
+#define LASI_STAT_CMPINTR 0x10
+#define LASI_STAT_DATSHD 0x40
+#define LASI_STAT_CLKSHD 0x80
+
+
+
+
+
+
+
+
+
diff -Nru linuxbf/drivers/char/hp_psaux.c linux/drivers/char/hp_psaux.c
--- linuxbf/drivers/char/hp_psaux.c Fri May 11 02:09:08 2001
+++ linux/drivers/char/hp_psaux.c Fri May 11 02:10:41 2001
@@ -9,7 +9,9 @@
* Marteau Thomas (marteaut@esiee.fr)
* Djoudi Malek (djoudim@esiee.fr)
* fixed leds control
+ * implemented the psaux and controlled the mouse scancode
*/
+#include <linux/config.h>
#include <asm/hardware.h>
#include <asm/keyboard.h>
@@ -17,58 +19,40 @@
#include <linux/types.h>
#include <linux/ptrace.h> /* interrupt.h wants struct pt_regs defined */
+#include <linux/interrupt.h>
#include <linux/sched.h> /* for request_irq/free_irq */
#include <linux/ioport.h>
#include <linux/kernel.h>
-#include <linux/interrupt.h>
#include <linux/wait.h>
+#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/pc_keyb.h>
#include <linux/kbd_kern.h>
+/* mouse include */
+#include <linux/miscdevice.h>
+#include <linux/malloc.h>
+#include <linux/random.h>
+#include <linux/spinlock.h>
+#include <linux/smp_lock.h>
+#include <asm/uaccess.h>
+#include <linux/poll.h>
+
+/* HP include */
+#include "hp_keyb.h"
static struct hp_device *lasi_psaux_keyb;
static void *lasikbd_hpa;
+static void *lasips2_hpa;
-
-#define KBD_BAT 0xaa /* in */
-#define KBD_SETLEDS 0xed /* out */
-#define KBD_ECHO 0xee /* in/out */
-#define KBD_BREAK 0xf0 /* in */
-#define KBD_TYPRATEDLY 0xf3 /* out */
-#define KBD_SCANENABLE 0xf4 /* out */
-#define KBD_DEFDISABLE 0xf5 /* out */
-#define KBD_DEFAULT 0xf6 /* out */
-#define KBD_ACK 0xfa /* in */
-#define KBD_DIAGFAIL 0xfd /* in */
-#define KBD_RESEND 0xfe /* in/out */
-#define KBD_RESET 0xff /* out */
-
-#define LASI_ID 0x00
-#define LASI_RESET 0x00
-#define LASI_RCVDATA 0x04
-#define LASI_XMTDATA 0x04
-#define LASI_CONTROL 0x08
-#define LASI_STATUS 0x0c
-
-/* Control register bits */
-
-#define LASI_CTRL_ENBL 0x01 /* enable interface */
-#define LASI_CTRL_LPBXR 0x02 /* loopback operation */
-#define LASI_CTRL_DIAG 0x20 /* directly control clock/data line */
-#define LASI_CTRL_DATDIR 0x40 /* data line direct control */
-#define LASI_CTRL_CLKDIR 0x80 /* clock line direct control */
-
-/* Status register bits */
-
-#define LASI_STAT_RBNE 0x01
-#define LASI_STAT_TBNE 0x02
-#define LASI_STAT_TERR 0x04
-#define LASI_STAT_PERR 0x08
-#define LASI_STAT_CMPINTR 0x10
-#define LASI_STAT_DATSHD 0x40
-#define LASI_STAT_CLKSHD 0x80
+#ifdef CONFIG_PSMOUSE
+/* mouse section */
+static unsigned char mouse_reply_expected;
+static struct aux_queue *queue; /* Mouse data buffer. */
+static int aux_count;
+static spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED;
+#endif
static inline u8 read_input(void *hpa)
@@ -94,7 +78,6 @@
static void write_output(u8 val, void *hpa)
{
int wait = 0;
-
while (read_status(hpa) & LASI_STAT_TBNE) {
wait++;
if (wait>10000) {
@@ -111,12 +94,19 @@
return;
}
+/* This function is the PA-RISC adaptation of i386 source */
+
+static void aux_write_ack(u8 val)
+{
+ write_output(val,lasikbd_hpa+LASI_OFFSET);
+}
+
static void lasikbd_leds(unsigned char leds)
{
- write_output(KBD_SETLEDS, lasikbd_hpa);
+ write_output(KBD_CMD_SET_LEDS, lasikbd_hpa);
write_output(leds, lasikbd_hpa);
- write_output(KBD_SCANENABLE, lasikbd_hpa);
+ write_output(KBD_CMD_ENABLE, lasikbd_hpa);
#if 0
printk("%s(%d)\n", __FUNCTION__, leds);
#endif
@@ -149,7 +139,7 @@
}
#endif
-int lasi_ps2_reset(void *hpa)
+int lasi_ps2_reset(void *hpa,int id)
{
u8 control;
@@ -161,6 +151,14 @@
control = read_control(hpa);
write_control(control | LASI_CTRL_ENBL, hpa);
+ /* initializes the leds at the default state */
+ if (id==0){
+ write_output(KBD_CMD_SET_LEDS, hpa);
+ write_output(0, hpa);
+ write_output(KBD_CMD_ENABLE, hpa);
+ }
+
+
return 0;
}
@@ -171,34 +169,248 @@
++inited;
}
-static u8 handle_lasikbd_event(void *hpa)
+
+/* Greatly inspired by pc_keyb.c */
+
+/*
+ * Wait for keyboard controller input buffer to drain.
+ *
+ * Don't use 'jiffies' so that we don't depend on
+ * interrupts..
+ *
+ * Quote from PS/2 System Reference Manual:
+ *
+ * "Address hex 0060 and address hex 0064 should be written only when
+ * the input-buffer-full bit and output-buffer-full bit in the
+ * Controller Status register are set 0."
+ */
+#ifdef CONFIG_PSMOUSE
+
+static int fasync_aux(int fd, struct file *filp, int on)
+{
+
+ int retval;
+
+ retval = fasync_helper(fd, filp, on, &queue->fasync);
+ if (retval < 0)
+ return retval;
+
+ return 0;
+}
+
+
+static inline void handle_mouse_scancode(unsigned char scancode)
+{
+
+ if (mouse_reply_expected) {
+ if (scancode == AUX_REPLY_ACK) {
+ mouse_reply_expected--;
+ return;
+ }
+ mouse_reply_expected = 0;
+ }
+ else if(scancode == AUX_RECONNECT){
+ queue->head = queue->tail = 0; /* Flush input queue */
+ return;
+ }
+
+ add_mouse_randomness(scancode);
+ if (aux_count) {
+ int head = queue->head;
+
+ queue->buf[head] = scancode;
+ head = (head + 1) & (AUX_BUF_SIZE-1);
+
+ if (head != queue->tail) {
+ queue->head = head;
+ kill_fasync(&queue->fasync, SIGIO, POLL_IN);
+ wake_up_interruptible(&queue->proc_list);
+ }
+ }
+}
+
+static inline int queue_empty(void)
+{
+ return queue->head == queue->tail;
+}
+
+static unsigned char get_from_queue(void)
{
- u8 status;
- extern void handle_at_scancode(int); /* in drivers/char/keyb_at.c */
+ unsigned char result;
+ unsigned long flags;
- while ((status = read_status(hpa)) & LASI_STAT_RBNE) {
- u8 scancode;
+ spin_lock_irqsave(&kbd_controller_lock, flags);
+ result = queue->buf[queue->tail];
+ queue->tail = (queue->tail + 1) & (AUX_BUF_SIZE-1);
+ spin_unlock_irqrestore(&kbd_controller_lock, flags);
+ return result;
+}
+
+
+/*
+ * Write to the aux device.
+ */
- scancode = read_input(hpa);
+static ssize_t write_aux(struct file * file, const char * buffer,
+ size_t count, loff_t *ppos)
+{
+ ssize_t retval = 0;
+
+ if (count) {
+ ssize_t written = 0;
- if (inited)
- handle_at_scancode(scancode);
+ if (count > 32)
+ count = 32; /* Limit to 32 bytes. */
+ do {
+ char c;
+ get_user(c, buffer++);
+ written++;
+ } while (--count);
+ retval = -EIO;
+ if (written) {
+ retval = written;
+ file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
+ }
}
- tasklet_schedule(&keyboard_tasklet);
+ return retval;
+}
- return status;
+
+
+static ssize_t read_aux(struct file * file, char * buffer,
+ size_t count, loff_t *ppos)
+{
+ DECLARE_WAITQUEUE(wait, current);
+ ssize_t i = count;
+ unsigned char c;
+
+ if (queue_empty()) {
+ if (file->f_flags & O_NONBLOCK)
+ return -EAGAIN;
+ add_wait_queue(&queue->proc_list, &wait);
+repeat:
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (queue_empty() && !signal_pending(current)) {
+ schedule();
+ goto repeat;
+ }
+ current->state = TASK_RUNNING;
+ remove_wait_queue(&queue->proc_list, &wait);
+ }
+ while (i > 0 && !queue_empty()) {
+ c = get_from_queue();
+ put_user(c, buffer++);
+ i--;
+ }
+ if (count-i) {
+ file->f_dentry->d_inode->i_atime = CURRENT_TIME;
+ return count-i;
+ }
+ if (signal_pending(current))
+ return -ERESTARTSYS;
+ return 0;
}
+
+
+static int open_aux(struct inode * inode, struct file * file)
+{
+ if (aux_count++) {
+ return 0;
+ }
+ queue->head = queue->tail = 0; /* Flush input queue */
+ aux_count =1;
+
+ aux_write_ack(AUX_ENABLE_DEV); /* Enable aux device */
+
+ return 0;
+}
+
+
+/* No kernel lock held - fine */
+static unsigned int aux_poll(struct file *file, poll_table * wait)
+{
+
+ poll_wait(file, &queue->proc_list, wait);
+ if (!queue_empty())
+ return POLLIN | POLLRDNORM;
+ return 0;
+}
+
+
+static int release_aux(struct inode * inode, struct file * file)
+{
+ lock_kernel();
+ fasync_aux(-1, file, 0);
+ if (--aux_count) {
+ unlock_kernel();
+ return 0;
+ }
+ unlock_kernel();
+ return 0;
+}
+#endif
+
+
+static u8 handle_lasikbd_event(void *hpa)
+{
+ u8 status_keyb,status_mouse,scancode,id;
+ extern void handle_at_scancode(int); /* in drivers/char/keyb_at.c */
+
+ /* Mask to get the base address of the PS/2 controller */
+
+ id = gsc_readb(hpa+LASI_ID) & 0x0f;
+
+ if (id==1)
+ hpa=hpa-LASI_OFFSET;
+ lasikbd_hpa=hpa;
+
+
+ status_keyb = read_status(hpa);
+ status_mouse = read_status(hpa+LASI_OFFSET);
+
+ while ((status_keyb|status_mouse) & LASI_STAT_RBNE){
+
+ while (status_keyb & LASI_STAT_RBNE) {
+
+ scancode = read_input(hpa);
+
+ if (inited)
+ {
+ handle_at_scancode(scancode);
+ }
+
+ status_keyb =read_status(hpa);
+ }
+
+#ifdef CONFIG_PSMOUSE
+ while (status_mouse & LASI_STAT_RBNE) {
+
+ scancode = read_input(hpa+LASI_OFFSET);
+ handle_mouse_scancode(scancode);
+ status_mouse=read_status(hpa+LASI_OFFSET);
+ }
+ status_mouse=read_status(hpa+LASI_OFFSET);
+#endif
+ status_keyb =read_status(hpa);
+ }
+
+ tasklet_schedule(&keyboard_tasklet);
+ return (status_keyb|status_mouse);
+}
+
+
extern struct pt_regs *kbd_pt_regs;
static void lasikbd_interrupt(int irq, void *dev, struct pt_regs *regs)
{
- lasikbd_hpa = dev; /* save "hpa" for lasikbd_leds() */
+
+ lasips2_hpa = dev; /* save "hpa" for lasikbd_leds() */
kbd_pt_regs = regs;
- handle_lasikbd_event(lasikbd_hpa);
+ handle_lasikbd_event(lasips2_hpa);
}
@@ -230,6 +442,23 @@
#endif
};
+#ifdef CONFIG_PSMOUSE
+struct file_operations psaux_fops = {
+ read: read_aux,
+ write: write_aux,
+ poll: aux_poll,
+ open: open_aux,
+ release: release_aux,
+ fasync: fasync_aux,
+};
+
+static struct miscdevice psaux_mouse = {
+ PSMOUSE_MINOR, "psaux", &psaux_fops
+};
+#endif
+
+
+
static int __init
lasi_ps2_register(struct hp_device *d, struct pa_iodc_driver *dri)
{
@@ -247,21 +476,27 @@
name = "psaux"; /* "mouse" */;
break;
default:
- printk(KERN_WARNING "unknown PS/2 port %d found! Get famous now by reporting this to parisc-linux@parisc-linux.org!\n", id);
+ printk(KERN_WARNING "unknown PS/2 port %d found! Get famous now by reporting this to parisc-linux@thepuffingroup.com!\n", id);
name = "unknown";
}
- if (id==0) {
- printk("Initializing Lasi PS/2-%s port at 0x%p...\n", name, hpa);
- } else {
- printk("Support for Lasi PS/2-%s not yet available !\n", name); /* FIXME */
- }
+ if (id==0)
+ printk("Initializing Lasi PS/2-%s port at 0x%p...\n", name, hpa);
+#ifdef CONFIG_PSMOUSE
+ else
+ if (id==1)
+ printk("Initializing Lasi PS/2-%s port at 0x%p...\n", name, hpa);
+#endif
+ else
+ printk("Support for Lasi PS/2-%s not yet available !\n", name); /* FIXME */
if (id==0) {
int err;
unsigned int irq;
-
- if ((err = lasi_ps2_reset(hpa)))
+
+ lasikbd_hpa=hpa;
+
+ if ((err = lasi_ps2_reset(hpa,id)))
printk("%s: lasi_ps2_reset() failed!\n", __FUNCTION__);
irq = busdevice_alloc_irq(d);
@@ -270,11 +505,39 @@
request_irq(irq, lasikbd_interrupt, 0, name, hpa);
- request_mem_region((unsigned long)hpa, LASI_STATUS + 4, name);
+ request_region((unsigned long)hpa, LASI_STATUS + 4, name);
register_kbd_ops(&gsc_ps2_kbd_ops);
}
+#ifdef CONFIG_PSMOUSE
+ if (id==1){
+ int err;
+ unsigned int irq;
+
+ if ((err = lasi_ps2_reset(hpa,id)))
+ printk("%s: lasi_ps2_reset() failed!\n", __FUNCTION__);
+
+ irq = busdevice_alloc_irq(d);
+ if (!irq)
+ return -ENODEV;
+
+ request_irq(irq, lasikbd_interrupt, 0, name, hpa);
+
+ request_region((unsigned long)hpa, LASI_STATUS + 4, name);
+
+ misc_register(&psaux_mouse);
+ queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL);
+ memset(queue, 0, sizeof(*queue));
+ queue->head = queue->tail = 0;
+ init_waitqueue_head(&queue->proc_list);
+
+ aux_write_ack(AUX_ENABLE_DEV);
+
+ }
+#endif
+
+
return 0;
}
@@ -290,3 +553,9 @@
register_driver(lasi_psaux_drivers_for);
return 0;
}
+
+
+
+
+
+
diff -Nru linuxbf/drivers/gsc/lasi.c linux/drivers/gsc/lasi.c
--- linuxbf/drivers/gsc/lasi.c Fri May 11 02:09:10 2001
+++ linux/drivers/gsc/lasi.c Fri May 11 02:10:57 2001
@@ -48,7 +48,8 @@
case 0x5000: irq = 26; break; /* RS232 */
case 0x6000: irq = 22; break; /* SCSI */
case 0x7000: irq = 23; break; /* LAN */
- case 0x8000: irq = 5; break; /* PS/2 Keyboard and Mouse */
+ case 0x8000: irq = 5; break; /* PS/2 Keyboard */
+ case 0x8100: irq = 5; break; /* PS/2 Mouse */
case 0xA000: irq = 11; break; /* Floppy Disk Controller */
default: irq = -1; break; /* unknown */
}
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2001-05-11 1:17 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2001-05-11 1:25 [parisc-linux] PS2 Mouse support Thomas Marteau
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.