xref: /csrg-svn/sys/vax/uba/qd.c (revision 34642)
134511Smarc /*
2*34642Smarc * Copyright (c) 1982, 1986 Regents of the University of California.
3*34642Smarc * All rights reserved.  The Berkeley software License Agreement
4*34642Smarc * specifies the terms and conditions for redistribution.
5*34642Smarc *
6*34642Smarc * 		@(#)qd.c	1.8  Berkeley  06/05/88
7*34642Smarc *
8*34642Smarc */
9*34642Smarc 
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 /*
33*34642Smarc  * qd.c - QDSS display driver for VAXSTATION-II GPX workstation
3430391Skarels  */
3530391Skarels 
36*34642Smarc #include "qd.h"
3734615Smarc 
3834511Smarc #if NQD > 0
3934615Smarc #include "types.h"
40*34642Smarc #include "../machine/pte.h"
41*34642Smarc #include "../machine/mtpr.h"
4234511Smarc #include "../machine/cpu.h"
43*34642Smarc #include "param.h"
44*34642Smarc #include "conf.h"
45*34642Smarc #include "dir.h"
46*34642Smarc #include "user.h"
47*34642Smarc #include "qdioctl.h"
4834511Smarc #include "tty.h"
49*34642Smarc #include "map.h"
50*34642Smarc #include "buf.h"
51*34642Smarc #include "vm.h"
52*34642Smarc #include "bk.h"
53*34642Smarc #include "clist.h"
54*34642Smarc #include "file.h"
55*34642Smarc #include "uio.h"
56*34642Smarc #include "kernel.h"
5734615Smarc #include "exec.h"
5834615Smarc #include "proc.h"
59*34642Smarc #include "ubareg.h"
60*34642Smarc #include "ubavar.h"
6134511Smarc #include "syslog.h"
62*34642Smarc #include "qduser.h"	/* definitions shared with user level client */
6334615Smarc #include "qdreg.h"	/* QDSS device register structures */
6432012Smarc 
65*34642Smarc /*
66*34642Smarc  * QDSS driver status flags for tracking operational state
67*34642Smarc  */
68*34642Smarc struct qdflags {
69*34642Smarc 	u_int inuse;		/* which minor dev's are in use now */
70*34642Smarc 	u_int config;		/* I/O page register content */
71*34642Smarc 	u_int mapped;		/* user mapping status word */
72*34642Smarc 	u_int kernel_loop;	/* if kernel console is redirected */
73*34642Smarc 	u_int user_dma;		/* DMA from user space in progress */
74*34642Smarc 	u_short pntr_id;	/* type code of pointing device */
75*34642Smarc 	u_short duart_imask;	/* shadowing for duart intrpt mask reg */
76*34642Smarc 	u_short adder_ie;	/* shadowing for adder intrpt enbl reg */
77*34642Smarc 	u_short curs_acc;	/* cursor acceleration factor */
78*34642Smarc 	u_short curs_thr;	/* cursor acceleration threshold level */
79*34642Smarc 	u_short tab_res;	/* tablet resolution factor */
80*34642Smarc 	u_short selmask;	/* mask for active qd select entries */
81*34642Smarc };
8232012Smarc 
83*34642Smarc /*
84*34642Smarc  * bit definitions for 'inuse' entry
85*34642Smarc  */
8632012Smarc #define CONS_DEV	0x01
8732012Smarc #define GRAPHIC_DEV	0x04
8832012Smarc 
89*34642Smarc /*
90*34642Smarc  * bit definitions for 'mapped' member of flag structure
91*34642Smarc  */
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 
98*34642Smarc /*
99*34642Smarc  * bit definitions for 'selmask' member of qdflag structure
100*34642Smarc  */
10132012Smarc #define SEL_READ	0x01		/* read select is active */
10232012Smarc #define SEL_WRITE	0x02		/* write select is active */
10332012Smarc 
104*34642Smarc /*
105*34642Smarc * constants used in shared memory operations
106*34642Smarc */
10732012Smarc #define EVENT_BUFSIZE  1024	/* # of bytes per device's event buffer */
10832012Smarc #define MAXEVENTS  ( (EVENT_BUFSIZE - sizeof(struct qdinput))	 \
109*34642Smarc 	/ sizeof(struct _vs_event) )
11034527Smarc #define DMA_BUFSIZ	(1024 * 10)
11132012Smarc #define COLOR_BUFSIZ  ((sizeof(struct color_buf) + 512) & ~0x01FF)
11232012Smarc 
113*34642Smarc /*
11432012Smarc * reference to an array of "uba_device" structures built by the auto
11532012Smarc * configuration program.  The uba_device structure decribes the device
11632012Smarc * sufficiently for the driver to talk to it.  The auto configuration code
11732012Smarc * fills in the uba_device structures (located in ioconf.c) from user
118*34642Smarc * maintained info.
119*34642Smarc */
120*34642Smarc struct uba_device *qdinfo[NQD];  /* array of pntrs to each QDSS's */
121*34642Smarc struct tty qd_tty[NQD*4];	/* teletype structures for each.. */
122*34642Smarc struct qd_softc qd_softc[NQD];
123*34642Smarc extern char qvmem[][128*NBPG];	/* XXX - *NQD - but can't test it */
124*34642Smarc extern struct pte QVmap[][128];
125*34642Smarc #define CHUNK	  (64 * 1024)
126*34642Smarc #define QMEMSIZE  (1024 * 1024 * 4)	/* 4 meg */
12732012Smarc 
128*34642Smarc /*
129*34642Smarc  * static storage used by multiple functions in this code
130*34642Smarc  */
131*34642Smarc int Qbus_unmap[NQD];		/* Qbus mapper release code */
132*34642Smarc struct qdflags qdflags[NQD];	/* QDSS device status flags */
133*34642Smarc struct qdmap qdmap[NQD];	/* QDSS register map structure */
134*34642Smarc caddr_t qdbase[NQD];		/* base address of each QDSS unit */
135*34642Smarc struct buf qdbuf[NQD];		/* buf structs used by strategy */
136*34642Smarc short qdopened[NQD];		/* graphics device is open exclusive use */
13732012Smarc 
138*34642Smarc /*
13934615Smarc * the array "event_shared[]" is made up of a number of event queue buffers
14032012Smarc * equal to the number of QDSS's configured into the running kernel (NQD).
14132012Smarc * Each event queue buffer begins with an event queue header (struct qdinput)
14232012Smarc * followed by a group of event queue entries (struct _vs_event).  The array
14332012Smarc * "*eq_header[]" is an array of pointers to the start of each event queue
144*34642Smarc * buffer in "event_shared[]".
145*34642Smarc */
14632012Smarc #define EQSIZE ((EVENT_BUFSIZE * NQD) + 512)
14732012Smarc 
148*34642Smarc char event_shared[EQSIZE];	    /* reserve space for event bufs */
149*34642Smarc struct qdinput *eq_header[NQD];     /* event queue header pntrs */
15032012Smarc 
151*34642Smarc /*
15232012Smarc * This allocation method reserves enough memory pages for NQD shared DMA I/O
15332012Smarc * buffers.  Each buffer must consume an integral number of memory pages to
15432012Smarc * guarantee that a following buffer will begin on a page boundary.  Also,
15532012Smarc * enough space is allocated so that the FIRST I/O buffer can start at the
15632012Smarc * 1st page boundary after "&DMA_shared".  Page boundaries are used so that
157*34642Smarc * memory protections can be turned on/off for individual buffers.
158*34642Smarc */
15932012Smarc #define IOBUFSIZE  ((DMA_BUFSIZ * NQD) + 512)
16032012Smarc 
161*34642Smarc char DMA_shared[IOBUFSIZE];	    /* reserve I/O buffer space */
162*34642Smarc struct DMAreq_header *DMAheader[NQD];  /* DMA buffer header pntrs */
16332012Smarc 
164*34642Smarc /*
16532012Smarc * The driver assists a client in scroll operations by loading dragon
16632012Smarc * registers from an interrupt service routine.	The loading is done using
16732012Smarc * parameters found in memory shrade between the driver and it's client.
16832012Smarc * The scroll parameter structures are ALL loacted in the same memory page
169*34642Smarc * for reasons of memory economy.
170*34642Smarc */
171*34642Smarc char scroll_shared[2 * 512];	/* reserve space for scroll structs */
172*34642Smarc struct scroll *scroll[NQD];	/* pointers to scroll structures */
17332012Smarc 
174*34642Smarc /*
17532012Smarc * the driver is programmable to provide the user with color map write
17632012Smarc * services at VSYNC interrupt time.  At interrupt time the driver loads
177*34642Smarc * the color map with any user-requested load data found in shared memory
178*34642Smarc */
17932012Smarc #define COLOR_SHARED  ((COLOR_BUFSIZ * NQD) + 512)
18032012Smarc 
181*34642Smarc char color_shared[COLOR_SHARED];      /* reserve space: color bufs */
182*34642Smarc struct color_buf *color_buf[NQD];     /* pointers to color bufs */
18332012Smarc 
184*34642Smarc /*
185*34642Smarc * mouse input event structures
186*34642Smarc */
187*34642Smarc struct mouse_report last_rep[NQD];
188*34642Smarc struct mouse_report current_rep[NQD];
18932012Smarc 
190*34642Smarc struct proc *rsel[NQD]; 	/* process waiting for select */
191*34642Smarc struct _vs_cursor cursor[NQD];	/* console cursor */
192*34642Smarc int qdcount = 0;		/* count of successfully probed qd's */
193*34642Smarc int nNQD = NQD;
194*34642Smarc int DMAbuf_size = DMA_BUFSIZ;
195*34642Smarc int QDlast_DMAtype;             /* type of the last DMA operation */
19632012Smarc 
197*34642Smarc #define QDSSMAJOR	41	/* QDSS major device number */
198*34642Smarc /*
199*34642Smarc * macro to get system time.  Used to time stamp event queue entries
200*34642Smarc */
20130391Skarels #define TOY ((time.tv_sec * 100) + (time.tv_usec / 10000))
20230391Skarels 
203*34642Smarc int qdprobe();
204*34642Smarc int qdattach();
205*34642Smarc int qddint();			/* DMA gate array intrpt service */
206*34642Smarc int qdaint();			/* Dragon ADDER intrpt service */
207*34642Smarc int qdiint();
20830391Skarels 
209*34642Smarc u_short qdstd[] = { 0 };
21030391Skarels 
211*34642Smarc struct uba_driver qddriver = {
212*34642Smarc 	qdprobe,			/* device probe entry */
213*34642Smarc 	0,				/* no slave device */
214*34642Smarc 	qdattach,			/* device attach entry */
215*34642Smarc 	0,				/* no "fill csr/ba to start" */
216*34642Smarc 	qdstd,			/* device addresses */
217*34642Smarc 	"qd",			/* device name string */
218*34642Smarc 	qdinfo			/* ptr to QDSS's uba_device struct */
219*34642Smarc };
22030391Skarels 
22134615Smarc #define QDPRIOR (PZERO-1)		/* must be negative */
22230391Skarels #define FALSE	0
22330391Skarels #define TRUE	~FALSE
22430391Skarels #define BAD	-1
22530391Skarels #define GOOD	0
22630391Skarels 
227*34642Smarc /*
228*34642Smarc  * macro to create a system virtual page number from system virtual adrs
229*34642Smarc  */
230*34642Smarc #define VTOP(x)  (((int)x & ~0xC0000000) >> PGSHIFT)
23130391Skarels 
232*34642Smarc /*
233*34642Smarc  * QDSS register address offsets from start of QDSS address space
234*34642Smarc  */
23530391Skarels #define QDSIZE	 (52 * 1024)	/* size of entire QDSS foot print */
23630391Skarels #define TMPSIZE  (16 * 1024)	/* template RAM is 8k SHORT WORDS */
23730391Skarels #define TMPSTART 0x8000 	/* offset of template RAM from base adrs */
23830391Skarels #define REGSIZE  (5 * 512)	/* regs touch 2.5k (5 pages) of addr space */
23930391Skarels #define REGSTART 0xC000 	/* offset of reg pages from base adrs */
24030391Skarels #define ADDER	(REGSTART+0x000)
24130391Skarels #define DGA	(REGSTART+0x200)
24230391Skarels #define DUART	(REGSTART+0x400)
24330391Skarels #define MEMCSR	(REGSTART+0x800)
24430391Skarels #define CLRSIZE  (3 * 512)		/* color map size */
24530391Skarels #define CLRSTART (REGSTART+0xA00)	/* color map start offset from base */
246*34642Smarc /*  0x0C00 really */
24730391Skarels #define RED	(CLRSTART+0x000)
24830391Skarels #define BLUE	(CLRSTART+0x200)
24930391Skarels #define GREEN	(CLRSTART+0x400)
25030391Skarels 
25130391Skarels 
252*34642Smarc /*
253*34642Smarc  * QDSS minor device numbers.  The *real* minor device numbers are in
254*34642Smarc  * the bottom two bits of the major/minor device spec.  Bits 2 and up are
255*34642Smarc  * used to specify the QDSS device number (ie: which one?)
256*34642Smarc  */
25730391Skarels 
25830391Skarels #define CONS		0
25930391Skarels #define GRAPHIC 	2
26030391Skarels 
261*34642Smarc /*
262*34642Smarc  * console cursor bitmap (white block cursor)
263*34642Smarc  */
264*34642Smarc short cons_cursor[32] = {
265*34642Smarc 	/* A */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
266*34642Smarc 	0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
267*34642Smarc 	/* B */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
268*34642Smarc 	0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF
269*34642Smarc };
27030391Skarels 
271*34642Smarc /*
272*34642Smarc  * constants used in font operations
273*34642Smarc  */
27434615Smarc #define CHARS		190 			/* # of chars in the font */
27530391Skarels #define CHAR_HEIGHT	15			/* char height in pixels */
27630391Skarels #define CHAR_WIDTH	8			/* char width in pixels*/
27730391Skarels #define FONT_WIDTH	(CHAR_WIDTH * CHARS)	/* font width in pixels */
27830391Skarels #define ROWS		CHAR_HEIGHT
27930391Skarels #define FONT_X		0			/* font's off screen adrs */
28030391Skarels #define FONT_Y		(2048 - CHAR_HEIGHT)
28130391Skarels 
282*34642Smarc /* Offset to second row characters (XXX - should remove) */
28334615Smarc #define FONT_OFFSET	((MAX_SCREEN_X/CHAR_WIDTH)*CHAR_HEIGHT)
28430391Skarels 
285*34642Smarc extern char q_font[];		/* reference font object code */
286*34642Smarc extern	u_short q_key[];	/* reference key xlation tables */
287*34642Smarc extern	u_short q_shift_key[];
288*34642Smarc extern	char *q_special[];
28930391Skarels 
290*34642Smarc /*
291*34642Smarc  * definitions for cursor acceleration reporting
292*34642Smarc  */
29330391Skarels #define ACC_OFF 	0x01		/* acceleration is inactive */
29430391Skarels 
295*34642Smarc /*
296*34642Smarc  * virtual console support.
297*34642Smarc  */
298*34642Smarc extern (*v_putc)();
299*34642Smarc extern struct cdevsw *consops;
300*34642Smarc int qdputc();
301*34642Smarc int qdstart();
30230391Skarels 
303*34642Smarc /*
304*34642Smarc  * LK-201 state storage for input console keyboard conversion to ASCII
305*34642Smarc  */
306*34642Smarc struct q_keyboard {
307*34642Smarc 	int shift;			/* state variables	*/
308*34642Smarc 	int cntrl;
309*34642Smarc 	int lock;
310*34642Smarc 	int lastcode;			/* last keycode typed	*/
311*34642Smarc 	unsigned kup[8];		/* bits for each keycode*/
312*34642Smarc 	unsigned dkeys[8];		/* down/up mode keys	*/
313*34642Smarc 	char last;			/* last character	*/
314*34642Smarc } q_keyboard;
31530391Skarels 
316*34642Smarc /*
317*34642Smarc  * tty settings on first open
318*34642Smarc  */
31934615Smarc #define IFLAGS	(EVENP|ECHO|XTABS|CRMOD)
32034615Smarc #ifdef POSIXTTY
32134615Smarc #define IFLAG (BRKINT|ISTRIP|IXON|IXANY|ICRNL|IEXTEN|IMAXBEL)
32234615Smarc #define OFLAG (OPOST|OXTABS|ONLCR)
32334615Smarc #define LFLAG (ISIG|ICANON|ECHO)
32434615Smarc #define CFLAG (PARENB|CREAD|CS7|CLOCAL)
32534615Smarc #endif
32634615Smarc 
32730391Skarels /*********************************************************************
32830391Skarels *
32934615Smarc *	qdcons_init()... init QDSS as console (before probe routine)
33030391Skarels *
33130391Skarels *********************************************************************/
33230391Skarels 
33330391Skarels qdcons_init()
33430391Skarels {
33530391Skarels 	register u_int unit;
33630391Skarels 	int *ptep;			/* page table entry pointer */
33730391Skarels 	caddr_t phys_adr;		/* physical QDSS base adrs */
33834615Smarc 	u_int mapix;			/* index into QVmap[] array */
33934615Smarc 	struct percpu *pcpu;		/* pointer to cpusw structure  */
34034615Smarc 	register struct qbus *qb;
34130391Skarels 	u_short *qdaddr;		/* address of QDSS IO page CSR */
34230391Skarels 	u_short *devptr;		/* vitual device space */
34334615Smarc 	extern cnputc();
34430391Skarels 
34530391Skarels #define QDSSCSR 0x1F00
34630391Skarels 
34732012Smarc 	if (v_putc != cnputc)
348*34642Smarc 	    return;
34932012Smarc 
35030391Skarels 	unit = 0;
35130391Skarels 
352*34642Smarc 	/*
353*34642Smarc 	 * find the cpusw entry that matches this machine.
354*34642Smarc 	 */
35532012Smarc 	for (pcpu = percpu; pcpu && pcpu->pc_cputype != cpu; pcpu++)
35632012Smarc 		;
35732012Smarc 	if (pcpu == NULL)
358*34642Smarc 	    return;
35930391Skarels 
36032012Smarc 	/*
36134615Smarc 	 * Map device registers - the last 8K of qvmem.
36232012Smarc 	 */
36332012Smarc 	qb = (struct qbus *)pcpu->pc_io->io_details;
36432012Smarc 	ioaccess(qb->qb_iopage, UMEMmap[0] + qb->qb_memsize,
365*34642Smarc 	UBAIOPAGES * NBPG);
36632012Smarc 	devptr = (u_short *)((char *)umem[0]+(qb->qb_memsize * NBPG));
36730391Skarels 	qdaddr = (u_short *)((u_int)devptr + ubdevreg(QDSSCSR));
36832012Smarc 	if (badaddr(qdaddr, sizeof(short)))  {
36934615Smarc 		printf("Can't find qdss (badaddr)\n"); /* debug */
37030391Skarels 		return(0);
37132012Smarc 	}
37234615Smarc 
37332012Smarc 	/*
37432012Smarc 	 * Map q-bus memory used by qdss. (separate map)
37532012Smarc 	 */
37632012Smarc 	mapix = QMEMSIZE - (CHUNK * (unit + 1));
37732012Smarc 	phys_adr = qb->qb_maddr + mapix;
37832012Smarc 	ioaccess(phys_adr, QVmap[0], (CHUNK*NQD));
37930391Skarels 
38032012Smarc 	/*
38132012Smarc 	 * tell QDSS which Q memory address base to decode
382*34642Smarc 	 * (shifted right 16 bits - its in 64K units)
38332012Smarc 	 */
38432012Smarc 	*qdaddr = (u_short)((int)mapix >> 16);
38530391Skarels 	qdflags[unit].config = *(u_short *)qdaddr;
38630391Skarels 
387*34642Smarc 	/*
388*34642Smarc 	 * load qdmap struct with the virtual addresses of the QDSS elements
389*34642Smarc 	 */
39034615Smarc 	qdbase[unit] = (caddr_t) (qvmem[0]);
39130391Skarels 	qdmap[unit].template = qdbase[unit] + TMPSTART;
39230391Skarels 	qdmap[unit].adder = qdbase[unit] + ADDER;
39330391Skarels 	qdmap[unit].dga = qdbase[unit] + DGA;
39430391Skarels 	qdmap[unit].duart = qdbase[unit] + DUART;
39530391Skarels 	qdmap[unit].memcsr = qdbase[unit] + MEMCSR;
39630391Skarels 	qdmap[unit].red = qdbase[unit] + RED;
39730391Skarels 	qdmap[unit].blue = qdbase[unit] + BLUE;
39830391Skarels 	qdmap[unit].green = qdbase[unit] + GREEN;
39930391Skarels 
40030391Skarels 	qdflags[unit].duart_imask = 0;	/* init shadow variables */
40130391Skarels 
402*34642Smarc 	/*
403*34642Smarc 	 * init the QDSS
404*34642Smarc 	 */
405*34642Smarc 	/*
40632012Smarc 	printf("qdbase[0] = %x, qdmap[0].memcsr = %x\n",
407*34642Smarc 		(char *)qdbase[0], qdmap[0].memcsr);
408*34642Smarc 	*/
40932012Smarc 
41030391Skarels 	*(short *)qdmap[unit].memcsr |= SYNC_ON; /* once only: turn on sync */
41130391Skarels 
41230391Skarels 	cursor[unit].x = 0;
41330391Skarels 	cursor[unit].y = 0;
41430391Skarels 	init_shared(unit);		/* init shared memory */
41530391Skarels 	setup_dragon(unit);		/* init the ADDER/VIPER stuff */
41630391Skarels 	clear_qd_screen(unit);		/* clear the screen */
41730391Skarels 	ldfont(unit);			/* load the console font */
41830391Skarels 	ldcursor(unit, cons_cursor);	/* load default cursor map */
41930391Skarels 	setup_input(unit);		/* init the DUART */
420*34642Smarc 	v_putc = qdputc;		/* kernel console output to qdss */
421*34642Smarc 	consops = &cdevsw[QDSSMAJOR];	/* virtual console is qdss */
42230391Skarels 	return(1);
42330391Skarels 
42430391Skarels } /* qdcons_init */
42530391Skarels 
42630391Skarels /*********************************************************************
42730391Skarels *
42830391Skarels *	qdprobe()... configure QDSS into Q memory and make it intrpt
42930391Skarels *
43030391Skarels **********************************************************************
43130391Skarels *
43230391Skarels *  calling convention:
43330391Skarels *			qdprobe(reg, ctlr);
43430391Skarels *			caddr_t reg;
43530391Skarels *			int ctlr;
43630391Skarels *
43730391Skarels *	where: reg - a character pointer to the QDSS I/O page register
43830391Skarels *	       ctlr - controller number (?)
43930391Skarels *
44030391Skarels *  side effects: QDSS gets mapped into Qbus memory space at the first
44130391Skarels *		 vacant 64kb boundary counting back from the top of
44234615Smarc *		 Qbus memory space (qvmem+4mb)
44330391Skarels *
44430391Skarels *  return: QDSS bus request level and vector address returned in
44530391Skarels *	   registers by UNIX convention.
44630391Skarels *
44730391Skarels *****************/
44830391Skarels 
44930391Skarels qdprobe(reg)
450*34642Smarc 	caddr_t reg;
45130391Skarels {
452*34642Smarc 	register int br, cvec;  	/* value-result */
45330391Skarels 	register int unit;
45430391Skarels 	struct dga *dga;		/* pointer to gate array structure */
45530391Skarels 	struct cpusw *cpup;		/* pointer to the cpusw structure */
45630391Skarels 	int *ptep;			/* page table entry pointer */
45730391Skarels 	int vector;
45830391Skarels 	caddr_t phys_adr;		/* physical QDSS base adrs */
45930391Skarels 	u_int mapix;
46030391Skarels 
461*34642Smarc 	/*
462*34642Smarc 	 * calculate board unit number from I/O page register address
463*34642Smarc 	 */
46430391Skarels 	unit = (int) (((int)reg >> 1) & 0x0007);
46530391Skarels 
466*34642Smarc 	/*
467*34642Smarc 	 * QDSS regs must be mapped to Qbus memory space at a 64kb
468*34642Smarc  	 * physical boundary.  The Qbus memory space is mapped into
469*34642Smarc 	 * the system memory space at config time.  After config
470*34642Smarc 	 * runs, "qvmem[0]" (ubavar.h) holds the system virtual adrs
471*34642Smarc 	 * of the start of Qbus memory.   The Qbus memory page table
472*34642Smarc 	 * is found via an array of pte ptrs called "QVmap[]" (ubavar.h)
473*34642Smarc 	 * which is also loaded at config time.   These are the
474*34642Smarc 	 * variables used below to find a vacant 64kb boundary in
475*34642Smarc 	 * Qbus memory, and load it's corresponding physical adrs
476*34642Smarc 	 * into the QDSS's I/O page CSR.
477*34642Smarc 	 */
47830391Skarels 
47934615Smarc 	/*
48034615Smarc 	 * Only if QD is the graphics device.
48134615Smarc 	 */
48234615Smarc 
48330391Skarels 	/* if this QDSS is NOT the console, then do init here.. */
48430391Skarels 
48534615Smarc 	if (unit != 0) {
48634615Smarc 		printf("qd: can't support two qdss's (yet)\n");
487*34642Smarc #ifdef notdef	/* notyet - don't have two qd's so i can't test it */
488*34642Smarc 		if (v_consputc != qdputc  ||  unit != 0) {
48930391Skarels 
490*34642Smarc 			/*
491*34642Smarc 			* read QDSS config info
492*34642Smarc 			*/
493*34642Smarc 			qdflags[unit].config = *(u_short *)reg;
49434615Smarc 
495*34642Smarc 			/*
496*34642Smarc 			* find an empty 64kb adrs boundary
497*34642Smarc 			*/
49830391Skarels 
499*34642Smarc 			qdbase[unit] = (caddr_t) (qvmem[0] + QMEMSIZE - CHUNK);
50030391Skarels 
501*34642Smarc 			/*
502*34642Smarc 			* find the cpusw entry that matches this machine. */
50334615Smarc 
504*34642Smarc 			cpup = &cpusw[cpu];
505*34642Smarc 			while ( !(BADADDR(qdbase[unit], sizeof(short))) )
506*34642Smarc 			    qdbase[unit] -= CHUNK;
50734615Smarc 
508*34642Smarc 			/*
509*34642Smarc 			* tell QDSS which Q memory address base to decode */
51030391Skarels 
511*34642Smarc 			mapix = (int) (VTOP(qdbase[unit]) - VTOP(qvmem[0]));
512*34642Smarc 			ptep = (int *) QVmap[0] + mapix;
513*34642Smarc 			phys_adr = (caddr_t)(((int)*ptep&0x001FFFFF)<<PGSHIFT);
514*34642Smarc 			*(u_short *)reg = (u_short) ((int)phys_adr >> 16);
51534615Smarc 
516*34642Smarc 			/*
517*34642Smarc 			* load QDSS adrs map with system addresses
518*34642Smarc 			* of device regs
519*34642Smarc 			*/
520*34642Smarc 			qdmap[unit].template = qdbase[unit] + TMPSTART;
521*34642Smarc 			qdmap[unit].adder = qdbase[unit] + ADDER;
522*34642Smarc 			qdmap[unit].dga = qdbase[unit] + DGA;
523*34642Smarc 			qdmap[unit].duart = qdbase[unit] + DUART;
524*34642Smarc 			qdmap[unit].memcsr = qdbase[unit] + MEMCSR;
525*34642Smarc 			qdmap[unit].red = qdbase[unit] + RED;
526*34642Smarc 			qdmap[unit].blue = qdbase[unit] + BLUE;
527*34642Smarc 			qdmap[unit].green = qdbase[unit] + GREEN;
52830391Skarels 
529*34642Smarc 			/* device init */
53034615Smarc 
531*34642Smarc 			cursor[unit].x = 0;
532*34642Smarc 			cursor[unit].y = 0;
533*34642Smarc 			init_shared(unit);		/* init shared memory */
534*34642Smarc 			setup_dragon(unit); 	/* init the ADDER/VIPER stuff */
535*34642Smarc 			ldcursor(unit, cons_cursor);	/* load default cursor map */
536*34642Smarc 			setup_input(unit);		/* init the DUART */
537*34642Smarc 			clear_qd_screen(unit);
538*34642Smarc 			ldfont(unit);			/* load the console font */
53930391Skarels 
540*34642Smarc 			/* once only: turn on sync */
54130391Skarels 
542*34642Smarc 			*(short *)qdmap[unit].memcsr |= SYNC_ON;
543*34642Smarc 		}
54434615Smarc #endif /*notdef*/
54530391Skarels 	}
54630391Skarels 
547*34642Smarc 	/*
548*34642Smarc 	* The QDSS interrupts at HEX vectors xx0 (DMA) xx4
549*34642Smarc 	* (ADDER) and xx8 (DUART).  Therefore, we take three
550*34642Smarc 	* vectors from the vector pool, and then continue
551*34642Smarc 	* to take them until we get a xx0 HEX vector.  The
552*34642Smarc 	* pool provides vectors in contiguous decending
553*34642Smarc 	* order.
554*34642Smarc 	*/
55530391Skarels 
55630391Skarels 	vector = (uba_hd[0].uh_lastiv -= 4*3);	/* take three vectors */
55730391Skarels 
558*34642Smarc 	while (vector & 0x0F) {		   /* if lo nibble != 0.. */
559*34642Smarc 		/* ..take another vector */
560*34642Smarc 		vector = (uba_hd[0].uh_lastiv -= 4);
56130391Skarels 	}
56230391Skarels 
563*34642Smarc 	/*
564*34642Smarc 	* setup DGA to do a DMA interrupt (transfer count = 0)
565*34642Smarc 	*/
56630391Skarels 	dga = (struct dga *) qdmap[unit].dga;
567*34642Smarc 	dga->csr = (short) HALT;	/* disable everything */
568*34642Smarc 	dga->ivr = (short) vector;	/* load intrpt base vector */
569*34642Smarc 	dga->bytcnt_lo = (short) 0;	/* DMA xfer count = 0 */
57030391Skarels 	dga->bytcnt_hi = (short) 0;
57130391Skarels 
572*34642Smarc 	/*
573*34642Smarc 	* turn on DMA interrupts
574*34642Smarc 	*/
57530391Skarels 	dga->csr &= ~SET_DONE_FIFO;
57630391Skarels 	dga->csr |= DMA_IE | DL_ENB;
57730391Skarels 
57830391Skarels 	DELAY(20000);			/* wait for the intrpt */
57930391Skarels 	dga->csr = HALT;		/* stop the wheels */
58030391Skarels 
58130391Skarels 	if (cvec != vector)		/* if vector != base vector.. */
58230391Skarels 	    return(0);			/* ..return = 'no device' */
58330391Skarels 
58434615Smarc 	/*
585*34642Smarc 	* score this as an existing qdss
586*34642Smarc 	*/
58734615Smarc 	qdcount++;
58834615Smarc 
58930391Skarels 	return(sizeof(short));	    /* return size of QDSS I/O page reg */
59030391Skarels 
59130391Skarels } /* qdprobe */
59230391Skarels 
59330391Skarels /*****************************************************************
59430391Skarels *
59534615Smarc *	qdattach()... do the one-time initialization
59630391Skarels *
59730391Skarels ******************************************************************
59830391Skarels *
59930391Skarels *  calling convention:
60030391Skarels *			qdattach(ui);
60130391Skarels *			struct uba_device *ui;
60230391Skarels *
60330391Skarels *		where: ui - pointer to the QDSS's uba_device structure
60430391Skarels *
60530391Skarels *  side effects: none
60630391Skarels *	 return: none
60730391Skarels *
60830391Skarels *************************/
60930391Skarels 
61030391Skarels qdattach(ui)
611*34642Smarc 	struct uba_device *ui;
61230391Skarels {
61330391Skarels 	register u_int unit;		/* QDSS module # for this call */
61430391Skarels 
61530391Skarels 	unit = ui->ui_unit;		/* get QDSS number */
61630391Skarels 
617*34642Smarc 	/*
618*34642Smarc 	* init "qdflags[]" for this QDSS
619*34642Smarc 	*/
62030391Skarels 	qdflags[unit].inuse = 0;	/* init inuse variable EARLY! */
62130391Skarels 	qdflags[unit].mapped = 0;
62234615Smarc 	qdflags[unit].kernel_loop = -1;
62330391Skarels 	qdflags[unit].user_dma = 0;
62430391Skarels 	qdflags[unit].curs_acc = ACC_OFF;
62530391Skarels 	qdflags[unit].curs_thr = 128;
62630391Skarels 	qdflags[unit].tab_res = 2;	/* default tablet resolution factor */
62730391Skarels 	qdflags[unit].duart_imask = 0;	/* init shadow variables */
62830391Skarels 	qdflags[unit].adder_ie = 0;
62930391Skarels 
630*34642Smarc 	/*
631*34642Smarc 	* init structures used in kbd/mouse interrupt service.	This code must
632*34642Smarc 	* come after the "init_shared()" routine has run since that routine
633*34642Smarc 	* inits the eq_header[unit] structure used here.
634*34642Smarc 	*/
63530391Skarels 
636*34642Smarc 	/*
637*34642Smarc 	* init the "latest mouse report" structure
638*34642Smarc 	*/
63930391Skarels 	last_rep[unit].state = 0;
64030391Skarels 	last_rep[unit].dx = 0;
64130391Skarels 	last_rep[unit].dy = 0;
64230391Skarels 	last_rep[unit].bytcnt = 0;
64330391Skarels 
644*34642Smarc 	/*
64534615Smarc 	* init the event queue (except mouse position) */
64630391Skarels 
64730391Skarels 	eq_header[unit]->header.events = (struct _vs_event *)
648*34642Smarc 	    ((int)eq_header[unit]
649*34642Smarc 	    + sizeof(struct qdinput));
65030391Skarels 
65130391Skarels 	eq_header[unit]->header.size = MAXEVENTS;
65230391Skarels 	eq_header[unit]->header.head = 0;
65330391Skarels 	eq_header[unit]->header.tail = 0;
65430391Skarels 
655*34642Smarc 	/*
656*34642Smarc 	 * open exclusive for graphics device.
657*34642Smarc 	 */
658*34642Smarc 	qdopened[unit] = 0;
65930391Skarels 
66030391Skarels } /* qdattach */
66130391Skarels 
66230391Skarels /***************************************************************
66330391Skarels *
66434615Smarc *	qdopen()... open a minor device
66530391Skarels *
66630391Skarels ****************************************************************
66730391Skarels *
66830391Skarels *  calling convention: qdopen(dev, flag);
66930391Skarels *		       dev_t dev;
67030391Skarels *		       int flag;
67130391Skarels *
67230391Skarels *  side effects: none
67330391Skarels *
67430391Skarels *********************/
67530391Skarels 
67630391Skarels qdopen(dev, flag)
677*34642Smarc 	dev_t dev;
678*34642Smarc 	int flag;
67930391Skarels {
68030391Skarels 	register struct uba_device *ui; /* ptr to uba structures */
68130391Skarels 	register struct dga *dga;	/* ptr to gate array struct */
68230391Skarels 	register struct tty *tp;
68330391Skarels 	struct adder *adder;
68430391Skarels 	struct duart *duart;
68530391Skarels 	u_int unit;
68630391Skarels 	u_int minor_dev;
68730391Skarels 	int s;
68830391Skarels 
68930391Skarels 	minor_dev = minor(dev); /* get QDSS minor device number */
69030391Skarels 	unit = minor_dev >> 2;
69130391Skarels 
692*34642Smarc 	/*
693*34642Smarc 	* check for illegal conditions
694*34642Smarc 	*/
69530391Skarels 	ui = qdinfo[unit];		/* get ptr to QDSS device struct */
69630391Skarels 	if (ui == 0  || ui->ui_alive == 0)
697*34642Smarc 		return(ENXIO);		/* no such device or address */
69830391Skarels 
69930391Skarels 	adder = (struct adder *) qdmap[unit].adder;
70030391Skarels 	duart = (struct duart *) qdmap[unit].duart;
70130391Skarels 	dga = (struct dga *) qdmap[unit].dga;
70230391Skarels 
70330391Skarels 	if ((minor_dev & 0x03) == 2) {
704*34642Smarc 		/*
705*34642Smarc 		* this is the graphic device...
706*34642Smarc 		*/
707*34642Smarc 		if (qdopened[unit] != 0)
708*34642Smarc 		    return(EBUSY);
709*34642Smarc 		else
710*34642Smarc 			qdopened[unit] = 1;
711*34642Smarc 		qdflags[unit].inuse |= GRAPHIC_DEV;  /* graphics dev is open */
712*34642Smarc 		/*
713*34642Smarc 		 * enble kbd & mouse intrpts in DUART mask reg
714*34642Smarc 		 */
715*34642Smarc 		qdflags[unit].duart_imask |= 0x22;
716*34642Smarc 		duart->imask = qdflags[unit].duart_imask;
717*34642Smarc 	} else {
718*34642Smarc 		/*
719*34642Smarc 		* this is the console
720*34642Smarc 		*/
721*34642Smarc 		qdflags[unit].inuse |= CONS_DEV;  /* mark console as open */
722*34642Smarc 		dga->csr |= CURS_ENB;
723*34642Smarc 		qdflags[unit].duart_imask |= 0x02;
724*34642Smarc 		duart->imask = qdflags[unit].duart_imask;
725*34642Smarc 		/*
726*34642Smarc 		* some setup for tty handling
727*34642Smarc 		*/
728*34642Smarc 		tp = &qd_tty[minor_dev];
729*34642Smarc 		tp->t_addr = ui->ui_addr;
730*34642Smarc 		tp->t_oproc = qdstart;
731*34642Smarc 		if ((tp->t_state & TS_ISOPEN) == 0) {
732*34642Smarc 			ttychars(tp);
733*34642Smarc 			tp->t_flags = IFLAGS;
734*34642Smarc 			tp->t_ispeed = B9600;
735*34642Smarc 			tp->t_ospeed = B9600;
736*34642Smarc 			tp->t_state = TS_ISOPEN | TS_CARR_ON;
737*34642Smarc #ifdef POSIXTTY
738*34642Smarc 			tp->t_iflag = TTYDEF_IFLAG;
739*34642Smarc 			tp->t_oflag = TTYDEF_OFLAG;
740*34642Smarc 			tp->t_lflag = TTYDEF_LFLAG;
741*34642Smarc 			tp->t_cflag = TTYDEF_CFLAG;
742*34642Smarc #endif
74332012Smarc 		}
744*34642Smarc 		/*
745*34642Smarc 		* enable intrpts, open line discipline
746*34642Smarc 		*/
747*34642Smarc 		dga->csr |= GLOBAL_IE;	/* turn on the interrupts */
748*34642Smarc 		return ((*linesw[tp->t_line].l_open)(dev, tp));
74930391Skarels 	}
75030391Skarels 	dga->csr |= GLOBAL_IE;	/* turn on the interrupts */
75130391Skarels 	return(0);
75230391Skarels 
75330391Skarels } /* qdopen */
75430391Skarels 
75530391Skarels /***************************************************************
75630391Skarels *
75734615Smarc *	qdclose()... clean up on the way out
75830391Skarels *
75930391Skarels ****************************************************************
76030391Skarels *
76130391Skarels *  calling convention: qdclose();
76230391Skarels *
76330391Skarels *  side effects: none
76430391Skarels *
76530391Skarels *  return: none
76630391Skarels *
76730391Skarels *********************/
76830391Skarels 
76930391Skarels qdclose(dev, flag)
770*34642Smarc 	dev_t dev;
771*34642Smarc 	int flag;
77230391Skarels {
77330391Skarels 	register struct tty *tp;
77430391Skarels 	register struct qdmap *qd;
77530391Skarels 	register int *ptep;
77630391Skarels 	struct dga *dga;		/* gate array register map pointer */
77730391Skarels 	struct duart *duart;
77830391Skarels 	struct adder *adder;
77930391Skarels 	u_int unit;
78030391Skarels 	u_int minor_dev;
78130391Skarels 	u_int mapix;
782*34642Smarc 	int i;				/* SIGNED index */
78330391Skarels 
78430391Skarels 	minor_dev = minor(dev); 	/* get minor device number */
78530391Skarels 	unit = minor_dev >> 2;		/* get QDSS number */
78630391Skarels 	qd = &qdmap[unit];
78730391Skarels 
78830391Skarels 	if ((minor_dev & 0x03) == 2) {
789*34642Smarc 		/*
790*34642Smarc 		* this is the graphic device...
791*34642Smarc 		*/
792*34642Smarc 		if (qdopened[unit] != 1)
793*34642Smarc 		    return(EBUSY);
794*34642Smarc 		else
795*34642Smarc 			qdopened[unit] = 0;	/* allow it to be re-opened */
796*34642Smarc 		/*
797*34642Smarc 		* re-protect device memory
798*34642Smarc 		*/
799*34642Smarc 		if (qdflags[unit].mapped & MAPDEV) {
800*34642Smarc 			/*
801*34642Smarc 			* TEMPLATE RAM
802*34642Smarc 			*/
803*34642Smarc 			mapix = VTOP((int)qd->template) - VTOP(qvmem[0]);
804*34642Smarc 			ptep = (int *)(QVmap[0] + mapix);
805*34642Smarc 			for (i = VTOP(TMPSIZE); i > 0; --i)
806*34642Smarc 				*ptep++ = (*ptep & ~PG_PROT) | PG_V | PG_KW;
807*34642Smarc 			/*
808*34642Smarc 			* ADDER
809*34642Smarc 			*/
810*34642Smarc 			mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]);
811*34642Smarc 			ptep = (int *)(QVmap[0] + mapix);
812*34642Smarc 			for (i = VTOP(REGSIZE); i > 0; --i)
813*34642Smarc 				*ptep++ = (*ptep & ~PG_PROT) | PG_V | PG_KW;
814*34642Smarc 			/*
815*34642Smarc 			* COLOR MAPS
816*34642Smarc 			*/
817*34642Smarc 			mapix = VTOP((int)qd->red) - VTOP(qvmem[0]);
818*34642Smarc 			ptep = (int *)(QVmap[0] + mapix);
819*34642Smarc 			for (i = VTOP(CLRSIZE); i > 0; --i)
820*34642Smarc 				*ptep++ = (*ptep & ~PG_PROT) | PG_V | PG_KW;
821*34642Smarc 		}
82234615Smarc 
823*34642Smarc 		/*
824*34642Smarc 		* re-protect DMA buffer and free the map registers
825*34642Smarc 		*/
826*34642Smarc 		if (qdflags[unit].mapped & MAPDMA) {
827*34642Smarc 			dga = (struct dga *) qdmap[unit].dga;
828*34642Smarc 			adder = (struct adder *) qdmap[unit].adder;
829*34642Smarc 			dga->csr &= ~DMA_IE;
830*34642Smarc 			dga->csr &= ~0x0600;	     /* kill DMA */
831*34642Smarc 			adder->command = CANCEL;
832*34642Smarc 			/*
833*34642Smarc 			 * if DMA was running, flush spurious intrpt
834*34642Smarc 			 */
835*34642Smarc 			if (dga->bytcnt_lo != 0) {
836*34642Smarc 				dga->bytcnt_lo = 0;
837*34642Smarc 				dga->bytcnt_hi = 0;
838*34642Smarc 				DMA_SETIGNORE(DMAheader[unit]);
839*34642Smarc 				dga->csr |= DMA_IE;
840*34642Smarc 				dga->csr &= ~DMA_IE;
841*34642Smarc 			}
842*34642Smarc 			ptep = (int *)
843*34642Smarc 			   ((VTOP(DMAheader[unit]*4)) + (mfpr(SBR)|0x80000000));
844*34642Smarc 			for (i = (DMAbuf_size >> PGSHIFT); i > 0; --i)
845*34642Smarc 				*ptep++ = (*ptep & ~PG_PROT) | PG_V | PG_KW;
846*34642Smarc 			ubarelse(0, &Qbus_unmap[unit]);
847*34642Smarc 		}
84834615Smarc 
849*34642Smarc 		/*
850*34642Smarc 		* re-protect 1K (2 pages) event queue
851*34642Smarc 		*/
852*34642Smarc 		if (qdflags[unit].mapped & MAPEQ) {
853*34642Smarc 			ptep = (int *)
854*34642Smarc 			   ((VTOP(eq_header[unit])*4) + (mfpr(SBR)|0x80000000));
85530391Skarels 
856*34642Smarc 			*ptep++ = (*ptep & ~PG_PROT) | PG_KW | PG_V;
857*34642Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
85830391Skarels 		}
859*34642Smarc 		/*
860*34642Smarc 		* re-protect scroll param area and disable scroll intrpts
861*34642Smarc 		*/
862*34642Smarc 		if (qdflags[unit].mapped & MAPSCR) {
863*34642Smarc 			ptep = (int *) ((VTOP(scroll[unit]) * 4)
864*34642Smarc 				+ (mfpr(SBR) | 0x80000000));
865*34642Smarc 			/*
866*34642Smarc 			 * re-protect 512 scroll param area
867*34642Smarc 			 */
868*34642Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
869*34642Smarc 			adder = (struct adder *) qdmap[unit].adder;
870*34642Smarc 			qdflags[unit].adder_ie &= ~FRAME_SYNC;
871*34642Smarc 			adder->interrupt_enable = qdflags[unit].adder_ie;
872*34642Smarc 		}
873*34642Smarc 		/*
874*34642Smarc 		* re-protect color map write buffer area and kill intrpts
875*34642Smarc 		*/
876*34642Smarc 		if (qdflags[unit].mapped & MAPCOLOR) {
877*34642Smarc 			ptep = (int *) ((VTOP(color_buf[unit]) * 4)
878*34642Smarc 				+ (mfpr(SBR) | 0x80000000));
879*34642Smarc 			*ptep++ = (*ptep & ~PG_PROT) | PG_KW | PG_V;
880*34642Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
881*34642Smarc 			color_buf[unit]->status = 0;
882*34642Smarc 			adder = (struct adder *) qdmap[unit].adder;
883*34642Smarc 			qdflags[unit].adder_ie &= ~VSYNC;
884*34642Smarc 			adder->interrupt_enable = qdflags[unit].adder_ie;
885*34642Smarc 		}
886*34642Smarc 		mtpr(TBIA, 0);
887*34642Smarc 		/* flag everything now unmapped */
888*34642Smarc 		qdflags[unit].mapped = 0;
889*34642Smarc 		qdflags[unit].inuse &= ~GRAPHIC_DEV;
890*34642Smarc 		qdflags[unit].curs_acc = ACC_OFF;
891*34642Smarc 		qdflags[unit].curs_thr = 128;
892*34642Smarc 		/*
893*34642Smarc 		* restore the console
894*34642Smarc 		*/
89530391Skarels 		dga = (struct dga *) qdmap[unit].dga;
89630391Skarels 		adder = (struct adder *) qdmap[unit].adder;
89730391Skarels 		dga->csr &= ~DMA_IE;
89830391Skarels 		dga->csr &= ~0x0600;	/* halt the DMA! (just in case...) */
89930391Skarels 		dga->csr |= DMA_ERR;	/* clear error condition */
90030391Skarels 		adder->command = CANCEL;
901*34642Smarc 		/*
902*34642Smarc 		 * if DMA was running, flush spurious intrpt
903*34642Smarc 		 */
90430391Skarels 		if (dga->bytcnt_lo != 0) {
905*34642Smarc 			dga->bytcnt_lo = 0;
906*34642Smarc 			dga->bytcnt_hi = 0;
907*34642Smarc 			DMA_SETIGNORE(DMAheader[unit]);
908*34642Smarc 			dga->csr |= DMA_IE;
909*34642Smarc 			dga->csr &= ~DMA_IE;
91030391Skarels 		}
91130391Skarels 		init_shared(unit);		/* init shared memory */
91230391Skarels 		setup_dragon(unit);		/* init ADDER/VIPER */
91330391Skarels 		ldcursor(unit, cons_cursor);	/* load default cursor map */
91430391Skarels 		setup_input(unit);		/* init the DUART */
91530391Skarels 		ldfont(unit);
91630391Skarels 		cursor[unit].x = 0;
91730391Skarels 		cursor[unit].y = 0;
918*34642Smarc 		/*
919*34642Smarc 		 * shut off the mouse rcv intrpt and turn on kbd intrpts
920*34642Smarc 		 */
921*34642Smarc 		duart = (struct duart *) qdmap[unit].duart;
922*34642Smarc 		qdflags[unit].duart_imask &= ~(0x20);
923*34642Smarc 		qdflags[unit].duart_imask |= 0x02;
924*34642Smarc 		duart->imask = qdflags[unit].duart_imask;
925*34642Smarc 		/*
926*34642Smarc 		* shut off interrupts if all is closed
927*34642Smarc 		*/
928*34642Smarc 		if (!(qdflags[unit].inuse & CONS_DEV)) {
929*34642Smarc 			dga = (struct dga *) qdmap[unit].dga;
930*34642Smarc 			dga->csr &= ~(GLOBAL_IE | DMA_IE);
931*34642Smarc 		}
932*34642Smarc 	} else {
933*34642Smarc 		/*
934*34642Smarc 		* this is the console
935*34642Smarc 		*/
936*34642Smarc 		tp = &qd_tty[minor_dev];
937*34642Smarc 		(*linesw[tp->t_line].l_close)(tp);
938*34642Smarc 		ttyclose(tp);
939*34642Smarc 		tp->t_state = 0;
940*34642Smarc 		qdflags[unit].inuse &= ~CONS_DEV;
941*34642Smarc 		/*
942*34642Smarc 		* if graphics device is closed, kill interrupts
943*34642Smarc 		*/
944*34642Smarc 		if (!(qdflags[unit].inuse & GRAPHIC_DEV)) {
945*34642Smarc 			dga = (struct dga *) qdmap[unit].dga;
946*34642Smarc 			dga->csr &= ~(GLOBAL_IE | DMA_IE);
947*34642Smarc 		}
94830391Skarels 	}
94934615Smarc 
95030391Skarels 	return(0);
95130391Skarels 
95230391Skarels } /* qdclose */
95330391Skarels 
95430391Skarels /***************************************************************
95530391Skarels *
95634615Smarc *	qdioctl()... provide QDSS control services
95730391Skarels *
95830391Skarels ****************************************************************
95930391Skarels *
96030391Skarels *  calling convention:	qdioctl(dev, cmd, datap, flags);
96130391Skarels *
96230391Skarels *		where:	dev - the major/minor device number
96330391Skarels *			cmd - the user-passed command argument
96430391Skarels *			datap - ptr to user input buff (128 bytes max)
96530391Skarels *			flags - "f_flags" from "struct file" in file.h
96630391Skarels *
96730391Skarels *
96830391Skarels *	- here is the format for the input "cmd" argument
96930391Skarels *
97030391Skarels *	31     29 28	23 22	      16 15		8 7		 0
97130391Skarels *	+----------------------------------------------------------------+
97230391Skarels *	|I/O type|	  | buff length | device ID char |  user command |
97330391Skarels *	+----------------------------------------------------------------+
97430391Skarels *
97530391Skarels *  Return data is in the data buffer pointed to by "datap" input spec
97630391Skarels *
97730391Skarels *********************/
97830391Skarels 
97930391Skarels qdioctl(dev, cmd, datap, flags)
980*34642Smarc 	dev_t dev;
981*34642Smarc 	int cmd;
982*34642Smarc 	caddr_t datap;
983*34642Smarc 	int flags;
98430391Skarels {
98530391Skarels 	register int *ptep;		/* page table entry pointer */
98632012Smarc 	register int mapix;		/* QVmap[] page table index */
98730391Skarels 	register struct _vs_event *event;
98830391Skarels 	register struct tty *tp;
98930391Skarels 	struct qdmap *qd;		/* pointer to device map struct */
99030391Skarels 	struct dga *dga;		/* Gate Array reg structure pntr */
99130391Skarels 	struct duart *duart;		/* DUART reg structure pointer */
99230391Skarels 	struct adder *adder;		/* ADDER reg structure pointer */
99330391Skarels 	struct prgkbd *cmdbuf;
99430391Skarels 	struct prg_cursor *curs;
99530391Skarels 	struct _vs_cursor *pos;
99630391Skarels 	u_int unit = minor(dev) >> 2;	/* number of caller's QDSS */
99730391Skarels 	u_int minor_dev = minor(dev);
99830391Skarels 	struct uba_device *ui = qdinfo[unit];
99930391Skarels 	struct qd_softc *sc = &qd_softc[ui->ui_unit];
100030391Skarels 	int error;
100130391Skarels 	int s;
100230391Skarels 	int i;				/* SIGNED index */
100330391Skarels 	int sbr;			/* SBR variable (you silly boy) */
100430391Skarels 	u_int ix;
100530391Skarels 	short status;
100630391Skarels 	short *shortp;			/* generic pointer to a short */
100730391Skarels 	char *chrp;			/* generic character pointer */
100830391Skarels 	short *temp;			/* a pointer to template RAM */
100930391Skarels 
1010*34642Smarc 	/*
1011*34642Smarc 	* service graphic device ioctl commands
1012*34642Smarc 	*/
101330391Skarels 	switch (cmd) {
101434615Smarc 
1015*34642Smarc 	case QD_GETEVENT:
1016*34642Smarc 		/*
1017*34642Smarc 		* extract the oldest event from the event queue
1018*34642Smarc 		*/
101930391Skarels 		if (ISEMPTY(eq_header[unit])) {
1020*34642Smarc 			event = (struct _vs_event *) datap;
1021*34642Smarc 			event->vse_device = VSE_NULL;
1022*34642Smarc 			break;
102330391Skarels 		}
102430391Skarels 		event = (struct _vs_event *) GETBEGIN(eq_header[unit]);
102534615Smarc 		s = spl5();
102630391Skarels 		GETEND(eq_header[unit]);
102730391Skarels 		splx(s);
102830391Skarels 		bcopy(event, datap, sizeof(struct _vs_event));
102930391Skarels 		break;
103030391Skarels 
1031*34642Smarc 	case QD_RESET:
1032*34642Smarc 		/*
1033*34642Smarc 		* init the dragon stuff, DUART, and driver variables
1034*34642Smarc 		*/
103530391Skarels 		init_shared(unit);		/* init shared memory */
103630391Skarels 		setup_dragon(unit);	      /* init the ADDER/VIPER stuff */
103730391Skarels 		clear_qd_screen(unit);
103830391Skarels 		ldcursor(unit, cons_cursor);	/* load default cursor map */
103930391Skarels 		ldfont(unit);			/* load the console font */
104030391Skarels 		setup_input(unit);		/* init the DUART */
104130391Skarels 		break;
104230391Skarels 
1043*34642Smarc 	case QD_SET:
1044*34642Smarc 		/*
1045*34642Smarc 		* init the DUART and driver variables
1046*34642Smarc 		*/
104730391Skarels 		init_shared(unit);
104830391Skarels 		setup_input(unit);
104930391Skarels 		break;
105030391Skarels 
1051*34642Smarc 	case QD_CLRSCRN:
1052*34642Smarc 		/*
1053*34642Smarc 		* clear the QDSS screen.  (NOTE that this reinits the dragon)
1054*34642Smarc 		*/
105534615Smarc #ifdef notdef	/* has caused problems and is not necessary */
105630391Skarels 		setup_dragon(unit);
105730391Skarels 		clear_qd_screen(unit);
105834615Smarc #endif
105930391Skarels 		break;
106030391Skarels 
1061*34642Smarc 	case QD_WTCURSOR:
1062*34642Smarc 		/*
1063*34642Smarc 		* load a cursor into template RAM
1064*34642Smarc 		*/
106530391Skarels 		ldcursor(unit, datap);
106630391Skarels 		break;
106730391Skarels 
1068*34642Smarc 	case QD_RDCURSOR:
106930391Skarels 
107030391Skarels 		temp = (short *) qdmap[unit].template;
1071*34642Smarc 		/*
1072*34642Smarc 		 * cursor is 32 WORDS from the end of the 8k WORD...
1073*34642Smarc 		 *  ...template space
1074*34642Smarc 		 */
107530391Skarels 		temp += (8 * 1024) - 32;
107630391Skarels 		for (i = 0; i < 32; ++i, datap += sizeof(short))
1077*34642Smarc 			*(short *)datap = *temp++;
107830391Skarels 		break;
107930391Skarels 
1080*34642Smarc 	case QD_POSCURSOR:
1081*34642Smarc 		/*
1082*34642Smarc 		* position the mouse cursor
1083*34642Smarc 		*/
108430391Skarels 		dga = (struct dga *) qdmap[unit].dga;
108530391Skarels 		pos = (struct _vs_cursor *) datap;
108634615Smarc 		s = spl5();
108730391Skarels 		dga->x_cursor = TRANX(pos->x);
108830391Skarels 		dga->y_cursor = TRANY(pos->y);
108930391Skarels 		eq_header[unit]->curs_pos.x = pos->x;
109030391Skarels 		eq_header[unit]->curs_pos.y = pos->y;
109130391Skarels 		splx(s);
109230391Skarels 		break;
109330391Skarels 
1094*34642Smarc 	case QD_PRGCURSOR:
1095*34642Smarc 		/*
1096*34642Smarc 		* set the cursor acceleration factor
1097*34642Smarc 		*/
109830391Skarels 		curs = (struct prg_cursor *) datap;
109934615Smarc 		s = spl5();
110030391Skarels 		qdflags[unit].curs_acc = curs->acc_factor;
110130391Skarels 		qdflags[unit].curs_thr = curs->threshold;
110230391Skarels 		splx(s);
110330391Skarels 		break;
110430391Skarels 
1105*34642Smarc 	case QD_MAPDEVICE:
1106*34642Smarc 		/*
1107*34642Smarc 		* enable 'user write' to device pages
1108*34642Smarc 		*/
110930391Skarels 		qdflags[unit].mapped |= MAPDEV;
111030391Skarels 		qd = (struct qdmap *) &qdmap[unit];
1111*34642Smarc 		/*
1112*34642Smarc 		* enable user write to template RAM
1113*34642Smarc 		*/
111432012Smarc 		mapix = VTOP((int)qd->template) - VTOP(qvmem[0]);
111532012Smarc 		ptep = (int *)(QVmap[0] + mapix);
111630391Skarels 		for (i = VTOP(TMPSIZE); i > 0; --i)
1117*34642Smarc 			*ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V;
1118*34642Smarc 		/*
1119*34642Smarc 		* enable user write to registers
1120*34642Smarc 		*/
112132012Smarc 		mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]);
112232012Smarc 		ptep = (int *)(QVmap[0] + mapix);
112330391Skarels 
112430391Skarels 		for (i = VTOP(REGSIZE); i > 0; --i)
1125*34642Smarc 			*ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V;
1126*34642Smarc 		/*
1127*34642Smarc 		* enable user write to color maps
1128*34642Smarc 		*/
112932012Smarc 		mapix = VTOP((int)qd->red) - VTOP(qvmem[0]);
113032012Smarc 		ptep = (int *)(QVmap[0] + mapix);
113130391Skarels 		for (i = VTOP(CLRSIZE); i > 0; --i)
1132*34642Smarc 			*ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V;
1133*34642Smarc 		/*
1134*34642Smarc 		* enable user write to DUART
1135*34642Smarc 		*/
113632012Smarc 		mapix = VTOP((int)qd->duart) - VTOP(qvmem[0]);
113732012Smarc 		ptep = (int *)(QVmap[0] + mapix);
113830391Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; /* duart page */
113930391Skarels 
114030391Skarels 		mtpr(TBIA, 0);		/* smash CPU's translation buffer */
114130391Skarels 
1142*34642Smarc 		/*
1143*34642Smarc 		* stuff qdmap structure in return buffer
1144*34642Smarc 		*/
114530391Skarels 		bcopy(qd, datap, sizeof(struct qdmap));
114630391Skarels 		break;
114730391Skarels 
1148*34642Smarc 	case QD_MAPIOBUF:
1149*34642Smarc 		/*
1150*34642Smarc 		 * do setup for DMA by user process
1151*34642Smarc 		 *
1152*34642Smarc 		 * set 'user write enable' bits for DMA buffer
1153*34642Smarc 		 */
115430391Skarels 		qdflags[unit].mapped |= MAPDMA;
115530391Skarels 		ptep = (int *) ((VTOP(DMAheader[unit]) * 4)
1156*34642Smarc 			+ (mfpr(SBR) | 0x80000000));
115730391Skarels 		for (i = (DMAbuf_size >> PGSHIFT); i > 0; --i)
1158*34642Smarc 			*ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V;
115930391Skarels 		mtpr(TBIA, 0);			/* clr CPU translation buf */
1160*34642Smarc 		/*
1161*34642Smarc 		* set up QBUS map registers for DMA
1162*34642Smarc 		*/
116330391Skarels 		DMAheader[unit]->QBAreg =
1164*34642Smarc 		    uballoc(0, DMAheader[unit], DMAbuf_size, 0);
116530391Skarels 		if (DMAheader[unit]->QBAreg == 0)
116634615Smarc 		    printf("\nqd%d: qdioctl: QBA setup error", unit);
116730391Skarels 		Qbus_unmap[unit] = DMAheader[unit]->QBAreg;
116830391Skarels 		DMAheader[unit]->QBAreg &= 0x3FFFF;
1169*34642Smarc 		/*
1170*34642Smarc 		* return I/O buf adr
1171*34642Smarc 		*/
117230391Skarels 		*(int *)datap = (int) DMAheader[unit];
117330391Skarels 		break;
117430391Skarels 
1175*34642Smarc 	case QD_MAPSCROLL:
1176*34642Smarc 		/*
1177*34642Smarc 		* map the shared scroll param area and enable scroll interpts
1178*34642Smarc 		*/
117930391Skarels 		qdflags[unit].mapped |= MAPSCR;
118030391Skarels 		ptep = (int *) ((VTOP(scroll[unit]) * 4)
1181*34642Smarc 			+ (mfpr(SBR) | 0x80000000));
1182*34642Smarc 		/*
1183*34642Smarc 		 * allow user write to scroll area
1184*34642Smarc 		 */
118530391Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
118630391Skarels 		mtpr(TBIA, 0);			/* clr CPU translation buf */
118730391Skarels 		scroll[unit]->status = 0;
118830391Skarels 		adder = (struct adder *) qdmap[unit].adder;
118930391Skarels 		qdflags[unit].adder_ie |= FRAME_SYNC;
119030391Skarels 		adder->interrupt_enable = qdflags[unit].adder_ie;
1191*34642Smarc 		*(int *)datap = (int) scroll[unit]; /* return scroll area */
119230391Skarels 		break;
119330391Skarels 
1194*34642Smarc 	case QD_UNMAPSCROLL:
1195*34642Smarc 		/*
1196*34642Smarc 		* unmap shared scroll param area and disable scroll intrpts
1197*34642Smarc 		*/
119830391Skarels 		if (qdflags[unit].mapped & MAPSCR) {
1199*34642Smarc 			qdflags[unit].mapped &= ~MAPSCR;
1200*34642Smarc 			ptep = (int *) ((VTOP(scroll[unit]) * 4)
1201*34642Smarc 				+ (mfpr(SBR) | 0x80000000));
1202*34642Smarc 			/*
1203*34642Smarc 			 * re-protect 512 scroll param area
1204*34642Smarc 			 */
1205*34642Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
1206*34642Smarc 			mtpr(TBIA, 0);	/* smash CPU's translation buf */
1207*34642Smarc 			adder = (struct adder *) qdmap[unit].adder;
1208*34642Smarc 			qdflags[unit].adder_ie &= ~FRAME_SYNC;
1209*34642Smarc 			adder->interrupt_enable = qdflags[unit].adder_ie;
121030391Skarels 		}
121130391Skarels 		break;
121230391Skarels 
1213*34642Smarc 	case QD_MAPCOLOR:
1214*34642Smarc 		/*
1215*34642Smarc 		* map shared color map write buf and turn on vsync intrpt
1216*34642Smarc 		*/
121730391Skarels 		qdflags[unit].mapped |= MAPCOLOR;
121830391Skarels 		ptep = (int *) ((VTOP(color_buf[unit]) * 4)
1219*34642Smarc 			+ (mfpr(SBR) | 0x80000000));
122030391Skarels 
122130391Skarels 		/* allow user write to color map write buffer */
122230391Skarels 
122330391Skarels 		*ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V;
122430391Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
122530391Skarels 		mtpr(TBIA, 0);			/* clr CPU translation buf */
1226*34642Smarc 		adder = (struct adder *) qdmap[unit].adder;
122730391Skarels 		qdflags[unit].adder_ie |= VSYNC;
122830391Skarels 		adder->interrupt_enable = qdflags[unit].adder_ie;
122934615Smarc 		/* return color area address */
123030391Skarels 		*(int *)datap = (int) color_buf[unit];
123130391Skarels 		break;
123230391Skarels 
1233*34642Smarc 	case QD_UNMAPCOLOR:
1234*34642Smarc 		/*
1235*34642Smarc 		* unmap shared color map write buffer and kill VSYNC intrpts
1236*34642Smarc 		*/
123730391Skarels 		if (qdflags[unit].mapped & MAPCOLOR) {
1238*34642Smarc 			qdflags[unit].mapped &= ~MAPCOLOR;
1239*34642Smarc 			ptep = (int *) ((VTOP(color_buf[unit]) * 4)
1240*34642Smarc 				+ (mfpr(SBR) | 0x80000000));
1241*34642Smarc 			/* re-protect color map write buffer */
1242*34642Smarc 			*ptep++ = (*ptep & ~PG_PROT) | PG_KW | PG_V;
1243*34642Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
1244*34642Smarc 			mtpr(TBIA, 0);	/* smash CPU's translation buf */
1245*34642Smarc 			adder = (struct adder *) qdmap[unit].adder;
1246*34642Smarc 			qdflags[unit].adder_ie &= ~VSYNC;
1247*34642Smarc 			adder->interrupt_enable = qdflags[unit].adder_ie;
124830391Skarels 		}
124930391Skarels 		break;
125030391Skarels 
1251*34642Smarc 	case QD_MAPEVENT:
1252*34642Smarc 		/*
1253*34642Smarc 		* give user write access to the event queue
1254*34642Smarc 		*/
125530391Skarels 		qdflags[unit].mapped |= MAPEQ;
125630391Skarels 		ptep = (int *) ((VTOP(eq_header[unit]) * 4)
1257*34642Smarc 			+ (mfpr(SBR) | 0x80000000));
125830391Skarels 		/* allow user write to 1K event queue */
125930391Skarels 		*ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V;
126030391Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
126130391Skarels 		mtpr(TBIA, 0);			/* clr CPU translation buf */
126230391Skarels 		/* return event queue address */
126330391Skarels 		*(int *)datap = (int) eq_header[unit];
126430391Skarels 		break;
126530391Skarels 
1266*34642Smarc 	case QD_PRGKBD:
1267*34642Smarc 		/*
1268*34642Smarc 		* pass caller's programming commands to LK201
1269*34642Smarc 		*/
127030391Skarels 		duart = (struct duart *) qdmap[unit].duart;
127130391Skarels 		cmdbuf = (struct prgkbd *) datap;    /* pnt to kbd cmd buf */
1272*34642Smarc 		/*
1273*34642Smarc 		* send command
1274*34642Smarc 		*/
127530391Skarels 		for (i = 1000; i > 0; --i) {
1276*34642Smarc 			if ((status = duart->statusA) & XMT_RDY) {
1277*34642Smarc 				duart->dataA = cmdbuf->cmd;
1278*34642Smarc 				break;
1279*34642Smarc 			}
128030391Skarels 		}
128130391Skarels 		if (i == 0) {
1282*34642Smarc 			printf("\nqd%d: qdioctl: timeout on XMT_RDY [1]", unit);
1283*34642Smarc 			break;
128430391Skarels 		}
1285*34642Smarc 		/*
1286*34642Smarc 		* send param1?
1287*34642Smarc 		*/
128830391Skarels 		if (cmdbuf->cmd & LAST_PARAM)
1289*34642Smarc 			break;
129030391Skarels 		for (i = 1000; i > 0; --i) {
1291*34642Smarc 			if ((status = duart->statusA) & XMT_RDY) {
1292*34642Smarc 				duart->dataA = cmdbuf->param1;
1293*34642Smarc 				break;
1294*34642Smarc 			}
129530391Skarels 		}
129630391Skarels 		if (i == 0) {
1297*34642Smarc 			printf("\nqd%d: qdioctl: timeout on XMT_RDY [2]", unit);
1298*34642Smarc 			break;
129930391Skarels 		}
1300*34642Smarc 		/*
1301*34642Smarc 		* send param2?
1302*34642Smarc 		*/
130330391Skarels 		if (cmdbuf->param1 & LAST_PARAM)
130430391Skarels 		    break;
130530391Skarels 		for (i = 1000; i > 0; --i) {
1306*34642Smarc 			if ((status = duart->statusA) & XMT_RDY) {
1307*34642Smarc 				duart->dataA = cmdbuf->param2;
1308*34642Smarc 				break;
1309*34642Smarc 			}
131030391Skarels 		}
131130391Skarels 		if (i == 0) {
1312*34642Smarc 			printf("\nqd%d: qdioctl: timeout on XMT_RDY [3]", unit);
1313*34642Smarc 			break;
131430391Skarels 		}
131530391Skarels 		break;
131630391Skarels 
1317*34642Smarc 	case QD_PRGMOUSE:
1318*34642Smarc 		/*
1319*34642Smarc 		* pass caller's programming commands to the mouse
1320*34642Smarc 		*/
132130391Skarels 		duart = (struct duart *) qdmap[unit].duart;
132230391Skarels 		for (i = 1000; i > 0; --i) {
1323*34642Smarc 			if ((status = duart->statusB) & XMT_RDY) {
1324*34642Smarc 				duart->dataB = *datap;
1325*34642Smarc 				break;
1326*34642Smarc 			}
132730391Skarels 		}
132830391Skarels 		if (i == 0) {
1329*34642Smarc 			printf("\nqd%d: qdioctl: timeout on XMT_RDY [4]", unit);
133030391Skarels 		}
133130391Skarels 		break;
133230391Skarels 
1333*34642Smarc 	case QD_RDCONFIG:
1334*34642Smarc 		/*
1335*34642Smarc 		* get QDSS configuration word and return it
1336*34642Smarc 		*/
133730391Skarels 		*(short *)datap = qdflags[unit].config;
133830391Skarels 		break;
133930391Skarels 
1340*34642Smarc 	case QD_KERN_LOOP:
1341*34642Smarc 	case QD_KERN_UNLOOP:
1342*34642Smarc 		/*
1343*34642Smarc 		 * vestige from ultrix.  BSD uses TIOCCONS to redirect
1344*34642Smarc 		 * kernel console output.
1345*34642Smarc 		 */
134634615Smarc 		break;
134734615Smarc 
1348*34642Smarc 	case QD_PRGTABLET:
1349*34642Smarc 		/*
1350*34642Smarc 		* program the tablet
1351*34642Smarc 		*/
135230391Skarels 		duart = (struct duart *) qdmap[unit].duart;
135330391Skarels 		for (i = 1000; i > 0; --i) {
1354*34642Smarc 			if ((status = duart->statusB) & XMT_RDY) {
1355*34642Smarc 				duart->dataB = *datap;
1356*34642Smarc 				break;
1357*34642Smarc 			}
135830391Skarels 		}
135930391Skarels 		if (i == 0) {
1360*34642Smarc 			printf("\nqd%d: qdioctl: timeout on XMT_RDY [5]", unit);
136130391Skarels 		}
136230391Skarels 		break;
136330391Skarels 
1364*34642Smarc 	case QD_PRGTABRES:
1365*34642Smarc 		/*
1366*34642Smarc 		* program the tablet report resolution factor
1367*34642Smarc 		*/
136830391Skarels 		qdflags[unit].tab_res = *(short *)datap;
136930391Skarels 		break;
137030391Skarels 
1371*34642Smarc 	default:
1372*34642Smarc 		/*
1373*34642Smarc 		* service tty ioctl's
1374*34642Smarc 		*/
1375*34642Smarc 		if (!(minor_dev & 0x02)) {
137630391Skarels 			tp = &qd_tty[minor_dev];
1377*34642Smarc 			error =
1378*34642Smarc 			   (*linesw[tp->t_line].l_ioctl)(tp, cmd, datap, flags);
137930391Skarels 			if (error >= 0) {
1380*34642Smarc 				return(error);
138130391Skarels 			}
138230391Skarels 			error = ttioctl(tp, cmd, datap, flags);
138330391Skarels 			if (error >= 0) {
1384*34642Smarc 				return(error);
138530391Skarels 			}
1386*34642Smarc 		}
1387*34642Smarc 		break;
138830391Skarels 	}
138930391Skarels 
139030391Skarels 	return(0);
139130391Skarels 
139230391Skarels } /* qdioctl */
139330391Skarels 
139430391Skarels /**********************************************************************
139530391Skarels *
139630391Skarels *	qdselect()... service select call for event queue input
139730391Skarels *
139830391Skarels **********************************************************************/
139930391Skarels 
140030391Skarels qdselect(dev, rw)
1401*34642Smarc 	dev_t dev;
1402*34642Smarc 	int rw;
140330391Skarels {
140430391Skarels 	register int s;
140530391Skarels 	register int unit;
140634615Smarc 	register struct tty *tp;
140734615Smarc 	u_int minor_dev = minor(dev);
140830391Skarels 
140934615Smarc 	s = spl5();
141034615Smarc 	unit = minor_dev >> 2;
141130391Skarels 
141230391Skarels 	switch (rw) {
1413*34642Smarc 	case FREAD:
1414*34642Smarc 		if ((minor_dev & 0x03) == 2) {
1415*34642Smarc 			/*
1416*34642Smarc 			* this is a graphics device, so check for events
1417*34642Smarc 			*/
1418*34642Smarc 			if(!(ISEMPTY(eq_header[unit])))
1419*34642Smarc 			    {
1420*34642Smarc 				splx(s);
1421*34642Smarc 				return(1);
1422*34642Smarc 			}
1423*34642Smarc 			rsel[unit] = u.u_procp;
1424*34642Smarc 			qdflags[unit].selmask |= SEL_READ;
1425*34642Smarc 			splx(s);
1426*34642Smarc 			return(0);
1427*34642Smarc 		} else {
1428*34642Smarc 			/*
1429*34642Smarc 			* this is a tty device
1430*34642Smarc 			*/
1431*34642Smarc 			tp = &qd_tty[minor_dev];
1432*34642Smarc 			if (ttnread(tp))
1433*34642Smarc 			    return(1);
1434*34642Smarc 			tp->t_rsel = u.u_procp;
1435*34642Smarc 			splx(s);
1436*34642Smarc 			return(0);
143730391Skarels 		}
143830391Skarels 
1439*34642Smarc 	case FWRITE:
1440*34642Smarc 		if ((minor(dev) & 0x03) == 2) {
1441*34642Smarc 			/*
1442*34642Smarc 			* this is a graphics device, so check for dma buffers
1443*34642Smarc 			*/
1444*34642Smarc 			if (DMA_ISEMPTY(DMAheader[unit]))
1445*34642Smarc 			    {
1446*34642Smarc 				splx(s);
1447*34642Smarc 				return(1);
1448*34642Smarc 			}
1449*34642Smarc 			rsel[unit] = u.u_procp;
1450*34642Smarc 			qdflags[unit].selmask |= SEL_WRITE;
1451*34642Smarc 			splx(s);
1452*34642Smarc 			return(0);
1453*34642Smarc 		} else {
1454*34642Smarc 			/*
1455*34642Smarc 			* this is a tty device
1456*34642Smarc 			*/
1457*34642Smarc 			tp = &qd_tty[minor_dev];
1458*34642Smarc 			if (tp->t_outq.c_cc <= TTLOWAT(tp))
1459*34642Smarc 			    return(1);
1460*34642Smarc 			tp->t_wsel = u.u_procp;
1461*34642Smarc 			splx(s);
1462*34642Smarc 			return(0);
146330391Skarels 		}
146430391Skarels 	}
146530391Skarels 
146630391Skarels } /* qdselect() */
146730391Skarels 
146830391Skarels /***************************************************************
146930391Skarels *
147030391Skarels *	qdwrite()... output to the QDSS screen as a TTY
147130391Skarels *
147230391Skarels ***************************************************************/
147330391Skarels 
147430391Skarels extern qd_strategy();
147530391Skarels 
147630391Skarels qdwrite(dev, uio)
1477*34642Smarc 	dev_t dev;
1478*34642Smarc 	struct uio *uio;
147930391Skarels {
148030391Skarels 	register struct tty *tp;
148130391Skarels 	register int minor_dev;
148230391Skarels 	register int unit;
148330391Skarels 
148430391Skarels 	minor_dev = minor(dev);
148530391Skarels 	unit = (minor_dev >> 2) & 0x07;
148630391Skarels 
1487*34642Smarc 	if (((minor_dev&0x03) != 0x02) && (qdflags[unit].inuse&CONS_DEV)) {
1488*34642Smarc 		/*
1489*34642Smarc 		* this is the console...
1490*34642Smarc 		*/
1491*34642Smarc 		tp = &qd_tty[minor_dev];
1492*34642Smarc 		return ((*linesw[tp->t_line].l_write)(tp, uio));
1493*34642Smarc 	} else if (qdflags[unit].inuse & GRAPHIC_DEV) {
1494*34642Smarc 		/*
1495*34642Smarc 		* this is a DMA xfer from user space
1496*34642Smarc 		*/
1497*34642Smarc 		return (physio(qd_strategy, &qdbuf[unit],
1498*34642Smarc 		dev, B_WRITE, minphys, uio));
149930391Skarels 	}
150030391Skarels }
150130391Skarels 
150230391Skarels /***************************************************************
150330391Skarels *
150430391Skarels *	qdread()... read from QDSS keyboard as a TTY
150530391Skarels *
150630391Skarels ***************************************************************/
150730391Skarels 
150830391Skarels qdread(dev, uio)
1509*34642Smarc 	dev_t dev;
1510*34642Smarc 	struct uio *uio;
151130391Skarels {
151230391Skarels 	register struct tty *tp;
151330391Skarels 	register int minor_dev;
151430391Skarels 	register int unit;
151530391Skarels 
151630391Skarels 	minor_dev = minor(dev);
151730391Skarels 	unit = (minor_dev >> 2) & 0x07;
151830391Skarels 
1519*34642Smarc 	if ((minor_dev & 0x03) != 0x02 && qdflags[unit].inuse & CONS_DEV) {
1520*34642Smarc 		/*
1521*34642Smarc 		* this is the console
1522*34642Smarc 		*/
1523*34642Smarc 		tp = &qd_tty[minor_dev];
1524*34642Smarc 		return ((*linesw[tp->t_line].l_read)(tp, uio));
1525*34642Smarc 	} else if (qdflags[unit].inuse & GRAPHIC_DEV) {
1526*34642Smarc 		/*
1527*34642Smarc 		* this is a bitmap-to-processor xfer
1528*34642Smarc 		*/
1529*34642Smarc 		return (physio(qd_strategy, &qdbuf[unit],
1530*34642Smarc 		dev, B_READ, minphys, uio));
153130391Skarels 	}
153230391Skarels }
153330391Skarels 
153430391Skarels /***************************************************************
153530391Skarels *
153630391Skarels *	qd_strategy()... strategy routine to do DMA
153730391Skarels *
153830391Skarels ***************************************************************/
153930391Skarels 
154030391Skarels qd_strategy(bp)
1541*34642Smarc 	register struct buf *bp;
154230391Skarels {
154330391Skarels 	register struct dga *dga;
154430391Skarels 	register struct adder *adder;
154530391Skarels 	char *DMAbufp;
154630391Skarels 	int QBAreg;
154730391Skarels 	int bytcnt;
154830391Skarels 	int s;
154930391Skarels 	int unit;
155030391Skarels 	int cookie;
155130391Skarels 	int i,j,k;
155230391Skarels 
155330391Skarels 	unit = (minor(bp->b_dev) >> 2) & 0x07;
155430391Skarels 
1555*34642Smarc 	/*
1556*34642Smarc 	* init pointers
1557*34642Smarc 	*/
155830391Skarels 	if ((QBAreg = ubasetup(0, bp, 0)) == 0) {
1559*34642Smarc 		printf("\nqd%d: qd_strategy: QBA setup error", unit);
1560*34642Smarc 		goto STRAT_ERR;
156130391Skarels 	}
156230391Skarels 	dga = (struct dga *) qdmap[unit].dga;
156334615Smarc 	s = spl5();
156430391Skarels 	qdflags[unit].user_dma = -1;
156530391Skarels 	dga->csr |= DMA_IE;
156630391Skarels 	cookie = QBAreg & 0x3FFFF;
156730391Skarels 	dga->adrs_lo = (short) cookie;
156830391Skarels 	dga->adrs_hi = (short) (cookie >> 16);
156930391Skarels 	dga->bytcnt_lo = (short) bp->b_bcount;
157030391Skarels 	dga->bytcnt_hi = (short) (bp->b_bcount >> 16);
157130391Skarels 
157230391Skarels 	while (qdflags[unit].user_dma) {
1573*34642Smarc 		sleep((caddr_t)&qdflags[unit].user_dma, QDPRIOR);
157430391Skarels 	}
157530391Skarels 	splx(s);
157630391Skarels 	ubarelse(0, &QBAreg);
157730391Skarels 	if (!(dga->csr & DMA_ERR)) {
1578*34642Smarc 		iodone(bp);
1579*34642Smarc 		return;
158030391Skarels 	}
158130391Skarels 
158230391Skarels STRAT_ERR:
158330391Skarels 	adder = (struct adder *) qdmap[unit].adder;
1584*34642Smarc 	adder->command = CANCEL;	/* cancel adder activity */
158530391Skarels 	dga->csr &= ~DMA_IE;
158630391Skarels 	dga->csr &= ~0x0600;		/* halt DMA (reset fifo) */
158730391Skarels 	dga->csr |= DMA_ERR;		/* clear error condition */
158830391Skarels 	bp->b_flags |= B_ERROR; 	/* flag an error to physio() */
158930391Skarels 
1590*34642Smarc 	/*
1591*34642Smarc 	 * if DMA was running, flush spurious intrpt
1592*34642Smarc 	 */
159330391Skarels 	if (dga->bytcnt_lo != 0) {
1594*34642Smarc 		dga->bytcnt_lo = 0;
1595*34642Smarc 		dga->bytcnt_hi = 0;
1596*34642Smarc 		DMA_SETIGNORE(DMAheader[unit]);
1597*34642Smarc 		dga->csr |= DMA_IE;
159830391Skarels 	}
159930391Skarels 	iodone(bp);
160030391Skarels 
160130391Skarels } /* qd_strategy */
160230391Skarels 
160330391Skarels /*******************************************************************
160430391Skarels *
160530391Skarels *	qdstart()... startup output to the console screen
160630391Skarels *
160730391Skarels ********************************************************************
160830391Skarels *
160930391Skarels *	calling convention:
161030391Skarels *
161130391Skarels *		qdstart(tp);
161234615Smarc *		struct tty *tp; 	;pointer to tty structure
161330391Skarels *
161430391Skarels ********/
161530391Skarels 
161630391Skarels qdstart(tp)
1617*34642Smarc 	register struct tty *tp;
161830391Skarels {
161930391Skarels 	register int which_unit, unit, c;
162030391Skarels 	int s;
162134615Smarc 	int curs_on;
162234615Smarc 	struct dga *dga;
162334615Smarc 
162430391Skarels 	unit = minor(tp->t_dev);
162530391Skarels 	which_unit = (unit >> 2) & 0x3;
162634615Smarc 	unit &= 0x03;
162730391Skarels 
162834615Smarc 	s = spl5();
162934615Smarc 
1630*34642Smarc 	/*
1631*34642Smarc 	* If it's currently active, or delaying, no need to do anything.
1632*34642Smarc 	*/
163330391Skarels 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
163430391Skarels 		goto out;
163530391Skarels 
1636*34642Smarc 	/*
1637*34642Smarc 	* Display chars until the queue is empty.
1638*34642Smarc 	* Drop input from anything but the console
1639*34642Smarc 	* device on the floor.
1640*34642Smarc 	*
1641*34642Smarc 	* XXX - this loop is done at spltty.
1642*34642Smarc 	*
1643*34642Smarc 	*/
1644*34642Smarc 	while (tp->t_outq.c_cc) {
164534511Smarc 		c = getc(&tp->t_outq);
164634615Smarc 		if (unit == 0)
1647*34642Smarc 			blitc(which_unit, (char)(c & 0xFF));
164830391Skarels 	}
1649*34642Smarc 	/*
1650*34642Smarc 	* If there are sleepers, and output has drained below low
1651*34642Smarc 	* water mark, wake up the sleepers.
1652*34642Smarc 	*/
1653*34642Smarc 	if (tp->t_outq.c_cc <= TTLOWAT(tp)) {
165434615Smarc 		if (tp->t_state & TS_ASLEEP){
165534615Smarc 			tp->t_state &= ~TS_ASLEEP;
165634615Smarc 			wakeup((caddr_t) &tp->t_outq);
165734615Smarc 		}
165830391Skarels 	}
165930391Skarels 
166034615Smarc 	tp->t_state &= ~TS_BUSY;
166134615Smarc 
166230391Skarels out:
166330391Skarels 	splx(s);
166430391Skarels 
166530391Skarels } /* qdstart */
166630391Skarels 
166730391Skarels 
166830391Skarels /*******************************************************************
166930391Skarels *
167030391Skarels *	qdstop()... stop the tty
167130391Skarels *
167230391Skarels *******************************************************************/
167330391Skarels 
167430391Skarels qdstop(tp, flag)
1675*34642Smarc 	register struct tty *tp;
1676*34642Smarc 	int flag;
167730391Skarels {
167830391Skarels 	register int s;
167930391Skarels 
168034615Smarc 	s = spl5();	/* block intrpts during state modification */
168130391Skarels 	if (tp->t_state & TS_BUSY) {
1682*34642Smarc 		if ((tp->t_state & TS_TTSTOP) == 0) {
1683*34642Smarc 			tp->t_state |= TS_FLUSH;
1684*34642Smarc 		}
1685*34642Smarc 		else
1686*34642Smarc 			tp->t_state &= ~TS_BUSY;
168730391Skarels 	}
168830391Skarels 	splx(s);
168930391Skarels }
169030391Skarels 
169130391Skarels /*******************************************************************
169230391Skarels *
169330391Skarels *	blitc()... output a character to the QDSS screen
169430391Skarels *
169530391Skarels ********************************************************************
169630391Skarels *
169730391Skarels *	calling convention:
169830391Skarels *
169930391Skarels *		blitc(chr);
1700*34642Smarc *		char chr;		# character to be displayed
170130391Skarels *
170230391Skarels ********/
170330391Skarels 
170430391Skarels blitc(unit, chr)
1705*34642Smarc 	int unit;
1706*34642Smarc 	unsigned char chr;
170730391Skarels {
170830391Skarels 	register struct adder *adder;
170930391Skarels 	register struct dga *dga;
171030391Skarels 	register int i;
1711*34642Smarc 	int nograph = !(qdflags[unit].inuse&GRAPHIC_DEV);
1712*34642Smarc 	unsigned char savechar;
171330391Skarels 	short x;
1714*34642Smarc 	static short inescape[NQD];
171530391Skarels 
171630391Skarels 	adder = (struct adder *) qdmap[unit].adder;
171730391Skarels 	dga = (struct dga *) qdmap[unit].dga;
1718*34642Smarc 	/*
1719*34642Smarc 	 * BSD comment: this (&=0177) defeats the extended character
1720*34642Smarc 	 * set code for the glass tty, but if i had the time i would
1721*34642Smarc 	 * spend it ripping out the code completely.  This driver
1722*34642Smarc 	 * is too big for its own good.
1723*34642Smarc 	 */
1724*34642Smarc 	chr &= 0177;
1725*34642Smarc 	/*
1726*34642Smarc 	 * Cursor addressing (so vi will work when i really need it).
1727*34642Smarc 	 * Decode for "\E=%.%." cursor motion description.
1728*34642Smarc 	 * Corresponds to type "qdcons" in /etc/termcap, or if you
1729*34642Smarc 	 * don't have it:
1730*34642Smarc 	 *
1731*34642Smarc 	 *    qd|qdss|qdcons|qdss glass tty (4.4 BSD):\
1732*34642Smarc 	 *      :am:do=^J:le=^H:bs:cm=\E=%.%.:cl=1^Z:co#128:li#57::nd=^L:up=^K:
1733*34642Smarc 	 *
1734*34642Smarc 	 */
1735*34642Smarc 	if (inescape[unit] && nograph) {
1736*34642Smarc 		switch (inescape[unit]++) {
1737*34642Smarc 		case 1:
1738*34642Smarc 			if (chr != '=') {
1739*34642Smarc 				/* abort escape sequence */
1740*34642Smarc 				inescape[unit] = 0;
1741*34642Smarc 				blitc(unit, chr);
1742*34642Smarc 			}
1743*34642Smarc 			return(0);
1744*34642Smarc 		case 2:
1745*34642Smarc 			/* position row */
1746*34642Smarc 			cursor[unit].y = CHAR_HEIGHT * chr;
1747*34642Smarc 			if (cursor[unit].y > 863 - CHAR_HEIGHT)
1748*34642Smarc 				cursor[unit].y = 863 - CHAR_HEIGHT;
1749*34642Smarc 			dga->y_cursor = TRANY(cursor[unit].y);
1750*34642Smarc 			return(0);
1751*34642Smarc 		case 3:
1752*34642Smarc 			/* position column */
1753*34642Smarc 			cursor[unit].x = CHAR_WIDTH * chr;
1754*34642Smarc 			if (cursor[unit].x > 1024 - CHAR_WIDTH)
1755*34642Smarc 				cursor[unit].x = 1023 - CHAR_WIDTH;
1756*34642Smarc 			dga->x_cursor = TRANX(cursor[unit].x);
1757*34642Smarc 			inescape[unit] = 0;
1758*34642Smarc 			return(0);
1759*34642Smarc 		default:
1760*34642Smarc 			inescape[unit] = 0;
1761*34642Smarc 			blitc(unit, chr);
1762*34642Smarc 		}
1763*34642Smarc 	}
176430391Skarels 
176530391Skarels 	switch (chr) {
1766*34642Smarc 	case '\r':			/* return char */
176730391Skarels 		cursor[unit].x = 0;
1768*34642Smarc 		if (nograph)
1769*34642Smarc 			dga->x_cursor = TRANX(cursor[unit].x);
177030391Skarels 		return(0);
177130391Skarels 
1772*34642Smarc 	case '\t':			/* tab char */
177330391Skarels 		for (i = 8 - ((cursor[unit].x >> 3) & 0x07); i > 0; --i) {
1774*34642Smarc 			blitc(unit, ' ');
177530391Skarels 		}
177630391Skarels 		return(0);
177730391Skarels 
1778*34642Smarc 	case '\n':			/* line feed char */
177930391Skarels 		if ((cursor[unit].y += CHAR_HEIGHT) > (863 - CHAR_HEIGHT)) {
1780*34642Smarc 			if (nograph) {
1781*34642Smarc 				cursor[unit].y -= CHAR_HEIGHT;
1782*34642Smarc 				scroll_up(adder);
1783*34642Smarc 			} else
1784*34642Smarc 				cursor[unit].y = 0;
178530391Skarels 		}
1786*34642Smarc 		if (nograph)
1787*34642Smarc 			dga->y_cursor = TRANY(cursor[unit].y);
178830391Skarels 		return(0);
178930391Skarels 
1790*34642Smarc 	case '\b':			/* backspace char */
179130391Skarels 		if (cursor[unit].x > 0) {
1792*34642Smarc 			cursor[unit].x -= CHAR_WIDTH;
1793*34642Smarc 			if (nograph)
1794*34642Smarc 				dga->x_cursor = TRANX(cursor[unit].x);
179530391Skarels 		}
179630391Skarels 		return(0);
1797*34642Smarc 	case CTRL('k'):		/* cursor up */
1798*34642Smarc 		if (nograph && cursor[unit].y > 0) {
1799*34642Smarc 			cursor[unit].y -= CHAR_HEIGHT;
1800*34642Smarc 			dga->y_cursor = TRANY(cursor[unit].y);
1801*34642Smarc 		}
1802*34642Smarc 		return(0);
180330391Skarels 
1804*34642Smarc 	case CTRL('^'):		/* home cursor */
1805*34642Smarc 		if (nograph) {
1806*34642Smarc 			cursor[unit].x = 0;
1807*34642Smarc 			dga->x_cursor = TRANX(cursor[unit].x);
1808*34642Smarc 			cursor[unit].y = 0;
1809*34642Smarc 			dga->y_cursor = TRANY(cursor[unit].y);
1810*34642Smarc 		}
1811*34642Smarc 		return(0);
181232012Smarc 
1813*34642Smarc 	case CTRL('l'):		/* cursor right */
1814*34642Smarc 		if (nograph && cursor[unit].x < 1023 - CHAR_WIDTH) {
1815*34642Smarc 			cursor[unit].x += CHAR_WIDTH;
1816*34642Smarc 			dga->x_cursor = TRANX(cursor[unit].x);
1817*34642Smarc 		}
1818*34642Smarc 		return(0);
181930391Skarels 
1820*34642Smarc 	case CTRL('z'):		/* clear screen */
1821*34642Smarc 		if (nograph) {
1822*34642Smarc 			setup_dragon(unit);
1823*34642Smarc 			clear_qd_screen(unit);
1824*34642Smarc 			/* home cursor - termcap seems to assume this */
1825*34642Smarc 			cursor[unit].x = 0;
1826*34642Smarc 			dga->x_cursor = TRANX(cursor[unit].x);
1827*34642Smarc 			cursor[unit].y = 0;
1828*34642Smarc 			dga->y_cursor = TRANY(cursor[unit].y);
1829*34642Smarc 		}
1830*34642Smarc 		return(0);
183130391Skarels 
1832*34642Smarc 	case '\033':		/* start escape sequence */
1833*34642Smarc 		if (nograph)
1834*34642Smarc 			inescape[unit] = 1;
1835*34642Smarc 		return(0);
1836*34642Smarc 
1837*34642Smarc 	default:
1838*34642Smarc 		if ((chr < ' ') || (chr > '~'))
1839*34642Smarc 			return(0);
1840*34642Smarc 	}
1841*34642Smarc 	/*
1842*34642Smarc 	 * setup VIPER operand control registers
1843*34642Smarc 	 */
184430391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0001);  /* select plane #0 */
184530391Skarels 	write_ID(adder, SRC1_OCR_B,
1846*34642Smarc 	EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY);
184730391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x00FE);  /* select other planes */
184830391Skarels 	write_ID(adder, SRC1_OCR_B,
1849*34642Smarc 	EXT_SOURCE | INT_NONE | NO_ID | BAR_SHIFT_DELAY);
185030391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x00FF);  /* select all planes */
185130391Skarels 	write_ID(adder, DST_OCR_B,
1852*34642Smarc 	EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
185330391Skarels 	write_ID(adder, MASK_1, 0xFFFF);
185430391Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 1);
185530391Skarels 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
1856*34642Smarc 	adder->x_clip_min = 0;
1857*34642Smarc 	adder->x_clip_max = 1024;
1858*34642Smarc 	adder->y_clip_min = 0;
1859*34642Smarc 	adder->y_clip_max = 864;
1860*34642Smarc 	/*
1861*34642Smarc 	 * load DESTINATION origin and vectors
1862*34642Smarc 	 */
186330391Skarels 	adder->fast_dest_dy = 0;
186430391Skarels 	adder->slow_dest_dx = 0;
186530391Skarels 	adder->error_1 = 0;
186630391Skarels 	adder->error_2 = 0;
186730391Skarels 	adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL;
186830391Skarels 	wait_status(adder, RASTEROP_COMPLETE);
186930391Skarels 	adder->destination_x = cursor[unit].x;
187030391Skarels 	adder->fast_dest_dx = CHAR_WIDTH;
187130391Skarels 	adder->destination_y = cursor[unit].y;
187230391Skarels 	adder->slow_dest_dy = CHAR_HEIGHT;
1873*34642Smarc 	/*
1874*34642Smarc 	 * load SOURCE origin and vectors
1875*34642Smarc 	 */
187634615Smarc 	if ((chr - ' ') > (CHARS - 1))  {
187734615Smarc 		printf("Invalid character (x)%x in blitc\n",chr);
187834615Smarc 		chr = ' ';
187934615Smarc 	}
1880*34642Smarc 	/*
1881*34642Smarc 	 * X position is modulo the number of characters per line
1882*34642Smarc 	 */
188334615Smarc 	adder->source_1_x = FONT_X +
1884*34642Smarc 	    (((chr - ' ') % (MAX_SCREEN_X/CHAR_WIDTH)) * CHAR_WIDTH);
1885*34642Smarc 	/*
1886*34642Smarc 	 * Point to either first or second row
1887*34642Smarc 	 */
188834615Smarc 	adder->source_1_y = 2048 - 15 *
1889*34642Smarc 	    (((chr - ' ')/(MAX_SCREEN_X/CHAR_WIDTH)) + 1);
189030391Skarels 	adder->source_1_dx = CHAR_WIDTH;
189130391Skarels 	adder->source_1_dy = CHAR_HEIGHT;
189230391Skarels 	write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
189330391Skarels 	adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE;
1894*34642Smarc 	/*
1895*34642Smarc 	 * update console cursor coordinates
1896*34642Smarc 	 */
189730391Skarels 	cursor[unit].x += CHAR_WIDTH;
1898*34642Smarc 	if (nograph)
1899*34642Smarc 		dga->x_cursor = TRANX(cursor[unit].x);
190030391Skarels 	if (cursor[unit].x > (1024 - CHAR_WIDTH)) {
1901*34642Smarc 		blitc(unit, '\r');
1902*34642Smarc 		blitc(unit, '\n');
190330391Skarels 	}
190430391Skarels 
190530391Skarels } /* blitc */
190630391Skarels 
1907*34642Smarc qdreset()
1908*34642Smarc {
1909*34642Smarc }
1910*34642Smarc qd_init()
1911*34642Smarc {
1912*34642Smarc }
191330391Skarels 
191430391Skarels /******************************************************************
191534615Smarc *******************************************************************
191634615Smarc *******************************************************************
191730391Skarels *
1918*34642Smarc *	INTERRUPT SERVICE ROUTINES
191930391Skarels *
192034615Smarc *******************************************************************
192134615Smarc *******************************************************************
192230391Skarels ******************************************************************/
192330391Skarels 
192430391Skarels /*****************************************************************
192530391Skarels *
192630391Skarels *	qddint()... service "DMA DONE" interrupt condition
192730391Skarels *
192830391Skarels *****************************************************************/
192930391Skarels 
193030391Skarels qddint(qd)
1931*34642Smarc 	int qd;
193230391Skarels {
193330391Skarels 	register struct DMAreq_header *header;
193430391Skarels 	register struct DMAreq *request;
193530391Skarels 	register struct dga *dga;
193630391Skarels 	struct adder *adder;
193730391Skarels 
193830391Skarels 	int cookie;			/* DMA adrs for QDSS */
193930391Skarels 	int i;
194030391Skarels 
194130391Skarels 	spl4(); 			/* allow interval timer in */
194230391Skarels 
1943*34642Smarc 	/*
1944*34642Smarc 	* init pointers
1945*34642Smarc 	*/
194630391Skarels 	header = DMAheader[qd]; 	    /* register for optimization */
194730391Skarels 	dga = (struct dga *) qdmap[qd].dga;
194830391Skarels 	adder = (struct adder *) qdmap[qd].adder;
194930391Skarels 
1950*34642Smarc 	/*
1951*34642Smarc 	* if this interrupt flagged as bogus for interrupt flushing purposes..
1952*34642Smarc 	*/
195330391Skarels 	if (DMA_ISIGNORE(header)) {
1954*34642Smarc 		DMA_CLRIGNORE(header);
1955*34642Smarc 		return;
195630391Skarels 	}
195730391Skarels 
1958*34642Smarc 	/*
1959*34642Smarc 	* dump a DMA hardware error message if appropriate
1960*34642Smarc 	*/
196130391Skarels 	if (dga->csr & DMA_ERR) {
196230391Skarels 
1963*34642Smarc 		if (dga->csr & PARITY_ERR)
1964*34642Smarc 		    printf("\nqd%d: qddint: DMA hardware parity fault.", qd);
196530391Skarels 
1966*34642Smarc 		if (dga->csr & BUS_ERR)
1967*34642Smarc 		    printf("\nqd%d: qddint: DMA hardware bus error.", qd);
196830391Skarels 	}
196930391Skarels 
1970*34642Smarc 	/*
1971*34642Smarc 	* if this was a DMA from user space...
1972*34642Smarc 	*/
197330391Skarels 	if (qdflags[qd].user_dma) {
1974*34642Smarc 		qdflags[qd].user_dma = 0;
1975*34642Smarc 		wakeup((caddr_t)&qdflags[qd].user_dma);
1976*34642Smarc 		return;
197730391Skarels 	}
197830391Skarels 
1979*34642Smarc 	/*
1980*34642Smarc 	* if we're doing DMA request queue services, field the error condition
1981*34642Smarc 	*/
198230391Skarels 	if (dga->csr & DMA_ERR) {
198330391Skarels 
1984*34642Smarc 		dga->csr &= ~0x0600;		/* halt DMA (reset fifo) */
1985*34642Smarc 		dga->csr |= DMA_ERR;		/* clear error condition */
1986*34642Smarc 		adder->command = CANCEL;	/* cancel adder activity */
198730391Skarels 
1988*34642Smarc 		DMA_SETERROR(header);	/* flag error in header status word */
1989*34642Smarc 		DMA_CLRACTIVE(header);
1990*34642Smarc 		header->DMAreq[header->oldest].DMAdone |= HARD_ERROR;
1991*34642Smarc 		header->newest = header->oldest;
1992*34642Smarc 		header->used = 0;
199330391Skarels 
1994*34642Smarc 		if (rsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
1995*34642Smarc 			selwakeup(rsel[qd], 0);
1996*34642Smarc 			rsel[qd] = 0;
1997*34642Smarc 			qdflags[qd].selmask &= ~SEL_WRITE;
1998*34642Smarc 		}
199930391Skarels 
2000*34642Smarc 		if (dga->bytcnt_lo != 0) {
2001*34642Smarc 			dga->bytcnt_lo = 0;
2002*34642Smarc 			dga->bytcnt_hi = 0;
2003*34642Smarc 			DMA_SETIGNORE(header);
2004*34642Smarc 		}
2005*34642Smarc 		return;
200630391Skarels 	}
200730391Skarels 
2008*34642Smarc 	/*
2009*34642Smarc 	* if the DMA request queue is now becoming non-full,
2010*34642Smarc 	* wakeup "select" client.
2011*34642Smarc 	*/
201230391Skarels 	if (DMA_ISFULL(header)) {
201330391Skarels 
2014*34642Smarc 		if (rsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
2015*34642Smarc 			selwakeup(rsel[qd], 0);
2016*34642Smarc 			rsel[qd] = 0;
2017*34642Smarc 			qdflags[qd].selmask &= ~SEL_WRITE;
2018*34642Smarc 		}
201930391Skarels 	}
202030391Skarels 
202130391Skarels 	header->DMAreq[header->oldest].DMAdone |= REQUEST_DONE;
2022*34642Smarc 	QDlast_DMAtype = header->DMAreq[header->oldest].DMAtype;
202330391Skarels 
202434615Smarc 	/* check for unexpected interrupt */
202534615Smarc 	if (DMA_ISEMPTY(header))
202630391Skarels 	    return;
202730391Skarels 
202830391Skarels 	DMA_GETEND(header);	/* update request queue indices */
202930391Skarels 
2030*34642Smarc 	/*
2031*34642Smarc 	* if no more DMA pending, wake up "select" client and exit */
203230391Skarels 
203330391Skarels 	if (DMA_ISEMPTY(header)) {
203430391Skarels 
2035*34642Smarc 		if (rsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
2036*34642Smarc 			selwakeup(rsel[qd], 0);
2037*34642Smarc 			rsel[qd] = 0;
2038*34642Smarc 			qdflags[qd].selmask &= ~SEL_WRITE;
2039*34642Smarc 		}
204030391Skarels 
2041*34642Smarc 		DMA_CLRACTIVE(header);  /* flag DMA done */
2042*34642Smarc 		return;
204330391Skarels 	}
204430391Skarels 
2045*34642Smarc 	/*
2046*34642Smarc 	* initiate next DMA xfer  */
204730391Skarels 
204830391Skarels 	request = DMA_GETBEGIN(header);
204934615Smarc 	if (request->DMAtype != QDlast_DMAtype) {
2050*34642Smarc 		dga->csr &= ~0x0600;	  /* halt DMA (reset fifo) */
2051*34642Smarc 		adder->command = CANCEL;  /* cancel adder activity */
205234615Smarc 	}
205330391Skarels 
205434615Smarc 
205530391Skarels 	switch (request->DMAtype) {
205630391Skarels 
2057*34642Smarc 	case DISPLIST:
205834615Smarc 		if (request->DMAtype != QDlast_DMAtype) {
205934615Smarc 			dga->csr |= DL_ENB;
206034615Smarc 			dga->csr &= ~(BTOP_ENB | BYTE_DMA);
206134615Smarc 		}
206230391Skarels 		break;
206330391Skarels 
2064*34642Smarc 	case PTOB:
206534615Smarc 		if (request->DMAtype != QDlast_DMAtype) {
206634615Smarc 			if (request->DMAdone & BYTE_PACK)
2067*34642Smarc 			    dga->csr |= (PTOB_ENB | BYTE_DMA);
206834615Smarc 			else {
206934615Smarc 				dga->csr |= PTOB_ENB;
207034615Smarc 				dga->csr &= ~BYTE_DMA;
207134615Smarc 			}
207234615Smarc 		}
207330391Skarels 		break;
207430391Skarels 
2075*34642Smarc 	case BTOP:
207634615Smarc 		if (request->DMAtype != QDlast_DMAtype) {
207734615Smarc 			if (request->DMAdone & BYTE_PACK) {
207834615Smarc 				dga->csr &= ~DL_ENB;
207934615Smarc 				dga->csr |= (BTOP_ENB | BYTE_DMA);
208034615Smarc 			}
208134615Smarc 			else {
208234615Smarc 				dga->csr |= BTOP_ENB;
208334615Smarc 				dga->csr &= ~(BYTE_DMA | DL_ENB);
208434615Smarc 			}
208534615Smarc 		}
208630391Skarels 		break;
2087*34642Smarc 	default:
208834615Smarc 		printf("\nqd%d: qddint: illegal DMAtype parameter.", qd);
208930391Skarels 		DMA_CLRACTIVE(header);	/* flag DMA done */
209030391Skarels 		return;
209130391Skarels 	}
209230391Skarels 
209330391Skarels 	if (request->DMAdone & COUNT_ZERO) {
2094*34642Smarc 		dga->csr &= ~SET_DONE_FIFO;
2095*34642Smarc 	}
2096*34642Smarc 	else if (request->DMAdone & FIFO_EMPTY) {
2097*34642Smarc 		dga->csr |= SET_DONE_FIFO;
209830391Skarels 	}
209930391Skarels 
210030391Skarels 	if (request->DMAdone & WORD_PACK)
210130391Skarels 	    dga->csr &= ~BYTE_DMA;
210230391Skarels 	else if (request->DMAdone & BYTE_PACK)
210330391Skarels 	    dga->csr |= BYTE_DMA;
210430391Skarels 
210530391Skarels 	dga->csr |= DMA_IE;
2106*34642Smarc 	QDlast_DMAtype = request->DMAtype;
210730391Skarels 
210830391Skarels 	cookie = ((int)request->bufp - (int)header) + (int)header->QBAreg;
210930391Skarels 
211030391Skarels 	dga->adrs_lo = (short) cookie;
211130391Skarels 	dga->adrs_hi = (short) (cookie >> 16);
211230391Skarels 
211330391Skarels 	dga->bytcnt_lo = (short) request->length;
211430391Skarels 	dga->bytcnt_hi = (short) (request->length >> 16);
211530391Skarels 
211630391Skarels 	return;
211730391Skarels }
211830391Skarels 
211930391Skarels /*****************************************************************
212030391Skarels *
212130391Skarels *	qdaint()... ADDER interrupt service
212230391Skarels *
212330391Skarels *****************************************************************/
212434615Smarc int Nqdaint;
212530391Skarels 
212630391Skarels qdaint(qd)
2127*34642Smarc 	register int qd;
212830391Skarels {
212930391Skarels 	register struct adder *adder;
213030391Skarels 	struct color_buf *cbuf;
213130391Skarels 
213230391Skarels 	short stat;
213330391Skarels 	int i;
213430391Skarels 	register struct rgb *rgbp;
213530391Skarels 	register short *red;
213630391Skarels 	register short *green;
213730391Skarels 	register short *blue;
213830391Skarels 
213930391Skarels 	spl4(); 			/* allow interval timer in */
214034615Smarc 	Nqdaint++;			/* debug */
214130391Skarels 
214230391Skarels 	adder = (struct adder *) qdmap[qd].adder;
214330391Skarels 
2144*34642Smarc 	/*
2145*34642Smarc 	* service the vertical blank interrupt (VSYNC bit) by loading
2146*34642Smarc 	* any pending color map load request
2147*34642Smarc 	*/
214830391Skarels 	if (adder->status & VSYNC) {
2149*34642Smarc 		adder->status &= ~VSYNC;	/* clear the interrupt */
2150*34642Smarc 		cbuf = color_buf[qd];
2151*34642Smarc 		if (cbuf->status & LOAD_COLOR_MAP) {
215230391Skarels 
2153*34642Smarc 			red = (short *) qdmap[qd].red;
2154*34642Smarc 			green = (short *) qdmap[qd].green;
2155*34642Smarc 			blue = (short *) qdmap[qd].blue;
215630391Skarels 
2157*34642Smarc 			for (i = cbuf->count, rgbp = cbuf->rgb;
2158*34642Smarc 			     --i >= 0; rgbp++) {
2159*34642Smarc 				red[rgbp->offset] = (short) rgbp->red;
2160*34642Smarc 				green[rgbp->offset] = (short) rgbp->green;
2161*34642Smarc 				blue[rgbp->offset] = (short) rgbp->blue;
2162*34642Smarc 			}
216330391Skarels 
2164*34642Smarc 			cbuf->status &= ~LOAD_COLOR_MAP;
216530391Skarels 		}
216630391Skarels 	}
216730391Skarels 
2168*34642Smarc 	/*
2169*34642Smarc 	* service the scroll interrupt (FRAME_SYNC bit)
2170*34642Smarc 	*/
217130391Skarels 	if (adder->status & FRAME_SYNC) {
2172*34642Smarc 		adder->status &= ~FRAME_SYNC;	/* clear the interrupt */
217330391Skarels 
2174*34642Smarc 		if (scroll[qd]->status & LOAD_REGS) {
217530391Skarels 
2176*34642Smarc 			for ( i = 1000, adder->status = 0; i > 0
2177*34642Smarc 			      &&  !((stat = adder->status) & ID_SCROLL_READY);
2178*34642Smarc 			      --i)
2179*34642Smarc 			      ;
218030391Skarels 
2181*34642Smarc 			if (i == 0) {
2182*34642Smarc 			    printf("\nqd%d: qdaint: timeout on ID_SCROLL_READY",
2183*34642Smarc 				qd);
2184*34642Smarc 				return;
2185*34642Smarc 			}
218630391Skarels 
2187*34642Smarc 			adder->ID_scroll_data = scroll[qd]->viper_constant;
2188*34642Smarc 			adder->ID_scroll_command = ID_LOAD | SCROLL_CONSTANT;
218930391Skarels 
2190*34642Smarc 			adder->y_scroll_constant =
2191*34642Smarc 				scroll[qd]->y_scroll_constant;
2192*34642Smarc 			adder->y_offset_pending = scroll[qd]->y_offset;
219330391Skarels 
2194*34642Smarc 			if (scroll[qd]->status & LOAD_INDEX) {
219530391Skarels 
2196*34642Smarc 				adder->x_index_pending =
2197*34642Smarc 					scroll[qd]->x_index_pending;
2198*34642Smarc 				adder->y_index_pending =
2199*34642Smarc 					scroll[qd]->y_index_pending;
2200*34642Smarc 			}
2201*34642Smarc 
2202*34642Smarc 			scroll[qd]->status = 0x00;
220330391Skarels 		}
220430391Skarels 	}
220530391Skarels }
220630391Skarels 
220730391Skarels /*****************************************************************
220830391Skarels *
220930391Skarels *	qdiint()... DUART input interrupt service routine
221030391Skarels *
2211*34642Smarc *	XXX - this routine should be broken out - it is essentially
2212*34642Smarc *	      straight line code.
2213*34642Smarc *
221430391Skarels *****************************************************************/
221530391Skarels 
221630391Skarels qdiint(qd)
2217*34642Smarc 	register int qd;
221830391Skarels {
221930391Skarels 	register struct _vs_event *event;
222030391Skarels 	register struct qdinput *eqh;
222130391Skarels 
222230391Skarels 	struct dga *dga;
222330391Skarels 	struct duart *duart;
222430391Skarels 	struct mouse_report *new_rep;
222530391Skarels 
222630391Skarels 	struct uba_device *ui;
222730391Skarels 	struct tty *tp;
222830391Skarels 
222934615Smarc 	u_short chr;
223030391Skarels 	int i,j;
223130391Skarels 	int k,l;
223230391Skarels 
223330391Skarels 	u_short status;
223430391Skarels 	u_short data;
223530391Skarels 	u_short key;
223630391Skarels 
223730391Skarels 	char do_wakeup = 0;		/* flag to do a select wakeup call */
223830391Skarels 	char a, b, c;			/* mouse button test variables */
223930391Skarels 
224030391Skarels 	spl4(); 			/* allow interval timer in */
224130391Skarels 
224230391Skarels 	eqh = eq_header[qd];		/* optimized as a register */
224330391Skarels 	new_rep = &current_rep[qd];
224430391Skarels 	duart = (struct duart *) qdmap[qd].duart;
224530391Skarels 
2246*34642Smarc 	/*
2247*34642Smarc 	* if the graphic device is turned on..	*/
224830391Skarels 
224930391Skarels 	if (qdflags[qd].inuse & GRAPHIC_DEV) {
225030391Skarels 
2251*34642Smarc 		/*
2252*34642Smarc 		* empty DUART
2253*34642Smarc 		*/
2254*34642Smarc 		while ((status = duart->statusA) & RCV_RDY	||
2255*34642Smarc 		    (status = duart->statusB) & RCV_RDY) {
225630391Skarels 
2257*34642Smarc 			/*
2258*34642Smarc 			* pick up LK-201 input (if any) */
225930391Skarels 
2260*34642Smarc 			if ((status = duart->statusA) & RCV_RDY) {
226130391Skarels 
2262*34642Smarc 				/* if error condition, then reset it */
226330391Skarels 
2264*34642Smarc 				if ((status = duart->statusA) & 0x70) {
2265*34642Smarc 					duart->cmdA = 0x40;
2266*34642Smarc 					continue;
2267*34642Smarc 				}
226830391Skarels 
2269*34642Smarc 				/* event queue full now? (overflow condition) */
227030391Skarels 
2271*34642Smarc 				if (ISFULL(eqh) == TRUE) {
2272*34642Smarc 					printf(
2273*34642Smarc 					 "\nqd%d: qdiint: event queue overflow",
2274*34642Smarc 					   qd);
2275*34642Smarc 					break;
2276*34642Smarc 				}
227730391Skarels 
2278*34642Smarc 				/*
2279*34642Smarc 				* Check for various keyboard errors  */
228030391Skarels 
2281*34642Smarc 				key = duart->dataA & 0xFF;
228230391Skarels 
2283*34642Smarc 				if (key==LK_POWER_ERROR ||
2284*34642Smarc 				    key==LK_KDOWN_ERROR ||
2285*34642Smarc 				    key == LK_INPUT_ERROR ||
2286*34642Smarc 				    key == LK_OUTPUT_ERROR) {
2287*34642Smarc 					printf(
2288*34642Smarc 				    "\nqd%d: qdiint: keyboard error, code = %x",
2289*34642Smarc 					qd,key);
2290*34642Smarc 					return(0);
2291*34642Smarc 				}
229230391Skarels 
2293*34642Smarc 				if (key < LK_LOWEST)
2294*34642Smarc 				    return(0);
229530391Skarels 
2296*34642Smarc 				++do_wakeup;  /* request a select wakeup call */
229730391Skarels 
2298*34642Smarc 				event = PUTBEGIN(eqh);
2299*34642Smarc 				PUTEND(eqh);
230030391Skarels 
2301*34642Smarc 				event->vse_key = key;
2302*34642Smarc 				event->vse_key &= 0x00FF;
2303*34642Smarc 				event->vse_x = eqh->curs_pos.x;
2304*34642Smarc 				event->vse_y = eqh->curs_pos.y;
2305*34642Smarc 				event->vse_time = TOY;
2306*34642Smarc 				event->vse_type = VSE_BUTTON;
2307*34642Smarc 				event->vse_direction = VSE_KBTRAW;
2308*34642Smarc 				event->vse_device = VSE_DKB;
2309*34642Smarc 			}
231030391Skarels 
2311*34642Smarc 			/*
2312*34642Smarc 			* pick up the mouse input (if any)  */
231330391Skarels 
2314*34642Smarc 			if ((status = duart->statusB) & RCV_RDY  &&
2315*34642Smarc 			    qdflags[qd].pntr_id == MOUSE_ID) {
231630391Skarels 
2317*34642Smarc 				if (status & 0x70) {
2318*34642Smarc 					duart->cmdB = 0x40;
2319*34642Smarc 					continue;
2320*34642Smarc 				}
232130391Skarels 
2322*34642Smarc 				/* event queue full now? (overflow condition) */
232330391Skarels 
2324*34642Smarc 				if (ISFULL(eqh) == TRUE) {
2325*34642Smarc 					printf(
2326*34642Smarc 					"\nqd%d: qdiint: event queue overflow",
2327*34642Smarc 					     qd);
2328*34642Smarc 					break;
2329*34642Smarc 				}
233030391Skarels 
2331*34642Smarc 				data = duart->dataB;      /* get report byte */
2332*34642Smarc 				++new_rep->bytcnt; /* bump report byte count */
233330391Skarels 
2334*34642Smarc 				/*
2335*34642Smarc 				* if 1st byte of report.. */
233630391Skarels 
2337*34642Smarc 				if ( data & START_FRAME) {
2338*34642Smarc 					new_rep->state = data;
2339*34642Smarc 					if (new_rep->bytcnt > 1) {
2340*34642Smarc 						/* start of new frame */
2341*34642Smarc 						new_rep->bytcnt = 1;
2342*34642Smarc 						/* ..continue looking */
2343*34642Smarc 						continue;
2344*34642Smarc 					}
2345*34642Smarc 				}
234630391Skarels 
2347*34642Smarc 				/*
2348*34642Smarc 				* if 2nd byte of report.. */
234930391Skarels 
2350*34642Smarc 				else if (new_rep->bytcnt == 2) {
2351*34642Smarc 					new_rep->dx = data & 0x00FF;
2352*34642Smarc 				}
235330391Skarels 
2354*34642Smarc 				/*
2355*34642Smarc 				* if 3rd byte of report, load input event queue */
235630391Skarels 
2357*34642Smarc 				else if (new_rep->bytcnt == 3) {
235830391Skarels 
2359*34642Smarc 					new_rep->dy = data & 0x00FF;
2360*34642Smarc 					new_rep->bytcnt = 0;
236130391Skarels 
2362*34642Smarc 					/*
2363*34642Smarc 					* if mouse position has changed.. */
236430391Skarels 
2365*34642Smarc 					if (new_rep->dx != 0  ||  new_rep->dy != 0) {
236630391Skarels 
2367*34642Smarc 						/*
2368*34642Smarc 						* calculate acceleration factor, if needed	*/
236930391Skarels 
2370*34642Smarc 						if (qdflags[qd].curs_acc > ACC_OFF) {
237130391Skarels 
2372*34642Smarc 							if (qdflags[qd].curs_thr <= new_rep->dx)
2373*34642Smarc 							    new_rep->dx +=
2374*34642Smarc 							    (new_rep->dx - qdflags[qd].curs_thr)
2375*34642Smarc 							    * qdflags[qd].curs_acc;
237630391Skarels 
2377*34642Smarc 							if (qdflags[qd].curs_thr <= new_rep->dy)
2378*34642Smarc 							    new_rep->dy +=
2379*34642Smarc 							    (new_rep->dy - qdflags[qd].curs_thr)
2380*34642Smarc 							    * qdflags[qd].curs_acc;
2381*34642Smarc 						}
238230391Skarels 
2383*34642Smarc 						/*
2384*34642Smarc 						* update cursor position coordinates */
238530391Skarels 
2386*34642Smarc 						if (new_rep->state & X_SIGN) {
2387*34642Smarc 							eqh->curs_pos.x += new_rep->dx;
2388*34642Smarc 							if (eqh->curs_pos.x > 1023)
2389*34642Smarc 							    eqh->curs_pos.x = 1023;
2390*34642Smarc 						}
2391*34642Smarc 						else {
2392*34642Smarc 							eqh->curs_pos.x -= new_rep->dx;
2393*34642Smarc 							if (eqh->curs_pos.x < -15)
2394*34642Smarc 							    eqh->curs_pos.x = -15;
2395*34642Smarc 						}
239630391Skarels 
2397*34642Smarc 						if (new_rep->state & Y_SIGN) {
2398*34642Smarc 							eqh->curs_pos.y -= new_rep->dy;
2399*34642Smarc 							if (eqh->curs_pos.y < -15)
2400*34642Smarc 							    eqh->curs_pos.y = -15;
2401*34642Smarc 						}
2402*34642Smarc 						else {
2403*34642Smarc 							eqh->curs_pos.y += new_rep->dy;
2404*34642Smarc 							if (eqh->curs_pos.y > 863)
2405*34642Smarc 							    eqh->curs_pos.y = 863;
2406*34642Smarc 						}
240730391Skarels 
2408*34642Smarc 						/*
2409*34642Smarc 						* update cursor screen position */
241030391Skarels 
2411*34642Smarc 						dga = (struct dga *) qdmap[qd].dga;
2412*34642Smarc 						dga->x_cursor = TRANX(eqh->curs_pos.x);
2413*34642Smarc 						dga->y_cursor = TRANY(eqh->curs_pos.y);
241430391Skarels 
2415*34642Smarc 						/*
2416*34642Smarc 						* if cursor is in the box, no event report */
241730391Skarels 
2418*34642Smarc 						if (eqh->curs_pos.x <= eqh->curs_box.right	&&
2419*34642Smarc 						    eqh->curs_pos.x >= eqh->curs_box.left  &&
2420*34642Smarc 						    eqh->curs_pos.y >= eqh->curs_box.top  &&
2421*34642Smarc 						    eqh->curs_pos.y <= eqh->curs_box.bottom ) {
2422*34642Smarc 							goto GET_MBUTTON;
2423*34642Smarc 						}
242430391Skarels 
2425*34642Smarc 						/*
2426*34642Smarc 						* report the mouse motion event */
242730391Skarels 
2428*34642Smarc 						event = PUTBEGIN(eqh);
2429*34642Smarc 						PUTEND(eqh);
243030391Skarels 
2431*34642Smarc 						++do_wakeup;   /* request a select wakeup call */
243230391Skarels 
2433*34642Smarc 						event->vse_x = eqh->curs_pos.x;
2434*34642Smarc 						event->vse_y = eqh->curs_pos.y;
243530391Skarels 
2436*34642Smarc 						event->vse_device = VSE_MOUSE;  /* mouse */
2437*34642Smarc 						event->vse_type = VSE_MMOTION;  /* pos changed */
2438*34642Smarc 						event->vse_key = 0;
2439*34642Smarc 						event->vse_direction = 0;
2440*34642Smarc 						event->vse_time = TOY;	/* time stamp */
2441*34642Smarc 					}
244230391Skarels 
244330391Skarels GET_MBUTTON:
2444*34642Smarc 					/*
2445*34642Smarc 					* if button state has changed */
244630391Skarels 
2447*34642Smarc 					a = new_rep->state & 0x07;    /*mask nonbutton bits */
2448*34642Smarc 					b = last_rep[qd].state & 0x07;
244930391Skarels 
2450*34642Smarc 					if (a ^ b) {
245130391Skarels 
2452*34642Smarc 						for ( c = 1;  c < 8; c <<= 1) {
245330391Skarels 
2454*34642Smarc 							if (!( c & (a ^ b))) /* this button change? */
2455*34642Smarc 							    continue;
245630391Skarels 
2457*34642Smarc 							/* event queue full? (overflow condition) */
245830391Skarels 
2459*34642Smarc 							if (ISFULL(eqh) == TRUE) {
2460*34642Smarc 								printf("\nqd%d: qdiint: event queue overflow", qd);
2461*34642Smarc 								break;
2462*34642Smarc 							}
246330391Skarels 
2464*34642Smarc 							event = PUTBEGIN(eqh);	/* get new event */
2465*34642Smarc 							PUTEND(eqh);
246630391Skarels 
2467*34642Smarc 							++do_wakeup;   /* request select wakeup */
246830391Skarels 
2469*34642Smarc 							event->vse_x = eqh->curs_pos.x;
2470*34642Smarc 							event->vse_y = eqh->curs_pos.y;
247130391Skarels 
2472*34642Smarc 							event->vse_device = VSE_MOUSE;	/* mouse */
2473*34642Smarc 							event->vse_type = VSE_BUTTON; /* new button */
2474*34642Smarc 							event->vse_time = TOY;	      /* time stamp */
247530391Skarels 
2476*34642Smarc 							/* flag changed button and if up or down */
247730391Skarels 
2478*34642Smarc 							if (c == RIGHT_BUTTON)
2479*34642Smarc 							    event->vse_key = VSE_RIGHT_BUTTON;
2480*34642Smarc 							else if (c == MIDDLE_BUTTON)
2481*34642Smarc 							    event->vse_key = VSE_MIDDLE_BUTTON;
2482*34642Smarc 							else if (c == LEFT_BUTTON)
2483*34642Smarc 							    event->vse_key = VSE_LEFT_BUTTON;
248430391Skarels 
2485*34642Smarc 							/* set bit = button depressed */
248630391Skarels 
2487*34642Smarc 							if (c & a)
2488*34642Smarc 							    event->vse_direction = VSE_KBTDOWN;
2489*34642Smarc 							else
2490*34642Smarc 								event->vse_direction = VSE_KBTUP;
2491*34642Smarc 						}
2492*34642Smarc 					}
249330391Skarels 
2494*34642Smarc 					/* refresh last report */
249530391Skarels 
2496*34642Smarc 					last_rep[qd] = current_rep[qd];
249730391Skarels 
2498*34642Smarc 				}  /* get last byte of report */
2499*34642Smarc 			} /* pickup mouse input */
250030391Skarels 
2501*34642Smarc 			/*
2502*34642Smarc 			* pickup tablet input, if any  */
250330391Skarels 
2504*34642Smarc 			else if ((status = duart->statusB) & RCV_RDY  &&
2505*34642Smarc 			    qdflags[qd].pntr_id == TABLET_ID) {
250630391Skarels 
2507*34642Smarc 				if (status & 0x70) {
2508*34642Smarc 					duart->cmdB = 0x40;
2509*34642Smarc 					continue;
2510*34642Smarc 				}
251130391Skarels 
2512*34642Smarc 				/* event queue full now? (overflow condition) */
251330391Skarels 
2514*34642Smarc 				if (ISFULL(eqh) == TRUE) {
2515*34642Smarc 					printf("\nqd%d: qdiint: event queue overflow", qd);
2516*34642Smarc 					break;
2517*34642Smarc 				}
251830391Skarels 
2519*34642Smarc 				data = duart->dataB;      /* get report byte */
2520*34642Smarc 				++new_rep->bytcnt;	      /* bump report byte count */
252130391Skarels 
2522*34642Smarc 				/*
2523*34642Smarc 				* if 1st byte of report.. */
252430391Skarels 
2525*34642Smarc 				if (data & START_FRAME) {
2526*34642Smarc 					new_rep->state = data;
2527*34642Smarc 					if (new_rep->bytcnt > 1) {
2528*34642Smarc 						new_rep->bytcnt = 1;    /* start of new frame */
2529*34642Smarc 						continue;		    /* ..continue looking */
2530*34642Smarc 					}
2531*34642Smarc 				}
253230391Skarels 
2533*34642Smarc 				/*
2534*34642Smarc 				* if 2nd byte of report.. */
253530391Skarels 
2536*34642Smarc 				else if (new_rep->bytcnt == 2) {
2537*34642Smarc 					new_rep->dx = data & 0x3F;
2538*34642Smarc 				}
253930391Skarels 
2540*34642Smarc 				/*
2541*34642Smarc 				* if 3rd byte of report.. */
254230391Skarels 
2543*34642Smarc 				else if (new_rep->bytcnt == 3) {
2544*34642Smarc 					new_rep->dx |= (data & 0x3F) << 6;
2545*34642Smarc 				}
254630391Skarels 
2547*34642Smarc 				/*
2548*34642Smarc 				* if 4th byte of report.. */
254930391Skarels 
2550*34642Smarc 				else if (new_rep->bytcnt == 4) {
2551*34642Smarc 					new_rep->dy = data & 0x3F;
2552*34642Smarc 				}
255330391Skarels 
2554*34642Smarc 				/*
2555*34642Smarc 				* if 5th byte of report, load input event queue */
255630391Skarels 
2557*34642Smarc 				else if (new_rep->bytcnt == 5) {
255830391Skarels 
2559*34642Smarc 					new_rep->dy |= (data & 0x3F) << 6;
2560*34642Smarc 					new_rep->bytcnt = 0;
256130391Skarels 
2562*34642Smarc 					/*
2563*34642Smarc 					* update cursor position coordinates */
256430391Skarels 
2565*34642Smarc 					new_rep->dx /= qdflags[qd].tab_res;
2566*34642Smarc 					new_rep->dy = (2200 - new_rep->dy)
2567*34642Smarc 					    / qdflags[qd].tab_res;
256830391Skarels 
2569*34642Smarc 					if (new_rep->dx > 1023) {
2570*34642Smarc 						new_rep->dx = 1023;
2571*34642Smarc 					}
2572*34642Smarc 					if (new_rep->dy > 863) {
2573*34642Smarc 						new_rep->dy = 863;
2574*34642Smarc 					}
257530391Skarels 
2576*34642Smarc 					/*
2577*34642Smarc 					* report an event if the puck/stylus has moved
2578*34642Smarc 					*/
257930391Skarels 
2580*34642Smarc 					if (eqh->curs_pos.x != new_rep->dx ||
2581*34642Smarc 					    eqh->curs_pos.y != new_rep->dy) {
258230391Skarels 
2583*34642Smarc 						eqh->curs_pos.x = new_rep->dx;
2584*34642Smarc 						eqh->curs_pos.y = new_rep->dy;
258530391Skarels 
2586*34642Smarc 						/*
2587*34642Smarc 						* update cursor screen position */
258830391Skarels 
2589*34642Smarc 						dga = (struct dga *) qdmap[qd].dga;
2590*34642Smarc 						dga->x_cursor = TRANX(eqh->curs_pos.x);
2591*34642Smarc 						dga->y_cursor = TRANY(eqh->curs_pos.y);
259230391Skarels 
2593*34642Smarc 						/*
2594*34642Smarc 						* if cursor is in the box, no event report
2595*34642Smarc 						*/
259630391Skarels 
2597*34642Smarc 						if (eqh->curs_pos.x <= eqh->curs_box.right	&&
2598*34642Smarc 						    eqh->curs_pos.x >= eqh->curs_box.left  &&
2599*34642Smarc 						    eqh->curs_pos.y >= eqh->curs_box.top  &&
2600*34642Smarc 						    eqh->curs_pos.y <= eqh->curs_box.bottom ) {
2601*34642Smarc 							goto GET_TBUTTON;
2602*34642Smarc 						}
260330391Skarels 
2604*34642Smarc 						/*
2605*34642Smarc 						* report the tablet motion event */
260630391Skarels 
2607*34642Smarc 						event = PUTBEGIN(eqh);
2608*34642Smarc 						PUTEND(eqh);
260930391Skarels 
2610*34642Smarc 						++do_wakeup;   /* request a select wakeup call */
261130391Skarels 
2612*34642Smarc 						event->vse_x = eqh->curs_pos.x;
2613*34642Smarc 						event->vse_y = eqh->curs_pos.y;
261430391Skarels 
2615*34642Smarc 						event->vse_device = VSE_TABLET;  /* tablet */
2616*34642Smarc 						/*
2617*34642Smarc 						* right now, X handles tablet motion the same
2618*34642Smarc 						* as mouse motion
2619*34642Smarc 						*/
2620*34642Smarc 						event->vse_type = VSE_MMOTION;   /* pos changed */
2621*34642Smarc 						event->vse_key = 0;
2622*34642Smarc 						event->vse_direction = 0;
2623*34642Smarc 						event->vse_time = TOY;	/* time stamp */
2624*34642Smarc 					}
262530391Skarels GET_TBUTTON:
2626*34642Smarc 					/*
2627*34642Smarc 					* if button state has changed */
262830391Skarels 
2629*34642Smarc 					a = new_rep->state & 0x1E;   /* mask nonbutton bits */
2630*34642Smarc 					b = last_rep[qd].state & 0x1E;
263130391Skarels 
2632*34642Smarc 					if (a ^ b) {
263330391Skarels 
2634*34642Smarc 						/* event queue full now? (overflow condition) */
263530391Skarels 
2636*34642Smarc 						if (ISFULL(eqh) == TRUE) {
2637*34642Smarc 							printf("\nqd%d: qdiint: event queue overflow",qd);
2638*34642Smarc 							break;
2639*34642Smarc 						}
264030391Skarels 
2641*34642Smarc 						event = PUTBEGIN(eqh);  /* get new event */
2642*34642Smarc 						PUTEND(eqh);
264330391Skarels 
2644*34642Smarc 						++do_wakeup;   /* request a select wakeup call */
264530391Skarels 
2646*34642Smarc 						event->vse_x = eqh->curs_pos.x;
2647*34642Smarc 						event->vse_y = eqh->curs_pos.y;
264830391Skarels 
2649*34642Smarc 						event->vse_device = VSE_TABLET;  /* tablet */
2650*34642Smarc 						event->vse_type = VSE_BUTTON; /* button changed */
2651*34642Smarc 						event->vse_time = TOY;	   /* time stamp */
265230391Skarels 
2653*34642Smarc 						/* define the changed button and if up or down */
265430391Skarels 
2655*34642Smarc 						for ( c = 1;  c <= 0x10; c <<= 1) {
2656*34642Smarc 							if (c & (a ^ b)) {
2657*34642Smarc 								if (c == T_LEFT_BUTTON)
2658*34642Smarc 								    event->vse_key = VSE_T_LEFT_BUTTON;
2659*34642Smarc 								else if (c == T_FRONT_BUTTON)
2660*34642Smarc 								    event->vse_key = VSE_T_FRONT_BUTTON;
2661*34642Smarc 								else if (c == T_RIGHT_BUTTON)
2662*34642Smarc 								    event->vse_key = VSE_T_RIGHT_BUTTON;
2663*34642Smarc 								else if (c == T_BACK_BUTTON)
2664*34642Smarc 								    event->vse_key = VSE_T_BACK_BUTTON;
2665*34642Smarc 								break;
2666*34642Smarc 							}
2667*34642Smarc 						}
266830391Skarels 
2669*34642Smarc 						/* set bit = button depressed */
267030391Skarels 
2671*34642Smarc 						if (c & a)
2672*34642Smarc 						    event->vse_direction = VSE_KBTDOWN;
2673*34642Smarc 						else
2674*34642Smarc 							event->vse_direction = VSE_KBTUP;
2675*34642Smarc 					}
267630391Skarels 
2677*34642Smarc 					/* refresh last report */
267830391Skarels 
2679*34642Smarc 					last_rep[qd] = current_rep[qd];
268030391Skarels 
2681*34642Smarc 				} /* get last byte of report */
2682*34642Smarc 			} /* pick up tablet input */
268330391Skarels 
2684*34642Smarc 		} /* while input available.. */
268530391Skarels 
2686*34642Smarc 		/*
2687*34642Smarc 		* do select wakeup
2688*34642Smarc 		*/
2689*34642Smarc 		if (rsel[qd] && do_wakeup && qdflags[qd].selmask & SEL_READ) {
2690*34642Smarc 			selwakeup(rsel[qd], 0);
2691*34642Smarc 			rsel[qd] = 0;
2692*34642Smarc 			qdflags[qd].selmask &= ~SEL_READ;
2693*34642Smarc 			do_wakeup = 0;
2694*34642Smarc 		}
269530391Skarels 	}
269630391Skarels 
2697*34642Smarc 	/*
2698*34642Smarc 	* if the graphic device is not turned on, this is console input */
269930391Skarels 
270030391Skarels 	else {
270130391Skarels 
2702*34642Smarc 		ui = qdinfo[qd];
2703*34642Smarc 		if (ui == 0 || ui->ui_alive == 0)
2704*34642Smarc 		    return(0);
270530391Skarels 
2706*34642Smarc 		tp = &qd_tty[qd << 2];
270730391Skarels 
2708*34642Smarc 		/*
2709*34642Smarc 		* Get a character from the keyboard. */
271030391Skarels 
2711*34642Smarc 		while ((status = duart->statusA) & RCV_RDY) {
271230391Skarels 
2713*34642Smarc 			key = duart->dataA;
2714*34642Smarc 			key &= 0xFF;
271530391Skarels 
2716*34642Smarc 			/*
2717*34642Smarc 			* Check for various keyboard errors  */
271830391Skarels 
2719*34642Smarc 			if( key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
2720*34642Smarc 			    key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
2721*34642Smarc 				printf("\nqd%d: qdiint: Keyboard error, code = %x",qd,key);
2722*34642Smarc 				return(0);
2723*34642Smarc 			}
272430391Skarels 
2725*34642Smarc 			if (key < LK_LOWEST)
2726*34642Smarc 			    return(0);
272730391Skarels 
2728*34642Smarc 			/*
2729*34642Smarc 			* See if its a state change key */
273030391Skarels 
2731*34642Smarc 			switch (key) {
273230391Skarels 
2733*34642Smarc 			case LOCK:
2734*34642Smarc 				q_keyboard.lock ^= 0xffff;	/* toggle */
2735*34642Smarc 				if (q_keyboard.lock)
2736*34642Smarc 				    led_control(qd, LK_LED_ENABLE, LK_LED_LOCK);
2737*34642Smarc 				else
2738*34642Smarc 					led_control(qd, LK_LED_DISABLE, LK_LED_LOCK);
2739*34642Smarc 				return;
274030391Skarels 
2741*34642Smarc 			case SHIFT:
2742*34642Smarc 				q_keyboard.shift ^= 0xFFFF;
2743*34642Smarc 				return;
274430391Skarels 
2745*34642Smarc 			case CNTRL:
2746*34642Smarc 				q_keyboard.cntrl ^= 0xFFFF;
2747*34642Smarc 				return;
274830391Skarels 
2749*34642Smarc 			case ALLUP:
2750*34642Smarc 				q_keyboard.cntrl = 0;
2751*34642Smarc 				q_keyboard.shift = 0;
2752*34642Smarc 				return;
275330391Skarels 
2754*34642Smarc 			case REPEAT:
2755*34642Smarc 				chr = q_keyboard.last;
2756*34642Smarc 				break;
275730391Skarels 
2758*34642Smarc 				/*
2759*34642Smarc 				* Test for cntrl characters. If set, see if the character
2760*34642Smarc 				* is elligible to become a control character. */
276130391Skarels 
2762*34642Smarc 			default:
276330391Skarels 
2764*34642Smarc 				if (q_keyboard.cntrl) {
2765*34642Smarc 					chr = q_key[key];
2766*34642Smarc 					if (chr >= ' ' && chr <= '~')
2767*34642Smarc 					    chr &= 0x1F;
2768*34642Smarc 					else if (chr >= 0xA1 && chr <= 0xFE)
2769*34642Smarc 					    chr &= 0x9F;
2770*34642Smarc 				}
2771*34642Smarc 				else if( q_keyboard.lock || q_keyboard.shift )
2772*34642Smarc 				    chr = q_shift_key[key];
2773*34642Smarc 				else
2774*34642Smarc 					chr = q_key[key];
2775*34642Smarc 				break;
277630391Skarels 			}
277730391Skarels 
2778*34642Smarc 			q_keyboard.last = chr;
277930391Skarels 
2780*34642Smarc 			/*
2781*34642Smarc 			* Check for special function keys */
278230391Skarels 
2783*34642Smarc 			if (chr & 0x100) {
2784*34642Smarc 				char *string;
2785*34642Smarc 				string = q_special[chr & 0x7F];
2786*34642Smarc 				while(*string)
2787*34642Smarc 				    (*linesw[tp->t_line].l_rint)(*string++, tp);
278834615Smarc 			}
2789*34642Smarc 			else {
2790*34642Smarc 				(*linesw[tp->t_line].l_rint)(chr&0177, tp);
2791*34642Smarc 			}
279230391Skarels 		}
279330391Skarels 	}
279430391Skarels 
2795*34642Smarc 	/*
2796*34642Smarc 	* cleanup and exit  */
279734615Smarc 
279830391Skarels 	return(0);
279930391Skarels 
280030391Skarels } /* qdiint */
280130391Skarels 
280230391Skarels /******************************************************************
280334615Smarc *******************************************************************
280434615Smarc *******************************************************************
280530391Skarels *
280630391Skarels *	THE SUBROUTINES START HERE:
280730391Skarels *
280830391Skarels ******************************************************************/
280930391Skarels 
281030391Skarels /*****************************************************************
281130391Skarels *
281230391Skarels *	clear_qd_screen()... clear the QDSS screen
281330391Skarels *
281430391Skarels ******************************************************************
281530391Skarels *
281630391Skarels *			     >>> NOTE <<<
281730391Skarels *
281830391Skarels *   This code requires that certain adder initialization be valid.  To
281930391Skarels *   assure that this requirement is satisfied, this routine should be
282030391Skarels *   called only after calling the "setup_dragon()" function.
282130391Skarels *
282230391Skarels *   Clear the bitmap a piece at a time. Since the fast scroll clear
282330391Skarels *   only clears the current displayed portion of the bitmap put a
282430391Skarels *   temporary value in the y limit register so we can access whole
282530391Skarels *   bitmap
282630391Skarels *
282730391Skarels ****************/
282830391Skarels 
282930391Skarels clear_qd_screen(unit)
283030391Skarels int unit;
283130391Skarels {
283230391Skarels 	register struct adder *adder;
283330391Skarels 	adder = (struct adder *) qdmap[unit].adder;
283430391Skarels 
283530391Skarels 	adder->x_limit = 1024;
283630391Skarels 	adder->y_limit = 2048 - CHAR_HEIGHT;
283730391Skarels 	adder->y_offset_pending = 0;
2838*34642Smarc #define WSV	wait_status(adder, VSYNC); wait_status(adder, VSYNC)
2839*34642Smarc 	WSV;
284030391Skarels 	adder->y_scroll_constant = SCROLL_ERASE;
2841*34642Smarc 	WSV;
284230391Skarels 	adder->y_offset_pending = 864;
2843*34642Smarc 	WSV;
284430391Skarels 	adder->y_scroll_constant = SCROLL_ERASE;
2845*34642Smarc 	WSV;
284630391Skarels 	adder->y_offset_pending = 1728;
2847*34642Smarc 	WSV;
284830391Skarels 	adder->y_scroll_constant = SCROLL_ERASE;
2849*34642Smarc 	WSV;
285030391Skarels 	adder->y_offset_pending = 0;	 /* back to normal */
2851*34642Smarc 	WSV;
285230391Skarels 	adder->x_limit = MAX_SCREEN_X;
285330391Skarels 	adder->y_limit = MAX_SCREEN_Y + FONT_HEIGHT;
2854*34642Smarc #undef WSV
285530391Skarels 
285630391Skarels } /* clear_qd_screen */
285730391Skarels 
285830391Skarels /**********************************************************************
285930391Skarels *
2860*34642Smarc *	qdputc()... route kernel console output to the glass tty
286130391Skarels *
286230391Skarels ***********************************************************************
286330391Skarels *
286430391Skarels *	calling convention:
286530391Skarels *
286630391Skarels *		qdputc(chr);
286730391Skarels *
286830391Skarels *	where:	char chr;	 ;character for output
286930391Skarels *
287030391Skarels ****************/
287130391Skarels 
287230391Skarels qdputc(chr)
2873*34642Smarc 	register char chr;
287430391Skarels {
287530391Skarels 
2876*34642Smarc 	/*
2877*34642Smarc 	 * if system is now physical, forget it (ie: crash DUMP)
2878*34642Smarc 	 */
2879*34642Smarc 	if ((mfpr(MAPEN) & 1) == 0)
2880*34642Smarc 		return;
288134615Smarc 
288234615Smarc 	blitc(0, chr & 0xff);
288332012Smarc 	if ((chr & 0177) == '\n')
288432012Smarc 		blitc(0, '\r');
288530391Skarels 
288630391Skarels } /* qdputc */
288730391Skarels 
288830391Skarels /*******************************************************************
288930391Skarels *
289030391Skarels *	qdgetc()... get a character from the LK201
289130391Skarels *
289230391Skarels *******************************************************************
289330391Skarels *
289430391Skarels *	calling convention:
289530391Skarels *
289630391Skarels *		qdgetc();
289730391Skarels *
289830391Skarels *	returns:  the character read.
289930391Skarels *
290030391Skarels ****************/
290130391Skarels 
290230391Skarels qdgetc()
290330391Skarels {
290430391Skarels 	register short key;
290530391Skarels 	register char chr;
290630391Skarels 	register struct duart *duart;
290730391Skarels 
290830391Skarels 	u_int status;
290930391Skarels 
291030391Skarels 	duart = (struct duart *) qdmap[0].duart;
291130391Skarels 
2912*34642Smarc 	/*
291330391Skarels 	* Get a character from the keyboard. */
291430391Skarels 
291530391Skarels LOOP:
291630391Skarels 	while (!((status = duart->statusA) & RCV_RDY))
2917*34642Smarc 	    ;
291830391Skarels 
291930391Skarels 	key = duart->dataA;
292030391Skarels 	key &= 0xFF;
292130391Skarels 
2922*34642Smarc 	/*
292330391Skarels 	* Check for various keyboard errors  */
292430391Skarels 
2925*34642Smarc 	if (key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
292630391Skarels 	    key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
292730391Skarels 		printf("Keyboard error, code = %x\n", key);
292830391Skarels 		return(0);
292930391Skarels 	}
293030391Skarels 
293130391Skarels 	if (key < LK_LOWEST)
293230391Skarels 	    return(0);
293330391Skarels 
2934*34642Smarc 	/*
293530391Skarels 	* See if its a state change key */
293630391Skarels 
293730391Skarels 	switch (key) {
293830391Skarels 
2939*34642Smarc 	case LOCK:
294030391Skarels 		q_keyboard.lock ^= 0xffff;	/* toggle */
294130391Skarels 		if (q_keyboard.lock)
294230391Skarels 		    led_control(LK_LED_ENABLE, LK_LED_LOCK);
294330391Skarels 		else
2944*34642Smarc 			led_control(LK_LED_DISABLE, LK_LED_LOCK);
294530391Skarels 		goto LOOP;
294630391Skarels 
2947*34642Smarc 	case SHIFT:
294830391Skarels 		q_keyboard.shift ^= 0xFFFF;
294930391Skarels 		goto LOOP;
295030391Skarels 
2951*34642Smarc 	case CNTRL:
295230391Skarels 		q_keyboard.cntrl ^= 0xFFFF;
295330391Skarels 		goto LOOP;
295430391Skarels 
2955*34642Smarc 	case ALLUP:
295630391Skarels 		q_keyboard.cntrl = 0;
295730391Skarels 		q_keyboard.shift = 0;
295830391Skarels 		goto LOOP;
295930391Skarels 
2960*34642Smarc 	case REPEAT:
296130391Skarels 		chr = q_keyboard.last;
296230391Skarels 		break;
296330391Skarels 
2964*34642Smarc 		/*
2965*34642Smarc 		* Test for cntrl characters. If set, see if the character
2966*34642Smarc 		* is elligible to become a control character. */
296730391Skarels 
2968*34642Smarc 	default:
296930391Skarels 
297030391Skarels 		if (q_keyboard.cntrl) {
2971*34642Smarc 			chr = q_key[key];
2972*34642Smarc 			if (chr >= ' ' && chr <= '~')
2973*34642Smarc 			    chr &= 0x1F;
297430391Skarels 		}
297530391Skarels 		else if ( q_keyboard.lock || q_keyboard.shift )
297630391Skarels 		    chr = q_shift_key[key];
297730391Skarels 		else
2978*34642Smarc 			chr = q_key[key];
297930391Skarels 		break;
298030391Skarels 	}
298130391Skarels 
298230391Skarels 	if (chr < ' ' && chr > '~')	/* if input is non-displayable */
2983*34642Smarc 		return(0);		/* ..then pitch it! */
298430391Skarels 
298530391Skarels 	q_keyboard.last = chr;
298630391Skarels 
2987*34642Smarc 	/*
298830391Skarels 	* Check for special function keys */
298930391Skarels 
299030391Skarels 	if (chr & 0x80) 		/* pitch the function keys */
2991*34642Smarc 		return(0);
299230391Skarels 	else
2993*34642Smarc 		return(chr);
299430391Skarels 
299530391Skarels } /* qdgetc */
299630391Skarels 
299730391Skarels /**********************************************************************
299830391Skarels *
299930391Skarels *	ldcursor()... load the mouse cursor's template RAM bitmap
300030391Skarels *
300130391Skarels *********************************************************************
300230391Skarels *
300330391Skarels *	calling convention:
300430391Skarels *
300530391Skarels *		ldcursor(unit, bitmap);
300630391Skarels *		u_int unit;
300730391Skarels *		short *bitmap;
300830391Skarels *
300930391Skarels ****************/
301030391Skarels 
301130391Skarels ldcursor(unit, bitmap)
3012*34642Smarc 	u_int unit;
3013*34642Smarc 	short *bitmap;
301430391Skarels {
301530391Skarels 	register struct dga *dga;
301630391Skarels 	register short *temp;
301730391Skarels 	register int i;
301830391Skarels 
301930391Skarels 	int cursor;
302030391Skarels 
302130391Skarels 	dga = (struct dga *) qdmap[unit].dga;
302230391Skarels 	temp = (short *) qdmap[unit].template;
302330391Skarels 
302430391Skarels 	if (dga->csr & CURS_ENB) {	/* if the cursor is enabled.. */
3025*34642Smarc 		cursor = -1;		/* ..note that.. */
3026*34642Smarc 		dga->csr &= ~CURS_ENB;	/* ..and shut it off */
302730391Skarels 	}
302830391Skarels 	else {
3029*34642Smarc 		cursor = 0;
303030391Skarels 	}
303130391Skarels 
303230391Skarels 	dga->csr &= ~CURS_ENB;		/* shut off the cursor */
303330391Skarels 
303430391Skarels 	temp += (8 * 1024) - 32;	/* cursor is 32 WORDS from the end */
3035*34642Smarc 	/* ..of the 8k WORD template space */
303630391Skarels 	for (i = 0; i < 32; ++i)
3037*34642Smarc 		*temp++ = *bitmap++;
303830391Skarels 
303930391Skarels 	if (cursor) {			/* if cursor was enabled.. */
3040*34642Smarc 		dga->csr |= CURS_ENB;	/* ..turn it back on */
304130391Skarels 	}
304230391Skarels 
304330391Skarels 	return(0);
304430391Skarels 
304530391Skarels } /* ldcursor */
304630391Skarels 
304730391Skarels /**********************************************************************
304830391Skarels *
304930391Skarels *	ldfont()... put the console font in the QDSS off-screen memory
305030391Skarels *
305130391Skarels ***********************************************************************
305230391Skarels *
305330391Skarels *	calling convention:
305430391Skarels *
305530391Skarels *		ldfont(unit);
305630391Skarels *		u_int unit;	;QDSS unit number
305730391Skarels *
305830391Skarels ****************/
305930391Skarels 
306030391Skarels ldfont(unit)
3061*34642Smarc 	u_int unit;
306230391Skarels {
306330391Skarels 	register struct adder *adder;
306430391Skarels 
306530391Skarels 	int i;		/* scratch variables */
306630391Skarels 	int j;
306730391Skarels 	int k;
306830391Skarels 	short packed;
306934615Smarc 	int max_chars_line;
307030391Skarels 
307130391Skarels 	adder = (struct adder *) qdmap[unit].adder;
307230391Skarels 
3073*34642Smarc 	/*
3074*34642Smarc 	* setup VIPER operand control registers  */
307530391Skarels 
307630391Skarels 	write_ID(adder, MASK_1, 0xFFFF);
307730391Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
307830391Skarels 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
307930391Skarels 
308030391Skarels 	write_ID(adder, SRC1_OCR_B,
3081*34642Smarc 	EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY);
308230391Skarels 	write_ID(adder, SRC2_OCR_B,
3083*34642Smarc 	EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY);
308430391Skarels 	write_ID(adder, DST_OCR_B,
3085*34642Smarc 	EXT_SOURCE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
308630391Skarels 
308730391Skarels 	adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL;
308830391Skarels 
3089*34642Smarc 	/*
3090*34642Smarc 	* load destination data  */
309130391Skarels 
309230391Skarels 	wait_status(adder, RASTEROP_COMPLETE);
309330391Skarels 
309430391Skarels 	adder->destination_x = FONT_X;
309530391Skarels 	adder->destination_y = FONT_Y;
309634615Smarc 	if (FONT_WIDTH > MAX_SCREEN_X)
3097*34642Smarc 	    adder->fast_dest_dx = MAX_SCREEN_X;
309834615Smarc 	else
309934615Smarc 		adder->fast_dest_dx = FONT_WIDTH;
310030391Skarels 	adder->slow_dest_dy = CHAR_HEIGHT;
310130391Skarels 
3102*34642Smarc 	/*
3103*34642Smarc 	* setup for processor to bitmap xfer  */
310430391Skarels 
310530391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0001);
310630391Skarels 	adder->cmd = PBT | OCRB | 2 | DTE | 2;
310730391Skarels 
3108*34642Smarc 	/*
3109*34642Smarc 	* Figure out how many characters can be stored on one "line" of
3110*34642Smarc 	* offscreen memory.
3111*34642Smarc 	*/
3112*34642Smarc 	max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
3113*34642Smarc 	if ((CHARS/2 + CHARS%2) < max_chars_line)
3114*34642Smarc 	    max_chars_line = CHARS/2 + CHARS%2;
311530391Skarels 
3116*34642Smarc 	/*
3117*34642Smarc 	* iteratively do the processor to bitmap xfer */
311834615Smarc 
311930391Skarels 	for (i = 0; i < ROWS; ++i) {
312030391Skarels 
3121*34642Smarc 		/* PTOB a scan line */
312230391Skarels 
3123*34642Smarc 		for (j = 0, k = i; j < max_chars_line; ++j) {
3124*34642Smarc 			/* PTOB one scan of a char cell */
312530391Skarels 
3126*34642Smarc 			packed = q_font[k];
3127*34642Smarc 			k += ROWS;
3128*34642Smarc 			packed |= ((short)q_font[k] << 8);
3129*34642Smarc 			k += ROWS;
313030391Skarels 
3131*34642Smarc 			wait_status(adder, TX_READY);
3132*34642Smarc 			adder->id_data = packed;
3133*34642Smarc 		}
313430391Skarels 	}
313530391Skarels 
3136*34642Smarc 	/*
3137*34642Smarc 	 * (XXX XXX XXX - should remove)
3138*34642Smarc 	 *
3139*34642Smarc 	 * Copy the second row of characters.  Subtract the first
3140*34642Smarc 	 * row from the total number.  Divide this quantity by 2
3141*34642Smarc 	 * because 2 chars are stored in a short in the PTOB loop
3142*34642Smarc 	 * below.  Figure out how many characters can be stored on
3143*34642Smarc 	 * one "line" of offscreen memory
3144*34642Smarc 	 */
3145*34642Smarc 
3146*34642Smarc 	max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
3147*34642Smarc 	if ((CHARS/2 + CHARS%2) < max_chars_line)
3148*34642Smarc 	    return;
3149*34642Smarc 	max_chars_line = (CHARS/2 + CHARS%2) - max_chars_line; /* 95 - 64 */
3150*34642Smarc 	/* Paranoia check to see if 3rd row may be needed */
3151*34642Smarc 	if (max_chars_line > (MAX_SCREEN_X/(CHAR_WIDTH*2)))
315234615Smarc 	    max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
315334615Smarc 
315434615Smarc 	adder->destination_x = FONT_X;
315534615Smarc 	adder->destination_y = FONT_Y - CHAR_HEIGHT;
315634615Smarc 	adder->fast_dest_dx = max_chars_line * CHAR_WIDTH * 2;
315734615Smarc 	adder->slow_dest_dy = CHAR_HEIGHT;
315834615Smarc 
3159*34642Smarc 	/*
3160*34642Smarc 	* setup for processor to bitmap xfer
3161*34642Smarc 	*/
316234615Smarc 	write_ID(adder, CS_UPDATE_MASK, 0x0001);
316334615Smarc 	adder->cmd = PBT | OCRB | 2 | DTE | 2;
316434615Smarc 
3165*34642Smarc 	/*
3166*34642Smarc 	* iteratively do the processor to bitmap xfer
3167*34642Smarc 	*/
316834615Smarc 	for (i = 0; i < ROWS; ++i) {
3169*34642Smarc 		/*
3170*34642Smarc 		 * PTOB a scan line
3171*34642Smarc 		 */
3172*34642Smarc 		for (j = 0, k = i; j < max_chars_line; ++j) {
3173*34642Smarc 			/*
3174*34642Smarc 			 * PTOB one scan of a char cell
3175*34642Smarc 			 */
3176*34642Smarc 			packed = q_font[k + FONT_OFFSET];
3177*34642Smarc 			k += ROWS;
3178*34642Smarc 			packed |= ((short)q_font[k + FONT_OFFSET] << 8);
3179*34642Smarc 			k += ROWS;
3180*34642Smarc 			wait_status(adder, TX_READY);
3181*34642Smarc 			adder->id_data = packed;
3182*34642Smarc 		}
318334615Smarc 	}
318434615Smarc 
318530391Skarels }  /* ldfont */
318630391Skarels 
318730391Skarels /*********************************************************************
318830391Skarels *
318930391Skarels *	led_control()... twiddle LK-201 LED's
319030391Skarels *
319130391Skarels **********************************************************************
319230391Skarels *
319330391Skarels *	led_control(unit, cmd, led_mask);
319430391Skarels *	u_int unit;	QDSS number
319530391Skarels *	int cmd;	LED enable/disable command
319630391Skarels *	int led_mask;	which LED(s) to twiddle
319730391Skarels *
319830391Skarels *************/
319930391Skarels 
320030391Skarels led_control(unit, cmd, led_mask)
3201*34642Smarc 	u_int unit;
3202*34642Smarc 	int cmd;
3203*34642Smarc 	int led_mask;
320430391Skarels {
320530391Skarels 	register int i;
320630391Skarels 	register int status;
320730391Skarels 	register struct duart *duart;
320830391Skarels 
320930391Skarels 	duart = (struct duart *) qdmap[unit].duart;
321030391Skarels 
321130391Skarels 	for (i = 1000; i > 0; --i) {
3212*34642Smarc 		if ((status = duart->statusA) & XMT_RDY) {
3213*34642Smarc 			duart->dataA = cmd;
3214*34642Smarc 			break;
3215*34642Smarc 		}
321630391Skarels 	}
321730391Skarels 	for (i = 1000; i > 0; --i) {
3218*34642Smarc 		if ((status = duart->statusA) & XMT_RDY) {
3219*34642Smarc 			duart->dataA = led_mask;
3220*34642Smarc 			break;
3221*34642Smarc 		}
322230391Skarels 	}
322330391Skarels 	if (i == 0)
3224*34642Smarc 		return(BAD);
322530391Skarels 	return(GOOD);
322630391Skarels 
322730391Skarels } /* led_control */
322830391Skarels 
322930391Skarels /*******************************************************************
323030391Skarels *
323130391Skarels *	scroll_up()... move the screen up one character height
323230391Skarels *
323330391Skarels ********************************************************************
323430391Skarels *
323530391Skarels *	calling convention:
323630391Skarels *
323730391Skarels *		scroll_up(adder);
323830391Skarels *		struct adder *adder;	;address of adder
323930391Skarels *
324030391Skarels ********/
324130391Skarels 
324230391Skarels scroll_up(adder)
3243*34642Smarc 	register struct adder *adder;
324430391Skarels {
3245*34642Smarc 	/*
3246*34642Smarc 	* setup VIPER operand control registers
3247*34642Smarc 	*/
324830391Skarels 	wait_status(adder, ADDRESS_COMPLETE);
324930391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x00FF);  /* select all planes */
325030391Skarels 	write_ID(adder, MASK_1, 0xFFFF);
325130391Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
325230391Skarels 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
325330391Skarels 	write_ID(adder, SRC1_OCR_B,
3254*34642Smarc 	EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY);
325530391Skarels 	write_ID(adder, DST_OCR_B,
3256*34642Smarc 	EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
3257*34642Smarc 	/*
3258*34642Smarc 	 * load DESTINATION origin and vectors
3259*34642Smarc 	 */
326030391Skarels 	adder->fast_dest_dy = 0;
326130391Skarels 	adder->slow_dest_dx = 0;
326230391Skarels 	adder->error_1 = 0;
326330391Skarels 	adder->error_2 = 0;
326430391Skarels 	adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL;
326530391Skarels 	adder->destination_x = 0;
326630391Skarels 	adder->fast_dest_dx = 1024;
326730391Skarels 	adder->destination_y = 0;
326830391Skarels 	adder->slow_dest_dy = 864 - CHAR_HEIGHT;
3269*34642Smarc 	/*
3270*34642Smarc 	 * load SOURCE origin and vectors
3271*34642Smarc 	 */
327230391Skarels 	adder->source_1_x = 0;
327330391Skarels 	adder->source_1_dx = 1024;
327430391Skarels 	adder->source_1_y = 0 + CHAR_HEIGHT;
327530391Skarels 	adder->source_1_dy = 864 - CHAR_HEIGHT;
327630391Skarels 	write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
327730391Skarels 	adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE;
3278*34642Smarc 	/*
3279*34642Smarc 	 * do a rectangle clear of last screen line
3280*34642Smarc 	 */
328130391Skarels 	write_ID(adder, MASK_1, 0xffff);
328230391Skarels 	write_ID(adder, SOURCE, 0xffff);
328330391Skarels 	write_ID(adder,DST_OCR_B,
3284*34642Smarc 	(EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY));
328530391Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 0);
328630391Skarels 	adder->error_1 = 0;
328730391Skarels 	adder->error_2 = 0;
3288*34642Smarc 	adder->slow_dest_dx = 0;		/* set up the width of	*/
328930391Skarels 	adder->slow_dest_dy = CHAR_HEIGHT;	/* rectangle */
329030391Skarels 	adder->rasterop_mode = (NORMAL | DST_WRITE_ENABLE) ;
329130391Skarels 	wait_status(adder, RASTEROP_COMPLETE);
329230391Skarels 	adder->destination_x = 0;
329330391Skarels 	adder->destination_y = 864 - CHAR_HEIGHT;
329430391Skarels 	adder->fast_dest_dx = 1024;	/* set up the height	*/
329530391Skarels 	adder->fast_dest_dy = 0;	/* of rectangle 	*/
329630391Skarels 	write_ID(adder, LU_FUNCTION_R2, (FULL_SRC_RESOLUTION | LF_SOURCE));
329730391Skarels 	adder->cmd = (RASTEROP | OCRB | LF_R2 | DTE ) ;
329830391Skarels 
329930391Skarels } /* scroll_up */
330030391Skarels 
330130391Skarels /********************************************************************
330230391Skarels *
330330391Skarels *	init_shared()... init shared memory pointers and structures
330430391Skarels *
330530391Skarels *********************************************************************
330630391Skarels *
330730391Skarels *	calling convention:
330830391Skarels *
330930391Skarels *		init_shared(unit);
331030391Skarels *		u_int unit;
331130391Skarels *
331230391Skarels ****************/
331330391Skarels 
331430391Skarels init_shared(unit)
3315*34642Smarc 	register u_int unit;
331630391Skarels {
331730391Skarels 	register struct dga *dga;
331830391Skarels 
331930391Skarels 	dga = (struct dga *) qdmap[unit].dga;
332030391Skarels 
3321*34642Smarc 	/*
3322*34642Smarc 	* initialize the event queue pointers and header */
332330391Skarels 
332430391Skarels 	eq_header[unit] = (struct qdinput *)
3325*34642Smarc 	    ((((int)event_shared & ~(0x01FF)) + 512)
3326*34642Smarc 		+ (EVENT_BUFSIZE * unit));
332730391Skarels 	eq_header[unit]->curs_pos.x = 0;
332830391Skarels 	eq_header[unit]->curs_pos.y = 0;
332930391Skarels 	dga->x_cursor = TRANX(eq_header[unit]->curs_pos.x);
333030391Skarels 	dga->y_cursor = TRANY(eq_header[unit]->curs_pos.y);
333130391Skarels 	eq_header[unit]->curs_box.left = 0;
333230391Skarels 	eq_header[unit]->curs_box.right = 0;
333330391Skarels 	eq_header[unit]->curs_box.top = 0;
333430391Skarels 	eq_header[unit]->curs_box.bottom = 0;
3335*34642Smarc 	/*
3336*34642Smarc 	 * assign a pointer to the DMA I/O buffer for this QDSS.
3337*34642Smarc 	 */
333830391Skarels 	DMAheader[unit] = (struct DMAreq_header *)
3339*34642Smarc 	    (((int)(&DMA_shared[0] + 512) & ~0x1FF)
3340*34642Smarc 		+ (DMAbuf_size * unit));
334130391Skarels 	DMAheader[unit]->DMAreq = (struct DMAreq *) ((int)DMAheader[unit]
3342*34642Smarc 	    + sizeof(struct DMAreq_header));
334330391Skarels 	DMAheader[unit]->QBAreg = 0;
334430391Skarels 	DMAheader[unit]->status = 0;
334530391Skarels 	DMAheader[unit]->shared_size = DMAbuf_size;
334630391Skarels 	DMAheader[unit]->used = 0;
334730391Skarels 	DMAheader[unit]->size = 10;	/* default = 10 requests */
334830391Skarels 	DMAheader[unit]->oldest = 0;
334930391Skarels 	DMAheader[unit]->newest = 0;
3350*34642Smarc 	/*
3351*34642Smarc 	* assign a pointer to the scroll structure for this QDSS.
3352*34642Smarc 	*/
335330391Skarels 	scroll[unit] = (struct scroll *)
3354*34642Smarc 	    (((int)(&scroll_shared[0] + 512) & ~0x1FF)
3355*34642Smarc 		+ (sizeof(struct scroll) * unit));
335630391Skarels 	scroll[unit]->status = 0;
335730391Skarels 	scroll[unit]->viper_constant = 0;
335830391Skarels 	scroll[unit]->y_scroll_constant = 0;
335930391Skarels 	scroll[unit]->y_offset = 0;
336030391Skarels 	scroll[unit]->x_index_pending = 0;
336130391Skarels 	scroll[unit]->y_index_pending = 0;
3362*34642Smarc 	/*
3363*34642Smarc 	* assign a pointer to the color map write buffer for this QDSS
3364*34642Smarc 	*/
336530391Skarels 	color_buf[unit] = (struct color_buf *)
3366*34642Smarc 	    (((int)(&color_shared[0] + 512) & ~0x1FF)
3367*34642Smarc 		+ (COLOR_BUFSIZ * unit));
336830391Skarels 	color_buf[unit]->status = 0;
336930391Skarels 	color_buf[unit]->count = 0;
337030391Skarels 
337130391Skarels } /* init_shared */
337230391Skarels 
337330391Skarels /*********************************************************************
337430391Skarels *
337530391Skarels *	setup_dragon()... init the ADDER, VIPER, bitmaps, & color map
337630391Skarels *
337730391Skarels **********************************************************************
337830391Skarels *
337930391Skarels *	calling convention:
338030391Skarels *
338130391Skarels *		setup_dragon();
338230391Skarels *
338330391Skarels *	return: NONE
338430391Skarels *
338530391Skarels ************************/
338630391Skarels 
338730391Skarels setup_dragon(unit)
3388*34642Smarc 	u_int unit;
338930391Skarels {
339030391Skarels 
339130391Skarels 	register struct adder *adder;
339230391Skarels 	register struct dga *dga;
339330391Skarels 	short *memcsr;
339430391Skarels 	int i;			/* general purpose variables */
339530391Skarels 	int status;
339630391Skarels 	short top;		/* clipping/scrolling boundaries */
339730391Skarels 	short bottom;
339830391Skarels 	short right;
339930391Skarels 	short left;
340030391Skarels 	short *red;		/* color map pointers */
340130391Skarels 	short *green;
340230391Skarels 	short *blue;
340330391Skarels 
3404*34642Smarc 	/*
3405*34642Smarc 	* init for setup
3406*34642Smarc 	*/
340730391Skarels 	adder = (struct adder *) qdmap[unit].adder;
340830391Skarels 	dga = (struct dga *) qdmap[unit].dga;
340930391Skarels 	memcsr = (short *) qdmap[unit].memcsr;
341030391Skarels 	dga->csr &= ~(DMA_IE | 0x700);	/* halt DMA and kill the intrpts */
341130391Skarels 	*memcsr = SYNC_ON;		/* blank screen and turn off LED's */
341230391Skarels 	adder->command = CANCEL;
3413*34642Smarc 	/*
3414*34642Smarc 	* set monitor timing
3415*34642Smarc 	*/
341630391Skarels 	adder->x_scan_count_0 = 0x2800;
341730391Skarels 	adder->x_scan_count_1 = 0x1020;
341830391Skarels 	adder->x_scan_count_2 = 0x003A;
341930391Skarels 	adder->x_scan_count_3 = 0x38F0;
342030391Skarels 	adder->x_scan_count_4 = 0x6128;
342130391Skarels 	adder->x_scan_count_5 = 0x093A;
342230391Skarels 	adder->x_scan_count_6 = 0x313C;
342330391Skarels 	adder->sync_phase_adj = 0x0100;
342430391Skarels 	adder->x_scan_conf = 0x00C8;
3425*34642Smarc 	/*
3426*34642Smarc 	 * got a bug in secound pass ADDER! lets take care of it
3427*34642Smarc 	 *
3428*34642Smarc 	 * normally, just use the code in the following bug fix code, but to
3429*34642Smarc 	 * make repeated demos look pretty, load the registers as if there was
3430*34642Smarc 	 * no bug and then test to see if we are getting sync
3431*34642Smarc 	 */
343230391Skarels 	adder->y_scan_count_0 = 0x135F;
343330391Skarels 	adder->y_scan_count_1 = 0x3363;
343430391Skarels 	adder->y_scan_count_2 = 0x2366;
343530391Skarels 	adder->y_scan_count_3 = 0x0388;
3436*34642Smarc 	/*
3437*34642Smarc 	 * if no sync, do the bug fix code
3438*34642Smarc 	 */
343930391Skarels 	if (wait_status(adder, VSYNC) == BAD) {
3440*34642Smarc 		/* first load all Y scan registers with very short frame and
3441*34642Smarc 		 * wait for scroll service.  This guarantees at least one SYNC
3442*34642Smarc 		 * to fix the pass 2 Adder initialization bug (synchronizes
3443*34642Smarc 		 * XCINCH with DMSEEDH)
3444*34642Smarc 		 */
3445*34642Smarc 		adder->y_scan_count_0 = 0x01;
3446*34642Smarc 		adder->y_scan_count_1 = 0x01;
3447*34642Smarc 		adder->y_scan_count_2 = 0x01;
3448*34642Smarc 		adder->y_scan_count_3 = 0x01;
3449*34642Smarc 		/*
3450*34642Smarc 		 * delay at least 1 full frame time
3451*34642Smarc 		 */
3452*34642Smarc 		wait_status(adder, VSYNC);
3453*34642Smarc 		wait_status(adder, VSYNC);
3454*34642Smarc 		/*
3455*34642Smarc 		 * now load the REAL sync values (in reverse order just to
3456*34642Smarc 		 * be safe.
3457*34642Smarc 		 */
3458*34642Smarc 		adder->y_scan_count_3 = 0x0388;
3459*34642Smarc 		adder->y_scan_count_2 = 0x2366;
3460*34642Smarc 		adder->y_scan_count_1 = 0x3363;
3461*34642Smarc 		adder->y_scan_count_0 = 0x135F;
346230391Skarels 	}
346330391Skarels 	*memcsr = SYNC_ON | UNBLANK;	/* turn off leds and turn on video */
3464*34642Smarc 	/*
3465*34642Smarc 	 * zero the index registers
3466*34642Smarc 	 */
346730391Skarels 	adder->x_index_pending = 0;
346830391Skarels 	adder->y_index_pending = 0;
346930391Skarels 	adder->x_index_new = 0;
347030391Skarels 	adder->y_index_new = 0;
347130391Skarels 	adder->x_index_old = 0;
347230391Skarels 	adder->y_index_old = 0;
347330391Skarels 	adder->pause = 0;
3474*34642Smarc 	/*
3475*34642Smarc 	 * set rasterop mode to normal pen down
3476*34642Smarc 	 */
347730391Skarels 	adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL;
3478*34642Smarc 	/*
3479*34642Smarc 	 * set the rasterop registers to a default values
3480*34642Smarc 	 */
348130391Skarels 	adder->source_1_dx = 1;
348230391Skarels 	adder->source_1_dy = 1;
348330391Skarels 	adder->source_1_x = 0;
348430391Skarels 	adder->source_1_y = 0;
348530391Skarels 	adder->destination_x = 0;
348630391Skarels 	adder->destination_y = 0;
348730391Skarels 	adder->fast_dest_dx = 1;
348830391Skarels 	adder->fast_dest_dy = 0;
348930391Skarels 	adder->slow_dest_dx = 0;
349030391Skarels 	adder->slow_dest_dy = 1;
349130391Skarels 	adder->error_1 = 0;
349230391Skarels 	adder->error_2 = 0;
3493*34642Smarc 	/*
3494*34642Smarc 	 * scale factor = unity
3495*34642Smarc 	 */
349630391Skarels 	adder->fast_scale = UNITY;
349730391Skarels 	adder->slow_scale = UNITY;
3498*34642Smarc 	/*
3499*34642Smarc 	 * set the source 2 parameters
3500*34642Smarc 	 */
350130391Skarels 	adder->source_2_x = 0;
350230391Skarels 	adder->source_2_y = 0;
350330391Skarels 	adder->source_2_size = 0x0022;
3504*34642Smarc 	/*
3505*34642Smarc 	* initialize plane addresses for eight vipers
3506*34642Smarc 	*/
350730391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0001);
350830391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0000);
350930391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0002);
351030391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0001);
351130391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0004);
351230391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0002);
351330391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0008);
351430391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0003);
351530391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0010);
351630391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0004);
351730391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0020);
351830391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0005);
351930391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0040);
352030391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0006);
352130391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0080);
352230391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0007);
3523*34642Smarc 	/*
3524*34642Smarc 	 * initialize the external registers.
3525*34642Smarc 	 */
352630391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x00FF);
352730391Skarels 	write_ID(adder, CS_SCROLL_MASK, 0x00FF);
3528*34642Smarc 	/*
3529*34642Smarc 	 * initialize resolution mode
3530*34642Smarc 	 */
353130391Skarels 	write_ID(adder, MEMORY_BUS_WIDTH, 0x000C);     /* bus width = 16 */
353230391Skarels 	write_ID(adder, RESOLUTION_MODE, 0x0000);      /* one bit/pixel */
3533*34642Smarc 	/*
3534*34642Smarc 	 * initialize viper registers
3535*34642Smarc 	 */
353630391Skarels 	write_ID(adder, SCROLL_CONSTANT, SCROLL_ENABLE|VIPER_LEFT|VIPER_UP);
353730391Skarels 	write_ID(adder, SCROLL_FILL, 0x0000);
3538*34642Smarc 	/*
3539*34642Smarc 	 * set clipping and scrolling limits to full screen
3540*34642Smarc 	 */
3541*34642Smarc 	for ( i = 1000, adder->status = 0 ;
3542*34642Smarc 	      i > 0  &&  !((status = adder->status) & ADDRESS_COMPLETE) ; --i)
3543*34642Smarc 		;
354430391Skarels 	if (i == 0)
354534615Smarc 	    printf("\nqd%d: setup_dragon: timeout on ADDRESS_COMPLETE",unit);
354630391Skarels 	top = 0;
354730391Skarels 	bottom = 2048;
354830391Skarels 	left = 0;
354930391Skarels 	right = 1024;
355030391Skarels 	adder->x_clip_min = left;
355130391Skarels 	adder->x_clip_max = right;
355230391Skarels 	adder->y_clip_min = top;
355330391Skarels 	adder->y_clip_max = bottom;
355430391Skarels 	adder->scroll_x_min = left;
355530391Skarels 	adder->scroll_x_max = right;
355630391Skarels 	adder->scroll_y_min = top;
355730391Skarels 	adder->scroll_y_max = bottom;
355830391Skarels 	wait_status(adder, VSYNC);	/* wait at LEAST 1 full frame */
355930391Skarels 	wait_status(adder, VSYNC);
356030391Skarels 	adder->x_index_pending = left;
356130391Skarels 	adder->y_index_pending = top;
356230391Skarels 	adder->x_index_new = left;
356330391Skarels 	adder->y_index_new = top;
356430391Skarels 	adder->x_index_old = left;
356530391Skarels 	adder->y_index_old = top;
356630391Skarels 
3567*34642Smarc 	for ( i = 1000, adder->status = 0 ;
3568*34642Smarc 	      i > 0  &&  !((status = adder->status) & ADDRESS_COMPLETE) ;
3569*34642Smarc 	      --i)
3570*34642Smarc 		;
357130391Skarels 	if (i == 0)
3572*34642Smarc 	       printf("\nqd%d: setup_dragon: timeout on ADDRESS_COMPLETE",unit);
357330391Skarels 
357430391Skarels 	write_ID(adder, LEFT_SCROLL_MASK, 0x0000);
357530391Skarels 	write_ID(adder, RIGHT_SCROLL_MASK, 0x0000);
3576*34642Smarc 	/*
3577*34642Smarc 	* set source and the mask register to all ones (ie: white) o
3578*34642Smarc 	*/
357930391Skarels 	write_ID(adder, SOURCE, 0xFFFF);
358030391Skarels 	write_ID(adder, MASK_1, 0xFFFF);
358130391Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
358230391Skarels 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
3583*34642Smarc 	/*
3584*34642Smarc 	* initialize Operand Control Register banks for fill command
3585*34642Smarc 	*/
358630391Skarels 	write_ID(adder, SRC1_OCR_A, EXT_NONE | INT_M1_M2  | NO_ID | WAIT);
358730391Skarels 	write_ID(adder, SRC2_OCR_A, EXT_NONE | INT_SOURCE | NO_ID | NO_WAIT);
358830391Skarels 	write_ID(adder, DST_OCR_A, EXT_NONE | INT_NONE	 | NO_ID | NO_WAIT);
358930391Skarels 	write_ID(adder, SRC1_OCR_B, EXT_NONE | INT_SOURCE | NO_ID | WAIT);
359030391Skarels 	write_ID(adder, SRC2_OCR_B, EXT_NONE | INT_M1_M2  | NO_ID | NO_WAIT);
359130391Skarels 	write_ID(adder, DST_OCR_B, EXT_NONE | INT_NONE | NO_ID | NO_WAIT);
3592*34642Smarc 	/*
3593*34642Smarc 	* init Logic Unit Function registers, (these are just common values,
3594*34642Smarc 	* and may be changed as required).
3595*34642Smarc 	*/
359630391Skarels 	write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
3597*34642Smarc 	write_ID(adder, LU_FUNCTION_R2, FULL_SRC_RESOLUTION | LF_SOURCE |
3598*34642Smarc 		 INV_M1_M2);
359930391Skarels 	write_ID(adder, LU_FUNCTION_R3, FULL_SRC_RESOLUTION | LF_D_OR_S);
360030391Skarels 	write_ID(adder, LU_FUNCTION_R4, FULL_SRC_RESOLUTION | LF_D_XOR_S);
3601*34642Smarc 	/*
3602*34642Smarc 	* load the color map for black & white
3603*34642Smarc 	*/
3604*34642Smarc 	for ( i = 0, adder->status = 0; i < 10000  &&
3605*34642Smarc 	      !((status = adder->status) & VSYNC) ; ++i)
3606*34642Smarc 		;
360730391Skarels 
360830391Skarels 	if (i == 0)
360934615Smarc 	    printf("\nqd%d: setup_dragon: timeout on VSYNC", unit);
361030391Skarels 
361130391Skarels 	red = (short *) qdmap[unit].red;
361230391Skarels 	green = (short *) qdmap[unit].green;
361330391Skarels 	blue = (short *) qdmap[unit].blue;
361430391Skarels 
361530391Skarels 	*red++ = 0x00;			/* black */
361630391Skarels 	*green++ = 0x00;
361730391Skarels 	*blue++ = 0x00;
361830391Skarels 
361930391Skarels 	*red-- = 0xFF;			/* white */
362030391Skarels 	*green-- = 0xFF;
362130391Skarels 	*blue-- = 0xFF;
362230391Skarels 
3623*34642Smarc 	/*
362430391Skarels 	* set color map for mouse cursor */
362530391Skarels 
362630391Skarels 	red += 254;
362730391Skarels 	green += 254;
362830391Skarels 	blue += 254;
362930391Skarels 
363030391Skarels 	*red++ = 0x00;			/* black */
363130391Skarels 	*green++ = 0x00;
363230391Skarels 	*blue++ = 0x00;
363330391Skarels 
363430391Skarels 	*red = 0xFF;			/* white */
363530391Skarels 	*green = 0xFF;
363630391Skarels 	*blue = 0xFF;
363730391Skarels 
363830391Skarels 	return(0);
363930391Skarels 
364030391Skarels } /* setup_dragon */
364130391Skarels 
364230391Skarels /******************************************************************
364330391Skarels *
364430391Skarels *	setup_input()... init the DUART and set defaults in input
364530391Skarels *			 devices
364630391Skarels *
364730391Skarels *******************************************************************
364830391Skarels *
364930391Skarels *	calling convention:
365030391Skarels *
365130391Skarels *		setup_input(unit);
365230391Skarels *
365330391Skarels *	where: unit - is the QDSS unit number to be setup
365430391Skarels *
365530391Skarels *********/
365630391Skarels 
365730391Skarels setup_input(unit)
365830391Skarels u_int unit;
365930391Skarels {
366030391Skarels 	register struct duart *duart;	/* DUART register structure pointer */
366130391Skarels 	register int i; 		/* scratch variable */
366230391Skarels 	register int bits;
366330391Skarels 	char id_byte;
366430391Skarels 	short status;
366530391Skarels 
366630391Skarels 	duart = (struct duart *) qdmap[unit].duart;
366730391Skarels 	duart->imask = 0;
366830391Skarels 
3669*34642Smarc 	/*
3670*34642Smarc 	* setup the DUART for kbd & pointing device
3671*34642Smarc 	*/
367230391Skarels 	duart->cmdA = RESET_M;	  /* reset mode reg ptr for kbd */
367330391Skarels 	duart->modeA = 0x13;	  /* 8 bits, no parity, rcv IE, */
3674*34642Smarc 	/* no RTS control,char error mode */
367530391Skarels 	duart->modeA = 0x07;	  /* 1 stop bit,CTS does not IE XMT */
3676*34642Smarc 	/* no RTS control,no echo or loop */
367730391Skarels 	duart->cmdB = RESET_M;	  /* reset mode reg pntr for host */
367830391Skarels 	duart->modeB = 0x07;	  /* 8 bits, odd parity, rcv IE.. */
3679*34642Smarc 	/* ..no RTS cntrl, char error mode */
368030391Skarels 	duart->modeB = 0x07;	  /* 1 stop bit,CTS does not IE XMT */
3681*34642Smarc 	/* no RTS control,no echo or loop */
368230391Skarels 
368330391Skarels 	duart->auxctl = 0x00;	  /* baud rate set 1 */
368430391Skarels 
368530391Skarels 	duart->clkselA = 0x99;	  /* 4800 baud for kbd */
368630391Skarels 	duart->clkselB = 0x99;	  /* 4800 baud for mouse */
368730391Skarels 
368830391Skarels 	/* reset everything for keyboard */
368930391Skarels 
369030391Skarels 	for (bits = RESET_M; bits < START_BREAK; bits += 0x10)
3691*34642Smarc 		duart->cmdA = bits;
369230391Skarels 
369330391Skarels 	/* reset everything for host */
369430391Skarels 
369530391Skarels 	for (bits = RESET_M; bits < START_BREAK; bits += 0x10)
3696*34642Smarc 		duart->cmdB = bits;
369730391Skarels 
369830391Skarels 	duart->cmdA = EN_RCV | EN_XMT; /* enbl xmt & rcv for kbd */
369930391Skarels 	duart->cmdB = EN_RCV | EN_XMT; /* enbl xmt & rcv for pointer device */
370030391Skarels 
3701*34642Smarc 	/*
3702*34642Smarc 	* init keyboard defaults (DUART channel A) */
370330391Skarels 
370430391Skarels 	for (i = 500; i > 0; --i) {
3705*34642Smarc 		if ((status = duart->statusA) & XMT_RDY) {
3706*34642Smarc 			duart->dataA = LK_DEFAULTS;
3707*34642Smarc 			break;
3708*34642Smarc 		}
370930391Skarels 	}
371030391Skarels 
371130391Skarels 	for (i = 100000; i > 0; --i) {
3712*34642Smarc 		if ((status = duart->statusA) & RCV_RDY) {
3713*34642Smarc 			break;
3714*34642Smarc 		}
371530391Skarels 	}
371630391Skarels 
371730391Skarels 	status = duart->dataA;		/* flush the ACK */
371830391Skarels 
3719*34642Smarc 	/*
3720*34642Smarc 	* identify the pointing device */
372130391Skarels 
372230391Skarels 	for (i = 500; i > 0; --i) {
3723*34642Smarc 		if ((status = duart->statusB) & XMT_RDY) {
3724*34642Smarc 			duart->dataB = SELF_TEST;
3725*34642Smarc 			break;
3726*34642Smarc 		}
372730391Skarels 	}
372830391Skarels 
3729*34642Smarc 	/*
373030391Skarels 	* wait for 1st byte of self test report */
373130391Skarels 
373230391Skarels 	for (i = 100000; i > 0; --i) {
3733*34642Smarc 		if ((status = duart->statusB) & RCV_RDY) {
3734*34642Smarc 			break;
3735*34642Smarc 		}
373630391Skarels 	}
373730391Skarels 
373830391Skarels 	if (i == 0) {
3739*34642Smarc 		printf("\nqd[%d]: setup_input: timeout on 1st byte of self test"
3740*34642Smarc 		       ,unit);
3741*34642Smarc 		goto OUT;
374230391Skarels 	}
374330391Skarels 
374430391Skarels 	status = duart->dataB;
374530391Skarels 
3746*34642Smarc 	/*
374730391Skarels 	* wait for ID byte of self test report	*/
374830391Skarels 
374930391Skarels 	for (i = 100000; i > 0; --i) {
3750*34642Smarc 		if ((status = duart->statusB) & RCV_RDY) {
3751*34642Smarc 			break;
3752*34642Smarc 		}
375330391Skarels 	}
375430391Skarels 
375530391Skarels 	if (i == 0) {
3756*34642Smarc 		printf("\nqd[%d]: setup_input: timeout on 2nd byte of self test", unit);
3757*34642Smarc 		goto OUT;
375830391Skarels 	}
375930391Skarels 
376030391Skarels 	id_byte = duart->dataB;
376130391Skarels 
3762*34642Smarc 	/*
376330391Skarels 	* wait for other bytes to come in  */
376430391Skarels 
376530391Skarels 	for (i = 100000; i > 0; --i) {
3766*34642Smarc 		if ((status = duart->statusB) & RCV_RDY) {
3767*34642Smarc 			status = duart->dataB;
3768*34642Smarc 			break;
3769*34642Smarc 		}
377030391Skarels 	}
377130391Skarels 
377230391Skarels 	if (i == 0) {
3773*34642Smarc 		printf("\nqd[%d]: setup_input: timeout on 3rd byte of self test", unit);
3774*34642Smarc 		goto OUT;
377530391Skarels 	}
377630391Skarels 
377730391Skarels 	for (i = 100000; i > 0; --i) {
3778*34642Smarc 		if ((status = duart->statusB) & RCV_RDY) {
3779*34642Smarc 			status = duart->dataB;
3780*34642Smarc 			break;
3781*34642Smarc 		}
378230391Skarels 	}
378330391Skarels 
378430391Skarels 	if (i == 0) {
3785*34642Smarc 		printf("\nqd[%d]: setup_input: timeout on 4th byte of self test\n", unit);
3786*34642Smarc 		goto OUT;
378730391Skarels 	}
378830391Skarels 
3789*34642Smarc 	/*
379030391Skarels 	* flag pointing device type and set defaults */
379130391Skarels 
379230391Skarels 	for (i=100000; i>0; --i);
379330391Skarels 
379430391Skarels 	if ((id_byte & 0x0F) != TABLET_ID) {
379530391Skarels 
3796*34642Smarc 		qdflags[unit].pntr_id = MOUSE_ID;
379730391Skarels 
3798*34642Smarc 		for (i = 500; i > 0; --i) {
3799*34642Smarc 			if ((status = duart->statusB) & XMT_RDY) {
3800*34642Smarc 				duart->dataB = INC_STREAM_MODE;
3801*34642Smarc 				break;
3802*34642Smarc 			}
380330391Skarels 		}
3804*34642Smarc 	}
3805*34642Smarc 	else {
380630391Skarels 
3807*34642Smarc 		qdflags[unit].pntr_id = TABLET_ID;
380830391Skarels 
3809*34642Smarc 		for (i = 500; i > 0; --i) {
3810*34642Smarc 			if ((status = duart->statusB) & XMT_RDY) {
3811*34642Smarc 				duart->dataB = T_STREAM;
3812*34642Smarc 				break;
3813*34642Smarc 			}
381430391Skarels 		}
381530391Skarels 	}
381630391Skarels 
3817*34642Smarc 	/*
3818*34642Smarc 	* exit */
381930391Skarels 
382030391Skarels OUT:
382130391Skarels 	duart->imask = qdflags[unit].duart_imask;
382230391Skarels 	return(0);
382330391Skarels 
382430391Skarels } /* setup_input */
382530391Skarels 
382630391Skarels /**********************************************************************
382730391Skarels *
382830391Skarels *	wait_status()... delay for at least one display frame time
382930391Skarels *
383030391Skarels ***********************************************************************
383130391Skarels *
383230391Skarels *	calling convention:
383330391Skarels *
383430391Skarels *		wait_status(adder, mask);
383530391Skarels *		struct *adder adder;
383630391Skarels *		int mask;
383730391Skarels *
383830391Skarels *	return: BAD means that we timed out without ever seeing the
383930391Skarels *		      vertical sync status bit
384030391Skarels *		GOOD otherwise
384130391Skarels *
384230391Skarels **************/
384330391Skarels 
384430391Skarels wait_status(adder, mask)
3845*34642Smarc 	register struct adder *adder;
3846*34642Smarc 	register int mask;
384730391Skarels {
384830391Skarels 	register short status;
384930391Skarels 	int i;
385030391Skarels 
3851*34642Smarc 	for ( i = 10000, adder->status = 0 ; i > 0  &&
3852*34642Smarc 	     !((status = adder->status) & mask) ; --i)
3853*34642Smarc 		;
385430391Skarels 
385530391Skarels 	if (i == 0) {
3856*34642Smarc 		printf("\nwait_status: timeout polling for 0x%x in adder->status", mask);
3857*34642Smarc 		return(BAD);
385830391Skarels 	}
385930391Skarels 
386030391Skarels 	return(GOOD);
386130391Skarels 
386230391Skarels } /* wait_status */
386330391Skarels 
386430391Skarels /**********************************************************************
386530391Skarels *
386630391Skarels *	write_ID()... write out onto the ID bus
386730391Skarels *
386830391Skarels ***********************************************************************
386930391Skarels *
387030391Skarels *	calling convention:
387130391Skarels *
387230391Skarels *		struct *adder adder;	;pntr to ADDER structure
387330391Skarels *		short adrs;		;VIPER address
387430391Skarels *		short data;		;data to be written
387530391Skarels *		write_ID(adder);
387630391Skarels *
387730391Skarels *	return: BAD means that we timed out waiting for status bits
387830391Skarels *		      VIPER-access-specific status bits
387930391Skarels *		GOOD otherwise
388030391Skarels *
388130391Skarels **************/
388230391Skarels 
388330391Skarels write_ID(adder, adrs, data)
3884*34642Smarc 	register struct adder *adder;
3885*34642Smarc 	register short adrs;
3886*34642Smarc 	register short data;
388730391Skarels {
388830391Skarels 	int i;
388930391Skarels 	short status;
389030391Skarels 
3891*34642Smarc 	for ( i = 100000, adder->status = 0 ;
3892*34642Smarc 	      i > 0  &&  !((status = adder->status) & ADDRESS_COMPLETE) ;
3893*34642Smarc 	      --i)
3894*34642Smarc 		;
389530391Skarels 
389630391Skarels 	if (i == 0)
389730391Skarels 	    goto ERR;
389830391Skarels 
3899*34642Smarc 	for ( i = 100000, adder->status = 0 ;
3900*34642Smarc 	      i > 0  &&  !((status = adder->status) & TX_READY) ; --i)
3901*34642Smarc 		;
390230391Skarels 
390330391Skarels 	if (i > 0) {
3904*34642Smarc 		adder->id_data = data;
3905*34642Smarc 		adder->command = ID_LOAD | adrs;
3906*34642Smarc 		return(GOOD);
390730391Skarels 	}
390830391Skarels 
390930391Skarels ERR:
391034615Smarc 	printf("\nwrite_ID: timeout trying to write to VIPER");
391130391Skarels 	return(BAD);
391230391Skarels 
391330391Skarels } /* write_ID */
391434511Smarc #endif
3915