blob: e7f4a7ba4fef9641aa6fca350f9c3d4f8603009a [file] [log] [blame]
/*
* Amiga Mouse Driver for Linux 68k by Michael Rausch
* based upon:
*
* Logitech Bus Mouse Driver for Linux
* by James Banks
*
* Mods by Matthew Dillon
* calls verify_area()
* tracks better when X is busy or paging
*
* Heavily modified by David Giller
* changed from queue- to counter- driven
* hacked out a (probably incorrect) mouse_poll
*
* Modified again by Nathan Laredo to interface with
* 0.96c-pl1 IRQ handling changes (13JUL92)
* didn't bother touching poll code.
*
* Modified the poll() code blindly to conform to the VFS
* requirements. 92.07.14 - Linus. Somebody should test it out.
*
* Modified by Johan Myreen to make room for other mice (9AUG92)
* removed assignment chr_fops[10] = &mouse_fops; see mouse.c
* renamed mouse_fops => bus_mouse_fops, made bus_mouse_fops public.
* renamed this file mouse.c => busmouse.c
*
* Modified for use in the 1.3 kernels by Jes Sorensen.
*
* Moved the isr-allocation to the mouse_{open,close} calls, as there
* is no reason to service the mouse in the vertical blank isr if
* the mouse is not in use. Jes Sorensen
*
* Converted to use new generic busmouse code. 5 Apr 1998
* Russell King <rmk@arm.uk.linux.org>
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/signal.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/random.h>
#include <linux/poll.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/logibusmouse.h>
#include <asm/setup.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/amigahw.h>
#include <asm/amigaints.h>
#include "busmouse.h"
#if AMIGA_OLD_INT
#define AMI_MSE_INT_ON() mouseint_allowed = 1
#define AMI_MSE_INT_OFF() mouseint_allowed = 0
static int mouseint_allowed;
#endif
static int msedev;
static void mouse_interrupt(int irq, void *dummy, struct pt_regs *fp)
{
static int lastx=0, lasty=0;
int dx, dy;
int nx, ny;
unsigned char buttons;
unsigned short joy0dat, potgor;
#if AMIGA_OLD_INT
if(!mouseint_allowed)
return;
AMI_MSE_INT_OFF();
#endif
/*
* This routine assumes, just like Kickstart, that the mouse
* has not moved more than 127 ticks since last VBL.
*/
joy0dat = custom.joy0dat;
nx = joy0dat & 0xff;
ny = joy0dat >> 8;
dx = nx - lastx;
if (dx < - 127)
dx = (256 + nx) - lastx;
if (dx > 127)
dx = (nx - 256) - lastx;
dy = ny - lasty;
if (dy < - 127)
dy = (256 + ny) - lasty;
if (dy > 127)
dy = (ny - 256) - lasty;
lastx = nx;
lasty = ny;
#if 0
dx = -lastdx;
dx += (lastdx = joy0dat & 0xff);
if (dx < -127)
dx = -255-dx; /* underrun */
else
if (dx > 127)
dx = 255-dx; /* overflow */
dy = -lastdy;
dy += (lastdy = joy0dat >> 8);
if (dy < -127)
dy = -255-dy;
else
if (dy > 127)
dy = 255-dy;
#endif
potgor = custom.potgor;
buttons = (ciaa.pra & 0x40 ? 4 : 0) | /* left button; note that the bits are low-active, as are the expected results -> double negation */
#if 1
(potgor & 0x0100 ? 2 : 0) | /* middle button; emulation goes here */
#endif
(potgor & 0x0400 ? 1 : 0); /* right button */
busmouse_add_movementbuttons(msedev, dx, -dy, buttons);
#if AMIGA_OLD_INT
AMI_MSE_INT_ON();
#endif
}
/*
* close access to the mouse
*/
static int release_mouse(struct inode * inode, struct file * file)
{
free_irq(IRQ_AMIGA_VERTB, mouse_interrupt);
#if AMIGA_OLD_INT
AMI_MSE_INT_OFF();
#endif
return 0;
}
/*
* open access to the mouse, currently only one open is
* allowed.
*/
static int open_mouse(struct inode * inode, struct file * file)
{
/*
* use VBL to poll mouse deltas
*/
if(request_irq(IRQ_AMIGA_VERTB, mouse_interrupt, 0,
"Amiga mouse", mouse_interrupt)) {
printk(KERN_INFO "Installing Amiga mouse failed.\n");
return -EIO;
}
#if AMIGA_OLD_INT
AMI_MSE_INT_ON();
#endif
return 0;
}
static struct busmouse amigamouse = {
AMIGAMOUSE_MINOR, "amigamouse", THIS_MODULE, open_mouse, release_mouse, 7
};
static int __init amiga_mouse_init(void)
{
if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_MOUSE))
return -ENODEV;
if (!request_mem_region(CUSTOM_PHYSADDR+10, 2, "amigamouse [Denise]"))
return -EBUSY;
custom.joytest = 0; /* reset counters */
#if AMIGA_OLD_INT
AMI_MSE_INT_OFF();
#endif
msedev = register_busmouse(&amigamouse);
if (msedev < 0)
printk(KERN_WARNING "Unable to install Amiga mouse driver.\n");
else
printk(KERN_INFO "Amiga mouse installed.\n");
return msedev < 0 ? msedev : 0;
}
static void __exit amiga_mouse_exit(void)
{
unregister_busmouse(msedev);
release_mem_region(CUSTOM_PHYSADDR+10, 2);
}
module_init(amiga_mouse_init);
module_exit(amiga_mouse_exit);
MODULE_LICENSE("GPL");