4.3BSD-Tahoe/usr/src/sys/vaxstand/qvcons.c

Compare this file to the similar file:
Show the results in this format:

/*
 * Copyright (c) 1982, 1986 Regents of the University of California.
 * All rights reserved.  The Berkeley software License Agreement
 * specifies the terms and conditions for redistribution.
 *
 * 		@(#)qvcons.c	1.3  Berkeley  6/29/88
 *
 *	derived from: @(#)qvcons.c	4.1 11/23/87
 */

/************************************************************************
 *									*
 *			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.			*
 *									*
 *   This software is  derived  from  software  received  from  the	*
 *   University    of   California,   Berkeley,   and   from   Bell	*
 *   Laboratories.  Use, duplication, or disclosure is  subject  to	*
 *   restrictions  under  license  agreements  with  University  of	*
 *   California and with AT&T.						*
 *									*
 *   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.	*
 *									*
 ************************************************************************/

/* ---------------------------------------------------------------------
 * Modification History - moved to sccs log
 *
 *  7 Jul 84 --  rjl
 *	Initial version to support the qvss as the system console
 *	during the boot process.
 *
 * ---------------------------------------------------------------------
 */

#include "../h/types.h"
#define KERNEL
#include "../vaxuba/qvioctl.h"
#undef KERNEL
#include "../vax/cpu.h"

/*
 * MicroVAX-II q-bus memory base
 */
#define QMEMBASE 0x30000000
#define QVMAXEVQ	64
#define QVSSCSR 0x20001e80

/*
 * Screen initialization tables. qv_def_scn is used as an index into the
 * table to select the proper initialization parameters.
 */
int qv_def_scn = 1;			/* Screen initialization flag	*/

char	qv_scrn_15[]= {
	31,25,27,0142,31,13,30,31,4,15,040,0,0,0,0,0
};

char	qv_scrn_19s[]= {
	39,30,31,0264,55,5,54,54,4,15,040,0,0,0,0,0
};

char	*qv_init_tbl[]= {
	qv_scrn_15,
	qv_scrn_19s,
};

struct qv_info qv_scn_defaults[] = {
	{0, {0, 0}, 0, {0, 0}, 0, 0, 30, 80, 768, 480, 768-16, 480-16,
	 0, 0, 0, 0, 0, QVMAXEVQ, 0, 0, {0, 0}, {0, 0, 0, 0}, 2, 4},
	{0, {0, 0}, 0, {0, 0}, 0, 0, 55, 120, 960, 864, 960-16, 864-16,
	 0, 0, 0, 0, 0, QVMAXEVQ, 0, 0, {0, 0}, {0, 0, 0, 0}, 2, 4},
	{0, {0, 0}, 0, {0, 0}, 0, 0, 56, 120,1024, 864,1024-16, 864-16,
	 0, 0, 0, 0, 0, QVMAXEVQ, 0, 0, {0, 0}, {0, 0, 0, 0}, 2, 4}
};

struct qv_info  qv_scn;

struct qv_keyboard {
	int shift;			/* state variables	*/
	int cntrl;
	int lock;
	char last;			/* last character	*/
} qv_keyboard;

int qvputc(),qvgetc();

/*
 * Keyboard translation and font tables
 */
extern  char q_key[],q_shift_key[],*q_special[],q_font[];
extern	short q_cursor[];

extern (*v_putc)(),(*v_getc)();

/*
 * Routine called to init a qvss.
 */
