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