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