root/drivers/char/atixlmouse.c

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

DEFINITIONS

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

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

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