File:  [MW Coherent from dump] / coherent / d / PS2_KERNEL / io.286 / ms.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Wed May 29 04:56:39 2019 UTC (7 years ago) by root
Branches: MarkWilliams, MAIN
CVS tags: relic, HEAD
coherent

/* (-lgl
 * 	COHERENT Driver Kit Version 1.1.0
 * 	Copyright (c) 1982, 1990 by Mark Williams Company.
 * 	All rights reserved. May not be copied without permission.
 -lgl) */
/*
 *	Microsoft bus mouse (rodent) driver.
 */

#include <sys/coherent.h>
#include <sys/con.h>
#include <sys/devices.h>
#include <sys/ms.h>
#include <errno.h>

#define Help(fmt, p)		printf(fmt, p)
#define Help2(fmt, p, q)	printf(fmt, p, q)
#define Diag(fmt, p)		/* Help(fmt, p) */
#define Diag2(fmt, p, q)	/* Help2(fmt, p, q) */

/*
 *	global patchable definitions
 */
unsigned MSPORT  = 0x23C;	/* mouse 8255A registers: */
				/* modified mouse is 0x23C */
				/* Geac modified mouse is 0x230 */
unsigned MSIRQ   = 2;		/* mouse interrupt # */

/*
 *	driver function definitions
 */
int	msload();
int	msunload();
int	msopen();
int	msclose();
int	msioctl();
int	mspoll();
int	msintr();
int	nulldev();
int	nonedev();

/*
 *	configuration table
 */
CON mscon = {
	DFCHR|DFPOL,			/* flags	*/
	MS_MAJOR,			/* major index	*/
	msopen,				/* open		*/
	msclose,			/* close	*/
	nonedev,			/* block	*/
	nonedev,			/* read		*/
	nonedev,			/* write	*/
	msioctl,			/* ioctl	*/
	nulldev,			/* power fail	*/
	nulldev,			/* timeout	*/
	msload,				/* load		*/
	msunload,			/* unload	*/
	mspoll				/* poll		*/
};

/*
 *	ioctl function definitions
 */

int	ms_setup();
int	ms_setcrs();
int	ms_readcrs();
int	ms_setmick();
int	ms_readmick();
int	ms_readbtns();
int	ms_readstat();
int	ms_wait();

int (*ioctls[])() = {
  /*	   0	     1		 2	     3		  4		*/
	ms_setup, ms_setcrs, ms_readcrs, ms_setmick, ms_readmick,

  /*	     5		 6	   7					*/
	ms_readbtns, ms_readstat, ms_wait
};

/*
 *	hardware constants
 */
static	int	porta;			/* 	port A (read/write) */
static	int	portb;			/*	port B (read/write) */
static	int	portc;			/*	port C (read/write) */
static	int	portcm;			/*	control port (write only) */

static	int	u_stts	=  0;		/* changed-status flags */
static	int	u_mask	=  0;		/* user condition mask */

static	event_t	ipolls;

static struct msparms parms, initparm = {
	2, -16, 655, -16, 215, 8, 16
};

static struct mspos crsr, csav, initcrsr = { 320, 100 };

static struct msmick mick, initmick = { 0, 0 };

static struct msbuts buttons, initbuttons = {
	0,
	{	{0, {320, 100}},
		{0, {320, 100}},
		{0, {320, 100}},
		{0, {320, 100}}
	}
};

static	int	ms_inuse = 0;		/* is mouse in use ? */

msload()
{
	int s;

	porta  = MSPORT;
	portb  = MSPORT + 1;
	portc  = MSPORT + 2;
	portcm = MSPORT + 3;

	s = sphi();
	outb( portcm, 0x91 );		/* set 8255A mode 9 */
	outb( portc,  0x10 );		/* disable interrupt */
	setivec( MSIRQ, msintr );	/* set up irq vector */
	spl(s);

	return 0;
}

/*
 * Unload function.
 */
