ATI VGA Wonder mouse driver for SCO System V 3.2

Jim Hoover hoover at cs.UAlberta.CA
Tue May 29 04:29:33 AEST 1990


Here is a mouse driver for those of you with ATI VGA wonder cards
with a busmouse.  I have not tested the xenix version, nor the vpix hooks,
so please send me mail if you do.

The program event.c is the sample test program for using the event driver.

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  busmouse.c event.c
# Wrapped by hoover at swanhills on Tue May 22 19:23:52 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'busmouse.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'busmouse.c'\"
else
echo shar: Extracting \"'busmouse.c'\" \(10724 characters\)
sed "s/^X//" >'busmouse.c' <<'END_OF_FILE'
X/*
X	  Sample driver for ATI VGA Wonder busmouse 
X
X 
X  Only one such mouse per system.  This driver has a tty interface
X  that uses the event line discipline (#2).
X
X  This code was influenced by the sample SCO busmouse event driver in
X	/usr/lib/samples/pack.d/exbm/exbmouse.c
X
X  I didn't test the vpix part, nor the Xenix version.
X 
X  On SCO UNIX System V 3.2, if you have done a
X	mkdev mouse
X  and installed a microsoft busmouse, then you should just have to
X  compile this driver and replace the one in 
X	/etc/conf/pack.d/busmouse
X  Rename the existing busmouse directory, and make a new one that
X  contains only a this Driver.o file.
X
X  Compile it with:
X    cc -O -K -Zp4 -DINKERNEL -M3 -DM_S_UNIX -DVPIX -c busmouse.c -o 
X
X  Here is my System entry for the driver:
X    busmouse    Y   1   3   1   5   238	  23f   0   0
X
X  and my Master entry:
X    busmouse   Iocri   icHO   mous   0   0   1   2   -1
X
X  Relink the kernel, and try it.
X
X  Send all comments and bug reports to:
X	Jim Hoover
X	hoover at cs.ualberta.ca
X*/
X 
X/*
X  Copyright (C) H. James Hoover, 1990.
X
X  This code is freely distributable in source form.  If you distribute
X  it in any other form, you must also distribute the source.
X*/
X
X#ifdef M_S_UNIX
X# include "sys/types.h"
X# include "sys/param.h"
X# include "sys/sysmacros.h"
X# include "sys/conf.h"
X# include "sys/buf.h"
X# include "sys/iobuf.h"
X# include "sys/signal.h"
X# include "sys/errno.h"
X# include "sys/dir.h"
X# include "sys/seg.h"
X# include "sys/page.h"
X# include "sys/user.h"
X# include "sys/inode.h"
X# include "sys/file.h"
X# include "sys/tty.h"
X# include "sys/systm.h"
X# include "sys/busmouse.h"
X# include "sys/immu.h"
X# include "sys/region.h"
X# include "sys/fcntl.h"
X#else
X# include "../h/types.h"
X# include "../h/param.h"
X# include "../h/sysmacros.h"
X# include "../h/conf.h"
X# include "../h/buf.h"
X# include "../h/iobuf.h"
X# include "../h/signal.h"
X# include "../h/errno.h"
X# include "../h/dir.h"
X# ifdef M_I386
X#  include "../h/seg.h"
X#  include "../h/page.h"
X# endif
X# include "../h/user.h"
X# include "../h/inode.h"
X# include "../h/file.h"
X# include "../h/tty.h"
X# include "../h/systm.h"
X# include "../h/fcntl.h"
X#endif
X
X#define ONEBYTE(x)      ((x) > 127 ? 127 : (x) < (-128) ? (-128) : (x))
X
X#ifdef VPIX
X# ifdef M_S_UNIX
X#  include "sys/proc.h"
X#  include "sys/tss.h"
X#  include "sys/v86.h"
X# else
X#  include "../h/proc.h"
X#  include "../h/v86.h"
X# endif
X#endif
X
X/* Minor device numbers */
X#define	MDEV_EVENT		0x00
X#define	MDEV_VPIX		0x01
X
X/* line discipline tty structure */
struct tty mous_tty[1];			
X
static struct {
X	char type;	/* ATI */
X	char mode;	/* VPIX or EVENT */
X	char exclusive;	/* Nonzero if opened exclusively */
X} port;
X
X/* Types */
X#define	T_ATI		0x01
X#define	T_NONE		0x02
X
X/* Values for mode */
X#define	M_CLOSED	0x00
X#define	M_VPIX		0x01
X#define	M_EVENT		0x02
X
X#ifdef VPIX
struct proc *mousectproc;
int	mousxmotion;		/* accumulate mouse x motion */
int	mousymotion;		/* accumulate mouse y motion */
char	mousrupted;		/* interrupted since vpc mouse read */
char	mousestatus;
X#endif
X
X
X#define CRITICAL_SECTION int old_prio
X#define CRITICAL_SECTION_BEGIN old_prio = splcli()
X#define CRITICAL_SECTION_END splx(old_prio)
X
X/* 	
X	mouse hardware registers and commands 
X*/
static int samp_xdelta;		/* data sampled from mouse hardware */
static int samp_ydelta;
static int samp_buttons;
static int prev_buttons = 0;
X
X#define CONTROL_REG 0x23f
X#define STATUS_REG 0x23c
X#define SELECTION_REG 0x23e
X#define ACCESS_REG 0x23b
X#define CONFIG_REG 0x238
X
X#define SELECT_INT_5 0x20
X#define SELECT_PRIM_AND_ENAB 0x18
X
X#define STOP_SAMPLING 0xf
X#define START_SAMPLING  0xe
X
X#define INT_ENAB 0x8
X#define INT_DISAB 0x9
X
X#define SET_LOW 0xb
X#define RESET_LOW 0xa
X#define SET_HI 0xd
X#define RESET_HI 0xc
X
X#define COUNT_MASK 0xf
X
X
X/*
X	Hardware interface routines
X*/
static void set_standby(void) 
X/*
X    pre: mouse initialized
X
X    post: state == STANDBY
X
X    note: critical section with respect to mouse io
X*/    
X{
X    outb(CONTROL_REG, STOP_SAMPLING);
X    outb(CONTROL_REG, INT_DISAB);
X    /* reset the button state to all up */
X    prev_buttons = 0;
X}
X
static void set_active(void) 
X/*
X    pre: mouse initialized
X
X    post: state == ACTIVE
X
X    note: critical section with respect to mouse io
X*/    
X{
X    outb(CONTROL_REG, INT_ENAB);
X    outb(CONTROL_REG, START_SAMPLING);
X}
X
static void readmouse(void)
X/*
X    sample the mouse registers to obtain x,y counter and button status.
X
X    pre: state == ACTIVE
X
X    post: samp_xdelta, samp_ydelta, samp_buttons data read from mouse.  
X	  state == ACTIVE
X
X    note: critical section with repect to mouse io
X
X    The mouse motions samp_xdelta, samp_ydelta are measurements of the 
X    mouse motion since the last position reset.  Their values range 
X    from -128 to +127.
X	for x, left motions are neg, right motions are pos
X	for y, up motions (away from you) are neg, down motions are pos
X    Think of the mouse moving about a screen rather than the x-y plane.
X
X    The right 3 bits of samp_buttons represent lmr (left-middle-right)
X    with the corresponding bit on to indicate button pressed.  All other
X    bits are off.  A two button mouse has no middle button.  A one button
X    mouse has only a middle button?
X*/
X{
X    register signed char xd, yd;
X
X    /* stop sampling */
X    outb(CONTROL_REG, STOP_SAMPLING);
X
X    /* fetch low 4, then hi 4 x bits */
X    outb(CONTROL_REG, RESET_LOW);
X    outb(CONTROL_REG, RESET_HI);
X
X    xd = inb(STATUS_REG) & COUNT_MASK;
X    outb(CONTROL_REG, SET_LOW);
X    xd |= (inb(STATUS_REG) & COUNT_MASK) << 4;
X    samp_xdelta = xd;
X
X    /* fetch hi 4, then low 4 y bits */
X    outb(CONTROL_REG, SET_HI);
X    yd = inb(STATUS_REG) & COUNT_MASK;
X    outb(CONTROL_REG, RESET_LOW);
X    xd = inb(STATUS_REG);
X    yd = (yd << 4) | (xd & COUNT_MASK);
X    samp_ydelta = yd;
X
X    /* fetch the button status */
X    samp_buttons = ~(xd >> 5) & 0x7;
X
X    /* start sampling again */
X    outb(CONTROL_REG, START_SAMPLING);
X}
X
mousinit()
X{
X    int	mousproc(), mousintr();
X
X    /* Initialize data */
X    port.type = T_NONE;		/* mouse is not present */
X    port.mode = M_CLOSED;	/* port is CLOSED */
X    port.exclusive = 0;		/* not opened exclusively */
X
X    /* put mouse into standby mode */
X    set_standby();
X
X    /* We can't check, so just assume the busmouse is installed */
X    port.type = T_ATI;
X
X#ifndef M_S_UNIX
X#define	INTLVL	1
X#define INTVEC  5
X    vecintsw[INTVEC] = mousintr;
X    vecintlev[INTVEC] = INTLVL;
X#endif
X
X    /* Init the tty structure fields to their default values */
X    ttinit(&mous_tty[0]);		
X    /* Satisfy common line discipline */
X    mous_tty[0].t_proc = mousproc;  
X
X    /* ok, we are setup now - hardwired int 5, base 0x238 */
X    printcfg("busmouse", 0x238, 8, 5, -1, "type=ATIbusmouse 1.0");
X}
X
mousopen(dev, mode, id)
dev_t	dev;
int mode, id;
X{
X    struct tty	*tp = &mous_tty[0];
X    char		tmpmode;
X    CRITICAL_SECTION;
X
X    /* Verify that we have a mouse */
X    if (port.type == T_NONE) 
X    {
X	u.u_error = ENXIO;
X	return;
X    }
X
X    port.mode = (minor(dev) == MDEV_VPIX) ? M_VPIX : M_EVENT;
X    port.exclusive = (mode & O_EXCL) ? 1 : 0;
X    tp->t_state |= CARR_ON;			/* let data flow */
X#ifdef VPIX
X    mousectproc = u.u_procp;
X    mousrupted = 0;
X#endif
X    /* 
X     * Call the event line discipline routine l_open as the last 
X     * step in the driver open.  This will initialize a new channel 
X     * for the device and initialize the following fields of struct 
X     * evldsilo (see event.h): silo.handle=-1, silo.count=0, 
X     * silo.oldbuttons=0, and silo.addevent=the event driver 
X     * enqueuing function.
X     */
X    (*linesw[tp->t_line].l_open)(tp); 
X
X    /* start the mouse interrupting */
X    CRITICAL_SECTION_BEGIN;
X    set_active();
X    CRITICAL_SECTION_END;
X}
X
X/*
X * satisfy common line discipline code.
X */
mousproc(tp, cmd)
struct tty *tp;
X{
X    return 0;
X}
X
mousclose(dev, mode)
dev_t dev;
int mode;
X{
X    register struct tty *tp;
X    CRITICAL_SECTION;
X	
X    /* turn off the mouse */
X    CRITICAL_SECTION_BEGIN;
X    set_standby();
X    CRITICAL_SECTION_END;
X
X    tp = &mous_tty[0];
X    /* 
X     * Call the event line discipline routine l_close on last close 
X     * of the device. l_close closes the channel the device was using.
X     */
X    (*linesw[tp->t_line].l_close)(tp);	
X    port.mode = M_CLOSED;
X    port.exclusive = 0;
X    tp->t_state &= ~ISOPEN;
X}
X
mousread()
X{
X    register struct tty *tp = &mous_tty[0];
X    /*
X     * Call the event line discipline routine l_read.  This 
X     * routine is virtually unused and simply returns 0.
X     */
X    (*linesw[tp->t_line].l_read)(tp);
X}
X
mousintr(level)
int level;
X{
X    int	status;
X    struct tty *tp;
X    register char *p;
X    char	tmp;
X
X    if (port.mode == M_CLOSED)	{
X	/* this is a critical section, but interrupts are disabled */
X	set_standby();
X	return;
X    }
X
X    readmouse();
X    /* has the mouse changed state ? */
X    if ( (samp_xdelta == 0) && (samp_ydelta == 0) && 
X    (samp_buttons == prev_buttons) ) {
X	/* no, it hasn't */
X	prev_buttons = samp_buttons;
X	return;
X    }
X    prev_buttons = samp_buttons;
X
X#ifdef VPIX
X    if ( port.mode == M_VPIX ) {
X	mousestatus = samp_buttons;
X	mousxmotion += samp_xdelta;
X	mousymotion += samp_ydelta;
X	if (!mousrupted && mousectproc->p_v86) {
X	    v86setint (mousectproc->p_v86, V86VI_MOUSE);
X	    mousrupted = 1;
X	}
X    } else
X#endif
X    {
X	tp = &mous_tty[0];
X	/* Read three bytes, put them in the tty structure */
X	p = (char*) tp->t_rbuf.c_ptr;
X	p[0] = (char) samp_buttons;
X	p[1] = (unsigned char) samp_xdelta;
X	p[2] = (unsigned char) samp_ydelta;
X
X	tp->t_rbuf.c_count -= 3;       /* read three characters */
X	/* report an event */
X	/*
X	 * Call the event line discipline routine l_input after 
X	 * loading the Rx buffer. l_input calls the busmouse 
X	 * eventizer. The eventizer receives the characters and 
X	 * the count stored in the tty structure (see above).
X	 */
X	(*linesw[tp->t_line].l_input)(tp);
X    }
X}
X
mousioctl(dev,cmd,arg,mode)
dev_t dev;
faddr_t arg;
int cmd, mode;
X{
X    CRITICAL_SECTION;
X    faddr_t	work_arg;
X#ifdef VPIX
X    struct mouseinfo info;
X#endif	
X
X    work_arg = arg;
X#ifndef M_S_UNIX
X# ifdef M_I386
X    if (!IS386()) work_arg=(faddr_t)cvttoaddr(arg);
X# endif
X#endif
X
X    switch(cmd)	{ 
X#ifdef VPIX 
X	case VPC_MOUSE_READ: 
X	    /* prevent mouse interrupts */
X	    CRITICAL_SECTION_BEGIN;
X	    info.status = mousestatus;
X	    info.xmotion = (char) ONEBYTE(mousxmotion);
X	    info.ymotion = (char) ONEBYTE(mousymotion);
X	    mousxmotion = mousymotion = 0;
X	    mousrupted = 0;
X	    CRITICAL_SECTION_END;
X	    if (copyout (&info, work_arg, sizeof(info))) 
X		u.u_error = EFAULT;
X	    break;
X#endif
X	case MOUSEACQUIRE:
X	    mousectproc = u.u_procp;
X	    mousrupted = 0;
X	    break;
X
X	default:	
X	    ttiocom(&mous_tty[0],cmd,arg,mode);
X    }
X    return(0);
X}
END_OF_FILE
if test 10724 -ne `wc -c <'busmouse.c'`; then
    echo shar: \"'busmouse.c'\" unpacked with wrong size!
