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

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