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