misc clean-ups
authorJuha Riihimäki <juhriihi@esdhcp03557.research.nokia.com>
Mon, 9 Mar 2009 11:20:15 +0000 (13:20 +0200)
committerJuha Riihimäki <juhriihi@esdhcp03557.research.nokia.com>
Mon, 9 Mar 2009 11:20:15 +0000 (13:20 +0200)
hw/beagle.c
hw/omap.h
hw/omap3.c
hw/omap3_mmc.c
hw/sd.c

index b8a540b..3296598 100644 (file)
@@ -32,7 +32,8 @@
 #include "hw.h"
 #include "block.h"
 
-#define BEAGLE_NAND_CS                 0
+#define BEAGLE_NAND_CS       0
+#define BEAGLE_NAND_PAGESIZE 0x800
 
 #define GPMC_NOR             0
 #define GPMC_NAND           1
 #define HS_DEVICE               0x2
 #define GP_DEVICE               0x3
 
-#define DEBUG_BEAGLE
-
-#ifdef DEBUG_BEAGLE
-#define BEAGLE_DEBUG(...)    do { fprintf(stderr, __VA_ARGS__); } while(0)
-#else
-#define BEAGLE_DEBUG(x)    
-#endif
-
 /* Beagle board support */
 struct beagle_s {
     struct omap_mpu_state_s *cpu;
@@ -65,122 +58,52 @@ struct beagle_s {
     struct twl4030_s *twl4030;
 };
 
-
-
 static struct arm_boot_info beagle_binfo = {
     .ram_size = 0x08000000,
 };
 
-
-static void beagle_nand_setup(struct beagle_s *s)
-{
-       s->nand = nand_init(NAND_MFR_MICRON, 0xba); /* MT29F2G16ABC */
-       nand_setpins(s->nand, 0, 0, 0, 1, 0); /* no write-protect */
-    omap_gpmc_attach(s->cpu->gpmc, BEAGLE_NAND_CS, 0, NULL, NULL, s, s->nand);
-    omap3_set_mem_type(s->cpu, GPMC_NAND);
-}
-
-static int beagle_nand_read_page(struct beagle_s *s,uint8_t *buf, uint32_t addr)
+static void beagle_nand_pread(struct nand_flash_s *nand,
+                              uint64_t addr,
+                              uint8_t *data,
+                              uint32_t len)
 {
-       uint16_t *p = (uint16_t *)buf;
-       int i;
-
+    uint16_t x;
+    uint32_t i;
+    
+    if ((len&1) || (addr&1)) {
+        fprintf(stderr, "%s: read byte length and address must be even (x16 device!)\n",
+                __FUNCTION__);
+        exit(-1);
+    }
     /* send command: reset */
-    nand_setpins(s->nand, 1, 0, 0, 1, 0);
-    nand_setio(s->nand, 0xff);
-       /* send command: read page (cycle1) */
-    nand_setpins(s->nand, 1, 0, 0, 1, 0);
-    nand_setio(s->nand, 0);
-       /* send page address (x16 device):
-       bits  0-11 define cache address in words (bit11 set only for OOB access)
-       bits 16-33 define page and block address */
-    nand_setpins(s->nand, 0, 1, 0, 1, 0);
-    nand_setio(s->nand, (addr >> 1) & 0xff);
-    nand_setio(s->nand, (addr >> 9) & 0x3);
-    nand_setio(s->nand, (addr >> 11) & 0xff);
-    nand_setio(s->nand, (addr >> 19) & 0xff);
-    nand_setio(s->nand, (addr >> 27) & 0x1);
-       /* send command: read page (cycle2) */
-    nand_setpins(s->nand, 1, 0, 0, 1, 0);
-    nand_setio(s->nand, 0x30);
-    /* read page data */
-    nand_setpins(s->nand, 0, 0, 0, 1, 0);
-    for (i = 0; i < 0x800 / 2; i++)
-        *(p++) = nand_getio(s->nand);
-    return 1;
-}
-
-/*read the xloader from NAND Flash into internal RAM*/
-static int beagle_boot_from_nand(struct beagle_s *s)
-{
-       uint32_t        loadaddr, len;
-       uint8_t nand_page[0x800],*load_dest;
-       uint32_t nand_pages,i;
-
-       /* The first two words(8 bytes) in first nand flash page have special meaning.
-               First word:x-loader len
-               Second word: x-load address in internal ram */
-       beagle_nand_read_page(s,nand_page,0);
-       len = *((uint32_t*)nand_page);
-       loadaddr =  *((uint32_t*)(nand_page+4));
-    fprintf(stderr, "%s: len = 0x%08x, addr = 0x%08x\n", __FUNCTION__, len, loadaddr);
-    if ((len==0)||(loadaddr==0)||(len==0xffffffff)||(loadaddr==0xffffffff))
-               return (-1);
-
-       /*put the first page into internal ram*/
-       load_dest = phys_ram_base + beagle_binfo.ram_size;
-       load_dest += loadaddr-OMAP3_SRAM_BASE;
-       
-       memcpy(load_dest,nand_page+8,0x800-8);
-       load_dest += 0x800-8;
-
-       nand_pages = len/0x800;
-       if (len%0x800!=0)
-               nand_pages++;
-
-       for (i=1;i<nand_pages;i++)
-       {
-               beagle_nand_read_page(s,nand_page,i*0x800);
-               memcpy(load_dest,nand_page,0x800);
-               load_dest += 0x800;
-       }
-       s->cpu->env->regs[15] = loadaddr;
-       return 0;
-
-}
-
-static int beagle_rom_emu(struct beagle_s *s)
-{
-    if (!omap3_mmc_boot(s->cpu))
-        if (beagle_boot_from_nand(s) < 0)
-            return -1;
-       return 0;
-}
-
-static void beagle_dss_setup(struct beagle_s *s)
-{
-       s->lcd_panel = omap3_lcd_panel_init();
-       omap3_lcd_panel_attach(s->cpu->dss, 0, s->lcd_panel);
-}
-
-//static void beagle_mmc_cs_cb(void *opaque, int line, int level)
-//{
-//    /* TODO: this seems to actually be connected to the menelaus, to
-//     * which also both MMC slots connect.  */
-//    omap_mmc_enable((struct omap_mmc_s *) opaque, !level);
-//
-//    printf("%s: MMC slot %i active\n", __FUNCTION__, level + 1);
-//}
-
-static void beagle_i2c_setup(struct beagle_s *s)
-{
-    /* Attach the CPU on one end of our I2C bus.  */
-    s->i2c = omap_i2c_bus(s->cpu->i2c[0]);
-
-    s->twl4030 = twl4030_init(s->i2c, s->cpu->irq[0][OMAP_INT_35XX_SYS_NIRQ]);
+    nand_setpins(nand, 1, 0, 0, 1, 0);
+    nand_setio(nand, 0xff);
+    while (len) {
+        /* send command: read page (cycle1) */
+        nand_setpins(nand, 1, 0, 0, 1, 0);
+        nand_setio(nand, 0);
+        /* send address */
+        nand_setpins(nand, 0, 1, 0, 1, 0);
+        nand_setio(nand, (uint32_t)((addr >> 1) & 0xff));
+        nand_setio(nand, (uint32_t)((addr >> 9) & 0x3));
+        nand_setio(nand, (uint32_t)((addr >> 11) & 0xff));
+        nand_setio(nand, (uint32_t)((addr >> 19) & 0xff));
+        nand_setio(nand, (uint32_t)((addr >> 27) & 0x1));
+        /* send command: read page (cycle2) */
+        nand_setpins(nand, 1, 0, 0, 1, 0);
+        nand_setio(nand, 0x30);
+        /* read page data */
+        nand_setpins(nand, 0, 0, 0, 1, 0);
+        for (i = (BEAGLE_NAND_PAGESIZE / 2) - (addr & 0x3ff); i && len; i--) {
+            x = nand_getio(nand);
+            *(data++) = (uint8_t)(x & 0xff);
+            *(data++) = (uint8_t)((x >> 8) & 0xff);
+            len -= 2;
+            addr += 2;
+        }
+    }
 }
 
-
 static void beagle_init(ram_addr_t ram_size, int vga_ram_size,
                 const char *boot_device,
                 const char *kernel_filename, const char *kernel_cmdline,
@@ -188,24 +111,43 @@ static void beagle_init(ram_addr_t ram_size, int vga_ram_size,
 {
     struct beagle_s *s = (struct beagle_s *) qemu_mallocz(sizeof(*s));
     int sdram_size = beagle_binfo.ram_size;
-
+    int sdindex = drive_get_index(IF_SD, 0, 0);
+    
+    if (sdindex == -1) {
+        fprintf(stderr, "qemu: missing SecureDigital device\n");
+        exit(1);
+    }
+    
        if (ram_size < sdram_size +  OMAP3530_SRAM_SIZE) {
         fprintf(stderr, "This architecture uses %i bytes of memory\n",
                         sdram_size + OMAP3530_SRAM_SIZE);
         exit(1);
     }
        s->cpu = omap3530_mpu_init(sdram_size, NULL);
-       beagle_nand_setup(s);
-       beagle_i2c_setup(s);
-       beagle_dss_setup(s);
-       omap3_set_device_type(s->cpu,GP_DEVICE);
-    if (beagle_rom_emu(s) < 0) {
-               fprintf(stderr,"boot from MMC and nand failed \n");
-               exit(-1);
-       }
-}
+    
+    if (serial_hds[0])
+        omap_uart_attach(s->cpu->uart[2], serial_hds[0]);
+
+       s->nand = nand_init(NAND_MFR_MICRON, 0xba); /* MT29F2G16ABC */
+       nand_setpins(s->nand, 0, 0, 0, 1, 0); /* no write-protect */
+    omap_gpmc_attach(s->cpu->gpmc, BEAGLE_NAND_CS, 0, NULL, NULL, s, s->nand);
+    omap3_mmc_attach(s->cpu->omap3_mmc[0], drives_table[sdindex].bdrv);
 
+    s->i2c = omap_i2c_bus(s->cpu->i2c[0]);
+    s->twl4030 = twl4030_init(s->i2c, s->cpu->irq[0][OMAP_INT_35XX_SYS_NIRQ]);
 
+       s->lcd_panel = omap3_lcd_panel_init();
+       omap3_lcd_panel_attach(s->cpu->dss, 0, s->lcd_panel);
+
+    omap3_set_mem_type(s->cpu, GPMC_NAND);
+       omap3_set_device_type(s->cpu,GP_DEVICE);
+    if (!omap3_mmc_boot(s->cpu) 
+        && !omap3_nand_boot(s->cpu, s->nand, beagle_nand_pread)) {
+        fprintf(stderr, "%s: boot from MMC and NAND failed\n",
+                __FUNCTION__);
+        exit(-1);
+    }
+}
 
 QEMUMachine beagle_machine = {
     .name = "beagle",
index e0fb14d..c69b932 100644 (file)
--- a/hw/omap.h
+++ b/hw/omap.h
@@ -986,8 +986,10 @@ void omap_mmc_enable(struct omap_mmc_s *s, int enable);
 /* omap3_mmc.c */
 struct omap3_mmc_s;
 struct omap3_mmc_s *omap3_mmc_init(struct omap_target_agent_s *ta,
-                BlockDriverState *bd, qemu_irq irq, qemu_irq dma[],
-                omap_clk fclk, omap_clk iclk);
+                                   qemu_irq irq, qemu_irq dma[],
+                                   omap_clk fclk, omap_clk iclk);
+void omap3_mmc_attach(struct omap3_mmc_s *s,
+                      BlockDriverState *bd);
 
 /* omap_i2c.c */
 struct omap_i2c_s;
@@ -1238,6 +1240,12 @@ struct omap_mpu_state_s *omap3530_mpu_init(unsigned long sdram_size,
 void omap3_set_mem_type(struct omap_mpu_state_s *s, int bootfrom);
 void omap3_set_device_type(struct omap_mpu_state_s *s, int device_type);
 int omap3_mmc_boot(struct omap_mpu_state_s *s);
+int omap3_nand_boot(struct omap_mpu_state_s *mpu,
+                    struct nand_flash_s *nand,
+                    void (*nand_pread_f)(struct nand_flash_s *nand,
+                                         uint64_t address,
+                                         uint8_t *data,
+                                         uint32_t len));
 
 # if TARGET_PHYS_ADDR_BITS == 32
 #  define OMAP_FMT_plx "0x%08x"
index 4edc398..b7889d3 100644 (file)
@@ -4207,8 +4207,6 @@ struct omap_mpu_state_s *omap3530_mpu_init(unsigned long sdram_size,
     qemu_irq *cpu_irq;
     qemu_irq dma_irqs[4];
     int i;
-    int sdindex;
-    //omap_clk gpio_clks[4];
 
     s->mpu_model = omap3530;
     s->env = cpu_init("cortex-a8-r2");
@@ -4219,12 +4217,6 @@ struct omap_mpu_state_s *omap3530_mpu_init(unsigned long sdram_size,
     s->sdram_size = sdram_size;
     s->sram_size = OMAP3530_SRAM_SIZE;
 
-    sdindex = drive_get_index(IF_SD, 0, 0);
-    if (sdindex == -1) {
-        fprintf(stderr, "qemu: missing SecureDigital device\n");
-        exit(1);
-    }
-
     /* Clocks */
     omap_clk_init(s);
 
@@ -4256,7 +4248,6 @@ struct omap_mpu_state_s *omap3530_mpu_init(unsigned long sdram_size,
                             omap_findclk(s, "omap3_sdma_iclk"));
     s->port->addr_valid = omap3_validate_addr;
 
-
     /* Register SDRAM and SRAM ports for fast DMA transfers.  */
     soc_dma_port_add_mem_ram(s->dma, q2_base, OMAP2_Q2_BASE, s->sdram_size);
     soc_dma_port_add_mem_ram(s->dma, sram_base, OMAP2_SRAM_BASE, s->sram_size);
@@ -4345,35 +4336,24 @@ struct omap_mpu_state_s *omap3530_mpu_init(unsigned long sdram_size,
                                  omap_findclk(s, "omap3_uart1_fclk"),
                                  omap_findclk(s, "omap3_uart1_iclk"),
                                  s->drq[OMAP35XX_DMA_UART1_TX],
-                                 s->drq[OMAP35XX_DMA_UART1_RX], serial_hds[0]);
+                                 s->drq[OMAP35XX_DMA_UART1_RX], 0);
     s->uart[1] = omap2_uart_init(omap3_l4ta_init(s->l4, L4A_UART2),
                                  s->irq[0][OMAP_INT_35XX_UART2_IRQ],
                                  omap_findclk(s, "omap3_uart2_fclk"),
                                  omap_findclk(s, "omap3_uart2_iclk"),
                                  s->drq[OMAP35XX_DMA_UART2_TX],
-                                 s->drq[OMAP35XX_DMA_UART2_RX],
-                                 serial_hds[0] ? serial_hds[1] : 0);
+                                 s->drq[OMAP35XX_DMA_UART2_RX], 0);
     s->uart[2] = omap2_uart_init(omap3_l4ta_init(s->l4, L4A_UART3),
                                  s->irq[0][OMAP_INT_35XX_UART3_IRQ],
                                  omap_findclk(s, "omap3_uart2_fclk"),
                                  omap_findclk(s, "omap3_uart3_iclk"),
                                  s->drq[OMAP35XX_DMA_UART3_TX],
-                                 s->drq[OMAP35XX_DMA_UART3_RX],
-                                 serial_hds[0]
-                                 && serial_hds[1] ? serial_hds[2] : 0);
+                                 s->drq[OMAP35XX_DMA_UART3_RX], 0);
     
-    /*attach serial[0] to uart 2 for beagle board */
-    omap_uart_attach(s->uart[2], serial_hds[0]);
-
     s->dss = omap_dss_init(s, omap3_l4ta_init(s->l4, L4A_DSS), 
                     s->irq[0][OMAP_INT_35XX_DSS_IRQ], s->drq[OMAP24XX_DMA_DSS],
                    NULL,NULL,NULL,NULL,NULL);
 
-    //gpio_clks[0] = NULL;
-    //gpio_clks[1] = NULL;
-    //gpio_clks[2] = NULL;
-    //gpio_clks[3] = NULL;
-
     s->gpif = omap3_gpif_init();
     omap3_gpio_init(s, s->gpif ,omap3_l4ta_init(s->l4, L4A_GPIO1),
                     &s->irq[0][OMAP_INT_35XX_GPIO1_MPU_IRQ], 
@@ -4397,21 +4377,18 @@ struct omap_mpu_state_s *omap3530_mpu_init(unsigned long sdram_size,
     omap_tap_init(omap3_l4ta_init(s->l4, L4A_TAP), s);
 
     s->omap3_mmc[0] = omap3_mmc_init(omap3_l4ta_init(s->l4, L4A_MMC1),
-                                     drives_table[sdindex].bdrv,
                                      s->irq[0][OMAP_INT_35XX_MMC1_IRQ],
                                      &s->drq[OMAP35XX_DMA_MMC1_TX],
                                      omap_findclk(s, "omap3_mmc1_fclk"),
                                      omap_findclk(s, "omap3_mmc1_iclk"));
 
     s->omap3_mmc[1] = omap3_mmc_init(omap3_l4ta_init(s->l4, L4A_MMC2),
-                                     NULL,
                                      s->irq[0][OMAP_INT_35XX_MMC2_IRQ],
                                      &s->drq[OMAP35XX_DMA_MMC2_TX],
                                      omap_findclk(s, "omap3_mmc2_fclk"),
                                      omap_findclk(s, "omap3_mmc2_iclk"));
 
     s->omap3_mmc[2] = omap3_mmc_init(omap3_l4ta_init(s->l4, L4A_MMC3),
-                                     NULL,
                                      s->irq[0][OMAP_INT_35XX_MMC3_IRQ],
                                      &s->drq[OMAP35XX_DMA_MMC3_TX],
                                      omap_findclk(s, "omap3_mmc3_fclk"),
@@ -4688,10 +4665,14 @@ static uint32_t omap3_boot_block(const uint8_t *data,
             s->state = imagehdr;
             /* fallthrough */
         case imagehdr:
+            if (!data_len)
+                return 1;
             if (data_len < 8)
                 break;
             s->count = omap3_get_le32(data);
             s->addr = omap3_get_le32(data + 4);
+            if (!s->count || !s->addr || s->addr == 0xffffffff)
+                break;
             s->mpu->env->regs[15] = s->addr;
             data += 8;
             data_len -= 8;
@@ -4702,7 +4683,7 @@ static uint32_t omap3_boot_block(const uint8_t *data,
             cpu_physical_memory_write(s->addr, data, i);
             s->addr += i;
             s->count -= i;
-           if (!s->count)
+            if (!s->count)
                 s->state = done;
             return s->count;
         default:
@@ -4837,8 +4818,8 @@ static int omap3_mmc_fat_boot(BlockDriverState *bs,
             boot->state = imagehdr; /* override CH detection */
             while (omap3_boot_block(data, j, boot))
                 i = omap3_read_fat_cluster(data, &drv, i);
+            result = (boot->state == done);
             free(boot);
-            result = 1;
         } else
             fprintf(stderr, "%s: unable to read MLO file contents from SD card\n",
                     __FUNCTION__);
@@ -4856,6 +4837,7 @@ static int omap3_mmc_raw_boot(BlockDriverState *bs,
 {
     struct omap3_boot_s *boot;
     uint32_t i = 0;
+    int result = 0;
     
     if (bdrv_pread(bs, 0, sector, 0x200) == 0x200) {
         boot = omap3_boot_init(sector, 0x200, mpu);
@@ -4868,9 +4850,10 @@ static int omap3_mmc_raw_boot(BlockDriverState *bs,
                 }
             }
         }
+        result = (boot->state == done);
         free(boot);
     }
-    return 0;
+    return result;
 }
 
 /* returns non-zero if successful, zero if unsuccessful */
@@ -4909,3 +4892,28 @@ int omap3_mmc_boot(struct omap_mpu_state_s *s)
     return result;
 }
 
+/* returns non-zero if successful, zero if unsuccessful */
+int omap3_nand_boot(struct omap_mpu_state_s *mpu,
+                    struct nand_flash_s *nand,
+                    void (*nand_pread_f)(struct nand_flash_s *nand,
+                                         uint64_t address,
+                                         uint8_t *data,
+                                         uint32_t len))
+{
+    struct omap3_boot_s *boot;
+    uint8_t *data;
+    uint64_t addr = 0;
+    int result = 0;
+    
+    data = qemu_mallocz(0x1000);
+    nand_pread_f(nand, 0, data, 0x1000);
+    boot = omap3_boot_init(data, 0x1000, mpu);
+    while (omap3_boot_block(data, 0x1000, boot)) {
+        addr += 0x1000;
+        nand_pread_f(nand, addr, data, 0x1000);
+    }
+    result = (boot->state == done);
+    free(boot);
+    free(data);
+    return result;
+}
index 6954ee6..dc7b2b8 100644 (file)
@@ -174,6 +174,10 @@ static void omap3_mmc_fifolevel_update(struct omap3_mmc_s *host)
                        ? "complete"
                        : "aborted --> complete");
                 host->stat_pending |= 0x2;         /* TC */
+                if (host->cmd & 0x04) {            /* ACEN */
+                    host->stop = 0x0cc30000;
+                    state = aborted;
+                }
                 if (state == aborted) {
                     host->cmd = host->stop;
                     host->stop = 0;
@@ -523,14 +527,15 @@ static void omap3_mmc_write(void *opaque, target_phys_addr_t addr,
             break;
         case 0x02c: /* MMCHS_CON */
             TRACE2("CON = %08x", value);
-            if (value & 0x10) {
-                fprintf(stderr, "%s: SYSTEST mode is not supported\n", __FUNCTION__);
-                exit(-1);
-            }
-            if (value & 0x20) {
-                fprintf(stderr, "%s: 8-bit data width is not supported\n", __FUNCTION__);
-                exit(-1);
-            }
+            if (value & 0x10)   /* MODE */
+                fprintf(stderr, "%s: SYSTEST mode is not supported\n",
+                        __FUNCTION__);
+            if (value & 0x20)   /* DW8 */
+                fprintf(stderr, "%s: 8-bit data width is not supported\n",
+                        __FUNCTION__);
+            if (value & 0x1000) /* CEATA */
+                fprintf(stderr, "%s: CE-ATA control mode not supported\n",
+                        __FUNCTION__);
             s->con = value & 0x1ffff;
             break;
         case 0x030:
@@ -549,21 +554,22 @@ static void omap3_mmc_write(void *opaque, target_phys_addr_t addr,
             break;
         case 0x10c: /* MMCHS_CMD */
             TRACE2("CMD = %08x", value);
-            /* TODO: writing to bits 0-15 should have no effect during
-               an active data transfer */
-            if (value & 4) { /* ACEN */
-                fprintf(stderr, "%s: AutoCMD12 not supported!\n", __FUNCTION__);
-                exit(-1);
-            }
-            if (!s->stop
-                && (((value >> 24) & 0x3f) == 12 || ((value >> 24) & 0x3f) == 52)) {
-                s->stop = value & 0x3ffb0037;
+            if (!s->card) {
+                s->stat_pending |= (1 << 16); /* CTO */
             } else {
-                s->cmd = value & 0x3ffb0037;
-                omap3_mmc_command(s);
+                /* TODO: writing to bits 0-15 should have no effect during
+                   an active data transfer */
+                if (!s->stop
+                    && (((value >> 24) & 0x3f) == 12
+                        || ((value >> 24) & 0x3f) == 52)) {
+                    s->stop = value & 0x3ffb0037;
+                } else {
+                    s->cmd = value & 0x3ffb0037;
+                    omap3_mmc_command(s);
+                }
+                omap3_mmc_transfer(s);
+                omap3_mmc_fifolevel_update(s);
             }
-            omap3_mmc_transfer(s);
-            omap3_mmc_fifolevel_update(s);
             omap3_mmc_interrupts_update(s);
             break;
         case 0x120:
@@ -662,14 +668,9 @@ static CPUWriteMemoryFunc *omap3_mmc_writefn[] = {
     omap3_mmc_write,
 };
 
-static void omap3_mmc_enable(struct omap3_mmc_s *s, int enable)
-{
-    sd_enable(s->card, enable);
-}
-
 struct omap3_mmc_s *omap3_mmc_init(struct omap_target_agent_s *ta,
-                                   BlockDriverState * bd, qemu_irq irq,
-                                   qemu_irq dma[], omap_clk fclk, omap_clk iclk)
+                                   qemu_irq irq, qemu_irq dma[],
+                                   omap_clk fclk, omap_clk iclk)
 {
     int iomemtype;
     struct omap3_mmc_s *s = (struct omap3_mmc_s *)
@@ -685,11 +686,16 @@ struct omap3_mmc_s *omap3_mmc_init(struct omap_target_agent_s *ta,
                                       omap3_mmc_writefn, s);
     omap_l4_attach(ta, 0, iomemtype);
 
-    /* Instantiate the storage */
-    if (bd!=NULL) {
-       s->card = sd_init(bd, 0);
-           omap3_mmc_enable(s,1);
-    }
-
     return s;
 }
+
+void omap3_mmc_attach(struct omap3_mmc_s *s,
+                      BlockDriverState *bd)
+{
+    if (s->card) {
+        fprintf(stderr, "%s: SD card already attached!\n", __FUNCTION__);
+        exit(-1);
+    }
+    s->card = sd_init(bd, 0);
+    sd_enable(s->card, 1);
+}
diff --git a/hw/sd.c b/hw/sd.c
index c09f09d..030da32 100644 (file)
--- a/hw/sd.c
+++ b/hw/sd.c
@@ -1230,7 +1230,7 @@ int sd_do_command(SDState *sd, struct sd_request_s *req,
     sd_rsp_type_t rtype;
     int rsplen;
 
-    if (!bdrv_is_inserted(sd->bdrv) || !sd->enable) {
+    if (!sd->bdrv || !bdrv_is_inserted(sd->bdrv) || !sd->enable) {
         return 0;
     }