loader: update elf module code from FreeBSD
[dragonfly.git] / sys / boot / common / console.c
bloba715b9d50b352824f5de62fe4b985b8fda3c3242
1 /*-
2 * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
26 * $FreeBSD: src/sys/boot/common/console.c,v 1.6 2003/08/25 23:30:41 obrien Exp $
27 * $DragonFly: src/sys/boot/common/console.c,v 1.5 2004/06/26 02:26:20 dillon Exp $
30 #include <stand.h>
31 #include <string.h>
33 #include "bootstrap.h"
35 * Core console support
38 static int cons_set(struct env_var *ev, int flags, const void *value);
39 static int cons_find(const char *name);
42 * Detect possible console(s) to use. The first probed console
43 * is marked active. Also create the console variable.
45 * XXX Add logic for multiple console support.
47 void
48 cons_probe(void)
50 int cons;
51 int active;
52 char *prefconsole;
55 * Probe all available consoles
57 for (cons = 0; consoles[cons] != NULL; cons++) {
58 consoles[cons]->c_flags = 0;
59 consoles[cons]->c_probe(consoles[cons]);
63 * Get our console preference. If there is no preference, all
64 * available consoles will be made active in parallel. Otherwise
65 * only the specified console is activated.
67 active = -1;
68 if ((prefconsole = getenv("console")) != NULL) {
69 for (cons = 0; consoles[cons] != NULL; cons++) {
70 if (strcmp(prefconsole, consoles[cons]->c_name) == 0) {
71 if (consoles[cons]->c_flags & (C_PRESENTIN | C_PRESENTOUT))
72 active = cons;
75 unsetenv("console");
76 if (active >= 0) {
77 env_setenv("console", EV_VOLATILE, consoles[active]->c_name,
78 cons_set, env_nounset);
83 * Active the active console or all consoles if active is -1.
85 for (cons = 0; consoles[cons] != NULL; cons++) {
86 if ((active == -1 || cons == active) &&
87 (consoles[cons]->c_flags & (C_PRESENTIN|C_PRESENTOUT))
88 ) {
89 consoles[cons]->c_flags |= (C_ACTIVEIN | C_ACTIVEOUT);
90 consoles[cons]->c_init(0);
91 printf("Console: %s\n", consoles[cons]->c_desc);
96 int
97 getchar(void)
99 int cons;
100 int rv;
102 /* Loop forever polling all active consoles */
103 for(;;) {
104 for (cons = 0; consoles[cons] != NULL; cons++) {
105 if ((consoles[cons]->c_flags & C_ACTIVEIN) &&
106 ((rv = consoles[cons]->c_in()) != -1)
108 return(rv);
115 ischar(void)
117 int cons;
119 for (cons = 0; consoles[cons] != NULL; cons++)
120 if ((consoles[cons]->c_flags & C_ACTIVEIN) &&
121 (consoles[cons]->c_ready() != 0))
122 return(1);
123 return(0);
126 #ifdef COMCONSOLE_DEBUG
128 static int
129 isa_inb(int port)
131 u_char data;
133 if (__builtin_constant_p(port) &&
134 (((port) & 0xffff) < 0x100) &&
135 ((port) < 0x10000)) {
136 __asm __volatile("inb %1,%0" : "=a" (data) : "id" ((u_short)(port)));
137 } else {
138 __asm __volatile("inb %%dx,%0" : "=a" (data) : "d" (port));
140 return(data);
143 static void
144 isa_outb(int port, int value)
146 u_char al = value;
148 if (__builtin_constant_p(port) &&
149 (((port) & 0xffff) < 0x100) &&
150 ((port) < 0x10000)) {
151 __asm __volatile("outb %0,%1" : : "a" (al), "id" ((u_short)(port)));
152 } else {
153 __asm __volatile("outb %0,%%dx" : : "a" (al), "d" (port));
157 #endif
159 void
160 putchar(int c)
162 int cons;
164 #ifdef COMCONSOLE_DEBUG
165 if ((consoles[1]->c_flags & C_ACTIVEOUT) == 0) {
166 while ((isa_inb(0x3f8+5) & 0x20) == 0) /* wait tx ready */
168 isa_outb(0x3f8, c); /* output */
170 #endif
172 /* Expand newlines */
173 if (c == '\n')
174 putchar('\r');
176 for (cons = 0; consoles[cons] != NULL; cons++) {
177 if (consoles[cons]->c_flags & C_ACTIVEOUT)
178 consoles[cons]->c_out(c);
182 static int
183 cons_find(const char *name)
185 int cons;
187 for (cons = 0; consoles[cons] != NULL; cons++)
188 if (!strcmp(consoles[cons]->c_name, name))
189 return(cons);
190 return(-1);
195 * Select a console.
197 * XXX Note that the console system design allows for some extension
198 * here (eg. multiple consoles, input/output only, etc.)
200 static int
201 cons_set(struct env_var *ev, int flags, const void *value)
203 int cons, active;
205 if ((value == NULL) || ((active = cons_find(value)) == -1)) {
206 if (value != NULL)
207 printf("no such console '%s'\n", (char *)value);
208 printf("Available consoles:\n");
209 for (cons = 0; consoles[cons] != NULL; cons++)
210 printf(" %s\n", consoles[cons]->c_name);
211 return(CMD_ERROR);
214 /* disable all current consoles */
215 for (cons = 0; consoles[cons] != NULL; cons++)
216 consoles[cons]->c_flags &= ~(C_ACTIVEIN | C_ACTIVEOUT);
218 /* enable selected console */
219 consoles[active]->c_flags |= C_ACTIVEIN | C_ACTIVEOUT;
220 consoles[active]->c_init(0);
222 env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
223 return(CMD_OK);