BSD 4_4 release
[unix-history] / usr / src / sys / vax / stand / qvcons.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.
*
* @(#)qvcons.c 7.7 (Berkeley) 12/16/90
*/
/*
* 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 "sys/types.h"
#define KERNEL
#include "../uba/qvioctl.h"
#undef KERNEL
#include "../include/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;
}
}