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