console.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (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 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/bootsvcs.h>
#include "serial.h"
#include "chario.h"
#include "vga.h"
#include "console.h"
#include "debug.h"
#include "graphics.h"
#include "bootprop.h"
static int cons_color = CONS_COLOR;
int console = CONS_SCREEN_TEXT;
/* or CONS_SCREEN_GRAPHICS, CONS_TTYA, CONS_TTYB */
static int serial_ischar(void);
static int serial_getchar(void);
static void serial_putchar(int);
static void serial_adjust_prop(void);
static int console_state = 0;
/* Clear the screen and initialize VIDEO, XPOS and YPOS. */
static void
clear_screen(void)
{
/*
* XXX should set vga mode so we don't depend on the
* state left by the boot loader
*/
vga_setpos(0, 0);
}
void
text_init(void)
{
set_videomode(0x3);
clear_screen();
}
/* Put the character C on the screen. */
static void
screen_putchar(int c)
{
switch (c) {
case '\r':
vga_setpos(row, 0);
break;
case '\b':
if (col > 0)
break;
case '\n':
else
break;
default:
vga_drawc(c, cons_color);
else {
vga_setpos(row, 0);
}
break;
}
}
/* serial port stuff */
static int port;
static void
serial_init(void)
{
extern void mdelay();
/* initialize only once */
if (port != 0)
return;
/*
* wait 2 seconds for serial console redirection to settle
* NOTE we only need to wait if BIOS console redirection
* is enabled, but we can't really tell without working
* through a scary Microsoft license.
*/
mdelay(2000);
switch (console) {
case CONS_TTYA:
port = 0x3f8;
break;
case CONS_TTYB:
port = 0x2f8;
break;
}
/*
* 82510 chip is present
*/
} else {
/*
* set the UART in FIFO mode if it has FIFO buffers.
* use 16550 fifo reset sequence specified in NS
* application note. disable fifos until chip is
* initialized.
*/
/*
* no fifo buffers so disable fifos.
* this is true for 8250's
*/
}
}
/* disable interrupts */
/* adjust setting based on tty properties */
/*
* Do a full reset to match console behavior.
* In verbose mode (-V), we only reset ansi attributes,
* leaving existing output on screen.
* 0x1B + c - reset everything
* 0x1B +
* [ - attribute change (blick, inverse, color, etc.)
* 0 - attribute value
* m - terminate escape sequence
*
*/
if (verbosemode) {
serial_putchar(0x1B);
serial_putchar('[');
serial_putchar('0');
serial_putchar('m');
} else {
serial_putchar(0x1B);
serial_putchar('c');
}
}
/* adjust serial port based on properties */
static void
serial_adjust_prop(void)
{
int plen;
char *p;
/* property is of the form: "9600,8,n,1,-" */
if (strcmp(p, "110") == 0)
else if (strcmp(p, "150") == 0)
else if (strcmp(p, "300") == 0)
else if (strcmp(p, "600") == 0)
else if (strcmp(p, "1200") == 0)
else if (strcmp(p, "2400") == 0)
else if (strcmp(p, "4800") == 0)
else if (strcmp(p, "19200") == 0)
else if (strcmp(p, "38400") == 0)
else if (strcmp(p, "57600") == 0)
else if (strcmp(p, "115200") == 0)
else
/* set baud */
if (p) {
switch (*p) {
case '5':
break;
case '6':
break;
case '7':
break;
case '8':
default:
break;
}
}
if (p) {
switch (*p) {
case 'n':
lcr |= PARITY_NONE;
break;
case 'o':
lcr |= PARITY_ODD;
break;
case 'e':
default:
lcr |= PARITY_EVEN;
break;
}
}
if (p) {
switch (*p) {
case '1':
/* STOP1 is 0 */
break;
default:
break;
}
}
/* set parity bits */
}
char *p;
mcr = 0;
/* set modem control bits */
}
}
void
console_init(char *bootstr)
{
char *cons;
if (cons) {
}
/*
* If no console device specified, default to text.
* Remember what was specified for second phase.
*/
if (console == CONS_INVALID)
switch (console) {
case CONS_TTYA:
case CONS_TTYB:
/* leave initialization till later, when we know tty mode */
break;
case CONS_SCREEN_TEXT:
default:
clear_screen();
kb_init();
break;
/*
* if console is CONS_SCREEN_GRAPHICS,
* initialize it in console_init2()
*/
}
}
/*
* Second phase of possible console redirection,
* based on input-device & output-device eeprom(1M) properties.
* Also support a unified "console" property.
*/
void
{
int cons = CONS_INVALID;
if (console_state == CONS_INVALID) {
if (consoledev) {
}
if (cons == CONS_INVALID) {
if (inputdev) {
}
if (outputdev) {
}
}
if (cons == CONS_INVALID)
switch (console) {
case CONS_TTYA:
case CONS_TTYB:
if (console_state != CONS_TTYA &&
console_state != CONS_TTYB) {
serial_init();
}
break;
case CONS_SCREEN_TEXT:
if (console_state != CONS_SCREEN_TEXT) {
clear_screen();
kb_init();
}
break;
}
}
/* special handling for graphics boot and serial console */
switch (console) {
case CONS_TTYA:
case CONS_TTYB:
serial_init();
break;
case CONS_SCREEN_GRAPHICS:
if (!graphics_init())
printf("failed to initialize "
"console to graphics mode\n");
break;
};
}
static void
serial_putchar(int c)
{
int checks = 10000;
;
}
static int
serial_getchar(void)
{
while (serial_ischar() == 0)
;
SERIAL_PARITY | SERIAL_OVERRUN)) {
if (lsr & SERIAL_OVERRUN) {
printf("silo overflow\n");
} else {
/* Toss the garbage */
return (0);
}
}
}
static int
serial_ischar(void)
{
}
static void
_doputchar(int c)
{
switch (console) {
case CONS_TTYA:
case CONS_TTYB:
serial_putchar(c);
return;
case CONS_SCREEN_TEXT:
screen_putchar(c);
return;
case CONS_SCREEN_GRAPHICS:
if (verbosemode)
graphics_putchar(c);
}
}
void
putchar(int c)
{
static int bhcharpos = 0;
if (c == '\t') {
do {
_doputchar(' ');
} while (++bhcharpos % 8);
return;
} else if (c == '\n' || c == '\r') {
bhcharpos = 0;
_doputchar('\r');
_doputchar(c);
return;
} else if (c == '\b') {
if (bhcharpos)
bhcharpos--;
_doputchar(c);
return;
}
bhcharpos++;
_doputchar(c);
}
int
getchar(void)
{
switch (console) {
case CONS_TTYA:
case CONS_TTYB:
return (serial_getchar());
default:
return (kb_getchar());
}
}
int
ischar(void)
{
switch (console) {
case CONS_TTYA:
case CONS_TTYB:
return (serial_ischar());
default:
return (kb_ischar());
}
}
/*
* Read from the console (using getchar) into string str,
* until a carriage return or until n-1 characters are read.
* Null terminate the string, and return.
* This all is made complicated by the fact that we must
* do our own echoing during input.
* N.B.: Returns the *number of characters in str*.
*/
int
{
int c;
int t;
char *p;
p = str;
c = 0;
while ((t = getchar()) != '\r') {
putchar(t);
if (t == '\b') {
if (c) {
printf(" \b");
c--; p--;
} else
putchar(' ');
continue;
}
if (c < n - 1) {
*p++ = t;
c++;
}
}
putchar('\n');
*p = '\0';
return (c);
}
/*PRINTFLIKE1*/
void
{
}
/* setup boot syscall fields needed by the kernel */
static struct boot_syscalls sc = {
};