From: gt7080a@prism.gatech.EDU (Nathan I. Laredo) Subject: New Bus Mouse Driver patches for 96c-patchlevel1 Date: 14 Jul 1992 13:43:08 GMT
Well I managed to make a quick hack at the bus mouse
driver that seems to work with 96c-patch1. The driver
works perfectly with the mouse installed, although the
code that's in select.c seems a little strange.
I've put the diff file on banjo.concert.net but I've
also included it below for anyone without ftp access.
I hope this code makes it into the next kernel.
I just finished making the kernel from the original sources
with this diff applied, so in the unlikely event that something's
wrong, PLEASE let me know. I want this code in the kernel
someday.
Thanks,
Nathan Laredo, laredo@cc.gatech.edu, gt7080a@prism.gatech.edu
One note, to create the mouse device, mknod /dev/mouse c 10 0
(major 10 minor 0 - this is used by other systems as well)
-- m96c-p1.diff:*** 0.96c-p1/kernel/chr_drv/mouse.c Tue Jul 14 09:10:21 1992 --- linux/kernel/chr_drv/mouse.c Mon Jul 13 17:40:33 1992 *************** *** 0 **** --- 1,176 ---- + /* + * Logitech Bus Mouse Driver for Linux + * by James Banks + * + * Heavily modified by David Giller + * changed from queue- to counter- driven + * hacked out a (probably incorrect) mouse_select + * + * Modified again by Nathan Laredo to interface with + * 0.96c-pl1 IRQ handling changes (13JUL92) + * didn't bother touching select code. + * + * version 0.1 + */ + + #include <linux/kernel.h> + #include <linux/sched.h> + #include <linux/mouse.h> + #include <linux/tty.h> + #include <asm/io.h> + #include <asm/segment.h> + #include <asm/system.h> + #include <asm/irq.h> + #include <signal.h> + #include <errno.h> + #include <signal.h> + + struct mouse_status mouse; + + void release_mouse(struct inode * inode, struct file * file) + { + MSE_INT_OFF(); + mouse.active = 0; + mouse.ready = 0; + mouse.inode = NULL; + + free_irq(MOUSE_IRQ); + } + + int open_mouse(struct inode * inode, struct file * file) + { + if (mouse.active) return -EBUSY; + if (!mouse.present) return -EINVAL; + + mouse.active = 1; + mouse.ready = 0; + mouse.inode = inode; + mouse.dx = 0; + mouse.dy = 0; + mouse.buttons = mouse.latch_buttons = 0x80; + + MSE_INT_ON(); + if (request_irq(MOUSE_IRQ, mouse_interrupt)) return -EBUSY; + + return 0; + } + + int write_mouse(struct inode * inode, struct file * file, + char * buffer, int count) + { + return -EINVAL; + } + + int read_mouse(struct inode * inode, struct file * file, + char * buffer, int count) + { + int i; + + if (count < 3) return -EINVAL; + if (!mouse.ready) return -EAGAIN; + + MSE_INT_OFF(); + + put_fs_byte(mouse.latch_buttons | 0x80, buffer); + + if (mouse.dx < -127) mouse.dx = -127; + if (mouse.dx > 127) mouse.dx = 127; + + put_fs_byte((char)mouse.dx, buffer + 1); + + if (mouse.dy < -127) mouse.dy = -127; + if (mouse.dy > 127) mouse.dy = 127; + + put_fs_byte((char) -mouse.dy, buffer + 2); + + for (i = 3; i < count; i++) + put_fs_byte(0x00, buffer + i); + + mouse.dx = 0; + mouse.dy = 0; + mouse.latch_buttons = mouse.buttons; + mouse.ready = 0; + + MSE_INT_ON(); + return i; + } + + void mouse_interrupt(void) + { + char dx, dy, buttons; + + MSE_INT_OFF(); + + outb(MSE_READ_X_LOW, MSE_CONTROL_PORT); + dx = (inb(MSE_DATA_PORT) & 0xf); + + outb(MSE_READ_X_HIGH, MSE_CONTROL_PORT); + dx |= (inb(MSE_DATA_PORT) & 0xf) << 4; + + outb(MSE_READ_Y_LOW, MSE_CONTROL_PORT ); + dy = (inb(MSE_DATA_PORT) & 0xf); + + outb(MSE_READ_Y_HIGH, MSE_CONTROL_PORT); + buttons = inb(MSE_DATA_PORT); + + dy |= (buttons & 0xf) << 4; + buttons = ((buttons >> 5) & 0x07); + + mouse.buttons = buttons; + mouse.latch_buttons |= buttons; + mouse.dx += dx; + mouse.dy += dy; + mouse.ready = 1; + if (mouse.inode && mouse.inode->i_wait) + wake_up(&mouse.inode->i_wait); + + MSE_INT_ON(); + } + + static struct file_operations mouse_fops = { + NULL, /* mouse_seek */ + read_mouse, + write_mouse, + NULL, /* mouse_readdir */ + mouse_select, /* mouse_select */ + NULL, /* mouse_ioctl */ + open_mouse, + release_mouse, + }; + + int mouse_select(struct inode *inode, struct file *file, int which, + select_table *seltable) + { + if (mouse.ready) + return 1; + else + return 0; + } + + long mouse_init(long kmem_start) + { + int i; + + outb(MSE_CONFIG_BYTE, MSE_CONFIG_PORT); + outb(MSE_SIGNATURE_BYTE, MSE_SIGNATURE_PORT); + + for (i = 0; i < 100000; i++); /* busy loop */ + if (inb(MSE_SIGNATURE_PORT) != MSE_SIGNATURE_BYTE) { + printk("No bus mouse detected.\n"); + mouse.present = 0; + return kmem_start; + } + chrdev_fops[10] = &mouse_fops; + outb(MSE_DEFAULT_MODE, MSE_CONFIG_PORT); + + MSE_INT_OFF(); + + mouse.present = 1; + mouse.active = 0; + mouse.ready = 0; + mouse.buttons = mouse.latch_buttons = 0x80; + mouse.dx = 0; + mouse.dy = 0; + printk("Bus mouse detected and installed.\n"); + return kmem_start; + } *** 0.96c-p1/kernel/chr_drv/Makefile Sun Jul 5 00:10:09 1992 --- linux/kernel/chr_drv/Makefile Tue Jul 14 09:07:19 1992 *************** *** 17,23 **** $(CC) $(CFLAGS) -c $< OBJS = tty_io.o console.o keyboard.o serial.o \ ! tty_ioctl.o pty.o lp.o vt.o mem.o chr_drv.a: $(OBJS) $(AR) rcs chr_drv.a $(OBJS) --- 17,23 ---- $(CC) $(CFLAGS) -c $< OBJS = tty_io.o console.o keyboard.o serial.o \ ! tty_ioctl.o pty.o lp.o vt.o mem.o mouse.o chr_drv.a: $(OBJS) $(AR) rcs chr_drv.a $(OBJS) *** 0.96c-p1/kernel/chr_drv/mem.c Sat Jul 4 21:47:52 1992 --- linux/kernel/chr_drv/mem.c Mon Jul 13 17:25:27 1992 *************** *** 246,250 **** --- 246,251 ---- chrdev_fops[1] = &mem_fops; mem_start = tty_init(mem_start); mem_start = lp_init(mem_start); + mem_start = mouse_init(mem_start); return mem_start; } *** 0.96c-p1/include/linux/mouse.h Tue Jul 14 09:10:02 1992 --- linux/include/linux/mouse.h Mon Jul 13 17:37:51 1992 *************** *** 0 **** --- 1,67 ---- + /* + * linux/include/linux/mouse.h: header file for Logitech Bus Mouse driver + * by James Banks + * + * based on information gleamed from various mouse drivers on the net + * + * Heavily modified by David giller (rafetmad@oxy.edu) + * + * Minor modifications for Linux 0.96c-pl1 by Nathan Laredo + * gt7080a@prism.gatech.edu (13JUL92) + * + */ + + #ifndef _MOUSE_H + #define _MOUSE_H + + #define MOUSE_IRQ 5 + + #define MSE_DATA_PORT 0x23c + #define MSE_SIGNATURE_PORT 0x23d + #define MSE_CONTROL_PORT 0x23e + #define MSE_INTERRUPT_PORT 0x23e + #define MSE_CONFIG_PORT 0x23f + + #define MSE_ENABLE_INTERRUPTS 0x00 + #define MSE_DISABLE_INTERRUPTS 0x10 + + #define MSE_READ_X_LOW 0x80 + #define MSE_READ_X_HIGH 0xa0 + #define MSE_READ_Y_LOW 0xc0 + #define MSE_READ_Y_HIGH 0xe0 + + /* Magic number used to check if the mouse exists */ + #define MSE_CONFIG_BYTE 0x91 + #define MSE_DEFAULT_MODE 0x90 + #define MSE_SIGNATURE_BYTE 0xa5 + + /* useful macros */ + + #define MSE_INT_OFF() outb(MSE_DISABLE_INTERRUPTS, MSE_CONTROL_PORT) + #define MSE_INT_ON() outb(MSE_ENABLE_INTERRUPTS, MSE_CONTROL_PORT) + + struct mouse_status + { + char buttons; + char latch_buttons; + int dx; + int dy; + + int present; + int ready; + int active; + + struct inode *inode; + }; + + /* Function Prototypes */ + extern void mouse_interrupt(void); + extern long mouse_init(long); + extern int open_mouse(struct inode *, struct file *); + extern void release_mouse(struct inode *, struct file *); + extern int read_mouse(struct inode *, struct file *, char *, int); + extern int write_mouse(struct inode *, struct file *, char *, int); + extern int mouse_select(struct inode *inode, struct file *file, int which, + select_table *seltable); + #endif + *** 0.96c-p1/fs/select.c Sat Jun 27 13:14:29 1992 --- linux/fs/select.c Mon Jul 13 17:27:15 1992 *************** *** 116,129 **** static int check_in(select_table * wait, struct inode * inode) { struct tty_struct * tty; ! if (tty = get_tty(inode)) ! if (!EMPTY(tty->secondary)) ! return 1; ! else if (tty->link && !tty->link->count) ! return 1; ! else ! add_wait(&tty->secondary->proc_list, wait); else if (inode->i_pipe) if (!PIPE_EMPTY(*inode) || !PIPE_WRITERS(*inode)) return 1; --- 116,140 ---- static int check_in(select_table * wait, struct inode * inode) { struct tty_struct * tty; + int major; ! if (S_ISCHR(inode->i_mode)) ! if (tty = get_tty(inode)) ! if (!EMPTY(tty->secondary)) ! return 1; ! else if (tty->link && !tty->link->count) ! return 1; ! else ! add_wait(&tty->secondary->proc_list, wait); ! else ! { ! major = MAJOR(inode->i_rdev); ! if (chrdev_fops[major]->select) ! if (chrdev_fops[major]->select(inode, NULL, SEL_IN, wait)) ! return 1; ! else ! add_wait(&inode->i_wait, wait); ! } else if (inode->i_pipe) if (!PIPE_EMPTY(*inode) || !PIPE_WRITERS(*inode)) return 1; *************** *** 140,151 **** static int check_out(select_table * wait, struct inode * inode) { struct tty_struct * tty; ! if (tty = get_tty(inode)) ! if (!FULL(tty->write_q)) ! return 1; ! else ! add_wait(&tty->write_q->proc_list, wait); else if (inode->i_pipe) if (!PIPE_FULL(*inode)) return 1; --- 151,173 ---- static int check_out(select_table * wait, struct inode * inode) { struct tty_struct * tty; + int major; ! if (S_ISCHR(inode->i_mode)) ! if (tty = get_tty(inode)) ! if (!FULL(tty->write_q)) ! return 1; ! else ! add_wait(&tty->write_q->proc_list, wait); ! else ! { ! major = MAJOR(inode->i_rdev); ! if (chrdev_fops[major]->select) ! if (chrdev_fops[major]->select(inode, NULL, SEL_OUT, wait)) ! return 1; ! else ! add_wait(&inode->i_wait, wait); ! } else if (inode->i_pipe) if (!PIPE_FULL(*inode)) return 1; *************** *** 162,173 **** static int check_ex(select_table * wait, struct inode * inode) { struct tty_struct * tty; ! if (tty = get_tty(inode)) ! if (!FULL(tty->write_q)) ! return 0; ! else ! return 0; else if (inode->i_pipe) if (!PIPE_READERS(*inode) || !PIPE_WRITERS(*inode)) return 1; --- 184,206 ---- static int check_ex(select_table * wait, struct inode * inode) { struct tty_struct * tty; + int major; ! if (S_ISCHR(inode->i_mode)) ! if (tty = get_tty(inode)) ! if (!FULL(tty->write_q)) ! return 0; ! else ! return 0; ! else ! { ! major = MAJOR(inode->i_rdev); ! if (chrdev_fops[major]->select) ! if (chrdev_fops[major]->select(inode, NULL, SEL_EX, wait)) ! return 1; ! else ! add_wait(&inode->i_wait, wait); ! } else if (inode->i_pipe) if (!PIPE_READERS(*inode) || !PIPE_WRITERS(*inode)) return 1;