The -hda, -hdb, -hdc, and -hdd command line options for g3beige don't match the order the kernel assigns the drives.
The reason is that the Linux kernel always initializes the cmd646 driver before the pmac driver, thus if there's a cmd646 it gets /dev/hda and /dev/hdb, and the pmac gets /dev/hdc and /dev/hdb. If you only supply an -hda (and/or -hdb) with no -hdc or -hdd, then the cmd646 driver never attaches to anything and only the pmac controller shows up, thus -hda and -hdb set /dev/hda and /dev/hdb. But if you specify a -hdc it shows up as /dev/hda every time, and kicks the -hda entry to /dev/hdc. Note that neither the kernel's CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST nor CONFIG_IDEPCI_PCIBUS_ORDER made any difference, because those affect multiple devices handled by the same driver, and this is a static driver initialization order issue. When you statically link in both drivers, cmd64x always probes before pmac due to the above hardwired device order in the kernel, 100% reliable and deterministic. It's hardwired, and you have to patch the kernel to change it. Here's a patch to the Linux kernel that changes the device probe order so the kernel behaves like g3beige is expecting it to: --- a/drivers/ide/Makefile +++ b/drivers/ide/Makefile @@ -39,6 +39,7 @@ obj-$(CONFIG_BLK_DEV_AMD74XX) += amd74xx.o obj-$(CONFIG_BLK_DEV_ATIIXP) += atiixp.o obj-$(CONFIG_BLK_DEV_CELLEB) += scc_pata.o +obj-$(CONFIG_BLK_DEV_IDE_PMAC) += pmac.o obj-$(CONFIG_BLK_DEV_CMD64X) += cmd64x.o obj-$(CONFIG_BLK_DEV_CS5520) += cs5520.o obj-$(CONFIG_BLK_DEV_CS5530) += cs5530.o @@ -76,8 +77,6 @@ obj-$(CONFIG_BLK_DEV_CMD640) += cmd640.o -obj-$(CONFIG_BLK_DEV_IDE_PMAC) += pmac.o - obj-$(CONFIG_IDE_H8300) += ide-h8300.o obj-$(CONFIG_IDE_GENERIC) += ide-generic.o The problem is, the kernel guys will never take that patch upstream because what they're currently doing isn't actually wrong. Their behavior is consistent, the kernel's been probing the same devices in the same order since the 90's, and they don't really care what order things go in. The problem is that the association between qemu's command line arguments and the devices they refer to is somewhat arbitrary. On the other targets I've used (arm, mips, x86, and so on), the device QEMU initializes in response to "-hda" is the one the Linux kernel makes /dev/hda (or /dev/sda), and the one it intializes in response to "-hdc" is the one Linux makes /dev/hdc. But in this case, they don't match up, and that's screwing up my same init/build script that works fine on all the other tarets. Here's a patch to QEMU that makes those arguments intialize the devices the kernel expects them to. This doesn't change where any of the hardware is on the board, just which command line arguments associate with which drives: --- a/hw/ppc_oldworld.c +++ b/hw/ppc_oldworld.c @@ -346,16 +346,16 @@ static void ppc_heathrow_init (ram_addr_t ram_size, exit(1); } - /* First IDE channel is a MAC IDE on the MacIO bus */ - hd[0] = drive_get(IF_IDE, 0, 0); - hd[1] = drive_get(IF_IDE, 0, 1); + /* Second IDE channel is a MAC IDE on the MacIO bus */ + hd[0] = drive_get(IF_IDE, 1, 0); + hd[1] = drive_get(IF_IDE, 1, 1); dbdma = DBDMA_init(&dbdma_mem_index); ide_mem_index[0] = -1; ide_mem_index[1] = pmac_ide_init(hd, pic[0x0D], dbdma, 0x16, pic[0x02]); - /* Second IDE channel is a CMD646 on the PCI bus */ - hd[0] = drive_get(IF_IDE, 1, 0); - hd[1] = drive_get(IF_IDE, 1, 1); + /* First IDE channel is a CMD646 on the PCI bus */ + hd[0] = drive_get(IF_IDE, 0, 0); + hd[1] = drive_get(IF_IDE, 0, 1); hd[3] = hd[2] = NULL; pci_cmd646_ide_init(pci_bus, hd, 0); Rob -- Latency is more important than throughput. It's that simple. - Linus Torvalds