qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] qemu-system-ppc -m g3beige -hda is setting /dev/hdc on Linu


From: Rob Landley
Subject: [Qemu-devel] qemu-system-ppc -m g3beige -hda is setting /dev/hdc on Linux.
Date: Sat, 13 Feb 2010 02:02:00 -0600
User-agent: KMail/1.11.2 (Linux/2.6.28-17-generic; KDE/4.2.2; x86_64; ; )

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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]