summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authoryokota <yokota@FreeBSD.org>1997-06-22 12:04:36 +0000
committeryokota <yokota@FreeBSD.org>1997-06-22 12:04:36 +0000
commit6d701eaf76faf2ebbc25c764ba001943a9d199f3 (patch)
tree54fc6fdca4451d1588fdb4e0219e9bf48739c0b0 /sys
parent10ace94da8fd39a4c5dec7c3cb89156e36d01bb3 (diff)
downloadFreeBSD-src-6d701eaf76faf2ebbc25c764ba001943a9d199f3.zip
FreeBSD-src-6d701eaf76faf2ebbc25c764ba001943a9d199f3.tar.gz
The syscons driver doesn't really check the presence of the display
adapter during the system boot. It always assumes there is at least a monochrome adapter. This is rather strange assumption. If there is no dispaly adapter, the console driver cannot be any good... In this patch, scinit() is split into two parts; the first part is now called scvidprobe() which will detect the presence of video card at the CGA or MONO buffer address and returns TRUE if found. It is called during sccnprobe() and scprobe(). Both will fail if no video card is found. The second part, whose name stays the same as before, scinit(), is called from sccninit() and scattach() to complete initialization of the found video card. The keyboard probe code is moved from scprobe() to sckbdprobe(); scprobe() now calls scvidprobe() and sckbdprobe() to carry out device probe. (This is rather a cosmetic change, but it sure makes the code look better organized.) The problem pointed out by Joerg.
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/syscons/syscons.c230
-rw-r--r--sys/i386/isa/syscons.c230
-rw-r--r--sys/isa/syscons.c230
3 files changed, 489 insertions, 201 deletions
diff --git a/sys/dev/syscons/syscons.c b/sys/dev/syscons/syscons.c
index 5d01115..5df4190 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);
@@ -303,17 +309,125 @@ 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 5d01115..5df4190 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);
@@ -303,17 +309,125 @@ 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 5d01115..5df4190 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);
@@ -303,17 +309,125 @@ 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]);
OpenPOWER on IntegriCloud