xref: /original-bsd/sys/vax/uba/qd.c (revision 61ab9802)
1006e9885Smarc /*
2537afb73Sbostic  * Copyright (c) 1988 Regents of the University of California.
3537afb73Sbostic  * All rights reserved.
4006e9885Smarc  *
59c395af7Sbostic  * %sccs.include.redist.c%
6006e9885Smarc  *
7*61ab9802Skarels  *	@(#)qd.c	7.1 (Berkeley) 06/28/91
8006e9885Smarc  */
9b2b69f49Smarc 
107e911b15Skarels /************************************************************************
117e911b15Skarels *									*
12e977faadSmarc *			Copyright (c) 1985-1988 by			*
137e911b15Skarels *		Digital Equipment Corporation, Maynard, MA		*
147e911b15Skarels *			All rights reserved.				*
157e911b15Skarels *									*
167e911b15Skarels *   This software is furnished under a license and may be used and	*
177e911b15Skarels *   copied  only  in accordance with the terms of such license and	*
187e911b15Skarels *   with the  inclusion  of  the  above  copyright  notice.   This	*
197e911b15Skarels *   software  or  any  other copies thereof may not be provided or	*
207e911b15Skarels *   otherwise made available to any other person.  No title to and	*
217e911b15Skarels *   ownership of the software is hereby transferred.			*
227e911b15Skarels *									*
237e911b15Skarels *   The information in this software is subject to change  without	*
247e911b15Skarels *   notice  and should not be construed as a commitment by Digital	*
257e911b15Skarels *   Equipment Corporation.						*
267e911b15Skarels *									*
277e911b15Skarels *   Digital assumes no responsibility for the use  or  reliability	*
287e911b15Skarels *   of its software on equipment which is not supplied by Digital.	*
297e911b15Skarels *									*
307e911b15Skarels *************************************************************************/
31e977faadSmarc 
327e911b15Skarels /*
33b2b69f49Smarc  * qd.c - QDSS display driver for VAXSTATION-II GPX workstation
347e911b15Skarels  */
357e911b15Skarels 
36b2b69f49Smarc #include "qd.h"
37e977faadSmarc 
38006e9885Smarc #if NQD > 0
3939bdaf89Sbostic #include "../include/pte.h"
4039bdaf89Sbostic #include "../include/mtpr.h"
4139bdaf89Sbostic #include "sys/param.h"
4239bdaf89Sbostic #include "../include/cpu.h"
4339bdaf89Sbostic #include "sys/conf.h"
4439bdaf89Sbostic #include "sys/user.h"
45b2b69f49Smarc #include "qdioctl.h"
4639bdaf89Sbostic #include "sys/tty.h"
4739bdaf89Sbostic #include "sys/map.h"
4839bdaf89Sbostic #include "sys/buf.h"
4939bdaf89Sbostic #include "sys/vm.h"
5039bdaf89Sbostic #include "sys/clist.h"
5139bdaf89Sbostic #include "sys/file.h"
5239bdaf89Sbostic #include "sys/uio.h"
5339bdaf89Sbostic #include "sys/kernel.h"
5439bdaf89Sbostic #include "sys/exec.h"
5539bdaf89Sbostic #include "sys/proc.h"
56b2b69f49Smarc #include "ubareg.h"
57b2b69f49Smarc #include "ubavar.h"
5839bdaf89Sbostic #include "sys/syslog.h"
59b2b69f49Smarc #include "qduser.h"	/* definitions shared with user level client */
60e977faadSmarc #include "qdreg.h"	/* QDSS device register structures */
6124f67f6bSmarc 
62b2b69f49Smarc /*
63b2b69f49Smarc  * QDSS driver status flags for tracking operational state
64b2b69f49Smarc  */
6524f67f6bSmarc struct qdflags {
6624f67f6bSmarc 	u_int inuse;		/* which minor dev's are in use now */
6724f67f6bSmarc 	u_int config;		/* I/O page register content */
6824f67f6bSmarc 	u_int mapped;		/* user mapping status word */
69e977faadSmarc 	u_int kernel_loop;	/* if kernel console is redirected */
7024f67f6bSmarc 	u_int user_dma;		/* DMA from user space in progress */
7124f67f6bSmarc 	u_short pntr_id;	/* type code of pointing device */
7224f67f6bSmarc 	u_short duart_imask;	/* shadowing for duart intrpt mask reg */
7324f67f6bSmarc 	u_short adder_ie;	/* shadowing for adder intrpt enbl reg */
7424f67f6bSmarc 	u_short curs_acc;	/* cursor acceleration factor */
7524f67f6bSmarc 	u_short curs_thr;	/* cursor acceleration threshold level */
7624f67f6bSmarc 	u_short tab_res;	/* tablet resolution factor */
7724f67f6bSmarc 	u_short selmask;	/* mask for active qd select entries */
7824f67f6bSmarc };
7924f67f6bSmarc 
80b2b69f49Smarc /*
81b2b69f49Smarc  * bit definitions for 'inuse' entry
82b2b69f49Smarc  */
8324f67f6bSmarc #define CONS_DEV	0x01
8424f67f6bSmarc #define GRAPHIC_DEV	0x04
8524f67f6bSmarc 
86b2b69f49Smarc /*
87b2b69f49Smarc  * bit definitions for 'mapped' member of flag structure
88b2b69f49Smarc  */
8924f67f6bSmarc #define MAPDEV		0x01		/* hardware is mapped */
9024f67f6bSmarc #define MAPDMA		0x02		/* DMA buffer mapped */
9124f67f6bSmarc #define MAPEQ		0x04		/* event queue buffer mapped */
9224f67f6bSmarc #define MAPSCR		0x08		/* scroll param area mapped */
9324f67f6bSmarc #define MAPCOLOR	0x10		/* color map writing buffer mapped */
9424f67f6bSmarc 
95b2b69f49Smarc /*
96b2b69f49Smarc  * bit definitions for 'selmask' member of qdflag structure
97b2b69f49Smarc  */
9824f67f6bSmarc #define SEL_READ	0x01		/* read select is active */
9924f67f6bSmarc #define SEL_WRITE	0x02		/* write select is active */
10024f67f6bSmarc 
101b2b69f49Smarc /*
102b2b69f49Smarc  * constants used in shared memory operations
103b2b69f49Smarc  */
10424f67f6bSmarc #define EVENT_BUFSIZE  1024	/* # of bytes per device's event buffer */
10524f67f6bSmarc #define MAXEVENTS  ( (EVENT_BUFSIZE - sizeof(struct qdinput))	 \
10624f67f6bSmarc 	/ sizeof(struct _vs_event) )
1070d59d4d6Smarc #define DMA_BUFSIZ	(1024 * 10)
10824f67f6bSmarc #define COLOR_BUFSIZ  ((sizeof(struct color_buf) + 512) & ~0x01FF)
10924f67f6bSmarc 
110b2b69f49Smarc /*
11124f67f6bSmarc  * reference to an array of "uba_device" structures built by the auto
11224f67f6bSmarc  * configuration program.  The uba_device structure decribes the device
11324f67f6bSmarc  * sufficiently for the driver to talk to it.  The auto configuration code
11424f67f6bSmarc  * fills in the uba_device structures (located in ioconf.c) from user
115b2b69f49Smarc  * maintained info.
116b2b69f49Smarc  */
11724f67f6bSmarc struct uba_device *qdinfo[NQD];  /* array of pntrs to each QDSS's */
11824f67f6bSmarc struct tty qd_tty[NQD*4];	/* teletype structures for each.. */
1197881ece5Smarc extern char qvmem[][128*NBPG];
120b2b69f49Smarc extern struct pte QVmap[][128];
121b2b69f49Smarc #define CHUNK	  (64 * 1024)
122b2b69f49Smarc #define QMEMSIZE  (1024 * 1024 * 4)	/* 4 meg */
12324f67f6bSmarc 
124b2b69f49Smarc /*
125b2b69f49Smarc  * static storage used by multiple functions in this code
126b2b69f49Smarc  */
12724f67f6bSmarc int Qbus_unmap[NQD];		/* Qbus mapper release code */
12824f67f6bSmarc struct qdflags qdflags[NQD];	/* QDSS device status flags */
12924f67f6bSmarc struct qdmap qdmap[NQD];	/* QDSS register map structure */
13024f67f6bSmarc caddr_t qdbase[NQD];		/* base address of each QDSS unit */
13124f67f6bSmarc struct buf qdbuf[NQD];		/* buf structs used by strategy */
132b2b69f49Smarc short qdopened[NQD];		/* graphics device is open exclusive use */
13324f67f6bSmarc 
134b2b69f49Smarc /*
135e977faadSmarc  * the array "event_shared[]" is made up of a number of event queue buffers
13624f67f6bSmarc  * equal to the number of QDSS's configured into the running kernel (NQD).
13724f67f6bSmarc  * Each event queue buffer begins with an event queue header (struct qdinput)
13824f67f6bSmarc  * followed by a group of event queue entries (struct _vs_event).  The array
13924f67f6bSmarc  * "*eq_header[]" is an array of pointers to the start of each event queue
140b2b69f49Smarc  * buffer in "event_shared[]".
141b2b69f49Smarc  */
14224f67f6bSmarc #define EQSIZE ((EVENT_BUFSIZE * NQD) + 512)
14324f67f6bSmarc 
14424f67f6bSmarc char event_shared[EQSIZE];	    /* reserve space for event bufs */
14524f67f6bSmarc struct qdinput *eq_header[NQD];     /* event queue header pntrs */
14624f67f6bSmarc 
147b2b69f49Smarc /*
14824f67f6bSmarc  * This allocation method reserves enough memory pages for NQD shared DMA I/O
14924f67f6bSmarc  * buffers.  Each buffer must consume an integral number of memory pages to
15024f67f6bSmarc  * guarantee that a following buffer will begin on a page boundary.  Also,
15124f67f6bSmarc  * enough space is allocated so that the FIRST I/O buffer can start at the
15224f67f6bSmarc  * 1st page boundary after "&DMA_shared".  Page boundaries are used so that
153b2b69f49Smarc  * memory protections can be turned on/off for individual buffers.
154b2b69f49Smarc  */
15524f67f6bSmarc #define IOBUFSIZE  ((DMA_BUFSIZ * NQD) + 512)
15624f67f6bSmarc 
15724f67f6bSmarc char DMA_shared[IOBUFSIZE];	    /* reserve I/O buffer space */
15824f67f6bSmarc struct DMAreq_header *DMAheader[NQD];  /* DMA buffer header pntrs */
15924f67f6bSmarc 
160b2b69f49Smarc /*
16124f67f6bSmarc  * The driver assists a client in scroll operations by loading dragon
16224f67f6bSmarc  * registers from an interrupt service routine.	The loading is done using
16324f67f6bSmarc  * parameters found in memory shrade between the driver and it's client.
16424f67f6bSmarc  * The scroll parameter structures are ALL loacted in the same memory page
165b2b69f49Smarc  * for reasons of memory economy.
166b2b69f49Smarc  */
16724f67f6bSmarc char scroll_shared[2 * 512];	/* reserve space for scroll structs */
16824f67f6bSmarc struct scroll *scroll[NQD];	/* pointers to scroll structures */
16924f67f6bSmarc 
170b2b69f49Smarc /*
17124f67f6bSmarc  * the driver is programmable to provide the user with color map write
17224f67f6bSmarc  * services at VSYNC interrupt time.  At interrupt time the driver loads
173b2b69f49Smarc  * the color map with any user-requested load data found in shared memory
174b2b69f49Smarc  */
17524f67f6bSmarc #define COLOR_SHARED  ((COLOR_BUFSIZ * NQD) + 512)
17624f67f6bSmarc 
177e977faadSmarc char color_shared[COLOR_SHARED];      /* reserve space: color bufs */
17824f67f6bSmarc struct color_buf *color_buf[NQD];     /* pointers to color bufs */
17924f67f6bSmarc 
180b2b69f49Smarc /*
181b2b69f49Smarc  * mouse input event structures
182b2b69f49Smarc  */
18324f67f6bSmarc struct mouse_report last_rep[NQD];
18424f67f6bSmarc struct mouse_report current_rep[NQD];
18524f67f6bSmarc 
1867881ece5Smarc struct proc *qdrsel[NQD]; 	/* process waiting for select */
187b2b69f49Smarc struct _vs_cursor cursor[NQD];	/* console cursor */
188b2b69f49Smarc int qdcount = 0;		/* count of successfully probed qd's */
18924f67f6bSmarc int nNQD = NQD;
19024f67f6bSmarc int DMAbuf_size = DMA_BUFSIZ;
191e977faadSmarc int QDlast_DMAtype;             /* type of the last DMA operation */
192e977faadSmarc 
193b2b69f49Smarc #define QDSSMAJOR	41	/* QDSS major device number */
194b2b69f49Smarc /*
195b2b69f49Smarc  * macro to get system time.  Used to time stamp event queue entries
196b2b69f49Smarc  */
1977e911b15Skarels #define TOY ((time.tv_sec * 100) + (time.tv_usec / 10000))
1987e911b15Skarels 
1997e911b15Skarels int qdprobe();
2007e911b15Skarels int qdattach();
2017e911b15Skarels int qddint();			/* DMA gate array intrpt service */
2027e911b15Skarels int qdaint();			/* Dragon ADDER intrpt service */
2037e911b15Skarels int qdiint();
2047e911b15Skarels 
2057e911b15Skarels u_short qdstd[] = { 0 };
2067e911b15Skarels 
207b2b69f49Smarc struct uba_driver qddriver = {
2087e911b15Skarels 	qdprobe,		/* device probe entry */
2097e911b15Skarels 	0,			/* no slave device */
2107e911b15Skarels 	qdattach,		/* device attach entry */
2117e911b15Skarels 	0,			/* no "fill csr/ba to start" */
2127e911b15Skarels 	qdstd,			/* device addresses */
2137e911b15Skarels 	"qd",			/* device name string */
2147e911b15Skarels 	qdinfo			/* ptr to QDSS's uba_device struct */
2157e911b15Skarels };
2167e911b15Skarels 
217e977faadSmarc #define QDPRIOR (PZERO-1)		/* must be negative */
2187e911b15Skarels #define FALSE	0
2197e911b15Skarels #define TRUE	~FALSE
2207e911b15Skarels #define BAD	-1
2217e911b15Skarels #define GOOD	0
2227e911b15Skarels 
223b2b69f49Smarc /*
224b2b69f49Smarc  * macro to create a system virtual page number from system virtual adrs
225b2b69f49Smarc  */
226b2b69f49Smarc #define VTOP(x)  (((int)x & ~0xC0000000) >> PGSHIFT)
2277e911b15Skarels 
228b2b69f49Smarc /*
229b2b69f49Smarc  * QDSS register address offsets from start of QDSS address space
230b2b69f49Smarc  */
2317e911b15Skarels #define QDSIZE	 (52 * 1024)	/* size of entire QDSS foot print */
2327e911b15Skarels #define TMPSIZE  (16 * 1024)	/* template RAM is 8k SHORT WORDS */
2337e911b15Skarels #define TMPSTART 0x8000 	/* offset of template RAM from base adrs */
2347e911b15Skarels #define REGSIZE  (5 * 512)	/* regs touch 2.5k (5 pages) of addr space */
2357e911b15Skarels #define REGSTART 0xC000 	/* offset of reg pages from base adrs */
2367e911b15Skarels #define ADDER	(REGSTART+0x000)
2377e911b15Skarels #define DGA	(REGSTART+0x200)
2387e911b15Skarels #define DUART	(REGSTART+0x400)
2397e911b15Skarels #define MEMCSR	(REGSTART+0x800)
2407e911b15Skarels #define CLRSIZE  (3 * 512)		/* color map size */
2417e911b15Skarels #define CLRSTART (REGSTART+0xA00)	/* color map start offset from base */
2427e911b15Skarels /*  0x0C00 really */
2437e911b15Skarels #define RED	(CLRSTART+0x000)
2447e911b15Skarels #define BLUE	(CLRSTART+0x200)
2457e911b15Skarels #define GREEN	(CLRSTART+0x400)
2467e911b15Skarels 
2477e911b15Skarels 
248b2b69f49Smarc /*
2497e911b15Skarels  * QDSS minor device numbers.  The *real* minor device numbers are in
2507e911b15Skarels  * the bottom two bits of the major/minor device spec.  Bits 2 and up are
251b2b69f49Smarc  * used to specify the QDSS device number (ie: which one?)
252b2b69f49Smarc  */
2537e911b15Skarels 
2547e911b15Skarels #define CONS		0
2557e911b15Skarels #define GRAPHIC 	2
2567e911b15Skarels 
257b2b69f49Smarc /*
258b2b69f49Smarc  * console cursor bitmap (white block cursor)
259b2b69f49Smarc  */
260b2b69f49Smarc short cons_cursor[32] = {
2617e911b15Skarels 	/* A */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
2627e911b15Skarels 	0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
2637e911b15Skarels 	/* B */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
2647e911b15Skarels 	0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF
2657e911b15Skarels };
2667e911b15Skarels 
267b2b69f49Smarc /*
268b2b69f49Smarc  * constants used in font operations
269b2b69f49Smarc  */
270e977faadSmarc #define CHARS		190 			/* # of chars in the font */
2717e911b15Skarels #define CHAR_HEIGHT	15			/* char height in pixels */
2727e911b15Skarels #define CHAR_WIDTH	8			/* char width in pixels*/
2737e911b15Skarels #define FONT_WIDTH	(CHAR_WIDTH * CHARS)	/* font width in pixels */
2747e911b15Skarels #define ROWS		CHAR_HEIGHT
2757e911b15Skarels #define FONT_X		0			/* font's off screen adrs */
2767e911b15Skarels #define FONT_Y		(2048 - CHAR_HEIGHT)
277e977faadSmarc 
278b2b69f49Smarc /* Offset to second row characters (XXX - should remove) */
279e977faadSmarc #define FONT_OFFSET	((MAX_SCREEN_X/CHAR_WIDTH)*CHAR_HEIGHT)
2807e911b15Skarels 
2817e911b15Skarels extern char q_font[];		/* reference font object code */
282e977faadSmarc extern	u_short q_key[];	/* reference key xlation tables */
283e977faadSmarc extern	u_short q_shift_key[];
2847e911b15Skarels extern	char *q_special[];
2857e911b15Skarels 
286b2b69f49Smarc /*
287b2b69f49Smarc  * definitions for cursor acceleration reporting
288b2b69f49Smarc  */
2897e911b15Skarels #define ACC_OFF 	0x01		/* acceleration is inactive */
2907e911b15Skarels 
291b2b69f49Smarc /*
292b2b69f49Smarc  * virtual console support.
2937e911b15Skarels  */
294e977faadSmarc extern (*v_putc)();
295f79d7b48Smarc #ifdef KADB
296f79d7b48Smarc extern (*v_getc)();
297f79d7b48Smarc extern (*v_poll)();
298f79d7b48Smarc #endif
299e977faadSmarc extern struct cdevsw *consops;
300e977faadSmarc int qdputc();
301f79d7b48Smarc int qdgetc();
302f79d7b48Smarc int qdpoll();
303e977faadSmarc int qdstart();
304f79d7b48Smarc int qdpolling = 0;
305e977faadSmarc 
306b2b69f49Smarc /*
307b2b69f49Smarc  * LK-201 state storage for input console keyboard conversion to ASCII
308b2b69f49Smarc  */
3097e911b15Skarels struct q_keyboard {
3107e911b15Skarels 	int shift;			/* state variables	*/
3117e911b15Skarels 	int cntrl;
3127e911b15Skarels 	int lock;
3137e911b15Skarels 	int lastcode;			/* last keycode typed	*/
3147e911b15Skarels 	unsigned kup[8];		/* bits for each keycode*/
3157e911b15Skarels 	unsigned dkeys[8];		/* down/up mode keys	*/
3167e911b15Skarels 	char last;			/* last character	*/
3177e911b15Skarels } q_keyboard;
3187e911b15Skarels 
319b2b69f49Smarc /*
320b2b69f49Smarc  * tty settings on first open
321b2b69f49Smarc  */
322f79d7b48Smarc #define IFLAG (BRKINT|ISTRIP|IXON|IXANY|ICRNL|IMAXBEL)
323e977faadSmarc #define OFLAG (OPOST|OXTABS|ONLCR)
324f79d7b48Smarc #define LFLAG (ISIG|ICANON|ECHO|IEXTEN)
325e977faadSmarc #define CFLAG (PARENB|CREAD|CS7|CLOCAL)
326e977faadSmarc 
3277881ece5Smarc /*
3287881ece5Smarc  * Init QDSS as console (before probe routine)
3297881ece5Smarc  */
3307e911b15Skarels 
qdcons_init()3317e911b15Skarels qdcons_init()
3327e911b15Skarels {
3337881ece5Smarc 	register unit;
3347e911b15Skarels 	caddr_t phys_adr;		/* physical QDSS base adrs */
335e977faadSmarc 	u_int mapix;			/* index into QVmap[] array */
336e977faadSmarc 	struct percpu *pcpu;		/* pointer to cpusw structure  */
337e977faadSmarc 	register struct qbus *qb;
3387e911b15Skarels 	u_short *qdaddr;		/* address of QDSS IO page CSR */
3397e911b15Skarels 	u_short *devptr;		/* vitual device space */
340e977faadSmarc 	extern cnputc();
3417e911b15Skarels 
3427e911b15Skarels #define QDSSCSR 0x1F00
3437e911b15Skarels 
34424f67f6bSmarc 	if (v_putc != cnputc)
3457881ece5Smarc 	    return 0;
34624f67f6bSmarc 
3477e911b15Skarels 	unit = 0;
3487e911b15Skarels 
349b2b69f49Smarc 	/*
350b2b69f49Smarc 	 * find the cpusw entry that matches this machine.
351b2b69f49Smarc 	 */
35224f67f6bSmarc 	for (pcpu = percpu; pcpu && pcpu->pc_cputype != cpu; pcpu++)
3537e911b15Skarels 		;
35424f67f6bSmarc 	if (pcpu == NULL)
3557881ece5Smarc 	    return 0;
3562b86b1e4Stef 	if (pcpu->pc_io->io_type != IO_QBUS)
3572b86b1e4Stef 	    return 0;
35824f67f6bSmarc 
35924f67f6bSmarc 	/*
360e977faadSmarc 	 * Map device registers - the last 8K of qvmem.
36124f67f6bSmarc 	 */
36224f67f6bSmarc 	qb = (struct qbus *)pcpu->pc_io->io_details;
36324f67f6bSmarc 	ioaccess(qb->qb_iopage, UMEMmap[0] + qb->qb_memsize,
36424f67f6bSmarc 		 UBAIOPAGES * NBPG);
36524f67f6bSmarc 	devptr = (u_short *)((char *)umem[0]+(qb->qb_memsize * NBPG));
36624f67f6bSmarc 	qdaddr = (u_short *)((u_int)devptr + ubdevreg(QDSSCSR));
3677881ece5Smarc 	if (badaddr((caddr_t)qdaddr, sizeof(short)))
3687881ece5Smarc 		return 0;
369e977faadSmarc 
37024f67f6bSmarc 	/*
37124f67f6bSmarc 	 * Map q-bus memory used by qdss. (separate map)
37224f67f6bSmarc 	 */
37324f67f6bSmarc 	mapix = QMEMSIZE - (CHUNK * (unit + 1));
37424f67f6bSmarc 	phys_adr = qb->qb_maddr + mapix;
37524f67f6bSmarc 	ioaccess(phys_adr, QVmap[0], (CHUNK*NQD));
3767e911b15Skarels 
37724f67f6bSmarc 	/*
37824f67f6bSmarc 	 * tell QDSS which Q memory address base to decode
379b2b69f49Smarc 	 * (shifted right 16 bits - its in 64K units)
38024f67f6bSmarc 	 */
38124f67f6bSmarc 	*qdaddr = (u_short)((int)mapix >> 16);
3827e911b15Skarels 	qdflags[unit].config = *(u_short *)qdaddr;
3837e911b15Skarels 
384b2b69f49Smarc 	/*
385b2b69f49Smarc 	 * load qdmap struct with the virtual addresses of the QDSS elements
386b2b69f49Smarc 	 */
387e977faadSmarc 	qdbase[unit] = (caddr_t) (qvmem[0]);
3887e911b15Skarels 	qdmap[unit].template = qdbase[unit] + TMPSTART;
3897e911b15Skarels 	qdmap[unit].adder = qdbase[unit] + ADDER;
3907e911b15Skarels 	qdmap[unit].dga = qdbase[unit] + DGA;
3917e911b15Skarels 	qdmap[unit].duart = qdbase[unit] + DUART;
3927e911b15Skarels 	qdmap[unit].memcsr = qdbase[unit] + MEMCSR;
3937e911b15Skarels 	qdmap[unit].red = qdbase[unit] + RED;
3947e911b15Skarels 	qdmap[unit].blue = qdbase[unit] + BLUE;
3957e911b15Skarels 	qdmap[unit].green = qdbase[unit] + GREEN;
3967e911b15Skarels 
3977e911b15Skarels 	qdflags[unit].duart_imask = 0;	/* init shadow variables */
3987e911b15Skarels 
399b2b69f49Smarc 	/*
400b2b69f49Smarc 	 * init the QDSS
401b2b69f49Smarc 	 */
402b2b69f49Smarc 	/*
40324f67f6bSmarc 	printf("qdbase[0] = %x, qdmap[0].memcsr = %x\n",
40424f67f6bSmarc 		(char *)qdbase[0], qdmap[0].memcsr);
405b2b69f49Smarc 	*/
4067e911b15Skarels 
4077e911b15Skarels 	*(short *)qdmap[unit].memcsr |= SYNC_ON; /* once only: turn on sync */
4087e911b15Skarels 
4097e911b15Skarels 	cursor[unit].x = 0;
4107e911b15Skarels 	cursor[unit].y = 0;
4117e911b15Skarels 	init_shared(unit);		/* init shared memory */
4127e911b15Skarels 	setup_dragon(unit);		/* init the ADDER/VIPER stuff */
4137e911b15Skarels 	clear_qd_screen(unit);		/* clear the screen */
4147e911b15Skarels 	ldfont(unit);			/* load the console font */
4157e911b15Skarels 	ldcursor(unit, cons_cursor);	/* load default cursor map */
4167e911b15Skarels 	setup_input(unit);		/* init the DUART */
417b2b69f49Smarc 	v_putc = qdputc;		/* kernel console output to qdss */
418f79d7b48Smarc #ifdef KADB
419f79d7b48Smarc 	v_getc = qdgetc;		/* kernel console input from qdss */
420f79d7b48Smarc 	v_poll = qdpoll;		/* kdb hook to disable char intr */
421f79d7b48Smarc #endif
422b2b69f49Smarc 	consops = &cdevsw[QDSSMAJOR];	/* virtual console is qdss */
4237881ece5Smarc 	return 1;
4247e911b15Skarels 
4257e911b15Skarels } /* qdcons_init */
4267e911b15Skarels 
4277881ece5Smarc /*
4287881ece5Smarc  *  Configure QDSS into Q memory and make it intrpt.
4297e911b15Skarels  *
4307e911b15Skarels  *  side effects: QDSS gets mapped into Qbus memory space at the first
4317e911b15Skarels  *		 vacant 64kb boundary counting back from the top of
432e977faadSmarc  *		 Qbus memory space (qvmem+4mb)
4337e911b15Skarels  *
4347e911b15Skarels  *  return: QDSS bus request level and vector address returned in
4357e911b15Skarels  *	   registers by UNIX convention.
4367e911b15Skarels  *
4377881ece5Smarc  */
qdprobe(reg)4387e911b15Skarels qdprobe(reg)
4397881ece5Smarc 	caddr_t reg;	/* character pointer to the QDSS I/O page register */
4407e911b15Skarels {
441f79d7b48Smarc 	register int br, cvec;
4427e911b15Skarels 	register int unit;
4437e911b15Skarels 	struct dga *dga;		/* pointer to gate array structure */
4447e911b15Skarels 	int vector;
4457881ece5Smarc #ifdef notdef
4467881ece5Smarc 	int *ptep;			/* page table entry pointer */
4477e911b15Skarels 	caddr_t phys_adr;		/* physical QDSS base adrs */
4487e911b15Skarels 	u_int mapix;
4497881ece5Smarc #endif
4507881ece5Smarc 
4517881ece5Smarc #ifdef lint
4527881ece5Smarc 	br = 0; cvec = br; br = cvec; nNQD = br; br = nNQD;
4537881ece5Smarc 	qddint(0); qdaint(0); qdiint(0); (void)qdgetc();
4547881ece5Smarc #endif
4557e911b15Skarels 
456b2b69f49Smarc 	/*
457b2b69f49Smarc 	 * calculate board unit number from I/O page register address
458b2b69f49Smarc 	 */
4597e911b15Skarels 	unit = (int) (((int)reg >> 1) & 0x0007);
4607e911b15Skarels 
461b2b69f49Smarc 	/*
462b2b69f49Smarc 	 * QDSS regs must be mapped to Qbus memory space at a 64kb
463b2b69f49Smarc  	 * physical boundary.  The Qbus memory space is mapped into
464b2b69f49Smarc 	 * the system memory space at config time.  After config
465b2b69f49Smarc 	 * runs, "qvmem[0]" (ubavar.h) holds the system virtual adrs
466b2b69f49Smarc 	 * of the start of Qbus memory.   The Qbus memory page table
467b2b69f49Smarc 	 * is found via an array of pte ptrs called "QVmap[]" (ubavar.h)
468b2b69f49Smarc 	 * which is also loaded at config time.   These are the
469b2b69f49Smarc 	 * variables used below to find a vacant 64kb boundary in
470b2b69f49Smarc 	 * Qbus memory, and load it's corresponding physical adrs
471b2b69f49Smarc 	 * into the QDSS's I/O page CSR.
472b2b69f49Smarc 	 */
473e977faadSmarc 
474e977faadSmarc 	/*
475e977faadSmarc 	 * Only if QD is the graphics device.
47624f67f6bSmarc 	 */
4777e911b15Skarels 
4787e911b15Skarels 	/* if this QDSS is NOT the console, then do init here.. */
4797e911b15Skarels 
480e977faadSmarc 	if (unit != 0) {
481e977faadSmarc 		printf("qd: can't support two qdss's (yet)\n");
4827881ece5Smarc #ifdef notdef	/* can't test */
4837e911b15Skarels 		if (v_consputc != qdputc  ||  unit != 0) {
4847e911b15Skarels 
485b2b69f49Smarc 			/*
486b2b69f49Smarc 			* read QDSS config info
487b2b69f49Smarc 			*/
4887e911b15Skarels 			qdflags[unit].config = *(u_short *)reg;
4897e911b15Skarels 
490b2b69f49Smarc 			/*
491b2b69f49Smarc 			* find an empty 64kb adrs boundary
492b2b69f49Smarc 			*/
4937e911b15Skarels 
494e977faadSmarc 			qdbase[unit] = (caddr_t) (qvmem[0] + QMEMSIZE - CHUNK);
495e977faadSmarc 
496b2b69f49Smarc 			/*
4977881ece5Smarc 			* find the cpusw entry that matches this machine.
4987881ece5Smarc 			*/
4997e911b15Skarels 			cpup = &cpusw[cpu];
5007e911b15Skarels 			while (!(BADADDR(qdbase[unit], sizeof(short))))
5017e911b15Skarels 				qdbase[unit] -= CHUNK;
5027e911b15Skarels 
503b2b69f49Smarc 			/*
5047881ece5Smarc 			* tell QDSS which Q memory address base to decode
5057881ece5Smarc 			*/
506e977faadSmarc 			mapix = (int) (VTOP(qdbase[unit]) - VTOP(qvmem[0]));
507e977faadSmarc 			ptep = (int *) QVmap[0] + mapix;
5087e911b15Skarels 			phys_adr = (caddr_t)(((int)*ptep&0x001FFFFF)<<PGSHIFT);
5097e911b15Skarels 			*(u_short *)reg = (u_short) ((int)phys_adr >> 16);
5107e911b15Skarels 
511b2b69f49Smarc 			/*
512b2b69f49Smarc 			* load QDSS adrs map with system addresses
513b2b69f49Smarc 			* of device regs
514b2b69f49Smarc 			*/
5157e911b15Skarels 			qdmap[unit].template = qdbase[unit] + TMPSTART;
5167e911b15Skarels 			qdmap[unit].adder = qdbase[unit] + ADDER;
5177e911b15Skarels 			qdmap[unit].dga = qdbase[unit] + DGA;
5187e911b15Skarels 			qdmap[unit].duart = qdbase[unit] + DUART;
5197e911b15Skarels 			qdmap[unit].memcsr = qdbase[unit] + MEMCSR;
5207e911b15Skarels 			qdmap[unit].red = qdbase[unit] + RED;
5217e911b15Skarels 			qdmap[unit].blue = qdbase[unit] + BLUE;
5227e911b15Skarels 			qdmap[unit].green = qdbase[unit] + GREEN;
5237e911b15Skarels 
5247e911b15Skarels 			/* device init */
5257e911b15Skarels 
5267e911b15Skarels 			cursor[unit].x = 0;
5277e911b15Skarels 			cursor[unit].y = 0;
5287e911b15Skarels 			init_shared(unit);		/* init shared memory */
5297e911b15Skarels 			setup_dragon(unit); 	/* init the ADDER/VIPER stuff */
5307e911b15Skarels 			ldcursor(unit, cons_cursor);	/* load default cursor map */
5317e911b15Skarels 			setup_input(unit);		/* init the DUART */
5327e911b15Skarels 			clear_qd_screen(unit);
5337e911b15Skarels 			ldfont(unit);			/* load the console font */
5347e911b15Skarels 
5357e911b15Skarels 			/* once only: turn on sync */
5367e911b15Skarels 
5377e911b15Skarels 			*(short *)qdmap[unit].memcsr |= SYNC_ON;
538b2b69f49Smarc 		}
539006e9885Smarc #endif /*notdef*/
540e977faadSmarc 	}
5417e911b15Skarels 
542b2b69f49Smarc 	/*
543b2b69f49Smarc 	* The QDSS interrupts at HEX vectors xx0 (DMA) xx4
544b2b69f49Smarc 	* (ADDER) and xx8 (DUART).  Therefore, we take three
545b2b69f49Smarc 	* vectors from the vector pool, and then continue
546b2b69f49Smarc 	* to take them until we get a xx0 HEX vector.  The
547b2b69f49Smarc 	* pool provides vectors in contiguous decending
548b2b69f49Smarc 	* order.
549b2b69f49Smarc 	*/
5507e911b15Skarels 
5517e911b15Skarels 	vector = (uba_hd[0].uh_lastiv -= 4*3);	/* take three vectors */
5527e911b15Skarels 
5537e911b15Skarels 	while (vector & 0x0F) {		   /* if lo nibble != 0.. */
554b2b69f49Smarc 		/* ..take another vector */
555b2b69f49Smarc 		vector = (uba_hd[0].uh_lastiv -= 4);
5567e911b15Skarels 	}
5577e911b15Skarels 
558b2b69f49Smarc 	/*
559b2b69f49Smarc 	* setup DGA to do a DMA interrupt (transfer count = 0)
560b2b69f49Smarc 	*/
5617e911b15Skarels 	dga = (struct dga *) qdmap[unit].dga;
5627e911b15Skarels 	dga->csr = (short) HALT;	/* disable everything */
5637e911b15Skarels 	dga->ivr = (short) vector;	/* load intrpt base vector */
5647e911b15Skarels 	dga->bytcnt_lo = (short) 0;	/* DMA xfer count = 0 */
5657e911b15Skarels 	dga->bytcnt_hi = (short) 0;
5667e911b15Skarels 
567b2b69f49Smarc 	/*
568b2b69f49Smarc 	* turn on DMA interrupts
569b2b69f49Smarc 	*/
5707e911b15Skarels 	dga->csr &= ~SET_DONE_FIFO;
5717e911b15Skarels 	dga->csr |= DMA_IE | DL_ENB;
5727e911b15Skarels 
5737e911b15Skarels 	DELAY(20000);			/* wait for the intrpt */
5747e911b15Skarels 	dga->csr = HALT;		/* stop the wheels */
5757e911b15Skarels 
5767e911b15Skarels 	if (cvec != vector)		/* if vector != base vector.. */
5777e911b15Skarels 		return(0);		/* ..return = 'no device' */
5787e911b15Skarels 
579e977faadSmarc 	/*
580e977faadSmarc 	* score this as an existing qdss
581e977faadSmarc 	*/
582e977faadSmarc 	qdcount++;
583e977faadSmarc 
5847e911b15Skarels 	return(sizeof(short));	    /* return size of QDSS I/O page reg */
5857e911b15Skarels 
5867e911b15Skarels } /* qdprobe */
5877e911b15Skarels 
5887e911b15Skarels qdattach(ui)
5897e911b15Skarels 	struct uba_device *ui;
5907e911b15Skarels {
5917881ece5Smarc 	register unit;			/* QDSS module # for this call */
5927e911b15Skarels 
5937e911b15Skarels 	unit = ui->ui_unit;		/* get QDSS number */
5947e911b15Skarels 
595b2b69f49Smarc 	/*
596b2b69f49Smarc 	* init "qdflags[]" for this QDSS
597b2b69f49Smarc 	*/
5987e911b15Skarels 	qdflags[unit].inuse = 0;	/* init inuse variable EARLY! */
5997e911b15Skarels 	qdflags[unit].mapped = 0;
600e977faadSmarc 	qdflags[unit].kernel_loop = -1;
6017e911b15Skarels 	qdflags[unit].user_dma = 0;
6027e911b15Skarels 	qdflags[unit].curs_acc = ACC_OFF;
6037e911b15Skarels 	qdflags[unit].curs_thr = 128;
6047e911b15Skarels 	qdflags[unit].tab_res = 2;	/* default tablet resolution factor */
6057e911b15Skarels 	qdflags[unit].duart_imask = 0;	/* init shadow variables */
6067e911b15Skarels 	qdflags[unit].adder_ie = 0;
6077e911b15Skarels 
608b2b69f49Smarc 	/*
6097e911b15Skarels 	* init structures used in kbd/mouse interrupt service.	This code must
610b2b69f49Smarc 	* come after the "init_shared()" routine has run since that routine
611b2b69f49Smarc 	* inits the eq_header[unit] structure used here.
612b2b69f49Smarc 	*/
6137e911b15Skarels 
614b2b69f49Smarc 	/*
615b2b69f49Smarc 	* init the "latest mouse report" structure
616b2b69f49Smarc 	*/
6177e911b15Skarels 	last_rep[unit].state = 0;
6187e911b15Skarels 	last_rep[unit].dx = 0;
6197e911b15Skarels 	last_rep[unit].dy = 0;
6207e911b15Skarels 	last_rep[unit].bytcnt = 0;
6217e911b15Skarels 
622b2b69f49Smarc 	/*
6237881ece5Smarc 	* init the event queue (except mouse position)
6247881ece5Smarc 	*/
6257881ece5Smarc 	eq_header[unit]->header.events =
6267881ece5Smarc 	    (struct _vs_event *)((int)eq_header[unit] + sizeof(struct qdinput));
6277e911b15Skarels 
6287e911b15Skarels 	eq_header[unit]->header.size = MAXEVENTS;
6297e911b15Skarels 	eq_header[unit]->header.head = 0;
6307e911b15Skarels 	eq_header[unit]->header.tail = 0;
6317e911b15Skarels 
632b2b69f49Smarc 	/*
633b2b69f49Smarc 	 * open exclusive for graphics device.
634b2b69f49Smarc 	 */
635b2b69f49Smarc 	qdopened[unit] = 0;
6367e911b15Skarels 
6377e911b15Skarels } /* qdattach */
6387e911b15Skarels 
6397881ece5Smarc /*ARGSUSED*/
qdopen(dev,flag)6407e911b15Skarels qdopen(dev, flag)
6417e911b15Skarels 	dev_t dev;
6427e911b15Skarels 	int flag;
6437e911b15Skarels {
6447e911b15Skarels 	register struct uba_device *ui; /* ptr to uba structures */
6457e911b15Skarels 	register struct dga *dga;	/* ptr to gate array struct */
6467e911b15Skarels 	register struct tty *tp;
6477e911b15Skarels 	struct duart *duart;
6487881ece5Smarc 	int unit;
6497881ece5Smarc 	int minor_dev;
6507e911b15Skarels 
6517e911b15Skarels 	minor_dev = minor(dev); /* get QDSS minor device number */
6527e911b15Skarels 	unit = minor_dev >> 2;
6537e911b15Skarels 
654b2b69f49Smarc 	/*
655b2b69f49Smarc 	* check for illegal conditions
656b2b69f49Smarc 	*/
6577e911b15Skarels 	ui = qdinfo[unit];		/* get ptr to QDSS device struct */
6587e911b15Skarels 	if (ui == 0  || ui->ui_alive == 0)
6597e911b15Skarels 		return(ENXIO);		/* no such device or address */
6607e911b15Skarels 
6617e911b15Skarels 	duart = (struct duart *) qdmap[unit].duart;
6627e911b15Skarels 	dga = (struct dga *) qdmap[unit].dga;
6637e911b15Skarels 
6647e911b15Skarels 	if ((minor_dev & 0x03) == 2) {
665b2b69f49Smarc 		/*
666b2b69f49Smarc 		* this is the graphic device...
667b2b69f49Smarc 		*/
668b2b69f49Smarc 		if (qdopened[unit] != 0)
6697e911b15Skarels 			return(EBUSY);
6707e911b15Skarels 		else
671b2b69f49Smarc 			qdopened[unit] = 1;
6727e911b15Skarels 		qdflags[unit].inuse |= GRAPHIC_DEV;  /* graphics dev is open */
673b2b69f49Smarc 		/*
674b2b69f49Smarc 		 * enble kbd & mouse intrpts in DUART mask reg
675b2b69f49Smarc 		 */
6767e911b15Skarels 		qdflags[unit].duart_imask |= 0x22;
6777e911b15Skarels 		duart->imask = qdflags[unit].duart_imask;
678b2b69f49Smarc 	} else {
679b2b69f49Smarc 		/*
680b2b69f49Smarc 		* this is the console
681b2b69f49Smarc 		*/
6827e911b15Skarels 		qdflags[unit].inuse |= CONS_DEV;  /* mark console as open */
6837e911b15Skarels 		dga->csr |= CURS_ENB;
6847e911b15Skarels 		qdflags[unit].duart_imask |= 0x02;
6857e911b15Skarels 		duart->imask = qdflags[unit].duart_imask;
686b2b69f49Smarc 		/*
687b2b69f49Smarc 		* some setup for tty handling
688b2b69f49Smarc 		*/
6897e911b15Skarels 		tp = &qd_tty[minor_dev];
6907e911b15Skarels 		tp->t_addr = ui->ui_addr;
6917e911b15Skarels 		tp->t_oproc = qdstart;
6927e911b15Skarels 		if ((tp->t_state & TS_ISOPEN) == 0) {
6937e911b15Skarels 			ttychars(tp);
6947e911b15Skarels 			tp->t_ispeed = B9600;
6957e911b15Skarels 			tp->t_ospeed = B9600;
696e977faadSmarc 			tp->t_state = TS_ISOPEN | TS_CARR_ON;
697b2b69f49Smarc 			tp->t_iflag = TTYDEF_IFLAG;
698b2b69f49Smarc 			tp->t_oflag = TTYDEF_OFLAG;
699b2b69f49Smarc 			tp->t_lflag = TTYDEF_LFLAG;
700b2b69f49Smarc 			tp->t_cflag = TTYDEF_CFLAG;
701e977faadSmarc 		}
702b2b69f49Smarc 		/*
703b2b69f49Smarc 		* enable intrpts, open line discipline
704b2b69f49Smarc 		*/
7057e911b15Skarels 		dga->csr |= GLOBAL_IE;	/* turn on the interrupts */
7067e911b15Skarels 		return ((*linesw[tp->t_line].l_open)(dev, tp));
7077e911b15Skarels 	}
7087e911b15Skarels 	dga->csr |= GLOBAL_IE;	/* turn on the interrupts */
7097e911b15Skarels 	return(0);
7107e911b15Skarels 
7117e911b15Skarels } /* qdopen */
7127e911b15Skarels 
7137881ece5Smarc /*ARGSUSED*/
qdclose(dev,flag,mode,p)7149e5284e4Smarc qdclose(dev, flag, mode, p)
7157e911b15Skarels 	dev_t dev;
7169e5284e4Smarc 	int flag, mode;
7179e5284e4Smarc 	struct proc *p;
7187e911b15Skarels {
7197e911b15Skarels 	register struct tty *tp;
7207e911b15Skarels 	register struct qdmap *qd;
7217e911b15Skarels 	register int *ptep;
7227e911b15Skarels 	struct dga *dga;		/* gate array register map pointer */
7237e911b15Skarels 	struct duart *duart;
7247e911b15Skarels 	struct adder *adder;
7257881ece5Smarc 	int unit;
7267881ece5Smarc 	int minor_dev;
7277e911b15Skarels 	u_int mapix;
728b2b69f49Smarc 	int i;				/* SIGNED index */
7297e911b15Skarels 
7307e911b15Skarels 	minor_dev = minor(dev); 	/* get minor device number */
7317e911b15Skarels 	unit = minor_dev >> 2;		/* get QDSS number */
7327e911b15Skarels 	qd = &qdmap[unit];
7337e911b15Skarels 
7347e911b15Skarels 	if ((minor_dev & 0x03) == 2) {
735b2b69f49Smarc 		/*
736b2b69f49Smarc 		* this is the graphic device...
737b2b69f49Smarc 		*/
738b2b69f49Smarc 		if (qdopened[unit] != 1)
7397e911b15Skarels 		    	return(EBUSY);
7407e911b15Skarels 		else
741b2b69f49Smarc 			qdopened[unit] = 0;	/* allow it to be re-opened */
742b2b69f49Smarc 		/*
743b2b69f49Smarc 		* re-protect device memory
744b2b69f49Smarc 		*/
7457e911b15Skarels 		if (qdflags[unit].mapped & MAPDEV) {
746b2b69f49Smarc 			/*
747b2b69f49Smarc 			* TEMPLATE RAM
748b2b69f49Smarc 			*/
74924f67f6bSmarc 			mapix = VTOP((int)qd->template) - VTOP(qvmem[0]);
75024f67f6bSmarc 			ptep = (int *)(QVmap[0] + mapix);
7517881ece5Smarc 			for (i = 0; i < btop(TMPSIZE); i++, ptep++)
7527881ece5Smarc 				*ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
753b2b69f49Smarc 			/*
754b2b69f49Smarc 			* ADDER
755b2b69f49Smarc 			*/
75624f67f6bSmarc 			mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]);
75724f67f6bSmarc 			ptep = (int *)(QVmap[0] + mapix);
7587881ece5Smarc 			for (i = 0; i < btop(REGSIZE); i++, ptep++)
7597881ece5Smarc 				*ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
760b2b69f49Smarc 			/*
761b2b69f49Smarc 			* COLOR MAPS
762b2b69f49Smarc 			*/
76324f67f6bSmarc 			mapix = VTOP((int)qd->red) - VTOP(qvmem[0]);
76424f67f6bSmarc 			ptep = (int *)(QVmap[0] + mapix);
7657881ece5Smarc 			for (i = 0; i < btop(CLRSIZE); i++, ptep++)
7667881ece5Smarc 				*ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
7677e911b15Skarels 		}
7687e911b15Skarels 
769b2b69f49Smarc 		/*
770b2b69f49Smarc 		* re-protect DMA buffer and free the map registers
771b2b69f49Smarc 		*/
7727e911b15Skarels 		if (qdflags[unit].mapped & MAPDMA) {
7737e911b15Skarels 			dga = (struct dga *) qdmap[unit].dga;
7747e911b15Skarels 			adder = (struct adder *) qdmap[unit].adder;
7757e911b15Skarels 			dga->csr &= ~DMA_IE;
7767e911b15Skarels 			dga->csr &= ~0x0600;	     /* kill DMA */
7777e911b15Skarels 			adder->command = CANCEL;
778b2b69f49Smarc 			/*
779b2b69f49Smarc 			 * if DMA was running, flush spurious intrpt
780b2b69f49Smarc 			 */
7817e911b15Skarels 			if (dga->bytcnt_lo != 0) {
7827e911b15Skarels 				dga->bytcnt_lo = 0;
7837e911b15Skarels 				dga->bytcnt_hi = 0;
7847e911b15Skarels 				DMA_SETIGNORE(DMAheader[unit]);
7857e911b15Skarels 				dga->csr |= DMA_IE;
7867e911b15Skarels 				dga->csr &= ~DMA_IE;
7877e911b15Skarels 			}
7887e911b15Skarels 			ptep = (int *)
7897e911b15Skarels 			   ((VTOP(DMAheader[unit]*4)) + (mfpr(SBR)|0x80000000));
7907881ece5Smarc 			for (i = 0; i < btop(DMAbuf_size); i++, ptep++)
7917881ece5Smarc 				*ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
7927e911b15Skarels 			ubarelse(0, &Qbus_unmap[unit]);
7937e911b15Skarels 		}
7947e911b15Skarels 
795b2b69f49Smarc 		/*
796b2b69f49Smarc 		* re-protect 1K (2 pages) event queue
797b2b69f49Smarc 		*/
7987e911b15Skarels 		if (qdflags[unit].mapped & MAPEQ) {
7997e911b15Skarels 			ptep = (int *)
8007e911b15Skarels 			   ((VTOP(eq_header[unit])*4) + (mfpr(SBR)|0x80000000));
8017881ece5Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++;
8027e911b15Skarels 			*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
8037e911b15Skarels 		}
804b2b69f49Smarc 		/*
805b2b69f49Smarc 		* re-protect scroll param area and disable scroll intrpts
806b2b69f49Smarc 		*/
8077e911b15Skarels 		if (qdflags[unit].mapped & MAPSCR) {
8087e911b15Skarels 			ptep = (int *) ((VTOP(scroll[unit]) * 4)
8097e911b15Skarels 				+ (mfpr(SBR) | 0x80000000));
810b2b69f49Smarc 			/*
811b2b69f49Smarc 			 * re-protect 512 scroll param area
812b2b69f49Smarc 			 */
8137e911b15Skarels 			*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
8147e911b15Skarels 			adder = (struct adder *) qdmap[unit].adder;
8157e911b15Skarels 			qdflags[unit].adder_ie &= ~FRAME_SYNC;
8167e911b15Skarels 			adder->interrupt_enable = qdflags[unit].adder_ie;
8177e911b15Skarels 		}
818b2b69f49Smarc 		/*
819b2b69f49Smarc 		* re-protect color map write buffer area and kill intrpts
820b2b69f49Smarc 		*/
8217e911b15Skarels 		if (qdflags[unit].mapped & MAPCOLOR) {
8227e911b15Skarels 			ptep = (int *) ((VTOP(color_buf[unit]) * 4)
8237e911b15Skarels 				+ (mfpr(SBR) | 0x80000000));
8247881ece5Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++;
8257e911b15Skarels 			*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
8267e911b15Skarels 			color_buf[unit]->status = 0;
8277e911b15Skarels 			adder = (struct adder *) qdmap[unit].adder;
8287e911b15Skarels 			qdflags[unit].adder_ie &= ~VSYNC;
8297e911b15Skarels 			adder->interrupt_enable = qdflags[unit].adder_ie;
8307e911b15Skarels 		}
831b2b69f49Smarc 		mtpr(TBIA, 0);
832b2b69f49Smarc 		/* flag everything now unmapped */
833b2b69f49Smarc 		qdflags[unit].mapped = 0;
8347e911b15Skarels 		qdflags[unit].inuse &= ~GRAPHIC_DEV;
8357e911b15Skarels 		qdflags[unit].curs_acc = ACC_OFF;
8367e911b15Skarels 		qdflags[unit].curs_thr = 128;
837b2b69f49Smarc 		/*
838b2b69f49Smarc 		* restore the console
839b2b69f49Smarc 		*/
8407e911b15Skarels 		dga = (struct dga *) qdmap[unit].dga;
8417e911b15Skarels 		adder = (struct adder *) qdmap[unit].adder;
8427e911b15Skarels 		dga->csr &= ~DMA_IE;
8437e911b15Skarels 		dga->csr &= ~0x0600;	/* halt the DMA! (just in case...) */
8447e911b15Skarels 		dga->csr |= DMA_ERR;	/* clear error condition */
8457e911b15Skarels 		adder->command = CANCEL;
846b2b69f49Smarc 		/*
847b2b69f49Smarc 		 * if DMA was running, flush spurious intrpt
848b2b69f49Smarc 		 */
8497e911b15Skarels 		if (dga->bytcnt_lo != 0) {
8507e911b15Skarels 			dga->bytcnt_lo = 0;
8517e911b15Skarels 			dga->bytcnt_hi = 0;
8527e911b15Skarels 			DMA_SETIGNORE(DMAheader[unit]);
8537e911b15Skarels 			dga->csr |= DMA_IE;
8547e911b15Skarels 			dga->csr &= ~DMA_IE;
8557e911b15Skarels 		}
8567e911b15Skarels 		init_shared(unit);		/* init shared memory */
8577e911b15Skarels 		setup_dragon(unit);		/* init ADDER/VIPER */
8587e911b15Skarels 		ldcursor(unit, cons_cursor);	/* load default cursor map */
8597e911b15Skarels 		setup_input(unit);		/* init the DUART */
8607e911b15Skarels 		ldfont(unit);
8617e911b15Skarels 		cursor[unit].x = 0;
8627e911b15Skarels 		cursor[unit].y = 0;
863b2b69f49Smarc 		/*
864b2b69f49Smarc 		 * shut off the mouse rcv intrpt and turn on kbd intrpts
865b2b69f49Smarc 		 */
8667e911b15Skarels 		duart = (struct duart *) qdmap[unit].duart;
8677e911b15Skarels 		qdflags[unit].duart_imask &= ~(0x20);
8687e911b15Skarels 		qdflags[unit].duart_imask |= 0x02;
8697e911b15Skarels 		duart->imask = qdflags[unit].duart_imask;
870b2b69f49Smarc 		/*
871b2b69f49Smarc 		* shut off interrupts if all is closed
872b2b69f49Smarc 		*/
873b2b69f49Smarc 		if (!(qdflags[unit].inuse & CONS_DEV)) {
8747e911b15Skarels 			dga = (struct dga *) qdmap[unit].dga;
8757e911b15Skarels 			dga->csr &= ~(GLOBAL_IE | DMA_IE);
8767e911b15Skarels 		}
877b2b69f49Smarc 	} else {
878b2b69f49Smarc 		/*
879b2b69f49Smarc 		* this is the console
880b2b69f49Smarc 		*/
8817e911b15Skarels 		tp = &qd_tty[minor_dev];
8829e5284e4Smarc 		(*linesw[tp->t_line].l_close)(tp, flag);
8837e911b15Skarels 		ttyclose(tp);
8847e911b15Skarels 		tp->t_state = 0;
8857e911b15Skarels 		qdflags[unit].inuse &= ~CONS_DEV;
886b2b69f49Smarc 		/*
887b2b69f49Smarc 		* if graphics device is closed, kill interrupts
888b2b69f49Smarc 		*/
8897e911b15Skarels 		if (!(qdflags[unit].inuse & GRAPHIC_DEV)) {
8907e911b15Skarels 			dga = (struct dga *) qdmap[unit].dga;
8917e911b15Skarels 			dga->csr &= ~(GLOBAL_IE | DMA_IE);
8927e911b15Skarels 		}
8937e911b15Skarels 	}
8947e911b15Skarels 
8957e911b15Skarels 	return(0);
8967e911b15Skarels 
8977e911b15Skarels } /* qdclose */
8987e911b15Skarels 
qdioctl(dev,cmd,datap,flags)8997e911b15Skarels qdioctl(dev, cmd, datap, flags)
9007e911b15Skarels 	dev_t dev;
9017e911b15Skarels 	int cmd;
9027881ece5Smarc 	register caddr_t datap;
9037e911b15Skarels 	int flags;
9047e911b15Skarels {
9057e911b15Skarels 	register int *ptep;		/* page table entry pointer */
90624f67f6bSmarc 	register int mapix;		/* QVmap[] page table index */
9077e911b15Skarels 	register struct _vs_event *event;
9087e911b15Skarels 	register struct tty *tp;
9097881ece5Smarc 	register i;
9107e911b15Skarels 	struct qdmap *qd;		/* pointer to device map struct */
9117e911b15Skarels 	struct dga *dga;		/* Gate Array reg structure pntr */
9127e911b15Skarels 	struct duart *duart;		/* DUART reg structure pointer */
9137e911b15Skarels 	struct adder *adder;		/* ADDER reg structure pointer */
9147e911b15Skarels 	struct prgkbd *cmdbuf;
9157e911b15Skarels 	struct prg_cursor *curs;
9167e911b15Skarels 	struct _vs_cursor *pos;
9177881ece5Smarc 	int unit = minor(dev) >> 2;	/* number of caller's QDSS */
9187e911b15Skarels 	u_int minor_dev = minor(dev);
9197e911b15Skarels 	int error;
9207e911b15Skarels 	int s;
9217e911b15Skarels 	short *temp;			/* a pointer to template RAM */
9227e911b15Skarels 
923b2b69f49Smarc 	/*
924b2b69f49Smarc 	* service graphic device ioctl commands
925b2b69f49Smarc 	*/
9267e911b15Skarels 	switch (cmd) {
927e977faadSmarc 
9287e911b15Skarels 	case QD_GETEVENT:
929b2b69f49Smarc 		/*
930b2b69f49Smarc 		* extract the oldest event from the event queue
931b2b69f49Smarc 		*/
9327e911b15Skarels 		if (ISEMPTY(eq_header[unit])) {
9337e911b15Skarels 			event = (struct _vs_event *) datap;
9347e911b15Skarels 			event->vse_device = VSE_NULL;
9357e911b15Skarels 			break;
9367e911b15Skarels 		}
9377e911b15Skarels 		event = (struct _vs_event *) GETBEGIN(eq_header[unit]);
938e977faadSmarc 		s = spl5();
9397e911b15Skarels 		GETEND(eq_header[unit]);
9407e911b15Skarels 		splx(s);
9417881ece5Smarc 		bcopy((caddr_t)event, datap, sizeof(struct _vs_event));
9427e911b15Skarels 		break;
9437e911b15Skarels 
9447e911b15Skarels 	case QD_RESET:
945b2b69f49Smarc 		/*
946b2b69f49Smarc 		* init the dragon stuff, DUART, and driver variables
947b2b69f49Smarc 		*/
9487e911b15Skarels 		init_shared(unit);		/* init shared memory */
9497e911b15Skarels 		setup_dragon(unit);	      /* init the ADDER/VIPER stuff */
9507e911b15Skarels 		clear_qd_screen(unit);
9517e911b15Skarels 		ldcursor(unit, cons_cursor);	/* load default cursor map */
9527e911b15Skarels 		ldfont(unit);			/* load the console font */
9537e911b15Skarels 		setup_input(unit);		/* init the DUART */
9547e911b15Skarels 		break;
9557e911b15Skarels 
9567e911b15Skarels 	case QD_SET:
957b2b69f49Smarc 		/*
958b2b69f49Smarc 		* init the DUART and driver variables
959b2b69f49Smarc 		*/
9607e911b15Skarels 		init_shared(unit);
9617e911b15Skarels 		setup_input(unit);
9627e911b15Skarels 		break;
9637e911b15Skarels 
9647e911b15Skarels 	case QD_CLRSCRN:
965b2b69f49Smarc 		/*
966b2b69f49Smarc 		* clear the QDSS screen.  (NOTE that this reinits the dragon)
967b2b69f49Smarc 		*/
9687881ece5Smarc #ifdef notdef	/* has caused problems and isn't necessary */
9697e911b15Skarels 		setup_dragon(unit);
9707e911b15Skarels 		clear_qd_screen(unit);
971e977faadSmarc #endif
9727e911b15Skarels 		break;
9737e911b15Skarels 
9747e911b15Skarels 	case QD_WTCURSOR:
975b2b69f49Smarc 		/*
976b2b69f49Smarc 		* load a cursor into template RAM
977b2b69f49Smarc 		*/
9787881ece5Smarc 		ldcursor(unit, (short *)datap);
9797e911b15Skarels 		break;
9807e911b15Skarels 
9817e911b15Skarels 	case QD_RDCURSOR:
9827e911b15Skarels 
9837e911b15Skarels 		temp = (short *) qdmap[unit].template;
984b2b69f49Smarc 		/*
985b2b69f49Smarc 		 * cursor is 32 WORDS from the end of the 8k WORD...
986b2b69f49Smarc 		 *  ...template space
987b2b69f49Smarc 		 */
9887e911b15Skarels 		temp += (8 * 1024) - 32;
9897e911b15Skarels 		for (i = 0; i < 32; ++i, datap += sizeof(short))
9907e911b15Skarels 			*(short *)datap = *temp++;
9917e911b15Skarels 		break;
9927e911b15Skarels 
9937e911b15Skarels 	case QD_POSCURSOR:
994b2b69f49Smarc 		/*
995b2b69f49Smarc 		* position the mouse cursor
996b2b69f49Smarc 		*/
9977e911b15Skarels 		dga = (struct dga *) qdmap[unit].dga;
9987e911b15Skarels 		pos = (struct _vs_cursor *) datap;
999e977faadSmarc 		s = spl5();
10007e911b15Skarels 		dga->x_cursor = TRANX(pos->x);
10017e911b15Skarels 		dga->y_cursor = TRANY(pos->y);
10027e911b15Skarels 		eq_header[unit]->curs_pos.x = pos->x;
10037e911b15Skarels 		eq_header[unit]->curs_pos.y = pos->y;
10047e911b15Skarels 		splx(s);
10057e911b15Skarels 		break;
10067e911b15Skarels 
10077e911b15Skarels 	case QD_PRGCURSOR:
1008b2b69f49Smarc 		/*
1009b2b69f49Smarc 		* set the cursor acceleration factor
1010b2b69f49Smarc 		*/
10117e911b15Skarels 		curs = (struct prg_cursor *) datap;
1012e977faadSmarc 		s = spl5();
10137e911b15Skarels 		qdflags[unit].curs_acc = curs->acc_factor;
10147e911b15Skarels 		qdflags[unit].curs_thr = curs->threshold;
10157e911b15Skarels 		splx(s);
10167e911b15Skarels 		break;
10177e911b15Skarels 
10187e911b15Skarels 	case QD_MAPDEVICE:
1019b2b69f49Smarc 		/*
1020b2b69f49Smarc 		* enable 'user write' to device pages
1021b2b69f49Smarc 		*/
10227e911b15Skarels 		qdflags[unit].mapped |= MAPDEV;
10237e911b15Skarels 		qd = (struct qdmap *) &qdmap[unit];
1024b2b69f49Smarc 		/*
1025b2b69f49Smarc 		* enable user write to template RAM
1026b2b69f49Smarc 		*/
102724f67f6bSmarc 		mapix = VTOP((int)qd->template) - VTOP(qvmem[0]);
102824f67f6bSmarc 		ptep = (int *)(QVmap[0] + mapix);
10297881ece5Smarc 		for (i = 0; i < btop(TMPSIZE); i++, ptep++)
10307881ece5Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
1031b2b69f49Smarc 		/*
1032b2b69f49Smarc 		* enable user write to registers
1033b2b69f49Smarc 		*/
103424f67f6bSmarc 		mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]);
103524f67f6bSmarc 		ptep = (int *)(QVmap[0] + mapix);
10367881ece5Smarc 		for (i = 0; i < btop(REGSIZE); i++, ptep++)
10377881ece5Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
1038b2b69f49Smarc 		/*
1039b2b69f49Smarc 		* enable user write to color maps
1040b2b69f49Smarc 		*/
104124f67f6bSmarc 		mapix = VTOP((int)qd->red) - VTOP(qvmem[0]);
104224f67f6bSmarc 		ptep = (int *)(QVmap[0] + mapix);
10437881ece5Smarc 		for (i = 0; i < btop(CLRSIZE); i++, ptep++)
10447881ece5Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
1045b2b69f49Smarc 		/*
1046b2b69f49Smarc 		* enable user write to DUART
1047b2b69f49Smarc 		*/
104824f67f6bSmarc 		mapix = VTOP((int)qd->duart) - VTOP(qvmem[0]);
104924f67f6bSmarc 		ptep = (int *)(QVmap[0] + mapix);
10507e911b15Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; /* duart page */
10517e911b15Skarels 
10527881ece5Smarc 		mtpr(TBIA, 0);		/* invalidate translation buffer */
10537e911b15Skarels 
1054b2b69f49Smarc 		/*
1055b2b69f49Smarc 		 * stuff qdmap structure in return buffer
1056b2b69f49Smarc 		 */
10577881ece5Smarc 		bcopy((caddr_t)qd, datap, sizeof(struct qdmap));
10587e911b15Skarels 		break;
10597e911b15Skarels 
10607e911b15Skarels 	case QD_MAPIOBUF:
1061b2b69f49Smarc 		/*
1062b2b69f49Smarc 		 * do setup for DMA by user process
1063b2b69f49Smarc 		 *
1064b2b69f49Smarc 		 * set 'user write enable' bits for DMA buffer
1065b2b69f49Smarc 		 */
10667e911b15Skarels 		qdflags[unit].mapped |= MAPDMA;
10677e911b15Skarels 		ptep = (int *) ((VTOP(DMAheader[unit]) * 4)
10687e911b15Skarels 			+ (mfpr(SBR) | 0x80000000));
10697881ece5Smarc 		for (i = 0; i < btop(DMAbuf_size); i++, ptep++)
10707881ece5Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
10717881ece5Smarc 		mtpr(TBIA, 0);		/* invalidate translation buffer */
1072b2b69f49Smarc 		/*
1073b2b69f49Smarc 		* set up QBUS map registers for DMA
1074b2b69f49Smarc 		*/
10757e911b15Skarels 		DMAheader[unit]->QBAreg =
10767881ece5Smarc 		    uballoc(0, (caddr_t)DMAheader[unit], DMAbuf_size, 0);
10777e911b15Skarels 		if (DMAheader[unit]->QBAreg == 0)
10787881ece5Smarc 		    printf("qd%d: qdioctl: QBA setup error\n", unit);
10797e911b15Skarels 		Qbus_unmap[unit] = DMAheader[unit]->QBAreg;
10807e911b15Skarels 		DMAheader[unit]->QBAreg &= 0x3FFFF;
1081b2b69f49Smarc 		/*
1082b2b69f49Smarc 		* return I/O buf adr
1083b2b69f49Smarc 		*/
10847e911b15Skarels 		*(int *)datap = (int) DMAheader[unit];
10857e911b15Skarels 		break;
10867e911b15Skarels 
10877e911b15Skarels 	case QD_MAPSCROLL:
1088b2b69f49Smarc 		/*
1089b2b69f49Smarc 		* map the shared scroll param area and enable scroll interpts
1090b2b69f49Smarc 		*/
10917e911b15Skarels 		qdflags[unit].mapped |= MAPSCR;
10927e911b15Skarels 		ptep = (int *) ((VTOP(scroll[unit]) * 4)
10937e911b15Skarels 			+ (mfpr(SBR) | 0x80000000));
1094b2b69f49Smarc 		/*
1095b2b69f49Smarc 		 * allow user write to scroll area
1096b2b69f49Smarc 		 */
10977e911b15Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
10987881ece5Smarc 		mtpr(TBIA, 0);			/* invalidate translation buf */
10997e911b15Skarels 		scroll[unit]->status = 0;
11007e911b15Skarels 		adder = (struct adder *) qdmap[unit].adder;
11017e911b15Skarels 		qdflags[unit].adder_ie |= FRAME_SYNC;
11027e911b15Skarels 		adder->interrupt_enable = qdflags[unit].adder_ie;
1103b2b69f49Smarc 		*(int *)datap = (int) scroll[unit]; /* return scroll area */
11047e911b15Skarels 		break;
11057e911b15Skarels 
11067e911b15Skarels 	case QD_UNMAPSCROLL:
1107b2b69f49Smarc 		/*
1108b2b69f49Smarc 		* unmap shared scroll param area and disable scroll intrpts
1109b2b69f49Smarc 		*/
11107e911b15Skarels 		if (qdflags[unit].mapped & MAPSCR) {
11117e911b15Skarels 			qdflags[unit].mapped &= ~MAPSCR;
11127e911b15Skarels 			ptep = (int *) ((VTOP(scroll[unit]) * 4)
11137e911b15Skarels 				+ (mfpr(SBR) | 0x80000000));
1114b2b69f49Smarc 			/*
1115b2b69f49Smarc 			 * re-protect 512 scroll param area
1116b2b69f49Smarc 			 */
11177e911b15Skarels 			*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
11187e911b15Skarels 			mtpr(TBIA, 0);	/* smash CPU's translation buf */
11197e911b15Skarels 			adder = (struct adder *) qdmap[unit].adder;
11207e911b15Skarels 			qdflags[unit].adder_ie &= ~FRAME_SYNC;
11217e911b15Skarels 			adder->interrupt_enable = qdflags[unit].adder_ie;
11227e911b15Skarels 		}
11237e911b15Skarels 		break;
11247e911b15Skarels 
11257e911b15Skarels 	case QD_MAPCOLOR:
1126b2b69f49Smarc 		/*
1127b2b69f49Smarc 		* map shared color map write buf and turn on vsync intrpt
1128b2b69f49Smarc 		*/
11297e911b15Skarels 		qdflags[unit].mapped |= MAPCOLOR;
11307e911b15Skarels 		ptep = (int *) ((VTOP(color_buf[unit]) * 4)
11317e911b15Skarels 			+ (mfpr(SBR) | 0x80000000));
11327881ece5Smarc 		/*
11337881ece5Smarc 		 * allow user write to color map write buffer
11347881ece5Smarc 		 */
11357881ece5Smarc 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; ptep++;
11367e911b15Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
11377e911b15Skarels 		mtpr(TBIA, 0);			/* clr CPU translation buf */
1138b2b69f49Smarc 		adder = (struct adder *) qdmap[unit].adder;
11397e911b15Skarels 		qdflags[unit].adder_ie |= VSYNC;
11407e911b15Skarels 		adder->interrupt_enable = qdflags[unit].adder_ie;
11417881ece5Smarc 		/*
11427881ece5Smarc 		 * return color area address
11437881ece5Smarc 		 */
11447e911b15Skarels 		*(int *)datap = (int) color_buf[unit];
11457e911b15Skarels 		break;
11467e911b15Skarels 
11477e911b15Skarels 	case QD_UNMAPCOLOR:
1148b2b69f49Smarc 		/*
1149b2b69f49Smarc 		 * unmap shared color map write buffer and kill VSYNC intrpts
1150b2b69f49Smarc 		 */
11517e911b15Skarels 		if (qdflags[unit].mapped & MAPCOLOR) {
11527e911b15Skarels 			qdflags[unit].mapped &= ~MAPCOLOR;
11537e911b15Skarels 			ptep = (int *) ((VTOP(color_buf[unit]) * 4)
11547e911b15Skarels 				+ (mfpr(SBR) | 0x80000000));
11557881ece5Smarc 			/*
11567881ece5Smarc 			 * re-protect color map write buffer
11577881ece5Smarc 			 */
11587881ece5Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++;
11597e911b15Skarels 			*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
11607881ece5Smarc 			mtpr(TBIA, 0);
11617e911b15Skarels 			adder = (struct adder *) qdmap[unit].adder;
11627e911b15Skarels 			qdflags[unit].adder_ie &= ~VSYNC;
11637e911b15Skarels 			adder->interrupt_enable = qdflags[unit].adder_ie;
11647e911b15Skarels 		}
11657e911b15Skarels 		break;
11667e911b15Skarels 
11677e911b15Skarels 	case QD_MAPEVENT:
1168b2b69f49Smarc 		/*
1169b2b69f49Smarc 		* give user write access to the event queue
1170b2b69f49Smarc 		*/
11717e911b15Skarels 		qdflags[unit].mapped |= MAPEQ;
11727e911b15Skarels 		ptep = (int *) ((VTOP(eq_header[unit]) * 4)
11737e911b15Skarels 			+ (mfpr(SBR) | 0x80000000));
11747881ece5Smarc 		/*
11757881ece5Smarc 		 * allow user write to 1K event queue
11767881ece5Smarc 		 */
11777881ece5Smarc 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; ptep++;
11787e911b15Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
11797e911b15Skarels 		mtpr(TBIA, 0);			/* clr CPU translation buf */
11807881ece5Smarc 		/*
11817881ece5Smarc 		 * return event queue address
11827881ece5Smarc 		 */
11837e911b15Skarels 		*(int *)datap = (int)eq_header[unit];
11847e911b15Skarels 		break;
11857e911b15Skarels 
11867e911b15Skarels 	case QD_PRGKBD:
1187b2b69f49Smarc 		/*
1188b2b69f49Smarc 		* pass caller's programming commands to LK201
1189b2b69f49Smarc 		*/
11907e911b15Skarels 		duart = (struct duart *)qdmap[unit].duart;
11917e911b15Skarels 		cmdbuf = (struct prgkbd *)datap;    /* pnt to kbd cmd buf */
1192b2b69f49Smarc 		/*
1193b2b69f49Smarc 		* send command
1194b2b69f49Smarc 		*/
11957e911b15Skarels 		for (i = 1000; i > 0; --i) {
11967881ece5Smarc 			if (duart->statusA&XMT_RDY) {
11977e911b15Skarels 				duart->dataA = cmdbuf->cmd;
11987e911b15Skarels 				break;
11997e911b15Skarels 			}
12007e911b15Skarels 		}
12017e911b15Skarels 		if (i == 0) {
12027881ece5Smarc 			printf("qd%d: qdioctl: timeout on XMT_RDY [1]\n", unit);
12037e911b15Skarels 			break;
12047e911b15Skarels 		}
1205b2b69f49Smarc 		/*
1206b2b69f49Smarc 		* send param1?
1207b2b69f49Smarc 		*/
12087e911b15Skarels 		if (cmdbuf->cmd & LAST_PARAM)
12097e911b15Skarels 			break;
12107e911b15Skarels 		for (i = 1000; i > 0; --i) {
12117881ece5Smarc 			if (duart->statusA&XMT_RDY) {
12127e911b15Skarels 				duart->dataA = cmdbuf->param1;
12137e911b15Skarels 				break;
12147e911b15Skarels 			}
12157e911b15Skarels 		}
12167e911b15Skarels 		if (i == 0) {
12177881ece5Smarc 			printf("qd%d: qdioctl: timeout on XMT_RDY [2]\n", unit);
12187e911b15Skarels 			break;
12197e911b15Skarels 		}
1220b2b69f49Smarc 		/*
1221b2b69f49Smarc 		* send param2?
1222b2b69f49Smarc 		*/
12237e911b15Skarels 		if (cmdbuf->param1 & LAST_PARAM)
12247e911b15Skarels 		    break;
12257e911b15Skarels 		for (i = 1000; i > 0; --i) {
12267881ece5Smarc 			if (duart->statusA&XMT_RDY) {
12277e911b15Skarels 				duart->dataA = cmdbuf->param2;
12287e911b15Skarels 				break;
12297e911b15Skarels 			}
12307e911b15Skarels 		}
12317e911b15Skarels 		if (i == 0) {
12327881ece5Smarc 			printf("qd%d: qdioctl: timeout on XMT_RDY [3]\n", unit);
12337e911b15Skarels 			break;
12347e911b15Skarels 		}
12357e911b15Skarels 		break;
12367e911b15Skarels 
12377e911b15Skarels 	case QD_PRGMOUSE:
1238b2b69f49Smarc 		/*
1239b2b69f49Smarc 		* pass caller's programming commands to the mouse
1240b2b69f49Smarc 		*/
12417e911b15Skarels 		duart = (struct duart *) qdmap[unit].duart;
12427e911b15Skarels 		for (i = 1000; i > 0; --i) {
12437881ece5Smarc 			if (duart->statusB&XMT_RDY) {
12447e911b15Skarels 				duart->dataB = *datap;
12457e911b15Skarels 				break;
12467e911b15Skarels 			}
12477e911b15Skarels 		}
12487e911b15Skarels 		if (i == 0) {
12497881ece5Smarc 			printf("qd%d: qdioctl: timeout on XMT_RDY [4]\n", unit);
12507e911b15Skarels 		}
12517e911b15Skarels 		break;
12527e911b15Skarels 
12537e911b15Skarels 	case QD_RDCONFIG:
1254b2b69f49Smarc 		/*
1255b2b69f49Smarc 		* get QDSS configuration word and return it
1256b2b69f49Smarc 		*/
12577e911b15Skarels 		*(short *)datap = qdflags[unit].config;
12587e911b15Skarels 		break;
12597e911b15Skarels 
1260e977faadSmarc 	case QD_KERN_LOOP:
1261e977faadSmarc 	case QD_KERN_UNLOOP:
1262b2b69f49Smarc 		/*
1263b2b69f49Smarc 		 * vestige from ultrix.  BSD uses TIOCCONS to redirect
1264b2b69f49Smarc 		 * kernel console output.
1265b2b69f49Smarc 		 */
1266e977faadSmarc 		break;
1267e977faadSmarc 
12687e911b15Skarels 	case QD_PRGTABLET:
1269b2b69f49Smarc 		/*
1270b2b69f49Smarc 		* program the tablet
1271b2b69f49Smarc 		*/
12727e911b15Skarels 		duart = (struct duart *) qdmap[unit].duart;
12737e911b15Skarels 		for (i = 1000; i > 0; --i) {
12747881ece5Smarc 			if (duart->statusB&XMT_RDY) {
12757e911b15Skarels 				duart->dataB = *datap;
12767e911b15Skarels 				break;
12777e911b15Skarels 			}
12787e911b15Skarels 		}
12797e911b15Skarels 		if (i == 0) {
12807881ece5Smarc 			printf("qd%d: qdioctl: timeout on XMT_RDY [5]\n", unit);
12817e911b15Skarels 		}
12827e911b15Skarels 		break;
12837e911b15Skarels 
12847e911b15Skarels 	case QD_PRGTABRES:
1285b2b69f49Smarc 		/*
1286b2b69f49Smarc 		* program the tablet report resolution factor
1287b2b69f49Smarc 		*/
12887e911b15Skarels 		qdflags[unit].tab_res = *(short *)datap;
12897e911b15Skarels 		break;
12908a2bf9b0Smarc 
12917e911b15Skarels 	default:
1292b2b69f49Smarc 		/*
1293b2b69f49Smarc 		* service tty ioctl's
1294b2b69f49Smarc 		*/
12957e911b15Skarels 		if (!(minor_dev & 0x02)) {
12967e911b15Skarels 			tp = &qd_tty[minor_dev];
1297b2b69f49Smarc 			error =
1298b2b69f49Smarc 			   (*linesw[tp->t_line].l_ioctl)(tp, cmd, datap, flags);
12997e911b15Skarels 			if (error >= 0) {
13007e911b15Skarels 				return(error);
13017e911b15Skarels 			}
13027e911b15Skarels 			error = ttioctl(tp, cmd, datap, flags);
13037e911b15Skarels 			if (error >= 0) {
13047e911b15Skarels 				return(error);
13057e911b15Skarels 			}
13067e911b15Skarels 		}
13077e911b15Skarels 		break;
13087e911b15Skarels 	}
13097e911b15Skarels 
13107e911b15Skarels 	return(0);
13117e911b15Skarels 
13127e911b15Skarels } /* qdioctl */
13137e911b15Skarels 
qdselect(dev,rw)13147e911b15Skarels qdselect(dev, rw)
13157e911b15Skarels 	dev_t dev;
13167e911b15Skarels 	int rw;
13177e911b15Skarels {
13187881ece5Smarc 	register s;
13197881ece5Smarc 	register unit;
1320e977faadSmarc 	register struct tty *tp;
1321e977faadSmarc 	u_int minor_dev = minor(dev);
13227e911b15Skarels 
1323e977faadSmarc 	s = spl5();
1324e977faadSmarc 	unit = minor_dev >> 2;
13257e911b15Skarels 
13267e911b15Skarels 	switch (rw) {
1327e977faadSmarc 	case FREAD:
1328b2b69f49Smarc 		if ((minor_dev & 0x03) == 2) {
1329e977faadSmarc 			/*
1330e977faadSmarc 			* this is a graphics device, so check for events
1331e977faadSmarc 			*/
13327881ece5Smarc 			if(!(ISEMPTY(eq_header[unit]))) {
13337e911b15Skarels 				splx(s);
1334e977faadSmarc 				return(1);
13357e911b15Skarels 			}
13367881ece5Smarc 			qdrsel[unit] = u.u_procp;
13377e911b15Skarels 			qdflags[unit].selmask |= SEL_READ;
13387e911b15Skarels 			splx(s);
13397e911b15Skarels 			return(0);
1340b2b69f49Smarc 		} else {
1341e977faadSmarc 			/*
1342e977faadSmarc 			* this is a tty device
1343e977faadSmarc 			*/
1344e977faadSmarc 			tp = &qd_tty[minor_dev];
1345e977faadSmarc 			if (ttnread(tp))
1346e977faadSmarc 			    return(1);
1347e977faadSmarc 			tp->t_rsel = u.u_procp;
13487e911b15Skarels 			splx(s);
1349e977faadSmarc 			return(0);
1350e977faadSmarc 		}
1351e977faadSmarc 
1352e977faadSmarc 	case FWRITE:
1353b2b69f49Smarc 		if ((minor(dev) & 0x03) == 2) {
1354e977faadSmarc 			/*
1355e977faadSmarc 			* this is a graphics device, so check for dma buffers
1356e977faadSmarc 			*/
1357e977faadSmarc 			if (DMA_ISEMPTY(DMAheader[unit]))
1358e977faadSmarc 			    {
1359e977faadSmarc 				splx(s);
1360e977faadSmarc 				return(1);
13617e911b15Skarels 			}
13627881ece5Smarc 			qdrsel[unit] = u.u_procp;
13637e911b15Skarels 			qdflags[unit].selmask |= SEL_WRITE;
13647e911b15Skarels 			splx(s);
13657e911b15Skarels 			return(0);
1366b2b69f49Smarc 		} else {
1367e977faadSmarc 			/*
1368e977faadSmarc 			* this is a tty device
1369e977faadSmarc 			*/
1370e977faadSmarc 			tp = &qd_tty[minor_dev];
1371f5319004Smarc 			if (tp->t_outq.c_cc <= tp->t_lowat)
1372e977faadSmarc 			    return(1);
1373e977faadSmarc 			tp->t_wsel = u.u_procp;
1374e977faadSmarc 			splx(s);
1375e977faadSmarc 			return(0);
1376e977faadSmarc 		}
1377e977faadSmarc 	}
13787881ece5Smarc 	splx(s);
13797881ece5Smarc 	return(0);
13807e911b15Skarels 
13817e911b15Skarels } /* qdselect() */
13827e911b15Skarels 
13837e911b15Skarels extern qd_strategy();
13847e911b15Skarels 
qdwrite(dev,uio)13857e911b15Skarels qdwrite(dev, uio)
13867e911b15Skarels 	dev_t dev;
13877e911b15Skarels 	struct uio *uio;
13887e911b15Skarels {
13897e911b15Skarels 	register struct tty *tp;
13907881ece5Smarc 	register minor_dev;
13917881ece5Smarc 	register unit;
13927e911b15Skarels 
13937e911b15Skarels 	minor_dev = minor(dev);
13947e911b15Skarels 	unit = (minor_dev >> 2) & 0x07;
13957e911b15Skarels 
1396b2b69f49Smarc 	if (((minor_dev&0x03) != 0x02) && (qdflags[unit].inuse&CONS_DEV)) {
1397b2b69f49Smarc 		/*
1398b2b69f49Smarc 		* this is the console...
1399b2b69f49Smarc 		*/
14007e911b15Skarels 		tp = &qd_tty[minor_dev];
14017e911b15Skarels 		return ((*linesw[tp->t_line].l_write)(tp, uio));
1402b2b69f49Smarc 	} else if (qdflags[unit].inuse & GRAPHIC_DEV) {
1403b2b69f49Smarc 		/*
1404b2b69f49Smarc 		* this is a DMA xfer from user space
1405b2b69f49Smarc 		*/
14067e911b15Skarels 		return (physio(qd_strategy, &qdbuf[unit],
14077e911b15Skarels 		dev, B_WRITE, minphys, uio));
14087e911b15Skarels 	}
14097881ece5Smarc 	return (ENXIO);
14107e911b15Skarels }
14117e911b15Skarels 
qdread(dev,uio)14127e911b15Skarels qdread(dev, uio)
14137e911b15Skarels 	dev_t dev;
14147e911b15Skarels 	struct uio *uio;
14157e911b15Skarels {
14167e911b15Skarels 	register struct tty *tp;
14177881ece5Smarc 	register minor_dev;
14187881ece5Smarc 	register unit;
14197e911b15Skarels 
14207e911b15Skarels 	minor_dev = minor(dev);
14217e911b15Skarels 	unit = (minor_dev >> 2) & 0x07;
14227e911b15Skarels 
1423b2b69f49Smarc 	if ((minor_dev & 0x03) != 0x02 && qdflags[unit].inuse & CONS_DEV) {
1424b2b69f49Smarc 		/*
1425b2b69f49Smarc 		* this is the console
1426b2b69f49Smarc 		*/
14277e911b15Skarels 		tp = &qd_tty[minor_dev];
14287e911b15Skarels 		return ((*linesw[tp->t_line].l_read)(tp, uio));
1429b2b69f49Smarc 	} else if (qdflags[unit].inuse & GRAPHIC_DEV) {
1430b2b69f49Smarc 		/*
1431b2b69f49Smarc 		* this is a bitmap-to-processor xfer
1432b2b69f49Smarc 		*/
14337e911b15Skarels 		return (physio(qd_strategy, &qdbuf[unit],
14347e911b15Skarels 		dev, B_READ, minphys, uio));
14357e911b15Skarels 	}
14367881ece5Smarc 	return (ENXIO);
14377e911b15Skarels }
14387e911b15Skarels 
14397e911b15Skarels /***************************************************************
14407e911b15Skarels *
14417e911b15Skarels *	qd_strategy()... strategy routine to do DMA
14427e911b15Skarels *
14437e911b15Skarels ***************************************************************/
14447e911b15Skarels 
qd_strategy(bp)14457e911b15Skarels qd_strategy(bp)
14467e911b15Skarels 	register struct buf *bp;
14477e911b15Skarels {
14487e911b15Skarels 	register struct dga *dga;
14497e911b15Skarels 	register struct adder *adder;
14507881ece5Smarc 	register unit;
14517e911b15Skarels 	int QBAreg;
14527e911b15Skarels 	int s;
14537e911b15Skarels 	int cookie;
14547e911b15Skarels 
14557e911b15Skarels 	unit = (minor(bp->b_dev) >> 2) & 0x07;
14567e911b15Skarels 
1457b2b69f49Smarc 	/*
1458b2b69f49Smarc 	* init pointers
1459b2b69f49Smarc 	*/
14607e911b15Skarels 	if ((QBAreg = ubasetup(0, bp, 0)) == 0) {
14617881ece5Smarc 		printf("qd%d: qd_strategy: QBA setup error\n", unit);
14627e911b15Skarels 		goto STRAT_ERR;
14637e911b15Skarels 	}
14647e911b15Skarels 	dga = (struct dga *) qdmap[unit].dga;
1465e977faadSmarc 	s = spl5();
14667e911b15Skarels 	qdflags[unit].user_dma = -1;
14677e911b15Skarels 	dga->csr |= DMA_IE;
14687e911b15Skarels 	cookie = QBAreg & 0x3FFFF;
14697e911b15Skarels 	dga->adrs_lo = (short) cookie;
14707e911b15Skarels 	dga->adrs_hi = (short) (cookie >> 16);
14717e911b15Skarels 	dga->bytcnt_lo = (short) bp->b_bcount;
14727e911b15Skarels 	dga->bytcnt_hi = (short) (bp->b_bcount >> 16);
14737e911b15Skarels 
14747e911b15Skarels 	while (qdflags[unit].user_dma) {
14757e911b15Skarels 		sleep((caddr_t)&qdflags[unit].user_dma, QDPRIOR);
14767e911b15Skarels 	}
14777e911b15Skarels 	splx(s);
14787e911b15Skarels 	ubarelse(0, &QBAreg);
14797e911b15Skarels 	if (!(dga->csr & DMA_ERR)) {
14807e911b15Skarels 		iodone(bp);
14817e911b15Skarels 		return;
14827e911b15Skarels 	}
14837e911b15Skarels 
14847e911b15Skarels STRAT_ERR:
14857e911b15Skarels 	adder = (struct adder *) qdmap[unit].adder;
14867e911b15Skarels 	adder->command = CANCEL;	/* cancel adder activity */
14877e911b15Skarels 	dga->csr &= ~DMA_IE;
14887e911b15Skarels 	dga->csr &= ~0x0600;		/* halt DMA (reset fifo) */
14897e911b15Skarels 	dga->csr |= DMA_ERR;		/* clear error condition */
14907e911b15Skarels 	bp->b_flags |= B_ERROR; 	/* flag an error to physio() */
14917e911b15Skarels 
1492b2b69f49Smarc 	/*
1493b2b69f49Smarc 	 * if DMA was running, flush spurious intrpt
1494b2b69f49Smarc 	 */
14957e911b15Skarels 	if (dga->bytcnt_lo != 0) {
14967e911b15Skarels 		dga->bytcnt_lo = 0;
14977e911b15Skarels 		dga->bytcnt_hi = 0;
14987e911b15Skarels 		DMA_SETIGNORE(DMAheader[unit]);
14997e911b15Skarels 		dga->csr |= DMA_IE;
15007e911b15Skarels 	}
15017e911b15Skarels 	iodone(bp);
15027e911b15Skarels 
15037e911b15Skarels } /* qd_strategy */
15047e911b15Skarels 
15057881ece5Smarc /*
15067881ece5Smarc  *  Start output to the console screen
15077881ece5Smarc  */
qdstart(tp)15087e911b15Skarels qdstart(tp)
15097e911b15Skarels 	register struct tty *tp;
15107e911b15Skarels {
15117881ece5Smarc 	register which_unit, unit, c;
15127e911b15Skarels 	int s;
15137e911b15Skarels 
1514e977faadSmarc 	unit = minor(tp->t_dev);
1515e977faadSmarc 	which_unit = (unit >> 2) & 0x3;
1516e977faadSmarc 	unit &= 0x03;
1517e977faadSmarc 
1518e977faadSmarc 	s = spl5();
1519e977faadSmarc 
1520b2b69f49Smarc 	/*
1521b2b69f49Smarc 	* If it's currently active, or delaying, no need to do anything.
1522b2b69f49Smarc 	*/
15237e911b15Skarels 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
15247e911b15Skarels 		goto out;
15257e911b15Skarels 
1526b2b69f49Smarc 	/*
1527b2b69f49Smarc 	* Display chars until the queue is empty.
1528b2b69f49Smarc 	* Drop input from anything but the console
1529b2b69f49Smarc 	* device on the floor.
1530b2b69f49Smarc 	*
1531b2b69f49Smarc 	* XXX - this loop is done at spltty.
1532b2b69f49Smarc 	*
1533b2b69f49Smarc 	*/
15347e911b15Skarels 	while (tp->t_outq.c_cc) {
15357e911b15Skarels 		c = getc(&tp->t_outq);
1536e977faadSmarc 		if (unit == 0)
15377881ece5Smarc 			blitc(which_unit, (u_char)c);
15387e911b15Skarels 	}
1539b2b69f49Smarc 	/*
1540e977faadSmarc 	* If there are sleepers, and output has drained below low
1541b2b69f49Smarc 	* water mark, wake up the sleepers.
1542b2b69f49Smarc 	*/
1543f5319004Smarc 	if (tp->t_outq.c_cc <= tp->t_lowat) {
15447e911b15Skarels 		if (tp->t_state & TS_ASLEEP){
15457e911b15Skarels 			tp->t_state &= ~TS_ASLEEP;
15467e911b15Skarels 			wakeup((caddr_t) &tp->t_outq);
15477e911b15Skarels 		}
1548e977faadSmarc 	}
1549e977faadSmarc 
1550e977faadSmarc 	tp->t_state &= ~TS_BUSY;
15517e911b15Skarels 
15527e911b15Skarels out:
15537e911b15Skarels 	splx(s);
15547e911b15Skarels 
15557e911b15Skarels } /* qdstart */
15567e911b15Skarels 
15577881ece5Smarc /*ARGSUSED*/
qdstop(tp,flag)15587e911b15Skarels qdstop(tp, flag)
15597e911b15Skarels 	register struct tty *tp;
15607e911b15Skarels 	int flag;
15617e911b15Skarels {
15627e911b15Skarels 	register int s;
15637e911b15Skarels 
1564e977faadSmarc 	s = spl5();	/* block intrpts during state modification */
15657881ece5Smarc 	if (tp->t_state & TS_BUSY)
15667881ece5Smarc 		if ((tp->t_state & TS_TTSTOP) == 0)
15677e911b15Skarels 			tp->t_state |= TS_FLUSH;
1568b2b69f49Smarc 		else
15697e911b15Skarels 			tp->t_state &= ~TS_BUSY;
15707e911b15Skarels 	splx(s);
15717e911b15Skarels }
15727e911b15Skarels 
15737881ece5Smarc /*
15747881ece5Smarc  *  Output a character to the QDSS screen
15757881ece5Smarc  */
15767e911b15Skarels 
blitc(unit,chr)15777e911b15Skarels blitc(unit, chr)
15787881ece5Smarc 	register unit;
15797881ece5Smarc 	register u_char chr;
15807e911b15Skarels {
15817e911b15Skarels 	register struct adder *adder;
15827e911b15Skarels 	register struct dga *dga;
15837e911b15Skarels 	register int i;
1584b2b69f49Smarc 	int nograph = !(qdflags[unit].inuse&GRAPHIC_DEV);
1585b2b69f49Smarc 	static short inescape[NQD];
15867e911b15Skarels 
15877e911b15Skarels 	adder = (struct adder *)qdmap[unit].adder;
15887e911b15Skarels 	dga = (struct dga *) qdmap[unit].dga;
1589b2b69f49Smarc 	/*
1590b2b69f49Smarc 	 * BSD comment: this (&=0177) defeats the extended character
1591b2b69f49Smarc 	 * set code for the glass tty, but if i had the time i would
1592b2b69f49Smarc 	 * spend it ripping out the code completely.  This driver
1593b2b69f49Smarc 	 * is too big for its own good.
1594b2b69f49Smarc 	 */
1595b2b69f49Smarc 	chr &= 0177;
1596b2b69f49Smarc 	/*
15977881ece5Smarc 	 * Cursor addressing (so vi will work).
1598b2b69f49Smarc 	 * Decode for "\E=%.%." cursor motion description.
15997881ece5Smarc 	 * Corresponds to type "qdcons" in /etc/termcap:
1600b2b69f49Smarc 	 *
1601b2b69f49Smarc 	 *    qd|qdss|qdcons|qdss glass tty (4.4 BSD):\
1602b2b69f49Smarc 	 *      :am:do=^J:le=^H:bs:cm=\E=%.%.:cl=1^Z:co#128:li#57::nd=^L:up=^K:
1603b2b69f49Smarc 	 *
1604b2b69f49Smarc 	 */
1605b2b69f49Smarc 	if (inescape[unit] && nograph) {
1606b2b69f49Smarc 		switch (inescape[unit]++) {
1607b2b69f49Smarc 		case 1:
1608b2b69f49Smarc 			if (chr != '=') {
1609b2b69f49Smarc 				/* abort escape sequence */
1610b2b69f49Smarc 				inescape[unit] = 0;
1611b2b69f49Smarc 				blitc(unit, chr);
1612b2b69f49Smarc 			}
16137881ece5Smarc 			return;
1614b2b69f49Smarc 		case 2:
1615b2b69f49Smarc 			/* position row */
1616b2b69f49Smarc 			cursor[unit].y = CHAR_HEIGHT * chr;
1617b2b69f49Smarc 			if (cursor[unit].y > 863 - CHAR_HEIGHT)
1618b2b69f49Smarc 				cursor[unit].y = 863 - CHAR_HEIGHT;
1619b2b69f49Smarc 			dga->y_cursor = TRANY(cursor[unit].y);
16207881ece5Smarc 			return;
1621b2b69f49Smarc 		case 3:
1622b2b69f49Smarc 			/* position column */
1623b2b69f49Smarc 			cursor[unit].x = CHAR_WIDTH * chr;
1624b2b69f49Smarc 			if (cursor[unit].x > 1024 - CHAR_WIDTH)
1625b2b69f49Smarc 				cursor[unit].x = 1023 - CHAR_WIDTH;
1626b2b69f49Smarc 			dga->x_cursor = TRANX(cursor[unit].x);
1627b2b69f49Smarc 			inescape[unit] = 0;
16287881ece5Smarc 			return;
1629b2b69f49Smarc 		default:
1630b2b69f49Smarc 			inescape[unit] = 0;
1631b2b69f49Smarc 			blitc(unit, chr);
1632b2b69f49Smarc 		}
1633b2b69f49Smarc 	}
163424f67f6bSmarc 
16357e911b15Skarels 	switch (chr) {
16367e911b15Skarels 	case '\r':			/* return char */
16377e911b15Skarels 		cursor[unit].x = 0;
1638b2b69f49Smarc 		if (nograph)
16397e911b15Skarels 			dga->x_cursor = TRANX(cursor[unit].x);
16407881ece5Smarc 		return;
16417e911b15Skarels 
16427e911b15Skarels 	case '\t':			/* tab char */
16437e911b15Skarels 		for (i = 8 - ((cursor[unit].x >> 3) & 0x07); i > 0; --i) {
16447e911b15Skarels 			blitc(unit, ' ');
16457e911b15Skarels 		}
16467881ece5Smarc 		return;
16477e911b15Skarels 
16487e911b15Skarels 	case '\n':			/* line feed char */
16497e911b15Skarels 		if ((cursor[unit].y += CHAR_HEIGHT) > (863 - CHAR_HEIGHT)) {
1650b2b69f49Smarc 			if (nograph) {
16517e911b15Skarels 				cursor[unit].y -= CHAR_HEIGHT;
16527e911b15Skarels 				scroll_up(adder);
1653b2b69f49Smarc 			} else
1654b2b69f49Smarc 				cursor[unit].y = 0;
16557e911b15Skarels 		}
1656b2b69f49Smarc 		if (nograph)
16577e911b15Skarels 			dga->y_cursor = TRANY(cursor[unit].y);
16587881ece5Smarc 		return;
16597e911b15Skarels 
16607e911b15Skarels 	case '\b':			/* backspace char */
16617e911b15Skarels 		if (cursor[unit].x > 0) {
16627e911b15Skarels 			cursor[unit].x -= CHAR_WIDTH;
1663b2b69f49Smarc 			if (nograph)
1664b2b69f49Smarc 				dga->x_cursor = TRANX(cursor[unit].x);
1665b2b69f49Smarc 		}
16667881ece5Smarc 		return;
1667b2b69f49Smarc 	case CTRL('k'):		/* cursor up */
1668b2b69f49Smarc 		if (nograph && cursor[unit].y > 0) {
1669b2b69f49Smarc 			cursor[unit].y -= CHAR_HEIGHT;
1670b2b69f49Smarc 			dga->y_cursor = TRANY(cursor[unit].y);
1671b2b69f49Smarc 		}
16727881ece5Smarc 		return;
1673b2b69f49Smarc 
1674b2b69f49Smarc 	case CTRL('^'):		/* home cursor */
1675b2b69f49Smarc 		if (nograph) {
1676b2b69f49Smarc 			cursor[unit].x = 0;
1677b2b69f49Smarc 			dga->x_cursor = TRANX(cursor[unit].x);
1678b2b69f49Smarc 			cursor[unit].y = 0;
1679b2b69f49Smarc 			dga->y_cursor = TRANY(cursor[unit].y);
1680b2b69f49Smarc 		}
16817881ece5Smarc 		return;
1682b2b69f49Smarc 
1683b2b69f49Smarc 	case CTRL('l'):		/* cursor right */
1684b2b69f49Smarc 		if (nograph && cursor[unit].x < 1023 - CHAR_WIDTH) {
1685b2b69f49Smarc 			cursor[unit].x += CHAR_WIDTH;
16867e911b15Skarels 			dga->x_cursor = TRANX(cursor[unit].x);
16877e911b15Skarels 		}
16887881ece5Smarc 		return;
16897e911b15Skarels 
1690b2b69f49Smarc 	case CTRL('z'):		/* clear screen */
1691b2b69f49Smarc 		if (nograph) {
1692b2b69f49Smarc 			setup_dragon(unit);
1693b2b69f49Smarc 			clear_qd_screen(unit);
1694b2b69f49Smarc 			/* home cursor - termcap seems to assume this */
1695b2b69f49Smarc 			cursor[unit].x = 0;
1696b2b69f49Smarc 			dga->x_cursor = TRANX(cursor[unit].x);
1697b2b69f49Smarc 			cursor[unit].y = 0;
1698b2b69f49Smarc 			dga->y_cursor = TRANY(cursor[unit].y);
1699b2b69f49Smarc 		}
17007881ece5Smarc 		return;
1701e977faadSmarc 
1702b2b69f49Smarc 	case '\033':		/* start escape sequence */
1703b2b69f49Smarc 		if (nograph)
1704b2b69f49Smarc 			inescape[unit] = 1;
17057881ece5Smarc 		return;
1706b2b69f49Smarc 
1707b2b69f49Smarc 	default:
1708b2b69f49Smarc 		if ((chr < ' ') || (chr > '~'))
17097881ece5Smarc 			return;
17107e911b15Skarels 	}
1711b2b69f49Smarc 	/*
1712b2b69f49Smarc 	 * setup VIPER operand control registers
1713b2b69f49Smarc 	 */
17147e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0001);  /* select plane #0 */
17157e911b15Skarels 	write_ID(adder, SRC1_OCR_B,
17167e911b15Skarels 	EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY);
17177e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x00FE);  /* select other planes */
17187e911b15Skarels 	write_ID(adder, SRC1_OCR_B,
17197e911b15Skarels 	EXT_SOURCE | INT_NONE | NO_ID | BAR_SHIFT_DELAY);
17207e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x00FF);  /* select all planes */
17217e911b15Skarels 	write_ID(adder, DST_OCR_B,
17227e911b15Skarels 	EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
17237e911b15Skarels 	write_ID(adder, MASK_1, 0xFFFF);
17247e911b15Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 1);
17257e911b15Skarels 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
1726e977faadSmarc 	adder->x_clip_min = 0;
1727e977faadSmarc 	adder->x_clip_max = 1024;
1728e977faadSmarc 	adder->y_clip_min = 0;
1729e977faadSmarc 	adder->y_clip_max = 864;
1730b2b69f49Smarc 	/*
1731b2b69f49Smarc 	 * load DESTINATION origin and vectors
1732b2b69f49Smarc 	 */
17337e911b15Skarels 	adder->fast_dest_dy = 0;
17347e911b15Skarels 	adder->slow_dest_dx = 0;
17357e911b15Skarels 	adder->error_1 = 0;
17367e911b15Skarels 	adder->error_2 = 0;
17377e911b15Skarels 	adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL;
17387881ece5Smarc 	(void)wait_status(adder, RASTEROP_COMPLETE);
17397e911b15Skarels 	adder->destination_x = cursor[unit].x;
17407e911b15Skarels 	adder->fast_dest_dx = CHAR_WIDTH;
17417e911b15Skarels 	adder->destination_y = cursor[unit].y;
17427e911b15Skarels 	adder->slow_dest_dy = CHAR_HEIGHT;
1743b2b69f49Smarc 	/*
1744b2b69f49Smarc 	 * load SOURCE origin and vectors
1745b2b69f49Smarc 	 */
1746e977faadSmarc 	if ((chr - ' ') > (CHARS - 1))  {
1747e977faadSmarc 		printf("Invalid character (x)%x in blitc\n",chr);
1748e977faadSmarc 		chr = ' ';
1749e977faadSmarc 	}
1750b2b69f49Smarc 	/*
1751b2b69f49Smarc 	 * X position is modulo the number of characters per line
1752b2b69f49Smarc 	 */
1753e977faadSmarc 	adder->source_1_x = FONT_X +
1754e977faadSmarc 	    (((chr - ' ') % (MAX_SCREEN_X/CHAR_WIDTH)) * CHAR_WIDTH);
1755b2b69f49Smarc 	/*
1756b2b69f49Smarc 	 * Point to either first or second row
1757b2b69f49Smarc 	 */
1758e977faadSmarc 	adder->source_1_y = 2048 - 15 *
1759e977faadSmarc 	    (((chr - ' ')/(MAX_SCREEN_X/CHAR_WIDTH)) + 1);
17607e911b15Skarels 	adder->source_1_dx = CHAR_WIDTH;
17617e911b15Skarels 	adder->source_1_dy = CHAR_HEIGHT;
17627e911b15Skarels 	write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
17637e911b15Skarels 	adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE;
1764b2b69f49Smarc 	/*
1765b2b69f49Smarc 	 * update console cursor coordinates
1766b2b69f49Smarc 	 */
17677e911b15Skarels 	cursor[unit].x += CHAR_WIDTH;
1768b2b69f49Smarc 	if (nograph)
17697e911b15Skarels 		dga->x_cursor = TRANX(cursor[unit].x);
17707e911b15Skarels 	if (cursor[unit].x > (1024 - CHAR_WIDTH)) {
17717e911b15Skarels 		blitc(unit, '\r');
17727e911b15Skarels 		blitc(unit, '\n');
17737e911b15Skarels 	}
17747e911b15Skarels 
17757e911b15Skarels } /* blitc */
17767e911b15Skarels 
qdreset()17777881ece5Smarc qdreset() { }
17787e911b15Skarels 
17797881ece5Smarc /*
1780b2b69f49Smarc  *  INTERRUPT SERVICE ROUTINES
17817881ece5Smarc  */
17827e911b15Skarels 
17837881ece5Smarc /*
17847881ece5Smarc  *  Service "DMA DONE" interrupt condition
17857881ece5Smarc  */
qddint(qd)17867e911b15Skarels qddint(qd)
17877881ece5Smarc 	register qd;
17887e911b15Skarels {
17897e911b15Skarels 	register struct DMAreq_header *header;
17907e911b15Skarels 	register struct DMAreq *request;
17917e911b15Skarels 	register struct dga *dga;
17927e911b15Skarels 	struct adder *adder;
17937e911b15Skarels 	int cookie;			/* DMA adrs for QDSS */
17947e911b15Skarels 
17957881ece5Smarc 	(void)spl4(); 			/* allow interval timer in */
17967e911b15Skarels 
1797b2b69f49Smarc 	/*
1798b2b69f49Smarc 	* init pointers
1799b2b69f49Smarc 	*/
18007e911b15Skarels 	header = DMAheader[qd]; 	    /* register for optimization */
18017e911b15Skarels 	dga = (struct dga *) qdmap[qd].dga;
18027e911b15Skarels 	adder = (struct adder *) qdmap[qd].adder;
18037e911b15Skarels 
1804b2b69f49Smarc 	/*
1805b2b69f49Smarc 	* if this interrupt flagged as bogus for interrupt flushing purposes..
1806b2b69f49Smarc 	*/
18077e911b15Skarels 	if (DMA_ISIGNORE(header)) {
18087e911b15Skarels 		DMA_CLRIGNORE(header);
18097e911b15Skarels 		return;
18107e911b15Skarels 	}
18117e911b15Skarels 
1812b2b69f49Smarc 	/*
1813b2b69f49Smarc 	* dump a DMA hardware error message if appropriate
1814b2b69f49Smarc 	*/
18157e911b15Skarels 	if (dga->csr & DMA_ERR) {
18167e911b15Skarels 
18177e911b15Skarels 		if (dga->csr & PARITY_ERR)
18187881ece5Smarc 		    printf("qd%d: qddint: DMA hardware parity fault.\n", qd);
18197e911b15Skarels 
18207e911b15Skarels 		if (dga->csr & BUS_ERR)
18217881ece5Smarc 		    printf("qd%d: qddint: DMA hardware bus error.\n", qd);
18227e911b15Skarels 	}
18237e911b15Skarels 
1824b2b69f49Smarc 	/*
1825b2b69f49Smarc 	* if this was a DMA from user space...
1826b2b69f49Smarc 	*/
18277e911b15Skarels 	if (qdflags[qd].user_dma) {
18287e911b15Skarels 		qdflags[qd].user_dma = 0;
18297e911b15Skarels 		wakeup((caddr_t)&qdflags[qd].user_dma);
18307e911b15Skarels 		return;
18317e911b15Skarels 	}
18327e911b15Skarels 
1833b2b69f49Smarc 	/*
1834b2b69f49Smarc 	* if we're doing DMA request queue services, field the error condition
1835b2b69f49Smarc 	*/
18367e911b15Skarels 	if (dga->csr & DMA_ERR) {
18377e911b15Skarels 
18387e911b15Skarels 		dga->csr &= ~0x0600;		/* halt DMA (reset fifo) */
18397e911b15Skarels 		dga->csr |= DMA_ERR;		/* clear error condition */
18407e911b15Skarels 		adder->command = CANCEL;	/* cancel adder activity */
18417e911b15Skarels 
18427e911b15Skarels 		DMA_SETERROR(header);	/* flag error in header status word */
18437e911b15Skarels 		DMA_CLRACTIVE(header);
18447e911b15Skarels 		header->DMAreq[header->oldest].DMAdone |= HARD_ERROR;
18457e911b15Skarels 		header->newest = header->oldest;
18467e911b15Skarels 		header->used = 0;
18477e911b15Skarels 
18487881ece5Smarc 		if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
18497881ece5Smarc 			selwakeup(qdrsel[qd], 0);
18507881ece5Smarc 			qdrsel[qd] = 0;
18517e911b15Skarels 			qdflags[qd].selmask &= ~SEL_WRITE;
18527e911b15Skarels 		}
18537e911b15Skarels 
18547e911b15Skarels 		if (dga->bytcnt_lo != 0) {
18557e911b15Skarels 			dga->bytcnt_lo = 0;
18567e911b15Skarels 			dga->bytcnt_hi = 0;
18577e911b15Skarels 			DMA_SETIGNORE(header);
18587e911b15Skarels 		}
18597e911b15Skarels 		return;
18607e911b15Skarels 	}
18617e911b15Skarels 
1862b2b69f49Smarc 	/*
1863b2b69f49Smarc 	* if the DMA request queue is now becoming non-full,
1864b2b69f49Smarc 	* wakeup "select" client.
1865b2b69f49Smarc 	*/
18667e911b15Skarels 	if (DMA_ISFULL(header)) {
18677881ece5Smarc 		if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
18687881ece5Smarc 			selwakeup(qdrsel[qd], 0);
18697881ece5Smarc 			qdrsel[qd] = 0;
18707e911b15Skarels 			qdflags[qd].selmask &= ~SEL_WRITE;
18717e911b15Skarels 		}
18727e911b15Skarels 	}
18737e911b15Skarels 
18747e911b15Skarels 	header->DMAreq[header->oldest].DMAdone |= REQUEST_DONE;
1875e977faadSmarc 	QDlast_DMAtype = header->DMAreq[header->oldest].DMAtype;
18767e911b15Skarels 
1877e977faadSmarc 	/* check for unexpected interrupt */
1878e977faadSmarc 	if (DMA_ISEMPTY(header))
18797e911b15Skarels 	    return;
18807e911b15Skarels 
18817e911b15Skarels 	DMA_GETEND(header);	/* update request queue indices */
18827e911b15Skarels 
1883b2b69f49Smarc 	/*
18847881ece5Smarc 	* if no more DMA pending, wake up "select" client and exit
18857881ece5Smarc 	*/
18867e911b15Skarels 	if (DMA_ISEMPTY(header)) {
18877e911b15Skarels 
18887881ece5Smarc 		if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
18897881ece5Smarc 			selwakeup(qdrsel[qd], 0);
18907881ece5Smarc 			qdrsel[qd] = 0;
18917e911b15Skarels 			qdflags[qd].selmask &= ~SEL_WRITE;
18927e911b15Skarels 		}
18937e911b15Skarels 
18947e911b15Skarels 		DMA_CLRACTIVE(header);  /* flag DMA done */
18957e911b15Skarels 		return;
18967e911b15Skarels 	}
18977e911b15Skarels 
1898b2b69f49Smarc 	/*
18997881ece5Smarc 	* initiate next DMA xfer
19007881ece5Smarc 	*/
19017e911b15Skarels 	request = DMA_GETBEGIN(header);
1902e977faadSmarc 	if (request->DMAtype != QDlast_DMAtype) {
1903e977faadSmarc 		dga->csr &= ~0x0600;	  /* halt DMA (reset fifo) */
1904e977faadSmarc 		adder->command = CANCEL;  /* cancel adder activity */
1905e977faadSmarc 	}
1906e977faadSmarc 
19077e911b15Skarels 
19087e911b15Skarels 	switch (request->DMAtype) {
19097e911b15Skarels 
19107e911b15Skarels 	case DISPLIST:
1911e977faadSmarc 		if (request->DMAtype != QDlast_DMAtype) {
19127e911b15Skarels 			dga->csr |= DL_ENB;
1913e977faadSmarc 			dga->csr &= ~(BTOP_ENB | BYTE_DMA);
1914e977faadSmarc 		}
19157e911b15Skarels 		break;
19167e911b15Skarels 
19177e911b15Skarels 	case PTOB:
1918e977faadSmarc 		if (request->DMAtype != QDlast_DMAtype) {
1919e977faadSmarc 			if (request->DMAdone & BYTE_PACK)
1920e977faadSmarc 			    dga->csr |= (PTOB_ENB | BYTE_DMA);
1921e977faadSmarc 			else {
19227e911b15Skarels 				dga->csr |= PTOB_ENB;
1923e977faadSmarc 				dga->csr &= ~BYTE_DMA;
1924e977faadSmarc 			}
1925e977faadSmarc 		}
19267e911b15Skarels 		break;
19277e911b15Skarels 
19287e911b15Skarels 	case BTOP:
1929e977faadSmarc 		if (request->DMAtype != QDlast_DMAtype) {
1930e977faadSmarc 			if (request->DMAdone & BYTE_PACK) {
1931e977faadSmarc 				dga->csr &= ~DL_ENB;
1932e977faadSmarc 				dga->csr |= (BTOP_ENB | BYTE_DMA);
1933e977faadSmarc 			}
1934e977faadSmarc 			else {
19357e911b15Skarels 				dga->csr |= BTOP_ENB;
1936e977faadSmarc 				dga->csr &= ~(BYTE_DMA | DL_ENB);
1937e977faadSmarc 			}
1938e977faadSmarc 		}
19397e911b15Skarels 		break;
19407e911b15Skarels 	default:
19417881ece5Smarc 		printf("qd%d: qddint: illegal DMAtype parameter.\n", qd);
19427e911b15Skarels 		DMA_CLRACTIVE(header);	/* flag DMA done */
19437e911b15Skarels 		return;
19447e911b15Skarels 	}
19457e911b15Skarels 
19467e911b15Skarels 	if (request->DMAdone & COUNT_ZERO) {
19477e911b15Skarels 		dga->csr &= ~SET_DONE_FIFO;
1948b2b69f49Smarc 	}
1949b2b69f49Smarc 	else if (request->DMAdone & FIFO_EMPTY) {
19507e911b15Skarels 		dga->csr |= SET_DONE_FIFO;
19517e911b15Skarels 	}
19527e911b15Skarels 
19537e911b15Skarels 	if (request->DMAdone & WORD_PACK)
19547e911b15Skarels 	    dga->csr &= ~BYTE_DMA;
19557e911b15Skarels 	else if (request->DMAdone & BYTE_PACK)
19567e911b15Skarels 	    dga->csr |= BYTE_DMA;
19577e911b15Skarels 
19587e911b15Skarels 	dga->csr |= DMA_IE;
1959e977faadSmarc 	QDlast_DMAtype = request->DMAtype;
19607e911b15Skarels 
19617e911b15Skarels 	cookie = ((int)request->bufp - (int)header) + (int)header->QBAreg;
19627e911b15Skarels 
19637e911b15Skarels 	dga->adrs_lo = (short) cookie;
19647e911b15Skarels 	dga->adrs_hi = (short) (cookie >> 16);
19657e911b15Skarels 
19667e911b15Skarels 	dga->bytcnt_lo = (short) request->length;
19677e911b15Skarels 	dga->bytcnt_hi = (short) (request->length >> 16);
19687e911b15Skarels 
19697e911b15Skarels 	return;
19707e911b15Skarels }
19717e911b15Skarels 
19727881ece5Smarc /*
19737881ece5Smarc  * ADDER interrupt service routine
19747881ece5Smarc  */
qdaint(qd)19757e911b15Skarels qdaint(qd)
19767881ece5Smarc 	register qd;
19777e911b15Skarels {
19787e911b15Skarels 	register struct adder *adder;
19797e911b15Skarels 	struct color_buf *cbuf;
19807e911b15Skarels 	int i;
19817e911b15Skarels 	register struct rgb *rgbp;
19827e911b15Skarels 	register short *red;
19837e911b15Skarels 	register short *green;
19847e911b15Skarels 	register short *blue;
19857e911b15Skarels 
19867881ece5Smarc 	(void)spl4(); 			/* allow interval timer in */
19877e911b15Skarels 
19887e911b15Skarels 	adder = (struct adder *) qdmap[qd].adder;
19897e911b15Skarels 
1990b2b69f49Smarc 	/*
1991b2b69f49Smarc 	* service the vertical blank interrupt (VSYNC bit) by loading
1992b2b69f49Smarc 	* any pending color map load request
1993b2b69f49Smarc 	*/
19947e911b15Skarels 	if (adder->status & VSYNC) {
19957e911b15Skarels 		adder->status &= ~VSYNC;	/* clear the interrupt */
19967e911b15Skarels 		cbuf = color_buf[qd];
19977e911b15Skarels 		if (cbuf->status & LOAD_COLOR_MAP) {
19987e911b15Skarels 
19997e911b15Skarels 			red = (short *) qdmap[qd].red;
20007e911b15Skarels 			green = (short *) qdmap[qd].green;
20017e911b15Skarels 			blue = (short *) qdmap[qd].blue;
20027e911b15Skarels 
2003b2b69f49Smarc 			for (i = cbuf->count, rgbp = cbuf->rgb;
2004b2b69f49Smarc 			     --i >= 0; rgbp++) {
20057e911b15Skarels 				red[rgbp->offset] = (short) rgbp->red;
20067e911b15Skarels 				green[rgbp->offset] = (short) rgbp->green;
20077e911b15Skarels 				blue[rgbp->offset] = (short) rgbp->blue;
20087e911b15Skarels 			}
20097e911b15Skarels 
20107e911b15Skarels 			cbuf->status &= ~LOAD_COLOR_MAP;
20117e911b15Skarels 		}
20127e911b15Skarels 	}
20137e911b15Skarels 
2014b2b69f49Smarc 	/*
2015b2b69f49Smarc 	* service the scroll interrupt (FRAME_SYNC bit)
2016b2b69f49Smarc 	*/
20177e911b15Skarels 	if (adder->status & FRAME_SYNC) {
20187e911b15Skarels 		adder->status &= ~FRAME_SYNC;	/* clear the interrupt */
20197e911b15Skarels 
20207e911b15Skarels 		if (scroll[qd]->status & LOAD_REGS) {
20217e911b15Skarels 
20227881ece5Smarc 			for (i = 1000, adder->status = 0; i > 0 &&
20237881ece5Smarc 			     !(adder->status&ID_SCROLL_READY); --i)
2024b2b69f49Smarc 			      ;
20257e911b15Skarels 
20267e911b15Skarels 			if (i == 0) {
20277881ece5Smarc 			    printf("qd%d: qdaint: timeout on ID_SCROLL_READY\n",
2028b2b69f49Smarc 				qd);
20297e911b15Skarels 				return;
20307e911b15Skarels 			}
20317e911b15Skarels 
20327e911b15Skarels 			adder->ID_scroll_data = scroll[qd]->viper_constant;
20337e911b15Skarels 			adder->ID_scroll_command = ID_LOAD | SCROLL_CONSTANT;
20347e911b15Skarels 
2035b2b69f49Smarc 			adder->y_scroll_constant =
2036b2b69f49Smarc 				scroll[qd]->y_scroll_constant;
20377e911b15Skarels 			adder->y_offset_pending = scroll[qd]->y_offset;
20387e911b15Skarels 
20397e911b15Skarels 			if (scroll[qd]->status & LOAD_INDEX) {
20407e911b15Skarels 
2041b2b69f49Smarc 				adder->x_index_pending =
2042b2b69f49Smarc 					scroll[qd]->x_index_pending;
2043b2b69f49Smarc 				adder->y_index_pending =
2044b2b69f49Smarc 					scroll[qd]->y_index_pending;
20457e911b15Skarels 			}
20467e911b15Skarels 
20477e911b15Skarels 			scroll[qd]->status = 0x00;
20487e911b15Skarels 		}
20497e911b15Skarels 	}
20507e911b15Skarels }
20517e911b15Skarels 
20527881ece5Smarc /*
20537881ece5Smarc  *  DUART input interrupt service routine
20547e911b15Skarels  *
2055b2b69f49Smarc  *  XXX - this routine should be broken out - it is essentially
2056b2b69f49Smarc  *	      straight line code.
20577881ece5Smarc  */
20587e911b15Skarels 
qdiint(qd)20597e911b15Skarels qdiint(qd)
20607881ece5Smarc 	register qd;
20617e911b15Skarels {
20627e911b15Skarels 	register struct _vs_event *event;
20637e911b15Skarels 	register struct qdinput *eqh;
20647e911b15Skarels 	struct dga *dga;
20657e911b15Skarels 	struct duart *duart;
20667e911b15Skarels 	struct mouse_report *new_rep;
20677e911b15Skarels 	struct uba_device *ui;
20687e911b15Skarels 	struct tty *tp;
2069e977faadSmarc 	u_short chr;
20707e911b15Skarels 	u_short status;
20717e911b15Skarels 	u_short data;
20727e911b15Skarels 	u_short key;
20737e911b15Skarels 	char do_wakeup = 0;		/* flag to do a select wakeup call */
20747e911b15Skarels 	char a, b, c;			/* mouse button test variables */
20757e911b15Skarels 
20767881ece5Smarc 	(void)spl4(); 			/* allow interval timer in */
20777e911b15Skarels 
20787e911b15Skarels 	eqh = eq_header[qd];		/* optimized as a register */
20797e911b15Skarels 	new_rep = &current_rep[qd];
20807e911b15Skarels 	duart = (struct duart *) qdmap[qd].duart;
20817e911b15Skarels 
2082b2b69f49Smarc 	/*
20837881ece5Smarc 	* if the graphic device is turned on..
20847881ece5Smarc 	*/
20857e911b15Skarels 	if (qdflags[qd].inuse & GRAPHIC_DEV) {
2086b2b69f49Smarc 		/*
2087b2b69f49Smarc 		* empty DUART
2088b2b69f49Smarc 		*/
20897881ece5Smarc 		while (duart->statusA&RCV_RDY || duart->statusB&RCV_RDY) {
2090b2b69f49Smarc 			/*
20917881ece5Smarc 			 * pick up LK-201 input (if any)
20927881ece5Smarc 			 */
20937881ece5Smarc 			if (duart->statusA&RCV_RDY) {
20947e911b15Skarels 
20957e911b15Skarels 				/* if error condition, then reset it */
20967e911b15Skarels 
20977881ece5Smarc 				if (duart->statusA&0x70) {
20987e911b15Skarels 					duart->cmdA = 0x40;
20997e911b15Skarels 					continue;
21007e911b15Skarels 				}
21017e911b15Skarels 
21027e911b15Skarels 				/* event queue full now? (overflow condition) */
21037e911b15Skarels 
21047e911b15Skarels 				if (ISFULL(eqh) == TRUE) {
2105b2b69f49Smarc 					printf(
21067881ece5Smarc 					 "qd%d: qdiint: event queue overflow\n",
2107b2b69f49Smarc 					   qd);
21087e911b15Skarels 					break;
21097e911b15Skarels 				}
21107e911b15Skarels 
2111b2b69f49Smarc 				/*
21127e911b15Skarels 				* Check for various keyboard errors  */
21137e911b15Skarels 
21147e911b15Skarels 				key = duart->dataA & 0xFF;
21157e911b15Skarels 
2116b2b69f49Smarc 				if (key==LK_POWER_ERROR ||
2117b2b69f49Smarc 				    key==LK_KDOWN_ERROR ||
2118b2b69f49Smarc 				    key == LK_INPUT_ERROR ||
2119b2b69f49Smarc 				    key == LK_OUTPUT_ERROR) {
2120b2b69f49Smarc 					printf(
21217881ece5Smarc 				    "qd%d: qdiint: keyboard error, code = %x\n",
2122b2b69f49Smarc 					qd,key);
21237881ece5Smarc 					return;
21247e911b15Skarels 				}
21257e911b15Skarels 
21267e911b15Skarels 				if (key < LK_LOWEST)
21277881ece5Smarc 				    return;
21287e911b15Skarels 
21297e911b15Skarels 				++do_wakeup;  /* request a select wakeup call */
21307e911b15Skarels 
21317e911b15Skarels 				event = PUTBEGIN(eqh);
21327e911b15Skarels 				PUTEND(eqh);
21337e911b15Skarels 
21347e911b15Skarels 				event->vse_key = key;
21357e911b15Skarels 				event->vse_key &= 0x00FF;
21367e911b15Skarels 				event->vse_x = eqh->curs_pos.x;
21377e911b15Skarels 				event->vse_y = eqh->curs_pos.y;
21387e911b15Skarels 				event->vse_time = TOY;
21397e911b15Skarels 				event->vse_type = VSE_BUTTON;
21407e911b15Skarels 				event->vse_direction = VSE_KBTRAW;
21417e911b15Skarels 				event->vse_device = VSE_DKB;
21427e911b15Skarels 			}
21437e911b15Skarels 
2144b2b69f49Smarc 			/*
21457e911b15Skarels 			* pick up the mouse input (if any)  */
21467e911b15Skarels 
21477e911b15Skarels 			if ((status = duart->statusB) & RCV_RDY  &&
21487e911b15Skarels 			    qdflags[qd].pntr_id == MOUSE_ID) {
21497e911b15Skarels 
21507e911b15Skarels 				if (status & 0x70) {
21517e911b15Skarels 					duart->cmdB = 0x40;
21527e911b15Skarels 					continue;
21537e911b15Skarels 				}
21547e911b15Skarels 
21557e911b15Skarels 				/* event queue full now? (overflow condition) */
21567e911b15Skarels 
21577e911b15Skarels 				if (ISFULL(eqh) == TRUE) {
2158b2b69f49Smarc 					printf(
21597881ece5Smarc 					"qd%d: qdiint: event queue overflow\n",
2160b2b69f49Smarc 					     qd);
21617e911b15Skarels 					break;
21627e911b15Skarels 				}
21637e911b15Skarels 
21647e911b15Skarels 				data = duart->dataB;      /* get report byte */
21657e911b15Skarels 				++new_rep->bytcnt; /* bump report byte count */
21667e911b15Skarels 
2167b2b69f49Smarc 				/*
21687e911b15Skarels 				* if 1st byte of report.. */
21697e911b15Skarels 
21707e911b15Skarels 				if ( data & START_FRAME) {
21717e911b15Skarels 					new_rep->state = data;
21727e911b15Skarels 					if (new_rep->bytcnt > 1) {
2173b2b69f49Smarc 						/* start of new frame */
2174b2b69f49Smarc 						new_rep->bytcnt = 1;
2175b2b69f49Smarc 						/* ..continue looking */
2176b2b69f49Smarc 						continue;
21777e911b15Skarels 					}
21787e911b15Skarels 				}
21797e911b15Skarels 
2180b2b69f49Smarc 				/*
21817e911b15Skarels 				* if 2nd byte of report.. */
21827e911b15Skarels 
21837e911b15Skarels 				else if (new_rep->bytcnt == 2) {
21847e911b15Skarels 					new_rep->dx = data & 0x00FF;
21857e911b15Skarels 				}
21867e911b15Skarels 
2187b2b69f49Smarc 				/*
21887e911b15Skarels 				* if 3rd byte of report, load input event queue */
21897e911b15Skarels 
21907e911b15Skarels 				else if (new_rep->bytcnt == 3) {
21917e911b15Skarels 
21927e911b15Skarels 					new_rep->dy = data & 0x00FF;
21937e911b15Skarels 					new_rep->bytcnt = 0;
21947e911b15Skarels 
2195b2b69f49Smarc 					/*
21967e911b15Skarels 					* if mouse position has changed.. */
21977e911b15Skarels 
21987e911b15Skarels 					if (new_rep->dx != 0  ||  new_rep->dy != 0) {
21997e911b15Skarels 
2200b2b69f49Smarc 						/*
22017e911b15Skarels 						* calculate acceleration factor, if needed	*/
22027e911b15Skarels 
22037e911b15Skarels 						if (qdflags[qd].curs_acc > ACC_OFF) {
22047e911b15Skarels 
22057e911b15Skarels 							if (qdflags[qd].curs_thr <= new_rep->dx)
22067e911b15Skarels 							    new_rep->dx +=
22077e911b15Skarels 							    (new_rep->dx - qdflags[qd].curs_thr)
22087e911b15Skarels 							    * qdflags[qd].curs_acc;
22097e911b15Skarels 
22107e911b15Skarels 							if (qdflags[qd].curs_thr <= new_rep->dy)
22117e911b15Skarels 							    new_rep->dy +=
22127e911b15Skarels 							    (new_rep->dy - qdflags[qd].curs_thr)
22137e911b15Skarels 							    * qdflags[qd].curs_acc;
22147e911b15Skarels 						}
22157e911b15Skarels 
2216b2b69f49Smarc 						/*
22177e911b15Skarels 						* update cursor position coordinates */
22187e911b15Skarels 
22197e911b15Skarels 						if (new_rep->state & X_SIGN) {
22207e911b15Skarels 							eqh->curs_pos.x += new_rep->dx;
22217e911b15Skarels 							if (eqh->curs_pos.x > 1023)
22227e911b15Skarels 							    eqh->curs_pos.x = 1023;
22237e911b15Skarels 						}
22247e911b15Skarels 						else {
22257e911b15Skarels 							eqh->curs_pos.x -= new_rep->dx;
22267e911b15Skarels 							if (eqh->curs_pos.x < -15)
22277e911b15Skarels 							    eqh->curs_pos.x = -15;
22287e911b15Skarels 						}
22297e911b15Skarels 
22307e911b15Skarels 						if (new_rep->state & Y_SIGN) {
22317e911b15Skarels 							eqh->curs_pos.y -= new_rep->dy;
22327e911b15Skarels 							if (eqh->curs_pos.y < -15)
22337e911b15Skarels 							    eqh->curs_pos.y = -15;
22347e911b15Skarels 						}
22357e911b15Skarels 						else {
22367e911b15Skarels 							eqh->curs_pos.y += new_rep->dy;
22377e911b15Skarels 							if (eqh->curs_pos.y > 863)
22387e911b15Skarels 							    eqh->curs_pos.y = 863;
22397e911b15Skarels 						}
22407e911b15Skarels 
2241b2b69f49Smarc 						/*
22427e911b15Skarels 						* update cursor screen position */
22437e911b15Skarels 
22447e911b15Skarels 						dga = (struct dga *) qdmap[qd].dga;
22457e911b15Skarels 						dga->x_cursor = TRANX(eqh->curs_pos.x);
22467e911b15Skarels 						dga->y_cursor = TRANY(eqh->curs_pos.y);
22477e911b15Skarels 
2248b2b69f49Smarc 						/*
22497e911b15Skarels 						* if cursor is in the box, no event report */
22507e911b15Skarels 
22517e911b15Skarels 						if (eqh->curs_pos.x <= eqh->curs_box.right	&&
22527e911b15Skarels 						    eqh->curs_pos.x >= eqh->curs_box.left  &&
22537e911b15Skarels 						    eqh->curs_pos.y >= eqh->curs_box.top  &&
22547e911b15Skarels 						    eqh->curs_pos.y <= eqh->curs_box.bottom ) {
22557e911b15Skarels 							goto GET_MBUTTON;
22567e911b15Skarels 						}
22577e911b15Skarels 
2258b2b69f49Smarc 						/*
22597e911b15Skarels 						* report the mouse motion event */
22607e911b15Skarels 
22617e911b15Skarels 						event = PUTBEGIN(eqh);
22627e911b15Skarels 						PUTEND(eqh);
22637e911b15Skarels 
22647e911b15Skarels 						++do_wakeup;   /* request a select wakeup call */
22657e911b15Skarels 
22667e911b15Skarels 						event->vse_x = eqh->curs_pos.x;
22677e911b15Skarels 						event->vse_y = eqh->curs_pos.y;
22687e911b15Skarels 
22697e911b15Skarels 						event->vse_device = VSE_MOUSE;  /* mouse */
22707e911b15Skarels 						event->vse_type = VSE_MMOTION;  /* pos changed */
22717e911b15Skarels 						event->vse_key = 0;
22727e911b15Skarels 						event->vse_direction = 0;
22737e911b15Skarels 						event->vse_time = TOY;	/* time stamp */
22747e911b15Skarels 					}
22757e911b15Skarels 
22767e911b15Skarels GET_MBUTTON:
2277b2b69f49Smarc 					/*
22787e911b15Skarels 					* if button state has changed */
22797e911b15Skarels 
22807e911b15Skarels 					a = new_rep->state & 0x07;    /*mask nonbutton bits */
22817e911b15Skarels 					b = last_rep[qd].state & 0x07;
22827e911b15Skarels 
22837e911b15Skarels 					if (a ^ b) {
22847e911b15Skarels 
22857e911b15Skarels 						for ( c = 1;  c < 8; c <<= 1) {
22867e911b15Skarels 
22877e911b15Skarels 							if (!( c & (a ^ b))) /* this button change? */
22887e911b15Skarels 							    continue;
22897e911b15Skarels 
22907e911b15Skarels 							/* event queue full? (overflow condition) */
22917e911b15Skarels 
22927e911b15Skarels 							if (ISFULL(eqh) == TRUE) {
22937881ece5Smarc 								printf("qd%d: qdiint: event queue overflow\n", qd);
22947e911b15Skarels 								break;
22957e911b15Skarels 							}
22967e911b15Skarels 
22977e911b15Skarels 							event = PUTBEGIN(eqh);	/* get new event */
22987e911b15Skarels 							PUTEND(eqh);
22997e911b15Skarels 
23007e911b15Skarels 							++do_wakeup;   /* request select wakeup */
23017e911b15Skarels 
23027e911b15Skarels 							event->vse_x = eqh->curs_pos.x;
23037e911b15Skarels 							event->vse_y = eqh->curs_pos.y;
23047e911b15Skarels 
23057e911b15Skarels 							event->vse_device = VSE_MOUSE;	/* mouse */
23067e911b15Skarels 							event->vse_type = VSE_BUTTON; /* new button */
23077e911b15Skarels 							event->vse_time = TOY;	      /* time stamp */
23087e911b15Skarels 
23097e911b15Skarels 							/* flag changed button and if up or down */
23107e911b15Skarels 
23117e911b15Skarels 							if (c == RIGHT_BUTTON)
23127e911b15Skarels 							    event->vse_key = VSE_RIGHT_BUTTON;
23137e911b15Skarels 							else if (c == MIDDLE_BUTTON)
23147e911b15Skarels 							    event->vse_key = VSE_MIDDLE_BUTTON;
23157e911b15Skarels 							else if (c == LEFT_BUTTON)
23167e911b15Skarels 							    event->vse_key = VSE_LEFT_BUTTON;
23177e911b15Skarels 
23187e911b15Skarels 							/* set bit = button depressed */
23197e911b15Skarels 
23207e911b15Skarels 							if (c & a)
23217e911b15Skarels 							    event->vse_direction = VSE_KBTDOWN;
23227e911b15Skarels 							else
23237e911b15Skarels 								event->vse_direction = VSE_KBTUP;
23247e911b15Skarels 						}
23257e911b15Skarels 					}
23267e911b15Skarels 
23277e911b15Skarels 					/* refresh last report */
23287e911b15Skarels 
23297e911b15Skarels 					last_rep[qd] = current_rep[qd];
23307e911b15Skarels 
23317e911b15Skarels 				}  /* get last byte of report */
23327881ece5Smarc 			} else if ((status = duart->statusB)&RCV_RDY &&
23337e911b15Skarels 			           qdflags[qd].pntr_id == TABLET_ID) {
23347881ece5Smarc 				/*
23357881ece5Smarc 				* pickup tablet input, if any
23367881ece5Smarc 				*/
23377e911b15Skarels 				if (status&0x70) {
23387e911b15Skarels 					duart->cmdB = 0x40;
23397e911b15Skarels 					continue;
23407e911b15Skarels 				}
23417881ece5Smarc 				/*
23427881ece5Smarc 				 * event queue full now? (overflow condition)
23437881ece5Smarc 				 */
23447e911b15Skarels 				if (ISFULL(eqh) == TRUE) {
23457881ece5Smarc 					printf("qd%d: qdiint: event queue overflow\n", qd);
23467e911b15Skarels 					break;
23477e911b15Skarels 				}
23487e911b15Skarels 
23497e911b15Skarels 				data = duart->dataB;      /* get report byte */
23507e911b15Skarels 				++new_rep->bytcnt;	      /* bump report byte count */
23517e911b15Skarels 
2352b2b69f49Smarc 				/*
23537e911b15Skarels 				* if 1st byte of report.. */
23547e911b15Skarels 
23557e911b15Skarels 				if (data & START_FRAME) {
23567e911b15Skarels 					new_rep->state = data;
23577e911b15Skarels 					if (new_rep->bytcnt > 1) {
23587e911b15Skarels 						new_rep->bytcnt = 1;    /* start of new frame */
23597e911b15Skarels 						continue;		    /* ..continue looking */
23607e911b15Skarels 					}
23617e911b15Skarels 				}
23627e911b15Skarels 
2363b2b69f49Smarc 				/*
23647e911b15Skarels 				* if 2nd byte of report.. */
23657e911b15Skarels 
23667e911b15Skarels 				else if (new_rep->bytcnt == 2) {
23677e911b15Skarels 					new_rep->dx = data & 0x3F;
23687e911b15Skarels 				}
23697e911b15Skarels 
2370b2b69f49Smarc 				/*
23717e911b15Skarels 				* if 3rd byte of report.. */
23727e911b15Skarels 
23737e911b15Skarels 				else if (new_rep->bytcnt == 3) {
23747e911b15Skarels 					new_rep->dx |= (data & 0x3F) << 6;
23757e911b15Skarels 				}
23767e911b15Skarels 
2377b2b69f49Smarc 				/*
23787e911b15Skarels 				* if 4th byte of report.. */
23797e911b15Skarels 
23807e911b15Skarels 				else if (new_rep->bytcnt == 4) {
23817e911b15Skarels 					new_rep->dy = data & 0x3F;
23827e911b15Skarels 				}
23837e911b15Skarels 
2384b2b69f49Smarc 				/*
23857e911b15Skarels 				* if 5th byte of report, load input event queue */
23867e911b15Skarels 
23877e911b15Skarels 				else if (new_rep->bytcnt == 5) {
23887e911b15Skarels 
23897e911b15Skarels 					new_rep->dy |= (data & 0x3F) << 6;
23907e911b15Skarels 					new_rep->bytcnt = 0;
23917e911b15Skarels 
2392b2b69f49Smarc 					/*
23937e911b15Skarels 					* update cursor position coordinates */
23947e911b15Skarels 
23957e911b15Skarels 					new_rep->dx /= qdflags[qd].tab_res;
23967e911b15Skarels 					new_rep->dy = (2200 - new_rep->dy)
23977e911b15Skarels 					    / qdflags[qd].tab_res;
23987e911b15Skarels 
23997e911b15Skarels 					if (new_rep->dx > 1023) {
24007e911b15Skarels 						new_rep->dx = 1023;
24017e911b15Skarels 					}
24027e911b15Skarels 					if (new_rep->dy > 863) {
24037e911b15Skarels 						new_rep->dy = 863;
24047e911b15Skarels 					}
24057e911b15Skarels 
24067e911b15Skarels 					/*
24077e911b15Skarels 					* report an event if the puck/stylus has moved
24087e911b15Skarels 					*/
24097e911b15Skarels 
24107e911b15Skarels 					if (eqh->curs_pos.x != new_rep->dx ||
24117e911b15Skarels 					    eqh->curs_pos.y != new_rep->dy) {
24127e911b15Skarels 
24137e911b15Skarels 						eqh->curs_pos.x = new_rep->dx;
24147e911b15Skarels 						eqh->curs_pos.y = new_rep->dy;
24157e911b15Skarels 
2416b2b69f49Smarc 						/*
24177e911b15Skarels 						* update cursor screen position */
24187e911b15Skarels 
24197e911b15Skarels 						dga = (struct dga *) qdmap[qd].dga;
24207e911b15Skarels 						dga->x_cursor = TRANX(eqh->curs_pos.x);
24217e911b15Skarels 						dga->y_cursor = TRANY(eqh->curs_pos.y);
24227e911b15Skarels 
24237e911b15Skarels 						/*
24247e911b15Skarels 						* if cursor is in the box, no event report
24257e911b15Skarels 						*/
24267e911b15Skarels 
24277e911b15Skarels 						if (eqh->curs_pos.x <= eqh->curs_box.right	&&
24287e911b15Skarels 						    eqh->curs_pos.x >= eqh->curs_box.left  &&
24297e911b15Skarels 						    eqh->curs_pos.y >= eqh->curs_box.top  &&
24307e911b15Skarels 						    eqh->curs_pos.y <= eqh->curs_box.bottom ) {
24317e911b15Skarels 							goto GET_TBUTTON;
24327e911b15Skarels 						}
24337e911b15Skarels 
2434b2b69f49Smarc 						/*
24357e911b15Skarels 						* report the tablet motion event */
24367e911b15Skarels 
24377e911b15Skarels 						event = PUTBEGIN(eqh);
24387e911b15Skarels 						PUTEND(eqh);
24397e911b15Skarels 
24407e911b15Skarels 						++do_wakeup;   /* request a select wakeup call */
24417e911b15Skarels 
24427e911b15Skarels 						event->vse_x = eqh->curs_pos.x;
24437e911b15Skarels 						event->vse_y = eqh->curs_pos.y;
24447e911b15Skarels 
24457e911b15Skarels 						event->vse_device = VSE_TABLET;  /* tablet */
24467e911b15Skarels 						/*
24477e911b15Skarels 						* right now, X handles tablet motion the same
24487e911b15Skarels 						* as mouse motion
24497e911b15Skarels 						*/
24507e911b15Skarels 						event->vse_type = VSE_MMOTION;   /* pos changed */
24517e911b15Skarels 						event->vse_key = 0;
24527e911b15Skarels 						event->vse_direction = 0;
24537e911b15Skarels 						event->vse_time = TOY;	/* time stamp */
24547e911b15Skarels 					}
24557e911b15Skarels GET_TBUTTON:
2456b2b69f49Smarc 					/*
24577e911b15Skarels 					* if button state has changed */
24587e911b15Skarels 
24597e911b15Skarels 					a = new_rep->state & 0x1E;   /* mask nonbutton bits */
24607e911b15Skarels 					b = last_rep[qd].state & 0x1E;
24617e911b15Skarels 
24627e911b15Skarels 					if (a ^ b) {
24637e911b15Skarels 
24647e911b15Skarels 						/* event queue full now? (overflow condition) */
24657e911b15Skarels 
24667e911b15Skarels 						if (ISFULL(eqh) == TRUE) {
24677881ece5Smarc 							printf("qd%d: qdiint: event queue overflow\n",qd);
24687e911b15Skarels 							break;
24697e911b15Skarels 						}
24707e911b15Skarels 
24717e911b15Skarels 						event = PUTBEGIN(eqh);  /* get new event */
24727e911b15Skarels 						PUTEND(eqh);
24737e911b15Skarels 
24747e911b15Skarels 						++do_wakeup;   /* request a select wakeup call */
24757e911b15Skarels 
24767e911b15Skarels 						event->vse_x = eqh->curs_pos.x;
24777e911b15Skarels 						event->vse_y = eqh->curs_pos.y;
24787e911b15Skarels 
24797e911b15Skarels 						event->vse_device = VSE_TABLET;  /* tablet */
24807e911b15Skarels 						event->vse_type = VSE_BUTTON; /* button changed */
24817e911b15Skarels 						event->vse_time = TOY;	   /* time stamp */
24827e911b15Skarels 
24837e911b15Skarels 						/* define the changed button and if up or down */
24847e911b15Skarels 
24857e911b15Skarels 						for ( c = 1;  c <= 0x10; c <<= 1) {
24867e911b15Skarels 							if (c & (a ^ b)) {
24877e911b15Skarels 								if (c == T_LEFT_BUTTON)
24887e911b15Skarels 								    event->vse_key = VSE_T_LEFT_BUTTON;
24897e911b15Skarels 								else if (c == T_FRONT_BUTTON)
24907e911b15Skarels 								    event->vse_key = VSE_T_FRONT_BUTTON;
24917e911b15Skarels 								else if (c == T_RIGHT_BUTTON)
24927e911b15Skarels 								    event->vse_key = VSE_T_RIGHT_BUTTON;
24937e911b15Skarels 								else if (c == T_BACK_BUTTON)
24947e911b15Skarels 								    event->vse_key = VSE_T_BACK_BUTTON;
24957e911b15Skarels 								break;
24967e911b15Skarels 							}
24977e911b15Skarels 						}
24987e911b15Skarels 
24997e911b15Skarels 						/* set bit = button depressed */
25007e911b15Skarels 
25017e911b15Skarels 						if (c & a)
25027e911b15Skarels 						    event->vse_direction = VSE_KBTDOWN;
25037e911b15Skarels 						else
25047e911b15Skarels 							event->vse_direction = VSE_KBTUP;
25057e911b15Skarels 					}
25067e911b15Skarels 
25077e911b15Skarels 					/* refresh last report */
25087e911b15Skarels 
25097e911b15Skarels 					last_rep[qd] = current_rep[qd];
25107e911b15Skarels 
25117e911b15Skarels 				} /* get last byte of report */
25127e911b15Skarels 			} /* pick up tablet input */
25137e911b15Skarels 
25147e911b15Skarels 		} /* while input available.. */
25157e911b15Skarels 
2516b2b69f49Smarc 		/*
2517b2b69f49Smarc 		* do select wakeup
2518b2b69f49Smarc 		*/
25197881ece5Smarc 		if (qdrsel[qd] && do_wakeup && qdflags[qd].selmask & SEL_READ) {
25207881ece5Smarc 			selwakeup(qdrsel[qd], 0);
25217881ece5Smarc 			qdrsel[qd] = 0;
25227e911b15Skarels 			qdflags[qd].selmask &= ~SEL_READ;
25237e911b15Skarels 			do_wakeup = 0;
25247e911b15Skarels 		}
25257881ece5Smarc 	} else {
2526b2b69f49Smarc 		/*
25277881ece5Smarc 		 * if the graphic device is not turned on, this is console input
25287881ece5Smarc 		 */
2529f79d7b48Smarc 		if (qdpolling)
2530f79d7b48Smarc 			return;
25317e911b15Skarels 		ui = qdinfo[qd];
25327e911b15Skarels 		if (ui == 0 || ui->ui_alive == 0)
25337881ece5Smarc 			return;
25347e911b15Skarels 
25357e911b15Skarels 		tp = &qd_tty[qd << 2];
25367e911b15Skarels 
2537b2b69f49Smarc 		/*
25387881ece5Smarc 		 * Get a character from the keyboard.
25397881ece5Smarc 		 */
25407881ece5Smarc 		while (duart->statusA&RCV_RDY) {
25417e911b15Skarels 			key = duart->dataA;
25427e911b15Skarels 			key &= 0xFF;
2543b2b69f49Smarc 			/*
25447881ece5Smarc 			* Check for various keyboard errors
25457881ece5Smarc 			*/
25467e911b15Skarels 			if (key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
25477e911b15Skarels 			    key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
25487881ece5Smarc 				printf("qd%d: qdiint: Keyboard error, code = %x\n",qd,key);
25497881ece5Smarc 				return;
25507e911b15Skarels 			}
25517e911b15Skarels 
25527e911b15Skarels 			if (key < LK_LOWEST)
25537881ece5Smarc 			    return;
25547e911b15Skarels 
2555b2b69f49Smarc 			/*
25567e911b15Skarels 			* See if its a state change key */
25577e911b15Skarels 
25587e911b15Skarels 			switch (key) {
25597e911b15Skarels 
25607e911b15Skarels 			case LOCK:
25617e911b15Skarels 				q_keyboard.lock ^= 0xffff;	/* toggle */
25627e911b15Skarels 				if (q_keyboard.lock)
25637881ece5Smarc 					(void)led_control(qd, LK_LED_ENABLE,
25647881ece5Smarc 							  LK_LED_LOCK);
25657e911b15Skarels 				else
25667881ece5Smarc 					(void)led_control(qd, LK_LED_DISABLE,
25677881ece5Smarc 							  LK_LED_LOCK);
25687e911b15Skarels 				return;
25697e911b15Skarels 
25707e911b15Skarels 			case SHIFT:
25717e911b15Skarels 				q_keyboard.shift ^= 0xFFFF;
25727e911b15Skarels 				return;
25737e911b15Skarels 
25747e911b15Skarels 			case CNTRL:
25757e911b15Skarels 				q_keyboard.cntrl ^= 0xFFFF;
25767e911b15Skarels 				return;
25777e911b15Skarels 
25787e911b15Skarels 			case ALLUP:
25797e911b15Skarels 				q_keyboard.cntrl = 0;
25807e911b15Skarels 				q_keyboard.shift = 0;
25817e911b15Skarels 				return;
25827e911b15Skarels 
25837e911b15Skarels 			case REPEAT:
25847e911b15Skarels 				chr = q_keyboard.last;
25857e911b15Skarels 				break;
25867e911b15Skarels 
2587b2b69f49Smarc 				/*
25887e911b15Skarels 				* Test for cntrl characters. If set, see if the character
25897e911b15Skarels 				* is elligible to become a control character. */
25907e911b15Skarels 
25917e911b15Skarels 			default:
25927e911b15Skarels 
25937e911b15Skarels 				if (q_keyboard.cntrl) {
25947e911b15Skarels 					chr = q_key[key];
25957e911b15Skarels 					if (chr >= ' ' && chr <= '~')
25967e911b15Skarels 					    chr &= 0x1F;
2597e977faadSmarc 					else if (chr >= 0xA1 && chr <= 0xFE)
2598e977faadSmarc 					    chr &= 0x9F;
25997e911b15Skarels 				}
26007e911b15Skarels 				else if( q_keyboard.lock || q_keyboard.shift )
26017e911b15Skarels 				    chr = q_shift_key[key];
26027e911b15Skarels 				else
26037e911b15Skarels 					chr = q_key[key];
26047e911b15Skarels 				break;
26057e911b15Skarels 			}
26067e911b15Skarels 
26077e911b15Skarels 			q_keyboard.last = chr;
26087e911b15Skarels 
2609b2b69f49Smarc 			/*
26107e911b15Skarels 			* Check for special function keys */
26117e911b15Skarels 
2612e977faadSmarc 			if (chr & 0x100) {
26137e911b15Skarels 				char *string;
26147e911b15Skarels 				string = q_special[chr & 0x7F];
26157e911b15Skarels 				while(*string)
26167e911b15Skarels 				    (*linesw[tp->t_line].l_rint)(*string++, tp);
26177e911b15Skarels 			}
26187e911b15Skarels 			else {
2619f79d7b48Smarc #ifdef KADB
2620f79d7b48Smarc 				if (!kdbrintr(chr&0177, tp))
2621f79d7b48Smarc #endif
2622b2b69f49Smarc 				(*linesw[tp->t_line].l_rint)(chr&0177, tp);
26237e911b15Skarels 			}
26247e911b15Skarels 		}
26257e911b15Skarels 	}
26267e911b15Skarels } /* qdiint */
26277e911b15Skarels 
26287881ece5Smarc /*
26297e911b15Skarels  *
26307881ece5Smarc  * Clear the QDSS screen
26317e911b15Skarels  *
26327e911b15Skarels  *			     >>> NOTE <<<
26337e911b15Skarels  *
26347e911b15Skarels  *   This code requires that certain adder initialization be valid.  To
26357e911b15Skarels  *   assure that this requirement is satisfied, this routine should be
26367e911b15Skarels  *   called only after calling the "setup_dragon()" function.
26377e911b15Skarels  *
26387e911b15Skarels  *   Clear the bitmap a piece at a time. Since the fast scroll clear
26397e911b15Skarels  *   only clears the current displayed portion of the bitmap put a
26407e911b15Skarels  *   temporary value in the y limit register so we can access whole
26417e911b15Skarels  *   bitmap
26427e911b15Skarels  *
26437881ece5Smarc  */
clear_qd_screen(unit)26447e911b15Skarels clear_qd_screen(unit)
26457e911b15Skarels 	int unit;
26467e911b15Skarels {
26477e911b15Skarels 	register struct adder *adder;
26487e911b15Skarels 	adder = (struct adder *) qdmap[unit].adder;
26497e911b15Skarels 
26507e911b15Skarels 	adder->x_limit = 1024;
26517e911b15Skarels 	adder->y_limit = 2048 - CHAR_HEIGHT;
26527e911b15Skarels 	adder->y_offset_pending = 0;
26537881ece5Smarc #define WSV  (void)wait_status(adder, VSYNC); (void)wait_status(adder, VSYNC)
2654b2b69f49Smarc 	WSV;
26557e911b15Skarels 	adder->y_scroll_constant = SCROLL_ERASE;
2656b2b69f49Smarc 	WSV;
26577e911b15Skarels 	adder->y_offset_pending = 864;
2658b2b69f49Smarc 	WSV;
26597e911b15Skarels 	adder->y_scroll_constant = SCROLL_ERASE;
2660b2b69f49Smarc 	WSV;
26617e911b15Skarels 	adder->y_offset_pending = 1728;
2662b2b69f49Smarc 	WSV;
26637e911b15Skarels 	adder->y_scroll_constant = SCROLL_ERASE;
2664b2b69f49Smarc 	WSV;
26657e911b15Skarels 	adder->y_offset_pending = 0;	 /* back to normal */
2666b2b69f49Smarc 	WSV;
26677e911b15Skarels 	adder->x_limit = MAX_SCREEN_X;
26687e911b15Skarels 	adder->y_limit = MAX_SCREEN_Y + FONT_HEIGHT;
2669b2b69f49Smarc #undef WSV
26707e911b15Skarels 
26717e911b15Skarels } /* clear_qd_screen */
26727e911b15Skarels 
26737881ece5Smarc /*
26747881ece5Smarc  *  kernel console output to the glass tty
26757881ece5Smarc  */
qdputc(chr)26767e911b15Skarels qdputc(chr)
26777e911b15Skarels 	register char chr;
26787e911b15Skarels {
26797e911b15Skarels 
2680b2b69f49Smarc 	/*
2681b2b69f49Smarc 	 * if system is now physical, forget it (ie: crash DUMP)
2682b2b69f49Smarc 	 */
26837e911b15Skarels 	if ((mfpr(MAPEN) & 1) == 0)
26847e911b15Skarels 		return;
26857e911b15Skarels 
26867881ece5Smarc 	blitc(0, (u_char)(chr & 0xff));
268724f67f6bSmarc 	if ((chr & 0177) == '\n')
268824f67f6bSmarc 		blitc(0, '\r');
268924f67f6bSmarc 
26907e911b15Skarels } /* qdputc */
26917e911b15Skarels 
2692b2b69f49Smarc /*
26937881ece5Smarc  *  load the mouse cursor's template RAM bitmap
26947881ece5Smarc  */
ldcursor(unit,bitmap)26957e911b15Skarels ldcursor(unit, bitmap)
26967881ece5Smarc 	int unit;
26977881ece5Smarc 	register short *bitmap;
26987e911b15Skarels {
26997e911b15Skarels 	register struct dga *dga;
27007e911b15Skarels 	register short *temp;
27017e911b15Skarels 	register int i;
27027881ece5Smarc 	int curs;
27037e911b15Skarels 
27047e911b15Skarels 	dga = (struct dga *) qdmap[unit].dga;
27057e911b15Skarels 	temp = (short *) qdmap[unit].template;
27067e911b15Skarels 
27077e911b15Skarels 	if (dga->csr & CURS_ENB) {	/* if the cursor is enabled.. */
27087881ece5Smarc 		curs = -1;		/* ..note that.. */
27097e911b15Skarels 		dga->csr &= ~CURS_ENB;	/* ..and shut it off */
27107881ece5Smarc 	} else
27117881ece5Smarc 		curs = 0;
27127e911b15Skarels 
27137e911b15Skarels 	dga->csr &= ~CURS_ENB;		/* shut off the cursor */
27147e911b15Skarels 
27157e911b15Skarels 	temp += (8 * 1024) - 32;	/* cursor is 32 WORDS from the end */
27167e911b15Skarels 	/* ..of the 8k WORD template space */
27177e911b15Skarels 	for (i = 0; i < 32; ++i)
27187e911b15Skarels 		*temp++ = *bitmap++;
27197e911b15Skarels 
27207881ece5Smarc 	if (curs) {			/* if cursor was enabled.. */
27217e911b15Skarels 		dga->csr |= CURS_ENB;	/* ..turn it back on */
27227e911b15Skarels 	}
27237e911b15Skarels 
27247e911b15Skarels } /* ldcursor */
27257e911b15Skarels 
27267881ece5Smarc /*
27277881ece5Smarc  *  Put the console font in the QDSS off-screen memory
27287881ece5Smarc  */
ldfont(unit)27297e911b15Skarels ldfont(unit)
27307881ece5Smarc 	int unit;
27317e911b15Skarels {
27327e911b15Skarels 	register struct adder *adder;
27337e911b15Skarels 
27347881ece5Smarc 	register i, j, k, max_chars_line;
27357881ece5Smarc 	register short packed;
27367e911b15Skarels 
27377e911b15Skarels 	adder = (struct adder *) qdmap[unit].adder;
27387e911b15Skarels 
2739b2b69f49Smarc 	/*
27407881ece5Smarc 	* setup VIPER operand control registers
27417881ece5Smarc 	*/
27427e911b15Skarels 	write_ID(adder, MASK_1, 0xFFFF);
27437e911b15Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
27447e911b15Skarels 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
27457e911b15Skarels 
27467e911b15Skarels 	write_ID(adder, SRC1_OCR_B,
27477e911b15Skarels 	EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY);
27487e911b15Skarels 	write_ID(adder, SRC2_OCR_B,
27497e911b15Skarels 	EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY);
27507e911b15Skarels 	write_ID(adder, DST_OCR_B,
27517e911b15Skarels 	EXT_SOURCE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
27527e911b15Skarels 
27537e911b15Skarels 	adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL;
27547e911b15Skarels 
2755b2b69f49Smarc 	/*
27567881ece5Smarc 	* load destination data
27577881ece5Smarc 	*/
27587881ece5Smarc 	(void)wait_status(adder, RASTEROP_COMPLETE);
27597e911b15Skarels 
27607e911b15Skarels 	adder->destination_x = FONT_X;
27617e911b15Skarels 	adder->destination_y = FONT_Y;
27627881ece5Smarc #if FONT_WIDTH > MAX_SCREEN_X
2763e977faadSmarc 	adder->fast_dest_dx = MAX_SCREEN_X;
27647881ece5Smarc #else
27657e911b15Skarels 	adder->fast_dest_dx = FONT_WIDTH;
27667881ece5Smarc #endif
27677e911b15Skarels 	adder->slow_dest_dy = CHAR_HEIGHT;
27687e911b15Skarels 
2769b2b69f49Smarc 	/*
27707e911b15Skarels 	* setup for processor to bitmap xfer  */
27717e911b15Skarels 
27727e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0001);
27737e911b15Skarels 	adder->cmd = PBT | OCRB | 2 | DTE | 2;
27747e911b15Skarels 
2775b2b69f49Smarc 	/*
2776b2b69f49Smarc 	* Figure out how many characters can be stored on one "line" of
2777b2b69f49Smarc 	* offscreen memory.
2778e977faadSmarc 	*/
2779e977faadSmarc 	max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
2780e977faadSmarc 	if ((CHARS/2 + CHARS%2) < max_chars_line)
2781e977faadSmarc 	    max_chars_line = CHARS/2 + CHARS%2;
2782e977faadSmarc 
2783b2b69f49Smarc 	/*
2784e977faadSmarc 	* iteratively do the processor to bitmap xfer */
2785e977faadSmarc 
2786e977faadSmarc 	for (i = 0; i < ROWS; ++i) {
2787e977faadSmarc 
2788e977faadSmarc 		/* PTOB a scan line */
2789e977faadSmarc 
2790e977faadSmarc 		for (j = 0, k = i; j < max_chars_line; ++j) {
2791e977faadSmarc 			/* PTOB one scan of a char cell */
2792e977faadSmarc 
2793e977faadSmarc 			packed = q_font[k];
2794e977faadSmarc 			k += ROWS;
2795e977faadSmarc 			packed |= ((short)q_font[k] << 8);
2796e977faadSmarc 			k += ROWS;
2797e977faadSmarc 
27987881ece5Smarc 			(void)wait_status(adder, TX_READY);
2799e977faadSmarc 			adder->id_data = packed;
2800e977faadSmarc 		}
2801e977faadSmarc 	}
2802e977faadSmarc 
2803b2b69f49Smarc 	/*
2804b2b69f49Smarc 	 * (XXX XXX XXX - should remove)
2805b2b69f49Smarc 	 *
2806b2b69f49Smarc 	 * Copy the second row of characters.  Subtract the first
2807b2b69f49Smarc 	 * row from the total number.  Divide this quantity by 2
2808b2b69f49Smarc 	 * because 2 chars are stored in a short in the PTOB loop
2809b2b69f49Smarc 	 * below.  Figure out how many characters can be stored on
2810b2b69f49Smarc 	 * one "line" of offscreen memory
2811e977faadSmarc 	 */
2812b2b69f49Smarc 
2813e977faadSmarc 	max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
2814e977faadSmarc 	if ((CHARS/2 + CHARS%2) < max_chars_line)
2815e977faadSmarc 	    return;
2816e977faadSmarc 	max_chars_line = (CHARS/2 + CHARS%2) - max_chars_line; /* 95 - 64 */
2817e977faadSmarc 	/* Paranoia check to see if 3rd row may be needed */
2818e977faadSmarc 	if (max_chars_line > (MAX_SCREEN_X/(CHAR_WIDTH*2)))
2819e977faadSmarc 	    max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
2820e977faadSmarc 
2821e977faadSmarc 	adder->destination_x = FONT_X;
2822e977faadSmarc 	adder->destination_y = FONT_Y - CHAR_HEIGHT;
2823e977faadSmarc 	adder->fast_dest_dx = max_chars_line * CHAR_WIDTH * 2;
2824e977faadSmarc 	adder->slow_dest_dy = CHAR_HEIGHT;
2825e977faadSmarc 
2826b2b69f49Smarc 	/*
2827b2b69f49Smarc 	* setup for processor to bitmap xfer
2828b2b69f49Smarc 	*/
2829e977faadSmarc 	write_ID(adder, CS_UPDATE_MASK, 0x0001);
2830e977faadSmarc 	adder->cmd = PBT | OCRB | 2 | DTE | 2;
2831e977faadSmarc 
2832b2b69f49Smarc 	/*
2833b2b69f49Smarc 	* iteratively do the processor to bitmap xfer
2834b2b69f49Smarc 	*/
28357e911b15Skarels 	for (i = 0; i < ROWS; ++i) {
2836b2b69f49Smarc 		/*
2837b2b69f49Smarc 		 * PTOB a scan line
2838b2b69f49Smarc 		 */
2839e977faadSmarc 		for (j = 0, k = i; j < max_chars_line; ++j) {
2840b2b69f49Smarc 			/*
2841b2b69f49Smarc 			 * PTOB one scan of a char cell
2842b2b69f49Smarc 			 */
2843e977faadSmarc 			packed = q_font[k + FONT_OFFSET];
28447e911b15Skarels 			k += ROWS;
2845e977faadSmarc 			packed |= ((short)q_font[k + FONT_OFFSET] << 8);
28467e911b15Skarels 			k += ROWS;
28477881ece5Smarc 			(void)wait_status(adder, TX_READY);
28487e911b15Skarels 			adder->id_data = packed;
28497e911b15Skarels 		}
28507e911b15Skarels 	}
28517e911b15Skarels 
28527e911b15Skarels }  /* ldfont */
28537e911b15Skarels 
qdpoll(onoff)2854f79d7b48Smarc qdpoll(onoff)
2855f79d7b48Smarc {
2856f79d7b48Smarc 	qdpolling = onoff;
2857f79d7b48Smarc }
2858f79d7b48Smarc 
28597881ece5Smarc /*
28607881ece5Smarc  *  Get a character from the LK201 (polled)
28617881ece5Smarc  */
qdgetc()28627881ece5Smarc qdgetc()
28637e911b15Skarels {
28647881ece5Smarc 	register short key;
28657881ece5Smarc 	register char chr;
28667881ece5Smarc 	register struct duart *duart;
28677881ece5Smarc 
28687881ece5Smarc 	duart = (struct duart *) qdmap[0].duart;
28697881ece5Smarc 
28707881ece5Smarc 	/*
28717881ece5Smarc 	* Get a character from the keyboard.
28727881ece5Smarc 	*/
28737881ece5Smarc LOOP:
28747881ece5Smarc 	while (!(duart->statusA&RCV_RDY))
28757881ece5Smarc 		;
28767881ece5Smarc 
28777881ece5Smarc 	key = duart->dataA;
28787881ece5Smarc 	key &= 0xFF;
28797881ece5Smarc 
28807881ece5Smarc 	/*
28817881ece5Smarc 	* Check for various keyboard errors  */
28827881ece5Smarc 
28837881ece5Smarc 	if (key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
28847881ece5Smarc 	    key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
28857881ece5Smarc 		printf("Keyboard error, code = %x\n", key);
28867881ece5Smarc 		return(0);
28877881ece5Smarc 	}
28887881ece5Smarc 
28897881ece5Smarc 	if (key < LK_LOWEST)
28907881ece5Smarc 		return(0);
28917881ece5Smarc 
28927881ece5Smarc 	/*
28937881ece5Smarc 	 * See if its a state change key
28947881ece5Smarc 	 */
28957881ece5Smarc 	switch (key) {
28967881ece5Smarc 
28977881ece5Smarc 	case LOCK:
28987881ece5Smarc 		q_keyboard.lock ^= 0xffff;	/* toggle */
28997881ece5Smarc 		if (q_keyboard.lock)
29007881ece5Smarc 			(void)led_control(0, LK_LED_ENABLE, LK_LED_LOCK);
29017881ece5Smarc 		else
29027881ece5Smarc 			(void)led_control(0, LK_LED_DISABLE, LK_LED_LOCK);
29037881ece5Smarc 		goto LOOP;
29047881ece5Smarc 
29057881ece5Smarc 	case SHIFT:
29067881ece5Smarc 		q_keyboard.shift ^= 0xFFFF;
29077881ece5Smarc 		goto LOOP;
29087881ece5Smarc 
29097881ece5Smarc 	case CNTRL:
29107881ece5Smarc 		q_keyboard.cntrl ^= 0xFFFF;
29117881ece5Smarc 		goto LOOP;
29127881ece5Smarc 
29137881ece5Smarc 	case ALLUP:
29147881ece5Smarc 		q_keyboard.cntrl = 0;
29157881ece5Smarc 		q_keyboard.shift = 0;
29167881ece5Smarc 		goto LOOP;
29177881ece5Smarc 
29187881ece5Smarc 	case REPEAT:
29197881ece5Smarc 		chr = q_keyboard.last;
29207881ece5Smarc 		break;
29217881ece5Smarc 
29227881ece5Smarc 		/*
29237881ece5Smarc 		* Test for cntrl characters. If set, see if the character
29247881ece5Smarc 		* is elligible to become a control character.
29257881ece5Smarc 		*/
29267881ece5Smarc 	default:
29277881ece5Smarc 
29287881ece5Smarc 		if (q_keyboard.cntrl) {
29297881ece5Smarc 			chr = q_key[key];
29307881ece5Smarc 			if (chr >= ' ' && chr <= '~')
29317881ece5Smarc 			    chr &= 0x1F;
29327881ece5Smarc 		}
29337881ece5Smarc 		else if ( q_keyboard.lock || q_keyboard.shift )
29347881ece5Smarc 		    chr = q_shift_key[key];
29357881ece5Smarc 		else
29367881ece5Smarc 			chr = q_key[key];
29377881ece5Smarc 		break;
29387881ece5Smarc 	}
29397881ece5Smarc 
29407881ece5Smarc 	if (chr < ' ' && chr > '~')	/* if input is non-displayable */
29417881ece5Smarc 		return(0);		/* ..then pitch it! */
29427881ece5Smarc 
29437881ece5Smarc 	q_keyboard.last = chr;
29447881ece5Smarc 
29457881ece5Smarc 	/*
29467881ece5Smarc 	* Check for special function keys */
29477881ece5Smarc 
29487881ece5Smarc 	if (chr & 0x80) 		/* pitch the function keys */
29497881ece5Smarc 		return(0);
29507881ece5Smarc 	else
29517881ece5Smarc 		return(chr);
29527881ece5Smarc 
29537881ece5Smarc } /* qdgetc */
29547881ece5Smarc 
29557881ece5Smarc /*
29567881ece5Smarc  *  led_control()... twiddle LK-201 LED's
29577881ece5Smarc  */
led_control(unit,cmd,led_mask)29587881ece5Smarc led_control(unit, cmd, led_mask)
29597881ece5Smarc 	int unit, cmd, led_mask;
29607881ece5Smarc {
29617881ece5Smarc 	register i;
29627e911b15Skarels 	register struct duart *duart;
29637e911b15Skarels 
29647e911b15Skarels 	duart = (struct duart *)qdmap[unit].duart;
29657e911b15Skarels 
29667e911b15Skarels 	for (i = 1000; i > 0; --i) {
29677881ece5Smarc 		if (duart->statusA&XMT_RDY) {
29687e911b15Skarels 			duart->dataA = cmd;
29697e911b15Skarels 			break;
29707e911b15Skarels 		}
29717e911b15Skarels 	}
29727e911b15Skarels 	for (i = 1000; i > 0; --i) {
29737881ece5Smarc 		if (duart->statusA&XMT_RDY) {
29747e911b15Skarels 			duart->dataA = led_mask;
29757e911b15Skarels 			break;
29767e911b15Skarels 		}
29777e911b15Skarels 	}
29787e911b15Skarels 	if (i == 0)
29797e911b15Skarels 		return(BAD);
29807e911b15Skarels 	return(GOOD);
29817e911b15Skarels 
29827e911b15Skarels } /* led_control */
29837e911b15Skarels 
29847881ece5Smarc /*
29857e911b15Skarels  *  scroll_up()... move the screen up one character height
29867881ece5Smarc  */
scroll_up(adder)29877e911b15Skarels scroll_up(adder)
29887e911b15Skarels 	register struct adder *adder;
29897e911b15Skarels {
2990b2b69f49Smarc 	/*
2991b2b69f49Smarc 	* setup VIPER operand control registers
2992b2b69f49Smarc 	*/
29937881ece5Smarc 	(void)wait_status(adder, ADDRESS_COMPLETE);
29947e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x00FF);  /* select all planes */
29957e911b15Skarels 	write_ID(adder, MASK_1, 0xFFFF);
29967e911b15Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
29977e911b15Skarels 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
29987e911b15Skarels 	write_ID(adder, SRC1_OCR_B,
29997e911b15Skarels 	EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY);
30007e911b15Skarels 	write_ID(adder, DST_OCR_B,
30017e911b15Skarels 	EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
3002b2b69f49Smarc 	/*
3003b2b69f49Smarc 	 * load DESTINATION origin and vectors
3004b2b69f49Smarc 	 */
30057e911b15Skarels 	adder->fast_dest_dy = 0;
30067e911b15Skarels 	adder->slow_dest_dx = 0;
30077e911b15Skarels 	adder->error_1 = 0;
30087e911b15Skarels 	adder->error_2 = 0;
30097e911b15Skarels 	adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL;
30107e911b15Skarels 	adder->destination_x = 0;
30117e911b15Skarels 	adder->fast_dest_dx = 1024;
30127e911b15Skarels 	adder->destination_y = 0;
30137e911b15Skarels 	adder->slow_dest_dy = 864 - CHAR_HEIGHT;
3014b2b69f49Smarc 	/*
3015b2b69f49Smarc 	 * load SOURCE origin and vectors
3016b2b69f49Smarc 	 */
30177e911b15Skarels 	adder->source_1_x = 0;
30187e911b15Skarels 	adder->source_1_dx = 1024;
30197e911b15Skarels 	adder->source_1_y = 0 + CHAR_HEIGHT;
30207e911b15Skarels 	adder->source_1_dy = 864 - CHAR_HEIGHT;
30217e911b15Skarels 	write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
30227e911b15Skarels 	adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE;
3023b2b69f49Smarc 	/*
3024b2b69f49Smarc 	 * do a rectangle clear of last screen line
3025b2b69f49Smarc 	 */
30267e911b15Skarels 	write_ID(adder, MASK_1, 0xffff);
30277e911b15Skarels 	write_ID(adder, SOURCE, 0xffff);
30287e911b15Skarels 	write_ID(adder,DST_OCR_B,
30297e911b15Skarels 	(EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY));
30307e911b15Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 0);
30317e911b15Skarels 	adder->error_1 = 0;
30327e911b15Skarels 	adder->error_2 = 0;
30337e911b15Skarels 	adder->slow_dest_dx = 0;		/* set up the width of	*/
30347e911b15Skarels 	adder->slow_dest_dy = CHAR_HEIGHT;	/* rectangle */
30357e911b15Skarels 	adder->rasterop_mode = (NORMAL | DST_WRITE_ENABLE) ;
30367881ece5Smarc 	(void)wait_status(adder, RASTEROP_COMPLETE);
30377e911b15Skarels 	adder->destination_x = 0;
30387e911b15Skarels 	adder->destination_y = 864 - CHAR_HEIGHT;
30397e911b15Skarels 	adder->fast_dest_dx = 1024;	/* set up the height	*/
30407e911b15Skarels 	adder->fast_dest_dy = 0;	/* of rectangle 	*/
30417e911b15Skarels 	write_ID(adder, LU_FUNCTION_R2, (FULL_SRC_RESOLUTION | LF_SOURCE));
30427e911b15Skarels 	adder->cmd = (RASTEROP | OCRB | LF_R2 | DTE ) ;
30437e911b15Skarels 
30447e911b15Skarels } /* scroll_up */
30457e911b15Skarels 
30467881ece5Smarc /*
30477881ece5Smarc  *  init shared memory pointers and structures
30487881ece5Smarc  */
init_shared(unit)30497e911b15Skarels init_shared(unit)
30507881ece5Smarc 	register unit;
30517e911b15Skarels {
30527e911b15Skarels 	register struct dga *dga;
30537e911b15Skarels 
30547e911b15Skarels 	dga = (struct dga *) qdmap[unit].dga;
30557e911b15Skarels 
3056b2b69f49Smarc 	/*
30577e911b15Skarels 	* initialize the event queue pointers and header */
30587e911b15Skarels 
30597e911b15Skarels 	eq_header[unit] = (struct qdinput *)
30607e911b15Skarels 	    ((((int)event_shared & ~(0x01FF)) + 512)
30617e911b15Skarels 		+ (EVENT_BUFSIZE * unit));
30627e911b15Skarels 	eq_header[unit]->curs_pos.x = 0;
30637e911b15Skarels 	eq_header[unit]->curs_pos.y = 0;
30647e911b15Skarels 	dga->x_cursor = TRANX(eq_header[unit]->curs_pos.x);
30657e911b15Skarels 	dga->y_cursor = TRANY(eq_header[unit]->curs_pos.y);
30667e911b15Skarels 	eq_header[unit]->curs_box.left = 0;
30677e911b15Skarels 	eq_header[unit]->curs_box.right = 0;
30687e911b15Skarels 	eq_header[unit]->curs_box.top = 0;
30697e911b15Skarels 	eq_header[unit]->curs_box.bottom = 0;
3070b2b69f49Smarc 	/*
3071b2b69f49Smarc 	 * assign a pointer to the DMA I/O buffer for this QDSS.
3072b2b69f49Smarc 	 */
30737e911b15Skarels 	DMAheader[unit] = (struct DMAreq_header *)
30747e911b15Skarels 	    (((int)(&DMA_shared[0] + 512) & ~0x1FF)
30757e911b15Skarels 		+ (DMAbuf_size * unit));
30767e911b15Skarels 	DMAheader[unit]->DMAreq = (struct DMAreq *) ((int)DMAheader[unit]
30777e911b15Skarels 	    + sizeof(struct DMAreq_header));
30787e911b15Skarels 	DMAheader[unit]->QBAreg = 0;
30797e911b15Skarels 	DMAheader[unit]->status = 0;
30807e911b15Skarels 	DMAheader[unit]->shared_size = DMAbuf_size;
30817e911b15Skarels 	DMAheader[unit]->used = 0;
30827e911b15Skarels 	DMAheader[unit]->size = 10;	/* default = 10 requests */
30837e911b15Skarels 	DMAheader[unit]->oldest = 0;
30847e911b15Skarels 	DMAheader[unit]->newest = 0;
3085b2b69f49Smarc 	/*
3086b2b69f49Smarc 	* assign a pointer to the scroll structure for this QDSS.
3087b2b69f49Smarc 	*/
30887e911b15Skarels 	scroll[unit] = (struct scroll *)
30897e911b15Skarels 	    (((int)(&scroll_shared[0] + 512) & ~0x1FF)
30907e911b15Skarels 		+ (sizeof(struct scroll) * unit));
30917e911b15Skarels 	scroll[unit]->status = 0;
30927e911b15Skarels 	scroll[unit]->viper_constant = 0;
30937e911b15Skarels 	scroll[unit]->y_scroll_constant = 0;
30947e911b15Skarels 	scroll[unit]->y_offset = 0;
30957e911b15Skarels 	scroll[unit]->x_index_pending = 0;
30967e911b15Skarels 	scroll[unit]->y_index_pending = 0;
3097b2b69f49Smarc 	/*
3098b2b69f49Smarc 	* assign a pointer to the color map write buffer for this QDSS
3099b2b69f49Smarc 	*/
31007e911b15Skarels 	color_buf[unit] = (struct color_buf *)
31017e911b15Skarels 	    (((int)(&color_shared[0] + 512) & ~0x1FF)
31027e911b15Skarels 		+ (COLOR_BUFSIZ * unit));
31037e911b15Skarels 	color_buf[unit]->status = 0;
31047e911b15Skarels 	color_buf[unit]->count = 0;
31057e911b15Skarels 
31067e911b15Skarels } /* init_shared */
31077e911b15Skarels 
31087881ece5Smarc /*
31097881ece5Smarc  * init the ADDER, VIPER, bitmaps, & color map
31107881ece5Smarc  */
setup_dragon(unit)31117e911b15Skarels setup_dragon(unit)
31127881ece5Smarc 	int unit;
31137e911b15Skarels {
31147e911b15Skarels 
31157e911b15Skarels 	register struct adder *adder;
31167e911b15Skarels 	register struct dga *dga;
31177e911b15Skarels 	short *memcsr;
31187881ece5Smarc 	register i;
31197e911b15Skarels 	short top;		/* clipping/scrolling boundaries */
31207e911b15Skarels 	short bottom;
31217e911b15Skarels 	short right;
31227e911b15Skarels 	short left;
31237e911b15Skarels 	short *red;		/* color map pointers */
31247e911b15Skarels 	short *green;
31257e911b15Skarels 	short *blue;
31267e911b15Skarels 
3127b2b69f49Smarc 	/*
3128b2b69f49Smarc 	* init for setup
3129b2b69f49Smarc 	*/
31307e911b15Skarels 	adder = (struct adder *) qdmap[unit].adder;
31317e911b15Skarels 	dga = (struct dga *) qdmap[unit].dga;
31327e911b15Skarels 	memcsr = (short *) qdmap[unit].memcsr;
31337e911b15Skarels 	dga->csr &= ~(DMA_IE | 0x700);	/* halt DMA and kill the intrpts */
31347e911b15Skarels 	*memcsr = SYNC_ON;		/* blank screen and turn off LED's */
31357e911b15Skarels 	adder->command = CANCEL;
3136b2b69f49Smarc 	/*
3137b2b69f49Smarc 	* set monitor timing
3138b2b69f49Smarc 	*/
31397e911b15Skarels 	adder->x_scan_count_0 = 0x2800;
31407e911b15Skarels 	adder->x_scan_count_1 = 0x1020;
31417e911b15Skarels 	adder->x_scan_count_2 = 0x003A;
31427e911b15Skarels 	adder->x_scan_count_3 = 0x38F0;
31437e911b15Skarels 	adder->x_scan_count_4 = 0x6128;
31447e911b15Skarels 	adder->x_scan_count_5 = 0x093A;
31457e911b15Skarels 	adder->x_scan_count_6 = 0x313C;
31467e911b15Skarels 	adder->sync_phase_adj = 0x0100;
31477e911b15Skarels 	adder->x_scan_conf = 0x00C8;
3148b2b69f49Smarc 	/*
3149b2b69f49Smarc 	 * got a bug in secound pass ADDER! lets take care of it
3150b2b69f49Smarc 	 *
3151b2b69f49Smarc 	 * normally, just use the code in the following bug fix code, but to
31527e911b15Skarels 	 * make repeated demos look pretty, load the registers as if there was
3153b2b69f49Smarc 	 * no bug and then test to see if we are getting sync
3154b2b69f49Smarc 	 */
31557e911b15Skarels 	adder->y_scan_count_0 = 0x135F;
31567e911b15Skarels 	adder->y_scan_count_1 = 0x3363;
31577e911b15Skarels 	adder->y_scan_count_2 = 0x2366;
31587e911b15Skarels 	adder->y_scan_count_3 = 0x0388;
3159b2b69f49Smarc 	/*
3160b2b69f49Smarc 	 * if no sync, do the bug fix code
3161b2b69f49Smarc 	 */
31627e911b15Skarels 	if (wait_status(adder, VSYNC) == BAD) {
31637e911b15Skarels 		/* first load all Y scan registers with very short frame and
31647e911b15Skarels 		 * wait for scroll service.  This guarantees at least one SYNC
31657e911b15Skarels 		 * to fix the pass 2 Adder initialization bug (synchronizes
3166b2b69f49Smarc 		 * XCINCH with DMSEEDH)
3167b2b69f49Smarc 		 */
31687e911b15Skarels 		adder->y_scan_count_0 = 0x01;
31697e911b15Skarels 		adder->y_scan_count_1 = 0x01;
31707e911b15Skarels 		adder->y_scan_count_2 = 0x01;
31717e911b15Skarels 		adder->y_scan_count_3 = 0x01;
3172b2b69f49Smarc 		/*
3173b2b69f49Smarc 		 * delay at least 1 full frame time
3174b2b69f49Smarc 		 */
31757881ece5Smarc 		(void)wait_status(adder, VSYNC);
31767881ece5Smarc 		(void)wait_status(adder, VSYNC);
3177b2b69f49Smarc 		/*
3178b2b69f49Smarc 		 * now load the REAL sync values (in reverse order just to
3179b2b69f49Smarc 		 * be safe.
3180b2b69f49Smarc 		 */
31817e911b15Skarels 		adder->y_scan_count_3 = 0x0388;
31827e911b15Skarels 		adder->y_scan_count_2 = 0x2366;
31837e911b15Skarels 		adder->y_scan_count_1 = 0x3363;
31847e911b15Skarels 		adder->y_scan_count_0 = 0x135F;
31857e911b15Skarels 	}
31867e911b15Skarels 	*memcsr = SYNC_ON | UNBLANK;	/* turn off leds and turn on video */
3187b2b69f49Smarc 	/*
3188b2b69f49Smarc 	 * zero the index registers
3189b2b69f49Smarc 	 */
31907e911b15Skarels 	adder->x_index_pending = 0;
31917e911b15Skarels 	adder->y_index_pending = 0;
31927e911b15Skarels 	adder->x_index_new = 0;
31937e911b15Skarels 	adder->y_index_new = 0;
31947e911b15Skarels 	adder->x_index_old = 0;
31957e911b15Skarels 	adder->y_index_old = 0;
31967e911b15Skarels 	adder->pause = 0;
3197b2b69f49Smarc 	/*
3198b2b69f49Smarc 	 * set rasterop mode to normal pen down
3199b2b69f49Smarc 	 */
32007e911b15Skarels 	adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL;
3201b2b69f49Smarc 	/*
3202b2b69f49Smarc 	 * set the rasterop registers to a default values
3203b2b69f49Smarc 	 */
32047e911b15Skarels 	adder->source_1_dx = 1;
32057e911b15Skarels 	adder->source_1_dy = 1;
32067e911b15Skarels 	adder->source_1_x = 0;
32077e911b15Skarels 	adder->source_1_y = 0;
32087e911b15Skarels 	adder->destination_x = 0;
32097e911b15Skarels 	adder->destination_y = 0;
32107e911b15Skarels 	adder->fast_dest_dx = 1;
32117e911b15Skarels 	adder->fast_dest_dy = 0;
32127e911b15Skarels 	adder->slow_dest_dx = 0;
32137e911b15Skarels 	adder->slow_dest_dy = 1;
32147e911b15Skarels 	adder->error_1 = 0;
32157e911b15Skarels 	adder->error_2 = 0;
3216b2b69f49Smarc 	/*
32177881ece5Smarc 	 * scale factor = UNITY
3218b2b69f49Smarc 	 */
32197e911b15Skarels 	adder->fast_scale = UNITY;
32207e911b15Skarels 	adder->slow_scale = UNITY;
3221b2b69f49Smarc 	/*
3222b2b69f49Smarc 	 * set the source 2 parameters
3223b2b69f49Smarc 	 */
32247e911b15Skarels 	adder->source_2_x = 0;
32257e911b15Skarels 	adder->source_2_y = 0;
32267e911b15Skarels 	adder->source_2_size = 0x0022;
3227b2b69f49Smarc 	/*
3228b2b69f49Smarc 	* initialize plane addresses for eight vipers
3229b2b69f49Smarc 	*/
32307e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0001);
32317e911b15Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0000);
32327e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0002);
32337e911b15Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0001);
32347e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0004);
32357e911b15Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0002);
32367e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0008);
32377e911b15Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0003);
32387e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0010);
32397e911b15Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0004);
32407e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0020);
32417e911b15Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0005);
32427e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0040);
32437e911b15Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0006);
32447e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0080);
32457e911b15Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0007);
3246b2b69f49Smarc 	/*
3247b2b69f49Smarc 	 * initialize the external registers.
3248b2b69f49Smarc 	 */
32497e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x00FF);
32507e911b15Skarels 	write_ID(adder, CS_SCROLL_MASK, 0x00FF);
3251b2b69f49Smarc 	/*
3252b2b69f49Smarc 	 * initialize resolution mode
3253b2b69f49Smarc 	 */
32547e911b15Skarels 	write_ID(adder, MEMORY_BUS_WIDTH, 0x000C);     /* bus width = 16 */
32557e911b15Skarels 	write_ID(adder, RESOLUTION_MODE, 0x0000);      /* one bit/pixel */
3256b2b69f49Smarc 	/*
3257b2b69f49Smarc 	 * initialize viper registers
3258b2b69f49Smarc 	 */
32597e911b15Skarels 	write_ID(adder, SCROLL_CONSTANT, SCROLL_ENABLE|VIPER_LEFT|VIPER_UP);
32607e911b15Skarels 	write_ID(adder, SCROLL_FILL, 0x0000);
3261b2b69f49Smarc 	/*
3262b2b69f49Smarc 	 * set clipping and scrolling limits to full screen
3263b2b69f49Smarc 	 */
3264b2b69f49Smarc 	for (i = 1000, adder->status = 0;
32657881ece5Smarc 	     i > 0 && !(adder->status&ADDRESS_COMPLETE); --i)
3266b2b69f49Smarc 		;
32677e911b15Skarels 	if (i == 0)
32687881ece5Smarc 	    printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n",unit);
32697e911b15Skarels 	top = 0;
32707e911b15Skarels 	bottom = 2048;
32717e911b15Skarels 	left = 0;
32727e911b15Skarels 	right = 1024;
32737e911b15Skarels 	adder->x_clip_min = left;
32747e911b15Skarels 	adder->x_clip_max = right;
32757e911b15Skarels 	adder->y_clip_min = top;
32767e911b15Skarels 	adder->y_clip_max = bottom;
32777e911b15Skarels 	adder->scroll_x_min = left;
32787e911b15Skarels 	adder->scroll_x_max = right;
32797e911b15Skarels 	adder->scroll_y_min = top;
32807e911b15Skarels 	adder->scroll_y_max = bottom;
32817881ece5Smarc 	(void)wait_status(adder, VSYNC);	/* wait at LEAST 1 full frame */
32827881ece5Smarc 	(void)wait_status(adder, VSYNC);
32837e911b15Skarels 	adder->x_index_pending = left;
32847e911b15Skarels 	adder->y_index_pending = top;
32857e911b15Skarels 	adder->x_index_new = left;
32867e911b15Skarels 	adder->y_index_new = top;
32877e911b15Skarels 	adder->x_index_old = left;
32887e911b15Skarels 	adder->y_index_old = top;
32897e911b15Skarels 
32907881ece5Smarc 	for (i = 1000, adder->status = 0; i > 0 &&
32917881ece5Smarc 	     !(adder->status&ADDRESS_COMPLETE) ; --i)
3292b2b69f49Smarc 		;
32937e911b15Skarels 	if (i == 0)
32947881ece5Smarc 	       printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n",unit);
32957e911b15Skarels 
32967e911b15Skarels 	write_ID(adder, LEFT_SCROLL_MASK, 0x0000);
32977e911b15Skarels 	write_ID(adder, RIGHT_SCROLL_MASK, 0x0000);
3298b2b69f49Smarc 	/*
3299b2b69f49Smarc 	* set source and the mask register to all ones (ie: white) o
3300b2b69f49Smarc 	*/
33017e911b15Skarels 	write_ID(adder, SOURCE, 0xFFFF);
33027e911b15Skarels 	write_ID(adder, MASK_1, 0xFFFF);
33037e911b15Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
33047e911b15Skarels 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
3305b2b69f49Smarc 	/*
3306b2b69f49Smarc 	* initialize Operand Control Register banks for fill command
3307b2b69f49Smarc 	*/
33087e911b15Skarels 	write_ID(adder, SRC1_OCR_A, EXT_NONE | INT_M1_M2  | NO_ID | WAIT);
33097e911b15Skarels 	write_ID(adder, SRC2_OCR_A, EXT_NONE | INT_SOURCE | NO_ID | NO_WAIT);
33107e911b15Skarels 	write_ID(adder, DST_OCR_A, EXT_NONE | INT_NONE	 | NO_ID | NO_WAIT);
33117e911b15Skarels 	write_ID(adder, SRC1_OCR_B, EXT_NONE | INT_SOURCE | NO_ID | WAIT);
33127e911b15Skarels 	write_ID(adder, SRC2_OCR_B, EXT_NONE | INT_M1_M2  | NO_ID | NO_WAIT);
33137e911b15Skarels 	write_ID(adder, DST_OCR_B, EXT_NONE | INT_NONE | NO_ID | NO_WAIT);
3314b2b69f49Smarc 	/*
33157e911b15Skarels 	* init Logic Unit Function registers, (these are just common values,
3316b2b69f49Smarc 	* and may be changed as required).
3317b2b69f49Smarc 	*/
33187e911b15Skarels 	write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
3319b2b69f49Smarc 	write_ID(adder, LU_FUNCTION_R2, FULL_SRC_RESOLUTION | LF_SOURCE |
3320b2b69f49Smarc 		 INV_M1_M2);
33217e911b15Skarels 	write_ID(adder, LU_FUNCTION_R3, FULL_SRC_RESOLUTION | LF_D_OR_S);
33227e911b15Skarels 	write_ID(adder, LU_FUNCTION_R4, FULL_SRC_RESOLUTION | LF_D_XOR_S);
3323b2b69f49Smarc 	/*
3324b2b69f49Smarc 	* load the color map for black & white
3325b2b69f49Smarc 	*/
33267881ece5Smarc 	for (i = 0, adder->status = 0; i < 10000 && !(adder->status&VSYNC); ++i)
3327b2b69f49Smarc 		;
33287e911b15Skarels 
33297e911b15Skarels 	if (i == 0)
33307881ece5Smarc 		printf("qd%d: setup_dragon: timeout on VSYNC\n", unit);
33317e911b15Skarels 
33327e911b15Skarels 	red = (short *) qdmap[unit].red;
33337e911b15Skarels 	green = (short *) qdmap[unit].green;
33347e911b15Skarels 	blue = (short *) qdmap[unit].blue;
33357e911b15Skarels 
33367e911b15Skarels 	*red++ = 0x00;			/* black */
33377e911b15Skarels 	*green++ = 0x00;
33387e911b15Skarels 	*blue++ = 0x00;
33397e911b15Skarels 
33407e911b15Skarels 	*red-- = 0xFF;			/* white */
33417e911b15Skarels 	*green-- = 0xFF;
33427e911b15Skarels 	*blue-- = 0xFF;
33437e911b15Skarels 
3344b2b69f49Smarc 	/*
33457881ece5Smarc 	* set color map for mouse cursor
33467881ece5Smarc 	*/
33477e911b15Skarels 
33487e911b15Skarels 	red += 254;
33497e911b15Skarels 	green += 254;
33507e911b15Skarels 	blue += 254;
33517e911b15Skarels 
33527e911b15Skarels 	*red++ = 0x00;			/* black */
33537e911b15Skarels 	*green++ = 0x00;
33547e911b15Skarels 	*blue++ = 0x00;
33557e911b15Skarels 
33567e911b15Skarels 	*red = 0xFF;			/* white */
33577e911b15Skarels 	*green = 0xFF;
33587e911b15Skarels 	*blue = 0xFF;
33597e911b15Skarels 
33607e911b15Skarels } /* setup_dragon */
33617e911b15Skarels 
33627881ece5Smarc /*
33637881ece5Smarc  * Init the DUART and set defaults in input
33647881ece5Smarc  */
setup_input(unit)33657e911b15Skarels setup_input(unit)
33667881ece5Smarc 	int unit;
33677e911b15Skarels {
33687e911b15Skarels 	register struct duart *duart;	/* DUART register structure pointer */
33697881ece5Smarc 	register i, bits;
33707e911b15Skarels 	char id_byte;
33717e911b15Skarels 
33727e911b15Skarels 	duart = (struct duart *) qdmap[unit].duart;
33737e911b15Skarels 	duart->imask = 0;
33747e911b15Skarels 
3375b2b69f49Smarc 	/*
3376b2b69f49Smarc 	* setup the DUART for kbd & pointing device
3377b2b69f49Smarc 	*/
33787e911b15Skarels 	duart->cmdA = RESET_M;	/* reset mode reg ptr for kbd */
33797e911b15Skarels 	duart->modeA = 0x13;	/* 8 bits, no parity, rcv IE, */
33807e911b15Skarels 				/* no RTS control,char error mode */
33817e911b15Skarels 	duart->modeA = 0x07;	/* 1 stop bit,CTS does not IE XMT */
33827e911b15Skarels 				/* no RTS control,no echo or loop */
33837e911b15Skarels 	duart->cmdB = RESET_M;	/* reset mode reg pntr for host */
33847e911b15Skarels 	duart->modeB = 0x07;	/* 8 bits, odd parity, rcv IE.. */
33857e911b15Skarels 				/* ..no RTS cntrl, char error mode */
33867e911b15Skarels 	duart->modeB = 0x07;	/* 1 stop bit,CTS does not IE XMT */
33877e911b15Skarels 				/* no RTS control,no echo or loop */
33887e911b15Skarels 	duart->auxctl = 0x00;	/* baud rate set 1 */
33897e911b15Skarels 	duart->clkselA = 0x99;	/* 4800 baud for kbd */
33907e911b15Skarels 	duart->clkselB = 0x99;	/* 4800 baud for mouse */
33917e911b15Skarels 
33927e911b15Skarels 	/* reset everything for keyboard */
33937e911b15Skarels 
33947e911b15Skarels 	for (bits = RESET_M; bits < START_BREAK; bits += 0x10)
33957e911b15Skarels 		duart->cmdA = bits;
33967e911b15Skarels 
33977e911b15Skarels 	/* reset everything for host */
33987e911b15Skarels 
33997e911b15Skarels 	for (bits = RESET_M; bits < START_BREAK; bits += 0x10)
34007e911b15Skarels 		duart->cmdB = bits;
34017e911b15Skarels 
34027e911b15Skarels 	duart->cmdA = EN_RCV | EN_XMT; /* enbl xmt & rcv for kbd */
34037e911b15Skarels 	duart->cmdB = EN_RCV | EN_XMT; /* enbl xmt & rcv for pointer device */
34047e911b15Skarels 
3405b2b69f49Smarc 	/*
34067881ece5Smarc 	* init keyboard defaults (DUART channel A)
34077881ece5Smarc 	*/
34087e911b15Skarels 	for (i = 500; i > 0; --i) {
34097881ece5Smarc 		if (duart->statusA&XMT_RDY) {
34107e911b15Skarels 			duart->dataA = LK_DEFAULTS;
34117e911b15Skarels 			break;
34127e911b15Skarels 		}
34137e911b15Skarels 	}
34147e911b15Skarels 
34157e911b15Skarels 	for (i = 100000; i > 0; --i) {
34167881ece5Smarc 		if (duart->statusA&RCV_RDY) {
34177e911b15Skarels 			break;
34187e911b15Skarels 		}
34197e911b15Skarels 	}
34207e911b15Skarels 
34217881ece5Smarc 	if (duart->dataA)	/* flush the ACK */
34227881ece5Smarc 		;
34237e911b15Skarels 
3424b2b69f49Smarc 	/*
34257881ece5Smarc 	* identify the pointing device
34267881ece5Smarc 	*/
34277e911b15Skarels 	for (i = 500; i > 0; --i) {
34287881ece5Smarc 		if (duart->statusB&XMT_RDY) {
34297e911b15Skarels 			duart->dataB = SELF_TEST;
34307e911b15Skarels 			break;
34317e911b15Skarels 		}
34327e911b15Skarels 	}
34337e911b15Skarels 
3434b2b69f49Smarc 	/*
34357e911b15Skarels 	* wait for 1st byte of self test report */
34367e911b15Skarels 
34377e911b15Skarels 	for (i = 100000; i > 0; --i) {
34387881ece5Smarc 		if (duart->statusB&RCV_RDY) {
34397e911b15Skarels 			break;
34407e911b15Skarels 		}
34417e911b15Skarels 	}
34427e911b15Skarels 
34437e911b15Skarels 	if (i == 0) {
34447881ece5Smarc 		printf("qd[%d]: setup_input: timeout on 1st byte of self test\n"
3445b2b69f49Smarc 		       ,unit);
34467e911b15Skarels 		goto OUT;
34477e911b15Skarels 	}
34487e911b15Skarels 
34497881ece5Smarc 	if (duart->dataB)
34507881ece5Smarc 		;
34517e911b15Skarels 
3452b2b69f49Smarc 	/*
34537881ece5Smarc 	* wait for ID byte of self test report
34547881ece5Smarc 	*/
34557e911b15Skarels 	for (i = 100000; i > 0; --i) {
34567881ece5Smarc 		if (duart->statusB&RCV_RDY) {
34577e911b15Skarels 			break;
34587e911b15Skarels 		}
34597e911b15Skarels 	}
34607e911b15Skarels 
34617e911b15Skarels 	if (i == 0) {
34627881ece5Smarc 		printf("qd[%d]: setup_input: timeout on 2nd byte of self test\n", unit);
34637e911b15Skarels 		goto OUT;
34647e911b15Skarels 	}
34657e911b15Skarels 
34667e911b15Skarels 	id_byte = duart->dataB;
34677e911b15Skarels 
3468b2b69f49Smarc 	/*
34697881ece5Smarc 	* wait for other bytes to come in
34707881ece5Smarc 	*/
34717e911b15Skarels 	for (i = 100000; i > 0; --i) {
34727881ece5Smarc 		if (duart->statusB & RCV_RDY) {
34737881ece5Smarc 			if (duart->dataB)
34747881ece5Smarc 				;
34757e911b15Skarels 			break;
34767e911b15Skarels 		}
34777e911b15Skarels 	}
34787e911b15Skarels 	if (i == 0) {
34797881ece5Smarc 		printf("qd[%d]: setup_input: timeout on 3rd byte of self test\n", unit);
34807e911b15Skarels 		goto OUT;
34817e911b15Skarels 	}
34827e911b15Skarels 	for (i = 100000; i > 0; --i) {
34837881ece5Smarc 		if (duart->statusB&RCV_RDY) {
34847881ece5Smarc 			if (duart->dataB)
34857881ece5Smarc 				;
34867e911b15Skarels 			break;
34877e911b15Skarels 		}
34887e911b15Skarels 	}
34897e911b15Skarels 	if (i == 0) {
34907881ece5Smarc 		printf("qd[%d]: setup_input: timeout on 4th byte of self test\n", unit);
34917e911b15Skarels 		goto OUT;
34927e911b15Skarels 	}
3493b2b69f49Smarc 	/*
34947881ece5Smarc 	* flag pointing device type and set defaults
34957881ece5Smarc 	*/
34967881ece5Smarc 	for (i=100000; i>0; --i)
34977881ece5Smarc 		;		/*XXX*/
34987e911b15Skarels 
34997e911b15Skarels 	if ((id_byte & 0x0F) != TABLET_ID) {
35007e911b15Skarels 		qdflags[unit].pntr_id = MOUSE_ID;
35017e911b15Skarels 
35027e911b15Skarels 		for (i = 500; i > 0; --i) {
35037881ece5Smarc 			if (duart->statusB&XMT_RDY) {
35047e911b15Skarels 				duart->dataB = INC_STREAM_MODE;
35057e911b15Skarels 				break;
35067e911b15Skarels 			}
35077e911b15Skarels 		}
3508b2b69f49Smarc 	}
3509b2b69f49Smarc 	else {
35107e911b15Skarels 		qdflags[unit].pntr_id = TABLET_ID;
35117e911b15Skarels 
35127e911b15Skarels 		for (i = 500; i > 0; --i) {
35137881ece5Smarc 			if (duart->statusB&XMT_RDY) {
35147e911b15Skarels 				duart->dataB = T_STREAM;
35157e911b15Skarels 				break;
35167e911b15Skarels 			}
35177e911b15Skarels 		}
35187e911b15Skarels 	}
35197e911b15Skarels OUT:
35207e911b15Skarels 	duart->imask = qdflags[unit].duart_imask;
35217e911b15Skarels 
35227e911b15Skarels } /* setup_input */
35237e911b15Skarels 
35247881ece5Smarc /*
35257881ece5Smarc  * delay for at least one display frame time
35267e911b15Skarels  *
35277e911b15Skarels  *	return: BAD means that we timed out without ever seeing the
35287e911b15Skarels  *		      vertical sync status bit
35297e911b15Skarels  *		GOOD otherwise
35307881ece5Smarc  */
wait_status(adder,mask)35317e911b15Skarels wait_status(adder, mask)
35327e911b15Skarels 	register struct adder *adder;
35337e911b15Skarels 	register int mask;
35347e911b15Skarels {
35357881ece5Smarc 	register i;
35367e911b15Skarels 
3537b2b69f49Smarc 	for (i = 10000, adder->status = 0 ; i > 0  &&
35387881ece5Smarc 	     !(adder->status&mask) ; --i)
3539b2b69f49Smarc 		;
35407e911b15Skarels 
35417e911b15Skarels 	if (i == 0) {
35427881ece5Smarc 		printf("wait_status: timeout polling for 0x%x in adder->status\n", mask);
35437e911b15Skarels 		return(BAD);
35447e911b15Skarels 	}
35457e911b15Skarels 
35467e911b15Skarels 	return(GOOD);
35477e911b15Skarels 
35487e911b15Skarels } /* wait_status */
35497e911b15Skarels 
35507881ece5Smarc /*
35517881ece5Smarc  * write out onto the ID bus
35527881ece5Smarc  */
write_ID(adder,adrs,data)35537e911b15Skarels write_ID(adder, adrs, data)
35547e911b15Skarels 	register struct adder *adder;
35557e911b15Skarels 	register short adrs;
35567e911b15Skarels 	register short data;
35577e911b15Skarels {
35587881ece5Smarc 	register i;
35597e911b15Skarels 
3560b2b69f49Smarc 	for (i = 100000, adder->status = 0 ;
35617881ece5Smarc 	      i > 0  &&  !(adder->status&ADDRESS_COMPLETE) ; --i)
3562b2b69f49Smarc 		;
35637e911b15Skarels 
35647e911b15Skarels 	if (i == 0)
35657e911b15Skarels 		goto ERR;
35667e911b15Skarels 
3567b2b69f49Smarc 	for (i = 100000, adder->status = 0 ;
35687881ece5Smarc 	      i > 0  &&  !(adder->status&TX_READY) ; --i)
3569b2b69f49Smarc 		;
35707e911b15Skarels 
35717e911b15Skarels 	if (i > 0) {
35727e911b15Skarels 		adder->id_data = data;
35737e911b15Skarels 		adder->command = ID_LOAD | adrs;
35747881ece5Smarc 		return ;
35757e911b15Skarels 	}
35767e911b15Skarels 
35777e911b15Skarels ERR:
35787881ece5Smarc 	printf("write_ID: timeout trying to write to VIPER\n");
35797881ece5Smarc 	return ;
35807e911b15Skarels 
35817e911b15Skarels } /* write_ID */
3582006e9885Smarc #endif
3583