Mateusz Viste <mateus...@localhost.localhost> wrote:
>Well, I do not assert that it *must* land somewhere in all situations and
>in all universes. I only state that I *observed* it to land somewhere,
>consistently on the three platforms I tested (DOSBox, DOSEMU and my
>oldish 386SX with a PVGA video chip).
>
>The test I posted earlier writes deterministic values (called "garbage"
>in my test) to B800:0000 while in graphic mode. This data doesn't show up
>on the screen, neither immediately nor after returning to text mode.
>However, the exact same data can be reliably read back from B800:0000
>while in graphic mode, so *in the scope of my test* it must land
>somewhere other than VRAM.
It would've been nice if you explained exactly what you meant by
your garbage test when you first mentioned it. My thinking was along
R.Wiesers, it was probably going nowhere since nothing you said showed
otherwise up until now. In anycase, I don't think this is behaviour
you can depend on. Who knows what the emulators you're using are doing,
but on real hardware there's four possible places the reads and writes
to the phyiscal adress B8000h can be ending up, nowhere, system RAM,
video RAM, or cache. Depsite your tests, nowhere seems to be the most
likely on real hardare. Your 386SX/PVGA case seems to be an exception,
and it appears mostly likely to me that it's actually going to video RAM.
I assume your system doesn't have any cache, and going system RAM because
of the video mode selected doesn't make sense to me.
Internally VGA graphics cards have only a 16-bit wide address bus, giving
internal addresses in the range of 0000h to FFFFh. However the data bus
is 32-bits wide, each address refers to a non-overlapping 32-bit value
in video memory. So a VGA card with 256 kilo-bytes of video memory is
actually internally orgianized as 64 kilo-dwords of RAM. Another way
to look at it is that the 256kb of video memory is divided into four
64kb planes, each plane corresponding to a different 8-bit byte of every
32-bit memory location.
How CPU memory accesses to the video memory regions (A0000h-BFFFFh) map
into interal VGA addresses depends on the video mode. The 16-colour
graphics modes offer the most direct mapping to video memory, and are
the only documented means by which the entire 256kb of VGA memory
can be accessed. In these modes the physical CPU addresses in the
range A0000h-AFFFFh directly map to VGA internal address. For example
CPU address A0000h is VGA adress 0000h, and CPU A1234h is VGA 1234h.
Each CPU byte access is mapped to one or more more bytes (planes) of the
32-bit VGA dword at that address. Which plane(s) depends on the setting
of various VGA control registers. For example to read every byte in
the 256kb video memory a program would need to read every byte in the
64kb A0000h region four times, changing the VGA registers as necessary
on to select which plane is being read.
In text modes, either the B0000h-B7FFFh (MDA compatible) or the
B8000-BFFFFh (CGA compatible) regions are mapped to VGA memory.
However the mapping isn't quite as simple as the 16-bit graphics modes.
Instead the video card uses an "even/odd" mapping. In this mapping,
even CPU addresses access plane 0 while odd addresses acces plane 1.
This puts the character values in plane 0 and the attribute values
plane 1. (Plane 2 is used for storing fonts, while plane 3 is unused.)
The least significant bit of the CPU address is set to 0 to form the
VGA address. So in text mode 3h, CPU address B8001h corresponds to
VGA address 0000h, plane 1, while CPU address B9234h corresponds to VGA
address 1234h, plane 0. Since LSB of the CPU address selects the plane
there's no need fiddle around with VGA registers to access video memory.
In the 256-colour graphics mode 13h the A0000h-AFFFFh range is mapped
to VGA memory, and like with the text modes this isn't a direct mapping,
"chain 4" mapping used instead. In this mapping the lowest two bits of
the CPU address determine the plane accessed, and are zeroed to obtain
the VGA addess. So in this mode CPU address A0003h is mapped to VGA
address 0, plane 3, while CPU address A1234h is mapped to VGA address
1234h, plane 0.
(Note the famous "Mode X" works by setting up the VGA registers to
display 256-colour graphics just like mode 13h does, except that the
"chain 4" bit isn't enabled. Instead video memory is accessed in the
same fashion as used by the 16-colour graphics modes, allowing access
to all 256kb of video RAM.)
Now this would seem exclude that your garbage writes to B8000h going to
video memory, because text mode write to B8000h would go VGA address
0000h, plane 0, the place a graphics mode 13h write to A0000h goes.
However that text mode mapping is no longer effect when in mode 13h,
and how writes to B8000h are mapped in that case is not entirely well
defined. I'd expect most VGA cards to ingore the writes, but there's
at least one VGA register configution where they could so somewhere.
The VGA Memory Map Select field has four possible values:
00b A0000h-BFFFFh
01b A0000h-AFFFFh
10b B0000h-B7FFFh
11b B8000h-BFFFFh
Note that there's one value, 00b, that maps the entire A0000h-BFFFFh
range to video memory. Unfortunately, what happens when you access memory
in the region B0000h-BFFFFh with this value selected doesn't seem to be
well defined in actual hardware.
One possible implementation is that access to B0000h-BFFFFh simply wraps
around to A0000h-BFFFFh, that is, CPU address bit 16 (A16) is simply
ingored by the VGA card. So a write to address B8000h (and A8000h) would
map to VGA address 8000h, right in the middle of mode 13h frame buffer.
The other is that the A16 bit is decoded and allows access to SuperVGA
memory (> 256kb). So a write to address B8000h would map to SVGA address
18000h, which is outside the mode 13h frame buffer.
Obviously if your PVGA card isn't a SuperVGA card and doesn't have more
256k then the later explaination wouldn't make sense. However even
then it's possible your card isn't 100% VGA compatible and uses some
other mapping that keeps your garbages writes away from the mode 13h
frame buffer.
The other alternative is that your garbage writes landed in system
memory, and I can't see how this could happen on actual hardware.
The memory controller has no idea what video mode the graphics card
is using and so can't dynamically change how it routes memory accesses
simply on that basis. For it to work the memory controller would have
to subtractively decode CPU memory accesses in the region B8000h-BFFFFh
to system RAM. That is, the memory controller would first try to peform
the access using a device bus (ISA, PCI, AGP, PCI-E, DMI, or HT) and if
that fails it would go to system memory instead.
I assume your 386SX system only has ISA slots and so your "PVGA" card
is an ISA card. In this case, I can't see this happening as there's no
reliable way to know whether an ISA bus transaction completed or not.
A write or read of a given memory location on the ISA bus can look the
same to the memory controller regardless of whether there's actually a
device on the bus that is decoding that memory location. (The device
can respond in various ways, like by asking the controller to wait until
its ready, but this isn't required. Even a read access can leave the
data bus unchanged.)
On PCI-based (including PCI-Express) systems, my understanding is this
can also never happen, but for a different reason. While PCI devices
(including AGP and PCI-Express devices) acknowledge bus cycles directed
at them, all PCI-based memory controllers I know of either positively
decode the entire A0000h-BFFFFh address range to a device bus, or
entirely to system memory. The later doesn't happen normal operations,
the one exception I know of is that it can potentially happen when the
CPU is in system management mode (SMM). There's no memory controller
configuration I've seen that would allow memory accesses in this range to
be subtractively decoded to system RAM. There's no reason to allow this,
indeed you'd never never want to use RAM that was subtractively decoded as
it would impose a huge latency penalty as the memory controller waits to
see if anything on the relatively slow device bus acknowleges the request.
So I think it's actually more likely that your 386SX/PVGA test case
actually wrote to video RAM. In any case, I think it's an unusual
case that its actually writing anywhere, and that's what my own testing
confirms. I tried various ATI cards (VGA Wonder XL, 3D Rage II+, Rage
128, Radeon 7200, Radeon 9550) and an NVIDIA card (TNT2 M64) on three
different systems (Pentium 4, Pentium 3 and Pentium MMX) and all gave
consistent results. Writes to B8000h when graphics mode 13h was active
all appeared to go nowhere.
Only under under emulated/virtualized enviroments did I see any difference
in behaviour. Under DOSBox and Windows 98 the writes did go somewhere,
virtualized RAM I assume. DOSBox also displayed different screens than
actual hardware during the test, indicating that it doesn't emulate the
VGA compatible memory mapping I described above. Under VirtualBox the
writes didn't go anywhere but the screens are also different than on
actual hardware.
Here's the code I used to perform the tests:
_TEXT SEGMENT PUBLIC WORD 'CODE'
ORG 100h
start:
; switch to each mode used in the test to ensure they all
; start in a "cleared" state
mov ax, 0003h
int 10h
mov ax, 0012h
int 10h
mov ax, 0013h
int 10h
; fill the mode 13h frame buffer with a pattern that
; should be easily recognizable in text mode
mov ax, 0a000h
mov es, ax
xor di, di
mov eax, 'a' OR 0a00h OR ('B' SHL 16) OR 40000000h
mov cx, 320 * 200 / 4
rep stosd
xor ax, ax
int 16h
; write a screenfull of words to B800:0000
mov ax, 0b800h
mov es, ax
mov ax, 'c' OR 0e00h
mov cx, 80 * 25 / 2
push cx
xor di, di
rep stosw
xchg ax, bx
xor ax, ax
int 16h
; check to see if any of the words written changed
xor si, si
pop cx
loop_check:
lods WORD PTR es:[si]
cmp ax, bx
jne fail
loop loop_check
fail:
push cx
; switch to mode 12h without clearing video memory
; this mode shows the most of video RAM of all
; standard VGA modes
mov ax, 0012h OR 80h
int 10h
xor ax, ax
int 16h
; switch to text mode without clearing the screen
mov ax, 0003h OR 80h
int 10h
xor ax, ax
int 16h
mov ax, 0003h
int 10h
mov dx, OFFSET pass_msg
pop cx
or cx, cx
jz passed
mov dx, OFFSET fail_msg
passed:
mov ah, 09h
int 21h
mov ax, 04c00h
int 21h
fail_msg:
DB 'comparison failed', 13, 10, '$'
pass_msg:
DB 'comparison passed', 13, 10, '$'
_TEXT ENDS
END start
--
l/ // Ross Ridge -- The Great HTMU
[oo][oo]
rri...@csclub.uwaterloo.ca
-()-/()/
http://www.csclub.uwaterloo.ca/~rridge/
db //