summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authoriedowse <iedowse@FreeBSD.org>2005-08-18 01:39:43 +0000
committeriedowse <iedowse@FreeBSD.org>2005-08-18 01:39:43 +0000
commit11293f3595866129f0cead6cc0cc9feb2f9fc1e7 (patch)
tree2bd3f8b92928c4902f341d508484eca99bcf78ce /sys
parent1161399eefe49cc63043fec5cc9e5ba8c9a2cb32 (diff)
downloadFreeBSD-src-11293f3595866129f0cead6cc0cc9feb2f9fc1e7.zip
FreeBSD-src-11293f3595866129f0cead6cc0cc9feb2f9fc1e7.tar.gz
Add a "comconsole_speed" loader variable that can be used to change
the serial console speed (i386 and amd64 only). If the previous stage boot loader requested a serial console (RB_SERIAL or RB_MULTIPLE) then the default speed is determined from the current serial port speed. Otherwise it is set to 9600 or the value of BOOT_COMCONSOLE_SPEED at compile time. This makes it possible to set the serial port speed once in /boot.config and the setting will propagate to boot2, loader and the kernel serial console.
Diffstat (limited to 'sys')
-rw-r--r--sys/boot/common/loader.815
-rw-r--r--sys/boot/forth/loader.conf1
-rw-r--r--sys/boot/forth/loader.conf.514
-rw-r--r--sys/boot/i386/libi386/comconsole.c117
4 files changed, 136 insertions, 11 deletions
diff --git a/sys/boot/common/loader.8 b/sys/boot/common/loader.8
index 13331c1..3e99eea 100644
--- a/sys/boot/common/loader.8
+++ b/sys/boot/common/loader.8
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd May 27, 2005
+.Dd August 18, 2005
.Dt LOADER 8
.Os
.Sh NAME
@@ -392,6 +392,19 @@ by the kernel during the boot phase.
List of semicolon-separated search path for bootable kernels.
The default is
.Dq Li kernel .
+.It Va comconsole_speed
+Defines the speed of the serial console (i386 and amd64 only).
+If the previous boot stage indicated that a serial console is in use
+then this variable is initialized to the current speed of the console
+serial port.
+Otherwise it is set to 9600 unless this was overridden using the
+.Va BOOT_COMCONSOLE_SPEED
+variable when
+.Nm
+was compiled.
+Changes to the
+.Va comconsole_speed
+variable take effect immediately.
.It Va console
Defines the current console or consoles.
Multiple consoles may be specified.
diff --git a/sys/boot/forth/loader.conf b/sys/boot/forth/loader.conf
index 8f97c1f..fcaf4e5 100644
--- a/sys/boot/forth/loader.conf
+++ b/sys/boot/forth/loader.conf
@@ -47,6 +47,7 @@ loader_color="NO" # Set this to YES to enable splash screen colors
# allowed to interrupt autoboot process and
# escape to the loader prompt
#beastie_disable="NO" # Turn the beastie boot menu on and off
+#comconsole_speed="9600" # Set the current serial console speed
#console="vidconsole" # A comma separated list of console(s)
#currdev="disk1s1a" # Set the current device
module_path="/boot/modules" # Set the module search path
diff --git a/sys/boot/forth/loader.conf.5 b/sys/boot/forth/loader.conf.5
index 4ee8b98..9d113e5 100644
--- a/sys/boot/forth/loader.conf.5
+++ b/sys/boot/forth/loader.conf.5
@@ -23,7 +23,7 @@
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD$
-.Dd November 7, 2004
+.Dd August 18, 2005
.Dt LOADER.CONF 5
.Os
.Sh NAME
@@ -164,6 +164,18 @@ a bitmap will be loaded to be displayed on screen while booting.
.Pq Dq Pa /boot/splash.bmp
Name of the bitmap to be loaded.
Any other name can be used.
+.It Va comconsole_speed
+.Po Dq 9600
+or the value of the
+.Va BOOT_COMCONSOLE_SPEED
+variable when
+.Xr loader 8
+was compiled
+.Pc .
+Sets the speed of the serial console.
+If the previous boot loader stage specified that a serial console
+is in use then the default speed is determined from the current
+serial port speed setting.
.It Va console
.Pq Dq vidconsole
.Dq comconsole
diff --git a/sys/boot/i386/libi386/comconsole.c b/sys/boot/i386/libi386/comconsole.c
index 1b08d9b..fa2b1b5 100644
--- a/sys/boot/i386/libi386/comconsole.c
+++ b/sys/boot/i386/libi386/comconsole.c
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
#define COMC_FMT 0x3 /* 8N1 */
#define COMC_TXWAIT 0x40000 /* transmit timeout */
#define COMC_BPS(x) (115200 / (x)) /* speed to DLAB divisor */
+#define COMC_DIV2BPS(x) (115200 / (x)) /* DLAB divisor to speed */
#ifndef COMPORT
#define COMPORT 0x3f8
@@ -47,9 +48,15 @@ static void comc_probe(struct console *cp);
static int comc_init(int arg);
static void comc_putchar(int c);
static int comc_getchar(void);
+static int comc_getspeed(void);
static int comc_ischar(void);
+static int comc_parsespeed(const char *string);
+static void comc_setup(int speed);
+static int comc_speed_set(struct env_var *ev, int flags,
+ const void *value);
static int comc_started;
+static int comc_curspeed;
struct console comconsole = {
"comconsole",
@@ -65,8 +72,36 @@ struct console comconsole = {
static void
comc_probe(struct console *cp)
{
+ char speedbuf[16];
+ char *cons, *speedenv;
+ int speed;
+
/* XXX check the BIOS equipment list? */
cp->c_flags |= (C_PRESENTIN | C_PRESENTOUT);
+
+ if (comc_curspeed == 0) {
+ comc_curspeed = COMSPEED;
+ /*
+ * Assume that the speed was set by an earlier boot loader if
+ * comconsole is already the preferred console.
+ */
+ cons = getenv("console");
+ if ((cons != NULL && strcmp(cons, comconsole.c_name) == 0) ||
+ getenv("boot_multicons") != NULL) {
+ comc_curspeed = comc_getspeed();
+ }
+ speedenv = getenv("comconsole_speed");
+ if (speedenv != NULL) {
+ speed = comc_parsespeed(speedenv);
+ if (speed > 0)
+ comc_curspeed = speed;
+ }
+
+ sprintf(speedbuf, "%d", comc_curspeed);
+ unsetenv("comconsole_speed");
+ env_setenv("comconsole_speed", EV_VOLATILE, speedbuf, comc_speed_set,
+ env_nounset);
+ }
}
static int
@@ -76,15 +111,7 @@ comc_init(int arg)
return 0;
comc_started = 1;
- outb(COMPORT + com_cfcr, CFCR_DLAB | COMC_FMT);
- outb(COMPORT + com_dlbl, COMC_BPS(COMSPEED) & 0xff);
- outb(COMPORT + com_dlbh, COMC_BPS(COMSPEED) >> 8);
- outb(COMPORT + com_cfcr, COMC_FMT);
- outb(COMPORT + com_mcr, MCR_RTS | MCR_DTR);
-
- do
- inb(COMPORT + com_data);
- while (inb(COMPORT + com_lsr) & LSR_RXRDY);
+ comc_setup(comc_curspeed);
return(0);
}
@@ -112,3 +139,75 @@ comc_ischar(void)
{
return(inb(COMPORT + com_lsr) & LSR_RXRDY);
}
+
+static int
+comc_speed_set(struct env_var *ev, int flags, const void *value)
+{
+ int speed;
+
+ if (value == NULL || (speed = comc_parsespeed(value)) <= 0) {
+ printf("Invalid speed\n");
+ return (CMD_ERROR);
+ }
+
+ if (comc_started && comc_curspeed != speed)
+ comc_setup(speed);
+
+ env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
+
+ return (CMD_OK);
+}
+
+static void
+comc_setup(int speed)
+{
+
+ comc_curspeed = speed;
+
+ outb(COMPORT + com_cfcr, CFCR_DLAB | COMC_FMT);
+ outb(COMPORT + com_dlbl, COMC_BPS(speed) & 0xff);
+ outb(COMPORT + com_dlbh, COMC_BPS(speed) >> 8);
+ outb(COMPORT + com_cfcr, COMC_FMT);
+ outb(COMPORT + com_mcr, MCR_RTS | MCR_DTR);
+
+ do
+ inb(COMPORT + com_data);
+ while (inb(COMPORT + com_lsr) & LSR_RXRDY);
+}
+
+static int
+comc_parsespeed(const char *speedstr)
+{
+ char *p;
+ int speed;
+
+ speed = strtol(speedstr, &p, 0);
+ if (p == speedstr || *p != '\0' || speed <= 0)
+ return (-1);
+
+ return (speed);
+}
+
+static int
+comc_getspeed(void)
+{
+ u_int divisor;
+ u_char dlbh;
+ u_char dlbl;
+ u_char cfcr;
+
+ cfcr = inb(COMPORT + com_cfcr);
+ outb(COMPORT + com_cfcr, CFCR_DLAB | cfcr);
+
+ dlbl = inb(COMPORT + com_dlbl);
+ dlbh = inb(COMPORT + com_dlbh);
+
+ outb(COMPORT + com_cfcr, cfcr);
+
+ divisor = dlbh << 8 | dlbl;
+
+ /* XXX there should be more sanity checking. */
+ if (divisor == 0)
+ return (COMSPEED);
+ return (COMC_DIV2BPS(divisor));
+}
OpenPOWER on IntegriCloud