xref: /csrg-svn/sys/vax/uba/qd.c (revision 40817)
134511Smarc /*
235353Sbostic  * Copyright (c) 1988 Regents of the University of California.
335353Sbostic  * All rights reserved.
435353Sbostic  *
535353Sbostic  * Redistribution and use in source and binary forms are permitted
635353Sbostic  * provided that the above copyright notice and this paragraph are
735353Sbostic  * duplicated in all such forms and that any documentation,
835353Sbostic  * advertising materials, and other materials related to such
935353Sbostic  * distribution and use acknowledge that the software was developed
1035353Sbostic  * by the University of California, Berkeley.  The name of the
1135353Sbostic  * University may not be used to endorse or promote products derived
1235353Sbostic  * from this software without specific prior written permission.
1335353Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1435353Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1535353Sbostic  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1635353Sbostic  *
17*40817Smarc  *	@(#)qd.c	1.15 (Berkeley) 04/05/90
1835353Sbostic  */
1934642Smarc 
2030391Skarels /************************************************************************
2134511Smarc *									*
2234615Smarc *			Copyright (c) 1985-1988 by			*
2330391Skarels *		Digital Equipment Corporation, Maynard, MA		*
2430391Skarels *			All rights reserved.				*
2530391Skarels *									*
2630391Skarels *   This software is furnished under a license and may be used and	*
2730391Skarels *   copied  only  in accordance with the terms of such license and	*
2830391Skarels *   with the  inclusion  of  the  above  copyright  notice.   This	*
2930391Skarels *   software  or  any  other copies thereof may not be provided or	*
3030391Skarels *   otherwise made available to any other person.  No title to and	*
3130391Skarels *   ownership of the software is hereby transferred.			*
3230391Skarels *									*
3330391Skarels *   The information in this software is subject to change  without	*
3430391Skarels *   notice  and should not be construed as a commitment by Digital	*
3530391Skarels *   Equipment Corporation.						*
3630391Skarels *									*
3730391Skarels *   Digital assumes no responsibility for the use  or  reliability	*
3830391Skarels *   of its software on equipment which is not supplied by Digital.	*
3930391Skarels *									*
4030391Skarels *************************************************************************/
4134615Smarc 
4230391Skarels /*
4334642Smarc  * qd.c - QDSS display driver for VAXSTATION-II GPX workstation
4430391Skarels  */
4530391Skarels 
4634642Smarc #include "qd.h"
4734615Smarc 
4834511Smarc #if NQD > 0
4934615Smarc #include "types.h"
5037513Smckusick #include "machine/pte.h"
5137513Smckusick #include "machine/mtpr.h"
5237513Smckusick #include "machine/cpu.h"
5334642Smarc #include "param.h"
5434642Smarc #include "conf.h"
5534642Smarc #include "user.h"
5634642Smarc #include "qdioctl.h"
5734511Smarc #include "tty.h"
5834642Smarc #include "map.h"
5934642Smarc #include "buf.h"
6034642Smarc #include "vm.h"
6134642Smarc #include "clist.h"
6234642Smarc #include "file.h"
6334642Smarc #include "uio.h"
6434642Smarc #include "kernel.h"
6534615Smarc #include "exec.h"
6634615Smarc #include "proc.h"
6734642Smarc #include "ubareg.h"
6834642Smarc #include "ubavar.h"
6934511Smarc #include "syslog.h"
7034642Smarc #include "qduser.h"	/* definitions shared with user level client */
7134615Smarc #include "qdreg.h"	/* QDSS device register structures */
7232012Smarc 
7334642Smarc /*
7434642Smarc  * QDSS driver status flags for tracking operational state
7534642Smarc  */
7634642Smarc struct qdflags {
7734642Smarc 	u_int inuse;		/* which minor dev's are in use now */
7834642Smarc 	u_int config;		/* I/O page register content */
7934642Smarc 	u_int mapped;		/* user mapping status word */
8034642Smarc 	u_int kernel_loop;	/* if kernel console is redirected */
8134642Smarc 	u_int user_dma;		/* DMA from user space in progress */
8234642Smarc 	u_short pntr_id;	/* type code of pointing device */
8334642Smarc 	u_short duart_imask;	/* shadowing for duart intrpt mask reg */
8434642Smarc 	u_short adder_ie;	/* shadowing for adder intrpt enbl reg */
8534642Smarc 	u_short curs_acc;	/* cursor acceleration factor */
8634642Smarc 	u_short curs_thr;	/* cursor acceleration threshold level */
8734642Smarc 	u_short tab_res;	/* tablet resolution factor */
8834642Smarc 	u_short selmask;	/* mask for active qd select entries */
8934642Smarc };
9032012Smarc 
9134642Smarc /*
9234642Smarc  * bit definitions for 'inuse' entry
9334642Smarc  */
9432012Smarc #define CONS_DEV	0x01
9532012Smarc #define GRAPHIC_DEV	0x04
9632012Smarc 
9734642Smarc /*
9834642Smarc  * bit definitions for 'mapped' member of flag structure
9934642Smarc  */
10032012Smarc #define MAPDEV		0x01		/* hardware is mapped */
10132012Smarc #define MAPDMA		0x02		/* DMA buffer mapped */
10232012Smarc #define MAPEQ		0x04		/* event queue buffer mapped */
10332012Smarc #define MAPSCR		0x08		/* scroll param area mapped */
10432012Smarc #define MAPCOLOR	0x10		/* color map writing buffer mapped */
10532012Smarc 
10634642Smarc /*
10734642Smarc  * bit definitions for 'selmask' member of qdflag structure
10834642Smarc  */
10932012Smarc #define SEL_READ	0x01		/* read select is active */
11032012Smarc #define SEL_WRITE	0x02		/* write select is active */
11132012Smarc 
11234642Smarc /*
11334732Smarc  * constants used in shared memory operations
11434732Smarc  */
11532012Smarc #define EVENT_BUFSIZE  1024	/* # of bytes per device's event buffer */
11632012Smarc #define MAXEVENTS  ( (EVENT_BUFSIZE - sizeof(struct qdinput))	 \
11734642Smarc 	/ sizeof(struct _vs_event) )
11834527Smarc #define DMA_BUFSIZ	(1024 * 10)
11932012Smarc #define COLOR_BUFSIZ  ((sizeof(struct color_buf) + 512) & ~0x01FF)
12032012Smarc 
12134642Smarc /*
12234732Smarc  * reference to an array of "uba_device" structures built by the auto
12334732Smarc  * configuration program.  The uba_device structure decribes the device
12434732Smarc  * sufficiently for the driver to talk to it.  The auto configuration code
12534732Smarc  * fills in the uba_device structures (located in ioconf.c) from user
12634732Smarc  * maintained info.
12734732Smarc  */
12834642Smarc struct uba_device *qdinfo[NQD];  /* array of pntrs to each QDSS's */
12934642Smarc struct tty qd_tty[NQD*4];	/* teletype structures for each.. */
13034732Smarc extern char qvmem[][128*NBPG];
13134642Smarc extern struct pte QVmap[][128];
13234642Smarc #define CHUNK	  (64 * 1024)
13334642Smarc #define QMEMSIZE  (1024 * 1024 * 4)	/* 4 meg */
13432012Smarc 
13534642Smarc /*
13634642Smarc  * static storage used by multiple functions in this code
13734642Smarc  */
13834642Smarc int Qbus_unmap[NQD];		/* Qbus mapper release code */
13934642Smarc struct qdflags qdflags[NQD];	/* QDSS device status flags */
14034642Smarc struct qdmap qdmap[NQD];	/* QDSS register map structure */
14134642Smarc caddr_t qdbase[NQD];		/* base address of each QDSS unit */
14234642Smarc struct buf qdbuf[NQD];		/* buf structs used by strategy */
14334642Smarc short qdopened[NQD];		/* graphics device is open exclusive use */
14432012Smarc 
14534642Smarc /*
14634732Smarc  * the array "event_shared[]" is made up of a number of event queue buffers
14734732Smarc  * equal to the number of QDSS's configured into the running kernel (NQD).
14834732Smarc  * Each event queue buffer begins with an event queue header (struct qdinput)
14934732Smarc  * followed by a group of event queue entries (struct _vs_event).  The array
15034732Smarc  * "*eq_header[]" is an array of pointers to the start of each event queue
15134732Smarc  * buffer in "event_shared[]".
15234732Smarc  */
15332012Smarc #define EQSIZE ((EVENT_BUFSIZE * NQD) + 512)
15432012Smarc 
15534642Smarc char event_shared[EQSIZE];	    /* reserve space for event bufs */
15634642Smarc struct qdinput *eq_header[NQD];     /* event queue header pntrs */
15732012Smarc 
15834642Smarc /*
15934732Smarc  * This allocation method reserves enough memory pages for NQD shared DMA I/O
16034732Smarc  * buffers.  Each buffer must consume an integral number of memory pages to
16134732Smarc  * guarantee that a following buffer will begin on a page boundary.  Also,
16234732Smarc  * enough space is allocated so that the FIRST I/O buffer can start at the
16334732Smarc  * 1st page boundary after "&DMA_shared".  Page boundaries are used so that
16434732Smarc  * memory protections can be turned on/off for individual buffers.
16534732Smarc  */
16632012Smarc #define IOBUFSIZE  ((DMA_BUFSIZ * NQD) + 512)
16732012Smarc 
16834642Smarc char DMA_shared[IOBUFSIZE];	    /* reserve I/O buffer space */
16934642Smarc struct DMAreq_header *DMAheader[NQD];  /* DMA buffer header pntrs */
17032012Smarc 
17134642Smarc /*
17234732Smarc  * The driver assists a client in scroll operations by loading dragon
17334732Smarc  * registers from an interrupt service routine.	The loading is done using
17434732Smarc  * parameters found in memory shrade between the driver and it's client.
17534732Smarc  * The scroll parameter structures are ALL loacted in the same memory page
17634732Smarc  * for reasons of memory economy.
17734732Smarc  */
17834642Smarc char scroll_shared[2 * 512];	/* reserve space for scroll structs */
17934642Smarc struct scroll *scroll[NQD];	/* pointers to scroll structures */
18032012Smarc 
18134642Smarc /*
18234732Smarc  * the driver is programmable to provide the user with color map write
18334732Smarc  * services at VSYNC interrupt time.  At interrupt time the driver loads
18434732Smarc  * the color map with any user-requested load data found in shared memory
18534732Smarc  */
18632012Smarc #define COLOR_SHARED  ((COLOR_BUFSIZ * NQD) + 512)
18732012Smarc 
18834642Smarc char color_shared[COLOR_SHARED];      /* reserve space: color bufs */
18934642Smarc struct color_buf *color_buf[NQD];     /* pointers to color bufs */
19032012Smarc 
19134642Smarc /*
19234732Smarc  * mouse input event structures
19334732Smarc  */
19434642Smarc struct mouse_report last_rep[NQD];
19534642Smarc struct mouse_report current_rep[NQD];
19632012Smarc 
19734732Smarc struct proc *qdrsel[NQD]; 	/* process waiting for select */
19834642Smarc struct _vs_cursor cursor[NQD];	/* console cursor */
19934642Smarc int qdcount = 0;		/* count of successfully probed qd's */
20034642Smarc int nNQD = NQD;
20134642Smarc int DMAbuf_size = DMA_BUFSIZ;
20234642Smarc int QDlast_DMAtype;             /* type of the last DMA operation */
20332012Smarc 
20434642Smarc #define QDSSMAJOR	41	/* QDSS major device number */
20534642Smarc /*
20634732Smarc  * macro to get system time.  Used to time stamp event queue entries
20734732Smarc  */
20830391Skarels #define TOY ((time.tv_sec * 100) + (time.tv_usec / 10000))
20930391Skarels 
21034642Smarc int qdprobe();
21134642Smarc int qdattach();
21234642Smarc int qddint();			/* DMA gate array intrpt service */
21334642Smarc int qdaint();			/* Dragon ADDER intrpt service */
21434642Smarc int qdiint();
21530391Skarels 
21634642Smarc u_short qdstd[] = { 0 };
21730391Skarels 
21834642Smarc struct uba_driver qddriver = {
21934732Smarc 	qdprobe,		/* device probe entry */
22034732Smarc 	0,			/* no slave device */
22134732Smarc 	qdattach,		/* device attach entry */
22234732Smarc 	0,			/* no "fill csr/ba to start" */
22334642Smarc 	qdstd,			/* device addresses */
22434642Smarc 	"qd",			/* device name string */
22534642Smarc 	qdinfo			/* ptr to QDSS's uba_device struct */
22634642Smarc };
22730391Skarels 
22834615Smarc #define QDPRIOR (PZERO-1)		/* must be negative */
22930391Skarels #define FALSE	0
23030391Skarels #define TRUE	~FALSE
23130391Skarels #define BAD	-1
23230391Skarels #define GOOD	0
23330391Skarels 
23434642Smarc /*
23534642Smarc  * macro to create a system virtual page number from system virtual adrs
23634642Smarc  */
23734642Smarc #define VTOP(x)  (((int)x & ~0xC0000000) >> PGSHIFT)
23830391Skarels 
23934642Smarc /*
24034642Smarc  * QDSS register address offsets from start of QDSS address space
24134642Smarc  */
24230391Skarels #define QDSIZE	 (52 * 1024)	/* size of entire QDSS foot print */
24330391Skarels #define TMPSIZE  (16 * 1024)	/* template RAM is 8k SHORT WORDS */
24430391Skarels #define TMPSTART 0x8000 	/* offset of template RAM from base adrs */
24530391Skarels #define REGSIZE  (5 * 512)	/* regs touch 2.5k (5 pages) of addr space */
24630391Skarels #define REGSTART 0xC000 	/* offset of reg pages from base adrs */
24730391Skarels #define ADDER	(REGSTART+0x000)
24830391Skarels #define DGA	(REGSTART+0x200)
24930391Skarels #define DUART	(REGSTART+0x400)
25030391Skarels #define MEMCSR	(REGSTART+0x800)
25130391Skarels #define CLRSIZE  (3 * 512)		/* color map size */
25230391Skarels #define CLRSTART (REGSTART+0xA00)	/* color map start offset from base */
25334642Smarc /*  0x0C00 really */
25430391Skarels #define RED	(CLRSTART+0x000)
25530391Skarels #define BLUE	(CLRSTART+0x200)
25630391Skarels #define GREEN	(CLRSTART+0x400)
25730391Skarels 
25830391Skarels 
25934642Smarc /*
26034642Smarc  * QDSS minor device numbers.  The *real* minor device numbers are in
26134642Smarc  * the bottom two bits of the major/minor device spec.  Bits 2 and up are
26234642Smarc  * used to specify the QDSS device number (ie: which one?)
26334642Smarc  */
26430391Skarels 
26530391Skarels #define CONS		0
26630391Skarels #define GRAPHIC 	2
26730391Skarels 
26834642Smarc /*
26934642Smarc  * console cursor bitmap (white block cursor)
27034642Smarc  */
27134642Smarc short cons_cursor[32] = {
27234642Smarc 	/* A */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
27334642Smarc 	0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
27434642Smarc 	/* B */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
27534642Smarc 	0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF
27634642Smarc };
27730391Skarels 
27834642Smarc /*
27934642Smarc  * constants used in font operations
28034642Smarc  */
28134615Smarc #define CHARS		190 			/* # of chars in the font */
28230391Skarels #define CHAR_HEIGHT	15			/* char height in pixels */
28330391Skarels #define CHAR_WIDTH	8			/* char width in pixels*/
28430391Skarels #define FONT_WIDTH	(CHAR_WIDTH * CHARS)	/* font width in pixels */
28530391Skarels #define ROWS		CHAR_HEIGHT
28630391Skarels #define FONT_X		0			/* font's off screen adrs */
28730391Skarels #define FONT_Y		(2048 - CHAR_HEIGHT)
28830391Skarels 
28934642Smarc /* Offset to second row characters (XXX - should remove) */
29034615Smarc #define FONT_OFFSET	((MAX_SCREEN_X/CHAR_WIDTH)*CHAR_HEIGHT)
29130391Skarels 
29234642Smarc extern char q_font[];		/* reference font object code */
29334642Smarc extern	u_short q_key[];	/* reference key xlation tables */
29434642Smarc extern	u_short q_shift_key[];
29534642Smarc extern	char *q_special[];
29630391Skarels 
29734642Smarc /*
29834642Smarc  * definitions for cursor acceleration reporting
29934642Smarc  */
30030391Skarels #define ACC_OFF 	0x01		/* acceleration is inactive */
30130391Skarels 
30234642Smarc /*
30334642Smarc  * virtual console support.
30434642Smarc  */
30534642Smarc extern (*v_putc)();
306*40817Smarc #ifdef KADB
307*40817Smarc extern (*v_getc)();
308*40817Smarc extern (*v_poll)();
309*40817Smarc #endif
31034642Smarc extern struct cdevsw *consops;
31134642Smarc int qdputc();
312*40817Smarc int qdgetc();
313*40817Smarc int qdpoll();
31434642Smarc int qdstart();
315*40817Smarc int qdpolling = 0;
31630391Skarels 
31734642Smarc /*
31834642Smarc  * LK-201 state storage for input console keyboard conversion to ASCII
31934642Smarc  */
32034642Smarc struct q_keyboard {
32134642Smarc 	int shift;			/* state variables	*/
32234642Smarc 	int cntrl;
32334642Smarc 	int lock;
32434642Smarc 	int lastcode;			/* last keycode typed	*/
32534642Smarc 	unsigned kup[8];		/* bits for each keycode*/
32634642Smarc 	unsigned dkeys[8];		/* down/up mode keys	*/
32734642Smarc 	char last;			/* last character	*/
32834642Smarc } q_keyboard;
32930391Skarels 
33034642Smarc /*
33134642Smarc  * tty settings on first open
33234642Smarc  */
333*40817Smarc #define IFLAG (BRKINT|ISTRIP|IXON|IXANY|ICRNL|IMAXBEL)
33434615Smarc #define OFLAG (OPOST|OXTABS|ONLCR)
335*40817Smarc #define LFLAG (ISIG|ICANON|ECHO|IEXTEN)
33634615Smarc #define CFLAG (PARENB|CREAD|CS7|CLOCAL)
33734615Smarc 
33834732Smarc /*
33934732Smarc  * Init QDSS as console (before probe routine)
34034732Smarc  */
34130391Skarels 
34230391Skarels qdcons_init()
34330391Skarels {
34434732Smarc 	register unit;
34530391Skarels 	caddr_t phys_adr;		/* physical QDSS base adrs */
34634615Smarc 	u_int mapix;			/* index into QVmap[] array */
34734615Smarc 	struct percpu *pcpu;		/* pointer to cpusw structure  */
34834615Smarc 	register struct qbus *qb;
34930391Skarels 	u_short *qdaddr;		/* address of QDSS IO page CSR */
35030391Skarels 	u_short *devptr;		/* vitual device space */
35134615Smarc 	extern cnputc();
35230391Skarels 
35330391Skarels #define QDSSCSR 0x1F00
35430391Skarels 
35532012Smarc 	if (v_putc != cnputc)
35634732Smarc 	    return 0;
35732012Smarc 
35830391Skarels 	unit = 0;
35930391Skarels 
36034642Smarc 	/*
36134642Smarc 	 * find the cpusw entry that matches this machine.
36234642Smarc 	 */
36332012Smarc 	for (pcpu = percpu; pcpu && pcpu->pc_cputype != cpu; pcpu++)
36432012Smarc 		;
36532012Smarc 	if (pcpu == NULL)
36634732Smarc 	    return 0;
36736705Stef 	if (pcpu->pc_io->io_type != IO_QBUS)
36836705Stef 	    return 0;
36930391Skarels 
37032012Smarc 	/*
37134615Smarc 	 * Map device registers - the last 8K of qvmem.
37232012Smarc 	 */
37332012Smarc 	qb = (struct qbus *)pcpu->pc_io->io_details;
37432012Smarc 	ioaccess(qb->qb_iopage, UMEMmap[0] + qb->qb_memsize,
37534732Smarc 		 UBAIOPAGES * NBPG);
37632012Smarc 	devptr = (u_short *)((char *)umem[0]+(qb->qb_memsize * NBPG));
37730391Skarels 	qdaddr = (u_short *)((u_int)devptr + ubdevreg(QDSSCSR));
37834732Smarc 	if (badaddr((caddr_t)qdaddr, sizeof(short)))
37934732Smarc 		return 0;
38034615Smarc 
38132012Smarc 	/*
38232012Smarc 	 * Map q-bus memory used by qdss. (separate map)
38332012Smarc 	 */
38432012Smarc 	mapix = QMEMSIZE - (CHUNK * (unit + 1));
38532012Smarc 	phys_adr = qb->qb_maddr + mapix;
38632012Smarc 	ioaccess(phys_adr, QVmap[0], (CHUNK*NQD));
38730391Skarels 
38832012Smarc 	/*
38932012Smarc 	 * tell QDSS which Q memory address base to decode
39034642Smarc 	 * (shifted right 16 bits - its in 64K units)
39132012Smarc 	 */
39232012Smarc 	*qdaddr = (u_short)((int)mapix >> 16);
39330391Skarels 	qdflags[unit].config = *(u_short *)qdaddr;
39430391Skarels 
39534642Smarc 	/*
39634642Smarc 	 * load qdmap struct with the virtual addresses of the QDSS elements
39734642Smarc 	 */
39834615Smarc 	qdbase[unit] = (caddr_t) (qvmem[0]);
39930391Skarels 	qdmap[unit].template = qdbase[unit] + TMPSTART;
40030391Skarels 	qdmap[unit].adder = qdbase[unit] + ADDER;
40130391Skarels 	qdmap[unit].dga = qdbase[unit] + DGA;
40230391Skarels 	qdmap[unit].duart = qdbase[unit] + DUART;
40330391Skarels 	qdmap[unit].memcsr = qdbase[unit] + MEMCSR;
40430391Skarels 	qdmap[unit].red = qdbase[unit] + RED;
40530391Skarels 	qdmap[unit].blue = qdbase[unit] + BLUE;
40630391Skarels 	qdmap[unit].green = qdbase[unit] + GREEN;
40730391Skarels 
40830391Skarels 	qdflags[unit].duart_imask = 0;	/* init shadow variables */
40930391Skarels 
41034642Smarc 	/*
41134642Smarc 	 * init the QDSS
41234642Smarc 	 */
41334642Smarc 	/*
41432012Smarc 	printf("qdbase[0] = %x, qdmap[0].memcsr = %x\n",
41534642Smarc 		(char *)qdbase[0], qdmap[0].memcsr);
41634642Smarc 	*/
41732012Smarc 
41830391Skarels 	*(short *)qdmap[unit].memcsr |= SYNC_ON; /* once only: turn on sync */
41930391Skarels 
42030391Skarels 	cursor[unit].x = 0;
42130391Skarels 	cursor[unit].y = 0;
42230391Skarels 	init_shared(unit);		/* init shared memory */
42330391Skarels 	setup_dragon(unit);		/* init the ADDER/VIPER stuff */
42430391Skarels 	clear_qd_screen(unit);		/* clear the screen */
42530391Skarels 	ldfont(unit);			/* load the console font */
42630391Skarels 	ldcursor(unit, cons_cursor);	/* load default cursor map */
42730391Skarels 	setup_input(unit);		/* init the DUART */
42834642Smarc 	v_putc = qdputc;		/* kernel console output to qdss */
429*40817Smarc #ifdef KADB
430*40817Smarc 	v_getc = qdgetc;		/* kernel console input from qdss */
431*40817Smarc 	v_poll = qdpoll;		/* kdb hook to disable char intr */
432*40817Smarc #endif
43334642Smarc 	consops = &cdevsw[QDSSMAJOR];	/* virtual console is qdss */
43434732Smarc 	return 1;
43530391Skarels 
43630391Skarels } /* qdcons_init */
43730391Skarels 
43834732Smarc /*
43934732Smarc  *  Configure QDSS into Q memory and make it intrpt.
44034732Smarc  *
44134732Smarc  *  side effects: QDSS gets mapped into Qbus memory space at the first
44234732Smarc  *		 vacant 64kb boundary counting back from the top of
44334732Smarc  *		 Qbus memory space (qvmem+4mb)
44434732Smarc  *
44534732Smarc  *  return: QDSS bus request level and vector address returned in
44634732Smarc  *	   registers by UNIX convention.
44734732Smarc  *
44834732Smarc  */
44930391Skarels qdprobe(reg)
45034732Smarc 	caddr_t reg;	/* character pointer to the QDSS I/O page register */
45130391Skarels {
452*40817Smarc 	register int br, cvec;
45330391Skarels 	register int unit;
45430391Skarels 	struct dga *dga;		/* pointer to gate array structure */
45534732Smarc 	int vector;
45634732Smarc #ifdef notdef
45730391Skarels 	int *ptep;			/* page table entry pointer */
45830391Skarels 	caddr_t phys_adr;		/* physical QDSS base adrs */
45930391Skarels 	u_int mapix;
46034732Smarc #endif
46130391Skarels 
46234732Smarc #ifdef lint
46334732Smarc 	br = 0; cvec = br; br = cvec; nNQD = br; br = nNQD;
46434732Smarc 	qddint(0); qdaint(0); qdiint(0); (void)qdgetc();
46534732Smarc #endif
46634732Smarc 
46734642Smarc 	/*
46834642Smarc 	 * calculate board unit number from I/O page register address
46934642Smarc 	 */
47030391Skarels 	unit = (int) (((int)reg >> 1) & 0x0007);
47130391Skarels 
47234642Smarc 	/*
47334642Smarc 	 * QDSS regs must be mapped to Qbus memory space at a 64kb
47434642Smarc  	 * physical boundary.  The Qbus memory space is mapped into
47534642Smarc 	 * the system memory space at config time.  After config
47634642Smarc 	 * runs, "qvmem[0]" (ubavar.h) holds the system virtual adrs
47734642Smarc 	 * of the start of Qbus memory.   The Qbus memory page table
47834642Smarc 	 * is found via an array of pte ptrs called "QVmap[]" (ubavar.h)
47934642Smarc 	 * which is also loaded at config time.   These are the
48034642Smarc 	 * variables used below to find a vacant 64kb boundary in
48134642Smarc 	 * Qbus memory, and load it's corresponding physical adrs
48234642Smarc 	 * into the QDSS's I/O page CSR.
48334642Smarc 	 */
48430391Skarels 
48534615Smarc 	/*
48634615Smarc 	 * Only if QD is the graphics device.
48734615Smarc 	 */
48834615Smarc 
48930391Skarels 	/* if this QDSS is NOT the console, then do init here.. */
49030391Skarels 
49134615Smarc 	if (unit != 0) {
49234615Smarc 		printf("qd: can't support two qdss's (yet)\n");
49334732Smarc #ifdef notdef	/* can't test */
49434642Smarc 		if (v_consputc != qdputc  ||  unit != 0) {
49530391Skarels 
49634642Smarc 			/*
49734642Smarc 			* read QDSS config info
49834642Smarc 			*/
49934642Smarc 			qdflags[unit].config = *(u_short *)reg;
50034615Smarc 
50134642Smarc 			/*
50234642Smarc 			* find an empty 64kb adrs boundary
50334642Smarc 			*/
50430391Skarels 
50534642Smarc 			qdbase[unit] = (caddr_t) (qvmem[0] + QMEMSIZE - CHUNK);
50630391Skarels 
50734642Smarc 			/*
50834732Smarc 			* find the cpusw entry that matches this machine.
50934732Smarc 			*/
51034642Smarc 			cpup = &cpusw[cpu];
51134732Smarc 			while (!(BADADDR(qdbase[unit], sizeof(short))))
51234732Smarc 				qdbase[unit] -= CHUNK;
51334615Smarc 
51434642Smarc 			/*
51534732Smarc 			* tell QDSS which Q memory address base to decode
51634732Smarc 			*/
51734642Smarc 			mapix = (int) (VTOP(qdbase[unit]) - VTOP(qvmem[0]));
51834642Smarc 			ptep = (int *) QVmap[0] + mapix;
51934642Smarc 			phys_adr = (caddr_t)(((int)*ptep&0x001FFFFF)<<PGSHIFT);
52034642Smarc 			*(u_short *)reg = (u_short) ((int)phys_adr >> 16);
52134615Smarc 
52234642Smarc 			/*
52334642Smarc 			* load QDSS adrs map with system addresses
52434642Smarc 			* of device regs
52534642Smarc 			*/
52634642Smarc 			qdmap[unit].template = qdbase[unit] + TMPSTART;
52734642Smarc 			qdmap[unit].adder = qdbase[unit] + ADDER;
52834642Smarc 			qdmap[unit].dga = qdbase[unit] + DGA;
52934642Smarc 			qdmap[unit].duart = qdbase[unit] + DUART;
53034642Smarc 			qdmap[unit].memcsr = qdbase[unit] + MEMCSR;
53134642Smarc 			qdmap[unit].red = qdbase[unit] + RED;
53234642Smarc 			qdmap[unit].blue = qdbase[unit] + BLUE;
53334642Smarc 			qdmap[unit].green = qdbase[unit] + GREEN;
53430391Skarels 
53534642Smarc 			/* device init */
53634615Smarc 
53734642Smarc 			cursor[unit].x = 0;
53834642Smarc 			cursor[unit].y = 0;
53934642Smarc 			init_shared(unit);		/* init shared memory */
54034642Smarc 			setup_dragon(unit); 	/* init the ADDER/VIPER stuff */
54134642Smarc 			ldcursor(unit, cons_cursor);	/* load default cursor map */
54234642Smarc 			setup_input(unit);		/* init the DUART */
54334642Smarc 			clear_qd_screen(unit);
54434642Smarc 			ldfont(unit);			/* load the console font */
54530391Skarels 
54634642Smarc 			/* once only: turn on sync */
54730391Skarels 
54834642Smarc 			*(short *)qdmap[unit].memcsr |= SYNC_ON;
54934642Smarc 		}
55034615Smarc #endif /*notdef*/
55130391Skarels 	}
55230391Skarels 
55334642Smarc 	/*
55434642Smarc 	* The QDSS interrupts at HEX vectors xx0 (DMA) xx4
55534642Smarc 	* (ADDER) and xx8 (DUART).  Therefore, we take three
55634642Smarc 	* vectors from the vector pool, and then continue
55734642Smarc 	* to take them until we get a xx0 HEX vector.  The
55834642Smarc 	* pool provides vectors in contiguous decending
55934642Smarc 	* order.
56034642Smarc 	*/
56130391Skarels 
56230391Skarels 	vector = (uba_hd[0].uh_lastiv -= 4*3);	/* take three vectors */
56330391Skarels 
56434642Smarc 	while (vector & 0x0F) {		   /* if lo nibble != 0.. */
56534642Smarc 		/* ..take another vector */
56634642Smarc 		vector = (uba_hd[0].uh_lastiv -= 4);
56730391Skarels 	}
56830391Skarels 
56934642Smarc 	/*
57034642Smarc 	* setup DGA to do a DMA interrupt (transfer count = 0)
57134642Smarc 	*/
57230391Skarels 	dga = (struct dga *) qdmap[unit].dga;
57334642Smarc 	dga->csr = (short) HALT;	/* disable everything */
57434642Smarc 	dga->ivr = (short) vector;	/* load intrpt base vector */
57534642Smarc 	dga->bytcnt_lo = (short) 0;	/* DMA xfer count = 0 */
57630391Skarels 	dga->bytcnt_hi = (short) 0;
57730391Skarels 
57834642Smarc 	/*
57934642Smarc 	* turn on DMA interrupts
58034642Smarc 	*/
58130391Skarels 	dga->csr &= ~SET_DONE_FIFO;
58230391Skarels 	dga->csr |= DMA_IE | DL_ENB;
58330391Skarels 
58430391Skarels 	DELAY(20000);			/* wait for the intrpt */
58530391Skarels 	dga->csr = HALT;		/* stop the wheels */
58630391Skarels 
58730391Skarels 	if (cvec != vector)		/* if vector != base vector.. */
58834732Smarc 		return(0);		/* ..return = 'no device' */
58930391Skarels 
59034615Smarc 	/*
59134642Smarc 	* score this as an existing qdss
59234642Smarc 	*/
59334615Smarc 	qdcount++;
59434615Smarc 
59530391Skarels 	return(sizeof(short));	    /* return size of QDSS I/O page reg */
59630391Skarels 
59730391Skarels } /* qdprobe */
59830391Skarels 
59930391Skarels qdattach(ui)
60034642Smarc 	struct uba_device *ui;
60130391Skarels {
60234732Smarc 	register unit;			/* QDSS module # for this call */
60330391Skarels 
60430391Skarels 	unit = ui->ui_unit;		/* get QDSS number */
60530391Skarels 
60634642Smarc 	/*
60734642Smarc 	* init "qdflags[]" for this QDSS
60834642Smarc 	*/
60930391Skarels 	qdflags[unit].inuse = 0;	/* init inuse variable EARLY! */
61030391Skarels 	qdflags[unit].mapped = 0;
61134615Smarc 	qdflags[unit].kernel_loop = -1;
61230391Skarels 	qdflags[unit].user_dma = 0;
61330391Skarels 	qdflags[unit].curs_acc = ACC_OFF;
61430391Skarels 	qdflags[unit].curs_thr = 128;
61530391Skarels 	qdflags[unit].tab_res = 2;	/* default tablet resolution factor */
61630391Skarels 	qdflags[unit].duart_imask = 0;	/* init shadow variables */
61730391Skarels 	qdflags[unit].adder_ie = 0;
61830391Skarels 
61934642Smarc 	/*
62034642Smarc 	* init structures used in kbd/mouse interrupt service.	This code must
62134642Smarc 	* come after the "init_shared()" routine has run since that routine
62234642Smarc 	* inits the eq_header[unit] structure used here.
62334642Smarc 	*/
62430391Skarels 
62534642Smarc 	/*
62634642Smarc 	* init the "latest mouse report" structure
62734642Smarc 	*/
62830391Skarels 	last_rep[unit].state = 0;
62930391Skarels 	last_rep[unit].dx = 0;
63030391Skarels 	last_rep[unit].dy = 0;
63130391Skarels 	last_rep[unit].bytcnt = 0;
63230391Skarels 
63334642Smarc 	/*
63434732Smarc 	* init the event queue (except mouse position)
63534732Smarc 	*/
63634732Smarc 	eq_header[unit]->header.events =
63734732Smarc 	    (struct _vs_event *)((int)eq_header[unit] + sizeof(struct qdinput));
63830391Skarels 
63930391Skarels 	eq_header[unit]->header.size = MAXEVENTS;
64030391Skarels 	eq_header[unit]->header.head = 0;
64130391Skarels 	eq_header[unit]->header.tail = 0;
64230391Skarels 
64334642Smarc 	/*
64434642Smarc 	 * open exclusive for graphics device.
64534642Smarc 	 */
64634642Smarc 	qdopened[unit] = 0;
64730391Skarels 
64830391Skarels } /* qdattach */
64930391Skarels 
65034732Smarc /*ARGSUSED*/
65130391Skarels qdopen(dev, flag)
65234642Smarc 	dev_t dev;
65334642Smarc 	int flag;
65430391Skarels {
65530391Skarels 	register struct uba_device *ui; /* ptr to uba structures */
65630391Skarels 	register struct dga *dga;	/* ptr to gate array struct */
65730391Skarels 	register struct tty *tp;
65830391Skarels 	struct duart *duart;
65934732Smarc 	int unit;
66034732Smarc 	int minor_dev;
66130391Skarels 
66230391Skarels 	minor_dev = minor(dev); /* get QDSS minor device number */
66330391Skarels 	unit = minor_dev >> 2;
66430391Skarels 
66534642Smarc 	/*
66634642Smarc 	* check for illegal conditions
66734642Smarc 	*/
66830391Skarels 	ui = qdinfo[unit];		/* get ptr to QDSS device struct */
66930391Skarels 	if (ui == 0  || ui->ui_alive == 0)
67034642Smarc 		return(ENXIO);		/* no such device or address */
67130391Skarels 
67230391Skarels 	duart = (struct duart *) qdmap[unit].duart;
67330391Skarels 	dga = (struct dga *) qdmap[unit].dga;
67430391Skarels 
67530391Skarels 	if ((minor_dev & 0x03) == 2) {
67634642Smarc 		/*
67734642Smarc 		* this is the graphic device...
67834642Smarc 		*/
67934642Smarc 		if (qdopened[unit] != 0)
68034732Smarc 			return(EBUSY);
68134642Smarc 		else
68234642Smarc 			qdopened[unit] = 1;
68334642Smarc 		qdflags[unit].inuse |= GRAPHIC_DEV;  /* graphics dev is open */
68434642Smarc 		/*
68534642Smarc 		 * enble kbd & mouse intrpts in DUART mask reg
68634642Smarc 		 */
68734642Smarc 		qdflags[unit].duart_imask |= 0x22;
68834642Smarc 		duart->imask = qdflags[unit].duart_imask;
68934642Smarc 	} else {
69034642Smarc 		/*
69134642Smarc 		* this is the console
69234642Smarc 		*/
69334642Smarc 		qdflags[unit].inuse |= CONS_DEV;  /* mark console as open */
69434642Smarc 		dga->csr |= CURS_ENB;
69534642Smarc 		qdflags[unit].duart_imask |= 0x02;
69634642Smarc 		duart->imask = qdflags[unit].duart_imask;
69734642Smarc 		/*
69834642Smarc 		* some setup for tty handling
69934642Smarc 		*/
70034642Smarc 		tp = &qd_tty[minor_dev];
70134642Smarc 		tp->t_addr = ui->ui_addr;
70234642Smarc 		tp->t_oproc = qdstart;
70334642Smarc 		if ((tp->t_state & TS_ISOPEN) == 0) {
70434642Smarc 			ttychars(tp);
70534642Smarc 			tp->t_ispeed = B9600;
70634642Smarc 			tp->t_ospeed = B9600;
70734642Smarc 			tp->t_state = TS_ISOPEN | TS_CARR_ON;
70834642Smarc 			tp->t_iflag = TTYDEF_IFLAG;
70934642Smarc 			tp->t_oflag = TTYDEF_OFLAG;
71034642Smarc 			tp->t_lflag = TTYDEF_LFLAG;
71134642Smarc 			tp->t_cflag = TTYDEF_CFLAG;
71232012Smarc 		}
71334642Smarc 		/*
71434642Smarc 		* enable intrpts, open line discipline
71534642Smarc 		*/
71634642Smarc 		dga->csr |= GLOBAL_IE;	/* turn on the interrupts */
71734642Smarc 		return ((*linesw[tp->t_line].l_open)(dev, tp));
71830391Skarels 	}
71930391Skarels 	dga->csr |= GLOBAL_IE;	/* turn on the interrupts */
72030391Skarels 	return(0);
72130391Skarels 
72230391Skarels } /* qdopen */
72330391Skarels 
72434732Smarc /*ARGSUSED*/
72530391Skarels qdclose(dev, flag)
72634642Smarc 	dev_t dev;
72734642Smarc 	int flag;
72830391Skarels {
72930391Skarels 	register struct tty *tp;
73030391Skarels 	register struct qdmap *qd;
73130391Skarels 	register int *ptep;
73230391Skarels 	struct dga *dga;		/* gate array register map pointer */
73330391Skarels 	struct duart *duart;
73430391Skarels 	struct adder *adder;
73534732Smarc 	int unit;
73634732Smarc 	int minor_dev;
73730391Skarels 	u_int mapix;
73834642Smarc 	int i;				/* SIGNED index */
73930391Skarels 
74030391Skarels 	minor_dev = minor(dev); 	/* get minor device number */
74130391Skarels 	unit = minor_dev >> 2;		/* get QDSS number */
74230391Skarels 	qd = &qdmap[unit];
74330391Skarels 
74430391Skarels 	if ((minor_dev & 0x03) == 2) {
74534642Smarc 		/*
74634642Smarc 		* this is the graphic device...
74734642Smarc 		*/
74834642Smarc 		if (qdopened[unit] != 1)
74934732Smarc 		    	return(EBUSY);
75034642Smarc 		else
75134642Smarc 			qdopened[unit] = 0;	/* allow it to be re-opened */
75234642Smarc 		/*
75334642Smarc 		* re-protect device memory
75434642Smarc 		*/
75534642Smarc 		if (qdflags[unit].mapped & MAPDEV) {
75634642Smarc 			/*
75734642Smarc 			* TEMPLATE RAM
75834642Smarc 			*/
75934642Smarc 			mapix = VTOP((int)qd->template) - VTOP(qvmem[0]);
76034642Smarc 			ptep = (int *)(QVmap[0] + mapix);
76134732Smarc 			for (i = 0; i < btop(TMPSIZE); i++, ptep++)
76234732Smarc 				*ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
76334642Smarc 			/*
76434642Smarc 			* ADDER
76534642Smarc 			*/
76634642Smarc 			mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]);
76734642Smarc 			ptep = (int *)(QVmap[0] + mapix);
76834732Smarc 			for (i = 0; i < btop(REGSIZE); i++, ptep++)
76934732Smarc 				*ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
77034642Smarc 			/*
77134642Smarc 			* COLOR MAPS
77234642Smarc 			*/
77334642Smarc 			mapix = VTOP((int)qd->red) - VTOP(qvmem[0]);
77434642Smarc 			ptep = (int *)(QVmap[0] + mapix);
77534732Smarc 			for (i = 0; i < btop(CLRSIZE); i++, ptep++)
77634732Smarc 				*ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
77734642Smarc 		}
77834615Smarc 
77934642Smarc 		/*
78034642Smarc 		* re-protect DMA buffer and free the map registers
78134642Smarc 		*/
78234642Smarc 		if (qdflags[unit].mapped & MAPDMA) {
78334642Smarc 			dga = (struct dga *) qdmap[unit].dga;
78434642Smarc 			adder = (struct adder *) qdmap[unit].adder;
78534642Smarc 			dga->csr &= ~DMA_IE;
78634642Smarc 			dga->csr &= ~0x0600;	     /* kill DMA */
78734642Smarc 			adder->command = CANCEL;
78834642Smarc 			/*
78934642Smarc 			 * if DMA was running, flush spurious intrpt
79034642Smarc 			 */
79134642Smarc 			if (dga->bytcnt_lo != 0) {
79234642Smarc 				dga->bytcnt_lo = 0;
79334642Smarc 				dga->bytcnt_hi = 0;
79434642Smarc 				DMA_SETIGNORE(DMAheader[unit]);
79534642Smarc 				dga->csr |= DMA_IE;
79634642Smarc 				dga->csr &= ~DMA_IE;
79734642Smarc 			}
79834642Smarc 			ptep = (int *)
79934642Smarc 			   ((VTOP(DMAheader[unit]*4)) + (mfpr(SBR)|0x80000000));
80034732Smarc 			for (i = 0; i < btop(DMAbuf_size); i++, ptep++)
80134732Smarc 				*ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
80234642Smarc 			ubarelse(0, &Qbus_unmap[unit]);
80334642Smarc 		}
80434615Smarc 
80534642Smarc 		/*
80634642Smarc 		* re-protect 1K (2 pages) event queue
80734642Smarc 		*/
80834642Smarc 		if (qdflags[unit].mapped & MAPEQ) {
80934642Smarc 			ptep = (int *)
81034642Smarc 			   ((VTOP(eq_header[unit])*4) + (mfpr(SBR)|0x80000000));
81134732Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++;
81234642Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
81330391Skarels 		}
81434642Smarc 		/*
81534642Smarc 		* re-protect scroll param area and disable scroll intrpts
81634642Smarc 		*/
81734642Smarc 		if (qdflags[unit].mapped & MAPSCR) {
81834642Smarc 			ptep = (int *) ((VTOP(scroll[unit]) * 4)
81934642Smarc 				+ (mfpr(SBR) | 0x80000000));
82034642Smarc 			/*
82134642Smarc 			 * re-protect 512 scroll param area
82234642Smarc 			 */
82334642Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
82434642Smarc 			adder = (struct adder *) qdmap[unit].adder;
82534642Smarc 			qdflags[unit].adder_ie &= ~FRAME_SYNC;
82634642Smarc 			adder->interrupt_enable = qdflags[unit].adder_ie;
82734642Smarc 		}
82834642Smarc 		/*
82934642Smarc 		* re-protect color map write buffer area and kill intrpts
83034642Smarc 		*/
83134642Smarc 		if (qdflags[unit].mapped & MAPCOLOR) {
83234642Smarc 			ptep = (int *) ((VTOP(color_buf[unit]) * 4)
83334642Smarc 				+ (mfpr(SBR) | 0x80000000));
83434732Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++;
83534642Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
83634642Smarc 			color_buf[unit]->status = 0;
83734642Smarc 			adder = (struct adder *) qdmap[unit].adder;
83834642Smarc 			qdflags[unit].adder_ie &= ~VSYNC;
83934642Smarc 			adder->interrupt_enable = qdflags[unit].adder_ie;
84034642Smarc 		}
84134642Smarc 		mtpr(TBIA, 0);
84234642Smarc 		/* flag everything now unmapped */
84334642Smarc 		qdflags[unit].mapped = 0;
84434642Smarc 		qdflags[unit].inuse &= ~GRAPHIC_DEV;
84534642Smarc 		qdflags[unit].curs_acc = ACC_OFF;
84634642Smarc 		qdflags[unit].curs_thr = 128;
84734642Smarc 		/*
84834642Smarc 		* restore the console
84934642Smarc 		*/
85030391Skarels 		dga = (struct dga *) qdmap[unit].dga;
85130391Skarels 		adder = (struct adder *) qdmap[unit].adder;
85230391Skarels 		dga->csr &= ~DMA_IE;
85330391Skarels 		dga->csr &= ~0x0600;	/* halt the DMA! (just in case...) */
85430391Skarels 		dga->csr |= DMA_ERR;	/* clear error condition */
85530391Skarels 		adder->command = CANCEL;
85634642Smarc 		/*
85734642Smarc 		 * if DMA was running, flush spurious intrpt
85834642Smarc 		 */
85930391Skarels 		if (dga->bytcnt_lo != 0) {
86034642Smarc 			dga->bytcnt_lo = 0;
86134642Smarc 			dga->bytcnt_hi = 0;
86234642Smarc 			DMA_SETIGNORE(DMAheader[unit]);
86334642Smarc 			dga->csr |= DMA_IE;
86434642Smarc 			dga->csr &= ~DMA_IE;
86530391Skarels 		}
86630391Skarels 		init_shared(unit);		/* init shared memory */
86730391Skarels 		setup_dragon(unit);		/* init ADDER/VIPER */
86830391Skarels 		ldcursor(unit, cons_cursor);	/* load default cursor map */
86930391Skarels 		setup_input(unit);		/* init the DUART */
87030391Skarels 		ldfont(unit);
87130391Skarels 		cursor[unit].x = 0;
87230391Skarels 		cursor[unit].y = 0;
87334642Smarc 		/*
87434642Smarc 		 * shut off the mouse rcv intrpt and turn on kbd intrpts
87534642Smarc 		 */
87634642Smarc 		duart = (struct duart *) qdmap[unit].duart;
87734642Smarc 		qdflags[unit].duart_imask &= ~(0x20);
87834642Smarc 		qdflags[unit].duart_imask |= 0x02;
87934642Smarc 		duart->imask = qdflags[unit].duart_imask;
88034642Smarc 		/*
88134642Smarc 		* shut off interrupts if all is closed
88234642Smarc 		*/
88334642Smarc 		if (!(qdflags[unit].inuse & CONS_DEV)) {
88434642Smarc 			dga = (struct dga *) qdmap[unit].dga;
88534642Smarc 			dga->csr &= ~(GLOBAL_IE | DMA_IE);
88634642Smarc 		}
88734642Smarc 	} else {
88834642Smarc 		/*
88934642Smarc 		* this is the console
89034642Smarc 		*/
89134642Smarc 		tp = &qd_tty[minor_dev];
89234642Smarc 		(*linesw[tp->t_line].l_close)(tp);
89334642Smarc 		ttyclose(tp);
89434642Smarc 		tp->t_state = 0;
89534642Smarc 		qdflags[unit].inuse &= ~CONS_DEV;
89634642Smarc 		/*
89734642Smarc 		* if graphics device is closed, kill interrupts
89834642Smarc 		*/
89934642Smarc 		if (!(qdflags[unit].inuse & GRAPHIC_DEV)) {
90034642Smarc 			dga = (struct dga *) qdmap[unit].dga;
90134642Smarc 			dga->csr &= ~(GLOBAL_IE | DMA_IE);
90234642Smarc 		}
90330391Skarels 	}
90434615Smarc 
90530391Skarels 	return(0);
90630391Skarels 
90730391Skarels } /* qdclose */
90830391Skarels 
90930391Skarels qdioctl(dev, cmd, datap, flags)
91034642Smarc 	dev_t dev;
91134642Smarc 	int cmd;
91234732Smarc 	register caddr_t datap;
91334642Smarc 	int flags;
91430391Skarels {
91530391Skarels 	register int *ptep;		/* page table entry pointer */
91632012Smarc 	register int mapix;		/* QVmap[] page table index */
91730391Skarels 	register struct _vs_event *event;
91830391Skarels 	register struct tty *tp;
91934732Smarc 	register i;
92030391Skarels 	struct qdmap *qd;		/* pointer to device map struct */
92130391Skarels 	struct dga *dga;		/* Gate Array reg structure pntr */
92230391Skarels 	struct duart *duart;		/* DUART reg structure pointer */
92330391Skarels 	struct adder *adder;		/* ADDER reg structure pointer */
92430391Skarels 	struct prgkbd *cmdbuf;
92530391Skarels 	struct prg_cursor *curs;
92630391Skarels 	struct _vs_cursor *pos;
92734732Smarc 	int unit = minor(dev) >> 2;	/* number of caller's QDSS */
92830391Skarels 	u_int minor_dev = minor(dev);
92930391Skarels 	int error;
93030391Skarels 	int s;
93130391Skarels 	short *temp;			/* a pointer to template RAM */
93230391Skarels 
93334642Smarc 	/*
93434642Smarc 	* service graphic device ioctl commands
93534642Smarc 	*/
93630391Skarels 	switch (cmd) {
93734615Smarc 
93834642Smarc 	case QD_GETEVENT:
93934642Smarc 		/*
94034642Smarc 		* extract the oldest event from the event queue
94134642Smarc 		*/
94230391Skarels 		if (ISEMPTY(eq_header[unit])) {
94334642Smarc 			event = (struct _vs_event *) datap;
94434642Smarc 			event->vse_device = VSE_NULL;
94534642Smarc 			break;
94630391Skarels 		}
94730391Skarels 		event = (struct _vs_event *) GETBEGIN(eq_header[unit]);
94834615Smarc 		s = spl5();
94930391Skarels 		GETEND(eq_header[unit]);
95030391Skarels 		splx(s);
95134732Smarc 		bcopy((caddr_t)event, datap, sizeof(struct _vs_event));
95230391Skarels 		break;
95330391Skarels 
95434642Smarc 	case QD_RESET:
95534642Smarc 		/*
95634642Smarc 		* init the dragon stuff, DUART, and driver variables
95734642Smarc 		*/
95830391Skarels 		init_shared(unit);		/* init shared memory */
95930391Skarels 		setup_dragon(unit);	      /* init the ADDER/VIPER stuff */
96030391Skarels 		clear_qd_screen(unit);
96130391Skarels 		ldcursor(unit, cons_cursor);	/* load default cursor map */
96230391Skarels 		ldfont(unit);			/* load the console font */
96330391Skarels 		setup_input(unit);		/* init the DUART */
96430391Skarels 		break;
96530391Skarels 
96634642Smarc 	case QD_SET:
96734642Smarc 		/*
96834642Smarc 		* init the DUART and driver variables
96934642Smarc 		*/
97030391Skarels 		init_shared(unit);
97130391Skarels 		setup_input(unit);
97230391Skarels 		break;
97330391Skarels 
97434642Smarc 	case QD_CLRSCRN:
97534642Smarc 		/*
97634642Smarc 		* clear the QDSS screen.  (NOTE that this reinits the dragon)
97734642Smarc 		*/
97834732Smarc #ifdef notdef	/* has caused problems and isn't necessary */
97930391Skarels 		setup_dragon(unit);
98030391Skarels 		clear_qd_screen(unit);
98134615Smarc #endif
98230391Skarels 		break;
98330391Skarels 
98434642Smarc 	case QD_WTCURSOR:
98534642Smarc 		/*
98634642Smarc 		* load a cursor into template RAM
98734642Smarc 		*/
98834732Smarc 		ldcursor(unit, (short *)datap);
98930391Skarels 		break;
99030391Skarels 
99134642Smarc 	case QD_RDCURSOR:
99230391Skarels 
99330391Skarels 		temp = (short *) qdmap[unit].template;
99434642Smarc 		/*
99534642Smarc 		 * cursor is 32 WORDS from the end of the 8k WORD...
99634642Smarc 		 *  ...template space
99734642Smarc 		 */
99830391Skarels 		temp += (8 * 1024) - 32;
99930391Skarels 		for (i = 0; i < 32; ++i, datap += sizeof(short))
100034642Smarc 			*(short *)datap = *temp++;
100130391Skarels 		break;
100230391Skarels 
100334642Smarc 	case QD_POSCURSOR:
100434642Smarc 		/*
100534642Smarc 		* position the mouse cursor
100634642Smarc 		*/
100730391Skarels 		dga = (struct dga *) qdmap[unit].dga;
100830391Skarels 		pos = (struct _vs_cursor *) datap;
100934615Smarc 		s = spl5();
101030391Skarels 		dga->x_cursor = TRANX(pos->x);
101130391Skarels 		dga->y_cursor = TRANY(pos->y);
101230391Skarels 		eq_header[unit]->curs_pos.x = pos->x;
101330391Skarels 		eq_header[unit]->curs_pos.y = pos->y;
101430391Skarels 		splx(s);
101530391Skarels 		break;
101630391Skarels 
101734642Smarc 	case QD_PRGCURSOR:
101834642Smarc 		/*
101934642Smarc 		* set the cursor acceleration factor
102034642Smarc 		*/
102130391Skarels 		curs = (struct prg_cursor *) datap;
102234615Smarc 		s = spl5();
102330391Skarels 		qdflags[unit].curs_acc = curs->acc_factor;
102430391Skarels 		qdflags[unit].curs_thr = curs->threshold;
102530391Skarels 		splx(s);
102630391Skarels 		break;
102730391Skarels 
102834642Smarc 	case QD_MAPDEVICE:
102934642Smarc 		/*
103034642Smarc 		* enable 'user write' to device pages
103134642Smarc 		*/
103230391Skarels 		qdflags[unit].mapped |= MAPDEV;
103330391Skarels 		qd = (struct qdmap *) &qdmap[unit];
103434642Smarc 		/*
103534642Smarc 		* enable user write to template RAM
103634642Smarc 		*/
103732012Smarc 		mapix = VTOP((int)qd->template) - VTOP(qvmem[0]);
103832012Smarc 		ptep = (int *)(QVmap[0] + mapix);
103934732Smarc 		for (i = 0; i < btop(TMPSIZE); i++, ptep++)
104034732Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
104134642Smarc 		/*
104234642Smarc 		* enable user write to registers
104334642Smarc 		*/
104432012Smarc 		mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]);
104532012Smarc 		ptep = (int *)(QVmap[0] + mapix);
104634732Smarc 		for (i = 0; i < btop(REGSIZE); i++, ptep++)
104734732Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
104834642Smarc 		/*
104934642Smarc 		* enable user write to color maps
105034642Smarc 		*/
105132012Smarc 		mapix = VTOP((int)qd->red) - VTOP(qvmem[0]);
105232012Smarc 		ptep = (int *)(QVmap[0] + mapix);
105334732Smarc 		for (i = 0; i < btop(CLRSIZE); i++, ptep++)
105434732Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
105534642Smarc 		/*
105634642Smarc 		* enable user write to DUART
105734642Smarc 		*/
105832012Smarc 		mapix = VTOP((int)qd->duart) - VTOP(qvmem[0]);
105932012Smarc 		ptep = (int *)(QVmap[0] + mapix);
106030391Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; /* duart page */
106130391Skarels 
106234732Smarc 		mtpr(TBIA, 0);		/* invalidate translation buffer */
106330391Skarels 
106434642Smarc 		/*
106534732Smarc 		 * stuff qdmap structure in return buffer
106634732Smarc 		 */
106734732Smarc 		bcopy((caddr_t)qd, datap, sizeof(struct qdmap));
106830391Skarels 		break;
106930391Skarels 
107034642Smarc 	case QD_MAPIOBUF:
107134642Smarc 		/*
107234642Smarc 		 * do setup for DMA by user process
107334642Smarc 		 *
107434642Smarc 		 * set 'user write enable' bits for DMA buffer
107534642Smarc 		 */
107630391Skarels 		qdflags[unit].mapped |= MAPDMA;
107730391Skarels 		ptep = (int *) ((VTOP(DMAheader[unit]) * 4)
107834642Smarc 			+ (mfpr(SBR) | 0x80000000));
107934732Smarc 		for (i = 0; i < btop(DMAbuf_size); i++, ptep++)
108034732Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
108134732Smarc 		mtpr(TBIA, 0);		/* invalidate translation buffer */
108234642Smarc 		/*
108334642Smarc 		* set up QBUS map registers for DMA
108434642Smarc 		*/
108530391Skarels 		DMAheader[unit]->QBAreg =
108634732Smarc 		    uballoc(0, (caddr_t)DMAheader[unit], DMAbuf_size, 0);
108730391Skarels 		if (DMAheader[unit]->QBAreg == 0)
108834732Smarc 		    printf("qd%d: qdioctl: QBA setup error\n", unit);
108930391Skarels 		Qbus_unmap[unit] = DMAheader[unit]->QBAreg;
109030391Skarels 		DMAheader[unit]->QBAreg &= 0x3FFFF;
109134642Smarc 		/*
109234642Smarc 		* return I/O buf adr
109334642Smarc 		*/
109430391Skarels 		*(int *)datap = (int) DMAheader[unit];
109530391Skarels 		break;
109630391Skarels 
109734642Smarc 	case QD_MAPSCROLL:
109834642Smarc 		/*
109934642Smarc 		* map the shared scroll param area and enable scroll interpts
110034642Smarc 		*/
110130391Skarels 		qdflags[unit].mapped |= MAPSCR;
110230391Skarels 		ptep = (int *) ((VTOP(scroll[unit]) * 4)
110334642Smarc 			+ (mfpr(SBR) | 0x80000000));
110434642Smarc 		/*
110534642Smarc 		 * allow user write to scroll area
110634642Smarc 		 */
110730391Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
110834732Smarc 		mtpr(TBIA, 0);			/* invalidate translation buf */
110930391Skarels 		scroll[unit]->status = 0;
111030391Skarels 		adder = (struct adder *) qdmap[unit].adder;
111130391Skarels 		qdflags[unit].adder_ie |= FRAME_SYNC;
111230391Skarels 		adder->interrupt_enable = qdflags[unit].adder_ie;
111334642Smarc 		*(int *)datap = (int) scroll[unit]; /* return scroll area */
111430391Skarels 		break;
111530391Skarels 
111634642Smarc 	case QD_UNMAPSCROLL:
111734642Smarc 		/*
111834642Smarc 		* unmap shared scroll param area and disable scroll intrpts
111934642Smarc 		*/
112030391Skarels 		if (qdflags[unit].mapped & MAPSCR) {
112134642Smarc 			qdflags[unit].mapped &= ~MAPSCR;
112234642Smarc 			ptep = (int *) ((VTOP(scroll[unit]) * 4)
112334642Smarc 				+ (mfpr(SBR) | 0x80000000));
112434642Smarc 			/*
112534642Smarc 			 * re-protect 512 scroll param area
112634642Smarc 			 */
112734642Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
112834642Smarc 			mtpr(TBIA, 0);	/* smash CPU's translation buf */
112934642Smarc 			adder = (struct adder *) qdmap[unit].adder;
113034642Smarc 			qdflags[unit].adder_ie &= ~FRAME_SYNC;
113134642Smarc 			adder->interrupt_enable = qdflags[unit].adder_ie;
113230391Skarels 		}
113330391Skarels 		break;
113430391Skarels 
113534642Smarc 	case QD_MAPCOLOR:
113634642Smarc 		/*
113734642Smarc 		* map shared color map write buf and turn on vsync intrpt
113834642Smarc 		*/
113930391Skarels 		qdflags[unit].mapped |= MAPCOLOR;
114030391Skarels 		ptep = (int *) ((VTOP(color_buf[unit]) * 4)
114134642Smarc 			+ (mfpr(SBR) | 0x80000000));
114234732Smarc 		/*
114334732Smarc 		 * allow user write to color map write buffer
114434732Smarc 		 */
114534732Smarc 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; ptep++;
114630391Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
114730391Skarels 		mtpr(TBIA, 0);			/* clr CPU translation buf */
114834642Smarc 		adder = (struct adder *) qdmap[unit].adder;
114930391Skarels 		qdflags[unit].adder_ie |= VSYNC;
115030391Skarels 		adder->interrupt_enable = qdflags[unit].adder_ie;
115134732Smarc 		/*
115234732Smarc 		 * return color area address
115334732Smarc 		 */
115430391Skarels 		*(int *)datap = (int) color_buf[unit];
115530391Skarels 		break;
115630391Skarels 
115734642Smarc 	case QD_UNMAPCOLOR:
115834642Smarc 		/*
115934732Smarc 		 * unmap shared color map write buffer and kill VSYNC intrpts
116034732Smarc 		 */
116130391Skarels 		if (qdflags[unit].mapped & MAPCOLOR) {
116234642Smarc 			qdflags[unit].mapped &= ~MAPCOLOR;
116334642Smarc 			ptep = (int *) ((VTOP(color_buf[unit]) * 4)
116434642Smarc 				+ (mfpr(SBR) | 0x80000000));
116534732Smarc 			/*
116634732Smarc 			 * re-protect color map write buffer
116734732Smarc 			 */
116834732Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++;
116934642Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
117034732Smarc 			mtpr(TBIA, 0);
117134642Smarc 			adder = (struct adder *) qdmap[unit].adder;
117234642Smarc 			qdflags[unit].adder_ie &= ~VSYNC;
117334642Smarc 			adder->interrupt_enable = qdflags[unit].adder_ie;
117430391Skarels 		}
117530391Skarels 		break;
117630391Skarels 
117734642Smarc 	case QD_MAPEVENT:
117834642Smarc 		/*
117934642Smarc 		* give user write access to the event queue
118034642Smarc 		*/
118130391Skarels 		qdflags[unit].mapped |= MAPEQ;
118230391Skarels 		ptep = (int *) ((VTOP(eq_header[unit]) * 4)
118334642Smarc 			+ (mfpr(SBR) | 0x80000000));
118434732Smarc 		/*
118534732Smarc 		 * allow user write to 1K event queue
118634732Smarc 		 */
118734732Smarc 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; ptep++;
118830391Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
118930391Skarels 		mtpr(TBIA, 0);			/* clr CPU translation buf */
119034732Smarc 		/*
119134732Smarc 		 * return event queue address
119234732Smarc 		 */
119334732Smarc 		*(int *)datap = (int)eq_header[unit];
119430391Skarels 		break;
119530391Skarels 
119634642Smarc 	case QD_PRGKBD:
119734642Smarc 		/*
119834642Smarc 		* pass caller's programming commands to LK201
119934642Smarc 		*/
120034732Smarc 		duart = (struct duart *)qdmap[unit].duart;
120134732Smarc 		cmdbuf = (struct prgkbd *)datap;    /* pnt to kbd cmd buf */
120234642Smarc 		/*
120334642Smarc 		* send command
120434642Smarc 		*/
120530391Skarels 		for (i = 1000; i > 0; --i) {
120634732Smarc 			if (duart->statusA&XMT_RDY) {
120734642Smarc 				duart->dataA = cmdbuf->cmd;
120834642Smarc 				break;
120934642Smarc 			}
121030391Skarels 		}
121130391Skarels 		if (i == 0) {
121234732Smarc 			printf("qd%d: qdioctl: timeout on XMT_RDY [1]\n", unit);
121334642Smarc 			break;
121430391Skarels 		}
121534642Smarc 		/*
121634642Smarc 		* send param1?
121734642Smarc 		*/
121830391Skarels 		if (cmdbuf->cmd & LAST_PARAM)
121934642Smarc 			break;
122030391Skarels 		for (i = 1000; i > 0; --i) {
122134732Smarc 			if (duart->statusA&XMT_RDY) {
122234642Smarc 				duart->dataA = cmdbuf->param1;
122334642Smarc 				break;
122434642Smarc 			}
122530391Skarels 		}
122630391Skarels 		if (i == 0) {
122734732Smarc 			printf("qd%d: qdioctl: timeout on XMT_RDY [2]\n", unit);
122834642Smarc 			break;
122930391Skarels 		}
123034642Smarc 		/*
123134642Smarc 		* send param2?
123234642Smarc 		*/
123330391Skarels 		if (cmdbuf->param1 & LAST_PARAM)
123430391Skarels 		    break;
123530391Skarels 		for (i = 1000; i > 0; --i) {
123634732Smarc 			if (duart->statusA&XMT_RDY) {
123734642Smarc 				duart->dataA = cmdbuf->param2;
123834642Smarc 				break;
123934642Smarc 			}
124030391Skarels 		}
124130391Skarels 		if (i == 0) {
124234732Smarc 			printf("qd%d: qdioctl: timeout on XMT_RDY [3]\n", unit);
124334642Smarc 			break;
124430391Skarels 		}
124530391Skarels 		break;
124630391Skarels 
124734642Smarc 	case QD_PRGMOUSE:
124834642Smarc 		/*
124934642Smarc 		* pass caller's programming commands to the mouse
125034642Smarc 		*/
125130391Skarels 		duart = (struct duart *) qdmap[unit].duart;
125230391Skarels 		for (i = 1000; i > 0; --i) {
125334732Smarc 			if (duart->statusB&XMT_RDY) {
125434642Smarc 				duart->dataB = *datap;
125534642Smarc 				break;
125634642Smarc 			}
125730391Skarels 		}
125830391Skarels 		if (i == 0) {
125934732Smarc 			printf("qd%d: qdioctl: timeout on XMT_RDY [4]\n", unit);
126030391Skarels 		}
126130391Skarels 		break;
126230391Skarels 
126334642Smarc 	case QD_RDCONFIG:
126434642Smarc 		/*
126534642Smarc 		* get QDSS configuration word and return it
126634642Smarc 		*/
126730391Skarels 		*(short *)datap = qdflags[unit].config;
126830391Skarels 		break;
126930391Skarels 
127034642Smarc 	case QD_KERN_LOOP:
127134642Smarc 	case QD_KERN_UNLOOP:
127234642Smarc 		/*
127334642Smarc 		 * vestige from ultrix.  BSD uses TIOCCONS to redirect
127434642Smarc 		 * kernel console output.
127534642Smarc 		 */
127634615Smarc 		break;
127734615Smarc 
127834642Smarc 	case QD_PRGTABLET:
127934642Smarc 		/*
128034642Smarc 		* program the tablet
128134642Smarc 		*/
128230391Skarels 		duart = (struct duart *) qdmap[unit].duart;
128330391Skarels 		for (i = 1000; i > 0; --i) {
128434732Smarc 			if (duart->statusB&XMT_RDY) {
128534642Smarc 				duart->dataB = *datap;
128634642Smarc 				break;
128734642Smarc 			}
128830391Skarels 		}
128930391Skarels 		if (i == 0) {
129034732Smarc 			printf("qd%d: qdioctl: timeout on XMT_RDY [5]\n", unit);
129130391Skarels 		}
129230391Skarels 		break;
129330391Skarels 
129434642Smarc 	case QD_PRGTABRES:
129534642Smarc 		/*
129634642Smarc 		* program the tablet report resolution factor
129734642Smarc 		*/
129830391Skarels 		qdflags[unit].tab_res = *(short *)datap;
129930391Skarels 		break;
130030391Skarels 
130134642Smarc 	default:
130234642Smarc 		/*
130334642Smarc 		* service tty ioctl's
130434642Smarc 		*/
130534642Smarc 		if (!(minor_dev & 0x02)) {
130630391Skarels 			tp = &qd_tty[minor_dev];
130734642Smarc 			error =
130834642Smarc 			   (*linesw[tp->t_line].l_ioctl)(tp, cmd, datap, flags);
130930391Skarels 			if (error >= 0) {
131034642Smarc 				return(error);
131130391Skarels 			}
131230391Skarels 			error = ttioctl(tp, cmd, datap, flags);
131330391Skarels 			if (error >= 0) {
131434642Smarc 				return(error);
131530391Skarels 			}
131634642Smarc 		}
131734642Smarc 		break;
131830391Skarels 	}
131930391Skarels 
132030391Skarels 	return(0);
132130391Skarels 
132230391Skarels } /* qdioctl */
132330391Skarels 
132430391Skarels qdselect(dev, rw)
132534642Smarc 	dev_t dev;
132634642Smarc 	int rw;
132730391Skarels {
132834732Smarc 	register s;
132934732Smarc 	register unit;
133034615Smarc 	register struct tty *tp;
133134615Smarc 	u_int minor_dev = minor(dev);
133230391Skarels 
133334615Smarc 	s = spl5();
133434615Smarc 	unit = minor_dev >> 2;
133530391Skarels 
133630391Skarels 	switch (rw) {
133734642Smarc 	case FREAD:
133834642Smarc 		if ((minor_dev & 0x03) == 2) {
133934642Smarc 			/*
134034642Smarc 			* this is a graphics device, so check for events
134134642Smarc 			*/
134234732Smarc 			if(!(ISEMPTY(eq_header[unit]))) {
134334642Smarc 				splx(s);
134434642Smarc 				return(1);
134534642Smarc 			}
134634732Smarc 			qdrsel[unit] = u.u_procp;
134734642Smarc 			qdflags[unit].selmask |= SEL_READ;
134834642Smarc 			splx(s);
134934642Smarc 			return(0);
135034642Smarc 		} else {
135134642Smarc 			/*
135234642Smarc 			* this is a tty device
135334642Smarc 			*/
135434642Smarc 			tp = &qd_tty[minor_dev];
135534642Smarc 			if (ttnread(tp))
135634642Smarc 			    return(1);
135734642Smarc 			tp->t_rsel = u.u_procp;
135834642Smarc 			splx(s);
135934642Smarc 			return(0);
136030391Skarels 		}
136130391Skarels 
136234642Smarc 	case FWRITE:
136334642Smarc 		if ((minor(dev) & 0x03) == 2) {
136434642Smarc 			/*
136534642Smarc 			* this is a graphics device, so check for dma buffers
136634642Smarc 			*/
136734642Smarc 			if (DMA_ISEMPTY(DMAheader[unit]))
136834642Smarc 			    {
136934642Smarc 				splx(s);
137034642Smarc 				return(1);
137134642Smarc 			}
137234732Smarc 			qdrsel[unit] = u.u_procp;
137334642Smarc 			qdflags[unit].selmask |= SEL_WRITE;
137434642Smarc 			splx(s);
137534642Smarc 			return(0);
137634642Smarc 		} else {
137734642Smarc 			/*
137834642Smarc 			* this is a tty device
137934642Smarc 			*/
138034642Smarc 			tp = &qd_tty[minor_dev];
138137605Smarc 			if (tp->t_outq.c_cc <= tp->t_lowat)
138234642Smarc 			    return(1);
138334642Smarc 			tp->t_wsel = u.u_procp;
138434642Smarc 			splx(s);
138534642Smarc 			return(0);
138630391Skarels 		}
138730391Skarels 	}
138834732Smarc 	splx(s);
138934732Smarc 	return(0);
139030391Skarels 
139130391Skarels } /* qdselect() */
139230391Skarels 
139330391Skarels extern qd_strategy();
139430391Skarels 
139530391Skarels qdwrite(dev, uio)
139634642Smarc 	dev_t dev;
139734642Smarc 	struct uio *uio;
139830391Skarels {
139930391Skarels 	register struct tty *tp;
140034732Smarc 	register minor_dev;
140134732Smarc 	register unit;
140230391Skarels 
140330391Skarels 	minor_dev = minor(dev);
140430391Skarels 	unit = (minor_dev >> 2) & 0x07;
140530391Skarels 
140634642Smarc 	if (((minor_dev&0x03) != 0x02) && (qdflags[unit].inuse&CONS_DEV)) {
140734642Smarc 		/*
140834642Smarc 		* this is the console...
140934642Smarc 		*/
141034642Smarc 		tp = &qd_tty[minor_dev];
141134642Smarc 		return ((*linesw[tp->t_line].l_write)(tp, uio));
141234642Smarc 	} else if (qdflags[unit].inuse & GRAPHIC_DEV) {
141334642Smarc 		/*
141434642Smarc 		* this is a DMA xfer from user space
141534642Smarc 		*/
141634642Smarc 		return (physio(qd_strategy, &qdbuf[unit],
141734642Smarc 		dev, B_WRITE, minphys, uio));
141830391Skarels 	}
141934732Smarc 	return (ENXIO);
142030391Skarels }
142130391Skarels 
142230391Skarels qdread(dev, uio)
142334642Smarc 	dev_t dev;
142434642Smarc 	struct uio *uio;
142530391Skarels {
142630391Skarels 	register struct tty *tp;
142734732Smarc 	register minor_dev;
142834732Smarc 	register unit;
142930391Skarels 
143030391Skarels 	minor_dev = minor(dev);
143130391Skarels 	unit = (minor_dev >> 2) & 0x07;
143230391Skarels 
143334642Smarc 	if ((minor_dev & 0x03) != 0x02 && qdflags[unit].inuse & CONS_DEV) {
143434642Smarc 		/*
143534642Smarc 		* this is the console
143634642Smarc 		*/
143734642Smarc 		tp = &qd_tty[minor_dev];
143834642Smarc 		return ((*linesw[tp->t_line].l_read)(tp, uio));
143934642Smarc 	} else if (qdflags[unit].inuse & GRAPHIC_DEV) {
144034642Smarc 		/*
144134642Smarc 		* this is a bitmap-to-processor xfer
144234642Smarc 		*/
144334642Smarc 		return (physio(qd_strategy, &qdbuf[unit],
144434642Smarc 		dev, B_READ, minphys, uio));
144530391Skarels 	}
144634732Smarc 	return (ENXIO);
144730391Skarels }
144830391Skarels 
144930391Skarels /***************************************************************
145030391Skarels *
145130391Skarels *	qd_strategy()... strategy routine to do DMA
145230391Skarels *
145330391Skarels ***************************************************************/
145430391Skarels 
145530391Skarels qd_strategy(bp)
145634642Smarc 	register struct buf *bp;
145730391Skarels {
145830391Skarels 	register struct dga *dga;
145930391Skarels 	register struct adder *adder;
146034732Smarc 	register unit;
146130391Skarels 	int QBAreg;
146230391Skarels 	int s;
146330391Skarels 	int cookie;
146430391Skarels 
146530391Skarels 	unit = (minor(bp->b_dev) >> 2) & 0x07;
146630391Skarels 
146734642Smarc 	/*
146834642Smarc 	* init pointers
146934642Smarc 	*/
147030391Skarels 	if ((QBAreg = ubasetup(0, bp, 0)) == 0) {
147134732Smarc 		printf("qd%d: qd_strategy: QBA setup error\n", unit);
147234642Smarc 		goto STRAT_ERR;
147330391Skarels 	}
147430391Skarels 	dga = (struct dga *) qdmap[unit].dga;
147534615Smarc 	s = spl5();
147630391Skarels 	qdflags[unit].user_dma = -1;
147730391Skarels 	dga->csr |= DMA_IE;
147830391Skarels 	cookie = QBAreg & 0x3FFFF;
147930391Skarels 	dga->adrs_lo = (short) cookie;
148030391Skarels 	dga->adrs_hi = (short) (cookie >> 16);
148130391Skarels 	dga->bytcnt_lo = (short) bp->b_bcount;
148230391Skarels 	dga->bytcnt_hi = (short) (bp->b_bcount >> 16);
148330391Skarels 
148430391Skarels 	while (qdflags[unit].user_dma) {
148534642Smarc 		sleep((caddr_t)&qdflags[unit].user_dma, QDPRIOR);
148630391Skarels 	}
148730391Skarels 	splx(s);
148830391Skarels 	ubarelse(0, &QBAreg);
148930391Skarels 	if (!(dga->csr & DMA_ERR)) {
149034642Smarc 		iodone(bp);
149134642Smarc 		return;
149230391Skarels 	}
149330391Skarels 
149430391Skarels STRAT_ERR:
149530391Skarels 	adder = (struct adder *) qdmap[unit].adder;
149634642Smarc 	adder->command = CANCEL;	/* cancel adder activity */
149730391Skarels 	dga->csr &= ~DMA_IE;
149830391Skarels 	dga->csr &= ~0x0600;		/* halt DMA (reset fifo) */
149930391Skarels 	dga->csr |= DMA_ERR;		/* clear error condition */
150030391Skarels 	bp->b_flags |= B_ERROR; 	/* flag an error to physio() */
150130391Skarels 
150234642Smarc 	/*
150334642Smarc 	 * if DMA was running, flush spurious intrpt
150434642Smarc 	 */
150530391Skarels 	if (dga->bytcnt_lo != 0) {
150634642Smarc 		dga->bytcnt_lo = 0;
150734642Smarc 		dga->bytcnt_hi = 0;
150834642Smarc 		DMA_SETIGNORE(DMAheader[unit]);
150934642Smarc 		dga->csr |= DMA_IE;
151030391Skarels 	}
151130391Skarels 	iodone(bp);
151230391Skarels 
151330391Skarels } /* qd_strategy */
151430391Skarels 
151534732Smarc /*
151634732Smarc  *  Start output to the console screen
151734732Smarc  */
151830391Skarels qdstart(tp)
151934642Smarc 	register struct tty *tp;
152030391Skarels {
152134732Smarc 	register which_unit, unit, c;
152230391Skarels 	int s;
152334615Smarc 
152430391Skarels 	unit = minor(tp->t_dev);
152530391Skarels 	which_unit = (unit >> 2) & 0x3;
152634615Smarc 	unit &= 0x03;
152730391Skarels 
152834615Smarc 	s = spl5();
152934615Smarc 
153034642Smarc 	/*
153134642Smarc 	* If it's currently active, or delaying, no need to do anything.
153234642Smarc 	*/
153330391Skarels 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
153430391Skarels 		goto out;
153530391Skarels 
153634642Smarc 	/*
153734642Smarc 	* Display chars until the queue is empty.
153834642Smarc 	* Drop input from anything but the console
153934642Smarc 	* device on the floor.
154034642Smarc 	*
154134642Smarc 	* XXX - this loop is done at spltty.
154234642Smarc 	*
154334642Smarc 	*/
154434642Smarc 	while (tp->t_outq.c_cc) {
154534511Smarc 		c = getc(&tp->t_outq);
154634615Smarc 		if (unit == 0)
154734732Smarc 			blitc(which_unit, (u_char)c);
154830391Skarels 	}
154934642Smarc 	/*
155034642Smarc 	* If there are sleepers, and output has drained below low
155134642Smarc 	* water mark, wake up the sleepers.
155234642Smarc 	*/
155337605Smarc 	if (tp->t_outq.c_cc <= tp->t_lowat) {
155434615Smarc 		if (tp->t_state & TS_ASLEEP){
155534615Smarc 			tp->t_state &= ~TS_ASLEEP;
155634615Smarc 			wakeup((caddr_t) &tp->t_outq);
155734615Smarc 		}
155830391Skarels 	}
155930391Skarels 
156034615Smarc 	tp->t_state &= ~TS_BUSY;
156134615Smarc 
156230391Skarels out:
156330391Skarels 	splx(s);
156430391Skarels 
156530391Skarels } /* qdstart */
156630391Skarels 
156734732Smarc /*ARGSUSED*/
156830391Skarels qdstop(tp, flag)
156934642Smarc 	register struct tty *tp;
157034642Smarc 	int flag;
157130391Skarels {
157230391Skarels 	register int s;
157330391Skarels 
157434615Smarc 	s = spl5();	/* block intrpts during state modification */
157534732Smarc 	if (tp->t_state & TS_BUSY)
157634732Smarc 		if ((tp->t_state & TS_TTSTOP) == 0)
157734642Smarc 			tp->t_state |= TS_FLUSH;
157834642Smarc 		else
157934642Smarc 			tp->t_state &= ~TS_BUSY;
158030391Skarels 	splx(s);
158130391Skarels }
158230391Skarels 
158334732Smarc /*
158434732Smarc  *  Output a character to the QDSS screen
158534732Smarc  */
158630391Skarels 
158730391Skarels blitc(unit, chr)
158834732Smarc 	register unit;
158934732Smarc 	register u_char chr;
159030391Skarels {
159130391Skarels 	register struct adder *adder;
159230391Skarels 	register struct dga *dga;
159330391Skarels 	register int i;
159434642Smarc 	int nograph = !(qdflags[unit].inuse&GRAPHIC_DEV);
159534642Smarc 	static short inescape[NQD];
159630391Skarels 
159734732Smarc 	adder = (struct adder *)qdmap[unit].adder;
159830391Skarels 	dga = (struct dga *) qdmap[unit].dga;
159934642Smarc 	/*
160034642Smarc 	 * BSD comment: this (&=0177) defeats the extended character
160134642Smarc 	 * set code for the glass tty, but if i had the time i would
160234642Smarc 	 * spend it ripping out the code completely.  This driver
160334642Smarc 	 * is too big for its own good.
160434642Smarc 	 */
160534642Smarc 	chr &= 0177;
160634642Smarc 	/*
160734732Smarc 	 * Cursor addressing (so vi will work).
160834642Smarc 	 * Decode for "\E=%.%." cursor motion description.
160934732Smarc 	 * Corresponds to type "qdcons" in /etc/termcap:
161034642Smarc 	 *
161134642Smarc 	 *    qd|qdss|qdcons|qdss glass tty (4.4 BSD):\
161234642Smarc 	 *      :am:do=^J:le=^H:bs:cm=\E=%.%.:cl=1^Z:co#128:li#57::nd=^L:up=^K:
161334642Smarc 	 *
161434642Smarc 	 */
161534642Smarc 	if (inescape[unit] && nograph) {
161634642Smarc 		switch (inescape[unit]++) {
161734642Smarc 		case 1:
161834642Smarc 			if (chr != '=') {
161934642Smarc 				/* abort escape sequence */
162034642Smarc 				inescape[unit] = 0;
162134642Smarc 				blitc(unit, chr);
162234642Smarc 			}
162334732Smarc 			return;
162434642Smarc 		case 2:
162534642Smarc 			/* position row */
162634642Smarc 			cursor[unit].y = CHAR_HEIGHT * chr;
162734642Smarc 			if (cursor[unit].y > 863 - CHAR_HEIGHT)
162834642Smarc 				cursor[unit].y = 863 - CHAR_HEIGHT;
162934642Smarc 			dga->y_cursor = TRANY(cursor[unit].y);
163034732Smarc 			return;
163134642Smarc 		case 3:
163234642Smarc 			/* position column */
163334642Smarc 			cursor[unit].x = CHAR_WIDTH * chr;
163434642Smarc 			if (cursor[unit].x > 1024 - CHAR_WIDTH)
163534642Smarc 				cursor[unit].x = 1023 - CHAR_WIDTH;
163634642Smarc 			dga->x_cursor = TRANX(cursor[unit].x);
163734642Smarc 			inescape[unit] = 0;
163834732Smarc 			return;
163934642Smarc 		default:
164034642Smarc 			inescape[unit] = 0;
164134642Smarc 			blitc(unit, chr);
164234642Smarc 		}
164334642Smarc 	}
164430391Skarels 
164530391Skarels 	switch (chr) {
164634642Smarc 	case '\r':			/* return char */
164730391Skarels 		cursor[unit].x = 0;
164834642Smarc 		if (nograph)
164934642Smarc 			dga->x_cursor = TRANX(cursor[unit].x);
165034732Smarc 		return;
165130391Skarels 
165234642Smarc 	case '\t':			/* tab char */
165330391Skarels 		for (i = 8 - ((cursor[unit].x >> 3) & 0x07); i > 0; --i) {
165434642Smarc 			blitc(unit, ' ');
165530391Skarels 		}
165634732Smarc 		return;
165730391Skarels 
165834642Smarc 	case '\n':			/* line feed char */
165930391Skarels 		if ((cursor[unit].y += CHAR_HEIGHT) > (863 - CHAR_HEIGHT)) {
166034642Smarc 			if (nograph) {
166134642Smarc 				cursor[unit].y -= CHAR_HEIGHT;
166234642Smarc 				scroll_up(adder);
166334642Smarc 			} else
166434642Smarc 				cursor[unit].y = 0;
166530391Skarels 		}
166634642Smarc 		if (nograph)
166734642Smarc 			dga->y_cursor = TRANY(cursor[unit].y);
166834732Smarc 		return;
166930391Skarels 
167034642Smarc 	case '\b':			/* backspace char */
167130391Skarels 		if (cursor[unit].x > 0) {
167234642Smarc 			cursor[unit].x -= CHAR_WIDTH;
167334642Smarc 			if (nograph)
167434642Smarc 				dga->x_cursor = TRANX(cursor[unit].x);
167530391Skarels 		}
167634732Smarc 		return;
167734642Smarc 	case CTRL('k'):		/* cursor up */
167834642Smarc 		if (nograph && cursor[unit].y > 0) {
167934642Smarc 			cursor[unit].y -= CHAR_HEIGHT;
168034642Smarc 			dga->y_cursor = TRANY(cursor[unit].y);
168134642Smarc 		}
168234732Smarc 		return;
168330391Skarels 
168434642Smarc 	case CTRL('^'):		/* home cursor */
168534642Smarc 		if (nograph) {
168634642Smarc 			cursor[unit].x = 0;
168734642Smarc 			dga->x_cursor = TRANX(cursor[unit].x);
168834642Smarc 			cursor[unit].y = 0;
168934642Smarc 			dga->y_cursor = TRANY(cursor[unit].y);
169034642Smarc 		}
169134732Smarc 		return;
169232012Smarc 
169334642Smarc 	case CTRL('l'):		/* cursor right */
169434642Smarc 		if (nograph && cursor[unit].x < 1023 - CHAR_WIDTH) {
169534642Smarc 			cursor[unit].x += CHAR_WIDTH;
169634642Smarc 			dga->x_cursor = TRANX(cursor[unit].x);
169734642Smarc 		}
169834732Smarc 		return;
169930391Skarels 
170034642Smarc 	case CTRL('z'):		/* clear screen */
170134642Smarc 		if (nograph) {
170234642Smarc 			setup_dragon(unit);
170334642Smarc 			clear_qd_screen(unit);
170434642Smarc 			/* home cursor - termcap seems to assume this */
170534642Smarc 			cursor[unit].x = 0;
170634642Smarc 			dga->x_cursor = TRANX(cursor[unit].x);
170734642Smarc 			cursor[unit].y = 0;
170834642Smarc 			dga->y_cursor = TRANY(cursor[unit].y);
170934642Smarc 		}
171034732Smarc 		return;
171130391Skarels 
171234642Smarc 	case '\033':		/* start escape sequence */
171334642Smarc 		if (nograph)
171434642Smarc 			inescape[unit] = 1;
171534732Smarc 		return;
171634642Smarc 
171734642Smarc 	default:
171834642Smarc 		if ((chr < ' ') || (chr > '~'))
171934732Smarc 			return;
172034642Smarc 	}
172134642Smarc 	/*
172234642Smarc 	 * setup VIPER operand control registers
172334642Smarc 	 */
172430391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0001);  /* select plane #0 */
172530391Skarels 	write_ID(adder, SRC1_OCR_B,
172634642Smarc 	EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY);
172730391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x00FE);  /* select other planes */
172830391Skarels 	write_ID(adder, SRC1_OCR_B,
172934642Smarc 	EXT_SOURCE | INT_NONE | NO_ID | BAR_SHIFT_DELAY);
173030391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x00FF);  /* select all planes */
173130391Skarels 	write_ID(adder, DST_OCR_B,
173234642Smarc 	EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
173330391Skarels 	write_ID(adder, MASK_1, 0xFFFF);
173430391Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 1);
173530391Skarels 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
173634642Smarc 	adder->x_clip_min = 0;
173734642Smarc 	adder->x_clip_max = 1024;
173834642Smarc 	adder->y_clip_min = 0;
173934642Smarc 	adder->y_clip_max = 864;
174034642Smarc 	/*
174134642Smarc 	 * load DESTINATION origin and vectors
174234642Smarc 	 */
174330391Skarels 	adder->fast_dest_dy = 0;
174430391Skarels 	adder->slow_dest_dx = 0;
174530391Skarels 	adder->error_1 = 0;
174630391Skarels 	adder->error_2 = 0;
174730391Skarels 	adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL;
174834732Smarc 	(void)wait_status(adder, RASTEROP_COMPLETE);
174930391Skarels 	adder->destination_x = cursor[unit].x;
175030391Skarels 	adder->fast_dest_dx = CHAR_WIDTH;
175130391Skarels 	adder->destination_y = cursor[unit].y;
175230391Skarels 	adder->slow_dest_dy = CHAR_HEIGHT;
175334642Smarc 	/*
175434642Smarc 	 * load SOURCE origin and vectors
175534642Smarc 	 */
175634615Smarc 	if ((chr - ' ') > (CHARS - 1))  {
175734615Smarc 		printf("Invalid character (x)%x in blitc\n",chr);
175834615Smarc 		chr = ' ';
175934615Smarc 	}
176034642Smarc 	/*
176134642Smarc 	 * X position is modulo the number of characters per line
176234642Smarc 	 */
176334615Smarc 	adder->source_1_x = FONT_X +
176434642Smarc 	    (((chr - ' ') % (MAX_SCREEN_X/CHAR_WIDTH)) * CHAR_WIDTH);
176534642Smarc 	/*
176634642Smarc 	 * Point to either first or second row
176734642Smarc 	 */
176834615Smarc 	adder->source_1_y = 2048 - 15 *
176934642Smarc 	    (((chr - ' ')/(MAX_SCREEN_X/CHAR_WIDTH)) + 1);
177030391Skarels 	adder->source_1_dx = CHAR_WIDTH;
177130391Skarels 	adder->source_1_dy = CHAR_HEIGHT;
177230391Skarels 	write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
177330391Skarels 	adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE;
177434642Smarc 	/*
177534642Smarc 	 * update console cursor coordinates
177634642Smarc 	 */
177730391Skarels 	cursor[unit].x += CHAR_WIDTH;
177834642Smarc 	if (nograph)
177934642Smarc 		dga->x_cursor = TRANX(cursor[unit].x);
178030391Skarels 	if (cursor[unit].x > (1024 - CHAR_WIDTH)) {
178134642Smarc 		blitc(unit, '\r');
178234642Smarc 		blitc(unit, '\n');
178330391Skarels 	}
178430391Skarels 
178530391Skarels } /* blitc */
178630391Skarels 
178734732Smarc qdreset() { }
178830391Skarels 
178934732Smarc /*
179034732Smarc  *  INTERRUPT SERVICE ROUTINES
179134732Smarc  */
179230391Skarels 
179334732Smarc /*
179434732Smarc  *  Service "DMA DONE" interrupt condition
179534732Smarc  */
179630391Skarels qddint(qd)
179734732Smarc 	register qd;
179830391Skarels {
179930391Skarels 	register struct DMAreq_header *header;
180030391Skarels 	register struct DMAreq *request;
180130391Skarels 	register struct dga *dga;
180230391Skarels 	struct adder *adder;
180330391Skarels 	int cookie;			/* DMA adrs for QDSS */
180430391Skarels 
180534732Smarc 	(void)spl4(); 			/* allow interval timer in */
180630391Skarels 
180734642Smarc 	/*
180834642Smarc 	* init pointers
180934642Smarc 	*/
181030391Skarels 	header = DMAheader[qd]; 	    /* register for optimization */
181130391Skarels 	dga = (struct dga *) qdmap[qd].dga;
181230391Skarels 	adder = (struct adder *) qdmap[qd].adder;
181330391Skarels 
181434642Smarc 	/*
181534642Smarc 	* if this interrupt flagged as bogus for interrupt flushing purposes..
181634642Smarc 	*/
181730391Skarels 	if (DMA_ISIGNORE(header)) {
181834642Smarc 		DMA_CLRIGNORE(header);
181934642Smarc 		return;
182030391Skarels 	}
182130391Skarels 
182234642Smarc 	/*
182334642Smarc 	* dump a DMA hardware error message if appropriate
182434642Smarc 	*/
182530391Skarels 	if (dga->csr & DMA_ERR) {
182630391Skarels 
182734642Smarc 		if (dga->csr & PARITY_ERR)
182834732Smarc 		    printf("qd%d: qddint: DMA hardware parity fault.\n", qd);
182930391Skarels 
183034642Smarc 		if (dga->csr & BUS_ERR)
183134732Smarc 		    printf("qd%d: qddint: DMA hardware bus error.\n", qd);
183230391Skarels 	}
183330391Skarels 
183434642Smarc 	/*
183534642Smarc 	* if this was a DMA from user space...
183634642Smarc 	*/
183730391Skarels 	if (qdflags[qd].user_dma) {
183834642Smarc 		qdflags[qd].user_dma = 0;
183934642Smarc 		wakeup((caddr_t)&qdflags[qd].user_dma);
184034642Smarc 		return;
184130391Skarels 	}
184230391Skarels 
184334642Smarc 	/*
184434642Smarc 	* if we're doing DMA request queue services, field the error condition
184534642Smarc 	*/
184630391Skarels 	if (dga->csr & DMA_ERR) {
184730391Skarels 
184834642Smarc 		dga->csr &= ~0x0600;		/* halt DMA (reset fifo) */
184934642Smarc 		dga->csr |= DMA_ERR;		/* clear error condition */
185034642Smarc 		adder->command = CANCEL;	/* cancel adder activity */
185130391Skarels 
185234642Smarc 		DMA_SETERROR(header);	/* flag error in header status word */
185334642Smarc 		DMA_CLRACTIVE(header);
185434642Smarc 		header->DMAreq[header->oldest].DMAdone |= HARD_ERROR;
185534642Smarc 		header->newest = header->oldest;
185634642Smarc 		header->used = 0;
185730391Skarels 
185834732Smarc 		if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
185934732Smarc 			selwakeup(qdrsel[qd], 0);
186034732Smarc 			qdrsel[qd] = 0;
186134642Smarc 			qdflags[qd].selmask &= ~SEL_WRITE;
186234642Smarc 		}
186330391Skarels 
186434642Smarc 		if (dga->bytcnt_lo != 0) {
186534642Smarc 			dga->bytcnt_lo = 0;
186634642Smarc 			dga->bytcnt_hi = 0;
186734642Smarc 			DMA_SETIGNORE(header);
186834642Smarc 		}
186934642Smarc 		return;
187030391Skarels 	}
187130391Skarels 
187234642Smarc 	/*
187334642Smarc 	* if the DMA request queue is now becoming non-full,
187434642Smarc 	* wakeup "select" client.
187534642Smarc 	*/
187630391Skarels 	if (DMA_ISFULL(header)) {
187734732Smarc 		if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
187834732Smarc 			selwakeup(qdrsel[qd], 0);
187934732Smarc 			qdrsel[qd] = 0;
188034642Smarc 			qdflags[qd].selmask &= ~SEL_WRITE;
188134642Smarc 		}
188230391Skarels 	}
188330391Skarels 
188430391Skarels 	header->DMAreq[header->oldest].DMAdone |= REQUEST_DONE;
188534642Smarc 	QDlast_DMAtype = header->DMAreq[header->oldest].DMAtype;
188630391Skarels 
188734615Smarc 	/* check for unexpected interrupt */
188834615Smarc 	if (DMA_ISEMPTY(header))
188930391Skarels 	    return;
189030391Skarels 
189130391Skarels 	DMA_GETEND(header);	/* update request queue indices */
189230391Skarels 
189334642Smarc 	/*
189434732Smarc 	* if no more DMA pending, wake up "select" client and exit
189534732Smarc 	*/
189630391Skarels 	if (DMA_ISEMPTY(header)) {
189730391Skarels 
189834732Smarc 		if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
189934732Smarc 			selwakeup(qdrsel[qd], 0);
190034732Smarc 			qdrsel[qd] = 0;
190134642Smarc 			qdflags[qd].selmask &= ~SEL_WRITE;
190234642Smarc 		}
190330391Skarels 
190434642Smarc 		DMA_CLRACTIVE(header);  /* flag DMA done */
190534642Smarc 		return;
190630391Skarels 	}
190730391Skarels 
190834642Smarc 	/*
190934732Smarc 	* initiate next DMA xfer
191034732Smarc 	*/
191130391Skarels 	request = DMA_GETBEGIN(header);
191234615Smarc 	if (request->DMAtype != QDlast_DMAtype) {
191334642Smarc 		dga->csr &= ~0x0600;	  /* halt DMA (reset fifo) */
191434642Smarc 		adder->command = CANCEL;  /* cancel adder activity */
191534615Smarc 	}
191630391Skarels 
191734615Smarc 
191830391Skarels 	switch (request->DMAtype) {
191930391Skarels 
192034642Smarc 	case DISPLIST:
192134615Smarc 		if (request->DMAtype != QDlast_DMAtype) {
192234615Smarc 			dga->csr |= DL_ENB;
192334615Smarc 			dga->csr &= ~(BTOP_ENB | BYTE_DMA);
192434615Smarc 		}
192530391Skarels 		break;
192630391Skarels 
192734642Smarc 	case PTOB:
192834615Smarc 		if (request->DMAtype != QDlast_DMAtype) {
192934615Smarc 			if (request->DMAdone & BYTE_PACK)
193034642Smarc 			    dga->csr |= (PTOB_ENB | BYTE_DMA);
193134615Smarc 			else {
193234615Smarc 				dga->csr |= PTOB_ENB;
193334615Smarc 				dga->csr &= ~BYTE_DMA;
193434615Smarc 			}
193534615Smarc 		}
193630391Skarels 		break;
193730391Skarels 
193834642Smarc 	case BTOP:
193934615Smarc 		if (request->DMAtype != QDlast_DMAtype) {
194034615Smarc 			if (request->DMAdone & BYTE_PACK) {
194134615Smarc 				dga->csr &= ~DL_ENB;
194234615Smarc 				dga->csr |= (BTOP_ENB | BYTE_DMA);
194334615Smarc 			}
194434615Smarc 			else {
194534615Smarc 				dga->csr |= BTOP_ENB;
194634615Smarc 				dga->csr &= ~(BYTE_DMA | DL_ENB);
194734615Smarc 			}
194834615Smarc 		}
194930391Skarels 		break;
195034642Smarc 	default:
195134732Smarc 		printf("qd%d: qddint: illegal DMAtype parameter.\n", qd);
195230391Skarels 		DMA_CLRACTIVE(header);	/* flag DMA done */
195330391Skarels 		return;
195430391Skarels 	}
195530391Skarels 
195630391Skarels 	if (request->DMAdone & COUNT_ZERO) {
195734642Smarc 		dga->csr &= ~SET_DONE_FIFO;
195834642Smarc 	}
195934642Smarc 	else if (request->DMAdone & FIFO_EMPTY) {
196034642Smarc 		dga->csr |= SET_DONE_FIFO;
196130391Skarels 	}
196230391Skarels 
196330391Skarels 	if (request->DMAdone & WORD_PACK)
196430391Skarels 	    dga->csr &= ~BYTE_DMA;
196530391Skarels 	else if (request->DMAdone & BYTE_PACK)
196630391Skarels 	    dga->csr |= BYTE_DMA;
196730391Skarels 
196830391Skarels 	dga->csr |= DMA_IE;
196934642Smarc 	QDlast_DMAtype = request->DMAtype;
197030391Skarels 
197130391Skarels 	cookie = ((int)request->bufp - (int)header) + (int)header->QBAreg;
197230391Skarels 
197330391Skarels 	dga->adrs_lo = (short) cookie;
197430391Skarels 	dga->adrs_hi = (short) (cookie >> 16);
197530391Skarels 
197630391Skarels 	dga->bytcnt_lo = (short) request->length;
197730391Skarels 	dga->bytcnt_hi = (short) (request->length >> 16);
197830391Skarels 
197930391Skarels 	return;
198030391Skarels }
198130391Skarels 
198234732Smarc /*
198334732Smarc  * ADDER interrupt service routine
198434732Smarc  */
198530391Skarels qdaint(qd)
198634732Smarc 	register qd;
198730391Skarels {
198830391Skarels 	register struct adder *adder;
198930391Skarels 	struct color_buf *cbuf;
199030391Skarels 	int i;
199130391Skarels 	register struct rgb *rgbp;
199230391Skarels 	register short *red;
199330391Skarels 	register short *green;
199430391Skarels 	register short *blue;
199530391Skarels 
199634732Smarc 	(void)spl4(); 			/* allow interval timer in */
199730391Skarels 
199830391Skarels 	adder = (struct adder *) qdmap[qd].adder;
199930391Skarels 
200034642Smarc 	/*
200134642Smarc 	* service the vertical blank interrupt (VSYNC bit) by loading
200234642Smarc 	* any pending color map load request
200334642Smarc 	*/
200430391Skarels 	if (adder->status & VSYNC) {
200534642Smarc 		adder->status &= ~VSYNC;	/* clear the interrupt */
200634642Smarc 		cbuf = color_buf[qd];
200734642Smarc 		if (cbuf->status & LOAD_COLOR_MAP) {
200830391Skarels 
200934642Smarc 			red = (short *) qdmap[qd].red;
201034642Smarc 			green = (short *) qdmap[qd].green;
201134642Smarc 			blue = (short *) qdmap[qd].blue;
201230391Skarels 
201334642Smarc 			for (i = cbuf->count, rgbp = cbuf->rgb;
201434642Smarc 			     --i >= 0; rgbp++) {
201534642Smarc 				red[rgbp->offset] = (short) rgbp->red;
201634642Smarc 				green[rgbp->offset] = (short) rgbp->green;
201734642Smarc 				blue[rgbp->offset] = (short) rgbp->blue;
201834642Smarc 			}
201930391Skarels 
202034642Smarc 			cbuf->status &= ~LOAD_COLOR_MAP;
202130391Skarels 		}
202230391Skarels 	}
202330391Skarels 
202434642Smarc 	/*
202534642Smarc 	* service the scroll interrupt (FRAME_SYNC bit)
202634642Smarc 	*/
202730391Skarels 	if (adder->status & FRAME_SYNC) {
202834642Smarc 		adder->status &= ~FRAME_SYNC;	/* clear the interrupt */
202930391Skarels 
203034642Smarc 		if (scroll[qd]->status & LOAD_REGS) {
203130391Skarels 
203234732Smarc 			for (i = 1000, adder->status = 0; i > 0 &&
203334732Smarc 			     !(adder->status&ID_SCROLL_READY); --i)
203434642Smarc 			      ;
203530391Skarels 
203634642Smarc 			if (i == 0) {
203734732Smarc 			    printf("qd%d: qdaint: timeout on ID_SCROLL_READY\n",
203834642Smarc 				qd);
203934642Smarc 				return;
204034642Smarc 			}
204130391Skarels 
204234642Smarc 			adder->ID_scroll_data = scroll[qd]->viper_constant;
204334642Smarc 			adder->ID_scroll_command = ID_LOAD | SCROLL_CONSTANT;
204430391Skarels 
204534642Smarc 			adder->y_scroll_constant =
204634642Smarc 				scroll[qd]->y_scroll_constant;
204734642Smarc 			adder->y_offset_pending = scroll[qd]->y_offset;
204830391Skarels 
204934642Smarc 			if (scroll[qd]->status & LOAD_INDEX) {
205030391Skarels 
205134642Smarc 				adder->x_index_pending =
205234642Smarc 					scroll[qd]->x_index_pending;
205334642Smarc 				adder->y_index_pending =
205434642Smarc 					scroll[qd]->y_index_pending;
205534642Smarc 			}
205634642Smarc 
205734642Smarc 			scroll[qd]->status = 0x00;
205830391Skarels 		}
205930391Skarels 	}
206030391Skarels }
206130391Skarels 
206234732Smarc /*
206334732Smarc  *  DUART input interrupt service routine
206434732Smarc  *
206534732Smarc  *  XXX - this routine should be broken out - it is essentially
206634732Smarc  *	      straight line code.
206734732Smarc  */
206830391Skarels 
206930391Skarels qdiint(qd)
207034732Smarc 	register qd;
207130391Skarels {
207230391Skarels 	register struct _vs_event *event;
207330391Skarels 	register struct qdinput *eqh;
207430391Skarels 	struct dga *dga;
207530391Skarels 	struct duart *duart;
207630391Skarels 	struct mouse_report *new_rep;
207730391Skarels 	struct uba_device *ui;
207830391Skarels 	struct tty *tp;
207934615Smarc 	u_short chr;
208030391Skarels 	u_short status;
208130391Skarels 	u_short data;
208230391Skarels 	u_short key;
208330391Skarels 	char do_wakeup = 0;		/* flag to do a select wakeup call */
208430391Skarels 	char a, b, c;			/* mouse button test variables */
208530391Skarels 
208634732Smarc 	(void)spl4(); 			/* allow interval timer in */
208730391Skarels 
208830391Skarels 	eqh = eq_header[qd];		/* optimized as a register */
208930391Skarels 	new_rep = &current_rep[qd];
209030391Skarels 	duart = (struct duart *) qdmap[qd].duart;
209130391Skarels 
209234642Smarc 	/*
209334732Smarc 	* if the graphic device is turned on..
209434732Smarc 	*/
209530391Skarels 	if (qdflags[qd].inuse & GRAPHIC_DEV) {
209634642Smarc 		/*
209734642Smarc 		* empty DUART
209834642Smarc 		*/
209934732Smarc 		while (duart->statusA&RCV_RDY || duart->statusB&RCV_RDY) {
210034642Smarc 			/*
210134732Smarc 			 * pick up LK-201 input (if any)
210234732Smarc 			 */
210334732Smarc 			if (duart->statusA&RCV_RDY) {
210430391Skarels 
210534642Smarc 				/* if error condition, then reset it */
210630391Skarels 
210734732Smarc 				if (duart->statusA&0x70) {
210834642Smarc 					duart->cmdA = 0x40;
210934642Smarc 					continue;
211034642Smarc 				}
211130391Skarels 
211234642Smarc 				/* event queue full now? (overflow condition) */
211330391Skarels 
211434642Smarc 				if (ISFULL(eqh) == TRUE) {
211534642Smarc 					printf(
211634732Smarc 					 "qd%d: qdiint: event queue overflow\n",
211734642Smarc 					   qd);
211834642Smarc 					break;
211934642Smarc 				}
212030391Skarels 
212134642Smarc 				/*
212234642Smarc 				* Check for various keyboard errors  */
212330391Skarels 
212434642Smarc 				key = duart->dataA & 0xFF;
212530391Skarels 
212634642Smarc 				if (key==LK_POWER_ERROR ||
212734642Smarc 				    key==LK_KDOWN_ERROR ||
212834642Smarc 				    key == LK_INPUT_ERROR ||
212934642Smarc 				    key == LK_OUTPUT_ERROR) {
213034642Smarc 					printf(
213134732Smarc 				    "qd%d: qdiint: keyboard error, code = %x\n",
213234642Smarc 					qd,key);
213334732Smarc 					return;
213434642Smarc 				}
213530391Skarels 
213634642Smarc 				if (key < LK_LOWEST)
213734732Smarc 				    return;
213830391Skarels 
213934642Smarc 				++do_wakeup;  /* request a select wakeup call */
214030391Skarels 
214134642Smarc 				event = PUTBEGIN(eqh);
214234642Smarc 				PUTEND(eqh);
214330391Skarels 
214434642Smarc 				event->vse_key = key;
214534642Smarc 				event->vse_key &= 0x00FF;
214634642Smarc 				event->vse_x = eqh->curs_pos.x;
214734642Smarc 				event->vse_y = eqh->curs_pos.y;
214834642Smarc 				event->vse_time = TOY;
214934642Smarc 				event->vse_type = VSE_BUTTON;
215034642Smarc 				event->vse_direction = VSE_KBTRAW;
215134642Smarc 				event->vse_device = VSE_DKB;
215234642Smarc 			}
215330391Skarels 
215434642Smarc 			/*
215534642Smarc 			* pick up the mouse input (if any)  */
215630391Skarels 
215734642Smarc 			if ((status = duart->statusB) & RCV_RDY  &&
215834642Smarc 			    qdflags[qd].pntr_id == MOUSE_ID) {
215930391Skarels 
216034642Smarc 				if (status & 0x70) {
216134642Smarc 					duart->cmdB = 0x40;
216234642Smarc 					continue;
216334642Smarc 				}
216430391Skarels 
216534642Smarc 				/* event queue full now? (overflow condition) */
216630391Skarels 
216734642Smarc 				if (ISFULL(eqh) == TRUE) {
216834642Smarc 					printf(
216934732Smarc 					"qd%d: qdiint: event queue overflow\n",
217034642Smarc 					     qd);
217134642Smarc 					break;
217234642Smarc 				}
217330391Skarels 
217434642Smarc 				data = duart->dataB;      /* get report byte */
217534642Smarc 				++new_rep->bytcnt; /* bump report byte count */
217630391Skarels 
217734642Smarc 				/*
217834642Smarc 				* if 1st byte of report.. */
217930391Skarels 
218034642Smarc 				if ( data & START_FRAME) {
218134642Smarc 					new_rep->state = data;
218234642Smarc 					if (new_rep->bytcnt > 1) {
218334642Smarc 						/* start of new frame */
218434642Smarc 						new_rep->bytcnt = 1;
218534642Smarc 						/* ..continue looking */
218634642Smarc 						continue;
218734642Smarc 					}
218834642Smarc 				}
218930391Skarels 
219034642Smarc 				/*
219134642Smarc 				* if 2nd byte of report.. */
219230391Skarels 
219334642Smarc 				else if (new_rep->bytcnt == 2) {
219434642Smarc 					new_rep->dx = data & 0x00FF;
219534642Smarc 				}
219630391Skarels 
219734642Smarc 				/*
219834642Smarc 				* if 3rd byte of report, load input event queue */
219930391Skarels 
220034642Smarc 				else if (new_rep->bytcnt == 3) {
220130391Skarels 
220234642Smarc 					new_rep->dy = data & 0x00FF;
220334642Smarc 					new_rep->bytcnt = 0;
220430391Skarels 
220534642Smarc 					/*
220634642Smarc 					* if mouse position has changed.. */
220730391Skarels 
220834642Smarc 					if (new_rep->dx != 0  ||  new_rep->dy != 0) {
220930391Skarels 
221034642Smarc 						/*
221134642Smarc 						* calculate acceleration factor, if needed	*/
221230391Skarels 
221334642Smarc 						if (qdflags[qd].curs_acc > ACC_OFF) {
221430391Skarels 
221534642Smarc 							if (qdflags[qd].curs_thr <= new_rep->dx)
221634642Smarc 							    new_rep->dx +=
221734642Smarc 							    (new_rep->dx - qdflags[qd].curs_thr)
221834642Smarc 							    * qdflags[qd].curs_acc;
221930391Skarels 
222034642Smarc 							if (qdflags[qd].curs_thr <= new_rep->dy)
222134642Smarc 							    new_rep->dy +=
222234642Smarc 							    (new_rep->dy - qdflags[qd].curs_thr)
222334642Smarc 							    * qdflags[qd].curs_acc;
222434642Smarc 						}
222530391Skarels 
222634642Smarc 						/*
222734642Smarc 						* update cursor position coordinates */
222830391Skarels 
222934642Smarc 						if (new_rep->state & X_SIGN) {
223034642Smarc 							eqh->curs_pos.x += new_rep->dx;
223134642Smarc 							if (eqh->curs_pos.x > 1023)
223234642Smarc 							    eqh->curs_pos.x = 1023;
223334642Smarc 						}
223434642Smarc 						else {
223534642Smarc 							eqh->curs_pos.x -= new_rep->dx;
223634642Smarc 							if (eqh->curs_pos.x < -15)
223734642Smarc 							    eqh->curs_pos.x = -15;
223834642Smarc 						}
223930391Skarels 
224034642Smarc 						if (new_rep->state & Y_SIGN) {
224134642Smarc 							eqh->curs_pos.y -= new_rep->dy;
224234642Smarc 							if (eqh->curs_pos.y < -15)
224334642Smarc 							    eqh->curs_pos.y = -15;
224434642Smarc 						}
224534642Smarc 						else {
224634642Smarc 							eqh->curs_pos.y += new_rep->dy;
224734642Smarc 							if (eqh->curs_pos.y > 863)
224834642Smarc 							    eqh->curs_pos.y = 863;
224934642Smarc 						}
225030391Skarels 
225134642Smarc 						/*
225234642Smarc 						* update cursor screen position */
225330391Skarels 
225434642Smarc 						dga = (struct dga *) qdmap[qd].dga;
225534642Smarc 						dga->x_cursor = TRANX(eqh->curs_pos.x);
225634642Smarc 						dga->y_cursor = TRANY(eqh->curs_pos.y);
225730391Skarels 
225834642Smarc 						/*
225934642Smarc 						* if cursor is in the box, no event report */
226030391Skarels 
226134642Smarc 						if (eqh->curs_pos.x <= eqh->curs_box.right	&&
226234642Smarc 						    eqh->curs_pos.x >= eqh->curs_box.left  &&
226334642Smarc 						    eqh->curs_pos.y >= eqh->curs_box.top  &&
226434642Smarc 						    eqh->curs_pos.y <= eqh->curs_box.bottom ) {
226534642Smarc 							goto GET_MBUTTON;
226634642Smarc 						}
226730391Skarels 
226834642Smarc 						/*
226934642Smarc 						* report the mouse motion event */
227030391Skarels 
227134642Smarc 						event = PUTBEGIN(eqh);
227234642Smarc 						PUTEND(eqh);
227330391Skarels 
227434642Smarc 						++do_wakeup;   /* request a select wakeup call */
227530391Skarels 
227634642Smarc 						event->vse_x = eqh->curs_pos.x;
227734642Smarc 						event->vse_y = eqh->curs_pos.y;
227830391Skarels 
227934642Smarc 						event->vse_device = VSE_MOUSE;  /* mouse */
228034642Smarc 						event->vse_type = VSE_MMOTION;  /* pos changed */
228134642Smarc 						event->vse_key = 0;
228234642Smarc 						event->vse_direction = 0;
228334642Smarc 						event->vse_time = TOY;	/* time stamp */
228434642Smarc 					}
228530391Skarels 
228630391Skarels GET_MBUTTON:
228734642Smarc 					/*
228834642Smarc 					* if button state has changed */
228930391Skarels 
229034642Smarc 					a = new_rep->state & 0x07;    /*mask nonbutton bits */
229134642Smarc 					b = last_rep[qd].state & 0x07;
229230391Skarels 
229334642Smarc 					if (a ^ b) {
229430391Skarels 
229534642Smarc 						for ( c = 1;  c < 8; c <<= 1) {
229630391Skarels 
229734642Smarc 							if (!( c & (a ^ b))) /* this button change? */
229834642Smarc 							    continue;
229930391Skarels 
230034642Smarc 							/* event queue full? (overflow condition) */
230130391Skarels 
230234642Smarc 							if (ISFULL(eqh) == TRUE) {
230334732Smarc 								printf("qd%d: qdiint: event queue overflow\n", qd);
230434642Smarc 								break;
230534642Smarc 							}
230630391Skarels 
230734642Smarc 							event = PUTBEGIN(eqh);	/* get new event */
230834642Smarc 							PUTEND(eqh);
230930391Skarels 
231034642Smarc 							++do_wakeup;   /* request select wakeup */
231130391Skarels 
231234642Smarc 							event->vse_x = eqh->curs_pos.x;
231334642Smarc 							event->vse_y = eqh->curs_pos.y;
231430391Skarels 
231534642Smarc 							event->vse_device = VSE_MOUSE;	/* mouse */
231634642Smarc 							event->vse_type = VSE_BUTTON; /* new button */
231734642Smarc 							event->vse_time = TOY;	      /* time stamp */
231830391Skarels 
231934642Smarc 							/* flag changed button and if up or down */
232030391Skarels 
232134642Smarc 							if (c == RIGHT_BUTTON)
232234642Smarc 							    event->vse_key = VSE_RIGHT_BUTTON;
232334642Smarc 							else if (c == MIDDLE_BUTTON)
232434642Smarc 							    event->vse_key = VSE_MIDDLE_BUTTON;
232534642Smarc 							else if (c == LEFT_BUTTON)
232634642Smarc 							    event->vse_key = VSE_LEFT_BUTTON;
232730391Skarels 
232834642Smarc 							/* set bit = button depressed */
232930391Skarels 
233034642Smarc 							if (c & a)
233134642Smarc 							    event->vse_direction = VSE_KBTDOWN;
233234642Smarc 							else
233334642Smarc 								event->vse_direction = VSE_KBTUP;
233434642Smarc 						}
233534642Smarc 					}
233630391Skarels 
233734642Smarc 					/* refresh last report */
233830391Skarels 
233934642Smarc 					last_rep[qd] = current_rep[qd];
234030391Skarels 
234134642Smarc 				}  /* get last byte of report */
234234732Smarc 			} else if ((status = duart->statusB)&RCV_RDY &&
234334732Smarc 			           qdflags[qd].pntr_id == TABLET_ID) {
234434732Smarc 				/*
234534732Smarc 				* pickup tablet input, if any
234634732Smarc 				*/
234734732Smarc 				if (status&0x70) {
234834642Smarc 					duart->cmdB = 0x40;
234934642Smarc 					continue;
235034642Smarc 				}
235134732Smarc 				/*
235234732Smarc 				 * event queue full now? (overflow condition)
235334732Smarc 				 */
235434642Smarc 				if (ISFULL(eqh) == TRUE) {
235534732Smarc 					printf("qd%d: qdiint: event queue overflow\n", qd);
235634642Smarc 					break;
235734642Smarc 				}
235830391Skarels 
235934642Smarc 				data = duart->dataB;      /* get report byte */
236034642Smarc 				++new_rep->bytcnt;	      /* bump report byte count */
236130391Skarels 
236234642Smarc 				/*
236334642Smarc 				* if 1st byte of report.. */
236430391Skarels 
236534642Smarc 				if (data & START_FRAME) {
236634642Smarc 					new_rep->state = data;
236734642Smarc 					if (new_rep->bytcnt > 1) {
236834642Smarc 						new_rep->bytcnt = 1;    /* start of new frame */
236934642Smarc 						continue;		    /* ..continue looking */
237034642Smarc 					}
237134642Smarc 				}
237230391Skarels 
237334642Smarc 				/*
237434642Smarc 				* if 2nd byte of report.. */
237530391Skarels 
237634642Smarc 				else if (new_rep->bytcnt == 2) {
237734642Smarc 					new_rep->dx = data & 0x3F;
237834642Smarc 				}
237930391Skarels 
238034642Smarc 				/*
238134642Smarc 				* if 3rd byte of report.. */
238230391Skarels 
238334642Smarc 				else if (new_rep->bytcnt == 3) {
238434642Smarc 					new_rep->dx |= (data & 0x3F) << 6;
238534642Smarc 				}
238630391Skarels 
238734642Smarc 				/*
238834642Smarc 				* if 4th byte of report.. */
238930391Skarels 
239034642Smarc 				else if (new_rep->bytcnt == 4) {
239134642Smarc 					new_rep->dy = data & 0x3F;
239234642Smarc 				}
239330391Skarels 
239434642Smarc 				/*
239534642Smarc 				* if 5th byte of report, load input event queue */
239630391Skarels 
239734642Smarc 				else if (new_rep->bytcnt == 5) {
239830391Skarels 
239934642Smarc 					new_rep->dy |= (data & 0x3F) << 6;
240034642Smarc 					new_rep->bytcnt = 0;
240130391Skarels 
240234642Smarc 					/*
240334642Smarc 					* update cursor position coordinates */
240430391Skarels 
240534642Smarc 					new_rep->dx /= qdflags[qd].tab_res;
240634642Smarc 					new_rep->dy = (2200 - new_rep->dy)
240734642Smarc 					    / qdflags[qd].tab_res;
240830391Skarels 
240934642Smarc 					if (new_rep->dx > 1023) {
241034642Smarc 						new_rep->dx = 1023;
241134642Smarc 					}
241234642Smarc 					if (new_rep->dy > 863) {
241334642Smarc 						new_rep->dy = 863;
241434642Smarc 					}
241530391Skarels 
241634642Smarc 					/*
241734642Smarc 					* report an event if the puck/stylus has moved
241834642Smarc 					*/
241930391Skarels 
242034642Smarc 					if (eqh->curs_pos.x != new_rep->dx ||
242134642Smarc 					    eqh->curs_pos.y != new_rep->dy) {
242230391Skarels 
242334642Smarc 						eqh->curs_pos.x = new_rep->dx;
242434642Smarc 						eqh->curs_pos.y = new_rep->dy;
242530391Skarels 
242634642Smarc 						/*
242734642Smarc 						* update cursor screen position */
242830391Skarels 
242934642Smarc 						dga = (struct dga *) qdmap[qd].dga;
243034642Smarc 						dga->x_cursor = TRANX(eqh->curs_pos.x);
243134642Smarc 						dga->y_cursor = TRANY(eqh->curs_pos.y);
243230391Skarels 
243334642Smarc 						/*
243434642Smarc 						* if cursor is in the box, no event report
243534642Smarc 						*/
243630391Skarels 
243734642Smarc 						if (eqh->curs_pos.x <= eqh->curs_box.right	&&
243834642Smarc 						    eqh->curs_pos.x >= eqh->curs_box.left  &&
243934642Smarc 						    eqh->curs_pos.y >= eqh->curs_box.top  &&
244034642Smarc 						    eqh->curs_pos.y <= eqh->curs_box.bottom ) {
244134642Smarc 							goto GET_TBUTTON;
244234642Smarc 						}
244330391Skarels 
244434642Smarc 						/*
244534642Smarc 						* report the tablet motion event */
244630391Skarels 
244734642Smarc 						event = PUTBEGIN(eqh);
244834642Smarc 						PUTEND(eqh);
244930391Skarels 
245034642Smarc 						++do_wakeup;   /* request a select wakeup call */
245130391Skarels 
245234642Smarc 						event->vse_x = eqh->curs_pos.x;
245334642Smarc 						event->vse_y = eqh->curs_pos.y;
245430391Skarels 
245534642Smarc 						event->vse_device = VSE_TABLET;  /* tablet */
245634642Smarc 						/*
245734642Smarc 						* right now, X handles tablet motion the same
245834642Smarc 						* as mouse motion
245934642Smarc 						*/
246034642Smarc 						event->vse_type = VSE_MMOTION;   /* pos changed */
246134642Smarc 						event->vse_key = 0;
246234642Smarc 						event->vse_direction = 0;
246334642Smarc 						event->vse_time = TOY;	/* time stamp */
246434642Smarc 					}
246530391Skarels GET_TBUTTON:
246634642Smarc 					/*
246734642Smarc 					* if button state has changed */
246830391Skarels 
246934642Smarc 					a = new_rep->state & 0x1E;   /* mask nonbutton bits */
247034642Smarc 					b = last_rep[qd].state & 0x1E;
247130391Skarels 
247234642Smarc 					if (a ^ b) {
247330391Skarels 
247434642Smarc 						/* event queue full now? (overflow condition) */
247530391Skarels 
247634642Smarc 						if (ISFULL(eqh) == TRUE) {
247734732Smarc 							printf("qd%d: qdiint: event queue overflow\n",qd);
247834642Smarc 							break;
247934642Smarc 						}
248030391Skarels 
248134642Smarc 						event = PUTBEGIN(eqh);  /* get new event */
248234642Smarc 						PUTEND(eqh);
248330391Skarels 
248434642Smarc 						++do_wakeup;   /* request a select wakeup call */
248530391Skarels 
248634642Smarc 						event->vse_x = eqh->curs_pos.x;
248734642Smarc 						event->vse_y = eqh->curs_pos.y;
248830391Skarels 
248934642Smarc 						event->vse_device = VSE_TABLET;  /* tablet */
249034642Smarc 						event->vse_type = VSE_BUTTON; /* button changed */
249134642Smarc 						event->vse_time = TOY;	   /* time stamp */
249230391Skarels 
249334642Smarc 						/* define the changed button and if up or down */
249430391Skarels 
249534642Smarc 						for ( c = 1;  c <= 0x10; c <<= 1) {
249634642Smarc 							if (c & (a ^ b)) {
249734642Smarc 								if (c == T_LEFT_BUTTON)
249834642Smarc 								    event->vse_key = VSE_T_LEFT_BUTTON;
249934642Smarc 								else if (c == T_FRONT_BUTTON)
250034642Smarc 								    event->vse_key = VSE_T_FRONT_BUTTON;
250134642Smarc 								else if (c == T_RIGHT_BUTTON)
250234642Smarc 								    event->vse_key = VSE_T_RIGHT_BUTTON;
250334642Smarc 								else if (c == T_BACK_BUTTON)
250434642Smarc 								    event->vse_key = VSE_T_BACK_BUTTON;
250534642Smarc 								break;
250634642Smarc 							}
250734642Smarc 						}
250830391Skarels 
250934642Smarc 						/* set bit = button depressed */
251030391Skarels 
251134642Smarc 						if (c & a)
251234642Smarc 						    event->vse_direction = VSE_KBTDOWN;
251334642Smarc 						else
251434642Smarc 							event->vse_direction = VSE_KBTUP;
251534642Smarc 					}
251630391Skarels 
251734642Smarc 					/* refresh last report */
251830391Skarels 
251934642Smarc 					last_rep[qd] = current_rep[qd];
252030391Skarels 
252134642Smarc 				} /* get last byte of report */
252234642Smarc 			} /* pick up tablet input */
252330391Skarels 
252434642Smarc 		} /* while input available.. */
252530391Skarels 
252634642Smarc 		/*
252734642Smarc 		* do select wakeup
252834642Smarc 		*/
252934732Smarc 		if (qdrsel[qd] && do_wakeup && qdflags[qd].selmask & SEL_READ) {
253034732Smarc 			selwakeup(qdrsel[qd], 0);
253134732Smarc 			qdrsel[qd] = 0;
253234642Smarc 			qdflags[qd].selmask &= ~SEL_READ;
253334642Smarc 			do_wakeup = 0;
253434642Smarc 		}
253534732Smarc 	} else {
253634732Smarc 		/*
253734732Smarc 		 * if the graphic device is not turned on, this is console input
253834732Smarc 		 */
2539*40817Smarc 		if (qdpolling)
2540*40817Smarc 			return;
254134642Smarc 		ui = qdinfo[qd];
254234642Smarc 		if (ui == 0 || ui->ui_alive == 0)
254334732Smarc 			return;
254430391Skarels 
254534642Smarc 		tp = &qd_tty[qd << 2];
254630391Skarels 
254734642Smarc 		/*
254834732Smarc 		 * Get a character from the keyboard.
254934732Smarc 		 */
255034732Smarc 		while (duart->statusA&RCV_RDY) {
255134642Smarc 			key = duart->dataA;
255234642Smarc 			key &= 0xFF;
255334642Smarc 			/*
255434732Smarc 			* Check for various keyboard errors
255534732Smarc 			*/
255634732Smarc 			if (key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
255734642Smarc 			    key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
255834732Smarc 				printf("qd%d: qdiint: Keyboard error, code = %x\n",qd,key);
255934732Smarc 				return;
256034642Smarc 			}
256130391Skarels 
256234642Smarc 			if (key < LK_LOWEST)
256334732Smarc 			    return;
256430391Skarels 
256534642Smarc 			/*
256634642Smarc 			* See if its a state change key */
256730391Skarels 
256834642Smarc 			switch (key) {
256930391Skarels 
257034642Smarc 			case LOCK:
257134642Smarc 				q_keyboard.lock ^= 0xffff;	/* toggle */
257234642Smarc 				if (q_keyboard.lock)
257334732Smarc 					(void)led_control(qd, LK_LED_ENABLE,
257434732Smarc 							  LK_LED_LOCK);
257534642Smarc 				else
257634732Smarc 					(void)led_control(qd, LK_LED_DISABLE,
257734732Smarc 							  LK_LED_LOCK);
257834642Smarc 				return;
257930391Skarels 
258034642Smarc 			case SHIFT:
258134642Smarc 				q_keyboard.shift ^= 0xFFFF;
258234642Smarc 				return;
258330391Skarels 
258434642Smarc 			case CNTRL:
258534642Smarc 				q_keyboard.cntrl ^= 0xFFFF;
258634642Smarc 				return;
258730391Skarels 
258834642Smarc 			case ALLUP:
258934642Smarc 				q_keyboard.cntrl = 0;
259034642Smarc 				q_keyboard.shift = 0;
259134642Smarc 				return;
259230391Skarels 
259334642Smarc 			case REPEAT:
259434642Smarc 				chr = q_keyboard.last;
259534642Smarc 				break;
259630391Skarels 
259734642Smarc 				/*
259834642Smarc 				* Test for cntrl characters. If set, see if the character
259934642Smarc 				* is elligible to become a control character. */
260030391Skarels 
260134642Smarc 			default:
260230391Skarels 
260334642Smarc 				if (q_keyboard.cntrl) {
260434642Smarc 					chr = q_key[key];
260534642Smarc 					if (chr >= ' ' && chr <= '~')
260634642Smarc 					    chr &= 0x1F;
260734642Smarc 					else if (chr >= 0xA1 && chr <= 0xFE)
260834642Smarc 					    chr &= 0x9F;
260934642Smarc 				}
261034642Smarc 				else if( q_keyboard.lock || q_keyboard.shift )
261134642Smarc 				    chr = q_shift_key[key];
261234642Smarc 				else
261334642Smarc 					chr = q_key[key];
261434642Smarc 				break;
261530391Skarels 			}
261630391Skarels 
261734642Smarc 			q_keyboard.last = chr;
261830391Skarels 
261934642Smarc 			/*
262034642Smarc 			* Check for special function keys */
262130391Skarels 
262234642Smarc 			if (chr & 0x100) {
262334642Smarc 				char *string;
262434642Smarc 				string = q_special[chr & 0x7F];
262534642Smarc 				while(*string)
262634642Smarc 				    (*linesw[tp->t_line].l_rint)(*string++, tp);
262734615Smarc 			}
262834642Smarc 			else {
2629*40817Smarc #ifdef KADB
2630*40817Smarc 				if (!kdbrintr(chr&0177, tp))
2631*40817Smarc #endif
263234642Smarc 				(*linesw[tp->t_line].l_rint)(chr&0177, tp);
263334642Smarc 			}
263430391Skarels 		}
263530391Skarels 	}
263630391Skarels } /* qdiint */
263730391Skarels 
263834732Smarc /*
263934732Smarc  *
264034732Smarc  * Clear the QDSS screen
264134732Smarc  *
264234732Smarc  *			     >>> NOTE <<<
264334732Smarc  *
264434732Smarc  *   This code requires that certain adder initialization be valid.  To
264534732Smarc  *   assure that this requirement is satisfied, this routine should be
264634732Smarc  *   called only after calling the "setup_dragon()" function.
264734732Smarc  *
264834732Smarc  *   Clear the bitmap a piece at a time. Since the fast scroll clear
264934732Smarc  *   only clears the current displayed portion of the bitmap put a
265034732Smarc  *   temporary value in the y limit register so we can access whole
265134732Smarc  *   bitmap
265234732Smarc  *
265334732Smarc  */
265430391Skarels clear_qd_screen(unit)
265534732Smarc 	int unit;
265630391Skarels {
265730391Skarels 	register struct adder *adder;
265830391Skarels 	adder = (struct adder *) qdmap[unit].adder;
265930391Skarels 
266030391Skarels 	adder->x_limit = 1024;
266130391Skarels 	adder->y_limit = 2048 - CHAR_HEIGHT;
266230391Skarels 	adder->y_offset_pending = 0;
266334732Smarc #define WSV  (void)wait_status(adder, VSYNC); (void)wait_status(adder, VSYNC)
266434642Smarc 	WSV;
266530391Skarels 	adder->y_scroll_constant = SCROLL_ERASE;
266634642Smarc 	WSV;
266730391Skarels 	adder->y_offset_pending = 864;
266834642Smarc 	WSV;
266930391Skarels 	adder->y_scroll_constant = SCROLL_ERASE;
267034642Smarc 	WSV;
267130391Skarels 	adder->y_offset_pending = 1728;
267234642Smarc 	WSV;
267330391Skarels 	adder->y_scroll_constant = SCROLL_ERASE;
267434642Smarc 	WSV;
267530391Skarels 	adder->y_offset_pending = 0;	 /* back to normal */
267634642Smarc 	WSV;
267730391Skarels 	adder->x_limit = MAX_SCREEN_X;
267830391Skarels 	adder->y_limit = MAX_SCREEN_Y + FONT_HEIGHT;
267934642Smarc #undef WSV
268030391Skarels 
268130391Skarels } /* clear_qd_screen */
268230391Skarels 
268334732Smarc /*
268434732Smarc  *  kernel console output to the glass tty
268534732Smarc  */
268630391Skarels qdputc(chr)
268734642Smarc 	register char chr;
268830391Skarels {
268930391Skarels 
269034642Smarc 	/*
269134642Smarc 	 * if system is now physical, forget it (ie: crash DUMP)
269234642Smarc 	 */
269334642Smarc 	if ((mfpr(MAPEN) & 1) == 0)
269434642Smarc 		return;
269534615Smarc 
269634732Smarc 	blitc(0, (u_char)(chr & 0xff));
269732012Smarc 	if ((chr & 0177) == '\n')
269832012Smarc 		blitc(0, '\r');
269930391Skarels 
270030391Skarels } /* qdputc */
270130391Skarels 
270234732Smarc /*
270334732Smarc  *  load the mouse cursor's template RAM bitmap
270434732Smarc  */
270530391Skarels ldcursor(unit, bitmap)
270634732Smarc 	int unit;
270734732Smarc 	register short *bitmap;
270830391Skarels {
270930391Skarels 	register struct dga *dga;
271030391Skarels 	register short *temp;
271130391Skarels 	register int i;
271234732Smarc 	int curs;
271330391Skarels 
271430391Skarels 	dga = (struct dga *) qdmap[unit].dga;
271530391Skarels 	temp = (short *) qdmap[unit].template;
271630391Skarels 
271730391Skarels 	if (dga->csr & CURS_ENB) {	/* if the cursor is enabled.. */
271834732Smarc 		curs = -1;		/* ..note that.. */
271934642Smarc 		dga->csr &= ~CURS_ENB;	/* ..and shut it off */
272034732Smarc 	} else
272134732Smarc 		curs = 0;
272230391Skarels 
272330391Skarels 	dga->csr &= ~CURS_ENB;		/* shut off the cursor */
272430391Skarels 
272530391Skarels 	temp += (8 * 1024) - 32;	/* cursor is 32 WORDS from the end */
272634642Smarc 	/* ..of the 8k WORD template space */
272730391Skarels 	for (i = 0; i < 32; ++i)
272834642Smarc 		*temp++ = *bitmap++;
272930391Skarels 
273034732Smarc 	if (curs) {			/* if cursor was enabled.. */
273134642Smarc 		dga->csr |= CURS_ENB;	/* ..turn it back on */
273230391Skarels 	}
273330391Skarels 
273430391Skarels } /* ldcursor */
273530391Skarels 
273634732Smarc /*
273734732Smarc  *  Put the console font in the QDSS off-screen memory
273834732Smarc  */
273930391Skarels ldfont(unit)
274034732Smarc 	int unit;
274130391Skarels {
274230391Skarels 	register struct adder *adder;
274330391Skarels 
274434732Smarc 	register i, j, k, max_chars_line;
274534732Smarc 	register short packed;
274630391Skarels 
274730391Skarels 	adder = (struct adder *) qdmap[unit].adder;
274830391Skarels 
274934642Smarc 	/*
275034732Smarc 	* setup VIPER operand control registers
275134732Smarc 	*/
275230391Skarels 	write_ID(adder, MASK_1, 0xFFFF);
275330391Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
275430391Skarels 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
275530391Skarels 
275630391Skarels 	write_ID(adder, SRC1_OCR_B,
275734642Smarc 	EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY);
275830391Skarels 	write_ID(adder, SRC2_OCR_B,
275934642Smarc 	EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY);
276030391Skarels 	write_ID(adder, DST_OCR_B,
276134642Smarc 	EXT_SOURCE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
276230391Skarels 
276330391Skarels 	adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL;
276430391Skarels 
276534642Smarc 	/*
276634732Smarc 	* load destination data
276734732Smarc 	*/
276834732Smarc 	(void)wait_status(adder, RASTEROP_COMPLETE);
276930391Skarels 
277030391Skarels 	adder->destination_x = FONT_X;
277130391Skarels 	adder->destination_y = FONT_Y;
277234732Smarc #if FONT_WIDTH > MAX_SCREEN_X
277334732Smarc 	adder->fast_dest_dx = MAX_SCREEN_X;
277434732Smarc #else
277534732Smarc 	adder->fast_dest_dx = FONT_WIDTH;
277634732Smarc #endif
277730391Skarels 	adder->slow_dest_dy = CHAR_HEIGHT;
277830391Skarels 
277934642Smarc 	/*
278034642Smarc 	* setup for processor to bitmap xfer  */
278130391Skarels 
278230391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0001);
278330391Skarels 	adder->cmd = PBT | OCRB | 2 | DTE | 2;
278430391Skarels 
278534642Smarc 	/*
278634642Smarc 	* Figure out how many characters can be stored on one "line" of
278734642Smarc 	* offscreen memory.
278834642Smarc 	*/
278934642Smarc 	max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
279034642Smarc 	if ((CHARS/2 + CHARS%2) < max_chars_line)
279134642Smarc 	    max_chars_line = CHARS/2 + CHARS%2;
279230391Skarels 
279334642Smarc 	/*
279434642Smarc 	* iteratively do the processor to bitmap xfer */
279534615Smarc 
279630391Skarels 	for (i = 0; i < ROWS; ++i) {
279730391Skarels 
279834642Smarc 		/* PTOB a scan line */
279930391Skarels 
280034642Smarc 		for (j = 0, k = i; j < max_chars_line; ++j) {
280134642Smarc 			/* PTOB one scan of a char cell */
280230391Skarels 
280334642Smarc 			packed = q_font[k];
280434642Smarc 			k += ROWS;
280534642Smarc 			packed |= ((short)q_font[k] << 8);
280634642Smarc 			k += ROWS;
280730391Skarels 
280834732Smarc 			(void)wait_status(adder, TX_READY);
280934642Smarc 			adder->id_data = packed;
281034642Smarc 		}
281130391Skarels 	}
281230391Skarels 
281334642Smarc 	/*
281434642Smarc 	 * (XXX XXX XXX - should remove)
281534642Smarc 	 *
281634642Smarc 	 * Copy the second row of characters.  Subtract the first
281734642Smarc 	 * row from the total number.  Divide this quantity by 2
281834642Smarc 	 * because 2 chars are stored in a short in the PTOB loop
281934642Smarc 	 * below.  Figure out how many characters can be stored on
282034642Smarc 	 * one "line" of offscreen memory
282134642Smarc 	 */
282234642Smarc 
282334642Smarc 	max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
282434642Smarc 	if ((CHARS/2 + CHARS%2) < max_chars_line)
282534642Smarc 	    return;
282634642Smarc 	max_chars_line = (CHARS/2 + CHARS%2) - max_chars_line; /* 95 - 64 */
282734642Smarc 	/* Paranoia check to see if 3rd row may be needed */
282834642Smarc 	if (max_chars_line > (MAX_SCREEN_X/(CHAR_WIDTH*2)))
282934615Smarc 	    max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
283034615Smarc 
283134615Smarc 	adder->destination_x = FONT_X;
283234615Smarc 	adder->destination_y = FONT_Y - CHAR_HEIGHT;
283334615Smarc 	adder->fast_dest_dx = max_chars_line * CHAR_WIDTH * 2;
283434615Smarc 	adder->slow_dest_dy = CHAR_HEIGHT;
283534615Smarc 
283634642Smarc 	/*
283734642Smarc 	* setup for processor to bitmap xfer
283834642Smarc 	*/
283934615Smarc 	write_ID(adder, CS_UPDATE_MASK, 0x0001);
284034615Smarc 	adder->cmd = PBT | OCRB | 2 | DTE | 2;
284134615Smarc 
284234642Smarc 	/*
284334642Smarc 	* iteratively do the processor to bitmap xfer
284434642Smarc 	*/
284534615Smarc 	for (i = 0; i < ROWS; ++i) {
284634642Smarc 		/*
284734642Smarc 		 * PTOB a scan line
284834642Smarc 		 */
284934642Smarc 		for (j = 0, k = i; j < max_chars_line; ++j) {
285034642Smarc 			/*
285134642Smarc 			 * PTOB one scan of a char cell
285234642Smarc 			 */
285334642Smarc 			packed = q_font[k + FONT_OFFSET];
285434642Smarc 			k += ROWS;
285534642Smarc 			packed |= ((short)q_font[k + FONT_OFFSET] << 8);
285634642Smarc 			k += ROWS;
285734732Smarc 			(void)wait_status(adder, TX_READY);
285834642Smarc 			adder->id_data = packed;
285934642Smarc 		}
286034615Smarc 	}
286134615Smarc 
286230391Skarels }  /* ldfont */
286330391Skarels 
2864*40817Smarc qdpoll(onoff)
2865*40817Smarc {
2866*40817Smarc 	qdpolling = onoff;
2867*40817Smarc }
2868*40817Smarc 
286934732Smarc /*
287034732Smarc  *  Get a character from the LK201 (polled)
287134732Smarc  */
287234732Smarc qdgetc()
287334732Smarc {
287434732Smarc 	register short key;
287534732Smarc 	register char chr;
287634732Smarc 	register struct duart *duart;
287730391Skarels 
287834732Smarc 	duart = (struct duart *) qdmap[0].duart;
287934732Smarc 
288034732Smarc 	/*
288134732Smarc 	* Get a character from the keyboard.
288234732Smarc 	*/
288334732Smarc LOOP:
288434732Smarc 	while (!(duart->statusA&RCV_RDY))
288534732Smarc 		;
288634732Smarc 
288734732Smarc 	key = duart->dataA;
288834732Smarc 	key &= 0xFF;
288934732Smarc 
289034732Smarc 	/*
289134732Smarc 	* Check for various keyboard errors  */
289234732Smarc 
289334732Smarc 	if (key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
289434732Smarc 	    key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
289534732Smarc 		printf("Keyboard error, code = %x\n", key);
289634732Smarc 		return(0);
289734732Smarc 	}
289834732Smarc 
289934732Smarc 	if (key < LK_LOWEST)
290034732Smarc 		return(0);
290134732Smarc 
290234732Smarc 	/*
290334732Smarc 	 * See if its a state change key
290434732Smarc 	 */
290534732Smarc 	switch (key) {
290634732Smarc 
290734732Smarc 	case LOCK:
290834732Smarc 		q_keyboard.lock ^= 0xffff;	/* toggle */
290934732Smarc 		if (q_keyboard.lock)
291034732Smarc 			(void)led_control(0, LK_LED_ENABLE, LK_LED_LOCK);
291134732Smarc 		else
291234732Smarc 			(void)led_control(0, LK_LED_DISABLE, LK_LED_LOCK);
291334732Smarc 		goto LOOP;
291434732Smarc 
291534732Smarc 	case SHIFT:
291634732Smarc 		q_keyboard.shift ^= 0xFFFF;
291734732Smarc 		goto LOOP;
291834732Smarc 
291934732Smarc 	case CNTRL:
292034732Smarc 		q_keyboard.cntrl ^= 0xFFFF;
292134732Smarc 		goto LOOP;
292234732Smarc 
292334732Smarc 	case ALLUP:
292434732Smarc 		q_keyboard.cntrl = 0;
292534732Smarc 		q_keyboard.shift = 0;
292634732Smarc 		goto LOOP;
292734732Smarc 
292834732Smarc 	case REPEAT:
292934732Smarc 		chr = q_keyboard.last;
293034732Smarc 		break;
293134732Smarc 
293234732Smarc 		/*
293334732Smarc 		* Test for cntrl characters. If set, see if the character
293434732Smarc 		* is elligible to become a control character.
293534732Smarc 		*/
293634732Smarc 	default:
293734732Smarc 
293834732Smarc 		if (q_keyboard.cntrl) {
293934732Smarc 			chr = q_key[key];
294034732Smarc 			if (chr >= ' ' && chr <= '~')
294134732Smarc 			    chr &= 0x1F;
294234732Smarc 		}
294334732Smarc 		else if ( q_keyboard.lock || q_keyboard.shift )
294434732Smarc 		    chr = q_shift_key[key];
294534732Smarc 		else
294634732Smarc 			chr = q_key[key];
294734732Smarc 		break;
294834732Smarc 	}
294934732Smarc 
295034732Smarc 	if (chr < ' ' && chr > '~')	/* if input is non-displayable */
295134732Smarc 		return(0);		/* ..then pitch it! */
295234732Smarc 
295334732Smarc 	q_keyboard.last = chr;
295434732Smarc 
295534732Smarc 	/*
295634732Smarc 	* Check for special function keys */
295734732Smarc 
295834732Smarc 	if (chr & 0x80) 		/* pitch the function keys */
295934732Smarc 		return(0);
296034732Smarc 	else
296134732Smarc 		return(chr);
296234732Smarc 
296334732Smarc } /* qdgetc */
296434732Smarc 
296534732Smarc /*
296634732Smarc  *  led_control()... twiddle LK-201 LED's
296734732Smarc  */
296830391Skarels led_control(unit, cmd, led_mask)
296934732Smarc 	int unit, cmd, led_mask;
297030391Skarels {
297134732Smarc 	register i;
297230391Skarels 	register struct duart *duart;
297330391Skarels 
297434732Smarc 	duart = (struct duart *)qdmap[unit].duart;
297530391Skarels 
297630391Skarels 	for (i = 1000; i > 0; --i) {
297734732Smarc 		if (duart->statusA&XMT_RDY) {
297834642Smarc 			duart->dataA = cmd;
297934642Smarc 			break;
298034642Smarc 		}
298130391Skarels 	}
298230391Skarels 	for (i = 1000; i > 0; --i) {
298334732Smarc 		if (duart->statusA&XMT_RDY) {
298434642Smarc 			duart->dataA = led_mask;
298534642Smarc 			break;
298634642Smarc 		}
298730391Skarels 	}
298830391Skarels 	if (i == 0)
298934642Smarc 		return(BAD);
299030391Skarels 	return(GOOD);
299130391Skarels 
299230391Skarels } /* led_control */
299330391Skarels 
299434732Smarc /*
299534732Smarc  *  scroll_up()... move the screen up one character height
299634732Smarc  */
299730391Skarels scroll_up(adder)
299834642Smarc 	register struct adder *adder;
299930391Skarels {
300034642Smarc 	/*
300134642Smarc 	* setup VIPER operand control registers
300234642Smarc 	*/
300334732Smarc 	(void)wait_status(adder, ADDRESS_COMPLETE);
300430391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x00FF);  /* select all planes */
300530391Skarels 	write_ID(adder, MASK_1, 0xFFFF);
300630391Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
300730391Skarels 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
300830391Skarels 	write_ID(adder, SRC1_OCR_B,
300934642Smarc 	EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY);
301030391Skarels 	write_ID(adder, DST_OCR_B,
301134642Smarc 	EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
301234642Smarc 	/*
301334642Smarc 	 * load DESTINATION origin and vectors
301434642Smarc 	 */
301530391Skarels 	adder->fast_dest_dy = 0;
301630391Skarels 	adder->slow_dest_dx = 0;
301730391Skarels 	adder->error_1 = 0;
301830391Skarels 	adder->error_2 = 0;
301930391Skarels 	adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL;
302030391Skarels 	adder->destination_x = 0;
302130391Skarels 	adder->fast_dest_dx = 1024;
302230391Skarels 	adder->destination_y = 0;
302330391Skarels 	adder->slow_dest_dy = 864 - CHAR_HEIGHT;
302434642Smarc 	/*
302534642Smarc 	 * load SOURCE origin and vectors
302634642Smarc 	 */
302730391Skarels 	adder->source_1_x = 0;
302830391Skarels 	adder->source_1_dx = 1024;
302930391Skarels 	adder->source_1_y = 0 + CHAR_HEIGHT;
303030391Skarels 	adder->source_1_dy = 864 - CHAR_HEIGHT;
303130391Skarels 	write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
303230391Skarels 	adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE;
303334642Smarc 	/*
303434642Smarc 	 * do a rectangle clear of last screen line
303534642Smarc 	 */
303630391Skarels 	write_ID(adder, MASK_1, 0xffff);
303730391Skarels 	write_ID(adder, SOURCE, 0xffff);
303830391Skarels 	write_ID(adder,DST_OCR_B,
303934642Smarc 	(EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY));
304030391Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 0);
304130391Skarels 	adder->error_1 = 0;
304230391Skarels 	adder->error_2 = 0;
304334642Smarc 	adder->slow_dest_dx = 0;		/* set up the width of	*/
304430391Skarels 	adder->slow_dest_dy = CHAR_HEIGHT;	/* rectangle */
304530391Skarels 	adder->rasterop_mode = (NORMAL | DST_WRITE_ENABLE) ;
304634732Smarc 	(void)wait_status(adder, RASTEROP_COMPLETE);
304730391Skarels 	adder->destination_x = 0;
304830391Skarels 	adder->destination_y = 864 - CHAR_HEIGHT;
304930391Skarels 	adder->fast_dest_dx = 1024;	/* set up the height	*/
305030391Skarels 	adder->fast_dest_dy = 0;	/* of rectangle 	*/
305130391Skarels 	write_ID(adder, LU_FUNCTION_R2, (FULL_SRC_RESOLUTION | LF_SOURCE));
305230391Skarels 	adder->cmd = (RASTEROP | OCRB | LF_R2 | DTE ) ;
305330391Skarels 
305430391Skarels } /* scroll_up */
305530391Skarels 
305634732Smarc /*
305734732Smarc  *  init shared memory pointers and structures
305834732Smarc  */
305930391Skarels init_shared(unit)
306034732Smarc 	register unit;
306130391Skarels {
306230391Skarels 	register struct dga *dga;
306330391Skarels 
306430391Skarels 	dga = (struct dga *) qdmap[unit].dga;
306530391Skarels 
306634642Smarc 	/*
306734642Smarc 	* initialize the event queue pointers and header */
306830391Skarels 
306930391Skarels 	eq_header[unit] = (struct qdinput *)
307034642Smarc 	    ((((int)event_shared & ~(0x01FF)) + 512)
307134642Smarc 		+ (EVENT_BUFSIZE * unit));
307230391Skarels 	eq_header[unit]->curs_pos.x = 0;
307330391Skarels 	eq_header[unit]->curs_pos.y = 0;
307430391Skarels 	dga->x_cursor = TRANX(eq_header[unit]->curs_pos.x);
307530391Skarels 	dga->y_cursor = TRANY(eq_header[unit]->curs_pos.y);
307630391Skarels 	eq_header[unit]->curs_box.left = 0;
307730391Skarels 	eq_header[unit]->curs_box.right = 0;
307830391Skarels 	eq_header[unit]->curs_box.top = 0;
307930391Skarels 	eq_header[unit]->curs_box.bottom = 0;
308034642Smarc 	/*
308134642Smarc 	 * assign a pointer to the DMA I/O buffer for this QDSS.
308234642Smarc 	 */
308330391Skarels 	DMAheader[unit] = (struct DMAreq_header *)
308434642Smarc 	    (((int)(&DMA_shared[0] + 512) & ~0x1FF)
308534642Smarc 		+ (DMAbuf_size * unit));
308630391Skarels 	DMAheader[unit]->DMAreq = (struct DMAreq *) ((int)DMAheader[unit]
308734642Smarc 	    + sizeof(struct DMAreq_header));
308830391Skarels 	DMAheader[unit]->QBAreg = 0;
308930391Skarels 	DMAheader[unit]->status = 0;
309030391Skarels 	DMAheader[unit]->shared_size = DMAbuf_size;
309130391Skarels 	DMAheader[unit]->used = 0;
309230391Skarels 	DMAheader[unit]->size = 10;	/* default = 10 requests */
309330391Skarels 	DMAheader[unit]->oldest = 0;
309430391Skarels 	DMAheader[unit]->newest = 0;
309534642Smarc 	/*
309634642Smarc 	* assign a pointer to the scroll structure for this QDSS.
309734642Smarc 	*/
309830391Skarels 	scroll[unit] = (struct scroll *)
309934642Smarc 	    (((int)(&scroll_shared[0] + 512) & ~0x1FF)
310034642Smarc 		+ (sizeof(struct scroll) * unit));
310130391Skarels 	scroll[unit]->status = 0;
310230391Skarels 	scroll[unit]->viper_constant = 0;
310330391Skarels 	scroll[unit]->y_scroll_constant = 0;
310430391Skarels 	scroll[unit]->y_offset = 0;
310530391Skarels 	scroll[unit]->x_index_pending = 0;
310630391Skarels 	scroll[unit]->y_index_pending = 0;
310734642Smarc 	/*
310834642Smarc 	* assign a pointer to the color map write buffer for this QDSS
310934642Smarc 	*/
311030391Skarels 	color_buf[unit] = (struct color_buf *)
311134642Smarc 	    (((int)(&color_shared[0] + 512) & ~0x1FF)
311234642Smarc 		+ (COLOR_BUFSIZ * unit));
311330391Skarels 	color_buf[unit]->status = 0;
311430391Skarels 	color_buf[unit]->count = 0;
311530391Skarels 
311630391Skarels } /* init_shared */
311730391Skarels 
311834732Smarc /*
311934732Smarc  * init the ADDER, VIPER, bitmaps, & color map
312034732Smarc  */
312130391Skarels setup_dragon(unit)
312234732Smarc 	int unit;
312330391Skarels {
312430391Skarels 
312530391Skarels 	register struct adder *adder;
312630391Skarels 	register struct dga *dga;
312730391Skarels 	short *memcsr;
312834732Smarc 	register i;
312930391Skarels 	short top;		/* clipping/scrolling boundaries */
313030391Skarels 	short bottom;
313130391Skarels 	short right;
313230391Skarels 	short left;
313330391Skarels 	short *red;		/* color map pointers */
313430391Skarels 	short *green;
313530391Skarels 	short *blue;
313630391Skarels 
313734642Smarc 	/*
313834642Smarc 	* init for setup
313934642Smarc 	*/
314030391Skarels 	adder = (struct adder *) qdmap[unit].adder;
314130391Skarels 	dga = (struct dga *) qdmap[unit].dga;
314230391Skarels 	memcsr = (short *) qdmap[unit].memcsr;
314330391Skarels 	dga->csr &= ~(DMA_IE | 0x700);	/* halt DMA and kill the intrpts */
314430391Skarels 	*memcsr = SYNC_ON;		/* blank screen and turn off LED's */
314530391Skarels 	adder->command = CANCEL;
314634642Smarc 	/*
314734642Smarc 	* set monitor timing
314834642Smarc 	*/
314930391Skarels 	adder->x_scan_count_0 = 0x2800;
315030391Skarels 	adder->x_scan_count_1 = 0x1020;
315130391Skarels 	adder->x_scan_count_2 = 0x003A;
315230391Skarels 	adder->x_scan_count_3 = 0x38F0;
315330391Skarels 	adder->x_scan_count_4 = 0x6128;
315430391Skarels 	adder->x_scan_count_5 = 0x093A;
315530391Skarels 	adder->x_scan_count_6 = 0x313C;
315630391Skarels 	adder->sync_phase_adj = 0x0100;
315730391Skarels 	adder->x_scan_conf = 0x00C8;
315834642Smarc 	/*
315934642Smarc 	 * got a bug in secound pass ADDER! lets take care of it
316034642Smarc 	 *
316134642Smarc 	 * normally, just use the code in the following bug fix code, but to
316234642Smarc 	 * make repeated demos look pretty, load the registers as if there was
316334642Smarc 	 * no bug and then test to see if we are getting sync
316434642Smarc 	 */
316530391Skarels 	adder->y_scan_count_0 = 0x135F;
316630391Skarels 	adder->y_scan_count_1 = 0x3363;
316730391Skarels 	adder->y_scan_count_2 = 0x2366;
316830391Skarels 	adder->y_scan_count_3 = 0x0388;
316934642Smarc 	/*
317034642Smarc 	 * if no sync, do the bug fix code
317134642Smarc 	 */
317230391Skarels 	if (wait_status(adder, VSYNC) == BAD) {
317334642Smarc 		/* first load all Y scan registers with very short frame and
317434642Smarc 		 * wait for scroll service.  This guarantees at least one SYNC
317534642Smarc 		 * to fix the pass 2 Adder initialization bug (synchronizes
317634642Smarc 		 * XCINCH with DMSEEDH)
317734642Smarc 		 */
317834642Smarc 		adder->y_scan_count_0 = 0x01;
317934642Smarc 		adder->y_scan_count_1 = 0x01;
318034642Smarc 		adder->y_scan_count_2 = 0x01;
318134642Smarc 		adder->y_scan_count_3 = 0x01;
318234642Smarc 		/*
318334642Smarc 		 * delay at least 1 full frame time
318434642Smarc 		 */
318534732Smarc 		(void)wait_status(adder, VSYNC);
318634732Smarc 		(void)wait_status(adder, VSYNC);
318734642Smarc 		/*
318834642Smarc 		 * now load the REAL sync values (in reverse order just to
318934642Smarc 		 * be safe.
319034642Smarc 		 */
319134642Smarc 		adder->y_scan_count_3 = 0x0388;
319234642Smarc 		adder->y_scan_count_2 = 0x2366;
319334642Smarc 		adder->y_scan_count_1 = 0x3363;
319434642Smarc 		adder->y_scan_count_0 = 0x135F;
319530391Skarels 	}
319630391Skarels 	*memcsr = SYNC_ON | UNBLANK;	/* turn off leds and turn on video */
319734642Smarc 	/*
319834642Smarc 	 * zero the index registers
319934642Smarc 	 */
320030391Skarels 	adder->x_index_pending = 0;
320130391Skarels 	adder->y_index_pending = 0;
320230391Skarels 	adder->x_index_new = 0;
320330391Skarels 	adder->y_index_new = 0;
320430391Skarels 	adder->x_index_old = 0;
320530391Skarels 	adder->y_index_old = 0;
320630391Skarels 	adder->pause = 0;
320734642Smarc 	/*
320834642Smarc 	 * set rasterop mode to normal pen down
320934642Smarc 	 */
321030391Skarels 	adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL;
321134642Smarc 	/*
321234642Smarc 	 * set the rasterop registers to a default values
321334642Smarc 	 */
321430391Skarels 	adder->source_1_dx = 1;
321530391Skarels 	adder->source_1_dy = 1;
321630391Skarels 	adder->source_1_x = 0;
321730391Skarels 	adder->source_1_y = 0;
321830391Skarels 	adder->destination_x = 0;
321930391Skarels 	adder->destination_y = 0;
322030391Skarels 	adder->fast_dest_dx = 1;
322130391Skarels 	adder->fast_dest_dy = 0;
322230391Skarels 	adder->slow_dest_dx = 0;
322330391Skarels 	adder->slow_dest_dy = 1;
322430391Skarels 	adder->error_1 = 0;
322530391Skarels 	adder->error_2 = 0;
322634642Smarc 	/*
322734732Smarc 	 * scale factor = UNITY
322834642Smarc 	 */
322930391Skarels 	adder->fast_scale = UNITY;
323030391Skarels 	adder->slow_scale = UNITY;
323134642Smarc 	/*
323234642Smarc 	 * set the source 2 parameters
323334642Smarc 	 */
323430391Skarels 	adder->source_2_x = 0;
323530391Skarels 	adder->source_2_y = 0;
323630391Skarels 	adder->source_2_size = 0x0022;
323734642Smarc 	/*
323834642Smarc 	* initialize plane addresses for eight vipers
323934642Smarc 	*/
324030391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0001);
324130391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0000);
324230391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0002);
324330391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0001);
324430391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0004);
324530391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0002);
324630391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0008);
324730391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0003);
324830391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0010);
324930391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0004);
325030391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0020);
325130391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0005);
325230391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0040);
325330391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0006);
325430391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0080);
325530391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0007);
325634642Smarc 	/*
325734642Smarc 	 * initialize the external registers.
325834642Smarc 	 */
325930391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x00FF);
326030391Skarels 	write_ID(adder, CS_SCROLL_MASK, 0x00FF);
326134642Smarc 	/*
326234642Smarc 	 * initialize resolution mode
326334642Smarc 	 */
326430391Skarels 	write_ID(adder, MEMORY_BUS_WIDTH, 0x000C);     /* bus width = 16 */
326530391Skarels 	write_ID(adder, RESOLUTION_MODE, 0x0000);      /* one bit/pixel */
326634642Smarc 	/*
326734642Smarc 	 * initialize viper registers
326834642Smarc 	 */
326930391Skarels 	write_ID(adder, SCROLL_CONSTANT, SCROLL_ENABLE|VIPER_LEFT|VIPER_UP);
327030391Skarels 	write_ID(adder, SCROLL_FILL, 0x0000);
327134642Smarc 	/*
327234642Smarc 	 * set clipping and scrolling limits to full screen
327334642Smarc 	 */
327434732Smarc 	for (i = 1000, adder->status = 0;
327534732Smarc 	     i > 0 && !(adder->status&ADDRESS_COMPLETE); --i)
327634642Smarc 		;
327730391Skarels 	if (i == 0)
327834732Smarc 	    printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n",unit);
327930391Skarels 	top = 0;
328030391Skarels 	bottom = 2048;
328130391Skarels 	left = 0;
328230391Skarels 	right = 1024;
328330391Skarels 	adder->x_clip_min = left;
328430391Skarels 	adder->x_clip_max = right;
328530391Skarels 	adder->y_clip_min = top;
328630391Skarels 	adder->y_clip_max = bottom;
328730391Skarels 	adder->scroll_x_min = left;
328830391Skarels 	adder->scroll_x_max = right;
328930391Skarels 	adder->scroll_y_min = top;
329030391Skarels 	adder->scroll_y_max = bottom;
329134732Smarc 	(void)wait_status(adder, VSYNC);	/* wait at LEAST 1 full frame */
329234732Smarc 	(void)wait_status(adder, VSYNC);
329330391Skarels 	adder->x_index_pending = left;
329430391Skarels 	adder->y_index_pending = top;
329530391Skarels 	adder->x_index_new = left;
329630391Skarels 	adder->y_index_new = top;
329730391Skarels 	adder->x_index_old = left;
329830391Skarels 	adder->y_index_old = top;
329930391Skarels 
330034732Smarc 	for (i = 1000, adder->status = 0; i > 0 &&
330134732Smarc 	     !(adder->status&ADDRESS_COMPLETE) ; --i)
330234642Smarc 		;
330330391Skarels 	if (i == 0)
330434732Smarc 	       printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n",unit);
330530391Skarels 
330630391Skarels 	write_ID(adder, LEFT_SCROLL_MASK, 0x0000);
330730391Skarels 	write_ID(adder, RIGHT_SCROLL_MASK, 0x0000);
330834642Smarc 	/*
330934642Smarc 	* set source and the mask register to all ones (ie: white) o
331034642Smarc 	*/
331130391Skarels 	write_ID(adder, SOURCE, 0xFFFF);
331230391Skarels 	write_ID(adder, MASK_1, 0xFFFF);
331330391Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
331430391Skarels 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
331534642Smarc 	/*
331634642Smarc 	* initialize Operand Control Register banks for fill command
331734642Smarc 	*/
331830391Skarels 	write_ID(adder, SRC1_OCR_A, EXT_NONE | INT_M1_M2  | NO_ID | WAIT);
331930391Skarels 	write_ID(adder, SRC2_OCR_A, EXT_NONE | INT_SOURCE | NO_ID | NO_WAIT);
332030391Skarels 	write_ID(adder, DST_OCR_A, EXT_NONE | INT_NONE	 | NO_ID | NO_WAIT);
332130391Skarels 	write_ID(adder, SRC1_OCR_B, EXT_NONE | INT_SOURCE | NO_ID | WAIT);
332230391Skarels 	write_ID(adder, SRC2_OCR_B, EXT_NONE | INT_M1_M2  | NO_ID | NO_WAIT);
332330391Skarels 	write_ID(adder, DST_OCR_B, EXT_NONE | INT_NONE | NO_ID | NO_WAIT);
332434642Smarc 	/*
332534642Smarc 	* init Logic Unit Function registers, (these are just common values,
332634642Smarc 	* and may be changed as required).
332734642Smarc 	*/
332830391Skarels 	write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
332934642Smarc 	write_ID(adder, LU_FUNCTION_R2, FULL_SRC_RESOLUTION | LF_SOURCE |
333034642Smarc 		 INV_M1_M2);
333130391Skarels 	write_ID(adder, LU_FUNCTION_R3, FULL_SRC_RESOLUTION | LF_D_OR_S);
333230391Skarels 	write_ID(adder, LU_FUNCTION_R4, FULL_SRC_RESOLUTION | LF_D_XOR_S);
333334642Smarc 	/*
333434642Smarc 	* load the color map for black & white
333534642Smarc 	*/
333634732Smarc 	for (i = 0, adder->status = 0; i < 10000 && !(adder->status&VSYNC); ++i)
333734642Smarc 		;
333830391Skarels 
333930391Skarels 	if (i == 0)
334034732Smarc 		printf("qd%d: setup_dragon: timeout on VSYNC\n", unit);
334130391Skarels 
334230391Skarels 	red = (short *) qdmap[unit].red;
334330391Skarels 	green = (short *) qdmap[unit].green;
334430391Skarels 	blue = (short *) qdmap[unit].blue;
334530391Skarels 
334630391Skarels 	*red++ = 0x00;			/* black */
334730391Skarels 	*green++ = 0x00;
334830391Skarels 	*blue++ = 0x00;
334930391Skarels 
335030391Skarels 	*red-- = 0xFF;			/* white */
335130391Skarels 	*green-- = 0xFF;
335230391Skarels 	*blue-- = 0xFF;
335330391Skarels 
335434642Smarc 	/*
335534732Smarc 	* set color map for mouse cursor
335634732Smarc 	*/
335730391Skarels 
335830391Skarels 	red += 254;
335930391Skarels 	green += 254;
336030391Skarels 	blue += 254;
336130391Skarels 
336230391Skarels 	*red++ = 0x00;			/* black */
336330391Skarels 	*green++ = 0x00;
336430391Skarels 	*blue++ = 0x00;
336530391Skarels 
336630391Skarels 	*red = 0xFF;			/* white */
336730391Skarels 	*green = 0xFF;
336830391Skarels 	*blue = 0xFF;
336930391Skarels 
337030391Skarels } /* setup_dragon */
337130391Skarels 
337234732Smarc /*
337334732Smarc  * Init the DUART and set defaults in input
337434732Smarc  */
337530391Skarels setup_input(unit)
337634732Smarc 	int unit;
337730391Skarels {
337830391Skarels 	register struct duart *duart;	/* DUART register structure pointer */
337934732Smarc 	register i, bits;
338030391Skarels 	char id_byte;
338130391Skarels 
338230391Skarels 	duart = (struct duart *) qdmap[unit].duart;
338330391Skarels 	duart->imask = 0;
338430391Skarels 
338534642Smarc 	/*
338634642Smarc 	* setup the DUART for kbd & pointing device
338734642Smarc 	*/
338834732Smarc 	duart->cmdA = RESET_M;	/* reset mode reg ptr for kbd */
338934732Smarc 	duart->modeA = 0x13;	/* 8 bits, no parity, rcv IE, */
339034732Smarc 				/* no RTS control,char error mode */
339134732Smarc 	duart->modeA = 0x07;	/* 1 stop bit,CTS does not IE XMT */
339234732Smarc 				/* no RTS control,no echo or loop */
339334732Smarc 	duart->cmdB = RESET_M;	/* reset mode reg pntr for host */
339434732Smarc 	duart->modeB = 0x07;	/* 8 bits, odd parity, rcv IE.. */
339534732Smarc 				/* ..no RTS cntrl, char error mode */
339634732Smarc 	duart->modeB = 0x07;	/* 1 stop bit,CTS does not IE XMT */
339734732Smarc 				/* no RTS control,no echo or loop */
339834732Smarc 	duart->auxctl = 0x00;	/* baud rate set 1 */
339934732Smarc 	duart->clkselA = 0x99;	/* 4800 baud for kbd */
340034732Smarc 	duart->clkselB = 0x99;	/* 4800 baud for mouse */
340130391Skarels 
340230391Skarels 	/* reset everything for keyboard */
340330391Skarels 
340430391Skarels 	for (bits = RESET_M; bits < START_BREAK; bits += 0x10)
340534642Smarc 		duart->cmdA = bits;
340630391Skarels 
340730391Skarels 	/* reset everything for host */
340830391Skarels 
340930391Skarels 	for (bits = RESET_M; bits < START_BREAK; bits += 0x10)
341034642Smarc 		duart->cmdB = bits;
341130391Skarels 
341230391Skarels 	duart->cmdA = EN_RCV | EN_XMT; /* enbl xmt & rcv for kbd */
341330391Skarels 	duart->cmdB = EN_RCV | EN_XMT; /* enbl xmt & rcv for pointer device */
341430391Skarels 
341534642Smarc 	/*
341634732Smarc 	* init keyboard defaults (DUART channel A)
341734732Smarc 	*/
341830391Skarels 	for (i = 500; i > 0; --i) {
341934732Smarc 		if (duart->statusA&XMT_RDY) {
342034642Smarc 			duart->dataA = LK_DEFAULTS;
342134642Smarc 			break;
342234642Smarc 		}
342330391Skarels 	}
342430391Skarels 
342530391Skarels 	for (i = 100000; i > 0; --i) {
342634732Smarc 		if (duart->statusA&RCV_RDY) {
342734642Smarc 			break;
342834642Smarc 		}
342930391Skarels 	}
343030391Skarels 
343134732Smarc 	if (duart->dataA)	/* flush the ACK */
343234732Smarc 		;
343330391Skarels 
343434642Smarc 	/*
343534732Smarc 	* identify the pointing device
343634732Smarc 	*/
343730391Skarels 	for (i = 500; i > 0; --i) {
343834732Smarc 		if (duart->statusB&XMT_RDY) {
343934642Smarc 			duart->dataB = SELF_TEST;
344034642Smarc 			break;
344134642Smarc 		}
344230391Skarels 	}
344330391Skarels 
344434642Smarc 	/*
344530391Skarels 	* wait for 1st byte of self test report */
344630391Skarels 
344730391Skarels 	for (i = 100000; i > 0; --i) {
344834732Smarc 		if (duart->statusB&RCV_RDY) {
344934642Smarc 			break;
345034642Smarc 		}
345130391Skarels 	}
345230391Skarels 
345330391Skarels 	if (i == 0) {
345434732Smarc 		printf("qd[%d]: setup_input: timeout on 1st byte of self test\n"
345534642Smarc 		       ,unit);
345634642Smarc 		goto OUT;
345730391Skarels 	}
345830391Skarels 
345934732Smarc 	if (duart->dataB)
346034732Smarc 		;
346130391Skarels 
346234642Smarc 	/*
346334732Smarc 	* wait for ID byte of self test report
346434732Smarc 	*/
346530391Skarels 	for (i = 100000; i > 0; --i) {
346634732Smarc 		if (duart->statusB&RCV_RDY) {
346734642Smarc 			break;
346834642Smarc 		}
346930391Skarels 	}
347030391Skarels 
347130391Skarels 	if (i == 0) {
347234732Smarc 		printf("qd[%d]: setup_input: timeout on 2nd byte of self test\n", unit);
347334642Smarc 		goto OUT;
347430391Skarels 	}
347530391Skarels 
347630391Skarels 	id_byte = duart->dataB;
347730391Skarels 
347834642Smarc 	/*
347934732Smarc 	* wait for other bytes to come in
348034732Smarc 	*/
348130391Skarels 	for (i = 100000; i > 0; --i) {
348234732Smarc 		if (duart->statusB & RCV_RDY) {
348334732Smarc 			if (duart->dataB)
348434732Smarc 				;
348534642Smarc 			break;
348634642Smarc 		}
348730391Skarels 	}
348830391Skarels 	if (i == 0) {
348934732Smarc 		printf("qd[%d]: setup_input: timeout on 3rd byte of self test\n", unit);
349034642Smarc 		goto OUT;
349130391Skarels 	}
349230391Skarels 	for (i = 100000; i > 0; --i) {
349334732Smarc 		if (duart->statusB&RCV_RDY) {
349434732Smarc 			if (duart->dataB)
349534732Smarc 				;
349634642Smarc 			break;
349734642Smarc 		}
349830391Skarels 	}
349930391Skarels 	if (i == 0) {
350034732Smarc 		printf("qd[%d]: setup_input: timeout on 4th byte of self test\n", unit);
350134642Smarc 		goto OUT;
350230391Skarels 	}
350334642Smarc 	/*
350434732Smarc 	* flag pointing device type and set defaults
350534732Smarc 	*/
350634732Smarc 	for (i=100000; i>0; --i)
350734732Smarc 		;		/*XXX*/
350830391Skarels 
350930391Skarels 	if ((id_byte & 0x0F) != TABLET_ID) {
351034642Smarc 		qdflags[unit].pntr_id = MOUSE_ID;
351130391Skarels 
351234642Smarc 		for (i = 500; i > 0; --i) {
351334732Smarc 			if (duart->statusB&XMT_RDY) {
351434642Smarc 				duart->dataB = INC_STREAM_MODE;
351534642Smarc 				break;
351634642Smarc 			}
351730391Skarels 		}
351834642Smarc 	}
351934642Smarc 	else {
352034642Smarc 		qdflags[unit].pntr_id = TABLET_ID;
352130391Skarels 
352234642Smarc 		for (i = 500; i > 0; --i) {
352334732Smarc 			if (duart->statusB&XMT_RDY) {
352434642Smarc 				duart->dataB = T_STREAM;
352534642Smarc 				break;
352634642Smarc 			}
352730391Skarels 		}
352830391Skarels 	}
352930391Skarels OUT:
353030391Skarels 	duart->imask = qdflags[unit].duart_imask;
353130391Skarels 
353230391Skarels } /* setup_input */
353330391Skarels 
353434732Smarc /*
353534732Smarc  * delay for at least one display frame time
353634732Smarc  *
353734732Smarc  *	return: BAD means that we timed out without ever seeing the
353834732Smarc  *		      vertical sync status bit
353934732Smarc  *		GOOD otherwise
354034732Smarc  */
354130391Skarels wait_status(adder, mask)
354234642Smarc 	register struct adder *adder;
354334642Smarc 	register int mask;
354430391Skarels {
354534732Smarc 	register i;
354630391Skarels 
354734732Smarc 	for (i = 10000, adder->status = 0 ; i > 0  &&
354834732Smarc 	     !(adder->status&mask) ; --i)
354934642Smarc 		;
355030391Skarels 
355130391Skarels 	if (i == 0) {
355234732Smarc 		printf("wait_status: timeout polling for 0x%x in adder->status\n", mask);
355334642Smarc 		return(BAD);
355430391Skarels 	}
355530391Skarels 
355630391Skarels 	return(GOOD);
355730391Skarels 
355830391Skarels } /* wait_status */
355930391Skarels 
356034732Smarc /*
356134732Smarc  * write out onto the ID bus
356234732Smarc  */
356330391Skarels write_ID(adder, adrs, data)
356434642Smarc 	register struct adder *adder;
356534642Smarc 	register short adrs;
356634642Smarc 	register short data;
356730391Skarels {
356834732Smarc 	register i;
356930391Skarels 
357034732Smarc 	for (i = 100000, adder->status = 0 ;
357134732Smarc 	      i > 0  &&  !(adder->status&ADDRESS_COMPLETE) ; --i)
357234642Smarc 		;
357330391Skarels 
357430391Skarels 	if (i == 0)
357534732Smarc 		goto ERR;
357630391Skarels 
357734732Smarc 	for (i = 100000, adder->status = 0 ;
357834732Smarc 	      i > 0  &&  !(adder->status&TX_READY) ; --i)
357934642Smarc 		;
358030391Skarels 
358130391Skarels 	if (i > 0) {
358234642Smarc 		adder->id_data = data;
358334642Smarc 		adder->command = ID_LOAD | adrs;
358434732Smarc 		return ;
358530391Skarels 	}
358630391Skarels 
358730391Skarels ERR:
358834732Smarc 	printf("write_ID: timeout trying to write to VIPER\n");
358934732Smarc 	return ;
359030391Skarels 
359130391Skarels } /* write_ID */
359234511Smarc #endif
3593