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