tem_safe.c revision 51fd492135573005d200c766ef62f709b4cb312c
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Polled I/O safe ANSI terminal emulator module;
* Supporting TERM types 'sun' and 'sun-color, parsing
* ANSI x3.64 escape sequences, and the like. (See wscons(7d)
* for more information).
*
* IMPORTANT:
*
* The functions in this file *must* be able to function in
* standalone mode, ie. on a quiesced system. In that state,
* access is single threaded, only one CPU is running.
* System services are NOT available.
*
* The following restrictions pertain to every function
* in this file:
*
* - CANNOT use the DDI or LDI interfaces
* - CANNOT call system services
* - CANNOT use mutexes
* - CANNOT wait for interrupts
* - CANNOT allocate memory
*
*/
#include <sys/visual_io.h>
#include <sys/tem_impl.h>
#include <sys/sysmacros.h>
static void tem_display(struct tem *,
struct vis_consdisplay *,
cred_t *, enum called_from);
static void tem_cursor(struct tem *,
struct vis_conscursor *,
cred_t *, enum called_from);
cred_t *, enum called_from);
static void tem_setparam(struct tem *, int, int);
static void tem_selgraph(struct tem *);
cred_t *, enum called_from);
cred_t *, enum called_from);
cred_t *, enum called_from);
cred_t *, enum called_from);
static void tem_new_line(struct tem *,
cred_t *, enum called_from);
cred_t *, enum called_from);
enum called_from);
cred_t *, enum called_from);
cred_t *, enum called_from);
static void tem_back_tab(struct tem *,
cred_t *, enum called_from);
static void tem_clear_tabs(struct tem *, int);
static void tem_set_tab(struct tem *);
static void tem_mv_cursor(struct tem *, int, int,
cred_t *, enum called_from);
cred_t *, enum called_from);
static void tem_scroll(struct tem *, int, int,
int, int, cred_t *, enum called_from);
int, int, screen_pos_t, screen_pos_t,
cred_t *, enum called_from);
enum called_from called_from);
#ifdef _HAVE_TEM_FIRMWARE
#else /* _HAVE_TEM_FIRMWARE */
#endif
/* BEGIN CSTYLED */
/* Bk Rd Gr Br Bl Mg Cy Wh */
/* END CSTYLED */
/* BEGIN CSTYLED */
/* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Wh+ Bk Bl Gr Cy Rd Mg Br Wh Bk+ Bl+ Gr+ Cy+ Rd+ Mg+ Yw */
0xff,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x40,0x00,0x00,0x00,0xff,0xff,0xff,
0xff,0x00,0x00,0x80,0x80,0x00,0x00,0x80,0x80,0x40,0x00,0xff,0xff,0x00,0x00,0xff,
0xff,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x40,0xff,0x00,0xff,0x00,0xff,0x00
/* END CSTYLED */
};
/*
* Fonts are statically linked with this module. At some point an
* RFE might be desireable to allow dynamic font loading. The
* original intention to facilitate dynamic fonts can be seen
* by examining the data structures and set_font(). As much of
* the original code is retained but modified to be suited to
* traversing a list of static fonts.
*/
#define DEFAULT_FONT_DATA font_data_12x22
extern bitmap_data_t font_data_12x22;
extern bitmap_data_t font_data_7x14;
extern bitmap_data_t font_data_6x10;
/*
* Must be sorted by font size in descending order
*/
{ &font_data_12x22, NULL },
{ &font_data_7x14, NULL },
{ &font_data_6x10, NULL },
};
}
void
enum called_from called_from)
{
static int first_time = 1;
/*
* Realign the console cursor. We did this in tem_init().
* However, drivers in the console stream may emit additional
* messages before we are ready. This causes text overwrite
* on the screen. This is a workaround.
*/
}
first_time = 0;
}
/*
* This entry point handles output requests from restricted contexts like
* kmdb, where services like mutexes are not available. This function
* is entered when OBP or when a kernel debugger (such as kmdb)
* are generating console output. In those cases, power management
* concerns are handled by the abort sequence initiation (ie. when
* the user hits L1+A or the equivalent to enter OBP or the debugger.).
* It is also entered when the kernel is panicing.
*/
void
int len)
{
}
/*
* This is the main entry point into the terminal emulator.
*
* For each data message coming downstream, ANSI assumes that it is composed
* of ASCII characters, which are treated as a byte-stream input to the
* parsing state machine. All data is parsed immediately -- there is
* no enqueing.
*/
void
int len,
enum called_from called_from)
{
}
/*
* Send the data we just got to the framebuffer.
*/
}
/*
* Display an rectangular image on the frame buffer using the
* mechanism appropriate for the system state being called
* from quiesced or normal (ie. use polled I/O vs. layered ioctls)
*/
static void
struct vis_consdisplay *pda,
enum called_from called_from)
{
if (called_from == CALLED_FROM_STANDALONE)
else
}
/*
* Copy a rectangle from one location to another on the frame buffer
* using the mechanism appropriate for the system state being called
* from, quiesced or normal (ie. use polled I/O vs. layered ioctls)
*/
void
struct vis_conscopy *pca,
enum called_from called_from)
{
if (called_from == CALLED_FROM_STANDALONE)
else
}
/*
* Display or hide a rectangular block text cursor of a specificsize
* at a specific location on frame buffer* using the mechanism
* appropriate for the system state being called from, quisced or
* normal (ie. use polled I/O vs. layered ioctls).
*/
static void
struct vis_conscursor *pca,
enum called_from called_from)
{
if (called_from == CALLED_FROM_STANDALONE)
else
}
/*
* send the appropriate control message or set state based on the
* value of the control character ch
*/
static void
enum called_from called_from)
{
switch (ch) {
case A_BEL:
break;
case A_BS:
credp, called_from);
break;
case A_HT:
break;
case A_NL:
/*
* tem_send_data(tem, credp, called_from);
* tem_new_line(tem, credp, called_from);
* break;
*/
case A_VT:
break;
case A_FF:
break;
case A_CR:
break;
case A_ESC:
break;
case A_CSI:
{
int i;
tems->a_curparam = 0;
tems->a_paramval = 0;
/* clear the parameters */
for (i = 0; i < TEM_MAXPARAMS; i++)
}
break;
case A_GS:
break;
default:
break;
}
}
/*
* if parameters [0..count - 1] are not set, set them to the value
* of newparam.
*/
static void
{
int i;
for (i = 0; i < count; i++) {
}
}
/*
* select graphics mode based on the param vals stored in a_params
*/
static void
{
int curparam;
int count = 0;
int param;
do {
switch (param) {
case -1:
case 0:
} else {
}
break;
case 1: /* Bold Intense */
break;
case 5: /* Blink */
break;
case 7: /* Reverse video */
} else {
}
break;
case 30: /* black (grey) foreground */
case 31: /* red (light red) foreground */
case 32: /* green (light green) foreground */
case 33: /* brown (yellow) foreground */
case 34: /* blue (light blue) foreground */
case 35: /* magenta (light magenta) foreground */
case 36: /* cyan (light cyan) foreground */
case 37: /* white (bright white) foreground */
break;
case 40: /* black (grey) background */
case 41: /* red (light red) background */
case 42: /* green (light green) background */
case 43: /* brown (yellow) background */
case 44: /* blue (light blue) background */
case 45: /* magenta (light magenta) background */
case 46: /* cyan (light cyan) background */
case 47: /* white (bright white) background */
break;
default:
break;
}
count++;
curparam--;
} while (curparam > 0);
}
/*
* perform the appropriate action for the escape sequence
*
* General rule: This code does not validate the arguments passed.
* It assumes that the next lower level will do so.
*/
static void
enum called_from called_from)
{
int i;
int row;
int col;
switch (ch) {
case 'm': /* select terminal graphics mode */
break;
case '@': /* insert char */
credp, called_from);
break;
case 'A': /* cursor up */
credp, called_from);
break;
case 'd': /* VPA - vertical position absolute */
credp, called_from);
break;
case 'e': /* VPR - vertical position relative */
case 'B': /* cursor down */
credp, called_from);
break;
case 'a': /* HPR - horizontal position relative */
case 'C': /* cursor right */
credp, called_from);
break;
case '`': /* HPA - horizontal position absolute */
credp, called_from);
break;
case 'D': /* cursor left */
credp, called_from);
break;
case 'E': /* CNL cursor next line */
credp, called_from);
break;
case 'F': /* CPL cursor previous line */
credp, called_from);
break;
case 'G': /* cursor horizontal position */
credp, called_from);
break;
case 'g': /* clear tabs */
break;
case 'f': /* HVP Horizontal and Vertical Position */
case 'H': /* CUP position cursor */
credp, called_from);
break;
case 'I': /* CHT - Cursor Horizontal Tab */
/* Not implemented */
break;
case 'J': /* ED - Erase in Display */
case 0:
/* erase cursor to end of screen */
/* FIRST erase cursor to end of line */
/* THEN erase lines below the cursor */
row++) {
}
break;
case 1:
/* erase beginning of screen to cursor */
/* FIRST erase lines above the cursor */
for (row = 0;
row++) {
}
/* THEN erase beginning of line to cursor */
0, credp, called_from);
break;
case 2:
/* erase whole screen */
for (row = 0;
row++) {
}
break;
}
break;
case 'K': /* EL - Erase in Line */
case 0:
/* erase cursor to end of line */
credp, called_from);
break;
case 1:
/* erase beginning of line to cursor */
0, credp, called_from);
break;
case 2:
/* erase whole line */
0, credp, called_from);
break;
}
break;
case 'L': /* insert line */
credp, called_from);
break;
case 'M': /* delete line */
credp, called_from);
break;
case 'P': /* DCH - delete char */
credp, called_from);
break;
case 'S': /* scroll up */
tem_scroll(tem, 0,
credp, called_from);
break;
case 'T': /* scroll down */
tem_scroll(tem, 0,
credp, called_from);
break;
case 'X': /* erase char */
credp, called_from);
break;
case 'Z': /* cursor backward tabulation */
/*
* Rule exception - We do sanity checking here.
*
* Restrict the count to a sane value to keep from
* looping for a long time. There can't be more than one
* tab stop per column, so use that as a limit.
*/
break;
}
}
/*
* Gather the parameters of an ANSI escape sequence
*/
static void
{
return; /* Return immediately */
} else {
if (tems->a_gotparam) {
/* get the parameter value */
}
tems->a_curparam++;
}
if (ch == ';') {
/* Restart parameter search */
} else {
/* Handle escape sequence */
}
}
}
/*
* Add character to internal buffer.
* When its full, send it to the next layer.
*/
static void
{
/* buffer up the character until later */
}
}
static void
{
}
static void
{
}
static void
{
int row;
/*
* Sanity checking notes:
* . a_nscroll was validated when it was set.
* . Regardless of that, tem_scroll and tem_mv_cursor will prevent
* anything bad from happening.
*/
tem_scroll(tem, 0,
credp, called_from);
} else { /* no scroll */
/*
* implement Esc[#r when # is zero. This means no
* scroll but just return cursor to top of screen,
* do not clear screen.
*/
row = 0;
}
}
credp, called_from);
/* erase rest of cursor line */
credp, called_from);
}
}
static void
enum called_from called_from)
{
if (tems->a_outindex != 0) {
} else {
}
/*
* Call the primitive to render this data.
*/
credp, called_from);
tems->a_outindex = 0;
}
}
/*
* We have just done something to the current output point. Reset the start
* point for the buffered data in a_outbuf. There shouldn't be any data
* buffered yet.
*/
void
{
}
/*
* State machine parser based on the current state and character input
* major terminations are to control character or normal character
*/
static void
{
int i;
else
/* Display */
return;
}
/* In <ESC> sequence */
return;
}
switch (ch) {
case '?':
return;
case '=':
return;
case 's':
/*
* As defined below, this sequence
* saves the cursor. However, Sun
* defines ESC[s as reset. We resolved
* the conflict by selecting reset as it
* is exported in the termcap file for
* sun-mon, while the "save cursor"
* definition does not exist anywhere in
* However, having no coherent
* definition of reset, we have not
* implemented it.
*/
/*
* Original code
* tems->a_r_cursor.row = tems->a_c_cursor.row;
* tems->a_r_cursor.col = tems->a_c_cursor.col;
* tems->a_state = A_STATE_START;
*/
return;
case 'u':
return;
case 'p': /* sunbow */
/*
* Don't set anything if we are
* already as we want to be.
*/
/*
* If we have switched the characters to be the
* inverse from the screen, then switch them as
* well to keep them the inverse of the screen.
*/
} else {
}
}
return;
case 'q': /* sunwob */
/*
* Don't set anything if we are
* already where as we want to be.
*/
/*
* If we have switched the characters to be the
* inverse from the screen, then switch them as
* well to keep them the inverse of the screen.
*/
} else {
}
}
return;
case 'r': /* sunscrl */
/*
* Rule exception: check for validity here.
*/
return;
default:
return;
}
}
/* Previous char was <ESC> */
if (ch == '[') {
tems->a_curparam = 0;
tems->a_paramval = 0;
/* clear the parameters */
for (i = 0; i < TEM_MAXPARAMS; i++)
} else {
if (ch == 'c')
/* ESC c resets display */
else if (ch == 'H')
/* ESC H sets a tab */
else if (ch == '7') {
/* ESC 7 Save Cursor position */
} else if (ch == '8')
/* ESC 8 Restore Cursor position */
/* check for control chars */
else if (ch < ' ')
else
}
}
/* ARGSUSED */
static void
{
if (called_from == CALLED_FROM_STANDALONE)
else
}
static void
{
int row;
int lines_affected;
if (count > lines_affected)
if (count <= 0)
return;
switch (direction) {
case TEM_SCROLL_UP:
if (count < lines_affected) {
}
}
break;
case TEM_SCROLL_DOWN:
if (count < lines_affected) {
credp, called_from);
}
}
break;
}
}
static void
{
int rows;
int cols;
return;
return;
return;
}
static void
{
count < 0)
return;
/*
* Note that very large values of "count" could cause col+count
* to overflow, so we check "count" independently.
*/
}
void
{
struct vis_consdisplay da;
}
/*
* This function is used to blit a rectangular color image,
* unperturbed on the underlying framebuffer, to render
* icons and pictures. The data is a pixel pattern that
* fills a rectangle bounded to the width and height parameters.
* The color pixel data must to be pre-adjusted by the caller
* for the current video depth.
*
* This function is unused now.
*/
void
{
struct vis_consdisplay da;
}
void
{
struct vis_conscopy da;
}
void
enum called_from called_from)
{
struct vis_consdisplay da;
}
void
{
struct vis_consdisplay da;
int i;
for (i = 0; i < count; i++) {
}
}
void
enum called_from called_from)
{
struct vis_conscopy ma;
/*
* Clear OBP output above our kernel console term
* when our kernel console term begins to scroll up,
* we hope it is user friendly.
* (Also see comments on tem_pix_clear_prom_output)
*
* This is only one time call.
*/
}
/*
* Check if we're in process of clearing OBP's columns area,
* which only happens when term scrolls up a whole line.
*/
/*
* We need to clear OBP's columns area outside our kernel
* console term. So that we set ma.e_col to entire row here.
*/
} else {
}
/* We have scrolled up (s_row - t_row) rows. */
if (tems->first_line <= 0) {
/* All OBP rows have been cleared. */
tems->first_line = 0;
}
}
}
/*
* This function only clears count of columns in one row
*/
void
enum called_from called_from)
{
}
/*
* This function clears OBP output above our kernel console term area
* because OBP's term may have a bigger terminal window than that of
* our kernel console term. So we need to clear OBP output garbage outside
* of our kernel console term at a proper time, which is when the first
* row output of our kernel console term scrolls at the first screen line.
*
* _________________________________
* | _____________________ | ---> OBP's bigger term window
* | | | |
* |___| | |
* | | | | |
* | | | | |
* |_|_|___________________|_______|
* | | | ---> first line
* | |___________________|---> our kernel console term window
* |
* |---> columns area to be cleared
*
* This function only takes care of the output above our kernel console term,
* and tem_prom_scroll_up takes care of columns area outside of our kernel
* console term.
*/
static void
enum called_from called_from)
{
}
/*
* clear the whole screen for pixel mode
*/
static void
enum called_from called_from)
{
/*
* Since the whole screen is cleared, we don't need
* to clear OBP output later.
*/
if (tems->first_line > 0) {
tems->first_line = 0;
}
}
/*
* clear the whole screen
*/
static void
{
int row;
}
return;
}
}
static void
{
int i;
tabstop = 0;
break;
}
}
}
static void
{
int i;
break;
}
}
}
static void
{
int i;
int j;
return;
return;
}
return;
return;
}
}
}
static void
{
int i;
int j;
switch (action) {
case 3: /* clear all tabs */
break;
case 0: /* clr tab at cursor */
return;
}
}
break;
}
}
static void
{
/*
* Sanity check and bounds enforcement. Out of bounds requests are
* clipped to the screen boundaries. This seems to be what SPARC
* does.
*/
if (row < 0)
row = 0;
if (col < 0)
col = 0;
}
/* ARGSUSED */
void
{
int j;
tems->a_outindex = 0;
tems->a_curparam = 0;
tems->a_paramval = 0;
/*
* set up the initial tab stops
*/
for (j = 0; j < TEM_MAXPARAMS; j++)
}
void
{
if (clear_txt) {
}
}
static void
int count,
int direction,
enum called_from called_from)
{
int rest_of_line;
if (count > rest_of_line)
if (count <= 0)
return;
switch (direction) {
case TEM_SHIFT_LEFT:
if (count < rest_of_line) {
credp, called_from);
}
break;
case TEM_SHIFT_RIGHT:
if (count < rest_of_line) {
credp, called_from);
}
break;
}
}
void
{
struct vis_conscursor ca;
if (action == VIS_GET_CURSOR) {
}
}
void
{
struct vis_conscursor ca;
tems->a_p_offset.y;
tems->a_p_offset.x;
} else {
}
} else {
}
}
}
#define BORDER_PIXELS 10
void
{
/*
* Find best font for these dimensions, or use default
*
* A 1 pixel border is the absolute minimum we could have
* as a border around the text window (BORDER_PIXELS = 2),
* however a slightly larger border not only looks better
* but for the fonts currently statically built into the
* emulator causes much better font selection for the
* normal range of screen resolutions.
*/
break;
}
}
/*
* The minus 2 is to make sure we have at least a 1 pixel
* boarder around the entire screen.
*/
if (font_selected == NULL) {
}
}
sizeof (f->char_ptr));
}
/*
* bit_to_pix4 is for 4-bit frame buffers. It will write one output byte
* for each 2 bits of input bitmap. It inverts the input bits before
* doing the output translation, for reverse video.
*
* Assuming foreground is 0001 and background is 0000...
* An input data byte of 0x53 will output the bit pattern
* 00000001 00000001 00000000 00010001.
*/
void
uchar_t c,
{
int row;
int byte;
int i;
int bytes_wide;
for (i = 0; i < 4; i++) {
switch (nibblett) {
case 0x0:
break;
case 0x1:
break;
case 0x2:
break;
case 0x3:
break;
}
}
}
}
}
/*
* bit_to_pix8 is for 8-bit frame buffers. It will write one output byte
* for each bit of input bitmap. It inverts the input bits before
* doing the output translation, for reverse video.
*
* Assuming foreground is 00000001 and background is 00000000...
* An input data byte of 0x53 will output the bit pattern
* 0000000 000000001 00000000 00000001 00000000 00000000 00000001 00000001.
*/
void
uchar_t c,
{
int row;
int byte;
int i;
int bytes_wide;
mask = 0x80;
for (i = 0; i < nbits; i++) {
}
}
}
}
/*
* bit_to_pix24 is for 24-bit frame buffers. It will write four output bytes
* for each bit of input bitmap. It inverts the input bits before
* doing the output translation, for reverse video. Note that each
* 24-bit RGB value is finally stored in a 32-bit unsigned int, with the
* high-order byte set to zero.
*
* Assuming foreground is 00000000 11111111 11111111 11111111
* and background is 00000000 00000000 00000000 00000000
* An input data byte of 0x53 will output the bit pattern
*
* 00000000 00000000 00000000 00000000
* 00000000 11111111 11111111 11111111
* 00000000 00000000 00000000 00000000
* 00000000 11111111 11111111 11111111
* 00000000 00000000 00000000 00000000
* 00000000 00000000 00000000 00000000
* 00000000 11111111 11111111 11111111
* 00000000 11111111 11111111 11111111
*
*/
void
uchar_t c,
{
int row;
int byte;
int i;
int bytes_wide;
for (i = 0; i < nbits; i++) {
fg_color32 : bg_color32);
}
}
}
}
/* ARGSUSED */
{
}
{
return (fg_brt_xlate[ansi]);
else
return (fg_dim_xlate[ansi]);
}
static void
{
} else {
}
}
/*
* Clear a rectangle of screen for pixel mode.
*
* arguments:
* row: start row#
* nrows: the number of rows to clear
* offset_y: the offset of height in pixels to begin clear
* col: start col#
* ncols: the number of cols to clear
* offset_x: the offset of width in pixels to begin clear
* scroll_up: whether this function is called during sroll up,
* which is called only once.
*/
void
enum called_from called_from)
{
struct vis_consdisplay da;
int i, j;
int row_add = 0;
if (sroll_up)
for (j = 0; j < ncols; j++) {
}
}
}