123334Smckusick /* 223334Smckusick * Copyright (c) 1982 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*26368Skarels * @(#)ps.c 6.7 (Berkeley) 02/23/86 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 239776Ssam #include "../machine/pte.h" 249776Ssam 2517075Sbloom #include "param.h" 2617075Sbloom #include "systm.h" 2717075Sbloom #include "ioctl.h" 2817075Sbloom #include "map.h" 2917075Sbloom #include "buf.h" 3017075Sbloom #include "conf.h" 3117075Sbloom #include "dir.h" 3217075Sbloom #include "user.h" 3317075Sbloom #include "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 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 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 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); 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; 2337296Ssam int n, arg, i; 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) 3287296Ssam sleep(&psp->ps_refresh.waiting, PSPRI); 32925476Ssam (void) spl0(); 33014600Ssam if (cmd == PSIOSTOPREFRESH) 33114600Ssam psp->ps_refresh.mode = STOPPED_RF; 33214600Ssam if (psp->ps_refresh.state == TIME_RF) 33314600Ssam psp->ps_refresh.state = SINGLE_STEP_RF; 3347296Ssam break; 3357632Ssam 3367632Ssam case PSIOWAITMAP: 3378572Sroot if (psp->ps_map.mode != RUNNING_MAP) /* not running */ 33825476Ssam return (0); /* dont wait */ 3398572Sroot /* fall into ... */ 3407632Ssam 3417632Ssam case PSIOSTOPMAP: 34214600Ssam if (cmd == PSIOSTOPMAP) 3437296Ssam psp->ps_map.stop = 1; 34425476Ssam (void) spl5(); 3457296Ssam psp->ps_map.waiting = 1; 3468572Sroot while (psp->ps_map.waiting) 3477296Ssam sleep(&psp->ps_map.waiting, PSPRI); 34825476Ssam (void) spl0(); 3497296Ssam break; 3507632Ssam 3517296Ssam default: 3528572Sroot return (ENOTTY); 3537296Ssam break; 3547296Ssam } 3558572Sroot return (0); 3567296Ssam } 3577296Ssam 35825476Ssam #define SAVEPSADDR(psaddr, savepsaddr) { \ 35925476Ssam register short i, xx1; \ 360*26368Skarels xx1 = splclock(); \ 36125476Ssam i = psaddr->ps_addr; \ 36225476Ssam while ((psaddr->ps_iostat & DIOREADY) == 0) \ 36325476Ssam ; \ 36425476Ssam savepsaddr = psaddr->ps_data; \ 36525476Ssam splx(xx1); \ 36625476Ssam } 36725476Ssam #define RESTORPSADDR(psaddr, savepsaddr) { \ 36825476Ssam register short xx2; \ 369*26368Skarels xx2 = splclock(); \ 37025476Ssam while ((psaddr->ps_iostat & DIOREADY) == 0) \ 37125476Ssam ;\ 37225476Ssam psaddr->ps_addr = savepsaddr; \ 37325476Ssam splx(xx2); \ 37425476Ssam } 3757296Ssam 3767296Ssam psclockintr(dev) 3777296Ssam dev_t dev; 3787296Ssam { 3797296Ssam register struct psdevice *psaddr = 38025476Ssam (struct psdevice *)psdinfo[PSUNIT(dev)]->ui_addr; 3817296Ssam register struct ps *psp = &ps[PSUNIT(dev)]; 3827296Ssam int savepsaddr; 3837296Ssam 3848572Sroot if (!psp->ps_open) 3857296Ssam return; 38625476Ssam psp->ps_clockcnt++; 38725476Ssam SAVEPSADDR(psaddr, savepsaddr); 3887296Ssam #ifndef EXTERNAL_SYNC 3898572Sroot if (psp->ps_refresh.state == AUTO_RF) { 39025476Ssam if (psp->ps_refresh.mode == SYNCING_RF && 39125476Ssam psp->ps_refresh.state != TIME_RF) { 39225472Ssam (void) psrfnext(psp, psaddr); 3937296Ssam } else { 39425476Ssam psp->ps_clockticks++; 39525476Ssam psp->ps_clockmiss++; 3967296Ssam } 3977296Ssam } 3987296Ssam #endif 39925476Ssam PSWAIT(psaddr); psaddr->ps_addr = RTCREQ; 40025476Ssam PSWAIT(psaddr); psaddr->ps_data = 01; /* clear the request bits */ 40125476Ssam RESTORPSADDR(psaddr, savepsaddr); 4027296Ssam } 4037296Ssam 4047296Ssam /*ARGSUSED*/ 4057296Ssam pssystemintr(dev) 4067296Ssam dev_t dev; 4077296Ssam { 4087296Ssam register struct psdevice *psaddr = 40925476Ssam (struct psdevice *)psdinfo[PSUNIT(dev)]->ui_addr; 4107296Ssam register struct ps *psp = &ps[PSUNIT(dev)]; 41125476Ssam short request, tmp; 4127296Ssam register int savepsaddr, x; 4137296Ssam 4148572Sroot if (!psp->ps_open) 4157296Ssam return; 41614600Ssam psp->ps_icnt++; 41725476Ssam SAVEPSADDR(psaddr, savepsaddr); 41825476Ssam PSWAIT(psaddr); psaddr->ps_addr = SYSREQ; 41925476Ssam PSWAIT(psaddr); request = psaddr->ps_data; 42025472Ssam request = request&0377; 42125476Ssam psp->ps_lastrequest2 = psp->ps_lastrequest; 42225476Ssam psp->ps_lastrequest = request; 42325476Ssam if (request &~ (HALT_REQ|RFSTOP_REQ|HIT_REQ)) { 42425476Ssam psp->ps_lastfunnyrequest = request; 42525476Ssam psp->ps_funnycnt++; 42625472Ssam } 42725476Ssam PSWAIT(psaddr); psaddr->ps_addr = SYSREQ; 42825476Ssam tmp = request&(~(HALT_REQ|MOSTOP_REQ)); /* acknowledge */ 42925476Ssam PSWAIT(psaddr); psaddr->ps_data = tmp; 4307296Ssam 4318572Sroot if (request & (MOSTOP_REQ|HALT_REQ)) { /* Map stopped */ 4327296Ssam psp->ps_map.icnt++; 43325476Ssam psmapstop(psaddr, psp, request);/* kill it dead */ 4348572Sroot if (psp->ps_map.waiting) { 4357296Ssam psp->ps_map.waiting = 0; 4367296Ssam wakeup(&psp->ps_map.waiting); 4378572Sroot if (psp->ps_map.stop) { 4387296Ssam psp->ps_map.stop = 0; 4397296Ssam goto tryrf; 4407296Ssam } 4417296Ssam } 44225476Ssam if (psp->ps_map.state == AUTO_MAP && !psmapnext(psp, psaddr)) { 44325472Ssam psp->ps_map.mcntr = 0; 44425472Ssam /* prepare for next round */ 44525472Ssam pssetmapbounds(psp, psaddr); 44625472Ssam if (psp->ps_refresh.state == AUTO_RF) { 44725476Ssam if (psp->ps_refresh.mode == WAITING_MAP){ 4488572Sroot if (psp->ps_dbuffer.state == ON_DB) 4497296Ssam /* fill other db */ 4507296Ssam psdbswitch(psp, psaddr); 4517296Ssam else 4527296Ssam psp->ps_map.mode = WAITING_RF; 45325472Ssam #ifdef EXTERNAL_SYNC 454*26368Skarels x = splclock(); 45525472Ssam #endif 45625472Ssam (void) psrfnext(psp, psaddr); 45725472Ssam #ifdef EXTERNAL_SYNC 45825472Ssam splx(x); 45925472Ssam #endif 4607296Ssam } else 4617296Ssam psp->ps_map.mode = WAITING_RF; 46225472Ssam } else { /* no auto refresh */ 46325472Ssam if (psp->ps_dbuffer.state == ON_DB) 46425472Ssam /* fill other db */ 46525472Ssam psdbswitch(psp, psaddr); 46625472Ssam else 46725472Ssam (void) psmapnext(psp, psaddr); 4687296Ssam } 46925472Ssam } 4707296Ssam } 4717296Ssam tryrf: 4728572Sroot if (request & RFSTOP_REQ) { /* Refresh stopped */ 4737296Ssam psp->ps_refresh.icnt++; 47414600Ssam if (psp->ps_refresh.state == TIME_RF) 47525476Ssam if (--psp->ps_refresh.timecnt > 0) 47614600Ssam goto tryhit; 4777296Ssam psrfstop(psaddr, psp); 4788572Sroot if (psp->ps_refresh.waiting) { 4797296Ssam psp->ps_refresh.waiting = 0; 4807296Ssam wakeup(&psp->ps_refresh.waiting); 4818572Sroot if (psp->ps_refresh.stop) { 4827296Ssam psp->ps_refresh.stop = 0; 4837296Ssam goto tryhit; 4847296Ssam } 4857296Ssam } 4868572Sroot if (psp->ps_refresh.state == AUTO_RF) 4878572Sroot if (!psrfnext(psp, psaddr)) { /* at end of refresh cycle */ 4888572Sroot if (psp->ps_map.state == AUTO_MAP && 48925476Ssam psp->ps_map.mode == WAITING_RF) { 4908572Sroot if (psp->ps_dbuffer.state == ON_DB) 4917296Ssam psdbswitch(psp, psaddr); 4927296Ssam else 49325472Ssam (void) psmapnext(psp, psaddr); 4947296Ssam } 4957296Ssam psp->ps_refresh.srcntr = 0; 4967296Ssam #ifdef EXTERNAL_SYNC 497*26368Skarels x = splclock(); 4987296Ssam #endif 49925472Ssam psp->ps_refresh.mode = SYNCING_RF; 50025476Ssam if (psp->ps_clockticks) 50125472Ssam (void) psrfnext(psp, psaddr); 50225476Ssam psp->ps_clockticks = 0; 5037296Ssam #ifdef EXTERNAL_SYNC 5047296Ssam splx(x); 5057296Ssam #endif 5067296Ssam } 5077296Ssam } 5087296Ssam tryhit: 50925476Ssam if (request & HIT_REQ) /* Hit request */ 51025476Ssam psp->ps_hitcnt++; 5118572Sroot if (request == 0) 5127296Ssam psp->ps_strayintr++; 51325476Ssam RESTORPSADDR(psaddr, savepsaddr); 5147296Ssam } 5157296Ssam 5167296Ssam psrfnext(psp, psaddr) 5177296Ssam register struct ps *psp; 5187296Ssam register struct psdevice *psaddr; 5197296Ssam { 52025476Ssam u_short start, last; 5217296Ssam 52225476Ssam if (psp->ps_refresh.srcntr < psp->ps_refresh.nsraddrs) { 5237296Ssam psrfstart(psp->ps_refresh.sraddrs[psp->ps_refresh.srcntr++], 52425476Ssam 0, psp, psaddr); 52525476Ssam return (1); 52625476Ssam } 52725476Ssam if (psp->ps_refresh.srcntr == psp->ps_refresh.nsraddrs && 52825476Ssam psp->ps_dbuffer.state == ON_DB) { 52925472Ssam start = psp->ps_dbuffer.dbaddrs[psp->ps_dbuffer.rbuffer]; 53025472Ssam last = start+psp->ps_dbuffer.dbsize; 53125472Ssam psrfstart(start, last, psp, psaddr); 5327296Ssam psp->ps_refresh.srcntr++; /* flag for after dbuffer */ 53325476Ssam return (1); 53425476Ssam } 53525476Ssam return (0); 5367296Ssam } 5377296Ssam 53825472Ssam psrfstart(dfaddr, last, psp, psaddr) 53925476Ssam u_short dfaddr, last; 5407296Ssam register struct ps *psp; 5417296Ssam register struct psdevice *psaddr; 5427296Ssam { 54325476Ssam short dummy; 5447296Ssam 54525476Ssam PSWAIT(psaddr); psaddr->ps_addr = RFASA; 54625476Ssam PSWAIT(psaddr); psaddr->ps_data = dfaddr; 54725476Ssam PSWAIT(psaddr); 54825476Ssam if (last != 0) 54925472Ssam psaddr->ps_data = last; 55025472Ssam else 55125472Ssam dummy = psaddr->ps_data;/* just access to get to status reg */ 55225476Ssam PSWAIT(psaddr); psaddr->ps_data = RFSTART; /* may want | here */ 5537296Ssam psp->ps_refresh.mode = RUNNING_RF; 5547296Ssam } 5557296Ssam 55625472Ssam /*ARGSUSED*/ 5577296Ssam psrfstop(psaddr, psp) 5587296Ssam register struct psdevice *psaddr; 5597296Ssam register struct ps *psp; 5607296Ssam { 5617296Ssam 56225476Ssam PSWAIT(psaddr); psaddr->ps_addr = RFSR; 56325476Ssam PSWAIT(psaddr); psaddr->ps_data = 0; 5647296Ssam } 5657296Ssam 5667296Ssam psdbswitch(psp, psaddr) 5677296Ssam register struct ps *psp; 5687296Ssam register struct psdevice *psaddr; 5697296Ssam { 5707296Ssam 5717296Ssam psp->ps_dbuffer.rbuffer = !psp->ps_dbuffer.rbuffer; 5727296Ssam pssetmapbounds(psp, psaddr); 57325472Ssam (void) psmapnext(psp, psaddr); 5747296Ssam } 5757296Ssam 5767296Ssam psmapnext(psp, psaddr) 5777296Ssam register struct ps *psp; 5787296Ssam register struct psdevice *psaddr; 5797296Ssam { 5807296Ssam 58125476Ssam if (psp->ps_map.mcntr < psp->ps_map.nmaddrs) { 58225476Ssam psmapstart(psp->ps_map.maddrs[psp->ps_map.mcntr++], 58325476Ssam psp, psaddr); 58425476Ssam return (1); 58525476Ssam } 58625476Ssam return (0); 5877296Ssam } 5887296Ssam 5897296Ssam pssetmapbounds(psp, psaddr) 5907296Ssam register struct ps *psp; 5917296Ssam register struct psdevice *psaddr; 5927296Ssam { 59325476Ssam u_short start, last; 5947296Ssam 59525476Ssam PSWAIT(psaddr); psaddr->ps_addr = MAOL; 59625476Ssam PSWAIT(psaddr); 5978572Sroot if (psp->ps_dbuffer.state == ON_DB) { 59825472Ssam start = psp->ps_dbuffer.dbaddrs[!psp->ps_dbuffer.rbuffer]; 59925472Ssam last = start+psp->ps_dbuffer.dbsize-2; /* 2 for halt cmd */ 60025472Ssam psaddr->ps_data = last; 60125476Ssam PSWAIT(psaddr); psaddr->ps_data = start; 6027296Ssam } else { 6037296Ssam start = psaddr->ps_data; /* dummy: don't update limit */ 60425476Ssam PSWAIT(psaddr); psaddr->ps_data = psp->ps_map.outputstart; 6057296Ssam } 6067296Ssam } 6077296Ssam 6087296Ssam psmapstart(dfaddr, psp, psaddr) 60925476Ssam u_short dfaddr; 6107296Ssam register struct ps *psp; 6117296Ssam register struct psdevice *psaddr; 6127296Ssam { 6137296Ssam 61425476Ssam PSWAIT(psaddr); psaddr->ps_addr = MAIA; 61525476Ssam PSWAIT(psaddr); psaddr->ps_data = dfaddr; 61625476Ssam PSWAIT(psaddr); psaddr->ps_data = MAO|MAI; /* may want more here */ 6177296Ssam psp->ps_map.mode = RUNNING_MAP; 6187296Ssam } 6197296Ssam 62025472Ssam int pskillcnt = 1; 62125472Ssam 62225472Ssam psmapstop(psaddr, psp, request) 6237296Ssam register struct psdevice *psaddr; 62425472Ssam register struct ps *psp; 62525476Ssam short request; 6267296Ssam { 62725472Ssam register int i; 6287296Ssam 62925476Ssam request &= HALT_REQ|MOSTOP_REQ; /* overkill?? */ 63025476Ssam for (i = 0; i < pskillcnt; i++) { 63125476Ssam PSWAIT(psaddr); psaddr->ps_addr = MASR; 63225476Ssam PSWAIT(psaddr); psaddr->ps_data = IOUT; /* zero MAI & MAO */ 63325476Ssam PSWAIT(psaddr); psaddr->ps_addr = MAIA; 63425476Ssam PSWAIT(psaddr); psaddr->ps_data = 0; /* 0 input addr reg */ 63525476Ssam PSWAIT(psaddr); psaddr->ps_addr = MAOA; 63625476Ssam PSWAIT(psaddr); psaddr->ps_data = 0; /* 0 output addr reg */ 63725476Ssam PSWAIT(psaddr); psaddr->ps_addr = SYSREQ; 63825476Ssam PSWAIT(psaddr); psaddr->ps_data = request; 63925472Ssam } 64025472Ssam psp->ps_map.mode = STOPPED_MAP; 6417296Ssam } 6427296Ssam 6437296Ssam /*ARGSUSED*/ 6447296Ssam psdeviceintr(dev) 6457296Ssam dev_t dev; 6467296Ssam { 6477296Ssam 6487296Ssam printf("ps device intr\n"); 6497296Ssam } 6507296Ssam 6517296Ssam /*ARGSUSED*/ 6527296Ssam psdmaintr(dev) 6537296Ssam dev_t dev; 6547296Ssam { 6557296Ssam 6567296Ssam printf("ps dma intr\n"); 6577296Ssam } 6587296Ssam 65925472Ssam /*ARGSUSED*/ 6607296Ssam psreset(uban) 6617296Ssam int uban; 6627296Ssam { 66325476Ssam 6647296Ssam } 6657296Ssam 66625472Ssam /*ARGSUSED*/ 66725476Ssam psextsync(PC, PS) 66825476Ssam { 6697296Ssam register int n; 6707296Ssam register struct psdevice *psaddr; 6717296Ssam register struct ps *psp; 6727296Ssam register int savepsaddr; 6737296Ssam 6747296Ssam #ifdef EXTERNAL_SYNC 6758572Sroot for (psp = ps, n = 0; n < NPS; psp++, n++) { 6768572Sroot if (!psp->ps_open) 6777296Ssam continue; 67825476Ssam if (psp->ps_refresh.mode == SYNCING_RF && 67925476Ssam psp->ps_refresh.state != TIME_RF) { 68025476Ssam psaddr = (struct psdevice *)psdinfo[n]->ui_addr; 68125476Ssam SAVEPSADDR(psaddr, savepsaddr); 68225472Ssam (void) psrfnext(psp, psaddr); 68325476Ssam RESTORPSADDR(psaddr, savepsaddr); 6847296Ssam } else { 68525476Ssam psp->ps_clockticks++; 68625476Ssam psp->ps_clockmiss++; 6877296Ssam } 6887296Ssam } 6897296Ssam #endif 6907296Ssam } 6917296Ssam #endif 692