[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 3/3] HACKS for vga text mode with Microport UNIX (ca
From: |
Matthew Ogilvie |
Subject: |
[Qemu-devel] [PATCH 3/3] HACKS for vga text mode with Microport UNIX (ca 1987) |
Date: |
Fri, 27 Jul 2012 12:55:57 -0600 |
========
Background:
========
I don't really think it is appropriate to include this patch in it's
current form, but I'm posting it to illustrate some of the obscure
things that Microport UNIX System V/386 v 2.1 (ca 1987) is trying
to do to the video card.
On real hardware, this version of UNIX could drive an MDA graphics
card (actually an HGC [hurcules graphics card] in text mode only)
just fine. BUT, the VGA card and monitor would always
display snow (timings were out of sync, and/or other problems).
In 1987, I initially had an HGC-only system, and added a VGA
to it later as a second graphics card and monitor. DOS could switch
between them (the "mode" command), but UNIX was only usable on the HGC.
The fact that it couldn't run a real VGA properly suggests that
hacking the emulated VGA isn't really the best solution. A better
approach might be to add specific support for graphics cards
(MDA, HGC, and/or maybe plain-CGA) that UNIX works properly on.
If anyone is interested in examining this UNIX system
directly (for these VGA issues or other issues), let me know and
I can email you at least the first (bootable) installation
floppy image.
========
Visible Problems in Qemu:
========
Running and debugging UNIX in qemu, I see two main VGA-related
problems, and a few associated nits (not counting non-VGA issues
written up separately):
1. (Blank screen): UNIX weirdly writes exactly
one byte to 0x3c0 (VGA_ATT_W). After reading
from 0x3da (which resets 0x3c0 to index mode),
it writes a 0 to 0x3c0, and then doesn't touch the register again.
It doesn't actually modify the contents of the data behind any index.
Writing zero also clears the 0x20 "palette access bit", which forces
qemu vga_update_display() to treat the screen as "GMODE_BLANK".
- My hackish workaround will not blank the screen if the index
register is still 0. Perhaps this hack could be (slightly)
improved to look at the index/data flip-flop as well, under
the theory that until the OS actually starts modifying things,
it is OK for the card to keep using the old palette?
2. (Characters cut in half): UNIX appears to be trying
to program the CRTC under the assumption that the text
mode is using a font that is only 8 pixels high, instead
of 16. I would guess it is trying to treat it like a CGA card.
- (main problem): It changes CRTC register 9 (0x3d4[9]/0x3d5)
from 0x4f to 0x07. The 0xf vs 7 halves the height of
the character, cutting off the bottom halves. The 0x40
bit doesn't seem to hurt, but documentation explains how
it has something to do with split screen scrolling.
- My hackish workaround is to ignore attempts to modify
register 9 if the lock bit in register 0x11 is locked.
- UNIX is also changing the cursor-height-within-a-character
values from (0xe through 0xf) to (6 through 7), effectively
moving the cursor to the middle of the character.
(I haven't tried to work around this, but it would be
trivial to disable these registers under some conditions TBD.
Or perhaps translate the supplied values with scaling logic.)
- UNIX changes register 8 (0x3d4[8]/0x3d5) from 0 to 2, but
this doesn't seem to hurt. (Documentation says it has to
do with smooth text mode scrolling, but UNIX only sets it
once...)
- UNIX also attempts to change registers 0-7 (0x3d4[0-7]/0x3d5), but
these attempts are ignored by qemu because of the lock bit
in register 0x11 (0x3d4[0x11]/0x3d5). (UNIX doesn't seem to
know anything about registers greater than 0xf.)
3. I haven't looked to see if it programming other VGA subsystems
strangely, but it wouldn't surprise me.
========
Possible "Real" Solutions:
========
1. The ideal solution would probably be to implement an emulated plain MDA
adapter, and a way to select it on the command line. (It could also be
extended to optionally be HGC-capable and/or to support a
dual monitor with a CGA/VGA [with two windows for the two
monitors], as well.)
Superficially, emulating an MDA or HGC card itself probably
wouldn't be too hard (mostly just copy, strip down [simplify], and
tweak the VGA support), but I'm still a little vague on the best
way to get it all hooked into the overall system cleanly,
and appropriate configurations options (perhaps options
like "-vga mda", "-vga mda+std", "-vgs cirrus+hgc", etc?).
This seems like a moderate amount of work, but it has the highest
likelyhood of being useful for running other ancient software,
rather than a hackish workaround for one rare OS.
2. Perhaps add some special command line option to enable hacks similar
to what I do in this patch (normally disabled). This is probably
the easiest. Any suggestions for command-line options, etc?
3. I wonder if maybe an alternative approach to these problems would be
to somehow identify that the target is trying to use the VGA like
a CGA, and have the fixups/hacks move it towards CGA functionality
instead of leaving things in VGA mode and disabling the bad
parts? (e.g. use a 8 pixel high font, etc)
- Identify if this is the case, and make a narrow exception
for better CGA support?
- Perhaps add a command line option to have the graphics card be
limited to just CGA functionality?
(Intentionally not signed off; this version of this patch isn't appropriate
for general use.)
---
hw/vga.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/hw/vga.c b/hw/vga.c
index f82ced8..c57d8e2 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -548,7 +548,8 @@ void vga_ioport_write(void *opaque, uint32_t addr, uint32_t
val)
#endif
/* handle CR0-7 protection */
if ((s->cr[VGA_CRTC_V_SYNC_END] & VGA_CR11_LOCK_CR0_CR7) &&
- s->cr_index <= VGA_CRTC_OVERFLOW) {
+ (s->cr_index <= VGA_CRTC_OVERFLOW ||
+ s->cr_index == VGA_CRTC_MAX_SCAN)) {
/* can always write bit 4 of CR7 */
if (s->cr_index == VGA_CRTC_OVERFLOW) {
s->cr[VGA_CRTC_OVERFLOW] = (s->cr[VGA_CRTC_OVERFLOW] & ~0x10) |
@@ -1886,7 +1887,7 @@ static void vga_update_display(void *opaque)
/* nothing to do */
} else {
full_update = 0;
- if (!(s->ar_index & 0x20)) {
+ if (!(s->ar_index & 0x20) && s->ar_index != 0) {
graphic_mode = GMODE_BLANK;
} else {
graphic_mode = s->gr[VGA_GFX_MISC] & VGA_GR06_GRAPHICS_MODE;
--
1.7.10.2.484.gcd07cc5