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