xref: /csrg-svn/sys/vax/stand/qdcons.c (revision 35402)
134514Smarc /*
235355Sbostic  * Copyright (c) 1988 Regents of the University of California.
335355Sbostic  * All rights reserved.
434514Smarc  *
535355Sbostic  * Redistribution and use in source and binary forms are permitted
635355Sbostic  * provided that the above copyright notice and this paragraph are
735355Sbostic  * duplicated in all such forms and that any documentation,
835355Sbostic  * advertising materials, and other materials related to such
935355Sbostic  * distribution and use acknowledge that the software was developed
1035355Sbostic  * by the University of California, Berkeley.  The name of the
1135355Sbostic  * University may not be used to endorse or promote products derived
1235355Sbostic  * from this software without specific prior written permission.
1335355Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1435355Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1535355Sbostic  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1634514Smarc  *
17*35402Stef  *	@(#)qdcons.c	7.2 (Berkeley) 08/27/88
1835355Sbostic  */
1935355Sbostic 
2035355Sbostic /*
2134514Smarc  *	derived from: @(#)qdcons.c  4.1 (ULTRIX    11/23/87
2234514Smarc  */
2334514Smarc 
2434514Smarc /************************************************************************
2534514Smarc *
2634514Smarc *	ULTRIX QDSS STANDALONE BOOT DEVICE DRIVER...
2734514Smarc *	device driver to boot system with QDSS as console
2834514Smarc *
2934514Smarc *************************************************************************/
3034514Smarc /************************************************************************
3134514Smarc *									*
3234514Smarc *			Copyright (c) 1985 by				*
3334514Smarc *		Digital Equipment Corporation, Maynard, MA		*
3434514Smarc *			All rights reserved.				*
3534514Smarc *									*
3634514Smarc *   This software is furnished under a license and may be used and	*
3734514Smarc *   copied  only  in accordance with the terms of such license and	*
3834514Smarc *   with the  inclusion  of  the  above  copyright  notice.   This	*
3934514Smarc *   software  or  any  other copies thereof may not be provided or	*
4034514Smarc *   otherwise made available to any other person.  No title to and	*
4134514Smarc *   ownership of the software is hereby transferred.			*
4234514Smarc *									*
4334514Smarc *   The information in this software is subject to change  without	*
4434514Smarc *   notice  and should not be construed as a commitment by Digital	*
4534514Smarc *   Equipment Corporation.						*
4634514Smarc *									*
4734514Smarc *   Digital assumes no responsibility for the use  or  reliability	*
4834514Smarc *   of its software on equipment which is not supplied by Digital.	*
4934514Smarc *									*
5034514Smarc *************************************************************************
5134659Smarc * revision history: (should be moved into sccs comments)
5234514Smarc *************************************************************************
5334514Smarc *
5434514Smarc * 09 oct 85  longo  added uVAXII console ROM cursor reset to bottom of
5534514Smarc *		    the screen.  Also spruced up qdputc() & scroll_up()
5634514Smarc * 02 oct 85  longo  changed references to ADDRESS to be ADDRESS_COMPLETE
5734514Smarc * 23 aug 85  longo  changed I/O page CSR address to be 0x1F00
5834514Smarc * 20 aug 85  longo  created
5934514Smarc *
6034514Smarc ************************************************************************/
6134514Smarc 
6234514Smarc #include "../h/types.h"
6334514Smarc #include "../vax/cpu.h"
6434514Smarc #define KERNEL
6534884Sbostic #include "../vaxuba/qdioctl.h"
6634884Sbostic #include "../vaxuba/qevent.h"
6734884Sbostic #include "../vaxuba/qduser.h"
6834884Sbostic #include "../vaxuba/qdreg.h"
6934514Smarc #undef KERNEL
7034514Smarc 
7134514Smarc /*-----------------------------------------------------------------------
7234514Smarc * constants used to set VAX ROM's cursor to bottom the of the screen  */
7334514Smarc 
7434514Smarc #define NVR_ADRS	0x200B8024
7534514Smarc 
7634514Smarc #define CURRENT_ROW	0x4C	/* these are offsets to the ROM's scratch.. */
7734514Smarc #define ROW_MIN		0x4D    /* ..RAM start adrs as picked up out of NVR */
7834514Smarc #define ROW_MAX		0x4E
7934514Smarc #define CURRENT_COL	0x50
8034514Smarc #define COL_MIN		0x51
8134514Smarc #define COL_MAX		0x52
8234514Smarc 
8334514Smarc /*----------------------------------------
8434514Smarc * LK201 keyboard state tracking struct */
8534514Smarc 
8634514Smarc 	struct q_keyboard {
8734514Smarc 
8834514Smarc 	    int shift;			/* state variables	*/
8934514Smarc 	    int cntrl;
9034514Smarc 	    int lock;
9134514Smarc 	    char last;			/* last character	*/
9234514Smarc 
9334514Smarc 	 } q_keyboard;
9434514Smarc 
9534514Smarc 	int qdputc(), qdgetc();
9634514Smarc 
9734514Smarc 	extern (*v_putc)(),(*v_getc)();
9834514Smarc 
9934514Smarc /*----------------------------
10034514Smarc * general purpose defines  */
10134514Smarc 
10234514Smarc #define BAD	-1
10334514Smarc #define GOOD	0
10434514Smarc 
10534514Smarc /*----------------------------------------------
10634514Smarc * console cursor bitmap (block cursor type)  */
10734514Smarc 
10834514Smarc 	short cons_cursor[32] = {      /* white block cursor */
10934514Smarc 
11034514Smarc  /* A */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
11134514Smarc  	 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
11234514Smarc  /* B */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
11334514Smarc          0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF
11434514Smarc 
11534514Smarc 	};
11634514Smarc 
11734514Smarc /*-------------------------------------
11834514Smarc * constants used in font operations */
11934514Smarc 
12034514Smarc #define CHARS		95			/* # of chars in the font */
12134514Smarc #define CHAR_HEIGHT	15			/* char height in pixels */
12234514Smarc #define CHAR_WIDTH	8			/* char width in pixels*/
12334514Smarc #define FONT_WIDTH	(CHAR_WIDTH * CHARS)    /* font width in pixels */
12434514Smarc #define ROWS  		CHAR_HEIGHT
12534514Smarc 
12634514Smarc #define FONT_X		0			/* font's off screen adrs */
12734514Smarc #define FONT_Y		(2047 - CHAR_HEIGHT)
12834514Smarc /*
12934514Smarc #define FONT_Y		200
13034514Smarc */
13134514Smarc 
13234514Smarc 	extern char q_font[];		/* reference font object code */
13334514Smarc 
13434514Smarc 	extern  char q_key[];		/* reference key xlation tables */
13534514Smarc 	extern  char q_shift_key[];
13634514Smarc 	extern  char *q_special[];
13734514Smarc 
13834514Smarc /*----------------------------
13934514Smarc * console cursor structure */
14034514Smarc 
14134514Smarc 	struct cons_cur {
14234514Smarc 	    int x;
14334514Smarc 	    int y;
14434514Smarc 	} cursor;
14534514Smarc 
14634514Smarc /*------------------------------------------
14734514Smarc * MicroVAX-II q-bus addressing constants */
14834514Smarc 
14934514Smarc #define QMEMBASE 0x30000000
15034514Smarc #define QDSSCSR  0x20001F00
15134514Smarc 
15234514Smarc #define CHUNK     (64 * 1024)
15334514Smarc #define QMEMSIZE  (1024 * 1024 * 4)
15434514Smarc #define	QDBASE    (QMEMBASE + QMEMSIZE - CHUNK)
15534514Smarc 
15634514Smarc /*------------------------------------------------------------------
15734514Smarc * QDSS register address offsets from start of QDSS address space */
15834514Smarc 
15934514Smarc #define QDSIZE 	 (52 * 1024)	/* size of entire QDSS foot print */
16034514Smarc 
16134514Smarc #define TMPSIZE  (16 * 1024)	/* template RAM is 8k SHORT WORDS */
16234514Smarc #define TMPSTART 0x8000		/* offset of template RAM from base adrs */
16334514Smarc 
16434514Smarc #define REGSIZE	 (5 * 512)	/* regs touch 2.5k (5 pages) of addr space */
16534514Smarc #define REGSTART 0xC000		/* offset of reg pages from base adrs */
16634514Smarc 
16734514Smarc #define ADDER	(REGSTART+0x000)
16834514Smarc #define DGA	(REGSTART+0x200)
16934514Smarc #define DUART	(REGSTART+0x400)
17034514Smarc #define MEMCSR  (REGSTART+0x800)
17134514Smarc 
17234514Smarc #define	CLRSIZE  (3 * 512)		/* color map size */
17334514Smarc #define CLRSTART (REGSTART+0xA00)	/* color map start offset from base */
17434514Smarc 					/*  0x0C00 really */
17534514Smarc #define RED	(CLRSTART+0x000)
17634514Smarc #define BLUE	(CLRSTART+0x200)
17734514Smarc #define GREEN	(CLRSTART+0x400)
17834514Smarc 
17934514Smarc /*---------------------------------------
18034514Smarc * QDSS register address map structure */
18134514Smarc 
18234514Smarc 	struct qdmap qdmap;
18334514Smarc 
18434514Smarc /************************************************************************
18534514Smarc *************************************************************************
18634514Smarc *************************************************************************
18734514Smarc *
18834514Smarc *	EXTERNALLY CALLED ROUTINES START HERE:
18934514Smarc *
19034514Smarc *************************************************************************
19134514Smarc *************************************************************************
19234514Smarc ************************************************************************/
19334514Smarc 
19434514Smarc /************************************************************************
19534514Smarc *
19634514Smarc *	qd_init()... init the QDSS into a physical memory system
19734514Smarc *
19834514Smarc ************************************************************************/
19934514Smarc 
20034514Smarc qd_init()
20134514Smarc {
20234514Smarc 	register char *ROM_console;
20334514Smarc 	register short *NVR;
20434514Smarc 	register int i;
20534514Smarc 
20634514Smarc 	caddr_t qdaddr;
20734514Smarc 	struct dga *dga;
208*35402Stef 	extern int cpu;
20934514Smarc 
21034514Smarc  	qdaddr = (caddr_t) QDSSCSR;
21134514Smarc         if (badaddr(qdaddr, sizeof(short)))
21234514Smarc             return(0);
21334514Smarc 
21434514Smarc 	*(short *)qdaddr = (short) (QDBASE >> 16);
21534514Smarc 
21634514Smarc /*----------------------------------------------------------------------
21734514Smarc * load qdmap struct with the physical addresses of the QDSS elements */
21834514Smarc 
21934514Smarc 	qdmap.template = (caddr_t) QDBASE + TMPSTART;
22034514Smarc 	qdmap.adder = (caddr_t) QDBASE + ADDER;
22134514Smarc 	qdmap.dga = (caddr_t) QDBASE + DGA;
22234514Smarc 	qdmap.duart = (caddr_t) QDBASE + DUART;
22334514Smarc 	qdmap.memcsr = (caddr_t) QDBASE + MEMCSR;
22434514Smarc 	qdmap.red = (caddr_t) QDBASE + RED;
22534514Smarc 	qdmap.blue = (caddr_t) QDBASE + BLUE;
22634514Smarc 	qdmap.green = (caddr_t) QDBASE + GREEN;
22734514Smarc 
22834514Smarc /*--------------------------
22934514Smarc * no interrupts allowed! */
23034514Smarc 
23134514Smarc 	dga = (struct dga *) qdmap.dga;
23234514Smarc 	dga->csr = HALT;
23334514Smarc 	dga->csr |= CURS_ENB;
23434514Smarc 
23534514Smarc /*----------------------------
23634514Smarc * init the default values  */
23734514Smarc 
23834514Smarc 	q_keyboard.shift = 0;		/* init keyboard state tracking */
23934514Smarc 	q_keyboard.lock = 0;
24034514Smarc 	q_keyboard.cntrl = 0;
24134514Smarc 	q_keyboard.last = 0;
24234514Smarc 
24334514Smarc 	cursor.x = 0;			/* init cursor to top left */
24434514Smarc 	cursor.y = 0;
24534514Smarc 
24634514Smarc 	set_defaults();		        /* setup the default device */
24734514Smarc 	ldfont();			/* PtoB the font into off-screen */
24834514Smarc 
24934514Smarc /*--------------------------------------------------------------------
25034514Smarc * tell the VAX ROM that the cursor is at the bottom of the screen  */
25134514Smarc 
252*35402Stef 	if (cpu == VAX_630) {
253*35402Stef 		NVR = (short *) NVR_ADRS;
25434514Smarc 
255*35402Stef 		i = *NVR++ & 0xFF;
256*35402Stef 		i |= (*NVR++ & 0xFF) << 8;
257*35402Stef 		i |= (*NVR++ & 0xFF) << 16;
258*35402Stef 		i |= (*NVR++ & 0xFF) << 24;
25934514Smarc 
260*35402Stef 		ROM_console = (char *) i;
26134514Smarc 
262*35402Stef 		ROM_console[CURRENT_COL] = ROM_console[COL_MIN];
263*35402Stef 		ROM_console[CURRENT_ROW] = ROM_console[ROW_MAX];
264*35402Stef 	}
26534514Smarc 
26634514Smarc /*----------------------------------------------------------
26734514Smarc * smash system virtual console service routine addresses */
26834514Smarc 
269*35402Stef 	printf("switching console to QDSS display...\n");
27034514Smarc 	v_getc = qdgetc;
27134514Smarc 	v_putc = qdputc;
27234514Smarc 
27334514Smarc 	return(1);
27434514Smarc 
27534514Smarc } /* qd_init */
27634514Smarc 
27734514Smarc /*******************************************************************
27834514Smarc *
27934514Smarc *	qdputc()... output a character to the QDSS screen
28034514Smarc *
28134514Smarc ********************************************************************
28234514Smarc *
28334514Smarc *	calling convention:
28434514Smarc *
28534514Smarc *		qdputc(chr);
28634514Smarc *		char chr; 		;character to be displayed
28734514Smarc *
28834514Smarc ********/
28934514Smarc 
29034514Smarc qdputc(chr)
29134514Smarc char chr;
29234514Smarc {
29334514Smarc 	register struct adder *adder;
29434514Smarc 	register struct dga *dga;
29534514Smarc 	register int i;
29634514Smarc 
29734514Smarc 	short x;
29834514Smarc 
29934514Smarc 	adder = (struct adder *) qdmap.adder;
30034514Smarc 	dga = (struct dga *) qdmap.dga;
30134514Smarc 
30234514Smarc /*---------------------------
30334514Smarc * non display character?  */
30434514Smarc 
30534514Smarc 	chr &= 0x7F;
30634514Smarc 
30734514Smarc 	switch (chr) {
30834514Smarc 
30934514Smarc 	    case '\r':			/* return char */
31034514Smarc 	        cursor.x = 0;
31134514Smarc 		dga->x_cursor = TRANX(cursor.x);
31234514Smarc 	    	return(0);
31334514Smarc 
31434514Smarc 	    case '\t':			/* tab char */
31534514Smarc 
31634514Smarc 	    	for (i = 8 - ((cursor.x >> 3) & 0x07); i > 0; --i) {
31734514Smarc 	    	    qdputc(' ');
31834514Smarc 		}
31934514Smarc 		return(0);
32034514Smarc 
32134514Smarc 	    case '\n':			/* line feed char */
32234514Smarc 
32334514Smarc 	        if ((cursor.y += CHAR_HEIGHT) > (863 - CHAR_HEIGHT)) {
32434514Smarc 		    cursor.y -= CHAR_HEIGHT;
32534514Smarc 		    scroll_up(adder);
32634514Smarc 		}
32734514Smarc 		dga->y_cursor = TRANY(cursor.y);
32834514Smarc 		return(0);
32934514Smarc 
33034514Smarc 	    case '\b':			/* backspace char */
33134514Smarc 	        if (cursor.x > 0) {
33234514Smarc 	    	    cursor.x -= CHAR_WIDTH;
33334514Smarc 		    qdputc(' ');
33434514Smarc 		    cursor.x -= CHAR_WIDTH;
33534514Smarc 		    dga->x_cursor = TRANX(cursor.x);
33634514Smarc 		}
33734514Smarc 		return(0);
33834514Smarc 
33934514Smarc 	    default:
34034514Smarc 		if (chr < ' ' || chr > '~') {
34134514Smarc 		    return(0);
34234514Smarc 		}
34334514Smarc 	}
34434514Smarc 
34534514Smarc /*------------------------------------------
34634514Smarc * setup VIPER operand control registers  */
34734514Smarc 
34834514Smarc 	write_ID(adder, CS_UPDATE_MASK, 0x0001);  /* select plane #0 */
34934514Smarc 	write_ID(adder, SRC1_OCR_B,
35034514Smarc 			EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY);
35134514Smarc 
35234514Smarc 	write_ID(adder, CS_UPDATE_MASK, 0x00FE);  /* select other planes */
35334514Smarc 	write_ID(adder, SRC1_OCR_B,
35434514Smarc 			EXT_SOURCE | INT_NONE | NO_ID | BAR_SHIFT_DELAY);
35534514Smarc 
35634514Smarc 	write_ID(adder, CS_UPDATE_MASK, 0x00FF);  /* select all planes */
35734514Smarc 	write_ID(adder, DST_OCR_B,
35834514Smarc 			EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
35934514Smarc 
36034514Smarc 	write_ID(adder, MASK_1, 0xFFFF);
36134514Smarc 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 1);
36234514Smarc 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
36334514Smarc 
36434514Smarc /*----------------------------------------
36534514Smarc * load DESTINATION origin and vectors  */
36634514Smarc 
36734514Smarc 	adder->fast_dest_dy = 0;
36834514Smarc 	adder->slow_dest_dx = 0;
36934514Smarc 	adder->error_1 = 0;
37034514Smarc 	adder->error_2 = 0;
37134514Smarc 
37234514Smarc 	adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL;
37334514Smarc 
37434514Smarc 	wait_status(adder, RASTEROP_COMPLETE);
37534514Smarc 
37634514Smarc 	adder->destination_x = cursor.x;
37734514Smarc 	adder->fast_dest_dx = CHAR_WIDTH;
37834514Smarc 
37934514Smarc 	adder->destination_y = cursor.y;
38034514Smarc 	adder->slow_dest_dy = CHAR_HEIGHT;
38134514Smarc 
38234514Smarc /*-----------------------------------
38334514Smarc * load SOURCE origin and vectors  */
38434514Smarc 
38534514Smarc 	adder->source_1_x = FONT_X + ((chr - ' ') * CHAR_WIDTH);
38634514Smarc 	adder->source_1_y = FONT_Y;
38734514Smarc 
38834514Smarc 	adder->source_1_dx = CHAR_WIDTH;
38934514Smarc 	adder->source_1_dy = CHAR_HEIGHT;
39034514Smarc 
39134514Smarc 	write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
39234514Smarc 	adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE;
39334514Smarc 
39434514Smarc /*-------------------------------------
39534514Smarc * update console cursor coordinates */
39634514Smarc 
39734514Smarc 	cursor.x += CHAR_WIDTH;
39834514Smarc 	dga->x_cursor = TRANX(cursor.x);
39934514Smarc 
40034514Smarc         if (cursor.x > (1024 - CHAR_WIDTH)) {
40134514Smarc 	    qdputc('\r');
40234514Smarc 	    qdputc('\n');
40334514Smarc 	}
40434514Smarc 
40534514Smarc } /* qdputc */
40634514Smarc 
40734514Smarc /*******************************************************************
40834514Smarc *
40934514Smarc *	qdgetc()... get a character from the LK201
41034514Smarc *
41134514Smarc *******************************************************************/
41234514Smarc 
41334514Smarc qdgetc()
41434514Smarc {
41534514Smarc 	register short key;
41634514Smarc 	register char chr;
41734514Smarc 	register struct duart *duart;
41834514Smarc 
41934514Smarc 	u_int status;
42034514Smarc 
42134514Smarc 	duart = (struct duart *) qdmap.duart;
42234514Smarc 
42334514Smarc 	/*--------------------------------------
42434514Smarc 	* Get a character from the keyboard. */
42534514Smarc 
42634514Smarc LOOP:
42734514Smarc 	while (!((status = duart->statusA) & RCV_RDY))
42834514Smarc 			;
42934514Smarc 
43034514Smarc 	key = duart->dataA;
43134514Smarc 	key &= 0xFF;
43234514Smarc 
43334514Smarc 	/*--------------------------------------
43434514Smarc 	* Check for various keyboard errors  */
43534514Smarc 
43634514Smarc 	if( key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
43734514Smarc 	    key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
43834514Smarc 		printf("Keyboard error, code = %x\n", key);
43934514Smarc 		return(0);
44034514Smarc 	}
44134514Smarc 
44234514Smarc 	if (key < LK_LOWEST)
44334514Smarc 	    return(0);
44434514Smarc 
44534514Smarc 	/*---------------------------------
44634514Smarc 	* See if its a state change key */
44734514Smarc 
44834514Smarc 	switch (key) {
44934514Smarc 
45034514Smarc 	    case LOCK:
45134514Smarc 		q_keyboard.lock ^= 0xffff;	/* toggle */
45234514Smarc 		if (q_keyboard.lock)
45334514Smarc 		    led_control(LK_LED_ENABLE, LK_LED_LOCK);
45434514Smarc 		else
45534514Smarc 		    led_control(LK_LED_DISABLE, LK_LED_LOCK);
45634514Smarc 		goto LOOP;
45734514Smarc 
45834514Smarc 	    case SHIFT:
45934514Smarc 		q_keyboard.shift ^= 0xFFFF;
46034514Smarc 		goto LOOP;
46134514Smarc 
46234514Smarc 	    case CNTRL:
46334514Smarc 		q_keyboard.cntrl ^= 0xFFFF;
46434514Smarc 		goto LOOP;
46534514Smarc 
46634514Smarc 	    case ALLUP:
46734514Smarc 		q_keyboard.cntrl = 0;
46834514Smarc 		q_keyboard.shift = 0;
46934514Smarc 		goto LOOP;
47034514Smarc 
47134514Smarc 	    case REPEAT:
47234514Smarc 		chr = q_keyboard.last;
47334514Smarc 		break;
47434514Smarc 
47534514Smarc 	    /*-------------------------------------------------------
47634514Smarc 	    * Test for cntrl characters. If set, see if the character
47734514Smarc 	    * is elligible to become a control character. */
47834514Smarc 
47934514Smarc 	    default:
48034514Smarc 
48134514Smarc 		if (q_keyboard.cntrl) {
48234514Smarc 		    chr = q_key[key];
48334514Smarc 		    if (chr >= ' ' && chr <= '~')
48434514Smarc 			chr &= 0x1F;
48534514Smarc 		}
48634514Smarc 		else if ( q_keyboard.lock || q_keyboard.shift )
48734514Smarc 		    chr = q_shift_key[key];
48834514Smarc 		else
48934514Smarc 		    chr = q_key[key];
49034514Smarc 		break;
49134514Smarc 	}
49234514Smarc 
49334514Smarc 	if (chr < ' ' && chr > '~')  	/* if input is non-displayable */
49434514Smarc 	    return(0);			/* ..then pitch it! */
49534514Smarc 
49634514Smarc 	q_keyboard.last = chr;
49734514Smarc 
49834514Smarc 	/*-----------------------------------
49934514Smarc 	* Check for special function keys */
50034514Smarc 
50134514Smarc 	if (chr & 0x80) 		/* pitch the function keys */
50234514Smarc 	    return(0);
50334514Smarc 	else
50434514Smarc 	    return(chr);
50534514Smarc 
50634514Smarc } /* qdgetc */
50734514Smarc 
50834514Smarc /************************************************************************
50934514Smarc *************************************************************************
51034514Smarc *************************************************************************
51134514Smarc *
51234514Smarc *	INTERNALLY USED ROUTINES START HERE:
51334514Smarc *
51434514Smarc *************************************************************************
51534514Smarc *************************************************************************
51634514Smarc ************************************************************************/
51734514Smarc 
51834514Smarc /********************************************************************
51934514Smarc *
52034514Smarc *	ldcursor()... load the mouse cursor's template RAM bitmap
52134514Smarc *
52234514Smarc ********************************************************************/
52334514Smarc 
52434514Smarc ldcursor()
52534514Smarc {
52634514Smarc 	register struct dga *dga;
52734514Smarc 	register short *temp;
52834514Smarc 	register int i;
52934514Smarc 
53034514Smarc 	int cursor;
53134514Smarc 
53234514Smarc 	dga = (struct dga *) qdmap.dga;
53334514Smarc 	temp = (short *) qdmap.template;
53434514Smarc 
53534514Smarc 	temp += (8 * 1024) - 32;	/* cursor is 32 WORDS from the end */
53634514Smarc 					/* ..of the 8k WORD template space */
53734514Smarc 	for (i = 0; i < 32; ++i)
53834514Smarc 	    *temp++ = cons_cursor[i];
53934514Smarc 
54034514Smarc 	return(0);
54134514Smarc 
54234514Smarc } /* ldcursor */
54334514Smarc 
54434514Smarc /**********************************************************************
54534514Smarc *
54634514Smarc *	ldfont()... put the console font in the QDSS off-screen memory
54734514Smarc *
54834514Smarc **********************************************************************/
54934514Smarc 
55034514Smarc ldfont()
55134514Smarc {
55234514Smarc 	register struct adder *adder;
55334514Smarc 
55434514Smarc 	int i;		/* scratch variables */
55534514Smarc 	int j;
55634514Smarc 	int k;
55734514Smarc 	short packed;
55834514Smarc 
55934514Smarc 	adder = (struct adder *) qdmap.adder;
56034514Smarc 
56134514Smarc /*------------------------------------------
56234514Smarc * setup VIPER operand control registers  */
56334514Smarc 
56434514Smarc 	write_ID(adder, MASK_1, 0xFFFF);
56534514Smarc 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
56634514Smarc 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
56734514Smarc 
56834514Smarc 	write_ID(adder, SRC1_OCR_B,
56934514Smarc 			EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY);
57034514Smarc 	write_ID(adder, SRC2_OCR_B,
57134514Smarc 			EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY);
57234514Smarc 	write_ID(adder, DST_OCR_B,
57334514Smarc 			EXT_SOURCE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
57434514Smarc 
57534514Smarc 	adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL;
57634514Smarc 
57734514Smarc /*--------------------------
57834514Smarc * load destination data  */
57934514Smarc 
58034514Smarc 	wait_status(adder, RASTEROP_COMPLETE);
58134514Smarc 
58234514Smarc 	adder->destination_x = FONT_X;
58334514Smarc 	adder->destination_y = FONT_Y;
58434514Smarc 	adder->fast_dest_dx = FONT_WIDTH;
58534514Smarc 	adder->slow_dest_dy = CHAR_HEIGHT;
58634514Smarc 
58734514Smarc /*---------------------------------------
58834514Smarc * setup for processor to bitmap xfer  */
58934514Smarc 
59034514Smarc 	write_ID(adder, CS_UPDATE_MASK, 0x0001);
59134514Smarc 	adder->cmd = PBT | OCRB | 2 | DTE | 2;
59234514Smarc 
59334514Smarc /*-----------------------------------------------
59434514Smarc * iteratively do the processor to bitmap xfer */
59534514Smarc 
59634514Smarc 	for (i = 0; i < ROWS; ++i) {
59734514Smarc 
59834514Smarc 	    /* PTOB a scan line */
59934514Smarc 
60034514Smarc 	    for (j = 0, k = i; j < 48; ++j) {
60134514Smarc 
60234514Smarc 	        /* PTOB one scan of a char cell */
60334514Smarc 
60434514Smarc 		packed = q_font[k];
60534514Smarc 		k += ROWS;
60634514Smarc 		packed |= ((short)q_font[k] << 8);
60734514Smarc 		k += ROWS;
60834514Smarc 
60934514Smarc 	        wait_status(adder, TX_READY);
61034514Smarc 	        adder->id_data = packed;
61134514Smarc 	    }
61234514Smarc 	}
61334514Smarc 
61434514Smarc }  /* ldfont */
61534514Smarc 
61634514Smarc /*********************************************************************
61734514Smarc *
61834514Smarc *	led_control()... twiddle LK-201 LED's
61934514Smarc *
62034514Smarc **********************************************************************
62134514Smarc *
62234514Smarc *	led_control(cmd, led_mask);
62334514Smarc *	int cmd;	LED enable/disable command
62434514Smarc *	int led_mask;	which LED(s) to twiddle
62534514Smarc *
62634514Smarc *************/
62734514Smarc 
62834514Smarc led_control(cmd, led_mask)
62934514Smarc int cmd;
63034514Smarc int led_mask;
63134514Smarc {
63234514Smarc 	register int i;
63334514Smarc 	register int status;
63434514Smarc 	register struct duart *duart;
63534514Smarc 
63634514Smarc 	duart = (struct duart *) qdmap.duart;
63734514Smarc 
63834514Smarc 	for (i = 1000; i > 0; --i) {
63934514Smarc     	    if ((status = duart->statusA) & XMT_RDY) {
64034514Smarc         	duart->dataA = cmd;
64134514Smarc 		break;
64234514Smarc     	    }
64334514Smarc 	}
64434514Smarc 
64534514Smarc 	for (i = 1000; i > 0; --i) {
64634514Smarc     	    if ((status = duart->statusA) & XMT_RDY) {
64734514Smarc         	duart->dataA = led_mask;
64834514Smarc 		break;
64934514Smarc     	    }
65034514Smarc 	}
65134514Smarc 
65234514Smarc 	if (i == 0)
65334514Smarc 	    return(BAD);
65434514Smarc 
65534514Smarc 	return(GOOD);
65634514Smarc 
65734514Smarc } /* led_control */
65834514Smarc 
65934514Smarc /*******************************************************************
66034514Smarc *
66134514Smarc *	scroll_up()... move the screen up one character height
66234514Smarc *
66334514Smarc ********************************************************************
66434514Smarc *
66534514Smarc *	calling convention:
66634514Smarc *
66734514Smarc *		scroll_up(adder);
66834514Smarc *		struct adder *adder;    ;address of adder
66934514Smarc *
67034514Smarc ********/
67134514Smarc 
67234514Smarc scroll_up(adder)
67334514Smarc register struct adder *adder;
67434514Smarc {
67534514Smarc 
67634514Smarc /*------------------------------------------
67734514Smarc * setup VIPER operand control registers  */
67834514Smarc 
67934514Smarc 	wait_status(adder, ADDRESS_COMPLETE);
68034514Smarc 
68134514Smarc 	write_ID(adder, CS_UPDATE_MASK, 0x00FF);  /* select all planes */
68234514Smarc 
68334514Smarc 	write_ID(adder, MASK_1, 0xFFFF);
68434514Smarc 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
68534514Smarc 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
68634514Smarc 
68734514Smarc 	write_ID(adder, SRC1_OCR_B,
68834514Smarc 			EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY);
68934514Smarc 	write_ID(adder, DST_OCR_B,
69034514Smarc 			EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
69134514Smarc 
69234514Smarc /*----------------------------------------
69334514Smarc * load DESTINATION origin and vectors  */
69434514Smarc 
69534514Smarc 	adder->fast_dest_dy = 0;
69634514Smarc 	adder->slow_dest_dx = 0;
69734514Smarc 	adder->error_1 = 0;
69834514Smarc 	adder->error_2 = 0;
69934514Smarc 
70034514Smarc 	adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL;
70134514Smarc 
70234514Smarc 	adder->destination_x = 0;
70334514Smarc 	adder->fast_dest_dx = 1024;
70434514Smarc 
70534514Smarc 	adder->destination_y = 0;
70634514Smarc 	adder->slow_dest_dy = 864 - CHAR_HEIGHT;
70734514Smarc 
70834514Smarc /*-----------------------------------
70934514Smarc * load SOURCE origin and vectors  */
71034514Smarc 
71134514Smarc 	adder->source_1_x = 0;
71234514Smarc 	adder->source_1_dx = 1024;
71334514Smarc 
71434514Smarc 	adder->source_1_y = 0 + CHAR_HEIGHT;
71534514Smarc 	adder->source_1_dy = 864 - CHAR_HEIGHT;
71634514Smarc 
71734514Smarc 	write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
71834514Smarc 	adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE;
71934514Smarc 
72034514Smarc /*--------------------------------------------
72134514Smarc * do a rectangle clear of last screen line */
72234514Smarc 
72334514Smarc 	write_ID(adder, MASK_1, 0xffff);
72434514Smarc 	write_ID(adder, SOURCE, 0xffff);
72534514Smarc 	write_ID(adder,DST_OCR_B,
72634514Smarc 	  	(EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY));
72734514Smarc 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 0);
72834514Smarc 	adder->error_1 = 0;
72934514Smarc 	adder->error_2 = 0;
73034514Smarc 	adder->slow_dest_dx = 0;	/* set up the width of	*/
73134514Smarc 	adder->slow_dest_dy = CHAR_HEIGHT;	/* rectangle */
73234514Smarc 
73334514Smarc 	adder->rasterop_mode = (NORMAL | DST_WRITE_ENABLE) ;
73434514Smarc 	wait_status(adder, RASTEROP_COMPLETE);
73534514Smarc 	adder->destination_x = 0;
73634514Smarc 	adder->destination_y = 864 - CHAR_HEIGHT;
73734514Smarc 
73834514Smarc 	adder->fast_dest_dx = 1024;	/* set up the height	*/
73934514Smarc 	adder->fast_dest_dy = 0;	/* of rectangle		*/
74034514Smarc 
74134514Smarc 	write_ID(adder, LU_FUNCTION_R2, (FULL_SRC_RESOLUTION | LF_SOURCE));
74234514Smarc 	adder->cmd = (RASTEROP | OCRB | LF_R2 | DTE ) ;
74334514Smarc 
74434514Smarc } /* scroll_up */
74534514Smarc 
74634514Smarc /**********************************************************************
74734514Smarc *
74834514Smarc *	set_defaults()... init the QDSS device and driver defaults
74934514Smarc *
75034514Smarc **********************************************************************/
75134514Smarc 
75234514Smarc set_defaults()
75334514Smarc {
75434514Smarc 	setup_input();		/* init the DUART */
75534514Smarc 	setup_dragon();		/* init the ADDER/VIPER stuff */
75634514Smarc 	ldcursor();		/* load default cursor map */
75734514Smarc 
75834514Smarc } /* set_defaults */
75934514Smarc 
76034514Smarc /*********************************************************************
76134514Smarc *
76234514Smarc *	setup_dragon()... init the ADDER, VIPER, bitmaps, & color map
76334514Smarc *
76434514Smarc *********************************************************************/
76534514Smarc 
76634514Smarc setup_dragon()
76734514Smarc {
76834514Smarc 
76934514Smarc 	register struct adder *adder;
77034514Smarc 	register struct dga *dga;
77134514Smarc 	short *memcsr;
77234514Smarc 
77334514Smarc 	int i;			/* general purpose variables */
77434514Smarc 	int status;
77534514Smarc 
77634514Smarc 	short top;		/* clipping/scrolling boundaries */
77734514Smarc 	short bottom;
77834514Smarc 	short right;
77934514Smarc 	short left;
78034514Smarc 
78134514Smarc 	short *red;		/* color map pointers */
78234514Smarc 	short *green;
78334514Smarc 	short *blue;
78434514Smarc 
78534514Smarc /*------------------
78634514Smarc * init for setup */
78734514Smarc 
78834514Smarc 	adder = (struct adder *) qdmap.adder;
78934514Smarc 	dga = (struct dga *) qdmap.dga;
79034514Smarc 	memcsr = (short *) qdmap.memcsr;
79134514Smarc 
79234514Smarc 	*memcsr = SYNC_ON;		/* blank screen and turn off LED's */
79334514Smarc 	adder->command = CANCEL;
79434514Smarc 
79534514Smarc /*----------------------
79634514Smarc * set monitor timing */
79734514Smarc 
79834514Smarc 	adder->x_scan_count_0 = 0x2800;
79934514Smarc 	adder->x_scan_count_1 = 0x1020;
80034514Smarc 	adder->x_scan_count_2 = 0x003A;
80134514Smarc 	adder->x_scan_count_3 = 0x38F0;
80234514Smarc 	adder->x_scan_count_4 = 0x6128;
80334514Smarc 	adder->x_scan_count_5 = 0x093A;
80434514Smarc 	adder->x_scan_count_6 = 0x313C;
80534514Smarc 	adder->sync_phase_adj = 0x0100;
80634514Smarc 	adder->x_scan_conf = 0x00C8;
80734514Smarc 
80834514Smarc /*---------------------------------------------------------
80934514Smarc * got a bug in secound pass ADDER! lets take care of it */
81034514Smarc 
81134514Smarc 	/* normally, just use the code in the following bug fix code, but to
81234514Smarc 	* make repeated demos look pretty, load the registers as if there was
81334514Smarc 	* no bug and then test to see if we are getting sync */
81434514Smarc 
81534514Smarc 	adder->y_scan_count_0 = 0x135F;
81634514Smarc 	adder->y_scan_count_1 = 0x3363;
81734514Smarc 	adder->y_scan_count_2 = 0x2366;
81834514Smarc 	adder->y_scan_count_3 = 0x0388;
81934514Smarc 
82034514Smarc 	/* if no sync, do the bug fix code */
82134514Smarc 
82234514Smarc 	if (wait_status(adder, VSYNC) == BAD) {
82334514Smarc 
82434514Smarc 	    /* first load all Y scan registers with very short frame and
82534514Smarc 	    * wait for scroll service.  This guarantees at least one SYNC
82634514Smarc 	    * to fix the pass 2 Adder initialization bug (synchronizes
82734514Smarc 	    * XCINCH with DMSEEDH) */
82834514Smarc 
82934514Smarc 	    adder->y_scan_count_0 = 0x01;
83034514Smarc 	    adder->y_scan_count_1 = 0x01;
83134514Smarc 	    adder->y_scan_count_2 = 0x01;
83234514Smarc 	    adder->y_scan_count_3 = 0x01;
83334514Smarc 
83434514Smarc 	    wait_status(adder, VSYNC);	/* delay at least 1 full frame time */
83534514Smarc 	    wait_status(adder, VSYNC);
83634514Smarc 
83734514Smarc 	    /* now load the REAL sync values (in reverse order just to
83834514Smarc 	    *  be safe.  */
83934514Smarc 
84034514Smarc 	    adder->y_scan_count_3 = 0x0388;
84134514Smarc 	    adder->y_scan_count_2 = 0x2366;
84234514Smarc 	    adder->y_scan_count_1 = 0x3363;
84334514Smarc 	    adder->y_scan_count_0 = 0x135F;
84434514Smarc   	}
84534514Smarc 
84634514Smarc /*----------------------------
84734514Smarc * zero the index registers */
84834514Smarc 
84934514Smarc 	adder->x_index_pending = 0;
85034514Smarc 	adder->y_index_pending = 0;
85134514Smarc 	adder->x_index_new = 0;
85234514Smarc 	adder->y_index_new = 0;
85334514Smarc 	adder->x_index_old = 0;
85434514Smarc 	adder->y_index_old = 0;
85534514Smarc 
85634514Smarc 	adder->pause = 0;
85734514Smarc 
85834514Smarc /*----------------------------------------
85934514Smarc * set rasterop mode to normal pen down */
86034514Smarc 
86134514Smarc 	adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL;
86234514Smarc 
86334514Smarc /*--------------------------------------------------
86434514Smarc * set the rasterop registers to a default values */
86534514Smarc 
86634514Smarc 	adder->source_1_dx = 1;
86734514Smarc 	adder->source_1_dy = 1;
86834514Smarc 	adder->source_1_x = 0;
86934514Smarc 	adder->source_1_y = 0;
87034514Smarc 	adder->destination_x = 0;
87134514Smarc 	adder->destination_y = 0;
87234514Smarc 	adder->fast_dest_dx = 1;
87334514Smarc 	adder->fast_dest_dy = 0;
87434514Smarc 	adder->slow_dest_dx = 0;
87534514Smarc 	adder->slow_dest_dy = 1;
87634514Smarc    	adder->error_1 = 0;
87734514Smarc 	adder->error_2 = 0;
87834514Smarc 
87934514Smarc /*------------------------
88034514Smarc * scale factor = unity */
88134514Smarc 
88234514Smarc 	adder->fast_scale = UNITY;
88334514Smarc 	adder->slow_scale = UNITY;
88434514Smarc 
88534514Smarc /*-------------------------------
88634514Smarc * set the source 2 parameters */
88734514Smarc 
88834514Smarc 	adder->source_2_x = 0;
88934514Smarc 	adder->source_2_y = 0;
89034514Smarc 	adder->source_2_size = 0x0022;
89134514Smarc 
89234514Smarc /*-----------------------------------------------
89334514Smarc * initialize plane addresses for eight vipers */
89434514Smarc 
89534514Smarc 	write_ID(adder, CS_UPDATE_MASK, 0x0001);
89634514Smarc 	write_ID(adder, PLANE_ADDRESS, 0x0000);
89734514Smarc 
89834514Smarc 	write_ID(adder, CS_UPDATE_MASK, 0x0002);
89934514Smarc 	write_ID(adder, PLANE_ADDRESS, 0x0001);
90034514Smarc 
90134514Smarc 	write_ID(adder, CS_UPDATE_MASK, 0x0004);
90234514Smarc 	write_ID(adder, PLANE_ADDRESS, 0x0002);
90334514Smarc 
90434514Smarc 	write_ID(adder, CS_UPDATE_MASK, 0x0008);
90534514Smarc 	write_ID(adder, PLANE_ADDRESS, 0x0003);
90634514Smarc 
90734514Smarc 	write_ID(adder, CS_UPDATE_MASK, 0x0010);
90834514Smarc 	write_ID(adder, PLANE_ADDRESS, 0x0004);
90934514Smarc 
91034514Smarc 	write_ID(adder, CS_UPDATE_MASK, 0x0020);
91134514Smarc 	write_ID(adder, PLANE_ADDRESS, 0x0005);
91234514Smarc 
91334514Smarc 	write_ID(adder, CS_UPDATE_MASK, 0x0040);
91434514Smarc 	write_ID(adder, PLANE_ADDRESS, 0x0006);
91534514Smarc 
91634514Smarc 	write_ID(adder, CS_UPDATE_MASK, 0x0080);
91734514Smarc 	write_ID(adder, PLANE_ADDRESS, 0x0007);
91834514Smarc 
91934514Smarc 	/* initialize the external registers. */
92034514Smarc 
92134514Smarc 	write_ID(adder, CS_UPDATE_MASK, 0x00FF);
92234514Smarc 	write_ID(adder, CS_SCROLL_MASK, 0x00FF);
92334514Smarc 
92434514Smarc 	/* initialize resolution mode */
92534514Smarc 
92634514Smarc 	write_ID(adder, MEMORY_BUS_WIDTH, 0x000C);     /* bus width = 16 */
92734514Smarc 	write_ID(adder, RESOLUTION_MODE, 0x0000);      /* one bit/pixel */
92834514Smarc 
92934514Smarc 	/* initialize viper registers */
93034514Smarc 
93134514Smarc 	write_ID(adder, SCROLL_CONSTANT, SCROLL_ENABLE|VIPER_LEFT|VIPER_UP);
93234514Smarc 	write_ID(adder, SCROLL_FILL, 0x0000);
93334514Smarc 
93434514Smarc /*----------------------------------------------------
93534514Smarc * set clipping and scrolling limits to full screen */
93634514Smarc 
93734514Smarc 	for ( i = 1000, adder->status = 0
93834514Smarc 	    ; i > 0  &&  !((status = adder->status) & ADDRESS_COMPLETE)
93934514Smarc 	    ; --i);
94034514Smarc 
94134514Smarc 	if (i == 0)
94234514Smarc 	    printf("timeout trying to setup clipping\n");
94334514Smarc 
94434514Smarc 	top = 0;
94534514Smarc 	bottom = 2048;
94634514Smarc 	left = 0;
94734514Smarc 	right = 1024;
94834514Smarc 
94934514Smarc 	adder->x_clip_min = left;
95034514Smarc 	adder->x_clip_max = right;
95134514Smarc 	adder->y_clip_min = top;
95234514Smarc 	adder->y_clip_max = bottom;
95334514Smarc 
95434514Smarc 	adder->scroll_x_min = left;
95534514Smarc 	adder->scroll_x_max = right;
95634514Smarc 	adder->scroll_y_min = top;
95734514Smarc 	adder->scroll_y_max = bottom;
95834514Smarc 
95934514Smarc 	wait_status(adder, VSYNC);	/* wait at LEAST 1 full frame */
96034514Smarc 	wait_status(adder, VSYNC);
96134514Smarc 
96234514Smarc 	adder->x_index_pending = left;
96334514Smarc 	adder->y_index_pending = top;
96434514Smarc 	adder->x_index_new = left;
96534514Smarc 	adder->y_index_new = top;
96634514Smarc 	adder->x_index_old = left;
96734514Smarc 	adder->y_index_old = top;
96834514Smarc 
96934514Smarc 	for ( i = 1000, adder->status = 0
97034514Smarc 	    ; i > 0  &&  !((status = adder->status) & ADDRESS_COMPLETE)
97134514Smarc 	    ; --i);
97234514Smarc 
97334514Smarc 	if (i == 0)
97434514Smarc 	    printf("timeout waiting for ADDRESS_COMPLETE bit\n");
97534514Smarc 
97634514Smarc 	write_ID(adder, LEFT_SCROLL_MASK, 0x0000);
97734514Smarc 	write_ID(adder, RIGHT_SCROLL_MASK, 0x0000);
97834514Smarc 
97934514Smarc /*------------------------------------------------------------
98034514Smarc * set source and the mask register to all ones (ie: white) */
98134514Smarc 
98234514Smarc 	write_ID(adder, SOURCE, 0xFFFF);
98334514Smarc 	write_ID(adder, MASK_1, 0xFFFF);
98434514Smarc 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
98534514Smarc 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
98634514Smarc 
98734514Smarc /*--------------------------------------------------------------
98834514Smarc * initialize Operand Control Register banks for fill command */
98934514Smarc 
99034514Smarc 	write_ID(adder, SRC1_OCR_A, EXT_NONE | INT_M1_M2  | NO_ID | WAIT);
99134514Smarc 	write_ID(adder, SRC2_OCR_A, EXT_NONE | INT_SOURCE | NO_ID | NO_WAIT);
99234514Smarc 	write_ID(adder, DST_OCR_A, EXT_NONE | INT_NONE   | NO_ID | NO_WAIT);
99334514Smarc 
99434514Smarc 	write_ID(adder, SRC1_OCR_B, EXT_NONE | INT_SOURCE | NO_ID | WAIT);
99534514Smarc 	write_ID(adder, SRC2_OCR_B, EXT_NONE | INT_M1_M2  | NO_ID | NO_WAIT);
99634514Smarc 	write_ID(adder, DST_OCR_B, EXT_NONE | INT_NONE | NO_ID | NO_WAIT);
99734514Smarc 
99834514Smarc /*------------------------------------------------------------------
99934514Smarc * init Logic Unit Function registers, (these are just common values,
100034514Smarc * and may be changed as required).  */
100134514Smarc 
100234514Smarc 	write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
100334514Smarc 	write_ID(adder, LU_FUNCTION_R2, FULL_SRC_RESOLUTION | LF_SOURCE | INV_M1_M2);
100434514Smarc 	write_ID(adder, LU_FUNCTION_R3, FULL_SRC_RESOLUTION | LF_D_OR_S);
100534514Smarc 	write_ID(adder, LU_FUNCTION_R4, FULL_SRC_RESOLUTION | LF_D_XOR_S);
100634514Smarc 
100734514Smarc /*----------------------------------------
100834514Smarc * load the color map for black & white */
100934514Smarc 
101034514Smarc 	for ( i = 0, adder->status = 0
101134514Smarc 	    ; i < 10000  &&  !((status = adder->status) & VSYNC)
101234514Smarc 	    ; ++i);
101334514Smarc 
101434514Smarc 	if (i == 0)
101534514Smarc 	    printf("timeout waiting for VSYNC bit\n");
101634514Smarc 
101734514Smarc 	red = (short *) qdmap.red;
101834514Smarc 	green = (short *) qdmap.green;
101934514Smarc 	blue = (short *) qdmap.blue;
102034514Smarc 
102134514Smarc 	*red++ = 0x00;			/* black */
102234514Smarc 	*green++ = 0x00;
102334514Smarc 	*blue++ = 0x00;
102434514Smarc 
102534514Smarc 	*red-- = 0xFF;			/* white */
102634514Smarc 	*green-- = 0xFF;
102734514Smarc 	*blue-- = 0xFF;
102834514Smarc 
102934514Smarc 	/*----------------------------------
103034514Smarc 	* set color map for mouse cursor */
103134514Smarc 
103234514Smarc 	red += 254;
103334514Smarc 	green += 254;
103434514Smarc 	blue += 254;
103534514Smarc 
103634514Smarc 	*red++ = 0x00;			/* black */
103734514Smarc 	*green++ = 0x00;
103834514Smarc 	*blue++ = 0x00;
103934514Smarc 
104034514Smarc 	*red = 0xFF;			/* white */
104134514Smarc 	*green = 0xFF;
104234514Smarc 	*blue = 0xFF;
104334514Smarc 
104434514Smarc /*---------------------------------------------------------------------------
104534514Smarc * clear the bitmap a piece at a time.  Since the fast scroll clear only clears
104634514Smarc * the current displayed portion of the bitmap put a temporary value in the y
104734514Smarc * limit register so we can access whole bitmap  */
104834514Smarc 
104934514Smarc 	adder->x_limit = 1024;
105034514Smarc 	adder->y_limit = 2048 - CHAR_HEIGHT;
105134514Smarc 	adder->y_offset_pending = 0;
105234514Smarc 
105334514Smarc 	wait_status(adder, VSYNC);	/* wait at LEAST 1 full frame */
105434514Smarc 	wait_status(adder, VSYNC);
105534514Smarc 
105634514Smarc 	adder->y_scroll_constant = SCROLL_ERASE;
105734514Smarc 
105834514Smarc 	wait_status(adder, VSYNC);
105934514Smarc 	wait_status(adder, VSYNC);
106034514Smarc 
106134514Smarc 	adder->y_offset_pending = 864;
106234514Smarc 
106334514Smarc 	wait_status(adder, VSYNC);
106434514Smarc 	wait_status(adder, VSYNC);
106534514Smarc 
106634514Smarc 	adder->y_scroll_constant = SCROLL_ERASE;
106734514Smarc 
106834514Smarc 	wait_status(adder, VSYNC);
106934514Smarc 	wait_status(adder, VSYNC);
107034514Smarc 
107134514Smarc 	adder->y_offset_pending = 1728;
107234514Smarc 
107334514Smarc 	wait_status(adder, VSYNC);
107434514Smarc 	wait_status(adder, VSYNC);
107534514Smarc 
107634514Smarc 	adder->y_scroll_constant = SCROLL_ERASE;
107734514Smarc 
107834514Smarc 	wait_status(adder, VSYNC);
107934514Smarc 	wait_status(adder, VSYNC);
108034514Smarc 
108134514Smarc 	adder->y_offset_pending = 0;     /* back to normal */
108234514Smarc 
108334514Smarc 	wait_status(adder, VSYNC);
108434514Smarc 	wait_status(adder, VSYNC);
108534514Smarc 
108634514Smarc 	adder->x_limit = MAX_SCREEN_X;
108734514Smarc 	adder->y_limit = MAX_SCREEN_Y + FONT_HEIGHT;
108834514Smarc 
108934514Smarc 	*memcsr = SYNC_ON | UNBLANK;	/* turn off leds and turn on video */
109034514Smarc 	return(0);
109134514Smarc 
109234514Smarc } /* setup_dragon */
109334514Smarc 
109434514Smarc /******************************************************************
109534514Smarc *
109634514Smarc *	setup_input()... init the DUART and set defaults in input
109734514Smarc *			 devices
109834514Smarc *
109934514Smarc ******************************************************************/
110034514Smarc 
110134514Smarc setup_input()
110234514Smarc {
110334514Smarc 	register struct duart *duart;	/* DUART register structure pointer */
110434514Smarc 	register int bits;
110534514Smarc 	int i, j;			/* scratch variables */
110634514Smarc 
110734514Smarc 	short status;
110834514Smarc 
110934514Smarc /*---------------
111034514Smarc * init stuff */
111134514Smarc 
111234514Smarc 	duart = (struct duart *) qdmap.duart;
111334514Smarc 
111434514Smarc /*---------------------------------------------
111534514Smarc * setup the DUART for kbd & pointing device */
111634514Smarc 
111734514Smarc 	duart->cmdA = RESET_M;    /* reset mode reg ptr for kbd */
111834514Smarc 	duart->modeA = 0x13;	  /* 8 bits, no parity, rcv IE, */
111934514Smarc 	 			  /* no RTS control,char error mode */
112034514Smarc 	duart->modeA = 0x07;	  /* 1 stop bit,CTS does not IE XMT */
112134514Smarc 				  /* no RTS control,no echo or loop */
112234514Smarc 	duart->auxctl = 0x00;	  /* baud rate set 1 */
112334514Smarc 
112434514Smarc 	duart->clkselA = 0x99;	  /* 4800 baud for kbd */
112534514Smarc 
112634514Smarc         /* reset everything for keyboard */
112734514Smarc 
112834514Smarc 	for (bits = RESET_M; bits < START_BREAK; bits += 0x10)
112934514Smarc 	    duart->cmdA = bits;
113034514Smarc 
113134514Smarc 	duart->cmdA = EN_RCV | EN_XMT; /* enbl xmt & rcv for kbd */
113234514Smarc 
113334514Smarc /*--------------------------
113434514Smarc * init keyboard defaults */
113534514Smarc /*
113634514Smarc 	for (i = 500; i > 0; --i) {
113734514Smarc     	    if ((status = duart->statusA) & XMT_RDY) {
113834514Smarc         	duart->dataA = LK_DEFAULTS;
113934514Smarc 		break;
114034514Smarc     	    }
114134514Smarc 	}
114234514Smarc 
114334514Smarc 	for (j = 0; j < 3; ++j) {
114434514Smarc 	    for (i = 50000; i > 0; --i) {
114534514Smarc     	        if ((status = duart->statusA) & RCV_RDY) {
114634514Smarc 		    status = duart->dataA;
114734514Smarc 		    break;
114834514Smarc  	        }
114934514Smarc 	    }
115034514Smarc 	}
115134514Smarc 
115234514Smarc 	if (i == 0)
115334514Smarc 	    printf("LK-201 init error\n");
115434514Smarc */
115534514Smarc 
115634514Smarc /*--------
115734514Smarc * exit */
115834514Smarc 
115934514Smarc 	return(0);
116034514Smarc 
116134514Smarc } /* setup_input */
116234514Smarc 
116334514Smarc /**********************************************************************
116434514Smarc *
116534514Smarc *	wait_status()... delay for at least one display frame time
116634514Smarc *
116734514Smarc ***********************************************************************
116834514Smarc *
116934514Smarc *	calling convention:
117034514Smarc *
117134514Smarc *		wait_status(adder, mask);
117234514Smarc *		struct *adder adder;
117334514Smarc *		int mask;
117434514Smarc *
117534514Smarc *	return: BAD means that we timed out without ever seeing the
117634514Smarc *	              vertical sync status bit
117734514Smarc *		GOOD otherwise
117834514Smarc *
117934514Smarc **************/
118034514Smarc 
118134514Smarc wait_status(adder, mask)
118234514Smarc register struct adder *adder;
118334514Smarc register int mask;
118434514Smarc {
118534514Smarc 	register short status;
118634514Smarc 	int i;
118734514Smarc 
118834514Smarc 	for ( i = 10000, adder->status = 0
118934514Smarc 	    ; i > 0  &&  !((status = adder->status) & mask)
119034514Smarc 	    ; --i);
119134514Smarc 
119234514Smarc 	if (i == 0) {
119334514Smarc 	    printf("timeout polling for 0x%x in adder->status\n", mask);
119434514Smarc 	    return(BAD);
119534514Smarc 	}
119634514Smarc 
119734514Smarc 	return(GOOD);
119834514Smarc 
119934514Smarc } /* wait_status */
120034514Smarc 
120134514Smarc /**********************************************************************
120234514Smarc *
120334514Smarc *	write_ID()... write out onto the ID bus
120434514Smarc *
120534514Smarc ***********************************************************************
120634514Smarc *
120734514Smarc *	calling convention:
120834514Smarc *
120934514Smarc *		struct *adder adder;	;pntr to ADDER structure
121034514Smarc *		short adrs;		;VIPER address
121134514Smarc *		short data;		;data to be written
121234514Smarc *		write_ID(adder);
121334514Smarc *
121434514Smarc *	return: BAD means that we timed out waiting for status bits
121534514Smarc *		      VIPER-access-specific status bits
121634514Smarc *		GOOD otherwise
121734514Smarc *
121834514Smarc **************/
121934514Smarc 
122034514Smarc write_ID(adder, adrs, data)
122134514Smarc register struct adder *adder;
122234514Smarc register short adrs;
122334514Smarc register short data;
122434514Smarc {
122534514Smarc 	int i;
122634514Smarc 	short status;
122734514Smarc 
122834514Smarc 	for ( i = 100000, adder->status = 0
122934514Smarc 	    ; i > 0  &&  !((status = adder->status) & ADDRESS_COMPLETE)
123034514Smarc 	    ; --i);
123134514Smarc 
123234514Smarc 	if (i == 0)
123334514Smarc 	    goto ERR;
123434514Smarc 
123534514Smarc 	for ( i = 100000, adder->status = 0
123634514Smarc 	    ; i > 0  &&  !((status = adder->status) & TX_READY)
123734514Smarc 	    ; --i);
123834514Smarc 
123934514Smarc 	if (i > 0) {
124034514Smarc 	    adder->id_data = data;
124134514Smarc 	    adder->command = ID_LOAD | adrs;
124234514Smarc 	    return(GOOD);
124334514Smarc 	}
124434514Smarc 
124534514Smarc ERR:
124634514Smarc 	printf("timeout trying to write to VIPER\n");
124734514Smarc 	return(BAD);
124834514Smarc 
124934514Smarc } /* write_ID */
1250