xref: /original-bsd/sys/vax/stand/qdcons.c (revision 054717d4)
1 /*
2  * Copyright (c) 1988 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)qdcons.c	7.5 (Berkeley) 12/16/90
8  */
9 
10 /*
11  *	derived from: @(#)qdcons.c  4.1 (ULTRIX    11/23/87
12  */
13 
14 /************************************************************************
15 *
16 *	ULTRIX QDSS STANDALONE BOOT DEVICE DRIVER...
17 *	device driver to boot system with QDSS as console
18 *
19 *************************************************************************/
20 /************************************************************************
21 *									*
22 *			Copyright (c) 1985 by				*
23 *		Digital Equipment Corporation, Maynard, MA		*
24 *			All rights reserved.				*
25 *									*
26 *   This software is furnished under a license and may be used and	*
27 *   copied  only  in accordance with the terms of such license and	*
28 *   with the  inclusion  of  the  above  copyright  notice.   This	*
29 *   software  or  any  other copies thereof may not be provided or	*
30 *   otherwise made available to any other person.  No title to and	*
31 *   ownership of the software is hereby transferred.			*
32 *									*
33 *   The information in this software is subject to change  without	*
34 *   notice  and should not be construed as a commitment by Digital	*
35 *   Equipment Corporation.						*
36 *									*
37 *   Digital assumes no responsibility for the use  or  reliability	*
38 *   of its software on equipment which is not supplied by Digital.	*
39 *									*
40 *************************************************************************
41 * revision history: (should be moved into sccs comments)
42 *************************************************************************
43 *
44 * 09 oct 85  longo  added uVAXII console ROM cursor reset to bottom of
45 *		    the screen.  Also spruced up qdputc() & scroll_up()
46 * 02 oct 85  longo  changed references to ADDRESS to be ADDRESS_COMPLETE
47 * 23 aug 85  longo  changed I/O page CSR address to be 0x1F00
48 * 20 aug 85  longo  created
49 *
50 ************************************************************************/
51 
52 #include "sys/types.h"
53 #include "../include/cpu.h"
54 #define KERNEL
55 #include "../uba/qdioctl.h"
56 #include "../uba/qevent.h"
57 #include "../uba/qduser.h"
58 #include "../uba/qdreg.h"
59 #undef KERNEL
60 
61 /*-----------------------------------------------------------------------
62 * constants used to set VAX ROM's cursor to bottom the of the screen  */
63 
64 #define NVR_ADRS	0x200B8024
65 
66 #define CURRENT_ROW	0x4C	/* these are offsets to the ROM's scratch.. */
67 #define ROW_MIN		0x4D    /* ..RAM start adrs as picked up out of NVR */
68 #define ROW_MAX		0x4E
69 #define CURRENT_COL	0x50
70 #define COL_MIN		0x51
71 #define COL_MAX		0x52
72 
73 /*----------------------------------------
74 * LK201 keyboard state tracking struct */
75 
76 	struct q_keyboard {
77 
78 	    int shift;			/* state variables	*/
79 	    int cntrl;
80 	    int lock;
81 	    char last;			/* last character	*/
82 
83 	 } q_keyboard;
84 
85 	int qdputc(), qdgetc();
86 
87 	extern (*v_putc)(),(*v_getc)();
88 
89 /*----------------------------
90 * general purpose defines  */
91 
92 #define BAD	-1
93 #define GOOD	0
94 
95 /*----------------------------------------------
96 * console cursor bitmap (block cursor type)  */
97 
98 	short cons_cursor[32] = {      /* white block cursor */
99 
100  /* A */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
101  	 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
102  /* B */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF,
103          0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF
104 
105 	};
106 
107 /*-------------------------------------
108 * constants used in font operations */
109 
110 #define CHARS		95			/* # of chars in the font */
111 #define CHAR_HEIGHT	15			/* char height in pixels */
112 #define CHAR_WIDTH	8			/* char width in pixels*/
113 #define FONT_WIDTH	(CHAR_WIDTH * CHARS)    /* font width in pixels */
114 #define ROWS  		CHAR_HEIGHT
115 
116 #define FONT_X		0			/* font's off screen adrs */
117 #define FONT_Y		(2047 - CHAR_HEIGHT)
118 /*
119 #define FONT_Y		200
120 */
121 
122 	extern char q_font[];		/* reference font object code */
123 
124 	extern  char q_key[];		/* reference key xlation tables */
125 	extern  char q_shift_key[];
126 	extern  char *q_special[];
127 
128 /*----------------------------
129 * console cursor structure */
130 
131 	struct cons_cur {
132 	    int x;
133 	    int y;
134 	} cursor;
135 
136 /*------------------------------------------
137 * MicroVAX-II q-bus addressing constants */
138 
139 #define QMEMBASE 0x30000000
140 #define QDSSCSR  0x20001F00
141 
142 #define CHUNK     (64 * 1024)
143 #define QMEMSIZE  (1024 * 1024 * 4)
144 #define	QDBASE    (QMEMBASE + QMEMSIZE - CHUNK)
145 
146 /*------------------------------------------------------------------
147 * QDSS register address offsets from start of QDSS address space */
148 
149 #define QDSIZE 	 (52 * 1024)	/* size of entire QDSS foot print */
150 
151 #define TMPSIZE  (16 * 1024)	/* template RAM is 8k SHORT WORDS */
152 #define TMPSTART 0x8000		/* offset of template RAM from base adrs */
153 
154 #define REGSIZE	 (5 * 512)	/* regs touch 2.5k (5 pages) of addr space */
155 #define REGSTART 0xC000		/* offset of reg pages from base adrs */
156 
157 #define ADDER	(REGSTART+0x000)
158 #define DGA	(REGSTART+0x200)
159 #define DUART	(REGSTART+0x400)
160 #define MEMCSR  (REGSTART+0x800)
161 
162 #define	CLRSIZE  (3 * 512)		/* color map size */
163 #define CLRSTART (REGSTART+0xA00)	/* color map start offset from base */
164 					/*  0x0C00 really */
165 #define RED	(CLRSTART+0x000)
166 #define BLUE	(CLRSTART+0x200)
167 #define GREEN	(CLRSTART+0x400)
168 
169 /*---------------------------------------
170 * QDSS register address map structure */
171 
172 	struct qdmap qdmap;
173 
174 /************************************************************************
175 *************************************************************************
176 *************************************************************************
177 *
178 *	EXTERNALLY CALLED ROUTINES START HERE:
179 *
180 *************************************************************************
181 *************************************************************************
182 ************************************************************************/
183 
184 /************************************************************************
185 *
186 *	qd_init()... init the QDSS into a physical memory system
187 *
188 ************************************************************************/
189 
190 qd_init()
191 {
192 	register char *ROM_console;
193 	register short *NVR;
194 	register int i;
195 
196 	caddr_t qdaddr;
197 	struct dga *dga;
198 	extern int cpu;
199 
200  	qdaddr = (caddr_t) QDSSCSR;
201         if (badaddr(qdaddr, sizeof(short)))
202             return(0);
203 
204 	*(short *)qdaddr = (short) (QDBASE >> 16);
205 
206 /*----------------------------------------------------------------------
207 * load qdmap struct with the physical addresses of the QDSS elements */
208 
209 	qdmap.template = (caddr_t) QDBASE + TMPSTART;
210 	qdmap.adder = (caddr_t) QDBASE + ADDER;
211 	qdmap.dga = (caddr_t) QDBASE + DGA;
212 	qdmap.duart = (caddr_t) QDBASE + DUART;
213 	qdmap.memcsr = (caddr_t) QDBASE + MEMCSR;
214 	qdmap.red = (caddr_t) QDBASE + RED;
215 	qdmap.blue = (caddr_t) QDBASE + BLUE;
216 	qdmap.green = (caddr_t) QDBASE + GREEN;
217 
218 /*--------------------------
219 * no interrupts allowed! */
220 
221 	dga = (struct dga *) qdmap.dga;
222 	dga->csr = HALT;
223 	dga->csr |= CURS_ENB;
224 
225 /*----------------------------
226 * init the default values  */
227 
228 	q_keyboard.shift = 0;		/* init keyboard state tracking */
229 	q_keyboard.lock = 0;
230 	q_keyboard.cntrl = 0;
231 	q_keyboard.last = 0;
232 
233 	cursor.x = 0;			/* init cursor to top left */
234 	cursor.y = 0;
235 
236 	set_defaults();		        /* setup the default device */
237 	ldfont();			/* PtoB the font into off-screen */
238 
239 /*--------------------------------------------------------------------
240 * tell the VAX ROM that the cursor is at the bottom of the screen  */
241 
242 	if (cpu == VAX_630) {
243 		NVR = (short *) NVR_ADRS;
244 
245 		i = *NVR++ & 0xFF;
246 		i |= (*NVR++ & 0xFF) << 8;
247 		i |= (*NVR++ & 0xFF) << 16;
248 		i |= (*NVR++ & 0xFF) << 24;
249 
250 		ROM_console = (char *) i;
251 
252 		ROM_console[CURRENT_COL] = ROM_console[COL_MIN];
253 		ROM_console[CURRENT_ROW] = ROM_console[ROW_MAX];
254 	}
255 
256 /*----------------------------------------------------------
257 * smash system virtual console service routine addresses */
258 
259 	printf("switching console to QDSS display...\n");
260 	v_getc = qdgetc;
261 	v_putc = qdputc;
262 
263 	return(1);
264 
265 } /* qd_init */
266 
267 /*******************************************************************
268 *
269 *	qdputc()... output a character to the QDSS screen
270 *
271 ********************************************************************
272 *
273 *	calling convention:
274 *
275 *		qdputc(chr);
276 *		char chr; 		;character to be displayed
277 *
278 ********/
279 
280 qdputc(chr)
281 char chr;
282 {
283 	register struct adder *adder;
284 	register struct dga *dga;
285 	register int i;
286 
287 	short x;
288 
289 	adder = (struct adder *) qdmap.adder;
290 	dga = (struct dga *) qdmap.dga;
291 
292 /*---------------------------
293 * non display character?  */
294 
295 	chr &= 0x7F;
296 
297 	switch (chr) {
298 
299 	    case '\r':			/* return char */
300 	        cursor.x = 0;
301 		dga->x_cursor = TRANX(cursor.x);
302 	    	return(0);
303 
304 	    case '\t':			/* tab char */
305 
306 	    	for (i = 8 - ((cursor.x >> 3) & 0x07); i > 0; --i) {
307 	    	    qdputc(' ');
308 		}
309 		return(0);
310 
311 	    case '\n':			/* line feed char */
312 
313 	        if ((cursor.y += CHAR_HEIGHT) > (863 - CHAR_HEIGHT)) {
314 		    cursor.y -= CHAR_HEIGHT;
315 		    scroll_up(adder);
316 		}
317 		dga->y_cursor = TRANY(cursor.y);
318 		return(0);
319 
320 	    case '\b':			/* backspace char */
321 	        if (cursor.x > 0) {
322 	    	    cursor.x -= CHAR_WIDTH;
323 		    qdputc(' ');
324 		    cursor.x -= CHAR_WIDTH;
325 		    dga->x_cursor = TRANX(cursor.x);
326 		}
327 		return(0);
328 
329 	    default:
330 		if (chr < ' ' || chr > '~') {
331 		    return(0);
332 		}
333 	}
334 
335 /*------------------------------------------
336 * setup VIPER operand control registers  */
337 
338 	write_ID(adder, CS_UPDATE_MASK, 0x0001);  /* select plane #0 */
339 	write_ID(adder, SRC1_OCR_B,
340 			EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY);
341 
342 	write_ID(adder, CS_UPDATE_MASK, 0x00FE);  /* select other planes */
343 	write_ID(adder, SRC1_OCR_B,
344 			EXT_SOURCE | INT_NONE | NO_ID | BAR_SHIFT_DELAY);
345 
346 	write_ID(adder, CS_UPDATE_MASK, 0x00FF);  /* select all planes */
347 	write_ID(adder, DST_OCR_B,
348 			EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
349 
350 	write_ID(adder, MASK_1, 0xFFFF);
351 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 1);
352 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
353 
354 /*----------------------------------------
355 * load DESTINATION origin and vectors  */
356 
357 	adder->fast_dest_dy = 0;
358 	adder->slow_dest_dx = 0;
359 	adder->error_1 = 0;
360 	adder->error_2 = 0;
361 
362 	adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL;
363 
364 	wait_status(adder, RASTEROP_COMPLETE);
365 
366 	adder->destination_x = cursor.x;
367 	adder->fast_dest_dx = CHAR_WIDTH;
368 
369 	adder->destination_y = cursor.y;
370 	adder->slow_dest_dy = CHAR_HEIGHT;
371 
372 /*-----------------------------------
373 * load SOURCE origin and vectors  */
374 
375 	adder->source_1_x = FONT_X + ((chr - ' ') * CHAR_WIDTH);
376 	adder->source_1_y = FONT_Y;
377 
378 	adder->source_1_dx = CHAR_WIDTH;
379 	adder->source_1_dy = CHAR_HEIGHT;
380 
381 	write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
382 	adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE;
383 
384 /*-------------------------------------
385 * update console cursor coordinates */
386 
387 	cursor.x += CHAR_WIDTH;
388 	dga->x_cursor = TRANX(cursor.x);
389 
390         if (cursor.x > (1024 - CHAR_WIDTH)) {
391 	    qdputc('\r');
392 	    qdputc('\n');
393 	}
394 
395 } /* qdputc */
396 
397 /*******************************************************************
398 *
399 *	qdgetc()... get a character from the LK201
400 *
401 *******************************************************************/
402 
403 qdgetc()
404 {
405 	register short key;
406 	register char chr;
407 	register struct duart *duart;
408 
409 	u_int status;
410 
411 	duart = (struct duart *) qdmap.duart;
412 
413 	/*--------------------------------------
414 	* Get a character from the keyboard. */
415 
416 LOOP:
417 	while (!((status = duart->statusA) & RCV_RDY))
418 			;
419 
420 	key = duart->dataA;
421 	key &= 0xFF;
422 
423 	/*--------------------------------------
424 	* Check for various keyboard errors  */
425 
426 	if( key == LK_POWER_ERROR || key == LK_KDOWN_ERROR ||
427 	    key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) {
428 		printf("Keyboard error, code = %x\n", key);
429 		return(0);
430 	}
431 
432 	if (key < LK_LOWEST)
433 	    return(0);
434 
435 	/*---------------------------------
436 	* See if its a state change key */
437 
438 	switch (key) {
439 
440 	    case LOCK:
441 		q_keyboard.lock ^= 0xffff;	/* toggle */
442 		if (q_keyboard.lock)
443 		    led_control(LK_LED_ENABLE, LK_LED_LOCK);
444 		else
445 		    led_control(LK_LED_DISABLE, LK_LED_LOCK);
446 		goto LOOP;
447 
448 	    case SHIFT:
449 		q_keyboard.shift ^= 0xFFFF;
450 		goto LOOP;
451 
452 	    case CNTRL:
453 		q_keyboard.cntrl ^= 0xFFFF;
454 		goto LOOP;
455 
456 	    case ALLUP:
457 		q_keyboard.cntrl = 0;
458 		q_keyboard.shift = 0;
459 		goto LOOP;
460 
461 	    case REPEAT:
462 		chr = q_keyboard.last;
463 		break;
464 
465 	    /*-------------------------------------------------------
466 	    * Test for cntrl characters. If set, see if the character
467 	    * is elligible to become a control character. */
468 
469 	    default:
470 
471 		if (q_keyboard.cntrl) {
472 		    chr = q_key[key];
473 		    if (chr >= ' ' && chr <= '~')
474 			chr &= 0x1F;
475 		}
476 		else if ( q_keyboard.lock || q_keyboard.shift )
477 		    chr = q_shift_key[key];
478 		else
479 		    chr = q_key[key];
480 		break;
481 	}
482 
483 	if (chr < ' ' && chr > '~')  	/* if input is non-displayable */
484 	    return(0);			/* ..then pitch it! */
485 
486 	q_keyboard.last = chr;
487 
488 	/*-----------------------------------
489 	* Check for special function keys */
490 
491 	if (chr & 0x80) 		/* pitch the function keys */
492 	    return(0);
493 	else
494 	    return(chr);
495 
496 } /* qdgetc */
497 
498 /************************************************************************
499 *************************************************************************
500 *************************************************************************
501 *
502 *	INTERNALLY USED ROUTINES START HERE:
503 *
504 *************************************************************************
505 *************************************************************************
506 ************************************************************************/
507 
508 /********************************************************************
509 *
510 *	ldcursor()... load the mouse cursor's template RAM bitmap
511 *
512 ********************************************************************/
513 
514 ldcursor()
515 {
516 	register struct dga *dga;
517 	register short *temp;
518 	register int i;
519 
520 	int cursor;
521 
522 	dga = (struct dga *) qdmap.dga;
523 	temp = (short *) qdmap.template;
524 
525 	temp += (8 * 1024) - 32;	/* cursor is 32 WORDS from the end */
526 					/* ..of the 8k WORD template space */
527 	for (i = 0; i < 32; ++i)
528 	    *temp++ = cons_cursor[i];
529 
530 	return(0);
531 
532 } /* ldcursor */
533 
534 /**********************************************************************
535 *
536 *	ldfont()... put the console font in the QDSS off-screen memory
537 *
538 **********************************************************************/
539 
540 ldfont()
541 {
542 	register struct adder *adder;
543 
544 	int i;		/* scratch variables */
545 	int j;
546 	int k;
547 	short packed;
548 
549 	adder = (struct adder *) qdmap.adder;
550 
551 /*------------------------------------------
552 * setup VIPER operand control registers  */
553 
554 	write_ID(adder, MASK_1, 0xFFFF);
555 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
556 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
557 
558 	write_ID(adder, SRC1_OCR_B,
559 			EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY);
560 	write_ID(adder, SRC2_OCR_B,
561 			EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY);
562 	write_ID(adder, DST_OCR_B,
563 			EXT_SOURCE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
564 
565 	adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL;
566 
567 /*--------------------------
568 * load destination data  */
569 
570 	wait_status(adder, RASTEROP_COMPLETE);
571 
572 	adder->destination_x = FONT_X;
573 	adder->destination_y = FONT_Y;
574 	adder->fast_dest_dx = FONT_WIDTH;
575 	adder->slow_dest_dy = CHAR_HEIGHT;
576 
577 /*---------------------------------------
578 * setup for processor to bitmap xfer  */
579 
580 	write_ID(adder, CS_UPDATE_MASK, 0x0001);
581 	adder->cmd = PBT | OCRB | 2 | DTE | 2;
582 
583 /*-----------------------------------------------
584 * iteratively do the processor to bitmap xfer */
585 
586 	for (i = 0; i < ROWS; ++i) {
587 
588 	    /* PTOB a scan line */
589 
590 	    for (j = 0, k = i; j < 48; ++j) {
591 
592 	        /* PTOB one scan of a char cell */
593 
594 		packed = q_font[k];
595 		k += ROWS;
596 		packed |= ((short)q_font[k] << 8);
597 		k += ROWS;
598 
599 	        wait_status(adder, TX_READY);
600 	        adder->id_data = packed;
601 	    }
602 	}
603 
604 }  /* ldfont */
605 
606 /*********************************************************************
607 *
608 *	led_control()... twiddle LK-201 LED's
609 *
610 **********************************************************************
611 *
612 *	led_control(cmd, led_mask);
613 *	int cmd;	LED enable/disable command
614 *	int led_mask;	which LED(s) to twiddle
615 *
616 *************/
617 
618 led_control(cmd, led_mask)
619 int cmd;
620 int led_mask;
621 {
622 	register int i;
623 	register int status;
624 	register struct duart *duart;
625 
626 	duart = (struct duart *) qdmap.duart;
627 
628 	for (i = 1000; i > 0; --i) {
629     	    if ((status = duart->statusA) & XMT_RDY) {
630         	duart->dataA = cmd;
631 		break;
632     	    }
633 	}
634 
635 	for (i = 1000; i > 0; --i) {
636     	    if ((status = duart->statusA) & XMT_RDY) {
637         	duart->dataA = led_mask;
638 		break;
639     	    }
640 	}
641 
642 	if (i == 0)
643 	    return(BAD);
644 
645 	return(GOOD);
646 
647 } /* led_control */
648 
649 /*******************************************************************
650 *
651 *	scroll_up()... move the screen up one character height
652 *
653 ********************************************************************
654 *
655 *	calling convention:
656 *
657 *		scroll_up(adder);
658 *		struct adder *adder;    ;address of adder
659 *
660 ********/
661 
662 scroll_up(adder)
663 register struct adder *adder;
664 {
665 
666 /*------------------------------------------
667 * setup VIPER operand control registers  */
668 
669 	wait_status(adder, ADDRESS_COMPLETE);
670 
671 	write_ID(adder, CS_UPDATE_MASK, 0x00FF);  /* select all planes */
672 
673 	write_ID(adder, MASK_1, 0xFFFF);
674 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
675 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
676 
677 	write_ID(adder, SRC1_OCR_B,
678 			EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY);
679 	write_ID(adder, DST_OCR_B,
680 			EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY);
681 
682 /*----------------------------------------
683 * load DESTINATION origin and vectors  */
684 
685 	adder->fast_dest_dy = 0;
686 	adder->slow_dest_dx = 0;
687 	adder->error_1 = 0;
688 	adder->error_2 = 0;
689 
690 	adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL;
691 
692 	adder->destination_x = 0;
693 	adder->fast_dest_dx = 1024;
694 
695 	adder->destination_y = 0;
696 	adder->slow_dest_dy = 864 - CHAR_HEIGHT;
697 
698 /*-----------------------------------
699 * load SOURCE origin and vectors  */
700 
701 	adder->source_1_x = 0;
702 	adder->source_1_dx = 1024;
703 
704 	adder->source_1_y = 0 + CHAR_HEIGHT;
705 	adder->source_1_dy = 864 - CHAR_HEIGHT;
706 
707 	write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
708 	adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE;
709 
710 /*--------------------------------------------
711 * do a rectangle clear of last screen line */
712 
713 	write_ID(adder, MASK_1, 0xffff);
714 	write_ID(adder, SOURCE, 0xffff);
715 	write_ID(adder,DST_OCR_B,
716 	  	(EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY));
717 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 0);
718 	adder->error_1 = 0;
719 	adder->error_2 = 0;
720 	adder->slow_dest_dx = 0;	/* set up the width of	*/
721 	adder->slow_dest_dy = CHAR_HEIGHT;	/* rectangle */
722 
723 	adder->rasterop_mode = (NORMAL | DST_WRITE_ENABLE) ;
724 	wait_status(adder, RASTEROP_COMPLETE);
725 	adder->destination_x = 0;
726 	adder->destination_y = 864 - CHAR_HEIGHT;
727 
728 	adder->fast_dest_dx = 1024;	/* set up the height	*/
729 	adder->fast_dest_dy = 0;	/* of rectangle		*/
730 
731 	write_ID(adder, LU_FUNCTION_R2, (FULL_SRC_RESOLUTION | LF_SOURCE));
732 	adder->cmd = (RASTEROP | OCRB | LF_R2 | DTE ) ;
733 
734 } /* scroll_up */
735 
736 /**********************************************************************
737 *
738 *	set_defaults()... init the QDSS device and driver defaults
739 *
740 **********************************************************************/
741 
742 set_defaults()
743 {
744 	setup_input();		/* init the DUART */
745 	setup_dragon();		/* init the ADDER/VIPER stuff */
746 	ldcursor();		/* load default cursor map */
747 
748 } /* set_defaults */
749 
750 /*********************************************************************
751 *
752 *	setup_dragon()... init the ADDER, VIPER, bitmaps, & color map
753 *
754 *********************************************************************/
755 
756 setup_dragon()
757 {
758 
759 	register struct adder *adder;
760 	register struct dga *dga;
761 	short *memcsr;
762 
763 	int i;			/* general purpose variables */
764 	int status;
765 
766 	short top;		/* clipping/scrolling boundaries */
767 	short bottom;
768 	short right;
769 	short left;
770 
771 	short *red;		/* color map pointers */
772 	short *green;
773 	short *blue;
774 
775 /*------------------
776 * init for setup */
777 
778 	adder = (struct adder *) qdmap.adder;
779 	dga = (struct dga *) qdmap.dga;
780 	memcsr = (short *) qdmap.memcsr;
781 
782 	*memcsr = SYNC_ON;		/* blank screen and turn off LED's */
783 	adder->command = CANCEL;
784 
785 /*----------------------
786 * set monitor timing */
787 
788 	adder->x_scan_count_0 = 0x2800;
789 	adder->x_scan_count_1 = 0x1020;
790 	adder->x_scan_count_2 = 0x003A;
791 	adder->x_scan_count_3 = 0x38F0;
792 	adder->x_scan_count_4 = 0x6128;
793 	adder->x_scan_count_5 = 0x093A;
794 	adder->x_scan_count_6 = 0x313C;
795 	adder->sync_phase_adj = 0x0100;
796 	adder->x_scan_conf = 0x00C8;
797 
798 /*---------------------------------------------------------
799 * got a bug in secound pass ADDER! lets take care of it */
800 
801 	/* normally, just use the code in the following bug fix code, but to
802 	* make repeated demos look pretty, load the registers as if there was
803 	* no bug and then test to see if we are getting sync */
804 
805 	adder->y_scan_count_0 = 0x135F;
806 	adder->y_scan_count_1 = 0x3363;
807 	adder->y_scan_count_2 = 0x2366;
808 	adder->y_scan_count_3 = 0x0388;
809 
810 	/* if no sync, do the bug fix code */
811 
812 	if (wait_status(adder, VSYNC) == BAD) {
813 
814 	    /* first load all Y scan registers with very short frame and
815 	    * wait for scroll service.  This guarantees at least one SYNC
816 	    * to fix the pass 2 Adder initialization bug (synchronizes
817 	    * XCINCH with DMSEEDH) */
818 
819 	    adder->y_scan_count_0 = 0x01;
820 	    adder->y_scan_count_1 = 0x01;
821 	    adder->y_scan_count_2 = 0x01;
822 	    adder->y_scan_count_3 = 0x01;
823 
824 	    wait_status(adder, VSYNC);	/* delay at least 1 full frame time */
825 	    wait_status(adder, VSYNC);
826 
827 	    /* now load the REAL sync values (in reverse order just to
828 	    *  be safe.  */
829 
830 	    adder->y_scan_count_3 = 0x0388;
831 	    adder->y_scan_count_2 = 0x2366;
832 	    adder->y_scan_count_1 = 0x3363;
833 	    adder->y_scan_count_0 = 0x135F;
834   	}
835 
836 /*----------------------------
837 * zero the index registers */
838 
839 	adder->x_index_pending = 0;
840 	adder->y_index_pending = 0;
841 	adder->x_index_new = 0;
842 	adder->y_index_new = 0;
843 	adder->x_index_old = 0;
844 	adder->y_index_old = 0;
845 
846 	adder->pause = 0;
847 
848 /*----------------------------------------
849 * set rasterop mode to normal pen down */
850 
851 	adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL;
852 
853 /*--------------------------------------------------
854 * set the rasterop registers to a default values */
855 
856 	adder->source_1_dx = 1;
857 	adder->source_1_dy = 1;
858 	adder->source_1_x = 0;
859 	adder->source_1_y = 0;
860 	adder->destination_x = 0;
861 	adder->destination_y = 0;
862 	adder->fast_dest_dx = 1;
863 	adder->fast_dest_dy = 0;
864 	adder->slow_dest_dx = 0;
865 	adder->slow_dest_dy = 1;
866    	adder->error_1 = 0;
867 	adder->error_2 = 0;
868 
869 /*------------------------
870 * scale factor = unity */
871 
872 	adder->fast_scale = UNITY;
873 	adder->slow_scale = UNITY;
874 
875 /*-------------------------------
876 * set the source 2 parameters */
877 
878 	adder->source_2_x = 0;
879 	adder->source_2_y = 0;
880 	adder->source_2_size = 0x0022;
881 
882 /*-----------------------------------------------
883 * initialize plane addresses for eight vipers */
884 
885 	write_ID(adder, CS_UPDATE_MASK, 0x0001);
886 	write_ID(adder, PLANE_ADDRESS, 0x0000);
887 
888 	write_ID(adder, CS_UPDATE_MASK, 0x0002);
889 	write_ID(adder, PLANE_ADDRESS, 0x0001);
890 
891 	write_ID(adder, CS_UPDATE_MASK, 0x0004);
892 	write_ID(adder, PLANE_ADDRESS, 0x0002);
893 
894 	write_ID(adder, CS_UPDATE_MASK, 0x0008);
895 	write_ID(adder, PLANE_ADDRESS, 0x0003);
896 
897 	write_ID(adder, CS_UPDATE_MASK, 0x0010);
898 	write_ID(adder, PLANE_ADDRESS, 0x0004);
899 
900 	write_ID(adder, CS_UPDATE_MASK, 0x0020);
901 	write_ID(adder, PLANE_ADDRESS, 0x0005);
902 
903 	write_ID(adder, CS_UPDATE_MASK, 0x0040);
904 	write_ID(adder, PLANE_ADDRESS, 0x0006);
905 
906 	write_ID(adder, CS_UPDATE_MASK, 0x0080);
907 	write_ID(adder, PLANE_ADDRESS, 0x0007);
908 
909 	/* initialize the external registers. */
910 
911 	write_ID(adder, CS_UPDATE_MASK, 0x00FF);
912 	write_ID(adder, CS_SCROLL_MASK, 0x00FF);
913 
914 	/* initialize resolution mode */
915 
916 	write_ID(adder, MEMORY_BUS_WIDTH, 0x000C);     /* bus width = 16 */
917 	write_ID(adder, RESOLUTION_MODE, 0x0000);      /* one bit/pixel */
918 
919 	/* initialize viper registers */
920 
921 	write_ID(adder, SCROLL_CONSTANT, SCROLL_ENABLE|VIPER_LEFT|VIPER_UP);
922 	write_ID(adder, SCROLL_FILL, 0x0000);
923 
924 /*----------------------------------------------------
925 * set clipping and scrolling limits to full screen */
926 
927 	for ( i = 1000, adder->status = 0
928 	    ; i > 0  &&  !((status = adder->status) & ADDRESS_COMPLETE)
929 	    ; --i);
930 
931 	if (i == 0)
932 	    printf("timeout trying to setup clipping\n");
933 
934 	top = 0;
935 	bottom = 2048;
936 	left = 0;
937 	right = 1024;
938 
939 	adder->x_clip_min = left;
940 	adder->x_clip_max = right;
941 	adder->y_clip_min = top;
942 	adder->y_clip_max = bottom;
943 
944 	adder->scroll_x_min = left;
945 	adder->scroll_x_max = right;
946 	adder->scroll_y_min = top;
947 	adder->scroll_y_max = bottom;
948 
949 	wait_status(adder, VSYNC);	/* wait at LEAST 1 full frame */
950 	wait_status(adder, VSYNC);
951 
952 	adder->x_index_pending = left;
953 	adder->y_index_pending = top;
954 	adder->x_index_new = left;
955 	adder->y_index_new = top;
956 	adder->x_index_old = left;
957 	adder->y_index_old = top;
958 
959 	for ( i = 1000, adder->status = 0
960 	    ; i > 0  &&  !((status = adder->status) & ADDRESS_COMPLETE)
961 	    ; --i);
962 
963 	if (i == 0)
964 	    printf("timeout waiting for ADDRESS_COMPLETE bit\n");
965 
966 	write_ID(adder, LEFT_SCROLL_MASK, 0x0000);
967 	write_ID(adder, RIGHT_SCROLL_MASK, 0x0000);
968 
969 /*------------------------------------------------------------
970 * set source and the mask register to all ones (ie: white) */
971 
972 	write_ID(adder, SOURCE, 0xFFFF);
973 	write_ID(adder, MASK_1, 0xFFFF);
974 	write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255);
975 	write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0);
976 
977 /*--------------------------------------------------------------
978 * initialize Operand Control Register banks for fill command */
979 
980 	write_ID(adder, SRC1_OCR_A, EXT_NONE | INT_M1_M2  | NO_ID | WAIT);
981 	write_ID(adder, SRC2_OCR_A, EXT_NONE | INT_SOURCE | NO_ID | NO_WAIT);
982 	write_ID(adder, DST_OCR_A, EXT_NONE | INT_NONE   | NO_ID | NO_WAIT);
983 
984 	write_ID(adder, SRC1_OCR_B, EXT_NONE | INT_SOURCE | NO_ID | WAIT);
985 	write_ID(adder, SRC2_OCR_B, EXT_NONE | INT_M1_M2  | NO_ID | NO_WAIT);
986 	write_ID(adder, DST_OCR_B, EXT_NONE | INT_NONE | NO_ID | NO_WAIT);
987 
988 /*------------------------------------------------------------------
989 * init Logic Unit Function registers, (these are just common values,
990 * and may be changed as required).  */
991 
992 	write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE);
993 	write_ID(adder, LU_FUNCTION_R2, FULL_SRC_RESOLUTION | LF_SOURCE | INV_M1_M2);
994 	write_ID(adder, LU_FUNCTION_R3, FULL_SRC_RESOLUTION | LF_D_OR_S);
995 	write_ID(adder, LU_FUNCTION_R4, FULL_SRC_RESOLUTION | LF_D_XOR_S);
996 
997 /*----------------------------------------
998 * load the color map for black & white */
999 
1000 	for ( i = 0, adder->status = 0
1001 	    ; i < 10000  &&  !((status = adder->status) & VSYNC)
1002 	    ; ++i);
1003 
1004 	if (i == 0)
1005 	    printf("timeout waiting for VSYNC bit\n");
1006 
1007 	red = (short *) qdmap.red;
1008 	green = (short *) qdmap.green;
1009 	blue = (short *) qdmap.blue;
1010 
1011 	*red++ = 0x00;			/* black */
1012 	*green++ = 0x00;
1013 	*blue++ = 0x00;
1014 
1015 	*red-- = 0xFF;			/* white */
1016 	*green-- = 0xFF;
1017 	*blue-- = 0xFF;
1018 
1019 	/*----------------------------------
1020 	* set color map for mouse cursor */
1021 
1022 	red += 254;
1023 	green += 254;
1024 	blue += 254;
1025 
1026 	*red++ = 0x00;			/* black */
1027 	*green++ = 0x00;
1028 	*blue++ = 0x00;
1029 
1030 	*red = 0xFF;			/* white */
1031 	*green = 0xFF;
1032 	*blue = 0xFF;
1033 
1034 /*---------------------------------------------------------------------------
1035 * clear the bitmap a piece at a time.  Since the fast scroll clear only clears
1036 * the current displayed portion of the bitmap put a temporary value in the y
1037 * limit register so we can access whole bitmap  */
1038 
1039 	adder->x_limit = 1024;
1040 	adder->y_limit = 2048 - CHAR_HEIGHT;
1041 	adder->y_offset_pending = 0;
1042 
1043 	wait_status(adder, VSYNC);	/* wait at LEAST 1 full frame */
1044 	wait_status(adder, VSYNC);
1045 
1046 	adder->y_scroll_constant = SCROLL_ERASE;
1047 
1048 	wait_status(adder, VSYNC);
1049 	wait_status(adder, VSYNC);
1050 
1051 	adder->y_offset_pending = 864;
1052 
1053 	wait_status(adder, VSYNC);
1054 	wait_status(adder, VSYNC);
1055 
1056 	adder->y_scroll_constant = SCROLL_ERASE;
1057 
1058 	wait_status(adder, VSYNC);
1059 	wait_status(adder, VSYNC);
1060 
1061 	adder->y_offset_pending = 1728;
1062 
1063 	wait_status(adder, VSYNC);
1064 	wait_status(adder, VSYNC);
1065 
1066 	adder->y_scroll_constant = SCROLL_ERASE;
1067 
1068 	wait_status(adder, VSYNC);
1069 	wait_status(adder, VSYNC);
1070 
1071 	adder->y_offset_pending = 0;     /* back to normal */
1072 
1073 	wait_status(adder, VSYNC);
1074 	wait_status(adder, VSYNC);
1075 
1076 	adder->x_limit = MAX_SCREEN_X;
1077 	adder->y_limit = MAX_SCREEN_Y + FONT_HEIGHT;
1078 
1079 	*memcsr = SYNC_ON | UNBLANK;	/* turn off leds and turn on video */
1080 	return(0);
1081 
1082 } /* setup_dragon */
1083 
1084 /******************************************************************
1085 *
1086 *	setup_input()... init the DUART and set defaults in input
1087 *			 devices
1088 *
1089 ******************************************************************/
1090 
1091 setup_input()
1092 {
1093 	register struct duart *duart;	/* DUART register structure pointer */
1094 	register int bits;
1095 	int i, j;			/* scratch variables */
1096 
1097 	short status;
1098 
1099 /*---------------
1100 * init stuff */
1101 
1102 	duart = (struct duart *) qdmap.duart;
1103 
1104 /*---------------------------------------------
1105 * setup the DUART for kbd & pointing device */
1106 
1107 	duart->cmdA = RESET_M;    /* reset mode reg ptr for kbd */
1108 	duart->modeA = 0x13;	  /* 8 bits, no parity, rcv IE, */
1109 	 			  /* no RTS control,char error mode */
1110 	duart->modeA = 0x07;	  /* 1 stop bit,CTS does not IE XMT */
1111 				  /* no RTS control,no echo or loop */
1112 	duart->auxctl = 0x00;	  /* baud rate set 1 */
1113 
1114 	duart->clkselA = 0x99;	  /* 4800 baud for kbd */
1115 
1116         /* reset everything for keyboard */
1117 
1118 	for (bits = RESET_M; bits < START_BREAK; bits += 0x10)
1119 	    duart->cmdA = bits;
1120 
1121 	duart->cmdA = EN_RCV | EN_XMT; /* enbl xmt & rcv for kbd */
1122 
1123 /*--------------------------
1124 * init keyboard defaults */
1125 /*
1126 	for (i = 500; i > 0; --i) {
1127     	    if ((status = duart->statusA) & XMT_RDY) {
1128         	duart->dataA = LK_DEFAULTS;
1129 		break;
1130     	    }
1131 	}
1132 
1133 	for (j = 0; j < 3; ++j) {
1134 	    for (i = 50000; i > 0; --i) {
1135     	        if ((status = duart->statusA) & RCV_RDY) {
1136 		    status = duart->dataA;
1137 		    break;
1138  	        }
1139 	    }
1140 	}
1141 
1142 	if (i == 0)
1143 	    printf("LK-201 init error\n");
1144 */
1145 
1146 /*--------
1147 * exit */
1148 
1149 	return(0);
1150 
1151 } /* setup_input */
1152 
1153 /**********************************************************************
1154 *
1155 *	wait_status()... delay for at least one display frame time
1156 *
1157 ***********************************************************************
1158 *
1159 *	calling convention:
1160 *
1161 *		wait_status(adder, mask);
1162 *		struct *adder adder;
1163 *		int mask;
1164 *
1165 *	return: BAD means that we timed out without ever seeing the
1166 *	              vertical sync status bit
1167 *		GOOD otherwise
1168 *
1169 **************/
1170 
1171 wait_status(adder, mask)
1172 register struct adder *adder;
1173 register int mask;
1174 {
1175 	register short status;
1176 	int i;
1177 
1178 	for ( i = 10000, adder->status = 0
1179 	    ; i > 0  &&  !((status = adder->status) & mask)
1180 	    ; --i);
1181 
1182 	if (i == 0) {
1183 	    printf("timeout polling for 0x%x in adder->status\n", mask);
1184 	    return(BAD);
1185 	}
1186 
1187 	return(GOOD);
1188 
1189 } /* wait_status */
1190 
1191 /**********************************************************************
1192 *
1193 *	write_ID()... write out onto the ID bus
1194 *
1195 ***********************************************************************
1196 *
1197 *	calling convention:
1198 *
1199 *		struct *adder adder;	;pntr to ADDER structure
1200 *		short adrs;		;VIPER address
1201 *		short data;		;data to be written
1202 *		write_ID(adder);
1203 *
1204 *	return: BAD means that we timed out waiting for status bits
1205 *		      VIPER-access-specific status bits
1206 *		GOOD otherwise
1207 *
1208 **************/
1209 
1210 write_ID(adder, adrs, data)
1211 register struct adder *adder;
1212 register short adrs;
1213 register short data;
1214 {
1215 	int i;
1216 	short status;
1217 
1218 	for ( i = 100000, adder->status = 0
1219 	    ; i > 0  &&  !((status = adder->status) & ADDRESS_COMPLETE)
1220 	    ; --i);
1221 
1222 	if (i == 0)
1223 	    goto ERR;
1224 
1225 	for ( i = 100000, adder->status = 0
1226 	    ; i > 0  &&  !((status = adder->status) & TX_READY)
1227 	    ; --i);
1228 
1229 	if (i > 0) {
1230 	    adder->id_data = data;
1231 	    adder->command = ID_LOAD | adrs;
1232 	    return(GOOD);
1233 	}
1234 
1235 ERR:
1236 	printf("timeout trying to write to VIPER\n");
1237 	return(BAD);
1238 
1239 } /* write_ID */
1240