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