xref: /csrg-svn/sys/vax/uba/ps.c (revision 45804)
123334Smckusick /*
229234Smckusick  * Copyright (c) 1982, 1986 Regents of the University of California.
323334Smckusick  * All rights reserved.  The Berkeley software License Agreement
423334Smckusick  * specifies the terms and conditions for redistribution.
523334Smckusick  *
6*45804Sbostic  *	@(#)ps.c	7.6 (Berkeley) 12/16/90
723334Smckusick  */
87296Ssam 
97296Ssam /*
1023511Ssam  * Evans and Sutherland Picture System 2 driver -- Bill Reeves.
117296Ssam  */
127296Ssam 
137296Ssam /*
147296Ssam  *	Still to be done:
157296Ssam  *		WAIT_HIT
167296Ssam  */
177296Ssam 
187296Ssam #include "ps.h"
197296Ssam #if NPS > 0
207296Ssam 
217296Ssam #define EXTERNAL_SYNC
227296Ssam 
23*45804Sbostic #include "../include/pte.h"
249776Ssam 
25*45804Sbostic #include "sys/param.h"
26*45804Sbostic #include "sys/systm.h"
27*45804Sbostic #include "sys/ioctl.h"
28*45804Sbostic #include "sys/map.h"
29*45804Sbostic #include "sys/buf.h"
30*45804Sbostic #include "sys/conf.h"
31*45804Sbostic #include "sys/user.h"
32*45804Sbostic #include "sys/uio.h"
337296Ssam 
3417075Sbloom #include "ubareg.h"
3517075Sbloom #include "ubavar.h"
3617075Sbloom #include "psreg.h"
378477Sroot 
3825472Ssam int	psprobe(), psattach(), psextsync();
3925472Ssam int	psclockintr(), pssystemintr(), psdeviceintr(), psdmaintr();
407296Ssam struct	uba_device *psdinfo[NPS];
417296Ssam u_short	psstd[] = { 0 };
427296Ssam struct	uba_driver psdriver =
437296Ssam     { psprobe, 0, psattach, 0, psstd, "ps", psdinfo };
447296Ssam 
457296Ssam #define	PSUNIT(dev)	(minor(dev))
467296Ssam 
4725476Ssam #define MAXAUTOREFRESH	4
4825476Ssam #define MAXAUTOMAP	4
4925476Ssam #define MAXDBSIZE	(0177777/2)
507296Ssam 
5125476Ssam #define PSPRI		(PZERO+1)
527296Ssam 
5325476Ssam #define PSWAIT(psaddr) { \
5425476Ssam 	register short i = 20000, j; \
5525476Ssam 	while (i-- != 0 && ((j = psaddr->ps_iostat) & DIOREADY) == 0) \
5625476Ssam 		;\
5725476Ssam }
587296Ssam 
5925476Ssam struct psrefresh {
6025476Ssam 	enum {
6125476Ssam 		SINGLE_STEP_RF,
6225476Ssam 		AUTO_RF,
6325476Ssam 		TIME_RF
6425476Ssam 	} state;
6525476Ssam 	enum {
6625476Ssam 		RUNNING_RF,
6725476Ssam 		SYNCING_RF,
6825476Ssam 		WAITING_MAP,
6925476Ssam 		STOPPED_RF
7025476Ssam 	} mode;
7125476Ssam 	u_short	sraddrs[MAXAUTOREFRESH];
7225476Ssam 	short	nsraddrs;
7325476Ssam 	short	srcntr;
7425476Ssam 	char	waiting;
7525476Ssam 	char	stop;
7625476Ssam 	int	icnt;
7725476Ssam 	int	timecnt;
7825476Ssam };
7925476Ssam 
8025476Ssam struct psdbuffer {
8125476Ssam 	enum {
8225476Ssam 		ON_DB,
8325476Ssam 		OFF_DB
8425476Ssam 	} state;
8525476Ssam 	u_short	dbaddrs[2];
8625476Ssam 	u_short	dbsize;
8725476Ssam 	short	rbuffer;
8825476Ssam };
8925476Ssam 
9025476Ssam struct psmap {
9125476Ssam 	enum {
9225476Ssam 		SINGLE_STEP_MAP,
9325476Ssam 		AUTO_MAP
9425476Ssam 	} state;
9525476Ssam 	enum {
9625476Ssam 		RUNNING_MAP,
9725476Ssam 		WAITING_RF,
9825476Ssam 		WAITING_START,
9925476Ssam 		STOPPED_MAP
10025476Ssam 	} mode;
10125476Ssam 	u_short	maddrs[MAXAUTOMAP];
10225476Ssam 	short	nmaddrs;
10325476Ssam 	short	mcntr;
10425476Ssam 	short	outputstart;
10525476Ssam 	char	waiting;
10625476Ssam 	char	stop;
10725476Ssam 	int	icnt;
10825476Ssam };
10925476Ssam 
11025476Ssam /*
11125476Ssam  * PS2 software state.
11225476Ssam  */
1137296Ssam struct ps {
11425476Ssam 	char	ps_open;		/* device is open */
11525476Ssam 	uid_t 	ps_uid;			/* uid of device owner */
11625476Ssam 	struct	psrefresh ps_refresh;	/* refresh state */
11725476Ssam 	struct	psdbuffer ps_dbuffer;	/* double buffering state */
11825476Ssam 	struct	psmap ps_map;		/* segment map state */
11925476Ssam 	int	ps_clockticks;		/* clock ints between refresh */
12025476Ssam 	int	ps_clockmiss;		/* clock ints w/o refresh */
12125476Ssam 	int	ps_clockcnt;		/* count of clock interrupts */
12225476Ssam 	int	ps_hitcnt;		/* count of hit interrupts */
12325476Ssam 	int	ps_strayintr;		/* count of stray interrupts */
12425476Ssam 	int	ps_icnt;		/* count of system interrupts */
12525476Ssam /* BEGIN GROT */
12625476Ssam 	int	ps_lastrequest;
12725476Ssam 	int	ps_lastrequest2;
12825476Ssam 	int	ps_lastfunnyrequest;
12925476Ssam 	int	ps_funnycnt;
13025476Ssam /* END GROT */
1317296Ssam } ps[NPS];
1327296Ssam 
1337296Ssam psprobe(reg)
1347296Ssam 	caddr_t reg;
1357296Ssam {
1367296Ssam 	register int br, cvec;
13725476Ssam 	register struct psdevice *psaddr = (struct psdevice *)reg;
1387296Ssam 
13925472Ssam #ifdef lint
14025472Ssam 	br = 0; cvec = br; br = cvec;
14125472Ssam 	psclockintr((dev_t)0); pssystemintr((dev_t)0);
14225472Ssam 	psdeviceintr((dev_t)0); psdmaintr((dev_t)0);
14325472Ssam 	psextsync(0, 0);
14425472Ssam #endif
1457296Ssam 	psaddr->ps_iostat = PSRESET;
1467296Ssam 	DELAY(200);
1477296Ssam 	psaddr->ps_addr = RTCIE;
14825476Ssam 	PSWAIT(psaddr); psaddr->ps_data = 01;
1497296Ssam 	psaddr->ps_iostat = PSIE;
1507296Ssam 	psaddr->ps_addr = RTCSR;
15125476Ssam 	PSWAIT(psaddr); psaddr->ps_data = SYNC|RUN;
1527296Ssam 	DELAY(200000);
1537296Ssam 	psaddr->ps_addr = RTCREQ;
15425476Ssam 	PSWAIT(psaddr); psaddr->ps_data = 01;
1557296Ssam 	psaddr->ps_iostat = 0;
1567296Ssam 	psaddr->ps_iostat = PSRESET;
1577418Skre 	return (sizeof (struct psdevice));
1587296Ssam }
1597296Ssam 
1607296Ssam /*ARGSUSED*/
1617296Ssam psattach(ui)
16225472Ssam 	struct uba_device *ui;
1637296Ssam {
1648572Sroot 
1657296Ssam }
1667296Ssam 
1677296Ssam psopen(dev)
1687296Ssam 	dev_t dev;
1697296Ssam {
1707296Ssam 	register struct ps *psp;
1717296Ssam 	register struct uba_device *ui;
1727296Ssam 	register int unit = PSUNIT(dev);
1737296Ssam 
1748572Sroot 	if (unit >= NPS || (psp = &ps[minor(dev)])->ps_open ||
1758572Sroot 	    (ui = psdinfo[unit]) == 0 || ui->ui_alive == 0)
1768572Sroot 		return (ENXIO);
1777296Ssam 	psp->ps_open = 1;
1787296Ssam 	psp->ps_uid = u.u_uid;
1797296Ssam 	psp->ps_strayintr = 0;
1807296Ssam 	psp->ps_refresh.state = SINGLE_STEP_RF;
18125472Ssam 	psp->ps_refresh.mode = STOPPED_RF;
1827296Ssam 	psp->ps_refresh.waiting = 0;
1837296Ssam 	psp->ps_refresh.stop = 0;
1847296Ssam 	psp->ps_dbuffer.state = OFF_DB;
1857296Ssam 	psp->ps_map.state = SINGLE_STEP_MAP;
18625472Ssam 	psp->ps_map.mode = STOPPED_MAP;
1877296Ssam 	psp->ps_map.waiting = 0;
1887296Ssam 	psp->ps_map.stop = 0;
18925476Ssam 	psp->ps_clockticks = 0;
19025476Ssam 	psp->ps_clockmiss = 0;
19125476Ssam 	psp->ps_refresh.icnt = psp->ps_map.icnt = psp->ps_clockcnt = 0;
19225476Ssam 	psp->ps_hitcnt = 0;
19314600Ssam 	psp->ps_icnt = 0;
1947296Ssam 	maptouser(ui->ui_addr);
1958572Sroot 	return (0);
1967296Ssam }
1977296Ssam 
1987296Ssam psclose(dev)
1997296Ssam 	dev_t dev;
2007296Ssam {
2017296Ssam 	register struct psdevice *psaddr =
20225476Ssam 	    (struct psdevice *)psdinfo[PSUNIT(dev)]->ui_addr;
2037296Ssam 
2047296Ssam 	ps[PSUNIT(dev)].ps_open = 0;
20525476Ssam 	psaddr->ps_iostat = 0;			 /* clear IENABLE */
20625476Ssam 	PSWAIT(psaddr); psaddr->ps_addr = RFSR;	 /* set in auto refresh mode */
20725476Ssam 	PSWAIT(psaddr); psaddr->ps_data = AUTOREF;
20825472Ssam 	unmaptouser((caddr_t)psaddr);
20940728Skarels 	return (0);
2107296Ssam }
2117296Ssam 
2127296Ssam /*ARGSUSED*/
2137730Sroot psread(dev, uio)
2147296Ssam 	dev_t dev;
2157730Sroot 	struct uio *uio;
2167296Ssam {
2177296Ssam }
2187296Ssam 
2197296Ssam /*ARGSUSED*/
2207730Sroot pswrite(dev, uio)
2217296Ssam 	dev_t dev;
2227730Sroot 	struct uio *uio;
2237296Ssam {
2247296Ssam }
2257296Ssam 
2267296Ssam /*ARGSUSED*/
2277632Ssam psioctl(dev, cmd, data, flag)
2287632Ssam 	register caddr_t data;
2297296Ssam {
2307296Ssam 	register struct uba_device *ui = psdinfo[PSUNIT(dev)];
2317296Ssam 	register struct ps *psp = &ps[PSUNIT(dev)];
2327632Ssam 	int *waddr = *(int **)data;
23340728Skarels 	int n, arg, i, error = 0;
2347296Ssam 
2357296Ssam 	switch (cmd) {
2367632Ssam 
2377632Ssam 	case PSIOGETADDR:
2387632Ssam 		*(caddr_t *)data = ui->ui_addr;
2397296Ssam 		break;
2407632Ssam 
2417632Ssam 	case PSIOAUTOREFRESH:
24225472Ssam 		n = fuword((caddr_t)waddr++);
2438572Sroot 		if (n == -1)
2448572Sroot 			return (EFAULT);
2458572Sroot 		if (n < 0 || n > MAXAUTOREFRESH)
2468572Sroot 			return (EINVAL);
2478572Sroot 		for (i = 0; i < n; i++) {
24825472Ssam 			if ((arg = fuword((caddr_t)waddr++)) == -1)
2498572Sroot 				return (EFAULT);
2508572Sroot 			psp->ps_refresh.sraddrs[i] = arg;
2517296Ssam 		}
2528572Sroot 		psp->ps_refresh.state = AUTO_RF;
2538572Sroot 		psp->ps_refresh.nsraddrs = n;
2548572Sroot 		psp->ps_refresh.srcntr = 0;
2558572Sroot 		psp->ps_refresh.mode = WAITING_MAP;
2567296Ssam 		break;
2577632Ssam 
2587632Ssam 	case PSIOAUTOMAP:
25925472Ssam 		n = fuword((caddr_t)waddr++);
2608572Sroot 		if (n == -1)
2618572Sroot 			return (EFAULT);
2628572Sroot 		if (n < 0 || n > MAXAUTOMAP)
2638572Sroot 			return (EINVAL);
2648572Sroot 		for (i = 0; i < n; i++) {
26525472Ssam 			if ((arg = fuword((caddr_t)waddr++)) == -1)
2668572Sroot 				return (EFAULT);
2678572Sroot 			psp->ps_map.maddrs[i] = arg;
2687296Ssam 		}
26925472Ssam 		if ((arg = fuword((caddr_t)waddr++)) == -1)
2708572Sroot 			return (EFAULT);
2718572Sroot 		psp->ps_map.outputstart = arg;
2728572Sroot 		psp->ps_map.state = AUTO_MAP;
2738572Sroot 		psp->ps_map.nmaddrs = n;
2748572Sroot 		psp->ps_map.mcntr = 0;
2758572Sroot 		psp->ps_map.mode = WAITING_START;
2767296Ssam 		break;
2777632Ssam 
2787632Ssam 	case PSIOSINGLEREFRESH:
2797296Ssam 		psp->ps_refresh.state = SINGLE_STEP_RF;
2807296Ssam 		break;
2817632Ssam 
2827632Ssam 	case PSIOSINGLEMAP:
2837296Ssam 		psp->ps_map.state = SINGLE_STEP_MAP;
2847296Ssam 		break;
2857632Ssam 
2867632Ssam 	case PSIODOUBLEBUFFER:
28725472Ssam 		if ((arg = fuword((caddr_t)waddr++)) == -1)
2888572Sroot 			return (EFAULT);
2898572Sroot 		psp->ps_dbuffer.dbaddrs[0] = arg;
29025472Ssam 		if ((arg = fuword((caddr_t)waddr++)) == -1)
2918572Sroot 			return (EFAULT);
2928572Sroot 		if (arg <= 0 || arg > MAXDBSIZE)
2938572Sroot 			return (EINVAL);
2948572Sroot 		psp->ps_dbuffer.dbsize = arg;
29525476Ssam 		psp->ps_dbuffer.dbaddrs[1] = psp->ps_dbuffer.dbaddrs[0]+arg;
2968572Sroot 		psp->ps_dbuffer.state = ON_DB;
2978572Sroot 		psp->ps_dbuffer.rbuffer = 0;
2987296Ssam 		break;
2997632Ssam 
3007632Ssam 	case PSIOSINGLEBUFFER:
3017296Ssam 		psp->ps_dbuffer.state = OFF_DB;
3027296Ssam 		break;
3037632Ssam 
30414600Ssam 	case PSIOTIMEREFRESH:
30514600Ssam 		if (psp->ps_refresh.state != SINGLE_STEP_RF)
30625476Ssam 			return (EINVAL);
30725472Ssam 		if ((arg = fuword((caddr_t)waddr++)) == -1)
30825476Ssam 			return (EFAULT);
30914600Ssam 		psp->ps_refresh.state = TIME_RF;
31014600Ssam 		psp->ps_refresh.timecnt = arg;
31114600Ssam 		break;
31214600Ssam 
3137632Ssam 	case PSIOWAITREFRESH:
3148572Sroot 		if (psp->ps_refresh.mode != RUNNING_RF)	/* not running */
31525476Ssam 			return (0);			/* dont wait */
3168572Sroot 		/* fall into ... */
3177632Ssam 
31814600Ssam 	case PSIOSTOPREFRESH:
31914600Ssam 		if (cmd == PSIOSTOPREFRESH) {
32025476Ssam 			if (psp->ps_refresh.mode == STOPPED_RF &&
32125476Ssam 			    psp->ps_refresh.state != TIME_RF)
32214600Ssam 				return (0);
3237296Ssam 			psp->ps_refresh.stop = 1;
32414600Ssam 		}
32525476Ssam 		(void) spl5();
3267296Ssam 		psp->ps_refresh.waiting = 1;
3278572Sroot 		while (psp->ps_refresh.waiting)
32840728Skarels 			if (error = tsleep(&psp->ps_refresh.waiting,
32940728Skarels 			    PSPRI | PCATCH, devwait, 0))
33040728Skarels 				break;
33125476Ssam 		(void) spl0();
33240728Skarels 		if (error)
33340728Skarels 			return (error);
33414600Ssam 		if (cmd == PSIOSTOPREFRESH)
33514600Ssam 			psp->ps_refresh.mode = STOPPED_RF;
33614600Ssam 		if (psp->ps_refresh.state == TIME_RF)
33714600Ssam 			psp->ps_refresh.state = SINGLE_STEP_RF;
3387296Ssam 		break;
3397632Ssam 
3407632Ssam 	case PSIOWAITMAP:
3418572Sroot 		if (psp->ps_map.mode != RUNNING_MAP)	/* not running */
34225476Ssam 			return (0);			/* dont wait */
3438572Sroot 		/* fall into ... */
3447632Ssam 
3457632Ssam 	case PSIOSTOPMAP:
34614600Ssam 		if (cmd == PSIOSTOPMAP)
3477296Ssam 			psp->ps_map.stop = 1;
34825476Ssam 		(void) spl5();
3497296Ssam 		psp->ps_map.waiting = 1;
3508572Sroot 		while (psp->ps_map.waiting)
35140728Skarels 			if (error = tsleep(&psp->ps_map.waiting, PSPRI | PCATCH,
35240728Skarels 			    devwait, 0))
35340728Skarels 				break;
35425476Ssam 		(void) spl0();
3557296Ssam 		break;
3567632Ssam 
3577296Ssam 	default:
3588572Sroot 		return (ENOTTY);
3597296Ssam 		break;
3607296Ssam 	}
36140728Skarels 	return (error);
3627296Ssam }
3637296Ssam 
36425476Ssam #define SAVEPSADDR(psaddr, savepsaddr) { \
36525476Ssam 	register short i, xx1; \
36626368Skarels 	xx1 = splclock(); \
36725476Ssam 	i = psaddr->ps_addr; \
36825476Ssam 	while ((psaddr->ps_iostat & DIOREADY) == 0) \
36925476Ssam 		; \
37025476Ssam 	savepsaddr = psaddr->ps_data; \
37125476Ssam 	splx(xx1); \
37225476Ssam }
37325476Ssam #define RESTORPSADDR(psaddr, savepsaddr) { \
37425476Ssam 	register short xx2; \
37526368Skarels 	xx2 = splclock(); \
37625476Ssam 	while ((psaddr->ps_iostat & DIOREADY) == 0) \
37725476Ssam 		;\
37825476Ssam 	psaddr->ps_addr = savepsaddr; \
37925476Ssam 	splx(xx2); \
38025476Ssam }
3817296Ssam 
3827296Ssam psclockintr(dev)
3837296Ssam 	dev_t dev;
3847296Ssam {
3857296Ssam 	register struct psdevice *psaddr =
38625476Ssam 	    (struct psdevice *)psdinfo[PSUNIT(dev)]->ui_addr;
3877296Ssam 	register struct ps *psp = &ps[PSUNIT(dev)];
3887296Ssam 	int savepsaddr;
3897296Ssam 
3908572Sroot 	if (!psp->ps_open)
3917296Ssam 		return;
39225476Ssam 	psp->ps_clockcnt++;
39325476Ssam 	SAVEPSADDR(psaddr, savepsaddr);
3947296Ssam #ifndef EXTERNAL_SYNC
3958572Sroot 	if (psp->ps_refresh.state == AUTO_RF) {
39625476Ssam 		if (psp->ps_refresh.mode == SYNCING_RF &&
39725476Ssam 		    psp->ps_refresh.state != TIME_RF) {
39825472Ssam 			(void) psrfnext(psp, psaddr);
3997296Ssam 		} else {
40025476Ssam 			psp->ps_clockticks++;
40125476Ssam 			psp->ps_clockmiss++;
4027296Ssam 		}
4037296Ssam 	}
4047296Ssam #endif
40525476Ssam 	PSWAIT(psaddr); psaddr->ps_addr = RTCREQ;
40625476Ssam 	PSWAIT(psaddr); psaddr->ps_data = 01;	/* clear the request bits */
40725476Ssam 	RESTORPSADDR(psaddr, savepsaddr);
4087296Ssam }
4097296Ssam 
4107296Ssam /*ARGSUSED*/
4117296Ssam pssystemintr(dev)
4127296Ssam 	dev_t dev;
4137296Ssam {
4147296Ssam 	register struct psdevice *psaddr =
41525476Ssam 	    (struct psdevice *)psdinfo[PSUNIT(dev)]->ui_addr;
4167296Ssam 	register struct ps *psp = &ps[PSUNIT(dev)];
41725476Ssam 	short request, tmp;
4187296Ssam 	register int savepsaddr, x;
4197296Ssam 
4208572Sroot 	if (!psp->ps_open)
4217296Ssam 		return;
42214600Ssam 	psp->ps_icnt++;
42325476Ssam 	SAVEPSADDR(psaddr, savepsaddr);
42425476Ssam 	PSWAIT(psaddr); psaddr->ps_addr = SYSREQ;
42525476Ssam 	PSWAIT(psaddr); request = psaddr->ps_data;
42625472Ssam 	request = request&0377;
42725476Ssam 	psp->ps_lastrequest2 = psp->ps_lastrequest;
42825476Ssam 	psp->ps_lastrequest = request;
42925476Ssam 	if (request &~ (HALT_REQ|RFSTOP_REQ|HIT_REQ)) {
43025476Ssam 		psp->ps_lastfunnyrequest = request;
43125476Ssam 		psp->ps_funnycnt++;
43225472Ssam 	}
43325476Ssam 	PSWAIT(psaddr); psaddr->ps_addr = SYSREQ;
43425476Ssam 	tmp = request&(~(HALT_REQ|MOSTOP_REQ));	/* acknowledge */
43525476Ssam 	PSWAIT(psaddr); psaddr->ps_data = tmp;
4367296Ssam 
4378572Sroot 	if (request & (MOSTOP_REQ|HALT_REQ)) {	/* Map stopped */
4387296Ssam 		psp->ps_map.icnt++;
43925476Ssam 		psmapstop(psaddr, psp, request);/* kill it dead */
4408572Sroot 		if (psp->ps_map.waiting) {
4417296Ssam 			psp->ps_map.waiting = 0;
4427296Ssam 			wakeup(&psp->ps_map.waiting);
4438572Sroot 			if (psp->ps_map.stop) {
4447296Ssam 				psp->ps_map.stop = 0;
4457296Ssam 				goto tryrf;
4467296Ssam 			}
4477296Ssam 		}
44825476Ssam 		if (psp->ps_map.state == AUTO_MAP && !psmapnext(psp, psaddr)) {
44925472Ssam 			psp->ps_map.mcntr = 0;
45025472Ssam 			/* prepare for next round */
45125472Ssam 			pssetmapbounds(psp, psaddr);
45225472Ssam 			if (psp->ps_refresh.state == AUTO_RF) {
45325476Ssam 				if (psp->ps_refresh.mode == WAITING_MAP){
4548572Sroot 					if (psp->ps_dbuffer.state == ON_DB)
4557296Ssam 						/* fill other db */
4567296Ssam 						psdbswitch(psp, psaddr);
4577296Ssam 					else
4587296Ssam 						psp->ps_map.mode = WAITING_RF;
45925472Ssam #ifdef EXTERNAL_SYNC
46026368Skarels 					x = splclock();
46125472Ssam #endif
46225472Ssam 					(void) psrfnext(psp, psaddr);
46325472Ssam #ifdef EXTERNAL_SYNC
46425472Ssam 					splx(x);
46525472Ssam #endif
4667296Ssam 				} else
4677296Ssam 					psp->ps_map.mode = WAITING_RF;
46825472Ssam 			} else {	/* no auto refresh */
46925472Ssam 				if (psp->ps_dbuffer.state == ON_DB)
47025472Ssam 					/* fill other db */
47125472Ssam 					psdbswitch(psp, psaddr);
47225472Ssam 				else
47325472Ssam 					(void) psmapnext(psp, psaddr);
4747296Ssam 			}
47525472Ssam 		}
4767296Ssam 	}
4777296Ssam tryrf:
4788572Sroot 	if (request & RFSTOP_REQ) {		/* Refresh stopped */
4797296Ssam 		psp->ps_refresh.icnt++;
48014600Ssam 		if (psp->ps_refresh.state == TIME_RF)
48125476Ssam 			if (--psp->ps_refresh.timecnt > 0)
48214600Ssam 				goto tryhit;
4837296Ssam 		psrfstop(psaddr, psp);
4848572Sroot 		if (psp->ps_refresh.waiting) {
4857296Ssam 			psp->ps_refresh.waiting = 0;
4867296Ssam 			wakeup(&psp->ps_refresh.waiting);
4878572Sroot 			if (psp->ps_refresh.stop) {
4887296Ssam 				psp->ps_refresh.stop = 0;
4897296Ssam 				goto tryhit;
4907296Ssam 			}
4917296Ssam 		}
4928572Sroot 		if (psp->ps_refresh.state == AUTO_RF)
4938572Sroot 			if (!psrfnext(psp, psaddr)) {	/* at end of refresh cycle */
4948572Sroot 				if (psp->ps_map.state == AUTO_MAP &&
49525476Ssam 				    psp->ps_map.mode == WAITING_RF) {
4968572Sroot 					if (psp->ps_dbuffer.state == ON_DB)
4977296Ssam 						psdbswitch(psp, psaddr);
4987296Ssam 					else
49925472Ssam 						(void) psmapnext(psp, psaddr);
5007296Ssam 				}
5017296Ssam 				psp->ps_refresh.srcntr = 0;
5027296Ssam #ifdef EXTERNAL_SYNC
50326368Skarels 				x = splclock();
5047296Ssam #endif
50525472Ssam 				psp->ps_refresh.mode = SYNCING_RF;
50625476Ssam 				if (psp->ps_clockticks)
50725472Ssam 					(void) psrfnext(psp, psaddr);
50825476Ssam 				psp->ps_clockticks = 0;
5097296Ssam #ifdef EXTERNAL_SYNC
5107296Ssam 				splx(x);
5117296Ssam #endif
5127296Ssam 			}
5137296Ssam 	}
5147296Ssam tryhit:
51525476Ssam 	if (request & HIT_REQ)			/* Hit request */
51625476Ssam 		psp->ps_hitcnt++;
5178572Sroot 	if (request == 0)
5187296Ssam 		psp->ps_strayintr++;
51925476Ssam 	RESTORPSADDR(psaddr, savepsaddr);
5207296Ssam }
5217296Ssam 
5227296Ssam psrfnext(psp, psaddr)
5237296Ssam 	register struct ps *psp;
5247296Ssam 	register struct psdevice *psaddr;
5257296Ssam {
52625476Ssam 	u_short start, last;
5277296Ssam 
52825476Ssam 	if (psp->ps_refresh.srcntr < psp->ps_refresh.nsraddrs) {
5297296Ssam 		psrfstart(psp->ps_refresh.sraddrs[psp->ps_refresh.srcntr++],
53025476Ssam 		    0, psp, psaddr);
53125476Ssam 		return (1);
53225476Ssam 	}
53325476Ssam 	if (psp->ps_refresh.srcntr == psp->ps_refresh.nsraddrs &&
53425476Ssam 	    psp->ps_dbuffer.state == ON_DB) {
53525472Ssam 		start = psp->ps_dbuffer.dbaddrs[psp->ps_dbuffer.rbuffer];
53625472Ssam 		last = start+psp->ps_dbuffer.dbsize;
53725472Ssam 		psrfstart(start, last, psp, psaddr);
5387296Ssam 		psp->ps_refresh.srcntr++;	/* flag for after dbuffer */
53925476Ssam 		return (1);
54025476Ssam 	}
54125476Ssam 	return (0);
5427296Ssam }
5437296Ssam 
54425472Ssam psrfstart(dfaddr, last, psp, psaddr)
54525476Ssam 	u_short dfaddr, last;
5467296Ssam 	register struct ps *psp;
5477296Ssam 	register struct psdevice *psaddr;
5487296Ssam {
54925476Ssam 	short dummy;
5507296Ssam 
55125476Ssam 	PSWAIT(psaddr); psaddr->ps_addr = RFASA;
55225476Ssam 	PSWAIT(psaddr); psaddr->ps_data = dfaddr;
55325476Ssam 	PSWAIT(psaddr);
55425476Ssam 	if (last != 0)
55525472Ssam 		psaddr->ps_data = last;
55625472Ssam 	else
55725472Ssam 		dummy = psaddr->ps_data;/* just access to get to status reg */
55825476Ssam 	PSWAIT(psaddr); psaddr->ps_data = RFSTART;	/* may want | here */
5597296Ssam 	psp->ps_refresh.mode = RUNNING_RF;
5607296Ssam }
5617296Ssam 
56225472Ssam /*ARGSUSED*/
5637296Ssam psrfstop(psaddr, psp)
5647296Ssam 	register struct psdevice *psaddr;
5657296Ssam 	register struct ps *psp;
5667296Ssam {
5677296Ssam 
56825476Ssam 	PSWAIT(psaddr); psaddr->ps_addr = RFSR;
56925476Ssam 	PSWAIT(psaddr); psaddr->ps_data = 0;
5707296Ssam }
5717296Ssam 
5727296Ssam psdbswitch(psp, psaddr)
5737296Ssam 	register struct ps *psp;
5747296Ssam 	register struct psdevice *psaddr;
5757296Ssam {
5767296Ssam 
5777296Ssam 	psp->ps_dbuffer.rbuffer = !psp->ps_dbuffer.rbuffer;
5787296Ssam 	pssetmapbounds(psp, psaddr);
57925472Ssam 	(void) psmapnext(psp, psaddr);
5807296Ssam }
5817296Ssam 
5827296Ssam psmapnext(psp, psaddr)
5837296Ssam 	register struct ps *psp;
5847296Ssam 	register struct psdevice *psaddr;
5857296Ssam {
5867296Ssam 
58725476Ssam 	if (psp->ps_map.mcntr < psp->ps_map.nmaddrs) {
58825476Ssam 		psmapstart(psp->ps_map.maddrs[psp->ps_map.mcntr++],
58925476Ssam 		    psp, psaddr);
59025476Ssam 		return (1);
59125476Ssam 	}
59225476Ssam 	return (0);
5937296Ssam }
5947296Ssam 
5957296Ssam pssetmapbounds(psp, psaddr)
5967296Ssam 	register struct ps *psp;
5977296Ssam 	register struct psdevice *psaddr;
5987296Ssam {
59925476Ssam 	u_short start, last;
6007296Ssam 
60125476Ssam 	PSWAIT(psaddr); psaddr->ps_addr = MAOL;
60225476Ssam 	PSWAIT(psaddr);
6038572Sroot 	if (psp->ps_dbuffer.state == ON_DB) {
60425472Ssam 		start = psp->ps_dbuffer.dbaddrs[!psp->ps_dbuffer.rbuffer];
60525472Ssam 		last = start+psp->ps_dbuffer.dbsize-2;   /* 2 for halt cmd */
60625472Ssam 		psaddr->ps_data = last;
60725476Ssam 		PSWAIT(psaddr); psaddr->ps_data = start;
6087296Ssam 	} else {
6097296Ssam 		start = psaddr->ps_data;	/* dummy: don't update limit */
61025476Ssam 		PSWAIT(psaddr); psaddr->ps_data = psp->ps_map.outputstart;
6117296Ssam 	}
6127296Ssam }
6137296Ssam 
6147296Ssam psmapstart(dfaddr, psp, psaddr)
61525476Ssam 	u_short dfaddr;
6167296Ssam 	register struct ps *psp;
6177296Ssam 	register struct psdevice *psaddr;
6187296Ssam {
6197296Ssam 
62025476Ssam 	PSWAIT(psaddr); psaddr->ps_addr = MAIA;
62125476Ssam 	PSWAIT(psaddr); psaddr->ps_data = dfaddr;
62225476Ssam 	PSWAIT(psaddr); psaddr->ps_data = MAO|MAI;	/* may want more here */
6237296Ssam 	psp->ps_map.mode = RUNNING_MAP;
6247296Ssam }
6257296Ssam 
62625472Ssam int pskillcnt = 1;
62725472Ssam 
62825472Ssam psmapstop(psaddr, psp, request)
6297296Ssam 	register struct psdevice *psaddr;
63025472Ssam 	register struct ps *psp;
63125476Ssam 	short request;
6327296Ssam {
63325472Ssam 	register int i;
6347296Ssam 
63525476Ssam 	request &= HALT_REQ|MOSTOP_REQ; 	/* overkill?? */
63625476Ssam 	for (i = 0; i < pskillcnt; i++) {
63725476Ssam 		PSWAIT(psaddr); psaddr->ps_addr = MASR;
63825476Ssam 		PSWAIT(psaddr); psaddr->ps_data = IOUT;	/* zero MAI & MAO */
63925476Ssam 		PSWAIT(psaddr); psaddr->ps_addr = MAIA;
64025476Ssam 		PSWAIT(psaddr); psaddr->ps_data = 0;	/* 0 input addr reg */
64125476Ssam 		PSWAIT(psaddr); psaddr->ps_addr = MAOA;
64225476Ssam 		PSWAIT(psaddr); psaddr->ps_data = 0;	/* 0 output addr reg */
64325476Ssam 		PSWAIT(psaddr); psaddr->ps_addr = SYSREQ;
64425476Ssam 		PSWAIT(psaddr); psaddr->ps_data = request;
64525472Ssam 	}
64625472Ssam 	psp->ps_map.mode = STOPPED_MAP;
6477296Ssam }
6487296Ssam 
6497296Ssam /*ARGSUSED*/
6507296Ssam psdeviceintr(dev)
6517296Ssam 	dev_t dev;
6527296Ssam {
6537296Ssam 
6547296Ssam 	printf("ps device intr\n");
6557296Ssam }
6567296Ssam 
6577296Ssam /*ARGSUSED*/
6587296Ssam psdmaintr(dev)
6597296Ssam 	dev_t dev;
6607296Ssam {
6617296Ssam 
6627296Ssam 	printf("ps dma intr\n");
6637296Ssam }
6647296Ssam 
66525472Ssam /*ARGSUSED*/
6667296Ssam psreset(uban)
6677296Ssam 	int uban;
6687296Ssam {
66925476Ssam 
6707296Ssam }
6717296Ssam 
67225472Ssam /*ARGSUSED*/
67325476Ssam psextsync(PC, PS)
67425476Ssam {
6757296Ssam 	register int n;
6767296Ssam 	register struct psdevice *psaddr;
6777296Ssam 	register struct ps *psp;
6787296Ssam 	register int savepsaddr;
6797296Ssam 
6807296Ssam #ifdef EXTERNAL_SYNC
6818572Sroot 	for (psp = ps, n = 0; n < NPS; psp++, n++) {
6828572Sroot 		if (!psp->ps_open)
6837296Ssam 			continue;
68425476Ssam 		if (psp->ps_refresh.mode == SYNCING_RF &&
68525476Ssam 		    psp->ps_refresh.state != TIME_RF) {
68625476Ssam 			psaddr = (struct psdevice *)psdinfo[n]->ui_addr;
68725476Ssam 			SAVEPSADDR(psaddr, savepsaddr);
68825472Ssam 			(void) psrfnext(psp, psaddr);
68925476Ssam 			RESTORPSADDR(psaddr, savepsaddr);
6907296Ssam 		} else {
69125476Ssam 			psp->ps_clockticks++;
69225476Ssam 			psp->ps_clockmiss++;
6937296Ssam 		}
6947296Ssam 	}
6957296Ssam #endif
6967296Ssam }
6977296Ssam #endif
698