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