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