From: gt6698a@prism.gatech.EDU (Andrew Hobson) Subject: Microsoft Bus mouse works, sorta Date: 27 Aug 1992 18:41:44 GMT
Greets!
I have an ATI VGA Wonder XL and I have a microsoft mouse plugged in the
bus port. (It is on the VGA card) Rik Faith (faith@cs.unc.edu) has
written a X386 for ATI cards and it works great, I think.
I received mail from Derrick C. Cole <cole@concert.net> when I posted
previously about getting the microsoft bus mouse to work. He mailed
me a patch by Frank ten Wolde (franky@duteca.et.tudelft.nl).
I have modified this patch and the existing mouse.c by
James Banks, David Giller, and Nathan Laredo (Thanks for the help,
Nathan!!!)
I have made modifications to mouse.c so that a microsoft mouse will
work. Essentially, these changes were only to the mouse_interrupt
function and should not have affected anything else. If I run X, then
my mouse will not work, even though I am pretty sure that the mouse
driver works. (I put printk's inside the driver, and I modified the
mouse test program that comes with X for use with a bus mouse and it
works) If I run a program that does an ioperm(port,1,1) for all
four of the port addresses, and then run X, I can use the mouse
until the xterm comes up. Then, as long as I hold down a key
(on the keyboard), the mouse works. If I do not hold down a key,
then move the mouse, and then press a key, the mouse will jump
to a new location, about where it should have moved. (I have no
way of telling exactly where it should have moved.) If I get
rid of the Xterm and Xclock, I still cannot use the mouse,
except by pressing down a key. Pressing a mouse button does not
register, unless the mouse is moved. Using the mouse program that came with X, if I press a button, then new information
is printed on the screen, but is is the same information as before until
I move the mouse.
I guess I need some testers to see if the problem is with the ATI
X or with my code.
I have sent mail to Rik Faith about this, as well, so hopefully this
can be resolved. I would really like to not have to press a key
to use my mouse in X!!
Thanks alot for any help you can give me. I will include copies of my
/usr/src/linux/kernel/chr_drv/mouse.c and
/usr/src/linux/include/linux/mouse.h files. I don't think that I have
changed mouse.h. I can't post a patch because
I am not sure I have the original I have done so many changes!!
Andrew Hobson
/*====================== MOUSE.C =========================*/
/*
* 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
*/
/* Modified to work with microsoft bus mice. Might work, might not */
/* Andrew Hobson gt6698a@prism.gatech.edu 27AUG92 */
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/tty.h>
#include <asm/io.h>
#include <asm/segment.h>
#include <asm/system.h>
#include <asm/irq.h>
#include <linux/errno.h>
#include <linux/signal.h>
#include <linux/mouse.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;
}
#define outp(a,b) outb(b,a);
void mouse_interrupt(void)
{
char dx, dy, buttons;
unsigned int i;
char tmp;
MSE_INT_OFF();
outp(MSE_DATA_PORT, 0x07); /* from MSDOS device driver */
outp(MSE_SIGNATURE_PORT, tmp = (inb(MSE_SIGNATURE_PORT) | 0x20));
/* FTW version 0.2 920614:
* I have seen this in the MSDOS Microsoft Bus Mouse device driver.
* Don't know what its for. It does not seem required as it works
* well as it is!
*/
if (0) {
/* I hope GCC is clever enough to just to remove this code :-) */
(void) inb(MSE_SIGNATURE_PORT);
(void) inb(MSE_SIGNATURE_PORT);
(void) inb(MSE_SIGNATURE_PORT);
outp(MSE_SIGNATURE_PORT, tmp);
}
outp(MSE_DATA_PORT, 0x01); /* from MSDOS device driver */
dx = inb(MSE_SIGNATURE_PORT);
outp(MSE_DATA_PORT, 0x02); /* from MSDOS device driver */
dy = inb(MSE_SIGNATURE_PORT);
outp(MSE_DATA_PORT, 0x00); /* from MSDOS device driver */
buttons = inb(MSE_SIGNATURE_PORT);
outp(MSE_DATA_PORT, 0x07); /* from MSDOS device driver */
outp(MSE_SIGNATURE_PORT, inb(MSE_SIGNATURE_PORT) & 0xDF);
/* FTW version 0.2 920614:
* Ah! The microsoft mouse has its buttons reversed with respect
* to the Logitech Mouse. You certainly get very strange mouse
* behaviour in X with the buttons reversed :-)
*/
buttons = ~buttons;
buttons &= 0x07; /* ignore button state change info */
/* FTW version 0.2 920614
* Another thing: The original code for do_IRQ5 simply returned
* immediately if the event_queue was full. This does not work
* for Microsoft as the mouse requires to be 'flushed.' The behaviour
* in X was that after violent mouse movements it would simply freeze
* up and remained dead until after a system reboot. Hence the
* !queuefull test at this point in the code.
*/
/* FTW version 0.2 920614
* The following outb() instruction probably does nothing for the
* Microsoft Mouse. It is a left over from the Logitech code.
*/
MSE_INT_ON();
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);
}
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,j;
unsigned char tchar;
outb(MSE_CONFIG_BYTE, MSE_CONFIG_PORT);
outb(0x09, MSE_SIGNATURE_PORT);
for (i = 0; i < 100000; i++); /* busy loop */
tchar = inb(MSE_SIGNATURE_PORT);
if (tchar != (0x09)) {
printk("No bus mouse detected.\n");
mouse.present = 0;
return kmem_start;
}
chrdev_fops[10] = &mouse_fops;
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;
}
/* ============================== MOUSE.H ========================== */
/*
* 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
-- Andrew Hobson Internet: gt6698a@prism.gatech.edu "He who joyfully marches to music in rank and file has already earned my contempt. He has been given a large brain by mistake, since for him the spinal cord would fully suffice." -- Albert Einstein