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