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