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