Merge commit 'gnu/master' into test
authorRiku Voipio <riku.voipio@nokia.com>
Mon, 8 Jun 2009 15:31:58 +0000 (18:31 +0300)
committerRiku Voipio <riku.voipio@nokia.com>
Mon, 8 Jun 2009 15:31:58 +0000 (18:31 +0300)
Epic merge

Conflicts:
Makefile
block.c
block.h
configure
hw/boards.h
hw/flash.h
hw/integratorcp.c
hw/nand.c
hw/omap2.c
hw/omap_i2c.c
hw/sd.c
hw/smc91c111.c
hw/tsc2005.c
hw/tusb6010.c
hw/usb-musb.c
linux-user/syscall.c
target-arm/machine.c
target-arm/translate.c

37 files changed:
1  2 
Makefile
Makefile.target
configure
cpu-all.h
elf.h
exec.c
hw/beagle.c
hw/blizzard.c
hw/devices.h
hw/flash.h
hw/i2c.h
hw/nand.c
hw/nseries.c
hw/omap.h
hw/omap1.c
hw/omap2.c
hw/omap3_mmc.c
hw/omap3_usb.c
hw/omap_clk.c
hw/omap_dss.c
hw/omap_i2c.c
hw/onenand.c
hw/sd.c
hw/smc91c111.c
hw/tsc2005.c
hw/tusb6010.c
hw/twl4030.c
hw/usb-musb.c
hw/usb-ohci.c
linux-user/elfload.c
linux-user/main.c
linux-user/qemu.h
linux-user/signal.c
linux-user/syscall.c
linux-user/syscall_defs.h
target-arm/machine.c
target-arm/translate.c

diff --cc Makefile
+++ b/Makefile
@@@ -63,10 -65,10 +65,10 @@@ recurse-all: $(SUBDIR_RULES
  #######################################################################
  # BLOCK_OBJS is code used by both qemu system emulation and qemu-img
  
- BLOCK_OBJS=cutils.o cache-utils.o qemu-malloc.o
- BLOCK_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o
- BLOCK_OBJS+=block-dmg.o block-bochs.o block-vpc.o block-vvfat.o
- BLOCK_OBJS+=block-qcow2.o block-parallels.o block-nbd.o block-vmstate.o
+ BLOCK_OBJS=cutils.o cache-utils.o qemu-malloc.o qemu-option.o module.o
+ BLOCK_OBJS+=block/cow.o block/qcow.o aes.o block/vmdk.o block/cloop.o
+ BLOCK_OBJS+=block/dmg.o block/bochs.o block/vpc.o block/vvfat.o
 -BLOCK_OBJS+=block/qcow2.o block/parallels.o block/nbd.o
++BLOCK_OBJS+=block/qcow2.o block/parallels.o block/nbd.o block-vmstate.o
  BLOCK_OBJS+=nbd.o block.o aio.o
  
  ifdef CONFIG_WIN32
@@@ -233,10 -254,10 +254,10 @@@ qemu-img-cmds.h: $(SRC_PATH)/qemu-img-c
  clean:
  # avoid old build problems by removing potentially incorrect old files
        rm -f config.mak config.h op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h
 -      rm -f *.o *.d *.a $(TOOLS) TAGS cscope.* *.pod *~ */*~
 +      rm -f *.o *.d *.a $(TOOLS) tags TAGS cscope.* *.pod *~ */*~
-       rm -f slirp/*.o slirp/*.d audio/*.o audio/*.d
+       rm -f slirp/*.o slirp/*.d audio/*.o audio/*.d block/*.o block/*.d
        $(MAKE) -C tests clean
-       for d in $(TARGET_DIRS); do \
+       for d in $(TARGET_DIRS) libhw32 libhw64; do \
        $(MAKE) -C $$d $@ || exit 1 ; \
          done
  
diff --cc Makefile.target
@@@ -669,10 -664,9 +666,10 @@@ OBJS+= arm-semi.
  OBJS+= pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o
  OBJS+= pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o pxa2xx_keypad.o
  OBJS+= pflash_cfi01.o gumstix.o
- OBJS+= zaurus.o ide.o serial.o nand.o ecc.o spitz.o tosa.o tc6393xb.o
+ OBJS+= zaurus.o ide.o serial.o spitz.o tosa.o tc6393xb.o
  OBJS+= omap1.o omap_lcdc.o omap_dma.o omap_clk.o omap_mmc.o omap_i2c.o
 -OBJS+= omap2.o omap_dss.o soc_dma.o
 +OBJS+= omap2.o omap_dss.o soc_dma.o omap_spi.o
 +OBJS+= omap3.o omap3_boot.o omap3_mmc.o omap3_usb.o beagle.o twl4030.o
  OBJS+= omap_sx1.o palm.o tsc210x.o
  OBJS+= nseries.o blizzard.o onenand.o vga.o cbus.o tusb6010.o usb-musb.o
  OBJS+= mst_fpga.o mainstone.o
diff --cc configure
+++ b/configure
@@@ -178,10 -180,10 +180,11 @@@ softmmu="yes
  linux_user="no"
  darwin_user="no"
  bsd_user="no"
 -build_docs="yes"
 +guest_base="no"
 +build_docs="no"
  uname_release=""
  curses="yes"
+ curl="yes"
  pthread="yes"
  aio="yes"
  io_thread="no"
    fi
  fi
  
 +# check if utimensat and futimens are supported
 +utimens=no
 +cat > $TMPC << EOF
 +#define _ATFILE_SOURCE
 +#define _GNU_SOURCE
 +#include <stddef.h>
 +#include <fcntl.h>
 +
 +int main(void)
 +{
 +    utimensat(AT_FDCWD, "foo", NULL, 0);
 +    futimens(0, NULL);
 +    return 0;
 +}
 +EOF
 +if $cc $ARCH_CFLAGS -o $TMPE $TMPC 2> /dev/null ; then
 +  utimens=yes
 +fi
 +
  # Check if tools are available to build documentation.
- if [ -x "`which texi2html 2>/dev/null`" ] && \
-    [ -x "`which pod2man 2>/dev/null`" ]; then
-   build_docs="yes"
+ if test "$build_docs" = "yes" -a \( ! -x "`which texi2html 2>/dev/null`" -o ! -x "`which pod2man 2>/dev/null`" \) ; then
+   build_docs="no"
  fi
  
  ##########################################
diff --cc cpu-all.h
Simple merge
diff --cc elf.h
Simple merge
diff --cc exec.c
Simple merge
diff --cc hw/beagle.c
index 3e91935,0000000..d422114
mode 100644,000000..100644
--- /dev/null
@@@ -1,87 -1,0 +1,94 @@@
 +/*
 + * Beagle board emulation. http://beagleboard.org/
 + * 
 + * Original code Copyright (C) 2008 yajin(yajin@vm-kernel.org)
 + * Rewrite Copyright (C) 2009 Nokia Corporation
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License as
 + * published by the Free Software Foundation; either version 2 or
 + * (at your option) version 3 of the License.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 + * MA 02111-1307 USA
 + */
 +
 +#include "qemu-common.h"
 +#include "sysemu.h"
 +#include "omap.h"
 +#include "arm-misc.h"
 +#include "boards.h"
 +#include "i2c.h"
 +#include "net.h"
 +#include "devices.h"
 +#include "flash.h"
 +
 +#define BEAGLE_NAND_CS       0
 +#define BEAGLE_SMC_CS        1
 +#define BEAGLE_NAND_PAGESIZE 0x800
 +#define BEAGLE_SDRAM_SIZE    (128 * 1024 * 1024) /* 128MB */
 +
 +/* Beagle board support */
 +struct beagle_s {
 +    struct omap_mpu_state_s *cpu;
 +    
-     struct nand_flash_s *nand;
++    NANDFlashState *nand;
 +    struct omap3_lcd_panel_s *lcd_panel;
 +    i2c_bus *i2c;
-     struct twl4030_s *twl4030;
++    void *twl4030;
 +};
 +
- 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,
-                 const char *initrd_filename, const char *cpu_model)
++static void beagle_init(ram_addr_t ram_size,
++                        const char *boot_device,
++                        const char *kernel_filename,
++                        const char *kernel_cmdline,
++                        const char *initrd_filename,
++                        const char *cpu_model)
 +{
 +    struct beagle_s *s = (struct beagle_s *) qemu_mallocz(sizeof(*s));
 +    int sdindex = drive_get_index(IF_SD, 0, 0);
 +    void *opaque;
 +    
 +    if (sdindex == -1) {
 +        fprintf(stderr, "%s: missing SecureDigital device\n", __FUNCTION__);
 +        exit(1);
 +    }
 +      s->cpu = omap3530_mpu_init(ram_size, NULL, NULL, 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->nand, 2);
 +    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_3XXX_SYS_NIRQ]);
-     opaque = smc91c111_init(&nd_table[0], 0x08000000,
-                     omap2_gpio_in_get(s->cpu->gpif, 54)[0], 0);
++    opaque = smc91c111_init_lite(&nd_table[0], /*0x08000000,*/
++                    omap2_gpio_in_get(s->cpu->gpif, 54)[0]);
 +    omap_gpmc_attach(s->cpu->gpmc, BEAGLE_SMC_CS, smc91c111_iomemtype(opaque),
-                      0, 0, opaque, 0);
++                     NULL, NULL, opaque, 0);
 +
 +      s->lcd_panel = omap3_lcd_panel_init();
 +      omap3_lcd_panel_attach(s->cpu->dss, 0, s->lcd_panel);
 +    
 +    omap3_boot_rom_emu(s->cpu);
 +}
 +
 +QEMUMachine beagle_machine = {
 +    .name =        "beagle",
 +    .desc =        "Beagle board (OMAP3530)",
 +    .init =        beagle_init,
- /*    .ram_require = OMAP3XXX_SRAM_SIZE + OMAP3XXX_BOOTROM_SIZE, */
 +};
 +
++static void beagle_machine_init(void)
++{
++    qemu_register_machine(&beagle_machine);
++}
++
++machine_init(beagle_machine_init);
diff --cc hw/blizzard.c
@@@ -117,8 -118,9 +117,8 @@@ typedef struct 
          uint16_t *ptr;
          int angle;
          int pitch;
 -        blizzard_fn_t line_fn;
      } data;
