xref: /original-bsd/sys/vax/uba/qd.c (revision 2b86b1e4)
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*2b86b1e4Stef  *	@(#)qd.c	1.11 (Berkeley) 02/07/89
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"
50b2b69f49Smarc #include "../machine/pte.h"
51b2b69f49Smarc #include "../machine/mtpr.h"
52006e9885Smarc #include "../machine/cpu.h"
53b2b69f49Smarc #include "param.h"
54b2b69f49Smarc #include "conf.h"
55b2b69f49Smarc #include "dir.h"
56b2b69f49Smarc #include "user.h"
57b2b69f49Smarc #include "qdioctl.h"
58006e9885Smarc #include "tty.h"
59b2b69f49Smarc #include "map.h"
60b2b69f49Smarc #include "buf.h"
61b2b69f49Smarc #include "vm.h"
62b2b69f49Smarc #include "bk.h"
63b2b69f49Smarc #include "clist.h"
64b2b69f49Smarc #include "file.h"
65b2b69f49Smarc #include "uio.h"
66b2b69f49Smarc #include "kernel.h"
67e977faadSmarc #include "exec.h"
68e977faadSmarc #include "proc.h"
69b2b69f49Smarc #include "ubareg.h"
70b2b69f49Smarc #include "ubavar.h"
71e977faadSmarc #include "syslog.h"
72b2b69f49Smarc #include "qduser.h"	/* definitions shared with user level client */
73e977faadSmarc #include "qdreg.h"	/* QDSS device register structures */
7424f67f6bSmarc 
75b2b69f49Smarc /*
76b2b69f49Smarc  * QDSS driver status flags for tracking operational state
77b2b69f49Smarc  */
7824f67f6bSmarc struct qdflags {
7924f67f6bSmarc 	u_int inuse;		/* which minor dev's are in use now */
8024f67f6bSmarc 	u_int config;		/* I/O page register content */
8124f67f6bSmarc 	u_int mapped;		/* user mapping status word */
82e977faadSmarc 	u_int kernel_loop;	/* if kernel console is redirected */
8324f67f6bSmarc 	u_int user_dma;		/* DMA from user space in progress */
8424f67f6bSmarc 	u_short pntr_id;	/* type code of pointing device */
8524f67f6bSmarc 	u_short duart_imask;	/* shadowing for duart intrpt mask reg */
8624f67f6bSmarc 	u_short adder_ie;	/* shadowing for adder intrpt enbl reg */
8724f67f6bSmarc 	u_short curs_acc;	/* cursor acceleration factor */
8824f67f6bSmarc 	u_short curs_thr;	/* cursor acceleration threshold level */
8924f67f6bSmarc 	u_short tab_res;	/* tablet resolution factor */
9024f67f6bSmarc 	u_short selmask;	/* mask for active qd select entries */
9124f67f6bSmarc };
9224f67f6bSmarc 
93b2b69f49Smarc /*
94b2b69f49Smarc  * bit definitions for 'inuse' entry
95b2b69f49Smarc  */
9624f67f6bSmarc #define CONS_DEV	0x01
9724f67f6bSmarc #define GRAPHIC_DEV	0x04
9824f67f6bSmarc 
99b2b69f49Smarc /*
100b2b69f49Smarc  * bit definitions for 'mapped' member of flag structure
101b2b69f49Smarc  */
10224f67f6bSmarc #define MAPDEV		0x01		/* hardware is mapped */
10324f67f6bSmarc #define MAPDMA		0x02		/* DMA buffer mapped */
10424f67f6bSmarc #define MAPEQ		0x04		/* event queue buffer mapped */
10524f67f6bSmarc #define MAPSCR		0x08		/* scroll param area mapped */
10624f67f6bSmarc #define MAPCOLOR	0x10		/* color map writing buffer mapped */
10724f67f6bSmarc 
108b2b69f49Smarc /*
109b2b69f49Smarc  * bit definitions for 'selmask' member of qdflag structure
110b2b69f49Smarc  */
11124f67f6bSmarc #define SEL_READ	0x01		/* read select is active */
11224f67f6bSmarc #define SEL_WRITE	0x02		/* write select is active */
11324f67f6bSmarc 
114b2b69f49Smarc /*
115b2b69f49Smarc  * constants used in shared memory operations
116b2b69f49Smarc  */
11724f67f6bSmarc #define EVENT_BUFSIZE  1024	/* # of bytes per device's event buffer */
11824f67f6bSmarc #define MAXEVENTS  ( (EVENT_BUFSIZE - sizeof(struct qdinput))	 \
11924f67f6bSmarc 	/ sizeof(struct _vs_event) )
1200d59d4d6Smarc #define DMA_BUFSIZ	(1024 * 10)
12124f67f6bSmarc #define COLOR_BUFSIZ  ((sizeof(struct color_buf) + 512) & ~0x01FF)
12224f67f6bSmarc 
123b2b69f49Smarc /*
12424f67f6bSmarc  * reference to an array of "uba_device" structures built by the auto
12524f67f6bSmarc  * configuration program.  The uba_device structure decribes the device
12624f67f6bSmarc  * sufficiently for the driver to talk to it.  The auto configuration code
12724f67f6bSmarc  * fills in the uba_device structures (located in ioconf.c) from user
128b2b69f49Smarc  * maintained info.
129b2b69f49Smarc  */
13024f67f6bSmarc struct uba_device *qdinfo[NQD];  /* array of pntrs to each QDSS's */
13124f67f6bSmarc struct tty qd_tty[NQD*4];	/* teletype structures for each.. */
1327881ece5Smarc extern char qvmem[][128*NBPG];
133b2b69f49Smarc extern struct pte QVmap[][128];
134b2b69f49Smarc #define CHUNK	  (64 * 1024)
135b2b69f49Smarc #define QMEMSIZE  (1024 * 1024 * 4)	/* 4 meg */
13624f67f6bSmarc 
137b2b69f49Smarc /*
138b2b69f49Smarc  * static storage used by multiple functions in this code
139b2b69f49Smarc  */
14024f67f6bSmarc int Qbus_unmap[NQD];		/* Qbus mapper release code */
14124f67f6bSmarc struct qdflags qdflags[NQD];	/* QDSS device status flags */
14224f67f6bSmarc struct qdmap qdmap[NQD];	/* QDSS register map structure */
14324f67f6bSmarc caddr_t qdbase[NQD];		/* base address of each QDSS unit */
14424f67f6bSmarc struct buf qdbuf[NQD];		/* buf structs used by strategy */
145b2b69f49Smarc short qdopened[NQD];		/* graphics device is open exclusive use */
14624f67f6bSmarc 
147b2b69f49Smarc /*
148e977faadSmarc  * the array "event_shared[]" is made up of a number of event queue buffers
14924f67f6bSmarc  * equal to the number of QDSS's configured into the running kernel (NQD).
15024f67f6bSmarc  * Each event queue buffer begins with an event queue header (struct qdinput)
15124f67f6bSmarc  * followed by a group of event queue entries (struct _vs_event).  The array
15224f67f6bSmarc  * "*eq_header[]" is an array of pointers to the start of each event queue
153b2b69f49Smarc  * buffer in "event_shared[]".
154b2b69f49Smarc  */
15524f67f6bSmarc #define EQSIZE ((EVENT_BUFSIZE * NQD) + 512)
15624f67f6bSmarc 
15724f67f6bSmarc char event_shared[EQSIZE];	    /* reserve space for event bufs */
15824f67f6bSmarc struct qdinput *eq_header[NQD];     /* event queue header pntrs */
15924f67f6bSmarc 
160b2b69f49Smarc /*
16124f67f6bSmarc  * This allocation method reserves enough memory pages for NQD shared DMA I/O
16224f67f6bSmarc  * buffers.  Each buffer must consume an integral number of memory pages to
16324f67f6bSmarc  * guarantee that a following buffer will begin on a page boundary.  Also,
16424f67f6bSmarc  * enough space is allocated so that the FIRST I/O buffer can start at the
16524f67f6bSmarc  * 1st page boundary after "&DMA_shared".  Page boundaries are used so that
166b2b69f49Smarc  * memory protections can be turned on/off for individual buffers.
167b2b69f49Smarc  */
16824f67f6bSmarc #define IOBUFSIZE  ((DMA_BUFSIZ * NQD) + 512)
16924f67f6bSmarc 
17024f67f6bSmarc char DMA_shared[IOBUFSIZE];	    /* reserve I/O buffer space */
17124f67f6bSmarc struct DMAreq_header *DMAheader[NQD];  /* DMA buffer header pntrs */
17224f67f6bSmarc 
173b2b69f49Smarc /*
17424f67f6bSmarc  * The driver assists a client in scroll operations by loading dragon
17524f67f6bSmarc  * registers from an interrupt service routine.	The loading is done using
17624f67f6bSmarc  * parameters found in memory shrade between the driver and it's client.
17724f67f6bSmarc  * The scroll parameter structures are ALL loacted in the same memory page
178b2b69f49Smarc  * for reasons of memory economy.
179b2b69f49Smarc  */
18024f67f6bSmarc char scroll_shared[2 * 512];	/* reserve space for scroll structs */
18124f67f6bSmarc struct scroll *scroll[NQD];	/* pointers to scroll structures */
18224f67f6bSmarc 
183b2b69f49Smarc /*
18424f67f6bSmarc  * the driver is programmable to provide the user with color map write
18524f67f6bSmarc  * services at VSYNC interrupt time.  At interrupt time the driver loads
186b2b69f49Smarc  * the color map with any user-requested load data found in shared memory
187b2b69f49Smarc  */
18824f67f6bSmarc #define COLOR_SHARED  ((COLOR_BUFSIZ * NQD) + 512)
18924f67f6bSmarc 
190e977faadSmarc char color_shared[COLOR_SHARED];      /* reserve space: color bufs */
19124f67f6bSmarc struct color_buf *color_buf[NQD];     /* pointers to color bufs */
19224f67f6bSmarc 
193b2b69f49Smarc /*
194b2b69f49Smarc  * mouse input event structures
195b2b69f49Smarc  */
19624f67f6bSmarc struct mouse_report last_rep[NQD];
19724f67f6bSmarc struct mouse_report current_rep[NQD];
19824f67f6bSmarc 
1997881ece5Smarc struct proc *qdrsel[NQD]; 	/* process waiting for select */
200b2b69f49Smarc struct _vs_cursor cursor[NQD];	/* console cursor */
201b2b69f49Smarc int qdcount = 0;		/* count of successfully probed qd's */
20224f67f6bSmarc int nNQD = NQD;
20324f67f6bSmarc int DMAbuf_size = DMA_BUFSIZ;
204e977faadSmarc int QDlast_DMAtype;             /* type of the last DMA operation */
205e977faadSmarc 
206b2b69f49Smarc #define QDSSMAJOR	41	/* QDSS major device number */
207b2b69f49Smarc /*
208b2b69f49Smarc  * macro to get system time.  Used to time stamp event queue entries
209b2b69f49Smarc  */
2107e911b15Skarels #define TOY ((time.tv_sec * 100) + (time.tv_usec / 10000))
2117e911b15Skarels 
2127e911b15Skarels int qdprobe();
2137e911b15Skarels int qdattach();
2147e911b15Skarels int qddint();			/* DMA gate array intrpt service */
2157e911b15Skarels int qdaint();			/* Dragon ADDER intrpt service */
2167e911b15Skarels int qdiint();
2177e911b15Skarels 
2187e911b15Skarels u_short qdstd[] = { 0 };
2197e911b15Skarels 
220b2b69f49Smarc struct uba_driver qddriver = {
2217e911b15Skarels 	qdprobe,		/* device probe entry */
2227e911b15Skarels 	0,			/* no slave device */
2237e911b15Skarels 	qdattach,		/* device attach entry */
2247e911b15Skarels 	0,			/* no "fill csr/ba to start" */
2257e911b15Skarels 	qdstd,			/* device addresses */
2267e911b15Skarels 	"qd",			/* device name string */
2277e911b15Skarels 	qdinfo			/* ptr to QDSS's uba_device struct */
2287e911b15Skarels };
2297e911b15Skarels 
230e977faadSmarc #define QDPRIOR (PZERO-1)		/* must be negative */
2317e911b15Skarels #define FALSE	0
2327e911b15Skarels #define TRUE	~FALSE
2337e911b15Skarels #define BAD	-1
2347e911b15Skarels #define GOOD	0
2357e911b15Skarels 
236b2b69f49Smarc /*
237b2b69f49Smarc  * macro to create a system virtual page number from system virtual adrs
238b2b69f49Smarc  */
239b2b69f49Smarc #define VTOP(x)  (((int)x & ~0xC0000000) >> PGSHIFT)
2407e911b15Skarels 
241b2b69f49Smarc /*
242b2b69f49Smarc  * QDSS register address offsets from start of QDSS address space
243b2b69f49Smarc  */
2447e911b15Skarels #define QDSIZE	 (52 * 1024)	/* size of entire QDSS foot print */
2457e911b15Skarels #define TMPSIZE  (16 * 1024)	/* template RAM is 8k SHORT WORDS */
2467e911b15Skarels #define TMPSTART 0x8000 	/* offset of template RAM from base adrs */
2477e911b15Skarels #define REGSIZE  (5 * 512)	/* regs touch 2.5k (5 pages) of addr space */
2487e911b15Skarels #define REGSTART 0xC000 	/* offset of reg pages from base adrs */
2497e911b15Skarels #define ADDER	(REGSTART+0x000)
2507e911b15Skarels #define DGA	(REGSTART+0x200)
2517e911b15Skarels #define DUART	(REGSTART+0x400)
2527e911b15Skarels #define MEMCSR	(REGSTART+0x800)
2537e911b15Skarels #define CLRSIZE  (3 * 512)		/* color map size */
2547e911b15Skarels #define CLRSTART (REGSTART+0xA00)	/* color map start offset from base */
2557e911b15Skarels /*  0x0C00 really */
2567e911b15Skarels #define RED	(CLRSTART+0x000)
2577e911b15Skarels #define BLUE	(CLRSTART+0x200)
2587e911b15Skarels #define GREEN	(CLRSTART+0x400)
2597e911b15Skarels 
2607e911b15Skarels 
261b2b69f49Smarc /*
2627e911b15Skarels  * QDSS minor device numbers.  The *real* minor device numbers are in
2637e911b15Skarels  * the bottom two bits of the major/minor device spec.  Bits 2 and up are
264b2b69f49Smarc  * used to specify the QDSS device number (ie: which one?)
265b2b69f49Smarc  */
2667e911b15Skarels 
2677e911b15Skarels #define CONS		0
2687e911b15Skarels #define GRAPHIC 	2
2697e911b15Skarels 
270b2b69f49Smarc /*
271b2b69f49Smarc  * console cursor bitmap (white block cursor)
272b2b69f49Smarc  */
273b2b69f49Smarc short cons_cursor[32] = {
2747e911b15Skarels 	/* A */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
2757e911b15Skarels 	0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
2767e911b15Skarels 	/* B */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
2777e911b15Skarels 	0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF
2787e911b15Skarels };
2797e911b15Skarels 
280b2b69f49Smarc /*
281b2b69f49Smarc  * constants used in font operations
282b2b69f49Smarc  */
283e977faadSmarc #define CHARS		190 			/* # of chars in the font */
2847e911b15Skarels #define CHAR_HEIGHT	15			/* char height in pixels */
2857e911b15Skarels #define CHAR_WIDTH	8			/* char width in pixels*/
2867e911b15Skarels #define FONT_WIDTH	(CHAR_WIDTH * CHARS)	/* font width in pixels */
2877e911b15Skarels #define ROWS		CHAR_HEIGHT
2887e911b15Skarels #define FONT_X		0			/* font's off screen adrs */
2897e911b15Skarels #define FONT_Y		(2048 - CHAR_HEIGHT)
290e977faadSmarc 
291b2b69f49Smarc /* Offset to second row characters (XXX - should remove) */
292e977faadSmarc #define FONT_OFFSET	((MAX_SCREEN_X/CHAR_WIDTH)*CHAR_HEIGHT)
2937e911b15Skarels 
2947e911b15Skarels extern char q_font[];		/* reference font object code */
295e977faadSmarc extern	u_short q_key[];	/* reference key xlation tables */
296e977faadSmarc extern	u_short q_shift_key[];
2977e911b15Skarels extern	char *q_special[];
2987e911b15Skarels 
299b2b69f49Smarc /*
300b2b69f49Smarc  * definitions for cursor acceleration reporting
301b2b69f49Smarc  */
3027e911b15Skarels #define ACC_OFF 	0x01		/* acceleration is inactive */
3037e911b15Skarels 
304b2b69f49Smarc /*
305b2b69f49Smarc  * virtual console support.
3067e911b15Skarels  */
307e977faadSmarc extern (*v_putc)();
308e977faadSmarc extern struct cdevsw *consops;
309e977faadSmarc int qdputc();
310e977faadSmarc int qdstart();
311e977faadSmarc 
312b2b69f49Smarc /*
313b2b69f49Smarc  * LK-201 state storage for input console keyboard conversion to ASCII
314b2b69f49Smarc  */
3157e911b15Skarels struct q_keyboard {
3167e911b15Skarels 	int shift;			/* state variables	*/
3177e911b15Skarels 	int cntrl;
3187e911b15Skarels 	int lock;
3197e911b15Skarels 	int lastcode;			/* last keycode typed	*/
3207e911b15Skarels 	unsigned kup[8];		/* bits for each keycode*/
3217e911b15Skarels 	unsigned dkeys[8];		/* down/up mode keys	*/
3227e911b15Skarels 	char last;			/* last character	*/
3237e911b15Skarels } q_keyboard;
3247e911b15Skarels 
325b2b69f49Smarc /*
326b2b69f49Smarc  * tty settings on first open
327b2b69f49Smarc  */
328e977faadSmarc #define IFLAGS	(EVENP|ECHO|XTABS|CRMOD)
329e977faadSmarc #ifdef POSIXTTY
330e977faadSmarc #define IFLAG (BRKINT|ISTRIP|IXON|IXANY|ICRNL|IEXTEN|IMAXBEL)
331e977faadSmarc #define OFLAG (OPOST|OXTABS|ONLCR)
332e977faadSmarc #define LFLAG (ISIG|ICANON|ECHO)
333e977faadSmarc #define CFLAG (PARENB|CREAD|CS7|CLOCAL)
334e977faadSmarc #endif
335e977faadSmarc 
3367881ece5Smarc /*
3377881ece5Smarc  * Init QDSS as console (before probe routine)
3387881ece5Smarc  */
3397e911b15Skarels 
3407e911b15Skarels qdcons_init()
3417e911b15Skarels {
3427881ece5Smarc 	register unit;
3437e911b15Skarels 	caddr_t phys_adr;		/* physical QDSS base adrs */
344e977faadSmarc 	u_int mapix;			/* index into QVmap[] array */
345e977faadSmarc 	struct percpu *pcpu;		/* pointer to cpusw structure  */
346e977faadSmarc 	register struct qbus *qb;
3477e911b15Skarels 	u_short *qdaddr;		/* address of QDSS IO page CSR */
3487e911b15Skarels 	u_short *devptr;		/* vitual device space */
349e977faadSmarc 	extern cnputc();
3507e911b15Skarels 
3517e911b15Skarels #define QDSSCSR 0x1F00
3527e911b15Skarels 
35324f67f6bSmarc 	if (v_putc != cnputc)
3547881ece5Smarc 	    return 0;
35524f67f6bSmarc 
3567e911b15Skarels 	unit = 0;
3577e911b15Skarels 
358b2b69f49Smarc 	/*
359b2b69f49Smarc 	 * find the cpusw entry that matches this machine.
360b2b69f49Smarc 	 */
36124f67f6bSmarc 	for (pcpu = percpu; pcpu && pcpu->pc_cputype != cpu; pcpu++)
3627e911b15Skarels 		;
36324f67f6bSmarc 	if (pcpu == NULL)
3647881ece5Smarc 	    return 0;
365*2b86b1e4Stef 	if (pcpu->pc_io->io_type != IO_QBUS)
366*2b86b1e4Stef 	    return 0;
36724f67f6bSmarc 
36824f67f6bSmarc 	/*
369e977faadSmarc 	 * Map device registers - the last 8K of qvmem.
37024f67f6bSmarc 	 */
37124f67f6bSmarc 	qb = (struct qbus *)pcpu->pc_io->io_details;
37224f67f6bSmarc 	ioaccess(qb->qb_iopage, UMEMmap[0] + qb->qb_memsize,
37324f67f6bSmarc 		 UBAIOPAGES * NBPG);
37424f67f6bSmarc 	devptr = (u_short *)((char *)umem[0]+(qb->qb_memsize * NBPG));
37524f67f6bSmarc 	qdaddr = (u_short *)((u_int)devptr + ubdevreg(QDSSCSR));
3767881ece5Smarc 	if (badaddr((caddr_t)qdaddr, sizeof(short)))
3777881ece5Smarc 		return 0;
378e977faadSmarc 
37924f67f6bSmarc 	/*
38024f67f6bSmarc 	 * Map q-bus memory used by qdss. (separate map)
38124f67f6bSmarc 	 */
38224f67f6bSmarc 	mapix = QMEMSIZE - (CHUNK * (unit + 1));
38324f67f6bSmarc 	phys_adr = qb->qb_maddr + mapix;
38424f67f6bSmarc 	ioaccess(phys_adr, QVmap[0], (CHUNK*NQD));
3857e911b15Skarels 
38624f67f6bSmarc 	/*
38724f67f6bSmarc 	 * tell QDSS which Q memory address base to decode
388b2b69f49Smarc 	 * (shifted right 16 bits - its in 64K units)
38924f67f6bSmarc 	 */
39024f67f6bSmarc 	*qdaddr = (u_short)((int)mapix >> 16);
3917e911b15Skarels 	qdflags[unit].config = *(u_short *)qdaddr;
3927e911b15Skarels 
393b2b69f49Smarc 	/*
394b2b69f49Smarc 	 * load qdmap struct with the virtual addresses of the QDSS elements
395b2b69f49Smarc 	 */
396e977faadSmarc 	qdbase[unit] = (caddr_t) (qvmem[0]);
3977e911b15Skarels 	qdmap[unit].template = qdbase[unit] + TMPSTART;
3987e911b15Skarels 	qdmap[unit].adder = qdbase[unit] + ADDER;
3997e911b15Skarels 	qdmap[unit].dga = qdbase[unit] + DGA;
4007e911b15Skarels 	qdmap[unit].duart = qdbase[unit] + DUART;
4017e911b15Skarels 	qdmap[unit].memcsr = qdbase[unit] + MEMCSR;
4027e911b15Skarels 	qdmap[unit].red = qdbase[unit] + RED;
4037e911b15Skarels 	qdmap[unit].blue = qdbase[unit] + BLUE;
4047e911b15Skarels 	qdmap[unit].green = qdbase[unit] + GREEN;
4057e911b15Skarels 
4067e911b15Skarels 	qdflags[unit].duart_imask = 0;	/* init shadow variables */
4077e911b15Skarels 
408b2b69f49Smarc 	/*
409b2b69f49Smarc 	 * init the QDSS
410b2b69f49Smarc 	 */
411b2b69f49Smarc 	/*
41224f67f6bSmarc 	printf("qdbase[0] = %x, qdmap[0].memcsr = %x\n",
41324f67f6bSmarc 		(char *)qdbase[0], qdmap[0].memcsr);
414b2b69f49Smarc 	*/
4157e911b15Skarels 
4167e911b15Skarels 	*(short *)qdmap[unit].memcsr |= SYNC_ON; /* once only: turn on sync */
4177e911b15Skarels 
4187e911b15Skarels 	cursor[unit].x = 0;
4197e911b15Skarels 	cursor[unit].y = 0;
4207e911b15Skarels 	init_shared(unit);		/* init shared memory */
4217e911b15Skarels 	setup_dragon(unit);		/* init the ADDER/VIPER stuff */
4227e911b15Skarels 	clear_qd_screen(unit);		/* clear the screen */
4237e911b15Skarels 	ldfont(unit);			/* load the console font */
4247e911b15Skarels 	ldcursor(unit, cons_cursor);	/* load default cursor map */
4257e911b15Skarels 	setup_input(unit);		/* init the DUART */
426b2b69f49Smarc 	v_putc = qdputc;		/* kernel console output to qdss */
427b2b69f49Smarc 	consops = &cdevsw[QDSSMAJOR];	/* virtual console is qdss */
4287881ece5Smarc 	return 1;
4297e911b15Skarels 
4307e911b15Skarels } /* qdcons_init */
4317e911b15Skarels 
4327881ece5Smarc /*
4337881ece5Smarc  *  Configure QDSS into Q memory and make it intrpt.
4347e911b15Skarels  *
4357e911b15Skarels  *  side effects: QDSS gets mapped into Qbus memory space at the first
4367e911b15Skarels  *		 vacant 64kb boundary counting back from the top of
437e977faadSmarc  *		 Qbus memory space (qvmem+4mb)
4387e911b15Skarels  *
4397e911b15Skarels  *  return: QDSS bus request level and vector address returned in
4407e911b15Skarels  *	   registers by UNIX convention.
4417e911b15Skarels  *
4427881ece5Smarc  */
4437e911b15Skarels qdprobe(reg)
4447881ece5Smarc 	caddr_t reg;	/* character pointer to the QDSS I/O page register */
4457e911b15Skarels {
44624f67f6bSmarc 	register int br, cvec;  	/* value-result */
4477e911b15Skarels 	register int unit;
4487e911b15Skarels 	struct dga *dga;		/* pointer to gate array structure */
4497e911b15Skarels 	int vector;
4507881ece5Smarc #ifdef notdef
4517881ece5Smarc 	int *ptep;			/* page table entry pointer */
4527e911b15Skarels 	caddr_t phys_adr;		/* physical QDSS base adrs */
4537e911b15Skarels 	u_int mapix;
4547881ece5Smarc #endif
4557881ece5Smarc 
4567881ece5Smarc #ifdef lint
4577881ece5Smarc 	br = 0; cvec = br; br = cvec; nNQD = br; br = nNQD;
4587881ece5Smarc 	qddint(0); qdaint(0); qdiint(0); (void)qdgetc();
4597881ece5Smarc #endif
4607e911b15Skarels 
461b2b69f49Smarc 	/*
462b2b69f49Smarc 	 * calculate board unit number from I/O page register address
463b2b69f49Smarc 	 */
4647e911b15Skarels 	unit = (int) (((int)reg >> 1) & 0x0007);
4657e911b15Skarels 
466b2b69f49Smarc 	/*
467b2b69f49Smarc 	 * QDSS regs must be mapped to Qbus memory space at a 64kb
468b2b69f49Smarc  	 * physical boundary.  The Qbus memory space is mapped into
469b2b69f49Smarc 	 * the system memory space at config time.  After config
470b2b69f49Smarc 	 * runs, "qvmem[0]" (ubavar.h) holds the system virtual adrs
471b2b69f49Smarc 	 * of the start of Qbus memory.   The Qbus memory page table
472b2b69f49Smarc 	 * is found via an array of pte ptrs called "QVmap[]" (ubavar.h)
473b2b69f49Smarc 	 * which is also loaded at config time.   These are the
474b2b69f49Smarc 	 * variables used below to find a vacant 64kb boundary in
475b2b69f49Smarc 	 * Qbus memory, and load it's corresponding physical adrs
476b2b69f49Smarc 	 * into the QDSS's I/O page CSR.
477b2b69f49Smarc 	 */
478e977faadSmarc 
479e977faadSmarc 	/*
480e977faadSmarc 	 * Only if QD is the graphics device.
48124f67f6bSmarc 	 */
4827e911b15Skarels 
4837e911b15Skarels 	/* if this QDSS is NOT the console, then do init here.. */
4847e911b15Skarels 
485e977faadSmarc 	if (unit != 0) {
486e977faadSmarc 		printf("qd: can't support two qdss's (yet)\n");
4877881ece5Smarc #ifdef notdef	/* can't test */
4887e911b15Skarels 		if (v_consputc != qdputc  ||  unit != 0) {
4897e911b15Skarels 
490b2b69f49Smarc 			/*
491b2b69f49Smarc 			* read QDSS config info
492b2b69f49Smarc 			*/
4937e911b15Skarels 			qdflags[unit].config = *(u_short *)reg;
4947e911b15Skarels 
495b2b69f49Smarc 			/*
496b2b69f49Smarc 			* find an empty 64kb adrs boundary
497b2b69f49Smarc 			*/
4987e911b15Skarels 
499e977faadSmarc 			qdbase[unit] = (caddr_t) (qvmem[0] + QMEMSIZE - CHUNK);
500e977faadSmarc 
501b2b69f49Smarc 			/*
5027881ece5Smarc 			* find the cpusw entry that matches this machine.
5037881ece5Smarc 			*/
5047e911b15Skarels 			cpup = &cpusw[cpu];
5057e911b15Skarels 			while (!(BADADDR(qdbase[unit], sizeof(short))))
5067e911b15Skarels 				qdbase[unit] -= CHUNK;
5077e911b15Skarels 
508b2b69f49Smarc 			/*
5097881ece5Smarc 			* tell QDSS which Q memory address base to decode
5107881ece5Smarc 			*/
511e977faadSmarc 			mapix = (int) (VTOP(qdbase[unit]) - VTOP(qvmem[0]));
512e977faadSmarc 			ptep = (int *) QVmap[0] + mapix;
5137e911b15Skarels 			phys_adr = (caddr_t)(((int)*ptep&0x001FFFFF)<<PGSHIFT);
5147e911b15Skarels 			*(u_short *)reg = (u_short) ((int)phys_adr >> 16);
5157e911b15Skarels 
516b2b69f49Smarc 			/*
517b2b69f49Smarc 			* load QDSS adrs map with system addresses
518b2b69f49Smarc 			* of device regs
519b2b69f49Smarc 			*/
5207e911b15Skarels 			qdmap[unit].template = qdbase[unit] + TMPSTART;
5217e911b15Skarels 			qdmap[unit].adder = qdbase[unit] + ADDER;
5227e911b15Skarels 			qdmap[unit].dga = qdbase[unit] + DGA;
5237e911b15Skarels 			qdmap[unit].duart = qdbase[unit] + DUART;
5247e911b15Skarels 			qdmap[unit].memcsr = qdbase[unit] + MEMCSR;
5257e911b15Skarels 			qdmap[unit].red = qdbase[unit] + RED;
5267e911b15Skarels 			qdmap[unit].blue = qdbase[unit] + BLUE;
5277e911b15Skarels 			qdmap[unit].green = qdbase[unit] + GREEN;
5287e911b15Skarels 
5297e911b15Skarels 			/* device init */
5307e911b15Skarels 
5317e911b15Skarels 			cursor[unit].x = 0;
5327e911b15Skarels 			cursor[unit].y = 0;
5337e911b15Skarels 			init_shared(unit);		/* init shared memory */
5347e911b15Skarels 			setup_dragon(unit); 	/* init the ADDER/VIPER stuff */
5357e911b15Skarels 			ldcursor(unit, cons_cursor);	/* load default cursor map */
5367e911b15Skarels 			setup_input(unit);		/* init the DUART */
5377e911b15Skarels 			clear_qd_screen(unit);
5387e911b15Skarels 			ldfont(unit);			/* load the console font */
5397e911b15Skarels 
5407e911b15Skarels 			/* once only: turn on sync */
5417e911b15Skarels 
5427e911b15Skarels 			*(short *)qdmap[unit].memcsr |= SYNC_ON;
543b2b69f49Smarc 		}
544006e9885Smarc #endif /*notdef*/
545e977faadSmarc 	}
5467e911b15Skarels 
547b2b69f49Smarc 	/*
548b2b69f49Smarc 	* The QDSS interrupts at HEX vectors xx0 (DMA) xx4
549b2b69f49Smarc 	* (ADDER) and xx8 (DUART).  Therefore, we take three
550b2b69f49Smarc 	* vectors from the vector pool, and then continue
551b2b69f49Smarc 	* to take them until we get a xx0 HEX vector.  The
552b2b69f49Smarc 	* pool provides vectors in contiguous decending
553b2b69f49Smarc 	* order.
554b2b69f49Smarc 	*/
5557e911b15Skarels 
5567e911b15Skarels 	vector = (uba_hd[0].uh_lastiv -= 4*3);	/* take three vectors */
5577e911b15Skarels 
5587e911b15Skarels 	while (vector & 0x0F) {		   /* if lo nibble != 0.. */
559b2b69f49Smarc 		/* ..take another vector */
560b2b69f49Smarc 		vector = (uba_hd[0].uh_lastiv -= 4);
5617e911b15Skarels 	}
5627e911b15Skarels 
563b2b69f49Smarc 	/*
564b2b69f49Smarc 	* setup DGA to do a DMA interrupt (transfer count = 0)
565b2b69f49Smarc 	*/
5667e911b15Skarels 	dga = (struct dga *) qdmap[unit].dga;
5677e911b15Skarels 	dga->csr = (short) HALT;	/* disable everything */
5687e911b15Skarels 	dga->ivr = (short) vector;	/* load intrpt base vector */
5697e911b15Skarels 	dga->bytcnt_lo = (short) 0;	/* DMA xfer count = 0 */
5707e911b15Skarels 	dga->bytcnt_hi = (short) 0;
5717e911b15Skarels 
572b2b69f49Smarc 	/*
573b2b69f49Smarc 	* turn on DMA interrupts
574b2b69f49Smarc 	*/
5757e911b15Skarels 	dga->csr &= ~SET_DONE_FIFO;
5767e911b15Skarels 	dga->csr |= DMA_IE | DL_ENB;
5777e911b15Skarels 
5787e911b15Skarels 	DELAY(20000);			/* wait for the intrpt */
5797e911b15Skarels 	dga->csr = HALT;		/* stop the wheels */
5807e911b15Skarels 
5817e911b15Skarels 	if (cvec != vector)		/* if vector != base vector.. */
5827e911b15Skarels 		return(0);		/* ..return = 'no device' */
5837e911b15Skarels 
584e977faadSmarc 	/*
585e977faadSmarc 	* score this as an existing qdss
586e977faadSmarc 	*/
587e977faadSmarc 	qdcount++;
588e977faadSmarc 
5897e911b15Skarels 	return(sizeof(short));	    /* return size of QDSS I/O page reg */
5907e911b15Skarels 
5917e911b15Skarels } /* qdprobe */
5927e911b15Skarels 
5937e911b15Skarels qdattach(ui)
5947e911b15Skarels 	struct uba_device *ui;
5957e911b15Skarels {
5967881ece5Smarc 	register unit;			/* QDSS module # for this call */
5977e911b15Skarels 
5987e911b15Skarels 	unit = ui->ui_unit;		/* get QDSS number */
5997e911b15Skarels 
600b2b69f49Smarc 	/*
601b2b69f49Smarc 	* init "qdflags[]" for this QDSS
602b2b69f49Smarc 	*/
6037e911b15Skarels 	qdflags[unit].inuse = 0;	/* init inuse variable EARLY! */
6047e911b15Skarels 	qdflags[unit].mapped = 0;
605e977faadSmarc 	qdflags[unit].kernel_loop = -1;
6067e911b15Skarels 	qdflags[unit].user_dma = 0;
6077e911b15Skarels 	qdflags[unit].curs_acc = ACC_OFF;
6087e911b15Skarels 	qdflags[unit].curs_thr = 128;
6097e911b15Skarels 	qdflags[unit].tab_res = 2;	/* default tablet resolution factor */
6107e911b15Skarels 	qdflags[unit].duart_imask = 0;	/* init shadow variables */
6117e911b15Skarels 	qdflags[unit].adder_ie = 0;
6127e911b15Skarels 
613b2b69f49Smarc 	/*
6147e911b15Skarels 	* init structures used in kbd/mouse interrupt service.	This code must
615b2b69f49Smarc 	* come after the "init_shared()" routine has run since that routine
616b2b69f49Smarc 	* inits the eq_header[unit] structure used here.
617b2b69f49Smarc 	*/
6187e911b15Skarels 
619b2b69f49Smarc 	/*
620b2b69f49Smarc 	* init the "latest mouse report" structure
621b2b69f49Smarc 	*/
6227e911b15Skarels 	last_rep[unit].state = 0;
6237e911b15Skarels 	last_rep[unit].dx = 0;
6247e911b15Skarels 	last_rep[unit].dy = 0;
6257e911b15Skarels 	last_rep[unit].bytcnt = 0;
6267e911b15Skarels 
627b2b69f49Smarc 	/*
6287881ece5Smarc 	* init the event queue (except mouse position)
6297881ece5Smarc 	*/
6307881ece5Smarc 	eq_header[unit]->header.events =
6317881ece5Smarc 	    (struct _vs_event *)((int)eq_header[unit] + sizeof(struct qdinput));
6327e911b15Skarels 
6337e911b15Skarels 	eq_header[unit]->header.size = MAXEVENTS;
6347e911b15Skarels 	eq_header[unit]->header.head = 0;
6357e911b15Skarels 	eq_header[unit]->header.tail = 0;
6367e911b15Skarels 
637b2b69f49Smarc 	/*
638b2b69f49Smarc 	 * open exclusive for graphics device.
639b2b69f49Smarc 	 */
640b2b69f49Smarc 	qdopened[unit] = 0;
6417e911b15Skarels 
6427e911b15Skarels } /* qdattach */
6437e911b15Skarels 
6447881ece5Smarc /*ARGSUSED*/
6457e911b15Skarels qdopen(dev, flag)
6467e911b15Skarels 	dev_t dev;
6477e911b15Skarels 	int flag;
6487e911b15Skarels {
6497e911b15Skarels 	register struct uba_device *ui; /* ptr to uba structures */
6507e911b15Skarels 	register struct dga *dga;	/* ptr to gate array struct */
6517e911b15Skarels 	register struct tty *tp;
6527e911b15Skarels 	struct duart *duart;
6537881ece5Smarc 	int unit;
6547881ece5Smarc 	int minor_dev;
6557e911b15Skarels 
6567e911b15Skarels 	minor_dev = minor(dev); /* get QDSS minor device number */
6577e911b15Skarels 	unit = minor_dev >> 2;
6587e911b15Skarels 
659b2b69f49Smarc 	/*
660b2b69f49Smarc 	* check for illegal conditions
661b2b69f49Smarc 	*/
6627e911b15Skarels 	ui = qdinfo[unit];		/* get ptr to QDSS device struct */
6637e911b15Skarels 	if (ui == 0  || ui->ui_alive == 0)
6647e911b15Skarels 		return(ENXIO);		/* no such device or address */
6657e911b15Skarels 
6667e911b15Skarels 	duart = (struct duart *) qdmap[unit].duart;
6677e911b15Skarels 	dga = (struct dga *) qdmap[unit].dga;
6687e911b15Skarels 
6697e911b15Skarels 	if ((minor_dev & 0x03) == 2) {
670b2b69f49Smarc 		/*
671b2b69f49Smarc 		* this is the graphic device...
672b2b69f49Smarc 		*/
673b2b69f49Smarc 		if (qdopened[unit] != 0)
6747e911b15Skarels 			return(EBUSY);
6757e911b15Skarels 		else
676b2b69f49Smarc 			qdopened[unit] = 1;
6777e911b15Skarels 		qdflags[unit].inuse |= GRAPHIC_DEV;  /* graphics dev is open */
678b2b69f49Smarc 		/*
679b2b69f49Smarc 		 * enble kbd & mouse intrpts in DUART mask reg
680b2b69f49Smarc 		 */
6817e911b15Skarels 		qdflags[unit].duart_imask |= 0x22;
6827e911b15Skarels 		duart->imask = qdflags[unit].duart_imask;
683b2b69f49Smarc 	} else {
684b2b69f49Smarc 		/*
685b2b69f49Smarc 		* this is the console
686b2b69f49Smarc 		*/
6877e911b15Skarels 		qdflags[unit].inuse |= CONS_DEV;  /* mark console as open */
6887e911b15Skarels 		dga->csr |= CURS_ENB;
6897e911b15Skarels 		qdflags[unit].duart_imask |= 0x02;
6907e911b15Skarels 		duart->imask = qdflags[unit].duart_imask;
691b2b69f49Smarc 		/*
692b2b69f49Smarc 		* some setup for tty handling
693b2b69f49Smarc 		*/
6947e911b15Skarels 		tp = &qd_tty[minor_dev];
6957e911b15Skarels 		tp->t_addr = ui->ui_addr;
6967e911b15Skarels 		tp->t_oproc = qdstart;
6977e911b15Skarels 		if ((tp->t_state & TS_ISOPEN) == 0) {
6987e911b15Skarels 			ttychars(tp);
699e977faadSmarc 			tp->t_flags = IFLAGS;
7007e911b15Skarels 			tp->t_ispeed = B9600;
7017e911b15Skarels 			tp->t_ospeed = B9600;
702e977faadSmarc 			tp->t_state = TS_ISOPEN | TS_CARR_ON;
703b2b69f49Smarc #ifdef POSIXTTY
704b2b69f49Smarc 			tp->t_iflag = TTYDEF_IFLAG;
705b2b69f49Smarc 			tp->t_oflag = TTYDEF_OFLAG;
706b2b69f49Smarc 			tp->t_lflag = TTYDEF_LFLAG;
707b2b69f49Smarc 			tp->t_cflag = TTYDEF_CFLAG;
708b2b69f49Smarc #endif
709e977faadSmarc 		}
710b2b69f49Smarc 		/*
711b2b69f49Smarc 		* enable intrpts, open line discipline
712b2b69f49Smarc 		*/
7137e911b15Skarels 		dga->csr |= GLOBAL_IE;	/* turn on the interrupts */
7147e911b15Skarels 		return ((*linesw[tp->t_line].l_open)(dev, tp));
7157e911b15Skarels 	}
7167e911b15Skarels 	dga->csr |= GLOBAL_IE;	/* turn on the interrupts */
7177e911b15Skarels 	return(0);
7187e911b15Skarels 
7197e911b15Skarels } /* qdopen */
7207e911b15Skarels 
7217881ece5Smarc /*ARGSUSED*/
7227e911b15Skarels qdclose(dev, flag)
7237e911b15Skarels 	dev_t dev;
7247e911b15Skarels 	int flag;
7257e911b15Skarels {
7267e911b15Skarels 	register struct tty *tp;
7277e911b15Skarels 	register struct qdmap *qd;
7287e911b15Skarels 	register int *ptep;
7297e911b15Skarels 	struct dga *dga;		/* gate array register map pointer */
7307e911b15Skarels 	struct duart *duart;
7317e911b15Skarels 	struct adder *adder;
7327881ece5Smarc 	int unit;
7337881ece5Smarc 	int minor_dev;
7347e911b15Skarels 	u_int mapix;
735b2b69f49Smarc 	int i;				/* SIGNED index */
7367e911b15Skarels 
7377e911b15Skarels 	minor_dev = minor(dev); 	/* get minor device number */
7387e911b15Skarels 	unit = minor_dev >> 2;		/* get QDSS number */
7397e911b15Skarels 	qd = &qdmap[unit];
7407e911b15Skarels 
7417e911b15Skarels 	if ((minor_dev & 0x03) == 2) {
742b2b69f49Smarc 		/*
743b2b69f49Smarc 		* this is the graphic device...
744b2b69f49Smarc 		*/
745b2b69f49Smarc 		if (qdopened[unit] != 1)
7467e911b15Skarels 		    	return(EBUSY);
7477e911b15Skarels 		else
748b2b69f49Smarc 			qdopened[unit] = 0;	/* allow it to be re-opened */
749b2b69f49Smarc 		/*
750b2b69f49Smarc 		* re-protect device memory
751b2b69f49Smarc 		*/
7527e911b15Skarels 		if (qdflags[unit].mapped & MAPDEV) {
753b2b69f49Smarc 			/*
754b2b69f49Smarc 			* TEMPLATE RAM
755b2b69f49Smarc 			*/
75624f67f6bSmarc 			mapix = VTOP((int)qd->template) - VTOP(qvmem[0]);
75724f67f6bSmarc 			ptep = (int *)(QVmap[0] + mapix);
7587881ece5Smarc 			for (i = 0; i < btop(TMPSIZE); i++, ptep++)
7597881ece5Smarc 				*ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
760b2b69f49Smarc 			/*
761b2b69f49Smarc 			* ADDER
762b2b69f49Smarc 			*/
76324f67f6bSmarc 			mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]);
76424f67f6bSmarc 			ptep = (int *)(QVmap[0] + mapix);
7657881ece5Smarc 			for (i = 0; i < btop(REGSIZE); i++, ptep++)
7667881ece5Smarc 				*ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
767b2b69f49Smarc 			/*
768b2b69f49Smarc 			* COLOR MAPS
769b2b69f49Smarc 			*/
77024f67f6bSmarc 			mapix = VTOP((int)qd->red) - VTOP(qvmem[0]);
77124f67f6bSmarc 			ptep = (int *)(QVmap[0] + mapix);
7727881ece5Smarc 			for (i = 0; i < btop(CLRSIZE); i++, ptep++)
7737881ece5Smarc 				*ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
7747e911b15Skarels 		}
7757e911b15Skarels 
776b2b69f49Smarc 		/*
777b2b69f49Smarc 		* re-protect DMA buffer and free the map registers
778b2b69f49Smarc 		*/
7797e911b15Skarels 		if (qdflags[unit].mapped & MAPDMA) {
7807e911b15Skarels 			dga = (struct dga *) qdmap[unit].dga;
7817e911b15Skarels 			adder = (struct adder *) qdmap[unit].adder;
7827e911b15Skarels 			dga->csr &= ~DMA_IE;
7837e911b15Skarels 			dga->csr &= ~0x0600;	     /* kill DMA */
7847e911b15Skarels 			adder->command = CANCEL;
785b2b69f49Smarc 			/*
786b2b69f49Smarc 			 * if DMA was running, flush spurious intrpt
787b2b69f49Smarc 			 */
7887e911b15Skarels 			if (dga->bytcnt_lo != 0) {
7897e911b15Skarels 				dga->bytcnt_lo = 0;
7907e911b15Skarels 				dga->bytcnt_hi = 0;
7917e911b15Skarels 				DMA_SETIGNORE(DMAheader[unit]);
7927e911b15Skarels 				dga->csr |= DMA_IE;
7937e911b15Skarels 				dga->csr &= ~DMA_IE;
7947e911b15Skarels 			}
7957e911b15Skarels 			ptep = (int *)
7967e911b15Skarels 			   ((VTOP(DMAheader[unit]*4)) + (mfpr(SBR)|0x80000000));
7977881ece5Smarc 			for (i = 0; i < btop(DMAbuf_size); i++, ptep++)
7987881ece5Smarc 				*ptep = (*ptep & ~PG_PROT) | PG_V | PG_KW;
7997e911b15Skarels 			ubarelse(0, &Qbus_unmap[unit]);
8007e911b15Skarels 		}
8017e911b15Skarels 
802b2b69f49Smarc 		/*
803b2b69f49Smarc 		* re-protect 1K (2 pages) event queue
804b2b69f49Smarc 		*/
8057e911b15Skarels 		if (qdflags[unit].mapped & MAPEQ) {
8067e911b15Skarels 			ptep = (int *)
8077e911b15Skarels 			   ((VTOP(eq_header[unit])*4) + (mfpr(SBR)|0x80000000));
8087881ece5Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++;
8097e911b15Skarels 			*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
8107e911b15Skarels 		}
811b2b69f49Smarc 		/*
812b2b69f49Smarc 		* re-protect scroll param area and disable scroll intrpts
813b2b69f49Smarc 		*/
8147e911b15Skarels 		if (qdflags[unit].mapped & MAPSCR) {
8157e911b15Skarels 			ptep = (int *) ((VTOP(scroll[unit]) * 4)
8167e911b15Skarels 				+ (mfpr(SBR) | 0x80000000));
817b2b69f49Smarc 			/*
818b2b69f49Smarc 			 * re-protect 512 scroll param area
819b2b69f49Smarc 			 */
8207e911b15Skarels 			*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
8217e911b15Skarels 			adder = (struct adder *) qdmap[unit].adder;
8227e911b15Skarels 			qdflags[unit].adder_ie &= ~FRAME_SYNC;
8237e911b15Skarels 			adder->interrupt_enable = qdflags[unit].adder_ie;
8247e911b15Skarels 		}
825b2b69f49Smarc 		/*
826b2b69f49Smarc 		* re-protect color map write buffer area and kill intrpts
827b2b69f49Smarc 		*/
8287e911b15Skarels 		if (qdflags[unit].mapped & MAPCOLOR) {
8297e911b15Skarels 			ptep = (int *) ((VTOP(color_buf[unit]) * 4)
8307e911b15Skarels 				+ (mfpr(SBR) | 0x80000000));
8317881ece5Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++;
8327e911b15Skarels 			*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
8337e911b15Skarels 			color_buf[unit]->status = 0;
8347e911b15Skarels 			adder = (struct adder *) qdmap[unit].adder;
8357e911b15Skarels 			qdflags[unit].adder_ie &= ~VSYNC;
8367e911b15Skarels 			adder->interrupt_enable = qdflags[unit].adder_ie;
8377e911b15Skarels 		}
838b2b69f49Smarc 		mtpr(TBIA, 0);
839b2b69f49Smarc 		/* flag everything now unmapped */
840b2b69f49Smarc 		qdflags[unit].mapped = 0;
8417e911b15Skarels 		qdflags[unit].inuse &= ~GRAPHIC_DEV;
8427e911b15Skarels 		qdflags[unit].curs_acc = ACC_OFF;
8437e911b15Skarels 		qdflags[unit].curs_thr = 128;
844b2b69f49Smarc 		/*
845b2b69f49Smarc 		* restore the console
846b2b69f49Smarc 		*/
8477e911b15Skarels 		dga = (struct dga *) qdmap[unit].dga;
8487e911b15Skarels 		adder = (struct adder *) qdmap[unit].adder;
8497e911b15Skarels 		dga->csr &= ~DMA_IE;
8507e911b15Skarels 		dga->csr &= ~0x0600;	/* halt the DMA! (just in case...) */
8517e911b15Skarels 		dga->csr |= DMA_ERR;	/* clear error condition */
8527e911b15Skarels 		adder->command = CANCEL;
853b2b69f49Smarc 		/*
854b2b69f49Smarc 		 * if DMA was running, flush spurious intrpt
855b2b69f49Smarc 		 */
8567e911b15Skarels 		if (dga->bytcnt_lo != 0) {
8577e911b15Skarels 			dga->bytcnt_lo = 0;
8587e911b15Skarels 			dga->bytcnt_hi = 0;
8597e911b15Skarels 			DMA_SETIGNORE(DMAheader[unit]);
8607e911b15Skarels 			dga->csr |= DMA_IE;
8617e911b15Skarels 			dga->csr &= ~DMA_IE;
8627e911b15Skarels 		}
8637e911b15Skarels 		init_shared(unit);		/* init shared memory */
8647e911b15Skarels 		setup_dragon(unit);		/* init ADDER/VIPER */
8657e911b15Skarels 		ldcursor(unit, cons_cursor);	/* load default cursor map */
8667e911b15Skarels 		setup_input(unit);		/* init the DUART */
8677e911b15Skarels 		ldfont(unit);
8687e911b15Skarels 		cursor[unit].x = 0;
8697e911b15Skarels 		cursor[unit].y = 0;
870b2b69f49Smarc 		/*
871b2b69f49Smarc 		 * shut off the mouse rcv intrpt and turn on kbd intrpts
872b2b69f49Smarc 		 */
8737e911b15Skarels 		duart = (struct duart *) qdmap[unit].duart;
8747e911b15Skarels 		qdflags[unit].duart_imask &= ~(0x20);
8757e911b15Skarels 		qdflags[unit].duart_imask |= 0x02;
8767e911b15Skarels 		duart->imask = qdflags[unit].duart_imask;
877b2b69f49Smarc 		/*
878b2b69f49Smarc 		* shut off interrupts if all is closed
879b2b69f49Smarc 		*/
880b2b69f49Smarc 		if (!(qdflags[unit].inuse & CONS_DEV)) {
8817e911b15Skarels 			dga = (struct dga *) qdmap[unit].dga;
8827e911b15Skarels 			dga->csr &= ~(GLOBAL_IE | DMA_IE);
8837e911b15Skarels 		}
884b2b69f49Smarc 	} else {
885b2b69f49Smarc 		/*
886b2b69f49Smarc 		* this is the console
887b2b69f49Smarc 		*/
8887e911b15Skarels 		tp = &qd_tty[minor_dev];
8897e911b15Skarels 		(*linesw[tp->t_line].l_close)(tp);
8907e911b15Skarels 		ttyclose(tp);
8917e911b15Skarels 		tp->t_state = 0;
8927e911b15Skarels 		qdflags[unit].inuse &= ~CONS_DEV;
893b2b69f49Smarc 		/*
894b2b69f49Smarc 		* if graphics device is closed, kill interrupts
895b2b69f49Smarc 		*/
8967e911b15Skarels 		if (!(qdflags[unit].inuse & GRAPHIC_DEV)) {
8977e911b15Skarels 			dga = (struct dga *) qdmap[unit].dga;
8987e911b15Skarels 			dga->csr &= ~(GLOBAL_IE | DMA_IE);
8997e911b15Skarels 		}
9007e911b15Skarels 	}
9017e911b15Skarels 
9027e911b15Skarels 	return(0);
9037e911b15Skarels 
9047e911b15Skarels } /* qdclose */
9057e911b15Skarels 
9067e911b15Skarels qdioctl(dev, cmd, datap, flags)
9077e911b15Skarels 	dev_t dev;
9087e911b15Skarels 	int cmd;
9097881ece5Smarc 	register caddr_t datap;
9107e911b15Skarels 	int flags;
9117e911b15Skarels {
9127e911b15Skarels 	register int *ptep;		/* page table entry pointer */
91324f67f6bSmarc 	register int mapix;		/* QVmap[] page table index */
9147e911b15Skarels 	register struct _vs_event *event;
9157e911b15Skarels 	register struct tty *tp;
9167881ece5Smarc 	register i;
9177e911b15Skarels 	struct qdmap *qd;		/* pointer to device map struct */
9187e911b15Skarels 	struct dga *dga;		/* Gate Array reg structure pntr */
9197e911b15Skarels 	struct duart *duart;		/* DUART reg structure pointer */
9207e911b15Skarels 	struct adder *adder;		/* ADDER reg structure pointer */
9217e911b15Skarels 	struct prgkbd *cmdbuf;
9227e911b15Skarels 	struct prg_cursor *curs;
9237e911b15Skarels 	struct _vs_cursor *pos;
9247881ece5Smarc 	int unit = minor(dev) >> 2;	/* number of caller's QDSS */
9257e911b15Skarels 	u_int minor_dev = minor(dev);
9267e911b15Skarels 	int error;
9277e911b15Skarels 	int s;
9287e911b15Skarels 	short *temp;			/* a pointer to template RAM */
9297e911b15Skarels 
930b2b69f49Smarc 	/*
931b2b69f49Smarc 	* service graphic device ioctl commands
932b2b69f49Smarc 	*/
9337e911b15Skarels 	switch (cmd) {
934e977faadSmarc 
9357e911b15Skarels 	case QD_GETEVENT:
936b2b69f49Smarc 		/*
937b2b69f49Smarc 		* extract the oldest event from the event queue
938b2b69f49Smarc 		*/
9397e911b15Skarels 		if (ISEMPTY(eq_header[unit])) {
9407e911b15Skarels 			event = (struct _vs_event *) datap;
9417e911b15Skarels 			event->vse_device = VSE_NULL;
9427e911b15Skarels 			break;
9437e911b15Skarels 		}
9447e911b15Skarels 		event = (struct _vs_event *) GETBEGIN(eq_header[unit]);
945e977faadSmarc 		s = spl5();
9467e911b15Skarels 		GETEND(eq_header[unit]);
9477e911b15Skarels 		splx(s);
9487881ece5Smarc 		bcopy((caddr_t)event, datap, sizeof(struct _vs_event));
9497e911b15Skarels 		break;
9507e911b15Skarels 
9517e911b15Skarels 	case QD_RESET:
952b2b69f49Smarc 		/*
953b2b69f49Smarc 		* init the dragon stuff, DUART, and driver variables
954b2b69f49Smarc 		*/
9557e911b15Skarels 		init_shared(unit);		/* init shared memory */
9567e911b15Skarels 		setup_dragon(unit);	      /* init the ADDER/VIPER stuff */
9577e911b15Skarels 		clear_qd_screen(unit);
9587e911b15Skarels 		ldcursor(unit, cons_cursor);	/* load default cursor map */
9597e911b15Skarels 		ldfont(unit);			/* load the console font */
9607e911b15Skarels 		setup_input(unit);		/* init the DUART */
9617e911b15Skarels 		break;
9627e911b15Skarels 
9637e911b15Skarels 	case QD_SET:
964b2b69f49Smarc 		/*
965b2b69f49Smarc 		* init the DUART and driver variables
966b2b69f49Smarc 		*/
9677e911b15Skarels 		init_shared(unit);
9687e911b15Skarels 		setup_input(unit);
9697e911b15Skarels 		break;
9707e911b15Skarels 
9717e911b15Skarels 	case QD_CLRSCRN:
972b2b69f49Smarc 		/*
973b2b69f49Smarc 		* clear the QDSS screen.  (NOTE that this reinits the dragon)
974b2b69f49Smarc 		*/
9757881ece5Smarc #ifdef notdef	/* has caused problems and isn't necessary */
9767e911b15Skarels 		setup_dragon(unit);
9777e911b15Skarels 		clear_qd_screen(unit);
978e977faadSmarc #endif
9797e911b15Skarels 		break;
9807e911b15Skarels 
9817e911b15Skarels 	case QD_WTCURSOR:
982b2b69f49Smarc 		/*
983b2b69f49Smarc 		* load a cursor into template RAM
984b2b69f49Smarc 		*/
9857881ece5Smarc 		ldcursor(unit, (short *)datap);
9867e911b15Skarels 		break;
9877e911b15Skarels 
9887e911b15Skarels 	case QD_RDCURSOR:
9897e911b15Skarels 
9907e911b15Skarels 		temp = (short *) qdmap[unit].template;
991b2b69f49Smarc 		/*
992b2b69f49Smarc 		 * cursor is 32 WORDS from the end of the 8k WORD...
993b2b69f49Smarc 		 *  ...template space
994b2b69f49Smarc 		 */
9957e911b15Skarels 		temp += (8 * 1024) - 32;
9967e911b15Skarels 		for (i = 0; i < 32; ++i, datap += sizeof(short))
9977e911b15Skarels 			*(short *)datap = *temp++;
9987e911b15Skarels 		break;
9997e911b15Skarels 
10007e911b15Skarels 	case QD_POSCURSOR:
1001b2b69f49Smarc 		/*
1002b2b69f49Smarc 		* position the mouse cursor
1003b2b69f49Smarc 		*/
10047e911b15Skarels 		dga = (struct dga *) qdmap[unit].dga;
10057e911b15Skarels 		pos = (struct _vs_cursor *) datap;
1006e977faadSmarc 		s = spl5();
10077e911b15Skarels 		dga->x_cursor = TRANX(pos->x);
10087e911b15Skarels 		dga->y_cursor = TRANY(pos->y);
10097e911b15Skarels 		eq_header[unit]->curs_pos.x = pos->x;
10107e911b15Skarels 		eq_header[unit]->curs_pos.y = pos->y;
10117e911b15Skarels 		splx(s);
10127e911b15Skarels 		break;
10137e911b15Skarels 
10147e911b15Skarels 	case QD_PRGCURSOR:
1015b2b69f49Smarc 		/*
1016b2b69f49Smarc 		* set the cursor acceleration factor
1017b2b69f49Smarc 		*/
10187e911b15Skarels 		curs = (struct prg_cursor *) datap;
1019e977faadSmarc 		s = spl5();
10207e911b15Skarels 		qdflags[unit].curs_acc = curs->acc_factor;
10217e911b15Skarels 		qdflags[unit].curs_thr = curs->threshold;
10227e911b15Skarels 		splx(s);
10237e911b15Skarels 		break;
10247e911b15Skarels 
10257e911b15Skarels 	case QD_MAPDEVICE:
1026b2b69f49Smarc 		/*
1027b2b69f49Smarc 		* enable 'user write' to device pages
1028b2b69f49Smarc 		*/
10297e911b15Skarels 		qdflags[unit].mapped |= MAPDEV;
10307e911b15Skarels 		qd = (struct qdmap *) &qdmap[unit];
1031b2b69f49Smarc 		/*
1032b2b69f49Smarc 		* enable user write to template RAM
1033b2b69f49Smarc 		*/
103424f67f6bSmarc 		mapix = VTOP((int)qd->template) - VTOP(qvmem[0]);
103524f67f6bSmarc 		ptep = (int *)(QVmap[0] + mapix);
10367881ece5Smarc 		for (i = 0; i < btop(TMPSIZE); i++, ptep++)
10377881ece5Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
1038b2b69f49Smarc 		/*
1039b2b69f49Smarc 		* enable user write to registers
1040b2b69f49Smarc 		*/
104124f67f6bSmarc 		mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]);
104224f67f6bSmarc 		ptep = (int *)(QVmap[0] + mapix);
10437881ece5Smarc 		for (i = 0; i < btop(REGSIZE); i++, ptep++)
10447881ece5Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
1045b2b69f49Smarc 		/*
1046b2b69f49Smarc 		* enable user write to color maps
1047b2b69f49Smarc 		*/
104824f67f6bSmarc 		mapix = VTOP((int)qd->red) - VTOP(qvmem[0]);
104924f67f6bSmarc 		ptep = (int *)(QVmap[0] + mapix);
10507881ece5Smarc 		for (i = 0; i < btop(CLRSIZE); i++, ptep++)
10517881ece5Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
1052b2b69f49Smarc 		/*
1053b2b69f49Smarc 		* enable user write to DUART
1054b2b69f49Smarc 		*/
105524f67f6bSmarc 		mapix = VTOP((int)qd->duart) - VTOP(qvmem[0]);
105624f67f6bSmarc 		ptep = (int *)(QVmap[0] + mapix);
10577e911b15Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; /* duart page */
10587e911b15Skarels 
10597881ece5Smarc 		mtpr(TBIA, 0);		/* invalidate translation buffer */
10607e911b15Skarels 
1061b2b69f49Smarc 		/*
1062b2b69f49Smarc 		 * stuff qdmap structure in return buffer
1063b2b69f49Smarc 		 */
10647881ece5Smarc 		bcopy((caddr_t)qd, datap, sizeof(struct qdmap));
10657e911b15Skarels 		break;
10667e911b15Skarels 
10677e911b15Skarels 	case QD_MAPIOBUF:
1068b2b69f49Smarc 		/*
1069b2b69f49Smarc 		 * do setup for DMA by user process
1070b2b69f49Smarc 		 *
1071b2b69f49Smarc 		 * set 'user write enable' bits for DMA buffer
1072b2b69f49Smarc 		 */
10737e911b15Skarels 		qdflags[unit].mapped |= MAPDMA;
10747e911b15Skarels 		ptep = (int *) ((VTOP(DMAheader[unit]) * 4)
10757e911b15Skarels 			+ (mfpr(SBR) | 0x80000000));
10767881ece5Smarc 		for (i = 0; i < btop(DMAbuf_size); i++, ptep++)
10777881ece5Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
10787881ece5Smarc 		mtpr(TBIA, 0);		/* invalidate translation buffer */
1079b2b69f49Smarc 		/*
1080b2b69f49Smarc 		* set up QBUS map registers for DMA
1081b2b69f49Smarc 		*/
10827e911b15Skarels 		DMAheader[unit]->QBAreg =
10837881ece5Smarc 		    uballoc(0, (caddr_t)DMAheader[unit], DMAbuf_size, 0);
10847e911b15Skarels 		if (DMAheader[unit]->QBAreg == 0)
10857881ece5Smarc 		    printf("qd%d: qdioctl: QBA setup error\n", unit);
10867e911b15Skarels 		Qbus_unmap[unit] = DMAheader[unit]->QBAreg;
10877e911b15Skarels 		DMAheader[unit]->QBAreg &= 0x3FFFF;
1088b2b69f49Smarc 		/*
1089b2b69f49Smarc 		* return I/O buf adr
1090b2b69f49Smarc 		*/
10917e911b15Skarels 		*(int *)datap = (int) DMAheader[unit];
10927e911b15Skarels 		break;
10937e911b15Skarels 
10947e911b15Skarels 	case QD_MAPSCROLL:
1095b2b69f49Smarc 		/*
1096b2b69f49Smarc 		* map the shared scroll param area and enable scroll interpts
1097b2b69f49Smarc 		*/
10987e911b15Skarels 		qdflags[unit].mapped |= MAPSCR;
10997e911b15Skarels 		ptep = (int *) ((VTOP(scroll[unit]) * 4)
11007e911b15Skarels 			+ (mfpr(SBR) | 0x80000000));
1101b2b69f49Smarc 		/*
1102b2b69f49Smarc 		 * allow user write to scroll area
1103b2b69f49Smarc 		 */
11047e911b15Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
11057881ece5Smarc 		mtpr(TBIA, 0);			/* invalidate translation buf */
11067e911b15Skarels 		scroll[unit]->status = 0;
11077e911b15Skarels 		adder = (struct adder *) qdmap[unit].adder;
11087e911b15Skarels 		qdflags[unit].adder_ie |= FRAME_SYNC;
11097e911b15Skarels 		adder->interrupt_enable = qdflags[unit].adder_ie;
1110b2b69f49Smarc 		*(int *)datap = (int) scroll[unit]; /* return scroll area */
11117e911b15Skarels 		break;
11127e911b15Skarels 
11137e911b15Skarels 	case QD_UNMAPSCROLL:
1114b2b69f49Smarc 		/*
1115b2b69f49Smarc 		* unmap shared scroll param area and disable scroll intrpts
1116b2b69f49Smarc 		*/
11177e911b15Skarels 		if (qdflags[unit].mapped & MAPSCR) {
11187e911b15Skarels 			qdflags[unit].mapped &= ~MAPSCR;
11197e911b15Skarels 			ptep = (int *) ((VTOP(scroll[unit]) * 4)
11207e911b15Skarels 				+ (mfpr(SBR) | 0x80000000));
1121b2b69f49Smarc 			/*
1122b2b69f49Smarc 			 * re-protect 512 scroll param area
1123b2b69f49Smarc 			 */
11247e911b15Skarels 			*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
11257e911b15Skarels 			mtpr(TBIA, 0);	/* smash CPU's translation buf */
11267e911b15Skarels 			adder = (struct adder *) qdmap[unit].adder;
11277e911b15Skarels 			qdflags[unit].adder_ie &= ~FRAME_SYNC;
11287e911b15Skarels 			adder->interrupt_enable = qdflags[unit].adder_ie;
11297e911b15Skarels 		}
11307e911b15Skarels 		break;
11317e911b15Skarels 
11327e911b15Skarels 	case QD_MAPCOLOR:
1133b2b69f49Smarc 		/*
1134b2b69f49Smarc 		* map shared color map write buf and turn on vsync intrpt
1135b2b69f49Smarc 		*/
11367e911b15Skarels 		qdflags[unit].mapped |= MAPCOLOR;
11377e911b15Skarels 		ptep = (int *) ((VTOP(color_buf[unit]) * 4)
11387e911b15Skarels 			+ (mfpr(SBR) | 0x80000000));
11397881ece5Smarc 		/*
11407881ece5Smarc 		 * allow user write to color map write buffer
11417881ece5Smarc 		 */
11427881ece5Smarc 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; ptep++;
11437e911b15Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
11447e911b15Skarels 		mtpr(TBIA, 0);			/* clr CPU translation buf */
1145b2b69f49Smarc 		adder = (struct adder *) qdmap[unit].adder;
11467e911b15Skarels 		qdflags[unit].adder_ie |= VSYNC;
11477e911b15Skarels 		adder->interrupt_enable = qdflags[unit].adder_ie;
11487881ece5Smarc 		/*
11497881ece5Smarc 		 * return color area address
11507881ece5Smarc 		 */
11517e911b15Skarels 		*(int *)datap = (int) color_buf[unit];
11527e911b15Skarels 		break;
11537e911b15Skarels 
11547e911b15Skarels 	case QD_UNMAPCOLOR:
1155b2b69f49Smarc 		/*
1156b2b69f49Smarc 		 * unmap shared color map write buffer and kill VSYNC intrpts
1157b2b69f49Smarc 		 */
11587e911b15Skarels 		if (qdflags[unit].mapped & MAPCOLOR) {
11597e911b15Skarels 			qdflags[unit].mapped &= ~MAPCOLOR;
11607e911b15Skarels 			ptep = (int *) ((VTOP(color_buf[unit]) * 4)
11617e911b15Skarels 				+ (mfpr(SBR) | 0x80000000));
11627881ece5Smarc 			/*
11637881ece5Smarc 			 * re-protect color map write buffer
11647881ece5Smarc 			 */
11657881ece5Smarc 			*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V; ptep++;
11667e911b15Skarels 			*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
11677881ece5Smarc 			mtpr(TBIA, 0);
11687e911b15Skarels 			adder = (struct adder *) qdmap[unit].adder;
11697e911b15Skarels 			qdflags[unit].adder_ie &= ~VSYNC;
11707e911b15Skarels 			adder->interrupt_enable = qdflags[unit].adder_ie;
11717e911b15Skarels 		}
11727e911b15Skarels 		break;
11737e911b15Skarels 
11747e911b15Skarels 	case QD_MAPEVENT:
1175b2b69f49Smarc 		/*
1176b2b69f49Smarc 		* give user write access to the event queue
1177b2b69f49Smarc 		*/
11787e911b15Skarels 		qdflags[unit].mapped |= MAPEQ;
11797e911b15Skarels 		ptep = (int *) ((VTOP(eq_header[unit]) * 4)
11807e911b15Skarels 			+ (mfpr(SBR) | 0x80000000));
11817881ece5Smarc 		/*
11827881ece5Smarc 		 * allow user write to 1K event queue
11837881ece5Smarc 		 */
11847881ece5Smarc 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; ptep++;
11857e911b15Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
11867e911b15Skarels 		mtpr(TBIA, 0);			/* clr CPU translation buf */
11877881ece5Smarc 		/*
11887881ece5Smarc 		 * return event queue address
11897881ece5Smarc 		 */
11907e911b15Skarels 		*(int *)datap = (int)eq_header[unit];
11917e911b15Skarels 		break;
11927e911b15Skarels 
11937e911b15Skarels 	case QD_PRGKBD:
1194b2b69f49Smarc 		/*
1195b2b69f49Smarc 		* pass caller's programming commands to LK201
1196b2b69f49Smarc 		*/
11977e911b15Skarels 		duart = (struct duart *)qdmap[unit].duart;
11987e911b15Skarels 		cmdbuf = (struct prgkbd *)datap;    /* pnt to kbd cmd buf */
1199b2b69f49Smarc 		/*
1200b2b69f49Smarc 		* send command
1201b2b69f49Smarc 		*/
12027e911b15Skarels 		for (i = 1000; i > 0; --i) {
12037881ece5Smarc 			if (duart->statusA&XMT_RDY) {
12047e911b15Skarels 				duart->dataA = cmdbuf->cmd;
12057e911b15Skarels 				break;
12067e911b15Skarels 			}
12077e911b15Skarels 		}
12087e911b15Skarels 		if (i == 0) {
12097881ece5Smarc 			printf("qd%d: qdioctl: timeout on XMT_RDY [1]\n", unit);
12107e911b15Skarels 			break;
12117e911b15Skarels 		}
1212b2b69f49Smarc 		/*
1213b2b69f49Smarc 		* send param1?
1214b2b69f49Smarc 		*/
12157e911b15Skarels 		if (cmdbuf->cmd & LAST_PARAM)
12167e911b15Skarels 			break;
12177e911b15Skarels 		for (i = 1000; i > 0; --i) {
12187881ece5Smarc 			if (duart->statusA&XMT_RDY) {
12197e911b15Skarels 				duart->dataA = cmdbuf->param1;
12207e911b15Skarels 				break;
12217e911b15Skarels 			}
12227e911b15Skarels 		}
12237e911b15Skarels 		if (i == 0) {
12247881ece5Smarc 			printf("qd%d: qdioctl: timeout on XMT_RDY [2]\n", unit);
12257e911b15Skarels 			break;
12267e911b15Skarels 		}
1227b2b69f49Smarc 		/*
1228b2b69f49Smarc 		* send param2?
1229b2b69f49Smarc 		*/
12307e911b15Skarels 		if (cmdbuf->param1 & LAST_PARAM)
12317e911b15Skarels 		    break;
12327e911b15Skarels 		for (i = 1000; i > 0; --i) {
12337881ece5Smarc 			if (duart->statusA&XMT_RDY) {
12347e911b15Skarels 				duart->dataA = cmdbuf->param2;
12357e911b15Skarels 				break;
12367e911b15Skarels 			}
12377e911b15Skarels 		}
12387e911b15Skarels 		if (i == 0) {
12397881ece5Smarc 			printf("qd%d: qdioctl: timeout on XMT_RDY [3]\n", unit);
12407e911b15Skarels 			break;
12417e911b15Skarels 		}
12427e911b15Skarels 		break;
12437e911b15Skarels 
12447e911b15Skarels 	case QD_PRGMOUSE:
1245b2b69f49Smarc 		/*
1246b2b69f49Smarc 		* pass caller's programming commands to the mouse
1247b2b69f49Smarc 		*/
12487e911b15Skarels 		duart = (struct duart *) qdmap[unit].duart;
12497e911b15Skarels 		for (i = 1000; i > 0; --i) {
12507881ece5Smarc 			if (duart->statusB&XMT_RDY) {
12517e911b15Skarels 				duart->dataB = *datap;
12527e911b15Skarels 				break;
12537e911b15Skarels 			}
12547e911b15Skarels 		}
12557e911b15Skarels 		if (i == 0) {
12567881ece5Smarc 			printf("qd%d: qdioctl: timeout on XMT_RDY [4]\n", unit);
12577e911b15Skarels 		}
12587e911b15Skarels 		break;
12597e911b15Skarels 
12607e911b15Skarels 	case QD_RDCONFIG:
1261b2b69f49Smarc 		/*
1262b2b69f49Smarc 		* get QDSS configuration word and return it
1263b2b69f49Smarc 		*/
12647e911b15Skarels 		*(short *)datap = qdflags[unit].config;
12657e911b15Skarels 		break;
12667e911b15Skarels 
1267e977faadSmarc 	case QD_KERN_LOOP:
1268e977faadSmarc 	case QD_KERN_UNLOOP:
1269b2b69f49Smarc 		/*
1270b2b69f49Smarc 		 * vestige from ultrix.  BSD uses TIOCCONS to redirect
1271b2b69f49Smarc 		 * kernel console output.
1272b2b69f49Smarc 		 */
1273e977faadSmarc 		break;
1274e977faadSmarc 
12757e911b15Skarels 	case QD_PRGTABLET:
1276b2b69f49Smarc 		/*
1277b2b69f49Smarc 		* program the tablet
1278b2b69f49Smarc 		*/
12797e911b15Skarels 		duart = (struct duart *) qdmap[unit].duart;
12807e911b15Skarels 		for (i = 1000; i > 0; --i) {
12817881ece5Smarc 			if (duart->statusB&XMT_RDY) {
12827e911b15Skarels 				duart->dataB = *datap;
12837e911b15Skarels 				break;
12847e911b15Skarels 			}
12857e911b15Skarels 		}
12867e911b15Skarels 		if (i == 0) {
12877881ece5Smarc 			printf("qd%d: qdioctl: timeout on XMT_RDY [5]\n", unit);
12887e911b15Skarels 		}
12897e911b15Skarels 		break;
12907e911b15Skarels 
12917e911b15Skarels 	case QD_PRGTABRES:
1292b2b69f49Smarc 		/*
1293b2b69f49Smarc 		* program the tablet report resolution factor
1294b2b69f49Smarc 		*/
12957e911b15Skarels 		qdflags[unit].tab_res = *(short *)datap;
12967e911b15Skarels 		break;
12978a2bf9b0Smarc 
12987e911b15Skarels 	default:
1299b2b69f49Smarc 		/*
1300b2b69f49Smarc 		* service tty ioctl's
1301b2b69f49Smarc 		*/
13027e911b15Skarels 		if (!(minor_dev & 0x02)) {
13037e911b15Skarels 			tp = &qd_tty[minor_dev];
1304b2b69f49Smarc 			error =
1305b2b69f49Smarc 			   (*linesw[tp->t_line].l_ioctl)(tp, cmd, datap, flags);
13067e911b15Skarels 			if (error >= 0) {
13077e911b15Skarels 				return(error);
13087e911b15Skarels 			}
13097e911b15Skarels 			error = ttioctl(tp, cmd, datap, flags);
13107e911b15Skarels 			if (error >= 0) {
13117e911b15Skarels 				return(error);
13127e911b15Skarels 			}
13137e911b15Skarels 		}
13147e911b15Skarels 		break;
13157e911b15Skarels 	}
13167e911b15Skarels 
13177e911b15Skarels 	return(0);
13187e911b15Skarels 
13197e911b15Skarels } /* qdioctl */
13207e911b15Skarels 
13217e911b15Skarels qdselect(dev, rw)
13227e911b15Skarels 	dev_t dev;
13237e911b15Skarels 	int rw;
13247e911b15Skarels {
13257881ece5Smarc 	register s;
13267881ece5Smarc 	register unit;
1327e977faadSmarc 	register struct tty *tp;
1328e977faadSmarc 	u_int minor_dev = minor(dev);
13297e911b15Skarels 
1330e977faadSmarc 	s = spl5();
1331e977faadSmarc 	unit = minor_dev >> 2;
13327e911b15Skarels 
13337e911b15Skarels 	switch (rw) {
1334e977faadSmarc 	case FREAD:
1335b2b69f49Smarc 		if ((minor_dev & 0x03) == 2) {
1336e977faadSmarc 			/*
1337e977faadSmarc 			* this is a graphics device, so check for events
1338e977faadSmarc 			*/
13397881ece5Smarc 			if(!(ISEMPTY(eq_header[unit]))) {
13407e911b15Skarels 				splx(s);
1341e977faadSmarc 				return(1);
13427e911b15Skarels 			}
13437881ece5Smarc 			qdrsel[unit] = u.u_procp;
13447e911b15Skarels 			qdflags[unit].selmask |= SEL_READ;
13457e911b15Skarels 			splx(s);
13467e911b15Skarels 			return(0);
1347b2b69f49Smarc 		} else {
1348e977faadSmarc 			/*
1349e977faadSmarc 			* this is a tty device
1350e977faadSmarc 			*/
1351e977faadSmarc 			tp = &qd_tty[minor_dev];
1352e977faadSmarc 			if (ttnread(tp))
1353e977faadSmarc 			    return(1);
1354e977faadSmarc 			tp->t_rsel = u.u_procp;
13557e911b15Skarels 			splx(s);
1356e977faadSmarc 			return(0);
1357e977faadSmarc 		}
1358e977faadSmarc 
1359e977faadSmarc 	case FWRITE:
1360b2b69f49Smarc 		if ((minor(dev) & 0x03) == 2) {
1361e977faadSmarc 			/*
1362e977faadSmarc 			* this is a graphics device, so check for dma buffers
1363e977faadSmarc 			*/
1364e977faadSmarc 			if (DMA_ISEMPTY(DMAheader[unit]))
1365e977faadSmarc 			    {
1366e977faadSmarc 				splx(s);
1367e977faadSmarc 				return(1);
13687e911b15Skarels 			}
13697881ece5Smarc 			qdrsel[unit] = u.u_procp;
13707e911b15Skarels 			qdflags[unit].selmask |= SEL_WRITE;
13717e911b15Skarels 			splx(s);
13727e911b15Skarels 			return(0);
1373b2b69f49Smarc 		} else {
1374e977faadSmarc 			/*
1375e977faadSmarc 			* this is a tty device
1376e977faadSmarc 			*/
1377e977faadSmarc 			tp = &qd_tty[minor_dev];
1378e977faadSmarc 			if (tp->t_outq.c_cc <= TTLOWAT(tp))
1379e977faadSmarc 			    return(1);
1380e977faadSmarc 			tp->t_wsel = u.u_procp;
1381e977faadSmarc 			splx(s);
1382e977faadSmarc 			return(0);
1383e977faadSmarc 		}
1384e977faadSmarc 	}
13857881ece5Smarc 	splx(s);
13867881ece5Smarc 	return(0);
13877e911b15Skarels 
13887e911b15Skarels } /* qdselect() */
13897e911b15Skarels 
13907e911b15Skarels extern qd_strategy();
13917e911b15Skarels 
13927e911b15Skarels qdwrite(dev, uio)
13937e911b15Skarels 	dev_t dev;
13947e911b15Skarels 	struct uio *uio;
13957e911b15Skarels {
13967e911b15Skarels 	register struct tty *tp;
13977881ece5Smarc 	register minor_dev;
13987881ece5Smarc 	register unit;
13997e911b15Skarels 
14007e911b15Skarels 	minor_dev = minor(dev);
14017e911b15Skarels 	unit = (minor_dev >> 2) & 0x07;
14027e911b15Skarels 
1403b2b69f49Smarc 	if (((minor_dev&0x03) != 0x02) && (qdflags[unit].inuse&CONS_DEV)) {
1404b2b69f49Smarc 		/*
1405b2b69f49Smarc 		* this is the console...
1406b2b69f49Smarc 		*/
14077e911b15Skarels 		tp = &qd_tty[minor_dev];
14087e911b15Skarels 		return ((*linesw[tp->t_line].l_write)(tp, uio));
1409b2b69f49Smarc 	} else if (qdflags[unit].inuse & GRAPHIC_DEV) {
1410b2b69f49Smarc 		/*
1411b2b69f49Smarc 		* this is a DMA xfer from user space
1412b2b69f49Smarc 		*/
14137e911b15Skarels 		return (physio(qd_strategy, &qdbuf[unit],
14147e911b15Skarels 		dev, B_WRITE, minphys, uio));
14157e911b15Skarels 	}
14167881ece5Smarc 	return (ENXIO);
14177e911b15Skarels }
14187e911b15Skarels 
14197e911b15Skarels qdread(dev, uio)
14207e911b15Skarels 	dev_t dev;
14217e911b15Skarels 	struct uio *uio;
14227e911b15Skarels {
14237e911b15Skarels 	register struct tty *tp;
14247881ece5Smarc 	register minor_dev;
14257881ece5Smarc 	register unit;
14267e911b15Skarels 
14277e911b15Skarels 	minor_dev = minor(dev);
14287e911b15Skarels 	unit = (minor_dev >> 2) & 0x07;
14297e911b15Skarels 
1430b2b69f49Smarc 	if ((minor_dev & 0x03) != 0x02 && qdflags[unit].inuse & CONS_DEV) {
1431b2b69f49Smarc 		/*
1432b2b69f49Smarc 		* this is the console
1433b2b69f49Smarc 		*/
14347e911b15Skarels 		tp = &qd_tty[minor_dev];
14357e911b15Skarels 		return ((*linesw[tp->t_line].l_read)(tp, uio));
1436b2b69f49Smarc 	} else if (qdflags[unit].inuse & GRAPHIC_DEV) {
1437b2b69f49Smarc 		/*
1438b2b69f49Smarc 		* this is a bitmap-to-processor xfer
1439b2b69f49Smarc 		*/
14407e911b15Skarels 		return (physio(qd_strategy, &qdbuf[unit],
14417e911b15Skarels 		dev, B_READ, minphys, uio));
14427e911b15Skarels 	}
14437881ece5Smarc 	return (ENXIO);
14447e911b15Skarels }
14457e911b15Skarels 
14467e911b15Skarels /***************************************************************
14477e911b15Skarels *
14487e911b15Skarels *	qd_strategy()... strategy routine to do DMA
14497e911b15Skarels *
14507e911b15Skarels ***************************************************************/
14517e911b15Skarels 
14527e911b15Skarels qd_strategy(bp)
14537e911b15Skarels 	register struct buf *bp;
14547e911b15Skarels {
14557e911b15Skarels 	register struct dga *dga;
14567e911b15Skarels 	register struct adder *adder;
14577881ece5Smarc 	register unit;
14587e911b15Skarels 	int QBAreg;
14597e911b15Skarels 	int s;
14607e911b15Skarels 	int cookie;
14617e911b15Skarels 
14627e911b15Skarels 	unit = (minor(bp->b_dev) >> 2) & 0x07;
14637e911b15Skarels 
1464b2b69f49Smarc 	/*
1465b2b69f49Smarc 	* init pointers
1466b2b69f49Smarc 	*/
14677e911b15Skarels 	if ((QBAreg = ubasetup(0, bp, 0)) == 0) {
14687881ece5Smarc 		printf("qd%d: qd_strategy: QBA setup error\n", unit);
14697e911b15Skarels 		goto STRAT_ERR;
14707e911b15Skarels 	}
14717e911b15Skarels 	dga = (struct dga *) qdmap[unit].dga;
1472e977faadSmarc 	s = spl5();
14737e911b15Skarels 	qdflags[unit].user_dma = -1;
14747e911b15Skarels 	dga->csr |= DMA_IE;
14757e911b15Skarels 	cookie = QBAreg & 0x3FFFF;
14767e911b15Skarels 	dga->adrs_lo = (short) cookie;
14777e911b15Skarels 	dga->adrs_hi = (short) (cookie >> 16);
14787e911b15Skarels 	dga->bytcnt_lo = (short) bp->b_bcount;
14797e911b15Skarels 	dga->bytcnt_hi = (short) (bp->b_bcount >> 16);
14807e911b15Skarels 
14817e911b15Skarels 	while (qdflags[unit].user_dma) {
14827e911b15Skarels 		sleep((caddr_t)&qdflags[unit].user_dma, QDPRIOR);
14837e911b15Skarels 	}
14847e911b15Skarels 	splx(s);
14857e911b15Skarels 	ubarelse(0, &QBAreg);
14867e911b15Skarels 	if (!(dga->csr & DMA_ERR)) {
14877e911b15Skarels 		iodone(bp);
14887e911b15Skarels 		return;
14897e911b15Skarels 	}
14907e911b15Skarels 
14917e911b15Skarels STRAT_ERR:
14927e911b15Skarels 	adder = (struct adder *) qdmap[unit].adder;
14937e911b15Skarels 	adder->command = CANCEL;	/* cancel adder activity */
14947e911b15Skarels 	dga->csr &= ~DMA_IE;
14957e911b15Skarels 	dga->csr &= ~0x0600;		/* halt DMA (reset fifo) */
14967e911b15Skarels 	dga->csr |= DMA_ERR;		/* clear error condition */
14977e911b15Skarels 	bp->b_flags |= B_ERROR; 	/* flag an error to physio() */
14987e911b15Skarels 
1499b2b69f49Smarc 	/*
1500b2b69f49Smarc 	 * if DMA was running, flush spurious intrpt
1501b2b69f49Smarc 	 */
15027e911b15Skarels 	if (dga->bytcnt_lo != 0) {
15037e911b15Skarels 		dga->bytcnt_lo = 0;
15047e911b15Skarels 		dga->bytcnt_hi = 0;
15057e911b15Skarels 		DMA_SETIGNORE(DMAheader[unit]);
15067e911b15Skarels 		dga->csr |= DMA_IE;
15077e911b15Skarels 	}
15087e911b15Skarels 	iodone(bp);
15097e911b15Skarels 
15107e911b15Skarels } /* qd_strategy */
15117e911b15Skarels 
15127881ece5Smarc /*
15137881ece5Smarc  *  Start output to the console screen
15147881ece5Smarc  */
15157e911b15Skarels qdstart(tp)
15167e911b15Skarels 	register struct tty *tp;
15177e911b15Skarels {
15187881ece5Smarc 	register which_unit, unit, c;
15197e911b15Skarels 	int s;
15207e911b15Skarels 
1521e977faadSmarc 	unit = minor(tp->t_dev);
1522e977faadSmarc 	which_unit = (unit >> 2) & 0x3;
1523e977faadSmarc 	unit &= 0x03;
1524e977faadSmarc 
1525e977faadSmarc 	s = spl5();
1526e977faadSmarc 
1527b2b69f49Smarc 	/*
1528b2b69f49Smarc 	* If it's currently active, or delaying, no need to do anything.
1529b2b69f49Smarc 	*/
15307e911b15Skarels 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
15317e911b15Skarels 		goto out;
15327e911b15Skarels 
1533b2b69f49Smarc 	/*
1534b2b69f49Smarc 	* Display chars until the queue is empty.
1535b2b69f49Smarc 	* Drop input from anything but the console
1536b2b69f49Smarc 	* device on the floor.
1537b2b69f49Smarc 	*
1538b2b69f49Smarc 	* XXX - this loop is done at spltty.
1539b2b69f49Smarc 	*
1540b2b69f49Smarc 	*/
15417e911b15Skarels 	while (tp->t_outq.c_cc) {
15427e911b15Skarels 		c = getc(&tp->t_outq);
1543e977faadSmarc 		if (unit == 0)
15447881ece5Smarc 			blitc(which_unit, (u_char)c);
15457e911b15Skarels 	}
1546b2b69f49Smarc 	/*
1547e977faadSmarc 	* If there are sleepers, and output has drained below low
1548b2b69f49Smarc 	* water mark, wake up the sleepers.
1549b2b69f49Smarc 	*/
1550e977faadSmarc 	if (tp->t_outq.c_cc <= TTLOWAT(tp)) {
15517e911b15Skarels 		if (tp->t_state & TS_ASLEEP){
15527e911b15Skarels 			tp->t_state &= ~TS_ASLEEP;
15537e911b15Skarels 			wakeup((caddr_t) &tp->t_outq);
15547e911b15Skarels 		}
1555e977faadSmarc 	}
1556e977faadSmarc 
1557e977faadSmarc 	tp->t_state &= ~TS_BUSY;
15587e911b15Skarels 
15597e911b15Skarels out:
15607e911b15Skarels 	splx(s);
15617e911b15Skarels 
15627e911b15Skarels } /* qdstart */
15637e911b15Skarels 
15647881ece5Smarc /*ARGSUSED*/
15657e911b15Skarels qdstop(tp, flag)
15667e911b15Skarels 	register struct tty *tp;
15677e911b15Skarels 	int flag;
15687e911b15Skarels {
15697e911b15Skarels 	register int s;
15707e911b15Skarels 
1571e977faadSmarc 	s = spl5();	/* block intrpts during state modification */
15727881ece5Smarc 	if (tp->t_state & TS_BUSY)
15737881ece5Smarc 		if ((tp->t_state & TS_TTSTOP) == 0)
15747e911b15Skarels 			tp->t_state |= TS_FLUSH;
1575b2b69f49Smarc 		else
15767e911b15Skarels 			tp->t_state &= ~TS_BUSY;
15777e911b15Skarels 	splx(s);
15787e911b15Skarels }
15797e911b15Skarels 
15807881ece5Smarc /*
15817881ece5Smarc  *  Output a character to the QDSS screen
15827881ece5Smarc  */
15837e911b15Skarels 
15847e911b15Skarels blitc(unit, chr)
15857881ece5Smarc 	register unit;
15867881ece5Smarc 	register u_char chr;
15877e911b15Skarels {
15887e911b15Skarels 	register struct adder *adder;
15897e911b15Skarels 	register struct dga *dga;
15907e911b15Skarels 	register int i;
1591b2b69f49Smarc 	int nograph = !(qdflags[unit].inuse&GRAPHIC_DEV);
1592b2b69f49Smarc 	static short inescape[NQD];
15937e911b15Skarels 
15947e911b15Skarels 	adder = (struct adder *)qdmap[unit].adder;
15957e911b15Skarels 	dga = (struct dga *) qdmap[unit].dga;
1596b2b69f49Smarc 	/*
1597b2b69f49Smarc 	 * BSD comment: this (&=0177) defeats the extended character
1598b2b69f49Smarc 	 * set code for the glass tty, but if i had the time i would
1599b2b69f49Smarc 	 * spend it ripping out the code completely.  This driver
1600b2b69f49Smarc 	 * is too big for its own good.
1601b2b69f49Smarc 	 */
1602b2b69f49Smarc 	chr &= 0177;
1603b2b69f49Smarc 	/*
16047881ece5Smarc 	 * Cursor addressing (so vi will work).
1605b2b69f49Smarc 	 * Decode for "\E=%.%." cursor motion description.
16067881ece5Smarc 	 * Corresponds to type "qdcons" in /etc/termcap:
1607b2b69f49Smarc 	 *
1608b2b69f49Smarc 	 *    qd|qdss|qdcons|qdss glass tty (4.4 BSD):\
1609b2b69f49Smarc 	 *      :am:do=^J:le=^H:bs:cm=\E=%.%.:cl=1^Z:co#128:li#57::nd=^L:up=^K:
1610b2b69f49Smarc 	 *
1611b2b69f49Smarc 	 */
1612b2b69f49Smarc 	if (inescape[unit] && nograph) {
1613b2b69f49Smarc 		switch (inescape[unit]++) {
1614b2b69f49Smarc 		case 1:
1615b2b69f49Smarc 			if (chr != '=') {
1616b2b69f49Smarc 				/* abort escape sequence */
1617b2b69f49Smarc 				inescape[unit] = 0;
1618b2b69f49Smarc 				blitc(unit, chr);
1619b2b69f49Smarc 			}
16207881ece5Smarc 			return;
1621b2b69f49Smarc 		case 2:
1622b2b69f49Smarc 			/* position row */
1623b2b69f49Smarc 			cursor[unit].y = CHAR_HEIGHT * chr;
1624b2b69f49Smarc 			if (cursor[unit].y > 863 - CHAR_HEIGHT)
1625b2b69f49Smarc 				cursor[unit].y = 863 - CHAR_HEIGHT;
1626b2b69f49Smarc 			dga->y_cursor = TRANY(cursor[unit].y);
16277881ece5Smarc 			return;
1628b2b69f49Smarc 		case 3:
1629b2b69f49Smarc 			/* position column */
1630b2b69f49Smarc 			cursor[unit].x = CHAR_WIDTH * chr;
1631b2b69f49Smarc 			if (cursor[unit].x > 1024 - CHAR_WIDTH)
1632b2b69f49Smarc 				cursor[unit].x = 1023 - CHAR_WIDTH;
1633b2b69f49Smarc 			dga->x_cursor = TRANX(cursor[unit].x);
1634b2b69f49Smarc 			inescape[unit] = 0;
16357881ece5Smarc 			return;
1636b2b69f49Smarc 		default:
1637b2b69f49Smarc 			inescape[unit] = 0;
1638b2b69f49Smarc 			blitc(unit, chr);
1639b2b69f49Smarc 		}
1640b2b69f49Smarc 	}
164124f67f6bSmarc 
16427e911b15Skarels 	switch (chr) {
16437e911b15Skarels 	case '\r':			/* return char */
16447e911b15Skarels 		cursor[unit].x = 0;
1645b2b69f49Smarc 		if (nograph)
16467e911b15Skarels 			dga->x_cursor = TRANX(cursor[unit].x);
16477881ece5Smarc 		return;
16487e911b15Skarels 
16497e911b15Skarels 	case '\t':			/* tab char */
16507e911b15Skarels 		for (i = 8 - ((cursor[unit].x >> 3) & 0x07); i > 0; --i) {
16517e911b15Skarels 			blitc(unit, ' ');
16527e911b15Skarels 		}
16537881ece5Smarc 		return;
16547e911b15Skarels 
16557e911b15Skarels 	case '\n':			/* line feed char */
16567e911b15Skarels 		if ((cursor[unit].y += CHAR_HEIGHT) > (863 - CHAR_HEIGHT)) {
1657b2b69f49Smarc 			if (nograph) {
16587e911b15Skarels 				cursor[unit].y -= CHAR_HEIGHT;
16597e911b15Skarels 				scroll_up(adder);
1660b2b69f49Smarc 			} else
1661b2b69f49Smarc 				cursor[unit].y = 0;
16627e911b15Skarels 		}
1663b2b69f49Smarc 		if (nograph)
16647e911b15Skarels 			dga->y_cursor = TRANY(cursor[unit].y);
16657881ece5Smarc 		return;
16667e911b15Skarels 
16677e911b15Skarels 	case '\b':			/* backspace char */
16687e911b15Skarels 		if (cursor[unit].x > 0) {
16697e911b15Skarels 			cursor[unit].x -= CHAR_WIDTH;
1670b2b69f49Smarc 			if (nograph)
1671b2b69f49Smarc 				dga->x_cursor = TRANX(cursor[unit].x);
1672b2b69f49Smarc 		}
16737881ece5Smarc 		return;
1674b2b69f49Smarc 	case CTRL('k'):		/* cursor up */
1675b2b69f49Smarc 		if (nograph && cursor[unit].y > 0) {
1676b2b69f49Smarc 			cursor[unit].y -= CHAR_HEIGHT;
1677b2b69f49Smarc 			dga->y_cursor = TRANY(cursor[unit].y);
1678b2b69f49Smarc 		}
16797881ece5Smarc 		return;
1680b2b69f49Smarc 
1681b2b69f49Smarc 	case CTRL('^'):		/* home cursor */
1682b2b69f49Smarc 		if (nograph) {
1683b2b69f49Smarc 			cursor[unit].x = 0;
1684b2b69f49Smarc 			dga->x_cursor = TRANX(cursor[unit].x);
1685b2b69f49Smarc 			cursor[unit].y = 0;
1686b2b69f49Smarc 			dga->y_cursor = TRANY(cursor[unit].y);
1687b2b69f49Smarc 		}
16887881ece5Smarc 		return;
1689b2b69f49Smarc 
1690b2b69f49Smarc 	case CTRL('l'):		/* cursor right */
1691b2b69f49Smarc 		if (nograph && cursor[unit].x < 1023 - CHAR_WIDTH) {
1692b2b69f49Smarc 			cursor[unit].x += CHAR_WIDTH;
16937e911b15Skarels 			dga->x_cursor = TRANX(cursor[unit].x);
16947e911b15Skarels 		}
16957881ece5Smarc 		return;
16967e911b15Skarels 
1697b2b69f49Smarc 	case CTRL('z'):		/* clear screen */
1698b2b69f49Smarc 		if (nograph) {
1699b2b69f49Smarc 			setup_dragon(unit);
1700b2b69f49Smarc 			clear_qd_screen(unit);
1701b2b69f49Smarc 			/* home cursor - termcap seems to assume this */
1702b2b69f49Smarc 			cursor[unit].x = 0;
1703b2b69f49Smarc 			dga->x_cursor = TRANX(cursor[unit].x);
1704b2b69f49Smarc 			cursor[unit].y = 0;
1705b2b69f49Smarc 			dga->y_cursor = TRANY(cursor[unit].y);
1706b2b69f49Smarc 		}
17077881ece5Smarc 		return;
1708e977faadSmarc 
1709b2b69f49Smarc 	case '\033':		/* start escape sequence */
1710b2b69f49Smarc 		if (nograph)
1711b2b69f49Smarc 			inescape[unit] = 1;
17127881ece5Smarc 		return;
1713b2b69f49Smarc 
1714b2b69f49Smarc 	default:
1715b2b69f49Smarc 		if ((chr < ' ') || (chr > '~'))
17167881ece5Smarc 			return;
17177e911b15Skarels 	}
1718b2b69f49Smarc 	/*
1719b2b69f49Smarc 	 * setup VIPER operand control registers
1720b2b69f49Smarc 	 */
17217e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0001);  /* select plane #0 */
17227e911b15Skarels 	write_ID(adder, SRC1_OCR_B,
17237e911b15Skarels 	EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY);
17247e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x00FE);  /* select other planes */
17257e911b15Skarels 	write_ID(adder, SRC1_OCR_B,
17267e911b15Skarels 	EXT_SOURCE | INT_NONE | NO_ID | BAR_SHIFT_DELAY);
17277e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x00FF);  /* select all planes */
17287e911b15Skarels 	write_ID(adder, DST_OCR_B,
17297e911b15Skarels 	EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
17307e911b15Skarels 	write_ID(adder, MASK_1, 0xFFFF);
17317e911b15Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 1);
17327e911b15Skarels 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
1733e977faadSmarc 	adder->x_clip_min = 0;
1734e977faadSmarc 	adder->x_clip_max = 1024;
1735e977faadSmarc 	adder->y_clip_min = 0;
1736e977faadSmarc 	adder->y_clip_max = 864;
1737b2b69f49Smarc 	/*
1738b2b69f49Smarc 	 * load DESTINATION origin and vectors
1739b2b69f49Smarc 	 */
17407e911b15Skarels 	adder->fast_dest_dy = 0;
17417e911b15Skarels 	adder->slow_dest_dx = 0;
17427e911b15Skarels 	adder->error_1 = 0;
17437e911b15Skarels 	adder->error_2 = 0;
17447e911b15Skarels 	adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL;
17457881ece5Smarc 	(void)wait_status(adder, RASTEROP_COMPLETE);
17467e911b15Skarels 	adder->destination_x = cursor[unit].x;
17477e911b15Skarels 	adder->fast_dest_dx = CHAR_WIDTH;
17487e911b15Skarels 	adder->destination_y = cursor[unit].y;
17497e911b15Skarels 	adder->slow_dest_dy = CHAR_HEIGHT;
1750b2b69f49Smarc 	/*
1751b2b69f49Smarc 	 * load SOURCE origin and vectors
1752b2b69f49Smarc 	 */
1753e977faadSmarc 	if ((chr - ' ') > (CHARS - 1))  {
1754e977faadSmarc 		printf("Invalid character (x)%x in blitc\n",chr);
1755e977faadSmarc 		chr = ' ';
1756e977faadSmarc 	}
1757b2b69f49Smarc 	/*
1758b2b69f49Smarc 	 * X position is modulo the number of characters per line
1759b2b69f49Smarc 	 */
1760e977faadSmarc 	adder->source_1_x = FONT_X +
1761e977faadSmarc 	    (((chr - ' ') % (MAX_SCREEN_X/CHAR_WIDTH)) * CHAR_WIDTH);
1762b2b69f49Smarc 	/*
1763b2b69f49Smarc 	 * Point to either first or second row
1764b2b69f49Smarc 	 */
1765e977faadSmarc 	adder->source_1_y = 2048 - 15 *
1766e977faadSmarc 	    (((chr - ' ')/(MAX_SCREEN_X/CHAR_WIDTH)) + 1);
17677e911b15Skarels 	adder->source_1_dx = CHAR_WIDTH;
17687e911b15Skarels 	adder->source_1_dy = CHAR_HEIGHT;
17697e911b15Skarels 	write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
17707e911b15Skarels 	adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE;
1771b2b69f49Smarc 	/*
1772b2b69f49Smarc 	 * update console cursor coordinates
1773b2b69f49Smarc 	 */
17747e911b15Skarels 	cursor[unit].x += CHAR_WIDTH;
1775b2b69f49Smarc 	if (nograph)
17767e911b15Skarels 		dga->x_cursor = TRANX(cursor[unit].x);
17777e911b15Skarels 	if (cursor[unit].x > (1024 - CHAR_WIDTH)) {
17787e911b15Skarels 		blitc(unit, '\r');
17797e911b15Skarels 		blitc(unit, '\n');
17807e911b15Skarels 	}
17817e911b15Skarels 
17827e911b15Skarels } /* blitc */
17837e911b15Skarels 
17847881ece5Smarc qdreset() { }
17857e911b15Skarels 
17867881ece5Smarc /*
1787b2b69f49Smarc  *  INTERRUPT SERVICE ROUTINES
17887881ece5Smarc  */
17897e911b15Skarels 
17907881ece5Smarc /*
17917881ece5Smarc  *  Service "DMA DONE" interrupt condition
17927881ece5Smarc  */
17937e911b15Skarels qddint(qd)
17947881ece5Smarc 	register qd;
17957e911b15Skarels {
17967e911b15Skarels 	register struct DMAreq_header *header;
17977e911b15Skarels 	register struct DMAreq *request;
17987e911b15Skarels 	register struct dga *dga;
17997e911b15Skarels 	struct adder *adder;
18007e911b15Skarels 	int cookie;			/* DMA adrs for QDSS */
18017e911b15Skarels 
18027881ece5Smarc 	(void)spl4(); 			/* allow interval timer in */
18037e911b15Skarels 
1804b2b69f49Smarc 	/*
1805b2b69f49Smarc 	* init pointers
1806b2b69f49Smarc 	*/
18077e911b15Skarels 	header = DMAheader[qd]; 	    /* register for optimization */
18087e911b15Skarels 	dga = (struct dga *) qdmap[qd].dga;
18097e911b15Skarels 	adder = (struct adder *) qdmap[qd].adder;
18107e911b15Skarels 
1811b2b69f49Smarc 	/*
1812b2b69f49Smarc 	* if this interrupt flagged as bogus for interrupt flushing purposes..
1813b2b69f49Smarc 	*/
18147e911b15Skarels 	if (DMA_ISIGNORE(header)) {
18157e911b15Skarels 		DMA_CLRIGNORE(header);
18167e911b15Skarels 		return;
18177e911b15Skarels 	}
18187e911b15Skarels 
1819b2b69f49Smarc 	/*
1820b2b69f49Smarc 	* dump a DMA hardware error message if appropriate
1821b2b69f49Smarc 	*/
18227e911b15Skarels 	if (dga->csr & DMA_ERR) {
18237e911b15Skarels 
18247e911b15Skarels 		if (dga->csr & PARITY_ERR)
18257881ece5Smarc 		    printf("qd%d: qddint: DMA hardware parity fault.\n", qd);
18267e911b15Skarels 
18277e911b15Skarels 		if (dga->csr & BUS_ERR)
18287881ece5Smarc 		    printf("qd%d: qddint: DMA hardware bus error.\n", qd);
18297e911b15Skarels 	}
18307e911b15Skarels 
1831b2b69f49Smarc 	/*
1832b2b69f49Smarc 	* if this was a DMA from user space...
1833b2b69f49Smarc 	*/
18347e911b15Skarels 	if (qdflags[qd].user_dma) {
18357e911b15Skarels 		qdflags[qd].user_dma = 0;
18367e911b15Skarels 		wakeup((caddr_t)&qdflags[qd].user_dma);
18377e911b15Skarels 		return;
18387e911b15Skarels 	}
18397e911b15Skarels 
1840b2b69f49Smarc 	/*
1841b2b69f49Smarc 	* if we're doing DMA request queue services, field the error condition
1842b2b69f49Smarc 	*/
18437e911b15Skarels 	if (dga->csr & DMA_ERR) {
18447e911b15Skarels 
18457e911b15Skarels 		dga->csr &= ~0x0600;		/* halt DMA (reset fifo) */
18467e911b15Skarels 		dga->csr |= DMA_ERR;		/* clear error condition */
18477e911b15Skarels 		adder->command = CANCEL;	/* cancel adder activity */
18487e911b15Skarels 
18497e911b15Skarels 		DMA_SETERROR(header);	/* flag error in header status word */
18507e911b15Skarels 		DMA_CLRACTIVE(header);
18517e911b15Skarels 		header->DMAreq[header->oldest].DMAdone |= HARD_ERROR;
18527e911b15Skarels 		header->newest = header->oldest;
18537e911b15Skarels 		header->used = 0;
18547e911b15Skarels 
18557881ece5Smarc 		if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
18567881ece5Smarc 			selwakeup(qdrsel[qd], 0);
18577881ece5Smarc 			qdrsel[qd] = 0;
18587e911b15Skarels 			qdflags[qd].selmask &= ~SEL_WRITE;
18597e911b15Skarels 		}
18607e911b15Skarels 
18617e911b15Skarels 		if (dga->bytcnt_lo != 0) {
18627e911b15Skarels 			dga->bytcnt_lo = 0;
18637e911b15Skarels 			dga->bytcnt_hi = 0;
18647e911b15Skarels 			DMA_SETIGNORE(header);
18657e911b15Skarels 		}
18667e911b15Skarels 		return;
18677e911b15Skarels 	}
18687e911b15Skarels 
1869b2b69f49Smarc 	/*
1870b2b69f49Smarc 	* if the DMA request queue is now becoming non-full,
1871b2b69f49Smarc 	* wakeup "select" client.
1872b2b69f49Smarc 	*/
18737e911b15Skarels 	if (DMA_ISFULL(header)) {
18747881ece5Smarc 		if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
18757881ece5Smarc 			selwakeup(qdrsel[qd], 0);
18767881ece5Smarc 			qdrsel[qd] = 0;
18777e911b15Skarels 			qdflags[qd].selmask &= ~SEL_WRITE;
18787e911b15Skarels 		}
18797e911b15Skarels 	}
18807e911b15Skarels 
18817e911b15Skarels 	header->DMAreq[header->oldest].DMAdone |= REQUEST_DONE;
1882e977faadSmarc 	QDlast_DMAtype = header->DMAreq[header->oldest].DMAtype;
18837e911b15Skarels 
1884e977faadSmarc 	/* check for unexpected interrupt */
1885e977faadSmarc 	if (DMA_ISEMPTY(header))
18867e911b15Skarels 	    return;
18877e911b15Skarels 
18887e911b15Skarels 	DMA_GETEND(header);	/* update request queue indices */
18897e911b15Skarels 
1890b2b69f49Smarc 	/*
18917881ece5Smarc 	* if no more DMA pending, wake up "select" client and exit
18927881ece5Smarc 	*/
18937e911b15Skarels 	if (DMA_ISEMPTY(header)) {
18947e911b15Skarels 
18957881ece5Smarc 		if (qdrsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
18967881ece5Smarc 			selwakeup(qdrsel[qd], 0);
18977881ece5Smarc 			qdrsel[qd] = 0;
18987e911b15Skarels 			qdflags[qd].selmask &= ~SEL_WRITE;
18997e911b15Skarels 		}
19007e911b15Skarels 
19017e911b15Skarels 		DMA_CLRACTIVE(header);  /* flag DMA done */
19027e911b15Skarels 		return;
19037e911b15Skarels 	}
19047e911b15Skarels 
1905b2b69f49Smarc 	/*
19067881ece5Smarc 	* initiate next DMA xfer
19077881ece5Smarc 	*/
19087e911b15Skarels 	request = DMA_GETBEGIN(header);
1909e977faadSmarc 	if (request->DMAtype != QDlast_DMAtype) {
1910e977faadSmarc 		dga->csr &= ~0x0600;	  /* halt DMA (reset fifo) */
1911e977faadSmarc 		adder->command = CANCEL;  /* cancel adder activity */
1912e977faadSmarc 	}
1913e977faadSmarc 
19147e911b15Skarels 
19157e911b15Skarels 	switch (request->DMAtype) {
19167e911b15Skarels 
19177e911b15Skarels 	case DISPLIST:
1918e977faadSmarc 		if (request->DMAtype != QDlast_DMAtype) {
19197e911b15Skarels 			dga->csr |= DL_ENB;
1920e977faadSmarc 			dga->csr &= ~(BTOP_ENB | BYTE_DMA);
1921e977faadSmarc 		}
19227e911b15Skarels 		break;
19237e911b15Skarels 
19247e911b15Skarels 	case PTOB:
1925e977faadSmarc 		if (request->DMAtype != QDlast_DMAtype) {
1926e977faadSmarc 			if (request->DMAdone & BYTE_PACK)
1927e977faadSmarc 			    dga->csr |= (PTOB_ENB | BYTE_DMA);
1928e977faadSmarc 			else {
19297e911b15Skarels 				dga->csr |= PTOB_ENB;
1930e977faadSmarc 				dga->csr &= ~BYTE_DMA;
1931e977faadSmarc 			}
1932e977faadSmarc 		}
19337e911b15Skarels 		break;
19347e911b15Skarels 
19357e911b15Skarels 	case BTOP:
1936e977faadSmarc 		if (request->DMAtype != QDlast_DMAtype) {
1937e977faadSmarc 			if (request->DMAdone & BYTE_PACK) {
1938e977faadSmarc 				dga->csr &= ~DL_ENB;
1939e977faadSmarc 				dga->csr |= (BTOP_ENB | BYTE_DMA);
1940e977faadSmarc 			}
1941e977faadSmarc 			else {
19427e911b15Skarels 				dga->csr |= BTOP_ENB;
1943e977faadSmarc 				dga->csr &= ~(BYTE_DMA | DL_ENB);
1944e977faadSmarc 			}
1945e977faadSmarc 		}
19467e911b15Skarels 		break;
19477e911b15Skarels 	default:
19487881ece5Smarc 		printf("qd%d: qddint: illegal DMAtype parameter.\n", qd);
19497e911b15Skarels 		DMA_CLRACTIVE(header);	/* flag DMA done */
19507e911b15Skarels 		return;
19517e911b15Skarels 	}
19527e911b15Skarels 
19537e911b15Skarels 	if (request->DMAdone & COUNT_ZERO) {
19547e911b15Skarels 		dga->csr &= ~SET_DONE_FIFO;
1955b2b69f49Smarc 	}
1956b2b69f49Smarc 	else if (request->DMAdone & FIFO_EMPTY) {
19577e911b15Skarels 		dga->csr |= SET_DONE_FIFO;
19587e911b15Skarels 	}
19597e911b15Skarels 
19607e911b15Skarels 	if (request->DMAdone & WORD_PACK)
19617e911b15Skarels 	    dga->csr &= ~BYTE_DMA;
19627e911b15Skarels 	else if (request->DMAdone & BYTE_PACK)
19637e911b15Skarels 	    dga->csr |= BYTE_DMA;
19647e911b15Skarels 
19657e911b15Skarels 	dga->csr |= DMA_IE;
1966e977faadSmarc 	QDlast_DMAtype = request->DMAtype;
19677e911b15Skarels 
19687e911b15Skarels 	cookie = ((int)request->bufp - (int)header) + (int)header->QBAreg;
19697e911b15Skarels 
19707e911b15Skarels 	dga->adrs_lo = (short) cookie;
19717e911b15Skarels 	dga->adrs_hi = (short) (cookie >> 16);
19727e911b15Skarels 
19737e911b15Skarels 	dga->bytcnt_lo = (short) request->length;
19747e911b15Skarels 	dga->bytcnt_hi = (short) (request->length >> 16);
19757e911b15Skarels 
19767e911b15Skarels 	return;
19777e911b15Skarels }
19787e911b15Skarels 
19797881ece5Smarc /*
19807881ece5Smarc  * ADDER interrupt service routine
19817881ece5Smarc  */
19827e911b15Skarels qdaint(qd)
19837881ece5Smarc 	register qd;
19847e911b15Skarels {
19857e911b15Skarels 	register struct adder *adder;
19867e911b15Skarels 	struct color_buf *cbuf;
19877e911b15Skarels 	int i;
19887e911b15Skarels 	register struct rgb *rgbp;
19897e911b15Skarels 	register short *red;
19907e911b15Skarels 	register short *green;
19917e911b15Skarels 	register short *blue;
19927e911b15Skarels 
19937881ece5Smarc 	(void)spl4(); 			/* allow interval timer in */
19947e911b15Skarels 
19957e911b15Skarels 	adder = (struct adder *) qdmap[qd].adder;
19967e911b15Skarels 
1997b2b69f49Smarc 	/*
1998b2b69f49Smarc 	* service the vertical blank interrupt (VSYNC bit) by loading
1999b2b69f49Smarc 	* any pending color map load request
2000b2b69f49Smarc 	*/
20017e911b15Skarels 	if (adder->status & VSYNC) {
20027e911b15Skarels 		adder->status &= ~VSYNC;	/* clear the interrupt */
20037e911b15Skarels 		cbuf = color_buf[qd];
20047e911b15Skarels 		if (cbuf->status & LOAD_COLOR_MAP) {
20057e911b15Skarels 
20067e911b15Skarels 			red = (short *) qdmap[qd].red;
20077e911b15Skarels 			green = (short *) qdmap[qd].green;
20087e911b15Skarels 			blue = (short *) qdmap[qd].blue;
20097e911b15Skarels 
2010b2b69f49Smarc 			for (i = cbuf->count, rgbp = cbuf->rgb;
2011b2b69f49Smarc 			     --i >= 0; rgbp++) {
20127e911b15Skarels 				red[rgbp->offset] = (short) rgbp->red;
20137e911b15Skarels 				green[rgbp->offset] = (short) rgbp->green;
20147e911b15Skarels 				blue[rgbp->offset] = (short) rgbp->blue;
20157e911b15Skarels 			}
20167e911b15Skarels 
20177e911b15Skarels 			cbuf->status &= ~LOAD_COLOR_MAP;
20187e911b15Skarels 		}
20197e911b15Skarels 	}
20207e911b15Skarels 
2021b2b69f49Smarc 	/*
2022b2b69f49Smarc 	* service the scroll interrupt (FRAME_SYNC bit)
2023b2b69f49Smarc 	*/
20247e911b15Skarels 	if (adder->status & FRAME_SYNC) {
20257e911b15Skarels 		adder->status &= ~FRAME_SYNC;	/* clear the interrupt */
20267e911b15Skarels 
20277e911b15Skarels 		if (scroll[qd]->status & LOAD_REGS) {
20287e911b15Skarels 
20297881ece5Smarc 			for (i = 1000, adder->status = 0; i > 0 &&
20307881ece5Smarc 			     !(adder->status&ID_SCROLL_READY); --i)
2031b2b69f49Smarc 			      ;
20327e911b15Skarels 
20337e911b15Skarels 			if (i == 0) {
20347881ece5Smarc 			    printf("qd%d: qdaint: timeout on ID_SCROLL_READY\n",
2035b2b69f49Smarc 				qd);
20367e911b15Skarels 				return;
20377e911b15Skarels 			}
20387e911b15Skarels 
20397e911b15Skarels 			adder->ID_scroll_data = scroll[qd]->viper_constant;
20407e911b15Skarels 			adder->ID_scroll_command = ID_LOAD | SCROLL_CONSTANT;
20417e911b15Skarels 
2042b2b69f49Smarc 			adder->y_scroll_constant =
2043b2b69f49Smarc 				scroll[qd]->y_scroll_constant;
20447e911b15Skarels 			adder->y_offset_pending = scroll[qd]->y_offset;
20457e911b15Skarels 
20467e911b15Skarels 			if (scroll[qd]->status & LOAD_INDEX) {
20477e911b15Skarels 
2048b2b69f49Smarc 				adder->x_index_pending =
2049b2b69f49Smarc 					scroll[qd]->x_index_pending;
2050b2b69f49Smarc 				adder->y_index_pending =
2051b2b69f49Smarc 					scroll[qd]->y_index_pending;
20527e911b15Skarels 			}
20537e911b15Skarels 
20547e911b15Skarels 			scroll[qd]->status = 0x00;
20557e911b15Skarels 		}
20567e911b15Skarels 	}
20577e911b15Skarels }
20587e911b15Skarels 
20597881ece5Smarc /*
20607881ece5Smarc  *  DUART input interrupt service routine
20617e911b15Skarels  *
2062b2b69f49Smarc  *  XXX - this routine should be broken out - it is essentially
2063b2b69f49Smarc  *	      straight line code.
20647881ece5Smarc  */
20657e911b15Skarels 
20667e911b15Skarels qdiint(qd)
20677881ece5Smarc 	register qd;
20687e911b15Skarels {
20697e911b15Skarels 	register struct _vs_event *event;
20707e911b15Skarels 	register struct qdinput *eqh;
20717e911b15Skarels 	struct dga *dga;
20727e911b15Skarels 	struct duart *duart;
20737e911b15Skarels 	struct mouse_report *new_rep;
20747e911b15Skarels 	struct uba_device *ui;
20757e911b15Skarels 	struct tty *tp;
2076e977faadSmarc 	u_short chr;
20777e911b15Skarels 	u_short status;
20787e911b15Skarels 	u_short data;
20797e911b15Skarels 	u_short key;
20807e911b15Skarels 	char do_wakeup = 0;		/* flag to do a select wakeup call */
20817e911b15Skarels 	char a, b, c;			/* mouse button test variables */
20827e911b15Skarels 
20837881ece5Smarc 	(void)spl4(); 			/* allow interval timer in */
20847e911b15Skarels 
20857e911b15Skarels 	eqh = eq_header[qd];		/* optimized as a register */
20867e911b15Skarels 	new_rep = &current_rep[qd];
20877e911b15Skarels 	duart = (struct duart *) qdmap[qd].duart;
20887e911b15Skarels 
2089b2b69f49Smarc 	/*
20907881ece5Smarc 	* if the graphic device is turned on..
20917881ece5Smarc 	*/
20927e911b15Skarels 	if (qdflags[qd].inuse & GRAPHIC_DEV) {
2093b2b69f49Smarc 		/*
2094b2b69f49Smarc 		* empty DUART
2095b2b69f49Smarc 		*/
20967881ece5Smarc 		while (duart->statusA&RCV_RDY || duart->statusB&RCV_RDY) {
2097b2b69f49Smarc 			/*
20987881ece5Smarc 			 * pick up LK-201 input (if any)
20997881ece5Smarc 			 */
21007881ece5Smarc 			if (duart->statusA&RCV_RDY) {
21017e911b15Skarels 
21027e911b15Skarels 				/* if error condition, then reset it */
21037e911b15Skarels 
21047881ece5Smarc 				if (duart->statusA&0x70) {
21057e911b15Skarels 					duart->cmdA = 0x40;
21067e911b15Skarels 					continue;
21077e911b15Skarels 				}
21087e911b15Skarels 
21097e911b15Skarels 				/* event queue full now? (overflow condition) */
21107e911b15Skarels 
21117e911b15Skarels 				if (ISFULL(eqh) == TRUE) {
2112b2b69f49Smarc 					printf(
21137881ece5Smarc 					 "qd%d: qdiint: event queue overflow\n",
2114b2b69f49Smarc 					   qd);
21157e911b15Skarels 					break;
21167e911b15Skarels 				}
21177e911b15Skarels 
2118b2b69f49Smarc 				/*
21197e911b15Skarels 				* Check for various keyboard errors  */
21207e911b15Skarels 
21217e911b15Skarels 				key = duart->dataA & 0xFF;
21227e911b15Skarels 
2123b2b69f49Smarc 				if (key==LK_POWER_ERROR ||
2124b2b69f49Smarc 				    key==LK_KDOWN_ERROR ||
2125b2b69f49Smarc 				    key == LK_INPUT_ERROR ||
2126b2b69f49Smarc 				    key == LK_OUTPUT_ERROR) {
2127b2b69f49Smarc 					printf(
21287881ece5Smarc 				    "qd%d: qdiint: keyboard error, code = %x\n",
2129b2b69f49Smarc 					qd,key);
21307881ece5Smarc 					return;
21317e911b15Skarels 				}
21327e911b15Skarels 
21337e911b15Skarels 				if (key < LK_LOWEST)
21347881ece5Smarc 				    return;
21357e911b15Skarels 
21367e911b15Skarels 				++do_wakeup;  /* request a select wakeup call */
21377e911b15Skarels 
21387e911b15Skarels 				event = PUTBEGIN(eqh);
21397e911b15Skarels 				PUTEND(eqh);
21407e911b15Skarels 
21417e911b15Skarels 				event->vse_key = key;
21427e911b15Skarels 				event->vse_key &= 0x00FF;
21437e911b15Skarels 				event->vse_x = eqh->curs_pos.x;
21447e911b15Skarels 				event->vse_y = eqh->curs_pos.y;
21457e911b15Skarels 				event->vse_time = TOY;
21467e911b15Skarels 				event->vse_type = VSE_BUTTON;
21477e911b15Skarels 				event->vse_direction = VSE_KBTRAW;
21487e911b15Skarels 				event->vse_device = VSE_DKB;
21497e911b15Skarels 			}
21507e911b15Skarels 
2151b2b69f49Smarc 			/*
21527e911b15Skarels 			* pick up the mouse input (if any)  */
21537e911b15Skarels 
21547e911b15Skarels 			if ((status = duart->statusB) & RCV_RDY  &&
21557e911b15Skarels 			    qdflags[qd].pntr_id == MOUSE_ID) {
21567e911b15Skarels 
21577e911b15Skarels 				if (status & 0x70) {
21587e911b15Skarels 					duart->cmdB = 0x40;
21597e911b15Skarels 					continue;
21607e911b15Skarels 				}
21617e911b15Skarels 
21627e911b15Skarels 				/* event queue full now? (overflow condition) */
21637e911b15Skarels 
21647e911b15Skarels 				if (ISFULL(eqh) == TRUE) {
2165b2b69f49Smarc 					printf(
21667881ece5Smarc 					"qd%d: qdiint: event queue overflow\n",
2167b2b69f49Smarc 					     qd);
21687e911b15Skarels 					break;
21697e911b15Skarels 				}
21707e911b15Skarels 
21717e911b15Skarels 				data = duart->dataB;      /* get report byte */
21727e911b15Skarels 				++new_rep->bytcnt; /* bump report byte count */
21737e911b15Skarels 
2174b2b69f49Smarc 				/*
21757e911b15Skarels 				* if 1st byte of report.. */
21767e911b15Skarels 
21777e911b15Skarels 				if ( data & START_FRAME) {
21787e911b15Skarels 					new_rep->state = data;
21797e911b15Skarels 					if (new_rep->bytcnt > 1) {
2180b2b69f49Smarc 						/* start of new frame */
2181b2b69f49Smarc 						new_rep->bytcnt = 1;
2182b2b69f49Smarc 						/* ..continue looking */
2183b2b69f49Smarc 						continue;
21847e911b15Skarels 					}
21857e911b15Skarels 				}
21867e911b15Skarels 
2187b2b69f49Smarc 				/*
21887e911b15Skarels 				* if 2nd byte of report.. */
21897e911b15Skarels 
21907e911b15Skarels 				else if (new_rep->bytcnt == 2) {
21917e911b15Skarels 					new_rep->dx = data & 0x00FF;
21927e911b15Skarels 				}
21937e911b15Skarels 
2194b2b69f49Smarc 				/*
21957e911b15Skarels 				* if 3rd byte of report, load input event queue */
21967e911b15Skarels 
21977e911b15Skarels 				else if (new_rep->bytcnt == 3) {
21987e911b15Skarels 
21997e911b15Skarels 					new_rep->dy = data & 0x00FF;
22007e911b15Skarels 					new_rep->bytcnt = 0;
22017e911b15Skarels 
2202b2b69f49Smarc 					/*
22037e911b15Skarels 					* if mouse position has changed.. */
22047e911b15Skarels 
22057e911b15Skarels 					if (new_rep->dx != 0  ||  new_rep->dy != 0) {
22067e911b15Skarels 
2207b2b69f49Smarc 						/*
22087e911b15Skarels 						* calculate acceleration factor, if needed	*/
22097e911b15Skarels 
22107e911b15Skarels 						if (qdflags[qd].curs_acc > ACC_OFF) {
22117e911b15Skarels 
22127e911b15Skarels 							if (qdflags[qd].curs_thr <= new_rep->dx)
22137e911b15Skarels 							    new_rep->dx +=
22147e911b15Skarels 							    (new_rep->dx - qdflags[qd].curs_thr)
22157e911b15Skarels 							    * qdflags[qd].curs_acc;
22167e911b15Skarels 
22177e911b15Skarels 							if (qdflags[qd].curs_thr <= new_rep->dy)
22187e911b15Skarels 							    new_rep->dy +=
22197e911b15Skarels 							    (new_rep->dy - qdflags[qd].curs_thr)
22207e911b15Skarels 							    * qdflags[qd].curs_acc;
22217e911b15Skarels 						}
22227e911b15Skarels 
2223b2b69f49Smarc 						/*
22247e911b15Skarels 						* update cursor position coordinates */
22257e911b15Skarels 
22267e911b15Skarels 						if (new_rep->state & X_SIGN) {
22277e911b15Skarels 							eqh->curs_pos.x += new_rep->dx;
22287e911b15Skarels 							if (eqh->curs_pos.x > 1023)
22297e911b15Skarels 							    eqh->curs_pos.x = 1023;
22307e911b15Skarels 						}
22317e911b15Skarels 						else {
22327e911b15Skarels 							eqh->curs_pos.x -= new_rep->dx;
22337e911b15Skarels 							if (eqh->curs_pos.x < -15)
22347e911b15Skarels 							    eqh->curs_pos.x = -15;
22357e911b15Skarels 						}
22367e911b15Skarels 
22377e911b15Skarels 						if (new_rep->state & Y_SIGN) {
22387e911b15Skarels 							eqh->curs_pos.y -= new_rep->dy;
22397e911b15Skarels 							if (eqh->curs_pos.y < -15)
22407e911b15Skarels 							    eqh->curs_pos.y = -15;
22417e911b15Skarels 						}
22427e911b15Skarels 						else {
22437e911b15Skarels 							eqh->curs_pos.y += new_rep->dy;
22447e911b15Skarels 							if (eqh->curs_pos.y > 863)
22457e911b15Skarels 							    eqh->curs_pos.y = 863;
22467e911b15Skarels 						}
22477e911b15Skarels 
2248b2b69f49Smarc 						/*
22497e911b15Skarels 						* update cursor screen position */
22507e911b15Skarels 
22517e911b15Skarels 						dga = (struct dga *) qdmap[qd].dga;
22527e911b15Skarels 						dga->x_cursor = TRANX(eqh->curs_pos.x);
22537e911b15Skarels 						dga->y_cursor = TRANY(eqh->curs_pos.y);
22547e911b15Skarels 
2255b2b69f49Smarc 						/*
22567e911b15Skarels 						* if cursor is in the box, no event report */
22577e911b15Skarels 
22587e911b15Skarels 						if (eqh->curs_pos.x <= eqh->curs_box.right	&&
22597e911b15Skarels 						    eqh->curs_pos.x >= eqh->curs_box.left  &&
22607e911b15Skarels 						    eqh->curs_pos.y >= eqh->curs_box.top  &&
22617e911b15Skarels 						    eqh->curs_pos.y <= eqh->curs_box.bottom ) {
22627e911b15Skarels 							goto GET_MBUTTON;
22637e911b15Skarels 						}
22647e911b15Skarels 
2265b2b69f49Smarc 						/*
22667e911b15Skarels 						* report the mouse motion event */
22677e911b15Skarels 
22687e911b15Skarels 						event = PUTBEGIN(eqh);
22697e911b15Skarels 						PUTEND(eqh);
22707e911b15Skarels 
22717e911b15Skarels 						++do_wakeup;   /* request a select wakeup call */
22727e911b15Skarels 
22737e911b15Skarels 						event->vse_x = eqh->curs_pos.x;
22747e911b15Skarels 						event->vse_y = eqh->curs_pos.y;
22757e911b15Skarels 
22767e911b15Skarels 						event->vse_device = VSE_MOUSE;  /* mouse */
22777e911b15Skarels 						event->vse_type = VSE_MMOTION;  /* pos changed */
22787e911b15Skarels 						event->vse_key = 0;
22797e911b15Skarels 						event->vse_direction = 0;
22807e911b15Skarels 						event->vse_time = TOY;	/* time stamp */
22817e911b15Skarels 					}
22827e911b15Skarels 
22837e911b15Skarels GET_MBUTTON:
2284b2b69f49Smarc 					/*
22857e911b15Skarels 					* if button state has changed */
22867e911b15Skarels 
22877e911b15Skarels 					a = new_rep->state & 0x07;    /*mask nonbutton bits */
22887e911b15Skarels 					b = last_rep[qd].state & 0x07;
22897e911b15Skarels 
22907e911b15Skarels 					if (a ^ b) {
22917e911b15Skarels 
22927e911b15Skarels 						for ( c = 1;  c < 8; c <<= 1) {
22937e911b15Skarels 
22947e911b15Skarels 							if (!( c & (a ^ b))) /* this button change? */
22957e911b15Skarels 							    continue;
22967e911b15Skarels 
22977e911b15Skarels 							/* event queue full? (overflow condition) */
22987e911b15Skarels 
22997e911b15Skarels 							if (ISFULL(eqh) == TRUE) {
23007881ece5Smarc 								printf("qd%d: qdiint: event queue overflow\n", qd);
23017e911b15Skarels 								break;
23027e911b15Skarels 							}
23037e911b15Skarels 
23047e911b15Skarels 							event = PUTBEGIN(eqh);	/* get new event */
23057e911b15Skarels 							PUTEND(eqh);
23067e911b15Skarels 
23077e911b15Skarels 							++do_wakeup;   /* request select wakeup */
23087e911b15Skarels 
23097e911b15Skarels 							event->vse_x = eqh->curs_pos.x;
23107e911b15Skarels 							event->vse_y = eqh->curs_pos.y;
23117e911b15Skarels 
23127e911b15Skarels 							event->vse_device = VSE_MOUSE;	/* mouse */
23137e911b15Skarels 							event->vse_type = VSE_BUTTON; /* new button */
23147e911b15Skarels 							event->vse_time = TOY;	      /* time stamp */
23157e911b15Skarels 
23167e911b15Skarels 							/* flag changed button and if up or down */
23177e911b15Skarels 
23187e911b15Skarels 							if (c == RIGHT_BUTTON)
23197e911b15Skarels 							    event->vse_key = VSE_RIGHT_BUTTON;
23207e911b15Skarels 							else if (c == MIDDLE_BUTTON)
23217e911b15Skarels 							    event->vse_key = VSE_MIDDLE_BUTTON;
23227e911b15Skarels 							else if (c == LEFT_BUTTON)
23237e911b15Skarels 							    event->vse_key = VSE_LEFT_BUTTON;
23247e911b15Skarels 
23257e911b15Skarels 							/* set bit = button depressed */
23267e911b15Skarels 
23277e911b15Skarels 							if (c & a)
23287e911b15Skarels 							    event->vse_direction = VSE_KBTDOWN;
23297e911b15Skarels 							else
23307e911b15Skarels 								event->vse_direction = VSE_KBTUP;
23317e911b15Skarels 						}
23327e911b15Skarels 					}
23337e911b15Skarels 
23347e911b15Skarels 					/* refresh last report */
23357e911b15Skarels 
23367e911b15Skarels 					last_rep[qd] = current_rep[qd];
23377e911b15Skarels 
23387e911b15Skarels 				}  /* get last byte of report */
23397881ece5Smarc 			} else if ((status = duart->statusB)&RCV_RDY &&
23407e911b15Skarels 			           qdflags[qd].pntr_id == TABLET_ID) {
23417881ece5Smarc 				/*
23427881ece5Smarc 				* pickup tablet input, if any
23437881ece5Smarc 				*/
23447e911b15Skarels 				if (status&0x70) {
23457e911b15Skarels 					duart->cmdB = 0x40;
23467e911b15Skarels 					continue;
23477e911b15Skarels 				}
23487881ece5Smarc 				/*
23497881ece5Smarc 				 * event queue full now? (overflow condition)
23507881ece5Smarc 				 */
23517e911b15Skarels 				if (ISFULL(eqh) == TRUE) {
23527881ece5Smarc 					printf("qd%d: qdiint: event queue overflow\n", qd);
23537e911b15Skarels 					break;
23547e911b15Skarels 				}
23557e911b15Skarels 
23567e911b15Skarels 				data = duart->dataB;      /* get report byte */
23577e911b15Skarels 				++new_rep->bytcnt;	      /* bump report byte count */
23587e911b15Skarels 
2359b2b69f49Smarc 				/*
23607e911b15Skarels 				* if 1st byte of report.. */
23617e911b15Skarels 
23627e911b15Skarels 				if (data & START_FRAME) {
23637e911b15Skarels 					new_rep->state = data;
23647e911b15Skarels 					if (new_rep->bytcnt > 1) {
23657e911b15Skarels 						new_rep->bytcnt = 1;    /* start of new frame */
23667e911b15Skarels 						continue;		    /* ..continue looking */
23677e911b15Skarels 					}
23687e911b15Skarels 				}
23697e911b15Skarels 
2370b2b69f49Smarc 				/*
23717e911b15Skarels 				* if 2nd byte of report.. */
23727e911b15Skarels 
23737e911b15Skarels 				else if (new_rep->bytcnt == 2) {
23747e911b15Skarels 					new_rep->dx = data & 0x3F;
23757e911b15Skarels 				}
23767e911b15Skarels 
2377b2b69f49Smarc 				/*
23787e911b15Skarels 				* if 3rd byte of report.. */
23797e911b15Skarels 
23807e911b15Skarels 				else if (new_rep->bytcnt == 3) {
23817e911b15Skarels 					new_rep->dx |= (data & 0x3F) << 6;
23827e911b15Skarels 				}
23837e911b15Skarels 
2384b2b69f49Smarc 				/*
23857e911b15Skarels 				* if 4th byte of report.. */
23867e911b15Skarels 
23877e911b15Skarels 				else if (new_rep->bytcnt == 4) {
23887e911b15Skarels 					new_rep->dy = data & 0x3F;
23897e911b15Skarels 				}
23907e911b15Skarels 
2391b2b69f49Smarc 				/*
23927e911b15Skarels 				* if 5th byte of report, load input event queue */
23937e911b15Skarels 
23947e911b15Skarels 				else if (new_rep->bytcnt == 5) {
23957e911b15Skarels 
23967e911b15Skarels 					new_rep->dy |= (data & 0x3F) << 6;
23977e911b15Skarels 					new_rep->bytcnt = 0;
23987e911b15Skarels 
2399b2b69f49Smarc 					/*
24007e911b15Skarels 					* update cursor position coordinates */
24017e911b15Skarels 
24027e911b15Skarels 					new_rep->dx /= qdflags[qd].tab_res;
24037e911b15Skarels 					new_rep->dy = (2200 - new_rep->dy)
24047e911b15Skarels 					    / qdflags[qd].tab_res;
24057e911b15Skarels 
24067e911b15Skarels 					if (new_rep->dx > 1023) {
24077e911b15Skarels 						new_rep->dx = 1023;
24087e911b15Skarels 					}
24097e911b15Skarels 					if (new_rep->dy > 863) {
24107e911b15Skarels 						new_rep->dy = 863;
24117e911b15Skarels 					}
24127e911b15Skarels 
24137e911b15Skarels 					/*
24147e911b15Skarels 					* report an event if the puck/stylus has moved
24157e911b15Skarels 					*/
24167e911b15Skarels 
24177e911b15Skarels 					if (eqh->curs_pos.x != new_rep->dx ||
24187e911b15Skarels 					    eqh->curs_pos.y != new_rep->dy) {
24197e911b15Skarels 
24207e911b15Skarels 						eqh->curs_pos.x = new_rep->dx;
24217e911b15Skarels 						eqh->curs_pos.y = new_rep->dy;
24227e911b15Skarels 
2423b2b69f49Smarc 						/*
24247e911b15Skarels 						* update cursor screen position */
24257e911b15Skarels 
24267e911b15Skarels 						dga = (struct dga *) qdmap[qd].dga;
24277e911b15Skarels 						dga->x_cursor = TRANX(eqh->curs_pos.x);
24287e911b15Skarels 						dga->y_cursor = TRANY(eqh->curs_pos.y);
24297e911b15Skarels 
24307e911b15Skarels 						/*
24317e911b15Skarels 						* if cursor is in the box, no event report
24327e911b15Skarels 						*/
24337e911b15Skarels 
24347e911b15Skarels 						if (eqh->curs_pos.x <= eqh->curs_box.right	&&
24357e911b15Skarels 						    eqh->curs_pos.x >= eqh->curs_box.left  &&
24367e911b15Skarels 						    eqh->curs_pos.y >= eqh->curs_box.top  &&
24377e911b15Skarels 						    eqh->curs_pos.y <= eqh->curs_box.bottom ) {
24387e911b15Skarels 							goto GET_TBUTTON;
24397e911b15Skarels 						}
24407e911b15Skarels 
2441b2b69f49Smarc 						/*
24427e911b15Skarels 						* report the tablet motion event */
24437e911b15Skarels 
24447e911b15Skarels 						event = PUTBEGIN(eqh);
24457e911b15Skarels 						PUTEND(eqh);
24467e911b15Skarels 
24477e911b15Skarels 						++do_wakeup;   /* request a select wakeup call */
24487e911b15Skarels 
24497e911b15Skarels 						event->vse_x = eqh->curs_pos.x;
24507e911b15Skarels 						event->vse_y = eqh->curs_pos.y;
24517e911b15Skarels 
24527e911b15Skarels 						event->vse_device = VSE_TABLET;  /* tablet */
24537e911b15Skarels 						/*
24547e911b15Skarels 						* right now, X handles tablet motion the same
24557e911b15Skarels 						* as mouse motion
24567e911b15Skarels 						*/
24577e911b15Skarels 						event->vse_type = VSE_MMOTION;   /* pos changed */
24587e911b15Skarels 						event->vse_key = 0;
24597e911b15Skarels 						event->vse_direction = 0;
24607e911b15Skarels 						event->vse_time = TOY;	/* time stamp */
24617e911b15Skarels 					}
24627e911b15Skarels GET_TBUTTON:
2463b2b69f49Smarc 					/*
24647e911b15Skarels 					* if button state has changed */
24657e911b15Skarels 
24667e911b15Skarels 					a = new_rep->state & 0x1E;   /* mask nonbutton bits */
24677e911b15Skarels 					b = last_rep[qd].state & 0x1E;
24687e911b15Skarels 
24697e911b15Skarels 					if (a ^ b) {
24707e911b15Skarels 
24717e911b15Skarels 						/* event queue full now? (overflow condition) */
24727e911b15Skarels 
24737e911b15Skarels 						if (ISFULL(eqh) == TRUE) {
24747881ece5Smarc 							printf("qd%d: qdiint: event queue overflow\n",qd);
24757e911b15Skarels 							break;
24767e911b15Skarels 						}
24777e911b15Skarels 
24787e911b15Skarels 						event = PUTBEGIN(eqh);  /* get new event */
24797e911b15Skarels 						PUTEND(eqh);
24807e911b15Skarels 
24817e911b15Skarels 						++do_wakeup;   /* request a select wakeup call */
24827e911b15Skarels 
24837e911b15Skarels 						event->vse_x = eqh->curs_pos.x;
24847e911b15Skarels 						event->vse_y = eqh->curs_pos.y;
24857e911b15Skarels 
24867e911b15Skarels 						event->vse_device = VSE_TABLET;  /* tablet */
24877e911b15Skarels 						event->vse_type = VSE_BUTTON; /* button changed */
24887e911b15Skarels 						event->vse_time = TOY;	   /* time stamp */
24897e911b15Skarels 
24907e911b15Skarels 						/* define the changed button and if up or down */
24917e911b15Skarels 
24927e911b15Skarels 						for ( c = 1;  c <= 0x10; c <<= 1) {
24937e911b15Skarels 							if (c & (a ^ b)) {
24947e911b15Skarels 								if (c == T_LEFT_BUTTON)
24957e911b15Skarels 								    event->vse_key = VSE_T_LEFT_BUTTON;
24967e911b15Skarels 								else if (c == T_FRONT_BUTTON)
24977e911b15Skarels 								    event->vse_key = VSE_T_FRONT_BUTTON;
24987e911b15Skarels 								else if (c == T_RIGHT_BUTTON)
24997e911b15Skarels 								    event->vse_key = VSE_T_RIGHT_BUTTON;
25007e911b15Skarels 								else if (c == T_BACK_BUTTON)
25017e911b15Skarels 								    event->vse_key = VSE_T_BACK_BUTTON;
25027e911b15Skarels 								break;
25037e911b15Skarels 							}
25047e911b15Skarels 						}
25057e911b15Skarels 
25067e911b15Skarels 						/* set bit = button depressed */
25077e911b15Skarels 
25087e911b15Skarels 						if (c & a)
25097e911b15Skarels 						    event->vse_direction = VSE_KBTDOWN;
25107e911b15Skarels 						else
25117e911b15Skarels 							event->vse_direction = VSE_KBTUP;
25127e911b15Skarels 					}
25137e911b15Skarels 
25147e911b15Skarels 					/* refresh last report */
25157e911b15Skarels 
25167e911b15Skarels 					last_rep[qd] = current_rep[qd];
25177e911b15Skarels 
25187e911b15Skarels 				} /* get last byte of report */
25197e911b15Skarels 			} /* pick up tablet input */
25207e911b15Skarels 
25217e911b15Skarels 		} /* while input available.. */
25227e911b15Skarels 
2523b2b69f49Smarc 		/*
2524b2b69f49Smarc 		* do select wakeup
2525b2b69f49Smarc 		*/
25267881ece5Smarc 		if (qdrsel[qd] && do_wakeup && qdflags[qd].selmask & SEL_READ) {
25277881ece5Smarc 			selwakeup(qdrsel[qd], 0);
25287881ece5Smarc 			qdrsel[qd] = 0;
25297e911b15Skarels 			qdflags[qd].selmask &= ~SEL_READ;
25307e911b15Skarels 			do_wakeup = 0;
25317e911b15Skarels 		}
25327881ece5Smarc 	} else {
2533b2b69f49Smarc 		/*
25347881ece5Smarc 		 * if the graphic device is not turned on, this is console input
25357881ece5Smarc 		 */
25367e911b15Skarels 		ui = qdinfo[qd];
25377e911b15Skarels 		if (ui == 0 || ui->ui_alive == 0)
25387881ece5Smarc 			return;
25397e911b15Skarels 
25407e911b15Skarels 		tp = &qd_tty[qd << 2];
25417e911b15Skarels 
2542b2b69f49Smarc 		/*
25437881ece5Smarc 		 * Get a character from the keyboard.
25447881ece5Smarc 		 */
25457881ece5Smarc 		while (duart->statusA&RCV_RDY) {
25467e911b15Skarels 			key = duart->dataA;
25477e911b15Skarels 			key &= 0xFF;
2548b2b69f49Smarc 			/*
25497881ece5Smarc 			* Check for various keyboard errors
25507881ece5Smarc 			*/
25517e911b15Skarels 			if (key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
25527e911b15Skarels 			    key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
25537881ece5Smarc 				printf("qd%d: qdiint: Keyboard error, code = %x\n",qd,key);
25547881ece5Smarc 				return;
25557e911b15Skarels 			}
25567e911b15Skarels 
25577e911b15Skarels 			if (key < LK_LOWEST)
25587881ece5Smarc 			    return;
25597e911b15Skarels 
2560b2b69f49Smarc 			/*
25617e911b15Skarels 			* See if its a state change key */
25627e911b15Skarels 
25637e911b15Skarels 			switch (key) {
25647e911b15Skarels 
25657e911b15Skarels 			case LOCK:
25667e911b15Skarels 				q_keyboard.lock ^= 0xffff;	/* toggle */
25677e911b15Skarels 				if (q_keyboard.lock)
25687881ece5Smarc 					(void)led_control(qd, LK_LED_ENABLE,
25697881ece5Smarc 							  LK_LED_LOCK);
25707e911b15Skarels 				else
25717881ece5Smarc 					(void)led_control(qd, LK_LED_DISABLE,
25727881ece5Smarc 							  LK_LED_LOCK);
25737e911b15Skarels 				return;
25747e911b15Skarels 
25757e911b15Skarels 			case SHIFT:
25767e911b15Skarels 				q_keyboard.shift ^= 0xFFFF;
25777e911b15Skarels 				return;
25787e911b15Skarels 
25797e911b15Skarels 			case CNTRL:
25807e911b15Skarels 				q_keyboard.cntrl ^= 0xFFFF;
25817e911b15Skarels 				return;
25827e911b15Skarels 
25837e911b15Skarels 			case ALLUP:
25847e911b15Skarels 				q_keyboard.cntrl = 0;
25857e911b15Skarels 				q_keyboard.shift = 0;
25867e911b15Skarels 				return;
25877e911b15Skarels 
25887e911b15Skarels 			case REPEAT:
25897e911b15Skarels 				chr = q_keyboard.last;
25907e911b15Skarels 				break;
25917e911b15Skarels 
2592b2b69f49Smarc 				/*
25937e911b15Skarels 				* Test for cntrl characters. If set, see if the character
25947e911b15Skarels 				* is elligible to become a control character. */
25957e911b15Skarels 
25967e911b15Skarels 			default:
25977e911b15Skarels 
25987e911b15Skarels 				if (q_keyboard.cntrl) {
25997e911b15Skarels 					chr = q_key[key];
26007e911b15Skarels 					if (chr >= ' ' && chr <= '~')
26017e911b15Skarels 					    chr &= 0x1F;
2602e977faadSmarc 					else if (chr >= 0xA1 && chr <= 0xFE)
2603e977faadSmarc 					    chr &= 0x9F;
26047e911b15Skarels 				}
26057e911b15Skarels 				else if( q_keyboard.lock || q_keyboard.shift )
26067e911b15Skarels 				    chr = q_shift_key[key];
26077e911b15Skarels 				else
26087e911b15Skarels 					chr = q_key[key];
26097e911b15Skarels 				break;
26107e911b15Skarels 			}
26117e911b15Skarels 
26127e911b15Skarels 			q_keyboard.last = chr;
26137e911b15Skarels 
2614b2b69f49Smarc 			/*
26157e911b15Skarels 			* Check for special function keys */
26167e911b15Skarels 
2617e977faadSmarc 			if (chr & 0x100) {
26187e911b15Skarels 				char *string;
26197e911b15Skarels 				string = q_special[chr & 0x7F];
26207e911b15Skarels 				while(*string)
26217e911b15Skarels 				    (*linesw[tp->t_line].l_rint)(*string++, tp);
26227e911b15Skarels 			}
26237e911b15Skarels 			else {
2624b2b69f49Smarc 				(*linesw[tp->t_line].l_rint)(chr&0177, tp);
26257e911b15Skarels 			}
26267e911b15Skarels 		}
26277e911b15Skarels 	}
26287e911b15Skarels } /* qdiint */
26297e911b15Skarels 
26307881ece5Smarc /*
26317e911b15Skarels  *
26327881ece5Smarc  * Clear the QDSS screen
26337e911b15Skarels  *
26347e911b15Skarels  *			     >>> NOTE <<<
26357e911b15Skarels  *
26367e911b15Skarels  *   This code requires that certain adder initialization be valid.  To
26377e911b15Skarels  *   assure that this requirement is satisfied, this routine should be
26387e911b15Skarels  *   called only after calling the "setup_dragon()" function.
26397e911b15Skarels  *
26407e911b15Skarels  *   Clear the bitmap a piece at a time. Since the fast scroll clear
26417e911b15Skarels  *   only clears the current displayed portion of the bitmap put a
26427e911b15Skarels  *   temporary value in the y limit register so we can access whole
26437e911b15Skarels  *   bitmap
26447e911b15Skarels  *
26457881ece5Smarc  */
26467e911b15Skarels clear_qd_screen(unit)
26477e911b15Skarels 	int unit;
26487e911b15Skarels {
26497e911b15Skarels 	register struct adder *adder;
26507e911b15Skarels 	adder = (struct adder *) qdmap[unit].adder;
26517e911b15Skarels 
26527e911b15Skarels 	adder->x_limit = 1024;
26537e911b15Skarels 	adder->y_limit = 2048 - CHAR_HEIGHT;
26547e911b15Skarels 	adder->y_offset_pending = 0;
26557881ece5Smarc #define WSV  (void)wait_status(adder, VSYNC); (void)wait_status(adder, VSYNC)
2656b2b69f49Smarc 	WSV;
26577e911b15Skarels 	adder->y_scroll_constant = SCROLL_ERASE;
2658b2b69f49Smarc 	WSV;
26597e911b15Skarels 	adder->y_offset_pending = 864;
2660b2b69f49Smarc 	WSV;
26617e911b15Skarels 	adder->y_scroll_constant = SCROLL_ERASE;
2662b2b69f49Smarc 	WSV;
26637e911b15Skarels 	adder->y_offset_pending = 1728;
2664b2b69f49Smarc 	WSV;
26657e911b15Skarels 	adder->y_scroll_constant = SCROLL_ERASE;
2666b2b69f49Smarc 	WSV;
26677e911b15Skarels 	adder->y_offset_pending = 0;	 /* back to normal */
2668b2b69f49Smarc 	WSV;
26697e911b15Skarels 	adder->x_limit = MAX_SCREEN_X;
26707e911b15Skarels 	adder->y_limit = MAX_SCREEN_Y + FONT_HEIGHT;
2671b2b69f49Smarc #undef WSV
26727e911b15Skarels 
26737e911b15Skarels } /* clear_qd_screen */
26747e911b15Skarels 
26757881ece5Smarc /*
26767881ece5Smarc  *  kernel console output to the glass tty
26777881ece5Smarc  */
26787e911b15Skarels qdputc(chr)
26797e911b15Skarels 	register char chr;
26807e911b15Skarels {
26817e911b15Skarels 
2682b2b69f49Smarc 	/*
2683b2b69f49Smarc 	 * if system is now physical, forget it (ie: crash DUMP)
2684b2b69f49Smarc 	 */
26857e911b15Skarels 	if ((mfpr(MAPEN) & 1) == 0)
26867e911b15Skarels 		return;
26877e911b15Skarels 
26887881ece5Smarc 	blitc(0, (u_char)(chr & 0xff));
268924f67f6bSmarc 	if ((chr & 0177) == '\n')
269024f67f6bSmarc 		blitc(0, '\r');
269124f67f6bSmarc 
26927e911b15Skarels } /* qdputc */
26937e911b15Skarels 
2694b2b69f49Smarc /*
26957881ece5Smarc  *  load the mouse cursor's template RAM bitmap
26967881ece5Smarc  */
26977e911b15Skarels ldcursor(unit, bitmap)
26987881ece5Smarc 	int unit;
26997881ece5Smarc 	register short *bitmap;
27007e911b15Skarels {
27017e911b15Skarels 	register struct dga *dga;
27027e911b15Skarels 	register short *temp;
27037e911b15Skarels 	register int i;
27047881ece5Smarc 	int curs;
27057e911b15Skarels 
27067e911b15Skarels 	dga = (struct dga *) qdmap[unit].dga;
27077e911b15Skarels 	temp = (short *) qdmap[unit].template;
27087e911b15Skarels 
27097e911b15Skarels 	if (dga->csr & CURS_ENB) {	/* if the cursor is enabled.. */
27107881ece5Smarc 		curs = -1;		/* ..note that.. */
27117e911b15Skarels 		dga->csr &= ~CURS_ENB;	/* ..and shut it off */
27127881ece5Smarc 	} else
27137881ece5Smarc 		curs = 0;
27147e911b15Skarels 
27157e911b15Skarels 	dga->csr &= ~CURS_ENB;		/* shut off the cursor */
27167e911b15Skarels 
27177e911b15Skarels 	temp += (8 * 1024) - 32;	/* cursor is 32 WORDS from the end */
27187e911b15Skarels 	/* ..of the 8k WORD template space */
27197e911b15Skarels 	for (i = 0; i < 32; ++i)
27207e911b15Skarels 		*temp++ = *bitmap++;
27217e911b15Skarels 
27227881ece5Smarc 	if (curs) {			/* if cursor was enabled.. */
27237e911b15Skarels 		dga->csr |= CURS_ENB;	/* ..turn it back on */
27247e911b15Skarels 	}
27257e911b15Skarels 
27267e911b15Skarels } /* ldcursor */
27277e911b15Skarels 
27287881ece5Smarc /*
27297881ece5Smarc  *  Put the console font in the QDSS off-screen memory
27307881ece5Smarc  */
27317e911b15Skarels ldfont(unit)
27327881ece5Smarc 	int unit;
27337e911b15Skarels {
27347e911b15Skarels 	register struct adder *adder;
27357e911b15Skarels 
27367881ece5Smarc 	register i, j, k, max_chars_line;
27377881ece5Smarc 	register short packed;
27387e911b15Skarels 
27397e911b15Skarels 	adder = (struct adder *) qdmap[unit].adder;
27407e911b15Skarels 
2741b2b69f49Smarc 	/*
27427881ece5Smarc 	* setup VIPER operand control registers
27437881ece5Smarc 	*/
27447e911b15Skarels 	write_ID(adder, MASK_1, 0xFFFF);
27457e911b15Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
27467e911b15Skarels 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
27477e911b15Skarels 
27487e911b15Skarels 	write_ID(adder, SRC1_OCR_B,
27497e911b15Skarels 	EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY);
27507e911b15Skarels 	write_ID(adder, SRC2_OCR_B,
27517e911b15Skarels 	EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY);
27527e911b15Skarels 	write_ID(adder, DST_OCR_B,
27537e911b15Skarels 	EXT_SOURCE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
27547e911b15Skarels 
27557e911b15Skarels 	adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL;
27567e911b15Skarels 
2757b2b69f49Smarc 	/*
27587881ece5Smarc 	* load destination data
27597881ece5Smarc 	*/
27607881ece5Smarc 	(void)wait_status(adder, RASTEROP_COMPLETE);
27617e911b15Skarels 
27627e911b15Skarels 	adder->destination_x = FONT_X;
27637e911b15Skarels 	adder->destination_y = FONT_Y;
27647881ece5Smarc #if FONT_WIDTH > MAX_SCREEN_X
2765e977faadSmarc 	adder->fast_dest_dx = MAX_SCREEN_X;
27667881ece5Smarc #else
27677e911b15Skarels 	adder->fast_dest_dx = FONT_WIDTH;
27687881ece5Smarc #endif
27697e911b15Skarels 	adder->slow_dest_dy = CHAR_HEIGHT;
27707e911b15Skarels 
2771b2b69f49Smarc 	/*
27727e911b15Skarels 	* setup for processor to bitmap xfer  */
27737e911b15Skarels 
27747e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0001);
27757e911b15Skarels 	adder->cmd = PBT | OCRB | 2 | DTE | 2;
27767e911b15Skarels 
2777b2b69f49Smarc 	/*
2778b2b69f49Smarc 	* Figure out how many characters can be stored on one "line" of
2779b2b69f49Smarc 	* offscreen memory.
2780e977faadSmarc 	*/
2781e977faadSmarc 	max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
2782e977faadSmarc 	if ((CHARS/2 + CHARS%2) < max_chars_line)
2783e977faadSmarc 	    max_chars_line = CHARS/2 + CHARS%2;
2784e977faadSmarc 
2785b2b69f49Smarc 	/*
2786e977faadSmarc 	* iteratively do the processor to bitmap xfer */
2787e977faadSmarc 
2788e977faadSmarc 	for (i = 0; i < ROWS; ++i) {
2789e977faadSmarc 
2790e977faadSmarc 		/* PTOB a scan line */
2791e977faadSmarc 
2792e977faadSmarc 		for (j = 0, k = i; j < max_chars_line; ++j) {
2793e977faadSmarc 			/* PTOB one scan of a char cell */
2794e977faadSmarc 
2795e977faadSmarc 			packed = q_font[k];
2796e977faadSmarc 			k += ROWS;
2797e977faadSmarc 			packed |= ((short)q_font[k] << 8);
2798e977faadSmarc 			k += ROWS;
2799e977faadSmarc 
28007881ece5Smarc 			(void)wait_status(adder, TX_READY);
2801e977faadSmarc 			adder->id_data = packed;
2802e977faadSmarc 		}
2803e977faadSmarc 	}
2804e977faadSmarc 
2805b2b69f49Smarc 	/*
2806b2b69f49Smarc 	 * (XXX XXX XXX - should remove)
2807b2b69f49Smarc 	 *
2808b2b69f49Smarc 	 * Copy the second row of characters.  Subtract the first
2809b2b69f49Smarc 	 * row from the total number.  Divide this quantity by 2
2810b2b69f49Smarc 	 * because 2 chars are stored in a short in the PTOB loop
2811b2b69f49Smarc 	 * below.  Figure out how many characters can be stored on
2812b2b69f49Smarc 	 * one "line" of offscreen memory
2813e977faadSmarc 	 */
2814b2b69f49Smarc 
2815e977faadSmarc 	max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
2816e977faadSmarc 	if ((CHARS/2 + CHARS%2) < max_chars_line)
2817e977faadSmarc 	    return;
2818e977faadSmarc 	max_chars_line = (CHARS/2 + CHARS%2) - max_chars_line; /* 95 - 64 */
2819e977faadSmarc 	/* Paranoia check to see if 3rd row may be needed */
2820e977faadSmarc 	if (max_chars_line > (MAX_SCREEN_X/(CHAR_WIDTH*2)))
2821e977faadSmarc 	    max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
2822e977faadSmarc 
2823e977faadSmarc 	adder->destination_x = FONT_X;
2824e977faadSmarc 	adder->destination_y = FONT_Y - CHAR_HEIGHT;
2825e977faadSmarc 	adder->fast_dest_dx = max_chars_line * CHAR_WIDTH * 2;
2826e977faadSmarc 	adder->slow_dest_dy = CHAR_HEIGHT;
2827e977faadSmarc 
2828b2b69f49Smarc 	/*
2829b2b69f49Smarc 	* setup for processor to bitmap xfer
2830b2b69f49Smarc 	*/
2831e977faadSmarc 	write_ID(adder, CS_UPDATE_MASK, 0x0001);
2832e977faadSmarc 	adder->cmd = PBT | OCRB | 2 | DTE | 2;
2833e977faadSmarc 
2834b2b69f49Smarc 	/*
2835b2b69f49Smarc 	* iteratively do the processor to bitmap xfer
2836b2b69f49Smarc 	*/
28377e911b15Skarels 	for (i = 0; i < ROWS; ++i) {
2838b2b69f49Smarc 		/*
2839b2b69f49Smarc 		 * PTOB a scan line
2840b2b69f49Smarc 		 */
2841e977faadSmarc 		for (j = 0, k = i; j < max_chars_line; ++j) {
2842b2b69f49Smarc 			/*
2843b2b69f49Smarc 			 * PTOB one scan of a char cell
2844b2b69f49Smarc 			 */
2845e977faadSmarc 			packed = q_font[k + FONT_OFFSET];
28467e911b15Skarels 			k += ROWS;
2847e977faadSmarc 			packed |= ((short)q_font[k + FONT_OFFSET] << 8);
28487e911b15Skarels 			k += ROWS;
28497881ece5Smarc 			(void)wait_status(adder, TX_READY);
28507e911b15Skarels 			adder->id_data = packed;
28517e911b15Skarels 		}
28527e911b15Skarels 	}
28537e911b15Skarels 
28547e911b15Skarels }  /* ldfont */
28557e911b15Skarels 
28567881ece5Smarc /*
28577881ece5Smarc  *  Get a character from the LK201 (polled)
28587881ece5Smarc  */
28597881ece5Smarc qdgetc()
28607e911b15Skarels {
28617881ece5Smarc 	register short key;
28627881ece5Smarc 	register char chr;
28637881ece5Smarc 	register struct duart *duart;
28647881ece5Smarc 
28657881ece5Smarc 	duart = (struct duart *) qdmap[0].duart;
28667881ece5Smarc 
28677881ece5Smarc 	/*
28687881ece5Smarc 	* Get a character from the keyboard.
28697881ece5Smarc 	*/
28707881ece5Smarc LOOP:
28717881ece5Smarc 	while (!(duart->statusA&RCV_RDY))
28727881ece5Smarc 		;
28737881ece5Smarc 
28747881ece5Smarc 	key = duart->dataA;
28757881ece5Smarc 	key &= 0xFF;
28767881ece5Smarc 
28777881ece5Smarc 	/*
28787881ece5Smarc 	* Check for various keyboard errors  */
28797881ece5Smarc 
28807881ece5Smarc 	if (key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
28817881ece5Smarc 	    key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
28827881ece5Smarc 		printf("Keyboard error, code = %x\n", key);
28837881ece5Smarc 		return(0);
28847881ece5Smarc 	}
28857881ece5Smarc 
28867881ece5Smarc 	if (key < LK_LOWEST)
28877881ece5Smarc 		return(0);
28887881ece5Smarc 
28897881ece5Smarc 	/*
28907881ece5Smarc 	 * See if its a state change key
28917881ece5Smarc 	 */
28927881ece5Smarc 	switch (key) {
28937881ece5Smarc 
28947881ece5Smarc 	case LOCK:
28957881ece5Smarc 		q_keyboard.lock ^= 0xffff;	/* toggle */
28967881ece5Smarc 		if (q_keyboard.lock)
28977881ece5Smarc 			(void)led_control(0, LK_LED_ENABLE, LK_LED_LOCK);
28987881ece5Smarc 		else
28997881ece5Smarc 			(void)led_control(0, LK_LED_DISABLE, LK_LED_LOCK);
29007881ece5Smarc 		goto LOOP;
29017881ece5Smarc 
29027881ece5Smarc 	case SHIFT:
29037881ece5Smarc 		q_keyboard.shift ^= 0xFFFF;
29047881ece5Smarc 		goto LOOP;
29057881ece5Smarc 
29067881ece5Smarc 	case CNTRL:
29077881ece5Smarc 		q_keyboard.cntrl ^= 0xFFFF;
29087881ece5Smarc 		goto LOOP;
29097881ece5Smarc 
29107881ece5Smarc 	case ALLUP:
29117881ece5Smarc 		q_keyboard.cntrl = 0;
29127881ece5Smarc 		q_keyboard.shift = 0;
29137881ece5Smarc 		goto LOOP;
29147881ece5Smarc 
29157881ece5Smarc 	case REPEAT:
29167881ece5Smarc 		chr = q_keyboard.last;
29177881ece5Smarc 		break;
29187881ece5Smarc 
29197881ece5Smarc 		/*
29207881ece5Smarc 		* Test for cntrl characters. If set, see if the character
29217881ece5Smarc 		* is elligible to become a control character.
29227881ece5Smarc 		*/
29237881ece5Smarc 	default:
29247881ece5Smarc 
29257881ece5Smarc 		if (q_keyboard.cntrl) {
29267881ece5Smarc 			chr = q_key[key];
29277881ece5Smarc 			if (chr >= ' ' && chr <= '~')
29287881ece5Smarc 			    chr &= 0x1F;
29297881ece5Smarc 		}
29307881ece5Smarc 		else if ( q_keyboard.lock || q_keyboard.shift )
29317881ece5Smarc 		    chr = q_shift_key[key];
29327881ece5Smarc 		else
29337881ece5Smarc 			chr = q_key[key];
29347881ece5Smarc 		break;
29357881ece5Smarc 	}
29367881ece5Smarc 
29377881ece5Smarc 	if (chr < ' ' && chr > '~')	/* if input is non-displayable */
29387881ece5Smarc 		return(0);		/* ..then pitch it! */
29397881ece5Smarc 
29407881ece5Smarc 	q_keyboard.last = chr;
29417881ece5Smarc 
29427881ece5Smarc 	/*
29437881ece5Smarc 	* Check for special function keys */
29447881ece5Smarc 
29457881ece5Smarc 	if (chr & 0x80) 		/* pitch the function keys */
29467881ece5Smarc 		return(0);
29477881ece5Smarc 	else
29487881ece5Smarc 		return(chr);
29497881ece5Smarc 
29507881ece5Smarc } /* qdgetc */
29517881ece5Smarc 
29527881ece5Smarc /*
29537881ece5Smarc  *  led_control()... twiddle LK-201 LED's
29547881ece5Smarc  */
29557881ece5Smarc led_control(unit, cmd, led_mask)
29567881ece5Smarc 	int unit, cmd, led_mask;
29577881ece5Smarc {
29587881ece5Smarc 	register i;
29597e911b15Skarels 	register struct duart *duart;
29607e911b15Skarels 
29617e911b15Skarels 	duart = (struct duart *)qdmap[unit].duart;
29627e911b15Skarels 
29637e911b15Skarels 	for (i = 1000; i > 0; --i) {
29647881ece5Smarc 		if (duart->statusA&XMT_RDY) {
29657e911b15Skarels 			duart->dataA = cmd;
29667e911b15Skarels 			break;
29677e911b15Skarels 		}
29687e911b15Skarels 	}
29697e911b15Skarels 	for (i = 1000; i > 0; --i) {
29707881ece5Smarc 		if (duart->statusA&XMT_RDY) {
29717e911b15Skarels 			duart->dataA = led_mask;
29727e911b15Skarels 			break;
29737e911b15Skarels 		}
29747e911b15Skarels 	}
29757e911b15Skarels 	if (i == 0)
29767e911b15Skarels 		return(BAD);
29777e911b15Skarels 	return(GOOD);
29787e911b15Skarels 
29797e911b15Skarels } /* led_control */
29807e911b15Skarels 
29817881ece5Smarc /*
29827e911b15Skarels  *  scroll_up()... move the screen up one character height
29837881ece5Smarc  */
29847e911b15Skarels scroll_up(adder)
29857e911b15Skarels 	register struct adder *adder;
29867e911b15Skarels {
2987b2b69f49Smarc 	/*
2988b2b69f49Smarc 	* setup VIPER operand control registers
2989b2b69f49Smarc 	*/
29907881ece5Smarc 	(void)wait_status(adder, ADDRESS_COMPLETE);
29917e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x00FF);  /* select all planes */
29927e911b15Skarels 	write_ID(adder, MASK_1, 0xFFFF);
29937e911b15Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
29947e911b15Skarels 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
29957e911b15Skarels 	write_ID(adder, SRC1_OCR_B,
29967e911b15Skarels 	EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY);
29977e911b15Skarels 	write_ID(adder, DST_OCR_B,
29987e911b15Skarels 	EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
2999b2b69f49Smarc 	/*
3000b2b69f49Smarc 	 * load DESTINATION origin and vectors
3001b2b69f49Smarc 	 */
30027e911b15Skarels 	adder->fast_dest_dy = 0;
30037e911b15Skarels 	adder->slow_dest_dx = 0;
30047e911b15Skarels 	adder->error_1 = 0;
30057e911b15Skarels 	adder->error_2 = 0;
30067e911b15Skarels 	adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL;
30077e911b15Skarels 	adder->destination_x = 0;
30087e911b15Skarels 	adder->fast_dest_dx = 1024;
30097e911b15Skarels 	adder->destination_y = 0;
30107e911b15Skarels 	adder->slow_dest_dy = 864 - CHAR_HEIGHT;
3011b2b69f49Smarc 	/*
3012b2b69f49Smarc 	 * load SOURCE origin and vectors
3013b2b69f49Smarc 	 */
30147e911b15Skarels 	adder->source_1_x = 0;
30157e911b15Skarels 	adder->source_1_dx = 1024;
30167e911b15Skarels 	adder->source_1_y = 0 + CHAR_HEIGHT;
30177e911b15Skarels 	adder->source_1_dy = 864 - CHAR_HEIGHT;
30187e911b15Skarels 	write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
30197e911b15Skarels 	adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE;
3020b2b69f49Smarc 	/*
3021b2b69f49Smarc 	 * do a rectangle clear of last screen line
3022b2b69f49Smarc 	 */
30237e911b15Skarels 	write_ID(adder, MASK_1, 0xffff);
30247e911b15Skarels 	write_ID(adder, SOURCE, 0xffff);
30257e911b15Skarels 	write_ID(adder,DST_OCR_B,
30267e911b15Skarels 	(EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY));
30277e911b15Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 0);
30287e911b15Skarels 	adder->error_1 = 0;
30297e911b15Skarels 	adder->error_2 = 0;
30307e911b15Skarels 	adder->slow_dest_dx = 0;		/* set up the width of	*/
30317e911b15Skarels 	adder->slow_dest_dy = CHAR_HEIGHT;	/* rectangle */
30327e911b15Skarels 	adder->rasterop_mode = (NORMAL | DST_WRITE_ENABLE) ;
30337881ece5Smarc 	(void)wait_status(adder, RASTEROP_COMPLETE);
30347e911b15Skarels 	adder->destination_x = 0;
30357e911b15Skarels 	adder->destination_y = 864 - CHAR_HEIGHT;
30367e911b15Skarels 	adder->fast_dest_dx = 1024;	/* set up the height	*/
30377e911b15Skarels 	adder->fast_dest_dy = 0;	/* of rectangle 	*/
30387e911b15Skarels 	write_ID(adder, LU_FUNCTION_R2, (FULL_SRC_RESOLUTION | LF_SOURCE));
30397e911b15Skarels 	adder->cmd = (RASTEROP | OCRB | LF_R2 | DTE ) ;
30407e911b15Skarels 
30417e911b15Skarels } /* scroll_up */
30427e911b15Skarels 
30437881ece5Smarc /*
30447881ece5Smarc  *  init shared memory pointers and structures
30457881ece5Smarc  */
30467e911b15Skarels init_shared(unit)
30477881ece5Smarc 	register unit;
30487e911b15Skarels {
30497e911b15Skarels 	register struct dga *dga;
30507e911b15Skarels 
30517e911b15Skarels 	dga = (struct dga *) qdmap[unit].dga;
30527e911b15Skarels 
3053b2b69f49Smarc 	/*
30547e911b15Skarels 	* initialize the event queue pointers and header */
30557e911b15Skarels 
30567e911b15Skarels 	eq_header[unit] = (struct qdinput *)
30577e911b15Skarels 	    ((((int)event_shared & ~(0x01FF)) + 512)
30587e911b15Skarels 		+ (EVENT_BUFSIZE * unit));
30597e911b15Skarels 	eq_header[unit]->curs_pos.x = 0;
30607e911b15Skarels 	eq_header[unit]->curs_pos.y = 0;
30617e911b15Skarels 	dga->x_cursor = TRANX(eq_header[unit]->curs_pos.x);
30627e911b15Skarels 	dga->y_cursor = TRANY(eq_header[unit]->curs_pos.y);
30637e911b15Skarels 	eq_header[unit]->curs_box.left = 0;
30647e911b15Skarels 	eq_header[unit]->curs_box.right = 0;
30657e911b15Skarels 	eq_header[unit]->curs_box.top = 0;
30667e911b15Skarels 	eq_header[unit]->curs_box.bottom = 0;
3067b2b69f49Smarc 	/*
3068b2b69f49Smarc 	 * assign a pointer to the DMA I/O buffer for this QDSS.
3069b2b69f49Smarc 	 */
30707e911b15Skarels 	DMAheader[unit] = (struct DMAreq_header *)
30717e911b15Skarels 	    (((int)(&DMA_shared[0] + 512) & ~0x1FF)
30727e911b15Skarels 		+ (DMAbuf_size * unit));
30737e911b15Skarels 	DMAheader[unit]->DMAreq = (struct DMAreq *) ((int)DMAheader[unit]
30747e911b15Skarels 	    + sizeof(struct DMAreq_header));
30757e911b15Skarels 	DMAheader[unit]->QBAreg = 0;
30767e911b15Skarels 	DMAheader[unit]->status = 0;
30777e911b15Skarels 	DMAheader[unit]->shared_size = DMAbuf_size;
30787e911b15Skarels 	DMAheader[unit]->used = 0;
30797e911b15Skarels 	DMAheader[unit]->size = 10;	/* default = 10 requests */
30807e911b15Skarels 	DMAheader[unit]->oldest = 0;
30817e911b15Skarels 	DMAheader[unit]->newest = 0;
3082b2b69f49Smarc 	/*
3083b2b69f49Smarc 	* assign a pointer to the scroll structure for this QDSS.
3084b2b69f49Smarc 	*/
30857e911b15Skarels 	scroll[unit] = (struct scroll *)
30867e911b15Skarels 	    (((int)(&scroll_shared[0] + 512) & ~0x1FF)
30877e911b15Skarels 		+ (sizeof(struct scroll) * unit));
30887e911b15Skarels 	scroll[unit]->status = 0;
30897e911b15Skarels 	scroll[unit]->viper_constant = 0;
30907e911b15Skarels 	scroll[unit]->y_scroll_constant = 0;
30917e911b15Skarels 	scroll[unit]->y_offset = 0;
30927e911b15Skarels 	scroll[unit]->x_index_pending = 0;
30937e911b15Skarels 	scroll[unit]->y_index_pending = 0;
3094b2b69f49Smarc 	/*
3095b2b69f49Smarc 	* assign a pointer to the color map write buffer for this QDSS
3096b2b69f49Smarc 	*/
30977e911b15Skarels 	color_buf[unit] = (struct color_buf *)
30987e911b15Skarels 	    (((int)(&color_shared[0] + 512) & ~0x1FF)
30997e911b15Skarels 		+ (COLOR_BUFSIZ * unit));
31007e911b15Skarels 	color_buf[unit]->status = 0;
31017e911b15Skarels 	color_buf[unit]->count = 0;
31027e911b15Skarels 
31037e911b15Skarels } /* init_shared */
31047e911b15Skarels 
31057881ece5Smarc /*
31067881ece5Smarc  * init the ADDER, VIPER, bitmaps, & color map
31077881ece5Smarc  */
31087e911b15Skarels setup_dragon(unit)
31097881ece5Smarc 	int unit;
31107e911b15Skarels {
31117e911b15Skarels 
31127e911b15Skarels 	register struct adder *adder;
31137e911b15Skarels 	register struct dga *dga;
31147e911b15Skarels 	short *memcsr;
31157881ece5Smarc 	register i;
31167e911b15Skarels 	short top;		/* clipping/scrolling boundaries */
31177e911b15Skarels 	short bottom;
31187e911b15Skarels 	short right;
31197e911b15Skarels 	short left;
31207e911b15Skarels 	short *red;		/* color map pointers */
31217e911b15Skarels 	short *green;
31227e911b15Skarels 	short *blue;
31237e911b15Skarels 
3124b2b69f49Smarc 	/*
3125b2b69f49Smarc 	* init for setup
3126b2b69f49Smarc 	*/
31277e911b15Skarels 	adder = (struct adder *) qdmap[unit].adder;
31287e911b15Skarels 	dga = (struct dga *) qdmap[unit].dga;
31297e911b15Skarels 	memcsr = (short *) qdmap[unit].memcsr;
31307e911b15Skarels 	dga->csr &= ~(DMA_IE | 0x700);	/* halt DMA and kill the intrpts */
31317e911b15Skarels 	*memcsr = SYNC_ON;		/* blank screen and turn off LED's */
31327e911b15Skarels 	adder->command = CANCEL;
3133b2b69f49Smarc 	/*
3134b2b69f49Smarc 	* set monitor timing
3135b2b69f49Smarc 	*/
31367e911b15Skarels 	adder->x_scan_count_0 = 0x2800;
31377e911b15Skarels 	adder->x_scan_count_1 = 0x1020;
31387e911b15Skarels 	adder->x_scan_count_2 = 0x003A;
31397e911b15Skarels 	adder->x_scan_count_3 = 0x38F0;
31407e911b15Skarels 	adder->x_scan_count_4 = 0x6128;
31417e911b15Skarels 	adder->x_scan_count_5 = 0x093A;
31427e911b15Skarels 	adder->x_scan_count_6 = 0x313C;
31437e911b15Skarels 	adder->sync_phase_adj = 0x0100;
31447e911b15Skarels 	adder->x_scan_conf = 0x00C8;
3145b2b69f49Smarc 	/*
3146b2b69f49Smarc 	 * got a bug in secound pass ADDER! lets take care of it
3147b2b69f49Smarc 	 *
3148b2b69f49Smarc 	 * normally, just use the code in the following bug fix code, but to
31497e911b15Skarels 	 * make repeated demos look pretty, load the registers as if there was
3150b2b69f49Smarc 	 * no bug and then test to see if we are getting sync
3151b2b69f49Smarc 	 */
31527e911b15Skarels 	adder->y_scan_count_0 = 0x135F;
31537e911b15Skarels 	adder->y_scan_count_1 = 0x3363;
31547e911b15Skarels 	adder->y_scan_count_2 = 0x2366;
31557e911b15Skarels 	adder->y_scan_count_3 = 0x0388;
3156b2b69f49Smarc 	/*
3157b2b69f49Smarc 	 * if no sync, do the bug fix code
3158b2b69f49Smarc 	 */
31597e911b15Skarels 	if (wait_status(adder, VSYNC) == BAD) {
31607e911b15Skarels 		/* first load all Y scan registers with very short frame and
31617e911b15Skarels 		 * wait for scroll service.  This guarantees at least one SYNC
31627e911b15Skarels 		 * to fix the pass 2 Adder initialization bug (synchronizes
3163b2b69f49Smarc 		 * XCINCH with DMSEEDH)
3164b2b69f49Smarc 		 */
31657e911b15Skarels 		adder->y_scan_count_0 = 0x01;
31667e911b15Skarels 		adder->y_scan_count_1 = 0x01;
31677e911b15Skarels 		adder->y_scan_count_2 = 0x01;
31687e911b15Skarels 		adder->y_scan_count_3 = 0x01;
3169b2b69f49Smarc 		/*
3170b2b69f49Smarc 		 * delay at least 1 full frame time
3171b2b69f49Smarc 		 */
31727881ece5Smarc 		(void)wait_status(adder, VSYNC);
31737881ece5Smarc 		(void)wait_status(adder, VSYNC);
3174b2b69f49Smarc 		/*
3175b2b69f49Smarc 		 * now load the REAL sync values (in reverse order just to
3176b2b69f49Smarc 		 * be safe.
3177b2b69f49Smarc 		 */
31787e911b15Skarels 		adder->y_scan_count_3 = 0x0388;
31797e911b15Skarels 		adder->y_scan_count_2 = 0x2366;
31807e911b15Skarels 		adder->y_scan_count_1 = 0x3363;
31817e911b15Skarels 		adder->y_scan_count_0 = 0x135F;
31827e911b15Skarels 	}
31837e911b15Skarels 	*memcsr = SYNC_ON | UNBLANK;	/* turn off leds and turn on video */
3184b2b69f49Smarc 	/*
3185b2b69f49Smarc 	 * zero the index registers
3186b2b69f49Smarc 	 */
31877e911b15Skarels 	adder->x_index_pending = 0;
31887e911b15Skarels 	adder->y_index_pending = 0;
31897e911b15Skarels 	adder->x_index_new = 0;
31907e911b15Skarels 	adder->y_index_new = 0;
31917e911b15Skarels 	adder->x_index_old = 0;
31927e911b15Skarels 	adder->y_index_old = 0;
31937e911b15Skarels 	adder->pause = 0;
3194b2b69f49Smarc 	/*
3195b2b69f49Smarc 	 * set rasterop mode to normal pen down
3196b2b69f49Smarc 	 */
31977e911b15Skarels 	adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL;
3198b2b69f49Smarc 	/*
3199b2b69f49Smarc 	 * set the rasterop registers to a default values
3200b2b69f49Smarc 	 */
32017e911b15Skarels 	adder->source_1_dx = 1;
32027e911b15Skarels 	adder->source_1_dy = 1;
32037e911b15Skarels 	adder->source_1_x = 0;
32047e911b15Skarels 	adder->source_1_y = 0;
32057e911b15Skarels 	adder->destination_x = 0;
32067e911b15Skarels 	adder->destination_y = 0;
32077e911b15Skarels 	adder->fast_dest_dx = 1;
32087e911b15Skarels 	adder->fast_dest_dy = 0;
32097e911b15Skarels 	adder->slow_dest_dx = 0;
32107e911b15Skarels 	adder->slow_dest_dy = 1;
32117e911b15Skarels 	adder->error_1 = 0;
32127e911b15Skarels 	adder->error_2 = 0;
3213b2b69f49Smarc 	/*
32147881ece5Smarc 	 * scale factor = UNITY
3215b2b69f49Smarc 	 */
32167e911b15Skarels 	adder->fast_scale = UNITY;
32177e911b15Skarels 	adder->slow_scale = UNITY;
3218b2b69f49Smarc 	/*
3219b2b69f49Smarc 	 * set the source 2 parameters
3220b2b69f49Smarc 	 */
32217e911b15Skarels 	adder->source_2_x = 0;
32227e911b15Skarels 	adder->source_2_y = 0;
32237e911b15Skarels 	adder->source_2_size = 0x0022;
3224b2b69f49Smarc 	/*
3225b2b69f49Smarc 	* initialize plane addresses for eight vipers
3226b2b69f49Smarc 	*/
32277e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0001);
32287e911b15Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0000);
32297e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0002);
32307e911b15Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0001);
32317e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0004);
32327e911b15Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0002);
32337e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0008);
32347e911b15Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0003);
32357e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0010);
32367e911b15Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0004);
32377e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0020);
32387e911b15Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0005);
32397e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0040);
32407e911b15Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0006);
32417e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0080);
32427e911b15Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0007);
3243b2b69f49Smarc 	/*
3244b2b69f49Smarc 	 * initialize the external registers.
3245b2b69f49Smarc 	 */
32467e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x00FF);
32477e911b15Skarels 	write_ID(adder, CS_SCROLL_MASK, 0x00FF);
3248b2b69f49Smarc 	/*
3249b2b69f49Smarc 	 * initialize resolution mode
3250b2b69f49Smarc 	 */
32517e911b15Skarels 	write_ID(adder, MEMORY_BUS_WIDTH, 0x000C);     /* bus width = 16 */
32527e911b15Skarels 	write_ID(adder, RESOLUTION_MODE, 0x0000);      /* one bit/pixel */
3253b2b69f49Smarc 	/*
3254b2b69f49Smarc 	 * initialize viper registers
3255b2b69f49Smarc 	 */
32567e911b15Skarels 	write_ID(adder, SCROLL_CONSTANT, SCROLL_ENABLE|VIPER_LEFT|VIPER_UP);
32577e911b15Skarels 	write_ID(adder, SCROLL_FILL, 0x0000);
3258b2b69f49Smarc 	/*
3259b2b69f49Smarc 	 * set clipping and scrolling limits to full screen
3260b2b69f49Smarc 	 */
3261b2b69f49Smarc 	for (i = 1000, adder->status = 0;
32627881ece5Smarc 	     i > 0 && !(adder->status&ADDRESS_COMPLETE); --i)
3263b2b69f49Smarc 		;
32647e911b15Skarels 	if (i == 0)
32657881ece5Smarc 	    printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n",unit);
32667e911b15Skarels 	top = 0;
32677e911b15Skarels 	bottom = 2048;
32687e911b15Skarels 	left = 0;
32697e911b15Skarels 	right = 1024;
32707e911b15Skarels 	adder->x_clip_min = left;
32717e911b15Skarels 	adder->x_clip_max = right;
32727e911b15Skarels 	adder->y_clip_min = top;
32737e911b15Skarels 	adder->y_clip_max = bottom;
32747e911b15Skarels 	adder->scroll_x_min = left;
32757e911b15Skarels 	adder->scroll_x_max = right;
32767e911b15Skarels 	adder->scroll_y_min = top;
32777e911b15Skarels 	adder->scroll_y_max = bottom;
32787881ece5Smarc 	(void)wait_status(adder, VSYNC);	/* wait at LEAST 1 full frame */
32797881ece5Smarc 	(void)wait_status(adder, VSYNC);
32807e911b15Skarels 	adder->x_index_pending = left;
32817e911b15Skarels 	adder->y_index_pending = top;
32827e911b15Skarels 	adder->x_index_new = left;
32837e911b15Skarels 	adder->y_index_new = top;
32847e911b15Skarels 	adder->x_index_old = left;
32857e911b15Skarels 	adder->y_index_old = top;
32867e911b15Skarels 
32877881ece5Smarc 	for (i = 1000, adder->status = 0; i > 0 &&
32887881ece5Smarc 	     !(adder->status&ADDRESS_COMPLETE) ; --i)
3289b2b69f49Smarc 		;
32907e911b15Skarels 	if (i == 0)
32917881ece5Smarc 	       printf("qd%d: setup_dragon: timeout on ADDRESS_COMPLETE\n",unit);
32927e911b15Skarels 
32937e911b15Skarels 	write_ID(adder, LEFT_SCROLL_MASK, 0x0000);
32947e911b15Skarels 	write_ID(adder, RIGHT_SCROLL_MASK, 0x0000);
3295b2b69f49Smarc 	/*
3296b2b69f49Smarc 	* set source and the mask register to all ones (ie: white) o
3297b2b69f49Smarc 	*/
32987e911b15Skarels 	write_ID(adder, SOURCE, 0xFFFF);
32997e911b15Skarels 	write_ID(adder, MASK_1, 0xFFFF);
33007e911b15Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
33017e911b15Skarels 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
3302b2b69f49Smarc 	/*
3303b2b69f49Smarc 	* initialize Operand Control Register banks for fill command
3304b2b69f49Smarc 	*/
33057e911b15Skarels 	write_ID(adder, SRC1_OCR_A, EXT_NONE | INT_M1_M2  | NO_ID | WAIT);
33067e911b15Skarels 	write_ID(adder, SRC2_OCR_A, EXT_NONE | INT_SOURCE | NO_ID | NO_WAIT);
33077e911b15Skarels 	write_ID(adder, DST_OCR_A, EXT_NONE | INT_NONE	 | NO_ID | NO_WAIT);
33087e911b15Skarels 	write_ID(adder, SRC1_OCR_B, EXT_NONE | INT_SOURCE | NO_ID | WAIT);
33097e911b15Skarels 	write_ID(adder, SRC2_OCR_B, EXT_NONE | INT_M1_M2  | NO_ID | NO_WAIT);
33107e911b15Skarels 	write_ID(adder, DST_OCR_B, EXT_NONE | INT_NONE | NO_ID | NO_WAIT);
3311b2b69f49Smarc 	/*
33127e911b15Skarels 	* init Logic Unit Function registers, (these are just common values,
3313b2b69f49Smarc 	* and may be changed as required).
3314b2b69f49Smarc 	*/
33157e911b15Skarels 	write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
3316b2b69f49Smarc 	write_ID(adder, LU_FUNCTION_R2, FULL_SRC_RESOLUTION | LF_SOURCE |
3317b2b69f49Smarc 		 INV_M1_M2);
33187e911b15Skarels 	write_ID(adder, LU_FUNCTION_R3, FULL_SRC_RESOLUTION | LF_D_OR_S);
33197e911b15Skarels 	write_ID(adder, LU_FUNCTION_R4, FULL_SRC_RESOLUTION | LF_D_XOR_S);
3320b2b69f49Smarc 	/*
3321b2b69f49Smarc 	* load the color map for black & white
3322b2b69f49Smarc 	*/
33237881ece5Smarc 	for (i = 0, adder->status = 0; i < 10000 && !(adder->status&VSYNC); ++i)
3324b2b69f49Smarc 		;
33257e911b15Skarels 
33267e911b15Skarels 	if (i == 0)
33277881ece5Smarc 		printf("qd%d: setup_dragon: timeout on VSYNC\n", unit);
33287e911b15Skarels 
33297e911b15Skarels 	red = (short *) qdmap[unit].red;
33307e911b15Skarels 	green = (short *) qdmap[unit].green;
33317e911b15Skarels 	blue = (short *) qdmap[unit].blue;
33327e911b15Skarels 
33337e911b15Skarels 	*red++ = 0x00;			/* black */
33347e911b15Skarels 	*green++ = 0x00;
33357e911b15Skarels 	*blue++ = 0x00;
33367e911b15Skarels 
33377e911b15Skarels 	*red-- = 0xFF;			/* white */
33387e911b15Skarels 	*green-- = 0xFF;
33397e911b15Skarels 	*blue-- = 0xFF;
33407e911b15Skarels 
3341b2b69f49Smarc 	/*
33427881ece5Smarc 	* set color map for mouse cursor
33437881ece5Smarc 	*/
33447e911b15Skarels 
33457e911b15Skarels 	red += 254;
33467e911b15Skarels 	green += 254;
33477e911b15Skarels 	blue += 254;
33487e911b15Skarels 
33497e911b15Skarels 	*red++ = 0x00;			/* black */
33507e911b15Skarels 	*green++ = 0x00;
33517e911b15Skarels 	*blue++ = 0x00;
33527e911b15Skarels 
33537e911b15Skarels 	*red = 0xFF;			/* white */
33547e911b15Skarels 	*green = 0xFF;
33557e911b15Skarels 	*blue = 0xFF;
33567e911b15Skarels 
33577e911b15Skarels } /* setup_dragon */
33587e911b15Skarels 
33597881ece5Smarc /*
33607881ece5Smarc  * Init the DUART and set defaults in input
33617881ece5Smarc  */
33627e911b15Skarels setup_input(unit)
33637881ece5Smarc 	int unit;
33647e911b15Skarels {
33657e911b15Skarels 	register struct duart *duart;	/* DUART register structure pointer */
33667881ece5Smarc 	register i, bits;
33677e911b15Skarels 	char id_byte;
33687e911b15Skarels 
33697e911b15Skarels 	duart = (struct duart *) qdmap[unit].duart;
33707e911b15Skarels 	duart->imask = 0;
33717e911b15Skarels 
3372b2b69f49Smarc 	/*
3373b2b69f49Smarc 	* setup the DUART for kbd & pointing device
3374b2b69f49Smarc 	*/
33757e911b15Skarels 	duart->cmdA = RESET_M;	/* reset mode reg ptr for kbd */
33767e911b15Skarels 	duart->modeA = 0x13;	/* 8 bits, no parity, rcv IE, */
33777e911b15Skarels 				/* no RTS control,char error mode */
33787e911b15Skarels 	duart->modeA = 0x07;	/* 1 stop bit,CTS does not IE XMT */
33797e911b15Skarels 				/* no RTS control,no echo or loop */
33807e911b15Skarels 	duart->cmdB = RESET_M;	/* reset mode reg pntr for host */
33817e911b15Skarels 	duart->modeB = 0x07;	/* 8 bits, odd parity, rcv IE.. */
33827e911b15Skarels 				/* ..no RTS cntrl, char error mode */
33837e911b15Skarels 	duart->modeB = 0x07;	/* 1 stop bit,CTS does not IE XMT */
33847e911b15Skarels 				/* no RTS control,no echo or loop */
33857e911b15Skarels 	duart->auxctl = 0x00;	/* baud rate set 1 */
33867e911b15Skarels 	duart->clkselA = 0x99;	/* 4800 baud for kbd */
33877e911b15Skarels 	duart->clkselB = 0x99;	/* 4800 baud for mouse */
33887e911b15Skarels 
33897e911b15Skarels 	/* reset everything for keyboard */
33907e911b15Skarels 
33917e911b15Skarels 	for (bits = RESET_M; bits < START_BREAK; bits += 0x10)
33927e911b15Skarels 		duart->cmdA = bits;
33937e911b15Skarels 
33947e911b15Skarels 	/* reset everything for host */
33957e911b15Skarels 
33967e911b15Skarels 	for (bits = RESET_M; bits < START_BREAK; bits += 0x10)
33977e911b15Skarels 		duart->cmdB = bits;
33987e911b15Skarels 
33997e911b15Skarels 	duart->cmdA = EN_RCV | EN_XMT; /* enbl xmt & rcv for kbd */
34007e911b15Skarels 	duart->cmdB = EN_RCV | EN_XMT; /* enbl xmt & rcv for pointer device */
34017e911b15Skarels 
3402b2b69f49Smarc 	/*
34037881ece5Smarc 	* init keyboard defaults (DUART channel A)
34047881ece5Smarc 	*/
34057e911b15Skarels 	for (i = 500; i > 0; --i) {
34067881ece5Smarc 		if (duart->statusA&XMT_RDY) {
34077e911b15Skarels 			duart->dataA = LK_DEFAULTS;
34087e911b15Skarels 			break;
34097e911b15Skarels 		}
34107e911b15Skarels 	}
34117e911b15Skarels 
34127e911b15Skarels 	for (i = 100000; i > 0; --i) {
34137881ece5Smarc 		if (duart->statusA&RCV_RDY) {
34147e911b15Skarels 			break;
34157e911b15Skarels 		}
34167e911b15Skarels 	}
34177e911b15Skarels 
34187881ece5Smarc 	if (duart->dataA)	/* flush the ACK */
34197881ece5Smarc 		;
34207e911b15Skarels 
3421b2b69f49Smarc 	/*
34227881ece5Smarc 	* identify the pointing device
34237881ece5Smarc 	*/
34247e911b15Skarels 	for (i = 500; i > 0; --i) {
34257881ece5Smarc 		if (duart->statusB&XMT_RDY) {
34267e911b15Skarels 			duart->dataB = SELF_TEST;
34277e911b15Skarels 			break;
34287e911b15Skarels 		}
34297e911b15Skarels 	}
34307e911b15Skarels 
3431b2b69f49Smarc 	/*
34327e911b15Skarels 	* wait for 1st byte of self test report */
34337e911b15Skarels 
34347e911b15Skarels 	for (i = 100000; i > 0; --i) {
34357881ece5Smarc 		if (duart->statusB&RCV_RDY) {
34367e911b15Skarels 			break;
34377e911b15Skarels 		}
34387e911b15Skarels 	}
34397e911b15Skarels 
34407e911b15Skarels 	if (i == 0) {
34417881ece5Smarc 		printf("qd[%d]: setup_input: timeout on 1st byte of self test\n"
3442b2b69f49Smarc 		       ,unit);
34437e911b15Skarels 		goto OUT;
34447e911b15Skarels 	}
34457e911b15Skarels 
34467881ece5Smarc 	if (duart->dataB)
34477881ece5Smarc 		;
34487e911b15Skarels 
3449b2b69f49Smarc 	/*
34507881ece5Smarc 	* wait for ID byte of self test report
34517881ece5Smarc 	*/
34527e911b15Skarels 	for (i = 100000; i > 0; --i) {
34537881ece5Smarc 		if (duart->statusB&RCV_RDY) {
34547e911b15Skarels 			break;
34557e911b15Skarels 		}
34567e911b15Skarels 	}
34577e911b15Skarels 
34587e911b15Skarels 	if (i == 0) {
34597881ece5Smarc 		printf("qd[%d]: setup_input: timeout on 2nd byte of self test\n", unit);
34607e911b15Skarels 		goto OUT;
34617e911b15Skarels 	}
34627e911b15Skarels 
34637e911b15Skarels 	id_byte = duart->dataB;
34647e911b15Skarels 
3465b2b69f49Smarc 	/*
34667881ece5Smarc 	* wait for other bytes to come in
34677881ece5Smarc 	*/
34687e911b15Skarels 	for (i = 100000; i > 0; --i) {
34697881ece5Smarc 		if (duart->statusB & RCV_RDY) {
34707881ece5Smarc 			if (duart->dataB)
34717881ece5Smarc 				;
34727e911b15Skarels 			break;
34737e911b15Skarels 		}
34747e911b15Skarels 	}
34757e911b15Skarels 	if (i == 0) {
34767881ece5Smarc 		printf("qd[%d]: setup_input: timeout on 3rd byte of self test\n", unit);
34777e911b15Skarels 		goto OUT;
34787e911b15Skarels 	}
34797e911b15Skarels 	for (i = 100000; i > 0; --i) {
34807881ece5Smarc 		if (duart->statusB&RCV_RDY) {
34817881ece5Smarc 			if (duart->dataB)
34827881ece5Smarc 				;
34837e911b15Skarels 			break;
34847e911b15Skarels 		}
34857e911b15Skarels 	}
34867e911b15Skarels 	if (i == 0) {
34877881ece5Smarc 		printf("qd[%d]: setup_input: timeout on 4th byte of self test\n", unit);
34887e911b15Skarels 		goto OUT;
34897e911b15Skarels 	}
3490b2b69f49Smarc 	/*
34917881ece5Smarc 	* flag pointing device type and set defaults
34927881ece5Smarc 	*/
34937881ece5Smarc 	for (i=100000; i>0; --i)
34947881ece5Smarc 		;		/*XXX*/
34957e911b15Skarels 
34967e911b15Skarels 	if ((id_byte & 0x0F) != TABLET_ID) {
34977e911b15Skarels 		qdflags[unit].pntr_id = MOUSE_ID;
34987e911b15Skarels 
34997e911b15Skarels 		for (i = 500; i > 0; --i) {
35007881ece5Smarc 			if (duart->statusB&XMT_RDY) {
35017e911b15Skarels 				duart->dataB = INC_STREAM_MODE;
35027e911b15Skarels 				break;
35037e911b15Skarels 			}
35047e911b15Skarels 		}
3505b2b69f49Smarc 	}
3506b2b69f49Smarc 	else {
35077e911b15Skarels 		qdflags[unit].pntr_id = TABLET_ID;
35087e911b15Skarels 
35097e911b15Skarels 		for (i = 500; i > 0; --i) {
35107881ece5Smarc 			if (duart->statusB&XMT_RDY) {
35117e911b15Skarels 				duart->dataB = T_STREAM;
35127e911b15Skarels 				break;
35137e911b15Skarels 			}
35147e911b15Skarels 		}
35157e911b15Skarels 	}
35167e911b15Skarels OUT:
35177e911b15Skarels 	duart->imask = qdflags[unit].duart_imask;
35187e911b15Skarels 
35197e911b15Skarels } /* setup_input */
35207e911b15Skarels 
35217881ece5Smarc /*
35227881ece5Smarc  * delay for at least one display frame time
35237e911b15Skarels  *
35247e911b15Skarels  *	return: BAD means that we timed out without ever seeing the
35257e911b15Skarels  *		      vertical sync status bit
35267e911b15Skarels  *		GOOD otherwise
35277881ece5Smarc  */
35287e911b15Skarels wait_status(adder, mask)
35297e911b15Skarels 	register struct adder *adder;
35307e911b15Skarels 	register int mask;
35317e911b15Skarels {
35327881ece5Smarc 	register i;
35337e911b15Skarels 
3534b2b69f49Smarc 	for (i = 10000, adder->status = 0 ; i > 0  &&
35357881ece5Smarc 	     !(adder->status&mask) ; --i)
3536b2b69f49Smarc 		;
35377e911b15Skarels 
35387e911b15Skarels 	if (i == 0) {
35397881ece5Smarc 		printf("wait_status: timeout polling for 0x%x in adder->status\n", mask);
35407e911b15Skarels 		return(BAD);
35417e911b15Skarels 	}
35427e911b15Skarels 
35437e911b15Skarels 	return(GOOD);
35447e911b15Skarels 
35457e911b15Skarels } /* wait_status */
35467e911b15Skarels 
35477881ece5Smarc /*
35487881ece5Smarc  * write out onto the ID bus
35497881ece5Smarc  */
35507e911b15Skarels write_ID(adder, adrs, data)
35517e911b15Skarels 	register struct adder *adder;
35527e911b15Skarels 	register short adrs;
35537e911b15Skarels 	register short data;
35547e911b15Skarels {
35557881ece5Smarc 	register i;
35567e911b15Skarels 
3557b2b69f49Smarc 	for (i = 100000, adder->status = 0 ;
35587881ece5Smarc 	      i > 0  &&  !(adder->status&ADDRESS_COMPLETE) ; --i)
3559b2b69f49Smarc 		;
35607e911b15Skarels 
35617e911b15Skarels 	if (i == 0)
35627e911b15Skarels 		goto ERR;
35637e911b15Skarels 
3564b2b69f49Smarc 	for (i = 100000, adder->status = 0 ;
35657881ece5Smarc 	      i > 0  &&  !(adder->status&TX_READY) ; --i)
3566b2b69f49Smarc 		;
35677e911b15Skarels 
35687e911b15Skarels 	if (i > 0) {
35697e911b15Skarels 		adder->id_data = data;
35707e911b15Skarels 		adder->command = ID_LOAD | adrs;
35717881ece5Smarc 		return ;
35727e911b15Skarels 	}
35737e911b15Skarels 
35747e911b15Skarels ERR:
35757881ece5Smarc 	printf("write_ID: timeout trying to write to VIPER\n");
35767881ece5Smarc 	return ;
35777e911b15Skarels 
35787e911b15Skarels } /* write_ID */
3579006e9885Smarc #endif
3580