xref: /csrg-svn/sys/vax/uba/qd.c (revision 34732)
134511Smarc /*
234642Smarc * Copyright (c) 1982, 1986 Regents of the University of California.
334642Smarc * All rights reserved.  The Berkeley software License Agreement
434642Smarc * specifies the terms and conditions for redistribution.
534642Smarc *
6*34732Smarc * 		@(#)qd.c	1.9  Berkeley  06/14/88
734642Smarc *
834642Smarc */
934642Smarc 
1030391Skarels /************************************************************************
1134511Smarc *									*
1234615Smarc *			Copyright (c) 1985-1988 by			*
1330391Skarels *		Digital Equipment Corporation, Maynard, MA		*
1430391Skarels *			All rights reserved.				*
1530391Skarels *									*
1630391Skarels *   This software is furnished under a license and may be used and	*
1730391Skarels *   copied  only  in accordance with the terms of such license and	*
1830391Skarels *   with the  inclusion  of  the  above  copyright  notice.   This	*
1930391Skarels *   software  or  any  other copies thereof may not be provided or	*
2030391Skarels *   otherwise made available to any other person.  No title to and	*
2130391Skarels *   ownership of the software is hereby transferred.			*
2230391Skarels *									*
2330391Skarels *   The information in this software is subject to change  without	*
2430391Skarels *   notice  and should not be construed as a commitment by Digital	*
2530391Skarels *   Equipment Corporation.						*
2630391Skarels *									*
2730391Skarels *   Digital assumes no responsibility for the use  or  reliability	*
2830391Skarels *   of its software on equipment which is not supplied by Digital.	*
2930391Skarels *									*
3030391Skarels *************************************************************************/
3134615Smarc 
3230391Skarels /*
3334642Smarc  * qd.c - QDSS display driver for VAXSTATION-II GPX workstation
3430391Skarels  */
3530391Skarels 
3634642Smarc #include "qd.h"
3734615Smarc 
3834511Smarc #if NQD > 0
3934615Smarc #include "types.h"
4034642Smarc #include "../machine/pte.h"
4134642Smarc #include "../machine/mtpr.h"
4234511Smarc #include "../machine/cpu.h"
4334642Smarc #include "param.h"
4434642Smarc #include "conf.h"
4534642Smarc #include "dir.h"
4634642Smarc #include "user.h"
4734642Smarc #include "qdioctl.h"
4834511Smarc #include "tty.h"
4934642Smarc #include "map.h"
5034642Smarc #include "buf.h"
5134642Smarc #include "vm.h"
5234642Smarc #include "bk.h"
5334642Smarc #include "clist.h"
5434642Smarc #include "file.h"
5534642Smarc #include "uio.h"
5634642Smarc #include "kernel.h"
5734615Smarc #include "exec.h"
5834615Smarc #include "proc.h"
5934642Smarc #include "ubareg.h"
6034642Smarc #include "ubavar.h"
6134511Smarc #include "syslog.h"
6234642Smarc #include "qduser.h"	/* definitions shared with user level client */
6334615Smarc #include "qdreg.h"	/* QDSS device register structures */
6432012Smarc 
6534642Smarc /*
6634642Smarc  * QDSS driver status flags for tracking operational state
6734642Smarc  */
6834642Smarc struct qdflags {
6934642Smarc 	u_int inuse;		/* which minor dev's are in use now */
7034642Smarc 	u_int config;		/* I/O page register content */
7134642Smarc 	u_int mapped;		/* user mapping status word */
7234642Smarc 	u_int kernel_loop;	/* if kernel console is redirected */
7334642Smarc 	u_int user_dma;		/* DMA from user space in progress */
7434642Smarc 	u_short pntr_id;	/* type code of pointing device */
7534642Smarc 	u_short duart_imask;	/* shadowing for duart intrpt mask reg */
7634642Smarc 	u_short adder_ie;	/* shadowing for adder intrpt enbl reg */
7734642Smarc 	u_short curs_acc;	/* cursor acceleration factor */
7834642Smarc 	u_short curs_thr;	/* cursor acceleration threshold level */
7934642Smarc 	u_short tab_res;	/* tablet resolution factor */
8034642Smarc 	u_short selmask;	/* mask for active qd select entries */
8134642Smarc };
8232012Smarc 
8334642Smarc /*
8434642Smarc  * bit definitions for 'inuse' entry
8534642Smarc  */
8632012Smarc #define CONS_DEV	0x01
8732012Smarc #define GRAPHIC_DEV	0x04
8832012Smarc 
8934642Smarc /*
9034642Smarc  * bit definitions for 'mapped' member of flag structure
9134642Smarc  */
9232012Smarc #define MAPDEV		0x01		/* hardware is mapped */
9332012Smarc #define MAPDMA		0x02		/* DMA buffer mapped */
9432012Smarc #define MAPEQ		0x04		/* event queue buffer mapped */
9532012Smarc #define MAPSCR		0x08		/* scroll param area mapped */
9632012Smarc #define MAPCOLOR	0x10		/* color map writing buffer mapped */
9732012Smarc 
9834642Smarc /*
9934642Smarc  * bit definitions for 'selmask' member of qdflag structure
10034642Smarc  */
10132012Smarc #define SEL_READ	0x01		/* read select is active */
10232012Smarc #define SEL_WRITE	0x02		/* write select is active */
10332012Smarc 
10434642Smarc /*
105*34732Smarc  * constants used in shared memory operations
106*34732Smarc  */
10732012Smarc #define EVENT_BUFSIZE  1024	/* # of bytes per device's event buffer */
10832012Smarc #define MAXEVENTS  ( (EVENT_BUFSIZE - sizeof(struct qdinput))	 \
10934642Smarc 	/ sizeof(struct _vs_event) )
11034527Smarc #define DMA_BUFSIZ	(1024 * 10)
11132012Smarc #define COLOR_BUFSIZ  ((sizeof(struct color_buf) + 512) & ~0x01FF)
11232012Smarc 
11334642Smarc /*
114*34732Smarc  * reference to an array of "uba_device" structures built by the auto
115*34732Smarc  * configuration program.  The uba_device structure decribes the device
116*34732Smarc  * sufficiently for the driver to talk to it.  The auto configuration code
117*34732Smarc  * fills in the uba_device structures (located in ioconf.c) from user
118*34732Smarc  * maintained info.
119*34732Smarc  */
12034642Smarc struct uba_device *qdinfo[NQD];  /* array of pntrs to each QDSS's */
12134642Smarc struct tty qd_tty[NQD*4];	/* teletype structures for each.. */
122*34732Smarc extern char qvmem[][128*NBPG];
12334642Smarc extern struct pte QVmap[][128];
12434642Smarc #define CHUNK	  (64 * 1024)
12534642Smarc #define QMEMSIZE  (1024 * 1024 * 4)	/* 4 meg */
12632012Smarc 
12734642Smarc /*
12834642Smarc  * static storage used by multiple functions in this code
12934642Smarc  */
13034642Smarc int Qbus_unmap[NQD];		/* Qbus mapper release code */
13134642Smarc struct qdflags qdflags[NQD];	/* QDSS device status flags */
13234642Smarc struct qdmap qdmap[NQD];	/* QDSS register map structure */
13334642Smarc caddr_t qdbase[NQD];		/* base address of each QDSS unit */
13434642Smarc struct buf qdbuf[NQD];		/* buf structs used by strategy */
13534642Smarc short qdopened[NQD];		/* graphics device is open exclusive use */
13632012Smarc 
13734642Smarc /*
138*34732Smarc  * the array "event_shared[]" is made up of a number of event queue buffers
139*34732Smarc  * equal to the number of QDSS's configured into the running kernel (NQD).
140*34732Smarc  * Each event queue buffer begins with an event queue header (struct qdinput)
141*34732Smarc  * followed by a group of event queue entries (struct _vs_event).  The array
142*34732Smarc  * "*eq_header[]" is an array of pointers to the start of each event queue
143*34732Smarc  * buffer in "event_shared[]".
144*34732Smarc  */
14532012Smarc #define EQSIZE ((EVENT_BUFSIZE * NQD) + 512)
14632012Smarc 
14734642Smarc char event_shared[EQSIZE];	    /* reserve space for event bufs */
14834642Smarc struct qdinput *eq_header[NQD];     /* event queue header pntrs */
14932012Smarc 
15034642Smarc /*
151*34732Smarc  * This allocation method reserves enough memory pages for NQD shared DMA I/O
152*34732Smarc  * buffers.  Each buffer must consume an integral number of memory pages to
153*34732Smarc  * guarantee that a following buffer will begin on a page boundary.  Also,
154*34732Smarc  * enough space is allocated so that the FIRST I/O buffer can start at the
155*34732Smarc  * 1st page boundary after "&DMA_shared".  Page boundaries are used so that
156*34732Smarc  * memory protections can be turned on/off for individual buffers.
157*34732Smarc  */
15832012Smarc #define IOBUFSIZE  ((DMA_BUFSIZ * NQD) + 512)
15932012Smarc 
16034642Smarc char DMA_shared[IOBUFSIZE];	    /* reserve I/O buffer space */
16134642Smarc struct DMAreq_header *DMAheader[NQD];  /* DMA buffer header pntrs */
16232012Smarc 
16334642Smarc /*
164*34732Smarc  * The driver assists a client in scroll operations by loading dragon
165*34732Smarc  * registers from an interrupt service routine.	The loading is done using
166*34732Smarc  * parameters found in memory shrade between the driver and it's client.
167*34732Smarc  * The scroll parameter structures are ALL loacted in the same memory page
168*34732Smarc  * for reasons of memory economy.
169*34732Smarc  */
17034642Smarc char scroll_shared[2 * 512];	/* reserve space for scroll structs */
17134642Smarc struct scroll *scroll[NQD];	/* pointers to scroll structures */
17232012Smarc 
17334642Smarc /*
174*34732Smarc  * the driver is programmable to provide the user with color map write
175*34732Smarc  * services at VSYNC interrupt time.  At interrupt time the driver loads
176*34732Smarc  * the color map with any user-requested load data found in shared memory
177*34732Smarc  */
17832012Smarc #define COLOR_SHARED  ((COLOR_BUFSIZ * NQD) + 512)
17932012Smarc 
18034642Smarc char color_shared[COLOR_SHARED];      /* reserve space: color bufs */
18134642Smarc struct color_buf *color_buf[NQD];     /* pointers to color bufs */
18232012Smarc 
18334642Smarc /*
184*34732Smarc  * mouse input event structures
185*34732Smarc  */
18634642Smarc struct mouse_report last_rep[NQD];
18734642Smarc struct mouse_report current_rep[NQD];
18832012Smarc 
189*34732Smarc struct proc *qdrsel[NQD]; 	/* process waiting for select */
19034642Smarc struct _vs_cursor cursor[NQD];	/* console cursor */
19134642Smarc int qdcount = 0;		/* count of successfully probed qd's */
19234642Smarc int nNQD = NQD;
19334642Smarc int DMAbuf_size = DMA_BUFSIZ;
19434642Smarc int QDlast_DMAtype;             /* type of the last DMA operation */
19532012Smarc 
19634642Smarc #define QDSSMAJOR	41	/* QDSS major device number */
19734642Smarc /*
198*34732Smarc  * macro to get system time.  Used to time stamp event queue entries
199*34732Smarc  */
20030391Skarels #define TOY ((time.tv_sec * 100) + (time.tv_usec / 10000))
20130391Skarels 
20234642Smarc int qdprobe();
20334642Smarc int qdattach();
20434642Smarc int qddint();			/* DMA gate array intrpt service */
20534642Smarc int qdaint();			/* Dragon ADDER intrpt service */
20634642Smarc int qdiint();
20730391Skarels 
20834642Smarc u_short qdstd[] = { 0 };
20930391Skarels 
21034642Smarc struct uba_driver qddriver = {
211*34732Smarc 	qdprobe,		/* device probe entry */
212*34732Smarc 	0,			/* no slave device */
213*34732Smarc 	qdattach,		/* device attach entry */
214*34732Smarc 	0,			/* no "fill csr/ba to start" */
21534642Smarc 	qdstd,			/* device addresses */
21634642Smarc 	"qd",			/* device name string */
21734642Smarc 	qdinfo			/* ptr to QDSS's uba_device struct */
21834642Smarc };
21930391Skarels 
22034615Smarc #define QDPRIOR (PZERO-1)		/* must be negative */
22130391Skarels #define FALSE	0
22230391Skarels #define TRUE	~FALSE
22330391Skarels #define BAD	-1
22430391Skarels #define GOOD	0
22530391Skarels 
22634642Smarc /*
22734642Smarc  * macro to create a system virtual page number from system virtual adrs
22834642Smarc  */
22934642Smarc #define VTOP(x)  (((int)x & ~0xC0000000) >> PGSHIFT)
23030391Skarels 
23134642Smarc /*
23234642Smarc  * QDSS register address offsets from start of QDSS address space
23334642Smarc  */
23430391Skarels #define QDSIZE	 (52 * 1024)	/* size of entire QDSS foot print */
23530391Skarels #define TMPSIZE  (16 * 1024)	/* template RAM is 8k SHORT WORDS */
23630391Skarels #define TMPSTART 0x8000 	/* offset of template RAM from base adrs */
23730391Skarels #define REGSIZE  (5 * 512)	/* regs touch 2.5k (5 pages) of addr space */
23830391Skarels #define REGSTART 0xC000 	/* offset of reg pages from base adrs */
23930391Skarels #define ADDER	(REGSTART+0x000)
24030391Skarels #define DGA	(REGSTART+0x200)
24130391Skarels #define DUART	(REGSTART+0x400)
24230391Skarels #define MEMCSR	(REGSTART+0x800)
24330391Skarels #define CLRSIZE  (3 * 512)		/* color map size */
24430391Skarels #define CLRSTART (REGSTART+0xA00)	/* color map start offset from base */
24534642Smarc /*  0x0C00 really */
24630391Skarels #define RED	(CLRSTART+0x000)
24730391Skarels #define BLUE	(CLRSTART+0x200)
24830391Skarels #define GREEN	(CLRSTART+0x400)
24930391Skarels 
25030391Skarels 
25134642Smarc /*
25234642Smarc  * QDSS minor device numbers.  The *real* minor device numbers are in
25334642Smarc  * the bottom two bits of the major/minor device spec.  Bits 2 and up are
25434642Smarc  * used to specify the QDSS device number (ie: which one?)
25534642Smarc  */
25630391Skarels 
25730391Skarels #define CONS		0
25830391Skarels #define GRAPHIC 	2
25930391Skarels 
26034642Smarc /*
26134642Smarc  * console cursor bitmap (white block cursor)
26234642Smarc  */
26334642Smarc short cons_cursor[32] = {
26434642Smarc 	/* A */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
26534642Smarc 	0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
26634642Smarc 	/* B */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
26734642Smarc 	0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF
26834642Smarc };
26930391Skarels 
27034642Smarc /*
27134642Smarc  * constants used in font operations
27234642Smarc  */
27334615Smarc #define CHARS		190 			/* # of chars in the font */
27430391Skarels #define CHAR_HEIGHT	15			/* char height in pixels */
27530391Skarels #define CHAR_WIDTH	8			/* char width in pixels*/
27630391Skarels #define FONT_WIDTH	(CHAR_WIDTH * CHARS)	/* font width in pixels */
27730391Skarels #define ROWS		CHAR_HEIGHT
27830391Skarels #define FONT_X		0			/* font's off screen adrs */
27930391Skarels #define FONT_Y		(2048 - CHAR_HEIGHT)
28030391Skarels 
28134642Smarc /* Offset to second row characters (XXX - should remove) */
28234615Smarc #define FONT_OFFSET	((MAX_SCREEN_X/CHAR_WIDTH)*CHAR_HEIGHT)
28330391Skarels 
28434642Smarc extern char q_font[];		/* reference font object code */
28534642Smarc extern	u_short q_key[];	/* reference key xlation tables */
28634642Smarc extern	u_short q_shift_key[];
28734642Smarc extern	char *q_special[];
28830391Skarels 
28934642Smarc /*
29034642Smarc  * definitions for cursor acceleration reporting
29134642Smarc  */
29230391Skarels #define ACC_OFF 	0x01		/* acceleration is inactive */
29330391Skarels 
29434642Smarc /*
29534642Smarc  * virtual console support.
29634642Smarc  */
29734642Smarc extern (*v_putc)();
29834642Smarc extern struct cdevsw *consops;
29934642Smarc int qdputc();
30034642Smarc int qdstart();
30130391Skarels 
30234642Smarc /*
30334642Smarc  * LK-201 state storage for input console keyboard conversion to ASCII
30434642Smarc  */
30534642Smarc struct q_keyboard {
30634642Smarc 	int shift;			/* state variables	*/
30734642Smarc 	int cntrl;
30834642Smarc 	int lock;
30934642Smarc 	int lastcode;			/* last keycode typed	*/
31034642Smarc 	unsigned kup[8];		/* bits for each keycode*/
31134642Smarc 	unsigned dkeys[8];		/* down/up mode keys	*/
31234642Smarc 	char last;			/* last character	*/
31334642Smarc } q_keyboard;
31430391Skarels 
31534642Smarc /*
31634642Smarc  * tty settings on first open
31734642Smarc  */
31834615Smarc #define IFLAGS	(EVENP|ECHO|XTABS|CRMOD)
31934615Smarc #ifdef POSIXTTY
32034615Smarc #define IFLAG (BRKINT|ISTRIP|IXON|IXANY|ICRNL|IEXTEN|IMAXBEL)
32134615Smarc #define OFLAG (OPOST|OXTABS|ONLCR)
32234615Smarc #define LFLAG (ISIG|ICANON|ECHO)
32334615Smarc #define CFLAG (PARENB|CREAD|CS7|CLOCAL)
32434615Smarc #endif
32534615Smarc 
326*34732Smarc /*
327*34732Smarc  * Init QDSS as console (before probe routine)
328*34732Smarc  */
32930391Skarels 
33030391Skarels qdcons_init()
33130391Skarels {
332*34732Smarc 	register unit;
33330391Skarels 	caddr_t phys_adr;		/* physical QDSS base adrs */
33434615Smarc 	u_int mapix;			/* index into QVmap[] array */
33534615Smarc 	struct percpu *pcpu;		/* pointer to cpusw structure  */
33634615Smarc 	register struct qbus *qb;
33730391Skarels 	u_short *qdaddr;		/* address of QDSS IO page CSR */
33830391Skarels 	u_short *devptr;		/* vitual device space */
33934615Smarc 	extern cnputc();
34030391Skarels 
34130391Skarels #define QDSSCSR 0x1F00
34230391Skarels 
34332012Smarc 	if (v_putc != cnputc)
344*34732Smarc 	    return 0;
34532012Smarc 
34630391Skarels 	unit = 0;
34730391Skarels 
34834642Smarc 	/*
34934642Smarc 	 * find the cpusw entry that matches this machine.
35034642Smarc 	 */
35132012Smarc 	for (pcpu = percpu; pcpu && pcpu->pc_cputype != cpu; pcpu++)
35232012Smarc 		;
35332012Smarc 	if (pcpu == NULL)
354*34732Smarc 	    return 0;
35530391Skarels 
35632012Smarc 	/*
35734615Smarc 	 * Map device registers - the last 8K of qvmem.
35832012Smarc 	 */
35932012Smarc 	qb = (struct qbus *)pcpu->pc_io->io_details;
36032012Smarc 	ioaccess(qb->qb_iopage, UMEMmap[0] + qb->qb_memsize,
361*34732Smarc 		 UBAIOPAGES * NBPG);
36232012Smarc 	devptr = (u_short *)((char *)umem[0]+(qb->qb_memsize * NBPG));
36330391Skarels 	qdaddr = (u_short *)((u_int)devptr + ubdevreg(QDSSCSR));
364*34732Smarc 	if (badaddr((caddr_t)qdaddr, sizeof(short)))
365*34732Smarc 		return 0;
36634615Smarc 
36732012Smarc 	/*
36832012Smarc 	 * Map q-bus memory used by qdss. (separate map)
36932012Smarc 	 */
37032012Smarc 	mapix = QMEMSIZE - (CHUNK * (unit + 1));
37132012Smarc 	phys_adr = qb->qb_maddr + mapix;
37232012Smarc 	ioaccess(phys_adr, QVmap[0], (CHUNK*NQD));
37330391Skarels 
37432012Smarc 	/*
37532012Smarc 	 * tell QDSS which Q memory address base to decode
37634642Smarc 	 * (shifted right 16 bits - its in 64K units)
37732012Smarc 	 */
37832012Smarc 	*qdaddr = (u_short)((int)mapix >> 16);
37930391Skarels 	qdflags[unit].config = *(u_short *)qdaddr;
38030391Skarels 
38134642Smarc 	/*
38234642Smarc 	 * load qdmap struct with the virtual addresses of the QDSS elements
38334642Smarc 	 */
38434615Smarc 	qdbase[unit] = (caddr_t) (qvmem[0]);
38530391Skarels 	qdmap[unit].template = qdbase[unit] + TMPSTART;
38630391Skarels 	qdmap[unit].adder = qdbase[unit] + ADDER;
38730391Skarels 	qdmap[unit].dga = qdbase[unit] + DGA;
38830391Skarels 	qdmap[unit].duart = qdbase[unit] + DUART;
38930391Skarels 	qdmap[unit].memcsr = qdbase[unit] + MEMCSR;
39030391Skarels 	qdmap[unit].red = qdbase[unit] + RED;
39130391Skarels 	qdmap[unit].blue = qdbase[unit] + BLUE;
39230391Skarels 	qdmap[unit].green = qdbase[unit] + GREEN;
39330391Skarels 
39430391Skarels 	qdflags[unit].duart_imask = 0;	/* init shadow variables */
39530391Skarels 
39634642Smarc 	/*
39734642Smarc 	 * init the QDSS
39834642Smarc 	 */
39934642Smarc 	/*
40032012Smarc 	printf("qdbase[0] = %x, qdmap[0].memcsr = %x\n",
40134642Smarc 		(char *)qdbase[0], qdmap[0].memcsr);
40234642Smarc 	*/
40332012Smarc 
40430391Skarels 	*(short *)qdmap[unit].memcsr |= SYNC_ON; /* once only: turn on sync */
40530391Skarels 
40630391Skarels 	cursor[unit].x = 0;
40730391Skarels 	cursor[unit].y = 0;
40830391Skarels 	init_shared(unit);		/* init shared memory */
40930391Skarels 	setup_dragon(unit);		/* init the ADDER/VIPER stuff */
41030391Skarels 	clear_qd_screen(unit);		/* clear the screen */
41130391Skarels 	ldfont(unit);			/* load the console font */
41230391Skarels 	ldcursor(unit, cons_cursor);	/* load default cursor map */
41330391Skarels 	setup_input(unit);		/* init the DUART */
41434642Smarc 	v_putc = qdputc;		/* kernel console output to qdss */
41534642Smarc 	consops = &cdevsw[QDSSMAJOR];	/* virtual console is qdss */
416*34732Smarc 	return 1;
41730391Skarels 
41830391Skarels } /* qdcons_init */
41930391Skarels 
420*34732Smarc /*
421*34732Smarc  *  Configure QDSS into Q memory and make it intrpt.
422*34732Smarc  *
423*34732Smarc  *  side effects: QDSS gets mapped into Qbus memory space at the first
424*34732Smarc  *		 vacant 64kb boundary counting back from the top of
425*34732Smarc  *		 Qbus memory space (qvmem+4mb)
426*34732Smarc  *
427*34732Smarc  *  return: QDSS bus request level and vector address returned in
428*34732Smarc  *	   registers by UNIX convention.
429*34732Smarc  *
430*34732Smarc  */
43130391Skarels qdprobe(reg)
432*34732Smarc 	caddr_t reg;	/* character pointer to the QDSS I/O page register */
43330391Skarels {
43434642Smarc 	register int br, cvec;  	/* value-result */
43530391Skarels 	register int unit;
43630391Skarels 	struct dga *dga;		/* pointer to gate array structure */
437*34732Smarc 	int vector;
438*34732Smarc #ifdef notdef
43930391Skarels 	int *ptep;			/* page table entry pointer */
44030391Skarels 	caddr_t phys_adr;		/* physical QDSS base adrs */
44130391Skarels 	u_int mapix;
442*34732Smarc #endif
44330391Skarels 
444*34732Smarc #ifdef lint
445*34732Smarc 	br = 0; cvec = br; br = cvec; nNQD = br; br = nNQD;
446*34732Smarc 	qddint(0); qdaint(0); qdiint(0); (void)qdgetc();
447*34732Smarc #endif
448*34732Smarc 
44934642Smarc 	/*
45034642Smarc 	 * calculate board unit number from I/O page register address
45134642Smarc 	 */
45230391Skarels 	unit = (int) (((int)reg >> 1) & 0x0007);
45330391Skarels 
45434642Smarc 	/*
45534642Smarc 	 * QDSS regs must be mapped to Qbus memory space at a 64kb
45634642Smarc  	 * physical boundary.  The Qbus memory space is mapped into
45734642Smarc 	 * the system memory space at config time.  After config
45834642Smarc 	 * runs, "qvmem[0]" (ubavar.h) holds the system virtual adrs
45934642Smarc 	 * of the start of Qbus memory.   The Qbus memory page table
46034642Smarc 	 * is found via an array of pte ptrs called "QVmap[]" (ubavar.h)
46134642Smarc 	 * which is also loaded at config time.   These are the
46234642Smarc 	 * variables used below to find a vacant 64kb boundary in
46334642Smarc 	 * Qbus memory, and load it's corresponding physical adrs
46434642Smarc 	 * into the QDSS's I/O page CSR.
46534642Smarc 	 */
46630391Skarels 
46734615Smarc 	/*
46834615Smarc 	 * Only if QD is the graphics device.
46934615Smarc 	 */
47034615Smarc 
47130391Skarels 	/* if this QDSS is NOT the console, then do init here.. */
47230391Skarels 
47334615Smarc 	if (unit != 0) {
47434615Smarc 		printf("qd: can't support two qdss's (yet)\n");
475*34732Smarc #ifdef notdef	/* can't test */
47634642Smarc 		if (v_consputc != qdputc  ||  unit != 0) {
47730391Skarels 
47834642Smarc 			/*
47934642Smarc 			* read QDSS config info
48034642Smarc 			*/
48134642Smarc 			qdflags[unit].config = *(u_short *)reg;
48234615Smarc 
48334642Smarc 			/*
48434642Smarc 			* find an empty 64kb adrs boundary
48534642Smarc 			*/
48630391Skarels 
48734642Smarc 			qdbase[unit] = (caddr_t) (qvmem[0] + QMEMSIZE - CHUNK);
48830391Skarels 
48934642Smarc 			/*
490*34732Smarc 			* find the cpusw entry that matches this machine.
491*34732Smarc 			*/
49234642Smarc 			cpup = &cpusw[cpu];
493*34732Smarc 			while (!(BADADDR(qdbase[unit], sizeof(short))))
494*34732Smarc 				qdbase[unit] -= CHUNK;
49534615Smarc 
49634642Smarc 			/*
497*34732Smarc 			* tell QDSS which Q memory address base to decode
498*34732Smarc 			*/
49934642Smarc 			mapix = (int) (VTOP(qdbase[unit]) - VTOP(qvmem[0]));
50034642Smarc 			ptep = (int *) QVmap[0] + mapix;
50134642Smarc 			phys_adr = (caddr_t)(((int)*ptep&0x001FFFFF)<<PGSHIFT);
50234642Smarc 			*(u_short *)reg = (u_short) ((int)phys_adr >> 16);
50334615Smarc 
50434642Smarc 			/*
50534642Smarc 			* load QDSS adrs map with system addresses
50634642Smarc 			* of device regs
50734642Smarc 			*/
50834642Smarc 			qdmap[unit].template = qdbase[unit] + TMPSTART;
50934642Smarc 			qdmap[unit].adder = qdbase[unit] + ADDER;
51034642Smarc 			qdmap[unit].dga = qdbase[unit] + DGA;
51134642Smarc 			qdmap[unit].duart = qdbase[unit] + DUART;
51234642Smarc 			qdmap[unit].memcsr = qdbase[unit] + MEMCSR;
51334642Smarc 			qdmap[unit].red = qdbase[unit] + RED;
51434642Smarc 			qdmap[unit].blue = qdbase[unit] + BLUE;
51534642Smarc 			qdmap[unit].green = qdbase[unit] + GREEN;
51630391Skarels 
51734642Smarc 			/* device init */
51834615Smarc 
51934642Smarc 			cursor[unit].x = 0;
52034642Smarc 			cursor[unit].y = 0;
52134642Smarc 			init_shared(unit);		/* init shared memory */
52234642Smarc 			setup_dragon(unit); 	/* init the ADDER/VIPER stuff */
52334642Smarc 			ldcursor(unit, cons_cursor);	/* load default cursor map */
52434642Smarc 			setup_input(unit);		/* init the DUART */
52534642Smarc 			clear_qd_screen(unit);
52634642Smarc 			ldfont(unit);			/* load the console font */
52730391Skarels 
52834642Smarc 			/* once only: turn on sync */
52930391Skarels 
53034642Smarc 			*(short *)qdmap[unit].memcsr |= SYNC_ON;
53134642Smarc 		}
53234615Smarc #endif /*notdef*/
53330391Skarels 	}
53430391Skarels 
53534642Smarc 	/*
53634642Smarc 	* The QDSS interrupts at HEX vectors xx0 (DMA) xx4
53734642Smarc 	* (ADDER) and xx8 (DUART).  Therefore, we take three
53834642Smarc 	* vectors from the vector pool, and then continue
53934642Smarc 	* to take them until we get a xx0 HEX vector.  The
54034642Smarc 	* pool provides vectors in contiguous decending
54134642Smarc 	* order.
54234642Smarc 	*/
54330391Skarels 
54430391Skarels 	vector = (uba_hd[0].uh_lastiv -= 4*3);	/* take three vectors */
54530391Skarels 
54634642Smarc 	while (vector & 0x0F) {		   /* if lo nibble != 0.. */
54734642Smarc 		/* ..take another vector */
54834642Smarc 		vector = (uba_hd[0].uh_lastiv -= 4);
54930391Skarels 	}
55030391Skarels 
55134642Smarc 	/*
55234642Smarc 	* setup DGA to do a DMA interrupt (transfer count = 0)
55334642Smarc 	*/
55430391Skarels 	dga = (struct dga *) qdmap[unit].dga;
55534642Smarc 	dga->csr = (short) HALT;	/* disable everything */
55634642Smarc 	dga->ivr = (short) vector;	/* load intrpt base vector */
55734642Smarc 	dga->bytcnt_lo = (short) 0;	/* DMA xfer count = 0 */
55830391Skarels 	dga->bytcnt_hi = (short) 0;
55930391Skarels 
56034642Smarc 	/*
56134642Smarc 	* turn on DMA interrupts
56234642Smarc 	*/
56330391Skarels 	dga->csr &= ~SET_DONE_FIFO;
56430391Skarels 	dga->csr |= DMA_IE | DL_ENB;
56530391Skarels 
56630391Skarels 	DELAY(20000);			/* wait for the intrpt */
56730391Skarels 	dga->csr = HALT;		/* stop the wheels */
56830391Skarels 
56930391Skarels 	if (cvec != vector)		/* if vector != base vector.. */
570*34732Smarc 		return(0);		/* ..return = 'no device' */
57130391Skarels 
57234615Smarc 	/*
57334642Smarc 	* score this as an existing qdss
57434642Smarc 	*/
57534615Smarc 	qdcount++;
57634615Smarc 
57730391Skarels 	return(sizeof(short));	    /* return size of QDSS I/O page reg */
57830391Skarels 
57930391Skarels } /* qdprobe */
58030391Skarels 
58130391Skarels qdattach(ui)
58234642Smarc 	struct uba_device *ui;
58330391Skarels {
584*34732Smarc 	register unit;			/* QDSS module # for this call */
58530391Skarels 
58630391Skarels 	unit = ui->ui_unit;		/* get QDSS number */
58730391Skarels 
58834642Smarc 	/*
58934642Smarc 	* init "qdflags[]" for this QDSS
59034642Smarc 	*/
59130391Skarels 	qdflags[unit].inuse = 0;	/* init inuse variable EARLY! */
59230391Skarels 	qdflags[unit].mapped = 0;
59334615Smarc 	qdflags[unit].kernel_loop = -1;
59430391Skarels 	qdflags[unit].user_dma = 0;
59530391Skarels 	qdflags[unit].curs_acc = ACC_OFF;
59630391Skarels 	qdflags[unit].curs_thr = 128;
59730391Skarels 	qdflags[unit].tab_res = 2;	/* default tablet resolution factor */
59830391Skarels 	qdflags[unit].duart_imask = 0;	/* init shadow variables */
59930391Skarels 	qdflags[unit].adder_ie = 0;
60030391Skarels 
60134642Smarc 	/*
60234642Smarc 	* init structures used in kbd/mouse interrupt service.	This code must
60334642Smarc 	* come after the "init_shared()" routine has run since that routine
60434642Smarc 	* inits the eq_header[unit] structure used here.
60534642Smarc 	*/
60630391Skarels 
60734642Smarc 	/*
60834642Smarc 	* init the "latest mouse report" structure
60934642Smarc 	*/
61030391Skarels 	last_rep[unit].state = 0;
61130391Skarels 	last_rep[unit].dx = 0;
61230391Skarels 	last_rep[unit].dy = 0;
61330391Skarels 	last_rep[unit].bytcnt = 0;
61430391Skarels 
61534642Smarc 	/*
616*34732Smarc 	* init the event queue (except mouse position)
617*34732Smarc 	*/
618*34732Smarc 	eq_header[unit]->header.events =
619*34732Smarc 	    (struct _vs_event *)((int)eq_header[unit] + sizeof(struct qdinput));
62030391Skarels 
62130391Skarels 	eq_header[unit]->header.size = MAXEVENTS;
62230391Skarels 	eq_header[unit]->header.head = 0;
62330391Skarels 	eq_header[unit]->header.tail = 0;
62430391Skarels 
62534642Smarc 	/*
62634642Smarc 	 * open exclusive for graphics device.
62734642Smarc 	 */
62834642Smarc 	qdopened[unit] = 0;
62930391Skarels 
63030391Skarels } /* qdattach */
63130391Skarels 
632*34732Smarc /*ARGSUSED*/
63330391Skarels qdopen(dev, flag)
63434642Smarc 	dev_t dev;
63534642Smarc 	int flag;
63630391Skarels {
63730391Skarels 	register struct uba_device *ui; /* ptr to uba structures */
63830391Skarels 	register struct dga *dga;	/* ptr to gate array struct */
63930391Skarels 	register struct tty *tp;
64030391Skarels 	struct duart *duart;
641*34732Smarc 	int unit;
642*34732Smarc 	int minor_dev;
64330391Skarels 
64430391Skarels 	minor_dev = minor(dev); /* get QDSS minor device number */
64530391Skarels 	unit = minor_dev >> 2;
64630391Skarels 
64734642Smarc 	/*
64834642Smarc 	* check for illegal conditions
64934642Smarc 	*/
65030391Skarels 	ui = qdinfo[unit];		/* get ptr to QDSS device struct */
65130391Skarels 	if (ui == 0  || ui->ui_alive == 0)
65234642Smarc 		return(ENXIO);		/* no such device or address */
65330391Skarels 
65430391Skarels 	duart = (struct duart *) qdmap[unit].duart;
65530391Skarels 	dga = (struct dga *) qdmap[unit].dga;
65630391Skarels 
65730391Skarels 	if ((minor_dev & 0x03) == 2) {
65834642Smarc 		/*
65934642Smarc 		* this is the graphic device...
66034642Smarc 		*/
66134642Smarc 		if (qdopened[unit] != 0)
662*34732Smarc 			return(EBUSY);
66334642Smarc 		else
66434642Smarc 			qdopened[unit] = 1;
66534642Smarc 		qdflags[unit].inuse |= GRAPHIC_DEV;  /* graphics dev is open */
66634642Smarc 		/*
66734642Smarc 		 * enble kbd & mouse intrpts in DUART mask reg
66834642Smarc 		 */
66934642Smarc 		qdflags[unit].duart_imask |= 0x22;
67034642Smarc 		duart->imask = qdflags[unit].duart_imask;
67134642Smarc 	} else {
67234642Smarc 		/*
67334642Smarc 		* this is the console
67434642Smarc 		*/
67534642Smarc 		qdflags[unit].inuse |= CONS_DEV;  /* mark console as open */
67634642Smarc 		dga->csr |= CURS_ENB;
67734642Smarc 		qdflags[unit].duart_imask |= 0x02;
67834642Smarc 		duart->imask = qdflags[unit].duart_imask;
67934642Smarc 		/*
68034642Smarc 		* some setup for tty handling
68134642Smarc 		*/
68234642Smarc 		tp = &qd_tty[minor_dev];
68334642Smarc 		tp->t_addr = ui->ui_addr;
68434642Smarc 		tp->t_oproc = qdstart;
68534642Smarc 		if ((tp->t_state & TS_ISOPEN) == 0) {
68634642Smarc 			ttychars(tp);
68734642Smarc 			tp->t_flags = IFLAGS;
68834642Smarc 			tp->t_ispeed = B9600;
68934642Smarc 			tp->t_ospeed = B9600;
69034642Smarc 			tp->t_state = TS_ISOPEN | TS_CARR_ON;
69134642Smarc #ifdef POSIXTTY
69234642Smarc 			tp->t_iflag = TTYDEF_IFLAG;
69334642Smarc 			tp->t_oflag = TTYDEF_OFLAG;
69434642Smarc 			tp->t_lflag = TTYDEF_LFLAG;
69534642Smarc 			tp->t_cflag = TTYDEF_CFLAG;
69634642Smarc #endif
69732012Smarc 		}
69834642Smarc 		/*
69934642Smarc 		* enable intrpts, open line discipline
70034642Smarc 		*/
70134642Smarc 		dga->csr |= GLOBAL_IE;	/* turn on the interrupts */
70234642Smarc 		return ((*linesw[tp->t_line].l_open)(dev, tp));
70330391Skarels 	}
70430391Skarels 	dga->csr |= GLOBAL_IE;	/* turn on the interrupts */
70530391Skarels 	return(0);
70630391Skarels 
70730391Skarels } /* qdopen */
70830391Skarels 
709*34732Smarc /*ARGSUSED*/
71030391Skarels qdclose(dev, flag)
71134642Smarc 	dev_t dev;
71234642Smarc 	int flag;
71330391Skarels {
71430391Skarels 	register struct tty *tp;
71530391Skarels 	register struct qdmap *qd;
71630391Skarels 	register int *ptep;
71730391Skarels 	struct dga *dga;		/* gate array register map pointer */
71830391Skarels 	struct duart *duart;
71930391Skarels 	struct adder *adder;
720*34732Smarc 	int unit;
721*34732Smarc 	int minor_dev;
72230391Skarels 	u_int mapix;
72334642Smarc 	int i;				/* SIGNED index */
72430391Skarels 
72530391Skarels 	minor_dev = minor(dev); 	/* get minor device number */
72630391Skarels 	unit = minor_dev >> 2;		/* get QDSS number */
72730391Skarels 	qd = &qdmap[unit];
72830391Skarels 
72930391Skarels 	if ((minor_dev & 0x03) == 2) {
73034642Smarc 		/*
73134642Smarc 		* this is the graphic device...
73234642Smarc 		*/
73334642Smarc 		if (qdopened[unit] != 1)
734*34732Smarc 		    	return(EBUSY);
73534642Smarc 		else
73634642Smarc 			qdopened[unit] = 0;	/* allow it to be re-opened */
73734642Smarc 		/*
73834642Smarc 		* re-protect device memory
73934642Smarc 		*/
74034642Smarc 		if (qdflags[unit].mapped & MAPDEV) {
74134642Smarc 			/*
74234642Smarc 			* TEMPLATE RAM
74334642Smarc 			*/
74434642Smarc 			mapix = VTOP((int)qd->template) - VTOP(qvmem[0]);
74534642Smarc 			ptep = (int *)(QVmap[0] + mapix);
746*34732Smarc 			for (i = 0; i < btop(TMPSIZE); i++, ptep++)
747*34732Smarc 				*ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
74834642Smarc 			/*
74934642Smarc 			* ADDER
75034642Smarc 			*/
75134642Smarc 			mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]);
75234642Smarc 			ptep = (int *)(QVmap[0] + mapix);
753*34732Smarc 			for (i = 0; i < btop(REGSIZE); i++, ptep++)
754*34732Smarc 				*ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
75534642Smarc 			/*
75634642Smarc 			* COLOR MAPS
75734642Smarc 			*/
75834642Smarc 			mapix = VTOP((int)qd->red) - VTOP(qvmem[0]);
75934642Smarc 			ptep = (int *)(QVmap[0] + mapix);
760*34732Smarc 			for (i = 0; i < btop(CLRSIZE); i++, ptep++)
761*34732Smarc 				*ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
76234642Smarc 		}
76334615Smarc 
76434642Smarc 		/*
76534642Smarc 		* re-protect DMA buffer and free the map registers
76634642Smarc 		*/
76734642Smarc 		if (qdflags[unit].mapped & MAPDMA) {
76834642Smarc 			dga = (struct dga *) qdmap[unit].dga;
76934642Smarc 			adder = (struct adder *) qdmap[unit].adder;
77034642Smarc 			dga->csr &= ~DMA_IE;
77134642Smarc 			dga->csr &= ~0x0600;	     /* kill DMA */
77234642Smarc 			adder->command = CANCEL;
77334642Smarc 			/*
77434642Smarc 			 * if DMA was running, flush spurious intrpt
77534642Smarc 			 */
77634642Smarc 			if (dga->bytcnt_lo != 0) {
77734642Smarc 				dga->bytcnt_lo = 0;
77834642Smarc 				dga->bytcnt_hi = 0;
77934642Smarc 				DMA_SETIGNORE(DMAheader[unit]);
78034642Smarc 				dga->csr |= DMA_IE;
78134642Smarc 				dga->csr &= ~DMA_IE;
78234642Smarc 			}
78334642Smarc 			ptep = (int *)
78434642Smarc 			   ((VTOP(DMAheader[unit]*4)) + (mfpr(SBR)|0x80000000));
785*34732Smarc 			for (i = 0; i < btop(DMAbuf_size); i++, ptep++)
786*34732Smarc 				*ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
78734642Smarc 			ubarelse(0, &Qbus_unmap[unit]);
78834642Smarc 		}
78934615Smarc 
79034642Smarc 		/*
79134642Smarc 		* re-protect 1K (2 pages) event queue
79234642Smarc 		*/
79334642Smarc 		if (qdflags[unit].mapped & MAPEQ) {
79434642Smarc 			ptep = (int *)
79534642Smarc 			   ((VTOP(eq_header[unit])*4) + (mfpr(SBR)|0x80000000));
796*34732Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++;
79734642Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
79830391Skarels 		}
79934642Smarc 		/*
80034642Smarc 		* re-protect scroll param area and disable scroll intrpts
80134642Smarc 		*/
80234642Smarc 		if (qdflags[unit].mapped & MAPSCR) {
80334642Smarc 			ptep = (int *) ((VTOP(scroll[unit]) * 4)
80434642Smarc 				+ (mfpr(SBR) | 0x80000000));
80534642Smarc 			/*
80634642Smarc 			 * re-protect 512 scroll param area
80734642Smarc 			 */
80834642Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
80934642Smarc 			adder = (struct adder *) qdmap[unit].adder;
81034642Smarc 			qdflags[unit].adder_ie &= ~FRAME_SYNC;
81134642Smarc 			adder->interrupt_enable = qdflags[unit].adder_ie;
81234642Smarc 		}
81334642Smarc 		/*
81434642Smarc 		* re-protect color map write buffer area and kill intrpts
81534642Smarc 		*/
81634642Smarc 		if (qdflags[unit].mapped & MAPCOLOR) {
81734642Smarc 			ptep = (int *) ((VTOP(color_buf[unit]) * 4)
81834642Smarc 				+ (mfpr(SBR) | 0x80000000));
819*34732Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++;
82034642Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
82134642Smarc 			color_buf[unit]->status = 0;
82234642Smarc 			adder = (struct adder *) qdmap[unit].adder;
82334642Smarc 			qdflags[unit].adder_ie &= ~VSYNC;
82434642Smarc 			adder->interrupt_enable = qdflags[unit].adder_ie;
82534642Smarc 		}
82634642Smarc 		mtpr(TBIA, 0);
82734642Smarc 		/* flag everything now unmapped */
82834642Smarc 		qdflags[unit].mapped = 0;
82934642Smarc 		qdflags[unit].inuse &= ~GRAPHIC_DEV;
83034642Smarc 		qdflags[unit].curs_acc = ACC_OFF;
83134642Smarc 		qdflags[unit].curs_thr = 128;
83234642Smarc 		/*
83334642Smarc 		* restore the console
83434642Smarc 		*/
83530391Skarels 		dga = (struct dga *) qdmap[unit].dga;
83630391Skarels 		adder = (struct adder *) qdmap[unit].adder;
83730391Skarels 		dga->csr &= ~DMA_IE;
83830391Skarels 		dga->csr &= ~0x0600;	/* halt the DMA! (just in case...) */
83930391Skarels 		dga->csr |= DMA_ERR;	/* clear error condition */
84030391Skarels 		adder->command = CANCEL;
84134642Smarc 		/*
84234642Smarc 		 * if DMA was running, flush spurious intrpt
84334642Smarc 		 */
84430391Skarels 		if (dga->bytcnt_lo != 0) {
84534642Smarc 			dga->bytcnt_lo = 0;
84634642Smarc 			dga->bytcnt_hi = 0;
84734642Smarc 			DMA_SETIGNORE(DMAheader[unit]);
84834642Smarc 			dga->csr |= DMA_IE;
84934642Smarc 			dga->csr &= ~DMA_IE;
85030391Skarels 		}
85130391Skarels 		init_shared(unit);		/* init shared memory */
85230391Skarels 		setup_dragon(unit);		/* init ADDER/VIPER */
85330391Skarels 		ldcursor(unit, cons_cursor);	/* load default cursor map */
85430391Skarels 		setup_input(unit);		/* init the DUART */
85530391Skarels 		ldfont(unit);
85630391Skarels 		cursor[unit].x = 0;
85730391Skarels 		cursor[unit].y = 0;
85834642Smarc 		/*
85934642Smarc 		 * shut off the mouse rcv intrpt and turn on kbd intrpts
86034642Smarc 		 */
86134642Smarc 		duart = (struct duart *) qdmap[unit].duart;
86234642Smarc 		qdflags[unit].duart_imask &= ~(0x20);
86334642Smarc 		qdflags[unit].duart_imask |= 0x02;
86434642Smarc 		duart->imask = qdflags[unit].duart_imask;
86534642Smarc 		/*
86634642Smarc 		* shut off interrupts if all is closed
86734642Smarc 		*/
86834642Smarc 		if (!(qdflags[unit].inuse & CONS_DEV)) {
86934642Smarc 			dga = (struct dga *) qdmap[unit].dga;
87034642Smarc 			dga->csr &= ~(GLOBAL_IE | DMA_IE);
87134642Smarc 		}
87234642Smarc 	} else {
87334642Smarc 		/*
87434642Smarc 		* this is the console
87534642Smarc 		*/
87634642Smarc 		tp = &qd_tty[minor_dev];
87734642Smarc 		(*linesw[tp->t_line].l_close)(tp);
87834642Smarc 		ttyclose(tp);
87934642Smarc 		tp->t_state = 0;
88034642Smarc 		qdflags[unit].inuse &= ~CONS_DEV;
88134642Smarc 		/*
88234642Smarc 		* if graphics device is closed, kill interrupts
88334642Smarc 		*/
88434642Smarc 		if (!(qdflags[unit].inuse & GRAPHIC_DEV)) {
88534642Smarc 			dga = (struct dga *) qdmap[unit].dga;
88634642Smarc 			dga->csr &= ~(GLOBAL_IE | DMA_IE);
88734642Smarc 		}
88830391Skarels 	}
88934615Smarc 
89030391Skarels 	return(0);
89130391Skarels 
89230391Skarels } /* qdclose */
89330391Skarels 
89430391Skarels qdioctl(dev, cmd, datap, flags)
89534642Smarc 	dev_t dev;
89634642Smarc 	int cmd;
897*34732Smarc 	register caddr_t datap;
89834642Smarc 	int flags;
89930391Skarels {
90030391Skarels 	register int *ptep;		/* page table entry pointer */
90132012Smarc 	register int mapix;		/* QVmap[] page table index */
90230391Skarels 	register struct _vs_event *event;
90330391Skarels 	register struct tty *tp;
904*34732Smarc 	register i;
90530391Skarels 	struct qdmap *qd;		/* pointer to device map struct */
90630391Skarels 	struct dga *dga;		/* Gate Array reg structure pntr */
90730391Skarels 	struct duart *duart;		/* DUART reg structure pointer */
90830391Skarels 	struct adder *adder;		/* ADDER reg structure pointer */
90930391Skarels 	struct prgkbd *cmdbuf;
91030391Skarels 	struct prg_cursor *curs;
91130391Skarels 	struct _vs_cursor *pos;
912*34732Smarc 	int unit = minor(dev) >> 2;	/* number of caller's QDSS */
91330391Skarels 	u_int minor_dev = minor(dev);
91430391Skarels 	int error;
91530391Skarels 	int s;
91630391Skarels 	short *temp;			/* a pointer to template RAM */
91730391Skarels 
91834642Smarc 	/*
91934642Smarc 	* service graphic device ioctl commands
92034642Smarc 	*/
92130391Skarels 	switch (cmd) {
92234615Smarc 
92334642Smarc 	case QD_GETEVENT:
92434642Smarc 		/*
92534642Smarc 		* extract the oldest event from the event queue
92634642Smarc 		*/
92730391Skarels 		if (ISEMPTY(eq_header[unit])) {
92834642Smarc 			event = (struct _vs_event *) datap;
92934642Smarc 			event->vse_device = VSE_NULL;
93034642Smarc 			break;
93130391Skarels 		}
93230391Skarels 		event = (struct _vs_event *) GETBEGIN(eq_header[unit]);
93334615Smarc 		s = spl5();
93430391Skarels 		GETEND(eq_header[unit]);
93530391Skarels 		splx(s);
936*34732Smarc 		bcopy((caddr_t)event, datap, sizeof(struct _vs_event));
93730391Skarels 		break;
93830391Skarels 
93934642Smarc 	case QD_RESET:
94034642Smarc 		/*
94134642Smarc 		* init the dragon stuff, DUART, and driver variables
94234642Smarc 		*/
94330391Skarels 		init_shared(unit);		/* init shared memory */
94430391Skarels 		setup_dragon(unit);	      /* init the ADDER/VIPER stuff */
94530391Skarels 		clear_qd_screen(unit);
94630391Skarels 		ldcursor(unit, cons_cursor);	/* load default cursor map */
94730391Skarels 		ldfont(unit);			/* load the console font */
94830391Skarels 		setup_input(unit);		/* init the DUART */
94930391Skarels 		break;
95030391Skarels 
95134642Smarc 	case QD_SET:
95234642Smarc 		/*
95334642Smarc 		* init the DUART and driver variables
95434642Smarc 		*/
95530391Skarels 		init_shared(unit);
95630391Skarels 		setup_input(unit);
95730391Skarels 		break;
95830391Skarels 
95934642Smarc 	case QD_CLRSCRN:
96034642Smarc 		/*
96134642Smarc 		* clear the QDSS screen.  (NOTE that this reinits the dragon)
96234642Smarc 		*/
963*34732Smarc #ifdef notdef	/* has caused problems and isn't necessary */
96430391Skarels 		setup_dragon(unit);
96530391Skarels 		clear_qd_screen(unit);
96634615Smarc #endif
96730391Skarels 		break;
96830391Skarels 
96934642Smarc 	case QD_WTCURSOR:
97034642Smarc 		/*
97134642Smarc 		* load a cursor into template RAM
97234642Smarc 		*/
973*34732Smarc 		ldcursor(unit, (short *)datap);
97430391Skarels 		break;
97530391Skarels 
97634642Smarc 	case QD_RDCURSOR:
97730391Skarels 
97830391Skarels 		temp = (short *) qdmap[unit].template;
97934642Smarc 		/*
98034642Smarc 		 * cursor is 32 WORDS from the end of the 8k WORD...
98134642Smarc 		 *  ...template space
98234642Smarc 		 */
98330391Skarels 		temp += (8 * 1024) - 32;
98430391Skarels 		for (i = 0; i < 32; ++i, datap += sizeof(short))
98534642Smarc 			*(short *)datap = *temp++;
98630391Skarels 		break;
98730391Skarels 
98834642Smarc 	case QD_POSCURSOR:
98934642Smarc 		/*
99034642Smarc 		* position the mouse cursor
99134642Smarc 		*/
99230391Skarels 		dga = (struct dga *) qdmap[unit].dga;
99330391Skarels 		pos = (struct _vs_cursor *) datap;
99434615Smarc 		s = spl5();
99530391Skarels 		dga->x_cursor = TRANX(pos->x);
99630391Skarels 		dga->y_cursor = TRANY(pos->y);
99730391Skarels 		eq_header[unit]->curs_pos.x = pos->x;
99830391Skarels 		eq_header[unit]->curs_pos.y = pos->y;
99930391Skarels 		splx(s);
100030391Skarels 		break;
100130391Skarels 
100234642Smarc 	case QD_PRGCURSOR:
100334642Smarc 		/*
100434642Smarc 		* set the cursor acceleration factor
100534642Smarc 		*/
100630391Skarels 		curs = (struct prg_cursor *) datap;
100734615Smarc 		s = spl5();
100830391Skarels 		qdflags[unit].curs_acc = curs->acc_factor;
100930391Skarels 		qdflags[unit].curs_thr = curs->threshold;
101030391Skarels 		splx(s);
101130391Skarels 		break;
101230391Skarels 
101334642Smarc 	case QD_MAPDEVICE:
101434642Smarc 		/*
101534642Smarc 		* enable 'user write' to device pages
101634642Smarc 		*/
101730391Skarels 		qdflags[unit].mapped |= MAPDEV;
101830391Skarels 		qd = (struct qdmap *) &qdmap[unit];
101934642Smarc 		/*
102034642Smarc 		* enable user write to template RAM
102134642Smarc 		*/
102232012Smarc 		mapix = VTOP((int)qd->template) - VTOP(qvmem[0]);
102332012Smarc 		ptep = (int *)(QVmap[0] + mapix);
1024*34732Smarc 		for (i = 0; i < btop(TMPSIZE); i++, ptep++)
1025*34732Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
102634642Smarc 		/*
102734642Smarc 		* enable user write to registers
102834642Smarc 		*/
102932012Smarc 		mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]);
103032012Smarc 		ptep = (int *)(QVmap[0] + mapix);
1031*34732Smarc 		for (i = 0; i < btop(REGSIZE); i++, ptep++)
1032*34732Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
103334642Smarc 		/*
103434642Smarc 		* enable user write to color maps
103534642Smarc 		*/
103632012Smarc 		mapix = VTOP((int)qd->red) - VTOP(qvmem[0]);
103732012Smarc 		ptep = (int *)(QVmap[0] + mapix);
1038*34732Smarc 		for (i = 0; i < btop(CLRSIZE); i++, ptep++)
1039*34732Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
104034642Smarc 		/*
104134642Smarc 		* enable user write to DUART
104234642Smarc 		*/
104332012Smarc 		mapix = VTOP((int)qd->duart) - VTOP(qvmem[0]);
104432012Smarc 		ptep = (int *)(QVmap[0] + mapix);
104530391Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; /* duart page */
104630391Skarels 
1047*34732Smarc 		mtpr(TBIA, 0);		/* invalidate translation buffer */
104830391Skarels 
104934642Smarc 		/*
1050*34732Smarc 		 * stuff qdmap structure in return buffer
1051*34732Smarc 		 */
1052*34732Smarc 		bcopy((caddr_t)qd, datap, sizeof(struct qdmap));
105330391Skarels 		break;
105430391Skarels 
105534642Smarc 	case QD_MAPIOBUF:
105634642Smarc 		/*
105734642Smarc 		 * do setup for DMA by user process
105834642Smarc 		 *
105934642Smarc 		 * set 'user write enable' bits for DMA buffer
106034642Smarc 		 */
106130391Skarels 		qdflags[unit].mapped |= MAPDMA;
106230391Skarels 		ptep = (int *) ((VTOP(DMAheader[unit]) * 4)
106334642Smarc 			+ (mfpr(SBR) | 0x80000000));
1064*34732Smarc 		for (i = 0; i < btop(DMAbuf_size); i++, ptep++)
1065*34732Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
1066*34732Smarc 		mtpr(TBIA, 0);		/* invalidate translation buffer */
106734642Smarc 		/*
106834642Smarc 		* set up QBUS map registers for DMA
106934642Smarc 		*/
107030391Skarels 		DMAheader[unit]->QBAreg =
1071*34732Smarc 		    uballoc(0, (caddr_t)DMAheader[unit], DMAbuf_size, 0);
107230391Skarels 		if (DMAheader[unit]->QBAreg == 0)
1073*34732Smarc 		    printf("qd%d: qdioctl: QBA setup error\n", unit);
107430391Skarels 		Qbus_unmap[unit] = DMAheader[unit]->QBAreg;
107530391Skarels 		DMAheader[unit]->QBAreg &= 0x3FFFF;
107634642Smarc 		/*
107734642Smarc 		* return I/O buf adr
107834642Smarc 		*/
107930391Skarels 		*(int *)datap = (int) DMAheader[unit];
108030391Skarels 		break;
108130391Skarels 
108234642Smarc 	case QD_MAPSCROLL:
108334642Smarc 		/*
108434642Smarc 		* map the shared scroll param area and enable scroll interpts
108534642Smarc 		*/
108630391Skarels 		qdflags[unit].mapped |= MAPSCR;
108730391Skarels 		ptep = (int *) ((VTOP(scroll[unit]) * 4)
108834642Smarc 			+ (mfpr(SBR) | 0x80000000));
108934642Smarc 		/*
109034642Smarc 		 * allow user write to scroll area
109134642Smarc 		 */
109230391Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
1093*34732Smarc 		mtpr(TBIA, 0);			/* invalidate translation buf */
109430391Skarels 		scroll[unit]->status = 0;
109530391Skarels 		adder = (struct adder *) qdmap[unit].adder;
109630391Skarels 		qdflags[unit].adder_ie |= FRAME_SYNC;
109730391Skarels 		adder->interrupt_enable = qdflags[unit].adder_ie;
109834642Smarc 		*(int *)datap = (int) scroll[unit]; /* return scroll area */
109930391Skarels 		break;
110030391Skarels 
110134642Smarc 	case QD_UNMAPSCROLL:
110234642Smarc 		/*
110334642Smarc 		* unmap shared scroll param area and disable scroll intrpts
110434642Smarc 		*/
110530391Skarels 		if (qdflags[unit].mapped & MAPSCR) {
110634642Smarc 			qdflags[unit].mapped &= ~MAPSCR;
110734642Smarc 			ptep = (int *) ((VTOP(scroll[unit]) * 4)
110834642Smarc 				+ (mfpr(SBR) | 0x80000000));
110934642Smarc 			/*
111034642Smarc 			 * re-protect 512 scroll param area
111134642Smarc 			 */
111234642Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
111334642Smarc 			mtpr(TBIA, 0);	/* smash CPU's translation buf */
111434642Smarc 			adder = (struct adder *) qdmap[unit].adder;
111534642Smarc 			qdflags[unit].adder_ie &= ~FRAME_SYNC;
111634642Smarc 			adder->interrupt_enable = qdflags[unit].adder_ie;
111730391Skarels 		}
111830391Skarels 		break;
111930391Skarels 
112034642Smarc 	case QD_MAPCOLOR:
112134642Smarc 		/*
112234642Smarc 		* map shared color map write buf and turn on vsync intrpt
112334642Smarc 		*/
112430391Skarels 		qdflags[unit].mapped |= MAPCOLOR;
112530391Skarels 		ptep = (int *) ((VTOP(color_buf[unit]) * 4)
112634642Smarc 			+ (mfpr(SBR) | 0x80000000));
1127*34732Smarc 		/*
1128*34732Smarc 		 * allow user write to color map write buffer
1129*34732Smarc 		 */
1130*34732Smarc 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; ptep++;
113130391Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
113230391Skarels 		mtpr(TBIA, 0);			/* clr CPU translation buf */
113334642Smarc 		adder = (struct adder *) qdmap[unit].adder;
113430391Skarels 		qdflags[unit].adder_ie |= VSYNC;
113530391Skarels 		adder->interrupt_enable = qdflags[unit].adder_ie;
1136*34732Smarc 		/*
1137*34732Smarc 		 * return color area address
1138*34732Smarc 		 */
113930391Skarels 		*(int *)datap = (int) color_buf[unit];
114030391Skarels 		break;
114130391Skarels 
114234642Smarc 	case QD_UNMAPCOLOR:
114334642Smarc 		/*
1144*34732Smarc 		 * unmap shared color map write buffer and kill VSYNC intrpts
1145*34732Smarc 		 */
114630391Skarels 		if (qdflags[unit].mapped & MAPCOLOR) {
114734642Smarc 			qdflags[unit].mapped &= ~MAPCOLOR;
114834642Smarc 			ptep = (int *) ((VTOP(color_buf[unit]) * 4)
114934642Smarc 				+ (mfpr(SBR) | 0x80000000));
1150*34732Smarc 			/*
1151*34732Smarc 			 * re-protect color map write buffer
1152*34732Smarc 			 */
1153*34732Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++;
115434642Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
1155*34732Smarc 			mtpr(TBIA, 0);
115634642Smarc 			adder = (struct adder *) qdmap[unit].adder;
115734642Smarc 			qdflags[unit].adder_ie &= ~VSYNC;
115834642Smarc 			adder->interrupt_enable = qdflags[unit].adder_ie;
115930391Skarels 		}
116030391Skarels 		break;
116130391Skarels 
116234642Smarc 	case QD_MAPEVENT:
116334642Smarc 		/*
116434642Smarc 		* give user write access to the event queue
116534642Smarc 		*/
116630391Skarels 		qdflags[unit].mapped |= MAPEQ;
116730391Skarels 		ptep = (int *) ((VTOP(eq_header[unit]) * 4)
116834642Smarc 			+ (mfpr(SBR) | 0x80000000));
1169*34732Smarc 		/*
1170*34732Smarc 		 * allow user write to 1K event queue
1171*34732Smarc 		 */
1172*34732Smarc 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; ptep++;
117330391Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
117430391Skarels 		mtpr(TBIA, 0);			/* clr CPU translation buf */
1175*34732Smarc 		/*
1176*34732Smarc 		 * return event queue address
1177*34732Smarc 		 */
1178*34732Smarc 		*(int *)datap = (int)eq_header[unit];
117930391Skarels 		break;
118030391Skarels 
118134642Smarc 	case QD_PRGKBD:
118234642Smarc 		/*
118334642Smarc 		* pass caller's programming commands to LK201
118434642Smarc 		*/
1185*34732Smarc 		duart = (struct duart *)qdmap[unit].duart;
1186*34732Smarc 		cmdbuf = (struct prgkbd *)datap;    /* pnt to kbd cmd buf */
118734642Smarc 		/*
118834642Smarc 		* send command
118934642Smarc 		*/
119030391Skarels 		for (i = 1000; i > 0; --i) {
1191*34732Smarc 			if (duart->statusA&XMT_RDY) {
119234642Smarc 				duart->dataA = cmdbuf->cmd;
119334642Smarc 				break;
119434642Smarc 			}
119530391Skarels 		}
119630391Skarels 		if (i == 0) {
1197*34732Smarc 			printf("qd%d: qdioctl: timeout on XMT_RDY [1]\n", unit);
119834642Smarc 			break;
119930391Skarels 		}
120034642Smarc 		/*
120134642Smarc 		* send param1?
120234642Smarc 		*/
120330391Skarels 		if (cmdbuf->cmd & LAST_PARAM)
120434642Smarc 			break;
120530391Skarels 		for (i = 1000; i > 0; --i) {
1206*34732Smarc 			if (duart->statusA&XMT_RDY) {
120734642Smarc 				duart->dataA = cmdbuf->param1;
120834642Smarc 				break;
120934642Smarc 			}
121030391Skarels 		}
121130391Skarels 		if (i == 0) {
1212*34732Smarc 			printf("qd%d: qdioctl: timeout on XMT_RDY [2]\n", unit);
121334642Smarc 			break;
121430391Skarels 		}
121534642Smarc 		/*
121634642Smarc 		* send param2?
121734642Smarc 		*/
121830391Skarels 		if (cmdbuf->param1 & LAST_PARAM)
121930391Skarels 		    break;
122030391Skarels 		for (i = 1000; i > 0; --i) {
1221*34732Smarc 			if (duart->statusA&XMT_RDY) {
122234642Smarc 				duart->dataA = cmdbuf->param2;
122334642Smarc 				break;
122434642Smarc 			}
122530391Skarels 		}
122630391Skarels 		if (i == 0) {
1227*34732Smarc 			printf("qd%d: qdioctl: timeout on XMT_RDY [3]\n", unit);
122834642Smarc 			break;
122930391Skarels 		}
123030391Skarels 		break;
123130391Skarels 
123234642Smarc 	case QD_PRGMOUSE:
123334642Smarc 		/*
123434642Smarc 		* pass caller's programming commands to the mouse
123534642Smarc 		*/
123630391Skarels 		duart = (struct duart *) qdmap[unit].duart;
123730391Skarels 		for (i = 1000; i > 0; --i) {
1238*34732Smarc 			if (duart->statusB&XMT_RDY) {
123934642Smarc 				duart->dataB = *datap;
124034642Smarc 				break;
124134642Smarc 			}
124230391Skarels 		}
124330391Skarels 		if (i == 0) {
1244*34732Smarc 			printf("qd%d: qdioctl: timeout on XMT_RDY [4]\n", unit);
124530391Skarels 		}
124630391Skarels 		break;
124730391Skarels 
124834642Smarc 	case QD_RDCONFIG:
124934642Smarc 		/*
125034642Smarc 		* get QDSS configuration word and return it
125134642Smarc 		*/
125230391Skarels 		*(short *)datap = qdflags[unit].config;
125330391Skarels 		break;
125430391Skarels 
125534642Smarc 	case QD_KERN_LOOP:
125634642Smarc 	case QD_KERN_UNLOOP:
125734642Smarc 		/*
125834642Smarc 		 * vestige from ultrix.  BSD uses TIOCCONS to redirect
125934642Smarc 		 * kernel console output.
126034642Smarc 		 */
126134615Smarc 		break;
126234615Smarc 
126334642Smarc 	case QD_PRGTABLET:
126434642Smarc 		/*
126534642Smarc 		* program the tablet
126634642Smarc 		*/
126730391Skarels 		duart = (struct duart *) qdmap[unit].duart;
126830391Skarels 		for (i = 1000; i > 0; --i) {
1269*34732Smarc 			if (duart->statusB&XMT_RDY) {
127034642Smarc 				duart->dataB = *datap;
127134642Smarc 				break;
127234642Smarc 			}
127330391Skarels 		}
127430391Skarels 		if (i == 0) {
1275*34732Smarc 			printf("qd%d: qdioctl: timeout on XMT_RDY [5]\n", unit);
127630391Skarels 		}
127730391Skarels 		break;
127830391Skarels 
127934642Smarc 	case QD_PRGTABRES:
128034642Smarc 		/*
128134642Smarc 		* program the tablet report resolution factor
128234642Smarc 		*/
128330391Skarels 		qdflags[unit].tab_res = *(short *)datap;
128430391Skarels 		break;
128530391Skarels 
128634642Smarc 	default:
128734642Smarc 		/*
128834642Smarc 		* service tty ioctl's
128934642Smarc 		*/
129034642Smarc 		if (!(minor_dev & 0x02)) {
129130391Skarels 			tp = &qd_tty[minor_dev];
129234642Smarc 			error =
129334642Smarc 			   (*linesw[tp->t_line].l_ioctl)(tp, cmd, datap, flags);
129430391Skarels 			if (error >= 0) {
129534642Smarc 				return(error);
129630391Skarels 			}
129730391Skarels 			error = ttioctl(tp, cmd, datap, flags);
129830391Skarels 			if (error >= 0) {
129934642Smarc 				return(error);
130030391Skarels 			}
130134642Smarc 		}
130234642Smarc 		break;
130330391Skarels 	}
130430391Skarels 
130530391Skarels 	return(0);
130630391Skarels 
130730391Skarels } /* qdioctl */
130830391Skarels 
130930391Skarels qdselect(dev, rw)
131034642Smarc 	dev_t dev;
131134642Smarc 	int rw;
131230391Skarels {
1313*34732Smarc 	register s;
1314*34732Smarc 	register unit;
131534615Smarc 	register struct tty *tp;
131634615Smarc 	u_int minor_dev = minor(dev);
131730391Skarels 
131834615Smarc 	s = spl5();
131934615Smarc 	unit = minor_dev >> 2;
132030391Skarels 
132130391Skarels 	switch (rw) {
132234642Smarc 	case FREAD:
132334642Smarc 		if ((minor_dev & 0x03) == 2) {
132434642Smarc 			/*
132534642Smarc 			* this is a graphics device, so check for events
132634642Smarc 			*/
1327*34732Smarc 			if(!(ISEMPTY(eq_header[unit]))) {
132834642Smarc 				splx(s);
132934642Smarc 				return(1);
133034642Smarc 			}
1331*34732Smarc 			qdrsel[unit] = u.u_procp;
133234642Smarc 			qdflags[unit].selmask |= SEL_READ;
133334642Smarc 			splx(s);
133434642Smarc 			return(0);
133534642Smarc 		} else {
133634642Smarc 			/*
133734642Smarc 			* this is a tty device
133834642Smarc 			*/
133934642Smarc 			tp = &qd_tty[minor_dev];
134034642Smarc 			if (ttnread(tp))
134134642Smarc 			    return(1);
134234642Smarc 			tp->t_rsel = u.u_procp;
134334642Smarc 			splx(s);
134434642Smarc 			return(0);
134530391Skarels 		}
134630391Skarels 
134734642Smarc 	case FWRITE:
134834642Smarc 		if ((minor(dev) & 0x03) == 2) {
134934642Smarc 			/*
135034642Smarc 			* this is a graphics device, so check for dma buffers
135134642Smarc 			*/
135234642Smarc 			if (DMA_ISEMPTY(DMAheader[unit]))
135334642Smarc 			    {
135434642Smarc 				splx(s);
135534642Smarc 				return(1);
135634642Smarc 			}
1357*34732Smarc 			qdrsel[unit] = u.u_procp;
135834642Smarc 			qdflags[unit].selmask |= SEL_WRITE;
135934642Smarc 			splx(s);
136034642Smarc 			return(0);
136134642Smarc 		} else {
136234642Smarc 			/*
136334642Smarc 			* this is a tty device
136434642Smarc 			*/
136534642Smarc 			tp = &qd_tty[minor_dev];
136634642Smarc 			if (tp->t_outq.c_cc <= TTLOWAT(tp))
136734642Smarc 			    return(1);
136834642Smarc 			tp->t_wsel = u.u_procp;
136934642Smarc 			splx(s);
137034642Smarc 			return(0);
137130391Skarels 		}
137230391Skarels 	}
1373*34732Smarc 	splx(s);
1374*34732Smarc 	return(0);
137530391Skarels 
137630391Skarels } /* qdselect() */
137730391Skarels 
137830391Skarels extern qd_strategy();
137930391Skarels 
138030391Skarels qdwrite(dev, uio)
138134642Smarc 	dev_t dev;
138234642Smarc 	struct uio *uio;
138330391Skarels {
138430391Skarels 	register struct tty *tp;
1385*34732Smarc 	register minor_dev;
1386*34732Smarc 	register unit;
138730391Skarels 
138830391Skarels 	minor_dev = minor(dev);
138930391Skarels 	unit = (minor_dev >> 2) & 0x07;
139030391Skarels 
139134642Smarc 	if (((minor_dev&0x03) != 0x02) && (qdflags[unit].inuse&CONS_DEV)) {
139234642Smarc 		/*
139334642Smarc 		* this is the console...
139434642Smarc 		*/
139534642Smarc 		tp = &qd_tty[minor_dev];
139634642Smarc 		return ((*linesw[tp->t_line].l_write)(tp, uio));
139734642Smarc 	} else if (qdflags[unit].inuse & GRAPHIC_DEV) {
139834642Smarc 		/*
139934642Smarc 		* this is a DMA xfer from user space
140034642Smarc 		*/
140134642Smarc 		return (physio(qd_strategy, &qdbuf[unit],
140234642Smarc 		dev, B_WRITE, minphys, uio));
140330391Skarels 	}
1404*34732Smarc 	return (ENXIO);
140530391Skarels }
140630391Skarels 
140730391Skarels qdread(dev, uio)
140834642Smarc 	dev_t dev;
140934642Smarc 	struct uio *uio;
141030391Skarels {
141130391Skarels 	register struct tty *tp;
1412*34732Smarc 	register minor_dev;
1413*34732Smarc 	register unit;
141430391Skarels 
141530391Skarels 	minor_dev = minor(dev);
141630391Skarels 	unit = (minor_dev >> 2) & 0x07;
141730391Skarels 
141834642Smarc 	if ((minor_dev & 0x03) != 0x02 && qdflags[unit].inuse & CONS_DEV) {
141934642Smarc 		/*
142034642Smarc 		* this is the console
142134642Smarc 		*/
142234642Smarc 		tp = &qd_tty[minor_dev];
142334642Smarc 		return ((*linesw[tp->t_line].l_read)(tp, uio));
142434642Smarc 	} else if (qdflags[unit].inuse & GRAPHIC_DEV) {
142534642Smarc 		/*
142634642Smarc 		* this is a bitmap-to-processor xfer
142734642Smarc 		*/
142834642Smarc 		return (physio(qd_strategy, &qdbuf[unit],
142934642Smarc 		dev, B_READ, minphys, uio));
143030391Skarels 	}
1431*34732Smarc 	return (ENXIO);
143230391Skarels }
143330391Skarels 
143430391Skarels /***************************************************************
143530391Skarels *
143630391Skarels *	qd_strategy()... strategy routine to do DMA
143730391Skarels *
143830391Skarels ***************************************************************/
143930391Skarels 
144030391Skarels qd_strategy(bp)
144134642Smarc 	register struct buf *bp;
144230391Skarels {
144330391Skarels 	register struct dga *dga;
144430391Skarels 	register struct adder *adder;
1445*34732Smarc 	register unit;
144630391Skarels 	int QBAreg;
144730391Skarels 	int s;
144830391Skarels 	int cookie;
144930391Skarels 
145030391Skarels 	unit = (minor(bp->b_dev) >> 2) & 0x07;
145130391Skarels 
145234642Smarc 	/*
145334642Smarc 	* init pointers
145434642Smarc 	*/
145530391Skarels 	if ((QBAreg = ubasetup(0, bp, 0)) == 0) {
1456*34732Smarc 		printf("qd%d: qd_strategy: QBA setup error\n", unit);
145734642Smarc 		goto STRAT_ERR;
145830391Skarels 	}
145930391Skarels 	dga = (struct dga *) qdmap[unit].dga;
146034615Smarc 	s = spl5();
146130391Skarels 	qdflags[unit].user_dma = -1;
146230391Skarels 	dga->csr |= DMA_IE;
146330391Skarels 	cookie = QBAreg & 0x3FFFF;
146430391Skarels 	dga->adrs_lo = (short) cookie;
146530391Skarels 	dga->adrs_hi = (short) (cookie >> 16);
146630391Skarels 	dga->bytcnt_lo = (short) bp->b_bcount;
146730391Skarels 	dga->bytcnt_hi = (short) (bp->b_bcount >> 16);
146830391Skarels 
146930391Skarels 	while (qdflags[unit].user_dma) {
147034642Smarc 		sleep((caddr_t)&qdflags[unit].user_dma, QDPRIOR);
147130391Skarels 	}
147230391Skarels 	splx(s);
147330391Skarels 	ubarelse(0, &QBAreg);
147430391Skarels 	if (!(dga->csr & DMA_ERR)) {
147534642Smarc 		iodone(bp);
147634642Smarc 		return;
147730391Skarels 	}
147830391Skarels 
147930391Skarels STRAT_ERR:
148030391Skarels 	adder = (struct adder *) qdmap[unit].adder;
148134642Smarc 	adder->command = CANCEL;	/* cancel adder activity */
148230391Skarels 	dga->csr &= ~DMA_IE;
148330391Skarels 	dga->csr &= ~0x0600;		/* halt DMA (reset fifo) */
148430391Skarels 	dga->csr |= DMA_ERR;		/* clear error condition */
148530391Skarels 	bp->b_flags |= B_ERROR; 	/* flag an error to physio() */
148630391Skarels 
148734642Smarc 	/*
148834642Smarc 	 * if DMA was running, flush spurious intrpt
148934642Smarc 	 */
149030391Skarels 	if (dga->bytcnt_lo != 0) {
149134642Smarc 		dga->bytcnt_lo = 0;
149234642Smarc 		dga->bytcnt_hi = 0;
149334642Smarc 		DMA_SETIGNORE(DMAheader[unit]);
149434642Smarc 		dga->csr |= DMA_IE;
149530391Skarels 	}
149630391Skarels 	iodone(bp);
149730391Skarels 
149830391Skarels } /* qd_strategy */
149930391Skarels 
1500*34732Smarc /*
1501*34732Smarc  *  Start output to the console screen
1502*34732Smarc  */
150330391Skarels qdstart(tp)
150434642Smarc 	register struct tty *tp;
150530391Skarels {
1506*34732Smarc 	register which_unit, unit, c;
150730391Skarels 	int s;
150834615Smarc 
150930391Skarels 	unit = minor(tp->t_dev);
151030391Skarels 	which_unit = (unit >> 2) & 0x3;
151134615Smarc 	unit &= 0x03;
151230391Skarels 
151334615Smarc 	s = spl5();
151434615Smarc 
151534642Smarc 	/*
151634642Smarc 	* If it's currently active, or delaying, no need to do anything.
151734642Smarc 	*/
151830391Skarels 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
151930391Skarels 		goto out;
152030391Skarels 
152134642Smarc 	/*
152234642Smarc 	* Display chars until the queue is empty.
152334642Smarc 	* Drop input from anything but the console
152434642Smarc 	* device on the floor.
152534642Smarc 	*
152634642Smarc 	* XXX - this loop is done at spltty.
152734642Smarc 	*
152834642Smarc 	*/
152934642Smarc 	while (tp->t_outq.c_cc) {
153034511Smarc 		c = getc(&tp->t_outq);
153134615Smarc 		if (unit == 0)
1532*34732Smarc 			blitc(which_unit, (u_char)c);
153330391Skarels 	}
153434642Smarc 	/*
153534642Smarc 	* If there are sleepers, and output has drained below low
153634642Smarc 	* water mark, wake up the sleepers.
153734642Smarc 	*/
153834642Smarc 	if (tp->t_outq.c_cc <= TTLOWAT(tp)) {
153934615Smarc 		if (tp->t_state & TS_ASLEEP){
154034615Smarc 			tp->t_state &= ~TS_ASLEEP;
154134615Smarc 			wakeup((caddr_t) &tp->t_outq);
154234615Smarc 		}
154330391Skarels 	}
154430391Skarels 
154534615Smarc 	tp->t_state &= ~TS_BUSY;
154634615Smarc 
154730391Skarels out:
154830391Skarels 	splx(s);
154930391Skarels 
155030391Skarels } /* qdstart */
155130391Skarels 
1552*34732Smarc /*ARGSUSED*/
155330391Skarels qdstop(tp, flag)
155434642Smarc 	register struct tty *tp;
155534642Smarc 	int flag;
155630391Skarels {
155730391Skarels 	register int s;
155830391Skarels 
155934615Smarc 	s = spl5();	/* block intrpts during state modification */
1560*34732Smarc 	if (tp->t_state & TS_BUSY)
1561*34732Smarc 		if ((tp->t_state & TS_TTSTOP) == 0)
156234642Smarc 			tp->t_state |= TS_FLUSH;
156334642Smarc 		else
156434642Smarc 			tp->t_state &= ~TS_BUSY;
156530391Skarels 	splx(s);
156630391Skarels }
156730391Skarels 
1568*34732Smarc /*
1569*34732Smarc  *  Output a character to the QDSS screen
1570*34732Smarc  */
157130391Skarels 
157230391Skarels blitc(unit, chr)
1573*34732Smarc 	register unit;
1574*34732Smarc 	register u_char chr;
157530391Skarels {
157630391Skarels 	register struct adder *adder;
157730391Skarels 	register struct dga *dga;
157830391Skarels 	register int i;
157934642Smarc 	int nograph = !(qdflags[unit].inuse&GRAPHIC_DEV);
158034642Smarc 	static short inescape[NQD];
158130391Skarels 
1582*34732Smarc 	adder = (struct adder *)qdmap[unit].adder;
158330391Skarels 	dga = (struct dga *) qdmap[unit].dga;
158434642Smarc 	/*
158534642Smarc 	 * BSD comment: this (&=0177) defeats the extended character
158634642Smarc 	 * set code for the glass tty, but if i had the time i would
158734642Smarc 	 * spend it ripping out the code completely.  This driver
158834642Smarc 	 * is too big for its own good.
158934642Smarc 	 */
159034642Smarc 	chr &= 0177;
159134642Smarc 	/*
1592*34732Smarc 	 * Cursor addressing (so vi will work).
159334642Smarc 	 * Decode for "\E=%.%." cursor motion description.
1594*34732Smarc 	 * Corresponds to type "qdcons" in /etc/termcap:
159534642Smarc 	 *
159634642Smarc 	 *    qd|qdss|qdcons|qdss glass tty (4.4 BSD):\
159734642Smarc 	 *      :am:do=^J:le=^H:bs:cm=\E=%.%.:cl=1^Z:co#128:li#57::nd=^L:up=^K:
159834642Smarc 	 *
159934642Smarc 	 */
160034642Smarc 	if (inescape[unit] && nograph) {
160134642Smarc 		switch (inescape[unit]++) {
160234642Smarc 		case 1:
160334642Smarc 			if (chr != '=') {
160434642Smarc 				/* abort escape sequence */
160534642Smarc 				inescape[unit] = 0;
160634642Smarc 				blitc(unit, chr);
160734642Smarc 			}
1608*34732Smarc 			return;
160934642Smarc 		case 2:
161034642Smarc 			/* position row */
161134642Smarc 			cursor[unit].y = CHAR_HEIGHT * chr;
161234642Smarc 			if (cursor[unit].y > 863 - CHAR_HEIGHT)
161334642Smarc 				cursor[unit].y = 863 - CHAR_HEIGHT;
161434642Smarc 			dga->y_cursor = TRANY(cursor[unit].y);
1615*34732Smarc 			return;
161634642Smarc 		case 3:
161734642Smarc 			/* position column */
161834642Smarc 			cursor[unit].x = CHAR_WIDTH * chr;
161934642Smarc 			if (cursor[unit].x > 1024 - CHAR_WIDTH)
162034642Smarc 				cursor[unit].x = 1023 - CHAR_WIDTH;
162134642Smarc 			dga->x_cursor = TRANX(cursor[unit].x);
162234642Smarc 			inescape[unit] = 0;
1623*34732Smarc 			return;
162434642Smarc 		default:
162534642Smarc 			inescape[unit] = 0;
162634642Smarc 			blitc(unit, chr);
162734642Smarc 		}
162834642Smarc 	}
162930391Skarels 
163030391Skarels 	switch (chr) {
163134642Smarc 	case '\r':			/* return char */
163230391Skarels 		cursor[unit].x = 0;
163334642Smarc 		if (nograph)
163434642Smarc 			dga->x_cursor = TRANX(cursor[unit].x);
1635*34732Smarc 		return;
163630391Skarels 
163734642Smarc 	case '\t':			/* tab char */
163830391Skarels 		for (i = 8 - ((cursor[unit].x >> 3) & 0x07); i > 0; --i) {
163934642Smarc 			blitc(unit, ' ');
164030391Skarels 		}
1641*34732Smarc 		return;
164230391Skarels 
164334642Smarc 	case '\n':			/* line feed char */
164430391Skarels 		if ((cursor[unit].y += CHAR_HEIGHT) > (863 - CHAR_HEIGHT)) {
164534642Smarc 			if (nograph) {
164634642Smarc 				cursor[unit].y -= CHAR_HEIGHT;
164734642Smarc 				scroll_up(adder);
164834642Smarc 			} else
164934642Smarc 				cursor[unit].y = 0;
165030391Skarels 		}
165134642Smarc 		if (nograph)
165234642Smarc 			dga->y_cursor = TRANY(cursor[unit].y);
1653*34732Smarc 		return;
165430391Skarels 
165534642Smarc 	case '\b':			/* backspace char */
165630391Skarels 		if (cursor[unit].x > 0) {
165734642Smarc 			cursor[unit].x -= CHAR_WIDTH;
165834642Smarc 			if (nograph)
165934642Smarc 				dga->x_cursor = TRANX(cursor[unit].x);
166030391Skarels 		}
1661*34732Smarc 		return;
166234642Smarc 	case CTRL('k'):		/* cursor up */
166334642Smarc 		if (nograph && cursor[unit].y > 0) {
166434642Smarc 			cursor[unit].y -= CHAR_HEIGHT;
166534642Smarc 			dga->y_cursor = TRANY(cursor[unit].y);
166634642Smarc 		}
1667*34732Smarc 		return;
166830391Skarels 
166934642Smarc 	case CTRL('^'):		/* home cursor */
167034642Smarc 		if (nograph) {
167134642Smarc 			cursor[unit].x = 0;
167234642Smarc 			dga->x_cursor = TRANX(cursor[unit].x);
167334642Smarc 			cursor[unit].y = 0;
167434642Smarc 			dga->y_cursor = TRANY(cursor[unit].y);
167534642Smarc 		}
1676*34732Smarc 		return;
167732012Smarc 
167834642Smarc 	case CTRL('l'):		/* cursor right */
167934642Smarc 		if (nograph && cursor[unit].x < 1023 - CHAR_WIDTH) {
168034642Smarc 			cursor[unit].x += CHAR_WIDTH;
168134642Smarc 			dga->x_cursor = TRANX(cursor[unit].x);
168234642Smarc 		}
1683*34732Smarc 		return;
168430391Skarels 
168534642Smarc 	case CTRL('z'):		/* clear screen */
168634642Smarc 		if (nograph) {
168734642Smarc 			setup_dragon(unit);
168834642Smarc 			clear_qd_screen(unit);
168934642Smarc 			/* home cursor - termcap seems to assume this */
169034642Smarc 			cursor[unit].x = 0;
169134642Smarc 			dga->x_cursor = TRANX(cursor[unit].x);
169234642Smarc 			cursor[unit].y = 0;
169334642Smarc 			dga->y_cursor = TRANY(cursor[unit].y);
169434642Smarc 		}
1695*34732Smarc 		return;
169630391Skarels 
169734642Smarc 	case '\033':		/* start escape sequence */
169834642Smarc 		if (nograph)
169934642Smarc 			inescape[unit] = 1;
1700*34732Smarc 		return;
170134642Smarc 
170234642Smarc 	default:
170334642Smarc 		if ((chr < ' ') || (chr > '~'))
1704*34732Smarc 			return;
170534642Smarc 	}
170634642Smarc 	/*
170734642Smarc 	 * setup VIPER operand control registers
170834642Smarc 	 */
170930391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0001);  /* select plane #0 */
171030391Skarels 	write_ID(adder, SRC1_OCR_B,
171134642Smarc 	EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY);
171230391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x00FE);  /* select other planes */
171330391Skarels 	write_ID(adder, SRC1_OCR_B,
171434642Smarc 	EXT_SOURCE | INT_NONE | NO_ID | BAR_SHIFT_DELAY);
171530391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x00FF);  /* select all planes */
171630391Skarels 	write_ID(adder, DST_OCR_B,
171734642Smarc 	EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
171830391Skarels 	write_ID(adder, MASK_1, 0xFFFF);
171930391Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 1);
172030391Skarels 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
172134642Smarc 	adder->x_clip_min = 0;
172234642Smarc 	adder->x_clip_max = 1024;
172334642Smarc 	adder->y_clip_min = 0;
172434642Smarc 	adder->y_clip_max = 864;
172534642Smarc 	/*
172634642Smarc 	 * load DESTINATION origin and vectors
172734642Smarc 	 */
172830391Skarels 	adder->fast_dest_dy = 0;
172930391Skarels 	adder->slow_dest_dx = 0;
173030391Skarels 	adder->error_1 = 0;
173130391Skarels 	adder->error_2 = 0;
173230391Skarels 	adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL;
1733*34732Smarc 	(void)wait_status(adder, RASTEROP_COMPLETE);
173430391Skarels 	adder->destination_x = cursor[unit].x;
173530391Skarels 	adder->fast_dest_dx = CHAR_WIDTH;
173630391Skarels 	adder->destination_y = cursor[unit].y;
173730391Skarels 	adder->slow_dest_dy = CHAR_HEIGHT;
173834642Smarc 	/*
173934642Smarc 	 * load SOURCE origin and vectors
174034642Smarc 	 */
174134615Smarc 	if ((chr - ' ') > (CHARS - 1))  {
174234615Smarc 		printf("Invalid character (x)%x in blitc\n",chr);
174334615Smarc 		chr = ' ';
174434615Smarc 	}
174534642Smarc 	/*
174634642Smarc 	 * X position is modulo the number of characters per line
174734642Smarc 	 */
174834615Smarc 	adder->source_1_x = FONT_X +
174934642Smarc 	    (((chr - ' ') % (MAX_SCREEN_X/CHAR_WIDTH)) * CHAR_WIDTH);
175034642Smarc 	/*
175134642Smarc 	 * Point to either first or second row
175234642Smarc 	 */
175334615Smarc 	adder->source_1_y = 2048 - 15 *
175434642Smarc 	    (((chr - ' ')/(MAX_SCREEN_X/CHAR_WIDTH)) + 1);
175530391Skarels 	adder->source_1_dx = CHAR_WIDTH;
175630391Skarels 	adder->source_1_dy = CHAR_HEIGHT;
175730391Skarels 	write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
175830391Skarels 	adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE;
175934642Smarc 	/*
176034642Smarc 	 * update console cursor coordinates
176134642Smarc 	 */
176230391Skarels 	cursor[unit].x += CHAR_WIDTH;
176334642Smarc 	if (nograph)
176434642Smarc 		dga->x_cursor = TRANX(cursor[unit].x);
176530391Skarels 	if (cursor[unit].x > (1024 - CHAR_WIDTH)) {
176634642Smarc 		blitc(unit, '\r');
176734642Smarc 		blitc(unit, '\n');
176830391Skarels 	}
176930391Skarels 
177030391Skarels } /* blitc */
177130391Skarels 
1772*34732Smarc qdreset() { }
177330391Skarels 
1774*34732Smarc /*
1775*34732Smarc  *  INTERRUPT SERVICE ROUTINES
1776*34732Smarc  */
177730391Skarels 
1778*34732Smarc /*
1779*34732Smarc  *  Service "DMA DONE" interrupt condition
1780*34732Smarc  */
178130391Skarels qddint(qd)
1782*34732Smarc 	register qd;
178330391Skarels {
178430391Skarels 	register struct DMAreq_header *header;
178530391Skarels 	register struct DMAreq *request;
178630391Skarels 	register struct dga *dga;
178730391Skarels 	struct adder *adder;
178830391Skarels 	int cookie;			/* DMA adrs for QDSS */
178930391Skarels 
1790*34732Smarc 	(void)spl4(); 			/* allow interval timer in */
179130391Skarels 
179234642Smarc 	/*
179334642Smarc 	* init pointers
179434642Smarc 	*/
179530391Skarels 	header = DMAheader[qd]; 	    /* register for optimization */
179630391Skarels 	dga = (struct dga *) qdmap[qd].dga;
179730391Skarels 	adder = (struct adder *) qdmap[qd].adder;
179830391Skarels 
179934642Smarc 	/*
180034642Smarc 	* if this interrupt flagged as bogus for interrupt flushing purposes..
180134642Smarc 	*/
180230391Skarels 	if (DMA_ISIGNORE(header)) {
180334642Smarc 		DMA_CLRIGNORE(header);
180434642Smarc 		return;
180530391Skarels 	}
180630391Skarels 
180734642Smarc 	/*
180834642Smarc 	* dump a DMA hardware error message if appropriate
180934642Smarc 	*/
181030391Skarels 	if (dga->csr & DMA_ERR) {
181130391Skarels 
181234642Smarc 		if (dga->csr & PARITY_ERR)
1813*34732Smarc 		    printf("qd%d: qddint: DMA hardware parity fault.\n", qd);
181430391Skarels 
181534642Smarc 		if (dga->csr & BUS_ERR)
1816*34732Smarc 		    printf("qd%d: qddint: DMA hardware bus error.\n", qd);
181730391Skarels 	}
181830391Skarels 
181934642Smarc 	/*
182034642Smarc 	* if this was a DMA from user space...
182134642Smarc 	*/
182230391Skarels 	if (qdflags[qd].user_dma) {
182334642Smarc 		qdflags[qd].user_dma = 0;
182434642Smarc 		wakeup((caddr_t)&qdflags[qd].user_dma);
182534642Smarc 		return;
182630391Skarels 	}
182730391Skarels 
182834642Smarc 	/*
182934642Smarc 	* if we're doing DMA request queue services, field the error condition
183034642Smarc 	*/
183130391Skarels 	if (dga->csr & DMA_ERR) {
183230391Skarels 
183334642Smarc 		dga->csr &= ~0x0600;		/* halt DMA (reset fifo) */
183434642Smarc 		dga->csr |= DMA_ERR;		/* clear error condition */
183534642Smarc 		adder->command = CANCEL;	/* cancel adder activity */
183630391Skarels 
183734642Smarc 		DMA_SETERROR(header);	/* flag error in header status word */
183834642Smarc 		DMA_CLRACTIVE(header);
183934642Smarc 		header->DMAreq[header->oldest].DMAdone |= HARD_ERROR;
184034642Smarc 		header->newest = header->oldest;
184134642Smarc 		header->used = 0;
184230391Skarels 
1843*34732Smarc 		if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
1844*34732Smarc 			selwakeup(qdrsel[qd], 0);
1845*34732Smarc 			qdrsel[qd] = 0;
184634642Smarc 			qdflags[qd].selmask &= ~SEL_WRITE;
184734642Smarc 		}
184830391Skarels 
184934642Smarc 		if (dga->bytcnt_lo != 0) {
185034642Smarc 			dga->bytcnt_lo = 0;
185134642Smarc 			dga->bytcnt_hi = 0;
185234642Smarc 			DMA_SETIGNORE(header);
185334642Smarc 		}
185434642Smarc 		return;
185530391Skarels 	}
185630391Skarels 
185734642Smarc 	/*
185834642Smarc 	* if the DMA request queue is now becoming non-full,
185934642Smarc 	* wakeup "select" client.
186034642Smarc 	*/
186130391Skarels 	if (DMA_ISFULL(header)) {
1862*34732Smarc 		if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
1863*34732Smarc 			selwakeup(qdrsel[qd], 0);
1864*34732Smarc 			qdrsel[qd] = 0;
186534642Smarc 			qdflags[qd].selmask &= ~SEL_WRITE;
186634642Smarc 		}
186730391Skarels 	}
186830391Skarels 
186930391Skarels 	header->DMAreq[header->oldest].DMAdone |= REQUEST_DONE;
187034642Smarc 	QDlast_DMAtype = header->DMAreq[header->oldest].DMAtype;
187130391Skarels 
187234615Smarc 	/* check for unexpected interrupt */
187334615Smarc 	if (DMA_ISEMPTY(header))
187430391Skarels 	    return;
187530391Skarels 
187630391Skarels 	DMA_GETEND(header);	/* update request queue indices */
187730391Skarels 
187834642Smarc 	/*
1879*34732Smarc 	* if no more DMA pending, wake up "select" client and exit
1880*34732Smarc 	*/
188130391Skarels 	if (DMA_ISEMPTY(header)) {
188230391Skarels 
1883*34732Smarc 		if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
1884*34732Smarc 			selwakeup(qdrsel[qd], 0);
1885*34732Smarc 			qdrsel[qd] = 0;
188634642Smarc 			qdflags[qd].selmask &= ~SEL_WRITE;
188734642Smarc 		}
188830391Skarels 
188934642Smarc 		DMA_CLRACTIVE(header);  /* flag DMA done */
189034642Smarc 		return;
189130391Skarels 	}
189230391Skarels 
189334642Smarc 	/*
1894*34732Smarc 	* initiate next DMA xfer
1895*34732Smarc 	*/
189630391Skarels 	request = DMA_GETBEGIN(header);
189734615Smarc 	if (request->DMAtype != QDlast_DMAtype) {
189834642Smarc 		dga->csr &= ~0x0600;	  /* halt DMA (reset fifo) */
189934642Smarc 		adder->command = CANCEL;  /* cancel adder activity */
190034615Smarc 	}
190130391Skarels 
190234615Smarc 
190330391Skarels 	switch (request->DMAtype) {
190430391Skarels 
190534642Smarc 	case DISPLIST:
190634615Smarc 		if (request->DMAtype != QDlast_DMAtype) {
190734615Smarc 			dga->csr |= DL_ENB;
190834615Smarc 			dga->csr &= ~(BTOP_ENB | BYTE_DMA);
190934615Smarc 		}
191030391Skarels 		break;
191130391Skarels 
191234642Smarc 	case PTOB:
191334615Smarc 		if (request->DMAtype != QDlast_DMAtype) {
191434615Smarc 			if (request->DMAdone & BYTE_PACK)
191534642Smarc 			    dga->csr |= (PTOB_ENB | BYTE_DMA);
191634615Smarc 			else {
191734615Smarc 				dga->csr |= PTOB_ENB;
191834615Smarc 				dga->csr &= ~BYTE_DMA;
191934615Smarc 			}
192034615Smarc 		}
192130391Skarels 		break;
192230391Skarels 
192334642Smarc 	case BTOP:
192434615Smarc 		if (request->DMAtype != QDlast_DMAtype) {
192534615Smarc 			if (request->DMAdone & BYTE_PACK) {
192634615Smarc 				dga->csr &= ~DL_ENB;
192734615Smarc 				dga->csr |= (BTOP_ENB | BYTE_DMA);
192834615Smarc 			}
192934615Smarc 			else {
193034615Smarc 				dga->csr |= BTOP_ENB;
193134615Smarc 				dga->csr &= ~(BYTE_DMA | DL_ENB);
193234615Smarc 			}
193334615Smarc 		}
193430391Skarels 		break;
193534642Smarc 	default:
1936*34732Smarc 		printf("qd%d: qddint: illegal DMAtype parameter.\n", qd);
193730391Skarels 		DMA_CLRACTIVE(header);	/* flag DMA done */
193830391Skarels 		return;
193930391Skarels 	}
194030391Skarels 
194130391Skarels 	if (request->DMAdone & COUNT_ZERO) {
194234642Smarc 		dga->csr &= ~SET_DONE_FIFO;
194334642Smarc 	}
194434642Smarc 	else if (request->DMAdone & FIFO_EMPTY) {
194534642Smarc 		dga->csr |= SET_DONE_FIFO;
194630391Skarels 	}
194730391Skarels 
194830391Skarels 	if (request->DMAdone & WORD_PACK)
194930391Skarels 	    dga->csr &= ~BYTE_DMA;
195030391Skarels 	else if (request->DMAdone & BYTE_PACK)
195130391Skarels 	    dga->csr |= BYTE_DMA;
195230391Skarels 
195330391Skarels 	dga->csr |= DMA_IE;
195434642Smarc 	QDlast_DMAtype = request->DMAtype;
195530391Skarels 
195630391Skarels 	cookie = ((int)request->bufp - (int)header) + (int)header->QBAreg;
195730391Skarels 
195830391Skarels 	dga->adrs_lo = (short) cookie;
195930391Skarels 	dga->adrs_hi = (short) (cookie >> 16);
196030391Skarels 
196130391Skarels 	dga->bytcnt_lo = (short) request->length;
196230391Skarels 	dga->bytcnt_hi = (short) (request->length >> 16);
196330391Skarels 
196430391Skarels 	return;
196530391Skarels }
196630391Skarels 
1967*34732Smarc /*
1968*34732Smarc  * ADDER interrupt service routine
1969*34732Smarc  */
197030391Skarels qdaint(qd)
1971*34732Smarc 	register qd;
197230391Skarels {
197330391Skarels 	register struct adder *adder;
197430391Skarels 	struct color_buf *cbuf;
197530391Skarels 	int i;
197630391Skarels 	register struct rgb *rgbp;
197730391Skarels 	register short *red;
197830391Skarels 	register short *green;
197930391Skarels 	register short *blue;
198030391Skarels 
1981*34732Smarc 	(void)spl4(); 			/* allow interval timer in */
198230391Skarels 
198330391Skarels 	adder = (struct adder *) qdmap[qd].adder;
198430391Skarels 
198534642Smarc 	/*
198634642Smarc 	* service the vertical blank interrupt (VSYNC bit) by loading
198734642Smarc 	* any pending color map load request
198834642Smarc 	*/
198930391Skarels 	if (adder->status & VSYNC) {
199034642Smarc 		adder->status &= ~VSYNC;	/* clear the interrupt */
199134642Smarc 		cbuf = color_buf[qd];
199234642Smarc 		if (cbuf->status & LOAD_COLOR_MAP) {
199330391Skarels 
199434642Smarc 			red = (short *) qdmap[qd].red;
199534642Smarc 			green = (short *) qdmap[qd].green;
199634642Smarc 			blue = (short *) qdmap[qd].blue;
199730391Skarels 
199834642Smarc 			for (i = cbuf->count, rgbp = cbuf->rgb;
199934642Smarc 			     --i >= 0; rgbp++) {
200034642Smarc 				red[rgbp->offset] = (short) rgbp->red;
200134642Smarc 				green[rgbp->offset] = (short) rgbp->green;
200234642Smarc 				blue[rgbp->offset] = (short) rgbp->blue;
200334642Smarc 			}
200430391Skarels 
200534642Smarc 			cbuf->status &= ~LOAD_COLOR_MAP;
200630391Skarels 		}
200730391Skarels 	}
200830391Skarels 
200934642Smarc 	/*
201034642Smarc 	* service the scroll interrupt (FRAME_SYNC bit)
201134642Smarc 	*/
201230391Skarels 	if (adder->status & FRAME_SYNC) {
201334642Smarc 		adder->status &= ~FRAME_SYNC;	/* clear the interrupt */
201430391Skarels 
201534642Smarc 		if (scroll[qd]->status & LOAD_REGS) {
201630391Skarels 
2017*34732Smarc 			for (i = 1000, adder->status = 0; i > 0 &&
2018*34732Smarc 			     !(adder->status&ID_SCROLL_READY); --i)
201934642Smarc 			      ;
202030391Skarels 
202134642Smarc 			if (i == 0) {
2022*34732Smarc 			    printf("qd%d: qdaint: timeout on ID_SCROLL_READY\n",
202334642Smarc 				qd);
202434642Smarc 				return;
202534642Smarc 			}
202630391Skarels 
202734642Smarc 			adder->ID_scroll_data = scroll[qd]->viper_constant;
202834642Smarc 			adder->ID_scroll_command = ID_LOAD | SCROLL_CONSTANT;
202930391Skarels 
203034642Smarc 			adder->y_scroll_constant =
203134642Smarc 				scroll[qd]->y_scroll_constant;
203234642Smarc 			adder->y_offset_pending = scroll[qd]->y_offset;
203330391Skarels 
203434642Smarc 			if (scroll[qd]->status & LOAD_INDEX) {
203530391Skarels 
203634642Smarc 				adder->x_index_pending =
203734642Smarc 					scroll[qd]->x_index_pending;
203834642Smarc 				adder->y_index_pending =
203934642Smarc 					scroll[qd]->y_index_pending;
204034642Smarc 			}
204134642Smarc 
204234642Smarc 			scroll[qd]->status = 0x00;
204330391Skarels 		}
204430391Skarels 	}
204530391Skarels }
204630391Skarels 
2047*34732Smarc /*
2048*34732Smarc  *  DUART input interrupt service routine
2049*34732Smarc  *
2050*34732Smarc  *  XXX - this routine should be broken out - it is essentially
2051*34732Smarc  *	      straight line code.
2052*34732Smarc  */
205330391Skarels 
205430391Skarels qdiint(qd)
2055*34732Smarc 	register qd;
205630391Skarels {
205730391Skarels 	register struct _vs_event *event;
205830391Skarels 	register struct qdinput *eqh;
205930391Skarels 	struct dga *dga;
206030391Skarels 	struct duart *duart;
206130391Skarels 	struct mouse_report *new_rep;
206230391Skarels 	struct uba_device *ui;
206330391Skarels 	struct tty *tp;
206434615Smarc 	u_short chr;
206530391Skarels 	u_short status;
206630391Skarels 	u_short data;
206730391Skarels 	u_short key;
206830391Skarels 	char do_wakeup = 0;		/* flag to do a select wakeup call */
206930391Skarels 	char a, b, c;			/* mouse button test variables */
207030391Skarels 
2071*34732Smarc 	(void)spl4(); 			/* allow interval timer in */
207230391Skarels 
207330391Skarels 	eqh = eq_header[qd];		/* optimized as a register */
207430391Skarels 	new_rep = &current_rep[qd];
207530391Skarels 	duart = (struct duart *) qdmap[qd].duart;
207630391Skarels 
207734642Smarc 	/*
2078*34732Smarc 	* if the graphic device is turned on..
2079*34732Smarc 	*/
208030391Skarels 	if (qdflags[qd].inuse & GRAPHIC_DEV) {
208134642Smarc 		/*
208234642Smarc 		* empty DUART
208334642Smarc 		*/
2084*34732Smarc 		while (duart->statusA&RCV_RDY || duart->statusB&RCV_RDY) {
208534642Smarc 			/*
2086*34732Smarc 			 * pick up LK-201 input (if any)
2087*34732Smarc 			 */
2088*34732Smarc 			if (duart->statusA&RCV_RDY) {
208930391Skarels 
209034642Smarc 				/* if error condition, then reset it */
209130391Skarels 
2092*34732Smarc 				if (duart->statusA&0x70) {
209334642Smarc 					duart->cmdA = 0x40;
209434642Smarc 					continue;
209534642Smarc 				}
209630391Skarels 
209734642Smarc 				/* event queue full now? (overflow condition) */
209830391Skarels 
209934642Smarc 				if (ISFULL(eqh) == TRUE) {
210034642Smarc 					printf(
2101*34732Smarc 					 "qd%d: qdiint: event queue overflow\n",
210234642Smarc 					   qd);
210334642Smarc 					break;
210434642Smarc 				}
210530391Skarels 
210634642Smarc 				/*
210734642Smarc 				* Check for various keyboard errors  */
210830391Skarels 
210934642Smarc 				key = duart->dataA & 0xFF;
211030391Skarels 
211134642Smarc 				if (key==LK_POWER_ERROR ||
211234642Smarc 				    key==LK_KDOWN_ERROR ||
211334642Smarc 				    key == LK_INPUT_ERROR ||
211434642Smarc 				    key == LK_OUTPUT_ERROR) {
211534642Smarc 					printf(
2116*34732Smarc 				    "qd%d: qdiint: keyboard error, code = %x\n",
211734642Smarc 					qd,key);
2118*34732Smarc 					return;
211934642Smarc 				}
212030391Skarels 
212134642Smarc 				if (key < LK_LOWEST)
2122*34732Smarc 				    return;
212330391Skarels 
212434642Smarc 				++do_wakeup;  /* request a select wakeup call */
212530391Skarels 
212634642Smarc 				event = PUTBEGIN(eqh);
212734642Smarc 				PUTEND(eqh);
212830391Skarels 
212934642Smarc 				event->vse_key = key;
213034642Smarc 				event->vse_key &= 0x00FF;
213134642Smarc 				event->vse_x = eqh->curs_pos.x;
213234642Smarc 				event->vse_y = eqh->curs_pos.y;
213334642Smarc 				event->vse_time = TOY;
213434642Smarc 				event->vse_type = VSE_BUTTON;
213534642Smarc 				event->vse_direction = VSE_KBTRAW;
213634642Smarc 				event->vse_device = VSE_DKB;
213734642Smarc 			}
213830391Skarels 
213934642Smarc 			/*
214034642Smarc 			* pick up the mouse input (if any)  */
214130391Skarels 
214234642Smarc 			if ((status = duart->statusB) & RCV_RDY  &&
214334642Smarc 			    qdflags[qd].pntr_id == MOUSE_ID) {
214430391Skarels 
214534642Smarc 				if (status & 0x70) {
214634642Smarc 					duart->cmdB = 0x40;
214734642Smarc 					continue;
214834642Smarc 				}
214930391Skarels 
215034642Smarc 				/* event queue full now? (overflow condition) */
215130391Skarels 
215234642Smarc 				if (ISFULL(eqh) == TRUE) {
215334642Smarc 					printf(
2154*34732Smarc 					"qd%d: qdiint: event queue overflow\n",
215534642Smarc 					     qd);
215634642Smarc 					break;
215734642Smarc 				}
215830391Skarels 
215934642Smarc 				data = duart->dataB;      /* get report byte */
216034642Smarc 				++new_rep->bytcnt; /* bump report byte count */
216130391Skarels 
216234642Smarc 				/*
216334642Smarc 				* if 1st byte of report.. */
216430391Skarels 
216534642Smarc 				if ( data & START_FRAME) {
216634642Smarc 					new_rep->state = data;
216734642Smarc 					if (new_rep->bytcnt > 1) {
216834642Smarc 						/* start of new frame */
216934642Smarc 						new_rep->bytcnt = 1;
217034642Smarc 						/* ..continue looking */
217134642Smarc 						continue;
217234642Smarc 					}
217334642Smarc 				}
217430391Skarels 
217534642Smarc 				/*
217634642Smarc 				* if 2nd byte of report.. */
217730391Skarels 
217834642Smarc 				else if (new_rep->bytcnt == 2) {
217934642Smarc 					new_rep->dx = data & 0x00FF;
218034642Smarc 				}
218130391Skarels 
218234642Smarc 				/*
218334642Smarc 				* if 3rd byte of report, load input event queue */
218430391Skarels 
218534642Smarc 				else if (new_rep->bytcnt == 3) {
218630391Skarels 
218734642Smarc 					new_rep->dy = data & 0x00FF;
218834642Smarc 					new_rep->bytcnt = 0;
218930391Skarels 
219034642Smarc 					/*
219134642Smarc 					* if mouse position has changed.. */
219230391Skarels 
219334642Smarc 					if (new_rep->dx != 0  ||  new_rep->dy != 0) {
219430391Skarels 
219534642Smarc 						/*
219634642Smarc 						* calculate acceleration factor, if needed	*/
219730391Skarels 
219834642Smarc 						if (qdflags[qd].curs_acc > ACC_OFF) {
219930391Skarels 
220034642Smarc 							if (qdflags[qd].curs_thr <= new_rep->dx)
220134642Smarc 							    new_rep->dx +=
220234642Smarc 							    (new_rep->dx - qdflags[qd].curs_thr)
220334642Smarc 							    * qdflags[qd].curs_acc;
220430391Skarels 
220534642Smarc 							if (qdflags[qd].curs_thr <= new_rep->dy)
220634642Smarc 							    new_rep->dy +=
220734642Smarc 							    (new_rep->dy - qdflags[qd].curs_thr)
220834642Smarc 							    * qdflags[qd].curs_acc;
220934642Smarc 						}
221030391Skarels 
221134642Smarc 						/*
221234642Smarc 						* update cursor position coordinates */
221330391Skarels 
221434642Smarc 						if (new_rep->state & X_SIGN) {
221534642Smarc 							eqh->curs_pos.x += new_rep->dx;
221634642Smarc 							if (eqh->curs_pos.x > 1023)
221734642Smarc 							    eqh->curs_pos.x = 1023;
221834642Smarc 						}
221934642Smarc 						else {
222034642Smarc 							eqh->curs_pos.x -= new_rep->dx;
222134642Smarc 							if (eqh->curs_pos.x < -15)
222234642Smarc 							    eqh->curs_pos.x = -15;
222334642Smarc 						}
222430391Skarels 
222534642Smarc 						if (new_rep->state & Y_SIGN) {
222634642Smarc 							eqh->curs_pos.y -= new_rep->dy;
222734642Smarc 							if (eqh->curs_pos.y < -15)
222834642Smarc 							    eqh->curs_pos.y = -15;
222934642Smarc 						}
223034642Smarc 						else {
223134642Smarc 							eqh->curs_pos.y += new_rep->dy;
223234642Smarc 							if (eqh->curs_pos.y > 863)
223334642Smarc 							    eqh->curs_pos.y = 863;
223434642Smarc 						}
223530391Skarels 
223634642Smarc 						/*
223734642Smarc 						* update cursor screen position */
223830391Skarels 
223934642Smarc 						dga = (struct dga *) qdmap[qd].dga;
224034642Smarc 						dga->x_cursor = TRANX(eqh->curs_pos.x);
224134642Smarc 						dga->y_cursor = TRANY(eqh->curs_pos.y);
224230391Skarels 
224334642Smarc 						/*
224434642Smarc 						* if cursor is in the box, no event report */
224530391Skarels 
224634642Smarc 						if (eqh->curs_pos.x <= eqh->curs_box.right	&&
224734642Smarc 						    eqh->curs_pos.x >= eqh->curs_box.left  &&
224834642Smarc 						    eqh->curs_pos.y >= eqh->curs_box.top  &&
224934642Smarc 						    eqh->curs_pos.y <= eqh->curs_box.bottom ) {
225034642Smarc 							goto GET_MBUTTON;
225134642Smarc 						}
225230391Skarels 
225334642Smarc 						/*
225434642Smarc 						* report the mouse motion event */
225530391Skarels 
225634642Smarc 						event = PUTBEGIN(eqh);
225734642Smarc 						PUTEND(eqh);
225830391Skarels 
225934642Smarc 						++do_wakeup;   /* request a select wakeup call */
226030391Skarels 
226134642Smarc 						event->vse_x = eqh->curs_pos.x;
226234642Smarc 						event->vse_y = eqh->curs_pos.y;
226330391Skarels 
226434642Smarc 						event->vse_device = VSE_MOUSE;  /* mouse */
226534642Smarc 						event->vse_type = VSE_MMOTION;  /* pos changed */
226634642Smarc 						event->vse_key = 0;
226734642Smarc 						event->vse_direction = 0;
226834642Smarc 						event->vse_time = TOY;	/* time stamp */
226934642Smarc 					}
227030391Skarels 
227130391Skarels GET_MBUTTON:
227234642Smarc 					/*
227334642Smarc 					* if button state has changed */
227430391Skarels 
227534642Smarc 					a = new_rep->state & 0x07;    /*mask nonbutton bits */
227634642Smarc 					b = last_rep[qd].state & 0x07;
227730391Skarels 
227834642Smarc 					if (a ^ b) {
227930391Skarels 
228034642Smarc 						for ( c = 1;  c < 8; c <<= 1) {
228130391Skarels 
228234642Smarc 							if (!( c & (a ^ b))) /* this button change? */
228334642Smarc 							    continue;
228430391Skarels 
228534642Smarc 							/* event queue full? (overflow condition) */
228630391Skarels 
228734642Smarc 							if (ISFULL(eqh) == TRUE) {
2288*34732Smarc 								printf("qd%d: qdiint: event queue overflow\n", qd);
228934642Smarc 								break;
229034642Smarc 							}
229130391Skarels 
229234642Smarc 							event = PUTBEGIN(eqh);	/* get new event */
229334642Smarc 							PUTEND(eqh);
229430391Skarels 
229534642Smarc 							++do_wakeup;   /* request select wakeup */
229630391Skarels 
229734642Smarc 							event->vse_x = eqh->curs_pos.x;
229834642Smarc 							event->vse_y = eqh->curs_pos.y;
229930391Skarels 
230034642Smarc 							event->vse_device = VSE_MOUSE;	/* mouse */
230134642Smarc 							event->vse_type = VSE_BUTTON; /* new button */
230234642Smarc 							event->vse_time = TOY;	      /* time stamp */
230330391Skarels 
230434642Smarc 							/* flag changed button and if up or down */
230530391Skarels 
230634642Smarc 							if (c == RIGHT_BUTTON)
230734642Smarc 							    event->vse_key = VSE_RIGHT_BUTTON;
230834642Smarc 							else if (c == MIDDLE_BUTTON)
230934642Smarc 							    event->vse_key = VSE_MIDDLE_BUTTON;
231034642Smarc 							else if (c == LEFT_BUTTON)
231134642Smarc 							    event->vse_key = VSE_LEFT_BUTTON;
231230391Skarels 
231334642Smarc 							/* set bit = button depressed */
231430391Skarels 
231534642Smarc 							if (c & a)
231634642Smarc 							    event->vse_direction = VSE_KBTDOWN;
231734642Smarc 							else
231834642Smarc 								event->vse_direction = VSE_KBTUP;
231934642Smarc 						}
232034642Smarc 					}
232130391Skarels 
232234642Smarc 					/* refresh last report */
232330391Skarels 
232434642Smarc 					last_rep[qd] = current_rep[qd];
232530391Skarels 
232634642Smarc 				}  /* get last byte of report */
2327*34732Smarc 			} else if ((status = duart->statusB)&RCV_RDY &&
2328*34732Smarc 			           qdflags[qd].pntr_id == TABLET_ID) {
2329*34732Smarc 				/*
2330*34732Smarc 				* pickup tablet input, if any
2331*34732Smarc 				*/
2332*34732Smarc 				if (status&0x70) {
233334642Smarc 					duart->cmdB = 0x40;
233434642Smarc 					continue;
233534642Smarc 				}
2336*34732Smarc 				/*
2337*34732Smarc 				 * event queue full now? (overflow condition)
2338*34732Smarc 				 */
233934642Smarc 				if (ISFULL(eqh) == TRUE) {
2340*34732Smarc 					printf("qd%d: qdiint: event queue overflow\n", qd);
234134642Smarc 					break;
234234642Smarc 				}
234330391Skarels 
234434642Smarc 				data = duart->dataB;      /* get report byte */
234534642Smarc 				++new_rep->bytcnt;	      /* bump report byte count */
234630391Skarels 
234734642Smarc 				/*
234834642Smarc 				* if 1st byte of report.. */
234930391Skarels 
235034642Smarc 				if (data & START_FRAME) {
235134642Smarc 					new_rep->state = data;
235234642Smarc 					if (new_rep->bytcnt > 1) {
235334642Smarc 						new_rep->bytcnt = 1;    /* start of new frame */
235434642Smarc 						continue;		    /* ..continue looking */
235534642Smarc 					}
235634642Smarc 				}
235730391Skarels 
235834642Smarc 				/*
235934642Smarc 				* if 2nd byte of report.. */
236030391Skarels 
236134642Smarc 				else if (new_rep->bytcnt == 2) {
236234642Smarc 					new_rep->dx = data & 0x3F;
236334642Smarc 				}
236430391Skarels 
236534642Smarc 				/*
236634642Smarc 				* if 3rd byte of report.. */
236730391Skarels 
236834642Smarc 				else if (new_rep->bytcnt == 3) {
236934642Smarc 					new_rep->dx |= (data & 0x3F) << 6;
237034642Smarc 				}
237130391Skarels 
237234642Smarc 				/*
237334642Smarc 				* if 4th byte of report.. */
237430391Skarels 
237534642Smarc 				else if (new_rep->bytcnt == 4) {
237634642Smarc 					new_rep->dy = data & 0x3F;
237734642Smarc 				}
237830391Skarels 
237934642Smarc 				/*
238034642Smarc 				* if 5th byte of report, load input event queue */
238130391Skarels 
238234642Smarc 				else if (new_rep->bytcnt == 5) {
238330391Skarels 
238434642Smarc 					new_rep->dy |= (data & 0x3F) << 6;
238534642Smarc 					new_rep->bytcnt = 0;
238630391Skarels 
238734642Smarc 					/*
238834642Smarc 					* update cursor position coordinates */
238930391Skarels 
239034642Smarc 					new_rep->dx /= qdflags[qd].tab_res;
239134642Smarc 					new_rep->dy = (2200 - new_rep->dy)
239234642Smarc 					    / qdflags[qd].tab_res;
239330391Skarels 
239434642Smarc 					if (new_rep->dx > 1023) {
239534642Smarc 						new_rep->dx = 1023;
239634642Smarc 					}
239734642Smarc 					if (new_rep->dy > 863) {
239834642Smarc 						new_rep->dy = 863;
239934642Smarc 					}
240030391Skarels 
240134642Smarc 					/*
240234642Smarc 					* report an event if the puck/stylus has moved
240334642Smarc 					*/
240430391Skarels 
240534642Smarc 					if (eqh->curs_pos.x != new_rep->dx ||
240634642Smarc 					    eqh->curs_pos.y != new_rep->dy) {
240730391Skarels 
240834642Smarc 						eqh->curs_pos.x = new_rep->dx;
240934642Smarc 						eqh->curs_pos.y = new_rep->dy;
241030391Skarels 
241134642Smarc 						/*
241234642Smarc 						* update cursor screen position */
241330391Skarels 
241434642Smarc 						dga = (struct dga *) qdmap[qd].dga;
241534642Smarc 						dga->x_cursor = TRANX(eqh->curs_pos.x);
241634642Smarc 						dga->y_cursor = TRANY(eqh->curs_pos.y);
241730391Skarels 
241834642Smarc 						/*
241934642Smarc 						* if cursor is in the box, no event report
242034642Smarc 						*/
242130391Skarels 
242234642Smarc 						if (eqh->curs_pos.x <= eqh->curs_box.right	&&
242334642Smarc 						    eqh->curs_pos.x >= eqh->curs_box.left  &&
242434642Smarc 						    eqh->curs_pos.y >= eqh->curs_box.top  &&
242534642Smarc 						    eqh->curs_pos.y <= eqh->curs_box.bottom ) {
242634642Smarc 							goto GET_TBUTTON;
242734642Smarc 						}
242830391Skarels 
242934642Smarc 						/*
243034642Smarc 						* report the tablet motion event */
243130391Skarels 
243234642Smarc 						event = PUTBEGIN(eqh);
243334642Smarc 						PUTEND(eqh);
243430391Skarels 
243534642Smarc 						++do_wakeup;   /* request a select wakeup call */
243630391Skarels 
243734642Smarc 						event->vse_x = eqh->curs_pos.x;
243834642Smarc 						event->vse_y = eqh->curs_pos.y;
243930391Skarels 
244034642Smarc 						event->vse_device = VSE_TABLET;  /* tablet */
244134642Smarc 						/*
244234642Smarc 						* right now, X handles tablet motion the same
244334642Smarc 						* as mouse motion
244434642Smarc 						*/
244534642Smarc 						event->vse_type = VSE_MMOTION;   /* pos changed */
244634642Smarc 						event->vse_key = 0;
244734642Smarc 						event->vse_direction = 0;
244834642Smarc 						event->vse_time = TOY;	/* time stamp */
244934642Smarc 					}
245030391Skarels GET_TBUTTON:
245134642Smarc 					/*
245234642Smarc 					* if button state has changed */
245330391Skarels 
245434642Smarc 					a = new_rep->state & 0x1E;   /* mask nonbutton bits */
245534642Smarc 					b = last_rep[qd].state & 0x1E;
245630391Skarels 
245734642Smarc 					if (a ^ b) {
245830391Skarels 
245934642Smarc 						/* event queue full now? (overflow condition) */
246030391Skarels 
246134642Smarc 						if (ISFULL(eqh) == TRUE) {
2462*34732Smarc 							printf("qd%d: qdiint: event queue overflow\n",qd);
246334642Smarc 							break;
246434642Smarc 						}
246530391Skarels 
246634642Smarc 						event = PUTBEGIN(eqh);  /* get new event */
246734642Smarc 						PUTEND(eqh);
246830391Skarels 
246934642Smarc 						++do_wakeup;   /* request a select wakeup call */
247030391Skarels 
247134642Smarc 						event->vse_x = eqh->curs_pos.x;
247234642Smarc 						event->vse_y = eqh->curs_pos.y;
247330391Skarels 
247434642Smarc 						event->vse_device = VSE_TABLET;  /* tablet */
247534642Smarc 						event->vse_type = VSE_BUTTON; /* button changed */
247634642Smarc 						event->vse_time = TOY;	   /* time stamp */
247730391Skarels 
247834642Smarc 						/* define the changed button and if up or down */
247930391Skarels 
248034642Smarc 						for ( c = 1;  c <= 0x10; c <<= 1) {
248134642Smarc 							if (c & (a ^ b)) {
248234642Smarc 								if (c == T_LEFT_BUTTON)
248334642Smarc 								    event->vse_key = VSE_T_LEFT_BUTTON;
248434642Smarc 								else if (c == T_FRONT_BUTTON)
248534642Smarc 								    event->vse_key = VSE_T_FRONT_BUTTON;
248634642Smarc 								else if (c == T_RIGHT_BUTTON)
248734642Smarc 								    event->vse_key = VSE_T_RIGHT_BUTTON;
248834642Smarc 								else if (c == T_BACK_BUTTON)
248934642Smarc 								    event->vse_key = VSE_T_BACK_BUTTON;
249034642Smarc 								break;
249134642Smarc 							}
249234642Smarc 						}
249330391Skarels 
249434642Smarc 						/* set bit = button depressed */
249530391Skarels 
249634642Smarc 						if (c & a)
249734642Smarc 						    event->vse_direction = VSE_KBTDOWN;
249834642Smarc 						else
249934642Smarc 							event->vse_direction = VSE_KBTUP;
250034642Smarc 					}
250130391Skarels 
250234642Smarc 					/* refresh last report */
250330391Skarels 
250434642Smarc 					last_rep[qd] = current_rep[qd];
250530391Skarels 
250634642Smarc 				} /* get last byte of report */
250734642Smarc 			} /* pick up tablet input */
250830391Skarels 
250934642Smarc 		} /* while input available.. */
251030391Skarels 
251134642Smarc 		/*
251234642Smarc 		* do select wakeup
251334642Smarc 		*/
2514*34732Smarc 		if (qdrsel[qd] && do_wakeup && qdflags[qd].selmask & SEL_READ) {
2515*34732Smarc 			selwakeup(qdrsel[qd], 0);
2516*34732Smarc 			qdrsel[qd] = 0;
251734642Smarc 			qdflags[qd].selmask &= ~SEL_READ;
251834642Smarc 			do_wakeup = 0;
251934642Smarc 		}
2520*34732Smarc 	} else {
2521*34732Smarc 		/*
2522*34732Smarc 		 * if the graphic device is not turned on, this is console input
2523*34732Smarc 		 */
252434642Smarc 		ui = qdinfo[qd];
252534642Smarc 		if (ui == 0 || ui->ui_alive == 0)
2526*34732Smarc 			return;
252730391Skarels 
252834642Smarc 		tp = &qd_tty[qd << 2];
252930391Skarels 
253034642Smarc 		/*
2531*34732Smarc 		 * Get a character from the keyboard.
2532*34732Smarc 		 */
2533*34732Smarc 		while (duart->statusA&RCV_RDY) {
253434642Smarc 			key = duart->dataA;
253534642Smarc 			key &= 0xFF;
253634642Smarc 			/*
2537*34732Smarc 			* Check for various keyboard errors
2538*34732Smarc 			*/
2539*34732Smarc 			if (key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
254034642Smarc 			    key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
2541*34732Smarc 				printf("qd%d: qdiint: Keyboard error, code = %x\n",qd,key);
2542*34732Smarc 				return;
254334642Smarc 			}
254430391Skarels 
254534642Smarc 			if (key < LK_LOWEST)
2546*34732Smarc 			    return;
254730391Skarels 
254834642Smarc 			/*
254934642Smarc 			* See if its a state change key */
255030391Skarels 
255134642Smarc 			switch (key) {
255230391Skarels 
255334642Smarc 			case LOCK:
255434642Smarc 				q_keyboard.lock ^= 0xffff;	/* toggle */
255534642Smarc 				if (q_keyboard.lock)
2556*34732Smarc 					(void)led_control(qd, LK_LED_ENABLE,
2557*34732Smarc 							  LK_LED_LOCK);
255834642Smarc 				else
2559*34732Smarc 					(void)led_control(qd, LK_LED_DISABLE,
2560*34732Smarc 							  LK_LED_LOCK);
256134642Smarc 				return;
256230391Skarels 
256334642Smarc 			case SHIFT:
256434642Smarc 				q_keyboard.shift ^= 0xFFFF;
256534642Smarc 				return;
256630391Skarels 
256734642Smarc 			case CNTRL:
256834642Smarc 				q_keyboard.cntrl ^= 0xFFFF;
256934642Smarc 				return;
257030391Skarels 
257134642Smarc 			case ALLUP:
257234642Smarc 				q_keyboard.cntrl = 0;
257334642Smarc 				q_keyboard.shift = 0;
257434642Smarc 				return;
257530391Skarels 
257634642Smarc 			case REPEAT:
257734642Smarc 				chr = q_keyboard.last;
257834642Smarc 				break;
257930391Skarels 
258034642Smarc 				/*
258134642Smarc 				* Test for cntrl characters. If set, see if the character
258234642Smarc 				* is elligible to become a control character. */
258330391Skarels 
258434642Smarc 			default:
258530391Skarels 
258634642Smarc 				if (q_keyboard.cntrl) {
258734642Smarc 					chr = q_key[key];
258834642Smarc 					if (chr >= ' ' && chr <= '~')
258934642Smarc 					    chr &= 0x1F;
259034642Smarc 					else if (chr >= 0xA1 && chr <= 0xFE)
259134642Smarc 					    chr &= 0x9F;
259234642Smarc 				}
259334642Smarc 				else if( q_keyboard.lock || q_keyboard.shift )
259434642Smarc 				    chr = q_shift_key[key];
259534642Smarc 				else
259634642Smarc 					chr = q_key[key];
259734642Smarc 				break;
259830391Skarels 			}
259930391Skarels 
260034642Smarc 			q_keyboard.last = chr;
260130391Skarels 
260234642Smarc 			/*
260334642Smarc 			* Check for special function keys */
260430391Skarels 
260534642Smarc 			if (chr & 0x100) {
260634642Smarc 				char *string;
260734642Smarc 				string = q_special[chr & 0x7F];
260834642Smarc 				while(*string)
260934642Smarc 				    (*linesw[tp->t_line].l_rint)(*string++, tp);
261034615Smarc 			}
261134642Smarc 			else {
261234642Smarc 				(*linesw[tp->t_line].l_rint)(chr&0177, tp);
261334642Smarc 			}
261430391Skarels 		}
261530391Skarels 	}
261630391Skarels } /* qdiint */
261730391Skarels 
2618*34732Smarc /*
2619*34732Smarc  *
2620*34732Smarc  * Clear the QDSS screen
2621*34732Smarc  *
2622*34732Smarc  *			     >>> NOTE <<<
2623*34732Smarc  *
2624*34732Smarc  *   This code requires that certain adder initialization be valid.  To
2625*34732Smarc  *   assure that this requirement is satisfied, this routine should be
2626*34732Smarc  *   called only after calling the "setup_dragon()" function.
2627*34732Smarc  *
2628*34732Smarc  *   Clear the bitmap a piece at a time. Since the fast scroll clear
2629*34732Smarc  *   only clears the current displayed portion of the bitmap put a
2630*34732Smarc  *   temporary value in the y limit register so we can access whole
2631*34732Smarc  *   bitmap
2632*34732Smarc  *
2633*34732Smarc  */
263430391Skarels clear_qd_screen(unit)
2635*34732Smarc 	int unit;
263630391Skarels {
263730391Skarels 	register struct adder *adder;
263830391Skarels 	adder = (struct adder *) qdmap[unit].adder;
263930391Skarels 
264030391Skarels 	adder->x_limit = 1024;
264130391Skarels 	adder->y_limit = 2048 - CHAR_HEIGHT;
264230391Skarels 	adder->y_offset_pending = 0;
2643*34732Smarc #define WSV  (void)wait_status(adder, VSYNC); (void)wait_status(adder, VSYNC)
264434642Smarc 	WSV;
264530391Skarels 	adder->y_scroll_constant = SCROLL_ERASE;
264634642Smarc 	WSV;
264730391Skarels 	adder->y_offset_pending = 864;
264834642Smarc 	WSV;
264930391Skarels 	adder->y_scroll_constant = SCROLL_ERASE;
265034642Smarc 	WSV;
265130391Skarels 	adder->y_offset_pending = 1728;
265234642Smarc 	WSV;
265330391Skarels 	adder->y_scroll_constant = SCROLL_ERASE;
265434642Smarc 	WSV;
265530391Skarels 	adder->y_offset_pending = 0;	 /* back to normal */
265634642Smarc 	WSV;
265730391Skarels 	adder->x_limit = MAX_SCREEN_X;
265830391Skarels 	adder->y_limit = MAX_SCREEN_Y + FONT_HEIGHT;
265934642Smarc #undef WSV
266030391Skarels 
266130391Skarels } /* clear_qd_screen */
266230391Skarels 
2663*34732Smarc /*
2664*34732Smarc  *  kernel console output to the glass tty
2665*34732Smarc  */
266630391Skarels qdputc(chr)
266734642Smarc 	register char chr;
266830391Skarels {
266930391Skarels 
267034642Smarc 	/*
267134642Smarc 	 * if system is now physical, forget it (ie: crash DUMP)
267234642Smarc 	 */
267334642Smarc 	if ((mfpr(MAPEN) & 1) == 0)
267434642Smarc 		return;
267534615Smarc 
2676*34732Smarc 	blitc(0, (u_char)(chr & 0xff));
267732012Smarc 	if ((chr & 0177) == '\n')
267832012Smarc 		blitc(0, '\r');
267930391Skarels 
268030391Skarels } /* qdputc */
268130391Skarels 
2682*34732Smarc /*
2683*34732Smarc  *  load the mouse cursor's template RAM bitmap
2684*34732Smarc  */
268530391Skarels ldcursor(unit, bitmap)
2686*34732Smarc 	int unit;
2687*34732Smarc 	register short *bitmap;
268830391Skarels {
268930391Skarels 	register struct dga *dga;
269030391Skarels 	register short *temp;
269130391Skarels 	register int i;
2692*34732Smarc 	int curs;
269330391Skarels 
269430391Skarels 	dga = (struct dga *) qdmap[unit].dga;
269530391Skarels 	temp = (short *) qdmap[unit].template;
269630391Skarels 
269730391Skarels 	if (dga->csr & CURS_ENB) {	/* if the cursor is enabled.. */
2698*34732Smarc 		curs = -1;		/* ..note that.. */
269934642Smarc 		dga->csr &= ~CURS_ENB;	/* ..and shut it off */
2700*34732Smarc 	} else
2701*34732Smarc 		curs = 0;
270230391Skarels 
270330391Skarels 	dga->csr &= ~CURS_ENB;		/* shut off the cursor */
270430391Skarels 
270530391Skarels 	temp += (8 * 1024) - 32;	/* cursor is 32 WORDS from the end */
270634642Smarc 	/* ..of the 8k WORD template space */
270730391Skarels 	for (i = 0; i < 32; ++i)
270834642Smarc 		*temp++ = *bitmap++;
270930391Skarels 
2710*34732Smarc 	if (curs) {			/* if cursor was enabled.. */
271134642Smarc 		dga->csr |= CURS_ENB;	/* ..turn it back on */
271230391Skarels 	}
271330391Skarels 
271430391Skarels } /* ldcursor */
271530391Skarels 
2716*34732Smarc /*
2717*34732Smarc  *  Put the console font in the QDSS off-screen memory
2718*34732Smarc  */
271930391Skarels ldfont(unit)
2720*34732Smarc 	int unit;
272130391Skarels {
272230391Skarels 	register struct adder *adder;
272330391Skarels 
2724*34732Smarc 	register i, j, k, max_chars_line;
2725*34732Smarc 	register short packed;
272630391Skarels 
272730391Skarels 	adder = (struct adder *) qdmap[unit].adder;
272830391Skarels 
272934642Smarc 	/*
2730*34732Smarc 	* setup VIPER operand control registers
2731*34732Smarc 	*/
273230391Skarels 	write_ID(adder, MASK_1, 0xFFFF);
273330391Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
273430391Skarels 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
273530391Skarels 
273630391Skarels 	write_ID(adder, SRC1_OCR_B,
273734642Smarc 	EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY);
273830391Skarels 	write_ID(adder, SRC2_OCR_B,
273934642Smarc 	EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY);
274030391Skarels 	write_ID(adder, DST_OCR_B,
274134642Smarc 	EXT_SOURCE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
274230391Skarels 
274330391Skarels 	adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL;
274430391Skarels 
274534642Smarc 	/*
2746*34732Smarc 	* load destination data
2747*34732Smarc 	*/
2748*34732Smarc 	(void)wait_status(adder, RASTEROP_COMPLETE);
274930391Skarels 
275030391Skarels 	adder->destination_x = FONT_X;
275130391Skarels 	adder->destination_y = FONT_Y;
2752*34732Smarc #if FONT_WIDTH > MAX_SCREEN_X
2753*34732Smarc 	adder->fast_dest_dx = MAX_SCREEN_X;
2754*34732Smarc #else
2755*34732Smarc 	adder->fast_dest_dx = FONT_WIDTH;
2756*34732Smarc #endif
275730391Skarels 	adder->slow_dest_dy = CHAR_HEIGHT;
275830391Skarels 
275934642Smarc 	/*
276034642Smarc 	* setup for processor to bitmap xfer  */
276130391Skarels 
276230391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0001);
276330391Skarels 	adder->cmd = PBT | OCRB | 2 | DTE | 2;
276430391Skarels 
276534642Smarc 	/*
276634642Smarc 	* Figure out how many characters can be stored on one "line" of
276734642Smarc 	* offscreen memory.
276834642Smarc 	*/
276934642Smarc 	max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
277034642Smarc 	if ((CHARS/2 + CHARS%2) < max_chars_line)
277134642Smarc 	    max_chars_line = CHARS/2 + CHARS%2;
277230391Skarels 
277334642Smarc 	/*
277434642Smarc 	* iteratively do the processor to bitmap xfer */
277534615Smarc 
277630391Skarels 	for (i = 0; i < ROWS; ++i) {
277730391Skarels 
277834642Smarc 		/* PTOB a scan line */
277930391Skarels 
278034642Smarc 		for (j = 0, k = i; j < max_chars_line; ++j) {
278134642Smarc 			/* PTOB one scan of a char cell */
278230391Skarels 
278334642Smarc 			packed = q_font[k];
278434642Smarc 			k += ROWS;
278534642Smarc 			packed |= ((short)q_font[k] << 8);
278634642Smarc 			k += ROWS;
278730391Skarels 
2788*34732Smarc 			(void)wait_status(adder, TX_READY);
278934642Smarc 			adder->id_data = packed;
279034642Smarc 		}
279130391Skarels 	}
279230391Skarels 
279334642Smarc 	/*
279434642Smarc 	 * (XXX XXX XXX - should remove)
279534642Smarc 	 *
279634642Smarc 	 * Copy the second row of characters.  Subtract the first
279734642Smarc 	 * row from the total number.  Divide this quantity by 2
279834642Smarc 	 * because 2 chars are stored in a short in the PTOB loop
279934642Smarc 	 * below.  Figure out how many characters can be stored on
280034642Smarc 	 * one "line" of offscreen memory
280134642Smarc 	 */
280234642Smarc 
280334642Smarc 	max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
280434642Smarc 	if ((CHARS/2 + CHARS%2) < max_chars_line)
280534642Smarc 	    return;
280634642Smarc 	max_chars_line = (CHARS/2 + CHARS%2) - max_chars_line; /* 95 - 64 */
280734642Smarc 	/* Paranoia check to see if 3rd row may be needed */
280834642Smarc 	if (max_chars_line > (MAX_SCREEN_X/(CHAR_WIDTH*2)))
280934615Smarc 	    max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
281034615Smarc 
281134615Smarc 	adder->destination_x = FONT_X;
281234615Smarc 	adder->destination_y = FONT_Y - CHAR_HEIGHT;
281334615Smarc 	adder->fast_dest_dx = max_chars_line * CHAR_WIDTH * 2;
281434615Smarc 	adder->slow_dest_dy = CHAR_HEIGHT;
281534615Smarc 
281634642Smarc 	/*
281734642Smarc 	* setup for processor to bitmap xfer
281834642Smarc 	*/
281934615Smarc 	write_ID(adder, CS_UPDATE_MASK, 0x0001);
282034615Smarc 	adder->cmd = PBT | OCRB | 2 | DTE | 2;
282134615Smarc 
282234642Smarc 	/*
282334642Smarc 	* iteratively do the processor to bitmap xfer
282434642Smarc 	*/
282534615Smarc 	for (i = 0; i < ROWS; ++i) {
282634642Smarc 		/*
282734642Smarc 		 * PTOB a scan line
282834642Smarc 		 */
282934642Smarc 		for (j = 0, k = i; j < max_chars_line; ++j) {
283034642Smarc 			/*
283134642Smarc 			 * PTOB one scan of a char cell
283234642Smarc 			 */
283334642Smarc 			packed = q_font[k + FONT_OFFSET];
283434642Smarc 			k += ROWS;
283534642Smarc 			packed |= ((short)q_font[k + FONT_OFFSET] << 8);
283634642Smarc 			k += ROWS;
2837*34732Smarc 			(void)wait_status(adder, TX_READY);
283834642Smarc 			adder->id_data = packed;
283934642Smarc 		}
284034615Smarc 	}
284134615Smarc 
284230391Skarels }  /* ldfont */
284330391Skarels 
2844*34732Smarc /*
2845*34732Smarc  *  Get a character from the LK201 (polled)
2846*34732Smarc  */
2847*34732Smarc qdgetc()
2848*34732Smarc {
2849*34732Smarc 	register short key;
2850*34732Smarc 	register char chr;
2851*34732Smarc 	register struct duart *duart;
285230391Skarels 
2853*34732Smarc 	duart = (struct duart *) qdmap[0].duart;
2854*34732Smarc 
2855*34732Smarc 	/*
2856*34732Smarc 	* Get a character from the keyboard.
2857*34732Smarc 	*/
2858*34732Smarc LOOP:
2859*34732Smarc 	while (!(duart->statusA&RCV_RDY))
2860*34732Smarc 		;
2861*34732Smarc 
2862*34732Smarc 	key = duart->dataA;
2863*34732Smarc 	key &= 0xFF;
2864*34732Smarc 
2865*34732Smarc 	/*
2866*34732Smarc 	* Check for various keyboard errors  */
2867*34732Smarc 
2868*34732Smarc 	if (key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
2869*34732Smarc 	    key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
2870*34732Smarc 		printf("Keyboard error, code = %x\n", key);
2871*34732Smarc 		return(0);
2872*34732Smarc 	}
2873*34732Smarc 
2874*34732Smarc 	if (key < LK_LOWEST)
2875*34732Smarc 		return(0);
2876*34732Smarc 
2877*34732Smarc 	/*
2878*34732Smarc 	 * See if its a state change key
2879*34732Smarc 	 */
2880*34732Smarc 	switch (key) {
2881*34732Smarc 
2882*34732Smarc 	case LOCK:
2883*34732Smarc 		q_keyboard.lock ^= 0xffff;	/* toggle */
2884*34732Smarc 		if (q_keyboard.lock)
2885*34732Smarc 			(void)led_control(0, LK_LED_ENABLE, LK_LED_LOCK);
2886*34732Smarc 		else
2887*34732Smarc 			(void)led_control(0, LK_LED_DISABLE, LK_LED_LOCK);
2888*34732Smarc 		goto LOOP;
2889*34732Smarc 
2890*34732Smarc 	case SHIFT:
2891*34732Smarc 		q_keyboard.shift ^= 0xFFFF;
2892*34732Smarc 		goto LOOP;
2893*34732Smarc 
2894*34732Smarc 	case CNTRL:
2895*34732Smarc 		q_keyboard.cntrl ^= 0xFFFF;
2896*34732Smarc 		goto LOOP;
2897*34732Smarc 
2898*34732Smarc 	case ALLUP:
2899*34732Smarc 		q_keyboard.cntrl = 0;
2900*34732Smarc 		q_keyboard.shift = 0;
2901*34732Smarc 		goto LOOP;
2902*34732Smarc 
2903*34732Smarc 	case REPEAT:
2904*34732Smarc 		chr = q_keyboard.last;
2905*34732Smarc 		break;
2906*34732Smarc 
2907*34732Smarc 		/*
2908*34732Smarc 		* Test for cntrl characters. If set, see if the character
2909*34732Smarc 		* is elligible to become a control character.
2910*34732Smarc 		*/
2911*34732Smarc 	default:
2912*34732Smarc 
2913*34732Smarc 		if (q_keyboard.cntrl) {
2914*34732Smarc 			chr = q_key[key];
2915*34732Smarc 			if (chr >= ' ' && chr <= '~')
2916*34732Smarc 			    chr &= 0x1F;
2917*34732Smarc 		}
2918*34732Smarc 		else if ( q_keyboard.lock || q_keyboard.shift )
2919*34732Smarc 		    chr = q_shift_key[key];
2920*34732Smarc 		else
2921*34732Smarc 			chr = q_key[key];
2922*34732Smarc 		break;
2923*34732Smarc 	}
2924*34732Smarc 
2925*34732Smarc 	if (chr < ' ' && chr > '~')	/* if input is non-displayable */
2926*34732Smarc 		return(0);		/* ..then pitch it! */
2927*34732Smarc 
2928*34732Smarc 	q_keyboard.last = chr;
2929*34732Smarc 
2930*34732Smarc 	/*
2931*34732Smarc 	* Check for special function keys */
2932*34732Smarc 
2933*34732Smarc 	if (chr & 0x80) 		/* pitch the function keys */
2934*34732Smarc 		return(0);
2935*34732Smarc 	else
2936*34732Smarc 		return(chr);
2937*34732Smarc 
2938*34732Smarc } /* qdgetc */
2939*34732Smarc 
2940*34732Smarc /*
2941*34732Smarc  *  led_control()... twiddle LK-201 LED's
2942*34732Smarc  */
294330391Skarels led_control(unit, cmd, led_mask)
2944*34732Smarc 	int unit, cmd, led_mask;
294530391Skarels {
2946*34732Smarc 	register i;
294730391Skarels 	register struct duart *duart;
294830391Skarels 
2949*34732Smarc 	duart = (struct duart *)qdmap[unit].duart;
295030391Skarels 
295130391Skarels 	for (i = 1000; i > 0; --i) {
2952*34732Smarc 		if (duart->statusA&XMT_RDY) {
295334642Smarc 			duart->dataA = cmd;
295434642Smarc 			break;
295534642Smarc 		}
295630391Skarels 	}
295730391Skarels 	for (i = 1000; i > 0; --i) {
2958*34732Smarc 		if (duart->statusA&XMT_RDY) {
295934642Smarc 			duart->dataA = led_mask;
296034642Smarc 			break;
296134642Smarc 		}
296230391Skarels 	}
296330391Skarels 	if (i == 0)
296434642Smarc 		return(BAD);
296530391Skarels 	return(GOOD);
296630391Skarels 
296730391Skarels } /* led_control */
296830391Skarels 
2969*34732Smarc /*
2970*34732Smarc  *  scroll_up()... move the screen up one character height
2971*34732Smarc  */
297230391Skarels scroll_up(adder)
297334642Smarc 	register struct adder *adder;
297430391Skarels {
297534642Smarc 	/*
297634642Smarc 	* setup VIPER operand control registers
297734642Smarc 	*/
2978*34732Smarc 	(void)wait_status(adder, ADDRESS_COMPLETE);
297930391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x00FF);  /* select all planes */
298030391Skarels 	write_ID(adder, MASK_1, 0xFFFF);
298130391Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
298230391Skarels 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
298330391Skarels 	write_ID(adder, SRC1_OCR_B,
298434642Smarc 	EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY);
298530391Skarels 	write_ID(adder, DST_OCR_B,
298634642Smarc 	EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
298734642Smarc 	/*
298834642Smarc 	 * load DESTINATION origin and vectors
298934642Smarc 	 */
299030391Skarels 	adder->fast_dest_dy = 0;
299130391Skarels 	adder->slow_dest_dx = 0;
299230391Skarels 	adder->error_1 = 0;
299330391Skarels 	adder->error_2 = 0;
299430391Skarels 	adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL;
299530391Skarels 	adder->destination_x = 0;
299630391Skarels 	adder->fast_dest_dx = 1024;
299730391Skarels 	adder->destination_y = 0;
299830391Skarels 	adder->slow_dest_dy = 864 - CHAR_HEIGHT;
299934642Smarc 	/*
300034642Smarc 	 * load SOURCE origin and vectors
300134642Smarc 	 */
300230391Skarels 	adder->source_1_x = 0;
300330391Skarels 	adder->source_1_dx = 1024;
300430391Skarels 	adder->source_1_y = 0 + CHAR_HEIGHT;
300530391Skarels 	adder->source_1_dy = 864 - CHAR_HEIGHT;
300630391Skarels 	write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
300730391Skarels 	adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE;
300834642Smarc 	/*
300934642Smarc 	 * do a rectangle clear of last screen line
301034642Smarc 	 */
301130391Skarels 	write_ID(adder, MASK_1, 0xffff);
301230391Skarels 	write_ID(adder, SOURCE, 0xffff);
301330391Skarels 	write_ID(adder,DST_OCR_B,
301434642Smarc 	(EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY));
301530391Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 0);
301630391Skarels 	adder->error_1 = 0;
301730391Skarels 	adder->error_2 = 0;
301834642Smarc 	adder->slow_dest_dx = 0;		/* set up the width of	*/
301930391Skarels 	adder->slow_dest_dy = CHAR_HEIGHT;	/* rectangle */
302030391Skarels 	adder->rasterop_mode = (NORMAL | DST_WRITE_ENABLE) ;
3021*34732Smarc 	(void)wait_status(adder, RASTEROP_COMPLETE);
302230391Skarels 	adder->destination_x = 0;
302330391Skarels 	adder->destination_y = 864 - CHAR_HEIGHT;
302430391Skarels 	adder->fast_dest_dx = 1024;	/* set up the height	*/
302530391Skarels 	adder->fast_dest_dy = 0;	/* of rectangle 	*/
302630391Skarels 	write_ID(adder, LU_FUNCTION_R2, (FULL_SRC_RESOLUTION | LF_SOURCE));
302730391Skarels 	adder->cmd = (RASTEROP | OCRB | LF_R2 | DTE ) ;
302830391Skarels 
302930391Skarels } /* scroll_up */
303030391Skarels 
3031*34732Smarc /*
3032*34732Smarc  *  init shared memory pointers and structures
3033*34732Smarc  */
303430391Skarels init_shared(unit)
3035*34732Smarc 	register unit;
303630391Skarels {
303730391Skarels 	register struct dga *dga;
303830391Skarels 
303930391Skarels 	dga = (struct dga *) qdmap[unit].dga;
304030391Skarels 
304134642Smarc 	/*
304234642Smarc 	* initialize the event queue pointers and header */
304330391Skarels 
304430391Skarels 	eq_header[unit] = (struct qdinput *)
304534642Smarc 	    ((((int)event_shared & ~(0x01FF)) + 512)
304634642Smarc 		+ (EVENT_BUFSIZE * unit));
304730391Skarels 	eq_header[unit]->curs_pos.x = 0;
304830391Skarels 	eq_header[unit]->curs_pos.y = 0;
304930391Skarels 	dga->x_cursor = TRANX(eq_header[unit]->curs_pos.x);
305030391Skarels 	dga->y_cursor = TRANY(eq_header[unit]->curs_pos.y);
305130391Skarels 	eq_header[unit]->curs_box.left = 0;
305230391Skarels 	eq_header[unit]->curs_box.right = 0;
305330391Skarels 	eq_header[unit]->curs_box.top = 0;
305430391Skarels 	eq_header[unit]->curs_box.bottom = 0;
305534642Smarc 	/*
305634642Smarc 	 * assign a pointer to the DMA I/O buffer for this QDSS.
305734642Smarc 	 */
305830391Skarels 	DMAheader[unit] = (struct DMAreq_header *)
305934642Smarc 	    (((int)(&DMA_shared[0] + 512) & ~0x1FF)
306034642Smarc 		+ (DMAbuf_size * unit));
306130391Skarels 	DMAheader[unit]->DMAreq = (struct DMAreq *) ((int)DMAheader[unit]
306234642Smarc 	    + sizeof(struct DMAreq_header));
306330391Skarels 	DMAheader[unit]->QBAreg = 0;
306430391Skarels 	DMAheader[unit]->status = 0;
306530391Skarels 	DMAheader[unit]->shared_size = DMAbuf_size;
306630391Skarels 	DMAheader[unit]->used = 0;
306730391Skarels 	DMAheader[unit]->size = 10;	/* default = 10 requests */
306830391Skarels 	DMAheader[unit]->oldest = 0;
306930391Skarels 	DMAheader[unit]->newest = 0;
307034642Smarc 	/*
307134642Smarc 	* assign a pointer to the scroll structure for this QDSS.
307234642Smarc 	*/
307330391Skarels 	scroll[unit] = (struct scroll *)
307434642Smarc 	    (((int)(&scroll_shared[0] + 512) & ~0x1FF)
307534642Smarc 		+ (sizeof(struct scroll) * unit));
307630391Skarels 	scroll[unit]->status = 0;
307730391Skarels 	scroll[unit]->viper_constant = 0;
307830391Skarels 	scroll[unit]->y_scroll_constant = 0;
307930391Skarels 	scroll[unit]->y_offset = 0;
308030391Skarels 	scroll[unit]->x_index_pending = 0;
308130391Skarels 	scroll[unit]->y_index_pending = 0;
308234642Smarc 	/*
308334642Smarc 	* assign a pointer to the color map write buffer for this QDSS
308434642Smarc 	*/
308530391Skarels 	color_buf[unit] = (struct color_buf *)
308634642Smarc 	    (((int)(&color_shared[0] + 512) & ~0x1FF)
308734642Smarc 		+ (COLOR_BUFSIZ * unit));
308830391Skarels 	color_buf[unit]->status = 0;
308930391Skarels 	color_buf[unit]->count = 0;
309030391Skarels 
309130391Skarels } /* init_shared */
309230391Skarels 
3093*34732Smarc /*
3094*34732Smarc  * init the ADDER, VIPER, bitmaps, & color map
3095*34732Smarc  */
309630391Skarels setup_dragon(unit)
3097*34732Smarc 	int unit;
309830391Skarels {
309930391Skarels 
310030391Skarels 	register struct adder *adder;
310130391Skarels 	register struct dga *dga;
310230391Skarels 	short *memcsr;
3103*34732Smarc 	register i;
310430391Skarels 	short top;		/* clipping/scrolling boundaries */
310530391Skarels 	short bottom;
310630391Skarels 	short right;
310730391Skarels 	short left;
310830391Skarels 	short *red;		/* color map pointers */
310930391Skarels 	short *green;
311030391Skarels 	short *blue;
311130391Skarels 
311234642Smarc 	/*
311334642Smarc 	* init for setup
311434642Smarc 	*/
311530391Skarels 	adder = (struct adder *) qdmap[unit].adder;
311630391Skarels 	dga = (struct dga *) qdmap[unit].dga;
311730391Skarels 	memcsr = (short *) qdmap[unit].memcsr;
311830391Skarels 	dga->csr &= ~(DMA_IE | 0x700);	/* halt DMA and kill the intrpts */
311930391Skarels 	*memcsr = SYNC_ON;		/* blank screen and turn off LED's */
312030391Skarels 	adder->command = CANCEL;
312134642Smarc 	/*
312234642Smarc 	* set monitor timing
312334642Smarc 	*/
312430391Skarels 	adder->x_scan_count_0 = 0x2800;
312530391Skarels 	adder->x_scan_count_1 = 0x1020;
312630391Skarels 	adder->x_scan_count_2 = 0x003A;
312730391Skarels 	adder->x_scan_count_3 = 0x38F0;
312830391Skarels 	adder->x_scan_count_4 = 0x6128;
312930391Skarels 	adder->x_scan_count_5 = 0x093A;
313030391Skarels 	adder->x_scan_count_6 = 0x313C;
313130391Skarels 	adder->sync_phase_adj = 0x0100;
313230391Skarels 	adder->x_scan_conf = 0x00C8;
313334642Smarc 	/*
313434642Smarc 	 * got a bug in secound pass ADDER! lets take care of it
313534642Smarc 	 *
313634642Smarc 	 * normally, just use the code in the following bug fix code, but to
313734642Smarc 	 * make repeated demos look pretty, load the registers as if there was
313834642Smarc 	 * no bug and then test to see if we are getting sync
313934642Smarc 	 */
314030391Skarels 	adder->y_scan_count_0 = 0x135F;
314130391Skarels 	adder->y_scan_count_1 = 0x3363;
314230391Skarels 	adder->y_scan_count_2 = 0x2366;
314330391Skarels 	adder->y_scan_count_3 = 0x0388;
314434642Smarc 	/*
314534642Smarc 	 * if no sync, do the bug fix code
314634642Smarc 	 */
314730391Skarels 	if (wait_status(adder, VSYNC) == BAD) {
314834642Smarc 		/* first load all Y scan registers with very short frame and
314934642Smarc 		 * wait for scroll service.  This guarantees at least one SYNC
315034642Smarc 		 * to fix the pass 2 Adder initialization bug (synchronizes
315134642Smarc 		 * XCINCH with DMSEEDH)
315234642Smarc 		 */
315334642Smarc 		adder->y_scan_count_0 = 0x01;
315434642Smarc 		adder->y_scan_count_1 = 0x01;
315534642Smarc 		adder->y_scan_count_2 = 0x01;
315634642Smarc 		adder->y_scan_count_3 = 0x01;
315734642Smarc 		/*
315834642Smarc 		 * delay at least 1 full frame time
315934642Smarc 		 */
3160*34732Smarc 		(void)wait_status(adder, VSYNC);
3161*34732Smarc 		(void)wait_status(adder, VSYNC);
316234642Smarc 		/*
316334642Smarc 		 * now load the REAL sync values (in reverse order just to
316434642Smarc 		 * be safe.
316534642Smarc 		 */
316634642Smarc 		adder->y_scan_count_3 = 0x0388;
316734642Smarc 		adder->y_scan_count_2 = 0x2366;
316834642Smarc 		adder->y_scan_count_1 = 0x3363;
316934642Smarc 		adder->y_scan_count_0 = 0x135F;
317030391Skarels 	}
317130391Skarels 	*memcsr = SYNC_ON | UNBLANK;	/* turn off leds and turn on video */
317234642Smarc 	/*
317334642Smarc 	 * zero the index registers
317434642Smarc 	 */
317530391Skarels 	adder->x_index_pending = 0;
317630391Skarels 	adder->y_index_pending = 0;
317730391Skarels 	adder->x_index_new = 0;
317830391Skarels 	adder->y_index_new = 0;
317930391Skarels 	adder->x_index_old = 0;
318030391Skarels 	adder->y_index_old = 0;
318130391Skarels 	adder->pause = 0;
318234642Smarc 	/*
318334642Smarc 	 * set rasterop mode to normal pen down
318434642Smarc 	 */
318530391Skarels 	adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL;
318634642Smarc 	/*
318734642Smarc 	 * set the rasterop registers to a default values
318834642Smarc 	 */
318930391Skarels 	adder->source_1_dx = 1;
319030391Skarels 	adder->source_1_dy = 1;
319130391Skarels 	adder->source_1_x = 0;
319230391Skarels 	adder->source_1_y = 0;
319330391Skarels 	adder->destination_x = 0;
319430391Skarels 	adder->destination_y = 0;
319530391Skarels 	adder->fast_dest_dx = 1;
319630391Skarels 	adder->fast_dest_dy = 0;
319730391Skarels 	adder->slow_dest_dx = 0;
319830391Skarels 	adder->slow_dest_dy = 1;
319930391Skarels 	adder->error_1 = 0;
320030391Skarels 	adder->error_2 = 0;
320134642Smarc 	/*
3202*34732Smarc 	 * scale factor = UNITY
320334642Smarc 	 */
320430391Skarels 	adder->fast_scale = UNITY;
320530391Skarels 	adder->slow_scale = UNITY;
320634642Smarc 	/*
320734642Smarc 	 * set the source 2 parameters
320834642Smarc 	 */
320930391Skarels 	adder->source_2_x = 0;
321030391Skarels 	adder->source_2_y = 0;
321130391Skarels 	adder->source_2_size = 0x0022;
321234642Smarc 	/*
321334642Smarc 	* initialize plane addresses for eight vipers
321434642Smarc 	*/
321530391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0001);
321630391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0000);
321730391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0002);
321830391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0001);
321930391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0004);
322030391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0002);
322130391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0008);
322230391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0003);
322330391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0010);
322430391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0004);
322530391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0020);
322630391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0005);
322730391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0040);
322830391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0006);
322930391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0080);
323030391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0007);
323134642Smarc 	/*
323234642Smarc 	 * initialize the external registers.
323334642Smarc 	 */
323430391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x00FF);
323530391Skarels 	write_ID(adder, CS_SCROLL_MASK, 0x00FF);
323634642Smarc 	/*
323734642Smarc 	 * initialize resolution mode
323834642Smarc 	 */
323930391Skarels 	write_ID(adder, MEMORY_BUS_WIDTH, 0x000C);     /* bus width = 16 */
324030391Skarels 	write_ID(adder, RESOLUTION_MODE, 0x0000);      /* one bit/pixel */
324134642Smarc 	/*
324234642Smarc 	 * initialize viper registers
324334642Smarc 	 */
324430391Skarels 	write_ID(adder, SCROLL_CONSTANT, SCROLL_ENABLE|VIPER_LEFT|VIPER_UP);
324530391Skarels 	write_ID(adder, SCROLL_FILL, 0x0000);
324634642Smarc 	/*
324734642Smarc 	 * set clipping and scrolling limits to full screen
324834642Smarc 	 */
3249*34732Smarc 	for (i = 1000, adder->status = 0;
3250*34732Smarc 	     i > 0 && !(adder->status&ADDRESS_COMPLETE); --i)
325134642Smarc 		;
325230391Skarels 	if (i == 0)
3253*34732Smarc 	    printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n",unit);
325430391Skarels 	top = 0;
325530391Skarels 	bottom = 2048;
325630391Skarels 	left = 0;
325730391Skarels 	right = 1024;
325830391Skarels 	adder->x_clip_min = left;
325930391Skarels 	adder->x_clip_max = right;
326030391Skarels 	adder->y_clip_min = top;
326130391Skarels 	adder->y_clip_max = bottom;
326230391Skarels 	adder->scroll_x_min = left;
326330391Skarels 	adder->scroll_x_max = right;
326430391Skarels 	adder->scroll_y_min = top;
326530391Skarels 	adder->scroll_y_max = bottom;
3266*34732Smarc 	(void)wait_status(adder, VSYNC);	/* wait at LEAST 1 full frame */
3267*34732Smarc 	(void)wait_status(adder, VSYNC);
326830391Skarels 	adder->x_index_pending = left;
326930391Skarels 	adder->y_index_pending = top;
327030391Skarels 	adder->x_index_new = left;
327130391Skarels 	adder->y_index_new = top;
327230391Skarels 	adder->x_index_old = left;
327330391Skarels 	adder->y_index_old = top;
327430391Skarels 
3275*34732Smarc 	for (i = 1000, adder->status = 0; i > 0 &&
3276*34732Smarc 	     !(adder->status&ADDRESS_COMPLETE) ; --i)
327734642Smarc 		;
327830391Skarels 	if (i == 0)
3279*34732Smarc 	       printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n",unit);
328030391Skarels 
328130391Skarels 	write_ID(adder, LEFT_SCROLL_MASK, 0x0000);
328230391Skarels 	write_ID(adder, RIGHT_SCROLL_MASK, 0x0000);
328334642Smarc 	/*
328434642Smarc 	* set source and the mask register to all ones (ie: white) o
328534642Smarc 	*/
328630391Skarels 	write_ID(adder, SOURCE, 0xFFFF);
328730391Skarels 	write_ID(adder, MASK_1, 0xFFFF);
328830391Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
328930391Skarels 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
329034642Smarc 	/*
329134642Smarc 	* initialize Operand Control Register banks for fill command
329234642Smarc 	*/
329330391Skarels 	write_ID(adder, SRC1_OCR_A, EXT_NONE | INT_M1_M2  | NO_ID | WAIT);
329430391Skarels 	write_ID(adder, SRC2_OCR_A, EXT_NONE | INT_SOURCE | NO_ID | NO_WAIT);
329530391Skarels 	write_ID(adder, DST_OCR_A, EXT_NONE | INT_NONE	 | NO_ID | NO_WAIT);
329630391Skarels 	write_ID(adder, SRC1_OCR_B, EXT_NONE | INT_SOURCE | NO_ID | WAIT);
329730391Skarels 	write_ID(adder, SRC2_OCR_B, EXT_NONE | INT_M1_M2  | NO_ID | NO_WAIT);
329830391Skarels 	write_ID(adder, DST_OCR_B, EXT_NONE | INT_NONE | NO_ID | NO_WAIT);
329934642Smarc 	/*
330034642Smarc 	* init Logic Unit Function registers, (these are just common values,
330134642Smarc 	* and may be changed as required).
330234642Smarc 	*/
330330391Skarels 	write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
330434642Smarc 	write_ID(adder, LU_FUNCTION_R2, FULL_SRC_RESOLUTION | LF_SOURCE |
330534642Smarc 		 INV_M1_M2);
330630391Skarels 	write_ID(adder, LU_FUNCTION_R3, FULL_SRC_RESOLUTION | LF_D_OR_S);
330730391Skarels 	write_ID(adder, LU_FUNCTION_R4, FULL_SRC_RESOLUTION | LF_D_XOR_S);
330834642Smarc 	/*
330934642Smarc 	* load the color map for black & white
331034642Smarc 	*/
3311*34732Smarc 	for (i = 0, adder->status = 0; i < 10000 && !(adder->status&VSYNC); ++i)
331234642Smarc 		;
331330391Skarels 
331430391Skarels 	if (i == 0)
3315*34732Smarc 		printf("qd%d: setup_dragon: timeout on VSYNC\n", unit);
331630391Skarels 
331730391Skarels 	red = (short *) qdmap[unit].red;
331830391Skarels 	green = (short *) qdmap[unit].green;
331930391Skarels 	blue = (short *) qdmap[unit].blue;
332030391Skarels 
332130391Skarels 	*red++ = 0x00;			/* black */
332230391Skarels 	*green++ = 0x00;
332330391Skarels 	*blue++ = 0x00;
332430391Skarels 
332530391Skarels 	*red-- = 0xFF;			/* white */
332630391Skarels 	*green-- = 0xFF;
332730391Skarels 	*blue-- = 0xFF;
332830391Skarels 
332934642Smarc 	/*
3330*34732Smarc 	* set color map for mouse cursor
3331*34732Smarc 	*/
333230391Skarels 
333330391Skarels 	red += 254;
333430391Skarels 	green += 254;
333530391Skarels 	blue += 254;
333630391Skarels 
333730391Skarels 	*red++ = 0x00;			/* black */
333830391Skarels 	*green++ = 0x00;
333930391Skarels 	*blue++ = 0x00;
334030391Skarels 
334130391Skarels 	*red = 0xFF;			/* white */
334230391Skarels 	*green = 0xFF;
334330391Skarels 	*blue = 0xFF;
334430391Skarels 
334530391Skarels } /* setup_dragon */
334630391Skarels 
3347*34732Smarc /*
3348*34732Smarc  * Init the DUART and set defaults in input
3349*34732Smarc  */
335030391Skarels setup_input(unit)
3351*34732Smarc 	int unit;
335230391Skarels {
335330391Skarels 	register struct duart *duart;	/* DUART register structure pointer */
3354*34732Smarc 	register i, bits;
335530391Skarels 	char id_byte;
335630391Skarels 
335730391Skarels 	duart = (struct duart *) qdmap[unit].duart;
335830391Skarels 	duart->imask = 0;
335930391Skarels 
336034642Smarc 	/*
336134642Smarc 	* setup the DUART for kbd & pointing device
336234642Smarc 	*/
3363*34732Smarc 	duart->cmdA = RESET_M;	/* reset mode reg ptr for kbd */
3364*34732Smarc 	duart->modeA = 0x13;	/* 8 bits, no parity, rcv IE, */
3365*34732Smarc 				/* no RTS control,char error mode */
3366*34732Smarc 	duart->modeA = 0x07;	/* 1 stop bit,CTS does not IE XMT */
3367*34732Smarc 				/* no RTS control,no echo or loop */
3368*34732Smarc 	duart->cmdB = RESET_M;	/* reset mode reg pntr for host */
3369*34732Smarc 	duart->modeB = 0x07;	/* 8 bits, odd parity, rcv IE.. */
3370*34732Smarc 				/* ..no RTS cntrl, char error mode */
3371*34732Smarc 	duart->modeB = 0x07;	/* 1 stop bit,CTS does not IE XMT */
3372*34732Smarc 				/* no RTS control,no echo or loop */
3373*34732Smarc 	duart->auxctl = 0x00;	/* baud rate set 1 */
3374*34732Smarc 	duart->clkselA = 0x99;	/* 4800 baud for kbd */
3375*34732Smarc 	duart->clkselB = 0x99;	/* 4800 baud for mouse */
337630391Skarels 
337730391Skarels 	/* reset everything for keyboard */
337830391Skarels 
337930391Skarels 	for (bits = RESET_M; bits < START_BREAK; bits += 0x10)
338034642Smarc 		duart->cmdA = bits;
338130391Skarels 
338230391Skarels 	/* reset everything for host */
338330391Skarels 
338430391Skarels 	for (bits = RESET_M; bits < START_BREAK; bits += 0x10)
338534642Smarc 		duart->cmdB = bits;
338630391Skarels 
338730391Skarels 	duart->cmdA = EN_RCV | EN_XMT; /* enbl xmt & rcv for kbd */
338830391Skarels 	duart->cmdB = EN_RCV | EN_XMT; /* enbl xmt & rcv for pointer device */
338930391Skarels 
339034642Smarc 	/*
3391*34732Smarc 	* init keyboard defaults (DUART channel A)
3392*34732Smarc 	*/
339330391Skarels 	for (i = 500; i > 0; --i) {
3394*34732Smarc 		if (duart->statusA&XMT_RDY) {
339534642Smarc 			duart->dataA = LK_DEFAULTS;
339634642Smarc 			break;
339734642Smarc 		}
339830391Skarels 	}
339930391Skarels 
340030391Skarels 	for (i = 100000; i > 0; --i) {
3401*34732Smarc 		if (duart->statusA&RCV_RDY) {
340234642Smarc 			break;
340334642Smarc 		}
340430391Skarels 	}
340530391Skarels 
3406*34732Smarc 	if (duart->dataA)	/* flush the ACK */
3407*34732Smarc 		;
340830391Skarels 
340934642Smarc 	/*
3410*34732Smarc 	* identify the pointing device
3411*34732Smarc 	*/
341230391Skarels 	for (i = 500; i > 0; --i) {
3413*34732Smarc 		if (duart->statusB&XMT_RDY) {
341434642Smarc 			duart->dataB = SELF_TEST;
341534642Smarc 			break;
341634642Smarc 		}
341730391Skarels 	}
341830391Skarels 
341934642Smarc 	/*
342030391Skarels 	* wait for 1st byte of self test report */
342130391Skarels 
342230391Skarels 	for (i = 100000; i > 0; --i) {
3423*34732Smarc 		if (duart->statusB&RCV_RDY) {
342434642Smarc 			break;
342534642Smarc 		}
342630391Skarels 	}
342730391Skarels 
342830391Skarels 	if (i == 0) {
3429*34732Smarc 		printf("qd[%d]: setup_input: timeout on 1st byte of self test\n"
343034642Smarc 		       ,unit);
343134642Smarc 		goto OUT;
343230391Skarels 	}
343330391Skarels 
3434*34732Smarc 	if (duart->dataB)
3435*34732Smarc 		;
343630391Skarels 
343734642Smarc 	/*
3438*34732Smarc 	* wait for ID byte of self test report
3439*34732Smarc 	*/
344030391Skarels 	for (i = 100000; i > 0; --i) {
3441*34732Smarc 		if (duart->statusB&RCV_RDY) {
344234642Smarc 			break;
344334642Smarc 		}
344430391Skarels 	}
344530391Skarels 
344630391Skarels 	if (i == 0) {
3447*34732Smarc 		printf("qd[%d]: setup_input: timeout on 2nd byte of self test\n", unit);
344834642Smarc 		goto OUT;
344930391Skarels 	}
345030391Skarels 
345130391Skarels 	id_byte = duart->dataB;
345230391Skarels 
345334642Smarc 	/*
3454*34732Smarc 	* wait for other bytes to come in
3455*34732Smarc 	*/
345630391Skarels 	for (i = 100000; i > 0; --i) {
3457*34732Smarc 		if (duart->statusB & RCV_RDY) {
3458*34732Smarc 			if (duart->dataB)
3459*34732Smarc 				;
346034642Smarc 			break;
346134642Smarc 		}
346230391Skarels 	}
346330391Skarels 	if (i == 0) {
3464*34732Smarc 		printf("qd[%d]: setup_input: timeout on 3rd byte of self test\n", unit);
346534642Smarc 		goto OUT;
346630391Skarels 	}
346730391Skarels 	for (i = 100000; i > 0; --i) {
3468*34732Smarc 		if (duart->statusB&RCV_RDY) {
3469*34732Smarc 			if (duart->dataB)
3470*34732Smarc 				;
347134642Smarc 			break;
347234642Smarc 		}
347330391Skarels 	}
347430391Skarels 	if (i == 0) {
3475*34732Smarc 		printf("qd[%d]: setup_input: timeout on 4th byte of self test\n", unit);
347634642Smarc 		goto OUT;
347730391Skarels 	}
347834642Smarc 	/*
3479*34732Smarc 	* flag pointing device type and set defaults
3480*34732Smarc 	*/
3481*34732Smarc 	for (i=100000; i>0; --i)
3482*34732Smarc 		;		/*XXX*/
348330391Skarels 
348430391Skarels 	if ((id_byte & 0x0F) != TABLET_ID) {
348534642Smarc 		qdflags[unit].pntr_id = MOUSE_ID;
348630391Skarels 
348734642Smarc 		for (i = 500; i > 0; --i) {
3488*34732Smarc 			if (duart->statusB&XMT_RDY) {
348934642Smarc 				duart->dataB = INC_STREAM_MODE;
349034642Smarc 				break;
349134642Smarc 			}
349230391Skarels 		}
349334642Smarc 	}
349434642Smarc 	else {
349534642Smarc 		qdflags[unit].pntr_id = TABLET_ID;
349630391Skarels 
349734642Smarc 		for (i = 500; i > 0; --i) {
3498*34732Smarc 			if (duart->statusB&XMT_RDY) {
349934642Smarc 				duart->dataB = T_STREAM;
350034642Smarc 				break;
350134642Smarc 			}
350230391Skarels 		}
350330391Skarels 	}
350430391Skarels OUT:
350530391Skarels 	duart->imask = qdflags[unit].duart_imask;
350630391Skarels 
350730391Skarels } /* setup_input */
350830391Skarels 
3509*34732Smarc /*
3510*34732Smarc  * delay for at least one display frame time
3511*34732Smarc  *
3512*34732Smarc  *	return: BAD means that we timed out without ever seeing the
3513*34732Smarc  *		      vertical sync status bit
3514*34732Smarc  *		GOOD otherwise
3515*34732Smarc  */
351630391Skarels wait_status(adder, mask)
351734642Smarc 	register struct adder *adder;
351834642Smarc 	register int mask;
351930391Skarels {
3520*34732Smarc 	register i;
352130391Skarels 
3522*34732Smarc 	for (i = 10000, adder->status = 0 ; i > 0  &&
3523*34732Smarc 	     !(adder->status&mask) ; --i)
352434642Smarc 		;
352530391Skarels 
352630391Skarels 	if (i == 0) {
3527*34732Smarc 		printf("wait_status: timeout polling for 0x%x in adder->status\n", mask);
352834642Smarc 		return(BAD);
352930391Skarels 	}
353030391Skarels 
353130391Skarels 	return(GOOD);
353230391Skarels 
353330391Skarels } /* wait_status */
353430391Skarels 
3535*34732Smarc /*
3536*34732Smarc  * write out onto the ID bus
3537*34732Smarc  */
353830391Skarels write_ID(adder, adrs, data)
353934642Smarc 	register struct adder *adder;
354034642Smarc 	register short adrs;
354134642Smarc 	register short data;
354230391Skarels {
3543*34732Smarc 	register i;
354430391Skarels 
3545*34732Smarc 	for (i = 100000, adder->status = 0 ;
3546*34732Smarc 	      i > 0  &&  !(adder->status&ADDRESS_COMPLETE) ; --i)
354734642Smarc 		;
354830391Skarels 
354930391Skarels 	if (i == 0)
3550*34732Smarc 		goto ERR;
355130391Skarels 
3552*34732Smarc 	for (i = 100000, adder->status = 0 ;
3553*34732Smarc 	      i > 0  &&  !(adder->status&TX_READY) ; --i)
355434642Smarc 		;
355530391Skarels 
355630391Skarels 	if (i > 0) {
355734642Smarc 		adder->id_data = data;
355834642Smarc 		adder->command = ID_LOAD | adrs;
3559*34732Smarc 		return ;
356030391Skarels 	}
356130391Skarels 
356230391Skarels ERR:
3563*34732Smarc 	printf("write_ID: timeout trying to write to VIPER\n");
3564*34732Smarc 	return ;
356530391Skarels 
356630391Skarels } /* write_ID */
356734511Smarc #endif
3568