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

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