xref: /csrg-svn/sys/vax/uba/qd.c (revision 30391)
1*30391Skarels 
2*30391Skarels #ifndef lint
3*30391Skarels static char *sccsid = "@(#)qd.c	1.40	ULTRIX	10/2/86";
4*30391Skarels #endif lint
5*30391Skarels 
6*30391Skarels /************************************************************************
7*30391Skarels  *									*
8*30391Skarels  *			Copyright (c) 1985, 1986 by			*
9*30391Skarels *		Digital Equipment Corporation, Maynard, MA		*
10*30391Skarels *			All rights reserved.				*
11*30391Skarels *									*
12*30391Skarels *   This software is furnished under a license and may be used and	*
13*30391Skarels *   copied  only  in accordance with the terms of such license and	*
14*30391Skarels *   with the  inclusion  of  the  above  copyright  notice.   This	*
15*30391Skarels *   software  or  any  other copies thereof may not be provided or	*
16*30391Skarels *   otherwise made available to any other person.  No title to and	*
17*30391Skarels *   ownership of the software is hereby transferred.			*
18*30391Skarels *									*
19*30391Skarels *   The information in this software is subject to change  without	*
20*30391Skarels *   notice  and should not be construed as a commitment by Digital	*
21*30391Skarels *   Equipment Corporation.						*
22*30391Skarels *									*
23*30391Skarels *   Digital assumes no responsibility for the use  or  reliability	*
24*30391Skarels *   of its software on equipment which is not supplied by Digital.	*
25*30391Skarels *									*
26*30391Skarels *************************************************************************/
27*30391Skarels 
28*30391Skarels /*
29*30391Skarels  * qd.c
30*30391Skarels  *
31*30391Skarels  * Modification history
32*30391Skarels  *
33*30391Skarels  * QDSS workstation driver
34*30391Skarels  *
35*30391Skarels  * 26-Aug-86 - rsp (Ricky Palmer)
36*30391Skarels  *
37*30391Skarels  *	Cleaned up devioctl code to (1) zero out devget structure
38*30391Skarels  *	upon entry and (2) use strlen instead of fixed storage
39*30391Skarels  *	for bcopy's.
40*30391Skarels  *
41*30391Skarels  * 21-Jul-86 - Ram Rao
42*30391Skarels  *	allowed cursor rectangle to hang (partially) off the
43*30391Skarels  *	top and left of screen
44*30391Skarels  *
45*30391Skarels  * 11-Jul-86 - ricky palmer
46*30391Skarels  *
47*30391Skarels  *	Added adpt and nexus fields to DEVIOCGET code.
48*30391Skarels  *
49*30391Skarels  * 02-July-86 - Brian Stevens
50*30391Skarels  *
51*30391Skarels  *	added support for console writing to second QDSS display
52*30391Skarels  *
53*30391Skarels  * 20-May-86 - ricky palmer
54*30391Skarels  *
55*30391Skarels  *	Added new DEVIOCGET ioctl request code. V2.0
56*30391Skarels  *
57*30391Skarels  * 16-Apr-86 -- darrell
58*30391Skarels  *	 badaddr is now called via the macro BADADDR
59*30391Skarels  *
60*30391Skarels  * 14-Apr-86 -- afd
61*30391Skarels  *	 Changed UMEMmap to QMEMmap and umem to qmem.
62*30391Skarels  *
63*30391Skarels  *	 v_console() is now refered to as v_consputc, and there is a
64*30391Skarels  *	 corresponding v_consgetc() (defined in /sys/vax/conf.c).
65*30391Skarels  *
66*30391Skarels  *	 Added "qdgetc()" routine for console read.  Needed to read
67*30391Skarels  *	 user's answer to the "root device?" prompt with a generic kernel.
68*30391Skarels  *
69*30391Skarels  * 19-Mar-86 -- pmk
70*30391Skarels  *	 Change DELAY to 20000, because microdelay now in real microsec.
71*30391Skarels  *
72*30391Skarels  * 18-mar-86  -- jaw	 br/cvec changed to NOT use registers.
73*30391Skarels  *
74*30391Skarels  * 11 mar 86  darrell	replaced percpu with cpusw, and removed all but
75*30391Skarels  *			 one global reference
76*30391Skarels  * 19 feb 86  bstevens	no report of motion event on puck/stylus button action
77*30391Skarels  * 18 feb 86  bstevens	put in cursor box support for tablets
78*30391Skarels  * 18-Mar-86 -- jaw  add routines to cpu switch for nexus/unibus addreses
79*30391Skarels  *		      also got rid of some globals like nexnum.
80*30391Skarels  *		      ka8800 cleanup.
81*30391Skarels  * 06 dec 85  longo  added LK-201 error reporting for graphics device ops
82*30391Skarels  * 03 dec 85  longo  made qddint() clear active bit on error
83*30391Skarels  * 02 dec 85  longo  fixed up some crocks in the error messages
84*30391Skarels  * 25 nov 85  longo  added error handling to DMA ISR and single user locking
85*30391Skarels  * 19 nov 85  longo  eliminated "set_defaults()" by breaking out sub-calls.
86*30391Skarels  *		     Changed init_shared to do real init of scroll struct
87*30391Skarels  * 12 nov 85  longo  fixed bug in open that broke alternate console re-direct
88*30391Skarels  * 11 nov 85  longo  changed "_vs_eventqueue" references to "qdinput"
89*30391Skarels  * 08 nov 85  longo  improved select service for read/write select wakeup.
90*30391Skarels  *		     Also set ISR's to ipl4 to allow the interval timer in.
91*30391Skarels  * 04 nov 85  longo  fixed bugs in mouse button reporting and dma request stuff
92*30391Skarels  * 30 oct 85  longo  DMA to/from user space is in place
93*30391Skarels  * 14 oct 85  longo  added kernel msg redirect and QD_RDCURSOR ioctl
94*30391Skarels  * 03 oct 85  longo  added support for multiple QDSS's
95*30391Skarels  * 02 oct 85  longo  added color map loading services in qdioctl() & qdaint()
96*30391Skarels  * 30 sep 85  longo  added DMA interrupt services
97*30391Skarels  * 18 sep 85  longo  added scroll services to "qdaint()" adder intrpt service
98*30391Skarels  *		     and put in supporting ioctl's
99*30391Skarels  * 04 sep 85  longo  initial implementation of DMA is working
100*30391Skarels  * 17 aug 85  longo  added support for the QDSS to be system console
101*30391Skarels  * 05 aug 85  longo  now using qfont (QVSS & QDSS) as linked object
102*30391Skarels  * 12 jun 85  longo  added mouse event loading to "qdiint()"
103*30391Skarels  * 31 may 85  longo  put live interrupts into the probe() routine
104*30391Skarels  * 30 may 85  longo  event queue shared memory implementation is now alive
105*30391Skarels  * 29 may 85  longo  LK-201 input is now interrupt driven
106*30391Skarels  * 25 apr 85  longo  MAPDEVICE works
107*30391Skarels  * 14 mar 85  longo  created
108*30391Skarels  *
109*30391Skarels  *	 todo:	 fix rlogin bug in console stuff
110*30391Skarels  *		 cat -u console redirection
111*30391Skarels  *		 check error return from strategy routine
112*30391Skarels  *		 verify TOY time stuff (what format?)
113*30391Skarels  *		 look at system based macro implementation of VTOP
114*30391Skarels  *
115*30391Skarels  */
116*30391Skarels 
117*30391Skarels #include "../data/qd_data.c"	/* include external references to data file */
118*30391Skarels 
119*30391Skarels /*---------------------------------------------------------------------
120*30391Skarels * macro to get system time.  Used to time stamp event queue entries */
121*30391Skarels 
122*30391Skarels #define TOY ((time.tv_sec * 100) + (time.tv_usec / 10000))
123*30391Skarels 
124*30391Skarels /*--------------------------------------------------------------------------
125*30391Skarels * the "ioconf.c" program, built and used by auto config, externally refers
126*30391Skarels * to definitions below.  */
127*30391Skarels 
128*30391Skarels 	int qdprobe();
129*30391Skarels 	int qdattach();
130*30391Skarels 	int qddint();			/* DMA gate array intrpt service */
131*30391Skarels 	int qdaint();			/* Dragon ADDER intrpt service */
132*30391Skarels 	int qdiint();
133*30391Skarels 
134*30391Skarels 	u_short qdstd[] = { 0 };
135*30391Skarels 
136*30391Skarels 	struct uba_driver qddriver = {	/* externally referenced: ioconf.c */
137*30391Skarels 
138*30391Skarels 	    qdprobe,			/* device probe entry */
139*30391Skarels 	    0,				/* no slave device */
140*30391Skarels 	    qdattach,			/* device attach entry */
141*30391Skarels 	    0,				/* no "fill csr/ba to start" */
142*30391Skarels 	    qdstd,			/* device addresses */
143*30391Skarels 	    "qd",			/* device name string */
144*30391Skarels 	    qdinfo			/* ptr to QDSS's uba_device struct */
145*30391Skarels 	};
146*30391Skarels 
147*30391Skarels /*-------------------
148*30391Skarels * general defines */
149*30391Skarels 
150*30391Skarels #define QDPRIOR (PZERO-1)		/* must be negative */
151*30391Skarels 
152*30391Skarels #define FALSE	0
153*30391Skarels #define TRUE	~FALSE
154*30391Skarels 
155*30391Skarels #define BAD	-1
156*30391Skarels #define GOOD	0
157*30391Skarels 
158*30391Skarels /*-----------------------------------------------------------------------
159*30391Skarels * macro to create a system virtual page number from system virtual adrs */
160*30391Skarels 
161*30391Skarels #define VTOP(x)  (((int)x & ~0xC0000000) >> PGSHIFT) /* convert qmem adrs */
162*30391Skarels 						     /* to system page # */
163*30391Skarels 
164*30391Skarels /*------------------------------------------------------------------
165*30391Skarels * QDSS register address offsets from start of QDSS address space */
166*30391Skarels 
167*30391Skarels #define QDSIZE	 (52 * 1024)	/* size of entire QDSS foot print */
168*30391Skarels 
169*30391Skarels #define TMPSIZE  (16 * 1024)	/* template RAM is 8k SHORT WORDS */
170*30391Skarels #define TMPSTART 0x8000 	/* offset of template RAM from base adrs */
171*30391Skarels 
172*30391Skarels #define REGSIZE  (5 * 512)	/* regs touch 2.5k (5 pages) of addr space */
173*30391Skarels #define REGSTART 0xC000 	/* offset of reg pages from base adrs */
174*30391Skarels 
175*30391Skarels #define ADDER	(REGSTART+0x000)
176*30391Skarels #define DGA	(REGSTART+0x200)
177*30391Skarels #define DUART	(REGSTART+0x400)
178*30391Skarels #define MEMCSR	(REGSTART+0x800)
179*30391Skarels 
180*30391Skarels #define CLRSIZE  (3 * 512)		/* color map size */
181*30391Skarels #define CLRSTART (REGSTART+0xA00)	/* color map start offset from base */
182*30391Skarels 					/*  0x0C00 really */
183*30391Skarels #define RED	(CLRSTART+0x000)
184*30391Skarels #define BLUE	(CLRSTART+0x200)
185*30391Skarels #define GREEN	(CLRSTART+0x400)
186*30391Skarels 
187*30391Skarels /*---------------------------------------------------------------
188*30391Skarels * values used in mapping QDSS hardware into the Q memory space */
189*30391Skarels 
190*30391Skarels #define CHUNK	  (64 * 1024)
191*30391Skarels #define QMEMSIZE  (1024 * 1024 * 4)	/* 4 meg */
192*30391Skarels 
193*30391Skarels /*----------------------------------------------------------------------
194*30391Skarels * QDSS minor device numbers.  The *real* minor device numbers are in
195*30391Skarels * the bottom two bits of the major/minor device spec.  Bits 2 and up are
196*30391Skarels * used to specify the QDSS device number (ie: which one?) */
197*30391Skarels 
198*30391Skarels #define QDSSMAJOR	42		/* QDSS major device number */
199*30391Skarels 
200*30391Skarels #define CONS		0
201*30391Skarels #define ALTCONS 	1
202*30391Skarels #define GRAPHIC 	2
203*30391Skarels 
204*30391Skarels /*----------------------------------------------
205*30391Skarels * console cursor bitmap (block cursor type)  */
206*30391Skarels 
207*30391Skarels 	short cons_cursor[32] = {      /* white block cursor */
208*30391Skarels 
209*30391Skarels  /* A */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
210*30391Skarels 	 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
211*30391Skarels  /* B */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
212*30391Skarels 	 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF
213*30391Skarels 
214*30391Skarels 	};
215*30391Skarels 
216*30391Skarels /*-------------------------------------
217*30391Skarels * constants used in font operations */
218*30391Skarels 
219*30391Skarels #define CHARS		95			/* # of chars in the font */
220*30391Skarels #define CHAR_HEIGHT	15			/* char height in pixels */
221*30391Skarels #define CHAR_WIDTH	8			/* char width in pixels*/
222*30391Skarels #define FONT_WIDTH	(CHAR_WIDTH * CHARS)	/* font width in pixels */
223*30391Skarels #define ROWS		CHAR_HEIGHT
224*30391Skarels 
225*30391Skarels 
226*30391Skarels #define FONT_X		0			/* font's off screen adrs */
227*30391Skarels #define FONT_Y		(2048 - CHAR_HEIGHT)
228*30391Skarels /*
229*30391Skarels #define FONT_Y		200
230*30391Skarels */
231*30391Skarels 
232*30391Skarels 	extern char q_font[];		/* reference font object code */
233*30391Skarels 
234*30391Skarels 	extern	char q_key[];		/* reference key xlation tables */
235*30391Skarels 	extern	char q_shift_key[];
236*30391Skarels 	extern	char *q_special[];
237*30391Skarels 
238*30391Skarels /*--------------------------------------------------
239*30391Skarels * definitions for cursor acceleration reporting  */
240*30391Skarels 
241*30391Skarels #define ACC_OFF 	0x01		/* acceleration is inactive */
242*30391Skarels 
243*30391Skarels /*--------------------------------------------------------------------------
244*30391Skarels * v_consputc is the switch that is used to redirect the console cnputc() to
245*30391Skarels * the virtual console qdputc().
246*30391Skarels * v_consgetc is the switch that is used to redirect the console getchar() to
247*30391Skarels * the virtual console qdgetc().
248*30391Skarels */
249*30391Skarels 
250*30391Skarels 	extern (*v_consputc)();
251*30391Skarels 	int qdputc();		/* used to direct kernel console output */
252*30391Skarels 	extern (*v_consgetc)();
253*30391Skarels 	int qdgetc();		/* used to read kernel console input */
254*30391Skarels 
255*30391Skarels 	int qdstart();		/* used to direct /dev/console output */
256*30391Skarels 
257*30391Skarels /*------------------------------------------------------------------------
258*30391Skarels * LK-201 state storage for input console keyboard conversion to ASCII */
259*30391Skarels 
260*30391Skarels 	struct q_keyboard {
261*30391Skarels 
262*30391Skarels 	    int shift;			/* state variables	*/
263*30391Skarels 	    int cntrl;
264*30391Skarels 	    int lock;
265*30391Skarels 	    int lastcode;		/* last keycode typed	*/
266*30391Skarels 	    unsigned kup[8];		/* bits for each keycode*/
267*30391Skarels 	    unsigned dkeys[8];		/* down/up mode keys	*/
268*30391Skarels 	    char last;			/* last character	*/
269*30391Skarels 
270*30391Skarels 	 } q_keyboard;
271*30391Skarels 
272*30391Skarels 
273*30391Skarels /*****************************************************************
274*30391Skarels ******************************************************************
275*30391Skarels ******************************************************************
276*30391Skarels *
277*30391Skarels *	DRIVER FUNCTIONS START HERE:
278*30391Skarels *
279*30391Skarels ******************************************************************
280*30391Skarels ******************************************************************
281*30391Skarels *****************************************************************/
282*30391Skarels 
283*30391Skarels /*********************************************************************
284*30391Skarels *
285*30391Skarels *	qdcons_init()... init QDSS as console (before probe routine)
286*30391Skarels *
287*30391Skarels *********************************************************************/
288*30391Skarels 
289*30391Skarels qdcons_init()
290*30391Skarels {
291*30391Skarels 	register u_int unit;
292*30391Skarels 
293*30391Skarels 	int *ptep;			/* page table entry pointer */
294*30391Skarels 	caddr_t phys_adr;		/* physical QDSS base adrs */
295*30391Skarels 	u_int mapix;			/* index into QMEMmap[] array */
296*30391Skarels 
297*30391Skarels 	struct cpusw *cpup;		/* pointer to cpusw structure  */
298*30391Skarels 	u_short *qdaddr;		/* address of QDSS IO page CSR */
299*30391Skarels 	u_short *devptr;		/* vitual device space */
300*30391Skarels 
301*30391Skarels #define QDSSCSR 0x1F00
302*30391Skarels 
303*30391Skarels 	unit = 0;
304*30391Skarels 
305*30391Skarels /*----------------------------------------------------
306*30391Skarels * find the cpusw entry that matches this machine. */
307*30391Skarels 
308*30391Skarels 	cpup = &cpusw[cpu];
309*30391Skarels 				;
310*30391Skarels 	if( cpup == NULL ) {
311*30391Skarels 		return(0);
312*30391Skarels 	}
313*30391Skarels 
314*30391Skarels /*------------------------------------------------------
315*30391Skarels * Map the Q-bus memory space into the system memory. */
316*30391Skarels 
317*30391Skarels 	ubaaccess(((*cpup->v_umaddr)(0)), QMEMmap[0],
318*30391Skarels 			cpup->pc_umsize, PG_V | PG_KW);
319*30391Skarels 
320*30391Skarels 	ubaaccess(((*cpup->v_udevaddr)(0)), QMEMmap[0]+btop(cpup->pc_umsize),
321*30391Skarels 			DEVSPACESIZE ,PG_V|PG_KW);
322*30391Skarels 
323*30391Skarels /*---------------------------------------------------------------------
324*30391Skarels * map the QDSS into the Qbus memory (which is now in system space)  */
325*30391Skarels 
326*30391Skarels 	devptr = (u_short *)((char *)qmem[0]+cpup->pc_umsize);
327*30391Skarels 	qdaddr = (u_short *)((u_int)devptr + ubdevreg(QDSSCSR));
328*30391Skarels 
329*30391Skarels 	if (BADADDR(qdaddr, sizeof(short)))
330*30391Skarels 		return(0);
331*30391Skarels 
332*30391Skarels 	/*---------------------------------------------------
333*30391Skarels 	* tell QDSS which Q memory address base to decode */
334*30391Skarels 
335*30391Skarels 	mapix = (int) VTOP(QMEMSIZE - CHUNK);
336*30391Skarels 	ptep = (int *) QMEMmap[0] + mapix;
337*30391Skarels 	phys_adr = (caddr_t) (((int)*ptep & 0x001FFFFF) << PGSHIFT);
338*30391Skarels 	*qdaddr = (u_short) ((int)phys_adr >> 16);
339*30391Skarels 
340*30391Skarels 	qdflags[unit].config = *(u_short *)qdaddr;
341*30391Skarels 
342*30391Skarels /*----------------------------------------------------------------------
343*30391Skarels * load qdmap struct with the virtual addresses of the QDSS elements */
344*30391Skarels 
345*30391Skarels 	qdbase[unit] = (caddr_t) (qmem[0] + QMEMSIZE - CHUNK);
346*30391Skarels 
347*30391Skarels 	qdmap[unit].template = qdbase[unit] + TMPSTART;
348*30391Skarels 	qdmap[unit].adder = qdbase[unit] + ADDER;
349*30391Skarels 	qdmap[unit].dga = qdbase[unit] + DGA;
350*30391Skarels 	qdmap[unit].duart = qdbase[unit] + DUART;
351*30391Skarels 	qdmap[unit].memcsr = qdbase[unit] + MEMCSR;
352*30391Skarels 	qdmap[unit].red = qdbase[unit] + RED;
353*30391Skarels 	qdmap[unit].blue = qdbase[unit] + BLUE;
354*30391Skarels 	qdmap[unit].green = qdbase[unit] + GREEN;
355*30391Skarels 
356*30391Skarels 	qdflags[unit].duart_imask = 0;	/* init shadow variables */
357*30391Skarels 
358*30391Skarels /*------------------
359*30391Skarels * init the QDSS  */
360*30391Skarels 
361*30391Skarels 	*(short *)qdmap[unit].memcsr |= SYNC_ON; /* once only: turn on sync */
362*30391Skarels 
363*30391Skarels 	cursor[unit].x = 0;
364*30391Skarels 	cursor[unit].y = 0;
365*30391Skarels 	init_shared(unit);		/* init shared memory */
366*30391Skarels 	setup_dragon(unit);		/* init the ADDER/VIPER stuff */
367*30391Skarels 	clear_qd_screen(unit);		/* clear the screen */
368*30391Skarels 	ldfont(unit);			/* load the console font */
369*30391Skarels 	ldcursor(unit, cons_cursor);	/* load default cursor map */
370*30391Skarels 	setup_input(unit);		/* init the DUART */
371*30391Skarels 
372*30391Skarels /*----------------------------------------------------
373*30391Skarels * smash the system's virtual console address table */
374*30391Skarels 
375*30391Skarels 	v_consputc = qdputc;
376*30391Skarels 	v_consgetc = qdgetc;
377*30391Skarels 	cdevsw[0] = cdevsw[QDSSMAJOR];
378*30391Skarels 	return(1);
379*30391Skarels 
380*30391Skarels } /* qdcons_init */
381*30391Skarels 
382*30391Skarels /*********************************************************************
383*30391Skarels *
384*30391Skarels *	qdprobe()... configure QDSS into Q memory and make it intrpt
385*30391Skarels *
386*30391Skarels **********************************************************************
387*30391Skarels *
388*30391Skarels *  calling convention:
389*30391Skarels *			qdprobe(reg, ctlr);
390*30391Skarels *			caddr_t reg;
391*30391Skarels *			int ctlr;
392*30391Skarels *
393*30391Skarels *	where: reg - a character pointer to the QDSS I/O page register
394*30391Skarels *	       ctlr - controller number (?)
395*30391Skarels *
396*30391Skarels *  side effects: QDSS gets mapped into Qbus memory space at the first
397*30391Skarels *		 vacant 64kb boundary counting back from the top of
398*30391Skarels *		 Qbus memory space (qmem+4mb)
399*30391Skarels *
400*30391Skarels *  return: QDSS bus request level and vector address returned in
401*30391Skarels *	   registers by UNIX convention.
402*30391Skarels *
403*30391Skarels *****************/
404*30391Skarels 
405*30391Skarels qdprobe(reg)
406*30391Skarels caddr_t reg;
407*30391Skarels {
408*30391Skarels 	/* the variables MUST reside in the first two register declarations
409*30391Skarels 	* by UNIX convention in order that they be loaded and returned
410*30391Skarels 	* properly by the interrupt catching mechanism.  */
411*30391Skarels 
412*30391Skarels 	register int unit;
413*30391Skarels 
414*30391Skarels 	struct dga *dga;		/* pointer to gate array structure */
415*30391Skarels 	struct cpusw *cpup;		/* pointer to the cpusw structure */
416*30391Skarels 
417*30391Skarels 	int *ptep;			/* page table entry pointer */
418*30391Skarels 	int vector;
419*30391Skarels 
420*30391Skarels 	caddr_t phys_adr;		/* physical QDSS base adrs */
421*30391Skarels 	u_int mapix;
422*30391Skarels 
423*30391Skarels /*---------------------------------------------------------------
424*30391Skarels * calculate board unit number from I/O page register address  */
425*30391Skarels 
426*30391Skarels 	unit = (int) (((int)reg >> 1) & 0x0007);
427*30391Skarels 
428*30391Skarels /*---------------------------------------------------------------------------
429*30391Skarels * QDSS regs must be mapped to Qbus memory space at a 64kb physical boundary.
430*30391Skarels * The Qbus memory space is mapped into the system memory space at config
431*30391Skarels * time.  After config runs, "qmem[0]" (ubavar.h) holds the system virtual adrs
432*30391Skarels * of the start of Qbus memory.	The Qbus memory page table is found via
433*30391Skarels * an array of pte ptrs called "QMEMmap[]" (ubavar.h) which is also loaded at
434*30391Skarels * config time.	These are the variables used below to find a vacant 64kb
435*30391Skarels * boundary in Qbus memory, and load it's corresponding physical adrs into
436*30391Skarels * the QDSS's I/O page CSR.  */
437*30391Skarels 
438*30391Skarels 	/* if this QDSS is NOT the console, then do init here.. */
439*30391Skarels 
440*30391Skarels 	if (v_consputc != qdputc  ||  unit != 0) {
441*30391Skarels 
442*30391Skarels 	    /*-------------------------
443*30391Skarels 	    * read QDSS config info */
444*30391Skarels 
445*30391Skarels 	    qdflags[unit].config = *(u_short *)reg;
446*30391Skarels 
447*30391Skarels 	    /*------------------------------------
448*30391Skarels 	    * find an empty 64kb adrs boundary */
449*30391Skarels 
450*30391Skarels 	    qdbase[unit] = (caddr_t) (qmem[0] + QMEMSIZE - CHUNK);
451*30391Skarels 
452*30391Skarels 	    /*----------------------------------------------------
453*30391Skarels 	    * find the cpusw entry that matches this machine. */
454*30391Skarels 
455*30391Skarels 	    cpup = &cpusw[cpu];
456*30391Skarels 	    while ( !(BADADDR(qdbase[unit], sizeof(short))) )
457*30391Skarels 		qdbase[unit] -= CHUNK;
458*30391Skarels 
459*30391Skarels 	    /*---------------------------------------------------
460*30391Skarels 	    * tell QDSS which Q memory address base to decode */
461*30391Skarels 
462*30391Skarels 	    mapix = (int) (VTOP(qdbase[unit]) - VTOP(qmem[0]));
463*30391Skarels 	    ptep = (int *) QMEMmap[0] + mapix;
464*30391Skarels 	    phys_adr = (caddr_t) (((int)*ptep & 0x001FFFFF) << PGSHIFT);
465*30391Skarels 	    *(u_short *)reg = (u_short) ((int)phys_adr >> 16);
466*30391Skarels 
467*30391Skarels 	    /*-----------------------------------------------------------
468*30391Skarels 	    * load QDSS adrs map with system addresses of device regs */
469*30391Skarels 
470*30391Skarels 	    qdmap[unit].template = qdbase[unit] + TMPSTART;
471*30391Skarels 	    qdmap[unit].adder = qdbase[unit] + ADDER;
472*30391Skarels 	    qdmap[unit].dga = qdbase[unit] + DGA;
473*30391Skarels 	    qdmap[unit].duart = qdbase[unit] + DUART;
474*30391Skarels 	    qdmap[unit].memcsr = qdbase[unit] + MEMCSR;
475*30391Skarels 	    qdmap[unit].red = qdbase[unit] + RED;
476*30391Skarels 	    qdmap[unit].blue = qdbase[unit] + BLUE;
477*30391Skarels 	    qdmap[unit].green = qdbase[unit] + GREEN;
478*30391Skarels 
479*30391Skarels 	    /* device init */
480*30391Skarels 
481*30391Skarels 	    cursor[unit].x = 0;
482*30391Skarels 	    cursor[unit].y = 0;
483*30391Skarels 	    init_shared(unit);		/* init shared memory */
484*30391Skarels 	    setup_dragon(unit); 	/* init the ADDER/VIPER stuff */
485*30391Skarels 	    ldcursor(unit, cons_cursor);	/* load default cursor map */
486*30391Skarels 	    setup_input(unit);		/* init the DUART */
487*30391Skarels 	    clear_qd_screen(unit);
488*30391Skarels 	    ldfont(unit);			/* load the console font */
489*30391Skarels 
490*30391Skarels 	    /* once only: turn on sync */
491*30391Skarels 
492*30391Skarels 	    *(short *)qdmap[unit].memcsr |= SYNC_ON;
493*30391Skarels 	}
494*30391Skarels 
495*30391Skarels /*--------------------------------------------------------------------------
496*30391Skarels * the QDSS interrupts at HEX vectors xx0 (DMA) xx4 (ADDER) and xx8 (DUART).
497*30391Skarels * Therefore, we take three vectors from the vector pool, and then continue
498*30391Skarels * to take them until we get a xx0 HEX vector.  The pool provides vectors
499*30391Skarels * in contiguous decending order.  */
500*30391Skarels 
501*30391Skarels 	vector = (uba_hd[0].uh_lastiv -= 4*3);	/* take three vectors */
502*30391Skarels 
503*30391Skarels 	while (vector & 0x0F) { 		   /* if lo nibble != 0.. */
504*30391Skarels 	    vector = (uba_hd[0].uh_lastiv -= 4);  /* ..take another vector */
505*30391Skarels 	}
506*30391Skarels 
507*30391Skarels 	/*---------------------------------------------------------
508*30391Skarels 	* setup DGA to do a DMA interrupt (transfer count = 0)	*/
509*30391Skarels 
510*30391Skarels 	dga = (struct dga *) qdmap[unit].dga;
511*30391Skarels 
512*30391Skarels 	dga->csr = (short) HALT;	      /* disable everything */
513*30391Skarels 	dga->ivr = (short) vector;	      /* load intrpt base vector */
514*30391Skarels 	dga->bytcnt_lo = (short) 0;	      /* DMA xfer count = 0 */
515*30391Skarels 	dga->bytcnt_hi = (short) 0;
516*30391Skarels 
517*30391Skarels 	/* turn on DMA interrupts */
518*30391Skarels 
519*30391Skarels 	dga->csr &= ~SET_DONE_FIFO;
520*30391Skarels 	dga->csr |= DMA_IE | DL_ENB;
521*30391Skarels 
522*30391Skarels 	DELAY(20000);			/* wait for the intrpt */
523*30391Skarels 
524*30391Skarels 	dga->csr = HALT;		/* stop the wheels */
525*30391Skarels 
526*30391Skarels /*----------
527*30391Skarels * exits  */
528*30391Skarels 
529*30391Skarels 	if (cvec != vector)		/* if vector != base vector.. */
530*30391Skarels 	    return(0);			/* ..return = 'no device' */
531*30391Skarels 
532*30391Skarels 	return(sizeof(short));	    /* return size of QDSS I/O page reg */
533*30391Skarels 
534*30391Skarels } /* qdprobe */
535*30391Skarels 
536*30391Skarels /*****************************************************************
537*30391Skarels *
538*30391Skarels *	qdattach()... do the one-time initialization
539*30391Skarels *
540*30391Skarels ******************************************************************
541*30391Skarels *
542*30391Skarels *  calling convention:
543*30391Skarels *			qdattach(ui);
544*30391Skarels *			struct uba_device *ui;
545*30391Skarels *
546*30391Skarels *		where: ui - pointer to the QDSS's uba_device structure
547*30391Skarels *
548*30391Skarels *  side effects: none
549*30391Skarels *	 return: none
550*30391Skarels *
551*30391Skarels *************************/
552*30391Skarels 
553*30391Skarels qdattach(ui)
554*30391Skarels struct uba_device *ui;
555*30391Skarels {
556*30391Skarels 	register u_int unit;		/* QDSS module # for this call */
557*30391Skarels 
558*30391Skarels 	unit = ui->ui_unit;		/* get QDSS number */
559*30391Skarels 
560*30391Skarels /*----------------------------------
561*30391Skarels * init "qdflags[]" for this QDSS */
562*30391Skarels 
563*30391Skarels 	qdflags[unit].inuse = 0;	/* init inuse variable EARLY! */
564*30391Skarels 	qdflags[unit].mapped = 0;
565*30391Skarels 	qdflags[unit].kernel_loop = 0;
566*30391Skarels 	qdflags[unit].user_dma = 0;
567*30391Skarels 	qdflags[unit].curs_acc = ACC_OFF;
568*30391Skarels 	qdflags[unit].curs_thr = 128;
569*30391Skarels 	qdflags[unit].tab_res = 2;	/* default tablet resolution factor */
570*30391Skarels 	qdflags[unit].duart_imask = 0;	/* init shadow variables */
571*30391Skarels 	qdflags[unit].adder_ie = 0;
572*30391Skarels 
573*30391Skarels /*----------------------------------------------------------------------
574*30391Skarels * init structures used in kbd/mouse interrupt service.	This code must
575*30391Skarels * come after the "init_shared()" routine has run since that routine inits
576*30391Skarels * the eq_header[unit] structure used here.   */
577*30391Skarels 
578*30391Skarels 	/*--------------------------------------------
579*30391Skarels 	* init the "latest mouse report" structure */
580*30391Skarels 
581*30391Skarels 	last_rep[unit].state = 0;
582*30391Skarels 	last_rep[unit].dx = 0;
583*30391Skarels 	last_rep[unit].dy = 0;
584*30391Skarels 	last_rep[unit].bytcnt = 0;
585*30391Skarels 
586*30391Skarels 	/*------------------------------------------------
587*30391Skarels 	* init the event queue (except mouse position) */
588*30391Skarels 
589*30391Skarels 	eq_header[unit]->header.events = (struct _vs_event *)
590*30391Skarels 					  ((int)eq_header[unit]
591*30391Skarels 					   + sizeof(struct qdinput));
592*30391Skarels 
593*30391Skarels 	eq_header[unit]->header.size = MAXEVENTS;
594*30391Skarels 	eq_header[unit]->header.head = 0;
595*30391Skarels 	eq_header[unit]->header.tail = 0;
596*30391Skarels 
597*30391Skarels /*------------------------------------------
598*30391Skarels * init single process access lock switch */
599*30391Skarels 
600*30391Skarels 	one_only[unit] = 0;
601*30391Skarels 
602*30391Skarels } /* qdattach */
603*30391Skarels 
604*30391Skarels /***************************************************************
605*30391Skarels *
606*30391Skarels *	qdopen()... open a minor device
607*30391Skarels *
608*30391Skarels ****************************************************************
609*30391Skarels *
610*30391Skarels *  calling convention: qdopen(dev, flag);
611*30391Skarels *		       dev_t dev;
612*30391Skarels *		       int flag;
613*30391Skarels *
614*30391Skarels *  side effects: none
615*30391Skarels *
616*30391Skarels *********************/
617*30391Skarels 
618*30391Skarels qdopen(dev, flag)
619*30391Skarels dev_t dev;
620*30391Skarels int flag;
621*30391Skarels {
622*30391Skarels 	register struct uba_device *ui; /* ptr to uba structures */
623*30391Skarels 	register struct dga *dga;	/* ptr to gate array struct */
624*30391Skarels 	register struct tty *tp;
625*30391Skarels 
626*30391Skarels 	struct adder *adder;
627*30391Skarels 	struct duart *duart;
628*30391Skarels 
629*30391Skarels 	u_int unit;
630*30391Skarels 	u_int minor_dev;
631*30391Skarels 	int s;
632*30391Skarels 
633*30391Skarels 	minor_dev = minor(dev); /* get QDSS minor device number */
634*30391Skarels 	unit = minor_dev >> 2;
635*30391Skarels 
636*30391Skarels /*---------------------------------
637*30391Skarels * check for illegal conditions	*/
638*30391Skarels 
639*30391Skarels 	ui = qdinfo[unit];		/* get ptr to QDSS device struct */
640*30391Skarels 
641*30391Skarels 	if (ui == 0  || ui->ui_alive == 0)
642*30391Skarels 	    return(ENXIO);		/* no such device or address */
643*30391Skarels 
644*30391Skarels /*--------------
645*30391Skarels * init stuff */
646*30391Skarels 
647*30391Skarels 	adder = (struct adder *) qdmap[unit].adder;
648*30391Skarels 	duart = (struct duart *) qdmap[unit].duart;
649*30391Skarels 	dga = (struct dga *) qdmap[unit].dga;
650*30391Skarels 
651*30391Skarels /*------------------------------------
652*30391Skarels * if this is the graphic device... */
653*30391Skarels 
654*30391Skarels 	if ((minor_dev & 0x03) == 2) {
655*30391Skarels 
656*30391Skarels 	    if (one_only[unit] != 0)
657*30391Skarels 		return(EBUSY);
658*30391Skarels 	    else
659*30391Skarels 		one_only[unit] = 1;
660*30391Skarels 
661*30391Skarels 	    qdflags[unit].inuse |= GRAPHIC_DEV;  /* graphics dev is open */
662*30391Skarels 
663*30391Skarels 	    /* enble kbd & mouse intrpts in DUART mask reg */
664*30391Skarels 
665*30391Skarels 	    qdflags[unit].duart_imask |= 0x22;
666*30391Skarels 	    duart->imask = qdflags[unit].duart_imask;
667*30391Skarels 
668*30391Skarels /*------------------------------------------------------------------
669*30391Skarels * if the open call is to the console or the alternate console... */
670*30391Skarels 
671*30391Skarels 	} else if ((minor_dev & 0x03) != 2) {
672*30391Skarels 
673*30391Skarels 	    qdflags[unit].inuse |= CONS_DEV;  /* mark console as open */
674*30391Skarels 	    dga->csr |= CURS_ENB;
675*30391Skarels 
676*30391Skarels 	    qdflags[unit].duart_imask |= 0x02;
677*30391Skarels 	    duart->imask = qdflags[unit].duart_imask;
678*30391Skarels 
679*30391Skarels 	    /*-------------------------------
680*30391Skarels 	    * some setup for tty handling */
681*30391Skarels 
682*30391Skarels 	    tp = &qd_tty[minor_dev];
683*30391Skarels 
684*30391Skarels 	    tp->t_addr = ui->ui_addr;
685*30391Skarels 	    tp->t_oproc = qdstart;
686*30391Skarels 
687*30391Skarels 	    if ((tp->t_state & TS_ISOPEN) == 0) {
688*30391Skarels 
689*30391Skarels 		ttychars(tp);
690*30391Skarels 		tp->t_state = TS_ISOPEN | TS_CARR_ON;
691*30391Skarels 		tp->t_ispeed = B9600;
692*30391Skarels 		tp->t_ospeed = B9600;
693*30391Skarels 
694*30391Skarels 		if( (minor_dev & 0x03) == 0 )
695*30391Skarels 		    tp->t_flags = XTABS|EVENP|ECHO|CRMOD;
696*30391Skarels 		else
697*30391Skarels 		    tp->t_flags = RAW;
698*30391Skarels 	    }
699*30391Skarels 
700*30391Skarels 	    /*----------------------------------------
701*30391Skarels 	    * enable intrpts, open line discipline */
702*30391Skarels 
703*30391Skarels 	    dga->csr |= GLOBAL_IE;	/* turn on the interrupts */
704*30391Skarels 	    return ((*linesw[tp->t_line].l_open)(dev, tp));
705*30391Skarels 	}
706*30391Skarels 
707*30391Skarels 	dga->csr |= GLOBAL_IE;	/* turn on the interrupts */
708*30391Skarels 	return(0);
709*30391Skarels 
710*30391Skarels } /* qdopen */
711*30391Skarels 
712*30391Skarels /***************************************************************
713*30391Skarels *
714*30391Skarels *	qdclose()... clean up on the way out
715*30391Skarels *
716*30391Skarels ****************************************************************
717*30391Skarels *
718*30391Skarels *  calling convention: qdclose();
719*30391Skarels *
720*30391Skarels *  side effects: none
721*30391Skarels *
722*30391Skarels *  return: none
723*30391Skarels *
724*30391Skarels *********************/
725*30391Skarels 
726*30391Skarels qdclose(dev, flag)
727*30391Skarels dev_t dev;
728*30391Skarels int flag;
729*30391Skarels {
730*30391Skarels 	register struct tty *tp;
731*30391Skarels 	register struct qdmap *qd;
732*30391Skarels 	register int *ptep;
733*30391Skarels 	int i;				/* SIGNED index */
734*30391Skarels 
735*30391Skarels 	struct dga *dga;		/* gate array register map pointer */
736*30391Skarels 	struct duart *duart;
737*30391Skarels 	struct adder *adder;
738*30391Skarels 
739*30391Skarels 	u_int unit;
740*30391Skarels 	u_int minor_dev;
741*30391Skarels 	u_int mapix;
742*30391Skarels 
743*30391Skarels 	minor_dev = minor(dev); 	/* get minor device number */
744*30391Skarels 	unit = minor_dev >> 2;		/* get QDSS number */
745*30391Skarels 	qd = &qdmap[unit];
746*30391Skarels 
747*30391Skarels /*------------------------------------
748*30391Skarels * if this is the graphic device... */
749*30391Skarels 
750*30391Skarels 	if ((minor_dev & 0x03) == 2) {
751*30391Skarels 
752*30391Skarels 	    /*-----------------
753*30391Skarels 	    * unlock driver */
754*30391Skarels 
755*30391Skarels 	    if (one_only[unit] != 1)
756*30391Skarels 		return(EBUSY);
757*30391Skarels 	    else
758*30391Skarels 		one_only[unit] = 0;
759*30391Skarels 
760*30391Skarels 	    /*----------------------------
761*30391Skarels 	    * re-protect device memory */
762*30391Skarels 
763*30391Skarels 	    if (qdflags[unit].mapped & MAPDEV) {
764*30391Skarels 
765*30391Skarels 		/*----------------
766*30391Skarels 		* TEMPLATE RAM */
767*30391Skarels 
768*30391Skarels 		mapix = VTOP((int)qd->template) - VTOP(qmem[0]);
769*30391Skarels 		ptep = (int *)(QMEMmap[0] + mapix);
770*30391Skarels 
771*30391Skarels 		for (i = VTOP(TMPSIZE); i > 0; --i)
772*30391Skarels 		    *ptep++ = (*ptep & ~PG_PROT) | PG_V | PG_KW;
773*30391Skarels 
774*30391Skarels 		/*---------
775*30391Skarels 		* ADDER */
776*30391Skarels 
777*30391Skarels 		mapix = VTOP((int)qd->adder) - VTOP(qmem[0]);
778*30391Skarels 		ptep = (int *)(QMEMmap[0] + mapix);
779*30391Skarels 
780*30391Skarels 		for (i = VTOP(REGSIZE); i > 0; --i)
781*30391Skarels 		    *ptep++ = (*ptep & ~PG_PROT) | PG_V | PG_KW;
782*30391Skarels 
783*30391Skarels 		/*--------------
784*30391Skarels 		* COLOR MAPS */
785*30391Skarels 
786*30391Skarels 		mapix = VTOP((int)qd->red) - VTOP(qmem[0]);
787*30391Skarels 		ptep = (int *)(QMEMmap[0] + mapix);
788*30391Skarels 
789*30391Skarels 		for (i = VTOP(CLRSIZE); i > 0; --i)
790*30391Skarels 		    *ptep++ = (*ptep & ~PG_PROT) | PG_V | PG_KW;
791*30391Skarels 	    }
792*30391Skarels 
793*30391Skarels 	    /*----------------------------------------------------
794*30391Skarels 	    * re-protect DMA buffer and free the map registers */
795*30391Skarels 
796*30391Skarels 	    if (qdflags[unit].mapped & MAPDMA) {
797*30391Skarels 
798*30391Skarels 		dga = (struct dga *) qdmap[unit].dga;
799*30391Skarels 		adder = (struct adder *) qdmap[unit].adder;
800*30391Skarels 
801*30391Skarels 		dga->csr &= ~DMA_IE;
802*30391Skarels 		dga->csr &= ~0x0600;	     /* kill DMA */
803*30391Skarels 		adder->command = CANCEL;
804*30391Skarels 
805*30391Skarels 		/* if DMA was running, flush spurious intrpt */
806*30391Skarels 
807*30391Skarels 		if (dga->bytcnt_lo != 0) {
808*30391Skarels 		    dga->bytcnt_lo = 0;
809*30391Skarels 		    dga->bytcnt_hi = 0;
810*30391Skarels 		    DMA_SETIGNORE(DMAheader[unit]);
811*30391Skarels 		    dga->csr |= DMA_IE;
812*30391Skarels 		    dga->csr &= ~DMA_IE;
813*30391Skarels 		}
814*30391Skarels 
815*30391Skarels 		ptep = (int *)
816*30391Skarels 			((VTOP(DMAheader[unit]*4)) + (mfpr(SBR)|0x80000000));
817*30391Skarels 
818*30391Skarels 		for (i = (DMAbuf_size >> PGSHIFT); i > 0; --i)
819*30391Skarels 		    *ptep++ = (*ptep & ~PG_PROT) | PG_V | PG_KW;
820*30391Skarels 
821*30391Skarels 		ubarelse(0, &Qbus_unmap[unit]);
822*30391Skarels 	    }
823*30391Skarels 
824*30391Skarels 	    /*---------------------------------------
825*30391Skarels 	    * re-protect 1K (2 pages) event queue */
826*30391Skarels 
827*30391Skarels 	    if (qdflags[unit].mapped & MAPEQ) {
828*30391Skarels 
829*30391Skarels 		ptep = (int *)
830*30391Skarels 			((VTOP(eq_header[unit])*4) + (mfpr(SBR)|0x80000000));
831*30391Skarels 
832*30391Skarels 		*ptep++ = (*ptep & ~PG_PROT) | PG_KW | PG_V;
833*30391Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
834*30391Skarels 	    }
835*30391Skarels 
836*30391Skarels 	    /*------------------------------------------------------------
837*30391Skarels 	    * re-protect scroll param area and disable scroll intrpts  */
838*30391Skarels 
839*30391Skarels 	    if (qdflags[unit].mapped & MAPSCR) {
840*30391Skarels 
841*30391Skarels 		ptep = (int *) ((VTOP(scroll[unit]) * 4)
842*30391Skarels 				    + (mfpr(SBR) | 0x80000000));
843*30391Skarels 
844*30391Skarels 		/* re-protect 512 scroll param area */
845*30391Skarels 
846*30391Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
847*30391Skarels 
848*30391Skarels 		adder = (struct adder *) qdmap[unit].adder;
849*30391Skarels 		qdflags[unit].adder_ie &= ~FRAME_SYNC;
850*30391Skarels 		adder->interrupt_enable = qdflags[unit].adder_ie;
851*30391Skarels 	    }
852*30391Skarels 
853*30391Skarels 	    /*-----------------------------------------------------------
854*30391Skarels 	    * re-protect color map write buffer area and kill intrpts */
855*30391Skarels 
856*30391Skarels 	    if (qdflags[unit].mapped & MAPCOLOR) {
857*30391Skarels 
858*30391Skarels 		ptep = (int *) ((VTOP(color_buf[unit]) * 4)
859*30391Skarels 				    + (mfpr(SBR) | 0x80000000));
860*30391Skarels 
861*30391Skarels 		*ptep++ = (*ptep & ~PG_PROT) | PG_KW | PG_V;
862*30391Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
863*30391Skarels 
864*30391Skarels 		color_buf[unit]->status = 0;
865*30391Skarels 
866*30391Skarels 		adder = (struct adder *) qdmap[unit].adder;
867*30391Skarels 		qdflags[unit].adder_ie &= ~VSYNC;
868*30391Skarels 		adder->interrupt_enable = qdflags[unit].adder_ie;
869*30391Skarels 	    }
870*30391Skarels 
871*30391Skarels 	    /*-----------------------------------
872*30391Skarels 	    * flag that everthing is unmapped */
873*30391Skarels 
874*30391Skarels 	    mtpr(TBIA, 0);		/* smash CPU's translation buf */
875*30391Skarels 	    qdflags[unit].mapped = 0;	/* flag everything now unmapped */
876*30391Skarels 	    qdflags[unit].inuse &= ~GRAPHIC_DEV;
877*30391Skarels 	    qdflags[unit].curs_acc = ACC_OFF;
878*30391Skarels 	    qdflags[unit].curs_thr = 128;
879*30391Skarels 
880*30391Skarels 	    /*---------------------
881*30391Skarels 	    * restore the console */
882*30391Skarels 
883*30391Skarels 		dga = (struct dga *) qdmap[unit].dga;
884*30391Skarels 		adder = (struct adder *) qdmap[unit].adder;
885*30391Skarels 
886*30391Skarels 		dga->csr &= ~DMA_IE;
887*30391Skarels 		dga->csr &= ~0x0600;	/* halt the DMA! (just in case...) */
888*30391Skarels 		dga->csr |= DMA_ERR;	/* clear error condition */
889*30391Skarels 		adder->command = CANCEL;
890*30391Skarels 
891*30391Skarels 		/* if DMA was running, flush spurious intrpt */
892*30391Skarels 
893*30391Skarels 		if (dga->bytcnt_lo != 0) {
894*30391Skarels 		    dga->bytcnt_lo = 0;
895*30391Skarels 		    dga->bytcnt_hi = 0;
896*30391Skarels 		    DMA_SETIGNORE(DMAheader[unit]);
897*30391Skarels 		    dga->csr |= DMA_IE;
898*30391Skarels 		    dga->csr &= ~DMA_IE;
899*30391Skarels 		}
900*30391Skarels 
901*30391Skarels 		init_shared(unit);		/* init shared memory */
902*30391Skarels 		setup_dragon(unit);		/* init ADDER/VIPER */
903*30391Skarels 		ldcursor(unit, cons_cursor);	/* load default cursor map */
904*30391Skarels 		setup_input(unit);		/* init the DUART */
905*30391Skarels 		ldfont(unit);
906*30391Skarels 		cursor[unit].x = 0;
907*30391Skarels 		cursor[unit].y = 0;
908*30391Skarels 
909*30391Skarels 	    /* shut off the mouse rcv intrpt and turn on kbd intrpts */
910*30391Skarels 
911*30391Skarels 	    duart = (struct duart *) qdmap[unit].duart;
912*30391Skarels 	    qdflags[unit].duart_imask &= ~(0x20);
913*30391Skarels 	    qdflags[unit].duart_imask |= 0x02;
914*30391Skarels 	    duart->imask = qdflags[unit].duart_imask;
915*30391Skarels 
916*30391Skarels 	    /*-----------------------------------------
917*30391Skarels 	    * shut off interrupts if all is closed  */
918*30391Skarels 
919*30391Skarels 	    if (!(qdflags[unit].inuse & (CONS_DEV | ALTCONS_DEV))) {
920*30391Skarels 
921*30391Skarels 		dga = (struct dga *) qdmap[unit].dga;
922*30391Skarels 		dga->csr &= ~(GLOBAL_IE | DMA_IE);
923*30391Skarels 	    }
924*30391Skarels 	}
925*30391Skarels 
926*30391Skarels /*----------------------------------------------------
927*30391Skarels * if this is the console or the alternate console  */
928*30391Skarels 
929*30391Skarels 	else {
930*30391Skarels 
931*30391Skarels 	    tp = &qd_tty[minor_dev];
932*30391Skarels 
933*30391Skarels 	    (*linesw[tp->t_line].l_close)(tp);
934*30391Skarels 	    ttyclose(tp);
935*30391Skarels 
936*30391Skarels 	    tp->t_state = 0;
937*30391Skarels 
938*30391Skarels 	    qdflags[unit].inuse &= ~CONS_DEV;
939*30391Skarels 
940*30391Skarels 	    /*-------------------------------------------------
941*30391Skarels 	    * if graphics device is closed, kill interrupts */
942*30391Skarels 
943*30391Skarels 	    if (!(qdflags[unit].inuse & GRAPHIC_DEV)) {
944*30391Skarels 		dga = (struct dga *) qdmap[unit].dga;
945*30391Skarels 		dga->csr &= ~(GLOBAL_IE | DMA_IE);
946*30391Skarels 	    }
947*30391Skarels 	}
948*30391Skarels 
949*30391Skarels /*--------
950*30391Skarels * exit */
951*30391Skarels 
952*30391Skarels 	return(0);
953*30391Skarels 
954*30391Skarels } /* qdclose */
955*30391Skarels 
956*30391Skarels /***************************************************************
957*30391Skarels *
958*30391Skarels *	qdioctl()... provide QDSS control services
959*30391Skarels *
960*30391Skarels ****************************************************************
961*30391Skarels *
962*30391Skarels *  calling convention:	qdioctl(dev, cmd, datap, flags);
963*30391Skarels *
964*30391Skarels *		where:	dev - the major/minor device number
965*30391Skarels *			cmd - the user-passed command argument
966*30391Skarels *			datap - ptr to user input buff (128 bytes max)
967*30391Skarels *			flags - "f_flags" from "struct file" in file.h
968*30391Skarels *
969*30391Skarels *
970*30391Skarels *	- here is the format for the input "cmd" argument
971*30391Skarels *
972*30391Skarels *	31     29 28	23 22	      16 15		8 7		 0
973*30391Skarels *	+----------------------------------------------------------------+
974*30391Skarels *	|I/O type|	  | buff length | device ID char |  user command |
975*30391Skarels *	+----------------------------------------------------------------+
976*30391Skarels *
977*30391Skarels *  Return data is in the data buffer pointed to by "datap" input spec
978*30391Skarels *
979*30391Skarels *********************/
980*30391Skarels 
981*30391Skarels qdioctl(dev, cmd, datap, flags)
982*30391Skarels dev_t dev;
983*30391Skarels int cmd;
984*30391Skarels caddr_t datap;
985*30391Skarels int flags;
986*30391Skarels {
987*30391Skarels 	register int *ptep;		/* page table entry pointer */
988*30391Skarels 	register int mapix;		/* QMEMmap[] page table index */
989*30391Skarels 	register struct _vs_event *event;
990*30391Skarels 	register struct tty *tp;
991*30391Skarels 
992*30391Skarels 	struct qdmap *qd;		/* pointer to device map struct */
993*30391Skarels 	struct dga *dga;		/* Gate Array reg structure pntr */
994*30391Skarels 	struct duart *duart;		/* DUART reg structure pointer */
995*30391Skarels 	struct adder *adder;		/* ADDER reg structure pointer */
996*30391Skarels 
997*30391Skarels 	struct prgkbd *cmdbuf;
998*30391Skarels 	struct prg_cursor *curs;
999*30391Skarels 	struct _vs_cursor *pos;
1000*30391Skarels 
1001*30391Skarels 	u_int unit = minor(dev) >> 2;	/* number of caller's QDSS */
1002*30391Skarels 	u_int minor_dev = minor(dev);
1003*30391Skarels 	struct uba_device *ui = qdinfo[unit];
1004*30391Skarels 	struct qd_softc *sc = &qd_softc[ui->ui_unit];
1005*30391Skarels 	struct devget *devget;
1006*30391Skarels 
1007*30391Skarels 	int error;
1008*30391Skarels 	int s;
1009*30391Skarels 
1010*30391Skarels 	int i;				/* SIGNED index */
1011*30391Skarels 	int sbr;			/* SBR variable (you silly boy) */
1012*30391Skarels 	u_int ix;
1013*30391Skarels 
1014*30391Skarels 	short status;
1015*30391Skarels 	short *shortp;			/* generic pointer to a short */
1016*30391Skarels 	char *chrp;			/* generic character pointer */
1017*30391Skarels 
1018*30391Skarels 	short *temp;			/* a pointer to template RAM */
1019*30391Skarels 
1020*30391Skarels /*-----------------------------------------
1021*30391Skarels * service graphic device ioctl commands */
1022*30391Skarels 
1023*30391Skarels 	switch (cmd) {
1024*30391Skarels 
1025*30391Skarels 	    /*-------------------------------------------------
1026*30391Skarels 	    * extract the oldest event from the event queue */
1027*30391Skarels 
1028*30391Skarels 	    case QD_GETEVENT:
1029*30391Skarels 
1030*30391Skarels 		if (ISEMPTY(eq_header[unit])) {
1031*30391Skarels 		    event = (struct _vs_event *) datap;
1032*30391Skarels 		    event->vse_device = VSE_NULL;
1033*30391Skarels 		    break;
1034*30391Skarels 		}
1035*30391Skarels 
1036*30391Skarels 		event = (struct _vs_event *) GETBEGIN(eq_header[unit]);
1037*30391Skarels 		s = spl5();
1038*30391Skarels 		GETEND(eq_header[unit]);
1039*30391Skarels 		splx(s);
1040*30391Skarels 		bcopy(event, datap, sizeof(struct _vs_event));
1041*30391Skarels 		break;
1042*30391Skarels 
1043*30391Skarels 	    /*-------------------------------------------------------
1044*30391Skarels 	    * init the dragon stuff, DUART, and driver variables  */
1045*30391Skarels 
1046*30391Skarels 	    case QD_RESET:
1047*30391Skarels 
1048*30391Skarels 		init_shared(unit);		/* init shared memory */
1049*30391Skarels 		setup_dragon(unit);	      /* init the ADDER/VIPER stuff */
1050*30391Skarels 		clear_qd_screen(unit);
1051*30391Skarels 		ldcursor(unit, cons_cursor);	/* load default cursor map */
1052*30391Skarels 		ldfont(unit);			/* load the console font */
1053*30391Skarels 		setup_input(unit);		/* init the DUART */
1054*30391Skarels 		break;
1055*30391Skarels 
1056*30391Skarels 	    /*----------------------------------------
1057*30391Skarels 	    * init the DUART and driver variables  */
1058*30391Skarels 
1059*30391Skarels 	    case QD_SET:
1060*30391Skarels 
1061*30391Skarels 		init_shared(unit);
1062*30391Skarels 		setup_input(unit);
1063*30391Skarels 		break;
1064*30391Skarels 
1065*30391Skarels 	    /*---------------------------------------------------------------
1066*30391Skarels 	    * clear the QDSS screen.  (NOTE that this reinits the dragon) */
1067*30391Skarels 
1068*30391Skarels 	    case QD_CLRSCRN:
1069*30391Skarels 
1070*30391Skarels 		setup_dragon(unit);
1071*30391Skarels 		clear_qd_screen(unit);
1072*30391Skarels 		break;
1073*30391Skarels 
1074*30391Skarels 	    /*------------------------------------
1075*30391Skarels 	    * load a cursor into template RAM  */
1076*30391Skarels 
1077*30391Skarels 	    case QD_WTCURSOR:
1078*30391Skarels 
1079*30391Skarels 		ldcursor(unit, datap);
1080*30391Skarels 		break;
1081*30391Skarels 
1082*30391Skarels 	    case QD_RDCURSOR:
1083*30391Skarels 
1084*30391Skarels 		temp = (short *) qdmap[unit].template;
1085*30391Skarels 
1086*30391Skarels 		/* cursor is 32 WORDS from the end of the 8k WORD...
1087*30391Skarels 		*  ...template space */
1088*30391Skarels 
1089*30391Skarels 		temp += (8 * 1024) - 32;
1090*30391Skarels 
1091*30391Skarels 		for (i = 0; i < 32; ++i, datap += sizeof(short))
1092*30391Skarels 		    *(short *)datap = *temp++;
1093*30391Skarels 		break;
1094*30391Skarels 
1095*30391Skarels 	    /*------------------------------
1096*30391Skarels 	    * position the mouse cursor  */
1097*30391Skarels 
1098*30391Skarels 	    case QD_POSCURSOR:
1099*30391Skarels 
1100*30391Skarels 		dga = (struct dga *) qdmap[unit].dga;
1101*30391Skarels 		pos = (struct _vs_cursor *) datap;
1102*30391Skarels 		s = spl5();
1103*30391Skarels 		dga->x_cursor = TRANX(pos->x);
1104*30391Skarels 		dga->y_cursor = TRANY(pos->y);
1105*30391Skarels 		eq_header[unit]->curs_pos.x = pos->x;
1106*30391Skarels 		eq_header[unit]->curs_pos.y = pos->y;
1107*30391Skarels 		splx(s);
1108*30391Skarels 		break;
1109*30391Skarels 
1110*30391Skarels 	    /*--------------------------------------
1111*30391Skarels 	    * set the cursor acceleration factor */
1112*30391Skarels 
1113*30391Skarels 	    case QD_PRGCURSOR:
1114*30391Skarels 
1115*30391Skarels 		curs = (struct prg_cursor *) datap;
1116*30391Skarels 		s = spl5();
1117*30391Skarels 		qdflags[unit].curs_acc = curs->acc_factor;
1118*30391Skarels 		qdflags[unit].curs_thr = curs->threshold;
1119*30391Skarels 		splx(s);
1120*30391Skarels 		break;
1121*30391Skarels 
1122*30391Skarels 	    /*---------------------------------------
1123*30391Skarels 	    * enable 'user write' to device pages */
1124*30391Skarels 
1125*30391Skarels 	    case QD_MAPDEVICE:
1126*30391Skarels 
1127*30391Skarels 		/*--------------
1128*30391Skarels 		* init stuff */
1129*30391Skarels 
1130*30391Skarels 		qdflags[unit].mapped |= MAPDEV;
1131*30391Skarels 		qd = (struct qdmap *) &qdmap[unit];
1132*30391Skarels 
1133*30391Skarels 		/*-------------------------------------
1134*30391Skarels 		* enable user write to template RAM */
1135*30391Skarels 
1136*30391Skarels 		mapix = VTOP((int)qd->template) - VTOP(qmem[0]);
1137*30391Skarels 		ptep = (int *)(QMEMmap[0] + mapix);
1138*30391Skarels 
1139*30391Skarels 		for (i = VTOP(TMPSIZE); i > 0; --i)
1140*30391Skarels 		    *ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V;
1141*30391Skarels 
1142*30391Skarels 		/*----------------------------------
1143*30391Skarels 		* enable user write to registers */
1144*30391Skarels 
1145*30391Skarels 		mapix = VTOP((int)qd->adder) - VTOP(qmem[0]);
1146*30391Skarels 		ptep = (int *)(QMEMmap[0] + mapix);
1147*30391Skarels 
1148*30391Skarels 		for (i = VTOP(REGSIZE); i > 0; --i)
1149*30391Skarels 		    *ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V;
1150*30391Skarels 
1151*30391Skarels 		/*-----------------------------------
1152*30391Skarels 		* enable user write to color maps */
1153*30391Skarels 
1154*30391Skarels 		mapix = VTOP((int)qd->red) - VTOP(qmem[0]);
1155*30391Skarels 		ptep = (int *)(QMEMmap[0] + mapix);
1156*30391Skarels 
1157*30391Skarels 		for (i = VTOP(CLRSIZE); i > 0; --i)
1158*30391Skarels 		    *ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V;
1159*30391Skarels 
1160*30391Skarels 		/*------------------------------
1161*30391Skarels 		* enable user write to DUART */
1162*30391Skarels 
1163*30391Skarels 		mapix = VTOP((int)qd->duart) - VTOP(qmem[0]);
1164*30391Skarels 		ptep = (int *)(QMEMmap[0] + mapix);
1165*30391Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; /* duart page */
1166*30391Skarels 
1167*30391Skarels 		mtpr(TBIA, 0);		/* smash CPU's translation buffer */
1168*30391Skarels 
1169*30391Skarels 		/*------------------------------------------
1170*30391Skarels 		* stuff qdmap structure in return buffer */
1171*30391Skarels 
1172*30391Skarels 		bcopy(qd, datap, sizeof(struct qdmap));
1173*30391Skarels 		break;
1174*30391Skarels 
1175*30391Skarels 	    /*-------------------------------------
1176*30391Skarels 	    * do setup for DMA by user process	*/
1177*30391Skarels 
1178*30391Skarels 	    case QD_MAPIOBUF:
1179*30391Skarels 
1180*30391Skarels 		/*------------------------------------------------
1181*30391Skarels 		* set 'user write enable' bits for DMA buffer  */
1182*30391Skarels 
1183*30391Skarels 		qdflags[unit].mapped |= MAPDMA;
1184*30391Skarels 
1185*30391Skarels 		ptep = (int *) ((VTOP(DMAheader[unit]) * 4)
1186*30391Skarels 				+ (mfpr(SBR) | 0x80000000));
1187*30391Skarels 
1188*30391Skarels 		for (i = (DMAbuf_size >> PGSHIFT); i > 0; --i)
1189*30391Skarels 		    *ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V;
1190*30391Skarels 
1191*30391Skarels 		mtpr(TBIA, 0);			/* clr CPU translation buf */
1192*30391Skarels 
1193*30391Skarels 		/*-------------------------------------
1194*30391Skarels 		* set up QBUS map registers for DMA */
1195*30391Skarels 
1196*30391Skarels 		DMAheader[unit]->QBAreg =
1197*30391Skarels 				uballoc(0, DMAheader[unit], DMAbuf_size, 0);
1198*30391Skarels 
1199*30391Skarels 		if (DMAheader[unit]->QBAreg == 0)
1200*30391Skarels 		    mprintf("\nqd%d: qdioctl: QBA setup error", unit);
1201*30391Skarels 
1202*30391Skarels 		Qbus_unmap[unit] = DMAheader[unit]->QBAreg;
1203*30391Skarels 		DMAheader[unit]->QBAreg &= 0x3FFFF;
1204*30391Skarels 
1205*30391Skarels 		/*----------------------
1206*30391Skarels 		* return I/O buf adr */
1207*30391Skarels 
1208*30391Skarels 		*(int *)datap = (int) DMAheader[unit];
1209*30391Skarels 		break;
1210*30391Skarels 
1211*30391Skarels 	    /*----------------------------------------------------------------
1212*30391Skarels 	    * map the shared scroll param area and enable scroll interpts  */
1213*30391Skarels 
1214*30391Skarels 	    case QD_MAPSCROLL:
1215*30391Skarels 
1216*30391Skarels 		qdflags[unit].mapped |= MAPSCR;
1217*30391Skarels 
1218*30391Skarels 		ptep = (int *) ((VTOP(scroll[unit]) * 4)
1219*30391Skarels 				+ (mfpr(SBR) | 0x80000000));
1220*30391Skarels 
1221*30391Skarels 		/* allow user write to scroll area */
1222*30391Skarels 
1223*30391Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
1224*30391Skarels 
1225*30391Skarels 		mtpr(TBIA, 0);			/* clr CPU translation buf */
1226*30391Skarels 
1227*30391Skarels 		scroll[unit]->status = 0;
1228*30391Skarels 
1229*30391Skarels 		adder = (struct adder *) qdmap[unit].adder;
1230*30391Skarels 
1231*30391Skarels 		qdflags[unit].adder_ie |= FRAME_SYNC;
1232*30391Skarels 		adder->interrupt_enable = qdflags[unit].adder_ie;
1233*30391Skarels 
1234*30391Skarels 		/* return scroll area address */
1235*30391Skarels 
1236*30391Skarels 		*(int *)datap = (int) scroll[unit];
1237*30391Skarels 		break;
1238*30391Skarels 
1239*30391Skarels 	    /*-------------------------------------------------------------
1240*30391Skarels 	    * unmap shared scroll param area and disable scroll intrpts */
1241*30391Skarels 
1242*30391Skarels 	    case QD_UNMAPSCROLL:
1243*30391Skarels 
1244*30391Skarels 		if (qdflags[unit].mapped & MAPSCR) {
1245*30391Skarels 
1246*30391Skarels 		    qdflags[unit].mapped &= ~MAPSCR;
1247*30391Skarels 
1248*30391Skarels 		    ptep = (int *) ((VTOP(scroll[unit]) * 4)
1249*30391Skarels 				    + (mfpr(SBR) | 0x80000000));
1250*30391Skarels 
1251*30391Skarels 		    /* re-protect 512 scroll param area */
1252*30391Skarels 
1253*30391Skarels 		    *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
1254*30391Skarels 
1255*30391Skarels 		    mtpr(TBIA, 0);	/* smash CPU's translation buf */
1256*30391Skarels 
1257*30391Skarels 		    adder = (struct adder *) qdmap[unit].adder;
1258*30391Skarels 		    qdflags[unit].adder_ie &= ~FRAME_SYNC;
1259*30391Skarels 		    adder->interrupt_enable = qdflags[unit].adder_ie;
1260*30391Skarels 		}
1261*30391Skarels 		break;
1262*30391Skarels 
1263*30391Skarels 	    /*-----------------------------------------------------------
1264*30391Skarels 	    * map shared color map write buf and turn on vsync intrpt */
1265*30391Skarels 
1266*30391Skarels 	    case QD_MAPCOLOR:
1267*30391Skarels 
1268*30391Skarels 		qdflags[unit].mapped |= MAPCOLOR;
1269*30391Skarels 
1270*30391Skarels 		ptep = (int *) ((VTOP(color_buf[unit]) * 4)
1271*30391Skarels 				+ (mfpr(SBR) | 0x80000000));
1272*30391Skarels 
1273*30391Skarels 		/* allow user write to color map write buffer */
1274*30391Skarels 
1275*30391Skarels 		*ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V;
1276*30391Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
1277*30391Skarels 
1278*30391Skarels 		mtpr(TBIA, 0);			/* clr CPU translation buf */
1279*30391Skarels 
1280*30391Skarels 		adder = (struct adder *) qdmap[unit].adder;
1281*30391Skarels 
1282*30391Skarels 		qdflags[unit].adder_ie |= VSYNC;
1283*30391Skarels 		adder->interrupt_enable = qdflags[unit].adder_ie;
1284*30391Skarels 
1285*30391Skarels 		/* return scroll area address */
1286*30391Skarels 
1287*30391Skarels 		*(int *)datap = (int) color_buf[unit];
1288*30391Skarels 		break;
1289*30391Skarels 
1290*30391Skarels 	    /*--------------------------------------------------------------
1291*30391Skarels 	    * unmap shared color map write buffer and kill VSYNC intrpts */
1292*30391Skarels 
1293*30391Skarels 	    case QD_UNMAPCOLOR:
1294*30391Skarels 
1295*30391Skarels 		if (qdflags[unit].mapped & MAPCOLOR) {
1296*30391Skarels 
1297*30391Skarels 		    qdflags[unit].mapped &= ~MAPCOLOR;
1298*30391Skarels 
1299*30391Skarels 		    ptep = (int *) ((VTOP(color_buf[unit]) * 4)
1300*30391Skarels 				    + (mfpr(SBR) | 0x80000000));
1301*30391Skarels 
1302*30391Skarels 		    /* re-protect color map write buffer */
1303*30391Skarels 
1304*30391Skarels 		    *ptep++ = (*ptep & ~PG_PROT) | PG_KW | PG_V;
1305*30391Skarels 		    *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
1306*30391Skarels 
1307*30391Skarels 		    mtpr(TBIA, 0);	/* smash CPU's translation buf */
1308*30391Skarels 
1309*30391Skarels 		    adder = (struct adder *) qdmap[unit].adder;
1310*30391Skarels 
1311*30391Skarels 		    qdflags[unit].adder_ie &= ~VSYNC;
1312*30391Skarels 		    adder->interrupt_enable = qdflags[unit].adder_ie;
1313*30391Skarels 		}
1314*30391Skarels 		break;
1315*30391Skarels 
1316*30391Skarels 	    /*---------------------------------------------
1317*30391Skarels 	    * give user write access to the event queue */
1318*30391Skarels 
1319*30391Skarels 	    case QD_MAPEVENT:
1320*30391Skarels 
1321*30391Skarels 		qdflags[unit].mapped |= MAPEQ;
1322*30391Skarels 
1323*30391Skarels 		ptep = (int *) ((VTOP(eq_header[unit]) * 4)
1324*30391Skarels 				+ (mfpr(SBR) | 0x80000000));
1325*30391Skarels 
1326*30391Skarels 		/* allow user write to 1K event queue */
1327*30391Skarels 
1328*30391Skarels 		*ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V;
1329*30391Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
1330*30391Skarels 
1331*30391Skarels 		mtpr(TBIA, 0);			/* clr CPU translation buf */
1332*30391Skarels 
1333*30391Skarels 		/* return event queue address */
1334*30391Skarels 
1335*30391Skarels 		*(int *)datap = (int) eq_header[unit];
1336*30391Skarels 		break;
1337*30391Skarels 
1338*30391Skarels 	    /*-----------------------------------------------
1339*30391Skarels 	    * pass caller's programming commands to LK201 */
1340*30391Skarels 
1341*30391Skarels 	    case QD_PRGKBD:
1342*30391Skarels 
1343*30391Skarels 		duart = (struct duart *) qdmap[unit].duart;
1344*30391Skarels 		cmdbuf = (struct prgkbd *) datap;    /* pnt to kbd cmd buf */
1345*30391Skarels 
1346*30391Skarels 		/*----------------
1347*30391Skarels 		* send command */
1348*30391Skarels 
1349*30391Skarels 		for (i = 1000; i > 0; --i) {
1350*30391Skarels 		    if ((status = duart->statusA) & XMT_RDY) {
1351*30391Skarels 			duart->dataA = cmdbuf->cmd;
1352*30391Skarels 			break;
1353*30391Skarels 		    }
1354*30391Skarels 		}
1355*30391Skarels 
1356*30391Skarels 		if (i == 0) {
1357*30391Skarels 		    mprintf("\nqd%d: qdioctl: timeout on XMT_RDY [1]", unit);
1358*30391Skarels 		    break;
1359*30391Skarels 		}
1360*30391Skarels 
1361*30391Skarels 		/*----------------
1362*30391Skarels 		* send param1? */
1363*30391Skarels 
1364*30391Skarels 		if (cmdbuf->cmd & LAST_PARAM)
1365*30391Skarels 		    break;
1366*30391Skarels 
1367*30391Skarels 		for (i = 1000; i > 0; --i) {
1368*30391Skarels 		    if ((status = duart->statusA) & XMT_RDY) {
1369*30391Skarels 			duart->dataA = cmdbuf->param1;
1370*30391Skarels 			break;
1371*30391Skarels 		    }
1372*30391Skarels 		}
1373*30391Skarels 
1374*30391Skarels 		if (i == 0) {
1375*30391Skarels 		    mprintf("\nqd%d: qdioctl: timeout on XMT_RDY [2]", unit);
1376*30391Skarels 		    break;
1377*30391Skarels 		}
1378*30391Skarels 
1379*30391Skarels 		/*----------------
1380*30391Skarels 		* send param2? */
1381*30391Skarels 
1382*30391Skarels 		if (cmdbuf->param1 & LAST_PARAM)
1383*30391Skarels 		    break;
1384*30391Skarels 
1385*30391Skarels 		for (i = 1000; i > 0; --i) {
1386*30391Skarels 		    if ((status = duart->statusA) & XMT_RDY) {
1387*30391Skarels 			duart->dataA = cmdbuf->param2;
1388*30391Skarels 			break;
1389*30391Skarels 		    }
1390*30391Skarels 		}
1391*30391Skarels 
1392*30391Skarels 		if (i == 0) {
1393*30391Skarels 		    mprintf("\nqd%d: qdioctl: timeout on XMT_RDY [3]", unit);
1394*30391Skarels 		    break;
1395*30391Skarels 		}
1396*30391Skarels 
1397*30391Skarels 		break;
1398*30391Skarels 
1399*30391Skarels 	    /*----------------------------------------------------
1400*30391Skarels 	    * pass caller's programming commands to the mouse  */
1401*30391Skarels 
1402*30391Skarels 	    case QD_PRGMOUSE:
1403*30391Skarels 
1404*30391Skarels 		duart = (struct duart *) qdmap[unit].duart;
1405*30391Skarels 
1406*30391Skarels 		for (i = 1000; i > 0; --i) {
1407*30391Skarels 		    if ((status = duart->statusB) & XMT_RDY) {
1408*30391Skarels 			duart->dataB = *datap;
1409*30391Skarels 			break;
1410*30391Skarels 		    }
1411*30391Skarels 		}
1412*30391Skarels 
1413*30391Skarels 		if (i == 0) {
1414*30391Skarels 		    mprintf("\nqd%d: qdioctl: timeout on XMT_RDY [4]", unit);
1415*30391Skarels 		}
1416*30391Skarels 
1417*30391Skarels 		break;
1418*30391Skarels 
1419*30391Skarels 	    /*----------------------------------------------
1420*30391Skarels 	    * get QDSS configuration word and return it  */
1421*30391Skarels 
1422*30391Skarels 	    case QD_RDCONFIG:
1423*30391Skarels 
1424*30391Skarels 		*(short *)datap = qdflags[unit].config;
1425*30391Skarels 		break;
1426*30391Skarels 
1427*30391Skarels 	    /*--------------------------------------------------------------
1428*30391Skarels 	    * re-route kernel console messages to the alternate console  */
1429*30391Skarels 
1430*30391Skarels 	    case QD_KERN_LOOP:
1431*30391Skarels 
1432*30391Skarels 		qdflags[unit].kernel_loop = -1;
1433*30391Skarels 		break;
1434*30391Skarels 
1435*30391Skarels 	    case QD_KERN_UNLOOP:
1436*30391Skarels 
1437*30391Skarels 		qdflags[unit].kernel_loop = 0;
1438*30391Skarels 		break;
1439*30391Skarels 
1440*30391Skarels 	    /*----------------------
1441*30391Skarels 	    * program the tablet */
1442*30391Skarels 
1443*30391Skarels 	    case QD_PRGTABLET:
1444*30391Skarels 
1445*30391Skarels 		duart = (struct duart *) qdmap[unit].duart;
1446*30391Skarels 
1447*30391Skarels 		for (i = 1000; i > 0; --i) {
1448*30391Skarels 		    if ((status = duart->statusB) & XMT_RDY) {
1449*30391Skarels 			duart->dataB = *datap;
1450*30391Skarels 			break;
1451*30391Skarels 		    }
1452*30391Skarels 		}
1453*30391Skarels 
1454*30391Skarels 		if (i == 0) {
1455*30391Skarels 		    mprintf("\nqd%d: qdioctl: timeout on XMT_RDY [5]", unit);
1456*30391Skarels 		}
1457*30391Skarels 
1458*30391Skarels 		break;
1459*30391Skarels 
1460*30391Skarels 	    /*-----------------------------------------------
1461*30391Skarels 	    * program the tablet report resolution factor */
1462*30391Skarels 
1463*30391Skarels 	    case QD_PRGTABRES:
1464*30391Skarels 
1465*30391Skarels 		qdflags[unit].tab_res = *(short *)datap;
1466*30391Skarels 		break;
1467*30391Skarels 
1468*30391Skarels 	    case DEVIOCGET:			    /* device status */
1469*30391Skarels 		    devget = (struct devget *)datap;
1470*30391Skarels 		    bzero(devget,sizeof(struct devget));
1471*30391Skarels 		    devget->category = DEV_TERMINAL;
1472*30391Skarels 		    devget->bus = DEV_QB;
1473*30391Skarels 		    bcopy(DEV_VCB02,devget->interface,
1474*30391Skarels 			  strlen(DEV_VCB02));
1475*30391Skarels 		    bcopy(DEV_VR290,devget->device,
1476*30391Skarels 			  strlen(DEV_VR290));		    /* terminal */
1477*30391Skarels 		    devget->adpt_num = ui->ui_adpt;	    /* which adapter*/
1478*30391Skarels 		    devget->nexus_num = ui->ui_nexus;	    /* which nexus  */
1479*30391Skarels 		    devget->bus_num = ui->ui_ubanum;	    /* which QB     */
1480*30391Skarels 		    devget->ctlr_num = unit;		    /* which interf.*/
1481*30391Skarels 		    devget->slave_num = unit;		    /* which line   */
1482*30391Skarels 		    bcopy(ui->ui_driver->ud_dname,
1483*30391Skarels 			  devget->dev_name,
1484*30391Skarels 			  strlen(ui->ui_driver->ud_dname)); /* Ultrix "qd"  */
1485*30391Skarels 		    devget->unit_num = unit;		    /* qd line?     */
1486*30391Skarels 		    devget->soft_count =
1487*30391Skarels 			  sc->sc_softcnt;		    /* soft er. cnt.*/
1488*30391Skarels 		    devget->hard_count =
1489*30391Skarels 			  sc->sc_hardcnt;		    /* hard er cnt. */
1490*30391Skarels 		    devget->stat = sc->sc_flags;	    /* status	    */
1491*30391Skarels 		    devget->category_stat =
1492*30391Skarels 			  sc->sc_category_flags;	    /* cat. stat.   */
1493*30391Skarels 		    break;
1494*30391Skarels 
1495*30391Skarels 	    default:
1496*30391Skarels 		/*-----------------------------
1497*30391Skarels 		* service tty type ioctl's  */
1498*30391Skarels 
1499*30391Skarels 		    if (!(minor_dev & 0x02)) {
1500*30391Skarels 
1501*30391Skarels 			tp = &qd_tty[minor_dev];
1502*30391Skarels 
1503*30391Skarels 			error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, datap, flags);
1504*30391Skarels 			if (error >= 0) {
1505*30391Skarels 			    return(error);
1506*30391Skarels 			}
1507*30391Skarels 
1508*30391Skarels 			error = ttioctl(tp, cmd, datap, flags);
1509*30391Skarels 			if (error >= 0) {
1510*30391Skarels 			    return(error);
1511*30391Skarels 			}
1512*30391Skarels 		    }
1513*30391Skarels 		    break;
1514*30391Skarels 	}
1515*30391Skarels 
1516*30391Skarels /*--------------------------------
1517*30391Skarels * clean up and get outta here  */
1518*30391Skarels 
1519*30391Skarels 	return(0);
1520*30391Skarels 
1521*30391Skarels } /* qdioctl */
1522*30391Skarels 
1523*30391Skarels /**********************************************************************
1524*30391Skarels *
1525*30391Skarels *	qdselect()... service select call for event queue input
1526*30391Skarels *
1527*30391Skarels **********************************************************************/
1528*30391Skarels 
1529*30391Skarels qdselect(dev, rw)
1530*30391Skarels dev_t dev;
1531*30391Skarels int rw;
1532*30391Skarels {
1533*30391Skarels 	register int s;
1534*30391Skarels 	register int unit;
1535*30391Skarels 
1536*30391Skarels 	s = spl5();
1537*30391Skarels 	unit = minor(dev) >> 2;
1538*30391Skarels 
1539*30391Skarels 	switch (rw) {
1540*30391Skarels 
1541*30391Skarels 	    case FREAD: 		/* event available? */
1542*30391Skarels 
1543*30391Skarels 		if(!(ISEMPTY(eq_header[unit]))) {
1544*30391Skarels 		    splx(s);
1545*30391Skarels 		    return(1);		/* return "1" if event exists */
1546*30391Skarels 		}
1547*30391Skarels 		rsel[unit] = u.u_procp;
1548*30391Skarels 		qdflags[unit].selmask |= SEL_READ;
1549*30391Skarels 		splx(s);
1550*30391Skarels 		return(0);
1551*30391Skarels 
1552*30391Skarels 	    case FWRITE:		/* DMA done? */
1553*30391Skarels 
1554*30391Skarels 		if (DMA_ISEMPTY(DMAheader[unit])) {
1555*30391Skarels 		    splx(s);
1556*30391Skarels 		    return(1);		/* return "1" if DMA is done */
1557*30391Skarels 		}
1558*30391Skarels 		rsel[unit] = u.u_procp;
1559*30391Skarels 		qdflags[unit].selmask |= SEL_WRITE;
1560*30391Skarels 		splx(s);
1561*30391Skarels 		return(0);
1562*30391Skarels 	}
1563*30391Skarels 
1564*30391Skarels } /* qdselect() */
1565*30391Skarels 
1566*30391Skarels /***************************************************************
1567*30391Skarels *
1568*30391Skarels *	qdwrite()... output to the QDSS screen as a TTY
1569*30391Skarels *
1570*30391Skarels ***************************************************************/
1571*30391Skarels 
1572*30391Skarels extern qd_strategy();
1573*30391Skarels 
1574*30391Skarels qdwrite(dev, uio)
1575*30391Skarels dev_t dev;
1576*30391Skarels struct uio *uio;
1577*30391Skarels {
1578*30391Skarels 	register struct tty *tp;
1579*30391Skarels 	register int minor_dev;
1580*30391Skarels 	register int unit;
1581*30391Skarels 
1582*30391Skarels 	minor_dev = minor(dev);
1583*30391Skarels 	unit = (minor_dev >> 2) & 0x07;
1584*30391Skarels 
1585*30391Skarels 	/*------------------------------
1586*30391Skarels 	* if this is the console...  */
1587*30391Skarels 
1588*30391Skarels 	if ((minor_dev & 0x03) != 0x02	&&
1589*30391Skarels 	     qdflags[unit].inuse & CONS_DEV) {
1590*30391Skarels 	    tp = &qd_tty[minor_dev];
1591*30391Skarels 	    return ((*linesw[tp->t_line].l_write)(tp, uio));
1592*30391Skarels 	}
1593*30391Skarels 
1594*30391Skarels 	/*------------------------------------------------
1595*30391Skarels 	* else this must be a DMA xfer from user space */
1596*30391Skarels 
1597*30391Skarels 	else if (qdflags[unit].inuse & GRAPHIC_DEV) {
1598*30391Skarels 	    return (physio(qd_strategy, &qdbuf[unit],
1599*30391Skarels 			   dev, B_WRITE, minphys, uio));
1600*30391Skarels 	}
1601*30391Skarels }
1602*30391Skarels 
1603*30391Skarels /***************************************************************
1604*30391Skarels *
1605*30391Skarels *	qdread()... read from QDSS keyboard as a TTY
1606*30391Skarels *
1607*30391Skarels ***************************************************************/
1608*30391Skarels 
1609*30391Skarels qdread(dev, uio)
1610*30391Skarels dev_t dev;
1611*30391Skarels struct uio *uio;
1612*30391Skarels {
1613*30391Skarels 	register struct tty *tp;
1614*30391Skarels 	register int minor_dev;
1615*30391Skarels 	register int unit;
1616*30391Skarels 
1617*30391Skarels 	minor_dev = minor(dev);
1618*30391Skarels 	unit = (minor_dev >> 2) & 0x07;
1619*30391Skarels 
1620*30391Skarels 	/*------------------------------
1621*30391Skarels 	* if this is the console...  */
1622*30391Skarels 
1623*30391Skarels 	if ((minor_dev & 0x03) != 0x02	&&
1624*30391Skarels 	     qdflags[unit].inuse & CONS_DEV) {
1625*30391Skarels 	    tp = &qd_tty[minor_dev];
1626*30391Skarels 	    return ((*linesw[tp->t_line].l_read)(tp, uio));
1627*30391Skarels 	}
1628*30391Skarels 
1629*30391Skarels 	/*------------------------------------------------
1630*30391Skarels 	* else this must be a bitmap-to-processor xfer */
1631*30391Skarels 
1632*30391Skarels 	else if (qdflags[unit].inuse & GRAPHIC_DEV) {
1633*30391Skarels 	    return (physio(qd_strategy, &qdbuf[unit],
1634*30391Skarels 			   dev, B_READ, minphys, uio));
1635*30391Skarels 	}
1636*30391Skarels }
1637*30391Skarels 
1638*30391Skarels /***************************************************************
1639*30391Skarels *
1640*30391Skarels *	qd_strategy()... strategy routine to do DMA
1641*30391Skarels *
1642*30391Skarels ***************************************************************/
1643*30391Skarels 
1644*30391Skarels qd_strategy(bp)
1645*30391Skarels register struct buf *bp;
1646*30391Skarels {
1647*30391Skarels 	register struct dga *dga;
1648*30391Skarels 	register struct adder *adder;
1649*30391Skarels 
1650*30391Skarels 	char *DMAbufp;
1651*30391Skarels 
1652*30391Skarels 	int QBAreg;
1653*30391Skarels 	int bytcnt;
1654*30391Skarels 	int s;
1655*30391Skarels 	int unit;
1656*30391Skarels 	int cookie;
1657*30391Skarels 
1658*30391Skarels 	int i,j,k;
1659*30391Skarels 
1660*30391Skarels 	unit = (minor(bp->b_dev) >> 2) & 0x07;
1661*30391Skarels 
1662*30391Skarels /*-----------------
1663*30391Skarels * init pointers */
1664*30391Skarels 
1665*30391Skarels 	if ((QBAreg = ubasetup(0, bp, 0)) == 0) {
1666*30391Skarels 	    mprintf("\nqd%d: qd_strategy: QBA setup error", unit);
1667*30391Skarels 	    goto STRAT_ERR;
1668*30391Skarels 	}
1669*30391Skarels 
1670*30391Skarels 	dga = (struct dga *) qdmap[unit].dga;
1671*30391Skarels 
1672*30391Skarels 	s = spl5();
1673*30391Skarels 
1674*30391Skarels 	qdflags[unit].user_dma = -1;
1675*30391Skarels 
1676*30391Skarels 	dga->csr |= DMA_IE;
1677*30391Skarels 
1678*30391Skarels 	cookie = QBAreg & 0x3FFFF;
1679*30391Skarels 	dga->adrs_lo = (short) cookie;
1680*30391Skarels 	dga->adrs_hi = (short) (cookie >> 16);
1681*30391Skarels 
1682*30391Skarels 	dga->bytcnt_lo = (short) bp->b_bcount;
1683*30391Skarels 	dga->bytcnt_hi = (short) (bp->b_bcount >> 16);
1684*30391Skarels 
1685*30391Skarels 	while (qdflags[unit].user_dma) {
1686*30391Skarels 	    sleep((caddr_t)&qdflags[unit].user_dma, QDPRIOR);
1687*30391Skarels 	}
1688*30391Skarels 
1689*30391Skarels 	splx(s);
1690*30391Skarels 	ubarelse(0, &QBAreg);
1691*30391Skarels 
1692*30391Skarels 	if (!(dga->csr & DMA_ERR)) {
1693*30391Skarels 	    iodone(bp);
1694*30391Skarels 	    return;
1695*30391Skarels 	}
1696*30391Skarels 
1697*30391Skarels STRAT_ERR:
1698*30391Skarels 	adder = (struct adder *) qdmap[unit].adder;
1699*30391Skarels 	adder->command = CANCEL;		/* cancel adder activity */
1700*30391Skarels 	dga->csr &= ~DMA_IE;
1701*30391Skarels 	dga->csr &= ~0x0600;		/* halt DMA (reset fifo) */
1702*30391Skarels 	dga->csr |= DMA_ERR;		/* clear error condition */
1703*30391Skarels 	bp->b_flags |= B_ERROR; 	/* flag an error to physio() */
1704*30391Skarels 
1705*30391Skarels 	/* if DMA was running, flush spurious intrpt */
1706*30391Skarels 
1707*30391Skarels 	if (dga->bytcnt_lo != 0) {
1708*30391Skarels 	    dga->bytcnt_lo = 0;
1709*30391Skarels 	    dga->bytcnt_hi = 0;
1710*30391Skarels 	    DMA_SETIGNORE(DMAheader[unit]);
1711*30391Skarels 	    dga->csr |= DMA_IE;
1712*30391Skarels 	}
1713*30391Skarels 
1714*30391Skarels 	iodone(bp);
1715*30391Skarels 
1716*30391Skarels } /* qd_strategy */
1717*30391Skarels 
1718*30391Skarels /*******************************************************************
1719*30391Skarels *
1720*30391Skarels *	qdstart()... startup output to the console screen
1721*30391Skarels *
1722*30391Skarels ********************************************************************
1723*30391Skarels *
1724*30391Skarels *	calling convention:
1725*30391Skarels *
1726*30391Skarels *		qdstart(tp);
1727*30391Skarels *		struct tty *tp; 	;pointer to tty structure
1728*30391Skarels *
1729*30391Skarels ********/
1730*30391Skarels 
1731*30391Skarels qdstart(tp)
1732*30391Skarels register struct tty *tp;
1733*30391Skarels {
1734*30391Skarels 	register int which_unit, unit, c;
1735*30391Skarels 	register struct tty *tp0;
1736*30391Skarels 	int s;
1737*30391Skarels 
1738*30391Skarels 	int curs_on;
1739*30391Skarels 	struct dga *dga;
1740*30391Skarels 
1741*30391Skarels 	unit = minor(tp->t_dev);
1742*30391Skarels 
1743*30391Skarels 	tp0 = &qd_tty[(unit & 0x0FC)+1];
1744*30391Skarels 	which_unit = (unit >> 2) & 0x3;
1745*30391Skarels 	unit &= 0x03;
1746*30391Skarels 
1747*30391Skarels 	s = spl5();
1748*30391Skarels 
1749*30391Skarels /*------------------------------------------------------------------
1750*30391Skarels * If it's currently active, or delaying, no need to do anything. */
1751*30391Skarels 
1752*30391Skarels 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
1753*30391Skarels 		goto out;
1754*30391Skarels 
1755*30391Skarels /*-------------------------------------------------------------------
1756*30391Skarels * Display chars until the queue is empty, if the alternate console device
1757*30391Skarels * is open direct chars there.  Drop input from anything but the console
1758*30391Skarels * device on the floor.	*/
1759*30391Skarels 
1760*30391Skarels 	while (tp->t_outq.c_cc) {
1761*30391Skarels 	    c = getc(&tp->t_outq);
1762*30391Skarels 	    if (unit == 0) {
1763*30391Skarels 		if (tp0->t_state & TS_ISOPEN)
1764*30391Skarels 		    (*linesw[tp0->t_line].l_rint)(c, tp0);
1765*30391Skarels 		else
1766*30391Skarels 		    blitc(which_unit, c & 0xFF);
1767*30391Skarels 	    }
1768*30391Skarels 	}
1769*30391Skarels 
1770*30391Skarels /*--------------------------------------------------------
1771*30391Skarels * If there are sleepers, and output has drained below low
1772*30391Skarels * water mark, wake up the sleepers. */
1773*30391Skarels 
1774*30391Skarels 	if ( tp->t_outq.c_cc <= TTLOWAT(tp) ) {
1775*30391Skarels 		if (tp->t_state & TS_ASLEEP){
1776*30391Skarels 			tp->t_state &= ~TS_ASLEEP;
1777*30391Skarels 			wakeup((caddr_t) &tp->t_outq);
1778*30391Skarels 		}
1779*30391Skarels 	}
1780*30391Skarels 
1781*30391Skarels 	tp->t_state &= ~TS_BUSY;
1782*30391Skarels 
1783*30391Skarels out:
1784*30391Skarels 	splx(s);
1785*30391Skarels 
1786*30391Skarels } /* qdstart */
1787*30391Skarels 
1788*30391Skarels 
1789*30391Skarels /*******************************************************************
1790*30391Skarels *
1791*30391Skarels *	qdstop()... stop the tty
1792*30391Skarels *
1793*30391Skarels *******************************************************************/
1794*30391Skarels 
1795*30391Skarels qdstop(tp, flag)
1796*30391Skarels register struct tty *tp;
1797*30391Skarels int flag;
1798*30391Skarels {
1799*30391Skarels 	register int s;
1800*30391Skarels 
1801*30391Skarels 	s = spl5();	/* block intrpts during state modification */
1802*30391Skarels 
1803*30391Skarels 	if (tp->t_state & TS_BUSY) {
1804*30391Skarels 	    if ((tp->t_state & TS_TTSTOP) == 0) {
1805*30391Skarels 		tp->t_state |= TS_FLUSH;
1806*30391Skarels 	    } else
1807*30391Skarels 		tp->t_state &= ~TS_BUSY;
1808*30391Skarels 	}
1809*30391Skarels 	splx(s);
1810*30391Skarels }
1811*30391Skarels 
1812*30391Skarels /*******************************************************************
1813*30391Skarels *
1814*30391Skarels *	blitc()... output a character to the QDSS screen
1815*30391Skarels *
1816*30391Skarels ********************************************************************
1817*30391Skarels *
1818*30391Skarels *	calling convention:
1819*30391Skarels *
1820*30391Skarels *		blitc(chr);
1821*30391Skarels *		char chr;		;character to be displayed
1822*30391Skarels *
1823*30391Skarels ********/
1824*30391Skarels 
1825*30391Skarels blitc(unit, chr)
1826*30391Skarels int unit;
1827*30391Skarels char chr;
1828*30391Skarels {
1829*30391Skarels 	register struct adder *adder;
1830*30391Skarels 	register struct dga *dga;
1831*30391Skarels 	register int i;
1832*30391Skarels 
1833*30391Skarels 	short x;
1834*30391Skarels 
1835*30391Skarels /*---------------
1836*30391Skarels * init stuff  */
1837*30391Skarels 
1838*30391Skarels 	adder = (struct adder *) qdmap[unit].adder;
1839*30391Skarels 	dga = (struct dga *) qdmap[unit].dga;
1840*30391Skarels 
1841*30391Skarels /*---------------------------
1842*30391Skarels * non display character?  */
1843*30391Skarels 
1844*30391Skarels 	chr &= 0x7F;
1845*30391Skarels 
1846*30391Skarels 	switch (chr) {
1847*30391Skarels 
1848*30391Skarels 	    case '\r':			/* return char */
1849*30391Skarels 		cursor[unit].x = 0;
1850*30391Skarels 		dga->x_cursor = TRANX(cursor[unit].x);
1851*30391Skarels 		return(0);
1852*30391Skarels 
1853*30391Skarels 	    case '\t':			/* tab char */
1854*30391Skarels 
1855*30391Skarels 		for (i = 8 - ((cursor[unit].x >> 3) & 0x07); i > 0; --i) {
1856*30391Skarels 		    blitc(unit, ' ');
1857*30391Skarels 		}
1858*30391Skarels 		return(0);
1859*30391Skarels 
1860*30391Skarels 	    case '\n':			/* line feed char */
1861*30391Skarels 
1862*30391Skarels 		if ((cursor[unit].y += CHAR_HEIGHT) > (863 - CHAR_HEIGHT)) {
1863*30391Skarels 		    if (qdflags[unit].inuse & GRAPHIC_DEV) {
1864*30391Skarels 			cursor[unit].y = 0;
1865*30391Skarels 		    } else {
1866*30391Skarels 			cursor[unit].y -= CHAR_HEIGHT;
1867*30391Skarels 			scroll_up(adder);
1868*30391Skarels 		    }
1869*30391Skarels 		}
1870*30391Skarels 		dga->y_cursor = TRANY(cursor[unit].y);
1871*30391Skarels 		return(0);
1872*30391Skarels 
1873*30391Skarels 	    case '\b':			/* backspace char */
1874*30391Skarels 		if (cursor[unit].x > 0) {
1875*30391Skarels 		    cursor[unit].x -= CHAR_WIDTH;
1876*30391Skarels 		    blitc(unit, ' ');
1877*30391Skarels 		    cursor[unit].x -= CHAR_WIDTH;
1878*30391Skarels 		    dga->x_cursor = TRANX(cursor[unit].x);
1879*30391Skarels 		}
1880*30391Skarels 		return(0);
1881*30391Skarels 
1882*30391Skarels 	    default:
1883*30391Skarels 		if (chr < ' ' || chr > '~')
1884*30391Skarels 		    return(0);
1885*30391Skarels 	}
1886*30391Skarels 
1887*30391Skarels /*------------------------------------------
1888*30391Skarels * setup VIPER operand control registers  */
1889*30391Skarels 
1890*30391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0001);  /* select plane #0 */
1891*30391Skarels 	write_ID(adder, SRC1_OCR_B,
1892*30391Skarels 			EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY);
1893*30391Skarels 
1894*30391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x00FE);  /* select other planes */
1895*30391Skarels 	write_ID(adder, SRC1_OCR_B,
1896*30391Skarels 			EXT_SOURCE | INT_NONE | NO_ID | BAR_SHIFT_DELAY);
1897*30391Skarels 
1898*30391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x00FF);  /* select all planes */
1899*30391Skarels 	write_ID(adder, DST_OCR_B,
1900*30391Skarels 			EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
1901*30391Skarels 
1902*30391Skarels 	write_ID(adder, MASK_1, 0xFFFF);
1903*30391Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 1);
1904*30391Skarels 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
1905*30391Skarels 
1906*30391Skarels /*----------------------------------------
1907*30391Skarels * load DESTINATION origin and vectors  */
1908*30391Skarels 
1909*30391Skarels 	adder->fast_dest_dy = 0;
1910*30391Skarels 	adder->slow_dest_dx = 0;
1911*30391Skarels 	adder->error_1 = 0;
1912*30391Skarels 	adder->error_2 = 0;
1913*30391Skarels 
1914*30391Skarels 	adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL;
1915*30391Skarels 
1916*30391Skarels 	wait_status(adder, RASTEROP_COMPLETE);
1917*30391Skarels 
1918*30391Skarels 	adder->destination_x = cursor[unit].x;
1919*30391Skarels 	adder->fast_dest_dx = CHAR_WIDTH;
1920*30391Skarels 
1921*30391Skarels 	adder->destination_y = cursor[unit].y;
1922*30391Skarels 	adder->slow_dest_dy = CHAR_HEIGHT;
1923*30391Skarels 
1924*30391Skarels /*-----------------------------------
1925*30391Skarels * load SOURCE origin and vectors  */
1926*30391Skarels 
1927*30391Skarels 	adder->source_1_x = FONT_X + ((chr - ' ') * CHAR_WIDTH);
1928*30391Skarels 	adder->source_1_y = FONT_Y;
1929*30391Skarels 
1930*30391Skarels 	adder->source_1_dx = CHAR_WIDTH;
1931*30391Skarels 	adder->source_1_dy = CHAR_HEIGHT;
1932*30391Skarels 
1933*30391Skarels 	write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
1934*30391Skarels 	adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE;
1935*30391Skarels 
1936*30391Skarels /*-------------------------------------
1937*30391Skarels * update console cursor coordinates */
1938*30391Skarels 
1939*30391Skarels 	cursor[unit].x += CHAR_WIDTH;
1940*30391Skarels 	dga->x_cursor = TRANX(cursor[unit].x);
1941*30391Skarels 
1942*30391Skarels 	if (cursor[unit].x > (1024 - CHAR_WIDTH)) {
1943*30391Skarels 	    blitc(unit, '\r');
1944*30391Skarels 	    blitc(unit, '\n');
1945*30391Skarels 	}
1946*30391Skarels 
1947*30391Skarels } /* blitc */
1948*30391Skarels 
1949*30391Skarels qdreset(){}
1950*30391Skarels qd_init(){}
1951*30391Skarels 
1952*30391Skarels /******************************************************************
1953*30391Skarels *******************************************************************
1954*30391Skarels *******************************************************************
1955*30391Skarels *
1956*30391Skarels *	INTERRUPT SERVICE ROUTINES START HERE:
1957*30391Skarels *
1958*30391Skarels *******************************************************************
1959*30391Skarels *******************************************************************
1960*30391Skarels ******************************************************************/
1961*30391Skarels 
1962*30391Skarels /*****************************************************************
1963*30391Skarels *
1964*30391Skarels *	qddint()... service "DMA DONE" interrupt condition
1965*30391Skarels *
1966*30391Skarels *****************************************************************/
1967*30391Skarels 
1968*30391Skarels qddint(qd)
1969*30391Skarels int qd;
1970*30391Skarels {
1971*30391Skarels 	register struct DMAreq_header *header;
1972*30391Skarels 	register struct DMAreq *request;
1973*30391Skarels 	register struct dga *dga;
1974*30391Skarels 	struct adder *adder;
1975*30391Skarels 
1976*30391Skarels 	int cookie;			/* DMA adrs for QDSS */
1977*30391Skarels 	int i;
1978*30391Skarels 
1979*30391Skarels 	spl4(); 			/* allow interval timer in */
1980*30391Skarels 
1981*30391Skarels /*-----------------
1982*30391Skarels * init pointers */
1983*30391Skarels 
1984*30391Skarels 	header = DMAheader[qd]; 	    /* register for optimization */
1985*30391Skarels 	dga = (struct dga *) qdmap[qd].dga;
1986*30391Skarels 	adder = (struct adder *) qdmap[qd].adder;
1987*30391Skarels 
1988*30391Skarels /*------------------------------------------------------------------------
1989*30391Skarels * if this interrupt flagged as bogus for interrupt flushing purposes.. */
1990*30391Skarels 
1991*30391Skarels 	if (DMA_ISIGNORE(header)) {
1992*30391Skarels 	    DMA_CLRIGNORE(header);
1993*30391Skarels 	    return;
1994*30391Skarels 	}
1995*30391Skarels 
1996*30391Skarels /*----------------------------------------------------
1997*30391Skarels * dump a DMA hardware error message if appropriate */
1998*30391Skarels 
1999*30391Skarels 	if (dga->csr & DMA_ERR) {
2000*30391Skarels 
2001*30391Skarels 	    if (dga->csr & PARITY_ERR)
2002*30391Skarels 		mprintf("\nqd%d: qddint: DMA hardware parity fault.", qd);
2003*30391Skarels 
2004*30391Skarels 	    if (dga->csr & BUS_ERR)
2005*30391Skarels 		mprintf("\nqd%d: qddint: DMA hardware bus error.", qd);
2006*30391Skarels 	}
2007*30391Skarels 
2008*30391Skarels /*----------------------------------------
2009*30391Skarels * if this was a DMA from user space... */
2010*30391Skarels 
2011*30391Skarels 	if (qdflags[qd].user_dma) {
2012*30391Skarels 	    qdflags[qd].user_dma = 0;
2013*30391Skarels 	    wakeup((caddr_t)&qdflags[qd].user_dma);
2014*30391Skarels 	    return;
2015*30391Skarels 	}
2016*30391Skarels 
2017*30391Skarels /*------------------------------------------------------------------------
2018*30391Skarels * if we're doing DMA request queue services, field the error condition */
2019*30391Skarels 
2020*30391Skarels 	if (dga->csr & DMA_ERR) {
2021*30391Skarels 
2022*30391Skarels 	    dga->csr &= ~0x0600;		/* halt DMA (reset fifo) */
2023*30391Skarels 	    dga->csr |= DMA_ERR;		/* clear error condition */
2024*30391Skarels 	    adder->command = CANCEL;		/* cancel adder activity */
2025*30391Skarels 
2026*30391Skarels 	    DMA_SETERROR(header);	/* flag error in header status word */
2027*30391Skarels 	    DMA_CLRACTIVE(header);
2028*30391Skarels 	    header->DMAreq[header->oldest].DMAdone |= HARD_ERROR;
2029*30391Skarels 	    header->newest = header->oldest;
2030*30391Skarels 	    header->used = 0;
2031*30391Skarels 
2032*30391Skarels 	    if (rsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
2033*30391Skarels 		selwakeup(rsel[qd], 0);
2034*30391Skarels 		rsel[qd] = 0;
2035*30391Skarels 		qdflags[qd].selmask &= ~SEL_WRITE;
2036*30391Skarels 	    }
2037*30391Skarels 
2038*30391Skarels 	    if (dga->bytcnt_lo != 0) {
2039*30391Skarels 		dga->bytcnt_lo = 0;
2040*30391Skarels 		dga->bytcnt_hi = 0;
2041*30391Skarels 		DMA_SETIGNORE(header);
2042*30391Skarels 	    }
2043*30391Skarels 
2044*30391Skarels 	    return;
2045*30391Skarels 	}
2046*30391Skarels 
2047*30391Skarels /*----------------------------------------------------------------------------
2048*30391Skarels * if the DMA request queue is now becoming non-full, wakeup "select" client */
2049*30391Skarels 
2050*30391Skarels 	if (DMA_ISFULL(header)) {
2051*30391Skarels 
2052*30391Skarels 	    if (rsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
2053*30391Skarels 		selwakeup(rsel[qd], 0);
2054*30391Skarels 		rsel[qd] = 0;
2055*30391Skarels 		qdflags[qd].selmask &= ~SEL_WRITE;
2056*30391Skarels 	    }
2057*30391Skarels 	}
2058*30391Skarels 
2059*30391Skarels 	header->DMAreq[header->oldest].DMAdone |= REQUEST_DONE;
2060*30391Skarels 
2061*30391Skarels 	if (DMA_ISEMPTY(header)) {
2062*30391Skarels 	    mprintf("\nqd%d: qddint: unexpected interrupt", qd);
2063*30391Skarels 	    return;
2064*30391Skarels 	}
2065*30391Skarels 
2066*30391Skarels 	DMA_GETEND(header);	/* update request queue indices */
2067*30391Skarels 
2068*30391Skarels /*------------------------------------------------------------
2069*30391Skarels * if no more DMA pending, wake up "select" client and exit */
2070*30391Skarels 
2071*30391Skarels 	if (DMA_ISEMPTY(header)) {
2072*30391Skarels 
2073*30391Skarels 	    if (rsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
2074*30391Skarels 		selwakeup(rsel[qd], 0);
2075*30391Skarels 		rsel[qd] = 0;
2076*30391Skarels 		qdflags[qd].selmask &= ~SEL_WRITE;
2077*30391Skarels 	    }
2078*30391Skarels 
2079*30391Skarels 	    DMA_CLRACTIVE(header);  /* flag DMA done */
2080*30391Skarels 	    return;
2081*30391Skarels 	}
2082*30391Skarels 
2083*30391Skarels /*---------------------------
2084*30391Skarels * initiate next DMA xfer  */
2085*30391Skarels 
2086*30391Skarels 	request = DMA_GETBEGIN(header);
2087*30391Skarels 
2088*30391Skarels 	switch (request->DMAtype) {
2089*30391Skarels 
2090*30391Skarels 	    case DISPLIST:
2091*30391Skarels 		dga->csr |= DL_ENB;
2092*30391Skarels 		break;
2093*30391Skarels 
2094*30391Skarels 	    case PTOB:
2095*30391Skarels 		dga->csr |= PTOB_ENB;
2096*30391Skarels 		break;
2097*30391Skarels 
2098*30391Skarels 	    case BTOP:
2099*30391Skarels 		dga->csr |= BTOP_ENB;
2100*30391Skarels 		break;
2101*30391Skarels 
2102*30391Skarels 	    default:
2103*30391Skarels 		mprintf("\nqd%d: qddint: illegal DMAtype parameter.", qd);
2104*30391Skarels 		DMA_CLRACTIVE(header);	/* flag DMA done */
2105*30391Skarels 		return;
2106*30391Skarels 	}
2107*30391Skarels 
2108*30391Skarels 	if (request->DMAdone & COUNT_ZERO) {
2109*30391Skarels 	    dga->csr &= ~SET_DONE_FIFO;
2110*30391Skarels 	} else if (request->DMAdone & FIFO_EMPTY) {
2111*30391Skarels 	    dga->csr |= SET_DONE_FIFO;
2112*30391Skarels 	}
2113*30391Skarels 
2114*30391Skarels 	if (request->DMAdone & WORD_PACK)
2115*30391Skarels 	    dga->csr &= ~BYTE_DMA;
2116*30391Skarels 	else if (request->DMAdone & BYTE_PACK)
2117*30391Skarels 	    dga->csr |= BYTE_DMA;
2118*30391Skarels 
2119*30391Skarels 	dga->csr |= DMA_IE;
2120*30391Skarels 
2121*30391Skarels 	cookie = ((int)request->bufp - (int)header) + (int)header->QBAreg;
2122*30391Skarels 
2123*30391Skarels 	dga->adrs_lo = (short) cookie;
2124*30391Skarels 	dga->adrs_hi = (short) (cookie >> 16);
2125*30391Skarels 
2126*30391Skarels 	dga->bytcnt_lo = (short) request->length;
2127*30391Skarels 	dga->bytcnt_hi = (short) (request->length >> 16);
2128*30391Skarels 
2129*30391Skarels 	return;
2130*30391Skarels }
2131*30391Skarels 
2132*30391Skarels /*****************************************************************
2133*30391Skarels *
2134*30391Skarels *	qdaint()... ADDER interrupt service
2135*30391Skarels *
2136*30391Skarels *****************************************************************/
2137*30391Skarels 
2138*30391Skarels qdaint(qd)
2139*30391Skarels register int qd;
2140*30391Skarels {
2141*30391Skarels 	register struct adder *adder;
2142*30391Skarels 	struct color_buf *cbuf;
2143*30391Skarels 
2144*30391Skarels 	short stat;
2145*30391Skarels 	int i;
2146*30391Skarels 	register struct rgb *rgbp;
2147*30391Skarels 	register short *red;
2148*30391Skarels 	register short *green;
2149*30391Skarels 	register short *blue;
2150*30391Skarels 
2151*30391Skarels 	spl4(); 			/* allow interval timer in */
2152*30391Skarels 
2153*30391Skarels 	adder = (struct adder *) qdmap[qd].adder;
2154*30391Skarels 
2155*30391Skarels /*------------------------------------------------------------------------
2156*30391Skarels * service the vertical blank interrupt (VSYNC bit) by loading any pending
2157*30391Skarels * color map load request  */
2158*30391Skarels 
2159*30391Skarels 	if (adder->status & VSYNC) {
2160*30391Skarels 	    adder->status &= ~VSYNC;		/* clear the interrupt */
2161*30391Skarels 
2162*30391Skarels 	    cbuf = color_buf[qd];
2163*30391Skarels 	    if (cbuf->status & LOAD_COLOR_MAP) {
2164*30391Skarels 
2165*30391Skarels 		red = (short *) qdmap[qd].red;
2166*30391Skarels 		green = (short *) qdmap[qd].green;
2167*30391Skarels 		blue = (short *) qdmap[qd].blue;
2168*30391Skarels 
2169*30391Skarels 		for (i = cbuf->count, rgbp = cbuf->rgb; --i >= 0; rgbp++) {
2170*30391Skarels 
2171*30391Skarels 		    red[rgbp->offset] = (short) rgbp->red;
2172*30391Skarels 		    green[rgbp->offset] = (short) rgbp->green;
2173*30391Skarels 		    blue[rgbp->offset] = (short) rgbp->blue;
2174*30391Skarels 		}
2175*30391Skarels 
2176*30391Skarels 		cbuf->status &= ~LOAD_COLOR_MAP;
2177*30391Skarels 	    }
2178*30391Skarels 	}
2179*30391Skarels 
2180*30391Skarels /*-------------------------------------------------
2181*30391Skarels * service the scroll interrupt (FRAME_SYNC bit) */
2182*30391Skarels 
2183*30391Skarels 	if (adder->status & FRAME_SYNC) {
2184*30391Skarels 	    adder->status &= ~FRAME_SYNC;	/* clear the interrupt */
2185*30391Skarels 
2186*30391Skarels 	    if (scroll[qd]->status & LOAD_REGS) {
2187*30391Skarels 
2188*30391Skarels 		for ( i = 1000, adder->status = 0
2189*30391Skarels 		    ; i > 0  &&  !((stat = adder->status) & ID_SCROLL_READY)
2190*30391Skarels 		    ; --i);
2191*30391Skarels 
2192*30391Skarels 		if (i == 0) {
2193*30391Skarels 		    mprintf("\nqd%d: qdaint: timeout on ID_SCROLL_READY", qd);
2194*30391Skarels 		    return;
2195*30391Skarels 		}
2196*30391Skarels 
2197*30391Skarels 		adder->ID_scroll_data = scroll[qd]->viper_constant;
2198*30391Skarels 		adder->ID_scroll_command = ID_LOAD | SCROLL_CONSTANT;
2199*30391Skarels 
2200*30391Skarels 		adder->y_scroll_constant = scroll[qd]->y_scroll_constant;
2201*30391Skarels 		adder->y_offset_pending = scroll[qd]->y_offset;
2202*30391Skarels 
2203*30391Skarels 		if (scroll[qd]->status & LOAD_INDEX) {
2204*30391Skarels 
2205*30391Skarels 		    adder->x_index_pending = scroll[qd]->x_index_pending;
2206*30391Skarels 		    adder->y_index_pending = scroll[qd]->y_index_pending;
2207*30391Skarels 		}
2208*30391Skarels 
2209*30391Skarels 	    scroll[qd]->status = 0x00;
2210*30391Skarels 	    }
2211*30391Skarels 	}
2212*30391Skarels }
2213*30391Skarels 
2214*30391Skarels /*****************************************************************
2215*30391Skarels *
2216*30391Skarels *	qdiint()... DUART input interrupt service routine
2217*30391Skarels *
2218*30391Skarels *****************************************************************/
2219*30391Skarels 
2220*30391Skarels qdiint(qd)
2221*30391Skarels register int qd;
2222*30391Skarels {
2223*30391Skarels 	register struct _vs_event *event;
2224*30391Skarels 	register struct qdinput *eqh;
2225*30391Skarels 
2226*30391Skarels 	struct dga *dga;
2227*30391Skarels 	struct duart *duart;
2228*30391Skarels 	struct mouse_report *new_rep;
2229*30391Skarels 
2230*30391Skarels 	struct uba_device *ui;
2231*30391Skarels 	struct tty *tp;
2232*30391Skarels 
2233*30391Skarels 	char chr;
2234*30391Skarels 	int i,j;
2235*30391Skarels 	int k,l;
2236*30391Skarels 
2237*30391Skarels 	u_short status;
2238*30391Skarels 	u_short data;
2239*30391Skarels 	u_short key;
2240*30391Skarels 
2241*30391Skarels 	char do_wakeup = 0;		/* flag to do a select wakeup call */
2242*30391Skarels 	char a, b, c;			/* mouse button test variables */
2243*30391Skarels 
2244*30391Skarels 	spl4(); 			/* allow interval timer in */
2245*30391Skarels 
2246*30391Skarels 	eqh = eq_header[qd];		/* optimized as a register */
2247*30391Skarels 	new_rep = &current_rep[qd];
2248*30391Skarels 	duart = (struct duart *) qdmap[qd].duart;
2249*30391Skarels 
2250*30391Skarels /*-----------------------------------------
2251*30391Skarels * if the graphic device is turned on..	*/
2252*30391Skarels 
2253*30391Skarels 	if (qdflags[qd].inuse & GRAPHIC_DEV) {
2254*30391Skarels 
2255*30391Skarels 	    /*---------------
2256*30391Skarels 	    * empty DUART */
2257*30391Skarels 
2258*30391Skarels 	    while ((status = duart->statusA) & RCV_RDY	||
2259*30391Skarels 		   (status = duart->statusB) & RCV_RDY) {
2260*30391Skarels 
2261*30391Skarels 		/*---------------------------------
2262*30391Skarels 		* pick up LK-201 input (if any) */
2263*30391Skarels 
2264*30391Skarels 		if ((status = duart->statusA) & RCV_RDY) {
2265*30391Skarels 
2266*30391Skarels 		    /* if error condition, then reset it */
2267*30391Skarels 
2268*30391Skarels 		    if ((status = duart->statusA) & 0x70) {
2269*30391Skarels 			duart->cmdA = 0x40;
2270*30391Skarels 			continue;
2271*30391Skarels 		    }
2272*30391Skarels 
2273*30391Skarels 		    /* event queue full now? (overflow condition) */
2274*30391Skarels 
2275*30391Skarels 		    if (ISFULL(eqh) == TRUE) {
2276*30391Skarels 			mprintf("\nqd%d: qdiint: event queue overflow", qd);
2277*30391Skarels 			break;
2278*30391Skarels 		    }
2279*30391Skarels 
2280*30391Skarels 		    /*--------------------------------------
2281*30391Skarels 		    * Check for various keyboard errors  */
2282*30391Skarels 
2283*30391Skarels 		    key = duart->dataA & 0xFF;
2284*30391Skarels 
2285*30391Skarels 		    if( key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
2286*30391Skarels 			key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
2287*30391Skarels 			mprintf("\nqd%d: qdiint: keyboard error, code = %x",qd,key);
2288*30391Skarels 			return(0);
2289*30391Skarels 		    }
2290*30391Skarels 
2291*30391Skarels 		    if (key < LK_LOWEST)
2292*30391Skarels 			return(0);
2293*30391Skarels 
2294*30391Skarels 		    ++do_wakeup;	/* request a select wakeup call */
2295*30391Skarels 
2296*30391Skarels 		    event = PUTBEGIN(eqh);
2297*30391Skarels 		    PUTEND(eqh);
2298*30391Skarels 
2299*30391Skarels 		    event->vse_key = key;
2300*30391Skarels 		    event->vse_key &= 0x00FF;
2301*30391Skarels 		    event->vse_x = eqh->curs_pos.x;
2302*30391Skarels 		    event->vse_y = eqh->curs_pos.y;
2303*30391Skarels 		    event->vse_time = TOY;
2304*30391Skarels 		    event->vse_type = VSE_BUTTON;
2305*30391Skarels 		    event->vse_direction = VSE_KBTRAW;
2306*30391Skarels 		    event->vse_device = VSE_DKB;
2307*30391Skarels 		}
2308*30391Skarels 
2309*30391Skarels 		/*-------------------------------------
2310*30391Skarels 		* pick up the mouse input (if any)  */
2311*30391Skarels 
2312*30391Skarels 		if ((status = duart->statusB) & RCV_RDY  &&
2313*30391Skarels 		     qdflags[qd].pntr_id == MOUSE_ID) {
2314*30391Skarels 
2315*30391Skarels 		    if (status & 0x70) {
2316*30391Skarels 			duart->cmdB = 0x40;
2317*30391Skarels 			continue;
2318*30391Skarels 		    }
2319*30391Skarels 
2320*30391Skarels 		    /* event queue full now? (overflow condition) */
2321*30391Skarels 
2322*30391Skarels 		    if (ISFULL(eqh) == TRUE) {
2323*30391Skarels 			mprintf("\nqd%d: qdiint: event queue overflow", qd);
2324*30391Skarels 			break;
2325*30391Skarels 		    }
2326*30391Skarels 
2327*30391Skarels 		    data = duart->dataB;      /* get report byte */
2328*30391Skarels 		    ++new_rep->bytcnt;	      /* bump report byte count */
2329*30391Skarels 
2330*30391Skarels 		    /*---------------------------
2331*30391Skarels 		    * if 1st byte of report.. */
2332*30391Skarels 
2333*30391Skarels 		    if ( data & START_FRAME) {
2334*30391Skarels 			new_rep->state = data;
2335*30391Skarels 			if (new_rep->bytcnt > 1) {
2336*30391Skarels 			    new_rep->bytcnt = 1;    /* start of new frame */
2337*30391Skarels 			    continue;		    /* ..continue looking */
2338*30391Skarels 			}
2339*30391Skarels 		    }
2340*30391Skarels 
2341*30391Skarels 		    /*---------------------------
2342*30391Skarels 		    * if 2nd byte of report.. */
2343*30391Skarels 
2344*30391Skarels 		    else if (new_rep->bytcnt == 2) {
2345*30391Skarels 			new_rep->dx = data & 0x00FF;
2346*30391Skarels 		    }
2347*30391Skarels 
2348*30391Skarels 		    /*-------------------------------------------------
2349*30391Skarels 		    * if 3rd byte of report, load input event queue */
2350*30391Skarels 
2351*30391Skarels 		    else if (new_rep->bytcnt == 3) {
2352*30391Skarels 
2353*30391Skarels 			new_rep->dy = data & 0x00FF;
2354*30391Skarels 			new_rep->bytcnt = 0;
2355*30391Skarels 
2356*30391Skarels 			/*-----------------------------------
2357*30391Skarels 			* if mouse position has changed.. */
2358*30391Skarels 
2359*30391Skarels 			if (new_rep->dx != 0  ||  new_rep->dy != 0) {
2360*30391Skarels 
2361*30391Skarels 			    /*---------------------------------------------
2362*30391Skarels 			    * calculate acceleration factor, if needed	*/
2363*30391Skarels 
2364*30391Skarels 			    if (qdflags[qd].curs_acc > ACC_OFF) {
2365*30391Skarels 
2366*30391Skarels 				if (qdflags[qd].curs_thr <= new_rep->dx)
2367*30391Skarels 				    new_rep->dx +=
2368*30391Skarels 					(new_rep->dx - qdflags[qd].curs_thr)
2369*30391Skarels 					 * qdflags[qd].curs_acc;
2370*30391Skarels 
2371*30391Skarels 				if (qdflags[qd].curs_thr <= new_rep->dy)
2372*30391Skarels 				    new_rep->dy +=
2373*30391Skarels 					(new_rep->dy - qdflags[qd].curs_thr)
2374*30391Skarels 					 * qdflags[qd].curs_acc;
2375*30391Skarels 			    }
2376*30391Skarels 
2377*30391Skarels 			    /*-------------------------------------
2378*30391Skarels 			    * update cursor position coordinates */
2379*30391Skarels 
2380*30391Skarels 			    if (new_rep->state & X_SIGN) {
2381*30391Skarels 				eqh->curs_pos.x += new_rep->dx;
2382*30391Skarels 				if (eqh->curs_pos.x > 1023)
2383*30391Skarels 				    eqh->curs_pos.x = 1023;
2384*30391Skarels 			    }
2385*30391Skarels 			    else {
2386*30391Skarels 				eqh->curs_pos.x -= new_rep->dx;
2387*30391Skarels 				if (eqh->curs_pos.x < -15)
2388*30391Skarels 				    eqh->curs_pos.x = -15;
2389*30391Skarels 			    }
2390*30391Skarels 
2391*30391Skarels 			    if (new_rep->state & Y_SIGN) {
2392*30391Skarels 				 eqh->curs_pos.y -= new_rep->dy;
2393*30391Skarels 				 if (eqh->curs_pos.y < -15)
2394*30391Skarels 				     eqh->curs_pos.y = -15;
2395*30391Skarels 			    }
2396*30391Skarels 			    else {
2397*30391Skarels 				eqh->curs_pos.y += new_rep->dy;
2398*30391Skarels 				if (eqh->curs_pos.y > 863)
2399*30391Skarels 				    eqh->curs_pos.y = 863;
2400*30391Skarels 			    }
2401*30391Skarels 
2402*30391Skarels 			    /*---------------------------------
2403*30391Skarels 			    * update cursor screen position */
2404*30391Skarels 
2405*30391Skarels 			    dga = (struct dga *) qdmap[qd].dga;
2406*30391Skarels 			    dga->x_cursor = TRANX(eqh->curs_pos.x);
2407*30391Skarels 			    dga->y_cursor = TRANY(eqh->curs_pos.y);
2408*30391Skarels 
2409*30391Skarels 			    /*--------------------------------------------
2410*30391Skarels 			    * if cursor is in the box, no event report */
2411*30391Skarels 
2412*30391Skarels 			    if (eqh->curs_pos.x <= eqh->curs_box.right	&&
2413*30391Skarels 				eqh->curs_pos.x >= eqh->curs_box.left  &&
2414*30391Skarels 				eqh->curs_pos.y >= eqh->curs_box.top  &&
2415*30391Skarels 				eqh->curs_pos.y <= eqh->curs_box.bottom ) {
2416*30391Skarels 				    goto GET_MBUTTON;
2417*30391Skarels 			    }
2418*30391Skarels 
2419*30391Skarels 			    /*---------------------------------
2420*30391Skarels 			    * report the mouse motion event */
2421*30391Skarels 
2422*30391Skarels 			    event = PUTBEGIN(eqh);
2423*30391Skarels 			    PUTEND(eqh);
2424*30391Skarels 
2425*30391Skarels 			    ++do_wakeup;   /* request a select wakeup call */
2426*30391Skarels 
2427*30391Skarels 			    event->vse_x = eqh->curs_pos.x;
2428*30391Skarels 			    event->vse_y = eqh->curs_pos.y;
2429*30391Skarels 
2430*30391Skarels 			    event->vse_device = VSE_MOUSE;  /* mouse */
2431*30391Skarels 			    event->vse_type = VSE_MMOTION;  /* pos changed */
2432*30391Skarels 			    event->vse_key = 0;
2433*30391Skarels 			    event->vse_direction = 0;
2434*30391Skarels 			    event->vse_time = TOY;	/* time stamp */
2435*30391Skarels 			}
2436*30391Skarels 
2437*30391Skarels GET_MBUTTON:
2438*30391Skarels 			/*-------------------------------
2439*30391Skarels 			* if button state has changed */
2440*30391Skarels 
2441*30391Skarels 			a = new_rep->state & 0x07;    /*mask nonbutton bits */
2442*30391Skarels 			b = last_rep[qd].state & 0x07;
2443*30391Skarels 
2444*30391Skarels 			if (a ^ b) {
2445*30391Skarels 
2446*30391Skarels 			    for ( c = 1;  c < 8; c <<= 1) {
2447*30391Skarels 
2448*30391Skarels 				if (!( c & (a ^ b))) /* this button change? */
2449*30391Skarels 				    continue;
2450*30391Skarels 
2451*30391Skarels 				/* event queue full? (overflow condition) */
2452*30391Skarels 
2453*30391Skarels 				if (ISFULL(eqh) == TRUE) {
2454*30391Skarels 				    mprintf("\nqd%d: qdiint: event queue overflow", qd);
2455*30391Skarels 				    break;
2456*30391Skarels 				}
2457*30391Skarels 
2458*30391Skarels 				event = PUTBEGIN(eqh);	/* get new event */
2459*30391Skarels 				PUTEND(eqh);
2460*30391Skarels 
2461*30391Skarels 				++do_wakeup;   /* request select wakeup */
2462*30391Skarels 
2463*30391Skarels 				event->vse_x = eqh->curs_pos.x;
2464*30391Skarels 				event->vse_y = eqh->curs_pos.y;
2465*30391Skarels 
2466*30391Skarels 				event->vse_device = VSE_MOUSE;	/* mouse */
2467*30391Skarels 				event->vse_type = VSE_BUTTON; /* new button */
2468*30391Skarels 				event->vse_time = TOY;	      /* time stamp */
2469*30391Skarels 
2470*30391Skarels 				/* flag changed button and if up or down */
2471*30391Skarels 
2472*30391Skarels 				if (c == RIGHT_BUTTON)
2473*30391Skarels 				    event->vse_key = VSE_RIGHT_BUTTON;
2474*30391Skarels 				else if (c == MIDDLE_BUTTON)
2475*30391Skarels 				    event->vse_key = VSE_MIDDLE_BUTTON;
2476*30391Skarels 				else if (c == LEFT_BUTTON)
2477*30391Skarels 				    event->vse_key = VSE_LEFT_BUTTON;
2478*30391Skarels 
2479*30391Skarels 				/* set bit = button depressed */
2480*30391Skarels 
2481*30391Skarels 				if (c & a)
2482*30391Skarels 				    event->vse_direction = VSE_KBTDOWN;
2483*30391Skarels 				else
2484*30391Skarels 				    event->vse_direction = VSE_KBTUP;
2485*30391Skarels 			    }
2486*30391Skarels 			}
2487*30391Skarels 
2488*30391Skarels 			/* refresh last report */
2489*30391Skarels 
2490*30391Skarels 			last_rep[qd] = current_rep[qd];
2491*30391Skarels 
2492*30391Skarels 		    }  /* get last byte of report */
2493*30391Skarels 		} /* pickup mouse input */
2494*30391Skarels 
2495*30391Skarels 		/*--------------------------------
2496*30391Skarels 		* pickup tablet input, if any  */
2497*30391Skarels 
2498*30391Skarels 		else if ((status = duart->statusB) & RCV_RDY  &&
2499*30391Skarels 			 qdflags[qd].pntr_id == TABLET_ID) {
2500*30391Skarels 
2501*30391Skarels 		    if (status & 0x70) {
2502*30391Skarels 			duart->cmdB = 0x40;
2503*30391Skarels 			continue;
2504*30391Skarels 		    }
2505*30391Skarels 
2506*30391Skarels 		    /* event queue full now? (overflow condition) */
2507*30391Skarels 
2508*30391Skarels 		    if (ISFULL(eqh) == TRUE) {
2509*30391Skarels 			mprintf("\nqd%d: qdiint: event queue overflow", qd);
2510*30391Skarels 			break;
2511*30391Skarels 		    }
2512*30391Skarels 
2513*30391Skarels 		    data = duart->dataB;      /* get report byte */
2514*30391Skarels 		    ++new_rep->bytcnt;	      /* bump report byte count */
2515*30391Skarels 
2516*30391Skarels 		    /*---------------------------
2517*30391Skarels 		    * if 1st byte of report.. */
2518*30391Skarels 
2519*30391Skarels 		    if (data & START_FRAME) {
2520*30391Skarels 			new_rep->state = data;
2521*30391Skarels 			if (new_rep->bytcnt > 1) {
2522*30391Skarels 			    new_rep->bytcnt = 1;    /* start of new frame */
2523*30391Skarels 			    continue;		    /* ..continue looking */
2524*30391Skarels 			}
2525*30391Skarels 		    }
2526*30391Skarels 
2527*30391Skarels 		    /*---------------------------
2528*30391Skarels 		    * if 2nd byte of report.. */
2529*30391Skarels 
2530*30391Skarels 		    else if (new_rep->bytcnt == 2) {
2531*30391Skarels 			new_rep->dx = data & 0x3F;
2532*30391Skarels 		    }
2533*30391Skarels 
2534*30391Skarels 		    /*---------------------------
2535*30391Skarels 		    * if 3rd byte of report.. */
2536*30391Skarels 
2537*30391Skarels 		    else if (new_rep->bytcnt == 3) {
2538*30391Skarels 			new_rep->dx |= (data & 0x3F) << 6;
2539*30391Skarels 		    }
2540*30391Skarels 
2541*30391Skarels 		    /*---------------------------
2542*30391Skarels 		    * if 4th byte of report.. */
2543*30391Skarels 
2544*30391Skarels 		    else if (new_rep->bytcnt == 4) {
2545*30391Skarels 			new_rep->dy = data & 0x3F;
2546*30391Skarels 		    }
2547*30391Skarels 
2548*30391Skarels 		    /*-------------------------------------------------
2549*30391Skarels 		    * if 5th byte of report, load input event queue */
2550*30391Skarels 
2551*30391Skarels 		    else if (new_rep->bytcnt == 5) {
2552*30391Skarels 
2553*30391Skarels 			new_rep->dy |= (data & 0x3F) << 6;
2554*30391Skarels 			new_rep->bytcnt = 0;
2555*30391Skarels 
2556*30391Skarels 			/*-------------------------------------
2557*30391Skarels 			* update cursor position coordinates */
2558*30391Skarels 
2559*30391Skarels 			new_rep->dx /= qdflags[qd].tab_res;
2560*30391Skarels 			new_rep->dy = (2200 - new_rep->dy)
2561*30391Skarels 				      / qdflags[qd].tab_res;
2562*30391Skarels 
2563*30391Skarels 			if (new_rep->dx > 1023) {
2564*30391Skarels 			    new_rep->dx = 1023;
2565*30391Skarels 			}
2566*30391Skarels 			if (new_rep->dy > 863) {
2567*30391Skarels 			    new_rep->dy = 863;
2568*30391Skarels 			}
2569*30391Skarels 
2570*30391Skarels 			/*
2571*30391Skarels 			 * report an event if the puck/stylus has moved
2572*30391Skarels 			 */
2573*30391Skarels 
2574*30391Skarels 			if (eqh->curs_pos.x != new_rep->dx ||
2575*30391Skarels 			    eqh->curs_pos.y != new_rep->dy) {
2576*30391Skarels 
2577*30391Skarels 			    eqh->curs_pos.x = new_rep->dx;
2578*30391Skarels 			    eqh->curs_pos.y = new_rep->dy;
2579*30391Skarels 
2580*30391Skarels 			    /*---------------------------------
2581*30391Skarels 			    * update cursor screen position */
2582*30391Skarels 
2583*30391Skarels 			    dga = (struct dga *) qdmap[qd].dga;
2584*30391Skarels 			    dga->x_cursor = TRANX(eqh->curs_pos.x);
2585*30391Skarels 			    dga->y_cursor = TRANY(eqh->curs_pos.y);
2586*30391Skarels 
2587*30391Skarels 			    /*
2588*30391Skarels 			     * if cursor is in the box, no event report
2589*30391Skarels 			     */
2590*30391Skarels 
2591*30391Skarels 			    if (eqh->curs_pos.x <= eqh->curs_box.right	&&
2592*30391Skarels 				eqh->curs_pos.x >= eqh->curs_box.left  &&
2593*30391Skarels 				eqh->curs_pos.y >= eqh->curs_box.top  &&
2594*30391Skarels 				eqh->curs_pos.y <= eqh->curs_box.bottom ) {
2595*30391Skarels 				goto GET_TBUTTON;
2596*30391Skarels 			    }
2597*30391Skarels 
2598*30391Skarels 			    /*---------------------------------
2599*30391Skarels 			    * report the tablet motion event */
2600*30391Skarels 
2601*30391Skarels 			    event = PUTBEGIN(eqh);
2602*30391Skarels 			    PUTEND(eqh);
2603*30391Skarels 
2604*30391Skarels 			    ++do_wakeup;   /* request a select wakeup call */
2605*30391Skarels 
2606*30391Skarels 			    event->vse_x = eqh->curs_pos.x;
2607*30391Skarels 			    event->vse_y = eqh->curs_pos.y;
2608*30391Skarels 
2609*30391Skarels 			    event->vse_device = VSE_TABLET;  /* tablet */
2610*30391Skarels 			    /*
2611*30391Skarels 			     * right now, X handles tablet motion the same
2612*30391Skarels 			     * as mouse motion
2613*30391Skarels 			     */
2614*30391Skarels 			    event->vse_type = VSE_MMOTION;   /* pos changed */
2615*30391Skarels 			    event->vse_key = 0;
2616*30391Skarels 			    event->vse_direction = 0;
2617*30391Skarels 			    event->vse_time = TOY;	/* time stamp */
2618*30391Skarels 			}
2619*30391Skarels GET_TBUTTON:
2620*30391Skarels 			/*-------------------------------
2621*30391Skarels 			* if button state has changed */
2622*30391Skarels 
2623*30391Skarels 			a = new_rep->state & 0x1E;   /* mask nonbutton bits */
2624*30391Skarels 			b = last_rep[qd].state & 0x1E;
2625*30391Skarels 
2626*30391Skarels 			if (a ^ b) {
2627*30391Skarels 
2628*30391Skarels 			    /* event queue full now? (overflow condition) */
2629*30391Skarels 
2630*30391Skarels 			    if (ISFULL(eqh) == TRUE) {
2631*30391Skarels 				mprintf("\nqd%d: qdiint: event queue overflow",qd);
2632*30391Skarels 				break;
2633*30391Skarels 			    }
2634*30391Skarels 
2635*30391Skarels 			    event = PUTBEGIN(eqh);  /* get new event */
2636*30391Skarels 			    PUTEND(eqh);
2637*30391Skarels 
2638*30391Skarels 			    ++do_wakeup;   /* request a select wakeup call */
2639*30391Skarels 
2640*30391Skarels 			    event->vse_x = eqh->curs_pos.x;
2641*30391Skarels 			    event->vse_y = eqh->curs_pos.y;
2642*30391Skarels 
2643*30391Skarels 			    event->vse_device = VSE_TABLET;  /* tablet */
2644*30391Skarels 			    event->vse_type = VSE_BUTTON; /* button changed */
2645*30391Skarels 			    event->vse_time = TOY;	   /* time stamp */
2646*30391Skarels 
2647*30391Skarels 			    /* define the changed button and if up or down */
2648*30391Skarels 
2649*30391Skarels 			    for ( c = 1;  c <= 0x10; c <<= 1) {
2650*30391Skarels 				if (c & (a ^ b)) {
2651*30391Skarels 				    if (c == T_LEFT_BUTTON)
2652*30391Skarels 					event->vse_key = VSE_T_LEFT_BUTTON;
2653*30391Skarels 				    else if (c == T_FRONT_BUTTON)
2654*30391Skarels 					event->vse_key = VSE_T_FRONT_BUTTON;
2655*30391Skarels 				    else if (c == T_RIGHT_BUTTON)
2656*30391Skarels 					event->vse_key = VSE_T_RIGHT_BUTTON;
2657*30391Skarels 				    else if (c == T_BACK_BUTTON)
2658*30391Skarels 					event->vse_key = VSE_T_BACK_BUTTON;
2659*30391Skarels 				    break;
2660*30391Skarels 				}
2661*30391Skarels 			    }
2662*30391Skarels 
2663*30391Skarels 			    /* set bit = button depressed */
2664*30391Skarels 
2665*30391Skarels 			    if (c & a)
2666*30391Skarels 				event->vse_direction = VSE_KBTDOWN;
2667*30391Skarels 			    else
2668*30391Skarels 				event->vse_direction = VSE_KBTUP;
2669*30391Skarels 			}
2670*30391Skarels 
2671*30391Skarels 			/* refresh last report */
2672*30391Skarels 
2673*30391Skarels 			last_rep[qd] = current_rep[qd];
2674*30391Skarels 
2675*30391Skarels 		    } /* get last byte of report */
2676*30391Skarels 		} /* pick up tablet input */
2677*30391Skarels 
2678*30391Skarels 	    } /* while input available.. */
2679*30391Skarels 
2680*30391Skarels 	    /*---------------------
2681*30391Skarels 	    * do select wakeup	*/
2682*30391Skarels 
2683*30391Skarels 	    if (rsel[qd] && do_wakeup && qdflags[qd].selmask & SEL_READ) {
2684*30391Skarels 		selwakeup(rsel[qd], 0);
2685*30391Skarels 		rsel[qd] = 0;
2686*30391Skarels 		qdflags[qd].selmask &= ~SEL_READ;
2687*30391Skarels 		do_wakeup = 0;
2688*30391Skarels 	    }
2689*30391Skarels 	}
2690*30391Skarels 
2691*30391Skarels /*-----------------------------------------------------------------
2692*30391Skarels * if the graphic device is not turned on, this is console input */
2693*30391Skarels 
2694*30391Skarels 	else {
2695*30391Skarels 
2696*30391Skarels 	    ui = qdinfo[qd];
2697*30391Skarels 	    if (ui == 0 || ui->ui_alive == 0)
2698*30391Skarels 		return(0);
2699*30391Skarels 
2700*30391Skarels 	    tp = &qd_tty[qd << 2];
2701*30391Skarels 
2702*30391Skarels 	    /*--------------------------------------
2703*30391Skarels 	    * Get a character from the keyboard. */
2704*30391Skarels 
2705*30391Skarels 	    while ((status = duart->statusA) & RCV_RDY) {
2706*30391Skarels 
2707*30391Skarels 		key = duart->dataA;
2708*30391Skarels 		key &= 0xFF;
2709*30391Skarels 
2710*30391Skarels 		/*--------------------------------------
2711*30391Skarels 		* Check for various keyboard errors  */
2712*30391Skarels 
2713*30391Skarels 		if( key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
2714*30391Skarels 		    key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
2715*30391Skarels 			mprintf("\nqd%d: qdiint: Keyboard error, code = %x",qd,key);
2716*30391Skarels 			return(0);
2717*30391Skarels 		}
2718*30391Skarels 
2719*30391Skarels 		if (key < LK_LOWEST)
2720*30391Skarels 		    return(0);
2721*30391Skarels 
2722*30391Skarels 		/*---------------------------------
2723*30391Skarels 		* See if its a state change key */
2724*30391Skarels 
2725*30391Skarels 		switch (key) {
2726*30391Skarels 
2727*30391Skarels 		    case LOCK:
2728*30391Skarels 			q_keyboard.lock ^= 0xffff;	/* toggle */
2729*30391Skarels 			if (q_keyboard.lock)
2730*30391Skarels 			    led_control(qd, LK_LED_ENABLE, LK_LED_LOCK);
2731*30391Skarels 			else
2732*30391Skarels 			    led_control(qd, LK_LED_DISABLE, LK_LED_LOCK);
2733*30391Skarels 			return;
2734*30391Skarels 
2735*30391Skarels 		    case SHIFT:
2736*30391Skarels 			q_keyboard.shift ^= 0xFFFF;
2737*30391Skarels 			return;
2738*30391Skarels 
2739*30391Skarels 		    case CNTRL:
2740*30391Skarels 			q_keyboard.cntrl ^= 0xFFFF;
2741*30391Skarels 			return;
2742*30391Skarels 
2743*30391Skarels 		    case ALLUP:
2744*30391Skarels 			q_keyboard.cntrl = 0;
2745*30391Skarels 			q_keyboard.shift = 0;
2746*30391Skarels 			return;
2747*30391Skarels 
2748*30391Skarels 		    case REPEAT:
2749*30391Skarels 			chr = q_keyboard.last;
2750*30391Skarels 			break;
2751*30391Skarels 
2752*30391Skarels 		    /*-------------------------------------------------------
2753*30391Skarels 		    * Test for cntrl characters. If set, see if the character
2754*30391Skarels 		    * is elligible to become a control character. */
2755*30391Skarels 
2756*30391Skarels 		    default:
2757*30391Skarels 
2758*30391Skarels 			if (q_keyboard.cntrl) {
2759*30391Skarels 				chr = q_key[key];
2760*30391Skarels 				if (chr >= ' ' && chr <= '~')
2761*30391Skarels 				    chr &= 0x1F;
2762*30391Skarels 			}
2763*30391Skarels 			else if( q_keyboard.lock || q_keyboard.shift )
2764*30391Skarels 			    chr = q_shift_key[key];
2765*30391Skarels 			else
2766*30391Skarels 			    chr = q_key[key];
2767*30391Skarels 			break;
2768*30391Skarels 		}
2769*30391Skarels 
2770*30391Skarels 		q_keyboard.last = chr;
2771*30391Skarels 
2772*30391Skarels 		/*-----------------------------------
2773*30391Skarels 		* Check for special function keys */
2774*30391Skarels 
2775*30391Skarels 		if (chr & 0x80) {
2776*30391Skarels 			char *string;
2777*30391Skarels 			string = q_special[chr & 0x7F];
2778*30391Skarels 			while(*string)
2779*30391Skarels 			    (*linesw[tp->t_line].l_rint)(*string++, tp);
2780*30391Skarels 		}
2781*30391Skarels 		else {
2782*30391Skarels 			(*linesw[tp->t_line].l_rint)(chr, tp);
2783*30391Skarels 		}
2784*30391Skarels 	    }
2785*30391Skarels 	}
2786*30391Skarels 
2787*30391Skarels /*----------------------
2788*30391Skarels * cleanup and exit  */
2789*30391Skarels 
2790*30391Skarels 	return(0);
2791*30391Skarels 
2792*30391Skarels } /* qdiint */
2793*30391Skarels 
2794*30391Skarels /******************************************************************
2795*30391Skarels *******************************************************************
2796*30391Skarels *******************************************************************
2797*30391Skarels *
2798*30391Skarels *	THE SUBROUTINES START HERE:
2799*30391Skarels *
2800*30391Skarels ******************************************************************/
2801*30391Skarels 
2802*30391Skarels /*****************************************************************
2803*30391Skarels *
2804*30391Skarels *	clear_qd_screen()... clear the QDSS screen
2805*30391Skarels *
2806*30391Skarels ******************************************************************
2807*30391Skarels *
2808*30391Skarels *			     >>> NOTE <<<
2809*30391Skarels *
2810*30391Skarels *   This code requires that certain adder initialization be valid.  To
2811*30391Skarels *   assure that this requirement is satisfied, this routine should be
2812*30391Skarels *   called only after calling the "setup_dragon()" function.
2813*30391Skarels *
2814*30391Skarels *   Clear the bitmap a piece at a time. Since the fast scroll clear
2815*30391Skarels *   only clears the current displayed portion of the bitmap put a
2816*30391Skarels *   temporary value in the y limit register so we can access whole
2817*30391Skarels *   bitmap
2818*30391Skarels *
2819*30391Skarels ****************/
2820*30391Skarels 
2821*30391Skarels clear_qd_screen(unit)
2822*30391Skarels int unit;
2823*30391Skarels {
2824*30391Skarels 	register struct adder *adder;
2825*30391Skarels 	adder = (struct adder *) qdmap[unit].adder;
2826*30391Skarels 
2827*30391Skarels 	adder->x_limit = 1024;
2828*30391Skarels 	adder->y_limit = 2048 - CHAR_HEIGHT;
2829*30391Skarels 	adder->y_offset_pending = 0;
2830*30391Skarels 
2831*30391Skarels 	wait_status(adder, VSYNC);	/* wait at LEAST 1 full frame */
2832*30391Skarels 	wait_status(adder, VSYNC);
2833*30391Skarels 
2834*30391Skarels 	adder->y_scroll_constant = SCROLL_ERASE;
2835*30391Skarels 
2836*30391Skarels 	wait_status(adder, VSYNC);
2837*30391Skarels 	wait_status(adder, VSYNC);
2838*30391Skarels 
2839*30391Skarels 	adder->y_offset_pending = 864;
2840*30391Skarels 
2841*30391Skarels 	wait_status(adder, VSYNC);
2842*30391Skarels 	wait_status(adder, VSYNC);
2843*30391Skarels 
2844*30391Skarels 	adder->y_scroll_constant = SCROLL_ERASE;
2845*30391Skarels 
2846*30391Skarels 	wait_status(adder, VSYNC);
2847*30391Skarels 	wait_status(adder, VSYNC);
2848*30391Skarels 
2849*30391Skarels 	adder->y_offset_pending = 1728;
2850*30391Skarels 
2851*30391Skarels 	wait_status(adder, VSYNC);
2852*30391Skarels 	wait_status(adder, VSYNC);
2853*30391Skarels 
2854*30391Skarels 	adder->y_scroll_constant = SCROLL_ERASE;
2855*30391Skarels 
2856*30391Skarels 	wait_status(adder, VSYNC);
2857*30391Skarels 	wait_status(adder, VSYNC);
2858*30391Skarels 
2859*30391Skarels 	adder->y_offset_pending = 0;	 /* back to normal */
2860*30391Skarels 
2861*30391Skarels 	wait_status(adder, VSYNC);
2862*30391Skarels 	wait_status(adder, VSYNC);
2863*30391Skarels 
2864*30391Skarels 	adder->x_limit = MAX_SCREEN_X;
2865*30391Skarels 	adder->y_limit = MAX_SCREEN_Y + FONT_HEIGHT;
2866*30391Skarels 
2867*30391Skarels } /* clear_qd_screen */
2868*30391Skarels 
2869*30391Skarels /**********************************************************************
2870*30391Skarels *
2871*30391Skarels *	qdputc()... route kernel console output to display destination
2872*30391Skarels *
2873*30391Skarels ***********************************************************************
2874*30391Skarels *
2875*30391Skarels *	calling convention:
2876*30391Skarels *
2877*30391Skarels *		qdputc(chr);
2878*30391Skarels *
2879*30391Skarels *	where:	char chr;	 ;character for output
2880*30391Skarels *
2881*30391Skarels ****************/
2882*30391Skarels 
2883*30391Skarels qdputc(chr)
2884*30391Skarels register char chr;
2885*30391Skarels {
2886*30391Skarels 	register struct tty *tp0;
2887*30391Skarels 
2888*30391Skarels /*---------------------------------------------------------
2889*30391Skarels * if system is now physical, forget it (ie: crash DUMP) */
2890*30391Skarels 
2891*30391Skarels 	if ( (mfpr(MAPEN) & 1) == 0 )
2892*30391Skarels 	    return;
2893*30391Skarels 
2894*30391Skarels /*--------------------------------------------------
2895*30391Skarels * direct kernel output char to the proper place  */
2896*30391Skarels 
2897*30391Skarels 	tp0 = &qd_tty[1];
2898*30391Skarels 
2899*30391Skarels 	if (qdflags[0].kernel_loop != 0  &&  tp0->t_state & TS_ISOPEN) {
2900*30391Skarels 	    (*linesw[tp0->t_line].l_rint)(chr, tp0);
2901*30391Skarels 	} else {
2902*30391Skarels 	    blitc(0, chr & 0xff);
2903*30391Skarels 	}
2904*30391Skarels 
2905*30391Skarels } /* qdputc */
2906*30391Skarels 
2907*30391Skarels /*******************************************************************
2908*30391Skarels *
2909*30391Skarels *	qdgetc()... get a character from the LK201
2910*30391Skarels *
2911*30391Skarels *******************************************************************
2912*30391Skarels *
2913*30391Skarels *	calling convention:
2914*30391Skarels *
2915*30391Skarels *		qdgetc();
2916*30391Skarels *
2917*30391Skarels *	returns:  the character read.
2918*30391Skarels *
2919*30391Skarels ****************/
2920*30391Skarels 
2921*30391Skarels qdgetc()
2922*30391Skarels {
2923*30391Skarels 	register short key;
2924*30391Skarels 	register char chr;
2925*30391Skarels 	register struct duart *duart;
2926*30391Skarels 
2927*30391Skarels 	u_int status;
2928*30391Skarels 
2929*30391Skarels 	duart = (struct duart *) qdmap[0].duart;
2930*30391Skarels 
2931*30391Skarels 	/*--------------------------------------
2932*30391Skarels 	* Get a character from the keyboard. */
2933*30391Skarels 
2934*30391Skarels LOOP:
2935*30391Skarels 	while (!((status = duart->statusA) & RCV_RDY))
2936*30391Skarels 			;
2937*30391Skarels 
2938*30391Skarels 	key = duart->dataA;
2939*30391Skarels 	key &= 0xFF;
2940*30391Skarels 
2941*30391Skarels 	/*--------------------------------------
2942*30391Skarels 	* Check for various keyboard errors  */
2943*30391Skarels 
2944*30391Skarels 	if( key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
2945*30391Skarels 	    key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
2946*30391Skarels 		printf("Keyboard error, code = %x\n", key);
2947*30391Skarels 		return(0);
2948*30391Skarels 	}
2949*30391Skarels 
2950*30391Skarels 	if (key < LK_LOWEST)
2951*30391Skarels 	    return(0);
2952*30391Skarels 
2953*30391Skarels 	/*---------------------------------
2954*30391Skarels 	* See if its a state change key */
2955*30391Skarels 
2956*30391Skarels 	switch (key) {
2957*30391Skarels 
2958*30391Skarels 	    case LOCK:
2959*30391Skarels 		q_keyboard.lock ^= 0xffff;	/* toggle */
2960*30391Skarels 		if (q_keyboard.lock)
2961*30391Skarels 		    led_control(LK_LED_ENABLE, LK_LED_LOCK);
2962*30391Skarels 		else
2963*30391Skarels 		    led_control(LK_LED_DISABLE, LK_LED_LOCK);
2964*30391Skarels 		goto LOOP;
2965*30391Skarels 
2966*30391Skarels 	    case SHIFT:
2967*30391Skarels 		q_keyboard.shift ^= 0xFFFF;
2968*30391Skarels 		goto LOOP;
2969*30391Skarels 
2970*30391Skarels 	    case CNTRL:
2971*30391Skarels 		q_keyboard.cntrl ^= 0xFFFF;
2972*30391Skarels 		goto LOOP;
2973*30391Skarels 
2974*30391Skarels 	    case ALLUP:
2975*30391Skarels 		q_keyboard.cntrl = 0;
2976*30391Skarels 		q_keyboard.shift = 0;
2977*30391Skarels 		goto LOOP;
2978*30391Skarels 
2979*30391Skarels 	    case REPEAT:
2980*30391Skarels 		chr = q_keyboard.last;
2981*30391Skarels 		break;
2982*30391Skarels 
2983*30391Skarels 	    /*-------------------------------------------------------
2984*30391Skarels 	    * Test for cntrl characters. If set, see if the character
2985*30391Skarels 	    * is elligible to become a control character. */
2986*30391Skarels 
2987*30391Skarels 	    default:
2988*30391Skarels 
2989*30391Skarels 		if (q_keyboard.cntrl) {
2990*30391Skarels 		    chr = q_key[key];
2991*30391Skarels 		    if (chr >= ' ' && chr <= '~')
2992*30391Skarels 			chr &= 0x1F;
2993*30391Skarels 		}
2994*30391Skarels 		else if ( q_keyboard.lock || q_keyboard.shift )
2995*30391Skarels 		    chr = q_shift_key[key];
2996*30391Skarels 		else
2997*30391Skarels 		    chr = q_key[key];
2998*30391Skarels 		break;
2999*30391Skarels 	}
3000*30391Skarels 
3001*30391Skarels 	if (chr < ' ' && chr > '~')	/* if input is non-displayable */
3002*30391Skarels 	    return(0);			/* ..then pitch it! */
3003*30391Skarels 
3004*30391Skarels 	q_keyboard.last = chr;
3005*30391Skarels 
3006*30391Skarels 	/*-----------------------------------
3007*30391Skarels 	* Check for special function keys */
3008*30391Skarels 
3009*30391Skarels 	if (chr & 0x80) 		/* pitch the function keys */
3010*30391Skarels 	    return(0);
3011*30391Skarels 	else
3012*30391Skarels 	    return(chr);
3013*30391Skarels 
3014*30391Skarels } /* qdgetc */
3015*30391Skarels 
3016*30391Skarels /**********************************************************************
3017*30391Skarels *
3018*30391Skarels *	ldcursor()... load the mouse cursor's template RAM bitmap
3019*30391Skarels *
3020*30391Skarels *********************************************************************
3021*30391Skarels *
3022*30391Skarels *	calling convention:
3023*30391Skarels *
3024*30391Skarels *		ldcursor(unit, bitmap);
3025*30391Skarels *		u_int unit;
3026*30391Skarels *		short *bitmap;
3027*30391Skarels *
3028*30391Skarels ****************/
3029*30391Skarels 
3030*30391Skarels ldcursor(unit, bitmap)
3031*30391Skarels u_int unit;
3032*30391Skarels short *bitmap;
3033*30391Skarels {
3034*30391Skarels 	register struct dga *dga;
3035*30391Skarels 	register short *temp;
3036*30391Skarels 	register int i;
3037*30391Skarels 
3038*30391Skarels 	int cursor;
3039*30391Skarels 
3040*30391Skarels 	dga = (struct dga *) qdmap[unit].dga;
3041*30391Skarels 	temp = (short *) qdmap[unit].template;
3042*30391Skarels 
3043*30391Skarels 	if (dga->csr & CURS_ENB) {	/* if the cursor is enabled.. */
3044*30391Skarels 	    cursor = -1;		/* ..note that.. */
3045*30391Skarels 	    dga->csr &= ~CURS_ENB;	/* ..and shut it off */
3046*30391Skarels 	}
3047*30391Skarels 	else {
3048*30391Skarels 	    cursor = 0;
3049*30391Skarels 	}
3050*30391Skarels 
3051*30391Skarels 	dga->csr &= ~CURS_ENB;		/* shut off the cursor */
3052*30391Skarels 
3053*30391Skarels 	temp += (8 * 1024) - 32;	/* cursor is 32 WORDS from the end */
3054*30391Skarels 					/* ..of the 8k WORD template space */
3055*30391Skarels 	for (i = 0; i < 32; ++i)
3056*30391Skarels 	    *temp++ = *bitmap++;
3057*30391Skarels 
3058*30391Skarels 	if (cursor) {			/* if cursor was enabled.. */
3059*30391Skarels 	    dga->csr |= CURS_ENB;	/* ..turn it back on */
3060*30391Skarels 	}
3061*30391Skarels 
3062*30391Skarels 	return(0);
3063*30391Skarels 
3064*30391Skarels } /* ldcursor */
3065*30391Skarels 
3066*30391Skarels /**********************************************************************
3067*30391Skarels *
3068*30391Skarels *	ldfont()... put the console font in the QDSS off-screen memory
3069*30391Skarels *
3070*30391Skarels ***********************************************************************
3071*30391Skarels *
3072*30391Skarels *	calling convention:
3073*30391Skarels *
3074*30391Skarels *		ldfont(unit);
3075*30391Skarels *		u_int unit;	;QDSS unit number
3076*30391Skarels *
3077*30391Skarels ****************/
3078*30391Skarels 
3079*30391Skarels ldfont(unit)
3080*30391Skarels u_int unit;
3081*30391Skarels {
3082*30391Skarels 	register struct adder *adder;
3083*30391Skarels 
3084*30391Skarels 	int i;		/* scratch variables */
3085*30391Skarels 	int j;
3086*30391Skarels 	int k;
3087*30391Skarels 	short packed;
3088*30391Skarels 
3089*30391Skarels 	adder = (struct adder *) qdmap[unit].adder;
3090*30391Skarels 
3091*30391Skarels /*------------------------------------------
3092*30391Skarels * setup VIPER operand control registers  */
3093*30391Skarels 
3094*30391Skarels 	write_ID(adder, MASK_1, 0xFFFF);
3095*30391Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
3096*30391Skarels 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
3097*30391Skarels 
3098*30391Skarels 	write_ID(adder, SRC1_OCR_B,
3099*30391Skarels 			EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY);
3100*30391Skarels 	write_ID(adder, SRC2_OCR_B,
3101*30391Skarels 			EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY);
3102*30391Skarels 	write_ID(adder, DST_OCR_B,
3103*30391Skarels 			EXT_SOURCE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
3104*30391Skarels 
3105*30391Skarels 	adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL;
3106*30391Skarels 
3107*30391Skarels /*--------------------------
3108*30391Skarels * load destination data  */
3109*30391Skarels 
3110*30391Skarels 	wait_status(adder, RASTEROP_COMPLETE);
3111*30391Skarels 
3112*30391Skarels 	adder->destination_x = FONT_X;
3113*30391Skarels 	adder->destination_y = FONT_Y;
3114*30391Skarels 	adder->fast_dest_dx = FONT_WIDTH;
3115*30391Skarels 	adder->slow_dest_dy = CHAR_HEIGHT;
3116*30391Skarels 
3117*30391Skarels /*---------------------------------------
3118*30391Skarels * setup for processor to bitmap xfer  */
3119*30391Skarels 
3120*30391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0001);
3121*30391Skarels 	adder->cmd = PBT | OCRB | 2 | DTE | 2;
3122*30391Skarels 
3123*30391Skarels /*-----------------------------------------------
3124*30391Skarels * iteratively do the processor to bitmap xfer */
3125*30391Skarels 
3126*30391Skarels 	for (i = 0; i < ROWS; ++i) {
3127*30391Skarels 
3128*30391Skarels 	    /* PTOB a scan line */
3129*30391Skarels 
3130*30391Skarels 	    for (j = 0, k = i; j < 48; ++j) {
3131*30391Skarels 
3132*30391Skarels 		/* PTOB one scan of a char cell */
3133*30391Skarels 
3134*30391Skarels 		packed = q_font[k];
3135*30391Skarels 		k += ROWS;
3136*30391Skarels 		packed |= ((short)q_font[k] << 8);
3137*30391Skarels 		k += ROWS;
3138*30391Skarels 
3139*30391Skarels 		wait_status(adder, TX_READY);
3140*30391Skarels 		adder->id_data = packed;
3141*30391Skarels 	    }
3142*30391Skarels 	}
3143*30391Skarels 
3144*30391Skarels }  /* ldfont */
3145*30391Skarels 
3146*30391Skarels /*********************************************************************
3147*30391Skarels *
3148*30391Skarels *	led_control()... twiddle LK-201 LED's
3149*30391Skarels *
3150*30391Skarels **********************************************************************
3151*30391Skarels *
3152*30391Skarels *	led_control(unit, cmd, led_mask);
3153*30391Skarels *	u_int unit;	QDSS number
3154*30391Skarels *	int cmd;	LED enable/disable command
3155*30391Skarels *	int led_mask;	which LED(s) to twiddle
3156*30391Skarels *
3157*30391Skarels *************/
3158*30391Skarels 
3159*30391Skarels led_control(unit, cmd, led_mask)
3160*30391Skarels u_int unit;
3161*30391Skarels int cmd;
3162*30391Skarels int led_mask;
3163*30391Skarels {
3164*30391Skarels 	register int i;
3165*30391Skarels 	register int status;
3166*30391Skarels 	register struct duart *duart;
3167*30391Skarels 
3168*30391Skarels 	duart = (struct duart *) qdmap[unit].duart;
3169*30391Skarels 
3170*30391Skarels 	for (i = 1000; i > 0; --i) {
3171*30391Skarels 	    if ((status = duart->statusA) & XMT_RDY) {
3172*30391Skarels 		duart->dataA = cmd;
3173*30391Skarels 		break;
3174*30391Skarels 	    }
3175*30391Skarels 	}
3176*30391Skarels 
3177*30391Skarels 	for (i = 1000; i > 0; --i) {
3178*30391Skarels 	    if ((status = duart->statusA) & XMT_RDY) {
3179*30391Skarels 		duart->dataA = led_mask;
3180*30391Skarels 		break;
3181*30391Skarels 	    }
3182*30391Skarels 	}
3183*30391Skarels 
3184*30391Skarels 	if (i == 0)
3185*30391Skarels 	    return(BAD);
3186*30391Skarels 
3187*30391Skarels 	return(GOOD);
3188*30391Skarels 
3189*30391Skarels } /* led_control */
3190*30391Skarels 
3191*30391Skarels /*******************************************************************
3192*30391Skarels *
3193*30391Skarels *	scroll_up()... move the screen up one character height
3194*30391Skarels *
3195*30391Skarels ********************************************************************
3196*30391Skarels *
3197*30391Skarels *	calling convention:
3198*30391Skarels *
3199*30391Skarels *		scroll_up(adder);
3200*30391Skarels *		struct adder *adder;	;address of adder
3201*30391Skarels *
3202*30391Skarels ********/
3203*30391Skarels 
3204*30391Skarels scroll_up(adder)
3205*30391Skarels register struct adder *adder;
3206*30391Skarels {
3207*30391Skarels 
3208*30391Skarels /*------------------------------------------
3209*30391Skarels * setup VIPER operand control registers  */
3210*30391Skarels 
3211*30391Skarels 	wait_status(adder, ADDRESS_COMPLETE);
3212*30391Skarels 
3213*30391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x00FF);  /* select all planes */
3214*30391Skarels 
3215*30391Skarels 	write_ID(adder, MASK_1, 0xFFFF);
3216*30391Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
3217*30391Skarels 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
3218*30391Skarels 
3219*30391Skarels 	write_ID(adder, SRC1_OCR_B,
3220*30391Skarels 			EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY);
3221*30391Skarels 	write_ID(adder, DST_OCR_B,
3222*30391Skarels 			EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
3223*30391Skarels 
3224*30391Skarels /*----------------------------------------
3225*30391Skarels * load DESTINATION origin and vectors  */
3226*30391Skarels 
3227*30391Skarels 	adder->fast_dest_dy = 0;
3228*30391Skarels 	adder->slow_dest_dx = 0;
3229*30391Skarels 	adder->error_1 = 0;
3230*30391Skarels 	adder->error_2 = 0;
3231*30391Skarels 
3232*30391Skarels 	adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL;
3233*30391Skarels 
3234*30391Skarels 	adder->destination_x = 0;
3235*30391Skarels 	adder->fast_dest_dx = 1024;
3236*30391Skarels 
3237*30391Skarels 	adder->destination_y = 0;
3238*30391Skarels 	adder->slow_dest_dy = 864 - CHAR_HEIGHT;
3239*30391Skarels 
3240*30391Skarels /*-----------------------------------
3241*30391Skarels * load SOURCE origin and vectors  */
3242*30391Skarels 
3243*30391Skarels 	adder->source_1_x = 0;
3244*30391Skarels 	adder->source_1_dx = 1024;
3245*30391Skarels 
3246*30391Skarels 	adder->source_1_y = 0 + CHAR_HEIGHT;
3247*30391Skarels 	adder->source_1_dy = 864 - CHAR_HEIGHT;
3248*30391Skarels 
3249*30391Skarels 	write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
3250*30391Skarels 	adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE;
3251*30391Skarels 
3252*30391Skarels /*--------------------------------------------
3253*30391Skarels * do a rectangle clear of last screen line */
3254*30391Skarels 
3255*30391Skarels 	write_ID(adder, MASK_1, 0xffff);
3256*30391Skarels 	write_ID(adder, SOURCE, 0xffff);
3257*30391Skarels 	write_ID(adder,DST_OCR_B,
3258*30391Skarels 		(EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY));
3259*30391Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 0);
3260*30391Skarels 	adder->error_1 = 0;
3261*30391Skarels 	adder->error_2 = 0;
3262*30391Skarels 	adder->slow_dest_dx = 0;	/* set up the width of	*/
3263*30391Skarels 	adder->slow_dest_dy = CHAR_HEIGHT;	/* rectangle */
3264*30391Skarels 
3265*30391Skarels 	adder->rasterop_mode = (NORMAL | DST_WRITE_ENABLE) ;
3266*30391Skarels 	wait_status(adder, RASTEROP_COMPLETE);
3267*30391Skarels 	adder->destination_x = 0;
3268*30391Skarels 	adder->destination_y = 864 - CHAR_HEIGHT;
3269*30391Skarels 
3270*30391Skarels 	adder->fast_dest_dx = 1024;	/* set up the height	*/
3271*30391Skarels 	adder->fast_dest_dy = 0;	/* of rectangle 	*/
3272*30391Skarels 
3273*30391Skarels 	write_ID(adder, LU_FUNCTION_R2, (FULL_SRC_RESOLUTION | LF_SOURCE));
3274*30391Skarels 	adder->cmd = (RASTEROP | OCRB | LF_R2 | DTE ) ;
3275*30391Skarels 
3276*30391Skarels } /* scroll_up */
3277*30391Skarels 
3278*30391Skarels /********************************************************************
3279*30391Skarels *
3280*30391Skarels *	init_shared()... init shared memory pointers and structures
3281*30391Skarels *
3282*30391Skarels *********************************************************************
3283*30391Skarels *
3284*30391Skarels *	calling convention:
3285*30391Skarels *
3286*30391Skarels *		init_shared(unit);
3287*30391Skarels *		u_int unit;
3288*30391Skarels *
3289*30391Skarels ****************/
3290*30391Skarels 
3291*30391Skarels init_shared(unit)
3292*30391Skarels register u_int unit;
3293*30391Skarels {
3294*30391Skarels 	register struct dga *dga;
3295*30391Skarels 
3296*30391Skarels 	dga = (struct dga *) qdmap[unit].dga;
3297*30391Skarels 
3298*30391Skarels /*--------------------------------------------------
3299*30391Skarels * initialize the event queue pointers and header */
3300*30391Skarels 
3301*30391Skarels 	eq_header[unit] = (struct qdinput *)
3302*30391Skarels 			  ((((int)event_shared & ~(0x01FF)) + 512)
3303*30391Skarels 			   + (EVENT_BUFSIZE * unit));
3304*30391Skarels 
3305*30391Skarels 	eq_header[unit]->curs_pos.x = 0;
3306*30391Skarels 	eq_header[unit]->curs_pos.y = 0;
3307*30391Skarels 
3308*30391Skarels 	dga->x_cursor = TRANX(eq_header[unit]->curs_pos.x);
3309*30391Skarels 	dga->y_cursor = TRANY(eq_header[unit]->curs_pos.y);
3310*30391Skarels 
3311*30391Skarels 	eq_header[unit]->curs_box.left = 0;
3312*30391Skarels 	eq_header[unit]->curs_box.right = 0;
3313*30391Skarels 	eq_header[unit]->curs_box.top = 0;
3314*30391Skarels 	eq_header[unit]->curs_box.bottom = 0;
3315*30391Skarels 
3316*30391Skarels /*---------------------------------------------------------
3317*30391Skarels * assign a pointer to the DMA I/O buffer for this QDSS. */
3318*30391Skarels 
3319*30391Skarels 	DMAheader[unit] = (struct DMAreq_header *)
3320*30391Skarels 			  (((int)(&DMA_shared[0] + 512) & ~0x1FF)
3321*30391Skarels 			   + (DMAbuf_size * unit));
3322*30391Skarels 
3323*30391Skarels 	DMAheader[unit]->DMAreq = (struct DMAreq *) ((int)DMAheader[unit]
3324*30391Skarels 				  + sizeof(struct DMAreq_header));
3325*30391Skarels 
3326*30391Skarels 	DMAheader[unit]->QBAreg = 0;
3327*30391Skarels 	DMAheader[unit]->status = 0;
3328*30391Skarels 	DMAheader[unit]->shared_size = DMAbuf_size;
3329*30391Skarels 	DMAheader[unit]->used = 0;
3330*30391Skarels 	DMAheader[unit]->size = 10;	/* default = 10 requests */
3331*30391Skarels 	DMAheader[unit]->oldest = 0;
3332*30391Skarels 	DMAheader[unit]->newest = 0;
3333*30391Skarels 
3334*30391Skarels /*-----------------------------------------------------------
3335*30391Skarels * assign a pointer to the scroll structure for this QDSS. */
3336*30391Skarels 
3337*30391Skarels 	scroll[unit] = (struct scroll *)
3338*30391Skarels 			 (((int)(&scroll_shared[0] + 512) & ~0x1FF)
3339*30391Skarels 			   + (sizeof(struct scroll) * unit));
3340*30391Skarels 
3341*30391Skarels 	scroll[unit]->status = 0;
3342*30391Skarels 	scroll[unit]->viper_constant = 0;
3343*30391Skarels 	scroll[unit]->y_scroll_constant = 0;
3344*30391Skarels 	scroll[unit]->y_offset = 0;
3345*30391Skarels 	scroll[unit]->x_index_pending = 0;
3346*30391Skarels 	scroll[unit]->y_index_pending = 0;
3347*30391Skarels 
3348*30391Skarels /*----------------------------------------------------------------
3349*30391Skarels * assign a pointer to the color map write buffer for this QDSS */
3350*30391Skarels 
3351*30391Skarels 	color_buf[unit] = (struct color_buf *)
3352*30391Skarels 			   (((int)(&color_shared[0] + 512) & ~0x1FF)
3353*30391Skarels 			    + (COLOR_BUFSIZ * unit));
3354*30391Skarels 
3355*30391Skarels 	color_buf[unit]->status = 0;
3356*30391Skarels 	color_buf[unit]->count = 0;
3357*30391Skarels 
3358*30391Skarels } /* init_shared */
3359*30391Skarels 
3360*30391Skarels /*********************************************************************
3361*30391Skarels *
3362*30391Skarels *	setup_dragon()... init the ADDER, VIPER, bitmaps, & color map
3363*30391Skarels *
3364*30391Skarels **********************************************************************
3365*30391Skarels *
3366*30391Skarels *	calling convention:
3367*30391Skarels *
3368*30391Skarels *		setup_dragon();
3369*30391Skarels *
3370*30391Skarels *	return: NONE
3371*30391Skarels *
3372*30391Skarels ************************/
3373*30391Skarels 
3374*30391Skarels setup_dragon(unit)
3375*30391Skarels u_int unit;
3376*30391Skarels {
3377*30391Skarels 
3378*30391Skarels 	register struct adder *adder;
3379*30391Skarels 	register struct dga *dga;
3380*30391Skarels 	short *memcsr;
3381*30391Skarels 
3382*30391Skarels 	int i;			/* general purpose variables */
3383*30391Skarels 	int status;
3384*30391Skarels 
3385*30391Skarels 	short top;		/* clipping/scrolling boundaries */
3386*30391Skarels 	short bottom;
3387*30391Skarels 	short right;
3388*30391Skarels 	short left;
3389*30391Skarels 
3390*30391Skarels 	short *red;		/* color map pointers */
3391*30391Skarels 	short *green;
3392*30391Skarels 	short *blue;
3393*30391Skarels 
3394*30391Skarels /*------------------
3395*30391Skarels * init for setup */
3396*30391Skarels 
3397*30391Skarels 	adder = (struct adder *) qdmap[unit].adder;
3398*30391Skarels 	dga = (struct dga *) qdmap[unit].dga;
3399*30391Skarels 	memcsr = (short *) qdmap[unit].memcsr;
3400*30391Skarels 
3401*30391Skarels 	dga->csr &= ~(DMA_IE | 0x700);	/* halt DMA and kill the intrpts */
3402*30391Skarels 	*memcsr = SYNC_ON;		/* blank screen and turn off LED's */
3403*30391Skarels 	adder->command = CANCEL;
3404*30391Skarels 
3405*30391Skarels /*----------------------
3406*30391Skarels * set monitor timing */
3407*30391Skarels 
3408*30391Skarels 	adder->x_scan_count_0 = 0x2800;
3409*30391Skarels 	adder->x_scan_count_1 = 0x1020;
3410*30391Skarels 	adder->x_scan_count_2 = 0x003A;
3411*30391Skarels 	adder->x_scan_count_3 = 0x38F0;
3412*30391Skarels 	adder->x_scan_count_4 = 0x6128;
3413*30391Skarels 	adder->x_scan_count_5 = 0x093A;
3414*30391Skarels 	adder->x_scan_count_6 = 0x313C;
3415*30391Skarels 	adder->sync_phase_adj = 0x0100;
3416*30391Skarels 	adder->x_scan_conf = 0x00C8;
3417*30391Skarels 
3418*30391Skarels /*---------------------------------------------------------
3419*30391Skarels * got a bug in secound pass ADDER! lets take care of it */
3420*30391Skarels 
3421*30391Skarels 	/* normally, just use the code in the following bug fix code, but to
3422*30391Skarels 	* make repeated demos look pretty, load the registers as if there was
3423*30391Skarels 	* no bug and then test to see if we are getting sync */
3424*30391Skarels 
3425*30391Skarels 	adder->y_scan_count_0 = 0x135F;
3426*30391Skarels 	adder->y_scan_count_1 = 0x3363;
3427*30391Skarels 	adder->y_scan_count_2 = 0x2366;
3428*30391Skarels 	adder->y_scan_count_3 = 0x0388;
3429*30391Skarels 
3430*30391Skarels 	/* if no sync, do the bug fix code */
3431*30391Skarels 
3432*30391Skarels 	if (wait_status(adder, VSYNC) == BAD) {
3433*30391Skarels 
3434*30391Skarels 	    /* first load all Y scan registers with very short frame and
3435*30391Skarels 	    * wait for scroll service.	This guarantees at least one SYNC
3436*30391Skarels 	    * to fix the pass 2 Adder initialization bug (synchronizes
3437*30391Skarels 	    * XCINCH with DMSEEDH) */
3438*30391Skarels 
3439*30391Skarels 	    adder->y_scan_count_0 = 0x01;
3440*30391Skarels 	    adder->y_scan_count_1 = 0x01;
3441*30391Skarels 	    adder->y_scan_count_2 = 0x01;
3442*30391Skarels 	    adder->y_scan_count_3 = 0x01;
3443*30391Skarels 
3444*30391Skarels 	    wait_status(adder, VSYNC);	/* delay at least 1 full frame time */
3445*30391Skarels 	    wait_status(adder, VSYNC);
3446*30391Skarels 
3447*30391Skarels 	    /* now load the REAL sync values (in reverse order just to
3448*30391Skarels 	    *  be safe.  */
3449*30391Skarels 
3450*30391Skarels 	    adder->y_scan_count_3 = 0x0388;
3451*30391Skarels 	    adder->y_scan_count_2 = 0x2366;
3452*30391Skarels 	    adder->y_scan_count_1 = 0x3363;
3453*30391Skarels 	    adder->y_scan_count_0 = 0x135F;
3454*30391Skarels 	}
3455*30391Skarels 
3456*30391Skarels 	*memcsr = SYNC_ON | UNBLANK;	/* turn off leds and turn on video */
3457*30391Skarels 
3458*30391Skarels /*----------------------------
3459*30391Skarels * zero the index registers */
3460*30391Skarels 
3461*30391Skarels 	adder->x_index_pending = 0;
3462*30391Skarels 	adder->y_index_pending = 0;
3463*30391Skarels 	adder->x_index_new = 0;
3464*30391Skarels 	adder->y_index_new = 0;
3465*30391Skarels 	adder->x_index_old = 0;
3466*30391Skarels 	adder->y_index_old = 0;
3467*30391Skarels 
3468*30391Skarels 	adder->pause = 0;
3469*30391Skarels 
3470*30391Skarels /*----------------------------------------
3471*30391Skarels * set rasterop mode to normal pen down */
3472*30391Skarels 
3473*30391Skarels 	adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL;
3474*30391Skarels 
3475*30391Skarels /*--------------------------------------------------
3476*30391Skarels * set the rasterop registers to a default values */
3477*30391Skarels 
3478*30391Skarels 	adder->source_1_dx = 1;
3479*30391Skarels 	adder->source_1_dy = 1;
3480*30391Skarels 	adder->source_1_x = 0;
3481*30391Skarels 	adder->source_1_y = 0;
3482*30391Skarels 	adder->destination_x = 0;
3483*30391Skarels 	adder->destination_y = 0;
3484*30391Skarels 	adder->fast_dest_dx = 1;
3485*30391Skarels 	adder->fast_dest_dy = 0;
3486*30391Skarels 	adder->slow_dest_dx = 0;
3487*30391Skarels 	adder->slow_dest_dy = 1;
3488*30391Skarels 	adder->error_1 = 0;
3489*30391Skarels 	adder->error_2 = 0;
3490*30391Skarels 
3491*30391Skarels /*------------------------
3492*30391Skarels * scale factor = unity */
3493*30391Skarels 
3494*30391Skarels 	adder->fast_scale = UNITY;
3495*30391Skarels 	adder->slow_scale = UNITY;
3496*30391Skarels 
3497*30391Skarels /*-------------------------------
3498*30391Skarels * set the source 2 parameters */
3499*30391Skarels 
3500*30391Skarels 	adder->source_2_x = 0;
3501*30391Skarels 	adder->source_2_y = 0;
3502*30391Skarels 	adder->source_2_size = 0x0022;
3503*30391Skarels 
3504*30391Skarels /*-----------------------------------------------
3505*30391Skarels * initialize plane addresses for eight vipers */
3506*30391Skarels 
3507*30391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0001);
3508*30391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0000);
3509*30391Skarels 
3510*30391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0002);
3511*30391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0001);
3512*30391Skarels 
3513*30391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0004);
3514*30391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0002);
3515*30391Skarels 
3516*30391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0008);
3517*30391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0003);
3518*30391Skarels 
3519*30391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0010);
3520*30391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0004);
3521*30391Skarels 
3522*30391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0020);
3523*30391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0005);
3524*30391Skarels 
3525*30391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0040);
3526*30391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0006);
3527*30391Skarels 
3528*30391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0080);
3529*30391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0007);
3530*30391Skarels 
3531*30391Skarels 	/* initialize the external registers. */
3532*30391Skarels 
3533*30391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x00FF);
3534*30391Skarels 	write_ID(adder, CS_SCROLL_MASK, 0x00FF);
3535*30391Skarels 
3536*30391Skarels 	/* initialize resolution mode */
3537*30391Skarels 
3538*30391Skarels 	write_ID(adder, MEMORY_BUS_WIDTH, 0x000C);     /* bus width = 16 */
3539*30391Skarels 	write_ID(adder, RESOLUTION_MODE, 0x0000);      /* one bit/pixel */
3540*30391Skarels 
3541*30391Skarels 	/* initialize viper registers */
3542*30391Skarels 
3543*30391Skarels 	write_ID(adder, SCROLL_CONSTANT, SCROLL_ENABLE|VIPER_LEFT|VIPER_UP);
3544*30391Skarels 	write_ID(adder, SCROLL_FILL, 0x0000);
3545*30391Skarels 
3546*30391Skarels /*----------------------------------------------------
3547*30391Skarels * set clipping and scrolling limits to full screen */
3548*30391Skarels 
3549*30391Skarels 	for ( i = 1000, adder->status = 0
3550*30391Skarels 	    ; i > 0  &&  !((status = adder->status) & ADDRESS_COMPLETE)
3551*30391Skarels 	    ; --i);
3552*30391Skarels 
3553*30391Skarels 	if (i == 0)
3554*30391Skarels 	    mprintf("\nqd%d: setup_dragon: timeout on ADDRESS_COMPLETE",unit);
3555*30391Skarels 
3556*30391Skarels 	top = 0;
3557*30391Skarels 	bottom = 2048;
3558*30391Skarels 	left = 0;
3559*30391Skarels 	right = 1024;
3560*30391Skarels 
3561*30391Skarels 	adder->x_clip_min = left;
3562*30391Skarels 	adder->x_clip_max = right;
3563*30391Skarels 	adder->y_clip_min = top;
3564*30391Skarels 	adder->y_clip_max = bottom;
3565*30391Skarels 
3566*30391Skarels 	adder->scroll_x_min = left;
3567*30391Skarels 	adder->scroll_x_max = right;
3568*30391Skarels 	adder->scroll_y_min = top;
3569*30391Skarels 	adder->scroll_y_max = bottom;
3570*30391Skarels 
3571*30391Skarels 	wait_status(adder, VSYNC);	/* wait at LEAST 1 full frame */
3572*30391Skarels 	wait_status(adder, VSYNC);
3573*30391Skarels 
3574*30391Skarels 	adder->x_index_pending = left;
3575*30391Skarels 	adder->y_index_pending = top;
3576*30391Skarels 	adder->x_index_new = left;
3577*30391Skarels 	adder->y_index_new = top;
3578*30391Skarels 	adder->x_index_old = left;
3579*30391Skarels 	adder->y_index_old = top;
3580*30391Skarels 
3581*30391Skarels 	for ( i = 1000, adder->status = 0
3582*30391Skarels 	    ; i > 0  &&  !((status = adder->status) & ADDRESS_COMPLETE)
3583*30391Skarels 	    ; --i);
3584*30391Skarels 
3585*30391Skarels 	if (i == 0)
3586*30391Skarels 	    mprintf("\nqd%d: setup_dragon: timeout on ADDRESS_COMPLETE",unit);
3587*30391Skarels 
3588*30391Skarels 	write_ID(adder, LEFT_SCROLL_MASK, 0x0000);
3589*30391Skarels 	write_ID(adder, RIGHT_SCROLL_MASK, 0x0000);
3590*30391Skarels 
3591*30391Skarels /*------------------------------------------------------------
3592*30391Skarels * set source and the mask register to all ones (ie: white) */
3593*30391Skarels 
3594*30391Skarels 	write_ID(adder, SOURCE, 0xFFFF);
3595*30391Skarels 	write_ID(adder, MASK_1, 0xFFFF);
3596*30391Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
3597*30391Skarels 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
3598*30391Skarels 
3599*30391Skarels /*--------------------------------------------------------------
3600*30391Skarels * initialize Operand Control Register banks for fill command */
3601*30391Skarels 
3602*30391Skarels 	write_ID(adder, SRC1_OCR_A, EXT_NONE | INT_M1_M2  | NO_ID | WAIT);
3603*30391Skarels 	write_ID(adder, SRC2_OCR_A, EXT_NONE | INT_SOURCE | NO_ID | NO_WAIT);
3604*30391Skarels 	write_ID(adder, DST_OCR_A, EXT_NONE | INT_NONE	 | NO_ID | NO_WAIT);
3605*30391Skarels 
3606*30391Skarels 	write_ID(adder, SRC1_OCR_B, EXT_NONE | INT_SOURCE | NO_ID | WAIT);
3607*30391Skarels 	write_ID(adder, SRC2_OCR_B, EXT_NONE | INT_M1_M2  | NO_ID | NO_WAIT);
3608*30391Skarels 	write_ID(adder, DST_OCR_B, EXT_NONE | INT_NONE | NO_ID | NO_WAIT);
3609*30391Skarels 
3610*30391Skarels /*------------------------------------------------------------------
3611*30391Skarels * init Logic Unit Function registers, (these are just common values,
3612*30391Skarels * and may be changed as required).  */
3613*30391Skarels 
3614*30391Skarels 	write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
3615*30391Skarels 	write_ID(adder, LU_FUNCTION_R2, FULL_SRC_RESOLUTION | LF_SOURCE | INV_M1_M2);
3616*30391Skarels 	write_ID(adder, LU_FUNCTION_R3, FULL_SRC_RESOLUTION | LF_D_OR_S);
3617*30391Skarels 	write_ID(adder, LU_FUNCTION_R4, FULL_SRC_RESOLUTION | LF_D_XOR_S);
3618*30391Skarels 
3619*30391Skarels /*----------------------------------------
3620*30391Skarels * load the color map for black & white */
3621*30391Skarels 
3622*30391Skarels 	for ( i = 0, adder->status = 0
3623*30391Skarels 	    ; i < 10000  &&  !((status = adder->status) & VSYNC)
3624*30391Skarels 	    ; ++i);
3625*30391Skarels 
3626*30391Skarels 	if (i == 0)
3627*30391Skarels 	    mprintf("\nqd%d: setup_dragon: timeout on VSYNC", unit);
3628*30391Skarels 
3629*30391Skarels 	red = (short *) qdmap[unit].red;
3630*30391Skarels 	green = (short *) qdmap[unit].green;
3631*30391Skarels 	blue = (short *) qdmap[unit].blue;
3632*30391Skarels 
3633*30391Skarels 	*red++ = 0x00;			/* black */
3634*30391Skarels 	*green++ = 0x00;
3635*30391Skarels 	*blue++ = 0x00;
3636*30391Skarels 
3637*30391Skarels 	*red-- = 0xFF;			/* white */
3638*30391Skarels 	*green-- = 0xFF;
3639*30391Skarels 	*blue-- = 0xFF;
3640*30391Skarels 
3641*30391Skarels 	/*----------------------------------
3642*30391Skarels 	* set color map for mouse cursor */
3643*30391Skarels 
3644*30391Skarels 	red += 254;
3645*30391Skarels 	green += 254;
3646*30391Skarels 	blue += 254;
3647*30391Skarels 
3648*30391Skarels 	*red++ = 0x00;			/* black */
3649*30391Skarels 	*green++ = 0x00;
3650*30391Skarels 	*blue++ = 0x00;
3651*30391Skarels 
3652*30391Skarels 	*red = 0xFF;			/* white */
3653*30391Skarels 	*green = 0xFF;
3654*30391Skarels 	*blue = 0xFF;
3655*30391Skarels 
3656*30391Skarels 	return(0);
3657*30391Skarels 
3658*30391Skarels } /* setup_dragon */
3659*30391Skarels 
3660*30391Skarels /******************************************************************
3661*30391Skarels *
3662*30391Skarels *	setup_input()... init the DUART and set defaults in input
3663*30391Skarels *			 devices
3664*30391Skarels *
3665*30391Skarels *******************************************************************
3666*30391Skarels *
3667*30391Skarels *	calling convention:
3668*30391Skarels *
3669*30391Skarels *		setup_input(unit);
3670*30391Skarels *
3671*30391Skarels *	where: unit - is the QDSS unit number to be setup
3672*30391Skarels *
3673*30391Skarels *********/
3674*30391Skarels 
3675*30391Skarels setup_input(unit)
3676*30391Skarels u_int unit;
3677*30391Skarels {
3678*30391Skarels 	register struct duart *duart;	/* DUART register structure pointer */
3679*30391Skarels 	register int i; 		/* scratch variable */
3680*30391Skarels 	register int bits;
3681*30391Skarels 
3682*30391Skarels 	char id_byte;
3683*30391Skarels 	short status;
3684*30391Skarels 
3685*30391Skarels /*---------------
3686*30391Skarels * init stuff */
3687*30391Skarels 
3688*30391Skarels 	duart = (struct duart *) qdmap[unit].duart;
3689*30391Skarels 	duart->imask = 0;
3690*30391Skarels 
3691*30391Skarels /*---------------------------------------------
3692*30391Skarels * setup the DUART for kbd & pointing device */
3693*30391Skarels 
3694*30391Skarels 	duart->cmdA = RESET_M;	  /* reset mode reg ptr for kbd */
3695*30391Skarels 	duart->modeA = 0x13;	  /* 8 bits, no parity, rcv IE, */
3696*30391Skarels 				  /* no RTS control,char error mode */
3697*30391Skarels 	duart->modeA = 0x07;	  /* 1 stop bit,CTS does not IE XMT */
3698*30391Skarels 				  /* no RTS control,no echo or loop */
3699*30391Skarels 	duart->cmdB = RESET_M;	  /* reset mode reg pntr for host */
3700*30391Skarels 	duart->modeB = 0x07;	  /* 8 bits, odd parity, rcv IE.. */
3701*30391Skarels 				  /* ..no RTS cntrl, char error mode */
3702*30391Skarels 	duart->modeB = 0x07;	  /* 1 stop bit,CTS does not IE XMT */
3703*30391Skarels 				  /* no RTS control,no echo or loop */
3704*30391Skarels 
3705*30391Skarels 	duart->auxctl = 0x00;	  /* baud rate set 1 */
3706*30391Skarels 
3707*30391Skarels 	duart->clkselA = 0x99;	  /* 4800 baud for kbd */
3708*30391Skarels 	duart->clkselB = 0x99;	  /* 4800 baud for mouse */
3709*30391Skarels 
3710*30391Skarels 	/* reset everything for keyboard */
3711*30391Skarels 
3712*30391Skarels 	for (bits = RESET_M; bits < START_BREAK; bits += 0x10)
3713*30391Skarels 	    duart->cmdA = bits;
3714*30391Skarels 
3715*30391Skarels 	/* reset everything for host */
3716*30391Skarels 
3717*30391Skarels 	for (bits = RESET_M; bits < START_BREAK; bits += 0x10)
3718*30391Skarels 	     duart->cmdB = bits;
3719*30391Skarels 
3720*30391Skarels 	duart->cmdA = EN_RCV | EN_XMT; /* enbl xmt & rcv for kbd */
3721*30391Skarels 	duart->cmdB = EN_RCV | EN_XMT; /* enbl xmt & rcv for pointer device */
3722*30391Skarels 
3723*30391Skarels /*--------------------------------------------
3724*30391Skarels * init keyboard defaults (DUART channel A) */
3725*30391Skarels 
3726*30391Skarels 	for (i = 500; i > 0; --i) {
3727*30391Skarels 	    if ((status = duart->statusA) & XMT_RDY) {
3728*30391Skarels 		duart->dataA = LK_DEFAULTS;
3729*30391Skarels 		break;
3730*30391Skarels 	    }
3731*30391Skarels 	}
3732*30391Skarels 
3733*30391Skarels 	for (i = 100000; i > 0; --i) {
3734*30391Skarels 	    if ((status = duart->statusA) & RCV_RDY) {
3735*30391Skarels 		break;
3736*30391Skarels 	    }
3737*30391Skarels 	}
3738*30391Skarels 
3739*30391Skarels 	status = duart->dataA;		/* flush the ACK */
3740*30391Skarels 
3741*30391Skarels /*--------------------------------
3742*30391Skarels * identify the pointing device */
3743*30391Skarels 
3744*30391Skarels 	for (i = 500; i > 0; --i) {
3745*30391Skarels 	    if ((status = duart->statusB) & XMT_RDY) {
3746*30391Skarels 		duart->dataB = SELF_TEST;
3747*30391Skarels 		break;
3748*30391Skarels 	    }
3749*30391Skarels 	}
3750*30391Skarels 
3751*30391Skarels 	/*-----------------------------------------
3752*30391Skarels 	* wait for 1st byte of self test report */
3753*30391Skarels 
3754*30391Skarels 	for (i = 100000; i > 0; --i) {
3755*30391Skarels 	    if ((status = duart->statusB) & RCV_RDY) {
3756*30391Skarels 		break;
3757*30391Skarels 	    }
3758*30391Skarels 	}
3759*30391Skarels 
3760*30391Skarels 	if (i == 0) {
3761*30391Skarels 	    mprintf("\nqd[%d]: setup_input: timeout on 1st byte of self test",unit);
3762*30391Skarels 	    goto OUT;
3763*30391Skarels 	}
3764*30391Skarels 
3765*30391Skarels 	status = duart->dataB;
3766*30391Skarels 
3767*30391Skarels 	/*-----------------------------------------
3768*30391Skarels 	* wait for ID byte of self test report	*/
3769*30391Skarels 
3770*30391Skarels 	for (i = 100000; i > 0; --i) {
3771*30391Skarels 	    if ((status = duart->statusB) & RCV_RDY) {
3772*30391Skarels 		break;
3773*30391Skarels 	    }
3774*30391Skarels 	}
3775*30391Skarels 
3776*30391Skarels 	if (i == 0) {
3777*30391Skarels 	    mprintf("\nqd[%d]: setup_input: timeout on 2nd byte of self test", unit);
3778*30391Skarels 	    goto OUT;
3779*30391Skarels 	}
3780*30391Skarels 
3781*30391Skarels 	id_byte = duart->dataB;
3782*30391Skarels 
3783*30391Skarels 	/*------------------------------------
3784*30391Skarels 	* wait for other bytes to come in  */
3785*30391Skarels 
3786*30391Skarels 	for (i = 100000; i > 0; --i) {
3787*30391Skarels 	    if ((status = duart->statusB) & RCV_RDY) {
3788*30391Skarels 		status = duart->dataB;
3789*30391Skarels 		break;
3790*30391Skarels 	    }
3791*30391Skarels 	}
3792*30391Skarels 
3793*30391Skarels 	if (i == 0) {
3794*30391Skarels 	    mprintf("\nqd[%d]: setup_input: timeout on 3rd byte of self test", unit);
3795*30391Skarels 	    goto OUT;
3796*30391Skarels 	}
3797*30391Skarels 
3798*30391Skarels 	for (i = 100000; i > 0; --i) {
3799*30391Skarels 	    if ((status = duart->statusB) & RCV_RDY) {
3800*30391Skarels 		status = duart->dataB;
3801*30391Skarels 		break;
3802*30391Skarels 	    }
3803*30391Skarels 	}
3804*30391Skarels 
3805*30391Skarels 	if (i == 0) {
3806*30391Skarels 	    mprintf("\nqd[%d]: setup_input: timeout on 4th byte of self test\n", unit);
3807*30391Skarels 	    goto OUT;
3808*30391Skarels 	}
3809*30391Skarels 
3810*30391Skarels 	/*----------------------------------------------
3811*30391Skarels 	* flag pointing device type and set defaults */
3812*30391Skarels 
3813*30391Skarels 	for (i=100000; i>0; --i);
3814*30391Skarels 
3815*30391Skarels 	if ((id_byte & 0x0F) != TABLET_ID) {
3816*30391Skarels 
3817*30391Skarels 	    qdflags[unit].pntr_id = MOUSE_ID;
3818*30391Skarels 
3819*30391Skarels 	    for (i = 500; i > 0; --i) {
3820*30391Skarels 		if ((status = duart->statusB) & XMT_RDY) {
3821*30391Skarels 		    duart->dataB = INC_STREAM_MODE;
3822*30391Skarels 		    break;
3823*30391Skarels 		}
3824*30391Skarels 	    }
3825*30391Skarels 	} else {
3826*30391Skarels 
3827*30391Skarels 	    qdflags[unit].pntr_id = TABLET_ID;
3828*30391Skarels 
3829*30391Skarels 	    for (i = 500; i > 0; --i) {
3830*30391Skarels 		if ((status = duart->statusB) & XMT_RDY) {
3831*30391Skarels 		    duart->dataB = T_STREAM;
3832*30391Skarels 		    break;
3833*30391Skarels 		}
3834*30391Skarels 	    }
3835*30391Skarels 	}
3836*30391Skarels 
3837*30391Skarels /*--------
3838*30391Skarels * exit */
3839*30391Skarels 
3840*30391Skarels OUT:
3841*30391Skarels 	duart->imask = qdflags[unit].duart_imask;
3842*30391Skarels 	return(0);
3843*30391Skarels 
3844*30391Skarels } /* setup_input */
3845*30391Skarels 
3846*30391Skarels /**********************************************************************
3847*30391Skarels *
3848*30391Skarels *	wait_status()... delay for at least one display frame time
3849*30391Skarels *
3850*30391Skarels ***********************************************************************
3851*30391Skarels *
3852*30391Skarels *	calling convention:
3853*30391Skarels *
3854*30391Skarels *		wait_status(adder, mask);
3855*30391Skarels *		struct *adder adder;
3856*30391Skarels *		int mask;
3857*30391Skarels *
3858*30391Skarels *	return: BAD means that we timed out without ever seeing the
3859*30391Skarels *		      vertical sync status bit
3860*30391Skarels *		GOOD otherwise
3861*30391Skarels *
3862*30391Skarels **************/
3863*30391Skarels 
3864*30391Skarels wait_status(adder, mask)
3865*30391Skarels register struct adder *adder;
3866*30391Skarels register int mask;
3867*30391Skarels {
3868*30391Skarels 	register short status;
3869*30391Skarels 	int i;
3870*30391Skarels 
3871*30391Skarels 	for ( i = 10000, adder->status = 0
3872*30391Skarels 	    ; i > 0  &&  !((status = adder->status) & mask)
3873*30391Skarels 	    ; --i);
3874*30391Skarels 
3875*30391Skarels 	if (i == 0) {
3876*30391Skarels 	    mprintf("\nwait_status: timeout polling for 0x%x in adder->status", mask);
3877*30391Skarels 	    return(BAD);
3878*30391Skarels 	}
3879*30391Skarels 
3880*30391Skarels 	return(GOOD);
3881*30391Skarels 
3882*30391Skarels } /* wait_status */
3883*30391Skarels 
3884*30391Skarels /**********************************************************************
3885*30391Skarels *
3886*30391Skarels *	write_ID()... write out onto the ID bus
3887*30391Skarels *
3888*30391Skarels ***********************************************************************
3889*30391Skarels *
3890*30391Skarels *	calling convention:
3891*30391Skarels *
3892*30391Skarels *		struct *adder adder;	;pntr to ADDER structure
3893*30391Skarels *		short adrs;		;VIPER address
3894*30391Skarels *		short data;		;data to be written
3895*30391Skarels *		write_ID(adder);
3896*30391Skarels *
3897*30391Skarels *	return: BAD means that we timed out waiting for status bits
3898*30391Skarels *		      VIPER-access-specific status bits
3899*30391Skarels *		GOOD otherwise
3900*30391Skarels *
3901*30391Skarels **************/
3902*30391Skarels 
3903*30391Skarels write_ID(adder, adrs, data)
3904*30391Skarels register struct adder *adder;
3905*30391Skarels register short adrs;
3906*30391Skarels register short data;
3907*30391Skarels {
3908*30391Skarels 	int i;
3909*30391Skarels 	short status;
3910*30391Skarels 
3911*30391Skarels 	for ( i = 100000, adder->status = 0
3912*30391Skarels 	    ; i > 0  &&  !((status = adder->status) & ADDRESS_COMPLETE)
3913*30391Skarels 	    ; --i);
3914*30391Skarels 
3915*30391Skarels 	if (i == 0)
3916*30391Skarels 	    goto ERR;
3917*30391Skarels 
3918*30391Skarels 	for ( i = 100000, adder->status = 0
3919*30391Skarels 	    ; i > 0  &&  !((status = adder->status) & TX_READY)
3920*30391Skarels 	    ; --i);
3921*30391Skarels 
3922*30391Skarels 	if (i > 0) {
3923*30391Skarels 	    adder->id_data = data;
3924*30391Skarels 	    adder->command = ID_LOAD | adrs;
3925*30391Skarels 	    return(GOOD);
3926*30391Skarels 	}
3927*30391Skarels 
3928*30391Skarels ERR:
3929*30391Skarels 	mprintf("\nwrite_ID: timeout trying to write to VIPER");
3930*30391Skarels 	return(BAD);
3931*30391Skarels 
3932*30391Skarels } /* write_ID */
3933