xref: /csrg-svn/sys/vax/uba/qd.c (revision 34511)
1*34511Smarc /*
2*34511Smarc  * Copyright (c) 1982, 1986 Regents of the University of California.
3*34511Smarc  * All rights reserved.  The Berkeley software License Agreement
4*34511Smarc  * specifies the terms and conditions for redistribution.
5*34511Smarc  *
6*34511Smarc  * 	@(#)qd.c	1.3  Berkeley  05/26/88
7*34511Smarc  *
8*34511Smarc  * derived from: "@(#)qd.c	1.40	ULTRIX	10/2/86";
9*34511Smarc  */
1030391Skarels 
1130391Skarels /************************************************************************
12*34511Smarc *									*
13*34511Smarc *			Copyright (c) 1985, 1986 by			*
1430391Skarels *		Digital Equipment Corporation, Maynard, MA		*
1530391Skarels *			All rights reserved.				*
1630391Skarels *									*
1730391Skarels *   This software is furnished under a license and may be used and	*
1830391Skarels *   copied  only  in accordance with the terms of such license and	*
1930391Skarels *   with the  inclusion  of  the  above  copyright  notice.   This	*
2030391Skarels *   software  or  any  other copies thereof may not be provided or	*
2130391Skarels *   otherwise made available to any other person.  No title to and	*
2230391Skarels *   ownership of the software is hereby transferred.			*
2330391Skarels *									*
2430391Skarels *   The information in this software is subject to change  without	*
2530391Skarels *   notice  and should not be construed as a commitment by Digital	*
2630391Skarels *   Equipment Corporation.						*
2730391Skarels *									*
2830391Skarels *   Digital assumes no responsibility for the use  or  reliability	*
2930391Skarels *   of its software on equipment which is not supplied by Digital.	*
3030391Skarels *									*
3130391Skarels *************************************************************************/
3230391Skarels /*
33*34511Smarc  * qd.c - QDSS display driver
3430391Skarels  */
3530391Skarels 
36*34511Smarc #include "qd.h"
37*34511Smarc #if NQD > 0
3830391Skarels 
39*34511Smarc #include "../machine/pte.h"
40*34511Smarc #include "../machine/mtpr.h"
41*34511Smarc #include "../machine/cpu.h"
42*34511Smarc #include "param.h"
43*34511Smarc #include "conf.h"
44*34511Smarc #include "dir.h"
45*34511Smarc #include "user.h"
46*34511Smarc #include "qdioctl.h"
47*34511Smarc #include "tty.h"
48*34511Smarc #include "map.h"
49*34511Smarc #include "buf.h"
50*34511Smarc #include "vm.h"
51*34511Smarc #include "clist.h"
52*34511Smarc #include "file.h"
53*34511Smarc #include "uio.h"
54*34511Smarc #include "kernel.h"
55*34511Smarc #include "ubareg.h"
56*34511Smarc #include "ubavar.h"
57*34511Smarc #include "syslog.h"
58*34511Smarc #include "qduser.h"	/* definitions shared with client */
59*34511Smarc #include "qdreg.h"
6030391Skarels 
6132012Smarc /*
6232012Smarc * QDSS driver status flags for tracking operational state
6332012Smarc */
6432012Smarc 
6532012Smarc struct qdflags {
6632012Smarc 
6732012Smarc     u_int inuse;	    /* which minor dev's are in use now */
6832012Smarc     u_int config;	    /* I/O page register content */
6932012Smarc     u_int mapped;	    /* user mapping status word */
7032012Smarc     u_int kernel_loop;	    /* if kernel console is redirected */
7132012Smarc     u_int user_dma;	    /* DMA from user space in progress */
7232012Smarc     u_short pntr_id;	    /* type code of pointing device */
7332012Smarc     u_short duart_imask;    /* shadowing for duart intrpt mask reg */
7432012Smarc     u_short adder_ie;	    /* shadowing for adder intrpt enbl reg */
7532012Smarc     u_short curs_acc;	    /* cursor acceleration factor */
7632012Smarc     u_short curs_thr;	    /* cursor acceleration threshold level */
7732012Smarc     u_short tab_res;	    /* tablet resolution factor */
7832012Smarc     u_short selmask;	    /* mask for active qd select entries */
7932012Smarc };
8032012Smarc 
81*34511Smarc /* #define POSIXTTY (4.4BSD) */
82*34511Smarc 
8332012Smarc /* bit definitions for "inuse" entry  */
8432012Smarc #define CONS_DEV	0x01
8532012Smarc #define ALTCONS_DEV	0x02
8632012Smarc #define GRAPHIC_DEV	0x04
8732012Smarc 
8832012Smarc /* bit definitions for 'mapped' member of flag structure */
8932012Smarc #define MAPDEV		0x01		/* hardware is mapped */
9032012Smarc #define MAPDMA		0x02		/* DMA buffer mapped */
9132012Smarc #define MAPEQ		0x04		/* event queue buffer mapped */
9232012Smarc #define MAPSCR		0x08		/* scroll param area mapped */
9332012Smarc #define MAPCOLOR	0x10		/* color map writing buffer mapped */
9432012Smarc 
9532012Smarc /* bit definitions for 'selmask' member of qdflag structure */
9632012Smarc 
9732012Smarc #define SEL_READ	0x01		/* read select is active */
9832012Smarc #define SEL_WRITE	0x02		/* write select is active */
9932012Smarc 
10032012Smarc /*
10132012Smarc * constants used in shared memory operations
10232012Smarc */
10332012Smarc 
10432012Smarc #define EVENT_BUFSIZE  1024	/* # of bytes per device's event buffer */
10532012Smarc #define MAXEVENTS  ( (EVENT_BUFSIZE - sizeof(struct qdinput))	 \
10632012Smarc 		     / sizeof(struct _vs_event) )
10732012Smarc #define DMA_BUFSIZ	(1024 * 3)
10832012Smarc #define COLOR_BUFSIZ  ((sizeof(struct color_buf) + 512) & ~0x01FF)
10932012Smarc 
11032012Smarc /*
11132012Smarc * reference to an array of "uba_device" structures built by the auto
11232012Smarc * configuration program.  The uba_device structure decribes the device
11332012Smarc * sufficiently for the driver to talk to it.  The auto configuration code
11432012Smarc * fills in the uba_device structures (located in ioconf.c) from user
11532012Smarc * maintained info.
11632012Smarc */
11732012Smarc 
11832012Smarc struct uba_device *qdinfo[NQD];  /* array of pntrs to each QDSS's */
11932012Smarc 				 /* uba structures  */
12032012Smarc struct tty qd_tty[NQD*4];	/* teletype structures for each.. */
12132012Smarc 				/* ..possible minor device */
12232012Smarc 
12332012Smarc struct qd_softc qd_softc[NQD];
12432012Smarc 
12532012Smarc /*
126*34511Smarc  * static storage used by multiple functions in this code
127*34511Smarc  */
12832012Smarc int Qbus_unmap[NQD];		/* Qbus mapper release code */
12932012Smarc struct qdflags qdflags[NQD];	/* QDSS device status flags */
13032012Smarc struct qdmap qdmap[NQD];	/* QDSS register map structure */
13132012Smarc caddr_t qdbase[NQD];		/* base address of each QDSS unit */
13232012Smarc struct buf qdbuf[NQD];		/* buf structs used by strategy */
13332012Smarc char one_only[NQD];		/* lock for single process access */
13432012Smarc 
13532012Smarc /*
13632012Smarc * The array "event_shared[]" is made up of a number of event queue buffers
13732012Smarc * equal to the number of QDSS's configured into the running kernel (NQD).
13832012Smarc * Each event queue buffer begins with an event queue header (struct qdinput)
13932012Smarc * followed by a group of event queue entries (struct _vs_event).  The array
14032012Smarc * "*eq_header[]" is an array of pointers to the start of each event queue
14132012Smarc * buffer in "event_shared[]".
14232012Smarc */
14332012Smarc 
14432012Smarc #define EQSIZE ((EVENT_BUFSIZE * NQD) + 512)
14532012Smarc 
14632012Smarc char event_shared[EQSIZE];	    /* reserve space for event bufs */
14732012Smarc struct qdinput *eq_header[NQD];     /* event queue header pntrs */
14832012Smarc 
14932012Smarc /*
15032012Smarc * This allocation method reserves enough memory pages for NQD shared DMA I/O
15132012Smarc * buffers.  Each buffer must consume an integral number of memory pages to
15232012Smarc * guarantee that a following buffer will begin on a page boundary.  Also,
15332012Smarc * enough space is allocated so that the FIRST I/O buffer can start at the
15432012Smarc * 1st page boundary after "&DMA_shared".  Page boundaries are used so that
15532012Smarc * memory protections can be turned on/off for individual buffers.
15632012Smarc */
15732012Smarc 
15832012Smarc #define IOBUFSIZE  ((DMA_BUFSIZ * NQD) + 512)
15932012Smarc 
16032012Smarc char DMA_shared[IOBUFSIZE];	    /* reserve I/O buffer space */
16132012Smarc struct DMAreq_header *DMAheader[NQD];  /* DMA buffer header pntrs */
16232012Smarc 
16332012Smarc /*
16432012Smarc * The driver assists a client in scroll operations by loading dragon
16532012Smarc * registers from an interrupt service routine.	The loading is done using
16632012Smarc * parameters found in memory shrade between the driver and it's client.
16732012Smarc * The scroll parameter structures are ALL loacted in the same memory page
16832012Smarc * for reasons of memory economy.
16932012Smarc */
17032012Smarc 
17132012Smarc char scroll_shared[2 * 512];	/* reserve space for scroll structs */
17232012Smarc struct scroll *scroll[NQD];	/* pointers to scroll structures */
17332012Smarc 
17432012Smarc /*
17532012Smarc * the driver is programmable to provide the user with color map write
17632012Smarc * services at VSYNC interrupt time.  At interrupt time the driver loads
17732012Smarc * the color map with any user-requested load data found in shared memory
17832012Smarc */
17932012Smarc 
18032012Smarc #define COLOR_SHARED  ((COLOR_BUFSIZ * NQD) + 512)
18132012Smarc 
182*34511Smarc char color_shared[COLOR_SHARED];      /* color bufs */
18332012Smarc struct color_buf *color_buf[NQD];     /* pointers to color bufs */
18432012Smarc 
18532012Smarc /*
18632012Smarc * mouse input event structures
18732012Smarc */
18832012Smarc 
18932012Smarc struct mouse_report last_rep[NQD];
19032012Smarc struct mouse_report current_rep[NQD];
19132012Smarc 
19232012Smarc /*
19332012Smarc * input event "select" use
19432012Smarc */
19532012Smarc 
19632012Smarc struct proc *rsel[NQD]; 	/* process waiting for select */
19732012Smarc 
19832012Smarc /*
19932012Smarc * console cursor structure
20032012Smarc */
20132012Smarc 
20232012Smarc struct _vs_cursor cursor[NQD];
20332012Smarc 
20432012Smarc 
20532012Smarc 
20632012Smarc int nNQD = NQD;
20732012Smarc 
20832012Smarc int DMAbuf_size = DMA_BUFSIZ;
20932012Smarc 
21032012Smarc 
21132012Smarc /*
21232012Smarc  * macro to get system time.  Used to time stamp event queue entries
21332012Smarc  */
21432012Smarc 
21530391Skarels #define TOY ((time.tv_sec * 100) + (time.tv_usec / 10000))
21630391Skarels 
21732012Smarc /*
21830391Skarels * the "ioconf.c" program, built and used by auto config, externally refers
21932012Smarc * to definitions below.
22032012Smarc */
22130391Skarels 
22232012Smarc int qdprobe();
22332012Smarc int qdattach();
22432012Smarc int qddint();			/* DMA gate array intrpt service */
22532012Smarc int qdaint();			/* Dragon ADDER intrpt service */
22632012Smarc int qdiint();
22730391Skarels 
22832012Smarc u_short qdstd[] = { 0 };
22930391Skarels 
23032012Smarc struct uba_driver qddriver = {	/* externally referenced: ioconf.c */
23130391Skarels 
23232012Smarc     qdprobe,			/* device probe entry */
23332012Smarc     0,				/* no slave device */
23432012Smarc     qdattach,			/* device attach entry */
23532012Smarc     0,				/* no "fill csr/ba to start" */
23632012Smarc     qdstd,			/* device addresses */
23732012Smarc     "qd",			/* device name string */
23832012Smarc     qdinfo			/* ptr to QDSS's uba_device struct */
23932012Smarc };
24030391Skarels 
24132012Smarc extern	char qvmem[][128*NBPG];
24232012Smarc extern	struct pte QVmap[][128];
24332012Smarc 
24432012Smarc /*
24532012Smarc  * v_putc is used to redirect the console cnputc to the virtual console
24632012Smarc  * vputc.  consops is used to direct the console device to the qvss console.
24732012Smarc  */
24832012Smarc extern (*v_putc)();
24932012Smarc extern struct cdevsw *consops;
25032012Smarc 
25132012Smarc /*
25230391Skarels * general defines */
25330391Skarels 
254*34511Smarc #define QDPRIOR (PZERO-1)
25530391Skarels 
25630391Skarels #define FALSE	0
25730391Skarels #define TRUE	~FALSE
25830391Skarels 
25930391Skarels #define BAD	-1
26030391Skarels #define GOOD	0
26130391Skarels 
26232012Smarc /*
26332012Smarc  * Macro to create a system virtual page number from system virtual adrs.
26432012Smarc  */
26530391Skarels 
26632012Smarc #define VTOP(x)  (((int)x & ~0xC0000000) >> PGSHIFT)
26730391Skarels 
26832012Smarc /*
26932012Smarc  * QDSS register address offsets from start of QDSS address space
27032012Smarc  */
27130391Skarels 
27230391Skarels #define QDSIZE	 (52 * 1024)	/* size of entire QDSS foot print */
27330391Skarels 
27430391Skarels #define TMPSIZE  (16 * 1024)	/* template RAM is 8k SHORT WORDS */
27530391Skarels #define TMPSTART 0x8000 	/* offset of template RAM from base adrs */
27630391Skarels 
27730391Skarels #define REGSIZE  (5 * 512)	/* regs touch 2.5k (5 pages) of addr space */
27830391Skarels #define REGSTART 0xC000 	/* offset of reg pages from base adrs */
27930391Skarels 
28030391Skarels #define ADDER	(REGSTART+0x000)
28130391Skarels #define DGA	(REGSTART+0x200)
28230391Skarels #define DUART	(REGSTART+0x400)
28330391Skarels #define MEMCSR	(REGSTART+0x800)
28430391Skarels 
28530391Skarels #define CLRSIZE  (3 * 512)		/* color map size */
28630391Skarels #define CLRSTART (REGSTART+0xA00)	/* color map start offset from base */
28730391Skarels 					/*  0x0C00 really */
28830391Skarels #define RED	(CLRSTART+0x000)
28930391Skarels #define BLUE	(CLRSTART+0x200)
29030391Skarels #define GREEN	(CLRSTART+0x400)
29130391Skarels 
29232012Smarc /*
29332012Smarc  * Values used in mapping QDSS hardware into the Q memory space.
29432012Smarc  */
29530391Skarels 
29630391Skarels #define CHUNK	  (64 * 1024)
29732012Smarc #define QMEMSIZE  (1024 * 1024 * 4)
29830391Skarels 
29932012Smarc /*
30030391Skarels * QDSS minor device numbers.  The *real* minor device numbers are in
30130391Skarels * the bottom two bits of the major/minor device spec.  Bits 2 and up are
30232012Smarc * used to specify the QDSS device number (ie: which one?)
30332012Smarc */
30430391Skarels 
30532012Smarc #define QDSSMAJOR	41		/* QDSS major device number */
30630391Skarels 
30730391Skarels #define CONS		0
30830391Skarels #define ALTCONS 	1
30930391Skarels #define GRAPHIC 	2
31030391Skarels 
31132012Smarc /*
31232012Smarc  * console cursor bitmap (block cursor type)
31332012Smarc  */
31430391Skarels 
31530391Skarels 	short cons_cursor[32] = {      /* white block cursor */
31630391Skarels 
31730391Skarels  /* A */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
31830391Skarels 	 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
31930391Skarels  /* B */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
32030391Skarels 	 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF
32130391Skarels 
32230391Skarels 	};
32330391Skarels 
32432012Smarc /*
32532012Smarc  * constants used in font operations
32632012Smarc  */
32730391Skarels 
32830391Skarels #define CHARS		95			/* # of chars in the font */
32930391Skarels #define CHAR_HEIGHT	15			/* char height in pixels */
33030391Skarels #define CHAR_WIDTH	8			/* char width in pixels*/
33130391Skarels #define FONT_WIDTH	(CHAR_WIDTH * CHARS)	/* font width in pixels */
33230391Skarels #define ROWS		CHAR_HEIGHT
33330391Skarels 
33430391Skarels 
33530391Skarels #define FONT_X		0			/* font's off screen adrs */
33630391Skarels #define FONT_Y		(2048 - CHAR_HEIGHT)
33730391Skarels /*
33830391Skarels #define FONT_Y		200
33930391Skarels */
34030391Skarels 
34132012Smarc extern char q_font[];		/* reference font object code */
34230391Skarels 
34332012Smarc extern	char q_key[];		/* reference key xlation tables */
34432012Smarc extern	char q_shift_key[];
34532012Smarc extern	char *q_special[];
34630391Skarels 
34732012Smarc /*
34832012Smarc  * definitions for cursor acceleration reporting
34932012Smarc  */
35030391Skarels 
35130391Skarels #define ACC_OFF 	0x01		/* acceleration is inactive */
35230391Skarels 
35332012Smarc int qdputc();		/* used to direct kernel console output *
35432012Smarc int qdstart();		/* used to direct /dev/console output *
35530391Skarels 
35632012Smarc /*
35732012Smarc  * LK-201 state storage for input console keyboard conversion to ASCII
35832012Smarc  */
35930391Skarels 
36032012Smarc struct q_keyboard {
36132012Smarc     int shift;			/* state variables	*/
36232012Smarc     int cntrl;
36332012Smarc     int lock;
36432012Smarc     int lastcode;		/* last keycode typed	*/
36532012Smarc     unsigned kup[8];		/* bits for each keycode*/
36632012Smarc     unsigned dkeys[8];		/* down/up mode keys	*/
36732012Smarc     char last;			/* last character	*/
368*34511Smarc } q_keyboard;
36930391Skarels 
37030391Skarels 
37130391Skarels /*********************************************************************
37230391Skarels *
373*34511Smarc *	qdcons_init - init QDSS as console (BEFORE probe routine)
37430391Skarels *
37530391Skarels *********************************************************************/
37630391Skarels 
37730391Skarels qdcons_init()
37830391Skarels {
37930391Skarels 	register u_int unit;
38030391Skarels 
38132012Smarc 	struct percpu *pcpu;		/* pointer to percpu structure */
38232012Smarc 	register struct qbus *qb;
38330391Skarels 	int *ptep;			/* page table entry pointer */
38430391Skarels 	caddr_t phys_adr;		/* physical QDSS base adrs */
38530391Skarels 	u_int mapix;			/* index into QMEMmap[] array */
38630391Skarels 
38730391Skarels 	u_short *qdaddr;		/* address of QDSS IO page CSR */
38830391Skarels 	u_short *devptr;		/* vitual device space */
38932012Smarc 	extern	cnputc();		/* standard serial console putc */
39030391Skarels 
39130391Skarels #define QDSSCSR 0x1F00
39230391Skarels 
39332012Smarc 	/*
39432012Smarc 	 * if console already configured, dont do again.
39532012Smarc 	 */
39632012Smarc 	if (v_putc != cnputc)
39732012Smarc 		return;
39832012Smarc 
39930391Skarels 	unit = 0;
40030391Skarels 
40132012Smarc 	/*
40232012Smarc 	 * find the cpusw entry that matches this machine.
40332012Smarc 	 */
40430391Skarels 
40532012Smarc 	for (pcpu = percpu; pcpu && pcpu->pc_cputype != cpu; pcpu++)
40632012Smarc 		;
40732012Smarc 	if (pcpu == NULL)
40832012Smarc 		return;
40930391Skarels 
41030391Skarels 
41132012Smarc 	/*
41232012Smarc 	 * Map device registers - the last 8K of umem.
41332012Smarc 	 */
41432012Smarc 	qb = (struct qbus *)pcpu->pc_io->io_details;
41532012Smarc 	ioaccess(qb->qb_iopage, UMEMmap[0] + qb->qb_memsize,
41632012Smarc 		UBAIOPAGES * NBPG);
41730391Skarels 
41832012Smarc 	devptr = (u_short *)((char *)umem[0]+(qb->qb_memsize * NBPG));
41930391Skarels 	qdaddr = (u_short *)((u_int)devptr + ubdevreg(QDSSCSR));
42032012Smarc 	if (badaddr(qdaddr, sizeof(short)))  {
42132012Smarc 		log(LOG_ERR, "Can't find qdss (badaddr)\n"); /* debug */
42230391Skarels 		return(0);
42332012Smarc 	}
42432012Smarc 	/*
42532012Smarc 	 * Map q-bus memory used by qdss. (separate map)
42632012Smarc 	 */
42732012Smarc 	mapix = QMEMSIZE - (CHUNK * (unit + 1));
42832012Smarc 	phys_adr = qb->qb_maddr + mapix;
42932012Smarc 	ioaccess(phys_adr, QVmap[0], (CHUNK*NQD));
43030391Skarels 
43132012Smarc 	/*
43232012Smarc 	 * tell QDSS which Q memory address base to decode
43332012Smarc 	 */
43430391Skarels 
43532012Smarc 	/*
43632012Smarc 	 * shifted right 16 bits - its in 64K units
43732012Smarc 	 */
43832012Smarc 	*qdaddr = (u_short)((int)mapix >> 16);
43930391Skarels 	qdflags[unit].config = *(u_short *)qdaddr;
44030391Skarels 
44132012Smarc 	/*
44232012Smarc 	 * load qdmap struct with the virtual addresses of the QDSS elements
44332012Smarc 	 */
44430391Skarels 
44532012Smarc 	qdbase[unit] = (caddr_t) qvmem[0];
44630391Skarels 
44730391Skarels 	qdmap[unit].template = qdbase[unit] + TMPSTART;
44830391Skarels 	qdmap[unit].adder = qdbase[unit] + ADDER;
44930391Skarels 	qdmap[unit].dga = qdbase[unit] + DGA;
45030391Skarels 	qdmap[unit].duart = qdbase[unit] + DUART;
45130391Skarels 	qdmap[unit].memcsr = qdbase[unit] + MEMCSR;
45230391Skarels 	qdmap[unit].red = qdbase[unit] + RED;
45330391Skarels 	qdmap[unit].blue = qdbase[unit] + BLUE;
45430391Skarels 	qdmap[unit].green = qdbase[unit] + GREEN;
45530391Skarels 
45630391Skarels 	qdflags[unit].duart_imask = 0;	/* init shadow variables */
45730391Skarels 
45832012Smarc 	/*
45932012Smarc 	 * init the QDSS
46032012Smarc 	 */
46130391Skarels 
46232012Smarc 	/***
46332012Smarc 	printf("qdbase[0] = %x, qdmap[0].memcsr = %x\n",
46432012Smarc 		(char *)qdbase[0], qdmap[0].memcsr);
46532012Smarc 	***/
46632012Smarc 
46730391Skarels 	*(short *)qdmap[unit].memcsr |= SYNC_ON; /* once only: turn on sync */
46830391Skarels 
46930391Skarels 	cursor[unit].x = 0;
47030391Skarels 	cursor[unit].y = 0;
47130391Skarels 	init_shared(unit);		/* init shared memory */
47230391Skarels 	setup_dragon(unit);		/* init the ADDER/VIPER stuff */
47330391Skarels 	clear_qd_screen(unit);		/* clear the screen */
47430391Skarels 	ldfont(unit);			/* load the console font */
47530391Skarels 	ldcursor(unit, cons_cursor);	/* load default cursor map */
47630391Skarels 	setup_input(unit);		/* init the DUART */
47730391Skarels 
47832012Smarc 	v_putc = qdputc;
47932012Smarc 	consops = &cdevsw[QDSSMAJOR];
48030391Skarels 
48130391Skarels 	return(1);
48230391Skarels 
48330391Skarels } /* qdcons_init */
48430391Skarels 
48530391Skarels /*********************************************************************
48630391Skarels *
48730391Skarels *	qdprobe()... configure QDSS into Q memory and make it intrpt
48830391Skarels *
48930391Skarels **********************************************************************
49030391Skarels *
49130391Skarels *  calling convention:
49230391Skarels *			qdprobe(reg, ctlr);
49330391Skarels *			caddr_t reg;
49430391Skarels *			int ctlr;
49530391Skarels *
49630391Skarels *	where: reg - a character pointer to the QDSS I/O page register
49730391Skarels *	       ctlr - controller number (?)
49830391Skarels *
49930391Skarels *  side effects: QDSS gets mapped into Qbus memory space at the first
50030391Skarels *		 vacant 64kb boundary counting back from the top of
50130391Skarels *		 Qbus memory space (qmem+4mb)
50230391Skarels *
50330391Skarels *  return: QDSS bus request level and vector address returned in
50430391Skarels *	   registers by UNIX convention.
50530391Skarels *
50630391Skarels *****************/
50730391Skarels 
50830391Skarels qdprobe(reg)
50930391Skarels caddr_t reg;
51030391Skarels {
51132012Smarc 	register int br, cvec; 	/* value-result */
51230391Skarels 
51330391Skarels 	register int unit;
51430391Skarels 
51530391Skarels 	struct dga *dga;		/* pointer to gate array structure */
51630391Skarels 	struct cpusw *cpup;		/* pointer to the cpusw structure */
51730391Skarels 
51830391Skarels 	int *ptep;			/* page table entry pointer */
51930391Skarels 	int vector;
52030391Skarels 
52130391Skarels 	caddr_t phys_adr;		/* physical QDSS base adrs */
52230391Skarels 	u_int mapix;
52330391Skarels 
52432012Smarc #ifdef lint
52532012Smarc 	br = 0; cvec = br; br = cvec;
52632012Smarc #endif
52730391Skarels 
52832012Smarc 	/*
52932012Smarc 	* calculate board unit number from I/O page register address
53032012Smarc 	*/
53132012Smarc 
53230391Skarels 	unit = (int) (((int)reg >> 1) & 0x0007);
53330391Skarels 
53432012Smarc /*
53530391Skarels * QDSS regs must be mapped to Qbus memory space at a 64kb physical boundary.
53630391Skarels * The Qbus memory space is mapped into the system memory space at config
53730391Skarels * time.  After config runs, "qmem[0]" (ubavar.h) holds the system virtual adrs
53830391Skarels * of the start of Qbus memory.	The Qbus memory page table is found via
53930391Skarels * an array of pte ptrs called "QMEMmap[]" (ubavar.h) which is also loaded at
54030391Skarels * config time.	These are the variables used below to find a vacant 64kb
54130391Skarels * boundary in Qbus memory, and load it's corresponding physical adrs into
54232012Smarc * the QDSS's I/O page CSR.
54332012Smarc */
54430391Skarels 
54530391Skarels 	/* if this QDSS is NOT the console, then do init here.. */
54630391Skarels 
547*34511Smarc 	/****** XXX - REMOVED (can't test) - STILL NEED TO DO FOR NQD > 1 ***/
54832012Smarc #ifdef notdef
54930391Skarels 	if (v_consputc != qdputc  ||  unit != 0) {
55030391Skarels 
55132012Smarc 	    /*
55232012Smarc 	     * read QDSS config info
55332012Smarc 	     */
55430391Skarels 	    qdflags[unit].config = *(u_short *)reg;
55530391Skarels 
55632012Smarc 	    /*
55732012Smarc 	     * find an empty 64kb adrs boundary
55832012Smarc 	     */
55930391Skarels 	    qdbase[unit] = (caddr_t) (qmem[0] + QMEMSIZE - CHUNK);
56030391Skarels 
56132012Smarc 	    /*
56232012Smarc 	     * find the cpusw entry that matches this machine.
56332012Smarc 	     */
56430391Skarels 	    cpup = &cpusw[cpu];
56530391Skarels 	    while ( !(BADADDR(qdbase[unit], sizeof(short))) )
56630391Skarels 		qdbase[unit] -= CHUNK;
56730391Skarels 
56832012Smarc 	    /*
56932012Smarc 	     * tell QDSS which Q memory address base to decode
57032012Smarc 	     */
57130391Skarels 	    mapix = (int) (VTOP(qdbase[unit]) - VTOP(qmem[0]));
57230391Skarels 	    ptep = (int *) QMEMmap[0] + mapix;
57330391Skarels 	    phys_adr = (caddr_t) (((int)*ptep & 0x001FFFFF) << PGSHIFT);
57430391Skarels 	    *(u_short *)reg = (u_short) ((int)phys_adr >> 16);
57530391Skarels 
57632012Smarc 	    /*
57732012Smarc 	     * load QDSS adrs map with system addresses of device regs
57832012Smarc 	     */
57930391Skarels 	    qdmap[unit].template = qdbase[unit] + TMPSTART;
58030391Skarels 	    qdmap[unit].adder = qdbase[unit] + ADDER;
58130391Skarels 	    qdmap[unit].dga = qdbase[unit] + DGA;
58230391Skarels 	    qdmap[unit].duart = qdbase[unit] + DUART;
58330391Skarels 	    qdmap[unit].memcsr = qdbase[unit] + MEMCSR;
58430391Skarels 	    qdmap[unit].red = qdbase[unit] + RED;
58530391Skarels 	    qdmap[unit].blue = qdbase[unit] + BLUE;
58630391Skarels 	    qdmap[unit].green = qdbase[unit] + GREEN;
58730391Skarels 
58830391Skarels 	    /* device init */
58930391Skarels 
59030391Skarels 	    cursor[unit].x = 0;
59130391Skarels 	    cursor[unit].y = 0;
59230391Skarels 	    init_shared(unit);		/* init shared memory */
59330391Skarels 	    setup_dragon(unit); 	/* init the ADDER/VIPER stuff */
59430391Skarels 	    ldcursor(unit, cons_cursor);	/* load default cursor map */
59530391Skarels 	    setup_input(unit);		/* init the DUART */
59630391Skarels 	    clear_qd_screen(unit);
59730391Skarels 	    ldfont(unit);			/* load the console font */
59830391Skarels 
59930391Skarels 	    /* once only: turn on sync */
60030391Skarels 
60130391Skarels 	    *(short *)qdmap[unit].memcsr |= SYNC_ON;
60230391Skarels 	}
603*34511Smarc #endif /* notdef */
60430391Skarels 
60532012Smarc /*
60632012Smarc  * the QDSS interrupts at HEX vectors xx0 (DMA) xx4 (ADDER) and xx8 (DUART).
60732012Smarc  * Therefore, we take three vectors from the vector pool, and then continue
60832012Smarc  * to take them until we get a xx0 HEX vector.  The pool provides vectors
60932012Smarc  * in contiguous decending order.
61032012Smarc  */
61130391Skarels 
61230391Skarels 	vector = (uba_hd[0].uh_lastiv -= 4*3);	/* take three vectors */
61330391Skarels 
61430391Skarels 	while (vector & 0x0F) { 		   /* if lo nibble != 0.. */
61530391Skarels 	    vector = (uba_hd[0].uh_lastiv -= 4);  /* ..take another vector */
61630391Skarels 	}
61730391Skarels 
61832012Smarc 	/*
61932012Smarc 	 * setup DGA to do a DMA interrupt (transfer count = 0)
62032012Smarc 	 */
62130391Skarels 
62230391Skarels 	dga = (struct dga *) qdmap[unit].dga;
62330391Skarels 
62430391Skarels 	dga->csr = (short) HALT;	      /* disable everything */
62530391Skarels 	dga->ivr = (short) vector;	      /* load intrpt base vector */
62630391Skarels 	dga->bytcnt_lo = (short) 0;	      /* DMA xfer count = 0 */
62730391Skarels 	dga->bytcnt_hi = (short) 0;
62830391Skarels 
62930391Skarels 	/* turn on DMA interrupts */
63030391Skarels 
63130391Skarels 	dga->csr &= ~SET_DONE_FIFO;
63230391Skarels 	dga->csr |= DMA_IE | DL_ENB;
63330391Skarels 
63430391Skarels 	DELAY(20000);			/* wait for the intrpt */
63530391Skarels 
63630391Skarels 	dga->csr = HALT;		/* stop the wheels */
63730391Skarels 
63830391Skarels 	if (cvec != vector)		/* if vector != base vector.. */
63930391Skarels 	    return(0);			/* ..return = 'no device' */
64030391Skarels 
64130391Skarels 	return(sizeof(short));	    /* return size of QDSS I/O page reg */
64230391Skarels 
64330391Skarels } /* qdprobe */
64430391Skarels 
64530391Skarels /*****************************************************************
64630391Skarels *
647*34511Smarc *	qdattach - one-time initialization
64830391Skarels *
64930391Skarels ******************************************************************
65030391Skarels *
65130391Skarels *  calling convention:
65230391Skarels *			qdattach(ui);
65330391Skarels *			struct uba_device *ui;
65430391Skarels *
65530391Skarels *		where: ui - pointer to the QDSS's uba_device structure
65630391Skarels *
65730391Skarels *  side effects: none
65830391Skarels *	 return: none
65930391Skarels *
66030391Skarels *************************/
66130391Skarels 
66230391Skarels qdattach(ui)
66330391Skarels struct uba_device *ui;
66430391Skarels {
66530391Skarels 	register u_int unit;		/* QDSS module # for this call */
66630391Skarels 
66730391Skarels 	unit = ui->ui_unit;		/* get QDSS number */
66830391Skarels 
669*34511Smarc 	/*
670*34511Smarc 	 * init "qdflags[]" for this QDSS
671*34511Smarc 	 */
67230391Skarels 
67330391Skarels 	qdflags[unit].inuse = 0;	/* init inuse variable EARLY! */
67430391Skarels 	qdflags[unit].mapped = 0;
67530391Skarels 	qdflags[unit].kernel_loop = 0;
67630391Skarels 	qdflags[unit].user_dma = 0;
67730391Skarels 	qdflags[unit].curs_acc = ACC_OFF;
67830391Skarels 	qdflags[unit].curs_thr = 128;
67930391Skarels 	qdflags[unit].tab_res = 2;	/* default tablet resolution factor */
68030391Skarels 	qdflags[unit].duart_imask = 0;	/* init shadow variables */
68130391Skarels 	qdflags[unit].adder_ie = 0;
68230391Skarels 
683*34511Smarc 	/*
684*34511Smarc 	* init structures used in kbd/mouse interrupt service.	This code must
685*34511Smarc 	* come after the "init_shared()" routine has run since that routine
686*34511Smarc 	* inits the eq_header[unit] structure used here.
687*34511Smarc 	*/
68830391Skarels 
68932012Smarc 	/*
69032012Smarc 	* init the "latest mouse report" structure
69132012Smarc 	*/
69230391Skarels 
69330391Skarels 	last_rep[unit].state = 0;
69430391Skarels 	last_rep[unit].dx = 0;
69530391Skarels 	last_rep[unit].dy = 0;
69630391Skarels 	last_rep[unit].bytcnt = 0;
69730391Skarels 
698*34511Smarc 	/*
699*34511Smarc 	* init the event queue (except mouse position)
700*34511Smarc 	*/
70130391Skarels 
70230391Skarels 	eq_header[unit]->header.events = (struct _vs_event *)
70330391Skarels 					  ((int)eq_header[unit]
70430391Skarels 					   + sizeof(struct qdinput));
70530391Skarels 
70630391Skarels 	eq_header[unit]->header.size = MAXEVENTS;
70730391Skarels 	eq_header[unit]->header.head = 0;
70830391Skarels 	eq_header[unit]->header.tail = 0;
70930391Skarels 
71032012Smarc 	/*
71132012Smarc 	* init single process access lock switch
71232012Smarc 	*/
71330391Skarels 
71430391Skarels 	one_only[unit] = 0;
71530391Skarels 
71630391Skarels } /* qdattach */
71730391Skarels 
71830391Skarels /***************************************************************
71930391Skarels *
720*34511Smarc *	qdopen - open a minor device
72130391Skarels *
72230391Skarels ****************************************************************
72330391Skarels *
72430391Skarels *  calling convention: qdopen(dev, flag);
72530391Skarels *		       dev_t dev;
72630391Skarels *		       int flag;
72730391Skarels *
72830391Skarels *  side effects: none
72930391Skarels *
73030391Skarels *********************/
73130391Skarels 
73230391Skarels qdopen(dev, flag)
73330391Skarels dev_t dev;
73430391Skarels int flag;
73530391Skarels {
73630391Skarels 	register struct uba_device *ui; /* ptr to uba structures */
73730391Skarels 	register struct dga *dga;	/* ptr to gate array struct */
73830391Skarels 	register struct tty *tp;
73932012Smarc 	int qdstart();
74030391Skarels 
74130391Skarels 	struct adder *adder;
74230391Skarels 	struct duart *duart;
74330391Skarels 
74430391Skarels 	u_int unit;
74530391Skarels 	u_int minor_dev;
74630391Skarels 	int s;
74730391Skarels 
74830391Skarels 	minor_dev = minor(dev); /* get QDSS minor device number */
74930391Skarels 	unit = minor_dev >> 2;
75030391Skarels 
75132012Smarc 	/* check for illegal conditions	*/
75230391Skarels 
75330391Skarels 	ui = qdinfo[unit];		/* get ptr to QDSS device struct */
75430391Skarels 
75530391Skarels 	if (ui == 0  || ui->ui_alive == 0)
75630391Skarels 	    return(ENXIO);		/* no such device or address */
75730391Skarels 
75832012Smarc 	/* init stuff */
75930391Skarels 
76030391Skarels 	adder = (struct adder *) qdmap[unit].adder;
76130391Skarels 	duart = (struct duart *) qdmap[unit].duart;
76230391Skarels 	dga = (struct dga *) qdmap[unit].dga;
76330391Skarels 
76432012Smarc 	/* if this is the graphic device... */
76530391Skarels 
76630391Skarels 	if ((minor_dev & 0x03) == 2) {
76730391Skarels 
76830391Skarels 	    if (one_only[unit] != 0)
76930391Skarels 		return(EBUSY);
77030391Skarels 	    else
77130391Skarels 		one_only[unit] = 1;
77230391Skarels 
77330391Skarels 	    qdflags[unit].inuse |= GRAPHIC_DEV;  /* graphics dev is open */
77430391Skarels 
77530391Skarels 	    /* enble kbd & mouse intrpts in DUART mask reg */
77630391Skarels 
77730391Skarels 	    qdflags[unit].duart_imask |= 0x22;
77830391Skarels 	    duart->imask = qdflags[unit].duart_imask;
77930391Skarels 
78032012Smarc 	/*
78132012Smarc 	 * if the open call is to the console or the alternate console...
78232012Smarc 	 */
78332012Smarc 	} else {
78430391Skarels 
78530391Skarels 	    qdflags[unit].inuse |= CONS_DEV;  /* mark console as open */
78630391Skarels 	    dga->csr |= CURS_ENB;
78730391Skarels 
78830391Skarels 	    qdflags[unit].duart_imask |= 0x02;
78930391Skarels 	    duart->imask = qdflags[unit].duart_imask;
79030391Skarels 
79130391Skarels 	    /*-------------------------------
79230391Skarels 	    * some setup for tty handling */
79330391Skarels 
79430391Skarels 	    tp = &qd_tty[minor_dev];
79530391Skarels 
79630391Skarels 	    tp->t_addr = ui->ui_addr;
79730391Skarels 	    tp->t_oproc = qdstart;
79830391Skarels 
79930391Skarels 	    if ((tp->t_state & TS_ISOPEN) == 0) {
80030391Skarels 
80130391Skarels 		ttychars(tp);
80230391Skarels 		tp->t_state = TS_ISOPEN | TS_CARR_ON;
80330391Skarels 		tp->t_ispeed = B9600;
80430391Skarels 		tp->t_ospeed = B9600;
80530391Skarels 
80632012Smarc 		if( (minor_dev & 0x03) == 0 ) {
80730391Skarels 		    tp->t_flags = XTABS|EVENP|ECHO|CRMOD;
808*34511Smarc #ifdef POSIXTTY
809*34511Smarc 		    tp->t_iflag = TTYDEF_IFLAG;
810*34511Smarc 		    tp->t_oflag = TTYDEF_OFLAG;
811*34511Smarc 		    tp->t_lflag = TTYDEF_LFLAG;
812*34511Smarc 		    tp->t_cflag = TTYDEF_CFLAG;
813*34511Smarc #endif
81432012Smarc 		}
81532012Smarc 		else {
81630391Skarels 		    tp->t_flags = RAW;
81732012Smarc 		}
81830391Skarels 	    }
81930391Skarels 
82030391Skarels 	    /*----------------------------------------
82130391Skarels 	    * enable intrpts, open line discipline */
82230391Skarels 
82330391Skarels 	    dga->csr |= GLOBAL_IE;	/* turn on the interrupts */
82430391Skarels 	    return ((*linesw[tp->t_line].l_open)(dev, tp));
82530391Skarels 	}
82630391Skarels 
82730391Skarels 	dga->csr |= GLOBAL_IE;	/* turn on the interrupts */
82830391Skarels 	return(0);
82930391Skarels 
83030391Skarels } /* qdopen */
83130391Skarels 
83230391Skarels /***************************************************************
83330391Skarels *
834*34511Smarc *	qdclose - clean up on the way out
83530391Skarels *
83630391Skarels ****************************************************************
83730391Skarels *
83830391Skarels *  calling convention: qdclose();
83930391Skarels *
84030391Skarels *  side effects: none
84130391Skarels *
84230391Skarels *  return: none
84330391Skarels *
84430391Skarels *********************/
84530391Skarels 
84630391Skarels qdclose(dev, flag)
84730391Skarels dev_t dev;
84830391Skarels int flag;
84930391Skarels {
85030391Skarels 	register struct tty *tp;
85130391Skarels 	register struct qdmap *qd;
85230391Skarels 	register int *ptep;
85330391Skarels 	int i;				/* SIGNED index */
85430391Skarels 
85530391Skarels 	struct dga *dga;		/* gate array register map pointer */
85630391Skarels 	struct duart *duart;
85730391Skarels 	struct adder *adder;
85830391Skarels 
85930391Skarels 	u_int unit;
86030391Skarels 	u_int minor_dev;
86130391Skarels 	u_int mapix;
86230391Skarels 
86330391Skarels 	minor_dev = minor(dev); 	/* get minor device number */
86430391Skarels 	unit = minor_dev >> 2;		/* get QDSS number */
86530391Skarels 	qd = &qdmap[unit];
86630391Skarels 
86732012Smarc 	/*
86832012Smarc 	 * if this is the graphic device...
86932012Smarc 	 */
87030391Skarels 
87130391Skarels 	if ((minor_dev & 0x03) == 2) {
872*34511Smarc 	    if (one_only[unit] != 1)	/* unlock driver */
87330391Skarels 		return(EBUSY);
87430391Skarels 	    else
87530391Skarels 		one_only[unit] = 0;
87630391Skarels 
877*34511Smarc 	    /*
878*34511Smarc 	    * re-protect device memory
879*34511Smarc 	    */
88030391Skarels 
88130391Skarels 	    if (qdflags[unit].mapped & MAPDEV) {
88230391Skarels 
883*34511Smarc 		/* TEMPLATE RAM */
88430391Skarels 
88532012Smarc 		mapix = VTOP((int)qd->template) - VTOP(qvmem[0]);
88632012Smarc 		ptep = (int *)(QVmap[0] + mapix);
88730391Skarels 
88830391Skarels 		for (i = VTOP(TMPSIZE); i > 0; --i)
88930391Skarels 		    *ptep++ = (*ptep & ~PG_PROT) | PG_V | PG_KW;
89030391Skarels 
891*34511Smarc 		/* ADDER */
89230391Skarels 
89332012Smarc 		mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]);
89432012Smarc 		ptep = (int *)(QVmap[0] + mapix);
89530391Skarels 
89630391Skarels 		for (i = VTOP(REGSIZE); i > 0; --i)
89730391Skarels 		    *ptep++ = (*ptep & ~PG_PROT) | PG_V | PG_KW;
89830391Skarels 
899*34511Smarc 		/* COLOR MAPS */
90030391Skarels 
90132012Smarc 		mapix = VTOP((int)qd->red) - VTOP(qvmem[0]);
90232012Smarc 		ptep = (int *)(QVmap[0] + mapix);
90330391Skarels 
90430391Skarels 		for (i = VTOP(CLRSIZE); i > 0; --i)
90530391Skarels 		    *ptep++ = (*ptep & ~PG_PROT) | PG_V | PG_KW;
90630391Skarels 	    }
90730391Skarels 
908*34511Smarc 	    /*
909*34511Smarc 	     * re-protect DMA buffer and free the map registers
910*34511Smarc 	     */
91130391Skarels 
91230391Skarels 	    if (qdflags[unit].mapped & MAPDMA) {
91330391Skarels 
91430391Skarels 		dga = (struct dga *) qdmap[unit].dga;
91530391Skarels 		adder = (struct adder *) qdmap[unit].adder;
91630391Skarels 
91730391Skarels 		dga->csr &= ~DMA_IE;
91830391Skarels 		dga->csr &= ~0x0600;	     /* kill DMA */
91930391Skarels 		adder->command = CANCEL;
92030391Skarels 
92130391Skarels 		/* if DMA was running, flush spurious intrpt */
92230391Skarels 
92330391Skarels 		if (dga->bytcnt_lo != 0) {
92430391Skarels 		    dga->bytcnt_lo = 0;
92530391Skarels 		    dga->bytcnt_hi = 0;
92630391Skarels 		    DMA_SETIGNORE(DMAheader[unit]);
92730391Skarels 		    dga->csr |= DMA_IE;
92830391Skarels 		    dga->csr &= ~DMA_IE;
92930391Skarels 		}
93030391Skarels 
93130391Skarels 		ptep = (int *)
93230391Skarels 			((VTOP(DMAheader[unit]*4)) + (mfpr(SBR)|0x80000000));
93330391Skarels 
93430391Skarels 		for (i = (DMAbuf_size >> PGSHIFT); i > 0; --i)
93530391Skarels 		    *ptep++ = (*ptep & ~PG_PROT) | PG_V | PG_KW;
93630391Skarels 
93730391Skarels 		ubarelse(0, &Qbus_unmap[unit]);
93830391Skarels 	    }
93930391Skarels 
940*34511Smarc 	    /*
941*34511Smarc 	     * re-protect 1K (2 pages) event queue
942*34511Smarc 	     */
94330391Skarels 
94430391Skarels 	    if (qdflags[unit].mapped & MAPEQ) {
94530391Skarels 
94630391Skarels 		ptep = (int *)
94730391Skarels 			((VTOP(eq_header[unit])*4) + (mfpr(SBR)|0x80000000));
94830391Skarels 
94930391Skarels 		*ptep++ = (*ptep & ~PG_PROT) | PG_KW | PG_V;
95030391Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
95130391Skarels 	    }
95230391Skarels 
953*34511Smarc 	    /*
954*34511Smarc 	     * re-protect scroll param area and disable scroll intrpts
955*34511Smarc 	     */
95630391Skarels 
95730391Skarels 	    if (qdflags[unit].mapped & MAPSCR) {
95830391Skarels 
95930391Skarels 		ptep = (int *) ((VTOP(scroll[unit]) * 4)
96030391Skarels 				    + (mfpr(SBR) | 0x80000000));
96130391Skarels 
96230391Skarels 		/* re-protect 512 scroll param area */
96330391Skarels 
96430391Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
96530391Skarels 
96630391Skarels 		adder = (struct adder *) qdmap[unit].adder;
96730391Skarels 		qdflags[unit].adder_ie &= ~FRAME_SYNC;
96830391Skarels 		adder->interrupt_enable = qdflags[unit].adder_ie;
96930391Skarels 	    }
97030391Skarels 
971*34511Smarc 	    /*
972*34511Smarc 	     * re-protect color map write buffer area and kill intrpts
973*34511Smarc 	     */
97430391Skarels 
97530391Skarels 	    if (qdflags[unit].mapped & MAPCOLOR) {
97630391Skarels 
97730391Skarels 		ptep = (int *) ((VTOP(color_buf[unit]) * 4)
97830391Skarels 				    + (mfpr(SBR) | 0x80000000));
97930391Skarels 
98030391Skarels 		*ptep++ = (*ptep & ~PG_PROT) | PG_KW | PG_V;
98130391Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
98230391Skarels 
98330391Skarels 		color_buf[unit]->status = 0;
98430391Skarels 
98530391Skarels 		adder = (struct adder *) qdmap[unit].adder;
98630391Skarels 		qdflags[unit].adder_ie &= ~VSYNC;
98730391Skarels 		adder->interrupt_enable = qdflags[unit].adder_ie;
98830391Skarels 	    }
98930391Skarels 
990*34511Smarc 	    /*
991*34511Smarc 	     * flag that everthing is unmapped
992*34511Smarc 	     */
99330391Skarels 
994*34511Smarc 	    mtpr(TBIA, 0);		/* invalidate translation buf */
995*34511Smarc 	    qdflags[unit].mapped = 0;	/* flag everything unmapped */
99630391Skarels 	    qdflags[unit].inuse &= ~GRAPHIC_DEV;
99730391Skarels 	    qdflags[unit].curs_acc = ACC_OFF;
99830391Skarels 	    qdflags[unit].curs_thr = 128;
99930391Skarels 
1000*34511Smarc 	    /*
1001*34511Smarc 	     * restore the console
1002*34511Smarc 	     */
100330391Skarels 
100430391Skarels 		dga = (struct dga *) qdmap[unit].dga;
100530391Skarels 		adder = (struct adder *) qdmap[unit].adder;
100630391Skarels 
100730391Skarels 		dga->csr &= ~DMA_IE;
100830391Skarels 		dga->csr &= ~0x0600;	/* halt the DMA! (just in case...) */
100930391Skarels 		dga->csr |= DMA_ERR;	/* clear error condition */
101030391Skarels 		adder->command = CANCEL;
101130391Skarels 
101230391Skarels 		/* if DMA was running, flush spurious intrpt */
101330391Skarels 
101430391Skarels 		if (dga->bytcnt_lo != 0) {
101530391Skarels 		    dga->bytcnt_lo = 0;
101630391Skarels 		    dga->bytcnt_hi = 0;
101730391Skarels 		    DMA_SETIGNORE(DMAheader[unit]);
101830391Skarels 		    dga->csr |= DMA_IE;
101930391Skarels 		    dga->csr &= ~DMA_IE;
102030391Skarels 		}
102130391Skarels 
102230391Skarels 		init_shared(unit);		/* init shared memory */
102330391Skarels 		setup_dragon(unit);		/* init ADDER/VIPER */
102430391Skarels 		ldcursor(unit, cons_cursor);	/* load default cursor map */
102530391Skarels 		setup_input(unit);		/* init the DUART */
102630391Skarels 		ldfont(unit);
102730391Skarels 		cursor[unit].x = 0;
102830391Skarels 		cursor[unit].y = 0;
102930391Skarels 
1030*34511Smarc 	    /*
1031*34511Smarc 	     * shut off the mouse rcv intrpt and turn on kbd intrpts
1032*34511Smarc 	     */
103330391Skarels 	    duart = (struct duart *) qdmap[unit].duart;
103430391Skarels 	    qdflags[unit].duart_imask &= ~(0x20);
103530391Skarels 	    qdflags[unit].duart_imask |= 0x02;
103630391Skarels 	    duart->imask = qdflags[unit].duart_imask;
1037*34511Smarc 	    /*
1038*34511Smarc 	     * shut off interrupts if all is closed
1039*34511Smarc 	     */
104030391Skarels 	    if (!(qdflags[unit].inuse & (CONS_DEV | ALTCONS_DEV))) {
104130391Skarels 		dga = (struct dga *) qdmap[unit].dga;
104230391Skarels 		dga->csr &= ~(GLOBAL_IE | DMA_IE);
104330391Skarels 	    }
104430391Skarels 	}
1045*34511Smarc 	else { /* if this is the console or the alternate console  */
104630391Skarels 	    tp = &qd_tty[minor_dev];
104730391Skarels 
104830391Skarels 	    (*linesw[tp->t_line].l_close)(tp);
104930391Skarels 	    ttyclose(tp);
105030391Skarels 	    tp->t_state = 0;
105130391Skarels 	    qdflags[unit].inuse &= ~CONS_DEV;
1052*34511Smarc 	    /*
1053*34511Smarc 	     * if graphics device is closed, kill interrupts
1054*34511Smarc 	     */
105530391Skarels 	    if (!(qdflags[unit].inuse & GRAPHIC_DEV)) {
105630391Skarels 		dga = (struct dga *) qdmap[unit].dga;
105730391Skarels 		dga->csr &= ~(GLOBAL_IE | DMA_IE);
105830391Skarels 	    }
105930391Skarels 	}
106030391Skarels 
106130391Skarels 	return(0);
106230391Skarels 
106330391Skarels } /* qdclose */
106430391Skarels 
106530391Skarels /***************************************************************
106630391Skarels *
1067*34511Smarc *	qdioctl - provide QDSS control services
106830391Skarels *
106930391Skarels ****************************************************************
107030391Skarels *
107130391Skarels *  calling convention:	qdioctl(dev, cmd, datap, flags);
107230391Skarels *
107330391Skarels *		where:	dev - the major/minor device number
107430391Skarels *			cmd - the user-passed command argument
107530391Skarels *			datap - ptr to user input buff (128 bytes max)
107630391Skarels *			flags - "f_flags" from "struct file" in file.h
107730391Skarels *
107830391Skarels *
107930391Skarels *	- here is the format for the input "cmd" argument
108030391Skarels *
108130391Skarels *	31     29 28	23 22	      16 15		8 7		 0
108230391Skarels *	+----------------------------------------------------------------+
108330391Skarels *	|I/O type|	  | buff length | device ID char |  user command |
108430391Skarels *	+----------------------------------------------------------------+
108530391Skarels *
108630391Skarels *  Return data is in the data buffer pointed to by "datap" input spec
108730391Skarels *
108830391Skarels *********************/
108930391Skarels 
109030391Skarels qdioctl(dev, cmd, datap, flags)
109130391Skarels dev_t dev;
109230391Skarels int cmd;
109330391Skarels caddr_t datap;
109430391Skarels int flags;
109530391Skarels {
109630391Skarels 	register int *ptep;		/* page table entry pointer */
109732012Smarc 	register int mapix;		/* QVmap[] page table index */
109830391Skarels 	register struct _vs_event *event;
109930391Skarels 	register struct tty *tp;
110030391Skarels 
110130391Skarels 	struct qdmap *qd;		/* pointer to device map struct */
110230391Skarels 	struct dga *dga;		/* Gate Array reg structure pntr */
110330391Skarels 	struct duart *duart;		/* DUART reg structure pointer */
110430391Skarels 	struct adder *adder;		/* ADDER reg structure pointer */
110530391Skarels 
110630391Skarels 	struct prgkbd *cmdbuf;
110730391Skarels 	struct prg_cursor *curs;
110830391Skarels 	struct _vs_cursor *pos;
110930391Skarels 
111030391Skarels 	u_int unit = minor(dev) >> 2;	/* number of caller's QDSS */
111130391Skarels 	u_int minor_dev = minor(dev);
111230391Skarels 	struct uba_device *ui = qdinfo[unit];
111330391Skarels 	struct qd_softc *sc = &qd_softc[ui->ui_unit];
111432012Smarc 	/* struct devget *devget; */
111530391Skarels 
111630391Skarels 	int error;
111730391Skarels 	int s;
111830391Skarels 
111930391Skarels 	int i;				/* SIGNED index */
112030391Skarels 	int sbr;			/* SBR variable (you silly boy) */
112130391Skarels 	u_int ix;
112230391Skarels 
112330391Skarels 	short status;
112430391Skarels 	short *shortp;			/* generic pointer to a short */
112530391Skarels 	char *chrp;			/* generic character pointer */
112630391Skarels 
112730391Skarels 	short *temp;			/* a pointer to template RAM */
112830391Skarels 
112932012Smarc 	/* service graphic device ioctl commands */
113030391Skarels 	switch (cmd) {
1131*34511Smarc 	    /*
1132*34511Smarc 	     * extract the oldest event from the event queue
1133*34511Smarc 	     */
113430391Skarels 	    case QD_GETEVENT:
113530391Skarels 		if (ISEMPTY(eq_header[unit])) {
113630391Skarels 		    event = (struct _vs_event *) datap;
113730391Skarels 		    event->vse_device = VSE_NULL;
113830391Skarels 		    break;
113930391Skarels 		}
114030391Skarels 		event = (struct _vs_event *) GETBEGIN(eq_header[unit]);
114132012Smarc 		s = spltty();
114230391Skarels 		GETEND(eq_header[unit]);
114330391Skarels 		splx(s);
114430391Skarels 		bcopy(event, datap, sizeof(struct _vs_event));
114530391Skarels 		break;
114630391Skarels 
114730391Skarels 	    /*-------------------------------------------------------
114830391Skarels 	    * init the dragon stuff, DUART, and driver variables  */
114930391Skarels 
115030391Skarels 	    case QD_RESET:
115130391Skarels 
115230391Skarels 		init_shared(unit);		/* init shared memory */
115330391Skarels 		setup_dragon(unit);	      /* init the ADDER/VIPER stuff */
115430391Skarels 		clear_qd_screen(unit);
115530391Skarels 		ldcursor(unit, cons_cursor);	/* load default cursor map */
115630391Skarels 		ldfont(unit);			/* load the console font */
115730391Skarels 		setup_input(unit);		/* init the DUART */
115830391Skarels 		break;
115930391Skarels 
116030391Skarels 	    /*----------------------------------------
116130391Skarels 	    * init the DUART and driver variables  */
116230391Skarels 
116330391Skarels 	    case QD_SET:
116430391Skarels 
116530391Skarels 		init_shared(unit);
116630391Skarels 		setup_input(unit);
116730391Skarels 		break;
116830391Skarels 
116930391Skarels 	    /*---------------------------------------------------------------
117030391Skarels 	    * clear the QDSS screen.  (NOTE that this reinits the dragon) */
117130391Skarels 
117230391Skarels 	    case QD_CLRSCRN:
117330391Skarels 
117430391Skarels 		setup_dragon(unit);
117530391Skarels 		clear_qd_screen(unit);
117630391Skarels 		break;
117730391Skarels 
117830391Skarels 	    /*------------------------------------
117930391Skarels 	    * load a cursor into template RAM  */
118030391Skarels 
118130391Skarels 	    case QD_WTCURSOR:
118230391Skarels 
118330391Skarels 		ldcursor(unit, datap);
118430391Skarels 		break;
118530391Skarels 
118630391Skarels 	    case QD_RDCURSOR:
118730391Skarels 
118830391Skarels 		temp = (short *) qdmap[unit].template;
118930391Skarels 
119030391Skarels 		/* cursor is 32 WORDS from the end of the 8k WORD...
119130391Skarels 		*  ...template space */
119230391Skarels 
119330391Skarels 		temp += (8 * 1024) - 32;
119430391Skarels 
119530391Skarels 		for (i = 0; i < 32; ++i, datap += sizeof(short))
119630391Skarels 		    *(short *)datap = *temp++;
119730391Skarels 		break;
119830391Skarels 
119930391Skarels 	    /*------------------------------
120030391Skarels 	    * position the mouse cursor  */
120130391Skarels 
120230391Skarels 	    case QD_POSCURSOR:
120330391Skarels 
120430391Skarels 		dga = (struct dga *) qdmap[unit].dga;
120530391Skarels 		pos = (struct _vs_cursor *) datap;
120632012Smarc 		s = spltty();
120730391Skarels 		dga->x_cursor = TRANX(pos->x);
120830391Skarels 		dga->y_cursor = TRANY(pos->y);
120930391Skarels 		eq_header[unit]->curs_pos.x = pos->x;
121030391Skarels 		eq_header[unit]->curs_pos.y = pos->y;
121130391Skarels 		splx(s);
121230391Skarels 		break;
121330391Skarels 
121430391Skarels 	    /*--------------------------------------
121530391Skarels 	    * set the cursor acceleration factor */
121630391Skarels 
121730391Skarels 	    case QD_PRGCURSOR:
121830391Skarels 
121930391Skarels 		curs = (struct prg_cursor *) datap;
122032012Smarc 		s = spltty();
122130391Skarels 		qdflags[unit].curs_acc = curs->acc_factor;
122230391Skarels 		qdflags[unit].curs_thr = curs->threshold;
122330391Skarels 		splx(s);
122430391Skarels 		break;
122530391Skarels 
122630391Skarels 	    /*---------------------------------------
122730391Skarels 	    * enable 'user write' to device pages */
122830391Skarels 
122930391Skarels 	    case QD_MAPDEVICE:
123030391Skarels 
123130391Skarels 		/*--------------
123230391Skarels 		* init stuff */
123330391Skarels 
123430391Skarels 		qdflags[unit].mapped |= MAPDEV;
123530391Skarels 		qd = (struct qdmap *) &qdmap[unit];
123630391Skarels 
123730391Skarels 		/*-------------------------------------
123830391Skarels 		* enable user write to template RAM */
123930391Skarels 
124032012Smarc 		mapix = VTOP((int)qd->template) - VTOP(qvmem[0]);
124132012Smarc 		ptep = (int *)(QVmap[0] + mapix);
124230391Skarels 
124330391Skarels 		for (i = VTOP(TMPSIZE); i > 0; --i)
124430391Skarels 		    *ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V;
124530391Skarels 
124630391Skarels 		/*----------------------------------
124730391Skarels 		* enable user write to registers */
124830391Skarels 
124932012Smarc 		mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]);
125032012Smarc 		ptep = (int *)(QVmap[0] + mapix);
125130391Skarels 
125230391Skarels 		for (i = VTOP(REGSIZE); i > 0; --i)
125330391Skarels 		    *ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V;
125430391Skarels 
125530391Skarels 		/*-----------------------------------
125630391Skarels 		* enable user write to color maps */
125730391Skarels 
125832012Smarc 		mapix = VTOP((int)qd->red) - VTOP(qvmem[0]);
125932012Smarc 		ptep = (int *)(QVmap[0] + mapix);
126030391Skarels 
126130391Skarels 		for (i = VTOP(CLRSIZE); i > 0; --i)
126230391Skarels 		    *ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V;
126330391Skarels 
126430391Skarels 		/*------------------------------
126530391Skarels 		* enable user write to DUART */
126630391Skarels 
126732012Smarc 		mapix = VTOP((int)qd->duart) - VTOP(qvmem[0]);
126832012Smarc 		ptep = (int *)(QVmap[0] + mapix);
126930391Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; /* duart page */
127030391Skarels 
127130391Skarels 		mtpr(TBIA, 0);		/* smash CPU's translation buffer */
127230391Skarels 
127330391Skarels 		/*------------------------------------------
127430391Skarels 		* stuff qdmap structure in return buffer */
127530391Skarels 
127630391Skarels 		bcopy(qd, datap, sizeof(struct qdmap));
127730391Skarels 		break;
127830391Skarels 
127930391Skarels 	    /*-------------------------------------
128030391Skarels 	    * do setup for DMA by user process	*/
128130391Skarels 
128230391Skarels 	    case QD_MAPIOBUF:
128330391Skarels 
128430391Skarels 		/*------------------------------------------------
128530391Skarels 		* set 'user write enable' bits for DMA buffer  */
128630391Skarels 
128730391Skarels 		qdflags[unit].mapped |= MAPDMA;
128830391Skarels 
128930391Skarels 		ptep = (int *) ((VTOP(DMAheader[unit]) * 4)
129030391Skarels 				+ (mfpr(SBR) | 0x80000000));
129130391Skarels 
129230391Skarels 		for (i = (DMAbuf_size >> PGSHIFT); i > 0; --i)
129330391Skarels 		    *ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V;
129430391Skarels 
129530391Skarels 		mtpr(TBIA, 0);			/* clr CPU translation buf */
129630391Skarels 
129730391Skarels 		/*-------------------------------------
129830391Skarels 		* set up QBUS map registers for DMA */
129930391Skarels 
130030391Skarels 		DMAheader[unit]->QBAreg =
130130391Skarels 				uballoc(0, DMAheader[unit], DMAbuf_size, 0);
130230391Skarels 
130330391Skarels 		if (DMAheader[unit]->QBAreg == 0)
1304*34511Smarc 		    printf("qd%d: qdioctl: QBA setup error\n", unit);
130530391Skarels 
130630391Skarels 		Qbus_unmap[unit] = DMAheader[unit]->QBAreg;
130730391Skarels 		DMAheader[unit]->QBAreg &= 0x3FFFF;
130830391Skarels 
130930391Skarels 		/*----------------------
131030391Skarels 		* return I/O buf adr */
131130391Skarels 
131230391Skarels 		*(int *)datap = (int) DMAheader[unit];
131330391Skarels 		break;
131430391Skarels 
131530391Skarels 	    /*----------------------------------------------------------------
131630391Skarels 	    * map the shared scroll param area and enable scroll interpts  */
131730391Skarels 
131830391Skarels 	    case QD_MAPSCROLL:
131930391Skarels 
132030391Skarels 		qdflags[unit].mapped |= MAPSCR;
132130391Skarels 
132230391Skarels 		ptep = (int *) ((VTOP(scroll[unit]) * 4)
132330391Skarels 				+ (mfpr(SBR) | 0x80000000));
132430391Skarels 
132530391Skarels 		/* allow user write to scroll area */
132630391Skarels 
132730391Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
132830391Skarels 
132930391Skarels 		mtpr(TBIA, 0);			/* clr CPU translation buf */
133030391Skarels 
133130391Skarels 		scroll[unit]->status = 0;
133230391Skarels 
133330391Skarels 		adder = (struct adder *) qdmap[unit].adder;
133430391Skarels 
133530391Skarels 		qdflags[unit].adder_ie |= FRAME_SYNC;
133630391Skarels 		adder->interrupt_enable = qdflags[unit].adder_ie;
133730391Skarels 
133830391Skarels 		/* return scroll area address */
133930391Skarels 
134030391Skarels 		*(int *)datap = (int) scroll[unit];
134130391Skarels 		break;
134230391Skarels 
134330391Skarels 	    /*-------------------------------------------------------------
134430391Skarels 	    * unmap shared scroll param area and disable scroll intrpts */
134530391Skarels 
134630391Skarels 	    case QD_UNMAPSCROLL:
134730391Skarels 
134830391Skarels 		if (qdflags[unit].mapped & MAPSCR) {
134930391Skarels 
135030391Skarels 		    qdflags[unit].mapped &= ~MAPSCR;
135130391Skarels 
135230391Skarels 		    ptep = (int *) ((VTOP(scroll[unit]) * 4)
135330391Skarels 				    + (mfpr(SBR) | 0x80000000));
135430391Skarels 
135530391Skarels 		    /* re-protect 512 scroll param area */
135630391Skarels 
135730391Skarels 		    *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
135830391Skarels 
135930391Skarels 		    mtpr(TBIA, 0);	/* smash CPU's translation buf */
136030391Skarels 
136130391Skarels 		    adder = (struct adder *) qdmap[unit].adder;
136230391Skarels 		    qdflags[unit].adder_ie &= ~FRAME_SYNC;
136330391Skarels 		    adder->interrupt_enable = qdflags[unit].adder_ie;
136430391Skarels 		}
136530391Skarels 		break;
136630391Skarels 
136730391Skarels 	    /*-----------------------------------------------------------
136830391Skarels 	    * map shared color map write buf and turn on vsync intrpt */
136930391Skarels 
137030391Skarels 	    case QD_MAPCOLOR:
137130391Skarels 
137230391Skarels 		qdflags[unit].mapped |= MAPCOLOR;
137330391Skarels 
137430391Skarels 		ptep = (int *) ((VTOP(color_buf[unit]) * 4)
137530391Skarels 				+ (mfpr(SBR) | 0x80000000));
137630391Skarels 
137730391Skarels 		/* allow user write to color map write buffer */
137830391Skarels 
137930391Skarels 		*ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V;
138030391Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
138130391Skarels 
138230391Skarels 		mtpr(TBIA, 0);			/* clr CPU translation buf */
138330391Skarels 
138430391Skarels 		adder = (struct adder *) qdmap[unit].adder;
138530391Skarels 
138630391Skarels 		qdflags[unit].adder_ie |= VSYNC;
138730391Skarels 		adder->interrupt_enable = qdflags[unit].adder_ie;
138830391Skarels 
138930391Skarels 		/* return scroll area address */
139030391Skarels 
139130391Skarels 		*(int *)datap = (int) color_buf[unit];
139230391Skarels 		break;
139330391Skarels 
139430391Skarels 	    /*--------------------------------------------------------------
139530391Skarels 	    * unmap shared color map write buffer and kill VSYNC intrpts */
139630391Skarels 
139730391Skarels 	    case QD_UNMAPCOLOR:
139830391Skarels 
139930391Skarels 		if (qdflags[unit].mapped & MAPCOLOR) {
140030391Skarels 
140130391Skarels 		    qdflags[unit].mapped &= ~MAPCOLOR;
140230391Skarels 
140330391Skarels 		    ptep = (int *) ((VTOP(color_buf[unit]) * 4)
140430391Skarels 				    + (mfpr(SBR) | 0x80000000));
140530391Skarels 
140630391Skarels 		    /* re-protect color map write buffer */
140730391Skarels 
140830391Skarels 		    *ptep++ = (*ptep & ~PG_PROT) | PG_KW | PG_V;
140930391Skarels 		    *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
141030391Skarels 
141130391Skarels 		    mtpr(TBIA, 0);	/* smash CPU's translation buf */
141230391Skarels 
141330391Skarels 		    adder = (struct adder *) qdmap[unit].adder;
141430391Skarels 
141530391Skarels 		    qdflags[unit].adder_ie &= ~VSYNC;
141630391Skarels 		    adder->interrupt_enable = qdflags[unit].adder_ie;
141730391Skarels 		}
141830391Skarels 		break;
141930391Skarels 
142030391Skarels 	    /*---------------------------------------------
142130391Skarels 	    * give user write access to the event queue */
142230391Skarels 
142330391Skarels 	    case QD_MAPEVENT:
142430391Skarels 
142530391Skarels 		qdflags[unit].mapped |= MAPEQ;
142630391Skarels 
142730391Skarels 		ptep = (int *) ((VTOP(eq_header[unit]) * 4)
142830391Skarels 				+ (mfpr(SBR) | 0x80000000));
142930391Skarels 
143030391Skarels 		/* allow user write to 1K event queue */
143130391Skarels 
143230391Skarels 		*ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V;
143330391Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
143430391Skarels 
143530391Skarels 		mtpr(TBIA, 0);			/* clr CPU translation buf */
143630391Skarels 
143730391Skarels 		/* return event queue address */
143830391Skarels 
143930391Skarels 		*(int *)datap = (int) eq_header[unit];
144030391Skarels 		break;
144130391Skarels 
144230391Skarels 	    /*-----------------------------------------------
144330391Skarels 	    * pass caller's programming commands to LK201 */
144430391Skarels 
144530391Skarels 	    case QD_PRGKBD:
144630391Skarels 
144730391Skarels 		duart = (struct duart *) qdmap[unit].duart;
144830391Skarels 		cmdbuf = (struct prgkbd *) datap;    /* pnt to kbd cmd buf */
144930391Skarels 
145030391Skarels 		/*----------------
145130391Skarels 		* send command */
145230391Skarels 
145330391Skarels 		for (i = 1000; i > 0; --i) {
145430391Skarels 		    if ((status = duart->statusA) & XMT_RDY) {
145530391Skarels 			duart->dataA = cmdbuf->cmd;
145630391Skarels 			break;
145730391Skarels 		    }
145830391Skarels 		}
145930391Skarels 
146030391Skarels 		if (i == 0) {
1461*34511Smarc 		    printf("qd%d: qdioctl: timeout on XMT_RDY [1]\n", unit);
146230391Skarels 		    break;
146330391Skarels 		}
146430391Skarels 
146530391Skarels 		/*----------------
146630391Skarels 		* send param1? */
146730391Skarels 
146830391Skarels 		if (cmdbuf->cmd & LAST_PARAM)
146930391Skarels 		    break;
147030391Skarels 
147130391Skarels 		for (i = 1000; i > 0; --i) {
147230391Skarels 		    if ((status = duart->statusA) & XMT_RDY) {
147330391Skarels 			duart->dataA = cmdbuf->param1;
147430391Skarels 			break;
147530391Skarels 		    }
147630391Skarels 		}
147730391Skarels 
147830391Skarels 		if (i == 0) {
1479*34511Smarc 		    printf("\nqd%d: qdioctl: timeout on XMT_RDY [2]\n", unit);
148030391Skarels 		    break;
148130391Skarels 		}
148230391Skarels 
148330391Skarels 		/*----------------
148430391Skarels 		* send param2? */
148530391Skarels 
148630391Skarels 		if (cmdbuf->param1 & LAST_PARAM)
148730391Skarels 		    break;
148830391Skarels 
148930391Skarels 		for (i = 1000; i > 0; --i) {
149030391Skarels 		    if ((status = duart->statusA) & XMT_RDY) {
149130391Skarels 			duart->dataA = cmdbuf->param2;
149230391Skarels 			break;
149330391Skarels 		    }
149430391Skarels 		}
149530391Skarels 
149630391Skarels 		if (i == 0) {
1497*34511Smarc 		    printf("qd%d: qdioctl: timeout on XMT_RDY [3]\n", unit);
149830391Skarels 		    break;
149930391Skarels 		}
150030391Skarels 
150130391Skarels 		break;
150230391Skarels 
150330391Skarels 	    /*----------------------------------------------------
150430391Skarels 	    * pass caller's programming commands to the mouse  */
150530391Skarels 
150630391Skarels 	    case QD_PRGMOUSE:
150730391Skarels 
150830391Skarels 		duart = (struct duart *) qdmap[unit].duart;
150930391Skarels 
151030391Skarels 		for (i = 1000; i > 0; --i) {
151130391Skarels 		    if ((status = duart->statusB) & XMT_RDY) {
151230391Skarels 			duart->dataB = *datap;
151330391Skarels 			break;
151430391Skarels 		    }
151530391Skarels 		}
151630391Skarels 
151730391Skarels 		if (i == 0) {
1518*34511Smarc 		    printf("qd%d: qdioctl: timeout on XMT_RDY [4]\n", unit);
151930391Skarels 		}
152030391Skarels 
152130391Skarels 		break;
152230391Skarels 
152330391Skarels 	    /*----------------------------------------------
152430391Skarels 	    * get QDSS configuration word and return it  */
152530391Skarels 
152630391Skarels 	    case QD_RDCONFIG:
152730391Skarels 
152830391Skarels 		*(short *)datap = qdflags[unit].config;
152930391Skarels 		break;
153030391Skarels 
153130391Skarels 	    /*----------------------
153230391Skarels 	    * program the tablet */
153330391Skarels 
153430391Skarels 	    case QD_PRGTABLET:
153530391Skarels 
153630391Skarels 		duart = (struct duart *) qdmap[unit].duart;
153730391Skarels 
153830391Skarels 		for (i = 1000; i > 0; --i) {
153930391Skarels 		    if ((status = duart->statusB) & XMT_RDY) {
154030391Skarels 			duart->dataB = *datap;
154130391Skarels 			break;
154230391Skarels 		    }
154330391Skarels 		}
154430391Skarels 
154530391Skarels 		if (i == 0) {
1546*34511Smarc 		    printf("qd%d: qdioctl: timeout on XMT_RDY [5]\n", unit);
154730391Skarels 		}
154830391Skarels 
154930391Skarels 		break;
155030391Skarels 
155130391Skarels 	    /*-----------------------------------------------
155230391Skarels 	    * program the tablet report resolution factor */
155330391Skarels 
155430391Skarels 	    case QD_PRGTABRES:
155530391Skarels 
155630391Skarels 		qdflags[unit].tab_res = *(short *)datap;
155730391Skarels 		break;
155830391Skarels 
155930391Skarels 	    default:
156030391Skarels 		/*-----------------------------
156130391Skarels 		* service tty type ioctl's  */
156230391Skarels 
156330391Skarels 		    if (!(minor_dev & 0x02)) {
156430391Skarels 
156530391Skarels 			tp = &qd_tty[minor_dev];
156630391Skarels 
156730391Skarels 			error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, datap, flags);
156830391Skarels 			if (error >= 0) {
156930391Skarels 			    return(error);
157030391Skarels 			}
157130391Skarels 
157230391Skarels 			error = ttioctl(tp, cmd, datap, flags);
157330391Skarels 			if (error >= 0) {
157430391Skarels 			    return(error);
157530391Skarels 			}
157630391Skarels 		    }
157730391Skarels 		    break;
157830391Skarels 	}
157930391Skarels 
158030391Skarels /*--------------------------------
158130391Skarels * clean up and get outta here  */
158230391Skarels 
158330391Skarels 	return(0);
158430391Skarels 
158530391Skarels } /* qdioctl */
158630391Skarels 
158730391Skarels /**********************************************************************
158830391Skarels *
158930391Skarels *	qdselect()... service select call for event queue input
159030391Skarels *
159130391Skarels **********************************************************************/
159230391Skarels 
159330391Skarels qdselect(dev, rw)
159430391Skarels dev_t dev;
159530391Skarels int rw;
159630391Skarels {
159730391Skarels 	register int s;
159830391Skarels 	register int unit;
159930391Skarels 
160032012Smarc 	s = spltty();
160130391Skarels 	unit = minor(dev) >> 2;
160230391Skarels 
160330391Skarels 	switch (rw) {
160430391Skarels 
160530391Skarels 	    case FREAD: 		/* event available? */
160630391Skarels 
160730391Skarels 		if(!(ISEMPTY(eq_header[unit]))) {
160830391Skarels 		    splx(s);
160930391Skarels 		    return(1);		/* return "1" if event exists */
161030391Skarels 		}
161130391Skarels 		rsel[unit] = u.u_procp;
161230391Skarels 		qdflags[unit].selmask |= SEL_READ;
161330391Skarels 		splx(s);
161430391Skarels 		return(0);
161530391Skarels 
161630391Skarels 	    case FWRITE:		/* DMA done? */
161730391Skarels 
161830391Skarels 		if (DMA_ISEMPTY(DMAheader[unit])) {
161930391Skarels 		    splx(s);
162030391Skarels 		    return(1);		/* return "1" if DMA is done */
162130391Skarels 		}
162230391Skarels 		rsel[unit] = u.u_procp;
162330391Skarels 		qdflags[unit].selmask |= SEL_WRITE;
162430391Skarels 		splx(s);
162530391Skarels 		return(0);
162630391Skarels 	}
162730391Skarels 
162830391Skarels } /* qdselect() */
162930391Skarels 
163030391Skarels /***************************************************************
163130391Skarels *
163230391Skarels *	qdwrite()... output to the QDSS screen as a TTY
163330391Skarels *
163430391Skarels ***************************************************************/
163530391Skarels 
163630391Skarels extern qd_strategy();
163730391Skarels 
163830391Skarels qdwrite(dev, uio)
163930391Skarels dev_t dev;
164030391Skarels struct uio *uio;
164130391Skarels {
164230391Skarels 	register struct tty *tp;
164330391Skarels 	register int minor_dev;
164430391Skarels 	register int unit;
164530391Skarels 
164630391Skarels 	minor_dev = minor(dev);
164730391Skarels 	unit = (minor_dev >> 2) & 0x07;
164830391Skarels 
164930391Skarels 	/*------------------------------
165030391Skarels 	* if this is the console...  */
165130391Skarels 
165230391Skarels 	if ((minor_dev & 0x03) != 0x02	&&
165330391Skarels 	     qdflags[unit].inuse & CONS_DEV) {
165430391Skarels 	    tp = &qd_tty[minor_dev];
165530391Skarels 	    return ((*linesw[tp->t_line].l_write)(tp, uio));
165630391Skarels 	}
165730391Skarels 
165830391Skarels 	/*------------------------------------------------
165930391Skarels 	* else this must be a DMA xfer from user space */
166030391Skarels 
166130391Skarels 	else if (qdflags[unit].inuse & GRAPHIC_DEV) {
166230391Skarels 	    return (physio(qd_strategy, &qdbuf[unit],
166330391Skarels 			   dev, B_WRITE, minphys, uio));
166430391Skarels 	}
166530391Skarels }
166630391Skarels 
166730391Skarels /***************************************************************
166830391Skarels *
166930391Skarels *	qdread()... read from QDSS keyboard as a TTY
167030391Skarels *
167130391Skarels ***************************************************************/
167230391Skarels 
167330391Skarels qdread(dev, uio)
167430391Skarels dev_t dev;
167530391Skarels struct uio *uio;
167630391Skarels {
167730391Skarels 	register struct tty *tp;
167830391Skarels 	register int minor_dev;
167930391Skarels 	register int unit;
168030391Skarels 
168130391Skarels 	minor_dev = minor(dev);
168230391Skarels 	unit = (minor_dev >> 2) & 0x07;
168330391Skarels 
168430391Skarels 	/*------------------------------
168530391Skarels 	* if this is the console...  */
168630391Skarels 
168730391Skarels 	if ((minor_dev & 0x03) != 0x02	&&
168830391Skarels 	     qdflags[unit].inuse & CONS_DEV) {
168930391Skarels 	    tp = &qd_tty[minor_dev];
169030391Skarels 	    return ((*linesw[tp->t_line].l_read)(tp, uio));
169130391Skarels 	}
169230391Skarels 
169330391Skarels 	/*------------------------------------------------
169430391Skarels 	* else this must be a bitmap-to-processor xfer */
169530391Skarels 
169630391Skarels 	else if (qdflags[unit].inuse & GRAPHIC_DEV) {
169730391Skarels 	    return (physio(qd_strategy, &qdbuf[unit],
169830391Skarels 			   dev, B_READ, minphys, uio));
169930391Skarels 	}
170030391Skarels }
170130391Skarels 
170230391Skarels /***************************************************************
170330391Skarels *
170430391Skarels *	qd_strategy()... strategy routine to do DMA
170530391Skarels *
170630391Skarels ***************************************************************/
170730391Skarels 
170830391Skarels qd_strategy(bp)
170930391Skarels register struct buf *bp;
171030391Skarels {
171130391Skarels 	register struct dga *dga;
171230391Skarels 	register struct adder *adder;
171330391Skarels 
171430391Skarels 	char *DMAbufp;
171530391Skarels 
171630391Skarels 	int QBAreg;
171730391Skarels 	int bytcnt;
171830391Skarels 	int s;
171930391Skarels 	int unit;
172030391Skarels 	int cookie;
172130391Skarels 
172230391Skarels 	int i,j,k;
172330391Skarels 
172430391Skarels 	unit = (minor(bp->b_dev) >> 2) & 0x07;
172530391Skarels 
172632012Smarc 	/*
172732012Smarc 	* init pointers
172832012Smarc 	*/
172930391Skarels 
173030391Skarels 	if ((QBAreg = ubasetup(0, bp, 0)) == 0) {
1731*34511Smarc 	    printf("qd%d: qd_strategy: QBA setup error\n", unit);
173230391Skarels 	    goto STRAT_ERR;
173330391Skarels 	}
173430391Skarels 
173530391Skarels 	dga = (struct dga *) qdmap[unit].dga;
173630391Skarels 
173732012Smarc 	s = spltty();
173830391Skarels 
173930391Skarels 	qdflags[unit].user_dma = -1;
174030391Skarels 
174130391Skarels 	dga->csr |= DMA_IE;
174230391Skarels 
174330391Skarels 	cookie = QBAreg & 0x3FFFF;
174430391Skarels 	dga->adrs_lo = (short) cookie;
174530391Skarels 	dga->adrs_hi = (short) (cookie >> 16);
174630391Skarels 
174730391Skarels 	dga->bytcnt_lo = (short) bp->b_bcount;
174830391Skarels 	dga->bytcnt_hi = (short) (bp->b_bcount >> 16);
174930391Skarels 
175030391Skarels 	while (qdflags[unit].user_dma) {
175130391Skarels 	    sleep((caddr_t)&qdflags[unit].user_dma, QDPRIOR);
175230391Skarels 	}
175330391Skarels 
175430391Skarels 	splx(s);
175530391Skarels 	ubarelse(0, &QBAreg);
175630391Skarels 
175730391Skarels 	if (!(dga->csr & DMA_ERR)) {
175830391Skarels 	    iodone(bp);
175930391Skarels 	    return;
176030391Skarels 	}
176130391Skarels 
176230391Skarels STRAT_ERR:
176330391Skarels 	adder = (struct adder *) qdmap[unit].adder;
176430391Skarels 	adder->command = CANCEL;		/* cancel adder activity */
176530391Skarels 	dga->csr &= ~DMA_IE;
176630391Skarels 	dga->csr &= ~0x0600;		/* halt DMA (reset fifo) */
176730391Skarels 	dga->csr |= DMA_ERR;		/* clear error condition */
176830391Skarels 	bp->b_flags |= B_ERROR; 	/* flag an error to physio() */
176930391Skarels 
177030391Skarels 	/* if DMA was running, flush spurious intrpt */
177130391Skarels 
177230391Skarels 	if (dga->bytcnt_lo != 0) {
177330391Skarels 	    dga->bytcnt_lo = 0;
177430391Skarels 	    dga->bytcnt_hi = 0;
177530391Skarels 	    DMA_SETIGNORE(DMAheader[unit]);
177630391Skarels 	    dga->csr |= DMA_IE;
177730391Skarels 	}
177830391Skarels 
177930391Skarels 	iodone(bp);
178030391Skarels 
178130391Skarels } /* qd_strategy */
178230391Skarels 
178330391Skarels /*******************************************************************
178430391Skarels *
178530391Skarels *	qdstart()... startup output to the console screen
178630391Skarels *
178730391Skarels ********************************************************************
1788*34511Smarc * NOTE - You must have tty.c fixed so it doesn't try to sleep
1789*34511Smarc *	waiting for a transmitter interrupt (which would never occur).
1790*34511Smarc *	Writes to the QDSS are synchronous and have (essentially)
1791*34511Smarc *	completed by the time the start routine returns.
179230391Skarels *
179330391Skarels *	calling convention:
179430391Skarels *
179530391Skarels *		qdstart(tp);
1796*34511Smarc *		struct tty *tp; 	# pointer to tty structure
179730391Skarels *
179830391Skarels ********/
179930391Skarels 
180030391Skarels qdstart(tp)
180130391Skarels register struct tty *tp;
180230391Skarels {
180330391Skarels 	register int which_unit, unit, c;
180430391Skarels 	int s;
180530391Skarels 
180630391Skarels 	unit = minor(tp->t_dev);
180730391Skarels 	which_unit = (unit >> 2) & 0x3;
1808*34511Smarc 	/* unit &= 0x03; */
180930391Skarels 
1810*34511Smarc 	/* If it's currently active, or delaying, no need to do anything. */
181132012Smarc 	s = spltty();
181230391Skarels 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
181330391Skarels 		goto out;
181430391Skarels 
181532012Smarc 	/*
1816*34511Smarc 	 * XXX - this loop is at spltty.  not good, but hardly worth
1817*34511Smarc 	 * fixing since the glass tty is only used when the window
1818*34511Smarc 	 * system isn't running.  if you debug window systems you
1819*34511Smarc 	 * might want to rethink this.
182032012Smarc 	 */
182130391Skarels 	while (tp->t_outq.c_cc) {
1822*34511Smarc 		c = getc(&tp->t_outq);
1823*34511Smarc 		blitc(which_unit, c & 0xFF);
182430391Skarels 	}
1825*34511Smarc 	tp->t_state &= ~TS_BUSY;
1826*34511Smarc 	if (tp->t_state&TS_ASLEEP) {
1827*34511Smarc 		tp->t_state &= ~TS_ASLEEP;
1828*34511Smarc 		wakeup((caddr_t)&tp->t_outq);
182930391Skarels 	}
183030391Skarels 
183130391Skarels out:
183230391Skarels 	splx(s);
183330391Skarels 
183430391Skarels } /* qdstart */
183530391Skarels 
183630391Skarels 
183730391Skarels /*******************************************************************
183830391Skarels *
183930391Skarels *	qdstop()... stop the tty
184030391Skarels *
184130391Skarels *******************************************************************/
184230391Skarels 
184330391Skarels qdstop(tp, flag)
184430391Skarels register struct tty *tp;
184530391Skarels int flag;
184630391Skarels {
184730391Skarels 	register int s;
184830391Skarels 
1849*34511Smarc #ifdef notdef	/* not needed - qdss is synchronous */
185032012Smarc 	s = spltty();	/* block intrpts during state modification */
185130391Skarels 	if (tp->t_state & TS_BUSY) {
185230391Skarels 	    if ((tp->t_state & TS_TTSTOP) == 0) {
185330391Skarels 		tp->t_state |= TS_FLUSH;
185430391Skarels 	    } else
185530391Skarels 		tp->t_state &= ~TS_BUSY;
185630391Skarels 	}
185730391Skarels 	splx(s);
1858*34511Smarc #endif
185930391Skarels }
186030391Skarels 
186130391Skarels /*******************************************************************
186230391Skarels *
186330391Skarels *	blitc()... output a character to the QDSS screen
186430391Skarels *
186530391Skarels ********************************************************************
186630391Skarels *
186730391Skarels *	calling convention:
186830391Skarels *
186930391Skarels *		blitc(chr);
187030391Skarels *		char chr;		;character to be displayed
187130391Skarels *
187230391Skarels ********/
187330391Skarels 
187430391Skarels blitc(unit, chr)
187530391Skarels int unit;
187630391Skarels char chr;
187730391Skarels {
187830391Skarels 	register struct adder *adder;
187930391Skarels 	register struct dga *dga;
188030391Skarels 	register int i;
188132012Smarc 	static	 short inescape[NQD];
188230391Skarels 
188330391Skarels 	short x;
188430391Skarels 
188532012Smarc 	/* init stuff  */
188630391Skarels 
188730391Skarels 	adder = (struct adder *) qdmap[unit].adder;
188830391Skarels 	dga = (struct dga *) qdmap[unit].dga;
188930391Skarels 
189030391Skarels 	chr &= 0x7F;
189130391Skarels 
189232012Smarc 	/*
189332012Smarc 	 *  Support cursor addressing so vi will work.
189432012Smarc 	 *  Decode for "\E=%.%." cursor motion description.
189532012Smarc 	 *
189632012Smarc 	 *  If we've seen an escape, grab up to three more
189732012Smarc 	 *  characters, bailing out if necessary.
189832012Smarc 	 */
189932012Smarc 	if (inescape[unit]) {
190032012Smarc 		switch (inescape[unit]++) {
190132012Smarc 		case 1:
190232012Smarc 			if (chr != '=') {
190332012Smarc 				/* bogus escape sequence */
190432012Smarc 				inescape[unit] = 0;
190532012Smarc 				blitc(unit, chr);
190632012Smarc 			}
190732012Smarc 			return(0);
190832012Smarc 		case 2:
190932012Smarc 			/* position row */
191032012Smarc 			cursor[unit].y = CHAR_HEIGHT * chr;
191132012Smarc 			if (cursor[unit].y > 863 - CHAR_HEIGHT)
191232012Smarc 				cursor[unit].y = 863 - CHAR_HEIGHT;
191332012Smarc 			dga->y_cursor = TRANY(cursor[unit].y);
191432012Smarc 			return(0);
191532012Smarc 		case 3:
191632012Smarc 			/* position column */
191732012Smarc 			cursor[unit].x = CHAR_WIDTH * chr;
191832012Smarc 			if (cursor[unit].x > 1024 - CHAR_WIDTH)
191932012Smarc 				cursor[unit].x = 1023 - CHAR_WIDTH;
192032012Smarc 			dga->x_cursor = TRANX(cursor[unit].x);
192132012Smarc 			inescape[unit] = 0;
192232012Smarc 			return(0);
192332012Smarc 		default:
192432012Smarc 			inescape[unit] = 0;
192532012Smarc 			blitc(unit, chr);
192632012Smarc 		}
192732012Smarc 	}
192832012Smarc 
192932012Smarc 
193030391Skarels 	switch (chr) {
193130391Skarels 
193230391Skarels 	    case '\r':			/* return char */
193330391Skarels 		cursor[unit].x = 0;
193430391Skarels 		dga->x_cursor = TRANX(cursor[unit].x);
193530391Skarels 		return(0);
193630391Skarels 
193730391Skarels 	    case '\t':			/* tab char */
193830391Skarels 
193930391Skarels 		for (i = 8 - ((cursor[unit].x >> 3) & 0x07); i > 0; --i) {
194030391Skarels 		    blitc(unit, ' ');
194130391Skarels 		}
194230391Skarels 		return(0);
194330391Skarels 
194430391Skarels 	    case '\n':			/* line feed char */
194530391Skarels 
194630391Skarels 		if ((cursor[unit].y += CHAR_HEIGHT) > (863 - CHAR_HEIGHT)) {
194730391Skarels 		    if (qdflags[unit].inuse & GRAPHIC_DEV) {
194830391Skarels 			cursor[unit].y = 0;
194930391Skarels 		    } else {
195030391Skarels 			cursor[unit].y -= CHAR_HEIGHT;
195130391Skarels 			scroll_up(adder);
195230391Skarels 		    }
195330391Skarels 		}
195430391Skarels 		dga->y_cursor = TRANY(cursor[unit].y);
195530391Skarels 		return(0);
195630391Skarels 
195730391Skarels 	    case '\b':			/* backspace char */
195830391Skarels 		if (cursor[unit].x > 0) {
195930391Skarels 		    cursor[unit].x -= CHAR_WIDTH;
196030391Skarels 		    dga->x_cursor = TRANX(cursor[unit].x);
196130391Skarels 		}
196230391Skarels 		return(0);
196330391Skarels 
1964*34511Smarc 	    case CTRL('k'):		/* cursor up */
196532012Smarc 		if (cursor[unit].y > 0) {
196632012Smarc 			cursor[unit].y -= CHAR_HEIGHT;
196732012Smarc 			dga->y_cursor = TRANY(cursor[unit].y);
196832012Smarc 		}
196932012Smarc 		return(0);
197032012Smarc 
1971*34511Smarc 	    case CTRL('^'):		/* home cursor */
197232012Smarc 		cursor[unit].x = 0;
197332012Smarc 		dga->x_cursor = TRANX(cursor[unit].x);
197432012Smarc 		cursor[unit].y = 0;
197532012Smarc 		dga->y_cursor = TRANY(cursor[unit].y);
197632012Smarc 		return(0);
197732012Smarc 
1978*34511Smarc 	    case CTRL('l'):		/* cursor right */
197932012Smarc 		if (cursor[unit].x < 1023 - CHAR_WIDTH) {
198032012Smarc 			cursor[unit].x += CHAR_WIDTH;
198132012Smarc 			dga->x_cursor = TRANX(cursor[unit].x);
198232012Smarc 		}
198332012Smarc 		return(0);
198432012Smarc 
1985*34511Smarc 	    case CTRL('z'):		/* clear screen */
198632012Smarc 		setup_dragon(unit);
198732012Smarc 		clear_qd_screen(unit);
198832012Smarc 		/* and home cursor - termcap seems to assume this */
198932012Smarc 		cursor[unit].x = 0;
199032012Smarc 		dga->x_cursor = TRANX(cursor[unit].x);
199132012Smarc 		cursor[unit].y = 0;
199232012Smarc 		dga->y_cursor = TRANY(cursor[unit].y);
199332012Smarc 		return(0);
199432012Smarc 
199532012Smarc 	    case '\033':		/* start escape sequence */
199632012Smarc 		inescape[unit] = 1;
199732012Smarc 		return(0);
199832012Smarc 
199930391Skarels 	    default:
200030391Skarels 		if (chr < ' ' || chr > '~')
200130391Skarels 		    return(0);
200230391Skarels 	}
200330391Skarels 
200432012Smarc 	/* setup VIPER operand control registers  */
200530391Skarels 
200630391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0001);  /* select plane #0 */
200730391Skarels 	write_ID(adder, SRC1_OCR_B,
200830391Skarels 			EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY);
200930391Skarels 
201030391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x00FE);  /* select other planes */
201130391Skarels 	write_ID(adder, SRC1_OCR_B,
201230391Skarels 			EXT_SOURCE | INT_NONE | NO_ID | BAR_SHIFT_DELAY);
201330391Skarels 
201430391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x00FF);  /* select all planes */
201530391Skarels 	write_ID(adder, DST_OCR_B,
201630391Skarels 			EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
201730391Skarels 
201830391Skarels 	write_ID(adder, MASK_1, 0xFFFF);
201930391Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 1);
202030391Skarels 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
202130391Skarels 
202232012Smarc 	/* load DESTINATION origin and vectors  */
202330391Skarels 
202430391Skarels 	adder->fast_dest_dy = 0;
202530391Skarels 	adder->slow_dest_dx = 0;
202630391Skarels 	adder->error_1 = 0;
202730391Skarels 	adder->error_2 = 0;
202830391Skarels 
202930391Skarels 	adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL;
203030391Skarels 
203130391Skarels 	wait_status(adder, RASTEROP_COMPLETE);
203230391Skarels 
203330391Skarels 	adder->destination_x = cursor[unit].x;
203430391Skarels 	adder->fast_dest_dx = CHAR_WIDTH;
203530391Skarels 
203630391Skarels 	adder->destination_y = cursor[unit].y;
203730391Skarels 	adder->slow_dest_dy = CHAR_HEIGHT;
203830391Skarels 
203932012Smarc 	/* load SOURCE origin and vectors  */
204030391Skarels 
204130391Skarels 	adder->source_1_x = FONT_X + ((chr - ' ') * CHAR_WIDTH);
204230391Skarels 	adder->source_1_y = FONT_Y;
204330391Skarels 
204430391Skarels 	adder->source_1_dx = CHAR_WIDTH;
204530391Skarels 	adder->source_1_dy = CHAR_HEIGHT;
204630391Skarels 
204730391Skarels 	write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
204830391Skarels 	adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE;
204930391Skarels 
205032012Smarc 	/* update console cursor coordinates */
205130391Skarels 
205230391Skarels 	cursor[unit].x += CHAR_WIDTH;
205330391Skarels 	dga->x_cursor = TRANX(cursor[unit].x);
205430391Skarels 
205532012Smarc 	/* auto-wrap margin */
205630391Skarels 	if (cursor[unit].x > (1024 - CHAR_WIDTH)) {
205730391Skarels 	    blitc(unit, '\r');
205830391Skarels 	    blitc(unit, '\n');
205930391Skarels 	}
206030391Skarels 
206130391Skarels } /* blitc */
206230391Skarels 
206330391Skarels qdreset(){}
206430391Skarels qd_init(){}
206530391Skarels 
206630391Skarels /******************************************************************
206730391Skarels *
206830391Skarels *	INTERRUPT SERVICE ROUTINES START HERE:
206930391Skarels *
207030391Skarels ******************************************************************/
207130391Skarels 
207230391Skarels /*****************************************************************
207330391Skarels *
207430391Skarels *	qddint()... service "DMA DONE" interrupt condition
207530391Skarels *
207630391Skarels *****************************************************************/
207730391Skarels 
207830391Skarels qddint(qd)
207930391Skarels int qd;
208030391Skarels {
208130391Skarels 	register struct DMAreq_header *header;
208230391Skarels 	register struct DMAreq *request;
208330391Skarels 	register struct dga *dga;
208430391Skarels 	struct adder *adder;
208530391Skarels 
208630391Skarels 	int cookie;			/* DMA adrs for QDSS */
208730391Skarels 	int i;
208830391Skarels 
208930391Skarels 	spl4(); 			/* allow interval timer in */
209030391Skarels 
209132012Smarc 	/*
209232012Smarc 	* init pointers
209332012Smarc 	*/
209430391Skarels 
209530391Skarels 	header = DMAheader[qd]; 	    /* register for optimization */
209630391Skarels 	dga = (struct dga *) qdmap[qd].dga;
209730391Skarels 	adder = (struct adder *) qdmap[qd].adder;
209830391Skarels 
209932012Smarc 	/*
210032012Smarc 	* if this interrupt flagged as bogus for interrupt flushing purposes..
210132012Smarc 	*/
210230391Skarels 
210330391Skarels 	if (DMA_ISIGNORE(header)) {
210430391Skarels 	    DMA_CLRIGNORE(header);
210530391Skarels 	    return;
210630391Skarels 	}
210730391Skarels 
210830391Skarels /*----------------------------------------------------
210930391Skarels * dump a DMA hardware error message if appropriate */
211030391Skarels 
211130391Skarels 	if (dga->csr & DMA_ERR) {
211230391Skarels 
211330391Skarels 	    if (dga->csr & PARITY_ERR)
2114*34511Smarc 		printf("qd%d: qddint: DMA hardware parity fault.\n", qd);
211530391Skarels 
211630391Skarels 	    if (dga->csr & BUS_ERR)
2117*34511Smarc 		printf("qd%d: qddint: DMA hardware bus error.\n", qd);
211830391Skarels 	}
211930391Skarels 
212030391Skarels /*----------------------------------------
212130391Skarels * if this was a DMA from user space... */
212230391Skarels 
212330391Skarels 	if (qdflags[qd].user_dma) {
212430391Skarels 	    qdflags[qd].user_dma = 0;
212530391Skarels 	    wakeup((caddr_t)&qdflags[qd].user_dma);
212630391Skarels 	    return;
212730391Skarels 	}
212830391Skarels 
212930391Skarels /*------------------------------------------------------------------------
213030391Skarels * if we're doing DMA request queue services, field the error condition */
213130391Skarels 
213230391Skarels 	if (dga->csr & DMA_ERR) {
213330391Skarels 
213430391Skarels 	    dga->csr &= ~0x0600;		/* halt DMA (reset fifo) */
213530391Skarels 	    dga->csr |= DMA_ERR;		/* clear error condition */
213630391Skarels 	    adder->command = CANCEL;		/* cancel adder activity */
213730391Skarels 
213830391Skarels 	    DMA_SETERROR(header);	/* flag error in header status word */
213930391Skarels 	    DMA_CLRACTIVE(header);
214030391Skarels 	    header->DMAreq[header->oldest].DMAdone |= HARD_ERROR;
214130391Skarels 	    header->newest = header->oldest;
214230391Skarels 	    header->used = 0;
214330391Skarels 
214430391Skarels 	    if (rsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
214530391Skarels 		selwakeup(rsel[qd], 0);
214630391Skarels 		rsel[qd] = 0;
214730391Skarels 		qdflags[qd].selmask &= ~SEL_WRITE;
214830391Skarels 	    }
214930391Skarels 
215030391Skarels 	    if (dga->bytcnt_lo != 0) {
215130391Skarels 		dga->bytcnt_lo = 0;
215230391Skarels 		dga->bytcnt_hi = 0;
215330391Skarels 		DMA_SETIGNORE(header);
215430391Skarels 	    }
215530391Skarels 
215630391Skarels 	    return;
215730391Skarels 	}
215830391Skarels 
215930391Skarels /*----------------------------------------------------------------------------
216030391Skarels * if the DMA request queue is now becoming non-full, wakeup "select" client */
216130391Skarels 
216230391Skarels 	if (DMA_ISFULL(header)) {
216330391Skarels 
216430391Skarels 	    if (rsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
216530391Skarels 		selwakeup(rsel[qd], 0);
216630391Skarels 		rsel[qd] = 0;
216730391Skarels 		qdflags[qd].selmask &= ~SEL_WRITE;
216830391Skarels 	    }
216930391Skarels 	}
217030391Skarels 
217130391Skarels 	header->DMAreq[header->oldest].DMAdone |= REQUEST_DONE;
217230391Skarels 
217330391Skarels 	if (DMA_ISEMPTY(header)) {
2174*34511Smarc 	    printf("qd%d: qddint: unexpected interrupt\n", qd);
217530391Skarels 	    return;
217630391Skarels 	}
217730391Skarels 
217830391Skarels 	DMA_GETEND(header);	/* update request queue indices */
217930391Skarels 
218030391Skarels /*------------------------------------------------------------
218130391Skarels * if no more DMA pending, wake up "select" client and exit */
218230391Skarels 
218330391Skarels 	if (DMA_ISEMPTY(header)) {
218430391Skarels 
218530391Skarels 	    if (rsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
218630391Skarels 		selwakeup(rsel[qd], 0);
218730391Skarels 		rsel[qd] = 0;
218830391Skarels 		qdflags[qd].selmask &= ~SEL_WRITE;
218930391Skarels 	    }
219030391Skarels 
219130391Skarels 	    DMA_CLRACTIVE(header);  /* flag DMA done */
219230391Skarels 	    return;
219330391Skarels 	}
219430391Skarels 
219530391Skarels /*---------------------------
219630391Skarels * initiate next DMA xfer  */
219730391Skarels 
219830391Skarels 	request = DMA_GETBEGIN(header);
219930391Skarels 
220030391Skarels 	switch (request->DMAtype) {
220130391Skarels 
220230391Skarels 	    case DISPLIST:
220330391Skarels 		dga->csr |= DL_ENB;
220430391Skarels 		break;
220530391Skarels 
220630391Skarels 	    case PTOB:
220730391Skarels 		dga->csr |= PTOB_ENB;
220830391Skarels 		break;
220930391Skarels 
221030391Skarels 	    case BTOP:
221130391Skarels 		dga->csr |= BTOP_ENB;
221230391Skarels 		break;
221330391Skarels 
221430391Skarels 	    default:
2215*34511Smarc 		printf("qd%d: qddint: illegal DMAtype parameter.\n", qd);
221630391Skarels 		DMA_CLRACTIVE(header);	/* flag DMA done */
221730391Skarels 		return;
221830391Skarels 	}
221930391Skarels 
222030391Skarels 	if (request->DMAdone & COUNT_ZERO) {
222130391Skarels 	    dga->csr &= ~SET_DONE_FIFO;
222230391Skarels 	} else if (request->DMAdone & FIFO_EMPTY) {
222330391Skarels 	    dga->csr |= SET_DONE_FIFO;
222430391Skarels 	}
222530391Skarels 
222630391Skarels 	if (request->DMAdone & WORD_PACK)
222730391Skarels 	    dga->csr &= ~BYTE_DMA;
222830391Skarels 	else if (request->DMAdone & BYTE_PACK)
222930391Skarels 	    dga->csr |= BYTE_DMA;
223030391Skarels 
223130391Skarels 	dga->csr |= DMA_IE;
223230391Skarels 
223330391Skarels 	cookie = ((int)request->bufp - (int)header) + (int)header->QBAreg;
223430391Skarels 
223530391Skarels 	dga->adrs_lo = (short) cookie;
223630391Skarels 	dga->adrs_hi = (short) (cookie >> 16);
223730391Skarels 
223830391Skarels 	dga->bytcnt_lo = (short) request->length;
223930391Skarels 	dga->bytcnt_hi = (short) (request->length >> 16);
224030391Skarels 
224130391Skarels 	return;
224230391Skarels }
224330391Skarels 
224430391Skarels /*****************************************************************
224530391Skarels *
224630391Skarels *	qdaint()... ADDER interrupt service
224730391Skarels *
224830391Skarels *****************************************************************/
224930391Skarels 
225030391Skarels qdaint(qd)
225130391Skarels register int qd;
225230391Skarels {
225330391Skarels 	register struct adder *adder;
225430391Skarels 	struct color_buf *cbuf;
225530391Skarels 
225630391Skarels 	short stat;
225730391Skarels 	int i;
225830391Skarels 	register struct rgb *rgbp;
225930391Skarels 	register short *red;
226030391Skarels 	register short *green;
226130391Skarels 	register short *blue;
226230391Skarels 
226330391Skarels 	spl4(); 			/* allow interval timer in */
226430391Skarels 
226530391Skarels 	adder = (struct adder *) qdmap[qd].adder;
226630391Skarels 
226730391Skarels /*------------------------------------------------------------------------
226830391Skarels * service the vertical blank interrupt (VSYNC bit) by loading any pending
226930391Skarels * color map load request  */
227030391Skarels 
227130391Skarels 	if (adder->status & VSYNC) {
227230391Skarels 	    adder->status &= ~VSYNC;		/* clear the interrupt */
227330391Skarels 
227430391Skarels 	    cbuf = color_buf[qd];
227530391Skarels 	    if (cbuf->status & LOAD_COLOR_MAP) {
227630391Skarels 
227730391Skarels 		red = (short *) qdmap[qd].red;
227830391Skarels 		green = (short *) qdmap[qd].green;
227930391Skarels 		blue = (short *) qdmap[qd].blue;
228030391Skarels 
228130391Skarels 		for (i = cbuf->count, rgbp = cbuf->rgb; --i >= 0; rgbp++) {
228230391Skarels 
228330391Skarels 		    red[rgbp->offset] = (short) rgbp->red;
228430391Skarels 		    green[rgbp->offset] = (short) rgbp->green;
228530391Skarels 		    blue[rgbp->offset] = (short) rgbp->blue;
228630391Skarels 		}
228730391Skarels 
228830391Skarels 		cbuf->status &= ~LOAD_COLOR_MAP;
228930391Skarels 	    }
229030391Skarels 	}
229130391Skarels 
229230391Skarels /*-------------------------------------------------
229330391Skarels * service the scroll interrupt (FRAME_SYNC bit) */
229430391Skarels 
229530391Skarels 	if (adder->status & FRAME_SYNC) {
229630391Skarels 	    adder->status &= ~FRAME_SYNC;	/* clear the interrupt */
229730391Skarels 
229830391Skarels 	    if (scroll[qd]->status & LOAD_REGS) {
229930391Skarels 
230030391Skarels 		for ( i = 1000, adder->status = 0
230130391Skarels 		    ; i > 0  &&  !((stat = adder->status) & ID_SCROLL_READY)
230230391Skarels 		    ; --i);
230330391Skarels 
230430391Skarels 		if (i == 0) {
2305*34511Smarc 		    printf("qd%d: qdaint: timeout on ID_SCROLL_READY\n", qd);
230630391Skarels 		    return;
230730391Skarels 		}
230830391Skarels 
230930391Skarels 		adder->ID_scroll_data = scroll[qd]->viper_constant;
231030391Skarels 		adder->ID_scroll_command = ID_LOAD | SCROLL_CONSTANT;
231130391Skarels 
231230391Skarels 		adder->y_scroll_constant = scroll[qd]->y_scroll_constant;
231330391Skarels 		adder->y_offset_pending = scroll[qd]->y_offset;
231430391Skarels 
231530391Skarels 		if (scroll[qd]->status & LOAD_INDEX) {
231630391Skarels 
231730391Skarels 		    adder->x_index_pending = scroll[qd]->x_index_pending;
231830391Skarels 		    adder->y_index_pending = scroll[qd]->y_index_pending;
231930391Skarels 		}
232030391Skarels 
232130391Skarels 	    scroll[qd]->status = 0x00;
232230391Skarels 	    }
232330391Skarels 	}
232430391Skarels }
232530391Skarels 
232630391Skarels /*****************************************************************
232730391Skarels *
232830391Skarels *	qdiint()... DUART input interrupt service routine
232930391Skarels *
233030391Skarels *****************************************************************/
233130391Skarels 
233230391Skarels qdiint(qd)
233330391Skarels register int qd;
233430391Skarels {
233530391Skarels 	register struct _vs_event *event;
233630391Skarels 	register struct qdinput *eqh;
233730391Skarels 
233830391Skarels 	struct dga *dga;
233930391Skarels 	struct duart *duart;
234030391Skarels 	struct mouse_report *new_rep;
234130391Skarels 
234230391Skarels 	struct uba_device *ui;
234330391Skarels 	struct tty *tp;
234430391Skarels 
234530391Skarels 	char chr;
234630391Skarels 	int i,j;
234730391Skarels 	int k,l;
234830391Skarels 
234930391Skarels 	u_short status;
235030391Skarels 	u_short data;
235130391Skarels 	u_short key;
235230391Skarels 
235330391Skarels 	char do_wakeup = 0;		/* flag to do a select wakeup call */
235430391Skarels 	char a, b, c;			/* mouse button test variables */
235530391Skarels 
235630391Skarels 	spl4(); 			/* allow interval timer in */
235730391Skarels 
235830391Skarels 	eqh = eq_header[qd];		/* optimized as a register */
235930391Skarels 	new_rep = &current_rep[qd];
236030391Skarels 	duart = (struct duart *) qdmap[qd].duart;
236130391Skarels 
236230391Skarels /*-----------------------------------------
236330391Skarels * if the graphic device is turned on..	*/
236430391Skarels 
236530391Skarels 	if (qdflags[qd].inuse & GRAPHIC_DEV) {
236630391Skarels 
236730391Skarels 	    /*---------------
236830391Skarels 	    * empty DUART */
236930391Skarels 
237030391Skarels 	    while ((status = duart->statusA) & RCV_RDY	||
237130391Skarels 		   (status = duart->statusB) & RCV_RDY) {
237230391Skarels 
237330391Skarels 		/*---------------------------------
237430391Skarels 		* pick up LK-201 input (if any) */
237530391Skarels 
237630391Skarels 		if ((status = duart->statusA) & RCV_RDY) {
237730391Skarels 
237830391Skarels 		    /* if error condition, then reset it */
237930391Skarels 
238030391Skarels 		    if ((status = duart->statusA) & 0x70) {
238130391Skarels 			duart->cmdA = 0x40;
238230391Skarels 			continue;
238330391Skarels 		    }
238430391Skarels 
238530391Skarels 		    /* event queue full now? (overflow condition) */
238630391Skarels 
238730391Skarels 		    if (ISFULL(eqh) == TRUE) {
2388*34511Smarc 			printf("qd%d: qdiint: event queue overflow\n", qd);
238930391Skarels 			break;
239030391Skarels 		    }
239130391Skarels 
239230391Skarels 		    /*--------------------------------------
239330391Skarels 		    * Check for various keyboard errors  */
239430391Skarels 
239530391Skarels 		    key = duart->dataA & 0xFF;
239630391Skarels 
239730391Skarels 		    if( key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
239830391Skarels 			key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
2399*34511Smarc 			printf("qd%d: qdiint: keyboard error, code = %x\n",
2400*34511Smarc 				qd, key);
240130391Skarels 			return(0);
240230391Skarels 		    }
240330391Skarels 
240430391Skarels 		    if (key < LK_LOWEST)
240530391Skarels 			return(0);
240630391Skarels 
240730391Skarels 		    ++do_wakeup;	/* request a select wakeup call */
240830391Skarels 
240930391Skarels 		    event = PUTBEGIN(eqh);
241030391Skarels 		    PUTEND(eqh);
241130391Skarels 
241230391Skarels 		    event->vse_key = key;
241330391Skarels 		    event->vse_key &= 0x00FF;
241430391Skarels 		    event->vse_x = eqh->curs_pos.x;
241530391Skarels 		    event->vse_y = eqh->curs_pos.y;
241630391Skarels 		    event->vse_time = TOY;
241730391Skarels 		    event->vse_type = VSE_BUTTON;
241830391Skarels 		    event->vse_direction = VSE_KBTRAW;
241930391Skarels 		    event->vse_device = VSE_DKB;
242030391Skarels 		}
242130391Skarels 
242230391Skarels 		/*-------------------------------------
242330391Skarels 		* pick up the mouse input (if any)  */
242430391Skarels 
242530391Skarels 		if ((status = duart->statusB) & RCV_RDY  &&
242630391Skarels 		     qdflags[qd].pntr_id == MOUSE_ID) {
242730391Skarels 
242830391Skarels 		    if (status & 0x70) {
242930391Skarels 			duart->cmdB = 0x40;
243030391Skarels 			continue;
243130391Skarels 		    }
243230391Skarels 
243330391Skarels 		    /* event queue full now? (overflow condition) */
243430391Skarels 
243530391Skarels 		    if (ISFULL(eqh) == TRUE) {
2436*34511Smarc 			printf("qd%d: qdiint: event queue overflow\n", qd);
243730391Skarels 			break;
243830391Skarels 		    }
243930391Skarels 
244030391Skarels 		    data = duart->dataB;      /* get report byte */
244130391Skarels 		    ++new_rep->bytcnt;	      /* bump report byte count */
244230391Skarels 
244330391Skarels 		    /*---------------------------
244430391Skarels 		    * if 1st byte of report.. */
244530391Skarels 
244630391Skarels 		    if ( data & START_FRAME) {
244730391Skarels 			new_rep->state = data;
244830391Skarels 			if (new_rep->bytcnt > 1) {
244930391Skarels 			    new_rep->bytcnt = 1;    /* start of new frame */
245030391Skarels 			    continue;		    /* ..continue looking */
245130391Skarels 			}
245230391Skarels 		    }
245330391Skarels 
245430391Skarels 		    /*---------------------------
245530391Skarels 		    * if 2nd byte of report.. */
245630391Skarels 
245730391Skarels 		    else if (new_rep->bytcnt == 2) {
245830391Skarels 			new_rep->dx = data & 0x00FF;
245930391Skarels 		    }
246030391Skarels 
246130391Skarels 		    /*-------------------------------------------------
246230391Skarels 		    * if 3rd byte of report, load input event queue */
246330391Skarels 
246430391Skarels 		    else if (new_rep->bytcnt == 3) {
246530391Skarels 
246630391Skarels 			new_rep->dy = data & 0x00FF;
246730391Skarels 			new_rep->bytcnt = 0;
246830391Skarels 
246930391Skarels 			/*-----------------------------------
247030391Skarels 			* if mouse position has changed.. */
247130391Skarels 
247230391Skarels 			if (new_rep->dx != 0  ||  new_rep->dy != 0) {
247330391Skarels 
247430391Skarels 			    /*---------------------------------------------
247530391Skarels 			    * calculate acceleration factor, if needed	*/
247630391Skarels 
247730391Skarels 			    if (qdflags[qd].curs_acc > ACC_OFF) {
247830391Skarels 
247930391Skarels 				if (qdflags[qd].curs_thr <= new_rep->dx)
248030391Skarels 				    new_rep->dx +=
248130391Skarels 					(new_rep->dx - qdflags[qd].curs_thr)
248230391Skarels 					 * qdflags[qd].curs_acc;
248330391Skarels 
248430391Skarels 				if (qdflags[qd].curs_thr <= new_rep->dy)
248530391Skarels 				    new_rep->dy +=
248630391Skarels 					(new_rep->dy - qdflags[qd].curs_thr)
248730391Skarels 					 * qdflags[qd].curs_acc;
248830391Skarels 			    }
248930391Skarels 
249030391Skarels 			    /*-------------------------------------
249130391Skarels 			    * update cursor position coordinates */
249230391Skarels 
249330391Skarels 			    if (new_rep->state & X_SIGN) {
249430391Skarels 				eqh->curs_pos.x += new_rep->dx;
249530391Skarels 				if (eqh->curs_pos.x > 1023)
249630391Skarels 				    eqh->curs_pos.x = 1023;
249730391Skarels 			    }
249830391Skarels 			    else {
249930391Skarels 				eqh->curs_pos.x -= new_rep->dx;
250030391Skarels 				if (eqh->curs_pos.x < -15)
250130391Skarels 				    eqh->curs_pos.x = -15;
250230391Skarels 			    }
250330391Skarels 
250430391Skarels 			    if (new_rep->state & Y_SIGN) {
250530391Skarels 				 eqh->curs_pos.y -= new_rep->dy;
250630391Skarels 				 if (eqh->curs_pos.y < -15)
250730391Skarels 				     eqh->curs_pos.y = -15;
250830391Skarels 			    }
250930391Skarels 			    else {
251030391Skarels 				eqh->curs_pos.y += new_rep->dy;
251130391Skarels 				if (eqh->curs_pos.y > 863)
251230391Skarels 				    eqh->curs_pos.y = 863;
251330391Skarels 			    }
251430391Skarels 
251530391Skarels 			    /*---------------------------------
251630391Skarels 			    * update cursor screen position */
251730391Skarels 
251830391Skarels 			    dga = (struct dga *) qdmap[qd].dga;
251930391Skarels 			    dga->x_cursor = TRANX(eqh->curs_pos.x);
252030391Skarels 			    dga->y_cursor = TRANY(eqh->curs_pos.y);
252130391Skarels 
252230391Skarels 			    /*--------------------------------------------
252330391Skarels 			    * if cursor is in the box, no event report */
252430391Skarels 
252530391Skarels 			    if (eqh->curs_pos.x <= eqh->curs_box.right	&&
252630391Skarels 				eqh->curs_pos.x >= eqh->curs_box.left  &&
252730391Skarels 				eqh->curs_pos.y >= eqh->curs_box.top  &&
252830391Skarels 				eqh->curs_pos.y <= eqh->curs_box.bottom ) {
252930391Skarels 				    goto GET_MBUTTON;
253030391Skarels 			    }
253130391Skarels 
253230391Skarels 			    /*---------------------------------
253330391Skarels 			    * report the mouse motion event */
253430391Skarels 
253530391Skarels 			    event = PUTBEGIN(eqh);
253630391Skarels 			    PUTEND(eqh);
253730391Skarels 
253830391Skarels 			    ++do_wakeup;   /* request a select wakeup call */
253930391Skarels 
254030391Skarels 			    event->vse_x = eqh->curs_pos.x;
254130391Skarels 			    event->vse_y = eqh->curs_pos.y;
254230391Skarels 
254330391Skarels 			    event->vse_device = VSE_MOUSE;  /* mouse */
254430391Skarels 			    event->vse_type = VSE_MMOTION;  /* pos changed */
254530391Skarels 			    event->vse_key = 0;
254630391Skarels 			    event->vse_direction = 0;
254730391Skarels 			    event->vse_time = TOY;	/* time stamp */
254830391Skarels 			}
254930391Skarels 
255030391Skarels GET_MBUTTON:
255130391Skarels 			/*-------------------------------
255230391Skarels 			* if button state has changed */
255330391Skarels 
255430391Skarels 			a = new_rep->state & 0x07;    /*mask nonbutton bits */
255530391Skarels 			b = last_rep[qd].state & 0x07;
255630391Skarels 
255730391Skarels 			if (a ^ b) {
255830391Skarels 
255930391Skarels 			    for ( c = 1;  c < 8; c <<= 1) {
256030391Skarels 
256130391Skarels 				if (!( c & (a ^ b))) /* this button change? */
256230391Skarels 				    continue;
256330391Skarels 
256430391Skarels 				/* event queue full? (overflow condition) */
256530391Skarels 
256630391Skarels 				if (ISFULL(eqh) == TRUE) {
2567*34511Smarc 				    printf("qd%d: qdiint: event queue overflow\n", qd);
256830391Skarels 				    break;
256930391Skarels 				}
257030391Skarels 
257130391Skarels 				event = PUTBEGIN(eqh);	/* get new event */
257230391Skarels 				PUTEND(eqh);
257330391Skarels 
257430391Skarels 				++do_wakeup;   /* request select wakeup */
257530391Skarels 
257630391Skarels 				event->vse_x = eqh->curs_pos.x;
257730391Skarels 				event->vse_y = eqh->curs_pos.y;
257830391Skarels 
257930391Skarels 				event->vse_device = VSE_MOUSE;	/* mouse */
258030391Skarels 				event->vse_type = VSE_BUTTON; /* new button */
258130391Skarels 				event->vse_time = TOY;	      /* time stamp */
258230391Skarels 
258330391Skarels 				/* flag changed button and if up or down */
258430391Skarels 
258530391Skarels 				if (c == RIGHT_BUTTON)
258630391Skarels 				    event->vse_key = VSE_RIGHT_BUTTON;
258730391Skarels 				else if (c == MIDDLE_BUTTON)
258830391Skarels 				    event->vse_key = VSE_MIDDLE_BUTTON;
258930391Skarels 				else if (c == LEFT_BUTTON)
259030391Skarels 				    event->vse_key = VSE_LEFT_BUTTON;
259130391Skarels 
259230391Skarels 				/* set bit = button depressed */
259330391Skarels 
259430391Skarels 				if (c & a)
259530391Skarels 				    event->vse_direction = VSE_KBTDOWN;
259630391Skarels 				else
259730391Skarels 				    event->vse_direction = VSE_KBTUP;
259830391Skarels 			    }
259930391Skarels 			}
260030391Skarels 
260130391Skarels 			/* refresh last report */
260230391Skarels 
260330391Skarels 			last_rep[qd] = current_rep[qd];
260430391Skarels 
260530391Skarels 		    }  /* get last byte of report */
260630391Skarels 		} /* pickup mouse input */
260730391Skarels 
260830391Skarels 		/*--------------------------------
260930391Skarels 		* pickup tablet input, if any  */
261030391Skarels 
261130391Skarels 		else if ((status = duart->statusB) & RCV_RDY  &&
261230391Skarels 			 qdflags[qd].pntr_id == TABLET_ID) {
261330391Skarels 
261430391Skarels 		    if (status & 0x70) {
261530391Skarels 			duart->cmdB = 0x40;
261630391Skarels 			continue;
261730391Skarels 		    }
261830391Skarels 
261930391Skarels 		    /* event queue full now? (overflow condition) */
262030391Skarels 
262130391Skarels 		    if (ISFULL(eqh) == TRUE) {
2622*34511Smarc 			printf("qd%d: qdiint: event queue overflow\n", qd);
262330391Skarels 			break;
262430391Skarels 		    }
262530391Skarels 
262630391Skarels 		    data = duart->dataB;      /* get report byte */
262730391Skarels 		    ++new_rep->bytcnt;	      /* bump report byte count */
262830391Skarels 
262930391Skarels 		    /*---------------------------
263030391Skarels 		    * if 1st byte of report.. */
263130391Skarels 
263230391Skarels 		    if (data & START_FRAME) {
263330391Skarels 			new_rep->state = data;
263430391Skarels 			if (new_rep->bytcnt > 1) {
263530391Skarels 			    new_rep->bytcnt = 1;    /* start of new frame */
263630391Skarels 			    continue;		    /* ..continue looking */
263730391Skarels 			}
263830391Skarels 		    }
263930391Skarels 
264030391Skarels 		    /*---------------------------
264130391Skarels 		    * if 2nd byte of report.. */
264230391Skarels 
264330391Skarels 		    else if (new_rep->bytcnt == 2) {
264430391Skarels 			new_rep->dx = data & 0x3F;
264530391Skarels 		    }
264630391Skarels 
264730391Skarels 		    /*---------------------------
264830391Skarels 		    * if 3rd byte of report.. */
264930391Skarels 
265030391Skarels 		    else if (new_rep->bytcnt == 3) {
265130391Skarels 			new_rep->dx |= (data & 0x3F) << 6;
265230391Skarels 		    }
265330391Skarels 
265430391Skarels 		    /*---------------------------
265530391Skarels 		    * if 4th byte of report.. */
265630391Skarels 
265730391Skarels 		    else if (new_rep->bytcnt == 4) {
265830391Skarels 			new_rep->dy = data & 0x3F;
265930391Skarels 		    }
266030391Skarels 
266130391Skarels 		    /*-------------------------------------------------
266230391Skarels 		    * if 5th byte of report, load input event queue */
266330391Skarels 
266430391Skarels 		    else if (new_rep->bytcnt == 5) {
266530391Skarels 
266630391Skarels 			new_rep->dy |= (data & 0x3F) << 6;
266730391Skarels 			new_rep->bytcnt = 0;
266830391Skarels 
266930391Skarels 			/*-------------------------------------
267030391Skarels 			* update cursor position coordinates */
267130391Skarels 
267230391Skarels 			new_rep->dx /= qdflags[qd].tab_res;
267330391Skarels 			new_rep->dy = (2200 - new_rep->dy)
267430391Skarels 				      / qdflags[qd].tab_res;
267530391Skarels 
267630391Skarels 			if (new_rep->dx > 1023) {
267730391Skarels 			    new_rep->dx = 1023;
267830391Skarels 			}
267930391Skarels 			if (new_rep->dy > 863) {
268030391Skarels 			    new_rep->dy = 863;
268130391Skarels 			}
268230391Skarels 
268330391Skarels 			/*
268430391Skarels 			 * report an event if the puck/stylus has moved
268530391Skarels 			 */
268630391Skarels 
268730391Skarels 			if (eqh->curs_pos.x != new_rep->dx ||
268830391Skarels 			    eqh->curs_pos.y != new_rep->dy) {
268930391Skarels 
269030391Skarels 			    eqh->curs_pos.x = new_rep->dx;
269130391Skarels 			    eqh->curs_pos.y = new_rep->dy;
269230391Skarels 
269330391Skarels 			    /*---------------------------------
269430391Skarels 			    * update cursor screen position */
269530391Skarels 
269630391Skarels 			    dga = (struct dga *) qdmap[qd].dga;
269730391Skarels 			    dga->x_cursor = TRANX(eqh->curs_pos.x);
269830391Skarels 			    dga->y_cursor = TRANY(eqh->curs_pos.y);
269930391Skarels 
270030391Skarels 			    /*
270130391Skarels 			     * if cursor is in the box, no event report
270230391Skarels 			     */
270330391Skarels 
270430391Skarels 			    if (eqh->curs_pos.x <= eqh->curs_box.right	&&
270530391Skarels 				eqh->curs_pos.x >= eqh->curs_box.left  &&
270630391Skarels 				eqh->curs_pos.y >= eqh->curs_box.top  &&
270730391Skarels 				eqh->curs_pos.y <= eqh->curs_box.bottom ) {
270830391Skarels 				goto GET_TBUTTON;
270930391Skarels 			    }
271030391Skarels 
271130391Skarels 			    /*---------------------------------
271230391Skarels 			    * report the tablet motion event */
271330391Skarels 
271430391Skarels 			    event = PUTBEGIN(eqh);
271530391Skarels 			    PUTEND(eqh);
271630391Skarels 
271730391Skarels 			    ++do_wakeup;   /* request a select wakeup call */
271830391Skarels 
271930391Skarels 			    event->vse_x = eqh->curs_pos.x;
272030391Skarels 			    event->vse_y = eqh->curs_pos.y;
272130391Skarels 
272230391Skarels 			    event->vse_device = VSE_TABLET;  /* tablet */
272330391Skarels 			    /*
272430391Skarels 			     * right now, X handles tablet motion the same
272530391Skarels 			     * as mouse motion
272630391Skarels 			     */
272730391Skarels 			    event->vse_type = VSE_MMOTION;   /* pos changed */
272830391Skarels 			    event->vse_key = 0;
272930391Skarels 			    event->vse_direction = 0;
273030391Skarels 			    event->vse_time = TOY;	/* time stamp */
273130391Skarels 			}
273230391Skarels GET_TBUTTON:
273330391Skarels 			/*-------------------------------
273430391Skarels 			* if button state has changed */
273530391Skarels 
273630391Skarels 			a = new_rep->state & 0x1E;   /* mask nonbutton bits */
273730391Skarels 			b = last_rep[qd].state & 0x1E;
273830391Skarels 
273930391Skarels 			if (a ^ b) {
274030391Skarels 
274130391Skarels 			    /* event queue full now? (overflow condition) */
274230391Skarels 
274330391Skarels 			    if (ISFULL(eqh) == TRUE) {
2744*34511Smarc 				printf("qd%d: qdiint: event queue overflow\n",
2745*34511Smarc 					qd);
274630391Skarels 				break;
274730391Skarels 			    }
274830391Skarels 
274930391Skarels 			    event = PUTBEGIN(eqh);  /* get new event */
275030391Skarels 			    PUTEND(eqh);
275130391Skarels 
275230391Skarels 			    ++do_wakeup;   /* request a select wakeup call */
275330391Skarels 
275430391Skarels 			    event->vse_x = eqh->curs_pos.x;
275530391Skarels 			    event->vse_y = eqh->curs_pos.y;
275630391Skarels 
275730391Skarels 			    event->vse_device = VSE_TABLET;  /* tablet */
275830391Skarels 			    event->vse_type = VSE_BUTTON; /* button changed */
275930391Skarels 			    event->vse_time = TOY;	   /* time stamp */
276030391Skarels 
276130391Skarels 			    /* define the changed button and if up or down */
276230391Skarels 
276330391Skarels 			    for ( c = 1;  c <= 0x10; c <<= 1) {
276430391Skarels 				if (c & (a ^ b)) {
276530391Skarels 				    if (c == T_LEFT_BUTTON)
276630391Skarels 					event->vse_key = VSE_T_LEFT_BUTTON;
276730391Skarels 				    else if (c == T_FRONT_BUTTON)
276830391Skarels 					event->vse_key = VSE_T_FRONT_BUTTON;
276930391Skarels 				    else if (c == T_RIGHT_BUTTON)
277030391Skarels 					event->vse_key = VSE_T_RIGHT_BUTTON;
277130391Skarels 				    else if (c == T_BACK_BUTTON)
277230391Skarels 					event->vse_key = VSE_T_BACK_BUTTON;
277330391Skarels 				    break;
277430391Skarels 				}
277530391Skarels 			    }
277630391Skarels 
277730391Skarels 			    /* set bit = button depressed */
277830391Skarels 
277930391Skarels 			    if (c & a)
278030391Skarels 				event->vse_direction = VSE_KBTDOWN;
278130391Skarels 			    else
278230391Skarels 				event->vse_direction = VSE_KBTUP;
278330391Skarels 			}
278430391Skarels 
278530391Skarels 			/* refresh last report */
278630391Skarels 
278730391Skarels 			last_rep[qd] = current_rep[qd];
278830391Skarels 
278930391Skarels 		    } /* get last byte of report */
279030391Skarels 		} /* pick up tablet input */
279130391Skarels 
279230391Skarels 	    } /* while input available.. */
279330391Skarels 
279430391Skarels 	    /*---------------------
279530391Skarels 	    * do select wakeup	*/
279630391Skarels 
279730391Skarels 	    if (rsel[qd] && do_wakeup && qdflags[qd].selmask & SEL_READ) {
279830391Skarels 		selwakeup(rsel[qd], 0);
279930391Skarels 		rsel[qd] = 0;
280030391Skarels 		qdflags[qd].selmask &= ~SEL_READ;
280130391Skarels 		do_wakeup = 0;
280230391Skarels 	    }
280330391Skarels 	}
280430391Skarels 
2805*34511Smarc 	/*-----------------------------------------------------------------
2806*34511Smarc 	* if the graphic device is not turned on, this is console input */
280730391Skarels 
280830391Skarels 	else {
280930391Skarels 
281030391Skarels 	    ui = qdinfo[qd];
281130391Skarels 	    if (ui == 0 || ui->ui_alive == 0)
281230391Skarels 		return(0);
281330391Skarels 
281430391Skarels 	    tp = &qd_tty[qd << 2];
281530391Skarels 
281630391Skarels 	    /*--------------------------------------
281730391Skarels 	    * Get a character from the keyboard. */
281830391Skarels 
281930391Skarels 	    while ((status = duart->statusA) & RCV_RDY) {
282030391Skarels 
282130391Skarels 		key = duart->dataA;
282230391Skarels 		key &= 0xFF;
282330391Skarels 
282430391Skarels 		/*--------------------------------------
282530391Skarels 		* Check for various keyboard errors  */
282630391Skarels 
282730391Skarels 		if( key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
282830391Skarels 		    key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
2829*34511Smarc 			printf("qd%d: qdiint: Keyboard error, code = %x\n",
2830*34511Smarc 				qd, key);
283130391Skarels 			return(0);
283230391Skarels 		}
283330391Skarels 
283430391Skarels 		if (key < LK_LOWEST)
283530391Skarels 		    return(0);
283630391Skarels 
283730391Skarels 		/*---------------------------------
283830391Skarels 		* See if its a state change key */
283930391Skarels 
284030391Skarels 		switch (key) {
284130391Skarels 
284230391Skarels 		    case LOCK:
284330391Skarels 			q_keyboard.lock ^= 0xffff;	/* toggle */
284430391Skarels 			if (q_keyboard.lock)
284530391Skarels 			    led_control(qd, LK_LED_ENABLE, LK_LED_LOCK);
284630391Skarels 			else
284730391Skarels 			    led_control(qd, LK_LED_DISABLE, LK_LED_LOCK);
284830391Skarels 			return;
284930391Skarels 
285030391Skarels 		    case SHIFT:
285130391Skarels 			q_keyboard.shift ^= 0xFFFF;
285230391Skarels 			return;
285330391Skarels 
285430391Skarels 		    case CNTRL:
285530391Skarels 			q_keyboard.cntrl ^= 0xFFFF;
285630391Skarels 			return;
285730391Skarels 
285830391Skarels 		    case ALLUP:
285930391Skarels 			q_keyboard.cntrl = 0;
286030391Skarels 			q_keyboard.shift = 0;
286130391Skarels 			return;
286230391Skarels 
286330391Skarels 		    case REPEAT:
286430391Skarels 			chr = q_keyboard.last;
286530391Skarels 			break;
286630391Skarels 
286730391Skarels 		    /*-------------------------------------------------------
286830391Skarels 		    * Test for cntrl characters. If set, see if the character
286930391Skarels 		    * is elligible to become a control character. */
287030391Skarels 
287130391Skarels 		    default:
287230391Skarels 
287330391Skarels 			if (q_keyboard.cntrl) {
287430391Skarels 				chr = q_key[key];
287530391Skarels 				if (chr >= ' ' && chr <= '~')
287630391Skarels 				    chr &= 0x1F;
287730391Skarels 			}
287830391Skarels 			else if( q_keyboard.lock || q_keyboard.shift )
287930391Skarels 			    chr = q_shift_key[key];
288030391Skarels 			else
288130391Skarels 			    chr = q_key[key];
288230391Skarels 			break;
288330391Skarels 		}
288430391Skarels 
288530391Skarels 		q_keyboard.last = chr;
288630391Skarels 
288730391Skarels 		/*-----------------------------------
288830391Skarels 		* Check for special function keys */
288930391Skarels 
289030391Skarels 		if (chr & 0x80) {
289130391Skarels 			char *string;
289230391Skarels 			string = q_special[chr & 0x7F];
289330391Skarels 			while(*string)
289430391Skarels 			    (*linesw[tp->t_line].l_rint)(*string++, tp);
289530391Skarels 		}
289630391Skarels 		else {
289730391Skarels 			(*linesw[tp->t_line].l_rint)(chr, tp);
289830391Skarels 		}
289930391Skarels 	    }
290030391Skarels 	}
290130391Skarels 
290230391Skarels 	return(0);
290330391Skarels 
290430391Skarels } /* qdiint */
290530391Skarels 
290630391Skarels /******************************************************************
290730391Skarels *
290830391Skarels *	THE SUBROUTINES START HERE:
290930391Skarels *
291030391Skarels ******************************************************************/
291130391Skarels 
291230391Skarels /*****************************************************************
291330391Skarels *
291430391Skarels *	clear_qd_screen()... clear the QDSS screen
291530391Skarels *
291630391Skarels ******************************************************************
291730391Skarels *
291830391Skarels *			     >>> NOTE <<<
291930391Skarels *
292030391Skarels *   This code requires that certain adder initialization be valid.  To
292130391Skarels *   assure that this requirement is satisfied, this routine should be
292230391Skarels *   called only after calling the "setup_dragon()" function.
292330391Skarels *
292430391Skarels *   Clear the bitmap a piece at a time. Since the fast scroll clear
292530391Skarels *   only clears the current displayed portion of the bitmap put a
292630391Skarels *   temporary value in the y limit register so we can access whole
292730391Skarels *   bitmap
292830391Skarels *
292930391Skarels ****************/
293030391Skarels 
293130391Skarels clear_qd_screen(unit)
293230391Skarels int unit;
293330391Skarels {
293430391Skarels 	register struct adder *adder;
293530391Skarels 	adder = (struct adder *) qdmap[unit].adder;
293630391Skarels 
293730391Skarels 	adder->x_limit = 1024;
293830391Skarels 	adder->y_limit = 2048 - CHAR_HEIGHT;
293930391Skarels 	adder->y_offset_pending = 0;
294030391Skarels 
294130391Skarels 	wait_status(adder, VSYNC);	/* wait at LEAST 1 full frame */
294230391Skarels 	wait_status(adder, VSYNC);
294330391Skarels 
294430391Skarels 	adder->y_scroll_constant = SCROLL_ERASE;
294530391Skarels 
294630391Skarels 	wait_status(adder, VSYNC);
294730391Skarels 	wait_status(adder, VSYNC);
294830391Skarels 
294930391Skarels 	adder->y_offset_pending = 864;
295030391Skarels 
295130391Skarels 	wait_status(adder, VSYNC);
295230391Skarels 	wait_status(adder, VSYNC);
295330391Skarels 
295430391Skarels 	adder->y_scroll_constant = SCROLL_ERASE;
295530391Skarels 
295630391Skarels 	wait_status(adder, VSYNC);
295730391Skarels 	wait_status(adder, VSYNC);
295830391Skarels 
295930391Skarels 	adder->y_offset_pending = 1728;
296030391Skarels 
296130391Skarels 	wait_status(adder, VSYNC);
296230391Skarels 	wait_status(adder, VSYNC);
296330391Skarels 
296430391Skarels 	adder->y_scroll_constant = SCROLL_ERASE;
296530391Skarels 
296630391Skarels 	wait_status(adder, VSYNC);
296730391Skarels 	wait_status(adder, VSYNC);
296830391Skarels 
296930391Skarels 	adder->y_offset_pending = 0;	 /* back to normal */
297030391Skarels 
297130391Skarels 	wait_status(adder, VSYNC);
297230391Skarels 	wait_status(adder, VSYNC);
297330391Skarels 
297430391Skarels 	adder->x_limit = MAX_SCREEN_X;
297530391Skarels 	adder->y_limit = MAX_SCREEN_Y + FONT_HEIGHT;
297630391Skarels 
297730391Skarels } /* clear_qd_screen */
297830391Skarels 
297930391Skarels /**********************************************************************
298030391Skarels *
298130391Skarels *	qdputc()... route kernel console output to display destination
298230391Skarels *
298330391Skarels ***********************************************************************
298430391Skarels *
298530391Skarels *	calling convention:
298630391Skarels *
298730391Skarels *		qdputc(chr);
298830391Skarels *
298930391Skarels *	where:	char chr;	 ;character for output
299030391Skarels *
299130391Skarels ****************/
299230391Skarels 
299330391Skarels qdputc(chr)
299430391Skarels register char chr;
299530391Skarels {
299630391Skarels 
299732012Smarc 	/* if system is now physical, forget it (ie: crash DUMP) */
299830391Skarels 	if ( (mfpr(MAPEN) & 1) == 0 )
299930391Skarels 	    return;
300030391Skarels 
300132012Smarc         blitc(0, chr & 0xff);
300232012Smarc 	if ((chr & 0177) == '\n')
300332012Smarc 		blitc(0, '\r');
300430391Skarels 
300530391Skarels 
300630391Skarels } /* qdputc */
300730391Skarels 
300830391Skarels /*******************************************************************
300930391Skarels *
301030391Skarels *	qdgetc()... get a character from the LK201
301130391Skarels *
301230391Skarels *******************************************************************
301330391Skarels *
301430391Skarels *	calling convention:
301530391Skarels *
301630391Skarels *		qdgetc();
301730391Skarels *
301830391Skarels *	returns:  the character read.
301930391Skarels *
302030391Skarels ****************/
302130391Skarels 
302230391Skarels qdgetc()
302330391Skarels {
302430391Skarels 	register short key;
302530391Skarels 	register char chr;
302630391Skarels 	register struct duart *duart;
302730391Skarels 
302830391Skarels 	u_int status;
302930391Skarels 
303030391Skarels 	duart = (struct duart *) qdmap[0].duart;
303130391Skarels 
303230391Skarels 	/*--------------------------------------
303330391Skarels 	* Get a character from the keyboard. */
303430391Skarels 
303530391Skarels LOOP:
303630391Skarels 	while (!((status = duart->statusA) & RCV_RDY))
303730391Skarels 			;
303830391Skarels 
303930391Skarels 	key = duart->dataA;
304030391Skarels 	key &= 0xFF;
304130391Skarels 
304230391Skarels 	/*--------------------------------------
304330391Skarels 	* Check for various keyboard errors  */
304430391Skarels 
304530391Skarels 	if( key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
304630391Skarels 	    key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
304730391Skarels 		printf("Keyboard error, code = %x\n", key);
304830391Skarels 		return(0);
304930391Skarels 	}
305030391Skarels 
305130391Skarels 	if (key < LK_LOWEST)
305230391Skarels 	    return(0);
305330391Skarels 
305430391Skarels 	/*---------------------------------
305530391Skarels 	* See if its a state change key */
305630391Skarels 
305730391Skarels 	switch (key) {
305830391Skarels 
305930391Skarels 	    case LOCK:
306030391Skarels 		q_keyboard.lock ^= 0xffff;	/* toggle */
306130391Skarels 		if (q_keyboard.lock)
306230391Skarels 		    led_control(LK_LED_ENABLE, LK_LED_LOCK);
306330391Skarels 		else
306430391Skarels 		    led_control(LK_LED_DISABLE, LK_LED_LOCK);
306530391Skarels 		goto LOOP;
306630391Skarels 
306730391Skarels 	    case SHIFT:
306830391Skarels 		q_keyboard.shift ^= 0xFFFF;
306930391Skarels 		goto LOOP;
307030391Skarels 
307130391Skarels 	    case CNTRL:
307230391Skarels 		q_keyboard.cntrl ^= 0xFFFF;
307330391Skarels 		goto LOOP;
307430391Skarels 
307530391Skarels 	    case ALLUP:
307630391Skarels 		q_keyboard.cntrl = 0;
307730391Skarels 		q_keyboard.shift = 0;
307830391Skarels 		goto LOOP;
307930391Skarels 
308030391Skarels 	    case REPEAT:
308130391Skarels 		chr = q_keyboard.last;
308230391Skarels 		break;
308330391Skarels 
308430391Skarels 	    /*-------------------------------------------------------
308530391Skarels 	    * Test for cntrl characters. If set, see if the character
308630391Skarels 	    * is elligible to become a control character. */
308730391Skarels 
308830391Skarels 	    default:
308930391Skarels 
309030391Skarels 		if (q_keyboard.cntrl) {
309130391Skarels 		    chr = q_key[key];
309230391Skarels 		    if (chr >= ' ' && chr <= '~')
309330391Skarels 			chr &= 0x1F;
309430391Skarels 		}
309530391Skarels 		else if ( q_keyboard.lock || q_keyboard.shift )
309630391Skarels 		    chr = q_shift_key[key];
309730391Skarels 		else
309830391Skarels 		    chr = q_key[key];
309930391Skarels 		break;
310030391Skarels 	}
310130391Skarels 
310230391Skarels 	if (chr < ' ' && chr > '~')	/* if input is non-displayable */
310330391Skarels 	    return(0);			/* ..then pitch it! */
310430391Skarels 
310530391Skarels 	q_keyboard.last = chr;
310630391Skarels 
310730391Skarels 	/*-----------------------------------
310830391Skarels 	* Check for special function keys */
310930391Skarels 
311030391Skarels 	if (chr & 0x80) 		/* pitch the function keys */
311130391Skarels 	    return(0);
311230391Skarels 	else
311330391Skarels 	    return(chr);
311430391Skarels 
311530391Skarels } /* qdgetc */
311630391Skarels 
311730391Skarels /**********************************************************************
311830391Skarels *
311930391Skarels *	ldcursor()... load the mouse cursor's template RAM bitmap
312030391Skarels *
312130391Skarels *********************************************************************
312230391Skarels *
312330391Skarels *	calling convention:
312430391Skarels *
312530391Skarels *		ldcursor(unit, bitmap);
312630391Skarels *		u_int unit;
312730391Skarels *		short *bitmap;
312830391Skarels *
312930391Skarels ****************/
313030391Skarels 
313130391Skarels ldcursor(unit, bitmap)
313230391Skarels u_int unit;
313330391Skarels short *bitmap;
313430391Skarels {
313530391Skarels 	register struct dga *dga;
313630391Skarels 	register short *temp;
313730391Skarels 	register int i;
313830391Skarels 
313930391Skarels 	int cursor;
314030391Skarels 
314130391Skarels 	dga = (struct dga *) qdmap[unit].dga;
314230391Skarels 	temp = (short *) qdmap[unit].template;
314330391Skarels 
314430391Skarels 	if (dga->csr & CURS_ENB) {	/* if the cursor is enabled.. */
314530391Skarels 	    cursor = -1;		/* ..note that.. */
314630391Skarels 	    dga->csr &= ~CURS_ENB;	/* ..and shut it off */
314730391Skarels 	}
314830391Skarels 	else {
314930391Skarels 	    cursor = 0;
315030391Skarels 	}
315130391Skarels 
315230391Skarels 	dga->csr &= ~CURS_ENB;		/* shut off the cursor */
315330391Skarels 
315430391Skarels 	temp += (8 * 1024) - 32;	/* cursor is 32 WORDS from the end */
315530391Skarels 					/* ..of the 8k WORD template space */
315630391Skarels 	for (i = 0; i < 32; ++i)
315730391Skarels 	    *temp++ = *bitmap++;
315830391Skarels 
315930391Skarels 	if (cursor) {			/* if cursor was enabled.. */
316030391Skarels 	    dga->csr |= CURS_ENB;	/* ..turn it back on */
316130391Skarels 	}
316230391Skarels 
316330391Skarels 	return(0);
316430391Skarels 
316530391Skarels } /* ldcursor */
316630391Skarels 
316730391Skarels /**********************************************************************
316830391Skarels *
316930391Skarels *	ldfont()... put the console font in the QDSS off-screen memory
317030391Skarels *
317130391Skarels ***********************************************************************
317230391Skarels *
317330391Skarels *	calling convention:
317430391Skarels *
317530391Skarels *		ldfont(unit);
317630391Skarels *		u_int unit;	;QDSS unit number
317730391Skarels *
317830391Skarels ****************/
317930391Skarels 
318030391Skarels ldfont(unit)
318130391Skarels u_int unit;
318230391Skarels {
318330391Skarels 	register struct adder *adder;
318430391Skarels 
318530391Skarels 	int i;		/* scratch variables */
318630391Skarels 	int j;
318730391Skarels 	int k;
318830391Skarels 	short packed;
318930391Skarels 
319030391Skarels 	adder = (struct adder *) qdmap[unit].adder;
319130391Skarels 
3192*34511Smarc 	/*------------------------------------------
3193*34511Smarc 	* setup VIPER operand control registers  */
319430391Skarels 
319530391Skarels 	write_ID(adder, MASK_1, 0xFFFF);
319630391Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
319730391Skarels 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
319830391Skarels 
319930391Skarels 	write_ID(adder, SRC1_OCR_B,
320030391Skarels 			EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY);
320130391Skarels 	write_ID(adder, SRC2_OCR_B,
320230391Skarels 			EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY);
320330391Skarels 	write_ID(adder, DST_OCR_B,
320430391Skarels 			EXT_SOURCE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
320530391Skarels 
320630391Skarels 	adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL;
320730391Skarels 
3208*34511Smarc 	/*--------------------------
3209*34511Smarc 	* load destination data  */
321030391Skarels 
321130391Skarels 	wait_status(adder, RASTEROP_COMPLETE);
321230391Skarels 
321330391Skarels 	adder->destination_x = FONT_X;
321430391Skarels 	adder->destination_y = FONT_Y;
321530391Skarels 	adder->fast_dest_dx = FONT_WIDTH;
321630391Skarels 	adder->slow_dest_dy = CHAR_HEIGHT;
321730391Skarels 
3218*34511Smarc 	/*---------------------------------------
3219*34511Smarc 	* setup for processor to bitmap xfer  */
322030391Skarels 
322130391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0001);
322230391Skarels 	adder->cmd = PBT | OCRB | 2 | DTE | 2;
322330391Skarels 
3224*34511Smarc 	/*-----------------------------------------------
3225*34511Smarc 	* iteratively do the processor to bitmap xfer */
322630391Skarels 
322730391Skarels 	for (i = 0; i < ROWS; ++i) {
322830391Skarels 
322930391Skarels 	    /* PTOB a scan line */
323030391Skarels 
323130391Skarels 	    for (j = 0, k = i; j < 48; ++j) {
323230391Skarels 
323330391Skarels 		/* PTOB one scan of a char cell */
323430391Skarels 
323530391Skarels 		packed = q_font[k];
323630391Skarels 		k += ROWS;
323730391Skarels 		packed |= ((short)q_font[k] << 8);
323830391Skarels 		k += ROWS;
323930391Skarels 
324030391Skarels 		wait_status(adder, TX_READY);
324130391Skarels 		adder->id_data = packed;
324230391Skarels 	    }
324330391Skarels 	}
324430391Skarels 
324530391Skarels }  /* ldfont */
324630391Skarels 
324730391Skarels /*********************************************************************
324830391Skarels *
324930391Skarels *	led_control()... twiddle LK-201 LED's
325030391Skarels *
325130391Skarels **********************************************************************
325230391Skarels *
325330391Skarels *	led_control(unit, cmd, led_mask);
325430391Skarels *	u_int unit;	QDSS number
325530391Skarels *	int cmd;	LED enable/disable command
325630391Skarels *	int led_mask;	which LED(s) to twiddle
325730391Skarels *
325830391Skarels *************/
325930391Skarels 
326030391Skarels led_control(unit, cmd, led_mask)
326130391Skarels u_int unit;
326230391Skarels int cmd;
326330391Skarels int led_mask;
326430391Skarels {
326530391Skarels 	register int i;
326630391Skarels 	register int status;
326730391Skarels 	register struct duart *duart;
326830391Skarels 
326930391Skarels 	duart = (struct duart *) qdmap[unit].duart;
327030391Skarels 
327130391Skarels 	for (i = 1000; i > 0; --i) {
327230391Skarels 	    if ((status = duart->statusA) & XMT_RDY) {
327330391Skarels 		duart->dataA = cmd;
327430391Skarels 		break;
327530391Skarels 	    }
327630391Skarels 	}
327730391Skarels 
327830391Skarels 	for (i = 1000; i > 0; --i) {
327930391Skarels 	    if ((status = duart->statusA) & XMT_RDY) {
328030391Skarels 		duart->dataA = led_mask;
328130391Skarels 		break;
328230391Skarels 	    }
328330391Skarels 	}
328430391Skarels 
328530391Skarels 	if (i == 0)
328630391Skarels 	    return(BAD);
328730391Skarels 
328830391Skarels 	return(GOOD);
328930391Skarels 
329030391Skarels } /* led_control */
329130391Skarels 
329230391Skarels /*******************************************************************
329330391Skarels *
329430391Skarels *	scroll_up()... move the screen up one character height
329530391Skarels *
329630391Skarels ********************************************************************
329730391Skarels *
329830391Skarels *	calling convention:
329930391Skarels *
330030391Skarels *		scroll_up(adder);
330130391Skarels *		struct adder *adder;	;address of adder
330230391Skarels *
330330391Skarels ********/
330430391Skarels 
330530391Skarels scroll_up(adder)
330630391Skarels register struct adder *adder;
330730391Skarels {
330830391Skarels 
3309*34511Smarc 	/*------------------------------------------
3310*34511Smarc 	* setup VIPER operand control registers  */
331130391Skarels 
331230391Skarels 	wait_status(adder, ADDRESS_COMPLETE);
331330391Skarels 
331430391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x00FF);  /* select all planes */
331530391Skarels 
331630391Skarels 	write_ID(adder, MASK_1, 0xFFFF);
331730391Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
331830391Skarels 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
331930391Skarels 
332030391Skarels 	write_ID(adder, SRC1_OCR_B,
332130391Skarels 			EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY);
332230391Skarels 	write_ID(adder, DST_OCR_B,
332330391Skarels 			EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
332430391Skarels 
3325*34511Smarc 	/*----------------------------------------
3326*34511Smarc 	* load DESTINATION origin and vectors  */
332730391Skarels 
332830391Skarels 	adder->fast_dest_dy = 0;
332930391Skarels 	adder->slow_dest_dx = 0;
333030391Skarels 	adder->error_1 = 0;
333130391Skarels 	adder->error_2 = 0;
333230391Skarels 
333330391Skarels 	adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL;
333430391Skarels 
333530391Skarels 	adder->destination_x = 0;
333630391Skarels 	adder->fast_dest_dx = 1024;
333730391Skarels 
333830391Skarels 	adder->destination_y = 0;
333930391Skarels 	adder->slow_dest_dy = 864 - CHAR_HEIGHT;
334030391Skarels 
3341*34511Smarc 	/*-----------------------------------
3342*34511Smarc 	* load SOURCE origin and vectors  */
334330391Skarels 
334430391Skarels 	adder->source_1_x = 0;
334530391Skarels 	adder->source_1_dx = 1024;
334630391Skarels 
334730391Skarels 	adder->source_1_y = 0 + CHAR_HEIGHT;
334830391Skarels 	adder->source_1_dy = 864 - CHAR_HEIGHT;
334930391Skarels 
335030391Skarels 	write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
335130391Skarels 	adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE;
335230391Skarels 
3353*34511Smarc 	/*--------------------------------------------
3354*34511Smarc 	* do a rectangle clear of last screen line */
335530391Skarels 
335630391Skarels 	write_ID(adder, MASK_1, 0xffff);
335730391Skarels 	write_ID(adder, SOURCE, 0xffff);
335830391Skarels 	write_ID(adder,DST_OCR_B,
335930391Skarels 		(EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY));
336030391Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 0);
336130391Skarels 	adder->error_1 = 0;
336230391Skarels 	adder->error_2 = 0;
336330391Skarels 	adder->slow_dest_dx = 0;	/* set up the width of	*/
336430391Skarels 	adder->slow_dest_dy = CHAR_HEIGHT;	/* rectangle */
336530391Skarels 
336630391Skarels 	adder->rasterop_mode = (NORMAL | DST_WRITE_ENABLE) ;
336730391Skarels 	wait_status(adder, RASTEROP_COMPLETE);
336830391Skarels 	adder->destination_x = 0;
336930391Skarels 	adder->destination_y = 864 - CHAR_HEIGHT;
337030391Skarels 
337130391Skarels 	adder->fast_dest_dx = 1024;	/* set up the height	*/
337230391Skarels 	adder->fast_dest_dy = 0;	/* of rectangle 	*/
337330391Skarels 
337430391Skarels 	write_ID(adder, LU_FUNCTION_R2, (FULL_SRC_RESOLUTION | LF_SOURCE));
337530391Skarels 	adder->cmd = (RASTEROP | OCRB | LF_R2 | DTE ) ;
337630391Skarels 
337730391Skarels } /* scroll_up */
337830391Skarels 
337930391Skarels /********************************************************************
338030391Skarels *
338130391Skarels *	init_shared()... init shared memory pointers and structures
338230391Skarels *
338330391Skarels *********************************************************************
338430391Skarels *
338530391Skarels *	calling convention:
338630391Skarels *
338730391Skarels *		init_shared(unit);
338830391Skarels *		u_int unit;
338930391Skarels *
339030391Skarels ****************/
339130391Skarels 
339230391Skarels init_shared(unit)
339330391Skarels register u_int unit;
339430391Skarels {
339530391Skarels 	register struct dga *dga;
339630391Skarels 
339730391Skarels 	dga = (struct dga *) qdmap[unit].dga;
339830391Skarels 
3399*34511Smarc 	/*--------------------------------------------------
3400*34511Smarc 	* initialize the event queue pointers and header */
340130391Skarels 
340230391Skarels 	eq_header[unit] = (struct qdinput *)
340330391Skarels 			  ((((int)event_shared & ~(0x01FF)) + 512)
340430391Skarels 			   + (EVENT_BUFSIZE * unit));
340530391Skarels 
340630391Skarels 	eq_header[unit]->curs_pos.x = 0;
340730391Skarels 	eq_header[unit]->curs_pos.y = 0;
340830391Skarels 
340930391Skarels 	dga->x_cursor = TRANX(eq_header[unit]->curs_pos.x);
341030391Skarels 	dga->y_cursor = TRANY(eq_header[unit]->curs_pos.y);
341130391Skarels 
341230391Skarels 	eq_header[unit]->curs_box.left = 0;
341330391Skarels 	eq_header[unit]->curs_box.right = 0;
341430391Skarels 	eq_header[unit]->curs_box.top = 0;
341530391Skarels 	eq_header[unit]->curs_box.bottom = 0;
341630391Skarels 
3417*34511Smarc 	/*---------------------------------------------------------
3418*34511Smarc 	* assign a pointer to the DMA I/O buffer for this QDSS. */
341930391Skarels 
342030391Skarels 	DMAheader[unit] = (struct DMAreq_header *)
342130391Skarels 			  (((int)(&DMA_shared[0] + 512) & ~0x1FF)
342230391Skarels 			   + (DMAbuf_size * unit));
342330391Skarels 
342430391Skarels 	DMAheader[unit]->DMAreq = (struct DMAreq *) ((int)DMAheader[unit]
342530391Skarels 				  + sizeof(struct DMAreq_header));
342630391Skarels 
342730391Skarels 	DMAheader[unit]->QBAreg = 0;
342830391Skarels 	DMAheader[unit]->status = 0;
342930391Skarels 	DMAheader[unit]->shared_size = DMAbuf_size;
343030391Skarels 	DMAheader[unit]->used = 0;
343130391Skarels 	DMAheader[unit]->size = 10;	/* default = 10 requests */
343230391Skarels 	DMAheader[unit]->oldest = 0;
343330391Skarels 	DMAheader[unit]->newest = 0;
343430391Skarels 
3435*34511Smarc 	/*-----------------------------------------------------------
3436*34511Smarc 	* assign a pointer to the scroll structure for this QDSS. */
343730391Skarels 
343830391Skarels 	scroll[unit] = (struct scroll *)
343930391Skarels 			 (((int)(&scroll_shared[0] + 512) & ~0x1FF)
344030391Skarels 			   + (sizeof(struct scroll) * unit));
344130391Skarels 
344230391Skarels 	scroll[unit]->status = 0;
344330391Skarels 	scroll[unit]->viper_constant = 0;
344430391Skarels 	scroll[unit]->y_scroll_constant = 0;
344530391Skarels 	scroll[unit]->y_offset = 0;
344630391Skarels 	scroll[unit]->x_index_pending = 0;
344730391Skarels 	scroll[unit]->y_index_pending = 0;
344830391Skarels 
3449*34511Smarc 	/*----------------------------------------------------------------
3450*34511Smarc 	* assign a pointer to the color map write buffer for this QDSS */
345130391Skarels 
345230391Skarels 	color_buf[unit] = (struct color_buf *)
345330391Skarels 			   (((int)(&color_shared[0] + 512) & ~0x1FF)
345430391Skarels 			    + (COLOR_BUFSIZ * unit));
345530391Skarels 
345630391Skarels 	color_buf[unit]->status = 0;
345730391Skarels 	color_buf[unit]->count = 0;
345830391Skarels 
345930391Skarels } /* init_shared */
346030391Skarels 
346130391Skarels /*********************************************************************
346230391Skarels *
346330391Skarels *	setup_dragon()... init the ADDER, VIPER, bitmaps, & color map
346430391Skarels *
346530391Skarels **********************************************************************
346630391Skarels *
346730391Skarels *	calling convention:
346830391Skarels *
346930391Skarels *		setup_dragon();
347030391Skarels *
347130391Skarels *	return: NONE
347230391Skarels *
347330391Skarels ************************/
347430391Skarels 
347530391Skarels setup_dragon(unit)
347630391Skarels u_int unit;
347730391Skarels {
347830391Skarels 
347930391Skarels 	register struct adder *adder;
348030391Skarels 	register struct dga *dga;
348130391Skarels 	short *memcsr;
348230391Skarels 
348330391Skarels 	int i;			/* general purpose variables */
348430391Skarels 	int status;
348530391Skarels 
348630391Skarels 	short top;		/* clipping/scrolling boundaries */
348730391Skarels 	short bottom;
348830391Skarels 	short right;
348930391Skarels 	short left;
349030391Skarels 
349130391Skarels 	short *red;		/* color map pointers */
349230391Skarels 	short *green;
349330391Skarels 	short *blue;
349430391Skarels 
3495*34511Smarc 	/*------------------
3496*34511Smarc 	* init for setup */
349730391Skarels 
349830391Skarels 	adder = (struct adder *) qdmap[unit].adder;
349930391Skarels 	dga = (struct dga *) qdmap[unit].dga;
350030391Skarels 	memcsr = (short *) qdmap[unit].memcsr;
350130391Skarels 
350230391Skarels 	dga->csr &= ~(DMA_IE | 0x700);	/* halt DMA and kill the intrpts */
350330391Skarels 	*memcsr = SYNC_ON;		/* blank screen and turn off LED's */
350430391Skarels 	adder->command = CANCEL;
350530391Skarels 
3506*34511Smarc 	/*----------------------
3507*34511Smarc 	* set monitor timing */
350830391Skarels 
350930391Skarels 	adder->x_scan_count_0 = 0x2800;
351030391Skarels 	adder->x_scan_count_1 = 0x1020;
351130391Skarels 	adder->x_scan_count_2 = 0x003A;
351230391Skarels 	adder->x_scan_count_3 = 0x38F0;
351330391Skarels 	adder->x_scan_count_4 = 0x6128;
351430391Skarels 	adder->x_scan_count_5 = 0x093A;
351530391Skarels 	adder->x_scan_count_6 = 0x313C;
351630391Skarels 	adder->sync_phase_adj = 0x0100;
351730391Skarels 	adder->x_scan_conf = 0x00C8;
351830391Skarels 
3519*34511Smarc 	/*---------------------------------------------------------
3520*34511Smarc 	* got a bug in secound pass ADDER! lets take care of it */
352130391Skarels 
352230391Skarels 	/* normally, just use the code in the following bug fix code, but to
352330391Skarels 	* make repeated demos look pretty, load the registers as if there was
352430391Skarels 	* no bug and then test to see if we are getting sync */
352530391Skarels 
352630391Skarels 	adder->y_scan_count_0 = 0x135F;
352730391Skarels 	adder->y_scan_count_1 = 0x3363;
352830391Skarels 	adder->y_scan_count_2 = 0x2366;
352930391Skarels 	adder->y_scan_count_3 = 0x0388;
353030391Skarels 
353130391Skarels 	/* if no sync, do the bug fix code */
353230391Skarels 
353330391Skarels 	if (wait_status(adder, VSYNC) == BAD) {
353430391Skarels 
353530391Skarels 	    /* first load all Y scan registers with very short frame and
353630391Skarels 	    * wait for scroll service.	This guarantees at least one SYNC
353730391Skarels 	    * to fix the pass 2 Adder initialization bug (synchronizes
353830391Skarels 	    * XCINCH with DMSEEDH) */
353930391Skarels 
354030391Skarels 	    adder->y_scan_count_0 = 0x01;
354130391Skarels 	    adder->y_scan_count_1 = 0x01;
354230391Skarels 	    adder->y_scan_count_2 = 0x01;
354330391Skarels 	    adder->y_scan_count_3 = 0x01;
354430391Skarels 
354530391Skarels 	    wait_status(adder, VSYNC);	/* delay at least 1 full frame time */
354630391Skarels 	    wait_status(adder, VSYNC);
354730391Skarels 
354830391Skarels 	    /* now load the REAL sync values (in reverse order just to
354930391Skarels 	    *  be safe.  */
355030391Skarels 
355130391Skarels 	    adder->y_scan_count_3 = 0x0388;
355230391Skarels 	    adder->y_scan_count_2 = 0x2366;
355330391Skarels 	    adder->y_scan_count_1 = 0x3363;
355430391Skarels 	    adder->y_scan_count_0 = 0x135F;
355530391Skarels 	}
355630391Skarels 
355730391Skarels 	*memcsr = SYNC_ON | UNBLANK;	/* turn off leds and turn on video */
355830391Skarels 
3559*34511Smarc 	/*----------------------------
3560*34511Smarc 	* zero the index registers */
356130391Skarels 
356230391Skarels 	adder->x_index_pending = 0;
356330391Skarels 	adder->y_index_pending = 0;
356430391Skarels 	adder->x_index_new = 0;
356530391Skarels 	adder->y_index_new = 0;
356630391Skarels 	adder->x_index_old = 0;
356730391Skarels 	adder->y_index_old = 0;
356830391Skarels 
356930391Skarels 	adder->pause = 0;
357030391Skarels 
3571*34511Smarc 	/*----------------------------------------
3572*34511Smarc 	* set rasterop mode to normal pen down */
357330391Skarels 
357430391Skarels 	adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL;
357530391Skarels 
3576*34511Smarc 	/*--------------------------------------------------
3577*34511Smarc 	* set the rasterop registers to a default values */
357830391Skarels 
357930391Skarels 	adder->source_1_dx = 1;
358030391Skarels 	adder->source_1_dy = 1;
358130391Skarels 	adder->source_1_x = 0;
358230391Skarels 	adder->source_1_y = 0;
358330391Skarels 	adder->destination_x = 0;
358430391Skarels 	adder->destination_y = 0;
358530391Skarels 	adder->fast_dest_dx = 1;
358630391Skarels 	adder->fast_dest_dy = 0;
358730391Skarels 	adder->slow_dest_dx = 0;
358830391Skarels 	adder->slow_dest_dy = 1;
358930391Skarels 	adder->error_1 = 0;
359030391Skarels 	adder->error_2 = 0;
359130391Skarels 
3592*34511Smarc 	/*------------------------
3593*34511Smarc 	* scale factor = unity */
359430391Skarels 
359530391Skarels 	adder->fast_scale = UNITY;
359630391Skarels 	adder->slow_scale = UNITY;
359730391Skarels 
3598*34511Smarc 	/*-------------------------------
3599*34511Smarc 	* set the source 2 parameters */
360030391Skarels 
360130391Skarels 	adder->source_2_x = 0;
360230391Skarels 	adder->source_2_y = 0;
360330391Skarels 	adder->source_2_size = 0x0022;
360430391Skarels 
3605*34511Smarc 	/*-----------------------------------------------
3606*34511Smarc 	* initialize plane addresses for eight vipers */
360730391Skarels 
360830391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0001);
360930391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0000);
361030391Skarels 
361130391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0002);
361230391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0001);
361330391Skarels 
361430391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0004);
361530391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0002);
361630391Skarels 
361730391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0008);
361830391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0003);
361930391Skarels 
362030391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0010);
362130391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0004);
362230391Skarels 
362330391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0020);
362430391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0005);
362530391Skarels 
362630391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0040);
362730391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0006);
362830391Skarels 
362930391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0080);
363030391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0007);
363130391Skarels 
363230391Skarels 	/* initialize the external registers. */
363330391Skarels 
363430391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x00FF);
363530391Skarels 	write_ID(adder, CS_SCROLL_MASK, 0x00FF);
363630391Skarels 
363730391Skarels 	/* initialize resolution mode */
363830391Skarels 
363930391Skarels 	write_ID(adder, MEMORY_BUS_WIDTH, 0x000C);     /* bus width = 16 */
364030391Skarels 	write_ID(adder, RESOLUTION_MODE, 0x0000);      /* one bit/pixel */
364130391Skarels 
364230391Skarels 	/* initialize viper registers */
364330391Skarels 
364430391Skarels 	write_ID(adder, SCROLL_CONSTANT, SCROLL_ENABLE|VIPER_LEFT|VIPER_UP);
364530391Skarels 	write_ID(adder, SCROLL_FILL, 0x0000);
364630391Skarels 
3647*34511Smarc 	/*----------------------------------------------------
3648*34511Smarc 	* set clipping and scrolling limits to full screen */
364930391Skarels 
365030391Skarels 	for ( i = 1000, adder->status = 0
365130391Skarels 	    ; i > 0  &&  !((status = adder->status) & ADDRESS_COMPLETE)
365230391Skarels 	    ; --i);
365330391Skarels 
365430391Skarels 	if (i == 0)
3655*34511Smarc 	    printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n", unit);
365630391Skarels 
365730391Skarels 	top = 0;
365830391Skarels 	bottom = 2048;
365930391Skarels 	left = 0;
366030391Skarels 	right = 1024;
366130391Skarels 
366230391Skarels 	adder->x_clip_min = left;
366330391Skarels 	adder->x_clip_max = right;
366430391Skarels 	adder->y_clip_min = top;
366530391Skarels 	adder->y_clip_max = bottom;
366630391Skarels 
366730391Skarels 	adder->scroll_x_min = left;
366830391Skarels 	adder->scroll_x_max = right;
366930391Skarels 	adder->scroll_y_min = top;
367030391Skarels 	adder->scroll_y_max = bottom;
367130391Skarels 
367230391Skarels 	wait_status(adder, VSYNC);	/* wait at LEAST 1 full frame */
367330391Skarels 	wait_status(adder, VSYNC);
367430391Skarels 
367530391Skarels 	adder->x_index_pending = left;
367630391Skarels 	adder->y_index_pending = top;
367730391Skarels 	adder->x_index_new = left;
367830391Skarels 	adder->y_index_new = top;
367930391Skarels 	adder->x_index_old = left;
368030391Skarels 	adder->y_index_old = top;
368130391Skarels 
368230391Skarels 	for ( i = 1000, adder->status = 0
368330391Skarels 	    ; i > 0  &&  !((status = adder->status) & ADDRESS_COMPLETE)
368430391Skarels 	    ; --i);
368530391Skarels 
368630391Skarels 	if (i == 0)
3687*34511Smarc 	    printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n", unit);
368830391Skarels 
368930391Skarels 	write_ID(adder, LEFT_SCROLL_MASK, 0x0000);
369030391Skarels 	write_ID(adder, RIGHT_SCROLL_MASK, 0x0000);
369130391Skarels 
3692*34511Smarc 	/*------------------------------------------------------------
3693*34511Smarc 	* set source and the mask register to all ones (ie: white) */
369430391Skarels 
369530391Skarels 	write_ID(adder, SOURCE, 0xFFFF);
369630391Skarels 	write_ID(adder, MASK_1, 0xFFFF);
369730391Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
369830391Skarels 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
369930391Skarels 
3700*34511Smarc 	/*--------------------------------------------------------------
3701*34511Smarc 	* initialize Operand Control Register banks for fill command */
370230391Skarels 
370330391Skarels 	write_ID(adder, SRC1_OCR_A, EXT_NONE | INT_M1_M2  | NO_ID | WAIT);
370430391Skarels 	write_ID(adder, SRC2_OCR_A, EXT_NONE | INT_SOURCE | NO_ID | NO_WAIT);
370530391Skarels 	write_ID(adder, DST_OCR_A, EXT_NONE | INT_NONE	 | NO_ID | NO_WAIT);
370630391Skarels 
370730391Skarels 	write_ID(adder, SRC1_OCR_B, EXT_NONE | INT_SOURCE | NO_ID | WAIT);
370830391Skarels 	write_ID(adder, SRC2_OCR_B, EXT_NONE | INT_M1_M2  | NO_ID | NO_WAIT);
370930391Skarels 	write_ID(adder, DST_OCR_B, EXT_NONE | INT_NONE | NO_ID | NO_WAIT);
371030391Skarels 
3711*34511Smarc 	/*------------------------------------------------------------------
3712*34511Smarc 	* init Logic Unit Function registers, (these are just common values,
371330391Skarels * and may be changed as required).  */
371430391Skarels 
371530391Skarels 	write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
371630391Skarels 	write_ID(adder, LU_FUNCTION_R2, FULL_SRC_RESOLUTION | LF_SOURCE | INV_M1_M2);
371730391Skarels 	write_ID(adder, LU_FUNCTION_R3, FULL_SRC_RESOLUTION | LF_D_OR_S);
371830391Skarels 	write_ID(adder, LU_FUNCTION_R4, FULL_SRC_RESOLUTION | LF_D_XOR_S);
371930391Skarels 
3720*34511Smarc 	/*----------------------------------------
3721*34511Smarc 	* load the color map for black & white */
372230391Skarels 
372330391Skarels 	for ( i = 0, adder->status = 0
372430391Skarels 	    ; i < 10000  &&  !((status = adder->status) & VSYNC)
372530391Skarels 	    ; ++i);
372630391Skarels 
372730391Skarels 	if (i == 0)
3728*34511Smarc 	    printf("qd%d: setup_dragon: timeout on VSYNC\n", unit);
372930391Skarels 
373030391Skarels 	red = (short *) qdmap[unit].red;
373130391Skarels 	green = (short *) qdmap[unit].green;
373230391Skarels 	blue = (short *) qdmap[unit].blue;
373330391Skarels 
373430391Skarels 	*red++ = 0x00;			/* black */
373530391Skarels 	*green++ = 0x00;
373630391Skarels 	*blue++ = 0x00;
373730391Skarels 
373830391Skarels 	*red-- = 0xFF;			/* white */
373930391Skarels 	*green-- = 0xFF;
374030391Skarels 	*blue-- = 0xFF;
374130391Skarels 
374230391Skarels 	/*----------------------------------
374330391Skarels 	* set color map for mouse cursor */
374430391Skarels 
374530391Skarels 	red += 254;
374630391Skarels 	green += 254;
374730391Skarels 	blue += 254;
374830391Skarels 
374930391Skarels 	*red++ = 0x00;			/* black */
375030391Skarels 	*green++ = 0x00;
375130391Skarels 	*blue++ = 0x00;
375230391Skarels 
375330391Skarels 	*red = 0xFF;			/* white */
375430391Skarels 	*green = 0xFF;
375530391Skarels 	*blue = 0xFF;
375630391Skarels 
375730391Skarels 	return(0);
375830391Skarels 
375930391Skarels } /* setup_dragon */
376030391Skarels 
376130391Skarels /******************************************************************
376230391Skarels *
376330391Skarels *	setup_input()... init the DUART and set defaults in input
376430391Skarels *			 devices
376530391Skarels *
376630391Skarels *******************************************************************
376730391Skarels *
376830391Skarels *	calling convention:
376930391Skarels *
377030391Skarels *		setup_input(unit);
377130391Skarels *
377230391Skarels *	where: unit - is the QDSS unit number to be setup
377330391Skarels *
377430391Skarels *********/
377530391Skarels 
377630391Skarels setup_input(unit)
377730391Skarels u_int unit;
377830391Skarels {
377930391Skarels 	register struct duart *duart;	/* DUART register structure pointer */
378030391Skarels 	register int i; 		/* scratch variable */
378130391Skarels 	register int bits;
378230391Skarels 
378330391Skarels 	char id_byte;
378430391Skarels 	short status;
378530391Skarels 
3786*34511Smarc 	/*---------------
3787*34511Smarc 	* init stuff */
378830391Skarels 
378930391Skarels 	duart = (struct duart *) qdmap[unit].duart;
379030391Skarels 	duart->imask = 0;
379130391Skarels 
3792*34511Smarc 	/*---------------------------------------------
3793*34511Smarc 	* setup the DUART for kbd & pointing device */
379430391Skarels 
379530391Skarels 	duart->cmdA = RESET_M;	  /* reset mode reg ptr for kbd */
379630391Skarels 	duart->modeA = 0x13;	  /* 8 bits, no parity, rcv IE, */
379730391Skarels 				  /* no RTS control,char error mode */
379830391Skarels 	duart->modeA = 0x07;	  /* 1 stop bit,CTS does not IE XMT */
379930391Skarels 				  /* no RTS control,no echo or loop */
380030391Skarels 	duart->cmdB = RESET_M;	  /* reset mode reg pntr for host */
380130391Skarels 	duart->modeB = 0x07;	  /* 8 bits, odd parity, rcv IE.. */
380230391Skarels 				  /* ..no RTS cntrl, char error mode */
380330391Skarels 	duart->modeB = 0x07;	  /* 1 stop bit,CTS does not IE XMT */
380430391Skarels 				  /* no RTS control,no echo or loop */
380530391Skarels 
380630391Skarels 	duart->auxctl = 0x00;	  /* baud rate set 1 */
380730391Skarels 
380830391Skarels 	duart->clkselA = 0x99;	  /* 4800 baud for kbd */
380930391Skarels 	duart->clkselB = 0x99;	  /* 4800 baud for mouse */
381030391Skarels 
381130391Skarels 	/* reset everything for keyboard */
381230391Skarels 
381330391Skarels 	for (bits = RESET_M; bits < START_BREAK; bits += 0x10)
381430391Skarels 	    duart->cmdA = bits;
381530391Skarels 
381630391Skarels 	/* reset everything for host */
381730391Skarels 
381830391Skarels 	for (bits = RESET_M; bits < START_BREAK; bits += 0x10)
381930391Skarels 	     duart->cmdB = bits;
382030391Skarels 
382130391Skarels 	duart->cmdA = EN_RCV | EN_XMT; /* enbl xmt & rcv for kbd */
382230391Skarels 	duart->cmdB = EN_RCV | EN_XMT; /* enbl xmt & rcv for pointer device */
382330391Skarels 
3824*34511Smarc 	/*--------------------------------------------
3825*34511Smarc 	* init keyboard defaults (DUART channel A) */
382630391Skarels 
382730391Skarels 	for (i = 500; i > 0; --i) {
382830391Skarels 	    if ((status = duart->statusA) & XMT_RDY) {
382930391Skarels 		duart->dataA = LK_DEFAULTS;
383030391Skarels 		break;
383130391Skarels 	    }
383230391Skarels 	}
383330391Skarels 
383430391Skarels 	for (i = 100000; i > 0; --i) {
383530391Skarels 	    if ((status = duart->statusA) & RCV_RDY) {
383630391Skarels 		break;
383730391Skarels 	    }
383830391Skarels 	}
383930391Skarels 
384030391Skarels 	status = duart->dataA;		/* flush the ACK */
384130391Skarels 
3842*34511Smarc 	/*--------------------------------
3843*34511Smarc 	* identify the pointing device */
384430391Skarels 
384530391Skarels 	for (i = 500; i > 0; --i) {
384630391Skarels 	    if ((status = duart->statusB) & XMT_RDY) {
384730391Skarels 		duart->dataB = SELF_TEST;
384830391Skarels 		break;
384930391Skarels 	    }
385030391Skarels 	}
385130391Skarels 
385230391Skarels 	/*-----------------------------------------
385330391Skarels 	* wait for 1st byte of self test report */
385430391Skarels 
385530391Skarels 	for (i = 100000; i > 0; --i) {
385630391Skarels 	    if ((status = duart->statusB) & RCV_RDY) {
385730391Skarels 		break;
385830391Skarels 	    }
385930391Skarels 	}
386030391Skarels 
386130391Skarels 	if (i == 0) {
3862*34511Smarc 	    printf("qd[%d]: setup_input: timeout on 1st byte of self test\n",
3863*34511Smarc 		   unit);
386430391Skarels 	    goto OUT;
386530391Skarels 	}
386630391Skarels 
386730391Skarels 	status = duart->dataB;
386830391Skarels 
386930391Skarels 	/*-----------------------------------------
387030391Skarels 	* wait for ID byte of self test report	*/
387130391Skarels 
387230391Skarels 	for (i = 100000; i > 0; --i) {
387330391Skarels 	    if ((status = duart->statusB) & RCV_RDY) {
387430391Skarels 		break;
387530391Skarels 	    }
387630391Skarels 	}
387730391Skarels 
387830391Skarels 	if (i == 0) {
3879*34511Smarc 	    printf("qd[%d]: setup_input: timeout on 2nd byte of self test\n",
3880*34511Smarc 		   unit);
388130391Skarels 	    goto OUT;
388230391Skarels 	}
388330391Skarels 
388430391Skarels 	id_byte = duart->dataB;
388530391Skarels 
388630391Skarels 	/*------------------------------------
388730391Skarels 	* wait for other bytes to come in  */
388830391Skarels 
388930391Skarels 	for (i = 100000; i > 0; --i) {
389030391Skarels 	    if ((status = duart->statusB) & RCV_RDY) {
389130391Skarels 		status = duart->dataB;
389230391Skarels 		break;
389330391Skarels 	    }
389430391Skarels 	}
389530391Skarels 
389630391Skarels 	if (i == 0) {
3897*34511Smarc 	    printf("qd[%d]: setup_input: timeout on 3rd byte of self test\n",
3898*34511Smarc 		   unit);
389930391Skarels 	    goto OUT;
390030391Skarels 	}
390130391Skarels 
390230391Skarels 	for (i = 100000; i > 0; --i) {
390330391Skarels 	    if ((status = duart->statusB) & RCV_RDY) {
390430391Skarels 		status = duart->dataB;
390530391Skarels 		break;
390630391Skarels 	    }
390730391Skarels 	}
390830391Skarels 
390930391Skarels 	if (i == 0) {
3910*34511Smarc 	    printf("qd[%d]: setup_input: timeout on 4th byte of self test\n",
3911*34511Smarc 		   unit);
391230391Skarels 	    goto OUT;
391330391Skarels 	}
391430391Skarels 
391530391Skarels 	/*----------------------------------------------
391630391Skarels 	* flag pointing device type and set defaults */
391730391Skarels 
391830391Skarels 	for (i=100000; i>0; --i);
391930391Skarels 
392030391Skarels 	if ((id_byte & 0x0F) != TABLET_ID) {
392130391Skarels 
392230391Skarels 	    qdflags[unit].pntr_id = MOUSE_ID;
392330391Skarels 
392430391Skarels 	    for (i = 500; i > 0; --i) {
392530391Skarels 		if ((status = duart->statusB) & XMT_RDY) {
392630391Skarels 		    duart->dataB = INC_STREAM_MODE;
392730391Skarels 		    break;
392830391Skarels 		}
392930391Skarels 	    }
393030391Skarels 	} else {
393130391Skarels 
393230391Skarels 	    qdflags[unit].pntr_id = TABLET_ID;
393330391Skarels 
393430391Skarels 	    for (i = 500; i > 0; --i) {
393530391Skarels 		if ((status = duart->statusB) & XMT_RDY) {
393630391Skarels 		    duart->dataB = T_STREAM;
393730391Skarels 		    break;
393830391Skarels 		}
393930391Skarels 	    }
394030391Skarels 	}
394130391Skarels 
3942*34511Smarc 	/*--------
3943*34511Smarc 	* exit */
394430391Skarels 
394530391Skarels OUT:
394630391Skarels 	duart->imask = qdflags[unit].duart_imask;
394730391Skarels 	return(0);
394830391Skarels 
394930391Skarels } /* setup_input */
395030391Skarels 
395130391Skarels /**********************************************************************
395230391Skarels *
395330391Skarels *	wait_status()... delay for at least one display frame time
395430391Skarels *
395530391Skarels ***********************************************************************
395630391Skarels *
395730391Skarels *	calling convention:
395830391Skarels *
395930391Skarels *		wait_status(adder, mask);
396030391Skarels *		struct *adder adder;
396130391Skarels *		int mask;
396230391Skarels *
396330391Skarels *	return: BAD means that we timed out without ever seeing the
396430391Skarels *		      vertical sync status bit
396530391Skarels *		GOOD otherwise
396630391Skarels *
396730391Skarels **************/
396830391Skarels 
396930391Skarels wait_status(adder, mask)
397030391Skarels register struct adder *adder;
397130391Skarels register int mask;
397230391Skarels {
397330391Skarels 	register short status;
397430391Skarels 	int i;
397530391Skarels 
397630391Skarels 	for ( i = 10000, adder->status = 0
397730391Skarels 	    ; i > 0  &&  !((status = adder->status) & mask)
397830391Skarels 	    ; --i);
397930391Skarels 
398030391Skarels 	if (i == 0) {
3981*34511Smarc 	    printf("wait_status: timeout polling for 0x%x in adder->status\n",
3982*34511Smarc 		   mask);
398330391Skarels 	    return(BAD);
398430391Skarels 	}
398530391Skarels 
398630391Skarels 	return(GOOD);
398730391Skarels 
398830391Skarels } /* wait_status */
398930391Skarels 
399030391Skarels /**********************************************************************
399130391Skarels *
399230391Skarels *	write_ID()... write out onto the ID bus
399330391Skarels *
399430391Skarels ***********************************************************************
399530391Skarels *
399630391Skarels *	calling convention:
399730391Skarels *
399830391Skarels *		struct *adder adder;	;pntr to ADDER structure
399930391Skarels *		short adrs;		;VIPER address
400030391Skarels *		short data;		;data to be written
400130391Skarels *		write_ID(adder);
400230391Skarels *
400330391Skarels *	return: BAD means that we timed out waiting for status bits
400430391Skarels *		      VIPER-access-specific status bits
400530391Skarels *		GOOD otherwise
400630391Skarels *
400730391Skarels **************/
400830391Skarels 
400930391Skarels write_ID(adder, adrs, data)
401030391Skarels register struct adder *adder;
401130391Skarels register short adrs;
401230391Skarels register short data;
401330391Skarels {
401430391Skarels 	int i;
401530391Skarels 	short status;
401630391Skarels 
4017*34511Smarc 	for ( i = 100000, adder->status = 0;
4018*34511Smarc 	      i > 0  &&  !((status = adder->status) & ADDRESS_COMPLETE); --i)
4019*34511Smarc 		;
402030391Skarels 
402130391Skarels 	if (i == 0)
402230391Skarels 	    goto ERR;
402330391Skarels 
4024*34511Smarc 	for ( i = 100000, adder->status = 0;
4025*34511Smarc 	      i > 0  &&  !((status = adder->status) & TX_READY); --i)
4026*34511Smarc 		;
402730391Skarels 
402830391Skarels 	if (i > 0) {
402930391Skarels 	    adder->id_data = data;
403030391Skarels 	    adder->command = ID_LOAD | adrs;
403130391Skarels 	    return(GOOD);
403230391Skarels 	}
403330391Skarels 
403430391Skarels ERR:
4035*34511Smarc 	printf("write_ID: timeout trying to write to VIPER\n");
403630391Skarels 	return(BAD);
403730391Skarels 
403830391Skarels } /* write_ID */
4039*34511Smarc #endif
4040