Xbox & nForce shared memory & video base address
Michael Steil <[email protected]> Mon, 1 Aug 2005 02:21:23 +0200
| Newsgroups | gmane.linux.ports.xbox.devel |
|---|---|
| Message-ID | <[email protected]> |
Hi!
I own an nForce 420D board (MS-6367), which is the nForce version
most similar to the Xbox chipset. It also uses shared memory, and in
the BIOS, it is possible to give 32 (default) or 16 MB to the video
hardware. The lower (TOTALMEM-VIDEOMEM) MB will be given to the CPU,
and the upper memory will be available to the video hardware only.
On the Xbox, the default setting (i.e. the setting in games, and,
since we don't know yet how to change it, also the setting inside
Xbox-Linux) is that the CPU and the video hardware completely share
the 64 MB or RAM. CPU address 0 matches video address 0.
I strongly suspect that the settings for the base address of video
RAM, i.e. the physical address that video address 0 translates to,
must be stored in the PCI config space. There are two other
possibilities:
* In some other config of the memory controllers or the bridges, but
none of these devices on the Xbox has additional I/O ports or MMIO
regions.
* In the VGA MMIO registers - but this would mean that a VGA driver
could set the base address to 0 and easily write into CPU RAM. This
is certainly not possible.
I made a complete PCI config space dump on the nForce using "lspci -
xxx" with 16 and 32 MB video RAM configured in the BIOS. The machine
has 384 MB or RAM installed, which is 0x18000000 bytes. So with 16 MB
of video RAM, there would be 0x17000000 bytes left, and with 32 MB,
0x16000000 bytes.
I dumped the PCI config space several times, and rebooted in-between,
in order to sort out changes that are unrelated to the video RAM
configuration.
-----------------------
0000:00:00.0 Host bridge: nVidia Corporation nForce CPU bridge (rev b2)
84: 16ffffff/15ffffff
94: dfb57e3e/dfb57a37
0000:00:00.1 RAM memory: nVidia Corporation nForce 220/420 Memory
Controller (rev b2)
7c: 170f13d0/170f17d0
c0: 00000016/00000017
0000:00:00.2 RAM memory: nVidia Corporation nForce 220/420 Memory
Controller (rev b2)
70: 2fffffff/2fbdffff
74: 67df7fff/659f7fff
78: 7fffffff/7fff7fff
7c: 5edfffff/5e1fffff
80: 7ef5ffff/7ef6bfff
84: 7e5fffff/7647bfff
88: 7fffbfff/7eb5bfff
8c: 77ffffff/7ff7ffff
c8: 8000a95d/8000a94e
0000:00:01.0 ISA bridge: nVidia Corporation nForce ISA Bridge (rev c3)
80: 07001100/04001100
d0: 7e7e7f78/7e707f78
0000:00:08.0 PCI bridge: nVidia Corporation nForce PCI-to-PCI bridge
(rev c2)
50: 16fe0d0c/15fe0d0c
0000:00:1e.0 PCI bridge: nVidia Corporation nForce AGP to PCI Bridge
(rev b2)
44: 16f00000/15f00000
-----------------------
What we knew already is that the amount of memory available to the
CPU is stored in 0:0.0-84 in the PCI config space. The X-Codes set it
to the highest memory address (either 0x7FFFFFF for 128 MB or
0x3FFFFFF for 64 MB). On an nForce board, this is set to the amount
of total memory installed minus the configured video memory minus one
(in my case 16ffffff for 384 MB minus 16 MB video RAM and 15ffffff
for 384 MB minus 32 MB video RAM).
Some more easy to explain differences:
0:00.1-c0: "CPU_RAM >> 48"
0:08.0-50: "(CPU_RAM-1) & 0xfffe0000 | 0x0d0c"
0:1e.0-44: "(CPU_RAM-1) & 0xfff00000"
All other differences are hard to explain, especially all these
differences in 0:0.2.
But we can exclude some of these differences as candidates, as some
devices cannot be related. Here is the list of devices with
differences again:
0000:00:00.0 Host bridge: nVidia Corporation nForce CPU bridge (rev b2)
0000:00:00.1 RAM memory: nVidia Corporation nForce 220/420 Memory
Controller (rev b2)
0000:00:00.2 RAM memory: nVidia Corporation nForce 220/420 Memory
Controller (rev b2)
0000:00:01.0 ISA bridge: nVidia Corporation nForce ISA Bridge (rev c3)
0000:00:08.0 PCI bridge: nVidia Corporation nForce PCI-to-PCI bridge
(rev c2)
0000:00:1e.0 PCI bridge: nVidia Corporation nForce AGP to PCI Bridge
(rev b2)
The RAM controllers 0:0.1 and 0:0.2 cannot be related, as they do not
exist on the Xbox. Honestly, I have no idea why the nForce 420 has
three different RAM controllers (0:0.1 through 0:0.3) and the Xbox
has only one. We can be sure that controllers 1 and 2 really do not
exist on the Xbox, because the Xcodes never touch these devices - and
of course because we know that reading any byte from their config
space freezes the machine (interestingly, writing is okay, though).
In theory, the VGA base setting could be inside one of the missing
memory controllers, but I doubt that. These are the three nForce
memory controllers:
0000:00:00.1 RAM memory: nVidia Corporation nForce 220/420 Memory
Controller (rev b2)
0000:00:00.2 RAM memory: nVidia Corporation nForce 220/420 Memory
Controller (rev b2)
0000:00:00.3 RAM memory: nVidia Corporation nForce 420 Memory
Controller (DDR) (rev b2)
Although 1 and 2 have different PCI device IDs, the names from the
PCI ID database (and I hope they are reliable) suggest that 1 and 2
are more or less symmetrical, and that device 3 is some kind of
master. This is supported by the fact that the nForce 420 (IGP-128)
includes "TwinBank", i.e. it can address two 64 bit DIMMs at the same
time. I suspect that the nForce 220 (IGP-64) only has one "slave"
memory controller (I don't have a 220). But this still does not
explain why the Xbox has none...
Back to the possible devices. I also exclude the ISA and PCI bridges,
as the video hardware is located on neither of these busses. So what
we have left is this:
0000:00:00.0 Host bridge: nVidia Corporation nForce CPU bridge (rev b2)
84: 16ffffff/15ffffff
94: dfb57e3e/dfb57a37
0000:00:1e.0 PCI bridge: nVidia Corporation nForce AGP to PCI Bridge
(rev b2)
44: 16f00000/15f00000
0:0.0-84 seems to have nothing to do with the base address; it only
specifies where to wrap around CPU memory. The meaning of 0:0.0-94 is
unknown.
The dword at 0:1e.0-44 will always be ANDed with 0xfff00000 when
written to. The location exists also on the Xbox, but the behaviour
is different: It is ANDed with 0xff000000. In case this is really the
video base address, then the granularity is 1 MB on the nForce and 16
MB on the Xbox - this would be quite a waste of memory!
Unfortunately, writing to 0:1e.0-44 has no effect on the Xbox. I
cannot test it on the nForce whether this is the correct location,
but at least it does not seem to work on the Xbox.
This is the code I used (inside Cromwell):
#define CPU_RAM ((128-16)*1024*1024-1)
outl((1 << 31) | (0<<16) | (0x00<<11) | (0<<8) | 0x84, 0xcf8);
outl(CPU_RAM-1, 0xcfc);
outl((1 << 31) | (0<<16) | (0x1e<<11) | (0<<8) | 0x44, 0xcf8);
outl(CPU_RAM-1, 0xcfc);
int ttt;
outl((1 << 31) | (0<<16) | (0x00<<11) | (0<<8) | 0x84, 0xcf8);
ttt = inl(0xcfc);
printk("%08x\n",ttt);
outl((1 << 31) | (0<<16) | (0x1e<<11) | (0<<8) | 0x44, 0xcf8);
ttt = inl(0xcfc);
printk("%08x\n",ttt);
It returned 0x6fffffff and 0x60000000 as expected, but had no effect
on the framebuffer (i.e. the picture was still visible).
It might well be the case that it is not possible at all to change
the base of video memory - if nForce has been finished *after* the
Xbox chipset, then the Xbox chipset might not yet have included this
feature - as it is not necessary for game operation.
Let us have a look at the revisions of the PCI devices in nForce and
Xbox:
Xbox nForce
0:00.0 a1 b2
0:00.3 a1 b2
0:1e.0 a1 b2
1:00.0 a1 b1
0:01.0 d4 c3
0:01.1 d1 c1
0:02.0 d4 c3
0:03.0 d4 c3
0:05.0 d2 c2
0:06.0 d2 c2
0:08.0 d2 c2
0:09.0 d4 c3
All revisions of devices contained in the Northbridge are older on
the Xbox, and all devices in the Southbridge are newer on the Xbox.
(A string in the BIOS of my nForce supports that the Northbridge is
indeed revision B2.)
So the Xbox GPU seems indeed older than the nForce GPU (while,
interestingly, the MCPX is a revised version of the MCP!). Maybe the
Xbox really does not have this feature.
Tomorrow, I am going to play around with 0:1e.0-44 on the nForce and
see whether this really is the register we are looking for. If it is,
then it seems to be the proof that it is impossible to change the
video RAM base address on the Xbox...
Michael