1*49567Sbostic /*-
2*49567Sbostic * Copyright (c) 1982, 1986 The Regents of the University of California.
3*49567Sbostic * All rights reserved.
423334Smckusick *
5*49567Sbostic * %sccs.include.redist.c%
6*49567Sbostic *
7*49567Sbostic * @(#)ps.c 7.7 (Berkeley) 05/09/91
823334Smckusick */
97296Ssam
107296Ssam /*
1123511Ssam * Evans and Sutherland Picture System 2 driver -- Bill Reeves.
127296Ssam */
137296Ssam
147296Ssam /*
157296Ssam * Still to be done:
167296Ssam * WAIT_HIT
177296Ssam */
187296Ssam
197296Ssam #include "ps.h"
207296Ssam #if NPS > 0
217296Ssam
227296Ssam #define EXTERNAL_SYNC
237296Ssam
2445804Sbostic #include "../include/pte.h"
259776Ssam
2645804Sbostic #include "sys/param.h"
2745804Sbostic #include "sys/systm.h"
2845804Sbostic #include "sys/ioctl.h"
2945804Sbostic #include "sys/map.h"
3045804Sbostic #include "sys/buf.h"
3145804Sbostic #include "sys/conf.h"
3245804Sbostic #include "sys/user.h"
3345804Sbostic #include "sys/uio.h"
347296Ssam
3517075Sbloom #include "ubareg.h"
3617075Sbloom #include "ubavar.h"
3717075Sbloom #include "psreg.h"
388477Sroot
3925472Ssam int psprobe(), psattach(), psextsync();
4025472Ssam int psclockintr(), pssystemintr(), psdeviceintr(), psdmaintr();
417296Ssam struct uba_device *psdinfo[NPS];
427296Ssam u_short psstd[] = { 0 };
437296Ssam struct uba_driver psdriver =
447296Ssam { psprobe, 0, psattach, 0, psstd, "ps", psdinfo };
457296Ssam
467296Ssam #define PSUNIT(dev) (minor(dev))
477296Ssam
4825476Ssam #define MAXAUTOREFRESH 4
4925476Ssam #define MAXAUTOMAP 4
5025476Ssam #define MAXDBSIZE (0177777/2)
517296Ssam
5225476Ssam #define PSPRI (PZERO+1)
537296Ssam
5425476Ssam #define PSWAIT(psaddr) { \
5525476Ssam register short i = 20000, j; \
5625476Ssam while (i-- != 0 && ((j = psaddr->ps_iostat) & DIOREADY) == 0) \
5725476Ssam ;\
5825476Ssam }
597296Ssam
6025476Ssam struct psrefresh {
6125476Ssam enum {
6225476Ssam SINGLE_STEP_RF,
6325476Ssam AUTO_RF,
6425476Ssam TIME_RF
6525476Ssam } state;
6625476Ssam enum {
6725476Ssam RUNNING_RF,
6825476Ssam SYNCING_RF,
6925476Ssam WAITING_MAP,
7025476Ssam STOPPED_RF
7125476Ssam } mode;
7225476Ssam u_short sraddrs[MAXAUTOREFRESH];
7325476Ssam short nsraddrs;
7425476Ssam short srcntr;
7525476Ssam char waiting;
7625476Ssam char stop;
7725476Ssam int icnt;
7825476Ssam int timecnt;
7925476Ssam };
8025476Ssam
8125476Ssam struct psdbuffer {
8225476Ssam enum {
8325476Ssam ON_DB,
8425476Ssam OFF_DB
8525476Ssam } state;
8625476Ssam u_short dbaddrs[2];
8725476Ssam u_short dbsize;
8825476Ssam short rbuffer;
8925476Ssam };
9025476Ssam
9125476Ssam struct psmap {
9225476Ssam enum {
9325476Ssam SINGLE_STEP_MAP,
9425476Ssam AUTO_MAP
9525476Ssam } state;
9625476Ssam enum {
9725476Ssam RUNNING_MAP,
9825476Ssam WAITING_RF,
9925476Ssam WAITING_START,
10025476Ssam STOPPED_MAP
10125476Ssam } mode;
10225476Ssam u_short maddrs[MAXAUTOMAP];
10325476Ssam short nmaddrs;
10425476Ssam short mcntr;
10525476Ssam short outputstart;
10625476Ssam char waiting;
10725476Ssam char stop;
10825476Ssam int icnt;
10925476Ssam };
11025476Ssam
11125476Ssam /*
11225476Ssam * PS2 software state.
11325476Ssam */
1147296Ssam struct ps {
11525476Ssam char ps_open; /* device is open */
11625476Ssam uid_t ps_uid; /* uid of device owner */
11725476Ssam struct psrefresh ps_refresh; /* refresh state */
11825476Ssam struct psdbuffer ps_dbuffer; /* double buffering state */
11925476Ssam struct psmap ps_map; /* segment map state */
12025476Ssam int ps_clockticks; /* clock ints between refresh */
12125476Ssam int ps_clockmiss; /* clock ints w/o refresh */
12225476Ssam int ps_clockcnt; /* count of clock interrupts */
12325476Ssam int ps_hitcnt; /* count of hit interrupts */
12425476Ssam int ps_strayintr; /* count of stray interrupts */
12525476Ssam int ps_icnt; /* count of system interrupts */
12625476Ssam /* BEGIN GROT */
12725476Ssam int ps_lastrequest;
12825476Ssam int ps_lastrequest2;
12925476Ssam int ps_lastfunnyrequest;
13025476Ssam int ps_funnycnt;
13125476Ssam /* END GROT */
1327296Ssam } ps[NPS];
1337296Ssam
psprobe(reg)1347296Ssam psprobe(reg)
1357296Ssam caddr_t reg;
1367296Ssam {
1377296Ssam register int br, cvec;
13825476Ssam register struct psdevice *psaddr = (struct psdevice *)reg;
1397296Ssam
14025472Ssam #ifdef lint
14125472Ssam br = 0; cvec = br; br = cvec;
14225472Ssam psclockintr((dev_t)0); pssystemintr((dev_t)0);
14325472Ssam psdeviceintr((dev_t)0); psdmaintr((dev_t)0);
14425472Ssam psextsync(0, 0);
14525472Ssam #endif
1467296Ssam psaddr->ps_iostat = PSRESET;
1477296Ssam DELAY(200);
1487296Ssam psaddr->ps_addr = RTCIE;
14925476Ssam PSWAIT(psaddr); psaddr->ps_data = 01;
1507296Ssam psaddr->ps_iostat = PSIE;
1517296Ssam psaddr->ps_addr = RTCSR;
15225476Ssam PSWAIT(psaddr); psaddr->ps_data = SYNC|RUN;
1537296Ssam DELAY(200000);
1547296Ssam psaddr->ps_addr = RTCREQ;
15525476Ssam PSWAIT(psaddr); psaddr->ps_data = 01;
1567296Ssam psaddr->ps_iostat = 0;
1577296Ssam psaddr->ps_iostat = PSRESET;
1587418Skre return (sizeof (struct psdevice));
1597296Ssam }
1607296Ssam
1617296Ssam /*ARGSUSED*/
1627296Ssam psattach(ui)
16325472Ssam struct uba_device *ui;
1647296Ssam {
1658572Sroot
1667296Ssam }
1677296Ssam
psopen(dev)1687296Ssam psopen(dev)
1697296Ssam dev_t dev;
1707296Ssam {
1717296Ssam register struct ps *psp;
1727296Ssam register struct uba_device *ui;
1737296Ssam register int unit = PSUNIT(dev);
1747296Ssam
1758572Sroot if (unit >= NPS || (psp = &ps[minor(dev)])->ps_open ||
1768572Sroot (ui = psdinfo[unit]) == 0 || ui->ui_alive == 0)
1778572Sroot return (ENXIO);
1787296Ssam psp->ps_open = 1;
1797296Ssam psp->ps_uid = u.u_uid;
1807296Ssam psp->ps_strayintr = 0;
1817296Ssam psp->ps_refresh.state = SINGLE_STEP_RF;
18225472Ssam psp->ps_refresh.mode = STOPPED_RF;
1837296Ssam psp->ps_refresh.waiting = 0;
1847296Ssam psp->ps_refresh.stop = 0;
1857296Ssam psp->ps_dbuffer.state = OFF_DB;
1867296Ssam psp->ps_map.state = SINGLE_STEP_MAP;
18725472Ssam psp->ps_map.mode = STOPPED_MAP;
1887296Ssam psp->ps_map.waiting = 0;
1897296Ssam psp->ps_map.stop = 0;
19025476Ssam psp->ps_clockticks = 0;
19125476Ssam psp->ps_clockmiss = 0;
19225476Ssam psp->ps_refresh.icnt = psp->ps_map.icnt = psp->ps_clockcnt = 0;
19325476Ssam psp->ps_hitcnt = 0;
19414600Ssam psp->ps_icnt = 0;
1957296Ssam maptouser(ui->ui_addr);
1968572Sroot return (0);
1977296Ssam }
1987296Ssam
psclose(dev)1997296Ssam psclose(dev)
2007296Ssam dev_t dev;
2017296Ssam {
2027296Ssam register struct psdevice *psaddr =
20325476Ssam (struct psdevice *)psdinfo[PSUNIT(dev)]->ui_addr;
2047296Ssam
2057296Ssam ps[PSUNIT(dev)].ps_open = 0;
20625476Ssam psaddr->ps_iostat = 0; /* clear IENABLE */
20725476Ssam PSWAIT(psaddr); psaddr->ps_addr = RFSR; /* set in auto refresh mode */
20825476Ssam PSWAIT(psaddr); psaddr->ps_data = AUTOREF;
20925472Ssam unmaptouser((caddr_t)psaddr);
21040728Skarels return (0);
2117296Ssam }
2127296Ssam
2137296Ssam /*ARGSUSED*/
psread(dev,uio)2147730Sroot psread(dev, uio)
2157296Ssam dev_t dev;
2167730Sroot struct uio *uio;
2177296Ssam {
2187296Ssam }
2197296Ssam
2207296Ssam /*ARGSUSED*/
pswrite(dev,uio)2217730Sroot pswrite(dev, uio)
2227296Ssam dev_t dev;
2237730Sroot struct uio *uio;
2247296Ssam {
2257296Ssam }
2267296Ssam
2277296Ssam /*ARGSUSED*/
psioctl(dev,cmd,data,flag)2287632Ssam psioctl(dev, cmd, data, flag)
2297632Ssam register caddr_t data;
2307296Ssam {
2317296Ssam register struct uba_device *ui = psdinfo[PSUNIT(dev)];
2327296Ssam register struct ps *psp = &ps[PSUNIT(dev)];
2337632Ssam int *waddr = *(int **)data;
23440728Skarels int n, arg, i, error = 0;
2357296Ssam
2367296Ssam switch (cmd) {
2377632Ssam
2387632Ssam case PSIOGETADDR:
2397632Ssam *(caddr_t *)data = ui->ui_addr;
2407296Ssam break;
2417632Ssam
2427632Ssam case PSIOAUTOREFRESH:
24325472Ssam n = fuword((caddr_t)waddr++);
2448572Sroot if (n == -1)
2458572Sroot return (EFAULT);
2468572Sroot if (n < 0 || n > MAXAUTOREFRESH)
2478572Sroot return (EINVAL);
2488572Sroot for (i = 0; i < n; i++) {
24925472Ssam if ((arg = fuword((caddr_t)waddr++)) == -1)
2508572Sroot return (EFAULT);
2518572Sroot psp->ps_refresh.sraddrs[i] = arg;
2527296Ssam }
2538572Sroot psp->ps_refresh.state = AUTO_RF;
2548572Sroot psp->ps_refresh.nsraddrs = n;
2558572Sroot psp->ps_refresh.srcntr = 0;
2568572Sroot psp->ps_refresh.mode = WAITING_MAP;
2577296Ssam break;
2587632Ssam
2597632Ssam case PSIOAUTOMAP:
26025472Ssam n = fuword((caddr_t)waddr++);
2618572Sroot if (n == -1)
2628572Sroot return (EFAULT);
2638572Sroot if (n < 0 || n > MAXAUTOMAP)
2648572Sroot return (EINVAL);
2658572Sroot for (i = 0; i < n; i++) {
26625472Ssam if ((arg = fuword((caddr_t)waddr++)) == -1)
2678572Sroot return (EFAULT);
2688572Sroot psp->ps_map.maddrs[i] = arg;
2697296Ssam }
27025472Ssam if ((arg = fuword((caddr_t)waddr++)) == -1)
2718572Sroot return (EFAULT);
2728572Sroot psp->ps_map.outputstart = arg;
2738572Sroot psp->ps_map.state = AUTO_MAP;
2748572Sroot psp->ps_map.nmaddrs = n;
2758572Sroot psp->ps_map.mcntr = 0;
2768572Sroot psp->ps_map.mode = WAITING_START;
2777296Ssam break;
2787632Ssam
2797632Ssam case PSIOSINGLEREFRESH:
2807296Ssam psp->ps_refresh.state = SINGLE_STEP_RF;
2817296Ssam break;
2827632Ssam
2837632Ssam case PSIOSINGLEMAP:
2847296Ssam psp->ps_map.state = SINGLE_STEP_MAP;
2857296Ssam break;
2867632Ssam
2877632Ssam case PSIODOUBLEBUFFER:
28825472Ssam if ((arg = fuword((caddr_t)waddr++)) == -1)
2898572Sroot return (EFAULT);
2908572Sroot psp->ps_dbuffer.dbaddrs[0] = arg;
29125472Ssam if ((arg = fuword((caddr_t)waddr++)) == -1)
2928572Sroot return (EFAULT);
2938572Sroot if (arg <= 0 || arg > MAXDBSIZE)
2948572Sroot return (EINVAL);
2958572Sroot psp->ps_dbuffer.dbsize = arg;
29625476Ssam psp->ps_dbuffer.dbaddrs[1] = psp->ps_dbuffer.dbaddrs[0]+arg;
2978572Sroot psp->ps_dbuffer.state = ON_DB;
2988572Sroot psp->ps_dbuffer.rbuffer = 0;
2997296Ssam break;
3007632Ssam
3017632Ssam case PSIOSINGLEBUFFER:
3027296Ssam psp->ps_dbuffer.state = OFF_DB;
3037296Ssam break;
3047632Ssam
30514600Ssam case PSIOTIMEREFRESH:
30614600Ssam if (psp->ps_refresh.state != SINGLE_STEP_RF)
30725476Ssam return (EINVAL);
30825472Ssam if ((arg = fuword((caddr_t)waddr++)) == -1)
30925476Ssam return (EFAULT);
31014600Ssam psp->ps_refresh.state = TIME_RF;
31114600Ssam psp->ps_refresh.timecnt = arg;
31214600Ssam break;
31314600Ssam
3147632Ssam case PSIOWAITREFRESH:
3158572Sroot if (psp->ps_refresh.mode != RUNNING_RF) /* not running */
31625476Ssam return (0); /* dont wait */
3178572Sroot /* fall into ... */
3187632Ssam
31914600Ssam case PSIOSTOPREFRESH:
32014600Ssam if (cmd == PSIOSTOPREFRESH) {
32125476Ssam if (psp->ps_refresh.mode == STOPPED_RF &&
32225476Ssam psp->ps_refresh.state != TIME_RF)
32314600Ssam return (0);
3247296Ssam psp->ps_refresh.stop = 1;
32514600Ssam }
32625476Ssam (void) spl5();
3277296Ssam psp->ps_refresh.waiting = 1;
3288572Sroot while (psp->ps_refresh.waiting)
32940728Skarels if (error = tsleep(&psp->ps_refresh.waiting,
33040728Skarels PSPRI | PCATCH, devwait, 0))
33140728Skarels break;
33225476Ssam (void) spl0();
33340728Skarels if (error)
33440728Skarels return (error);
33514600Ssam if (cmd == PSIOSTOPREFRESH)
33614600Ssam psp->ps_refresh.mode = STOPPED_RF;
33714600Ssam if (psp->ps_refresh.state == TIME_RF)
33814600Ssam psp->ps_refresh.state = SINGLE_STEP_RF;
3397296Ssam break;
3407632Ssam
3417632Ssam case PSIOWAITMAP:
3428572Sroot if (psp->ps_map.mode != RUNNING_MAP) /* not running */
34325476Ssam return (0); /* dont wait */
3448572Sroot /* fall into ... */
3457632Ssam
3467632Ssam case PSIOSTOPMAP:
34714600Ssam if (cmd == PSIOSTOPMAP)
3487296Ssam psp->ps_map.stop = 1;
34925476Ssam (void) spl5();
3507296Ssam psp->ps_map.waiting = 1;
3518572Sroot while (psp->ps_map.waiting)
35240728Skarels if (error = tsleep(&psp->ps_map.waiting, PSPRI | PCATCH,
35340728Skarels devwait, 0))
35440728Skarels break;
35525476Ssam (void) spl0();
3567296Ssam break;
3577632Ssam
3587296Ssam default:
3598572Sroot return (ENOTTY);
3607296Ssam break;
3617296Ssam }
36240728Skarels return (error);
3637296Ssam }
3647296Ssam
36525476Ssam #define SAVEPSADDR(psaddr, savepsaddr) { \
36625476Ssam register short i, xx1; \
36726368Skarels xx1 = splclock(); \
36825476Ssam i = psaddr->ps_addr; \
36925476Ssam while ((psaddr->ps_iostat & DIOREADY) == 0) \
37025476Ssam ; \
37125476Ssam savepsaddr = psaddr->ps_data; \
37225476Ssam splx(xx1); \
37325476Ssam }
37425476Ssam #define RESTORPSADDR(psaddr, savepsaddr) { \
37525476Ssam register short xx2; \
37626368Skarels xx2 = splclock(); \
37725476Ssam while ((psaddr->ps_iostat & DIOREADY) == 0) \
37825476Ssam ;\
37925476Ssam psaddr->ps_addr = savepsaddr; \
38025476Ssam splx(xx2); \
38125476Ssam }
3827296Ssam
psclockintr(dev)3837296Ssam psclockintr(dev)
3847296Ssam dev_t dev;
3857296Ssam {
3867296Ssam register struct psdevice *psaddr =
38725476Ssam (struct psdevice *)psdinfo[PSUNIT(dev)]->ui_addr;
3887296Ssam register struct ps *psp = &ps[PSUNIT(dev)];
3897296Ssam int savepsaddr;
3907296Ssam
3918572Sroot if (!psp->ps_open)
3927296Ssam return;
39325476Ssam psp->ps_clockcnt++;
39425476Ssam SAVEPSADDR(psaddr, savepsaddr);
3957296Ssam #ifndef EXTERNAL_SYNC
3968572Sroot if (psp->ps_refresh.state == AUTO_RF) {
39725476Ssam if (psp->ps_refresh.mode == SYNCING_RF &&
39825476Ssam psp->ps_refresh.state != TIME_RF) {
39925472Ssam (void) psrfnext(psp, psaddr);
4007296Ssam } else {
40125476Ssam psp->ps_clockticks++;
40225476Ssam psp->ps_clockmiss++;
4037296Ssam }
4047296Ssam }
4057296Ssam #endif
40625476Ssam PSWAIT(psaddr); psaddr->ps_addr = RTCREQ;
40725476Ssam PSWAIT(psaddr); psaddr->ps_data = 01; /* clear the request bits */
40825476Ssam RESTORPSADDR(psaddr, savepsaddr);
4097296Ssam }
4107296Ssam
4117296Ssam /*ARGSUSED*/
pssystemintr(dev)4127296Ssam pssystemintr(dev)
4137296Ssam dev_t dev;
4147296Ssam {
4157296Ssam register struct psdevice *psaddr =
41625476Ssam (struct psdevice *)psdinfo[PSUNIT(dev)]->ui_addr;
4177296Ssam register struct ps *psp = &ps[PSUNIT(dev)];
41825476Ssam short request, tmp;
4197296Ssam register int savepsaddr, x;
4207296Ssam
4218572Sroot if (!psp->ps_open)
4227296Ssam return;
42314600Ssam psp->ps_icnt++;
42425476Ssam SAVEPSADDR(psaddr, savepsaddr);
42525476Ssam PSWAIT(psaddr); psaddr->ps_addr = SYSREQ;
42625476Ssam PSWAIT(psaddr); request = psaddr->ps_data;
42725472Ssam request = request&0377;
42825476Ssam psp->ps_lastrequest2 = psp->ps_lastrequest;
42925476Ssam psp->ps_lastrequest = request;
43025476Ssam if (request &~ (HALT_REQ|RFSTOP_REQ|HIT_REQ)) {
43125476Ssam psp->ps_lastfunnyrequest = request;
43225476Ssam psp->ps_funnycnt++;
43325472Ssam }
43425476Ssam PSWAIT(psaddr); psaddr->ps_addr = SYSREQ;
43525476Ssam tmp = request&(~(HALT_REQ|MOSTOP_REQ)); /* acknowledge */
43625476Ssam PSWAIT(psaddr); psaddr->ps_data = tmp;
4377296Ssam
4388572Sroot if (request & (MOSTOP_REQ|HALT_REQ)) { /* Map stopped */
4397296Ssam psp->ps_map.icnt++;
44025476Ssam psmapstop(psaddr, psp, request);/* kill it dead */
4418572Sroot if (psp->ps_map.waiting) {
4427296Ssam psp->ps_map.waiting = 0;
4437296Ssam wakeup(&psp->ps_map.waiting);
4448572Sroot if (psp->ps_map.stop) {
4457296Ssam psp->ps_map.stop = 0;
4467296Ssam goto tryrf;
4477296Ssam }
4487296Ssam }
44925476Ssam if (psp->ps_map.state == AUTO_MAP && !psmapnext(psp, psaddr)) {
45025472Ssam psp->ps_map.mcntr = 0;
45125472Ssam /* prepare for next round */
45225472Ssam pssetmapbounds(psp, psaddr);
45325472Ssam if (psp->ps_refresh.state == AUTO_RF) {
45425476Ssam if (psp->ps_refresh.mode == WAITING_MAP){
4558572Sroot if (psp->ps_dbuffer.state == ON_DB)
4567296Ssam /* fill other db */
4577296Ssam psdbswitch(psp, psaddr);
4587296Ssam else
4597296Ssam psp->ps_map.mode = WAITING_RF;
46025472Ssam #ifdef EXTERNAL_SYNC
46126368Skarels x = splclock();
46225472Ssam #endif
46325472Ssam (void) psrfnext(psp, psaddr);
46425472Ssam #ifdef EXTERNAL_SYNC
46525472Ssam splx(x);
46625472Ssam #endif
4677296Ssam } else
4687296Ssam psp->ps_map.mode = WAITING_RF;
46925472Ssam } else { /* no auto refresh */
47025472Ssam if (psp->ps_dbuffer.state == ON_DB)
47125472Ssam /* fill other db */
47225472Ssam psdbswitch(psp, psaddr);
47325472Ssam else
47425472Ssam (void) psmapnext(psp, psaddr);
4757296Ssam }
47625472Ssam }
4777296Ssam }
4787296Ssam tryrf:
4798572Sroot if (request & RFSTOP_REQ) { /* Refresh stopped */
4807296Ssam psp->ps_refresh.icnt++;
48114600Ssam if (psp->ps_refresh.state == TIME_RF)
48225476Ssam if (--psp->ps_refresh.timecnt > 0)
48314600Ssam goto tryhit;
4847296Ssam psrfstop(psaddr, psp);
4858572Sroot if (psp->ps_refresh.waiting) {
4867296Ssam psp->ps_refresh.waiting = 0;
4877296Ssam wakeup(&psp->ps_refresh.waiting);
4888572Sroot if (psp->ps_refresh.stop) {
4897296Ssam psp->ps_refresh.stop = 0;
4907296Ssam goto tryhit;
4917296Ssam }
4927296Ssam }
4938572Sroot if (psp->ps_refresh.state == AUTO_RF)
4948572Sroot if (!psrfnext(psp, psaddr)) { /* at end of refresh cycle */
4958572Sroot if (psp->ps_map.state == AUTO_MAP &&
49625476Ssam psp->ps_map.mode == WAITING_RF) {
4978572Sroot if (psp->ps_dbuffer.state == ON_DB)
4987296Ssam psdbswitch(psp, psaddr);
4997296Ssam else
50025472Ssam (void) psmapnext(psp, psaddr);
5017296Ssam }
5027296Ssam psp->ps_refresh.srcntr = 0;
5037296Ssam #ifdef EXTERNAL_SYNC
50426368Skarels x = splclock();
5057296Ssam #endif
50625472Ssam psp->ps_refresh.mode = SYNCING_RF;
50725476Ssam if (psp->ps_clockticks)
50825472Ssam (void) psrfnext(psp, psaddr);
50925476Ssam psp->ps_clockticks = 0;
5107296Ssam #ifdef EXTERNAL_SYNC
5117296Ssam splx(x);
5127296Ssam #endif
5137296Ssam }
5147296Ssam }
5157296Ssam tryhit:
51625476Ssam if (request & HIT_REQ) /* Hit request */
51725476Ssam psp->ps_hitcnt++;
5188572Sroot if (request == 0)
5197296Ssam psp->ps_strayintr++;
52025476Ssam RESTORPSADDR(psaddr, savepsaddr);
5217296Ssam }
5227296Ssam
psrfnext(psp,psaddr)5237296Ssam psrfnext(psp, psaddr)
5247296Ssam register struct ps *psp;
5257296Ssam register struct psdevice *psaddr;
5267296Ssam {
52725476Ssam u_short start, last;
5287296Ssam
52925476Ssam if (psp->ps_refresh.srcntr < psp->ps_refresh.nsraddrs) {
5307296Ssam psrfstart(psp->ps_refresh.sraddrs[psp->ps_refresh.srcntr++],
53125476Ssam 0, psp, psaddr);
53225476Ssam return (1);
53325476Ssam }
53425476Ssam if (psp->ps_refresh.srcntr == psp->ps_refresh.nsraddrs &&
53525476Ssam psp->ps_dbuffer.state == ON_DB) {
53625472Ssam start = psp->ps_dbuffer.dbaddrs[psp->ps_dbuffer.rbuffer];
53725472Ssam last = start+psp->ps_dbuffer.dbsize;
53825472Ssam psrfstart(start, last, psp, psaddr);
5397296Ssam psp->ps_refresh.srcntr++; /* flag for after dbuffer */
54025476Ssam return (1);
54125476Ssam }
54225476Ssam return (0);
5437296Ssam }
5447296Ssam
psrfstart(dfaddr,last,psp,psaddr)54525472Ssam psrfstart(dfaddr, last, psp, psaddr)
54625476Ssam u_short dfaddr, last;
5477296Ssam register struct ps *psp;
5487296Ssam register struct psdevice *psaddr;
5497296Ssam {
55025476Ssam short dummy;
5517296Ssam
55225476Ssam PSWAIT(psaddr); psaddr->ps_addr = RFASA;
55325476Ssam PSWAIT(psaddr); psaddr->ps_data = dfaddr;
55425476Ssam PSWAIT(psaddr);
55525476Ssam if (last != 0)
55625472Ssam psaddr->ps_data = last;
55725472Ssam else
55825472Ssam dummy = psaddr->ps_data;/* just access to get to status reg */
55925476Ssam PSWAIT(psaddr); psaddr->ps_data = RFSTART; /* may want | here */
5607296Ssam psp->ps_refresh.mode = RUNNING_RF;
5617296Ssam }
5627296Ssam
56325472Ssam /*ARGSUSED*/
psrfstop(psaddr,psp)5647296Ssam psrfstop(psaddr, psp)
5657296Ssam register struct psdevice *psaddr;
5667296Ssam register struct ps *psp;
5677296Ssam {
5687296Ssam
56925476Ssam PSWAIT(psaddr); psaddr->ps_addr = RFSR;
57025476Ssam PSWAIT(psaddr); psaddr->ps_data = 0;
5717296Ssam }
5727296Ssam
psdbswitch(psp,psaddr)5737296Ssam psdbswitch(psp, psaddr)
5747296Ssam register struct ps *psp;
5757296Ssam register struct psdevice *psaddr;
5767296Ssam {
5777296Ssam
5787296Ssam psp->ps_dbuffer.rbuffer = !psp->ps_dbuffer.rbuffer;
5797296Ssam pssetmapbounds(psp, psaddr);
58025472Ssam (void) psmapnext(psp, psaddr);
5817296Ssam }
5827296Ssam
psmapnext(psp,psaddr)5837296Ssam psmapnext(psp, psaddr)
5847296Ssam register struct ps *psp;
5857296Ssam register struct psdevice *psaddr;
5867296Ssam {
5877296Ssam
58825476Ssam if (psp->ps_map.mcntr < psp->ps_map.nmaddrs) {
58925476Ssam psmapstart(psp->ps_map.maddrs[psp->ps_map.mcntr++],
59025476Ssam psp, psaddr);
59125476Ssam return (1);
59225476Ssam }
59325476Ssam return (0);
5947296Ssam }
5957296Ssam
pssetmapbounds(psp,psaddr)5967296Ssam pssetmapbounds(psp, psaddr)
5977296Ssam register struct ps *psp;
5987296Ssam register struct psdevice *psaddr;
5997296Ssam {
60025476Ssam u_short start, last;
6017296Ssam
60225476Ssam PSWAIT(psaddr); psaddr->ps_addr = MAOL;
60325476Ssam PSWAIT(psaddr);
6048572Sroot if (psp->ps_dbuffer.state == ON_DB) {
60525472Ssam start = psp->ps_dbuffer.dbaddrs[!psp->ps_dbuffer.rbuffer];
60625472Ssam last = start+psp->ps_dbuffer.dbsize-2; /* 2 for halt cmd */
60725472Ssam psaddr->ps_data = last;
60825476Ssam PSWAIT(psaddr); psaddr->ps_data = start;
6097296Ssam } else {
6107296Ssam start = psaddr->ps_data; /* dummy: don't update limit */
61125476Ssam PSWAIT(psaddr); psaddr->ps_data = psp->ps_map.outputstart;
6127296Ssam }
6137296Ssam }
6147296Ssam
psmapstart(dfaddr,psp,psaddr)6157296Ssam psmapstart(dfaddr, psp, psaddr)
61625476Ssam u_short dfaddr;
6177296Ssam register struct ps *psp;
6187296Ssam register struct psdevice *psaddr;
6197296Ssam {
6207296Ssam
62125476Ssam PSWAIT(psaddr); psaddr->ps_addr = MAIA;
62225476Ssam PSWAIT(psaddr); psaddr->ps_data = dfaddr;
62325476Ssam PSWAIT(psaddr); psaddr->ps_data = MAO|MAI; /* may want more here */
6247296Ssam psp->ps_map.mode = RUNNING_MAP;
6257296Ssam }
6267296Ssam
62725472Ssam int pskillcnt = 1;
62825472Ssam
psmapstop(psaddr,psp,request)62925472Ssam psmapstop(psaddr, psp, request)
6307296Ssam register struct psdevice *psaddr;
63125472Ssam register struct ps *psp;
63225476Ssam short request;
6337296Ssam {
63425472Ssam register int i;
6357296Ssam
63625476Ssam request &= HALT_REQ|MOSTOP_REQ; /* overkill?? */
63725476Ssam for (i = 0; i < pskillcnt; i++) {
63825476Ssam PSWAIT(psaddr); psaddr->ps_addr = MASR;
63925476Ssam PSWAIT(psaddr); psaddr->ps_data = IOUT; /* zero MAI & MAO */
64025476Ssam PSWAIT(psaddr); psaddr->ps_addr = MAIA;
64125476Ssam PSWAIT(psaddr); psaddr->ps_data = 0; /* 0 input addr reg */
64225476Ssam PSWAIT(psaddr); psaddr->ps_addr = MAOA;
64325476Ssam PSWAIT(psaddr); psaddr->ps_data = 0; /* 0 output addr reg */
64425476Ssam PSWAIT(psaddr); psaddr->ps_addr = SYSREQ;
64525476Ssam PSWAIT(psaddr); psaddr->ps_data = request;
64625472Ssam }
64725472Ssam psp->ps_map.mode = STOPPED_MAP;
6487296Ssam }
6497296Ssam
6507296Ssam /*ARGSUSED*/
psdeviceintr(dev)6517296Ssam psdeviceintr(dev)
6527296Ssam dev_t dev;
6537296Ssam {
6547296Ssam
6557296Ssam printf("ps device intr\n");
6567296Ssam }
6577296Ssam
6587296Ssam /*ARGSUSED*/
psdmaintr(dev)6597296Ssam psdmaintr(dev)
6607296Ssam dev_t dev;
6617296Ssam {
6627296Ssam
6637296Ssam printf("ps dma intr\n");
6647296Ssam }
6657296Ssam
66625472Ssam /*ARGSUSED*/
psreset(uban)6677296Ssam psreset(uban)
6687296Ssam int uban;
6697296Ssam {
67025476Ssam
6717296Ssam }
6727296Ssam
67325472Ssam /*ARGSUSED*/
psextsync(PC,PS)67425476Ssam psextsync(PC, PS)
67525476Ssam {
6767296Ssam register int n;
6777296Ssam register struct psdevice *psaddr;
6787296Ssam register struct ps *psp;
6797296Ssam register int savepsaddr;
6807296Ssam
6817296Ssam #ifdef EXTERNAL_SYNC
6828572Sroot for (psp = ps, n = 0; n < NPS; psp++, n++) {
6838572Sroot if (!psp->ps_open)
6847296Ssam continue;
68525476Ssam if (psp->ps_refresh.mode == SYNCING_RF &&
68625476Ssam psp->ps_refresh.state != TIME_RF) {
68725476Ssam psaddr = (struct psdevice *)psdinfo[n]->ui_addr;
68825476Ssam SAVEPSADDR(psaddr, savepsaddr);
68925472Ssam (void) psrfnext(psp, psaddr);
69025476Ssam RESTORPSADDR(psaddr, savepsaddr);
6917296Ssam } else {
69225476Ssam psp->ps_clockticks++;
69325476Ssam psp->ps_clockmiss++;
6947296Ssam }
6957296Ssam }
6967296Ssam #endif
6977296Ssam }
6987296Ssam #endif
699