home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.2 / LINUX-1.2 / LINUX-1 / linux / drivers / char / atixlmouse.c next >
Encoding:
C/C++ Source or Header  |  1995-01-16  |  5.2 KB  |  199 lines

  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)
  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)
  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)
  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)
  117. {
  118.     return -EINVAL;
  119. }
  120.  
  121. static int read_mouse(struct inode * inode, struct file * file, char * buffer, int count)
  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)
  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)
  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. }
  199.