- };
+ } BlizzardState;
  
  /* Bytes(!) per pixel */
  static const int blizzard_iformat_bpp[0x10] = {
@@@ -985,16 -942,23 +985,16 @@@ static void blizzard_screen_dump(void *
          ppm_save(filename, s->state->surface);
  }
  
 -#define DEPTH 8
 -#include "blizzard_template.h"
 -#define DEPTH 15
 -#include "blizzard_template.h"
 -#define DEPTH 16
 -#include "blizzard_template.h"
 -#define DEPTH 24
 -#include "blizzard_template.h"
 -#define DEPTH 32
 -#include "blizzard_template.h"
 -
  void *s1d13745_init(qemu_irq gpio_int)
  {
-     struct blizzard_s *s = (struct blizzard_s *) qemu_mallocz(sizeof(*s));
+     BlizzardState *s = (BlizzardState *) qemu_mallocz(sizeof(*s));
  
      s->fb = qemu_malloc(0x180000);
 -
 +    /* Fill the framebuffer with white color here because the corresponding
 +     * code in nseries.c is broken since the DisplayState change in QEMU.
 +     * This is supposedly ok since nseries.c is the only user of blizzard.c */
 +    memset(s->fb, 0xff, 0x180000);
 +    
      s->state = graphic_console_init(blizzard_update_display,
                                   blizzard_invalidate_display,
                                   blizzard_screen_dump, NULL, s);
diff --cc hw/devices.h
@@@ -4,30 -4,16 +4,18 @@@
  /* Devices that have nowhere better to go.  */
  
  /* smc91c111.c */
- void *smc91c111_init(NICInfo *, uint32_t, qemu_irq, int phys_alloc);
 -void smc91c111_init(NICInfo *, uint32_t, qemu_irq);
++void smc91c111_init(NICInfo *nd, uint32_t base, qemu_irq irq);
++void *smc91c111_init_lite(NICInfo *nd, qemu_irq irq);
 +int smc91c111_iomemtype(void *opaque);
  
- /* ssd0323.c */
- int ssd0323_xfer_ssi(void *opaque, int data);
- void *ssd0323_init(qemu_irq *cmd_p);
- /* ads7846.c */
- struct ads7846_state_s;
- uint32_t ads7846_read(void *opaque);
- void ads7846_write(void *opaque, uint32_t value);
- struct ads7846_state_s *ads7846_init(qemu_irq penirq);
  /* tsc210x.c */
- struct uwire_slave_s;
- struct mouse_transform_info_s;
- struct uwire_slave_s *tsc2102_init(qemu_irq pint, AudioState *audio);
- struct uwire_slave_s *tsc2301_init(qemu_irq penirq, qemu_irq kbirq,
-                 qemu_irq dav, AudioState *audio);
- struct i2s_codec_s *tsc210x_codec(struct uwire_slave_s *chip);
+ uWireSlave *tsc2102_init(qemu_irq pint);
+ uWireSlave *tsc2301_init(qemu_irq penirq, qemu_irq kbirq, qemu_irq dav);
+ I2SCodec *tsc210x_codec(uWireSlave *chip);
  uint32_t tsc210x_txrx(void *opaque, uint32_t value, int len);
- void tsc210x_set_transform(struct uwire_slave_s *chip,
-                 struct mouse_transform_info_s *info);
- void tsc210x_key_event(struct uwire_slave_s *chip, int key, int down);
+ void tsc210x_set_transform(uWireSlave *chip,
+                 MouseTransformInfo *info);
+ void tsc210x_key_event(uWireSlave *chip, int key, int down);
  
  /* tsc2005.c */
  void *tsc2005_init(qemu_irq pintdav);
diff --cc hw/flash.h
@@@ -17,15 -17,14 +17,15 @@@ pflash_t *pflash_cfi02_register(target_
                                  uint16_t unlock_addr0, uint16_t unlock_addr1);
  
  /* nand.c */
- struct nand_flash_s;
- struct nand_flash_s *nand_init(int manf_id, int chip_id);
- void nand_done(struct nand_flash_s *s);
- void nand_setpins(struct nand_flash_s *s,
+ typedef struct NANDFlashState NANDFlashState;
+ NANDFlashState *nand_init(int manf_id, int chip_id);
+ void nand_done(NANDFlashState *s);
+ void nand_setpins(NANDFlashState *s,
                  int cle, int ale, int ce, int wp, int gnd);
- void nand_getpins(struct nand_flash_s *s, int *rb);
- void nand_setio(struct nand_flash_s *s, uint32_t value);
- uint32_t nand_getio(struct nand_flash_s *s);
- uint32_t nand_getbuswidth(struct nand_flash_s *s);
+ void nand_getpins(NANDFlashState *s, int *rb);
 -void nand_setio(NANDFlashState *s, uint8_t value);
 -uint8_t nand_getio(NANDFlashState *s);
++void nand_setio(NANDFlashState *s, uint32_t value);
++uint32_t nand_getio(NANDFlashState *s);
++uint32_t nand_getbuswidth(NANDFlashState *s);
  
  #define NAND_MFR_TOSHIBA      0x98
  #define NAND_MFR_SAMSUNG      0xec
diff --cc hw/i2c.h
+++ b/hw/i2c.h
@@@ -82,13 -79,6 +79,9 @@@ void wm8750_set_bclk_in(void *opaque, i
  void tmp105_set(i2c_slave *i2c, int temp);
  
  /* lm832x.c */
- struct i2c_slave *lm8323_init(i2c_bus *bus, qemu_irq nirq);
- void lm832x_key_event(struct i2c_slave *i2c, int key, int state);
+ void lm832x_key_event(i2c_slave *i2c, int key, int state);
  
 +/* twl4030.c */
- struct twl4030_s;
- struct twl4030_s *twl4030_init(i2c_bus *bus, qemu_irq irq);
++void *twl4030_init(i2c_bus *gp_bus, qemu_irq irq);
 +
  #endif
diff --cc hw/nand.c
+++ b/hw/nand.c
@@@ -52,9 -45,8 +52,9 @@@
  # define MAX_PAGE             0x800
  # define MAX_OOB              0x40
  
- struct nand_flash_s {
+ struct NANDFlashState {
      uint8_t manf_id, chip_id;
 +    uint8_t buswidth; /* in BYTES */
      int size, pages;
      int page_shift, oob_shift, erase_shift, addr_shift;
      uint8_t *storage;
@@@ -73,9 -64,9 +73,9 @@@
      int status;
      int offset;
  
-     void (*blk_write)(struct nand_flash_s *s);
-     void (*blk_erase)(struct nand_flash_s *s);
-     void (*blk_load)(struct nand_flash_s *s, uint64_t addr, int offset);
+     void (*blk_write)(NANDFlashState *s);
+     void (*blk_erase)(NANDFlashState *s);
 -    void (*blk_load)(NANDFlashState *s, uint32_t addr, int offset);
++    void (*blk_load)(NANDFlashState *s, uint64_t addr, int offset);
  };
  
  # define NAND_NO_AUTOINCR     0x00000001
@@@ -217,17 -208,9 +217,17 @@@ static void nand_reset(NANDFlashState *
      s->iolen = 0;
      s->offset = 0;
      s->status &= NAND_IOSTATUS_UNPROTCT;
 +    s->status |= NAND_IOSTATUS_READY;
 +}
 +
- static inline void nand_pushio_byte(struct nand_flash_s *s, uint8_t value)
++static inline void nand_pushio_byte(NANDFlashState *s, uint8_t value)
 +{
 +    s->ioaddr[s->iolen++] = value;
 +    for (value = s->buswidth; --value;)
 +        s->ioaddr[s->iolen++] = 0;
  }
  
- static void nand_command(struct nand_flash_s *s)
+ static void nand_command(NANDFlashState *s)
  {
      switch (s->cmd) {
      case NAND_CMD_READ0:
@@@ -362,16 -344,11 +362,16 @@@ void nand_getpins(NANDFlashState *s, in
      *rb = 1;
  }
  
- void nand_setio(struct nand_flash_s *s, uint32_t value)
 -void nand_setio(NANDFlashState *s, uint8_t value)
++void nand_setio(NANDFlashState *s, uint32_t value)
  {
 +    int i;
 +    
      if (!s->ce && s->cle) {
          if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) {
 -            if (s->cmd == NAND_CMD_READ0 && value == NAND_CMD_LPREAD2)
 +            if (s->cmd == NAND_CMD_READ0 
 +                && (value == NAND_CMD_LPREAD2
 +                    || value == NAND_CMD_READCACHESTART
 +                    || value == NAND_CMD_READCACHELAST))
                  return;
              if (value == NAND_CMD_RANDOMREAD1) {
                  s->addr &= ~((1 << s->addr_shift) - 1);
      }
  }
  
- uint32_t nand_getio(struct nand_flash_s *s)
 -uint8_t nand_getio(NANDFlashState *s)
++uint32_t nand_getio(NANDFlashState *s)
  {
      int offset;
 +    uint32_t x = 0;
  
      /* Allow sequential reading */
      if (!s->iolen && s->cmd == NAND_CMD_READ0) {
      if (s->ce || s->iolen <= 0)
          return 0;
  
 -    s->iolen --;
 -    return *(s->ioaddr ++);
 +    for (offset = s->buswidth; offset--;)
 +        x |= s->ioaddr[offset] << (offset << 3);
 +    /* after receiving READ STATUS command all subsequent reads will
 +       return the status register value until another command is issued */
 +    if (s->cmd != NAND_CMD_READSTATUS) {
 +        s->ioaddr += s->buswidth;
 +        s->iolen  -= s->buswidth;
 +    }
 +    return x;
 +}
 +
- uint32_t nand_getbuswidth(struct nand_flash_s *s)
++uint32_t nand_getbuswidth(NANDFlashState *s)
 +{
 +    if (!s)
 +        return 0;
 +    return (s->buswidth << 3);
  }
  
- struct nand_flash_s *nand_init(int manf_id, int chip_id)
+ NANDFlashState *nand_init(int manf_id, int chip_id)
  {
      int pagesize;
-     struct nand_flash_s *s;
+     NANDFlashState *s;
      int index;
  
      if (nand_flash_ids[chip_id].size == 0) {
@@@ -576,9 -515,9 +574,9 @@@ void nand_done(NANDFlashState *s
  #else
  
  /* Program a single page */
- static void glue(nand_blk_write_, PAGE_SIZE)(struct nand_flash_s *s)
+ static void glue(nand_blk_write_, PAGE_SIZE)(NANDFlashState *s)
  {
 -    uint32_t off, page, sector, soff;
 +    uint64_t off, page, sector, soff;
      uint8_t iobuf[(PAGE_SECTORS + 2) * 0x200];
      if (PAGE(s->addr) >= s->pages)
          return;
  }
  
  /* Erase a single block */
- static void glue(nand_blk_erase_, PAGE_SIZE)(struct nand_flash_s *s)
+ static void glue(nand_blk_erase_, PAGE_SIZE)(NANDFlashState *s)
  {
 -    uint32_t i, page, addr;
 +    uint64_t i, page, addr;
      uint8_t iobuf[0x200] = { [0 ... 0x1ff] = 0xff, };
      addr = s->addr & ~((1 << (ADDR_SHIFT + s->erase_shift)) - 1);
  
      }
  }
  
- static void glue(nand_blk_load_, PAGE_SIZE)(struct nand_flash_s *s,
+ static void glue(nand_blk_load_, PAGE_SIZE)(NANDFlashState *s,
 -                uint32_t addr, int offset)
 +                uint64_t addr, int offset)
  {
      if (PAGE(addr) >= s->pages)
          return;
diff --cc hw/nseries.c
Simple merge
diff --cc hw/omap.h
+++ b/hw/omap.h
@@@ -893,8 -690,15 +893,8 @@@ struct omap_uwire_s
  struct omap_uwire_s *omap_uwire_init(target_phys_addr_t base,
                  qemu_irq *irq, qemu_irq dma, omap_clk clk);
  void omap_uwire_attach(struct omap_uwire_s *s,
-                 struct uwire_slave_s *slave, int chipselect);
+                 uWireSlave *slave, int chipselect);
  
 -struct omap_mcspi_s;
 -struct omap_mcspi_s *omap_mcspi_init(struct omap_target_agent_s *ta, int chnum,
 -                qemu_irq irq, qemu_irq *drq, omap_clk fclk, omap_clk iclk);
 -void omap_mcspi_attach(struct omap_mcspi_s *s,
 -                uint32_t (*txrx)(void *opaque, uint32_t, int), void *opaque,
 -                int chipselect);
 -
  struct omap_rtc_s;
  struct omap_rtc_s *omap_rtc_init(target_phys_addr_t base,
                  qemu_irq *irq, omap_clk clk);
diff --cc hw/omap1.c
Simple merge
diff --cc hw/omap2.c
@@@ -2565,10 -2638,8 +2563,10 @@@ static uint32_t omap_tap_read(void *opa
              return 0x5b68a02f;        /* ES 2.2 */
          case omap3430:
              return 0x1b7ae02f;        /* ES 2 */
 +        case omap3530:
 +            return 0x3b7ae02f;  /* ES 3.0 */
          default:
-             cpu_abort(cpu_single_env, "%s: Bad mpu model\n", __FUNCTION__);
+             hw_error("%s: Bad mpu model\n", __FUNCTION__);
          }
  
      case 0x208:       /* PRODUCTION_ID_reg for OMAP2 */
              return 0x000000f0;
          case omap3430:
              return 0x000000f0;
 +        case omap3530:
 +            return 0x000f00f0;
          default:
-             cpu_abort(cpu_single_env, "%s: Bad mpu model\n", __FUNCTION__);
+             hw_error("%s: Bad mpu model\n", __FUNCTION__);
          }
  
      case 0x20c:
          case omap2430:
              return 0xcafeb68a;        /* ES 2.2 */
          case omap3430:
 +        case omap3530:
              return 0xcafeb7ae;        /* ES 2 */
          default:
-             cpu_abort(cpu_single_env, "%s: Bad mpu model\n", __FUNCTION__);
+             hw_error("%s: Bad mpu model\n", __FUNCTION__);
          }
  
      case 0x218:       /* DIE_ID_reg */
diff --cc hw/omap3_mmc.c
index 402db19,0000000..7897424
mode 100644,000000..100644
--- /dev/null
@@@ -1,793 -1,0 +1,793 @@@
 +/*
 + * OMAP3 Multimedia Card/Secure Digital/Secure Digital I/O (MMC/SD/SDIO) Card Interface emulation
 + *
 + * Copyright (C) 2008 yajin  <yajin@vm-kernel.org>
 + * Copyright (C) 2009 Nokia Corporation
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License as
 + * published by the Free Software Foundation; either version 2 or
 + * (at your option) version 3 of the License.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 + * MA 02111-1307 USA
 + */
 +#include "hw.h"
 +#include "omap.h"
 +#include "sd.h"
 +
 +/* debug levels:
 +   0 - no debug
 +   1 - print out all commands in processing order
 +   2 - dump all register accesses and buffer management */
 +#define MMC_DEBUG_LEVEL 0
 +
 +#if MMC_DEBUG_LEVEL>0
 +#define TRACE(fmt,...) fprintf(stderr, "%s: " fmt "\n", __FUNCTION__, ##__VA_ARGS__)
 +#if MMC_DEBUG_LEVEL>1
 +#define TRACE2(...) TRACE(__VA_ARGS__)
 +#else
 +#define TRACE2(...)
 +#endif
 +#else
 +#define TRACE(...)
 +#define TRACE2(...)
 +#endif
 +
 +struct omap3_mmc_s
 +{
 +    qemu_irq irq;
 +    qemu_irq *dma;
 +    qemu_irq coverswitch;
 +    omap_clk clk;
 +    SDState *card;
 +
 +    uint32_t sysconfig;
 +    uint32_t sysstatus;
 +    uint32_t csre;
 +    uint32_t systest;
 +    uint32_t con;
 +    uint32_t pwcnt;
 +    uint32_t blk;
 +    uint32_t arg;
 +    uint32_t cmd;
 +    uint32_t rsp10;
 +    uint32_t rsp32;
 +    uint32_t rsp54;
 +    uint32_t rsp76;
 +    uint32_t data;
 +    uint32_t pstate;
 +    uint32_t hctl;
 +    uint32_t sysctl;
 +    uint32_t stat;
 +    uint32_t ie;
 +    uint32_t ise;
 +    uint32_t ac12;
 +    uint32_t capa;
 +    uint32_t cur_capa;
 +    uint32_t rev;
 +
 +    uint16_t blen_counter;
 +    uint16_t nblk_counter;
 +
 +    uint32_t fifo[256];
 +    int fifo_start;
 +    int fifo_len;
 +
 +    int ddir;
 +    int transfer;
 +    int stop;
 +    
 +    uint32_t stat_pending;
 +};
 +
 +
 +typedef enum
 +{
 +    sd_nore = 0,     /* no response */
 +    sd_136_bits = 1, /* response length 136 bits */
 +    sd_48_bits = 2,  /* response length 48 bits */
 +    sd_48b_bits = 3, /* response length 48 bits with busy after response */
 +} omap3_sd_rsp_type_t;
 +
 +static void omap3_mmc_command(struct omap3_mmc_s *host);
 +
 +static void omap3_mmc_interrupts_update(struct omap3_mmc_s *s)
 +{
 +    qemu_set_irq(s->irq, !!((s->stat | s->stat_pending) & s->ie & s->ise));
 +}
 +
 +static void omap3_mmc_fifolevel_update(struct omap3_mmc_s *host)
 +{
 +    enum { ongoing, ready, aborted } state = ongoing;
 +    
 +    if ((host->cmd & (1 << 21))) { /* DP */
 +        if (host->ddir) {
 +            TRACE2("receive, dma=%d, fifo_len=%d bytes",
 +                   host->cmd & 1, host->fifo_len * 4);
 +            
 +            /* omap3_mmc_transfer ensures we always have data in FIFO
 +               during receive as long as all data has not been transferred -
 +               NOTE that the actual transfer may be finished already (i.e.
 +               host->transfer is cleared) but not all data has been read out
 +               from FIFO yet */
 +            if (host->fifo_len) {
 +                if (host->cmd & 1) { /* DE */
 +                    if (host->fifo_len * 4 == (host->blk & 0x7ff)) { /* BLEN */
 +                        if (host->stop)
 +                            state = aborted;
 +                        else
 +                            qemu_irq_raise(host->dma[1]);
 +                    } else
 +                        qemu_irq_lower(host->dma[1]);
 +                } else {
 +                    if (host->stop 
 +                        && host->fifo_len * 4 == (host->blk & 0x7ff))
 +                        state = aborted;
 +                    else {
 +                        host->pstate |= 0x0800;      /* BRE */
 +                        host->stat_pending |= 0x20;  /* BRR */
 +                    }
 +                }
 +            }
 +            else
 +                state = host->stop ? aborted : ready;
 +        } else {
 +            /* omap3_mmc_transfer keeps FIFO empty during transmit so
 +               we just check all blocks have been transferred or not */
 +            if (host->transfer) {
 +                if (host->cmd & 1) { /* DE */
 +                    if (host->blen_counter == (host->blk & 0x7ff)) { /* BLEN */
 +                        if (host->stop)
 +                            state = aborted;
 +                        else
 +                            qemu_irq_raise(host->dma[0]);
 +                    } else
 +                        qemu_irq_lower(host->dma[0]);
 +                } else {
 +                    if (host->stop
 +                        && host->blen_counter == (host->blk & 0x7ff))
 +                        state = aborted;
 +                    else {
 +                        host->pstate |= 0x0400;      /* BWE */
 +                        host->stat_pending |= 0x10;  /* BWR */
 +                    }
 +                }
 +            } else
 +                state = host->stop ? aborted : ready;
 +        }
 +
 +        if ((host->cmd & 1) || state != ongoing) { /* DE */
 +            host->pstate &= ~0x0c00;               /* BRE | BWE */
 +            host->stat_pending &= ~0x30;           /* BRR | BWR */
 +            host->stat &= ~0x30;                   /* BRR | BWR */
 +            if (state != ongoing) {
 +                TRACE2("transfer %s", 
 +                       state == ready
 +                       ? "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;
 +                    omap3_mmc_command(host);
 +                }
 +            }
 +        }
 +    }
 +}
 +
 +static void omap3_mmc_transfer(struct omap3_mmc_s *host)
 +{
 +    int i;
 +    uint32_t x;
 +#if MMC_DEBUG_LEVEL>1
 +    int j;
 +    uint8_t c, sym[17];
 +#endif
 +
 +    /* IF data transfer is inactive
 +       OR block count enabled with zero block count
 +       OR in receive mode and we have unread data in FIFO
 +       OR in transmit mode and we have no data in FIFO,
 +       THEN don't do anything */
 +    if (!host->transfer
 +        || ((host->cmd & 2) && !host->nblk_counter)
 +        || (host->ddir && host->fifo_len)
 +        || (!host->ddir && !host->fifo_len))
 +        return;
 +    
 +    if (host->ddir) {
 +        TRACE2("begin, %d blocks (%d bytes/block) left to receive, %d bytes in FIFO",
 +               (host->cmd & 2) ? host->nblk_counter : 1,
 +               host->blk & 0x7ff, 
 +               host->fifo_len * 4);
 +        while (host->blen_counter && host->fifo_len < 255) {
 +            for (i = 0, x = 0; i < 32 && host->blen_counter; i += 8, host->blen_counter--)
 +                x |= sd_read_data(host->card) << i;
 +            host->fifo[(host->fifo_start + host->fifo_len) & 0xff] = x;
 +            host->fifo_len++;
 +        }
 +        TRACE2("end, %d bytes in FIFO:", host->fifo_len * 4);
 +#if MMC_DEBUG_LEVEL>1
 +        for (i = 0; i < host->fifo_len; ) {
 +            fprintf(stderr, "%s: [0x%03x] ", __FUNCTION__, i * 4);
 +            do {
 +                x = host->fifo[(host->fifo_start + i) & 0xff];
 +                for (j = 0; j < 4; j++) {
 +                    c = (x >> (j * 8)) & 0xff;
 +                    fprintf(stderr, "%02x ", c);
 +                    sym[(i & 3) * 4 + j] = (c < 32 || c > 126) ? '.' : c;
 +                }
 +            } while (((++i) & 3));
 +            sym[16] = 0;
 +            fprintf(stderr, "%s\n", sym);
 +        }
 +#endif
 +    } else {
 +        TRACE2("%d bytes left to transmit in current block", host->blen_counter);
 +        while (host->blen_counter && host->fifo_len) {
 +            for (i = 0; i < 32 && host->blen_counter; i += 8, host->blen_counter--)
 +                sd_write_data(host->card, (host->fifo[host->fifo_start] >> i) & 0xff);
 +            host->fifo_start++;
 +            host->fifo_len--;
 +            host->fifo_start &= 0xff;
 +        }
 +    }
 +
 +    if (!host->blen_counter) {
 +        if (host->cmd & 2) /* BCE */
 +            host->nblk_counter--;
 +        TRACE2("block done, %d blocks left",
 +               (host->cmd & (1 << 5)) ? host->nblk_counter : 0);
 +        host->blen_counter = host->blk & 0x7ff;
 +        if (!(host->cmd & (1 << 5)) /* MSBS */
 +            || !host->nblk_counter) {
 +            host->nblk_counter = (host->blk >> 16) & 0xffff;
 +            host->transfer = 0;
 +            host->pstate &= ~0x0306; /* RTA | WTA | DLA | DATI */
 +        }
 +    }
 +}
 +
 +static void omap3_mmc_command(struct omap3_mmc_s *host)
 +{
 +    uint32_t rspstatus, mask;
 +    int rsplen, timeout;
-     struct sd_request_s request;
++    SDRequest request;
 +    uint8_t response[16];
 +    int cmd = (host->cmd >> 24) & 0x3f; /* INDX */
 +    
 +    TRACE("%d type=%d arg=0x%08x blk=0x%08x, fifo=%d/%d",
 +          cmd, (host->cmd >> 22) & 3, host->arg, host->blk,
 +          host->fifo_start, host->fifo_len);
 +
 +    if ((host->con & 2) && !cmd) { /* INIT and CMD0 */
 +        host->stat_pending |= 0x1;
 +        host->pstate &= 0xfffffffe;
 +        return;
 +    }
 +    
 +    if (host->cmd & (1 << 21)) { /* DP */
 +        host->fifo_start = 0;
 +        host->fifo_len = 0;
 +        host->transfer = 1;
 +        host->ddir = (host->cmd >> 4) & 1;
 +        /* DLA | DATI | (RTA/WTA) */
 +        host->pstate |= 0x6 | (host->ddir ? 0x200 : 0x100);
 +    } else {
 +        host->transfer = 0;
 +        host->pstate &= ~0x306; /* RTA | WTA | DLA | DATI */
 +    }
 +    
 +    timeout = 0;
 +    mask = 0;
 +    rspstatus = 0;
 +    
 +    request.cmd = cmd;
 +    request.arg = host->arg;
 +    request.crc = 0; /* FIXME */
 +    
 +    rsplen = sd_do_command(host->card, &request, response);
 +    
 +    switch ((host->cmd >> 16) & 3) { /* RSP_TYPE */
 +        case sd_nore:
 +            rsplen = 0;
 +            break;
 +        case sd_136_bits:
 +            if (rsplen < 16) {
 +                timeout = 1;
 +                break;
 +            }
 +            rsplen = 16;
 +            host->rsp76 = (response[0] << 24) | (response[1] << 16) |
 +            (response[2] << 8) | (response[3] << 0);
 +            host->rsp54 = (response[4] << 24) | (response[5] << 16) |
 +            (response[6] << 8) | (response[7] << 0);
 +            host->rsp32 = (response[8] << 24) | (response[9] << 16) |
 +            (response[10] << 8) | (response[11] << 0);
 +            host->rsp10 = (response[12] << 24) | (response[13] << 16) |
 +            (response[14] << 8) | (response[15] << 0);
 +            break;
 +            case sd_48_bits:
 +            case sd_48b_bits:
 +            if (rsplen < 4) {
 +                timeout = 1;
 +                break;
 +            }
 +            rsplen = 4;
 +            host->rsp10 = (response[0] << 24) | (response[1] << 16) |
 +            (response[2] << 8) | (response[3] << 0);
 +            switch (cmd) {
 +                case 41: /* r3 */
 +                case 8:  /* r7 */
 +                    break;
 +                case 3:  /* r6 */
 +                    mask = 0xe00;
 +                    rspstatus = (response[2] << 8) | response[3];
 +                    break;
 +                default:
 +                    mask = OUT_OF_RANGE | ADDRESS_ERROR | BLOCK_LEN_ERROR |
 +                    ERASE_SEQ_ERROR | ERASE_PARAM | WP_VIOLATION |
 +                    LOCK_UNLOCK_FAILED | COM_CRC_ERROR | ILLEGAL_COMMAND |
 +                    CARD_ECC_FAILED | CC_ERROR | SD_ERROR |
 +                    CID_CSD_OVERWRITE | WP_ERASE_SKIP;
 +                    rspstatus = (response[0] << 24) | (response[1] << 16) |
 +                    (response[2] << 8) | (response[3] << 0);
 +                    break;
 +            }
 +            default:
 +            break;
 +    }
 +    
 +    if (cmd == 12 || cmd == 52) { /* stop transfer commands */
 +        /*host->fifo_start = 0;*/
 +        /*host->fifo_len = 0;*/
 +        host->transfer = 0;
 +        host->pstate &= ~0x0f06;     /* BRE | BWE | RTA | WTA | DLA | DATI */
 +        host->stat_pending &= ~0x30; /* BRR | BWR */
 +        host->stat &= ~0x30;         /* BRR | BWR */
 +        host->stat_pending |= 0x2;   /* TC */
 +        qemu_irq_lower(host->dma[0]);
 +        qemu_irq_lower(host->dma[1]);
 +    }
 +    
 +    if (rspstatus & mask & host->csre) {
 +        host->stat_pending |= 1 << 28;    /* CERR */
 +        host->pstate &= ~0x306;           /* RTA | WTA | DLA | DATI */
 +        host->transfer = 0;
 +    } else {
 +        host->stat &= ~(1 << 28);         /* CERR */
 +        host->stat_pending &= ~(1 << 28); /* CERR */
 +    }
 +    host->stat_pending |= timeout ? (1 << 16) : 0x1; /* CTO : CC */
 +}
 +
 +static void omap3_mmc_reset(struct omap3_mmc_s *s)
 +{
 +    s->sysconfig = 0x00000015;
 +    s->con       = 0x00000500;
 +    s->pstate    = 0x00040000;
 +    s->capa      = 0x00e10080;
 +    s->rev       = 0x26000000;
 +
 +    s->fifo_start = 0;
 +    s->fifo_len   = 0;
 +    s->stop       = 0;
 +}
 +
 +static uint32_t omap3_mmc_read(void *opaque, target_phys_addr_t addr)
 +{
 +    struct omap3_mmc_s *s = (struct omap3_mmc_s *) opaque;
 +    uint32_t i ;
 +
 +    switch (addr) {
 +        case 0x10:
 +            TRACE2("SYSCONFIG = %08x", s->sysconfig);
 +            return s->sysconfig;
 +        case 0x14:
 +            TRACE2("SYSSTATUS = %08x", s->sysstatus | 0x1);
 +            return s->sysstatus | 0x1; /*reset completed */
 +        case 0x24:
 +            TRACE2("CSRE = %08x", s->csre);
 +            return s->csre;
 +        case 0x28:
 +            TRACE2("SYSTEST = %08x", s->systest);
 +            return s->systest;
 +        case 0x2c: /* MMCHS_CON */
 +            TRACE2("CON = %08x", s->con);
 +            return s->con;
 +        case 0x30:
 +            TRACE2("PWCNT = %08x", s->pwcnt);
 +            return s->pwcnt;
 +        case 0x104: /* MMCHS_BLK */
 +            TRACE2("BLK = %08x", s->blk);
 +            return s->blk;
 +        case 0x108: /* MMCHS_ARG */
 +            TRACE2("ARG = %08x", s->arg);
 +            return s->arg;
 +        case 0x10c:
 +            TRACE2("CMD = %08x", s->cmd);
 +            return s->cmd;
 +        case 0x110:
 +            TRACE2("RSP10 = %08x", s->rsp10);
 +            return s->rsp10;
 +        case 0x114:
 +            TRACE2("RSP32 = %08x", s->rsp32);
 +            return s->rsp32;
 +        case 0x118:
 +            TRACE2("RSP54 = %08x", s->rsp54);
 +            return s->rsp54;
 +        case 0x11c:
 +            TRACE2("RSP76 = %08x", s->rsp76);
 +            return s->rsp76;
 +        case 0x120:
 +            /* in PIO mode, access allowed only when BRE is set */
 +            if (!(s->cmd & 1) && !(s->pstate & 0x0800)) {
 +                s->stat_pending |= 1 << 29; /* BADA */
 +                i = 0;
 +            } else {
 +                i = s->fifo[s->fifo_start];
 +                s->fifo[s->fifo_start] = 0;
 +                if (s->fifo_len == 0) {
 +                    fprintf(stderr, "%s: FIFO underrun\n", __FUNCTION__);
 +                    return i;
 +                }
 +                s->fifo_start++;
 +                s->fifo_len--;
 +                s->fifo_start &= 255;
 +                omap3_mmc_transfer(s);
 +                omap3_mmc_fifolevel_update(s);
 +            }
 +            omap3_mmc_interrupts_update(s);
 +            return i;
 +        case 0x124: /* MMCHS_PSTATE */
 +            TRACE2("PSTATE = %08x", s->pstate);
 +            return s->pstate;
 +        case 0x128:
 +            TRACE2("HCTL = %08x", s->hctl);
 +            return s->hctl;
 +        case 0x12c: /* MMCHS_SYSCTL */
 +            TRACE2("SYSCTL = %08x", s->sysctl);
 +            return s->sysctl;
 +        case 0x130: /* MMCHS_STAT */
 +            s->stat |= s->stat_pending;
 +            if (s->stat & 0xffff0000)
 +                   s->stat |= 1 << 15;    /* ERRI */
 +            else
 +                   s->stat &= ~(1 << 15); /* ERRI */
 +            s->stat_pending = 0;
 +            TRACE2("STAT = %08x", s->stat);
 +            return s->stat;
 +        case 0x134:
 +            TRACE2("IE = %08x", s->ie);
 +            return s->ie;
 +        case 0x138:
 +            TRACE2("ISE = %08x", s->ise);
 +            return s->ise;
 +        case 0x13c:
 +            TRACE2("AC12 = %08x", s->ac12);
 +            return s->ac12;
 +        case 0x140: /* MMCHS_CAPA */
 +            TRACE2("CAPA = %08x", s->capa);
 +            return s->capa;
 +        case 0x148:
 +            TRACE2("CUR_CAPA = %08x", s->cur_capa);
 +            return s->cur_capa;
 +        case 0x1fc:
 +            TRACE2("REV = %08x", s->rev);
 +            return s->rev;
 +        default:
 +            OMAP_BAD_REG(addr);
 +            exit(-1);
 +            return 0;
 +    }
 +}
 +
 +static void omap3_mmc_write(void *opaque, target_phys_addr_t addr,
 +                            uint32_t value)
 +{
 +    struct omap3_mmc_s *s = (struct omap3_mmc_s *) opaque;
 +    
 +    switch (addr) {
 +        case 0x014:
 +        case 0x110:
 +        case 0x114:
 +        case 0x118:
 +        case 0x11c:
 +        case 0x124:
 +        case 0x13c:
 +        case 0x1fc:
 +            OMAP_RO_REG(addr);
 +            break;
 +        case 0x010:
 +            TRACE2("SYSCONFIG = %08x", value);
 +            if (value & 2)
 +                omap3_mmc_reset(s);
 +            s->sysconfig = value & 0x31d;
 +            break;
 +        case 0x024:
 +            TRACE2("CSRE = %08x", value);
 +            s->csre = value;
 +            break;
 +        case 0x028:
 +            TRACE2("SYSTEST = %08x", value);
 +            s->systest = value;
 +            break;
 +        case 0x02c: /* MMCHS_CON */
 +            TRACE2("CON = %08x", value);
 +            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:
 +            TRACE2("PWCNT = %08x", value);
 +            s->pwcnt = value;
 +            break;
 +        case 0x104: /* MMCHS_BLK */
 +            TRACE2("BLK = %08x", value);
 +            s->blk = value & 0xffff07ff;
 +            s->blen_counter = value & 0x7ff;
 +            s->nblk_counter = (value >> 16) & 0xffff;
 +            break;
 +        case 0x108: /* MMCHS_ARG */
 +            TRACE2("ARG = %08x", value);
 +            s->arg = value;
 +            break;
 +        case 0x10c: /* MMCHS_CMD */
 +            TRACE2("CMD = %08x", value);
 +            if (!s->card) {
 +                s->stat_pending |= (1 << 16); /* CTO */
 +            } else {
 +                /* 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_interrupts_update(s);
 +            break;
 +        case 0x120:
 +            /* in PIO mode, access allowed only when BWE is set */
 +            if (!(s->cmd & 1) && !(s->pstate & 0x0400)) {
 +                s->stat_pending |= 1 << 29; /* BADA */
 +            } else {
 +                if (s->fifo_len == 256) {
 +                    fprintf(stderr, "%s: FIFO overrun\n", __FUNCTION__);
 +                    break;
 +                }
 +                s->fifo[(s->fifo_start + s->fifo_len) & 255] = value;
 +                s->fifo_len++;
 +                omap3_mmc_transfer(s);
 +                omap3_mmc_fifolevel_update(s);
 +            }
 +            omap3_mmc_interrupts_update(s);
 +            break;
 +        case 0x128: /* MMCHS_HCTL */
 +            TRACE2("HCTL = %08x", value);
 +            s->hctl = value & 0xf0f0f02;
 +            if (s->hctl & (1 << 16)) /* SBGR */
 +                fprintf(stderr, "%s: Stop at block gap feature not implemented!\n", __FUNCTION__);
 +            break;
 +        case 0x12c: /* MMCHS_SYSCTL */
 +            TRACE2("SYSCTL = %08x", value);
 +            if (value & 0x04000000) { /* SRD */
 +                s->data    = 0;
 +                s->pstate &= ~0x00000f06; /* BRE, BWE, RTA, WTA, DLA, DATI */
 +                s->hctl   &= ~0x00030000; /* SGBR, CR */
 +                s->stat   &= ~0x00000034; /* BRR, BWR, BGE */
 +                s->stat_pending &= ~0x00000034;
 +                s->fifo_start = 0;
 +                s->fifo_len = 0;
 +            }
 +            if (value & 0x02000000) { /* SRC */
 +                s->pstate &= ~0x00000001; /* CMDI */
 +            }
 +            if (value & 0x01000000) { /* SRA */
 +                uint32_t capa = s->capa;
 +                uint32_t cur_capa = s->cur_capa;
 +                omap3_mmc_reset(s);
 +                s->capa = capa;
 +                s->cur_capa = cur_capa;
 +            }
 +            value = (value & ~2) | ((value & 1) << 1); /* copy ICE directly to ICS */
 +            s->sysctl = value & 0x000fffc7;
 +            break;
 +        case 0x130:
 +            TRACE2("STAT = %08x", value);
 +            value = value & 0x317f0237;
 +            s->stat &= ~value;
 +            /* stat_pending is NOT cleared */
 +            omap3_mmc_interrupts_update(s);
 +            break;
 +        case 0x134: /* MMCHS_IE */
 +            TRACE2("IE = %08x", value);
 +            if (!(s->con & 0x4000)) /* if CON:OBIE is clear, ignore write to OBI_ENABLE */
 +                value = (value & ~0x200) | (s->ie & 0x200);
 +            s->ie = value & 0x317f0337;
 +            if (!(s->ie & 0x100)) {
 +                s->stat &= ~0x100;
 +                s->stat_pending &= ~0x100;
 +            }
 +            omap3_mmc_interrupts_update(s);
 +            break;
 +        case 0x138:
 +            TRACE2("ISE = %08x", value);
 +            s->ise = value & 0x317f0337;
 +            omap3_mmc_interrupts_update(s);
 +            break;
 +        case 0x140: /* MMCHS_CAPA */
 +            TRACE2("CAPA = %08x", value);
 +            s->capa &= ~0x07000000;
 +            s->capa |= value & 0x07000000;
 +            break;
 +        case 0x148:
 +            TRACE2("CUR_CAPA = %08x", value);
 +            s->cur_capa = value & 0xffffff;
 +            break;
 +        default:
 +            OMAP_BAD_REG(addr);
 +            exit(-1);
 +    }
 +}
 +
 +static CPUReadMemoryFunc *omap3_mmc_readfn[] = {
 +    omap_badwidth_read32,
 +    omap_badwidth_read32,
 +    omap3_mmc_read,
 +};
 +
 +static CPUWriteMemoryFunc *omap3_mmc_writefn[] = {
 +    omap_badwidth_write32,
 +    omap_badwidth_write32,
 +    omap3_mmc_write,
 +};
 +
 +static void omap3_mmc_save_state(QEMUFile *f, void *opaque)
 +{
 +    struct omap3_mmc_s *s = (struct omap3_mmc_s *)opaque;
 +    int i;
 +    
 +    qemu_put_be32(f, s->sysconfig);
 +    qemu_put_be32(f, s->sysstatus);
 +    qemu_put_be32(f, s->csre);
 +    qemu_put_be32(f, s->systest);
 +    qemu_put_be32(f, s->con);
 +    qemu_put_be32(f, s->pwcnt);
 +    qemu_put_be32(f, s->blk);
 +    qemu_put_be32(f, s->arg);
 +    qemu_put_be32(f, s->cmd);
 +    qemu_put_be32(f, s->rsp10);
 +    qemu_put_be32(f, s->rsp32);
 +    qemu_put_be32(f, s->rsp54);
 +    qemu_put_be32(f, s->rsp76);
 +    qemu_put_be32(f, s->data);
 +    qemu_put_be32(f, s->pstate);
 +    qemu_put_be32(f, s->hctl);
 +    qemu_put_be32(f, s->sysctl);
 +    qemu_put_be32(f, s->stat);
 +    qemu_put_be32(f, s->ie);
 +    qemu_put_be32(f, s->ise);
 +    qemu_put_be32(f, s->ac12);
 +    qemu_put_be32(f, s->capa);
 +    qemu_put_be32(f, s->cur_capa);
 +    qemu_put_be32(f, s->rev);
 +    qemu_put_be16(f, s->blen_counter);
 +    qemu_put_be16(f, s->nblk_counter);
 +    for (i = 0; i < sizeof(s->fifo)/sizeof(uint32_t); i++)
 +        qemu_put_be32(f, s->fifo[i]);
 +    qemu_put_sbe32(f, s->fifo_start);
 +    qemu_put_sbe32(f, s->fifo_len);
 +    qemu_put_sbe32(f, s->ddir);
 +    qemu_put_sbe32(f, s->transfer);
 +    qemu_put_sbe32(f, s->stop);
 +    qemu_put_be32(f, s->stat_pending);
 +}
 +
 +static int omap3_mmc_load_state(QEMUFile *f, void *opaque, int version_id)
 +{
 +    struct omap3_mmc_s *s = (struct omap3_mmc_s *)opaque;
 +    int i;
 +    
 +    if (version_id)
 +        return -EINVAL;
 +    
 +    s->sysconfig = qemu_get_be32(f);
 +    s->sysstatus = qemu_get_be32(f);
 +    s->csre = qemu_get_be32(f);
 +    s->systest = qemu_get_be32(f);
 +    s->con = qemu_get_be32(f);
 +    s->pwcnt = qemu_get_be32(f);
 +    s->blk = qemu_get_be32(f);
 +    s->arg = qemu_get_be32(f);
 +    s->cmd = qemu_get_be32(f);
 +    s->rsp10 = qemu_get_be32(f);
 +    s->rsp32 = qemu_get_be32(f);
 +    s->rsp54 = qemu_get_be32(f);
 +    s->rsp76 = qemu_get_be32(f);
 +    s->data = qemu_get_be32(f);
 +    s->pstate = qemu_get_be32(f);
 +    s->hctl = qemu_get_be32(f);
 +    s->sysctl = qemu_get_be32(f);
 +    s->stat = qemu_get_be32(f);
 +    s->ie = qemu_get_be32(f);
 +    s->ise = qemu_get_be32(f);
 +    s->ac12 = qemu_get_be32(f);
 +    s->capa = qemu_get_be32(f);
 +    s->cur_capa = qemu_get_be32(f);
 +    s->rev = qemu_get_be32(f);
 +    s->blen_counter = qemu_get_be16(f);
 +    s->nblk_counter = qemu_get_be16(f);
 +    for (i = 0; i < sizeof(s->fifo)/sizeof(uint32_t); i++)
 +        s->fifo[i] = qemu_get_be32(f);
 +    s->fifo_start = qemu_get_sbe32(f);
 +    s->fifo_len = qemu_get_sbe32(f);
 +    s->ddir = qemu_get_sbe32(f);
 +    s->transfer = qemu_get_sbe32(f);
 +    s->stop = qemu_get_sbe32(f);
 +    s->stat_pending = qemu_get_be32(f);
 +    
 +    omap3_mmc_fifolevel_update(s);
 +    omap3_mmc_interrupts_update(s);
 +    
 +    return 0;
 +}
 +
 +struct omap3_mmc_s *omap3_mmc_init(struct omap_target_agent_s *ta,
 +                                   qemu_irq irq, qemu_irq dma[],
 +                                   omap_clk fclk, omap_clk iclk)
 +{
 +    int iomemtype;
 +    struct omap3_mmc_s *s = (struct omap3_mmc_s *)
 +        qemu_mallocz(sizeof(struct omap3_mmc_s));
 +
 +    s->irq = irq;
 +    s->dma = dma;
 +    s->clk = fclk;
 +
 +    omap3_mmc_reset(s);
 +
 +    iomemtype = l4_register_io_memory(0, omap3_mmc_readfn,
 +                                      omap3_mmc_writefn, s);
 +    omap_l4_attach(ta, 0, iomemtype);
 +
 +    register_savevm("omap3_mmc", (ta->base >> 12) & 0xff, 0,
 +                    omap3_mmc_save_state, omap3_mmc_load_state, s);
 +    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 --cc hw/omap3_usb.c
index 06eeaa3,0000000..f89c317
mode 100644,000000..100644
--- /dev/null
@@@ -1,512 -1,0 +1,512 @@@
 +/*
 + * TI OMAP3 High-Speed USB Host and OTG Controller emulation.
 + *
 + * Copyright (C) 2009 Nokia Corporation
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License as
 + * published by the Free Software Foundation; either version 2 or
 + * (at your option) version 3 of the License.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License along
 + * with this program; if not, write to the Free Software Foundation, Inc.,
 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 + */
 +#include "qemu-common.h"
 +#include "qemu-timer.h"
 +#include "usb.h"
 +#include "omap.h"
 +#include "irq.h"
 +#include "devices.h"
 +#include "hw.h"
 +
 +#define OMAP3_HSUSB_OTG
 +#define OMAP3_HSUSB_HOST
 +
 +#define OMAP3_HSUSB_DEBUG
 +
 +#ifdef OMAP3_HSUSB_DEBUG
 +#define TRACE(fmt,...) fprintf(stderr, "%s: " fmt "\n", __FUNCTION__, ##__VA_ARGS__)
 +#else
 +#define TRACE(...)
 +#endif
 +
 +#ifdef OMAP3_HSUSB_OTG
 +/* usb-musb.c */
 +extern CPUReadMemoryFunc *musb_read[];
 +extern CPUWriteMemoryFunc *musb_write[];
 +
 +struct omap3_hsusb_otg_s {
 +    qemu_irq mc_irq;
 +    qemu_irq dma_irq;
-     struct musb_s *musb;
++    MUSBState *musb;
 +    
 +    uint8_t rev;
 +    uint16_t sysconfig;
 +    uint8_t interfsel;
 +    uint8_t simenable;
 +    uint8_t forcestdby;
 +};
 +
 +static void omap3_hsusb_otg_save_state(QEMUFile *f, void *opaque)
 +{
 +    struct omap3_hsusb_otg_s *s = (struct omap3_hsusb_otg_s *)opaque;
 +    
 +    qemu_put_be16(f, s->sysconfig);
 +    qemu_put_byte(f, s->interfsel);
 +    qemu_put_byte(f, s->simenable);
 +    qemu_put_byte(f, s->forcestdby);
 +}
 +
 +static int omap3_hsusb_otg_load_state(QEMUFile *f, void *opaque,
 +                                      int version_id)
 +{
 +    struct omap3_hsusb_otg_s *s = (struct omap3_hsusb_otg_s *)opaque;
 +    
 +    if (version_id)
 +        return -EINVAL;
 +    
 +    s->sysconfig = qemu_get_be16(f);
 +    s->interfsel = qemu_get_byte(f);
 +    s->simenable = qemu_get_byte(f);
 +    s->forcestdby = qemu_get_byte(f);
 +    
 +    return 0;
 +}
 +
 +static void omap3_hsusb_otg_reset(struct omap3_hsusb_otg_s *s)
 +{
 +    s->rev = 0x33;
 +    s->sysconfig = 0;
 +    s->interfsel = 0x1;
 +    s->simenable = 0;
 +    s->forcestdby = 1;
 +}
 +
 +static uint32_t omap3_hsusb_otg_read(int access,
 +                                     void *opaque,
 +                                     target_phys_addr_t addr)
 +{
 +    struct omap3_hsusb_otg_s *s = (struct omap3_hsusb_otg_s *)opaque;
 +    
 +    if (addr < 0x200)
 +        return musb_read[access](s->musb, addr);
 +    if (addr < 0x400)
 +        return musb_read[access](s->musb, 0x20 + ((addr >> 3) & 0x3c));
 +    switch (addr) {
 +        case 0x400: /* OTG_REVISION */
 +            TRACE("OTG_REVISION: 0x%08x", s->rev);
 +            return s->rev;
 +        case 0x404: /* OTG_SYSCONFIG */
 +            TRACE("OTG_SYSCONFIG: 0x%08x", s->sysconfig);
 +            return s->sysconfig;
 +        case 0x408: /* OTG_SYSSTATUS */
 +            TRACE("OTG_SYSSTATUS: 0x00000001");
 +            return 1; /* reset finished */
 +        case 0x40c: /* OTG_INTERFSEL */
 +            TRACE("OTG_INTERFSEL: 0x%08x", s->interfsel);
 +            return s->interfsel;
 +        case 0x410: /* OTG_SIMENABLE */
 +            TRACE("OTG_SIMENABLE: 0x%08x", s->simenable);
 +            return s->simenable;
 +        case 0x414: /* OTG_FORCESTDBY */
 +            TRACE("OTG_FORCESTDBY: 0x%08x", s->forcestdby);
 +            return s->forcestdby;
 +        default:
 +            break;
 +    }
 +    OMAP_BAD_REG(addr);
 +    return 0;
 +}
 +
 +static void omap3_hsusb_otg_write(int access,
 +                                  void *opaque,
 +                                  target_phys_addr_t addr,
 +                                  uint32_t value)
 +{
 +    struct omap3_hsusb_otg_s *s = (struct omap3_hsusb_otg_s *)opaque;
 +    
 +    if (addr < 0x200)
 +        musb_write[access](s->musb, addr, value);
 +    else if (addr < 0x400)
 +        musb_write[access](s->musb, 0x20 + ((addr >> 3) & 0x3c), value);
 +    else switch (addr) {
 +        case 0x400: /* OTG_REVISION */
 +        case 0x408: /* OTG_SYSSTATUS */
 +            OMAP_RO_REGV(addr, value);
 +            break;
 +        case 0x404: /* OTG_SYSCONFIG */
 +            TRACE("OTG_SYSCONFIG = 0x%08x", value);
 +            if (value & 2) /* SOFTRESET */
 +                omap3_hsusb_otg_reset(s);
 +            s->sysconfig = value & 0x301f;
 +            break;
 +        case 0x40c: /* OTG_INTERFSEL */
 +            TRACE("OTG_INTERFSEL = 0x%08x", value);
 +            s->interfsel = value & 0x3;
 +            break;
 +        case 0x410: /* OTG_SIMENABLE */
 +            TRACE("OTG_SIMENABLE = 0x%08x", value);
 +            cpu_abort(cpu_single_env,
 +                      "%s: USB simulation mode not supported\n",
 +                      __FUNCTION__);
 +            break;
 +        case 0x414: /* OTG_FORCESTDBY */
 +            TRACE("OTG_FORCESTDBY = 0x%08x", value);
 +            s->forcestdby = value & 1;
 +            break;
 +        default:
 +            OMAP_BAD_REGV(addr, value);
 +            break;
 +    }
 +}
 +
 +static uint32_t omap3_hsusb_otg_readb(void *opaque, target_phys_addr_t addr)
 +{
 +    return omap3_hsusb_otg_read(0, opaque, addr);
 +}
 +
 +static uint32_t omap3_hsusb_otg_readh(void *opaque, target_phys_addr_t addr)
 +{
 +    return omap3_hsusb_otg_read(1, opaque, addr);
 +}
 +
 +static uint32_t omap3_hsusb_otg_readw(void *opaque, target_phys_addr_t addr)
 +{
 +    return omap3_hsusb_otg_read(2, opaque, addr);
 +}
 +
 +static void omap3_hsusb_otg_writeb(void *opaque, target_phys_addr_t addr,
 +                                   uint32_t value)
 +{
 +    omap3_hsusb_otg_write(0, opaque, addr, value);
 +}
 +
 +static void omap3_hsusb_otg_writeh(void *opaque, target_phys_addr_t addr,
 +                                   uint32_t value)
 +{
 +    omap3_hsusb_otg_write(1, opaque, addr, value);
 +}
 +
 +static void omap3_hsusb_otg_writew(void *opaque, target_phys_addr_t addr,
 +                                   uint32_t value)
 +{
 +    omap3_hsusb_otg_write(2, opaque, addr, value);
 +}
 +
 +static CPUReadMemoryFunc *omap3_hsusb_otg_readfn[] = {
 +    omap3_hsusb_otg_readb,
 +    omap3_hsusb_otg_readh,
 +    omap3_hsusb_otg_readw,
 +};
 +
 +static CPUWriteMemoryFunc *omap3_hsusb_otg_writefn[] = {
 +    omap3_hsusb_otg_writeb,
 +    omap3_hsusb_otg_writeh,
 +    omap3_hsusb_otg_writew,
 +};
 +
 +static void omap3_hsusb_musb_core_intr(void *opaque, int source, int level)
 +{
 +    struct omap3_hsusb_otg_s *s = (struct omap3_hsusb_otg_s *)opaque;
 +    /*TRACE("intr 0x%08x, 0x%08x, 0x%08x", source, level, musb_core_intr_get(s->musb));*/
 +    qemu_set_irq(s->mc_irq, level);
 +}
 +
 +static void omap3_hsusb_otg_init(struct omap_target_agent_s *otg_ta,
 +                                 qemu_irq mc_irq,
 +                                 qemu_irq dma_irq,
 +                                 struct omap3_hsusb_otg_s *s)
 +{
 +    s->mc_irq = mc_irq;
 +    s->dma_irq = dma_irq;
 +    
 +    omap_l4_attach(otg_ta, 0, l4_register_io_memory(0,
 +                                                    omap3_hsusb_otg_readfn,
 +                                                    omap3_hsusb_otg_writefn,
 +                                                    s));
 +    
 +    s->musb = musb_init(qemu_allocate_irqs(omap3_hsusb_musb_core_intr, s,
 +                                           __musb_irq_max));
 +    omap3_hsusb_otg_reset(s);
 +    
 +    register_savevm("omap3_hsusb_otg", -1, 0,
 +                    omap3_hsusb_otg_save_state,
 +                    omap3_hsusb_otg_load_state,
 +                    s);
 +}
 +#endif
 +
 +#ifdef OMAP3_HSUSB_HOST
 +struct omap3_hsusb_host_s {
 +    qemu_irq ehci_irq;
 +    qemu_irq tll_irq;
 +    
 +    uint32_t uhh_sysconfig;
 +    uint32_t uhh_hostconfig;
 +    uint32_t uhh_debug_csr;
 +    uint32_t tll_sysconfig;
 +    uint32_t insnreg05_ulpi;
 +};
 +
 +static void omap3_hsusb_host_save_state(QEMUFile *f, void *opaque)
 +{
 +    struct omap3_hsusb_host_s *s = (struct omap3_hsusb_host_s *)opaque;
 +    
 +    qemu_put_be32(f, s->uhh_sysconfig);
 +    qemu_put_be32(f, s->uhh_hostconfig);
 +    qemu_put_be32(f, s->uhh_debug_csr);
 +    qemu_put_be32(f, s->tll_sysconfig);
 +    qemu_put_be32(f, s->insnreg05_ulpi);
 +}
 +
 +static int omap3_hsusb_host_load_state(QEMUFile *f, void *opaque,
 +                                       int version_id)
 +{
 +    struct omap3_hsusb_host_s *s = (struct omap3_hsusb_host_s *)opaque;
 +    
 +    if (version_id)
 +        return -EINVAL;
 +    
 +    s->uhh_sysconfig = qemu_get_be32(f);
 +    s->uhh_hostconfig = qemu_get_be32(f);
 +    s->uhh_debug_csr = qemu_get_be32(f);
 +    s->tll_sysconfig = qemu_get_be32(f);
 +    s->insnreg05_ulpi = qemu_get_be32(f);
 +    
 +    return 0;
 +}
 +
 +static void omap3_hsusb_host_reset(struct omap3_hsusb_host_s *s)
 +{
 +    s->uhh_sysconfig = 1;
 +    s->uhh_hostconfig = 0x700;
 +    s->uhh_debug_csr = 0x20;
 +    /* TODO: perform OHCI & EHCI reset */
 +    s->tll_sysconfig = 1;
 +}
 +
 +static uint32_t omap3_hsusb_host_read(void *opaque, target_phys_addr_t addr)
 +{
 +    struct omap3_hsusb_host_s *s = (struct omap3_hsusb_host_s *)opaque;
 +    TRACE(OMAP_FMT_plx, addr);
 +
 +    switch (addr) {
 +        case 0x00: /* UHH_REVISION */
 +            return 0x10;
 +        case 0x10: /* UHH_SYSCONFIG */
 +            return s->uhh_sysconfig;
 +        case 0x14: /* UHH_SYSSTATUS */
 +            return 0x7; /* EHCI_RESETDONE | OHCI_RESETDONE | RESETDONE */
 +        case 0x40: /* UHH_HOSTCONFIG */
 +            return s->uhh_hostconfig;
 +        case 0x44: /* UHH_DEBUG_CSR */
 +            return s->uhh_debug_csr;
 +        default:
 +            break;
 +    }
 +    OMAP_BAD_REG(addr);
 +    return 0;
 +}
 +
 +static void omap3_hsusb_host_write(void *opaque, target_phys_addr_t addr,
 +                                   uint32_t value)
 +{
 +    struct omap3_hsusb_host_s *s = (struct omap3_hsusb_host_s *)opaque;
 +    TRACE(OMAP_FMT_plx " = 0x%08x", addr, value);
 +
 +    switch (addr) {
 +        case 0x00: /* UHH_REVISION */
 +        case 0x14: /* UHH_SYSSTATUS */
 +            OMAP_RO_REGV(addr, value);
 +            break;
 +        case 0x10: /* UHH_SYSCONFIG */
 +            s->uhh_sysconfig = value & 0x311d;
 +            if (value & 2) { /* SOFTRESET */
 +                omap3_hsusb_host_reset(s);
 +            }
 +            break;
 +        case 0x40: /* UHH_HOSTCONFIG */
 +            s->uhh_hostconfig = value & 0x1f3d;
 +            break;
 +        case 0x44: /* UHH_DEBUG_CSR */
 +            s->uhh_debug_csr = value & 0xf00ff;
 +            break;
 +        default:
 +            OMAP_BAD_REGV(addr, value);
 +            break;
 +    }
 +}
 +
 +static CPUReadMemoryFunc *omap3_hsusb_host_readfn[] = {
 +    omap_badwidth_read32,
 +    omap_badwidth_read32,
 +    omap3_hsusb_host_read,
 +};
 +
 +static CPUWriteMemoryFunc *omap3_hsusb_host_writefn[] = {
 +    omap_badwidth_write32,
 +    omap_badwidth_write32,
 +    omap3_hsusb_host_write,
 +};
 +
 +static uint32_t omap3_hsusb_ehci_read(void *opaque, target_phys_addr_t addr)
 +{
 +    struct omap3_hsusb_host_s *s = (struct omap3_hsusb_host_s *)opaque;
 +    TRACE(OMAP_FMT_plx, addr);
 +    switch (addr) {
 +        case 0xa4: /* INSNREG05_ULPI */
 +            return s->insnreg05_ulpi;
 +        default:
 +            break;
 +    }
 +    return 0;
 +}
 +
 +static void omap3_hsusb_ehci_write(void *opaque, target_phys_addr_t addr,
 +                                   uint32_t value)
 +{
 +    struct omap3_hsusb_host_s *s = (struct omap3_hsusb_host_s *)opaque;
 +    TRACE(OMAP_FMT_plx " = 0x%08x", addr, value);
 +
 +    switch (addr) {
 +        case 0xa4: /* INSNREG05_ULPI */
 +            s->insnreg05_ulpi = value & 0xF0000000;
 +        default:
 +            break;
 +     }
 +}
 +
 +static CPUReadMemoryFunc *omap3_hsusb_ehci_readfn[] = {
 +    omap_badwidth_read32,
 +    omap_badwidth_read32,
 +    omap3_hsusb_ehci_read,
 +};
 +
 +static CPUWriteMemoryFunc *omap3_hsusb_ehci_writefn[] = {
 +    omap_badwidth_write32,
 +    omap_badwidth_write32,
 +    omap3_hsusb_ehci_write,
 +};
 +
 +static uint32_t omap3_hsusb_tll_read(void *opaque, target_phys_addr_t addr)
 +{
 +    struct omap3_hsusb_host_s *s = (struct omap3_hsusb_host_s *)opaque;
 +    TRACE(OMAP_FMT_plx, addr);
 +
 +    switch (addr) {
 +        case 0x00: /* USBTLL_REVISION */
 +            return 0x1;
 +        case 0x10: /* USBTLL_SYSCONFIG */
 +            return s->tll_sysconfig;
 +        case 0x14: /* USBTLL_SYSSTATUS */
 +            return 0x1; /* RESETDONE */
 +        case 0x18: /* USBTLL_IRQSTATUS */
 +            return 0;
 +        case 0x1C: /* USBTLL_IRQENABLE */
 +            return 0;
 +        default:
 +            break;
 +    }
 +    return 0;
 +}
 +
 +static void omap3_hsusb_tll_write(void *opaque, target_phys_addr_t addr,
 +                                  uint32_t value)
 +{
 +    struct omap3_hsusb_host_s *s = (struct omap3_hsusb_host_s *)opaque;
 +    TRACE(OMAP_FMT_plx " = 0x%08x", addr, value);
 +
 +    switch (addr) {
 +        case 0x00: /* USBTLL_REVISION */
 +        case 0x14: /* USBTLL_SYSSTATUS */
 +            OMAP_RO_REGV(addr, value);
 +        case 0x10: /* USBTLL_SYSCONFIG */
 +            s->tll_sysconfig = value & 0xFFFFFEE0;;
 +        default:
 +            OMAP_BAD_REGV(addr, value);
 +            break;
 +    }
 +}
 +
 +static CPUReadMemoryFunc *omap3_hsusb_tll_readfn[] = {
 +    omap_badwidth_read32,
 +    omap_badwidth_read32,
 +    omap3_hsusb_tll_read,
 +};
 +
 +static CPUWriteMemoryFunc *omap3_hsusb_tll_writefn[] = {
 +    omap_badwidth_write32,
 +    omap_badwidth_write32,
 +    omap3_hsusb_tll_write,
 +};
 +
 +static void omap3_hsusb_host_init(struct omap_target_agent_s *host_ta,
 +                                  struct omap_target_agent_s *tll_ta,
 +                                  qemu_irq ohci_irq,
 +                                  qemu_irq ehci_irq,
 +                                  qemu_irq tll_irq,
 +                                  struct omap3_hsusb_host_s *s)
 +{
 +    s->ehci_irq = ehci_irq;
 +    s->tll_irq  = tll_irq;
 +    
 +    omap_l4_attach(tll_ta, 0, l4_register_io_memory(0,
 +                                                    omap3_hsusb_tll_readfn,
 +                                                    omap3_hsusb_tll_writefn,
 +                                                    s));
 +    omap_l4_attach(host_ta, 0, l4_register_io_memory(0,
 +                                                     omap3_hsusb_host_readfn,
 +                                                     omap3_hsusb_host_writefn,
 +                                                     s));
 +/*    omap_l4_attach(host_ta, 1, usb_ohci_init_omap(omap_l4_base(host_ta, 1),
 +                                                  omap_l4_size(host_ta, 1),
 +                                                  3, ohci_irq));*/
 +    omap_l4_attach(host_ta, 2, l4_register_io_memory(0,
 +                                                     omap3_hsusb_ehci_readfn,
 +                                                     omap3_hsusb_ehci_writefn,
 +                                                     s));
 +    
 +    omap3_hsusb_host_reset(s);
 +    
 +    register_savevm("omap3_hsusb_host", -1, 0,
 +                    omap3_hsusb_host_save_state,
 +                    omap3_hsusb_host_load_state, s);
 +}
 +#endif
 +
 +struct omap3_hsusb_s {
 +#ifdef OMAP3_HSUSB_OTG
 +    struct omap3_hsusb_otg_s otg;
 +#endif
 +#ifdef OMAP3_HSUSB_HOST
 +    struct omap3_hsusb_host_s host;
 +#endif
 +};
 +
 +struct omap3_hsusb_s *omap3_hsusb_init(struct omap_target_agent_s *otg_ta,
 +                                       struct omap_target_agent_s *host_ta,
 +                                       struct omap_target_agent_s *tll_ta,
 +                                       qemu_irq mc_irq,
 +                                       qemu_irq dma_irq,
 +                                       qemu_irq ohci_irq,
 +                                       qemu_irq ehci_irq,
 +                                       qemu_irq tll_irq)
 +{
 +    struct omap3_hsusb_s *s = qemu_mallocz(sizeof(struct omap3_hsusb_s));
 +#ifdef OMAP3_HSUSB_HOST
 +    omap3_hsusb_host_init(host_ta, tll_ta,
 +                          ohci_irq, ehci_irq, tll_irq,
 +                          &s->host);
 +#endif
 +#ifdef OMAP3_HSUSB_OTG
 +    omap3_hsusb_otg_init(otg_ta, mc_irq, dma_irq, &s->otg);
 +#endif
 +    return s;
 +}
 +
diff --cc hw/omap_clk.c
Simple merge
diff --cc hw/omap_dss.c
@@@ -2190,163 -1064,6 +2190,163 @@@ struct omap_dss_s *omap_dss_init(struc
  void omap_rfbi_attach(struct omap_dss_s *s, int cs, struct rfbi_chip_s *chip)
  {
      if (cs < 0 || cs > 1)
-         cpu_abort(cpu_single_env, "%s: wrong CS %i\n", __FUNCTION__, cs);
+         hw_error("%s: wrong CS %i\n", __FUNCTION__, cs);
      s->rfbi.chip[cs] = chip;
  }
 +
 +void omap3_lcd_panel_attach(struct omap_dss_s *dss,
 +                            int cs,
 +                            struct omap3_lcd_panel_s *lcd_panel)
 +{
 +    if (cs < 0 || cs > 1)
 +        cpu_abort(cpu_single_env, "%s: wrong CS %i\n", __FUNCTION__, cs);
 +    dss->omap_lcd_panel[cs] = lcd_panel;
 +      lcd_panel->dss = dss;
 +}
 +
 +/*omap3 lcd panel stuff*/
 +
 +#define DEPTH 8
 +#include "omap3_lcd_panel_template.h"
 +#define DEPTH 15
 +#include "omap3_lcd_panel_template.h"
 +#define DEPTH 16
 +#include "omap3_lcd_panel_template.h"
 +#define DEPTH 24
 +#include "omap3_lcd_panel_template.h"
 +#define DEPTH 32
 +#include "omap3_lcd_panel_template.h"
 +
 +/* Bytes(!) per pixel */
 +static const int omap3_lcd_panel_bpp[0x10] = {
 +    0,  /* 0x0: BITMAP1 (CLUT) */
 +    0,  /* 0x1: BITMAP2 (CLUT) */
 +    0,  /* 0x2: BITMAP4 (CLUT) */
 +    0,  /* 0x3: BITMAP8 (CLUT) */
 +    2,  /* 0x4: RGB12 (unpacked 16-bit container)*/
 +    2,  /* 0x5: ARGB16 */
 +    2,  /* 0x6: RGB16 */
 +    0,  /* 0x7: reserved */
 +    4,  /* 0x8: RGB24 (unpacked in 32-bit container) */
 +    3,  /* 0x9: RGB24 (packed in 24-bit container) */
 +    2,  /* 0xa: YUV2 422 */
 +    2,  /* 0xb: UYVY 422 */
 +    4,  /* 0xc: ARGB32 */
 +    4,  /* 0xd: RGBA32 */
 +    4,  /* 0xe: RGBx32 (24-bit RGB aligned on MSB of the 32-bit container) */
 +    0,  /* 0xf: reserved */
 +};
 +
 +static inline void omap3_lcd_panel_invalidate_display(void *opaque) 
 +{
 +    struct omap3_lcd_panel_s *s = (struct omap3_lcd_panel_s *)opaque;
 +    s->invalidate = 1;
 +}
 +
 +static void omap3_lcd_panel_update_display(void *opaque)
 +{
 +    struct omap3_lcd_panel_s *s = (struct omap3_lcd_panel_s *)opaque;
 +    struct omap_dss_s *dss = s->dss;
 +    const uint32_t lcd_width = dss->lcd.nx;
 +    const uint32_t lcd_height = dss->lcd.ny;
 +    uint32_t graphic_width, graphic_height;
 +    uint32_t start_x, start_y;
 +    const uint32_t lcd_Bpp = omap3_lcd_panel_bpp[dss->dispc.l[0].gfx_format];
 +    uint32_t dss_Bpp;
 +    uint32_t linesize, y;
 +    uint32_t copy_width, copy_height;
 +    uint8_t *src, *dest;
 +    target_phys_addr_t size;
 +
 +    if (!dss->lcd.enable
 +        || dss->dispc.l[0].gfx_channel /* 24bit digital out */
 +        || ((dss->dispc.control & (1 << 11))) /* RFBI */
 +        || !lcd_Bpp)
 +        return;
 +    
 +    /* check for setup changes since last visit only if flagged */
 +    if (dss->dispc.invalidate) {
 +        dss->dispc.invalidate = 0;
 +        if (lcd_width != ds_get_width(s->state) 
 +            || lcd_height != ds_get_height(s->state)) {
 +            qemu_console_resize(s->state, lcd_width, lcd_height);
 +            s->invalidate = 1;
 +        }
 +        int gf = dss->dispc.l[0].gfx_format;
 +        if (!(dss->dispc.l[0].rotation_flag)) {         /* rotation*/
 +            switch (ds_get_bits_per_pixel(s->state)) {
 +              case 8:  s->line_fn = omap3_lcd_panel_draw_fn_8[gf]; break;
 +              case 15: s->line_fn = omap3_lcd_panel_draw_fn_15[gf]; break;
 +              case 16: s->line_fn = omap3_lcd_panel_draw_fn_16[gf]; break;
 +              case 24: s->line_fn = omap3_lcd_panel_draw_fn_24[gf]; break;
 +              case 32: s->line_fn = omap3_lcd_panel_draw_fn_32[gf]; break;
 +              default: s->line_fn = 0; break;
 +            }
 +        } else {
 +              switch (ds_get_bits_per_pixel(s->state)) {
 +              case 8:  s->line_fn = omap3_lcd_panel_draw_fn_r_8[gf]; break;
 +              case 15: s->line_fn = omap3_lcd_panel_draw_fn_r_15[gf]; break;
 +              case 16: s->line_fn = omap3_lcd_panel_draw_fn_r_16[gf]; break;
 +              case 24: s->line_fn = omap3_lcd_panel_draw_fn_r_24[gf]; break;
 +              case 32: s->line_fn = omap3_lcd_panel_draw_fn_r_32[gf]; break;
 +              default: s->line_fn = 0; break;
 +            }
 +        }
 +    }
 +    if (!s->line_fn) {
 +        fprintf(stderr,
 +                "%s: line_fn is NULL - host bpp=%d, omap3 lcd gfx_format=%d\n",
 +                __FUNCTION__,
 +                ds_get_bits_per_pixel(s->state),
 +                dss->dispc.l[0].gfx_format);
 +        exit(1);
 +    }
 +    
 +    /* Resolution */
 +    graphic_width = dss->dispc.l[0].nx;
 +    graphic_height = dss->dispc.l[0].ny;
 +    start_x = dss->dispc.l[0].posx;
 +    start_y = dss->dispc.l[0].posy;
 +
 +    dest = ds_get_data(s->state);
 +    linesize = ds_get_linesize(s->state);
 +
 +    dss_Bpp = linesize / ds_get_width(s->state);
 +
 +    dest += linesize * start_y;
 +    dest += start_x * dss_Bpp;
 +
 +    if ((start_x + graphic_width) > lcd_width)
 +        copy_width = lcd_width - start_x;
 +    else
 +      copy_width = graphic_width;
 +    copy_height = lcd_height > graphic_height ? graphic_height : lcd_height;
 +
 +    size = copy_height * copy_width * lcd_Bpp;
 +    src = cpu_physical_memory_map(dss->dispc.l[0].addr[0], &size, 0);
 +    if (src) {
 +        if (size == copy_height * copy_width * lcd_Bpp) {
 +            for (y = start_y; y < copy_height; y++) {
 +                s->line_fn(dest, src, copy_width * lcd_Bpp);
 +                src += graphic_width * lcd_Bpp;
 +                dest += linesize;
 +            }
 +            dpy_update(s->state, start_x, start_y, graphic_width, graphic_height);
 +        }
 +        cpu_physical_memory_unmap(src, size, 0, size);
 +    }
 +    s->invalidate = 0;
 +    
 +    dss->dispc.irqst |= 1; /* FRAMEDONE */
 +    omap_dss_interrupt_update(dss);
 +}
 +
 +void *omap3_lcd_panel_init()
 +{
 +    struct omap3_lcd_panel_s *s = (struct omap3_lcd_panel_s *) qemu_mallocz(sizeof(*s));
 +
 +    s->state = graphic_console_init(omap3_lcd_panel_update_display,
 +                                    omap3_lcd_panel_invalidate_display,
 +                                    NULL, NULL, s);
 +    return s;
 +}
diff --cc hw/omap_i2c.c
@@@ -65,95 -47,16 +64,20 @@@ struct omap_i2c_s 
  
  static void omap_i2c_interrupts_update(struct omap_i2c_s *s)
  {
 +    TRACE("IRQ=%04x,RDRQ=%d,XDRQ=%d", 
 +          s->stat & s->mask,
 +          ((s->dma >> 15 ) & 1) & ((s->stat >> 3) & 1),
 +          ((s->dma >> 7 ) & 1 )& ((s->stat >> 4 ) & 1));
      qemu_set_irq(s->irq, s->stat & s->mask);
 -    if ((s->dma >> 15) & 1)                                   /* RDMA_EN */
 -        qemu_set_irq(s->drq[0], (s->stat >> 3) & 1);          /* RRDY */
 -    if ((s->dma >> 7) & 1)                                    /* XDMA_EN */
 -        qemu_set_irq(s->drq[1], (s->stat >> 4) & 1);          /* XRDY */
 +    if ((s->dma >> 15) & 1)                          /* RDMA_EN */
 +        qemu_set_irq(s->drq[0], (s->stat >> 3) & 1); /* RRDY */
 +    if ((s->dma >> 7) & 1)                           /* XDMA_EN */
 +        qemu_set_irq(s->drq[1], (s->stat >> 4) & 1); /* XRDY */
  }
  
- /* These are only stubs now.  */
- static void omap_i2c_event(i2c_slave *i2c, enum i2c_event event)
- {
-     fprintf(stderr, "%s: I^2C slave mode not supported\n", __FUNCTION__);
-     
-     /* code below is broken, i2c_slave CANNOT be cast to omap_i2c_s! */
-      
-     //struct omap_i2c_s *s = (struct omap_i2c_s *) i2c;
-     // 
-     //if ((~s->control >> 15) & 1)                            /* I2C_EN */
-     //    return;
-     //
-     //switch (event) {
-     //    case I2C_START_SEND:
-     //    case I2C_START_RECV:
-     //        s->stat |= 1 << 9;                                      /* AAS */
-     //        break;
-     //    case I2C_FINISH:
-     //        s->stat |= 1 << 2;                                      /* ARDY */
-     //        break;
-     //    case I2C_NACK:
-     //        s->stat |= 1 << 1;                                      /* NACK */
-     //        break;
-     //    default:
-     //        break;
-     //}
-     //
-     //omap_i2c_interrupts_update(s);
- }
- static int omap_i2c_rx(i2c_slave *i2c)
- {
-     fprintf(stderr, "%s: I^2C slave mode not supported\n", __FUNCTION__);
-     return 0;
-     
-     /* code below is broken, i2c_slave CANNOT be cast to omap_i2c_s! */
-     
-     //struct omap_i2c_s *s = (struct omap_i2c_s *) i2c;
-     //uint8_t ret = 0;
-     //
-     //if ((~s->control >> 15) & 1)                            /* I2C_EN */
-     //    return -1;
-     //
-     //if (s->rxlen < s->txlen)
-     //    ret = s->fifo[s->rxlen++];
-     //else
-     //    s->stat |= 1 << 10;                                 /* XUDF */
-     //s->stat |= 1 << 4;                                              /* XRDY */
-     //
-     //omap_i2c_interrupts_update(s);
-     //return ret;
- }
- static int omap_i2c_tx(i2c_slave *i2c, uint8_t data)
- {
-     fprintf(stderr, "%s: I^2C slave mode not supported\n", __FUNCTION__);
-     return 1;
-     
-     /* code below is broken, i2c_slave CANNOT be cast to omap_i2c_s! */
-     
-     //struct omap_i2c_s *s = (struct omap_i2c_s *) i2c;
-     //
-     //if ((~s->control >> 15) & 1)                            /* I2C_EN */
-     //    return 1;
-     //
-     //if (s->txlen < s->fifosize)
-     //    s->fifo[s->txlen++] = data;
-     //else
-     //    s->stat |= 1 << 11;                                 /* ROVR */
-     //s->stat |= 1 << 3;                                              /* RRDY */
-     //
-     //omap_i2c_interrupts_update(s);
-     //return 1;
- }
  static void omap_i2c_fifo_run(struct omap_i2c_s *s)
  {
 -    int ack = 1;
 +    int ack = 1, i;
  
      if (!i2c_bus_busy(s->bus))
          return;
@@@ -272,127 -148,91 +196,127 @@@ static uint32_t omap_i2c_read(void *opa
      uint16_t ret;
  
      switch (offset) {
 -    case 0x00:        /* I2C_REV */
 -        return s->revision;                                   /* REV */
 -
 -    case 0x04:        /* I2C_IE */
 -        return s->mask;
 -
 -    case 0x08:        /* I2C_STAT */
 -        return s->stat | (i2c_bus_busy(s->bus) << 12);
 -
 -    case 0x0c:        /* I2C_IV */
 -        if (s->revision >= OMAP2_INTR_REV)
 -            break;
 -        ret = ffs(s->stat & s->mask);
 -        if (ret)
 -            s->stat ^= 1 << (ret - 1);
 -        omap_i2c_interrupts_update(s);
 -        return ret;
 -
 -    case 0x10:        /* I2C_SYSS */
 -        return (s->control >> 15) & 1;                                /* I2C_EN */
 -
 -    case 0x14:        /* I2C_BUF */
 -        return s->dma;
 -
 -    case 0x18:        /* I2C_CNT */
 -        return s->count_cur;                                  /* DCOUNT */
 -
 -    case 0x1c:        /* I2C_DATA */
 -        ret = 0;
 -        if (s->control & (1 << 14)) {                         /* BE */
 -            ret |= ((s->fifo >> 0) & 0xff) << 8;
 -            ret |= ((s->fifo >> 8) & 0xff) << 0;
 -        } else {
 -            ret |= ((s->fifo >> 8) & 0xff) << 8;
 -            ret |= ((s->fifo >> 0) & 0xff) << 0;
 -        }
 -        if (s->rxlen == 1) {
 -            s->stat |= 1 << 15;                                       /* SBD */
 -            s->rxlen = 0;
 -        } else if (s->rxlen > 1) {
 -            if (s->rxlen > 2)
 -                s->fifo >>= 16;
 -            s->rxlen -= 2;
 -        } else
 -            /* XXX: remote access (qualifier) error - what's that?  */;
 -        if (!s->rxlen) {
 -            s->stat &= ~(1 << 3);                             /* RRDY */
 -            if (((s->control >> 10) & 1) &&                   /* MST */
 -                            ((~s->control >> 9) & 1)) {               /* TRX */
 -                s->stat |= 1 << 2;                            /* ARDY */
 -                s->control &= ~(1 << 10);                     /* MST */
 +        case 0x00: /* I2C_REV */
 +            TRACE("REV returns %04x", s->revision);
 +            return s->revision;
 +        case 0x04: /* I2C_IE */
 +            TRACE("IE returns %04x", s->mask);
 +            return s->mask;
 +        case 0x08: /* I2C_STAT */
 +            TRACE("STAT returns %04x", s->stat | (i2c_bus_busy(s->bus) << 12));
 +            return s->stat | (i2c_bus_busy(s->bus) << 12);
 +        case 0x0c: /* I2C_IV / I2C_WE */
 +            if (s->revision >= OMAP3_INTR_REV)
 +                return s->we;
 +            if (s->revision >= OMAP2_INTR_REV)
 +                break;
 +            ret = ffs(s->stat & s->mask);
 +            if (ret)
 +                s->stat ^= 1 << (ret - 1);
 +            omap_i2c_interrupts_update(s);
 +            return ret;
 +        case 0x10: /* I2C_SYSS */
 +            return (s->control >> 15) & 1; /* reset completed == I2C_EN */
 +        case 0x14: /* I2C_BUF */
 +            TRACE("BUF returns %04x", s->dma);
 +            return s->dma;
 +        case 0x18: /* I2C_CNT */
 +            TRACE("CNT returns %04x", s->count_cur);
 +            return s->count_cur; /* DCOUNT */
 +        case 0x1c: /* I2C_DATA */
 +            ret = 0;
 +            if (s->fifolen) {
 +                if (s->revision < OMAP3_INTR_REV) {
 +                    if (s->control & (1 << 14)) /* BE */
 +                        ret = (((uint16_t)s->fifo[s->fifostart]) << 8) 
 +                            | s->fifo[(s->fifostart + 1) & I2C_FIFO_SIZE_MASK];
 +                    else
 +                        ret = (((uint16_t)s->fifo[(s->fifostart + 1) & I2C_FIFO_SIZE_MASK]) << 8) 
 +                            | s->fifo[s->fifostart];
 +                    s->fifostart = (s->fifostart + 2) & I2C_FIFO_SIZE_MASK;
 +                    if (s->fifolen == 1) {
 +                        s->stat |= 1 << 15; /* SBD */
 +                        s->fifolen = 0;
 +                    } else
 +                        s->fifolen -= 2;
 +                    if (!s->fifolen) {
 +                        s->stat &= ~(1 << 3); /* RRDY */
 +                        s->stat |= 1 << 2;    /* ARDY */
 +                    }
 +                } else {
 +                    s->stat &= ~(1 << 7); /* AERR */
 +                    ret = s->fifo[s->fifostart++];
 +                    s->fifostart &= I2C_FIFO_SIZE_MASK;
 +                    if (--s->fifolen) {
-                         if (s->fifolen < ((s->dma & 0x3f) >> 8)) {
++                        if (s->fifolen <= ((s->dma >> 8) & 0x3f)) {
 +                            s->stat &= ~(1 << 3); /* RRDY */
 +                            s->stat |= 1 << 13;   /* RDR */
 +                        }
 +                    } else {
 +                        s->stat &= ~((1 << 3) | (1 << 13)); /* RRDY | RDR */
 +                        s->stat |= 1 << 2;                  /* ARDY */
 +                    }
 +                }
 +                s->stat &= ~(1 << 11); /* ROVR */
 +            } else if (s->revision >= OMAP3_INTR_REV)
 +                s->stat |= (1 << 7); /* AERR */
 +            TRACE("DATA returns %04x", ret);
 +            omap_i2c_fifo_run(s);
 +            omap_i2c_interrupts_update(s);
 +            return ret;
 +        case 0x20: /* I2C_SYSC */
 +            TRACE("SYSC returns %04x", s->sysc);
 +            return s->sysc;
 +        case 0x24: /* I2C_CON */
 +            TRACE("CON returns %04x", s->control);
 +            return s->control;
 +        case 0x28: /* I2C_OA / I2C_OA0 */
 +            return s->own_addr[0];
 +        case 0x2c: /* I2C_SA */
 +            return s->slave_addr;
 +        case 0x30: /* I2C_PSC */
 +            return s->divider;
 +        case 0x34: /* I2C_SCLL */
 +            return s->times[0];
 +        case 0x38: /* I2C_SCLH */
 +            return s->times[1];
 +        case 0x3c: /* I2C_SYSTEST */
 +            if (s->test & (1 << 15)) { /* ST_EN */
 +                s->test ^= 0xa;
 +                return s->test;
              }
 -        }
 -        s->stat &= ~(1 << 11);                                        /* ROVR */
 -        omap_i2c_fifo_run(s);
 -        omap_i2c_interrupts_update(s);
 -        return ret;
 -
 -    case 0x20:        /* I2C_SYSC */
 -        return 0;
 -
 -    case 0x24:        /* I2C_CON */
 -        return s->control;
 -
 -    case 0x28:        /* I2C_OA */
 -        return s->addr[0];
 -
 -    case 0x2c:        /* I2C_SA */
 -        return s->addr[1];
 -
 -    case 0x30:        /* I2C_PSC */
 -        return s->divider;
 -
 -    case 0x34:        /* I2C_SCLL */
 -        return s->times[0];
 -
 -    case 0x38:        /* I2C_SCLH */
 -        return s->times[1];
 -
 -    case 0x3c:        /* I2C_SYSTEST */
 -        if (s->test & (1 << 15)) {                            /* ST_EN */
 -            s->test ^= 0xa;
 -            return s->test;
 -        } else
              return s->test & ~0x300f;
 +        case 0x40: /* I2C_BUFSTAT */
 +            if (s->revision >= OMAP3_INTR_REV) {
 +                switch (s->fifosize) {
 +                    case 8:  ret = 0x0000; break;
 +                    case 16: ret = 0x4000; break;
 +                    case 32: ret = 0x8000; break;
 +                    case 64: ret = 0xc000; break;
 +                    default: ret = 0x0000; break;
 +                }
 +                ret |= ((s->fifolen) & 0x3f) << 8;  /* RXSTAT */
 +                ret |= (s->count_cur) & 0x3f;       /* TXSTAT */
 +                TRACE("BUFSTAT returns %04x", ret);
 +                return ret;
 +            }
 +            break;
 +        case 0x44: /* I2C_OA1 */
 +        case 0x48: /* I2C_OA2 */
 +        case 0x4c: /* I2C_OA3 */
 +            if (s->revision >= OMAP3_INTR_REV)
 +                return s->own_addr[(addr >> 2) & 3];
 +            break;
 +        case 0x50: /* I2C_ACTOA */
 +            if (s->revision >= OMAP3_INTR_REV)
 +                return 0; /* TODO: determine accessed slave own address */
 +            break;
 +        case 0x54: /* I2C_SBLOCK */
 +            if (s->revision >= OMAP3_INTR_REV)
 +                return s->sblock;
 +            break;
 +        default:
 +            break;
      }
  
      OMAP_BAD_REG(addr);
@@@ -407,195 -247,137 +331,195 @@@ static void omap_i2c_write(void *opaque
      int nack;
  
      switch (offset) {
 -    case 0x00:        /* I2C_REV */
 -    case 0x0c:        /* I2C_IV */
 -    case 0x10:        /* I2C_SYSS */
 -        OMAP_RO_REG(addr);
 -        return;
 -
 -    case 0x04:        /* I2C_IE */
 -        s->mask = value & (s->revision < OMAP2_GC_REV ? 0x1f : 0x3f);
 -        break;
 -
 -    case 0x08:        /* I2C_STAT */
 -        if (s->revision < OMAP2_INTR_REV) {
 +        case 0x00: /* I2C_REV */
 +        case 0x10: /* I2C_SYSS */
 +        case 0x40: /* I2C_BUFSTAT */
 +        case 0x50: /* I2C_ACTOA */
              OMAP_RO_REG(addr);
 -            return;
 -        }
 -
 -        /* RRDY and XRDY are reset by hardware. (in all versions???) */
 -        s->stat &= ~(value & 0x27);
 -        omap_i2c_interrupts_update(s);
 -        break;
 -
 -    case 0x14:        /* I2C_BUF */
 -        s->dma = value & 0x8080;
 -        if (value & (1 << 15))                                        /* RDMA_EN */
 -            s->mask &= ~(1 << 3);                             /* RRDY_IE */
 -        if (value & (1 << 7))                                 /* XDMA_EN */
 -            s->mask &= ~(1 << 4);                             /* XRDY_IE */
 -        break;
 -
 -    case 0x18:        /* I2C_CNT */
 -        s->count = value;                                     /* DCOUNT */
 -        break;
 -
 -    case 0x1c:        /* I2C_DATA */
 -        if (s->txlen > 2) {
 -            /* XXX: remote access (qualifier) error - what's that?  */
              break;
 -        }
 -        s->fifo <<= 16;
 -        s->txlen += 2;
 -        if (s->control & (1 << 14)) {                         /* BE */
 -            s->fifo |= ((value >> 8) & 0xff) << 8;
 -            s->fifo |= ((value >> 0) & 0xff) << 0;
 -        } else {
 -            s->fifo |= ((value >> 0) & 0xff) << 8;
 -            s->fifo |= ((value >> 8) & 0xff) << 0;
 -        }
 -        s->stat &= ~(1 << 10);                                        /* XUDF */
 -        if (s->txlen > 2)
 -            s->stat &= ~(1 << 4);                             /* XRDY */
 -        omap_i2c_fifo_run(s);
 -        omap_i2c_interrupts_update(s);
 -        break;
 -
 -    case 0x20:        /* I2C_SYSC */
 -        if (s->revision < OMAP2_INTR_REV) {
 -            OMAP_BAD_REG(addr);
 -            return;
 -        }
 -
 -        if (value & 2)
 -            omap_i2c_reset(s);
 -        break;
 -
 -    case 0x24:        /* I2C_CON */
 -        s->control = value & 0xcf87;
 -        if (~value & (1 << 15)) {                             /* I2C_EN */
 +        case 0x04: /* I2C_IE */
 +            TRACE("IE = %04x", value);
 +            if (s->revision >= OMAP3_INTR_REV)
 +                s->mask = value & 0x63ff;
 +            else
 +                s->mask = value & (s->revision < OMAP2_GC_REV ? 0x1f : 0x3f);
 +            omap_i2c_interrupts_update(s);
 +            break;
 +        case 0x08: /* I2C_STAT */
              if (s->revision < OMAP2_INTR_REV)
 +                OMAP_RO_REG(addr);
 +            else {
 +                TRACE("STAT = %04x", value);
 +                /* RRDY and XRDY are reset by hardware. (in all versions???) */
 +                s->stat &= ~(value & (s->revision < OMAP3_INTR_REV ? 0x27 : 0x63e7));
 +                omap_i2c_interrupts_update(s);
 +            }
 +            break;
 +        case 0x0c: /* I2C_IV / I2C_WE */
 +            if (s->revision < OMAP3_INTR_REV)
 +                OMAP_RO_REG(addr);
 +            else
 +                s->we = value & 0x636f;
 +            break;
 +        case 0x14: /* I2C_BUF */
 +            TRACE("BUF = %04x", value);
 +            if (s->revision < OMAP3_INTR_REV)
 +                s->dma = value & 0x8080;
 +            else {
 +                s->dma = value & 0xbfbf;
 +                if ((value & (1 << 14))    /* RXFIFO_CLR */
 +                    || (value & (1 << 6))) /* TXFIFO_CLR */
 +                    s->fifolen = 0;
 +            }
 +            if (value & (1 << 15))     /* RDMA_EN */
 +                s->mask &= ~(1 << 3);  /* RRDY_IE */
 +            if (value & (1 << 7))      /* XDMA_EN */
 +                s->mask &= ~(1 << 4);  /* XRDY_IE */
 +            break;
 +        case 0x18: /* I2C_CNT */
 +            TRACE("CNT = %04x", value);
 +            s->count = value; /* DCOUNT */
 +            break;
 +        case 0x1c: /* I2C_DATA */
 +            TRACE("DATA = %04x", value);
 +            if (s->revision < OMAP3_INTR_REV) {
 +                if (s->fifolen > 2) {
 +                    /* XXX: remote access (qualifier) error - what's that? */
 +                    break;
 +                }
 +                if (s->control & (1 << 14)) { /* BE */
 +                    s->fifo[(s->fifostart + s->fifolen++) & I2C_FIFO_SIZE_MASK] =
 +                        (uint8_t)((value >> 8) & 0xff);
 +                    s->fifo[(s->fifostart + s->fifolen++) & I2C_FIFO_SIZE_MASK] =
 +                        (uint8_t)(value & 0xff);
 +                } else {
 +                    s->fifo[(s->fifostart + s->fifolen++) & I2C_FIFO_SIZE_MASK] =
 +                        (uint8_t)(value & 0xff);
 +                    s->fifo[(s->fifostart + s->fifolen++) & I2C_FIFO_SIZE_MASK] =
 +                        (uint8_t)((value >> 8) & 0xff);
 +                }
 +            } else {
 +                if (s->fifolen < s->fifosize) {
 +                    s->stat &= ~(1 << 7); /* AERR */
 +                    s->fifo[(s->fifostart + s->fifolen++) & I2C_FIFO_SIZE_MASK] =
 +                        (uint8_t)(value & 0xff);
 +                } else
 +                    s->stat |= (1 << 7); /* AERR */
 +            }
 +            s->stat &= ~(1 << 10); /* XUDF */
 +            omap_i2c_fifo_run(s);
 +            omap_i2c_interrupts_update(s);
 +            break;
 +        case 0x20: /* I2C_SYSC */
 +            if (s->revision < OMAP2_INTR_REV) {
 +                OMAP_BAD_REG(addr);
 +                break;
 +            }
 +            TRACE("SYSC = %04x", value);
 +            if (value & 2)
                  omap_i2c_reset(s);
 +            else if (s->revision >= OMAP3_INTR_REV)
 +                s->sysc = value & 0x031d;
              break;
 -        }
 -        if ((value & (1 << 15)) && !(value & (1 << 10))) {    /* MST */
 -            fprintf(stderr, "%s: I^2C slave mode not supported\n",
 -                            __FUNCTION__);
 +        case 0x24: /* I2C_CON */
 +            TRACE("CON = %04x", value);
 +            s->control = value & (s->revision < OMAP3_INTR_REV ? 0xcf87 : 0xbff3);
 +            if (~value & (1 << 15)) { /* I2C_EN */
 +                if (s->revision < OMAP2_INTR_REV)
 +                    omap_i2c_reset(s);
 +                break;
 +            }
 +            if (s->revision >= OMAP3_INTR_REV && ((value >> 12) & 3) > 1) { /* OPMODE */
 +                fprintf(stderr,
 +                        "%s: only FS and HS modes are supported\n",
 +                        __FUNCTION__);
 +                break;
 +            }
 +            if ((value & (1 << 10))) { /* MST */
 +                if (value & 1) { /* STT */
 +                    nack = !!i2c_start_transfer(s->bus, s->slave_addr, /*SA*/
 +                                                (~value >> 9) & 1);    /*TRX*/
 +                    s->stat |= nack << 1;        /* NACK */
 +                    s->control &= ~(1 << 0);     /* STT */
 +                    s->fifolen = 0;
 +                    if (nack)
 +                        s->control &= ~(1 << 1); /* STP */
 +                    else {
 +                        s->count_cur = s->count;
 +                        omap_i2c_fifo_run(s);
 +                    }
 +                    omap_i2c_interrupts_update(s);
 +                } else if (value & 2) { /* STP, but not STT */
 +                    i2c_end_transfer(s->bus);
 +                    s->control &= ~0x0602;     /* MST | TRX | STP */
 +                    s->count_cur = s->count;
 +                }
 +            }
              break;
 -        }
 -        if ((value & (1 << 15)) && value & (1 << 8)) {                /* XA */
 -            fprintf(stderr, "%s: 10-bit addressing mode not supported\n",
 -                            __FUNCTION__);
 +        case 0x28: /* I2C_OA / I2C_OA0 */
 +            TRACE("OA0 = %04x", value);
 +            s->own_addr[0] = value & (s->revision < OMAP3_INTR_REV 
 +                                      ? 0x3ff : 0xe3ff);
-             i2c_set_slave_address(&s->slave[0], 
++            /*i2c_set_slave_address(&s->slave[0], 
 +                                  value & (s->revision >= OMAP3_INTR_REV 
 +                                           && (s->control & 0x80) 
-                                            ? 0x3ff: 0x7f));
++                                           ? 0x3ff: 0x7f));*/
              break;
 -        }
 -        if ((value & (1 << 15)) && value & (1 << 0)) {                /* STT */
 -            nack = !!i2c_start_transfer(s->bus, s->addr[1],   /* SA */
 -                            (~value >> 9) & 1);                       /* TRX */
 -            s->stat |= nack << 1;                             /* NACK */
 -            s->control &= ~(1 << 0);                          /* STT */
 -            s->fifo = 0;
 -            if (nack)
 -                s->control &= ~(1 << 1);                      /* STP */
 +        case 0x2c: /* I2C_SA */
 +            TRACE("SA = %04x", value);
 +            s->slave_addr = value & 0x3ff;
 +            break;
 +        case 0x30: /* I2C_PSC */
 +            s->divider = value;
 +            break;
 +        case 0x34: /* I2C_SCLL */
 +            s->times[0] = value & (s->revision < OMAP3_INTR_REV 
 +                                   ? 0xff : 0xffff);
 +            break;
 +        case 0x38: /* I2C_SCLH */
 +            s->times[1] = value & (s->revision < OMAP3_INTR_REV
 +                                   ? 0xff : 0xffff);
 +            break;
 +        case 0x3c: /* I2C_SYSTEST */
 +            value &= s->revision < OMAP3_INTR_REV ? 0xf805 : 0xf815;
 +            if ((value & (1 << 15))) { /* ST_EN */
 +                fprintf(stderr, "%s: System Test not supported\n",
 +                        __FUNCTION__);
 +                s->test = (s->test & 0x0a) | value;
 +            } else
 +                s->test = (s->test & 0x1f) | (value & 0xf800);
 +            if (value & (1 << 11)) /* SBB */
 +                if (s->revision >= OMAP2_INTR_REV) {
 +                    s->stat |= 0x3f;
 +                    if (s->revision >= OMAP3_INTR_REV)
 +                        s->stat |= 0x600;
 +                    omap_i2c_interrupts_update(s);
 +                }
 +            break;
 +        case 0x44: /* I2C_OA1 */
 +        case 0x48: /* I2C_OA2 */
 +        case 0x4c: /* I2C_OA3 */
 +            if (s->revision < OMAP3_INTR_REV)
 +                OMAP_BAD_REG(addr);
              else {
 -                s->count_cur = s->count;
 -                omap_i2c_fifo_run(s);
 +                addr = (addr >> 2) & 3;
 +                TRACE("OA%d = %04x", (int)addr, value);
 +                s->own_addr[addr] = value & 0x3ff;
-                 i2c_set_slave_address(&s->slave[addr], 
++                /*i2c_set_slave_address(&s->slave[addr], 
 +                                      value & ((s->control & (0x80 >> addr)) 
-                                                ? 0x3ff: 0x7f));
++                                               ? 0x3ff: 0x7f));*/
              }
 -            omap_i2c_interrupts_update(s);
 -        }
 -        break;
 -
 -    case 0x28:        /* I2C_OA */
 -        s->addr[0] = value & 0x3ff;
 -        break;
 -
 -    case 0x2c:        /* I2C_SA */
 -        s->addr[1] = value & 0x3ff;
 -        break;
 -
 -    case 0x30:        /* I2C_PSC */
 -        s->divider = value;
 -        break;
 -
 -    case 0x34:        /* I2C_SCLL */
 -        s->times[0] = value;
 -        break;
 -
 -    case 0x38:        /* I2C_SCLH */
 -        s->times[1] = value;
 -        break;
 -
 -    case 0x3c:        /* I2C_SYSTEST */
 -        s->test = value & 0xf80f;
 -        if (value & (1 << 11))                                        /* SBB */
 -            if (s->revision >= OMAP2_INTR_REV) {
 -                s->stat |= 0x3f;
 -                omap_i2c_interrupts_update(s);
 +            break;
 +        case 0x54: /* I2C_SBLOCK */
 +            if (s->revision < OMAP3_INTR_REV)
 +                OMAP_BAD_REG(addr);
 +            else {
 +                s->sblock = value & 0x0f;
              }
 -        if (value & (1 << 15))                                        /* ST_EN */
 -            fprintf(stderr, "%s: System Test not supported\n", __FUNCTION__);
 -        break;
 -
 -    default:
 -        OMAP_BAD_REG(addr);
 -        return;
 +            break;
 +        default:
 +            OMAP_BAD_REG(addr);
 +            break;
      }
  }
  
@@@ -721,26 -433,13 +645,20 @@@ static struct omap_i2c_s *omap_i2c_comm
      s->irq = irq;
      s->drq[0] = dma[0];
      s->drq[1] = dma[1];
-     s->slave[0].event = s->slave[1].event = s->slave[2].event =
-         s->slave[3].event = omap_i2c_event;
-     s->slave[0].recv = s->slave[1].recv = s->slave[2].recv =
-         s->slave[3].recv = omap_i2c_rx;
-     s->slave[0].send = s->slave[1].send = s->slave[2].send =
-         s->slave[3].send = omap_i2c_tx;
-     s->bus = i2c_init_bus();
+     s->bus = i2c_init_bus(NULL, "i2c");
 +    s->fifosize = fifosize;
      omap_i2c_reset(s);
 +    return s;
 +}
  
 -    iomemtype = cpu_register_io_memory(0, omap_i2c_readfn,
 -                    omap_i2c_writefn, s);
 -    cpu_register_physical_memory(base, 0x800, iomemtype);
 +struct omap_i2c_s *omap_i2c_init(target_phys_addr_t base,
 +                qemu_irq irq, qemu_irq *dma, omap_clk clk)
 +{
 +    struct omap_i2c_s *s = omap_i2c_common_init(0x11, 4, irq, dma);
  
 +    cpu_register_physical_memory(base, 0x800,
 +                                 cpu_register_io_memory(0, omap_i2c_readfn,
 +                                                        omap_i2c_writefn, s));
      return s;
  }
  
diff --cc hw/onenand.c
@@@ -130,87 -129,8 +130,87 @@@ static void onenand_intr_update(OneNAND
      qemu_set_irq(s->intr, ((s->intstatus >> 15) ^ (~s->config[0] >> 6)) & 1);
  }
  
 +static void onenand_save_state(QEMUFile *f, void *opaque)
 +{
-     struct onenand_s *s = (struct onenand_s *)opaque;
++    OneNANDState *s = (OneNANDState *)opaque;
 +    int i;
 +    
 +    if (s->current == s->otp)
 +        qemu_put_byte(f, 1);
 +    else if (s->current == s->image)
 +        qemu_put_byte(f, 2);
 +    else
 +        qemu_put_byte(f, 0);
 +    qemu_put_sbe32(f, s->cycle);
 +    qemu_put_sbe32(f, s->otpmode);
 +    for (i = 0; i < 8; i++) {
 +        qemu_put_be16(f, s->addr[i]);
 +        qemu_put_be16(f, s->unladdr[i]);
 +    }
 +    qemu_put_sbe32(f, s->bufaddr);
 +    qemu_put_sbe32(f, s->count);
 +    qemu_put_be16(f, s->command);
 +    qemu_put_be16(f, s->config[0]);
 +    qemu_put_be16(f, s->config[1]);
 +    qemu_put_be16(f, s->status);
 +    qemu_put_be16(f, s->intstatus);
 +    qemu_put_be16(f, s->wpstatus);
 +    qemu_put_sbe32(f, s->secs_cur);
 +    qemu_put_buffer(f, s->blockwp, s->blocks);
 +    qemu_put_byte(f, s->ecc.cp);
 +    qemu_put_be16(f, s->ecc.lp[0]);
 +    qemu_put_be16(f, s->ecc.lp[1]);
 +    qemu_put_be16(f, s->ecc.count);
 +    qemu_put_buffer(f, s->otp, (64 + 2) << PAGE_SHIFT);
 +}
 +
 +static int onenand_load_state(QEMUFile *f, void *opaque, int version_id)
 +{
-     struct onenand_s *s = (struct onenand_s *)opaque;
++    OneNANDState *s = (OneNANDState *)opaque;
 +    int i;
 +    
 +    if (version_id)
 +        return -EINVAL;
 +    
 +    switch (qemu_get_byte(f)) {
 +        case 1:
 +            s->current = s->otp;
 +            break;
 +        case 2:
 +            s->current = s->image;
 +            break;
 +        default:
 +            break;
 +    }
 +    s->cycle = qemu_get_sbe32(f);
 +    s->otpmode = qemu_get_sbe32(f);
 +    for (i = 0; i < 8; i++) {
 +        s->addr[i] = qemu_get_be16(f);
 +        s->unladdr[i] = qemu_get_be16(f);
 +    }
 +    s->bufaddr = qemu_get_sbe32(f);
 +    s->count = qemu_get_sbe32(f);
 +    s->command = qemu_get_be16(f);
 +    s->config[0] = qemu_get_be16(f);
 +    s->config[1] = qemu_get_be16(f);
 +    s->status = qemu_get_be16(f);
 +    s->intstatus = qemu_get_be16(f);
 +    s->wpstatus = qemu_get_be16(f);
 +    s->secs_cur = qemu_get_sbe32(f);
 +    qemu_get_buffer(f, s->blockwp, s->blocks);
 +    s->ecc.cp = qemu_get_byte(f);
 +    s->ecc.lp[0] = qemu_get_be16(f);
 +    s->ecc.lp[1] = qemu_get_be16(f);
 +    s->ecc.count = qemu_get_be16(f);
 +    qemu_get_buffer(f, s->otp, (64 + 2) << PAGE_SHIFT);
 +    
 +    onenand_intr_update(s);
 +    
 +    return 0;
 +}
 +
  /* Hot reset (Reset OneNAND command) or warm reset (RP pin low) */
- static void onenand_reset(struct onenand_s *s, int cold)
+ static void onenand_reset(OneNANDState *s, int cold)
  {
      memset(&s->addr, 0, sizeof(s->addr));
      s->command = 0;
diff --cc hw/sd.c
Simple merge
diff --cc hw/smc91c111.c
@@@ -691,78 -690,6 +690,73 @@@ static CPUWriteMemoryFunc *smc91c111_wr
      smc91c111_writel
  };
  
- int smc91c111_iomemtype(void *opaque) {
-     smc91c111_state *s=(smc91c111_state *) opaque;
-     return s->mmio_index;
- }
 +static void smc91c111_save_state(QEMUFile *f, void *opaque)
 +{
 +    smc91c111_state *s = (smc91c111_state *)opaque;
 +    int i;
 +    
 +    qemu_put_be16(f, s->tcr);
 +    qemu_put_be16(f, s->rcr);
 +    qemu_put_be16(f, s->cr);
 +    qemu_put_be16(f, s->ctr);
 +    qemu_put_be16(f, s->gpr);
 +    qemu_put_be16(f, s->ptr);
 +    qemu_put_be16(f, s->ercv);
 +    qemu_put_sbe32(f, s->bank);
 +    qemu_put_sbe32(f, s->packet_num);
 +    qemu_put_sbe32(f, s->tx_alloc);
 +    qemu_put_sbe32(f, s->allocated);
 +    qemu_put_sbe32(f, s->tx_fifo_len);
 +    qemu_put_sbe32(f, s->rx_fifo_len);
 +    qemu_put_sbe32(f, s->tx_fifo_done_len);
 +    qemu_put_byte(f, s->int_level);
 +    qemu_put_byte(f, s->int_mask);
 +    qemu_put_buffer(f, s->macaddr, sizeof(s->macaddr));
 +    for (i = 0; i < NUM_PACKETS; i++) {
 +        qemu_put_sbe32(f, s->tx_fifo[i]);
 +        qemu_put_sbe32(f, s->rx_fifo[i]);
 +        qemu_put_sbe32(f, s->tx_fifo_done[i]);
 +        qemu_put_buffer(f, s->data[i], sizeof(s->data[i]));
 +    }
 +}
 +
 +static int smc91c111_load_state(QEMUFile *f, void *opaque, int version_id)
 +{
 +    smc91c111_state *s = (smc91c111_state *)opaque;
 +    int i;
 +    
 +    if (version_id)
 +        return -EINVAL;
 +    
 +    s->tcr = qemu_get_be16(f);
 +    s->rcr = qemu_get_be16(f);
 +    s->cr = qemu_get_be16(f);
 +    s->ctr = qemu_get_be16(f);
 +    s->gpr = qemu_get_be16(f);
 +    s->ptr = qemu_get_be16(f);
 +    s->ercv = qemu_get_be16(f);
 +    s->bank = qemu_get_sbe32(f);
 +    s->packet_num = qemu_get_sbe32(f);
 +    s->tx_alloc = qemu_get_sbe32(f);
 +    s->allocated = qemu_get_sbe32(f);
 +    s->tx_fifo_len = qemu_get_sbe32(f);
 +    s->rx_fifo_len = qemu_get_sbe32(f);
 +    s->tx_fifo_done_len = qemu_get_sbe32(f);
 +    s->int_level = qemu_get_byte(f);
 +    s->int_mask = qemu_get_byte(f);
 +    qemu_get_buffer(f, s->macaddr, sizeof(s->macaddr));
 +    for (i = 0; i < NUM_PACKETS; i++) {
 +        s->tx_fifo[i] = qemu_get_sbe32(f);
 +        s->rx_fifo[i] = qemu_get_sbe32(f);
 +        s->tx_fifo_done[i] = qemu_get_sbe32(f);
 +        qemu_get_buffer(f, s->data[i], sizeof(s->data[i]));
 +    }
 +    
 +    smc91c111_update(s);
 +    
 +    return 0;
 +}
 +
  static void smc91c111_cleanup(VLANClientState *vc)
  {
      smc91c111_state *s = vc->opaque;
@@@ -792,7 -715,27 +782,51 @@@ static void smc91c111_init1(SysBusDevic
                                   smc91c111_cleanup, s);
      qemu_format_nic_info_str(s->vc, s->macaddr);
      /* ??? Save/restore.  */
 +    register_savevm("smc91c111", -1, 0,
 +                    smc91c111_save_state, smc91c111_load_state, s);
++    /*return s;*/
+ }
+ static void smc91c111_register_devices(void)
+ {
+     sysbus_register_dev("smc91c111", sizeof(smc91c111_state), smc91c111_init1);
+ }
+ /* Legacy helper function.  Should go away when machine config files are
+    implemented.  */
+ void smc91c111_init(NICInfo *nd, uint32_t base, qemu_irq irq)
+ {
+     DeviceState *dev;
+     SysBusDevice *s;
+     qemu_check_nic_model(nd, "smc91c111");
+     dev = qdev_create(NULL, "smc91c111");
+     qdev_set_netdev(dev, nd);
+     qdev_init(dev);
+     s = sysbus_from_qdev(dev);
+     sysbus_mmio_map(s, 0, base);
+     sysbus_connect_irq(s, 0, irq);
+ }
++void *smc91c111_init_lite(NICInfo *nd, qemu_irq irq)
++{
++    DeviceState *dev;
++    SysBusDevice *s;
++    
++    qemu_check_nic_model(nd, "smc91c111");
++    dev = qdev_create(NULL, "smc91c111");
++    qdev_set_netdev(dev, nd);
++    qdev_init(dev);
++    s = sysbus_from_qdev(dev);
++    //sysbus_mmio_map(s, 0, base);
++    sysbus_connect_irq(s, 0, irq);
 +    return s;
 +}
++
++int smc91c111_iomemtype(void *opaque)
++{
++    SysBusDevice *s = (SysBusDevice *)opaque;
++    return (FROM_SYSBUS(smc91c111_state, s))->mmio_index;
++}
++
+ device_init(smc91c111_register_devices)
diff --cc hw/tsc2005.c
@@@ -226,9 -226,28 +226,9 @@@ static void tsc2005_write(TSC2005State 
  }
  
  /* This handles most of the chip's logic.  */
- static void tsc2005_pin_update(struct tsc2005_state_s *s)
+ static void tsc2005_pin_update(TSC2005State *s)
  {
      int64_t expires;
 -    int pin_state;
 -
 -    switch (s->pin_func) {
 -    case 0:
 -        pin_state = !s->pressure && !!s->dav;
 -        break;
 -    case 1:
 -    case 3:
 -    default:
 -        pin_state = !s->dav;
 -        break;
 -    case 2:
 -        pin_state = !s->pressure;
 -    }
 -
 -    if (pin_state != s->irq) {
 -        s->irq = pin_state;
 -        qemu_set_irq(s->pint, s->irq);
 -    }
  
      switch (s->nextfunction) {
      case TSC_MODE_XYZ_SCAN:
@@@ -380,8 -399,7 +380,8 @@@ uint32_t tsc2005_txrx(void *opaque, uin
  
  static void tsc2005_timer_tick(void *opaque)
  {
-     struct tsc2005_state_s *s = opaque;
+     TSC2005State *s = opaque;
 +      int pin_state;
  
      /* Timer ticked -- a set of conversions has been finished.  */
  
diff --cc hw/tusb6010.c
  #include "irq.h"
  #include "devices.h"
  
 +#define OMAP3_HSUSB_DEBUG
 +
 +#ifdef OMAP3_HSUSB_DEBUG
 +#define TRACE(fmt,...) fprintf(stderr, "%s: " fmt "\n", __FUNCTION__, ##__VA_ARGS__)
 +#else
 +#define TRACE(...)
 +#endif
 +
 +
- struct tusb_s {
+ struct TUSBState {
      int iomemtype[2];
      qemu_irq irq;
-     struct musb_s *musb;
+     MUSBState *musb;
      QEMUTimer *otg_timer;
      QEMUTimer *pwr_timer;
  
@@@ -693,9 -683,8 +692,9 @@@ static void tusb_power_tick(void *opaqu
  
  static void tusb_musb_core_intr(void *opaque, int source, int level)
  {
-     struct tusb_s *s = (struct tusb_s *) opaque;
+     TUSBState *s = (TUSBState *) opaque;
      uint16_t otg_status = s->otg_status;
 +    TRACE("intr 0x%08x, 0x%08x, 0x%08x", source, level, musb_core_intr_get(s->musb));
  
      switch (source) {
      case musb_set_vbus:
diff --cc hw/twl4030.c
index a60b438,0000000..9be8c21
mode 100644,000000..100644
--- /dev/null
@@@ -1,947 -1,0 +1,888 @@@
 +/*
 + * TI TWL4030 emulation
 + *
 + * Copyright (C) 2008 yajin<yajin@vm-kernel.org>
 + * Copyright (C) 2009 Nokia Corporation
 + *
 + * Register implementation based on TPS65950 ES1.0 specification.
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License as
 + * published by the Free Software Foundation; either version 2 or
 + * (at your option) version 3 of the License.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 + * MA 02111-1307 USA
 + */
 + 
 +#include "hw.h"
 +#include "qemu-timer.h"
 +#include "i2c.h"
 +#include "sysemu.h"
 +#include "console.h"
 +#include "cpu-all.h"
 +
 +//#define VERBOSE 1
 +
 +#ifdef VERBOSE
 +#define TRACE(fmt, ...) fprintf(stderr, "%s: " fmt "\n", __FUNCTION__, ##__VA_ARGS__)
 +#else
 +#define TRACE(...)
 +#endif
 +
- struct twl4030_i2c_s {
++typedef struct TWL4030State TWL4030State;
++typedef struct TWL4030NodeState TWL4030NodeState;
++
++typedef uint8_t (*twl4030_read_func)(TWL4030NodeState *s,
++                                     uint8_t addr);
++typedef void (*twl4030_write_func)(TWL4030NodeState *s,
++                                   uint8_t addr, uint8_t value);
++
++struct TWL4030NodeState {
 +    i2c_slave i2c;
 +    int firstbyte;
 +    uint8_t reg;
-     qemu_irq irq;
++
++    twl4030_read_func read_func;
++    twl4030_write_func write_func;
++    TWL4030State *twl4030;
++
 +    uint8 reg_data[256];
-     struct twl4030_s *twl4030;
 +};
 +
- struct twl4030_s {
-     struct twl4030_i2c_s *i2c[5];
-     
++struct TWL4030State {
++    qemu_irq irq;
++
 +    int key_cfg;
 +    int key_tst;
 +    
++    TWL4030NodeState *i2c[5];
++    
 +    uint8_t seq_mem[64][4]; /* power-management sequencing memory */
 +};
 +
 +static const uint8_t addr_48_reset_values[256] = {
 +    0x51, 0x04, 0x02, 0xc0, 0x41, 0x41, 0x41, 0x10, /* 0x00...0x07 */
 +    0x10, 0x10, 0x06, 0x06, 0x06, 0x1f, 0x1f, 0x1f, /* 0x08...0x0f */
 +    0x1f, 0x1f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10...0x17 */
 +    0x00, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, /* 0x18...0x1f */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0a, 0x03, /* 0x20...0x27 */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28...0x2f */
 +    0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x00, 0x00, /* 0x30...0x37 */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38...0x3f */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40...0x47 */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48...0x4f */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50...0x57 */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58...0x5f */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60...0x67 */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68...0x6f */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70...0x77 */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78...0x7f */
 +    0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, /* 0x80...0x87 */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88...0x8f */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90...0x97 */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98...0x9f */
 +    0x00, 0x10, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* 0xa0...0xa7 */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8...0xaf */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0...0xb7 */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8...0xb8 */
 +    0xa0, 0xa0, 0x64, 0x7f, 0x6c, 0x75, 0x64, 0x20, /* 0xc0...0xc7 */
 +    0x01, 0x17, 0x01, 0x02, 0x00, 0x36, 0x44, 0x07, /* 0xc8...0xcf */
 +    0x3b, 0x17, 0x6b, 0x04, 0x00, 0x00, 0x00, 0x00, /* 0xd0...0xd7 */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8...0xdf */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0...0xe7 */
 +    0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, /* 0xe8...0xef */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0...0xf7 */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00  /* 0xf8...0xff */
 +};
 +
 +static const uint8_t addr_49_reset_values[256] = {
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00...0x07 */
 +    0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, /* 0x08...0x0f */
 +    0x3f, 0x3f, 0x3f, 0x3f, 0x25, 0x00, 0x00, 0x00, /* 0x10...0x17 */
 +    0x00, 0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x55, /* 0x18...0x1f */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20...0x27 */
 +    0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, /* 0x28...0x2f */
 +    0x13, 0x00, 0x00, 0x00, 0x00, 0x79, 0x11, 0x00, /* 0x30...0x37 */
 +    0x00, 0x00, 0x06, 0x00, 0x44, 0x69, 0x00, 0x00, /* 0x38...0x3f */
 +    0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, /* 0x40...0x47 */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48...0x4f */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50...0x57 */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58...0x5f */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60...0x67 */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68...0x6f */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70...0x77 */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78...0x7f */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80...0x87 */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88...0x8f */
 +    0x00, 0x90, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, /* 0x90...0x97 */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98...0x9f */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0...0xa7 */
 +    0x00, 0x00, 0x04, 0x00, 0x55, 0x01, 0x55, 0x05, /* 0xa8...0xaf */
 +    0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x03, 0x00, /* 0xb0...0xb7 */
 +    0x00, 0x00, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, /* 0xb8...0xbf */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, /* 0xc0...0xc7 */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8...0xcf */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0...0xd7 */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8...0xdf */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0...0xe7 */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8...0xef */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0...0xf7 */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8...0xff */
 +};
 +
 +static const uint8_t addr_4a_reset_values[256] = {
 +    0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00...0x07 */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08...0x0f */
 +    0xc0, 0x8c, 0xde, 0xde, 0x00, 0x00, 0x00, 0x00, /* 0x10...0x17 */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18...0x1f */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20...0x27 */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28...0x2f */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30...0x37 */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38...0x3f */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40...0x47 */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48...0x4f */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50...0x57 */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58...0x5f */
 +    0x00, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x55, 0x07, /* 0x60...0x67 */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68...0x6f */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70...0x77 */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78...0x7f */
 +    0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, /* 0x80...0x87 */
 +    0x00, 0x68, 0x9b, 0x86, 0x48, 0x2a, 0x07, 0x28, /* 0x88...0x8f */
 +    0x09, 0x69, 0x90, 0x00, 0x2a, 0x00, 0x02, 0x00, /* 0x90...0x97 */
 +    0x10, 0xcd, 0x02, 0x68, 0x03, 0x00, 0x00, 0x00, /* 0x98...0x9f */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0...0xa7 */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8...0xaf */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0...0xb7 */
 +    0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xff, /* 0xb8...0xbf */
 +    0x0f, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x01, 0x00, /* 0xc0...0xc7 */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8...0xcf */
 +    0x00, 0x00, 0x03, 0x00, 0x00, 0xe0, 0x00, 0x00, /* 0xd0...0xd7 */
 +    0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8...0xdf */
 +    0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0f, 0x00, /* 0xe0...0xe7 */
 +    0x55, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8...0xef */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0...0xf7 */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  /* 0xf8...0xff */
 +};
 +
 +static const uint8_t addr_4b_reset_values[256] = {
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00...0x07 */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08...0x0f */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10...0x17 */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0x18...0x1f */
 +    0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, /* 0x20...0x27 */
 +    0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x60, 0x00, /* 0x28...0x2f */
 +    0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0xbf, 0xbf, /* 0x30...0x37 */
 +    0xbf, 0xab, 0x00, 0x08, 0x3f, 0x15, 0x40, 0x0e, /* 0x38...0x3f */
 +    0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40...0x47 */
 +    0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, /* 0x48...0x4f */
 +    0x00, 0x02, 0x00, 0x04, 0x0d, 0x00, 0x00, 0x00, /* 0x50...0x57 */
 +    0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58...0x5f */
 +    0x00, 0x00, 0x2f, 0x18, 0x0f, 0x08, 0x0f, 0x08, /* 0x60...0x67 */
 +    0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68...0x6f */
 +    0x00, 0x00, 0x00, 0x00, 0x08, 0x02, 0x80, 0x03, /* 0x70...0x77 */
 +    0x08, 0x09, 0x00, 0x00, 0x08, 0x03, 0x80, 0x03, /* 0x78...0x7f */
 +    0x08, 0x02, 0x00, 0x00, 0x08, 0x00, 0x80, 0x03, /* 0x80...0x87 */
 +    0x08, 0x08, 0x20, 0x00, 0x00, 0x02, 0x80, 0x04, /* 0x88...0x8f */
 +    0x08, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, /* 0x90...0x97 */
 +    0x08, 0x02, 0xe0, 0x01, 0x08, 0x00, 0xe0, 0x00, /* 0x98...0x9f */
 +    0x08, 0x01, 0xe0, 0x01, 0x08, 0x04, 0xe0, 0x03, /* 0xa0...0xa7 */
 +    0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8...0xaf */
 +    0x20, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0...0xb7 */
 +    0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, /* 0xb8...0xbf */
 +    0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, /* 0xc0...0xc7 */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, /* 0xc8...0xcf */
 +    0x00, 0x08, 0xe0, 0x00, 0x08, 0x00, 0x00, 0x00, /* 0xd0...0xd7 */
 +    0x14, 0x08, 0xe0, 0x02, 0x08, 0xe0, 0x00, 0x08, /* 0xd8...0xdf */
 +    0xe0, 0x05, 0x08, 0xe0, 0x06, 0x08, 0xe0, 0x00, /* 0xe0...0xe7 */
 +    0x08, 0xe0, 0x00, 0x08, 0xe0, 0x06, 0x06, 0xe0, /* 0xe8...0xef */
 +    0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0...0xf7 */
 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  /* 0xf8...0xff */
 +};
 +
- static uint8_t twl4030_48_read(void *opaque, uint8_t addr)
++static uint8_t twl4030_48_read(TWL4030NodeState *s, uint8_t addr)
 +{
-     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) opaque;
-       
 +    TRACE("addr=0x%02x", addr);
 +    switch (addr) {
 +        case 0x00: /* VENDOR_ID_LO */
 +        case 0x01: /* VENDOR_ID_HI */
 +        case 0x02: /* PRODUCT_ID_LO */
 +        case 0x03: /* PRODUCT_ID_HI */
 +            return s->reg_data[addr];
 +        case 0x04: /* FUNC_CTRL */
 +        case 0x05: /* FUNC_CRTL_SET */
 +        case 0x06: /* FUNC_CRTL_CLR */
 +            return s->reg_data[0x04];
 +        case 0x07: /* IFC_CTRL */
 +        case 0x08: /* IFC_CRTL_SET */
 +        case 0x09: /* IFC_CRTL_CLR */
 +            return s->reg_data[0x07];
 +        case 0xac: /* POWER_CTRL */
 +        case 0xad: /* POWER_SET */
 +        case 0xae: /* POWER_CLR */
 +            return s->reg_data[0xac];
 +        case 0xfd: /* PHY_PWR_CTRL */
 +        case 0xfe: /* PHY_CLK_CTRL */
 +            return s->reg_data[addr];
 +        case 0xff: /* PHY_CLK_CTRL_STS */
 +            if (s->reg_data[0xfd] & 1) /* PHY_PWR_CTRL */
 +                return 0;
 +            if (s->reg_data[0xfe] & 1) /* REQ_PHY_DPLL_CLK */
 +                return 1;
 +            return (s->reg_data[0x04] >> 6) & 1; /* SUSPENDM */
 +        default:
-             fprintf(stderr, "%s: unknown register 0x%02x pc 0x%x\n",
-                     __FUNCTION__, addr, cpu_single_env->regs[15]);
++            fprintf(stderr, "%s: unknown register 0x%02x\n",
++                    __FUNCTION__, addr);
 +            break;
 +    }
 +    return 0;
 +}
 +
- static void twl4030_48_write(void *opaque, uint8_t addr, uint8_t value)
++static void twl4030_48_write(TWL4030NodeState *s, uint8_t addr, uint8_t value)
 +{
-     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) opaque;
-       
 +    TRACE("addr=0x%02x, value=0x%02x", addr, value);
 +    switch (addr) {
 +        case 0x04: /* FUNC_CTRL */
 +            s->reg_data[0x04] = value & 0x7f;
 +            break;
 +        case 0x05: /* FUNC_CRTL_SET */
 +            s->reg_data[0x04] = (s->reg_data[0x04] | value) & 0x7f;
 +            break;
 +        case 0x06: /* FUNC_CTRL_CLEAR */
 +            s->reg_data[0x04] = (s->reg_data[0x04] & ~value) & 0x7f;
 +            break;
 +        case 0x07: /* IFC_CTRL */
 +            s->reg_data[0x07] = value & 0x9e;
 +            break;
 +        case 0x08: /* IFC_CRTL_SET */
 +            s->reg_data[0x07] = (s->reg_data[0x07] | value) & 0x9e;
 +            break;
 +        case 0x09: /* IFC_CRTL_CLEAR */
 +            s->reg_data[0x07] = (s->reg_data[0x07] & ~value) & 0x9e;
 +            break;
 +        case 0xa1: /* CARKIT_SM_CTRL */
 +            s->reg_data[0xa1] = value & 0x3f;
 +            break;
 +        case 0xa2: /* CARKIT_SM_CTRL_SET */
 +            s->reg_data[0xa1] = (s->reg_data[0xa1] | value) & 0x3f;
 +            break;
 +        case 0xa3: /* CARKIT_SM_CTRL_CLR */
 +            s->reg_data[0xa1] = (s->reg_data[0xa1] & ~value) & 0x3f;
 +            break;
 +        case 0xac: /* POWER_CTRL */
 +            s->reg_data[0xac] = value & 0x20;
 +            break;
 +        case 0xad: /* POWER_SET */
 +            s->reg_data[0xac] = (s->reg_data[0xac] | value) & 0x20;
 +            break;
 +        case 0xae: /* POWER_CLEAR */
 +            s->reg_data[0xac] = (s->reg_data[0xac] & ~value) & 0x20;
 +            break;
 +        case 0xbb: /* CARKIT_ANA_CTRL */
 +            s->reg_data[0xbb] = value;
 +            break;
 +        case 0xbc: /* CARKIT_ANA_CTRL_SET */
 +            s->reg_data[0xbb] |= value;
 +            break;
 +        case 0xbd: /* CARKIT_ANA_CTRL_CLR */
 +            s->reg_data[0xbb] &= ~value;
 +            break;
 +        case 0xfd: /* PHY_PWR_CTRL */
 +            s->reg_data[addr] = value & 0x1;
 +            break;
 +        case 0xfe: /* PHY_CLK_CTRL */
 +            s->reg_data[addr] = value & 0x7;
 +            break;
 +        default:
-             fprintf(stderr, "%s: unknown register 0x%02x pc 0x%x\n",
-                     __FUNCTION__, addr, cpu_single_env->regs[15]);
++            fprintf(stderr, "%s: unknown register 0x%02x\n",
++                    __FUNCTION__, addr);
 +                      break;
 +    }
 +}
 +
- static int twl4030_48_tx(i2c_slave *i2c, uint8_t data)
- {
-     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
-     /* Interpret register address byte */
-     if (s->firstbyte) {
-         s->reg = data;
-         s->firstbyte = 0;
-     } else
-         twl4030_48_write(s, s->reg++, data);
-       
-     return 0;
- }
- static int twl4030_48_rx(i2c_slave *i2c)
- {
-     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
-       
-     return twl4030_48_read(s, s->reg++);
- }
- static void twl4030_48_reset(i2c_slave *i2c)
- {
-     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
-     s->reg = 0x00;
-     memcpy(s->reg_data, addr_48_reset_values, 256);
- }
- static void twl4030_48_event(i2c_slave *i2c, enum i2c_event event)
- {
-     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
-     
-     if (event == I2C_START_SEND)
-         s->firstbyte = 1;
- }
- static uint8_t twl4030_49_read(void *opaque, uint8_t addr)
++static uint8_t twl4030_49_read(TWL4030NodeState *s, uint8_t addr)
 +{
-     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) opaque;
 +    TRACE("addr=0x%02x", addr);
 +    switch (addr) {
 +        /* AUDIO_VOICE region */
 +        case 0x01 ... 0x49:
 +            return s->reg_data[addr];
 +        /* Test region */
 +        case 0x4c ... 0x60:
 +            return s->reg_data[addr];
 +        /* PIH region */
 +        case 0x81: /* PIH_ISR_P1 */
 +        case 0x82: /* PIH_ISR_P2 */
 +        case 0x83: /* PIH_SIR */
 +            return s->reg_data[addr];
 +        /* INTBR region */
 +        case 0x85 ... 0x97:
 +            return s->reg_data[addr];
 +        /* GPIO region */
 +        case 0x98 ... 0xc5:
 +            return s->reg_data[addr];
 +        default:
-             fprintf(stderr, "%s: unknown register 0x%02x pc 0x%x\n",
-                     __FUNCTION__, addr, cpu_single_env->regs[15]);
++            fprintf(stderr, "%s: unknown register 0x%02x\n",
++                    __FUNCTION__, addr);
 +                      break;
 +    }
 +    return 0;
 +}
 +
- static void twl4030_49_write(void *opaque, uint8_t addr, uint8_t value)
++static void twl4030_49_write(TWL4030NodeState *s, uint8_t addr, uint8_t value)
 +{
-     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) opaque;
-       
 +    TRACE("addr=0x%02x, value=0x%02x", addr, value);
 +    switch (addr) {
 +        /* AUDIO_VOICE region */
 +        case 0x01 ... 0x49:
 +            s->reg_data[addr] = value;
 +            break;
 +        /* Test region */
 +        case 0x4c ... 0x59:
 +            s->reg_data[addr] = value;
 +            break;
 +        case 0x5a ... 0x60:
 +            /* read-only, ignore */
 +            break;
 +        /* PIH region */
 +        case 0x81: /* PIH_ISR_P1 */
 +        case 0x82: /* PIH_ISR_P2 */
 +        case 0x83: /* PIH_SIR */
 +            s->reg_data[addr] = value;
 +            break;
 +        /* INTBR region */
 +        case 0x85 ... 0x90:
 +            /* read-only, ignore */
 +            break;
 +        case 0x91 ... 0x97:
 +            s->reg_data[addr] = value;
 +            break;
 +        /* GPIO region */
 +        case 0x98 ... 0x9a:
 +            /* read-only, ignore */
 +            break;
 +        case 0x9b ... 0xae:
 +            s->reg_data[addr] = value;
 +            break;
 +        case 0xaf: /* GPIOPUPDCTR5 */
 +            s->reg_data[addr] = value & 0x0f;
 +            break;
 +        case 0xb0 ... 0xb5:
 +            s->reg_data[addr] = value;
 +            break;
 +          case 0xb6: /* GPIO_IMR3A */
 +            s->reg_data[addr] = value & 0x03;
 +            break;
 +        case 0xb7 ... 0xc4:
 +            s->reg_data[addr] = value;
 +            break;
 +          case 0xc5: /* GPIO_SIH_CTRL */
 +            s->reg_data[addr] = value & 0x07;
 +            break;
 +        default:
-             fprintf(stderr, "%s: unknown register 0x%02x pc 0x%x\n",
-                     __FUNCTION__, addr, cpu_single_env->regs[15]);
++            fprintf(stderr, "%s: unknown register 0x%02x\n",
++                    __FUNCTION__, addr);
 +            break;
 +    }
 +}
 +
- static int twl4030_49_tx(i2c_slave *i2c, uint8_t data)
- {
-     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
-     /* Interpret register address byte */
-     if (s->firstbyte) {
-         s->reg = data;
-         s->firstbyte = 0;
-     } else
-         twl4030_49_write(s, s->reg++, data);
-       
-     return 0;
- }
- static int twl4030_49_rx(i2c_slave *i2c)
- {
-     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
-       
-     return twl4030_49_read(s, s->reg++);
- }
- static void twl4030_49_reset(i2c_slave *i2c)
++static uint8_t twl4030_4a_read(TWL4030NodeState *s, uint8_t addr)
 +{
-     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
-     s->reg = 0x00;
-     memcpy(s->reg_data, addr_49_reset_values, 256);
- }
- static void twl4030_49_event(i2c_slave *i2c, enum i2c_event event)
- {
-     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
-       
-     if (event == I2C_START_SEND)
-         s->firstbyte = 1;
- }
- static uint8_t twl4030_4a_read(void *opaque, uint8_t addr)
- {
-     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) opaque;
-       
 +    TRACE("addr=0x%02x", addr);
 +    switch (addr) {
 +        /* MADC region */
 +        case 0x00 ... 0x13:
 +        case 0x61 ... 0x67:
 +            return s->reg_data[addr];
 +        case 0x17 ... 0x36: /* RT conversion registers */
 +        case 0x37 ... 0x56: /* GP conversion registers */
 +        case 0x57 ... 0x60: /* BCI conversion registers */
 +            return (addr & 1) ? 0 : 0x60;
 +        /* MAIN_CHARGE region */
 +        case 0x74 ... 0xa6:
 +            return s->reg_data[addr];
 +        /* Interrupt region */
 +        case 0xb9 ... 0xc6:
 +            return s->reg_data[addr];
 +        /* KEYPAD region */
 +        case 0xd2 ... 0xe9:
 +            return s->reg_data[addr];
 +        /* LED region */
 +        case 0xee: /* LEDEN */
 +            return s->reg_data[addr];
 +        /* PWMA region */
 +        case 0xef: /* PWMAON */
 +        case 0xf0: /* PWMAOFF */
 +            return s->reg_data[addr];
 +        /* PWMB region */
 +        case 0xf1: /* PWMBON */
 +        case 0xf2: /* PWMBOFF */
 +            return s->reg_data[addr];
 +        /* PWM0 region */
 +        case 0xf8: /* PWM0ON */
 +        case 0xf9: /* PWM0OFF */
 +            return s->reg_data[addr];
 +        /* PWM1 region */
 +        case 0xfb: /* PWM1ON */
 +        case 0xfc: /* PWM1OFF */
 +            return s->reg_data[addr];
 +        default:
-               fprintf(stderr, "%s: unknown register 0x%02x pc 0x%x\n",
-                     __FUNCTION__, addr, cpu_single_env->regs[15] );
++              fprintf(stderr, "%s: unknown register 0x%02x\n",
++                    __FUNCTION__, addr);
 +            break;
 +    }
 +    return 0;
 +}
 +
- static void twl4030_4a_write(void *opaque, uint8_t addr, uint8_t value)
++static void twl4030_4a_write(TWL4030NodeState *s, uint8_t addr, uint8_t value)
 +{
-     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) opaque;
 +    TRACE("addr=0x%02x, value=0x%02x", addr, value);
 +    switch (addr) {
 +        case 0x00: /* CTRL1 */
 +            s->reg_data[addr] = value;
 +            break;
 +        case 0x06: /* SW1SELECT_LSB */
 +        case 0x07: /* SW1SELECT_MSB */
 +        case 0x08: /* SW1AVERAGE_LSB */
 +        case 0x09: /* SW1AVERAGE_MSB */
 +            s->reg_data[addr] = value;
 +            break;
 +        case 0x12: /* CTRL_SW1 */
 +            s->reg_data[addr] = 0xde;
 +            break;
 +        case 0x61: /* MADC_ISR1 */
 +            s->reg_data[addr] &= ~(value & 0x0f);
 +            break;
 +        case 0x62: /* MADC_IMR1 */
 +            s->reg_data[addr] = value & 0x0f;
 +            break;
 +        case 0x97: /* BCICTL1 */
 +            s->reg_data[addr] = value;
 +            break;
 +        case 0xb9: /* BCIISR1A */
 +            s->reg_data[addr] &= ~value;
 +            break;
 +        case 0xba: /* BCIISR2A */
 +            s->reg_data[addr] &= ~(value & 0x0f);
 +            break;
 +        case 0xbb: /* BCIIMR1A */
 +            s->reg_data[addr] = value;
 +            break;
 +        case 0xbc: /* BCIIMR2A */
 +            s->reg_data[addr] = value & 0x0f;
 +            break;
 +        case 0xd2: /* KEYP_CTRL_REG */
 +            s->reg_data[addr] = value & 0x7f;
 +            break;
 +        case 0xe4: /* KEYP_IMR1 */
 +            s->reg_data[addr] = value & 0x0f;
 +            break;
 +        case 0xe9: /* KEYP_SIH_CTRL */
 +            s->reg_data[addr] = value & 0x07;
 +            break;
 +        case 0xee: /* LEDEN */
 +            s->reg_data[addr] = value;
 +            TRACE("LEDA power=%s/enable=%s, LEDB power=%s/enable=%s",
 +                    value & 0x10 ? "on" : "off", value & 0x01 ? "yes" : "no",
 +                    value & 0x20 ? "on" : "off", value & 0x02 ? "yes" : "no");
 +            break;
 +        case 0xef: /* PWMAON */
 +        case 0xf8: /* PWM0ON */
 +        case 0xfb: /* PWM1ON */
 +            s->reg_data[addr] = value;
 +            break;
 +        case 0xf0: /* PWMAOFF */
 +        case 0xf9: /* PWM0OFF */
 +        case 0xfc: /* PWM1OFF */
 +            s->reg_data[addr] = value & 0x7f;
 +            break;
 +        default:
-               fprintf(stderr, "%s: unknown register 0x%02x pc 0x%x\n",
-                     __FUNCTION__, addr, cpu_single_env->regs[15]);
++              fprintf(stderr, "%s: unknown register 0x%02x\n",
++                    __FUNCTION__, addr);
 +            break;
 +    }
 +}
 +
- static int twl4030_4a_tx(i2c_slave *i2c, uint8_t data)
- {
-     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
-     /* Interpret register address byte */
-     if (s->firstbyte) {
-         s->reg = data;
-         s->firstbyte = 0;
-     } else
-         twl4030_4a_write(s, s->reg++, data);
-       
-     return 0;
- }
- static int twl4030_4a_rx(i2c_slave *i2c)
- {
-     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
-       
-     return twl4030_4a_read(s, s->reg++);
- }
- static void twl4030_4a_reset(i2c_slave *i2c)
++static uint8_t twl4030_4b_read(TWL4030NodeState *s, uint8_t addr)
 +{
-     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
-     s->reg = 0x00;
-     memcpy(s->reg_data, addr_4a_reset_values, 256);
- }
- static void twl4030_4a_event(i2c_slave *i2c, enum i2c_event event)
- {
-     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
-       
-     if (event == I2C_START_SEND)
-         s->firstbyte = 1;
- }
- static uint8_t twl4030_4b_read(void *opaque, uint8_t addr)
- {
-     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) opaque;
 +      TRACE("addr=0x%02x", addr);
 +    switch (addr) {
 +        /* SECURED_REG region */
 +        case 0x00 ... 0x13:
 +            return s->reg_data[addr];
 +        /* BACKUP_REG region */
 +        case 0x14 ... 0x1b:
 +            return s->reg_data[addr];
 +        /* RTC region */
 +        case 0x1c ... 0x2d:
 +            return s->reg_data[addr];
 +        /* INT region */
 +        case 0x2e ... 0x35:
 +            return s->reg_data[addr];
 +        /* PM_MASTER region */
 +        case 0x36 ... 0x44:
 +            return s->reg_data[addr];
 +        case 0x45: /* STS_HW_CONDITIONS - USB plugged, no VBUS -> host usb */
 +            return 0x4;
 +        case 0x46 ... 0x5a:
 +            return s->reg_data[addr];
 +        /* PM_RECEIVER region */
 +        case 0x5b ... 0xf1: 
 +            return s->reg_data[addr];
 +        default:
-               fprintf(stderr, "%s: unknown register 0x%02x pc 0x%x\n",
-                     __FUNCTION__, addr, cpu_single_env->regs[15] );
++              fprintf(stderr, "%s: unknown register 0x%02x\n",
++                    __FUNCTION__, addr);
 +            break;
 +    }
 +    return 0;
 +}
 +
 +
- static void twl4030_4b_write(void *opaque, uint8_t addr, uint8_t value)
++static void twl4030_4b_write(TWL4030NodeState *s, uint8_t addr, uint8_t value)
 +{
-     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) opaque;
 +    uint8_t seq_addr, seq_sub;
 +
 +      TRACE("addr=0x%02x, value=0x%02x", addr, value);
 +    switch (addr) {
 +        case 0x1c: /* SECONDS_REG */
 +        case 0x1d: /* MINUTES_REG */
 +        case 0x23: /* ALARM_SECONDS_REG */
 +        case 0x24: /* ALARM_MINUTES_REG */
 +            s->reg_data[addr] = value & 0x7f;
 +            break;
 +        case 0x1e: /* HOURS_REG */
 +        case 0x25: /* ALARM_HOURS_REG */
 +            s->reg_data[addr] = value & 0xbf;
 +            break;
 +        case 0x1f: /* DAYS_REG */
 +        case 0x26: /* ALARM_DAYS_REG */
 +            s->reg_data[addr] = value & 0x3f;
 +            break;
 +        case 0x20: /* MONTHS_REG */
 +        case 0x27: /* ALARM_MONTHS_REG */
 +            s->reg_data[addr] = value & 0x1f;
 +            break;
 +        case 0x21: /* YEARS_REG */
 +        case 0x28: /* ALARM_YEARS_REG */
 +            s->reg_data[addr] = value;
 +            break;
 +        case 0x22: /* WEEKS_REG */
 +            s->reg_data[addr] = value & 0x07;
 +            break;
 +        case 0x29: /* RTC_CTRL_REG */
 +            s->reg_data[addr] = value & 0x7f;
 +            break;
 +        case 0x2a: /* RTC_STATUS_REG */
 +            s->reg_data[addr] = value & 0xfe;
 +            break;
 +        case 0x2b: /* RTC_INTERRUPTS_REG */
 +            s->reg_data[addr] = value & 0x0f;
 +            break;
 +        case 0x2c: /* RTC_COMP_LSB_REG */
 +        case 0x2d: /* RTC_COMP_MSB_REG */
 +            s->reg_data[addr] = value;
 +            break;
 +        case 0x2e: /* PWR_ISR1 */
 +        case 0x2f: /* PWR_IMR1 */
 +            s->reg_data[addr] = value;
 +            break;
 +        case 0x33: /* PWR_EDR1 */
 +        case 0x34: /* PWR_EDR2 */
 +            s->reg_data[addr] = value;
 +            break;
 +        case 0x35: /* PWR_SIH_CTRL */
 +            s->reg_data[addr] = value & 0x07;
 +            break;
 +        case 0x3b: /* CFG_BOOT */
 +            if (s->twl4030->key_cfg)
 +                s->reg_data[addr] = (s->reg_data[addr] & 0x70) | (value & 0x8f);
 +            break;
 +        case 0x44: /* PROTECT_KEY */
 +            s->twl4030->key_cfg = 0;
 +            s->twl4030->key_tst = 0;
 +            switch (value) {
 +                case 0x0C: 
 +                    if (s->reg_data[addr] == 0xC0)
 +                        s->twl4030->key_cfg = 1;
 +                    break;
 +                case 0xE0:
 +                    if (s->reg_data[addr] == 0x0E)
 +                        s->twl4030->key_tst = 1;
 +                    break;
 +                case 0xEC:
 +                    if (s->reg_data[addr] == 0xCE) {
 +                        s->twl4030->key_cfg = 1;
 +                        s->twl4030->key_tst = 1;
 +                    }
 +                    break;
 +                default:
 +                    break;
 +            }
 +            s->reg_data[addr] = value;
 +            break;
 +        case 0x46: /* P1_SW_EVENTS */
 +        case 0x47: /* P2_SW_EVENTS */
 +        case 0x48: /* P3_SW_EVENTS */
 +            s->reg_data[addr] = value & 0x78;
 +            break;
 +        case 0x52: /* SEQ_ADD_W2P */
 +        case 0x53: /* SEQ_ADD_P2A */
 +        case 0x54: /* SEQ_ADD_A2W */
 +        case 0x55: /* SEQ_ADD_A2S */
 +        case 0x56: /* SEQ_ADD_S2A12 */
 +        case 0x57: /* SEQ_ADD_S2A3 */
 +        case 0x58: /* SEQ_ADD_WARM */
 +            if (s->twl4030->key_cfg)
 +                s->reg_data[addr] = value & 0x3f;
 +            break;
 +        case 0x59: /* MEMORY_ADDRESS */
 +            if (s->twl4030->key_cfg)
 +                s->reg_data[addr] = value;
 +            break;
 +        case 0x5a: /* MEMORY_DATA */
 +            if (s->twl4030->key_cfg) {
 +                s->reg_data[addr] = value;
 +                seq_addr = s->reg_data[0x59];
 +                seq_sub = seq_addr & 3;
 +                seq_addr >>= 2;
 +                if ((seq_addr >= 0x2b && seq_addr <= 0x3e) ||
 +                    (seq_addr <= 0x0e && seq_sub == 3))
 +                    s->twl4030->seq_mem[seq_addr][seq_sub] = value;
 +            }
 +            /* TODO: check if autoincrement is write-protected as well */
 +            s->reg_data[0x59]++; 
 +            break;
 +        case 0x68: /* MISC_CFG */
 +            s->reg_data[addr] = value;
 +            break;
 +        case 0x7a: /* VAUX3_DEV_GRP */
 +        case 0x82: /* VMMC1_DEV_GRP */
 +        case 0x8e: /* VPLL2_DEV_GRP */
 +        case 0x96: /* VDAC_DEV_GRP */
 +        case 0xcc: /* VUSB1V5_DEV_GRP */
 +        case 0xcf: /* VUSB1V8_DEV_GRP */
 +        case 0xd2: /* VUSB3V1_DEV_GRP */
 +        case 0xe6: /* HFCLKOUT_DEV_GRP */
 +            s->reg_data[addr] = (s->reg_data[addr] & 0x0f) | (value & 0xf0); 
 +            break;
 +        case 0x75: /* VAUX1_DEDICATED */
 +        case 0x7d: /* VAUX3_DEDICATED */
 +            if (s->twl4030->key_tst)
 +                s->reg_data[addr] = value & 0x77;
 +            else
 +                s->reg_data[addr] = (s->reg_data[addr] & 0x70) | (value & 0x07);
 +            break;
 +        case 0x79: /* VAUX2_DEDICATED */
 +        case 0x81: /* VAUX4_DEDICATED */
 +        case 0x91: /* VPLL2_DEDICATED */
 +            if (s->twl4030->key_tst)
 +                s->reg_data[addr] = value & 0x7f;
 +            else
 +                s->reg_data[addr] = (s->reg_data[addr] & 0x70) | (value & 0x0f);
 +            break;
 +        case 0x85: /* VMMC1_DEDICATED */
 +        case 0x99: /* VDAC_DEDICATED */
 +            if (s->twl4030->key_tst) 
 +                s->reg_data[addr] = value & 0x73;
 +            else
 +                s->reg_data[addr] = (s->reg_data[addr] & 0x70) | (value & 0x03);
 +            break;
 +        case 0x74: /* VAUX1_REMAP */
 +        case 0x78: /* VAUX2_REMAP */
 +        case 0x7c: /* VAUX3_REMAP */
 +        case 0x80: /* VAUX4_REMAP */
 +        case 0x90: /* VPLL2_REMAP */
 +            s->reg_data[addr] = value;
 +            break;
 +        case 0xcd: /* VUSB1V5_TYPE */
 +        case 0xd0: /* VUSB1V8_TYPE */
 +        case 0xd3: /* VUSB3V1_TYPE */
 +            s->reg_data[addr] = value & 0x1f;
 +            break;
 +        case 0xd8: /* VUSB_DEDICATED1 */
 +            s->reg_data[addr] = value & 0x1f;
 +            break;
 +        case 0xd9: /* VUSB_DEDICATED2 */
 +            s->reg_data[addr] = value & 0x08;
 +            break;
 +            
 +        default:
 +              fprintf(stderr,
-                     "%s: unknown register 0x%02x value 0x%02x pc 0x%x\n",
-                     __FUNCTION__, addr, value, cpu_single_env->regs[15]);
++                    "%s: unknown register 0x%02x value 0x%02x\n",
++                    __FUNCTION__, addr, value);
 +            break;
 +    }
 +}
 +
- static int twl4030_4b_tx(i2c_slave *i2c, uint8_t data)
++static void twl4030_node_init(TWL4030NodeState *s,
++                              twl4030_read_func read,
++                              twl4030_write_func write,
++                              const uint8_t *reset_values)
 +{
-     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
-     /* Interpret register address byte */
-     if (s->firstbyte) {
-         s->reg = data;
-         s->firstbyte = 0;
-     } else
-         twl4030_4b_write(s, s->reg++, data);
-       
-     return 1;
++    s->read_func = read;
++    s->write_func = write;
++    s->reg = 0x00;
++    memcpy(s->reg_data, reset_values, 256);
 +}
 +
- static int twl4030_4b_rx(i2c_slave *i2c)
++static void twl4030_48_init(i2c_slave *i2c)
 +{
-     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
-       
-     return twl4030_4b_read(s, s->reg++);
++    twl4030_node_init(FROM_I2C_SLAVE(TWL4030NodeState, i2c),
++                      twl4030_48_read, twl4030_48_write,
++                      addr_48_reset_values);
 +}
 +
- static void twl4030_4b_reset(i2c_slave *i2c)
++static void twl4030_49_init(i2c_slave *i2c)
 +{
-     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
-     s->reg = 0x00;
-     memcpy(s->reg_data, addr_4b_reset_values, 256);
-     s->twl4030->key_cfg = 0;
-     s->twl4030->key_tst = 0;
++    twl4030_node_init(FROM_I2C_SLAVE(TWL4030NodeState, i2c),
++                      twl4030_49_read, twl4030_49_write,
++                      addr_49_reset_values);
 +}
 +
- static void twl4030_4b_event(i2c_slave *i2c, enum i2c_event event)
++static void twl4030_4a_init(i2c_slave *i2c)
 +{
-     struct twl4030_i2c_s *s = (struct twl4030_i2c_s *) i2c;
-       
-     if (event == I2C_START_SEND)
++    twl4030_node_init(FROM_I2C_SLAVE(TWL4030NodeState, i2c),
++                      twl4030_4a_read, twl4030_4a_write,
++                      addr_4a_reset_values);
++}
++
++static void twl4030_4b_init(i2c_slave *i2c)
++{
++    twl4030_node_init(FROM_I2C_SLAVE(TWL4030NodeState, i2c),
++                      twl4030_4b_read, twl4030_4b_write,
++                      addr_4b_reset_values);
++}
++
++static void twl4030_event(i2c_slave *i2c, enum i2c_event event)
++{
++    if (event == I2C_START_SEND) {
++        TWL4030NodeState *s = FROM_I2C_SLAVE(TWL4030NodeState, i2c);
 +        s->firstbyte = 1;
++    }
++}
++
++static int twl4030_rx(i2c_slave *i2c)
++{
++    TWL4030NodeState *s = FROM_I2C_SLAVE(TWL4030NodeState, i2c);
++    return s->read_func(s, s->reg++);
++}
++
++static int twl4030_tx(i2c_slave *i2c, uint8_t data)
++{
++    TWL4030NodeState *s = FROM_I2C_SLAVE(TWL4030NodeState, i2c);
++    if (s->firstbyte) {
++        s->reg = data;
++        s->firstbyte = 0;
++    } else {
++        s->write_func(s, s->reg++, data);
++      }
++    return 1;
 +}
 +
 +static void twl4030_save_state(QEMUFile *f, void *opaque)
 +{
-     struct twl4030_s *s = (struct twl4030_s *)opaque;
++    TWL4030State *s = (TWL4030State *)opaque;
 +    int i;
 +    
 +    qemu_put_sbe32(f, s->key_cfg);
 +    qemu_put_sbe32(f, s->key_tst);
 +    for (i = 0; i < 64; i++)
 +        qemu_put_buffer(f, s->seq_mem[i], 4);
 +    for (i = 0; i < 5; i++) {
 +        qemu_put_sbe32(f, s->i2c[i]->firstbyte);
 +        qemu_put_byte(f, s->i2c[i]->reg);
 +        qemu_put_buffer(f, s->i2c[i]->reg_data, sizeof(s->i2c[i]->reg_data));
 +    }
 +}
 +
 +static int twl4030_load_state(QEMUFile *f, void *opaque, int version_id)
 +{
-     struct twl4030_s *s = (struct twl4030_s *)opaque;
++    TWL4030State *s = (TWL4030State *)opaque;
 +    int i;
 +    
 +    if (version_id)
 +        return -EINVAL;
 +    
 +    s->key_cfg = qemu_get_sbe32(f);
 +    s->key_tst = qemu_get_sbe32(f);
 +    for (i = 0; i < 64; i++)
 +        qemu_get_buffer(f, s->seq_mem[i], 4);
 +    for (i = 0; i < 5; i++) {
 +        s->i2c[i]->firstbyte = qemu_get_sbe32(f);
 +        s->i2c[i]->reg = qemu_get_byte(f);
 +        qemu_get_buffer(f, s->i2c[i]->reg_data, sizeof(s->i2c[i]->reg_data));
 +    }
 +    
 +    return 0;
 +}
 +
- struct twl4030_s *twl4030_init(i2c_bus *bus, qemu_irq irq)
++void *twl4030_init(i2c_bus *gp_bus, qemu_irq irq)
 +{
-     int i;
++    TWL4030State *s = (TWL4030State *)qemu_mallocz(sizeof(*s));
 +      
-     struct twl4030_s *s = (struct twl4030_s *) qemu_mallocz(sizeof(*s));
-       
-     for (i = 0; i < 5; i++) {
-         s->i2c[i]=(struct twl4030_i2c_s *)i2c_slave_init(
-             bus, 0, sizeof(struct twl4030_i2c_s));
-         s->i2c[i]->irq = irq;
++    s->irq = irq;
++    s->key_cfg = 0;
++    s->key_tst = 0;
++    
++    int i;
++    for (i = 0; i < 4; i++) {
++        char name[16];
++        sprintf(name, "twl4030_id%d", i + 1);
++        DeviceState *ds = i2c_create_slave(gp_bus, name, 0x48 + i);
++        s->i2c[i] = FROM_I2C_SLAVE(TWL4030NodeState, I2C_SLAVE_FROM_QDEV(ds));
 +        s->i2c[i]->twl4030 = s;
 +    }
-     s->i2c[0]->i2c.event = twl4030_48_event;
-     s->i2c[0]->i2c.recv = twl4030_48_rx;
-     s->i2c[0]->i2c.send = twl4030_48_tx;
-     twl4030_48_reset(&s->i2c[0]->i2c);
-     i2c_set_slave_address((i2c_slave *)&s->i2c[0]->i2c,0x48);
-       
-     s->i2c[1]->i2c.event = twl4030_49_event;
-     s->i2c[1]->i2c.recv = twl4030_49_rx;
-     s->i2c[1]->i2c.send = twl4030_49_tx;
-     twl4030_49_reset(&s->i2c[1]->i2c);
-     i2c_set_slave_address((i2c_slave *)&s->i2c[1]->i2c,0x49);
-       
-     s->i2c[2]->i2c.event = twl4030_4a_event;
-     s->i2c[2]->i2c.recv = twl4030_4a_rx;
-     s->i2c[2]->i2c.send = twl4030_4a_tx;
-     twl4030_4a_reset(&s->i2c[2]->i2c);
-     i2c_set_slave_address((i2c_slave *)&s->i2c[2]->i2c,0x4a);
-       
-     s->i2c[3]->i2c.event = twl4030_4b_event;
-     s->i2c[3]->i2c.recv = twl4030_4b_rx;
-     s->i2c[3]->i2c.send = twl4030_4b_tx;
-     twl4030_4b_reset(&s->i2c[3]->i2c);
-     i2c_set_slave_address((i2c_slave *)&s->i2c[3]->i2c,0x4b);
-       
++
 +    register_savevm("twl4030", -1, 0,
 +                    twl4030_save_state, twl4030_load_state, s);
 +
 +    return s;
 +}
++
++static I2CSlaveInfo twl4030_info[4] = {
++    {
++        .init = twl4030_48_init,
++        .event = twl4030_event,
++        .recv = twl4030_rx,
++        .send = twl4030_tx
++    },
++    {
++        .init = twl4030_49_init,
++        .event = twl4030_event,
++        .recv = twl4030_rx,
++        .send = twl4030_tx
++    },
++    {
++        .init = twl4030_4a_init,
++        .event = twl4030_event,
++        .recv = twl4030_rx,
++        .send = twl4030_tx
++    },
++    {
++        .init = twl4030_4b_init,
++        .event = twl4030_event,
++        .recv = twl4030_rx,
++        .send = twl4030_tx
++    },
++};
++
++static void twl4030_register_devices(void)
++{
++    I2CSlaveInfo *p = twl4030_info;
++    int i;
++    for (i = 0; i < 4; p++, i++) {
++        char name[16];
++        sprintf(name, "twl4030_id%d", i + 1);
++        i2c_register_slave(name, sizeof(TWL4030NodeState), p);
++    }
++}
++
++device_init(twl4030_register_devices);
diff --cc hw/usb-musb.c
  #define MGC_M_ULPI_REGCTL_COMPLETE    0x02
  #define MGC_M_ULPI_REGCTL_REG         0x01
  
 +/* #define MUSB_DEBUG */
 +
 +#ifdef MUSB_DEBUG
 +#define TRACE(fmt,...) fprintf(stderr, "%s: " fmt "\n", __FUNCTION__, ##__VA_ARGS__)
 +#else
 +#define TRACE(...)
 +#endif
 +
 +
  static void musb_attach(USBPort *port, USBDevice *dev);
  
- struct musb_s {
+ typedef struct {
+     uint16_t faddr[2];
+     uint8_t haddr[2];
+     uint8_t hport[2];
+     uint16_t csr[2];
+     uint16_t maxp[2];
+     uint16_t rxcount;
+     uint8_t type[2];
+     uint8_t interval[2];
+     uint8_t config;
+     uint8_t fifosize;
+     int timeout[2];   /* Always in microframes */
 -    uint32_t *buf[2];
++    uint8_t *buf[2];
+     int fifolen[2];
+     int fifostart[2];
+     int fifoaddr[2];
+     USBPacket packey[2];
+     int status[2];
+     int ext_size[2];
+     /* For callbacks' use */
+     int epnum;
+     int interrupt[2];
+     MUSBState *musb;
+     USBCallback *delayed_cb[2];
+     QEMUTimer *intv_timer[2];
+ } MUSBEndPoint;
+ struct MUSBState {
      qemu_irq *irqs;
      USBPort port;
  
      int setup_len;
      int session;
  
 -    uint32_t buf[0x2000];
 +    uint8_t buf[0x8000];
  
-     struct musb_ep_s {
-         uint16_t faddr[2];
-         uint8_t haddr[2];
-         uint8_t hport[2];
-         uint16_t csr[2];
-         uint16_t maxp[2];
-         uint16_t rxcount;
-         uint8_t type[2];
-         uint8_t interval[2];
-         uint8_t config;
-         uint8_t fifosize;
-         int timeout[2];       /* Always in microframes */
-         uint8_t *buf[2];
-         int fifolen[2];
-         int fifostart[2];
-         int fifoaddr[2];
-         USBPacket packey[2];
-         int status[2];
-         int ext_size[2];
-         /* For callbacks' use */
-         int epnum;
-         int interrupt[2];
-         struct musb_s *musb;
-         USBCallback *delayed_cb[2];
-         QEMUTimer *intv_timer[2];
          /* Duplicating the world since 2008!...  probably we should have 32
           * logical, single endpoints instead.  */
-     } ep[16];
+     MUSBEndPoint ep[16];
 -} *musb_init(qemu_irq *irqs)
 -{
 -    MUSBState *s = qemu_mallocz(sizeof(*s));
 -    int i;
 -
 -    s->irqs = irqs;
 -
 -    s->faddr = 0x00;
 -    s->power = MGC_M_POWER_HSENAB;
 -    s->tx_intr = 0x0000;
 -    s->rx_intr = 0x0000;
 -    s->tx_mask = 0xffff;
 -    s->rx_mask = 0xffff;
 -    s->intr = 0x00;
 -    s->mask = 0x06;
 -    s->idx = 0;
 -
 -    /* TODO: _DW */
 -    s->ep[0].config = MGC_M_CONFIGDATA_SOFTCONE | MGC_M_CONFIGDATA_DYNFIFO;
 -    for (i = 0; i < 16; i ++) {
 -        s->ep[i].fifosize = 64;
 -        s->ep[i].maxp[0] = 0x40;
 -        s->ep[i].maxp[1] = 0x40;
 -        s->ep[i].musb = s;
 -        s->ep[i].epnum = i;
 -    }
 -
 -    qemu_register_usb_port(&s->port, s, 0, musb_attach);
 -
 -    return s;
 -}
 +};
  
- static void musb_vbus_set(struct musb_s *s, int level)
+ static void musb_vbus_set(MUSBState *s, int level)
  {
      if (level)
          s->devctl |= 3 << MGC_S_DEVCTL_VBUS;
@@@ -746,12 -768,12 +748,12 @@@ static void musb_rx_packet_complete(USB
      musb_rx_intr_set(s, epnum, 1);
  }
  
- static void musb_tx_rdy(struct musb_s *s, int epnum)
+ static void musb_tx_rdy(MUSBState *s, int epnum)
  {
-     struct musb_ep_s *ep = s->ep + epnum;
+     MUSBEndPoint *ep = s->ep + epnum;
      int pid;
      int total, valid = 0;
 -
 +    TRACE("start %d, len %d",  ep->fifostart[0], ep->fifolen[0] );
      ep->fifostart[0] += ep->fifolen[0];
      ep->fifolen[0] = 0;
  
@@@ -850,39 -871,7 +852,39 @@@ static void musb_rx_req(MUSBState *s, i
                      total, musb_rx_packet_complete, 1);
  }
  
- static uint8_t musb_read_fifo(struct musb_ep_s *ep)
++static uint8_t musb_read_fifo(MUSBEndPoint *ep)
 +{
 +    uint8_t value;
 +    if (ep->fifolen[1] >= 64) {
 +        /* We have a FIFO underrun */
 +        printf("%s: EP%d FIFO is now empty, stop reading\n",
 +                __FUNCTION__, ep->epnum);
 +        return 0x00000000;
 +    }
 +    /* In DMA mode clear RXPKTRDY and set REQPKT automatically
 +     * (if AUTOREQ is set) */
 +
 +    ep->csr[1] &= ~MGC_M_RXCSR_FIFOFULL;
 +    value=ep->buf[1][ep->fifostart[1] + ep->fifolen[1] ++];
 +    TRACE("EP%d 0x%02x, %d", ep->epnum, value, ep->fifolen[1] );
 +    return value;
 +}
 +
- static void musb_write_fifo(struct musb_ep_s *ep, uint8_t value)
++static void musb_write_fifo(MUSBEndPoint *ep, uint8_t value)
 +{
 +    TRACE("EP%d = %02x", ep->epnum, value);
 +    if (ep->fifolen[0] >= 64) {
 +        /* We have a FIFO overrun */
 +        printf("%s: EP%d FIFO exceeded 64 bytes, stop feeding data\n",
 +                __FUNCTION__, ep->epnum);
 +        return;
 +     }
 +
 +     ep->buf[0][ep->fifostart[0] + ep->fifolen[0] ++] = value;
 +     ep->csr[0] |= MGC_M_TXCSR_FIFONOTEMPTY;
 +}
 +
- static void musb_ep_frame_cancel(struct musb_ep_s *ep, int dir)
+ static void musb_ep_frame_cancel(MUSBEndPoint *ep, int dir)
  {
      if (ep->intv_timer[dir])
          qemu_del_timer(ep->intv_timer[dir]);
  /* Bus control */
  static uint8_t musb_busctl_readb(void *opaque, int ep, int addr)
  {
-     struct musb_s *s = (struct musb_s *) opaque;
- //    TRACE("ADDR = 0x%08x", addr);
+     MUSBState *s = (MUSBState *) opaque;
++    //    TRACE("ADDR = 0x%08x", addr);
  
      switch (addr) {
      /* For USB2.0 HS hubs only */
  
  static void musb_busctl_writeb(void *opaque, int ep, int addr, uint8_t value)
  {
-     struct musb_s *s = (struct musb_s *) opaque;
+     MUSBState *s = (MUSBState *) opaque;
  
      switch (addr) {
 +    case MUSB_HDRC_TXFUNCADDR:
 +        s->ep[ep].faddr[0] = value;
 +        break;
 +    case MUSB_HDRC_RXFUNCADDR:
 +        s->ep[ep].faddr[1] = value;
 +        break;
      case MUSB_HDRC_TXHUBADDR:
          s->ep[ep].haddr[0] = value;
          break;
@@@ -1162,10 -1143,9 +1164,10 @@@ static void musb_ep_writeh(void *opaque
  /* Generic control */
  static uint32_t musb_readb(void *opaque, target_phys_addr_t addr)
  {
-     struct musb_s *s = (struct musb_s *) opaque;
+     MUSBState *s = (MUSBState *) opaque;
      int ep, i;
      uint8_t ret;
 +//    TRACE("ADDR = 0x%08x", addr);
  
      switch (addr) {
      case MUSB_HDRC_FADDR:
  
  static void musb_writeb(void *opaque, target_phys_addr_t addr, uint32_t value)
  {
-     struct musb_s *s = (struct musb_s *) opaque;
+     MUSBState *s = (MUSBState *) opaque;
      int ep;
 +//    TRACE("ADDR = 0x%08x = %08x", addr, value);
  
      switch (addr) {
      case MUSB_HDRC_FADDR:
  
  static uint32_t musb_readh(void *opaque, target_phys_addr_t addr)
  {
-     struct musb_s *s = (struct musb_s *) opaque;
+     MUSBState *s = (MUSBState *) opaque;
      int ep, i;
      uint16_t ret;
 +//    TRACE("ADDR = 0x%08x", addr);
  
      switch (addr) {
      case MUSB_HDRC_INTRTX:
  
  static void musb_writeh(void *opaque, target_phys_addr_t addr, uint32_t value)
  {
-     struct musb_s *s = (struct musb_s *) opaque;
+     MUSBState *s = (MUSBState *) opaque;
      int ep;
 +    //TRACE("ADDR = 0x%08x = %08x", addr, value);
  
      switch (addr) {
      case MUSB_HDRC_INTRTXE:
  
  static uint32_t musb_readw(void *opaque, target_phys_addr_t addr)
  {
-     struct musb_s *s = (struct musb_s *) opaque;
+     MUSBState *s = (MUSBState *) opaque;
 -    MUSBEndPoint *ep;
 -    int epnum;
 +    int ep;
  
      switch (addr) {
      case MUSB_HDRC_FIFO ... (MUSB_HDRC_FIFO + 0x3f):
  
  static void musb_writew(void *opaque, target_phys_addr_t addr, uint32_t value)
  {
-     struct musb_s *s = (struct musb_s *) opaque;
+     MUSBState *s = (MUSBState *) opaque;
 -    MUSBEndPoint *ep;
 -    int epnum;
 +    int ep;
 +//    TRACE("ADDR = 0x%08x = %08x", addr, value);
  
      switch (addr) {
      case MUSB_HDRC_FIFO ... (MUSB_HDRC_FIFO + 0x3f):
@@@ -1472,182 -1448,3 +1474,182 @@@ CPUWriteMemoryFunc *musb_write[] = 
      musb_writeh,
      musb_writew,
  };
 +
 +static void musb_save_state(QEMUFile *f, void *opaque)
 +{
-     struct musb_s *s = (struct musb_s *)opaque;
++    MUSBState *s = (MUSBState *)opaque;
 +    int i, j;
 +    
 +    qemu_put_sbe32(f, s->idx);
 +    qemu_put_byte(f, s->devctl);
 +    qemu_put_byte(f, s->power);
 +    qemu_put_byte(f, s->faddr);
 +    qemu_put_byte(f, s->intr);
 +    qemu_put_byte(f, s->mask);
 +    qemu_put_be16(f, s->tx_intr);
 +    qemu_put_be16(f, s->tx_mask);
 +    qemu_put_be16(f, s->rx_intr);
 +    qemu_put_be16(f, s->rx_mask);
 +    qemu_put_sbe32(f, s->setup_len);
 +    qemu_put_sbe32(f, s->session);
 +    qemu_put_buffer(f, s->buf, sizeof(s->buf));
 +    for (i = 0; i < 16; i++) {
 +        qemu_put_be16(f, s->ep[i].rxcount);
 +        qemu_put_byte(f, s->ep[i].config);
 +        qemu_put_byte(f, s->ep[i].fifosize);
 +        for (j = 0; j < 2; j++) {
 +            qemu_put_be16(f, s->ep[i].faddr[j]);
 +            qemu_put_byte(f, s->ep[i].haddr[j]);
 +            qemu_put_byte(f, s->ep[i].hport[j]);
 +            qemu_put_be16(f, s->ep[i].csr[j]);
 +            qemu_put_be16(f, s->ep[i].maxp[j]);
 +            qemu_put_byte(f, s->ep[i].type[j]);
 +            qemu_put_byte(f, s->ep[i].interval[j]);
 +            qemu_put_sbe32(f, s->ep[i].timeout[j]);
 +            if (s->ep[i].buf[j])
 +                qemu_put_be32(f, s->ep[i].buf[j] - s->buf);
 +            else
 +                qemu_put_be32(f, 0xffffffff);
 +            qemu_put_sbe32(f, s->ep[i].fifolen[j]);
 +            qemu_put_sbe32(f, s->ep[i].fifostart[j]);
 +            qemu_put_sbe32(f, s->ep[i].fifoaddr[j]);
 +            qemu_put_sbe32(f, s->ep[i].packey[j].pid);
 +            qemu_put_byte(f, s->ep[i].packey[j].devaddr);
 +            qemu_put_byte(f, s->ep[i].packey[j].devep);
 +            qemu_put_sbe32(f, s->ep[i].packey[j].len);
 +            qemu_put_sbe32(f, s->ep[i].status[j]);
 +            qemu_put_sbe32(f, s->ep[i].ext_size[j]);
 +            qemu_put_sbe32(f, s->ep[i].interrupt[j]);
 +            if (s->ep[i].delayed_cb[j] == musb_rx_packet_complete)
 +                qemu_put_byte(f, 1);
 +            else if (s->ep[i].delayed_cb[j] == musb_tx_packet_complete)
 +                qemu_put_byte(f, 2);
 +            else
 +                qemu_put_byte(f, 0);
 +            if (s->ep[i].intv_timer[j]) {
 +                qemu_put_byte(f, 1);
 +                qemu_put_timer(f, s->ep[i].intv_timer[j]);
 +            } else
 +                qemu_put_byte(f, 0);
 +        }
 +    }
 +}
 +
 +static int musb_load_state(QEMUFile *f, void *opaque, int version_id)
 +{
-     struct musb_s *s = (struct musb_s *)opaque;
++    MUSBState *s = (MUSBState *)opaque;
 +    int i, j;
 +    uint32_t x;
 +    
 +    if (version_id)
 +        return -EINVAL;
 +    
 +    s->idx = qemu_get_sbe32(f);
 +    s->devctl = qemu_get_byte(f);
 +    s->power = qemu_get_byte(f);
 +    s->faddr = qemu_get_byte(f);
 +    s->intr = qemu_get_byte(f);
 +    s->mask = qemu_get_byte(f);
 +    s->tx_intr = qemu_get_be16(f);
 +    s->tx_mask = qemu_get_be16(f);
 +    s->rx_intr = qemu_get_be16(f);
 +    s->rx_mask = qemu_get_be16(f);
 +    s->setup_len = qemu_get_sbe32(f);
 +    s->session = qemu_get_sbe32(f);
 +    qemu_get_buffer(f, s->buf, sizeof(s->buf));
 +    for (i = 0; i < 16; i++) {
 +        s->ep[i].rxcount = qemu_get_be16(f);
 +        s->ep[i].config = qemu_get_byte(f);
 +        s->ep[i].fifosize = qemu_get_byte(f);
 +        for (j = 0; j < 2; j++) {
 +            s->ep[i].faddr[j] = qemu_get_be16(f);
 +            s->ep[i].haddr[j] = qemu_get_byte(f);
 +            s->ep[i].hport[j] = qemu_get_byte(f);
 +            s->ep[i].csr[j] = qemu_get_be16(f);
 +            s->ep[i].maxp[j] = qemu_get_be16(f);
 +            s->ep[i].type[j] = qemu_get_byte(f);
 +            s->ep[i].interval[j] = qemu_get_byte(f);
 +            s->ep[i].timeout[j] = qemu_get_sbe32(f);
 +            x = qemu_get_be32(f);
 +            if (x != 0xffffffff)
 +                s->ep[i].buf[j] = s->buf + x;
 +            else
 +                s->ep[i].buf[j] = 0;
 +            s->ep[i].fifolen[j] = qemu_get_sbe32(f);
 +            s->ep[i].fifostart[j] = qemu_get_sbe32(f);
 +            s->ep[i].fifoaddr[j] = qemu_get_sbe32(f);
 +            s->ep[i].packey[j].pid = qemu_get_sbe32(f);
 +            s->ep[i].packey[j].devaddr = qemu_get_byte(f);
 +            s->ep[i].packey[j].devep = qemu_get_byte(f);
 +            s->ep[i].packey[j].data = s->ep[i].buf[j];
 +            s->ep[i].packey[j].len = qemu_get_sbe32(f);
 +            s->ep[i].packey[j].complete_opaque = &s->ep[i];
 +            s->ep[i].status[j] = qemu_get_sbe32(f);
 +            s->ep[i].ext_size[j] = qemu_get_sbe32(f);
 +            s->ep[i].interrupt[j] = qemu_get_sbe32(f);
 +            switch (qemu_get_byte(f)) {
 +                case 0:
 +                    s->ep[i].delayed_cb[j] = 0;
 +                    s->ep[i].packey[j].complete_cb = 0;
 +                    break;
 +                case 1:
 +                    s->ep[i].delayed_cb[j] = musb_rx_packet_complete;
 +                    s->ep[i].packey[j].complete_cb = musb_rx_packet_complete;
 +                    break;
 +                case 2:
 +                    s->ep[i].delayed_cb[j] = musb_tx_packet_complete;
 +                    s->ep[i].packey[j].complete_cb = musb_tx_packet_complete;
 +                    break;
 +                default:
 +                    fprintf(stderr, "%s: unknown delayed_cb\n", __FUNCTION__);
 +                    exit(-1);
 +                    break;
 +            }
 +            if (qemu_get_byte(f)) {
 +                if (!s->ep[i].intv_timer[j]) {
 +                    s->ep[i].intv_timer[j] =
 +                        qemu_new_timer(vm_clock,
 +                                       j ? musb_cb_tick1 : musb_cb_tick0,
 +                                       &s->ep[i]);
 +                }
 +                qemu_get_timer(f, s->ep[i].intv_timer[j]);
 +            }
 +        }
 +    }
 +    
 +    /* TODO: restore interrupt status */
 +    
 +    return 0;
 +}
 +
- struct musb_s *musb_init(qemu_irq *irqs)
++MUSBState *musb_init(qemu_irq *irqs)
 +{
-     struct musb_s *s = qemu_mallocz(sizeof(*s));
++    MUSBState *s = qemu_mallocz(sizeof(*s));
 +    int i;
 +    
 +    s->irqs = irqs;
 +    
 +    s->faddr = 0x00;
 +    s->power = MGC_M_POWER_HSENAB;
 +    s->tx_intr = 0x0000;
 +    s->rx_intr = 0x0000;
 +    s->tx_mask = 0xffff;
 +    s->rx_mask = 0xffff;
 +    s->intr = 0x00;
 +    s->mask = 0x06;
 +    s->idx = 0;
 +    
 +    /* TODO: _DW */
 +    s->ep[0].config = MGC_M_CONFIGDATA_SOFTCONE | MGC_M_CONFIGDATA_DYNFIFO;
 +    for (i = 0; i < 16; i ++) {
 +        s->ep[i].fifosize = 64;
 +        s->ep[i].maxp[0] = 0x40;
 +        s->ep[i].maxp[1] = 0x40;
 +        s->ep[i].musb = s;
 +        s->ep[i].epnum = i;
 +    }
 +    
 +    qemu_register_usb_port(&s->port, s, 0, musb_attach);
 +    register_savevm("musb", -1, 0, musb_save_state, musb_load_state, s);
 +    return s;
 +}
diff --cc hw/usb-ohci.c
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -3468,9 -3201,8 +3468,10 @@@ static void *clone_func(void *arg
  
      env = info->env;
      thread_env = env;
 +    ts = (TaskState *)thread_env->opaque;
-     info->tid = gettid();
 +    task_settid(ts);
+     info->tid = gettid();
+     env->host_tid = info->tid;
      if (info->child_tidptr)
          put_user_u32(info->tid, info->child_tidptr);
      if (info->parent_tidptr)
Simple merge
Simple merge
Simple merge