Sunday, October 11, 2009

Radeon Driver Installation

This post details the steps undertaken to merge the Radeon driver into the source tree. The driver doesn't come with installation instructions, as it is presumed that everyone already knows how to plug it in. Therefore, these instructions are directed to the truly clueless (i.e., I could have really used them a few minutes ago).

Graphics drivers for Plan 9 are divided into two components. The kernel component is responsible for enabling the hardware, handling the cursor, and providing accelerated fill and scroll functions, among other things. The userland component, named aux/vga, is responsible for modesetting and implementing an interface to the card. Thankfully, this is all nicely detailed in /sys/src/cmd/aux/vga/notes.txt.

The three files {radeon.c, radeon.h, radeon_pciids.h} are part of the userspace component of the driver, and consequently go into /sys/src/cmd/aux/vga. To install them, copy the above files into that folder, and then perform the following steps:
  1. Update the mkfile by adding the text " radeon.$O\" as part of the $OFILES variable, in the obvious way.
  2. Add the lines "extern Ctlr radeon;" and "extern Ctlr radeonhwgc;" to vga.h. This allows the vgadb to determine which controller to activate.
  3. Add the lines "&radeon," and "&radeonhwgc," to data.c in the obvious location.
  4. Build the program by issuing the "mk" command, and observe that 8.out is successfully created.
The driver also comes with a file called vgaradeon.c, which is the kernel component of the driver. If you examine /sys/src/9/pc, you'll notice that there are many files that contain the same "vga" prefix, which is used by the mkfile to fill in the $VGA variable for building. But to actually integrate this driver into the build process, we need to copy vgaradeon.c into this folder, and then update a bunch of other files (which were determined by looking at the vganvidia driver, and by selective grepping).

If you grep for "nvidia", you'll notice that this string is contained within certain files without extensions that provide build targets for mk. Specifically, these files are: {pc, pccd, pccpuf, pcdisk, pcf, pcfl, pcflop}. To each of these files, add the line " vgaradeon +cur" immediately after the " vganvidia +cur" line. Then issue "mk 'CONF=pcdisk'", and observe that the "pcdisk" file is built successfully.

[Do note, however, that the kernel Radeon driver depends on the {radeon.h, radeon_pciids.h} files in aux/vga, and that if you are building from a location other than /sys/src, you may have to change radeon.c to address the headers relatively, for example by "#include ../../cmd/aux/vga/radeon.h".]

Finally, we need to update the /lib/vgadb file with Radeon PCI device IDs, so that aux/vga can map them with the radeon and radeonhwgc controllers. Since I don't have write permissions on /lib/vgadb, I instead rebound an updated file over it in my namespace. You can do this by running "cat radeon_vgadb /lib/vgadb > $home/vgadb_radeon", and then overlay this new file on top of the original by running "bind $home/vgadb_radeon /lib/vgadb". If you have a Radeon card covered by the pciids in the driver, your new aux/vga version should be able to identify it.

This concludes the explanation of how to install the Radeon driver for Plan 9.

Unfortunately, for my special case, it isn't exactly as simple. The function that the kernel and aux/vga use to find a suitable Radeon card is called pcimatch(), which exists in both /sys/src/9/pc/pci.c (with the header "Needs a massive rewrite.") and /sys/src/cmd/aux/vga/pci.c (with no such header). This function takes a callback-like object (very useful in a few seconds!), a vendor ID, and a device ID, and attempts to locate a match in the PCI list. Both kernel and userspace radeon drivers use this function while specifying a device ID of 0, which means "I don't care what the device ID is; just find me something that has ATI as the vendor."

I have an ATI motherboard. If I issue the "pci" command, it becomes pretty evident that ATI is listed as the vendor for 12/17 of the devices on my system. So, the driver's default action is to complain that my Fast EtherLink PCI TX is not a known graphics card, and then drop out. The suboptimal solution is to use the first argument of pcimatch() to look for the next device with the same vendor ID, and so on. That's what I am doing, because it doesn't involve changing pcimatch().

A better solution would be to have pcimatch() take an int list of valid device IDs for that vendor. I should figure out who owns that file (how?).

Fighting with PXE over. Fighting with Plan9 begins!

The original plan was to have the computer with the Radeon X1600 PXE-boot a kernel from a tftp server writable by the development host. The kernel would then connect to the auth and file servers, load a filesystem with the most recent version of aux/vga, and display a tty.

Unfortunately, after configuring the network and getting a kernel to boot, the plan collapsed: PXE appears to not properly reset the network card (a Realtek RTL8139 [0x10ec, 0x8139]), so the booted kernel could not connect to the auth server. So, at least for the time being, we're avoiding PXE and are instead booting from a local 9fat partition. This is more tedious, since each kernel revision must be explicitly written to the disk, and we need a working local kernel to do that. But it functions, and we have discovered yet another project for a rainy day.

I took a few minutes to modify 9/pc/kdb.c, changing the default hardcoded Qwerty layout to my preferred Dvorak. Feels like home.

Sunday, September 27, 2009


Здравствуйте. This site is a detailed story about writing/updating an ATI Radeon driver for the Plan 9 operating system to support modern GPUs. This project is being completed as part of the 15-412 (Operating Systems Practicum) course at Carnegie Mellon University. Nevertheless, this story is directed to a general audience, who I will be presupposing is familiar with neither Radeon internals nor Plan9 whatsoever. Occasionally, I will distract the audience and myself with dancing kitten macros. It'll be a good time.

As of the moment, the most recent release of Plan 9 (meaning, that release that was made seven years ago) does not include a driver for any Radeon card. However, there exists an unmerged driver called "radeon" floating around the Internet, written by Philippe Anel, and updated by Venkatesh Srinivas and others, located here [tar.gz] for the time being. This particular driver provides support for the Radeon R200 and R300 series, which also date back to ~2002.

For an overview of the different R* series that ATI created, there is the complete list of ATI cards, which provides a mapping between R* series and marketing name.

I have a desktop with a Radeon X1600, which is an R5xx-series card from approximately 2005. The current goal is to generate a driver to get a usable desktop from that card and hopefully scale that driver to also support the R600 and R700 series, which use a different acceleration mechanism than the R200s and R300s. Sanity preservation is also an important part of this project!

Right now, I have lugged the computer with the X1600 into our lab, and am waiting for network privileges so I can PXE-boot a freshly-compiled Plan 9 kernel from our server. Then, I will become intimately familiar with the Acid debugger, to debug a remote kernel over a serial port. After that, I will sleep for a while.