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