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