msunload()
{
	clrivec( MSIRQ );		/* release irq vector */
	outb( portcm, 0x91 );		/* set 8255A mode 9 */
	outb( portc,  0x10 );		/* disable interrupt */
}

msopen(dev, mode)
dev_t	dev;
{
	int	s;

	s = sphi(s);
	if (ms_inuse) {
		u.u_error = EDBUSY;
		spl(s);
		return( -1 );
	}

	outb( portcm, 0x91 );			/* set 8255A mode 9 */
	outb( portb,  0x5a );

	if( inb( portb ) != 0x5a) {		/* hardware installed? */
		u.u_error = ENXIO;
		spl(s);
		return( -1 );
	}

	outb( portc, 0x90 );
	inb( porta );
	outb( portc, 0xb0 );
	inb( porta );
	outb( portc, 0xd0 );
	inb( porta );
	outb( portc, 0xf0 );
	inb( porta );
	outb( portc, 0 );		/* clear all mouse registers */

/* set things */
	parms = initparm;
	crsr = csav = initcrsr;
	mick = initmick;
	buttons = initbuttons;
	u_stts = u.u_error = 0;
	ms_inuse = 1;
	spl(s);

	return( 0 );
}

msclose()
{
	int s;

	s = sphi();
	outb( portc, 0x10 );			/* disable interrupt */
	ms_inuse = u.u_error = 0;
	spl(s);
	return( 0 );
}

msioctl( dev, com, vec )
dev_t	dev;
int	com;
char	*vec;
{
	int s;

	s = sphi();
	if (com >= 0 && com < sizeof(ioctls)/sizeof(ioctls[0])) {
		(*ioctls[com])(vec);	/* indirect func call */
		u.u_error = 0;
	} else
		u.u_error = EINVAL;
	spl(s);
	if (u.u_error)
		return( -1 );

	return( 0 );
}

/*
 * Polling routine.
 * [System V.3 Compatible].
 */
mspoll( dev, ev, msec )
dev_t dev;
int ev;
int msec;
{
	ev &= ~POLLPRI;
	ev &= ~POLLOUT;

	/*
	 * No input.
	 */
	if ( (u_stts & u_mask) == 0 ) {
		/*
		 * Enable monitor if blocking poll.
		 */
		if ( msec != 0 ) 
			pollopen( &ipolls );
		/*
		 * Look again to avoid interrupt race.
		 */
		if ( (u_stts & u_mask) == 0 )
			ev &= ~POLLIN;
	}

	return ev;
}

/*
 *	write setup structure
 */
ms_setup( newparm )
struct msparms *newparm;
{
	ukcopy(newparm, &parms, sizeof(struct msparms));
	if (parms.h_mpr == 0)
		parms.h_mpr = 1;
	if (parms.v_mpr == 0)
		parms.v_mpr = 1;
}

/*
 *	write cursor position
 */
ms_setcrs( pos )
struct mspos *pos;
{
	ukcopy(pos, &crsr, sizeof(struct mspos));
	u_stts &= ~MS_S_MOVE;		/* clear u_stts pos bit */
}

/*
 *	read cursor postion
 */
ms_readcrs( pos )
struct mspos *pos;
{
	kucopy(&crsr, pos, sizeof(struct mspos));
	u_stts &= ~MS_S_MOVE;		/* clear u_stts pos bit */
}

/*
 *	write mickey postion
 */
ms_setmick( pos )
struct msmick *pos;
{
	ukcopy(pos, &mick, sizeof(struct msmick));
}

/*
 *	read mickey postion
 */
ms_readmick( pos )
struct msmick *pos;
{
	kucopy(&mick, pos, sizeof(struct msmick));
}

/*
 *	read button status
 */
ms_readbtns( btns )
struct msbuts *btns;
{
	kucopy(&buttons, btns, sizeof(struct msbuts));
	u_stts &= ~MS_S_BUTTONS;		/* clear u_stts button bits */
}

/*
 *	read "changed status" mask
 */
ms_readstat( stat )
int *stat;
{
	kucopy(&u_stts, stat, sizeof(int));
}