qv_init()
{
	struct qvdevice *qvaddr = (struct qvdevice *)QVSSCSR;
	char *qvssmem;
	short *scanline;
	int i;
	short scan;
	char *ptr;
	extern int cpu;

        if( badaddr( qvaddr, sizeof(short) ) )
                return(0);

        if( qvaddr->qv_csr & QV_19INCH )
                qv_def_scn = 1;
        else
                qv_def_scn = 0;
        qv_scn = qv_scn_defaults[ qv_def_scn ];
	qv_scn.qvaddr = qvaddr;

	/*
	 * Initialize the screen.
	 */
	ptr = qv_init_tbl[ qv_def_scn ];
	for( i=0 ; i<16 ; i++ ) {
		qvaddr->qv_crtaddr = i;
		qvaddr->qv_crtdata = *ptr++;
	}

	/*
	 * Turn on the keyboard. 
	 */
	qvaddr->qv_uartcmd = 0x15;	/* set mode pntr/enable rx/tx	*/
	qvaddr->qv_uartmode = 0x17;	/* noparity, 8-bit		*/
	qvaddr->qv_uartmode = 0x07;	/* 1 stop bit			*/
	qvaddr->qv_uartstatus = 0x99;	/* 4800 baud xmit/recv 		*/

	qvssmem = (char *)((qvaddr->qv_csr & QV_MEM_BANK) << 7);
	if( cpu == VAX_630 )
		qvssmem += QMEMBASE;

	qv_scn.bitmap = qvssmem;
	qv_scn.scanmap = (short *)((int)qvssmem + ( 254 * 1024 ));
	qv_scn.cursorbits = (short *)((int)qvssmem + ( 256 * 1024 ) - 32);

	/*
	 * Setup the cursor.
	 */
	for( i=0 ; i<16 ; i++ )
		qv_scn.cursorbits[i] = q_cursor[i];

	/*
	 * Clear the bit map
	 */
	for( i=0 , ptr = qv_scn.bitmap ; i<254 ; i += 2 , ptr += 2048)
		bzero( ptr, 2048 );
	
	/*
	 * Reinitialize the scanmap
	 */
	scan = qv_scn.qvaddr->qv_csr & QV_MEM_BANK;
	scanline = qv_scn.scanmap;
	for(i = 0 ; i < qv_scn.max_y ; i++ )
		*scanline++ = scan++;

	/*
	 * Home the cursor
	 */
	qv_scn.row = qv_scn.col = 0;

	/*
	 * Turn it on.
	 */
	v_getc = qvgetc;
	v_putc = qvputc;
	qvaddr->qv_csr |= QV_CUR_MODE | QV_VIDEO_ENA;
	return 1;
}

/*
 * Routine to display a character on the screen.  The model used is a 
 * glass tty.  It is assummed that the user will only use this emulation
 * during system boot and that the screen will be eventually controlled
 * by a window manager.
 */
qvputc( c )
char c;
{

	char *b_row, *f_row;
	int i, j;
	short *scanline;

	c &= 0x7f;

	switch ( c ) {
	case '\t':				/* tab		*/
		for( j = 8 - (qv_scn.col & 0x7) ; j > 0 ; j-- )
			qvputc( ' ' );
		break;

	case '\r':				/* return	*/
		qv_scn.col = 0;
		break;

	case '\010':				/* backspace	*/
		if( --qv_scn.col < 0 )
			qv_scn.col = 0;
		break;

	case '\n':				/* linefeed	*/
		if( qv_scn.row+1 >= qv_scn.max_row )
			qvscroll();
		else
			qv_scn.row++;
		break;

	case '\007':				/* bell		*/
		if( qv_scn.qvaddr )
			qv_key_out( LK_BELL_ENABLE );
		return;

	default:
		if( c >= ' ' && c <= '~' ) {
			scanline = qv_scn.scanmap;
			b_row = qv_scn.bitmap+(scanline[qv_scn.row*15]&0x3ff)*128+qv_scn.col;
			i = c - ' ';
			if( i < 0 || i > 95 )
				i = 0;
			else
				i *= 15;
			f_row = (char *)((int)q_font + i);
		
			for( i=0 ; i<15 ; i++ , b_row += 128, f_row++ )
				*b_row = *f_row;

			if( ++qv_scn.col >= qv_scn.max_col ) {
				qv_scn.col = 0 ;
				if( qv_scn.row+1 >= qv_scn.max_row )
					qvscroll();
				else
					qv_scn.row++;
			}
		}
		break;
	}
	/*
	 * Position the cursor to the next character location.
	 */
	qv_pos_cur( qv_scn.col*8, qv_scn.row*15 );
}

/*
 * Position the cursor to a particular spot.
 */
