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