xref: /original-bsd/sys/vax/uba/qd.c (revision f79d7b48)
1006e9885Smarc /*
2537afb73Sbostic  * Copyright (c) 1988 Regents of the University of California.
3537afb73Sbostic  * All rights reserved.
4006e9885Smarc  *
5537afb73Sbostic  * Redistribution and use in source and binary forms are permitted
6537afb73Sbostic  * provided that the above copyright notice and this paragraph are
7537afb73Sbostic  * duplicated in all such forms and that any documentation,
8537afb73Sbostic  * advertising materials, and other materials related to such
9537afb73Sbostic  * distribution and use acknowledge that the software was developed
10537afb73Sbostic  * by the University of California, Berkeley.  The name of the
11537afb73Sbostic  * University may not be used to endorse or promote products derived
12537afb73Sbostic  * from this software without specific prior written permission.
13537afb73Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14537afb73Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15537afb73Sbostic  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16006e9885Smarc  *
17*f79d7b48Smarc  *	@(#)qd.c	1.15 (Berkeley) 04/05/90
18006e9885Smarc  */
19b2b69f49Smarc 
207e911b15Skarels /************************************************************************
217e911b15Skarels *									*
22e977faadSmarc *			Copyright (c) 1985-1988 by			*
237e911b15Skarels *		Digital Equipment Corporation, Maynard, MA		*
247e911b15Skarels *			All rights reserved.				*
257e911b15Skarels *									*
267e911b15Skarels *   This software is furnished under a license and may be used and	*
277e911b15Skarels *   copied  only  in accordance with the terms of such license and	*
287e911b15Skarels *   with the  inclusion  of  the  above  copyright  notice.   This	*
297e911b15Skarels *   software  or  any  other copies thereof may not be provided or	*
307e911b15Skarels *   otherwise made available to any other person.  No title to and	*
317e911b15Skarels *   ownership of the software is hereby transferred.			*
327e911b15Skarels *									*
337e911b15Skarels *   The information in this software is subject to change  without	*
347e911b15Skarels *   notice  and should not be construed as a commitment by Digital	*
357e911b15Skarels *   Equipment Corporation.						*
367e911b15Skarels *									*
377e911b15Skarels *   Digital assumes no responsibility for the use  or  reliability	*
387e911b15Skarels *   of its software on equipment which is not supplied by Digital.	*
397e911b15Skarels *									*
407e911b15Skarels *************************************************************************/
41e977faadSmarc 
427e911b15Skarels /*
43b2b69f49Smarc  * qd.c - QDSS display driver for VAXSTATION-II GPX workstation
447e911b15Skarels  */
457e911b15Skarels 
46b2b69f49Smarc #include "qd.h"
47e977faadSmarc 
48006e9885Smarc #if NQD > 0
49e977faadSmarc #include "types.h"
5019612d62Smckusick #include "machine/pte.h"
5119612d62Smckusick #include "machine/mtpr.h"
5219612d62Smckusick #include "machine/cpu.h"
53b2b69f49Smarc #include "param.h"
54b2b69f49Smarc #include "conf.h"
55b2b69f49Smarc #include "user.h"
56b2b69f49Smarc #include "qdioctl.h"
57006e9885Smarc #include "tty.h"
58b2b69f49Smarc #include "map.h"
59b2b69f49Smarc #include "buf.h"
60b2b69f49Smarc #include "vm.h"
61b2b69f49Smarc #include "clist.h"
62b2b69f49Smarc #include "file.h"
63b2b69f49Smarc #include "uio.h"
64b2b69f49Smarc #include "kernel.h"
65e977faadSmarc #include "exec.h"
66e977faadSmarc #include "proc.h"
67b2b69f49Smarc #include "ubareg.h"
68b2b69f49Smarc #include "ubavar.h"
69e977faadSmarc #include "syslog.h"
70b2b69f49Smarc #include "qduser.h"	/* definitions shared with user level client */
71e977faadSmarc #include "qdreg.h"	/* QDSS device register structures */
7224f67f6bSmarc 
73b2b69f49Smarc /*
74b2b69f49Smarc  * QDSS driver status flags for tracking operational state
75b2b69f49Smarc  */
7624f67f6bSmarc struct qdflags {
7724f67f6bSmarc 	u_int inuse;		/* which minor dev's are in use now */
7824f67f6bSmarc 	u_int config;		/* I/O page register content */
7924f67f6bSmarc 	u_int mapped;		/* user mapping status word */
80e977faadSmarc 	u_int kernel_loop;	/* if kernel console is redirected */
8124f67f6bSmarc 	u_int user_dma;		/* DMA from user space in progress */
8224f67f6bSmarc 	u_short pntr_id;	/* type code of pointing device */
8324f67f6bSmarc 	u_short duart_imask;	/* shadowing for duart intrpt mask reg */
8424f67f6bSmarc 	u_short adder_ie;	/* shadowing for adder intrpt enbl reg */
8524f67f6bSmarc 	u_short curs_acc;	/* cursor acceleration factor */
8624f67f6bSmarc 	u_short curs_thr;	/* cursor acceleration threshold level */
8724f67f6bSmarc 	u_short tab_res;	/* tablet resolution factor */
8824f67f6bSmarc 	u_short selmask;	/* mask for active qd select entries */
8924f67f6bSmarc };
9024f67f6bSmarc 
91b2b69f49Smarc /*
92b2b69f49Smarc  * bit definitions for 'inuse' entry
93b2b69f49Smarc  */
9424f67f6bSmarc #define CONS_DEV	0x01
9524f67f6bSmarc #define GRAPHIC_DEV	0x04
9624f67f6bSmarc 
97b2b69f49Smarc /*
98b2b69f49Smarc  * bit definitions for 'mapped' member of flag structure
99b2b69f49Smarc  */
10024f67f6bSmarc #define MAPDEV		0x01		/* hardware is mapped */
10124f67f6bSmarc #define MAPDMA		0x02		/* DMA buffer mapped */
10224f67f6bSmarc #define MAPEQ		0x04		/* event queue buffer mapped */
10324f67f6bSmarc #define MAPSCR		0x08		/* scroll param area mapped */
10424f67f6bSmarc #define MAPCOLOR	0x10		/* color map writing buffer mapped */
10524f67f6bSmarc 
106b2b69f49Smarc /*
107b2b69f49Smarc  * bit definitions for 'selmask' member of qdflag structure
108b2b69f49Smarc  */
10924f67f6bSmarc #define SEL_READ	0x01		/* read select is active */
11024f67f6bSmarc #define SEL_WRITE	0x02		/* write select is active */
11124f67f6bSmarc 
112b2b69f49Smarc /*
113b2b69f49Smarc  * constants used in shared memory operations
114b2b69f49Smarc  */
11524f67f6bSmarc #define EVENT_BUFSIZE  1024	/* # of bytes per device's event buffer */
11624f67f6bSmarc #define MAXEVENTS  ( (EVENT_BUFSIZE - sizeof(struct qdinput))	 \
11724f67f6bSmarc 	/ sizeof(struct _vs_event) )
1180d59d4d6Smarc #define DMA_BUFSIZ	(1024 * 10)
11924f67f6bSmarc #define COLOR_BUFSIZ  ((sizeof(struct color_buf) + 512) & ~0x01FF)
12024f67f6bSmarc 
121b2b69f49Smarc /*
12224f67f6bSmarc  * reference to an array of "uba_device" structures built by the auto
12324f67f6bSmarc  * configuration program.  The uba_device structure decribes the device
12424f67f6bSmarc  * sufficiently for the driver to talk to it.  The auto configuration code
12524f67f6bSmarc  * fills in the uba_device structures (located in ioconf.c) from user
126b2b69f49Smarc  * maintained info.
127b2b69f49Smarc  */
12824f67f6bSmarc struct uba_device *qdinfo[NQD];  /* array of pntrs to each QDSS's */
12924f67f6bSmarc struct tty qd_tty[NQD*4];	/* teletype structures for each.. */
1307881ece5Smarc extern char qvmem[][128*NBPG];
131b2b69f49Smarc extern struct pte QVmap[][128];
132b2b69f49Smarc #define CHUNK	  (64 * 1024)
133b2b69f49Smarc #define QMEMSIZE  (1024 * 1024 * 4)	/* 4 meg */
13424f67f6bSmarc 
135b2b69f49Smarc /*
136b2b69f49Smarc  * static storage used by multiple functions in this code
137b2b69f49Smarc  */
13824f67f6bSmarc int Qbus_unmap[NQD];		/* Qbus mapper release code */
13924f67f6bSmarc struct qdflags qdflags[NQD];	/* QDSS device status flags */
14024f67f6bSmarc struct qdmap qdmap[NQD];	/* QDSS register map structure */
14124f67f6bSmarc caddr_t qdbase[NQD];		/* base address of each QDSS unit */
14224f67f6bSmarc struct buf qdbuf[NQD];		/* buf structs used by strategy */
143b2b69f49Smarc short qdopened[NQD];		/* graphics device is open exclusive use */
14424f67f6bSmarc 
145b2b69f49Smarc /*
146e977faadSmarc  * the array "event_shared[]" is made up of a number of event queue buffers
14724f67f6bSmarc  * equal to the number of QDSS's configured into the running kernel (NQD).
14824f67f6bSmarc  * Each event queue buffer begins with an event queue header (struct qdinput)
14924f67f6bSmarc  * followed by a group of event queue entries (struct _vs_event).  The array
15024f67f6bSmarc  * "*eq_header[]" is an array of pointers to the start of each event queue
151b2b69f49Smarc  * buffer in "event_shared[]".
152b2b69f49Smarc  */
15324f67f6bSmarc #define EQSIZE ((EVENT_BUFSIZE * NQD) + 512)
15424f67f6bSmarc 
15524f67f6bSmarc char event_shared[EQSIZE];	    /* reserve space for event bufs */
15624f67f6bSmarc struct qdinput *eq_header[NQD];     /* event queue header pntrs */
15724f67f6bSmarc 
158b2b69f49Smarc /*
15924f67f6bSmarc  * This allocation method reserves enough memory pages for NQD shared DMA I/O
16024f67f6bSmarc  * buffers.  Each buffer must consume an integral number of memory pages to
16124f67f6bSmarc  * guarantee that a following buffer will begin on a page boundary.  Also,
16224f67f6bSmarc  * enough space is allocated so that the FIRST I/O buffer can start at the
16324f67f6bSmarc  * 1st page boundary after "&DMA_shared".  Page boundaries are used so that
164b2b69f49Smarc  * memory protections can be turned on/off for individual buffers.
165b2b69f49Smarc  */
16624f67f6bSmarc #define IOBUFSIZE  ((DMA_BUFSIZ * NQD) + 512)
16724f67f6bSmarc 
16824f67f6bSmarc char DMA_shared[IOBUFSIZE];	    /* reserve I/O buffer space */
16924f67f6bSmarc struct DMAreq_header *DMAheader[NQD];  /* DMA buffer header pntrs */
17024f67f6bSmarc 
171b2b69f49Smarc /*
17224f67f6bSmarc  * The driver assists a client in scroll operations by loading dragon
17324f67f6bSmarc  * registers from an interrupt service routine.	The loading is done using
17424f67f6bSmarc  * parameters found in memory shrade between the driver and it's client.
17524f67f6bSmarc  * The scroll parameter structures are ALL loacted in the same memory page
176b2b69f49Smarc  * for reasons of memory economy.
177b2b69f49Smarc  */
17824f67f6bSmarc char scroll_shared[2 * 512];	/* reserve space for scroll structs */
17924f67f6bSmarc struct scroll *scroll[NQD];	/* pointers to scroll structures */
18024f67f6bSmarc 
181b2b69f49Smarc /*
18224f67f6bSmarc  * the driver is programmable to provide the user with color map write
18324f67f6bSmarc  * services at VSYNC interrupt time.  At interrupt time the driver loads
184b2b69f49Smarc  * the color map with any user-requested load data found in shared memory
185b2b69f49Smarc  */
18624f67f6bSmarc #define COLOR_SHARED  ((COLOR_BUFSIZ * NQD) + 512)
18724f67f6bSmarc 
188e977faadSmarc char color_shared[COLOR_SHARED];      /* reserve space: color bufs */
18924f67f6bSmarc struct color_buf *color_buf[NQD];     /* pointers to color bufs */
19024f67f6bSmarc 
191b2b69f49Smarc /*
192b2b69f49Smarc  * mouse input event structures
193b2b69f49Smarc  */
19424f67f6bSmarc struct mouse_report last_rep[NQD];
19524f67f6bSmarc struct mouse_report current_rep[NQD];
19624f67f6bSmarc 
1977881ece5Smarc struct proc *qdrsel[NQD]; 	/* process waiting for select */
198b2b69f49Smarc struct _vs_cursor cursor[NQD];	/* console cursor */
199b2b69f49Smarc int qdcount = 0;		/* count of successfully probed qd's */
20024f67f6bSmarc int nNQD = NQD;
20124f67f6bSmarc int DMAbuf_size = DMA_BUFSIZ;
202e977faadSmarc int QDlast_DMAtype;             /* type of the last DMA operation */
203e977faadSmarc 
204b2b69f49Smarc #define QDSSMAJOR	41	/* QDSS major device number */
205b2b69f49Smarc /*
206b2b69f49Smarc  * macro to get system time.  Used to time stamp event queue entries
207b2b69f49Smarc  */
2087e911b15Skarels #define TOY ((time.tv_sec * 100) + (time.tv_usec / 10000))
2097e911b15Skarels 
2107e911b15Skarels int qdprobe();
2117e911b15Skarels int qdattach();
2127e911b15Skarels int qddint();			/* DMA gate array intrpt service */
2137e911b15Skarels int qdaint();			/* Dragon ADDER intrpt service */
2147e911b15Skarels int qdiint();
2157e911b15Skarels 
2167e911b15Skarels u_short qdstd[] = { 0 };
2177e911b15Skarels 
218b2b69f49Smarc struct uba_driver qddriver = {
2197e911b15Skarels 	qdprobe,		/* device probe entry */
2207e911b15Skarels 	0,			/* no slave device */
2217e911b15Skarels 	qdattach,		/* device attach entry */
2227e911b15Skarels 	0,			/* no "fill csr/ba to start" */
2237e911b15Skarels 	qdstd,			/* device addresses */
2247e911b15Skarels 	"qd",			/* device name string */
2257e911b15Skarels 	qdinfo			/* ptr to QDSS's uba_device struct */
2267e911b15Skarels };
2277e911b15Skarels 
228e977faadSmarc #define QDPRIOR (PZERO-1)		/* must be negative */
2297e911b15Skarels #define FALSE	0
2307e911b15Skarels #define TRUE	~FALSE
2317e911b15Skarels #define BAD	-1
2327e911b15Skarels #define GOOD	0
2337e911b15Skarels 
234b2b69f49Smarc /*
235b2b69f49Smarc  * macro to create a system virtual page number from system virtual adrs
236b2b69f49Smarc  */
237b2b69f49Smarc #define VTOP(x)  (((int)x & ~0xC0000000) >> PGSHIFT)
2387e911b15Skarels 
239b2b69f49Smarc /*
240b2b69f49Smarc  * QDSS register address offsets from start of QDSS address space
241b2b69f49Smarc  */
2427e911b15Skarels #define QDSIZE	 (52 * 1024)	/* size of entire QDSS foot print */
2437e911b15Skarels #define TMPSIZE  (16 * 1024)	/* template RAM is 8k SHORT WORDS */
2447e911b15Skarels #define TMPSTART 0x8000 	/* offset of template RAM from base adrs */
2457e911b15Skarels #define REGSIZE  (5 * 512)	/* regs touch 2.5k (5 pages) of addr space */
2467e911b15Skarels #define REGSTART 0xC000 	/* offset of reg pages from base adrs */
2477e911b15Skarels #define ADDER	(REGSTART+0x000)
2487e911b15Skarels #define DGA	(REGSTART+0x200)
2497e911b15Skarels #define DUART	(REGSTART+0x400)
2507e911b15Skarels #define MEMCSR	(REGSTART+0x800)
2517e911b15Skarels #define CLRSIZE  (3 * 512)		/* color map size */
2527e911b15Skarels #define CLRSTART (REGSTART+0xA00)	/* color map start offset from base */
2537e911b15Skarels /*  0x0C00 really */
2547e911b15Skarels #define RED	(CLRSTART+0x000)
2557e911b15Skarels #define BLUE	(CLRSTART+0x200)
2567e911b15Skarels #define GREEN	(CLRSTART+0x400)
2577e911b15Skarels 
2587e911b15Skarels 
259b2b69f49Smarc /*
2607e911b15Skarels  * QDSS minor device numbers.  The *real* minor device numbers are in
2617e911b15Skarels  * the bottom two bits of the major/minor device spec.  Bits 2 and up are
262b2b69f49Smarc  * used to specify the QDSS device number (ie: which one?)
263b2b69f49Smarc  */
2647e911b15Skarels 
2657e911b15Skarels #define CONS		0
2667e911b15Skarels #define GRAPHIC 	2
2677e911b15Skarels 
268b2b69f49Smarc /*
269b2b69f49Smarc  * console cursor bitmap (white block cursor)
270b2b69f49Smarc  */
271b2b69f49Smarc short cons_cursor[32] = {
2727e911b15Skarels 	/* A */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
2737e911b15Skarels 	0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
2747e911b15Skarels 	/* B */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
2757e911b15Skarels 	0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF
2767e911b15Skarels };
2777e911b15Skarels 
278b2b69f49Smarc /*
279b2b69f49Smarc  * constants used in font operations
280b2b69f49Smarc  */
281e977faadSmarc #define CHARS		190 			/* # of chars in the font */
2827e911b15Skarels #define CHAR_HEIGHT	15			/* char height in pixels */
2837e911b15Skarels #define CHAR_WIDTH	8			/* char width in pixels*/
2847e911b15Skarels #define FONT_WIDTH	(CHAR_WIDTH * CHARS)	/* font width in pixels */
2857e911b15Skarels #define ROWS		CHAR_HEIGHT
2867e911b15Skarels #define FONT_X		0			/* font's off screen adrs */
2877e911b15Skarels #define FONT_Y		(2048 - CHAR_HEIGHT)
288e977faadSmarc 
289b2b69f49Smarc /* Offset to second row characters (XXX - should remove) */
290e977faadSmarc #define FONT_OFFSET	((MAX_SCREEN_X/CHAR_WIDTH)*CHAR_HEIGHT)
2917e911b15Skarels 
2927e911b15Skarels extern char q_font[];		/* reference font object code */
293e977faadSmarc extern	u_short q_key[];	/* reference key xlation tables */
294e977faadSmarc extern	u_short q_shift_key[];
2957e911b15Skarels extern	char *q_special[];
2967e911b15Skarels 
297b2b69f49Smarc /*
298b2b69f49Smarc  * definitions for cursor acceleration reporting
299b2b69f49Smarc  */
3007e911b15Skarels #define ACC_OFF 	0x01		/* acceleration is inactive */
3017e911b15Skarels 
302b2b69f49Smarc /*
303b2b69f49Smarc  * virtual console support.
3047e911b15Skarels  */
305e977faadSmarc extern (*v_putc)();
306*f79d7b48Smarc #ifdef KADB
307*f79d7b48Smarc extern (*v_getc)();
308*f79d7b48Smarc extern (*v_poll)();
309*f79d7b48Smarc #endif
310e977faadSmarc extern struct cdevsw *consops;
311e977faadSmarc int qdputc();
312*f79d7b48Smarc int qdgetc();
313*f79d7b48Smarc int qdpoll();
314e977faadSmarc int qdstart();
315*f79d7b48Smarc int qdpolling = 0;
316e977faadSmarc 
317b2b69f49Smarc /*
318b2b69f49Smarc  * LK-201 state storage for input console keyboard conversion to ASCII
319b2b69f49Smarc  */
3207e911b15Skarels struct q_keyboard {
3217e911b15Skarels 	int shift;			/* state variables	*/
3227e911b15Skarels 	int cntrl;
3237e911b15Skarels 	int lock;
3247e911b15Skarels 	int lastcode;			/* last keycode typed	*/
3257e911b15Skarels 	unsigned kup[8];		/* bits for each keycode*/
3267e911b15Skarels 	unsigned dkeys[8];		/* down/up mode keys	*/
3277e911b15Skarels 	char last;			/* last character	*/
3287e911b15Skarels } q_keyboard;
3297e911b15Skarels 
330b2b69f49Smarc /*
331b2b69f49Smarc  * tty settings on first open
332b2b69f49Smarc  */
333*f79d7b48Smarc #define IFLAG (BRKINT|ISTRIP|IXON|IXANY|ICRNL|IMAXBEL)
334e977faadSmarc #define OFLAG (OPOST|OXTABS|ONLCR)
335*f79d7b48Smarc #define LFLAG (ISIG|ICANON|ECHO|IEXTEN)
336e977faadSmarc #define CFLAG (PARENB|CREAD|CS7|CLOCAL)
337e977faadSmarc 
3387881ece5Smarc /*
3397881ece5Smarc  * Init QDSS as console (before probe routine)
3407881ece5Smarc  */
3417e911b15Skarels 
3427e911b15Skarels qdcons_init()
3437e911b15Skarels {
3447881ece5Smarc 	register unit;
3457e911b15Skarels 	caddr_t phys_adr;		/* physical QDSS base adrs */
346e977faadSmarc 	u_int mapix;			/* index into QVmap[] array */
347e977faadSmarc 	struct percpu *pcpu;		/* pointer to cpusw structure  */
348e977faadSmarc 	register struct qbus *qb;
3497e911b15Skarels 	u_short *qdaddr;		/* address of QDSS IO page CSR */
3507e911b15Skarels 	u_short *devptr;		/* vitual device space */
351e977faadSmarc 	extern cnputc();
3527e911b15Skarels 
3537e911b15Skarels #define QDSSCSR 0x1F00
3547e911b15Skarels 
35524f67f6bSmarc 	if (v_putc != cnputc)
3567881ece5Smarc 	    return 0;
35724f67f6bSmarc 
3587e911b15Skarels 	unit = 0;
3597e911b15Skarels 
360b2b69f49Smarc 	/*
361b2b69f49Smarc 	 * find the cpusw entry that matches this machine.
362b2b69f49Smarc 	 */
36324f67f6bSmarc 	for (pcpu = percpu; pcpu && pcpu->pc_cputype != cpu; pcpu++)
3647e911b15Skarels 		;
36524f67f6bSmarc 	if (pcpu == NULL)
3667881ece5Smarc 	    return 0;
3672b86b1e4Stef 	if (pcpu->pc_io->io_type != IO_QBUS)
3682b86b1e4Stef 	    return 0;
36924f67f6bSmarc 
37024f67f6bSmarc 	/*
371e977faadSmarc 	 * Map device registers - the last 8K of qvmem.
37224f67f6bSmarc 	 */
37324f67f6bSmarc 	qb = (struct qbus *)pcpu->pc_io->io_details;
37424f67f6bSmarc 	ioaccess(qb->qb_iopage, UMEMmap[0] + qb->qb_memsize,
37524f67f6bSmarc 		 UBAIOPAGES * NBPG);
37624f67f6bSmarc 	devptr = (u_short *)((char *)umem[0]+(qb->qb_memsize * NBPG));
37724f67f6bSmarc 	qdaddr = (u_short *)((u_int)devptr + ubdevreg(QDSSCSR));
3787881ece5Smarc 	if (badaddr((caddr_t)qdaddr, sizeof(short)))
3797881ece5Smarc 		return 0;
380e977faadSmarc 
38124f67f6bSmarc 	/*
38224f67f6bSmarc 	 * Map q-bus memory used by qdss. (separate map)
38324f67f6bSmarc 	 */
38424f67f6bSmarc 	mapix = QMEMSIZE - (CHUNK * (unit + 1));
38524f67f6bSmarc 	phys_adr = qb->qb_maddr + mapix;
38624f67f6bSmarc 	ioaccess(phys_adr, QVmap[0], (CHUNK*NQD));
3877e911b15Skarels 
38824f67f6bSmarc 	/*
38924f67f6bSmarc 	 * tell QDSS which Q memory address base to decode
390b2b69f49Smarc 	 * (shifted right 16 bits - its in 64K units)
39124f67f6bSmarc 	 */
39224f67f6bSmarc 	*qdaddr = (u_short)((int)mapix >> 16);
3937e911b15Skarels 	qdflags[unit].config = *(u_short *)qdaddr;
3947e911b15Skarels 
395b2b69f49Smarc 	/*
396b2b69f49Smarc 	 * load qdmap struct with the virtual addresses of the QDSS elements
397b2b69f49Smarc 	 */
398e977faadSmarc 	qdbase[unit] = (caddr_t) (qvmem[0]);
3997e911b15Skarels 	qdmap[unit].template = qdbase[unit] + TMPSTART;
4007e911b15Skarels 	qdmap[unit].adder = qdbase[unit] + ADDER;
4017e911b15Skarels 	qdmap[unit].dga = qdbase[unit] + DGA;
4027e911b15Skarels 	qdmap[unit].duart = qdbase[unit] + DUART;
4037e911b15Skarels 	qdmap[unit].memcsr = qdbase[unit] + MEMCSR;
4047e911b15Skarels 	qdmap[unit].red = qdbase[unit] + RED;
4057e911b15Skarels 	qdmap[unit].blue = qdbase[unit] + BLUE;
4067e911b15Skarels 	qdmap[unit].green = qdbase[unit] + GREEN;
4077e911b15Skarels 
4087e911b15Skarels 	qdflags[unit].duart_imask = 0;	/* init shadow variables */
4097e911b15Skarels 
410b2b69f49Smarc 	/*
411b2b69f49Smarc 	 * init the QDSS
412b2b69f49Smarc 	 */
413b2b69f49Smarc 	/*
41424f67f6bSmarc 	printf("qdbase[0] = %x, qdmap[0].memcsr = %x\n",
41524f67f6bSmarc 		(char *)qdbase[0], qdmap[0].memcsr);
416b2b69f49Smarc 	*/
4177e911b15Skarels 
4187e911b15Skarels 	*(short *)qdmap[unit].memcsr |= SYNC_ON; /* once only: turn on sync */
4197e911b15Skarels 
4207e911b15Skarels 	cursor[unit].x = 0;
4217e911b15Skarels 	cursor[unit].y = 0;
4227e911b15Skarels 	init_shared(unit);		/* init shared memory */
4237e911b15Skarels 	setup_dragon(unit);		/* init the ADDER/VIPER stuff */
4247e911b15Skarels 	clear_qd_screen(unit);		/* clear the screen */
4257e911b15Skarels 	ldfont(unit);			/* load the console font */
4267e911b15Skarels 	ldcursor(unit, cons_cursor);	/* load default cursor map */
4277e911b15Skarels 	setup_input(unit);		/* init the DUART */
428b2b69f49Smarc 	v_putc = qdputc;		/* kernel console output to qdss */
429*f79d7b48Smarc #ifdef KADB
430*f79d7b48Smarc 	v_getc = qdgetc;		/* kernel console input from qdss */
431*f79d7b48Smarc 	v_poll = qdpoll;		/* kdb hook to disable char intr */
432*f79d7b48Smarc #endif
433b2b69f49Smarc 	consops = &cdevsw[QDSSMAJOR];	/* virtual console is qdss */
4347881ece5Smarc 	return 1;
4357e911b15Skarels 
4367e911b15Skarels } /* qdcons_init */
4377e911b15Skarels 
4387881ece5Smarc /*
4397881ece5Smarc  *  Configure QDSS into Q memory and make it intrpt.
4407e911b15Skarels  *
4417e911b15Skarels  *  side effects: QDSS gets mapped into Qbus memory space at the first
4427e911b15Skarels  *		 vacant 64kb boundary counting back from the top of
443e977faadSmarc  *		 Qbus memory space (qvmem+4mb)
4447e911b15Skarels  *
4457e911b15Skarels  *  return: QDSS bus request level and vector address returned in
4467e911b15Skarels  *	   registers by UNIX convention.
4477e911b15Skarels  *
4487881ece5Smarc  */
4497e911b15Skarels qdprobe(reg)
4507881ece5Smarc 	caddr_t reg;	/* character pointer to the QDSS I/O page register */
4517e911b15Skarels {
452*f79d7b48Smarc 	register int br, cvec;
4537e911b15Skarels 	register int unit;
4547e911b15Skarels 	struct dga *dga;		/* pointer to gate array structure */
4557e911b15Skarels 	int vector;
4567881ece5Smarc #ifdef notdef
4577881ece5Smarc 	int *ptep;			/* page table entry pointer */
4587e911b15Skarels 	caddr_t phys_adr;		/* physical QDSS base adrs */
4597e911b15Skarels 	u_int mapix;
4607881ece5Smarc #endif
4617881ece5Smarc 
4627881ece5Smarc #ifdef lint
4637881ece5Smarc 	br = 0; cvec = br; br = cvec; nNQD = br; br = nNQD;
4647881ece5Smarc 	qddint(0); qdaint(0); qdiint(0); (void)qdgetc();
4657881ece5Smarc #endif
4667e911b15Skarels 
467b2b69f49Smarc 	/*
468b2b69f49Smarc 	 * calculate board unit number from I/O page register address
469b2b69f49Smarc 	 */
4707e911b15Skarels 	unit = (int) (((int)reg >> 1) & 0x0007);
4717e911b15Skarels 
472b2b69f49Smarc 	/*
473b2b69f49Smarc 	 * QDSS regs must be mapped to Qbus memory space at a 64kb
474b2b69f49Smarc  	 * physical boundary.  The Qbus memory space is mapped into
475b2b69f49Smarc 	 * the system memory space at config time.  After config
476b2b69f49Smarc 	 * runs, "qvmem[0]" (ubavar.h) holds the system virtual adrs
477b2b69f49Smarc 	 * of the start of Qbus memory.   The Qbus memory page table
478b2b69f49Smarc 	 * is found via an array of pte ptrs called "QVmap[]" (ubavar.h)
479b2b69f49Smarc 	 * which is also loaded at config time.   These are the
480b2b69f49Smarc 	 * variables used below to find a vacant 64kb boundary in
481b2b69f49Smarc 	 * Qbus memory, and load it's corresponding physical adrs
482b2b69f49Smarc 	 * into the QDSS's I/O page CSR.
483b2b69f49Smarc 	 */
484e977faadSmarc 
485e977faadSmarc 	/*
486e977faadSmarc 	 * Only if QD is the graphics device.
48724f67f6bSmarc 	 */
4887e911b15Skarels 
4897e911b15Skarels 	/* if this QDSS is NOT the console, then do init here.. */
4907e911b15Skarels 
491e977faadSmarc 	if (unit != 0) {
492e977faadSmarc 		printf("qd: can't support two qdss's (yet)\n");
4937881ece5Smarc #ifdef notdef	/* can't test */
4947e911b15Skarels 		if (v_consputc != qdputc  ||  unit != 0) {
4957e911b15Skarels 
496b2b69f49Smarc 			/*
497b2b69f49Smarc 			* read QDSS config info
498b2b69f49Smarc 			*/
4997e911b15Skarels 			qdflags[unit].config = *(u_short *)reg;
5007e911b15Skarels 
501b2b69f49Smarc 			/*
502b2b69f49Smarc 			* find an empty 64kb adrs boundary
503b2b69f49Smarc 			*/
5047e911b15Skarels 
505e977faadSmarc 			qdbase[unit] = (caddr_t) (qvmem[0] + QMEMSIZE - CHUNK);
506e977faadSmarc 
507b2b69f49Smarc 			/*
5087881ece5Smarc 			* find the cpusw entry that matches this machine.
5097881ece5Smarc 			*/
5107e911b15Skarels 			cpup = &cpusw[cpu];
5117e911b15Skarels 			while (!(BADADDR(qdbase[unit], sizeof(short))))
5127e911b15Skarels 				qdbase[unit] -= CHUNK;
5137e911b15Skarels 
514b2b69f49Smarc 			/*
5157881ece5Smarc 			* tell QDSS which Q memory address base to decode
5167881ece5Smarc 			*/
517e977faadSmarc 			mapix = (int) (VTOP(qdbase[unit]) - VTOP(qvmem[0]));
518e977faadSmarc 			ptep = (int *) QVmap[0] + mapix;
5197e911b15Skarels 			phys_adr = (caddr_t)(((int)*ptep&0x001FFFFF)<<PGSHIFT);
5207e911b15Skarels 			*(u_short *)reg = (u_short) ((int)phys_adr >> 16);
5217e911b15Skarels 
522b2b69f49Smarc 			/*
523b2b69f49Smarc 			* load QDSS adrs map with system addresses
524b2b69f49Smarc 			* of device regs
525b2b69f49Smarc 			*/
5267e911b15Skarels 			qdmap[unit].template = qdbase[unit] + TMPSTART;
5277e911b15Skarels 			qdmap[unit].adder = qdbase[unit] + ADDER;
5287e911b15Skarels 			qdmap[unit].dga = qdbase[unit] + DGA;
5297e911b15Skarels 			qdmap[unit].duart = qdbase[unit] + DUART;
5307e911b15Skarels 			qdmap[unit].memcsr = qdbase[unit] + MEMCSR;
5317e911b15Skarels 			qdmap[unit].red = qdbase[unit] + RED;
5327e911b15Skarels 			qdmap[unit].blue = qdbase[unit] + BLUE;
5337e911b15Skarels 			qdmap[unit].green = qdbase[unit] + GREEN;
5347e911b15Skarels 
5357e911b15Skarels 			/* device init */
5367e911b15Skarels 
5377e911b15Skarels 			cursor[unit].x = 0;
5387e911b15Skarels 			cursor[unit].y = 0;
5397e911b15Skarels 			init_shared(unit);		/* init shared memory */
5407e911b15Skarels 			setup_dragon(unit); 	/* init the ADDER/VIPER stuff */
5417e911b15Skarels 			ldcursor(unit, cons_cursor);	/* load default cursor map */
5427e911b15Skarels 			setup_input(unit);		/* init the DUART */
5437e911b15Skarels 			clear_qd_screen(unit);
5447e911b15Skarels 			ldfont(unit);			/* load the console font */
5457e911b15Skarels 
5467e911b15Skarels 			/* once only: turn on sync */
5477e911b15Skarels 
5487e911b15Skarels 			*(short *)qdmap[unit].memcsr |= SYNC_ON;
549b2b69f49Smarc 		}
550006e9885Smarc #endif /*notdef*/
551e977faadSmarc 	}
5527e911b15Skarels 
553b2b69f49Smarc 	/*
554b2b69f49Smarc 	* The QDSS interrupts at HEX vectors xx0 (DMA) xx4
555b2b69f49Smarc 	* (ADDER) and xx8 (DUART).  Therefore, we take three
556b2b69f49Smarc 	* vectors from the vector pool, and then continue
557b2b69f49Smarc 	* to take them until we get a xx0 HEX vector.  The
558b2b69f49Smarc 	* pool provides vectors in contiguous decending
559b2b69f49Smarc 	* order.
560b2b69f49Smarc 	*/
5617e911b15Skarels 
5627e911b15Skarels 	vector = (uba_hd[0].uh_lastiv -= 4*3);	/* take three vectors */
5637e911b15Skarels 
5647e911b15Skarels 	while (vector & 0x0F) {		   /* if lo nibble != 0.. */
565b2b69f49Smarc 		/* ..take another vector */
566b2b69f49Smarc 		vector = (uba_hd[0].uh_lastiv -= 4);
5677e911b15Skarels 	}
5687e911b15Skarels 
569b2b69f49Smarc 	/*
570b2b69f49Smarc 	* setup DGA to do a DMA interrupt (transfer count = 0)
571b2b69f49Smarc 	*/
5727e911b15Skarels 	dga = (struct dga *) qdmap[unit].dga;
5737e911b15Skarels 	dga->csr = (short) HALT;	/* disable everything */
5747e911b15Skarels 	dga->ivr = (short) vector;	/* load intrpt base vector */
5757e911b15Skarels 	dga->bytcnt_lo = (short) 0;	/* DMA xfer count = 0 */
5767e911b15Skarels 	dga->bytcnt_hi = (short) 0;
5777e911b15Skarels 
578b2b69f49Smarc 	/*
579b2b69f49Smarc 	* turn on DMA interrupts
580b2b69f49Smarc 	*/
5817e911b15Skarels 	dga->csr &= ~SET_DONE_FIFO;
5827e911b15Skarels 	dga->csr |= DMA_IE | DL_ENB;
5837e911b15Skarels 
5847e911b15Skarels 	DELAY(20000);			/* wait for the intrpt */
5857e911b15Skarels 	dga->csr = HALT;		/* stop the wheels */
5867e911b15Skarels 
5877e911b15Skarels 	if (cvec != vector)		/* if vector != base vector.. */
5887e911b15Skarels 		return(0);		/* ..return = 'no device' */
5897e911b15Skarels 
590e977faadSmarc 	/*
591e977faadSmarc 	* score this as an existing qdss
592e977faadSmarc 	*/
593e977faadSmarc 	qdcount++;
594e977faadSmarc 
5957e911b15Skarels 	return(sizeof(short));	    /* return size of QDSS I/O page reg */
5967e911b15Skarels 
5977e911b15Skarels } /* qdprobe */
5987e911b15Skarels 
5997e911b15Skarels qdattach(ui)
6007e911b15Skarels 	struct uba_device *ui;
6017e911b15Skarels {
6027881ece5Smarc 	register unit;			/* QDSS module # for this call */
6037e911b15Skarels 
6047e911b15Skarels 	unit = ui->ui_unit;		/* get QDSS number */
6057e911b15Skarels 
606b2b69f49Smarc 	/*
607b2b69f49Smarc 	* init "qdflags[]" for this QDSS
608b2b69f49Smarc 	*/
6097e911b15Skarels 	qdflags[unit].inuse = 0;	/* init inuse variable EARLY! */
6107e911b15Skarels 	qdflags[unit].mapped = 0;
611e977faadSmarc 	qdflags[unit].kernel_loop = -1;
6127e911b15Skarels 	qdflags[unit].user_dma = 0;
6137e911b15Skarels 	qdflags[unit].curs_acc = ACC_OFF;
6147e911b15Skarels 	qdflags[unit].curs_thr = 128;
6157e911b15Skarels 	qdflags[unit].tab_res = 2;	/* default tablet resolution factor */
6167e911b15Skarels 	qdflags[unit].duart_imask = 0;	/* init shadow variables */
6177e911b15Skarels 	qdflags[unit].adder_ie = 0;
6187e911b15Skarels 
619b2b69f49Smarc 	/*
6207e911b15Skarels 	* init structures used in kbd/mouse interrupt service.	This code must
621b2b69f49Smarc 	* come after the "init_shared()" routine has run since that routine
622b2b69f49Smarc 	* inits the eq_header[unit] structure used here.
623b2b69f49Smarc 	*/
6247e911b15Skarels 
625b2b69f49Smarc 	/*
626b2b69f49Smarc 	* init the "latest mouse report" structure
627b2b69f49Smarc 	*/
6287e911b15Skarels 	last_rep[unit].state = 0;
6297e911b15Skarels 	last_rep[unit].dx = 0;
6307e911b15Skarels 	last_rep[unit].dy = 0;
6317e911b15Skarels 	last_rep[unit].bytcnt = 0;
6327e911b15Skarels 
633b2b69f49Smarc 	/*
6347881ece5Smarc 	* init the event queue (except mouse position)
6357881ece5Smarc 	*/
6367881ece5Smarc 	eq_header[unit]->header.events =
6377881ece5Smarc 	    (struct _vs_event *)((int)eq_header[unit] + sizeof(struct qdinput));
6387e911b15Skarels 
6397e911b15Skarels 	eq_header[unit]->header.size = MAXEVENTS;
6407e911b15Skarels 	eq_header[unit]->header.head = 0;
6417e911b15Skarels 	eq_header[unit]->header.tail = 0;
6427e911b15Skarels 
643b2b69f49Smarc 	/*
644b2b69f49Smarc 	 * open exclusive for graphics device.
645b2b69f49Smarc 	 */
646b2b69f49Smarc 	qdopened[unit] = 0;
6477e911b15Skarels 
6487e911b15Skarels } /* qdattach */
6497e911b15Skarels 
6507881ece5Smarc /*ARGSUSED*/
6517e911b15Skarels qdopen(dev, flag)
6527e911b15Skarels 	dev_t dev;
6537e911b15Skarels 	int flag;
6547e911b15Skarels {
6557e911b15Skarels 	register struct uba_device *ui; /* ptr to uba structures */
6567e911b15Skarels 	register struct dga *dga;	/* ptr to gate array struct */
6577e911b15Skarels 	register struct tty *tp;
6587e911b15Skarels 	struct duart *duart;
6597881ece5Smarc 	int unit;
6607881ece5Smarc 	int minor_dev;
6617e911b15Skarels 
6627e911b15Skarels 	minor_dev = minor(dev); /* get QDSS minor device number */
6637e911b15Skarels 	unit = minor_dev >> 2;
6647e911b15Skarels 
665b2b69f49Smarc 	/*
666b2b69f49Smarc 	* check for illegal conditions
667b2b69f49Smarc 	*/
6687e911b15Skarels 	ui = qdinfo[unit];		/* get ptr to QDSS device struct */
6697e911b15Skarels 	if (ui == 0  || ui->ui_alive == 0)
6707e911b15Skarels 		return(ENXIO);		/* no such device or address */
6717e911b15Skarels 
6727e911b15Skarels 	duart = (struct duart *) qdmap[unit].duart;
6737e911b15Skarels 	dga = (struct dga *) qdmap[unit].dga;
6747e911b15Skarels 
6757e911b15Skarels 	if ((minor_dev & 0x03) == 2) {
676b2b69f49Smarc 		/*
677b2b69f49Smarc 		* this is the graphic device...
678b2b69f49Smarc 		*/
679b2b69f49Smarc 		if (qdopened[unit] != 0)
6807e911b15Skarels 			return(EBUSY);
6817e911b15Skarels 		else
682b2b69f49Smarc 			qdopened[unit] = 1;
6837e911b15Skarels 		qdflags[unit].inuse |= GRAPHIC_DEV;  /* graphics dev is open */
684b2b69f49Smarc 		/*
685b2b69f49Smarc 		 * enble kbd & mouse intrpts in DUART mask reg
686b2b69f49Smarc 		 */
6877e911b15Skarels 		qdflags[unit].duart_imask |= 0x22;
6887e911b15Skarels 		duart->imask = qdflags[unit].duart_imask;
689b2b69f49Smarc 	} else {
690b2b69f49Smarc 		/*
691b2b69f49Smarc 		* this is the console
692b2b69f49Smarc 		*/
6937e911b15Skarels 		qdflags[unit].inuse |= CONS_DEV;  /* mark console as open */
6947e911b15Skarels 		dga->csr |= CURS_ENB;
6957e911b15Skarels 		qdflags[unit].duart_imask |= 0x02;
6967e911b15Skarels 		duart->imask = qdflags[unit].duart_imask;
697b2b69f49Smarc 		/*
698b2b69f49Smarc 		* some setup for tty handling
699b2b69f49Smarc 		*/
7007e911b15Skarels 		tp = &qd_tty[minor_dev];
7017e911b15Skarels 		tp->t_addr = ui->ui_addr;
7027e911b15Skarels 		tp->t_oproc = qdstart;
7037e911b15Skarels 		if ((tp->t_state & TS_ISOPEN) == 0) {
7047e911b15Skarels 			ttychars(tp);
7057e911b15Skarels 			tp->t_ispeed = B9600;
7067e911b15Skarels 			tp->t_ospeed = B9600;
707e977faadSmarc 			tp->t_state = TS_ISOPEN | TS_CARR_ON;
708b2b69f49Smarc 			tp->t_iflag = TTYDEF_IFLAG;
709b2b69f49Smarc 			tp->t_oflag = TTYDEF_OFLAG;
710b2b69f49Smarc 			tp->t_lflag = TTYDEF_LFLAG;
711b2b69f49Smarc 			tp->t_cflag = TTYDEF_CFLAG;
712e977faadSmarc 		}
713b2b69f49Smarc 		/*
714b2b69f49Smarc 		* enable intrpts, open line discipline
715b2b69f49Smarc 		*/
7167e911b15Skarels 		dga->csr |= GLOBAL_IE;	/* turn on the interrupts */
7177e911b15Skarels 		return ((*linesw[tp->t_line].l_open)(dev, tp));
7187e911b15Skarels 	}
7197e911b15Skarels 	dga->csr |= GLOBAL_IE;	/* turn on the interrupts */
7207e911b15Skarels 	return(0);
7217e911b15Skarels 
7227e911b15Skarels } /* qdopen */
7237e911b15Skarels 
7247881ece5Smarc /*ARGSUSED*/
7257e911b15Skarels qdclose(dev, flag)
7267e911b15Skarels 	dev_t dev;
7277e911b15Skarels 	int flag;
7287e911b15Skarels {
7297e911b15Skarels 	register struct tty *tp;
7307e911b15Skarels 	register struct qdmap *qd;
7317e911b15Skarels 	register int *ptep;
7327e911b15Skarels 	struct dga *dga;		/* gate array register map pointer */
7337e911b15Skarels 	struct duart *duart;
7347e911b15Skarels 	struct adder *adder;
7357881ece5Smarc 	int unit;
7367881ece5Smarc 	int minor_dev;
7377e911b15Skarels 	u_int mapix;
738b2b69f49Smarc 	int i;				/* SIGNED index */
7397e911b15Skarels 
7407e911b15Skarels 	minor_dev = minor(dev); 	/* get minor device number */
7417e911b15Skarels 	unit = minor_dev >> 2;		/* get QDSS number */
7427e911b15Skarels 	qd = &qdmap[unit];
7437e911b15Skarels 
7447e911b15Skarels 	if ((minor_dev & 0x03) == 2) {
745b2b69f49Smarc 		/*
746b2b69f49Smarc 		* this is the graphic device...
747b2b69f49Smarc 		*/
748b2b69f49Smarc 		if (qdopened[unit] != 1)
7497e911b15Skarels 		    	return(EBUSY);
7507e911b15Skarels 		else
751b2b69f49Smarc 			qdopened[unit] = 0;	/* allow it to be re-opened */
752b2b69f49Smarc 		/*
753b2b69f49Smarc 		* re-protect device memory
754b2b69f49Smarc 		*/
7557e911b15Skarels 		if (qdflags[unit].mapped & MAPDEV) {
756b2b69f49Smarc 			/*
757b2b69f49Smarc 			* TEMPLATE RAM
758b2b69f49Smarc 			*/
75924f67f6bSmarc 			mapix = VTOP((int)qd->template) - VTOP(qvmem[0]);
76024f67f6bSmarc 			ptep = (int *)(QVmap[0] + mapix);
7617881ece5Smarc 			for (i = 0; i < btop(TMPSIZE); i++, ptep++)
7627881ece5Smarc 				*ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
763b2b69f49Smarc 			/*
764b2b69f49Smarc 			* ADDER
765b2b69f49Smarc 			*/
76624f67f6bSmarc 			mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]);
76724f67f6bSmarc 			ptep = (int *)(QVmap[0] + mapix);
7687881ece5Smarc 			for (i = 0; i < btop(REGSIZE); i++, ptep++)
7697881ece5Smarc 				*ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
770b2b69f49Smarc 			/*
771b2b69f49Smarc 			* COLOR MAPS
772b2b69f49Smarc 			*/
77324f67f6bSmarc 			mapix = VTOP((int)qd->red) - VTOP(qvmem[0]);
77424f67f6bSmarc 			ptep = (int *)(QVmap[0] + mapix);
7757881ece5Smarc 			for (i = 0; i < btop(CLRSIZE); i++, ptep++)
7767881ece5Smarc 				*ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
7777e911b15Skarels 		}
7787e911b15Skarels 
779b2b69f49Smarc 		/*
780b2b69f49Smarc 		* re-protect DMA buffer and free the map registers
781b2b69f49Smarc 		*/
7827e911b15Skarels 		if (qdflags[unit].mapped & MAPDMA) {
7837e911b15Skarels 			dga = (struct dga *) qdmap[unit].dga;
7847e911b15Skarels 			adder = (struct adder *) qdmap[unit].adder;
7857e911b15Skarels 			dga->csr &= ~DMA_IE;
7867e911b15Skarels 			dga->csr &= ~0x0600;	     /* kill DMA */
7877e911b15Skarels 			adder->command = CANCEL;
788b2b69f49Smarc 			/*
789b2b69f49Smarc 			 * if DMA was running, flush spurious intrpt
790b2b69f49Smarc 			 */
7917e911b15Skarels 			if (dga->bytcnt_lo != 0) {
7927e911b15Skarels 				dga->bytcnt_lo = 0;
7937e911b15Skarels 				dga->bytcnt_hi = 0;
7947e911b15Skarels 				DMA_SETIGNORE(DMAheader[unit]);
7957e911b15Skarels 				dga->csr |= DMA_IE;
7967e911b15Skarels 				dga->csr &= ~DMA_IE;
7977e911b15Skarels 			}
7987e911b15Skarels 			ptep = (int *)
7997e911b15Skarels 			   ((VTOP(DMAheader[unit]*4)) + (mfpr(SBR)|0x80000000));
8007881ece5Smarc 			for (i = 0; i < btop(DMAbuf_size); i++, ptep++)
8017881ece5Smarc 				*ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
8027e911b15Skarels 			ubarelse(0, &Qbus_unmap[unit]);
8037e911b15Skarels 		}
8047e911b15Skarels 
805b2b69f49Smarc 		/*
806b2b69f49Smarc 		* re-protect 1K (2 pages) event queue
807b2b69f49Smarc 		*/
8087e911b15Skarels 		if (qdflags[unit].mapped & MAPEQ) {
8097e911b15Skarels 			ptep = (int *)
8107e911b15Skarels 			   ((VTOP(eq_header[unit])*4) + (mfpr(SBR)|0x80000000));
8117881ece5Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++;
8127e911b15Skarels 			*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
8137e911b15Skarels 		}
814b2b69f49Smarc 		/*
815b2b69f49Smarc 		* re-protect scroll param area and disable scroll intrpts
816b2b69f49Smarc 		*/
8177e911b15Skarels 		if (qdflags[unit].mapped & MAPSCR) {
8187e911b15Skarels 			ptep = (int *) ((VTOP(scroll[unit]) * 4)
8197e911b15Skarels 				+ (mfpr(SBR) | 0x80000000));
820b2b69f49Smarc 			/*
821b2b69f49Smarc 			 * re-protect 512 scroll param area
822b2b69f49Smarc 			 */
8237e911b15Skarels 			*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
8247e911b15Skarels 			adder = (struct adder *) qdmap[unit].adder;
8257e911b15Skarels 			qdflags[unit].adder_ie &= ~FRAME_SYNC;
8267e911b15Skarels 			adder->interrupt_enable = qdflags[unit].adder_ie;
8277e911b15Skarels 		}
828b2b69f49Smarc 		/*
829b2b69f49Smarc 		* re-protect color map write buffer area and kill intrpts
830b2b69f49Smarc 		*/
8317e911b15Skarels 		if (qdflags[unit].mapped & MAPCOLOR) {
8327e911b15Skarels 			ptep = (int *) ((VTOP(color_buf[unit]) * 4)
8337e911b15Skarels 				+ (mfpr(SBR) | 0x80000000));
8347881ece5Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++;
8357e911b15Skarels 			*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
8367e911b15Skarels 			color_buf[unit]->status = 0;
8377e911b15Skarels 			adder = (struct adder *) qdmap[unit].adder;
8387e911b15Skarels 			qdflags[unit].adder_ie &= ~VSYNC;
8397e911b15Skarels 			adder->interrupt_enable = qdflags[unit].adder_ie;
8407e911b15Skarels 		}
841b2b69f49Smarc 		mtpr(TBIA, 0);
842b2b69f49Smarc 		/* flag everything now unmapped */
843b2b69f49Smarc 		qdflags[unit].mapped = 0;
8447e911b15Skarels 		qdflags[unit].inuse &= ~GRAPHIC_DEV;
8457e911b15Skarels 		qdflags[unit].curs_acc = ACC_OFF;
8467e911b15Skarels 		qdflags[unit].curs_thr = 128;
847b2b69f49Smarc 		/*
848b2b69f49Smarc 		* restore the console
849b2b69f49Smarc 		*/
8507e911b15Skarels 		dga = (struct dga *) qdmap[unit].dga;
8517e911b15Skarels 		adder = (struct adder *) qdmap[unit].adder;
8527e911b15Skarels 		dga->csr &= ~DMA_IE;
8537e911b15Skarels 		dga->csr &= ~0x0600;	/* halt the DMA! (just in case...) */
8547e911b15Skarels 		dga->csr |= DMA_ERR;	/* clear error condition */
8557e911b15Skarels 		adder->command = CANCEL;
856b2b69f49Smarc 		/*
857b2b69f49Smarc 		 * if DMA was running, flush spurious intrpt
858b2b69f49Smarc 		 */
8597e911b15Skarels 		if (dga->bytcnt_lo != 0) {
8607e911b15Skarels 			dga->bytcnt_lo = 0;
8617e911b15Skarels 			dga->bytcnt_hi = 0;
8627e911b15Skarels 			DMA_SETIGNORE(DMAheader[unit]);
8637e911b15Skarels 			dga->csr |= DMA_IE;
8647e911b15Skarels 			dga->csr &= ~DMA_IE;
8657e911b15Skarels 		}
8667e911b15Skarels 		init_shared(unit);		/* init shared memory */
8677e911b15Skarels 		setup_dragon(unit);		/* init ADDER/VIPER */
8687e911b15Skarels 		ldcursor(unit, cons_cursor);	/* load default cursor map */
8697e911b15Skarels 		setup_input(unit);		/* init the DUART */
8707e911b15Skarels 		ldfont(unit);
8717e911b15Skarels 		cursor[unit].x = 0;
8727e911b15Skarels 		cursor[unit].y = 0;
873b2b69f49Smarc 		/*
874b2b69f49Smarc 		 * shut off the mouse rcv intrpt and turn on kbd intrpts
875b2b69f49Smarc 		 */
8767e911b15Skarels 		duart = (struct duart *) qdmap[unit].duart;
8777e911b15Skarels 		qdflags[unit].duart_imask &= ~(0x20);
8787e911b15Skarels 		qdflags[unit].duart_imask |= 0x02;
8797e911b15Skarels 		duart->imask = qdflags[unit].duart_imask;
880b2b69f49Smarc 		/*
881b2b69f49Smarc 		* shut off interrupts if all is closed
882b2b69f49Smarc 		*/
883b2b69f49Smarc 		if (!(qdflags[unit].inuse & CONS_DEV)) {
8847e911b15Skarels 			dga = (struct dga *) qdmap[unit].dga;
8857e911b15Skarels 			dga->csr &= ~(GLOBAL_IE | DMA_IE);
8867e911b15Skarels 		}
887b2b69f49Smarc 	} else {
888b2b69f49Smarc 		/*
889b2b69f49Smarc 		* this is the console
890b2b69f49Smarc 		*/
8917e911b15Skarels 		tp = &qd_tty[minor_dev];
8927e911b15Skarels 		(*linesw[tp->t_line].l_close)(tp);
8937e911b15Skarels 		ttyclose(tp);
8947e911b15Skarels 		tp->t_state = 0;
8957e911b15Skarels 		qdflags[unit].inuse &= ~CONS_DEV;
896b2b69f49Smarc 		/*
897b2b69f49Smarc 		* if graphics device is closed, kill interrupts
898b2b69f49Smarc 		*/
8997e911b15Skarels 		if (!(qdflags[unit].inuse & GRAPHIC_DEV)) {
9007e911b15Skarels 			dga = (struct dga *) qdmap[unit].dga;
9017e911b15Skarels 			dga->csr &= ~(GLOBAL_IE | DMA_IE);
9027e911b15Skarels 		}
9037e911b15Skarels 	}
9047e911b15Skarels 
9057e911b15Skarels 	return(0);
9067e911b15Skarels 
9077e911b15Skarels } /* qdclose */
9087e911b15Skarels 
9097e911b15Skarels qdioctl(dev, cmd, datap, flags)
9107e911b15Skarels 	dev_t dev;
9117e911b15Skarels 	int cmd;
9127881ece5Smarc 	register caddr_t datap;
9137e911b15Skarels 	int flags;
9147e911b15Skarels {
9157e911b15Skarels 	register int *ptep;		/* page table entry pointer */
91624f67f6bSmarc 	register int mapix;		/* QVmap[] page table index */
9177e911b15Skarels 	register struct _vs_event *event;
9187e911b15Skarels 	register struct tty *tp;
9197881ece5Smarc 	register i;
9207e911b15Skarels 	struct qdmap *qd;		/* pointer to device map struct */
9217e911b15Skarels 	struct dga *dga;		/* Gate Array reg structure pntr */
9227e911b15Skarels 	struct duart *duart;		/* DUART reg structure pointer */
9237e911b15Skarels 	struct adder *adder;		/* ADDER reg structure pointer */
9247e911b15Skarels 	struct prgkbd *cmdbuf;
9257e911b15Skarels 	struct prg_cursor *curs;
9267e911b15Skarels 	struct _vs_cursor *pos;
9277881ece5Smarc 	int unit = minor(dev) >> 2;	/* number of caller's QDSS */
9287e911b15Skarels 	u_int minor_dev = minor(dev);
9297e911b15Skarels 	int error;
9307e911b15Skarels 	int s;
9317e911b15Skarels 	short *temp;			/* a pointer to template RAM */
9327e911b15Skarels 
933b2b69f49Smarc 	/*
934b2b69f49Smarc 	* service graphic device ioctl commands
935b2b69f49Smarc 	*/
9367e911b15Skarels 	switch (cmd) {
937e977faadSmarc 
9387e911b15Skarels 	case QD_GETEVENT:
939b2b69f49Smarc 		/*
940b2b69f49Smarc 		* extract the oldest event from the event queue
941b2b69f49Smarc 		*/
9427e911b15Skarels 		if (ISEMPTY(eq_header[unit])) {
9437e911b15Skarels 			event = (struct _vs_event *) datap;
9447e911b15Skarels 			event->vse_device = VSE_NULL;
9457e911b15Skarels 			break;
9467e911b15Skarels 		}
9477e911b15Skarels 		event = (struct _vs_event *) GETBEGIN(eq_header[unit]);
948e977faadSmarc 		s = spl5();
9497e911b15Skarels 		GETEND(eq_header[unit]);
9507e911b15Skarels 		splx(s);
9517881ece5Smarc 		bcopy((caddr_t)event, datap, sizeof(struct _vs_event));
9527e911b15Skarels 		break;
9537e911b15Skarels 
9547e911b15Skarels 	case QD_RESET:
955b2b69f49Smarc 		/*
956b2b69f49Smarc 		* init the dragon stuff, DUART, and driver variables
957b2b69f49Smarc 		*/
9587e911b15Skarels 		init_shared(unit);		/* init shared memory */
9597e911b15Skarels 		setup_dragon(unit);	      /* init the ADDER/VIPER stuff */
9607e911b15Skarels 		clear_qd_screen(unit);
9617e911b15Skarels 		ldcursor(unit, cons_cursor);	/* load default cursor map */
9627e911b15Skarels 		ldfont(unit);			/* load the console font */
9637e911b15Skarels 		setup_input(unit);		/* init the DUART */
9647e911b15Skarels 		break;
9657e911b15Skarels 
9667e911b15Skarels 	case QD_SET:
967b2b69f49Smarc 		/*
968b2b69f49Smarc 		* init the DUART and driver variables
969b2b69f49Smarc 		*/
9707e911b15Skarels 		init_shared(unit);
9717e911b15Skarels 		setup_input(unit);
9727e911b15Skarels 		break;
9737e911b15Skarels 
9747e911b15Skarels 	case QD_CLRSCRN:
975b2b69f49Smarc 		/*
976b2b69f49Smarc 		* clear the QDSS screen.  (NOTE that this reinits the dragon)
977b2b69f49Smarc 		*/
9787881ece5Smarc #ifdef notdef	/* has caused problems and isn't necessary */
9797e911b15Skarels 		setup_dragon(unit);
9807e911b15Skarels 		clear_qd_screen(unit);
981e977faadSmarc #endif
9827e911b15Skarels 		break;
9837e911b15Skarels 
9847e911b15Skarels 	case QD_WTCURSOR:
985b2b69f49Smarc 		/*
986b2b69f49Smarc 		* load a cursor into template RAM
987b2b69f49Smarc 		*/
9887881ece5Smarc 		ldcursor(unit, (short *)datap);
9897e911b15Skarels 		break;
9907e911b15Skarels 
9917e911b15Skarels 	case QD_RDCURSOR:
9927e911b15Skarels 
9937e911b15Skarels 		temp = (short *) qdmap[unit].template;
994b2b69f49Smarc 		/*
995b2b69f49Smarc 		 * cursor is 32 WORDS from the end of the 8k WORD...
996b2b69f49Smarc 		 *  ...template space
997b2b69f49Smarc 		 */
9987e911b15Skarels 		temp += (8 * 1024) - 32;
9997e911b15Skarels 		for (i = 0; i < 32; ++i, datap += sizeof(short))
10007e911b15Skarels 			*(short *)datap = *temp++;
10017e911b15Skarels 		break;
10027e911b15Skarels 
10037e911b15Skarels 	case QD_POSCURSOR:
1004b2b69f49Smarc 		/*
1005b2b69f49Smarc 		* position the mouse cursor
1006b2b69f49Smarc 		*/
10077e911b15Skarels 		dga = (struct dga *) qdmap[unit].dga;
10087e911b15Skarels 		pos = (struct _vs_cursor *) datap;
1009e977faadSmarc 		s = spl5();
10107e911b15Skarels 		dga->x_cursor = TRANX(pos->x);
10117e911b15Skarels 		dga->y_cursor = TRANY(pos->y);
10127e911b15Skarels 		eq_header[unit]->curs_pos.x = pos->x;
10137e911b15Skarels 		eq_header[unit]->curs_pos.y = pos->y;
10147e911b15Skarels 		splx(s);
10157e911b15Skarels 		break;
10167e911b15Skarels 
10177e911b15Skarels 	case QD_PRGCURSOR:
1018b2b69f49Smarc 		/*
1019b2b69f49Smarc 		* set the cursor acceleration factor
1020b2b69f49Smarc 		*/
10217e911b15Skarels 		curs = (struct prg_cursor *) datap;
1022e977faadSmarc 		s = spl5();
10237e911b15Skarels 		qdflags[unit].curs_acc = curs->acc_factor;
10247e911b15Skarels 		qdflags[unit].curs_thr = curs->threshold;
10257e911b15Skarels 		splx(s);
10267e911b15Skarels 		break;
10277e911b15Skarels 
10287e911b15Skarels 	case QD_MAPDEVICE:
1029b2b69f49Smarc 		/*
1030b2b69f49Smarc 		* enable 'user write' to device pages
1031b2b69f49Smarc 		*/
10327e911b15Skarels 		qdflags[unit].mapped |= MAPDEV;
10337e911b15Skarels 		qd = (struct qdmap *) &qdmap[unit];
1034b2b69f49Smarc 		/*
1035b2b69f49Smarc 		* enable user write to template RAM
1036b2b69f49Smarc 		*/
103724f67f6bSmarc 		mapix = VTOP((int)qd->template) - VTOP(qvmem[0]);
103824f67f6bSmarc 		ptep = (int *)(QVmap[0] + mapix);
10397881ece5Smarc 		for (i = 0; i < btop(TMPSIZE); i++, ptep++)
10407881ece5Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
1041b2b69f49Smarc 		/*
1042b2b69f49Smarc 		* enable user write to registers
1043b2b69f49Smarc 		*/
104424f67f6bSmarc 		mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]);
104524f67f6bSmarc 		ptep = (int *)(QVmap[0] + mapix);
10467881ece5Smarc 		for (i = 0; i < btop(REGSIZE); i++, ptep++)
10477881ece5Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
1048b2b69f49Smarc 		/*
1049b2b69f49Smarc 		* enable user write to color maps
1050b2b69f49Smarc 		*/
105124f67f6bSmarc 		mapix = VTOP((int)qd->red) - VTOP(qvmem[0]);
105224f67f6bSmarc 		ptep = (int *)(QVmap[0] + mapix);
10537881ece5Smarc 		for (i = 0; i < btop(CLRSIZE); i++, ptep++)
10547881ece5Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
1055b2b69f49Smarc 		/*
1056b2b69f49Smarc 		* enable user write to DUART
1057b2b69f49Smarc 		*/
105824f67f6bSmarc 		mapix = VTOP((int)qd->duart) - VTOP(qvmem[0]);
105924f67f6bSmarc 		ptep = (int *)(QVmap[0] + mapix);
10607e911b15Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; /* duart page */
10617e911b15Skarels 
10627881ece5Smarc 		mtpr(TBIA, 0);		/* invalidate translation buffer */
10637e911b15Skarels 
1064b2b69f49Smarc 		/*
1065b2b69f49Smarc 		 * stuff qdmap structure in return buffer
1066b2b69f49Smarc 		 */
10677881ece5Smarc 		bcopy((caddr_t)qd, datap, sizeof(struct qdmap));
10687e911b15Skarels 		break;
10697e911b15Skarels 
10707e911b15Skarels 	case QD_MAPIOBUF:
1071b2b69f49Smarc 		/*
1072b2b69f49Smarc 		 * do setup for DMA by user process
1073b2b69f49Smarc 		 *
1074b2b69f49Smarc 		 * set 'user write enable' bits for DMA buffer
1075b2b69f49Smarc 		 */
10767e911b15Skarels 		qdflags[unit].mapped |= MAPDMA;
10777e911b15Skarels 		ptep = (int *) ((VTOP(DMAheader[unit]) * 4)
10787e911b15Skarels 			+ (mfpr(SBR) | 0x80000000));
10797881ece5Smarc 		for (i = 0; i < btop(DMAbuf_size); i++, ptep++)
10807881ece5Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
10817881ece5Smarc 		mtpr(TBIA, 0);		/* invalidate translation buffer */
1082b2b69f49Smarc 		/*
1083b2b69f49Smarc 		* set up QBUS map registers for DMA
1084b2b69f49Smarc 		*/
10857e911b15Skarels 		DMAheader[unit]->QBAreg =
10867881ece5Smarc 		    uballoc(0, (caddr_t)DMAheader[unit], DMAbuf_size, 0);
10877e911b15Skarels 		if (DMAheader[unit]->QBAreg == 0)
10887881ece5Smarc 		    printf("qd%d: qdioctl: QBA setup error\n", unit);
10897e911b15Skarels 		Qbus_unmap[unit] = DMAheader[unit]->QBAreg;
10907e911b15Skarels 		DMAheader[unit]->QBAreg &= 0x3FFFF;
1091b2b69f49Smarc 		/*
1092b2b69f49Smarc 		* return I/O buf adr
1093b2b69f49Smarc 		*/
10947e911b15Skarels 		*(int *)datap = (int) DMAheader[unit];
10957e911b15Skarels 		break;
10967e911b15Skarels 
10977e911b15Skarels 	case QD_MAPSCROLL:
1098b2b69f49Smarc 		/*
1099b2b69f49Smarc 		* map the shared scroll param area and enable scroll interpts
1100b2b69f49Smarc 		*/
11017e911b15Skarels 		qdflags[unit].mapped |= MAPSCR;
11027e911b15Skarels 		ptep = (int *) ((VTOP(scroll[unit]) * 4)
11037e911b15Skarels 			+ (mfpr(SBR) | 0x80000000));
1104b2b69f49Smarc 		/*
1105b2b69f49Smarc 		 * allow user write to scroll area
1106b2b69f49Smarc 		 */
11077e911b15Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
11087881ece5Smarc 		mtpr(TBIA, 0);			/* invalidate translation buf */
11097e911b15Skarels 		scroll[unit]->status = 0;
11107e911b15Skarels 		adder = (struct adder *) qdmap[unit].adder;
11117e911b15Skarels 		qdflags[unit].adder_ie |= FRAME_SYNC;
11127e911b15Skarels 		adder->interrupt_enable = qdflags[unit].adder_ie;
1113b2b69f49Smarc 		*(int *)datap = (int) scroll[unit]; /* return scroll area */
11147e911b15Skarels 		break;
11157e911b15Skarels 
11167e911b15Skarels 	case QD_UNMAPSCROLL:
1117b2b69f49Smarc 		/*
1118b2b69f49Smarc 		* unmap shared scroll param area and disable scroll intrpts
1119b2b69f49Smarc 		*/
11207e911b15Skarels 		if (qdflags[unit].mapped & MAPSCR) {
11217e911b15Skarels 			qdflags[unit].mapped &= ~MAPSCR;
11227e911b15Skarels 			ptep = (int *) ((VTOP(scroll[unit]) * 4)
11237e911b15Skarels 				+ (mfpr(SBR) | 0x80000000));
1124b2b69f49Smarc 			/*
1125b2b69f49Smarc 			 * re-protect 512 scroll param area
1126b2b69f49Smarc 			 */
11277e911b15Skarels 			*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
11287e911b15Skarels 			mtpr(TBIA, 0);	/* smash CPU's translation buf */
11297e911b15Skarels 			adder = (struct adder *) qdmap[unit].adder;
11307e911b15Skarels 			qdflags[unit].adder_ie &= ~FRAME_SYNC;
11317e911b15Skarels 			adder->interrupt_enable = qdflags[unit].adder_ie;
11327e911b15Skarels 		}
11337e911b15Skarels 		break;
11347e911b15Skarels 
11357e911b15Skarels 	case QD_MAPCOLOR:
1136b2b69f49Smarc 		/*
1137b2b69f49Smarc 		* map shared color map write buf and turn on vsync intrpt
1138b2b69f49Smarc 		*/
11397e911b15Skarels 		qdflags[unit].mapped |= MAPCOLOR;
11407e911b15Skarels 		ptep = (int *) ((VTOP(color_buf[unit]) * 4)
11417e911b15Skarels 			+ (mfpr(SBR) | 0x80000000));
11427881ece5Smarc 		/*
11437881ece5Smarc 		 * allow user write to color map write buffer
11447881ece5Smarc 		 */
11457881ece5Smarc 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; ptep++;
11467e911b15Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
11477e911b15Skarels 		mtpr(TBIA, 0);			/* clr CPU translation buf */
1148b2b69f49Smarc 		adder = (struct adder *) qdmap[unit].adder;
11497e911b15Skarels 		qdflags[unit].adder_ie |= VSYNC;
11507e911b15Skarels 		adder->interrupt_enable = qdflags[unit].adder_ie;
11517881ece5Smarc 		/*
11527881ece5Smarc 		 * return color area address
11537881ece5Smarc 		 */
11547e911b15Skarels 		*(int *)datap = (int) color_buf[unit];
11557e911b15Skarels 		break;
11567e911b15Skarels 
11577e911b15Skarels 	case QD_UNMAPCOLOR:
1158b2b69f49Smarc 		/*
1159b2b69f49Smarc 		 * unmap shared color map write buffer and kill VSYNC intrpts
1160b2b69f49Smarc 		 */
11617e911b15Skarels 		if (qdflags[unit].mapped & MAPCOLOR) {
11627e911b15Skarels 			qdflags[unit].mapped &= ~MAPCOLOR;
11637e911b15Skarels 			ptep = (int *) ((VTOP(color_buf[unit]) * 4)
11647e911b15Skarels 				+ (mfpr(SBR) | 0x80000000));
11657881ece5Smarc 			/*
11667881ece5Smarc 			 * re-protect color map write buffer
11677881ece5Smarc 			 */
11687881ece5Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++;
11697e911b15Skarels 			*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
11707881ece5Smarc 			mtpr(TBIA, 0);
11717e911b15Skarels 			adder = (struct adder *) qdmap[unit].adder;
11727e911b15Skarels 			qdflags[unit].adder_ie &= ~VSYNC;
11737e911b15Skarels 			adder->interrupt_enable = qdflags[unit].adder_ie;
11747e911b15Skarels 		}
11757e911b15Skarels 		break;
11767e911b15Skarels 
11777e911b15Skarels 	case QD_MAPEVENT:
1178b2b69f49Smarc 		/*
1179b2b69f49Smarc 		* give user write access to the event queue
1180b2b69f49Smarc 		*/
11817e911b15Skarels 		qdflags[unit].mapped |= MAPEQ;
11827e911b15Skarels 		ptep = (int *) ((VTOP(eq_header[unit]) * 4)
11837e911b15Skarels 			+ (mfpr(SBR) | 0x80000000));
11847881ece5Smarc 		/*
11857881ece5Smarc 		 * allow user write to 1K event queue
11867881ece5Smarc 		 */
11877881ece5Smarc 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; ptep++;
11887e911b15Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
11897e911b15Skarels 		mtpr(TBIA, 0);			/* clr CPU translation buf */
11907881ece5Smarc 		/*
11917881ece5Smarc 		 * return event queue address
11927881ece5Smarc 		 */
11937e911b15Skarels 		*(int *)datap = (int)eq_header[unit];
11947e911b15Skarels 		break;
11957e911b15Skarels 
11967e911b15Skarels 	case QD_PRGKBD:
1197b2b69f49Smarc 		/*
1198b2b69f49Smarc 		* pass caller's programming commands to LK201
1199b2b69f49Smarc 		*/
12007e911b15Skarels 		duart = (struct duart *)qdmap[unit].duart;
12017e911b15Skarels 		cmdbuf = (struct prgkbd *)datap;    /* pnt to kbd cmd buf */
1202b2b69f49Smarc 		/*
1203b2b69f49Smarc 		* send command
1204b2b69f49Smarc 		*/
12057e911b15Skarels 		for (i = 1000; i > 0; --i) {
12067881ece5Smarc 			if (duart->statusA&XMT_RDY) {
12077e911b15Skarels 				duart->dataA = cmdbuf->cmd;
12087e911b15Skarels 				break;
12097e911b15Skarels 			}
12107e911b15Skarels 		}
12117e911b15Skarels 		if (i == 0) {
12127881ece5Smarc 			printf("qd%d: qdioctl: timeout on XMT_RDY [1]\n", unit);
12137e911b15Skarels 			break;
12147e911b15Skarels 		}
1215b2b69f49Smarc 		/*
1216b2b69f49Smarc 		* send param1?
1217b2b69f49Smarc 		*/
12187e911b15Skarels 		if (cmdbuf->cmd & LAST_PARAM)
12197e911b15Skarels 			break;
12207e911b15Skarels 		for (i = 1000; i > 0; --i) {
12217881ece5Smarc 			if (duart->statusA&XMT_RDY) {
12227e911b15Skarels 				duart->dataA = cmdbuf->param1;
12237e911b15Skarels 				break;
12247e911b15Skarels 			}
12257e911b15Skarels 		}
12267e911b15Skarels 		if (i == 0) {
12277881ece5Smarc 			printf("qd%d: qdioctl: timeout on XMT_RDY [2]\n", unit);
12287e911b15Skarels 			break;
12297e911b15Skarels 		}
1230b2b69f49Smarc 		/*
1231b2b69f49Smarc 		* send param2?
1232b2b69f49Smarc 		*/
12337e911b15Skarels 		if (cmdbuf->param1 & LAST_PARAM)
12347e911b15Skarels 		    break;
12357e911b15Skarels 		for (i = 1000; i > 0; --i) {
12367881ece5Smarc 			if (duart->statusA&XMT_RDY) {
12377e911b15Skarels 				duart->dataA = cmdbuf->param2;
12387e911b15Skarels 				break;
12397e911b15Skarels 			}
12407e911b15Skarels 		}
12417e911b15Skarels 		if (i == 0) {
12427881ece5Smarc 			printf("qd%d: qdioctl: timeout on XMT_RDY [3]\n", unit);
12437e911b15Skarels 			break;
12447e911b15Skarels 		}
12457e911b15Skarels 		break;
12467e911b15Skarels 
12477e911b15Skarels 	case QD_PRGMOUSE:
1248b2b69f49Smarc 		/*
1249b2b69f49Smarc 		* pass caller's programming commands to the mouse
1250b2b69f49Smarc 		*/
12517e911b15Skarels 		duart = (struct duart *) qdmap[unit].duart;
12527e911b15Skarels 		for (i = 1000; i > 0; --i) {
12537881ece5Smarc 			if (duart->statusB&XMT_RDY) {
12547e911b15Skarels 				duart->dataB = *datap;
12557e911b15Skarels 				break;
12567e911b15Skarels 			}
12577e911b15Skarels 		}
12587e911b15Skarels 		if (i == 0) {
12597881ece5Smarc 			printf("qd%d: qdioctl: timeout on XMT_RDY [4]\n", unit);
12607e911b15Skarels 		}
12617e911b15Skarels 		break;
12627e911b15Skarels 
12637e911b15Skarels 	case QD_RDCONFIG:
1264b2b69f49Smarc 		/*
1265b2b69f49Smarc 		* get QDSS configuration word and return it
1266b2b69f49Smarc 		*/
12677e911b15Skarels 		*(short *)datap = qdflags[unit].config;
12687e911b15Skarels 		break;
12697e911b15Skarels 
1270e977faadSmarc 	case QD_KERN_LOOP:
1271e977faadSmarc 	case QD_KERN_UNLOOP:
1272b2b69f49Smarc 		/*
1273b2b69f49Smarc 		 * vestige from ultrix.  BSD uses TIOCCONS to redirect
1274b2b69f49Smarc 		 * kernel console output.
1275b2b69f49Smarc 		 */
1276e977faadSmarc 		break;
1277e977faadSmarc 
12787e911b15Skarels 	case QD_PRGTABLET:
1279b2b69f49Smarc 		/*
1280b2b69f49Smarc 		* program the tablet
1281b2b69f49Smarc 		*/
12827e911b15Skarels 		duart = (struct duart *) qdmap[unit].duart;
12837e911b15Skarels 		for (i = 1000; i > 0; --i) {
12847881ece5Smarc 			if (duart->statusB&XMT_RDY) {
12857e911b15Skarels 				duart->dataB = *datap;
12867e911b15Skarels 				break;
12877e911b15Skarels 			}
12887e911b15Skarels 		}
12897e911b15Skarels 		if (i == 0) {
12907881ece5Smarc 			printf("qd%d: qdioctl: timeout on XMT_RDY [5]\n", unit);
12917e911b15Skarels 		}
12927e911b15Skarels 		break;
12937e911b15Skarels 
12947e911b15Skarels 	case QD_PRGTABRES:
1295b2b69f49Smarc 		/*
1296b2b69f49Smarc 		* program the tablet report resolution factor
1297b2b69f49Smarc 		*/
12987e911b15Skarels 		qdflags[unit].tab_res = *(short *)datap;
12997e911b15Skarels 		break;
13008a2bf9b0Smarc 
13017e911b15Skarels 	default:
1302b2b69f49Smarc 		/*
1303b2b69f49Smarc 		* service tty ioctl's
1304b2b69f49Smarc 		*/
13057e911b15Skarels 		if (!(minor_dev & 0x02)) {
13067e911b15Skarels 			tp = &qd_tty[minor_dev];
1307b2b69f49Smarc 			error =
1308b2b69f49Smarc 			   (*linesw[tp->t_line].l_ioctl)(tp, cmd, datap, flags);
13097e911b15Skarels 			if (error >= 0) {
13107e911b15Skarels 				return(error);
13117e911b15Skarels 			}
13127e911b15Skarels 			error = ttioctl(tp, cmd, datap, flags);
13137e911b15Skarels 			if (error >= 0) {
13147e911b15Skarels 				return(error);
13157e911b15Skarels 			}
13167e911b15Skarels 		}
13177e911b15Skarels 		break;
13187e911b15Skarels 	}
13197e911b15Skarels 
13207e911b15Skarels 	return(0);
13217e911b15Skarels 
13227e911b15Skarels } /* qdioctl */
13237e911b15Skarels 
13247e911b15Skarels qdselect(dev, rw)
13257e911b15Skarels 	dev_t dev;
13267e911b15Skarels 	int rw;
13277e911b15Skarels {
13287881ece5Smarc 	register s;
13297881ece5Smarc 	register unit;
1330e977faadSmarc 	register struct tty *tp;
1331e977faadSmarc 	u_int minor_dev = minor(dev);
13327e911b15Skarels 
1333e977faadSmarc 	s = spl5();
1334e977faadSmarc 	unit = minor_dev >> 2;
13357e911b15Skarels 
13367e911b15Skarels 	switch (rw) {
1337e977faadSmarc 	case FREAD:
1338b2b69f49Smarc 		if ((minor_dev & 0x03) == 2) {
1339e977faadSmarc 			/*
1340e977faadSmarc 			* this is a graphics device, so check for events
1341e977faadSmarc 			*/
13427881ece5Smarc 			if(!(ISEMPTY(eq_header[unit]))) {
13437e911b15Skarels 				splx(s);
1344e977faadSmarc 				return(1);
13457e911b15Skarels 			}
13467881ece5Smarc 			qdrsel[unit] = u.u_procp;
13477e911b15Skarels 			qdflags[unit].selmask |= SEL_READ;
13487e911b15Skarels 			splx(s);
13497e911b15Skarels 			return(0);
1350b2b69f49Smarc 		} else {
1351e977faadSmarc 			/*
1352e977faadSmarc 			* this is a tty device
1353e977faadSmarc 			*/
1354e977faadSmarc 			tp = &qd_tty[minor_dev];
1355e977faadSmarc 			if (ttnread(tp))
1356e977faadSmarc 			    return(1);
1357e977faadSmarc 			tp->t_rsel = u.u_procp;
13587e911b15Skarels 			splx(s);
1359e977faadSmarc 			return(0);
1360e977faadSmarc 		}
1361e977faadSmarc 
1362e977faadSmarc 	case FWRITE:
1363b2b69f49Smarc 		if ((minor(dev) & 0x03) == 2) {
1364e977faadSmarc 			/*
1365e977faadSmarc 			* this is a graphics device, so check for dma buffers
1366e977faadSmarc 			*/
1367e977faadSmarc 			if (DMA_ISEMPTY(DMAheader[unit]))
1368e977faadSmarc 			    {
1369e977faadSmarc 				splx(s);
1370e977faadSmarc 				return(1);
13717e911b15Skarels 			}
13727881ece5Smarc 			qdrsel[unit] = u.u_procp;
13737e911b15Skarels 			qdflags[unit].selmask |= SEL_WRITE;
13747e911b15Skarels 			splx(s);
13757e911b15Skarels 			return(0);
1376b2b69f49Smarc 		} else {
1377e977faadSmarc 			/*
1378e977faadSmarc 			* this is a tty device
1379e977faadSmarc 			*/
1380e977faadSmarc 			tp = &qd_tty[minor_dev];
1381f5319004Smarc 			if (tp->t_outq.c_cc <= tp->t_lowat)
1382e977faadSmarc 			    return(1);
1383e977faadSmarc 			tp->t_wsel = u.u_procp;
1384e977faadSmarc 			splx(s);
1385e977faadSmarc 			return(0);
1386e977faadSmarc 		}
1387e977faadSmarc 	}
13887881ece5Smarc 	splx(s);
13897881ece5Smarc 	return(0);
13907e911b15Skarels 
13917e911b15Skarels } /* qdselect() */
13927e911b15Skarels 
13937e911b15Skarels extern qd_strategy();
13947e911b15Skarels 
13957e911b15Skarels qdwrite(dev, uio)
13967e911b15Skarels 	dev_t dev;
13977e911b15Skarels 	struct uio *uio;
13987e911b15Skarels {
13997e911b15Skarels 	register struct tty *tp;
14007881ece5Smarc 	register minor_dev;
14017881ece5Smarc 	register unit;
14027e911b15Skarels 
14037e911b15Skarels 	minor_dev = minor(dev);
14047e911b15Skarels 	unit = (minor_dev >> 2) & 0x07;
14057e911b15Skarels 
1406b2b69f49Smarc 	if (((minor_dev&0x03) != 0x02) && (qdflags[unit].inuse&CONS_DEV)) {
1407b2b69f49Smarc 		/*
1408b2b69f49Smarc 		* this is the console...
1409b2b69f49Smarc 		*/
14107e911b15Skarels 		tp = &qd_tty[minor_dev];
14117e911b15Skarels 		return ((*linesw[tp->t_line].l_write)(tp, uio));
1412b2b69f49Smarc 	} else if (qdflags[unit].inuse & GRAPHIC_DEV) {
1413b2b69f49Smarc 		/*
1414b2b69f49Smarc 		* this is a DMA xfer from user space
1415b2b69f49Smarc 		*/
14167e911b15Skarels 		return (physio(qd_strategy, &qdbuf[unit],
14177e911b15Skarels 		dev, B_WRITE, minphys, uio));
14187e911b15Skarels 	}
14197881ece5Smarc 	return (ENXIO);
14207e911b15Skarels }
14217e911b15Skarels 
14227e911b15Skarels qdread(dev, uio)
14237e911b15Skarels 	dev_t dev;
14247e911b15Skarels 	struct uio *uio;
14257e911b15Skarels {
14267e911b15Skarels 	register struct tty *tp;
14277881ece5Smarc 	register minor_dev;
14287881ece5Smarc 	register unit;
14297e911b15Skarels 
14307e911b15Skarels 	minor_dev = minor(dev);
14317e911b15Skarels 	unit = (minor_dev >> 2) & 0x07;
14327e911b15Skarels 
1433b2b69f49Smarc 	if ((minor_dev & 0x03) != 0x02 && qdflags[unit].inuse & CONS_DEV) {
1434b2b69f49Smarc 		/*
1435b2b69f49Smarc 		* this is the console
1436b2b69f49Smarc 		*/
14377e911b15Skarels 		tp = &qd_tty[minor_dev];
14387e911b15Skarels 		return ((*linesw[tp->t_line].l_read)(tp, uio));
1439b2b69f49Smarc 	} else if (qdflags[unit].inuse & GRAPHIC_DEV) {
1440b2b69f49Smarc 		/*
1441b2b69f49Smarc 		* this is a bitmap-to-processor xfer
1442b2b69f49Smarc 		*/
14437e911b15Skarels 		return (physio(qd_strategy, &qdbuf[unit],
14447e911b15Skarels 		dev, B_READ, minphys, uio));
14457e911b15Skarels 	}
14467881ece5Smarc 	return (ENXIO);
14477e911b15Skarels }
14487e911b15Skarels 
14497e911b15Skarels /***************************************************************
14507e911b15Skarels *
14517e911b15Skarels *	qd_strategy()... strategy routine to do DMA
14527e911b15Skarels *
14537e911b15Skarels ***************************************************************/
14547e911b15Skarels 
14557e911b15Skarels qd_strategy(bp)
14567e911b15Skarels 	register struct buf *bp;
14577e911b15Skarels {
14587e911b15Skarels 	register struct dga *dga;
14597e911b15Skarels 	register struct adder *adder;
14607881ece5Smarc 	register unit;
14617e911b15Skarels 	int QBAreg;
14627e911b15Skarels 	int s;
14637e911b15Skarels 	int cookie;
14647e911b15Skarels 
14657e911b15Skarels 	unit = (minor(bp->b_dev) >> 2) & 0x07;
14667e911b15Skarels 
1467b2b69f49Smarc 	/*
1468b2b69f49Smarc 	* init pointers
1469b2b69f49Smarc 	*/
14707e911b15Skarels 	if ((QBAreg = ubasetup(0, bp, 0)) == 0) {
14717881ece5Smarc 		printf("qd%d: qd_strategy: QBA setup error\n", unit);
14727e911b15Skarels 		goto STRAT_ERR;
14737e911b15Skarels 	}
14747e911b15Skarels 	dga = (struct dga *) qdmap[unit].dga;
1475e977faadSmarc 	s = spl5();
14767e911b15Skarels 	qdflags[unit].user_dma = -1;
14777e911b15Skarels 	dga->csr |= DMA_IE;
14787e911b15Skarels 	cookie = QBAreg & 0x3FFFF;
14797e911b15Skarels 	dga->adrs_lo = (short) cookie;
14807e911b15Skarels 	dga->adrs_hi = (short) (cookie >> 16);
14817e911b15Skarels 	dga->bytcnt_lo = (short) bp->b_bcount;
14827e911b15Skarels 	dga->bytcnt_hi = (short) (bp->b_bcount >> 16);
14837e911b15Skarels 
14847e911b15Skarels 	while (qdflags[unit].user_dma) {
14857e911b15Skarels 		sleep((caddr_t)&qdflags[unit].user_dma, QDPRIOR);
14867e911b15Skarels 	}
14877e911b15Skarels 	splx(s);
14887e911b15Skarels 	ubarelse(0, &QBAreg);
14897e911b15Skarels 	if (!(dga->csr & DMA_ERR)) {
14907e911b15Skarels 		iodone(bp);
14917e911b15Skarels 		return;
14927e911b15Skarels 	}
14937e911b15Skarels 
14947e911b15Skarels STRAT_ERR:
14957e911b15Skarels 	adder = (struct adder *) qdmap[unit].adder;
14967e911b15Skarels 	adder->command = CANCEL;	/* cancel adder activity */
14977e911b15Skarels 	dga->csr &= ~DMA_IE;
14987e911b15Skarels 	dga->csr &= ~0x0600;		/* halt DMA (reset fifo) */
14997e911b15Skarels 	dga->csr |= DMA_ERR;		/* clear error condition */
15007e911b15Skarels 	bp->b_flags |= B_ERROR; 	/* flag an error to physio() */
15017e911b15Skarels 
1502b2b69f49Smarc 	/*
1503b2b69f49Smarc 	 * if DMA was running, flush spurious intrpt
1504b2b69f49Smarc 	 */
15057e911b15Skarels 	if (dga->bytcnt_lo != 0) {
15067e911b15Skarels 		dga->bytcnt_lo = 0;
15077e911b15Skarels 		dga->bytcnt_hi = 0;
15087e911b15Skarels 		DMA_SETIGNORE(DMAheader[unit]);
15097e911b15Skarels 		dga->csr |= DMA_IE;
15107e911b15Skarels 	}
15117e911b15Skarels 	iodone(bp);
15127e911b15Skarels 
15137e911b15Skarels } /* qd_strategy */
15147e911b15Skarels 
15157881ece5Smarc /*
15167881ece5Smarc  *  Start output to the console screen
15177881ece5Smarc  */
15187e911b15Skarels qdstart(tp)
15197e911b15Skarels 	register struct tty *tp;
15207e911b15Skarels {
15217881ece5Smarc 	register which_unit, unit, c;
15227e911b15Skarels 	int s;
15237e911b15Skarels 
1524e977faadSmarc 	unit = minor(tp->t_dev);
1525e977faadSmarc 	which_unit = (unit >> 2) & 0x3;
1526e977faadSmarc 	unit &= 0x03;
1527e977faadSmarc 
1528e977faadSmarc 	s = spl5();
1529e977faadSmarc 
1530b2b69f49Smarc 	/*
1531b2b69f49Smarc 	* If it's currently active, or delaying, no need to do anything.
1532b2b69f49Smarc 	*/
15337e911b15Skarels 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
15347e911b15Skarels 		goto out;
15357e911b15Skarels 
1536b2b69f49Smarc 	/*
1537b2b69f49Smarc 	* Display chars until the queue is empty.
1538b2b69f49Smarc 	* Drop input from anything but the console
1539b2b69f49Smarc 	* device on the floor.
1540b2b69f49Smarc 	*
1541b2b69f49Smarc 	* XXX - this loop is done at spltty.
1542b2b69f49Smarc 	*
1543b2b69f49Smarc 	*/
15447e911b15Skarels 	while (tp->t_outq.c_cc) {
15457e911b15Skarels 		c = getc(&tp->t_outq);
1546e977faadSmarc 		if (unit == 0)
15477881ece5Smarc 			blitc(which_unit, (u_char)c);
15487e911b15Skarels 	}
1549b2b69f49Smarc 	/*
1550e977faadSmarc 	* If there are sleepers, and output has drained below low
1551b2b69f49Smarc 	* water mark, wake up the sleepers.
1552b2b69f49Smarc 	*/
1553f5319004Smarc 	if (tp->t_outq.c_cc <= tp->t_lowat) {
15547e911b15Skarels 		if (tp->t_state & TS_ASLEEP){
15557e911b15Skarels 			tp->t_state &= ~TS_ASLEEP;
15567e911b15Skarels 			wakeup((caddr_t) &tp->t_outq);
15577e911b15Skarels 		}
1558e977faadSmarc 	}
1559e977faadSmarc 
1560e977faadSmarc 	tp->t_state &= ~TS_BUSY;
15617e911b15Skarels 
15627e911b15Skarels out:
15637e911b15Skarels 	splx(s);
15647e911b15Skarels 
15657e911b15Skarels } /* qdstart */
15667e911b15Skarels 
15677881ece5Smarc /*ARGSUSED*/
15687e911b15Skarels qdstop(tp, flag)
15697e911b15Skarels 	register struct tty *tp;
15707e911b15Skarels 	int flag;
15717e911b15Skarels {
15727e911b15Skarels 	register int s;
15737e911b15Skarels 
1574e977faadSmarc 	s = spl5();	/* block intrpts during state modification */
15757881ece5Smarc 	if (tp->t_state & TS_BUSY)
15767881ece5Smarc 		if ((tp->t_state & TS_TTSTOP) == 0)
15777e911b15Skarels 			tp->t_state |= TS_FLUSH;
1578b2b69f49Smarc 		else
15797e911b15Skarels 			tp->t_state &= ~TS_BUSY;
15807e911b15Skarels 	splx(s);
15817e911b15Skarels }
15827e911b15Skarels 
15837881ece5Smarc /*
15847881ece5Smarc  *  Output a character to the QDSS screen
15857881ece5Smarc  */
15867e911b15Skarels 
15877e911b15Skarels blitc(unit, chr)
15887881ece5Smarc 	register unit;
15897881ece5Smarc 	register u_char chr;
15907e911b15Skarels {
15917e911b15Skarels 	register struct adder *adder;
15927e911b15Skarels 	register struct dga *dga;
15937e911b15Skarels 	register int i;
1594b2b69f49Smarc 	int nograph = !(qdflags[unit].inuse&GRAPHIC_DEV);
1595b2b69f49Smarc 	static short inescape[NQD];
15967e911b15Skarels 
15977e911b15Skarels 	adder = (struct adder *)qdmap[unit].adder;
15987e911b15Skarels 	dga = (struct dga *) qdmap[unit].dga;
1599b2b69f49Smarc 	/*
1600b2b69f49Smarc 	 * BSD comment: this (&=0177) defeats the extended character
1601b2b69f49Smarc 	 * set code for the glass tty, but if i had the time i would
1602b2b69f49Smarc 	 * spend it ripping out the code completely.  This driver
1603b2b69f49Smarc 	 * is too big for its own good.
1604b2b69f49Smarc 	 */
1605b2b69f49Smarc 	chr &= 0177;
1606b2b69f49Smarc 	/*
16077881ece5Smarc 	 * Cursor addressing (so vi will work).
1608b2b69f49Smarc 	 * Decode for "\E=%.%." cursor motion description.
16097881ece5Smarc 	 * Corresponds to type "qdcons" in /etc/termcap:
1610b2b69f49Smarc 	 *
1611b2b69f49Smarc 	 *    qd|qdss|qdcons|qdss glass tty (4.4 BSD):\
1612b2b69f49Smarc 	 *      :am:do=^J:le=^H:bs:cm=\E=%.%.:cl=1^Z:co#128:li#57::nd=^L:up=^K:
1613b2b69f49Smarc 	 *
1614b2b69f49Smarc 	 */
1615b2b69f49Smarc 	if (inescape[unit] && nograph) {
1616b2b69f49Smarc 		switch (inescape[unit]++) {
1617b2b69f49Smarc 		case 1:
1618b2b69f49Smarc 			if (chr != '=') {
1619b2b69f49Smarc 				/* abort escape sequence */
1620b2b69f49Smarc 				inescape[unit] = 0;
1621b2b69f49Smarc 				blitc(unit, chr);
1622b2b69f49Smarc 			}
16237881ece5Smarc 			return;
1624b2b69f49Smarc 		case 2:
1625b2b69f49Smarc 			/* position row */
1626b2b69f49Smarc 			cursor[unit].y = CHAR_HEIGHT * chr;
1627b2b69f49Smarc 			if (cursor[unit].y > 863 - CHAR_HEIGHT)
1628b2b69f49Smarc 				cursor[unit].y = 863 - CHAR_HEIGHT;
1629b2b69f49Smarc 			dga->y_cursor = TRANY(cursor[unit].y);
16307881ece5Smarc 			return;
1631b2b69f49Smarc 		case 3:
1632b2b69f49Smarc 			/* position column */
1633b2b69f49Smarc 			cursor[unit].x = CHAR_WIDTH * chr;
1634b2b69f49Smarc 			if (cursor[unit].x > 1024 - CHAR_WIDTH)
1635b2b69f49Smarc 				cursor[unit].x = 1023 - CHAR_WIDTH;
1636b2b69f49Smarc 			dga->x_cursor = TRANX(cursor[unit].x);
1637b2b69f49Smarc 			inescape[unit] = 0;
16387881ece5Smarc 			return;
1639b2b69f49Smarc 		default:
1640b2b69f49Smarc 			inescape[unit] = 0;
1641b2b69f49Smarc 			blitc(unit, chr);
1642b2b69f49Smarc 		}
1643b2b69f49Smarc 	}
164424f67f6bSmarc 
16457e911b15Skarels 	switch (chr) {
16467e911b15Skarels 	case '\r':			/* return char */
16477e911b15Skarels 		cursor[unit].x = 0;
1648b2b69f49Smarc 		if (nograph)
16497e911b15Skarels 			dga->x_cursor = TRANX(cursor[unit].x);
16507881ece5Smarc 		return;
16517e911b15Skarels 
16527e911b15Skarels 	case '\t':			/* tab char */
16537e911b15Skarels 		for (i = 8 - ((cursor[unit].x >> 3) & 0x07); i > 0; --i) {
16547e911b15Skarels 			blitc(unit, ' ');
16557e911b15Skarels 		}
16567881ece5Smarc 		return;
16577e911b15Skarels 
16587e911b15Skarels 	case '\n':			/* line feed char */
16597e911b15Skarels 		if ((cursor[unit].y += CHAR_HEIGHT) > (863 - CHAR_HEIGHT)) {
1660b2b69f49Smarc 			if (nograph) {
16617e911b15Skarels 				cursor[unit].y -= CHAR_HEIGHT;
16627e911b15Skarels 				scroll_up(adder);
1663b2b69f49Smarc 			} else
1664b2b69f49Smarc 				cursor[unit].y = 0;
16657e911b15Skarels 		}
1666b2b69f49Smarc 		if (nograph)
16677e911b15Skarels 			dga->y_cursor = TRANY(cursor[unit].y);
16687881ece5Smarc 		return;
16697e911b15Skarels 
16707e911b15Skarels 	case '\b':			/* backspace char */
16717e911b15Skarels 		if (cursor[unit].x > 0) {
16727e911b15Skarels 			cursor[unit].x -= CHAR_WIDTH;
1673b2b69f49Smarc 			if (nograph)
1674b2b69f49Smarc 				dga->x_cursor = TRANX(cursor[unit].x);
1675b2b69f49Smarc 		}
16767881ece5Smarc 		return;
1677b2b69f49Smarc 	case CTRL('k'):		/* cursor up */
1678b2b69f49Smarc 		if (nograph && cursor[unit].y > 0) {
1679b2b69f49Smarc 			cursor[unit].y -= CHAR_HEIGHT;
1680b2b69f49Smarc 			dga->y_cursor = TRANY(cursor[unit].y);
1681b2b69f49Smarc 		}
16827881ece5Smarc 		return;
1683b2b69f49Smarc 
1684b2b69f49Smarc 	case CTRL('^'):		/* home cursor */
1685b2b69f49Smarc 		if (nograph) {
1686b2b69f49Smarc 			cursor[unit].x = 0;
1687b2b69f49Smarc 			dga->x_cursor = TRANX(cursor[unit].x);
1688b2b69f49Smarc 			cursor[unit].y = 0;
1689b2b69f49Smarc 			dga->y_cursor = TRANY(cursor[unit].y);
1690b2b69f49Smarc 		}
16917881ece5Smarc 		return;
1692b2b69f49Smarc 
1693b2b69f49Smarc 	case CTRL('l'):		/* cursor right */
1694b2b69f49Smarc 		if (nograph && cursor[unit].x < 1023 - CHAR_WIDTH) {
1695b2b69f49Smarc 			cursor[unit].x += CHAR_WIDTH;
16967e911b15Skarels 			dga->x_cursor = TRANX(cursor[unit].x);
16977e911b15Skarels 		}
16987881ece5Smarc 		return;
16997e911b15Skarels 
1700b2b69f49Smarc 	case CTRL('z'):		/* clear screen */
1701b2b69f49Smarc 		if (nograph) {
1702b2b69f49Smarc 			setup_dragon(unit);
1703b2b69f49Smarc 			clear_qd_screen(unit);
1704b2b69f49Smarc 			/* home cursor - termcap seems to assume this */
1705b2b69f49Smarc 			cursor[unit].x = 0;
1706b2b69f49Smarc 			dga->x_cursor = TRANX(cursor[unit].x);
1707b2b69f49Smarc 			cursor[unit].y = 0;
1708b2b69f49Smarc 			dga->y_cursor = TRANY(cursor[unit].y);
1709b2b69f49Smarc 		}
17107881ece5Smarc 		return;
1711e977faadSmarc 
1712b2b69f49Smarc 	case '\033':		/* start escape sequence */
1713b2b69f49Smarc 		if (nograph)
1714b2b69f49Smarc 			inescape[unit] = 1;
17157881ece5Smarc 		return;
1716b2b69f49Smarc 
1717b2b69f49Smarc 	default:
1718b2b69f49Smarc 		if ((chr < ' ') || (chr > '~'))
17197881ece5Smarc 			return;
17207e911b15Skarels 	}
1721b2b69f49Smarc 	/*
1722b2b69f49Smarc 	 * setup VIPER operand control registers
1723b2b69f49Smarc 	 */
17247e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0001);  /* select plane #0 */
17257e911b15Skarels 	write_ID(adder, SRC1_OCR_B,
17267e911b15Skarels 	EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY);
17277e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x00FE);  /* select other planes */
17287e911b15Skarels 	write_ID(adder, SRC1_OCR_B,
17297e911b15Skarels 	EXT_SOURCE | INT_NONE | NO_ID | BAR_SHIFT_DELAY);
17307e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x00FF);  /* select all planes */
17317e911b15Skarels 	write_ID(adder, DST_OCR_B,
17327e911b15Skarels 	EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
17337e911b15Skarels 	write_ID(adder, MASK_1, 0xFFFF);
17347e911b15Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 1);
17357e911b15Skarels 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
1736e977faadSmarc 	adder->x_clip_min = 0;
1737e977faadSmarc 	adder->x_clip_max = 1024;
1738e977faadSmarc 	adder->y_clip_min = 0;
1739e977faadSmarc 	adder->y_clip_max = 864;
1740b2b69f49Smarc 	/*
1741b2b69f49Smarc 	 * load DESTINATION origin and vectors
1742b2b69f49Smarc 	 */
17437e911b15Skarels 	adder->fast_dest_dy = 0;
17447e911b15Skarels 	adder->slow_dest_dx = 0;
17457e911b15Skarels 	adder->error_1 = 0;
17467e911b15Skarels 	adder->error_2 = 0;
17477e911b15Skarels 	adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL;
17487881ece5Smarc 	(void)wait_status(adder, RASTEROP_COMPLETE);
17497e911b15Skarels 	adder->destination_x = cursor[unit].x;
17507e911b15Skarels 	adder->fast_dest_dx = CHAR_WIDTH;
17517e911b15Skarels 	adder->destination_y = cursor[unit].y;
17527e911b15Skarels 	adder->slow_dest_dy = CHAR_HEIGHT;
1753b2b69f49Smarc 	/*
1754b2b69f49Smarc 	 * load SOURCE origin and vectors
1755b2b69f49Smarc 	 */
1756e977faadSmarc 	if ((chr - ' ') > (CHARS - 1))  {
1757e977faadSmarc 		printf("Invalid character (x)%x in blitc\n",chr);
1758e977faadSmarc 		chr = ' ';
1759e977faadSmarc 	}
1760b2b69f49Smarc 	/*
1761b2b69f49Smarc 	 * X position is modulo the number of characters per line
1762b2b69f49Smarc 	 */
1763e977faadSmarc 	adder->source_1_x = FONT_X +
1764e977faadSmarc 	    (((chr - ' ') % (MAX_SCREEN_X/CHAR_WIDTH)) * CHAR_WIDTH);
1765b2b69f49Smarc 	/*
1766b2b69f49Smarc 	 * Point to either first or second row
1767b2b69f49Smarc 	 */
1768e977faadSmarc 	adder->source_1_y = 2048 - 15 *
1769e977faadSmarc 	    (((chr - ' ')/(MAX_SCREEN_X/CHAR_WIDTH)) + 1);
17707e911b15Skarels 	adder->source_1_dx = CHAR_WIDTH;
17717e911b15Skarels 	adder->source_1_dy = CHAR_HEIGHT;
17727e911b15Skarels 	write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
17737e911b15Skarels 	adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE;
1774b2b69f49Smarc 	/*
1775b2b69f49Smarc 	 * update console cursor coordinates
1776b2b69f49Smarc 	 */
17777e911b15Skarels 	cursor[unit].x += CHAR_WIDTH;
1778b2b69f49Smarc 	if (nograph)
17797e911b15Skarels 		dga->x_cursor = TRANX(cursor[unit].x);
17807e911b15Skarels 	if (cursor[unit].x > (1024 - CHAR_WIDTH)) {
17817e911b15Skarels 		blitc(unit, '\r');
17827e911b15Skarels 		blitc(unit, '\n');
17837e911b15Skarels 	}
17847e911b15Skarels 
17857e911b15Skarels } /* blitc */
17867e911b15Skarels 
17877881ece5Smarc qdreset() { }
17887e911b15Skarels 
17897881ece5Smarc /*
1790b2b69f49Smarc  *  INTERRUPT SERVICE ROUTINES
17917881ece5Smarc  */
17927e911b15Skarels 
17937881ece5Smarc /*
17947881ece5Smarc  *  Service "DMA DONE" interrupt condition
17957881ece5Smarc  */
17967e911b15Skarels qddint(qd)
17977881ece5Smarc 	register qd;
17987e911b15Skarels {
17997e911b15Skarels 	register struct DMAreq_header *header;
18007e911b15Skarels 	register struct DMAreq *request;
18017e911b15Skarels 	register struct dga *dga;
18027e911b15Skarels 	struct adder *adder;
18037e911b15Skarels 	int cookie;			/* DMA adrs for QDSS */
18047e911b15Skarels 
18057881ece5Smarc 	(void)spl4(); 			/* allow interval timer in */
18067e911b15Skarels 
1807b2b69f49Smarc 	/*
1808b2b69f49Smarc 	* init pointers
1809b2b69f49Smarc 	*/
18107e911b15Skarels 	header = DMAheader[qd]; 	    /* register for optimization */
18117e911b15Skarels 	dga = (struct dga *) qdmap[qd].dga;
18127e911b15Skarels 	adder = (struct adder *) qdmap[qd].adder;
18137e911b15Skarels 
1814b2b69f49Smarc 	/*
1815b2b69f49Smarc 	* if this interrupt flagged as bogus for interrupt flushing purposes..
1816b2b69f49Smarc 	*/
18177e911b15Skarels 	if (DMA_ISIGNORE(header)) {
18187e911b15Skarels 		DMA_CLRIGNORE(header);
18197e911b15Skarels 		return;
18207e911b15Skarels 	}
18217e911b15Skarels 
1822b2b69f49Smarc 	/*
1823b2b69f49Smarc 	* dump a DMA hardware error message if appropriate
1824b2b69f49Smarc 	*/
18257e911b15Skarels 	if (dga->csr & DMA_ERR) {
18267e911b15Skarels 
18277e911b15Skarels 		if (dga->csr & PARITY_ERR)
18287881ece5Smarc 		    printf("qd%d: qddint: DMA hardware parity fault.\n", qd);
18297e911b15Skarels 
18307e911b15Skarels 		if (dga->csr & BUS_ERR)
18317881ece5Smarc 		    printf("qd%d: qddint: DMA hardware bus error.\n", qd);
18327e911b15Skarels 	}
18337e911b15Skarels 
1834b2b69f49Smarc 	/*
1835b2b69f49Smarc 	* if this was a DMA from user space...
1836b2b69f49Smarc 	*/
18377e911b15Skarels 	if (qdflags[qd].user_dma) {
18387e911b15Skarels 		qdflags[qd].user_dma = 0;
18397e911b15Skarels 		wakeup((caddr_t)&qdflags[qd].user_dma);
18407e911b15Skarels 		return;
18417e911b15Skarels 	}
18427e911b15Skarels 
1843b2b69f49Smarc 	/*
1844b2b69f49Smarc 	* if we're doing DMA request queue services, field the error condition
1845b2b69f49Smarc 	*/
18467e911b15Skarels 	if (dga->csr & DMA_ERR) {
18477e911b15Skarels 
18487e911b15Skarels 		dga->csr &= ~0x0600;		/* halt DMA (reset fifo) */
18497e911b15Skarels 		dga->csr |= DMA_ERR;		/* clear error condition */
18507e911b15Skarels 		adder->command = CANCEL;	/* cancel adder activity */
18517e911b15Skarels 
18527e911b15Skarels 		DMA_SETERROR(header);	/* flag error in header status word */
18537e911b15Skarels 		DMA_CLRACTIVE(header);
18547e911b15Skarels 		header->DMAreq[header->oldest].DMAdone |= HARD_ERROR;
18557e911b15Skarels 		header->newest = header->oldest;
18567e911b15Skarels 		header->used = 0;
18577e911b15Skarels 
18587881ece5Smarc 		if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
18597881ece5Smarc 			selwakeup(qdrsel[qd], 0);
18607881ece5Smarc 			qdrsel[qd] = 0;
18617e911b15Skarels 			qdflags[qd].selmask &= ~SEL_WRITE;
18627e911b15Skarels 		}
18637e911b15Skarels 
18647e911b15Skarels 		if (dga->bytcnt_lo != 0) {
18657e911b15Skarels 			dga->bytcnt_lo = 0;
18667e911b15Skarels 			dga->bytcnt_hi = 0;
18677e911b15Skarels 			DMA_SETIGNORE(header);
18687e911b15Skarels 		}
18697e911b15Skarels 		return;
18707e911b15Skarels 	}
18717e911b15Skarels 
1872b2b69f49Smarc 	/*
1873b2b69f49Smarc 	* if the DMA request queue is now becoming non-full,
1874b2b69f49Smarc 	* wakeup "select" client.
1875b2b69f49Smarc 	*/
18767e911b15Skarels 	if (DMA_ISFULL(header)) {
18777881ece5Smarc 		if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
18787881ece5Smarc 			selwakeup(qdrsel[qd], 0);
18797881ece5Smarc 			qdrsel[qd] = 0;
18807e911b15Skarels 			qdflags[qd].selmask &= ~SEL_WRITE;
18817e911b15Skarels 		}
18827e911b15Skarels 	}
18837e911b15Skarels 
18847e911b15Skarels 	header->DMAreq[header->oldest].DMAdone |= REQUEST_DONE;
1885e977faadSmarc 	QDlast_DMAtype = header->DMAreq[header->oldest].DMAtype;
18867e911b15Skarels 
1887e977faadSmarc 	/* check for unexpected interrupt */
1888e977faadSmarc 	if (DMA_ISEMPTY(header))
18897e911b15Skarels 	    return;
18907e911b15Skarels 
18917e911b15Skarels 	DMA_GETEND(header);	/* update request queue indices */
18927e911b15Skarels 
1893b2b69f49Smarc 	/*
18947881ece5Smarc 	* if no more DMA pending, wake up "select" client and exit
18957881ece5Smarc 	*/
18967e911b15Skarels 	if (DMA_ISEMPTY(header)) {
18977e911b15Skarels 
18987881ece5Smarc 		if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
18997881ece5Smarc 			selwakeup(qdrsel[qd], 0);
19007881ece5Smarc 			qdrsel[qd] = 0;
19017e911b15Skarels 			qdflags[qd].selmask &= ~SEL_WRITE;
19027e911b15Skarels 		}
19037e911b15Skarels 
19047e911b15Skarels 		DMA_CLRACTIVE(header);  /* flag DMA done */
19057e911b15Skarels 		return;
19067e911b15Skarels 	}
19077e911b15Skarels 
1908b2b69f49Smarc 	/*
19097881ece5Smarc 	* initiate next DMA xfer
19107881ece5Smarc 	*/
19117e911b15Skarels 	request = DMA_GETBEGIN(header);
1912e977faadSmarc 	if (request->DMAtype != QDlast_DMAtype) {
1913e977faadSmarc 		dga->csr &= ~0x0600;	  /* halt DMA (reset fifo) */
1914e977faadSmarc 		adder->command = CANCEL;  /* cancel adder activity */
1915e977faadSmarc 	}
1916e977faadSmarc 
19177e911b15Skarels 
19187e911b15Skarels 	switch (request->DMAtype) {
19197e911b15Skarels 
19207e911b15Skarels 	case DISPLIST:
1921e977faadSmarc 		if (request->DMAtype != QDlast_DMAtype) {
19227e911b15Skarels 			dga->csr |= DL_ENB;
1923e977faadSmarc 			dga->csr &= ~(BTOP_ENB | BYTE_DMA);
1924e977faadSmarc 		}
19257e911b15Skarels 		break;
19267e911b15Skarels 
19277e911b15Skarels 	case PTOB:
1928e977faadSmarc 		if (request->DMAtype != QDlast_DMAtype) {
1929e977faadSmarc 			if (request->DMAdone & BYTE_PACK)
1930e977faadSmarc 			    dga->csr |= (PTOB_ENB | BYTE_DMA);
1931e977faadSmarc 			else {
19327e911b15Skarels 				dga->csr |= PTOB_ENB;
1933e977faadSmarc 				dga->csr &= ~BYTE_DMA;
1934e977faadSmarc 			}
1935e977faadSmarc 		}
19367e911b15Skarels 		break;
19377e911b15Skarels 
19387e911b15Skarels 	case BTOP:
1939e977faadSmarc 		if (request->DMAtype != QDlast_DMAtype) {
1940e977faadSmarc 			if (request->DMAdone & BYTE_PACK) {
1941e977faadSmarc 				dga->csr &= ~DL_ENB;
1942e977faadSmarc 				dga->csr |= (BTOP_ENB | BYTE_DMA);
1943e977faadSmarc 			}
1944e977faadSmarc 			else {
19457e911b15Skarels 				dga->csr |= BTOP_ENB;
1946e977faadSmarc 				dga->csr &= ~(BYTE_DMA | DL_ENB);
1947e977faadSmarc 			}
1948e977faadSmarc 		}
19497e911b15Skarels 		break;
19507e911b15Skarels 	default:
19517881ece5Smarc 		printf("qd%d: qddint: illegal DMAtype parameter.\n", qd);
19527e911b15Skarels 		DMA_CLRACTIVE(header);	/* flag DMA done */
19537e911b15Skarels 		return;
19547e911b15Skarels 	}
19557e911b15Skarels 
19567e911b15Skarels 	if (request->DMAdone & COUNT_ZERO) {
19577e911b15Skarels 		dga->csr &= ~SET_DONE_FIFO;
1958b2b69f49Smarc 	}
1959b2b69f49Smarc 	else if (request->DMAdone & FIFO_EMPTY) {
19607e911b15Skarels 		dga->csr |= SET_DONE_FIFO;
19617e911b15Skarels 	}
19627e911b15Skarels 
19637e911b15Skarels 	if (request->DMAdone & WORD_PACK)
19647e911b15Skarels 	    dga->csr &= ~BYTE_DMA;
19657e911b15Skarels 	else if (request->DMAdone & BYTE_PACK)
19667e911b15Skarels 	    dga->csr |= BYTE_DMA;
19677e911b15Skarels 
19687e911b15Skarels 	dga->csr |= DMA_IE;
1969e977faadSmarc 	QDlast_DMAtype = request->DMAtype;
19707e911b15Skarels 
19717e911b15Skarels 	cookie = ((int)request->bufp - (int)header) + (int)header->QBAreg;
19727e911b15Skarels 
19737e911b15Skarels 	dga->adrs_lo = (short) cookie;
19747e911b15Skarels 	dga->adrs_hi = (short) (cookie >> 16);
19757e911b15Skarels 
19767e911b15Skarels 	dga->bytcnt_lo = (short) request->length;
19777e911b15Skarels 	dga->bytcnt_hi = (short) (request->length >> 16);
19787e911b15Skarels 
19797e911b15Skarels 	return;
19807e911b15Skarels }
19817e911b15Skarels 
19827881ece5Smarc /*
19837881ece5Smarc  * ADDER interrupt service routine
19847881ece5Smarc  */
19857e911b15Skarels qdaint(qd)
19867881ece5Smarc 	register qd;
19877e911b15Skarels {
19887e911b15Skarels 	register struct adder *adder;
19897e911b15Skarels 	struct color_buf *cbuf;
19907e911b15Skarels 	int i;
19917e911b15Skarels 	register struct rgb *rgbp;
19927e911b15Skarels 	register short *red;
19937e911b15Skarels 	register short *green;
19947e911b15Skarels 	register short *blue;
19957e911b15Skarels 
19967881ece5Smarc 	(void)spl4(); 			/* allow interval timer in */
19977e911b15Skarels 
19987e911b15Skarels 	adder = (struct adder *) qdmap[qd].adder;
19997e911b15Skarels 
2000b2b69f49Smarc 	/*
2001b2b69f49Smarc 	* service the vertical blank interrupt (VSYNC bit) by loading
2002b2b69f49Smarc 	* any pending color map load request
2003b2b69f49Smarc 	*/
20047e911b15Skarels 	if (adder->status & VSYNC) {
20057e911b15Skarels 		adder->status &= ~VSYNC;	/* clear the interrupt */
20067e911b15Skarels 		cbuf = color_buf[qd];
20077e911b15Skarels 		if (cbuf->status & LOAD_COLOR_MAP) {
20087e911b15Skarels 
20097e911b15Skarels 			red = (short *) qdmap[qd].red;
20107e911b15Skarels 			green = (short *) qdmap[qd].green;
20117e911b15Skarels 			blue = (short *) qdmap[qd].blue;
20127e911b15Skarels 
2013b2b69f49Smarc 			for (i = cbuf->count, rgbp = cbuf->rgb;
2014b2b69f49Smarc 			     --i >= 0; rgbp++) {
20157e911b15Skarels 				red[rgbp->offset] = (short) rgbp->red;
20167e911b15Skarels 				green[rgbp->offset] = (short) rgbp->green;
20177e911b15Skarels 				blue[rgbp->offset] = (short) rgbp->blue;
20187e911b15Skarels 			}
20197e911b15Skarels 
20207e911b15Skarels 			cbuf->status &= ~LOAD_COLOR_MAP;
20217e911b15Skarels 		}
20227e911b15Skarels 	}
20237e911b15Skarels 
2024b2b69f49Smarc 	/*
2025b2b69f49Smarc 	* service the scroll interrupt (FRAME_SYNC bit)
2026b2b69f49Smarc 	*/
20277e911b15Skarels 	if (adder->status & FRAME_SYNC) {
20287e911b15Skarels 		adder->status &= ~FRAME_SYNC;	/* clear the interrupt */
20297e911b15Skarels 
20307e911b15Skarels 		if (scroll[qd]->status & LOAD_REGS) {
20317e911b15Skarels 
20327881ece5Smarc 			for (i = 1000, adder->status = 0; i > 0 &&
20337881ece5Smarc 			     !(adder->status&ID_SCROLL_READY); --i)
2034b2b69f49Smarc 			      ;
20357e911b15Skarels 
20367e911b15Skarels 			if (i == 0) {
20377881ece5Smarc 			    printf("qd%d: qdaint: timeout on ID_SCROLL_READY\n",
2038b2b69f49Smarc 				qd);
20397e911b15Skarels 				return;
20407e911b15Skarels 			}
20417e911b15Skarels 
20427e911b15Skarels 			adder->ID_scroll_data = scroll[qd]->viper_constant;
20437e911b15Skarels 			adder->ID_scroll_command = ID_LOAD | SCROLL_CONSTANT;
20447e911b15Skarels 
2045b2b69f49Smarc 			adder->y_scroll_constant =
2046b2b69f49Smarc 				scroll[qd]->y_scroll_constant;
20477e911b15Skarels 			adder->y_offset_pending = scroll[qd]->y_offset;
20487e911b15Skarels 
20497e911b15Skarels 			if (scroll[qd]->status & LOAD_INDEX) {
20507e911b15Skarels 
2051b2b69f49Smarc 				adder->x_index_pending =
2052b2b69f49Smarc 					scroll[qd]->x_index_pending;
2053b2b69f49Smarc 				adder->y_index_pending =
2054b2b69f49Smarc 					scroll[qd]->y_index_pending;
20557e911b15Skarels 			}
20567e911b15Skarels 
20577e911b15Skarels 			scroll[qd]->status = 0x00;
20587e911b15Skarels 		}
20597e911b15Skarels 	}
20607e911b15Skarels }
20617e911b15Skarels 
20627881ece5Smarc /*
20637881ece5Smarc  *  DUART input interrupt service routine
20647e911b15Skarels  *
2065b2b69f49Smarc  *  XXX - this routine should be broken out - it is essentially
2066b2b69f49Smarc  *	      straight line code.
20677881ece5Smarc  */
20687e911b15Skarels 
20697e911b15Skarels qdiint(qd)
20707881ece5Smarc 	register qd;
20717e911b15Skarels {
20727e911b15Skarels 	register struct _vs_event *event;
20737e911b15Skarels 	register struct qdinput *eqh;
20747e911b15Skarels 	struct dga *dga;
20757e911b15Skarels 	struct duart *duart;
20767e911b15Skarels 	struct mouse_report *new_rep;
20777e911b15Skarels 	struct uba_device *ui;
20787e911b15Skarels 	struct tty *tp;
2079e977faadSmarc 	u_short chr;
20807e911b15Skarels 	u_short status;
20817e911b15Skarels 	u_short data;
20827e911b15Skarels 	u_short key;
20837e911b15Skarels 	char do_wakeup = 0;		/* flag to do a select wakeup call */
20847e911b15Skarels 	char a, b, c;			/* mouse button test variables */
20857e911b15Skarels 
20867881ece5Smarc 	(void)spl4(); 			/* allow interval timer in */
20877e911b15Skarels 
20887e911b15Skarels 	eqh = eq_header[qd];		/* optimized as a register */
20897e911b15Skarels 	new_rep = &current_rep[qd];
20907e911b15Skarels 	duart = (struct duart *) qdmap[qd].duart;
20917e911b15Skarels 
2092b2b69f49Smarc 	/*
20937881ece5Smarc 	* if the graphic device is turned on..
20947881ece5Smarc 	*/
20957e911b15Skarels 	if (qdflags[qd].inuse & GRAPHIC_DEV) {
2096b2b69f49Smarc 		/*
2097b2b69f49Smarc 		* empty DUART
2098b2b69f49Smarc 		*/
20997881ece5Smarc 		while (duart->statusA&RCV_RDY || duart->statusB&RCV_RDY) {
2100b2b69f49Smarc 			/*
21017881ece5Smarc 			 * pick up LK-201 input (if any)
21027881ece5Smarc 			 */
21037881ece5Smarc 			if (duart->statusA&RCV_RDY) {
21047e911b15Skarels 
21057e911b15Skarels 				/* if error condition, then reset it */
21067e911b15Skarels 
21077881ece5Smarc 				if (duart->statusA&0x70) {
21087e911b15Skarels 					duart->cmdA = 0x40;
21097e911b15Skarels 					continue;
21107e911b15Skarels 				}
21117e911b15Skarels 
21127e911b15Skarels 				/* event queue full now? (overflow condition) */
21137e911b15Skarels 
21147e911b15Skarels 				if (ISFULL(eqh) == TRUE) {
2115b2b69f49Smarc 					printf(
21167881ece5Smarc 					 "qd%d: qdiint: event queue overflow\n",
2117b2b69f49Smarc 					   qd);
21187e911b15Skarels 					break;
21197e911b15Skarels 				}
21207e911b15Skarels 
2121b2b69f49Smarc 				/*
21227e911b15Skarels 				* Check for various keyboard errors  */
21237e911b15Skarels 
21247e911b15Skarels 				key = duart->dataA & 0xFF;
21257e911b15Skarels 
2126b2b69f49Smarc 				if (key==LK_POWER_ERROR ||
2127b2b69f49Smarc 				    key==LK_KDOWN_ERROR ||
2128b2b69f49Smarc 				    key == LK_INPUT_ERROR ||
2129b2b69f49Smarc 				    key == LK_OUTPUT_ERROR) {
2130b2b69f49Smarc 					printf(
21317881ece5Smarc 				    "qd%d: qdiint: keyboard error, code = %x\n",
2132b2b69f49Smarc 					qd,key);
21337881ece5Smarc 					return;
21347e911b15Skarels 				}
21357e911b15Skarels 
21367e911b15Skarels 				if (key < LK_LOWEST)
21377881ece5Smarc 				    return;
21387e911b15Skarels 
21397e911b15Skarels 				++do_wakeup;  /* request a select wakeup call */
21407e911b15Skarels 
21417e911b15Skarels 				event = PUTBEGIN(eqh);
21427e911b15Skarels 				PUTEND(eqh);
21437e911b15Skarels 
21447e911b15Skarels 				event->vse_key = key;
21457e911b15Skarels 				event->vse_key &= 0x00FF;
21467e911b15Skarels 				event->vse_x = eqh->curs_pos.x;
21477e911b15Skarels 				event->vse_y = eqh->curs_pos.y;
21487e911b15Skarels 				event->vse_time = TOY;
21497e911b15Skarels 				event->vse_type = VSE_BUTTON;
21507e911b15Skarels 				event->vse_direction = VSE_KBTRAW;
21517e911b15Skarels 				event->vse_device = VSE_DKB;
21527e911b15Skarels 			}
21537e911b15Skarels 
2154b2b69f49Smarc 			/*
21557e911b15Skarels 			* pick up the mouse input (if any)  */
21567e911b15Skarels 
21577e911b15Skarels 			if ((status = duart->statusB) & RCV_RDY  &&
21587e911b15Skarels 			    qdflags[qd].pntr_id == MOUSE_ID) {
21597e911b15Skarels 
21607e911b15Skarels 				if (status & 0x70) {
21617e911b15Skarels 					duart->cmdB = 0x40;
21627e911b15Skarels 					continue;
21637e911b15Skarels 				}
21647e911b15Skarels 
21657e911b15Skarels 				/* event queue full now? (overflow condition) */
21667e911b15Skarels 
21677e911b15Skarels 				if (ISFULL(eqh) == TRUE) {
2168b2b69f49Smarc 					printf(
21697881ece5Smarc 					"qd%d: qdiint: event queue overflow\n",
2170b2b69f49Smarc 					     qd);
21717e911b15Skarels 					break;
21727e911b15Skarels 				}
21737e911b15Skarels 
21747e911b15Skarels 				data = duart->dataB;      /* get report byte */
21757e911b15Skarels 				++new_rep->bytcnt; /* bump report byte count */
21767e911b15Skarels 
2177b2b69f49Smarc 				/*
21787e911b15Skarels 				* if 1st byte of report.. */
21797e911b15Skarels 
21807e911b15Skarels 				if ( data & START_FRAME) {
21817e911b15Skarels 					new_rep->state = data;
21827e911b15Skarels 					if (new_rep->bytcnt > 1) {
2183b2b69f49Smarc 						/* start of new frame */
2184b2b69f49Smarc 						new_rep->bytcnt = 1;
2185b2b69f49Smarc 						/* ..continue looking */
2186b2b69f49Smarc 						continue;
21877e911b15Skarels 					}
21887e911b15Skarels 				}
21897e911b15Skarels 
2190b2b69f49Smarc 				/*
21917e911b15Skarels 				* if 2nd byte of report.. */
21927e911b15Skarels 
21937e911b15Skarels 				else if (new_rep->bytcnt == 2) {
21947e911b15Skarels 					new_rep->dx = data & 0x00FF;
21957e911b15Skarels 				}
21967e911b15Skarels 
2197b2b69f49Smarc 				/*
21987e911b15Skarels 				* if 3rd byte of report, load input event queue */
21997e911b15Skarels 
22007e911b15Skarels 				else if (new_rep->bytcnt == 3) {
22017e911b15Skarels 
22027e911b15Skarels 					new_rep->dy = data & 0x00FF;
22037e911b15Skarels 					new_rep->bytcnt = 0;
22047e911b15Skarels 
2205b2b69f49Smarc 					/*
22067e911b15Skarels 					* if mouse position has changed.. */
22077e911b15Skarels 
22087e911b15Skarels 					if (new_rep->dx != 0  ||  new_rep->dy != 0) {
22097e911b15Skarels 
2210b2b69f49Smarc 						/*
22117e911b15Skarels 						* calculate acceleration factor, if needed	*/
22127e911b15Skarels 
22137e911b15Skarels 						if (qdflags[qd].curs_acc > ACC_OFF) {
22147e911b15Skarels 
22157e911b15Skarels 							if (qdflags[qd].curs_thr <= new_rep->dx)
22167e911b15Skarels 							    new_rep->dx +=
22177e911b15Skarels 							    (new_rep->dx - qdflags[qd].curs_thr)
22187e911b15Skarels 							    * qdflags[qd].curs_acc;
22197e911b15Skarels 
22207e911b15Skarels 							if (qdflags[qd].curs_thr <= new_rep->dy)
22217e911b15Skarels 							    new_rep->dy +=
22227e911b15Skarels 							    (new_rep->dy - qdflags[qd].curs_thr)
22237e911b15Skarels 							    * qdflags[qd].curs_acc;
22247e911b15Skarels 						}
22257e911b15Skarels 
2226b2b69f49Smarc 						/*
22277e911b15Skarels 						* update cursor position coordinates */
22287e911b15Skarels 
22297e911b15Skarels 						if (new_rep->state & X_SIGN) {
22307e911b15Skarels 							eqh->curs_pos.x += new_rep->dx;
22317e911b15Skarels 							if (eqh->curs_pos.x > 1023)
22327e911b15Skarels 							    eqh->curs_pos.x = 1023;
22337e911b15Skarels 						}
22347e911b15Skarels 						else {
22357e911b15Skarels 							eqh->curs_pos.x -= new_rep->dx;
22367e911b15Skarels 							if (eqh->curs_pos.x < -15)
22377e911b15Skarels 							    eqh->curs_pos.x = -15;
22387e911b15Skarels 						}
22397e911b15Skarels 
22407e911b15Skarels 						if (new_rep->state & Y_SIGN) {
22417e911b15Skarels 							eqh->curs_pos.y -= new_rep->dy;
22427e911b15Skarels 							if (eqh->curs_pos.y < -15)
22437e911b15Skarels 							    eqh->curs_pos.y = -15;
22447e911b15Skarels 						}
22457e911b15Skarels 						else {
22467e911b15Skarels 							eqh->curs_pos.y += new_rep->dy;
22477e911b15Skarels 							if (eqh->curs_pos.y > 863)
22487e911b15Skarels 							    eqh->curs_pos.y = 863;
22497e911b15Skarels 						}
22507e911b15Skarels 
2251b2b69f49Smarc 						/*
22527e911b15Skarels 						* update cursor screen position */
22537e911b15Skarels 
22547e911b15Skarels 						dga = (struct dga *) qdmap[qd].dga;
22557e911b15Skarels 						dga->x_cursor = TRANX(eqh->curs_pos.x);
22567e911b15Skarels 						dga->y_cursor = TRANY(eqh->curs_pos.y);
22577e911b15Skarels 
2258b2b69f49Smarc 						/*
22597e911b15Skarels 						* if cursor is in the box, no event report */
22607e911b15Skarels 
22617e911b15Skarels 						if (eqh->curs_pos.x <= eqh->curs_box.right	&&
22627e911b15Skarels 						    eqh->curs_pos.x >= eqh->curs_box.left  &&
22637e911b15Skarels 						    eqh->curs_pos.y >= eqh->curs_box.top  &&
22647e911b15Skarels 						    eqh->curs_pos.y <= eqh->curs_box.bottom ) {
22657e911b15Skarels 							goto GET_MBUTTON;
22667e911b15Skarels 						}
22677e911b15Skarels 
2268b2b69f49Smarc 						/*
22697e911b15Skarels 						* report the mouse motion event */
22707e911b15Skarels 
22717e911b15Skarels 						event = PUTBEGIN(eqh);
22727e911b15Skarels 						PUTEND(eqh);
22737e911b15Skarels 
22747e911b15Skarels 						++do_wakeup;   /* request a select wakeup call */
22757e911b15Skarels 
22767e911b15Skarels 						event->vse_x = eqh->curs_pos.x;
22777e911b15Skarels 						event->vse_y = eqh->curs_pos.y;
22787e911b15Skarels 
22797e911b15Skarels 						event->vse_device = VSE_MOUSE;  /* mouse */
22807e911b15Skarels 						event->vse_type = VSE_MMOTION;  /* pos changed */
22817e911b15Skarels 						event->vse_key = 0;
22827e911b15Skarels 						event->vse_direction = 0;
22837e911b15Skarels 						event->vse_time = TOY;	/* time stamp */
22847e911b15Skarels 					}
22857e911b15Skarels 
22867e911b15Skarels GET_MBUTTON:
2287b2b69f49Smarc 					/*
22887e911b15Skarels 					* if button state has changed */
22897e911b15Skarels 
22907e911b15Skarels 					a = new_rep->state & 0x07;    /*mask nonbutton bits */
22917e911b15Skarels 					b = last_rep[qd].state & 0x07;
22927e911b15Skarels 
22937e911b15Skarels 					if (a ^ b) {
22947e911b15Skarels 
22957e911b15Skarels 						for ( c = 1;  c < 8; c <<= 1) {
22967e911b15Skarels 
22977e911b15Skarels 							if (!( c & (a ^ b))) /* this button change? */
22987e911b15Skarels 							    continue;
22997e911b15Skarels 
23007e911b15Skarels 							/* event queue full? (overflow condition) */
23017e911b15Skarels 
23027e911b15Skarels 							if (ISFULL(eqh) == TRUE) {
23037881ece5Smarc 								printf("qd%d: qdiint: event queue overflow\n", qd);
23047e911b15Skarels 								break;
23057e911b15Skarels 							}
23067e911b15Skarels 
23077e911b15Skarels 							event = PUTBEGIN(eqh);	/* get new event */
23087e911b15Skarels 							PUTEND(eqh);
23097e911b15Skarels 
23107e911b15Skarels 							++do_wakeup;   /* request select wakeup */
23117e911b15Skarels 
23127e911b15Skarels 							event->vse_x = eqh->curs_pos.x;
23137e911b15Skarels 							event->vse_y = eqh->curs_pos.y;
23147e911b15Skarels 
23157e911b15Skarels 							event->vse_device = VSE_MOUSE;	/* mouse */
23167e911b15Skarels 							event->vse_type = VSE_BUTTON; /* new button */
23177e911b15Skarels 							event->vse_time = TOY;	      /* time stamp */
23187e911b15Skarels 
23197e911b15Skarels 							/* flag changed button and if up or down */
23207e911b15Skarels 
23217e911b15Skarels 							if (c == RIGHT_BUTTON)
23227e911b15Skarels 							    event->vse_key = VSE_RIGHT_BUTTON;
23237e911b15Skarels 							else if (c == MIDDLE_BUTTON)
23247e911b15Skarels 							    event->vse_key = VSE_MIDDLE_BUTTON;
23257e911b15Skarels 							else if (c == LEFT_BUTTON)
23267e911b15Skarels 							    event->vse_key = VSE_LEFT_BUTTON;
23277e911b15Skarels 
23287e911b15Skarels 							/* set bit = button depressed */
23297e911b15Skarels 
23307e911b15Skarels 							if (c & a)
23317e911b15Skarels 							    event->vse_direction = VSE_KBTDOWN;
23327e911b15Skarels 							else
23337e911b15Skarels 								event->vse_direction = VSE_KBTUP;
23347e911b15Skarels 						}
23357e911b15Skarels 					}
23367e911b15Skarels 
23377e911b15Skarels 					/* refresh last report */
23387e911b15Skarels 
23397e911b15Skarels 					last_rep[qd] = current_rep[qd];
23407e911b15Skarels 
23417e911b15Skarels 				}  /* get last byte of report */
23427881ece5Smarc 			} else if ((status = duart->statusB)&RCV_RDY &&
23437e911b15Skarels 			           qdflags[qd].pntr_id == TABLET_ID) {
23447881ece5Smarc 				/*
23457881ece5Smarc 				* pickup tablet input, if any
23467881ece5Smarc 				*/
23477e911b15Skarels 				if (status&0x70) {
23487e911b15Skarels 					duart->cmdB = 0x40;
23497e911b15Skarels 					continue;
23507e911b15Skarels 				}
23517881ece5Smarc 				/*
23527881ece5Smarc 				 * event queue full now? (overflow condition)
23537881ece5Smarc 				 */
23547e911b15Skarels 				if (ISFULL(eqh) == TRUE) {
23557881ece5Smarc 					printf("qd%d: qdiint: event queue overflow\n", qd);
23567e911b15Skarels 					break;
23577e911b15Skarels 				}
23587e911b15Skarels 
23597e911b15Skarels 				data = duart->dataB;      /* get report byte */
23607e911b15Skarels 				++new_rep->bytcnt;	      /* bump report byte count */
23617e911b15Skarels 
2362b2b69f49Smarc 				/*
23637e911b15Skarels 				* if 1st byte of report.. */
23647e911b15Skarels 
23657e911b15Skarels 				if (data & START_FRAME) {
23667e911b15Skarels 					new_rep->state = data;
23677e911b15Skarels 					if (new_rep->bytcnt > 1) {
23687e911b15Skarels 						new_rep->bytcnt = 1;    /* start of new frame */
23697e911b15Skarels 						continue;		    /* ..continue looking */
23707e911b15Skarels 					}
23717e911b15Skarels 				}
23727e911b15Skarels 
2373b2b69f49Smarc 				/*
23747e911b15Skarels 				* if 2nd byte of report.. */
23757e911b15Skarels 
23767e911b15Skarels 				else if (new_rep->bytcnt == 2) {
23777e911b15Skarels 					new_rep->dx = data & 0x3F;
23787e911b15Skarels 				}
23797e911b15Skarels 
2380b2b69f49Smarc 				/*
23817e911b15Skarels 				* if 3rd byte of report.. */
23827e911b15Skarels 
23837e911b15Skarels 				else if (new_rep->bytcnt == 3) {
23847e911b15Skarels 					new_rep->dx |= (data & 0x3F) << 6;
23857e911b15Skarels 				}
23867e911b15Skarels 
2387b2b69f49Smarc 				/*
23887e911b15Skarels 				* if 4th byte of report.. */
23897e911b15Skarels 
23907e911b15Skarels 				else if (new_rep->bytcnt == 4) {
23917e911b15Skarels 					new_rep->dy = data & 0x3F;
23927e911b15Skarels 				}
23937e911b15Skarels 
2394b2b69f49Smarc 				/*
23957e911b15Skarels 				* if 5th byte of report, load input event queue */
23967e911b15Skarels 
23977e911b15Skarels 				else if (new_rep->bytcnt == 5) {
23987e911b15Skarels 
23997e911b15Skarels 					new_rep->dy |= (data & 0x3F) << 6;
24007e911b15Skarels 					new_rep->bytcnt = 0;
24017e911b15Skarels 
2402b2b69f49Smarc 					/*
24037e911b15Skarels 					* update cursor position coordinates */
24047e911b15Skarels 
24057e911b15Skarels 					new_rep->dx /= qdflags[qd].tab_res;
24067e911b15Skarels 					new_rep->dy = (2200 - new_rep->dy)
24077e911b15Skarels 					    / qdflags[qd].tab_res;
24087e911b15Skarels 
24097e911b15Skarels 					if (new_rep->dx > 1023) {
24107e911b15Skarels 						new_rep->dx = 1023;
24117e911b15Skarels 					}
24127e911b15Skarels 					if (new_rep->dy > 863) {
24137e911b15Skarels 						new_rep->dy = 863;
24147e911b15Skarels 					}
24157e911b15Skarels 
24167e911b15Skarels 					/*
24177e911b15Skarels 					* report an event if the puck/stylus has moved
24187e911b15Skarels 					*/
24197e911b15Skarels 
24207e911b15Skarels 					if (eqh->curs_pos.x != new_rep->dx ||
24217e911b15Skarels 					    eqh->curs_pos.y != new_rep->dy) {
24227e911b15Skarels 
24237e911b15Skarels 						eqh->curs_pos.x = new_rep->dx;
24247e911b15Skarels 						eqh->curs_pos.y = new_rep->dy;
24257e911b15Skarels 
2426b2b69f49Smarc 						/*
24277e911b15Skarels 						* update cursor screen position */
24287e911b15Skarels 
24297e911b15Skarels 						dga = (struct dga *) qdmap[qd].dga;
24307e911b15Skarels 						dga->x_cursor = TRANX(eqh->curs_pos.x);
24317e911b15Skarels 						dga->y_cursor = TRANY(eqh->curs_pos.y);
24327e911b15Skarels 
24337e911b15Skarels 						/*
24347e911b15Skarels 						* if cursor is in the box, no event report
24357e911b15Skarels 						*/
24367e911b15Skarels 
24377e911b15Skarels 						if (eqh->curs_pos.x <= eqh->curs_box.right	&&
24387e911b15Skarels 						    eqh->curs_pos.x >= eqh->curs_box.left  &&
24397e911b15Skarels 						    eqh->curs_pos.y >= eqh->curs_box.top  &&
24407e911b15Skarels 						    eqh->curs_pos.y <= eqh->curs_box.bottom ) {
24417e911b15Skarels 							goto GET_TBUTTON;
24427e911b15Skarels 						}
24437e911b15Skarels 
2444b2b69f49Smarc 						/*
24457e911b15Skarels 						* report the tablet motion event */
24467e911b15Skarels 
24477e911b15Skarels 						event = PUTBEGIN(eqh);
24487e911b15Skarels 						PUTEND(eqh);
24497e911b15Skarels 
24507e911b15Skarels 						++do_wakeup;   /* request a select wakeup call */
24517e911b15Skarels 
24527e911b15Skarels 						event->vse_x = eqh->curs_pos.x;
24537e911b15Skarels 						event->vse_y = eqh->curs_pos.y;
24547e911b15Skarels 
24557e911b15Skarels 						event->vse_device = VSE_TABLET;  /* tablet */
24567e911b15Skarels 						/*
24577e911b15Skarels 						* right now, X handles tablet motion the same
24587e911b15Skarels 						* as mouse motion
24597e911b15Skarels 						*/
24607e911b15Skarels 						event->vse_type = VSE_MMOTION;   /* pos changed */
24617e911b15Skarels 						event->vse_key = 0;
24627e911b15Skarels 						event->vse_direction = 0;
24637e911b15Skarels 						event->vse_time = TOY;	/* time stamp */
24647e911b15Skarels 					}
24657e911b15Skarels GET_TBUTTON:
2466b2b69f49Smarc 					/*
24677e911b15Skarels 					* if button state has changed */
24687e911b15Skarels 
24697e911b15Skarels 					a = new_rep->state & 0x1E;   /* mask nonbutton bits */
24707e911b15Skarels 					b = last_rep[qd].state & 0x1E;
24717e911b15Skarels 
24727e911b15Skarels 					if (a ^ b) {
24737e911b15Skarels 
24747e911b15Skarels 						/* event queue full now? (overflow condition) */
24757e911b15Skarels 
24767e911b15Skarels 						if (ISFULL(eqh) == TRUE) {
24777881ece5Smarc 							printf("qd%d: qdiint: event queue overflow\n",qd);
24787e911b15Skarels 							break;
24797e911b15Skarels 						}
24807e911b15Skarels 
24817e911b15Skarels 						event = PUTBEGIN(eqh);  /* get new event */
24827e911b15Skarels 						PUTEND(eqh);
24837e911b15Skarels 
24847e911b15Skarels 						++do_wakeup;   /* request a select wakeup call */
24857e911b15Skarels 
24867e911b15Skarels 						event->vse_x = eqh->curs_pos.x;
24877e911b15Skarels 						event->vse_y = eqh->curs_pos.y;
24887e911b15Skarels 
24897e911b15Skarels 						event->vse_device = VSE_TABLET;  /* tablet */
24907e911b15Skarels 						event->vse_type = VSE_BUTTON; /* button changed */
24917e911b15Skarels 						event->vse_time = TOY;	   /* time stamp */
24927e911b15Skarels 
24937e911b15Skarels 						/* define the changed button and if up or down */
24947e911b15Skarels 
24957e911b15Skarels 						for ( c = 1;  c <= 0x10; c <<= 1) {
24967e911b15Skarels 							if (c & (a ^ b)) {
24977e911b15Skarels 								if (c == T_LEFT_BUTTON)
24987e911b15Skarels 								    event->vse_key = VSE_T_LEFT_BUTTON;
24997e911b15Skarels 								else if (c == T_FRONT_BUTTON)
25007e911b15Skarels 								    event->vse_key = VSE_T_FRONT_BUTTON;
25017e911b15Skarels 								else if (c == T_RIGHT_BUTTON)
25027e911b15Skarels 								    event->vse_key = VSE_T_RIGHT_BUTTON;
25037e911b15Skarels 								else if (c == T_BACK_BUTTON)
25047e911b15Skarels 								    event->vse_key = VSE_T_BACK_BUTTON;
25057e911b15Skarels 								break;
25067e911b15Skarels 							}
25077e911b15Skarels 						}
25087e911b15Skarels 
25097e911b15Skarels 						/* set bit = button depressed */
25107e911b15Skarels 
25117e911b15Skarels 						if (c & a)
25127e911b15Skarels 						    event->vse_direction = VSE_KBTDOWN;
25137e911b15Skarels 						else
25147e911b15Skarels 							event->vse_direction = VSE_KBTUP;
25157e911b15Skarels 					}
25167e911b15Skarels 
25177e911b15Skarels 					/* refresh last report */
25187e911b15Skarels 
25197e911b15Skarels 					last_rep[qd] = current_rep[qd];
25207e911b15Skarels 
25217e911b15Skarels 				} /* get last byte of report */
25227e911b15Skarels 			} /* pick up tablet input */
25237e911b15Skarels 
25247e911b15Skarels 		} /* while input available.. */
25257e911b15Skarels 
2526b2b69f49Smarc 		/*
2527b2b69f49Smarc 		* do select wakeup
2528b2b69f49Smarc 		*/
25297881ece5Smarc 		if (qdrsel[qd] && do_wakeup && qdflags[qd].selmask & SEL_READ) {
25307881ece5Smarc 			selwakeup(qdrsel[qd], 0);
25317881ece5Smarc 			qdrsel[qd] = 0;
25327e911b15Skarels 			qdflags[qd].selmask &= ~SEL_READ;
25337e911b15Skarels 			do_wakeup = 0;
25347e911b15Skarels 		}
25357881ece5Smarc 	} else {
2536b2b69f49Smarc 		/*
25377881ece5Smarc 		 * if the graphic device is not turned on, this is console input
25387881ece5Smarc 		 */
2539*f79d7b48Smarc 		if (qdpolling)
2540*f79d7b48Smarc 			return;
25417e911b15Skarels 		ui = qdinfo[qd];
25427e911b15Skarels 		if (ui == 0 || ui->ui_alive == 0)
25437881ece5Smarc 			return;
25447e911b15Skarels 
25457e911b15Skarels 		tp = &qd_tty[qd << 2];
25467e911b15Skarels 
2547b2b69f49Smarc 		/*
25487881ece5Smarc 		 * Get a character from the keyboard.
25497881ece5Smarc 		 */
25507881ece5Smarc 		while (duart->statusA&RCV_RDY) {
25517e911b15Skarels 			key = duart->dataA;
25527e911b15Skarels 			key &= 0xFF;
2553b2b69f49Smarc 			/*
25547881ece5Smarc 			* Check for various keyboard errors
25557881ece5Smarc 			*/
25567e911b15Skarels 			if (key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
25577e911b15Skarels 			    key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
25587881ece5Smarc 				printf("qd%d: qdiint: Keyboard error, code = %x\n",qd,key);
25597881ece5Smarc 				return;
25607e911b15Skarels 			}
25617e911b15Skarels 
25627e911b15Skarels 			if (key < LK_LOWEST)
25637881ece5Smarc 			    return;
25647e911b15Skarels 
2565b2b69f49Smarc 			/*
25667e911b15Skarels 			* See if its a state change key */
25677e911b15Skarels 
25687e911b15Skarels 			switch (key) {
25697e911b15Skarels 
25707e911b15Skarels 			case LOCK:
25717e911b15Skarels 				q_keyboard.lock ^= 0xffff;	/* toggle */
25727e911b15Skarels 				if (q_keyboard.lock)
25737881ece5Smarc 					(void)led_control(qd, LK_LED_ENABLE,
25747881ece5Smarc 							  LK_LED_LOCK);
25757e911b15Skarels 				else
25767881ece5Smarc 					(void)led_control(qd, LK_LED_DISABLE,
25777881ece5Smarc 							  LK_LED_LOCK);
25787e911b15Skarels 				return;
25797e911b15Skarels 
25807e911b15Skarels 			case SHIFT:
25817e911b15Skarels 				q_keyboard.shift ^= 0xFFFF;
25827e911b15Skarels 				return;
25837e911b15Skarels 
25847e911b15Skarels 			case CNTRL:
25857e911b15Skarels 				q_keyboard.cntrl ^= 0xFFFF;
25867e911b15Skarels 				return;
25877e911b15Skarels 
25887e911b15Skarels 			case ALLUP:
25897e911b15Skarels 				q_keyboard.cntrl = 0;
25907e911b15Skarels 				q_keyboard.shift = 0;
25917e911b15Skarels 				return;
25927e911b15Skarels 
25937e911b15Skarels 			case REPEAT:
25947e911b15Skarels 				chr = q_keyboard.last;
25957e911b15Skarels 				break;
25967e911b15Skarels 
2597b2b69f49Smarc 				/*
25987e911b15Skarels 				* Test for cntrl characters. If set, see if the character
25997e911b15Skarels 				* is elligible to become a control character. */
26007e911b15Skarels 
26017e911b15Skarels 			default:
26027e911b15Skarels 
26037e911b15Skarels 				if (q_keyboard.cntrl) {
26047e911b15Skarels 					chr = q_key[key];
26057e911b15Skarels 					if (chr >= ' ' && chr <= '~')
26067e911b15Skarels 					    chr &= 0x1F;
2607e977faadSmarc 					else if (chr >= 0xA1 && chr <= 0xFE)
2608e977faadSmarc 					    chr &= 0x9F;
26097e911b15Skarels 				}
26107e911b15Skarels 				else if( q_keyboard.lock || q_keyboard.shift )
26117e911b15Skarels 				    chr = q_shift_key[key];
26127e911b15Skarels 				else
26137e911b15Skarels 					chr = q_key[key];
26147e911b15Skarels 				break;
26157e911b15Skarels 			}
26167e911b15Skarels 
26177e911b15Skarels 			q_keyboard.last = chr;
26187e911b15Skarels 
2619b2b69f49Smarc 			/*
26207e911b15Skarels 			* Check for special function keys */
26217e911b15Skarels 
2622e977faadSmarc 			if (chr & 0x100) {
26237e911b15Skarels 				char *string;
26247e911b15Skarels 				string = q_special[chr & 0x7F];
26257e911b15Skarels 				while(*string)
26267e911b15Skarels 				    (*linesw[tp->t_line].l_rint)(*string++, tp);
26277e911b15Skarels 			}
26287e911b15Skarels 			else {
2629*f79d7b48Smarc #ifdef KADB
2630*f79d7b48Smarc 				if (!kdbrintr(chr&0177, tp))
2631*f79d7b48Smarc #endif
2632b2b69f49Smarc 				(*linesw[tp->t_line].l_rint)(chr&0177, tp);
26337e911b15Skarels 			}
26347e911b15Skarels 		}
26357e911b15Skarels 	}
26367e911b15Skarels } /* qdiint */
26377e911b15Skarels 
26387881ece5Smarc /*
26397e911b15Skarels  *
26407881ece5Smarc  * Clear the QDSS screen
26417e911b15Skarels  *
26427e911b15Skarels  *			     >>> NOTE <<<
26437e911b15Skarels  *
26447e911b15Skarels  *   This code requires that certain adder initialization be valid.  To
26457e911b15Skarels  *   assure that this requirement is satisfied, this routine should be
26467e911b15Skarels  *   called only after calling the "setup_dragon()" function.
26477e911b15Skarels  *
26487e911b15Skarels  *   Clear the bitmap a piece at a time. Since the fast scroll clear
26497e911b15Skarels  *   only clears the current displayed portion of the bitmap put a
26507e911b15Skarels  *   temporary value in the y limit register so we can access whole
26517e911b15Skarels  *   bitmap
26527e911b15Skarels  *
26537881ece5Smarc  */
26547e911b15Skarels clear_qd_screen(unit)
26557e911b15Skarels 	int unit;
26567e911b15Skarels {
26577e911b15Skarels 	register struct adder *adder;
26587e911b15Skarels 	adder = (struct adder *) qdmap[unit].adder;
26597e911b15Skarels 
26607e911b15Skarels 	adder->x_limit = 1024;
26617e911b15Skarels 	adder->y_limit = 2048 - CHAR_HEIGHT;
26627e911b15Skarels 	adder->y_offset_pending = 0;
26637881ece5Smarc #define WSV  (void)wait_status(adder, VSYNC); (void)wait_status(adder, VSYNC)
2664b2b69f49Smarc 	WSV;
26657e911b15Skarels 	adder->y_scroll_constant = SCROLL_ERASE;
2666b2b69f49Smarc 	WSV;
26677e911b15Skarels 	adder->y_offset_pending = 864;
2668b2b69f49Smarc 	WSV;
26697e911b15Skarels 	adder->y_scroll_constant = SCROLL_ERASE;
2670b2b69f49Smarc 	WSV;
26717e911b15Skarels 	adder->y_offset_pending = 1728;
2672b2b69f49Smarc 	WSV;
26737e911b15Skarels 	adder->y_scroll_constant = SCROLL_ERASE;
2674b2b69f49Smarc 	WSV;
26757e911b15Skarels 	adder->y_offset_pending = 0;	 /* back to normal */
2676b2b69f49Smarc 	WSV;
26777e911b15Skarels 	adder->x_limit = MAX_SCREEN_X;
26787e911b15Skarels 	adder->y_limit = MAX_SCREEN_Y + FONT_HEIGHT;
2679b2b69f49Smarc #undef WSV
26807e911b15Skarels 
26817e911b15Skarels } /* clear_qd_screen */
26827e911b15Skarels 
26837881ece5Smarc /*
26847881ece5Smarc  *  kernel console output to the glass tty
26857881ece5Smarc  */
26867e911b15Skarels qdputc(chr)
26877e911b15Skarels 	register char chr;
26887e911b15Skarels {
26897e911b15Skarels 
2690b2b69f49Smarc 	/*
2691b2b69f49Smarc 	 * if system is now physical, forget it (ie: crash DUMP)
2692b2b69f49Smarc 	 */
26937e911b15Skarels 	if ((mfpr(MAPEN) & 1) == 0)
26947e911b15Skarels 		return;
26957e911b15Skarels 
26967881ece5Smarc 	blitc(0, (u_char)(chr & 0xff));
269724f67f6bSmarc 	if ((chr & 0177) == '\n')
269824f67f6bSmarc 		blitc(0, '\r');
269924f67f6bSmarc 
27007e911b15Skarels } /* qdputc */
27017e911b15Skarels 
2702b2b69f49Smarc /*
27037881ece5Smarc  *  load the mouse cursor's template RAM bitmap
27047881ece5Smarc  */
27057e911b15Skarels ldcursor(unit, bitmap)
27067881ece5Smarc 	int unit;
27077881ece5Smarc 	register short *bitmap;
27087e911b15Skarels {
27097e911b15Skarels 	register struct dga *dga;
27107e911b15Skarels 	register short *temp;
27117e911b15Skarels 	register int i;
27127881ece5Smarc 	int curs;
27137e911b15Skarels 
27147e911b15Skarels 	dga = (struct dga *) qdmap[unit].dga;
27157e911b15Skarels 	temp = (short *) qdmap[unit].template;
27167e911b15Skarels 
27177e911b15Skarels 	if (dga->csr & CURS_ENB) {	/* if the cursor is enabled.. */
27187881ece5Smarc 		curs = -1;		/* ..note that.. */
27197e911b15Skarels 		dga->csr &= ~CURS_ENB;	/* ..and shut it off */
27207881ece5Smarc 	} else
27217881ece5Smarc 		curs = 0;
27227e911b15Skarels 
27237e911b15Skarels 	dga->csr &= ~CURS_ENB;		/* shut off the cursor */
27247e911b15Skarels 
27257e911b15Skarels 	temp += (8 * 1024) - 32;	/* cursor is 32 WORDS from the end */
27267e911b15Skarels 	/* ..of the 8k WORD template space */
27277e911b15Skarels 	for (i = 0; i < 32; ++i)
27287e911b15Skarels 		*temp++ = *bitmap++;
27297e911b15Skarels 
27307881ece5Smarc 	if (curs) {			/* if cursor was enabled.. */
27317e911b15Skarels 		dga->csr |= CURS_ENB;	/* ..turn it back on */
27327e911b15Skarels 	}
27337e911b15Skarels 
27347e911b15Skarels } /* ldcursor */
27357e911b15Skarels 
27367881ece5Smarc /*
27377881ece5Smarc  *  Put the console font in the QDSS off-screen memory
27387881ece5Smarc  */
27397e911b15Skarels ldfont(unit)
27407881ece5Smarc 	int unit;
27417e911b15Skarels {
27427e911b15Skarels 	register struct adder *adder;
27437e911b15Skarels 
27447881ece5Smarc 	register i, j, k, max_chars_line;
27457881ece5Smarc 	register short packed;
27467e911b15Skarels 
27477e911b15Skarels 	adder = (struct adder *) qdmap[unit].adder;
27487e911b15Skarels 
2749b2b69f49Smarc 	/*
27507881ece5Smarc 	* setup VIPER operand control registers
27517881ece5Smarc 	*/
27527e911b15Skarels 	write_ID(adder, MASK_1, 0xFFFF);
27537e911b15Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
27547e911b15Skarels 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
27557e911b15Skarels 
27567e911b15Skarels 	write_ID(adder, SRC1_OCR_B,
27577e911b15Skarels 	EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY);
27587e911b15Skarels 	write_ID(adder, SRC2_OCR_B,
27597e911b15Skarels 	EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY);
27607e911b15Skarels 	write_ID(adder, DST_OCR_B,
27617e911b15Skarels 	EXT_SOURCE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
27627e911b15Skarels 
27637e911b15Skarels 	adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL;
27647e911b15Skarels 
2765b2b69f49Smarc 	/*
27667881ece5Smarc 	* load destination data
27677881ece5Smarc 	*/
27687881ece5Smarc 	(void)wait_status(adder, RASTEROP_COMPLETE);
27697e911b15Skarels 
27707e911b15Skarels 	adder->destination_x = FONT_X;
27717e911b15Skarels 	adder->destination_y = FONT_Y;
27727881ece5Smarc #if FONT_WIDTH > MAX_SCREEN_X
2773e977faadSmarc 	adder->fast_dest_dx = MAX_SCREEN_X;
27747881ece5Smarc #else
27757e911b15Skarels 	adder->fast_dest_dx = FONT_WIDTH;
27767881ece5Smarc #endif
27777e911b15Skarels 	adder->slow_dest_dy = CHAR_HEIGHT;
27787e911b15Skarels 
2779b2b69f49Smarc 	/*
27807e911b15Skarels 	* setup for processor to bitmap xfer  */
27817e911b15Skarels 
27827e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0001);
27837e911b15Skarels 	adder->cmd = PBT | OCRB | 2 | DTE | 2;
27847e911b15Skarels 
2785b2b69f49Smarc 	/*
2786b2b69f49Smarc 	* Figure out how many characters can be stored on one "line" of
2787b2b69f49Smarc 	* offscreen memory.
2788e977faadSmarc 	*/
2789e977faadSmarc 	max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
2790e977faadSmarc 	if ((CHARS/2 + CHARS%2) < max_chars_line)
2791e977faadSmarc 	    max_chars_line = CHARS/2 + CHARS%2;
2792e977faadSmarc 
2793b2b69f49Smarc 	/*
2794e977faadSmarc 	* iteratively do the processor to bitmap xfer */
2795e977faadSmarc 
2796e977faadSmarc 	for (i = 0; i < ROWS; ++i) {
2797e977faadSmarc 
2798e977faadSmarc 		/* PTOB a scan line */
2799e977faadSmarc 
2800e977faadSmarc 		for (j = 0, k = i; j < max_chars_line; ++j) {
2801e977faadSmarc 			/* PTOB one scan of a char cell */
2802e977faadSmarc 
2803e977faadSmarc 			packed = q_font[k];
2804e977faadSmarc 			k += ROWS;
2805e977faadSmarc 			packed |= ((short)q_font[k] << 8);
2806e977faadSmarc 			k += ROWS;
2807e977faadSmarc 
28087881ece5Smarc 			(void)wait_status(adder, TX_READY);
2809e977faadSmarc 			adder->id_data = packed;
2810e977faadSmarc 		}
2811e977faadSmarc 	}
2812e977faadSmarc 
2813b2b69f49Smarc 	/*
2814b2b69f49Smarc 	 * (XXX XXX XXX - should remove)
2815b2b69f49Smarc 	 *
2816b2b69f49Smarc 	 * Copy the second row of characters.  Subtract the first
2817b2b69f49Smarc 	 * row from the total number.  Divide this quantity by 2
2818b2b69f49Smarc 	 * because 2 chars are stored in a short in the PTOB loop
2819b2b69f49Smarc 	 * below.  Figure out how many characters can be stored on
2820b2b69f49Smarc 	 * one "line" of offscreen memory
2821e977faadSmarc 	 */
2822b2b69f49Smarc 
2823e977faadSmarc 	max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
2824e977faadSmarc 	if ((CHARS/2 + CHARS%2) < max_chars_line)
2825e977faadSmarc 	    return;
2826e977faadSmarc 	max_chars_line = (CHARS/2 + CHARS%2) - max_chars_line; /* 95 - 64 */
2827e977faadSmarc 	/* Paranoia check to see if 3rd row may be needed */
2828e977faadSmarc 	if (max_chars_line > (MAX_SCREEN_X/(CHAR_WIDTH*2)))
2829e977faadSmarc 	    max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
2830e977faadSmarc 
2831e977faadSmarc 	adder->destination_x = FONT_X;
2832e977faadSmarc 	adder->destination_y = FONT_Y - CHAR_HEIGHT;
2833e977faadSmarc 	adder->fast_dest_dx = max_chars_line * CHAR_WIDTH * 2;
2834e977faadSmarc 	adder->slow_dest_dy = CHAR_HEIGHT;
2835e977faadSmarc 
2836b2b69f49Smarc 	/*
2837b2b69f49Smarc 	* setup for processor to bitmap xfer
2838b2b69f49Smarc 	*/
2839e977faadSmarc 	write_ID(adder, CS_UPDATE_MASK, 0x0001);
2840e977faadSmarc 	adder->cmd = PBT | OCRB | 2 | DTE | 2;
2841e977faadSmarc 
2842b2b69f49Smarc 	/*
2843b2b69f49Smarc 	* iteratively do the processor to bitmap xfer
2844b2b69f49Smarc 	*/
28457e911b15Skarels 	for (i = 0; i < ROWS; ++i) {
2846b2b69f49Smarc 		/*
2847b2b69f49Smarc 		 * PTOB a scan line
2848b2b69f49Smarc 		 */
2849e977faadSmarc 		for (j = 0, k = i; j < max_chars_line; ++j) {
2850b2b69f49Smarc 			/*
2851b2b69f49Smarc 			 * PTOB one scan of a char cell
2852b2b69f49Smarc 			 */
2853e977faadSmarc 			packed = q_font[k + FONT_OFFSET];
28547e911b15Skarels 			k += ROWS;
2855e977faadSmarc 			packed |= ((short)q_font[k + FONT_OFFSET] << 8);
28567e911b15Skarels 			k += ROWS;
28577881ece5Smarc 			(void)wait_status(adder, TX_READY);
28587e911b15Skarels 			adder->id_data = packed;
28597e911b15Skarels 		}
28607e911b15Skarels 	}
28617e911b15Skarels 
28627e911b15Skarels }  /* ldfont */
28637e911b15Skarels 
2864*f79d7b48Smarc qdpoll(onoff)
2865*f79d7b48Smarc {
2866*f79d7b48Smarc 	qdpolling = onoff;
2867*f79d7b48Smarc }
2868*f79d7b48Smarc 
28697881ece5Smarc /*
28707881ece5Smarc  *  Get a character from the LK201 (polled)
28717881ece5Smarc  */
28727881ece5Smarc qdgetc()
28737e911b15Skarels {
28747881ece5Smarc 	register short key;
28757881ece5Smarc 	register char chr;
28767881ece5Smarc 	register struct duart *duart;
28777881ece5Smarc 
28787881ece5Smarc 	duart = (struct duart *) qdmap[0].duart;
28797881ece5Smarc 
28807881ece5Smarc 	/*
28817881ece5Smarc 	* Get a character from the keyboard.
28827881ece5Smarc 	*/
28837881ece5Smarc LOOP:
28847881ece5Smarc 	while (!(duart->statusA&RCV_RDY))
28857881ece5Smarc 		;
28867881ece5Smarc 
28877881ece5Smarc 	key = duart->dataA;
28887881ece5Smarc 	key &= 0xFF;
28897881ece5Smarc 
28907881ece5Smarc 	/*
28917881ece5Smarc 	* Check for various keyboard errors  */
28927881ece5Smarc 
28937881ece5Smarc 	if (key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
28947881ece5Smarc 	    key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
28957881ece5Smarc 		printf("Keyboard error, code = %x\n", key);
28967881ece5Smarc 		return(0);
28977881ece5Smarc 	}
28987881ece5Smarc 
28997881ece5Smarc 	if (key < LK_LOWEST)
29007881ece5Smarc 		return(0);
29017881ece5Smarc 
29027881ece5Smarc 	/*
29037881ece5Smarc 	 * See if its a state change key
29047881ece5Smarc 	 */
29057881ece5Smarc 	switch (key) {
29067881ece5Smarc 
29077881ece5Smarc 	case LOCK:
29087881ece5Smarc 		q_keyboard.lock ^= 0xffff;	/* toggle */
29097881ece5Smarc 		if (q_keyboard.lock)
29107881ece5Smarc 			(void)led_control(0, LK_LED_ENABLE, LK_LED_LOCK);
29117881ece5Smarc 		else
29127881ece5Smarc 			(void)led_control(0, LK_LED_DISABLE, LK_LED_LOCK);
29137881ece5Smarc 		goto LOOP;
29147881ece5Smarc 
29157881ece5Smarc 	case SHIFT:
29167881ece5Smarc 		q_keyboard.shift ^= 0xFFFF;
29177881ece5Smarc 		goto LOOP;
29187881ece5Smarc 
29197881ece5Smarc 	case CNTRL:
29207881ece5Smarc 		q_keyboard.cntrl ^= 0xFFFF;
29217881ece5Smarc 		goto LOOP;
29227881ece5Smarc 
29237881ece5Smarc 	case ALLUP:
29247881ece5Smarc 		q_keyboard.cntrl = 0;
29257881ece5Smarc 		q_keyboard.shift = 0;
29267881ece5Smarc 		goto LOOP;
29277881ece5Smarc 
29287881ece5Smarc 	case REPEAT:
29297881ece5Smarc 		chr = q_keyboard.last;
29307881ece5Smarc 		break;
29317881ece5Smarc 
29327881ece5Smarc 		/*
29337881ece5Smarc 		* Test for cntrl characters. If set, see if the character
29347881ece5Smarc 		* is elligible to become a control character.
29357881ece5Smarc 		*/
29367881ece5Smarc 	default:
29377881ece5Smarc 
29387881ece5Smarc 		if (q_keyboard.cntrl) {
29397881ece5Smarc 			chr = q_key[key];
29407881ece5Smarc 			if (chr >= ' ' && chr <= '~')
29417881ece5Smarc 			    chr &= 0x1F;
29427881ece5Smarc 		}
29437881ece5Smarc 		else if ( q_keyboard.lock || q_keyboard.shift )
29447881ece5Smarc 		    chr = q_shift_key[key];
29457881ece5Smarc 		else
29467881ece5Smarc 			chr = q_key[key];
29477881ece5Smarc 		break;
29487881ece5Smarc 	}
29497881ece5Smarc 
29507881ece5Smarc 	if (chr < ' ' && chr > '~')	/* if input is non-displayable */
29517881ece5Smarc 		return(0);		/* ..then pitch it! */
29527881ece5Smarc 
29537881ece5Smarc 	q_keyboard.last = chr;
29547881ece5Smarc 
29557881ece5Smarc 	/*
29567881ece5Smarc 	* Check for special function keys */
29577881ece5Smarc 
29587881ece5Smarc 	if (chr & 0x80) 		/* pitch the function keys */
29597881ece5Smarc 		return(0);
29607881ece5Smarc 	else
29617881ece5Smarc 		return(chr);
29627881ece5Smarc 
29637881ece5Smarc } /* qdgetc */
29647881ece5Smarc 
29657881ece5Smarc /*
29667881ece5Smarc  *  led_control()... twiddle LK-201 LED's
29677881ece5Smarc  */
29687881ece5Smarc led_control(unit, cmd, led_mask)
29697881ece5Smarc 	int unit, cmd, led_mask;
29707881ece5Smarc {
29717881ece5Smarc 	register i;
29727e911b15Skarels 	register struct duart *duart;
29737e911b15Skarels 
29747e911b15Skarels 	duart = (struct duart *)qdmap[unit].duart;
29757e911b15Skarels 
29767e911b15Skarels 	for (i = 1000; i > 0; --i) {
29777881ece5Smarc 		if (duart->statusA&XMT_RDY) {
29787e911b15Skarels 			duart->dataA = cmd;
29797e911b15Skarels 			break;
29807e911b15Skarels 		}
29817e911b15Skarels 	}
29827e911b15Skarels 	for (i = 1000; i > 0; --i) {
29837881ece5Smarc 		if (duart->statusA&XMT_RDY) {
29847e911b15Skarels 			duart->dataA = led_mask;
29857e911b15Skarels 			break;
29867e911b15Skarels 		}
29877e911b15Skarels 	}
29887e911b15Skarels 	if (i == 0)
29897e911b15Skarels 		return(BAD);
29907e911b15Skarels 	return(GOOD);
29917e911b15Skarels 
29927e911b15Skarels } /* led_control */
29937e911b15Skarels 
29947881ece5Smarc /*
29957e911b15Skarels  *  scroll_up()... move the screen up one character height
29967881ece5Smarc  */
29977e911b15Skarels scroll_up(adder)
29987e911b15Skarels 	register struct adder *adder;
29997e911b15Skarels {
3000b2b69f49Smarc 	/*
3001b2b69f49Smarc 	* setup VIPER operand control registers
3002b2b69f49Smarc 	*/
30037881ece5Smarc 	(void)wait_status(adder, ADDRESS_COMPLETE);
30047e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x00FF);  /* select all planes */
30057e911b15Skarels 	write_ID(adder, MASK_1, 0xFFFF);
30067e911b15Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
30077e911b15Skarels 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
30087e911b15Skarels 	write_ID(adder, SRC1_OCR_B,
30097e911b15Skarels 	EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY);
30107e911b15Skarels 	write_ID(adder, DST_OCR_B,
30117e911b15Skarels 	EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
3012b2b69f49Smarc 	/*
3013b2b69f49Smarc 	 * load DESTINATION origin and vectors
3014b2b69f49Smarc 	 */
30157e911b15Skarels 	adder->fast_dest_dy = 0;
30167e911b15Skarels 	adder->slow_dest_dx = 0;
30177e911b15Skarels 	adder->error_1 = 0;
30187e911b15Skarels 	adder->error_2 = 0;
30197e911b15Skarels 	adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL;
30207e911b15Skarels 	adder->destination_x = 0;
30217e911b15Skarels 	adder->fast_dest_dx = 1024;
30227e911b15Skarels 	adder->destination_y = 0;
30237e911b15Skarels 	adder->slow_dest_dy = 864 - CHAR_HEIGHT;
3024b2b69f49Smarc 	/*
3025b2b69f49Smarc 	 * load SOURCE origin and vectors
3026b2b69f49Smarc 	 */
30277e911b15Skarels 	adder->source_1_x = 0;
30287e911b15Skarels 	adder->source_1_dx = 1024;
30297e911b15Skarels 	adder->source_1_y = 0 + CHAR_HEIGHT;
30307e911b15Skarels 	adder->source_1_dy = 864 - CHAR_HEIGHT;
30317e911b15Skarels 	write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
30327e911b15Skarels 	adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE;
3033b2b69f49Smarc 	/*
3034b2b69f49Smarc 	 * do a rectangle clear of last screen line
3035b2b69f49Smarc 	 */
30367e911b15Skarels 	write_ID(adder, MASK_1, 0xffff);
30377e911b15Skarels 	write_ID(adder, SOURCE, 0xffff);
30387e911b15Skarels 	write_ID(adder,DST_OCR_B,
30397e911b15Skarels 	(EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY));
30407e911b15Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 0);
30417e911b15Skarels 	adder->error_1 = 0;
30427e911b15Skarels 	adder->error_2 = 0;
30437e911b15Skarels 	adder->slow_dest_dx = 0;		/* set up the width of	*/
30447e911b15Skarels 	adder->slow_dest_dy = CHAR_HEIGHT;	/* rectangle */
30457e911b15Skarels 	adder->rasterop_mode = (NORMAL | DST_WRITE_ENABLE) ;
30467881ece5Smarc 	(void)wait_status(adder, RASTEROP_COMPLETE);
30477e911b15Skarels 	adder->destination_x = 0;
30487e911b15Skarels 	adder->destination_y = 864 - CHAR_HEIGHT;
30497e911b15Skarels 	adder->fast_dest_dx = 1024;	/* set up the height	*/
30507e911b15Skarels 	adder->fast_dest_dy = 0;	/* of rectangle 	*/
30517e911b15Skarels 	write_ID(adder, LU_FUNCTION_R2, (FULL_SRC_RESOLUTION | LF_SOURCE));
30527e911b15Skarels 	adder->cmd = (RASTEROP | OCRB | LF_R2 | DTE ) ;
30537e911b15Skarels 
30547e911b15Skarels } /* scroll_up */
30557e911b15Skarels 
30567881ece5Smarc /*
30577881ece5Smarc  *  init shared memory pointers and structures
30587881ece5Smarc  */
30597e911b15Skarels init_shared(unit)
30607881ece5Smarc 	register unit;
30617e911b15Skarels {
30627e911b15Skarels 	register struct dga *dga;
30637e911b15Skarels 
30647e911b15Skarels 	dga = (struct dga *) qdmap[unit].dga;
30657e911b15Skarels 
3066b2b69f49Smarc 	/*
30677e911b15Skarels 	* initialize the event queue pointers and header */
30687e911b15Skarels 
30697e911b15Skarels 	eq_header[unit] = (struct qdinput *)
30707e911b15Skarels 	    ((((int)event_shared & ~(0x01FF)) + 512)
30717e911b15Skarels 		+ (EVENT_BUFSIZE * unit));
30727e911b15Skarels 	eq_header[unit]->curs_pos.x = 0;
30737e911b15Skarels 	eq_header[unit]->curs_pos.y = 0;
30747e911b15Skarels 	dga->x_cursor = TRANX(eq_header[unit]->curs_pos.x);
30757e911b15Skarels 	dga->y_cursor = TRANY(eq_header[unit]->curs_pos.y);
30767e911b15Skarels 	eq_header[unit]->curs_box.left = 0;
30777e911b15Skarels 	eq_header[unit]->curs_box.right = 0;
30787e911b15Skarels 	eq_header[unit]->curs_box.top = 0;
30797e911b15Skarels 	eq_header[unit]->curs_box.bottom = 0;
3080b2b69f49Smarc 	/*
3081b2b69f49Smarc 	 * assign a pointer to the DMA I/O buffer for this QDSS.
3082b2b69f49Smarc 	 */
30837e911b15Skarels 	DMAheader[unit] = (struct DMAreq_header *)
30847e911b15Skarels 	    (((int)(&DMA_shared[0] + 512) & ~0x1FF)
30857e911b15Skarels 		+ (DMAbuf_size * unit));
30867e911b15Skarels 	DMAheader[unit]->DMAreq = (struct DMAreq *) ((int)DMAheader[unit]
30877e911b15Skarels 	    + sizeof(struct DMAreq_header));
30887e911b15Skarels 	DMAheader[unit]->QBAreg = 0;
30897e911b15Skarels 	DMAheader[unit]->status = 0;
30907e911b15Skarels 	DMAheader[unit]->shared_size = DMAbuf_size;
30917e911b15Skarels 	DMAheader[unit]->used = 0;
30927e911b15Skarels 	DMAheader[unit]->size = 10;	/* default = 10 requests */
30937e911b15Skarels 	DMAheader[unit]->oldest = 0;
30947e911b15Skarels 	DMAheader[unit]->newest = 0;
3095b2b69f49Smarc 	/*
3096b2b69f49Smarc 	* assign a pointer to the scroll structure for this QDSS.
3097b2b69f49Smarc 	*/
30987e911b15Skarels 	scroll[unit] = (struct scroll *)
30997e911b15Skarels 	    (((int)(&scroll_shared[0] + 512) & ~0x1FF)
31007e911b15Skarels 		+ (sizeof(struct scroll) * unit));
31017e911b15Skarels 	scroll[unit]->status = 0;
31027e911b15Skarels 	scroll[unit]->viper_constant = 0;
31037e911b15Skarels 	scroll[unit]->y_scroll_constant = 0;
31047e911b15Skarels 	scroll[unit]->y_offset = 0;
31057e911b15Skarels 	scroll[unit]->x_index_pending = 0;
31067e911b15Skarels 	scroll[unit]->y_index_pending = 0;
3107b2b69f49Smarc 	/*
3108b2b69f49Smarc 	* assign a pointer to the color map write buffer for this QDSS
3109b2b69f49Smarc 	*/
31107e911b15Skarels 	color_buf[unit] = (struct color_buf *)
31117e911b15Skarels 	    (((int)(&color_shared[0] + 512) & ~0x1FF)
31127e911b15Skarels 		+ (COLOR_BUFSIZ * unit));
31137e911b15Skarels 	color_buf[unit]->status = 0;
31147e911b15Skarels 	color_buf[unit]->count = 0;
31157e911b15Skarels 
31167e911b15Skarels } /* init_shared */
31177e911b15Skarels 
31187881ece5Smarc /*
31197881ece5Smarc  * init the ADDER, VIPER, bitmaps, & color map
31207881ece5Smarc  */
31217e911b15Skarels setup_dragon(unit)
31227881ece5Smarc 	int unit;
31237e911b15Skarels {
31247e911b15Skarels 
31257e911b15Skarels 	register struct adder *adder;
31267e911b15Skarels 	register struct dga *dga;
31277e911b15Skarels 	short *memcsr;
31287881ece5Smarc 	register i;
31297e911b15Skarels 	short top;		/* clipping/scrolling boundaries */
31307e911b15Skarels 	short bottom;
31317e911b15Skarels 	short right;
31327e911b15Skarels 	short left;
31337e911b15Skarels 	short *red;		/* color map pointers */
31347e911b15Skarels 	short *green;
31357e911b15Skarels 	short *blue;
31367e911b15Skarels 
3137b2b69f49Smarc 	/*
3138b2b69f49Smarc 	* init for setup
3139b2b69f49Smarc 	*/
31407e911b15Skarels 	adder = (struct adder *) qdmap[unit].adder;
31417e911b15Skarels 	dga = (struct dga *) qdmap[unit].dga;
31427e911b15Skarels 	memcsr = (short *) qdmap[unit].memcsr;
31437e911b15Skarels 	dga->csr &= ~(DMA_IE | 0x700);	/* halt DMA and kill the intrpts */
31447e911b15Skarels 	*memcsr = SYNC_ON;		/* blank screen and turn off LED's */
31457e911b15Skarels 	adder->command = CANCEL;
3146b2b69f49Smarc 	/*
3147b2b69f49Smarc 	* set monitor timing
3148b2b69f49Smarc 	*/
31497e911b15Skarels 	adder->x_scan_count_0 = 0x2800;
31507e911b15Skarels 	adder->x_scan_count_1 = 0x1020;
31517e911b15Skarels 	adder->x_scan_count_2 = 0x003A;
31527e911b15Skarels 	adder->x_scan_count_3 = 0x38F0;
31537e911b15Skarels 	adder->x_scan_count_4 = 0x6128;
31547e911b15Skarels 	adder->x_scan_count_5 = 0x093A;
31557e911b15Skarels 	adder->x_scan_count_6 = 0x313C;
31567e911b15Skarels 	adder->sync_phase_adj = 0x0100;
31577e911b15Skarels 	adder->x_scan_conf = 0x00C8;
3158b2b69f49Smarc 	/*
3159b2b69f49Smarc 	 * got a bug in secound pass ADDER! lets take care of it
3160b2b69f49Smarc 	 *
3161b2b69f49Smarc 	 * normally, just use the code in the following bug fix code, but to
31627e911b15Skarels 	 * make repeated demos look pretty, load the registers as if there was
3163b2b69f49Smarc 	 * no bug and then test to see if we are getting sync
3164b2b69f49Smarc 	 */
31657e911b15Skarels 	adder->y_scan_count_0 = 0x135F;
31667e911b15Skarels 	adder->y_scan_count_1 = 0x3363;
31677e911b15Skarels 	adder->y_scan_count_2 = 0x2366;
31687e911b15Skarels 	adder->y_scan_count_3 = 0x0388;
3169b2b69f49Smarc 	/*
3170b2b69f49Smarc 	 * if no sync, do the bug fix code
3171b2b69f49Smarc 	 */
31727e911b15Skarels 	if (wait_status(adder, VSYNC) == BAD) {
31737e911b15Skarels 		/* first load all Y scan registers with very short frame and
31747e911b15Skarels 		 * wait for scroll service.  This guarantees at least one SYNC
31757e911b15Skarels 		 * to fix the pass 2 Adder initialization bug (synchronizes
3176b2b69f49Smarc 		 * XCINCH with DMSEEDH)
3177b2b69f49Smarc 		 */
31787e911b15Skarels 		adder->y_scan_count_0 = 0x01;
31797e911b15Skarels 		adder->y_scan_count_1 = 0x01;
31807e911b15Skarels 		adder->y_scan_count_2 = 0x01;
31817e911b15Skarels 		adder->y_scan_count_3 = 0x01;
3182b2b69f49Smarc 		/*
3183b2b69f49Smarc 		 * delay at least 1 full frame time
3184b2b69f49Smarc 		 */
31857881ece5Smarc 		(void)wait_status(adder, VSYNC);
31867881ece5Smarc 		(void)wait_status(adder, VSYNC);
3187b2b69f49Smarc 		/*
3188b2b69f49Smarc 		 * now load the REAL sync values (in reverse order just to
3189b2b69f49Smarc 		 * be safe.
3190b2b69f49Smarc 		 */
31917e911b15Skarels 		adder->y_scan_count_3 = 0x0388;
31927e911b15Skarels 		adder->y_scan_count_2 = 0x2366;
31937e911b15Skarels 		adder->y_scan_count_1 = 0x3363;
31947e911b15Skarels 		adder->y_scan_count_0 = 0x135F;
31957e911b15Skarels 	}
31967e911b15Skarels 	*memcsr = SYNC_ON | UNBLANK;	/* turn off leds and turn on video */
3197b2b69f49Smarc 	/*
3198b2b69f49Smarc 	 * zero the index registers
3199b2b69f49Smarc 	 */
32007e911b15Skarels 	adder->x_index_pending = 0;
32017e911b15Skarels 	adder->y_index_pending = 0;
32027e911b15Skarels 	adder->x_index_new = 0;
32037e911b15Skarels 	adder->y_index_new = 0;
32047e911b15Skarels 	adder->x_index_old = 0;
32057e911b15Skarels 	adder->y_index_old = 0;
32067e911b15Skarels 	adder->pause = 0;
3207b2b69f49Smarc 	/*
3208b2b69f49Smarc 	 * set rasterop mode to normal pen down
3209b2b69f49Smarc 	 */
32107e911b15Skarels 	adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL;
3211b2b69f49Smarc 	/*
3212b2b69f49Smarc 	 * set the rasterop registers to a default values
3213b2b69f49Smarc 	 */
32147e911b15Skarels 	adder->source_1_dx = 1;
32157e911b15Skarels 	adder->source_1_dy = 1;
32167e911b15Skarels 	adder->source_1_x = 0;
32177e911b15Skarels 	adder->source_1_y = 0;
32187e911b15Skarels 	adder->destination_x = 0;
32197e911b15Skarels 	adder->destination_y = 0;
32207e911b15Skarels 	adder->fast_dest_dx = 1;
32217e911b15Skarels 	adder->fast_dest_dy = 0;
32227e911b15Skarels 	adder->slow_dest_dx = 0;
32237e911b15Skarels 	adder->slow_dest_dy = 1;
32247e911b15Skarels 	adder->error_1 = 0;
32257e911b15Skarels 	adder->error_2 = 0;
3226b2b69f49Smarc 	/*
32277881ece5Smarc 	 * scale factor = UNITY
3228b2b69f49Smarc 	 */
32297e911b15Skarels 	adder->fast_scale = UNITY;
32307e911b15Skarels 	adder->slow_scale = UNITY;
3231b2b69f49Smarc 	/*
3232b2b69f49Smarc 	 * set the source 2 parameters
3233b2b69f49Smarc 	 */
32347e911b15Skarels 	adder->source_2_x = 0;
32357e911b15Skarels 	adder->source_2_y = 0;
32367e911b15Skarels 	adder->source_2_size = 0x0022;
3237b2b69f49Smarc 	/*
3238b2b69f49Smarc 	* initialize plane addresses for eight vipers
3239b2b69f49Smarc 	*/
32407e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0001);
32417e911b15Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0000);
32427e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0002);
32437e911b15Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0001);
32447e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0004);
32457e911b15Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0002);
32467e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0008);
32477e911b15Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0003);
32487e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0010);
32497e911b15Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0004);
32507e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0020);
32517e911b15Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0005);
32527e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0040);
32537e911b15Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0006);
32547e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0080);
32557e911b15Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0007);
3256b2b69f49Smarc 	/*
3257b2b69f49Smarc 	 * initialize the external registers.
3258b2b69f49Smarc 	 */
32597e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x00FF);
32607e911b15Skarels 	write_ID(adder, CS_SCROLL_MASK, 0x00FF);
3261b2b69f49Smarc 	/*
3262b2b69f49Smarc 	 * initialize resolution mode
3263b2b69f49Smarc 	 */
32647e911b15Skarels 	write_ID(adder, MEMORY_BUS_WIDTH, 0x000C);     /* bus width = 16 */
32657e911b15Skarels 	write_ID(adder, RESOLUTION_MODE, 0x0000);      /* one bit/pixel */
3266b2b69f49Smarc 	/*
3267b2b69f49Smarc 	 * initialize viper registers
3268b2b69f49Smarc 	 */
32697e911b15Skarels 	write_ID(adder, SCROLL_CONSTANT, SCROLL_ENABLE|VIPER_LEFT|VIPER_UP);
32707e911b15Skarels 	write_ID(adder, SCROLL_FILL, 0x0000);
3271b2b69f49Smarc 	/*
3272b2b69f49Smarc 	 * set clipping and scrolling limits to full screen
3273b2b69f49Smarc 	 */
3274b2b69f49Smarc 	for (i = 1000, adder->status = 0;
32757881ece5Smarc 	     i > 0 && !(adder->status&ADDRESS_COMPLETE); --i)
3276b2b69f49Smarc 		;
32777e911b15Skarels 	if (i == 0)
32787881ece5Smarc 	    printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n",unit);
32797e911b15Skarels 	top = 0;
32807e911b15Skarels 	bottom = 2048;
32817e911b15Skarels 	left = 0;
32827e911b15Skarels 	right = 1024;
32837e911b15Skarels 	adder->x_clip_min = left;
32847e911b15Skarels 	adder->x_clip_max = right;
32857e911b15Skarels 	adder->y_clip_min = top;
32867e911b15Skarels 	adder->y_clip_max = bottom;
32877e911b15Skarels 	adder->scroll_x_min = left;
32887e911b15Skarels 	adder->scroll_x_max = right;
32897e911b15Skarels 	adder->scroll_y_min = top;
32907e911b15Skarels 	adder->scroll_y_max = bottom;
32917881ece5Smarc 	(void)wait_status(adder, VSYNC);	/* wait at LEAST 1 full frame */
32927881ece5Smarc 	(void)wait_status(adder, VSYNC);
32937e911b15Skarels 	adder->x_index_pending = left;
32947e911b15Skarels 	adder->y_index_pending = top;
32957e911b15Skarels 	adder->x_index_new = left;
32967e911b15Skarels 	adder->y_index_new = top;
32977e911b15Skarels 	adder->x_index_old = left;
32987e911b15Skarels 	adder->y_index_old = top;
32997e911b15Skarels 
33007881ece5Smarc 	for (i = 1000, adder->status = 0; i > 0 &&
33017881ece5Smarc 	     !(adder->status&ADDRESS_COMPLETE) ; --i)
3302b2b69f49Smarc 		;
33037e911b15Skarels 	if (i == 0)
33047881ece5Smarc 	       printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n",unit);
33057e911b15Skarels 
33067e911b15Skarels 	write_ID(adder, LEFT_SCROLL_MASK, 0x0000);
33077e911b15Skarels 	write_ID(adder, RIGHT_SCROLL_MASK, 0x0000);
3308b2b69f49Smarc 	/*
3309b2b69f49Smarc 	* set source and the mask register to all ones (ie: white) o
3310b2b69f49Smarc 	*/
33117e911b15Skarels 	write_ID(adder, SOURCE, 0xFFFF);
33127e911b15Skarels 	write_ID(adder, MASK_1, 0xFFFF);
33137e911b15Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
33147e911b15Skarels 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
3315b2b69f49Smarc 	/*
3316b2b69f49Smarc 	* initialize Operand Control Register banks for fill command
3317b2b69f49Smarc 	*/
33187e911b15Skarels 	write_ID(adder, SRC1_OCR_A, EXT_NONE | INT_M1_M2  | NO_ID | WAIT);
33197e911b15Skarels 	write_ID(adder, SRC2_OCR_A, EXT_NONE | INT_SOURCE | NO_ID | NO_WAIT);
33207e911b15Skarels 	write_ID(adder, DST_OCR_A, EXT_NONE | INT_NONE	 | NO_ID | NO_WAIT);
33217e911b15Skarels 	write_ID(adder, SRC1_OCR_B, EXT_NONE | INT_SOURCE | NO_ID | WAIT);
33227e911b15Skarels 	write_ID(adder, SRC2_OCR_B, EXT_NONE | INT_M1_M2  | NO_ID | NO_WAIT);
33237e911b15Skarels 	write_ID(adder, DST_OCR_B, EXT_NONE | INT_NONE | NO_ID | NO_WAIT);
3324b2b69f49Smarc 	/*
33257e911b15Skarels 	* init Logic Unit Function registers, (these are just common values,
3326b2b69f49Smarc 	* and may be changed as required).
3327b2b69f49Smarc 	*/
33287e911b15Skarels 	write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
3329b2b69f49Smarc 	write_ID(adder, LU_FUNCTION_R2, FULL_SRC_RESOLUTION | LF_SOURCE |
3330b2b69f49Smarc 		 INV_M1_M2);
33317e911b15Skarels 	write_ID(adder, LU_FUNCTION_R3, FULL_SRC_RESOLUTION | LF_D_OR_S);
33327e911b15Skarels 	write_ID(adder, LU_FUNCTION_R4, FULL_SRC_RESOLUTION | LF_D_XOR_S);
3333b2b69f49Smarc 	/*
3334b2b69f49Smarc 	* load the color map for black & white
3335b2b69f49Smarc 	*/
33367881ece5Smarc 	for (i = 0, adder->status = 0; i < 10000 && !(adder->status&VSYNC); ++i)
3337b2b69f49Smarc 		;
33387e911b15Skarels 
33397e911b15Skarels 	if (i == 0)
33407881ece5Smarc 		printf("qd%d: setup_dragon: timeout on VSYNC\n", unit);
33417e911b15Skarels 
33427e911b15Skarels 	red = (short *) qdmap[unit].red;
33437e911b15Skarels 	green = (short *) qdmap[unit].green;
33447e911b15Skarels 	blue = (short *) qdmap[unit].blue;
33457e911b15Skarels 
33467e911b15Skarels 	*red++ = 0x00;			/* black */
33477e911b15Skarels 	*green++ = 0x00;
33487e911b15Skarels 	*blue++ = 0x00;
33497e911b15Skarels 
33507e911b15Skarels 	*red-- = 0xFF;			/* white */
33517e911b15Skarels 	*green-- = 0xFF;
33527e911b15Skarels 	*blue-- = 0xFF;
33537e911b15Skarels 
3354b2b69f49Smarc 	/*
33557881ece5Smarc 	* set color map for mouse cursor
33567881ece5Smarc 	*/
33577e911b15Skarels 
33587e911b15Skarels 	red += 254;
33597e911b15Skarels 	green += 254;
33607e911b15Skarels 	blue += 254;
33617e911b15Skarels 
33627e911b15Skarels 	*red++ = 0x00;			/* black */
33637e911b15Skarels 	*green++ = 0x00;
33647e911b15Skarels 	*blue++ = 0x00;
33657e911b15Skarels 
33667e911b15Skarels 	*red = 0xFF;			/* white */
33677e911b15Skarels 	*green = 0xFF;
33687e911b15Skarels 	*blue = 0xFF;
33697e911b15Skarels 
33707e911b15Skarels } /* setup_dragon */
33717e911b15Skarels 
33727881ece5Smarc /*
33737881ece5Smarc  * Init the DUART and set defaults in input
33747881ece5Smarc  */
33757e911b15Skarels setup_input(unit)
33767881ece5Smarc 	int unit;
33777e911b15Skarels {
33787e911b15Skarels 	register struct duart *duart;	/* DUART register structure pointer */
33797881ece5Smarc 	register i, bits;
33807e911b15Skarels 	char id_byte;
33817e911b15Skarels 
33827e911b15Skarels 	duart = (struct duart *) qdmap[unit].duart;
33837e911b15Skarels 	duart->imask = 0;
33847e911b15Skarels 
3385b2b69f49Smarc 	/*
3386b2b69f49Smarc 	* setup the DUART for kbd & pointing device
3387b2b69f49Smarc 	*/
33887e911b15Skarels 	duart->cmdA = RESET_M;	/* reset mode reg ptr for kbd */
33897e911b15Skarels 	duart->modeA = 0x13;	/* 8 bits, no parity, rcv IE, */
33907e911b15Skarels 				/* no RTS control,char error mode */
33917e911b15Skarels 	duart->modeA = 0x07;	/* 1 stop bit,CTS does not IE XMT */
33927e911b15Skarels 				/* no RTS control,no echo or loop */
33937e911b15Skarels 	duart->cmdB = RESET_M;	/* reset mode reg pntr for host */
33947e911b15Skarels 	duart->modeB = 0x07;	/* 8 bits, odd parity, rcv IE.. */
33957e911b15Skarels 				/* ..no RTS cntrl, char error mode */
33967e911b15Skarels 	duart->modeB = 0x07;	/* 1 stop bit,CTS does not IE XMT */
33977e911b15Skarels 				/* no RTS control,no echo or loop */
33987e911b15Skarels 	duart->auxctl = 0x00;	/* baud rate set 1 */
33997e911b15Skarels 	duart->clkselA = 0x99;	/* 4800 baud for kbd */
34007e911b15Skarels 	duart->clkselB = 0x99;	/* 4800 baud for mouse */
34017e911b15Skarels 
34027e911b15Skarels 	/* reset everything for keyboard */
34037e911b15Skarels 
34047e911b15Skarels 	for (bits = RESET_M; bits < START_BREAK; bits += 0x10)
34057e911b15Skarels 		duart->cmdA = bits;
34067e911b15Skarels 
34077e911b15Skarels 	/* reset everything for host */
34087e911b15Skarels 
34097e911b15Skarels 	for (bits = RESET_M; bits < START_BREAK; bits += 0x10)
34107e911b15Skarels 		duart->cmdB = bits;
34117e911b15Skarels 
34127e911b15Skarels 	duart->cmdA = EN_RCV | EN_XMT; /* enbl xmt & rcv for kbd */
34137e911b15Skarels 	duart->cmdB = EN_RCV | EN_XMT; /* enbl xmt & rcv for pointer device */
34147e911b15Skarels 
3415b2b69f49Smarc 	/*
34167881ece5Smarc 	* init keyboard defaults (DUART channel A)
34177881ece5Smarc 	*/
34187e911b15Skarels 	for (i = 500; i > 0; --i) {
34197881ece5Smarc 		if (duart->statusA&XMT_RDY) {
34207e911b15Skarels 			duart->dataA = LK_DEFAULTS;
34217e911b15Skarels 			break;
34227e911b15Skarels 		}
34237e911b15Skarels 	}
34247e911b15Skarels 
34257e911b15Skarels 	for (i = 100000; i > 0; --i) {
34267881ece5Smarc 		if (duart->statusA&RCV_RDY) {
34277e911b15Skarels 			break;
34287e911b15Skarels 		}
34297e911b15Skarels 	}
34307e911b15Skarels 
34317881ece5Smarc 	if (duart->dataA)	/* flush the ACK */
34327881ece5Smarc 		;
34337e911b15Skarels 
3434b2b69f49Smarc 	/*
34357881ece5Smarc 	* identify the pointing device
34367881ece5Smarc 	*/
34377e911b15Skarels 	for (i = 500; i > 0; --i) {
34387881ece5Smarc 		if (duart->statusB&XMT_RDY) {
34397e911b15Skarels 			duart->dataB = SELF_TEST;
34407e911b15Skarels 			break;
34417e911b15Skarels 		}
34427e911b15Skarels 	}
34437e911b15Skarels 
3444b2b69f49Smarc 	/*
34457e911b15Skarels 	* wait for 1st byte of self test report */
34467e911b15Skarels 
34477e911b15Skarels 	for (i = 100000; i > 0; --i) {
34487881ece5Smarc 		if (duart->statusB&RCV_RDY) {
34497e911b15Skarels 			break;
34507e911b15Skarels 		}
34517e911b15Skarels 	}
34527e911b15Skarels 
34537e911b15Skarels 	if (i == 0) {
34547881ece5Smarc 		printf("qd[%d]: setup_input: timeout on 1st byte of self test\n"
3455b2b69f49Smarc 		       ,unit);
34567e911b15Skarels 		goto OUT;
34577e911b15Skarels 	}
34587e911b15Skarels 
34597881ece5Smarc 	if (duart->dataB)
34607881ece5Smarc 		;
34617e911b15Skarels 
3462b2b69f49Smarc 	/*
34637881ece5Smarc 	* wait for ID byte of self test report
34647881ece5Smarc 	*/
34657e911b15Skarels 	for (i = 100000; i > 0; --i) {
34667881ece5Smarc 		if (duart->statusB&RCV_RDY) {
34677e911b15Skarels 			break;
34687e911b15Skarels 		}
34697e911b15Skarels 	}
34707e911b15Skarels 
34717e911b15Skarels 	if (i == 0) {
34727881ece5Smarc 		printf("qd[%d]: setup_input: timeout on 2nd byte of self test\n", unit);
34737e911b15Skarels 		goto OUT;
34747e911b15Skarels 	}
34757e911b15Skarels 
34767e911b15Skarels 	id_byte = duart->dataB;
34777e911b15Skarels 
3478b2b69f49Smarc 	/*
34797881ece5Smarc 	* wait for other bytes to come in
34807881ece5Smarc 	*/
34817e911b15Skarels 	for (i = 100000; i > 0; --i) {
34827881ece5Smarc 		if (duart->statusB & RCV_RDY) {
34837881ece5Smarc 			if (duart->dataB)
34847881ece5Smarc 				;
34857e911b15Skarels 			break;
34867e911b15Skarels 		}
34877e911b15Skarels 	}
34887e911b15Skarels 	if (i == 0) {
34897881ece5Smarc 		printf("qd[%d]: setup_input: timeout on 3rd byte of self test\n", unit);
34907e911b15Skarels 		goto OUT;
34917e911b15Skarels 	}
34927e911b15Skarels 	for (i = 100000; i > 0; --i) {
34937881ece5Smarc 		if (duart->statusB&RCV_RDY) {
34947881ece5Smarc 			if (duart->dataB)
34957881ece5Smarc 				;
34967e911b15Skarels 			break;
34977e911b15Skarels 		}
34987e911b15Skarels 	}
34997e911b15Skarels 	if (i == 0) {
35007881ece5Smarc 		printf("qd[%d]: setup_input: timeout on 4th byte of self test\n", unit);
35017e911b15Skarels 		goto OUT;
35027e911b15Skarels 	}
3503b2b69f49Smarc 	/*
35047881ece5Smarc 	* flag pointing device type and set defaults
35057881ece5Smarc 	*/
35067881ece5Smarc 	for (i=100000; i>0; --i)
35077881ece5Smarc 		;		/*XXX*/
35087e911b15Skarels 
35097e911b15Skarels 	if ((id_byte & 0x0F) != TABLET_ID) {
35107e911b15Skarels 		qdflags[unit].pntr_id = MOUSE_ID;
35117e911b15Skarels 
35127e911b15Skarels 		for (i = 500; i > 0; --i) {
35137881ece5Smarc 			if (duart->statusB&XMT_RDY) {
35147e911b15Skarels 				duart->dataB = INC_STREAM_MODE;
35157e911b15Skarels 				break;
35167e911b15Skarels 			}
35177e911b15Skarels 		}
3518b2b69f49Smarc 	}
3519b2b69f49Smarc 	else {
35207e911b15Skarels 		qdflags[unit].pntr_id = TABLET_ID;
35217e911b15Skarels 
35227e911b15Skarels 		for (i = 500; i > 0; --i) {
35237881ece5Smarc 			if (duart->statusB&XMT_RDY) {
35247e911b15Skarels 				duart->dataB = T_STREAM;
35257e911b15Skarels 				break;
35267e911b15Skarels 			}
35277e911b15Skarels 		}
35287e911b15Skarels 	}
35297e911b15Skarels OUT:
35307e911b15Skarels 	duart->imask = qdflags[unit].duart_imask;
35317e911b15Skarels 
35327e911b15Skarels } /* setup_input */
35337e911b15Skarels 
35347881ece5Smarc /*
35357881ece5Smarc  * delay for at least one display frame time
35367e911b15Skarels  *
35377e911b15Skarels  *	return: BAD means that we timed out without ever seeing the
35387e911b15Skarels  *		      vertical sync status bit
35397e911b15Skarels  *		GOOD otherwise
35407881ece5Smarc  */
35417e911b15Skarels wait_status(adder, mask)
35427e911b15Skarels 	register struct adder *adder;
35437e911b15Skarels 	register int mask;
35447e911b15Skarels {
35457881ece5Smarc 	register i;
35467e911b15Skarels 
3547b2b69f49Smarc 	for (i = 10000, adder->status = 0 ; i > 0  &&
35487881ece5Smarc 	     !(adder->status&mask) ; --i)
3549b2b69f49Smarc 		;
35507e911b15Skarels 
35517e911b15Skarels 	if (i == 0) {
35527881ece5Smarc 		printf("wait_status: timeout polling for 0x%x in adder->status\n", mask);
35537e911b15Skarels 		return(BAD);
35547e911b15Skarels 	}
35557e911b15Skarels 
35567e911b15Skarels 	return(GOOD);
35577e911b15Skarels 
35587e911b15Skarels } /* wait_status */
35597e911b15Skarels 
35607881ece5Smarc /*
35617881ece5Smarc  * write out onto the ID bus
35627881ece5Smarc  */
35637e911b15Skarels write_ID(adder, adrs, data)
35647e911b15Skarels 	register struct adder *adder;
35657e911b15Skarels 	register short adrs;
35667e911b15Skarels 	register short data;
35677e911b15Skarels {
35687881ece5Smarc 	register i;
35697e911b15Skarels 
3570b2b69f49Smarc 	for (i = 100000, adder->status = 0 ;
35717881ece5Smarc 	      i > 0  &&  !(adder->status&ADDRESS_COMPLETE) ; --i)
3572b2b69f49Smarc 		;
35737e911b15Skarels 
35747e911b15Skarels 	if (i == 0)
35757e911b15Skarels 		goto ERR;
35767e911b15Skarels 
3577b2b69f49Smarc 	for (i = 100000, adder->status = 0 ;
35787881ece5Smarc 	      i > 0  &&  !(adder->status&TX_READY) ; --i)
3579b2b69f49Smarc 		;
35807e911b15Skarels 
35817e911b15Skarels 	if (i > 0) {
35827e911b15Skarels 		adder->id_data = data;
35837e911b15Skarels 		adder->command = ID_LOAD | adrs;
35847881ece5Smarc 		return ;
35857e911b15Skarels 	}
35867e911b15Skarels 
35877e911b15Skarels ERR:
35887881ece5Smarc 	printf("write_ID: timeout trying to write to VIPER\n");
35897881ece5Smarc 	return ;
35907e911b15Skarels 
35917e911b15Skarels } /* write_ID */
3592006e9885Smarc #endif
3593