xref: /original-bsd/sys/vax/uba/qd.c (revision e977faad)
1006e9885Smarc /*
2006e9885Smarc  * Copyright (c) 1982, 1986 Regents of the University of California.
3006e9885Smarc  * All rights reserved.  The Berkeley software License Agreement
4006e9885Smarc  * specifies the terms and conditions for redistribution.
5006e9885Smarc  *
6*e977faadSmarc  * 	@(#)qd.c	1.6  Berkeley  06/01/88
7006e9885Smarc  *
8*e977faadSmarc  * derived from: "@(#)qd.c	ULTRIX";
9006e9885Smarc  */
107e911b15Skarels /************************************************************************
117e911b15Skarels *									*
12*e977faadSmarc *			Copyright (c) 1985-1988 by			*
137e911b15Skarels *		Digital Equipment Corporation, Maynard, MA		*
147e911b15Skarels *			All rights reserved.				*
157e911b15Skarels *									*
167e911b15Skarels *   This software is furnished under a license and may be used and	*
177e911b15Skarels *   copied  only  in accordance with the terms of such license and	*
187e911b15Skarels *   with the  inclusion  of  the  above  copyright  notice.   This	*
197e911b15Skarels *   software  or  any  other copies thereof may not be provided or	*
207e911b15Skarels *   otherwise made available to any other person.  No title to and	*
217e911b15Skarels *   ownership of the software is hereby transferred.			*
227e911b15Skarels *									*
237e911b15Skarels *   The information in this software is subject to change  without	*
247e911b15Skarels *   notice  and should not be construed as a commitment by Digital	*
257e911b15Skarels *   Equipment Corporation.						*
267e911b15Skarels *									*
277e911b15Skarels *   Digital assumes no responsibility for the use  or  reliability	*
287e911b15Skarels *   of its software on equipment which is not supplied by Digital.	*
297e911b15Skarels *									*
307e911b15Skarels *************************************************************************/
31*e977faadSmarc 
327e911b15Skarels /*
33*e977faadSmarc  * qd.c
34*e977faadSmarc  *
35*e977faadSmarc  * Modification history
36*e977faadSmarc  *
37*e977faadSmarc  * QDSS workstation driver
38*e977faadSmarc  *
39*e977faadSmarc  *
40*e977faadSmarc  *  1-Dec-87 - Tim Burke
41*e977faadSmarc  *
42*e977faadSmarc  *	Added support for both System V termio(7) and POSIX termios(7).  These
43*e977faadSmarc  *	changes also include support for 8-bit canonical processing.  Changes
44*e977faadSmarc  *	involve:
45*e977faadSmarc  *
46*e977faadSmarc  *	- Default settings on first open depend on mode of open.  For termio
47*e977faadSmarc  *	  opens the defaults are "RAW" style, while non-termio opens default
48*e977faadSmarc  *	  to the traditional "cooked" style.
49*e977faadSmarc  *	- The driver now represents its terminal attributes and special
50*e977faadSmarc  *	  characters in the POSIX termios data structure.  This contrasts the
51*e977faadSmarc  *	  original approach of storing attributes and special chars in the
52*e977faadSmarc  *	  t_flags, ltchars and tchars.
53*e977faadSmarc  *	- Addition of LPASS8 to local mode word for 8-bit canonical support.
54*e977faadSmarc  *
55*e977faadSmarc  * 28-Sep-87 - Ali Rafieymehr
56*e977faadSmarc  *    Fixed a bug in qddint() routine. The bug was discovered on CVAX.
57*e977faadSmarc  *    Incorrect logic was used when taking an entry from the request queue.
58*e977faadSmarc  *
59*e977faadSmarc  * 12-Oct-87 - Tim Burke
60*e977faadSmarc  *	Modified driver to provide 8-bit support to the console port.  To do
61*e977faadSmarc  *	this characters are defined in the remainder of the first 15 rows of
62*e977faadSmarc  *	off screen memory as well as in next 15 rows.
63*e977faadSmarc  *
64*e977faadSmarc  *  2-Aug-87 - Fred Canter
65*e977faadSmarc  *    Use TANDEM mode on qconsole for flow control of writes to
66*e977faadSmarc  *    /dev/console.
67*e977faadSmarc  *
68*e977faadSmarc  * 12-Jun-87 - Tim Burke
69*e977faadSmarc  *
70*e977faadSmarc  *	Added full TERMIO functionality to terminal subsystem.
71*e977faadSmarc  *	Changed open routine to setup propper default settings if the line
72*e977faadSmarc  *	is not being used as a graphics device.  Added defines of defaults.
73*e977faadSmarc  *
74*e977faadSmarc  *
75*e977faadSmarc  * 14-May-87 - Fred Canter
76*e977faadSmarc  *	Changed default state of kernel_loop to on.
77*e977faadSmarc  *
78*e977faadSmarc  * 21-Apr-87 - Brian Stevens
79*e977faadSmarc  *	Xos support
80*e977faadSmarc  *
81*e977faadSmarc  * 16-Apr-87 - Fred Canter (for Brian Stevens)
82*e977faadSmarc  *	Multi-head GPX changes.
83*e977faadSmarc  *
84*e977faadSmarc  * 19-Mar-87 - Fred Canter (for Brian Stevens)
85*e977faadSmarc  *	Added X in the kernel support.
86*e977faadSmarc  *
87*e977faadSmarc  * 16-Dec-86 - Brian Stevens
88*e977faadSmarc  *
89*e977faadSmarc  *	added support so "select" could be called on tty type device
90*e977faadSmarc  *      fixed rlogin bug
91*e977faadSmarc  *
92*e977faadSmarc  * 30-Oct-86 - Brian Stevens
93*e977faadSmarc  *
94*e977faadSmarc  *	Removed the mprintf for "unexpected interrupts"
95*e977faadSmarc  *
96*e977faadSmarc  * 26-Aug-86 - rsp (Ricky Palmer)
97*e977faadSmarc  *
98*e977faadSmarc  *	Cleaned up devioctl code to (1) zero out devget structure
99*e977faadSmarc  *	upon entry and (2) use strlen instead of fixed storage
100*e977faadSmarc  *	for bcopy's.
101*e977faadSmarc  *
102*e977faadSmarc  * 21-Jul-86 - Ram Rao
103*e977faadSmarc  *	allowed cursor rectangle to hang (partially) off the
104*e977faadSmarc  *	top and left of screen
105*e977faadSmarc  *
106*e977faadSmarc  * 11-Jul-86 - ricky palmer
107*e977faadSmarc  *
108*e977faadSmarc  *	Added adpt and nexus fields to DEVIOCGET code.
109*e977faadSmarc  *
110*e977faadSmarc  * 02-July-86 - Brian Stevens
111*e977faadSmarc  *
112*e977faadSmarc  *	added support for console writing to second QDSS display
113*e977faadSmarc  *
114*e977faadSmarc  * 20-May-86 - ricky palmer
115*e977faadSmarc  *
116*e977faadSmarc  *	Added new DEVIOCGET ioctl request code. V2.0
117*e977faadSmarc  *
118*e977faadSmarc  * 16-Apr-86 -- darrell
119*e977faadSmarc  *	 badaddr is now called via the macro BADADDR
120*e977faadSmarc  *
121*e977faadSmarc  * 14-Apr-86 -- afd
122*e977faadSmarc  *	 Changed UMEMmap to QVmap and umem to qvmem.
123*e977faadSmarc  *
124*e977faadSmarc  *	 v_console() is now refered to as v_consputc, and there is a
125*e977faadSmarc  *	 corresponding v_consgetc() (defined in /sys/vax/conf.c).
126*e977faadSmarc  *
127*e977faadSmarc  *	 Added "qdgetc()" routine for console read.  Needed to read
128*e977faadSmarc  *	 user's answer to the "root device?" prompt with a generic kernel.
129*e977faadSmarc  *
130*e977faadSmarc  * 19-Mar-86 -- pmk
131*e977faadSmarc  *	 Change DELAY to 20000, because microdelay now in real microsec.
132*e977faadSmarc  *
133*e977faadSmarc  * 18-mar-86  -- jaw	 br/cvec changed to NOT use registers.
134*e977faadSmarc  *
135*e977faadSmarc  * 11 mar 86  darrell	replaced percpu with cpusw, and removed all but
136*e977faadSmarc  *			 one global reference
137*e977faadSmarc  * 19 feb 86  bstevens	no report of motion event on puck/stylus button action
138*e977faadSmarc  * 18 feb 86  bstevens	put in cursor box support for tablets
139*e977faadSmarc  * 18-Mar-86 -- jaw  add routines to cpu switch for nexus/unibus addreses
140*e977faadSmarc  *		      also got rid of some globals like nexnum.
141*e977faadSmarc  *		      ka8800 cleanup.
142*e977faadSmarc  * 06 dec 85  longo  added LK-201 error reporting for graphics device ops
143*e977faadSmarc  * 03 dec 85  longo  made qddint() clear active bit on error
144*e977faadSmarc  * 02 dec 85  longo  fixed up some crocks in the error messages
145*e977faadSmarc  * 25 nov 85  longo  added error handling to DMA ISR and single user locking
146*e977faadSmarc  * 19 nov 85  longo  eliminated "set_defaults()" by breaking out sub-calls.
147*e977faadSmarc  *		     Changed init_shared to do real init of scroll struct
148*e977faadSmarc  * 12 nov 85  longo  fixed bug in open that broke alternate console re-direct
149*e977faadSmarc  * 11 nov 85  longo  changed "_vs_eventqueue" references to "qdinput"
150*e977faadSmarc  * 08 nov 85  longo  improved select service for read/write select wakeup.
151*e977faadSmarc  *		     Also set ISR's to ipl4 to allow the interval timer in.
152*e977faadSmarc  * 04 nov 85  longo  fixed bugs in mouse button reporting and dma request stuff
153*e977faadSmarc  * 30 oct 85  longo  DMA to/from user space is in place
154*e977faadSmarc  * 14 oct 85  longo  added kernel msg redirect and QD_RDCURSOR ioctl
155*e977faadSmarc  * 03 oct 85  longo  added support for multiple QDSS's
156*e977faadSmarc  * 02 oct 85  longo  added color map loading services in qdioctl() & qdaint()
157*e977faadSmarc  * 30 sep 85  longo  added DMA interrupt services
158*e977faadSmarc  * 18 sep 85  longo  added scroll services to "qdaint()" adder intrpt service
159*e977faadSmarc  *		     and put in supporting ioctl's
160*e977faadSmarc  * 04 sep 85  longo  initial implementation of DMA is working
161*e977faadSmarc  * 17 aug 85  longo  added support for the QDSS to be system console
162*e977faadSmarc  * 05 aug 85  longo  now using qfont (QVSS & QDSS) as linked object
163*e977faadSmarc  * 12 jun 85  longo  added mouse event loading to "qdiint()"
164*e977faadSmarc  * 31 may 85  longo  put live interrupts into the probe() routine
165*e977faadSmarc  * 30 may 85  longo  event queue shared memory implementation is now alive
166*e977faadSmarc  * 29 may 85  longo  LK-201 input is now interrupt driven
167*e977faadSmarc  * 25 apr 85  longo  MAPDEVICE works
168*e977faadSmarc  * 14 mar 85  longo  created
169*e977faadSmarc  *
170*e977faadSmarc  *	 todo:	 fix rlogin bug in console stuff
171*e977faadSmarc  *		 cat -u console redirection
172*e977faadSmarc  *		 check error return from strategy routine
173*e977faadSmarc  *		 verify TOY time stuff (what format?)
174*e977faadSmarc  *		 look at system based macro implementation of VTOP
175*e977faadSmarc  *
1767e911b15Skarels  */
1777e911b15Skarels 
178*e977faadSmarc #include "qd.h" 	/* # of QDSS's the system is configured for */
179*e977faadSmarc 
180006e9885Smarc #if NQD > 0
181*e977faadSmarc #include "types.h"
182*e977faadSmarc #include "../machine/pte.h"	/* page table values */
183*e977faadSmarc #include "../machine/mtpr.h"	/* VAX register access stuff */
184006e9885Smarc #include "../machine/cpu.h"
185*e977faadSmarc #include "param.h" 	/* general system params & macros */
186*e977faadSmarc #include "conf.h"		/* "linesw" tty driver dispatch */
187*e977faadSmarc #include "dir.h"		/* for directory handling */
188*e977faadSmarc #include "user.h"		/* user structure (what else?) */
189*e977faadSmarc #include "qdioctl.h"	/* ioctl call values */
190006e9885Smarc #include "tty.h"
191*e977faadSmarc #include "map.h"		/* resource allocation map struct */
192*e977faadSmarc #include "buf.h"		/* buf structs */
193*e977faadSmarc #include "vm.h"		/* includes 'vm' header files */
194*e977faadSmarc #include "bk.h"		/* BKINPUT macro for line stuff */
195*e977faadSmarc #include "clist.h" 	/* char list handling structs */
196*e977faadSmarc #include "file.h"		/* file I/O definitions */
197*e977faadSmarc #include "uio.h"		/* write/read call structs */
198*e977faadSmarc #include "kernel.h"	/* clock handling structs */
199*e977faadSmarc #ifdef notdef	/* notneeded */
200*e977faadSmarc #include "cpuconf.h"
201*e977faadSmarc #include "devio.h"
202*e977faadSmarc #endif
203*e977faadSmarc #include "exec.h"
204*e977faadSmarc #include "proc.h"
20524f67f6bSmarc 
206*e977faadSmarc #include "ubareg.h"	/* uba & 'qba' register structs */
207*e977faadSmarc #include "ubavar.h"	/* uba structs & uba map externs */
208*e977faadSmarc #include "syslog.h"
209*e977faadSmarc 
210*e977faadSmarc #include "qduser.h"	/* definitions shared with my client */
211*e977faadSmarc #include "qdreg.h"	/* QDSS device register structures */
212*e977faadSmarc /*-----------------------------------------------------------
213*e977faadSmarc * QDSS driver status flags for tracking operational state */
21424f67f6bSmarc 
21524f67f6bSmarc 	struct qdflags {
21624f67f6bSmarc 
21724f67f6bSmarc 	    u_int inuse;	    /* which minor dev's are in use now */
21824f67f6bSmarc 	    u_int config;	    /* I/O page register content */
21924f67f6bSmarc 	    u_int mapped;	    /* user mapping status word */
220*e977faadSmarc 	    u_int kernel_loop;	    /* if kernel console is redirected */
22124f67f6bSmarc 	    u_int user_dma;	    /* DMA from user space in progress */
22224f67f6bSmarc 	    u_short pntr_id;	    /* type code of pointing device */
22324f67f6bSmarc 	    u_short duart_imask;    /* shadowing for duart intrpt mask reg */
22424f67f6bSmarc 	    u_short adder_ie;	    /* shadowing for adder intrpt enbl reg */
22524f67f6bSmarc 	    u_short curs_acc;	    /* cursor acceleration factor */
22624f67f6bSmarc 	    u_short curs_thr;	    /* cursor acceleration threshold level */
22724f67f6bSmarc 	    u_short tab_res;	    /* tablet resolution factor */
22824f67f6bSmarc 	    u_short selmask;	    /* mask for active qd select entries */
22924f67f6bSmarc 	};
23024f67f6bSmarc 
231006e9885Smarc 	/* bit definitions for "inuse" entry  */
232*e977faadSmarc 
23324f67f6bSmarc #define CONS_DEV	0x01
23424f67f6bSmarc #define ALTCONS_DEV	0x02
23524f67f6bSmarc #define GRAPHIC_DEV	0x04
23624f67f6bSmarc 
23724f67f6bSmarc 	/* bit definitions for 'mapped' member of flag structure */
238*e977faadSmarc 
23924f67f6bSmarc #define MAPDEV		0x01		/* hardware is mapped */
24024f67f6bSmarc #define MAPDMA		0x02		/* DMA buffer mapped */
24124f67f6bSmarc #define MAPEQ		0x04		/* event queue buffer mapped */
24224f67f6bSmarc #define MAPSCR		0x08		/* scroll param area mapped */
24324f67f6bSmarc #define MAPCOLOR	0x10		/* color map writing buffer mapped */
24424f67f6bSmarc 
24524f67f6bSmarc 	/* bit definitions for 'selmask' member of qdflag structure */
24624f67f6bSmarc 
24724f67f6bSmarc #define SEL_READ	0x01		/* read select is active */
24824f67f6bSmarc #define SEL_WRITE	0x02		/* write select is active */
24924f67f6bSmarc 
250*e977faadSmarc /*----------------------------------------------
251*e977faadSmarc * constants used in shared memory operations */
25224f67f6bSmarc 
25324f67f6bSmarc #define EVENT_BUFSIZE  1024	/* # of bytes per device's event buffer */
254*e977faadSmarc 
25524f67f6bSmarc #define MAXEVENTS  ( (EVENT_BUFSIZE - sizeof(struct qdinput))	 \
25624f67f6bSmarc 		     / sizeof(struct _vs_event) )
257*e977faadSmarc 
2580d59d4d6Smarc #define DMA_BUFSIZ	(1024 * 10)
259*e977faadSmarc 
26024f67f6bSmarc #define COLOR_BUFSIZ  ((sizeof(struct color_buf) + 512) & ~0x01FF)
26124f67f6bSmarc 
262*e977faadSmarc /*******************************************************************/
263*e977faadSmarc 
264*e977faadSmarc extern char qvmem[][128*NBPG];
265*e977faadSmarc extern struct pte QVmap[][128];
266*e977faadSmarc 
267*e977faadSmarc 
268*e977faadSmarc /*--------------------------------------------------------------------------
26924f67f6bSmarc * reference to an array of "uba_device" structures built by the auto
27024f67f6bSmarc * configuration program.  The uba_device structure decribes the device
27124f67f6bSmarc * sufficiently for the driver to talk to it.  The auto configuration code
27224f67f6bSmarc * fills in the uba_device structures (located in ioconf.c) from user
273*e977faadSmarc * maintained info.  */
27424f67f6bSmarc 
27524f67f6bSmarc 	struct uba_device *qdinfo[NQD];  /* array of pntrs to each QDSS's */
27624f67f6bSmarc 					 /* uba structures  */
27724f67f6bSmarc 	struct tty qd_tty[NQD*4];	/* teletype structures for each.. */
27824f67f6bSmarc 					/* ..possible minor device */
27924f67f6bSmarc 
28024f67f6bSmarc 	struct qd_softc qd_softc[NQD];
28124f67f6bSmarc 
282*e977faadSmarc /*----------------------------------------------------------
283*e977faadSmarc * static storage used by multiple functions in this code  */
284*e977faadSmarc 
28524f67f6bSmarc 	int Qbus_unmap[NQD];		/* Qbus mapper release code */
28624f67f6bSmarc 	struct qdflags qdflags[NQD];	/* QDSS device status flags */
28724f67f6bSmarc 	struct qdmap qdmap[NQD];	/* QDSS register map structure */
28824f67f6bSmarc 	caddr_t qdbase[NQD];		/* base address of each QDSS unit */
28924f67f6bSmarc 	struct buf qdbuf[NQD];		/* buf structs used by strategy */
29024f67f6bSmarc 	char one_only[NQD];		/* lock for single process access */
29124f67f6bSmarc 
292*e977faadSmarc /*------------------------------------------------------------------------
293*e977faadSmarc * the array "event_shared[]" is made up of a number of event queue buffers
29424f67f6bSmarc * equal to the number of QDSS's configured into the running kernel (NQD).
29524f67f6bSmarc * Each event queue buffer begins with an event queue header (struct qdinput)
29624f67f6bSmarc * followed by a group of event queue entries (struct _vs_event).  The array
29724f67f6bSmarc * "*eq_header[]" is an array of pointers to the start of each event queue
298*e977faadSmarc * buffer in "event_shared[]".  */
29924f67f6bSmarc 
30024f67f6bSmarc #define EQSIZE ((EVENT_BUFSIZE * NQD) + 512)
30124f67f6bSmarc 
30224f67f6bSmarc 	char event_shared[EQSIZE];	    /* reserve space for event bufs */
30324f67f6bSmarc 	struct qdinput *eq_header[NQD];     /* event queue header pntrs */
30424f67f6bSmarc 
305*e977faadSmarc /*--------------------------------------------------------------------------
30624f67f6bSmarc * This allocation method reserves enough memory pages for NQD shared DMA I/O
30724f67f6bSmarc * buffers.  Each buffer must consume an integral number of memory pages to
30824f67f6bSmarc * guarantee that a following buffer will begin on a page boundary.  Also,
30924f67f6bSmarc * enough space is allocated so that the FIRST I/O buffer can start at the
31024f67f6bSmarc * 1st page boundary after "&DMA_shared".  Page boundaries are used so that
311*e977faadSmarc * memory protections can be turned on/off for individual buffers. */
31224f67f6bSmarc 
31324f67f6bSmarc #define IOBUFSIZE  ((DMA_BUFSIZ * NQD) + 512)
31424f67f6bSmarc 
31524f67f6bSmarc 	char DMA_shared[IOBUFSIZE];	    /* reserve I/O buffer space */
31624f67f6bSmarc 	struct DMAreq_header *DMAheader[NQD];  /* DMA buffer header pntrs */
31724f67f6bSmarc 
318*e977faadSmarc /*-------------------------------------------------------------------------
31924f67f6bSmarc * The driver assists a client in scroll operations by loading dragon
32024f67f6bSmarc * registers from an interrupt service routine.	The loading is done using
32124f67f6bSmarc * parameters found in memory shrade between the driver and it's client.
32224f67f6bSmarc * The scroll parameter structures are ALL loacted in the same memory page
323*e977faadSmarc * for reasons of memory economy.  */
32424f67f6bSmarc 
32524f67f6bSmarc 	char scroll_shared[2 * 512];	/* reserve space for scroll structs */
32624f67f6bSmarc 	struct scroll *scroll[NQD];	/* pointers to scroll structures */
32724f67f6bSmarc 
328*e977faadSmarc /*-----------------------------------------------------------------------
32924f67f6bSmarc * the driver is programmable to provide the user with color map write
33024f67f6bSmarc * services at VSYNC interrupt time.  At interrupt time the driver loads
331*e977faadSmarc * the color map with any user-requested load data found in shared memory */
33224f67f6bSmarc 
33324f67f6bSmarc #define COLOR_SHARED  ((COLOR_BUFSIZ * NQD) + 512)
33424f67f6bSmarc 
335*e977faadSmarc 	char color_shared[COLOR_SHARED];      /* reserve space: color bufs */
33624f67f6bSmarc 	struct color_buf *color_buf[NQD];     /* pointers to color bufs */
33724f67f6bSmarc 
338*e977faadSmarc /*--------------------------------
339*e977faadSmarc * mouse input event structures */
34024f67f6bSmarc 
34124f67f6bSmarc 	struct mouse_report last_rep[NQD];
34224f67f6bSmarc 	struct mouse_report current_rep[NQD];
34324f67f6bSmarc 
344*e977faadSmarc /*----------------------------
345*e977faadSmarc * input event "select" use */
34624f67f6bSmarc 
34724f67f6bSmarc 	struct proc *rsel[NQD]; 	/* process waiting for select */
34824f67f6bSmarc 
349*e977faadSmarc /*----------------------------
350*e977faadSmarc * console cursor structure */
35124f67f6bSmarc 
35224f67f6bSmarc 	struct _vs_cursor cursor[NQD];
35324f67f6bSmarc 
354*e977faadSmarc /*----------------------------
355*e977faadSmarc * count of successfully probed qd's */
35624f67f6bSmarc 
357*e977faadSmarc 	int qdcount = 0;
358*e977faadSmarc 
359*e977faadSmarc 
360*e977faadSmarc /************************************************************************/
36124f67f6bSmarc 
36224f67f6bSmarc 	int nNQD = NQD;
36324f67f6bSmarc 
36424f67f6bSmarc 	int DMAbuf_size = DMA_BUFSIZ;
36524f67f6bSmarc 
36624f67f6bSmarc 
367*e977faadSmarc #define QDSSMAJOR	41		/* QDSS major device number */
368*e977faadSmarc #ifdef notdef	/* on ultrix */
369*e977faadSmarc extern	int	ws_display_type;
370*e977faadSmarc extern	int	ws_display_units;
371*e977faadSmarc #endif
372*e977faadSmarc /* don't need these  */
373*e977faadSmarc int	ws_display_type;
374*e977faadSmarc int	ws_display_units;
375*e977faadSmarc 
376*e977faadSmarc int     QDlast_DMAtype;                 /* type of the last DMA operation */
377*e977faadSmarc 
378*e977faadSmarc /*---------------------------------------------------------------------
379*e977faadSmarc * macro to get system time.  Used to time stamp event queue entries */
3807e911b15Skarels 
3817e911b15Skarels #define TOY ((time.tv_sec * 100) + (time.tv_usec / 10000))
3827e911b15Skarels 
383*e977faadSmarc /*--------------------------------------------------------------------------
3847e911b15Skarels * the "ioconf.c" program, built and used by auto config, externally refers
385*e977faadSmarc * to definitions below.  */
3867e911b15Skarels 
3877e911b15Skarels 	int qdprobe();
3887e911b15Skarels 	int qdattach();
3897e911b15Skarels 	int qddint();			/* DMA gate array intrpt service */
3907e911b15Skarels 	int qdaint();			/* Dragon ADDER intrpt service */
3917e911b15Skarels 	int qdiint();
3927e911b15Skarels 
3937e911b15Skarels 	u_short qdstd[] = { 0 };
3947e911b15Skarels 
3957e911b15Skarels 	struct uba_driver qddriver = {	/* externally referenced: ioconf.c */
3967e911b15Skarels 
3977e911b15Skarels 	    qdprobe,			/* device probe entry */
3987e911b15Skarels 	    0,				/* no slave device */
3997e911b15Skarels 	    qdattach,			/* device attach entry */
4007e911b15Skarels 	    0,				/* no "fill csr/ba to start" */
4017e911b15Skarels 	    qdstd,			/* device addresses */
4027e911b15Skarels 	    "qd",			/* device name string */
4037e911b15Skarels 	    qdinfo			/* ptr to QDSS's uba_device struct */
4047e911b15Skarels 	};
4057e911b15Skarels 
406*e977faadSmarc /*-------------------
4077e911b15Skarels * general defines */
4087e911b15Skarels 
409*e977faadSmarc #define QDPRIOR (PZERO-1)		/* must be negative */
4107e911b15Skarels 
4117e911b15Skarels #define FALSE	0
4127e911b15Skarels #define TRUE	~FALSE
4137e911b15Skarels 
4147e911b15Skarels #define BAD	-1
4157e911b15Skarels #define GOOD	0
4167e911b15Skarels 
417*e977faadSmarc /*-----------------------------------------------------------------------
418*e977faadSmarc * macro to create a system virtual page number from system virtual adrs */
4197e911b15Skarels 
420*e977faadSmarc #define VTOP(x)  (((int)x & ~0xC0000000) >> PGSHIFT) /* convert qvmem adrs */
421*e977faadSmarc 						     /* to system page # */
4227e911b15Skarels 
423*e977faadSmarc /*------------------------------------------------------------------
424*e977faadSmarc * QDSS register address offsets from start of QDSS address space */
4257e911b15Skarels 
4267e911b15Skarels #define QDSIZE	 (52 * 1024)	/* size of entire QDSS foot print */
4277e911b15Skarels 
4287e911b15Skarels #define TMPSIZE  (16 * 1024)	/* template RAM is 8k SHORT WORDS */
4297e911b15Skarels #define TMPSTART 0x8000 	/* offset of template RAM from base adrs */
4307e911b15Skarels 
4317e911b15Skarels #define REGSIZE  (5 * 512)	/* regs touch 2.5k (5 pages) of addr space */
4327e911b15Skarels #define REGSTART 0xC000 	/* offset of reg pages from base adrs */
4337e911b15Skarels 
4347e911b15Skarels #define ADDER	(REGSTART+0x000)
4357e911b15Skarels #define DGA	(REGSTART+0x200)
4367e911b15Skarels #define DUART	(REGSTART+0x400)
4377e911b15Skarels #define MEMCSR	(REGSTART+0x800)
4387e911b15Skarels 
4397e911b15Skarels #define CLRSIZE  (3 * 512)		/* color map size */
4407e911b15Skarels #define CLRSTART (REGSTART+0xA00)	/* color map start offset from base */
4417e911b15Skarels 					/*  0x0C00 really */
4427e911b15Skarels #define RED	(CLRSTART+0x000)
4437e911b15Skarels #define BLUE	(CLRSTART+0x200)
4447e911b15Skarels #define GREEN	(CLRSTART+0x400)
4457e911b15Skarels 
446*e977faadSmarc /*---------------------------------------------------------------
447*e977faadSmarc * values used in mapping QDSS hardware into the Q memory space */
4487e911b15Skarels 
4497e911b15Skarels #define CHUNK	  (64 * 1024)
450*e977faadSmarc #define QMEMSIZE  (1024 * 1024 * 4)	/* 4 meg */
4517e911b15Skarels 
452*e977faadSmarc /*----------------------------------------------------------------------
4537e911b15Skarels * QDSS minor device numbers.  The *real* minor device numbers are in
4547e911b15Skarels * the bottom two bits of the major/minor device spec.  Bits 2 and up are
455*e977faadSmarc * used to specify the QDSS device number (ie: which one?) */
4567e911b15Skarels 
4577e911b15Skarels 
4587e911b15Skarels #define CONS		0
4597e911b15Skarels #define ALTCONS 	1
4607e911b15Skarels #define GRAPHIC 	2
4617e911b15Skarels 
462*e977faadSmarc /*----------------------------------------------
463*e977faadSmarc * console cursor bitmap (block cursor type)  */
4647e911b15Skarels 
4657e911b15Skarels 	short cons_cursor[32] = {      /* white block cursor */
4667e911b15Skarels 
4677e911b15Skarels  /* A */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
4687e911b15Skarels 	 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
4697e911b15Skarels  /* B */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
4707e911b15Skarels 	 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF
4717e911b15Skarels 
4727e911b15Skarels 	};
4737e911b15Skarels 
474*e977faadSmarc /*-------------------------------------
475*e977faadSmarc * constants used in font operations */
4767e911b15Skarels 
477*e977faadSmarc 
478*e977faadSmarc /* Originaly this was CHARS 95 */
479*e977faadSmarc #define CHARS		190 			/* # of chars in the font */
480*e977faadSmarc 
4817e911b15Skarels #define CHAR_HEIGHT	15			/* char height in pixels */
4827e911b15Skarels #define CHAR_WIDTH	8			/* char width in pixels*/
4837e911b15Skarels #define FONT_WIDTH	(CHAR_WIDTH * CHARS)	/* font width in pixels */
4847e911b15Skarels #define ROWS		CHAR_HEIGHT
4857e911b15Skarels 
4867e911b15Skarels 
4877e911b15Skarels #define FONT_X		0			/* font's off screen adrs */
4887e911b15Skarels #define FONT_Y		(2048 - CHAR_HEIGHT)
489*e977faadSmarc 
490*e977faadSmarc 					/* Offset to second row characters */
491*e977faadSmarc #define FONT_OFFSET	((MAX_SCREEN_X/CHAR_WIDTH)*CHAR_HEIGHT)
4927e911b15Skarels 
4937e911b15Skarels 	extern char q_font[];		/* reference font object code */
4947e911b15Skarels 
495*e977faadSmarc 	extern	u_short q_key[];		/* reference key xlation tables */
496*e977faadSmarc 	extern	u_short q_shift_key[];
4977e911b15Skarels 	extern	char *q_special[];
4987e911b15Skarels 
499*e977faadSmarc /*--------------------------------------------------
500*e977faadSmarc * definitions for cursor acceleration reporting  */
5017e911b15Skarels 
5027e911b15Skarels #define ACC_OFF 	0x01		/* acceleration is inactive */
5037e911b15Skarels 
504*e977faadSmarc /*--------------------------------------------------------------------------
505*e977faadSmarc * v_consputc is the switch that is used to redirect the console cnputc() to
506*e977faadSmarc * the virtual console qdputc().
507*e977faadSmarc * v_consgetc is the switch that is used to redirect the console getchar() to
508*e977faadSmarc * the virtual console qdgetc().
5097e911b15Skarels */
5107e911b15Skarels 
511*e977faadSmarc #ifdef notdef
512*e977faadSmarc 	extern (*v_consputc)();
513*e977faadSmarc 	int qdputc();		/* used to direct kernel console output */
514*e977faadSmarc 	extern (*v_consgetc)();
515*e977faadSmarc 	int qdgetc();		/* used to read kernel console input */
516*e977faadSmarc 
517*e977faadSmarc 	int qdstart();		/* used to direct /dev/console output */
518*e977faadSmarc #endif
519*e977faadSmarc 	extern (*v_putc)();
520*e977faadSmarc 	extern struct cdevsw *consops;
521*e977faadSmarc 	int qdputc();
522*e977faadSmarc 	int qdstart();
523*e977faadSmarc 
524*e977faadSmarc /*------------------------------------------------------------------------
525*e977faadSmarc * LK-201 state storage for input console keyboard conversion to ASCII */
526*e977faadSmarc 
5277e911b15Skarels 	struct q_keyboard {
528*e977faadSmarc 
5297e911b15Skarels 	    int shift;			/* state variables	*/
5307e911b15Skarels 	    int cntrl;
5317e911b15Skarels 	    int lock;
5327e911b15Skarels 	    int lastcode;		/* last keycode typed	*/
5337e911b15Skarels 	    unsigned kup[8];		/* bits for each keycode*/
5347e911b15Skarels 	    unsigned dkeys[8];		/* down/up mode keys	*/
5357e911b15Skarels 	    char last;			/* last character	*/
536*e977faadSmarc 
5377e911b15Skarels 	 } q_keyboard;
5387e911b15Skarels 
539*e977faadSmarc /*--------------------------------------------------
540*e977faadSmarc * ULTRIX settings for first open.		  */
541*e977faadSmarc 
542*e977faadSmarc #define IFLAGS	(EVENP|ECHO|XTABS|CRMOD)
543*e977faadSmarc 
544*e977faadSmarc /*------------------------------------------------------------------------
545*e977faadSmarc * termio flags will be set to these default values in non-termio mode to
546*e977faadSmarc * provide a backward compatible ULTRIX environment. */
547*e977faadSmarc 
548*e977faadSmarc #ifdef POSIXTTY
549*e977faadSmarc #define IFLAG (BRKINT|ISTRIP|IXON|IXANY|ICRNL|IEXTEN|IMAXBEL)
550*e977faadSmarc #define OFLAG (OPOST|OXTABS|ONLCR)
551*e977faadSmarc #define LFLAG (ISIG|ICANON|ECHO)
552*e977faadSmarc #define CFLAG (PARENB|CREAD|CS7|CLOCAL)
553*e977faadSmarc #endif
554*e977faadSmarc 
555*e977faadSmarc /*****************************************************************
556*e977faadSmarc ******************************************************************
557*e977faadSmarc ******************************************************************
558*e977faadSmarc *
559*e977faadSmarc *	DRIVER FUNCTIONS START HERE:
560*e977faadSmarc *
561*e977faadSmarc ******************************************************************
562*e977faadSmarc ******************************************************************
563*e977faadSmarc *****************************************************************/
5647e911b15Skarels 
5657e911b15Skarels /*********************************************************************
5667e911b15Skarels *
567*e977faadSmarc *	qdcons_init()... init QDSS as console (before probe routine)
5687e911b15Skarels *
5697e911b15Skarels *********************************************************************/
5707e911b15Skarels 
5717e911b15Skarels qdcons_init()
5727e911b15Skarels {
5737e911b15Skarels 	register u_int unit;
5747e911b15Skarels 
5757e911b15Skarels 	int *ptep;			/* page table entry pointer */
5767e911b15Skarels 	caddr_t phys_adr;		/* physical QDSS base adrs */
577*e977faadSmarc 	u_int mapix;			/* index into QVmap[] array */
5787e911b15Skarels 
579*e977faadSmarc 	struct percpu *pcpu;		/* pointer to cpusw structure  */
580*e977faadSmarc 	register struct qbus *qb;
5817e911b15Skarels 	u_short *qdaddr;		/* address of QDSS IO page CSR */
5827e911b15Skarels 	u_short *devptr;		/* vitual device space */
583*e977faadSmarc 	extern cnputc();
5847e911b15Skarels 
5857e911b15Skarels #define QDSSCSR 0x1F00
5867e911b15Skarels 
58724f67f6bSmarc 	if (v_putc != cnputc)
58824f67f6bSmarc 		return;
58924f67f6bSmarc 
5907e911b15Skarels 	unit = 0;
5917e911b15Skarels 
592*e977faadSmarc /*----------------------------------------------------
593*e977faadSmarc * find the cpusw entry that matches this machine. */
5947e911b15Skarels 
59524f67f6bSmarc 	for (pcpu = percpu; pcpu && pcpu->pc_cputype != cpu; pcpu++)
5967e911b15Skarels 		;
59724f67f6bSmarc 	if (pcpu == NULL)
59824f67f6bSmarc 		return;
59924f67f6bSmarc 
600*e977faadSmarc #ifdef notdef	/* the ultrix way */
601*e977faadSmarc /*------------------------------------------------------
602*e977faadSmarc * Map the Q-bus memory space into the system memory. */
60324f67f6bSmarc 
604*e977faadSmarc 	ubaaccess(((*cpup->v_umaddr)(0)), QVmap[0],
605*e977faadSmarc 			cpup->pc_umsize, PG_V | PG_KW);
606*e977faadSmarc 
607*e977faadSmarc 	ubaaccess(((*cpup->v_udevaddr)(0)), QVmap[0]+btop(cpup->pc_umsize),
608*e977faadSmarc 			DEVSPACESIZE ,PG_V|PG_KW);
609*e977faadSmarc 
610*e977faadSmarc /*---------------------------------------------------------------------
611*e977faadSmarc * map the QDSS into the Qbus memory (which is now in system space)  */
612*e977faadSmarc 
613*e977faadSmarc 	devptr = (u_short *)((char *)qvmem[0]+cpup->pc_umsize);
614*e977faadSmarc 	qdaddr = (u_short *)((u_int)devptr + ubdevreg(QDSSCSR));
615*e977faadSmarc 
616*e977faadSmarc 	if (BADADDR(qdaddr, sizeof(short)))
617*e977faadSmarc 		return(0);
618*e977faadSmarc 
619*e977faadSmarc 	/*---------------------------------------------------
620*e977faadSmarc 	* tell QDSS which Q memory address base to decode */
621*e977faadSmarc 
622*e977faadSmarc 	mapix = (int) VTOP(QMEMSIZE - CHUNK);
623*e977faadSmarc 	ptep = (int *) QVmap[0] + mapix;
624*e977faadSmarc 	phys_adr = (caddr_t) (((int)*ptep & 0x001FFFFF) << PGSHIFT);
625*e977faadSmarc 	*qdaddr = (u_short) ((int)phys_adr >> 16);
626*e977faadSmarc 
627*e977faadSmarc 	qdflags[unit].config = *(u_short *)qdaddr;
628*e977faadSmarc 
629*e977faadSmarc #endif /*notdef*/
630*e977faadSmarc 
631*e977faadSmarc 	/* the BSD way */
63224f67f6bSmarc 	/*
633*e977faadSmarc 	 * Map device registers - the last 8K of qvmem.
63424f67f6bSmarc 	 */
63524f67f6bSmarc 	qb = (struct qbus *)pcpu->pc_io->io_details;
63624f67f6bSmarc 	ioaccess(qb->qb_iopage, UMEMmap[0] + qb->qb_memsize,
63724f67f6bSmarc 		UBAIOPAGES * NBPG);
63824f67f6bSmarc 
63924f67f6bSmarc 	devptr = (u_short *)((char *)umem[0]+(qb->qb_memsize * NBPG));
64024f67f6bSmarc 	qdaddr = (u_short *)((u_int)devptr + ubdevreg(QDSSCSR));
64124f67f6bSmarc 	if (badaddr(qdaddr, sizeof(short)))  {
642*e977faadSmarc 		printf("Can't find qdss (badaddr)\n"); /* debug */
6437e911b15Skarels 		return(0);
6447e911b15Skarels 	}
645*e977faadSmarc 
646*e977faadSmarc 
647*e977faadSmarc 
64824f67f6bSmarc 	/*
64924f67f6bSmarc 	 * Map q-bus memory used by qdss. (separate map)
65024f67f6bSmarc 	 */
65124f67f6bSmarc 	mapix = QMEMSIZE - (CHUNK * (unit + 1));
65224f67f6bSmarc 	phys_adr = qb->qb_maddr + mapix;
65324f67f6bSmarc 	ioaccess(phys_adr, QVmap[0], (CHUNK*NQD));
6547e911b15Skarels 
65524f67f6bSmarc 	/*
65624f67f6bSmarc 	 * tell QDSS which Q memory address base to decode
65724f67f6bSmarc 	 */
6587e911b15Skarels 
65924f67f6bSmarc 	/*
66024f67f6bSmarc 	 * shifted right 16 bits - its in 64K units
66124f67f6bSmarc 	 */
66224f67f6bSmarc 	*qdaddr = (u_short)((int)mapix >> 16);
6637e911b15Skarels 	qdflags[unit].config = *(u_short *)qdaddr;
6647e911b15Skarels 
665*e977faadSmarc /*----------------------------------------------------------------------
666*e977faadSmarc * load qdmap struct with the virtual addresses of the QDSS elements */
6677e911b15Skarels 
668*e977faadSmarc #ifdef notdef	/*ultrix way */
669*e977faadSmarc 	qdbase[unit] = (caddr_t) (qvmem[0] + QMEMSIZE - CHUNK);
670*e977faadSmarc #endif
671*e977faadSmarc 
672*e977faadSmarc 	qdbase[unit] = (caddr_t) (qvmem[0]);
6737e911b15Skarels 
6747e911b15Skarels 	qdmap[unit].template = qdbase[unit] + TMPSTART;
6757e911b15Skarels 	qdmap[unit].adder = qdbase[unit] + ADDER;
6767e911b15Skarels 	qdmap[unit].dga = qdbase[unit] + DGA;
6777e911b15Skarels 	qdmap[unit].duart = qdbase[unit] + DUART;
6787e911b15Skarels 	qdmap[unit].memcsr = qdbase[unit] + MEMCSR;
6797e911b15Skarels 	qdmap[unit].red = qdbase[unit] + RED;
6807e911b15Skarels 	qdmap[unit].blue = qdbase[unit] + BLUE;
6817e911b15Skarels 	qdmap[unit].green = qdbase[unit] + GREEN;
6827e911b15Skarels 
6837e911b15Skarels 	qdflags[unit].duart_imask = 0;	/* init shadow variables */
6847e911b15Skarels 
685*e977faadSmarc /*------------------
686*e977faadSmarc * init the QDSS  */
68724f67f6bSmarc 
68824f67f6bSmarc 	printf("qdbase[0] = %x, qdmap[0].memcsr = %x\n",
68924f67f6bSmarc 			(char *)qdbase[0], qdmap[0].memcsr);
6907e911b15Skarels 
6917e911b15Skarels 	*(short *)qdmap[unit].memcsr |= SYNC_ON; /* once only: turn on sync */
6927e911b15Skarels 
6937e911b15Skarels 	cursor[unit].x = 0;
6947e911b15Skarels 	cursor[unit].y = 0;
6957e911b15Skarels 	init_shared(unit);		/* init shared memory */
6967e911b15Skarels 	setup_dragon(unit);		/* init the ADDER/VIPER stuff */
6977e911b15Skarels 	clear_qd_screen(unit);		/* clear the screen */
6987e911b15Skarels 	ldfont(unit);			/* load the console font */
6997e911b15Skarels 	ldcursor(unit, cons_cursor);	/* load default cursor map */
7007e911b15Skarels 	setup_input(unit);		/* init the DUART */
7017e911b15Skarels 
702*e977faadSmarc /*----------------------------------------------------
703*e977faadSmarc * smash the system's virtual console address table */
704*e977faadSmarc 
705*e977faadSmarc #ifdef notdef	/* the ultrix way */
706*e977faadSmarc 	v_consputc = qdputc;
707*e977faadSmarc 	v_consgetc = qdgetc;
708*e977faadSmarc 	cdevsw[0] = cdevsw[QDSSMAJOR];
709*e977faadSmarc #endif
710*e977faadSmarc 	/* the bsd way */
71124f67f6bSmarc 	v_putc = qdputc;
71224f67f6bSmarc 	consops = &cdevsw[QDSSMAJOR];
7137e911b15Skarels 
714*e977faadSmarc  	ws_display_type = QDSSMAJOR;	/* Idenify QDSS as graphics device */
7157e911b15Skarels 	return(1);
7167e911b15Skarels 
7177e911b15Skarels } /* qdcons_init */
7187e911b15Skarels 
7197e911b15Skarels /*********************************************************************
7207e911b15Skarels *
7217e911b15Skarels *	qdprobe()... configure QDSS into Q memory and make it intrpt
7227e911b15Skarels *
7237e911b15Skarels **********************************************************************
7247e911b15Skarels *
7257e911b15Skarels *  calling convention:
7267e911b15Skarels *			qdprobe(reg, ctlr);
7277e911b15Skarels *			caddr_t reg;
7287e911b15Skarels *			int ctlr;
7297e911b15Skarels *
7307e911b15Skarels *	where: reg - a character pointer to the QDSS I/O page register
7317e911b15Skarels *	       ctlr - controller number (?)
7327e911b15Skarels *
7337e911b15Skarels *  side effects: QDSS gets mapped into Qbus memory space at the first
7347e911b15Skarels *		 vacant 64kb boundary counting back from the top of
735*e977faadSmarc *		 Qbus memory space (qvmem+4mb)
7367e911b15Skarels *
7377e911b15Skarels *  return: QDSS bus request level and vector address returned in
7387e911b15Skarels *	   registers by UNIX convention.
7397e911b15Skarels *
7407e911b15Skarels *****************/
7417e911b15Skarels 
7427e911b15Skarels qdprobe(reg)
7437e911b15Skarels caddr_t reg;
7447e911b15Skarels {
74524f67f6bSmarc 	register int br, cvec;  /* value-result */
7467e911b15Skarels 
7477e911b15Skarels 	register int unit;
7487e911b15Skarels 
7497e911b15Skarels 	struct dga *dga;		/* pointer to gate array structure */
7507e911b15Skarels 	struct cpusw *cpup;		/* pointer to the cpusw structure */
7517e911b15Skarels 
7527e911b15Skarels 	int *ptep;			/* page table entry pointer */
7537e911b15Skarels 	int vector;
7547e911b15Skarels 
7557e911b15Skarels 	caddr_t phys_adr;		/* physical QDSS base adrs */
7567e911b15Skarels 	u_int mapix;
7577e911b15Skarels 
758*e977faadSmarc /*---------------------------------------------------------------
759*e977faadSmarc * calculate board unit number from I/O page register address  */
7607e911b15Skarels 
7617e911b15Skarels 	unit = (int) (((int)reg >> 1) & 0x0007);
7627e911b15Skarels 
763*e977faadSmarc /*---------------------------------------------------------------------------
7647e911b15Skarels * QDSS regs must be mapped to Qbus memory space at a 64kb physical boundary.
7657e911b15Skarels * The Qbus memory space is mapped into the system memory space at config
766*e977faadSmarc * time.  After config runs, "qvmem[0]" (ubavar.h) holds the system virtual adrs
7677e911b15Skarels * of the start of Qbus memory.	The Qbus memory page table is found via
768*e977faadSmarc * an array of pte ptrs called "QVmap[]" (ubavar.h) which is also loaded at
7697e911b15Skarels * config time.	These are the variables used below to find a vacant 64kb
7707e911b15Skarels * boundary in Qbus memory, and load it's corresponding physical adrs into
771*e977faadSmarc * the QDSS's I/O page CSR.  */
772*e977faadSmarc 
773*e977faadSmarc 	/*
774*e977faadSmarc 	 * Only if QD is the graphics device.
77524f67f6bSmarc 	 */
7767e911b15Skarels 
777*e977faadSmarc 	if (ws_display_type && (ws_display_type != QDSSMAJOR))
778*e977faadSmarc 		return(0);
779*e977faadSmarc 
7807e911b15Skarels 	/* if this QDSS is NOT the console, then do init here.. */
7817e911b15Skarels 
782*e977faadSmarc 	if (unit != 0) {
783*e977faadSmarc 		printf("qd: can't support two qdss's (yet)\n");
784*e977faadSmarc #ifdef notdef	/* notyet */
7857e911b15Skarels 	if (v_consputc != qdputc  ||  unit != 0) {
7867e911b15Skarels 
787*e977faadSmarc 	    /*-------------------------
788*e977faadSmarc 	    * read QDSS config info */
789*e977faadSmarc 
7907e911b15Skarels 	    qdflags[unit].config = *(u_short *)reg;
7917e911b15Skarels 
792*e977faadSmarc 	    /*------------------------------------
793*e977faadSmarc 	    * find an empty 64kb adrs boundary */
7947e911b15Skarels 
795*e977faadSmarc 	    qdbase[unit] = (caddr_t) (qvmem[0] + QMEMSIZE - CHUNK);
796*e977faadSmarc 
797*e977faadSmarc 	    /*----------------------------------------------------
798*e977faadSmarc 	    * find the cpusw entry that matches this machine. */
799*e977faadSmarc 
8007e911b15Skarels 	    cpup = &cpusw[cpu];
8017e911b15Skarels 	    while ( !(BADADDR(qdbase[unit], sizeof(short))) )
8027e911b15Skarels 		qdbase[unit] -= CHUNK;
8037e911b15Skarels 
804*e977faadSmarc 	    /*---------------------------------------------------
805*e977faadSmarc 	    * tell QDSS which Q memory address base to decode */
806*e977faadSmarc 
807*e977faadSmarc 	    mapix = (int) (VTOP(qdbase[unit]) - VTOP(qvmem[0]));
808*e977faadSmarc 	    ptep = (int *) QVmap[0] + mapix;
8097e911b15Skarels 	    phys_adr = (caddr_t) (((int)*ptep & 0x001FFFFF) << PGSHIFT);
8107e911b15Skarels 	    *(u_short *)reg = (u_short) ((int)phys_adr >> 16);
8117e911b15Skarels 
812*e977faadSmarc 	    /*-----------------------------------------------------------
813*e977faadSmarc 	    * load QDSS adrs map with system addresses of device regs */
814*e977faadSmarc 
8157e911b15Skarels 	    qdmap[unit].template = qdbase[unit] + TMPSTART;
8167e911b15Skarels 	    qdmap[unit].adder = qdbase[unit] + ADDER;
8177e911b15Skarels 	    qdmap[unit].dga = qdbase[unit] + DGA;
8187e911b15Skarels 	    qdmap[unit].duart = qdbase[unit] + DUART;
8197e911b15Skarels 	    qdmap[unit].memcsr = qdbase[unit] + MEMCSR;
8207e911b15Skarels 	    qdmap[unit].red = qdbase[unit] + RED;
8217e911b15Skarels 	    qdmap[unit].blue = qdbase[unit] + BLUE;
8227e911b15Skarels 	    qdmap[unit].green = qdbase[unit] + GREEN;
8237e911b15Skarels 
8247e911b15Skarels 	    /* device init */
8257e911b15Skarels 
8267e911b15Skarels 	    cursor[unit].x = 0;
8277e911b15Skarels 	    cursor[unit].y = 0;
8287e911b15Skarels 	    init_shared(unit);		/* init shared memory */
8297e911b15Skarels 	    setup_dragon(unit); 	/* init the ADDER/VIPER stuff */
8307e911b15Skarels 	    ldcursor(unit, cons_cursor);	/* load default cursor map */
8317e911b15Skarels 	    setup_input(unit);		/* init the DUART */
8327e911b15Skarels 	    clear_qd_screen(unit);
8337e911b15Skarels 	    ldfont(unit);			/* load the console font */
8347e911b15Skarels 
8357e911b15Skarels 	    /* once only: turn on sync */
8367e911b15Skarels 
8377e911b15Skarels 	    *(short *)qdmap[unit].memcsr |= SYNC_ON;
838006e9885Smarc #endif /*notdef*/
839*e977faadSmarc 	}
8407e911b15Skarels 
841*e977faadSmarc /*--------------------------------------------------------------------------
8427e911b15Skarels * the QDSS interrupts at HEX vectors xx0 (DMA) xx4 (ADDER) and xx8 (DUART).
8437e911b15Skarels * Therefore, we take three vectors from the vector pool, and then continue
8447e911b15Skarels * to take them until we get a xx0 HEX vector.  The pool provides vectors
845*e977faadSmarc * in contiguous decending order.  */
8467e911b15Skarels 
8477e911b15Skarels 	vector = (uba_hd[0].uh_lastiv -= 4*3);	/* take three vectors */
8487e911b15Skarels 
8497e911b15Skarels 	while (vector & 0x0F) { 		   /* if lo nibble != 0.. */
8507e911b15Skarels 	    vector = (uba_hd[0].uh_lastiv -= 4);  /* ..take another vector */
8517e911b15Skarels 	}
8527e911b15Skarels 
853*e977faadSmarc 	/*---------------------------------------------------------
854*e977faadSmarc 	* setup DGA to do a DMA interrupt (transfer count = 0)	*/
8557e911b15Skarels 
8567e911b15Skarels 	dga = (struct dga *) qdmap[unit].dga;
8577e911b15Skarels 
8587e911b15Skarels 	dga->csr = (short) HALT;	      /* disable everything */
8597e911b15Skarels 	dga->ivr = (short) vector;	      /* load intrpt base vector */
8607e911b15Skarels 	dga->bytcnt_lo = (short) 0;	      /* DMA xfer count = 0 */
8617e911b15Skarels 	dga->bytcnt_hi = (short) 0;
8627e911b15Skarels 
8637e911b15Skarels 	/* turn on DMA interrupts */
8647e911b15Skarels 
8657e911b15Skarels 	dga->csr &= ~SET_DONE_FIFO;
8667e911b15Skarels 	dga->csr |= DMA_IE | DL_ENB;
8677e911b15Skarels 
8687e911b15Skarels 	DELAY(20000);			/* wait for the intrpt */
8697e911b15Skarels 
8707e911b15Skarels 	dga->csr = HALT;		/* stop the wheels */
8717e911b15Skarels 
872*e977faadSmarc /*----------
873*e977faadSmarc * exits  */
874*e977faadSmarc 
8757e911b15Skarels 	if (cvec != vector)		/* if vector != base vector.. */
8767e911b15Skarels 	    return(0);			/* ..return = 'no device' */
8777e911b15Skarels 
878*e977faadSmarc 	/*
879*e977faadSmarc 	 * score this as an existing qdss
880*e977faadSmarc 	 */
881*e977faadSmarc 	qdcount++;
882*e977faadSmarc  	ws_display_units |= (1 << unit);
883*e977faadSmarc 
8847e911b15Skarels 	return(sizeof(short));	    /* return size of QDSS I/O page reg */
8857e911b15Skarels 
8867e911b15Skarels } /* qdprobe */
8877e911b15Skarels 
8887e911b15Skarels /*****************************************************************
8897e911b15Skarels *
890*e977faadSmarc *	qdattach()... do the one-time initialization
8917e911b15Skarels *
8927e911b15Skarels ******************************************************************
8937e911b15Skarels *
8947e911b15Skarels *  calling convention:
8957e911b15Skarels *			qdattach(ui);
8967e911b15Skarels *			struct uba_device *ui;
8977e911b15Skarels *
8987e911b15Skarels *		where: ui - pointer to the QDSS's uba_device structure
8997e911b15Skarels *
9007e911b15Skarels *  side effects: none
9017e911b15Skarels *	 return: none
9027e911b15Skarels *
9037e911b15Skarels *************************/
9047e911b15Skarels 
9057e911b15Skarels qdattach(ui)
9067e911b15Skarels struct uba_device *ui;
9077e911b15Skarels {
9087e911b15Skarels 	register u_int unit;		/* QDSS module # for this call */
9097e911b15Skarels 
9107e911b15Skarels 	unit = ui->ui_unit;		/* get QDSS number */
9117e911b15Skarels 
912*e977faadSmarc /*----------------------------------
913*e977faadSmarc * init "qdflags[]" for this QDSS */
9147e911b15Skarels 
9157e911b15Skarels 	qdflags[unit].inuse = 0;	/* init inuse variable EARLY! */
9167e911b15Skarels 	qdflags[unit].mapped = 0;
917*e977faadSmarc 	qdflags[unit].kernel_loop = -1;
9187e911b15Skarels 	qdflags[unit].user_dma = 0;
9197e911b15Skarels 	qdflags[unit].curs_acc = ACC_OFF;
9207e911b15Skarels 	qdflags[unit].curs_thr = 128;
9217e911b15Skarels 	qdflags[unit].tab_res = 2;	/* default tablet resolution factor */
9227e911b15Skarels 	qdflags[unit].duart_imask = 0;	/* init shadow variables */
9237e911b15Skarels 	qdflags[unit].adder_ie = 0;
9247e911b15Skarels 
925*e977faadSmarc /*----------------------------------------------------------------------
9267e911b15Skarels * init structures used in kbd/mouse interrupt service.	This code must
927*e977faadSmarc * come after the "init_shared()" routine has run since that routine inits
928*e977faadSmarc * the eq_header[unit] structure used here.   */
9297e911b15Skarels 
930*e977faadSmarc 	/*--------------------------------------------
931*e977faadSmarc 	* init the "latest mouse report" structure */
9327e911b15Skarels 
9337e911b15Skarels 	last_rep[unit].state = 0;
9347e911b15Skarels 	last_rep[unit].dx = 0;
9357e911b15Skarels 	last_rep[unit].dy = 0;
9367e911b15Skarels 	last_rep[unit].bytcnt = 0;
9377e911b15Skarels 
938*e977faadSmarc 	/*------------------------------------------------
939*e977faadSmarc 	* init the event queue (except mouse position) */
9407e911b15Skarels 
9417e911b15Skarels 	eq_header[unit]->header.events = (struct _vs_event *)
9427e911b15Skarels 					  ((int)eq_header[unit]
9437e911b15Skarels 					   + sizeof(struct qdinput));
9447e911b15Skarels 
9457e911b15Skarels 	eq_header[unit]->header.size = MAXEVENTS;
9467e911b15Skarels 	eq_header[unit]->header.head = 0;
9477e911b15Skarels 	eq_header[unit]->header.tail = 0;
9487e911b15Skarels 
949*e977faadSmarc /*------------------------------------------
950*e977faadSmarc * init single process access lock switch */
9517e911b15Skarels 
9527e911b15Skarels 	one_only[unit] = 0;
9537e911b15Skarels 
9547e911b15Skarels } /* qdattach */
9557e911b15Skarels 
9567e911b15Skarels /***************************************************************
9577e911b15Skarels *
958*e977faadSmarc *	qdopen()... open a minor device
9597e911b15Skarels *
9607e911b15Skarels ****************************************************************
9617e911b15Skarels *
9627e911b15Skarels *  calling convention: qdopen(dev, flag);
9637e911b15Skarels *		       dev_t dev;
9647e911b15Skarels *		       int flag;
9657e911b15Skarels *
9667e911b15Skarels *  side effects: none
9677e911b15Skarels *
9687e911b15Skarels *********************/
9697e911b15Skarels 
9707e911b15Skarels qdopen(dev, flag)
9717e911b15Skarels dev_t dev;
9727e911b15Skarels int flag;
9737e911b15Skarels {
9747e911b15Skarels 	register struct uba_device *ui; /* ptr to uba structures */
9757e911b15Skarels 	register struct dga *dga;	/* ptr to gate array struct */
9767e911b15Skarels 	register struct tty *tp;
9777e911b15Skarels 
9787e911b15Skarels 	struct adder *adder;
9797e911b15Skarels 	struct duart *duart;
9807e911b15Skarels 
9817e911b15Skarels 	u_int unit;
9827e911b15Skarels 	u_int minor_dev;
9837e911b15Skarels 	int s;
9847e911b15Skarels 
9857e911b15Skarels 	minor_dev = minor(dev); /* get QDSS minor device number */
9867e911b15Skarels 	unit = minor_dev >> 2;
9877e911b15Skarels 
988*e977faadSmarc /*---------------------------------
989*e977faadSmarc * check for illegal conditions	*/
9907e911b15Skarels 
9917e911b15Skarels 	ui = qdinfo[unit];		/* get ptr to QDSS device struct */
9927e911b15Skarels 
9937e911b15Skarels 	if (ui == 0  || ui->ui_alive == 0)
9947e911b15Skarels 	    return(ENXIO);		/* no such device or address */
9957e911b15Skarels 
996*e977faadSmarc /*--------------
997*e977faadSmarc * init stuff */
9987e911b15Skarels 
9997e911b15Skarels 	adder = (struct adder *) qdmap[unit].adder;
10007e911b15Skarels 	duart = (struct duart *) qdmap[unit].duart;
10017e911b15Skarels 	dga = (struct dga *) qdmap[unit].dga;
10027e911b15Skarels 
1003*e977faadSmarc /*------------------------------------
1004*e977faadSmarc * if this is the graphic device... */
10057e911b15Skarels 
10067e911b15Skarels 	if ((minor_dev & 0x03) == 2) {
10077e911b15Skarels 
10087e911b15Skarels 	    if (one_only[unit] != 0)
10097e911b15Skarels 		return(EBUSY);
10107e911b15Skarels 	    else
10117e911b15Skarels 		one_only[unit] = 1;
10127e911b15Skarels 
10137e911b15Skarels 	    qdflags[unit].inuse |= GRAPHIC_DEV;  /* graphics dev is open */
10147e911b15Skarels 
10157e911b15Skarels 	    /* enble kbd & mouse intrpts in DUART mask reg */
10167e911b15Skarels 
10177e911b15Skarels 	    qdflags[unit].duart_imask |= 0x22;
10187e911b15Skarels 	    duart->imask = qdflags[unit].duart_imask;
10197e911b15Skarels 
1020*e977faadSmarc /*------------------------------------------------------------------
1021*e977faadSmarc * if the open call is to the console or the alternate console... */
1022*e977faadSmarc 
1023*e977faadSmarc 	} else if ((minor_dev & 0x03) != 2) {
10247e911b15Skarels 
10257e911b15Skarels 	    qdflags[unit].inuse |= CONS_DEV;  /* mark console as open */
10267e911b15Skarels 	    dga->csr |= CURS_ENB;
10277e911b15Skarels 
10287e911b15Skarels 	    qdflags[unit].duart_imask |= 0x02;
10297e911b15Skarels 	    duart->imask = qdflags[unit].duart_imask;
10307e911b15Skarels 
10317e911b15Skarels 	    /*-------------------------------
10327e911b15Skarels 	    * some setup for tty handling */
10337e911b15Skarels 
10347e911b15Skarels 	    tp = &qd_tty[minor_dev];
10357e911b15Skarels 
10367e911b15Skarels 	    tp->t_addr = ui->ui_addr;
10377e911b15Skarels 	    tp->t_oproc = qdstart;
1038*e977faadSmarc #ifdef notdef	/* never */
1039*e977faadSmarc 	/*---------------------------------------------------------------------
1040*e977faadSmarc 	* Look at the compatibility mode to specify correct default parameters
1041*e977faadSmarc 	* and to insure only standard specified functionality. */
1042*e977faadSmarc 	if ((u.u_procp->p_progenv == A_SYSV) ||
1043*e977faadSmarc 		(u.u_procp->p_progenv == A_POSIX)) {
1044*e977faadSmarc 		flag |= O_TERMIO;
1045*e977faadSmarc 		tp->t_line = TERMIODISC;
1046*e977faadSmarc 	}
1047*e977faadSmarc #endif /*notdef*/
10487e911b15Skarels 
10497e911b15Skarels 	    if ((tp->t_state & TS_ISOPEN) == 0) {
10507e911b15Skarels 
10517e911b15Skarels 		ttychars(tp);
1052*e977faadSmarc 		tp->t_flags = IFLAGS;
10537e911b15Skarels 		tp->t_ispeed = B9600;
10547e911b15Skarels 		tp->t_ospeed = B9600;
1055*e977faadSmarc 		tp->t_state = TS_ISOPEN | TS_CARR_ON;
1056*e977faadSmarc 
1057*e977faadSmarc #ifdef notdef	/* never */
1058*e977faadSmarc 		tp->t_cflag = tp->t_cflag_ext = B9600;
1059*e977faadSmarc 		tp->t_iflag_ext = 0;
1060*e977faadSmarc 		tp->t_oflag_ext = 0;
1061*e977faadSmarc 		tp->t_lflag_ext = 0;
10627e911b15Skarels 
106324f67f6bSmarc 		if( (minor_dev & 0x03) == 0 ) {
1064*e977faadSmarc 			/*----------------------------------------------------
1065*e977faadSmarc 			* Ultrix defaults to a "COOKED" mode on the first
1066*e977faadSmarc 			* open, while termio defaults to a "RAW" style.
1067*e977faadSmarc 			* Base this decision by a flag set in the termio
1068*e977faadSmarc 			* emulation routine for open, or set by an explicit
1069*e977faadSmarc 			* ioctl call. */
1070*e977faadSmarc 
1071*e977faadSmarc 			if ( flag & O_TERMIO ) {
1072*e977faadSmarc 				/*--------------------------------------
1073*e977faadSmarc 				* Provide a termio style environment.
1074*e977faadSmarc 				* "RAW" style by default. */
1075*e977faadSmarc 
1076*e977faadSmarc 				tp->t_flags = RAW;
1077*e977faadSmarc 				tp->t_iflag = 0;
1078*e977faadSmarc 				tp->t_oflag = 0;
1079*e977faadSmarc 				tp->t_cflag |= CS8|CREAD|HUPCL;
1080*e977faadSmarc 				tp->t_lflag = 0;
1081*e977faadSmarc 
1082*e977faadSmarc 				/*-------------------------------------
1083*e977faadSmarc 				 * Change to System V line discipline.*/
1084*e977faadSmarc 
1085*e977faadSmarc 				tp->t_line = TERMIODISC;
1086*e977faadSmarc 				/*-----------------------------------------
1087*e977faadSmarc 				* The following three control chars have
1088*e977faadSmarc 				* different default values than ULTRIX.	*/
1089*e977faadSmarc 
1090*e977faadSmarc 	 			tp->t_cc[VERASE] = '#';
1091*e977faadSmarc 	 			tp->t_cc[VKILL] = '@';
1092*e977faadSmarc 	 			tp->t_cc[VINTR] = 0177;
1093*e977faadSmarc  				tp->t_cc[VMIN] = 6;
1094*e977faadSmarc  				tp->t_cc[VTIME] = 1;
1095*e977faadSmarc 			} else {
1096*e977faadSmarc 				/*--------------------------------------
1097*e977faadSmarc 				* Provide a backward compatible ULTRIX
1098*e977faadSmarc 				* environment.  "COOKED" style.	*/
1099*e977faadSmarc 
1100*e977faadSmarc 				tp->t_flags = IFLAGS;
1101*e977faadSmarc 				tp->t_iflag = IFLAG;
1102*e977faadSmarc 				tp->t_oflag = OFLAG;
1103*e977faadSmarc 				tp->t_lflag = LFLAG;
1104*e977faadSmarc 				tp->t_cflag |= CFLAG;
1105*e977faadSmarc 			}
110624f67f6bSmarc 		}
110724f67f6bSmarc 		else {
11087e911b15Skarels 		    tp->t_flags = RAW;
1109*e977faadSmarc 		    tp->t_iflag = 0;
1110*e977faadSmarc 		    tp->t_oflag = 0;
1111*e977faadSmarc 		    tp->t_cflag |= CS8|CREAD|HUPCL;
1112*e977faadSmarc 		    tp->t_lflag = 0;
11137e911b15Skarels 		}
1114*e977faadSmarc                 if( (minor_dev & 0x03) == 1 )
1115*e977faadSmarc                     tp->t_iflag |= IXOFF;	/* flow control for qconsole */
1116*e977faadSmarc #endif /*notdef*/
111724f67f6bSmarc 	    }
11187e911b15Skarels 
11197e911b15Skarels 	    /*----------------------------------------
11207e911b15Skarels 	    * enable intrpts, open line discipline */
11217e911b15Skarels 
11227e911b15Skarels 	    dga->csr |= GLOBAL_IE;	/* turn on the interrupts */
11237e911b15Skarels 	    return ((*linesw[tp->t_line].l_open)(dev, tp));
11247e911b15Skarels 	}
11257e911b15Skarels 
11267e911b15Skarels 	dga->csr |= GLOBAL_IE;	/* turn on the interrupts */
11277e911b15Skarels 	return(0);
11287e911b15Skarels 
11297e911b15Skarels } /* qdopen */
11307e911b15Skarels 
11317e911b15Skarels /***************************************************************
11327e911b15Skarels *
1133*e977faadSmarc *	qdclose()... clean up on the way out
11347e911b15Skarels *
11357e911b15Skarels ****************************************************************
11367e911b15Skarels *
11377e911b15Skarels *  calling convention: qdclose();
11387e911b15Skarels *
11397e911b15Skarels *  side effects: none
11407e911b15Skarels *
11417e911b15Skarels *  return: none
11427e911b15Skarels *
11437e911b15Skarels *********************/
11447e911b15Skarels 
11457e911b15Skarels qdclose(dev, flag)
11467e911b15Skarels dev_t dev;
11477e911b15Skarels int flag;
11487e911b15Skarels {
11497e911b15Skarels 	register struct tty *tp;
11507e911b15Skarels 	register struct qdmap *qd;
11517e911b15Skarels 	register int *ptep;
11527e911b15Skarels 	int i;				/* SIGNED index */
11537e911b15Skarels 
11547e911b15Skarels 	struct dga *dga;		/* gate array register map pointer */
11557e911b15Skarels 	struct duart *duart;
11567e911b15Skarels 	struct adder *adder;
11577e911b15Skarels 
11587e911b15Skarels 	u_int unit;
11597e911b15Skarels 	u_int minor_dev;
11607e911b15Skarels 	u_int mapix;
11617e911b15Skarels 
11627e911b15Skarels 	minor_dev = minor(dev); 	/* get minor device number */
11637e911b15Skarels 	unit = minor_dev >> 2;		/* get QDSS number */
11647e911b15Skarels 	qd = &qdmap[unit];
11657e911b15Skarels 
1166*e977faadSmarc /*------------------------------------
1167*e977faadSmarc * if this is the graphic device... */
11687e911b15Skarels 
11697e911b15Skarels 	if ((minor_dev & 0x03) == 2) {
1170*e977faadSmarc 
1171*e977faadSmarc 	    /*-----------------
1172*e977faadSmarc 	    * unlock driver */
1173*e977faadSmarc 
1174*e977faadSmarc 	    if (one_only[unit] != 1)
11757e911b15Skarels 		return(EBUSY);
11767e911b15Skarels 	    else
11777e911b15Skarels 		one_only[unit] = 0;
11787e911b15Skarels 
1179*e977faadSmarc 	    /*----------------------------
1180*e977faadSmarc 	    * re-protect device memory */
11817e911b15Skarels 
11827e911b15Skarels 	    if (qdflags[unit].mapped & MAPDEV) {
11837e911b15Skarels 
1184*e977faadSmarc 		/*----------------
1185*e977faadSmarc 		* TEMPLATE RAM */
11867e911b15Skarels 
118724f67f6bSmarc 		mapix = VTOP((int)qd->template) - VTOP(qvmem[0]);
118824f67f6bSmarc 		ptep = (int *)(QVmap[0] + mapix);
11897e911b15Skarels 
11907e911b15Skarels 		for (i = VTOP(TMPSIZE); i > 0; --i)
11917e911b15Skarels 		    *ptep++ = (*ptep & ~PG_PROT) | PG_V | PG_KW;
11927e911b15Skarels 
1193*e977faadSmarc 		/*---------
1194*e977faadSmarc 		* ADDER */
11957e911b15Skarels 
119624f67f6bSmarc 		mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]);
119724f67f6bSmarc 		ptep = (int *)(QVmap[0] + mapix);
11987e911b15Skarels 
11997e911b15Skarels 		for (i = VTOP(REGSIZE); i > 0; --i)
12007e911b15Skarels 		    *ptep++ = (*ptep & ~PG_PROT) | PG_V | PG_KW;
12017e911b15Skarels 
1202*e977faadSmarc 		/*--------------
1203*e977faadSmarc 		* COLOR MAPS */
12047e911b15Skarels 
120524f67f6bSmarc 		mapix = VTOP((int)qd->red) - VTOP(qvmem[0]);
120624f67f6bSmarc 		ptep = (int *)(QVmap[0] + mapix);
12077e911b15Skarels 
12087e911b15Skarels 		for (i = VTOP(CLRSIZE); i > 0; --i)
12097e911b15Skarels 		    *ptep++ = (*ptep & ~PG_PROT) | PG_V | PG_KW;
12107e911b15Skarels 	    }
12117e911b15Skarels 
1212*e977faadSmarc 	    /*----------------------------------------------------
1213*e977faadSmarc 	    * re-protect DMA buffer and free the map registers */
12147e911b15Skarels 
12157e911b15Skarels 	    if (qdflags[unit].mapped & MAPDMA) {
12167e911b15Skarels 
12177e911b15Skarels 		dga = (struct dga *) qdmap[unit].dga;
12187e911b15Skarels 		adder = (struct adder *) qdmap[unit].adder;
12197e911b15Skarels 
12207e911b15Skarels 		dga->csr &= ~DMA_IE;
12217e911b15Skarels 		dga->csr &= ~0x0600;	     /* kill DMA */
12227e911b15Skarels 		adder->command = CANCEL;
12237e911b15Skarels 
12247e911b15Skarels 		/* if DMA was running, flush spurious intrpt */
12257e911b15Skarels 
12267e911b15Skarels 		if (dga->bytcnt_lo != 0) {
12277e911b15Skarels 		    dga->bytcnt_lo = 0;
12287e911b15Skarels 		    dga->bytcnt_hi = 0;
12297e911b15Skarels 		    DMA_SETIGNORE(DMAheader[unit]);
12307e911b15Skarels 		    dga->csr |= DMA_IE;
12317e911b15Skarels 		    dga->csr &= ~DMA_IE;
12327e911b15Skarels 		}
12337e911b15Skarels 
12347e911b15Skarels 		ptep = (int *)
12357e911b15Skarels 			((VTOP(DMAheader[unit]*4)) + (mfpr(SBR)|0x80000000));
12367e911b15Skarels 
12377e911b15Skarels 		for (i = (DMAbuf_size >> PGSHIFT); i > 0; --i)
12387e911b15Skarels 		    *ptep++ = (*ptep & ~PG_PROT) | PG_V | PG_KW;
12397e911b15Skarels 
12407e911b15Skarels 		ubarelse(0, &Qbus_unmap[unit]);
12417e911b15Skarels 	    }
12427e911b15Skarels 
1243*e977faadSmarc 	    /*---------------------------------------
1244*e977faadSmarc 	    * re-protect 1K (2 pages) event queue */
12457e911b15Skarels 
12467e911b15Skarels 	    if (qdflags[unit].mapped & MAPEQ) {
12477e911b15Skarels 
12487e911b15Skarels 		ptep = (int *)
12497e911b15Skarels 			((VTOP(eq_header[unit])*4) + (mfpr(SBR)|0x80000000));
12507e911b15Skarels 
12517e911b15Skarels 		*ptep++ = (*ptep & ~PG_PROT) | PG_KW | PG_V;
12527e911b15Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
12537e911b15Skarels 	    }
12547e911b15Skarels 
1255*e977faadSmarc 	    /*------------------------------------------------------------
1256*e977faadSmarc 	    * re-protect scroll param area and disable scroll intrpts  */
12577e911b15Skarels 
12587e911b15Skarels 	    if (qdflags[unit].mapped & MAPSCR) {
12597e911b15Skarels 
12607e911b15Skarels 		ptep = (int *) ((VTOP(scroll[unit]) * 4)
12617e911b15Skarels 				    + (mfpr(SBR) | 0x80000000));
12627e911b15Skarels 
12637e911b15Skarels 		/* re-protect 512 scroll param area */
12647e911b15Skarels 
12657e911b15Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
12667e911b15Skarels 
12677e911b15Skarels 		adder = (struct adder *) qdmap[unit].adder;
12687e911b15Skarels 		qdflags[unit].adder_ie &= ~FRAME_SYNC;
12697e911b15Skarels 		adder->interrupt_enable = qdflags[unit].adder_ie;
12707e911b15Skarels 	    }
12717e911b15Skarels 
1272*e977faadSmarc 	    /*-----------------------------------------------------------
1273*e977faadSmarc 	    * re-protect color map write buffer area and kill intrpts */
12747e911b15Skarels 
12757e911b15Skarels 	    if (qdflags[unit].mapped & MAPCOLOR) {
12767e911b15Skarels 
12777e911b15Skarels 		ptep = (int *) ((VTOP(color_buf[unit]) * 4)
12787e911b15Skarels 				    + (mfpr(SBR) | 0x80000000));
12797e911b15Skarels 
12807e911b15Skarels 		*ptep++ = (*ptep & ~PG_PROT) | PG_KW | PG_V;
12817e911b15Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
12827e911b15Skarels 
12837e911b15Skarels 		color_buf[unit]->status = 0;
12847e911b15Skarels 
12857e911b15Skarels 		adder = (struct adder *) qdmap[unit].adder;
12867e911b15Skarels 		qdflags[unit].adder_ie &= ~VSYNC;
12877e911b15Skarels 		adder->interrupt_enable = qdflags[unit].adder_ie;
12887e911b15Skarels 	    }
12897e911b15Skarels 
1290*e977faadSmarc 	    /*-----------------------------------
1291*e977faadSmarc 	    * flag that everthing is unmapped */
12927e911b15Skarels 
1293*e977faadSmarc 	    mtpr(TBIA, 0);		/* smash CPU's translation buf */
1294*e977faadSmarc 	    qdflags[unit].mapped = 0;	/* flag everything now unmapped */
12957e911b15Skarels 	    qdflags[unit].inuse &= ~GRAPHIC_DEV;
12967e911b15Skarels 	    qdflags[unit].curs_acc = ACC_OFF;
12977e911b15Skarels 	    qdflags[unit].curs_thr = 128;
12987e911b15Skarels 
1299*e977faadSmarc 	    /*---------------------
1300*e977faadSmarc 	    * restore the console */
13017e911b15Skarels 
13027e911b15Skarels 		dga = (struct dga *) qdmap[unit].dga;
13037e911b15Skarels 		adder = (struct adder *) qdmap[unit].adder;
13047e911b15Skarels 
13057e911b15Skarels 		dga->csr &= ~DMA_IE;
13067e911b15Skarels 		dga->csr &= ~0x0600;	/* halt the DMA! (just in case...) */
13077e911b15Skarels 		dga->csr |= DMA_ERR;	/* clear error condition */
13087e911b15Skarels 		adder->command = CANCEL;
13097e911b15Skarels 
13107e911b15Skarels 		/* if DMA was running, flush spurious intrpt */
13117e911b15Skarels 
13127e911b15Skarels 		if (dga->bytcnt_lo != 0) {
13137e911b15Skarels 		    dga->bytcnt_lo = 0;
13147e911b15Skarels 		    dga->bytcnt_hi = 0;
13157e911b15Skarels 		    DMA_SETIGNORE(DMAheader[unit]);
13167e911b15Skarels 		    dga->csr |= DMA_IE;
13177e911b15Skarels 		    dga->csr &= ~DMA_IE;
13187e911b15Skarels 		}
13197e911b15Skarels 
13207e911b15Skarels 		init_shared(unit);		/* init shared memory */
13217e911b15Skarels 		setup_dragon(unit);		/* init ADDER/VIPER */
13227e911b15Skarels 		ldcursor(unit, cons_cursor);	/* load default cursor map */
13237e911b15Skarels 		setup_input(unit);		/* init the DUART */
13247e911b15Skarels 		ldfont(unit);
13257e911b15Skarels 		cursor[unit].x = 0;
13267e911b15Skarels 		cursor[unit].y = 0;
13277e911b15Skarels 
1328*e977faadSmarc 	    /* shut off the mouse rcv intrpt and turn on kbd intrpts */
1329*e977faadSmarc 
13307e911b15Skarels 	    duart = (struct duart *) qdmap[unit].duart;
13317e911b15Skarels 	    qdflags[unit].duart_imask &= ~(0x20);
13327e911b15Skarels 	    qdflags[unit].duart_imask |= 0x02;
13337e911b15Skarels 	    duart->imask = qdflags[unit].duart_imask;
1334*e977faadSmarc 
1335*e977faadSmarc 	    /*-----------------------------------------
1336*e977faadSmarc 	    * shut off interrupts if all is closed  */
1337*e977faadSmarc 
13387e911b15Skarels 	    if (!(qdflags[unit].inuse & (CONS_DEV | ALTCONS_DEV))) {
1339*e977faadSmarc 
13407e911b15Skarels 		dga = (struct dga *) qdmap[unit].dga;
13417e911b15Skarels 		dga->csr &= ~(GLOBAL_IE | DMA_IE);
13427e911b15Skarels 	    }
13437e911b15Skarels 	}
1344*e977faadSmarc 
1345*e977faadSmarc /*----------------------------------------------------
1346*e977faadSmarc * if this is the console or the alternate console  */
1347*e977faadSmarc 
1348*e977faadSmarc 	else {
1349*e977faadSmarc 
13507e911b15Skarels 	    tp = &qd_tty[minor_dev];
13517e911b15Skarels 
13527e911b15Skarels 	    (*linesw[tp->t_line].l_close)(tp);
13537e911b15Skarels 	    ttyclose(tp);
1354*e977faadSmarc 
13557e911b15Skarels 	    tp->t_state = 0;
1356*e977faadSmarc 	    /* Remove termio flags that do not map */
1357*e977faadSmarc #ifdef notdef	/* never */
1358*e977faadSmarc 	    tp->t_iflag &= ~TERMIO_ONLY_IFLAG;
1359*e977faadSmarc 	    tp->t_oflag &= ~TERMIO_ONLY_OFLAG;
1360*e977faadSmarc 	    tp->t_cflag &= ~TERMIO_ONLY_CFLAG;
1361*e977faadSmarc 	    tp->t_lflag &= ~TERMIO_ONLY_LFLAG;
1362*e977faadSmarc #endif /*notdef*/
1363*e977faadSmarc 
13647e911b15Skarels 	    qdflags[unit].inuse &= ~CONS_DEV;
1365*e977faadSmarc 
1366*e977faadSmarc 	    /*-------------------------------------------------
1367*e977faadSmarc 	    * if graphics device is closed, kill interrupts */
1368*e977faadSmarc 
13697e911b15Skarels 	    if (!(qdflags[unit].inuse & GRAPHIC_DEV)) {
13707e911b15Skarels 		dga = (struct dga *) qdmap[unit].dga;
13717e911b15Skarels 		dga->csr &= ~(GLOBAL_IE | DMA_IE);
13727e911b15Skarels 	    }
13737e911b15Skarels 	}
13747e911b15Skarels 
1375*e977faadSmarc /*--------
1376*e977faadSmarc * exit */
1377*e977faadSmarc 
13787e911b15Skarels 	return(0);
13797e911b15Skarels 
13807e911b15Skarels } /* qdclose */
13817e911b15Skarels 
13827e911b15Skarels /***************************************************************
13837e911b15Skarels *
1384*e977faadSmarc *	qdioctl()... provide QDSS control services
13857e911b15Skarels *
13867e911b15Skarels ****************************************************************
13877e911b15Skarels *
13887e911b15Skarels *  calling convention:	qdioctl(dev, cmd, datap, flags);
13897e911b15Skarels *
13907e911b15Skarels *		where:	dev - the major/minor device number
13917e911b15Skarels *			cmd - the user-passed command argument
13927e911b15Skarels *			datap - ptr to user input buff (128 bytes max)
13937e911b15Skarels *			flags - "f_flags" from "struct file" in file.h
13947e911b15Skarels *
13957e911b15Skarels *
13967e911b15Skarels *	- here is the format for the input "cmd" argument
13977e911b15Skarels *
13987e911b15Skarels *	31     29 28	23 22	      16 15		8 7		 0
13997e911b15Skarels *	+----------------------------------------------------------------+
14007e911b15Skarels *	|I/O type|	  | buff length | device ID char |  user command |
14017e911b15Skarels *	+----------------------------------------------------------------+
14027e911b15Skarels *
14037e911b15Skarels *  Return data is in the data buffer pointed to by "datap" input spec
14047e911b15Skarels *
14057e911b15Skarels *********************/
14067e911b15Skarels 
14077e911b15Skarels qdioctl(dev, cmd, datap, flags)
14087e911b15Skarels dev_t dev;
14097e911b15Skarels int cmd;
14107e911b15Skarels caddr_t datap;
14117e911b15Skarels int flags;
14127e911b15Skarels {
14137e911b15Skarels 	register int *ptep;		/* page table entry pointer */
141424f67f6bSmarc 	register int mapix;		/* QVmap[] page table index */
14157e911b15Skarels 	register struct _vs_event *event;
14167e911b15Skarels 	register struct tty *tp;
1417*e977faadSmarc 
14187e911b15Skarels 	struct qdmap *qd;		/* pointer to device map struct */
14197e911b15Skarels 	struct dga *dga;		/* Gate Array reg structure pntr */
14207e911b15Skarels 	struct duart *duart;		/* DUART reg structure pointer */
14217e911b15Skarels 	struct adder *adder;		/* ADDER reg structure pointer */
1422*e977faadSmarc 
14237e911b15Skarels 	struct prgkbd *cmdbuf;
14247e911b15Skarels 	struct prg_cursor *curs;
14257e911b15Skarels 	struct _vs_cursor *pos;
1426*e977faadSmarc 
14277e911b15Skarels 	u_int unit = minor(dev) >> 2;	/* number of caller's QDSS */
14287e911b15Skarels 	u_int minor_dev = minor(dev);
14297e911b15Skarels 	struct uba_device *ui = qdinfo[unit];
14307e911b15Skarels 	struct qd_softc *sc = &qd_softc[ui->ui_unit];
1431*e977faadSmarc #ifdef notdef
1432*e977faadSmarc 	struct devget *devget;
1433*e977faadSmarc #endif
1434*e977faadSmarc 
14357e911b15Skarels 	int error;
14367e911b15Skarels 	int s;
1437*e977faadSmarc 
14387e911b15Skarels 	int i;				/* SIGNED index */
14397e911b15Skarels 	int sbr;			/* SBR variable (you silly boy) */
14407e911b15Skarels 	u_int ix;
1441*e977faadSmarc 
14427e911b15Skarels 	short status;
14437e911b15Skarels 	short *shortp;			/* generic pointer to a short */
14447e911b15Skarels 	char *chrp;			/* generic character pointer */
1445*e977faadSmarc 
14467e911b15Skarels 	short *temp;			/* a pointer to template RAM */
14477e911b15Skarels 
1448*e977faadSmarc /*-----------------------------------------
1449*e977faadSmarc * service graphic device ioctl commands */
1450*e977faadSmarc 
14517e911b15Skarels 	switch (cmd) {
1452*e977faadSmarc 
1453*e977faadSmarc 	    /*-------------------------------------------------
1454*e977faadSmarc 	    * extract the oldest event from the event queue */
1455*e977faadSmarc 
14567e911b15Skarels 	    case QD_GETEVENT:
1457*e977faadSmarc 
14587e911b15Skarels 		if (ISEMPTY(eq_header[unit])) {
14597e911b15Skarels 		    event = (struct _vs_event *) datap;
14607e911b15Skarels 		    event->vse_device = VSE_NULL;
14617e911b15Skarels 		    break;
14627e911b15Skarels 		}
1463*e977faadSmarc 
14647e911b15Skarels 		event = (struct _vs_event *) GETBEGIN(eq_header[unit]);
1465*e977faadSmarc 		s = spl5();
14667e911b15Skarels 		GETEND(eq_header[unit]);
14677e911b15Skarels 		splx(s);
14687e911b15Skarels 		bcopy(event, datap, sizeof(struct _vs_event));
14697e911b15Skarels 		break;
14707e911b15Skarels 
14717e911b15Skarels 	    /*-------------------------------------------------------
14727e911b15Skarels 	    * init the dragon stuff, DUART, and driver variables  */
14737e911b15Skarels 
14747e911b15Skarels 	    case QD_RESET:
14757e911b15Skarels 
14767e911b15Skarels 		init_shared(unit);		/* init shared memory */
14777e911b15Skarels 		setup_dragon(unit);	      /* init the ADDER/VIPER stuff */
14787e911b15Skarels 		clear_qd_screen(unit);
14797e911b15Skarels 		ldcursor(unit, cons_cursor);	/* load default cursor map */
14807e911b15Skarels 		ldfont(unit);			/* load the console font */
14817e911b15Skarels 		setup_input(unit);		/* init the DUART */
14827e911b15Skarels 		break;
14837e911b15Skarels 
14847e911b15Skarels 	    /*----------------------------------------
14857e911b15Skarels 	    * init the DUART and driver variables  */
14867e911b15Skarels 
14877e911b15Skarels 	    case QD_SET:
14887e911b15Skarels 
14897e911b15Skarels 		init_shared(unit);
14907e911b15Skarels 		setup_input(unit);
14917e911b15Skarels 		break;
14927e911b15Skarels 
14937e911b15Skarels 	    /*---------------------------------------------------------------
14947e911b15Skarels 	    * clear the QDSS screen.  (NOTE that this reinits the dragon) */
14957e911b15Skarels 
14967e911b15Skarels 	    case QD_CLRSCRN:
14977e911b15Skarels 
1498*e977faadSmarc #ifdef notdef	/* has caused problems and is not necessary */
14997e911b15Skarels 		setup_dragon(unit);
15007e911b15Skarels 		clear_qd_screen(unit);
1501*e977faadSmarc #endif
15027e911b15Skarels 		break;
15037e911b15Skarels 
15047e911b15Skarels 	    /*------------------------------------
15057e911b15Skarels 	    * load a cursor into template RAM  */
15067e911b15Skarels 
15077e911b15Skarels 	    case QD_WTCURSOR:
15087e911b15Skarels 
15097e911b15Skarels 		ldcursor(unit, datap);
15107e911b15Skarels 		break;
15117e911b15Skarels 
15127e911b15Skarels 	    case QD_RDCURSOR:
15137e911b15Skarels 
15147e911b15Skarels 		temp = (short *) qdmap[unit].template;
15157e911b15Skarels 
15167e911b15Skarels 		/* cursor is 32 WORDS from the end of the 8k WORD...
15177e911b15Skarels 		*  ...template space */
15187e911b15Skarels 
15197e911b15Skarels 		temp += (8 * 1024) - 32;
15207e911b15Skarels 
15217e911b15Skarels 		for (i = 0; i < 32; ++i, datap += sizeof(short))
15227e911b15Skarels 		    *(short *)datap = *temp++;
15237e911b15Skarels 		break;
15247e911b15Skarels 
15257e911b15Skarels 	    /*------------------------------
15267e911b15Skarels 	    * position the mouse cursor  */
15277e911b15Skarels 
15287e911b15Skarels 	    case QD_POSCURSOR:
15297e911b15Skarels 
15307e911b15Skarels 		dga = (struct dga *) qdmap[unit].dga;
15317e911b15Skarels 		pos = (struct _vs_cursor *) datap;
1532*e977faadSmarc 		s = spl5();
15337e911b15Skarels 		dga->x_cursor = TRANX(pos->x);
15347e911b15Skarels 		dga->y_cursor = TRANY(pos->y);
15357e911b15Skarels 		eq_header[unit]->curs_pos.x = pos->x;
15367e911b15Skarels 		eq_header[unit]->curs_pos.y = pos->y;
15377e911b15Skarels 		splx(s);
15387e911b15Skarels 		break;
15397e911b15Skarels 
15407e911b15Skarels 	    /*--------------------------------------
15417e911b15Skarels 	    * set the cursor acceleration factor */
15427e911b15Skarels 
15437e911b15Skarels 	    case QD_PRGCURSOR:
15447e911b15Skarels 
15457e911b15Skarels 		curs = (struct prg_cursor *) datap;
1546*e977faadSmarc 		s = spl5();
15477e911b15Skarels 		qdflags[unit].curs_acc = curs->acc_factor;
15487e911b15Skarels 		qdflags[unit].curs_thr = curs->threshold;
15497e911b15Skarels 		splx(s);
15507e911b15Skarels 		break;
15517e911b15Skarels 
15527e911b15Skarels 	    /*---------------------------------------
15537e911b15Skarels 	    * enable 'user write' to device pages */
15547e911b15Skarels 
15557e911b15Skarels 	    case QD_MAPDEVICE:
15567e911b15Skarels 
15577e911b15Skarels 		/*--------------
15587e911b15Skarels 		* init stuff */
15597e911b15Skarels 
15607e911b15Skarels 		qdflags[unit].mapped |= MAPDEV;
15617e911b15Skarels 		qd = (struct qdmap *) &qdmap[unit];
15627e911b15Skarels 
15637e911b15Skarels 		/*-------------------------------------
15647e911b15Skarels 		* enable user write to template RAM */
15657e911b15Skarels 
156624f67f6bSmarc 		mapix = VTOP((int)qd->template) - VTOP(qvmem[0]);
156724f67f6bSmarc 		ptep = (int *)(QVmap[0] + mapix);
15687e911b15Skarels 
15697e911b15Skarels 		for (i = VTOP(TMPSIZE); i > 0; --i)
15707e911b15Skarels 		    *ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V;
15717e911b15Skarels 
15727e911b15Skarels 		/*----------------------------------
15737e911b15Skarels 		* enable user write to registers */
15747e911b15Skarels 
157524f67f6bSmarc 		mapix = VTOP((int)qd->adder) - VTOP(qvmem[0]);
157624f67f6bSmarc 		ptep = (int *)(QVmap[0] + mapix);
15777e911b15Skarels 
15787e911b15Skarels 		for (i = VTOP(REGSIZE); i > 0; --i)
15797e911b15Skarels 		    *ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V;
15807e911b15Skarels 
15817e911b15Skarels 		/*-----------------------------------
15827e911b15Skarels 		* enable user write to color maps */
15837e911b15Skarels 
158424f67f6bSmarc 		mapix = VTOP((int)qd->red) - VTOP(qvmem[0]);
158524f67f6bSmarc 		ptep = (int *)(QVmap[0] + mapix);
15867e911b15Skarels 
15877e911b15Skarels 		for (i = VTOP(CLRSIZE); i > 0; --i)
15887e911b15Skarels 		    *ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V;
15897e911b15Skarels 
15907e911b15Skarels 		/*------------------------------
15917e911b15Skarels 		* enable user write to DUART */
15927e911b15Skarels 
159324f67f6bSmarc 		mapix = VTOP((int)qd->duart) - VTOP(qvmem[0]);
159424f67f6bSmarc 		ptep = (int *)(QVmap[0] + mapix);
15957e911b15Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V; /* duart page */
15967e911b15Skarels 
15977e911b15Skarels 		mtpr(TBIA, 0);		/* smash CPU's translation buffer */
15987e911b15Skarels 
15997e911b15Skarels 		/*------------------------------------------
16007e911b15Skarels 		* stuff qdmap structure in return buffer */
16017e911b15Skarels 
16027e911b15Skarels 		bcopy(qd, datap, sizeof(struct qdmap));
16037e911b15Skarels 		break;
16047e911b15Skarels 
16057e911b15Skarels 	    /*-------------------------------------
16067e911b15Skarels 	    * do setup for DMA by user process	*/
16077e911b15Skarels 
16087e911b15Skarels 	    case QD_MAPIOBUF:
16097e911b15Skarels 
16107e911b15Skarels 		/*------------------------------------------------
16117e911b15Skarels 		* set 'user write enable' bits for DMA buffer  */
16127e911b15Skarels 
16137e911b15Skarels 		qdflags[unit].mapped |= MAPDMA;
16147e911b15Skarels 
16157e911b15Skarels 		ptep = (int *) ((VTOP(DMAheader[unit]) * 4)
16167e911b15Skarels 				+ (mfpr(SBR) | 0x80000000));
16177e911b15Skarels 
16187e911b15Skarels 		for (i = (DMAbuf_size >> PGSHIFT); i > 0; --i)
16197e911b15Skarels 		    *ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V;
16207e911b15Skarels 
16217e911b15Skarels 		mtpr(TBIA, 0);			/* clr CPU translation buf */
16227e911b15Skarels 
16237e911b15Skarels 		/*-------------------------------------
16247e911b15Skarels 		* set up QBUS map registers for DMA */
16257e911b15Skarels 
16267e911b15Skarels 		DMAheader[unit]->QBAreg =
16277e911b15Skarels 				uballoc(0, DMAheader[unit], DMAbuf_size, 0);
16287e911b15Skarels 
16297e911b15Skarels 		if (DMAheader[unit]->QBAreg == 0)
1630*e977faadSmarc 		    printf("\nqd%d: qdioctl: QBA setup error", unit);
16317e911b15Skarels 
16327e911b15Skarels 		Qbus_unmap[unit] = DMAheader[unit]->QBAreg;
16337e911b15Skarels 		DMAheader[unit]->QBAreg &= 0x3FFFF;
16347e911b15Skarels 
16357e911b15Skarels 		/*----------------------
16367e911b15Skarels 		* return I/O buf adr */
16377e911b15Skarels 
16387e911b15Skarels 		*(int *)datap = (int) DMAheader[unit];
16397e911b15Skarels 		break;
16407e911b15Skarels 
16417e911b15Skarels 	    /*----------------------------------------------------------------
16427e911b15Skarels 	    * map the shared scroll param area and enable scroll interpts  */
16437e911b15Skarels 
16447e911b15Skarels 	    case QD_MAPSCROLL:
16457e911b15Skarels 
16467e911b15Skarels 		qdflags[unit].mapped |= MAPSCR;
16477e911b15Skarels 
16487e911b15Skarels 		ptep = (int *) ((VTOP(scroll[unit]) * 4)
16497e911b15Skarels 				+ (mfpr(SBR) | 0x80000000));
16507e911b15Skarels 
16517e911b15Skarels 		/* allow user write to scroll area */
16527e911b15Skarels 
16537e911b15Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
16547e911b15Skarels 
16557e911b15Skarels 		mtpr(TBIA, 0);			/* clr CPU translation buf */
16567e911b15Skarels 
16577e911b15Skarels 		scroll[unit]->status = 0;
16587e911b15Skarels 
16597e911b15Skarels 		adder = (struct adder *) qdmap[unit].adder;
16607e911b15Skarels 
16617e911b15Skarels 		qdflags[unit].adder_ie |= FRAME_SYNC;
16627e911b15Skarels 		adder->interrupt_enable = qdflags[unit].adder_ie;
16637e911b15Skarels 
1664*e977faadSmarc 
16657e911b15Skarels 		/* return scroll area address */
16667e911b15Skarels 
16677e911b15Skarels 		*(int *)datap = (int) scroll[unit];
16687e911b15Skarels 		break;
16697e911b15Skarels 
16707e911b15Skarels 	    /*-------------------------------------------------------------
16717e911b15Skarels 	    * unmap shared scroll param area and disable scroll intrpts */
16727e911b15Skarels 
16737e911b15Skarels 	    case QD_UNMAPSCROLL:
16747e911b15Skarels 
16757e911b15Skarels 		if (qdflags[unit].mapped & MAPSCR) {
16767e911b15Skarels 
16777e911b15Skarels 		    qdflags[unit].mapped &= ~MAPSCR;
16787e911b15Skarels 
16797e911b15Skarels 		    ptep = (int *) ((VTOP(scroll[unit]) * 4)
16807e911b15Skarels 				    + (mfpr(SBR) | 0x80000000));
16817e911b15Skarels 
16827e911b15Skarels 		    /* re-protect 512 scroll param area */
16837e911b15Skarels 
16847e911b15Skarels 		    *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
16857e911b15Skarels 
16867e911b15Skarels 		    mtpr(TBIA, 0);	/* smash CPU's translation buf */
16877e911b15Skarels 
16887e911b15Skarels 		    adder = (struct adder *) qdmap[unit].adder;
16897e911b15Skarels 		    qdflags[unit].adder_ie &= ~FRAME_SYNC;
16907e911b15Skarels 		    adder->interrupt_enable = qdflags[unit].adder_ie;
16917e911b15Skarels 		}
16927e911b15Skarels 		break;
16937e911b15Skarels 
16947e911b15Skarels 	    /*-----------------------------------------------------------
16957e911b15Skarels 	    * map shared color map write buf and turn on vsync intrpt */
16967e911b15Skarels 
16977e911b15Skarels 	    case QD_MAPCOLOR:
16987e911b15Skarels 
16997e911b15Skarels 		qdflags[unit].mapped |= MAPCOLOR;
17007e911b15Skarels 
17017e911b15Skarels 		ptep = (int *) ((VTOP(color_buf[unit]) * 4)
17027e911b15Skarels 				+ (mfpr(SBR) | 0x80000000));
17037e911b15Skarels 
17047e911b15Skarels 		/* allow user write to color map write buffer */
17057e911b15Skarels 
17067e911b15Skarels 		*ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V;
17077e911b15Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
17087e911b15Skarels 
17097e911b15Skarels 		mtpr(TBIA, 0);			/* clr CPU translation buf */
17107e911b15Skarels 
1711*e977faadSmarc 		adder = (struct adder *) qdmap[unit].adder.
17127e911b15Skarels 		qdflags[unit].adder_ie |= VSYNC;
17137e911b15Skarels 		adder->interrupt_enable = qdflags[unit].adder_ie;
17147e911b15Skarels 
1715*e977faadSmarc 		/* return color area address */
17167e911b15Skarels 
17177e911b15Skarels 		*(int *)datap = (int) color_buf[unit];
17187e911b15Skarels 		break;
17197e911b15Skarels 
17207e911b15Skarels 	    /*--------------------------------------------------------------
17217e911b15Skarels 	    * unmap shared color map write buffer and kill VSYNC intrpts */
17227e911b15Skarels 
17237e911b15Skarels 	    case QD_UNMAPCOLOR:
17247e911b15Skarels 
17257e911b15Skarels 		if (qdflags[unit].mapped & MAPCOLOR) {
17267e911b15Skarels 
17277e911b15Skarels 		    qdflags[unit].mapped &= ~MAPCOLOR;
17287e911b15Skarels 
17297e911b15Skarels 		    ptep = (int *) ((VTOP(color_buf[unit]) * 4)
17307e911b15Skarels 				    + (mfpr(SBR) | 0x80000000));
17317e911b15Skarels 
17327e911b15Skarels 		    /* re-protect color map write buffer */
17337e911b15Skarels 
17347e911b15Skarels 		    *ptep++ = (*ptep & ~PG_PROT) | PG_KW | PG_V;
17357e911b15Skarels 		    *ptep = (*ptep & ~PG_PROT) | PG_KW | PG_V;
17367e911b15Skarels 
17377e911b15Skarels 		    mtpr(TBIA, 0);	/* smash CPU's translation buf */
17387e911b15Skarels 
17397e911b15Skarels 		    adder = (struct adder *) qdmap[unit].adder;
17407e911b15Skarels 
17417e911b15Skarels 		    qdflags[unit].adder_ie &= ~VSYNC;
17427e911b15Skarels 		    adder->interrupt_enable = qdflags[unit].adder_ie;
17437e911b15Skarels 		}
17447e911b15Skarels 		break;
17457e911b15Skarels 
17467e911b15Skarels 	    /*---------------------------------------------
17477e911b15Skarels 	    * give user write access to the event queue */
17487e911b15Skarels 
17497e911b15Skarels 	    case QD_MAPEVENT:
17507e911b15Skarels 
17517e911b15Skarels 		qdflags[unit].mapped |= MAPEQ;
17527e911b15Skarels 
17537e911b15Skarels 		ptep = (int *) ((VTOP(eq_header[unit]) * 4)
17547e911b15Skarels 				+ (mfpr(SBR) | 0x80000000));
17557e911b15Skarels 
17567e911b15Skarels 		/* allow user write to 1K event queue */
17577e911b15Skarels 
17587e911b15Skarels 		*ptep++ = (*ptep & ~PG_PROT) | PG_UW | PG_V;
17597e911b15Skarels 		*ptep = (*ptep & ~PG_PROT) | PG_UW | PG_V;
17607e911b15Skarels 
17617e911b15Skarels 		mtpr(TBIA, 0);			/* clr CPU translation buf */
17627e911b15Skarels 
17637e911b15Skarels 		/* return event queue address */
17647e911b15Skarels 
17657e911b15Skarels 		*(int *)datap = (int) eq_header[unit];
17667e911b15Skarels 		break;
17677e911b15Skarels 
17687e911b15Skarels 	    /*-----------------------------------------------
17697e911b15Skarels 	    * pass caller's programming commands to LK201 */
17707e911b15Skarels 
17717e911b15Skarels 	    case QD_PRGKBD:
17727e911b15Skarels 
17737e911b15Skarels 		duart = (struct duart *) qdmap[unit].duart;
17747e911b15Skarels 		cmdbuf = (struct prgkbd *) datap;    /* pnt to kbd cmd buf */
17757e911b15Skarels 
17767e911b15Skarels 		/*----------------
17777e911b15Skarels 		* send command */
17787e911b15Skarels 
17797e911b15Skarels 		for (i = 1000; i > 0; --i) {
17807e911b15Skarels 		    if ((status = duart->statusA) & XMT_RDY) {
17817e911b15Skarels 			duart->dataA = cmdbuf->cmd;
17827e911b15Skarels 			break;
17837e911b15Skarels 		    }
17847e911b15Skarels 		}
17857e911b15Skarels 
17867e911b15Skarels 		if (i == 0) {
1787*e977faadSmarc 		    printf("\nqd%d: qdioctl: timeout on XMT_RDY [1]", unit);
17887e911b15Skarels 		    break;
17897e911b15Skarels 		}
17907e911b15Skarels 
17917e911b15Skarels 		/*----------------
17927e911b15Skarels 		* send param1? */
17937e911b15Skarels 
17947e911b15Skarels 		if (cmdbuf->cmd & LAST_PARAM)
17957e911b15Skarels 		    break;
17967e911b15Skarels 
17977e911b15Skarels 		for (i = 1000; i > 0; --i) {
17987e911b15Skarels 		    if ((status = duart->statusA) & XMT_RDY) {
17997e911b15Skarels 			duart->dataA = cmdbuf->param1;
18007e911b15Skarels 			break;
18017e911b15Skarels 		    }
18027e911b15Skarels 		}
18037e911b15Skarels 
18047e911b15Skarels 		if (i == 0) {
1805*e977faadSmarc 		    printf("\nqd%d: qdioctl: timeout on XMT_RDY [2]", unit);
18067e911b15Skarels 		    break;
18077e911b15Skarels 		}
18087e911b15Skarels 
18097e911b15Skarels 		/*----------------
18107e911b15Skarels 		* send param2? */
18117e911b15Skarels 
18127e911b15Skarels 		if (cmdbuf->param1 & LAST_PARAM)
18137e911b15Skarels 		    break;
18147e911b15Skarels 
18157e911b15Skarels 		for (i = 1000; i > 0; --i) {
18167e911b15Skarels 		    if ((status = duart->statusA) & XMT_RDY) {
18177e911b15Skarels 			duart->dataA = cmdbuf->param2;
18187e911b15Skarels 			break;
18197e911b15Skarels 		    }
18207e911b15Skarels 		}
18217e911b15Skarels 
18227e911b15Skarels 		if (i == 0) {
1823*e977faadSmarc 		    printf("\nqd%d: qdioctl: timeout on XMT_RDY [3]", unit);
18247e911b15Skarels 		    break;
18257e911b15Skarels 		}
18267e911b15Skarels 
18277e911b15Skarels 		break;
18287e911b15Skarels 
18297e911b15Skarels 	    /*----------------------------------------------------
18307e911b15Skarels 	    * pass caller's programming commands to the mouse  */
18317e911b15Skarels 
18327e911b15Skarels 	    case QD_PRGMOUSE:
18337e911b15Skarels 
18347e911b15Skarels 		duart = (struct duart *) qdmap[unit].duart;
18357e911b15Skarels 
18367e911b15Skarels 		for (i = 1000; i > 0; --i) {
18377e911b15Skarels 		    if ((status = duart->statusB) & XMT_RDY) {
18387e911b15Skarels 			duart->dataB = *datap;
18397e911b15Skarels 			break;
18407e911b15Skarels 		    }
18417e911b15Skarels 		}
18427e911b15Skarels 
18437e911b15Skarels 		if (i == 0) {
1844*e977faadSmarc 		    printf("\nqd%d: qdioctl: timeout on XMT_RDY [4]", unit);
18457e911b15Skarels 		}
18467e911b15Skarels 
18477e911b15Skarels 		break;
18487e911b15Skarels 
18497e911b15Skarels 	    /*----------------------------------------------
18507e911b15Skarels 	    * get QDSS configuration word and return it  */
18517e911b15Skarels 
18527e911b15Skarels 	    case QD_RDCONFIG:
18537e911b15Skarels 
18547e911b15Skarels 		*(short *)datap = qdflags[unit].config;
18557e911b15Skarels 		break;
18567e911b15Skarels 
1857*e977faadSmarc 	    /*--------------------------------------------------------------
1858*e977faadSmarc 	    * re-route kernel console messages to the alternate console  */
1859*e977faadSmarc 
1860*e977faadSmarc 	    case QD_KERN_LOOP:
1861*e977faadSmarc 
1862*e977faadSmarc 		qdflags[unit].kernel_loop = -1;
1863*e977faadSmarc 		break;
1864*e977faadSmarc 
1865*e977faadSmarc 	    case QD_KERN_UNLOOP:
1866*e977faadSmarc 
1867*e977faadSmarc 		qdflags[unit].kernel_loop = 0;
1868*e977faadSmarc 		break;
1869*e977faadSmarc 
18707e911b15Skarels 	    /*----------------------
18717e911b15Skarels 	    * program the tablet */
18727e911b15Skarels 
18737e911b15Skarels 	    case QD_PRGTABLET:
18747e911b15Skarels 
18757e911b15Skarels 		duart = (struct duart *) qdmap[unit].duart;
18767e911b15Skarels 
18777e911b15Skarels 		for (i = 1000; i > 0; --i) {
18787e911b15Skarels 		    if ((status = duart->statusB) & XMT_RDY) {
18797e911b15Skarels 			duart->dataB = *datap;
18807e911b15Skarels 			break;
18817e911b15Skarels 		    }
18827e911b15Skarels 		}
18837e911b15Skarels 
18847e911b15Skarels 		if (i == 0) {
1885*e977faadSmarc 		    printf("\nqd%d: qdioctl: timeout on XMT_RDY [5]", unit);
18867e911b15Skarels 		}
18877e911b15Skarels 
18887e911b15Skarels 		break;
18897e911b15Skarels 
18907e911b15Skarels 	    /*-----------------------------------------------
18917e911b15Skarels 	    * program the tablet report resolution factor */
18927e911b15Skarels 
18937e911b15Skarels 	    case QD_PRGTABRES:
18947e911b15Skarels 
18957e911b15Skarels 		qdflags[unit].tab_res = *(short *)datap;
18967e911b15Skarels 		break;
1897*e977faadSmarc #ifdef notdef	/* never */
1898*e977faadSmarc 	    case DEVIOCGET:			    /* device status */
1899*e977faadSmarc 		    devget = (struct devget *)datap;
1900*e977faadSmarc 		    bzero(devget,sizeof(struct devget));
1901*e977faadSmarc 		    devget->category = DEV_TERMINAL;
1902*e977faadSmarc 		    devget->bus = DEV_QB;
1903*e977faadSmarc 		    bcopy(DEV_VCB02,devget->interface,
1904*e977faadSmarc 			  strlen(DEV_VCB02));
1905*e977faadSmarc 		    bcopy(DEV_VR290,devget->device,
1906*e977faadSmarc 			  strlen(DEV_VR290));		    /* terminal */
1907*e977faadSmarc 		    devget->adpt_num = ui->ui_adpt;	    /* which adapter*/
1908*e977faadSmarc 		    devget->nexus_num = ui->ui_nexus;	    /* which nexus  */
1909*e977faadSmarc 		    devget->bus_num = ui->ui_ubanum;	    /* which QB     */
1910*e977faadSmarc 		    devget->ctlr_num = unit;		    /* which interf.*/
1911*e977faadSmarc 		    devget->slave_num = unit;		    /* which line   */
1912*e977faadSmarc 		    bcopy(ui->ui_driver->ud_dname,
1913*e977faadSmarc 			  devget->dev_name,
1914*e977faadSmarc 			  strlen(ui->ui_driver->ud_dname)); /* Ultrix "qd"  */
1915*e977faadSmarc 		    devget->unit_num = unit;		    /* qd line?     */
1916*e977faadSmarc 		    devget->soft_count =
1917*e977faadSmarc 			  sc->sc_softcnt;		    /* soft er. cnt.*/
1918*e977faadSmarc 		    devget->hard_count =
1919*e977faadSmarc 			  sc->sc_hardcnt;		    /* hard er cnt. */
1920*e977faadSmarc 		    devget->stat = sc->sc_flags;	    /* status	    */
1921*e977faadSmarc 		    devget->category_stat =
1922*e977faadSmarc 			  sc->sc_category_flags;	    /* cat. stat.   */
19238a2bf9b0Smarc 		    break;
1924*e977faadSmarc #endif /*notdef*/
19258a2bf9b0Smarc 
19267e911b15Skarels 	    default:
19277e911b15Skarels 		/*-----------------------------
19287e911b15Skarels 		* service tty type ioctl's  */
19297e911b15Skarels 
19307e911b15Skarels 		    if (!(minor_dev & 0x02)) {
19317e911b15Skarels 
19327e911b15Skarels 			tp = &qd_tty[minor_dev];
19337e911b15Skarels 
19347e911b15Skarels 			error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, datap, flags);
19357e911b15Skarels 			if (error >= 0) {
19367e911b15Skarels 			    return(error);
19377e911b15Skarels 			}
19387e911b15Skarels 
19397e911b15Skarels 			error = ttioctl(tp, cmd, datap, flags);
19407e911b15Skarels 			if (error >= 0) {
19417e911b15Skarels 			    return(error);
19427e911b15Skarels 			}
19437e911b15Skarels 		    }
19447e911b15Skarels 		    break;
19457e911b15Skarels 	}
19467e911b15Skarels 
19477e911b15Skarels /*--------------------------------
19487e911b15Skarels * clean up and get outta here  */
19497e911b15Skarels 
19507e911b15Skarels 	return(0);
19517e911b15Skarels 
19527e911b15Skarels } /* qdioctl */
19537e911b15Skarels 
19547e911b15Skarels /**********************************************************************
19557e911b15Skarels *
19567e911b15Skarels *	qdselect()... service select call for event queue input
19577e911b15Skarels *
19587e911b15Skarels **********************************************************************/
19597e911b15Skarels 
19607e911b15Skarels qdselect(dev, rw)
19617e911b15Skarels dev_t dev;
19627e911b15Skarels int rw;
19637e911b15Skarels {
19647e911b15Skarels 	register int s;
19657e911b15Skarels 	register int unit;
1966*e977faadSmarc 	register struct tty *tp;
1967*e977faadSmarc 	u_int minor_dev = minor(dev);
19687e911b15Skarels 
1969*e977faadSmarc 	s = spl5();
1970*e977faadSmarc 	unit = minor_dev >> 2;
19717e911b15Skarels 
19727e911b15Skarels 	switch (rw) {
19737e911b15Skarels 
1974*e977faadSmarc 	    case FREAD:
19757e911b15Skarels 
1976*e977faadSmarc 		if ((minor_dev & 0x03) == 2)
1977*e977faadSmarc 		{
1978*e977faadSmarc 		    /*
1979*e977faadSmarc 		     * this is a graphics device, so check for events
1980*e977faadSmarc 		     */
1981*e977faadSmarc 		    if(!(ISEMPTY(eq_header[unit])))
1982*e977faadSmarc 		    {
19837e911b15Skarels 		        splx(s);
1984*e977faadSmarc 		        return(1);
19857e911b15Skarels 		    }
19867e911b15Skarels 		    rsel[unit] = u.u_procp;
19877e911b15Skarels 		    qdflags[unit].selmask |= SEL_READ;
19887e911b15Skarels 		    splx(s);
19897e911b15Skarels 		    return(0);
1990*e977faadSmarc 		}
1991*e977faadSmarc 		else
1992*e977faadSmarc 		{
1993*e977faadSmarc 		    /*
1994*e977faadSmarc 		     * this is a tty device
1995*e977faadSmarc 		     */
1996*e977faadSmarc 	    	    tp = &qd_tty[minor_dev];
1997*e977faadSmarc 		    if (ttnread(tp))
1998*e977faadSmarc 			return(1);
1999*e977faadSmarc 		    tp->t_rsel = u.u_procp;
20007e911b15Skarels 		    splx(s);
2001*e977faadSmarc 		    return(0);
2002*e977faadSmarc 		}
2003*e977faadSmarc 
2004*e977faadSmarc 	    case FWRITE:
2005*e977faadSmarc 
2006*e977faadSmarc 		if ((minor(dev) & 0x03) == 2)
2007*e977faadSmarc 		{
2008*e977faadSmarc 		    /*
2009*e977faadSmarc 		     * this is a graphics device, so check for dma buffers
2010*e977faadSmarc 		     */
2011*e977faadSmarc 		    if (DMA_ISEMPTY(DMAheader[unit]))
2012*e977faadSmarc 		    {
2013*e977faadSmarc 		        splx(s);
2014*e977faadSmarc 		        return(1);
20157e911b15Skarels 		    }
20167e911b15Skarels 		    rsel[unit] = u.u_procp;
20177e911b15Skarels 		    qdflags[unit].selmask |= SEL_WRITE;
20187e911b15Skarels 		    splx(s);
20197e911b15Skarels 		    return(0);
20207e911b15Skarels 		}
2021*e977faadSmarc 		else
2022*e977faadSmarc 		{
2023*e977faadSmarc 		    /*
2024*e977faadSmarc 		     * this is a tty device
2025*e977faadSmarc 		     */
2026*e977faadSmarc 	    	    tp = &qd_tty[minor_dev];
2027*e977faadSmarc 		    if (tp->t_outq.c_cc <= TTLOWAT(tp))
2028*e977faadSmarc 			return(1);
2029*e977faadSmarc 		    tp->t_wsel = u.u_procp;
2030*e977faadSmarc 		    splx(s);
2031*e977faadSmarc 		    return(0);
2032*e977faadSmarc 		}
2033*e977faadSmarc 	}
20347e911b15Skarels 
20357e911b15Skarels } /* qdselect() */
20367e911b15Skarels 
20377e911b15Skarels /***************************************************************
20387e911b15Skarels *
20397e911b15Skarels *	qdwrite()... output to the QDSS screen as a TTY
20407e911b15Skarels *
20417e911b15Skarels ***************************************************************/
20427e911b15Skarels 
20437e911b15Skarels extern qd_strategy();
20447e911b15Skarels 
20457e911b15Skarels qdwrite(dev, uio)
20467e911b15Skarels dev_t dev;
20477e911b15Skarels struct uio *uio;
20487e911b15Skarels {
20497e911b15Skarels 	register struct tty *tp;
20507e911b15Skarels 	register int minor_dev;
20517e911b15Skarels 	register int unit;
20527e911b15Skarels 
20537e911b15Skarels 	minor_dev = minor(dev);
20547e911b15Skarels 	unit = (minor_dev >> 2) & 0x07;
20557e911b15Skarels 
20567e911b15Skarels 	/*------------------------------
20577e911b15Skarels 	* if this is the console...  */
20587e911b15Skarels 
20597e911b15Skarels 	if ((minor_dev & 0x03) != 0x02	&&
20607e911b15Skarels 	     qdflags[unit].inuse & CONS_DEV) {
20617e911b15Skarels 	    tp = &qd_tty[minor_dev];
20627e911b15Skarels 	    return ((*linesw[tp->t_line].l_write)(tp, uio));
20637e911b15Skarels 	}
20647e911b15Skarels 
20657e911b15Skarels 	/*------------------------------------------------
20667e911b15Skarels 	* else this must be a DMA xfer from user space */
20677e911b15Skarels 
20687e911b15Skarels 	else if (qdflags[unit].inuse & GRAPHIC_DEV) {
20697e911b15Skarels 	    return (physio(qd_strategy, &qdbuf[unit],
20707e911b15Skarels 			   dev, B_WRITE, minphys, uio));
20717e911b15Skarels 	}
20727e911b15Skarels }
20737e911b15Skarels 
20747e911b15Skarels /***************************************************************
20757e911b15Skarels *
20767e911b15Skarels *	qdread()... read from QDSS keyboard as a TTY
20777e911b15Skarels *
20787e911b15Skarels ***************************************************************/
20797e911b15Skarels 
20807e911b15Skarels qdread(dev, uio)
20817e911b15Skarels dev_t dev;
20827e911b15Skarels struct uio *uio;
20837e911b15Skarels {
20847e911b15Skarels 	register struct tty *tp;
20857e911b15Skarels 	register int minor_dev;
20867e911b15Skarels 	register int unit;
20877e911b15Skarels 
20887e911b15Skarels 	minor_dev = minor(dev);
20897e911b15Skarels 	unit = (minor_dev >> 2) & 0x07;
20907e911b15Skarels 
20917e911b15Skarels 	/*------------------------------
20927e911b15Skarels 	* if this is the console...  */
20937e911b15Skarels 
20947e911b15Skarels 	if ((minor_dev & 0x03) != 0x02	&&
20957e911b15Skarels 	     qdflags[unit].inuse & CONS_DEV) {
20967e911b15Skarels 	    tp = &qd_tty[minor_dev];
20977e911b15Skarels 	    return ((*linesw[tp->t_line].l_read)(tp, uio));
20987e911b15Skarels 	}
20997e911b15Skarels 
21007e911b15Skarels 	/*------------------------------------------------
21017e911b15Skarels 	* else this must be a bitmap-to-processor xfer */
21027e911b15Skarels 
21037e911b15Skarels 	else if (qdflags[unit].inuse & GRAPHIC_DEV) {
21047e911b15Skarels 	    return (physio(qd_strategy, &qdbuf[unit],
21057e911b15Skarels 			   dev, B_READ, minphys, uio));
21067e911b15Skarels 	}
21077e911b15Skarels }
21087e911b15Skarels 
21097e911b15Skarels /***************************************************************
21107e911b15Skarels *
21117e911b15Skarels *	qd_strategy()... strategy routine to do DMA
21127e911b15Skarels *
21137e911b15Skarels ***************************************************************/
21147e911b15Skarels 
21157e911b15Skarels qd_strategy(bp)
21167e911b15Skarels register struct buf *bp;
21177e911b15Skarels {
21187e911b15Skarels 	register struct dga *dga;
21197e911b15Skarels 	register struct adder *adder;
21207e911b15Skarels 
21217e911b15Skarels 	char *DMAbufp;
21227e911b15Skarels 
21237e911b15Skarels 	int QBAreg;
21247e911b15Skarels 	int bytcnt;
21257e911b15Skarels 	int s;
21267e911b15Skarels 	int unit;
21277e911b15Skarels 	int cookie;
21287e911b15Skarels 
21297e911b15Skarels 	int i,j,k;
21307e911b15Skarels 
21317e911b15Skarels 	unit = (minor(bp->b_dev) >> 2) & 0x07;
21327e911b15Skarels 
2133*e977faadSmarc /*-----------------
2134*e977faadSmarc * init pointers */
21357e911b15Skarels 
21367e911b15Skarels 	if ((QBAreg = ubasetup(0, bp, 0)) == 0) {
2137*e977faadSmarc 	    printf("\nqd%d: qd_strategy: QBA setup error", unit);
21387e911b15Skarels 	    goto STRAT_ERR;
21397e911b15Skarels 	}
21407e911b15Skarels 
21417e911b15Skarels 	dga = (struct dga *) qdmap[unit].dga;
21427e911b15Skarels 
2143*e977faadSmarc 	s = spl5();
21447e911b15Skarels 
21457e911b15Skarels 	qdflags[unit].user_dma = -1;
21467e911b15Skarels 
21477e911b15Skarels 	dga->csr |= DMA_IE;
21487e911b15Skarels 
21497e911b15Skarels 	cookie = QBAreg & 0x3FFFF;
21507e911b15Skarels 	dga->adrs_lo = (short) cookie;
21517e911b15Skarels 	dga->adrs_hi = (short) (cookie >> 16);
21527e911b15Skarels 
21537e911b15Skarels 	dga->bytcnt_lo = (short) bp->b_bcount;
21547e911b15Skarels 	dga->bytcnt_hi = (short) (bp->b_bcount >> 16);
21557e911b15Skarels 
21567e911b15Skarels 	while (qdflags[unit].user_dma) {
21577e911b15Skarels 	    sleep((caddr_t)&qdflags[unit].user_dma, QDPRIOR);
21587e911b15Skarels 	}
21597e911b15Skarels 
21607e911b15Skarels 	splx(s);
21617e911b15Skarels 	ubarelse(0, &QBAreg);
21627e911b15Skarels 
21637e911b15Skarels 	if (!(dga->csr & DMA_ERR)) {
21647e911b15Skarels 	    iodone(bp);
21657e911b15Skarels 	    return;
21667e911b15Skarels 	}
21677e911b15Skarels 
21687e911b15Skarels STRAT_ERR:
21697e911b15Skarels 	adder = (struct adder *) qdmap[unit].adder;
21707e911b15Skarels 	adder->command = CANCEL;		/* cancel adder activity */
21717e911b15Skarels 	dga->csr &= ~DMA_IE;
21727e911b15Skarels 	dga->csr &= ~0x0600;		/* halt DMA (reset fifo) */
21737e911b15Skarels 	dga->csr |= DMA_ERR;		/* clear error condition */
21747e911b15Skarels 	bp->b_flags |= B_ERROR; 	/* flag an error to physio() */
21757e911b15Skarels 
21767e911b15Skarels 	/* if DMA was running, flush spurious intrpt */
21777e911b15Skarels 
21787e911b15Skarels 	if (dga->bytcnt_lo != 0) {
21797e911b15Skarels 	    dga->bytcnt_lo = 0;
21807e911b15Skarels 	    dga->bytcnt_hi = 0;
21817e911b15Skarels 	    DMA_SETIGNORE(DMAheader[unit]);
21827e911b15Skarels 	    dga->csr |= DMA_IE;
21837e911b15Skarels 	}
21847e911b15Skarels 
21857e911b15Skarels 	iodone(bp);
21867e911b15Skarels 
21877e911b15Skarels } /* qd_strategy */
21887e911b15Skarels 
21897e911b15Skarels /*******************************************************************
21907e911b15Skarels *
21917e911b15Skarels *	qdstart()... startup output to the console screen
21927e911b15Skarels *
21937e911b15Skarels ********************************************************************
21947e911b15Skarels *
21957e911b15Skarels *	calling convention:
21967e911b15Skarels *
21977e911b15Skarels *		qdstart(tp);
2198*e977faadSmarc *		struct tty *tp; 	;pointer to tty structure
21997e911b15Skarels *
22007e911b15Skarels ********/
22017e911b15Skarels 
22027e911b15Skarels qdstart(tp)
22037e911b15Skarels register struct tty *tp;
22047e911b15Skarels {
22057e911b15Skarels 	register int which_unit, unit, c;
2206*e977faadSmarc 	register struct tty *tp0;
22077e911b15Skarels 	int s;
22087e911b15Skarels 
2209*e977faadSmarc 	int curs_on;
2210*e977faadSmarc 	struct dga *dga;
22117e911b15Skarels 
2212*e977faadSmarc 	unit = minor(tp->t_dev);
2213*e977faadSmarc 
2214*e977faadSmarc 	tp0 = &qd_tty[(unit & 0x0FC)+1];
2215*e977faadSmarc 	which_unit = (unit >> 2) & 0x3;
2216*e977faadSmarc 	unit &= 0x03;
2217*e977faadSmarc 
2218*e977faadSmarc 	s = spl5();
2219*e977faadSmarc 
2220*e977faadSmarc /*------------------------------------------------------------------
2221*e977faadSmarc * If it's currently active, or delaying, no need to do anything. */
2222*e977faadSmarc 
22237e911b15Skarels 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
22247e911b15Skarels 		goto out;
22257e911b15Skarels 
2226*e977faadSmarc /*-------------------------------------------------------------------
2227*e977faadSmarc * Display chars until the queue is empty, if the alternate console device
2228*e977faadSmarc * is open direct chars there.  Drop input from anything but the console
2229*e977faadSmarc * device on the floor.	*/
2230*e977faadSmarc /* TANDEM is set on the second subchannel for flow control. */
2231*e977faadSmarc 
22327e911b15Skarels 	while ( tp->t_outq.c_cc ) {
22337e911b15Skarels 		c = getc(&tp->t_outq);
2234*e977faadSmarc 		if (unit == 0)
2235*e977faadSmarc 		    blitc(which_unit, (char)(c & 0xFF));
2236*e977faadSmarc #ifdef notdef	/* never never never */
2237*e977faadSmarc 	    if (unit == 0) {		/* console device */
2238*e977faadSmarc 		if (tp0->t_state & TS_ISOPEN) {
2239*e977faadSmarc 		    if (tp0->t_state & TS_TBLOCK)
2240*e977faadSmarc 			goto out;
2241*e977faadSmarc 		    c = getc(&tp->t_outq);
2242*e977faadSmarc 		    (*linesw[tp0->t_line].l_rint)(c, tp0);
2243*e977faadSmarc 		} else {
2244*e977faadSmarc 		    c = getc(&tp->t_outq);
2245*e977faadSmarc 		    blitc(which_unit, (char)(c & 0xFF));
22467e911b15Skarels 		}
2247*e977faadSmarc 	    } else if (unit == 1) {	/* qconsole, do flow control */
2248*e977faadSmarc 		    c = getc(&tp->t_outq);
2249*e977faadSmarc 		    if ((tp0->t_state&TS_TBLOCK) == 0) {
2250*e977faadSmarc 			tp = &qd_tty[0];
2251*e977faadSmarc 			unit = minor(tp->t_dev);
2252*e977faadSmarc 			unit &= 0x03;
2253*e977faadSmarc 			continue;
2254*e977faadSmarc 		    } else
2255*e977faadSmarc 			goto out;
2256*e977faadSmarc 	    } else
2257*e977faadSmarc 		c = getc(&tp->t_outq);
2258*e977faadSmarc #endif
2259*e977faadSmarc 	}
2260*e977faadSmarc 
2261*e977faadSmarc /*--------------------------------------------------------
2262*e977faadSmarc * If there are sleepers, and output has drained below low
2263*e977faadSmarc * water mark, wake up the sleepers. */
2264*e977faadSmarc 
2265*e977faadSmarc 	if ( tp->t_outq.c_cc <= TTLOWAT(tp) ) {
22667e911b15Skarels 		if (tp->t_state & TS_ASLEEP){
22677e911b15Skarels 			tp->t_state &= ~TS_ASLEEP;
22687e911b15Skarels 			wakeup((caddr_t) &tp->t_outq);
22697e911b15Skarels 		}
2270*e977faadSmarc 	}
2271*e977faadSmarc 
2272*e977faadSmarc 	tp->t_state &= ~TS_BUSY;
22737e911b15Skarels 
22747e911b15Skarels out:
22757e911b15Skarels 	splx(s);
22767e911b15Skarels 
22777e911b15Skarels } /* qdstart */
22787e911b15Skarels 
22797e911b15Skarels 
22807e911b15Skarels /*******************************************************************
22817e911b15Skarels *
22827e911b15Skarels *	qdstop()... stop the tty
22837e911b15Skarels *
22847e911b15Skarels *******************************************************************/
22857e911b15Skarels 
22867e911b15Skarels qdstop(tp, flag)
22877e911b15Skarels register struct tty *tp;
22887e911b15Skarels int flag;
22897e911b15Skarels {
22907e911b15Skarels 	register int s;
22917e911b15Skarels 
2292*e977faadSmarc 	s = spl5();	/* block intrpts during state modification */
2293*e977faadSmarc 
22947e911b15Skarels 	if (tp->t_state & TS_BUSY) {
22957e911b15Skarels 	    if ((tp->t_state & TS_TTSTOP) == 0) {
22967e911b15Skarels 		tp->t_state |= TS_FLUSH;
22977e911b15Skarels 	    } else
22987e911b15Skarels 		tp->t_state &= ~TS_BUSY;
22997e911b15Skarels 	}
23007e911b15Skarels 	splx(s);
23017e911b15Skarels }
23027e911b15Skarels 
23037e911b15Skarels /*******************************************************************
23047e911b15Skarels *
23057e911b15Skarels *	blitc()... output a character to the QDSS screen
23067e911b15Skarels *
23077e911b15Skarels ********************************************************************
23087e911b15Skarels *
23097e911b15Skarels *	calling convention:
23107e911b15Skarels *
23117e911b15Skarels *		blitc(chr);
23127e911b15Skarels *		char chr;		;character to be displayed
23137e911b15Skarels *
23147e911b15Skarels ********/
23157e911b15Skarels 
23167e911b15Skarels blitc(unit, chr)
23177e911b15Skarels int unit;
2318*e977faadSmarc unsigned char chr;
23197e911b15Skarels {
23207e911b15Skarels 	register struct adder *adder;
23217e911b15Skarels 	register struct dga *dga;
23227e911b15Skarels 	register int i;
23237e911b15Skarels 
23247e911b15Skarels 	short x;
2325*e977faadSmarc 	unsigned char savechar;
23267e911b15Skarels 
2327*e977faadSmarc /*---------------
2328*e977faadSmarc * init stuff  */
23297e911b15Skarels 
23307e911b15Skarels 	adder = (struct adder *) qdmap[unit].adder;
23317e911b15Skarels 	dga = (struct dga *) qdmap[unit].dga;
23327e911b15Skarels 
2333*e977faadSmarc /*---------------------------
2334*e977faadSmarc * non display character?  */
23357e911b15Skarels 
2336*e977faadSmarc 	chr &= 0xFF;
233724f67f6bSmarc 
23387e911b15Skarels 	switch (chr) {
23397e911b15Skarels 
23407e911b15Skarels 	    case '\r':			/* return char */
23417e911b15Skarels 		cursor[unit].x = 0;
2342*e977faadSmarc 	        if (!(qdflags[unit].inuse & GRAPHIC_DEV))
23437e911b15Skarels 		    dga->x_cursor = TRANX(cursor[unit].x);
23447e911b15Skarels 		return(0);
23457e911b15Skarels 
23467e911b15Skarels 	    case '\t':			/* tab char */
23477e911b15Skarels 
23487e911b15Skarels 		for (i = 8 - ((cursor[unit].x >> 3) & 0x07); i > 0; --i) {
23497e911b15Skarels 		    blitc(unit, ' ');
23507e911b15Skarels 		}
23517e911b15Skarels 		return(0);
23527e911b15Skarels 
23537e911b15Skarels 	    case '\n':			/* line feed char */
23547e911b15Skarels 
23557e911b15Skarels 		if ((cursor[unit].y += CHAR_HEIGHT) > (863 - CHAR_HEIGHT)) {
23567e911b15Skarels 		    if (qdflags[unit].inuse & GRAPHIC_DEV) {
23577e911b15Skarels 			cursor[unit].y = 0;
23587e911b15Skarels 		    } else {
23597e911b15Skarels 			cursor[unit].y -= CHAR_HEIGHT;
23607e911b15Skarels 			scroll_up(adder);
23617e911b15Skarels 		    }
23627e911b15Skarels 		}
2363*e977faadSmarc 	        if (!(qdflags[unit].inuse & GRAPHIC_DEV))
23647e911b15Skarels 		    dga->y_cursor = TRANY(cursor[unit].y);
23657e911b15Skarels 		return(0);
23667e911b15Skarels 
23677e911b15Skarels 	    case '\b':			/* backspace char */
23687e911b15Skarels 		if (cursor[unit].x > 0) {
23697e911b15Skarels 		    cursor[unit].x -= CHAR_WIDTH;
2370*e977faadSmarc 		    blitc(unit, ' ');
2371*e977faadSmarc 		    cursor[unit].x -= CHAR_WIDTH;
2372*e977faadSmarc 	            if (!(qdflags[unit].inuse & GRAPHIC_DEV))
23737e911b15Skarels 		        dga->x_cursor = TRANX(cursor[unit].x);
23747e911b15Skarels 		}
23757e911b15Skarels 		return(0);
23767e911b15Skarels 
23777e911b15Skarels 	    default:
2378*e977faadSmarc 		/*----------------------------------------------------------
2379*e977faadSmarc 		 * Weed out unprintable characters.  Printable characters fall
2380*e977faadSmarc 		 * between space (0x20) and tilde (0x7E).  For 8-bit support
2381*e977faadSmarc 		 * another range of printable characters are those between
2382*e977faadSmarc 		 * 0xA1 and 0xFD. */
2383*e977faadSmarc 
2384*e977faadSmarc 		if ((chr < ' ') || (chr > 0xFD) || (chr < 0xA1 && chr > '~'))
23857e911b15Skarels 		    return(0);
23867e911b15Skarels 	}
23877e911b15Skarels 
2388*e977faadSmarc /*------------------------------------------
2389*e977faadSmarc * setup VIPER operand control registers  */
23907e911b15Skarels 
23917e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0001);  /* select plane #0 */
23927e911b15Skarels 	write_ID(adder, SRC1_OCR_B,
23937e911b15Skarels 			EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY);
23947e911b15Skarels 
23957e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x00FE);  /* select other planes */
23967e911b15Skarels 	write_ID(adder, SRC1_OCR_B,
23977e911b15Skarels 			EXT_SOURCE | INT_NONE | NO_ID | BAR_SHIFT_DELAY);
23987e911b15Skarels 
23997e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x00FF);  /* select all planes */
24007e911b15Skarels 	write_ID(adder, DST_OCR_B,
24017e911b15Skarels 			EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
24027e911b15Skarels 
24037e911b15Skarels 	write_ID(adder, MASK_1, 0xFFFF);
24047e911b15Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 1);
24057e911b15Skarels 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
24067e911b15Skarels 
2407*e977faadSmarc         adder->x_clip_min = 0;
2408*e977faadSmarc         adder->x_clip_max = 1024;
2409*e977faadSmarc         adder->y_clip_min = 0;
2410*e977faadSmarc         adder->y_clip_max = 864;
2411*e977faadSmarc 
2412*e977faadSmarc /*----------------------------------------
2413*e977faadSmarc * load DESTINATION origin and vectors  */
24147e911b15Skarels 
24157e911b15Skarels 	adder->fast_dest_dy = 0;
24167e911b15Skarels 	adder->slow_dest_dx = 0;
24177e911b15Skarels 	adder->error_1 = 0;
24187e911b15Skarels 	adder->error_2 = 0;
24197e911b15Skarels 
24207e911b15Skarels 	adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL;
24217e911b15Skarels 
24227e911b15Skarels 	wait_status(adder, RASTEROP_COMPLETE);
24237e911b15Skarels 
24247e911b15Skarels 	adder->destination_x = cursor[unit].x;
24257e911b15Skarels 	adder->fast_dest_dx = CHAR_WIDTH;
24267e911b15Skarels 
24277e911b15Skarels 	adder->destination_y = cursor[unit].y;
24287e911b15Skarels 	adder->slow_dest_dy = CHAR_HEIGHT;
24297e911b15Skarels 
2430*e977faadSmarc /*-----------------------------------
2431*e977faadSmarc * load SOURCE origin and vectors  */
24327e911b15Skarels 
2433*e977faadSmarc 	if (chr > '~') {
2434*e977faadSmarc 		savechar = chr;
2435*e977faadSmarc 		chr -= 34; /* These are to skip the (32) 8-bit control chars.
2436*e977faadSmarc 			      as well as DEL and 0xA0 which aren't printable */
2437*e977faadSmarc 	}
2438*e977faadSmarc 	if ((chr - ' ') > (CHARS - 1))  {
2439*e977faadSmarc 		printf("Invalid character (x)%x in blitc\n",chr);
2440*e977faadSmarc 		chr = ' ';
2441*e977faadSmarc 	}
2442*e977faadSmarc 	/* X position is modulo the number of characters per line */
2443*e977faadSmarc 	adder->source_1_x = FONT_X +
2444*e977faadSmarc 		(((chr - ' ') % (MAX_SCREEN_X/CHAR_WIDTH)) * CHAR_WIDTH);
2445*e977faadSmarc 	/* Point to either first or second row */
2446*e977faadSmarc 	adder->source_1_y = 2048 - 15 *
2447*e977faadSmarc 		(((chr - ' ')/(MAX_SCREEN_X/CHAR_WIDTH)) + 1);
24487e911b15Skarels 
24497e911b15Skarels 	adder->source_1_dx = CHAR_WIDTH;
24507e911b15Skarels 	adder->source_1_dy = CHAR_HEIGHT;
24517e911b15Skarels 
24527e911b15Skarels 	write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
24537e911b15Skarels 	adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE;
24547e911b15Skarels 
2455*e977faadSmarc /*-------------------------------------
2456*e977faadSmarc * update console cursor coordinates */
24577e911b15Skarels 
24587e911b15Skarels 	cursor[unit].x += CHAR_WIDTH;
2459*e977faadSmarc 	if (!(qdflags[unit].inuse & GRAPHIC_DEV))
24607e911b15Skarels 	    dga->x_cursor = TRANX(cursor[unit].x);
24617e911b15Skarels 
24627e911b15Skarels 	if (cursor[unit].x > (1024 - CHAR_WIDTH)) {
24637e911b15Skarels 	    blitc(unit, '\r');
24647e911b15Skarels 	    blitc(unit, '\n');
24657e911b15Skarels 	}
24667e911b15Skarels 
24677e911b15Skarels } /* blitc */
24687e911b15Skarels 
24697e911b15Skarels qdreset(){}
24707e911b15Skarels qd_init(){}
24717e911b15Skarels 
24727e911b15Skarels /******************************************************************
2473*e977faadSmarc *******************************************************************
2474*e977faadSmarc *******************************************************************
24757e911b15Skarels *
24767e911b15Skarels *	INTERRUPT SERVICE ROUTINES START HERE:
24777e911b15Skarels *
2478*e977faadSmarc *******************************************************************
2479*e977faadSmarc *******************************************************************
24807e911b15Skarels ******************************************************************/
24817e911b15Skarels 
24827e911b15Skarels /*****************************************************************
24837e911b15Skarels *
24847e911b15Skarels *	qddint()... service "DMA DONE" interrupt condition
24857e911b15Skarels *
24867e911b15Skarels *****************************************************************/
24877e911b15Skarels 
24887e911b15Skarels qddint(qd)
24897e911b15Skarels int qd;
24907e911b15Skarels {
24917e911b15Skarels 	register struct DMAreq_header *header;
24927e911b15Skarels 	register struct DMAreq *request;
24937e911b15Skarels 	register struct dga *dga;
24947e911b15Skarels 	struct adder *adder;
24957e911b15Skarels 
24967e911b15Skarels 	int cookie;			/* DMA adrs for QDSS */
24977e911b15Skarels 	int i;
24987e911b15Skarels 
24997e911b15Skarels 	spl4(); 			/* allow interval timer in */
25007e911b15Skarels 
2501*e977faadSmarc /*-----------------
2502*e977faadSmarc * init pointers */
25037e911b15Skarels 
25047e911b15Skarels 	header = DMAheader[qd]; 	    /* register for optimization */
25057e911b15Skarels 	dga = (struct dga *) qdmap[qd].dga;
25067e911b15Skarels 	adder = (struct adder *) qdmap[qd].adder;
25077e911b15Skarels 
2508*e977faadSmarc /*------------------------------------------------------------------------
2509*e977faadSmarc * if this interrupt flagged as bogus for interrupt flushing purposes.. */
25107e911b15Skarels 
25117e911b15Skarels 	if (DMA_ISIGNORE(header)) {
25127e911b15Skarels 	    DMA_CLRIGNORE(header);
25137e911b15Skarels 	    return;
25147e911b15Skarels 	}
25157e911b15Skarels 
25167e911b15Skarels /*----------------------------------------------------
25177e911b15Skarels * dump a DMA hardware error message if appropriate */
25187e911b15Skarels 
25197e911b15Skarels 	if (dga->csr & DMA_ERR) {
25207e911b15Skarels 
25217e911b15Skarels 	    if (dga->csr & PARITY_ERR)
2522*e977faadSmarc 		printf("\nqd%d: qddint: DMA hardware parity fault.", qd);
25237e911b15Skarels 
25247e911b15Skarels 	    if (dga->csr & BUS_ERR)
2525*e977faadSmarc 		printf("\nqd%d: qddint: DMA hardware bus error.", qd);
25267e911b15Skarels 	}
25277e911b15Skarels 
25287e911b15Skarels /*----------------------------------------
25297e911b15Skarels * if this was a DMA from user space... */
25307e911b15Skarels 
25317e911b15Skarels 	if (qdflags[qd].user_dma) {
25327e911b15Skarels 	    qdflags[qd].user_dma = 0;
25337e911b15Skarels 	    wakeup((caddr_t)&qdflags[qd].user_dma);
25347e911b15Skarels 	    return;
25357e911b15Skarels 	}
25367e911b15Skarels 
25377e911b15Skarels /*------------------------------------------------------------------------
25387e911b15Skarels * if we're doing DMA request queue services, field the error condition */
25397e911b15Skarels 
25407e911b15Skarels 	if (dga->csr & DMA_ERR) {
25417e911b15Skarels 
25427e911b15Skarels 	    dga->csr &= ~0x0600;		/* halt DMA (reset fifo) */
25437e911b15Skarels 	    dga->csr |= DMA_ERR;		/* clear error condition */
25447e911b15Skarels 	    adder->command = CANCEL;		/* cancel adder activity */
25457e911b15Skarels 
25467e911b15Skarels 	    DMA_SETERROR(header);	/* flag error in header status word */
25477e911b15Skarels 	    DMA_CLRACTIVE(header);
25487e911b15Skarels 	    header->DMAreq[header->oldest].DMAdone |= HARD_ERROR;
25497e911b15Skarels 	    header->newest = header->oldest;
25507e911b15Skarels 	    header->used = 0;
25517e911b15Skarels 
25527e911b15Skarels 	    if (rsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
25537e911b15Skarels 		selwakeup(rsel[qd], 0);
25547e911b15Skarels 		rsel[qd] = 0;
25557e911b15Skarels 		qdflags[qd].selmask &= ~SEL_WRITE;
25567e911b15Skarels 	    }
25577e911b15Skarels 
25587e911b15Skarels 	    if (dga->bytcnt_lo != 0) {
25597e911b15Skarels 		dga->bytcnt_lo = 0;
25607e911b15Skarels 		dga->bytcnt_hi = 0;
25617e911b15Skarels 		DMA_SETIGNORE(header);
25627e911b15Skarels 	    }
25637e911b15Skarels 
25647e911b15Skarels 	    return;
25657e911b15Skarels 	}
25667e911b15Skarels 
25677e911b15Skarels /*----------------------------------------------------------------------------
25687e911b15Skarels * if the DMA request queue is now becoming non-full, wakeup "select" client */
25697e911b15Skarels 
25707e911b15Skarels 	if (DMA_ISFULL(header)) {
25717e911b15Skarels 
25727e911b15Skarels 	    if (rsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
25737e911b15Skarels 		selwakeup(rsel[qd], 0);
25747e911b15Skarels 		rsel[qd] = 0;
25757e911b15Skarels 		qdflags[qd].selmask &= ~SEL_WRITE;
25767e911b15Skarels 	    }
25777e911b15Skarels 	}
25787e911b15Skarels 
25797e911b15Skarels 	header->DMAreq[header->oldest].DMAdone |= REQUEST_DONE;
2580*e977faadSmarc         QDlast_DMAtype = header->DMAreq[header->oldest].DMAtype;
25817e911b15Skarels 
2582*e977faadSmarc 	/* check for unexpected interrupt */
2583*e977faadSmarc 	if (DMA_ISEMPTY(header))
25847e911b15Skarels 	    return;
25857e911b15Skarels 
25867e911b15Skarels 	DMA_GETEND(header);	/* update request queue indices */
25877e911b15Skarels 
25887e911b15Skarels /*------------------------------------------------------------
25897e911b15Skarels * if no more DMA pending, wake up "select" client and exit */
25907e911b15Skarels 
25917e911b15Skarels 	if (DMA_ISEMPTY(header)) {
25927e911b15Skarels 
25937e911b15Skarels 	    if (rsel[qd] && qdflags[qd].selmask & SEL_WRITE) {
25947e911b15Skarels 		selwakeup(rsel[qd], 0);
25957e911b15Skarels 		rsel[qd] = 0;
25967e911b15Skarels 		qdflags[qd].selmask &= ~SEL_WRITE;
25977e911b15Skarels 	    }
25987e911b15Skarels 
25997e911b15Skarels 	    DMA_CLRACTIVE(header);  /* flag DMA done */
26007e911b15Skarels 	    return;
26017e911b15Skarels 	}
26027e911b15Skarels 
26037e911b15Skarels /*---------------------------
26047e911b15Skarels * initiate next DMA xfer  */
26057e911b15Skarels 
26067e911b15Skarels 	request = DMA_GETBEGIN(header);
2607*e977faadSmarc 	if (request->DMAtype != QDlast_DMAtype) {
2608*e977faadSmarc 	    	dga->csr &= ~0x0600;	  /* halt DMA (reset fifo) */
2609*e977faadSmarc 	    	adder->command = CANCEL;  /* cancel adder activity */
2610*e977faadSmarc 	}
2611*e977faadSmarc 
26127e911b15Skarels 
26137e911b15Skarels 	switch (request->DMAtype) {
26147e911b15Skarels 
26157e911b15Skarels 	    case DISPLIST:
2616*e977faadSmarc 		if (request->DMAtype != QDlast_DMAtype) {
26177e911b15Skarels 			dga->csr |= DL_ENB;
2618*e977faadSmarc 			dga->csr &= ~(BTOP_ENB | BYTE_DMA);
2619*e977faadSmarc 		}
26207e911b15Skarels 		break;
26217e911b15Skarels 
26227e911b15Skarels 	    case PTOB:
2623*e977faadSmarc 		if (request->DMAtype != QDlast_DMAtype) {
2624*e977faadSmarc 			if (request->DMAdone & BYTE_PACK)
2625*e977faadSmarc 				dga->csr |= (PTOB_ENB | BYTE_DMA);
2626*e977faadSmarc 			else {
26277e911b15Skarels 				dga->csr |= PTOB_ENB;
2628*e977faadSmarc 				dga->csr &= ~BYTE_DMA;
2629*e977faadSmarc 			}
2630*e977faadSmarc 		}
26317e911b15Skarels 		break;
26327e911b15Skarels 
26337e911b15Skarels 	    case BTOP:
2634*e977faadSmarc 		if (request->DMAtype != QDlast_DMAtype) {
2635*e977faadSmarc 			if (request->DMAdone & BYTE_PACK) {
2636*e977faadSmarc 				dga->csr &= ~DL_ENB;
2637*e977faadSmarc 				dga->csr |= (BTOP_ENB | BYTE_DMA);
2638*e977faadSmarc 			}
2639*e977faadSmarc 			else {
26407e911b15Skarels 				dga->csr |= BTOP_ENB;
2641*e977faadSmarc 				dga->csr &= ~(BYTE_DMA | DL_ENB);
2642*e977faadSmarc 			}
2643*e977faadSmarc 		}
26447e911b15Skarels 		break;
26457e911b15Skarels 	    default:
2646*e977faadSmarc 		printf("\nqd%d: qddint: illegal DMAtype parameter.", qd);
26477e911b15Skarels 		DMA_CLRACTIVE(header);	/* flag DMA done */
26487e911b15Skarels 		return;
26497e911b15Skarels 	}
26507e911b15Skarels 
26517e911b15Skarels 	if (request->DMAdone & COUNT_ZERO) {
26527e911b15Skarels 	    dga->csr &= ~SET_DONE_FIFO;
26537e911b15Skarels 	} else if (request->DMAdone & FIFO_EMPTY) {
26547e911b15Skarels 	    dga->csr |= SET_DONE_FIFO;
26557e911b15Skarels 	}
26567e911b15Skarels 
26577e911b15Skarels 	if (request->DMAdone & WORD_PACK)
26587e911b15Skarels 	    dga->csr &= ~BYTE_DMA;
26597e911b15Skarels 	else if (request->DMAdone & BYTE_PACK)
26607e911b15Skarels 	    dga->csr |= BYTE_DMA;
26617e911b15Skarels 
26627e911b15Skarels 	dga->csr |= DMA_IE;
2663*e977faadSmarc         QDlast_DMAtype = request->DMAtype;
26647e911b15Skarels 
26657e911b15Skarels 	cookie = ((int)request->bufp - (int)header) + (int)header->QBAreg;
26667e911b15Skarels 
26677e911b15Skarels 	dga->adrs_lo = (short) cookie;
26687e911b15Skarels 	dga->adrs_hi = (short) (cookie >> 16);
26697e911b15Skarels 
26707e911b15Skarels 	dga->bytcnt_lo = (short) request->length;
26717e911b15Skarels 	dga->bytcnt_hi = (short) (request->length >> 16);
26727e911b15Skarels 
26737e911b15Skarels 	return;
26747e911b15Skarels }
26757e911b15Skarels 
26767e911b15Skarels /*****************************************************************
26777e911b15Skarels *
26787e911b15Skarels *	qdaint()... ADDER interrupt service
26797e911b15Skarels *
26807e911b15Skarels *****************************************************************/
2681*e977faadSmarc int Nqdaint;
26827e911b15Skarels 
26837e911b15Skarels qdaint(qd)
26847e911b15Skarels register int qd;
26857e911b15Skarels {
26867e911b15Skarels 	register struct adder *adder;
26877e911b15Skarels 	struct color_buf *cbuf;
26887e911b15Skarels 
26897e911b15Skarels 	short stat;
26907e911b15Skarels 	int i;
26917e911b15Skarels 	register struct rgb *rgbp;
26927e911b15Skarels 	register short *red;
26937e911b15Skarels 	register short *green;
26947e911b15Skarels 	register short *blue;
26957e911b15Skarels 
26967e911b15Skarels 	spl4(); 			/* allow interval timer in */
2697*e977faadSmarc 	Nqdaint++;			/* debug */
26987e911b15Skarels 
26997e911b15Skarels 	adder = (struct adder *) qdmap[qd].adder;
27007e911b15Skarels 
27017e911b15Skarels /*------------------------------------------------------------------------
27027e911b15Skarels * service the vertical blank interrupt (VSYNC bit) by loading any pending
27037e911b15Skarels * color map load request  */
27047e911b15Skarels 
27057e911b15Skarels 	if (adder->status & VSYNC) {
27067e911b15Skarels 	    adder->status &= ~VSYNC;		/* clear the interrupt */
27077e911b15Skarels 
27087e911b15Skarels 	    cbuf = color_buf[qd];
27097e911b15Skarels 	    if (cbuf->status & LOAD_COLOR_MAP) {
27107e911b15Skarels 
27117e911b15Skarels 		red = (short *) qdmap[qd].red;
27127e911b15Skarels 		green = (short *) qdmap[qd].green;
27137e911b15Skarels 		blue = (short *) qdmap[qd].blue;
27147e911b15Skarels 
27157e911b15Skarels 		for (i = cbuf->count, rgbp = cbuf->rgb; --i >= 0; rgbp++) {
27167e911b15Skarels 
27177e911b15Skarels 		    red[rgbp->offset] = (short) rgbp->red;
27187e911b15Skarels 		    green[rgbp->offset] = (short) rgbp->green;
27197e911b15Skarels 		    blue[rgbp->offset] = (short) rgbp->blue;
27207e911b15Skarels 		}
27217e911b15Skarels 
27227e911b15Skarels 		cbuf->status &= ~LOAD_COLOR_MAP;
27237e911b15Skarels 	    }
27247e911b15Skarels 	}
27257e911b15Skarels 
27267e911b15Skarels /*-------------------------------------------------
27277e911b15Skarels * service the scroll interrupt (FRAME_SYNC bit) */
27287e911b15Skarels 
27297e911b15Skarels 	if (adder->status & FRAME_SYNC) {
27307e911b15Skarels 	    adder->status &= ~FRAME_SYNC;	/* clear the interrupt */
27317e911b15Skarels 
27327e911b15Skarels 	    if (scroll[qd]->status & LOAD_REGS) {
27337e911b15Skarels 
27347e911b15Skarels 		for ( i = 1000, adder->status = 0
27357e911b15Skarels 		    ; i > 0  &&  !((stat = adder->status) & ID_SCROLL_READY)
27367e911b15Skarels 		    ; --i);
27377e911b15Skarels 
27387e911b15Skarels 		if (i == 0) {
2739*e977faadSmarc 		    printf("\nqd%d: qdaint: timeout on ID_SCROLL_READY", qd);
27407e911b15Skarels 		    return;
27417e911b15Skarels 		}
27427e911b15Skarels 
27437e911b15Skarels 		adder->ID_scroll_data = scroll[qd]->viper_constant;
27447e911b15Skarels 		adder->ID_scroll_command = ID_LOAD | SCROLL_CONSTANT;
27457e911b15Skarels 
27467e911b15Skarels 		adder->y_scroll_constant = scroll[qd]->y_scroll_constant;
27477e911b15Skarels 		adder->y_offset_pending = scroll[qd]->y_offset;
27487e911b15Skarels 
27497e911b15Skarels 		if (scroll[qd]->status & LOAD_INDEX) {
27507e911b15Skarels 
27517e911b15Skarels 		    adder->x_index_pending = scroll[qd]->x_index_pending;
27527e911b15Skarels 		    adder->y_index_pending = scroll[qd]->y_index_pending;
27537e911b15Skarels 		}
27547e911b15Skarels 
27557e911b15Skarels 	    scroll[qd]->status = 0x00;
27567e911b15Skarels 	    }
27577e911b15Skarels 	}
27587e911b15Skarels }
27597e911b15Skarels 
27607e911b15Skarels /*****************************************************************
27617e911b15Skarels *
27627e911b15Skarels *	qdiint()... DUART input interrupt service routine
27637e911b15Skarels *
27647e911b15Skarels *****************************************************************/
27657e911b15Skarels 
27667e911b15Skarels qdiint(qd)
27677e911b15Skarels register int qd;
27687e911b15Skarels {
27697e911b15Skarels 	register struct _vs_event *event;
27707e911b15Skarels 	register struct qdinput *eqh;
27717e911b15Skarels 
27727e911b15Skarels 	struct dga *dga;
27737e911b15Skarels 	struct duart *duart;
27747e911b15Skarels 	struct mouse_report *new_rep;
27757e911b15Skarels 
27767e911b15Skarels 	struct uba_device *ui;
27777e911b15Skarels 	struct tty *tp;
27787e911b15Skarels 
2779*e977faadSmarc 	u_short chr;
27807e911b15Skarels 	int i,j;
27817e911b15Skarels 	int k,l;
27827e911b15Skarels 
27837e911b15Skarels 	u_short status;
27847e911b15Skarels 	u_short data;
27857e911b15Skarels 	u_short key;
27867e911b15Skarels 
27877e911b15Skarels 	char do_wakeup = 0;		/* flag to do a select wakeup call */
27887e911b15Skarels 	char a, b, c;			/* mouse button test variables */
27897e911b15Skarels 
27907e911b15Skarels 	spl4(); 			/* allow interval timer in */
27917e911b15Skarels 
27927e911b15Skarels 	eqh = eq_header[qd];		/* optimized as a register */
27937e911b15Skarels 	new_rep = &current_rep[qd];
27947e911b15Skarels 	duart = (struct duart *) qdmap[qd].duart;
27957e911b15Skarels 
27967e911b15Skarels /*-----------------------------------------
27977e911b15Skarels * if the graphic device is turned on..	*/
27987e911b15Skarels 
27997e911b15Skarels 	if (qdflags[qd].inuse & GRAPHIC_DEV) {
28007e911b15Skarels 
28017e911b15Skarels 	    /*---------------
28027e911b15Skarels 	    * empty DUART */
28037e911b15Skarels 
28047e911b15Skarels 	    while ((status = duart->statusA) & RCV_RDY	||
28057e911b15Skarels 		   (status = duart->statusB) & RCV_RDY) {
28067e911b15Skarels 
28077e911b15Skarels 		/*---------------------------------
28087e911b15Skarels 		* pick up LK-201 input (if any) */
28097e911b15Skarels 
28107e911b15Skarels 		if ((status = duart->statusA) & RCV_RDY) {
28117e911b15Skarels 
28127e911b15Skarels 		    /* if error condition, then reset it */
28137e911b15Skarels 
28147e911b15Skarels 		    if ((status = duart->statusA) & 0x70) {
28157e911b15Skarels 			duart->cmdA = 0x40;
28167e911b15Skarels 			continue;
28177e911b15Skarels 		    }
28187e911b15Skarels 
28197e911b15Skarels 		    /* event queue full now? (overflow condition) */
28207e911b15Skarels 
28217e911b15Skarels 		    if (ISFULL(eqh) == TRUE) {
2822*e977faadSmarc 			printf("\nqd%d: qdiint: event queue overflow", qd);
28237e911b15Skarels 			break;
28247e911b15Skarels 		    }
28257e911b15Skarels 
28267e911b15Skarels 		    /*--------------------------------------
28277e911b15Skarels 		    * Check for various keyboard errors  */
28287e911b15Skarels 
28297e911b15Skarels 		    key = duart->dataA & 0xFF;
28307e911b15Skarels 
28317e911b15Skarels 		    if( key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
28327e911b15Skarels 			key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
2833*e977faadSmarc 			printf("\nqd%d: qdiint: keyboard error, code = %x",qd,key);
28347e911b15Skarels 			return(0);
28357e911b15Skarels 		    }
28367e911b15Skarels 
28377e911b15Skarels 		    if (key < LK_LOWEST)
28387e911b15Skarels 			return(0);
28397e911b15Skarels 
28407e911b15Skarels 		    ++do_wakeup;	/* request a select wakeup call */
28417e911b15Skarels 
28427e911b15Skarels 		    event = PUTBEGIN(eqh);
28437e911b15Skarels 		    PUTEND(eqh);
28447e911b15Skarels 
28457e911b15Skarels 		    event->vse_key = key;
28467e911b15Skarels 		    event->vse_key &= 0x00FF;
28477e911b15Skarels 		    event->vse_x = eqh->curs_pos.x;
28487e911b15Skarels 		    event->vse_y = eqh->curs_pos.y;
28497e911b15Skarels 		    event->vse_time = TOY;
28507e911b15Skarels 		    event->vse_type = VSE_BUTTON;
28517e911b15Skarels 		    event->vse_direction = VSE_KBTRAW;
28527e911b15Skarels 		    event->vse_device = VSE_DKB;
28537e911b15Skarels 		}
28547e911b15Skarels 
28557e911b15Skarels 		/*-------------------------------------
28567e911b15Skarels 		* pick up the mouse input (if any)  */
28577e911b15Skarels 
28587e911b15Skarels 		if ((status = duart->statusB) & RCV_RDY  &&
28597e911b15Skarels 		     qdflags[qd].pntr_id == MOUSE_ID) {
28607e911b15Skarels 
28617e911b15Skarels 		    if (status & 0x70) {
28627e911b15Skarels 			duart->cmdB = 0x40;
28637e911b15Skarels 			continue;
28647e911b15Skarels 		    }
28657e911b15Skarels 
28667e911b15Skarels 		    /* event queue full now? (overflow condition) */
28677e911b15Skarels 
28687e911b15Skarels 		    if (ISFULL(eqh) == TRUE) {
2869*e977faadSmarc 			printf("\nqd%d: qdiint: event queue overflow", qd);
28707e911b15Skarels 			break;
28717e911b15Skarels 		    }
28727e911b15Skarels 
28737e911b15Skarels 		    data = duart->dataB;      /* get report byte */
28747e911b15Skarels 		    ++new_rep->bytcnt;	      /* bump report byte count */
28757e911b15Skarels 
28767e911b15Skarels 		    /*---------------------------
28777e911b15Skarels 		    * if 1st byte of report.. */
28787e911b15Skarels 
28797e911b15Skarels 		    if ( data & START_FRAME) {
28807e911b15Skarels 			new_rep->state = data;
28817e911b15Skarels 			if (new_rep->bytcnt > 1) {
28827e911b15Skarels 			    new_rep->bytcnt = 1;    /* start of new frame */
28837e911b15Skarels 			    continue;		    /* ..continue looking */
28847e911b15Skarels 			}
28857e911b15Skarels 		    }
28867e911b15Skarels 
28877e911b15Skarels 		    /*---------------------------
28887e911b15Skarels 		    * if 2nd byte of report.. */
28897e911b15Skarels 
28907e911b15Skarels 		    else if (new_rep->bytcnt == 2) {
28917e911b15Skarels 			new_rep->dx = data & 0x00FF;
28927e911b15Skarels 		    }
28937e911b15Skarels 
28947e911b15Skarels 		    /*-------------------------------------------------
28957e911b15Skarels 		    * if 3rd byte of report, load input event queue */
28967e911b15Skarels 
28977e911b15Skarels 		    else if (new_rep->bytcnt == 3) {
28987e911b15Skarels 
28997e911b15Skarels 			new_rep->dy = data & 0x00FF;
29007e911b15Skarels 			new_rep->bytcnt = 0;
29017e911b15Skarels 
29027e911b15Skarels 			/*-----------------------------------
29037e911b15Skarels 			* if mouse position has changed.. */
29047e911b15Skarels 
29057e911b15Skarels 			if (new_rep->dx != 0  ||  new_rep->dy != 0) {
29067e911b15Skarels 
29077e911b15Skarels 			    /*---------------------------------------------
29087e911b15Skarels 			    * calculate acceleration factor, if needed	*/
29097e911b15Skarels 
29107e911b15Skarels 			    if (qdflags[qd].curs_acc > ACC_OFF) {
29117e911b15Skarels 
29127e911b15Skarels 				if (qdflags[qd].curs_thr <= new_rep->dx)
29137e911b15Skarels 				    new_rep->dx +=
29147e911b15Skarels 					(new_rep->dx - qdflags[qd].curs_thr)
29157e911b15Skarels 					 * qdflags[qd].curs_acc;
29167e911b15Skarels 
29177e911b15Skarels 				if (qdflags[qd].curs_thr <= new_rep->dy)
29187e911b15Skarels 				    new_rep->dy +=
29197e911b15Skarels 					(new_rep->dy - qdflags[qd].curs_thr)
29207e911b15Skarels 					 * qdflags[qd].curs_acc;
29217e911b15Skarels 			    }
29227e911b15Skarels 
29237e911b15Skarels 			    /*-------------------------------------
29247e911b15Skarels 			    * update cursor position coordinates */
29257e911b15Skarels 
29267e911b15Skarels 			    if (new_rep->state & X_SIGN) {
29277e911b15Skarels 				eqh->curs_pos.x += new_rep->dx;
29287e911b15Skarels 				if (eqh->curs_pos.x > 1023)
29297e911b15Skarels 				    eqh->curs_pos.x = 1023;
29307e911b15Skarels 			    }
29317e911b15Skarels 			    else {
29327e911b15Skarels 				eqh->curs_pos.x -= new_rep->dx;
29337e911b15Skarels 				if (eqh->curs_pos.x < -15)
29347e911b15Skarels 				    eqh->curs_pos.x = -15;
29357e911b15Skarels 			    }
29367e911b15Skarels 
29377e911b15Skarels 			    if (new_rep->state & Y_SIGN) {
29387e911b15Skarels 				 eqh->curs_pos.y -= new_rep->dy;
29397e911b15Skarels 				 if (eqh->curs_pos.y < -15)
29407e911b15Skarels 				     eqh->curs_pos.y = -15;
29417e911b15Skarels 			    }
29427e911b15Skarels 			    else {
29437e911b15Skarels 				eqh->curs_pos.y += new_rep->dy;
29447e911b15Skarels 				if (eqh->curs_pos.y > 863)
29457e911b15Skarels 				    eqh->curs_pos.y = 863;
29467e911b15Skarels 			    }
29477e911b15Skarels 
29487e911b15Skarels 			    /*---------------------------------
29497e911b15Skarels 			    * update cursor screen position */
29507e911b15Skarels 
29517e911b15Skarels 			    dga = (struct dga *) qdmap[qd].dga;
29527e911b15Skarels 			    dga->x_cursor = TRANX(eqh->curs_pos.x);
29537e911b15Skarels 			    dga->y_cursor = TRANY(eqh->curs_pos.y);
29547e911b15Skarels 
29557e911b15Skarels 			    /*--------------------------------------------
29567e911b15Skarels 			    * if cursor is in the box, no event report */
29577e911b15Skarels 
29587e911b15Skarels 			    if (eqh->curs_pos.x <= eqh->curs_box.right	&&
29597e911b15Skarels 				eqh->curs_pos.x >= eqh->curs_box.left  &&
29607e911b15Skarels 				eqh->curs_pos.y >= eqh->curs_box.top  &&
29617e911b15Skarels 				eqh->curs_pos.y <= eqh->curs_box.bottom ) {
29627e911b15Skarels 				    goto GET_MBUTTON;
29637e911b15Skarels 			    }
29647e911b15Skarels 
29657e911b15Skarels 			    /*---------------------------------
29667e911b15Skarels 			    * report the mouse motion event */
29677e911b15Skarels 
29687e911b15Skarels 			    event = PUTBEGIN(eqh);
29697e911b15Skarels 			    PUTEND(eqh);
29707e911b15Skarels 
29717e911b15Skarels 			    ++do_wakeup;   /* request a select wakeup call */
29727e911b15Skarels 
29737e911b15Skarels 			    event->vse_x = eqh->curs_pos.x;
29747e911b15Skarels 			    event->vse_y = eqh->curs_pos.y;
29757e911b15Skarels 
29767e911b15Skarels 			    event->vse_device = VSE_MOUSE;  /* mouse */
29777e911b15Skarels 			    event->vse_type = VSE_MMOTION;  /* pos changed */
29787e911b15Skarels 			    event->vse_key = 0;
29797e911b15Skarels 			    event->vse_direction = 0;
29807e911b15Skarels 			    event->vse_time = TOY;	/* time stamp */
29817e911b15Skarels 			}
29827e911b15Skarels 
29837e911b15Skarels GET_MBUTTON:
29847e911b15Skarels 			/*-------------------------------
29857e911b15Skarels 			* if button state has changed */
29867e911b15Skarels 
29877e911b15Skarels 			a = new_rep->state & 0x07;    /*mask nonbutton bits */
29887e911b15Skarels 			b = last_rep[qd].state & 0x07;
29897e911b15Skarels 
29907e911b15Skarels 			if (a ^ b) {
29917e911b15Skarels 
29927e911b15Skarels 			    for ( c = 1;  c < 8; c <<= 1) {
29937e911b15Skarels 
29947e911b15Skarels 				if (!( c & (a ^ b))) /* this button change? */
29957e911b15Skarels 				    continue;
29967e911b15Skarels 
29977e911b15Skarels 				/* event queue full? (overflow condition) */
29987e911b15Skarels 
29997e911b15Skarels 				if (ISFULL(eqh) == TRUE) {
3000*e977faadSmarc 				    printf("\nqd%d: qdiint: event queue overflow", qd);
30017e911b15Skarels 				    break;
30027e911b15Skarels 				}
30037e911b15Skarels 
30047e911b15Skarels 				event = PUTBEGIN(eqh);	/* get new event */
30057e911b15Skarels 				PUTEND(eqh);
30067e911b15Skarels 
30077e911b15Skarels 				++do_wakeup;   /* request select wakeup */
30087e911b15Skarels 
30097e911b15Skarels 				event->vse_x = eqh->curs_pos.x;
30107e911b15Skarels 				event->vse_y = eqh->curs_pos.y;
30117e911b15Skarels 
30127e911b15Skarels 				event->vse_device = VSE_MOUSE;	/* mouse */
30137e911b15Skarels 				event->vse_type = VSE_BUTTON; /* new button */
30147e911b15Skarels 				event->vse_time = TOY;	      /* time stamp */
30157e911b15Skarels 
30167e911b15Skarels 				/* flag changed button and if up or down */
30177e911b15Skarels 
30187e911b15Skarels 				if (c == RIGHT_BUTTON)
30197e911b15Skarels 				    event->vse_key = VSE_RIGHT_BUTTON;
30207e911b15Skarels 				else if (c == MIDDLE_BUTTON)
30217e911b15Skarels 				    event->vse_key = VSE_MIDDLE_BUTTON;
30227e911b15Skarels 				else if (c == LEFT_BUTTON)
30237e911b15Skarels 				    event->vse_key = VSE_LEFT_BUTTON;
30247e911b15Skarels 
30257e911b15Skarels 				/* set bit = button depressed */
30267e911b15Skarels 
30277e911b15Skarels 				if (c & a)
30287e911b15Skarels 				    event->vse_direction = VSE_KBTDOWN;
30297e911b15Skarels 				else
30307e911b15Skarels 				    event->vse_direction = VSE_KBTUP;
30317e911b15Skarels 			    }
30327e911b15Skarels 			}
30337e911b15Skarels 
30347e911b15Skarels 			/* refresh last report */
30357e911b15Skarels 
30367e911b15Skarels 			last_rep[qd] = current_rep[qd];
30377e911b15Skarels 
30387e911b15Skarels 		    }  /* get last byte of report */
30397e911b15Skarels 		} /* pickup mouse input */
30407e911b15Skarels 
30417e911b15Skarels 		/*--------------------------------
30427e911b15Skarels 		* pickup tablet input, if any  */
30437e911b15Skarels 
30447e911b15Skarels 		else if ((status = duart->statusB) & RCV_RDY  &&
30457e911b15Skarels 			 qdflags[qd].pntr_id == TABLET_ID) {
30467e911b15Skarels 
30477e911b15Skarels 		    if (status & 0x70) {
30487e911b15Skarels 			duart->cmdB = 0x40;
30497e911b15Skarels 			continue;
30507e911b15Skarels 		    }
30517e911b15Skarels 
30527e911b15Skarels 		    /* event queue full now? (overflow condition) */
30537e911b15Skarels 
30547e911b15Skarels 		    if (ISFULL(eqh) == TRUE) {
3055*e977faadSmarc 			printf("\nqd%d: qdiint: event queue overflow", qd);
30567e911b15Skarels 			break;
30577e911b15Skarels 		    }
30587e911b15Skarels 
30597e911b15Skarels 		    data = duart->dataB;      /* get report byte */
30607e911b15Skarels 		    ++new_rep->bytcnt;	      /* bump report byte count */
30617e911b15Skarels 
30627e911b15Skarels 		    /*---------------------------
30637e911b15Skarels 		    * if 1st byte of report.. */
30647e911b15Skarels 
30657e911b15Skarels 		    if (data & START_FRAME) {
30667e911b15Skarels 			new_rep->state = data;
30677e911b15Skarels 			if (new_rep->bytcnt > 1) {
30687e911b15Skarels 			    new_rep->bytcnt = 1;    /* start of new frame */
30697e911b15Skarels 			    continue;		    /* ..continue looking */
30707e911b15Skarels 			}
30717e911b15Skarels 		    }
30727e911b15Skarels 
30737e911b15Skarels 		    /*---------------------------
30747e911b15Skarels 		    * if 2nd byte of report.. */
30757e911b15Skarels 
30767e911b15Skarels 		    else if (new_rep->bytcnt == 2) {
30777e911b15Skarels 			new_rep->dx = data & 0x3F;
30787e911b15Skarels 		    }
30797e911b15Skarels 
30807e911b15Skarels 		    /*---------------------------
30817e911b15Skarels 		    * if 3rd byte of report.. */
30827e911b15Skarels 
30837e911b15Skarels 		    else if (new_rep->bytcnt == 3) {
30847e911b15Skarels 			new_rep->dx |= (data & 0x3F) << 6;
30857e911b15Skarels 		    }
30867e911b15Skarels 
30877e911b15Skarels 		    /*---------------------------
30887e911b15Skarels 		    * if 4th byte of report.. */
30897e911b15Skarels 
30907e911b15Skarels 		    else if (new_rep->bytcnt == 4) {
30917e911b15Skarels 			new_rep->dy = data & 0x3F;
30927e911b15Skarels 		    }
30937e911b15Skarels 
30947e911b15Skarels 		    /*-------------------------------------------------
30957e911b15Skarels 		    * if 5th byte of report, load input event queue */
30967e911b15Skarels 
30977e911b15Skarels 		    else if (new_rep->bytcnt == 5) {
30987e911b15Skarels 
30997e911b15Skarels 			new_rep->dy |= (data & 0x3F) << 6;
31007e911b15Skarels 			new_rep->bytcnt = 0;
31017e911b15Skarels 
31027e911b15Skarels 			/*-------------------------------------
31037e911b15Skarels 			* update cursor position coordinates */
31047e911b15Skarels 
31057e911b15Skarels 			new_rep->dx /= qdflags[qd].tab_res;
31067e911b15Skarels 			new_rep->dy = (2200 - new_rep->dy)
31077e911b15Skarels 				      / qdflags[qd].tab_res;
31087e911b15Skarels 
31097e911b15Skarels 			if (new_rep->dx > 1023) {
31107e911b15Skarels 			    new_rep->dx = 1023;
31117e911b15Skarels 			}
31127e911b15Skarels 			if (new_rep->dy > 863) {
31137e911b15Skarels 			    new_rep->dy = 863;
31147e911b15Skarels 			}
31157e911b15Skarels 
31167e911b15Skarels 			/*
31177e911b15Skarels 			 * report an event if the puck/stylus has moved
31187e911b15Skarels 			 */
31197e911b15Skarels 
31207e911b15Skarels 			if (eqh->curs_pos.x != new_rep->dx ||
31217e911b15Skarels 			    eqh->curs_pos.y != new_rep->dy) {
31227e911b15Skarels 
31237e911b15Skarels 			    eqh->curs_pos.x = new_rep->dx;
31247e911b15Skarels 			    eqh->curs_pos.y = new_rep->dy;
31257e911b15Skarels 
31267e911b15Skarels 			    /*---------------------------------
31277e911b15Skarels 			    * update cursor screen position */
31287e911b15Skarels 
31297e911b15Skarels 			    dga = (struct dga *) qdmap[qd].dga;
31307e911b15Skarels 			    dga->x_cursor = TRANX(eqh->curs_pos.x);
31317e911b15Skarels 			    dga->y_cursor = TRANY(eqh->curs_pos.y);
31327e911b15Skarels 
31337e911b15Skarels 			    /*
31347e911b15Skarels 			     * if cursor is in the box, no event report
31357e911b15Skarels 			     */
31367e911b15Skarels 
31377e911b15Skarels 			    if (eqh->curs_pos.x <= eqh->curs_box.right	&&
31387e911b15Skarels 				eqh->curs_pos.x >= eqh->curs_box.left  &&
31397e911b15Skarels 				eqh->curs_pos.y >= eqh->curs_box.top  &&
31407e911b15Skarels 				eqh->curs_pos.y <= eqh->curs_box.bottom ) {
31417e911b15Skarels 				goto GET_TBUTTON;
31427e911b15Skarels 			    }
31437e911b15Skarels 
31447e911b15Skarels 			    /*---------------------------------
31457e911b15Skarels 			    * report the tablet motion event */
31467e911b15Skarels 
31477e911b15Skarels 			    event = PUTBEGIN(eqh);
31487e911b15Skarels 			    PUTEND(eqh);
31497e911b15Skarels 
31507e911b15Skarels 			    ++do_wakeup;   /* request a select wakeup call */
31517e911b15Skarels 
31527e911b15Skarels 			    event->vse_x = eqh->curs_pos.x;
31537e911b15Skarels 			    event->vse_y = eqh->curs_pos.y;
31547e911b15Skarels 
31557e911b15Skarels 			    event->vse_device = VSE_TABLET;  /* tablet */
31567e911b15Skarels 			    /*
31577e911b15Skarels 			     * right now, X handles tablet motion the same
31587e911b15Skarels 			     * as mouse motion
31597e911b15Skarels 			     */
31607e911b15Skarels 			    event->vse_type = VSE_MMOTION;   /* pos changed */
31617e911b15Skarels 			    event->vse_key = 0;
31627e911b15Skarels 			    event->vse_direction = 0;
31637e911b15Skarels 			    event->vse_time = TOY;	/* time stamp */
31647e911b15Skarels 			}
31657e911b15Skarels GET_TBUTTON:
31667e911b15Skarels 			/*-------------------------------
31677e911b15Skarels 			* if button state has changed */
31687e911b15Skarels 
31697e911b15Skarels 			a = new_rep->state & 0x1E;   /* mask nonbutton bits */
31707e911b15Skarels 			b = last_rep[qd].state & 0x1E;
31717e911b15Skarels 
31727e911b15Skarels 			if (a ^ b) {
31737e911b15Skarels 
31747e911b15Skarels 			    /* event queue full now? (overflow condition) */
31757e911b15Skarels 
31767e911b15Skarels 			    if (ISFULL(eqh) == TRUE) {
3177*e977faadSmarc 				printf("\nqd%d: qdiint: event queue overflow",qd);
31787e911b15Skarels 				break;
31797e911b15Skarels 			    }
31807e911b15Skarels 
31817e911b15Skarels 			    event = PUTBEGIN(eqh);  /* get new event */
31827e911b15Skarels 			    PUTEND(eqh);
31837e911b15Skarels 
31847e911b15Skarels 			    ++do_wakeup;   /* request a select wakeup call */
31857e911b15Skarels 
31867e911b15Skarels 			    event->vse_x = eqh->curs_pos.x;
31877e911b15Skarels 			    event->vse_y = eqh->curs_pos.y;
31887e911b15Skarels 
31897e911b15Skarels 			    event->vse_device = VSE_TABLET;  /* tablet */
31907e911b15Skarels 			    event->vse_type = VSE_BUTTON; /* button changed */
31917e911b15Skarels 			    event->vse_time = TOY;	   /* time stamp */
31927e911b15Skarels 
31937e911b15Skarels 			    /* define the changed button and if up or down */
31947e911b15Skarels 
31957e911b15Skarels 			    for ( c = 1;  c <= 0x10; c <<= 1) {
31967e911b15Skarels 				if (c & (a ^ b)) {
31977e911b15Skarels 				    if (c == T_LEFT_BUTTON)
31987e911b15Skarels 					event->vse_key = VSE_T_LEFT_BUTTON;
31997e911b15Skarels 				    else if (c == T_FRONT_BUTTON)
32007e911b15Skarels 					event->vse_key = VSE_T_FRONT_BUTTON;
32017e911b15Skarels 				    else if (c == T_RIGHT_BUTTON)
32027e911b15Skarels 					event->vse_key = VSE_T_RIGHT_BUTTON;
32037e911b15Skarels 				    else if (c == T_BACK_BUTTON)
32047e911b15Skarels 					event->vse_key = VSE_T_BACK_BUTTON;
32057e911b15Skarels 				    break;
32067e911b15Skarels 				}
32077e911b15Skarels 			    }
32087e911b15Skarels 
32097e911b15Skarels 			    /* set bit = button depressed */
32107e911b15Skarels 
32117e911b15Skarels 			    if (c & a)
32127e911b15Skarels 				event->vse_direction = VSE_KBTDOWN;
32137e911b15Skarels 			    else
32147e911b15Skarels 				event->vse_direction = VSE_KBTUP;
32157e911b15Skarels 			}
32167e911b15Skarels 
32177e911b15Skarels 			/* refresh last report */
32187e911b15Skarels 
32197e911b15Skarels 			last_rep[qd] = current_rep[qd];
32207e911b15Skarels 
32217e911b15Skarels 		    } /* get last byte of report */
32227e911b15Skarels 		} /* pick up tablet input */
32237e911b15Skarels 
32247e911b15Skarels 	    } /* while input available.. */
32257e911b15Skarels 
32267e911b15Skarels 	    /*---------------------
32277e911b15Skarels 	    * do select wakeup	*/
32287e911b15Skarels 
3229*e977faadSmarc 
32307e911b15Skarels 	    if (rsel[qd] && do_wakeup && qdflags[qd].selmask & SEL_READ) {
32317e911b15Skarels 		selwakeup(rsel[qd], 0);
32327e911b15Skarels 		rsel[qd] = 0;
32337e911b15Skarels 		qdflags[qd].selmask &= ~SEL_READ;
32347e911b15Skarels 		do_wakeup = 0;
32357e911b15Skarels 	    }
32367e911b15Skarels 	}
32377e911b15Skarels 
32387e911b15Skarels /*-----------------------------------------------------------------
32397e911b15Skarels * if the graphic device is not turned on, this is console input */
32407e911b15Skarels 
32417e911b15Skarels 	else {
32427e911b15Skarels 
32437e911b15Skarels 	    ui = qdinfo[qd];
32447e911b15Skarels 	    if (ui == 0 || ui->ui_alive == 0)
32457e911b15Skarels 		return(0);
32467e911b15Skarels 
32477e911b15Skarels 	    tp = &qd_tty[qd << 2];
32487e911b15Skarels 
32497e911b15Skarels 	    /*--------------------------------------
32507e911b15Skarels 	    * Get a character from the keyboard. */
32517e911b15Skarels 
32527e911b15Skarels 	    while ((status = duart->statusA) & RCV_RDY) {
32537e911b15Skarels 
32547e911b15Skarels 		key = duart->dataA;
32557e911b15Skarels 		key &= 0xFF;
32567e911b15Skarels 
32577e911b15Skarels 		/*--------------------------------------
32587e911b15Skarels 		* Check for various keyboard errors  */
32597e911b15Skarels 
32607e911b15Skarels 		if( key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
32617e911b15Skarels 		    key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
3262*e977faadSmarc 			printf("\nqd%d: qdiint: Keyboard error, code = %x",qd,key);
32637e911b15Skarels 			return(0);
32647e911b15Skarels 		}
32657e911b15Skarels 
32667e911b15Skarels 		if (key < LK_LOWEST)
32677e911b15Skarels 		    return(0);
32687e911b15Skarels 
32697e911b15Skarels 		/*---------------------------------
32707e911b15Skarels 		* See if its a state change key */
32717e911b15Skarels 
32727e911b15Skarels 		switch (key) {
32737e911b15Skarels 
32747e911b15Skarels 		    case LOCK:
32757e911b15Skarels 			q_keyboard.lock ^= 0xffff;	/* toggle */
32767e911b15Skarels 			if (q_keyboard.lock)
32777e911b15Skarels 			    led_control(qd, LK_LED_ENABLE, LK_LED_LOCK);
32787e911b15Skarels 			else
32797e911b15Skarels 			    led_control(qd, LK_LED_DISABLE, LK_LED_LOCK);
32807e911b15Skarels 			return;
32817e911b15Skarels 
32827e911b15Skarels 		    case SHIFT:
32837e911b15Skarels 			q_keyboard.shift ^= 0xFFFF;
32847e911b15Skarels 			return;
32857e911b15Skarels 
32867e911b15Skarels 		    case CNTRL:
32877e911b15Skarels 			q_keyboard.cntrl ^= 0xFFFF;
32887e911b15Skarels 			return;
32897e911b15Skarels 
32907e911b15Skarels 		    case ALLUP:
32917e911b15Skarels 			q_keyboard.cntrl = 0;
32927e911b15Skarels 			q_keyboard.shift = 0;
32937e911b15Skarels 			return;
32947e911b15Skarels 
32957e911b15Skarels 		    case REPEAT:
32967e911b15Skarels 			chr = q_keyboard.last;
32977e911b15Skarels 			break;
32987e911b15Skarels 
32997e911b15Skarels 		    /*-------------------------------------------------------
33007e911b15Skarels 		    * Test for cntrl characters. If set, see if the character
33017e911b15Skarels 		    * is elligible to become a control character. */
33027e911b15Skarels 
33037e911b15Skarels 		    default:
33047e911b15Skarels 
33057e911b15Skarels 			if (q_keyboard.cntrl) {
33067e911b15Skarels 				chr = q_key[key];
33077e911b15Skarels 				if (chr >= ' ' && chr <= '~')
33087e911b15Skarels 				    chr &= 0x1F;
3309*e977faadSmarc 				else if (chr >= 0xA1 && chr <= 0xFE)
3310*e977faadSmarc 				    chr &= 0x9F;
33117e911b15Skarels 			}
33127e911b15Skarels 			else if( q_keyboard.lock || q_keyboard.shift )
33137e911b15Skarels 			    chr = q_shift_key[key];
33147e911b15Skarels 			else
33157e911b15Skarels 			    chr = q_key[key];
33167e911b15Skarels 			break;
33177e911b15Skarels 		}
33187e911b15Skarels 
33197e911b15Skarels 		q_keyboard.last = chr;
33207e911b15Skarels 
33217e911b15Skarels 		/*-----------------------------------
33227e911b15Skarels 		* Check for special function keys */
33237e911b15Skarels 
3324*e977faadSmarc 		if (chr & 0x100) {
33257e911b15Skarels 			char *string;
33267e911b15Skarels 			string = q_special[chr & 0x7F];
33277e911b15Skarels 			while(*string)
33287e911b15Skarels 			    (*linesw[tp->t_line].l_rint)(*string++, tp);
33297e911b15Skarels 		}
33307e911b15Skarels 		else {
3331*e977faadSmarc #ifdef notdef	/* notneeded */
3332*e977faadSmarc 			if (tp->t_iflag & ISTRIP)	/* Strip to 7 bits. */
3333*e977faadSmarc 				c &= 0177;
3334*e977faadSmarc 			else {			/* Take the full 8-bits */
3335*e977faadSmarc 				/* If ISTRIP is not set a valid character of 377
3336*e977faadSmarc 			 	* is read as 0377,0377 to avoid ambiguity with
3337*e977faadSmarc 			 	* the PARMARK sequence.
3338*e977faadSmarc 			 	*/
3339*e977faadSmarc 				if ((c == 0377) && (tp->t_line == TERMIODISC))
3340*e977faadSmarc 					(*linesw[tp->t_line].l_rint)(0377,tp);
3341*e977faadSmarc 
3342*e977faadSmarc 			}
3343*e977faadSmarc #endif /*notdef*/
33447e911b15Skarels 			(*linesw[tp->t_line].l_rint)(chr, tp);
33457e911b15Skarels 		}
33467e911b15Skarels 	    }
33477e911b15Skarels 	}
33487e911b15Skarels 
3349*e977faadSmarc /*----------------------
3350*e977faadSmarc * cleanup and exit  */
3351*e977faadSmarc 
33527e911b15Skarels 	return(0);
33537e911b15Skarels 
33547e911b15Skarels } /* qdiint */
33557e911b15Skarels 
33567e911b15Skarels /******************************************************************
3357*e977faadSmarc *******************************************************************
3358*e977faadSmarc *******************************************************************
33597e911b15Skarels *
33607e911b15Skarels *	THE SUBROUTINES START HERE:
33617e911b15Skarels *
33627e911b15Skarels ******************************************************************/
33637e911b15Skarels 
33647e911b15Skarels /*****************************************************************
33657e911b15Skarels *
33667e911b15Skarels *	clear_qd_screen()... clear the QDSS screen
33677e911b15Skarels *
33687e911b15Skarels ******************************************************************
33697e911b15Skarels *
33707e911b15Skarels *			     >>> NOTE <<<
33717e911b15Skarels *
33727e911b15Skarels *   This code requires that certain adder initialization be valid.  To
33737e911b15Skarels *   assure that this requirement is satisfied, this routine should be
33747e911b15Skarels *   called only after calling the "setup_dragon()" function.
33757e911b15Skarels *
33767e911b15Skarels *   Clear the bitmap a piece at a time. Since the fast scroll clear
33777e911b15Skarels *   only clears the current displayed portion of the bitmap put a
33787e911b15Skarels *   temporary value in the y limit register so we can access whole
33797e911b15Skarels *   bitmap
33807e911b15Skarels *
33817e911b15Skarels ****************/
33827e911b15Skarels 
33837e911b15Skarels clear_qd_screen(unit)
33847e911b15Skarels int unit;
33857e911b15Skarels {
33867e911b15Skarels 	register struct adder *adder;
33877e911b15Skarels 	adder = (struct adder *) qdmap[unit].adder;
33887e911b15Skarels 
33897e911b15Skarels 	adder->x_limit = 1024;
33907e911b15Skarels 	adder->y_limit = 2048 - CHAR_HEIGHT;
33917e911b15Skarels 	adder->y_offset_pending = 0;
33927e911b15Skarels 
33937e911b15Skarels 	wait_status(adder, VSYNC);	/* wait at LEAST 1 full frame */
33947e911b15Skarels 	wait_status(adder, VSYNC);
33957e911b15Skarels 
33967e911b15Skarels 	adder->y_scroll_constant = SCROLL_ERASE;
33977e911b15Skarels 
33987e911b15Skarels 	wait_status(adder, VSYNC);
33997e911b15Skarels 	wait_status(adder, VSYNC);
34007e911b15Skarels 
34017e911b15Skarels 	adder->y_offset_pending = 864;
34027e911b15Skarels 
34037e911b15Skarels 	wait_status(adder, VSYNC);
34047e911b15Skarels 	wait_status(adder, VSYNC);
34057e911b15Skarels 
34067e911b15Skarels 	adder->y_scroll_constant = SCROLL_ERASE;
34077e911b15Skarels 
34087e911b15Skarels 	wait_status(adder, VSYNC);
34097e911b15Skarels 	wait_status(adder, VSYNC);
34107e911b15Skarels 
34117e911b15Skarels 	adder->y_offset_pending = 1728;
34127e911b15Skarels 
34137e911b15Skarels 	wait_status(adder, VSYNC);
34147e911b15Skarels 	wait_status(adder, VSYNC);
34157e911b15Skarels 
34167e911b15Skarels 	adder->y_scroll_constant = SCROLL_ERASE;
34177e911b15Skarels 
34187e911b15Skarels 	wait_status(adder, VSYNC);
34197e911b15Skarels 	wait_status(adder, VSYNC);
34207e911b15Skarels 
34217e911b15Skarels 	adder->y_offset_pending = 0;	 /* back to normal */
34227e911b15Skarels 
34237e911b15Skarels 	wait_status(adder, VSYNC);
34247e911b15Skarels 	wait_status(adder, VSYNC);
34257e911b15Skarels 
34267e911b15Skarels 	adder->x_limit = MAX_SCREEN_X;
34277e911b15Skarels 	adder->y_limit = MAX_SCREEN_Y + FONT_HEIGHT;
34287e911b15Skarels 
34297e911b15Skarels } /* clear_qd_screen */
34307e911b15Skarels 
34317e911b15Skarels /**********************************************************************
34327e911b15Skarels *
34337e911b15Skarels *	qdputc()... route kernel console output to display destination
34347e911b15Skarels *
34357e911b15Skarels ***********************************************************************
34367e911b15Skarels *
34377e911b15Skarels *	calling convention:
34387e911b15Skarels *
34397e911b15Skarels *		qdputc(chr);
34407e911b15Skarels *
34417e911b15Skarels *	where:	char chr;	 ;character for output
34427e911b15Skarels *
34437e911b15Skarels ****************/
34447e911b15Skarels 
34457e911b15Skarels qdputc(chr)
34467e911b15Skarels register char chr;
34477e911b15Skarels {
3448*e977faadSmarc 	register struct tty *tp0;
34497e911b15Skarels 
3450*e977faadSmarc /*---------------------------------------------------------
3451*e977faadSmarc * if system is now physical, forget it (ie: crash DUMP) */
3452*e977faadSmarc 
34537e911b15Skarels 	if ( (mfpr(MAPEN) & 1) == 0 )
34547e911b15Skarels 	    return;
34557e911b15Skarels 
3456*e977faadSmarc /*--------------------------------------------------
3457*e977faadSmarc * direct kernel output char to the proper place  */
3458*e977faadSmarc 
3459*e977faadSmarc #ifdef notdef	/* never */
3460*e977faadSmarc 	tp0 = &qd_tty[1];
3461*e977faadSmarc 
3462*e977faadSmarc 	if (qdflags[0].kernel_loop != 0  &&  tp0->t_state & TS_ISOPEN) {
3463*e977faadSmarc 	    (*linesw[tp0->t_line].l_rint)(chr, tp0);
3464*e977faadSmarc 	} else {
3465*e977faadSmarc 	    blitc(0, chr & 0xff);
3466*e977faadSmarc 	}
3467*e977faadSmarc #endif /*notdef*/
34687e911b15Skarels 	blitc(0, chr & 0xff);
346924f67f6bSmarc 	if ((chr & 0177) == '\n')
347024f67f6bSmarc 		blitc(0, '\r');
347124f67f6bSmarc 
34727e911b15Skarels 
34737e911b15Skarels } /* qdputc */
34747e911b15Skarels 
34757e911b15Skarels /*******************************************************************
34767e911b15Skarels *
34777e911b15Skarels *	qdgetc()... get a character from the LK201
34787e911b15Skarels *
34797e911b15Skarels *******************************************************************
34807e911b15Skarels *
34817e911b15Skarels *	calling convention:
34827e911b15Skarels *
34837e911b15Skarels *		qdgetc();
34847e911b15Skarels *
34857e911b15Skarels *	returns:  the character read.
34867e911b15Skarels *
34877e911b15Skarels ****************/
34887e911b15Skarels 
34897e911b15Skarels qdgetc()
34907e911b15Skarels {
34917e911b15Skarels 	register short key;
34927e911b15Skarels 	register char chr;
34937e911b15Skarels 	register struct duart *duart;
34947e911b15Skarels 
34957e911b15Skarels 	u_int status;
34967e911b15Skarels 
34977e911b15Skarels 	duart = (struct duart *) qdmap[0].duart;
34987e911b15Skarels 
34997e911b15Skarels 	/*--------------------------------------
35007e911b15Skarels 	* Get a character from the keyboard. */
35017e911b15Skarels 
35027e911b15Skarels LOOP:
35037e911b15Skarels 	while (!((status = duart->statusA) & RCV_RDY))
35047e911b15Skarels 			;
35057e911b15Skarels 
35067e911b15Skarels 	key = duart->dataA;
35077e911b15Skarels 	key &= 0xFF;
35087e911b15Skarels 
35097e911b15Skarels 	/*--------------------------------------
35107e911b15Skarels 	* Check for various keyboard errors  */
35117e911b15Skarels 
35127e911b15Skarels 	if( key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
35137e911b15Skarels 	    key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
35147e911b15Skarels 		printf("Keyboard error, code = %x\n", key);
35157e911b15Skarels 		return(0);
35167e911b15Skarels 	}
35177e911b15Skarels 
35187e911b15Skarels 	if (key < LK_LOWEST)
35197e911b15Skarels 	    return(0);
35207e911b15Skarels 
35217e911b15Skarels 	/*---------------------------------
35227e911b15Skarels 	* See if its a state change key */
35237e911b15Skarels 
35247e911b15Skarels 	switch (key) {
35257e911b15Skarels 
35267e911b15Skarels 	    case LOCK:
35277e911b15Skarels 		q_keyboard.lock ^= 0xffff;	/* toggle */
35287e911b15Skarels 		if (q_keyboard.lock)
35297e911b15Skarels 		    led_control(LK_LED_ENABLE, LK_LED_LOCK);
35307e911b15Skarels 		else
35317e911b15Skarels 		    led_control(LK_LED_DISABLE, LK_LED_LOCK);
35327e911b15Skarels 		goto LOOP;
35337e911b15Skarels 
35347e911b15Skarels 	    case SHIFT:
35357e911b15Skarels 		q_keyboard.shift ^= 0xFFFF;
35367e911b15Skarels 		goto LOOP;
35377e911b15Skarels 
35387e911b15Skarels 	    case CNTRL:
35397e911b15Skarels 		q_keyboard.cntrl ^= 0xFFFF;
35407e911b15Skarels 		goto LOOP;
35417e911b15Skarels 
35427e911b15Skarels 	    case ALLUP:
35437e911b15Skarels 		q_keyboard.cntrl = 0;
35447e911b15Skarels 		q_keyboard.shift = 0;
35457e911b15Skarels 		goto LOOP;
35467e911b15Skarels 
35477e911b15Skarels 	    case REPEAT:
35487e911b15Skarels 		chr = q_keyboard.last;
35497e911b15Skarels 		break;
35507e911b15Skarels 
35517e911b15Skarels 	    /*-------------------------------------------------------
35527e911b15Skarels 	    * Test for cntrl characters. If set, see if the character
35537e911b15Skarels 	    * is elligible to become a control character. */
35547e911b15Skarels 
35557e911b15Skarels 	    default:
35567e911b15Skarels 
35577e911b15Skarels 		if (q_keyboard.cntrl) {
35587e911b15Skarels 		    chr = q_key[key];
35597e911b15Skarels 		    if (chr >= ' ' && chr <= '~')
35607e911b15Skarels 			chr &= 0x1F;
35617e911b15Skarels 		}
35627e911b15Skarels 		else if ( q_keyboard.lock || q_keyboard.shift )
35637e911b15Skarels 		    chr = q_shift_key[key];
35647e911b15Skarels 		else
35657e911b15Skarels 		    chr = q_key[key];
35667e911b15Skarels 		break;
35677e911b15Skarels 	}
35687e911b15Skarels 
35697e911b15Skarels 	if (chr < ' ' && chr > '~')	/* if input is non-displayable */
35707e911b15Skarels 	    return(0);			/* ..then pitch it! */
35717e911b15Skarels 
35727e911b15Skarels 	q_keyboard.last = chr;
35737e911b15Skarels 
35747e911b15Skarels 	/*-----------------------------------
35757e911b15Skarels 	* Check for special function keys */
35767e911b15Skarels 
35777e911b15Skarels 	if (chr & 0x80) 		/* pitch the function keys */
35787e911b15Skarels 	    return(0);
35797e911b15Skarels 	else
35807e911b15Skarels 	    return(chr);
35817e911b15Skarels 
35827e911b15Skarels } /* qdgetc */
35837e911b15Skarels 
35847e911b15Skarels /**********************************************************************
35857e911b15Skarels *
35867e911b15Skarels *	ldcursor()... load the mouse cursor's template RAM bitmap
35877e911b15Skarels *
35887e911b15Skarels *********************************************************************
35897e911b15Skarels *
35907e911b15Skarels *	calling convention:
35917e911b15Skarels *
35927e911b15Skarels *		ldcursor(unit, bitmap);
35937e911b15Skarels *		u_int unit;
35947e911b15Skarels *		short *bitmap;
35957e911b15Skarels *
35967e911b15Skarels ****************/
35977e911b15Skarels 
35987e911b15Skarels ldcursor(unit, bitmap)
35997e911b15Skarels u_int unit;
36007e911b15Skarels short *bitmap;
36017e911b15Skarels {
36027e911b15Skarels 	register struct dga *dga;
36037e911b15Skarels 	register short *temp;
36047e911b15Skarels 	register int i;
36057e911b15Skarels 
36067e911b15Skarels 	int cursor;
36077e911b15Skarels 
36087e911b15Skarels 	dga = (struct dga *) qdmap[unit].dga;
36097e911b15Skarels 	temp = (short *) qdmap[unit].template;
36107e911b15Skarels 
36117e911b15Skarels 	if (dga->csr & CURS_ENB) {	/* if the cursor is enabled.. */
36127e911b15Skarels 	    cursor = -1;		/* ..note that.. */
36137e911b15Skarels 	    dga->csr &= ~CURS_ENB;	/* ..and shut it off */
36147e911b15Skarels 	}
36157e911b15Skarels 	else {
36167e911b15Skarels 	    cursor = 0;
36177e911b15Skarels 	}
36187e911b15Skarels 
36197e911b15Skarels 	dga->csr &= ~CURS_ENB;		/* shut off the cursor */
36207e911b15Skarels 
36217e911b15Skarels 	temp += (8 * 1024) - 32;	/* cursor is 32 WORDS from the end */
36227e911b15Skarels 					/* ..of the 8k WORD template space */
36237e911b15Skarels 	for (i = 0; i < 32; ++i)
36247e911b15Skarels 	    *temp++ = *bitmap++;
36257e911b15Skarels 
36267e911b15Skarels 	if (cursor) {			/* if cursor was enabled.. */
36277e911b15Skarels 	    dga->csr |= CURS_ENB;	/* ..turn it back on */
36287e911b15Skarels 	}
36297e911b15Skarels 
36307e911b15Skarels 	return(0);
36317e911b15Skarels 
36327e911b15Skarels } /* ldcursor */
36337e911b15Skarels 
36347e911b15Skarels /**********************************************************************
36357e911b15Skarels *
36367e911b15Skarels *	ldfont()... put the console font in the QDSS off-screen memory
36377e911b15Skarels *
36387e911b15Skarels ***********************************************************************
36397e911b15Skarels *
36407e911b15Skarels *	calling convention:
36417e911b15Skarels *
36427e911b15Skarels *		ldfont(unit);
36437e911b15Skarels *		u_int unit;	;QDSS unit number
36447e911b15Skarels *
36457e911b15Skarels ****************/
36467e911b15Skarels 
36477e911b15Skarels ldfont(unit)
36487e911b15Skarels u_int unit;
36497e911b15Skarels {
36507e911b15Skarels 	register struct adder *adder;
36517e911b15Skarels 
36527e911b15Skarels 	int i;		/* scratch variables */
36537e911b15Skarels 	int j;
36547e911b15Skarels 	int k;
36557e911b15Skarels 	short packed;
3656*e977faadSmarc 	int max_chars_line;
36577e911b15Skarels 
36587e911b15Skarels 	adder = (struct adder *) qdmap[unit].adder;
36597e911b15Skarels 
36607e911b15Skarels /*------------------------------------------
36617e911b15Skarels * setup VIPER operand control registers  */
36627e911b15Skarels 
36637e911b15Skarels 	write_ID(adder, MASK_1, 0xFFFF);
36647e911b15Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
36657e911b15Skarels 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
36667e911b15Skarels 
36677e911b15Skarels 	write_ID(adder, SRC1_OCR_B,
36687e911b15Skarels 			EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY);
36697e911b15Skarels 	write_ID(adder, SRC2_OCR_B,
36707e911b15Skarels 			EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY);
36717e911b15Skarels 	write_ID(adder, DST_OCR_B,
36727e911b15Skarels 			EXT_SOURCE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
36737e911b15Skarels 
36747e911b15Skarels 	adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL;
36757e911b15Skarels 
36767e911b15Skarels /*--------------------------
36777e911b15Skarels * load destination data  */
36787e911b15Skarels 
36797e911b15Skarels 	wait_status(adder, RASTEROP_COMPLETE);
36807e911b15Skarels 
36817e911b15Skarels 	adder->destination_x = FONT_X;
36827e911b15Skarels 	adder->destination_y = FONT_Y;
3683*e977faadSmarc 	if (FONT_WIDTH > MAX_SCREEN_X)
3684*e977faadSmarc 		adder->fast_dest_dx = MAX_SCREEN_X;
3685*e977faadSmarc 	else
36867e911b15Skarels 		adder->fast_dest_dx = FONT_WIDTH;
36877e911b15Skarels 	adder->slow_dest_dy = CHAR_HEIGHT;
36887e911b15Skarels 
36897e911b15Skarels /*---------------------------------------
36907e911b15Skarels * setup for processor to bitmap xfer  */
36917e911b15Skarels 
36927e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0001);
36937e911b15Skarels 	adder->cmd = PBT | OCRB | 2 | DTE | 2;
36947e911b15Skarels 
3695*e977faadSmarc /*---------------------------------------
3696*e977faadSmarc * Figure out how many characters can be stored on one "line" of offscreen memory
3697*e977faadSmarc */
3698*e977faadSmarc 	    max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
3699*e977faadSmarc 	    if ((CHARS/2 + CHARS%2) < max_chars_line)
3700*e977faadSmarc 		max_chars_line = CHARS/2 + CHARS%2;
3701*e977faadSmarc 
3702*e977faadSmarc /*-----------------------------------------------
3703*e977faadSmarc * iteratively do the processor to bitmap xfer */
3704*e977faadSmarc 
3705*e977faadSmarc 	for (i = 0; i < ROWS; ++i) {
3706*e977faadSmarc 
3707*e977faadSmarc 	    /* PTOB a scan line */
3708*e977faadSmarc 
3709*e977faadSmarc 	    for (j = 0, k = i; j < max_chars_line; ++j) {
3710*e977faadSmarc 		/* PTOB one scan of a char cell */
3711*e977faadSmarc 
3712*e977faadSmarc 		packed = q_font[k];
3713*e977faadSmarc 		k += ROWS;
3714*e977faadSmarc 		packed |= ((short)q_font[k] << 8);
3715*e977faadSmarc 		k += ROWS;
3716*e977faadSmarc 
3717*e977faadSmarc 		wait_status(adder, TX_READY);
3718*e977faadSmarc 		adder->id_data = packed;
3719*e977faadSmarc 	    }
3720*e977faadSmarc 	}
3721*e977faadSmarc 
3722*e977faadSmarc /*---------------------------------------
3723*e977faadSmarc * Copy the second row of characters.
3724*e977faadSmarc * Subtract the first row from the total number.  Divide this quantity by 2
3725*e977faadSmarc * because 2 chars are stored in a short in the PTOB loop below.
3726*e977faadSmarc * Figure out how many characters can be stored on one "line" of offscreen memory
3727*e977faadSmarc */
3728*e977faadSmarc 	    max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
3729*e977faadSmarc 	    if ((CHARS/2 + CHARS%2) < max_chars_line)
3730*e977faadSmarc 		return;
3731*e977faadSmarc 	    max_chars_line = (CHARS/2 + CHARS%2) - max_chars_line; /* 95 - 64 */
3732*e977faadSmarc 	    /* Paranoia check to see if 3rd row may be needed */
3733*e977faadSmarc 	    if (max_chars_line > (MAX_SCREEN_X/(CHAR_WIDTH*2)))
3734*e977faadSmarc 	    	max_chars_line = MAX_SCREEN_X/(CHAR_WIDTH*2);
3735*e977faadSmarc 
3736*e977faadSmarc 
3737*e977faadSmarc /*-----------------------------------------------*/
3738*e977faadSmarc 
3739*e977faadSmarc 	adder->destination_x = FONT_X;
3740*e977faadSmarc 	adder->destination_y = FONT_Y - CHAR_HEIGHT;
3741*e977faadSmarc 	adder->fast_dest_dx = max_chars_line * CHAR_WIDTH * 2;
3742*e977faadSmarc 	adder->slow_dest_dy = CHAR_HEIGHT;
3743*e977faadSmarc 
3744*e977faadSmarc /*---------------------------------------
3745*e977faadSmarc * setup for processor to bitmap xfer  */
3746*e977faadSmarc 
3747*e977faadSmarc 	write_ID(adder, CS_UPDATE_MASK, 0x0001);
3748*e977faadSmarc 	adder->cmd = PBT | OCRB | 2 | DTE | 2;
3749*e977faadSmarc 
37507e911b15Skarels /*-----------------------------------------------
37517e911b15Skarels * iteratively do the processor to bitmap xfer */
37527e911b15Skarels 
37537e911b15Skarels 	for (i = 0; i < ROWS; ++i) {
37547e911b15Skarels 
37557e911b15Skarels 	    /* PTOB a scan line */
37567e911b15Skarels 
3757*e977faadSmarc 	    for (j = 0, k = i; j < max_chars_line; ++j) {
37587e911b15Skarels 
37597e911b15Skarels 		/* PTOB one scan of a char cell */
37607e911b15Skarels 
3761*e977faadSmarc 		packed = q_font[k + FONT_OFFSET];
37627e911b15Skarels 		k += ROWS;
3763*e977faadSmarc 		packed |= ((short)q_font[k + FONT_OFFSET] << 8);
37647e911b15Skarels 		k += ROWS;
37657e911b15Skarels 
37667e911b15Skarels 		wait_status(adder, TX_READY);
37677e911b15Skarels 		adder->id_data = packed;
37687e911b15Skarels 	    }
37697e911b15Skarels 	}
37707e911b15Skarels 
37717e911b15Skarels }  /* ldfont */
37727e911b15Skarels 
37737e911b15Skarels /*********************************************************************
37747e911b15Skarels *
37757e911b15Skarels *	led_control()... twiddle LK-201 LED's
37767e911b15Skarels *
37777e911b15Skarels **********************************************************************
37787e911b15Skarels *
37797e911b15Skarels *	led_control(unit, cmd, led_mask);
37807e911b15Skarels *	u_int unit;	QDSS number
37817e911b15Skarels *	int cmd;	LED enable/disable command
37827e911b15Skarels *	int led_mask;	which LED(s) to twiddle
37837e911b15Skarels *
37847e911b15Skarels *************/
37857e911b15Skarels 
37867e911b15Skarels led_control(unit, cmd, led_mask)
37877e911b15Skarels u_int unit;
37887e911b15Skarels int cmd;
37897e911b15Skarels int led_mask;
37907e911b15Skarels {
37917e911b15Skarels 	register int i;
37927e911b15Skarels 	register int status;
37937e911b15Skarels 	register struct duart *duart;
37947e911b15Skarels 
37957e911b15Skarels 	duart = (struct duart *) qdmap[unit].duart;
37967e911b15Skarels 
37977e911b15Skarels 	for (i = 1000; i > 0; --i) {
37987e911b15Skarels 	    if ((status = duart->statusA) & XMT_RDY) {
37997e911b15Skarels 		duart->dataA = cmd;
38007e911b15Skarels 		break;
38017e911b15Skarels 	    }
38027e911b15Skarels 	}
38037e911b15Skarels 
38047e911b15Skarels 	for (i = 1000; i > 0; --i) {
38057e911b15Skarels 	    if ((status = duart->statusA) & XMT_RDY) {
38067e911b15Skarels 		duart->dataA = led_mask;
38077e911b15Skarels 		break;
38087e911b15Skarels 	    }
38097e911b15Skarels 	}
38107e911b15Skarels 
38117e911b15Skarels 	if (i == 0)
38127e911b15Skarels 	    return(BAD);
38137e911b15Skarels 
38147e911b15Skarels 	return(GOOD);
38157e911b15Skarels 
38167e911b15Skarels } /* led_control */
38177e911b15Skarels 
38187e911b15Skarels /*******************************************************************
38197e911b15Skarels *
38207e911b15Skarels *	scroll_up()... move the screen up one character height
38217e911b15Skarels *
38227e911b15Skarels ********************************************************************
38237e911b15Skarels *
38247e911b15Skarels *	calling convention:
38257e911b15Skarels *
38267e911b15Skarels *		scroll_up(adder);
38277e911b15Skarels *		struct adder *adder;	;address of adder
38287e911b15Skarels *
38297e911b15Skarels ********/
38307e911b15Skarels 
38317e911b15Skarels scroll_up(adder)
38327e911b15Skarels register struct adder *adder;
38337e911b15Skarels {
38347e911b15Skarels 
38357e911b15Skarels /*------------------------------------------
38367e911b15Skarels * setup VIPER operand control registers  */
38377e911b15Skarels 
38387e911b15Skarels 	wait_status(adder, ADDRESS_COMPLETE);
38397e911b15Skarels 
38407e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x00FF);  /* select all planes */
38417e911b15Skarels 
38427e911b15Skarels 	write_ID(adder, MASK_1, 0xFFFF);
38437e911b15Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
38447e911b15Skarels 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
38457e911b15Skarels 
38467e911b15Skarels 	write_ID(adder, SRC1_OCR_B,
38477e911b15Skarels 			EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY);
38487e911b15Skarels 	write_ID(adder, DST_OCR_B,
38497e911b15Skarels 			EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
38507e911b15Skarels 
38517e911b15Skarels /*----------------------------------------
38527e911b15Skarels * load DESTINATION origin and vectors  */
38537e911b15Skarels 
38547e911b15Skarels 	adder->fast_dest_dy = 0;
38557e911b15Skarels 	adder->slow_dest_dx = 0;
38567e911b15Skarels 	adder->error_1 = 0;
38577e911b15Skarels 	adder->error_2 = 0;
38587e911b15Skarels 
38597e911b15Skarels 	adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL;
38607e911b15Skarels 
38617e911b15Skarels 	adder->destination_x = 0;
38627e911b15Skarels 	adder->fast_dest_dx = 1024;
38637e911b15Skarels 
38647e911b15Skarels 	adder->destination_y = 0;
38657e911b15Skarels 	adder->slow_dest_dy = 864 - CHAR_HEIGHT;
38667e911b15Skarels 
38677e911b15Skarels /*-----------------------------------
38687e911b15Skarels * load SOURCE origin and vectors  */
38697e911b15Skarels 
38707e911b15Skarels 	adder->source_1_x = 0;
38717e911b15Skarels 	adder->source_1_dx = 1024;
38727e911b15Skarels 
38737e911b15Skarels 	adder->source_1_y = 0 + CHAR_HEIGHT;
38747e911b15Skarels 	adder->source_1_dy = 864 - CHAR_HEIGHT;
38757e911b15Skarels 
38767e911b15Skarels 	write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
38777e911b15Skarels 	adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE;
38787e911b15Skarels 
38797e911b15Skarels /*--------------------------------------------
38807e911b15Skarels * do a rectangle clear of last screen line */
38817e911b15Skarels 
38827e911b15Skarels 	write_ID(adder, MASK_1, 0xffff);
38837e911b15Skarels 	write_ID(adder, SOURCE, 0xffff);
38847e911b15Skarels 	write_ID(adder,DST_OCR_B,
38857e911b15Skarels 		(EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY));
38867e911b15Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 0);
38877e911b15Skarels 	adder->error_1 = 0;
38887e911b15Skarels 	adder->error_2 = 0;
38897e911b15Skarels 	adder->slow_dest_dx = 0;	/* set up the width of	*/
38907e911b15Skarels 	adder->slow_dest_dy = CHAR_HEIGHT;	/* rectangle */
38917e911b15Skarels 
38927e911b15Skarels 	adder->rasterop_mode = (NORMAL | DST_WRITE_ENABLE) ;
38937e911b15Skarels 	wait_status(adder, RASTEROP_COMPLETE);
38947e911b15Skarels 	adder->destination_x = 0;
38957e911b15Skarels 	adder->destination_y = 864 - CHAR_HEIGHT;
38967e911b15Skarels 
38977e911b15Skarels 	adder->fast_dest_dx = 1024;	/* set up the height	*/
38987e911b15Skarels 	adder->fast_dest_dy = 0;	/* of rectangle 	*/
38997e911b15Skarels 
39007e911b15Skarels 	write_ID(adder, LU_FUNCTION_R2, (FULL_SRC_RESOLUTION | LF_SOURCE));
39017e911b15Skarels 	adder->cmd = (RASTEROP | OCRB | LF_R2 | DTE ) ;
39027e911b15Skarels 
39037e911b15Skarels } /* scroll_up */
39047e911b15Skarels 
39057e911b15Skarels /********************************************************************
39067e911b15Skarels *
39077e911b15Skarels *	init_shared()... init shared memory pointers and structures
39087e911b15Skarels *
39097e911b15Skarels *********************************************************************
39107e911b15Skarels *
39117e911b15Skarels *	calling convention:
39127e911b15Skarels *
39137e911b15Skarels *		init_shared(unit);
39147e911b15Skarels *		u_int unit;
39157e911b15Skarels *
39167e911b15Skarels ****************/
39177e911b15Skarels 
39187e911b15Skarels init_shared(unit)
39197e911b15Skarels register u_int unit;
39207e911b15Skarels {
39217e911b15Skarels 	register struct dga *dga;
39227e911b15Skarels 
39237e911b15Skarels 	dga = (struct dga *) qdmap[unit].dga;
39247e911b15Skarels 
39257e911b15Skarels /*--------------------------------------------------
39267e911b15Skarels * initialize the event queue pointers and header */
39277e911b15Skarels 
39287e911b15Skarels 	eq_header[unit] = (struct qdinput *)
39297e911b15Skarels 			  ((((int)event_shared & ~(0x01FF)) + 512)
39307e911b15Skarels 			   + (EVENT_BUFSIZE * unit));
39317e911b15Skarels 
39327e911b15Skarels 	eq_header[unit]->curs_pos.x = 0;
39337e911b15Skarels 	eq_header[unit]->curs_pos.y = 0;
39347e911b15Skarels 
39357e911b15Skarels 	dga->x_cursor = TRANX(eq_header[unit]->curs_pos.x);
39367e911b15Skarels 	dga->y_cursor = TRANY(eq_header[unit]->curs_pos.y);
39377e911b15Skarels 
39387e911b15Skarels 	eq_header[unit]->curs_box.left = 0;
39397e911b15Skarels 	eq_header[unit]->curs_box.right = 0;
39407e911b15Skarels 	eq_header[unit]->curs_box.top = 0;
39417e911b15Skarels 	eq_header[unit]->curs_box.bottom = 0;
39427e911b15Skarels 
39437e911b15Skarels /*---------------------------------------------------------
39447e911b15Skarels * assign a pointer to the DMA I/O buffer for this QDSS. */
39457e911b15Skarels 
39467e911b15Skarels 	DMAheader[unit] = (struct DMAreq_header *)
39477e911b15Skarels 			  (((int)(&DMA_shared[0] + 512) & ~0x1FF)
39487e911b15Skarels 			   + (DMAbuf_size * unit));
39497e911b15Skarels 
39507e911b15Skarels 	DMAheader[unit]->DMAreq = (struct DMAreq *) ((int)DMAheader[unit]
39517e911b15Skarels 				  + sizeof(struct DMAreq_header));
39527e911b15Skarels 
39537e911b15Skarels 	DMAheader[unit]->QBAreg = 0;
39547e911b15Skarels 	DMAheader[unit]->status = 0;
39557e911b15Skarels 	DMAheader[unit]->shared_size = DMAbuf_size;
39567e911b15Skarels 	DMAheader[unit]->used = 0;
39577e911b15Skarels 	DMAheader[unit]->size = 10;	/* default = 10 requests */
39587e911b15Skarels 	DMAheader[unit]->oldest = 0;
39597e911b15Skarels 	DMAheader[unit]->newest = 0;
39607e911b15Skarels 
39617e911b15Skarels /*-----------------------------------------------------------
39627e911b15Skarels * assign a pointer to the scroll structure for this QDSS. */
39637e911b15Skarels 
39647e911b15Skarels 	scroll[unit] = (struct scroll *)
39657e911b15Skarels 			 (((int)(&scroll_shared[0] + 512) & ~0x1FF)
39667e911b15Skarels 			   + (sizeof(struct scroll) * unit));
39677e911b15Skarels 
39687e911b15Skarels 	scroll[unit]->status = 0;
39697e911b15Skarels 	scroll[unit]->viper_constant = 0;
39707e911b15Skarels 	scroll[unit]->y_scroll_constant = 0;
39717e911b15Skarels 	scroll[unit]->y_offset = 0;
39727e911b15Skarels 	scroll[unit]->x_index_pending = 0;
39737e911b15Skarels 	scroll[unit]->y_index_pending = 0;
39747e911b15Skarels 
39757e911b15Skarels /*----------------------------------------------------------------
39767e911b15Skarels * assign a pointer to the color map write buffer for this QDSS */
39777e911b15Skarels 
39787e911b15Skarels 	color_buf[unit] = (struct color_buf *)
39797e911b15Skarels 			   (((int)(&color_shared[0] + 512) & ~0x1FF)
39807e911b15Skarels 			    + (COLOR_BUFSIZ * unit));
39817e911b15Skarels 
39827e911b15Skarels 	color_buf[unit]->status = 0;
39837e911b15Skarels 	color_buf[unit]->count = 0;
39847e911b15Skarels 
39857e911b15Skarels } /* init_shared */
39867e911b15Skarels 
39877e911b15Skarels /*********************************************************************
39887e911b15Skarels *
39897e911b15Skarels *	setup_dragon()... init the ADDER, VIPER, bitmaps, & color map
39907e911b15Skarels *
39917e911b15Skarels **********************************************************************
39927e911b15Skarels *
39937e911b15Skarels *	calling convention:
39947e911b15Skarels *
39957e911b15Skarels *		setup_dragon();
39967e911b15Skarels *
39977e911b15Skarels *	return: NONE
39987e911b15Skarels *
39997e911b15Skarels ************************/
40007e911b15Skarels 
40017e911b15Skarels setup_dragon(unit)
40027e911b15Skarels u_int unit;
40037e911b15Skarels {
40047e911b15Skarels 
40057e911b15Skarels 	register struct adder *adder;
40067e911b15Skarels 	register struct dga *dga;
40077e911b15Skarels 	short *memcsr;
40087e911b15Skarels 
40097e911b15Skarels 	int i;			/* general purpose variables */
40107e911b15Skarels 	int status;
40117e911b15Skarels 
40127e911b15Skarels 	short top;		/* clipping/scrolling boundaries */
40137e911b15Skarels 	short bottom;
40147e911b15Skarels 	short right;
40157e911b15Skarels 	short left;
40167e911b15Skarels 
40177e911b15Skarels 	short *red;		/* color map pointers */
40187e911b15Skarels 	short *green;
40197e911b15Skarels 	short *blue;
40207e911b15Skarels 
40217e911b15Skarels /*------------------
40227e911b15Skarels * init for setup */
40237e911b15Skarels 
40247e911b15Skarels 	adder = (struct adder *) qdmap[unit].adder;
40257e911b15Skarels 	dga = (struct dga *) qdmap[unit].dga;
40267e911b15Skarels 	memcsr = (short *) qdmap[unit].memcsr;
40277e911b15Skarels 
40287e911b15Skarels 	dga->csr &= ~(DMA_IE | 0x700);	/* halt DMA and kill the intrpts */
40297e911b15Skarels 	*memcsr = SYNC_ON;		/* blank screen and turn off LED's */
40307e911b15Skarels 	adder->command = CANCEL;
40317e911b15Skarels 
40327e911b15Skarels /*----------------------
40337e911b15Skarels * set monitor timing */
40347e911b15Skarels 
40357e911b15Skarels 	adder->x_scan_count_0 = 0x2800;
40367e911b15Skarels 	adder->x_scan_count_1 = 0x1020;
40377e911b15Skarels 	adder->x_scan_count_2 = 0x003A;
40387e911b15Skarels 	adder->x_scan_count_3 = 0x38F0;
40397e911b15Skarels 	adder->x_scan_count_4 = 0x6128;
40407e911b15Skarels 	adder->x_scan_count_5 = 0x093A;
40417e911b15Skarels 	adder->x_scan_count_6 = 0x313C;
40427e911b15Skarels 	adder->sync_phase_adj = 0x0100;
40437e911b15Skarels 	adder->x_scan_conf = 0x00C8;
40447e911b15Skarels 
40457e911b15Skarels /*---------------------------------------------------------
40467e911b15Skarels * got a bug in secound pass ADDER! lets take care of it */
40477e911b15Skarels 
40487e911b15Skarels 	/* normally, just use the code in the following bug fix code, but to
40497e911b15Skarels 	* make repeated demos look pretty, load the registers as if there was
40507e911b15Skarels 	* no bug and then test to see if we are getting sync */
40517e911b15Skarels 
40527e911b15Skarels 	adder->y_scan_count_0 = 0x135F;
40537e911b15Skarels 	adder->y_scan_count_1 = 0x3363;
40547e911b15Skarels 	adder->y_scan_count_2 = 0x2366;
40557e911b15Skarels 	adder->y_scan_count_3 = 0x0388;
40567e911b15Skarels 
40577e911b15Skarels 	/* if no sync, do the bug fix code */
40587e911b15Skarels 
40597e911b15Skarels 	if (wait_status(adder, VSYNC) == BAD) {
40607e911b15Skarels 
40617e911b15Skarels 	    /* first load all Y scan registers with very short frame and
40627e911b15Skarels 	    * wait for scroll service.	This guarantees at least one SYNC
40637e911b15Skarels 	    * to fix the pass 2 Adder initialization bug (synchronizes
40647e911b15Skarels 	    * XCINCH with DMSEEDH) */
40657e911b15Skarels 
40667e911b15Skarels 	    adder->y_scan_count_0 = 0x01;
40677e911b15Skarels 	    adder->y_scan_count_1 = 0x01;
40687e911b15Skarels 	    adder->y_scan_count_2 = 0x01;
40697e911b15Skarels 	    adder->y_scan_count_3 = 0x01;
40707e911b15Skarels 
40717e911b15Skarels 	    wait_status(adder, VSYNC);	/* delay at least 1 full frame time */
40727e911b15Skarels 	    wait_status(adder, VSYNC);
40737e911b15Skarels 
40747e911b15Skarels 	    /* now load the REAL sync values (in reverse order just to
40757e911b15Skarels 	    *  be safe.  */
40767e911b15Skarels 
40777e911b15Skarels 	    adder->y_scan_count_3 = 0x0388;
40787e911b15Skarels 	    adder->y_scan_count_2 = 0x2366;
40797e911b15Skarels 	    adder->y_scan_count_1 = 0x3363;
40807e911b15Skarels 	    adder->y_scan_count_0 = 0x135F;
40817e911b15Skarels 	}
40827e911b15Skarels 
40837e911b15Skarels 	*memcsr = SYNC_ON | UNBLANK;	/* turn off leds and turn on video */
40847e911b15Skarels 
40857e911b15Skarels /*----------------------------
40867e911b15Skarels * zero the index registers */
40877e911b15Skarels 
40887e911b15Skarels 	adder->x_index_pending = 0;
40897e911b15Skarels 	adder->y_index_pending = 0;
40907e911b15Skarels 	adder->x_index_new = 0;
40917e911b15Skarels 	adder->y_index_new = 0;
40927e911b15Skarels 	adder->x_index_old = 0;
40937e911b15Skarels 	adder->y_index_old = 0;
40947e911b15Skarels 
40957e911b15Skarels 	adder->pause = 0;
40967e911b15Skarels 
40977e911b15Skarels /*----------------------------------------
40987e911b15Skarels * set rasterop mode to normal pen down */
40997e911b15Skarels 
41007e911b15Skarels 	adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL;
41017e911b15Skarels 
41027e911b15Skarels /*--------------------------------------------------
41037e911b15Skarels * set the rasterop registers to a default values */
41047e911b15Skarels 
41057e911b15Skarels 	adder->source_1_dx = 1;
41067e911b15Skarels 	adder->source_1_dy = 1;
41077e911b15Skarels 	adder->source_1_x = 0;
41087e911b15Skarels 	adder->source_1_y = 0;
41097e911b15Skarels 	adder->destination_x = 0;
41107e911b15Skarels 	adder->destination_y = 0;
41117e911b15Skarels 	adder->fast_dest_dx = 1;
41127e911b15Skarels 	adder->fast_dest_dy = 0;
41137e911b15Skarels 	adder->slow_dest_dx = 0;
41147e911b15Skarels 	adder->slow_dest_dy = 1;
41157e911b15Skarels 	adder->error_1 = 0;
41167e911b15Skarels 	adder->error_2 = 0;
41177e911b15Skarels 
41187e911b15Skarels /*------------------------
41197e911b15Skarels * scale factor = unity */
41207e911b15Skarels 
41217e911b15Skarels 	adder->fast_scale = UNITY;
41227e911b15Skarels 	adder->slow_scale = UNITY;
41237e911b15Skarels 
41247e911b15Skarels /*-------------------------------
41257e911b15Skarels * set the source 2 parameters */
41267e911b15Skarels 
41277e911b15Skarels 	adder->source_2_x = 0;
41287e911b15Skarels 	adder->source_2_y = 0;
41297e911b15Skarels 	adder->source_2_size = 0x0022;
41307e911b15Skarels 
41317e911b15Skarels /*-----------------------------------------------
41327e911b15Skarels * initialize plane addresses for eight vipers */
41337e911b15Skarels 
41347e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0001);
41357e911b15Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0000);
41367e911b15Skarels 
41377e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0002);
41387e911b15Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0001);
41397e911b15Skarels 
41407e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0004);
41417e911b15Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0002);
41427e911b15Skarels 
41437e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0008);
41447e911b15Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0003);
41457e911b15Skarels 
41467e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0010);
41477e911b15Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0004);
41487e911b15Skarels 
41497e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0020);
41507e911b15Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0005);
41517e911b15Skarels 
41527e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0040);
41537e911b15Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0006);
41547e911b15Skarels 
41557e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x0080);
41567e911b15Skarels 	write_ID(adder, PLANE_ADDRESS, 0x0007);
41577e911b15Skarels 
41587e911b15Skarels 	/* initialize the external registers. */
41597e911b15Skarels 
41607e911b15Skarels 	write_ID(adder, CS_UPDATE_MASK, 0x00FF);
41617e911b15Skarels 	write_ID(adder, CS_SCROLL_MASK, 0x00FF);
41627e911b15Skarels 
41637e911b15Skarels 	/* initialize resolution mode */
41647e911b15Skarels 
41657e911b15Skarels 	write_ID(adder, MEMORY_BUS_WIDTH, 0x000C);     /* bus width = 16 */
41667e911b15Skarels 	write_ID(adder, RESOLUTION_MODE, 0x0000);      /* one bit/pixel */
41677e911b15Skarels 
41687e911b15Skarels 	/* initialize viper registers */
41697e911b15Skarels 
41707e911b15Skarels 	write_ID(adder, SCROLL_CONSTANT, SCROLL_ENABLE|VIPER_LEFT|VIPER_UP);
41717e911b15Skarels 	write_ID(adder, SCROLL_FILL, 0x0000);
41727e911b15Skarels 
41737e911b15Skarels /*----------------------------------------------------
41747e911b15Skarels * set clipping and scrolling limits to full screen */
41757e911b15Skarels 
41767e911b15Skarels 	for ( i = 1000, adder->status = 0
41777e911b15Skarels 	    ; i > 0  &&  !((status = adder->status) & ADDRESS_COMPLETE)
41787e911b15Skarels 	    ; --i);
41797e911b15Skarels 
41807e911b15Skarels 	if (i == 0)
4181*e977faadSmarc 	    printf("\nqd%d: setup_dragon: timeout on ADDRESS_COMPLETE",unit);
41827e911b15Skarels 
41837e911b15Skarels 	top = 0;
41847e911b15Skarels 	bottom = 2048;
41857e911b15Skarels 	left = 0;
41867e911b15Skarels 	right = 1024;
41877e911b15Skarels 
41887e911b15Skarels 	adder->x_clip_min = left;
41897e911b15Skarels 	adder->x_clip_max = right;
41907e911b15Skarels 	adder->y_clip_min = top;
41917e911b15Skarels 	adder->y_clip_max = bottom;
41927e911b15Skarels 
41937e911b15Skarels 	adder->scroll_x_min = left;
41947e911b15Skarels 	adder->scroll_x_max = right;
41957e911b15Skarels 	adder->scroll_y_min = top;
41967e911b15Skarels 	adder->scroll_y_max = bottom;
41977e911b15Skarels 
41987e911b15Skarels 	wait_status(adder, VSYNC);	/* wait at LEAST 1 full frame */
41997e911b15Skarels 	wait_status(adder, VSYNC);
42007e911b15Skarels 
42017e911b15Skarels 	adder->x_index_pending = left;
42027e911b15Skarels 	adder->y_index_pending = top;
42037e911b15Skarels 	adder->x_index_new = left;
42047e911b15Skarels 	adder->y_index_new = top;
42057e911b15Skarels 	adder->x_index_old = left;
42067e911b15Skarels 	adder->y_index_old = top;
42077e911b15Skarels 
42087e911b15Skarels 	for ( i = 1000, adder->status = 0
42097e911b15Skarels 	    ; i > 0  &&  !((status = adder->status) & ADDRESS_COMPLETE)
42107e911b15Skarels 	    ; --i);
42117e911b15Skarels 
42127e911b15Skarels 	if (i == 0)
4213*e977faadSmarc 	    printf("\nqd%d: setup_dragon: timeout on ADDRESS_COMPLETE",unit);
42147e911b15Skarels 
42157e911b15Skarels 	write_ID(adder, LEFT_SCROLL_MASK, 0x0000);
42167e911b15Skarels 	write_ID(adder, RIGHT_SCROLL_MASK, 0x0000);
42177e911b15Skarels 
42187e911b15Skarels /*------------------------------------------------------------
42197e911b15Skarels * set source and the mask register to all ones (ie: white) */
42207e911b15Skarels 
42217e911b15Skarels 	write_ID(adder, SOURCE, 0xFFFF);
42227e911b15Skarels 	write_ID(adder, MASK_1, 0xFFFF);
42237e911b15Skarels 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
42247e911b15Skarels 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
42257e911b15Skarels 
42267e911b15Skarels /*--------------------------------------------------------------
42277e911b15Skarels * initialize Operand Control Register banks for fill command */
42287e911b15Skarels 
42297e911b15Skarels 	write_ID(adder, SRC1_OCR_A, EXT_NONE | INT_M1_M2  | NO_ID | WAIT);
42307e911b15Skarels 	write_ID(adder, SRC2_OCR_A, EXT_NONE | INT_SOURCE | NO_ID | NO_WAIT);
42317e911b15Skarels 	write_ID(adder, DST_OCR_A, EXT_NONE | INT_NONE	 | NO_ID | NO_WAIT);
42327e911b15Skarels 
42337e911b15Skarels 	write_ID(adder, SRC1_OCR_B, EXT_NONE | INT_SOURCE | NO_ID | WAIT);
42347e911b15Skarels 	write_ID(adder, SRC2_OCR_B, EXT_NONE | INT_M1_M2  | NO_ID | NO_WAIT);
42357e911b15Skarels 	write_ID(adder, DST_OCR_B, EXT_NONE | INT_NONE | NO_ID | NO_WAIT);
42367e911b15Skarels 
42377e911b15Skarels /*------------------------------------------------------------------
42387e911b15Skarels * init Logic Unit Function registers, (these are just common values,
42397e911b15Skarels * and may be changed as required).  */
42407e911b15Skarels 
42417e911b15Skarels 	write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
42427e911b15Skarels 	write_ID(adder, LU_FUNCTION_R2, FULL_SRC_RESOLUTION | LF_SOURCE | INV_M1_M2);
42437e911b15Skarels 	write_ID(adder, LU_FUNCTION_R3, FULL_SRC_RESOLUTION | LF_D_OR_S);
42447e911b15Skarels 	write_ID(adder, LU_FUNCTION_R4, FULL_SRC_RESOLUTION | LF_D_XOR_S);
42457e911b15Skarels 
42467e911b15Skarels /*----------------------------------------
42477e911b15Skarels * load the color map for black & white */
42487e911b15Skarels 
42497e911b15Skarels 	for ( i = 0, adder->status = 0
42507e911b15Skarels 	    ; i < 10000  &&  !((status = adder->status) & VSYNC)
42517e911b15Skarels 	    ; ++i);
42527e911b15Skarels 
42537e911b15Skarels 	if (i == 0)
4254*e977faadSmarc 	    printf("\nqd%d: setup_dragon: timeout on VSYNC", unit);
42557e911b15Skarels 
42567e911b15Skarels 	red = (short *) qdmap[unit].red;
42577e911b15Skarels 	green = (short *) qdmap[unit].green;
42587e911b15Skarels 	blue = (short *) qdmap[unit].blue;
42597e911b15Skarels 
42607e911b15Skarels 	*red++ = 0x00;			/* black */
42617e911b15Skarels 	*green++ = 0x00;
42627e911b15Skarels 	*blue++ = 0x00;
42637e911b15Skarels 
42647e911b15Skarels 	*red-- = 0xFF;			/* white */
42657e911b15Skarels 	*green-- = 0xFF;
42667e911b15Skarels 	*blue-- = 0xFF;
42677e911b15Skarels 
42687e911b15Skarels 	/*----------------------------------
42697e911b15Skarels 	* set color map for mouse cursor */
42707e911b15Skarels 
42717e911b15Skarels 	red += 254;
42727e911b15Skarels 	green += 254;
42737e911b15Skarels 	blue += 254;
42747e911b15Skarels 
42757e911b15Skarels 	*red++ = 0x00;			/* black */
42767e911b15Skarels 	*green++ = 0x00;
42777e911b15Skarels 	*blue++ = 0x00;
42787e911b15Skarels 
42797e911b15Skarels 	*red = 0xFF;			/* white */
42807e911b15Skarels 	*green = 0xFF;
42817e911b15Skarels 	*blue = 0xFF;
42827e911b15Skarels 
42837e911b15Skarels 	return(0);
42847e911b15Skarels 
42857e911b15Skarels } /* setup_dragon */
42867e911b15Skarels 
42877e911b15Skarels /******************************************************************
42887e911b15Skarels *
42897e911b15Skarels *	setup_input()... init the DUART and set defaults in input
42907e911b15Skarels *			 devices
42917e911b15Skarels *
42927e911b15Skarels *******************************************************************
42937e911b15Skarels *
42947e911b15Skarels *	calling convention:
42957e911b15Skarels *
42967e911b15Skarels *		setup_input(unit);
42977e911b15Skarels *
42987e911b15Skarels *	where: unit - is the QDSS unit number to be setup
42997e911b15Skarels *
43007e911b15Skarels *********/
43017e911b15Skarels 
43027e911b15Skarels setup_input(unit)
43037e911b15Skarels u_int unit;
43047e911b15Skarels {
43057e911b15Skarels 	register struct duart *duart;	/* DUART register structure pointer */
43067e911b15Skarels 	register int i; 		/* scratch variable */
43077e911b15Skarels 	register int bits;
43087e911b15Skarels 
43097e911b15Skarels 	char id_byte;
43107e911b15Skarels 	short status;
43117e911b15Skarels 
43127e911b15Skarels /*---------------
43137e911b15Skarels * init stuff */
43147e911b15Skarels 
43157e911b15Skarels 	duart = (struct duart *) qdmap[unit].duart;
43167e911b15Skarels 	duart->imask = 0;
43177e911b15Skarels 
43187e911b15Skarels /*---------------------------------------------
43197e911b15Skarels * setup the DUART for kbd & pointing device */
43207e911b15Skarels 
43217e911b15Skarels 	duart->cmdA = RESET_M;	  /* reset mode reg ptr for kbd */
43227e911b15Skarels 	duart->modeA = 0x13;	  /* 8 bits, no parity, rcv IE, */
43237e911b15Skarels 				  /* no RTS control,char error mode */
43247e911b15Skarels 	duart->modeA = 0x07;	  /* 1 stop bit,CTS does not IE XMT */
43257e911b15Skarels 				  /* no RTS control,no echo or loop */
43267e911b15Skarels 	duart->cmdB = RESET_M;	  /* reset mode reg pntr for host */
43277e911b15Skarels 	duart->modeB = 0x07;	  /* 8 bits, odd parity, rcv IE.. */
43287e911b15Skarels 				  /* ..no RTS cntrl, char error mode */
43297e911b15Skarels 	duart->modeB = 0x07;	  /* 1 stop bit,CTS does not IE XMT */
43307e911b15Skarels 				  /* no RTS control,no echo or loop */
43317e911b15Skarels 
43327e911b15Skarels 	duart->auxctl = 0x00;	  /* baud rate set 1 */
43337e911b15Skarels 
43347e911b15Skarels 	duart->clkselA = 0x99;	  /* 4800 baud for kbd */
43357e911b15Skarels 	duart->clkselB = 0x99;	  /* 4800 baud for mouse */
43367e911b15Skarels 
43377e911b15Skarels 	/* reset everything for keyboard */
43387e911b15Skarels 
43397e911b15Skarels 	for (bits = RESET_M; bits < START_BREAK; bits += 0x10)
43407e911b15Skarels 	    duart->cmdA = bits;
43417e911b15Skarels 
43427e911b15Skarels 	/* reset everything for host */
43437e911b15Skarels 
43447e911b15Skarels 	for (bits = RESET_M; bits < START_BREAK; bits += 0x10)
43457e911b15Skarels 	     duart->cmdB = bits;
43467e911b15Skarels 
43477e911b15Skarels 	duart->cmdA = EN_RCV | EN_XMT; /* enbl xmt & rcv for kbd */
43487e911b15Skarels 	duart->cmdB = EN_RCV | EN_XMT; /* enbl xmt & rcv for pointer device */
43497e911b15Skarels 
43507e911b15Skarels /*--------------------------------------------
43517e911b15Skarels * init keyboard defaults (DUART channel A) */
43527e911b15Skarels 
43537e911b15Skarels 	for (i = 500; i > 0; --i) {
43547e911b15Skarels 	    if ((status = duart->statusA) & XMT_RDY) {
43557e911b15Skarels 		duart->dataA = LK_DEFAULTS;
43567e911b15Skarels 		break;
43577e911b15Skarels 	    }
43587e911b15Skarels 	}
43597e911b15Skarels 
43607e911b15Skarels 	for (i = 100000; i > 0; --i) {
43617e911b15Skarels 	    if ((status = duart->statusA) & RCV_RDY) {
43627e911b15Skarels 		break;
43637e911b15Skarels 	    }
43647e911b15Skarels 	}
43657e911b15Skarels 
43667e911b15Skarels 	status = duart->dataA;		/* flush the ACK */
43677e911b15Skarels 
43687e911b15Skarels /*--------------------------------
43697e911b15Skarels * identify the pointing device */
43707e911b15Skarels 
43717e911b15Skarels 	for (i = 500; i > 0; --i) {
43727e911b15Skarels 	    if ((status = duart->statusB) & XMT_RDY) {
43737e911b15Skarels 		duart->dataB = SELF_TEST;
43747e911b15Skarels 		break;
43757e911b15Skarels 	    }
43767e911b15Skarels 	}
43777e911b15Skarels 
43787e911b15Skarels 	/*-----------------------------------------
43797e911b15Skarels 	* wait for 1st byte of self test report */
43807e911b15Skarels 
43817e911b15Skarels 	for (i = 100000; i > 0; --i) {
43827e911b15Skarels 	    if ((status = duart->statusB) & RCV_RDY) {
43837e911b15Skarels 		break;
43847e911b15Skarels 	    }
43857e911b15Skarels 	}
43867e911b15Skarels 
43877e911b15Skarels 	if (i == 0) {
4388*e977faadSmarc 	    printf("\nqd[%d]: setup_input: timeout on 1st byte of self test",unit);
43897e911b15Skarels 	    goto OUT;
43907e911b15Skarels 	}
43917e911b15Skarels 
43927e911b15Skarels 	status = duart->dataB;
43937e911b15Skarels 
43947e911b15Skarels 	/*-----------------------------------------
43957e911b15Skarels 	* wait for ID byte of self test report	*/
43967e911b15Skarels 
43977e911b15Skarels 	for (i = 100000; i > 0; --i) {
43987e911b15Skarels 	    if ((status = duart->statusB) & RCV_RDY) {
43997e911b15Skarels 		break;
44007e911b15Skarels 	    }
44017e911b15Skarels 	}
44027e911b15Skarels 
44037e911b15Skarels 	if (i == 0) {
4404*e977faadSmarc 	    printf("\nqd[%d]: setup_input: timeout on 2nd byte of self test", unit);
44057e911b15Skarels 	    goto OUT;
44067e911b15Skarels 	}
44077e911b15Skarels 
44087e911b15Skarels 	id_byte = duart->dataB;
44097e911b15Skarels 
44107e911b15Skarels 	/*------------------------------------
44117e911b15Skarels 	* wait for other bytes to come in  */
44127e911b15Skarels 
44137e911b15Skarels 	for (i = 100000; i > 0; --i) {
44147e911b15Skarels 	    if ((status = duart->statusB) & RCV_RDY) {
44157e911b15Skarels 		status = duart->dataB;
44167e911b15Skarels 		break;
44177e911b15Skarels 	    }
44187e911b15Skarels 	}
44197e911b15Skarels 
44207e911b15Skarels 	if (i == 0) {
4421*e977faadSmarc 	    printf("\nqd[%d]: setup_input: timeout on 3rd byte of self test", unit);
44227e911b15Skarels 	    goto OUT;
44237e911b15Skarels 	}
44247e911b15Skarels 
44257e911b15Skarels 	for (i = 100000; i > 0; --i) {
44267e911b15Skarels 	    if ((status = duart->statusB) & RCV_RDY) {
44277e911b15Skarels 		status = duart->dataB;
44287e911b15Skarels 		break;
44297e911b15Skarels 	    }
44307e911b15Skarels 	}
44317e911b15Skarels 
44327e911b15Skarels 	if (i == 0) {
4433*e977faadSmarc 	    printf("\nqd[%d]: setup_input: timeout on 4th byte of self test\n", unit);
44347e911b15Skarels 	    goto OUT;
44357e911b15Skarels 	}
44367e911b15Skarels 
44377e911b15Skarels 	/*----------------------------------------------
44387e911b15Skarels 	* flag pointing device type and set defaults */
44397e911b15Skarels 
44407e911b15Skarels 	for (i=100000; i>0; --i);
44417e911b15Skarels 
44427e911b15Skarels 	if ((id_byte & 0x0F) != TABLET_ID) {
44437e911b15Skarels 
44447e911b15Skarels 	    qdflags[unit].pntr_id = MOUSE_ID;
44457e911b15Skarels 
44467e911b15Skarels 	    for (i = 500; i > 0; --i) {
44477e911b15Skarels 		if ((status = duart->statusB) & XMT_RDY) {
44487e911b15Skarels 		    duart->dataB = INC_STREAM_MODE;
44497e911b15Skarels 		    break;
44507e911b15Skarels 		}
44517e911b15Skarels 	    }
44527e911b15Skarels 	} else {
44537e911b15Skarels 
44547e911b15Skarels 	    qdflags[unit].pntr_id = TABLET_ID;
44557e911b15Skarels 
44567e911b15Skarels 	    for (i = 500; i > 0; --i) {
44577e911b15Skarels 		if ((status = duart->statusB) & XMT_RDY) {
44587e911b15Skarels 		    duart->dataB = T_STREAM;
44597e911b15Skarels 		    break;
44607e911b15Skarels 		}
44617e911b15Skarels 	    }
44627e911b15Skarels 	}
44637e911b15Skarels 
44647e911b15Skarels /*--------
44657e911b15Skarels * exit */
44667e911b15Skarels 
44677e911b15Skarels OUT:
44687e911b15Skarels 	duart->imask = qdflags[unit].duart_imask;
44697e911b15Skarels 	return(0);
44707e911b15Skarels 
44717e911b15Skarels } /* setup_input */
44727e911b15Skarels 
44737e911b15Skarels /**********************************************************************
44747e911b15Skarels *
44757e911b15Skarels *	wait_status()... delay for at least one display frame time
44767e911b15Skarels *
44777e911b15Skarels ***********************************************************************
44787e911b15Skarels *
44797e911b15Skarels *	calling convention:
44807e911b15Skarels *
44817e911b15Skarels *		wait_status(adder, mask);
44827e911b15Skarels *		struct *adder adder;
44837e911b15Skarels *		int mask;
44847e911b15Skarels *
44857e911b15Skarels *	return: BAD means that we timed out without ever seeing the
44867e911b15Skarels *		      vertical sync status bit
44877e911b15Skarels *		GOOD otherwise
44887e911b15Skarels *
44897e911b15Skarels **************/
44907e911b15Skarels 
44917e911b15Skarels wait_status(adder, mask)
44927e911b15Skarels register struct adder *adder;
44937e911b15Skarels register int mask;
44947e911b15Skarels {
44957e911b15Skarels 	register short status;
44967e911b15Skarels 	int i;
44977e911b15Skarels 
44987e911b15Skarels 	for ( i = 10000, adder->status = 0
44997e911b15Skarels 	    ; i > 0  &&  !((status = adder->status) & mask)
45007e911b15Skarels 	    ; --i);
45017e911b15Skarels 
45027e911b15Skarels 	if (i == 0) {
4503*e977faadSmarc 	    printf("\nwait_status: timeout polling for 0x%x in adder->status", mask);
45047e911b15Skarels 	    return(BAD);
45057e911b15Skarels 	}
45067e911b15Skarels 
45077e911b15Skarels 	return(GOOD);
45087e911b15Skarels 
45097e911b15Skarels } /* wait_status */
45107e911b15Skarels 
45117e911b15Skarels /**********************************************************************
45127e911b15Skarels *
45137e911b15Skarels *	write_ID()... write out onto the ID bus
45147e911b15Skarels *
45157e911b15Skarels ***********************************************************************
45167e911b15Skarels *
45177e911b15Skarels *	calling convention:
45187e911b15Skarels *
45197e911b15Skarels *		struct *adder adder;	;pntr to ADDER structure
45207e911b15Skarels *		short adrs;		;VIPER address
45217e911b15Skarels *		short data;		;data to be written
45227e911b15Skarels *		write_ID(adder);
45237e911b15Skarels *
45247e911b15Skarels *	return: BAD means that we timed out waiting for status bits
45257e911b15Skarels *		      VIPER-access-specific status bits
45267e911b15Skarels *		GOOD otherwise
45277e911b15Skarels *
45287e911b15Skarels **************/
45297e911b15Skarels 
45307e911b15Skarels write_ID(adder, adrs, data)
45317e911b15Skarels register struct adder *adder;
45327e911b15Skarels register short adrs;
45337e911b15Skarels register short data;
45347e911b15Skarels {
45357e911b15Skarels 	int i;
45367e911b15Skarels 	short status;
45377e911b15Skarels 
4538*e977faadSmarc 	for ( i = 100000, adder->status = 0
4539*e977faadSmarc 	    ; i > 0  &&  !((status = adder->status) & ADDRESS_COMPLETE)
4540*e977faadSmarc 	    ; --i);
45417e911b15Skarels 
45427e911b15Skarels 	if (i == 0)
45437e911b15Skarels 	    goto ERR;
45447e911b15Skarels 
4545*e977faadSmarc 	for ( i = 100000, adder->status = 0
4546*e977faadSmarc 	    ; i > 0  &&  !((status = adder->status) & TX_READY)
4547*e977faadSmarc 	    ; --i);
45487e911b15Skarels 
45497e911b15Skarels 	if (i > 0) {
45507e911b15Skarels 	    adder->id_data = data;
45517e911b15Skarels 	    adder->command = ID_LOAD | adrs;
45527e911b15Skarels 	    return(GOOD);
45537e911b15Skarels 	}
45547e911b15Skarels 
45557e911b15Skarels ERR:
4556*e977faadSmarc 	printf("\nwrite_ID: timeout trying to write to VIPER");
45577e911b15Skarels 	return(BAD);
45587e911b15Skarels 
45597e911b15Skarels } /* write_ID */
4560*e977faadSmarc 
4561006e9885Smarc #endif
4562