create netif directory
[unix-history] / usr / src / sys / vax / uba / ps.c
CommitLineData
7da157da 1/* ps.c 4.7 82/10/17 */
705372a2
SL
2
3/*
4 * Evans and Sutherland Picture System 2 driver
5 */
6
7/*
8 * Still to be done:
9 * WAIT_HIT
10 */
11
12#include "ps.h"
13#if NPS > 0
14
15#define EXTERNAL_SYNC
16
17#include "../h/param.h"
18#include "../h/systm.h"
19#include "../h/tty.h"
20#include "../h/pte.h"
21#include "../h/map.h"
22#include "../h/buf.h"
705372a2
SL
23#include "../h/conf.h"
24#include "../h/dir.h"
25#include "../h/user.h"
740e4029 26#include "../h/uio.h"
705372a2 27
896962b1
BJ
28#include "../vaxuba/ubareg.h"
29#include "../vaxuba/ubavar.h"
30#include "../vaxuba/psreg.h"
31
705372a2
SL
32int psprobe(), psattach(), psintr();
33struct uba_device *psdinfo[NPS];
34u_short psstd[] = { 0 };
35struct uba_driver psdriver =
36 { psprobe, 0, psattach, 0, psstd, "ps", psdinfo };
37
38#define PSUNIT(dev) (minor(dev))
39
40#define MAXAUTOREFRESH (4)
41#define MAXAUTOMAP (4)
42#define MAXDBSIZE (0177777/2)
43
44#define PSPRI (PZERO+1)
45
46#define PSWAIT() {register short int i, j; i=20000; while((i-- != 0)\
47 && (((j=psaddr->ps_iostat)&DIOREADY)==0));}
48
49struct ps {
50 char ps_open;
51 short int ps_uid;
52 struct {
53 enum { SINGLE_STEP_RF, AUTO_RF } state;
54 enum { RUNNING_RF, SYNCING_RF, WAITING_MAP } mode;
55 unsigned short int sraddrs[MAXAUTOREFRESH];
56 short int nsraddrs;
57 short int srcntr;
58 char waiting;
59 char stop;
60 int icnt;
61 } ps_refresh;
62 struct {
63 enum { ON_DB, OFF_DB } state;
64 unsigned short int dbaddrs[2];
65 unsigned short int dbsize;
66 short int rbuffer;
67 } ps_dbuffer;
68 struct {
69 enum { SINGLE_STEP_MAP, AUTO_MAP } state;
70 enum { RUNNING_MAP, WAITING_RF, WAITING_START } mode;
71 unsigned short int maddrs[MAXAUTOMAP];
72 short int nmaddrs;
73 short int mcntr;
74 short int outputstart;
75 char waiting;
76 char stop;
77 int icnt;
78 } ps_map;
79 struct {
80 short int ticked;
81 short int missed;
82 int icnt;
83 } ps_clock;
84 struct {
85 int icnt;
86 } ps_hit;
87 int ps_strayintr;
88 int last_request;
89 int strayrequest;
90} ps[NPS];
91
92psprobe(reg)
93 caddr_t reg;
94{
95 register int br, cvec;
96 register struct psdevice *psaddr = (struct psdevice *) reg;
97
98 psaddr->ps_iostat = PSRESET;
99 DELAY(200);
100 psaddr->ps_addr = RTCIE;
101 PSWAIT();
102 psaddr->ps_data = 01;
103 psaddr->ps_iostat = PSIE;
104 psaddr->ps_addr = RTCSR;
105 PSWAIT();
106 psaddr->ps_data = (SYNC|RUN);
107 DELAY(200000);
108 psaddr->ps_addr = RTCREQ;
109 PSWAIT();
110 psaddr->ps_data = 01;
111 psaddr->ps_iostat = 0;
112 psaddr->ps_iostat = PSRESET;
9c0adba0 113 return (sizeof (struct psdevice));
705372a2
SL
114}
115
116/*ARGSUSED*/
117psattach(ui)
118 register struct uba_device *ui;
119{
705372a2 120
7da157da 121}
705372a2
SL
122
123psopen(dev)
124 dev_t dev;
125{
126 register struct ps *psp;
127 register struct uba_device *ui;
128 register int unit = PSUNIT(dev);
129
7da157da
BJ
130 if (unit >= NPS || (psp = &ps[minor(dev)])->ps_open ||
131 (ui = psdinfo[unit]) == 0 || ui->ui_alive == 0)
132 return (ENXIO);
705372a2
SL
133 psp->ps_open = 1;
134 psp->ps_uid = u.u_uid;
135 psp->ps_strayintr = 0;
136 psp->ps_refresh.state = SINGLE_STEP_RF;
137 psp->ps_refresh.waiting = 0;
138 psp->ps_refresh.stop = 0;
139 psp->ps_dbuffer.state = OFF_DB;
140 psp->ps_map.state = SINGLE_STEP_MAP;
141 psp->ps_map.waiting = 0;
142 psp->ps_map.stop = 0;
143 psp->ps_clock.ticked = 0;
144 psp->ps_refresh.icnt = psp->ps_map.icnt = psp->ps_clock.icnt = 0;
145 maptouser(ui->ui_addr);
7da157da 146 return (0);
705372a2
SL
147}
148
149psclose(dev)
150 dev_t dev;
151{
152 register struct psdevice *psaddr =
153 (struct psdevice *) psdinfo[PSUNIT(dev)]->ui_addr;
154
155 ps[PSUNIT(dev)].ps_open = 0;
156 psaddr->ps_iostat = 0; /* clear IENABLE */
157 PSWAIT();
158 psaddr->ps_addr = RFSR; /* set in auto refresh mode */
159 PSWAIT();
160 psaddr->ps_data = AUTOREF;
161 unmaptouser(psaddr);
162}
163
164/*ARGSUSED*/
740e4029 165psread(dev, uio)
705372a2 166 dev_t dev;
740e4029 167 struct uio *uio;
705372a2
SL
168{
169}
170
171/*ARGSUSED*/
740e4029 172pswrite(dev, uio)
705372a2 173 dev_t dev;
740e4029 174 struct uio *uio;
705372a2
SL
175{
176}
177
178/*ARGSUSED*/
942f05a9
SL
179psioctl(dev, cmd, data, flag)
180 register caddr_t data;
705372a2
SL
181{
182 register struct uba_device *ui = psdinfo[PSUNIT(dev)];
183 register struct ps *psp = &ps[PSUNIT(dev)];
942f05a9 184 int *waddr = *(int **)data;
705372a2
SL
185 int n, arg, i;
186
187 switch (cmd) {
942f05a9
SL
188
189 case PSIOGETADDR:
190 *(caddr_t *)data = ui->ui_addr;
705372a2 191 break;
942f05a9
SL
192
193 case PSIOAUTOREFRESH:
705372a2 194 n = fuword(waddr++);
7da157da
BJ
195 if (n == -1)
196 return (EFAULT);
197 if (n < 0 || n > MAXAUTOREFRESH)
198 return (EINVAL);
199 for (i = 0; i < n; i++) {
200 if ((arg = fuword(waddr++)) == -1)
201 return (EFAULT);
202 psp->ps_refresh.sraddrs[i] = arg;
705372a2 203 }
7da157da
BJ
204 psp->ps_refresh.state = AUTO_RF;
205 psp->ps_refresh.nsraddrs = n;
206 psp->ps_refresh.srcntr = 0;
207 psp->ps_refresh.mode = WAITING_MAP;
705372a2 208 break;
942f05a9
SL
209
210 case PSIOAUTOMAP:
705372a2 211 n = fuword(waddr++);
7da157da
BJ
212 if (n == -1)
213 return (EFAULT);
214 if (n < 0 || n > MAXAUTOMAP)
215 return (EINVAL);
216 for (i = 0; i < n; i++) {
217 if ((arg = fuword(waddr++)) == -1)
218 return (EFAULT);
219 psp->ps_map.maddrs[i] = arg;
705372a2 220 }
7da157da
BJ
221 if ((arg = fuword(waddr++)) == -1)
222 return (EFAULT);
223 psp->ps_map.outputstart = arg;
224 psp->ps_map.state = AUTO_MAP;
225 psp->ps_map.nmaddrs = n;
226 psp->ps_map.mcntr = 0;
227 psp->ps_map.mode = WAITING_START;
705372a2 228 break;
942f05a9
SL
229
230 case PSIOSINGLEREFRESH:
705372a2
SL
231 psp->ps_refresh.state = SINGLE_STEP_RF;
232 break;
942f05a9
SL
233
234 case PSIOSINGLEMAP:
705372a2
SL
235 psp->ps_map.state = SINGLE_STEP_MAP;
236 break;
942f05a9
SL
237
238 case PSIODOUBLEBUFFER:
7da157da
BJ
239 if ((arg = fuword(waddr++)) == -1)
240 return (EFAULT);
241 psp->ps_dbuffer.dbaddrs[0] = arg;
242 if ((arg = fuword(waddr++)) == -1)
243 return (EFAULT);
244 if (arg <= 0 || arg > MAXDBSIZE)
245 return (EINVAL);
246 psp->ps_dbuffer.dbsize = arg;
247 psp->ps_dbuffer.dbaddrs[1] =
248 psp->ps_dbuffer.dbaddrs[0]+arg;
249 psp->ps_dbuffer.state = ON_DB;
250 psp->ps_dbuffer.rbuffer = 0;
705372a2
SL
251 }
252 break;
942f05a9
SL
253
254 case PSIOSINGLEBUFFER:
705372a2
SL
255 psp->ps_dbuffer.state = OFF_DB;
256 break;
942f05a9
SL
257
258 case PSIOWAITREFRESH:
7da157da
BJ
259 if (psp->ps_refresh.mode != RUNNING_RF) /* not running */
260 return (0); /* dont wait */
261 /* fall into ... */
942f05a9
SL
262
263 case PSSIOTOPREFRESH:
7da157da 264 if (cmd == PSSTOPREFRESH)
705372a2
SL
265 psp->ps_refresh.stop = 1;
266 spl5();
267 psp->ps_refresh.waiting = 1;
7da157da 268 while (psp->ps_refresh.waiting)
705372a2
SL
269 sleep(&psp->ps_refresh.waiting, PSPRI);
270 spl0();
271 break;
942f05a9
SL
272
273 case PSIOWAITMAP:
7da157da
BJ
274 if (psp->ps_map.mode != RUNNING_MAP) /* not running */
275 return (0); /* dont wait */
276 /* fall into ... */
942f05a9
SL
277
278 case PSIOSTOPMAP:
7da157da 279 if (cmd == PSSTOPMAP)
705372a2
SL
280 psp->ps_map.stop = 1;
281 spl5();
282 psp->ps_map.waiting = 1;
7da157da 283 while (psp->ps_map.waiting)
705372a2
SL
284 sleep(&psp->ps_map.waiting, PSPRI);
285 spl0();
286 break;
942f05a9 287
705372a2 288 default:
7da157da 289 return (ENOTTY);
705372a2
SL
290 break;
291 }
7da157da 292 return (0);
705372a2
SL
293}
294
295#define SAVEPSADDR() {register short int i, x;x=spl6();i=psaddr->ps_addr;\
296 while(((i=psaddr->ps_iostat)&DIOREADY)==0);\
297 savepsaddr=psaddr->ps_data;splx(x);}
298#define RESTORPSADDR() {register int x,i;x=spl6();\
299 while(((i=psaddr->ps_iostat)&DIOREADY)==0);\
300 psaddr->ps_addr=savepsaddr;splx(x);}
301
302psclockintr(dev)
303 dev_t dev;
304{
305 register struct psdevice *psaddr =
306 (struct psdevice *) psdinfo[PSUNIT(dev)]->ui_addr;
307 register struct ps *psp = &ps[PSUNIT(dev)];
308 int savepsaddr;
309
7da157da 310 if (!psp->ps_open)
705372a2
SL
311 return;
312 psp->ps_clock.icnt++;
313 SAVEPSADDR();
314#ifndef EXTERNAL_SYNC
7da157da
BJ
315 if (psp->ps_refresh.state == AUTO_RF) {
316 if (psp->ps_refresh.mode == SYNCING_RF) {
705372a2
SL
317 psrfnext(psp, psaddr);
318 } else {
319 psp->ps_clock.ticked++;
320 psp->ps_clock.missed++;
321 }
322 }
323#endif
324 PSWAIT();
325 psaddr->ps_addr = RTCREQ;
326 PSWAIT();
327 psaddr->ps_data = 01; /* clear the request bits */
328 RESTORPSADDR();
329}
330
331/*ARGSUSED*/
332pssystemintr(dev)
333 dev_t dev;
334{
335 register struct psdevice *psaddr =
336 (struct psdevice *) psdinfo[PSUNIT(dev)]->ui_addr;
337 register struct ps *psp = &ps[PSUNIT(dev)];
338 short int request;
339 register int savepsaddr, x;
340
7da157da 341 if (!psp->ps_open)
705372a2
SL
342 return;
343 SAVEPSADDR();
344 PSWAIT();
345 psaddr->ps_addr = SYSREQ;
346 PSWAIT();
347 request = psaddr->ps_data;
348 psp->last_request = request;
349 PSWAIT();
350 psaddr->ps_addr = SYSREQ;
351 PSWAIT();
352 psaddr->ps_data = request&(~(HALT_REQ|MOSTOP_REQ)); /* acknowledge */
353
7da157da 354 if (request & (MOSTOP_REQ|HALT_REQ)) { /* Map stopped */
705372a2
SL
355 psp->ps_map.icnt++;
356 psmapstop(psaddr); /* kill it dead */
7da157da 357 if (psp->ps_map.waiting) {
705372a2
SL
358 psp->ps_map.waiting = 0;
359 wakeup(&psp->ps_map.waiting);
7da157da 360 if (psp->ps_map.stop) {
705372a2
SL
361 psp->ps_map.stop = 0;
362 goto tryrf;
363 }
364 }
7da157da
BJ
365 if (psp->ps_map.state == AUTO_MAP)
366 if (!psmapnext(psp, psaddr)) {
705372a2
SL
367 psp->ps_map.mcntr = 0;
368 /* prepare for next round */
369 pssetmapbounds(psp, psaddr);
7da157da
BJ
370 if (psp->ps_refresh.mode == WAITING_MAP) {
371 if (psp->ps_dbuffer.state == ON_DB)
705372a2
SL
372 /* fill other db */
373 psdbswitch(psp, psaddr);
374 else
375 psp->ps_map.mode = WAITING_RF;
376 psrfnext(psp, psaddr); /* start rf */
377 } else
378 psp->ps_map.mode = WAITING_RF;
379 }
380 }
381tryrf:
7da157da 382 if (request & RFSTOP_REQ) { /* Refresh stopped */
705372a2
SL
383 psp->ps_refresh.icnt++;
384 psrfstop(psaddr, psp);
7da157da 385 if (psp->ps_refresh.waiting) {
705372a2
SL
386 psp->ps_refresh.waiting = 0;
387 wakeup(&psp->ps_refresh.waiting);
7da157da 388 if (psp->ps_refresh.stop) {
705372a2
SL
389 psp->ps_refresh.stop = 0;
390 goto tryhit;
391 }
392 }
7da157da
BJ
393 if (psp->ps_refresh.state == AUTO_RF)
394 if (!psrfnext(psp, psaddr)) { /* at end of refresh cycle */
395 if (psp->ps_map.state == AUTO_MAP &&
705372a2 396 psp->ps_map.mode==WAITING_RF) {
7da157da 397 if (psp->ps_dbuffer.state == ON_DB)
705372a2
SL
398 psdbswitch(psp, psaddr);
399 else
400 psmapnext(psp, psaddr);
401 }
402 psp->ps_refresh.srcntr = 0;
403#ifdef EXTERNAL_SYNC
404 x = spl6();
405#endif
7da157da 406 if (!psp->ps_clock.ticked ||
705372a2
SL
407 !psrfnext(psp, psaddr)) {
408 psp->ps_refresh.mode = SYNCING_RF;
409 }
410 psp->ps_clock.ticked = 0;
411 psp->ps_refresh.mode = SYNCING_RF;
412#ifdef EXTERNAL_SYNC
413 splx(x);
414#endif
415 }
416 }
417tryhit:
7da157da 418 if (request & HIT_REQ) { /* Hit request */
705372a2
SL
419 psp->ps_hit.icnt++;
420 }
7da157da 421 if (request == 0)
705372a2
SL
422 psp->ps_strayintr++;
423 RESTORPSADDR();
424}
425
426psrfnext(psp, psaddr)
427 register struct ps *psp;
428 register struct psdevice *psaddr;
429{
430
7da157da 431 if (psp->ps_refresh.srcntr < psp->ps_refresh.nsraddrs)
705372a2
SL
432 psrfstart(psp->ps_refresh.sraddrs[psp->ps_refresh.srcntr++],
433 psp, psaddr);
7da157da 434 else if (psp->ps_refresh.srcntr == psp->ps_refresh.nsraddrs
705372a2
SL
435 && psp->ps_dbuffer.state == ON_DB) {
436 psrfstart(psp->ps_dbuffer.dbaddrs[psp->ps_dbuffer.rbuffer],
437 psp, psaddr);
438 psp->ps_refresh.srcntr++; /* flag for after dbuffer */
439 } else
440 return(0);
441 return(1);
442}
443
444psrfstart(dfaddr, psp, psaddr)
445 short int dfaddr;
446 register struct ps *psp;
447 register struct psdevice *psaddr;
448{
449 int dummy;
450
451 PSWAIT();
452 psaddr->ps_addr = RFASA;
453 PSWAIT();
454 psaddr->ps_data = dfaddr;
455 PSWAIT();
456 dummy = psaddr->ps_data; /* just access to get to status reg */
457 PSWAIT();
458 psaddr->ps_data = RFSTART; /* may want to | this value in */
459 psp->ps_refresh.mode = RUNNING_RF;
460}
461
462psrfstop(psaddr, psp)
463 register struct psdevice *psaddr;
464 register struct ps *psp;
465{
466
467 PSWAIT();
468 psaddr->ps_addr = RFSR;
469 PSWAIT();
470 psaddr->ps_data = 0;
471}
472
473psdbswitch(psp, psaddr)
474 register struct ps *psp;
475 register struct psdevice *psaddr;
476{
477
478 psp->ps_dbuffer.rbuffer = !psp->ps_dbuffer.rbuffer;
479 pssetmapbounds(psp, psaddr);
480 psmapnext(psp, psaddr);
481}
482
483psmapnext(psp, psaddr)
484 register struct ps *psp;
485 register struct psdevice *psaddr;
486{
487
7da157da 488 if (psp->ps_map.mcntr < psp->ps_map.nmaddrs)
705372a2
SL
489 psmapstart(psp->ps_map.maddrs[psp->ps_map.mcntr++], psp, psaddr);
490 else
491 return(0);
492 return(1);
493}
494
495pssetmapbounds(psp, psaddr)
496 register struct ps *psp;
497 register struct psdevice *psaddr;
498{
499 unsigned short int start;
500
501 PSWAIT();
502 psaddr->ps_addr = MAOL;
503 PSWAIT();
7da157da 504 if (psp->ps_dbuffer.state == ON_DB) {
705372a2
SL
505 psaddr->ps_data = (start = psp->ps_dbuffer.dbaddrs[!psp->ps_dbuffer.rbuffer])
506 +psp->ps_dbuffer.dbsize-2; /* 2 for a refresh halt command */
507 PSWAIT();
508 psaddr->ps_data = start;
509 } else {
510 start = psaddr->ps_data; /* dummy: don't update limit */
511 PSWAIT();
512 psaddr->ps_data = psp->ps_map.outputstart;
513 }
514}
515
516psmapstart(dfaddr, psp, psaddr)
517 int dfaddr;
518 register struct ps *psp;
519 register struct psdevice *psaddr;
520{
521 int data;
522
523 PSWAIT();
524 psaddr->ps_addr = MAIA;
525 PSWAIT();
526 psaddr->ps_data = dfaddr;
527 PSWAIT();
528 psaddr->ps_data = MAO|MAI; /* may want more here */
529 psp->ps_map.mode = RUNNING_MAP;
530}
531
532psmapstop(psaddr)
533 register struct psdevice *psaddr;
534{
535
536 PSWAIT();
537 psaddr->ps_addr = MASR;
538 PSWAIT();
539 psaddr->ps_data = 0; /* zero MAI bit */
540 PSWAIT();
541 psaddr->ps_addr = MAIA;
542 PSWAIT();
543 psaddr->ps_data = 0; /* zero input address register */
544 PSWAIT();
545 psaddr->ps_addr = SYSREQ;
546 PSWAIT();
547 psaddr->ps_data = HALT_REQ|MOSTOP_REQ; /* overkill?? */
548}
549
550/*ARGSUSED*/
551psdeviceintr(dev)
552 dev_t dev;
553{
554
555 printf("ps device intr\n");
556}
557
558/*ARGSUSED*/
559psdmaintr(dev)
560 dev_t dev;
561{
562
563 printf("ps dma intr\n");
564}
565
566psreset(uban)
567 int uban;
568{
569}
570
571psextsync(PC, PS) {
572 register int n;
573 register struct psdevice *psaddr;
574 register struct ps *psp;
575 register int savepsaddr;
576
577#ifdef EXTERNAL_SYNC
7da157da
BJ
578 for (psp = ps, n = 0; n < NPS; psp++, n++) {
579 if (!psp->ps_open)
705372a2 580 continue;
7da157da 581 if (psp->ps_refresh.mode == SYNCING_RF) {
705372a2
SL
582 psaddr = (struct psdevice *) psdinfo[n]->ui_addr;
583 SAVEPSADDR();
584 psrfnext(psp, psaddr);
585 RESTORPSADDR();
586 } else {
587 psp->ps_clock.ticked++;
588 psp->ps_clock.missed++;
589 }
590 }
591#endif
592}
593#endif