Subject: ps/2 mouse driver
To: None <netbsd-bugs@sun-lamp.cs.berkeley.edu>
From: Havard Eidnes <Havard.Eidnes@runit.sintef.no>
List: netbsd-bugs
Date: 01/09/1994 16:50:33
------- =_aaaaaaaaaa0
Content-Type: text/plain; charset="us-ascii"
Hi,
someone on the current-users list recently sent out a message that the
current PS/2 mouse driver doesn't work, and that someone had sent out
patches fixing that. I saw no response, so here goes.
Below you will find the changes between the current driver and one that
works for me. I guess some of the style (eg. autoconf message) and
includes will have to be changed back (presumably done after these diffs
were created). Please note that I am not the author of these changes --
the diffs give more clues.
Anyway, the changes below makes the difference between a kernel that hangs
in autoconfig and a kernel with a PS/2 driver that actually works on my
Intel-GX/Pro machine where the mouse plugs into the AUX port.
Regards,
- Havard
------- =_aaaaaaaaaa0
Content-Type: text/plain; charset="us-ascii"
Content-Description: PS/2 mouse driver changes
*** pms.c.old Mon Dec 20 12:23:16 1993
--- pms.c Sat Jan 8 16:26:30 1994
***************
*** 19,47 ****
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
! * $Id: pms.c,v 1.9 1993/12/20 09:06:39 mycroft Exp $
*/
#include "pms.h"
#if NPMS > 0
! #include <sys/param.h>
! #include <sys/kernel.h>
! #include <sys/systm.h>
! #include <sys/buf.h>
! #include <sys/malloc.h>
! #include <sys/ioctl.h>
! #include <sys/tty.h>
! #include <sys/file.h>
#ifdef NetBSD
! #include <sys/select.h>
#endif
! #include <sys/proc.h>
! #include <sys/vnode.h>
! #include <machine/mouse.h>
! #include <machine/pio.h>
! #include <i386/isa/isa_device.h>
#define DATA 0 /* Offset for data port, read-write */
--- 19,74 ----
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+ /*
+ * Ported to 386bsd Oct 17, 1992
+ * Sandi Donno, Computer Science, University of Cape Town, South Africa
+ * Please send bug reports to sandi@cs.uct.ac.za
+ *
+ * Thanks are also due to Rick Macklem, rick@snowhite.cis.uoguelph.ca -
+ * although I was only partially successful in getting the alpha release
+ * of his "driver for the Logitech and ATI Inport Bus mice for use with
+ * 386bsd and the X386 port" to work with my Microsoft mouse, I nevertheless
+ * found his code to be an invaluable reference when porting this driver
+ * to 386bsd.
+ *
+ * Further modifications for latest 386BSD+patchkit and port to NetBSD,
+ * Andrew Herbert <andrew@werple.apana.org.au> - 8 June 1993
+ *
+ * Cloned from the Microsoft Bus Mouse driver, also by Erik Forsberg, by
+ * Andrew Herbert - 12 June 1993
*
! * Modified for PS/2 mouse by Charles Hannum <mycroft@ai.mit.edu>
! * - 13 June 1993
! *
! * Modified for PS/2 AUX mouse by Shoji Yuen <yuen@nuie.nagoya-u.ac.jp>
! * - 24 October 1993
*/
#include "pms.h"
+
#if NPMS > 0
! #include "param.h"
! #include "kernel.h"
! #include "systm.h"
! #include "buf.h"
! #include "malloc.h"
! #include "ioctl.h"
! #include "tty.h"
! #include "file.h"
#ifdef NetBSD
! #include "select.h"
#endif
! #include "proc.h"
! #include "vnode.h"
! #include "i386/include/mouse.h"
! #include "i386/include/pio.h" /* Julian's fast IO macros */
! #include "i386/isa/isa_device.h"
! #ifdef 0
! #include "syslog.h" /* For debugging */
! #endif
#define DATA 0 /* Offset for data port, read-write */
***************
*** 50,69 ****
/* status bits */
! #define PMS_OBUF_FULL 0x21
! #define PMS_IBUF_FULL 0x02
/* controller commands */
#define PMS_INT_ENABLE 0x47 /* enable controller interrupts */
#define PMS_INT_DISABLE 0x65 /* disable controller interrupts */
! #define PMS_AUX_DISABLE 0xa7 /* enable auxiliary port */
! #define PMS_AUX_ENABLE 0xa8 /* disable auxiliary port */
! #define PMS_MAGIC_1 0xa9 /* XXX */
! #define PMS_MAGIC_2 0xaa /* XXX */
!
! /* mouse commands */
! #define PMS_SET_SCALE11 0xe6 /* set scaling 1:1 */
! #define PMS_SET_SCALE21 0xe7 /* set scaling 2:1 */
#define PMS_SET_RES 0xe8 /* set resolution */
! #define PMS_GET_SCALE 0xe9 /* get scaling factor */
#define PMS_SET_STREAM 0xea /* set streaming mode */
#define PMS_SET_SAMPLE 0xf3 /* set sampling rate */
--- 77,94 ----
/* status bits */
! #define PMS_OUTPUT_ACK 0x02 /* output acknowledge */
! /*#define PMS_OUTPUT_ACK 0x21 /* output acknowledge */
/* controller commands */
+ #define PMS_ENABLE 0xa8 /* enable auxiliary port */
+ #define PMS_DISABLE 0xa7 /* disable auxiliary port */
#define PMS_INT_ENABLE 0x47 /* enable controller interrupts */
#define PMS_INT_DISABLE 0x65 /* disable controller interrupts */
!
! /* m+use commands */
! #define PMS_SET_SCALE11 0xe6 /* set 1:1 scaling */
! #define PMS_SET_SCALE21 0xe7 /* set 2:1 scaling */
#define PMS_SET_RES 0xe8 /* set resolution */
! #define PMS_GET_SCALE 0xe9 /* set scaling factor */
#define PMS_SET_STREAM 0xea /* set streaming mode */
#define PMS_SET_SAMPLE 0xf3 /* set sampling rate */
***************
*** 92,96 ****
--- 117,125 ----
static struct pms_softc { /* Driver status information */
struct ringbuf inq; /* Input queue */
+ #ifdef NetBSD
struct selinfo rsel;
+ #else
+ pid_t rsel; /* Process selecting for Input */
+ #endif
unsigned char state; /* Mouse driver state */
unsigned char status; /* Mouse button status */
***************
*** 104,134 ****
struct isa_driver pmsdriver = { pmsprobe, pmsattach, "pms" };
! static inline void pms_flush(int ioport)
! {
! u_char c;
! while (c = inb(ioport+STATUS) & 0x03)
! if ((c & PMS_OBUF_FULL) == PMS_OBUF_FULL)
! (void) inb(ioport+DATA);
! }
! static inline void pms_dev_cmd(int ioport, u_char value)
{
! pms_flush(ioport);
! outb(ioport+CNTRL, 0xd4);
! pms_flush(ioport);
! outb(ioport+DATA, value);
}
! static inline void pms_aux_cmd(int ioport, u_char value)
{
! pms_flush(ioport);
! outb(ioport+CNTRL, value);
! }
!
! static inline void pms_pit_cmd(int ioport, u_char value)
! {
! pms_flush(ioport);
outb(ioport+CNTRL, 0x60);
! pms_flush(ioport);
outb(ioport+DATA, value);
}
--- 133,151 ----
struct isa_driver pmsdriver = { pmsprobe, pmsattach, "pms" };
! #define AUX_PORT 0x60 /* AUX_PORT base (S.Yuen) */
! static void pms_write_dev(int inport, u_char value)
{
! pms_poll_status();
! outb(inport+CNTRL, 0xd4);
! pms_poll_status();
! outb(inport+DATA,value);
}
! static inline void pms_command(int ioport, u_char value)
{
! pms_poll_status();
outb(ioport+CNTRL, 0x60);
! pms_poll_status();
outb(ioport+DATA, value);
}
***************
*** 136,151 ****
int pmsprobe(struct isa_device *dvp)
{
! int unit = dvp->id_unit;
! int ioport = dvp->id_iobase;
! u_char c;
! pms_dev_cmd(ioport, PMS_RESET);
! pms_aux_cmd(ioport, PMS_MAGIC_1);
! pms_aux_cmd(ioport, PMS_MAGIC_2);
c = inb(ioport+DATA);
! pms_pit_cmd(ioport, PMS_INT_DISABLE);
! if (c & 0x04)
! return 0;
! return 1;
}
--- 153,175 ----
int pmsprobe(struct isa_device *dvp)
{
! /* XXX: Needs a real probe routine. */
!
! int ioport,c,unit;
! ioport=dvp->id_iobase;
! unit=dvp->id_unit;
! pms_write_dev(ioport,0xff); /* Reset aux device */
! pms_poll_status();
! outb(ioport+CNTRL,0xa9);
! pms_poll_status();
! outb(ioport+CNTRL,0xaa);
c = inb(ioport+DATA);
! if(c&0x04) {
! printf("PS/2 AUX mouse is not found\n");
! pms_command(ioport,0x65);
! pmsaddr[unit] = 0; /* Device not found */
! return(0);}
! printf("PS/2 AUX mouse found. Installing driver\n");
! return (1);
}
***************
*** 157,179 ****
/* Save I/O base address */
pmsaddr[unit] = ioport;
! /* Disable mouse interrupts and initialize */
! pms_pit_cmd(ioport, PMS_INT_DISABLE);
! pms_aux_cmd(ioport, PMS_AUX_ENABLE);
! pms_dev_cmd(ioport, PMS_DEV_ENABLE);
! pms_dev_cmd(ioport, PMS_SET_RES);
! pms_dev_cmd(ioport, 3); /* 8 counts/mm */
! pms_dev_cmd(ioport, PMS_SET_SCALE21);
! pms_dev_cmd(ioport, PMS_SET_SAMPLE);
! pms_dev_cmd(ioport, 100); /* 100 samples/sec */
! pms_dev_cmd(ioport, PMS_SET_STREAM);
! pms_dev_cmd(ioport, PMS_DEV_DISABLE);
! pms_aux_cmd(ioport, PMS_AUX_DISABLE);
- /* Setup initial driver state */
sc->state = 0;
/* Done */
return(0);
}
--- 181,211 ----
/* Save I/O base address */
+
pmsaddr[unit] = ioport;
! /* Disable mouse interrupts */
!
! pms_poll_status();
! outb(ioport+CNTRL, PMS_ENABLE);
! #ifdef 0
! pms_write(ioport, PMS_SET_RES);
! pms_write(ioport, 0x03); /* 8 counts/mm */
! pms_write(ioport, PMS_SET_SCALE);
! pms_write(ioport, 0x02); /* 2:1 */
! pms_write(ioport, PMS_SET_SCALE21);
! pms_write(ioport, PMS_SET_SAMPLE);
! pms_write(ioport, 0x64); /* 100 samples/sec */
! pms_write(ioport, PMS_SET_STREAM);
! #endif
! pms_poll_status();
! outb(ioport+CNTRL, PMS_DISABLE);
! pms_command(ioport, PMS_INT_DISABLE);
!
! /* Setup initial state */
sc->state = 0;
/* Done */
+
return(0);
}
***************
*** 186,197 ****
--- 218,232 ----
/* Validate unit number */
+
if (unit >= NPMS)
return(ENXIO);
/* Get device data */
+
sc = &pms_softc[unit];
ioport = pmsaddr[unit];
/* If device does not exist */
+
if (ioport == 0)
return(ENXIO);
***************
*** 202,206 ****
--- 237,248 ----
/* Initialize state */
+
sc->state |= OPEN;
+ #ifdef NetBSD
+ sc->rsel.si_pid = 0;
+ sc->rsel.si_coll = 0;
+ #else
+ sc->rsel = 0;
+ #endif
sc->status = 0;
sc->button = 0;
***************
*** 209,223 ****
/* Allocate and initialize a ring buffer */
sc->inq.count = sc->inq.first = sc->inq.last = 0;
/* Enable Bus Mouse interrupts */
! pms_aux_cmd(ioport, PMS_AUX_ENABLE);
! pms_pit_cmd(ioport, PMS_INT_ENABLE);
! pms_dev_cmd(ioport, PMS_DEV_ENABLE);
/* Successful open */
return(0);
}
int pmsclose(dev_t dev, int flag, int fmt, struct proc *p)
{
--- 251,278 ----
/* Allocate and initialize a ring buffer */
+
sc->inq.count = sc->inq.first = sc->inq.last = 0;
/* Enable Bus Mouse interrupts */
!
! pms_write_dev(ioport, PMS_DEV_ENABLE);
! pms_poll_status();
! outb(ioport+CNTRL, PMS_ENABLE);
! pms_command(ioport, PMS_INT_ENABLE);
/* Successful open */
+
return(0);
}
+ int pms_poll_status() /* 24 Oct. 1993 */
+ {
+
+ while(inb(AUX_PORT+STATUS)&0x03) {
+ if(inb(AUX_PORT+STATUS) & 0x2 == 0x2)
+ inb(AUX_PORT+DATA);}
+ }
+
+
int pmsclose(dev_t dev, int flag, int fmt, struct proc *p)
{
***************
*** 226,229 ****
--- 281,285 ----
/* Get unit and associated info */
+
unit = PMSUNIT(dev);
sc = &pms_softc[unit];
***************
*** 231,242 ****
/* Disable further mouse interrupts */
! pms_dev_cmd(ioport, PMS_DEV_DISABLE);
! pms_pit_cmd(ioport, PMS_INT_DISABLE);
! pms_aux_cmd(ioport, PMS_AUX_DISABLE);
/* Complete the close */
sc->state &= ~OPEN;
/* close is almost always successful */
return(0);
}
--- 287,301 ----
/* Disable further mouse interrupts */
!
! pms_command(ioport,PMS_INT_DISABLE);
! pms_poll_status();
! outb(ioport+CNTRL,PMS_DISABLE );
/* Complete the close */
+
sc->state &= ~OPEN;
/* close is almost always successful */
+
return(0);
}
***************
*** 252,258 ****
--- 311,319 ----
/* Get device information */
+
sc = &pms_softc[PMSUNIT(dev)];
/* Block until mouse activity occured */
+
s = spltty();
while (sc->inq.count == 0) {
***************
*** 270,273 ****
--- 331,335 ----
/* Transfer as many chunks as possible */
+
while (sc->inq.count > 0 && uio->uio_resid > 0) {
length = min(sc->inq.count, uio->uio_resid);
***************
*** 276,279 ****
--- 338,342 ----
/* Remove a small chunk from input queue */
+
if (sc->inq.first + length >= MSBSZ) {
bcopy(&sc->inq.queue[sc->inq.first],
***************
*** 289,292 ****
--- 352,356 ----
/* Copy data to user process */
+
error = uiomove(buffer, length, uio);
if (error)
***************
*** 297,300 ****
--- 361,365 ----
/* Allow interrupts again */
+
splx(s);
return(error);
***************
*** 308,314 ****
--- 373,381 ----
/* Get device information */
+
sc = &pms_softc[PMSUNIT(dev)];
/* Perform IOCTL command */
+
switch (cmd) {
***************
*** 316,322 ****
--- 383,391 ----
/* Don't modify info while calculating */
+
s = spltty();
/* Build mouse status octet */
+
info.status = sc->status;
if (sc->x || sc->y)
***************
*** 324,327 ****
--- 393,397 ----
/* Encode X and Y motion as good as we can */
+
if (sc->x > 127)
info.xmotion = 127;
***************
*** 339,342 ****
--- 409,413 ----
/* Reset historical information */
+
sc->x = 0;
sc->y = 0;
***************
*** 344,347 ****
--- 415,419 ----
/* Allow interrupts and copy result buffer */
+
splx(s);
error = copyout(&info, addr, sizeof(struct mouseinfo));
***************
*** 354,357 ****
--- 426,430 ----
/* Return error code */
+
return(error);
}
***************
*** 362,428 ****
struct pms_softc *sc = &pms_softc[unit];
int ioport = pmsaddr[unit];
- static int state = 0;
- static char buttons, dx, dy;
- char changed;
-
- switch (state) {
-
- case 0:
- buttons = inb(ioport + DATA);
- if (!(buttons & 0xc0))
- ++state;
- break;
-
- case 1:
- dx = inb(ioport + DATA);
- ++state;
- break;
-
- case 2:
- dy = inb(ioport + DATA);
- state = 0;
-
- if (buttons & 0x10)
- dx -= 256;
- if (buttons & 0x20)
- dy -= 256;
-
- if (dx == -128)
- dx = -127;
- if (dy == -128)
- dy = 127;
- else
- dy = -dy;
-
- buttons = ~(((buttons&1) << 2) | (buttons&3));
-
- changed = buttons ^ sc->button;
- sc->button = buttons;
- sc->status = buttons | (sc->status & ~BUTSTATMASK) | (changed << 3);
-
- /* Update accumulated movements */
- sc->x += dx;
- sc->y += dy;
-
- /* If device in use and a change occurred... */
- if (sc->state & OPEN && (dx || dy || changed)) {
- sc->inq.queue[sc->inq.last++] = 0x40 |
- (buttons ^ BUTSTATMASK);
- sc->inq.queue[sc->inq.last++ % MSBSZ] = dx;
- sc->inq.queue[sc->inq.last++ % MSBSZ] = dy;
- sc->inq.queue[sc->inq.last++ % MSBSZ] = 0;
- sc->inq.queue[sc->inq.last++ % MSBSZ] = 0;
- sc->inq.last = sc->inq.last % MSBSZ;
- sc->inq.count += 5;
-
- if (sc->state & ASLP) {
- sc->state &= ~ASLP;
- wakeup((caddr_t)sc);
- }
- selwakeup(&sc->rsel);
- }
! break;
}
}
--- 435,453 ----
struct pms_softc *sc = &pms_softc[unit];
int ioport = pmsaddr[unit];
! sc->inq.queue[sc->inq.last++ % MSBSZ] = inb(ioport+DATA);
! sc->inq.count++;
! if (sc -> state & ASLP) {
! sc->state &= ~ASLP;
! wakeup((caddr_t)sc);
}
+ #ifdef NetBSD
+ selwakeup(&sc->rsel);
+ #else
+ if (sc->rsel) {
+ selwakeup(sc->rsel, 0);
+ sc->rsel = 0;
+ }
+ #endif
}
***************
*** 433,445 ****
--- 458,476 ----
/* Silly to select for output */
+
if (rw == FWRITE)
return(0);
/* Return true if a mouse event available */
+
s = spltty();
if (sc->inq.count)
ret = 1;
else {
+ #ifdef NetBSD
selrecord(p, &sc->rsel);
+ #else
+ sc->rsel = p->p_pid;
+ #endif
ret = 0;
}
------- =_aaaaaaaaaa0--
------------------------------------------------------------------------------