root/drivers/char/atixlmouse.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mouse_interrupt
  2. fasync_mouse
  3. release_mouse
  4. open_mouse
  5. write_mouse
  6. read_mouse
  7. mouse_select
  8. atixl_busmouse_init
  9. cleanup_module

   1 /*
   2  * ATI XL Bus Mouse Driver for Linux
   3  * by Bob Harris (rth@sparta.com)
   4  *
   5  * Uses VFS interface for linux 0.98 (01OCT92)
   6  *
   7  * Modified by Chris Colohan (colohan@eecg.toronto.edu)
   8  * Modularised 8-Sep-95 Philip Blundell <pjb27@cam.ac.uk>
   9  *
  10  * version 0.3a
  11  */
  12 
  13 #ifdef MODULE
  14 #include <linux/module.h>
  15 #include <linux/version.h>
  16 
  17 char kernel_version[] = UTS_RELEASE;
  18 #define atixl_busmouse_init init_module
  19 #else
  20 #define MOD_INC_USE_COUNT
  21 #define MOD_DEC_USE_COUNT
  22 #endif
  23 
  24 #include <linux/kernel.h>
  25 #include <linux/sched.h>
  26 #include <linux/signal.h>
  27 #include <linux/errno.h>
  28 #include <linux/mouse.h>
  29 
  30 #include <asm/io.h>
  31 #include <asm/segment.h>
  32 #include <asm/system.h>
  33 #include <asm/irq.h>
  34 
  35 #define ATIXL_MOUSE_IRQ         5 /* H/W interrupt # set up on ATIXL board */
  36 #define ATIXL_BUSMOUSE          3 /* Minor device # (mknod c 10 3 /dev/bm) */
  37 
  38 /* ATI XL Inport Busmouse Definitions */
  39 
  40 #define ATIXL_MSE_DATA_PORT             0x23d
  41 #define ATIXL_MSE_SIGNATURE_PORT        0x23e
  42 #define ATIXL_MSE_CONTROL_PORT          0x23c
  43 
  44 #define ATIXL_MSE_READ_BUTTONS          0x00
  45 #define ATIXL_MSE_READ_X                0x01
  46 #define ATIXL_MSE_READ_Y                0x02
  47 
  48 /* Some nice ATI XL macros */
  49 
  50 /* Select IR7, HOLD UPDATES (INT ENABLED), save X,Y */
  51 #define ATIXL_MSE_DISABLE_UPDATE() { outb( 0x07, ATIXL_MSE_CONTROL_PORT ); \
  52         outb( (0x20 | inb( ATIXL_MSE_DATA_PORT )), ATIXL_MSE_DATA_PORT ); }
  53 
  54 /* Select IR7, Enable updates (INT ENABLED) */
  55 #define ATIXL_MSE_ENABLE_UPDATE() { outb( 0x07, ATIXL_MSE_CONTROL_PORT ); \
  56          outb( (0xdf & inb( ATIXL_MSE_DATA_PORT )), ATIXL_MSE_DATA_PORT ); }
  57 
  58 /* Select IR7 - Mode Register, NO INTERRUPTS */
  59 #define ATIXL_MSE_INT_OFF() { outb( 0x07, ATIXL_MSE_CONTROL_PORT ); \
  60         outb( (0xe7 & inb( ATIXL_MSE_DATA_PORT )), ATIXL_MSE_DATA_PORT ); }
  61 
  62 /* Select IR7 - Mode Register, DATA INTERRUPTS ENABLED */
  63 #define ATIXL_MSE_INT_ON() { outb( 0x07, ATIXL_MSE_CONTROL_PORT ); \
  64         outb( (0x08 | inb( ATIXL_MSE_DATA_PORT )), ATIXL_MSE_DATA_PORT ); }
  65 
  66 /* Same general mouse structure */
  67 
  68 static struct mouse_status {
  69         char buttons;
  70         char latch_buttons;
  71         int dx;
  72         int dy;
  73         int present;
  74         int ready;
  75         int active;
  76         struct wait_queue *wait;
  77         struct fasync_struct *fasync;
  78 } mouse;
  79 
  80 void mouse_interrupt(int irq, struct pt_regs * regs)
     /* [previous][next][first][last][top][bottom][index][help] */
  81 {
  82         char dx, dy, buttons;
  83 
  84         ATIXL_MSE_DISABLE_UPDATE(); /* Note that interrupts are still enabled */
  85         outb(ATIXL_MSE_READ_X, ATIXL_MSE_CONTROL_PORT); /* Select IR1 - X movement */
  86         dx = inb( ATIXL_MSE_DATA_PORT);
  87         outb(ATIXL_MSE_READ_Y, ATIXL_MSE_CONTROL_PORT); /* Select IR2 - Y movement */
  88         dy = inb( ATIXL_MSE_DATA_PORT);
  89         outb(ATIXL_MSE_READ_BUTTONS, ATIXL_MSE_CONTROL_PORT); /* Select IR0 - Button Status */
  90         buttons = inb( ATIXL_MSE_DATA_PORT);
  91         if (dx != 0 || dy != 0 || buttons != mouse.latch_buttons) {
  92                 mouse.latch_buttons |= buttons;
  93                 mouse.dx += dx;
  94                 mouse.dy += dy;
  95                 mouse.ready = 1;
  96                 wake_up_interruptible(&mouse.wait);
  97                 if (mouse.fasync)
  98                         kill_fasync(mouse.fasync, SIGIO);
  99         }
 100         ATIXL_MSE_ENABLE_UPDATE();
 101 }
 102 
 103 static int fasync_mouse(struct inode *inode, struct file *filp, int on)
     /* [previous][next][first][last][top][bottom][index][help] */
 104 {
 105         int retval;
 106 
 107         retval = fasync_helper(inode, filp, on, &mouse.fasync);
 108         if (retval < 0)
 109                 return retval;
 110         return 0;
 111 }
 112 
 113 static void release_mouse(struct inode * inode, struct file * file)
     /* [previous][next][first][last][top][bottom][index][help] */
 114 {
 115         fasync_mouse(inode, file, 0);
 116         if (--mouse.active)
 117                 return;
 118         ATIXL_MSE_INT_OFF(); /* Interrupts are really shut down here */
 119         mouse.ready = 0;
 120         free_irq(ATIXL_MOUSE_IRQ);
 121         MOD_DEC_USE_COUNT;
 122 }
 123 
 124 static int open_mouse(struct inode * inode, struct file * file)
     /* [previous][next][first][last][top][bottom][index][help] */
 125 {
 126         if (!mouse.present)
 127                 return -EINVAL;
 128         if (mouse.active++)
 129                 return 0;
 130         if (request_irq(ATIXL_MOUSE_IRQ, mouse_interrupt, 0, "ATIXL mouse")) {
 131                 mouse.active--;
 132                 return -EBUSY;
 133         }
 134         mouse.ready = 0;
 135         mouse.dx = 0;
 136         mouse.dy = 0;
 137         mouse.buttons = mouse.latch_buttons = 0;
 138         ATIXL_MSE_INT_ON(); /* Interrupts are really enabled here */
 139         MOD_INC_USE_COUNT;
 140         return 0;
 141 }
 142 
 143 
 144 static int write_mouse(struct inode * inode, struct file * file, const char * buffer, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 145 {
 146         return -EINVAL;
 147 }
 148 
 149 static int read_mouse(struct inode * inode, struct file * file, char * buffer, int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 150 {
 151         int i;
 152 
 153         if (count < 3)
 154                 return -EINVAL;
 155         if (!mouse.ready)
 156                 return -EAGAIN;
 157         ATIXL_MSE_DISABLE_UPDATE();
 158         /* Allowed interrupts to occur during data gathering - shouldn't hurt */
 159         put_user((char)(~mouse.latch_buttons&7) | 0x80 , buffer);
 160         if (mouse.dx < -127)
 161                 mouse.dx = -127;
 162         if (mouse.dx > 127)
 163                 mouse.dx =  127;
 164         put_user((char)mouse.dx, buffer + 1);
 165         if (mouse.dy < -127)
 166                 mouse.dy = -127;
 167         if (mouse.dy > 127)
 168                 mouse.dy =  127;
 169         put_user((char)-mouse.dy, buffer + 2);
 170         for(i = 3; i < count; i++)
 171                 put_user(0x00, buffer + i);
 172         mouse.dx = 0;
 173         mouse.dy = 0;
 174         mouse.latch_buttons = mouse.buttons;
 175         mouse.ready = 0;
 176         ATIXL_MSE_ENABLE_UPDATE();
 177         return i; /* i data bytes returned */
 178 }
 179 
 180 static int mouse_select(struct inode *inode, struct file *file, int sel_type, select_table * wait)
     /* [previous][next][first][last][top][bottom][index][help] */
 181 {
 182         if (sel_type != SEL_IN)
 183                 return 0;
 184         if (mouse.ready)
 185                 return 1;
 186         select_wait(&mouse.wait,wait);
 187         return 0;
 188 }
 189 
 190 struct file_operations atixl_busmouse_fops = {
 191         NULL,           /* mouse_seek */
 192         read_mouse,
 193         write_mouse,
 194         NULL,           /* mouse_readdir */
 195         mouse_select,   /* mouse_select */
 196         NULL,           /* mouse_ioctl */
 197         NULL,           /* mouse_mmap */
 198         open_mouse,
 199         release_mouse,
 200         NULL,
 201         fasync_mouse,
 202 };
 203 
 204 static struct mouse atixl_mouse = { 
 205         ATIXL_BUSMOUSE, "atixl", &atixl_busmouse_fops
 206 };
 207 
 208 
 209 int atixl_busmouse_init(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 210 {
 211         unsigned char a,b,c;
 212 
 213         a = inb( ATIXL_MSE_SIGNATURE_PORT );    /* Get signature */
 214         b = inb( ATIXL_MSE_SIGNATURE_PORT );
 215         c = inb( ATIXL_MSE_SIGNATURE_PORT );
 216         if (( a != b ) && ( a == c ))
 217                 printk("\nATI Inport ");
 218         else{
 219                 mouse.present = 0;
 220                 return -EIO;
 221         }
 222         outb(0x80, ATIXL_MSE_CONTROL_PORT);     /* Reset the Inport device */
 223         outb(0x07, ATIXL_MSE_CONTROL_PORT);     /* Select Internal Register 7 */
 224         outb(0x0a, ATIXL_MSE_DATA_PORT);        /* Data Interrupts 8+, 1=30hz, 2=50hz, 3=100hz, 4=200hz rate */
 225         mouse.present = 1;
 226         mouse.active = 0;
 227         mouse.ready = 0;
 228         mouse.buttons = mouse.latch_buttons = 0;
 229         mouse.dx = mouse.dy = 0;
 230         mouse.wait = NULL;
 231         printk("Bus mouse detected and installed.\n");
 232         mouse_register(&atixl_mouse);
 233         return 0;
 234 }
 235 
 236 #ifdef MODULE
 237 void cleanup_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 238 {
 239         if (MOD_IN_USE) {
 240                 printk("atixlmouse: in use, remove delayed\n");
 241                 return;
 242         }
 243         mouse_deregister(&atixl_mouse);
 244 }
 245 #endif

/* [previous][next][first][last][top][bottom][index][help] */