xref: /csrg-svn/sys/vax/uba/qd.c (revision 32012)
130391Skarels #ifndef lint
2*32012Smarc static char *sccsid = "@(#)qd.c	1.2  Berkeley  08/07/87";
3*32012Smarc static char *osccsid = "@(#)qd.c	1.40	ULTRIX	10/2/86";
430391Skarels #endif lint
530391Skarels 
630391Skarels /************************************************************************
730391Skarels  *									*
830391Skarels  *			Copyright (c) 1985, 1986 by			*
930391Skarels *		Digital Equipment Corporation, Maynard, MA		*
1030391Skarels *			All rights reserved.				*
1130391Skarels *									*
1230391Skarels *   This software is furnished under a license and may be used and	*
1330391Skarels *   copied  only  in accordance with the terms of such license and	*
1430391Skarels *   with the  inclusion  of  the  above  copyright  notice.   This	*
1530391Skarels *   software  or  any  other copies thereof may not be provided or	*
1630391Skarels *   otherwise made available to any other person.  No title to and	*
1730391Skarels *   ownership of the software is hereby transferred.			*
1830391Skarels *									*
1930391Skarels *   The information in this software is subject to change  without	*
2030391Skarels *   notice  and should not be construed as a commitment by Digital	*
2130391Skarels *   Equipment Corporation.						*
2230391Skarels *									*
2330391Skarels *   Digital assumes no responsibility for the use  or  reliability	*
2430391Skarels *   of its software on equipment which is not supplied by Digital.	*
2530391Skarels *									*
2630391Skarels *************************************************************************/
2730391Skarels 
28*32012Smarc 
2930391Skarels /*
3030391Skarels  * qd.c
3130391Skarels  *
3230391Skarels  * Modification history
3330391Skarels  *
3430391Skarels  * QDSS workstation driver
3530391Skarels  *
36*32012Smarc  *  Aug 1987 - marc@ucbvax.berkeley.edu
37*32012Smarc  *
38*32012Smarc  *	Modify for 4.3bsd with Mikes help.  Add cursor motion support
39*32012Smarc  *	in glass tty.  Work around glass tty output bug (which causes
40*32012Smarc  *	screen to freeze).  Reformat as many comments as patience would
41*32012Smarc  *	allow. Use 4.3 console redirect (TIOCCONS) instead of smashing
42*32012Smarc  *	cdevsw.  Supporting changes are in locore.s (for map),
43*32012Smarc  *	machdep.c, and conf.c. Note that the major number for qd
44*32012Smarc  *	is different from ultrix: on 4.3bsd its 41, and on
45*32012Smarc  *	ultrix its 42.
46*32012Smarc  *
4730391Skarels  * 26-Aug-86 - rsp (Ricky Palmer)
4830391Skarels  *
4930391Skarels  *	Cleaned up devioctl code to (1) zero out devget structure
5030391Skarels  *	upon entry and (2) use strlen instead of fixed storage
5130391Skarels  *	for bcopy's.
5230391Skarels  *
5330391Skarels  * 21-Jul-86 - Ram Rao
5430391Skarels  *	allowed cursor rectangle to hang (partially) off the
5530391Skarels  *	top and left of screen
5630391Skarels  *
5730391Skarels  * 11-Jul-86 - ricky palmer
5830391Skarels  *
5930391Skarels  *	Added adpt and nexus fields to DEVIOCGET code.
6030391Skarels  *
6130391Skarels  * 02-July-86 - Brian Stevens
6230391Skarels  *
6330391Skarels  *	added support for console writing to second QDSS display
6430391Skarels  *
6530391Skarels  * 20-May-86 - ricky palmer
6630391Skarels  *
6730391Skarels  *	Added new DEVIOCGET ioctl request code. V2.0
6830391Skarels  *
6930391Skarels  * 16-Apr-86 -- darrell
7030391Skarels  *	 badaddr is now called via the macro BADADDR
7130391Skarels  *
7230391Skarels  * 14-Apr-86 -- afd
7330391Skarels  *	 Changed UMEMmap to QMEMmap and umem to qmem.
7430391Skarels  *
7530391Skarels  *	 v_console() is now refered to as v_consputc, and there is a
7630391Skarels  *	 corresponding v_consgetc() (defined in /sys/vax/conf.c).
7730391Skarels  *
7830391Skarels  *	 Added "qdgetc()" routine for console read.  Needed to read
7930391Skarels  *	 user's answer to the "root device?" prompt with a generic kernel.
8030391Skarels  *
8130391Skarels  * 19-Mar-86 -- pmk
8230391Skarels  *	 Change DELAY to 20000, because microdelay now in real microsec.
8330391Skarels  *
8430391Skarels  * 18-mar-86  -- jaw	 br/cvec changed to NOT use registers.
8530391Skarels  *
8630391Skarels  * 11 mar 86  darrell	replaced percpu with cpusw, and removed all but
8730391Skarels  *			 one global reference
8830391Skarels  * 19 feb 86  bstevens	no report of motion event on puck/stylus button action
8930391Skarels  * 18 feb 86  bstevens	put in cursor box support for tablets
9030391Skarels  * 18-Mar-86 -- jaw  add routines to cpu switch for nexus/unibus addreses
9130391Skarels  *		      also got rid of some globals like nexnum.
9230391Skarels  *		      ka8800 cleanup.
9330391Skarels  * 06 dec 85  longo  added LK-201 error reporting for graphics device ops
9430391Skarels  * 03 dec 85  longo  made qddint() clear active bit on error
9530391Skarels  * 02 dec 85  longo  fixed up some crocks in the error messages
9630391Skarels  * 25 nov 85  longo  added error handling to DMA ISR and single user locking
9730391Skarels  * 19 nov 85  longo  eliminated "set_defaults()" by breaking out sub-calls.
9830391Skarels  *		     Changed init_shared to do real init of scroll struct
9930391Skarels  * 12 nov 85  longo  fixed bug in open that broke alternate console re-direct
10030391Skarels  * 11 nov 85  longo  changed "_vs_eventqueue" references to "qdinput"
10130391Skarels  * 08 nov 85  longo  improved select service for read/write select wakeup.
10230391Skarels  *		     Also set ISR's to ipl4 to allow the interval timer in.
10330391Skarels  * 04 nov 85  longo  fixed bugs in mouse button reporting and dma request stuff
10430391Skarels  * 30 oct 85  longo  DMA to/from user space is in place
10530391Skarels  * 14 oct 85  longo  added kernel msg redirect and QD_RDCURSOR ioctl
10630391Skarels  * 03 oct 85  longo  added support for multiple QDSS's
10730391Skarels  * 02 oct 85  longo  added color map loading services in qdioctl() & qdaint()
10830391Skarels  * 30 sep 85  longo  added DMA interrupt services
10930391Skarels  * 18 sep 85  longo  added scroll services to "qdaint()" adder intrpt service
11030391Skarels  *		     and put in supporting ioctl's
11130391Skarels  * 04 sep 85  longo  initial implementation of DMA is working
11230391Skarels  * 17 aug 85  longo  added support for the QDSS to be system console
11330391Skarels  * 05 aug 85  longo  now using qfont (QVSS & QDSS) as linked object
11430391Skarels  * 12 jun 85  longo  added mouse event loading to "qdiint()"
11530391Skarels  * 31 may 85  longo  put live interrupts into the probe() routine
11630391Skarels  * 30 may 85  longo  event queue shared memory implementation is now alive
11730391Skarels  * 29 may 85  longo  LK-201 input is now interrupt driven
11830391Skarels  * 25 apr 85  longo  MAPDEVICE works
11930391Skarels  * 14 mar 85  longo  created
12030391Skarels  *
12130391Skarels  *	 todo:	 fix rlogin bug in console stuff
12230391Skarels  *		 check error return from strategy routine
12330391Skarels  *		 verify TOY time stuff (what format?)
12430391Skarels  *		 look at system based macro implementation of VTOP
12530391Skarels  *
12630391Skarels  */
12730391Skarels 
128*32012Smarc #define mprintf printf
129*32012Smarc #include "qd.h" 	/* # of QDSS's the system is configured for */
13030391Skarels 
131*32012Smarc #include "../vax/pte.h"	/* page table values */
132*32012Smarc #include "../vax/mtpr.h"	/* VAX register access stuff */
13330391Skarels 
134*32012Smarc #include "../h/param.h" 	/* general system params & macros */
135*32012Smarc #include "../h/conf.h"		/* "linesw" tty driver dispatch */
136*32012Smarc #include "../h/dir.h"		/* for directory handling */
137*32012Smarc #include "../h/user.h"		/* user structure (what else?) */
138*32012Smarc #include "../ultrix/qdioctl.h" 		/* ioctl call values */
139*32012Smarc #include "../h/tty.h"
140*32012Smarc #include "../h/map.h"		/* resource allocation map struct */
141*32012Smarc #include "../h/buf.h"		/* buf structs */
142*32012Smarc #include "../h/vm.h"		/* includes 'vm' header files */
143*32012Smarc #include "../h/clist.h" 	/* char list handling structs */
144*32012Smarc #include "../h/file.h"		/* file I/O definitions */
145*32012Smarc #include "../h/uio.h"		/* write/read call structs */
146*32012Smarc #include "../h/kernel.h"	/* clock handling structs */
147*32012Smarc #include "../vax/cpu.h" 	/* per cpu (pcpu) struct */
148*32012Smarc 
149*32012Smarc #include "../vaxuba/ubareg.h"	/* uba & 'qba' register structs */
150*32012Smarc #include "../vaxuba/ubavar.h"	/* uba structs & uba map externs */
151*32012Smarc #include "../h/syslog.h"
152*32012Smarc 
153*32012Smarc #include "../ultrix/qduser.h"	/* definitions shared with my client */
154*32012Smarc #include "../ultrix/qdreg.h"	/* QDSS device register structures */
155*32012Smarc 
156*32012Smarc /*
157*32012Smarc * QDSS driver status flags for tracking operational state
158*32012Smarc */
159*32012Smarc 
160*32012Smarc struct qdflags {
161*32012Smarc 
162*32012Smarc     u_int inuse;	    /* which minor dev's are in use now */
163*32012Smarc     u_int config;	    /* I/O page register content */
164*32012Smarc     u_int mapped;	    /* user mapping status word */
165*32012Smarc     u_int kernel_loop;	    /* if kernel console is redirected */
166*32012Smarc     u_int user_dma;	    /* DMA from user space in progress */
167*32012Smarc     u_short pntr_id;	    /* type code of pointing device */
168*32012Smarc     u_short duart_imask;    /* shadowing for duart intrpt mask reg */
169*32012Smarc     u_short adder_ie;	    /* shadowing for adder intrpt enbl reg */
170*32012Smarc     u_short curs_acc;	    /* cursor acceleration factor */
171*32012Smarc     u_short curs_thr;	    /* cursor acceleration threshold level */
172*32012Smarc     u_short tab_res;	    /* tablet resolution factor */
173*32012Smarc     u_short selmask;	    /* mask for active qd select entries */
174*32012Smarc };
175*32012Smarc 
176*32012Smarc /* bit definitions for "inuse" entry  */
177*32012Smarc 
178*32012Smarc #define CONS_DEV	0x01
179*32012Smarc #define ALTCONS_DEV	0x02
180*32012Smarc #define GRAPHIC_DEV	0x04
181*32012Smarc 
182*32012Smarc /* bit definitions for 'mapped' member of flag structure */
183*32012Smarc 
184*32012Smarc #define MAPDEV		0x01		/* hardware is mapped */
185*32012Smarc #define MAPDMA		0x02		/* DMA buffer mapped */
186*32012Smarc #define MAPEQ		0x04		/* event queue buffer mapped */
187*32012Smarc #define MAPSCR		0x08		/* scroll param area mapped */
188*32012Smarc #define MAPCOLOR	0x10		/* color map writing buffer mapped */
189*32012Smarc 
190*32012Smarc /* bit definitions for 'selmask' member of qdflag structure */
191*32012Smarc 
192*32012Smarc #define SEL_READ	0x01		/* read select is active */
193*32012Smarc #define SEL_WRITE	0x02		/* write select is active */
194*32012Smarc 
195*32012Smarc /*
196*32012Smarc * constants used in shared memory operations
197*32012Smarc */
198*32012Smarc 
199*32012Smarc #define EVENT_BUFSIZE  1024	/* # of bytes per device's event buffer */
200*32012Smarc 
201*32012Smarc #define MAXEVENTS  ( (EVENT_BUFSIZE - sizeof(struct qdinput))	 \
202*32012Smarc 		     / sizeof(struct _vs_event) )
203*32012Smarc 
204*32012Smarc #define DMA_BUFSIZ	(1024 * 3)
205*32012Smarc 
206*32012Smarc #define COLOR_BUFSIZ  ((sizeof(struct color_buf) + 512) & ~0x01FF)
207*32012Smarc 
208*32012Smarc 
209*32012Smarc 
210*32012Smarc /*
211*32012Smarc * reference to an array of "uba_device" structures built by the auto
212*32012Smarc * configuration program.  The uba_device structure decribes the device
213*32012Smarc * sufficiently for the driver to talk to it.  The auto configuration code
214*32012Smarc * fills in the uba_device structures (located in ioconf.c) from user
215*32012Smarc * maintained info.
216*32012Smarc */
217*32012Smarc 
218*32012Smarc struct uba_device *qdinfo[NQD];  /* array of pntrs to each QDSS's */
219*32012Smarc 				 /* uba structures  */
220*32012Smarc struct tty qd_tty[NQD*4];	/* teletype structures for each.. */
221*32012Smarc 				/* ..possible minor device */
222*32012Smarc 
223*32012Smarc struct qd_softc qd_softc[NQD];
224*32012Smarc 
225*32012Smarc /*
226*32012Smarc * static storage used by multiple functions in this code
227*32012Smarc */
228*32012Smarc 
229*32012Smarc int Qbus_unmap[NQD];		/* Qbus mapper release code */
230*32012Smarc struct qdflags qdflags[NQD];	/* QDSS device status flags */
231*32012Smarc struct qdmap qdmap[NQD];	/* QDSS register map structure */
232*32012Smarc caddr_t qdbase[NQD];		/* base address of each QDSS unit */
233*32012Smarc struct buf qdbuf[NQD];		/* buf structs used by strategy */
234*32012Smarc char one_only[NQD];		/* lock for single process access */
235*32012Smarc 
236*32012Smarc /*
237*32012Smarc * The array "event_shared[]" is made up of a number of event queue buffers
238*32012Smarc * equal to the number of QDSS's configured into the running kernel (NQD).
239*32012Smarc * Each event queue buffer begins with an event queue header (struct qdinput)
240*32012Smarc * followed by a group of event queue entries (struct _vs_event).  The array
241*32012Smarc * "*eq_header[]" is an array of pointers to the start of each event queue
242*32012Smarc * buffer in "event_shared[]".
243*32012Smarc */
244*32012Smarc 
245*32012Smarc #define EQSIZE ((EVENT_BUFSIZE * NQD) + 512)
246*32012Smarc 
247*32012Smarc char event_shared[EQSIZE];	    /* reserve space for event bufs */
248*32012Smarc struct qdinput *eq_header[NQD];     /* event queue header pntrs */
249*32012Smarc 
250*32012Smarc /*
251*32012Smarc * This allocation method reserves enough memory pages for NQD shared DMA I/O
252*32012Smarc * buffers.  Each buffer must consume an integral number of memory pages to
253*32012Smarc * guarantee that a following buffer will begin on a page boundary.  Also,
254*32012Smarc * enough space is allocated so that the FIRST I/O buffer can start at the
255*32012Smarc * 1st page boundary after "&DMA_shared".  Page boundaries are used so that
256*32012Smarc * memory protections can be turned on/off for individual buffers.
257*32012Smarc */
258*32012Smarc 
259*32012Smarc #define IOBUFSIZE  ((DMA_BUFSIZ * NQD) + 512)
260*32012Smarc 
261*32012Smarc char DMA_shared[IOBUFSIZE];	    /* reserve I/O buffer space */
262*32012Smarc struct DMAreq_header *DMAheader[NQD];  /* DMA buffer header pntrs */
263*32012Smarc 
264*32012Smarc /*
265*32012Smarc * The driver assists a client in scroll operations by loading dragon
266*32012Smarc * registers from an interrupt service routine.	The loading is done using
267*32012Smarc * parameters found in memory shrade between the driver and it's client.
268*32012Smarc * The scroll parameter structures are ALL loacted in the same memory page
269*32012Smarc * for reasons of memory economy.
270*32012Smarc */
271*32012Smarc 
272*32012Smarc char scroll_shared[2 * 512];	/* reserve space for scroll structs */
273*32012Smarc struct scroll *scroll[NQD];	/* pointers to scroll structures */
274*32012Smarc 
275*32012Smarc /*
276*32012Smarc * the driver is programmable to provide the user with color map write
277*32012Smarc * services at VSYNC interrupt time.  At interrupt time the driver loads
278*32012Smarc * the color map with any user-requested load data found in shared memory
279*32012Smarc */
280*32012Smarc 
281*32012Smarc #define COLOR_SHARED  ((COLOR_BUFSIZ * NQD) + 512)
282*32012Smarc 
283*32012Smarc char color_shared[COLOR_SHARED];      /* reserve space: color bufs */
284*32012Smarc struct color_buf *color_buf[NQD];     /* pointers to color bufs */
285*32012Smarc 
286*32012Smarc /*
287*32012Smarc * mouse input event structures
288*32012Smarc */
289*32012Smarc 
290*32012Smarc struct mouse_report last_rep[NQD];
291*32012Smarc struct mouse_report current_rep[NQD];
292*32012Smarc 
293*32012Smarc /*
294*32012Smarc * input event "select" use
295*32012Smarc */
296*32012Smarc 
297*32012Smarc struct proc *rsel[NQD]; 	/* process waiting for select */
298*32012Smarc 
299*32012Smarc /*
300*32012Smarc * console cursor structure
301*32012Smarc */
302*32012Smarc 
303*32012Smarc struct _vs_cursor cursor[NQD];
304*32012Smarc 
305*32012Smarc 
306*32012Smarc 
307*32012Smarc int nNQD = NQD;
308*32012Smarc 
309*32012Smarc int DMAbuf_size = DMA_BUFSIZ;
310*32012Smarc 
311*32012Smarc 
312*32012Smarc /*
313*32012Smarc  * macro to get system time.  Used to time stamp event queue entries
314*32012Smarc  */
315*32012Smarc 
31630391Skarels #define TOY ((time.tv_sec * 100) + (time.tv_usec / 10000))
31730391Skarels 
318*32012Smarc /*
31930391Skarels * the "ioconf.c" program, built and used by auto config, externally refers
320*32012Smarc * to definitions below.
321*32012Smarc */
32230391Skarels 
323*32012Smarc int qdprobe();
324*32012Smarc int qdattach();
325*32012Smarc int qddint();			/* DMA gate array intrpt service */
326*32012Smarc int qdaint();			/* Dragon ADDER intrpt service */
327*32012Smarc int qdiint();
32830391Skarels 
329*32012Smarc u_short qdstd[] = { 0 };
33030391Skarels 
331*32012Smarc struct uba_driver qddriver = {	/* externally referenced: ioconf.c */
33230391Skarels 
333*32012Smarc     qdprobe,			/* device probe entry */
334*32012Smarc     0,				/* no slave device */
335*32012Smarc     qdattach,			/* device attach entry */
336*32012Smarc     0,				/* no "fill csr/ba to start" */
337*32012Smarc     qdstd,			/* device addresses */
338*32012Smarc     "qd",			/* device name string */
339*32012Smarc     qdinfo			/* ptr to QDSS's uba_device struct */
340*32012Smarc };
34130391Skarels 
342*32012Smarc extern	char qvmem[][128*NBPG];
343*32012Smarc extern	struct pte QVmap[][128];
344*32012Smarc 
345*32012Smarc /*
346*32012Smarc  * v_putc is used to redirect the console cnputc to the virtual console
347*32012Smarc  * vputc.  consops is used to direct the console device to the qvss console.
348*32012Smarc  */
349*32012Smarc extern (*v_putc)();
350*32012Smarc extern struct cdevsw *consops;
351*32012Smarc 
352*32012Smarc /*
35330391Skarels * general defines */
35430391Skarels 
35530391Skarels #define QDPRIOR (PZERO-1)		/* must be negative */
35630391Skarels 
35730391Skarels #define FALSE	0
35830391Skarels #define TRUE	~FALSE
35930391Skarels 
36030391Skarels #define BAD	-1
36130391Skarels #define GOOD	0
36230391Skarels 
363*32012Smarc /*
364*32012Smarc  * Macro to create a system virtual page number from system virtual adrs.
365*32012Smarc  */
36630391Skarels 
367*32012Smarc #define VTOP(x)  (((int)x & ~0xC0000000) >> PGSHIFT)
36830391Skarels 
369*32012Smarc /*
370*32012Smarc  * QDSS register address offsets from start of QDSS address space
371*32012Smarc  */
37230391Skarels 
37330391Skarels #define QDSIZE	 (52 * 1024)	/* size of entire QDSS foot print */
37430391Skarels 
37530391Skarels #define TMPSIZE  (16 * 1024)	/* template RAM is 8k SHORT WORDS */
37630391Skarels #define TMPSTART 0x8000 	/* offset of template RAM from base adrs */
37730391Skarels 
37830391Skarels #define REGSIZE  (5 * 512)	/* regs touch 2.5k (5 pages) of addr space */
37930391Skarels #define REGSTART 0xC000 	/* offset of reg pages from base adrs */
38030391Skarels 
38130391Skarels #define ADDER	(REGSTART+0x000)
38230391Skarels #define DGA	(REGSTART+0x200)
38330391Skarels #define DUART	(REGSTART+0x400)
38430391Skarels #define MEMCSR	(REGSTART+0x800)
38530391Skarels 
38630391Skarels #define CLRSIZE  (3 * 512)		/* color map size */
38730391Skarels #define CLRSTART (REGSTART+0xA00)	/* color map start offset from base */
38830391Skarels 					/*  0x0C00 really */
38930391Skarels #define RED	(CLRSTART+0x000)
39030391Skarels #define BLUE	(CLRSTART+0x200)
39130391Skarels #define GREEN	(CLRSTART+0x400)
39230391Skarels 
393*32012Smarc /*
394*32012Smarc  * Values used in mapping QDSS hardware into the Q memory space.
395*32012Smarc  */
39630391Skarels 
39730391Skarels #define CHUNK	  (64 * 1024)
398*32012Smarc #define QMEMSIZE  (1024 * 1024 * 4)
39930391Skarels 
400*32012Smarc /*
40130391Skarels * QDSS minor device numbers.  The *real* minor device numbers are in
40230391Skarels * the bottom two bits of the major/minor device spec.  Bits 2 and up are
403*32012Smarc * used to specify the QDSS device number (ie: which one?)
404*32012Smarc */
40530391Skarels 
406*32012Smarc #define QDSSMAJOR	41		/* QDSS major device number */
40730391Skarels 
40830391Skarels #define CONS		0
40930391Skarels #define ALTCONS 	1
41030391Skarels #define GRAPHIC 	2
41130391Skarels 
412*32012Smarc /*
413*32012Smarc  * console cursor bitmap (block cursor type)
414*32012Smarc  */
41530391Skarels 
41630391Skarels 	short cons_cursor[32] = {      /* white block cursor */
41730391Skarels 
41830391Skarels  /* A */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
41930391Skarels 	 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
42030391Skarels  /* B */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
42130391Skarels 	 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF
42230391Skarels 
42330391Skarels 	};
42430391Skarels 
425*32012Smarc /*
426*32012Smarc  * constants used in font operations
427*32012Smarc  */
42830391Skarels 
42930391Skarels #define CHARS		95			/* # of chars in the font */
43030391Skarels #define CHAR_HEIGHT	15			/* char height in pixels */
43130391Skarels #define CHAR_WIDTH	8			/* char width in pixels*/
43230391Skarels #define FONT_WIDTH	(CHAR_WIDTH * CHARS)	/* font width in pixels */
43330391Skarels #define ROWS		CHAR_HEIGHT
43430391Skarels 
43530391Skarels 
43630391Skarels #define FONT_X		0			/* font's off screen adrs */
43730391Skarels #define FONT_Y		(2048 - CHAR_HEIGHT)
43830391Skarels /*
43930391Skarels #define FONT_Y		200
44030391Skarels */
44130391Skarels 
442*32012Smarc extern char q_font[];		/* reference font object code */
44330391Skarels 
444*32012Smarc extern	char q_key[];		/* reference key xlation tables */
445*32012Smarc extern	char q_shift_key[];
446*32012Smarc extern	char *q_special[];
44730391Skarels 
448*32012Smarc /*
449*32012Smarc  * definitions for cursor acceleration reporting
450*32012Smarc  */
45130391Skarels 
45230391Skarels #define ACC_OFF 	0x01		/* acceleration is inactive */
45330391Skarels 
454*32012Smarc int qdputc();		/* used to direct kernel console output *
455*32012Smarc int qdstart();		/* used to direct /dev/console output *
45630391Skarels 
457*32012Smarc /*
458*32012Smarc  * LK-201 state storage for input console keyboard conversion to ASCII
459*32012Smarc  */
46030391Skarels 
461*32012Smarc struct q_keyboard {
46230391Skarels 
463*32012Smarc     int shift;			/* state variables	*/
464*32012Smarc     int cntrl;
465*32012Smarc     int lock;
466*32012Smarc     int lastcode;		/* last keycode typed	*/
467*32012Smarc     unsigned kup[8];		/* bits for each keycode*/
468*32012Smarc     unsigned dkeys[8];		/* down/up mode keys	*/
469*32012Smarc     char last;			/* last character	*/
47030391Skarels 
471*32012Smarc  } q_keyboard;
47230391Skarels 
47330391Skarels 
474*32012Smarc /*
47530391Skarels *
476*32012Smarc *	DRIVER FUNCTIONS :
47730391Skarels *
478*32012Smarc */
47930391Skarels 
48030391Skarels /*********************************************************************
48130391Skarels *
48230391Skarels *	qdcons_init()... init QDSS as console (before probe routine)
48330391Skarels *
48430391Skarels *********************************************************************/
48530391Skarels 
48630391Skarels qdcons_init()
48730391Skarels {
48830391Skarels 	register u_int unit;
48930391Skarels 
490*32012Smarc 	struct percpu *pcpu;		/* pointer to percpu structure */
491*32012Smarc 	register struct qbus *qb;
49230391Skarels 	int *ptep;			/* page table entry pointer */
49330391Skarels 	caddr_t phys_adr;		/* physical QDSS base adrs */
49430391Skarels 	u_int mapix;			/* index into QMEMmap[] array */
49530391Skarels 
49630391Skarels 	u_short *qdaddr;		/* address of QDSS IO page CSR */
49730391Skarels 	u_short *devptr;		/* vitual device space */
498*32012Smarc 	extern	cnputc();		/* standard serial console putc */
49930391Skarels 
50030391Skarels #define QDSSCSR 0x1F00
50130391Skarels 
502*32012Smarc 	/*
503*32012Smarc 	 * if console already configured, dont do again.
504*32012Smarc 	 */
505*32012Smarc 	if (v_putc != cnputc)
506*32012Smarc 		return;
507*32012Smarc 
50830391Skarels 	unit = 0;
50930391Skarels 
510*32012Smarc 	/*
511*32012Smarc 	 * find the cpusw entry that matches this machine.
512*32012Smarc 	 */
51330391Skarels 
514*32012Smarc 	for (pcpu = percpu; pcpu && pcpu->pc_cputype != cpu; pcpu++)
515*32012Smarc 		;
516*32012Smarc 	if (pcpu == NULL)
517*32012Smarc 		return;
51830391Skarels 
51930391Skarels 
520*32012Smarc 	/*
521*32012Smarc 	 * Map device registers - the last 8K of umem.
522*32012Smarc 	 */
523*32012Smarc 	qb = (struct qbus *)pcpu->pc_io->io_details;
524*32012Smarc 	ioaccess(qb->qb_iopage, UMEMmap[0] + qb->qb_memsize,
525*32012Smarc 		UBAIOPAGES * NBPG);
52630391Skarels 
527*32012Smarc 	devptr = (u_short *)((char *)umem[0]+(qb->qb_memsize * NBPG));
52830391Skarels 	qdaddr = (u_short *)((u_int)devptr + ubdevreg(QDSSCSR));
529*32012Smarc 	if (badaddr(qdaddr, sizeof(short)))  {
530*32012Smarc 		log(LOG_ERR, "Can't find qdss (badaddr)\n"); /* debug */
53130391Skarels 		return(0);
532*32012Smarc 	}
533*32012Smarc 	/*
534*32012Smarc 	 * Map q-bus memory used by qdss. (separate map)
535*32012Smarc 	 */
536*32012Smarc 	mapix = QMEMSIZE - (CHUNK * (unit + 1));
537*32012Smarc 	phys_adr = qb->qb_maddr + mapix;
538*32012Smarc 	ioaccess(phys_adr, QVmap[0], (CHUNK*NQD));
53930391Skarels 
540*32012Smarc 	/*
541*32012Smarc 	 * tell QDSS which Q memory address base to decode
542*32012Smarc 	 */
54330391Skarels 
544*32012Smarc 	/*
545*32012Smarc 	 * shifted right 16 bits - its in 64K units
546*32012Smarc 	 */
547*32012Smarc 	*qdaddr = (u_short)((int)mapix >> 16);
54830391Skarels 	qdflags[unit].config = *(u_short *)qdaddr;
54930391Skarels 
550*32012Smarc 	/*
551*32012Smarc 	 * load qdmap struct with the virtual addresses of the QDSS elements
552*32012Smarc 	 */
55330391Skarels 
554*32012Smarc 	qdbase[unit] = (caddr_t) qvmem[0];
55530391Skarels 
55630391Skarels 	qdmap[unit].template = qdbase[unit] + TMPSTART;
55730391Skarels 	qdmap[unit].adder = qdbase[unit] + ADDER;
55830391Skarels 	qdmap[unit].dga = qdbase[unit] + DGA;
55930391Skarels 	qdmap[unit].duart = qdbase[unit] + DUART;
56030391Skarels 	qdmap[unit].memcsr = qdbase[unit] + MEMCSR;
56130391Skarels 	qdmap[unit].red = qdbase[unit] + RED;
56230391Skarels 	qdmap[unit].blue = qdbase[unit] + BLUE;
56330391Skarels 	qdmap[unit].green = qdbase[unit] + GREEN;
56430391Skarels 
56530391Skarels 	qdflags[unit].duart_imask = 0;	/* init shadow variables */
56630391Skarels 
567*32012Smarc 	/*
568*32012Smarc 	 * init the QDSS
569*32012Smarc 	 */
57030391Skarels 
571*32012Smarc 	/***
572*32012Smarc 	printf("qdbase[0] = %x, qdmap[0].memcsr = %x\n",
573*32012Smarc 		(char *)qdbase[0], qdmap[0].memcsr);
574*32012Smarc 	***/
575*32012Smarc 
57630391Skarels 	*(short *)qdmap[unit].memcsr |= SYNC_ON; /* once only: turn on sync */
57730391Skarels 
57830391Skarels 	cursor[unit].x = 0;
57930391Skarels 	cursor[unit].y = 0;
58030391Skarels 	init_shared(unit);		/* init shared memory */
58130391Skarels 	setup_dragon(unit);		/* init the ADDER/VIPER stuff */
58230391Skarels 	clear_qd_screen(unit);		/* clear the screen */
58330391Skarels 	ldfont(unit);			/* load the console font */
58430391Skarels 	ldcursor(unit, cons_cursor);	/* load default cursor map */
58530391Skarels 	setup_input(unit);		/* init the DUART */
58630391Skarels 
587*32012Smarc 	v_putc = qdputc;
588*32012Smarc 	consops = &cdevsw[QDSSMAJOR];
58930391Skarels 
59030391Skarels 	return(1);
59130391Skarels 
59230391Skarels } /* qdcons_init */
59330391Skarels 
59430391Skarels /*********************************************************************
59530391Skarels *
59630391Skarels *	qdprobe()... configure QDSS into Q memory and make it intrpt
59730391Skarels *
59830391Skarels **********************************************************************
59930391Skarels *
60030391Skarels *  calling convention:
60130391Skarels *			qdprobe(reg, ctlr);
60230391Skarels *			caddr_t reg;
60330391Skarels *			int ctlr;
60430391Skarels *
60530391Skarels *	where: reg - a character pointer to the QDSS I/O page register
60630391Skarels *	       ctlr - controller number (?)
60730391Skarels *
60830391Skarels *  side effects: QDSS gets mapped into Qbus memory space at the first
60930391Skarels *		 vacant 64kb boundary counting back from the top of
61030391Skarels *		 Qbus memory space (qmem+4mb)
61130391Skarels *
61230391Skarels *  return: QDSS bus request level and vector address returned in
61330391Skarels *	   registers by UNIX convention.
61430391Skarels *
61530391Skarels *****************/
61630391Skarels 
61730391Skarels qdprobe(reg)
61830391Skarels caddr_t reg;
61930391Skarels {
620*32012Smarc 	register int br, cvec; 	/* value-result */
62130391Skarels 
62230391Skarels 	register int unit;
62330391Skarels 
62430391Skarels 	struct dga *dga;		/* pointer to gate array structure */
62530391Skarels 	struct cpusw *cpup;		/* pointer to the cpusw structure */
62630391Skarels 
62730391Skarels 	int *ptep;			/* page table entry pointer */
62830391Skarels 	int vector;
62930391Skarels 
63030391Skarels 	caddr_t phys_adr;		/* physical QDSS base adrs */
63130391Skarels 	u_int mapix;
63230391Skarels 
633*32012Smarc #ifdef lint
634*32012Smarc 	br = 0; cvec = br; br = cvec;
635*32012Smarc #endif
63630391Skarels 
637*32012Smarc 	/*
638*32012Smarc 	* calculate board unit number from I/O page register address
639*32012Smarc 	*/
640*32012Smarc 
64130391Skarels 	unit = (int) (((int)reg >> 1) & 0x0007);
64230391Skarels 
643*32012Smarc /*
64430391Skarels * QDSS regs must be mapped to Qbus memory space at a 64kb physical boundary.
64530391Skarels * The Qbus memory space is mapped into the system memory space at config
64630391Skarels * time.  After config runs, "qmem[0]" (ubavar.h) holds the system virtual adrs
64730391Skarels * of the start of Qbus memory.	The Qbus memory page table is found via
64830391Skarels * an array of pte ptrs called "QMEMmap[]" (ubavar.h) which is also loaded at
64930391Skarels * config time.	These are the variables used below to find a vacant 64kb
65030391Skarels * boundary in Qbus memory, and load it's corresponding physical adrs into
651*32012Smarc * the QDSS's I/O page CSR.
652*32012Smarc */
65330391Skarels 
65430391Skarels 	/* if this QDSS is NOT the console, then do init here.. */
65530391Skarels 
656*32012Smarc 	/****** NOT FOR NOW - DO LATER (FARKLE) ***/
657*32012Smarc #ifdef notdef
65830391Skarels 	if (v_consputc != qdputc  ||  unit != 0) {
65930391Skarels 
660*32012Smarc 	    /*
661*32012Smarc 	     * read QDSS config info
662*32012Smarc 	     */
66330391Skarels 	    qdflags[unit].config = *(u_short *)reg;
66430391Skarels 
665*32012Smarc 	    /*
666*32012Smarc 	     * find an empty 64kb adrs boundary
667*32012Smarc 	     */
66830391Skarels 	    qdbase[unit] = (caddr_t) (qmem[0] + QMEMSIZE - CHUNK);
66930391Skarels 
670*32012Smarc 	    /*
671*32012Smarc 	     * find the cpusw entry that matches this machine.
672*32012Smarc 	     */
67330391Skarels 	    cpup = &cpusw[cpu];
67430391Skarels 	    while ( !(BADADDR(qdbase[unit], sizeof(short))) )
67530391Skarels 		qdbase[unit] -= CHUNK;
67630391Skarels 
677*32012Smarc 	    /*
678*32012Smarc 	     * tell QDSS which Q memory address base to decode
679*32012Smarc 	     */
68030391Skarels 	    mapix = (int) (VTOP(qdbase[unit]) - VTOP(qmem[0]));
68130391Skarels 	    ptep = (int *) QMEMmap[0] + mapix;
68230391Skarels 	    phys_adr = (caddr_t) (((int)*ptep & 0x001FFFFF) << PGSHIFT);
68330391Skarels 	    *(u_short *)reg = (u_short) ((int)phys_adr >> 16);
68430391Skarels 
685*32012Smarc 	    /*
686*32012Smarc 	     * load QDSS adrs map with system addresses of device regs
687*32012Smarc 	     */
68830391Skarels 	    qdmap[unit].template = qdbase[unit] + TMPSTART;
68930391Skarels 	    qdmap[unit].adder = qdbase[unit] + ADDER;
69030391Skarels 	    qdmap[unit].dga = qdbase[unit] + DGA;
69130391Skarels 	    qdmap[unit].duart = qdbase[unit] + DUART;
69230391Skarels 	    qdmap[unit].memcsr = qdbase[unit] + MEMCSR;
69330391Skarels 	    qdmap[unit].red = qdbase[unit] + RED;
69430391Skarels 	    qdmap[unit].blue = qdbase[unit] + BLUE;
69530391Skarels 	    qdmap[unit].green = qdbase[unit] + GREEN;
69630391Skarels 
69730391Skarels 	    /* device init */
69830391Skarels 
69930391Skarels 	    cursor[unit].x = 0;
70030391Skarels 	    cursor[unit].y = 0;
70130391Skarels 	    init_shared(unit);		/* init shared memory */
70230391Skarels 	    setup_dragon(unit); 	/* init the ADDER/VIPER stuff */
70330391Skarels 	    ldcursor(unit, cons_cursor);	/* load default cursor map */
70430391Skarels 	    setup_input(unit);		/* init the DUART */
70530391Skarels 	    clear_qd_screen(unit);
70630391Skarels 	    ldfont(unit);			/* load the console font */
70730391Skarels 
70830391Skarels 	    /* once only: turn on sync */
70930391Skarels 
71030391Skarels 	    *(short *)qdmap[unit].memcsr |= SYNC_ON;
71130391Skarels 	}
712*32012Smarc #endif notdef
71330391Skarels 
714*32012Smarc /*
715*32012Smarc  * the QDSS interrupts at HEX vectors xx0 (DMA) xx4 (ADDER) and xx8 (DUART).
716*32012Smarc  * Therefore, we take three vectors from the vector pool, and then continue
717*32012Smarc  * to take them until we get a xx0 HEX vector.  The pool provides vectors
718*32012Smarc  * in contiguous decending order.
719*32012Smarc  */
72030391Skarels 
72130391Skarels 	vector = (uba_hd[0].uh_lastiv -= 4*3);	/* take three vectors */
72230391Skarels 
72330391Skarels 	while (vector & 0x0F) { 		   /* if lo nibble != 0.. */
72430391Skarels 	    vector = (uba_hd[0].uh_lastiv -= 4);  /* ..take another vector */
72530391Skarels 	}
72630391Skarels 
727*32012Smarc 	/*
728*32012Smarc 	 * setup DGA to do a DMA interrupt (transfer count = 0)
729*32012Smarc 	 */
73030391Skarels 
73130391Skarels 	dga = (struct dga *) qdmap[unit].dga;
73230391Skarels 
73330391Skarels 	dga->csr = (short) HALT;	      /* disable everything */
73430391Skarels 	dga->ivr = (short) vector;	      /* load intrpt base vector */
73530391Skarels 	dga->bytcnt_lo = (short) 0;	      /* DMA xfer count = 0 */
73630391Skarels 	dga->bytcnt_hi = (short) 0;
73730391Skarels 
73830391Skarels 	/* turn on DMA interrupts */
73930391Skarels 
74030391Skarels 	dga->csr &= ~SET_DONE_FIFO;
74130391Skarels 	dga->csr |= DMA_IE | DL_ENB;
74230391Skarels 
74330391Skarels 	DELAY(20000);			/* wait for the intrpt */
74430391Skarels 
74530391Skarels 	dga->csr = HALT;		/* stop the wheels */
74630391Skarels 
74730391Skarels 	if (cvec != vector)		/* if vector != base vector.. */
74830391Skarels 	    return(0);			/* ..return = 'no device' */
74930391Skarels 
75030391Skarels 	return(sizeof(short));	    /* return size of QDSS I/O page reg */
75130391Skarels 
75230391Skarels } /* qdprobe */
75330391Skarels 
75430391Skarels /*****************************************************************
75530391Skarels *
75630391Skarels *	qdattach()... do the one-time initialization
75730391Skarels *
75830391Skarels ******************************************************************
75930391Skarels *
76030391Skarels *  calling convention:
76130391Skarels *			qdattach(ui);
76230391Skarels *			struct uba_device *ui;
76330391Skarels *
76430391Skarels *		where: ui - pointer to the QDSS's uba_device structure
76530391Skarels *
76630391Skarels *  side effects: none
76730391Skarels *	 return: none
76830391Skarels *
76930391Skarels *************************/
77030391Skarels 
77130391Skarels qdattach(ui)
77230391Skarels struct uba_device *ui;
77330391Skarels {
77430391Skarels 	register u_int unit;		/* QDSS module # for this call */
77530391Skarels 
77630391Skarels 	unit = ui->ui_unit;		/* get QDSS number */
77730391Skarels 
778*32012Smarc /*
779*32012Smarc * init "qdflags[]" for this QDSS
780*32012Smarc */
78130391Skarels 
78230391Skarels 	qdflags[unit].inuse = 0;	/* init inuse variable EARLY! */
78330391Skarels 	qdflags[unit].mapped = 0;
78430391Skarels 	qdflags[unit].kernel_loop = 0;
78530391Skarels 	qdflags[unit].user_dma = 0;
78630391Skarels 	qdflags[unit].curs_acc = ACC_OFF;
78730391Skarels 	qdflags[unit].curs_thr = 128;
78830391Skarels 	qdflags[unit].tab_res = 2;	/* default tablet resolution factor */
78930391Skarels 	qdflags[unit].duart_imask = 0;	/* init shadow variables */
79030391Skarels 	qdflags[unit].adder_ie = 0;
79130391Skarels 
792*32012Smarc /*
79330391Skarels * init structures used in kbd/mouse interrupt service.	This code must
79430391Skarels * come after the "init_shared()" routine has run since that routine inits
795*32012Smarc * the eq_header[unit] structure used here.
796*32012Smarc */
79730391Skarels 
798*32012Smarc 	/*
799*32012Smarc 	* init the "latest mouse report" structure
800*32012Smarc 	*/
80130391Skarels 
80230391Skarels 	last_rep[unit].state = 0;
80330391Skarels 	last_rep[unit].dx = 0;
80430391Skarels 	last_rep[unit].dy = 0;
80530391Skarels 	last_rep[unit].bytcnt = 0;
80630391Skarels 
80730391Skarels 	/*------------------------------------------------
80830391Skarels 	* init the event queue (except mouse position) */
80930391Skarels 
81030391Skarels 	eq_header[unit]->header.events = (struct _vs_event *)
81130391Skarels 					  ((int)eq_header[unit]
81230391Skarels 					   + sizeof(struct qdinput));
81330391Skarels 
81430391Skarels 	eq_header[unit]->header.size = MAXEVENTS;
81530391Skarels 	eq_header[unit]->header.head = 0;
81630391Skarels 	eq_header[unit]->header.tail = 0;
81730391Skarels 
818*32012Smarc 	/*
819*32012Smarc 	* init single process access lock switch
820*32012Smarc 	*/
82130391Skarels 
82230391Skarels 	one_only[unit] = 0;
82330391Skarels 
82430391Skarels } /* qdattach */
82530391Skarels 
82630391Skarels /***************************************************************
82730391Skarels *
82830391Skarels *	qdopen()... open a minor device
82930391Skarels *
83030391Skarels ****************************************************************
83130391Skarels *
83230391Skarels *  calling convention: qdopen(dev, flag);
83330391Skarels *		       dev_t dev;
83430391Skarels *		       int flag;
83530391Skarels *
83630391Skarels *  side effects: none
83730391Skarels *
83830391Skarels *********************/
83930391Skarels 
84030391Skarels qdopen(dev, flag)
84130391Skarels dev_t dev;
84230391Skarels int flag;
84330391Skarels {
84430391Skarels 	register struct uba_device *ui; /* ptr to uba structures */
84530391Skarels 	register struct dga *dga;	/* ptr to gate array struct */
84630391Skarels 	register struct tty *tp;
847*32012Smarc 	int qdstart();
84830391Skarels 
84930391Skarels 	struct adder *adder;
85030391Skarels 	struct duart *duart;
85130391Skarels 
85230391Skarels 	u_int unit;
85330391Skarels 	u_int minor_dev;
85430391Skarels 	int s;
85530391Skarels 
85630391Skarels 	minor_dev = minor(dev); /* get QDSS minor device number */
85730391Skarels 	unit = minor_dev >> 2;
85830391Skarels 
859*32012Smarc 	/* check for illegal conditions	*/
86030391Skarels 
86130391Skarels 	ui = qdinfo[unit];		/* get ptr to QDSS device struct */
86230391Skarels 
86330391Skarels 	if (ui == 0  || ui->ui_alive == 0)
86430391Skarels 	    return(ENXIO);		/* no such device or address */
86530391Skarels 
866*32012Smarc 	/* init stuff */
86730391Skarels 
86830391Skarels 	adder = (struct adder *) qdmap[unit].adder;
86930391Skarels 	duart = (struct duart *) qdmap[unit].duart;
87030391Skarels 	dga = (struct dga *) qdmap[unit].dga;
87130391Skarels 
872*32012Smarc 	/* if this is the graphic device... */
87330391Skarels 
87430391Skarels 	if ((minor_dev & 0x03) == 2) {
87530391Skarels 
87630391Skarels 	    if (one_only[unit] != 0)
87730391Skarels 		return(EBUSY);
87830391Skarels 	    else
87930391Skarels 		one_only[unit] = 1;
88030391Skarels 
88130391Skarels 	    qdflags[unit].inuse |= GRAPHIC_DEV;  /* graphics dev is open */
88230391Skarels 
88330391Skarels 	    /* enble kbd & mouse intrpts in DUART mask reg */
88430391Skarels 
88530391Skarels 	    qdflags[unit].duart_imask |= 0x22;
88630391Skarels 	    duart->imask = qdflags[unit].duart_imask;
88730391Skarels 
888*32012Smarc 	/*
889*32012Smarc 	 * if the open call is to the console or the alternate console...
890*32012Smarc 	 */
891*32012Smarc 	} else {
89230391Skarels 
89330391Skarels 	    qdflags[unit].inuse |= CONS_DEV;  /* mark console as open */
89430391Skarels 	    dga->csr |= CURS_ENB;
89530391Skarels 
89630391Skarels 	    qdflags[unit].duart_imask |= 0x02;
89730391Skarels 	    duart->imask = qdflags[unit].duart_imask;
89830391Skarels 
89930391Skarels 	    /*-------------------------------
90030391Skarels 	    * some setup for tty handling */
90130391Skarels 
90230391Skarels 	    tp = &qd_tty[minor_dev];
90330391Skarels 
90430391Skarels 	    tp->t_addr = ui->ui_addr;
90530391Skarels 	    tp->t_oproc = qdstart;
90630391Skarels 
90730391Skarels 	    if ((tp->t_state & TS_ISOPEN) == 0) {
90830391Skarels 
90930391Skarels 		ttychars(tp);
91030391Skarels 		tp->t_state = TS_ISOPEN | TS_CARR_ON;
91130391Skarels 		tp->t_ispeed = B9600;
91230391Skarels 		tp->t_ospeed = B9600;
91330391Skarels 
914*32012Smarc 		if( (minor_dev & 0x03) == 0 ) {
91530391Skarels 		    tp->t_flags = XTABS|EVENP|ECHO|CRMOD;
916*32012Smarc 		}
917*32012Smarc 		else {
91830391Skarels 		    tp->t_flags = RAW;
919*32012Smarc 		}
92030391Skarels 	    }
92130391Skarels 
92230391Skarels 	    /*----------------------------------------
92330391Skarels 	    * enable intrpts, open line discipline */
92430391Skarels 
92530391Skarels 	    dga->csr |= GLOBAL_IE;	/* turn on the interrupts */
92630391Skarels 	    return ((*linesw[tp->t_line].l_open)(dev, tp));
92730391Skarels 	}
92830391Skarels 
92930391Skarels 	dga->csr |= GLOBAL_IE;	/* turn on the interrupts */
93030391Skarels 	return(0);
93130391Skarels 
93230391Skarels } /* qdopen */
93330391Skarels 
93430391Skarels /***************************************************************
93530391Skarels *
93630391Skarels *	qdclose()... clean up on the way out
93730391Skarels *
93830391Skarels ****************************************************************
93930391Skarels *
94030391Skarels *  calling convention: qdclose();
94130391Skarels *
94230391Skarels *  side effects: none
94330391Skarels *
94430391Skarels *  return: none
94530391Skarels *
94630391Skarels *********************/
94730391Skarels 
94830391Skarels qdclose(dev, flag)
94930391Skarels dev_t dev;
95030391Skarels int flag;
95130391Skarels {
95230391Skarels 	register struct tty *tp;
95330391Skarels 	register struct qdmap *qd;
95430391Skarels 	register int *ptep;
95530391Skarels 	int i;				/* SIGNED index */
95630391Skarels 
95730391Skarels 	struct dga *dga;		/* gate array register map pointer */
95830391Skarels 	struct duart *duart;
95930391Skarels 	struct adder *adder;
96030391Skarels 
96130391Skarels 	u_int unit;
96230391Skarels 	u_int minor_dev;
96330391Skarels 	u_int mapix;
96430391Skarels 
96530391Skarels 	minor_dev = minor(dev); 	/* get minor device number */
96630391Skarels 	unit = minor_dev >> 2;		/* get QDSS number */
96730391Skarels 	qd = &qdmap[unit];
96830391Skarels 
969*32012Smarc 	/*
970*32012Smarc 	 * if this is the graphic device...
971*32012Smarc 	 */
97230391Skarels 
97330391Skarels 	if ((minor_dev & 0x03) == 2) {
97430391Skarels 
97530391Skarels 	    /*-----------------
97630391Skarels 	    * unlock driver */
97730391Skarels 
97830391Skarels 	    if (one_only[unit] != 1)
97930391Skarels 		return(EBUSY);
98030391Skarels 	    else
98130391Skarels 		one_only[unit] = 0;
98230391Skarels 
98330391Skarels 	    /*----------------------------
98430391Skarels 	    * re-protect device memory */
98530391Skarels 
98630391Skarels 	    if (qdflags[unit].mapped & MAPDEV) {
98730391Skarels 
98830391Skarels 		/*----------------
98930391Skarels 		* TEMPLATE RAM */
99030391Skarels 
991*32012Smarc 		mapix = VTOP((int)qd->template) - VTOP(qvmem[0]);
992*32012Smarc 		ptep = (int *)(QVmap[0] + mapix);
99330391Skarels 
99430391Skarels 		for (i = VTOP(TMPSIZE); i > 0; --i)
99530391Skarels 		    *ptep++ = (*ptep & ~PG_PROT) | PG_V | PG_KW;
99630391Skarels 
99730391Skarels 		/*---------
99830391Skarels 		* ADDER */
99930391Skarels 
1000*32012Smarc 		mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]);
1001*32012Smarc 		ptep = (int *)(QVmap[0] + mapix);
100230391Skarels 
100330391Skarels 		for (i = VTOP(REGSIZE); i > 0; --i)
100430391Skarels 		    *ptep++ = (*ptep & ~PG_PROT) | PG_V | PG_KW;
100530391Skarels 
100630391Skarels 		/*--------------
100730391Skarels 		* COLOR MAPS */
100830391Skarels 
1009*32012Smarc 		mapix = VTOP((int)qd->red) - VTOP(qvmem[0]);
1010*32012Smarc 		ptep = (int *)(QVmap[0] + mapix);
101130391Skarels 
101230391Skarels 		for (i = VTOP(CLRSIZE); i > 0; --i)
101330391Skarels 		    *ptep++ = (*ptep & ~PG_PROT) | PG_V | PG_KW;
101430391Skarels 	    }
101530391Skarels 
101630391Skarels 	    /*----------------------------------------------------
101730391Skarels 	    * re-protect DMA buffer and free the map registers */
101830391Skarels 
101930391Skarels 	    if (qdflags[unit].mapped & MAPDMA) {
102030391Skarels 
102130391Skarels 		dga = (struct dga *) qdmap[unit].dga;
102230391Skarels 		adder = (struct adder *) qdmap[unit].adder;
102330391Skarels 
102430391Skarels 		dga->csr &= ~DMA_IE;
102530391Skarels 		dga->csr &= ~0x0600;	     /* kill DMA */
102630391Skarels 		adder->command = CANCEL;
102730391Skarels 
102830391Skarels 		/* if DMA was running, flush spurious intrpt */
102930391Skarels 
103030391Skarels 		if (dga->bytcnt_lo != 0) {
103130391Skarels 		    dga->bytcnt_lo = 0;
103230391Skarels 		    dga->bytcnt_hi = 0;
103330391Skarels 		    DMA_SETIGNORE(DMAheader[unit]);
103430391Skarels 		    dga->csr |= DMA_IE;
103530391Skarels 		    dga->csr &= ~DMA_IE;
103630391Skarels 		}
103730391Skarels 
103830391Skarels 		ptep = (int *)
103930391Skarels 			((VTOP(DMAheader[unit]*4)) + (mfpr(SBR)|0x80000000));
104030391Skarels 
104130391Skarels 		for (i = (DMAbuf_size >> PGSHIFT); i > 0; --i)
104230391Skarels 		    *ptep++ = (*ptep & ~PG_PROT) | PG_V | PG_KW;
104330391Skarels 
104430391Skarels 		ubarelse(0, &Qbus_unmap[unit]);
104530391Skarels 	    }
104630391Skarels 
104730391Skarels 	    /*---------------------------------------
104830391Skarels 	    * re-protect 1K (2 pages) event queue */
104930391Skarels 
105030391Skarels 	    if (qdflags[unit].mapped & MAPEQ) {
105130391Skarels 
105230391Skarels 		ptep = (int *)
105330391Skarels 			((VTOP(eq_header[unit])*4) + (mfpr(SBR)|0x80000000));
105430391Skarels 
105530391Skarels 		*ptep++ = (*ptep & ~PG_PROT) | PG_KW | PG_V;
105630391Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
105730391Skarels 	    }
105830391Skarels 
105930391Skarels 	    /*------------------------------------------------------------
106030391Skarels 	    * re-protect scroll param area and disable scroll intrpts  */
106130391Skarels 
106230391Skarels 	    if (qdflags[unit].mapped & MAPSCR) {
106330391Skarels 
106430391Skarels 		ptep = (int *) ((VTOP(scroll[unit]) * 4)
106530391Skarels 				    + (mfpr(SBR) | 0x80000000));
106630391Skarels 
106730391Skarels 		/* re-protect 512 scroll param area */
106830391Skarels 
106930391Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
107030391Skarels 
107130391Skarels 		adder = (struct adder *) qdmap[unit].adder;
107230391Skarels 		qdflags[unit].adder_ie &= ~FRAME_SYNC;
107330391Skarels 		adder->interrupt_enable = qdflags[unit].adder_ie;
107430391Skarels 	    }
107530391Skarels 
107630391Skarels 	    /*-----------------------------------------------------------
107730391Skarels 	    * re-protect color map write buffer area and kill intrpts */
107830391Skarels 
107930391Skarels 	    if (qdflags[unit].mapped & MAPCOLOR) {
108030391Skarels 
108130391Skarels 		ptep = (int *) ((VTOP(color_buf[unit]) * 4)
108230391Skarels 				    + (mfpr(SBR) | 0x80000000));
108330391Skarels 
108430391Skarels 		*ptep++ = (*ptep & ~PG_PROT) | PG_KW | PG_V;
108530391Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
108630391Skarels 
108730391Skarels 		color_buf[unit]->status = 0;
108830391Skarels 
108930391Skarels 		adder = (struct adder *) qdmap[unit].adder;
109030391Skarels 		qdflags[unit].adder_ie &= ~VSYNC;
109130391Skarels 		adder->interrupt_enable = qdflags[unit].adder_ie;
109230391Skarels 	    }
109330391Skarels 
109430391Skarels 	    /*-----------------------------------
109530391Skarels 	    * flag that everthing is unmapped */
109630391Skarels 
109730391Skarels 	    mtpr(TBIA, 0);		/* smash CPU's translation buf */
109830391Skarels 	    qdflags[unit].mapped = 0;	/* flag everything now unmapped */
109930391Skarels 	    qdflags[unit].inuse &= ~GRAPHIC_DEV;
110030391Skarels 	    qdflags[unit].curs_acc = ACC_OFF;
110130391Skarels 	    qdflags[unit].curs_thr = 128;
110230391Skarels 
110330391Skarels 	    /*---------------------
110430391Skarels 	    * restore the console */
110530391Skarels 
110630391Skarels 		dga = (struct dga *) qdmap[unit].dga;
110730391Skarels 		adder = (struct adder *) qdmap[unit].adder;
110830391Skarels 
110930391Skarels 		dga->csr &= ~DMA_IE;
111030391Skarels 		dga->csr &= ~0x0600;	/* halt the DMA! (just in case...) */
111130391Skarels 		dga->csr |= DMA_ERR;	/* clear error condition */
111230391Skarels 		adder->command = CANCEL;
111330391Skarels 
111430391Skarels 		/* if DMA was running, flush spurious intrpt */
111530391Skarels 
111630391Skarels 		if (dga->bytcnt_lo != 0) {
111730391Skarels 		    dga->bytcnt_lo = 0;
111830391Skarels 		    dga->bytcnt_hi = 0;
111930391Skarels 		    DMA_SETIGNORE(DMAheader[unit]);
112030391Skarels 		    dga->csr |= DMA_IE;
112130391Skarels 		    dga->csr &= ~DMA_IE;
112230391Skarels 		}
112330391Skarels 
112430391Skarels 		init_shared(unit);		/* init shared memory */
112530391Skarels 		setup_dragon(unit);		/* init ADDER/VIPER */
112630391Skarels 		ldcursor(unit, cons_cursor);	/* load default cursor map */
112730391Skarels 		setup_input(unit);		/* init the DUART */
112830391Skarels 		ldfont(unit);
112930391Skarels 		cursor[unit].x = 0;
113030391Skarels 		cursor[unit].y = 0;
113130391Skarels 
113230391Skarels 	    /* shut off the mouse rcv intrpt and turn on kbd intrpts */
113330391Skarels 
113430391Skarels 	    duart = (struct duart *) qdmap[unit].duart;
113530391Skarels 	    qdflags[unit].duart_imask &= ~(0x20);
113630391Skarels 	    qdflags[unit].duart_imask |= 0x02;
113730391Skarels 	    duart->imask = qdflags[unit].duart_imask;
113830391Skarels 
113930391Skarels 	    /*-----------------------------------------
114030391Skarels 	    * shut off interrupts if all is closed  */
114130391Skarels 
114230391Skarels 	    if (!(qdflags[unit].inuse & (CONS_DEV | ALTCONS_DEV))) {
114330391Skarels 
114430391Skarels 		dga = (struct dga *) qdmap[unit].dga;
114530391Skarels 		dga->csr &= ~(GLOBAL_IE | DMA_IE);
114630391Skarels 	    }
114730391Skarels 	}
114830391Skarels 	else {
1149*32012Smarc 	    /* if this is the console or the alternate console  */
115030391Skarels 
115130391Skarels 	    tp = &qd_tty[minor_dev];
115230391Skarels 
115330391Skarels 	    (*linesw[tp->t_line].l_close)(tp);
115430391Skarels 	    ttyclose(tp);
115530391Skarels 
115630391Skarels 	    tp->t_state = 0;
115730391Skarels 
115830391Skarels 	    qdflags[unit].inuse &= ~CONS_DEV;
115930391Skarels 
116030391Skarels 	    /*-------------------------------------------------
116130391Skarels 	    * if graphics device is closed, kill interrupts */
116230391Skarels 
116330391Skarels 	    if (!(qdflags[unit].inuse & GRAPHIC_DEV)) {
116430391Skarels 		dga = (struct dga *) qdmap[unit].dga;
116530391Skarels 		dga->csr &= ~(GLOBAL_IE | DMA_IE);
116630391Skarels 	    }
116730391Skarels 	}
116830391Skarels 
116930391Skarels 	return(0);
117030391Skarels 
117130391Skarels } /* qdclose */
117230391Skarels 
117330391Skarels /***************************************************************
117430391Skarels *
117530391Skarels *	qdioctl()... provide QDSS control services
117630391Skarels *
117730391Skarels ****************************************************************
117830391Skarels *
117930391Skarels *  calling convention:	qdioctl(dev, cmd, datap, flags);
118030391Skarels *
118130391Skarels *		where:	dev - the major/minor device number
118230391Skarels *			cmd - the user-passed command argument
118330391Skarels *			datap - ptr to user input buff (128 bytes max)
118430391Skarels *			flags - "f_flags" from "struct file" in file.h
118530391Skarels *
118630391Skarels *
118730391Skarels *	- here is the format for the input "cmd" argument
118830391Skarels *
118930391Skarels *	31     29 28	23 22	      16 15		8 7		 0
119030391Skarels *	+----------------------------------------------------------------+
119130391Skarels *	|I/O type|	  | buff length | device ID char |  user command |
119230391Skarels *	+----------------------------------------------------------------+
119330391Skarels *
119430391Skarels *  Return data is in the data buffer pointed to by "datap" input spec
119530391Skarels *
119630391Skarels *********************/
119730391Skarels 
119830391Skarels qdioctl(dev, cmd, datap, flags)
119930391Skarels dev_t dev;
120030391Skarels int cmd;
120130391Skarels caddr_t datap;
120230391Skarels int flags;
120330391Skarels {
120430391Skarels 	register int *ptep;		/* page table entry pointer */
1205*32012Smarc 	register int mapix;		/* QVmap[] page table index */
120630391Skarels 	register struct _vs_event *event;
120730391Skarels 	register struct tty *tp;
120830391Skarels 
120930391Skarels 	struct qdmap *qd;		/* pointer to device map struct */
121030391Skarels 	struct dga *dga;		/* Gate Array reg structure pntr */
121130391Skarels 	struct duart *duart;		/* DUART reg structure pointer */
121230391Skarels 	struct adder *adder;		/* ADDER reg structure pointer */
121330391Skarels 
121430391Skarels 	struct prgkbd *cmdbuf;
121530391Skarels 	struct prg_cursor *curs;
121630391Skarels 	struct _vs_cursor *pos;
121730391Skarels 
121830391Skarels 	u_int unit = minor(dev) >> 2;	/* number of caller's QDSS */
121930391Skarels 	u_int minor_dev = minor(dev);
122030391Skarels 	struct uba_device *ui = qdinfo[unit];
122130391Skarels 	struct qd_softc *sc = &qd_softc[ui->ui_unit];
1222*32012Smarc 	/* struct devget *devget; */
122330391Skarels 
122430391Skarels 	int error;
122530391Skarels 	int s;
122630391Skarels 
122730391Skarels 	int i;				/* SIGNED index */
122830391Skarels 	int sbr;			/* SBR variable (you silly boy) */
122930391Skarels 	u_int ix;
123030391Skarels 
123130391Skarels 	short status;
123230391Skarels 	short *shortp;			/* generic pointer to a short */
123330391Skarels 	char *chrp;			/* generic character pointer */
123430391Skarels 
123530391Skarels 	short *temp;			/* a pointer to template RAM */
123630391Skarels 
1237*32012Smarc 	/* service graphic device ioctl commands */
123830391Skarels 	switch (cmd) {
123930391Skarels 
124030391Skarels 	    /*-------------------------------------------------
124130391Skarels 	    * extract the oldest event from the event queue */
124230391Skarels 
124330391Skarels 	    case QD_GETEVENT:
124430391Skarels 
124530391Skarels 		if (ISEMPTY(eq_header[unit])) {
124630391Skarels 		    event = (struct _vs_event *) datap;
124730391Skarels 		    event->vse_device = VSE_NULL;
124830391Skarels 		    break;
124930391Skarels 		}
125030391Skarels 
125130391Skarels 		event = (struct _vs_event *) GETBEGIN(eq_header[unit]);
1252*32012Smarc 		s = spltty();
125330391Skarels 		GETEND(eq_header[unit]);
125430391Skarels 		splx(s);
125530391Skarels 		bcopy(event, datap, sizeof(struct _vs_event));
125630391Skarels 		break;
125730391Skarels 
125830391Skarels 	    /*-------------------------------------------------------
125930391Skarels 	    * init the dragon stuff, DUART, and driver variables  */
126030391Skarels 
126130391Skarels 	    case QD_RESET:
126230391Skarels 
126330391Skarels 		init_shared(unit);		/* init shared memory */
126430391Skarels 		setup_dragon(unit);	      /* init the ADDER/VIPER stuff */
126530391Skarels 		clear_qd_screen(unit);
126630391Skarels 		ldcursor(unit, cons_cursor);	/* load default cursor map */
126730391Skarels 		ldfont(unit);			/* load the console font */
126830391Skarels 		setup_input(unit);		/* init the DUART */
126930391Skarels 		break;
127030391Skarels 
127130391Skarels 	    /*----------------------------------------
127230391Skarels 	    * init the DUART and driver variables  */
127330391Skarels 
127430391Skarels 	    case QD_SET:
127530391Skarels 
127630391Skarels 		init_shared(unit);
127730391Skarels 		setup_input(unit);
127830391Skarels 		break;
127930391Skarels 
128030391Skarels 	    /*---------------------------------------------------------------
128130391Skarels 	    * clear the QDSS screen.  (NOTE that this reinits the dragon) */
128230391Skarels 
128330391Skarels 	    case QD_CLRSCRN:
128430391Skarels 
128530391Skarels 		setup_dragon(unit);
128630391Skarels 		clear_qd_screen(unit);
128730391Skarels 		break;
128830391Skarels 
128930391Skarels 	    /*------------------------------------
129030391Skarels 	    * load a cursor into template RAM  */
129130391Skarels 
129230391Skarels 	    case QD_WTCURSOR:
129330391Skarels 
129430391Skarels 		ldcursor(unit, datap);
129530391Skarels 		break;
129630391Skarels 
129730391Skarels 	    case QD_RDCURSOR:
129830391Skarels 
129930391Skarels 		temp = (short *) qdmap[unit].template;
130030391Skarels 
130130391Skarels 		/* cursor is 32 WORDS from the end of the 8k WORD...
130230391Skarels 		*  ...template space */
130330391Skarels 
130430391Skarels 		temp += (8 * 1024) - 32;
130530391Skarels 
130630391Skarels 		for (i = 0; i < 32; ++i, datap += sizeof(short))
130730391Skarels 		    *(short *)datap = *temp++;
130830391Skarels 		break;
130930391Skarels 
131030391Skarels 	    /*------------------------------
131130391Skarels 	    * position the mouse cursor  */
131230391Skarels 
131330391Skarels 	    case QD_POSCURSOR:
131430391Skarels 
131530391Skarels 		dga = (struct dga *) qdmap[unit].dga;
131630391Skarels 		pos = (struct _vs_cursor *) datap;
1317*32012Smarc 		s = spltty();
131830391Skarels 		dga->x_cursor = TRANX(pos->x);
131930391Skarels 		dga->y_cursor = TRANY(pos->y);
132030391Skarels 		eq_header[unit]->curs_pos.x = pos->x;
132130391Skarels 		eq_header[unit]->curs_pos.y = pos->y;
132230391Skarels 		splx(s);
132330391Skarels 		break;
132430391Skarels 
132530391Skarels 	    /*--------------------------------------
132630391Skarels 	    * set the cursor acceleration factor */
132730391Skarels 
132830391Skarels 	    case QD_PRGCURSOR:
132930391Skarels 
133030391Skarels 		curs = (struct prg_cursor *) datap;
1331*32012Smarc 		s = spltty();
133230391Skarels 		qdflags[unit].curs_acc = curs->acc_factor;
133330391Skarels 		qdflags[unit].curs_thr = curs->threshold;
133430391Skarels 		splx(s);
133530391Skarels 		break;
133630391Skarels 
133730391Skarels 	    /*---------------------------------------
133830391Skarels 	    * enable 'user write' to device pages */
133930391Skarels 
134030391Skarels 	    case QD_MAPDEVICE:
134130391Skarels 
134230391Skarels 		/*--------------
134330391Skarels 		* init stuff */
134430391Skarels 
134530391Skarels 		qdflags[unit].mapped |= MAPDEV;
134630391Skarels 		qd = (struct qdmap *) &qdmap[unit];
134730391Skarels 
134830391Skarels 		/*-------------------------------------
134930391Skarels 		* enable user write to template RAM */
135030391Skarels 
1351*32012Smarc 		mapix = VTOP((int)qd->template) - VTOP(qvmem[0]);
1352*32012Smarc 		ptep = (int *)(QVmap[0] + mapix);
135330391Skarels 
135430391Skarels 		for (i = VTOP(TMPSIZE); i > 0; --i)
135530391Skarels 		    *ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V;
135630391Skarels 
135730391Skarels 		/*----------------------------------
135830391Skarels 		* enable user write to registers */
135930391Skarels 
1360*32012Smarc 		mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]);
1361*32012Smarc 		ptep = (int *)(QVmap[0] + mapix);
136230391Skarels 
136330391Skarels 		for (i = VTOP(REGSIZE); i > 0; --i)
136430391Skarels 		    *ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V;
136530391Skarels 
136630391Skarels 		/*-----------------------------------
136730391Skarels 		* enable user write to color maps */
136830391Skarels 
1369*32012Smarc 		mapix = VTOP((int)qd->red) - VTOP(qvmem[0]);
1370*32012Smarc 		ptep = (int *)(QVmap[0] + mapix);
137130391Skarels 
137230391Skarels 		for (i = VTOP(CLRSIZE); i > 0; --i)
137330391Skarels 		    *ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V;
137430391Skarels 
137530391Skarels 		/*------------------------------
137630391Skarels 		* enable user write to DUART */
137730391Skarels 
1378*32012Smarc 		mapix = VTOP((int)qd->duart) - VTOP(qvmem[0]);
1379*32012Smarc 		ptep = (int *)(QVmap[0] + mapix);
138030391Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; /* duart page */
138130391Skarels 
138230391Skarels 		mtpr(TBIA, 0);		/* smash CPU's translation buffer */
138330391Skarels 
138430391Skarels 		/*------------------------------------------
138530391Skarels 		* stuff qdmap structure in return buffer */
138630391Skarels 
138730391Skarels 		bcopy(qd, datap, sizeof(struct qdmap));
138830391Skarels 		break;
138930391Skarels 
139030391Skarels 	    /*-------------------------------------
139130391Skarels 	    * do setup for DMA by user process	*/
139230391Skarels 
139330391Skarels 	    case QD_MAPIOBUF:
139430391Skarels 
139530391Skarels 		/*------------------------------------------------
139630391Skarels 		* set 'user write enable' bits for DMA buffer  */
139730391Skarels 
139830391Skarels 		qdflags[unit].mapped |= MAPDMA;
139930391Skarels 
140030391Skarels 		ptep = (int *) ((VTOP(DMAheader[unit]) * 4)
140130391Skarels 				+ (mfpr(SBR) | 0x80000000));
140230391Skarels 
140330391Skarels 		for (i = (DMAbuf_size >> PGSHIFT); i > 0; --i)
140430391Skarels 		    *ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V;
140530391Skarels 
140630391Skarels 		mtpr(TBIA, 0);			/* clr CPU translation buf */
140730391Skarels 
140830391Skarels 		/*-------------------------------------
140930391Skarels 		* set up QBUS map registers for DMA */
141030391Skarels 
141130391Skarels 		DMAheader[unit]->QBAreg =
141230391Skarels 				uballoc(0, DMAheader[unit], DMAbuf_size, 0);
141330391Skarels 
141430391Skarels 		if (DMAheader[unit]->QBAreg == 0)
141530391Skarels 		    mprintf("\nqd%d: qdioctl: QBA setup error", unit);
141630391Skarels 
141730391Skarels 		Qbus_unmap[unit] = DMAheader[unit]->QBAreg;
141830391Skarels 		DMAheader[unit]->QBAreg &= 0x3FFFF;
141930391Skarels 
142030391Skarels 		/*----------------------
142130391Skarels 		* return I/O buf adr */
142230391Skarels 
142330391Skarels 		*(int *)datap = (int) DMAheader[unit];
142430391Skarels 		break;
142530391Skarels 
142630391Skarels 	    /*----------------------------------------------------------------
142730391Skarels 	    * map the shared scroll param area and enable scroll interpts  */
142830391Skarels 
142930391Skarels 	    case QD_MAPSCROLL:
143030391Skarels 
143130391Skarels 		qdflags[unit].mapped |= MAPSCR;
143230391Skarels 
143330391Skarels 		ptep = (int *) ((VTOP(scroll[unit]) * 4)
143430391Skarels 				+ (mfpr(SBR) | 0x80000000));
143530391Skarels 
143630391Skarels 		/* allow user write to scroll area */
143730391Skarels 
143830391Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
143930391Skarels 
144030391Skarels 		mtpr(TBIA, 0);			/* clr CPU translation buf */
144130391Skarels 
144230391Skarels 		scroll[unit]->status = 0;
144330391Skarels 
144430391Skarels 		adder = (struct adder *) qdmap[unit].adder;
144530391Skarels 
144630391Skarels 		qdflags[unit].adder_ie |= FRAME_SYNC;
144730391Skarels 		adder->interrupt_enable = qdflags[unit].adder_ie;
144830391Skarels 
144930391Skarels 		/* return scroll area address */
145030391Skarels 
145130391Skarels 		*(int *)datap = (int) scroll[unit];
145230391Skarels 		break;
145330391Skarels 
145430391Skarels 	    /*-------------------------------------------------------------
145530391Skarels 	    * unmap shared scroll param area and disable scroll intrpts */
145630391Skarels 
145730391Skarels 	    case QD_UNMAPSCROLL:
145830391Skarels 
145930391Skarels 		if (qdflags[unit].mapped & MAPSCR) {
146030391Skarels 
146130391Skarels 		    qdflags[unit].mapped &= ~MAPSCR;
146230391Skarels 
146330391Skarels 		    ptep = (int *) ((VTOP(scroll[unit]) * 4)
146430391Skarels 				    + (mfpr(SBR) | 0x80000000));
146530391Skarels 
146630391Skarels 		    /* re-protect 512 scroll param area */
146730391Skarels 
146830391Skarels 		    *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
146930391Skarels 
147030391Skarels 		    mtpr(TBIA, 0);	/* smash CPU's translation buf */
147130391Skarels 
147230391Skarels 		    adder = (struct adder *) qdmap[unit].adder;
147330391Skarels 		    qdflags[unit].adder_ie &= ~FRAME_SYNC;
147430391Skarels 		    adder->interrupt_enable = qdflags[unit].adder_ie;
147530391Skarels 		}
147630391Skarels 		break;
147730391Skarels 
147830391Skarels 	    /*-----------------------------------------------------------
147930391Skarels 	    * map shared color map write buf and turn on vsync intrpt */
148030391Skarels 
148130391Skarels 	    case QD_MAPCOLOR:
148230391Skarels 
148330391Skarels 		qdflags[unit].mapped |= MAPCOLOR;
148430391Skarels 
148530391Skarels 		ptep = (int *) ((VTOP(color_buf[unit]) * 4)
148630391Skarels 				+ (mfpr(SBR) | 0x80000000));
148730391Skarels 
148830391Skarels 		/* allow user write to color map write buffer */
148930391Skarels 
149030391Skarels 		*ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V;
149130391Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
149230391Skarels 
149330391Skarels 		mtpr(TBIA, 0);			/* clr CPU translation buf */
149430391Skarels 
149530391Skarels 		adder = (struct adder *) qdmap[unit].adder;
149630391Skarels 
149730391Skarels 		qdflags[unit].adder_ie |= VSYNC;
149830391Skarels 		adder->interrupt_enable = qdflags[unit].adder_ie;
149930391Skarels 
150030391Skarels 		/* return scroll area address */
150130391Skarels 
150230391Skarels 		*(int *)datap = (int) color_buf[unit];
150330391Skarels 		break;
150430391Skarels 
150530391Skarels 	    /*--------------------------------------------------------------
150630391Skarels 	    * unmap shared color map write buffer and kill VSYNC intrpts */
150730391Skarels 
150830391Skarels 	    case QD_UNMAPCOLOR:
150930391Skarels 
151030391Skarels 		if (qdflags[unit].mapped & MAPCOLOR) {
151130391Skarels 
151230391Skarels 		    qdflags[unit].mapped &= ~MAPCOLOR;
151330391Skarels 
151430391Skarels 		    ptep = (int *) ((VTOP(color_buf[unit]) * 4)
151530391Skarels 				    + (mfpr(SBR) | 0x80000000));
151630391Skarels 
151730391Skarels 		    /* re-protect color map write buffer */
151830391Skarels 
151930391Skarels 		    *ptep++ = (*ptep & ~PG_PROT) | PG_KW | PG_V;
152030391Skarels 		    *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
152130391Skarels 
152230391Skarels 		    mtpr(TBIA, 0);	/* smash CPU's translation buf */
152330391Skarels 
152430391Skarels 		    adder = (struct adder *) qdmap[unit].adder;
152530391Skarels 
152630391Skarels 		    qdflags[unit].adder_ie &= ~VSYNC;
152730391Skarels 		    adder->interrupt_enable = qdflags[unit].adder_ie;
152830391Skarels 		}
152930391Skarels 		break;
153030391Skarels 
153130391Skarels 	    /*---------------------------------------------
153230391Skarels 	    * give user write access to the event queue */
153330391Skarels 
153430391Skarels 	    case QD_MAPEVENT:
153530391Skarels 
153630391Skarels 		qdflags[unit].mapped |= MAPEQ;
153730391Skarels 
153830391Skarels 		ptep = (int *) ((VTOP(eq_header[unit]) * 4)
153930391Skarels 				+ (mfpr(SBR) | 0x80000000));
154030391Skarels 
154130391Skarels 		/* allow user write to 1K event queue */
154230391Skarels 
154330391Skarels 		*ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V;
154430391Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
154530391Skarels 
154630391Skarels 		mtpr(TBIA, 0);			/* clr CPU translation buf */
154730391Skarels 
154830391Skarels 		/* return event queue address */
154930391Skarels 
155030391Skarels 		*(int *)datap = (int) eq_header[unit];
155130391Skarels 		break;
155230391Skarels 
155330391Skarels 	    /*-----------------------------------------------
155430391Skarels 	    * pass caller's programming commands to LK201 */
155530391Skarels 
155630391Skarels 	    case QD_PRGKBD:
155730391Skarels 
155830391Skarels 		duart = (struct duart *) qdmap[unit].duart;
155930391Skarels 		cmdbuf = (struct prgkbd *) datap;    /* pnt to kbd cmd buf */
156030391Skarels 
156130391Skarels 		/*----------------
156230391Skarels 		* send command */
156330391Skarels 
156430391Skarels 		for (i = 1000; i > 0; --i) {
156530391Skarels 		    if ((status = duart->statusA) & XMT_RDY) {
156630391Skarels 			duart->dataA = cmdbuf->cmd;
156730391Skarels 			break;
156830391Skarels 		    }
156930391Skarels 		}
157030391Skarels 
157130391Skarels 		if (i == 0) {
157230391Skarels 		    mprintf("\nqd%d: qdioctl: timeout on XMT_RDY [1]", unit);
157330391Skarels 		    break;
157430391Skarels 		}
157530391Skarels 
157630391Skarels 		/*----------------
157730391Skarels 		* send param1? */
157830391Skarels 
157930391Skarels 		if (cmdbuf->cmd & LAST_PARAM)
158030391Skarels 		    break;
158130391Skarels 
158230391Skarels 		for (i = 1000; i > 0; --i) {
158330391Skarels 		    if ((status = duart->statusA) & XMT_RDY) {
158430391Skarels 			duart->dataA = cmdbuf->param1;
158530391Skarels 			break;
158630391Skarels 		    }
158730391Skarels 		}
158830391Skarels 
158930391Skarels 		if (i == 0) {
159030391Skarels 		    mprintf("\nqd%d: qdioctl: timeout on XMT_RDY [2]", unit);
159130391Skarels 		    break;
159230391Skarels 		}
159330391Skarels 
159430391Skarels 		/*----------------
159530391Skarels 		* send param2? */
159630391Skarels 
159730391Skarels 		if (cmdbuf->param1 & LAST_PARAM)
159830391Skarels 		    break;
159930391Skarels 
160030391Skarels 		for (i = 1000; i > 0; --i) {
160130391Skarels 		    if ((status = duart->statusA) & XMT_RDY) {
160230391Skarels 			duart->dataA = cmdbuf->param2;
160330391Skarels 			break;
160430391Skarels 		    }
160530391Skarels 		}
160630391Skarels 
160730391Skarels 		if (i == 0) {
160830391Skarels 		    mprintf("\nqd%d: qdioctl: timeout on XMT_RDY [3]", unit);
160930391Skarels 		    break;
161030391Skarels 		}
161130391Skarels 
161230391Skarels 		break;
161330391Skarels 
161430391Skarels 	    /*----------------------------------------------------
161530391Skarels 	    * pass caller's programming commands to the mouse  */
161630391Skarels 
161730391Skarels 	    case QD_PRGMOUSE:
161830391Skarels 
161930391Skarels 		duart = (struct duart *) qdmap[unit].duart;
162030391Skarels 
162130391Skarels 		for (i = 1000; i > 0; --i) {
162230391Skarels 		    if ((status = duart->statusB) & XMT_RDY) {
162330391Skarels 			duart->dataB = *datap;
162430391Skarels 			break;
162530391Skarels 		    }
162630391Skarels 		}
162730391Skarels 
162830391Skarels 		if (i == 0) {
162930391Skarels 		    mprintf("\nqd%d: qdioctl: timeout on XMT_RDY [4]", unit);
163030391Skarels 		}
163130391Skarels 
163230391Skarels 		break;
163330391Skarels 
163430391Skarels 	    /*----------------------------------------------
163530391Skarels 	    * get QDSS configuration word and return it  */
163630391Skarels 
163730391Skarels 	    case QD_RDCONFIG:
163830391Skarels 
163930391Skarels 		*(short *)datap = qdflags[unit].config;
164030391Skarels 		break;
164130391Skarels 
164230391Skarels 	    /*----------------------
164330391Skarels 	    * program the tablet */
164430391Skarels 
164530391Skarels 	    case QD_PRGTABLET:
164630391Skarels 
164730391Skarels 		duart = (struct duart *) qdmap[unit].duart;
164830391Skarels 
164930391Skarels 		for (i = 1000; i > 0; --i) {
165030391Skarels 		    if ((status = duart->statusB) & XMT_RDY) {
165130391Skarels 			duart->dataB = *datap;
165230391Skarels 			break;
165330391Skarels 		    }
165430391Skarels 		}
165530391Skarels 
165630391Skarels 		if (i == 0) {
165730391Skarels 		    mprintf("\nqd%d: qdioctl: timeout on XMT_RDY [5]", unit);
165830391Skarels 		}
165930391Skarels 
166030391Skarels 		break;
166130391Skarels 
166230391Skarels 	    /*-----------------------------------------------
166330391Skarels 	    * program the tablet report resolution factor */
166430391Skarels 
166530391Skarels 	    case QD_PRGTABRES:
166630391Skarels 
166730391Skarels 		qdflags[unit].tab_res = *(short *)datap;
166830391Skarels 		break;
166930391Skarels 
1670*32012Smarc #ifdef notdef
167130391Skarels 	    case DEVIOCGET:			    /* device status */
167230391Skarels 		    devget = (struct devget *)datap;
167330391Skarels 		    bzero(devget,sizeof(struct devget));
167430391Skarels 		    devget->category = DEV_TERMINAL;
167530391Skarels 		    devget->bus = DEV_QB;
167630391Skarels 		    bcopy(DEV_VCB02,devget->interface,
167730391Skarels 			  strlen(DEV_VCB02));
167830391Skarels 		    bcopy(DEV_VR290,devget->device,
167930391Skarels 			  strlen(DEV_VR290));		    /* terminal */
168030391Skarels 		    devget->adpt_num = ui->ui_adpt;	    /* which adapter*/
168130391Skarels 		    devget->nexus_num = ui->ui_nexus;	    /* which nexus  */
168230391Skarels 		    devget->bus_num = ui->ui_ubanum;	    /* which QB     */
168330391Skarels 		    devget->ctlr_num = unit;		    /* which interf.*/
168430391Skarels 		    devget->slave_num = unit;		    /* which line   */
168530391Skarels 		    bcopy(ui->ui_driver->ud_dname,
168630391Skarels 			  devget->dev_name,
168730391Skarels 			  strlen(ui->ui_driver->ud_dname)); /* Ultrix "qd"  */
168830391Skarels 		    devget->unit_num = unit;		    /* qd line?     */
168930391Skarels 		    devget->soft_count =
169030391Skarels 			  sc->sc_softcnt;		    /* soft er. cnt.*/
169130391Skarels 		    devget->hard_count =
169230391Skarels 			  sc->sc_hardcnt;		    /* hard er cnt. */
169330391Skarels 		    devget->stat = sc->sc_flags;	    /* status	    */
169430391Skarels 		    devget->category_stat =
169530391Skarels 			  sc->sc_category_flags;	    /* cat. stat.   */
169630391Skarels 		    break;
1697*32012Smarc #endif /* notdef */
169830391Skarels 
169930391Skarels 	    default:
170030391Skarels 		/*-----------------------------
170130391Skarels 		* service tty type ioctl's  */
170230391Skarels 
170330391Skarels 		    if (!(minor_dev & 0x02)) {
170430391Skarels 
170530391Skarels 			tp = &qd_tty[minor_dev];
170630391Skarels 
170730391Skarels 			error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, datap, flags);
170830391Skarels 			if (error >= 0) {
170930391Skarels 			    return(error);
171030391Skarels 			}
171130391Skarels 
171230391Skarels 			error = ttioctl(tp, cmd, datap, flags);
171330391Skarels 			if (error >= 0) {
171430391Skarels 			    return(error);
171530391Skarels 			}
171630391Skarels 		    }
171730391Skarels 		    break;
171830391Skarels 	}
171930391Skarels 
172030391Skarels /*--------------------------------
172130391Skarels * clean up and get outta here  */
172230391Skarels 
172330391Skarels 	return(0);
172430391Skarels 
172530391Skarels } /* qdioctl */
172630391Skarels 
172730391Skarels /**********************************************************************
172830391Skarels *
172930391Skarels *	qdselect()... service select call for event queue input
173030391Skarels *
173130391Skarels **********************************************************************/
173230391Skarels 
173330391Skarels qdselect(dev, rw)
173430391Skarels dev_t dev;
173530391Skarels int rw;
173630391Skarels {
173730391Skarels 	register int s;
173830391Skarels 	register int unit;
173930391Skarels 
1740*32012Smarc 	s = spltty();
174130391Skarels 	unit = minor(dev) >> 2;
174230391Skarels 
174330391Skarels 	switch (rw) {
174430391Skarels 
174530391Skarels 	    case FREAD: 		/* event available? */
174630391Skarels 
174730391Skarels 		if(!(ISEMPTY(eq_header[unit]))) {
174830391Skarels 		    splx(s);
174930391Skarels 		    return(1);		/* return "1" if event exists */
175030391Skarels 		}
175130391Skarels 		rsel[unit] = u.u_procp;
175230391Skarels 		qdflags[unit].selmask |= SEL_READ;
175330391Skarels 		splx(s);
175430391Skarels 		return(0);
175530391Skarels 
175630391Skarels 	    case FWRITE:		/* DMA done? */
175730391Skarels 
175830391Skarels 		if (DMA_ISEMPTY(DMAheader[unit])) {
175930391Skarels 		    splx(s);
176030391Skarels 		    return(1);		/* return "1" if DMA is done */
176130391Skarels 		}
176230391Skarels 		rsel[unit] = u.u_procp;
176330391Skarels 		qdflags[unit].selmask |= SEL_WRITE;
176430391Skarels 		splx(s);
176530391Skarels 		return(0);
176630391Skarels 	}
176730391Skarels 
176830391Skarels } /* qdselect() */
176930391Skarels 
177030391Skarels /***************************************************************
177130391Skarels *
177230391Skarels *	qdwrite()... output to the QDSS screen as a TTY
177330391Skarels *
177430391Skarels ***************************************************************/
177530391Skarels 
177630391Skarels extern qd_strategy();
177730391Skarels 
177830391Skarels qdwrite(dev, uio)
177930391Skarels dev_t dev;
178030391Skarels struct uio *uio;
178130391Skarels {
178230391Skarels 	register struct tty *tp;
178330391Skarels 	register int minor_dev;
178430391Skarels 	register int unit;
178530391Skarels 
178630391Skarels 	minor_dev = minor(dev);
178730391Skarels 	unit = (minor_dev >> 2) & 0x07;
178830391Skarels 
178930391Skarels 	/*------------------------------
179030391Skarels 	* if this is the console...  */
179130391Skarels 
179230391Skarels 	if ((minor_dev & 0x03) != 0x02	&&
179330391Skarels 	     qdflags[unit].inuse & CONS_DEV) {
179430391Skarels 	    tp = &qd_tty[minor_dev];
179530391Skarels 	    return ((*linesw[tp->t_line].l_write)(tp, uio));
179630391Skarels 	}
179730391Skarels 
179830391Skarels 	/*------------------------------------------------
179930391Skarels 	* else this must be a DMA xfer from user space */
180030391Skarels 
180130391Skarels 	else if (qdflags[unit].inuse & GRAPHIC_DEV) {
180230391Skarels 	    return (physio(qd_strategy, &qdbuf[unit],
180330391Skarels 			   dev, B_WRITE, minphys, uio));
180430391Skarels 	}
180530391Skarels }
180630391Skarels 
180730391Skarels /***************************************************************
180830391Skarels *
180930391Skarels *	qdread()... read from QDSS keyboard as a TTY
181030391Skarels *
181130391Skarels ***************************************************************/
181230391Skarels 
181330391Skarels qdread(dev, uio)
181430391Skarels dev_t dev;
181530391Skarels struct uio *uio;
181630391Skarels {
181730391Skarels 	register struct tty *tp;
181830391Skarels 	register int minor_dev;
181930391Skarels 	register int unit;
182030391Skarels 
182130391Skarels 	minor_dev = minor(dev);
182230391Skarels 	unit = (minor_dev >> 2) & 0x07;
182330391Skarels 
182430391Skarels 	/*------------------------------
182530391Skarels 	* if this is the console...  */
182630391Skarels 
182730391Skarels 	if ((minor_dev & 0x03) != 0x02	&&
182830391Skarels 	     qdflags[unit].inuse & CONS_DEV) {
182930391Skarels 	    tp = &qd_tty[minor_dev];
183030391Skarels 	    return ((*linesw[tp->t_line].l_read)(tp, uio));
183130391Skarels 	}
183230391Skarels 
183330391Skarels 	/*------------------------------------------------
183430391Skarels 	* else this must be a bitmap-to-processor xfer */
183530391Skarels 
183630391Skarels 	else if (qdflags[unit].inuse & GRAPHIC_DEV) {
183730391Skarels 	    return (physio(qd_strategy, &qdbuf[unit],
183830391Skarels 			   dev, B_READ, minphys, uio));
183930391Skarels 	}
184030391Skarels }
184130391Skarels 
184230391Skarels /***************************************************************
184330391Skarels *
184430391Skarels *	qd_strategy()... strategy routine to do DMA
184530391Skarels *
184630391Skarels ***************************************************************/
184730391Skarels 
184830391Skarels qd_strategy(bp)
184930391Skarels register struct buf *bp;
185030391Skarels {
185130391Skarels 	register struct dga *dga;
185230391Skarels 	register struct adder *adder;
185330391Skarels 
185430391Skarels 	char *DMAbufp;
185530391Skarels 
185630391Skarels 	int QBAreg;
185730391Skarels 	int bytcnt;
185830391Skarels 	int s;
185930391Skarels 	int unit;
186030391Skarels 	int cookie;
186130391Skarels 
186230391Skarels 	int i,j,k;
186330391Skarels 
186430391Skarels 	unit = (minor(bp->b_dev) >> 2) & 0x07;
186530391Skarels 
1866*32012Smarc 	/*
1867*32012Smarc 	* init pointers
1868*32012Smarc 	*/
186930391Skarels 
187030391Skarels 	if ((QBAreg = ubasetup(0, bp, 0)) == 0) {
187130391Skarels 	    mprintf("\nqd%d: qd_strategy: QBA setup error", unit);
187230391Skarels 	    goto STRAT_ERR;
187330391Skarels 	}
187430391Skarels 
187530391Skarels 	dga = (struct dga *) qdmap[unit].dga;
187630391Skarels 
1877*32012Smarc 	s = spltty();
187830391Skarels 
187930391Skarels 	qdflags[unit].user_dma = -1;
188030391Skarels 
188130391Skarels 	dga->csr |= DMA_IE;
188230391Skarels 
188330391Skarels 	cookie = QBAreg & 0x3FFFF;
188430391Skarels 	dga->adrs_lo = (short) cookie;
188530391Skarels 	dga->adrs_hi = (short) (cookie >> 16);
188630391Skarels 
188730391Skarels 	dga->bytcnt_lo = (short) bp->b_bcount;
188830391Skarels 	dga->bytcnt_hi = (short) (bp->b_bcount >> 16);
188930391Skarels 
189030391Skarels 	while (qdflags[unit].user_dma) {
189130391Skarels 	    sleep((caddr_t)&qdflags[unit].user_dma, QDPRIOR);
189230391Skarels 	}
189330391Skarels 
189430391Skarels 	splx(s);
189530391Skarels 	ubarelse(0, &QBAreg);
189630391Skarels 
189730391Skarels 	if (!(dga->csr & DMA_ERR)) {
189830391Skarels 	    iodone(bp);
189930391Skarels 	    return;
190030391Skarels 	}
190130391Skarels 
190230391Skarels STRAT_ERR:
190330391Skarels 	adder = (struct adder *) qdmap[unit].adder;
190430391Skarels 	adder->command = CANCEL;		/* cancel adder activity */
190530391Skarels 	dga->csr &= ~DMA_IE;
190630391Skarels 	dga->csr &= ~0x0600;		/* halt DMA (reset fifo) */
190730391Skarels 	dga->csr |= DMA_ERR;		/* clear error condition */
190830391Skarels 	bp->b_flags |= B_ERROR; 	/* flag an error to physio() */
190930391Skarels 
191030391Skarels 	/* if DMA was running, flush spurious intrpt */
191130391Skarels 
191230391Skarels 	if (dga->bytcnt_lo != 0) {
191330391Skarels 	    dga->bytcnt_lo = 0;
191430391Skarels 	    dga->bytcnt_hi = 0;
191530391Skarels 	    DMA_SETIGNORE(DMAheader[unit]);
191630391Skarels 	    dga->csr |= DMA_IE;
191730391Skarels 	}
191830391Skarels 
191930391Skarels 	iodone(bp);
192030391Skarels 
192130391Skarels } /* qd_strategy */
192230391Skarels 
192330391Skarels /*******************************************************************
192430391Skarels *
192530391Skarels *	qdstart()... startup output to the console screen
192630391Skarels *
192730391Skarels ********************************************************************
192830391Skarels *
192930391Skarels *	calling convention:
193030391Skarels *
193130391Skarels *		qdstart(tp);
193230391Skarels *		struct tty *tp; 	;pointer to tty structure
193330391Skarels *
193430391Skarels ********/
193530391Skarels 
193630391Skarels qdstart(tp)
193730391Skarels register struct tty *tp;
193830391Skarels {
193930391Skarels 	register int which_unit, unit, c;
194030391Skarels 	register struct tty *tp0;
1941*32012Smarc 	int needwakeup = 0;
1942*32012Smarc 	static int qdwakeuptime = 5;
1943*32012Smarc 	int wakeup();
194430391Skarels 	int s;
194530391Skarels 
194630391Skarels 	int curs_on;
194730391Skarels 	struct dga *dga;
194830391Skarels 
194930391Skarels 	unit = minor(tp->t_dev);
195030391Skarels 
195130391Skarels 	tp0 = &qd_tty[(unit & 0x0FC)+1];
195230391Skarels 	which_unit = (unit >> 2) & 0x3;
195330391Skarels 	unit &= 0x03;
195430391Skarels 
1955*32012Smarc 	s = spltty();
195630391Skarels 
1957*32012Smarc 	/* If it's currently active, or delaying, no need to do anything. */
195830391Skarels 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
195930391Skarels 		goto out;
196030391Skarels 
1961*32012Smarc 	/*
1962*32012Smarc 	 * XXX  FARKLE
1963*32012Smarc 	 *
1964*32012Smarc 	 * Check if the caller is going to sleep and prepare to
1965*32012Smarc 	 * wake him up with a timeout.  This is a temporary hack.
1966*32012Smarc 	 */
1967*32012Smarc 	if (tp->t_outq.c_cc > TTHIWAT(tp))
1968*32012Smarc 		needwakeup++;
196930391Skarels 
1970*32012Smarc 	/*
1971*32012Smarc 	 * Drain the queue.
1972*32012Smarc 	 * Drop input from anything but the console
1973*32012Smarc 	 * device on the floor.
1974*32012Smarc 	 */
1975*32012Smarc 
197630391Skarels 	while (tp->t_outq.c_cc) {
197730391Skarels 	    c = getc(&tp->t_outq);
1978*32012Smarc 	    if (unit == 0)
1979*32012Smarc 	    	blitc(which_unit, c & 0xFF);
198030391Skarels 	}
198130391Skarels 
1982*32012Smarc 	/*
1983*32012Smarc 	 *  - FARKLE -
1984*32012Smarc 	 *  We are not a real hardware tty device that incures transmitter
1985*32012Smarc 	 *  interrupts.  This breaks the paradigm used in tty.c for
1986*32012Smarc 	 *  flow control. I.e.
1987*32012Smarc 	 *
1988*32012Smarc 	 *	spltty();
1989*32012Smarc 	 *	 ttstart();  /* schedule output which should interrupt*
1990*32012Smarc 	 *	 set TT_SLEEP flag
1991*32012Smarc 	 *	 sleep(outq)
1992*32012Smarc 	 *	splx();
1993*32012Smarc 	 *
1994*32012Smarc 	 *  Don't know what to do about this one.  In the meantime we schedule
1995*32012Smarc 	 *  a wakeup for the sleep that will occur.  Its gross - but works
1996*32012Smarc 	 *  for now.  This will all be rewritten anyway.
1997*32012Smarc 	 *
1998*32012Smarc 	 */
199930391Skarels 
200030391Skarels 	if ( tp->t_outq.c_cc <= TTLOWAT(tp) ) {
2001*32012Smarc 		if (needwakeup)
2002*32012Smarc 			timeout(wakeup,(caddr_t)&tp->t_outq,qdwakeuptime); /*XXX*/
200330391Skarels 		if (tp->t_state & TS_ASLEEP){
200430391Skarels 			tp->t_state &= ~TS_ASLEEP;
200530391Skarels 			wakeup((caddr_t) &tp->t_outq);
2006*32012Smarc 		}
200730391Skarels 	}
200830391Skarels 
200930391Skarels 	tp->t_state &= ~TS_BUSY;
201030391Skarels 
201130391Skarels out:
201230391Skarels 	splx(s);
201330391Skarels 
201430391Skarels } /* qdstart */
201530391Skarels 
201630391Skarels 
201730391Skarels /*******************************************************************
201830391Skarels *
201930391Skarels *	qdstop()... stop the tty
202030391Skarels *
202130391Skarels *******************************************************************/
202230391Skarels 
202330391Skarels qdstop(tp, flag)
202430391Skarels register struct tty *tp;
202530391Skarels int flag;
202630391Skarels {
202730391Skarels 	register int s;
202830391Skarels 
2029*32012Smarc 	log(LOG_NOTICE, "*qdstop*");
2030*32012Smarc 	s = spltty();	/* block intrpts during state modification */
203130391Skarels 
203230391Skarels 	if (tp->t_state & TS_BUSY) {
203330391Skarels 	    if ((tp->t_state & TS_TTSTOP) == 0) {
203430391Skarels 		tp->t_state |= TS_FLUSH;
203530391Skarels 	    } else
203630391Skarels 		tp->t_state &= ~TS_BUSY;
203730391Skarels 	}
203830391Skarels 	splx(s);
203930391Skarels }
204030391Skarels 
204130391Skarels /*******************************************************************
204230391Skarels *
204330391Skarels *	blitc()... output a character to the QDSS screen
204430391Skarels *
204530391Skarels ********************************************************************
204630391Skarels *
204730391Skarels *	calling convention:
204830391Skarels *
204930391Skarels *		blitc(chr);
205030391Skarels *		char chr;		;character to be displayed
205130391Skarels *
205230391Skarels ********/
205330391Skarels 
205430391Skarels blitc(unit, chr)
205530391Skarels int unit;
205630391Skarels char chr;
205730391Skarels {
205830391Skarels 	register struct adder *adder;
205930391Skarels 	register struct dga *dga;
206030391Skarels 	register int i;
2061*32012Smarc 	static	 short inescape[NQD];
206230391Skarels 
206330391Skarels 	short x;
206430391Skarels 
2065*32012Smarc 	/* init stuff  */
206630391Skarels 
206730391Skarels 	adder = (struct adder *) qdmap[unit].adder;
206830391Skarels 	dga = (struct dga *) qdmap[unit].dga;
206930391Skarels 
207030391Skarels 	chr &= 0x7F;
207130391Skarels 
2072*32012Smarc 	/*
2073*32012Smarc 	 *  Support cursor addressing so vi will work.
2074*32012Smarc 	 *  Decode for "\E=%.%." cursor motion description.
2075*32012Smarc 	 *
2076*32012Smarc 	 *  If we've seen an escape, grab up to three more
2077*32012Smarc 	 *  characters, bailing out if necessary.
2078*32012Smarc 	 */
2079*32012Smarc 	if (inescape[unit]) {
2080*32012Smarc 		switch (inescape[unit]++) {
2081*32012Smarc 		case 1:
2082*32012Smarc 			if (chr != '=') {
2083*32012Smarc 				/* bogus escape sequence */
2084*32012Smarc 				inescape[unit] = 0;
2085*32012Smarc 				blitc(unit, chr);
2086*32012Smarc 			}
2087*32012Smarc 			return(0);
2088*32012Smarc 		case 2:
2089*32012Smarc 			/* position row */
2090*32012Smarc 			cursor[unit].y = CHAR_HEIGHT * chr;
2091*32012Smarc 			if (cursor[unit].y > 863 - CHAR_HEIGHT)
2092*32012Smarc 				cursor[unit].y = 863 - CHAR_HEIGHT;
2093*32012Smarc 			dga->y_cursor = TRANY(cursor[unit].y);
2094*32012Smarc 			return(0);
2095*32012Smarc 		case 3:
2096*32012Smarc 			/* position column */
2097*32012Smarc 			cursor[unit].x = CHAR_WIDTH * chr;
2098*32012Smarc 			if (cursor[unit].x > 1024 - CHAR_WIDTH)
2099*32012Smarc 				cursor[unit].x = 1023 - CHAR_WIDTH;
2100*32012Smarc 			dga->x_cursor = TRANX(cursor[unit].x);
2101*32012Smarc 			inescape[unit] = 0;
2102*32012Smarc 			return(0);
2103*32012Smarc 		default:
2104*32012Smarc 			inescape[unit] = 0;
2105*32012Smarc 			blitc(unit, chr);
2106*32012Smarc 		}
2107*32012Smarc 	}
2108*32012Smarc 
2109*32012Smarc 
211030391Skarels 	switch (chr) {
211130391Skarels 
211230391Skarels 	    case '\r':			/* return char */
211330391Skarels 		cursor[unit].x = 0;
211430391Skarels 		dga->x_cursor = TRANX(cursor[unit].x);
211530391Skarels 		return(0);
211630391Skarels 
211730391Skarels 	    case '\t':			/* tab char */
211830391Skarels 
211930391Skarels 		for (i = 8 - ((cursor[unit].x >> 3) & 0x07); i > 0; --i) {
212030391Skarels 		    blitc(unit, ' ');
212130391Skarels 		}
212230391Skarels 		return(0);
212330391Skarels 
212430391Skarels 	    case '\n':			/* line feed char */
212530391Skarels 
212630391Skarels 		if ((cursor[unit].y += CHAR_HEIGHT) > (863 - CHAR_HEIGHT)) {
212730391Skarels 		    if (qdflags[unit].inuse & GRAPHIC_DEV) {
212830391Skarels 			cursor[unit].y = 0;
212930391Skarels 		    } else {
213030391Skarels 			cursor[unit].y -= CHAR_HEIGHT;
213130391Skarels 			scroll_up(adder);
213230391Skarels 		    }
213330391Skarels 		}
213430391Skarels 		dga->y_cursor = TRANY(cursor[unit].y);
213530391Skarels 		return(0);
213630391Skarels 
213730391Skarels 	    case '\b':			/* backspace char */
213830391Skarels 		if (cursor[unit].x > 0) {
2139*32012Smarc 		    /**** - REMOVED - CRTBS is a function of the line discipline
214030391Skarels 		    cursor[unit].x -= CHAR_WIDTH;
214130391Skarels 		    blitc(unit, ' ');
2142*32012Smarc 		    ****/
214330391Skarels 		    cursor[unit].x -= CHAR_WIDTH;
214430391Skarels 		    dga->x_cursor = TRANX(cursor[unit].x);
214530391Skarels 		}
214630391Skarels 		return(0);
214730391Skarels 
2148*32012Smarc 	    case CTRL(k):		/* cursor up */
2149*32012Smarc 		if (cursor[unit].y > 0) {
2150*32012Smarc 			cursor[unit].y -= CHAR_HEIGHT;
2151*32012Smarc 			dga->y_cursor = TRANY(cursor[unit].y);
2152*32012Smarc 		}
2153*32012Smarc 		return(0);
2154*32012Smarc 
2155*32012Smarc 	    case CTRL(^):		/* home cursor */
2156*32012Smarc 		cursor[unit].x = 0;
2157*32012Smarc 		dga->x_cursor = TRANX(cursor[unit].x);
2158*32012Smarc 		cursor[unit].y = 0;
2159*32012Smarc 		dga->y_cursor = TRANY(cursor[unit].y);
2160*32012Smarc 		return(0);
2161*32012Smarc 
2162*32012Smarc 	    case CTRL(l):		/* cursor right */
2163*32012Smarc 		if (cursor[unit].x < 1023 - CHAR_WIDTH) {
2164*32012Smarc 			cursor[unit].x += CHAR_WIDTH;
2165*32012Smarc 			dga->x_cursor = TRANX(cursor[unit].x);
2166*32012Smarc 		}
2167*32012Smarc 		return(0);
2168*32012Smarc 
2169*32012Smarc 	    case CTRL(z):		/* clear screen */
2170*32012Smarc 		setup_dragon(unit);
2171*32012Smarc 		clear_qd_screen(unit);
2172*32012Smarc 		/* and home cursor - termcap seems to assume this */
2173*32012Smarc 		cursor[unit].x = 0;
2174*32012Smarc 		dga->x_cursor = TRANX(cursor[unit].x);
2175*32012Smarc 		cursor[unit].y = 0;
2176*32012Smarc 		dga->y_cursor = TRANY(cursor[unit].y);
2177*32012Smarc 		return(0);
2178*32012Smarc 
2179*32012Smarc 	    case '\033':		/* start escape sequence */
2180*32012Smarc 		inescape[unit] = 1;
2181*32012Smarc 		return(0);
2182*32012Smarc 
218330391Skarels 	    default:
218430391Skarels 		if (chr < ' ' || chr > '~')
218530391Skarels 		    return(0);
218630391Skarels 	}
218730391Skarels 
2188*32012Smarc 	/* setup VIPER operand control registers  */
218930391Skarels 
219030391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0001);  /* select plane #0 */
219130391Skarels 	write_ID(adder, SRC1_OCR_B,
219230391Skarels 			EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY);
219330391Skarels 
219430391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x00FE);  /* select other planes */
219530391Skarels 	write_ID(adder, SRC1_OCR_B,
219630391Skarels 			EXT_SOURCE | INT_NONE | NO_ID | BAR_SHIFT_DELAY);
219730391Skarels 
219830391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x00FF);  /* select all planes */
219930391Skarels 	write_ID(adder, DST_OCR_B,
220030391Skarels 			EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
220130391Skarels 
220230391Skarels 	write_ID(adder, MASK_1, 0xFFFF);
220330391Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 1);
220430391Skarels 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
220530391Skarels 
2206*32012Smarc 	/* load DESTINATION origin and vectors  */
220730391Skarels 
220830391Skarels 	adder->fast_dest_dy = 0;
220930391Skarels 	adder->slow_dest_dx = 0;
221030391Skarels 	adder->error_1 = 0;
221130391Skarels 	adder->error_2 = 0;
221230391Skarels 
221330391Skarels 	adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL;
221430391Skarels 
221530391Skarels 	wait_status(adder, RASTEROP_COMPLETE);
221630391Skarels 
221730391Skarels 	adder->destination_x = cursor[unit].x;
221830391Skarels 	adder->fast_dest_dx = CHAR_WIDTH;
221930391Skarels 
222030391Skarels 	adder->destination_y = cursor[unit].y;
222130391Skarels 	adder->slow_dest_dy = CHAR_HEIGHT;
222230391Skarels 
2223*32012Smarc 	/* load SOURCE origin and vectors  */
222430391Skarels 
222530391Skarels 	adder->source_1_x = FONT_X + ((chr - ' ') * CHAR_WIDTH);
222630391Skarels 	adder->source_1_y = FONT_Y;
222730391Skarels 
222830391Skarels 	adder->source_1_dx = CHAR_WIDTH;
222930391Skarels 	adder->source_1_dy = CHAR_HEIGHT;
223030391Skarels 
223130391Skarels 	write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
223230391Skarels 	adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE;
223330391Skarels 
2234*32012Smarc 	/* update console cursor coordinates */
223530391Skarels 
223630391Skarels 	cursor[unit].x += CHAR_WIDTH;
223730391Skarels 	dga->x_cursor = TRANX(cursor[unit].x);
223830391Skarels 
2239*32012Smarc 	/* auto-wrap margin */
224030391Skarels 	if (cursor[unit].x > (1024 - CHAR_WIDTH)) {
224130391Skarels 	    blitc(unit, '\r');
224230391Skarels 	    blitc(unit, '\n');
224330391Skarels 	}
224430391Skarels 
224530391Skarels } /* blitc */
224630391Skarels 
224730391Skarels qdreset(){}
224830391Skarels qd_init(){}
224930391Skarels 
225030391Skarels /******************************************************************
225130391Skarels *
225230391Skarels *	INTERRUPT SERVICE ROUTINES START HERE:
225330391Skarels *
225430391Skarels ******************************************************************/
225530391Skarels 
225630391Skarels /*****************************************************************
225730391Skarels *
225830391Skarels *	qddint()... service "DMA DONE" interrupt condition
225930391Skarels *
226030391Skarels *****************************************************************/
226130391Skarels 
226230391Skarels qddint(qd)
226330391Skarels int qd;
226430391Skarels {
226530391Skarels 	register struct DMAreq_header *header;
226630391Skarels 	register struct DMAreq *request;
226730391Skarels 	register struct dga *dga;
226830391Skarels 	struct adder *adder;
226930391Skarels 
227030391Skarels 	int cookie;			/* DMA adrs for QDSS */
227130391Skarels 	int i;
227230391Skarels 
227330391Skarels 	spl4(); 			/* allow interval timer in */
227430391Skarels 
2275*32012Smarc 	/*
2276*32012Smarc 	* init pointers
2277*32012Smarc 	*/
227830391Skarels 
227930391Skarels 	header = DMAheader[qd]; 	    /* register for optimization */
228030391Skarels 	dga = (struct dga *) qdmap[qd].dga;
228130391Skarels 	adder = (struct adder *) qdmap[qd].adder;
228230391Skarels 
2283*32012Smarc 	/*
2284*32012Smarc 	* if this interrupt flagged as bogus for interrupt flushing purposes..
2285*32012Smarc 	*/
228630391Skarels 
228730391Skarels 	if (DMA_ISIGNORE(header)) {
228830391Skarels 	    DMA_CLRIGNORE(header);
228930391Skarels 	    return;
229030391Skarels 	}
229130391Skarels 
229230391Skarels /*----------------------------------------------------
229330391Skarels * dump a DMA hardware error message if appropriate */
229430391Skarels 
229530391Skarels 	if (dga->csr & DMA_ERR) {
229630391Skarels 
229730391Skarels 	    if (dga->csr & PARITY_ERR)
229830391Skarels 		mprintf("\nqd%d: qddint: DMA hardware parity fault.", qd);
229930391Skarels 
230030391Skarels 	    if (dga->csr & BUS_ERR)
230130391Skarels 		mprintf("\nqd%d: qddint: DMA hardware bus error.", qd);
230230391Skarels 	}
230330391Skarels 
230430391Skarels /*----------------------------------------
230530391Skarels * if this was a DMA from user space... */
230630391Skarels 
230730391Skarels 	if (qdflags[qd].user_dma) {
230830391Skarels 	    qdflags[qd].user_dma = 0;
230930391Skarels 	    wakeup((caddr_t)&qdflags[qd].user_dma);
231030391Skarels 	    return;
231130391Skarels 	}
231230391Skarels 
231330391Skarels /*------------------------------------------------------------------------
231430391Skarels * if we're doing DMA request queue services, field the error condition */
231530391Skarels 
231630391Skarels 	if (dga->csr & DMA_ERR) {
231730391Skarels 
231830391Skarels 	    dga->csr &= ~0x0600;		/* halt DMA (reset fifo) */
231930391Skarels 	    dga->csr |= DMA_ERR;		/* clear error condition */
232030391Skarels 	    adder->command = CANCEL;		/* cancel adder activity */
232130391Skarels 
232230391Skarels 	    DMA_SETERROR(header);	/* flag error in header status word */
232330391Skarels 	    DMA_CLRACTIVE(header);
232430391Skarels 	    header->DMAreq[header->oldest].DMAdone |= HARD_ERROR;
232530391Skarels 	    header->newest = header->oldest;
232630391Skarels 	    header->used = 0;
232730391Skarels 
232830391Skarels 	    if (rsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
232930391Skarels 		selwakeup(rsel[qd], 0);
233030391Skarels 		rsel[qd] = 0;
233130391Skarels 		qdflags[qd].selmask &= ~SEL_WRITE;
233230391Skarels 	    }
233330391Skarels 
233430391Skarels 	    if (dga->bytcnt_lo != 0) {
233530391Skarels 		dga->bytcnt_lo = 0;
233630391Skarels 		dga->bytcnt_hi = 0;
233730391Skarels 		DMA_SETIGNORE(header);
233830391Skarels 	    }
233930391Skarels 
234030391Skarels 	    return;
234130391Skarels 	}
234230391Skarels 
234330391Skarels /*----------------------------------------------------------------------------
234430391Skarels * if the DMA request queue is now becoming non-full, wakeup "select" client */
234530391Skarels 
234630391Skarels 	if (DMA_ISFULL(header)) {
234730391Skarels 
234830391Skarels 	    if (rsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
234930391Skarels 		selwakeup(rsel[qd], 0);
235030391Skarels 		rsel[qd] = 0;
235130391Skarels 		qdflags[qd].selmask &= ~SEL_WRITE;
235230391Skarels 	    }
235330391Skarels 	}
235430391Skarels 
235530391Skarels 	header->DMAreq[header->oldest].DMAdone |= REQUEST_DONE;
235630391Skarels 
235730391Skarels 	if (DMA_ISEMPTY(header)) {
235830391Skarels 	    mprintf("\nqd%d: qddint: unexpected interrupt", qd);
235930391Skarels 	    return;
236030391Skarels 	}
236130391Skarels 
236230391Skarels 	DMA_GETEND(header);	/* update request queue indices */
236330391Skarels 
236430391Skarels /*------------------------------------------------------------
236530391Skarels * if no more DMA pending, wake up "select" client and exit */
236630391Skarels 
236730391Skarels 	if (DMA_ISEMPTY(header)) {
236830391Skarels 
236930391Skarels 	    if (rsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
237030391Skarels 		selwakeup(rsel[qd], 0);
237130391Skarels 		rsel[qd] = 0;
237230391Skarels 		qdflags[qd].selmask &= ~SEL_WRITE;
237330391Skarels 	    }
237430391Skarels 
237530391Skarels 	    DMA_CLRACTIVE(header);  /* flag DMA done */
237630391Skarels 	    return;
237730391Skarels 	}
237830391Skarels 
237930391Skarels /*---------------------------
238030391Skarels * initiate next DMA xfer  */
238130391Skarels 
238230391Skarels 	request = DMA_GETBEGIN(header);
238330391Skarels 
238430391Skarels 	switch (request->DMAtype) {
238530391Skarels 
238630391Skarels 	    case DISPLIST:
238730391Skarels 		dga->csr |= DL_ENB;
238830391Skarels 		break;
238930391Skarels 
239030391Skarels 	    case PTOB:
239130391Skarels 		dga->csr |= PTOB_ENB;
239230391Skarels 		break;
239330391Skarels 
239430391Skarels 	    case BTOP:
239530391Skarels 		dga->csr |= BTOP_ENB;
239630391Skarels 		break;
239730391Skarels 
239830391Skarels 	    default:
239930391Skarels 		mprintf("\nqd%d: qddint: illegal DMAtype parameter.", qd);
240030391Skarels 		DMA_CLRACTIVE(header);	/* flag DMA done */
240130391Skarels 		return;
240230391Skarels 	}
240330391Skarels 
240430391Skarels 	if (request->DMAdone & COUNT_ZERO) {
240530391Skarels 	    dga->csr &= ~SET_DONE_FIFO;
240630391Skarels 	} else if (request->DMAdone & FIFO_EMPTY) {
240730391Skarels 	    dga->csr |= SET_DONE_FIFO;
240830391Skarels 	}
240930391Skarels 
241030391Skarels 	if (request->DMAdone & WORD_PACK)
241130391Skarels 	    dga->csr &= ~BYTE_DMA;
241230391Skarels 	else if (request->DMAdone & BYTE_PACK)
241330391Skarels 	    dga->csr |= BYTE_DMA;
241430391Skarels 
241530391Skarels 	dga->csr |= DMA_IE;
241630391Skarels 
241730391Skarels 	cookie = ((int)request->bufp - (int)header) + (int)header->QBAreg;
241830391Skarels 
241930391Skarels 	dga->adrs_lo = (short) cookie;
242030391Skarels 	dga->adrs_hi = (short) (cookie >> 16);
242130391Skarels 
242230391Skarels 	dga->bytcnt_lo = (short) request->length;
242330391Skarels 	dga->bytcnt_hi = (short) (request->length >> 16);
242430391Skarels 
242530391Skarels 	return;
242630391Skarels }
242730391Skarels 
242830391Skarels /*****************************************************************
242930391Skarels *
243030391Skarels *	qdaint()... ADDER interrupt service
243130391Skarels *
243230391Skarels *****************************************************************/
243330391Skarels 
243430391Skarels qdaint(qd)
243530391Skarels register int qd;
243630391Skarels {
243730391Skarels 	register struct adder *adder;
243830391Skarels 	struct color_buf *cbuf;
243930391Skarels 
244030391Skarels 	short stat;
244130391Skarels 	int i;
244230391Skarels 	register struct rgb *rgbp;
244330391Skarels 	register short *red;
244430391Skarels 	register short *green;
244530391Skarels 	register short *blue;
244630391Skarels 
244730391Skarels 	spl4(); 			/* allow interval timer in */
244830391Skarels 
244930391Skarels 	adder = (struct adder *) qdmap[qd].adder;
245030391Skarels 
245130391Skarels /*------------------------------------------------------------------------
245230391Skarels * service the vertical blank interrupt (VSYNC bit) by loading any pending
245330391Skarels * color map load request  */
245430391Skarels 
245530391Skarels 	if (adder->status & VSYNC) {
245630391Skarels 	    adder->status &= ~VSYNC;		/* clear the interrupt */
245730391Skarels 
245830391Skarels 	    cbuf = color_buf[qd];
245930391Skarels 	    if (cbuf->status & LOAD_COLOR_MAP) {
246030391Skarels 
246130391Skarels 		red = (short *) qdmap[qd].red;
246230391Skarels 		green = (short *) qdmap[qd].green;
246330391Skarels 		blue = (short *) qdmap[qd].blue;
246430391Skarels 
246530391Skarels 		for (i = cbuf->count, rgbp = cbuf->rgb; --i >= 0; rgbp++) {
246630391Skarels 
246730391Skarels 		    red[rgbp->offset] = (short) rgbp->red;
246830391Skarels 		    green[rgbp->offset] = (short) rgbp->green;
246930391Skarels 		    blue[rgbp->offset] = (short) rgbp->blue;
247030391Skarels 		}
247130391Skarels 
247230391Skarels 		cbuf->status &= ~LOAD_COLOR_MAP;
247330391Skarels 	    }
247430391Skarels 	}
247530391Skarels 
247630391Skarels /*-------------------------------------------------
247730391Skarels * service the scroll interrupt (FRAME_SYNC bit) */
247830391Skarels 
247930391Skarels 	if (adder->status & FRAME_SYNC) {
248030391Skarels 	    adder->status &= ~FRAME_SYNC;	/* clear the interrupt */
248130391Skarels 
248230391Skarels 	    if (scroll[qd]->status & LOAD_REGS) {
248330391Skarels 
248430391Skarels 		for ( i = 1000, adder->status = 0
248530391Skarels 		    ; i > 0  &&  !((stat = adder->status) & ID_SCROLL_READY)
248630391Skarels 		    ; --i);
248730391Skarels 
248830391Skarels 		if (i == 0) {
248930391Skarels 		    mprintf("\nqd%d: qdaint: timeout on ID_SCROLL_READY", qd);
249030391Skarels 		    return;
249130391Skarels 		}
249230391Skarels 
249330391Skarels 		adder->ID_scroll_data = scroll[qd]->viper_constant;
249430391Skarels 		adder->ID_scroll_command = ID_LOAD | SCROLL_CONSTANT;
249530391Skarels 
249630391Skarels 		adder->y_scroll_constant = scroll[qd]->y_scroll_constant;
249730391Skarels 		adder->y_offset_pending = scroll[qd]->y_offset;
249830391Skarels 
249930391Skarels 		if (scroll[qd]->status & LOAD_INDEX) {
250030391Skarels 
250130391Skarels 		    adder->x_index_pending = scroll[qd]->x_index_pending;
250230391Skarels 		    adder->y_index_pending = scroll[qd]->y_index_pending;
250330391Skarels 		}
250430391Skarels 
250530391Skarels 	    scroll[qd]->status = 0x00;
250630391Skarels 	    }
250730391Skarels 	}
250830391Skarels }
250930391Skarels 
251030391Skarels /*****************************************************************
251130391Skarels *
251230391Skarels *	qdiint()... DUART input interrupt service routine
251330391Skarels *
251430391Skarels *****************************************************************/
251530391Skarels 
251630391Skarels qdiint(qd)
251730391Skarels register int qd;
251830391Skarels {
251930391Skarels 	register struct _vs_event *event;
252030391Skarels 	register struct qdinput *eqh;
252130391Skarels 
252230391Skarels 	struct dga *dga;
252330391Skarels 	struct duart *duart;
252430391Skarels 	struct mouse_report *new_rep;
252530391Skarels 
252630391Skarels 	struct uba_device *ui;
252730391Skarels 	struct tty *tp;
252830391Skarels 
252930391Skarels 	char chr;
253030391Skarels 	int i,j;
253130391Skarels 	int k,l;
253230391Skarels 
253330391Skarels 	u_short status;
253430391Skarels 	u_short data;
253530391Skarels 	u_short key;
253630391Skarels 
253730391Skarels 	char do_wakeup = 0;		/* flag to do a select wakeup call */
253830391Skarels 	char a, b, c;			/* mouse button test variables */
253930391Skarels 
254030391Skarels 	spl4(); 			/* allow interval timer in */
254130391Skarels 
254230391Skarels 	eqh = eq_header[qd];		/* optimized as a register */
254330391Skarels 	new_rep = &current_rep[qd];
254430391Skarels 	duart = (struct duart *) qdmap[qd].duart;
254530391Skarels 
254630391Skarels /*-----------------------------------------
254730391Skarels * if the graphic device is turned on..	*/
254830391Skarels 
254930391Skarels 	if (qdflags[qd].inuse & GRAPHIC_DEV) {
255030391Skarels 
255130391Skarels 	    /*---------------
255230391Skarels 	    * empty DUART */
255330391Skarels 
255430391Skarels 	    while ((status = duart->statusA) & RCV_RDY	||
255530391Skarels 		   (status = duart->statusB) & RCV_RDY) {
255630391Skarels 
255730391Skarels 		/*---------------------------------
255830391Skarels 		* pick up LK-201 input (if any) */
255930391Skarels 
256030391Skarels 		if ((status = duart->statusA) & RCV_RDY) {
256130391Skarels 
256230391Skarels 		    /* if error condition, then reset it */
256330391Skarels 
256430391Skarels 		    if ((status = duart->statusA) & 0x70) {
256530391Skarels 			duart->cmdA = 0x40;
256630391Skarels 			continue;
256730391Skarels 		    }
256830391Skarels 
256930391Skarels 		    /* event queue full now? (overflow condition) */
257030391Skarels 
257130391Skarels 		    if (ISFULL(eqh) == TRUE) {
257230391Skarels 			mprintf("\nqd%d: qdiint: event queue overflow", qd);
257330391Skarels 			break;
257430391Skarels 		    }
257530391Skarels 
257630391Skarels 		    /*--------------------------------------
257730391Skarels 		    * Check for various keyboard errors  */
257830391Skarels 
257930391Skarels 		    key = duart->dataA & 0xFF;
258030391Skarels 
258130391Skarels 		    if( key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
258230391Skarels 			key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
258330391Skarels 			mprintf("\nqd%d: qdiint: keyboard error, code = %x",qd,key);
258430391Skarels 			return(0);
258530391Skarels 		    }
258630391Skarels 
258730391Skarels 		    if (key < LK_LOWEST)
258830391Skarels 			return(0);
258930391Skarels 
259030391Skarels 		    ++do_wakeup;	/* request a select wakeup call */
259130391Skarels 
259230391Skarels 		    event = PUTBEGIN(eqh);
259330391Skarels 		    PUTEND(eqh);
259430391Skarels 
259530391Skarels 		    event->vse_key = key;
259630391Skarels 		    event->vse_key &= 0x00FF;
259730391Skarels 		    event->vse_x = eqh->curs_pos.x;
259830391Skarels 		    event->vse_y = eqh->curs_pos.y;
259930391Skarels 		    event->vse_time = TOY;
260030391Skarels 		    event->vse_type = VSE_BUTTON;
260130391Skarels 		    event->vse_direction = VSE_KBTRAW;
260230391Skarels 		    event->vse_device = VSE_DKB;
260330391Skarels 		}
260430391Skarels 
260530391Skarels 		/*-------------------------------------
260630391Skarels 		* pick up the mouse input (if any)  */
260730391Skarels 
260830391Skarels 		if ((status = duart->statusB) & RCV_RDY  &&
260930391Skarels 		     qdflags[qd].pntr_id == MOUSE_ID) {
261030391Skarels 
261130391Skarels 		    if (status & 0x70) {
261230391Skarels 			duart->cmdB = 0x40;
261330391Skarels 			continue;
261430391Skarels 		    }
261530391Skarels 
261630391Skarels 		    /* event queue full now? (overflow condition) */
261730391Skarels 
261830391Skarels 		    if (ISFULL(eqh) == TRUE) {
261930391Skarels 			mprintf("\nqd%d: qdiint: event queue overflow", qd);
262030391Skarels 			break;
262130391Skarels 		    }
262230391Skarels 
262330391Skarels 		    data = duart->dataB;      /* get report byte */
262430391Skarels 		    ++new_rep->bytcnt;	      /* bump report byte count */
262530391Skarels 
262630391Skarels 		    /*---------------------------
262730391Skarels 		    * if 1st byte of report.. */
262830391Skarels 
262930391Skarels 		    if ( data & START_FRAME) {
263030391Skarels 			new_rep->state = data;
263130391Skarels 			if (new_rep->bytcnt > 1) {
263230391Skarels 			    new_rep->bytcnt = 1;    /* start of new frame */
263330391Skarels 			    continue;		    /* ..continue looking */
263430391Skarels 			}
263530391Skarels 		    }
263630391Skarels 
263730391Skarels 		    /*---------------------------
263830391Skarels 		    * if 2nd byte of report.. */
263930391Skarels 
264030391Skarels 		    else if (new_rep->bytcnt == 2) {
264130391Skarels 			new_rep->dx = data & 0x00FF;
264230391Skarels 		    }
264330391Skarels 
264430391Skarels 		    /*-------------------------------------------------
264530391Skarels 		    * if 3rd byte of report, load input event queue */
264630391Skarels 
264730391Skarels 		    else if (new_rep->bytcnt == 3) {
264830391Skarels 
264930391Skarels 			new_rep->dy = data & 0x00FF;
265030391Skarels 			new_rep->bytcnt = 0;
265130391Skarels 
265230391Skarels 			/*-----------------------------------
265330391Skarels 			* if mouse position has changed.. */
265430391Skarels 
265530391Skarels 			if (new_rep->dx != 0  ||  new_rep->dy != 0) {
265630391Skarels 
265730391Skarels 			    /*---------------------------------------------
265830391Skarels 			    * calculate acceleration factor, if needed	*/
265930391Skarels 
266030391Skarels 			    if (qdflags[qd].curs_acc > ACC_OFF) {
266130391Skarels 
266230391Skarels 				if (qdflags[qd].curs_thr <= new_rep->dx)
266330391Skarels 				    new_rep->dx +=
266430391Skarels 					(new_rep->dx - qdflags[qd].curs_thr)
266530391Skarels 					 * qdflags[qd].curs_acc;
266630391Skarels 
266730391Skarels 				if (qdflags[qd].curs_thr <= new_rep->dy)
266830391Skarels 				    new_rep->dy +=
266930391Skarels 					(new_rep->dy - qdflags[qd].curs_thr)
267030391Skarels 					 * qdflags[qd].curs_acc;
267130391Skarels 			    }
267230391Skarels 
267330391Skarels 			    /*-------------------------------------
267430391Skarels 			    * update cursor position coordinates */
267530391Skarels 
267630391Skarels 			    if (new_rep->state & X_SIGN) {
267730391Skarels 				eqh->curs_pos.x += new_rep->dx;
267830391Skarels 				if (eqh->curs_pos.x > 1023)
267930391Skarels 				    eqh->curs_pos.x = 1023;
268030391Skarels 			    }
268130391Skarels 			    else {
268230391Skarels 				eqh->curs_pos.x -= new_rep->dx;
268330391Skarels 				if (eqh->curs_pos.x < -15)
268430391Skarels 				    eqh->curs_pos.x = -15;
268530391Skarels 			    }
268630391Skarels 
268730391Skarels 			    if (new_rep->state & Y_SIGN) {
268830391Skarels 				 eqh->curs_pos.y -= new_rep->dy;
268930391Skarels 				 if (eqh->curs_pos.y < -15)
269030391Skarels 				     eqh->curs_pos.y = -15;
269130391Skarels 			    }
269230391Skarels 			    else {
269330391Skarels 				eqh->curs_pos.y += new_rep->dy;
269430391Skarels 				if (eqh->curs_pos.y > 863)
269530391Skarels 				    eqh->curs_pos.y = 863;
269630391Skarels 			    }
269730391Skarels 
269830391Skarels 			    /*---------------------------------
269930391Skarels 			    * update cursor screen position */
270030391Skarels 
270130391Skarels 			    dga = (struct dga *) qdmap[qd].dga;
270230391Skarels 			    dga->x_cursor = TRANX(eqh->curs_pos.x);
270330391Skarels 			    dga->y_cursor = TRANY(eqh->curs_pos.y);
270430391Skarels 
270530391Skarels 			    /*--------------------------------------------
270630391Skarels 			    * if cursor is in the box, no event report */
270730391Skarels 
270830391Skarels 			    if (eqh->curs_pos.x <= eqh->curs_box.right	&&
270930391Skarels 				eqh->curs_pos.x >= eqh->curs_box.left  &&
271030391Skarels 				eqh->curs_pos.y >= eqh->curs_box.top  &&
271130391Skarels 				eqh->curs_pos.y <= eqh->curs_box.bottom ) {
271230391Skarels 				    goto GET_MBUTTON;
271330391Skarels 			    }
271430391Skarels 
271530391Skarels 			    /*---------------------------------
271630391Skarels 			    * report the mouse motion event */
271730391Skarels 
271830391Skarels 			    event = PUTBEGIN(eqh);
271930391Skarels 			    PUTEND(eqh);
272030391Skarels 
272130391Skarels 			    ++do_wakeup;   /* request a select wakeup call */
272230391Skarels 
272330391Skarels 			    event->vse_x = eqh->curs_pos.x;
272430391Skarels 			    event->vse_y = eqh->curs_pos.y;
272530391Skarels 
272630391Skarels 			    event->vse_device = VSE_MOUSE;  /* mouse */
272730391Skarels 			    event->vse_type = VSE_MMOTION;  /* pos changed */
272830391Skarels 			    event->vse_key = 0;
272930391Skarels 			    event->vse_direction = 0;
273030391Skarels 			    event->vse_time = TOY;	/* time stamp */
273130391Skarels 			}
273230391Skarels 
273330391Skarels GET_MBUTTON:
273430391Skarels 			/*-------------------------------
273530391Skarels 			* if button state has changed */
273630391Skarels 
273730391Skarels 			a = new_rep->state & 0x07;    /*mask nonbutton bits */
273830391Skarels 			b = last_rep[qd].state & 0x07;
273930391Skarels 
274030391Skarels 			if (a ^ b) {
274130391Skarels 
274230391Skarels 			    for ( c = 1;  c < 8; c <<= 1) {
274330391Skarels 
274430391Skarels 				if (!( c & (a ^ b))) /* this button change? */
274530391Skarels 				    continue;
274630391Skarels 
274730391Skarels 				/* event queue full? (overflow condition) */
274830391Skarels 
274930391Skarels 				if (ISFULL(eqh) == TRUE) {
275030391Skarels 				    mprintf("\nqd%d: qdiint: event queue overflow", qd);
275130391Skarels 				    break;
275230391Skarels 				}
275330391Skarels 
275430391Skarels 				event = PUTBEGIN(eqh);	/* get new event */
275530391Skarels 				PUTEND(eqh);
275630391Skarels 
275730391Skarels 				++do_wakeup;   /* request select wakeup */
275830391Skarels 
275930391Skarels 				event->vse_x = eqh->curs_pos.x;
276030391Skarels 				event->vse_y = eqh->curs_pos.y;
276130391Skarels 
276230391Skarels 				event->vse_device = VSE_MOUSE;	/* mouse */
276330391Skarels 				event->vse_type = VSE_BUTTON; /* new button */
276430391Skarels 				event->vse_time = TOY;	      /* time stamp */
276530391Skarels 
276630391Skarels 				/* flag changed button and if up or down */
276730391Skarels 
276830391Skarels 				if (c == RIGHT_BUTTON)
276930391Skarels 				    event->vse_key = VSE_RIGHT_BUTTON;
277030391Skarels 				else if (c == MIDDLE_BUTTON)
277130391Skarels 				    event->vse_key = VSE_MIDDLE_BUTTON;
277230391Skarels 				else if (c == LEFT_BUTTON)
277330391Skarels 				    event->vse_key = VSE_LEFT_BUTTON;
277430391Skarels 
277530391Skarels 				/* set bit = button depressed */
277630391Skarels 
277730391Skarels 				if (c & a)
277830391Skarels 				    event->vse_direction = VSE_KBTDOWN;
277930391Skarels 				else
278030391Skarels 				    event->vse_direction = VSE_KBTUP;
278130391Skarels 			    }
278230391Skarels 			}
278330391Skarels 
278430391Skarels 			/* refresh last report */
278530391Skarels 
278630391Skarels 			last_rep[qd] = current_rep[qd];
278730391Skarels 
278830391Skarels 		    }  /* get last byte of report */
278930391Skarels 		} /* pickup mouse input */
279030391Skarels 
279130391Skarels 		/*--------------------------------
279230391Skarels 		* pickup tablet input, if any  */
279330391Skarels 
279430391Skarels 		else if ((status = duart->statusB) & RCV_RDY  &&
279530391Skarels 			 qdflags[qd].pntr_id == TABLET_ID) {
279630391Skarels 
279730391Skarels 		    if (status & 0x70) {
279830391Skarels 			duart->cmdB = 0x40;
279930391Skarels 			continue;
280030391Skarels 		    }
280130391Skarels 
280230391Skarels 		    /* event queue full now? (overflow condition) */
280330391Skarels 
280430391Skarels 		    if (ISFULL(eqh) == TRUE) {
280530391Skarels 			mprintf("\nqd%d: qdiint: event queue overflow", qd);
280630391Skarels 			break;
280730391Skarels 		    }
280830391Skarels 
280930391Skarels 		    data = duart->dataB;      /* get report byte */
281030391Skarels 		    ++new_rep->bytcnt;	      /* bump report byte count */
281130391Skarels 
281230391Skarels 		    /*---------------------------
281330391Skarels 		    * if 1st byte of report.. */
281430391Skarels 
281530391Skarels 		    if (data & START_FRAME) {
281630391Skarels 			new_rep->state = data;
281730391Skarels 			if (new_rep->bytcnt > 1) {
281830391Skarels 			    new_rep->bytcnt = 1;    /* start of new frame */
281930391Skarels 			    continue;		    /* ..continue looking */
282030391Skarels 			}
282130391Skarels 		    }
282230391Skarels 
282330391Skarels 		    /*---------------------------
282430391Skarels 		    * if 2nd byte of report.. */
282530391Skarels 
282630391Skarels 		    else if (new_rep->bytcnt == 2) {
282730391Skarels 			new_rep->dx = data & 0x3F;
282830391Skarels 		    }
282930391Skarels 
283030391Skarels 		    /*---------------------------
283130391Skarels 		    * if 3rd byte of report.. */
283230391Skarels 
283330391Skarels 		    else if (new_rep->bytcnt == 3) {
283430391Skarels 			new_rep->dx |= (data & 0x3F) << 6;
283530391Skarels 		    }
283630391Skarels 
283730391Skarels 		    /*---------------------------
283830391Skarels 		    * if 4th byte of report.. */
283930391Skarels 
284030391Skarels 		    else if (new_rep->bytcnt == 4) {
284130391Skarels 			new_rep->dy = data & 0x3F;
284230391Skarels 		    }
284330391Skarels 
284430391Skarels 		    /*-------------------------------------------------
284530391Skarels 		    * if 5th byte of report, load input event queue */
284630391Skarels 
284730391Skarels 		    else if (new_rep->bytcnt == 5) {
284830391Skarels 
284930391Skarels 			new_rep->dy |= (data & 0x3F) << 6;
285030391Skarels 			new_rep->bytcnt = 0;
285130391Skarels 
285230391Skarels 			/*-------------------------------------
285330391Skarels 			* update cursor position coordinates */
285430391Skarels 
285530391Skarels 			new_rep->dx /= qdflags[qd].tab_res;
285630391Skarels 			new_rep->dy = (2200 - new_rep->dy)
285730391Skarels 				      / qdflags[qd].tab_res;
285830391Skarels 
285930391Skarels 			if (new_rep->dx > 1023) {
286030391Skarels 			    new_rep->dx = 1023;
286130391Skarels 			}
286230391Skarels 			if (new_rep->dy > 863) {
286330391Skarels 			    new_rep->dy = 863;
286430391Skarels 			}
286530391Skarels 
286630391Skarels 			/*
286730391Skarels 			 * report an event if the puck/stylus has moved
286830391Skarels 			 */
286930391Skarels 
287030391Skarels 			if (eqh->curs_pos.x != new_rep->dx ||
287130391Skarels 			    eqh->curs_pos.y != new_rep->dy) {
287230391Skarels 
287330391Skarels 			    eqh->curs_pos.x = new_rep->dx;
287430391Skarels 			    eqh->curs_pos.y = new_rep->dy;
287530391Skarels 
287630391Skarels 			    /*---------------------------------
287730391Skarels 			    * update cursor screen position */
287830391Skarels 
287930391Skarels 			    dga = (struct dga *) qdmap[qd].dga;
288030391Skarels 			    dga->x_cursor = TRANX(eqh->curs_pos.x);
288130391Skarels 			    dga->y_cursor = TRANY(eqh->curs_pos.y);
288230391Skarels 
288330391Skarels 			    /*
288430391Skarels 			     * if cursor is in the box, no event report
288530391Skarels 			     */
288630391Skarels 
288730391Skarels 			    if (eqh->curs_pos.x <= eqh->curs_box.right	&&
288830391Skarels 				eqh->curs_pos.x >= eqh->curs_box.left  &&
288930391Skarels 				eqh->curs_pos.y >= eqh->curs_box.top  &&
289030391Skarels 				eqh->curs_pos.y <= eqh->curs_box.bottom ) {
289130391Skarels 				goto GET_TBUTTON;
289230391Skarels 			    }
289330391Skarels 
289430391Skarels 			    /*---------------------------------
289530391Skarels 			    * report the tablet motion event */
289630391Skarels 
289730391Skarels 			    event = PUTBEGIN(eqh);
289830391Skarels 			    PUTEND(eqh);
289930391Skarels 
290030391Skarels 			    ++do_wakeup;   /* request a select wakeup call */
290130391Skarels 
290230391Skarels 			    event->vse_x = eqh->curs_pos.x;
290330391Skarels 			    event->vse_y = eqh->curs_pos.y;
290430391Skarels 
290530391Skarels 			    event->vse_device = VSE_TABLET;  /* tablet */
290630391Skarels 			    /*
290730391Skarels 			     * right now, X handles tablet motion the same
290830391Skarels 			     * as mouse motion
290930391Skarels 			     */
291030391Skarels 			    event->vse_type = VSE_MMOTION;   /* pos changed */
291130391Skarels 			    event->vse_key = 0;
291230391Skarels 			    event->vse_direction = 0;
291330391Skarels 			    event->vse_time = TOY;	/* time stamp */
291430391Skarels 			}
291530391Skarels GET_TBUTTON:
291630391Skarels 			/*-------------------------------
291730391Skarels 			* if button state has changed */
291830391Skarels 
291930391Skarels 			a = new_rep->state & 0x1E;   /* mask nonbutton bits */
292030391Skarels 			b = last_rep[qd].state & 0x1E;
292130391Skarels 
292230391Skarels 			if (a ^ b) {
292330391Skarels 
292430391Skarels 			    /* event queue full now? (overflow condition) */
292530391Skarels 
292630391Skarels 			    if (ISFULL(eqh) == TRUE) {
292730391Skarels 				mprintf("\nqd%d: qdiint: event queue overflow",qd);
292830391Skarels 				break;
292930391Skarels 			    }
293030391Skarels 
293130391Skarels 			    event = PUTBEGIN(eqh);  /* get new event */
293230391Skarels 			    PUTEND(eqh);
293330391Skarels 
293430391Skarels 			    ++do_wakeup;   /* request a select wakeup call */
293530391Skarels 
293630391Skarels 			    event->vse_x = eqh->curs_pos.x;
293730391Skarels 			    event->vse_y = eqh->curs_pos.y;
293830391Skarels 
293930391Skarels 			    event->vse_device = VSE_TABLET;  /* tablet */
294030391Skarels 			    event->vse_type = VSE_BUTTON; /* button changed */
294130391Skarels 			    event->vse_time = TOY;	   /* time stamp */
294230391Skarels 
294330391Skarels 			    /* define the changed button and if up or down */
294430391Skarels 
294530391Skarels 			    for ( c = 1;  c <= 0x10; c <<= 1) {
294630391Skarels 				if (c & (a ^ b)) {
294730391Skarels 				    if (c == T_LEFT_BUTTON)
294830391Skarels 					event->vse_key = VSE_T_LEFT_BUTTON;
294930391Skarels 				    else if (c == T_FRONT_BUTTON)
295030391Skarels 					event->vse_key = VSE_T_FRONT_BUTTON;
295130391Skarels 				    else if (c == T_RIGHT_BUTTON)
295230391Skarels 					event->vse_key = VSE_T_RIGHT_BUTTON;
295330391Skarels 				    else if (c == T_BACK_BUTTON)
295430391Skarels 					event->vse_key = VSE_T_BACK_BUTTON;
295530391Skarels 				    break;
295630391Skarels 				}
295730391Skarels 			    }
295830391Skarels 
295930391Skarels 			    /* set bit = button depressed */
296030391Skarels 
296130391Skarels 			    if (c & a)
296230391Skarels 				event->vse_direction = VSE_KBTDOWN;
296330391Skarels 			    else
296430391Skarels 				event->vse_direction = VSE_KBTUP;
296530391Skarels 			}
296630391Skarels 
296730391Skarels 			/* refresh last report */
296830391Skarels 
296930391Skarels 			last_rep[qd] = current_rep[qd];
297030391Skarels 
297130391Skarels 		    } /* get last byte of report */
297230391Skarels 		} /* pick up tablet input */
297330391Skarels 
297430391Skarels 	    } /* while input available.. */
297530391Skarels 
297630391Skarels 	    /*---------------------
297730391Skarels 	    * do select wakeup	*/
297830391Skarels 
297930391Skarels 	    if (rsel[qd] && do_wakeup && qdflags[qd].selmask & SEL_READ) {
298030391Skarels 		selwakeup(rsel[qd], 0);
298130391Skarels 		rsel[qd] = 0;
298230391Skarels 		qdflags[qd].selmask &= ~SEL_READ;
298330391Skarels 		do_wakeup = 0;
298430391Skarels 	    }
298530391Skarels 	}
298630391Skarels 
298730391Skarels /*-----------------------------------------------------------------
298830391Skarels * if the graphic device is not turned on, this is console input */
298930391Skarels 
299030391Skarels 	else {
299130391Skarels 
299230391Skarels 	    ui = qdinfo[qd];
299330391Skarels 	    if (ui == 0 || ui->ui_alive == 0)
299430391Skarels 		return(0);
299530391Skarels 
299630391Skarels 	    tp = &qd_tty[qd << 2];
299730391Skarels 
299830391Skarels 	    /*--------------------------------------
299930391Skarels 	    * Get a character from the keyboard. */
300030391Skarels 
300130391Skarels 	    while ((status = duart->statusA) & RCV_RDY) {
300230391Skarels 
300330391Skarels 		key = duart->dataA;
300430391Skarels 		key &= 0xFF;
300530391Skarels 
300630391Skarels 		/*--------------------------------------
300730391Skarels 		* Check for various keyboard errors  */
300830391Skarels 
300930391Skarels 		if( key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
301030391Skarels 		    key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
301130391Skarels 			mprintf("\nqd%d: qdiint: Keyboard error, code = %x",qd,key);
301230391Skarels 			return(0);
301330391Skarels 		}
301430391Skarels 
301530391Skarels 		if (key < LK_LOWEST)
301630391Skarels 		    return(0);
301730391Skarels 
301830391Skarels 		/*---------------------------------
301930391Skarels 		* See if its a state change key */
302030391Skarels 
302130391Skarels 		switch (key) {
302230391Skarels 
302330391Skarels 		    case LOCK:
302430391Skarels 			q_keyboard.lock ^= 0xffff;	/* toggle */
302530391Skarels 			if (q_keyboard.lock)
302630391Skarels 			    led_control(qd, LK_LED_ENABLE, LK_LED_LOCK);
302730391Skarels 			else
302830391Skarels 			    led_control(qd, LK_LED_DISABLE, LK_LED_LOCK);
302930391Skarels 			return;
303030391Skarels 
303130391Skarels 		    case SHIFT:
303230391Skarels 			q_keyboard.shift ^= 0xFFFF;
303330391Skarels 			return;
303430391Skarels 
303530391Skarels 		    case CNTRL:
303630391Skarels 			q_keyboard.cntrl ^= 0xFFFF;
303730391Skarels 			return;
303830391Skarels 
303930391Skarels 		    case ALLUP:
304030391Skarels 			q_keyboard.cntrl = 0;
304130391Skarels 			q_keyboard.shift = 0;
304230391Skarels 			return;
304330391Skarels 
304430391Skarels 		    case REPEAT:
304530391Skarels 			chr = q_keyboard.last;
304630391Skarels 			break;
304730391Skarels 
304830391Skarels 		    /*-------------------------------------------------------
304930391Skarels 		    * Test for cntrl characters. If set, see if the character
305030391Skarels 		    * is elligible to become a control character. */
305130391Skarels 
305230391Skarels 		    default:
305330391Skarels 
305430391Skarels 			if (q_keyboard.cntrl) {
305530391Skarels 				chr = q_key[key];
305630391Skarels 				if (chr >= ' ' && chr <= '~')
305730391Skarels 				    chr &= 0x1F;
305830391Skarels 			}
305930391Skarels 			else if( q_keyboard.lock || q_keyboard.shift )
306030391Skarels 			    chr = q_shift_key[key];
306130391Skarels 			else
306230391Skarels 			    chr = q_key[key];
306330391Skarels 			break;
306430391Skarels 		}
306530391Skarels 
306630391Skarels 		q_keyboard.last = chr;
306730391Skarels 
306830391Skarels 		/*-----------------------------------
306930391Skarels 		* Check for special function keys */
307030391Skarels 
307130391Skarels 		if (chr & 0x80) {
307230391Skarels 			char *string;
307330391Skarels 			string = q_special[chr & 0x7F];
307430391Skarels 			while(*string)
307530391Skarels 			    (*linesw[tp->t_line].l_rint)(*string++, tp);
307630391Skarels 		}
307730391Skarels 		else {
307830391Skarels 			(*linesw[tp->t_line].l_rint)(chr, tp);
307930391Skarels 		}
308030391Skarels 	    }
308130391Skarels 	}
308230391Skarels 
308330391Skarels 	return(0);
308430391Skarels 
308530391Skarels } /* qdiint */
308630391Skarels 
308730391Skarels /******************************************************************
308830391Skarels *
308930391Skarels *	THE SUBROUTINES START HERE:
309030391Skarels *
309130391Skarels ******************************************************************/
309230391Skarels 
309330391Skarels /*****************************************************************
309430391Skarels *
309530391Skarels *	clear_qd_screen()... clear the QDSS screen
309630391Skarels *
309730391Skarels ******************************************************************
309830391Skarels *
309930391Skarels *			     >>> NOTE <<<
310030391Skarels *
310130391Skarels *   This code requires that certain adder initialization be valid.  To
310230391Skarels *   assure that this requirement is satisfied, this routine should be
310330391Skarels *   called only after calling the "setup_dragon()" function.
310430391Skarels *
310530391Skarels *   Clear the bitmap a piece at a time. Since the fast scroll clear
310630391Skarels *   only clears the current displayed portion of the bitmap put a
310730391Skarels *   temporary value in the y limit register so we can access whole
310830391Skarels *   bitmap
310930391Skarels *
311030391Skarels ****************/
311130391Skarels 
311230391Skarels clear_qd_screen(unit)
311330391Skarels int unit;
311430391Skarels {
311530391Skarels 	register struct adder *adder;
311630391Skarels 	adder = (struct adder *) qdmap[unit].adder;
311730391Skarels 
311830391Skarels 	adder->x_limit = 1024;
311930391Skarels 	adder->y_limit = 2048 - CHAR_HEIGHT;
312030391Skarels 	adder->y_offset_pending = 0;
312130391Skarels 
312230391Skarels 	wait_status(adder, VSYNC);	/* wait at LEAST 1 full frame */
312330391Skarels 	wait_status(adder, VSYNC);
312430391Skarels 
312530391Skarels 	adder->y_scroll_constant = SCROLL_ERASE;
312630391Skarels 
312730391Skarels 	wait_status(adder, VSYNC);
312830391Skarels 	wait_status(adder, VSYNC);
312930391Skarels 
313030391Skarels 	adder->y_offset_pending = 864;
313130391Skarels 
313230391Skarels 	wait_status(adder, VSYNC);
313330391Skarels 	wait_status(adder, VSYNC);
313430391Skarels 
313530391Skarels 	adder->y_scroll_constant = SCROLL_ERASE;
313630391Skarels 
313730391Skarels 	wait_status(adder, VSYNC);
313830391Skarels 	wait_status(adder, VSYNC);
313930391Skarels 
314030391Skarels 	adder->y_offset_pending = 1728;
314130391Skarels 
314230391Skarels 	wait_status(adder, VSYNC);
314330391Skarels 	wait_status(adder, VSYNC);
314430391Skarels 
314530391Skarels 	adder->y_scroll_constant = SCROLL_ERASE;
314630391Skarels 
314730391Skarels 	wait_status(adder, VSYNC);
314830391Skarels 	wait_status(adder, VSYNC);
314930391Skarels 
315030391Skarels 	adder->y_offset_pending = 0;	 /* back to normal */
315130391Skarels 
315230391Skarels 	wait_status(adder, VSYNC);
315330391Skarels 	wait_status(adder, VSYNC);
315430391Skarels 
315530391Skarels 	adder->x_limit = MAX_SCREEN_X;
315630391Skarels 	adder->y_limit = MAX_SCREEN_Y + FONT_HEIGHT;
315730391Skarels 
315830391Skarels } /* clear_qd_screen */
315930391Skarels 
316030391Skarels /**********************************************************************
316130391Skarels *
316230391Skarels *	qdputc()... route kernel console output to display destination
316330391Skarels *
316430391Skarels ***********************************************************************
316530391Skarels *
316630391Skarels *	calling convention:
316730391Skarels *
316830391Skarels *		qdputc(chr);
316930391Skarels *
317030391Skarels *	where:	char chr;	 ;character for output
317130391Skarels *
317230391Skarels ****************/
317330391Skarels 
317430391Skarels qdputc(chr)
317530391Skarels register char chr;
317630391Skarels {
317730391Skarels 
3178*32012Smarc 	/* if system is now physical, forget it (ie: crash DUMP) */
317930391Skarels 	if ( (mfpr(MAPEN) & 1) == 0 )
318030391Skarels 	    return;
318130391Skarels 
3182*32012Smarc         blitc(0, chr & 0xff);
3183*32012Smarc 	if ((chr & 0177) == '\n')
3184*32012Smarc 		blitc(0, '\r');
318530391Skarels 
318630391Skarels 
318730391Skarels } /* qdputc */
318830391Skarels 
318930391Skarels /*******************************************************************
319030391Skarels *
319130391Skarels *	qdgetc()... get a character from the LK201
319230391Skarels *
319330391Skarels *******************************************************************
319430391Skarels *
319530391Skarels *	calling convention:
319630391Skarels *
319730391Skarels *		qdgetc();
319830391Skarels *
319930391Skarels *	returns:  the character read.
320030391Skarels *
320130391Skarels ****************/
320230391Skarels 
320330391Skarels qdgetc()
320430391Skarels {
320530391Skarels 	register short key;
320630391Skarels 	register char chr;
320730391Skarels 	register struct duart *duart;
320830391Skarels 
320930391Skarels 	u_int status;
321030391Skarels 
321130391Skarels 	duart = (struct duart *) qdmap[0].duart;
321230391Skarels 
321330391Skarels 	/*--------------------------------------
321430391Skarels 	* Get a character from the keyboard. */
321530391Skarels 
321630391Skarels LOOP:
321730391Skarels 	while (!((status = duart->statusA) & RCV_RDY))
321830391Skarels 			;
321930391Skarels 
322030391Skarels 	key = duart->dataA;
322130391Skarels 	key &= 0xFF;
322230391Skarels 
322330391Skarels 	/*--------------------------------------
322430391Skarels 	* Check for various keyboard errors  */
322530391Skarels 
322630391Skarels 	if( key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
322730391Skarels 	    key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
322830391Skarels 		printf("Keyboard error, code = %x\n", key);
322930391Skarels 		return(0);
323030391Skarels 	}
323130391Skarels 
323230391Skarels 	if (key < LK_LOWEST)
323330391Skarels 	    return(0);
323430391Skarels 
323530391Skarels 	/*---------------------------------
323630391Skarels 	* See if its a state change key */
323730391Skarels 
323830391Skarels 	switch (key) {
323930391Skarels 
324030391Skarels 	    case LOCK:
324130391Skarels 		q_keyboard.lock ^= 0xffff;	/* toggle */
324230391Skarels 		if (q_keyboard.lock)
324330391Skarels 		    led_control(LK_LED_ENABLE, LK_LED_LOCK);
324430391Skarels 		else
324530391Skarels 		    led_control(LK_LED_DISABLE, LK_LED_LOCK);
324630391Skarels 		goto LOOP;
324730391Skarels 
324830391Skarels 	    case SHIFT:
324930391Skarels 		q_keyboard.shift ^= 0xFFFF;
325030391Skarels 		goto LOOP;
325130391Skarels 
325230391Skarels 	    case CNTRL:
325330391Skarels 		q_keyboard.cntrl ^= 0xFFFF;
325430391Skarels 		goto LOOP;
325530391Skarels 
325630391Skarels 	    case ALLUP:
325730391Skarels 		q_keyboard.cntrl = 0;
325830391Skarels 		q_keyboard.shift = 0;
325930391Skarels 		goto LOOP;
326030391Skarels 
326130391Skarels 	    case REPEAT:
326230391Skarels 		chr = q_keyboard.last;
326330391Skarels 		break;
326430391Skarels 
326530391Skarels 	    /*-------------------------------------------------------
326630391Skarels 	    * Test for cntrl characters. If set, see if the character
326730391Skarels 	    * is elligible to become a control character. */
326830391Skarels 
326930391Skarels 	    default:
327030391Skarels 
327130391Skarels 		if (q_keyboard.cntrl) {
327230391Skarels 		    chr = q_key[key];
327330391Skarels 		    if (chr >= ' ' && chr <= '~')
327430391Skarels 			chr &= 0x1F;
327530391Skarels 		}
327630391Skarels 		else if ( q_keyboard.lock || q_keyboard.shift )
327730391Skarels 		    chr = q_shift_key[key];
327830391Skarels 		else
327930391Skarels 		    chr = q_key[key];
328030391Skarels 		break;
328130391Skarels 	}
328230391Skarels 
328330391Skarels 	if (chr < ' ' && chr > '~')	/* if input is non-displayable */
328430391Skarels 	    return(0);			/* ..then pitch it! */
328530391Skarels 
328630391Skarels 	q_keyboard.last = chr;
328730391Skarels 
328830391Skarels 	/*-----------------------------------
328930391Skarels 	* Check for special function keys */
329030391Skarels 
329130391Skarels 	if (chr & 0x80) 		/* pitch the function keys */
329230391Skarels 	    return(0);
329330391Skarels 	else
329430391Skarels 	    return(chr);
329530391Skarels 
329630391Skarels } /* qdgetc */
329730391Skarels 
329830391Skarels /**********************************************************************
329930391Skarels *
330030391Skarels *	ldcursor()... load the mouse cursor's template RAM bitmap
330130391Skarels *
330230391Skarels *********************************************************************
330330391Skarels *
330430391Skarels *	calling convention:
330530391Skarels *
330630391Skarels *		ldcursor(unit, bitmap);
330730391Skarels *		u_int unit;
330830391Skarels *		short *bitmap;
330930391Skarels *
331030391Skarels ****************/
331130391Skarels 
331230391Skarels ldcursor(unit, bitmap)
331330391Skarels u_int unit;
331430391Skarels short *bitmap;
331530391Skarels {
331630391Skarels 	register struct dga *dga;
331730391Skarels 	register short *temp;
331830391Skarels 	register int i;
331930391Skarels 
332030391Skarels 	int cursor;
332130391Skarels 
332230391Skarels 	dga = (struct dga *) qdmap[unit].dga;
332330391Skarels 	temp = (short *) qdmap[unit].template;
332430391Skarels 
332530391Skarels 	if (dga->csr & CURS_ENB) {	/* if the cursor is enabled.. */
332630391Skarels 	    cursor = -1;		/* ..note that.. */
332730391Skarels 	    dga->csr &= ~CURS_ENB;	/* ..and shut it off */
332830391Skarels 	}
332930391Skarels 	else {
333030391Skarels 	    cursor = 0;
333130391Skarels 	}
333230391Skarels 
333330391Skarels 	dga->csr &= ~CURS_ENB;		/* shut off the cursor */
333430391Skarels 
333530391Skarels 	temp += (8 * 1024) - 32;	/* cursor is 32 WORDS from the end */
333630391Skarels 					/* ..of the 8k WORD template space */
333730391Skarels 	for (i = 0; i < 32; ++i)
333830391Skarels 	    *temp++ = *bitmap++;
333930391Skarels 
334030391Skarels 	if (cursor) {			/* if cursor was enabled.. */
334130391Skarels 	    dga->csr |= CURS_ENB;	/* ..turn it back on */
334230391Skarels 	}
334330391Skarels 
334430391Skarels 	return(0);
334530391Skarels 
334630391Skarels } /* ldcursor */
334730391Skarels 
334830391Skarels /**********************************************************************
334930391Skarels *
335030391Skarels *	ldfont()... put the console font in the QDSS off-screen memory
335130391Skarels *
335230391Skarels ***********************************************************************
335330391Skarels *
335430391Skarels *	calling convention:
335530391Skarels *
335630391Skarels *		ldfont(unit);
335730391Skarels *		u_int unit;	;QDSS unit number
335830391Skarels *
335930391Skarels ****************/
336030391Skarels 
336130391Skarels ldfont(unit)
336230391Skarels u_int unit;
336330391Skarels {
336430391Skarels 	register struct adder *adder;
336530391Skarels 
336630391Skarels 	int i;		/* scratch variables */
336730391Skarels 	int j;
336830391Skarels 	int k;
336930391Skarels 	short packed;
337030391Skarels 
337130391Skarels 	adder = (struct adder *) qdmap[unit].adder;
337230391Skarels 
337330391Skarels /*------------------------------------------
337430391Skarels * setup VIPER operand control registers  */
337530391Skarels 
337630391Skarels 	write_ID(adder, MASK_1, 0xFFFF);
337730391Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
337830391Skarels 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
337930391Skarels 
338030391Skarels 	write_ID(adder, SRC1_OCR_B,
338130391Skarels 			EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY);
338230391Skarels 	write_ID(adder, SRC2_OCR_B,
338330391Skarels 			EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY);
338430391Skarels 	write_ID(adder, DST_OCR_B,
338530391Skarels 			EXT_SOURCE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
338630391Skarels 
338730391Skarels 	adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL;
338830391Skarels 
338930391Skarels /*--------------------------
339030391Skarels * load destination data  */
339130391Skarels 
339230391Skarels 	wait_status(adder, RASTEROP_COMPLETE);
339330391Skarels 
339430391Skarels 	adder->destination_x = FONT_X;
339530391Skarels 	adder->destination_y = FONT_Y;
339630391Skarels 	adder->fast_dest_dx = FONT_WIDTH;
339730391Skarels 	adder->slow_dest_dy = CHAR_HEIGHT;
339830391Skarels 
339930391Skarels /*---------------------------------------
340030391Skarels * setup for processor to bitmap xfer  */
340130391Skarels 
340230391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0001);
340330391Skarels 	adder->cmd = PBT | OCRB | 2 | DTE | 2;
340430391Skarels 
340530391Skarels /*-----------------------------------------------
340630391Skarels * iteratively do the processor to bitmap xfer */
340730391Skarels 
340830391Skarels 	for (i = 0; i < ROWS; ++i) {
340930391Skarels 
341030391Skarels 	    /* PTOB a scan line */
341130391Skarels 
341230391Skarels 	    for (j = 0, k = i; j < 48; ++j) {
341330391Skarels 
341430391Skarels 		/* PTOB one scan of a char cell */
341530391Skarels 
341630391Skarels 		packed = q_font[k];
341730391Skarels 		k += ROWS;
341830391Skarels 		packed |= ((short)q_font[k] << 8);
341930391Skarels 		k += ROWS;
342030391Skarels 
342130391Skarels 		wait_status(adder, TX_READY);
342230391Skarels 		adder->id_data = packed;
342330391Skarels 	    }
342430391Skarels 	}
342530391Skarels 
342630391Skarels }  /* ldfont */
342730391Skarels 
342830391Skarels /*********************************************************************
342930391Skarels *
343030391Skarels *	led_control()... twiddle LK-201 LED's
343130391Skarels *
343230391Skarels **********************************************************************
343330391Skarels *
343430391Skarels *	led_control(unit, cmd, led_mask);
343530391Skarels *	u_int unit;	QDSS number
343630391Skarels *	int cmd;	LED enable/disable command
343730391Skarels *	int led_mask;	which LED(s) to twiddle
343830391Skarels *
343930391Skarels *************/
344030391Skarels 
344130391Skarels led_control(unit, cmd, led_mask)
344230391Skarels u_int unit;
344330391Skarels int cmd;
344430391Skarels int led_mask;
344530391Skarels {
344630391Skarels 	register int i;
344730391Skarels 	register int status;
344830391Skarels 	register struct duart *duart;
344930391Skarels 
345030391Skarels 	duart = (struct duart *) qdmap[unit].duart;
345130391Skarels 
345230391Skarels 	for (i = 1000; i > 0; --i) {
345330391Skarels 	    if ((status = duart->statusA) & XMT_RDY) {
345430391Skarels 		duart->dataA = cmd;
345530391Skarels 		break;
345630391Skarels 	    }
345730391Skarels 	}
345830391Skarels 
345930391Skarels 	for (i = 1000; i > 0; --i) {
346030391Skarels 	    if ((status = duart->statusA) & XMT_RDY) {
346130391Skarels 		duart->dataA = led_mask;
346230391Skarels 		break;
346330391Skarels 	    }
346430391Skarels 	}
346530391Skarels 
346630391Skarels 	if (i == 0)
346730391Skarels 	    return(BAD);
346830391Skarels 
346930391Skarels 	return(GOOD);
347030391Skarels 
347130391Skarels } /* led_control */
347230391Skarels 
347330391Skarels /*******************************************************************
347430391Skarels *
347530391Skarels *	scroll_up()... move the screen up one character height
347630391Skarels *
347730391Skarels ********************************************************************
347830391Skarels *
347930391Skarels *	calling convention:
348030391Skarels *
348130391Skarels *		scroll_up(adder);
348230391Skarels *		struct adder *adder;	;address of adder
348330391Skarels *
348430391Skarels ********/
348530391Skarels 
348630391Skarels scroll_up(adder)
348730391Skarels register struct adder *adder;
348830391Skarels {
348930391Skarels 
349030391Skarels /*------------------------------------------
349130391Skarels * setup VIPER operand control registers  */
349230391Skarels 
349330391Skarels 	wait_status(adder, ADDRESS_COMPLETE);
349430391Skarels 
349530391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x00FF);  /* select all planes */
349630391Skarels 
349730391Skarels 	write_ID(adder, MASK_1, 0xFFFF);
349830391Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
349930391Skarels 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
350030391Skarels 
350130391Skarels 	write_ID(adder, SRC1_OCR_B,
350230391Skarels 			EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY);
350330391Skarels 	write_ID(adder, DST_OCR_B,
350430391Skarels 			EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
350530391Skarels 
350630391Skarels /*----------------------------------------
350730391Skarels * load DESTINATION origin and vectors  */
350830391Skarels 
350930391Skarels 	adder->fast_dest_dy = 0;
351030391Skarels 	adder->slow_dest_dx = 0;
351130391Skarels 	adder->error_1 = 0;
351230391Skarels 	adder->error_2 = 0;
351330391Skarels 
351430391Skarels 	adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL;
351530391Skarels 
351630391Skarels 	adder->destination_x = 0;
351730391Skarels 	adder->fast_dest_dx = 1024;
351830391Skarels 
351930391Skarels 	adder->destination_y = 0;
352030391Skarels 	adder->slow_dest_dy = 864 - CHAR_HEIGHT;
352130391Skarels 
352230391Skarels /*-----------------------------------
352330391Skarels * load SOURCE origin and vectors  */
352430391Skarels 
352530391Skarels 	adder->source_1_x = 0;
352630391Skarels 	adder->source_1_dx = 1024;
352730391Skarels 
352830391Skarels 	adder->source_1_y = 0 + CHAR_HEIGHT;
352930391Skarels 	adder->source_1_dy = 864 - CHAR_HEIGHT;
353030391Skarels 
353130391Skarels 	write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
353230391Skarels 	adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE;
353330391Skarels 
353430391Skarels /*--------------------------------------------
353530391Skarels * do a rectangle clear of last screen line */
353630391Skarels 
353730391Skarels 	write_ID(adder, MASK_1, 0xffff);
353830391Skarels 	write_ID(adder, SOURCE, 0xffff);
353930391Skarels 	write_ID(adder,DST_OCR_B,
354030391Skarels 		(EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY));
354130391Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 0);
354230391Skarels 	adder->error_1 = 0;
354330391Skarels 	adder->error_2 = 0;
354430391Skarels 	adder->slow_dest_dx = 0;	/* set up the width of	*/
354530391Skarels 	adder->slow_dest_dy = CHAR_HEIGHT;	/* rectangle */
354630391Skarels 
354730391Skarels 	adder->rasterop_mode = (NORMAL | DST_WRITE_ENABLE) ;
354830391Skarels 	wait_status(adder, RASTEROP_COMPLETE);
354930391Skarels 	adder->destination_x = 0;
355030391Skarels 	adder->destination_y = 864 - CHAR_HEIGHT;
355130391Skarels 
355230391Skarels 	adder->fast_dest_dx = 1024;	/* set up the height	*/
355330391Skarels 	adder->fast_dest_dy = 0;	/* of rectangle 	*/
355430391Skarels 
355530391Skarels 	write_ID(adder, LU_FUNCTION_R2, (FULL_SRC_RESOLUTION | LF_SOURCE));
355630391Skarels 	adder->cmd = (RASTEROP | OCRB | LF_R2 | DTE ) ;
355730391Skarels 
355830391Skarels } /* scroll_up */
355930391Skarels 
356030391Skarels /********************************************************************
356130391Skarels *
356230391Skarels *	init_shared()... init shared memory pointers and structures
356330391Skarels *
356430391Skarels *********************************************************************
356530391Skarels *
356630391Skarels *	calling convention:
356730391Skarels *
356830391Skarels *		init_shared(unit);
356930391Skarels *		u_int unit;
357030391Skarels *
357130391Skarels ****************/
357230391Skarels 
357330391Skarels init_shared(unit)
357430391Skarels register u_int unit;
357530391Skarels {
357630391Skarels 	register struct dga *dga;
357730391Skarels 
357830391Skarels 	dga = (struct dga *) qdmap[unit].dga;
357930391Skarels 
358030391Skarels /*--------------------------------------------------
358130391Skarels * initialize the event queue pointers and header */
358230391Skarels 
358330391Skarels 	eq_header[unit] = (struct qdinput *)
358430391Skarels 			  ((((int)event_shared & ~(0x01FF)) + 512)
358530391Skarels 			   + (EVENT_BUFSIZE * unit));
358630391Skarels 
358730391Skarels 	eq_header[unit]->curs_pos.x = 0;
358830391Skarels 	eq_header[unit]->curs_pos.y = 0;
358930391Skarels 
359030391Skarels 	dga->x_cursor = TRANX(eq_header[unit]->curs_pos.x);
359130391Skarels 	dga->y_cursor = TRANY(eq_header[unit]->curs_pos.y);
359230391Skarels 
359330391Skarels 	eq_header[unit]->curs_box.left = 0;
359430391Skarels 	eq_header[unit]->curs_box.right = 0;
359530391Skarels 	eq_header[unit]->curs_box.top = 0;
359630391Skarels 	eq_header[unit]->curs_box.bottom = 0;
359730391Skarels 
359830391Skarels /*---------------------------------------------------------
359930391Skarels * assign a pointer to the DMA I/O buffer for this QDSS. */
360030391Skarels 
360130391Skarels 	DMAheader[unit] = (struct DMAreq_header *)
360230391Skarels 			  (((int)(&DMA_shared[0] + 512) & ~0x1FF)
360330391Skarels 			   + (DMAbuf_size * unit));
360430391Skarels 
360530391Skarels 	DMAheader[unit]->DMAreq = (struct DMAreq *) ((int)DMAheader[unit]
360630391Skarels 				  + sizeof(struct DMAreq_header));
360730391Skarels 
360830391Skarels 	DMAheader[unit]->QBAreg = 0;
360930391Skarels 	DMAheader[unit]->status = 0;
361030391Skarels 	DMAheader[unit]->shared_size = DMAbuf_size;
361130391Skarels 	DMAheader[unit]->used = 0;
361230391Skarels 	DMAheader[unit]->size = 10;	/* default = 10 requests */
361330391Skarels 	DMAheader[unit]->oldest = 0;
361430391Skarels 	DMAheader[unit]->newest = 0;
361530391Skarels 
361630391Skarels /*-----------------------------------------------------------
361730391Skarels * assign a pointer to the scroll structure for this QDSS. */
361830391Skarels 
361930391Skarels 	scroll[unit] = (struct scroll *)
362030391Skarels 			 (((int)(&scroll_shared[0] + 512) & ~0x1FF)
362130391Skarels 			   + (sizeof(struct scroll) * unit));
362230391Skarels 
362330391Skarels 	scroll[unit]->status = 0;
362430391Skarels 	scroll[unit]->viper_constant = 0;
362530391Skarels 	scroll[unit]->y_scroll_constant = 0;
362630391Skarels 	scroll[unit]->y_offset = 0;
362730391Skarels 	scroll[unit]->x_index_pending = 0;
362830391Skarels 	scroll[unit]->y_index_pending = 0;
362930391Skarels 
363030391Skarels /*----------------------------------------------------------------
363130391Skarels * assign a pointer to the color map write buffer for this QDSS */
363230391Skarels 
363330391Skarels 	color_buf[unit] = (struct color_buf *)
363430391Skarels 			   (((int)(&color_shared[0] + 512) & ~0x1FF)
363530391Skarels 			    + (COLOR_BUFSIZ * unit));
363630391Skarels 
363730391Skarels 	color_buf[unit]->status = 0;
363830391Skarels 	color_buf[unit]->count = 0;
363930391Skarels 
364030391Skarels } /* init_shared */
364130391Skarels 
364230391Skarels /*********************************************************************
364330391Skarels *
364430391Skarels *	setup_dragon()... init the ADDER, VIPER, bitmaps, & color map
364530391Skarels *
364630391Skarels **********************************************************************
364730391Skarels *
364830391Skarels *	calling convention:
364930391Skarels *
365030391Skarels *		setup_dragon();
365130391Skarels *
365230391Skarels *	return: NONE
365330391Skarels *
365430391Skarels ************************/
365530391Skarels 
365630391Skarels setup_dragon(unit)
365730391Skarels u_int unit;
365830391Skarels {
365930391Skarels 
366030391Skarels 	register struct adder *adder;
366130391Skarels 	register struct dga *dga;
366230391Skarels 	short *memcsr;
366330391Skarels 
366430391Skarels 	int i;			/* general purpose variables */
366530391Skarels 	int status;
366630391Skarels 
366730391Skarels 	short top;		/* clipping/scrolling boundaries */
366830391Skarels 	short bottom;
366930391Skarels 	short right;
367030391Skarels 	short left;
367130391Skarels 
367230391Skarels 	short *red;		/* color map pointers */
367330391Skarels 	short *green;
367430391Skarels 	short *blue;
367530391Skarels 
367630391Skarels /*------------------
367730391Skarels * init for setup */
367830391Skarels 
367930391Skarels 	adder = (struct adder *) qdmap[unit].adder;
368030391Skarels 	dga = (struct dga *) qdmap[unit].dga;
368130391Skarels 	memcsr = (short *) qdmap[unit].memcsr;
368230391Skarels 
368330391Skarels 	dga->csr &= ~(DMA_IE | 0x700);	/* halt DMA and kill the intrpts */
368430391Skarels 	*memcsr = SYNC_ON;		/* blank screen and turn off LED's */
368530391Skarels 	adder->command = CANCEL;
368630391Skarels 
368730391Skarels /*----------------------
368830391Skarels * set monitor timing */
368930391Skarels 
369030391Skarels 	adder->x_scan_count_0 = 0x2800;
369130391Skarels 	adder->x_scan_count_1 = 0x1020;
369230391Skarels 	adder->x_scan_count_2 = 0x003A;
369330391Skarels 	adder->x_scan_count_3 = 0x38F0;
369430391Skarels 	adder->x_scan_count_4 = 0x6128;
369530391Skarels 	adder->x_scan_count_5 = 0x093A;
369630391Skarels 	adder->x_scan_count_6 = 0x313C;
369730391Skarels 	adder->sync_phase_adj = 0x0100;
369830391Skarels 	adder->x_scan_conf = 0x00C8;
369930391Skarels 
370030391Skarels /*---------------------------------------------------------
370130391Skarels * got a bug in secound pass ADDER! lets take care of it */
370230391Skarels 
370330391Skarels 	/* normally, just use the code in the following bug fix code, but to
370430391Skarels 	* make repeated demos look pretty, load the registers as if there was
370530391Skarels 	* no bug and then test to see if we are getting sync */
370630391Skarels 
370730391Skarels 	adder->y_scan_count_0 = 0x135F;
370830391Skarels 	adder->y_scan_count_1 = 0x3363;
370930391Skarels 	adder->y_scan_count_2 = 0x2366;
371030391Skarels 	adder->y_scan_count_3 = 0x0388;
371130391Skarels 
371230391Skarels 	/* if no sync, do the bug fix code */
371330391Skarels 
371430391Skarels 	if (wait_status(adder, VSYNC) == BAD) {
371530391Skarels 
371630391Skarels 	    /* first load all Y scan registers with very short frame and
371730391Skarels 	    * wait for scroll service.	This guarantees at least one SYNC
371830391Skarels 	    * to fix the pass 2 Adder initialization bug (synchronizes
371930391Skarels 	    * XCINCH with DMSEEDH) */
372030391Skarels 
372130391Skarels 	    adder->y_scan_count_0 = 0x01;
372230391Skarels 	    adder->y_scan_count_1 = 0x01;
372330391Skarels 	    adder->y_scan_count_2 = 0x01;
372430391Skarels 	    adder->y_scan_count_3 = 0x01;
372530391Skarels 
372630391Skarels 	    wait_status(adder, VSYNC);	/* delay at least 1 full frame time */
372730391Skarels 	    wait_status(adder, VSYNC);
372830391Skarels 
372930391Skarels 	    /* now load the REAL sync values (in reverse order just to
373030391Skarels 	    *  be safe.  */
373130391Skarels 
373230391Skarels 	    adder->y_scan_count_3 = 0x0388;
373330391Skarels 	    adder->y_scan_count_2 = 0x2366;
373430391Skarels 	    adder->y_scan_count_1 = 0x3363;
373530391Skarels 	    adder->y_scan_count_0 = 0x135F;
373630391Skarels 	}
373730391Skarels 
373830391Skarels 	*memcsr = SYNC_ON | UNBLANK;	/* turn off leds and turn on video */
373930391Skarels 
374030391Skarels /*----------------------------
374130391Skarels * zero the index registers */
374230391Skarels 
374330391Skarels 	adder->x_index_pending = 0;
374430391Skarels 	adder->y_index_pending = 0;
374530391Skarels 	adder->x_index_new = 0;
374630391Skarels 	adder->y_index_new = 0;
374730391Skarels 	adder->x_index_old = 0;
374830391Skarels 	adder->y_index_old = 0;
374930391Skarels 
375030391Skarels 	adder->pause = 0;
375130391Skarels 
375230391Skarels /*----------------------------------------
375330391Skarels * set rasterop mode to normal pen down */
375430391Skarels 
375530391Skarels 	adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL;
375630391Skarels 
375730391Skarels /*--------------------------------------------------
375830391Skarels * set the rasterop registers to a default values */
375930391Skarels 
376030391Skarels 	adder->source_1_dx = 1;
376130391Skarels 	adder->source_1_dy = 1;
376230391Skarels 	adder->source_1_x = 0;
376330391Skarels 	adder->source_1_y = 0;
376430391Skarels 	adder->destination_x = 0;
376530391Skarels 	adder->destination_y = 0;
376630391Skarels 	adder->fast_dest_dx = 1;
376730391Skarels 	adder->fast_dest_dy = 0;
376830391Skarels 	adder->slow_dest_dx = 0;
376930391Skarels 	adder->slow_dest_dy = 1;
377030391Skarels 	adder->error_1 = 0;
377130391Skarels 	adder->error_2 = 0;
377230391Skarels 
377330391Skarels /*------------------------
377430391Skarels * scale factor = unity */
377530391Skarels 
377630391Skarels 	adder->fast_scale = UNITY;
377730391Skarels 	adder->slow_scale = UNITY;
377830391Skarels 
377930391Skarels /*-------------------------------
378030391Skarels * set the source 2 parameters */
378130391Skarels 
378230391Skarels 	adder->source_2_x = 0;
378330391Skarels 	adder->source_2_y = 0;
378430391Skarels 	adder->source_2_size = 0x0022;
378530391Skarels 
378630391Skarels /*-----------------------------------------------
378730391Skarels * initialize plane addresses for eight vipers */
378830391Skarels 
378930391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0001);
379030391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0000);
379130391Skarels 
379230391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0002);
379330391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0001);
379430391Skarels 
379530391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0004);
379630391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0002);
379730391Skarels 
379830391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0008);
379930391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0003);
380030391Skarels 
380130391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0010);
380230391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0004);
380330391Skarels 
380430391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0020);
380530391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0005);
380630391Skarels 
380730391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0040);
380830391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0006);
380930391Skarels 
381030391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0080);
381130391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0007);
381230391Skarels 
381330391Skarels 	/* initialize the external registers. */
381430391Skarels 
381530391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x00FF);
381630391Skarels 	write_ID(adder, CS_SCROLL_MASK, 0x00FF);
381730391Skarels 
381830391Skarels 	/* initialize resolution mode */
381930391Skarels 
382030391Skarels 	write_ID(adder, MEMORY_BUS_WIDTH, 0x000C);     /* bus width = 16 */
382130391Skarels 	write_ID(adder, RESOLUTION_MODE, 0x0000);      /* one bit/pixel */
382230391Skarels 
382330391Skarels 	/* initialize viper registers */
382430391Skarels 
382530391Skarels 	write_ID(adder, SCROLL_CONSTANT, SCROLL_ENABLE|VIPER_LEFT|VIPER_UP);
382630391Skarels 	write_ID(adder, SCROLL_FILL, 0x0000);
382730391Skarels 
382830391Skarels /*----------------------------------------------------
382930391Skarels * set clipping and scrolling limits to full screen */
383030391Skarels 
383130391Skarels 	for ( i = 1000, adder->status = 0
383230391Skarels 	    ; i > 0  &&  !((status = adder->status) & ADDRESS_COMPLETE)
383330391Skarels 	    ; --i);
383430391Skarels 
383530391Skarels 	if (i == 0)
383630391Skarels 	    mprintf("\nqd%d: setup_dragon: timeout on ADDRESS_COMPLETE",unit);
383730391Skarels 
383830391Skarels 	top = 0;
383930391Skarels 	bottom = 2048;
384030391Skarels 	left = 0;
384130391Skarels 	right = 1024;
384230391Skarels 
384330391Skarels 	adder->x_clip_min = left;
384430391Skarels 	adder->x_clip_max = right;
384530391Skarels 	adder->y_clip_min = top;
384630391Skarels 	adder->y_clip_max = bottom;
384730391Skarels 
384830391Skarels 	adder->scroll_x_min = left;
384930391Skarels 	adder->scroll_x_max = right;
385030391Skarels 	adder->scroll_y_min = top;
385130391Skarels 	adder->scroll_y_max = bottom;
385230391Skarels 
385330391Skarels 	wait_status(adder, VSYNC);	/* wait at LEAST 1 full frame */
385430391Skarels 	wait_status(adder, VSYNC);
385530391Skarels 
385630391Skarels 	adder->x_index_pending = left;
385730391Skarels 	adder->y_index_pending = top;
385830391Skarels 	adder->x_index_new = left;
385930391Skarels 	adder->y_index_new = top;
386030391Skarels 	adder->x_index_old = left;
386130391Skarels 	adder->y_index_old = top;
386230391Skarels 
386330391Skarels 	for ( i = 1000, adder->status = 0
386430391Skarels 	    ; i > 0  &&  !((status = adder->status) & ADDRESS_COMPLETE)
386530391Skarels 	    ; --i);
386630391Skarels 
386730391Skarels 	if (i == 0)
386830391Skarels 	    mprintf("\nqd%d: setup_dragon: timeout on ADDRESS_COMPLETE",unit);
386930391Skarels 
387030391Skarels 	write_ID(adder, LEFT_SCROLL_MASK, 0x0000);
387130391Skarels 	write_ID(adder, RIGHT_SCROLL_MASK, 0x0000);
387230391Skarels 
387330391Skarels /*------------------------------------------------------------
387430391Skarels * set source and the mask register to all ones (ie: white) */
387530391Skarels 
387630391Skarels 	write_ID(adder, SOURCE, 0xFFFF);
387730391Skarels 	write_ID(adder, MASK_1, 0xFFFF);
387830391Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
387930391Skarels 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
388030391Skarels 
388130391Skarels /*--------------------------------------------------------------
388230391Skarels * initialize Operand Control Register banks for fill command */
388330391Skarels 
388430391Skarels 	write_ID(adder, SRC1_OCR_A, EXT_NONE | INT_M1_M2  | NO_ID | WAIT);
388530391Skarels 	write_ID(adder, SRC2_OCR_A, EXT_NONE | INT_SOURCE | NO_ID | NO_WAIT);
388630391Skarels 	write_ID(adder, DST_OCR_A, EXT_NONE | INT_NONE	 | NO_ID | NO_WAIT);
388730391Skarels 
388830391Skarels 	write_ID(adder, SRC1_OCR_B, EXT_NONE | INT_SOURCE | NO_ID | WAIT);
388930391Skarels 	write_ID(adder, SRC2_OCR_B, EXT_NONE | INT_M1_M2  | NO_ID | NO_WAIT);
389030391Skarels 	write_ID(adder, DST_OCR_B, EXT_NONE | INT_NONE | NO_ID | NO_WAIT);
389130391Skarels 
389230391Skarels /*------------------------------------------------------------------
389330391Skarels * init Logic Unit Function registers, (these are just common values,
389430391Skarels * and may be changed as required).  */
389530391Skarels 
389630391Skarels 	write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
389730391Skarels 	write_ID(adder, LU_FUNCTION_R2, FULL_SRC_RESOLUTION | LF_SOURCE | INV_M1_M2);
389830391Skarels 	write_ID(adder, LU_FUNCTION_R3, FULL_SRC_RESOLUTION | LF_D_OR_S);
389930391Skarels 	write_ID(adder, LU_FUNCTION_R4, FULL_SRC_RESOLUTION | LF_D_XOR_S);
390030391Skarels 
390130391Skarels /*----------------------------------------
390230391Skarels * load the color map for black & white */
390330391Skarels 
390430391Skarels 	for ( i = 0, adder->status = 0
390530391Skarels 	    ; i < 10000  &&  !((status = adder->status) & VSYNC)
390630391Skarels 	    ; ++i);
390730391Skarels 
390830391Skarels 	if (i == 0)
390930391Skarels 	    mprintf("\nqd%d: setup_dragon: timeout on VSYNC", unit);
391030391Skarels 
391130391Skarels 	red = (short *) qdmap[unit].red;
391230391Skarels 	green = (short *) qdmap[unit].green;
391330391Skarels 	blue = (short *) qdmap[unit].blue;
391430391Skarels 
391530391Skarels 	*red++ = 0x00;			/* black */
391630391Skarels 	*green++ = 0x00;
391730391Skarels 	*blue++ = 0x00;
391830391Skarels 
391930391Skarels 	*red-- = 0xFF;			/* white */
392030391Skarels 	*green-- = 0xFF;
392130391Skarels 	*blue-- = 0xFF;
392230391Skarels 
392330391Skarels 	/*----------------------------------
392430391Skarels 	* set color map for mouse cursor */
392530391Skarels 
392630391Skarels 	red += 254;
392730391Skarels 	green += 254;
392830391Skarels 	blue += 254;
392930391Skarels 
393030391Skarels 	*red++ = 0x00;			/* black */
393130391Skarels 	*green++ = 0x00;
393230391Skarels 	*blue++ = 0x00;
393330391Skarels 
393430391Skarels 	*red = 0xFF;			/* white */
393530391Skarels 	*green = 0xFF;
393630391Skarels 	*blue = 0xFF;
393730391Skarels 
393830391Skarels 	return(0);
393930391Skarels 
394030391Skarels } /* setup_dragon */
394130391Skarels 
394230391Skarels /******************************************************************
394330391Skarels *
394430391Skarels *	setup_input()... init the DUART and set defaults in input
394530391Skarels *			 devices
394630391Skarels *
394730391Skarels *******************************************************************
394830391Skarels *
394930391Skarels *	calling convention:
395030391Skarels *
395130391Skarels *		setup_input(unit);
395230391Skarels *
395330391Skarels *	where: unit - is the QDSS unit number to be setup
395430391Skarels *
395530391Skarels *********/
395630391Skarels 
395730391Skarels setup_input(unit)
395830391Skarels u_int unit;
395930391Skarels {
396030391Skarels 	register struct duart *duart;	/* DUART register structure pointer */
396130391Skarels 	register int i; 		/* scratch variable */
396230391Skarels 	register int bits;
396330391Skarels 
396430391Skarels 	char id_byte;
396530391Skarels 	short status;
396630391Skarels 
396730391Skarels /*---------------
396830391Skarels * init stuff */
396930391Skarels 
397030391Skarels 	duart = (struct duart *) qdmap[unit].duart;
397130391Skarels 	duart->imask = 0;
397230391Skarels 
397330391Skarels /*---------------------------------------------
397430391Skarels * setup the DUART for kbd & pointing device */
397530391Skarels 
397630391Skarels 	duart->cmdA = RESET_M;	  /* reset mode reg ptr for kbd */
397730391Skarels 	duart->modeA = 0x13;	  /* 8 bits, no parity, rcv IE, */
397830391Skarels 				  /* no RTS control,char error mode */
397930391Skarels 	duart->modeA = 0x07;	  /* 1 stop bit,CTS does not IE XMT */
398030391Skarels 				  /* no RTS control,no echo or loop */
398130391Skarels 	duart->cmdB = RESET_M;	  /* reset mode reg pntr for host */
398230391Skarels 	duart->modeB = 0x07;	  /* 8 bits, odd parity, rcv IE.. */
398330391Skarels 				  /* ..no RTS cntrl, char error mode */
398430391Skarels 	duart->modeB = 0x07;	  /* 1 stop bit,CTS does not IE XMT */
398530391Skarels 				  /* no RTS control,no echo or loop */
398630391Skarels 
398730391Skarels 	duart->auxctl = 0x00;	  /* baud rate set 1 */
398830391Skarels 
398930391Skarels 	duart->clkselA = 0x99;	  /* 4800 baud for kbd */
399030391Skarels 	duart->clkselB = 0x99;	  /* 4800 baud for mouse */
399130391Skarels 
399230391Skarels 	/* reset everything for keyboard */
399330391Skarels 
399430391Skarels 	for (bits = RESET_M; bits < START_BREAK; bits += 0x10)
399530391Skarels 	    duart->cmdA = bits;
399630391Skarels 
399730391Skarels 	/* reset everything for host */
399830391Skarels 
399930391Skarels 	for (bits = RESET_M; bits < START_BREAK; bits += 0x10)
400030391Skarels 	     duart->cmdB = bits;
400130391Skarels 
400230391Skarels 	duart->cmdA = EN_RCV | EN_XMT; /* enbl xmt & rcv for kbd */
400330391Skarels 	duart->cmdB = EN_RCV | EN_XMT; /* enbl xmt & rcv for pointer device */
400430391Skarels 
400530391Skarels /*--------------------------------------------
400630391Skarels * init keyboard defaults (DUART channel A) */
400730391Skarels 
400830391Skarels 	for (i = 500; i > 0; --i) {
400930391Skarels 	    if ((status = duart->statusA) & XMT_RDY) {
401030391Skarels 		duart->dataA = LK_DEFAULTS;
401130391Skarels 		break;
401230391Skarels 	    }
401330391Skarels 	}
401430391Skarels 
401530391Skarels 	for (i = 100000; i > 0; --i) {
401630391Skarels 	    if ((status = duart->statusA) & RCV_RDY) {
401730391Skarels 		break;
401830391Skarels 	    }
401930391Skarels 	}
402030391Skarels 
402130391Skarels 	status = duart->dataA;		/* flush the ACK */
402230391Skarels 
402330391Skarels /*--------------------------------
402430391Skarels * identify the pointing device */
402530391Skarels 
402630391Skarels 	for (i = 500; i > 0; --i) {
402730391Skarels 	    if ((status = duart->statusB) & XMT_RDY) {
402830391Skarels 		duart->dataB = SELF_TEST;
402930391Skarels 		break;
403030391Skarels 	    }
403130391Skarels 	}
403230391Skarels 
403330391Skarels 	/*-----------------------------------------
403430391Skarels 	* wait for 1st byte of self test report */
403530391Skarels 
403630391Skarels 	for (i = 100000; i > 0; --i) {
403730391Skarels 	    if ((status = duart->statusB) & RCV_RDY) {
403830391Skarels 		break;
403930391Skarels 	    }
404030391Skarels 	}
404130391Skarels 
404230391Skarels 	if (i == 0) {
404330391Skarels 	    mprintf("\nqd[%d]: setup_input: timeout on 1st byte of self test",unit);
404430391Skarels 	    goto OUT;
404530391Skarels 	}
404630391Skarels 
404730391Skarels 	status = duart->dataB;
404830391Skarels 
404930391Skarels 	/*-----------------------------------------
405030391Skarels 	* wait for ID byte of self test report	*/
405130391Skarels 
405230391Skarels 	for (i = 100000; i > 0; --i) {
405330391Skarels 	    if ((status = duart->statusB) & RCV_RDY) {
405430391Skarels 		break;
405530391Skarels 	    }
405630391Skarels 	}
405730391Skarels 
405830391Skarels 	if (i == 0) {
405930391Skarels 	    mprintf("\nqd[%d]: setup_input: timeout on 2nd byte of self test", unit);
406030391Skarels 	    goto OUT;
406130391Skarels 	}
406230391Skarels 
406330391Skarels 	id_byte = duart->dataB;
406430391Skarels 
406530391Skarels 	/*------------------------------------
406630391Skarels 	* wait for other bytes to come in  */
406730391Skarels 
406830391Skarels 	for (i = 100000; i > 0; --i) {
406930391Skarels 	    if ((status = duart->statusB) & RCV_RDY) {
407030391Skarels 		status = duart->dataB;
407130391Skarels 		break;
407230391Skarels 	    }
407330391Skarels 	}
407430391Skarels 
407530391Skarels 	if (i == 0) {
407630391Skarels 	    mprintf("\nqd[%d]: setup_input: timeout on 3rd byte of self test", unit);
407730391Skarels 	    goto OUT;
407830391Skarels 	}
407930391Skarels 
408030391Skarels 	for (i = 100000; i > 0; --i) {
408130391Skarels 	    if ((status = duart->statusB) & RCV_RDY) {
408230391Skarels 		status = duart->dataB;
408330391Skarels 		break;
408430391Skarels 	    }
408530391Skarels 	}
408630391Skarels 
408730391Skarels 	if (i == 0) {
408830391Skarels 	    mprintf("\nqd[%d]: setup_input: timeout on 4th byte of self test\n", unit);
408930391Skarels 	    goto OUT;
409030391Skarels 	}
409130391Skarels 
409230391Skarels 	/*----------------------------------------------
409330391Skarels 	* flag pointing device type and set defaults */
409430391Skarels 
409530391Skarels 	for (i=100000; i>0; --i);
409630391Skarels 
409730391Skarels 	if ((id_byte & 0x0F) != TABLET_ID) {
409830391Skarels 
409930391Skarels 	    qdflags[unit].pntr_id = MOUSE_ID;
410030391Skarels 
410130391Skarels 	    for (i = 500; i > 0; --i) {
410230391Skarels 		if ((status = duart->statusB) & XMT_RDY) {
410330391Skarels 		    duart->dataB = INC_STREAM_MODE;
410430391Skarels 		    break;
410530391Skarels 		}
410630391Skarels 	    }
410730391Skarels 	} else {
410830391Skarels 
410930391Skarels 	    qdflags[unit].pntr_id = TABLET_ID;
411030391Skarels 
411130391Skarels 	    for (i = 500; i > 0; --i) {
411230391Skarels 		if ((status = duart->statusB) & XMT_RDY) {
411330391Skarels 		    duart->dataB = T_STREAM;
411430391Skarels 		    break;
411530391Skarels 		}
411630391Skarels 	    }
411730391Skarels 	}
411830391Skarels 
411930391Skarels /*--------
412030391Skarels * exit */
412130391Skarels 
412230391Skarels OUT:
412330391Skarels 	duart->imask = qdflags[unit].duart_imask;
412430391Skarels 	return(0);
412530391Skarels 
412630391Skarels } /* setup_input */
412730391Skarels 
412830391Skarels /**********************************************************************
412930391Skarels *
413030391Skarels *	wait_status()... delay for at least one display frame time
413130391Skarels *
413230391Skarels ***********************************************************************
413330391Skarels *
413430391Skarels *	calling convention:
413530391Skarels *
413630391Skarels *		wait_status(adder, mask);
413730391Skarels *		struct *adder adder;
413830391Skarels *		int mask;
413930391Skarels *
414030391Skarels *	return: BAD means that we timed out without ever seeing the
414130391Skarels *		      vertical sync status bit
414230391Skarels *		GOOD otherwise
414330391Skarels *
414430391Skarels **************/
414530391Skarels 
414630391Skarels wait_status(adder, mask)
414730391Skarels register struct adder *adder;
414830391Skarels register int mask;
414930391Skarels {
415030391Skarels 	register short status;
415130391Skarels 	int i;
415230391Skarels 
415330391Skarels 	for ( i = 10000, adder->status = 0
415430391Skarels 	    ; i > 0  &&  !((status = adder->status) & mask)
415530391Skarels 	    ; --i);
415630391Skarels 
415730391Skarels 	if (i == 0) {
415830391Skarels 	    mprintf("\nwait_status: timeout polling for 0x%x in adder->status", mask);
415930391Skarels 	    return(BAD);
416030391Skarels 	}
416130391Skarels 
416230391Skarels 	return(GOOD);
416330391Skarels 
416430391Skarels } /* wait_status */
416530391Skarels 
416630391Skarels /**********************************************************************
416730391Skarels *
416830391Skarels *	write_ID()... write out onto the ID bus
416930391Skarels *
417030391Skarels ***********************************************************************
417130391Skarels *
417230391Skarels *	calling convention:
417330391Skarels *
417430391Skarels *		struct *adder adder;	;pntr to ADDER structure
417530391Skarels *		short adrs;		;VIPER address
417630391Skarels *		short data;		;data to be written
417730391Skarels *		write_ID(adder);
417830391Skarels *
417930391Skarels *	return: BAD means that we timed out waiting for status bits
418030391Skarels *		      VIPER-access-specific status bits
418130391Skarels *		GOOD otherwise
418230391Skarels *
418330391Skarels **************/
418430391Skarels 
418530391Skarels write_ID(adder, adrs, data)
418630391Skarels register struct adder *adder;
418730391Skarels register short adrs;
418830391Skarels register short data;
418930391Skarels {
419030391Skarels 	int i;
419130391Skarels 	short status;
419230391Skarels 
419330391Skarels 	for ( i = 100000, adder->status = 0
419430391Skarels 	    ; i > 0  &&  !((status = adder->status) & ADDRESS_COMPLETE)
419530391Skarels 	    ; --i);
419630391Skarels 
419730391Skarels 	if (i == 0)
419830391Skarels 	    goto ERR;
419930391Skarels 
420030391Skarels 	for ( i = 100000, adder->status = 0
420130391Skarels 	    ; i > 0  &&  !((status = adder->status) & TX_READY)
420230391Skarels 	    ; --i);
420330391Skarels 
420430391Skarels 	if (i > 0) {
420530391Skarels 	    adder->id_data = data;
420630391Skarels 	    adder->command = ID_LOAD | adrs;
420730391Skarels 	    return(GOOD);
420830391Skarels 	}
420930391Skarels 
421030391Skarels ERR:
421130391Skarels 	mprintf("\nwrite_ID: timeout trying to write to VIPER");
421230391Skarels 	return(BAD);
421330391Skarels 
421430391Skarels } /* write_ID */
4215