Daily development journal
Author: Devin Smith
August 26th, 2008
I decided to take a look at how FreeBSD and Linux handle the ATI SB700 southbridge chip. The good
news is that they both seem to work fine with this chip and don't have very many flaws. After looking
at both Linux support and FreeBSD support, it appears this chip can work directly with AHCI. The good
news is that OpenBSD has had ahci support since OpenBSD 4.1. The even better news, was that OpenBSD
used the ahci driver for the older SB600 chip. I took a look at the the Linux driver (in drivers/ata/ahci.c)
and also the FreeBSD driver (sys/dev/ata/ata-chipset.c) to see what kind of differences these two drivers
made that would distinguish the SB600 fom the SB700 so I would know how to adapt the SB700 for OpenBSD. The
differences were so minor and it appears that the SB700 can work without some of the SB600's hacks. Here's
the diff I made against the OpenBSD kernel.
Index: dev/pci/ahci.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/ahci.c,v
retrieving revision 1.140
diff -u -r1.140 ahci.c
--- dev/pci/ahci.c 31 May 2008 23:50:32 -0000 1.140
+++ dev/pci/ahci.c 27 Aug 2008 05:04:36 -0000
@@ -423,12 +423,16 @@
struct pci_attach_args *);
int ahci_ati_ixp600_attach(struct ahci_softc *,
struct pci_attach_args *);
+int ahci_ati_ixp700_attach(struct ahci_softc *,
+ struct pci_attach_args *);
static const struct ahci_device ahci_devices[] = {
{ PCI_VENDOR_VIATECH, PCI_PRODUCT_VIATECH_VT8251_SATA,
ahci_no_match, ahci_vt8251_attach },
{ PCI_VENDOR_ATI, PCI_PRODUCT_ATI_IXP_SATA_600,
- NULL, ahci_ati_ixp600_attach }
+ NULL, ahci_ati_ixp600_attach },
+ { PCI_VENDOR_ATI, PCI_PRODUCT_ATI_IXP_SATA_X00_1,
+ NULL, ahci_ati_ixp700_attach }
};
int ahci_pci_match(struct device *, void *, void *);
@@ -585,6 +589,12 @@
sc->sc_flags |= AHCI_F_IGN_FR;
+ return (0);
+}
+
+int
+ahci_ati_ixp700_attach(struct ahci_softc *sc, struct pci_attach_args *pa)
+{
return (0);
}
Now here is the before:
pciide0 at pci0 dev 17 function 0 "ATI IXPx00 SATA" rev 0x00: DMA (unsupported), channel 0 configured to native-PCI,
channel 1 configured to native-PCI
and after:
ahci0 at pci0 dev 17 function 0 "ATI IXPx00 SATA" rev 0x00: apic 4 int 22 (irq 10), AHCI 1.1
scsibus0 at ahci0: 32 targets, initiator 32
versions of the dmesg.
August 25th, 2008
To write a device driver you need to find out as much as possible about the hardware you are
about to be supporting. One of the first things to do was to collect some data from OpenBSD's
pcidump(8) utility.
Running pcidump in verbose mode I was able to get the following output:
0:17:0: ATI IXPx00 SATA
0x0000: Vendor ID: 1002 Product ID: 4390
0x0004: Command: 0107 Status ID: 0230
0x0008: Class: 01 Subclass: 01 Interface: 8f Revision: 00
0x000c: BIST: 00 Header Type: 00 Latency Timer: 40 Cache Line Size: 10
0x0010: BAR io addr: 0x0000b000
0x0014: BAR io addr: 0x0000a000
0x0018: BAR io addr: 0x00009000
0x001c: BAR io addr: 0x00008000
0x0020: BAR io addr: 0x00007000
0x0024: BAR mem 32bit addr: 0xfe6ff800
0x0028: Cardbus CIS: 00000000
0x002c: Subsystem Vendor ID: 1025 Product ID: 014e
0x0030: Expansion ROM Base Address: 00000000
0x0038: 00000000
0x003c: Interrupt Pin: 01 Line: 0a Min Gnt: 00 Max Lat: 00
0x0060: Capability 0x01: Power Management
0x0070: Capability 0x12: Reserved
You can also get more information on a specific piece of hardware by going to pcidatabase.com
and looking up the vendor and product id. I intended to do this but it seems that today the site
was having problems or I was having problems reaching it. Another thing I decided to do was to
see what NetBSD's pcidevs file had to say about the device. Here's what it had:
product ATI SB700_SATA_IDE 0x4390 SB700/SB800 SATA Controller (IDE Mode)
versus OpenBSD's
product ATI IXP_SATA_X00_1 0x4390 IXPx00 SATA
Based on the specifications of the motherboard inside the Gateway computer I believe that NetBSD's
description of the chip was more accurate.
August 23rd, 2008
Today I decided to get a little more information on why the ATI IXPx00 SATA device was not
supporting DMA. The first thing to do of course was to find out what part of the kernel was printing
the unsupported message and why. Using a little grep(1)
magic inside /usr/src/sys I was able to find
that pciide.c inside /usr/src/sys/dev/pci was responsible for printing the message. The function
default_chip_map prints it.
void
default_chip_map(struct pciide_softc *sc, struct pci_attach_args *pa)
{
struct pciide_channel *cp;
pcireg_t interface = PCI_INTERFACE(pa->pa_class);
pcireg_t csr;
int channel, drive;
struct ata_drive_datas *drvp;
u_int8_t idedma_ctl;
bus_size_t cmdsize, ctlsize;
char *failreason;
if (interface & PCIIDE_INTERFACE_BUS_MASTER_DMA) {
printf(": DMA");
if (sc->sc_pp == &default_product_desc &&
(sc->sc_wdcdev.sc_dev.dv_cfdata->cf_flags &
PCIIDE_OPTIONS_DMA) == 0) {
printf(" (unsupported)");
sc->sc_dma_ok = 0;
} else {
pciide_mapreg_dma(sc, pa);
if (sc->sc_dma_ok != 0)
printf(", (partial support)");
}
} else {
printf(": no DMA");
sc->sc_dma_ok = 0;
}
/* ... */
}
The first thing you can do as a developer is find out why the if statement is succeeding. Another thing you
can do is find out who calls default_chip_map by doing a search thoughout the code. If you actually look
through the code it quickly becomes apparent that default_chip_map is the generic
routine for handling generic PCI IDE devices. Near the top of the pciide.c file is a structure that maps the
top corresponding PCI device to a chip initialization function. Each vendor has a different structure and
here is ATI's:
const struct pciide_product_desc pciide_ati_products[] = {
{ PCI_PRODUCT_ATI_IXP_IDE_200,
0,
ixp_chip_map
},
{ PCI_PRODUCT_ATI_IXP_IDE_300,
0,
ixp_chip_map
},
{ PCI_PRODUCT_ATI_IXP_IDE_400,
0,
ixp_chip_map
},
{ PCI_PRODUCT_ATI_IXP_IDE_600,
0,
ixp_chip_map
},
{ PCI_PRODUCT_ATI_IXP_IDE_700,
0,
ixp_chip_map
},
{ PCI_PRODUCT_ATI_IXP_SATA_300,
0,
sii3112_chip_map
},
{ PCI_PRODUCT_ATI_IXP_SATA_400_1,
0,
sii3112_chip_map
},
{ PCI_PRODUCT_ATI_IXP_SATA_400_2,
0,
sii3112_chip_map
}
};
All the ATI IXP chips have special initialization routines, if a device is not in the list, then it calls
default_chip_map. As you can see some of the devices use the same initialization routine, so one thing we
need to do is found out if the ATI IXPx00 SATA can use one of the existing routines.
August 21th, 2008
Today I sent the dmesg out to the OpenBSD team. What I sent is here
in case anyone is interested.
I decided today to test out Midori (a new up and coming web browser that is supposed to be faster than
Firefox). OpenBSD has version 0.0.18 in ports so that is the version I
installed. Midori, while so far seems faster than Firefox, took forever to
build. This is because it required gcc 4.2 and webkit, and compiling both on
a system with a IDE controller that doesn't have DMA was painful. Midori starts
up very fast but as soon as I went to a website that had flash or any type of plugin, the
browser starting chewing up 100% cpu. Now my OpenBSD system didn't have any type of flash
plugin installed so I don't know what was going on. I ended up having to kill the process.
I'll probably keep trying Midori and testing it as new versions are released. It does look
promising.
August 20th, 2008
I decided to update the entire OpenBSD system to current so that I could
work on testing and developing with ports. As I was extracting source code so
that I could rebuild everything I noticed
that the system became quite sluggish. It was slower than my 2001 laptop even, and
so the first thing that I did was recompile the kernel. The new dmesg is here:
dmesg. The problem did not
get fixed and it was at this time I noticed that the kernel was now only
recognizing half of my installed memory.
OpenBSD 4.4 (GENERIC.MP) #1809: Wed Aug 6 11:38:06 MDT 2008
deraadt@amd64.openbsd.org:/usr/src/sys/arch/amd64/compile/GENERIC.MP
real mem = 6160216064 (5874MB)
avail mem = 5973213184 (5696MB)
versus
OpenBSD 4.4-current (GENERIC.MP) #0: Wed Aug 20 11:54:22 PDT 2008
devin@gateway:/usr/src/sys/arch/amd64/compile/GENERIC.MP
real mem = 3207413760 (3058MB)
avail mem = 3110494208 (2966MB)
I also noticed the reason for the
very slow response when I was extracting files. A line in the dmesg said
that the pciide0 controller was running without DMA support (bold text added by me).
pciide0 at pci0 dev 17 function 0 "ATI IXPx00 SATA" rev 0x00: DMA (unsupported), channel 0 configured to native-PCI,
channel 1 configured to native-PCI
It was running
with the old PIO mode which is super
slow. I gathered as much data as I could to prepare to send a dmesg out to the OpenBSD development team.
August 15th, 2008
About 1 week ago, on August 10th, I picked up a new Gateway computer.
After making sure that the system worked with the supplied Microsoft Windows Vista
I proceeded to repartition the system (after all, it came with 640 GB of
space) and install OpenBSD. I was surprised to find out that Windows Vista
comes with the ability resize a partition. You can find it in the disk management portion of the computer
management control panel extension. The disk partitioner was fast and seems to have worked very well.
I decided to go with an OpenBSD snapshot to make sure that the upcoming OpenBSD 4.4
would work with the new hardware. I installed an OpenBSD snapshot, and got
the system setup to dual boot into OpenBSD and Windows Vista. Dual booting Vista
and OpenBSD is a lot more difficult than it was with Windows XP. I have used
the following article that describes how it can be done:
Dual booting Vista and OpenBSD.
At this point here is what the dmesg looked like: dmesg.
For those that do know, the dmesg prints the message buffer of the kernel.
With OpenBSD it is often very useful/interesting to look through the dmesg to
see if there are any problems with hardware and to see what hardware is
recognized.