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
qd_init()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
qdputc(chr)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
qdgetc()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
ldcursor()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
ldfont()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
led_control(cmd,led_mask)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
scroll_up(adder)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
set_defaults()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
setup_dragon()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
setup_input()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
wait_status(adder,mask)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
write_ID(adder,adrs,data)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