diff --git a/sys/dev/syscons/syscons.c b/sys/dev/syscons/syscons.c index 5d01115481b9..5df41907a37a 100644 --- a/sys/dev/syscons/syscons.c +++ b/sys/dev/syscons/syscons.c @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: syscons.c,v 1.215 1997/05/07 20:02:38 peter Exp $ + * $Id: syscons.c,v 1.216 1997/05/15 05:43:57 yokota Exp $ */ #include "sc.h" @@ -111,6 +111,7 @@ static char write_in_progress = FALSE; static char blink_in_progress = FALSE; static int blinkrate = 0; u_int crtc_addr = MONO_BASE; + char crtc_type = KD_MONO; char crtc_vga = FALSE; static u_char shfts = 0, ctls = 0, alts = 0, agrs = 0, metas = 0; static u_char nlkcnt = 0, clkcnt = 0, slkcnt = 0, alkcnt = 0; @@ -171,10 +172,15 @@ static const int nsccons = MAXCONS+2; + (offset)) % (scp->history_size))) #define ISSIGVALID(sig) ((sig) > 0 && (sig) < NSIG) +/* this should really be in `rtc.h' */ +#define RTC_EQUIPMENT 0x14 + /* prototypes */ static int scattach(struct isa_device *dev); static int scparam(struct tty *tp, struct termios *t); static int scprobe(struct isa_device *dev); +static int scvidprobe(int unit, int flags); +static int sckbdprobe(int unit, int flags); static void scstart(struct tty *tp); static void scmousestart(struct tty *tp); static void scinit(void); @@ -302,18 +308,126 @@ move_crsr(scr_stat *scp, int x, int y) static int scprobe(struct isa_device *dev) +{ + if (!scvidprobe(dev->id_unit, dev->id_flags)) { + if (bootverbose) + printf("sc%d: no video adapter is found.\n", dev->id_unit); + return (0); + } + + sc_port = dev->id_iobase; + if (sckbdprobe(dev->id_unit, dev->id_flags)) + return (IO_KBDSIZE); + else + return ((dev->id_flags & DETECT_KBD) ? 0 : IO_KBDSIZE); +} + +/* probe video adapters, return TRUE if found */ +static int +scvidprobe(int unit, int flags) +{ + /* + * XXX don't try to `printf' anything here, the console may not have + * been configured yet. + */ + u_short volatile *cp; + u_short was; + u_long pa; + u_long segoff; + + /* do this test only once */ + if (init_done != COLD) + return (Crtat != 0); + + /* + * Finish defaulting crtc variables for a mono screen. Crtat is a + * bogus common variable so that it can be shared with pcvt, so it + * can't be statically initialized. XXX. + */ + Crtat = (u_short *)MONO_BUF; + crtc_type = KD_MONO; + /* If CGA memory seems to work, switch to color. */ + cp = (u_short *)CGA_BUF; + was = *cp; + *cp = (u_short) 0xA55A; + if (*cp == 0xA55A) { + Crtat = (u_short *)CGA_BUF; + crtc_addr = COLOR_BASE; + crtc_type = KD_CGA; + } else { + cp = Crtat; + was = *cp; + *cp = (u_short) 0xA55A; + if (*cp != 0xA55A) { + /* no screen at all, bail out */ + Crtat = 0; + return FALSE; + } + } + *cp = was; + + /* + * Check rtc and BIOS date area. + * XXX: don't use BIOSDATA_EQUIPMENT, it is not a dead copy + * of RTC_EQUIPMENT. The bit 4 and 5 of the ETC_EQUIPMENT are + * zeros for EGA and VGA. However, the EGA/VGA BIOS will set + * these bits in BIOSDATA_EQUIPMENT according to the monitor + * type detected. + */ + switch ((rtcin(RTC_EQUIPMENT) >> 4) & 3) { /* bit 4 and 5 */ + case 0: /* EGA/VGA, or nothing */ + crtc_type = KD_EGA; + /* the color adapter may be in the 40x25 mode... XXX */ + break; + case 1: /* CGA 40x25 */ + /* switch to the 80x25 mode? XXX */ + /* FALL THROUGH */ + case 2: /* CGA 80x25 */ + /* `crtc_type' has already been set... */ + /* crtc_type = KD_CGA; */ + break; + case 3: /* MDA */ + /* `crtc_type' has already been set... */ + /* crtc_type = KD_MONO; */ + break; + } + + /* is this a VGA or higher ? */ + outb(crtc_addr, 7); + if (inb(crtc_addr) == 7) { + + crtc_type = KD_VGA; + crtc_vga = TRUE; + read_vgaregs(vgaregs); + + /* Get the BIOS video mode pointer */ + segoff = *(u_long *)pa_to_va(0x4a8); + pa = (((segoff & 0xffff0000) >> 12) + (segoff & 0xffff)); + if (ISMAPPED(pa, sizeof(u_long))) { + segoff = *(u_long *)pa_to_va(pa); + pa = (((segoff & 0xffff0000) >> 12) + (segoff & 0xffff)); + if (ISMAPPED(pa, 64)) + video_mode_ptr = (char *)pa_to_va(pa); + } + } + + return TRUE; +} + +/* probe the keyboard, return TRUE if found */ +static int +sckbdprobe(int unit, int flags) { int codeset; int c = -1; int m; - sc_port = dev->id_iobase; sc_kbdc = kbdc_open(sc_port); if (!kbdc_lock(sc_kbdc, TRUE)) { /* driver error? */ - printf("sc%d: unable to lock the controller.\n", dev->id_unit); - return ((dev->id_flags & DETECT_KBD) ? 0 : IO_KBDSIZE); + printf("sc%d: unable to lock the controller.\n", unit); + return ((flags & DETECT_KBD) ? FALSE : TRUE); } /* discard anything left after UserConfig */ @@ -324,26 +438,35 @@ scprobe(struct isa_device *dev) c = get_controller_command_byte(sc_kbdc); if (c == -1) { /* CONTROLLER ERROR */ - printf("sc%d: unable to get the current command byte value.\n", - dev->id_unit); + printf("sc%d: unable to get the current command byte value.\n", unit); goto fail; } if (bootverbose) printf("sc%d: the current keyboard controller command byte %04x\n", - dev->id_unit, c); + unit, c); #if 0 /* override the keyboard lock switch */ c |= KBD_OVERRIDE_KBD_LOCK; #endif + /* + * The keyboard may have been screwed up by the boot block. + * We may just be able to recover from error by testing the controller + * and the keyboard port. The controller command byte needs to be saved + * before this recovery operation, as some controllers seem to set + * the command byte to particular values. + */ + test_controller(sc_kbdc); + test_kbd_port(sc_kbdc); + /* enable the keyboard port, but disable the keyboard intr. */ if (!set_controller_command_byte(sc_kbdc, - KBD_KBD_CONTROL_BITS, + KBD_KBD_CONTROL_BITS, KBD_ENABLE_KBD_PORT | KBD_DISABLE_KBD_INT)) { /* CONTROLLER ERROR * there is very little we can do... */ - printf("sc%d: unable to set the command byte.\n", dev->id_unit); + printf("sc%d: unable to set the command byte.\n", unit); goto fail; } @@ -354,7 +477,7 @@ scprobe(struct isa_device *dev) * during the boot process. */ codeset = -1; - if (dev->id_flags & XT_KEYBD) + if (flags & XT_KEYBD) /* the user says there is a XT keyboard */ codeset = 1; #ifdef DETECT_XT_KEYBOARD @@ -365,7 +488,7 @@ scprobe(struct isa_device *dev) codeset = read_kbd_data(sc_kbdc); } if (bootverbose) - printf("sc%d: keyboard scancode set %d\n", dev->id_unit, codeset); + printf("sc%d: keyboard scancode set %d\n", unit, codeset); #endif /* DETECT_XT_KEYBOARD */ /* reset keyboard hardware */ @@ -386,7 +509,7 @@ scprobe(struct isa_device *dev) * the keyboard may still exist (see above). */ if (bootverbose) - printf("sc%d: failed to reset the keyboard.\n", dev->id_unit); + printf("sc%d: failed to reset the keyboard.\n", unit); goto fail; } @@ -405,7 +528,7 @@ scprobe(struct isa_device *dev) * The XT kbd isn't usable unless the proper scan code set * is selected. */ - printf("sc%d: unable to set the XT keyboard mode.\n", dev->id_unit); + printf("sc%d: unable to set the XT keyboard mode.\n", unit); goto fail; } } @@ -417,24 +540,23 @@ scprobe(struct isa_device *dev) /* CONTROLLER ERROR * This is serious; we are left with the disabled keyboard intr. */ - printf("sc%d: unable to enable the keyboard port and intr.\n", - dev->id_unit); + printf("sc%d: unable to enable the keyboard port and intr.\n", unit); goto fail; } succeed: kbdc_set_device_mask(sc_kbdc, m | KBD_KBD_CONTROL_BITS), kbdc_lock(sc_kbdc, FALSE); - return (IO_KBDSIZE); + return TRUE; fail: if (c != -1) /* try to restore the command byte as before, if possible */ set_controller_command_byte(sc_kbdc, 0xff, c); kbdc_set_device_mask(sc_kbdc, - (dev->id_flags & DETECT_KBD) ? m : m | KBD_KBD_CONTROL_BITS); + (flags & DETECT_KBD) ? m : m | KBD_KBD_CONTROL_BITS); kbdc_lock(sc_kbdc, FALSE); - return ((dev->id_flags & DETECT_KBD) ? 0 : IO_KBDSIZE); + return FALSE; } #if NAPM > 0 @@ -508,16 +630,28 @@ scattach(struct isa_device *dev) } printf("sc%d: ", dev->id_unit); - if (crtc_vga) + switch(crtc_type) { + case KD_VGA: if (crtc_addr == MONO_BASE) printf("VGA mono"); else printf("VGA color"); - else + break; + case KD_EGA: if (crtc_addr == MONO_BASE) - printf("MDA/hercules"); + printf("EGA mono"); else - printf("CGA/EGA"); + printf("EGA color"); + break; + case KD_CGA: + printf("CGA"); + break; + case KD_MONO: + case KD_HERCULES: + default: + printf("MDA/hercules"); + break; + } printf(" <%d virtual consoles, flags=0x%x>\n", MAXCONS, flags); #if NAPM > 0 @@ -745,13 +879,7 @@ scioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p) return 0; case CONS_CURRENT: /* get current adapter type */ - if (crtc_vga) - *(int*)data = KD_VGA; - else - if (crtc_addr == MONO_BASE) - *(int*)data = KD_MONO; - else - *(int*)data = KD_CGA; + *(int *)data = crtc_type; return 0; case CONS_GET: /* get current video mode */ @@ -1465,6 +1593,11 @@ sccnprobe(struct consdev *cp) return; } + if (!scvidprobe(dvp->id_unit, dvp->id_flags)) { + cp->cn_pri = CN_DEAD; + return; + } + /* initialize required fields */ cp->cn_dev = makedev(CDEV_MAJOR, SC_CONSOLE); cp->cn_pri = CN_INTERNAL; @@ -2395,31 +2528,12 @@ outloop: static void scinit(void) { - u_short volatile *cp; - u_short was; u_int hw_cursor; u_int i; if (init_done != COLD) return; init_done = WARM; - /* - * Finish defaulting crtc variables for a mono screen. Crtat is a - * bogus common variable so that it can be shared with pcvt, so it - * can't be statically initialized. XXX. - */ - Crtat = (u_short *)MONO_BUF; - /* - * If CGA memory seems to work, switch to color. - */ - cp = (u_short *)CGA_BUF; - was = *cp; - *cp = (u_short) 0xA55A; - if (*cp == 0xA55A) { - Crtat = (u_short *)CGA_BUF; - crtc_addr = COLOR_BASE; - } - *cp = was; /* * Ensure a zero start address. This is mainly to recover after @@ -2451,25 +2565,7 @@ scinit(void) outb(crtc_addr, 15); outb(crtc_addr + 1, 0xff); - /* is this a VGA or higher ? */ - outb(crtc_addr, 7); - if (inb(crtc_addr) == 7) { - u_long pa; - u_long segoff; - - crtc_vga = TRUE; - read_vgaregs(vgaregs); - - /* Get the BIOS video mode pointer */ - segoff = *(u_long *)pa_to_va(0x4a8); - pa = (((segoff & 0xffff0000) >> 12) + (segoff & 0xffff)); - if (ISMAPPED(pa, sizeof(u_long))) { - segoff = *(u_long *)pa_to_va(pa); - pa = (((segoff & 0xffff0000) >> 12) + (segoff & 0xffff)); - if (ISMAPPED(pa, 64)) - video_mode_ptr = (char *)pa_to_va(pa); - } - } + /* set up the first console */ current_default = &user_default; console[0] = &main_console; init_scp(console[0]); diff --git a/sys/i386/isa/syscons.c b/sys/i386/isa/syscons.c index 5d01115481b9..5df41907a37a 100644 --- a/sys/i386/isa/syscons.c +++ b/sys/i386/isa/syscons.c @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: syscons.c,v 1.215 1997/05/07 20:02:38 peter Exp $ + * $Id: syscons.c,v 1.216 1997/05/15 05:43:57 yokota Exp $ */ #include "sc.h" @@ -111,6 +111,7 @@ static char write_in_progress = FALSE; static char blink_in_progress = FALSE; static int blinkrate = 0; u_int crtc_addr = MONO_BASE; + char crtc_type = KD_MONO; char crtc_vga = FALSE; static u_char shfts = 0, ctls = 0, alts = 0, agrs = 0, metas = 0; static u_char nlkcnt = 0, clkcnt = 0, slkcnt = 0, alkcnt = 0; @@ -171,10 +172,15 @@ static const int nsccons = MAXCONS+2; + (offset)) % (scp->history_size))) #define ISSIGVALID(sig) ((sig) > 0 && (sig) < NSIG) +/* this should really be in `rtc.h' */ +#define RTC_EQUIPMENT 0x14 + /* prototypes */ static int scattach(struct isa_device *dev); static int scparam(struct tty *tp, struct termios *t); static int scprobe(struct isa_device *dev); +static int scvidprobe(int unit, int flags); +static int sckbdprobe(int unit, int flags); static void scstart(struct tty *tp); static void scmousestart(struct tty *tp); static void scinit(void); @@ -302,18 +308,126 @@ move_crsr(scr_stat *scp, int x, int y) static int scprobe(struct isa_device *dev) +{ + if (!scvidprobe(dev->id_unit, dev->id_flags)) { + if (bootverbose) + printf("sc%d: no video adapter is found.\n", dev->id_unit); + return (0); + } + + sc_port = dev->id_iobase; + if (sckbdprobe(dev->id_unit, dev->id_flags)) + return (IO_KBDSIZE); + else + return ((dev->id_flags & DETECT_KBD) ? 0 : IO_KBDSIZE); +} + +/* probe video adapters, return TRUE if found */ +static int +scvidprobe(int unit, int flags) +{ + /* + * XXX don't try to `printf' anything here, the console may not have + * been configured yet. + */ + u_short volatile *cp; + u_short was; + u_long pa; + u_long segoff; + + /* do this test only once */ + if (init_done != COLD) + return (Crtat != 0); + + /* + * Finish defaulting crtc variables for a mono screen. Crtat is a + * bogus common variable so that it can be shared with pcvt, so it + * can't be statically initialized. XXX. + */ + Crtat = (u_short *)MONO_BUF; + crtc_type = KD_MONO; + /* If CGA memory seems to work, switch to color. */ + cp = (u_short *)CGA_BUF; + was = *cp; + *cp = (u_short) 0xA55A; + if (*cp == 0xA55A) { + Crtat = (u_short *)CGA_BUF; + crtc_addr = COLOR_BASE; + crtc_type = KD_CGA; + } else { + cp = Crtat; + was = *cp; + *cp = (u_short) 0xA55A; + if (*cp != 0xA55A) { + /* no screen at all, bail out */ + Crtat = 0; + return FALSE; + } + } + *cp = was; + + /* + * Check rtc and BIOS date area. + * XXX: don't use BIOSDATA_EQUIPMENT, it is not a dead copy + * of RTC_EQUIPMENT. The bit 4 and 5 of the ETC_EQUIPMENT are + * zeros for EGA and VGA. However, the EGA/VGA BIOS will set + * these bits in BIOSDATA_EQUIPMENT according to the monitor + * type detected. + */ + switch ((rtcin(RTC_EQUIPMENT) >> 4) & 3) { /* bit 4 and 5 */ + case 0: /* EGA/VGA, or nothing */ + crtc_type = KD_EGA; + /* the color adapter may be in the 40x25 mode... XXX */ + break; + case 1: /* CGA 40x25 */ + /* switch to the 80x25 mode? XXX */ + /* FALL THROUGH */ + case 2: /* CGA 80x25 */ + /* `crtc_type' has already been set... */ + /* crtc_type = KD_CGA; */ + break; + case 3: /* MDA */ + /* `crtc_type' has already been set... */ + /* crtc_type = KD_MONO; */ + break; + } + + /* is this a VGA or higher ? */ + outb(crtc_addr, 7); + if (inb(crtc_addr) == 7) { + + crtc_type = KD_VGA; + crtc_vga = TRUE; + read_vgaregs(vgaregs); + + /* Get the BIOS video mode pointer */ + segoff = *(u_long *)pa_to_va(0x4a8); + pa = (((segoff & 0xffff0000) >> 12) + (segoff & 0xffff)); + if (ISMAPPED(pa, sizeof(u_long))) { + segoff = *(u_long *)pa_to_va(pa); + pa = (((segoff & 0xffff0000) >> 12) + (segoff & 0xffff)); + if (ISMAPPED(pa, 64)) + video_mode_ptr = (char *)pa_to_va(pa); + } + } + + return TRUE; +} + +/* probe the keyboard, return TRUE if found */ +static int +sckbdprobe(int unit, int flags) { int codeset; int c = -1; int m; - sc_port = dev->id_iobase; sc_kbdc = kbdc_open(sc_port); if (!kbdc_lock(sc_kbdc, TRUE)) { /* driver error? */ - printf("sc%d: unable to lock the controller.\n", dev->id_unit); - return ((dev->id_flags & DETECT_KBD) ? 0 : IO_KBDSIZE); + printf("sc%d: unable to lock the controller.\n", unit); + return ((flags & DETECT_KBD) ? FALSE : TRUE); } /* discard anything left after UserConfig */ @@ -324,26 +438,35 @@ scprobe(struct isa_device *dev) c = get_controller_command_byte(sc_kbdc); if (c == -1) { /* CONTROLLER ERROR */ - printf("sc%d: unable to get the current command byte value.\n", - dev->id_unit); + printf("sc%d: unable to get the current command byte value.\n", unit); goto fail; } if (bootverbose) printf("sc%d: the current keyboard controller command byte %04x\n", - dev->id_unit, c); + unit, c); #if 0 /* override the keyboard lock switch */ c |= KBD_OVERRIDE_KBD_LOCK; #endif + /* + * The keyboard may have been screwed up by the boot block. + * We may just be able to recover from error by testing the controller + * and the keyboard port. The controller command byte needs to be saved + * before this recovery operation, as some controllers seem to set + * the command byte to particular values. + */ + test_controller(sc_kbdc); + test_kbd_port(sc_kbdc); + /* enable the keyboard port, but disable the keyboard intr. */ if (!set_controller_command_byte(sc_kbdc, - KBD_KBD_CONTROL_BITS, + KBD_KBD_CONTROL_BITS, KBD_ENABLE_KBD_PORT | KBD_DISABLE_KBD_INT)) { /* CONTROLLER ERROR * there is very little we can do... */ - printf("sc%d: unable to set the command byte.\n", dev->id_unit); + printf("sc%d: unable to set the command byte.\n", unit); goto fail; } @@ -354,7 +477,7 @@ scprobe(struct isa_device *dev) * during the boot process. */ codeset = -1; - if (dev->id_flags & XT_KEYBD) + if (flags & XT_KEYBD) /* the user says there is a XT keyboard */ codeset = 1; #ifdef DETECT_XT_KEYBOARD @@ -365,7 +488,7 @@ scprobe(struct isa_device *dev) codeset = read_kbd_data(sc_kbdc); } if (bootverbose) - printf("sc%d: keyboard scancode set %d\n", dev->id_unit, codeset); + printf("sc%d: keyboard scancode set %d\n", unit, codeset); #endif /* DETECT_XT_KEYBOARD */ /* reset keyboard hardware */ @@ -386,7 +509,7 @@ scprobe(struct isa_device *dev) * the keyboard may still exist (see above). */ if (bootverbose) - printf("sc%d: failed to reset the keyboard.\n", dev->id_unit); + printf("sc%d: failed to reset the keyboard.\n", unit); goto fail; } @@ -405,7 +528,7 @@ scprobe(struct isa_device *dev) * The XT kbd isn't usable unless the proper scan code set * is selected. */ - printf("sc%d: unable to set the XT keyboard mode.\n", dev->id_unit); + printf("sc%d: unable to set the XT keyboard mode.\n", unit); goto fail; } } @@ -417,24 +540,23 @@ scprobe(struct isa_device *dev) /* CONTROLLER ERROR * This is serious; we are left with the disabled keyboard intr. */ - printf("sc%d: unable to enable the keyboard port and intr.\n", - dev->id_unit); + printf("sc%d: unable to enable the keyboard port and intr.\n", unit); goto fail; } succeed: kbdc_set_device_mask(sc_kbdc, m | KBD_KBD_CONTROL_BITS), kbdc_lock(sc_kbdc, FALSE); - return (IO_KBDSIZE); + return TRUE; fail: if (c != -1) /* try to restore the command byte as before, if possible */ set_controller_command_byte(sc_kbdc, 0xff, c); kbdc_set_device_mask(sc_kbdc, - (dev->id_flags & DETECT_KBD) ? m : m | KBD_KBD_CONTROL_BITS); + (flags & DETECT_KBD) ? m : m | KBD_KBD_CONTROL_BITS); kbdc_lock(sc_kbdc, FALSE); - return ((dev->id_flags & DETECT_KBD) ? 0 : IO_KBDSIZE); + return FALSE; } #if NAPM > 0 @@ -508,16 +630,28 @@ scattach(struct isa_device *dev) } printf("sc%d: ", dev->id_unit); - if (crtc_vga) + switch(crtc_type) { + case KD_VGA: if (crtc_addr == MONO_BASE) printf("VGA mono"); else printf("VGA color"); - else + break; + case KD_EGA: if (crtc_addr == MONO_BASE) - printf("MDA/hercules"); + printf("EGA mono"); else - printf("CGA/EGA"); + printf("EGA color"); + break; + case KD_CGA: + printf("CGA"); + break; + case KD_MONO: + case KD_HERCULES: + default: + printf("MDA/hercules"); + break; + } printf(" <%d virtual consoles, flags=0x%x>\n", MAXCONS, flags); #if NAPM > 0 @@ -745,13 +879,7 @@ scioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p) return 0; case CONS_CURRENT: /* get current adapter type */ - if (crtc_vga) - *(int*)data = KD_VGA; - else - if (crtc_addr == MONO_BASE) - *(int*)data = KD_MONO; - else - *(int*)data = KD_CGA; + *(int *)data = crtc_type; return 0; case CONS_GET: /* get current video mode */ @@ -1465,6 +1593,11 @@ sccnprobe(struct consdev *cp) return; } + if (!scvidprobe(dvp->id_unit, dvp->id_flags)) { + cp->cn_pri = CN_DEAD; + return; + } + /* initialize required fields */ cp->cn_dev = makedev(CDEV_MAJOR, SC_CONSOLE); cp->cn_pri = CN_INTERNAL; @@ -2395,31 +2528,12 @@ outloop: static void scinit(void) { - u_short volatile *cp; - u_short was; u_int hw_cursor; u_int i; if (init_done != COLD) return; init_done = WARM; - /* - * Finish defaulting crtc variables for a mono screen. Crtat is a - * bogus common variable so that it can be shared with pcvt, so it - * can't be statically initialized. XXX. - */ - Crtat = (u_short *)MONO_BUF; - /* - * If CGA memory seems to work, switch to color. - */ - cp = (u_short *)CGA_BUF; - was = *cp; - *cp = (u_short) 0xA55A; - if (*cp == 0xA55A) { - Crtat = (u_short *)CGA_BUF; - crtc_addr = COLOR_BASE; - } - *cp = was; /* * Ensure a zero start address. This is mainly to recover after @@ -2451,25 +2565,7 @@ scinit(void) outb(crtc_addr, 15); outb(crtc_addr + 1, 0xff); - /* is this a VGA or higher ? */ - outb(crtc_addr, 7); - if (inb(crtc_addr) == 7) { - u_long pa; - u_long segoff; - - crtc_vga = TRUE; - read_vgaregs(vgaregs); - - /* Get the BIOS video mode pointer */ - segoff = *(u_long *)pa_to_va(0x4a8); - pa = (((segoff & 0xffff0000) >> 12) + (segoff & 0xffff)); - if (ISMAPPED(pa, sizeof(u_long))) { - segoff = *(u_long *)pa_to_va(pa); - pa = (((segoff & 0xffff0000) >> 12) + (segoff & 0xffff)); - if (ISMAPPED(pa, 64)) - video_mode_ptr = (char *)pa_to_va(pa); - } - } + /* set up the first console */ current_default = &user_default; console[0] = &main_console; init_scp(console[0]); diff --git a/sys/isa/syscons.c b/sys/isa/syscons.c index 5d01115481b9..5df41907a37a 100644 --- a/sys/isa/syscons.c +++ b/sys/isa/syscons.c @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: syscons.c,v 1.215 1997/05/07 20:02:38 peter Exp $ + * $Id: syscons.c,v 1.216 1997/05/15 05:43:57 yokota Exp $ */ #include "sc.h" @@ -111,6 +111,7 @@ static char write_in_progress = FALSE; static char blink_in_progress = FALSE; static int blinkrate = 0; u_int crtc_addr = MONO_BASE; + char crtc_type = KD_MONO; char crtc_vga = FALSE; static u_char shfts = 0, ctls = 0, alts = 0, agrs = 0, metas = 0; static u_char nlkcnt = 0, clkcnt = 0, slkcnt = 0, alkcnt = 0; @@ -171,10 +172,15 @@ static const int nsccons = MAXCONS+2; + (offset)) % (scp->history_size))) #define ISSIGVALID(sig) ((sig) > 0 && (sig) < NSIG) +/* this should really be in `rtc.h' */ +#define RTC_EQUIPMENT 0x14 + /* prototypes */ static int scattach(struct isa_device *dev); static int scparam(struct tty *tp, struct termios *t); static int scprobe(struct isa_device *dev); +static int scvidprobe(int unit, int flags); +static int sckbdprobe(int unit, int flags); static void scstart(struct tty *tp); static void scmousestart(struct tty *tp); static void scinit(void); @@ -302,18 +308,126 @@ move_crsr(scr_stat *scp, int x, int y) static int scprobe(struct isa_device *dev) +{ + if (!scvidprobe(dev->id_unit, dev->id_flags)) { + if (bootverbose) + printf("sc%d: no video adapter is found.\n", dev->id_unit); + return (0); + } + + sc_port = dev->id_iobase; + if (sckbdprobe(dev->id_unit, dev->id_flags)) + return (IO_KBDSIZE); + else + return ((dev->id_flags & DETECT_KBD) ? 0 : IO_KBDSIZE); +} + +/* probe video adapters, return TRUE if found */ +static int +scvidprobe(int unit, int flags) +{ + /* + * XXX don't try to `printf' anything here, the console may not have + * been configured yet. + */ + u_short volatile *cp; + u_short was; + u_long pa; + u_long segoff; + + /* do this test only once */ + if (init_done != COLD) + return (Crtat != 0); + + /* + * Finish defaulting crtc variables for a mono screen. Crtat is a + * bogus common variable so that it can be shared with pcvt, so it + * can't be statically initialized. XXX. + */ + Crtat = (u_short *)MONO_BUF; + crtc_type = KD_MONO; + /* If CGA memory seems to work, switch to color. */ + cp = (u_short *)CGA_BUF; + was = *cp; + *cp = (u_short) 0xA55A; + if (*cp == 0xA55A) { + Crtat = (u_short *)CGA_BUF; + crtc_addr = COLOR_BASE; + crtc_type = KD_CGA; + } else { + cp = Crtat; + was = *cp; + *cp = (u_short) 0xA55A; + if (*cp != 0xA55A) { + /* no screen at all, bail out */ + Crtat = 0; + return FALSE; + } + } + *cp = was; + + /* + * Check rtc and BIOS date area. + * XXX: don't use BIOSDATA_EQUIPMENT, it is not a dead copy + * of RTC_EQUIPMENT. The bit 4 and 5 of the ETC_EQUIPMENT are + * zeros for EGA and VGA. However, the EGA/VGA BIOS will set + * these bits in BIOSDATA_EQUIPMENT according to the monitor + * type detected. + */ + switch ((rtcin(RTC_EQUIPMENT) >> 4) & 3) { /* bit 4 and 5 */ + case 0: /* EGA/VGA, or nothing */ + crtc_type = KD_EGA; + /* the color adapter may be in the 40x25 mode... XXX */ + break; + case 1: /* CGA 40x25 */ + /* switch to the 80x25 mode? XXX */ + /* FALL THROUGH */ + case 2: /* CGA 80x25 */ + /* `crtc_type' has already been set... */ + /* crtc_type = KD_CGA; */ + break; + case 3: /* MDA */ + /* `crtc_type' has already been set... */ + /* crtc_type = KD_MONO; */ + break; + } + + /* is this a VGA or higher ? */ + outb(crtc_addr, 7); + if (inb(crtc_addr) == 7) { + + crtc_type = KD_VGA; + crtc_vga = TRUE; + read_vgaregs(vgaregs); + + /* Get the BIOS video mode pointer */ + segoff = *(u_long *)pa_to_va(0x4a8); + pa = (((segoff & 0xffff0000) >> 12) + (segoff & 0xffff)); + if (ISMAPPED(pa, sizeof(u_long))) { + segoff = *(u_long *)pa_to_va(pa); + pa = (((segoff & 0xffff0000) >> 12) + (segoff & 0xffff)); + if (ISMAPPED(pa, 64)) + video_mode_ptr = (char *)pa_to_va(pa); + } + } + + return TRUE; +} + +/* probe the keyboard, return TRUE if found */ +static int +sckbdprobe(int unit, int flags) { int codeset; int c = -1; int m; - sc_port = dev->id_iobase; sc_kbdc = kbdc_open(sc_port); if (!kbdc_lock(sc_kbdc, TRUE)) { /* driver error? */ - printf("sc%d: unable to lock the controller.\n", dev->id_unit); - return ((dev->id_flags & DETECT_KBD) ? 0 : IO_KBDSIZE); + printf("sc%d: unable to lock the controller.\n", unit); + return ((flags & DETECT_KBD) ? FALSE : TRUE); } /* discard anything left after UserConfig */ @@ -324,26 +438,35 @@ scprobe(struct isa_device *dev) c = get_controller_command_byte(sc_kbdc); if (c == -1) { /* CONTROLLER ERROR */ - printf("sc%d: unable to get the current command byte value.\n", - dev->id_unit); + printf("sc%d: unable to get the current command byte value.\n", unit); goto fail; } if (bootverbose) printf("sc%d: the current keyboard controller command byte %04x\n", - dev->id_unit, c); + unit, c); #if 0 /* override the keyboard lock switch */ c |= KBD_OVERRIDE_KBD_LOCK; #endif + /* + * The keyboard may have been screwed up by the boot block. + * We may just be able to recover from error by testing the controller + * and the keyboard port. The controller command byte needs to be saved + * before this recovery operation, as some controllers seem to set + * the command byte to particular values. + */ + test_controller(sc_kbdc); + test_kbd_port(sc_kbdc); + /* enable the keyboard port, but disable the keyboard intr. */ if (!set_controller_command_byte(sc_kbdc, - KBD_KBD_CONTROL_BITS, + KBD_KBD_CONTROL_BITS, KBD_ENABLE_KBD_PORT | KBD_DISABLE_KBD_INT)) { /* CONTROLLER ERROR * there is very little we can do... */ - printf("sc%d: unable to set the command byte.\n", dev->id_unit); + printf("sc%d: unable to set the command byte.\n", unit); goto fail; } @@ -354,7 +477,7 @@ scprobe(struct isa_device *dev) * during the boot process. */ codeset = -1; - if (dev->id_flags & XT_KEYBD) + if (flags & XT_KEYBD) /* the user says there is a XT keyboard */ codeset = 1; #ifdef DETECT_XT_KEYBOARD @@ -365,7 +488,7 @@ scprobe(struct isa_device *dev) codeset = read_kbd_data(sc_kbdc); } if (bootverbose) - printf("sc%d: keyboard scancode set %d\n", dev->id_unit, codeset); + printf("sc%d: keyboard scancode set %d\n", unit, codeset); #endif /* DETECT_XT_KEYBOARD */ /* reset keyboard hardware */ @@ -386,7 +509,7 @@ scprobe(struct isa_device *dev) * the keyboard may still exist (see above). */ if (bootverbose) - printf("sc%d: failed to reset the keyboard.\n", dev->id_unit); + printf("sc%d: failed to reset the keyboard.\n", unit); goto fail; } @@ -405,7 +528,7 @@ scprobe(struct isa_device *dev) * The XT kbd isn't usable unless the proper scan code set * is selected. */ - printf("sc%d: unable to set the XT keyboard mode.\n", dev->id_unit); + printf("sc%d: unable to set the XT keyboard mode.\n", unit); goto fail; } } @@ -417,24 +540,23 @@ scprobe(struct isa_device *dev) /* CONTROLLER ERROR * This is serious; we are left with the disabled keyboard intr. */ - printf("sc%d: unable to enable the keyboard port and intr.\n", - dev->id_unit); + printf("sc%d: unable to enable the keyboard port and intr.\n", unit); goto fail; } succeed: kbdc_set_device_mask(sc_kbdc, m | KBD_KBD_CONTROL_BITS), kbdc_lock(sc_kbdc, FALSE); - return (IO_KBDSIZE); + return TRUE; fail: if (c != -1) /* try to restore the command byte as before, if possible */ set_controller_command_byte(sc_kbdc, 0xff, c); kbdc_set_device_mask(sc_kbdc, - (dev->id_flags & DETECT_KBD) ? m : m | KBD_KBD_CONTROL_BITS); + (flags & DETECT_KBD) ? m : m | KBD_KBD_CONTROL_BITS); kbdc_lock(sc_kbdc, FALSE); - return ((dev->id_flags & DETECT_KBD) ? 0 : IO_KBDSIZE); + return FALSE; } #if NAPM > 0 @@ -508,16 +630,28 @@ scattach(struct isa_device *dev) } printf("sc%d: ", dev->id_unit); - if (crtc_vga) + switch(crtc_type) { + case KD_VGA: if (crtc_addr == MONO_BASE) printf("VGA mono"); else printf("VGA color"); - else + break; + case KD_EGA: if (crtc_addr == MONO_BASE) - printf("MDA/hercules"); + printf("EGA mono"); else - printf("CGA/EGA"); + printf("EGA color"); + break; + case KD_CGA: + printf("CGA"); + break; + case KD_MONO: + case KD_HERCULES: + default: + printf("MDA/hercules"); + break; + } printf(" <%d virtual consoles, flags=0x%x>\n", MAXCONS, flags); #if NAPM > 0 @@ -745,13 +879,7 @@ scioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p) return 0; case CONS_CURRENT: /* get current adapter type */ - if (crtc_vga) - *(int*)data = KD_VGA; - else - if (crtc_addr == MONO_BASE) - *(int*)data = KD_MONO; - else - *(int*)data = KD_CGA; + *(int *)data = crtc_type; return 0; case CONS_GET: /* get current video mode */ @@ -1465,6 +1593,11 @@ sccnprobe(struct consdev *cp) return; } + if (!scvidprobe(dvp->id_unit, dvp->id_flags)) { + cp->cn_pri = CN_DEAD; + return; + } + /* initialize required fields */ cp->cn_dev = makedev(CDEV_MAJOR, SC_CONSOLE); cp->cn_pri = CN_INTERNAL; @@ -2395,31 +2528,12 @@ outloop: static void scinit(void) { - u_short volatile *cp; - u_short was; u_int hw_cursor; u_int i; if (init_done != COLD) return; init_done = WARM; - /* - * Finish defaulting crtc variables for a mono screen. Crtat is a - * bogus common variable so that it can be shared with pcvt, so it - * can't be statically initialized. XXX. - */ - Crtat = (u_short *)MONO_BUF; - /* - * If CGA memory seems to work, switch to color. - */ - cp = (u_short *)CGA_BUF; - was = *cp; - *cp = (u_short) 0xA55A; - if (*cp == 0xA55A) { - Crtat = (u_short *)CGA_BUF; - crtc_addr = COLOR_BASE; - } - *cp = was; /* * Ensure a zero start address. This is mainly to recover after @@ -2451,25 +2565,7 @@ scinit(void) outb(crtc_addr, 15); outb(crtc_addr + 1, 0xff); - /* is this a VGA or higher ? */ - outb(crtc_addr, 7); - if (inb(crtc_addr) == 7) { - u_long pa; - u_long segoff; - - crtc_vga = TRUE; - read_vgaregs(vgaregs); - - /* Get the BIOS video mode pointer */ - segoff = *(u_long *)pa_to_va(0x4a8); - pa = (((segoff & 0xffff0000) >> 12) + (segoff & 0xffff)); - if (ISMAPPED(pa, sizeof(u_long))) { - segoff = *(u_long *)pa_to_va(pa); - pa = (((segoff & 0xffff0000) >> 12) + (segoff & 0xffff)); - if (ISMAPPED(pa, 64)) - video_mode_ptr = (char *)pa_to_va(pa); - } - } + /* set up the first console */ current_default = &user_default; console[0] = &main_console; init_scp(console[0]);