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