/* * Copyright (c) 1988 Regents of the University of California. * All rights reserved. * * %sccs.include.redist.c% * * @(#)qdcons.c 7.5 (Berkeley) 12/16/90 */ /* * derived from: @(#)qdcons.c 4.1 (ULTRIX 11/23/87 */ /************************************************************************ * * ULTRIX QDSS STANDALONE BOOT DEVICE DRIVER... * device driver to boot system with QDSS as console * *************************************************************************/ /************************************************************************ * * * Copyright (c) 1985 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************* * revision history: (should be moved into sccs comments) ************************************************************************* * * 09 oct 85 longo added uVAXII console ROM cursor reset to bottom of * the screen. Also spruced up qdputc() & scroll_up() * 02 oct 85 longo changed references to ADDRESS to be ADDRESS_COMPLETE * 23 aug 85 longo changed I/O page CSR address to be 0x1F00 * 20 aug 85 longo created * ************************************************************************/ #include "sys/types.h" #include "../include/cpu.h" #define KERNEL #include "../uba/qdioctl.h" #include "../uba/qevent.h" #include "../uba/qduser.h" #include "../uba/qdreg.h" #undef KERNEL /*----------------------------------------------------------------------- * constants used to set VAX ROM's cursor to bottom the of the screen */ #define NVR_ADRS 0x200B8024 #define CURRENT_ROW 0x4C /* these are offsets to the ROM's scratch.. */ #define ROW_MIN 0x4D /* ..RAM start adrs as picked up out of NVR */ #define ROW_MAX 0x4E #define CURRENT_COL 0x50 #define COL_MIN 0x51 #define COL_MAX 0x52 /*---------------------------------------- * LK201 keyboard state tracking struct */ struct q_keyboard { int shift; /* state variables */ int cntrl; int lock; char last; /* last character */ } q_keyboard; int qdputc(), qdgetc(); extern (*v_putc)(),(*v_getc)(); /*---------------------------- * general purpose defines */ #define BAD -1 #define GOOD 0 /*---------------------------------------------- * console cursor bitmap (block cursor type) */ short cons_cursor[32] = { /* white block cursor */ /* A */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, /* B */ 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF, 0x00FF }; /*------------------------------------- * constants used in font operations */ #define CHARS 95 /* # of chars in the font */ #define CHAR_HEIGHT 15 /* char height in pixels */ #define CHAR_WIDTH 8 /* char width in pixels*/ #define FONT_WIDTH (CHAR_WIDTH * CHARS) /* font width in pixels */ #define ROWS CHAR_HEIGHT #define FONT_X 0 /* font's off screen adrs */ #define FONT_Y (2047 - CHAR_HEIGHT) /* #define FONT_Y 200 */ extern char q_font[]; /* reference font object code */ extern char q_key[]; /* reference key xlation tables */ extern char q_shift_key[]; extern char *q_special[]; /*---------------------------- * console cursor structure */ struct cons_cur { int x; int y; } cursor; /*------------------------------------------ * MicroVAX-II q-bus addressing constants */ #define QMEMBASE 0x30000000 #define QDSSCSR 0x20001F00 #define CHUNK (64 * 1024) #define QMEMSIZE (1024 * 1024 * 4) #define QDBASE (QMEMBASE + QMEMSIZE - CHUNK) /*------------------------------------------------------------------ * QDSS register address offsets from start of QDSS address space */ #define QDSIZE (52 * 1024) /* size of entire QDSS foot print */ #define TMPSIZE (16 * 1024) /* template RAM is 8k SHORT WORDS */ #define TMPSTART 0x8000 /* offset of template RAM from base adrs */ #define REGSIZE (5 * 512) /* regs touch 2.5k (5 pages) of addr space */ #define REGSTART 0xC000 /* offset of reg pages from base adrs */ #define ADDER (REGSTART+0x000) #define DGA (REGSTART+0x200) #define DUART (REGSTART+0x400) #define MEMCSR (REGSTART+0x800) #define CLRSIZE (3 * 512) /* color map size */ #define CLRSTART (REGSTART+0xA00) /* color map start offset from base */ /* 0x0C00 really */ #define RED (CLRSTART+0x000) #define BLUE (CLRSTART+0x200) #define GREEN (CLRSTART+0x400) /*--------------------------------------- * QDSS register address map structure */ struct qdmap qdmap; /************************************************************************ ************************************************************************* ************************************************************************* * * EXTERNALLY CALLED ROUTINES START HERE: * ************************************************************************* ************************************************************************* ************************************************************************/ /************************************************************************ * * qd_init()... init the QDSS into a physical memory system * ************************************************************************/ qd_init() { register char *ROM_console; register short *NVR; register int i; caddr_t qdaddr; struct dga *dga; extern int cpu; qdaddr = (caddr_t) QDSSCSR; if (badaddr(qdaddr, sizeof(short))) return(0); *(short *)qdaddr = (short) (QDBASE >> 16); /*---------------------------------------------------------------------- * load qdmap struct with the physical addresses of the QDSS elements */ qdmap.template = (caddr_t) QDBASE + TMPSTART; qdmap.adder = (caddr_t) QDBASE + ADDER; qdmap.dga = (caddr_t) QDBASE + DGA; qdmap.duart = (caddr_t) QDBASE + DUART; qdmap.memcsr = (caddr_t) QDBASE + MEMCSR; qdmap.red = (caddr_t) QDBASE + RED; qdmap.blue = (caddr_t) QDBASE + BLUE; qdmap.green = (caddr_t) QDBASE + GREEN; /*-------------------------- * no interrupts allowed! */ dga = (struct dga *) qdmap.dga; dga->csr = HALT; dga->csr |= CURS_ENB; /*---------------------------- * init the default values */ q_keyboard.shift = 0; /* init keyboard state tracking */ q_keyboard.lock = 0; q_keyboard.cntrl = 0; q_keyboard.last = 0; cursor.x = 0; /* init cursor to top left */ cursor.y = 0; set_defaults(); /* setup the default device */ ldfont(); /* PtoB the font into off-screen */ /*-------------------------------------------------------------------- * tell the VAX ROM that the cursor is at the bottom of the screen */ if (cpu == VAX_630) { NVR = (short *) NVR_ADRS; i = *NVR++ & 0xFF; i |= (*NVR++ & 0xFF) << 8; i |= (*NVR++ & 0xFF) << 16; i |= (*NVR++ & 0xFF) << 24; ROM_console = (char *) i; ROM_console[CURRENT_COL] = ROM_console[COL_MIN]; ROM_console[CURRENT_ROW] = ROM_console[ROW_MAX]; } /*---------------------------------------------------------- * smash system virtual console service routine addresses */ printf("switching console to QDSS display...\n"); v_getc = qdgetc; v_putc = qdputc; return(1); } /* qd_init */ /******************************************************************* * * qdputc()... output a character to the QDSS screen * ******************************************************************** * * calling convention: * * qdputc(chr); * char chr; ;character to be displayed * ********/ qdputc(chr) char chr; { register struct adder *adder; register struct dga *dga; register int i; short x; adder = (struct adder *) qdmap.adder; dga = (struct dga *) qdmap.dga; /*--------------------------- * non display character? */ chr &= 0x7F; switch (chr) { case '\r': /* return char */ cursor.x = 0; dga->x_cursor = TRANX(cursor.x); return(0); case '\t': /* tab char */ for (i = 8 - ((cursor.x >> 3) & 0x07); i > 0; --i) { qdputc(' '); } return(0); case '\n': /* line feed char */ if ((cursor.y += CHAR_HEIGHT) > (863 - CHAR_HEIGHT)) { cursor.y -= CHAR_HEIGHT; scroll_up(adder); } dga->y_cursor = TRANY(cursor.y); return(0); case '\b': /* backspace char */ if (cursor.x > 0) { cursor.x -= CHAR_WIDTH; qdputc(' '); cursor.x -= CHAR_WIDTH; dga->x_cursor = TRANX(cursor.x); } return(0); default: if (chr < ' ' || chr > '~') { return(0); } } /*------------------------------------------ * setup VIPER operand control registers */ write_ID(adder, CS_UPDATE_MASK, 0x0001); /* select plane #0 */ write_ID(adder, SRC1_OCR_B, EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY); write_ID(adder, CS_UPDATE_MASK, 0x00FE); /* select other planes */ write_ID(adder, SRC1_OCR_B, EXT_SOURCE | INT_NONE | NO_ID | BAR_SHIFT_DELAY); write_ID(adder, CS_UPDATE_MASK, 0x00FF); /* select all planes */ write_ID(adder, DST_OCR_B, EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY); write_ID(adder, MASK_1, 0xFFFF); write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 1); write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); /*---------------------------------------- * load DESTINATION origin and vectors */ adder->fast_dest_dy = 0; adder->slow_dest_dx = 0; adder->error_1 = 0; adder->error_2 = 0; adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL; wait_status(adder, RASTEROP_COMPLETE); adder->destination_x = cursor.x; adder->fast_dest_dx = CHAR_WIDTH; adder->destination_y = cursor.y; adder->slow_dest_dy = CHAR_HEIGHT; /*----------------------------------- * load SOURCE origin and vectors */ adder->source_1_x = FONT_X + ((chr - ' ') * CHAR_WIDTH); adder->source_1_y = FONT_Y; adder->source_1_dx = CHAR_WIDTH; adder->source_1_dy = CHAR_HEIGHT; write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE); adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE; /*------------------------------------- * update console cursor coordinates */ cursor.x += CHAR_WIDTH; dga->x_cursor = TRANX(cursor.x); if (cursor.x > (1024 - CHAR_WIDTH)) { qdputc('\r'); qdputc('\n'); } } /* qdputc */ /******************************************************************* * * qdgetc()... get a character from the LK201 * *******************************************************************/ qdgetc() { register short key; register char chr; register struct duart *duart; u_int status; duart = (struct duart *) qdmap.duart; /*-------------------------------------- * Get a character from the keyboard. */ LOOP: while (!((status = duart->statusA) & RCV_RDY)) ; key = duart->dataA; key &= 0xFF; /*-------------------------------------- * Check for various keyboard errors */ if( key == LK_POWER_ERROR || key == LK_KDOWN_ERROR || key == LK_INPUT_ERROR || key == LK_OUTPUT_ERROR) { printf("Keyboard error, code = %x\n", key); return(0); } if (key < LK_LOWEST) return(0); /*--------------------------------- * See if its a state change key */ switch (key) { case LOCK: q_keyboard.lock ^= 0xffff; /* toggle */ if (q_keyboard.lock) led_control(LK_LED_ENABLE, LK_LED_LOCK); else led_control(LK_LED_DISABLE, LK_LED_LOCK); goto LOOP; case SHIFT: q_keyboard.shift ^= 0xFFFF; goto LOOP; case CNTRL: q_keyboard.cntrl ^= 0xFFFF; goto LOOP; case ALLUP: q_keyboard.cntrl = 0; q_keyboard.shift = 0; goto LOOP; case REPEAT: chr = q_keyboard.last; break; /*------------------------------------------------------- * Test for cntrl characters. If set, see if the character * is elligible to become a control character. */ default: if (q_keyboard.cntrl) { chr = q_key[key]; if (chr >= ' ' && chr <= '~') chr &= 0x1F; } else if ( q_keyboard.lock || q_keyboard.shift ) chr = q_shift_key[key]; else chr = q_key[key]; break; } if (chr < ' ' && chr > '~') /* if input is non-displayable */ return(0); /* ..then pitch it! */ q_keyboard.last = chr; /*----------------------------------- * Check for special function keys */ if (chr & 0x80) /* pitch the function keys */ return(0); else return(chr); } /* qdgetc */ /************************************************************************ ************************************************************************* ************************************************************************* * * INTERNALLY USED ROUTINES START HERE: * ************************************************************************* ************************************************************************* ************************************************************************/ /******************************************************************** * * ldcursor()... load the mouse cursor's template RAM bitmap * ********************************************************************/ ldcursor() { register struct dga *dga; register short *temp; register int i; int cursor; dga = (struct dga *) qdmap.dga; temp = (short *) qdmap.template; temp += (8 * 1024) - 32; /* cursor is 32 WORDS from the end */ /* ..of the 8k WORD template space */ for (i = 0; i < 32; ++i) *temp++ = cons_cursor[i]; return(0); } /* ldcursor */ /********************************************************************** * * ldfont()... put the console font in the QDSS off-screen memory * **********************************************************************/ ldfont() { register struct adder *adder; int i; /* scratch variables */ int j; int k; short packed; adder = (struct adder *) qdmap.adder; /*------------------------------------------ * setup VIPER operand control registers */ write_ID(adder, MASK_1, 0xFFFF); write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255); write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); write_ID(adder, SRC1_OCR_B, EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY); write_ID(adder, SRC2_OCR_B, EXT_NONE | INT_NONE | ID | BAR_SHIFT_DELAY); write_ID(adder, DST_OCR_B, EXT_SOURCE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY); adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL; /*-------------------------- * load destination data */ wait_status(adder, RASTEROP_COMPLETE); adder->destination_x = FONT_X; adder->destination_y = FONT_Y; adder->fast_dest_dx = FONT_WIDTH; adder->slow_dest_dy = CHAR_HEIGHT; /*--------------------------------------- * setup for processor to bitmap xfer */ write_ID(adder, CS_UPDATE_MASK, 0x0001); adder->cmd = PBT | OCRB | 2 | DTE | 2; /*----------------------------------------------- * iteratively do the processor to bitmap xfer */ for (i = 0; i < ROWS; ++i) { /* PTOB a scan line */ for (j = 0, k = i; j < 48; ++j) { /* PTOB one scan of a char cell */ packed = q_font[k]; k += ROWS; packed |= ((short)q_font[k] << 8); k += ROWS; wait_status(adder, TX_READY); adder->id_data = packed; } } } /* ldfont */ /********************************************************************* * * led_control()... twiddle LK-201 LED's * ********************************************************************** * * led_control(cmd, led_mask); * int cmd; LED enable/disable command * int led_mask; which LED(s) to twiddle * *************/ led_control(cmd, led_mask) int cmd; int led_mask; { register int i; register int status; register struct duart *duart; duart = (struct duart *) qdmap.duart; for (i = 1000; i > 0; --i) { if ((status = duart->statusA) & XMT_RDY) { duart->dataA = cmd; break; } } for (i = 1000; i > 0; --i) { if ((status = duart->statusA) & XMT_RDY) { duart->dataA = led_mask; break; } } if (i == 0) return(BAD); return(GOOD); } /* led_control */ /******************************************************************* * * scroll_up()... move the screen up one character height * ******************************************************************** * * calling convention: * * scroll_up(adder); * struct adder *adder; ;address of adder * ********/ scroll_up(adder) register struct adder *adder; { /*------------------------------------------ * setup VIPER operand control registers */ wait_status(adder, ADDRESS_COMPLETE); write_ID(adder, CS_UPDATE_MASK, 0x00FF); /* select all planes */ write_ID(adder, MASK_1, 0xFFFF); write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255); write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); write_ID(adder, SRC1_OCR_B, EXT_NONE | INT_SOURCE | ID | BAR_SHIFT_DELAY); write_ID(adder, DST_OCR_B, EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY); /*---------------------------------------- * load DESTINATION origin and vectors */ adder->fast_dest_dy = 0; adder->slow_dest_dx = 0; adder->error_1 = 0; adder->error_2 = 0; adder->rasterop_mode = DST_WRITE_ENABLE | NORMAL; adder->destination_x = 0; adder->fast_dest_dx = 1024; adder->destination_y = 0; adder->slow_dest_dy = 864 - CHAR_HEIGHT; /*----------------------------------- * load SOURCE origin and vectors */ adder->source_1_x = 0; adder->source_1_dx = 1024; adder->source_1_y = 0 + CHAR_HEIGHT; adder->source_1_dy = 864 - CHAR_HEIGHT; write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE); adder->cmd = RASTEROP | OCRB | 0 | S1E | DTE; /*-------------------------------------------- * do a rectangle clear of last screen line */ write_ID(adder, MASK_1, 0xffff); write_ID(adder, SOURCE, 0xffff); write_ID(adder,DST_OCR_B, (EXT_NONE | INT_NONE | NO_ID | NO_BAR_SHIFT_DELAY)); write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 0); adder->error_1 = 0; adder->error_2 = 0; adder->slow_dest_dx = 0; /* set up the width of */ adder->slow_dest_dy = CHAR_HEIGHT; /* rectangle */ adder->rasterop_mode = (NORMAL | DST_WRITE_ENABLE) ; wait_status(adder, RASTEROP_COMPLETE); adder->destination_x = 0; adder->destination_y = 864 - CHAR_HEIGHT; adder->fast_dest_dx = 1024; /* set up the height */ adder->fast_dest_dy = 0; /* of rectangle */ write_ID(adder, LU_FUNCTION_R2, (FULL_SRC_RESOLUTION | LF_SOURCE)); adder->cmd = (RASTEROP | OCRB | LF_R2 | DTE ) ; } /* scroll_up */ /********************************************************************** * * set_defaults()... init the QDSS device and driver defaults * **********************************************************************/ set_defaults() { setup_input(); /* init the DUART */ setup_dragon(); /* init the ADDER/VIPER stuff */ ldcursor(); /* load default cursor map */ } /* set_defaults */ /********************************************************************* * * setup_dragon()... init the ADDER, VIPER, bitmaps, & color map * *********************************************************************/ setup_dragon() { register struct adder *adder; register struct dga *dga; short *memcsr; int i; /* general purpose variables */ int status; short top; /* clipping/scrolling boundaries */ short bottom; short right; short left; short *red; /* color map pointers */ short *green; short *blue; /*------------------ * init for setup */ adder = (struct adder *) qdmap.adder; dga = (struct dga *) qdmap.dga; memcsr = (short *) qdmap.memcsr; *memcsr = SYNC_ON; /* blank screen and turn off LED's */ adder->command = CANCEL; /*---------------------- * set monitor timing */ adder->x_scan_count_0 = 0x2800; adder->x_scan_count_1 = 0x1020; adder->x_scan_count_2 = 0x003A; adder->x_scan_count_3 = 0x38F0; adder->x_scan_count_4 = 0x6128; adder->x_scan_count_5 = 0x093A; adder->x_scan_count_6 = 0x313C; adder->sync_phase_adj = 0x0100; adder->x_scan_conf = 0x00C8; /*--------------------------------------------------------- * got a bug in secound pass ADDER! lets take care of it */ /* normally, just use the code in the following bug fix code, but to * make repeated demos look pretty, load the registers as if there was * no bug and then test to see if we are getting sync */ adder->y_scan_count_0 = 0x135F; adder->y_scan_count_1 = 0x3363; adder->y_scan_count_2 = 0x2366; adder->y_scan_count_3 = 0x0388; /* if no sync, do the bug fix code */ if (wait_status(adder, VSYNC) == BAD) { /* first load all Y scan registers with very short frame and * wait for scroll service. This guarantees at least one SYNC * to fix the pass 2 Adder initialization bug (synchronizes * XCINCH with DMSEEDH) */ adder->y_scan_count_0 = 0x01; adder->y_scan_count_1 = 0x01; adder->y_scan_count_2 = 0x01; adder->y_scan_count_3 = 0x01; wait_status(adder, VSYNC); /* delay at least 1 full frame time */ wait_status(adder, VSYNC); /* now load the REAL sync values (in reverse order just to * be safe. */ adder->y_scan_count_3 = 0x0388; adder->y_scan_count_2 = 0x2366; adder->y_scan_count_1 = 0x3363; adder->y_scan_count_0 = 0x135F; } /*---------------------------- * zero the index registers */ adder->x_index_pending = 0; adder->y_index_pending = 0; adder->x_index_new = 0; adder->y_index_new = 0; adder->x_index_old = 0; adder->y_index_old = 0; adder->pause = 0; /*---------------------------------------- * set rasterop mode to normal pen down */ adder->rasterop_mode = DST_WRITE_ENABLE | DST_INDEX_ENABLE | NORMAL; /*-------------------------------------------------- * set the rasterop registers to a default values */ adder->source_1_dx = 1; adder->source_1_dy = 1; adder->source_1_x = 0; adder->source_1_y = 0; adder->destination_x = 0; adder->destination_y = 0; adder->fast_dest_dx = 1; adder->fast_dest_dy = 0; adder->slow_dest_dx = 0; adder->slow_dest_dy = 1; adder->error_1 = 0; adder->error_2 = 0; /*------------------------ * scale factor = unity */ adder->fast_scale = UNITY; adder->slow_scale = UNITY; /*------------------------------- * set the source 2 parameters */ adder->source_2_x = 0; adder->source_2_y = 0; adder->source_2_size = 0x0022; /*----------------------------------------------- * initialize plane addresses for eight vipers */ write_ID(adder, CS_UPDATE_MASK, 0x0001); write_ID(adder, PLANE_ADDRESS, 0x0000); write_ID(adder, CS_UPDATE_MASK, 0x0002); write_ID(adder, PLANE_ADDRESS, 0x0001); write_ID(adder, CS_UPDATE_MASK, 0x0004); write_ID(adder, PLANE_ADDRESS, 0x0002); write_ID(adder, CS_UPDATE_MASK, 0x0008); write_ID(adder, PLANE_ADDRESS, 0x0003); write_ID(adder, CS_UPDATE_MASK, 0x0010); write_ID(adder, PLANE_ADDRESS, 0x0004); write_ID(adder, CS_UPDATE_MASK, 0x0020); write_ID(adder, PLANE_ADDRESS, 0x0005); write_ID(adder, CS_UPDATE_MASK, 0x0040); write_ID(adder, PLANE_ADDRESS, 0x0006); write_ID(adder, CS_UPDATE_MASK, 0x0080); write_ID(adder, PLANE_ADDRESS, 0x0007); /* initialize the external registers. */ write_ID(adder, CS_UPDATE_MASK, 0x00FF); write_ID(adder, CS_SCROLL_MASK, 0x00FF); /* initialize resolution mode */ write_ID(adder, MEMORY_BUS_WIDTH, 0x000C); /* bus width = 16 */ write_ID(adder, RESOLUTION_MODE, 0x0000); /* one bit/pixel */ /* initialize viper registers */ write_ID(adder, SCROLL_CONSTANT, SCROLL_ENABLE|VIPER_LEFT|VIPER_UP); write_ID(adder, SCROLL_FILL, 0x0000); /*---------------------------------------------------- * set clipping and scrolling limits to full screen */ for ( i = 1000, adder->status = 0 ; i > 0 && !((status = adder->status) & ADDRESS_COMPLETE) ; --i); if (i == 0) printf("timeout trying to setup clipping\n"); top = 0; bottom = 2048; left = 0; right = 1024; adder->x_clip_min = left; adder->x_clip_max = right; adder->y_clip_min = top; adder->y_clip_max = bottom; adder->scroll_x_min = left; adder->scroll_x_max = right; adder->scroll_y_min = top; adder->scroll_y_max = bottom; wait_status(adder, VSYNC); /* wait at LEAST 1 full frame */ wait_status(adder, VSYNC); adder->x_index_pending = left; adder->y_index_pending = top; adder->x_index_new = left; adder->y_index_new = top; adder->x_index_old = left; adder->y_index_old = top; for ( i = 1000, adder->status = 0 ; i > 0 && !((status = adder->status) & ADDRESS_COMPLETE) ; --i); if (i == 0) printf("timeout waiting for ADDRESS_COMPLETE bit\n"); write_ID(adder, LEFT_SCROLL_MASK, 0x0000); write_ID(adder, RIGHT_SCROLL_MASK, 0x0000); /*------------------------------------------------------------ * set source and the mask register to all ones (ie: white) */ write_ID(adder, SOURCE, 0xFFFF); write_ID(adder, MASK_1, 0xFFFF); write_ID(adder, VIPER_Z_LOAD | FOREGROUND_COLOR_Z, 255); write_ID(adder, VIPER_Z_LOAD | BACKGROUND_COLOR_Z, 0); /*-------------------------------------------------------------- * initialize Operand Control Register banks for fill command */ write_ID(adder, SRC1_OCR_A, EXT_NONE | INT_M1_M2 | NO_ID | WAIT); write_ID(adder, SRC2_OCR_A, EXT_NONE | INT_SOURCE | NO_ID | NO_WAIT); write_ID(adder, DST_OCR_A, EXT_NONE | INT_NONE | NO_ID | NO_WAIT); write_ID(adder, SRC1_OCR_B, EXT_NONE | INT_SOURCE | NO_ID | WAIT); write_ID(adder, SRC2_OCR_B, EXT_NONE | INT_M1_M2 | NO_ID | NO_WAIT); write_ID(adder, DST_OCR_B, EXT_NONE | INT_NONE | NO_ID | NO_WAIT); /*------------------------------------------------------------------ * init Logic Unit Function registers, (these are just common values, * and may be changed as required). */ write_ID(adder, LU_FUNCTION_R1, FULL_SRC_RESOLUTION | LF_SOURCE); write_ID(adder, LU_FUNCTION_R2, FULL_SRC_RESOLUTION | LF_SOURCE | INV_M1_M2); write_ID(adder, LU_FUNCTION_R3, FULL_SRC_RESOLUTION | LF_D_OR_S); write_ID(adder, LU_FUNCTION_R4, FULL_SRC_RESOLUTION | LF_D_XOR_S); /*---------------------------------------- * load the color map for black & white */ for ( i = 0, adder->status = 0 ; i < 10000 && !((status = adder->status) & VSYNC) ; ++i); if (i == 0) printf("timeout waiting for VSYNC bit\n"); red = (short *) qdmap.red; green = (short *) qdmap.green; blue = (short *) qdmap.blue; *red++ = 0x00; /* black */ *green++ = 0x00; *blue++ = 0x00; *red-- = 0xFF; /* white */ *green-- = 0xFF; *blue-- = 0xFF; /*---------------------------------- * set color map for mouse cursor */ red += 254; green += 254; blue += 254; *red++ = 0x00; /* black */ *green++ = 0x00; *blue++ = 0x00; *red = 0xFF; /* white */ *green = 0xFF; *blue = 0xFF; /*--------------------------------------------------------------------------- * clear the bitmap a piece at a time. Since the fast scroll clear only clears * the current displayed portion of the bitmap put a temporary value in the y * limit register so we can access whole bitmap */ adder->x_limit = 1024; adder->y_limit = 2048 - CHAR_HEIGHT; adder->y_offset_pending = 0; wait_status(adder, VSYNC); /* wait at LEAST 1 full frame */ wait_status(adder, VSYNC); adder->y_scroll_constant = SCROLL_ERASE; wait_status(adder, VSYNC); wait_status(adder, VSYNC); adder->y_offset_pending = 864; wait_status(adder, VSYNC); wait_status(adder, VSYNC); adder->y_scroll_constant = SCROLL_ERASE; wait_status(adder, VSYNC); wait_status(adder, VSYNC); adder->y_offset_pending = 1728; wait_status(adder, VSYNC); wait_status(adder, VSYNC); adder->y_scroll_constant = SCROLL_ERASE; wait_status(adder, VSYNC); wait_status(adder, VSYNC); adder->y_offset_pending = 0; /* back to normal */ wait_status(adder, VSYNC); wait_status(adder, VSYNC); adder->x_limit = MAX_SCREEN_X; adder->y_limit = MAX_SCREEN_Y + FONT_HEIGHT; *memcsr = SYNC_ON | UNBLANK; /* turn off leds and turn on video */ return(0); } /* setup_dragon */ /****************************************************************** * * setup_input()... init the DUART and set defaults in input * devices * ******************************************************************/ setup_input() { register struct duart *duart; /* DUART register structure pointer */ register int bits; int i, j; /* scratch variables */ short status; /*--------------- * init stuff */ duart = (struct duart *) qdmap.duart; /*--------------------------------------------- * setup the DUART for kbd & pointing device */ duart->cmdA = RESET_M; /* reset mode reg ptr for kbd */ duart->modeA = 0x13; /* 8 bits, no parity, rcv IE, */ /* no RTS control,char error mode */ duart->modeA = 0x07; /* 1 stop bit,CTS does not IE XMT */ /* no RTS control,no echo or loop */ duart->auxctl = 0x00; /* baud rate set 1 */ duart->clkselA = 0x99; /* 4800 baud for kbd */ /* reset everything for keyboard */ for (bits = RESET_M; bits < START_BREAK; bits += 0x10) duart->cmdA = bits; duart->cmdA = EN_RCV | EN_XMT; /* enbl xmt & rcv for kbd */ /*-------------------------- * init keyboard defaults */ /* for (i = 500; i > 0; --i) { if ((status = duart->statusA) & XMT_RDY) { duart->dataA = LK_DEFAULTS; break; } } for (j = 0; j < 3; ++j) { for (i = 50000; i > 0; --i) { if ((status = duart->statusA) & RCV_RDY) { status = duart->dataA; break; } } } if (i == 0) printf("LK-201 init error\n"); */ /*-------- * exit */ return(0); } /* setup_input */ /********************************************************************** * * wait_status()... delay for at least one display frame time * *********************************************************************** * * calling convention: * * wait_status(adder, mask); * struct *adder adder; * int mask; * * return: BAD means that we timed out without ever seeing the * vertical sync status bit * GOOD otherwise * **************/ wait_status(adder, mask) register struct adder *adder; register int mask; { register short status; int i; for ( i = 10000, adder->status = 0 ; i > 0 && !((status = adder->status) & mask) ; --i); if (i == 0) { printf("timeout polling for 0x%x in adder->status\n", mask); return(BAD); } return(GOOD); } /* wait_status */ /********************************************************************** * * write_ID()... write out onto the ID bus * *********************************************************************** * * calling convention: * * struct *adder adder; ;pntr to ADDER structure * short adrs; ;VIPER address * short data; ;data to be written * write_ID(adder); * * return: BAD means that we timed out waiting for status bits * VIPER-access-specific status bits * GOOD otherwise * **************/ write_ID(adder, adrs, data) register struct adder *adder; register short adrs; register short data; { int i; short status; for ( i = 100000, adder->status = 0 ; i > 0 && !((status = adder->status) & ADDRESS_COMPLETE) ; --i); if (i == 0) goto ERR; for ( i = 100000, adder->status = 0 ; i > 0 && !((status = adder->status) & TX_READY) ; --i); if (i > 0) { adder->id_data = data; adder->command = ID_LOAD | adrs; return(GOOD); } ERR: printf("timeout trying to write to VIPER\n"); return(BAD); } /* write_ID */