]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/pc98/pc98/mse.c
Remove #if NFOO > 0 (it's not required in most cases) and also where it
[FreeBSD/FreeBSD.git] / sys / pc98 / pc98 / mse.c
1 /*
2  * Copyright 1992 by the University of Guelph
3  *
4  * Permission to use, copy and modify this
5  * software and its documentation for any purpose and without
6  * fee is hereby granted, provided that the above copyright
7  * notice appear in all copies and that both that copyright
8  * notice and this permission notice appear in supporting
9  * documentation.
10  * University of Guelph makes no representations about the suitability of
11  * this software for any purpose.  It is provided "as is"
12  * without express or implied warranty.
13  *
14  * $FreeBSD$
15  */
16 /*
17  * Driver for the Logitech and ATI Inport Bus mice for use with 386bsd and
18  * the X386 port, courtesy of
19  * Rick Macklem, rick@snowhite.cis.uoguelph.ca
20  * Caveats: The driver currently uses spltty(), but doesn't use any
21  * generic tty code. It could use splmse() (that only masks off the
22  * bus mouse interrupt, but that would require hacking in i386/isa/icu.s.
23  * (This may be worth the effort, since the Logitech generates 30/60
24  * interrupts/sec continuously while it is open.)
25  * NB: The ATI has NOT been tested yet!
26  */
27
28 /*
29  * Modification history:
30  * Sep 6, 1994 -- Lars Fredriksen(fredriks@mcs.com)
31  *   improved probe based on input from Logitech.
32  *
33  * Oct 19, 1992 -- E. Stark (stark@cs.sunysb.edu)
34  *   fixes to make it work with Microsoft InPort busmouse
35  *
36  * Jan, 1993 -- E. Stark (stark@cs.sunysb.edu)
37  *   added patches for new "select" interface
38  *
39  * May 4, 1993 -- E. Stark (stark@cs.sunysb.edu)
40  *   changed position of some spl()'s in mseread
41  *
42  * October 8, 1993 -- E. Stark (stark@cs.sunysb.edu)
43  *   limit maximum negative x/y value to -127 to work around XFree problem
44  *   that causes spurious button pushes.
45  */
46
47 #include "mse.h"
48 #if NMSE > 0
49
50 #include <sys/param.h>
51 #include <sys/systm.h>
52 #include <sys/conf.h>
53 #include <sys/kernel.h>
54 #include <sys/poll.h>
55 #include <sys/select.h>
56 #include <sys/uio.h>
57
58 #include <machine/clock.h>
59 #include <machine/mouse.h>
60
61 #include <i386/isa/isa_device.h>
62 #include <i386/isa/icu.h>
63
64 /* driver configuration flags (config) */
65 #define MSE_CONFIG_ACCEL        0x00f0  /* acceleration factor */
66 #define MSE_CONFIG_FLAGS        (MSE_CONFIG_ACCEL)
67
68 static int mseprobe(struct isa_device *);
69 static int mseattach(struct isa_device *);
70
71 struct  isa_driver msedriver = {
72         mseprobe, mseattach, "mse"
73 };
74
75 static  d_open_t        mseopen;
76 static  d_close_t       mseclose;
77 static  d_read_t        mseread;
78 static  d_ioctl_t       mseioctl;
79 static  d_poll_t        msepoll;
80
81 #define CDEV_MAJOR 27
82 static struct cdevsw mse_cdevsw = {
83         /* open */      mseopen,
84         /* close */     mseclose,
85         /* read */      mseread,
86         /* write */     nowrite,
87         /* ioctl */     mseioctl,
88         /* poll */      msepoll,
89         /* mmap */      nommap,
90         /* strategy */  nostrategy,
91         /* name */      "mse",
92         /* maj */       CDEV_MAJOR,
93         /* dump */      nodump,
94         /* psize */     nopsize,
95         /* flags */     0,
96         /* bmaj */      -1
97 };
98
99 static ointhand2_t mseintr;
100
101 /*
102  * Software control structure for mouse. The sc_enablemouse(),
103  * sc_disablemouse() and sc_getmouse() routines must be called spl'd().
104  */
105 static struct mse_softc {
106         int     sc_flags;
107         int     sc_mousetype;
108         struct  selinfo sc_selp;
109         u_int   sc_port;
110         void    (*sc_enablemouse) __P((u_int port));
111         void    (*sc_disablemouse) __P((u_int port));
112         void    (*sc_getmouse) __P((u_int port, int *dx, int *dy, int *but));
113         int     sc_deltax;
114         int     sc_deltay;
115         int     sc_obuttons;
116         int     sc_buttons;
117         int     sc_bytesread;
118         u_char  sc_bytes[MOUSE_SYS_PACKETSIZE];
119         mousehw_t       hw;
120         mousemode_t     mode;
121         mousestatus_t   status;
122 } mse_sc[NMSE];
123
124 /* Flags */
125 #define MSESC_OPEN      0x1
126 #define MSESC_WANT      0x2
127
128 /* and Mouse Types */
129 #define MSE_NONE        0       /* don't move this! */
130 #ifdef PC98
131 #define MSE_98BUSMOUSE  0x1
132 #else
133 #define MSE_LOGITECH    0x1
134 #define MSE_ATIINPORT   0x2
135 #define MSE_LOGI_SIG    0xA5
136 #endif
137
138 #ifdef PC98
139 #define NORMAL_MSPORT   0x7fd9
140 #define       PORT_A  0
141 #define       PORT_B  2
142 #define       PORT_C  4
143
144 #else /* IBM_PC */
145
146 #define MSE_PORTA       0
147 #define MSE_PORTB       1
148 #define MSE_PORTC       2
149 #define MSE_PORTD       3
150 #endif
151
152 #define MSE_UNIT(dev)           (minor(dev) >> 1)
153 #define MSE_NBLOCKIO(dev)       (minor(dev) & 0x1)
154
155 #ifdef PC98
156 /*
157  * PC-9801 Bus mouse definitions
158  */
159
160 #define MODE    6
161 #define HC      6
162 #define INT     6
163
164 #define XL      0x00
165 #define XH      0x20
166 #define YL      0x40
167 #define YH      0x60
168
169 #define INT_ENABLE      0x8
170 #define INT_DISABLE     0x9
171 #define HC_NO_CLEAR     0xe
172 #define HC_CLEAR        0xf
173
174 #define NORMAL_MSIRQ    IRQ13   /* INT6 */
175
176 static  int     msport;
177 static  int     msirq;
178
179 static int mse_probe98m __P((struct isa_device *idp));
180 static void mse_disable98m __P((u_int port));
181 static void mse_get98m __P((u_int port, int *dx, int *dy, int *but));
182 static void mse_enable98m __P((u_int port));
183 #else
184 /*
185  * Logitech bus mouse definitions
186  */
187 #define MSE_SETUP       0x91    /* What does this mean? */
188                                 /* The definition for the control port */
189                                 /* is as follows: */
190
191                                 /* D7    =  Mode set flag (1 = active)  */
192                                 /* D6,D5 =  Mode selection (port A)     */
193                                 /*          00 = Mode 0 = Basic I/O     */
194                                 /*          01 = Mode 1 = Strobed I/O   */
195                                 /*          10 = Mode 2 = Bi-dir bus    */
196                                 /* D4    =  Port A direction (1 = input)*/
197                                 /* D3    =  Port C (upper 4 bits)       */
198                                 /*          direction. (1 = input)      */
199                                 /* D2    =  Mode selection (port B & C) */
200                                 /*          0 = Mode 0 = Basic I/O      */
201                                 /*          1 = Mode 1 = Strobed I/O    */
202                                 /* D1    =  Port B direction (1 = input)*/
203                                 /* D0    =  Port C (lower 4 bits)       */
204                                 /*          direction. (1 = input)      */
205
206                                 /* So 91 means Basic I/O on all 3 ports,*/
207                                 /* Port A is an input port, B is an     */
208                                 /* output port, C is split with upper   */
209                                 /* 4 bits being an output port and lower*/
210                                 /* 4 bits an input port, and enable the */
211                                 /* sucker.                              */
212                                 /* Courtesy Intel 8255 databook. Lars   */
213 #define MSE_HOLD        0x80
214 #define MSE_RXLOW       0x00
215 #define MSE_RXHIGH      0x20
216 #define MSE_RYLOW       0x40
217 #define MSE_RYHIGH      0x60
218 #define MSE_DISINTR     0x10
219 #define MSE_INTREN      0x00
220
221 static int mse_probelogi __P((struct isa_device *idp));
222 static void mse_disablelogi __P((u_int port));
223 static void mse_getlogi __P((u_int port, int *dx, int *dy, int *but));
224 static void mse_enablelogi __P((u_int port));
225
226 /*
227  * ATI Inport mouse definitions
228  */
229 #define MSE_INPORT_RESET        0x80
230 #define MSE_INPORT_STATUS       0x00
231 #define MSE_INPORT_DX           0x01
232 #define MSE_INPORT_DY           0x02
233 #define MSE_INPORT_MODE         0x07
234 #define MSE_INPORT_HOLD         0x20
235 #define MSE_INPORT_INTREN       0x09
236
237 static int mse_probeati __P((struct isa_device *idp));
238 static void mse_enableati __P((u_int port));
239 static void mse_disableati __P((u_int port));
240 static void mse_getati __P((u_int port, int *dx, int *dy, int *but));
241 #endif
242
243 #define MSEPRI  (PZERO + 3)
244
245 /*
246  * Table of mouse types.
247  * Keep the Logitech last, since I haven't figured out how to probe it
248  * properly yet. (Someday I'll have the documentation.)
249  */
250 static struct mse_types {
251         int     m_type;         /* Type of bus mouse */
252         int     (*m_probe) __P((struct isa_device *idp));
253                                 /* Probe routine to test for it */
254         void    (*m_enable) __P((u_int port));
255                                 /* Start routine */
256         void    (*m_disable) __P((u_int port));
257                                 /* Disable interrupts routine */
258         void    (*m_get) __P((u_int port, int *dx, int *dy, int *but));
259                                 /* and get mouse status */
260         mousehw_t   m_hw;       /* buttons iftype type model hwid */
261         mousemode_t m_mode;     /* proto rate res accel level size mask */
262 } mse_types[] = {
263 #ifdef PC98
264         { MSE_98BUSMOUSE,
265           mse_probe98m, mse_enable98m, mse_disable98m, mse_get98m,
266           { 2, MOUSE_IF_BUS, MOUSE_MOUSE, MOUSE_MODEL_GENERIC, 0, },
267           { MOUSE_PROTO_BUS, -1, -1, 0, 0, MOUSE_MSC_PACKETSIZE, 
268             { MOUSE_MSC_SYNCMASK, MOUSE_MSC_SYNC, }, }, },
269 #else
270         { MSE_ATIINPORT, 
271           mse_probeati, mse_enableati, mse_disableati, mse_getati,
272           { 2, MOUSE_IF_INPORT, MOUSE_MOUSE, MOUSE_MODEL_GENERIC, 0, },
273           { MOUSE_PROTO_INPORT, -1, -1, 0, 0, MOUSE_MSC_PACKETSIZE, 
274             { MOUSE_MSC_SYNCMASK, MOUSE_MSC_SYNC, }, }, },
275         { MSE_LOGITECH, 
276           mse_probelogi, mse_enablelogi, mse_disablelogi, mse_getlogi,
277           { 2, MOUSE_IF_BUS, MOUSE_MOUSE, MOUSE_MODEL_GENERIC, 0, },
278           { MOUSE_PROTO_BUS, -1, -1, 0, 0, MOUSE_MSC_PACKETSIZE, 
279             { MOUSE_MSC_SYNCMASK, MOUSE_MSC_SYNC, }, }, },
280 #endif
281         { 0, },
282 };
283
284 int
285 mseprobe(idp)
286         register struct isa_device *idp;
287 {
288         register struct mse_softc *sc = &mse_sc[idp->id_unit];
289         register int i;
290
291         /*
292          * Check for each mouse type in the table.
293          */
294         i = 0;
295         while (mse_types[i].m_type) {
296                 if ((*mse_types[i].m_probe)(idp)) {
297                         sc->sc_mousetype = mse_types[i].m_type;
298                         sc->sc_enablemouse = mse_types[i].m_enable;
299                         sc->sc_disablemouse = mse_types[i].m_disable;
300                         sc->sc_getmouse = mse_types[i].m_get;
301                         sc->hw = mse_types[i].m_hw;
302                         sc->mode = mse_types[i].m_mode;
303                         return (1);
304                 }
305                 i++;
306         }
307         return (0);
308 }
309
310 int
311 mseattach(idp)
312         struct isa_device *idp;
313 {
314         int unit = idp->id_unit;
315         struct mse_softc *sc = &mse_sc[unit];
316
317 #ifdef PC98
318         if (msport != idp->id_iobase) {
319                 idp->id_iobase = msport;
320                 printf(" [ioport is changed to #0x%x]", msport);
321         }
322
323         if (msirq != idp->id_irq) {
324                 idp->id_irq = msirq;
325                 printf(" [irq is changed to IR%d]", ffs(msirq)-1);
326         }
327 #endif
328
329         idp->id_ointr = mseintr;
330         sc->sc_port = idp->id_iobase;
331         sc->mode.accelfactor = (idp->id_flags & MSE_CONFIG_ACCEL) >> 4;
332         make_dev(&mse_cdevsw, unit << 1, 0, 0, 0600, "mse%d", unit);
333         make_dev(&mse_cdevsw, (unit<<1)+1, 0, 0, 0600, "nmse%d", unit);
334         return (1);
335 }
336
337 /*
338  * Exclusive open the mouse, initialize it and enable interrupts.
339  */
340 static  int
341 mseopen(dev, flags, fmt, p)
342         dev_t dev;
343         int flags;
344         int fmt;
345         struct proc *p;
346 {
347         register struct mse_softc *sc;
348         int s;
349
350         if (MSE_UNIT(dev) >= NMSE)
351                 return (ENXIO);
352         sc = &mse_sc[MSE_UNIT(dev)];
353         if (sc->sc_mousetype == MSE_NONE)
354                 return (ENXIO);
355         if (sc->sc_flags & MSESC_OPEN)
356                 return (EBUSY);
357         sc->sc_flags |= MSESC_OPEN;
358         sc->sc_obuttons = sc->sc_buttons = MOUSE_MSC_BUTTONS;
359         sc->sc_deltax = sc->sc_deltay = 0;
360         sc->sc_bytesread = sc->mode.packetsize = MOUSE_MSC_PACKETSIZE;
361         sc->mode.level = 0;
362         sc->status.flags = 0;
363         sc->status.button = sc->status.obutton = 0;
364         sc->status.dx = sc->status.dy = sc->status.dz = 0;
365
366         /*
367          * Initialize mouse interface and enable interrupts.
368          */
369         s = spltty();
370         (*sc->sc_enablemouse)(sc->sc_port);
371         splx(s);
372         return (0);
373 }
374
375 /*
376  * mseclose: just turn off mouse innterrupts.
377  */
378 static  int
379 mseclose(dev, flags, fmt, p)
380         dev_t dev;
381         int flags;
382         int fmt;
383         struct proc *p;
384 {
385         struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)];
386         int s;
387
388         s = spltty();
389         (*sc->sc_disablemouse)(sc->sc_port);
390         sc->sc_flags &= ~MSESC_OPEN;
391         splx(s);
392         return(0);
393 }
394
395 /*
396  * mseread: return mouse info using the MSC serial protocol, but without
397  * using bytes 4 and 5.
398  * (Yes this is cheesy, but it makes the X386 server happy, so...)
399  */
400 static  int
401 mseread(dev, uio, ioflag)
402         dev_t dev;
403         struct uio *uio;
404         int ioflag;
405 {
406         register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)];
407         int xfer, s, error;
408
409         /*
410          * If there are no protocol bytes to be read, set up a new protocol
411          * packet.
412          */
413         s = spltty(); /* XXX Should be its own spl, but where is imlXX() */
414         if (sc->sc_bytesread >= sc->mode.packetsize) {
415                 while (sc->sc_deltax == 0 && sc->sc_deltay == 0 &&
416                        (sc->sc_obuttons ^ sc->sc_buttons) == 0) {
417                         if (MSE_NBLOCKIO(dev)) {
418                                 splx(s);
419                                 return (0);
420                         }
421                         sc->sc_flags |= MSESC_WANT;
422                         error = tsleep((caddr_t)sc, MSEPRI | PCATCH,
423                                 "mseread", 0);
424                         if (error) {
425                                 splx(s);
426                                 return (error);
427                         }
428                 }
429
430                 /*
431                  * Generate protocol bytes.
432                  * For some reason X386 expects 5 bytes but never uses
433                  * the fourth or fifth?
434                  */
435                 sc->sc_bytes[0] = sc->mode.syncmask[1] 
436                     | (sc->sc_buttons & ~sc->mode.syncmask[0]);
437                 if (sc->sc_deltax > 127)
438                         sc->sc_deltax = 127;
439                 if (sc->sc_deltax < -127)
440                         sc->sc_deltax = -127;
441                 sc->sc_deltay = -sc->sc_deltay; /* Otherwise mousey goes wrong way */
442                 if (sc->sc_deltay > 127)
443                         sc->sc_deltay = 127;
444                 if (sc->sc_deltay < -127)
445                         sc->sc_deltay = -127;
446                 sc->sc_bytes[1] = sc->sc_deltax;
447                 sc->sc_bytes[2] = sc->sc_deltay;
448                 sc->sc_bytes[3] = sc->sc_bytes[4] = 0;
449                 sc->sc_bytes[5] = sc->sc_bytes[6] = 0;
450                 sc->sc_bytes[7] = MOUSE_SYS_EXTBUTTONS;
451                 sc->sc_obuttons = sc->sc_buttons;
452                 sc->sc_deltax = sc->sc_deltay = 0;
453                 sc->sc_bytesread = 0;
454         }
455         splx(s);
456         xfer = min(uio->uio_resid, sc->mode.packetsize - sc->sc_bytesread);
457         error = uiomove(&sc->sc_bytes[sc->sc_bytesread], xfer, uio);
458         if (error)
459                 return (error);
460         sc->sc_bytesread += xfer;
461         return(0);
462 }
463
464 /*
465  * mseioctl: process ioctl commands.
466  */
467 static int
468 mseioctl(dev, cmd, addr, flag, p)
469         dev_t dev;
470         u_long cmd;
471         caddr_t addr;
472         int flag;
473         struct proc *p;
474 {
475         register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)];
476         mousestatus_t status;
477         int err = 0;
478         int s;
479
480         switch (cmd) {
481
482         case MOUSE_GETHWINFO:
483                 s = spltty();
484                 *(mousehw_t *)addr = sc->hw;
485                 if (sc->mode.level == 0)
486                         ((mousehw_t *)addr)->model = MOUSE_MODEL_GENERIC;
487                 splx(s);
488                 break;
489
490         case MOUSE_GETMODE:
491                 s = spltty();
492                 *(mousemode_t *)addr = sc->mode;
493                 switch (sc->mode.level) {
494                 case 0:
495                         break;
496                 case 1:
497                         ((mousemode_t *)addr)->protocol = MOUSE_PROTO_SYSMOUSE;
498                         ((mousemode_t *)addr)->syncmask[0] = MOUSE_SYS_SYNCMASK;
499                         ((mousemode_t *)addr)->syncmask[1] = MOUSE_SYS_SYNC;
500                         break;
501                 }
502                 splx(s);
503                 break;
504
505         case MOUSE_SETMODE:
506                 switch (((mousemode_t *)addr)->level) {
507                 case 0:
508                 case 1:
509                         break;
510                 default:
511                         return (EINVAL);
512                 }
513                 if (((mousemode_t *)addr)->accelfactor < -1)
514                         return (EINVAL);
515                 else if (((mousemode_t *)addr)->accelfactor >= 0)
516                         sc->mode.accelfactor = 
517                             ((mousemode_t *)addr)->accelfactor;
518                 sc->mode.level = ((mousemode_t *)addr)->level;
519                 switch (sc->mode.level) {
520                 case 0:
521                         sc->sc_bytesread = sc->mode.packetsize 
522                             = MOUSE_MSC_PACKETSIZE;
523                         break;
524                 case 1:
525                         sc->sc_bytesread = sc->mode.packetsize 
526                             = MOUSE_SYS_PACKETSIZE;
527                         break;
528                 }
529                 break;
530
531         case MOUSE_GETLEVEL:
532                 *(int *)addr = sc->mode.level;
533                 break;
534
535         case MOUSE_SETLEVEL:
536                 switch (*(int *)addr) {
537                 case 0:
538                         sc->mode.level = *(int *)addr;
539                         sc->sc_bytesread = sc->mode.packetsize 
540                             = MOUSE_MSC_PACKETSIZE;
541                         break;
542                 case 1:
543                         sc->mode.level = *(int *)addr;
544                         sc->sc_bytesread = sc->mode.packetsize 
545                             = MOUSE_SYS_PACKETSIZE;
546                         break;
547                 default:
548                         return (EINVAL);
549                 }
550                 break;
551
552         case MOUSE_GETSTATUS:
553                 s = spltty();
554                 status = sc->status;
555                 sc->status.flags = 0;
556                 sc->status.obutton = sc->status.button;
557                 sc->status.button = 0;
558                 sc->status.dx = 0;
559                 sc->status.dy = 0;
560                 sc->status.dz = 0;
561                 splx(s);
562                 *(mousestatus_t *)addr = status;
563                 break;
564
565         case MOUSE_READSTATE:
566         case MOUSE_READDATA:
567                 return (ENODEV);
568
569 #if (defined(MOUSE_GETVARS))
570         case MOUSE_GETVARS:
571         case MOUSE_SETVARS:
572                 return (ENODEV);
573 #endif
574
575         default:
576                 return (ENOTTY);
577         }
578         return (err);
579 }
580
581 /*
582  * msepoll: check for mouse input to be processed.
583  */
584 static  int
585 msepoll(dev, events, p)
586         dev_t dev;
587         int events;
588         struct proc *p;
589 {
590         register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)];
591         int s;
592         int revents = 0;
593
594         s = spltty();
595         if (events & (POLLIN | POLLRDNORM)) {
596                 if (sc->sc_bytesread != sc->mode.packetsize ||
597                     sc->sc_deltax != 0 || sc->sc_deltay != 0 ||
598                     (sc->sc_obuttons ^ sc->sc_buttons) != 0)
599                         revents |= events & (POLLIN | POLLRDNORM);
600                 else {
601                         /*
602                          * Since this is an exclusive open device, any previous
603                          * proc pointer is trash now, so we can just assign it.
604                          */
605                         selrecord(p, &sc->sc_selp);
606                 }
607         }
608         splx(s);
609         return (revents);
610 }
611
612 /*
613  * mseintr: update mouse status. sc_deltax and sc_deltay are accumulative.
614  */
615 static void
616 mseintr(unit)
617         int unit;
618 {
619         /*
620          * the table to turn MouseSystem button bits (MOUSE_MSC_BUTTON?UP)
621          * into `mousestatus' button bits (MOUSE_BUTTON?DOWN).
622          */
623         static int butmap[8] = {
624                 0, 
625                 MOUSE_BUTTON3DOWN, 
626                 MOUSE_BUTTON2DOWN, 
627                 MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN, 
628                 MOUSE_BUTTON1DOWN, 
629                 MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN, 
630                 MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN,
631                 MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN
632         };
633         register struct mse_softc *sc = &mse_sc[unit];
634         int dx, dy, but;
635         int sign;
636
637 #ifdef DEBUG
638         static int mse_intrcnt = 0;
639         if((mse_intrcnt++ % 10000) == 0)
640                 printf("mseintr\n");
641 #endif /* DEBUG */
642         if ((sc->sc_flags & MSESC_OPEN) == 0)
643                 return;
644
645         (*sc->sc_getmouse)(sc->sc_port, &dx, &dy, &but);
646         if (sc->mode.accelfactor > 0) {
647                 sign = (dx < 0);
648                 dx = dx * dx / sc->mode.accelfactor;
649                 if (dx == 0)
650                         dx = 1;
651                 if (sign)
652                         dx = -dx;
653                 sign = (dy < 0);
654                 dy = dy * dy / sc->mode.accelfactor;
655                 if (dy == 0)
656                         dy = 1;
657                 if (sign)
658                         dy = -dy;
659         }
660         sc->sc_deltax += dx;
661         sc->sc_deltay += dy;
662         sc->sc_buttons = but;
663
664         but = butmap[~but & MOUSE_MSC_BUTTONS];
665         sc->status.dx += dx;
666         sc->status.dy += dy;
667         sc->status.flags |= ((dx || dy) ? MOUSE_POSCHANGED : 0)
668             | (sc->status.button ^ but);
669         sc->status.button = but;
670
671         /*
672          * If mouse state has changed, wake up anyone wanting to know.
673          */
674         if (sc->sc_deltax != 0 || sc->sc_deltay != 0 ||
675             (sc->sc_obuttons ^ sc->sc_buttons) != 0) {
676                 if (sc->sc_flags & MSESC_WANT) {
677                         sc->sc_flags &= ~MSESC_WANT;
678                         wakeup((caddr_t)sc);
679                 }
680                 selwakeup(&sc->sc_selp);
681         }
682 }
683
684 #ifndef PC98
685 /*
686  * Routines for the Logitech mouse.
687  */
688 /*
689  * Test for a Logitech bus mouse and return 1 if it is.
690  * (until I know how to use the signature port properly, just disable
691  *  interrupts and return 1)
692  */
693 static int
694 mse_probelogi(idp)
695         register struct isa_device *idp;
696 {
697
698         int sig;
699
700         outb(idp->id_iobase + MSE_PORTD, MSE_SETUP);
701                 /* set the signature port */
702         outb(idp->id_iobase + MSE_PORTB, MSE_LOGI_SIG);
703
704         DELAY(30000); /* 30 ms delay */
705         sig = inb(idp->id_iobase + MSE_PORTB) & 0xFF;
706         if (sig == MSE_LOGI_SIG) {
707                 outb(idp->id_iobase + MSE_PORTC, MSE_DISINTR);
708                 return(1);
709         } else {
710                 if (bootverbose)
711                         printf("mse%d: wrong signature %x\n",idp->id_unit,sig);
712                 return(0);
713         }
714 }
715
716 /*
717  * Initialize Logitech mouse and enable interrupts.
718  */
719 static void
720 mse_enablelogi(port)
721         register u_int port;
722 {
723         int dx, dy, but;
724
725         outb(port + MSE_PORTD, MSE_SETUP);
726         mse_getlogi(port, &dx, &dy, &but);
727 }
728
729 /*
730  * Disable interrupts for Logitech mouse.
731  */
732 static void
733 mse_disablelogi(port)
734         register u_int port;
735 {
736
737         outb(port + MSE_PORTC, MSE_DISINTR);
738 }
739
740 /*
741  * Get the current dx, dy and button up/down state.
742  */
743 static void
744 mse_getlogi(port, dx, dy, but)
745         register u_int port;
746         int *dx;
747         int *dy;
748         int *but;
749 {
750         register char x, y;
751
752         outb(port + MSE_PORTC, MSE_HOLD | MSE_RXLOW);
753         x = inb(port + MSE_PORTA);
754         *but = (x >> 5) & MOUSE_MSC_BUTTONS;
755         x &= 0xf;
756         outb(port + MSE_PORTC, MSE_HOLD | MSE_RXHIGH);
757         x |= (inb(port + MSE_PORTA) << 4);
758         outb(port + MSE_PORTC, MSE_HOLD | MSE_RYLOW);
759         y = (inb(port + MSE_PORTA) & 0xf);
760         outb(port + MSE_PORTC, MSE_HOLD | MSE_RYHIGH);
761         y |= (inb(port + MSE_PORTA) << 4);
762         *dx = x;
763         *dy = y;
764         outb(port + MSE_PORTC, MSE_INTREN);
765 }
766
767 /*
768  * Routines for the ATI Inport bus mouse.
769  */
770 /*
771  * Test for a ATI Inport bus mouse and return 1 if it is.
772  * (do not enable interrupts)
773  */
774 static int
775 mse_probeati(idp)
776         register struct isa_device *idp;
777 {
778         int i;
779
780         for (i = 0; i < 2; i++)
781                 if (inb(idp->id_iobase + MSE_PORTC) == 0xde)
782                         return (1);
783         return (0);
784 }
785
786 /*
787  * Initialize ATI Inport mouse and enable interrupts.
788  */
789 static void
790 mse_enableati(port)
791         register u_int port;
792 {
793
794         outb(port + MSE_PORTA, MSE_INPORT_RESET);
795         outb(port + MSE_PORTA, MSE_INPORT_MODE);
796         outb(port + MSE_PORTB, MSE_INPORT_INTREN);
797 }
798
799 /*
800  * Disable interrupts for ATI Inport mouse.
801  */
802 static void
803 mse_disableati(port)
804         register u_int port;
805 {
806
807         outb(port + MSE_PORTA, MSE_INPORT_MODE);
808         outb(port + MSE_PORTB, 0);
809 }
810
811 /*
812  * Get current dx, dy and up/down button state.
813  */
814 static void
815 mse_getati(port, dx, dy, but)
816         register u_int port;
817         int *dx;
818         int *dy;
819         int *but;
820 {
821         register char byte;
822
823         outb(port + MSE_PORTA, MSE_INPORT_MODE);
824         outb(port + MSE_PORTB, MSE_INPORT_HOLD);
825         outb(port + MSE_PORTA, MSE_INPORT_STATUS);
826         *but = ~inb(port + MSE_PORTB) & MOUSE_MSC_BUTTONS;
827         outb(port + MSE_PORTA, MSE_INPORT_DX);
828         byte = inb(port + MSE_PORTB);
829         *dx = byte;
830         outb(port + MSE_PORTA, MSE_INPORT_DY);
831         byte = inb(port + MSE_PORTB);
832         *dy = byte;
833         outb(port + MSE_PORTA, MSE_INPORT_MODE);
834         outb(port + MSE_PORTB, MSE_INPORT_INTREN);
835 }
836 #endif
837
838 #ifdef PC98
839
840 /*
841  * Routines for the PC98 bus mouse.
842  */
843
844 /*
845  * Test for a PC98 bus mouse and return 1 if it is.
846  * (do not enable interrupts)
847  */
848 static int
849 mse_probe98m(idp)
850         register struct isa_device *idp;
851 {
852
853         msport = NORMAL_MSPORT;
854         msirq = NORMAL_MSIRQ;
855         
856         /* mode set */
857         outb(msport + MODE, 0x93);
858         /* initialize */
859         outb(msport + INT, INT_DISABLE);        /* INT disable */
860         outb(msport + HC, HC_NO_CLEAR);         /* HC = 0 */
861         outb(msport + HC, HC_CLEAR);            /* HC = 1 */
862         return (1);
863 }
864
865 /*
866  * Initialize PC98 bus mouse and enable interrupts.
867  */
868 static void
869 mse_enable98m(port)
870         register u_int port;
871 {
872         outb(port + INT, INT_ENABLE);/* INT enable */
873         outb(port + HC, HC_NO_CLEAR); /* HC = 0 */
874         outb(port + HC, HC_CLEAR);      /* HC = 1 */
875 }
876  
877 /*
878  * Disable interrupts for PC98 Bus mouse.
879  */
880 static void
881 mse_disable98m(port)
882         register u_int port;
883 {
884         outb(port + INT, INT_DISABLE);/* INT disable */
885         outb(port + HC, HC_NO_CLEAR); /* HC = 0 */
886         outb(port + HC, HC_CLEAR);      /* HC = 1 */
887 }
888
889 /*
890  * Get current dx, dy and up/down button state.
891  */
892 static void
893 mse_get98m(port, dx, dy, but)
894         register u_int port;
895         int *dx;
896         int *dy;
897         int *but;
898 {
899         register char x, y;
900
901         outb(port + INT, INT_DISABLE); /* INT disable */
902
903         outb(port + HC, HC_CLEAR);      /* HC = 1 */
904
905         outb(port + PORT_C, 0x90 | XL);
906         x = inb(port + PORT_A) & 0x0f;                  /* X low */
907         outb(port + PORT_C, 0x90 | XH);
908         x |= ((inb(port + PORT_A)  & 0x0f) << 4);       /* X high */
909
910         outb(port + PORT_C, 0x90 | YL);
911         y = (inb(port + PORT_A) & 0x0f);                /* Y low */
912         outb(port + PORT_C, 0x90 | YH);
913         y |= ((inb(port + PORT_A) & 0x0f) << 4);
914
915         *but = (inb(port + PORT_A) >> 5) & 7;
916
917         *dx = x;
918         *dy = y;
919
920         outb(port + HC, HC_NO_CLEAR);   /* HC = 0 */
921
922         outb(port + INT, INT_ENABLE); /* INT enable */
923 }
924 #endif
925
926 #endif /* NMSE */