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.
This commit is contained in:
Kazutaka YOKOTA 1997-06-22 12:04:36 +00:00
parent c222d4bb39
commit 124ff4169d
3 changed files with 489 additions and 201 deletions

View File

@ -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 @@ ansi_put(scr_stat *scp, u_char *buf, int len)
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]);

View File

@ -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 @@ ansi_put(scr_stat *scp, u_char *buf, int len)
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]);

View File

@ -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 @@ ansi_put(scr_stat *scp, u_char *buf, int len)
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]);