Return to BSD News archive
Path: sserve!manuel.anu.edu.au!munnari.oz.au!sgiblab!swrinde!cs.utexas.edu!sun-barr!olivea!charnel!psgrain!ee.und.ac.za!ucthpx!casper.cs.uct.ac.za!uctcs!sandi From: sandi@uctcs.cs.uct.ac.za (Sandi Donno) Newsgroups: comp.unix.bsd Subject: [386BSD] Improved port of Microsoft BusMouse driver Message-ID: <sandi.720348398@uctcs> Date: 29 Oct 92 08:46:38 GMT Sender: news@casper.cs.uct.ac.za (news) Organization: Computer Science Department, University of Cape Town Lines: 753 This is a repost of my port of busmouse.v3 to 386bsd, with a few improvements (thanks to Andrew Herbert, andrew@werple.apana.org.au). This shar file contains everything needed to compile the driver, unlike my previous post which was a patchkit. Enjoy! -- Sandi Donno sandi@cs.uct.ac.za # This is a shell archive. Save it in a file, remove anything before # this line, and then unpack it by entering "sh file". Note, it may # create directories; files and directories will be owned by you and # have default permissions. # # This archive contains: # # README.386bsd # bms.c # conf.c.diff # files.i386.diff # isa.h.diff # mouse.h # testmse.c # echo x - README.386bsd sed 's/^X//' >README.386bsd << 'END-of-README.386bsd' XThis driver is a port of the Microsoft busmouse driver for BSD/386 Xby Erik Forsberg (busmouse.v3) to 386bsd. I have not ported the Logitech Xdriver included in this package. X XThe following files are identical to those in the BSD/386 version: Xmouse.h should be placed in /sys/sys Xisa.h.diff patch should be applied to /sys/i386/isa/isa.h X XThe following files/patches replace those supplied with busmouse.v3: Xbms.c should be placed in /sys/sys/i386/isa Xconf.c.diff patch should be applied to /sys/i386/i386/conf.c Xfiles.i386.diff patch should be applied to /sys/i386/conf/files.i386 X (replaces file.i386.diff in busmouse.v3) X XThe following is an example of a suitable line to add in your Xkernel configuration file: X Xdevice bms0 at isa? port "IO_BMS1" tty irq 5 vector bmsintr X XThe testmse program from the 386bsd busmouse package by Rick Macklem, Xrick@snowhite.cis.uoguelph.ca, is useful for testing the mouse in Xblocking mode. To use this program, first mknod /dev/mouse c 14 0. X XIf this works, then X1) rm /dev/mouse X2) mknod /dev/mouse c 14 1 Xto create a non-blocking device suitable for use with X386. X XIf you wish to get hold of busmouse.v3, it can be obtained from Xphysics.su.oz.au, in /XFree86. X386bsd-busmouse.tar.Z can be obtained from athene.uni-paderborn.de, in X/uninstalled/386BSD/386bsd-0.1/unofficial X X -- Sandi Donno (sandi@cs.uct.ac.za) END-of-README.386bsd echo x - bms.c sed 's/^X//' >bms.c << 'END-of-bms.c' X/*- X * Copyright (c) 1992 The Regents of the University of California. X * All rights reserved. X * X * This code is derived from software contributed to Berkeley by X * Erik Forsberg. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * 3. All advertising materials mentioning features or use of this software X * must display the following acknowledgement: X * This product includes software developed by the University of X * California, Berkeley and its contributors. X * 4. Neither the name of the University nor the names of its contributors X * may be used to endorse or promote products derived from this software X * without specific prior written permission. X * X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X * SUCH DAMAGE. X */ X X/* X * Microsoft Bus Mouse driver. X * Written April 26th, 1992 for the BSDI/386 system. X * Please send bugs and enhancements to erik@eab.retix.com X * Copyright 1992, Erik Forsberg. X */ X X/* X * Ported to 386bsd Oct 17, 1992 X * Sandi Donno, Computer Science, University of Cape Town, South Africa X * Please send bug reports to sandi@cs.uct.ac.za X * X * Thanks are also due to Rick Macklem, rick@snowhite.cis.uoguelph.ca - X * although I was only partially successful in getting the alpha release X * of his "driver for the Logitech and ATI Inport Bus mice for use with X * 386bsd and the X386 port" to work with my Microsoft mouse, I nevertheless X * found his code to be an invaluable reference when porting this driver X * to 386bsd. X * X * Thanks also to Andrew Herbert (andrew@werple.apana.org.au) for some X * improvements. X */ X X#include "bms.h" X X#if NBMS > 0 X X#include "param.h" X#include "kernel.h" X#include "systm.h" X#include "buf.h" X#include "malloc.h" X#include "ioctl.h" X#include "tty.h" X#include "file.h" X#include "proc.h" X#include "vnode.h" X#include "mouse.h" X X#include "i386/isa/isa_device.h" X X#define ADDR 0 /* Offset for register select */ X#define DATA 1 /* Offset for InPort data */ X#define IDENT 2 /* Offset for identification register */ X X#define BMSUNIT(dev) (minor(dev) >> 1) X Xint bmsprobe(); Xint bmsattach(); X Xstatic int bmsaddr[NBMS]; /* Base I/O port addresses per unit */ X X#define MSBSZ 1024 /* Output queue size (pwr of 2 is best) */ X Xstruct ringbuf { X int count, first, last; X char queue[MSBSZ]; X}; X Xstatic struct bms_softc { /* Driver status information */ X struct ringbuf inq; /* Input queue */ X struct proc *rsel; /* Process selecting for Input */ X unsigned char state; /* Mouse driver state */ X unsigned char status; /* Mouse button status */ X int x, y; /* accumulated motion in the X,Y axis */ X} bms_softc[NBMS]; X X#define OPEN 1 /* Device is open */ X#define ASLP 2 /* Waiting for mouse data */ X Xstruct isa_driver bmsdriver = X { bmsprobe, bmsattach, "bms" }; X Xint bmsprobe(dvp) X struct isa_device *dvp; X { X int ioport = dvp->id_iobase; X X /* Read identification register to see if present */ X X if (inb(ioport+IDENT) != 0xDE) X return(0); X X /* Seems it was there, reset */ X X outb(ioport+ADDR, 0x87); X return(1); X } X Xint bmsattach(dvp) X struct isa_device *dvp; X { X int unit = dvp->id_unit; X int ioport = dvp->id_iobase; X struct bms_softc *sc = &bms_softc[unit]; X X /* Save I/O base address */ X X bmsaddr[unit] = ioport; X X /* Setup initial state */ X X sc->state = 0; X X /* Done */ X X return(0); X } X Xint bmsopen(dev, flag, fmt, p) X dev_t dev; X int flag, fmt; X struct proc *p; X { X int unit = BMSUNIT(dev); X struct bms_softc *sc; X int ioport; X X /* Validate unit number */ X X if (unit >= NBMS) X return(ENXIO); X X /* Get device data */ X X sc = &bms_softc[unit]; X ioport = bmsaddr[unit]; X X /* If device does not exist */ X X if (ioport == 0) X return(ENXIO); X X /* Disallow multiple opens */ X X if (sc->state & OPEN) X return(ENXIO); X X /* Initialize state */ X X sc->state |= OPEN; X sc->rsel = NULL; X sc->status = 0; X sc->x = 0; X sc->y = 0; X X /* Allocate and initialize a ring buffer */ X X sc->inq.count = sc->inq.first = sc->inq.last = 0; X X /* Setup Bus Mouse */ X X outb(ioport+ADDR, 7); X outb(ioport+DATA, 0x09); X X /* Successful open */ X X return(0); X } X Xint bmsclose(dev, flag, fmt, p) X dev_t dev; X int flag, fmt; X struct proc *p; X { X int unit, ioport; X struct bms_softc *sc; X X /* Get unit and associated info */ X X unit = BMSUNIT(dev); X sc = &bms_softc[unit]; X ioport = bmsaddr[unit]; X X /* Reset Bus Mouse */ X X outb(ioport+ADDR, 0x87); X X /* Complete the close */ X X sc->state &= ~OPEN; X X /* close is almost always successful */ X X return(0); X } X Xint bmsread(dev, uio, flag) X dev_t dev; X struct uio *uio; X int flag; X { X int s, error; X unsigned length; X struct bms_softc *sc; X unsigned char buffer[100]; X X /* Get device information */ X X sc = &bms_softc[BMSUNIT(dev)]; X X /* Block until mouse activity occured */ X X s = spltty(); X while (sc->inq.count == 0) X { X if (minor(dev) & 0x1) X { X splx(s); X return(EWOULDBLOCK); X } X sc->state |= ASLP; X error = tsleep(sc, PZERO | PCATCH, "bmsrea", 0); X if (error != 0) X { X splx(s); X return(error); X } X } X X /* Transfer as many chunks as possible */ X X while (sc->inq.count > 0 && uio->uio_resid > 0) X { X length = min(sc->inq.count, uio->uio_resid); X if (length > sizeof(buffer)) X length = sizeof(buffer); X X /* Remove a small chunk from input queue */ X X if (sc->inq.first + length >= MSBSZ) X { X bcopy(&sc->inq.queue[sc->inq.first], X buffer, MSBSZ - sc->inq.first); X bcopy(sc->inq.queue, &buffer[MSBSZ-sc->inq.first], X length - (MSBSZ - sc->inq.first)); X } X else X bcopy(&sc->inq.queue[sc->inq.first], buffer, length); X X sc->inq.first = (sc->inq.first + length) % MSBSZ; X sc->inq.count -= length; X X X /* Copy data to user process */ X X error = uiomove(buffer, length, uio); X if (error) X break; X } X X sc->x = sc->y = 0; X X /* Allow interrupts again */ X X splx(s); X return(error); X } X Xint bmsioctl(dev, cmd, addr, flag, p) X dev_t dev; X caddr_t addr; X int cmd, flag; X struct proc *p; X { X struct bms_softc *sc; X struct mouseinfo info; X int s, error; X X /* Get device information */ X X sc = &bms_softc[BMSUNIT(dev)]; X X /* Perform IOCTL command */ X X switch (cmd) X { X X case MOUSEIOCREAD: X X /* Dont modify info while calculating */ X X s = spltty(); X X /* Build mouse status octet */ X X info.status = sc->status; X if (sc->x || sc->y) X info.status |= MOVEMENT; X X /* Encode X and Y motion as good as we can */ X X if (sc->x > 127) X info.xmotion = 127; X else if (sc->x < -128) X info.xmotion = -128; X else X info.xmotion = sc->x; X X if (sc->y > 127) X info.ymotion = 127; X else if (sc->y < -128) X info.ymotion = -128; X else X info.ymotion = sc->y; X X /* Reset historical information */ X X sc->x = 0; X sc->y = 0; X sc->status &= ~BUTCHNGMASK; X X /* Allow interrupts and copy result buffer */ X X splx(s); X error = copyout(&info, addr, sizeof(struct mouseinfo)); X break; X X default: X error = EINVAL; X break; X } X X /* Return error code */ X X return(error); X } X Xvoid bmsintr(unit) X int unit; X { X struct bms_softc *sc = &bms_softc[unit]; X int ioport = bmsaddr[unit]; X char x, y, sts; X X /* Freeze InPort registers */ X X outb(ioport+ADDR, 7); X outb(ioport+DATA, 0x29); X X /* Read mouse status */ X X outb(ioport+ADDR, 0); X sts = inb(ioport+DATA); X X /* Check if any movement detected */ X X if (sts & 0x40) X { X outb(ioport+ADDR, 1); X x = inb(ioport+DATA); X outb(ioport+ADDR, 2); X y = inb(ioport+DATA); X if (y == -128) X y = 127; X else X y = -y; X } X else X { X x = 0; X y = 0; X } X X /* Unfreeze InPort Registers (re-enables interrupts) */ X X outb(ioport+ADDR, 7); X outb(ioport+DATA, 0x09); X X /* Update accumulated movements */ X X sc->x += x; X sc->y += y; X X /* Inclusive OR status changes, but always save only last state */ X X sc->status |= sts & BUTCHNGMASK; X sc->status = (sc->status & ~BUTSTATMASK) | (sts & BUTSTATMASK); X X /* If device in use and any change occurred ... */ X X if (sc->state & OPEN && sts & 0x78 && sc->inq.count < (MSBSZ-5)) X { X sts &= BUTSTATMASK; X sc->inq.queue[sc->inq.last++] = 0x80 | (sts ^ BUTSTATMASK); X sc->inq.queue[sc->inq.last++ % MSBSZ] = x; X sc->inq.queue[sc->inq.last++ % MSBSZ] = y; X sc->inq.queue[sc->inq.last++ % MSBSZ] = 0; X sc->inq.queue[sc->inq.last++ % MSBSZ] = 0; X sc->inq.last = sc->inq.last % MSBSZ; X sc->inq.count += 5; X X if (sc->state & ASLP) X { X sc->state &= ~ASLP; X wakeup(sc); X } X if (sc->rsel) X { X selwakeup(sc->rsel, 0); X sc->rsel = NULL; X } X } X } X Xint bmsselect(dev, rw, p) X dev_t dev; X int rw; X struct proc *p; X { X int s, ret; X struct bms_softc *sc = &bms_softc[BMSUNIT(dev)]; X X /* Silly to select for Output */ X X if (rw == FWRITE) X return(0); X X /* Return true if a mouse event available */ X X s = spltty(); X if (sc->inq.count != 0) X ret = 1; X else X { X ret = 0; X sc->rsel = p; X } X X splx(s); X return(ret); X } X X#endif END-of-bms.c echo x - conf.c.diff sed 's/^X//' >conf.c.diff << 'END-of-conf.c.diff' X*** conf.c.orig Sat Oct 17 15:30:58 1992 X--- conf.c Sat Oct 17 15:34:45 1992 X*************** X*** 165,175 **** X #define com_tty NULL X #endif X X int logopen(),logclose(),logread(),logioctl(),logselect(); X X int ttselect(), seltrue(); X X- X struct cdevsw cdevsw[] = X { X { cnopen, cnclose, cnread, cnwrite, /*0*/ X--- 165,185 ---- X #define com_tty NULL X #endif X X+ #include "bms.h" X+ #if NBMS > 0 X+ int bmsopen(),bmsclose(),bmsread(),bmsselect(),bmsioctl(); X+ #else X+ #define bmsopen enxio X+ #define bmsclose enxio X+ #define bmsread enxio X+ #define bmsselect enxio X+ #define bmsioctl enxio X+ #endif X+ X int logopen(),logclose(),logread(),logioctl(),logselect(); X X int ttselect(), seltrue(); X X struct cdevsw cdevsw[] = X { X { cnopen, cnclose, cnread, cnwrite, /*0*/ X*************** X*** 214,219 **** X--- 224,232 ---- X { asopen, asclose, rawread, rawwrite, /*D*/ X asioctl, enodev, nullop, NULL, X seltrue, enodev, asstrategy }, X+ { bmsopen, bmsclose, bmsread, nullop, /*E*/ X+ bmsioctl, enodev, nullop, NULL, X+ bmsselect, enodev, NULL }, X }; X int nchrdev = sizeof (cdevsw) / sizeof (cdevsw[0]); END-of-conf.c.diff echo x - files.i386.diff sed 's/^X//' >files.i386.diff << 'END-of-files.i386.diff' X*** files.i386.orig Sat Oct 17 15:40:39 1992 X--- files.i386 Sat Oct 17 15:40:57 1992 X*************** X*** 21,26 **** X--- 21,27 ---- X i386/isa/isa.c optional isa device-driver X i386/isa/com.c optional com device-driver X i386/isa/npx.c optional npx device-driver X+ i386/isa/bms.c optional bms device-driver X i386/isa/as.c optional as device-driver X i386/i386/db_disasm.c optional ddb X i386/i386/db_interface.c optional ddb END-of-files.i386.diff echo x - isa.h.diff sed 's/^X//' >isa.h.diff << 'END-of-isa.h.diff' X*** isa.h Thu Feb 20 14:26:12 1992 X--- /usr/src/sys/i386/isa/isa.h Mon Apr 27 22:13:39 1992 X*************** X*** 76,82 **** X #define IO_WD1 0x1f0 /* Primary Fixed Disk Controller */ X #define IO_GAME 0x200 /* Game Controller */ X X! /* 0x208 - 0x277 Open */ X X #define IO_LPT2 0x278 /* Parallel Port #2 */ X X--- 76,87 ---- X #define IO_WD1 0x1f0 /* Primary Fixed Disk Controller */ X #define IO_GAME 0x200 /* Game Controller */ X X! /* 0x208 - 0x237 Open */ X! X! #define IO_BMS2 0x238 /* secondary InPort Bus Mouse */ X! #define IO_BMS1 0x23c /* primary InPort Bus Mouse */ X! X! /* 0x240 - 0x277 Open */ X X #define IO_LPT2 0x278 /* Parallel Port #2 */ X END-of-isa.h.diff echo x - mouse.h sed 's/^X//' >mouse.h << 'END-of-mouse.h' X/*- X * Copyright (c) 1990 The Regents of the University of California. X * All rights reserved. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * 3. All advertising materials mentioning features or use of this software X * must display the following acknowledgement: X * This product includes software developed by the University of X * California, Berkeley and its contributors. X * 4. Neither the name of the University nor the names of its contributors X * may be used to endorse or promote products derived from this software X * without specific prior written permission. X * X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X * SUCH DAMAGE. X */ X Xstruct mouseinfo { X unsigned char status; X char xmotion, ymotion; X }; X X#define BUTSTATMASK 0x07 /* Any mouse button down if any bit set */ X#define BUTCHNGMASK 0x38 /* Any mouse button changed if any bit set */ X X#define BUT3STAT 0x01 /* Button 3 down if set */ X#define BUT2STAT 0x02 /* Button 2 down if set */ X#define BUT1STAT 0x04 /* Button 1 down if set */ X#define BUT3CHNG 0x08 /* Button 3 changed if set */ X#define BUT2CHNG 0x10 /* Button 2 changed if set */ X#define BUT1CHNG 0x20 /* Button 1 changed if set */ X#define MOVEMENT 0x40 /* Mouse movement detected */ X X/* Ioctl definitions */ X X#define MOUSEIOC ('M'<<8) X#define MOUSEIOCREAD (MOUSEIOC|60) END-of-mouse.h echo x - testmse.c sed 's/^X//' >testmse.c << 'END-of-testmse.c' X#include <stdio.h> X#include <fcntl.h> X#include <sys/types.h> X#include <sys/time.h> X X/* X * A simple test program for the bus mouse driver. X */ Xmain() { X int mfd, i, j; X fd_set readfd; X char buf[1024]; X extern int errno; X X mfd = open("/dev/mouse", O_RDONLY); X if (mfd < 0) { X fprintf(stderr, "Mouse open err=%d\n", errno); X exit(1); X } X X /* X * Test reading the mouse. X */ X printf("Mouse read test: jiggle mousey please\n"); X for (j = 0; j < 20; j++) { X if (read(mfd, buf, 5) != 5) { X fprintf(stderr, "Mouse read err=%d\n", errno); X exit(1); X } X printf("mse: but=0x%x dx=%d dy=%d\n",buf[0] & 0x7, buf[1], buf[2]); X } X printf("Got 20 mouse inputs\n"); X X /* X * Now test the select syscall for the mouse and stdin. X */ X printf("Mouse select test: type keys and wiggle mouse please\n"); X for (j = 0; j < 50; j++) { X FD_ZERO(&readfd); X FD_SET(0, &readfd); /* stdin */ X FD_SET(mfd, &readfd); /* and mouse */ X i = select(mfd + 1, &readfd, (fd_set *)0, (fd_set *)0, X (struct timeval *)0); X if (i <= 0) { X fprintf(stderr, "Select syscall err=%d\n", errno); X exit(1); X } X if (FD_ISSET(0, &readfd)) { X if ((i = read(0, buf, 1024)) <= 0) { X fprintf(stderr, "Stdin read err=%d\n", errno); X exit(1); X } X buf[i] = '\0'; X printf("kbd: Got %s\n", buf); X } X if (FD_ISSET(mfd, &readfd)) { X if (read(mfd, buf, 5) != 5) { X fprintf(stderr, "Mouse read err=%d\n", errno); X exit(1); X } X printf("mse: but=0x%x dx=%d dy=%d\n",buf[0] & 0x7, buf[1], buf[2]); X } X } X printf("Test done, bye\n"); X} END-of-testmse.c exit