qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH 1/8] kill drives_table


From: Gerd Hoffmann
Subject: [Qemu-devel] [PATCH 1/8] kill drives_table
Date: Wed, 22 Jul 2009 12:25:00 +0200

First step cleaning up the drives handling.  This one does nothing but
removing drives_table[], still it became seriously big.

drive_get_index() is gone and is replaced by drives_get() which hands
out DriveInfo pointers instead of a table index.  This needs adaption in
*tons* of places all over.

The drives are now maintained as linked list.

Signed-off-by: Gerd Hoffmann <address@hidden>
---
 hw/device-hotplug.c           |   23 +++---
 hw/etraxfs.c                  |    5 +-
 hw/gumstix.c                  |   16 ++--
 hw/mainstone.c                |    9 +-
 hw/mips_jazz.c                |    7 +-
 hw/mips_malta.c               |   24 ++----
 hw/mips_r4k.c                 |   13 +--
 hw/musicpal.c                 |   10 +-
 hw/nand.c                     |    8 +-
 hw/omap1.c                    |    8 +-
 hw/omap2.c                    |    8 +-
 hw/omap_sx1.c                 |   10 +-
 hw/onenand.c                  |    6 +-
 hw/pc.c                       |   21 ++---
 hw/pci-hotplug.c              |   28 ++++---
 hw/petalogix_s3adsp1800_mmu.c |    5 +-
 hw/ppc405_boards.c            |   34 ++++----
 hw/ppc440_bamboo.c            |    5 +-
 hw/ppc_newworld.c             |    9 +--
 hw/ppc_oldworld.c             |   30 ++-----
 hw/ppc_prep.c                 |   16 +---
 hw/ppce500_mpc8544ds.c        |    5 +-
 hw/pxa2xx.c                   |   16 ++--
 hw/qdev.c                     |   17 ++---
 hw/r2d.c                      |    5 +-
 hw/spitz.c                    |    8 +-
 hw/sun4m.c                    |   16 ++--
 hw/sun4u.c                    |   18 ++---
 hw/tosa.c                     |    8 +-
 hw/xen_disk.c                 |   14 ++--
 hw/xen_machine_pv.c           |    9 +-
 monitor.c                     |   12 ++-
 qemu-char.c                   |    6 +-
 savevm.c                      |   32 ++++---
 sysemu.h                      |   13 ++--
 vl.c                          |  177 ++++++++++++++++++++---------------------
 36 files changed, 308 insertions(+), 343 deletions(-)

diff --git a/hw/device-hotplug.c b/hw/device-hotplug.c
index e178083..5257274 100644
--- a/hw/device-hotplug.c
+++ b/hw/device-hotplug.c
@@ -28,22 +28,23 @@
 #include "block_int.h"
 #include "sysemu.h"
 