fi
# end of 'busmouse.c'
fi
if test -f 'event.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'event.c'\"
else
echo shar: Extracting \"'event.c'\" \(2599 characters\)
sed "s/^X//" >'event.c' <<'END_OF_FILE'
X/* 
X** Example event queue program supplied in the C Language Guide.
X*/
X
X/* 
X * This program opens an event queue with a relative device (mouse) 
X * and a string device (keyboard).  It prints out information about 
X * events as they enter the queue.
X *
X * Since the keyboard is put into the event line discipline, we
X * lose line discipline zero functionality like signals.  Therefore
X * the DEL key loses its special meaning.  So we test each 
X * keyboard character against DEL and finish when we see one.
X*/
X
X#include <fcntl.h>
X#include <sys/termio.h>
X#include <stdio.h>
X#include <signal.h>
X#include <sys/machdep.h>
X#include <sys/types.h>
X#include <sys/param.h>
X#include <sys/sysmacros.h>
X#include <sys/page.h>
X#include <sys/event.h>
X#include <mouse.h>
X
X#define DEL 0x7f 
X
char progname[80];
extern int errno;
X
main(argc, argv)
int argc;
char *argv[]; 					
X{
X   int qfd, finish(), report();
X   EVENT *evp;
X   int ret;
X    
X   dmask_t dmask = D_STRING | D_REL | D_BUTTON;
X   extern int ev_errlev;		
X
X   ev_errlev = 1; 			/* Turn on event manager diagnostics */
X   strcpy(progname, argv[0]);
X   signal(SIGINT, finish);
X   signal(SIGSEGV, report);
X   signal(SIGSYS, report);
X   
X   printf("\n");
X   ret = ev_init();
X   printf("init == %d\n", ret);
X   if ( ret < 0 )
X      finish();
X   qfd = ev_open(&dmask);
X   printf("open == %d\n", qfd);
X   if ( qfd < 0 ) 
X      fail("could not open event queue");
X
X   if ( dmask != (D_STRING | D_REL | D_BUTTON)) 
X      fail("could not attach mouse and keyboard");
X   /* Events should be enqueued now */
X   while ( !(ev_block()) ) 	       
X      if ( (evp = ev_read()) != (EVENT *) NULL ) {
X         evprint(evp);
X         ev_pop();
X      }
X   return 0;
X}
X
fail(s)
char *s;
X{
X   extern int errno;
X
X   printf("%s(%d): %s\n", progname, errno, s);
X   finish();
X   return 0;
X}
X
evprint(evp)
XEVENT *evp;
X{
X   static long time = -1;
X
X   if ( time == -1 )
X      time = evp->timestamp;
X   if ( EV_TAG(*evp) & T_STRING ) {
X      printf("time(%d) tag(%d) bufsize(%d) buf(%x)\n",
X              EV_TIME(*evp) - time,  
X              EV_TAG(*evp), 
X              EV_BUFCNT(*evp), 
X              EV_BUF(*evp)[0]);
X      if ( EV_BUF(*evp)[0] == DEL ) 
X         finish();
X   }
X   else {
X      printf("time(%ld) tag(%d) butts(%d) x(%ld) y(%ld)\n",
X         EV_TIME(*evp) - time,
X         EV_TAG(*evp),
X         EV_BUTTONS(*evp),
X         EV_DX(*evp),
X         EV_DY(*evp));
X      if( EV_BUTTONS(*evp) == 7 )
X         finish();
X   }
X   return 0;
X}
X
finish()
X{
X   ev_close();
X   printf("done\n");
X   exit(0);
X}
X
report(s)
int s;
X{
X   printf("got signal %d\n", s);
X   finish(); 
X}
X
END_OF_FILE
if test 2599 -ne `wc -c <'event.c'`; then
    echo shar: \"'event.c'\" unpacked with wrong size!
fi
# end of 'event.c'
fi
echo shar: End of shell archive.
exit 0
--
Prof. Jim Hoover                   | Office +1 403 492 5401 or 5290
Dept. of Computing Science         | FAX    +1 403 492 1071
University of Alberta              | hoover at cs.ualberta.ca
Edmonton, Alberta, Canada T6G 2H1  | 



More information about the Comp.unix.i386 mailing list