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