-int add_init_drive(const char *opts)
+DriveInfo *add_init_drive(const char *opts)
 {
-    int drive_opt_idx, drive_idx;
-    int ret = -1;
+    int drive_opt_idx;
+    int fatal_error;
+    DriveInfo *dinfo;
 
     drive_opt_idx = drive_add(NULL, "%s", opts);
     if (!drive_opt_idx)
-        return ret;
+        return NULL;
 
-    drive_idx = drive_init(&drives_opt[drive_opt_idx], 0, current_machine);
-    if (drive_idx == -1) {
+    dinfo = drive_init(&drives_opt[drive_opt_idx], 0, current_machine, 
&fatal_error);
+    if (!dinfo) {
         drive_remove(drive_opt_idx);
-        return ret;
+        return NULL;
     }
 
-    return drive_idx;
+    return dinfo;
 }
 
 void destroy_nic(dev_match_fn *match_fn, void *arg)
@@ -64,11 +65,11 @@ void destroy_nic(dev_match_fn *match_fn, void *arg)
 
 void destroy_bdrvs(dev_match_fn *match_fn, void *arg)
 {
-    int i;
+    DriveInfo *dinfo;
     struct BlockDriverState *bs;
 
-    for (i = 0; i <= MAX_DRIVES; i++) {
-        bs = drives_table[i].bdrv;
+    TAILQ_FOREACH(dinfo, &drives, next) {
+        bs = dinfo->bdrv;
         if (bs) {
             if (bs->private && match_fn(bs->private, arg)) {
                 drive_uninit(bs);
diff --git a/hw/etraxfs.c b/hw/etraxfs.c
index c2eca52..ab6a3a3 100644
--- a/hw/etraxfs.c
+++ b/hw/etraxfs.c
@@ -55,6 +55,7 @@ void bareetraxfs_init (ram_addr_t ram_size,
     void *etraxfs_dmac;
     struct etraxfs_dma_client *eth[2] = {NULL, NULL};
     int kernel_size;
+    DriveInfo *dinfo;
     int i;
     ram_addr_t phys_ram;
     ram_addr_t phys_flash;
@@ -79,9 +80,9 @@ void bareetraxfs_init (ram_addr_t ram_size,
 
 
     phys_flash = qemu_ram_alloc(FLASH_SIZE);
-    i = drive_get_index(IF_PFLASH, 0, 0);
+    dinfo = drive_get(IF_PFLASH, 0, 0);
     pflash_cfi02_register(0x0, phys_flash,
-                          i != -1 ? drives_table[i].bdrv : NULL, (64 * 1024),
+                          dinfo ? dinfo->bdrv : NULL, (64 * 1024),
                           FLASH_SIZE >> 16,
                           1, 2, 0x0000, 0x0000, 0x0000, 0x0000,
                           0x555, 0x2aa);
diff --git a/hw/gumstix.c b/hw/gumstix.c
index 85b95ee..8fbf64c 100644
--- a/hw/gumstix.c
+++ b/hw/gumstix.c
@@ -47,22 +47,22 @@ static void connex_init(ram_addr_t ram_size,
                 const char *initrd_filename, const char *cpu_model)
 {
     PXA2xxState *cpu;
-    int index;
+    DriveInfo *dinfo;
 
     uint32_t connex_rom = 0x01000000;
     uint32_t connex_ram = 0x04000000;
 
     cpu = pxa255_init(connex_ram);
 
-    index = drive_get_index(IF_PFLASH, 0, 0);
-    if (index == -1) {
+    dinfo = drive_get(IF_PFLASH, 0, 0);
+    if (!dinfo) {
         fprintf(stderr, "A flash image must be given with the "
                 "'pflash' parameter\n");
         exit(1);
     }
 
     if (!pflash_cfi01_register(0x00000000, qemu_ram_alloc(connex_rom),
-            drives_table[index].bdrv, sector_len, connex_rom / sector_len,
+            dinfo->bdrv, sector_len, connex_rom / sector_len,
             2, 0, 0, 0, 0)) {
         fprintf(stderr, "qemu: Error registering flash memory.\n");
         exit(1);
@@ -81,22 +81,22 @@ static void verdex_init(ram_addr_t ram_size,
                 const char *initrd_filename, const char *cpu_model)
 {
     PXA2xxState *cpu;
-    int index;
+    DriveInfo *dinfo;
 
     uint32_t verdex_rom = 0x02000000;
     uint32_t verdex_ram = 0x10000000;
 
     cpu = pxa270_init(verdex_ram, cpu_model ?: "pxa270-c0");
 
-    index = drive_get_index(IF_PFLASH, 0, 0);
-    if (index == -1) {
+    dinfo = drive_get(IF_PFLASH, 0, 0);
+    if (!dinfo) {
         fprintf(stderr, "A flash image must be given with the "
                 "'pflash' parameter\n");
         exit(1);
     }
 
     if (!pflash_cfi01_register(0x00000000, qemu_ram_alloc(verdex_rom),
-            drives_table[index].bdrv, sector_len, verdex_rom / sector_len,
+            dinfo->bdrv, sector_len, verdex_rom / sector_len,
             2, 0, 0, 0, 0)) {
         fprintf(stderr, "qemu: Error registering flash memory.\n");
         exit(1);
diff --git a/hw/mainstone.c b/hw/mainstone.c
index 151ea0e..3e517f0 100644
--- a/hw/mainstone.c
+++ b/hw/mainstone.c
@@ -77,7 +77,8 @@ static void mainstone_common_init(ram_addr_t ram_size,
     target_phys_addr_t mainstone_flash_base[] = { MST_FLASH_0, MST_FLASH_1 };
     PXA2xxState *cpu;
     qemu_irq *mst_irq;
-    int i, index;
+    DriveInfo *dinfo;
+    int i;
 
     if (!cpu_model)
         cpu_model = "pxa270-c5";
@@ -92,8 +93,8 @@ static void mainstone_common_init(ram_addr_t ram_size,
 
     /* There are two 32MiB flash devices on the board */
     for (i = 0; i < 2; i ++) {
-        index = drive_get_index(IF_PFLASH, 0, i);
-        if (index == -1) {
+        dinfo = drive_get(IF_PFLASH, 0, i);
+        if (!dinfo) {
             fprintf(stderr, "Two flash images must be given with the "
                     "'pflash' parameter\n");
             exit(1);
@@ -101,7 +102,7 @@ static void mainstone_common_init(ram_addr_t ram_size,
 
         if (!pflash_cfi01_register(mainstone_flash_base[i],
                                 qemu_ram_alloc(MAINSTONE_FLASH),
-                                drives_table[index].bdrv, sector_len,
+                                dinfo->bdrv, sector_len,
                                 MAINSTONE_FLASH / sector_len, 4, 0, 0, 0, 0)) {
             fprintf(stderr, "qemu: Error registering flash memory.\n");
             exit(1);
diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c
index 82cd385..e09a6b2 100644
--- a/hw/mips_jazz.c
+++ b/hw/mips_jazz.c
@@ -235,11 +235,8 @@ void mips_jazz_init (ram_addr_t ram_size,
         exit(1);
     }
     for (n = 0; n < MAX_FD; n++) {
-        int fd = drive_get_index(IF_FLOPPY, 0, n);
-        if (fd != -1)
-            fds[n] = drives_table[fd].bdrv;
-        else
-            fds[n] = NULL;
+        DriveInfo *dinfo = drive_get(IF_FLOPPY, 0, n);
+        fds[n] = dinfo ? dinfo->bdrv : NULL;
     }
     fdctrl_init(rc4030[1], 0, 1, 0x80003000, fds);
 
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index 7728e58..4e51c8d 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -773,7 +773,7 @@ void mips_malta_init (ram_addr_t ram_size,
     uint8_t *eeprom_buf;
     i2c_bus *smbus;
     int i;
-    int index;
+    DriveInfo *dinfo;
     BlockDriverState *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
     BlockDriverState *fd[MAX_FD];
     int fl_idx = 0;
@@ -827,8 +827,8 @@ void mips_malta_init (ram_addr_t ram_size,
         env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL));
         write_bootloader(env, qemu_get_ram_ptr(bios_offset), kernel_entry);
     } else {
-        index = drive_get_index(IF_PFLASH, 0, fl_idx);
-        if (index != -1) {
+        dinfo = drive_get(IF_PFLASH, 0, fl_idx);
+        if (dinfo) {
             /* Load firmware from flash. */
             bios_size = 0x400000;
             fl_sectors = bios_size >> 16;
@@ -836,10 +836,10 @@ void mips_malta_init (ram_addr_t ram_size,
             printf("Register parallel flash %d size " TARGET_FMT_lx " at "
                    "offset %08lx addr %08llx '%s' %x\n",
                    fl_idx, bios_size, bios_offset, 0x1e000000LL,
-                   bdrv_get_device_name(drives_table[index].bdrv), fl_sectors);
+                   bdrv_get_device_name(dinfo->bdrv), fl_sectors);
 #endif
             pflash_cfi01_register(0x1e000000LL, bios_offset,
-                                  drives_table[index].bdrv, 65536, fl_sectors,
+                                  dinfo->bdrv, 65536, fl_sectors,
                                   4, 0x0000, 0x0000, 0x0000, 0x0000);
             fl_idx++;
         } else {
@@ -898,11 +898,8 @@ void mips_malta_init (ram_addr_t ram_size,
     }
 
     for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) {
-        index = drive_get_index(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
-        if (index != -1)
-            hd[i] = drives_table[index].bdrv;
-        else
-            hd[i] = NULL;
+        dinfo = drive_get(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
+        hd[i] = dinfo ? dinfo->bdrv : NULL;
     }
 
     piix4_devfn = piix4_init(pci_bus, 80);
@@ -929,11 +926,8 @@ void mips_malta_init (ram_addr_t ram_size,
     if (parallel_hds[0])
         parallel_init(0x378, i8259[7], parallel_hds[0]);
     for(i = 0; i < MAX_FD; i++) {
-        index = drive_get_index(IF_FLOPPY, 0, i);
-       if (index != -1)
-           fd[i] = drives_table[index].bdrv;
-       else
-           fd[i] = NULL;
+        dinfo = drive_get(IF_FLOPPY, 0, i);
+        fd[i] = dinfo ? dinfo->bdrv : NULL;
     }
     floppy_controller = fdctrl_init(i8259[6], 2, 0, 0x3f0, fd);
 
diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c
index 7f8af74..476612c 100644
--- a/hw/mips_r4k.c
+++ b/hw/mips_r4k.c
@@ -155,8 +155,8 @@ void mips_r4k_init (ram_addr_t ram_size,
     RTCState *rtc_state;
     int i;
     qemu_irq *i8259;
-    int index;
     BlockDriverState *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
+    DriveInfo *dinfo;
 
     /* init CPUs */
     if (cpu_model == NULL) {
@@ -208,11 +208,11 @@ void mips_r4k_init (ram_addr_t ram_size,
                                      bios_offset | IO_MEM_ROM);
 
         load_image_targphys(filename, 0x1fc00000, BIOS_SIZE);
-    } else if ((index = drive_get_index(IF_PFLASH, 0, 0)) > -1) {
+    } else if ((dinfo = drive_get(IF_PFLASH, 0, 0)) != NULL) {
         uint32_t mips_rom = 0x00400000;
         bios_offset = qemu_ram_alloc(mips_rom);
         if (!pflash_cfi01_register(0x1fc00000, bios_offset,
-            drives_table[index].bdrv, sector_len, mips_rom / sector_len,
+            dinfo->bdrv, sector_len, mips_rom / sector_len,
             4, 0, 0, 0, 0)) {
             fprintf(stderr, "qemu: Error registering flash memory.\n");
        }
@@ -267,11 +267,8 @@ void mips_r4k_init (ram_addr_t ram_size,
     }
 
     for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) {
-        index = drive_get_index(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
-        if (index != -1)
-            hd[i] = drives_table[index].bdrv;
-        else
-            hd[i] = NULL;
+        dinfo = drive_get(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
+        hd[i] = dinfo ? dinfo->bdrv : NULL;
     }
 
     for(i = 0; i < MAX_IDE_BUS; i++)
diff --git a/hw/musicpal.c b/hw/musicpal.c
index e636791..2d26b33 100644
--- a/hw/musicpal.c
+++ b/hw/musicpal.c
@@ -1512,8 +1512,8 @@ static void musicpal_init(ram_addr_t ram_size,
     qemu_irq pic[32];
     DeviceState *dev;
     int i;
-    int index;
     unsigned long flash_size;
+    DriveInfo *dinfo;
 
     if (!cpu_model)
         cpu_model = "arm926";
@@ -1549,9 +1549,9 @@ static void musicpal_init(ram_addr_t ram_size,
                    serial_hds[1], 1);
 
     /* Register flash */
-    index = drive_get_index(IF_PFLASH, 0, 0);
-    if (index != -1) {
-        flash_size = bdrv_getlength(drives_table[index].bdrv);
+    dinfo = drive_get(IF_PFLASH, 0, 0);
+    if (dinfo) {
+        flash_size = bdrv_getlength(dinfo->bdrv);
         if (flash_size != 8*1024*1024 && flash_size != 16*1024*1024 &&
             flash_size != 32*1024*1024) {
             fprintf(stderr, "Invalid flash image size\n");
@@ -1564,7 +1564,7 @@ static void musicpal_init(ram_addr_t ram_size,
          * image is smaller than 32 MB.
          */
         pflash_cfi02_register(0-MP_FLASH_SIZE_MAX, qemu_ram_alloc(flash_size),
-                              drives_table[index].bdrv, 0x10000,
+                              dinfo->bdrv, 0x10000,
                               (flash_size + 0xffff) >> 16,
                               MP_FLASH_SIZE_MAX / flash_size,
                               2, 0x00BF, 0x236D, 0x0000, 0x0000,
diff --git a/hw/nand.c b/hw/nand.c
index 4ad77ec..37fd524 100644
--- a/hw/nand.c
+++ b/hw/nand.c
@@ -442,16 +442,16 @@ NANDFlashState *nand_init(int manf_id, int chip_id)
 {
     int pagesize;
     NANDFlashState *s;
-    int index;
+    DriveInfo *dinfo;
 
     if (nand_flash_ids[chip_id].size == 0) {
         hw_error("%s: Unsupported NAND chip ID.\n", __FUNCTION__);
     }
 
     s = (NANDFlashState *) qemu_mallocz(sizeof(NANDFlashState));
-    index = drive_get_index(IF_MTD, 0, 0);
-    if (index != -1)
-        s->bdrv = drives_table[index].bdrv;
+    dinfo = drive_get(IF_MTD, 0, 0);
+    if (dinfo)
+        s->bdrv = dinfo->bdrv;
     s->manf_id = manf_id;
     s->chip_id = chip_id;
     s->size = nand_flash_ids[s->chip_id].size << 20;
diff --git a/hw/omap1.c b/hw/omap1.c
index 14d7a82..93515ee 100644
--- a/hw/omap1.c
+++ b/hw/omap1.c
@@ -4628,7 +4628,7 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long 
sdram_size,
     ram_addr_t imif_base, emiff_base;
     qemu_irq *cpu_irq;
     qemu_irq dma_irqs[6];
-    int sdindex;
+    DriveInfo *dinfo;
 
     if (!core)
         core = "ti925t";
@@ -4740,12 +4740,12 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long 
sdram_size,
     omap_dpll_init(&s->dpll[1], 0xfffed000, omap_findclk(s, "dpll2"));
     omap_dpll_init(&s->dpll[2], 0xfffed100, omap_findclk(s, "dpll3"));
 
-    sdindex = drive_get_index(IF_SD, 0, 0);
-    if (sdindex == -1) {
+    dinfo = drive_get(IF_SD, 0, 0);
+    if (!dinfo) {
         fprintf(stderr, "qemu: missing SecureDigital device\n");
         exit(1);
     }
-    s->mmc = omap_mmc_init(0xfffb7800, drives_table[sdindex].bdrv,
+    s->mmc = omap_mmc_init(0xfffb7800, dinfo->bdrv,
                     s->irq[1][OMAP_INT_OQN], &s->drq[OMAP_DMA_MMC_TX],
                     omap_findclk(s, "mmc_ck"));
 
diff --git a/hw/omap2.c b/hw/omap2.c
index 8cbc4b5..e43b4a8 100644
--- a/hw/omap2.c
+++ b/hw/omap2.c
@@ -4496,7 +4496,7 @@ struct omap_mpu_state_s *omap2420_mpu_init(unsigned long 
sdram_size,
     qemu_irq *cpu_irq;
     qemu_irq dma_irqs[4];
     omap_clk gpio_clks[4];
-    int sdindex;
+    DriveInfo *dinfo;
     int i;
 
     /* Core */
@@ -4645,12 +4645,12 @@ struct omap_mpu_state_s *omap2420_mpu_init(unsigned 
long sdram_size,
     s->sdrc = omap_sdrc_init(0x68009000);
     s->gpmc = omap_gpmc_init(0x6800a000, s->irq[0][OMAP_INT_24XX_GPMC_IRQ]);
 
-    sdindex = drive_get_index(IF_SD, 0, 0);
-    if (sdindex == -1) {
+    dinfo = drive_get(IF_SD, 0, 0);
+    if (!dinfo) {
         fprintf(stderr, "qemu: missing SecureDigital device\n");
         exit(1);
     }
-    s->mmc = omap2_mmc_init(omap_l4tao(s->l4, 9), drives_table[sdindex].bdrv,
+    s->mmc = omap2_mmc_init(omap_l4tao(s->l4, 9), dinfo->bdrv,
                     s->irq[0][OMAP_INT_24XX_MMC_IRQ],
                     &s->drq[OMAP24XX_DMA_MMC1_TX],
                     omap_findclk(s, "mmc_fclk"), omap_findclk(s, "mmc_iclk"));
diff --git a/hw/omap_sx1.c b/hw/omap_sx1.c
index 1ba42f6..22f801b 100644
--- a/hw/omap_sx1.c
+++ b/hw/omap_sx1.c
@@ -127,7 +127,7 @@ static void sx1_init(ram_addr_t ram_size,
     static uint32_t cs2val = 0x00001139;
     static uint32_t cs3val = 0x00001139;
     ram_addr_t phys_flash;
-    int index;
+    DriveInfo *dinfo;
     int fl_idx;
     uint32_t flash_size = flash0_size;
 
@@ -151,9 +151,9 @@ static void sx1_init(ram_addr_t ram_size,
 
     fl_idx = 0;
 
-    if ((index = drive_get_index(IF_PFLASH, 0, fl_idx)) > -1) {
+    if ((dinfo = drive_get(IF_PFLASH, 0, fl_idx)) != NULL) {
         if (!pflash_cfi01_register(OMAP_CS0_BASE, qemu_ram_alloc(flash_size),
-            drives_table[index].bdrv, sector_size, flash_size / sector_size,
+            dinfo->bdrv, sector_size, flash_size / sector_size,
             4, 0, 0, 0, 0)) {
             fprintf(stderr, "qemu: Error registering flash memory %d.\n",
                            fl_idx);
@@ -162,7 +162,7 @@ static void sx1_init(ram_addr_t ram_size,
     }
 
     if ((version == 1) &&
-            (index = drive_get_index(IF_PFLASH, 0, fl_idx)) > -1) {
+            (dinfo = drive_get(IF_PFLASH, 0, fl_idx)) != NULL) {
         cpu_register_physical_memory(OMAP_CS1_BASE, flash1_size,
                         (phys_flash = qemu_ram_alloc(flash1_size)) |
                         IO_MEM_ROM);
@@ -171,7 +171,7 @@ static void sx1_init(ram_addr_t ram_size,
                         OMAP_CS1_SIZE - flash1_size, io);
 
         if (!pflash_cfi01_register(OMAP_CS1_BASE, qemu_ram_alloc(flash1_size),
-            drives_table[index].bdrv, sector_size, flash1_size / sector_size,
+            dinfo->bdrv, sector_size, flash1_size / sector_size,
             4, 0, 0, 0, 0)) {
             fprintf(stderr, "qemu: Error registering flash memory %d.\n",
                            fl_idx);
diff --git a/hw/onenand.c b/hw/onenand.c
index 870cfd9..84fdb21 100644
--- a/hw/onenand.c
+++ b/hw/onenand.c
@@ -618,7 +618,7 @@ static CPUWriteMemoryFunc *onenand_writefn[] = {
 void *onenand_init(uint32_t id, int regshift, qemu_irq irq)
 {
     OneNANDState *s = (OneNANDState *) qemu_mallocz(sizeof(*s));
-    int bdrv_index = drive_get_index(IF_MTD, 0, 0);
+    DriveInfo *dinfo = drive_get(IF_MTD, 0, 0);
     uint32_t size = 1 << (24 + ((id >> 12) & 7));
     void *ram;
 
@@ -632,11 +632,11 @@ void *onenand_init(uint32_t id, int regshift, qemu_irq 
irq)
     s->density_mask = (id & (1 << 11)) ? (1 << (6 + ((id >> 12) & 7))) : 0;
     s->iomemtype = cpu_register_io_memory(onenand_readfn,
                     onenand_writefn, s);
-    if (bdrv_index == -1)
+    if (!dinfo)
         s->image = memset(qemu_malloc(size + (size >> 5)),
                         0xff, size + (size >> 5));
     else
-        s->bdrv = drives_table[bdrv_index].bdrv;
+        s->bdrv = dinfo->bdrv;
     s->otp = memset(qemu_malloc((64 + 2) << PAGE_SHIFT),
                     0xff, (64 + 2) << PAGE_SHIFT);
     s->ram = qemu_ram_alloc(0xc000 << s->shift);
diff --git a/hw/pc.c b/hw/pc.c
index a50f23d..da0ef18 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -1126,7 +1126,7 @@ static void pc_init1(ram_addr_t ram_size,
     CPUState *env;
     qemu_irq *cpu_irq;
     qemu_irq *i8259;
-    int index;
+    DriveInfo *dinfo;
     BlockDriverState *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
     BlockDriverState *fd[MAX_FD];
     int using_vga = cirrus_vga_enabled || std_vga_enabled || vmsvga_enabled;
@@ -1356,11 +1356,8 @@ static void pc_init1(ram_addr_t ram_size,
     }
 
     for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) {
-        index = drive_get_index(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
-       if (index != -1)
-           hd[i] = drives_table[index].bdrv;
-       else
-           hd[i] = NULL;
+        dinfo = drive_get(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
+        hd[i] = dinfo ? dinfo->bdrv : NULL;
     }
 
     if (pci_enabled) {
@@ -1379,11 +1376,8 @@ static void pc_init1(ram_addr_t ram_size,
 #endif
 
     for(i = 0; i < MAX_FD; i++) {
-        index = drive_get_index(IF_FLOPPY, 0, i);
-       if (index != -1)
-           fd[i] = drives_table[index].bdrv;
-       else
-           fd[i] = NULL;
+        dinfo = drive_get(IF_FLOPPY, 0, i);
+        fd[i] = dinfo ? dinfo->bdrv : NULL;
     }
     floppy_controller = fdctrl_init(i8259[6], 2, 0, 0x3f0, fd);
 
@@ -1437,12 +1431,11 @@ static void pc_init1(ram_addr_t ram_size,
 
     /* Add virtio block devices */
     if (pci_enabled) {
-        int index;
         int unit_id = 0;
 
-        while ((index = drive_get_index(IF_VIRTIO, 0, unit_id)) != -1) {
+        while ((dinfo = drive_get(IF_VIRTIO, 0, unit_id)) != NULL) {
             pci_dev = pci_create(virtio_blk_name,
-                                 drives_table[index].devaddr);
+                                 dinfo->devaddr);
             qdev_init(&pci_dev->qdev);
             unit_id++;
         }
diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
index d0f2911..43675e2 100644
--- a/hw/pci-hotplug.c
+++ b/hw/pci-hotplug.c
@@ -52,9 +52,10 @@ void drive_hot_add(Monitor *mon, const char *pci_addr, const 
char *opts)
 {
     int dom, pci_bus;
     unsigned slot;
-    int drive_idx, type, bus;
+    int type, bus;
     int success = 0;
     PCIDevice *dev;
+    DriveInfo *dinfo;
 
     if (pci_read_devaddr(mon, pci_addr, &dom, &pci_bus, &slot)) {
         return;
@@ -66,21 +67,21 @@ void drive_hot_add(Monitor *mon, const char *pci_addr, 
const char *opts)
         return;
     }
 
-    drive_idx = add_init_drive(opts);
-    if (drive_idx < 0)
+    dinfo = add_init_drive(opts);
+    if (!dinfo)
         return;
-    if (drives_table[drive_idx].devaddr) {
+    if (dinfo->devaddr) {
         monitor_printf(mon, "Parameter addr not supported\n");
         return;
     }
-    type = drives_table[drive_idx].type;
+    type = dinfo->type;
     bus = drive_get_max_bus (type);
 
     switch (type) {
     case IF_SCSI:
         success = 1;
-        lsi_scsi_attach(&dev->qdev, drives_table[drive_idx].bdrv,
-                        drives_table[drive_idx].unit);
+        lsi_scsi_attach(&dev->qdev, dinfo->bdrv,
+                        dinfo->unit);
         break;
     default:
         monitor_printf(mon, "Can't hot-add drive to type %d\n", type);
@@ -88,8 +89,8 @@ void drive_hot_add(Monitor *mon, const char *pci_addr, const 
char *opts)
 
     if (success)
         monitor_printf(mon, "OK bus %d, unit %d\n",
-                       drives_table[drive_idx].bus,
-                       drives_table[drive_idx].unit);
+                       dinfo->bus,
+                       dinfo->unit);
     return;
 }
 
@@ -98,7 +99,8 @@ static PCIDevice *qemu_pci_hot_add_storage(Monitor *mon,
                                            const char *opts)
 {
     PCIDevice *dev;
-    int type = -1, drive_idx = -1;
+    DriveInfo *dinfo;
+    int type = -1;
     char buf[128];
 
     if (get_param_value(buf, sizeof(buf), "if", opts)) {
@@ -116,10 +118,10 @@ static PCIDevice *qemu_pci_hot_add_storage(Monitor *mon,
     }
 
     if (get_param_value(buf, sizeof(buf), "file", opts)) {
-        drive_idx = add_init_drive(opts);
-        if (drive_idx < 0)
+        dinfo = add_init_drive(opts);
+        if (!dinfo)
             return NULL;
-        if (drives_table[drive_idx].devaddr) {
+        if (dinfo->devaddr) {
             monitor_printf(mon, "Parameter addr not supported\n");
             return NULL;
         }
diff --git a/hw/petalogix_s3adsp1800_mmu.c b/hw/petalogix_s3adsp1800_mmu.c
index c2a196f..1a1cc0e 100644
--- a/hw/petalogix_s3adsp1800_mmu.c
+++ b/hw/petalogix_s3adsp1800_mmu.c
@@ -106,6 +106,7 @@ petalogix_s3adsp1800_init(ram_addr_t ram_size,
     DeviceState *dev;
     CPUState *env;
     int kernel_size;
+    DriveInfo *dinfo;
     int i;
     target_phys_addr_t ddr_base = 0x90000000;
     ram_addr_t phys_lmb_bram;
@@ -131,9 +132,9 @@ petalogix_s3adsp1800_init(ram_addr_t ram_size,
     cpu_register_physical_memory(ddr_base, ram_size, phys_ram | IO_MEM_RAM);
 
     phys_flash = qemu_ram_alloc(FLASH_SIZE);
-    i = drive_get_index(IF_PFLASH, 0, 0);
+    dinfo = drive_get(IF_PFLASH, 0, 0);
     pflash_cfi02_register(0xa0000000, phys_flash,
-                          i != -1 ? drives_table[i].bdrv : NULL, (64 * 1024),
+                          dinfo ? dinfo->bdrv : NULL, (64 * 1024),
                           FLASH_SIZE >> 16,
                           1, 1, 0x0000, 0x0000, 0x0000, 0x0000,
                           0x555, 0x2aa);
diff --git a/hw/ppc405_boards.c b/hw/ppc405_boards.c
index c9a1986..f2b4a84 100644
--- a/hw/ppc405_boards.c
+++ b/hw/ppc405_boards.c
@@ -188,7 +188,7 @@ static void ref405ep_init (ram_addr_t ram_size,
     int linux_boot;
     int fl_idx, fl_sectors, len;
     int ppc_boot_device = boot_device[0];
-    int index;
+    DriveInfo *dinfo;
 
     /* XXX: fix this */
     ram_bases[0] = qemu_ram_alloc(0x08000000);
@@ -215,19 +215,19 @@ static void ref405ep_init (ram_addr_t ram_size,
 #endif
     fl_idx = 0;
 #ifdef USE_FLASH_BIOS
-    index = drive_get_index(IF_PFLASH, 0, fl_idx);
-    if (index != -1) {
-        bios_size = bdrv_getlength(drives_table[index].bdrv);
+    dinfo = drive_get(IF_PFLASH, 0, fl_idx);
+    if (dinfo) {
+        bios_size = bdrv_getlength(dinfo->bdrv);
         bios_offset = qemu_ram_alloc(bios_size);
         fl_sectors = (bios_size + 65535) >> 16;
 #ifdef DEBUG_BOARD_INIT
         printf("Register parallel flash %d size " ADDRX " at offset %08lx "
                " addr " ADDRX " '%s' %d\n",
                fl_idx, bios_size, bios_offset, -bios_size,
-               bdrv_get_device_name(drives_table[index].bdrv), fl_sectors);
+               bdrv_get_device_name(dinfo->bdrv), fl_sectors);
 #endif
         pflash_cfi02_register((uint32_t)(-bios_size), bios_offset,
-                              drives_table[index].bdrv, 65536, fl_sectors, 1,
+                              dinfo->bdrv, 65536, fl_sectors, 1,
                               2, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA);
         fl_idx++;
     } else
@@ -509,7 +509,7 @@ static void taihu_405ep_init(ram_addr_t ram_size,
     int linux_boot;
     int fl_idx, fl_sectors;
     int ppc_boot_device = boot_device[0];
-    int index;
+    DriveInfo *dinfo;
 
     /* RAM is soldered to the board so the size cannot be changed */
     ram_bases[0] = qemu_ram_alloc(0x04000000);
@@ -528,9 +528,9 @@ static void taihu_405ep_init(ram_addr_t ram_size,
 #endif
     fl_idx = 0;
 #if defined(USE_FLASH_BIOS)
-    index = drive_get_index(IF_PFLASH, 0, fl_idx);
-    if (index != -1) {
-        bios_size = bdrv_getlength(drives_table[index].bdrv);
+    dinfo = drive_get(IF_PFLASH, 0, fl_idx);
+    if (dinfo) {
+        bios_size = bdrv_getlength(dinfo->bdrv);
         /* XXX: should check that size is 2MB */
         //        bios_size = 2 * 1024 * 1024;
         fl_sectors = (bios_size + 65535) >> 16;
@@ -539,10 +539,10 @@ static void taihu_405ep_init(ram_addr_t ram_size,
         printf("Register parallel flash %d size " ADDRX " at offset %08lx "
                " addr " ADDRX " '%s' %d\n",
                fl_idx, bios_size, bios_offset, -bios_size,
-               bdrv_get_device_name(drives_table[index].bdrv), fl_sectors);
+               bdrv_get_device_name(dinfo->bdrv), fl_sectors);
 #endif
         pflash_cfi02_register((uint32_t)(-bios_size), bios_offset,
-                              drives_table[index].bdrv, 65536, fl_sectors, 1,
+                              dinfo->bdrv, 65536, fl_sectors, 1,
                               4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA);
         fl_idx++;
     } else
@@ -570,9 +570,9 @@ static void taihu_405ep_init(ram_addr_t ram_size,
                                      bios_size, bios_offset | IO_MEM_ROM);
     }
     /* Register Linux flash */
-    index = drive_get_index(IF_PFLASH, 0, fl_idx);
-    if (index != -1) {
-        bios_size = bdrv_getlength(drives_table[index].bdrv);
+    dinfo = drive_get(IF_PFLASH, 0, fl_idx);
+    if (dinfo) {
+        bios_size = bdrv_getlength(dinfo->bdrv);
         /* XXX: should check that size is 32MB */
         bios_size = 32 * 1024 * 1024;
         fl_sectors = (bios_size + 65535) >> 16;
@@ -580,11 +580,11 @@ static void taihu_405ep_init(ram_addr_t ram_size,
         printf("Register parallel flash %d size " ADDRX " at offset %08lx "
                " addr " ADDRX " '%s'\n",
                fl_idx, bios_size, bios_offset, (target_ulong)0xfc000000,
-               bdrv_get_device_name(drives_table[index].bdrv));
+               bdrv_get_device_name(dinfo->bdrv));
 #endif
         bios_offset = qemu_ram_alloc(bios_size);
         pflash_cfi02_register(0xfc000000, bios_offset,
-                              drives_table[index].bdrv, 65536, fl_sectors, 1,
+                              dinfo->bdrv, 65536, fl_sectors, 1,
                               4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA);
         fl_idx++;
     }
diff --git a/hw/ppc440_bamboo.c b/hw/ppc440_bamboo.c
index d9ef3ec..624e15b 100644
--- a/hw/ppc440_bamboo.c
+++ b/hw/ppc440_bamboo.c
@@ -102,6 +102,7 @@ static void bamboo_init(ram_addr_t ram_size,
     target_ulong dt_base = 0;
     void *fdt;
     int i;
+    DriveInfo *dinfo;
 
     /* Setup CPU. */
     env = ppc440ep_init(&ram_size, &pcibus, pci_irq_nrs, 1, cpu_model);
@@ -110,8 +111,8 @@ static void bamboo_init(ram_addr_t ram_size,
         int unit_id = 0;
 
         /* Add virtio block devices. */
-        while ((i = drive_get_index(IF_VIRTIO, 0, unit_id)) != -1) {
-            pci_dev = pci_create("virtio-blk-pci", drives_table[i].devaddr);
+        while ((dinfo = drive_get(IF_VIRTIO, 0, unit_id)) != NULL) {
+            pci_dev = pci_create("virtio-blk-pci", dinfo->devaddr);
             qdev_init(&pci_dev->qdev);
             unit_id++;
         }
diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c
index 4e5043c..caab74e 100644
--- a/hw/ppc_newworld.c
+++ b/hw/ppc_newworld.c
@@ -106,7 +106,7 @@ static void ppc_core99_init (ram_addr_t ram_size,
     qemu_irq *dummy_irq;
     int pic_mem_index, dbdma_mem_index, cuda_mem_index, escc_mem_index;
     int ppc_boot_device;
-    int index;
+    DriveInfo *dinfo;
     BlockDriverState *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
     void *fw_cfg;
     void *dbdma;
@@ -311,11 +311,8 @@ static void ppc_core99_init (ram_addr_t ram_size,
         exit(1);
     }
     for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) {
-        index = drive_get_index(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
-        if (index != -1)
-            hd[i] = drives_table[index].bdrv;
-        else
-            hd[i] = NULL;
+        dinfo = drive_get(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
+        hd[i] = dinfo ? dinfo->bdrv : NULL;
     }
     dbdma = DBDMA_init(&dbdma_mem_index);
     pci_cmd646_ide_init(pci_bus, hd, 0);
diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c
index b26e407..388db31 100644
--- a/hw/ppc_oldworld.c
+++ b/hw/ppc_oldworld.c
@@ -135,7 +135,7 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
     int escc_mem_index, ide_mem_index[2];
     uint16_t ppc_boot_device;
     BlockDriverState *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
-    int index;
+    DriveInfo *dinfo;
     void *fw_cfg;
     void *dbdma;
     uint8_t *vga_bios_ptr;
@@ -324,31 +324,19 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
     }
 
     /* First IDE channel is a MAC IDE on the MacIO bus */
-    index = drive_get_index(IF_IDE, 0, 0);
-    if (index == -1)
-        hd[0] = NULL;
-    else
-        hd[0] =  drives_table[index].bdrv;
-    index = drive_get_index(IF_IDE, 0, 1);
-    if (index == -1)
-        hd[1] = NULL;
-    else
-        hd[1] =  drives_table[index].bdrv;
+    dinfo = drive_get(IF_IDE, 0, 0);
+    hd[0] = dinfo ? dinfo->bdrv : NULL;
+    dinfo = drive_get(IF_IDE, 0, 1);
+    hd[1] = dinfo ? dinfo->bdrv : NULL;
     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 */
-    index = drive_get_index(IF_IDE, 1, 0);
-    if (index == -1)
-        hd[0] = NULL;
-    else
-        hd[0] =  drives_table[index].bdrv;
-    index = drive_get_index(IF_IDE, 1, 1);
-    if (index == -1)
-        hd[1] = NULL;
-    else
-        hd[1] =  drives_table[index].bdrv;
+    dinfo = drive_get(IF_IDE, 1, 0);
+    hd[0] = dinfo ? dinfo->bdrv : NULL;
+    dinfo = drive_get(IF_IDE, 1, 1);
+    hd[1] = dinfo ? dinfo->bdrv : NULL;
     hd[3] = hd[2] = NULL;
     pci_cmd646_ide_init(pci_bus, hd, 0);
 
diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
index 7a21977..97190a2 100644
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@ -550,7 +550,7 @@ static void ppc_prep_init (ram_addr_t ram_size,
     PCIBus *pci_bus;
     qemu_irq *i8259;
     int ppc_boot_device;
-    int index;
+    DriveInfo *dinfo;
     BlockDriverState *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
     BlockDriverState *fd[MAX_FD];
 
@@ -691,11 +691,8 @@ static void ppc_prep_init (ram_addr_t ram_size,
     }
 
     for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) {
-        index = drive_get_index(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
-        if (index != -1)
-            hd[i] = drives_table[index].bdrv;
-        else
-            hd[i] = NULL;
+        dinfo = drive_get(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
+        hd[i] = dinfo ? dinfo->bdrv : NULL;
     }
 
     for(i = 0; i < MAX_IDE_BUS; i++) {
@@ -708,11 +705,8 @@ static void ppc_prep_init (ram_addr_t ram_size,
     //    SB16_init();
 
     for(i = 0; i < MAX_FD; i++) {
-        index = drive_get_index(IF_FLOPPY, 0, i);
-        if (index != -1)
-            fd[i] = drives_table[index].bdrv;
-        else
-            fd[i] = NULL;
+        dinfo = drive_get(IF_FLOPPY, 0, i);
+        fd[i] = dinfo ? dinfo->bdrv : NULL;
     }
     fdctrl_init(i8259[6], 2, 0, 0x3f0, fd);
 
diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c
index c0e367d..04c6acd 100644
--- a/hw/ppce500_mpc8544ds.c
+++ b/hw/ppce500_mpc8544ds.c
@@ -172,6 +172,7 @@ static void mpc8544ds_init(ram_addr_t ram_size,
     unsigned int pci_irq_nrs[4] = {1, 2, 3, 4};
     qemu_irq *irqs, *mpic, *pci_irqs;
     SerialState * serial[2];
+    DriveInfo *dinfo;
 
     /* Setup CPU */
     env = cpu_ppc_init("e500v2_v30");
@@ -219,8 +220,8 @@ static void mpc8544ds_init(ram_addr_t ram_size,
         int unit_id = 0;
 
         /* Add virtio block devices. */
-        while ((i = drive_get_index(IF_VIRTIO, 0, unit_id)) != -1) {
-            pci_dev = pci_create("virtio-blk-pci", drives_table[i].devaddr);
+        while ((dinfo = drive_get(IF_VIRTIO, 0, unit_id)) != NULL) {
+            pci_dev = pci_create("virtio-blk-pci", dinfo->devaddr);
             qdev_init(&pci_dev->qdev);
             unit_id++;
         }
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index f2e98ff..28e9610 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -2034,7 +2034,7 @@ PXA2xxState *pxa270_init(unsigned int sdram_size, const 
char *revision)
 {
     PXA2xxState *s;
     int iomemtype, i;
-    int index;
+    DriveInfo *dinfo;
     s = (PXA2xxState *) qemu_mallocz(sizeof(PXA2xxState));
 
     if (revision && strncmp(revision, "pxa27", 5)) {
@@ -2066,12 +2066,12 @@ PXA2xxState *pxa270_init(unsigned int sdram_size, const 
char *revision)
 
     s->gpio = pxa2xx_gpio_init(0x40e00000, s->env, s->pic, 121);
 
-    index = drive_get_index(IF_SD, 0, 0);
-    if (index == -1) {
+    dinfo = drive_get(IF_SD, 0, 0);
+    if (!dinfo) {
         fprintf(stderr, "qemu: missing SecureDigital device\n");
         exit(1);
     }
-    s->mmc = pxa2xx_mmci_init(0x41100000, drives_table[index].bdrv,
+    s->mmc = pxa2xx_mmci_init(0x41100000, dinfo->bdrv,
                               s->pic[PXA2XX_PIC_MMC], s->dma);
 
     for (i = 0; pxa270_serial[i].io_base; i ++)
@@ -2153,7 +2153,7 @@ PXA2xxState *pxa255_init(unsigned int sdram_size)
 {
     PXA2xxState *s;
     int iomemtype, i;
-    int index;
+    DriveInfo *dinfo;
 
     s = (PXA2xxState *) qemu_mallocz(sizeof(PXA2xxState));
 
@@ -2178,12 +2178,12 @@ PXA2xxState *pxa255_init(unsigned int sdram_size)
 
     s->gpio = pxa2xx_gpio_init(0x40e00000, s->env, s->pic, 85);
 
-    index = drive_get_index(IF_SD, 0, 0);
-    if (index == -1) {
+    dinfo = drive_get(IF_SD, 0, 0);
+    if (!dinfo) {
         fprintf(stderr, "qemu: missing SecureDigital device\n");
         exit(1);
     }
-    s->mmc = pxa2xx_mmci_init(0x41100000, drives_table[index].bdrv,
+    s->mmc = pxa2xx_mmci_init(0x41100000, dinfo->bdrv,
                               s->pic[PXA2XX_PIC_MMC], s->dma);
 
     for (i = 0; pxa255_serial[i].io_base; i ++)
diff --git a/hw/qdev.c b/hw/qdev.c
index faecc76..c3ddd66 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -189,13 +189,10 @@ static int next_block_unit[IF_COUNT];
 BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type)
 {
     int unit = next_block_unit[type]++;
-    int index;
+    DriveInfo *dinfo;
 
-    index = drive_get_index(type, 0, unit);
-    if (index == -1) {
-        return NULL;
-    }
-    return drives_table[index].bdrv;
+    dinfo = drive_get(type, 0, unit);
+    return dinfo ? dinfo->bdrv : NULL;
 }
 
 BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
@@ -218,14 +215,14 @@ void scsi_bus_new(DeviceState *host, SCSIAttachFn attach)
 {
    int bus = next_scsi_bus++;
    int unit;
-   int index;
+   DriveInfo *dinfo;
 
    for (unit = 0; unit < MAX_SCSI_DEVS; unit++) {
-       index = drive_get_index(IF_SCSI, bus, unit);
-       if (index == -1) {
+       dinfo = drive_get(IF_SCSI, bus, unit);
+       if (!dinfo) {
            continue;
        }
-       attach(host, drives_table[index].bdrv, unit);
+       attach(host, dinfo->bdrv, unit);
    }
 }
 
diff --git a/hw/r2d.c b/hw/r2d.c
index 8ce6832..697bcb6 100644
--- a/hw/r2d.c
+++ b/hw/r2d.c
@@ -203,6 +203,7 @@ static void r2d_init(ram_addr_t ram_size,
     ram_addr_t sdram_addr;
     qemu_irq *irq;
     PCIBus *pci;
+    DriveInfo *dinfo;
     int i;
 
     if (!cpu_model)
@@ -225,9 +226,9 @@ static void r2d_init(ram_addr_t ram_size,
     sm501_init(0x10000000, SM501_VRAM_SIZE, irq[SM501], serial_hds[2]);
 
     /* onboard CF (True IDE mode, Master only). */
-    if ((i = drive_get_index(IF_IDE, 0, 0)) != -1)
+    if ((dinfo = drive_get(IF_IDE, 0, 0)) != NULL)
        mmio_ide_init(0x14001000, 0x1400080c, irq[CF_IDE], 1,
-                     drives_table[i].bdrv, NULL);
+                     dinfo->bdrv, NULL);
 
     /* NIC: rtl8139 on-board, and 2 slots. */
     for (i = 0; i < nb_nics; i++)
diff --git a/hw/spitz.c b/hw/spitz.c
index d9ff85e..36bf534 100644
--- a/hw/spitz.c
+++ b/hw/spitz.c
@@ -744,13 +744,13 @@ static void spitz_ssp_attach(PXA2xxState *cpu)
 static void spitz_microdrive_attach(PXA2xxState *cpu, int slot)
 {
     PCMCIACardState *md;
-    int index;
     BlockDriverState *bs;
+    DriveInfo *dinfo;
 
-    index = drive_get_index(IF_IDE, 0, 0);
-    if (index == -1)
+    dinfo = drive_get(IF_IDE, 0, 0);
+    if (!dinfo)
         return;
-    bs = drives_table[index].bdrv;
+    bs = dinfo->bdrv;
     if (bdrv_is_inserted(bs) && !bdrv_is_removable(bs)) {
         md = dscm1xxxx_init(bs);
         pxa2xx_pcmcia_attach(cpu->pcmcia[slot], md);
diff --git a/hw/sun4m.c b/hw/sun4m.c
index c810b35..6d42caf 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -580,9 +580,9 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, 
ram_addr_t RAM_size,
     qemu_irq *cpu_halt;
     unsigned long kernel_size;
     BlockDriverState *fd[MAX_FD];
-    int drive_index;
     void *fw_cfg;
     DeviceState *dev;
+    DriveInfo *dinfo;
 
     /* init CPUs */
     if (!cpu_model)
@@ -661,9 +661,9 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, 
ram_addr_t RAM_size,
     if (hwdef->fd_base) {
         /* there is zero or one floppy drive */
         memset(fd, 0, sizeof(fd));
-        drive_index = drive_get_index(IF_FLOPPY, 0, 0);
-        if (drive_index != -1)
-            fd[0] = drives_table[drive_index].bdrv;
+        dinfo = drive_get(IF_FLOPPY, 0, 0);
+        if (dinfo)
+            fd[0] = dinfo->bdrv;
 
         sun4m_fdctrl_init(slavio_irq[hwdef->fd_irq], hwdef->fd_base, fd,
                           &fdc_tc);
@@ -1498,8 +1498,8 @@ static void sun4c_hw_init(const struct sun4c_hwdef 
*hwdef, ram_addr_t RAM_size,
     qemu_irq fdc_tc;
     unsigned long kernel_size;
     BlockDriverState *fd[MAX_FD];
-    int drive_index;
     void *fw_cfg;
+    DriveInfo *dinfo;
 
     /* init CPU */
     if (!cpu_model)
@@ -1551,9 +1551,9 @@ static void sun4c_hw_init(const struct sun4c_hwdef 
*hwdef, ram_addr_t RAM_size,
     if (hwdef->fd_base != (target_phys_addr_t)-1) {
         /* there is zero or one floppy drive */
         memset(fd, 0, sizeof(fd));
-        drive_index = drive_get_index(IF_FLOPPY, 0, 0);
-        if (drive_index != -1)
-            fd[0] = drives_table[drive_index].bdrv;
+        dinfo = drive_get(IF_FLOPPY, 0, 0);
+        if (dinfo)
+            fd[0] = dinfo->bdrv;
 
         sun4m_fdctrl_init(slavio_irq[hwdef->fd_irq], hwdef->fd_base, fd,
                           &fdc_tc);
diff --git a/hw/sun4u.c b/hw/sun4u.c
index 9d2a7f5..1fba1a4 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -358,11 +358,11 @@ static void sun4uv_init(ram_addr_t RAM_size,
     PCIBus *pci_bus, *pci_bus2, *pci_bus3;
     QEMUBH *bh;
     qemu_irq *irq;
-    int drive_index;
     BlockDriverState *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
     BlockDriverState *fd[MAX_FD];
     void *fw_cfg;
     ResetData *reset_info;
+    DriveInfo *dinfo;
 
     linux_boot = (kernel_filename != NULL);
 
@@ -504,12 +504,9 @@ static void sun4uv_init(ram_addr_t RAM_size,
         exit(1);
     }
     for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) {
-        drive_index = drive_get_index(IF_IDE, i / MAX_IDE_DEVS,
-                                      i % MAX_IDE_DEVS);
-       if (drive_index != -1)
-           hd[i] = drives_table[drive_index].bdrv;
-       else
-           hd[i] = NULL;
+        dinfo = drive_get(IF_IDE, i / MAX_IDE_DEVS,
+                          i % MAX_IDE_DEVS);
+        hd[i] = dinfo ? dinfo->bdrv : NULL;
     }
 
     pci_cmd646_ide_init(pci_bus, hd, 1);
@@ -517,11 +514,8 @@ static void sun4uv_init(ram_addr_t RAM_size,
     /* FIXME: wire up interrupts.  */
     i8042_init(NULL/*1*/, NULL/*12*/, 0x60);
     for(i = 0; i < MAX_FD; i++) {
-        drive_index = drive_get_index(IF_FLOPPY, 0, i);
-       if (drive_index != -1)
-           fd[i] = drives_table[drive_index].bdrv;
-       else
-           fd[i] = NULL;
+        dinfo = drive_get(IF_FLOPPY, 0, i);
+        fd[i] = dinfo ? dinfo->bdrv : NULL;
     }
     floppy_controller = fdctrl_init(NULL/*6*/, 2, 0, 0x3f0, fd);
     nvram = m48t59_init(NULL/*8*/, 0, 0x0074, NVRAM_SIZE, 59);
diff --git a/hw/tosa.c b/hw/tosa.c
index b2d66f3..b932efc 100644
--- a/hw/tosa.c
+++ b/hw/tosa.c
@@ -49,13 +49,13 @@
 static void tosa_microdrive_attach(PXA2xxState *cpu)
 {
     PCMCIACardState *md;
-    int index;
     BlockDriverState *bs;
+    DriveInfo *dinfo;
 
-    index = drive_get_index(IF_IDE, 0, 0);
-    if (index == -1)
+    dinfo = drive_get(IF_IDE, 0, 0);
+    if (!dinfo)
         return;
-    bs = drives_table[index].bdrv;
+    bs = dinfo->bdrv;
     if (bdrv_is_inserted(bs) && !bdrv_is_removable(bs)) {
         md = dscm1xxxx_init(bs);
         pxa2xx_pcmcia_attach(cpu->pcmcia[0], md);
diff --git a/hw/xen_disk.c b/hw/xen_disk.c
index 7ed6c33..100ef8e 100644
--- a/hw/xen_disk.c
+++ b/hw/xen_disk.c
@@ -107,7 +107,7 @@ struct XenBlkDev {
     int                 requests_finished;
 
     /* qemu block driver */
-    int                 index;
+    DriveInfo           *dinfo;
     BlockDriverState    *bs;
     QEMUBH              *bh;
 };
@@ -575,7 +575,7 @@ static void blk_alloc(struct XenDevice *xendev)
 static int blk_init(struct XenDevice *xendev)
 {
     struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev);
-    int mode, qflags, have_barriers, info = 0;
+    int index, mode, qflags, have_barriers, info = 0;
     char *h;
 
     /* read xenstore entries */
@@ -622,9 +622,9 @@ static int blk_init(struct XenDevice *xendev)
        info  |= VDISK_CDROM;
 
     /* init qemu block driver */
-    blkdev->index = (blkdev->xendev.dev - 202 * 256) / 16;
-    blkdev->index = drive_get_index(IF_XEN, 0, blkdev->index);
-    if (blkdev->index == -1) {
+    index = (blkdev->xendev.dev - 202 * 256) / 16;
+    blkdev->dinfo = drive_get(IF_XEN, 0, index);
+    if (!blkdev->dinfo) {
         /* setup via xenbus -> create new block driver instance */
         xen_be_printf(&blkdev->xendev, 2, "create new bdrv (xenbus setup)\n");
        blkdev->bs = bdrv_new(blkdev->dev);
@@ -640,7 +640,7 @@ static int blk_init(struct XenDevice *xendev)
     } else {
         /* setup via qemu cmdline -> already setup for us */
         xen_be_printf(&blkdev->xendev, 2, "get configured bdrv (cmdline 
setup)\n");
-       blkdev->bs = drives_table[blkdev->index].bdrv;
+       blkdev->bs = blkdev->dinfo->bdrv;
     }
     blkdev->file_blk  = BLOCK_SIZE;
     blkdev->file_size = bdrv_getlength(blkdev->bs);
@@ -729,7 +729,7 @@ static void blk_disconnect(struct XenDevice *xendev)
     struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev);
 
     if (blkdev->bs) {
-        if (blkdev->index == -1) {
+        if (!blkdev->dinfo) {
             /* close/delete only if we created it ourself */
             bdrv_close(blkdev->bs);
             bdrv_delete(blkdev->bs);
diff --git a/hw/xen_machine_pv.c b/hw/xen_machine_pv.c
index 6ae5000..162f88d 100644
--- a/hw/xen_machine_pv.c
+++ b/hw/xen_machine_pv.c
@@ -40,7 +40,8 @@ static void xen_init_pv(ram_addr_t ram_size,
                        const char *cpu_model)
 {
     CPUState *env;
-    int i, index;
+    DriveInfo *dinfo;
+    int i;
 
     /* Initialize a dummy CPU */
     if (cpu_model == NULL) {
@@ -90,10 +91,10 @@ static void xen_init_pv(ram_addr_t ram_size,
 
     /* configure disks */
     for (i = 0; i < 16; i++) {
-        index = drive_get_index(IF_XEN, 0, i);
-        if (index == -1)
+        dinfo = drive_get(IF_XEN, 0, i);
+        if (!dinfo)
             continue;
-        xen_config_dev_blk(drives_table + index);
+        xen_config_dev_blk(dinfo);
     }
 
     /* configure nics */
diff --git a/monitor.c b/monitor.c
index e38c86e..9a426be 100644
--- a/monitor.c
+++ b/monitor.c
@@ -244,13 +244,15 @@ static void help_cmd(Monitor *mon, const char *name)
 
 static void do_commit(Monitor *mon, const char *device)
 {
-    int i, all_devices;
+    int all_devices;
+    DriveInfo *dinfo;
 
     all_devices = !strcmp(device, "all");
-    for (i = 0; i < nb_drives; i++) {
-            if (all_devices ||
-                !strcmp(bdrv_get_device_name(drives_table[i].bdrv), device))
-                bdrv_commit(drives_table[i].bdrv);
+    TAILQ_FOREACH(dinfo, &drives, next) {
+        if (!all_devices)
+            if (!strcmp(bdrv_get_device_name(dinfo->bdrv), device))
+                continue;
+        bdrv_commit(dinfo->bdrv);
     }
 }
 
diff --git a/qemu-char.c b/qemu-char.c
index 287e0cd..4a1c082 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -345,9 +345,9 @@ static int mux_proc_byte(CharDriverState *chr, MuxDriver 
*d, int ch)
             }
         case 's':
             {
-                int i;
-                for (i = 0; i < nb_drives; i++) {
-                        bdrv_commit(drives_table[i].bdrv);
+                DriveInfo *dinfo;
+                TAILQ_FOREACH(dinfo, &drives, next) {
+                    bdrv_commit(dinfo->bdrv);
                 }
             }
             break;
diff --git a/savevm.c b/savevm.c
index 181c088..0c0b49f 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1011,12 +1011,12 @@ static int bdrv_has_snapshot(BlockDriverState *bs)
 static BlockDriverState *get_bs_snapshots(void)
 {
     BlockDriverState *bs;
-    int i;
+    DriveInfo *dinfo;
 
     if (bs_snapshots)
         return bs_snapshots;
-    for(i = 0; i <= nb_drives; i++) {
-        bs = drives_table[i].bdrv;
+    TAILQ_FOREACH(dinfo, &drives, next) {
+        bs = dinfo->bdrv;
         if (bdrv_can_snapshot(bs))
             goto ok;
     }
@@ -1050,9 +1050,10 @@ static int bdrv_snapshot_find(BlockDriverState *bs, 
QEMUSnapshotInfo *sn_info,
 
 void do_savevm(Monitor *mon, const char *name)
 {
+    DriveInfo *dinfo;
     BlockDriverState *bs, *bs1;
     QEMUSnapshotInfo sn1, *sn = &sn1, old_sn1, *old_sn = &old_sn1;
-    int must_delete, ret, i;
+    int must_delete, ret;
     QEMUFile *f;
     int saved_vm_running;
     uint32_t vm_state_size;
@@ -1118,8 +1119,8 @@ void do_savevm(Monitor *mon, const char *name)
 
     /* create the snapshots */
 
-    for(i = 0; i < nb_drives; i++) {
-        bs1 = drives_table[i].bdrv;
+    TAILQ_FOREACH(dinfo, &drives, next) {
+        bs1 = dinfo->bdrv;
         if (bdrv_has_snapshot(bs1)) {
             if (must_delete) {
                 ret = bdrv_snapshot_delete(bs1, old_sn->id_str);
@@ -1146,10 +1147,11 @@ void do_savevm(Monitor *mon, const char *name)
 
 void do_loadvm(Monitor *mon, const char *name)
 {
+    DriveInfo *dinfo;
     BlockDriverState *bs, *bs1;
     QEMUSnapshotInfo sn;
     QEMUFile *f;
-    int i, ret;
+    int ret;
     int saved_vm_running;
 
     bs = get_bs_snapshots();
@@ -1164,8 +1166,8 @@ void do_loadvm(Monitor *mon, const char *name)
     saved_vm_running = vm_running;
     vm_stop(0);
 
-    for(i = 0; i <= nb_drives; i++) {
-        bs1 = drives_table[i].bdrv;
+    TAILQ_FOREACH(dinfo, &drives, next) {
+        bs1 = dinfo->bdrv;
         if (bdrv_has_snapshot(bs1)) {
             ret = bdrv_snapshot_goto(bs1, name);
             if (ret < 0) {
@@ -1217,8 +1219,9 @@ void do_loadvm(Monitor *mon, const char *name)
 
 void do_delvm(Monitor *mon, const char *name)
 {
+    DriveInfo *dinfo;
     BlockDriverState *bs, *bs1;
-    int i, ret;
+    int ret;
 
     bs = get_bs_snapshots();
     if (!bs) {
@@ -1226,8 +1229,8 @@ void do_delvm(Monitor *mon, const char *name)
         return;
     }
 
-    for(i = 0; i <= nb_drives; i++) {
-        bs1 = drives_table[i].bdrv;
+    TAILQ_FOREACH(dinfo, &drives, next) {
+        bs1 = dinfo->bdrv;
         if (bdrv_has_snapshot(bs1)) {
             ret = bdrv_snapshot_delete(bs1, name);
             if (ret < 0) {
@@ -1245,6 +1248,7 @@ void do_delvm(Monitor *mon, const char *name)
 
 void do_info_snapshots(Monitor *mon)
 {
+    DriveInfo *dinfo;
     BlockDriverState *bs, *bs1;
     QEMUSnapshotInfo *sn_tab, *sn;
     int nb_sns, i;
@@ -1256,8 +1260,8 @@ void do_info_snapshots(Monitor *mon)
         return;
     }
     monitor_printf(mon, "Snapshot devices:");
-    for(i = 0; i <= nb_drives; i++) {
-        bs1 = drives_table[i].bdrv;
+    TAILQ_FOREACH(dinfo, &drives, next) {
+        bs1 = dinfo->bdrv;
         if (bdrv_has_snapshot(bs1)) {
             if (bs == bs1)
                 monitor_printf(mon, " %s", bdrv_get_device_name(bs1));
diff --git a/sysemu.h b/sysemu.h
index df19f02..e2a8cf5 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -3,6 +3,7 @@
 /* Misc. things related to the system emulator.  */
 
 #include "qemu-common.h"
+#include "sys-queue.h"
 
 #ifdef _WIN32
 #include <windows.h>
@@ -164,20 +165,19 @@ typedef struct DriveInfo {
     BlockInterfaceType type;
     int bus;
     int unit;
-    int used;
     int drive_opt_idx;
     BlockInterfaceErrorAction onerror;
     char serial[BLOCK_SERIAL_STRLEN + 1];
+    TAILQ_ENTRY(DriveInfo) next;
 } DriveInfo;
 
 #define MAX_IDE_DEVS   2
 #define MAX_SCSI_DEVS  7
 #define MAX_DRIVES 32
 
-extern int nb_drives;
-extern DriveInfo drives_table[MAX_DRIVES+1];
+extern TAILQ_HEAD(drivelist, DriveInfo) drives;
 
-extern int drive_get_index(BlockInterfaceType type, int bus, int unit);
+extern DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit);
 extern int drive_get_max_bus(BlockInterfaceType type);
 extern void drive_uninit(BlockDriverState *bdrv);
 extern void drive_remove(int index);
@@ -196,7 +196,8 @@ extern struct drive_opt drives_opt[MAX_DRIVES];
 extern int nb_drives_opt;
 
 extern int drive_add(const char *file, const char *fmt, ...);
-extern int drive_init(struct drive_opt *arg, int snapshot, void *machine);
+extern DriveInfo *drive_init(struct drive_opt *arg, int snapshot, void 
*machine,
+                             int *fatal_error);
 
 /* acpi */
 typedef void (*qemu_system_device_hot_add_t)(int pcibus, int slot, int state);
@@ -207,7 +208,7 @@ void qemu_system_device_hot_add(int pcibus, int slot, int 
state);
 
 typedef int (dev_match_fn)(void *dev_private, void *arg);
 
-int add_init_drive(const char *opts);
+DriveInfo *add_init_drive(const char *opts);
 void destroy_nic(dev_match_fn *match_fn, void *arg);
 void destroy_bdrvs(dev_match_fn *match_fn, void *arg);
 
diff --git a/vl.c b/vl.c
index ce213c2..68c2454 100644
--- a/vl.c
+++ b/vl.c
@@ -185,8 +185,7 @@ static const char *data_dir;
 const char *bios_name = NULL;
 /* Note: drives_table[MAX_DRIVES] is a dummy block driver if none available
    to store the VM snapshots */
-DriveInfo drives_table[MAX_DRIVES+1];
-int nb_drives;
+struct drivelist drives = TAILQ_HEAD_INITIALIZER(drives);
 enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
 static DisplayState *display_state;
 DisplayType display_type = DT_DEFAULT;
@@ -1884,19 +1883,6 @@ static int drive_opt_get_free_idx(void)
     return -1;
 }
 
-static int drive_get_free_idx(void)
-{
-    int index;
-
-    for (index = 0; index < MAX_DRIVES; index++)
-        if (!drives_table[index].used) {
-            drives_table[index].used = 1;
-            return index;
-        }
-
-    return -1;
-}
-
 int drive_add(const char *file, const char *fmt, ...)
 {
     va_list ap;
@@ -1923,54 +1909,56 @@ void drive_remove(int index)
     nb_drives_opt--;
 }
 
-int drive_get_index(BlockInterfaceType type, int bus, int unit)
+DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit)
 {
-    int index;
+    DriveInfo *dinfo;
 
     /* seek interface, bus and unit */
 
-    for (index = 0; index < MAX_DRIVES; index++)
-        if (drives_table[index].type == type &&
-           drives_table[index].bus == bus &&
-           drives_table[index].unit == unit &&
-           drives_table[index].used)
-        return index;
+    TAILQ_FOREACH(dinfo, &drives, next) {
+        if (dinfo->type == type &&
+           dinfo->bus == bus &&
+           dinfo->unit == unit)
+            return dinfo;
+    }
 
-    return -1;
+    return NULL;
 }
 
 int drive_get_max_bus(BlockInterfaceType type)
 {
     int max_bus;
-    int index;
+    DriveInfo *dinfo;
 
     max_bus = -1;
-    for (index = 0; index < nb_drives; index++) {
-        if(drives_table[index].type == type &&
-           drives_table[index].bus > max_bus)
-            max_bus = drives_table[index].bus;
+    TAILQ_FOREACH(dinfo, &drives, next) {
+        if(dinfo->type == type &&
+           dinfo->bus > max_bus)
+            max_bus = dinfo->bus;
     }
     return max_bus;
 }
 
 const char *drive_get_serial(BlockDriverState *bdrv)
 {
-    int index;
+    DriveInfo *dinfo;
 
-    for (index = 0; index < nb_drives; index++)
-        if (drives_table[index].bdrv == bdrv)
-            return drives_table[index].serial;
+    TAILQ_FOREACH(dinfo, &drives, next) {
+        if (dinfo->bdrv == bdrv)
+            return dinfo->serial;
+    }
 
     return "\0";
 }
 
 BlockInterfaceErrorAction drive_get_onerror(BlockDriverState *bdrv)
 {
-    int index;
+    DriveInfo *dinfo;
 
-    for (index = 0; index < nb_drives; index++)
-        if (drives_table[index].bdrv == bdrv)
-            return drives_table[index].onerror;
+    TAILQ_FOREACH(dinfo, &drives, next) {
+        if (dinfo->bdrv == bdrv)
+            return dinfo->onerror;
+    }
 
     return BLOCK_ERR_STOP_ENOSPC;
 }
@@ -1982,19 +1970,20 @@ static void bdrv_format_print(void *opaque, const char 
*name)
 
 void drive_uninit(BlockDriverState *bdrv)
 {
-    int i;
+    DriveInfo *dinfo;
 
-    for (i = 0; i < MAX_DRIVES; i++)
-        if (drives_table[i].bdrv == bdrv) {
-            drives_table[i].bdrv = NULL;
-            drives_table[i].used = 0;
-            drive_remove(drives_table[i].drive_opt_idx);
-            nb_drives--;
-            break;
-        }
+    TAILQ_FOREACH(dinfo, &drives, next) {
+        if (dinfo->bdrv != bdrv)
+            continue;
+        drive_remove(dinfo->drive_opt_idx);
+        TAILQ_REMOVE(&drives, dinfo, next);
+        qemu_free(dinfo);
+        break;
+    }
 }
 
-int drive_init(struct drive_opt *arg, int snapshot, void *opaque)
+DriveInfo *drive_init(struct drive_opt *arg, int snapshot, void *opaque,
+                      int *fatal_error)
 {
     char buf[128];
     char file[1024];
@@ -2013,7 +2002,7 @@ int drive_init(struct drive_opt *arg, int snapshot, void 
*opaque)
     int cache;
     int bdrv_flags, onerror;
     const char *devaddr;
-    int drives_table_idx;
+    DriveInfo *dinfo;
     char *str = arg->opt;
     static const char * const params[] = { "bus", "unit", "if", "index",
                                            "cyls", "heads", "secs", "trans",
@@ -2021,11 +2010,12 @@ int drive_init(struct drive_opt *arg, int snapshot, 
void *opaque)
                                            "cache", "format", "serial",
                                            "werror", "addr",
                                            NULL };
+    *fatal_error = 1;
 
     if (check_params(buf, sizeof(buf), params, str) < 0) {
          fprintf(stderr, "qemu: unknown parameter '%s' in '%s'\n",
                          buf, str);
-         return -1;
+         return NULL;
     }
 
     file[0] = 0;
@@ -2053,7 +2043,7 @@ int drive_init(struct drive_opt *arg, int snapshot, void 
*opaque)
         bus_id = strtol(buf, NULL, 0);
        if (bus_id < 0) {
            fprintf(stderr, "qemu: '%s' invalid bus id\n", str);
-           return -1;
+           return NULL;
        }
     }
 
@@ -2061,7 +2051,7 @@ int drive_init(struct drive_opt *arg, int snapshot, void 
*opaque)
         unit_id = strtol(buf, NULL, 0);
        if (unit_id < 0) {
            fprintf(stderr, "qemu: '%s' invalid unit id\n", str);
-           return -1;
+           return NULL;
        }
     }
 
@@ -2093,7 +2083,7 @@ int drive_init(struct drive_opt *arg, int snapshot, void 
*opaque)
             max_devs = 0;
        } else {
             fprintf(stderr, "qemu: '%s' unsupported bus type '%s'\n", str, 
buf);
-            return -1;
+            return NULL;
        }
     }
 
@@ -2101,7 +2091,7 @@ int drive_init(struct drive_opt *arg, int snapshot, void 
*opaque)
         index = strtol(buf, NULL, 0);
        if (index < 0) {
            fprintf(stderr, "qemu: '%s' invalid index\n", str);
-           return -1;
+           return NULL;
        }
     }
 
@@ -2120,15 +2110,15 @@ int drive_init(struct drive_opt *arg, int snapshot, 
void *opaque)
     if (cyls || heads || secs) {
         if (cyls < 1 || cyls > 16383) {
             fprintf(stderr, "qemu: '%s' invalid physical cyls number\n", str);
-           return -1;
+           return NULL;
        }
         if (heads < 1 || heads > 16) {
             fprintf(stderr, "qemu: '%s' invalid physical heads number\n", str);
-           return -1;
+           return NULL;
        }
         if (secs < 1 || secs > 63) {
             fprintf(stderr, "qemu: '%s' invalid physical secs number\n", str);
-           return -1;
+           return NULL;
        }
     }
 
@@ -2137,7 +2127,7 @@ int drive_init(struct drive_opt *arg, int snapshot, void 
*opaque)
             fprintf(stderr,
                     "qemu: '%s' trans must be used with cyls,heads and secs\n",
                     str);
-            return -1;
+            return NULL;
         }
         if (!strcmp(buf, "none"))
             translation = BIOS_ATA_TRANSLATION_NONE;
@@ -2147,7 +2137,7 @@ int drive_init(struct drive_opt *arg, int snapshot, void 
*opaque)
             translation = BIOS_ATA_TRANSLATION_AUTO;
        else {
             fprintf(stderr, "qemu: '%s' invalid translation type\n", str);
-           return -1;
+           return NULL;
        }
     }
 
@@ -2158,12 +2148,12 @@ int drive_init(struct drive_opt *arg, int snapshot, 
void *opaque)
             if (cyls || secs || heads) {
                 fprintf(stderr,
                         "qemu: '%s' invalid physical CHS format\n", str);
-               return -1;
+               return NULL;
             }
            media = MEDIA_CDROM;
        } else {
            fprintf(stderr, "qemu: '%s' invalid media\n", str);
-           return -1;
+           return NULL;
        }
     }
 
@@ -2174,7 +2164,7 @@ int drive_init(struct drive_opt *arg, int snapshot, void 
*opaque)
            snapshot = 0;
        else {
            fprintf(stderr, "qemu: '%s' invalid snapshot option\n", str);
-           return -1;
+           return NULL;
        }
     }
 
@@ -2187,7 +2177,7 @@ int drive_init(struct drive_opt *arg, int snapshot, void 
*opaque)
             cache = 2;
         else {
            fprintf(stderr, "qemu: invalid cache option\n");
-           return -1;
+           return NULL;
         }
     }
 
@@ -2196,12 +2186,12 @@ int drive_init(struct drive_opt *arg, int snapshot, 
void *opaque)
             fprintf(stderr, "qemu: Supported formats:");
             bdrv_iterate_format(bdrv_format_print, NULL);
             fprintf(stderr, "\n");
-           return -1;
+           return NULL;
         }
         drv = bdrv_find_format(buf);
         if (!drv) {
             fprintf(stderr, "qemu: '%s' invalid format\n", buf);
-            return -1;
+            return NULL;
         }
     }
 
@@ -2217,7 +2207,7 @@ int drive_init(struct drive_opt *arg, int snapshot, void 
*opaque)
     if (get_param_value(buf, sizeof(serial), "werror", str)) {
         if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO) {
             fprintf(stderr, "werror is no supported by this format\n");
-            return -1;
+            return NULL;
         }
         if (!strcmp(buf, "ignore"))
             onerror = BLOCK_ERR_IGNORE;
@@ -2229,7 +2219,7 @@ int drive_init(struct drive_opt *arg, int snapshot, void 
*opaque)
             onerror = BLOCK_ERR_REPORT;
         else {
             fprintf(stderr, "qemu: '%s' invalid write error action\n", buf);
-            return -1;
+            return NULL;
         }
     }
 
@@ -2237,7 +2227,7 @@ int drive_init(struct drive_opt *arg, int snapshot, void 
*opaque)
     if (get_param_value(buf, sizeof(buf), "addr", str)) {
         if (type != IF_VIRTIO) {
             fprintf(stderr, "addr is not supported by in '%s'\n", str);
-            return -1;
+            return NULL;
         }
         devaddr = strdup(buf);
     }
@@ -2248,7 +2238,7 @@ int drive_init(struct drive_opt *arg, int snapshot, void 
*opaque)
         if (bus_id != 0 || unit_id != -1) {
             fprintf(stderr,
                     "qemu: '%s' index cannot be used with bus and unit\n", 
str);
-            return -1;
+            return NULL;
         }
         if (max_devs == 0)
         {
@@ -2266,7 +2256,7 @@ int drive_init(struct drive_opt *arg, int snapshot, void 
*opaque)
 
     if (unit_id == -1) {
        unit_id = 0;
-       while (drive_get_index(type, bus_id, unit_id) != -1) {
+       while (drive_get(type, bus_id, unit_id) != NULL) {
            unit_id++;
            if (max_devs && unit_id >= max_devs) {
                unit_id -= max_devs;
@@ -2280,15 +2270,17 @@ int drive_init(struct drive_opt *arg, int snapshot, 
void *opaque)
     if (max_devs && unit_id >= max_devs) {
         fprintf(stderr, "qemu: '%s' unit %d too big (max is %d)\n",
                         str, unit_id, max_devs - 1);
-        return -1;
+        return NULL;
     }
 
     /*
      * ignore multiple definitions
      */
 
-    if (drive_get_index(type, bus_id, unit_id) != -1)
-        return -2;
+    if (drive_get(type, bus_id, unit_id) != NULL) {
+        *fatal_error = 0;
+        return NULL;
+    }
 
     /* init */
 
@@ -2301,16 +2293,16 @@ int drive_init(struct drive_opt *arg, int snapshot, 
void *opaque)
         snprintf(buf, sizeof(buf), "%s%s%i",
                  devname, mediastr, unit_id);
     bdrv = bdrv_new(buf);
-    drives_table_idx = drive_get_free_idx();
-    drives_table[drives_table_idx].bdrv = bdrv;
-    drives_table[drives_table_idx].devaddr = devaddr;
-    drives_table[drives_table_idx].type = type;
-    drives_table[drives_table_idx].bus = bus_id;
-    drives_table[drives_table_idx].unit = unit_id;
-    drives_table[drives_table_idx].onerror = onerror;
-    drives_table[drives_table_idx].drive_opt_idx = arg - drives_opt;
-    strncpy(drives_table[drives_table_idx].serial, serial, sizeof(serial));
-    nb_drives++;
+    dinfo = qemu_mallocz(sizeof(*dinfo));
+    dinfo->bdrv = bdrv;
+    dinfo->devaddr = devaddr;
+    dinfo->type = type;
+    dinfo->bus = bus_id;
+    dinfo->unit = unit_id;
+    dinfo->onerror = onerror;
+    dinfo->drive_opt_idx = arg - drives_opt;
+    strncpy(dinfo->serial, serial, sizeof(serial));
+    TAILQ_INSERT_TAIL(&drives, dinfo, next);
 
     switch(type) {
     case IF_IDE:
@@ -2341,8 +2333,10 @@ int drive_init(struct drive_opt *arg, int snapshot, void 
*opaque)
     case IF_COUNT:
         abort();
     }
-    if (!file[0])
-        return -2;
+    if (!file[0]) {
+        *fatal_error = 0;
+        return NULL;
+    }
     bdrv_flags = 0;
     if (snapshot) {
         bdrv_flags |= BDRV_O_SNAPSHOT;
@@ -2355,11 +2349,12 @@ int drive_init(struct drive_opt *arg, int snapshot, 
void *opaque)
     if (bdrv_open2(bdrv, file, bdrv_flags, drv) < 0) {
         fprintf(stderr, "qemu: could not open disk image %s\n",
                         file);
-        return -1;
+        return NULL;
     }
     if (bdrv_key_required(bdrv))
         autostart = 0;
-    return drives_table_idx;
+    *fatal_error = 0;
+    return dinfo;
 }
 
 void qemu_register_boot_set(QEMUBootSetHandler *func, void *opaque)
@@ -4940,7 +4935,6 @@ int main(int argc, char **argv, char **envp)
 
     nb_net_clients = 0;
     nb_bt_opts = 0;
-    nb_drives = 0;
     nb_drives_opt = 0;
     nb_numa_nodes = 0;
     hda_index = -1;
@@ -5817,9 +5811,12 @@ int main(int argc, char **argv, char **envp)
 
     /* open the virtual block devices */
 
-    for(i = 0; i < nb_drives_opt; i++)
-        if (drive_init(&drives_opt[i], snapshot, machine) == -1)
-           exit(1);
+    for(i = 0; i < nb_drives_opt; i++) {
+        int fatal_error;
+        if (drive_init(&drives_opt[i], snapshot, machine, &fatal_error) == 
NULL)
+            if (fatal_error)
+                exit(1);
+    }
 
     register_savevm("timer", 0, 2, timer_save, timer_load, NULL);
     register_savevm_live("ram", 0, 3, ram_save_live, NULL, ram_load, NULL);
-- 
1.6.2.5





reply via email to

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