diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/boot/pc/console.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/boot/pc/console.c')
-rwxr-xr-x | sys/src/boot/pc/console.c | 239 |
1 files changed, 239 insertions, 0 deletions
diff --git a/sys/src/boot/pc/console.c b/sys/src/boot/pc/console.c new file mode 100755 index 000000000..3afb74c07 --- /dev/null +++ b/sys/src/boot/pc/console.c @@ -0,0 +1,239 @@ +#include "u.h" +#include "lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" + +IOQ consiq; +IOQ consoq; + +static int useuart; + +int debug = 0; + +void +kbdchar(int c) +{ + c &= 0x7F; + if(c == 0x10) + warp86("\n^P\n", 0); + if(c == 0x12) /* control-r? */ + debug = !debug; + consiq.putc(&consiq, c); +} + +static int +consputc(void) +{ + return consoq.getc(&consoq); +} + +void +kbdinit(void) +{ + i8042init(); + qinit(&consiq); +} + +void +consinit(char* name, char* speed) +{ + int baud, port; + + if(name == nil || cistrcmp(name, "cga") == 0) + return; + port = strtoul(name, 0, 0); + if(port < 0 || port > 1) + return; + if(speed == nil || (baud = strtoul(speed, 0, 0)) == 0) + baud = 9600; + + qinit(&consoq); + + uartspecial(port, kbdchar, consputc, baud); + useuart = 1; + uartputs(&consoq, "\n", 1); +} + +void +consdrain(void) +{ + if(useuart) + uartdrain(); +} + +void +consputs(char* s, int n) +{ + cgascreenputs(s, n); + if(useuart) + uartputs(&consoq, s, n); +} + +void +warp86(char* s, ulong) +{ + if(s != nil) + print(s); + spllo(); + consdrain(); + + i8042reset(); + + /* + * Often the BIOS hangs during restart if a conventional 8042 + * warm-boot sequence is tried. The following is Intel specific and + * seems to perform a cold-boot, but at least it comes back. + * And sometimes there is no keyboard... + * + * The reset register (0xcf9) is usually in one of the bridge + * chips. The actual location and sequence could be extracted from + * ACPI but why bother, this is the end of the line anyway. + */ + print("Takes a licking and keeps on ticking...\n"); + *(ushort*)KADDR(0x472) = 0x1234; /* BIOS warm-boot flag */ + outb(0xcf9, 0x02); + outb(0xcf9, 0x06); + + for(;;) + idle(); +} + +static int +getline(char *buf, int size, int timeout) +{ + int c, i=0; + ulong start; + char echo; + + for (;;) { + start = m->ticks; + do{ + /* timeout seconds to first char */ + if(timeout && ((m->ticks - start) > timeout*HZ)) + return -2; + c = consiq.getc(&consiq); + }while(c == -1); + timeout = 0; + + if(c == '\r') + c = '\n'; /* turn carriage return into newline */ + if(c == '\177') + c = '\010'; /* turn delete into backspace */ + if(c == '\025') + echo = '\n'; /* echo ^U as a newline */ + else + echo = c; + consputs(&echo, 1); + + if(c == '\010'){ + if(i > 0) + i--; /* bs deletes last character */ + continue; + } + /* a newline ends a line */ + if (c == '\n') + break; + /* ^U wipes out the line */ + if (c =='\025') + return -1; + if(i == size) + return size; + buf[i++] = c; + } + buf[i] = 0; + return i; +} + +int +getstr(char *prompt, char *buf, int size, char *def, int timeout) +{ + int len, isdefault; + char pbuf[PRINTSIZE]; + + buf[0] = 0; + isdefault = (def && *def); + if(isdefault == 0){ + timeout = 0; + sprint(pbuf, "%s: ", prompt); + } + else if(timeout) + sprint(pbuf, "%s[default==%s (%ds timeout)]: ", prompt, def, timeout); + else + sprint(pbuf, "%s[default==%s]: ", prompt, def); + for (;;) { + print(pbuf); + consdrain(); + len = getline(buf, size, timeout); + switch(len){ + case 0: + /* RETURN */ + if(isdefault) + break; + continue; + case -1: + /* ^U typed */ + continue; + case -2: + /* timeout, use default */ + consputs("\n", 1); + len = 0; + break; + default: + break; + } + if(len >= size){ + print("line too long\n"); + continue; + } + break; + } + if(len == 0 && isdefault) + strncpy(buf, def, size); + return 0; +} + +int +print(char *fmt, ...) +{ + int n; + va_list arg; + char buf[PRINTSIZE]; + + va_start(arg, fmt); + n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf; + va_end(arg); + consputs(buf, n); + + return n; +} + +void +panic(char *fmt, ...) +{ + int n; + va_list arg; + char buf[PRINTSIZE]; + + strcpy(buf, "panic: "); + va_start(arg, fmt); + n = vseprint(buf+7, buf+sizeof(buf), fmt, arg) - buf; + va_end(arg); + buf[n] = '\n'; + consputs(buf, n+1); + +//floppymemwrite(); +//splhi(); for(;;); + if(etherdetach) + etherdetach(); + if(sddetach) + sddetach(); + + consputs("\nPress almost any key to reset...", 32); + spllo(); + while(consiq.getc(&consiq) == -1) + ; + + warp86(nil, 0); +} |