xref: /csrg-svn/sys/vax/uba/qd.c (revision 34615)
134511Smarc /*
234511Smarc  * Copyright (c) 1982, 1986 Regents of the University of California.
334511Smarc  * All rights reserved.  The Berkeley software License Agreement
434511Smarc  * specifies the terms and conditions for redistribution.
534511Smarc  *
6*34615Smarc  * 	@(#)qd.c	1.6  Berkeley  06/01/88
734511Smarc  *
8*34615Smarc  * derived from: "@(#)qd.c	ULTRIX";
934511Smarc  */
1030391Skarels /************************************************************************
1134511Smarc *									*
12*34615Smarc *			Copyright (c) 1985-1988 by			*
1330391Skarels *		Digital Equipment Corporation, Maynard, MA		*
1430391Skarels *			All rights reserved.				*
1530391Skarels *									*
1630391Skarels *   This software is furnished under a license and may be used and	*
1730391Skarels *   copied  only  in accordance with the terms of such license and	*
1830391Skarels *   with the  inclusion  of  the  above  copyright  notice.   This	*
1930391Skarels *   software  or  any  other copies thereof may not be provided or	*
2030391Skarels *   otherwise made available to any other person.  No title to and	*
2130391Skarels *   ownership of the software is hereby transferred.			*
2230391Skarels *									*
2330391Skarels *   The information in this software is subject to change  without	*
2430391Skarels *   notice  and should not be construed as a commitment by Digital	*
2530391Skarels *   Equipment Corporation.						*
2630391Skarels *									*
2730391Skarels *   Digital assumes no responsibility for the use  or  reliability	*
2830391Skarels *   of its software on equipment which is not supplied by Digital.	*
2930391Skarels *									*
3030391Skarels *************************************************************************/
31*34615Smarc 
3230391Skarels /*
33*34615Smarc  * qd.c
34*34615Smarc  *
35*34615Smarc  * Modification history
36*34615Smarc  *
37*34615Smarc  * QDSS workstation driver
38*34615Smarc  *
39*34615Smarc  *
40*34615Smarc  *  1-Dec-87 - Tim Burke
41*34615Smarc  *
42*34615Smarc  *	Added support for both System V termio(7) and POSIX termios(7).  These
43*34615Smarc  *	changes also include support for 8-bit canonical processing.  Changes
44*34615Smarc  *	involve:
45*34615Smarc  *
46*34615Smarc  *	- Default settings on first open depend on mode of open.  For termio
47*34615Smarc  *	  opens the defaults are "RAW" style, while non-termio opens default
48*34615Smarc  *	  to the traditional "cooked" style.
49*34615Smarc  *	- The driver now represents its terminal attributes and special
50*34615Smarc  *	  characters in the POSIX termios data structure.  This contrasts the
51*34615Smarc  *	  original approach of storing attributes and special chars in the
52*34615Smarc  *	  t_flags, ltchars and tchars.
53*34615Smarc  *	- Addition of LPASS8 to local mode word for 8-bit canonical support.
54*34615Smarc  *
55*34615Smarc  * 28-Sep-87 - Ali Rafieymehr
56*34615Smarc  *    Fixed a bug in qddint() routine. The bug was discovered on CVAX.
57*34615Smarc  *    Incorrect logic was used when taking an entry from the request queue.
58*34615Smarc  *
59*34615Smarc  * 12-Oct-87 - Tim Burke
60*34615Smarc  *	Modified driver to provide 8-bit support to the console port.  To do
61*34615Smarc  *	this characters are defined in the remainder of the first 15 rows of
62*34615Smarc  *	off screen memory as well as in next 15 rows.
63*34615Smarc  *
64*34615Smarc  *  2-Aug-87 - Fred Canter
65*34615Smarc  *    Use TANDEM mode on qconsole for flow control of writes to
66*34615Smarc  *    /dev/console.
67*34615Smarc  *
68*34615Smarc  * 12-Jun-87 - Tim Burke
69*34615Smarc  *
70*34615Smarc  *	Added full TERMIO functionality to terminal subsystem.
71*34615Smarc  *	Changed open routine to setup propper default settings if the line
72*34615Smarc  *	is not being used as a graphics device.  Added defines of defaults.
73*34615Smarc  *
74*34615Smarc  *
75*34615Smarc  * 14-May-87 - Fred Canter
76*34615Smarc  *	Changed default state of kernel_loop to on.
77*34615Smarc  *
78*34615Smarc  * 21-Apr-87 - Brian Stevens
79*34615Smarc  *	Xos support
80*34615Smarc  *
81*34615Smarc  * 16-Apr-87 - Fred Canter (for Brian Stevens)
82*34615Smarc  *	Multi-head GPX changes.
83*34615Smarc  *
84*34615Smarc  * 19-Mar-87 - Fred Canter (for Brian Stevens)
85*34615Smarc  *	Added X in the kernel support.
86*34615Smarc  *
87*34615Smarc  * 16-Dec-86 - Brian Stevens
88*34615Smarc  *
89*34615Smarc  *	added support so "select" could be called on tty type device
90*34615Smarc  *      fixed rlogin bug
91*34615Smarc  *
92*34615Smarc  * 30-Oct-86 - Brian Stevens
93*34615Smarc  *
94*34615Smarc  *	Removed the mprintf for "unexpected interrupts"
95*34615Smarc  *
96*34615Smarc  * 26-Aug-86 - rsp (Ricky Palmer)
97*34615Smarc  *
98*34615Smarc  *	Cleaned up devioctl code to (1) zero out devget structure
99*34615Smarc  *	upon entry and (2) use strlen instead of fixed storage
100*34615Smarc  *	for bcopy's.
101*34615Smarc  *
102*34615Smarc  * 21-Jul-86 - Ram Rao
103*34615Smarc  *	allowed cursor rectangle to hang (partially) off the
104*34615Smarc  *	top and left of screen
105*34615Smarc  *
106*34615Smarc  * 11-Jul-86 - ricky palmer
107*34615Smarc  *
108*34615Smarc  *	Added adpt and nexus fields to DEVIOCGET code.
109*34615Smarc  *
110*34615Smarc  * 02-July-86 - Brian Stevens
111*34615Smarc  *
112*34615Smarc  *	added support for console writing to second QDSS display
113*34615Smarc  *
114*34615Smarc  * 20-May-86 - ricky palmer
115*34615Smarc  *
116*34615Smarc  *	Added new DEVIOCGET ioctl request code. V2.0
117*34615Smarc  *
118*34615Smarc  * 16-Apr-86 -- darrell
119*34615Smarc  *	 badaddr is now called via the macro BADADDR
120*34615Smarc  *
121*34615Smarc  * 14-Apr-86 -- afd
122*34615Smarc  *	 Changed UMEMmap to QVmap and umem to qvmem.
123*34615Smarc  *
124*34615Smarc  *	 v_console() is now refered to as v_consputc, and there is a
125*34615Smarc  *	 corresponding v_consgetc() (defined in /sys/vax/conf.c).
126*34615Smarc  *
127*34615Smarc  *	 Added "qdgetc()" routine for console read.  Needed to read
128*34615Smarc  *	 user's answer to the "root device?" prompt with a generic kernel.
129*34615Smarc  *
130*34615Smarc  * 19-Mar-86 -- pmk
131*34615Smarc  *	 Change DELAY to 20000, because microdelay now in real microsec.
132*34615Smarc  *
133*34615Smarc  * 18-mar-86  -- jaw	 br/cvec changed to NOT use registers.
134*34615Smarc  *
135*34615Smarc  * 11 mar 86  darrell	replaced percpu with cpusw, and removed all but
136*34615Smarc  *			 one global reference
137*34615Smarc  * 19 feb 86  bstevens	no report of motion event on puck/stylus button action
138*34615Smarc  * 18 feb 86  bstevens	put in cursor box support for tablets
139*34615Smarc  * 18-Mar-86 -- jaw  add routines to cpu switch for nexus/unibus addreses
140*34615Smarc  *		      also got rid of some globals like nexnum.
141*34615Smarc  *		      ka8800 cleanup.
142*34615Smarc  * 06 dec 85  longo  added LK-201 error reporting for graphics device ops
143*34615Smarc  * 03 dec 85  longo  made qddint() clear active bit on error
144*34615Smarc  * 02 dec 85  longo  fixed up some crocks in the error messages
145*34615Smarc  * 25 nov 85  longo  added error handling to DMA ISR and single user locking
146*34615Smarc  * 19 nov 85  longo  eliminated "set_defaults()" by breaking out sub-calls.
147*34615Smarc  *		     Changed init_shared to do real init of scroll struct
148*34615Smarc  * 12 nov 85  longo  fixed bug in open that broke alternate console re-direct
149*34615Smarc  * 11 nov 85  longo  changed "_vs_eventqueue" references to "qdinput"
150*34615Smarc  * 08 nov 85  longo  improved select service for read/write select wakeup.
151*34615Smarc  *		     Also set ISR's to ipl4 to allow the interval timer in.
152*34615Smarc  * 04 nov 85  longo  fixed bugs in mouse button reporting and dma request stuff
153*34615Smarc  * 30 oct 85  longo  DMA to/from user space is in place
154*34615Smarc  * 14 oct 85  longo  added kernel msg redirect and QD_RDCURSOR ioctl
155*34615Smarc  * 03 oct 85  longo  added support for multiple QDSS's
156*34615Smarc  * 02 oct 85  longo  added color map loading services in qdioctl() & qdaint()
157*34615Smarc  * 30 sep 85  longo  added DMA interrupt services
158*34615Smarc  * 18 sep 85  longo  added scroll services to "qdaint()" adder intrpt service
159*34615Smarc  *		     and put in supporting ioctl's
160*34615Smarc  * 04 sep 85  longo  initial implementation of DMA is working
161*34615Smarc  * 17 aug 85  longo  added support for the QDSS to be system console
162*34615Smarc  * 05 aug 85  longo  now using qfont (QVSS & QDSS) as linked object
163*34615Smarc  * 12 jun 85  longo  added mouse event loading to "qdiint()"
164*34615Smarc  * 31 may 85  longo  put live interrupts into the probe() routine
165*34615Smarc  * 30 may 85  longo  event queue shared memory implementation is now alive
166*34615Smarc  * 29 may 85  longo  LK-201 input is now interrupt driven
167*34615Smarc  * 25 apr 85  longo  MAPDEVICE works
168*34615Smarc  * 14 mar 85  longo  created
169*34615Smarc  *
170*34615Smarc  *	 todo:	 fix rlogin bug in console stuff
171*34615Smarc  *		 cat -u console redirection
172*34615Smarc  *		 check error return from strategy routine
173*34615Smarc  *		 verify TOY time stuff (what format?)
174*34615Smarc  *		 look at system based macro implementation of VTOP
175*34615Smarc  *
17630391Skarels  */
17730391Skarels 
178*34615Smarc #include "qd.h" 	/* # of QDSS's the system is configured for */
179*34615Smarc 
18034511Smarc #if NQD > 0
181*34615Smarc #include "types.h"
182*34615Smarc #include "../machine/pte.h"	/* page table values */
183*34615Smarc #include "../machine/mtpr.h"	/* VAX register access stuff */
18434511Smarc #include "../machine/cpu.h"
185*34615Smarc #include "param.h" 	/* general system params & macros */
186*34615Smarc #include "conf.h"		/* "linesw" tty driver dispatch */
187*34615Smarc #include "dir.h"		/* for directory handling */
188*34615Smarc #include "user.h"		/* user structure (what else?) */
189*34615Smarc #include "qdioctl.h"	/* ioctl call values */
19034511Smarc #include "tty.h"
191*34615Smarc #include "map.h"		/* resource allocation map struct */
192*34615Smarc #include "buf.h"		/* buf structs */
193*34615Smarc #include "vm.h"		/* includes 'vm' header files */
194*34615Smarc #include "bk.h"		/* BKINPUT macro for line stuff */
195*34615Smarc #include "clist.h" 	/* char list handling structs */
196*34615Smarc #include "file.h"		/* file I/O definitions */
197*34615Smarc #include "uio.h"		/* write/read call structs */
198*34615Smarc #include "kernel.h"	/* clock handling structs */
199*34615Smarc #ifdef notdef	/* notneeded */
200*34615Smarc #include "cpuconf.h"
201*34615Smarc #include "devio.h"
202*34615Smarc #endif
203*34615Smarc #include "exec.h"
204*34615Smarc #include "proc.h"
205*34615Smarc 
206*34615Smarc #include "ubareg.h"	/* uba & 'qba' register structs */
207*34615Smarc #include "ubavar.h"	/* uba structs & uba map externs */
20834511Smarc #include "syslog.h"
20930391Skarels 
210*34615Smarc #include "qduser.h"	/* definitions shared with my client */
211*34615Smarc #include "qdreg.h"	/* QDSS device register structures */
212*34615Smarc /*-----------------------------------------------------------
213*34615Smarc * QDSS driver status flags for tracking operational state */
21432012Smarc 
215*34615Smarc 	struct qdflags {
21632012Smarc 
217*34615Smarc 	    u_int inuse;	    /* which minor dev's are in use now */
218*34615Smarc 	    u_int config;	    /* I/O page register content */
219*34615Smarc 	    u_int mapped;	    /* user mapping status word */
220*34615Smarc 	    u_int kernel_loop;	    /* if kernel console is redirected */
221*34615Smarc 	    u_int user_dma;	    /* DMA from user space in progress */
222*34615Smarc 	    u_short pntr_id;	    /* type code of pointing device */
223*34615Smarc 	    u_short duart_imask;    /* shadowing for duart intrpt mask reg */
224*34615Smarc 	    u_short adder_ie;	    /* shadowing for adder intrpt enbl reg */
225*34615Smarc 	    u_short curs_acc;	    /* cursor acceleration factor */
226*34615Smarc 	    u_short curs_thr;	    /* cursor acceleration threshold level */
227*34615Smarc 	    u_short tab_res;	    /* tablet resolution factor */
228*34615Smarc 	    u_short selmask;	    /* mask for active qd select entries */
229*34615Smarc 	};
23032012Smarc 
231*34615Smarc 	/* bit definitions for "inuse" entry  */
23234511Smarc 
23332012Smarc #define CONS_DEV	0x01
23432012Smarc #define ALTCONS_DEV	0x02
23532012Smarc #define GRAPHIC_DEV	0x04
23632012Smarc 
237*34615Smarc 	/* bit definitions for 'mapped' member of flag structure */
238*34615Smarc 
23932012Smarc #define MAPDEV		0x01		/* hardware is mapped */
24032012Smarc #define MAPDMA		0x02		/* DMA buffer mapped */
24132012Smarc #define MAPEQ		0x04		/* event queue buffer mapped */
24232012Smarc #define MAPSCR		0x08		/* scroll param area mapped */
24332012Smarc #define MAPCOLOR	0x10		/* color map writing buffer mapped */
24432012Smarc 
245*34615Smarc 	/* bit definitions for 'selmask' member of qdflag structure */
24632012Smarc 
24732012Smarc #define SEL_READ	0x01		/* read select is active */
24832012Smarc #define SEL_WRITE	0x02		/* write select is active */
24932012Smarc 
250*34615Smarc /*----------------------------------------------
251*34615Smarc * constants used in shared memory operations */
25232012Smarc 
25332012Smarc #define EVENT_BUFSIZE  1024	/* # of bytes per device's event buffer */
254*34615Smarc 
25532012Smarc #define MAXEVENTS  ( (EVENT_BUFSIZE - sizeof(struct qdinput))	 \
25632012Smarc 		     / sizeof(struct _vs_event) )
257*34615Smarc 
25834527Smarc #define DMA_BUFSIZ	(1024 * 10)
259*34615Smarc 
26032012Smarc #define COLOR_BUFSIZ  ((sizeof(struct color_buf) + 512) & ~0x01FF)
26132012Smarc 
262*34615Smarc /*******************************************************************/
263*34615Smarc 
264*34615Smarc extern char qvmem[][128*NBPG];
265*34615Smarc extern struct pte QVmap[][128];
266*34615Smarc 
267*34615Smarc 
268*34615Smarc /*--------------------------------------------------------------------------
26932012Smarc * reference to an array of "uba_device" structures built by the auto
27032012Smarc * configuration program.  The uba_device structure decribes the device
27132012Smarc * sufficiently for the driver to talk to it.  The auto configuration code
27232012Smarc * fills in the uba_device structures (located in ioconf.c) from user
273*34615Smarc * maintained info.  */
27432012Smarc 
275*34615Smarc 	struct uba_device *qdinfo[NQD];  /* array of pntrs to each QDSS's */
276*34615Smarc 					 /* uba structures  */
277*34615Smarc 	struct tty qd_tty[NQD*4];	/* teletype structures for each.. */
278*34615Smarc 					/* ..possible minor device */
27932012Smarc 
280*34615Smarc 	struct qd_softc qd_softc[NQD];
28132012Smarc 
282*34615Smarc /*----------------------------------------------------------
283*34615Smarc * static storage used by multiple functions in this code  */
28432012Smarc 
285*34615Smarc 	int Qbus_unmap[NQD];		/* Qbus mapper release code */
286*34615Smarc 	struct qdflags qdflags[NQD];	/* QDSS device status flags */
287*34615Smarc 	struct qdmap qdmap[NQD];	/* QDSS register map structure */
288*34615Smarc 	caddr_t qdbase[NQD];		/* base address of each QDSS unit */
289*34615Smarc 	struct buf qdbuf[NQD];		/* buf structs used by strategy */
290*34615Smarc 	char one_only[NQD];		/* lock for single process access */
291*34615Smarc 
292*34615Smarc /*------------------------------------------------------------------------
293*34615Smarc * the array "event_shared[]" is made up of a number of event queue buffers
29432012Smarc * equal to the number of QDSS's configured into the running kernel (NQD).
29532012Smarc * Each event queue buffer begins with an event queue header (struct qdinput)
29632012Smarc * followed by a group of event queue entries (struct _vs_event).  The array
29732012Smarc * "*eq_header[]" is an array of pointers to the start of each event queue
298*34615Smarc * buffer in "event_shared[]".  */
29932012Smarc 
30032012Smarc #define EQSIZE ((EVENT_BUFSIZE * NQD) + 512)
30132012Smarc 
302*34615Smarc 	char event_shared[EQSIZE];	    /* reserve space for event bufs */
303*34615Smarc 	struct qdinput *eq_header[NQD];     /* event queue header pntrs */
30432012Smarc 
305*34615Smarc /*--------------------------------------------------------------------------
30632012Smarc * This allocation method reserves enough memory pages for NQD shared DMA I/O
30732012Smarc * buffers.  Each buffer must consume an integral number of memory pages to
30832012Smarc * guarantee that a following buffer will begin on a page boundary.  Also,
30932012Smarc * enough space is allocated so that the FIRST I/O buffer can start at the
31032012Smarc * 1st page boundary after "&DMA_shared".  Page boundaries are used so that
311*34615Smarc * memory protections can be turned on/off for individual buffers. */
31232012Smarc 
31332012Smarc #define IOBUFSIZE  ((DMA_BUFSIZ * NQD) + 512)
31432012Smarc 
315*34615Smarc 	char DMA_shared[IOBUFSIZE];	    /* reserve I/O buffer space */
316*34615Smarc 	struct DMAreq_header *DMAheader[NQD];  /* DMA buffer header pntrs */
31732012Smarc 
318*34615Smarc /*-------------------------------------------------------------------------
31932012Smarc * The driver assists a client in scroll operations by loading dragon
32032012Smarc * registers from an interrupt service routine.	The loading is done using
32132012Smarc * parameters found in memory shrade between the driver and it's client.
32232012Smarc * The scroll parameter structures are ALL loacted in the same memory page
323*34615Smarc * for reasons of memory economy.  */
32432012Smarc 
325*34615Smarc 	char scroll_shared[2 * 512];	/* reserve space for scroll structs */
326*34615Smarc 	struct scroll *scroll[NQD];	/* pointers to scroll structures */
32732012Smarc 
328*34615Smarc /*-----------------------------------------------------------------------
32932012Smarc * the driver is programmable to provide the user with color map write
33032012Smarc * services at VSYNC interrupt time.  At interrupt time the driver loads
331*34615Smarc * the color map with any user-requested load data found in shared memory */
33232012Smarc 
33332012Smarc #define COLOR_SHARED  ((COLOR_BUFSIZ * NQD) + 512)
33432012Smarc 
335*34615Smarc 	char color_shared[COLOR_SHARED];      /* reserve space: color bufs */
336*34615Smarc 	struct color_buf *color_buf[NQD];     /* pointers to color bufs */
33732012Smarc 
338*34615Smarc /*--------------------------------
339*34615Smarc * mouse input event structures */
34032012Smarc 
341*34615Smarc 	struct mouse_report last_rep[NQD];
342*34615Smarc 	struct mouse_report current_rep[NQD];
34332012Smarc 
344*34615Smarc /*----------------------------
345*34615Smarc * input event "select" use */
34632012Smarc 
347*34615Smarc 	struct proc *rsel[NQD]; 	/* process waiting for select */
34832012Smarc 
349*34615Smarc /*----------------------------
350*34615Smarc * console cursor structure */
35132012Smarc 
352*34615Smarc 	struct _vs_cursor cursor[NQD];
35332012Smarc 
354*34615Smarc /*----------------------------
355*34615Smarc * count of successfully probed qd's */
35632012Smarc 
357*34615Smarc 	int qdcount = 0;
35832012Smarc 
35932012Smarc 
360*34615Smarc /************************************************************************/
36132012Smarc 
362*34615Smarc 	int nNQD = NQD;
36332012Smarc 
364*34615Smarc 	int DMAbuf_size = DMA_BUFSIZ;
36532012Smarc 
366*34615Smarc 
367*34615Smarc #define QDSSMAJOR	41		/* QDSS major device number */
368*34615Smarc #ifdef notdef	/* on ultrix */
369*34615Smarc extern	int	ws_display_type;
370*34615Smarc extern	int	ws_display_units;
371*34615Smarc #endif
372*34615Smarc /* don't need these  */
373*34615Smarc int	ws_display_type;
374*34615Smarc int	ws_display_units;
375*34615Smarc 
376*34615Smarc int     QDlast_DMAtype;                 /* type of the last DMA operation */
377*34615Smarc 
378*34615Smarc /*---------------------------------------------------------------------
379*34615Smarc * macro to get system time.  Used to time stamp event queue entries */
380*34615Smarc 
38130391Skarels #define TOY ((time.tv_sec * 100) + (time.tv_usec / 10000))
38230391Skarels 
383*34615Smarc /*--------------------------------------------------------------------------
38430391Skarels * the "ioconf.c" program, built and used by auto config, externally refers
385*34615Smarc * to definitions below.  */
38630391Skarels 
387*34615Smarc 	int qdprobe();
388*34615Smarc 	int qdattach();
389*34615Smarc 	int qddint();			/* DMA gate array intrpt service */
390*34615Smarc 	int qdaint();			/* Dragon ADDER intrpt service */
391*34615Smarc 	int qdiint();
39230391Skarels 
393*34615Smarc 	u_short qdstd[] = { 0 };
39430391Skarels 
395*34615Smarc 	struct uba_driver qddriver = {	/* externally referenced: ioconf.c */
39630391Skarels 
397*34615Smarc 	    qdprobe,			/* device probe entry */
398*34615Smarc 	    0,				/* no slave device */
399*34615Smarc 	    qdattach,			/* device attach entry */
400*34615Smarc 	    0,				/* no "fill csr/ba to start" */
401*34615Smarc 	    qdstd,			/* device addresses */
402*34615Smarc 	    "qd",			/* device name string */
403*34615Smarc 	    qdinfo			/* ptr to QDSS's uba_device struct */
404*34615Smarc 	};
40530391Skarels 
406*34615Smarc /*-------------------
40730391Skarels * general defines */
40830391Skarels 
409*34615Smarc #define QDPRIOR (PZERO-1)		/* must be negative */
41030391Skarels 
41130391Skarels #define FALSE	0
41230391Skarels #define TRUE	~FALSE
41330391Skarels 
41430391Skarels #define BAD	-1
41530391Skarels #define GOOD	0
41630391Skarels 
417*34615Smarc /*-----------------------------------------------------------------------
418*34615Smarc * macro to create a system virtual page number from system virtual adrs */
41930391Skarels 
420*34615Smarc #define VTOP(x)  (((int)x & ~0xC0000000) >> PGSHIFT) /* convert qvmem adrs */
421*34615Smarc 						     /* to system page # */
42230391Skarels 
423*34615Smarc /*------------------------------------------------------------------
424*34615Smarc * QDSS register address offsets from start of QDSS address space */
42530391Skarels 
42630391Skarels #define QDSIZE	 (52 * 1024)	/* size of entire QDSS foot print */
42730391Skarels 
42830391Skarels #define TMPSIZE  (16 * 1024)	/* template RAM is 8k SHORT WORDS */
42930391Skarels #define TMPSTART 0x8000 	/* offset of template RAM from base adrs */
43030391Skarels 
43130391Skarels #define REGSIZE  (5 * 512)	/* regs touch 2.5k (5 pages) of addr space */
43230391Skarels #define REGSTART 0xC000 	/* offset of reg pages from base adrs */
43330391Skarels 
43430391Skarels #define ADDER	(REGSTART+0x000)
43530391Skarels #define DGA	(REGSTART+0x200)
43630391Skarels #define DUART	(REGSTART+0x400)
43730391Skarels #define MEMCSR	(REGSTART+0x800)
43830391Skarels 
43930391Skarels #define CLRSIZE  (3 * 512)		/* color map size */
44030391Skarels #define CLRSTART (REGSTART+0xA00)	/* color map start offset from base */
44130391Skarels 					/*  0x0C00 really */
44230391Skarels #define RED	(CLRSTART+0x000)
44330391Skarels #define BLUE	(CLRSTART+0x200)
44430391Skarels #define GREEN	(CLRSTART+0x400)
44530391Skarels 
446*34615Smarc /*---------------------------------------------------------------
447*34615Smarc * values used in mapping QDSS hardware into the Q memory space */
44830391Skarels 
44930391Skarels #define CHUNK	  (64 * 1024)
450*34615Smarc #define QMEMSIZE  (1024 * 1024 * 4)	/* 4 meg */
45130391Skarels 
452*34615Smarc /*----------------------------------------------------------------------
45330391Skarels * QDSS minor device numbers.  The *real* minor device numbers are in
45430391Skarels * the bottom two bits of the major/minor device spec.  Bits 2 and up are
455*34615Smarc * used to specify the QDSS device number (ie: which one?) */
45630391Skarels 
45730391Skarels 
45830391Skarels #define CONS		0
45930391Skarels #define ALTCONS 	1
46030391Skarels #define GRAPHIC 	2
46130391Skarels 
462*34615Smarc /*----------------------------------------------
463*34615Smarc * console cursor bitmap (block cursor type)  */
46430391Skarels 
46530391Skarels 	short cons_cursor[32] = {      /* white block cursor */
46630391Skarels 
46730391Skarels  /* A */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
46830391Skarels 	 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
46930391Skarels  /* B */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
47030391Skarels 	 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF
47130391Skarels 
47230391Skarels 	};
47330391Skarels 
474*34615Smarc /*-------------------------------------
475*34615Smarc * constants used in font operations */
47630391Skarels 
477*34615Smarc 
478*34615Smarc /* Originaly this was CHARS 95 */
479*34615Smarc #define CHARS		190 			/* # of chars in the font */
480*34615Smarc 
48130391Skarels #define CHAR_HEIGHT	15			/* char height in pixels */
48230391Skarels #define CHAR_WIDTH	8			/* char width in pixels*/
48330391Skarels #define FONT_WIDTH	(CHAR_WIDTH * CHARS)	/* font width in pixels */
48430391Skarels #define ROWS		CHAR_HEIGHT
48530391Skarels 
48630391Skarels 
48730391Skarels #define FONT_X		0			/* font's off screen adrs */
48830391Skarels #define FONT_Y		(2048 - CHAR_HEIGHT)
48930391Skarels 
490*34615Smarc 					/* Offset to second row characters */
491*34615Smarc #define FONT_OFFSET	((MAX_SCREEN_X/CHAR_WIDTH)*CHAR_HEIGHT)
49230391Skarels 
493*34615Smarc 	extern char q_font[];		/* reference font object code */
49430391Skarels 
495*34615Smarc 	extern	u_short q_key[];		/* reference key xlation tables */
496*34615Smarc 	extern	u_short q_shift_key[];
497*34615Smarc 	extern	char *q_special[];
49830391Skarels 
499*34615Smarc /*--------------------------------------------------
500*34615Smarc * definitions for cursor acceleration reporting  */
501*34615Smarc 
50230391Skarels #define ACC_OFF 	0x01		/* acceleration is inactive */
50330391Skarels 
504*34615Smarc /*--------------------------------------------------------------------------
505*34615Smarc * v_consputc is the switch that is used to redirect the console cnputc() to
506*34615Smarc * the virtual console qdputc().
507*34615Smarc * v_consgetc is the switch that is used to redirect the console getchar() to
508*34615Smarc * the virtual console qdgetc().
509*34615Smarc */
51030391Skarels 
511*34615Smarc #ifdef notdef
512*34615Smarc 	extern (*v_consputc)();
513*34615Smarc 	int qdputc();		/* used to direct kernel console output */
514*34615Smarc 	extern (*v_consgetc)();
515*34615Smarc 	int qdgetc();		/* used to read kernel console input */
51630391Skarels 
517*34615Smarc 	int qdstart();		/* used to direct /dev/console output */
518*34615Smarc #endif
519*34615Smarc 	extern (*v_putc)();
520*34615Smarc 	extern struct cdevsw *consops;
521*34615Smarc 	int qdputc();
522*34615Smarc 	int qdstart();
52330391Skarels 
524*34615Smarc /*------------------------------------------------------------------------
525*34615Smarc * LK-201 state storage for input console keyboard conversion to ASCII */
52630391Skarels 
527*34615Smarc 	struct q_keyboard {
528*34615Smarc 
529*34615Smarc 	    int shift;			/* state variables	*/
530*34615Smarc 	    int cntrl;
531*34615Smarc 	    int lock;
532*34615Smarc 	    int lastcode;		/* last keycode typed	*/
533*34615Smarc 	    unsigned kup[8];		/* bits for each keycode*/
534*34615Smarc 	    unsigned dkeys[8];		/* down/up mode keys	*/
535*34615Smarc 	    char last;			/* last character	*/
536*34615Smarc 
537*34615Smarc 	 } q_keyboard;
538*34615Smarc 
539*34615Smarc /*--------------------------------------------------
540*34615Smarc * ULTRIX settings for first open.		  */
541*34615Smarc 
542*34615Smarc #define IFLAGS	(EVENP|ECHO|XTABS|CRMOD)
543*34615Smarc 
544*34615Smarc /*------------------------------------------------------------------------
545*34615Smarc * termio flags will be set to these default values in non-termio mode to
546*34615Smarc * provide a backward compatible ULTRIX environment. */
547*34615Smarc 
548*34615Smarc #ifdef POSIXTTY
549*34615Smarc #define IFLAG (BRKINT|ISTRIP|IXON|IXANY|ICRNL|IEXTEN|IMAXBEL)
550*34615Smarc #define OFLAG (OPOST|OXTABS|ONLCR)
551*34615Smarc #define LFLAG (ISIG|ICANON|ECHO)
552*34615Smarc #define CFLAG (PARENB|CREAD|CS7|CLOCAL)
553*34615Smarc #endif
554*34615Smarc 
555*34615Smarc /*****************************************************************
556*34615Smarc ******************************************************************
557*34615Smarc ******************************************************************
558*34615Smarc *
559*34615Smarc *	DRIVER FUNCTIONS START HERE:
560*34615Smarc *
561*34615Smarc ******************************************************************
562*34615Smarc ******************************************************************
563*34615Smarc *****************************************************************/
564*34615Smarc 
56530391Skarels /*********************************************************************
56630391Skarels *
567*34615Smarc *	qdcons_init()... init QDSS as console (before probe routine)
56830391Skarels *
56930391Skarels *********************************************************************/
57030391Skarels 
57130391Skarels qdcons_init()
57230391Skarels {
57330391Skarels 	register u_int unit;
57430391Skarels 
57530391Skarels 	int *ptep;			/* page table entry pointer */
57630391Skarels 	caddr_t phys_adr;		/* physical QDSS base adrs */
577*34615Smarc 	u_int mapix;			/* index into QVmap[] array */
57830391Skarels 
579*34615Smarc 	struct percpu *pcpu;		/* pointer to cpusw structure  */
580*34615Smarc 	register struct qbus *qb;
58130391Skarels 	u_short *qdaddr;		/* address of QDSS IO page CSR */
58230391Skarels 	u_short *devptr;		/* vitual device space */
583*34615Smarc 	extern cnputc();
58430391Skarels 
58530391Skarels #define QDSSCSR 0x1F00
58630391Skarels 
58732012Smarc 	if (v_putc != cnputc)
58832012Smarc 		return;
58932012Smarc 
59030391Skarels 	unit = 0;
59130391Skarels 
592*34615Smarc /*----------------------------------------------------
593*34615Smarc * find the cpusw entry that matches this machine. */
59430391Skarels 
59532012Smarc 	for (pcpu = percpu; pcpu && pcpu->pc_cputype != cpu; pcpu++)
59632012Smarc 		;
59732012Smarc 	if (pcpu == NULL)
59832012Smarc 		return;
59930391Skarels 
600*34615Smarc #ifdef notdef	/* the ultrix way */
601*34615Smarc /*------------------------------------------------------
602*34615Smarc * Map the Q-bus memory space into the system memory. */
60330391Skarels 
604*34615Smarc 	ubaaccess(((*cpup->v_umaddr)(0)), QVmap[0],
605*34615Smarc 			cpup->pc_umsize, PG_V | PG_KW);
606*34615Smarc 
607*34615Smarc 	ubaaccess(((*cpup->v_udevaddr)(0)), QVmap[0]+btop(cpup->pc_umsize),
608*34615Smarc 			DEVSPACESIZE ,PG_V|PG_KW);
609*34615Smarc 
610*34615Smarc /*---------------------------------------------------------------------
611*34615Smarc * map the QDSS into the Qbus memory (which is now in system space)  */
612*34615Smarc 
613*34615Smarc 	devptr = (u_short *)((char *)qvmem[0]+cpup->pc_umsize);
614*34615Smarc 	qdaddr = (u_short *)((u_int)devptr + ubdevreg(QDSSCSR));
615*34615Smarc 
616*34615Smarc 	if (BADADDR(qdaddr, sizeof(short)))
617*34615Smarc 		return(0);
618*34615Smarc 
619*34615Smarc 	/*---------------------------------------------------
620*34615Smarc 	* tell QDSS which Q memory address base to decode */
621*34615Smarc 
622*34615Smarc 	mapix = (int) VTOP(QMEMSIZE - CHUNK);
623*34615Smarc 	ptep = (int *) QVmap[0] + mapix;
624*34615Smarc 	phys_adr = (caddr_t) (((int)*ptep & 0x001FFFFF) << PGSHIFT);
625*34615Smarc 	*qdaddr = (u_short) ((int)phys_adr >> 16);
626*34615Smarc 
627*34615Smarc 	qdflags[unit].config = *(u_short *)qdaddr;
628*34615Smarc 
629*34615Smarc #endif /*notdef*/
630*34615Smarc 
631*34615Smarc 	/* the BSD way */
63232012Smarc 	/*
633*34615Smarc 	 * Map device registers - the last 8K of qvmem.
63432012Smarc 	 */
63532012Smarc 	qb = (struct qbus *)pcpu->pc_io->io_details;
63632012Smarc 	ioaccess(qb->qb_iopage, UMEMmap[0] + qb->qb_memsize,
63732012Smarc 		UBAIOPAGES * NBPG);
63830391Skarels 
63932012Smarc 	devptr = (u_short *)((char *)umem[0]+(qb->qb_memsize * NBPG));
64030391Skarels 	qdaddr = (u_short *)((u_int)devptr + ubdevreg(QDSSCSR));
64132012Smarc 	if (badaddr(qdaddr, sizeof(short)))  {
642*34615Smarc 		printf("Can't find qdss (badaddr)\n"); /* debug */
64330391Skarels 		return(0);
64432012Smarc 	}
645*34615Smarc 
646*34615Smarc 
647*34615Smarc 
64832012Smarc 	/*
64932012Smarc 	 * Map q-bus memory used by qdss. (separate map)
65032012Smarc 	 */
65132012Smarc 	mapix = QMEMSIZE - (CHUNK * (unit + 1));
65232012Smarc 	phys_adr = qb->qb_maddr + mapix;
65332012Smarc 	ioaccess(phys_adr, QVmap[0], (CHUNK*NQD));
65430391Skarels 
65532012Smarc 	/*
65632012Smarc 	 * tell QDSS which Q memory address base to decode
65732012Smarc 	 */
65830391Skarels 
65932012Smarc 	/*
66032012Smarc 	 * shifted right 16 bits - its in 64K units
66132012Smarc 	 */
66232012Smarc 	*qdaddr = (u_short)((int)mapix >> 16);
66330391Skarels 	qdflags[unit].config = *(u_short *)qdaddr;
66430391Skarels 
665*34615Smarc /*----------------------------------------------------------------------
666*34615Smarc * load qdmap struct with the virtual addresses of the QDSS elements */
66730391Skarels 
668*34615Smarc #ifdef notdef	/*ultrix way */
669*34615Smarc 	qdbase[unit] = (caddr_t) (qvmem[0] + QMEMSIZE - CHUNK);
670*34615Smarc #endif
67130391Skarels 
672*34615Smarc 	qdbase[unit] = (caddr_t) (qvmem[0]);
673*34615Smarc 
67430391Skarels 	qdmap[unit].template = qdbase[unit] + TMPSTART;
67530391Skarels 	qdmap[unit].adder = qdbase[unit] + ADDER;
67630391Skarels 	qdmap[unit].dga = qdbase[unit] + DGA;
67730391Skarels 	qdmap[unit].duart = qdbase[unit] + DUART;
67830391Skarels 	qdmap[unit].memcsr = qdbase[unit] + MEMCSR;
67930391Skarels 	qdmap[unit].red = qdbase[unit] + RED;
68030391Skarels 	qdmap[unit].blue = qdbase[unit] + BLUE;
68130391Skarels 	qdmap[unit].green = qdbase[unit] + GREEN;
68230391Skarels 
68330391Skarels 	qdflags[unit].duart_imask = 0;	/* init shadow variables */
68430391Skarels 
685*34615Smarc /*------------------
686*34615Smarc * init the QDSS  */
68730391Skarels 
68832012Smarc 	printf("qdbase[0] = %x, qdmap[0].memcsr = %x\n",
689*34615Smarc 			(char *)qdbase[0], qdmap[0].memcsr);
69032012Smarc 
69130391Skarels 	*(short *)qdmap[unit].memcsr |= SYNC_ON; /* once only: turn on sync */
69230391Skarels 
69330391Skarels 	cursor[unit].x = 0;
69430391Skarels 	cursor[unit].y = 0;
69530391Skarels 	init_shared(unit);		/* init shared memory */
69630391Skarels 	setup_dragon(unit);		/* init the ADDER/VIPER stuff */
69730391Skarels 	clear_qd_screen(unit);		/* clear the screen */
69830391Skarels 	ldfont(unit);			/* load the console font */
69930391Skarels 	ldcursor(unit, cons_cursor);	/* load default cursor map */
70030391Skarels 	setup_input(unit);		/* init the DUART */
70130391Skarels 
702*34615Smarc /*----------------------------------------------------
703*34615Smarc * smash the system's virtual console address table */
704*34615Smarc 
705*34615Smarc #ifdef notdef	/* the ultrix way */
706*34615Smarc 	v_consputc = qdputc;
707*34615Smarc 	v_consgetc = qdgetc;
708*34615Smarc 	cdevsw[0] = cdevsw[QDSSMAJOR];
709*34615Smarc #endif
710*34615Smarc 	/* the bsd way */
71132012Smarc 	v_putc = qdputc;
71232012Smarc 	consops = &cdevsw[QDSSMAJOR];
71330391Skarels 
714*34615Smarc  	ws_display_type = QDSSMAJOR;	/* Idenify QDSS as graphics device */
71530391Skarels 	return(1);
71630391Skarels 
71730391Skarels } /* qdcons_init */
71830391Skarels 
71930391Skarels /*********************************************************************
72030391Skarels *
72130391Skarels *	qdprobe()... configure QDSS into Q memory and make it intrpt
72230391Skarels *
72330391Skarels **********************************************************************
72430391Skarels *
72530391Skarels *  calling convention:
72630391Skarels *			qdprobe(reg, ctlr);
72730391Skarels *			caddr_t reg;
72830391Skarels *			int ctlr;
72930391Skarels *
73030391Skarels *	where: reg - a character pointer to the QDSS I/O page register
73130391Skarels *	       ctlr - controller number (?)
73230391Skarels *
73330391Skarels *  side effects: QDSS gets mapped into Qbus memory space at the first
73430391Skarels *		 vacant 64kb boundary counting back from the top of
735*34615Smarc *		 Qbus memory space (qvmem+4mb)
73630391Skarels *
73730391Skarels *  return: QDSS bus request level and vector address returned in
73830391Skarels *	   registers by UNIX convention.
73930391Skarels *
74030391Skarels *****************/
74130391Skarels 
74230391Skarels qdprobe(reg)
74330391Skarels caddr_t reg;
74430391Skarels {
745*34615Smarc 	register int br, cvec;  /* value-result */
74630391Skarels 
74730391Skarels 	register int unit;
74830391Skarels 
74930391Skarels 	struct dga *dga;		/* pointer to gate array structure */
75030391Skarels 	struct cpusw *cpup;		/* pointer to the cpusw structure */
75130391Skarels 
75230391Skarels 	int *ptep;			/* page table entry pointer */
75330391Skarels 	int vector;
75430391Skarels 
75530391Skarels 	caddr_t phys_adr;		/* physical QDSS base adrs */
75630391Skarels 	u_int mapix;
75730391Skarels 
758*34615Smarc /*---------------------------------------------------------------
759*34615Smarc * calculate board unit number from I/O page register address  */
76030391Skarels 
76130391Skarels 	unit = (int) (((int)reg >> 1) & 0x0007);
76230391Skarels 
763*34615Smarc /*---------------------------------------------------------------------------
76430391Skarels * QDSS regs must be mapped to Qbus memory space at a 64kb physical boundary.
76530391Skarels * The Qbus memory space is mapped into the system memory space at config
766*34615Smarc * time.  After config runs, "qvmem[0]" (ubavar.h) holds the system virtual adrs
76730391Skarels * of the start of Qbus memory.	The Qbus memory page table is found via
768*34615Smarc * an array of pte ptrs called "QVmap[]" (ubavar.h) which is also loaded at
76930391Skarels * config time.	These are the variables used below to find a vacant 64kb
77030391Skarels * boundary in Qbus memory, and load it's corresponding physical adrs into
771*34615Smarc * the QDSS's I/O page CSR.  */
77230391Skarels 
773*34615Smarc 	/*
774*34615Smarc 	 * Only if QD is the graphics device.
775*34615Smarc 	 */
776*34615Smarc 
777*34615Smarc 	if (ws_display_type && (ws_display_type != QDSSMAJOR))
778*34615Smarc 		return(0);
779*34615Smarc 
78030391Skarels 	/* if this QDSS is NOT the console, then do init here.. */
78130391Skarels 
782*34615Smarc 	if (unit != 0) {
783*34615Smarc 		printf("qd: can't support two qdss's (yet)\n");
784*34615Smarc #ifdef notdef	/* notyet */
78530391Skarels 	if (v_consputc != qdputc  ||  unit != 0) {
78630391Skarels 
787*34615Smarc 	    /*-------------------------
788*34615Smarc 	    * read QDSS config info */
789*34615Smarc 
79030391Skarels 	    qdflags[unit].config = *(u_short *)reg;
79130391Skarels 
792*34615Smarc 	    /*------------------------------------
793*34615Smarc 	    * find an empty 64kb adrs boundary */
79430391Skarels 
795*34615Smarc 	    qdbase[unit] = (caddr_t) (qvmem[0] + QMEMSIZE - CHUNK);
796*34615Smarc 
797*34615Smarc 	    /*----------------------------------------------------
798*34615Smarc 	    * find the cpusw entry that matches this machine. */
799*34615Smarc 
80030391Skarels 	    cpup = &cpusw[cpu];
80130391Skarels 	    while ( !(BADADDR(qdbase[unit], sizeof(short))) )
80230391Skarels 		qdbase[unit] -= CHUNK;
80330391Skarels 
804*34615Smarc 	    /*---------------------------------------------------
805*34615Smarc 	    * tell QDSS which Q memory address base to decode */
806*34615Smarc 
807*34615Smarc 	    mapix = (int) (VTOP(qdbase[unit]) - VTOP(qvmem[0]));
808*34615Smarc 	    ptep = (int *) QVmap[0] + mapix;
80930391Skarels 	    phys_adr = (caddr_t) (((int)*ptep & 0x001FFFFF) << PGSHIFT);
81030391Skarels 	    *(u_short *)reg = (u_short) ((int)phys_adr >> 16);
81130391Skarels 
812*34615Smarc 	    /*-----------------------------------------------------------
813*34615Smarc 	    * load QDSS adrs map with system addresses of device regs */
814*34615Smarc 
81530391Skarels 	    qdmap[unit].template = qdbase[unit] + TMPSTART;
81630391Skarels 	    qdmap[unit].adder = qdbase[unit] + ADDER;
81730391Skarels 	    qdmap[unit].dga = qdbase[unit] + DGA;
81830391Skarels 	    qdmap[unit].duart = qdbase[unit] + DUART;
81930391Skarels 	    qdmap[unit].memcsr = qdbase[unit] + MEMCSR;
82030391Skarels 	    qdmap[unit].red = qdbase[unit] + RED;
82130391Skarels 	    qdmap[unit].blue = qdbase[unit] + BLUE;
82230391Skarels 	    qdmap[unit].green = qdbase[unit] + GREEN;
82330391Skarels 
82430391Skarels 	    /* device init */
82530391Skarels 
82630391Skarels 	    cursor[unit].x = 0;
82730391Skarels 	    cursor[unit].y = 0;
82830391Skarels 	    init_shared(unit);		/* init shared memory */
82930391Skarels 	    setup_dragon(unit); 	/* init the ADDER/VIPER stuff */
83030391Skarels 	    ldcursor(unit, cons_cursor);	/* load default cursor map */
83130391Skarels 	    setup_input(unit);		/* init the DUART */
83230391Skarels 	    clear_qd_screen(unit);
83330391Skarels 	    ldfont(unit);			/* load the console font */
83430391Skarels 
83530391Skarels 	    /* once only: turn on sync */
83630391Skarels 
83730391Skarels 	    *(short *)qdmap[unit].memcsr |= SYNC_ON;
838*34615Smarc #endif /*notdef*/
83930391Skarels 	}
84030391Skarels 
841*34615Smarc /*--------------------------------------------------------------------------
842*34615Smarc * the QDSS interrupts at HEX vectors xx0 (DMA) xx4 (ADDER) and xx8 (DUART).
843*34615Smarc * Therefore, we take three vectors from the vector pool, and then continue
844*34615Smarc * to take them until we get a xx0 HEX vector.  The pool provides vectors
845*34615Smarc * in contiguous decending order.  */
84630391Skarels 
84730391Skarels 	vector = (uba_hd[0].uh_lastiv -= 4*3);	/* take three vectors */
84830391Skarels 
84930391Skarels 	while (vector & 0x0F) { 		   /* if lo nibble != 0.. */
85030391Skarels 	    vector = (uba_hd[0].uh_lastiv -= 4);  /* ..take another vector */
85130391Skarels 	}
85230391Skarels 
853*34615Smarc 	/*---------------------------------------------------------
854*34615Smarc 	* setup DGA to do a DMA interrupt (transfer count = 0)	*/
85530391Skarels 
85630391Skarels 	dga = (struct dga *) qdmap[unit].dga;
85730391Skarels 
85830391Skarels 	dga->csr = (short) HALT;	      /* disable everything */
85930391Skarels 	dga->ivr = (short) vector;	      /* load intrpt base vector */
86030391Skarels 	dga->bytcnt_lo = (short) 0;	      /* DMA xfer count = 0 */
86130391Skarels 	dga->bytcnt_hi = (short) 0;
86230391Skarels 
86330391Skarels 	/* turn on DMA interrupts */
86430391Skarels 
86530391Skarels 	dga->csr &= ~SET_DONE_FIFO;
86630391Skarels 	dga->csr |= DMA_IE | DL_ENB;
86730391Skarels 
86830391Skarels 	DELAY(20000);			/* wait for the intrpt */
86930391Skarels 
87030391Skarels 	dga->csr = HALT;		/* stop the wheels */
87130391Skarels 
872*34615Smarc /*----------
873*34615Smarc * exits  */
874*34615Smarc 
87530391Skarels 	if (cvec != vector)		/* if vector != base vector.. */
87630391Skarels 	    return(0);			/* ..return = 'no device' */
87730391Skarels 
878*34615Smarc 	/*
879*34615Smarc 	 * score this as an existing qdss
880*34615Smarc 	 */
881*34615Smarc 	qdcount++;
882*34615Smarc  	ws_display_units |= (1 << unit);
883*34615Smarc 
88430391Skarels 	return(sizeof(short));	    /* return size of QDSS I/O page reg */
88530391Skarels 
88630391Skarels } /* qdprobe */
88730391Skarels 
88830391Skarels /*****************************************************************
88930391Skarels *
890*34615Smarc *	qdattach()... do the one-time initialization
89130391Skarels *
89230391Skarels ******************************************************************
89330391Skarels *
89430391Skarels *  calling convention:
89530391Skarels *			qdattach(ui);
89630391Skarels *			struct uba_device *ui;
89730391Skarels *
89830391Skarels *		where: ui - pointer to the QDSS's uba_device structure
89930391Skarels *
90030391Skarels *  side effects: none
90130391Skarels *	 return: none
90230391Skarels *
90330391Skarels *************************/
90430391Skarels 
90530391Skarels qdattach(ui)
90630391Skarels struct uba_device *ui;
90730391Skarels {
90830391Skarels 	register u_int unit;		/* QDSS module # for this call */
90930391Skarels 
91030391Skarels 	unit = ui->ui_unit;		/* get QDSS number */
91130391Skarels 
912*34615Smarc /*----------------------------------
913*34615Smarc * init "qdflags[]" for this QDSS */
91430391Skarels 
91530391Skarels 	qdflags[unit].inuse = 0;	/* init inuse variable EARLY! */
91630391Skarels 	qdflags[unit].mapped = 0;
917*34615Smarc 	qdflags[unit].kernel_loop = -1;
91830391Skarels 	qdflags[unit].user_dma = 0;
91930391Skarels 	qdflags[unit].curs_acc = ACC_OFF;
92030391Skarels 	qdflags[unit].curs_thr = 128;
92130391Skarels 	qdflags[unit].tab_res = 2;	/* default tablet resolution factor */
92230391Skarels 	qdflags[unit].duart_imask = 0;	/* init shadow variables */
92330391Skarels 	qdflags[unit].adder_ie = 0;
92430391Skarels 
925*34615Smarc /*----------------------------------------------------------------------
926*34615Smarc * init structures used in kbd/mouse interrupt service.	This code must
927*34615Smarc * come after the "init_shared()" routine has run since that routine inits
928*34615Smarc * the eq_header[unit] structure used here.   */
92930391Skarels 
930*34615Smarc 	/*--------------------------------------------
931*34615Smarc 	* init the "latest mouse report" structure */
93230391Skarels 
93330391Skarels 	last_rep[unit].state = 0;
93430391Skarels 	last_rep[unit].dx = 0;
93530391Skarels 	last_rep[unit].dy = 0;
93630391Skarels 	last_rep[unit].bytcnt = 0;
93730391Skarels 
938*34615Smarc 	/*------------------------------------------------
939*34615Smarc 	* init the event queue (except mouse position) */
94030391Skarels 
94130391Skarels 	eq_header[unit]->header.events = (struct _vs_event *)
94230391Skarels 					  ((int)eq_header[unit]
94330391Skarels 					   + sizeof(struct qdinput));
94430391Skarels 
94530391Skarels 	eq_header[unit]->header.size = MAXEVENTS;
94630391Skarels 	eq_header[unit]->header.head = 0;
94730391Skarels 	eq_header[unit]->header.tail = 0;
94830391Skarels 
949*34615Smarc /*------------------------------------------
950*34615Smarc * init single process access lock switch */
95130391Skarels 
95230391Skarels 	one_only[unit] = 0;
95330391Skarels 
95430391Skarels } /* qdattach */
95530391Skarels 
95630391Skarels /***************************************************************
95730391Skarels *
958*34615Smarc *	qdopen()... open a minor device
95930391Skarels *
96030391Skarels ****************************************************************
96130391Skarels *
96230391Skarels *  calling convention: qdopen(dev, flag);
96330391Skarels *		       dev_t dev;
96430391Skarels *		       int flag;
96530391Skarels *
96630391Skarels *  side effects: none
96730391Skarels *
96830391Skarels *********************/
96930391Skarels 
97030391Skarels qdopen(dev, flag)
97130391Skarels dev_t dev;
97230391Skarels int flag;
97330391Skarels {
97430391Skarels 	register struct uba_device *ui; /* ptr to uba structures */
97530391Skarels 	register struct dga *dga;	/* ptr to gate array struct */
97630391Skarels 	register struct tty *tp;
97730391Skarels 
97830391Skarels 	struct adder *adder;
97930391Skarels 	struct duart *duart;
98030391Skarels 
98130391Skarels 	u_int unit;
98230391Skarels 	u_int minor_dev;
98330391Skarels 	int s;
98430391Skarels 
98530391Skarels 	minor_dev = minor(dev); /* get QDSS minor device number */
98630391Skarels 	unit = minor_dev >> 2;
98730391Skarels 
988*34615Smarc /*---------------------------------
989*34615Smarc * check for illegal conditions	*/
99030391Skarels 
99130391Skarels 	ui = qdinfo[unit];		/* get ptr to QDSS device struct */
99230391Skarels 
99330391Skarels 	if (ui == 0  || ui->ui_alive == 0)
99430391Skarels 	    return(ENXIO);		/* no such device or address */
99530391Skarels 
996*34615Smarc /*--------------
997*34615Smarc * init stuff */
99830391Skarels 
99930391Skarels 	adder = (struct adder *) qdmap[unit].adder;
100030391Skarels 	duart = (struct duart *) qdmap[unit].duart;
100130391Skarels 	dga = (struct dga *) qdmap[unit].dga;
100230391Skarels 
1003*34615Smarc /*------------------------------------
1004*34615Smarc * if this is the graphic device... */
100530391Skarels 
100630391Skarels 	if ((minor_dev & 0x03) == 2) {
100730391Skarels 
100830391Skarels 	    if (one_only[unit] != 0)
100930391Skarels 		return(EBUSY);
101030391Skarels 	    else
101130391Skarels 		one_only[unit] = 1;
101230391Skarels 
101330391Skarels 	    qdflags[unit].inuse |= GRAPHIC_DEV;  /* graphics dev is open */
101430391Skarels 
101530391Skarels 	    /* enble kbd & mouse intrpts in DUART mask reg */
101630391Skarels 
101730391Skarels 	    qdflags[unit].duart_imask |= 0x22;
101830391Skarels 	    duart->imask = qdflags[unit].duart_imask;
101930391Skarels 
1020*34615Smarc /*------------------------------------------------------------------
1021*34615Smarc * if the open call is to the console or the alternate console... */
102230391Skarels 
1023*34615Smarc 	} else if ((minor_dev & 0x03) != 2) {
1024*34615Smarc 
102530391Skarels 	    qdflags[unit].inuse |= CONS_DEV;  /* mark console as open */
102630391Skarels 	    dga->csr |= CURS_ENB;
102730391Skarels 
102830391Skarels 	    qdflags[unit].duart_imask |= 0x02;
102930391Skarels 	    duart->imask = qdflags[unit].duart_imask;
103030391Skarels 
103130391Skarels 	    /*-------------------------------
103230391Skarels 	    * some setup for tty handling */
103330391Skarels 
103430391Skarels 	    tp = &qd_tty[minor_dev];
103530391Skarels 
103630391Skarels 	    tp->t_addr = ui->ui_addr;
103730391Skarels 	    tp->t_oproc = qdstart;
1038*34615Smarc #ifdef notdef	/* never */
1039*34615Smarc 	/*---------------------------------------------------------------------
1040*34615Smarc 	* Look at the compatibility mode to specify correct default parameters
1041*34615Smarc 	* and to insure only standard specified functionality. */
1042*34615Smarc 	if ((u.u_procp->p_progenv == A_SYSV) ||
1043*34615Smarc 		(u.u_procp->p_progenv == A_POSIX)) {
1044*34615Smarc 		flag |= O_TERMIO;
1045*34615Smarc 		tp->t_line = TERMIODISC;
1046*34615Smarc 	}
1047*34615Smarc #endif /*notdef*/
104830391Skarels 
104930391Skarels 	    if ((tp->t_state & TS_ISOPEN) == 0) {
105030391Skarels 
105130391Skarels 		ttychars(tp);
1052*34615Smarc 		tp->t_flags = IFLAGS;
105330391Skarels 		tp->t_ispeed = B9600;
105430391Skarels 		tp->t_ospeed = B9600;
1055*34615Smarc 		tp->t_state = TS_ISOPEN | TS_CARR_ON;
105630391Skarels 
1057*34615Smarc #ifdef notdef	/* never */
1058*34615Smarc 		tp->t_cflag = tp->t_cflag_ext = B9600;
1059*34615Smarc 		tp->t_iflag_ext = 0;
1060*34615Smarc 		tp->t_oflag_ext = 0;
1061*34615Smarc 		tp->t_lflag_ext = 0;
1062*34615Smarc 
1063*34615Smarc 		if( (minor_dev & 0x03) == 0 ) {
1064*34615Smarc 			/*----------------------------------------------------
1065*34615Smarc 			* Ultrix defaults to a "COOKED" mode on the first
1066*34615Smarc 			* open, while termio defaults to a "RAW" style.
1067*34615Smarc 			* Base this decision by a flag set in the termio
1068*34615Smarc 			* emulation routine for open, or set by an explicit
1069*34615Smarc 			* ioctl call. */
1070*34615Smarc 
1071*34615Smarc 			if ( flag & O_TERMIO ) {
1072*34615Smarc 				/*--------------------------------------
1073*34615Smarc 				* Provide a termio style environment.
1074*34615Smarc 				* "RAW" style by default. */
1075*34615Smarc 
1076*34615Smarc 				tp->t_flags = RAW;
1077*34615Smarc 				tp->t_iflag = 0;
1078*34615Smarc 				tp->t_oflag = 0;
1079*34615Smarc 				tp->t_cflag |= CS8|CREAD|HUPCL;
1080*34615Smarc 				tp->t_lflag = 0;
1081*34615Smarc 
1082*34615Smarc 				/*-------------------------------------
1083*34615Smarc 				 * Change to System V line discipline.*/
1084*34615Smarc 
1085*34615Smarc 				tp->t_line = TERMIODISC;
1086*34615Smarc 				/*-----------------------------------------
1087*34615Smarc 				* The following three control chars have
1088*34615Smarc 				* different default values than ULTRIX.	*/
1089*34615Smarc 
1090*34615Smarc 	 			tp->t_cc[VERASE] = '#';
1091*34615Smarc 	 			tp->t_cc[VKILL] = '@';
1092*34615Smarc 	 			tp->t_cc[VINTR] = 0177;
1093*34615Smarc  				tp->t_cc[VMIN] = 6;
1094*34615Smarc  				tp->t_cc[VTIME] = 1;
1095*34615Smarc 			} else {
1096*34615Smarc 				/*--------------------------------------
1097*34615Smarc 				* Provide a backward compatible ULTRIX
1098*34615Smarc 				* environment.  "COOKED" style.	*/
1099*34615Smarc 
1100*34615Smarc 				tp->t_flags = IFLAGS;
1101*34615Smarc 				tp->t_iflag = IFLAG;
1102*34615Smarc 				tp->t_oflag = OFLAG;
1103*34615Smarc 				tp->t_lflag = LFLAG;
1104*34615Smarc 				tp->t_cflag |= CFLAG;
1105*34615Smarc 			}
110632012Smarc 		}
110732012Smarc 		else {
110830391Skarels 		    tp->t_flags = RAW;
1109*34615Smarc 		    tp->t_iflag = 0;
1110*34615Smarc 		    tp->t_oflag = 0;
1111*34615Smarc 		    tp->t_cflag |= CS8|CREAD|HUPCL;
1112*34615Smarc 		    tp->t_lflag = 0;
111332012Smarc 		}
1114*34615Smarc                 if( (minor_dev & 0x03) == 1 )
1115*34615Smarc                     tp->t_iflag |= IXOFF;	/* flow control for qconsole */
1116*34615Smarc #endif /*notdef*/
111730391Skarels 	    }
111830391Skarels 
111930391Skarels 	    /*----------------------------------------
112030391Skarels 	    * enable intrpts, open line discipline */
112130391Skarels 
112230391Skarels 	    dga->csr |= GLOBAL_IE;	/* turn on the interrupts */
112330391Skarels 	    return ((*linesw[tp->t_line].l_open)(dev, tp));
112430391Skarels 	}
112530391Skarels 
112630391Skarels 	dga->csr |= GLOBAL_IE;	/* turn on the interrupts */
112730391Skarels 	return(0);
112830391Skarels 
112930391Skarels } /* qdopen */
113030391Skarels 
113130391Skarels /***************************************************************
113230391Skarels *
1133*34615Smarc *	qdclose()... clean up on the way out
113430391Skarels *
113530391Skarels ****************************************************************
113630391Skarels *
113730391Skarels *  calling convention: qdclose();
113830391Skarels *
113930391Skarels *  side effects: none
114030391Skarels *
114130391Skarels *  return: none
114230391Skarels *
114330391Skarels *********************/
114430391Skarels 
114530391Skarels qdclose(dev, flag)
114630391Skarels dev_t dev;
114730391Skarels int flag;
114830391Skarels {
114930391Skarels 	register struct tty *tp;
115030391Skarels 	register struct qdmap *qd;
115130391Skarels 	register int *ptep;
115230391Skarels 	int i;				/* SIGNED index */
115330391Skarels 
115430391Skarels 	struct dga *dga;		/* gate array register map pointer */
115530391Skarels 	struct duart *duart;
115630391Skarels 	struct adder *adder;
115730391Skarels 
115830391Skarels 	u_int unit;
115930391Skarels 	u_int minor_dev;
116030391Skarels 	u_int mapix;
116130391Skarels 
116230391Skarels 	minor_dev = minor(dev); 	/* get minor device number */
116330391Skarels 	unit = minor_dev >> 2;		/* get QDSS number */
116430391Skarels 	qd = &qdmap[unit];
116530391Skarels 
1166*34615Smarc /*------------------------------------
1167*34615Smarc * if this is the graphic device... */
116830391Skarels 
116930391Skarels 	if ((minor_dev & 0x03) == 2) {
1170*34615Smarc 
1171*34615Smarc 	    /*-----------------
1172*34615Smarc 	    * unlock driver */
1173*34615Smarc 
1174*34615Smarc 	    if (one_only[unit] != 1)
117530391Skarels 		return(EBUSY);
117630391Skarels 	    else
117730391Skarels 		one_only[unit] = 0;
117830391Skarels 
1179*34615Smarc 	    /*----------------------------
1180*34615Smarc 	    * re-protect device memory */
118130391Skarels 
118230391Skarels 	    if (qdflags[unit].mapped & MAPDEV) {
118330391Skarels 
1184*34615Smarc 		/*----------------
1185*34615Smarc 		* TEMPLATE RAM */
118630391Skarels 
118732012Smarc 		mapix = VTOP((int)qd->template) - VTOP(qvmem[0]);
118832012Smarc 		ptep = (int *)(QVmap[0] + mapix);
118930391Skarels 
119030391Skarels 		for (i = VTOP(TMPSIZE); i > 0; --i)
119130391Skarels 		    *ptep++ = (*ptep & ~PG_PROT) | PG_V | PG_KW;
119230391Skarels 
1193*34615Smarc 		/*---------
1194*34615Smarc 		* ADDER */
119530391Skarels 
119632012Smarc 		mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]);
119732012Smarc 		ptep = (int *)(QVmap[0] + mapix);
119830391Skarels 
119930391Skarels 		for (i = VTOP(REGSIZE); i > 0; --i)
120030391Skarels 		    *ptep++ = (*ptep & ~PG_PROT) | PG_V | PG_KW;
120130391Skarels 
1202*34615Smarc 		/*--------------
1203*34615Smarc 		* COLOR MAPS */
120430391Skarels 
120532012Smarc 		mapix = VTOP((int)qd->red) - VTOP(qvmem[0]);
120632012Smarc 		ptep = (int *)(QVmap[0] + mapix);
120730391Skarels 
120830391Skarels 		for (i = VTOP(CLRSIZE); i > 0; --i)
120930391Skarels 		    *ptep++ = (*ptep & ~PG_PROT) | PG_V | PG_KW;
121030391Skarels 	    }
121130391Skarels 
1212*34615Smarc 	    /*----------------------------------------------------
1213*34615Smarc 	    * re-protect DMA buffer and free the map registers */
121430391Skarels 
121530391Skarels 	    if (qdflags[unit].mapped & MAPDMA) {
121630391Skarels 
121730391Skarels 		dga = (struct dga *) qdmap[unit].dga;
121830391Skarels 		adder = (struct adder *) qdmap[unit].adder;
121930391Skarels 
122030391Skarels 		dga->csr &= ~DMA_IE;
122130391Skarels 		dga->csr &= ~0x0600;	     /* kill DMA */
122230391Skarels 		adder->command = CANCEL;
122330391Skarels 
122430391Skarels 		/* if DMA was running, flush spurious intrpt */
122530391Skarels 
122630391Skarels 		if (dga->bytcnt_lo != 0) {
122730391Skarels 		    dga->bytcnt_lo = 0;
122830391Skarels 		    dga->bytcnt_hi = 0;
122930391Skarels 		    DMA_SETIGNORE(DMAheader[unit]);
123030391Skarels 		    dga->csr |= DMA_IE;
123130391Skarels 		    dga->csr &= ~DMA_IE;
123230391Skarels 		}
123330391Skarels 
123430391Skarels 		ptep = (int *)
123530391Skarels 			((VTOP(DMAheader[unit]*4)) + (mfpr(SBR)|0x80000000));
123630391Skarels 
123730391Skarels 		for (i = (DMAbuf_size >> PGSHIFT); i > 0; --i)
123830391Skarels 		    *ptep++ = (*ptep & ~PG_PROT) | PG_V | PG_KW;
123930391Skarels 
124030391Skarels 		ubarelse(0, &Qbus_unmap[unit]);
124130391Skarels 	    }
124230391Skarels 
1243*34615Smarc 	    /*---------------------------------------
1244*34615Smarc 	    * re-protect 1K (2 pages) event queue */
124530391Skarels 
124630391Skarels 	    if (qdflags[unit].mapped & MAPEQ) {
124730391Skarels 
124830391Skarels 		ptep = (int *)
124930391Skarels 			((VTOP(eq_header[unit])*4) + (mfpr(SBR)|0x80000000));
125030391Skarels 
125130391Skarels 		*ptep++ = (*ptep & ~PG_PROT) | PG_KW | PG_V;
125230391Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
125330391Skarels 	    }
125430391Skarels 
1255*34615Smarc 	    /*------------------------------------------------------------
1256*34615Smarc 	    * re-protect scroll param area and disable scroll intrpts  */
125730391Skarels 
125830391Skarels 	    if (qdflags[unit].mapped & MAPSCR) {
125930391Skarels 
126030391Skarels 		ptep = (int *) ((VTOP(scroll[unit]) * 4)
126130391Skarels 				    + (mfpr(SBR) | 0x80000000));
126230391Skarels 
126330391Skarels 		/* re-protect 512 scroll param area */
126430391Skarels 
126530391Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
126630391Skarels 
126730391Skarels 		adder = (struct adder *) qdmap[unit].adder;
126830391Skarels 		qdflags[unit].adder_ie &= ~FRAME_SYNC;
126930391Skarels 		adder->interrupt_enable = qdflags[unit].adder_ie;
127030391Skarels 	    }
127130391Skarels 
1272*34615Smarc 	    /*-----------------------------------------------------------
1273*34615Smarc 	    * re-protect color map write buffer area and kill intrpts */
127430391Skarels 
127530391Skarels 	    if (qdflags[unit].mapped & MAPCOLOR) {
127630391Skarels 
127730391Skarels 		ptep = (int *) ((VTOP(color_buf[unit]) * 4)
127830391Skarels 				    + (mfpr(SBR) | 0x80000000));
127930391Skarels 
128030391Skarels 		*ptep++ = (*ptep & ~PG_PROT) | PG_KW | PG_V;
128130391Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
128230391Skarels 
128330391Skarels 		color_buf[unit]->status = 0;
128430391Skarels 
128530391Skarels 		adder = (struct adder *) qdmap[unit].adder;
128630391Skarels 		qdflags[unit].adder_ie &= ~VSYNC;
128730391Skarels 		adder->interrupt_enable = qdflags[unit].adder_ie;
128830391Skarels 	    }
128930391Skarels 
1290*34615Smarc 	    /*-----------------------------------
1291*34615Smarc 	    * flag that everthing is unmapped */
129230391Skarels 
1293*34615Smarc 	    mtpr(TBIA, 0);		/* smash CPU's translation buf */
1294*34615Smarc 	    qdflags[unit].mapped = 0;	/* flag everything now unmapped */
129530391Skarels 	    qdflags[unit].inuse &= ~GRAPHIC_DEV;
129630391Skarels 	    qdflags[unit].curs_acc = ACC_OFF;
129730391Skarels 	    qdflags[unit].curs_thr = 128;
129830391Skarels 
1299*34615Smarc 	    /*---------------------
1300*34615Smarc 	    * restore the console */
130130391Skarels 
130230391Skarels 		dga = (struct dga *) qdmap[unit].dga;
130330391Skarels 		adder = (struct adder *) qdmap[unit].adder;
130430391Skarels 
130530391Skarels 		dga->csr &= ~DMA_IE;
130630391Skarels 		dga->csr &= ~0x0600;	/* halt the DMA! (just in case...) */
130730391Skarels 		dga->csr |= DMA_ERR;	/* clear error condition */
130830391Skarels 		adder->command = CANCEL;
130930391Skarels 
131030391Skarels 		/* if DMA was running, flush spurious intrpt */
131130391Skarels 
131230391Skarels 		if (dga->bytcnt_lo != 0) {
131330391Skarels 		    dga->bytcnt_lo = 0;
131430391Skarels 		    dga->bytcnt_hi = 0;
131530391Skarels 		    DMA_SETIGNORE(DMAheader[unit]);
131630391Skarels 		    dga->csr |= DMA_IE;
131730391Skarels 		    dga->csr &= ~DMA_IE;
131830391Skarels 		}
131930391Skarels 
132030391Skarels 		init_shared(unit);		/* init shared memory */
132130391Skarels 		setup_dragon(unit);		/* init ADDER/VIPER */
132230391Skarels 		ldcursor(unit, cons_cursor);	/* load default cursor map */
132330391Skarels 		setup_input(unit);		/* init the DUART */
132430391Skarels 		ldfont(unit);
132530391Skarels 		cursor[unit].x = 0;
132630391Skarels 		cursor[unit].y = 0;
132730391Skarels 
1328*34615Smarc 	    /* shut off the mouse rcv intrpt and turn on kbd intrpts */
1329*34615Smarc 
133030391Skarels 	    duart = (struct duart *) qdmap[unit].duart;
133130391Skarels 	    qdflags[unit].duart_imask &= ~(0x20);
133230391Skarels 	    qdflags[unit].duart_imask |= 0x02;
133330391Skarels 	    duart->imask = qdflags[unit].duart_imask;
1334*34615Smarc 
1335*34615Smarc 	    /*-----------------------------------------
1336*34615Smarc 	    * shut off interrupts if all is closed  */
1337*34615Smarc 
133830391Skarels 	    if (!(qdflags[unit].inuse & (CONS_DEV | ALTCONS_DEV))) {
1339*34615Smarc 
134030391Skarels 		dga = (struct dga *) qdmap[unit].dga;
134130391Skarels 		dga->csr &= ~(GLOBAL_IE | DMA_IE);
134230391Skarels 	    }
134330391Skarels 	}
1344*34615Smarc 
1345*34615Smarc /*----------------------------------------------------
1346*34615Smarc * if this is the console or the alternate console  */
1347*34615Smarc 
1348*34615Smarc 	else {
1349*34615Smarc 
135030391Skarels 	    tp = &qd_tty[minor_dev];
135130391Skarels 
135230391Skarels 	    (*linesw[tp->t_line].l_close)(tp);
135330391Skarels 	    ttyclose(tp);
1354*34615Smarc 
135530391Skarels 	    tp->t_state = 0;
1356*34615Smarc 	    /* Remove termio flags that do not map */
1357*34615Smarc #ifdef notdef	/* never */
1358*34615Smarc 	    tp->t_iflag &= ~TERMIO_ONLY_IFLAG;
1359*34615Smarc 	    tp->t_oflag &= ~TERMIO_ONLY_OFLAG;
1360*34615Smarc 	    tp->t_cflag &= ~TERMIO_ONLY_CFLAG;
1361*34615Smarc 	    tp->t_lflag &= ~TERMIO_ONLY_LFLAG;
1362*34615Smarc #endif /*notdef*/
1363*34615Smarc 
136430391Skarels 	    qdflags[unit].inuse &= ~CONS_DEV;
1365*34615Smarc 
1366*34615Smarc 	    /*-------------------------------------------------
1367*34615Smarc 	    * if graphics device is closed, kill interrupts */
1368*34615Smarc 
136930391Skarels 	    if (!(qdflags[unit].inuse & GRAPHIC_DEV)) {
137030391Skarels 		dga = (struct dga *) qdmap[unit].dga;
137130391Skarels 		dga->csr &= ~(GLOBAL_IE | DMA_IE);
137230391Skarels 	    }
137330391Skarels 	}
137430391Skarels 
1375*34615Smarc /*--------
1376*34615Smarc * exit */
1377*34615Smarc 
137830391Skarels 	return(0);
137930391Skarels 
138030391Skarels } /* qdclose */
138130391Skarels 
138230391Skarels /***************************************************************
138330391Skarels *
1384*34615Smarc *	qdioctl()... provide QDSS control services
138530391Skarels *
138630391Skarels ****************************************************************
138730391Skarels *
138830391Skarels *  calling convention:	qdioctl(dev, cmd, datap, flags);
138930391Skarels *
139030391Skarels *		where:	dev - the major/minor device number
139130391Skarels *			cmd - the user-passed command argument
139230391Skarels *			datap - ptr to user input buff (128 bytes max)
139330391Skarels *			flags - "f_flags" from "struct file" in file.h
139430391Skarels *
139530391Skarels *
139630391Skarels *	- here is the format for the input "cmd" argument
139730391Skarels *
139830391Skarels *	31     29 28	23 22	      16 15		8 7		 0
139930391Skarels *	+----------------------------------------------------------------+
140030391Skarels *	|I/O type|	  | buff length | device ID char |  user command |
140130391Skarels *	+----------------------------------------------------------------+
140230391Skarels *
140330391Skarels *  Return data is in the data buffer pointed to by "datap" input spec
140430391Skarels *
140530391Skarels *********************/
140630391Skarels 
140730391Skarels qdioctl(dev, cmd, datap, flags)
140830391Skarels dev_t dev;
140930391Skarels int cmd;
141030391Skarels caddr_t datap;
141130391Skarels int flags;
141230391Skarels {
141330391Skarels 	register int *ptep;		/* page table entry pointer */
141432012Smarc 	register int mapix;		/* QVmap[] page table index */
141530391Skarels 	register struct _vs_event *event;
141630391Skarels 	register struct tty *tp;
1417*34615Smarc 
141830391Skarels 	struct qdmap *qd;		/* pointer to device map struct */
141930391Skarels 	struct dga *dga;		/* Gate Array reg structure pntr */
142030391Skarels 	struct duart *duart;		/* DUART reg structure pointer */
142130391Skarels 	struct adder *adder;		/* ADDER reg structure pointer */
1422*34615Smarc 
142330391Skarels 	struct prgkbd *cmdbuf;
142430391Skarels 	struct prg_cursor *curs;
142530391Skarels 	struct _vs_cursor *pos;
1426*34615Smarc 
142730391Skarels 	u_int unit = minor(dev) >> 2;	/* number of caller's QDSS */
142830391Skarels 	u_int minor_dev = minor(dev);
142930391Skarels 	struct uba_device *ui = qdinfo[unit];
143030391Skarels 	struct qd_softc *sc = &qd_softc[ui->ui_unit];
1431*34615Smarc #ifdef notdef
1432*34615Smarc 	struct devget *devget;
1433*34615Smarc #endif
1434*34615Smarc 
143530391Skarels 	int error;
143630391Skarels 	int s;
1437*34615Smarc 
143830391Skarels 	int i;				/* SIGNED index */
143930391Skarels 	int sbr;			/* SBR variable (you silly boy) */
144030391Skarels 	u_int ix;
1441*34615Smarc 
144230391Skarels 	short status;
144330391Skarels 	short *shortp;			/* generic pointer to a short */
144430391Skarels 	char *chrp;			/* generic character pointer */
1445*34615Smarc 
144630391Skarels 	short *temp;			/* a pointer to template RAM */
144730391Skarels 
1448*34615Smarc /*-----------------------------------------
1449*34615Smarc * service graphic device ioctl commands */
1450*34615Smarc 
145130391Skarels 	switch (cmd) {
1452*34615Smarc 
1453*34615Smarc 	    /*-------------------------------------------------
1454*34615Smarc 	    * extract the oldest event from the event queue */
1455*34615Smarc 
145630391Skarels 	    case QD_GETEVENT:
1457*34615Smarc 
145830391Skarels 		if (ISEMPTY(eq_header[unit])) {
145930391Skarels 		    event = (struct _vs_event *) datap;
146030391Skarels 		    event->vse_device = VSE_NULL;
146130391Skarels 		    break;
146230391Skarels 		}
1463*34615Smarc 
146430391Skarels 		event = (struct _vs_event *) GETBEGIN(eq_header[unit]);
1465*34615Smarc 		s = spl5();
146630391Skarels 		GETEND(eq_header[unit]);
146730391Skarels 		splx(s);
146830391Skarels 		bcopy(event, datap, sizeof(struct _vs_event));
146930391Skarels 		break;
147030391Skarels 
147130391Skarels 	    /*-------------------------------------------------------
147230391Skarels 	    * init the dragon stuff, DUART, and driver variables  */
147330391Skarels 
147430391Skarels 	    case QD_RESET:
147530391Skarels 
147630391Skarels 		init_shared(unit);		/* init shared memory */
147730391Skarels 		setup_dragon(unit);	      /* init the ADDER/VIPER stuff */
147830391Skarels 		clear_qd_screen(unit);
147930391Skarels 		ldcursor(unit, cons_cursor);	/* load default cursor map */
148030391Skarels 		ldfont(unit);			/* load the console font */
148130391Skarels 		setup_input(unit);		/* init the DUART */
148230391Skarels 		break;
148330391Skarels 
148430391Skarels 	    /*----------------------------------------
148530391Skarels 	    * init the DUART and driver variables  */
148630391Skarels 
148730391Skarels 	    case QD_SET:
148830391Skarels 
148930391Skarels 		init_shared(unit);
149030391Skarels 		setup_input(unit);
149130391Skarels 		break;
149230391Skarels 
149330391Skarels 	    /*---------------------------------------------------------------
149430391Skarels 	    * clear the QDSS screen.  (NOTE that this reinits the dragon) */
149530391Skarels 
149630391Skarels 	    case QD_CLRSCRN:
149730391Skarels 
1498*34615Smarc #ifdef notdef	/* has caused problems and is not necessary */
149930391Skarels 		setup_dragon(unit);
150030391Skarels 		clear_qd_screen(unit);
1501*34615Smarc #endif
150230391Skarels 		break;
150330391Skarels 
150430391Skarels 	    /*------------------------------------
150530391Skarels 	    * load a cursor into template RAM  */
150630391Skarels 
150730391Skarels 	    case QD_WTCURSOR:
150830391Skarels 
150930391Skarels 		ldcursor(unit, datap);
151030391Skarels 		break;
151130391Skarels 
151230391Skarels 	    case QD_RDCURSOR:
151330391Skarels 
151430391Skarels 		temp = (short *) qdmap[unit].template;
151530391Skarels 
151630391Skarels 		/* cursor is 32 WORDS from the end of the 8k WORD...
151730391Skarels 		*  ...template space */
151830391Skarels 
151930391Skarels 		temp += (8 * 1024) - 32;
152030391Skarels 
152130391Skarels 		for (i = 0; i < 32; ++i, datap += sizeof(short))
152230391Skarels 		    *(short *)datap = *temp++;
152330391Skarels 		break;
152430391Skarels 
152530391Skarels 	    /*------------------------------
152630391Skarels 	    * position the mouse cursor  */
152730391Skarels 
152830391Skarels 	    case QD_POSCURSOR:
152930391Skarels 
153030391Skarels 		dga = (struct dga *) qdmap[unit].dga;
153130391Skarels 		pos = (struct _vs_cursor *) datap;
1532*34615Smarc 		s = spl5();
153330391Skarels 		dga->x_cursor = TRANX(pos->x);
153430391Skarels 		dga->y_cursor = TRANY(pos->y);
153530391Skarels 		eq_header[unit]->curs_pos.x = pos->x;
153630391Skarels 		eq_header[unit]->curs_pos.y = pos->y;
153730391Skarels 		splx(s);
153830391Skarels 		break;
153930391Skarels 
154030391Skarels 	    /*--------------------------------------
154130391Skarels 	    * set the cursor acceleration factor */
154230391Skarels 
154330391Skarels 	    case QD_PRGCURSOR:
154430391Skarels 
154530391Skarels 		curs = (struct prg_cursor *) datap;
1546*34615Smarc 		s = spl5();
154730391Skarels 		qdflags[unit].curs_acc = curs->acc_factor;
154830391Skarels 		qdflags[unit].curs_thr = curs->threshold;
154930391Skarels 		splx(s);
155030391Skarels 		break;
155130391Skarels 
155230391Skarels 	    /*---------------------------------------
155330391Skarels 	    * enable 'user write' to device pages */
155430391Skarels 
155530391Skarels 	    case QD_MAPDEVICE:
155630391Skarels 
155730391Skarels 		/*--------------
155830391Skarels 		* init stuff */
155930391Skarels 
156030391Skarels 		qdflags[unit].mapped |= MAPDEV;
156130391Skarels 		qd = (struct qdmap *) &qdmap[unit];
156230391Skarels 
156330391Skarels 		/*-------------------------------------
156430391Skarels 		* enable user write to template RAM */
156530391Skarels 
156632012Smarc 		mapix = VTOP((int)qd->template) - VTOP(qvmem[0]);
156732012Smarc 		ptep = (int *)(QVmap[0] + mapix);
156830391Skarels 
156930391Skarels 		for (i = VTOP(TMPSIZE); i > 0; --i)
157030391Skarels 		    *ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V;
157130391Skarels 
157230391Skarels 		/*----------------------------------
157330391Skarels 		* enable user write to registers */
157430391Skarels 
157532012Smarc 		mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]);
157632012Smarc 		ptep = (int *)(QVmap[0] + mapix);
157730391Skarels 
157830391Skarels 		for (i = VTOP(REGSIZE); i > 0; --i)
157930391Skarels 		    *ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V;
158030391Skarels 
158130391Skarels 		/*-----------------------------------
158230391Skarels 		* enable user write to color maps */
158330391Skarels 
158432012Smarc 		mapix = VTOP((int)qd->red) - VTOP(qvmem[0]);
158532012Smarc 		ptep = (int *)(QVmap[0] + mapix);
158630391Skarels 
158730391Skarels 		for (i = VTOP(CLRSIZE); i > 0; --i)
158830391Skarels 		    *ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V;
158930391Skarels 
159030391Skarels 		/*------------------------------
159130391Skarels 		* enable user write to DUART */
159230391Skarels 
159332012Smarc 		mapix = VTOP((int)qd->duart) - VTOP(qvmem[0]);
159432012Smarc 		ptep = (int *)(QVmap[0] + mapix);
159530391Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; /* duart page */
159630391Skarels 
159730391Skarels 		mtpr(TBIA, 0);		/* smash CPU's translation buffer */
159830391Skarels 
159930391Skarels 		/*------------------------------------------
160030391Skarels 		* stuff qdmap structure in return buffer */
160130391Skarels 
160230391Skarels 		bcopy(qd, datap, sizeof(struct qdmap));
160330391Skarels 		break;
160430391Skarels 
160530391Skarels 	    /*-------------------------------------
160630391Skarels 	    * do setup for DMA by user process	*/
160730391Skarels 
160830391Skarels 	    case QD_MAPIOBUF:
160930391Skarels 
161030391Skarels 		/*------------------------------------------------
161130391Skarels 		* set 'user write enable' bits for DMA buffer  */
161230391Skarels 
161330391Skarels 		qdflags[unit].mapped |= MAPDMA;
161430391Skarels 
161530391Skarels 		ptep = (int *) ((VTOP(DMAheader[unit]) * 4)
161630391Skarels 				+ (mfpr(SBR) | 0x80000000));
161730391Skarels 
161830391Skarels 		for (i = (DMAbuf_size >> PGSHIFT); i > 0; --i)
161930391Skarels 		    *ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V;
162030391Skarels 
162130391Skarels 		mtpr(TBIA, 0);			/* clr CPU translation buf */
162230391Skarels 
162330391Skarels 		/*-------------------------------------
162430391Skarels 		* set up QBUS map registers for DMA */
162530391Skarels 
162630391Skarels 		DMAheader[unit]->QBAreg =
162730391Skarels 				uballoc(0, DMAheader[unit], DMAbuf_size, 0);
162830391Skarels 
162930391Skarels 		if (DMAheader[unit]->QBAreg == 0)
1630*34615Smarc 		    printf("\nqd%d: qdioctl: QBA setup error", unit);
163130391Skarels 
163230391Skarels 		Qbus_unmap[unit] = DMAheader[unit]->QBAreg;
163330391Skarels 		DMAheader[unit]->QBAreg &= 0x3FFFF;
163430391Skarels 
163530391Skarels 		/*----------------------
163630391Skarels 		* return I/O buf adr */
163730391Skarels 
163830391Skarels 		*(int *)datap = (int) DMAheader[unit];
163930391Skarels 		break;
164030391Skarels 
164130391Skarels 	    /*----------------------------------------------------------------
164230391Skarels 	    * map the shared scroll param area and enable scroll interpts  */
164330391Skarels 
164430391Skarels 	    case QD_MAPSCROLL:
164530391Skarels 
164630391Skarels 		qdflags[unit].mapped |= MAPSCR;
164730391Skarels 
164830391Skarels 		ptep = (int *) ((VTOP(scroll[unit]) * 4)
164930391Skarels 				+ (mfpr(SBR) | 0x80000000));
165030391Skarels 
165130391Skarels 		/* allow user write to scroll area */
165230391Skarels 
165330391Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
165430391Skarels 
165530391Skarels 		mtpr(TBIA, 0);			/* clr CPU translation buf */
165630391Skarels 
165730391Skarels 		scroll[unit]->status = 0;
165830391Skarels 
165930391Skarels 		adder = (struct adder *) qdmap[unit].adder;
166030391Skarels 
166130391Skarels 		qdflags[unit].adder_ie |= FRAME_SYNC;
166230391Skarels 		adder->interrupt_enable = qdflags[unit].adder_ie;
166330391Skarels 
1664*34615Smarc 
166530391Skarels 		/* return scroll area address */
166630391Skarels 
166730391Skarels 		*(int *)datap = (int) scroll[unit];
166830391Skarels 		break;
166930391Skarels 
167030391Skarels 	    /*-------------------------------------------------------------
167130391Skarels 	    * unmap shared scroll param area and disable scroll intrpts */
167230391Skarels 
167330391Skarels 	    case QD_UNMAPSCROLL:
167430391Skarels 
167530391Skarels 		if (qdflags[unit].mapped & MAPSCR) {
167630391Skarels 
167730391Skarels 		    qdflags[unit].mapped &= ~MAPSCR;
167830391Skarels 
167930391Skarels 		    ptep = (int *) ((VTOP(scroll[unit]) * 4)
168030391Skarels 				    + (mfpr(SBR) | 0x80000000));
168130391Skarels 
168230391Skarels 		    /* re-protect 512 scroll param area */
168330391Skarels 
168430391Skarels 		    *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
168530391Skarels 
168630391Skarels 		    mtpr(TBIA, 0);	/* smash CPU's translation buf */
168730391Skarels 
168830391Skarels 		    adder = (struct adder *) qdmap[unit].adder;
168930391Skarels 		    qdflags[unit].adder_ie &= ~FRAME_SYNC;
169030391Skarels 		    adder->interrupt_enable = qdflags[unit].adder_ie;
169130391Skarels 		}
169230391Skarels 		break;
169330391Skarels 
169430391Skarels 	    /*-----------------------------------------------------------
169530391Skarels 	    * map shared color map write buf and turn on vsync intrpt */
169630391Skarels 
169730391Skarels 	    case QD_MAPCOLOR:
169830391Skarels 
169930391Skarels 		qdflags[unit].mapped |= MAPCOLOR;
170030391Skarels 
170130391Skarels 		ptep = (int *) ((VTOP(color_buf[unit]) * 4)
170230391Skarels 				+ (mfpr(SBR) | 0x80000000));
170330391Skarels 
170430391Skarels 		/* allow user write to color map write buffer */
170530391Skarels 
170630391Skarels 		*ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V;
170730391Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
170830391Skarels 
170930391Skarels 		mtpr(TBIA, 0);			/* clr CPU translation buf */
1710*34615Smarc 
1711*34615Smarc 		adder = (struct adder *) qdmap[unit].adder.
171230391Skarels 		qdflags[unit].adder_ie |= VSYNC;
171330391Skarels 		adder->interrupt_enable = qdflags[unit].adder_ie;
171430391Skarels 
1715*34615Smarc 		/* return color area address */
171630391Skarels 
171730391Skarels 		*(int *)datap = (int) color_buf[unit];
171830391Skarels 		break;
171930391Skarels 
172030391Skarels 	    /*--------------------------------------------------------------
172130391Skarels 	    * unmap shared color map write buffer and kill VSYNC intrpts */
172230391Skarels 
172330391Skarels 	    case QD_UNMAPCOLOR:
172430391Skarels 
172530391Skarels 		if (qdflags[unit].mapped & MAPCOLOR) {
172630391Skarels 
172730391Skarels 		    qdflags[unit].mapped &= ~MAPCOLOR;
172830391Skarels 
172930391Skarels 		    ptep = (int *) ((VTOP(color_buf[unit]) * 4)
173030391Skarels 				    + (mfpr(SBR) | 0x80000000));
173130391Skarels 
173230391Skarels 		    /* re-protect color map write buffer */
173330391Skarels 
173430391Skarels 		    *ptep++ = (*ptep & ~PG_PROT) | PG_KW | PG_V;
173530391Skarels 		    *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
173630391Skarels 
173730391Skarels 		    mtpr(TBIA, 0);	/* smash CPU's translation buf */
173830391Skarels 
173930391Skarels 		    adder = (struct adder *) qdmap[unit].adder;
174030391Skarels 
174130391Skarels 		    qdflags[unit].adder_ie &= ~VSYNC;
174230391Skarels 		    adder->interrupt_enable = qdflags[unit].adder_ie;
174330391Skarels 		}
174430391Skarels 		break;
174530391Skarels 
174630391Skarels 	    /*---------------------------------------------
174730391Skarels 	    * give user write access to the event queue */
174830391Skarels 
174930391Skarels 	    case QD_MAPEVENT:
175030391Skarels 
175130391Skarels 		qdflags[unit].mapped |= MAPEQ;
175230391Skarels 
175330391Skarels 		ptep = (int *) ((VTOP(eq_header[unit]) * 4)
175430391Skarels 				+ (mfpr(SBR) | 0x80000000));
175530391Skarels 
175630391Skarels 		/* allow user write to 1K event queue */
175730391Skarels 
175830391Skarels 		*ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V;
175930391Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
176030391Skarels 
176130391Skarels 		mtpr(TBIA, 0);			/* clr CPU translation buf */
176230391Skarels 
176330391Skarels 		/* return event queue address */
176430391Skarels 
176530391Skarels 		*(int *)datap = (int) eq_header[unit];
176630391Skarels 		break;
176730391Skarels 
176830391Skarels 	    /*-----------------------------------------------
176930391Skarels 	    * pass caller's programming commands to LK201 */
177030391Skarels 
177130391Skarels 	    case QD_PRGKBD:
177230391Skarels 
177330391Skarels 		duart = (struct duart *) qdmap[unit].duart;
177430391Skarels 		cmdbuf = (struct prgkbd *) datap;    /* pnt to kbd cmd buf */
177530391Skarels 
177630391Skarels 		/*----------------
177730391Skarels 		* send command */
177830391Skarels 
177930391Skarels 		for (i = 1000; i > 0; --i) {
178030391Skarels 		    if ((status = duart->statusA) & XMT_RDY) {
178130391Skarels 			duart->dataA = cmdbuf->cmd;
178230391Skarels 			break;
178330391Skarels 		    }
178430391Skarels 		}
178530391Skarels 
178630391Skarels 		if (i == 0) {
1787*34615Smarc 		    printf("\nqd%d: qdioctl: timeout on XMT_RDY [1]", unit);
178830391Skarels 		    break;
178930391Skarels 		}
179030391Skarels 
179130391Skarels 		/*----------------
179230391Skarels 		* send param1? */
179330391Skarels 
179430391Skarels 		if (cmdbuf->cmd & LAST_PARAM)
179530391Skarels 		    break;
179630391Skarels 
179730391Skarels 		for (i = 1000; i > 0; --i) {
179830391Skarels 		    if ((status = duart->statusA) & XMT_RDY) {
179930391Skarels 			duart->dataA = cmdbuf->param1;
180030391Skarels 			break;
180130391Skarels 		    }
180230391Skarels 		}
180330391Skarels 
180430391Skarels 		if (i == 0) {
1805*34615Smarc 		    printf("\nqd%d: qdioctl: timeout on XMT_RDY [2]", unit);
180630391Skarels 		    break;
180730391Skarels 		}
180830391Skarels 
180930391Skarels 		/*----------------
181030391Skarels 		* send param2? */
181130391Skarels 
181230391Skarels 		if (cmdbuf->param1 & LAST_PARAM)
181330391Skarels 		    break;
181430391Skarels 
181530391Skarels 		for (i = 1000; i > 0; --i) {
181630391Skarels 		    if ((status = duart->statusA) & XMT_RDY) {
181730391Skarels 			duart->dataA = cmdbuf->param2;
181830391Skarels 			break;
181930391Skarels 		    }
182030391Skarels 		}
182130391Skarels 
182230391Skarels 		if (i == 0) {
1823*34615Smarc 		    printf("\nqd%d: qdioctl: timeout on XMT_RDY [3]", unit);
182430391Skarels 		    break;
182530391Skarels 		}
182630391Skarels 
182730391Skarels 		break;
182830391Skarels 
182930391Skarels 	    /*----------------------------------------------------
183030391Skarels 	    * pass caller's programming commands to the mouse  */
183130391Skarels 
183230391Skarels 	    case QD_PRGMOUSE:
183330391Skarels 
183430391Skarels 		duart = (struct duart *) qdmap[unit].duart;
183530391Skarels 
183630391Skarels 		for (i = 1000; i > 0; --i) {
183730391Skarels 		    if ((status = duart->statusB) & XMT_RDY) {
183830391Skarels 			duart->dataB = *datap;
183930391Skarels 			break;
184030391Skarels 		    }
184130391Skarels 		}
184230391Skarels 
184330391Skarels 		if (i == 0) {
1844*34615Smarc 		    printf("\nqd%d: qdioctl: timeout on XMT_RDY [4]", unit);
184530391Skarels 		}
184630391Skarels 
184730391Skarels 		break;
184830391Skarels 
184930391Skarels 	    /*----------------------------------------------
185030391Skarels 	    * get QDSS configuration word and return it  */
185130391Skarels 
185230391Skarels 	    case QD_RDCONFIG:
185330391Skarels 
185430391Skarels 		*(short *)datap = qdflags[unit].config;
185530391Skarels 		break;
185630391Skarels 
1857*34615Smarc 	    /*--------------------------------------------------------------
1858*34615Smarc 	    * re-route kernel console messages to the alternate console  */
1859*34615Smarc 
1860*34615Smarc 	    case QD_KERN_LOOP:
1861*34615Smarc 
1862*34615Smarc 		qdflags[unit].kernel_loop = -1;
1863*34615Smarc 		break;
1864*34615Smarc 
1865*34615Smarc 	    case QD_KERN_UNLOOP:
1866*34615Smarc 
1867*34615Smarc 		qdflags[unit].kernel_loop = 0;
1868*34615Smarc 		break;
1869*34615Smarc 
187030391Skarels 	    /*----------------------
187130391Skarels 	    * program the tablet */
187230391Skarels 
187330391Skarels 	    case QD_PRGTABLET:
187430391Skarels 
187530391Skarels 		duart = (struct duart *) qdmap[unit].duart;
187630391Skarels 
187730391Skarels 		for (i = 1000; i > 0; --i) {
187830391Skarels 		    if ((status = duart->statusB) & XMT_RDY) {
187930391Skarels 			duart->dataB = *datap;
188030391Skarels 			break;
188130391Skarels 		    }
188230391Skarels 		}
188330391Skarels 
188430391Skarels 		if (i == 0) {
1885*34615Smarc 		    printf("\nqd%d: qdioctl: timeout on XMT_RDY [5]", unit);
188630391Skarels 		}
188730391Skarels 
188830391Skarels 		break;
188930391Skarels 
189030391Skarels 	    /*-----------------------------------------------
189130391Skarels 	    * program the tablet report resolution factor */
189230391Skarels 
189330391Skarels 	    case QD_PRGTABRES:
189430391Skarels 
189530391Skarels 		qdflags[unit].tab_res = *(short *)datap;
189630391Skarels 		break;
1897*34615Smarc #ifdef notdef	/* never */
1898*34615Smarc 	    case DEVIOCGET:			    /* device status */
1899*34615Smarc 		    devget = (struct devget *)datap;
1900*34615Smarc 		    bzero(devget,sizeof(struct devget));
1901*34615Smarc 		    devget->category = DEV_TERMINAL;
1902*34615Smarc 		    devget->bus = DEV_QB;
1903*34615Smarc 		    bcopy(DEV_VCB02,devget->interface,
1904*34615Smarc 			  strlen(DEV_VCB02));
1905*34615Smarc 		    bcopy(DEV_VR290,devget->device,
1906*34615Smarc 			  strlen(DEV_VR290));		    /* terminal */
1907*34615Smarc 		    devget->adpt_num = ui->ui_adpt;	    /* which adapter*/
1908*34615Smarc 		    devget->nexus_num = ui->ui_nexus;	    /* which nexus  */
1909*34615Smarc 		    devget->bus_num = ui->ui_ubanum;	    /* which QB     */
1910*34615Smarc 		    devget->ctlr_num = unit;		    /* which interf.*/
1911*34615Smarc 		    devget->slave_num = unit;		    /* which line   */
1912*34615Smarc 		    bcopy(ui->ui_driver->ud_dname,
1913*34615Smarc 			  devget->dev_name,
1914*34615Smarc 			  strlen(ui->ui_driver->ud_dname)); /* Ultrix "qd"  */
1915*34615Smarc 		    devget->unit_num = unit;		    /* qd line?     */
1916*34615Smarc 		    devget->soft_count =
1917*34615Smarc 			  sc->sc_softcnt;		    /* soft er. cnt.*/
1918*34615Smarc 		    devget->hard_count =
1919*34615Smarc 			  sc->sc_hardcnt;		    /* hard er cnt. */
1920*34615Smarc 		    devget->stat = sc->sc_flags;	    /* status	    */
1921*34615Smarc 		    devget->category_stat =
1922*34615Smarc 			  sc->sc_category_flags;	    /* cat. stat.   */
1923*34615Smarc 		    break;
1924*34615Smarc #endif /*notdef*/
192530391Skarels 
192630391Skarels 	    default:
192730391Skarels 		/*-----------------------------
192830391Skarels 		* service tty type ioctl's  */
192930391Skarels 
193030391Skarels 		    if (!(minor_dev & 0x02)) {
193130391Skarels 
193230391Skarels 			tp = &qd_tty[minor_dev];
193330391Skarels 
193430391Skarels 			error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, datap, flags);
193530391Skarels 			if (error >= 0) {
193630391Skarels 			    return(error);
193730391Skarels 			}
193830391Skarels 
193930391Skarels 			error = ttioctl(tp, cmd, datap, flags);
194030391Skarels 			if (error >= 0) {
194130391Skarels 			    return(error);
194230391Skarels 			}
194330391Skarels 		    }
194430391Skarels 		    break;
194530391Skarels 	}
194630391Skarels 
194730391Skarels /*--------------------------------
194830391Skarels * clean up and get outta here  */
194930391Skarels 
195030391Skarels 	return(0);
195130391Skarels 
195230391Skarels } /* qdioctl */
195330391Skarels 
195430391Skarels /**********************************************************************
195530391Skarels *
195630391Skarels *	qdselect()... service select call for event queue input
195730391Skarels *
195830391Skarels **********************************************************************/
195930391Skarels 
196030391Skarels qdselect(dev, rw)
196130391Skarels dev_t dev;
196230391Skarels int rw;
196330391Skarels {
196430391Skarels 	register int s;
196530391Skarels 	register int unit;
1966*34615Smarc 	register struct tty *tp;
1967*34615Smarc 	u_int minor_dev = minor(dev);
196830391Skarels 
1969*34615Smarc 	s = spl5();
1970*34615Smarc 	unit = minor_dev >> 2;
197130391Skarels 
197230391Skarels 	switch (rw) {
197330391Skarels 
1974*34615Smarc 	    case FREAD:
197530391Skarels 
1976*34615Smarc 		if ((minor_dev & 0x03) == 2)
1977*34615Smarc 		{
1978*34615Smarc 		    /*
1979*34615Smarc 		     * this is a graphics device, so check for events
1980*34615Smarc 		     */
1981*34615Smarc 		    if(!(ISEMPTY(eq_header[unit])))
1982*34615Smarc 		    {
1983*34615Smarc 		        splx(s);
1984*34615Smarc 		        return(1);
1985*34615Smarc 		    }
1986*34615Smarc 		    rsel[unit] = u.u_procp;
1987*34615Smarc 		    qdflags[unit].selmask |= SEL_READ;
198830391Skarels 		    splx(s);
1989*34615Smarc 		    return(0);
199030391Skarels 		}
1991*34615Smarc 		else
1992*34615Smarc 		{
1993*34615Smarc 		    /*
1994*34615Smarc 		     * this is a tty device
1995*34615Smarc 		     */
1996*34615Smarc 	    	    tp = &qd_tty[minor_dev];
1997*34615Smarc 		    if (ttnread(tp))
1998*34615Smarc 			return(1);
1999*34615Smarc 		    tp->t_rsel = u.u_procp;
2000*34615Smarc 		    splx(s);
2001*34615Smarc 		    return(0);
2002*34615Smarc 		}
200330391Skarels 
2004*34615Smarc 	    case FWRITE:
200530391Skarels 
2006*34615Smarc 		if ((minor(dev) & 0x03) == 2)
2007*34615Smarc 		{
2008*34615Smarc 		    /*
2009*34615Smarc 		     * this is a graphics device, so check for dma buffers
2010*34615Smarc 		     */
2011*34615Smarc 		    if (DMA_ISEMPTY(DMAheader[unit]))
2012*34615Smarc 		    {
2013*34615Smarc 		        splx(s);
2014*34615Smarc 		        return(1);
2015*34615Smarc 		    }
2016*34615Smarc 		    rsel[unit] = u.u_procp;
2017*34615Smarc 		    qdflags[unit].selmask |= SEL_WRITE;
201830391Skarels 		    splx(s);
2019*34615Smarc 		    return(0);
202030391Skarels 		}
2021*34615Smarc 		else
2022*34615Smarc 		{
2023*34615Smarc 		    /*
2024*34615Smarc 		     * this is a tty device
2025*34615Smarc 		     */
2026*34615Smarc 	    	    tp = &qd_tty[minor_dev];
2027*34615Smarc 		    if (tp->t_outq.c_cc <= TTLOWAT(tp))
2028*34615Smarc 			return(1);
2029*34615Smarc 		    tp->t_wsel = u.u_procp;
2030*34615Smarc 		    splx(s);
2031*34615Smarc 		    return(0);
2032*34615Smarc 		}
203330391Skarels 	}
203430391Skarels 
203530391Skarels } /* qdselect() */
203630391Skarels 
203730391Skarels /***************************************************************
203830391Skarels *
203930391Skarels *	qdwrite()... output to the QDSS screen as a TTY
204030391Skarels *
204130391Skarels ***************************************************************/
204230391Skarels 
204330391Skarels extern qd_strategy();
204430391Skarels 
204530391Skarels qdwrite(dev, uio)
204630391Skarels dev_t dev;
204730391Skarels struct uio *uio;
204830391Skarels {
204930391Skarels 	register struct tty *tp;
205030391Skarels 	register int minor_dev;
205130391Skarels 	register int unit;
205230391Skarels 
205330391Skarels 	minor_dev = minor(dev);
205430391Skarels 	unit = (minor_dev >> 2) & 0x07;
205530391Skarels 
205630391Skarels 	/*------------------------------
205730391Skarels 	* if this is the console...  */
205830391Skarels 
205930391Skarels 	if ((minor_dev & 0x03) != 0x02	&&
206030391Skarels 	     qdflags[unit].inuse & CONS_DEV) {
206130391Skarels 	    tp = &qd_tty[minor_dev];
206230391Skarels 	    return ((*linesw[tp->t_line].l_write)(tp, uio));
206330391Skarels 	}
206430391Skarels 
206530391Skarels 	/*------------------------------------------------
206630391Skarels 	* else this must be a DMA xfer from user space */
206730391Skarels 
206830391Skarels 	else if (qdflags[unit].inuse & GRAPHIC_DEV) {
206930391Skarels 	    return (physio(qd_strategy, &qdbuf[unit],
207030391Skarels 			   dev, B_WRITE, minphys, uio));
207130391Skarels 	}
207230391Skarels }
207330391Skarels 
207430391Skarels /***************************************************************
207530391Skarels *
207630391Skarels *	qdread()... read from QDSS keyboard as a TTY
207730391Skarels *
207830391Skarels ***************************************************************/
207930391Skarels 
208030391Skarels qdread(dev, uio)
208130391Skarels dev_t dev;
208230391Skarels struct uio *uio;
208330391Skarels {
208430391Skarels 	register struct tty *tp;
208530391Skarels 	register int minor_dev;
208630391Skarels 	register int unit;
208730391Skarels 
208830391Skarels 	minor_dev = minor(dev);
208930391Skarels 	unit = (minor_dev >> 2) & 0x07;
209030391Skarels 
209130391Skarels 	/*------------------------------
209230391Skarels 	* if this is the console...  */
209330391Skarels 
209430391Skarels 	if ((minor_dev & 0x03) != 0x02	&&
209530391Skarels 	     qdflags[unit].inuse & CONS_DEV) {
209630391Skarels 	    tp = &qd_tty[minor_dev];
209730391Skarels 	    return ((*linesw[tp->t_line].l_read)(tp, uio));
209830391Skarels 	}
209930391Skarels 
210030391Skarels 	/*------------------------------------------------
210130391Skarels 	* else this must be a bitmap-to-processor xfer */
210230391Skarels 
210330391Skarels 	else if (qdflags[unit].inuse & GRAPHIC_DEV) {
210430391Skarels 	    return (physio(qd_strategy, &qdbuf[unit],
210530391Skarels 			   dev, B_READ, minphys, uio));
210630391Skarels 	}
210730391Skarels }
210830391Skarels 
210930391Skarels /***************************************************************
211030391Skarels *
211130391Skarels *	qd_strategy()... strategy routine to do DMA
211230391Skarels *
211330391Skarels ***************************************************************/
211430391Skarels 
211530391Skarels qd_strategy(bp)
211630391Skarels register struct buf *bp;
211730391Skarels {
211830391Skarels 	register struct dga *dga;
211930391Skarels 	register struct adder *adder;
212030391Skarels 
212130391Skarels 	char *DMAbufp;
212230391Skarels 
212330391Skarels 	int QBAreg;
212430391Skarels 	int bytcnt;
212530391Skarels 	int s;
212630391Skarels 	int unit;
212730391Skarels 	int cookie;
212830391Skarels 
212930391Skarels 	int i,j,k;
213030391Skarels 
213130391Skarels 	unit = (minor(bp->b_dev) >> 2) & 0x07;
213230391Skarels 
2133*34615Smarc /*-----------------
2134*34615Smarc * init pointers */
213530391Skarels 
213630391Skarels 	if ((QBAreg = ubasetup(0, bp, 0)) == 0) {
2137*34615Smarc 	    printf("\nqd%d: qd_strategy: QBA setup error", unit);
213830391Skarels 	    goto STRAT_ERR;
213930391Skarels 	}
214030391Skarels 
214130391Skarels 	dga = (struct dga *) qdmap[unit].dga;
214230391Skarels 
2143*34615Smarc 	s = spl5();
214430391Skarels 
214530391Skarels 	qdflags[unit].user_dma = -1;
214630391Skarels 
214730391Skarels 	dga->csr |= DMA_IE;
214830391Skarels 
214930391Skarels 	cookie = QBAreg & 0x3FFFF;
215030391Skarels 	dga->adrs_lo = (short) cookie;
215130391Skarels 	dga->adrs_hi = (short) (cookie >> 16);
215230391Skarels 
215330391Skarels 	dga->bytcnt_lo = (short) bp->b_bcount;
215430391Skarels 	dga->bytcnt_hi = (short) (bp->b_bcount >> 16);
215530391Skarels 
215630391Skarels 	while (qdflags[unit].user_dma) {
215730391Skarels 	    sleep((caddr_t)&qdflags[unit].user_dma, QDPRIOR);
215830391Skarels 	}
215930391Skarels 
216030391Skarels 	splx(s);
216130391Skarels 	ubarelse(0, &QBAreg);
216230391Skarels 
216330391Skarels 	if (!(dga->csr & DMA_ERR)) {
216430391Skarels 	    iodone(bp);
216530391Skarels 	    return;
216630391Skarels 	}
216730391Skarels 
216830391Skarels STRAT_ERR:
216930391Skarels 	adder = (struct adder *) qdmap[unit].adder;
217030391Skarels 	adder->command = CANCEL;		/* cancel adder activity */
217130391Skarels 	dga->csr &= ~DMA_IE;
217230391Skarels 	dga->csr &= ~0x0600;		/* halt DMA (reset fifo) */
217330391Skarels 	dga->csr |= DMA_ERR;		/* clear error condition */
217430391Skarels 	bp->b_flags |= B_ERROR; 	/* flag an error to physio() */
217530391Skarels 
217630391Skarels 	/* if DMA was running, flush spurious intrpt */
217730391Skarels 
217830391Skarels 	if (dga->bytcnt_lo != 0) {
217930391Skarels 	    dga->bytcnt_lo = 0;
218030391Skarels 	    dga->bytcnt_hi = 0;
218130391Skarels 	    DMA_SETIGNORE(DMAheader[unit]);
218230391Skarels 	    dga->csr |= DMA_IE;
218330391Skarels 	}
218430391Skarels 
218530391Skarels 	iodone(bp);
218630391Skarels 
218730391Skarels } /* qd_strategy */
218830391Skarels 
218930391Skarels /*******************************************************************
219030391Skarels *
219130391Skarels *	qdstart()... startup output to the console screen
219230391Skarels *
219330391Skarels ********************************************************************
219430391Skarels *
219530391Skarels *	calling convention:
219630391Skarels *
219730391Skarels *		qdstart(tp);
2198*34615Smarc *		struct tty *tp; 	;pointer to tty structure
219930391Skarels *
220030391Skarels ********/
220130391Skarels 
220230391Skarels qdstart(tp)
220330391Skarels register struct tty *tp;
220430391Skarels {
220530391Skarels 	register int which_unit, unit, c;
2206*34615Smarc 	register struct tty *tp0;
220730391Skarels 	int s;
220830391Skarels 
2209*34615Smarc 	int curs_on;
2210*34615Smarc 	struct dga *dga;
2211*34615Smarc 
221230391Skarels 	unit = minor(tp->t_dev);
2213*34615Smarc 
2214*34615Smarc 	tp0 = &qd_tty[(unit & 0x0FC)+1];
221530391Skarels 	which_unit = (unit >> 2) & 0x3;
2216*34615Smarc 	unit &= 0x03;
221730391Skarels 
2218*34615Smarc 	s = spl5();
2219*34615Smarc 
2220*34615Smarc /*------------------------------------------------------------------
2221*34615Smarc * If it's currently active, or delaying, no need to do anything. */
2222*34615Smarc 
222330391Skarels 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
222430391Skarels 		goto out;
222530391Skarels 
2226*34615Smarc /*-------------------------------------------------------------------
2227*34615Smarc * Display chars until the queue is empty, if the alternate console device
2228*34615Smarc * is open direct chars there.  Drop input from anything but the console
2229*34615Smarc * device on the floor.	*/
2230*34615Smarc /* TANDEM is set on the second subchannel for flow control. */
2231*34615Smarc 
2232*34615Smarc 	while ( tp->t_outq.c_cc ) {
223334511Smarc 		c = getc(&tp->t_outq);
2234*34615Smarc 		if (unit == 0)
2235*34615Smarc 		    blitc(which_unit, (char)(c & 0xFF));
2236*34615Smarc #ifdef notdef	/* never never never */
2237*34615Smarc 	    if (unit == 0) {		/* console device */
2238*34615Smarc 		if (tp0->t_state & TS_ISOPEN) {
2239*34615Smarc 		    if (tp0->t_state & TS_TBLOCK)
2240*34615Smarc 			goto out;
2241*34615Smarc 		    c = getc(&tp->t_outq);
2242*34615Smarc 		    (*linesw[tp0->t_line].l_rint)(c, tp0);
2243*34615Smarc 		} else {
2244*34615Smarc 		    c = getc(&tp->t_outq);
2245*34615Smarc 		    blitc(which_unit, (char)(c & 0xFF));
2246*34615Smarc 		}
2247*34615Smarc 	    } else if (unit == 1) {	/* qconsole, do flow control */
2248*34615Smarc 		    c = getc(&tp->t_outq);
2249*34615Smarc 		    if ((tp0->t_state&TS_TBLOCK) == 0) {
2250*34615Smarc 			tp = &qd_tty[0];
2251*34615Smarc 			unit = minor(tp->t_dev);
2252*34615Smarc 			unit &= 0x03;
2253*34615Smarc 			continue;
2254*34615Smarc 		    } else
2255*34615Smarc 			goto out;
2256*34615Smarc 	    } else
2257*34615Smarc 		c = getc(&tp->t_outq);
2258*34615Smarc #endif
225930391Skarels 	}
2260*34615Smarc 
2261*34615Smarc /*--------------------------------------------------------
2262*34615Smarc * If there are sleepers, and output has drained below low
2263*34615Smarc * water mark, wake up the sleepers. */
2264*34615Smarc 
2265*34615Smarc 	if ( tp->t_outq.c_cc <= TTLOWAT(tp) ) {
2266*34615Smarc 		if (tp->t_state & TS_ASLEEP){
2267*34615Smarc 			tp->t_state &= ~TS_ASLEEP;
2268*34615Smarc 			wakeup((caddr_t) &tp->t_outq);
2269*34615Smarc 		}
227030391Skarels 	}
227130391Skarels 
2272*34615Smarc 	tp->t_state &= ~TS_BUSY;
2273*34615Smarc 
227430391Skarels out:
227530391Skarels 	splx(s);
227630391Skarels 
227730391Skarels } /* qdstart */
227830391Skarels 
227930391Skarels 
228030391Skarels /*******************************************************************
228130391Skarels *
228230391Skarels *	qdstop()... stop the tty
228330391Skarels *
228430391Skarels *******************************************************************/
228530391Skarels 
228630391Skarels qdstop(tp, flag)
228730391Skarels register struct tty *tp;
228830391Skarels int flag;
228930391Skarels {
229030391Skarels 	register int s;
229130391Skarels 
2292*34615Smarc 	s = spl5();	/* block intrpts during state modification */
2293*34615Smarc 
229430391Skarels 	if (tp->t_state & TS_BUSY) {
229530391Skarels 	    if ((tp->t_state & TS_TTSTOP) == 0) {
229630391Skarels 		tp->t_state |= TS_FLUSH;
229730391Skarels 	    } else
229830391Skarels 		tp->t_state &= ~TS_BUSY;
229930391Skarels 	}
230030391Skarels 	splx(s);
230130391Skarels }
230230391Skarels 
230330391Skarels /*******************************************************************
230430391Skarels *
230530391Skarels *	blitc()... output a character to the QDSS screen
230630391Skarels *
230730391Skarels ********************************************************************
230830391Skarels *
230930391Skarels *	calling convention:
231030391Skarels *
231130391Skarels *		blitc(chr);
231230391Skarels *		char chr;		;character to be displayed
231330391Skarels *
231430391Skarels ********/
231530391Skarels 
231630391Skarels blitc(unit, chr)
231730391Skarels int unit;
2318*34615Smarc unsigned char chr;
231930391Skarels {
232030391Skarels 	register struct adder *adder;
232130391Skarels 	register struct dga *dga;
232230391Skarels 	register int i;
232330391Skarels 
232430391Skarels 	short x;
2325*34615Smarc 	unsigned char savechar;
232630391Skarels 
2327*34615Smarc /*---------------
2328*34615Smarc * init stuff  */
232930391Skarels 
233030391Skarels 	adder = (struct adder *) qdmap[unit].adder;
233130391Skarels 	dga = (struct dga *) qdmap[unit].dga;
233230391Skarels 
2333*34615Smarc /*---------------------------
2334*34615Smarc * non display character?  */
233530391Skarels 
2336*34615Smarc 	chr &= 0xFF;
233732012Smarc 
233830391Skarels 	switch (chr) {
233930391Skarels 
234030391Skarels 	    case '\r':			/* return char */
234130391Skarels 		cursor[unit].x = 0;
2342*34615Smarc 	        if (!(qdflags[unit].inuse & GRAPHIC_DEV))
2343*34615Smarc 		    dga->x_cursor = TRANX(cursor[unit].x);
234430391Skarels 		return(0);
234530391Skarels 
234630391Skarels 	    case '\t':			/* tab char */
234730391Skarels 
234830391Skarels 		for (i = 8 - ((cursor[unit].x >> 3) & 0x07); i > 0; --i) {
234930391Skarels 		    blitc(unit, ' ');
235030391Skarels 		}
235130391Skarels 		return(0);
235230391Skarels 
235330391Skarels 	    case '\n':			/* line feed char */
235430391Skarels 
235530391Skarels 		if ((cursor[unit].y += CHAR_HEIGHT) > (863 - CHAR_HEIGHT)) {
235630391Skarels 		    if (qdflags[unit].inuse & GRAPHIC_DEV) {
235730391Skarels 			cursor[unit].y = 0;
235830391Skarels 		    } else {
235930391Skarels 			cursor[unit].y -= CHAR_HEIGHT;
236030391Skarels 			scroll_up(adder);
236130391Skarels 		    }
236230391Skarels 		}
2363*34615Smarc 	        if (!(qdflags[unit].inuse & GRAPHIC_DEV))
2364*34615Smarc 		    dga->y_cursor = TRANY(cursor[unit].y);
236530391Skarels 		return(0);
236630391Skarels 
236730391Skarels 	    case '\b':			/* backspace char */
236830391Skarels 		if (cursor[unit].x > 0) {
236930391Skarels 		    cursor[unit].x -= CHAR_WIDTH;
2370*34615Smarc 		    blitc(unit, ' ');
2371*34615Smarc 		    cursor[unit].x -= CHAR_WIDTH;
2372*34615Smarc 	            if (!(qdflags[unit].inuse & GRAPHIC_DEV))
2373*34615Smarc 		        dga->x_cursor = TRANX(cursor[unit].x);
237430391Skarels 		}
237530391Skarels 		return(0);
237630391Skarels 
2377*34615Smarc 	    default:
2378*34615Smarc 		/*----------------------------------------------------------
2379*34615Smarc 		 * Weed out unprintable characters.  Printable characters fall
2380*34615Smarc 		 * between space (0x20) and tilde (0x7E).  For 8-bit support
2381*34615Smarc 		 * another range of printable characters are those between
2382*34615Smarc 		 * 0xA1 and 0xFD. */
238332012Smarc 
2384*34615Smarc 		if ((chr < ' ') || (chr > 0xFD) || (chr < 0xA1 && chr > '~'))
238530391Skarels 		    return(0);
238630391Skarels 	}
238730391Skarels 
2388*34615Smarc /*------------------------------------------
2389*34615Smarc * setup VIPER operand control registers  */
239030391Skarels 
239130391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0001);  /* select plane #0 */
239230391Skarels 	write_ID(adder, SRC1_OCR_B,
239330391Skarels 			EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY);
239430391Skarels 
239530391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x00FE);  /* select other planes */
239630391Skarels 	write_ID(adder, SRC1_OCR_B,
239730391Skarels 			EXT_SOURCE | INT_NONE | NO_ID | BAR_SHIFT_DELAY);
239830391Skarels 
239930391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x00FF);  /* select all planes */
240030391Skarels 	write_ID(adder, DST_OCR_B,
240130391Skarels 			EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
240230391Skarels 
240330391Skarels 	write_ID(adder, MASK_1, 0xFFFF);
240430391Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 1);
240530391Skarels 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
240630391Skarels 
2407*34615Smarc         adder->x_clip_min = 0;
2408*34615Smarc         adder->x_clip_max = 1024;
2409*34615Smarc         adder->y_clip_min = 0;
2410*34615Smarc         adder->y_clip_max = 864;
241130391Skarels 
2412*34615Smarc /*----------------------------------------
2413*34615Smarc * load DESTINATION origin and vectors  */
2414*34615Smarc 
241530391Skarels 	adder->fast_dest_dy = 0;
241630391Skarels 	adder->slow_dest_dx = 0;
241730391Skarels 	adder->error_1 = 0;
241830391Skarels 	adder->error_2 = 0;
241930391Skarels 
242030391Skarels 	adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL;
242130391Skarels 
242230391Skarels 	wait_status(adder, RASTEROP_COMPLETE);
242330391Skarels 
242430391Skarels 	adder->destination_x = cursor[unit].x;
242530391Skarels 	adder->fast_dest_dx = CHAR_WIDTH;
242630391Skarels 
242730391Skarels 	adder->destination_y = cursor[unit].y;
242830391Skarels 	adder->slow_dest_dy = CHAR_HEIGHT;
242930391Skarels 
2430*34615Smarc /*-----------------------------------
2431*34615Smarc * load SOURCE origin and vectors  */
243230391Skarels 
2433*34615Smarc 	if (chr > '~') {
2434*34615Smarc 		savechar = chr;
2435*34615Smarc 		chr -= 34; /* These are to skip the (32) 8-bit control chars.
2436*34615Smarc 			      as well as DEL and 0xA0 which aren't printable */
2437*34615Smarc 	}
2438*34615Smarc 	if ((chr - ' ') > (CHARS - 1))  {
2439*34615Smarc 		printf("Invalid character (x)%x in blitc\n",chr);
2440*34615Smarc 		chr = ' ';
2441*34615Smarc 	}
2442*34615Smarc 	/* X position is modulo the number of characters per line */
2443*34615Smarc 	adder->source_1_x = FONT_X +
2444*34615Smarc 		(((chr - ' ') % (MAX_SCREEN_X/CHAR_WIDTH)) * CHAR_WIDTH);
2445*34615Smarc 	/* Point to either first or second row */
2446*34615Smarc 	adder->source_1_y = 2048 - 15 *
2447*34615Smarc 		(((chr - ' ')/(MAX_SCREEN_X/CHAR_WIDTH)) + 1);
244830391Skarels 
244930391Skarels 	adder->source_1_dx = CHAR_WIDTH;
245030391Skarels 	adder->source_1_dy = CHAR_HEIGHT;
245130391Skarels 
245230391Skarels 	write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
245330391Skarels 	adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE;
245430391Skarels 
2455*34615Smarc /*-------------------------------------
2456*34615Smarc * update console cursor coordinates */
245730391Skarels 
245830391Skarels 	cursor[unit].x += CHAR_WIDTH;
2459*34615Smarc 	if (!(qdflags[unit].inuse & GRAPHIC_DEV))
2460*34615Smarc 	    dga->x_cursor = TRANX(cursor[unit].x);
246130391Skarels 
246230391Skarels 	if (cursor[unit].x > (1024 - CHAR_WIDTH)) {
246330391Skarels 	    blitc(unit, '\r');
246430391Skarels 	    blitc(unit, '\n');
246530391Skarels 	}
246630391Skarels 
246730391Skarels } /* blitc */
246830391Skarels 
246930391Skarels qdreset(){}
247030391Skarels qd_init(){}
247130391Skarels 
247230391Skarels /******************************************************************
2473*34615Smarc *******************************************************************
2474*34615Smarc *******************************************************************
247530391Skarels *
247630391Skarels *	INTERRUPT SERVICE ROUTINES START HERE:
247730391Skarels *
2478*34615Smarc *******************************************************************
2479*34615Smarc *******************************************************************
248030391Skarels ******************************************************************/
248130391Skarels 
248230391Skarels /*****************************************************************
248330391Skarels *
248430391Skarels *	qddint()... service "DMA DONE" interrupt condition
248530391Skarels *
248630391Skarels *****************************************************************/
248730391Skarels 
248830391Skarels qddint(qd)
248930391Skarels int qd;
249030391Skarels {
249130391Skarels 	register struct DMAreq_header *header;
249230391Skarels 	register struct DMAreq *request;
249330391Skarels 	register struct dga *dga;
249430391Skarels 	struct adder *adder;
249530391Skarels 
249630391Skarels 	int cookie;			/* DMA adrs for QDSS */
249730391Skarels 	int i;
249830391Skarels 
249930391Skarels 	spl4(); 			/* allow interval timer in */
250030391Skarels 
2501*34615Smarc /*-----------------
2502*34615Smarc * init pointers */
250330391Skarels 
250430391Skarels 	header = DMAheader[qd]; 	    /* register for optimization */
250530391Skarels 	dga = (struct dga *) qdmap[qd].dga;
250630391Skarels 	adder = (struct adder *) qdmap[qd].adder;
250730391Skarels 
2508*34615Smarc /*------------------------------------------------------------------------
2509*34615Smarc * if this interrupt flagged as bogus for interrupt flushing purposes.. */
251030391Skarels 
251130391Skarels 	if (DMA_ISIGNORE(header)) {
251230391Skarels 	    DMA_CLRIGNORE(header);
251330391Skarels 	    return;
251430391Skarels 	}
251530391Skarels 
251630391Skarels /*----------------------------------------------------
251730391Skarels * dump a DMA hardware error message if appropriate */
251830391Skarels 
251930391Skarels 	if (dga->csr & DMA_ERR) {
252030391Skarels 
252130391Skarels 	    if (dga->csr & PARITY_ERR)
2522*34615Smarc 		printf("\nqd%d: qddint: DMA hardware parity fault.", qd);
252330391Skarels 
252430391Skarels 	    if (dga->csr & BUS_ERR)
2525*34615Smarc 		printf("\nqd%d: qddint: DMA hardware bus error.", qd);
252630391Skarels 	}
252730391Skarels 
252830391Skarels /*----------------------------------------
252930391Skarels * if this was a DMA from user space... */
253030391Skarels 
253130391Skarels 	if (qdflags[qd].user_dma) {
253230391Skarels 	    qdflags[qd].user_dma = 0;
253330391Skarels 	    wakeup((caddr_t)&qdflags[qd].user_dma);
253430391Skarels 	    return;
253530391Skarels 	}
253630391Skarels 
253730391Skarels /*------------------------------------------------------------------------
253830391Skarels * if we're doing DMA request queue services, field the error condition */
253930391Skarels 
254030391Skarels 	if (dga->csr & DMA_ERR) {
254130391Skarels 
254230391Skarels 	    dga->csr &= ~0x0600;		/* halt DMA (reset fifo) */
254330391Skarels 	    dga->csr |= DMA_ERR;		/* clear error condition */
254430391Skarels 	    adder->command = CANCEL;		/* cancel adder activity */
254530391Skarels 
254630391Skarels 	    DMA_SETERROR(header);	/* flag error in header status word */
254730391Skarels 	    DMA_CLRACTIVE(header);
254830391Skarels 	    header->DMAreq[header->oldest].DMAdone |= HARD_ERROR;
254930391Skarels 	    header->newest = header->oldest;
255030391Skarels 	    header->used = 0;
255130391Skarels 
255230391Skarels 	    if (rsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
255330391Skarels 		selwakeup(rsel[qd], 0);
255430391Skarels 		rsel[qd] = 0;
255530391Skarels 		qdflags[qd].selmask &= ~SEL_WRITE;
255630391Skarels 	    }
255730391Skarels 
255830391Skarels 	    if (dga->bytcnt_lo != 0) {
255930391Skarels 		dga->bytcnt_lo = 0;
256030391Skarels 		dga->bytcnt_hi = 0;
256130391Skarels 		DMA_SETIGNORE(header);
256230391Skarels 	    }
256330391Skarels 
256430391Skarels 	    return;
256530391Skarels 	}
256630391Skarels 
256730391Skarels /*----------------------------------------------------------------------------
256830391Skarels * if the DMA request queue is now becoming non-full, wakeup "select" client */
256930391Skarels 
257030391Skarels 	if (DMA_ISFULL(header)) {
257130391Skarels 
257230391Skarels 	    if (rsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
257330391Skarels 		selwakeup(rsel[qd], 0);
257430391Skarels 		rsel[qd] = 0;
257530391Skarels 		qdflags[qd].selmask &= ~SEL_WRITE;
257630391Skarels 	    }
257730391Skarels 	}
257830391Skarels 
257930391Skarels 	header->DMAreq[header->oldest].DMAdone |= REQUEST_DONE;
2580*34615Smarc         QDlast_DMAtype = header->DMAreq[header->oldest].DMAtype;
258130391Skarels 
2582*34615Smarc 	/* check for unexpected interrupt */
2583*34615Smarc 	if (DMA_ISEMPTY(header))
258430391Skarels 	    return;
258530391Skarels 
258630391Skarels 	DMA_GETEND(header);	/* update request queue indices */
258730391Skarels 
258830391Skarels /*------------------------------------------------------------
258930391Skarels * if no more DMA pending, wake up "select" client and exit */
259030391Skarels 
259130391Skarels 	if (DMA_ISEMPTY(header)) {
259230391Skarels 
259330391Skarels 	    if (rsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
259430391Skarels 		selwakeup(rsel[qd], 0);
259530391Skarels 		rsel[qd] = 0;
259630391Skarels 		qdflags[qd].selmask &= ~SEL_WRITE;
259730391Skarels 	    }
259830391Skarels 
259930391Skarels 	    DMA_CLRACTIVE(header);  /* flag DMA done */
260030391Skarels 	    return;
260130391Skarels 	}
260230391Skarels 
260330391Skarels /*---------------------------
260430391Skarels * initiate next DMA xfer  */
260530391Skarels 
260630391Skarels 	request = DMA_GETBEGIN(header);
2607*34615Smarc 	if (request->DMAtype != QDlast_DMAtype) {
2608*34615Smarc 	    	dga->csr &= ~0x0600;	  /* halt DMA (reset fifo) */
2609*34615Smarc 	    	adder->command = CANCEL;  /* cancel adder activity */
2610*34615Smarc 	}
261130391Skarels 
2612*34615Smarc 
261330391Skarels 	switch (request->DMAtype) {
261430391Skarels 
261530391Skarels 	    case DISPLIST:
2616*34615Smarc 		if (request->DMAtype != QDlast_DMAtype) {
2617*34615Smarc 			dga->csr |= DL_ENB;
2618*34615Smarc 			dga->csr &= ~(BTOP_ENB | BYTE_DMA);
2619*34615Smarc 		}
262030391Skarels 		break;
262130391Skarels 
262230391Skarels 	    case PTOB:
2623*34615Smarc 		if (request->DMAtype != QDlast_DMAtype) {
2624*34615Smarc 			if (request->DMAdone & BYTE_PACK)
2625*34615Smarc 				dga->csr |= (PTOB_ENB | BYTE_DMA);
2626*34615Smarc 			else {
2627*34615Smarc 				dga->csr |= PTOB_ENB;
2628*34615Smarc 				dga->csr &= ~BYTE_DMA;
2629*34615Smarc 			}
2630*34615Smarc 		}
263130391Skarels 		break;
263230391Skarels 
263330391Skarels 	    case BTOP:
2634*34615Smarc 		if (request->DMAtype != QDlast_DMAtype) {
2635*34615Smarc 			if (request->DMAdone & BYTE_PACK) {
2636*34615Smarc 				dga->csr &= ~DL_ENB;
2637*34615Smarc 				dga->csr |= (BTOP_ENB | BYTE_DMA);
2638*34615Smarc 			}
2639*34615Smarc 			else {
2640*34615Smarc 				dga->csr |= BTOP_ENB;
2641*34615Smarc 				dga->csr &= ~(BYTE_DMA | DL_ENB);
2642*34615Smarc 			}
2643*34615Smarc 		}
264430391Skarels 		break;
264530391Skarels 	    default:
2646*34615Smarc 		printf("\nqd%d: qddint: illegal DMAtype parameter.", qd);
264730391Skarels 		DMA_CLRACTIVE(header);	/* flag DMA done */
264830391Skarels 		return;
264930391Skarels 	}
265030391Skarels 
265130391Skarels 	if (request->DMAdone & COUNT_ZERO) {
265230391Skarels 	    dga->csr &= ~SET_DONE_FIFO;
265330391Skarels 	} else if (request->DMAdone & FIFO_EMPTY) {
265430391Skarels 	    dga->csr |= SET_DONE_FIFO;
265530391Skarels 	}
265630391Skarels 
265730391Skarels 	if (request->DMAdone & WORD_PACK)
265830391Skarels 	    dga->csr &= ~BYTE_DMA;
265930391Skarels 	else if (request->DMAdone & BYTE_PACK)
266030391Skarels 	    dga->csr |= BYTE_DMA;
266130391Skarels 
266230391Skarels 	dga->csr |= DMA_IE;
2663*34615Smarc         QDlast_DMAtype = request->DMAtype;
266430391Skarels 
266530391Skarels 	cookie = ((int)request->bufp - (int)header) + (int)header->QBAreg;
266630391Skarels 
266730391Skarels 	dga->adrs_lo = (short) cookie;
266830391Skarels 	dga->adrs_hi = (short) (cookie >> 16);
266930391Skarels 
267030391Skarels 	dga->bytcnt_lo = (short) request->length;
267130391Skarels 	dga->bytcnt_hi = (short) (request->length >> 16);
267230391Skarels 
267330391Skarels 	return;
267430391Skarels }
267530391Skarels 
267630391Skarels /*****************************************************************
267730391Skarels *
267830391Skarels *	qdaint()... ADDER interrupt service
267930391Skarels *
268030391Skarels *****************************************************************/
2681*34615Smarc int Nqdaint;
268230391Skarels 
268330391Skarels qdaint(qd)
268430391Skarels register int qd;
268530391Skarels {
268630391Skarels 	register struct adder *adder;
268730391Skarels 	struct color_buf *cbuf;
268830391Skarels 
268930391Skarels 	short stat;
269030391Skarels 	int i;
269130391Skarels 	register struct rgb *rgbp;
269230391Skarels 	register short *red;
269330391Skarels 	register short *green;
269430391Skarels 	register short *blue;
269530391Skarels 
269630391Skarels 	spl4(); 			/* allow interval timer in */
2697*34615Smarc 	Nqdaint++;			/* debug */
269830391Skarels 
269930391Skarels 	adder = (struct adder *) qdmap[qd].adder;
270030391Skarels 
270130391Skarels /*------------------------------------------------------------------------
270230391Skarels * service the vertical blank interrupt (VSYNC bit) by loading any pending
270330391Skarels * color map load request  */
270430391Skarels 
270530391Skarels 	if (adder->status & VSYNC) {
270630391Skarels 	    adder->status &= ~VSYNC;		/* clear the interrupt */
270730391Skarels 
270830391Skarels 	    cbuf = color_buf[qd];
270930391Skarels 	    if (cbuf->status & LOAD_COLOR_MAP) {
271030391Skarels 
271130391Skarels 		red = (short *) qdmap[qd].red;
271230391Skarels 		green = (short *) qdmap[qd].green;
271330391Skarels 		blue = (short *) qdmap[qd].blue;
271430391Skarels 
271530391Skarels 		for (i = cbuf->count, rgbp = cbuf->rgb; --i >= 0; rgbp++) {
271630391Skarels 
271730391Skarels 		    red[rgbp->offset] = (short) rgbp->red;
271830391Skarels 		    green[rgbp->offset] = (short) rgbp->green;
271930391Skarels 		    blue[rgbp->offset] = (short) rgbp->blue;
272030391Skarels 		}
272130391Skarels 
272230391Skarels 		cbuf->status &= ~LOAD_COLOR_MAP;
272330391Skarels 	    }
272430391Skarels 	}
272530391Skarels 
272630391Skarels /*-------------------------------------------------
272730391Skarels * service the scroll interrupt (FRAME_SYNC bit) */
272830391Skarels 
272930391Skarels 	if (adder->status & FRAME_SYNC) {
273030391Skarels 	    adder->status &= ~FRAME_SYNC;	/* clear the interrupt */
273130391Skarels 
273230391Skarels 	    if (scroll[qd]->status & LOAD_REGS) {
273330391Skarels 
273430391Skarels 		for ( i = 1000, adder->status = 0
273530391Skarels 		    ; i > 0  &&  !((stat = adder->status) & ID_SCROLL_READY)
273630391Skarels 		    ; --i);
273730391Skarels 
273830391Skarels 		if (i == 0) {
2739*34615Smarc 		    printf("\nqd%d: qdaint: timeout on ID_SCROLL_READY", qd);
274030391Skarels 		    return;
274130391Skarels 		}
274230391Skarels 
274330391Skarels 		adder->ID_scroll_data = scroll[qd]->viper_constant;
274430391Skarels 		adder->ID_scroll_command = ID_LOAD | SCROLL_CONSTANT;
274530391Skarels 
274630391Skarels 		adder->y_scroll_constant = scroll[qd]->y_scroll_constant;
274730391Skarels 		adder->y_offset_pending = scroll[qd]->y_offset;
274830391Skarels 
274930391Skarels 		if (scroll[qd]->status & LOAD_INDEX) {
275030391Skarels 
275130391Skarels 		    adder->x_index_pending = scroll[qd]->x_index_pending;
275230391Skarels 		    adder->y_index_pending = scroll[qd]->y_index_pending;
275330391Skarels 		}
275430391Skarels 
275530391Skarels 	    scroll[qd]->status = 0x00;
275630391Skarels 	    }
275730391Skarels 	}
275830391Skarels }
275930391Skarels 
276030391Skarels /*****************************************************************
276130391Skarels *
276230391Skarels *	qdiint()... DUART input interrupt service routine
276330391Skarels *
276430391Skarels *****************************************************************/
276530391Skarels 
276630391Skarels qdiint(qd)
276730391Skarels register int qd;
276830391Skarels {
276930391Skarels 	register struct _vs_event *event;
277030391Skarels 	register struct qdinput *eqh;
277130391Skarels 
277230391Skarels 	struct dga *dga;
277330391Skarels 	struct duart *duart;
277430391Skarels 	struct mouse_report *new_rep;
277530391Skarels 
277630391Skarels 	struct uba_device *ui;
277730391Skarels 	struct tty *tp;
277830391Skarels 
2779*34615Smarc 	u_short chr;
278030391Skarels 	int i,j;
278130391Skarels 	int k,l;
278230391Skarels 
278330391Skarels 	u_short status;
278430391Skarels 	u_short data;
278530391Skarels 	u_short key;
278630391Skarels 
278730391Skarels 	char do_wakeup = 0;		/* flag to do a select wakeup call */
278830391Skarels 	char a, b, c;			/* mouse button test variables */
278930391Skarels 
279030391Skarels 	spl4(); 			/* allow interval timer in */
279130391Skarels 
279230391Skarels 	eqh = eq_header[qd];		/* optimized as a register */
279330391Skarels 	new_rep = &current_rep[qd];
279430391Skarels 	duart = (struct duart *) qdmap[qd].duart;
279530391Skarels 
279630391Skarels /*-----------------------------------------
279730391Skarels * if the graphic device is turned on..	*/
279830391Skarels 
279930391Skarels 	if (qdflags[qd].inuse & GRAPHIC_DEV) {
280030391Skarels 
280130391Skarels 	    /*---------------
280230391Skarels 	    * empty DUART */
280330391Skarels 
280430391Skarels 	    while ((status = duart->statusA) & RCV_RDY	||
280530391Skarels 		   (status = duart->statusB) & RCV_RDY) {
280630391Skarels 
280730391Skarels 		/*---------------------------------
280830391Skarels 		* pick up LK-201 input (if any) */
280930391Skarels 
281030391Skarels 		if ((status = duart->statusA) & RCV_RDY) {
281130391Skarels 
281230391Skarels 		    /* if error condition, then reset it */
281330391Skarels 
281430391Skarels 		    if ((status = duart->statusA) & 0x70) {
281530391Skarels 			duart->cmdA = 0x40;
281630391Skarels 			continue;
281730391Skarels 		    }
281830391Skarels 
281930391Skarels 		    /* event queue full now? (overflow condition) */
282030391Skarels 
282130391Skarels 		    if (ISFULL(eqh) == TRUE) {
2822*34615Smarc 			printf("\nqd%d: qdiint: event queue overflow", qd);
282330391Skarels 			break;
282430391Skarels 		    }
282530391Skarels 
282630391Skarels 		    /*--------------------------------------
282730391Skarels 		    * Check for various keyboard errors  */
282830391Skarels 
282930391Skarels 		    key = duart->dataA & 0xFF;
283030391Skarels 
283130391Skarels 		    if( key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
283230391Skarels 			key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
2833*34615Smarc 			printf("\nqd%d: qdiint: keyboard error, code = %x",qd,key);
283430391Skarels 			return(0);
283530391Skarels 		    }
283630391Skarels 
283730391Skarels 		    if (key < LK_LOWEST)
283830391Skarels 			return(0);
283930391Skarels 
284030391Skarels 		    ++do_wakeup;	/* request a select wakeup call */
284130391Skarels 
284230391Skarels 		    event = PUTBEGIN(eqh);
284330391Skarels 		    PUTEND(eqh);
284430391Skarels 
284530391Skarels 		    event->vse_key = key;
284630391Skarels 		    event->vse_key &= 0x00FF;
284730391Skarels 		    event->vse_x = eqh->curs_pos.x;
284830391Skarels 		    event->vse_y = eqh->curs_pos.y;
284930391Skarels 		    event->vse_time = TOY;
285030391Skarels 		    event->vse_type = VSE_BUTTON;
285130391Skarels 		    event->vse_direction = VSE_KBTRAW;
285230391Skarels 		    event->vse_device = VSE_DKB;
285330391Skarels 		}
285430391Skarels 
285530391Skarels 		/*-------------------------------------
285630391Skarels 		* pick up the mouse input (if any)  */
285730391Skarels 
285830391Skarels 		if ((status = duart->statusB) & RCV_RDY  &&
285930391Skarels 		     qdflags[qd].pntr_id == MOUSE_ID) {
286030391Skarels 
286130391Skarels 		    if (status & 0x70) {
286230391Skarels 			duart->cmdB = 0x40;
286330391Skarels 			continue;
286430391Skarels 		    }
286530391Skarels 
286630391Skarels 		    /* event queue full now? (overflow condition) */
286730391Skarels 
286830391Skarels 		    if (ISFULL(eqh) == TRUE) {
2869*34615Smarc 			printf("\nqd%d: qdiint: event queue overflow", qd);
287030391Skarels 			break;
287130391Skarels 		    }
287230391Skarels 
287330391Skarels 		    data = duart->dataB;      /* get report byte */
287430391Skarels 		    ++new_rep->bytcnt;	      /* bump report byte count */
287530391Skarels 
287630391Skarels 		    /*---------------------------
287730391Skarels 		    * if 1st byte of report.. */
287830391Skarels 
287930391Skarels 		    if ( data & START_FRAME) {
288030391Skarels 			new_rep->state = data;
288130391Skarels 			if (new_rep->bytcnt > 1) {
288230391Skarels 			    new_rep->bytcnt = 1;    /* start of new frame */
288330391Skarels 			    continue;		    /* ..continue looking */
288430391Skarels 			}
288530391Skarels 		    }
288630391Skarels 
288730391Skarels 		    /*---------------------------
288830391Skarels 		    * if 2nd byte of report.. */
288930391Skarels 
289030391Skarels 		    else if (new_rep->bytcnt == 2) {
289130391Skarels 			new_rep->dx = data & 0x00FF;
289230391Skarels 		    }
289330391Skarels 
289430391Skarels 		    /*-------------------------------------------------
289530391Skarels 		    * if 3rd byte of report, load input event queue */
289630391Skarels 
289730391Skarels 		    else if (new_rep->bytcnt == 3) {
289830391Skarels 
289930391Skarels 			new_rep->dy = data & 0x00FF;
290030391Skarels 			new_rep->bytcnt = 0;
290130391Skarels 
290230391Skarels 			/*-----------------------------------
290330391Skarels 			* if mouse position has changed.. */
290430391Skarels 
290530391Skarels 			if (new_rep->dx != 0  ||  new_rep->dy != 0) {
290630391Skarels 
290730391Skarels 			    /*---------------------------------------------
290830391Skarels 			    * calculate acceleration factor, if needed	*/
290930391Skarels 
291030391Skarels 			    if (qdflags[qd].curs_acc > ACC_OFF) {
291130391Skarels 
291230391Skarels 				if (qdflags[qd].curs_thr <= new_rep->dx)
291330391Skarels 				    new_rep->dx +=
291430391Skarels 					(new_rep->dx - qdflags[qd].curs_thr)
291530391Skarels 					 * qdflags[qd].curs_acc;
291630391Skarels 
291730391Skarels 				if (qdflags[qd].curs_thr <= new_rep->dy)
291830391Skarels 				    new_rep->dy +=
291930391Skarels 					(new_rep->dy - qdflags[qd].curs_thr)
292030391Skarels 					 * qdflags[qd].curs_acc;
292130391Skarels 			    }
292230391Skarels 
292330391Skarels 			    /*-------------------------------------
292430391Skarels 			    * update cursor position coordinates */
292530391Skarels 
292630391Skarels 			    if (new_rep->state & X_SIGN) {
292730391Skarels 				eqh->curs_pos.x += new_rep->dx;
292830391Skarels 				if (eqh->curs_pos.x > 1023)
292930391Skarels 				    eqh->curs_pos.x = 1023;
293030391Skarels 			    }
293130391Skarels 			    else {
293230391Skarels 				eqh->curs_pos.x -= new_rep->dx;
293330391Skarels 				if (eqh->curs_pos.x < -15)
293430391Skarels 				    eqh->curs_pos.x = -15;
293530391Skarels 			    }
293630391Skarels 
293730391Skarels 			    if (new_rep->state & Y_SIGN) {
293830391Skarels 				 eqh->curs_pos.y -= new_rep->dy;
293930391Skarels 				 if (eqh->curs_pos.y < -15)
294030391Skarels 				     eqh->curs_pos.y = -15;
294130391Skarels 			    }
294230391Skarels 			    else {
294330391Skarels 				eqh->curs_pos.y += new_rep->dy;
294430391Skarels 				if (eqh->curs_pos.y > 863)
294530391Skarels 				    eqh->curs_pos.y = 863;
294630391Skarels 			    }
294730391Skarels 
294830391Skarels 			    /*---------------------------------
294930391Skarels 			    * update cursor screen position */
295030391Skarels 
295130391Skarels 			    dga = (struct dga *) qdmap[qd].dga;
295230391Skarels 			    dga->x_cursor = TRANX(eqh->curs_pos.x);
295330391Skarels 			    dga->y_cursor = TRANY(eqh->curs_pos.y);
295430391Skarels 
295530391Skarels 			    /*--------------------------------------------
295630391Skarels 			    * if cursor is in the box, no event report */
295730391Skarels 
295830391Skarels 			    if (eqh->curs_pos.x <= eqh->curs_box.right	&&
295930391Skarels 				eqh->curs_pos.x >= eqh->curs_box.left  &&
296030391Skarels 				eqh->curs_pos.y >= eqh->curs_box.top  &&
296130391Skarels 				eqh->curs_pos.y <= eqh->curs_box.bottom ) {
296230391Skarels 				    goto GET_MBUTTON;
296330391Skarels 			    }
296430391Skarels 
296530391Skarels 			    /*---------------------------------
296630391Skarels 			    * report the mouse motion event */
296730391Skarels 
296830391Skarels 			    event = PUTBEGIN(eqh);
296930391Skarels 			    PUTEND(eqh);
297030391Skarels 
297130391Skarels 			    ++do_wakeup;   /* request a select wakeup call */
297230391Skarels 
297330391Skarels 			    event->vse_x = eqh->curs_pos.x;
297430391Skarels 			    event->vse_y = eqh->curs_pos.y;
297530391Skarels 
297630391Skarels 			    event->vse_device = VSE_MOUSE;  /* mouse */
297730391Skarels 			    event->vse_type = VSE_MMOTION;  /* pos changed */
297830391Skarels 			    event->vse_key = 0;
297930391Skarels 			    event->vse_direction = 0;
298030391Skarels 			    event->vse_time = TOY;	/* time stamp */
298130391Skarels 			}
298230391Skarels 
298330391Skarels GET_MBUTTON:
298430391Skarels 			/*-------------------------------
298530391Skarels 			* if button state has changed */
298630391Skarels 
298730391Skarels 			a = new_rep->state & 0x07;    /*mask nonbutton bits */
298830391Skarels 			b = last_rep[qd].state & 0x07;
298930391Skarels 
299030391Skarels 			if (a ^ b) {
299130391Skarels 
299230391Skarels 			    for ( c = 1;  c < 8; c <<= 1) {
299330391Skarels 
299430391Skarels 				if (!( c & (a ^ b))) /* this button change? */
299530391Skarels 				    continue;
299630391Skarels 
299730391Skarels 				/* event queue full? (overflow condition) */
299830391Skarels 
299930391Skarels 				if (ISFULL(eqh) == TRUE) {
3000*34615Smarc 				    printf("\nqd%d: qdiint: event queue overflow", qd);
300130391Skarels 				    break;
300230391Skarels 				}
300330391Skarels 
300430391Skarels 				event = PUTBEGIN(eqh);	/* get new event */
300530391Skarels 				PUTEND(eqh);
300630391Skarels 
300730391Skarels 				++do_wakeup;   /* request select wakeup */
300830391Skarels 
300930391Skarels 				event->vse_x = eqh->curs_pos.x;
301030391Skarels 				event->vse_y = eqh->curs_pos.y;
301130391Skarels 
301230391Skarels 				event->vse_device = VSE_MOUSE;	/* mouse */
301330391Skarels 				event->vse_type = VSE_BUTTON; /* new button */
301430391Skarels 				event->vse_time = TOY;	      /* time stamp */
301530391Skarels 
301630391Skarels 				/* flag changed button and if up or down */
301730391Skarels 
301830391Skarels 				if (c == RIGHT_BUTTON)
301930391Skarels 				    event->vse_key = VSE_RIGHT_BUTTON;
302030391Skarels 				else if (c == MIDDLE_BUTTON)
302130391Skarels 				    event->vse_key = VSE_MIDDLE_BUTTON;
302230391Skarels 				else if (c == LEFT_BUTTON)
302330391Skarels 				    event->vse_key = VSE_LEFT_BUTTON;
302430391Skarels 
302530391Skarels 				/* set bit = button depressed */
302630391Skarels 
302730391Skarels 				if (c & a)
302830391Skarels 				    event->vse_direction = VSE_KBTDOWN;
302930391Skarels 				else
303030391Skarels 				    event->vse_direction = VSE_KBTUP;
303130391Skarels 			    }
303230391Skarels 			}
303330391Skarels 
303430391Skarels 			/* refresh last report */
303530391Skarels 
303630391Skarels 			last_rep[qd] = current_rep[qd];
303730391Skarels 
303830391Skarels 		    }  /* get last byte of report */
303930391Skarels 		} /* pickup mouse input */
304030391Skarels 
304130391Skarels 		/*--------------------------------
304230391Skarels 		* pickup tablet input, if any  */
304330391Skarels 
304430391Skarels 		else if ((status = duart->statusB) & RCV_RDY  &&
304530391Skarels 			 qdflags[qd].pntr_id == TABLET_ID) {
304630391Skarels 
304730391Skarels 		    if (status & 0x70) {
304830391Skarels 			duart->cmdB = 0x40;
304930391Skarels 			continue;
305030391Skarels 		    }
305130391Skarels 
305230391Skarels 		    /* event queue full now? (overflow condition) */
305330391Skarels 
305430391Skarels 		    if (ISFULL(eqh) == TRUE) {
3055*34615Smarc 			printf("\nqd%d: qdiint: event queue overflow", qd);
305630391Skarels 			break;
305730391Skarels 		    }
305830391Skarels 
305930391Skarels 		    data = duart->dataB;      /* get report byte */
306030391Skarels 		    ++new_rep->bytcnt;	      /* bump report byte count */
306130391Skarels 
306230391Skarels 		    /*---------------------------
306330391Skarels 		    * if 1st byte of report.. */
306430391Skarels 
306530391Skarels 		    if (data & START_FRAME) {
306630391Skarels 			new_rep->state = data;
306730391Skarels 			if (new_rep->bytcnt > 1) {
306830391Skarels 			    new_rep->bytcnt = 1;    /* start of new frame */
306930391Skarels 			    continue;		    /* ..continue looking */
307030391Skarels 			}
307130391Skarels 		    }
307230391Skarels 
307330391Skarels 		    /*---------------------------
307430391Skarels 		    * if 2nd byte of report.. */
307530391Skarels 
307630391Skarels 		    else if (new_rep->bytcnt == 2) {
307730391Skarels 			new_rep->dx = data & 0x3F;
307830391Skarels 		    }
307930391Skarels 
308030391Skarels 		    /*---------------------------
308130391Skarels 		    * if 3rd byte of report.. */
308230391Skarels 
308330391Skarels 		    else if (new_rep->bytcnt == 3) {
308430391Skarels 			new_rep->dx |= (data & 0x3F) << 6;
308530391Skarels 		    }
308630391Skarels 
308730391Skarels 		    /*---------------------------
308830391Skarels 		    * if 4th byte of report.. */
308930391Skarels 
309030391Skarels 		    else if (new_rep->bytcnt == 4) {
309130391Skarels 			new_rep->dy = data & 0x3F;
309230391Skarels 		    }
309330391Skarels 
309430391Skarels 		    /*-------------------------------------------------
309530391Skarels 		    * if 5th byte of report, load input event queue */
309630391Skarels 
309730391Skarels 		    else if (new_rep->bytcnt == 5) {
309830391Skarels 
309930391Skarels 			new_rep->dy |= (data & 0x3F) << 6;
310030391Skarels 			new_rep->bytcnt = 0;
310130391Skarels 
310230391Skarels 			/*-------------------------------------
310330391Skarels 			* update cursor position coordinates */
310430391Skarels 
310530391Skarels 			new_rep->dx /= qdflags[qd].tab_res;
310630391Skarels 			new_rep->dy = (2200 - new_rep->dy)
310730391Skarels 				      / qdflags[qd].tab_res;
310830391Skarels 
310930391Skarels 			if (new_rep->dx > 1023) {
311030391Skarels 			    new_rep->dx = 1023;
311130391Skarels 			}
311230391Skarels 			if (new_rep->dy > 863) {
311330391Skarels 			    new_rep->dy = 863;
311430391Skarels 			}
311530391Skarels 
311630391Skarels 			/*
311730391Skarels 			 * report an event if the puck/stylus has moved
311830391Skarels 			 */
311930391Skarels 
312030391Skarels 			if (eqh->curs_pos.x != new_rep->dx ||
312130391Skarels 			    eqh->curs_pos.y != new_rep->dy) {
312230391Skarels 
312330391Skarels 			    eqh->curs_pos.x = new_rep->dx;
312430391Skarels 			    eqh->curs_pos.y = new_rep->dy;
312530391Skarels 
312630391Skarels 			    /*---------------------------------
312730391Skarels 			    * update cursor screen position */
312830391Skarels 
312930391Skarels 			    dga = (struct dga *) qdmap[qd].dga;
313030391Skarels 			    dga->x_cursor = TRANX(eqh->curs_pos.x);
313130391Skarels 			    dga->y_cursor = TRANY(eqh->curs_pos.y);
313230391Skarels 
313330391Skarels 			    /*
313430391Skarels 			     * if cursor is in the box, no event report
313530391Skarels 			     */
313630391Skarels 
313730391Skarels 			    if (eqh->curs_pos.x <= eqh->curs_box.right	&&
313830391Skarels 				eqh->curs_pos.x >= eqh->curs_box.left  &&
313930391Skarels 				eqh->curs_pos.y >= eqh->curs_box.top  &&
314030391Skarels 				eqh->curs_pos.y <= eqh->curs_box.bottom ) {
314130391Skarels 				goto GET_TBUTTON;
314230391Skarels 			    }
314330391Skarels 
314430391Skarels 			    /*---------------------------------
314530391Skarels 			    * report the tablet motion event */
314630391Skarels 
314730391Skarels 			    event = PUTBEGIN(eqh);
314830391Skarels 			    PUTEND(eqh);
314930391Skarels 
315030391Skarels 			    ++do_wakeup;   /* request a select wakeup call */
315130391Skarels 
315230391Skarels 			    event->vse_x = eqh->curs_pos.x;
315330391Skarels 			    event->vse_y = eqh->curs_pos.y;
315430391Skarels 
315530391Skarels 			    event->vse_device = VSE_TABLET;  /* tablet */
315630391Skarels 			    /*
315730391Skarels 			     * right now, X handles tablet motion the same
315830391Skarels 			     * as mouse motion
315930391Skarels 			     */
316030391Skarels 			    event->vse_type = VSE_MMOTION;   /* pos changed */
316130391Skarels 			    event->vse_key = 0;
316230391Skarels 			    event->vse_direction = 0;
316330391Skarels 			    event->vse_time = TOY;	/* time stamp */
316430391Skarels 			}
316530391Skarels GET_TBUTTON:
316630391Skarels 			/*-------------------------------
316730391Skarels 			* if button state has changed */
316830391Skarels 
316930391Skarels 			a = new_rep->state & 0x1E;   /* mask nonbutton bits */
317030391Skarels 			b = last_rep[qd].state & 0x1E;
317130391Skarels 
317230391Skarels 			if (a ^ b) {
317330391Skarels 
317430391Skarels 			    /* event queue full now? (overflow condition) */
317530391Skarels 
317630391Skarels 			    if (ISFULL(eqh) == TRUE) {
3177*34615Smarc 				printf("\nqd%d: qdiint: event queue overflow",qd);
317830391Skarels 				break;
317930391Skarels 			    }
318030391Skarels 
318130391Skarels 			    event = PUTBEGIN(eqh);  /* get new event */
318230391Skarels 			    PUTEND(eqh);
318330391Skarels 
318430391Skarels 			    ++do_wakeup;   /* request a select wakeup call */
318530391Skarels 
318630391Skarels 			    event->vse_x = eqh->curs_pos.x;
318730391Skarels 			    event->vse_y = eqh->curs_pos.y;
318830391Skarels 
318930391Skarels 			    event->vse_device = VSE_TABLET;  /* tablet */
319030391Skarels 			    event->vse_type = VSE_BUTTON; /* button changed */
319130391Skarels 			    event->vse_time = TOY;	   /* time stamp */
319230391Skarels 
319330391Skarels 			    /* define the changed button and if up or down */
319430391Skarels 
319530391Skarels 			    for ( c = 1;  c <= 0x10; c <<= 1) {
319630391Skarels 				if (c & (a ^ b)) {
319730391Skarels 				    if (c == T_LEFT_BUTTON)
319830391Skarels 					event->vse_key = VSE_T_LEFT_BUTTON;
319930391Skarels 				    else if (c == T_FRONT_BUTTON)
320030391Skarels 					event->vse_key = VSE_T_FRONT_BUTTON;
320130391Skarels 				    else if (c == T_RIGHT_BUTTON)
320230391Skarels 					event->vse_key = VSE_T_RIGHT_BUTTON;
320330391Skarels 				    else if (c == T_BACK_BUTTON)
320430391Skarels 					event->vse_key = VSE_T_BACK_BUTTON;
320530391Skarels 				    break;
320630391Skarels 				}
320730391Skarels 			    }
320830391Skarels 
320930391Skarels 			    /* set bit = button depressed */
321030391Skarels 
321130391Skarels 			    if (c & a)
321230391Skarels 				event->vse_direction = VSE_KBTDOWN;
321330391Skarels 			    else
321430391Skarels 				event->vse_direction = VSE_KBTUP;
321530391Skarels 			}
321630391Skarels 
321730391Skarels 			/* refresh last report */
321830391Skarels 
321930391Skarels 			last_rep[qd] = current_rep[qd];
322030391Skarels 
322130391Skarels 		    } /* get last byte of report */
322230391Skarels 		} /* pick up tablet input */
322330391Skarels 
322430391Skarels 	    } /* while input available.. */
322530391Skarels 
322630391Skarels 	    /*---------------------
322730391Skarels 	    * do select wakeup	*/
322830391Skarels 
3229*34615Smarc 
323030391Skarels 	    if (rsel[qd] && do_wakeup && qdflags[qd].selmask & SEL_READ) {
323130391Skarels 		selwakeup(rsel[qd], 0);
323230391Skarels 		rsel[qd] = 0;
323330391Skarels 		qdflags[qd].selmask &= ~SEL_READ;
323430391Skarels 		do_wakeup = 0;
323530391Skarels 	    }
323630391Skarels 	}
323730391Skarels 
3238*34615Smarc /*-----------------------------------------------------------------
3239*34615Smarc * if the graphic device is not turned on, this is console input */
324030391Skarels 
324130391Skarels 	else {
324230391Skarels 
324330391Skarels 	    ui = qdinfo[qd];
324430391Skarels 	    if (ui == 0 || ui->ui_alive == 0)
324530391Skarels 		return(0);
324630391Skarels 
324730391Skarels 	    tp = &qd_tty[qd << 2];
324830391Skarels 
324930391Skarels 	    /*--------------------------------------
325030391Skarels 	    * Get a character from the keyboard. */
325130391Skarels 
325230391Skarels 	    while ((status = duart->statusA) & RCV_RDY) {
325330391Skarels 
325430391Skarels 		key = duart->dataA;
325530391Skarels 		key &= 0xFF;
325630391Skarels 
325730391Skarels 		/*--------------------------------------
325830391Skarels 		* Check for various keyboard errors  */
325930391Skarels 
326030391Skarels 		if( key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
326130391Skarels 		    key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
3262*34615Smarc 			printf("\nqd%d: qdiint: Keyboard error, code = %x",qd,key);
326330391Skarels 			return(0);
326430391Skarels 		}
326530391Skarels 
326630391Skarels 		if (key < LK_LOWEST)
326730391Skarels 		    return(0);
326830391Skarels 
326930391Skarels 		/*---------------------------------
327030391Skarels 		* See if its a state change key */
327130391Skarels 
327230391Skarels 		switch (key) {
327330391Skarels 
327430391Skarels 		    case LOCK:
327530391Skarels 			q_keyboard.lock ^= 0xffff;	/* toggle */
327630391Skarels 			if (q_keyboard.lock)
327730391Skarels 			    led_control(qd, LK_LED_ENABLE, LK_LED_LOCK);
327830391Skarels 			else
327930391Skarels 			    led_control(qd, LK_LED_DISABLE, LK_LED_LOCK);
328030391Skarels 			return;
328130391Skarels 
328230391Skarels 		    case SHIFT:
328330391Skarels 			q_keyboard.shift ^= 0xFFFF;
328430391Skarels 			return;
328530391Skarels 
328630391Skarels 		    case CNTRL:
328730391Skarels 			q_keyboard.cntrl ^= 0xFFFF;
328830391Skarels 			return;
328930391Skarels 
329030391Skarels 		    case ALLUP:
329130391Skarels 			q_keyboard.cntrl = 0;
329230391Skarels 			q_keyboard.shift = 0;
329330391Skarels 			return;
329430391Skarels 
329530391Skarels 		    case REPEAT:
329630391Skarels 			chr = q_keyboard.last;
329730391Skarels 			break;
329830391Skarels 
329930391Skarels 		    /*-------------------------------------------------------
330030391Skarels 		    * Test for cntrl characters. If set, see if the character
330130391Skarels 		    * is elligible to become a control character. */
330230391Skarels 
330330391Skarels 		    default:
330430391Skarels 
330530391Skarels 			if (q_keyboard.cntrl) {
330630391Skarels 				chr = q_key[key];
330730391Skarels 				if (chr >= ' ' && chr <= '~')
330830391Skarels 				    chr &= 0x1F;
3309*34615Smarc 				else if (chr >= 0xA1 && chr <= 0xFE)
3310*34615Smarc 				    chr &= 0x9F;
331130391Skarels 			}
331230391Skarels 			else if( q_keyboard.lock || q_keyboard.shift )
331330391Skarels 			    chr = q_shift_key[key];
331430391Skarels 			else
331530391Skarels 			    chr = q_key[key];
331630391Skarels 			break;
331730391Skarels 		}
331830391Skarels 
331930391Skarels 		q_keyboard.last = chr;
332030391Skarels 
332130391Skarels 		/*-----------------------------------
332230391Skarels 		* Check for special function keys */
332330391Skarels 
3324*34615Smarc 		if (chr & 0x100) {
332530391Skarels 			char *string;
332630391Skarels 			string = q_special[chr & 0x7F];
332730391Skarels 			while(*string)
332830391Skarels 			    (*linesw[tp->t_line].l_rint)(*string++, tp);
332930391Skarels 		}
333030391Skarels 		else {
3331*34615Smarc #ifdef notdef	/* notneeded */
3332*34615Smarc 			if (tp->t_iflag & ISTRIP)	/* Strip to 7 bits. */
3333*34615Smarc 				c &= 0177;
3334*34615Smarc 			else {			/* Take the full 8-bits */
3335*34615Smarc 				/* If ISTRIP is not set a valid character of 377
3336*34615Smarc 			 	* is read as 0377,0377 to avoid ambiguity with
3337*34615Smarc 			 	* the PARMARK sequence.
3338*34615Smarc 			 	*/
3339*34615Smarc 				if ((c == 0377) && (tp->t_line == TERMIODISC))
3340*34615Smarc 					(*linesw[tp->t_line].l_rint)(0377,tp);
3341*34615Smarc 
3342*34615Smarc 			}
3343*34615Smarc #endif /*notdef*/
334430391Skarels 			(*linesw[tp->t_line].l_rint)(chr, tp);
334530391Skarels 		}
334630391Skarels 	    }
334730391Skarels 	}
334830391Skarels 
3349*34615Smarc /*----------------------
3350*34615Smarc * cleanup and exit  */
3351*34615Smarc 
335230391Skarels 	return(0);
335330391Skarels 
335430391Skarels } /* qdiint */
335530391Skarels 
335630391Skarels /******************************************************************
3357*34615Smarc *******************************************************************
3358*34615Smarc *******************************************************************
335930391Skarels *
336030391Skarels *	THE SUBROUTINES START HERE:
336130391Skarels *
336230391Skarels ******************************************************************/
336330391Skarels 
336430391Skarels /*****************************************************************
336530391Skarels *
336630391Skarels *	clear_qd_screen()... clear the QDSS screen
336730391Skarels *
336830391Skarels ******************************************************************
336930391Skarels *
337030391Skarels *			     >>> NOTE <<<
337130391Skarels *
337230391Skarels *   This code requires that certain adder initialization be valid.  To
337330391Skarels *   assure that this requirement is satisfied, this routine should be
337430391Skarels *   called only after calling the "setup_dragon()" function.
337530391Skarels *
337630391Skarels *   Clear the bitmap a piece at a time. Since the fast scroll clear
337730391Skarels *   only clears the current displayed portion of the bitmap put a
337830391Skarels *   temporary value in the y limit register so we can access whole
337930391Skarels *   bitmap
338030391Skarels *
338130391Skarels ****************/
338230391Skarels 
338330391Skarels clear_qd_screen(unit)
338430391Skarels int unit;
338530391Skarels {
338630391Skarels 	register struct adder *adder;
338730391Skarels 	adder = (struct adder *) qdmap[unit].adder;
338830391Skarels 
338930391Skarels 	adder->x_limit = 1024;
339030391Skarels 	adder->y_limit = 2048 - CHAR_HEIGHT;
339130391Skarels 	adder->y_offset_pending = 0;
339230391Skarels 
339330391Skarels 	wait_status(adder, VSYNC);	/* wait at LEAST 1 full frame */
339430391Skarels 	wait_status(adder, VSYNC);
339530391Skarels 
339630391Skarels 	adder->y_scroll_constant = SCROLL_ERASE;
339730391Skarels 
339830391Skarels 	wait_status(adder, VSYNC);
339930391Skarels 	wait_status(adder, VSYNC);
340030391Skarels 
340130391Skarels 	adder->y_offset_pending = 864;
340230391Skarels 
340330391Skarels 	wait_status(adder, VSYNC);
340430391Skarels 	wait_status(adder, VSYNC);
340530391Skarels 
340630391Skarels 	adder->y_scroll_constant = SCROLL_ERASE;
340730391Skarels 
340830391Skarels 	wait_status(adder, VSYNC);
340930391Skarels 	wait_status(adder, VSYNC);
341030391Skarels 
341130391Skarels 	adder->y_offset_pending = 1728;
341230391Skarels 
341330391Skarels 	wait_status(adder, VSYNC);
341430391Skarels 	wait_status(adder, VSYNC);
341530391Skarels 
341630391Skarels 	adder->y_scroll_constant = SCROLL_ERASE;
341730391Skarels 
341830391Skarels 	wait_status(adder, VSYNC);
341930391Skarels 	wait_status(adder, VSYNC);
342030391Skarels 
342130391Skarels 	adder->y_offset_pending = 0;	 /* back to normal */
342230391Skarels 
342330391Skarels 	wait_status(adder, VSYNC);
342430391Skarels 	wait_status(adder, VSYNC);
342530391Skarels 
342630391Skarels 	adder->x_limit = MAX_SCREEN_X;
342730391Skarels 	adder->y_limit = MAX_SCREEN_Y + FONT_HEIGHT;
342830391Skarels 
342930391Skarels } /* clear_qd_screen */
343030391Skarels 
343130391Skarels /**********************************************************************
343230391Skarels *
343330391Skarels *	qdputc()... route kernel console output to display destination
343430391Skarels *
343530391Skarels ***********************************************************************
343630391Skarels *
343730391Skarels *	calling convention:
343830391Skarels *
343930391Skarels *		qdputc(chr);
344030391Skarels *
344130391Skarels *	where:	char chr;	 ;character for output
344230391Skarels *
344330391Skarels ****************/
344430391Skarels 
344530391Skarels qdputc(chr)
344630391Skarels register char chr;
344730391Skarels {
3448*34615Smarc 	register struct tty *tp0;
344930391Skarels 
3450*34615Smarc /*---------------------------------------------------------
3451*34615Smarc * if system is now physical, forget it (ie: crash DUMP) */
3452*34615Smarc 
345330391Skarels 	if ( (mfpr(MAPEN) & 1) == 0 )
345430391Skarels 	    return;
345530391Skarels 
3456*34615Smarc /*--------------------------------------------------
3457*34615Smarc * direct kernel output char to the proper place  */
3458*34615Smarc 
3459*34615Smarc #ifdef notdef	/* never */
3460*34615Smarc 	tp0 = &qd_tty[1];
3461*34615Smarc 
3462*34615Smarc 	if (qdflags[0].kernel_loop != 0  &&  tp0->t_state & TS_ISOPEN) {
3463*34615Smarc 	    (*linesw[tp0->t_line].l_rint)(chr, tp0);
3464*34615Smarc 	} else {
3465*34615Smarc 	    blitc(0, chr & 0xff);
3466*34615Smarc 	}
3467*34615Smarc #endif /*notdef*/
3468*34615Smarc 	blitc(0, chr & 0xff);
346932012Smarc 	if ((chr & 0177) == '\n')
347032012Smarc 		blitc(0, '\r');
347130391Skarels 
347230391Skarels 
347330391Skarels } /* qdputc */
347430391Skarels 
347530391Skarels /*******************************************************************
347630391Skarels *
347730391Skarels *	qdgetc()... get a character from the LK201
347830391Skarels *
347930391Skarels *******************************************************************
348030391Skarels *
348130391Skarels *	calling convention:
348230391Skarels *
348330391Skarels *		qdgetc();
348430391Skarels *
348530391Skarels *	returns:  the character read.
348630391Skarels *
348730391Skarels ****************/
348830391Skarels 
348930391Skarels qdgetc()
349030391Skarels {
349130391Skarels 	register short key;
349230391Skarels 	register char chr;
349330391Skarels 	register struct duart *duart;
349430391Skarels 
349530391Skarels 	u_int status;
349630391Skarels 
349730391Skarels 	duart = (struct duart *) qdmap[0].duart;
349830391Skarels 
349930391Skarels 	/*--------------------------------------
350030391Skarels 	* Get a character from the keyboard. */
350130391Skarels 
350230391Skarels LOOP:
350330391Skarels 	while (!((status = duart->statusA) & RCV_RDY))
350430391Skarels 			;
350530391Skarels 
350630391Skarels 	key = duart->dataA;
350730391Skarels 	key &= 0xFF;
350830391Skarels 
350930391Skarels 	/*--------------------------------------
351030391Skarels 	* Check for various keyboard errors  */
351130391Skarels 
351230391Skarels 	if( key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
351330391Skarels 	    key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
351430391Skarels 		printf("Keyboard error, code = %x\n", key);
351530391Skarels 		return(0);
351630391Skarels 	}
351730391Skarels 
351830391Skarels 	if (key < LK_LOWEST)
351930391Skarels 	    return(0);
352030391Skarels 
352130391Skarels 	/*---------------------------------
352230391Skarels 	* See if its a state change key */
352330391Skarels 
352430391Skarels 	switch (key) {
352530391Skarels 
352630391Skarels 	    case LOCK:
352730391Skarels 		q_keyboard.lock ^= 0xffff;	/* toggle */
352830391Skarels 		if (q_keyboard.lock)
352930391Skarels 		    led_control(LK_LED_ENABLE, LK_LED_LOCK);
353030391Skarels 		else
353130391Skarels 		    led_control(LK_LED_DISABLE, LK_LED_LOCK);
353230391Skarels 		goto LOOP;
353330391Skarels 
353430391Skarels 	    case SHIFT:
353530391Skarels 		q_keyboard.shift ^= 0xFFFF;
353630391Skarels 		goto LOOP;
353730391Skarels 
353830391Skarels 	    case CNTRL:
353930391Skarels 		q_keyboard.cntrl ^= 0xFFFF;
354030391Skarels 		goto LOOP;
354130391Skarels 
354230391Skarels 	    case ALLUP:
354330391Skarels 		q_keyboard.cntrl = 0;
354430391Skarels 		q_keyboard.shift = 0;
354530391Skarels 		goto LOOP;
354630391Skarels 
354730391Skarels 	    case REPEAT:
354830391Skarels 		chr = q_keyboard.last;
354930391Skarels 		break;
355030391Skarels 
355130391Skarels 	    /*-------------------------------------------------------
355230391Skarels 	    * Test for cntrl characters. If set, see if the character
355330391Skarels 	    * is elligible to become a control character. */
355430391Skarels 
355530391Skarels 	    default:
355630391Skarels 
355730391Skarels 		if (q_keyboard.cntrl) {
355830391Skarels 		    chr = q_key[key];
355930391Skarels 		    if (chr >= ' ' && chr <= '~')
356030391Skarels 			chr &= 0x1F;
356130391Skarels 		}
356230391Skarels 		else if ( q_keyboard.lock || q_keyboard.shift )
356330391Skarels 		    chr = q_shift_key[key];
356430391Skarels 		else
356530391Skarels 		    chr = q_key[key];
356630391Skarels 		break;
356730391Skarels 	}
356830391Skarels 
356930391Skarels 	if (chr < ' ' && chr > '~')	/* if input is non-displayable */
357030391Skarels 	    return(0);			/* ..then pitch it! */
357130391Skarels 
357230391Skarels 	q_keyboard.last = chr;
357330391Skarels 
357430391Skarels 	/*-----------------------------------
357530391Skarels 	* Check for special function keys */
357630391Skarels 
357730391Skarels 	if (chr & 0x80) 		/* pitch the function keys */
357830391Skarels 	    return(0);
357930391Skarels 	else
358030391Skarels 	    return(chr);
358130391Skarels 
358230391Skarels } /* qdgetc */
358330391Skarels 
358430391Skarels /**********************************************************************
358530391Skarels *
358630391Skarels *	ldcursor()... load the mouse cursor's template RAM bitmap
358730391Skarels *
358830391Skarels *********************************************************************
358930391Skarels *
359030391Skarels *	calling convention:
359130391Skarels *
359230391Skarels *		ldcursor(unit, bitmap);
359330391Skarels *		u_int unit;
359430391Skarels *		short *bitmap;
359530391Skarels *
359630391Skarels ****************/
359730391Skarels 
359830391Skarels ldcursor(unit, bitmap)
359930391Skarels u_int unit;
360030391Skarels short *bitmap;
360130391Skarels {
360230391Skarels 	register struct dga *dga;
360330391Skarels 	register short *temp;
360430391Skarels 	register int i;
360530391Skarels 
360630391Skarels 	int cursor;
360730391Skarels 
360830391Skarels 	dga = (struct dga *) qdmap[unit].dga;
360930391Skarels 	temp = (short *) qdmap[unit].template;
361030391Skarels 
361130391Skarels 	if (dga->csr & CURS_ENB) {	/* if the cursor is enabled.. */
361230391Skarels 	    cursor = -1;		/* ..note that.. */
361330391Skarels 	    dga->csr &= ~CURS_ENB;	/* ..and shut it off */
361430391Skarels 	}
361530391Skarels 	else {
361630391Skarels 	    cursor = 0;
361730391Skarels 	}
361830391Skarels 
361930391Skarels 	dga->csr &= ~CURS_ENB;		/* shut off the cursor */
362030391Skarels 
362130391Skarels 	temp += (8 * 1024) - 32;	/* cursor is 32 WORDS from the end */
362230391Skarels 					/* ..of the 8k WORD template space */
362330391Skarels 	for (i = 0; i < 32; ++i)
362430391Skarels 	    *temp++ = *bitmap++;
362530391Skarels 
362630391Skarels 	if (cursor) {			/* if cursor was enabled.. */
362730391Skarels 	    dga->csr |= CURS_ENB;	/* ..turn it back on */
362830391Skarels 	}
362930391Skarels 
363030391Skarels 	return(0);
363130391Skarels 
363230391Skarels } /* ldcursor */
363330391Skarels 
363430391Skarels /**********************************************************************
363530391Skarels *
363630391Skarels *	ldfont()... put the console font in the QDSS off-screen memory
363730391Skarels *
363830391Skarels ***********************************************************************
363930391Skarels *
364030391Skarels *	calling convention:
364130391Skarels *
364230391Skarels *		ldfont(unit);
364330391Skarels *		u_int unit;	;QDSS unit number
364430391Skarels *
364530391Skarels ****************/
364630391Skarels 
364730391Skarels ldfont(unit)
364830391Skarels u_int unit;
364930391Skarels {
365030391Skarels 	register struct adder *adder;
365130391Skarels 
365230391Skarels 	int i;		/* scratch variables */
365330391Skarels 	int j;
365430391Skarels 	int k;
365530391Skarels 	short packed;
3656*34615Smarc 	int max_chars_line;
365730391Skarels 
365830391Skarels 	adder = (struct adder *) qdmap[unit].adder;
365930391Skarels 
3660*34615Smarc /*------------------------------------------
3661*34615Smarc * setup VIPER operand control registers  */
366230391Skarels 
366330391Skarels 	write_ID(adder, MASK_1, 0xFFFF);
366430391Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
366530391Skarels 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
366630391Skarels 
366730391Skarels 	write_ID(adder, SRC1_OCR_B,
366830391Skarels 			EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY);
366930391Skarels 	write_ID(adder, SRC2_OCR_B,
367030391Skarels 			EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY);
367130391Skarels 	write_ID(adder, DST_OCR_B,
367230391Skarels 			EXT_SOURCE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
367330391Skarels 
367430391Skarels 	adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL;
367530391Skarels 
3676*34615Smarc /*--------------------------
3677*34615Smarc * load destination data  */
367830391Skarels 
367930391Skarels 	wait_status(adder, RASTEROP_COMPLETE);
368030391Skarels 
368130391Skarels 	adder->destination_x = FONT_X;
368230391Skarels 	adder->destination_y = FONT_Y;
3683*34615Smarc 	if (FONT_WIDTH > MAX_SCREEN_X)
3684*34615Smarc 		adder->fast_dest_dx = MAX_SCREEN_X;
3685*34615Smarc 	else
3686*34615Smarc 		adder->fast_dest_dx = FONT_WIDTH;
368730391Skarels 	adder->slow_dest_dy = CHAR_HEIGHT;
368830391Skarels 
3689*34615Smarc /*---------------------------------------
3690*34615Smarc * setup for processor to bitmap xfer  */
369130391Skarels 
369230391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0001);
369330391Skarels 	adder->cmd = PBT | OCRB | 2 | DTE | 2;
369430391Skarels 
3695*34615Smarc /*---------------------------------------
3696*34615Smarc * Figure out how many characters can be stored on one "line" of offscreen memory
3697*34615Smarc */
3698*34615Smarc 	    max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
3699*34615Smarc 	    if ((CHARS/2 + CHARS%2) < max_chars_line)
3700*34615Smarc 		max_chars_line = CHARS/2 + CHARS%2;
370130391Skarels 
3702*34615Smarc /*-----------------------------------------------
3703*34615Smarc * iteratively do the processor to bitmap xfer */
3704*34615Smarc 
370530391Skarels 	for (i = 0; i < ROWS; ++i) {
370630391Skarels 
370730391Skarels 	    /* PTOB a scan line */
370830391Skarels 
3709*34615Smarc 	    for (j = 0, k = i; j < max_chars_line; ++j) {
371030391Skarels 		/* PTOB one scan of a char cell */
371130391Skarels 
371230391Skarels 		packed = q_font[k];
371330391Skarels 		k += ROWS;
371430391Skarels 		packed |= ((short)q_font[k] << 8);
371530391Skarels 		k += ROWS;
371630391Skarels 
371730391Skarels 		wait_status(adder, TX_READY);
371830391Skarels 		adder->id_data = packed;
371930391Skarels 	    }
372030391Skarels 	}
372130391Skarels 
3722*34615Smarc /*---------------------------------------
3723*34615Smarc * Copy the second row of characters.
3724*34615Smarc * Subtract the first row from the total number.  Divide this quantity by 2
3725*34615Smarc * because 2 chars are stored in a short in the PTOB loop below.
3726*34615Smarc * Figure out how many characters can be stored on one "line" of offscreen memory
3727*34615Smarc */
3728*34615Smarc 	    max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
3729*34615Smarc 	    if ((CHARS/2 + CHARS%2) < max_chars_line)
3730*34615Smarc 		return;
3731*34615Smarc 	    max_chars_line = (CHARS/2 + CHARS%2) - max_chars_line; /* 95 - 64 */
3732*34615Smarc 	    /* Paranoia check to see if 3rd row may be needed */
3733*34615Smarc 	    if (max_chars_line > (MAX_SCREEN_X/(CHAR_WIDTH*2)))
3734*34615Smarc 	    	max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
3735*34615Smarc 
3736*34615Smarc 
3737*34615Smarc /*-----------------------------------------------*/
3738*34615Smarc 
3739*34615Smarc 	adder->destination_x = FONT_X;
3740*34615Smarc 	adder->destination_y = FONT_Y - CHAR_HEIGHT;
3741*34615Smarc 	adder->fast_dest_dx = max_chars_line * CHAR_WIDTH * 2;
3742*34615Smarc 	adder->slow_dest_dy = CHAR_HEIGHT;
3743*34615Smarc 
3744*34615Smarc /*---------------------------------------
3745*34615Smarc * setup for processor to bitmap xfer  */
3746*34615Smarc 
3747*34615Smarc 	write_ID(adder, CS_UPDATE_MASK, 0x0001);
3748*34615Smarc 	adder->cmd = PBT | OCRB | 2 | DTE | 2;
3749*34615Smarc 
3750*34615Smarc /*-----------------------------------------------
3751*34615Smarc * iteratively do the processor to bitmap xfer */
3752*34615Smarc 
3753*34615Smarc 	for (i = 0; i < ROWS; ++i) {
3754*34615Smarc 
3755*34615Smarc 	    /* PTOB a scan line */
3756*34615Smarc 
3757*34615Smarc 	    for (j = 0, k = i; j < max_chars_line; ++j) {
3758*34615Smarc 
3759*34615Smarc 		/* PTOB one scan of a char cell */
3760*34615Smarc 
3761*34615Smarc 		packed = q_font[k + FONT_OFFSET];
3762*34615Smarc 		k += ROWS;
3763*34615Smarc 		packed |= ((short)q_font[k + FONT_OFFSET] << 8);
3764*34615Smarc 		k += ROWS;
3765*34615Smarc 
3766*34615Smarc 		wait_status(adder, TX_READY);
3767*34615Smarc 		adder->id_data = packed;
3768*34615Smarc 	    }
3769*34615Smarc 	}
3770*34615Smarc 
377130391Skarels }  /* ldfont */
377230391Skarels 
377330391Skarels /*********************************************************************
377430391Skarels *
377530391Skarels *	led_control()... twiddle LK-201 LED's
377630391Skarels *
377730391Skarels **********************************************************************
377830391Skarels *
377930391Skarels *	led_control(unit, cmd, led_mask);
378030391Skarels *	u_int unit;	QDSS number
378130391Skarels *	int cmd;	LED enable/disable command
378230391Skarels *	int led_mask;	which LED(s) to twiddle
378330391Skarels *
378430391Skarels *************/
378530391Skarels 
378630391Skarels led_control(unit, cmd, led_mask)
378730391Skarels u_int unit;
378830391Skarels int cmd;
378930391Skarels int led_mask;
379030391Skarels {
379130391Skarels 	register int i;
379230391Skarels 	register int status;
379330391Skarels 	register struct duart *duart;
379430391Skarels 
379530391Skarels 	duart = (struct duart *) qdmap[unit].duart;
379630391Skarels 
379730391Skarels 	for (i = 1000; i > 0; --i) {
379830391Skarels 	    if ((status = duart->statusA) & XMT_RDY) {
379930391Skarels 		duart->dataA = cmd;
380030391Skarels 		break;
380130391Skarels 	    }
380230391Skarels 	}
380330391Skarels 
380430391Skarels 	for (i = 1000; i > 0; --i) {
380530391Skarels 	    if ((status = duart->statusA) & XMT_RDY) {
380630391Skarels 		duart->dataA = led_mask;
380730391Skarels 		break;
380830391Skarels 	    }
380930391Skarels 	}
381030391Skarels 
381130391Skarels 	if (i == 0)
381230391Skarels 	    return(BAD);
381330391Skarels 
381430391Skarels 	return(GOOD);
381530391Skarels 
381630391Skarels } /* led_control */
381730391Skarels 
381830391Skarels /*******************************************************************
381930391Skarels *
382030391Skarels *	scroll_up()... move the screen up one character height
382130391Skarels *
382230391Skarels ********************************************************************
382330391Skarels *
382430391Skarels *	calling convention:
382530391Skarels *
382630391Skarels *		scroll_up(adder);
382730391Skarels *		struct adder *adder;	;address of adder
382830391Skarels *
382930391Skarels ********/
383030391Skarels 
383130391Skarels scroll_up(adder)
383230391Skarels register struct adder *adder;
383330391Skarels {
383430391Skarels 
3835*34615Smarc /*------------------------------------------
3836*34615Smarc * setup VIPER operand control registers  */
383730391Skarels 
383830391Skarels 	wait_status(adder, ADDRESS_COMPLETE);
383930391Skarels 
384030391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x00FF);  /* select all planes */
384130391Skarels 
384230391Skarels 	write_ID(adder, MASK_1, 0xFFFF);
384330391Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
384430391Skarels 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
384530391Skarels 
384630391Skarels 	write_ID(adder, SRC1_OCR_B,
384730391Skarels 			EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY);
384830391Skarels 	write_ID(adder, DST_OCR_B,
384930391Skarels 			EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
385030391Skarels 
3851*34615Smarc /*----------------------------------------
3852*34615Smarc * load DESTINATION origin and vectors  */
385330391Skarels 
385430391Skarels 	adder->fast_dest_dy = 0;
385530391Skarels 	adder->slow_dest_dx = 0;
385630391Skarels 	adder->error_1 = 0;
385730391Skarels 	adder->error_2 = 0;
385830391Skarels 
385930391Skarels 	adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL;
386030391Skarels 
386130391Skarels 	adder->destination_x = 0;
386230391Skarels 	adder->fast_dest_dx = 1024;
386330391Skarels 
386430391Skarels 	adder->destination_y = 0;
386530391Skarels 	adder->slow_dest_dy = 864 - CHAR_HEIGHT;
386630391Skarels 
3867*34615Smarc /*-----------------------------------
3868*34615Smarc * load SOURCE origin and vectors  */
386930391Skarels 
387030391Skarels 	adder->source_1_x = 0;
387130391Skarels 	adder->source_1_dx = 1024;
387230391Skarels 
387330391Skarels 	adder->source_1_y = 0 + CHAR_HEIGHT;
387430391Skarels 	adder->source_1_dy = 864 - CHAR_HEIGHT;
387530391Skarels 
387630391Skarels 	write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
387730391Skarels 	adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE;
387830391Skarels 
3879*34615Smarc /*--------------------------------------------
3880*34615Smarc * do a rectangle clear of last screen line */
388130391Skarels 
388230391Skarels 	write_ID(adder, MASK_1, 0xffff);
388330391Skarels 	write_ID(adder, SOURCE, 0xffff);
388430391Skarels 	write_ID(adder,DST_OCR_B,
388530391Skarels 		(EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY));
388630391Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 0);
388730391Skarels 	adder->error_1 = 0;
388830391Skarels 	adder->error_2 = 0;
388930391Skarels 	adder->slow_dest_dx = 0;	/* set up the width of	*/
389030391Skarels 	adder->slow_dest_dy = CHAR_HEIGHT;	/* rectangle */
389130391Skarels 
389230391Skarels 	adder->rasterop_mode = (NORMAL | DST_WRITE_ENABLE) ;
389330391Skarels 	wait_status(adder, RASTEROP_COMPLETE);
389430391Skarels 	adder->destination_x = 0;
389530391Skarels 	adder->destination_y = 864 - CHAR_HEIGHT;
389630391Skarels 
389730391Skarels 	adder->fast_dest_dx = 1024;	/* set up the height	*/
389830391Skarels 	adder->fast_dest_dy = 0;	/* of rectangle 	*/
389930391Skarels 
390030391Skarels 	write_ID(adder, LU_FUNCTION_R2, (FULL_SRC_RESOLUTION | LF_SOURCE));
390130391Skarels 	adder->cmd = (RASTEROP | OCRB | LF_R2 | DTE ) ;
390230391Skarels 
390330391Skarels } /* scroll_up */
390430391Skarels 
390530391Skarels /********************************************************************
390630391Skarels *
390730391Skarels *	init_shared()... init shared memory pointers and structures
390830391Skarels *
390930391Skarels *********************************************************************
391030391Skarels *
391130391Skarels *	calling convention:
391230391Skarels *
391330391Skarels *		init_shared(unit);
391430391Skarels *		u_int unit;
391530391Skarels *
391630391Skarels ****************/
391730391Skarels 
391830391Skarels init_shared(unit)
391930391Skarels register u_int unit;
392030391Skarels {
392130391Skarels 	register struct dga *dga;
392230391Skarels 
392330391Skarels 	dga = (struct dga *) qdmap[unit].dga;
392430391Skarels 
3925*34615Smarc /*--------------------------------------------------
3926*34615Smarc * initialize the event queue pointers and header */
392730391Skarels 
392830391Skarels 	eq_header[unit] = (struct qdinput *)
392930391Skarels 			  ((((int)event_shared & ~(0x01FF)) + 512)
393030391Skarels 			   + (EVENT_BUFSIZE * unit));
393130391Skarels 
393230391Skarels 	eq_header[unit]->curs_pos.x = 0;
393330391Skarels 	eq_header[unit]->curs_pos.y = 0;
393430391Skarels 
393530391Skarels 	dga->x_cursor = TRANX(eq_header[unit]->curs_pos.x);
393630391Skarels 	dga->y_cursor = TRANY(eq_header[unit]->curs_pos.y);
393730391Skarels 
393830391Skarels 	eq_header[unit]->curs_box.left = 0;
393930391Skarels 	eq_header[unit]->curs_box.right = 0;
394030391Skarels 	eq_header[unit]->curs_box.top = 0;
394130391Skarels 	eq_header[unit]->curs_box.bottom = 0;
394230391Skarels 
3943*34615Smarc /*---------------------------------------------------------
3944*34615Smarc * assign a pointer to the DMA I/O buffer for this QDSS. */
394530391Skarels 
394630391Skarels 	DMAheader[unit] = (struct DMAreq_header *)
394730391Skarels 			  (((int)(&DMA_shared[0] + 512) & ~0x1FF)
394830391Skarels 			   + (DMAbuf_size * unit));
394930391Skarels 
395030391Skarels 	DMAheader[unit]->DMAreq = (struct DMAreq *) ((int)DMAheader[unit]
395130391Skarels 				  + sizeof(struct DMAreq_header));
395230391Skarels 
395330391Skarels 	DMAheader[unit]->QBAreg = 0;
395430391Skarels 	DMAheader[unit]->status = 0;
395530391Skarels 	DMAheader[unit]->shared_size = DMAbuf_size;
395630391Skarels 	DMAheader[unit]->used = 0;
395730391Skarels 	DMAheader[unit]->size = 10;	/* default = 10 requests */
395830391Skarels 	DMAheader[unit]->oldest = 0;
395930391Skarels 	DMAheader[unit]->newest = 0;
396030391Skarels 
3961*34615Smarc /*-----------------------------------------------------------
3962*34615Smarc * assign a pointer to the scroll structure for this QDSS. */
396330391Skarels 
396430391Skarels 	scroll[unit] = (struct scroll *)
396530391Skarels 			 (((int)(&scroll_shared[0] + 512) & ~0x1FF)
396630391Skarels 			   + (sizeof(struct scroll) * unit));
396730391Skarels 
396830391Skarels 	scroll[unit]->status = 0;
396930391Skarels 	scroll[unit]->viper_constant = 0;
397030391Skarels 	scroll[unit]->y_scroll_constant = 0;
397130391Skarels 	scroll[unit]->y_offset = 0;
397230391Skarels 	scroll[unit]->x_index_pending = 0;
397330391Skarels 	scroll[unit]->y_index_pending = 0;
397430391Skarels 
3975*34615Smarc /*----------------------------------------------------------------
3976*34615Smarc * assign a pointer to the color map write buffer for this QDSS */
397730391Skarels 
397830391Skarels 	color_buf[unit] = (struct color_buf *)
397930391Skarels 			   (((int)(&color_shared[0] + 512) & ~0x1FF)
398030391Skarels 			    + (COLOR_BUFSIZ * unit));
398130391Skarels 
398230391Skarels 	color_buf[unit]->status = 0;
398330391Skarels 	color_buf[unit]->count = 0;
398430391Skarels 
398530391Skarels } /* init_shared */
398630391Skarels 
398730391Skarels /*********************************************************************
398830391Skarels *
398930391Skarels *	setup_dragon()... init the ADDER, VIPER, bitmaps, & color map
399030391Skarels *
399130391Skarels **********************************************************************
399230391Skarels *
399330391Skarels *	calling convention:
399430391Skarels *
399530391Skarels *		setup_dragon();
399630391Skarels *
399730391Skarels *	return: NONE
399830391Skarels *
399930391Skarels ************************/
400030391Skarels 
400130391Skarels setup_dragon(unit)
400230391Skarels u_int unit;
400330391Skarels {
400430391Skarels 
400530391Skarels 	register struct adder *adder;
400630391Skarels 	register struct dga *dga;
400730391Skarels 	short *memcsr;
400830391Skarels 
400930391Skarels 	int i;			/* general purpose variables */
401030391Skarels 	int status;
401130391Skarels 
401230391Skarels 	short top;		/* clipping/scrolling boundaries */
401330391Skarels 	short bottom;
401430391Skarels 	short right;
401530391Skarels 	short left;
401630391Skarels 
401730391Skarels 	short *red;		/* color map pointers */
401830391Skarels 	short *green;
401930391Skarels 	short *blue;
402030391Skarels 
4021*34615Smarc /*------------------
4022*34615Smarc * init for setup */
402330391Skarels 
402430391Skarels 	adder = (struct adder *) qdmap[unit].adder;
402530391Skarels 	dga = (struct dga *) qdmap[unit].dga;
402630391Skarels 	memcsr = (short *) qdmap[unit].memcsr;
402730391Skarels 
402830391Skarels 	dga->csr &= ~(DMA_IE | 0x700);	/* halt DMA and kill the intrpts */
402930391Skarels 	*memcsr = SYNC_ON;		/* blank screen and turn off LED's */
403030391Skarels 	adder->command = CANCEL;
403130391Skarels 
4032*34615Smarc /*----------------------
4033*34615Smarc * set monitor timing */
403430391Skarels 
403530391Skarels 	adder->x_scan_count_0 = 0x2800;
403630391Skarels 	adder->x_scan_count_1 = 0x1020;
403730391Skarels 	adder->x_scan_count_2 = 0x003A;
403830391Skarels 	adder->x_scan_count_3 = 0x38F0;
403930391Skarels 	adder->x_scan_count_4 = 0x6128;
404030391Skarels 	adder->x_scan_count_5 = 0x093A;
404130391Skarels 	adder->x_scan_count_6 = 0x313C;
404230391Skarels 	adder->sync_phase_adj = 0x0100;
404330391Skarels 	adder->x_scan_conf = 0x00C8;
404430391Skarels 
4045*34615Smarc /*---------------------------------------------------------
4046*34615Smarc * got a bug in secound pass ADDER! lets take care of it */
404730391Skarels 
404830391Skarels 	/* normally, just use the code in the following bug fix code, but to
404930391Skarels 	* make repeated demos look pretty, load the registers as if there was
405030391Skarels 	* no bug and then test to see if we are getting sync */
405130391Skarels 
405230391Skarels 	adder->y_scan_count_0 = 0x135F;
405330391Skarels 	adder->y_scan_count_1 = 0x3363;
405430391Skarels 	adder->y_scan_count_2 = 0x2366;
405530391Skarels 	adder->y_scan_count_3 = 0x0388;
405630391Skarels 
405730391Skarels 	/* if no sync, do the bug fix code */
405830391Skarels 
405930391Skarels 	if (wait_status(adder, VSYNC) == BAD) {
406030391Skarels 
406130391Skarels 	    /* first load all Y scan registers with very short frame and
406230391Skarels 	    * wait for scroll service.	This guarantees at least one SYNC
406330391Skarels 	    * to fix the pass 2 Adder initialization bug (synchronizes
406430391Skarels 	    * XCINCH with DMSEEDH) */
406530391Skarels 
406630391Skarels 	    adder->y_scan_count_0 = 0x01;
406730391Skarels 	    adder->y_scan_count_1 = 0x01;
406830391Skarels 	    adder->y_scan_count_2 = 0x01;
406930391Skarels 	    adder->y_scan_count_3 = 0x01;
407030391Skarels 
407130391Skarels 	    wait_status(adder, VSYNC);	/* delay at least 1 full frame time */
407230391Skarels 	    wait_status(adder, VSYNC);
407330391Skarels 
407430391Skarels 	    /* now load the REAL sync values (in reverse order just to
407530391Skarels 	    *  be safe.  */
407630391Skarels 
407730391Skarels 	    adder->y_scan_count_3 = 0x0388;
407830391Skarels 	    adder->y_scan_count_2 = 0x2366;
407930391Skarels 	    adder->y_scan_count_1 = 0x3363;
408030391Skarels 	    adder->y_scan_count_0 = 0x135F;
408130391Skarels 	}
408230391Skarels 
408330391Skarels 	*memcsr = SYNC_ON | UNBLANK;	/* turn off leds and turn on video */
408430391Skarels 
4085*34615Smarc /*----------------------------
4086*34615Smarc * zero the index registers */
408730391Skarels 
408830391Skarels 	adder->x_index_pending = 0;
408930391Skarels 	adder->y_index_pending = 0;
409030391Skarels 	adder->x_index_new = 0;
409130391Skarels 	adder->y_index_new = 0;
409230391Skarels 	adder->x_index_old = 0;
409330391Skarels 	adder->y_index_old = 0;
409430391Skarels 
409530391Skarels 	adder->pause = 0;
409630391Skarels 
4097*34615Smarc /*----------------------------------------
4098*34615Smarc * set rasterop mode to normal pen down */
409930391Skarels 
410030391Skarels 	adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL;
410130391Skarels 
4102*34615Smarc /*--------------------------------------------------
4103*34615Smarc * set the rasterop registers to a default values */
410430391Skarels 
410530391Skarels 	adder->source_1_dx = 1;
410630391Skarels 	adder->source_1_dy = 1;
410730391Skarels 	adder->source_1_x = 0;
410830391Skarels 	adder->source_1_y = 0;
410930391Skarels 	adder->destination_x = 0;
411030391Skarels 	adder->destination_y = 0;
411130391Skarels 	adder->fast_dest_dx = 1;
411230391Skarels 	adder->fast_dest_dy = 0;
411330391Skarels 	adder->slow_dest_dx = 0;
411430391Skarels 	adder->slow_dest_dy = 1;
411530391Skarels 	adder->error_1 = 0;
411630391Skarels 	adder->error_2 = 0;
411730391Skarels 
4118*34615Smarc /*------------------------
4119*34615Smarc * scale factor = unity */
412030391Skarels 
412130391Skarels 	adder->fast_scale = UNITY;
412230391Skarels 	adder->slow_scale = UNITY;
412330391Skarels 
4124*34615Smarc /*-------------------------------
4125*34615Smarc * set the source 2 parameters */
412630391Skarels 
412730391Skarels 	adder->source_2_x = 0;
412830391Skarels 	adder->source_2_y = 0;
412930391Skarels 	adder->source_2_size = 0x0022;
413030391Skarels 
4131*34615Smarc /*-----------------------------------------------
4132*34615Smarc * initialize plane addresses for eight vipers */
413330391Skarels 
413430391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0001);
413530391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0000);
413630391Skarels 
413730391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0002);
413830391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0001);
413930391Skarels 
414030391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0004);
414130391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0002);
414230391Skarels 
414330391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0008);
414430391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0003);
414530391Skarels 
414630391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0010);
414730391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0004);
414830391Skarels 
414930391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0020);
415030391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0005);
415130391Skarels 
415230391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0040);
415330391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0006);
415430391Skarels 
415530391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0080);
415630391Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0007);
415730391Skarels 
415830391Skarels 	/* initialize the external registers. */
415930391Skarels 
416030391Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x00FF);
416130391Skarels 	write_ID(adder, CS_SCROLL_MASK, 0x00FF);
416230391Skarels 
416330391Skarels 	/* initialize resolution mode */
416430391Skarels 
416530391Skarels 	write_ID(adder, MEMORY_BUS_WIDTH, 0x000C);     /* bus width = 16 */
416630391Skarels 	write_ID(adder, RESOLUTION_MODE, 0x0000);      /* one bit/pixel */
416730391Skarels 
416830391Skarels 	/* initialize viper registers */
416930391Skarels 
417030391Skarels 	write_ID(adder, SCROLL_CONSTANT, SCROLL_ENABLE|VIPER_LEFT|VIPER_UP);
417130391Skarels 	write_ID(adder, SCROLL_FILL, 0x0000);
417230391Skarels 
4173*34615Smarc /*----------------------------------------------------
4174*34615Smarc * set clipping and scrolling limits to full screen */
417530391Skarels 
417630391Skarels 	for ( i = 1000, adder->status = 0
417730391Skarels 	    ; i > 0  &&  !((status = adder->status) & ADDRESS_COMPLETE)
417830391Skarels 	    ; --i);
417930391Skarels 
418030391Skarels 	if (i == 0)
4181*34615Smarc 	    printf("\nqd%d: setup_dragon: timeout on ADDRESS_COMPLETE",unit);
418230391Skarels 
418330391Skarels 	top = 0;
418430391Skarels 	bottom = 2048;
418530391Skarels 	left = 0;
418630391Skarels 	right = 1024;
418730391Skarels 
418830391Skarels 	adder->x_clip_min = left;
418930391Skarels 	adder->x_clip_max = right;
419030391Skarels 	adder->y_clip_min = top;
419130391Skarels 	adder->y_clip_max = bottom;
419230391Skarels 
419330391Skarels 	adder->scroll_x_min = left;
419430391Skarels 	adder->scroll_x_max = right;
419530391Skarels 	adder->scroll_y_min = top;
419630391Skarels 	adder->scroll_y_max = bottom;
419730391Skarels 
419830391Skarels 	wait_status(adder, VSYNC);	/* wait at LEAST 1 full frame */
419930391Skarels 	wait_status(adder, VSYNC);
420030391Skarels 
420130391Skarels 	adder->x_index_pending = left;
420230391Skarels 	adder->y_index_pending = top;
420330391Skarels 	adder->x_index_new = left;
420430391Skarels 	adder->y_index_new = top;
420530391Skarels 	adder->x_index_old = left;
420630391Skarels 	adder->y_index_old = top;
420730391Skarels 
420830391Skarels 	for ( i = 1000, adder->status = 0
420930391Skarels 	    ; i > 0  &&  !((status = adder->status) & ADDRESS_COMPLETE)
421030391Skarels 	    ; --i);
421130391Skarels 
421230391Skarels 	if (i == 0)
4213*34615Smarc 	    printf("\nqd%d: setup_dragon: timeout on ADDRESS_COMPLETE",unit);
421430391Skarels 
421530391Skarels 	write_ID(adder, LEFT_SCROLL_MASK, 0x0000);
421630391Skarels 	write_ID(adder, RIGHT_SCROLL_MASK, 0x0000);
421730391Skarels 
4218*34615Smarc /*------------------------------------------------------------
4219*34615Smarc * set source and the mask register to all ones (ie: white) */
422030391Skarels 
422130391Skarels 	write_ID(adder, SOURCE, 0xFFFF);
422230391Skarels 	write_ID(adder, MASK_1, 0xFFFF);
422330391Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
422430391Skarels 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
422530391Skarels 
4226*34615Smarc /*--------------------------------------------------------------
4227*34615Smarc * initialize Operand Control Register banks for fill command */
422830391Skarels 
422930391Skarels 	write_ID(adder, SRC1_OCR_A, EXT_NONE | INT_M1_M2  | NO_ID | WAIT);
423030391Skarels 	write_ID(adder, SRC2_OCR_A, EXT_NONE | INT_SOURCE | NO_ID | NO_WAIT);
423130391Skarels 	write_ID(adder, DST_OCR_A, EXT_NONE | INT_NONE	 | NO_ID | NO_WAIT);
423230391Skarels 
423330391Skarels 	write_ID(adder, SRC1_OCR_B, EXT_NONE | INT_SOURCE | NO_ID | WAIT);
423430391Skarels 	write_ID(adder, SRC2_OCR_B, EXT_NONE | INT_M1_M2  | NO_ID | NO_WAIT);
423530391Skarels 	write_ID(adder, DST_OCR_B, EXT_NONE | INT_NONE | NO_ID | NO_WAIT);
423630391Skarels 
4237*34615Smarc /*------------------------------------------------------------------
4238*34615Smarc * init Logic Unit Function registers, (these are just common values,
423930391Skarels * and may be changed as required).  */
424030391Skarels 
424130391Skarels 	write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
424230391Skarels 	write_ID(adder, LU_FUNCTION_R2, FULL_SRC_RESOLUTION | LF_SOURCE | INV_M1_M2);
424330391Skarels 	write_ID(adder, LU_FUNCTION_R3, FULL_SRC_RESOLUTION | LF_D_OR_S);
424430391Skarels 	write_ID(adder, LU_FUNCTION_R4, FULL_SRC_RESOLUTION | LF_D_XOR_S);
424530391Skarels 
4246*34615Smarc /*----------------------------------------
4247*34615Smarc * load the color map for black & white */
424830391Skarels 
424930391Skarels 	for ( i = 0, adder->status = 0
425030391Skarels 	    ; i < 10000  &&  !((status = adder->status) & VSYNC)
425130391Skarels 	    ; ++i);
425230391Skarels 
425330391Skarels 	if (i == 0)
4254*34615Smarc 	    printf("\nqd%d: setup_dragon: timeout on VSYNC", unit);
425530391Skarels 
425630391Skarels 	red = (short *) qdmap[unit].red;
425730391Skarels 	green = (short *) qdmap[unit].green;
425830391Skarels 	blue = (short *) qdmap[unit].blue;
425930391Skarels 
426030391Skarels 	*red++ = 0x00;			/* black */
426130391Skarels 	*green++ = 0x00;
426230391Skarels 	*blue++ = 0x00;
426330391Skarels 
426430391Skarels 	*red-- = 0xFF;			/* white */
426530391Skarels 	*green-- = 0xFF;
426630391Skarels 	*blue-- = 0xFF;
426730391Skarels 
426830391Skarels 	/*----------------------------------
426930391Skarels 	* set color map for mouse cursor */
427030391Skarels 
427130391Skarels 	red += 254;
427230391Skarels 	green += 254;
427330391Skarels 	blue += 254;
427430391Skarels 
427530391Skarels 	*red++ = 0x00;			/* black */
427630391Skarels 	*green++ = 0x00;
427730391Skarels 	*blue++ = 0x00;
427830391Skarels 
427930391Skarels 	*red = 0xFF;			/* white */
428030391Skarels 	*green = 0xFF;
428130391Skarels 	*blue = 0xFF;
428230391Skarels 
428330391Skarels 	return(0);
428430391Skarels 
428530391Skarels } /* setup_dragon */
428630391Skarels 
428730391Skarels /******************************************************************
428830391Skarels *
428930391Skarels *	setup_input()... init the DUART and set defaults in input
429030391Skarels *			 devices
429130391Skarels *
429230391Skarels *******************************************************************
429330391Skarels *
429430391Skarels *	calling convention:
429530391Skarels *
429630391Skarels *		setup_input(unit);
429730391Skarels *
429830391Skarels *	where: unit - is the QDSS unit number to be setup
429930391Skarels *
430030391Skarels *********/
430130391Skarels 
430230391Skarels setup_input(unit)
430330391Skarels u_int unit;
430430391Skarels {
430530391Skarels 	register struct duart *duart;	/* DUART register structure pointer */
430630391Skarels 	register int i; 		/* scratch variable */
430730391Skarels 	register int bits;
430830391Skarels 
430930391Skarels 	char id_byte;
431030391Skarels 	short status;
431130391Skarels 
4312*34615Smarc /*---------------
4313*34615Smarc * init stuff */
431430391Skarels 
431530391Skarels 	duart = (struct duart *) qdmap[unit].duart;
431630391Skarels 	duart->imask = 0;
431730391Skarels 
4318*34615Smarc /*---------------------------------------------
4319*34615Smarc * setup the DUART for kbd & pointing device */
432030391Skarels 
432130391Skarels 	duart->cmdA = RESET_M;	  /* reset mode reg ptr for kbd */
432230391Skarels 	duart->modeA = 0x13;	  /* 8 bits, no parity, rcv IE, */
432330391Skarels 				  /* no RTS control,char error mode */
432430391Skarels 	duart->modeA = 0x07;	  /* 1 stop bit,CTS does not IE XMT */
432530391Skarels 				  /* no RTS control,no echo or loop */
432630391Skarels 	duart->cmdB = RESET_M;	  /* reset mode reg pntr for host */
432730391Skarels 	duart->modeB = 0x07;	  /* 8 bits, odd parity, rcv IE.. */
432830391Skarels 				  /* ..no RTS cntrl, char error mode */
432930391Skarels 	duart->modeB = 0x07;	  /* 1 stop bit,CTS does not IE XMT */
433030391Skarels 				  /* no RTS control,no echo or loop */
433130391Skarels 
433230391Skarels 	duart->auxctl = 0x00;	  /* baud rate set 1 */
433330391Skarels 
433430391Skarels 	duart->clkselA = 0x99;	  /* 4800 baud for kbd */
433530391Skarels 	duart->clkselB = 0x99;	  /* 4800 baud for mouse */
433630391Skarels 
433730391Skarels 	/* reset everything for keyboard */
433830391Skarels 
433930391Skarels 	for (bits = RESET_M; bits < START_BREAK; bits += 0x10)
434030391Skarels 	    duart->cmdA = bits;
434130391Skarels 
434230391Skarels 	/* reset everything for host */
434330391Skarels 
434430391Skarels 	for (bits = RESET_M; bits < START_BREAK; bits += 0x10)
434530391Skarels 	     duart->cmdB = bits;
434630391Skarels 
434730391Skarels 	duart->cmdA = EN_RCV | EN_XMT; /* enbl xmt & rcv for kbd */
434830391Skarels 	duart->cmdB = EN_RCV | EN_XMT; /* enbl xmt & rcv for pointer device */
434930391Skarels 
4350*34615Smarc /*--------------------------------------------
4351*34615Smarc * init keyboard defaults (DUART channel A) */
435230391Skarels 
435330391Skarels 	for (i = 500; i > 0; --i) {
435430391Skarels 	    if ((status = duart->statusA) & XMT_RDY) {
435530391Skarels 		duart->dataA = LK_DEFAULTS;
435630391Skarels 		break;
435730391Skarels 	    }
435830391Skarels 	}
435930391Skarels 
436030391Skarels 	for (i = 100000; i > 0; --i) {
436130391Skarels 	    if ((status = duart->statusA) & RCV_RDY) {
436230391Skarels 		break;
436330391Skarels 	    }
436430391Skarels 	}
436530391Skarels 
436630391Skarels 	status = duart->dataA;		/* flush the ACK */
436730391Skarels 
4368*34615Smarc /*--------------------------------
4369*34615Smarc * identify the pointing device */
437030391Skarels 
437130391Skarels 	for (i = 500; i > 0; --i) {
437230391Skarels 	    if ((status = duart->statusB) & XMT_RDY) {
437330391Skarels 		duart->dataB = SELF_TEST;
437430391Skarels 		break;
437530391Skarels 	    }
437630391Skarels 	}
437730391Skarels 
437830391Skarels 	/*-----------------------------------------
437930391Skarels 	* wait for 1st byte of self test report */
438030391Skarels 
438130391Skarels 	for (i = 100000; i > 0; --i) {
438230391Skarels 	    if ((status = duart->statusB) & RCV_RDY) {
438330391Skarels 		break;
438430391Skarels 	    }
438530391Skarels 	}
438630391Skarels 
438730391Skarels 	if (i == 0) {
4388*34615Smarc 	    printf("\nqd[%d]: setup_input: timeout on 1st byte of self test",unit);
438930391Skarels 	    goto OUT;
439030391Skarels 	}
439130391Skarels 
439230391Skarels 	status = duart->dataB;
439330391Skarels 
439430391Skarels 	/*-----------------------------------------
439530391Skarels 	* wait for ID byte of self test report	*/
439630391Skarels 
439730391Skarels 	for (i = 100000; i > 0; --i) {
439830391Skarels 	    if ((status = duart->statusB) & RCV_RDY) {
439930391Skarels 		break;
440030391Skarels 	    }
440130391Skarels 	}
440230391Skarels 
440330391Skarels 	if (i == 0) {
4404*34615Smarc 	    printf("\nqd[%d]: setup_input: timeout on 2nd byte of self test", unit);
440530391Skarels 	    goto OUT;
440630391Skarels 	}
440730391Skarels 
440830391Skarels 	id_byte = duart->dataB;
440930391Skarels 
441030391Skarels 	/*------------------------------------
441130391Skarels 	* wait for other bytes to come in  */
441230391Skarels 
441330391Skarels 	for (i = 100000; i > 0; --i) {
441430391Skarels 	    if ((status = duart->statusB) & RCV_RDY) {
441530391Skarels 		status = duart->dataB;
441630391Skarels 		break;
441730391Skarels 	    }
441830391Skarels 	}
441930391Skarels 
442030391Skarels 	if (i == 0) {
4421*34615Smarc 	    printf("\nqd[%d]: setup_input: timeout on 3rd byte of self test", unit);
442230391Skarels 	    goto OUT;
442330391Skarels 	}
442430391Skarels 
442530391Skarels 	for (i = 100000; i > 0; --i) {
442630391Skarels 	    if ((status = duart->statusB) & RCV_RDY) {
442730391Skarels 		status = duart->dataB;
442830391Skarels 		break;
442930391Skarels 	    }
443030391Skarels 	}
443130391Skarels 
443230391Skarels 	if (i == 0) {
4433*34615Smarc 	    printf("\nqd[%d]: setup_input: timeout on 4th byte of self test\n", unit);
443430391Skarels 	    goto OUT;
443530391Skarels 	}
443630391Skarels 
443730391Skarels 	/*----------------------------------------------
443830391Skarels 	* flag pointing device type and set defaults */
443930391Skarels 
444030391Skarels 	for (i=100000; i>0; --i);
444130391Skarels 
444230391Skarels 	if ((id_byte & 0x0F) != TABLET_ID) {
444330391Skarels 
444430391Skarels 	    qdflags[unit].pntr_id = MOUSE_ID;
444530391Skarels 
444630391Skarels 	    for (i = 500; i > 0; --i) {
444730391Skarels 		if ((status = duart->statusB) & XMT_RDY) {
444830391Skarels 		    duart->dataB = INC_STREAM_MODE;
444930391Skarels 		    break;
445030391Skarels 		}
445130391Skarels 	    }
445230391Skarels 	} else {
445330391Skarels 
445430391Skarels 	    qdflags[unit].pntr_id = TABLET_ID;
445530391Skarels 
445630391Skarels 	    for (i = 500; i > 0; --i) {
445730391Skarels 		if ((status = duart->statusB) & XMT_RDY) {
445830391Skarels 		    duart->dataB = T_STREAM;
445930391Skarels 		    break;
446030391Skarels 		}
446130391Skarels 	    }
446230391Skarels 	}
446330391Skarels 
4464*34615Smarc /*--------
4465*34615Smarc * exit */
446630391Skarels 
446730391Skarels OUT:
446830391Skarels 	duart->imask = qdflags[unit].duart_imask;
446930391Skarels 	return(0);
447030391Skarels 
447130391Skarels } /* setup_input */
447230391Skarels 
447330391Skarels /**********************************************************************
447430391Skarels *
447530391Skarels *	wait_status()... delay for at least one display frame time
447630391Skarels *
447730391Skarels ***********************************************************************
447830391Skarels *
447930391Skarels *	calling convention:
448030391Skarels *
448130391Skarels *		wait_status(adder, mask);
448230391Skarels *		struct *adder adder;
448330391Skarels *		int mask;
448430391Skarels *
448530391Skarels *	return: BAD means that we timed out without ever seeing the
448630391Skarels *		      vertical sync status bit
448730391Skarels *		GOOD otherwise
448830391Skarels *
448930391Skarels **************/
449030391Skarels 
449130391Skarels wait_status(adder, mask)
449230391Skarels register struct adder *adder;
449330391Skarels register int mask;
449430391Skarels {
449530391Skarels 	register short status;
449630391Skarels 	int i;
449730391Skarels 
449830391Skarels 	for ( i = 10000, adder->status = 0
449930391Skarels 	    ; i > 0  &&  !((status = adder->status) & mask)
450030391Skarels 	    ; --i);
450130391Skarels 
450230391Skarels 	if (i == 0) {
4503*34615Smarc 	    printf("\nwait_status: timeout polling for 0x%x in adder->status", mask);
450430391Skarels 	    return(BAD);
450530391Skarels 	}
450630391Skarels 
450730391Skarels 	return(GOOD);
450830391Skarels 
450930391Skarels } /* wait_status */
451030391Skarels 
451130391Skarels /**********************************************************************
451230391Skarels *
451330391Skarels *	write_ID()... write out onto the ID bus
451430391Skarels *
451530391Skarels ***********************************************************************
451630391Skarels *
451730391Skarels *	calling convention:
451830391Skarels *
451930391Skarels *		struct *adder adder;	;pntr to ADDER structure
452030391Skarels *		short adrs;		;VIPER address
452130391Skarels *		short data;		;data to be written
452230391Skarels *		write_ID(adder);
452330391Skarels *
452430391Skarels *	return: BAD means that we timed out waiting for status bits
452530391Skarels *		      VIPER-access-specific status bits
452630391Skarels *		GOOD otherwise
452730391Skarels *
452830391Skarels **************/
452930391Skarels 
453030391Skarels write_ID(adder, adrs, data)
453130391Skarels register struct adder *adder;
453230391Skarels register short adrs;
453330391Skarels register short data;
453430391Skarels {
453530391Skarels 	int i;
453630391Skarels 	short status;
453730391Skarels 
4538*34615Smarc 	for ( i = 100000, adder->status = 0
4539*34615Smarc 	    ; i > 0  &&  !((status = adder->status) & ADDRESS_COMPLETE)
4540*34615Smarc 	    ; --i);
454130391Skarels 
454230391Skarels 	if (i == 0)
454330391Skarels 	    goto ERR;
454430391Skarels 
4545*34615Smarc 	for ( i = 100000, adder->status = 0
4546*34615Smarc 	    ; i > 0  &&  !((status = adder->status) & TX_READY)
4547*34615Smarc 	    ; --i);
454830391Skarels 
454930391Skarels 	if (i > 0) {
455030391Skarels 	    adder->id_data = data;
455130391Skarels 	    adder->command = ID_LOAD | adrs;
455230391Skarels 	    return(GOOD);
455330391Skarels 	}
455430391Skarels 
455530391Skarels ERR:
4556*34615Smarc 	printf("\nwrite_ID: timeout trying to write to VIPER");
455730391Skarels 	return(BAD);
455830391Skarels 
455930391Skarels } /* write_ID */
4560*34615Smarc 
456134511Smarc #endif
4562