/*
 *	wait on "changed status" mask
 */
ms_wait( flag )
int *flag;
{
	ukcopy(flag, &u_mask, sizeof(int));
	while ((u_mask & u_stts) == 0)	/* wait until any bit is on */
		sleep(&u_stts, 0x7fff, 0x7fff, 0);
	u_mask = 0;
}

/*
 *	mouse interrupt service routine
 */
msintr()
{
	static	int h_fpix =  0;			/* fractional pixel */
	static	int v_fpix = 0;				/* ditto */
	int	s, n_l, n_h, h_diff, v_diff, tmp, left, right;

	if (!ms_inuse)			/* dev not open - ignore interrupts */
		return;
	
	s = sphi();
	outb( portc, 0x90 );		/* get horizontal change */
	n_l = inb( porta );
	outb( portc, 0xb0 );
	n_h = inb( porta );
	h_diff = (char) ((n_l & 0x0f) | (n_h << 4));

	outb( portc, 0xd0 );		/* get vertical change */
	n_l = inb( porta );
	outb( portc, 0xf0 );
	n_h = inb( porta );
	v_diff = (char) ((n_l & 0x0f) | (n_h << 4));

	outb( portc, 0 );
	left = right = 0;				/* set button status */
	if (!(n_h & 0x80)) left = MS_L_DOWN;		/* left button.. */
	if ((buttons.bbstat & MS_L_DOWN) ^ left) {
		if (left)
			button(MS_B_L_PRESS,   MS_S_L_PRESS);
		else
			button(MS_B_L_RELEASE, MS_S_L_RELEASE);
	}
	if (!(n_h & 0x20))				/* right button.. */
		right = MS_R_DOWN;
	if ((buttons.bbstat & MS_R_DOWN) ^ right) {
		if (right)
			button(MS_B_R_PRESS,   MS_S_R_PRESS);
		else
			button(MS_B_R_RELEASE, MS_S_R_RELEASE);
	}

	buttons.bbstat = left | right;		/* set new button status */

	if (h_diff || v_diff) {			/* any motion? */
		mick.h_mick += h_diff;		/* yes - update positions */
		mick.v_mick += v_diff;
		if ((abs(h_diff) > parms.accel_t) || (abs(v_diff) > parms.accel_t)) {
			h_diff *= 2;
			v_diff *= 2;
		}

		if (h_diff) {			/* horizontal change */
			tmp   = h_fpix + 8 * h_diff;
			h_fpix = tmp % parms.h_mpr;
			tmp    = crsr.h_crsr + tmp / parms.h_mpr;
			crsr.h_crsr = c_range(tmp, parms.h_cmin, parms.h_cmax);
		}

		if (v_diff) {			/* vertical change */                                                                                                                                                                                           
			tmp   = v_fpix + 8 * v_diff;
			v_fpix = tmp % parms.v_mpr;
			tmp    = crsr.v_crsr + tmp / parms.v_mpr;
			crsr.v_crsr = c_range(tmp, parms.v_cmin, parms.v_cmax);
		}

		if ((crsr.h_crsr != csav.h_crsr) || (crsr.v_crsr != csav.v_crsr)) {
			u_stts |= MS_S_MOVE;
			csav = crsr;
		}
	}

	if (u_stts & u_mask) {
		wakeup(&u_stts);
		if ( ipolls.e_procp )
			pollwake( &ipolls );
	}

	spl(s);
}

/*
 *	update button-press/release data
 */
button( bp, sbit )
int bp;
unsigned sbit;
{
	++buttons.buts[bp].cnt;
	buttons.buts[bp].bpos = crsr;
	u_stts |= sbit;
}

/*
 *	force return value to be within specified range
 */
c_range(c, cmin, cmax)
int	c, cmin, cmax;
{
	if( c < cmin )
		c = cmin;
	else if( c > cmax )
		c = cmax;
	return( c );
}

abs(i)
int i;
{
	if (i < 0)
		return (-i);
	return i;
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.