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

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