home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2620 / lmouse.c next >
Encoding:
C/C++ Source or Header  |  1991-01-29  |  12.1 KB  |  422 lines

  1. #define VPIX
  2.  
  3. #include "sys/param.h"
  4. #include "sys/types.h"
  5. #include "sys/sysmacros.h"
  6. #include "sys/dir.h"
  7. #include "sys/signal.h"
  8. #include "sys/user.h"
  9. #include "sys/errno.h"
  10.  
  11. /* Definitions for Logitech Mouse */
  12.  
  13. /* Base I/O addresses of mouse registers */
  14. #define DATA_REG      0x23c  /* Data          register (read  only) */
  15. #define SIGNATURE_REG 0x23d  /* Signature     register (read/write) */
  16. #define INTERRUPT_REG 0x23e  /* Interrupt     register (read  only) */
  17. #define CONTROL_REG   0x23e  /* Control       register (write only) */
  18. #define CONFIG_REG    0x23f  /* Configuration register (read/write) */
  19.  
  20. /* Definitions of bits in interrupt register. */
  21. #define IRQ5 0x01
  22. #define IRQ4 0x02
  23. #define IRQ3 0x04
  24. #define IRQ2 0x08
  25.  
  26. /* Definitions of bits in control register. */
  27. #define DINT 0x10  /* Disable Interrupts */
  28. #define SHL  0x20  /* Select Hi/Lo (0/1) nibble */
  29. #define SXY  0x40  /* Select X/Y (0/1) counter */
  30. #define HC   0x80  /* Hold Counters (latch counters on 0->1 edge) */
  31.  
  32. /* Magic number needed for configuration register. */
  33. #define CONFIG_BYTE 0x91
  34.  
  35. #define BUT3STAT        0x01
  36. #define BUT2STAT        0x02
  37. #define BUT1STAT        0x04
  38.  
  39. #define BUT3CHNG        0x08
  40. #define BUT2CHNG        0x10
  41. #define BUT1CHNG        0x20
  42. #define MOVEMENT        0x40
  43.  
  44. #define BUTSTATMASK     0x07
  45. #define BUTCHNGMASK     0x38
  46.  
  47. struct mouseinfo
  48. {       unsigned char status;
  49.     char xmotion, ymotion;
  50. };
  51.  
  52. /* Ioctl definitions */
  53. #define MOUSEIOC        ('M'<<8)
  54. #define MOUSEIOCREAD    (MOUSEIOC|60)
  55.  
  56. #ifdef VPIX
  57. #define VPC_MOUSE_READ  MOUSEIOCREAD
  58. #endif /* VPIX */
  59.  
  60. #ifdef VPIX
  61. #include "sys/immu.h"
  62. #include "sys/region.h"
  63. #include "sys/proc.h"
  64. #include "sys/tss.h"
  65. #include "sys/v86.h"
  66. #endif /* VPIX */
  67.  
  68. static char mousepresent;
  69. static char mouseinuse;
  70. static char mousemode;
  71. static char last_buttons;
  72. static char mousestatus;
  73. static int xmotion, ymotion;
  74. #ifdef VPIX
  75. static struct proc *ectproc;
  76. static char rupted;
  77. #endif /* VPIX */
  78.  
  79. #define UPPERLIM    127
  80. #define LOWERLIM   -128
  81. #define ONEBYTE(x) ((x)>UPPERLIM ? UPPERLIM : (x)<LOWERLIM ? LOWERLIM : (x))
  82.  
  83. /*---------------------------------------------------------------------------*/
  84. void logminit()
  85. {
  86.    unsigned char id1, id2, toggles, irq;
  87.    int i;
  88.  
  89.    /* Assume no mouse in system. */
  90.    mouseinuse = mousepresent = 0;
  91.  
  92.    /* Initialize configuration register with the required magic number. */
  93.    outb(CONFIG_REG, CONFIG_BYTE);
  94.  
  95.    /* See if we can store into the signature register.  If not return. */
  96.    outb(SIGNATURE_REG, 0xA5);
  97.    for (i=0; i<1000; i++); /* busy loop */
  98.    id1 = inb(SIGNATURE_REG);
  99.    if (id1 != 0xA5) {
  100.       printf("logminit: SIGNATURE_REG = 0x%x (should equal 0xA5)\n", id1);
  101.       printf("Logitech Bus Mouse not loaded.\n");
  102.       return;
  103.    }
  104.  
  105.    /* See which bits toggle in the interrupt register. */
  106.    outb(CONTROL_REG, 0); /* Make sure interrupts are enabled. */
  107.    id1 = inb(INTERRUPT_REG);
  108. #ifdef DEBUG
  109. printf("logminit:  Initial value of interrupt reg = 0x%x\n", id1);
  110. #endif /* DEBUG */
  111.    toggles = 0;
  112.    for (i=0; i<10000; i++) {
  113.       id2 = inb(INTERRUPT_REG);
  114.       toggles |= id1 ^ id2;
  115.       id1 = id2;
  116.    }
  117.    outb(CONTROL_REG, DINT); /* Disable interrupts just to be safe. */
  118.  
  119.    /* Based upon which bit(s) toggled, determine which IRQ is being used.
  120.       If nothing toggled, then something is wrong so don't set the
  121.       mousepresent flag. */
  122.    if      (toggles & IRQ5)  irq = 5;
  123.    else if (toggles & IRQ2)  irq = 2;
  124.    else if (toggles & IRQ3)  irq = 3;
  125.    else if (toggles & IRQ4)  irq = 4;
  126.    else {
  127.       printf("logminit: IRQ line did not respond (INTERRUPT_REG = 0x%x)\n",
  128.              toggles);
  129.       printf("Logitech Bus Mouse not loaded.\n");
  130.       return;
  131.    }
  132.    printf("Logitech Bus Mouse loaded with IRQ%d\n", irq);
  133.  
  134.    /* Set control register.  Set HC to 1:  A rising edge of HC transfers
  135.       the content of the counters into latches and resets the counters;
  136.       Disable interrupts; (also selects low nibble of the X counter.) */
  137.    outb(CONTROL_REG, HC | DINT);
  138.  
  139.    mousepresent = 1;
  140.  
  141. } /* logminit */
  142.  
  143. /*---------------------------------------------------------------------------*/
  144. void logmopen(dev, flag)
  145. int dev, flag;
  146. {
  147. #ifdef DEBUG
  148. printf("logmopen: dev = 0x%x, flag = 0x%x\n", dev, flag);
  149. #endif /* DEBUG */
  150.  
  151.    /* Insist on minor device 0 */
  152.    if (minor(dev))    { u.u_error = ENXIO;  return; }
  153.  
  154.    /* Make sure there is a mouse. */
  155.    if (!mousepresent) { u.u_error = ENXIO;  return; }
  156.  
  157.    /* Enforce exclusive use. */
  158.    if (mouseinuse)    { u.u_error = EBUSY;  return; }
  159.  
  160.    xmotion = ymotion = 0;
  161.    mousestatus = last_buttons = 0;
  162.  
  163. #ifdef VPIX
  164.    ectproc = u.u_procp;
  165.    rupted = 0;
  166. #endif /* VPIX */
  167.  
  168.    mouseinuse = 1;
  169.  
  170.    /* Set HC to 0 and enable interrupts. */
  171.    outb(CONTROL_REG, 0);
  172.  
  173. } /* logmopen */
  174.  
  175. /*---------------------------------------------------------------------------*/
  176. void logmclose(dev)
  177. int dev;
  178. {
  179. #ifdef DEBUG
  180. printf("logmclose\n");
  181. #endif /* DEBUG */
  182.  
  183.    /* Insist on minor device 0 */
  184.    if (minor(dev))    { u.u_error = ENXIO;  return; }
  185.  
  186.    /* Make sure there is a mouse. */
  187.    if (!mousepresent) { u.u_error = ENXIO;  return; }
  188.  
  189.    /* Make sure mouse has been opened. */
  190.    if (!mouseinuse)   { u.u_error = EACCES;  return; }
  191.  
  192.    /* Reset the mouse to make sure it does not interrupt. */
  193.    outb(CONTROL_REG, DINT);
  194.    mouseinuse = 0;
  195.  
  196. } /* logmclose */
  197.  
  198. /*---------------------------------------------------------------------------*/
  199. void logmioctl(dev, cmd, arg, flag)
  200. int dev, cmd, flag;
  201. caddr_t arg;
  202. {
  203.    struct mouseinfo info;
  204.    register int intmask;
  205.  
  206. #ifdef DEBUG
  207.    unsigned char ir;
  208.  
  209.    printf("logmioctl\n");
  210. #endif /* DEBUG */
  211.  
  212.    /* Insist on minor device 0 */
  213.    if (minor(dev))    { u.u_error = ENXIO;  return; }
  214.  
  215.    /* Make sure there is a mouse. */
  216.    if (!mousepresent) { u.u_error = ENXIO;  return; }
  217.  
  218.    /* Make sure mouse has been opened. */
  219.    if (!mouseinuse)   { u.u_error = EACCES;  return; }
  220.  
  221.    switch (cmd) {
  222. #ifdef DEBUG
  223.       case 0:
  224.          printf("logmioctl: outb(CONTROL_REG, 0                    )\n");
  225.          outb(CONTROL_REG, 0                    );
  226.          break;
  227.       case 1:
  228.          printf("logmioctl: outb(CONTROL_REG,                  DINT)\n");
  229.          outb(CONTROL_REG,                  DINT);
  230.          break;
  231.       case 2:
  232.          printf("logmioctl: outb(CONTROL_REG,            SHL       )\n");
  233.          outb(CONTROL_REG,            SHL       );
  234.          break;
  235.       case 3:
  236.          printf("logmioctl: outb(CONTROL_REG,            SHL | DINT)\n");
  237.          outb(CONTROL_REG,            SHL | DINT);
  238.          break;
  239.       case 4:
  240.          printf("logmioctl: outb(CONTROL_REG,      SXY             )\n");
  241.          outb(CONTROL_REG,      SXY             );
  242.          break;
  243.       case 5:
  244.          printf("logmioctl: outb(CONTROL_REG,      SXY |       DINT)\n");
  245.          outb(CONTROL_REG,      SXY |       DINT);
  246.          break;
  247.       case 6:
  248.          printf("logmioctl: outb(CONTROL_REG,      SXY | SHL       )\n");
  249.          outb(CONTROL_REG,      SXY | SHL       );
  250.          break;
  251.       case 7:
  252.          printf("logmioctl: outb(CONTROL_REG,      SXY | SHL | DINT)\n");
  253.          outb(CONTROL_REG,      SXY | SHL | DINT);
  254.          break;
  255.       case 8:
  256.          printf("logmioctl: outb(CONTROL_REG, HC                   )\n");
  257.          outb(CONTROL_REG, HC                   );
  258.          break;
  259.       case 9:
  260.          printf("logmioctl: outb(CONTROL_REG, HC |             DINT)\n");
  261.          outb(CONTROL_REG, HC |             DINT);
  262.          break;
  263.       case 10:
  264.          printf("logmioctl: outb(CONTROL_REG, HC |       SHL       )\n");
  265.          outb(CONTROL_REG, HC |       SHL       );
  266.          break;
  267.       case 11:
  268.          printf("logmioctl: outb(CONTROL_REG, HC |       SHL | DINT)\n");
  269.          outb(CONTROL_REG, HC |       SHL | DINT);
  270.          break;
  271.       case 12:
  272.          printf("logmioctl: outb(CONTROL_REG, HC | SXY             )\n");
  273.          outb(CONTROL_REG, HC | SXY             );
  274.          break;
  275.       case 13:
  276.          printf("logmioctl: outb(CONTROL_REG, HC | SXY |       DINT)\n");
  277.          outb(CONTROL_REG, HC | SXY |       DINT);
  278.          break;
  279.       case 14:
  280.          printf("logmioctl: outb(CONTROL_REG, HC | SXY | SHL       )\n");
  281.          outb(CONTROL_REG, HC | SXY | SHL       );
  282.          break;
  283.       case 15:
  284.          printf("logmioctl: outb(CONTROL_REG, HC | SXY | SHL | DINT)\n");
  285.          outb(CONTROL_REG, HC | SXY | SHL | DINT);
  286.          break;
  287.  
  288.       case 20:
  289.          ir = inb(DATA_REG);
  290.          printf("logmioctl: inb(DATA_REG) = 0x%x\n", ir);
  291.          break;
  292.       case 21:
  293.          ir = inb(SIGNATURE_REG);
  294.          printf("logmioctl: inb(SIGNATURE_REG) = 0x%x\n", ir);
  295.          break;
  296.       case 22:
  297.          ir = inb(INTERRUPT_REG);
  298.          printf("logmioctl: inb(INTERRUPT_REG) = 0x%x\n", ir);
  299.          break;
  300.       case 23:
  301.          ir = inb(CONFIG_REG);
  302.          printf("logmioctl: inb(CONFIG_REG) = 0x%x\n", ir);
  303.          break;
  304.       case 24:
  305.          outb(CONFIG_REG, CONFIG_BYTE);
  306.          printf("logmioctl: outb(CONFIG_REG, CONFIG_BYTE)\n");
  307.          break;
  308. #endif /* DEBUG */
  309.  
  310.       default:
  311.          /* Return error "Invalid argument". */
  312.          u.u_error = EINVAL;
  313. #ifdef DEBUG
  314.          printf("logmioctl: unknown cmd = 0x%x\n", cmd);
  315. #endif /* DEBUG */
  316.          break;
  317.  
  318.        case MOUSEIOCREAD:
  319.          /* Prevent mouse interrupts during update. */
  320.          intmask = splhi();
  321.  
  322.          /* Read and reset the accumulated interrupt info. */
  323.  
  324.          /* This emulates the microsoft bus mouse status return. */
  325.          info.status = mousestatus;
  326.          if (xmotion || ymotion) info.status |= MOVEMENT;
  327.  
  328.          info.xmotion = ONEBYTE(xmotion);
  329.          info.ymotion = ONEBYTE(ymotion);
  330.          xmotion = ymotion = 0;
  331.          mousestatus &= ~BUTCHNGMASK; /* clear "button changed" bits */
  332. #ifdef VPIX
  333.          rupted = 0;
  334. #endif /* VPIX */
  335.  
  336.          /* Resume mouse interrupts. */
  337.          splx(intmask);
  338.  
  339.          if (copyout(&info, arg, sizeof info)) u.u_error = EFAULT;
  340.          break;
  341.    } /* switch */
  342. } /* logmioctl */
  343.  
  344. /*---------------------------------------------------------------------------*/
  345. void logmintr(ivect)
  346. int ivect;
  347. {
  348.    unsigned char lo, hi, buttons, changed_buttons;
  349.    int dx, dy;
  350.  
  351.    /* Ignore if mouse is not present. */
  352.    if (!mousepresent) return;
  353.  
  354.    /* Print error on console if mouse has not been opened. */
  355.    if (!mouseinuse) {
  356. #ifdef DEBUG
  357.       printf("logmintr: Unsolicited INT %d\n", ivect);
  358. #endif /* DEBUG */
  359.       outb(CONTROL_REG, DINT); /* disable interrupts */
  360.       return;
  361.    }
  362.  
  363.    /* Read low X nibble. */
  364.    outb(CONTROL_REG, HC);
  365.    lo = inb(DATA_REG) & 0x0F;
  366.  
  367.    /* Read high X nibble. */
  368.    outb(CONTROL_REG, HC | SHL);
  369.    hi = inb(DATA_REG) & 0x0F;
  370.  
  371.    /* Combine high and low X nibbles. */
  372.    dx = (char) ((hi << 4) | lo);  /* force dx to be signed */
  373.  
  374.    /* Read low Y nibble. */
  375.    outb(CONTROL_REG, HC | SXY);
  376.    lo = inb(DATA_REG) & 0x0F;
  377.  
  378.    /* Read high Y nibble. */
  379.    outb(CONTROL_REG, HC | SXY | SHL);
  380.    hi = inb(DATA_REG);
  381.  
  382.    /* Extract and invert the button bits.
  383.       After inverting, a set bit means the button was pressed down. */
  384.    buttons = (~hi >> 5) & 0x07;
  385.    changed_buttons = buttons ^ last_buttons;
  386.    last_buttons = buttons;
  387.  
  388.    /* Combine high and low X nibbles. */
  389.    dy = (char) (((hi & 0x0F) << 4) | lo);  /* force dy to be signed */
  390.  
  391.    /* This code emulates the Microsoft bus mouse status (except for the MOTION
  392.       bit which is set in the ioctl routine).  State changes are or'ed over
  393.       any number of interrupts, but the buttons bits are always set to the
  394.       current state.  (The state changes are cleared when read in the ioctl
  395.       routine.) */
  396.    mousestatus = buttons | (mousestatus & ~BUTSTATMASK)
  397.                          | (changed_buttons << 3);
  398.  
  399.    /* Reset HC to 0. */
  400.    outb(CONTROL_REG, 0);
  401.  
  402.    /* If nothing has changed, nothing needs to be done, so return. */
  403.    if (!(dx || dy || changed_buttons)) return;
  404.  
  405.    /* Update global variables with info just read. */
  406.    xmotion += dx;
  407.    ymotion += dy;
  408. #ifdef DEBUG
  409.    printf("logmintr: dx = %d, dy = %d, buttons = %d\n", dx, dy, buttons);
  410. #endif /* DEBUG */
  411.  
  412. #ifdef VPIX
  413.    /* Send a pseudorupt if this is an ECT and the mouse has been read since
  414.       the last pseudorupt. */
  415.    if (ectproc && ectproc->p_v86 && !rupted) {
  416.       v86setint(ectproc->p_v86, V86VI_MOUSE);
  417.       rupted = 1;
  418.    }
  419. #endif /* VPIX */
  420.  
  421. } /* logmintr */
  422.