======== 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