qv_pos_cur( x, y)
int x,y;
{
	struct qvdevice *qvaddr;

	if( qvaddr = qv_scn.qvaddr ) {
		if( y < 0 || y > qv_scn.max_cur_y )
			y = qv_scn.max_cur_y;
		if( x < 0 || x > qv_scn.max_cur_x )
			x = qv_scn.max_cur_x;

		qvaddr->qv_crtaddr = 10;	/* select cursor start reg */
		qvaddr->qv_crtdata = y & 0xf;
		qvaddr->qv_crtaddr = 11;	/* select cursor end reg */
		qvaddr->qv_crtdata = y & 0xf;
		qvaddr->qv_crtaddr = 14;	/* select cursor y pos. */
		qvaddr->qv_crtdata = y >> 4;
		qvaddr->qv_xcur = x;		/* pos x axis	*/
	}
}
/*
 * Scroll the bitmap by moving the scanline map words. This could
 * be done by moving the bitmap but it's much too slow for a full screen.
 * The only drawback is that the scanline map must be reset when the user 
 * wants to do graphics.
 */
qvscroll()
{
	int i;
	short tmpscanlines[15];
	char *b_row;
	short *scanline;


	/*
	 * Save the first 15 scanlines so that we can put them at
	 * the bottom when done.
	 */
	bcopy( qv_scn.scanmap, tmpscanlines, sizeof tmpscanlines );

	/*
	 * Clear the wrapping line so that it won't flash on the bottom
	 * of the screen.
	 */
	scanline = qv_scn.scanmap;
	b_row = qv_scn.bitmap+(*scanline&0x3ff)*128;
	bzero( b_row, 1920 );

	/*
	 * Now move the scanlines down 
	 */
	bcopy( qv_scn.scanmap+15, qv_scn.scanmap, (qv_scn.row * 15) * sizeof (short) );

	/*
	 * Now put the other lines back
	 */
	bcopy( tmpscanlines, qv_scn.scanmap+(qv_scn.row * 15), sizeof tmpscanlines );

}

/*
 * QVSS keyboard interrupt.
 */
qvgetc()
{
	int c;
	struct qvdevice *qvaddr;
	char *string;
	int j;

	qvaddr = qv_scn.qvaddr;
	/*
	 * Get a character from the keyboard.
	 */
loop:
	while( (qvaddr->qv_uartstatus & 0x01) == 0 )
		;
	j = qvaddr->qv_uartdata & 0xff;
	/*
	 * See if its a state change key
	 */
	switch ( j ) {
	case LOCK:
		qv_keyboard.lock ^= 0xffff;	/* toggle */
		if( qv_keyboard.lock )
			qv_key_out( LK_LED_ENABLE );
		else
			qv_key_out( LK_LED_DISABLE );
		qv_key_out( LED_3 );
		goto loop;
	case SHIFT:
		qv_keyboard.shift ^= 0xffff;
		goto loop;
	case CNTRL:
		qv_keyboard.cntrl ^= 0xffff;
		goto loop;
	case ALLUP:
		qv_keyboard.cntrl = qv_keyboard.shift = 0;
		goto loop;
	case REPEAT:
		c = qv_keyboard.last;
		break;
	default:
		/*
		 * Test for control characters. If set, see if the character
		 * is elligible to become a control character.
		 */
		if( qv_keyboard.cntrl ) {
			c = q_key[ j ];
			if( c >= ' ' && c <= '~' )
				c &= 0x1f;
		} else if( qv_keyboard.lock || qv_keyboard.shift )
			c = q_shift_key[ j ];
		else
			c = q_key[ j ];
		break;
	}

	qv_keyboard.last = c;

	/*
	 * Check for special function keys
	 */
	if( c & 0x80 ) 
		return 0;
	else
		return c;
}

/*
 * Output to the keyboard. This routine status polls the transmitter on the
 * keyboard to output a code. The timer is to avoid hanging on a bad device.
 */
qv_key_out( c )
char c;
{
	int timer = 30000;

	if( qv_scn.qvaddr ) {
		while( (qv_scn.qvaddr->qv_uartstatus & 0x4) == 0  && timer-- )
			;
		qv_scn.qvaddr->qv_uartdata = c;
	}
}