BSD 4_4 release
[unix-history] / usr / src / sys / vax / stand / qdcons.c
/*
* Copyright (c) 1988 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)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 */