xref: /original-bsd/sys/vax/uba/qd.c (revision 883fb6be)
1 
2 #ifndef lint
3 static char *sccsid = "@(#)qd.c	1.40	ULTRIX	10/2/86";
4 #endif lint
5 
6 /************************************************************************
7  *									*
8  *			Copyright (c) 1985, 1986 by			*
9 *		Digital Equipment Corporation, Maynard, MA		*
10 *			All rights reserved.				*
11 *									*
12 *   This software is furnished under a license and may be used and	*
13 *   copied  only  in accordance with the terms of such license and	*
14 *   with the  inclusion  of  the  above  copyright  notice.   This	*
15 *   software  or  any  other copies thereof may not be provided or	*
16 *   otherwise made available to any other person.  No title to and	*
17 *   ownership of the software is hereby transferred.			*
18 *									*
19 *   The information in this software is subject to change  without	*
20 *   notice  and should not be construed as a commitment by Digital	*
21 *   Equipment Corporation.						*
22 *									*
23 *   Digital assumes no responsibility for the use  or  reliability	*
24 *   of its software on equipment which is not supplied by Digital.	*
25 *									*
26 *************************************************************************/
27 
28 /*
29  * qd.c
30  *
31  * Modification history
32  *
33  * QDSS workstation driver
34  *
35  * 26-Aug-86 - rsp (Ricky Palmer)
36  *
37  *	Cleaned up devioctl code to (1) zero out devget structure
38  *	upon entry and (2) use strlen instead of fixed storage
39  *	for bcopy's.
40  *
41  * 21-Jul-86 - Ram Rao
42  *	allowed cursor rectangle to hang (partially) off the
43  *	top and left of screen
44  *
45  * 11-Jul-86 - ricky palmer
46  *
47  *	Added adpt and nexus fields to DEVIOCGET code.
48  *
49  * 02-July-86 - Brian Stevens
50  *
51  *	added support for console writing to second QDSS display
52  *
53  * 20-May-86 - ricky palmer
54  *
55  *	Added new DEVIOCGET ioctl request code. V2.0
56  *
57  * 16-Apr-86 -- darrell
58  *	 badaddr is now called via the macro BADADDR
59  *
60  * 14-Apr-86 -- afd
61  *	 Changed UMEMmap to QMEMmap and umem to qmem.
62  *
63  *	 v_console() is now refered to as v_consputc, and there is a
64  *	 corresponding v_consgetc() (defined in /sys/vax/conf.c).
65  *
66  *	 Added "qdgetc()" routine for console read.  Needed to read
67  *	 user's answer to the "root device?" prompt with a generic kernel.
68  *
69  * 19-Mar-86 -- pmk
70  *	 Change DELAY to 20000, because microdelay now in real microsec.
71  *
72  * 18-mar-86  -- jaw	 br/cvec changed to NOT use registers.
73  *
74  * 11 mar 86  darrell	replaced percpu with cpusw, and removed all but
75  *			 one global reference
76  * 19 feb 86  bstevens	no report of motion event on puck/stylus button action
77  * 18 feb 86  bstevens	put in cursor box support for tablets
78  * 18-Mar-86 -- jaw  add routines to cpu switch for nexus/unibus addreses
79  *		      also got rid of some globals like nexnum.
80  *		      ka8800 cleanup.
81  * 06 dec 85  longo  added LK-201 error reporting for graphics device ops
82  * 03 dec 85  longo  made qddint() clear active bit on error
83  * 02 dec 85  longo  fixed up some crocks in the error messages
84  * 25 nov 85  longo  added error handling to DMA ISR and single user locking
85  * 19 nov 85  longo  eliminated "set_defaults()" by breaking out sub-calls.
86  *		     Changed init_shared to do real init of scroll struct
87  * 12 nov 85  longo  fixed bug in open that broke alternate console re-direct
88  * 11 nov 85  longo  changed "_vs_eventqueue" references to "qdinput"
89  * 08 nov 85  longo  improved select service for read/write select wakeup.
90  *		     Also set ISR's to ipl4 to allow the interval timer in.
91  * 04 nov 85  longo  fixed bugs in mouse button reporting and dma request stuff
92  * 30 oct 85  longo  DMA to/from user space is in place
93  * 14 oct 85  longo  added kernel msg redirect and QD_RDCURSOR ioctl
94  * 03 oct 85  longo  added support for multiple QDSS's
95  * 02 oct 85  longo  added color map loading services in qdioctl() & qdaint()
96  * 30 sep 85  longo  added DMA interrupt services
97  * 18 sep 85  longo  added scroll services to "qdaint()" adder intrpt service
98  *		     and put in supporting ioctl's
99  * 04 sep 85  longo  initial implementation of DMA is working
100  * 17 aug 85  longo  added support for the QDSS to be system console
101  * 05 aug 85  longo  now using qfont (QVSS & QDSS) as linked object
102  * 12 jun 85  longo  added mouse event loading to "qdiint()"
103  * 31 may 85  longo  put live interrupts into the probe() routine
104  * 30 may 85  longo  event queue shared memory implementation is now alive
105  * 29 may 85  longo  LK-201 input is now interrupt driven
106  * 25 apr 85  longo  MAPDEVICE works
107  * 14 mar 85  longo  created
108  *
109  *	 todo:	 fix rlogin bug in console stuff
110  *		 cat -u console redirection
111  *		 check error return from strategy routine
112  *		 verify TOY time stuff (what format?)
113  *		 look at system based macro implementation of VTOP
114  *
115  */
116 
117 #include "../data/qd_data.c"	/* include external references to data file */
118 
119 /*---------------------------------------------------------------------
120 * macro to get system time.  Used to time stamp event queue entries */
121 
122 #define TOY ((time.tv_sec * 100) + (time.tv_usec / 10000))
123 
124 /*--------------------------------------------------------------------------
125 * the "ioconf.c" program, built and used by auto config, externally refers
126 * to definitions below.  */
127 
128 	int qdprobe();
129 	int qdattach();
130 	int qddint();			/* DMA gate array intrpt service */
131 	int qdaint();			/* Dragon ADDER intrpt service */
132 	int qdiint();
133 
134 	u_short qdstd[] = { 0 };
135 
136 	struct uba_driver qddriver = {	/* externally referenced: ioconf.c */
137 
138 	    qdprobe,			/* device probe entry */
139 	    0,				/* no slave device */
140 	    qdattach,			/* device attach entry */
141 	    0,				/* no "fill csr/ba to start" */
142 	    qdstd,			/* device addresses */
143 	    "qd",			/* device name string */
144 	    qdinfo			/* ptr to QDSS's uba_device struct */
145 	};
146 
147 /*-------------------
148 * general defines */
149 
150 #define QDPRIOR (PZERO-1)		/* must be negative */
151 
152 #define FALSE	0
153 #define TRUE	~FALSE
154 
155 #define BAD	-1
156 #define GOOD	0
157 
158 /*-----------------------------------------------------------------------
159 * macro to create a system virtual page number from system virtual adrs */
160 
161 #define VTOP(x)  (((int)x & ~0xC0000000) >> PGSHIFT) /* convert qmem adrs */
162 						     /* to system page # */
163 
164 /*------------------------------------------------------------------
165 * QDSS register address offsets from start of QDSS address space */
166 
167 #define QDSIZE	 (52 * 1024)	/* size of entire QDSS foot print */
168 
169 #define TMPSIZE  (16 * 1024)	/* template RAM is 8k SHORT WORDS */
170 #define TMPSTART 0x8000 	/* offset of template RAM from base adrs */
171 
172 #define REGSIZE  (5 * 512)	/* regs touch 2.5k (5 pages) of addr space */
173 #define REGSTART 0xC000 	/* offset of reg pages from base adrs */
174 
175 #define ADDER	(REGSTART+0x000)
176 #define DGA	(REGSTART+0x200)
177 #define DUART	(REGSTART+0x400)
178 #define MEMCSR	(REGSTART+0x800)
179 
180 #define CLRSIZE  (3 * 512)		/* color map size */
181 #define CLRSTART (REGSTART+0xA00)	/* color map start offset from base */
182 					/*  0x0C00 really */
183 #define RED	(CLRSTART+0x000)
184 #define BLUE	(CLRSTART+0x200)
185 #define GREEN	(CLRSTART+0x400)
186 
187 /*---------------------------------------------------------------
188 * values used in mapping QDSS hardware into the Q memory space */
189 
190 #define CHUNK	  (64 * 1024)
191 #define QMEMSIZE  (1024 * 1024 * 4)	/* 4 meg */
192 
193 /*----------------------------------------------------------------------
194 * QDSS minor device numbers.  The *real* minor device numbers are in
195 * the bottom two bits of the major/minor device spec.  Bits 2 and up are
196 * used to specify the QDSS device number (ie: which one?) */
197 
198 #define QDSSMAJOR	42		/* QDSS major device number */
199 
200 #define CONS		0
201 #define ALTCONS 	1
202 #define GRAPHIC 	2
203 
204 /*----------------------------------------------
205 * console cursor bitmap (block cursor type)  */
206 
207 	short cons_cursor[32] = {      /* white block cursor */
208 
209  /* A */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
210 	 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
211  /* B */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
212 	 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF
213 
214 	};
215 
216 /*-------------------------------------
217 * constants used in font operations */
218 
219 #define CHARS		95			/* # of chars in the font */
220 #define CHAR_HEIGHT	15			/* char height in pixels */
221 #define CHAR_WIDTH	8			/* char width in pixels*/
222 #define FONT_WIDTH	(CHAR_WIDTH * CHARS)	/* font width in pixels */
223 #define ROWS		CHAR_HEIGHT
224 
225 
226 #define FONT_X		0			/* font's off screen adrs */
227 #define FONT_Y		(2048 - CHAR_HEIGHT)
228 /*
229 #define FONT_Y		200
230 */
231 
232 	extern char q_font[];		/* reference font object code */
233 
234 	extern	char q_key[];		/* reference key xlation tables */
235 	extern	char q_shift_key[];
236 	extern	char *q_special[];
237 
238 /*--------------------------------------------------
239 * definitions for cursor acceleration reporting  */
240 
241 #define ACC_OFF 	0x01		/* acceleration is inactive */
242 
243 /*--------------------------------------------------------------------------
244 * v_consputc is the switch that is used to redirect the console cnputc() to
245 * the virtual console qdputc().
246 * v_consgetc is the switch that is used to redirect the console getchar() to
247 * the virtual console qdgetc().
248 */
249 
250 	extern (*v_consputc)();
251 	int qdputc();		/* used to direct kernel console output */
252 	extern (*v_consgetc)();
253 	int qdgetc();		/* used to read kernel console input */
254 
255 	int qdstart();		/* used to direct /dev/console output */
256 
257 /*------------------------------------------------------------------------
258 * LK-201 state storage for input console keyboard conversion to ASCII */
259 
260 	struct q_keyboard {
261 
262 	    int shift;			/* state variables	*/
263 	    int cntrl;
264 	    int lock;
265 	    int lastcode;		/* last keycode typed	*/
266 	    unsigned kup[8];		/* bits for each keycode*/
267 	    unsigned dkeys[8];		/* down/up mode keys	*/
268 	    char last;			/* last character	*/
269 
270 	 } q_keyboard;
271 
272 
273 /*****************************************************************
274 ******************************************************************
275 ******************************************************************
276 *
277 *	DRIVER FUNCTIONS START HERE:
278 *
279 ******************************************************************
280 ******************************************************************
281 *****************************************************************/
282 
283 /*********************************************************************
284 *
285 *	qdcons_init()... init QDSS as console (before probe routine)
286 *
287 *********************************************************************/
288 
289 qdcons_init()
290 {
291 	register u_int unit;
292 
293 	int *ptep;			/* page table entry pointer */
294 	caddr_t phys_adr;		/* physical QDSS base adrs */
295 	u_int mapix;			/* index into QMEMmap[] array */
296 
297 	struct cpusw *cpup;		/* pointer to cpusw structure  */
298 	u_short *qdaddr;		/* address of QDSS IO page CSR */
299 	u_short *devptr;		/* vitual device space */
300 
301 #define QDSSCSR 0x1F00
302 
303 	unit = 0;
304 
305 /*----------------------------------------------------
306 * find the cpusw entry that matches this machine. */
307 
308 	cpup = &cpusw[cpu];
309 				;
310 	if( cpup == NULL ) {
311 		return(0);
312 	}
313 
314 /*------------------------------------------------------
315 * Map the Q-bus memory space into the system memory. */
316 
317 	ubaaccess(((*cpup->v_umaddr)(0)), QMEMmap[0],
318 			cpup->pc_umsize, PG_V | PG_KW);
319 
320 	ubaaccess(((*cpup->v_udevaddr)(0)), QMEMmap[0]+btop(cpup->pc_umsize),
321 			DEVSPACESIZE ,PG_V|PG_KW);
322 
323 /*---------------------------------------------------------------------
324 * map the QDSS into the Qbus memory (which is now in system space)  */
325 
326 	devptr = (u_short *)((char *)qmem[0]+cpup->pc_umsize);
327 	qdaddr = (u_short *)((u_int)devptr + ubdevreg(QDSSCSR));
328 
329 	if (BADADDR(qdaddr, sizeof(short)))
330 		return(0);
331 
332 	/*---------------------------------------------------
333 	* tell QDSS which Q memory address base to decode */
334 
335 	mapix = (int) VTOP(QMEMSIZE - CHUNK);
336 	ptep = (int *) QMEMmap[0] + mapix;
337 	phys_adr = (caddr_t) (((int)*ptep & 0x001FFFFF) << PGSHIFT);
338 	*qdaddr = (u_short) ((int)phys_adr >> 16);
339 
340 	qdflags[unit].config = *(u_short *)qdaddr;
341 
342 /*----------------------------------------------------------------------
343 * load qdmap struct with the virtual addresses of the QDSS elements */
344 
345 	qdbase[unit] = (caddr_t) (qmem[0] + QMEMSIZE - CHUNK);
346 
347 	qdmap[unit].template = qdbase[unit] + TMPSTART;
348 	qdmap[unit].adder = qdbase[unit] + ADDER;
349 	qdmap[unit].dga = qdbase[unit] + DGA;
350 	qdmap[unit].duart = qdbase[unit] + DUART;
351 	qdmap[unit].memcsr = qdbase[unit] + MEMCSR;
352 	qdmap[unit].red = qdbase[unit] + RED;
353 	qdmap[unit].blue = qdbase[unit] + BLUE;
354 	qdmap[unit].green = qdbase[unit] + GREEN;
355 
356 	qdflags[unit].duart_imask = 0;	/* init shadow variables */
357 
358 /*------------------
359 * init the QDSS  */
360 
361 	*(short *)qdmap[unit].memcsr |= SYNC_ON; /* once only: turn on sync */
362 
363 	cursor[unit].x = 0;
364 	cursor[unit].y = 0;
365 	init_shared(unit);		/* init shared memory */
366 	setup_dragon(unit);		/* init the ADDER/VIPER stuff */
367 	clear_qd_screen(unit);		/* clear the screen */
368 	ldfont(unit);			/* load the console font */
369 	ldcursor(unit, cons_cursor);	/* load default cursor map */
370 	setup_input(unit);		/* init the DUART */
371 
372 /*----------------------------------------------------
373 * smash the system's virtual console address table */
374 
375 	v_consputc = qdputc;
376 	v_consgetc = qdgetc;
377 	cdevsw[0] = cdevsw[QDSSMAJOR];
378 	return(1);
379 
380 } /* qdcons_init */
381 
382 /*********************************************************************
383 *
384 *	qdprobe()... configure QDSS into Q memory and make it intrpt
385 *
386 **********************************************************************
387 *
388 *  calling convention:
389 *			qdprobe(reg, ctlr);
390 *			caddr_t reg;
391 *			int ctlr;
392 *
393 *	where: reg - a character pointer to the QDSS I/O page register
394 *	       ctlr - controller number (?)
395 *
396 *  side effects: QDSS gets mapped into Qbus memory space at the first
397 *		 vacant 64kb boundary counting back from the top of
398 *		 Qbus memory space (qmem+4mb)
399 *
400 *  return: QDSS bus request level and vector address returned in
401 *	   registers by UNIX convention.
402 *
403 *****************/
404 
405 qdprobe(reg)
406 caddr_t reg;
407 {
408 	/* the variables MUST reside in the first two register declarations
409 	* by UNIX convention in order that they be loaded and returned
410 	* properly by the interrupt catching mechanism.  */
411 
412 	register int unit;
413 
414 	struct dga *dga;		/* pointer to gate array structure */
415 	struct cpusw *cpup;		/* pointer to the cpusw structure */
416 
417 	int *ptep;			/* page table entry pointer */
418 	int vector;
419 
420 	caddr_t phys_adr;		/* physical QDSS base adrs */
421 	u_int mapix;
422 
423 /*---------------------------------------------------------------
424 * calculate board unit number from I/O page register address  */
425 
426 	unit = (int) (((int)reg >> 1) & 0x0007);
427 
428 /*---------------------------------------------------------------------------
429 * QDSS regs must be mapped to Qbus memory space at a 64kb physical boundary.
430 * The Qbus memory space is mapped into the system memory space at config
431 * time.  After config runs, "qmem[0]" (ubavar.h) holds the system virtual adrs
432 * of the start of Qbus memory.	The Qbus memory page table is found via
433 * an array of pte ptrs called "QMEMmap[]" (ubavar.h) which is also loaded at
434 * config time.	These are the variables used below to find a vacant 64kb
435 * boundary in Qbus memory, and load it's corresponding physical adrs into
436 * the QDSS's I/O page CSR.  */
437 
438 	/* if this QDSS is NOT the console, then do init here.. */
439 
440 	if (v_consputc != qdputc  ||  unit != 0) {
441 
442 	    /*-------------------------
443 	    * read QDSS config info */
444 
445 	    qdflags[unit].config = *(u_short *)reg;
446 
447 	    /*------------------------------------
448 	    * find an empty 64kb adrs boundary */
449 
450 	    qdbase[unit] = (caddr_t) (qmem[0] + QMEMSIZE - CHUNK);
451 
452 	    /*----------------------------------------------------
453 	    * find the cpusw entry that matches this machine. */
454 
455 	    cpup = &cpusw[cpu];
456 	    while ( !(BADADDR(qdbase[unit], sizeof(short))) )
457 		qdbase[unit] -= CHUNK;
458 
459 	    /*---------------------------------------------------
460 	    * tell QDSS which Q memory address base to decode */
461 
462 	    mapix = (int) (VTOP(qdbase[unit]) - VTOP(qmem[0]));
463 	    ptep = (int *) QMEMmap[0] + mapix;
464 	    phys_adr = (caddr_t) (((int)*ptep & 0x001FFFFF) << PGSHIFT);
465 	    *(u_short *)reg = (u_short) ((int)phys_adr >> 16);
466 
467 	    /*-----------------------------------------------------------
468 	    * load QDSS adrs map with system addresses of device regs */
469 
470 	    qdmap[unit].template = qdbase[unit] + TMPSTART;
471 	    qdmap[unit].adder = qdbase[unit] + ADDER;
472 	    qdmap[unit].dga = qdbase[unit] + DGA;
473 	    qdmap[unit].duart = qdbase[unit] + DUART;
474 	    qdmap[unit].memcsr = qdbase[unit] + MEMCSR;
475 	    qdmap[unit].red = qdbase[unit] + RED;
476 	    qdmap[unit].blue = qdbase[unit] + BLUE;
477 	    qdmap[unit].green = qdbase[unit] + GREEN;
478 
479 	    /* device init */
480 
481 	    cursor[unit].x = 0;
482 	    cursor[unit].y = 0;
483 	    init_shared(unit);		/* init shared memory */
484 	    setup_dragon(unit); 	/* init the ADDER/VIPER stuff */
485 	    ldcursor(unit, cons_cursor);	/* load default cursor map */
486 	    setup_input(unit);		/* init the DUART */
487 	    clear_qd_screen(unit);
488 	    ldfont(unit);			/* load the console font */
489 
490 	    /* once only: turn on sync */
491 
492 	    *(short *)qdmap[unit].memcsr |= SYNC_ON;
493 	}
494 
495 /*--------------------------------------------------------------------------
496 * the QDSS interrupts at HEX vectors xx0 (DMA) xx4 (ADDER) and xx8 (DUART).
497 * Therefore, we take three vectors from the vector pool, and then continue
498 * to take them until we get a xx0 HEX vector.  The pool provides vectors
499 * in contiguous decending order.  */
500 
501 	vector = (uba_hd[0].uh_lastiv -= 4*3);	/* take three vectors */
502 
503 	while (vector & 0x0F) { 		   /* if lo nibble != 0.. */
504 	    vector = (uba_hd[0].uh_lastiv -= 4);  /* ..take another vector */
505 	}
506 
507 	/*---------------------------------------------------------
508 	* setup DGA to do a DMA interrupt (transfer count = 0)	*/
509 
510 	dga = (struct dga *) qdmap[unit].dga;
511 
512 	dga->csr = (short) HALT;	      /* disable everything */
513 	dga->ivr = (short) vector;	      /* load intrpt base vector */
514 	dga->bytcnt_lo = (short) 0;	      /* DMA xfer count = 0 */
515 	dga->bytcnt_hi = (short) 0;
516 
517 	/* turn on DMA interrupts */
518 
519 	dga->csr &= ~SET_DONE_FIFO;
520 	dga->csr |= DMA_IE | DL_ENB;
521 
522 	DELAY(20000);			/* wait for the intrpt */
523 
524 	dga->csr = HALT;		/* stop the wheels */
525 
526 /*----------
527 * exits  */
528 
529 	if (cvec != vector)		/* if vector != base vector.. */
530 	    return(0);			/* ..return = 'no device' */
531 
532 	return(sizeof(short));	    /* return size of QDSS I/O page reg */
533 
534 } /* qdprobe */
535 
536 /*****************************************************************
537 *
538 *	qdattach()... do the one-time initialization
539 *
540 ******************************************************************
541 *
542 *  calling convention:
543 *			qdattach(ui);
544 *			struct uba_device *ui;
545 *
546 *		where: ui - pointer to the QDSS's uba_device structure
547 *
548 *  side effects: none
549 *	 return: none
550 *
551 *************************/
552 
553 qdattach(ui)
554 struct uba_device *ui;
555 {
556 	register u_int unit;		/* QDSS module # for this call */
557 
558 	unit = ui->ui_unit;		/* get QDSS number */
559 
560 /*----------------------------------
561 * init "qdflags[]" for this QDSS */
562 
563 	qdflags[unit].inuse = 0;	/* init inuse variable EARLY! */
564 	qdflags[unit].mapped = 0;
565 	qdflags[unit].kernel_loop = 0;
566 	qdflags[unit].user_dma = 0;
567 	qdflags[unit].curs_acc = ACC_OFF;
568 	qdflags[unit].curs_thr = 128;
569 	qdflags[unit].tab_res = 2;	/* default tablet resolution factor */
570 	qdflags[unit].duart_imask = 0;	/* init shadow variables */
571 	qdflags[unit].adder_ie = 0;
572 
573 /*----------------------------------------------------------------------
574 * init structures used in kbd/mouse interrupt service.	This code must
575 * come after the "init_shared()" routine has run since that routine inits
576 * the eq_header[unit] structure used here.   */
577 
578 	/*--------------------------------------------
579 	* init the "latest mouse report" structure */
580 
581 	last_rep[unit].state = 0;
582 	last_rep[unit].dx = 0;
583 	last_rep[unit].dy = 0;
584 	last_rep[unit].bytcnt = 0;
585 
586 	/*------------------------------------------------
587 	* init the event queue (except mouse position) */
588 
589 	eq_header[unit]->header.events = (struct _vs_event *)
590 					  ((int)eq_header[unit]
591 					   + sizeof(struct qdinput));
592 
593 	eq_header[unit]->header.size = MAXEVENTS;
594 	eq_header[unit]->header.head = 0;
595 	eq_header[unit]->header.tail = 0;
596 
597 /*------------------------------------------
598 * init single process access lock switch */
599 
600 	one_only[unit] = 0;
601 
602 } /* qdattach */
603 
604 /***************************************************************
605 *
606 *	qdopen()... open a minor device
607 *
608 ****************************************************************
609 *
610 *  calling convention: qdopen(dev, flag);
611 *		       dev_t dev;
612 *		       int flag;
613 *
614 *  side effects: none
615 *
616 *********************/
617 
618 qdopen(dev, flag)
619 dev_t dev;
620 int flag;
621 {
622 	register struct uba_device *ui; /* ptr to uba structures */
623 	register struct dga *dga;	/* ptr to gate array struct */
624 	register struct tty *tp;
625 
626 	struct adder *adder;
627 	struct duart *duart;
628 
629 	u_int unit;
630 	u_int minor_dev;
631 	int s;
632 
633 	minor_dev = minor(dev); /* get QDSS minor device number */
634 	unit = minor_dev >> 2;
635 
636 /*---------------------------------
637 * check for illegal conditions	*/
638 
639 	ui = qdinfo[unit];		/* get ptr to QDSS device struct */
640 
641 	if (ui == 0  || ui->ui_alive == 0)
642 	    return(ENXIO);		/* no such device or address */
643 
644 /*--------------
645 * init stuff */
646 
647 	adder = (struct adder *) qdmap[unit].adder;
648 	duart = (struct duart *) qdmap[unit].duart;
649 	dga = (struct dga *) qdmap[unit].dga;
650 
651 /*------------------------------------
652 * if this is the graphic device... */
653 
654 	if ((minor_dev & 0x03) == 2) {
655 
656 	    if (one_only[unit] != 0)
657 		return(EBUSY);
658 	    else
659 		one_only[unit] = 1;
660 
661 	    qdflags[unit].inuse |= GRAPHIC_DEV;  /* graphics dev is open */
662 
663 	    /* enble kbd & mouse intrpts in DUART mask reg */
664 
665 	    qdflags[unit].duart_imask |= 0x22;
666 	    duart->imask = qdflags[unit].duart_imask;
667 
668 /*------------------------------------------------------------------
669 * if the open call is to the console or the alternate console... */
670 
671 	} else if ((minor_dev & 0x03) != 2) {
672 
673 	    qdflags[unit].inuse |= CONS_DEV;  /* mark console as open */
674 	    dga->csr |= CURS_ENB;
675 
676 	    qdflags[unit].duart_imask |= 0x02;
677 	    duart->imask = qdflags[unit].duart_imask;
678 
679 	    /*-------------------------------
680 	    * some setup for tty handling */
681 
682 	    tp = &qd_tty[minor_dev];
683 
684 	    tp->t_addr = ui->ui_addr;
685 	    tp->t_oproc = qdstart;
686 
687 	    if ((tp->t_state & TS_ISOPEN) == 0) {
688 
689 		ttychars(tp);
690 		tp->t_state = TS_ISOPEN | TS_CARR_ON;
691 		tp->t_ispeed = B9600;
692 		tp->t_ospeed = B9600;
693 
694 		if( (minor_dev & 0x03) == 0 )
695 		    tp->t_flags = XTABS|EVENP|ECHO|CRMOD;
696 		else
697 		    tp->t_flags = RAW;
698 	    }
699 
700 	    /*----------------------------------------
701 	    * enable intrpts, open line discipline */
702 
703 	    dga->csr |= GLOBAL_IE;	/* turn on the interrupts */
704 	    return ((*linesw[tp->t_line].l_open)(dev, tp));
705 	}
706 
707 	dga->csr |= GLOBAL_IE;	/* turn on the interrupts */
708 	return(0);
709 
710 } /* qdopen */
711 
712 /***************************************************************
713 *
714 *	qdclose()... clean up on the way out
715 *
716 ****************************************************************
717 *
718 *  calling convention: qdclose();
719 *
720 *  side effects: none
721 *
722 *  return: none
723 *
724 *********************/
725 
726 qdclose(dev, flag)
727 dev_t dev;
728 int flag;
729 {
730 	register struct tty *tp;
731 	register struct qdmap *qd;
732 	register int *ptep;
733 	int i;				/* SIGNED index */
734 
735 	struct dga *dga;		/* gate array register map pointer */
736 	struct duart *duart;
737 	struct adder *adder;
738 
739 	u_int unit;
740 	u_int minor_dev;
741 	u_int mapix;
742 
743 	minor_dev = minor(dev); 	/* get minor device number */
744 	unit = minor_dev >> 2;		/* get QDSS number */
745 	qd = &qdmap[unit];
746 
747 /*------------------------------------
748 * if this is the graphic device... */
749 
750 	if ((minor_dev & 0x03) == 2) {
751 
752 	    /*-----------------
753 	    * unlock driver */
754 
755 	    if (one_only[unit] != 1)
756 		return(EBUSY);
757 	    else
758 		one_only[unit] = 0;
759 
760 	    /*----------------------------
761 	    * re-protect device memory */
762 
763 	    if (qdflags[unit].mapped & MAPDEV) {
764 
765 		/*----------------
766 		* TEMPLATE RAM */
767 
768 		mapix = VTOP((int)qd->template) - VTOP(qmem[0]);
769 		ptep = (int *)(QMEMmap[0] + mapix);
770 
771 		for (i = VTOP(TMPSIZE); i > 0; --i)
772 		    *ptep++ = (*ptep & ~PG_PROT) | PG_V | PG_KW;
773 
774 		/*---------
775 		* ADDER */
776 
777 		mapix = VTOP((int)qd->adder) - VTOP(qmem[0]);
778 		ptep = (int *)(QMEMmap[0] + mapix);
779 
780 		for (i = VTOP(REGSIZE); i > 0; --i)
781 		    *ptep++ = (*ptep & ~PG_PROT) | PG_V | PG_KW;
782 
783 		/*--------------
784 		* COLOR MAPS */
785 
786 		mapix = VTOP((int)qd->red) - VTOP(qmem[0]);
787 		ptep = (int *)(QMEMmap[0] + mapix);
788 
789 		for (i = VTOP(CLRSIZE); i > 0; --i)
790 		    *ptep++ = (*ptep & ~PG_PROT) | PG_V | PG_KW;
791 	    }
792 
793 	    /*----------------------------------------------------
794 	    * re-protect DMA buffer and free the map registers */
795 
796 	    if (qdflags[unit].mapped & MAPDMA) {
797 
798 		dga = (struct dga *) qdmap[unit].dga;
799 		adder = (struct adder *) qdmap[unit].adder;
800 
801 		dga->csr &= ~DMA_IE;
802 		dga->csr &= ~0x0600;	     /* kill DMA */
803 		adder->command = CANCEL;
804 
805 		/* if DMA was running, flush spurious intrpt */
806 
807 		if (dga->bytcnt_lo != 0) {
808 		    dga->bytcnt_lo = 0;
809 		    dga->bytcnt_hi = 0;
810 		    DMA_SETIGNORE(DMAheader[unit]);
811 		    dga->csr |= DMA_IE;
812 		    dga->csr &= ~DMA_IE;
813 		}
814 
815 		ptep = (int *)
816 			((VTOP(DMAheader[unit]*4)) + (mfpr(SBR)|0x80000000));
817 
818 		for (i = (DMAbuf_size >> PGSHIFT); i > 0; --i)
819 		    *ptep++ = (*ptep & ~PG_PROT) | PG_V | PG_KW;
820 
821 		ubarelse(0, &Qbus_unmap[unit]);
822 	    }
823 
824 	    /*---------------------------------------
825 	    * re-protect 1K (2 pages) event queue */
826 
827 	    if (qdflags[unit].mapped & MAPEQ) {
828 
829 		ptep = (int *)
830 			((VTOP(eq_header[unit])*4) + (mfpr(SBR)|0x80000000));
831 
832 		*ptep++ = (*ptep & ~PG_PROT) | PG_KW | PG_V;
833 		*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
834 	    }
835 
836 	    /*------------------------------------------------------------
837 	    * re-protect scroll param area and disable scroll intrpts  */
838 
839 	    if (qdflags[unit].mapped & MAPSCR) {
840 
841 		ptep = (int *) ((VTOP(scroll[unit]) * 4)
842 				    + (mfpr(SBR) | 0x80000000));
843 
844 		/* re-protect 512 scroll param area */
845 
846 		*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
847 
848 		adder = (struct adder *) qdmap[unit].adder;
849 		qdflags[unit].adder_ie &= ~FRAME_SYNC;
850 		adder->interrupt_enable = qdflags[unit].adder_ie;
851 	    }
852 
853 	    /*-----------------------------------------------------------
854 	    * re-protect color map write buffer area and kill intrpts */
855 
856 	    if (qdflags[unit].mapped & MAPCOLOR) {
857 
858 		ptep = (int *) ((VTOP(color_buf[unit]) * 4)
859 				    + (mfpr(SBR) | 0x80000000));
860 
861 		*ptep++ = (*ptep & ~PG_PROT) | PG_KW | PG_V;
862 		*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
863 
864 		color_buf[unit]->status = 0;
865 
866 		adder = (struct adder *) qdmap[unit].adder;
867 		qdflags[unit].adder_ie &= ~VSYNC;
868 		adder->interrupt_enable = qdflags[unit].adder_ie;
869 	    }
870 
871 	    /*-----------------------------------
872 	    * flag that everthing is unmapped */
873 
874 	    mtpr(TBIA, 0);		/* smash CPU's translation buf */
875 	    qdflags[unit].mapped = 0;	/* flag everything now unmapped */
876 	    qdflags[unit].inuse &= ~GRAPHIC_DEV;
877 	    qdflags[unit].curs_acc = ACC_OFF;
878 	    qdflags[unit].curs_thr = 128;
879 
880 	    /*---------------------
881 	    * restore the console */
882 
883 		dga = (struct dga *) qdmap[unit].dga;
884 		adder = (struct adder *) qdmap[unit].adder;
885 
886 		dga->csr &= ~DMA_IE;
887 		dga->csr &= ~0x0600;	/* halt the DMA! (just in case...) */
888 		dga->csr |= DMA_ERR;	/* clear error condition */
889 		adder->command = CANCEL;
890 
891 		/* if DMA was running, flush spurious intrpt */
892 
893 		if (dga->bytcnt_lo != 0) {
894 		    dga->bytcnt_lo = 0;
895 		    dga->bytcnt_hi = 0;
896 		    DMA_SETIGNORE(DMAheader[unit]);
897 		    dga->csr |= DMA_IE;
898 		    dga->csr &= ~DMA_IE;
899 		}
900 
901 		init_shared(unit);		/* init shared memory */
902 		setup_dragon(unit);		/* init ADDER/VIPER */
903 		ldcursor(unit, cons_cursor);	/* load default cursor map */
904 		setup_input(unit);		/* init the DUART */
905 		ldfont(unit);
906 		cursor[unit].x = 0;
907 		cursor[unit].y = 0;
908 
909 	    /* shut off the mouse rcv intrpt and turn on kbd intrpts */
910 
911 	    duart = (struct duart *) qdmap[unit].duart;
912 	    qdflags[unit].duart_imask &= ~(0x20);
913 	    qdflags[unit].duart_imask |= 0x02;
914 	    duart->imask = qdflags[unit].duart_imask;
915 
916 	    /*-----------------------------------------
917 	    * shut off interrupts if all is closed  */
918 
919 	    if (!(qdflags[unit].inuse & (CONS_DEV | ALTCONS_DEV))) {
920 
921 		dga = (struct dga *) qdmap[unit].dga;
922 		dga->csr &= ~(GLOBAL_IE | DMA_IE);
923 	    }
924 	}
925 
926 /*----------------------------------------------------
927 * if this is the console or the alternate console  */
928 
929 	else {
930 
931 	    tp = &qd_tty[minor_dev];
932 
933 	    (*linesw[tp->t_line].l_close)(tp);
934 	    ttyclose(tp);
935 
936 	    tp->t_state = 0;
937 
938 	    qdflags[unit].inuse &= ~CONS_DEV;
939 
940 	    /*-------------------------------------------------
941 	    * if graphics device is closed, kill interrupts */
942 
943 	    if (!(qdflags[unit].inuse & GRAPHIC_DEV)) {
944 		dga = (struct dga *) qdmap[unit].dga;
945 		dga->csr &= ~(GLOBAL_IE | DMA_IE);
946 	    }
947 	}
948 
949 /*--------
950 * exit */
951 
952 	return(0);
953 
954 } /* qdclose */
955 
956 /***************************************************************
957 *
958 *	qdioctl()... provide QDSS control services
959 *
960 ****************************************************************
961 *
962 *  calling convention:	qdioctl(dev, cmd, datap, flags);
963 *
964 *		where:	dev - the major/minor device number
965 *			cmd - the user-passed command argument
966 *			datap - ptr to user input buff (128 bytes max)
967 *			flags - "f_flags" from "struct file" in file.h
968 *
969 *
970 *	- here is the format for the input "cmd" argument
971 *
972 *	31     29 28	23 22	      16 15		8 7		 0
973 *	+----------------------------------------------------------------+
974 *	|I/O type|	  | buff length | device ID char |  user command |
975 *	+----------------------------------------------------------------+
976 *
977 *  Return data is in the data buffer pointed to by "datap" input spec
978 *
979 *********************/
980 
981 qdioctl(dev, cmd, datap, flags)
982 dev_t dev;
983 int cmd;
984 caddr_t datap;
985 int flags;
986 {
987 	register int *ptep;		/* page table entry pointer */
988 	register int mapix;		/* QMEMmap[] page table index */
989 	register struct _vs_event *event;
990 	register struct tty *tp;
991 
992 	struct qdmap *qd;		/* pointer to device map struct */
993 	struct dga *dga;		/* Gate Array reg structure pntr */
994 	struct duart *duart;		/* DUART reg structure pointer */
995 	struct adder *adder;		/* ADDER reg structure pointer */
996 
997 	struct prgkbd *cmdbuf;
998 	struct prg_cursor *curs;
999 	struct _vs_cursor *pos;
1000 
1001 	u_int unit = minor(dev) >> 2;	/* number of caller's QDSS */
1002 	u_int minor_dev = minor(dev);
1003 	struct uba_device *ui = qdinfo[unit];
1004 	struct qd_softc *sc = &qd_softc[ui->ui_unit];
1005 	struct devget *devget;
1006 
1007 	int error;
1008 	int s;
1009 
1010 	int i;				/* SIGNED index */
1011 	int sbr;			/* SBR variable (you silly boy) */
1012 	u_int ix;
1013 
1014 	short status;
1015 	short *shortp;			/* generic pointer to a short */
1016 	char *chrp;			/* generic character pointer */
1017 
1018 	short *temp;			/* a pointer to template RAM */
1019 
1020 /*-----------------------------------------
1021 * service graphic device ioctl commands */
1022 
1023 	switch (cmd) {
1024 
1025 	    /*-------------------------------------------------
1026 	    * extract the oldest event from the event queue */
1027 
1028 	    case QD_GETEVENT:
1029 
1030 		if (ISEMPTY(eq_header[unit])) {
1031 		    event = (struct _vs_event *) datap;
1032 		    event->vse_device = VSE_NULL;
1033 		    break;
1034 		}
1035 
1036 		event = (struct _vs_event *) GETBEGIN(eq_header[unit]);
1037 		s = spl5();
1038 		GETEND(eq_header[unit]);
1039 		splx(s);
1040 		bcopy(event, datap, sizeof(struct _vs_event));
1041 		break;
1042 
1043 	    /*-------------------------------------------------------
1044 	    * init the dragon stuff, DUART, and driver variables  */
1045 
1046 	    case QD_RESET:
1047 
1048 		init_shared(unit);		/* init shared memory */
1049 		setup_dragon(unit);	      /* init the ADDER/VIPER stuff */
1050 		clear_qd_screen(unit);
1051 		ldcursor(unit, cons_cursor);	/* load default cursor map */
1052 		ldfont(unit);			/* load the console font */
1053 		setup_input(unit);		/* init the DUART */
1054 		break;
1055 
1056 	    /*----------------------------------------
1057 	    * init the DUART and driver variables  */
1058 
1059 	    case QD_SET:
1060 
1061 		init_shared(unit);
1062 		setup_input(unit);
1063 		break;
1064 
1065 	    /*---------------------------------------------------------------
1066 	    * clear the QDSS screen.  (NOTE that this reinits the dragon) */
1067 
1068 	    case QD_CLRSCRN:
1069 
1070 		setup_dragon(unit);
1071 		clear_qd_screen(unit);
1072 		break;
1073 
1074 	    /*------------------------------------
1075 	    * load a cursor into template RAM  */
1076 
1077 	    case QD_WTCURSOR:
1078 
1079 		ldcursor(unit, datap);
1080 		break;
1081 
1082 	    case QD_RDCURSOR:
1083 
1084 		temp = (short *) qdmap[unit].template;
1085 
1086 		/* cursor is 32 WORDS from the end of the 8k WORD...
1087 		*  ...template space */
1088 
1089 		temp += (8 * 1024) - 32;
1090 
1091 		for (i = 0; i < 32; ++i, datap += sizeof(short))
1092 		    *(short *)datap = *temp++;
1093 		break;
1094 
1095 	    /*------------------------------
1096 	    * position the mouse cursor  */
1097 
1098 	    case QD_POSCURSOR:
1099 
1100 		dga = (struct dga *) qdmap[unit].dga;
1101 		pos = (struct _vs_cursor *) datap;
1102 		s = spl5();
1103 		dga->x_cursor = TRANX(pos->x);
1104 		dga->y_cursor = TRANY(pos->y);
1105 		eq_header[unit]->curs_pos.x = pos->x;
1106 		eq_header[unit]->curs_pos.y = pos->y;
1107 		splx(s);
1108 		break;
1109 
1110 	    /*--------------------------------------
1111 	    * set the cursor acceleration factor */
1112 
1113 	    case QD_PRGCURSOR:
1114 
1115 		curs = (struct prg_cursor *) datap;
1116 		s = spl5();
1117 		qdflags[unit].curs_acc = curs->acc_factor;
1118 		qdflags[unit].curs_thr = curs->threshold;
1119 		splx(s);
1120 		break;
1121 
1122 	    /*---------------------------------------
1123 	    * enable 'user write' to device pages */
1124 
1125 	    case QD_MAPDEVICE:
1126 
1127 		/*--------------
1128 		* init stuff */
1129 
1130 		qdflags[unit].mapped |= MAPDEV;
1131 		qd = (struct qdmap *) &qdmap[unit];
1132 
1133 		/*-------------------------------------
1134 		* enable user write to template RAM */
1135 
1136 		mapix = VTOP((int)qd->template) - VTOP(qmem[0]);
1137 		ptep = (int *)(QMEMmap[0] + mapix);
1138 
1139 		for (i = VTOP(TMPSIZE); i > 0; --i)
1140 		    *ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V;
1141 
1142 		/*----------------------------------
1143 		* enable user write to registers */
1144 
1145 		mapix = VTOP((int)qd->adder) - VTOP(qmem[0]);
1146 		ptep = (int *)(QMEMmap[0] + mapix);
1147 
1148 		for (i = VTOP(REGSIZE); i > 0; --i)
1149 		    *ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V;
1150 
1151 		/*-----------------------------------
1152 		* enable user write to color maps */
1153 
1154 		mapix = VTOP((int)qd->red) - VTOP(qmem[0]);
1155 		ptep = (int *)(QMEMmap[0] + mapix);
1156 
1157 		for (i = VTOP(CLRSIZE); i > 0; --i)
1158 		    *ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V;
1159 
1160 		/*------------------------------
1161 		* enable user write to DUART */
1162 
1163 		mapix = VTOP((int)qd->duart) - VTOP(qmem[0]);
1164 		ptep = (int *)(QMEMmap[0] + mapix);
1165 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; /* duart page */
1166 
1167 		mtpr(TBIA, 0);		/* smash CPU's translation buffer */
1168 
1169 		/*------------------------------------------
1170 		* stuff qdmap structure in return buffer */
1171 
1172 		bcopy(qd, datap, sizeof(struct qdmap));
1173 		break;
1174 
1175 	    /*-------------------------------------
1176 	    * do setup for DMA by user process	*/
1177 
1178 	    case QD_MAPIOBUF:
1179 
1180 		/*------------------------------------------------
1181 		* set 'user write enable' bits for DMA buffer  */
1182 
1183 		qdflags[unit].mapped |= MAPDMA;
1184 
1185 		ptep = (int *) ((VTOP(DMAheader[unit]) * 4)
1186 				+ (mfpr(SBR) | 0x80000000));
1187 
1188 		for (i = (DMAbuf_size >> PGSHIFT); i > 0; --i)
1189 		    *ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V;
1190 
1191 		mtpr(TBIA, 0);			/* clr CPU translation buf */
1192 
1193 		/*-------------------------------------
1194 		* set up QBUS map registers for DMA */
1195 
1196 		DMAheader[unit]->QBAreg =
1197 				uballoc(0, DMAheader[unit], DMAbuf_size, 0);
1198 
1199 		if (DMAheader[unit]->QBAreg == 0)
1200 		    mprintf("\nqd%d: qdioctl: QBA setup error", unit);
1201 
1202 		Qbus_unmap[unit] = DMAheader[unit]->QBAreg;
1203 		DMAheader[unit]->QBAreg &= 0x3FFFF;
1204 
1205 		/*----------------------
1206 		* return I/O buf adr */
1207 
1208 		*(int *)datap = (int) DMAheader[unit];
1209 		break;
1210 
1211 	    /*----------------------------------------------------------------
1212 	    * map the shared scroll param area and enable scroll interpts  */
1213 
1214 	    case QD_MAPSCROLL:
1215 
1216 		qdflags[unit].mapped |= MAPSCR;
1217 
1218 		ptep = (int *) ((VTOP(scroll[unit]) * 4)
1219 				+ (mfpr(SBR) | 0x80000000));
1220 
1221 		/* allow user write to scroll area */
1222 
1223 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
1224 
1225 		mtpr(TBIA, 0);			/* clr CPU translation buf */
1226 
1227 		scroll[unit]->status = 0;
1228 
1229 		adder = (struct adder *) qdmap[unit].adder;
1230 
1231 		qdflags[unit].adder_ie |= FRAME_SYNC;
1232 		adder->interrupt_enable = qdflags[unit].adder_ie;
1233 
1234 		/* return scroll area address */
1235 
1236 		*(int *)datap = (int) scroll[unit];
1237 		break;
1238 
1239 	    /*-------------------------------------------------------------
1240 	    * unmap shared scroll param area and disable scroll intrpts */
1241 
1242 	    case QD_UNMAPSCROLL:
1243 
1244 		if (qdflags[unit].mapped & MAPSCR) {
1245 
1246 		    qdflags[unit].mapped &= ~MAPSCR;
1247 
1248 		    ptep = (int *) ((VTOP(scroll[unit]) * 4)
1249 				    + (mfpr(SBR) | 0x80000000));
1250 
1251 		    /* re-protect 512 scroll param area */
1252 
1253 		    *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
1254 
1255 		    mtpr(TBIA, 0);	/* smash CPU's translation buf */
1256 
1257 		    adder = (struct adder *) qdmap[unit].adder;
1258 		    qdflags[unit].adder_ie &= ~FRAME_SYNC;
1259 		    adder->interrupt_enable = qdflags[unit].adder_ie;
1260 		}
1261 		break;
1262 
1263 	    /*-----------------------------------------------------------
1264 	    * map shared color map write buf and turn on vsync intrpt */
1265 
1266 	    case QD_MAPCOLOR:
1267 
1268 		qdflags[unit].mapped |= MAPCOLOR;
1269 
1270 		ptep = (int *) ((VTOP(color_buf[unit]) * 4)
1271 				+ (mfpr(SBR) | 0x80000000));
1272 
1273 		/* allow user write to color map write buffer */
1274 
1275 		*ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V;
1276 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
1277 
1278 		mtpr(TBIA, 0);			/* clr CPU translation buf */
1279 
1280 		adder = (struct adder *) qdmap[unit].adder;
1281 
1282 		qdflags[unit].adder_ie |= VSYNC;
1283 		adder->interrupt_enable = qdflags[unit].adder_ie;
1284 
1285 		/* return scroll area address */
1286 
1287 		*(int *)datap = (int) color_buf[unit];
1288 		break;
1289 
1290 	    /*--------------------------------------------------------------
1291 	    * unmap shared color map write buffer and kill VSYNC intrpts */
1292 
1293 	    case QD_UNMAPCOLOR:
1294 
1295 		if (qdflags[unit].mapped & MAPCOLOR) {
1296 
1297 		    qdflags[unit].mapped &= ~MAPCOLOR;
1298 
1299 		    ptep = (int *) ((VTOP(color_buf[unit]) * 4)
1300 				    + (mfpr(SBR) | 0x80000000));
1301 
1302 		    /* re-protect color map write buffer */
1303 
1304 		    *ptep++ = (*ptep & ~PG_PROT) | PG_KW | PG_V;
1305 		    *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
1306 
1307 		    mtpr(TBIA, 0);	/* smash CPU's translation buf */
1308 
1309 		    adder = (struct adder *) qdmap[unit].adder;
1310 
1311 		    qdflags[unit].adder_ie &= ~VSYNC;
1312 		    adder->interrupt_enable = qdflags[unit].adder_ie;
1313 		}
1314 		break;
1315 
1316 	    /*---------------------------------------------
1317 	    * give user write access to the event queue */
1318 
1319 	    case QD_MAPEVENT:
1320 
1321 		qdflags[unit].mapped |= MAPEQ;
1322 
1323 		ptep = (int *) ((VTOP(eq_header[unit]) * 4)
1324 				+ (mfpr(SBR) | 0x80000000));
1325 
1326 		/* allow user write to 1K event queue */
1327 
1328 		*ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V;
1329 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
1330 
1331 		mtpr(TBIA, 0);			/* clr CPU translation buf */
1332 
1333 		/* return event queue address */
1334 
1335 		*(int *)datap = (int) eq_header[unit];
1336 		break;
1337 
1338 	    /*-----------------------------------------------
1339 	    * pass caller's programming commands to LK201 */
1340 
1341 	    case QD_PRGKBD:
1342 
1343 		duart = (struct duart *) qdmap[unit].duart;
1344 		cmdbuf = (struct prgkbd *) datap;    /* pnt to kbd cmd buf */
1345 
1346 		/*----------------
1347 		* send command */
1348 
1349 		for (i = 1000; i > 0; --i) {
1350 		    if ((status = duart->statusA) & XMT_RDY) {
1351 			duart->dataA = cmdbuf->cmd;
1352 			break;
1353 		    }
1354 		}
1355 
1356 		if (i == 0) {
1357 		    mprintf("\nqd%d: qdioctl: timeout on XMT_RDY [1]", unit);
1358 		    break;
1359 		}
1360 
1361 		/*----------------
1362 		* send param1? */
1363 
1364 		if (cmdbuf->cmd & LAST_PARAM)
1365 		    break;
1366 
1367 		for (i = 1000; i > 0; --i) {
1368 		    if ((status = duart->statusA) & XMT_RDY) {
1369 			duart->dataA = cmdbuf->param1;
1370 			break;
1371 		    }
1372 		}
1373 
1374 		if (i == 0) {
1375 		    mprintf("\nqd%d: qdioctl: timeout on XMT_RDY [2]", unit);
1376 		    break;
1377 		}
1378 
1379 		/*----------------
1380 		* send param2? */
1381 
1382 		if (cmdbuf->param1 & LAST_PARAM)
1383 		    break;
1384 
1385 		for (i = 1000; i > 0; --i) {
1386 		    if ((status = duart->statusA) & XMT_RDY) {
1387 			duart->dataA = cmdbuf->param2;
1388 			break;
1389 		    }
1390 		}
1391 
1392 		if (i == 0) {
1393 		    mprintf("\nqd%d: qdioctl: timeout on XMT_RDY [3]", unit);
1394 		    break;
1395 		}
1396 
1397 		break;
1398 
1399 	    /*----------------------------------------------------
1400 	    * pass caller's programming commands to the mouse  */
1401 
1402 	    case QD_PRGMOUSE:
1403 
1404 		duart = (struct duart *) qdmap[unit].duart;
1405 
1406 		for (i = 1000; i > 0; --i) {
1407 		    if ((status = duart->statusB) & XMT_RDY) {
1408 			duart->dataB = *datap;
1409 			break;
1410 		    }
1411 		}
1412 
1413 		if (i == 0) {
1414 		    mprintf("\nqd%d: qdioctl: timeout on XMT_RDY [4]", unit);
1415 		}
1416 
1417 		break;
1418 
1419 	    /*----------------------------------------------
1420 	    * get QDSS configuration word and return it  */
1421 
1422 	    case QD_RDCONFIG:
1423 
1424 		*(short *)datap = qdflags[unit].config;
1425 		break;
1426 
1427 	    /*--------------------------------------------------------------
1428 	    * re-route kernel console messages to the alternate console  */
1429 
1430 	    case QD_KERN_LOOP:
1431 
1432 		qdflags[unit].kernel_loop = -1;
1433 		break;
1434 
1435 	    case QD_KERN_UNLOOP:
1436 
1437 		qdflags[unit].kernel_loop = 0;
1438 		break;
1439 
1440 	    /*----------------------
1441 	    * program the tablet */
1442 
1443 	    case QD_PRGTABLET:
1444 
1445 		duart = (struct duart *) qdmap[unit].duart;
1446 
1447 		for (i = 1000; i > 0; --i) {
1448 		    if ((status = duart->statusB) & XMT_RDY) {
1449 			duart->dataB = *datap;
1450 			break;
1451 		    }
1452 		}
1453 
1454 		if (i == 0) {
1455 		    mprintf("\nqd%d: qdioctl: timeout on XMT_RDY [5]", unit);
1456 		}
1457 
1458 		break;
1459 
1460 	    /*-----------------------------------------------
1461 	    * program the tablet report resolution factor */
1462 
1463 	    case QD_PRGTABRES:
1464 
1465 		qdflags[unit].tab_res = *(short *)datap;
1466 		break;
1467 
1468 	    case DEVIOCGET:			    /* device status */
1469 		    devget = (struct devget *)datap;
1470 		    bzero(devget,sizeof(struct devget));
1471 		    devget->category = DEV_TERMINAL;
1472 		    devget->bus = DEV_QB;
1473 		    bcopy(DEV_VCB02,devget->interface,
1474 			  strlen(DEV_VCB02));
1475 		    bcopy(DEV_VR290,devget->device,
1476 			  strlen(DEV_VR290));		    /* terminal */
1477 		    devget->adpt_num = ui->ui_adpt;	    /* which adapter*/
1478 		    devget->nexus_num = ui->ui_nexus;	    /* which nexus  */
1479 		    devget->bus_num = ui->ui_ubanum;	    /* which QB     */
1480 		    devget->ctlr_num = unit;		    /* which interf.*/
1481 		    devget->slave_num = unit;		    /* which line   */
1482 		    bcopy(ui->ui_driver->ud_dname,
1483 			  devget->dev_name,
1484 			  strlen(ui->ui_driver->ud_dname)); /* Ultrix "qd"  */
1485 		    devget->unit_num = unit;		    /* qd line?     */
1486 		    devget->soft_count =
1487 			  sc->sc_softcnt;		    /* soft er. cnt.*/
1488 		    devget->hard_count =
1489 			  sc->sc_hardcnt;		    /* hard er cnt. */
1490 		    devget->stat = sc->sc_flags;	    /* status	    */
1491 		    devget->category_stat =
1492 			  sc->sc_category_flags;	    /* cat. stat.   */
1493 		    break;
1494 
1495 	    default:
1496 		/*-----------------------------
1497 		* service tty type ioctl's  */
1498 
1499 		    if (!(minor_dev & 0x02)) {
1500 
1501 			tp = &qd_tty[minor_dev];
1502 
1503 			error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, datap, flags);
1504 			if (error >= 0) {
1505 			    return(error);
1506 			}
1507 
1508 			error = ttioctl(tp, cmd, datap, flags);
1509 			if (error >= 0) {
1510 			    return(error);
1511 			}
1512 		    }
1513 		    break;
1514 	}
1515 
1516 /*--------------------------------
1517 * clean up and get outta here  */
1518 
1519 	return(0);
1520 
1521 } /* qdioctl */
1522 
1523 /**********************************************************************
1524 *
1525 *	qdselect()... service select call for event queue input
1526 *
1527 **********************************************************************/
1528 
1529 qdselect(dev, rw)
1530 dev_t dev;
1531 int rw;
1532 {
1533 	register int s;
1534 	register int unit;
1535 
1536 	s = spl5();
1537 	unit = minor(dev) >> 2;
1538 
1539 	switch (rw) {
1540 
1541 	    case FREAD: 		/* event available? */
1542 
1543 		if(!(ISEMPTY(eq_header[unit]))) {
1544 		    splx(s);
1545 		    return(1);		/* return "1" if event exists */
1546 		}
1547 		rsel[unit] = u.u_procp;
1548 		qdflags[unit].selmask |= SEL_READ;
1549 		splx(s);
1550 		return(0);
1551 
1552 	    case FWRITE:		/* DMA done? */
1553 
1554 		if (DMA_ISEMPTY(DMAheader[unit])) {
1555 		    splx(s);
1556 		    return(1);		/* return "1" if DMA is done */
1557 		}
1558 		rsel[unit] = u.u_procp;
1559 		qdflags[unit].selmask |= SEL_WRITE;
1560 		splx(s);
1561 		return(0);
1562 	}
1563 
1564 } /* qdselect() */
1565 
1566 /***************************************************************
1567 *
1568 *	qdwrite()... output to the QDSS screen as a TTY
1569 *
1570 ***************************************************************/
1571 
1572 extern qd_strategy();
1573 
1574 qdwrite(dev, uio)
1575 dev_t dev;
1576 struct uio *uio;
1577 {
1578 	register struct tty *tp;
1579 	register int minor_dev;
1580 	register int unit;
1581 
1582 	minor_dev = minor(dev);
1583 	unit = (minor_dev >> 2) & 0x07;
1584 
1585 	/*------------------------------
1586 	* if this is the console...  */
1587 
1588 	if ((minor_dev & 0x03) != 0x02	&&
1589 	     qdflags[unit].inuse & CONS_DEV) {
1590 	    tp = &qd_tty[minor_dev];
1591 	    return ((*linesw[tp->t_line].l_write)(tp, uio));
1592 	}
1593 
1594 	/*------------------------------------------------
1595 	* else this must be a DMA xfer from user space */
1596 
1597 	else if (qdflags[unit].inuse & GRAPHIC_DEV) {
1598 	    return (physio(qd_strategy, &qdbuf[unit],
1599 			   dev, B_WRITE, minphys, uio));
1600 	}
1601 }
1602 
1603 /***************************************************************
1604 *
1605 *	qdread()... read from QDSS keyboard as a TTY
1606 *
1607 ***************************************************************/
1608 
1609 qdread(dev, uio)
1610 dev_t dev;
1611 struct uio *uio;
1612 {
1613 	register struct tty *tp;
1614 	register int minor_dev;
1615 	register int unit;
1616 
1617 	minor_dev = minor(dev);
1618 	unit = (minor_dev >> 2) & 0x07;
1619 
1620 	/*------------------------------
1621 	* if this is the console...  */
1622 
1623 	if ((minor_dev & 0x03) != 0x02	&&
1624 	     qdflags[unit].inuse & CONS_DEV) {
1625 	    tp = &qd_tty[minor_dev];
1626 	    return ((*linesw[tp->t_line].l_read)(tp, uio));
1627 	}
1628 
1629 	/*------------------------------------------------
1630 	* else this must be a bitmap-to-processor xfer */
1631 
1632 	else if (qdflags[unit].inuse & GRAPHIC_DEV) {
1633 	    return (physio(qd_strategy, &qdbuf[unit],
1634 			   dev, B_READ, minphys, uio));
1635 	}
1636 }
1637 
1638 /***************************************************************
1639 *
1640 *	qd_strategy()... strategy routine to do DMA
1641 *
1642 ***************************************************************/
1643 
1644 qd_strategy(bp)
1645 register struct buf *bp;
1646 {
1647 	register struct dga *dga;
1648 	register struct adder *adder;
1649 
1650 	char *DMAbufp;
1651 
1652 	int QBAreg;
1653 	int bytcnt;
1654 	int s;
1655 	int unit;
1656 	int cookie;
1657 
1658 	int i,j,k;
1659 
1660 	unit = (minor(bp->b_dev) >> 2) & 0x07;
1661 
1662 /*-----------------
1663 * init pointers */
1664 
1665 	if ((QBAreg = ubasetup(0, bp, 0)) == 0) {
1666 	    mprintf("\nqd%d: qd_strategy: QBA setup error", unit);
1667 	    goto STRAT_ERR;
1668 	}
1669 
1670 	dga = (struct dga *) qdmap[unit].dga;
1671 
1672 	s = spl5();
1673 
1674 	qdflags[unit].user_dma = -1;
1675 
1676 	dga->csr |= DMA_IE;
1677 
1678 	cookie = QBAreg & 0x3FFFF;
1679 	dga->adrs_lo = (short) cookie;
1680 	dga->adrs_hi = (short) (cookie >> 16);
1681 
1682 	dga->bytcnt_lo = (short) bp->b_bcount;
1683 	dga->bytcnt_hi = (short) (bp->b_bcount >> 16);
1684 
1685 	while (qdflags[unit].user_dma) {
1686 	    sleep((caddr_t)&qdflags[unit].user_dma, QDPRIOR);
1687 	}
1688 
1689 	splx(s);
1690 	ubarelse(0, &QBAreg);
1691 
1692 	if (!(dga->csr & DMA_ERR)) {
1693 	    iodone(bp);
1694 	    return;
1695 	}
1696 
1697 STRAT_ERR:
1698 	adder = (struct adder *) qdmap[unit].adder;
1699 	adder->command = CANCEL;		/* cancel adder activity */
1700 	dga->csr &= ~DMA_IE;
1701 	dga->csr &= ~0x0600;		/* halt DMA (reset fifo) */
1702 	dga->csr |= DMA_ERR;		/* clear error condition */
1703 	bp->b_flags |= B_ERROR; 	/* flag an error to physio() */
1704 
1705 	/* if DMA was running, flush spurious intrpt */
1706 
1707 	if (dga->bytcnt_lo != 0) {
1708 	    dga->bytcnt_lo = 0;
1709 	    dga->bytcnt_hi = 0;
1710 	    DMA_SETIGNORE(DMAheader[unit]);
1711 	    dga->csr |= DMA_IE;
1712 	}
1713 
1714 	iodone(bp);
1715 
1716 } /* qd_strategy */
1717 
1718 /*******************************************************************
1719 *
1720 *	qdstart()... startup output to the console screen
1721 *
1722 ********************************************************************
1723 *
1724 *	calling convention:
1725 *
1726 *		qdstart(tp);
1727 *		struct tty *tp; 	;pointer to tty structure
1728 *
1729 ********/
1730 
1731 qdstart(tp)
1732 register struct tty *tp;
1733 {
1734 	register int which_unit, unit, c;
1735 	register struct tty *tp0;
1736 	int s;
1737 
1738 	int curs_on;
1739 	struct dga *dga;
1740 
1741 	unit = minor(tp->t_dev);
1742 
1743 	tp0 = &qd_tty[(unit & 0x0FC)+1];
1744 	which_unit = (unit >> 2) & 0x3;
1745 	unit &= 0x03;
1746 
1747 	s = spl5();
1748 
1749 /*------------------------------------------------------------------
1750 * If it's currently active, or delaying, no need to do anything. */
1751 
1752 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
1753 		goto out;
1754 
1755 /*-------------------------------------------------------------------
1756 * Display chars until the queue is empty, if the alternate console device
1757 * is open direct chars there.  Drop input from anything but the console
1758 * device on the floor.	*/
1759 
1760 	while (tp->t_outq.c_cc) {
1761 	    c = getc(&tp->t_outq);
1762 	    if (unit == 0) {
1763 		if (tp0->t_state & TS_ISOPEN)
1764 		    (*linesw[tp0->t_line].l_rint)(c, tp0);
1765 		else
1766 		    blitc(which_unit, c & 0xFF);
1767 	    }
1768 	}
1769 
1770 /*--------------------------------------------------------
1771 * If there are sleepers, and output has drained below low
1772 * water mark, wake up the sleepers. */
1773 
1774 	if ( tp->t_outq.c_cc <= TTLOWAT(tp) ) {
1775 		if (tp->t_state & TS_ASLEEP){
1776 			tp->t_state &= ~TS_ASLEEP;
1777 			wakeup((caddr_t) &tp->t_outq);
1778 		}
1779 	}
1780 
1781 	tp->t_state &= ~TS_BUSY;
1782 
1783 out:
1784 	splx(s);
1785 
1786 } /* qdstart */
1787 
1788 
1789 /*******************************************************************
1790 *
1791 *	qdstop()... stop the tty
1792 *
1793 *******************************************************************/
1794 
1795 qdstop(tp, flag)
1796 register struct tty *tp;
1797 int flag;
1798 {
1799 	register int s;
1800 
1801 	s = spl5();	/* block intrpts during state modification */
1802 
1803 	if (tp->t_state & TS_BUSY) {
1804 	    if ((tp->t_state & TS_TTSTOP) == 0) {
1805 		tp->t_state |= TS_FLUSH;
1806 	    } else
1807 		tp->t_state &= ~TS_BUSY;
1808 	}
1809 	splx(s);
1810 }
1811 
1812 /*******************************************************************
1813 *
1814 *	blitc()... output a character to the QDSS screen
1815 *
1816 ********************************************************************
1817 *
1818 *	calling convention:
1819 *
1820 *		blitc(chr);
1821 *		char chr;		;character to be displayed
1822 *
1823 ********/
1824 
1825 blitc(unit, chr)
1826 int unit;
1827 char chr;
1828 {
1829 	register struct adder *adder;
1830 	register struct dga *dga;
1831 	register int i;
1832 
1833 	short x;
1834 
1835 /*---------------
1836 * init stuff  */
1837 
1838 	adder = (struct adder *) qdmap[unit].adder;
1839 	dga = (struct dga *) qdmap[unit].dga;
1840 
1841 /*---------------------------
1842 * non display character?  */
1843 
1844 	chr &= 0x7F;
1845 
1846 	switch (chr) {
1847 
1848 	    case '\r':			/* return char */
1849 		cursor[unit].x = 0;
1850 		dga->x_cursor = TRANX(cursor[unit].x);
1851 		return(0);
1852 
1853 	    case '\t':			/* tab char */
1854 
1855 		for (i = 8 - ((cursor[unit].x >> 3) & 0x07); i > 0; --i) {
1856 		    blitc(unit, ' ');
1857 		}
1858 		return(0);
1859 
1860 	    case '\n':			/* line feed char */
1861 
1862 		if ((cursor[unit].y += CHAR_HEIGHT) > (863 - CHAR_HEIGHT)) {
1863 		    if (qdflags[unit].inuse & GRAPHIC_DEV) {
1864 			cursor[unit].y = 0;
1865 		    } else {
1866 			cursor[unit].y -= CHAR_HEIGHT;
1867 			scroll_up(adder);
1868 		    }
1869 		}
1870 		dga->y_cursor = TRANY(cursor[unit].y);
1871 		return(0);
1872 
1873 	    case '\b':			/* backspace char */
1874 		if (cursor[unit].x > 0) {
1875 		    cursor[unit].x -= CHAR_WIDTH;
1876 		    blitc(unit, ' ');
1877 		    cursor[unit].x -= CHAR_WIDTH;
1878 		    dga->x_cursor = TRANX(cursor[unit].x);
1879 		}
1880 		return(0);
1881 
1882 	    default:
1883 		if (chr < ' ' || chr > '~')
1884 		    return(0);
1885 	}
1886 
1887 /*------------------------------------------
1888 * setup VIPER operand control registers  */
1889 
1890 	write_ID(adder, CS_UPDATE_MASK, 0x0001);  /* select plane #0 */
1891 	write_ID(adder, SRC1_OCR_B,
1892 			EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY);
1893 
1894 	write_ID(adder, CS_UPDATE_MASK, 0x00FE);  /* select other planes */
1895 	write_ID(adder, SRC1_OCR_B,
1896 			EXT_SOURCE | INT_NONE | NO_ID | BAR_SHIFT_DELAY);
1897 
1898 	write_ID(adder, CS_UPDATE_MASK, 0x00FF);  /* select all planes */
1899 	write_ID(adder, DST_OCR_B,
1900 			EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
1901 
1902 	write_ID(adder, MASK_1, 0xFFFF);
1903 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 1);
1904 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
1905 
1906 /*----------------------------------------
1907 * load DESTINATION origin and vectors  */
1908 
1909 	adder->fast_dest_dy = 0;
1910 	adder->slow_dest_dx = 0;
1911 	adder->error_1 = 0;
1912 	adder->error_2 = 0;
1913 
1914 	adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL;
1915 
1916 	wait_status(adder, RASTEROP_COMPLETE);
1917 
1918 	adder->destination_x = cursor[unit].x;
1919 	adder->fast_dest_dx = CHAR_WIDTH;
1920 
1921 	adder->destination_y = cursor[unit].y;
1922 	adder->slow_dest_dy = CHAR_HEIGHT;
1923 
1924 /*-----------------------------------
1925 * load SOURCE origin and vectors  */
1926 
1927 	adder->source_1_x = FONT_X + ((chr - ' ') * CHAR_WIDTH);
1928 	adder->source_1_y = FONT_Y;
1929 
1930 	adder->source_1_dx = CHAR_WIDTH;
1931 	adder->source_1_dy = CHAR_HEIGHT;
1932 
1933 	write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
1934 	adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE;
1935 
1936 /*-------------------------------------
1937 * update console cursor coordinates */
1938 
1939 	cursor[unit].x += CHAR_WIDTH;
1940 	dga->x_cursor = TRANX(cursor[unit].x);
1941 
1942 	if (cursor[unit].x > (1024 - CHAR_WIDTH)) {
1943 	    blitc(unit, '\r');
1944 	    blitc(unit, '\n');
1945 	}
1946 
1947 } /* blitc */
1948 
1949 qdreset(){}
1950 qd_init(){}
1951 
1952 /******************************************************************
1953 *******************************************************************
1954 *******************************************************************
1955 *
1956 *	INTERRUPT SERVICE ROUTINES START HERE:
1957 *
1958 *******************************************************************
1959 *******************************************************************
1960 ******************************************************************/
1961 
1962 /*****************************************************************
1963 *
1964 *	qddint()... service "DMA DONE" interrupt condition
1965 *
1966 *****************************************************************/
1967 
1968 qddint(qd)
1969 int qd;
1970 {
1971 	register struct DMAreq_header *header;
1972 	register struct DMAreq *request;
1973 	register struct dga *dga;
1974 	struct adder *adder;
1975 
1976 	int cookie;			/* DMA adrs for QDSS */
1977 	int i;
1978 
1979 	spl4(); 			/* allow interval timer in */
1980 
1981 /*-----------------
1982 * init pointers */
1983 
1984 	header = DMAheader[qd]; 	    /* register for optimization */
1985 	dga = (struct dga *) qdmap[qd].dga;
1986 	adder = (struct adder *) qdmap[qd].adder;
1987 
1988 /*------------------------------------------------------------------------
1989 * if this interrupt flagged as bogus for interrupt flushing purposes.. */
1990 
1991 	if (DMA_ISIGNORE(header)) {
1992 	    DMA_CLRIGNORE(header);
1993 	    return;
1994 	}
1995 
1996 /*----------------------------------------------------
1997 * dump a DMA hardware error message if appropriate */
1998 
1999 	if (dga->csr & DMA_ERR) {
2000 
2001 	    if (dga->csr & PARITY_ERR)
2002 		mprintf("\nqd%d: qddint: DMA hardware parity fault.", qd);
2003 
2004 	    if (dga->csr & BUS_ERR)
2005 		mprintf("\nqd%d: qddint: DMA hardware bus error.", qd);
2006 	}
2007 
2008 /*----------------------------------------
2009 * if this was a DMA from user space... */
2010 
2011 	if (qdflags[qd].user_dma) {
2012 	    qdflags[qd].user_dma = 0;
2013 	    wakeup((caddr_t)&qdflags[qd].user_dma);
2014 	    return;
2015 	}
2016 
2017 /*------------------------------------------------------------------------
2018 * if we're doing DMA request queue services, field the error condition */
2019 
2020 	if (dga->csr & DMA_ERR) {
2021 
2022 	    dga->csr &= ~0x0600;		/* halt DMA (reset fifo) */
2023 	    dga->csr |= DMA_ERR;		/* clear error condition */
2024 	    adder->command = CANCEL;		/* cancel adder activity */
2025 
2026 	    DMA_SETERROR(header);	/* flag error in header status word */
2027 	    DMA_CLRACTIVE(header);
2028 	    header->DMAreq[header->oldest].DMAdone |= HARD_ERROR;
2029 	    header->newest = header->oldest;
2030 	    header->used = 0;
2031 
2032 	    if (rsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
2033 		selwakeup(rsel[qd], 0);
2034 		rsel[qd] = 0;
2035 		qdflags[qd].selmask &= ~SEL_WRITE;
2036 	    }
2037 
2038 	    if (dga->bytcnt_lo != 0) {
2039 		dga->bytcnt_lo = 0;
2040 		dga->bytcnt_hi = 0;
2041 		DMA_SETIGNORE(header);
2042 	    }
2043 
2044 	    return;
2045 	}
2046 
2047 /*----------------------------------------------------------------------------
2048 * if the DMA request queue is now becoming non-full, wakeup "select" client */
2049 
2050 	if (DMA_ISFULL(header)) {
2051 
2052 	    if (rsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
2053 		selwakeup(rsel[qd], 0);
2054 		rsel[qd] = 0;
2055 		qdflags[qd].selmask &= ~SEL_WRITE;
2056 	    }
2057 	}
2058 
2059 	header->DMAreq[header->oldest].DMAdone |= REQUEST_DONE;
2060 
2061 	if (DMA_ISEMPTY(header)) {
2062 	    mprintf("\nqd%d: qddint: unexpected interrupt", qd);
2063 	    return;
2064 	}
2065 
2066 	DMA_GETEND(header);	/* update request queue indices */
2067 
2068 /*------------------------------------------------------------
2069 * if no more DMA pending, wake up "select" client and exit */
2070 
2071 	if (DMA_ISEMPTY(header)) {
2072 
2073 	    if (rsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
2074 		selwakeup(rsel[qd], 0);
2075 		rsel[qd] = 0;
2076 		qdflags[qd].selmask &= ~SEL_WRITE;
2077 	    }
2078 
2079 	    DMA_CLRACTIVE(header);  /* flag DMA done */
2080 	    return;
2081 	}
2082 
2083 /*---------------------------
2084 * initiate next DMA xfer  */
2085 
2086 	request = DMA_GETBEGIN(header);
2087 
2088 	switch (request->DMAtype) {
2089 
2090 	    case DISPLIST:
2091 		dga->csr |= DL_ENB;
2092 		break;
2093 
2094 	    case PTOB:
2095 		dga->csr |= PTOB_ENB;
2096 		break;
2097 
2098 	    case BTOP:
2099 		dga->csr |= BTOP_ENB;
2100 		break;
2101 
2102 	    default:
2103 		mprintf("\nqd%d: qddint: illegal DMAtype parameter.", qd);
2104 		DMA_CLRACTIVE(header);	/* flag DMA done */
2105 		return;
2106 	}
2107 
2108 	if (request->DMAdone & COUNT_ZERO) {
2109 	    dga->csr &= ~SET_DONE_FIFO;
2110 	} else if (request->DMAdone & FIFO_EMPTY) {
2111 	    dga->csr |= SET_DONE_FIFO;
2112 	}
2113 
2114 	if (request->DMAdone & WORD_PACK)
2115 	    dga->csr &= ~BYTE_DMA;
2116 	else if (request->DMAdone & BYTE_PACK)
2117 	    dga->csr |= BYTE_DMA;
2118 
2119 	dga->csr |= DMA_IE;
2120 
2121 	cookie = ((int)request->bufp - (int)header) + (int)header->QBAreg;
2122 
2123 	dga->adrs_lo = (short) cookie;
2124 	dga->adrs_hi = (short) (cookie >> 16);
2125 
2126 	dga->bytcnt_lo = (short) request->length;
2127 	dga->bytcnt_hi = (short) (request->length >> 16);
2128 
2129 	return;
2130 }
2131 
2132 /*****************************************************************
2133 *
2134 *	qdaint()... ADDER interrupt service
2135 *
2136 *****************************************************************/
2137 
2138 qdaint(qd)
2139 register int qd;
2140 {
2141 	register struct adder *adder;
2142 	struct color_buf *cbuf;
2143 
2144 	short stat;
2145 	int i;
2146 	register struct rgb *rgbp;
2147 	register short *red;
2148 	register short *green;
2149 	register short *blue;
2150 
2151 	spl4(); 			/* allow interval timer in */
2152 
2153 	adder = (struct adder *) qdmap[qd].adder;
2154 
2155 /*------------------------------------------------------------------------
2156 * service the vertical blank interrupt (VSYNC bit) by loading any pending
2157 * color map load request  */
2158 
2159 	if (adder->status & VSYNC) {
2160 	    adder->status &= ~VSYNC;		/* clear the interrupt */
2161 
2162 	    cbuf = color_buf[qd];
2163 	    if (cbuf->status & LOAD_COLOR_MAP) {
2164 
2165 		red = (short *) qdmap[qd].red;
2166 		green = (short *) qdmap[qd].green;
2167 		blue = (short *) qdmap[qd].blue;
2168 
2169 		for (i = cbuf->count, rgbp = cbuf->rgb; --i >= 0; rgbp++) {
2170 
2171 		    red[rgbp->offset] = (short) rgbp->red;
2172 		    green[rgbp->offset] = (short) rgbp->green;
2173 		    blue[rgbp->offset] = (short) rgbp->blue;
2174 		}
2175 
2176 		cbuf->status &= ~LOAD_COLOR_MAP;
2177 	    }
2178 	}
2179 
2180 /*-------------------------------------------------
2181 * service the scroll interrupt (FRAME_SYNC bit) */
2182 
2183 	if (adder->status & FRAME_SYNC) {
2184 	    adder->status &= ~FRAME_SYNC;	/* clear the interrupt */
2185 
2186 	    if (scroll[qd]->status & LOAD_REGS) {
2187 
2188 		for ( i = 1000, adder->status = 0
2189 		    ; i > 0  &&  !((stat = adder->status) & ID_SCROLL_READY)
2190 		    ; --i);
2191 
2192 		if (i == 0) {
2193 		    mprintf("\nqd%d: qdaint: timeout on ID_SCROLL_READY", qd);
2194 		    return;
2195 		}
2196 
2197 		adder->ID_scroll_data = scroll[qd]->viper_constant;
2198 		adder->ID_scroll_command = ID_LOAD | SCROLL_CONSTANT;
2199 
2200 		adder->y_scroll_constant = scroll[qd]->y_scroll_constant;
2201 		adder->y_offset_pending = scroll[qd]->y_offset;
2202 
2203 		if (scroll[qd]->status & LOAD_INDEX) {
2204 
2205 		    adder->x_index_pending = scroll[qd]->x_index_pending;
2206 		    adder->y_index_pending = scroll[qd]->y_index_pending;
2207 		}
2208 
2209 	    scroll[qd]->status = 0x00;
2210 	    }
2211 	}
2212 }
2213 
2214 /*****************************************************************
2215 *
2216 *	qdiint()... DUART input interrupt service routine
2217 *
2218 *****************************************************************/
2219 
2220 qdiint(qd)
2221 register int qd;
2222 {
2223 	register struct _vs_event *event;
2224 	register struct qdinput *eqh;
2225 
2226 	struct dga *dga;
2227 	struct duart *duart;
2228 	struct mouse_report *new_rep;
2229 
2230 	struct uba_device *ui;
2231 	struct tty *tp;
2232 
2233 	char chr;
2234 	int i,j;
2235 	int k,l;
2236 
2237 	u_short status;
2238 	u_short data;
2239 	u_short key;
2240 
2241 	char do_wakeup = 0;		/* flag to do a select wakeup call */
2242 	char a, b, c;			/* mouse button test variables */
2243 
2244 	spl4(); 			/* allow interval timer in */
2245 
2246 	eqh = eq_header[qd];		/* optimized as a register */
2247 	new_rep = &current_rep[qd];
2248 	duart = (struct duart *) qdmap[qd].duart;
2249 
2250 /*-----------------------------------------
2251 * if the graphic device is turned on..	*/
2252 
2253 	if (qdflags[qd].inuse & GRAPHIC_DEV) {
2254 
2255 	    /*---------------
2256 	    * empty DUART */
2257 
2258 	    while ((status = duart->statusA) & RCV_RDY	||
2259 		   (status = duart->statusB) & RCV_RDY) {
2260 
2261 		/*---------------------------------
2262 		* pick up LK-201 input (if any) */
2263 
2264 		if ((status = duart->statusA) & RCV_RDY) {
2265 
2266 		    /* if error condition, then reset it */
2267 
2268 		    if ((status = duart->statusA) & 0x70) {
2269 			duart->cmdA = 0x40;
2270 			continue;
2271 		    }
2272 
2273 		    /* event queue full now? (overflow condition) */
2274 
2275 		    if (ISFULL(eqh) == TRUE) {
2276 			mprintf("\nqd%d: qdiint: event queue overflow", qd);
2277 			break;
2278 		    }
2279 
2280 		    /*--------------------------------------
2281 		    * Check for various keyboard errors  */
2282 
2283 		    key = duart->dataA & 0xFF;
2284 
2285 		    if( key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
2286 			key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
2287 			mprintf("\nqd%d: qdiint: keyboard error, code = %x",qd,key);
2288 			return(0);
2289 		    }
2290 
2291 		    if (key < LK_LOWEST)
2292 			return(0);
2293 
2294 		    ++do_wakeup;	/* request a select wakeup call */
2295 
2296 		    event = PUTBEGIN(eqh);
2297 		    PUTEND(eqh);
2298 
2299 		    event->vse_key = key;
2300 		    event->vse_key &= 0x00FF;
2301 		    event->vse_x = eqh->curs_pos.x;
2302 		    event->vse_y = eqh->curs_pos.y;
2303 		    event->vse_time = TOY;
2304 		    event->vse_type = VSE_BUTTON;
2305 		    event->vse_direction = VSE_KBTRAW;
2306 		    event->vse_device = VSE_DKB;
2307 		}
2308 
2309 		/*-------------------------------------
2310 		* pick up the mouse input (if any)  */
2311 
2312 		if ((status = duart->statusB) & RCV_RDY  &&
2313 		     qdflags[qd].pntr_id == MOUSE_ID) {
2314 
2315 		    if (status & 0x70) {
2316 			duart->cmdB = 0x40;
2317 			continue;
2318 		    }
2319 
2320 		    /* event queue full now? (overflow condition) */
2321 
2322 		    if (ISFULL(eqh) == TRUE) {
2323 			mprintf("\nqd%d: qdiint: event queue overflow", qd);
2324 			break;
2325 		    }
2326 
2327 		    data = duart->dataB;      /* get report byte */
2328 		    ++new_rep->bytcnt;	      /* bump report byte count */
2329 
2330 		    /*---------------------------
2331 		    * if 1st byte of report.. */
2332 
2333 		    if ( data & START_FRAME) {
2334 			new_rep->state = data;
2335 			if (new_rep->bytcnt > 1) {
2336 			    new_rep->bytcnt = 1;    /* start of new frame */
2337 			    continue;		    /* ..continue looking */
2338 			}
2339 		    }
2340 
2341 		    /*---------------------------
2342 		    * if 2nd byte of report.. */
2343 
2344 		    else if (new_rep->bytcnt == 2) {
2345 			new_rep->dx = data & 0x00FF;
2346 		    }
2347 
2348 		    /*-------------------------------------------------
2349 		    * if 3rd byte of report, load input event queue */
2350 
2351 		    else if (new_rep->bytcnt == 3) {
2352 
2353 			new_rep->dy = data & 0x00FF;
2354 			new_rep->bytcnt = 0;
2355 
2356 			/*-----------------------------------
2357 			* if mouse position has changed.. */
2358 
2359 			if (new_rep->dx != 0  ||  new_rep->dy != 0) {
2360 
2361 			    /*---------------------------------------------
2362 			    * calculate acceleration factor, if needed	*/
2363 
2364 			    if (qdflags[qd].curs_acc > ACC_OFF) {
2365 
2366 				if (qdflags[qd].curs_thr <= new_rep->dx)
2367 				    new_rep->dx +=
2368 					(new_rep->dx - qdflags[qd].curs_thr)
2369 					 * qdflags[qd].curs_acc;
2370 
2371 				if (qdflags[qd].curs_thr <= new_rep->dy)
2372 				    new_rep->dy +=
2373 					(new_rep->dy - qdflags[qd].curs_thr)
2374 					 * qdflags[qd].curs_acc;
2375 			    }
2376 
2377 			    /*-------------------------------------
2378 			    * update cursor position coordinates */
2379 
2380 			    if (new_rep->state & X_SIGN) {
2381 				eqh->curs_pos.x += new_rep->dx;
2382 				if (eqh->curs_pos.x > 1023)
2383 				    eqh->curs_pos.x = 1023;
2384 			    }
2385 			    else {
2386 				eqh->curs_pos.x -= new_rep->dx;
2387 				if (eqh->curs_pos.x < -15)
2388 				    eqh->curs_pos.x = -15;
2389 			    }
2390 
2391 			    if (new_rep->state & Y_SIGN) {
2392 				 eqh->curs_pos.y -= new_rep->dy;
2393 				 if (eqh->curs_pos.y < -15)
2394 				     eqh->curs_pos.y = -15;
2395 			    }
2396 			    else {
2397 				eqh->curs_pos.y += new_rep->dy;
2398 				if (eqh->curs_pos.y > 863)
2399 				    eqh->curs_pos.y = 863;
2400 			    }
2401 
2402 			    /*---------------------------------
2403 			    * update cursor screen position */
2404 
2405 			    dga = (struct dga *) qdmap[qd].dga;
2406 			    dga->x_cursor = TRANX(eqh->curs_pos.x);
2407 			    dga->y_cursor = TRANY(eqh->curs_pos.y);
2408 
2409 			    /*--------------------------------------------
2410 			    * if cursor is in the box, no event report */
2411 
2412 			    if (eqh->curs_pos.x <= eqh->curs_box.right	&&
2413 				eqh->curs_pos.x >= eqh->curs_box.left  &&
2414 				eqh->curs_pos.y >= eqh->curs_box.top  &&
2415 				eqh->curs_pos.y <= eqh->curs_box.bottom ) {
2416 				    goto GET_MBUTTON;
2417 			    }
2418 
2419 			    /*---------------------------------
2420 			    * report the mouse motion event */
2421 
2422 			    event = PUTBEGIN(eqh);
2423 			    PUTEND(eqh);
2424 
2425 			    ++do_wakeup;   /* request a select wakeup call */
2426 
2427 			    event->vse_x = eqh->curs_pos.x;
2428 			    event->vse_y = eqh->curs_pos.y;
2429 
2430 			    event->vse_device = VSE_MOUSE;  /* mouse */
2431 			    event->vse_type = VSE_MMOTION;  /* pos changed */
2432 			    event->vse_key = 0;
2433 			    event->vse_direction = 0;
2434 			    event->vse_time = TOY;	/* time stamp */
2435 			}
2436 
2437 GET_MBUTTON:
2438 			/*-------------------------------
2439 			* if button state has changed */
2440 
2441 			a = new_rep->state & 0x07;    /*mask nonbutton bits */
2442 			b = last_rep[qd].state & 0x07;
2443 
2444 			if (a ^ b) {
2445 
2446 			    for ( c = 1;  c < 8; c <<= 1) {
2447 
2448 				if (!( c & (a ^ b))) /* this button change? */
2449 				    continue;
2450 
2451 				/* event queue full? (overflow condition) */
2452 
2453 				if (ISFULL(eqh) == TRUE) {
2454 				    mprintf("\nqd%d: qdiint: event queue overflow", qd);
2455 				    break;
2456 				}
2457 
2458 				event = PUTBEGIN(eqh);	/* get new event */
2459 				PUTEND(eqh);
2460 
2461 				++do_wakeup;   /* request select wakeup */
2462 
2463 				event->vse_x = eqh->curs_pos.x;
2464 				event->vse_y = eqh->curs_pos.y;
2465 
2466 				event->vse_device = VSE_MOUSE;	/* mouse */
2467 				event->vse_type = VSE_BUTTON; /* new button */
2468 				event->vse_time = TOY;	      /* time stamp */
2469 
2470 				/* flag changed button and if up or down */
2471 
2472 				if (c == RIGHT_BUTTON)
2473 				    event->vse_key = VSE_RIGHT_BUTTON;
2474 				else if (c == MIDDLE_BUTTON)
2475 				    event->vse_key = VSE_MIDDLE_BUTTON;
2476 				else if (c == LEFT_BUTTON)
2477 				    event->vse_key = VSE_LEFT_BUTTON;
2478 
2479 				/* set bit = button depressed */
2480 
2481 				if (c & a)
2482 				    event->vse_direction = VSE_KBTDOWN;
2483 				else
2484 				    event->vse_direction = VSE_KBTUP;
2485 			    }
2486 			}
2487 
2488 			/* refresh last report */
2489 
2490 			last_rep[qd] = current_rep[qd];
2491 
2492 		    }  /* get last byte of report */
2493 		} /* pickup mouse input */
2494 
2495 		/*--------------------------------
2496 		* pickup tablet input, if any  */
2497 
2498 		else if ((status = duart->statusB) & RCV_RDY  &&
2499 			 qdflags[qd].pntr_id == TABLET_ID) {
2500 
2501 		    if (status & 0x70) {
2502 			duart->cmdB = 0x40;
2503 			continue;
2504 		    }
2505 
2506 		    /* event queue full now? (overflow condition) */
2507 
2508 		    if (ISFULL(eqh) == TRUE) {
2509 			mprintf("\nqd%d: qdiint: event queue overflow", qd);
2510 			break;
2511 		    }
2512 
2513 		    data = duart->dataB;      /* get report byte */
2514 		    ++new_rep->bytcnt;	      /* bump report byte count */
2515 
2516 		    /*---------------------------
2517 		    * if 1st byte of report.. */
2518 
2519 		    if (data & START_FRAME) {
2520 			new_rep->state = data;
2521 			if (new_rep->bytcnt > 1) {
2522 			    new_rep->bytcnt = 1;    /* start of new frame */
2523 			    continue;		    /* ..continue looking */
2524 			}
2525 		    }
2526 
2527 		    /*---------------------------
2528 		    * if 2nd byte of report.. */
2529 
2530 		    else if (new_rep->bytcnt == 2) {
2531 			new_rep->dx = data & 0x3F;
2532 		    }
2533 
2534 		    /*---------------------------
2535 		    * if 3rd byte of report.. */
2536 
2537 		    else if (new_rep->bytcnt == 3) {
2538 			new_rep->dx |= (data & 0x3F) << 6;
2539 		    }
2540 
2541 		    /*---------------------------
2542 		    * if 4th byte of report.. */
2543 
2544 		    else if (new_rep->bytcnt == 4) {
2545 			new_rep->dy = data & 0x3F;
2546 		    }
2547 
2548 		    /*-------------------------------------------------
2549 		    * if 5th byte of report, load input event queue */
2550 
2551 		    else if (new_rep->bytcnt == 5) {
2552 
2553 			new_rep->dy |= (data & 0x3F) << 6;
2554 			new_rep->bytcnt = 0;
2555 
2556 			/*-------------------------------------
2557 			* update cursor position coordinates */
2558 
2559 			new_rep->dx /= qdflags[qd].tab_res;
2560 			new_rep->dy = (2200 - new_rep->dy)
2561 				      / qdflags[qd].tab_res;
2562 
2563 			if (new_rep->dx > 1023) {
2564 			    new_rep->dx = 1023;
2565 			}
2566 			if (new_rep->dy > 863) {
2567 			    new_rep->dy = 863;
2568 			}
2569 
2570 			/*
2571 			 * report an event if the puck/stylus has moved
2572 			 */
2573 
2574 			if (eqh->curs_pos.x != new_rep->dx ||
2575 			    eqh->curs_pos.y != new_rep->dy) {
2576 
2577 			    eqh->curs_pos.x = new_rep->dx;
2578 			    eqh->curs_pos.y = new_rep->dy;
2579 
2580 			    /*---------------------------------
2581 			    * update cursor screen position */
2582 
2583 			    dga = (struct dga *) qdmap[qd].dga;
2584 			    dga->x_cursor = TRANX(eqh->curs_pos.x);
2585 			    dga->y_cursor = TRANY(eqh->curs_pos.y);
2586 
2587 			    /*
2588 			     * if cursor is in the box, no event report
2589 			     */
2590 
2591 			    if (eqh->curs_pos.x <= eqh->curs_box.right	&&
2592 				eqh->curs_pos.x >= eqh->curs_box.left  &&
2593 				eqh->curs_pos.y >= eqh->curs_box.top  &&
2594 				eqh->curs_pos.y <= eqh->curs_box.bottom ) {
2595 				goto GET_TBUTTON;
2596 			    }
2597 
2598 			    /*---------------------------------
2599 			    * report the tablet motion event */
2600 
2601 			    event = PUTBEGIN(eqh);
2602 			    PUTEND(eqh);
2603 
2604 			    ++do_wakeup;   /* request a select wakeup call */
2605 
2606 			    event->vse_x = eqh->curs_pos.x;
2607 			    event->vse_y = eqh->curs_pos.y;
2608 
2609 			    event->vse_device = VSE_TABLET;  /* tablet */
2610 			    /*
2611 			     * right now, X handles tablet motion the same
2612 			     * as mouse motion
2613 			     */
2614 			    event->vse_type = VSE_MMOTION;   /* pos changed */
2615 			    event->vse_key = 0;
2616 			    event->vse_direction = 0;
2617 			    event->vse_time = TOY;	/* time stamp */
2618 			}
2619 GET_TBUTTON:
2620 			/*-------------------------------
2621 			* if button state has changed */
2622 
2623 			a = new_rep->state & 0x1E;   /* mask nonbutton bits */
2624 			b = last_rep[qd].state & 0x1E;
2625 
2626 			if (a ^ b) {
2627 
2628 			    /* event queue full now? (overflow condition) */
2629 
2630 			    if (ISFULL(eqh) == TRUE) {
2631 				mprintf("\nqd%d: qdiint: event queue overflow",qd);
2632 				break;
2633 			    }
2634 
2635 			    event = PUTBEGIN(eqh);  /* get new event */
2636 			    PUTEND(eqh);
2637 
2638 			    ++do_wakeup;   /* request a select wakeup call */
2639 
2640 			    event->vse_x = eqh->curs_pos.x;
2641 			    event->vse_y = eqh->curs_pos.y;
2642 
2643 			    event->vse_device = VSE_TABLET;  /* tablet */
2644 			    event->vse_type = VSE_BUTTON; /* button changed */
2645 			    event->vse_time = TOY;	   /* time stamp */
2646 
2647 			    /* define the changed button and if up or down */
2648 
2649 			    for ( c = 1;  c <= 0x10; c <<= 1) {
2650 				if (c & (a ^ b)) {
2651 				    if (c == T_LEFT_BUTTON)
2652 					event->vse_key = VSE_T_LEFT_BUTTON;
2653 				    else if (c == T_FRONT_BUTTON)
2654 					event->vse_key = VSE_T_FRONT_BUTTON;
2655 				    else if (c == T_RIGHT_BUTTON)
2656 					event->vse_key = VSE_T_RIGHT_BUTTON;
2657 				    else if (c == T_BACK_BUTTON)
2658 					event->vse_key = VSE_T_BACK_BUTTON;
2659 				    break;
2660 				}
2661 			    }
2662 
2663 			    /* set bit = button depressed */
2664 
2665 			    if (c & a)
2666 				event->vse_direction = VSE_KBTDOWN;
2667 			    else
2668 				event->vse_direction = VSE_KBTUP;
2669 			}
2670 
2671 			/* refresh last report */
2672 
2673 			last_rep[qd] = current_rep[qd];
2674 
2675 		    } /* get last byte of report */
2676 		} /* pick up tablet input */
2677 
2678 	    } /* while input available.. */
2679 
2680 	    /*---------------------
2681 	    * do select wakeup	*/
2682 
2683 	    if (rsel[qd] && do_wakeup && qdflags[qd].selmask & SEL_READ) {
2684 		selwakeup(rsel[qd], 0);
2685 		rsel[qd] = 0;
2686 		qdflags[qd].selmask &= ~SEL_READ;
2687 		do_wakeup = 0;
2688 	    }
2689 	}
2690 
2691 /*-----------------------------------------------------------------
2692 * if the graphic device is not turned on, this is console input */
2693 
2694 	else {
2695 
2696 	    ui = qdinfo[qd];
2697 	    if (ui == 0 || ui->ui_alive == 0)
2698 		return(0);
2699 
2700 	    tp = &qd_tty[qd << 2];
2701 
2702 	    /*--------------------------------------
2703 	    * Get a character from the keyboard. */
2704 
2705 	    while ((status = duart->statusA) & RCV_RDY) {
2706 
2707 		key = duart->dataA;
2708 		key &= 0xFF;
2709 
2710 		/*--------------------------------------
2711 		* Check for various keyboard errors  */
2712 
2713 		if( key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
2714 		    key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
2715 			mprintf("\nqd%d: qdiint: Keyboard error, code = %x",qd,key);
2716 			return(0);
2717 		}
2718 
2719 		if (key < LK_LOWEST)
2720 		    return(0);
2721 
2722 		/*---------------------------------
2723 		* See if its a state change key */
2724 
2725 		switch (key) {
2726 
2727 		    case LOCK:
2728 			q_keyboard.lock ^= 0xffff;	/* toggle */
2729 			if (q_keyboard.lock)
2730 			    led_control(qd, LK_LED_ENABLE, LK_LED_LOCK);
2731 			else
2732 			    led_control(qd, LK_LED_DISABLE, LK_LED_LOCK);
2733 			return;
2734 
2735 		    case SHIFT:
2736 			q_keyboard.shift ^= 0xFFFF;
2737 			return;
2738 
2739 		    case CNTRL:
2740 			q_keyboard.cntrl ^= 0xFFFF;
2741 			return;
2742 
2743 		    case ALLUP:
2744 			q_keyboard.cntrl = 0;
2745 			q_keyboard.shift = 0;
2746 			return;
2747 
2748 		    case REPEAT:
2749 			chr = q_keyboard.last;
2750 			break;
2751 
2752 		    /*-------------------------------------------------------
2753 		    * Test for cntrl characters. If set, see if the character
2754 		    * is elligible to become a control character. */
2755 
2756 		    default:
2757 
2758 			if (q_keyboard.cntrl) {
2759 				chr = q_key[key];
2760 				if (chr >= ' ' && chr <= '~')
2761 				    chr &= 0x1F;
2762 			}
2763 			else if( q_keyboard.lock || q_keyboard.shift )
2764 			    chr = q_shift_key[key];
2765 			else
2766 			    chr = q_key[key];
2767 			break;
2768 		}
2769 
2770 		q_keyboard.last = chr;
2771 
2772 		/*-----------------------------------
2773 		* Check for special function keys */
2774 
2775 		if (chr & 0x80) {
2776 			char *string;
2777 			string = q_special[chr & 0x7F];
2778 			while(*string)
2779 			    (*linesw[tp->t_line].l_rint)(*string++, tp);
2780 		}
2781 		else {
2782 			(*linesw[tp->t_line].l_rint)(chr, tp);
2783 		}
2784 	    }
2785 	}
2786 
2787 /*----------------------
2788 * cleanup and exit  */
2789 
2790 	return(0);
2791 
2792 } /* qdiint */
2793 
2794 /******************************************************************
2795 *******************************************************************
2796 *******************************************************************
2797 *
2798 *	THE SUBROUTINES START HERE:
2799 *
2800 ******************************************************************/
2801 
2802 /*****************************************************************
2803 *
2804 *	clear_qd_screen()... clear the QDSS screen
2805 *
2806 ******************************************************************
2807 *
2808 *			     >>> NOTE <<<
2809 *
2810 *   This code requires that certain adder initialization be valid.  To
2811 *   assure that this requirement is satisfied, this routine should be
2812 *   called only after calling the "setup_dragon()" function.
2813 *
2814 *   Clear the bitmap a piece at a time. Since the fast scroll clear
2815 *   only clears the current displayed portion of the bitmap put a
2816 *   temporary value in the y limit register so we can access whole
2817 *   bitmap
2818 *
2819 ****************/
2820 
2821 clear_qd_screen(unit)
2822 int unit;
2823 {
2824 	register struct adder *adder;
2825 	adder = (struct adder *) qdmap[unit].adder;
2826 
2827 	adder->x_limit = 1024;
2828 	adder->y_limit = 2048 - CHAR_HEIGHT;
2829 	adder->y_offset_pending = 0;
2830 
2831 	wait_status(adder, VSYNC);	/* wait at LEAST 1 full frame */
2832 	wait_status(adder, VSYNC);
2833 
2834 	adder->y_scroll_constant = SCROLL_ERASE;
2835 
2836 	wait_status(adder, VSYNC);
2837 	wait_status(adder, VSYNC);
2838 
2839 	adder->y_offset_pending = 864;
2840 
2841 	wait_status(adder, VSYNC);
2842 	wait_status(adder, VSYNC);
2843 
2844 	adder->y_scroll_constant = SCROLL_ERASE;
2845 
2846 	wait_status(adder, VSYNC);
2847 	wait_status(adder, VSYNC);
2848 
2849 	adder->y_offset_pending = 1728;
2850 
2851 	wait_status(adder, VSYNC);
2852 	wait_status(adder, VSYNC);
2853 
2854 	adder->y_scroll_constant = SCROLL_ERASE;
2855 
2856 	wait_status(adder, VSYNC);
2857 	wait_status(adder, VSYNC);
2858 
2859 	adder->y_offset_pending = 0;	 /* back to normal */
2860 
2861 	wait_status(adder, VSYNC);
2862 	wait_status(adder, VSYNC);
2863 
2864 	adder->x_limit = MAX_SCREEN_X;
2865 	adder->y_limit = MAX_SCREEN_Y + FONT_HEIGHT;
2866 
2867 } /* clear_qd_screen */
2868 
2869 /**********************************************************************
2870 *
2871 *	qdputc()... route kernel console output to display destination
2872 *
2873 ***********************************************************************
2874 *
2875 *	calling convention:
2876 *
2877 *		qdputc(chr);
2878 *
2879 *	where:	char chr;	 ;character for output
2880 *
2881 ****************/
2882 
2883 qdputc(chr)
2884 register char chr;
2885 {
2886 	register struct tty *tp0;
2887 
2888 /*---------------------------------------------------------
2889 * if system is now physical, forget it (ie: crash DUMP) */
2890 
2891 	if ( (mfpr(MAPEN) & 1) == 0 )
2892 	    return;
2893 
2894 /*--------------------------------------------------
2895 * direct kernel output char to the proper place  */
2896 
2897 	tp0 = &qd_tty[1];
2898 
2899 	if (qdflags[0].kernel_loop != 0  &&  tp0->t_state & TS_ISOPEN) {
2900 	    (*linesw[tp0->t_line].l_rint)(chr, tp0);
2901 	} else {
2902 	    blitc(0, chr & 0xff);
2903 	}
2904 
2905 } /* qdputc */
2906 
2907 /*******************************************************************
2908 *
2909 *	qdgetc()... get a character from the LK201
2910 *
2911 *******************************************************************
2912 *
2913 *	calling convention:
2914 *
2915 *		qdgetc();
2916 *
2917 *	returns:  the character read.
2918 *
2919 ****************/
2920 
2921 qdgetc()
2922 {
2923 	register short key;
2924 	register char chr;
2925 	register struct duart *duart;
2926 
2927 	u_int status;
2928 
2929 	duart = (struct duart *) qdmap[0].duart;
2930 
2931 	/*--------------------------------------
2932 	* Get a character from the keyboard. */
2933 
2934 LOOP:
2935 	while (!((status = duart->statusA) & RCV_RDY))
2936 			;
2937 
2938 	key = duart->dataA;
2939 	key &= 0xFF;
2940 
2941 	/*--------------------------------------
2942 	* Check for various keyboard errors  */
2943 
2944 	if( key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
2945 	    key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
2946 		printf("Keyboard error, code = %x\n", key);
2947 		return(0);
2948 	}
2949 
2950 	if (key < LK_LOWEST)
2951 	    return(0);
2952 
2953 	/*---------------------------------
2954 	* See if its a state change key */
2955 
2956 	switch (key) {
2957 
2958 	    case LOCK:
2959 		q_keyboard.lock ^= 0xffff;	/* toggle */
2960 		if (q_keyboard.lock)
2961 		    led_control(LK_LED_ENABLE, LK_LED_LOCK);
2962 		else
2963 		    led_control(LK_LED_DISABLE, LK_LED_LOCK);
2964 		goto LOOP;
2965 
2966 	    case SHIFT:
2967 		q_keyboard.shift ^= 0xFFFF;
2968 		goto LOOP;
2969 
2970 	    case CNTRL:
2971 		q_keyboard.cntrl ^= 0xFFFF;
2972 		goto LOOP;
2973 
2974 	    case ALLUP:
2975 		q_keyboard.cntrl = 0;
2976 		q_keyboard.shift = 0;
2977 		goto LOOP;
2978 
2979 	    case REPEAT:
2980 		chr = q_keyboard.last;
2981 		break;
2982 
2983 	    /*-------------------------------------------------------
2984 	    * Test for cntrl characters. If set, see if the character
2985 	    * is elligible to become a control character. */
2986 
2987 	    default:
2988 
2989 		if (q_keyboard.cntrl) {
2990 		    chr = q_key[key];
2991 		    if (chr >= ' ' && chr <= '~')
2992 			chr &= 0x1F;
2993 		}
2994 		else if ( q_keyboard.lock || q_keyboard.shift )
2995 		    chr = q_shift_key[key];
2996 		else
2997 		    chr = q_key[key];
2998 		break;
2999 	}
3000 
3001 	if (chr < ' ' && chr > '~')	/* if input is non-displayable */
3002 	    return(0);			/* ..then pitch it! */
3003 
3004 	q_keyboard.last = chr;
3005 
3006 	/*-----------------------------------
3007 	* Check for special function keys */
3008 
3009 	if (chr & 0x80) 		/* pitch the function keys */
3010 	    return(0);
3011 	else
3012 	    return(chr);
3013 
3014 } /* qdgetc */
3015 
3016 /**********************************************************************
3017 *
3018 *	ldcursor()... load the mouse cursor's template RAM bitmap
3019 *
3020 *********************************************************************
3021 *
3022 *	calling convention:
3023 *
3024 *		ldcursor(unit, bitmap);
3025 *		u_int unit;
3026 *		short *bitmap;
3027 *
3028 ****************/
3029 
3030 ldcursor(unit, bitmap)
3031 u_int unit;
3032 short *bitmap;
3033 {
3034 	register struct dga *dga;
3035 	register short *temp;
3036 	register int i;
3037 
3038 	int cursor;
3039 
3040 	dga = (struct dga *) qdmap[unit].dga;
3041 	temp = (short *) qdmap[unit].template;
3042 
3043 	if (dga->csr & CURS_ENB) {	/* if the cursor is enabled.. */
3044 	    cursor = -1;		/* ..note that.. */
3045 	    dga->csr &= ~CURS_ENB;	/* ..and shut it off */
3046 	}
3047 	else {
3048 	    cursor = 0;
3049 	}
3050 
3051 	dga->csr &= ~CURS_ENB;		/* shut off the cursor */
3052 
3053 	temp += (8 * 1024) - 32;	/* cursor is 32 WORDS from the end */
3054 					/* ..of the 8k WORD template space */
3055 	for (i = 0; i < 32; ++i)
3056 	    *temp++ = *bitmap++;
3057 
3058 	if (cursor) {			/* if cursor was enabled.. */
3059 	    dga->csr |= CURS_ENB;	/* ..turn it back on */
3060 	}
3061 
3062 	return(0);
3063 
3064 } /* ldcursor */
3065 
3066 /**********************************************************************
3067 *
3068 *	ldfont()... put the console font in the QDSS off-screen memory
3069 *
3070 ***********************************************************************
3071 *
3072 *	calling convention:
3073 *
3074 *		ldfont(unit);
3075 *		u_int unit;	;QDSS unit number
3076 *
3077 ****************/
3078 
3079 ldfont(unit)
3080 u_int unit;
3081 {
3082 	register struct adder *adder;
3083 
3084 	int i;		/* scratch variables */
3085 	int j;
3086 	int k;
3087 	short packed;
3088 
3089 	adder = (struct adder *) qdmap[unit].adder;
3090 
3091 /*------------------------------------------
3092 * setup VIPER operand control registers  */
3093 
3094 	write_ID(adder, MASK_1, 0xFFFF);
3095 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
3096 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
3097 
3098 	write_ID(adder, SRC1_OCR_B,
3099 			EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY);
3100 	write_ID(adder, SRC2_OCR_B,
3101 			EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY);
3102 	write_ID(adder, DST_OCR_B,
3103 			EXT_SOURCE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
3104 
3105 	adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL;
3106 
3107 /*--------------------------
3108 * load destination data  */
3109 
3110 	wait_status(adder, RASTEROP_COMPLETE);
3111 
3112 	adder->destination_x = FONT_X;
3113 	adder->destination_y = FONT_Y;
3114 	adder->fast_dest_dx = FONT_WIDTH;
3115 	adder->slow_dest_dy = CHAR_HEIGHT;
3116 
3117 /*---------------------------------------
3118 * setup for processor to bitmap xfer  */
3119 
3120 	write_ID(adder, CS_UPDATE_MASK, 0x0001);
3121 	adder->cmd = PBT | OCRB | 2 | DTE | 2;
3122 
3123 /*-----------------------------------------------
3124 * iteratively do the processor to bitmap xfer */
3125 
3126 	for (i = 0; i < ROWS; ++i) {
3127 
3128 	    /* PTOB a scan line */
3129 
3130 	    for (j = 0, k = i; j < 48; ++j) {
3131 
3132 		/* PTOB one scan of a char cell */
3133 
3134 		packed = q_font[k];
3135 		k += ROWS;
3136 		packed |= ((short)q_font[k] << 8);
3137 		k += ROWS;
3138 
3139 		wait_status(adder, TX_READY);
3140 		adder->id_data = packed;
3141 	    }
3142 	}
3143 
3144 }  /* ldfont */
3145 
3146 /*********************************************************************
3147 *
3148 *	led_control()... twiddle LK-201 LED's
3149 *
3150 **********************************************************************
3151 *
3152 *	led_control(unit, cmd, led_mask);
3153 *	u_int unit;	QDSS number
3154 *	int cmd;	LED enable/disable command
3155 *	int led_mask;	which LED(s) to twiddle
3156 *
3157 *************/
3158 
3159 led_control(unit, cmd, led_mask)
3160 u_int unit;
3161 int cmd;
3162 int led_mask;
3163 {
3164 	register int i;
3165 	register int status;
3166 	register struct duart *duart;
3167 
3168 	duart = (struct duart *) qdmap[unit].duart;
3169 
3170 	for (i = 1000; i > 0; --i) {
3171 	    if ((status = duart->statusA) & XMT_RDY) {
3172 		duart->dataA = cmd;
3173 		break;
3174 	    }
3175 	}
3176 
3177 	for (i = 1000; i > 0; --i) {
3178 	    if ((status = duart->statusA) & XMT_RDY) {
3179 		duart->dataA = led_mask;
3180 		break;
3181 	    }
3182 	}
3183 
3184 	if (i == 0)
3185 	    return(BAD);
3186 
3187 	return(GOOD);
3188 
3189 } /* led_control */
3190 
3191 /*******************************************************************
3192 *
3193 *	scroll_up()... move the screen up one character height
3194 *
3195 ********************************************************************
3196 *
3197 *	calling convention:
3198 *
3199 *		scroll_up(adder);
3200 *		struct adder *adder;	;address of adder
3201 *
3202 ********/
3203 
3204 scroll_up(adder)
3205 register struct adder *adder;
3206 {
3207 
3208 /*------------------------------------------
3209 * setup VIPER operand control registers  */
3210 
3211 	wait_status(adder, ADDRESS_COMPLETE);
3212 
3213 	write_ID(adder, CS_UPDATE_MASK, 0x00FF);  /* select all planes */
3214 
3215 	write_ID(adder, MASK_1, 0xFFFF);
3216 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
3217 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
3218 
3219 	write_ID(adder, SRC1_OCR_B,
3220 			EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY);
3221 	write_ID(adder, DST_OCR_B,
3222 			EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
3223 
3224 /*----------------------------------------
3225 * load DESTINATION origin and vectors  */
3226 
3227 	adder->fast_dest_dy = 0;
3228 	adder->slow_dest_dx = 0;
3229 	adder->error_1 = 0;
3230 	adder->error_2 = 0;
3231 
3232 	adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL;
3233 
3234 	adder->destination_x = 0;
3235 	adder->fast_dest_dx = 1024;
3236 
3237 	adder->destination_y = 0;
3238 	adder->slow_dest_dy = 864 - CHAR_HEIGHT;
3239 
3240 /*-----------------------------------
3241 * load SOURCE origin and vectors  */
3242 
3243 	adder->source_1_x = 0;
3244 	adder->source_1_dx = 1024;
3245 
3246 	adder->source_1_y = 0 + CHAR_HEIGHT;
3247 	adder->source_1_dy = 864 - CHAR_HEIGHT;
3248 
3249 	write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
3250 	adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE;
3251 
3252 /*--------------------------------------------
3253 * do a rectangle clear of last screen line */
3254 
3255 	write_ID(adder, MASK_1, 0xffff);
3256 	write_ID(adder, SOURCE, 0xffff);
3257 	write_ID(adder,DST_OCR_B,
3258 		(EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY));
3259 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 0);
3260 	adder->error_1 = 0;
3261 	adder->error_2 = 0;
3262 	adder->slow_dest_dx = 0;	/* set up the width of	*/
3263 	adder->slow_dest_dy = CHAR_HEIGHT;	/* rectangle */
3264 
3265 	adder->rasterop_mode = (NORMAL | DST_WRITE_ENABLE) ;
3266 	wait_status(adder, RASTEROP_COMPLETE);
3267 	adder->destination_x = 0;
3268 	adder->destination_y = 864 - CHAR_HEIGHT;
3269 
3270 	adder->fast_dest_dx = 1024;	/* set up the height	*/
3271 	adder->fast_dest_dy = 0;	/* of rectangle 	*/
3272 
3273 	write_ID(adder, LU_FUNCTION_R2, (FULL_SRC_RESOLUTION | LF_SOURCE));
3274 	adder->cmd = (RASTEROP | OCRB | LF_R2 | DTE ) ;
3275 
3276 } /* scroll_up */
3277 
3278 /********************************************************************
3279 *
3280 *	init_shared()... init shared memory pointers and structures
3281 *
3282 *********************************************************************
3283 *
3284 *	calling convention:
3285 *
3286 *		init_shared(unit);
3287 *		u_int unit;
3288 *
3289 ****************/
3290 
3291 init_shared(unit)
3292 register u_int unit;
3293 {
3294 	register struct dga *dga;
3295 
3296 	dga = (struct dga *) qdmap[unit].dga;
3297 
3298 /*--------------------------------------------------
3299 * initialize the event queue pointers and header */
3300 
3301 	eq_header[unit] = (struct qdinput *)
3302 			  ((((int)event_shared & ~(0x01FF)) + 512)
3303 			   + (EVENT_BUFSIZE * unit));
3304 
3305 	eq_header[unit]->curs_pos.x = 0;
3306 	eq_header[unit]->curs_pos.y = 0;
3307 
3308 	dga->x_cursor = TRANX(eq_header[unit]->curs_pos.x);
3309 	dga->y_cursor = TRANY(eq_header[unit]->curs_pos.y);
3310 
3311 	eq_header[unit]->curs_box.left = 0;
3312 	eq_header[unit]->curs_box.right = 0;
3313 	eq_header[unit]->curs_box.top = 0;
3314 	eq_header[unit]->curs_box.bottom = 0;
3315 
3316 /*---------------------------------------------------------
3317 * assign a pointer to the DMA I/O buffer for this QDSS. */
3318 
3319 	DMAheader[unit] = (struct DMAreq_header *)
3320 			  (((int)(&DMA_shared[0] + 512) & ~0x1FF)
3321 			   + (DMAbuf_size * unit));
3322 
3323 	DMAheader[unit]->DMAreq = (struct DMAreq *) ((int)DMAheader[unit]
3324 				  + sizeof(struct DMAreq_header));
3325 
3326 	DMAheader[unit]->QBAreg = 0;
3327 	DMAheader[unit]->status = 0;
3328 	DMAheader[unit]->shared_size = DMAbuf_size;
3329 	DMAheader[unit]->used = 0;
3330 	DMAheader[unit]->size = 10;	/* default = 10 requests */
3331 	DMAheader[unit]->oldest = 0;
3332 	DMAheader[unit]->newest = 0;
3333 
3334 /*-----------------------------------------------------------
3335 * assign a pointer to the scroll structure for this QDSS. */
3336 
3337 	scroll[unit] = (struct scroll *)
3338 			 (((int)(&scroll_shared[0] + 512) & ~0x1FF)
3339 			   + (sizeof(struct scroll) * unit));
3340 
3341 	scroll[unit]->status = 0;
3342 	scroll[unit]->viper_constant = 0;
3343 	scroll[unit]->y_scroll_constant = 0;
3344 	scroll[unit]->y_offset = 0;
3345 	scroll[unit]->x_index_pending = 0;
3346 	scroll[unit]->y_index_pending = 0;
3347 
3348 /*----------------------------------------------------------------
3349 * assign a pointer to the color map write buffer for this QDSS */
3350 
3351 	color_buf[unit] = (struct color_buf *)
3352 			   (((int)(&color_shared[0] + 512) & ~0x1FF)
3353 			    + (COLOR_BUFSIZ * unit));
3354 
3355 	color_buf[unit]->status = 0;
3356 	color_buf[unit]->count = 0;
3357 
3358 } /* init_shared */
3359 
3360 /*********************************************************************
3361 *
3362 *	setup_dragon()... init the ADDER, VIPER, bitmaps, & color map
3363 *
3364 **********************************************************************
3365 *
3366 *	calling convention:
3367 *
3368 *		setup_dragon();
3369 *
3370 *	return: NONE
3371 *
3372 ************************/
3373 
3374 setup_dragon(unit)
3375 u_int unit;
3376 {
3377 
3378 	register struct adder *adder;
3379 	register struct dga *dga;
3380 	short *memcsr;
3381 
3382 	int i;			/* general purpose variables */
3383 	int status;
3384 
3385 	short top;		/* clipping/scrolling boundaries */
3386 	short bottom;
3387 	short right;
3388 	short left;
3389 
3390 	short *red;		/* color map pointers */
3391 	short *green;
3392 	short *blue;
3393 
3394 /*------------------
3395 * init for setup */
3396 
3397 	adder = (struct adder *) qdmap[unit].adder;
3398 	dga = (struct dga *) qdmap[unit].dga;
3399 	memcsr = (short *) qdmap[unit].memcsr;
3400 
3401 	dga->csr &= ~(DMA_IE | 0x700);	/* halt DMA and kill the intrpts */
3402 	*memcsr = SYNC_ON;		/* blank screen and turn off LED's */
3403 	adder->command = CANCEL;
3404 
3405 /*----------------------
3406 * set monitor timing */
3407 
3408 	adder->x_scan_count_0 = 0x2800;
3409 	adder->x_scan_count_1 = 0x1020;
3410 	adder->x_scan_count_2 = 0x003A;
3411 	adder->x_scan_count_3 = 0x38F0;
3412 	adder->x_scan_count_4 = 0x6128;
3413 	adder->x_scan_count_5 = 0x093A;
3414 	adder->x_scan_count_6 = 0x313C;
3415 	adder->sync_phase_adj = 0x0100;
3416 	adder->x_scan_conf = 0x00C8;
3417 
3418 /*---------------------------------------------------------
3419 * got a bug in secound pass ADDER! lets take care of it */
3420 
3421 	/* normally, just use the code in the following bug fix code, but to
3422 	* make repeated demos look pretty, load the registers as if there was
3423 	* no bug and then test to see if we are getting sync */
3424 
3425 	adder->y_scan_count_0 = 0x135F;
3426 	adder->y_scan_count_1 = 0x3363;
3427 	adder->y_scan_count_2 = 0x2366;
3428 	adder->y_scan_count_3 = 0x0388;
3429 
3430 	/* if no sync, do the bug fix code */
3431 
3432 	if (wait_status(adder, VSYNC) == BAD) {
3433 
3434 	    /* first load all Y scan registers with very short frame and
3435 	    * wait for scroll service.	This guarantees at least one SYNC
3436 	    * to fix the pass 2 Adder initialization bug (synchronizes
3437 	    * XCINCH with DMSEEDH) */
3438 
3439 	    adder->y_scan_count_0 = 0x01;
3440 	    adder->y_scan_count_1 = 0x01;
3441 	    adder->y_scan_count_2 = 0x01;
3442 	    adder->y_scan_count_3 = 0x01;
3443 
3444 	    wait_status(adder, VSYNC);	/* delay at least 1 full frame time */
3445 	    wait_status(adder, VSYNC);
3446 
3447 	    /* now load the REAL sync values (in reverse order just to
3448 	    *  be safe.  */
3449 
3450 	    adder->y_scan_count_3 = 0x0388;
3451 	    adder->y_scan_count_2 = 0x2366;
3452 	    adder->y_scan_count_1 = 0x3363;
3453 	    adder->y_scan_count_0 = 0x135F;
3454 	}
3455 
3456 	*memcsr = SYNC_ON | UNBLANK;	/* turn off leds and turn on video */
3457 
3458 /*----------------------------
3459 * zero the index registers */
3460 
3461 	adder->x_index_pending = 0;
3462 	adder->y_index_pending = 0;
3463 	adder->x_index_new = 0;
3464 	adder->y_index_new = 0;
3465 	adder->x_index_old = 0;
3466 	adder->y_index_old = 0;
3467 
3468 	adder->pause = 0;
3469 
3470 /*----------------------------------------
3471 * set rasterop mode to normal pen down */
3472 
3473 	adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL;
3474 
3475 /*--------------------------------------------------
3476 * set the rasterop registers to a default values */
3477 
3478 	adder->source_1_dx = 1;
3479 	adder->source_1_dy = 1;
3480 	adder->source_1_x = 0;
3481 	adder->source_1_y = 0;
3482 	adder->destination_x = 0;
3483 	adder->destination_y = 0;
3484 	adder->fast_dest_dx = 1;
3485 	adder->fast_dest_dy = 0;
3486 	adder->slow_dest_dx = 0;
3487 	adder->slow_dest_dy = 1;
3488 	adder->error_1 = 0;
3489 	adder->error_2 = 0;
3490 
3491 /*------------------------
3492 * scale factor = unity */
3493 
3494 	adder->fast_scale = UNITY;
3495 	adder->slow_scale = UNITY;
3496 
3497 /*-------------------------------
3498 * set the source 2 parameters */
3499 
3500 	adder->source_2_x = 0;
3501 	adder->source_2_y = 0;
3502 	adder->source_2_size = 0x0022;
3503 
3504 /*-----------------------------------------------
3505 * initialize plane addresses for eight vipers */
3506 
3507 	write_ID(adder, CS_UPDATE_MASK, 0x0001);
3508 	write_ID(adder, PLANE_ADDRESS, 0x0000);
3509 
3510 	write_ID(adder, CS_UPDATE_MASK, 0x0002);
3511 	write_ID(adder, PLANE_ADDRESS, 0x0001);
3512 
3513 	write_ID(adder, CS_UPDATE_MASK, 0x0004);
3514 	write_ID(adder, PLANE_ADDRESS, 0x0002);
3515 
3516 	write_ID(adder, CS_UPDATE_MASK, 0x0008);
3517 	write_ID(adder, PLANE_ADDRESS, 0x0003);
3518 
3519 	write_ID(adder, CS_UPDATE_MASK, 0x0010);
3520 	write_ID(adder, PLANE_ADDRESS, 0x0004);
3521 
3522 	write_ID(adder, CS_UPDATE_MASK, 0x0020);
3523 	write_ID(adder, PLANE_ADDRESS, 0x0005);
3524 
3525 	write_ID(adder, CS_UPDATE_MASK, 0x0040);
3526 	write_ID(adder, PLANE_ADDRESS, 0x0006);
3527 
3528 	write_ID(adder, CS_UPDATE_MASK, 0x0080);
3529 	write_ID(adder, PLANE_ADDRESS, 0x0007);
3530 
3531 	/* initialize the external registers. */
3532 
3533 	write_ID(adder, CS_UPDATE_MASK, 0x00FF);
3534 	write_ID(adder, CS_SCROLL_MASK, 0x00FF);
3535 
3536 	/* initialize resolution mode */
3537 
3538 	write_ID(adder, MEMORY_BUS_WIDTH, 0x000C);     /* bus width = 16 */
3539 	write_ID(adder, RESOLUTION_MODE, 0x0000);      /* one bit/pixel */
3540 
3541 	/* initialize viper registers */
3542 
3543 	write_ID(adder, SCROLL_CONSTANT, SCROLL_ENABLE|VIPER_LEFT|VIPER_UP);
3544 	write_ID(adder, SCROLL_FILL, 0x0000);
3545 
3546 /*----------------------------------------------------
3547 * set clipping and scrolling limits to full screen */
3548 
3549 	for ( i = 1000, adder->status = 0
3550 	    ; i > 0  &&  !((status = adder->status) & ADDRESS_COMPLETE)
3551 	    ; --i);
3552 
3553 	if (i == 0)
3554 	    mprintf("\nqd%d: setup_dragon: timeout on ADDRESS_COMPLETE",unit);
3555 
3556 	top = 0;
3557 	bottom = 2048;
3558 	left = 0;
3559 	right = 1024;
3560 
3561 	adder->x_clip_min = left;
3562 	adder->x_clip_max = right;
3563 	adder->y_clip_min = top;
3564 	adder->y_clip_max = bottom;
3565 
3566 	adder->scroll_x_min = left;
3567 	adder->scroll_x_max = right;
3568 	adder->scroll_y_min = top;
3569 	adder->scroll_y_max = bottom;
3570 
3571 	wait_status(adder, VSYNC);	/* wait at LEAST 1 full frame */
3572 	wait_status(adder, VSYNC);
3573 
3574 	adder->x_index_pending = left;
3575 	adder->y_index_pending = top;
3576 	adder->x_index_new = left;
3577 	adder->y_index_new = top;
3578 	adder->x_index_old = left;
3579 	adder->y_index_old = top;
3580 
3581 	for ( i = 1000, adder->status = 0
3582 	    ; i > 0  &&  !((status = adder->status) & ADDRESS_COMPLETE)
3583 	    ; --i);
3584 
3585 	if (i == 0)
3586 	    mprintf("\nqd%d: setup_dragon: timeout on ADDRESS_COMPLETE",unit);
3587 
3588 	write_ID(adder, LEFT_SCROLL_MASK, 0x0000);
3589 	write_ID(adder, RIGHT_SCROLL_MASK, 0x0000);
3590 
3591 /*------------------------------------------------------------
3592 * set source and the mask register to all ones (ie: white) */
3593 
3594 	write_ID(adder, SOURCE, 0xFFFF);
3595 	write_ID(adder, MASK_1, 0xFFFF);
3596 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
3597 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
3598 
3599 /*--------------------------------------------------------------
3600 * initialize Operand Control Register banks for fill command */
3601 
3602 	write_ID(adder, SRC1_OCR_A, EXT_NONE | INT_M1_M2  | NO_ID | WAIT);
3603 	write_ID(adder, SRC2_OCR_A, EXT_NONE | INT_SOURCE | NO_ID | NO_WAIT);
3604 	write_ID(adder, DST_OCR_A, EXT_NONE | INT_NONE	 | NO_ID | NO_WAIT);
3605 
3606 	write_ID(adder, SRC1_OCR_B, EXT_NONE | INT_SOURCE | NO_ID | WAIT);
3607 	write_ID(adder, SRC2_OCR_B, EXT_NONE | INT_M1_M2  | NO_ID | NO_WAIT);
3608 	write_ID(adder, DST_OCR_B, EXT_NONE | INT_NONE | NO_ID | NO_WAIT);
3609 
3610 /*------------------------------------------------------------------
3611 * init Logic Unit Function registers, (these are just common values,
3612 * and may be changed as required).  */
3613 
3614 	write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
3615 	write_ID(adder, LU_FUNCTION_R2, FULL_SRC_RESOLUTION | LF_SOURCE | INV_M1_M2);
3616 	write_ID(adder, LU_FUNCTION_R3, FULL_SRC_RESOLUTION | LF_D_OR_S);
3617 	write_ID(adder, LU_FUNCTION_R4, FULL_SRC_RESOLUTION | LF_D_XOR_S);
3618 
3619 /*----------------------------------------
3620 * load the color map for black & white */
3621 
3622 	for ( i = 0, adder->status = 0
3623 	    ; i < 10000  &&  !((status = adder->status) & VSYNC)
3624 	    ; ++i);
3625 
3626 	if (i == 0)
3627 	    mprintf("\nqd%d: setup_dragon: timeout on VSYNC", unit);
3628 
3629 	red = (short *) qdmap[unit].red;
3630 	green = (short *) qdmap[unit].green;
3631 	blue = (short *) qdmap[unit].blue;
3632 
3633 	*red++ = 0x00;			/* black */
3634 	*green++ = 0x00;
3635 	*blue++ = 0x00;
3636 
3637 	*red-- = 0xFF;			/* white */
3638 	*green-- = 0xFF;
3639 	*blue-- = 0xFF;
3640 
3641 	/*----------------------------------
3642 	* set color map for mouse cursor */
3643 
3644 	red += 254;
3645 	green += 254;
3646 	blue += 254;
3647 
3648 	*red++ = 0x00;			/* black */
3649 	*green++ = 0x00;
3650 	*blue++ = 0x00;
3651 
3652 	*red = 0xFF;			/* white */
3653 	*green = 0xFF;
3654 	*blue = 0xFF;
3655 
3656 	return(0);
3657 
3658 } /* setup_dragon */
3659 
3660 /******************************************************************
3661 *
3662 *	setup_input()... init the DUART and set defaults in input
3663 *			 devices
3664 *
3665 *******************************************************************
3666 *
3667 *	calling convention:
3668 *
3669 *		setup_input(unit);
3670 *
3671 *	where: unit - is the QDSS unit number to be setup
3672 *
3673 *********/
3674 
3675 setup_input(unit)
3676 u_int unit;
3677 {
3678 	register struct duart *duart;	/* DUART register structure pointer */
3679 	register int i; 		/* scratch variable */
3680 	register int bits;
3681 
3682 	char id_byte;
3683 	short status;
3684 
3685 /*---------------
3686 * init stuff */
3687 
3688 	duart = (struct duart *) qdmap[unit].duart;
3689 	duart->imask = 0;
3690 
3691 /*---------------------------------------------
3692 * setup the DUART for kbd & pointing device */
3693 
3694 	duart->cmdA = RESET_M;	  /* reset mode reg ptr for kbd */
3695 	duart->modeA = 0x13;	  /* 8 bits, no parity, rcv IE, */
3696 				  /* no RTS control,char error mode */
3697 	duart->modeA = 0x07;	  /* 1 stop bit,CTS does not IE XMT */
3698 				  /* no RTS control,no echo or loop */
3699 	duart->cmdB = RESET_M;	  /* reset mode reg pntr for host */
3700 	duart->modeB = 0x07;	  /* 8 bits, odd parity, rcv IE.. */
3701 				  /* ..no RTS cntrl, char error mode */
3702 	duart->modeB = 0x07;	  /* 1 stop bit,CTS does not IE XMT */
3703 				  /* no RTS control,no echo or loop */
3704 
3705 	duart->auxctl = 0x00;	  /* baud rate set 1 */
3706 
3707 	duart->clkselA = 0x99;	  /* 4800 baud for kbd */
3708 	duart->clkselB = 0x99;	  /* 4800 baud for mouse */
3709 
3710 	/* reset everything for keyboard */
3711 
3712 	for (bits = RESET_M; bits < START_BREAK; bits += 0x10)
3713 	    duart->cmdA = bits;
3714 
3715 	/* reset everything for host */
3716 
3717 	for (bits = RESET_M; bits < START_BREAK; bits += 0x10)
3718 	     duart->cmdB = bits;
3719 
3720 	duart->cmdA = EN_RCV | EN_XMT; /* enbl xmt & rcv for kbd */
3721 	duart->cmdB = EN_RCV | EN_XMT; /* enbl xmt & rcv for pointer device */
3722 
3723 /*--------------------------------------------
3724 * init keyboard defaults (DUART channel A) */
3725 
3726 	for (i = 500; i > 0; --i) {
3727 	    if ((status = duart->statusA) & XMT_RDY) {
3728 		duart->dataA = LK_DEFAULTS;
3729 		break;
3730 	    }
3731 	}
3732 
3733 	for (i = 100000; i > 0; --i) {
3734 	    if ((status = duart->statusA) & RCV_RDY) {
3735 		break;
3736 	    }
3737 	}
3738 
3739 	status = duart->dataA;		/* flush the ACK */
3740 
3741 /*--------------------------------
3742 * identify the pointing device */
3743 
3744 	for (i = 500; i > 0; --i) {
3745 	    if ((status = duart->statusB) & XMT_RDY) {
3746 		duart->dataB = SELF_TEST;
3747 		break;
3748 	    }
3749 	}
3750 
3751 	/*-----------------------------------------
3752 	* wait for 1st byte of self test report */
3753 
3754 	for (i = 100000; i > 0; --i) {
3755 	    if ((status = duart->statusB) & RCV_RDY) {
3756 		break;
3757 	    }
3758 	}
3759 
3760 	if (i == 0) {
3761 	    mprintf("\nqd[%d]: setup_input: timeout on 1st byte of self test",unit);
3762 	    goto OUT;
3763 	}
3764 
3765 	status = duart->dataB;
3766 
3767 	/*-----------------------------------------
3768 	* wait for ID byte of self test report	*/
3769 
3770 	for (i = 100000; i > 0; --i) {
3771 	    if ((status = duart->statusB) & RCV_RDY) {
3772 		break;
3773 	    }
3774 	}
3775 
3776 	if (i == 0) {
3777 	    mprintf("\nqd[%d]: setup_input: timeout on 2nd byte of self test", unit);
3778 	    goto OUT;
3779 	}
3780 
3781 	id_byte = duart->dataB;
3782 
3783 	/*------------------------------------
3784 	* wait for other bytes to come in  */
3785 
3786 	for (i = 100000; i > 0; --i) {
3787 	    if ((status = duart->statusB) & RCV_RDY) {
3788 		status = duart->dataB;
3789 		break;
3790 	    }
3791 	}
3792 
3793 	if (i == 0) {
3794 	    mprintf("\nqd[%d]: setup_input: timeout on 3rd byte of self test", unit);
3795 	    goto OUT;
3796 	}
3797 
3798 	for (i = 100000; i > 0; --i) {
3799 	    if ((status = duart->statusB) & RCV_RDY) {
3800 		status = duart->dataB;
3801 		break;
3802 	    }
3803 	}
3804 
3805 	if (i == 0) {
3806 	    mprintf("\nqd[%d]: setup_input: timeout on 4th byte of self test\n", unit);
3807 	    goto OUT;
3808 	}
3809 
3810 	/*----------------------------------------------
3811 	* flag pointing device type and set defaults */
3812 
3813 	for (i=100000; i>0; --i);
3814 
3815 	if ((id_byte & 0x0F) != TABLET_ID) {
3816 
3817 	    qdflags[unit].pntr_id = MOUSE_ID;
3818 
3819 	    for (i = 500; i > 0; --i) {
3820 		if ((status = duart->statusB) & XMT_RDY) {
3821 		    duart->dataB = INC_STREAM_MODE;
3822 		    break;
3823 		}
3824 	    }
3825 	} else {
3826 
3827 	    qdflags[unit].pntr_id = TABLET_ID;
3828 
3829 	    for (i = 500; i > 0; --i) {
3830 		if ((status = duart->statusB) & XMT_RDY) {
3831 		    duart->dataB = T_STREAM;
3832 		    break;
3833 		}
3834 	    }
3835 	}
3836 
3837 /*--------
3838 * exit */
3839 
3840 OUT:
3841 	duart->imask = qdflags[unit].duart_imask;
3842 	return(0);
3843 
3844 } /* setup_input */
3845 
3846 /**********************************************************************
3847 *
3848 *	wait_status()... delay for at least one display frame time
3849 *
3850 ***********************************************************************
3851 *
3852 *	calling convention:
3853 *
3854 *		wait_status(adder, mask);
3855 *		struct *adder adder;
3856 *		int mask;
3857 *
3858 *	return: BAD means that we timed out without ever seeing the
3859 *		      vertical sync status bit
3860 *		GOOD otherwise
3861 *
3862 **************/
3863 
3864 wait_status(adder, mask)
3865 register struct adder *adder;
3866 register int mask;
3867 {
3868 	register short status;
3869 	int i;
3870 
3871 	for ( i = 10000, adder->status = 0
3872 	    ; i > 0  &&  !((status = adder->status) & mask)
3873 	    ; --i);
3874 
3875 	if (i == 0) {
3876 	    mprintf("\nwait_status: timeout polling for 0x%x in adder->status", mask);
3877 	    return(BAD);
3878 	}
3879 
3880 	return(GOOD);
3881 
3882 } /* wait_status */
3883 
3884 /**********************************************************************
3885 *
3886 *	write_ID()... write out onto the ID bus
3887 *
3888 ***********************************************************************
3889 *
3890 *	calling convention:
3891 *
3892 *		struct *adder adder;	;pntr to ADDER structure
3893 *		short adrs;		;VIPER address
3894 *		short data;		;data to be written
3895 *		write_ID(adder);
3896 *
3897 *	return: BAD means that we timed out waiting for status bits
3898 *		      VIPER-access-specific status bits
3899 *		GOOD otherwise
3900 *
3901 **************/
3902 
3903 write_ID(adder, adrs, data)
3904 register struct adder *adder;
3905 register short adrs;
3906 register short data;
3907 {
3908 	int i;
3909 	short status;
3910 
3911 	for ( i = 100000, adder->status = 0
3912 	    ; i > 0  &&  !((status = adder->status) & ADDRESS_COMPLETE)
3913 	    ; --i);
3914 
3915 	if (i == 0)
3916 	    goto ERR;
3917 
3918 	for ( i = 100000, adder->status = 0
3919 	    ; i > 0  &&  !((status = adder->status) & TX_READY)
3920 	    ; --i);
3921 
3922 	if (i > 0) {
3923 	    adder->id_data = data;
3924 	    adder->command = ID_LOAD | adrs;
3925 	    return(GOOD);
3926 	}
3927 
3928 ERR:
3929 	mprintf("\nwrite_ID: timeout trying to write to VIPER");
3930 	return(BAD);
3931 
3932 } /* write_ID */
3933