xref: /csrg-svn/sys/vax/uba/ps.c (revision 9552)
1 /*	ps.c	4.8	82/12/05	*/
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/ioctl.h"
20 #include "../h/pte.h"
21 #include "../h/map.h"
22 #include "../h/buf.h"
23 #include "../h/conf.h"
24 #include "../h/dir.h"
25 #include "../h/user.h"
26 #include "../h/uio.h"
27 
28 #include "../vaxuba/ubareg.h"
29 #include "../vaxuba/ubavar.h"
30 #include "../vaxuba/psreg.h"
31 
32 int	psprobe(), psattach(), psintr();
33 struct	uba_device *psdinfo[NPS];
34 u_short	psstd[] = { 0 };
35 struct	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 
49 struct 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 
92 psprobe(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;
113 	return (sizeof (struct psdevice));
114 }
115 
116 /*ARGSUSED*/
117 psattach(ui)
118 	register struct uba_device *ui;
119 {
120 
121 }
122 
123 psopen(dev)
124 	dev_t dev;
125 {
126 	register struct ps *psp;
127 	register struct uba_device *ui;
128 	register int unit = PSUNIT(dev);
129 
130 	if (unit >= NPS || (psp = &ps[minor(dev)])->ps_open ||
131 	    (ui = psdinfo[unit]) == 0 || ui->ui_alive == 0)
132 		return (ENXIO);
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);
146 	return (0);
147 }
148 
149 psclose(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*/
165 psread(dev, uio)
166 	dev_t dev;
167 	struct uio *uio;
168 {
169 }
170 
171 /*ARGSUSED*/
172 pswrite(dev, uio)
173 	dev_t dev;
174 	struct uio *uio;
175 {
176 }
177 
178 /*ARGSUSED*/
179 psioctl(dev, cmd, data, flag)
180 	register caddr_t data;
181 {
182 	register struct uba_device *ui = psdinfo[PSUNIT(dev)];
183 	register struct ps *psp = &ps[PSUNIT(dev)];
184 	int *waddr = *(int **)data;
185 	int n, arg, i;
186 
187 	switch (cmd) {
188 
189 	case PSIOGETADDR:
190 		*(caddr_t *)data = ui->ui_addr;
191 		break;
192 
193 	case PSIOAUTOREFRESH:
194 		n = fuword(waddr++);
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;
203 		}
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;
208 		break;
209 
210 	case PSIOAUTOMAP:
211 		n = fuword(waddr++);
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;
220 		}
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;
228 		break;
229 
230 	case PSIOSINGLEREFRESH:
231 		psp->ps_refresh.state = SINGLE_STEP_RF;
232 		break;
233 
234 	case PSIOSINGLEMAP:
235 		psp->ps_map.state = SINGLE_STEP_MAP;
236 		break;
237 
238 	case PSIODOUBLEBUFFER:
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;
251 		}
252 		break;
253 
254 	case PSIOSINGLEBUFFER:
255 		psp->ps_dbuffer.state = OFF_DB;
256 		break;
257 
258 	case PSIOWAITREFRESH:
259 		if (psp->ps_refresh.mode != RUNNING_RF)	/* not running */
260 			return (0);				/* dont wait */
261 		/* fall into ... */
262 
263 	case PSSIOTOPREFRESH:
264 		if (cmd == PSSTOPREFRESH)
265 			psp->ps_refresh.stop = 1;
266 		spl5();
267 		psp->ps_refresh.waiting = 1;
268 		while (psp->ps_refresh.waiting)
269 			sleep(&psp->ps_refresh.waiting, PSPRI);
270 		spl0();
271 		break;
272 
273 	case PSIOWAITMAP:
274 		if (psp->ps_map.mode != RUNNING_MAP)	/* not running */
275 			return (0);				/* dont wait */
276 		/* fall into ... */
277 
278 	case PSIOSTOPMAP:
279 		if (cmd == PSSTOPMAP)
280 			psp->ps_map.stop = 1;
281 		spl5();
282 		psp->ps_map.waiting = 1;
283 		while (psp->ps_map.waiting)
284 			sleep(&psp->ps_map.waiting, PSPRI);
285 		spl0();
286 		break;
287 
288 	default:
289 		return (ENOTTY);
290 		break;
291 	}
292 	return (0);
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 
302 psclockintr(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 
310 	if (!psp->ps_open)
311 		return;
312 	psp->ps_clock.icnt++;
313 	SAVEPSADDR();
314 #ifndef EXTERNAL_SYNC
315 	if (psp->ps_refresh.state == AUTO_RF) {
316 		if (psp->ps_refresh.mode == SYNCING_RF) {
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*/
332 pssystemintr(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 
341 	if (!psp->ps_open)
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 
354 	if (request & (MOSTOP_REQ|HALT_REQ)) {	/* Map stopped */
355 		psp->ps_map.icnt++;
356 		psmapstop(psaddr);		/* kill it dead */
357 		if (psp->ps_map.waiting) {
358 			psp->ps_map.waiting = 0;
359 			wakeup(&psp->ps_map.waiting);
360 			if (psp->ps_map.stop) {
361 				psp->ps_map.stop = 0;
362 				goto tryrf;
363 			}
364 		}
365 		if (psp->ps_map.state == AUTO_MAP)
366 			if (!psmapnext(psp, psaddr)) {
367 				psp->ps_map.mcntr = 0;
368 				/* prepare for next round */
369 				pssetmapbounds(psp, psaddr);
370 				if (psp->ps_refresh.mode == WAITING_MAP) {
371 					if (psp->ps_dbuffer.state == ON_DB)
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 	}
381 tryrf:
382 	if (request & RFSTOP_REQ) {		/* Refresh stopped */
383 		psp->ps_refresh.icnt++;
384 		psrfstop(psaddr, psp);
385 		if (psp->ps_refresh.waiting) {
386 			psp->ps_refresh.waiting = 0;
387 			wakeup(&psp->ps_refresh.waiting);
388 			if (psp->ps_refresh.stop) {
389 				psp->ps_refresh.stop = 0;
390 				goto tryhit;
391 			}
392 		}
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 &&
396 						psp->ps_map.mode==WAITING_RF) {
397 					if (psp->ps_dbuffer.state == ON_DB)
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
406 				if (!psp->ps_clock.ticked ||
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 	}
417 tryhit:
418 	if (request & HIT_REQ) {		/* Hit request */
419 		psp->ps_hit.icnt++;
420 	}
421 	if (request == 0)
422 		psp->ps_strayintr++;
423 	RESTORPSADDR();
424 }
425 
426 psrfnext(psp, psaddr)
427 	register struct ps *psp;
428 	register struct psdevice *psaddr;
429 {
430 
431 	if (psp->ps_refresh.srcntr < psp->ps_refresh.nsraddrs)
432 		psrfstart(psp->ps_refresh.sraddrs[psp->ps_refresh.srcntr++],
433 						psp, psaddr);
434 	else if (psp->ps_refresh.srcntr == psp->ps_refresh.nsraddrs
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 
444 psrfstart(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 
462 psrfstop(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 
473 psdbswitch(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 
483 psmapnext(psp, psaddr)
484 	register struct ps *psp;
485 	register struct psdevice *psaddr;
486 {
487 
488 	if (psp->ps_map.mcntr < psp->ps_map.nmaddrs)
489 		psmapstart(psp->ps_map.maddrs[psp->ps_map.mcntr++], psp, psaddr);
490 	else
491 		return(0);
492 	return(1);
493 }
494 
495 pssetmapbounds(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();
504 	if (psp->ps_dbuffer.state == ON_DB) {
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 
516 psmapstart(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 
532 psmapstop(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*/
551 psdeviceintr(dev)
552 	dev_t dev;
553 {
554 
555 	printf("ps device intr\n");
556 }
557 
558 /*ARGSUSED*/
559 psdmaintr(dev)
560 	dev_t dev;
561 {
562 
563 	printf("ps dma intr\n");
564 }
565 
566 psreset(uban)
567 	int uban;
568 {
569 }
570 
571 psextsync(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
578 	for (psp = ps, n = 0; n < NPS; psp++, n++) {
579 		if (!psp->ps_open)
580 			continue;
581 		if (psp->ps_refresh.mode == SYNCING_RF) {
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
594