merage qemu master
authoryajin <yajin@vm-kernel.org>
Wed, 14 Jan 2009 22:56:30 +0000 (15 06:56 +0800)
committeryajin <yajin@vm-kernel.org>
Wed, 14 Jan 2009 22:56:30 +0000 (15 06:56 +0800)
103 files changed:
Makefile
Makefile.target
block-qcow.c
block-qcow2.c
cache-utils.c
cache-utils.h
configure
cpu-exec.c
exec.c
gdbstub.c
hw/alpha_palcode.c
hw/apb_pci.c
hw/axis_dev88.c
hw/e1000.c
hw/escc.c [moved from hw/slavio_serial.c with 85% similarity]
hw/escc.h [new file with mode: 0644]
hw/etraxfs.c
hw/etraxfs.h
hw/etraxfs_eth.c
hw/flash.h
hw/ide.c
hw/integratorcp.c
hw/macio.c
hw/mcf5208.c
hw/mcf_fec.c
hw/mips_int.c
hw/mips_jz.c
hw/mips_jz.h
hw/mips_jz_clk.c
hw/mips_jz_glue.h
hw/mips_malta.c
hw/mips_mipssim.c
hw/mips_pavo.c
hw/mips_r4k.c
hw/mips_timer.c
hw/mipsnet.c
hw/musicpal.c
hw/ne2000.c
hw/pc.c
hw/pci.c
hw/pci.h
hw/pci_host.h
hw/pcnet.c
hw/ppc.h
hw/ppc440_bamboo.c
hw/ppc_chrp.c
hw/ppc_mac.h
hw/ppc_oldworld.c
hw/ppc_prep.c
hw/r2d.c
hw/realview.c
hw/rtl8139.c
hw/smc91c111.c
hw/stellaris.c
hw/stellaris_enet.c
hw/sun4m.c
hw/sun4m.h
hw/sun4u.c
hw/versatilepb.c
hw/virtio-net.c
hw/virtio-net.h
monitor.c
net.c
net.h
pc-bios/README
pc-bios/bios-pq/0002_e820-high-mem.patch [deleted file]
pc-bios/bios-pq/0003_smp-startup-poll.patch [deleted file]
pc-bios/bios-pq/0005_hpet.patch [deleted file]
pc-bios/bios-pq/HEAD
pc-bios/bios-pq/series
pc-bios/bios.bin
pc-bios/openbios-ppc [new file with mode: 0644]
pc-bios/openbios-sparc32
pc-bios/openbios-sparc64
posix-aio-compat.c
qemu-doc.texi
qemu-nbd.c
slirp/bootp.c
slirp/ip.h
slirp/ip_input.c
slirp/libslirp.h
slirp/main.h
slirp/misc.c
slirp/sbuf.c
slirp/slirp.c
slirp/slirp.h
slirp/socket.c
slirp/socket.h
slirp/tcp_input.c
slirp/tcp_subr.c
slirp/tcp_var.h
slirp/tcpip.h
slirp/udp.c
slirp/udp.h
target-mips/helper.c
target-mips/mips-defs.h
target-mips/translate.c
target-mips/translate_init.c
target-ppc/helper.h
target-ppc/op_helper.c
target-ppc/translate.c
target-sparc/helper.c
vl.c

index 871970a..8cbdcda 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -221,8 +221,9 @@ common  de-ch  es     fo  fr-ca  hu     ja  mk  nl-be      pt  sl     tr
 
 ifdef INSTALL_BLOBS
 BLOBS=bios.bin vgabios.bin vgabios-cirrus.bin ppc_rom.bin \
-video.x openbios-sparc32 openbios-sparc64 pxe-ne2k_pci.bin \
-pxe-rtl8139.bin pxe-pcnet.bin pxe-e1000.bin bamboo.dtb
+video.x openbios-sparc32 openbios-sparc64 openbios-ppc \
+pxe-ne2k_pci.bin pxe-rtl8139.bin pxe-pcnet.bin pxe-e1000.bin \
+bamboo.dtb
 else
 BLOBS=
 endif
@@ -354,6 +355,7 @@ tarbin:
        $(datadir)/video.x \
        $(datadir)/openbios-sparc32 \
        $(datadir)/openbios-sparc64 \
+       $(datadir)/openbios-ppc \
        $(datadir)/pxe-ne2k_pci.bin \
        $(datadir)/pxe-rtl8139.bin \
        $(datadir)/pxe-pcnet.bin \
index 5db1302..1718d86 100644 (file)
@@ -593,10 +593,7 @@ ifdef CONFIG_OSS
 LIBS += $(CONFIG_OSS_LIB)
 endif
 
-SOUND_HW = sb16.o es1370.o
-ifdef CONFIG_AC97
-SOUND_HW += ac97.o
-endif
+SOUND_HW = sb16.o es1370.o ac97.o
 ifdef CONFIG_ADLIB
 SOUND_HW += fmopl.o adlib.o
 adlib.o fmopl.o: CFLAGS := ${CFLAGS} -DBUILD_Y8950=0
@@ -649,7 +646,7 @@ OBJS+= ppc.o ide.o vga.o $(SOUND_HW) dma.o openpic.o
 OBJS+= pckbd.o ps2.o serial.o i8259.o i8254.o fdc.o m48t59.o mc146818rtc.o
 OBJS+= prep_pci.o ppc_prep.o
 # Mac shared devices
-OBJS+= macio.o cuda.o adb.o mac_nvram.o mac_dbdma.o
+OBJS+= macio.o cuda.o adb.o mac_nvram.o mac_dbdma.o escc.o
 # OldWorld PowerMac
 OBJS+= heathrow_pic.o grackle_pci.o ppc_oldworld.o
 # NewWorld PowerMac
@@ -666,7 +663,7 @@ OBJS+= kvm_ppc.o
 endif
 endif
 ifeq ($(TARGET_BASE_ARCH), mips)
-OBJS+= mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o mips_pavo.o
+OBJS+= mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o mips_pavo.o nand_bpage.o
 OBJS+= mips_jz.o mips_jz_clk.o
 OBJS+= mips_timer.o mips_int.o dma.o vga.o serial.o i8254.o i8259.o rc4030.o
 OBJS+= g364fb.o jazz_led.o
@@ -697,7 +694,7 @@ OBJS+= fdc.o mc146818rtc.o serial.o m48t59.o
 OBJS+= cirrus_vga.o parallel.o ptimer.o
 else
 OBJS+= sun4m.o tcx.o pcnet.o iommu.o m48t59.o slavio_intctl.o
-OBJS+= slavio_timer.o slavio_serial.o slavio_misc.o fdc.o sparc32_dma.o
+OBJS+= slavio_timer.o escc.o slavio_misc.o fdc.o sparc32_dma.o
 OBJS+= cs4231.o ptimer.o eccmemctl.o sbi.o sun4c_intctl.o
 endif
 endif
index 1fecf30..91c53b1 100644 (file)
@@ -339,28 +339,33 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
                 return -1;
         } else {
             cluster_offset = bdrv_getlength(s->hd);
-            /* round to cluster size */
-            cluster_offset = (cluster_offset + s->cluster_size - 1) &
-                ~(s->cluster_size - 1);
-            bdrv_truncate(s->hd, cluster_offset + s->cluster_size);
-            /* if encrypted, we must initialize the cluster
-               content which won't be written */
-            if (s->crypt_method &&
-                (n_end - n_start) < s->cluster_sectors) {
-                uint64_t start_sect;
-                start_sect = (offset & ~(s->cluster_size - 1)) >> 9;
-                memset(s->cluster_data + 512, 0x00, 512);
-                for(i = 0; i < s->cluster_sectors; i++) {
-                    if (i < n_start || i >= n_end) {
-                        encrypt_sectors(s, start_sect + i,
-                                        s->cluster_data,
-                                        s->cluster_data + 512, 1, 1,
-                                        &s->aes_encrypt_key);
-                        if (bdrv_pwrite(s->hd, cluster_offset + i * 512,
-                                        s->cluster_data, 512) != 512)
-                            return -1;
+            if (allocate == 1) {
+                /* round to cluster size */
+                cluster_offset = (cluster_offset + s->cluster_size - 1) &
+                    ~(s->cluster_size - 1);
+                bdrv_truncate(s->hd, cluster_offset + s->cluster_size);
+                /* if encrypted, we must initialize the cluster
+                   content which won't be written */
+                if (s->crypt_method &&
+                    (n_end - n_start) < s->cluster_sectors) {
+                    uint64_t start_sect;
+                    start_sect = (offset & ~(s->cluster_size - 1)) >> 9;
+                    memset(s->cluster_data + 512, 0x00, 512);
+                    for(i = 0; i < s->cluster_sectors; i++) {
+                        if (i < n_start || i >= n_end) {
+                            encrypt_sectors(s, start_sect + i,
+                                            s->cluster_data,
+                                            s->cluster_data + 512, 1, 1,
+                                            &s->aes_encrypt_key);
+                            if (bdrv_pwrite(s->hd, cluster_offset + i * 512,
+                                            s->cluster_data, 512) != 512)
+                                return -1;
+                        }
                     }
                 }
+            } else if (allocate == 2) {
+                cluster_offset |= QCOW_OFLAG_COMPRESSED |
+                    (uint64_t)compressed_size << (63 - s->cluster_bits);
             }
         }
         /* update L2 table */
index 707109e..9aa7261 100644 (file)
@@ -2024,6 +2024,7 @@ static int qcow_snapshot_create(BlockDriverState *bs,
     if (!snapshots1)
         goto fail;
     memcpy(snapshots1, s->snapshots, s->nb_snapshots * sizeof(QCowSnapshot));
+    qemu_free(s->snapshots);
     s->snapshots = snapshots1;
     s->snapshots[s->nb_snapshots++] = *sn;
 
index 7c98144..7df1fcf 100644 (file)
@@ -1,6 +1,6 @@
 #include "cache-utils.h"
 
-#ifdef __powerpc__
+#if defined HOST_PPC || defined HOST_PPC64
 struct qemu_cache_conf qemu_cache_conf = {
     .dcache_bsize = 16,
     .icache_bsize = 16
@@ -68,4 +68,4 @@ void qemu_cache_utils_init(char **envp)
 }
 #endif
 
-#endif /* __powerpc__ */
+#endif /* HOST_PPC || HOST_PPC64  */
index 0598b96..8847dbb 100644 (file)
@@ -1,7 +1,9 @@
 #ifndef QEMU_CACHE_UTILS_H
 #define QEMU_CACHE_UTILS_H
 
-#ifdef __powerpc__
+#include "config-host.h"
+
+#if defined HOST_PPC || defined HOST_PPC64
 struct qemu_cache_conf {
     unsigned long dcache_bsize;
     unsigned long icache_bsize;
index 0d18534..a8ea55a 100755 (executable)
--- a/configure
+++ b/configure
@@ -27,7 +27,8 @@ static="no"
 cross_prefix=""
 cc="gcc"
 audio_drv_list=""
-audio_card_list=""
+audio_card_list="ac97 es1370 sb16"
+audio_possible_cards="ac97 es1370 sb16 cs4231a adlib gus"
 host_cc="gcc"
 ar="ar"
 make="make"
@@ -519,8 +520,8 @@ echo "  --disable-sdl            disable SDL"
 echo "  --enable-cocoa           enable COCOA (Mac OS X only)"
 echo "  --audio-drv-list=LIST    set audio drivers list:"
 echo "                           Available drivers: $audio_possible_drivers"
-echo "  --audio-card-list=LIST   set list of additional emulated audio cards"
-echo "                           Available cards: ac97 adlib cs4231a gus"
+echo "  --audio-card-list=LIST   set list of emulated audio cards [$audio_card_list]"
+echo "                           Available cards: $audio_possible_cards"
 echo "  --enable-mixemu          enable mixer emulation"
 echo "  --disable-brlapi         disable BrlAPI"
 echo "  --disable-vnc-tls        disable TLS encryption for VNC server"
@@ -963,6 +964,12 @@ int main(void) { return 0; }
 EOF
   if test "$kerneldir" != "" ; then
       kvm_cflags=-I"$kerneldir"/include
+      if test \( "$cpu" = "i386" -o "$cpu" = "x86_64" \) \
+         -a -d "$kerneldir/arch/x86/include" ; then
+            kvm_cflags="$kvm_cflags -I$kerneldir/arch/x86/include"
+        elif test -d "$kerneldir/arch/$cpu/include" ; then
+            kvm_cflags="$kvm_cflags -I$kerneldir/arch/$cpu/include"
+      fi
   else
       kvm_cflags=""
   fi
index f574877..e179786 100644 (file)
@@ -424,6 +424,16 @@ int cpu_exec(CPUState *env1)
                         next_tb = 0;
                     }
 #elif defined(TARGET_MIPS)
+if (interrupt_request & CPU_INTERRUPT_HARD)
+{
+if (env->CP0_Cause&0x400)
+{
+       printf("HARD INT \n");
+       printf("env->CP0_Status %x env->CP0_Cause %x CP0Ca_IP_mask %x \n",env->CP0_Status,env->CP0_Cause,CP0Ca_IP_mask);
+       printf("CP0St_IE %x CP0St_EXL %x CP0St_ERL %x \n",CP0St_IE,CP0St_EXL,CP0St_ERL);
+       printf("env->hflags %x MIPS_HFLAG_DM %x \n",env->hflags ,MIPS_HFLAG_DM);
+}
+}
                     if ((interrupt_request & CPU_INTERRUPT_HARD) &&
                         (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
                         (env->CP0_Status & (1 << CP0St_IE)) &&
diff --git a/exec.c b/exec.c
index e633b74..a19c06c 100644 (file)
--- a/exec.c
+++ b/exec.c
@@ -2379,6 +2379,8 @@ static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr)
 #ifdef DEBUG_UNASSIGNED
     printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
 #endif
+//printf("Unassigned mem readb " TARGET_FMT_plx " pc %x \n", addr,cpu_single_env->active_tc.PC);
+//exit(-1);
 #if defined(TARGET_SPARC)
     do_unassigned_access(addr, 0, 0, 0, 1);
 #endif
@@ -2390,6 +2392,8 @@ static uint32_t unassigned_mem_readw(void *opaque, target_phys_addr_t addr)
 #ifdef DEBUG_UNASSIGNED
     printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
 #endif
+//printf("Unassigned mem readw " TARGET_FMT_plx " pc %x \n", addr,cpu_single_env->active_tc.PC);
+//exit(-1);
 #if defined(TARGET_SPARC)
     do_unassigned_access(addr, 0, 0, 0, 2);
 #endif
@@ -2401,6 +2405,8 @@ static uint32_t unassigned_mem_readl(void *opaque, target_phys_addr_t addr)
 #ifdef DEBUG_UNASSIGNED
     printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
 #endif
+//printf("Unassigned mem readl " TARGET_FMT_plx " pc %x \n", addr,cpu_single_env->active_tc.PC);
+//exit(-1);
 #if defined(TARGET_SPARC)
     do_unassigned_access(addr, 0, 0, 0, 4);
 #endif
@@ -2412,6 +2418,8 @@ static void unassigned_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_
 #ifdef DEBUG_UNASSIGNED
     printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
 #endif
+//printf("Unassigned mem writeb " TARGET_FMT_plx " = 0x%x PC %x \n", addr, val,cpu_single_env->active_tc.PC);
+//if (addr!=0x20 )exit(-1);
 #if defined(TARGET_SPARC)
     do_unassigned_access(addr, 1, 0, 0, 1);
 #endif
@@ -2422,6 +2430,8 @@ static void unassigned_mem_writew(void *opaque, target_phys_addr_t addr, uint32_
 #ifdef DEBUG_UNASSIGNED
     printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
 #endif
+//printf("Unassigned mem writew " TARGET_FMT_plx " = 0x%x PC %x \n", addr, val,cpu_single_env->active_tc.PC);
+//exit(-1);
 #if defined(TARGET_SPARC)
     do_unassigned_access(addr, 1, 0, 0, 2);
 #endif
@@ -2432,6 +2442,8 @@ static void unassigned_mem_writel(void *opaque, target_phys_addr_t addr, uint32_
 #ifdef DEBUG_UNASSIGNED
     printf("Unassigned mem write " TARGET_FMT_plx " = 0x%x\n", addr, val);
 #endif
+//printf("Unassigned mem writel " TARGET_FMT_plx " = 0x%x PC %x \n", addr, val,cpu_single_env->active_tc.PC);
+//exit(-1);
 #if defined(TARGET_SPARC)
     do_unassigned_access(addr, 1, 0, 0, 4);
 #endif
index b8198ee..a3ff07a 100644 (file)
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -694,7 +694,7 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
 #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
 #define NUM_CORE_REGS 86
 #else
-#define NUM_CORE_REGS 73
+#define NUM_CORE_REGS 72
 #endif
 
 #ifdef TARGET_ABI32
@@ -728,7 +728,7 @@ static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
     case 69: GET_REGA(env->npc);
     case 70: GET_REGA(env->fsr);
     case 71: GET_REGA(0); /* csr */
-    case 72: GET_REGA(0);
+    default: GET_REGA(0);
     }
 #else
     if (n < 64) {
index 70d4af6..151f3c2 100644 (file)
@@ -998,12 +998,12 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
     uint64_t physical, page_size, end;
     int prot, zbits, ret;
 
-    if (env->user_mode_only) {
+#if defined(CONFIG_USER_ONLY)
         ret = 2;
-    } else {
+#else
         ret = virtual_to_physical(env, &physical, &zbits, &prot,
                                   address, mmu_idx, rw);
-    }
+#endif
     switch (ret) {
     case 0:
         /* No fault */
index d847888..f222f3c 100644 (file)
  * THE SOFTWARE.
  */
 
-/* XXX This file and most of its contests are somewhat misnamed.  The
+/* XXX This file and most of its contents are somewhat misnamed.  The
    Ultrasparc PCI host is called the PCI Bus Module (PBM).  The APB is
    the secondary PCI bridge.  */
 
 #include "hw.h"
 #include "pci.h"
+
+/* debug APB */
+//#define DEBUG_APB
+
+#ifdef DEBUG_APB
+#define APB_DPRINTF(fmt, args...) \
+do { printf("APB: " fmt , ##args); } while (0)
+#else
+#define APB_DPRINTF(fmt, args...)
+#endif
+
 typedef target_phys_addr_t pci_addr_t;
 #include "pci_host.h"
 
@@ -37,13 +48,13 @@ static void pci_apb_config_writel (void *opaque, target_phys_addr_t addr,
                                          uint32_t val)
 {
     APBState *s = opaque;
-    int i;
 
-    for (i = 11; i < 32; i++) {
-        if ((val & (1 << i)) != 0)
-            break;
-    }
-    s->config_reg = (1 << 16) | (val & 0x7FC) | (i << 11);
+#ifdef TARGET_WORDS_BIGENDIAN
+    val = bswap32(val);
+#endif
+    APB_DPRINTF("config_writel addr " TARGET_FMT_plx " val %x\n", addr,
+                val);
+    s->config_reg = val;
 }
 
 static uint32_t pci_apb_config_readl (void *opaque,
@@ -51,10 +62,13 @@ static uint32_t pci_apb_config_readl (void *opaque,
 {
     APBState *s = opaque;
     uint32_t val;
-    int devfn;
 
-    devfn = (s->config_reg >> 8) & 0xFF;
-    val = (1 << (devfn >> 3)) | ((devfn & 0x07) << 8) | (s->config_reg & 0xFC);
+    val = s->config_reg;
+#ifdef TARGET_WORDS_BIGENDIAN
+    val = bswap32(val);
+#endif
+    APB_DPRINTF("config_readl addr " TARGET_FMT_plx " val %x\n", addr,
+                val);
     return val;
 }
 
@@ -209,12 +223,11 @@ static void pci_apb_set_irq(qemu_irq *pic, int irq_num, int level)
 
 PCIBus *pci_apb_init(target_phys_addr_t special_base,
                      target_phys_addr_t mem_base,
-                     qemu_irq *pic)
+                     qemu_irq *pic, PCIBus **bus2, PCIBus **bus3)
 {
     APBState *s;
     PCIDevice *d;
     int pci_mem_config, pci_mem_data, apb_config, pci_ioport;
-    PCIBus *secondary;
 
     s = qemu_mallocz(sizeof(APBState));
     /* Ultrasparc PBM main bus */
@@ -255,9 +268,9 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base,
     d->config[0x0E] = 0x00; // header_type
 
     /* APB secondary busses */
-    secondary = pci_bridge_init(s->bus, 8, 0x108e5000, pci_apb_map_irq,
-                                "Advanced PCI Bus secondary bridge 1");
-    pci_bridge_init(s->bus, 9, 0x108e5000, pci_apb_map_irq,
-                    "Advanced PCI Bus secondary bridge 2");
-    return secondary;
+    *bus2 = pci_bridge_init(s->bus, 8, 0x108e5000, pci_apb_map_irq,
+                            "Advanced PCI Bus secondary bridge 1");
+    *bus3 = pci_bridge_init(s->bus, 9, 0x108e5000, pci_apb_map_irq,
+                            "Advanced PCI Bus secondary bridge 2");
+    return s->bus;
 }
index f7bdd14..066b969 100644 (file)
@@ -303,12 +303,10 @@ void axisdev88_init (ram_addr_t ram_size, int vga_ram_size,
     }
 
     /* Add the two ethernet blocks.  */
-    nd_table[0].model = nd_table[0].model ? nd_table[0].model : "fseth";
-    eth[0] = etraxfs_eth_init(&nd_table[0], env, pic->irq + 25, 0x30034000);
-    if (nb_nics > 1) {
-        nd_table[1].model = nd_table[1].model ? nd_table[1].model : "fseth";
-        eth[1] = etraxfs_eth_init(&nd_table[1], env, pic->irq + 26, 0x30036000);
-    }
+    eth[0] = etraxfs_eth_init(&nd_table[0], env, pic->irq + 25, 0x30034000, 1);
+    if (nb_nics > 1)
+        eth[1] = etraxfs_eth_init(&nd_table[1], env,
+                                  pic->irq + 26, 0x30036000, 2);
 
     /* The DMA Connector block is missing, hardwire things for now.  */
     etraxfs_dmac_connect_client(etraxfs_dmac, 0, eth[0]);
index 09cb96a..ccf9bc0 100644 (file)
@@ -570,6 +570,21 @@ receive_filter(E1000State *s, const uint8_t *buf, int size)
     return 0;
 }
 
+static void
+e1000_set_link_status(VLANClientState *vc)
+{
+    E1000State *s = vc->opaque;
+    uint32_t old_status = s->mac_reg[STATUS];
+
+    if (vc->link_down)
+        s->mac_reg[STATUS] &= ~E1000_STATUS_LU;
+    else
+        s->mac_reg[STATUS] |= E1000_STATUS_LU;
+
+    if (s->mac_reg[STATUS] != old_status)
+        set_ics(s, 0, E1000_ICR_LSC);
+}
+
 static int
 e1000_can_receive(void *opaque)
 {
@@ -1073,6 +1088,7 @@ pci_e1000_init(PCIBus *bus, NICInfo *nd, int devfn)
 
     d->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
                                  e1000_receive, e1000_can_receive, d);
+    d->vc->link_status_changed = e1000_set_link_status;
 
     qemu_format_nic_info_str(d->vc, d->nd->macaddr);
 
similarity index 85%
rename from hw/slavio_serial.c
rename to hw/escc.c
index 1028ed9..372ad5a 100644 (file)
+++ b/hw/escc.c
@@ -1,5 +1,5 @@
 /*
- * QEMU Sparc SLAVIO serial port emulation
+ * QEMU ESCC (Z8030/Z8530/Z85C30/SCC/ESCC) serial port emulation
  *
  * Copyright (c) 2003-2005 Fabrice Bellard
  *
@@ -22,7 +22,7 @@
  * THE SOFTWARE.
  */
 #include "hw.h"
-#include "sun4m.h"
+#include "escc.h"
 #include "qemu-char.h"
 #include "console.h"
 
@@ -36,7 +36,7 @@
 //#define DEBUG_MOUSE
 
 /*
- * This is the serial port, mouse and keyboard part of chip STP2001
+ * On Sparc32 this is the serial port, mouse and keyboard part of chip STP2001
  * (Slave I/O), also produced as NCR89C105. See
  * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
  *
  * mouse and keyboard ports don't implement all functions and they are
  * only asynchronous. There is no DMA.
  *
+ * Z85C30 is also used on PowerMacs. There are some small differences
+ * between Sparc version (sunzilog) and PowerMac (pmac):
+ *  Offset between control and data registers
+ *  There is some kind of lockup bug, but we can ignore it
+ *  CTS is inverted
+ *  DMA on pmac using DBDMA chip
+ *  pmac can do IRDA and faster rates, sunzilog can only do 38400
+ *  pmac baud rate generator clock is 3.6864 MHz, sunzilog 4.9152 MHz
  */
 
 /*
@@ -102,13 +110,14 @@ typedef struct ChannelState {
     CharDriverState *chr;
     int e0_mode, led_mode, caps_lock_mode, num_lock_mode;
     int disabled;
+    int clock;
 } ChannelState;
 
 struct SerialState {
     struct ChannelState chn[2];
+    int it_shift;
 };
 
-#define SERIAL_SIZE 8
 #define SERIAL_CTRL 0
 #define SERIAL_DATA 1
 
@@ -257,7 +266,7 @@ static uint32_t get_queue(void *opaque)
     return val;
 }
 
-static int slavio_serial_update_irq_chn(ChannelState *s)
+static int escc_update_irq_chn(ChannelState *s)
 {
     if ((((s->wregs[W_INTR] & INTR_TXINT) && s->txint == 1) ||
          // tx ints enabled, pending
@@ -271,23 +280,23 @@ static int slavio_serial_update_irq_chn(ChannelState *s)
     return 0;
 }
 
-static void slavio_serial_update_irq(ChannelState *s)
+static void escc_update_irq(ChannelState *s)
 {
     int irq;
 
-    irq = slavio_serial_update_irq_chn(s);
-    irq |= slavio_serial_update_irq_chn(s->otherchn);
+    irq = escc_update_irq_chn(s);
+    irq |= escc_update_irq_chn(s->otherchn);
 
     SER_DPRINTF("IRQ = %d\n", irq);
     qemu_set_irq(s->irq, irq);
 }
 
-static void slavio_serial_reset_chn(ChannelState *s)
+static void escc_reset_chn(ChannelState *s)
 {
     int i;
 
     s->reg = 0;
-    for (i = 0; i < SERIAL_SIZE; i++) {
+    for (i = 0; i < SERIAL_REGS; i++) {
         s->rregs[i] = 0;
         s->wregs[i] = 0;
     }
@@ -311,11 +320,11 @@ static void slavio_serial_reset_chn(ChannelState *s)
     clear_queue(s);
 }
 
-static void slavio_serial_reset(void *opaque)
+static void escc_reset(void *opaque)
 {
     SerialState *s = opaque;
-    slavio_serial_reset_chn(&s->chn[0]);
-    slavio_serial_reset_chn(&s->chn[1]);
+    escc_reset_chn(&s->chn[0]);
+    escc_reset_chn(&s->chn[1]);
 }
 
 static inline void set_rxint(ChannelState *s)
@@ -339,7 +348,7 @@ static inline void set_rxint(ChannelState *s)
         s->rregs[R_INTR] |= INTR_RXINTA;
     else
         s->otherchn->rregs[R_INTR] |= INTR_RXINTB;
-    slavio_serial_update_irq(s);
+    escc_update_irq(s);
 }
 
 static inline void set_txint(ChannelState *s)
@@ -360,7 +369,7 @@ static inline void set_txint(ChannelState *s)
         s->rregs[R_INTR] |= INTR_TXINTA;
     else
         s->otherchn->rregs[R_INTR] |= INTR_TXINTB;
-    slavio_serial_update_irq(s);
+    escc_update_irq(s);
 }
 
 static inline void clr_rxint(ChannelState *s)
@@ -382,7 +391,7 @@ static inline void clr_rxint(ChannelState *s)
     }
     if (s->txint)
         set_txint(s);
-    slavio_serial_update_irq(s);
+    escc_update_irq(s);
 }
 
 static inline void clr_txint(ChannelState *s)
@@ -404,10 +413,10 @@ static inline void clr_txint(ChannelState *s)
     }
     if (s->rxint)
         set_rxint(s);
-    slavio_serial_update_irq(s);
+    escc_update_irq(s);
 }
 
-static void slavio_serial_update_parameters(ChannelState *s)
+static void escc_update_parameters(ChannelState *s)
 {
     int speed, parity, data_bits, stop_bits;
     QEMUSerialSetParams ssp;
@@ -442,7 +451,7 @@ static void slavio_serial_update_parameters(ChannelState *s)
         data_bits = 8;
         break;
     }
-    speed = 2457600 / ((s->wregs[W_BRGLO] | (s->wregs[W_BRGHI] << 8)) + 2);
+    speed = s->clock / ((s->wregs[W_BRGLO] | (s->wregs[W_BRGHI] << 8)) + 2);
     switch (s->wregs[W_TXCTRL1] & TXCTRL1_CLKMSK) {
     case TXCTRL1_CLK1X:
         break;
@@ -466,8 +475,7 @@ static void slavio_serial_update_parameters(ChannelState *s)
     qemu_chr_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
 }
 
-static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr,
-                                     uint32_t val)
+static void escc_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
 {
     SerialState *serial = opaque;
     ChannelState *s;
@@ -475,8 +483,8 @@ static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr,
     int newreg, channel;
 
     val &= 0xff;
-    saddr = (addr & 3) >> 1;
-    channel = addr >> 2;
+    saddr = (addr >> serial->it_shift) & 1;
+    channel = (addr >> (serial->it_shift + 1)) & 1;
     s = &serial->chn[channel];
     switch (saddr) {
     case SERIAL_CTRL:
@@ -513,13 +521,13 @@ static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr,
         case W_TXCTRL1:
         case W_TXCTRL2:
             s->wregs[s->reg] = val;
-            slavio_serial_update_parameters(s);
+            escc_update_parameters(s);
             break;
         case W_BRGLO:
         case W_BRGHI:
             s->wregs[s->reg] = val;
             s->rregs[s->reg] = val;
-            slavio_serial_update_parameters(s);
+            escc_update_parameters(s);
             break;
         case W_MINTR:
             switch (val & MINTR_RST_MASK) {
@@ -527,13 +535,13 @@ static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr,
             default:
                 break;
             case MINTR_RST_B:
-                slavio_serial_reset_chn(&serial->chn[0]);
+                escc_reset_chn(&serial->chn[0]);
                 return;
             case MINTR_RST_A:
-                slavio_serial_reset_chn(&serial->chn[1]);
+                escc_reset_chn(&serial->chn[1]);
                 return;
             case MINTR_RST_ALL:
-                slavio_serial_reset(serial);
+                escc_reset(serial);
                 return;
             }
             break;
@@ -564,7 +572,7 @@ static void slavio_serial_mem_writeb(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static uint32_t slavio_serial_mem_readb(void *opaque, target_phys_addr_t addr)
+static uint32_t escc_mem_readb(void *opaque, target_phys_addr_t addr)
 {
     SerialState *serial = opaque;
     ChannelState *s;
@@ -572,8 +580,8 @@ static uint32_t slavio_serial_mem_readb(void *opaque, target_phys_addr_t addr)
     uint32_t ret;
     int channel;
 
-    saddr = (addr & 3) >> 1;
-    channel = addr >> 2;
+    saddr = (addr >> serial->it_shift) & 1;
+    channel = (addr >> (serial->it_shift + 1)) & 1;
     s = &serial->chn[channel];
     switch (saddr) {
     case SERIAL_CTRL:
@@ -624,7 +632,7 @@ static void serial_receive_byte(ChannelState *s, int ch)
 static void serial_receive_break(ChannelState *s)
 {
     s->rregs[R_STATUS] |= STATUS_BRK;
-    slavio_serial_update_irq(s);
+    escc_update_irq(s);
 }
 
 static void serial_receive1(void *opaque, const uint8_t *buf, int size)
@@ -640,19 +648,19 @@ static void serial_event(void *opaque, int event)
         serial_receive_break(s);
 }
 
-static CPUReadMemoryFunc *slavio_serial_mem_read[3] = {
-    slavio_serial_mem_readb,
+static CPUReadMemoryFunc *escc_mem_read[3] = {
+    escc_mem_readb,
     NULL,
     NULL,
 };
 
-static CPUWriteMemoryFunc *slavio_serial_mem_write[3] = {
-    slavio_serial_mem_writeb,
+static CPUWriteMemoryFunc *escc_mem_write[3] = {
+    escc_mem_writeb,
     NULL,
     NULL,
 };
 
-static void slavio_serial_save_chn(QEMUFile *f, ChannelState *s)
+static void escc_save_chn(QEMUFile *f, ChannelState *s)
 {
     uint32_t tmp = 0;
 
@@ -668,15 +676,15 @@ static void slavio_serial_save_chn(QEMUFile *f, ChannelState *s)
     qemu_put_buffer(f, s->rregs, SERIAL_REGS);
 }
 
-static void slavio_serial_save(QEMUFile *f, void *opaque)
+static void escc_save(QEMUFile *f, void *opaque)
 {
     SerialState *s = opaque;
 
-    slavio_serial_save_chn(f, &s->chn[0]);
-    slavio_serial_save_chn(f, &s->chn[1]);
+    escc_save_chn(f, &s->chn[0]);
+    escc_save_chn(f, &s->chn[1]);
 }
 
-static int slavio_serial_load_chn(QEMUFile *f, ChannelState *s, int version_id)
+static int escc_load_chn(QEMUFile *f, ChannelState *s, int version_id)
 {
     uint32_t tmp;
 
@@ -698,43 +706,49 @@ static int slavio_serial_load_chn(QEMUFile *f, ChannelState *s, int version_id)
     return 0;
 }
 
-static int slavio_serial_load(QEMUFile *f, void *opaque, int version_id)
+static int escc_load(QEMUFile *f, void *opaque, int version_id)
 {
     SerialState *s = opaque;
     int ret;
 
-    ret = slavio_serial_load_chn(f, &s->chn[0], version_id);
+    ret = escc_load_chn(f, &s->chn[0], version_id);
     if (ret != 0)
         return ret;
-    ret = slavio_serial_load_chn(f, &s->chn[1], version_id);
+    ret = escc_load_chn(f, &s->chn[1], version_id);
     return ret;
 
 }
 
-SerialState *slavio_serial_init(target_phys_addr_t base, qemu_irq irq,
-                                CharDriverState *chr1, CharDriverState *chr2)
+int escc_init(target_phys_addr_t base, qemu_irq irqA, qemu_irq irqB,
+              CharDriverState *chrA, CharDriverState *chrB,
+              int clock, int it_shift)
 {
-    int slavio_serial_io_memory, i;
+    int escc_io_memory, i;
     SerialState *s;
 
     s = qemu_mallocz(sizeof(SerialState));
     if (!s)
-        return NULL;
+        return 0;
 
-    slavio_serial_io_memory = cpu_register_io_memory(0, slavio_serial_mem_read,
-                                                     slavio_serial_mem_write,
-                                                     s);
-    cpu_register_physical_memory(base, SERIAL_SIZE, slavio_serial_io_memory);
+    escc_io_memory = cpu_register_io_memory(0, escc_mem_read,
+                                            escc_mem_write,
+                                            s);
+    if (base)
+        cpu_register_physical_memory(base, ESCC_SIZE << it_shift,
+                                     escc_io_memory);
 
-    s->chn[0].chr = chr1;
-    s->chn[1].chr = chr2;
+    s->it_shift = it_shift;
+    s->chn[0].chr = chrB;
+    s->chn[1].chr = chrA;
     s->chn[0].disabled = 0;
     s->chn[1].disabled = 0;
+    s->chn[0].irq = irqB;
+    s->chn[1].irq = irqA;
 
     for (i = 0; i < 2; i++) {
-        s->chn[i].irq = irq;
         s->chn[i].chn = 1 - i;
         s->chn[i].type = ser;
+        s->chn[i].clock = clock / 2;
         if (s->chn[i].chr) {
             qemu_chr_add_handlers(s->chn[i].chr, serial_can_receive,
                                   serial_receive1, serial_event, &s->chn[i]);
@@ -742,11 +756,13 @@ SerialState *slavio_serial_init(target_phys_addr_t base, qemu_irq irq,
     }
     s->chn[0].otherchn = &s->chn[1];
     s->chn[1].otherchn = &s->chn[0];
-    register_savevm("slavio_serial", base, 2, slavio_serial_save,
-                    slavio_serial_load, s);
-    qemu_register_reset(slavio_serial_reset, s);
-    slavio_serial_reset(s);
-    return s;
+    if (base)
+        register_savevm("escc", base, 2, escc_save, escc_load, s);
+    else
+        register_savevm("escc", -1, 2, escc_save, escc_load, s);
+    qemu_register_reset(escc_reset, s);
+    escc_reset(s);
+    return escc_io_memory;
 }
 
 static const uint8_t keycodes[128] = {
@@ -887,7 +903,7 @@ static void sunmouse_event(void *opaque,
 }
 
 void slavio_serial_ms_kbd_init(target_phys_addr_t base, qemu_irq irq,
-                               int disabled)
+                               int disabled, int clock, int it_shift)
 {
     int slavio_serial_io_memory, i;
     SerialState *s;
@@ -895,10 +911,13 @@ void slavio_serial_ms_kbd_init(target_phys_addr_t base, qemu_irq irq,
     s = qemu_mallocz(sizeof(SerialState));
     if (!s)
         return;
+
+    s->it_shift = it_shift;
     for (i = 0; i < 2; i++) {
         s->chn[i].irq = irq;
         s->chn[i].chn = 1 - i;
         s->chn[i].chr = NULL;
+        s->chn[i].clock = clock / 2;
     }
     s->chn[0].otherchn = &s->chn[1];
     s->chn[1].otherchn = &s->chn[0];
@@ -907,16 +926,16 @@ void slavio_serial_ms_kbd_init(target_phys_addr_t base, qemu_irq irq,
     s->chn[0].disabled = disabled;
     s->chn[1].disabled = disabled;
 
-    slavio_serial_io_memory = cpu_register_io_memory(0, slavio_serial_mem_read,
-                                                     slavio_serial_mem_write,
+    slavio_serial_io_memory = cpu_register_io_memory(0, escc_mem_read,
+                                                     escc_mem_write,
                                                      s);
-    cpu_register_physical_memory(base, SERIAL_SIZE, slavio_serial_io_memory);
+    cpu_register_physical_memory(base, ESCC_SIZE << it_shift,
+                                 slavio_serial_io_memory);
 
     qemu_add_mouse_event_handler(sunmouse_event, &s->chn[0], 0,
                                  "QEMU Sun Mouse");
     qemu_add_kbd_event_handler(sunkbd_event, &s->chn[1]);
-    register_savevm("slavio_serial_mouse", base, 2, slavio_serial_save,
-                    slavio_serial_load, s);
-    qemu_register_reset(slavio_serial_reset, s);
-    slavio_serial_reset(s);
+    register_savevm("slavio_serial_mouse", base, 2, escc_save, escc_load, s);
+    qemu_register_reset(escc_reset, s);
+    escc_reset(s);
 }
diff --git a/hw/escc.h b/hw/escc.h
new file mode 100644 (file)
index 0000000..015b9d0
--- /dev/null
+++ b/hw/escc.h
@@ -0,0 +1,8 @@
+/* escc.c */
+#define ESCC_SIZE 4
+int escc_init(target_phys_addr_t base, qemu_irq irqA, qemu_irq irqB,
+              CharDriverState *chrA, CharDriverState *chrB,
+              int clock, int it_shift);
+
+void slavio_serial_ms_kbd_init(target_phys_addr_t base, qemu_irq irq,
+                               int disabled, int clock, int it_shift);
index 01b5a6e..e409a94 100644 (file)
@@ -94,12 +94,10 @@ void bareetraxfs_init (ram_addr_t ram_size, int vga_ram_size,
     }
 
     /* Add the two ethernet blocks.  */
-    nd_table[0].model = nd_table[0].model ? nd_table[0].model : "fseth";
-    eth[0] = etraxfs_eth_init(&nd_table[0], env, pic->irq + 25, 0x30034000);
-    if (nb_nics > 1) {
-        nd_table[1].model = nd_table[1].model ? nd_table[1].model : "fseth";
-        eth[1] = etraxfs_eth_init(&nd_table[1], env, pic->irq + 26, 0x30036000);
-    }
+    eth[0] = etraxfs_eth_init(&nd_table[0], env, pic->irq + 25, 0x30034000, 1);
+    if (nb_nics > 1)
+        eth[1] = etraxfs_eth_init(&nd_table[1], env,
+                                  pic->irq + 26, 0x30036000, 2);
 
     /* The DMA Connector block is missing, hardwire things for now.  */
     etraxfs_dmac_connect_client(etraxfs_dmac, 0, eth[0]);
index 0c9fdbb..17dca29 100644 (file)
@@ -37,6 +37,6 @@ struct etraxfs_pic *etraxfs_pic_init(CPUState *env, target_phys_addr_t base);
 void etraxfs_timer_init(CPUState *env, qemu_irq *irqs, qemu_irq *nmi,
                         target_phys_addr_t base);
 void *etraxfs_eth_init(NICInfo *nd, CPUState *env,
-                       qemu_irq *irq, target_phys_addr_t base);
+                       qemu_irq *irq, target_phys_addr_t base, int phyaddr);
 void etraxfs_ser_init(CPUState *env, qemu_irq *irq, CharDriverState *chr,
                       target_phys_addr_t base);
index 239e0d8..cce8917 100644 (file)
@@ -45,6 +45,8 @@ struct qemu_phy
 {
        uint32_t regs[32];
 
+       int link;
+
        unsigned int (*read)(struct qemu_phy *phy, unsigned int req);
        void (*write)(struct qemu_phy *phy, unsigned int req, 
                      unsigned int data);
@@ -59,13 +61,15 @@ static unsigned int tdk_read(struct qemu_phy *phy, unsigned int req)
 
        switch (regnum) {
                case 1:
+                       if (!phy->link)
+                               break;
                        /* MR1.  */
                        /* Speeds and modes.  */
                        r |= (1 << 13) | (1 << 14);
                        r |= (1 << 11) | (1 << 12);
                        r |= (1 << 5); /* Autoneg complete.  */
                        r |= (1 << 3); /* Autoneg able.  */
-                       r |= (1 << 2); /* Link.  */
+                       r |= (1 << 2); /* link.  */
                        break;
                case 5:
                        /* Link partner ability.
@@ -83,6 +87,9 @@ static unsigned int tdk_read(struct qemu_phy *phy, unsigned int req)
                        int duplex = 0;
                        int speed_100 = 0;
 
+                       if (!phy->link)
+                               break;
+
                        /* Are we advertising 100 half or 100 duplex ? */
                        speed_100 = !!(phy->regs[4] & ADVERTISE_100HALF);
                        speed_100 |= !!(phy->regs[4] & ADVERTISE_100FULL);
@@ -125,6 +132,7 @@ tdk_init(struct qemu_phy *phy)
        phy->regs[3] = 0xe400;
        /* Autonegotiation advertisement reg.  */
        phy->regs[4] = 0x01E1;
+       phy->link = 1;
 
        phy->read = tdk_read;
        phy->write = tdk_write;
@@ -530,6 +538,13 @@ static int eth_tx_push(void *opaque, unsigned char *buf, int len)
        return len;
 }
 
+static void eth_set_link(VLANClientState *vc)
+{
+       struct fs_eth *eth = vc->opaque;
+       D(printf("%s %d\n", __func__, vc->link_down));
+       eth->phy.link = !vc->link_down;
+}
+
 static CPUReadMemoryFunc *eth_read[] = {
        NULL, NULL,
        &eth_readl,
@@ -541,11 +556,13 @@ static CPUWriteMemoryFunc *eth_write[] = {
 };
 
 void *etraxfs_eth_init(NICInfo *nd, CPUState *env, 
-                      qemu_irq *irq, target_phys_addr_t base)
+                      qemu_irq *irq, target_phys_addr_t base, int phyaddr)
 {
        struct etraxfs_dma_client *dma = NULL;  
        struct fs_eth *eth = NULL;
 
+       qemu_check_nic_model(nd, "fseth");
+
        dma = qemu_mallocz(sizeof *dma * 2);
        if (!dma)
                return NULL;
@@ -565,7 +582,7 @@ void *etraxfs_eth_init(NICInfo *nd, CPUState *env,
        eth->dma_in = dma + 1;
 
        /* Connect the phy.  */
-       eth->phyaddr = 1;
+       eth->phyaddr = phyaddr & 0x1f;
        tdk_init(&eth->phy);
        mdio_attach(&eth->mdio_bus, &eth->phy, eth->phyaddr);
 
@@ -574,6 +591,8 @@ void *etraxfs_eth_init(NICInfo *nd, CPUState *env,
 
        eth->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
                                       eth_receive, eth_can_receive, eth);
+       eth->vc->opaque = eth;
+       eth->vc->link_status_changed = eth_set_link;
 
        return dma;
   err:
index faba93d..70e3b9e 100644 (file)
@@ -26,6 +26,18 @@ void nand_getpins(struct nand_flash_s *s, int *rb);
 void nand_setio(struct nand_flash_s *s, uint8_t value);
 uint8_t nand_getio(struct nand_flash_s *s);
 
+/* nand_bpage.c */
+struct nand_bflash_s;
+struct nand_bflash_s *nandb_init(int manf_id, int chip_id);
+void nandb_write_data16(struct nand_bflash_s *s, uint16_t value);
+uint16_t nandb_read_data16(struct nand_bflash_s *s);
+void nandb_write_data8(struct nand_bflash_s *s, uint8_t value);
+uint8_t nandb_read_data8(struct nand_bflash_s *s);
+void nandb_write_address(struct nand_bflash_s *s, uint16_t value);
+void nandb_write_command(struct nand_bflash_s *s, uint16_t value);
+
+
+
 #define NAND_MFR_TOSHIBA       0x98
 #define NAND_MFR_SAMSUNG       0xec
 #define NAND_MFR_FUJITSU       0x04
index 915390a..7dd41f7 100644 (file)
--- a/hw/ide.c
+++ b/hw/ide.c
@@ -955,7 +955,7 @@ static void ide_read_dma_cb(void *opaque, int ret)
     s->io_buffer_index = 0;
     s->io_buffer_size = n * 512;
 #ifdef DEBUG_AIO
-    printf("aio_read: sector_num=%lld n=%d\n", sector_num, n);
+    printf("aio_read: sector_num=%" PRId64 " n=%d\n", sector_num, n);
 #endif
     bm->aiocb = bdrv_aio_read(s->bs, sector_num, s->io_buffer, n,
                               ide_read_dma_cb, bm);
@@ -1067,7 +1067,7 @@ static void ide_write_dma_cb(void *opaque, int ret)
     if (dma_buf_rw(bm, 0) == 0)
         goto eot;
 #ifdef DEBUG_AIO
-    printf("aio_write: sector_num=%lld n=%d\n", sector_num, n);
+    printf("aio_write: sector_num=%" PRId64 " n=%d\n", sector_num, n);
 #endif
     bm->aiocb = bdrv_aio_write(s->bs, sector_num, s->io_buffer, n,
                                ide_write_dma_cb, bm);
@@ -2467,7 +2467,8 @@ static uint32_t ide_ioport_read(void *opaque, uint32_t addr1)
         ret = 0xff;
         break;
     case 1:
-        if (!ide_if[0].bs && !ide_if[1].bs)
+        if ((!ide_if[0].bs && !ide_if[1].bs) ||
+            (s != ide_if && !s->bs))
             ret = 0;
         else if (!hob)
             ret = s->error;
@@ -3185,9 +3186,10 @@ void pci_cmd646_ide_init(PCIBus *bus, BlockDriverState **hd_table,
     pci_conf[0x0b] = 0x01; // class_base = PCI_mass_storage
     pci_conf[0x0e] = 0x00; // header_type
 
+    pci_conf[0x51] = 0x04; // enable IDE0
     if (secondary_ide_enabled) {
         /* XXX: if not enabled, really disable the seconday IDE controller */
-        pci_conf[0x51] = 0x80; /* enable IDE1 */
+        pci_conf[0x51] |= 0x08; /* enable IDE1 */
     }
 
     pci_register_io_region((PCIDevice *)d, 0, 0x8,
index a2d3d43..fdbfe20 100644 (file)
@@ -497,18 +497,8 @@ static void integratorcp_init(ram_addr_t ram_size, int vga_ram_size,
         exit(1);
     }
     pl181_init(0x1c000000, drives_table[sd].bdrv, pic[23], pic[24]);
-    if (nd_table[0].vlan) {
-        if (nd_table[0].model == NULL
-            || strcmp(nd_table[0].model, "smc91c111") == 0) {
-            smc91c111_init(&nd_table[0], 0xc8000000, pic[27]);
-        } else if (strcmp(nd_table[0].model, "?") == 0) {
-            fprintf(stderr, "qemu: Supported NICs: smc91c111\n");
-            exit (1);
-        } else {
-            fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model);
-            exit (1);
-        }
-    }
+    if (nd_table[0].vlan)
+        smc91c111_init(&nd_table[0], 0xc8000000, pic[27]);
     pl110_init(ds, 0xc0000000, pic[22], 0);
 
     integrator_binfo.ram_size = ram_size;
index 7f0d9f7..2a98dfb 100644 (file)
@@ -25,6 +25,7 @@
 #include "hw.h"
 #include "ppc_mac.h"
 #include "pci.h"
+#include "escc.h"
 
 typedef struct macio_state_t macio_state_t;
 struct macio_state_t {
@@ -32,6 +33,7 @@ struct macio_state_t {
     int pic_mem_index;
     int dbdma_mem_index;
     int cuda_mem_index;
+    int escc_mem_index;
     void *nvram;
     int nb_ide;
     int ide_mem_index[4];
@@ -59,6 +61,10 @@ static void macio_map (PCIDevice *pci_dev, int region_num,
         cpu_register_physical_memory(addr + 0x08000, 0x1000,
                                      macio_state->dbdma_mem_index);
     }
+    if (macio_state->escc_mem_index >= 0) {
+        cpu_register_physical_memory(addr + 0x13000, ESCC_SIZE << 4,
+                                     macio_state->escc_mem_index);
+    }
     if (macio_state->cuda_mem_index >= 0) {
         cpu_register_physical_memory(addr + 0x16000, 0x2000,
                                      macio_state->cuda_mem_index);
@@ -75,7 +81,7 @@ static void macio_map (PCIDevice *pci_dev, int region_num,
 
 void macio_init (PCIBus *bus, int device_id, int is_oldworld, int pic_mem_index,
                  int dbdma_mem_index, int cuda_mem_index, void *nvram,
-                 int nb_ide, int *ide_mem_index)
+                 int nb_ide, int *ide_mem_index, int escc_mem_index)
 {
     PCIDevice *d;
     macio_state_t *macio_state;
@@ -89,6 +95,7 @@ void macio_init (PCIBus *bus, int device_id, int is_oldworld, int pic_mem_index,
     macio_state->pic_mem_index = pic_mem_index;
     macio_state->dbdma_mem_index = dbdma_mem_index;
     macio_state->cuda_mem_index = cuda_mem_index;
+    macio_state->escc_mem_index = escc_mem_index;
     macio_state->nvram = nvram;
     if (nb_ide > 4)
         nb_ide = 4;
index 71ba3fb..f06c25a 100644 (file)
@@ -241,18 +241,8 @@ static void mcf5208evb_init(ram_addr_t ram_size, int vga_ram_size,
         fprintf(stderr, "Too many NICs\n");
         exit(1);
     }
-    if (nd_table[0].vlan) {
-        if (nd_table[0].model == NULL
-            || strcmp(nd_table[0].model, "mcf_fec") == 0) {
-            mcf_fec_init(&nd_table[0], 0xfc030000, pic + 36);
-        } else if (strcmp(nd_table[0].model, "?") == 0) {
-            fprintf(stderr, "qemu: Supported NICs: mcf_fec\n");
-            exit (1);
-        } else {
-            fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model);
-            exit (1);
-        }
-    }
+    if (nd_table[0].vlan)
+        mcf_fec_init(&nd_table[0], 0xfc030000, pic + 36);
 
     /*  0xfc000000 SCM.  */
     /*  0xfc004000 XBS.  */
index 49ae69b..413c569 100644 (file)
@@ -446,6 +446,8 @@ void mcf_fec_init(NICInfo *nd, target_phys_addr_t base, qemu_irq *irq)
     mcf_fec_state *s;
     int iomemtype;
 
+    qemu_check_nic_model(nd, "mcf_fec");
+
     s = (mcf_fec_state *)qemu_mallocz(sizeof(mcf_fec_state));
     s->irq = irq;
     iomemtype = cpu_register_io_memory(0, mcf_fec_readfn,
index ad48b4f..f7e4c62 100644 (file)
@@ -6,12 +6,23 @@
    IRQ may change */
 void cpu_mips_update_irq(CPUState *env)
 {
+//     if (interrupt_request & CPU_INTERRUPT_HARD)
+//{
+//if (env->CP0_Cause&0x400)
+//{
+//     printf("cpu_mips_update_irq \n");
+//     printf("env->CP0_Status %x env->CP0_Cause %x CP0Ca_IP_mask %x \n",env->CP0_Status,env->CP0_Cause,CP0Ca_IP_mask);
+//     printf("CP0St_IE %x CP0St_EXL %x CP0St_ERL %x \n",CP0St_IE,CP0St_EXL,CP0St_ERL);
+//     printf("env->hflags %x MIPS_HFLAG_DM %x \n",env->hflags ,MIPS_HFLAG_DM);
+//}
+//}
     if ((env->CP0_Status & (1 << CP0St_IE)) &&
         !(env->CP0_Status & (1 << CP0St_EXL)) &&
         !(env->CP0_Status & (1 << CP0St_ERL)) &&
         !(env->hflags & MIPS_HFLAG_DM)) {
         if ((env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
             !(env->interrupt_request & CPU_INTERRUPT_HARD)) {
+            printf("cpu_mips_update_irq \n");
             cpu_interrupt(env, CPU_INTERRUPT_HARD);
        }
     } else
@@ -26,9 +37,15 @@ static void cpu_mips_irq_request(void *opaque, int irq, int level)
         return;
 
     if (level) {
-        env->CP0_Cause |= 1 << (irq + CP0Ca_IP);
+        env->CP0_Cause |= 1 << (irq + CP0Ca_IP);
+        if (env->CP0_Status & 0x1)
+               {
+        printf("irq %d env->CP0_Cause %x \n",irq,env->CP0_Cause);
+        printf("status %x\n",env->CP0_Status);
+               }
     } else {
         env->CP0_Cause &= ~(1 << (irq + CP0Ca_IP));
+        //printf("clear irq %d env->CP0_Cause %x \n",irq,env->CP0_Cause);
     }
     cpu_mips_update_irq(env);
 }
index 07c8c4c..28f4e13 100755 (executable)
@@ -1,7 +1,7 @@
 /*
  * QEMU JZ Soc emulation
  *
- * Copyright (c) 2008 yajin (yajin@vm-kernel.org)
+ * Copyright (c) 2009 yajin (yajin@vm-kernel.org)
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
 
 #include "hw.h"
 #include "mips.h"
-#include "mips_jz.h"
 #include "sysemu.h"
 #include "qemu-timer.h"
 #include "qemu-char.h"
 #include "flash.h"
 #include "soc_dma.h"
 #include "audio/audio.h"
+#include "pc.h"
+#include "osdep.h"
+#include "mips_jz.h"
+#include "console.h"
 
-#define DEBUG_CPM                     (1<<0x1)
+#define DEBUG                   /*global debug on/off */
 
-#define  DEBUG_FLAG  (DEBUG_CPM)
+#define DEBUG_CPM                     (1<<0x0)
+#define DEBUG_EMC                     (1<<0x1)
+#define DEBUG_GPIO                    (1<<0x2)
+#define DEBUG_RTC                       (1<<0x3)
+#define DEBUG_TCU                       (1<<0x4)
+#define DEBUG_LCDC                      (1<<0x5)
+#define DEBUG_DMA                      (1<<0x6)
+#define  DEBUG_FLAG                 0//DEBUG_TCU// (DEBUG_CPM|DEBUG_EMC|DEBUG_GPIO  \
+                                                                                                               //      | DEBUG_RTC | DEBUG_TCU | DEBUG_LCDC | DEBUG_DMA)
 
 
 #ifdef DEBUG
-
 FILE *fp;
-static void debug_init()
+static void debug_init(void)
 {
     fp = fopen("jz4740.txt", "w+");
     if (fp == NULL)
@@ -79,7 +89,7 @@ static void debug_out(uint32_t flag, const char *format, ...)
 }
 #endif
 
-static uint32_t jz4740_badwidth_read8(void *opaque, target_phys_addr_t addr)
+uint32_t jz4740_badwidth_read8(void *opaque, target_phys_addr_t addr)
 {
     uint8_t ret;
 
@@ -88,8 +98,8 @@ static uint32_t jz4740_badwidth_read8(void *opaque, target_phys_addr_t addr)
     return ret;
 }
 
-static void jz4740_badwidth_write8(void *opaque, target_phys_addr_t addr,
-                                   uint32_t value)
+void jz4740_badwidth_write8(void *opaque, target_phys_addr_t addr,
+                            uint32_t value)
 {
     uint8_t val8 = value;
 
@@ -97,7 +107,7 @@ static void jz4740_badwidth_write8(void *opaque, target_phys_addr_t addr,
     cpu_physical_memory_write(addr, (void *) &val8, 1);
 }
 
-static uint32_t jz4740_badwidth_read16(void *opaque, target_phys_addr_t addr)
+uint32_t jz4740_badwidth_read16(void *opaque, target_phys_addr_t addr)
 {
     uint16_t ret;
     JZ4740_16B_REG(addr);
@@ -105,8 +115,8 @@ static uint32_t jz4740_badwidth_read16(void *opaque, target_phys_addr_t addr)
     return ret;
 }
 
-static void jz4740_badwidth_write16(void *opaque, target_phys_addr_t addr,
-                                    uint32_t value)
+void jz4740_badwidth_write16(void *opaque, target_phys_addr_t addr,
+                             uint32_t value)
 {
     uint16_t val16 = value;
 
@@ -114,7 +124,7 @@ static void jz4740_badwidth_write16(void *opaque, target_phys_addr_t addr,
     cpu_physical_memory_write(addr, (void *) &val16, 2);
 }
 
-static uint32_t jz4740_badwidth_read32(void *opaque, target_phys_addr_t addr)
+uint32_t jz4740_badwidth_read32(void *opaque, target_phys_addr_t addr)
 {
     uint32_t ret;
 
@@ -123,8 +133,8 @@ static uint32_t jz4740_badwidth_read32(void *opaque, target_phys_addr_t addr)
     return ret;
 }
 
-static void jz4740_badwidth_write32(void *opaque, target_phys_addr_t addr,
-                                    uint32_t value)
+void jz4740_badwidth_write32(void *opaque, target_phys_addr_t addr,
+                             uint32_t value)
 {
     JZ4740_32B_REG(addr);
     cpu_physical_memory_write(addr, (void *) &value, 4);
@@ -145,13 +155,17 @@ struct jz4740_cpm_s
     uint32_t uhccdr;
     uint32_t uhctst;
     uint32_t ssicdr;
+
+    uint32_t lcr;
+    uint32_t clkgr;
+    uint32_t scr;
 };
 
 static void jz4740_dump_clocks(jz_clk parent)
 {
     jz_clk i = parent;
 
-    debug_out(DEBUG_CPM, "clock %x rate 0x%x \n", i->name, i->rate);
+    debug_out(DEBUG_CPM, "clock %s rate %d \n", i->name, i->rate);
     for (i = i->child1; i; i = i->sibling)
         jz4740_dump_clocks(i);
 }
@@ -160,7 +174,9 @@ static inline void jz4740_cpccr_update(struct jz4740_cpm_s *s,
                                        uint32_t new_value)
 {
     uint32_t ldiv, mdiv, pdiv, hdiv, cdiv, udiv;
-    uint32_t div_table[10] = { 1, 2, 3, 4, 6, 8, 12, 16, 24, 32 };
+    uint32_t div_table[10] = {
+        1, 2, 3, 4, 6, 8, 12, 16, 24, 32
+    };
 
     if (unlikely(new_value == s->cpccr))
         return;
@@ -212,7 +228,9 @@ static inline void jz4740_cppcr_update(struct jz4740_cpm_s *s,
                                        uint32_t new_value)
 {
     uint32_t pllm, plln, pllod, pllbp, pllen;
-    uint32_t pll0[4] = { 1, 2, 2, 4 };
+    uint32_t pll0[4] = {
+        1, 2, 2, 4
+    };
 
 
     pllen = new_value & CPM_CPPCR_PLLEN;
@@ -302,13 +320,21 @@ static void jz4740_cpm_write(void *opaque, target_phys_addr_t addr,
                              uint32_t value)
 {
     struct jz4740_cpm_s *s = (struct jz4740_cpm_s *) opaque;
-    int offset = addr - s->base;
 
-    switch (offset)
+    switch (addr)
     {
     case 0x0:
         jz4740_cpccr_update(s, value);
         break;
+    case 0x4:
+        s->lcr = value & 0xff;
+        break;
+    case 0x20:
+        s->clkgr = value & 0xffff;
+        break;
+    case 0x24:
+        s->scr = value & 0xffff;
+        break;
     case 0x10:
         jz4740_cppcr_update(s, value);
         break;
@@ -332,8 +358,8 @@ static void jz4740_cpm_write(void *opaque, target_phys_addr_t addr,
         break;
     default:
         cpu_abort(s->soc->env,
-                  "jz4740_cpm_write undefined addr " JZ_FMT_plx "  value %x \n",
-                  addr, value);
+                  "jz4740_cpm_write undefined addr " JZ_FMT_plx
+                  "  value %x \n", addr, value);
     }
 
 }
@@ -342,12 +368,17 @@ static void jz4740_cpm_write(void *opaque, target_phys_addr_t addr,
 static uint32_t jz474_cpm_read(void *opaque, target_phys_addr_t addr)
 {
     struct jz4740_cpm_s *s = (struct jz4740_cpm_s *) opaque;
-    int offset = addr - s->base;
 
-    switch (offset)
+    switch (addr)
     {
     case 0x0:
         return s->cpccr;
+    case 0x4:
+        return s->lcr;
+    case 0x20:
+        return s->clkgr;
+    case 0x24:
+        return s->scr;
     case 0x10:
         return s->cppcr;
     case 0x60:
@@ -372,15 +403,11 @@ static uint32_t jz474_cpm_read(void *opaque, target_phys_addr_t addr)
 
 
 static CPUReadMemoryFunc *jz4740_cpm_readfn[] = {
-    jz4740_badwidth_read32,
-    jz4740_badwidth_read32,
-    jz474_cpm_read,
+    jz4740_badwidth_read32, jz4740_badwidth_read32, jz474_cpm_read,
 };
 
 static CPUWriteMemoryFunc *jz4740_cpm_writefn[] = {
-    jz4740_badwidth_write32,
-    jz4740_badwidth_write32,
-    jz4740_cpm_write,
+    jz4740_badwidth_write32, jz4740_badwidth_write32, jz4740_cpm_write,
 };
 
 static void jz4740_cpm_reset(struct jz4740_cpm_s *s)
@@ -393,6 +420,10 @@ static void jz4740_cpm_reset(struct jz4740_cpm_s *s)
     s->uhccdr = 0x00000004;
     s->uhctst = 0x0;
     s->ssicdr = 0x00000004;
+
+    s->lcr = 0xf8;
+    s->clkgr = 0x0;
+    s->scr = 0x1500;
 }
 
 static struct jz4740_cpm_s *jz4740_cpm_init(struct jz_state_s *soc)
@@ -431,8 +462,8 @@ struct jz4740_intc_s
 static uint32_t jz4740_intc_read(void *opaque, target_phys_addr_t addr)
 {
     struct jz4740_intc_s *s = (struct jz4740_intc_s *) opaque;
-    int offset = addr - s->base;
-    switch (offset)
+
+    switch (addr)
     {
     case 0x8:
     case 0xc:
@@ -456,12 +487,10 @@ static void jz4740_intc_write(void *opaque, target_phys_addr_t addr,
                               uint32_t value)
 {
     struct jz4740_intc_s *s = (struct jz4740_intc_s *) opaque;
-    int offset = addr - s->base;
 
-    switch (offset)
+    switch (addr)
     {
     case 0x0:
-    case 0x10:
         JZ4740_RO_REG(addr);
         break;
     case 0x4:
@@ -473,6 +502,9 @@ static void jz4740_intc_write(void *opaque, target_phys_addr_t addr,
     case 0xc:
         s->icmr &= ~value;
         break;
+    case 0x10:
+        s->icpr = value;
+        break;
     default:
         cpu_abort(s->soc->env,
                   "jz4740_intc_write undefined addr " JZ_FMT_plx
@@ -482,15 +514,11 @@ static void jz4740_intc_write(void *opaque, target_phys_addr_t addr,
 
 
 static CPUReadMemoryFunc *jz4740_intc_readfn[] = {
-    jz4740_badwidth_read32,
-    jz4740_badwidth_read32,
-    jz4740_intc_read,
+    jz4740_badwidth_read32, jz4740_badwidth_read32, jz4740_intc_read,
 };
 
 static CPUWriteMemoryFunc *jz4740_intc_writefn[] = {
-    jz4740_badwidth_write32,
-    jz4740_badwidth_write32,
-    jz4740_intc_write,
+    jz4740_badwidth_write32, jz4740_badwidth_write32, jz4740_intc_write,
 };
 
 static void jz4740_intc_reset(struct jz4740_intc_s *s)
@@ -505,14 +533,19 @@ static void jz4740_set_irq(void *opaque, int irq, int level)
     struct jz4740_intc_s *s = (struct jz4740_intc_s *) opaque;
     uint32_t irq_mask = 1 << irq;
 
-    s->icsr |= irq_mask;
-    s->icpr |= irq_mask;
-    s->icpr &= ~s->icmr;
-
-    if (((~s->icmr) & irq_mask) && (level))
-        qemu_set_irq(s->parent_irq, 1);
+       s->icpr &= ~irq_mask;
+       if (level)
+    {
+       s->icsr |= irq_mask;
+       //printf("s->icmr %x \n",s->icmr);
+       if (!(s->icmr & irq_mask))
+       {
+               s->icpr |= irq_mask;
+               qemu_set_irq(s->parent_irq, 1);
+       }
+    }
     else
-        qemu_set_irq(s->parent_irq, 0);
+       qemu_set_irq(s->parent_irq, 0);
 }
 
 static qemu_irq *jz4740_intc_init(struct jz_state_s *soc, qemu_irq parent_irq)
@@ -538,6 +571,7 @@ struct jz4740_emc_s
     target_phys_addr_t base;
     struct jz_state_s *soc;
 
+    uint32_t bcr;
     uint32_t smcr1;             /*0x13010014 */
     uint32_t smcr2;             /*0x13010018 */
     uint32_t smcr3;             /*0x1301001c */
@@ -606,29 +640,29 @@ static void jz4740_emc_reset(struct jz4740_emc_s *s)
 static uint32_t jz4740_emc_read8(void *opaque, target_phys_addr_t addr)
 {
     struct jz4740_emc_s *s = (struct jz4740_emc_s *) opaque;
-    int offset = addr - s->base;
-    switch (offset)
+
+    switch (addr)
     {
     case 0x108:
     case 0x109:
     case 0x10a:
     case 0x10b:
-        return (s->nfpar0 >> ((offset - 0x108) * 8)) & 0xff;
+        return (s->nfpar0 >> ((addr - 0x108) * 8)) & 0xff;
     case 0x10c:
     case 0x10d:
     case 0x10e:
     case 0x10f:
-        return (s->nfpar1 >> ((offset - 0x10c) * 8)) & 0xff;
+        return (s->nfpar1 >> ((addr - 0x10c) * 8)) & 0xff;
     case 0x110:
     case 0x111:
     case 0x112:
     case 0x113:
-        return (s->nfpar2 >> ((offset - 0x110) * 8)) & 0xff;
+        return (s->nfpar2 >> ((addr - 0x110) * 8)) & 0xff;
     case 0xa000:
     case 0xa001:
     case 0xa002:
     case 0xa003:
-        return (s->sdmr >> ((offset - 0xa000) * 8)) & 0xff;
+        return (s->sdmr >> ((addr - 0xa000) * 8)) & 0xff;
     default:
         cpu_abort(s->soc->env,
                   "jz4740_emc_read8 undefined addr " JZ_FMT_plx " \n", addr);
@@ -641,30 +675,30 @@ static uint32_t jz4740_emc_read8(void *opaque, target_phys_addr_t addr)
 static uint32_t jz4740_emc_read16(void *opaque, target_phys_addr_t addr)
 {
     struct jz4740_emc_s *s = (struct jz4740_emc_s *) opaque;
-    int offset = addr - s->base;
-    switch (offset)
+
+    switch (addr)
     {
     case 0x108:
     case 0x10a:
-        return (s->nfpar0 >> ((offset - 0x108) * 8)) & 0xffff;
+        return (s->nfpar0 >> ((addr - 0x108) * 8)) & 0xffff;
     case 0x10c:
     case 0x10e:
-        return (s->nfpar1 >> ((offset - 0x10c) * 8)) & 0xffff;
+        return (s->nfpar1 >> ((addr - 0x10c) * 8)) & 0xffff;
     case 0x110:
     case 0x112:
-        return (s->nfpar2 >> ((offset - 0x110) * 8)) & 0xffff;
+        return (s->nfpar2 >> ((addr - 0x110) * 8)) & 0xffff;
     case 0x11c:
     case 0x11e:
-        return (s->nferr0 >> ((offset - 0x11c) * 8)) & 0xffff;
+        return (s->nferr0 >> ((addr - 0x11c) * 8)) & 0xffff;
     case 0x120:
     case 0x122:
-        return (s->nferr1 >> ((offset - 0x120) * 8)) & 0xffff;
+        return (s->nferr1 >> ((addr - 0x120) * 8)) & 0xffff;
     case 0x124:
     case 0x126:
-        return (s->nferr2 >> ((offset - 0x124) * 8)) & 0xffff;
+        return (s->nferr2 >> ((addr - 0x124) * 8)) & 0xffff;
     case 0x128:
     case 0x12a:
-        return (s->nferr3 >> ((offset - 0x128) * 8)) & 0xffff;
+        return (s->nferr3 >> ((addr - 0x128) * 8)) & 0xffff;
     default:
         cpu_abort(s->soc->env,
                   "jz4740_emc_read16 undefined addr " JZ_FMT_plx " \n", addr);
@@ -675,9 +709,11 @@ static uint32_t jz4740_emc_read16(void *opaque, target_phys_addr_t addr)
 static uint32_t jz4740_emc_read32(void *opaque, target_phys_addr_t addr)
 {
     struct jz4740_emc_s *s = (struct jz4740_emc_s *) opaque;
-    int offset = addr - s->base;
-    switch (offset)
+
+    switch (addr)
     {
+    case 0x0:
+        return s->bcr;
     case 0x14:
         return s->smcr1;
     case 0x18:
@@ -733,33 +769,30 @@ static void jz4740_emc_write8(void *opaque, target_phys_addr_t addr,
                               uint32_t value)
 {
     struct jz4740_emc_s *s = (struct jz4740_emc_s *) opaque;
-    int offset = addr - s->base;
 
-    switch (offset)
+    debug_out(DEBUG_EMC, "jz4740_emc_write8 addr %x value %x\n", addr, value);
+
+    switch (addr)
     {
     case 0x108:
     case 0x109:
     case 0x10a:
     case 0x10b:
-        s->nfpar0 |= (value & 0xff) << ((offset - 0x108) * 8);
+        s->nfpar0 |= (value & 0xff) << ((addr - 0x108) * 8);
         break;
     case 0x10c:
     case 0x10d:
     case 0x10e:
     case 0x10f:
-        s->nfpar1 |= (value & 0xff) << ((offset - 0x10c) * 8);
+        s->nfpar1 |= (value & 0xff) << ((addr - 0x10c) * 8);
         break;
     case 0x110:
     case 0x111:
     case 0x112:
     case 0x113:
-        s->nfpar2 |= (value & 0xff) << ((offset - 0x110) * 8);
+        s->nfpar2 |= (value & 0xff) << ((addr - 0x110) * 8);
         break;
-    case 0xa000:
-    case 0xa001:
-    case 0xa002:
-    case 0xa003:
-        s->sdmr |= (value & 0xff) << ((offset - 0x110) * 8);
+    case 0xa000 ... 0xa3ff:
         break;
     default:
         cpu_abort(s->soc->env,
@@ -771,32 +804,32 @@ static void jz4740_emc_write16(void *opaque, target_phys_addr_t addr,
                                uint32_t value)
 {
     struct jz4740_emc_s *s = (struct jz4740_emc_s *) opaque;
-    int offset = addr - s->base;
 
-    switch (offset)
+    debug_out(DEBUG_EMC, "jz4740_emc_write16 addr %x value %x\n", addr, value);
+    switch (addr)
     {
     case 0x108:
     case 0x10a:
-        s->nfpar0 |= (value & 0xffff) << ((offset - 0x108) * 8);
+        s->nfpar0 |= (value & 0xffff) << ((addr - 0x108) * 8);
         break;
     case 0x10c:
     case 0x10e:
-        s->nfpar1 |= (value & 0xffff) << ((offset - 0x10c) * 8);
+        s->nfpar1 |= (value & 0xffff) << ((addr - 0x10c) * 8);
         break;
     case 0x110:
     case 0x112:
-        s->nfpar2 |= (value & 0xffff) << ((offset - 0x110) * 8);
+        s->nfpar2 |= (value & 0xffff) << ((addr - 0x110) * 8);
         break;
     case 0x84:
     case 0x86:
-        s->rtcsr |= (value & 0xffff) << ((offset - 0x84) * 8);
+        s->rtcsr |= (value & 0xffff) << ((addr - 0x84) * 8);
         break;
     case 0x88:
     case 0x8a:
-        s->rtcnt |= (value & 0xffff) << ((offset - 0x88) * 8);
+        s->rtcnt |= (value & 0xffff) << ((addr - 0x88) * 8);
         break;
     case 0x8c:
-        s->rtcor |= (value & 0xffff) << ((offset - 0x8c) * 8);
+        s->rtcor |= (value & 0xffff) << ((addr - 0x8c) * 8);
         break;
     default:
         cpu_abort(s->soc->env,
@@ -814,9 +847,9 @@ static void jz4740_emc_write32(void *opaque, target_phys_addr_t addr,
                                uint32_t value)
 {
     struct jz4740_emc_s *s = (struct jz4740_emc_s *) opaque;
-    int offset = addr - s->base;
 
-    switch (offset)
+    debug_out(DEBUG_EMC, "jz4740_emc_write32 addr %x value %x\n", addr, value);
+    switch (addr)
     {
     case 0x104:
     case 0x11c:
@@ -825,6 +858,9 @@ static void jz4740_emc_write32(void *opaque, target_phys_addr_t addr,
     case 0x128:
         JZ4740_RO_REG(addr);
         break;
+    case 0x0:
+        s->bcr = value;
+        break;
     case 0x14:
         s->smcr1 = value & 0xfff77cf;
         break;
@@ -927,19 +963,16 @@ static void jz4740_emc_write32(void *opaque, target_phys_addr_t addr,
 }
 
 static CPUReadMemoryFunc *jz4740_emc_readfn[] = {
-    jz4740_emc_read8,
-    jz4740_emc_read16,
-    jz4740_emc_read32,
+    jz4740_emc_read8, jz4740_emc_read16, jz4740_emc_read32,
 };
 
 static CPUWriteMemoryFunc *jz4740_emc_writefn[] = {
-    jz4740_emc_write8,
-    jz4740_emc_write16,
-    jz4740_emc_write32,
+    jz4740_emc_write8, jz4740_emc_write16, jz4740_emc_write32,
 };
 
 
-static struct jz4740_emc_s *jz4740_emc_init(struct jz_state_s *soc, qemu_irq irq)
+static struct jz4740_emc_s *jz4740_emc_init(struct jz_state_s *soc,
+                                            qemu_irq irq)
 {
     int iomemtype;
     struct jz4740_emc_s *s = (struct jz4740_emc_s *) qemu_mallocz(sizeof(*s));
@@ -956,6 +989,1639 @@ static struct jz4740_emc_s *jz4740_emc_init(struct jz_state_s *soc, qemu_irq irq
 
 }
 
+struct jz4740_gpio_s
+{
+    qemu_irq irq;
+    target_phys_addr_t base;
+    struct jz_state_s *soc;
+
+    uint32_t papin[4];
+    uint32_t padat[4];
+    uint32_t paim[4];
+    uint32_t pape[4];
+    uint32_t pafun[4];
+    uint32_t pasel[4];
+    uint32_t padir[4];
+    uint32_t patrg[4];
+    uint32_t paflg[4];
+};
+
+static void jz4740_gpio_reset(struct jz4740_gpio_s *s)
+{
+    memset(s->papin, 0x0, sizeof(s->papin));
+    memset(s->padat, 0x0, sizeof(s->padat));
+    memset(s->paim, 0xffffffff, sizeof(s->paim));
+    memset(s->pape, 0x0, sizeof(s->pape));
+    memset(s->pafun, 0x0, sizeof(s->pafun));
+    memset(s->pasel, 0x0, sizeof(s->pasel));
+    memset(s->padir, 0x0, sizeof(s->padir));
+    memset(s->patrg, 0x0, sizeof(s->patrg));
+    memset(s->paflg, 0x0, sizeof(s->paflg));
+}
+
+static uint32_t jz4740_gpio_read(void *opaque, target_phys_addr_t addr)
+{
+    struct jz4740_gpio_s *s = (struct jz4740_gpio_s *) opaque;
+    uint32_t group;
+    debug_out(DEBUG_GPIO, "jz4740_gpio_read addr %x\n", addr);
+
+    switch (addr)
+    {
+    case 0x14:
+    case 0x114:
+    case 0x214:
+    case 0x314:
+    case 0x18:
+    case 0x118:
+    case 0x218:
+    case 0x318:
+    case 0x24:
+    case 0x124:
+    case 0x224:
+    case 0x324:
+    case 0x28:
+    case 0x128:
+    case 0x228:
+    case 0x328:
+    case 0x34:
+    case 0x134:
+    case 0x234:
+    case 0x334:
+    case 0x38:
+    case 0x138:
+    case 0x238:
+    case 0x338:
+    case 0x44:
+    case 0x144:
+    case 0x244:
+    case 0x344:
+    case 0x48:
+    case 0x148:
+    case 0x248:
+    case 0x348:
+    case 0x54:
+    case 0x154:
+    case 0x254:
+    case 0x354:
+    case 0x58:
+    case 0x158:
+    case 0x258:
+    case 0x358:
+    case 0x64:
+    case 0x164:
+    case 0x264:
+    case 0x364:
+    case 0x68:
+    case 0x168:
+    case 0x268:
+    case 0x368:
+    case 0x74:
+    case 0x174:
+    case 0x274:
+    case 0x374:
+    case 0x78:
+    case 0x178:
+    case 0x278:
+    case 0x378:
+    case 0x84:
+    case 0x184:
+    case 0x284:
+    case 0x384:
+        JZ4740_WO_REG(addr);
+        break;
+
+    case 0x0:
+    case 0x100:
+    case 0x200:
+    case 0x300:
+        group = (addr - 0x0) / 0x100;
+        if (addr == 0x200)
+        {
+            /*GPIO(C) PIN 30  -> NAND FLASH R/B. */
+            /*FOR NAND FLASH.PIN 30 ----|_____|------ */
+            s->papin[2] &= 0x40000000;
+            if (s->papin[2])
+                s->papin[2] &= ~0x40000000;
+            else
+                s->papin[2] |= 0x40000000;
+        }
+        return s->papin[group];
+    case 0x10:
+    case 0x110:
+    case 0x210:
+    case 0x310:
+        group = (addr - 0x10) / 0x100;
+        return s->padat[group];
+    case 0x20:
+    case 0x120:
+    case 0x220:
+    case 0x320:
+        group = (addr - 0x20) / 0x100;
+        return s->paim[group];
+    case 0x30:
+    case 0x130:
+    case 0x230:
+    case 0x330:
+        group = (addr - 0x30) / 0x100;
+        return s->pape[group];
+    case 0x40:
+    case 0x140:
+    case 0x240:
+    case 0x340:
+        group = (addr - 0x40) / 0x100;
+        return s->pafun[group];
+    case 0x50:
+    case 0x150:
+    case 0x250:
+    case 0x350:
+        group = (addr - 0x50) / 0x100;
+        return s->pasel[group];
+    case 0x60:
+    case 0x160:
+    case 0x260:
+    case 0x360:
+        group = (addr - 0x60) / 0x100;
+        return s->padir[group];
+    case 0x70:
+    case 0x170:
+    case 0x270:
+    case 0x370:
+        group = (addr - 0x70) / 0x100;
+        return s->patrg[group];
+    case 0x80:
+    case 0x180:
+    case 0x280:
+    case 0x380:
+        group = (addr - 0x80) / 0x100;
+        return s->paflg[group];
+    default:
+        cpu_abort(s->soc->env,
+                  "jz4740_gpio_read undefined addr " JZ_FMT_plx " \n", addr);
+    }
+    return (0);
+}
+
+static void jz4740_gpio_write(void *opaque, target_phys_addr_t addr,
+                              uint32_t value)
+{
+    struct jz4740_gpio_s *s = (struct jz4740_gpio_s *) opaque;
+    uint32_t group;
+
+    debug_out(DEBUG_GPIO, "jz4740_gpio_write addr %x value %x\n", addr, value);
+
+    switch (addr)
+    {
+    case 0x0:
+    case 0x100:
+    case 0x200:
+    case 0x300:
+    case 0x10:
+    case 0x110:
+    case 0x210:
+    case 0x310:
+    case 0x20:
+    case 0x120:
+    case 0x220:
+    case 0x320:
+    case 0x30:
+    case 0x130:
+    case 0x230:
+    case 0x330:
+    case 0x40:
+    case 0x140:
+    case 0x240:
+    case 0x340:
+    case 0x50:
+    case 0x150:
+    case 0x250:
+    case 0x350:
+    case 0x60:
+    case 0x160:
+    case 0x260:
+    case 0x360:
+    case 0x70:
+    case 0x170:
+    case 0x270:
+    case 0x370:
+    case 0x80:
+    case 0x180:
+    case 0x280:
+    case 0x380:
+        JZ4740_RO_REG(addr);
+        break;
+    case 0x14:
+    case 0x114:
+    case 0x214:
+    case 0x314:
+        group = (addr - 0x14) / 0x100;
+        s->padat[group] = value;
+        break;
+    case 0x18:
+    case 0x118:
+    case 0x218:
+    case 0x318:
+        group = (addr - 0x18) / 0x100;
+        s->padat[group] &= ~value;
+        break;
+    case 0x24:
+    case 0x124:
+    case 0x224:
+    case 0x324:
+        group = (addr - 0x24) / 0x100;
+        s->paim[group] = value;
+        break;
+    case 0x28:
+    case 0x128:
+    case 0x228:
+    case 0x328:
+        group = (addr - 0x28) / 0x100;
+        s->paim[group] &= ~value;
+        break;
+    case 0x34:
+    case 0x134:
+    case 0x234:
+    case 0x334:
+        group = (addr - 0x34) / 0x100;
+        s->pape[group] = value;
+        break;
+    case 0x38:
+    case 0x138:
+    case 0x238:
+    case 0x338:
+        group = (addr - 0x38) / 0x100;
+        s->pape[group] &= ~value;
+        break;
+    case 0x44:
+    case 0x144:
+    case 0x244:
+    case 0x344:
+        group = (addr - 0x44) / 0x100;
+        s->pafun[group] = value;
+        break;
+    case 0x48:
+    case 0x148:
+    case 0x248:
+    case 0x348:
+        group = (addr - 0x48) / 0x100;
+        s->pafun[group] &= ~value;
+        break;
+    case 0x54:
+    case 0x154:
+    case 0x254:
+    case 0x354:
+        group = (addr - 0x54) / 0x100;
+        s->pasel[group] = value;
+        break;
+    case 0x58:
+    case 0x158:
+    case 0x258:
+    case 0x358:
+        group = (addr - 0x58) / 0x100;
+        s->pasel[group] &= ~value;
+        break;
+    case 0x64:
+    case 0x164:
+    case 0x264:
+    case 0x364:
+        group = (addr - 0x64) / 0x100;
+        s->padir[group] = value;
+        break;
+    case 0x68:
+    case 0x168:
+    case 0x268:
+    case 0x368:
+        group = (addr - 0x68) / 0x100;
+        s->padir[group] &= ~value;
+        break;
+    case 0x74:
+    case 0x174:
+    case 0x274:
+    case 0x374:
+        group = (addr - 0x74) / 0x100;
+        s->patrg[group] = value;
+        break;
+    case 0x78:
+    case 0x178:
+    case 0x278:
+    case 0x378:
+        group = (addr - 0x78) / 0x100;
+        s->patrg[group] &= ~value;
+        break;
+    case 0x84:
+    case 0x184:
+    case 0x284:
+    case 0x384:
+        group = (addr - 0x74) / 0x100;
+        s->paflg[group] &= ~value;
+        break;
+    default:
+        cpu_abort(s->soc->env,
+                  "jz4740_gpio_write undefined addr " JZ_FMT_plx
+                  "  value %x \n", addr, value);
+
+    }
+
+
+}
+
+
+static CPUReadMemoryFunc *jz4740_gpio_readfn[] = {
+    jz4740_badwidth_read32, jz4740_badwidth_read32, jz4740_gpio_read,
+};
+
+static CPUWriteMemoryFunc *jz4740_gpio_writefn[] = {
+    jz4740_badwidth_write32, jz4740_badwidth_write32, jz4740_gpio_write,
+};
+
+static struct jz4740_gpio_s *jz4740_gpio_init(struct jz_state_s *soc,
+                                              qemu_irq irq)
+{
+    int iomemtype;
+    struct jz4740_gpio_s *s = (struct jz4740_gpio_s *) qemu_mallocz(sizeof(*s));
+    s->base = JZ4740_PHYS_BASE(JZ4740_GPIO_BASE);
+    s->soc = soc;
+    s->irq = irq;
+
+    jz4740_gpio_reset(s);
+
+    iomemtype =
+        cpu_register_io_memory(0, jz4740_gpio_readfn, jz4740_gpio_writefn, s);
+    cpu_register_physical_memory(s->base, 0x00010000, iomemtype);
+    return s;
+
+}
+
+struct jz4740_rtc_s
+{
+    qemu_irq irq;
+    target_phys_addr_t base;
+    struct jz_state_s *soc;
+
+    QEMUTimer *hz_tm;
+    //struct tm tm;
+    //int sec_offset;
+    int64_t next;
+
+    uint32_t rtccr;
+    uint32_t rtcsr;
+    uint32_t rtcsar;
+    uint32_t rtcgr;
+
+    uint32_t hcr;
+    uint32_t hwfcr;
+    uint32_t hrcr;
+    uint32_t hwcr;
+    uint32_t hwrsr;
+    uint32_t hspr;
+
+};
+
+
+static void jz4740_rtc_update_interrupt(struct jz4740_rtc_s *s)
+{
+    if (((s->rtcsr & 0x40) && (s->rtcsr & 0x20))
+        || ((s->rtcsr & 0x10) && (s->rtcsr & 0x8)))
+        qemu_set_irq(s->irq, 1);
+    else
+        qemu_set_irq(s->irq, 0);
+}
+
+static inline void jz4740_rtc_start(struct jz4740_rtc_s *s)
+{
+    s->next = +qemu_get_clock(rt_clock);
+    qemu_mod_timer(s->hz_tm, s->next);
+}
+
+static inline void jz4740_rtc_stop(struct jz4740_rtc_s *s)
+{
+    qemu_del_timer(s->hz_tm);
+    s->next = -qemu_get_clock(rt_clock);
+    if (s->next < 1)
+        s->next = 1;
+}
+
+static void jz4740_rtc_hz(void *opaque)
+{
+    struct jz4740_rtc_s *s = (struct jz4740_rtc_s *) opaque;
+
+    s->next += 1000;
+    qemu_mod_timer(s->hz_tm, s->next);
+    if (s->rtccr & 0x1)
+    {
+        s->rtcsr++;
+        s->rtccr |= 0x40;
+        if (s->rtcsr & 0x4)
+        {
+            if (s->rtcsr == s->rtcsar)
+                s->rtccr |= 0x10;
+        }
+        jz4740_rtc_update_interrupt(s);
+    }
+}
+
+static void jz4740_rtc_reset(struct jz4740_rtc_s *s)
+{
+    s->rtccr = 0x81;
+
+    s->next = 1000;
+
+    /*Maybe rtcsr need to be saved to file */
+    s->rtcsr = 0;
+    //s->sec_offset = 0;
+    //qemu_get_timedate(&s->tm, s->sec_offset);
+    jz4740_rtc_start(s);
+
+}
+
+static uint32_t jz4740_rtc_read(void *opaque, target_phys_addr_t addr)
+{
+    struct jz4740_rtc_s *s = (struct jz4740_rtc_s *) opaque;
+
+    debug_out(DEBUG_RTC, "jz4740_rtc_read addr %x\n", addr);
+    switch (addr)
+    {
+    case 0x0:
+        return s->rtccr | 0x80;
+    case 0x4:
+        return s->rtcsr;
+    case 0x8:
+        return s->rtcsar;
+    case 0xc:
+        return s->rtcgr;
+    case 0x20:
+        return s->hcr;
+    case 0x24:
+        return s->hwfcr;
+    case 0x28:
+        return s->hrcr;
+    case 0x2c:
+        return s->hwcr;
+    case 0x30:
+        return s->hwrsr;
+    case 0x34:
+        return s->hspr;
+    default:
+        cpu_abort(s->soc->env,
+                  "jz4740_rtc_read undefined addr " JZ_FMT_plx "\n", addr);
+    }
+
+    return (0);
+}
+
+static void jz4740_rtc_write(void *opaque, target_phys_addr_t addr,
+                             uint32_t value)
+{
+    struct jz4740_rtc_s *s = (struct jz4740_rtc_s *) opaque;
+
+    debug_out(DEBUG_RTC, "jz4740_rtc_write addr %x value %x\n", addr, value);
+
+    switch (addr)
+    {
+    case 0x0:
+        s->rtccr = value & 0x2d;
+        if (!value & 0x40)
+            s->rtccr &= ~0x40;
+        if (!value & 0x10)
+            s->rtccr &= ~0x10;
+        if (s->rtccr & 0x1)
+        {
+            jz4740_rtc_start(s);
+            jz4740_rtc_update_interrupt(s);
+        }
+        break;
+    case 0x4:
+        s->rtcsr = value;
+        //s->sec_offset = qemu_timedate_diff(&s->tm);
+        break;
+    case 0x8:
+        s->rtcsar = value;
+        break;
+    case 0xc:
+        s->rtcgr = value & 0x13ffffff;
+        break;
+    case 0x20:
+        s->hcr = value & 0x1;
+        break;
+    case 0x24:
+        s->hwfcr = value & 0xffe0;
+        break;
+    case 0x28:
+        s->hrcr = value & 0xfe0;
+        break;
+    case 0x2c:
+        s->hwcr = value & 0x1;
+        break;
+    case 0x30:
+        s->hwrsr = value & 0x33;
+        break;
+    case 0x34:
+        s->hspr = value;
+        break;
+    default:
+        cpu_abort(s->soc->env,
+                  "jz4740_rtc_write undefined addr " JZ_FMT_plx
+                  "  value %x \n", addr, value);
+    }
+
+}
+
+static CPUReadMemoryFunc *jz4740_rtc_readfn[] = {
+    jz4740_badwidth_read32, jz4740_badwidth_read32, jz4740_rtc_read,
+};
+
+static CPUWriteMemoryFunc *jz4740_rtc_writefn[] = {
+    jz4740_badwidth_write32, jz4740_badwidth_write32, jz4740_rtc_write,
+};
+
+static struct jz4740_rtc_s *jz4740_rtc_init(struct jz_state_s *soc,
+                                            qemu_irq irq)
+{
+    int iomemtype;
+    struct jz4740_rtc_s *s = (struct jz4740_rtc_s *) qemu_mallocz(sizeof(*s));
+    s->base = JZ4740_PHYS_BASE(JZ4740_RTC_BASE);
+    s->soc = soc;
+    s->irq = irq;
+
+    s->hz_tm = qemu_new_timer(rt_clock, jz4740_rtc_hz, s);
+
+    jz4740_rtc_reset(s);
+
+    iomemtype =
+        cpu_register_io_memory(0, jz4740_rtc_readfn, jz4740_rtc_writefn, s);
+    cpu_register_physical_memory(s->base, 0x00001000, iomemtype);
+    return s;
+}
+
+struct jz4740_tcu_s
+{
+    qemu_irq tcu_irq0;
+    qemu_irq tcu_irq1;
+    qemu_irq tcu_irq2;
+
+    target_phys_addr_t base;
+    struct jz_state_s *soc;
+
+
+    QEMUTimer *half_timer[8];
+    QEMUTimer *full_timer[8];
+    int64_t time[8];
+
+    uint32_t tsr;
+    uint32_t ter;
+    uint32_t tfr;
+    uint32_t tmr;
+
+    uint32_t tdfr[8];
+    uint32_t tdhr[8];
+    uint32_t tcnt[8];
+    uint32_t tcsr[8];
+
+    uint32_t prescale[8];
+    uint32_t freq[8];
+};
+
+static void jz4740_tcu_update_interrupt(struct jz4740_tcu_s *s)
+{
+       //printf("s->tfr %x s->tmr %x \n",s->tfr,s->tmr);
+    if (((s->tfr & 0x1) & (~(s->tmr & 0x1)))
+        || ((s->tfr & 0x10000) & (~(s->tmr & 0x10000))))
+    {
+        qemu_set_irq(s->tcu_irq0, 1);
+    }
+   // else
+   //     qemu_set_irq(s->tcu_irq0, 0);
+#if 0
+    if (((s->tfr & 0x2) & (~(s->tmr & 0x2)))
+        || ((s->tfr & 0x20000) & (~(s->tmr & 0x20000))))
+    {
+        qemu_set_irq(s->tcu_irq1, 1);
+    }
+    else
+        qemu_set_irq(s->tcu_irq1, 0);
+
+    if (((s->tfr & 0xfc) & (~(s->tmr & 0xfc)))
+        || ((s->tfr & 0xfc0000) & (~(s->tmr & 0xfc0000))))
+    {
+        qemu_set_irq(s->tcu_irq2, 1);
+    }
+    else
+        qemu_set_irq(s->tcu_irq2, 0);
+    #endif
+}
+
+#undef TCU_INDEX
+#define TCU_INDEX   0
+#include "mips_jz_glue.h"
+#define TCU_INDEX   1
+#include "mips_jz_glue.h"
+#define TCU_INDEX   2
+#include "mips_jz_glue.h"
+#define TCU_INDEX   3
+#include "mips_jz_glue.h"
+#define TCU_INDEX   4
+#include "mips_jz_glue.h"
+#define TCU_INDEX   5
+#include "mips_jz_glue.h"
+#define TCU_INDEX   6
+#include "mips_jz_glue.h"
+#define TCU_INDEX   7
+#include "mips_jz_glue.h"
+#undef TCU_INDEX
+
+#define  jz4740_tcu_start(s) do {        \
+       jz4740_tcu_start_half0(s);              \
+       jz4740_tcu_start_full0(s);    \
+       jz4740_tcu_start_half1(s); \
+       jz4740_tcu_start_full1(s); \
+       jz4740_tcu_start_half2(s); \
+       jz4740_tcu_start_full2(s); \
+       jz4740_tcu_start_half3(s); \
+       jz4740_tcu_start_full3(s); \
+       jz4740_tcu_start_half4(s); \
+       jz4740_tcu_start_full4(s); \
+       jz4740_tcu_start_half5(s); \
+       jz4740_tcu_start_full5(s); \
+       jz4740_tcu_start_half6(s); \
+       jz4740_tcu_start_full6(s); \
+       jz4740_tcu_start_half7(s); \
+       jz4740_tcu_start_full7(s); \
+}while (0)
+
+static void jz4740_tcu_if_reset(struct jz4740_tcu_s *s)
+{
+    int i;
+
+    s->tsr = 0x0;
+    s->ter = 0x0;
+    s->tfr = 0x0;
+    s->tmr = 0x0;
+    for (i = 0; i < 8; i++)
+    {
+        s->tdfr[i] = 0xffff;
+        s->tdhr[i] = 0x8000;
+        s->tcnt[i] = 0x0;
+        s->tcsr[i] = 0x0;
+        s->half_timer[i] = NULL;
+        s->full_timer[i] = NULL;
+    }
+}
+
+static void jz4740_tcu_if_write8(void *opaque, target_phys_addr_t addr,
+                                 uint32_t value)
+{
+    struct jz4740_tcu_s *s = (struct jz4740_tcu_s *) opaque;
+
+    debug_out(DEBUG_TCU, "jz4740_tcu_if_write8 addr %x value %x\n", addr,
+              value);
+
+    switch (addr)
+    {
+    case 0x14:
+        s->ter |= (value & 0xff);
+        jz4740_tcu_start(s);
+        break;
+    case 0x18:
+        s->ter &= ~(value & 0xff);
+        jz4740_tcu_start(s);
+        break;
+    default:
+        cpu_abort(s->soc->env,
+                  "jz4740_tcu_if_write8 undefined addr " JZ_FMT_plx
+                  " value %x \n", addr, value);
+    }
+
+}
+
+static void jz4740_tcu_if_write32(void *opaque, target_phys_addr_t addr,
+                                  uint32_t value)
+{
+    struct jz4740_tcu_s *s = (struct jz4740_tcu_s *) opaque;
+
+    debug_out(DEBUG_TCU, "jz4740_tcu_if_write32 addr %x value %x\n", addr,
+              value);
+
+        fprintf(fp, "jz4740_tcu_if_write32 addr %x value %x\n", addr,
+              value);
+    switch (addr)
+    {
+    case 0x2c:
+        s->tsr |= (value & 0x100ff);
+        jz4740_tcu_start(s);
+        break;
+    case 0x3c:
+        s->tsr &= ~(value & 0x100ff);
+        jz4740_tcu_start(s);
+        break;
+    case 0x24:
+        s->tfr |= (value & 0xff00ff);
+        break;
+    case 0x28:
+        s->tfr &= ~(value & 0xff00ff);
+        break;
+    case 0x34:
+        s->tmr |= (value & 0xff00ff);
+        jz4740_tcu_update_interrupt(s);
+        break;
+    case 0x38:
+        s->tmr &= ~(value & 0xff00ff);
+        jz4740_tcu_update_interrupt(s);
+        break;
+    default:
+        cpu_abort(s->soc->env,
+                  "jz4740_tcu_if_write32 undefined addr " JZ_FMT_plx
+                  " value %x \n", addr, value);
+
+    }
+}
+
+static uint32_t jz4740_tcu_if_read8(void *opaque, target_phys_addr_t addr)
+{
+    struct jz4740_tcu_s *s = (struct jz4740_tcu_s *) opaque;
+
+    debug_out(DEBUG_TCU, "jz4740_tcu_if_read8 addr %x\n", addr);
+
+    switch (addr)
+    {
+    case 0x10:
+        return s->ter;
+    default:
+        cpu_abort(s->soc->env,
+                  "jz4740_tcu_if_read8 undefined addr " JZ_FMT_plx "\n", addr);
+    }
+    return (0);
+}
+
+static uint32_t jz4740_tcu_if_read32(void *opaque, target_phys_addr_t addr)
+{
+    struct jz4740_tcu_s *s = (struct jz4740_tcu_s *) opaque;
+
+    debug_out(DEBUG_TCU, "jz4740_tcu_if_read32 addr %x\n", addr);
+
+    switch (addr)
+    {
+    case 0x1c:
+        return s->tsr;
+    case 0x20:
+        return s->tfr;
+    case 0x30:
+        return s->tmr;
+    default:
+        cpu_abort(s->soc->env,
+                  "jz4740_tcu_if_read32 undefined addr " JZ_FMT_plx "\n", addr);
+
+    }
+    return (0);
+
+}
+
+static CPUReadMemoryFunc *jz4740_tcu_if_readfn[] = {
+    jz4740_tcu_if_read8, jz4740_badwidth_read32, jz4740_tcu_if_read32,
+};
+
+static CPUWriteMemoryFunc *jz4740_tcu_if_writefn[] = {
+    jz4740_tcu_if_write8, jz4740_badwidth_write32, jz4740_tcu_if_write32,
+};
+
+static struct jz4740_tcu_s *jz4740_tcu_if_init(struct jz_state_s *soc,
+                                               qemu_irq tcu_irq0,
+                                               qemu_irq tcu_irq1,
+                                               qemu_irq tcu_irq2)
+{
+    int iomemtype;
+    //int i;
+
+    struct jz4740_tcu_s *s = (struct jz4740_tcu_s *) qemu_mallocz(sizeof(*s));
+    s->base = JZ4740_PHYS_BASE(JZ4740_TCU_BASE);
+    s->soc = soc;
+    s->tcu_irq0 = tcu_irq0;
+    s->tcu_irq1 = tcu_irq1;
+    s->tcu_irq2 = tcu_irq2;
+
+    jz4740_tcu_if_reset(s);
+
+    iomemtype =
+        cpu_register_io_memory(0, jz4740_tcu_if_readfn, jz4740_tcu_if_writefn,
+                               s);
+    cpu_register_physical_memory(s->base, 0x00000040, iomemtype);
+    return s;
+
+}
+
+static void jz4740_tcu_init(struct jz_state_s *soc,
+                            struct jz4740_tcu_s *s, int timer_index)
+{
+    switch (timer_index)
+    {
+    case 0x0:
+        jz4740_tcu_init0(soc, s);
+        break;
+    case 0x1:
+        jz4740_tcu_init1(soc, s);
+        break;
+    case 0x2:
+        jz4740_tcu_init2(soc, s);
+        break;
+    case 0x3:
+        jz4740_tcu_init3(soc, s);
+        break;
+    case 0x4:
+        jz4740_tcu_init4(soc, s);
+        break;
+    case 0x5:
+        jz4740_tcu_init5(soc, s);
+        break;
+    case 0x6:
+        jz4740_tcu_init6(soc, s);
+        break;
+    case 0x7:
+        jz4740_tcu_init7(soc, s);
+        break;
+    default:
+        cpu_abort(s->soc->env,
+                  "jz4740_tcu_init undefined timer %x \n", timer_index);
+    }
+}
+
+typedef void (*jz4740_lcd_fn_t) (uint8_t * d, const uint8_t * s, int width,
+                                 const uint16_t * pal);
+struct jz_fb_descriptor
+{
+    uint32_t fdadr;             /* Frame descriptor address register */
+    uint32_t fsadr;             /* Frame source address register */
+    uint32_t fidr;              /* Frame ID register */
+    uint32_t ldcmd;             /* Command register */
+};
+
+struct jz4740_lcdc_s
+{
+    qemu_irq irq;
+
+    target_phys_addr_t base;
+    struct jz_state_s *soc;
+
+    DisplayState *state;
+    QEMUConsole *console;
+    jz4740_lcd_fn_t *line_fn_tab;
+    jz4740_lcd_fn_t line_fn;
+
+
+    uint32_t lcdcfg;
+    uint32_t lcdvsync;
+    uint32_t lcdhsync;
+    uint32_t lcdvat;
+    uint32_t lcddah;
+    uint32_t lcddav;
+    uint32_t lcdps;
+    uint32_t lcdcls;
+    uint32_t lcdspl;
+    uint32_t lcdrev;
+    uint32_t lcdctrl;
+    uint32_t lcdstate;
+    uint32_t lcdiid;
+    uint32_t lcdda0;
+    uint32_t lcdsa0;
+    uint32_t lcdfid0;
+    uint32_t lcdcmd0;
+    uint32_t lcdda1;
+    uint32_t lcdsa1;
+    uint32_t lcdfid1;
+    uint32_t lcdcmd1;
+
+    uint32_t ena;
+    uint32_t dis;
+    uint32_t width;
+    uint32_t height;
+    uint32_t bpp;               /*bit per second */
+    uint16_t palette[256];
+    uint32_t invalidate;
+
+};
+
+/*bit per pixel*/
+static const int jz4740_lcd_bpp[0x6] = {
+    1, 2, 4, 8, 16, 32          /*4740 uses 32 bit for 24bpp */
+};
+
+static void jz4740_lcdc_reset(struct jz4740_lcdc_s *s)
+{
+
+}
+
+static uint32_t jz4740_lcdc_read(void *opaque, target_phys_addr_t addr)
+{
+    struct jz4740_lcdc_s *s = (struct jz4740_lcdc_s *) opaque;
+
+    debug_out(DEBUG_LCDC, "jz4740_lcdc_read addr %x \n", addr);
+    switch (addr)
+    {
+    case 0x0:
+        return s->lcdcfg;
+    case 0x4:
+        return s->lcdvsync;
+    case 0x8:
+        return s->lcdhsync;
+    case 0xc:
+        return s->lcdvat;
+    case 0x10:
+        return s->lcddah;
+    case 0x14:
+        return s->lcddav;
+    case 0x18:
+        return s->lcdps;
+    case 0x1c:
+        return s->lcdcls;
+    case 0x20:
+        return s->lcdspl;
+    case 0x24:
+        return s->lcdrev;
+    case 0x30:
+        return s->lcdctrl;
+    case 0x34:
+        return s->lcdstate;
+    case 0x38:
+        return s->lcdiid;
+    case 0x40:
+        return s->lcdda0;
+    case 0x44:
+        return s->lcdsa0;
+    case 0x48:
+        return s->lcdfid0;
+    case 0x4c:
+        return s->lcdcmd0;
+    case 0x50:
+        return s->lcdda1;
+    case 0x54:
+        return s->lcdsa1;
+    case 0x58:
+        return s->lcdfid1;
+    case 0x5c:
+        return s->lcdcmd1;
+    default:
+        cpu_abort(s->soc->env,
+                  "jz4740_lcdc_read undefined addr " JZ_FMT_plx " \n", addr);
+
+    }
+
+}
+
+static void jz4740_lcdc_write(void *opaque, target_phys_addr_t addr,
+                              uint32_t value)
+{
+    struct jz4740_lcdc_s *s = (struct jz4740_lcdc_s *) opaque;
+
+    debug_out(DEBUG_LCDC, "jz4740_lcdc_write addr %x value %x\n", addr, value);
+
+    switch (addr)
+    {
+    case 0x44:
+    case 0x48:
+    case 0x4c:
+        JZ4740_RO_REG(addr);
+        break;
+    case 0x0:
+        s->lcdcfg = value & 0x80ffffbf;
+        break;
+    case 0x4:
+        s->lcdvsync = value & 0x7ff07ff;
+        break;
+    case 0x8:
+        s->lcdhsync = value & 0x7ff07ff;
+        break;
+    case 0xc:
+        s->lcdvat = value & 0x7ff07ff;
+        break;
+    case 0x10:
+        s->lcddah = value & 0x7ff07ff;
+        s->width = (value & 0x7ff) - ((value >> 16) & 0x7ff);
+        break;
+    case 0x14:
+        s->height = (value & 0x7ff) - ((value >> 16) & 0x7ff);
+        s->lcddav = value & 0x7ff07ff;
+        break;
+    case 0x18:
+        s->lcdps = value & 0x7ff07ff;
+        break;
+    case 0x1c:
+        s->lcdcls = value & 0x7ff07ff;
+        break;
+    case 0x20:
+        s->lcdspl = value & 0x7ff07ff;
+        break;
+    case 0x24:
+        s->lcdrev = value & 0x7ff0000;
+        break;
+    case 0x30:
+        s->lcdctrl = value & 0x3fff3fff;
+        s->ena = (value & 0x8) >> 3;
+        s->dis = (value & 0x10) >> 4;
+        s->bpp = jz4740_lcd_bpp[value & 0x7];
+        if ((s->bpp == 1))
+        {
+            fprintf(stderr, "bpp =1 is not supported\n");
+            exit(-1);
+        }
+        s->line_fn = s->line_fn_tab[value & 0x7];
+        break;
+    case 0x34:
+        s->lcdstate = value & 0xbf;
+        break;
+    case 0x38:
+        s->lcdiid = value;
+        break;
+    case 0x40:
+        s->lcdda0 = value;
+        break;
+    case 0x50:
+        s->lcdda1 = value;
+        break;
+    default:
+        cpu_abort(s->soc->env,
+                  "jz4740_lcdc_write undefined addr " JZ_FMT_plx " value %x \n",
+                  addr, value);
+    }
+
+}
+
+static CPUReadMemoryFunc *jz4740_lcdc_readfn[] = {
+    jz4740_badwidth_read32, jz4740_badwidth_read32, jz4740_lcdc_read,
+};
+
+static CPUWriteMemoryFunc *jz4740_lcdc_writefn[] = {
+    jz4740_badwidth_write32, jz4740_badwidth_write32, jz4740_lcdc_write,
+};
+
+#include "pixel_ops.h"
+#define JZ4740_LCD_PANEL
+#define DEPTH 8
+#include "mips_jz_glue.h"
+#define DEPTH 15
+#include "mips_jz_glue.h"
+#define DEPTH 16
+#include "mips_jz_glue.h"
+#define DEPTH 24
+#include "mips_jz_glue.h"
+#define DEPTH 32
+#include "mips_jz_glue.h"
+#undef JZ4740_LCD_PANEL
+
+static void *jz4740_lcd_get_buffer(struct jz4740_lcdc_s *s,
+                                   target_phys_addr_t addr)
+{
+    uint32_t pd;
+
+    pd = cpu_get_physical_page_desc(addr);
+    if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM)
+        /* TODO */
+        cpu_abort(cpu_single_env, "%s: framebuffer outside RAM!\n",
+                  __FUNCTION__);
+    else
+        return phys_ram_base +
+            (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
+}
+
+static void jz4740_lcd_update_display(void *opaque)
+{
+    struct jz4740_lcdc_s *s = (struct jz4740_lcdc_s *) opaque;
+
+    uint8_t *src, *dest;
+    struct jz_fb_descriptor *fb_des;
+
+    int step, linesize;
+    int y;
+
+
+    if (!s->ena)
+        return;
+    if (s->dis)
+        return;
+
+    if (!s->lcdda0)
+        return;
+
+    fb_des = (struct jz_fb_descriptor *) jz4740_lcd_get_buffer(s, s->lcdda0);
+    s->lcdda0 = fb_des->fdadr;
+    s->lcdsa0 = fb_des->fsadr;
+    s->lcdfid0 = fb_des->fidr;
+    s->lcdcmd0 = fb_des->ldcmd;
+
+    src = (uint8_t *) jz4740_lcd_get_buffer(s, fb_des->fsadr);
+    if (s->lcdcmd0 & (0x1 << 28))
+    {
+        /*palette */
+        memcpy(s->palette, src, sizeof(s->palette));
+        return;
+    }
+
+    /*frame buffer */
+
+    if (s->width != ds_get_width(s->state) ||
+        s->height != ds_get_height(s->state))
+    {
+        qemu_console_resize(s->console, s->width, s->height);
+        s->invalidate = 1;
+    }
+
+    step = (s->width * s->bpp) >> 3;
+    dest = ds_get_data(s->state);
+    linesize = ds_get_linesize(s->state);
+
+    //printf("s->width %d s->height  %d s->bpp %d linesize %d \n",s->width,s->height ,s->bpp,linesize);
+
+    for (y = 0; y < s->height; y++)
+    {
+        s->line_fn(dest, src, s->width, s->palette);
+        //memcpy(dest,src,step);
+        src += step;
+        dest += linesize;
+    }
+
+
+    dpy_update(s->state, 0, 0, s->width, s->height);
+    s->lcdstate |= 0x20;
+    if ((s->lcdcmd0 & 0x40000000) && (!(s->lcdctrl & 0x2000)))
+        qemu_set_irq(s->irq, 1);
+}
+
+static inline void jz4740_lcd_invalidate_display(void *opaque)
+{
+    struct jz4740_lcdc_s *s = (struct jz4740_lcdc_s *) opaque;
+    s->invalidate = 1;
+}
+
+static struct jz4740_lcdc_s *jz4740_lcdc_init(struct jz_state_s *soc,
+                                              qemu_irq irq, DisplayState * ds)
+{
+    int iomemtype;
+
+    struct jz4740_lcdc_s *s = (struct jz4740_lcdc_s *) qemu_mallocz(sizeof(*s));
+    s->base = JZ4740_PHYS_BASE(JZ4740_LCD_BASE);
+    s->soc = soc;
+    s->irq = irq;
+    s->state = ds;
+
+
+    jz4740_lcdc_reset(s);
+
+    iomemtype =
+        cpu_register_io_memory(0, jz4740_lcdc_readfn, jz4740_lcdc_writefn, s);
+    cpu_register_physical_memory(s->base, 0x10000, iomemtype);
+
+    s->console = graphic_console_init(s->state, jz4740_lcd_update_display,
+                                      jz4740_lcd_invalidate_display,
+                                      NULL, NULL, s);
+    switch (ds_get_bits_per_pixel(s->state))
+    {
+    case 0x0:
+        s->line_fn_tab = qemu_mallocz(sizeof(jz4740_lcd_fn_t) * 6);
+        break;
+    case 8:
+        s->line_fn_tab = jz4740_lcd_draw_fn_8;
+        break;
+    case 15:
+        s->line_fn_tab = jz4740_lcd_draw_fn_15;
+        break;
+    case 16:
+        s->line_fn_tab = jz4740_lcd_draw_fn_16;
+        break;
+    case 24:
+        s->line_fn_tab = jz4740_lcd_draw_fn_24;
+        break;
+    case 32:
+        s->line_fn_tab = jz4740_lcd_draw_fn_32;
+        break;
+    default:
+        fprintf(stderr, "%s: Bad color depth\n", __FUNCTION__);
+        exit(1);
+    }
+
+    return s;
+
+}
+
+#define JZ4740_DMA_NUM         6
+struct jz4740_dma_s
+{
+    qemu_irq irq;
+
+    target_phys_addr_t base;
+    struct jz_state_s *soc;
+
+    uint32_t dmac;
+    uint32_t dirqp;
+    uint32_t ddr;
+    uint32_t ddrs;
+
+    uint32_t dsa[JZ4740_DMA_NUM];
+    uint32_t dta[JZ4740_DMA_NUM];
+    uint32_t dtc[JZ4740_DMA_NUM];
+    uint32_t drs[JZ4740_DMA_NUM];
+    uint32_t dcs[JZ4740_DMA_NUM];
+    uint32_t dcm[JZ4740_DMA_NUM];
+    uint32_t dda[JZ4740_DMA_NUM];
+
+};
+
+struct jz4740_desc_s
+{
+    uint32_t dcmd;              /* DCMD value for the current transfer */
+    uint32_t dsadr;             /* DSAR value for the current transfer */
+    uint32_t dtadr;             /* DTAR value for the current transfer */
+    uint32_t ddadr;             /* Points to the next descriptor + transfer count */
+};
+
+static inline void jz4740_dma_transfer(struct jz4740_dma_s *s,
+                                       target_phys_addr_t src,
+                                       target_phys_addr_t dest, uint32_t len)
+{
+    uint32_t pd_src, pd_dest;
+    uint8_t *sr, *de;
+
+    pd_src = cpu_get_physical_page_desc(src);
+    if ((pd_src & ~TARGET_PAGE_MASK) != IO_MEM_RAM)
+        /* TODO */
+        cpu_abort(cpu_single_env, "%s: DMA source address %x outside RAM!\n",
+                  __FUNCTION__, src);
+    else
+        sr = phys_ram_base +
+            (pd_src & TARGET_PAGE_MASK) + (src & ~TARGET_PAGE_MASK);
+
+    pd_dest = cpu_get_physical_page_desc(dest);
+    if ((pd_dest & ~TARGET_PAGE_MASK) != IO_MEM_RAM)
+        /* TODO */
+        cpu_abort(cpu_single_env,
+                  "%s: DMA destination address %x outside RAM!\n",
+                  __FUNCTION__, dest);
+    else
+        de = phys_ram_base +
+            (pd_dest & TARGET_PAGE_MASK) + (dest & ~TARGET_PAGE_MASK);
+
+    memcpy(de, sr, len);
+}
+
+static inline uint32_t jz4740_dma_unit_size(struct jz4740_dma_s *s,
+                                            uint32_t cmd)
+{
+    switch ((cmd & 0x700) >> 8)
+    {
+    case 0x0:
+        return 4;
+    case 0x1:
+        return 1;
+    case 0x2:
+        return 2;
+    case 0x3:
+        return 16;
+    case 0x4:
+        return 32;
+    }
+    return (0);
+}
+
+
+/*No-descriptor transfer*/
+static inline void jz4740_dma_ndrun(struct jz4740_dma_s *s, int channel)
+{
+    uint32_t len;
+
+    len = jz4740_dma_unit_size(s, s->dcs[channel]) * s->dtc[channel];
+
+    jz4740_dma_transfer(s, s->dsa[channel], s->dta[channel], len);
+
+    /*finish dma transfer */
+    s->dtc[channel] = 0;
+    /*set DIR QP */
+    s->dirqp |= 1 << channel;
+
+    /*some cleanup work */
+    /*clean AR TT GLOBAL AR */
+    s->dcs[channel] &= 0xffffffe7;
+    s->dmac &= 0xfffffffb;
+
+    if (s->dcm[channel] & 0x2)
+        qemu_set_irq(s->irq, 1);
+}
+
+        /*descriptor transfer */
+static inline void jz4740_dma_drun(struct jz4740_dma_s *s, int channel)
+{
+    struct jz4740_desc_s *desc;
+    target_phys_addr_t desc_phy;
+    uint32_t pd;
+
+    desc_phy = s->dda[channel];
+    if (desc_phy & 0xf)
+        cpu_abort(s->soc->env,
+                  "jz4740_dma_drun descriptor address " JZ_FMT_plx
+                  " must be 4 bytes aligned \n", desc_phy);
+
+    pd = cpu_get_physical_page_desc(desc_phy);
+    if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM)
+        cpu_abort(cpu_single_env,
+                  "%s: DMA descriptor address " JZ_FMT_plx " outside RAM!\n",
+                  __FUNCTION__, desc_phy);
+    else
+        desc = (struct jz4740_desc_s *) (phys_ram_base +
+                                         (pd & TARGET_PAGE_MASK) +
+                                         (desc_phy & ~TARGET_PAGE_MASK));
+
+    if (!desc)
+        cpu_abort(cpu_single_env,
+                  "%s: DMA descriptor " JZ_FMT_plx " is NULL!\n", __FUNCTION__,
+                  (uint32_t) desc);
+
+    while (1)
+    {
+        if ((desc->dcmd & 0x8) && (!(desc->dcmd & 0x10)))
+        {
+            /*Stop DMA and set DCSN.INV=1 */
+            s->dcs[channel] |= 1 << 6;
+            return;
+        }
+        jz4740_dma_transfer(s, desc->dtadr, desc->dsadr,
+                            (desc->ddadr & 0xffffff) *
+                            jz4740_dma_unit_size(s, desc->dcmd));
+
+        if ((desc->dcmd) & (1 << 3))
+            /*clear v */
+            desc->dcmd &= ~(1 << 4);
+        if (desc->dcmd & 0x1)
+            /*set DCSN.CT=1 */
+            s->dcs[channel] |= 0x2;
+        else
+            /*set DCSN.TT=1 */
+            s->dcs[channel] |= 0x8;
+
+        if (desc->dcmd & 0x2)
+            qemu_set_irq(s->irq, 1);
+
+        if ((desc->dcmd) & 0x1)
+        {
+            /*fetch next descriptor */
+            desc_phy = s->dda[channel] & 0xfffff000;
+            desc_phy += (desc->dtadr & 0xff000000) >> 24;
+            pd = cpu_get_physical_page_desc(desc_phy);
+            if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM)
+                cpu_abort(cpu_single_env,
+                          "%s: DMA descriptor address %x outside RAM!\n",
+                          __FUNCTION__, desc_phy);
+            else
+                desc = (struct jz4740_desc_s *) (phys_ram_base +
+                                                 (pd & TARGET_PAGE_MASK)
+                                                 +
+                                                 (desc_phy &
+                                                  ~TARGET_PAGE_MASK));
+            if (!desc)
+                cpu_abort(cpu_single_env,
+                          "%s: DMA descriptor %x is NULL!\n",
+                          __FUNCTION__, (uint32_t) desc);
+        }
+        else
+            break;
+    }
+}
+
+static void jz4740_dma_en_channel(struct jz4740_dma_s *s, int channel)
+{
+    if (s->dmac & 0x1)
+    {
+        if (s->dcs[channel] & (1 << 31))
+        {
+            /*NON DESCRIPTOR */
+            jz4740_dma_ndrun(s, channel);
+        }
+    }
+}
+
+static inline void jz4740_dma_en_global(struct jz4740_dma_s *s)
+{
+    int channel;
+    for (channel = 0; channel < JZ4740_DMA_NUM; channel++)
+    {
+        jz4740_dma_en_channel(s, channel);
+    }
+}
+
+static inline void jz4740_dma_en_dbn(struct jz4740_dma_s *s, int channel)
+{
+    if ((s->dmac & 0x1) && (s->dcs[channel] & (1 << 31)))
+    {
+        jz4740_dma_drun(s, channel);
+    }
+}
+
+static void jz4740_dma_reset(struct jz4740_dma_s *s)
+{
+
+}
+
+static uint32_t jz4740_dma_read(void *opaque, target_phys_addr_t addr)
+{
+    struct jz4740_dma_s *s = (struct jz4740_dma_s *) opaque;
+    int channel;
+
+    debug_out(DEBUG_DMA, "jz4740_dma_read addr %x \n", addr);
+    switch (addr)
+    {
+    case 0x300:
+        return s->dmac;
+    case 0x304:
+        return s->dirqp;
+    case 0x308:
+        return s->ddr;
+    case 0x0:
+    case 0x20:
+    case 0x40:
+    case 0x60:
+    case 0x80:
+    case 0xa0:
+        channel = (addr - 0x0) / 0x20;
+        return s->dsa[channel];
+    case 0x4:
+    case 0x24:
+    case 0x44:
+    case 0x64:
+    case 0x84:
+    case 0xa4:
+        channel = (addr - 0x4) / 0x20;
+        return s->dta[channel];
+    case 0x8:
+    case 0x28:
+    case 0x48:
+    case 0x68:
+    case 0x88:
+    case 0xa8:
+        channel = (addr - 0x8) / 0x20;
+        return s->dtc[channel];
+    case 0xc:
+    case 0x2c:
+    case 0x4c:
+    case 0x6c:
+    case 0x8c:
+    case 0xac:
+        channel = (addr - 0xc) / 0x20;
+        return s->drs[channel];
+    case 0x10:
+    case 0x30:
+    case 0x50:
+    case 0x70:
+    case 0x90:
+    case 0xb0:
+        channel = (addr - 0x10) / 0x20;
+        return s->dcs[channel];
+    case 0x14:
+    case 0x34:
+    case 0x54:
+    case 0x74:
+    case 0x94:
+    case 0xb4:
+        channel = (addr - 0x14) / 0x20;
+        return s->dcm[channel];
+    case 0x18:
+    case 0x38:
+    case 0x58:
+    case 0x78:
+    case 0x98:
+    case 0xb8:
+        channel = (addr - 0x18) / 0x20;
+        return s->dda[channel];
+    default:
+        cpu_abort(s->soc->env,
+                  "jz4740_dma_read undefined addr " JZ_FMT_plx "  \n", addr);
+    }
+    return (0);
+}
+
+static void jz4740_dma_write(void *opaque, target_phys_addr_t addr,
+                             uint32_t value)
+{
+    struct jz4740_dma_s *s = (struct jz4740_dma_s *) opaque;
+    int channel;
+
+    debug_out(DEBUG_DMA, "jz4740_dma_write addr %x value %x \n", addr, value);
+    switch (addr)
+    {
+    case 0x304:
+        JZ4740_RO_REG(addr);
+        break;
+    case 0x300:
+        s->dmac = value & 0x30d;
+        if (s->dmac & 0x1)
+            jz4740_dma_en_global(s);
+        break;
+    case 0x308:
+    case 0x30c:
+        s->ddr = value & 0xff;
+        for (channel = 0; channel < JZ4740_DMA_NUM; channel++)
+        {
+            if (s->ddr & (1 << channel))
+            {
+                jz4740_dma_en_dbn(s, channel);
+                break;
+            }
+        }
+        break;
+    case 0x0:
+    case 0x20:
+    case 0x40:
+    case 0x60:
+    case 0x80:
+    case 0xa0:
+        channel = (addr - 0x0) / 0x20;
+        s->dsa[channel] = value;
+        break;
+    case 0x4:
+    case 0x24:
+    case 0x44:
+    case 0x64:
+    case 0x84:
+    case 0xa4:
+        channel = (addr - 0x4) / 0x20;
+        s->dta[channel] = value;
+        break;
+    case 0x8:
+    case 0x28:
+    case 0x48:
+    case 0x68:
+    case 0x88:
+    case 0xa8:
+        channel = (addr - 0x8) / 0x20;
+        s->dtc[channel] = value;
+        break;
+    case 0xc:
+    case 0x2c:
+    case 0x4c:
+    case 0x6c:
+    case 0x8c:
+    case 0xac:
+        channel = (addr - 0xc) / 0x20;
+        s->drs[channel] = value & 0x10;
+        if (s->drs[channel] != 0x8)
+        {
+            fprintf(stderr, "Only auto request is supproted \n");
+        }
+        break;
+    case 0x10:
+    case 0x30:
+    case 0x50:
+    case 0x70:
+    case 0x90:
+    case 0xb0:
+        channel = (addr - 0x10) / 0x20;
+        s->dcs[channel] = value & 0x80ff005f;
+        if (s->dcs[channel] & 0x1)
+            jz4740_dma_en_channel(s, channel);
+        break;
+    case 0x14:
+    case 0x34:
+    case 0x54:
+    case 0x74:
+    case 0x94:
+    case 0xb4:
+        channel = (addr - 0x14) / 0x20;
+        s->dcm[channel] = value & 0xcff79f;
+        break;
+    case 0x18:
+    case 0x38:
+    case 0x58:
+    case 0x78:
+    case 0x98:
+    case 0xb8:
+        channel = (addr - 0x18) / 0x20;
+        s->dda[channel] = 0xfffffff0;
+        break;
+    default:
+        cpu_abort(s->soc->env,
+                  "jz4740_dma_read undefined addr " JZ_FMT_plx "  \n", addr);
+    }
+
+}
+
+static CPUReadMemoryFunc *jz4740_dma_readfn[] = {
+    jz4740_badwidth_read32, jz4740_badwidth_read32, jz4740_dma_read,
+};
+
+static CPUWriteMemoryFunc *jz4740_dma_writefn[] = {
+    jz4740_badwidth_write32, jz4740_badwidth_write32, jz4740_dma_write,
+};
+
+
+static struct jz4740_dma_s *jz4740_dma_init(struct jz_state_s *soc,
+                                            qemu_irq irq)
+{
+    int iomemtype;
+    struct jz4740_dma_s *s = (struct jz4740_dma_s *) qemu_mallocz(sizeof(*s));
+    s->base = JZ4740_PHYS_BASE(JZ4740_DMAC_BASE);
+    s->soc = soc;
+    s->irq = irq;
+
+    jz4740_dma_reset(s);
+
+    iomemtype =
+        cpu_register_io_memory(0, jz4740_dma_readfn, jz4740_dma_writefn, s);
+    cpu_register_physical_memory(s->base, 0x00010000, iomemtype);
+    return s;
+
+}
 
 static void jz4740_cpu_reset(void *opaque)
 {
@@ -963,7 +2629,7 @@ static void jz4740_cpu_reset(void *opaque)
 }
 
 struct jz_state_s *jz4740_init(unsigned long sdram_size,
-                               uint32_t osc_extal_freq)
+                               uint32_t osc_extal_freq, DisplayState * ds)
 {
     struct jz_state_s *s = (struct jz_state_s *)
         qemu_mallocz(sizeof(struct jz_state_s));
@@ -990,10 +2656,9 @@ struct jz_state_s *jz4740_init(unsigned long sdram_size,
 
     /*map sram to 0x80000000 and sdram to 0x80004000 */
     sram_base = qemu_ram_alloc(s->sram_size);
-    cpu_register_physical_memory(JZ4740_SRAM_BASE, s->sram_size,
-                                 (sram_base | IO_MEM_RAM));
+    cpu_register_physical_memory(0x0, s->sram_size, (sram_base | IO_MEM_RAM));
     sdram_base = qemu_ram_alloc(s->sdram_size);
-    cpu_register_physical_memory(JZ4740_SDRAM_BASE, s->sdram_size,
+    cpu_register_physical_memory(JZ4740_SRAM_SIZE, s->sdram_size,
                                  (sdram_base | IO_MEM_RAM));
 
     /* Init internal devices */
@@ -1006,7 +2671,16 @@ struct jz_state_s *jz4740_init(unsigned long sdram_size,
 
     intc = jz4740_intc_init(s, s->env->irq[2]);
     s->cpm = jz4740_cpm_init(s);
-    s->emc = jz4740_emc_init(s,intc[2]);
+    s->emc = jz4740_emc_init(s, intc[2]);
+    s->gpio = jz4740_gpio_init(s, intc[25]);
+    s->rtc = jz4740_rtc_init(s, intc[15]);
+    s->tcu = jz4740_tcu_if_init(s, intc[23], intc[22], intc[21]);
+    jz4740_tcu_init(s, s->tcu, 0);
+    s->lcdc = jz4740_lcdc_init(s, intc[30], ds);
+    s->dma = jz4740_dma_init(s, intc[20]);
+
+    if (serial_hds[0])
+        serial_mm_init(0x10030000, 2, intc[9], 57600, serial_hds[0], 1);
 
     return s;
 }
index 4f0275e..f28bfc3 100755 (executable)
 
 
 
-#if TARGET_PHYS_ADDR_BITS == 32
-#define JZ_FMT_plx "%#08x"
-#elif TARGET_PHYS_ADDR_BITS == 64
-#define JZ_FMT_plx "%#08" PRIx64
-#else
-#error TARGET_PHYS_ADDR_BITS undefined
-#endif
-
+#define JZ_FMT_plx "%#16x"
+
+uint32_t jz4740_badwidth_read8(void *opaque, target_phys_addr_t addr);
+uint32_t jz4740_badwidth_read16(void *opaque, target_phys_addr_t addr);
+uint32_t jz4740_badwidth_read32(void *opaque, target_phys_addr_t addr);
+void jz4740_badwidth_write8(void *opaque, target_phys_addr_t addr,
+                                    uint32_t value);
+void jz4740_badwidth_write16(void *opaque, target_phys_addr_t addr,
+                                    uint32_t value);
+void jz4740_badwidth_write32(void *opaque, target_phys_addr_t addr,
+                                    uint32_t value);
 
 #define IO_ACCESS_VERBOSE                      1
 
@@ -159,7 +162,7 @@ struct clk {
     unsigned long rate;                /* Current rate (if .running) */
     unsigned int divisor;      /* Rate relative to input (if .enabled) */
     unsigned int multiplier;   /* Rate relative to input (if .enabled) */
-    int usecount;      
+    //int usecount;    
 };
 typedef struct clk *jz_clk;
 void jz_clk_init(struct jz_state_s *mpu,uint32_t osc_extal_freq);
@@ -174,7 +177,7 @@ void jz_clk_reparent(jz_clk clk, jz_clk parent);
 
 /*mips_jz.c*/
 struct jz_state_s *jz4740_init(unsigned long sdram_size,
-                                                              uint32_t osc_extal_freq);
+                                                              uint32_t osc_extal_freq,DisplayState * ds);
 
 enum jz_cpu_model {
         jz4740,
@@ -195,7 +198,11 @@ struct jz_state_s {
 
        struct jz4740_cpm_s *cpm;
        struct jz4740_emc_s *emc;
-
+       struct jz4740_gpio_s *gpio;
+       struct jz4740_rtc_s *rtc;
+       struct jz4740_tcu_s *tcu;
+       struct jz4740_lcdc_s *lcdc;
+       struct jz4740_dma_s *dma;
        
 };
 
index c5ac296..60e85e2 100755 (executable)
@@ -1,7 +1,7 @@
 /*
  * JZ Soc clocks.
  *
- * Copyright (C) 2006-2008 yajin <yajin@vm-kernel.org>
+ * Copyright (C) 2009 yajin <yajin@vm-kernel.org>
  *
  *
  * This program is free software; you can redistribute it and/or
@@ -33,7 +33,7 @@
 
 
 static struct clk osc_extal = {
-    .name = "osc_extal_12M",
+    .name = "osc_extal",
     .rate = 12000000,
     .flags = ALWAYS_ENABLED | CLOCK_IN_JZ4740,
 };
@@ -151,18 +151,6 @@ struct clk *jz_findclk(struct jz_state_s *cpu, const char *name)
     cpu_abort(cpu->env, "%s: %s not found\n", __FUNCTION__, name);
 }
 
-void jz_clk_get(struct clk *clk)
-{
-    clk->usecount++;
-}
-
-void jz_clk_put(struct clk *clk)
-{
-    if (!(clk->usecount--))
-        cpu_abort(cpu_single_env, "%s: %s is not in use\n",
-                  __FUNCTION__, clk->name);
-}
-
 static void jz_clk_update(struct clk *clk)
 {
     int parent, running;
@@ -175,7 +163,7 @@ static void jz_clk_update(struct clk *clk)
         parent = 1;
 
     running = parent && (clk->enabled ||
-                         ((clk->flags & ALWAYS_ENABLED) && clk->usecount));
+                         ((clk->flags & ALWAYS_ENABLED)));
     if (clk->running != running)
     {
         clk->running = running;
@@ -244,14 +232,6 @@ void jz_clk_onoff(struct clk *clk, int on)
     jz_clk_update(clk);
 }
 
-void jz_clk_canidle(struct clk *clk, int can)
-{
-    if (can)
-        jz_clk_put(clk);
-    else
-        jz_clk_get(clk);
-}
-
 void jz_clk_setrate(struct clk *clk, int divide, int multiply)
 {
     clk->divisor = divide;
index 0aebbc3..9e41c4e 100755 (executable)
-/*\r
- * QEMU JZ Soc emulation glue code\r
- *\r
- * Copyright (c) 2009 yajin (yajin@vm-kernel.org)\r
- *\r
- * Permission is hereby granted, free of charge, to any person obtaining a copy\r
- * of this software and associated documentation files (the "Software"), to deal\r
- * in the Software without restriction, including without limitation the rights\r
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
- * copies of the Software, and to permit persons to whom the Software is\r
- * furnished to do so, subject to the following conditions:\r
- *\r
- * The above copyright notice and this permission notice shall be included in\r
- * all copies or substantial portions of the Software.\r
- *\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\r
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r
- * THE SOFTWARE.\r
- */\r
-\r
-\r
\r
-#ifdef TCU_INDEX\r
-static inline void glue(jz4740_tcu_time_sync,\r
-                        TCU_INDEX) (struct jz4740_tcu_s * s)\r
-{\r
-    int64_t distance;\r
-    int64_t temp;\r
-\r
-    if ((!(s->tsr & (1 << TCU_INDEX))) && (s->ter & (1 << TCU_INDEX))\r
-        && (s->freq[TCU_INDEX] != 0))\r
-    {\r
-        //debug_out(DEBUG_TCU, "jz4740_tcu_time_sync%x \n", TCU_INDEX);\r
-        /*first enable timer */\r
-        if (s->time[TCU_INDEX] == 0)\r
-        {\r
-            s->time[TCU_INDEX] = qemu_get_clock(vm_clock);\r
-            s->tcnt[TCU_INDEX] = 0;\r
-            return;\r
-        }\r
-        distance = qemu_get_clock(vm_clock) - s->time[TCU_INDEX];\r
-        //debug_out(DEBUG_TCU,\r
-         //         "s->freq[TCU_INDEX]  %d s->prescale[TCU_INDEX] %d \n",\r
-         //         s->freq[TCU_INDEX], s->prescale[TCU_INDEX]);\r
-       // debug_out(DEBUG_TCU, "distance %lld s->time[TCU_INDEX] %lld \n",\r
-       //           distance, s->time[TCU_INDEX]);\r
-        //temp = muldiv64(distance,(s->freq[TCU_INDEX]/s->prescale[TCU_INDEX]),ticks_per_sec);\r
-        temp = muldiv64(distance, 46875, ticks_per_sec);\r
-        if (temp != 0)\r
-        {\r
-            /*distance is too short */\r
-            s->tcnt[TCU_INDEX] += temp;\r
-            s->time[TCU_INDEX] = qemu_get_clock(vm_clock);\r
-        }\r
-        else\r
-        {\r
-            /*distance is too short.\r
-             * Do not sync timer this timer.\r
-             */\r
-        }\r
-\r
-        //printf("%lld distance %lld \n",muldiv64(distance,(s->freq[TCU_INDEX]/s->prescale[TCU_INDEX]),ticks_per_sec),distance);\r
-\r
-        if (s->tcnt[TCU_INDEX] >= 0x10000)\r
-            s->tcnt[TCU_INDEX] = 0x0;\r
-\r
-\r
-    }\r
-}\r
-\r
-static inline void glue(jz4740_tcu_start_half,\r
-                        TCU_INDEX) (struct jz4740_tcu_s * s)\r
-{\r
-    int64_t next = qemu_get_clock(vm_clock);\r
-    int64_t count;\r
-\r
-    /*The timer has not beed initialized */\r
-    if (!s->half_timer[TCU_INDEX])\r
-        return;\r
-       \r
-    if ((!(s->tsr & (1 << (TCU_INDEX+16)))) && (s->ter & (1 << (TCU_INDEX+16)))\r
-        && (s->freq[TCU_INDEX] != 0))\r
-    {\r
-        glue(jz4740_tcu_time_sync, TCU_INDEX) (s);\r
-        /*calculate next fire time */\r
-        count =\r
-            (s->tdhr[TCU_INDEX] - s->tcnt[TCU_INDEX]) * s->prescale[TCU_INDEX];\r
-        next += muldiv64(count, ticks_per_sec, s->freq[TCU_INDEX]);\r
-        qemu_mod_timer(s->half_timer[TCU_INDEX], next);\r
-\r
-    }\r
-    else\r
-        qemu_del_timer(s->half_timer[TCU_INDEX]);\r
-\r
-}\r
-\r
-static inline void glue(jz4740_tcu_start_full,\r
-                        TCU_INDEX) (struct jz4740_tcu_s * s)\r
-{\r
-    int64_t next = qemu_get_clock(vm_clock);\r
-    int64_t count;\r
-\r
-    /*The timer has not beed initialized */\r
-    if (!s->full_timer[TCU_INDEX])\r
-        return;\r
-        \r
-       debug_out(DEBUG_TCU, "s->tsr %d  s->ter %d  s->freq[TCU_INDEX]  %d \n",\r
-                                         s->tsr ,  s->ter ,s->freq[TCU_INDEX]);\r
-printf("s->tsr %d  s->ter %d  s->freq[TCU_INDEX]  %d \n",\r
-                                         s->tsr ,  s->ter ,s->freq[TCU_INDEX]);\r
-    if ((!(s->tsr & (1 << TCU_INDEX))) && (s->ter & (1 << TCU_INDEX))\r
-        && (s->freq[TCU_INDEX] != 0))\r
-    {\r
-        glue(jz4740_tcu_time_sync, TCU_INDEX) (s);\r
-        printf("tdfr %x \n",s->tdfr[TCU_INDEX] );\r
-        /*calculate next fire time */\r
-        count =\r
-            (s->tdfr[TCU_INDEX] - s->tcnt[TCU_INDEX]) * s->prescale[TCU_INDEX];\r
-        printf("tdfr11 %x count %lld\n",s->tdfr[TCU_INDEX],count );\r
-        next += muldiv64(count, ticks_per_sec, s->freq[TCU_INDEX]);\r
-        qemu_mod_timer(s->full_timer[TCU_INDEX], next);\r
-                debug_out(DEBUG_TCU, "s->tdfr[TCU_INDEX]  %d  s->tcnt[TCU_INDEX] %d  next  %lld \n",\r
-                                         s->tdfr[TCU_INDEX] ,  s->tcnt[TCU_INDEX]  ,next);\r
-                       printf("s->tdfr[TCU_INDEX]22  %x  s->tcnt[TCU_INDEX] %x next  %lld \n",\r
-                                         s->tdfr[TCU_INDEX] ,  s->tcnt[TCU_INDEX]  ,next);\r
-\r
-    }\r
-    else\r
-        qemu_del_timer(s->full_timer[TCU_INDEX]);\r
-}\r
-\r
-\r
-/* \r
- *     TCNT will reset to 0 if it reach to TDFR.\r
- *       So for the half compare, the next fire count is (TDFR-TDHR) + TDHR\r
- *                                                                                            \r
- */\r
-static void glue(jz4740_tcu_half_cb, TCU_INDEX) (void *opaque)\r
-{\r
-    struct jz4740_tcu_s *s = (struct jz4740_tcu_s *) opaque;\r
-    int64_t next = qemu_get_clock(vm_clock);\r
-    int64_t count;\r
-\r
-    if ((!(s->tsr & (1 << TCU_INDEX))) && (s->ter & (1 << TCU_INDEX))\r
-        && (s->freq[TCU_INDEX] != 0))\r
-    {\r
-        count = s->tdfr[TCU_INDEX] * s->prescale[TCU_INDEX];\r
-        next += muldiv64(count, ticks_per_sec, s->freq[TCU_INDEX]);\r
-        qemu_mod_timer(s->half_timer[TCU_INDEX], next);\r
-        s->tfr |= 1 << (16 + TCU_INDEX);\r
-        jz4740_tcu_update_interrupt(s);\r
-        s->tcnt[TCU_INDEX] = s->tdhr[TCU_INDEX];\r
-        s->time[TCU_INDEX] = qemu_get_clock(vm_clock);\r
-    }\r
-    else\r
-        qemu_del_timer(s->half_timer[TCU_INDEX]);\r
-}\r
-\r
-\r
-static void glue(jz4740_tcu_full_cb, TCU_INDEX) (void *opaque)\r
-{\r
-    struct jz4740_tcu_s *s = (struct jz4740_tcu_s *) opaque;\r
-    int64_t next = qemu_get_clock(vm_clock);\r
-    int64_t count;\r
-\r
-    if ((!(s->tsr & (1 << TCU_INDEX))) && (s->ter & (1 << TCU_INDEX))\r
-        && (s->freq[TCU_INDEX] != 0))\r
-    {\r
-        //printf("s->tdfr[TCU_INDEX]  %x s->prescale[TCU_INDEX]  %x \n",s->tdfr[TCU_INDEX] ,s->prescale[TCU_INDEX] );\r
-        count = s->tdfr[TCU_INDEX] * s->prescale[TCU_INDEX];\r
-        next += muldiv64(count, ticks_per_sec, s->freq[TCU_INDEX]);\r
-        //printf("count  %lld next  %lld \n",count,next);\r
-        qemu_mod_timer(s->full_timer[TCU_INDEX], next);\r
-        s->tfr |= 1 << TCU_INDEX;\r
-        jz4740_tcu_update_interrupt(s);\r
-        s->tcnt[TCU_INDEX] = 0;\r
-        s->time[TCU_INDEX] = qemu_get_clock(vm_clock);\r
-    }\r
-    else\r
-        qemu_del_timer(s->full_timer[TCU_INDEX]);\r
-}\r
-\r
-static uint32_t glue(jz4740_tcu_read, TCU_INDEX) (void *opaque,\r
-                                                  target_phys_addr_t addr)\r
-{\r
-    struct jz4740_tcu_s *s = (struct jz4740_tcu_s *) opaque;\r
-\r
-    debug_out(DEBUG_TCU, "jz4740_tcu_read%x addr %x\n", TCU_INDEX, addr);\r
-    addr -= 0x40 + TCU_INDEX * 0x10;\r
-\r
-    switch (addr)\r
-    {\r
-    case 0x0:\r
-        return s->tdfr[TCU_INDEX];\r
-    case 0x4:\r
-        return s->tdhr[TCU_INDEX];\r
-    case 0x8:\r
-        glue(jz4740_tcu_time_sync, TCU_INDEX) (s);\r
-        //debug_out(DEBUG_TCU, "s->tcnt  %x\n", s->tcnt[TCU_INDEX]);\r
-        //printf("s->tcnt  %x\n", s->tcnt[TCU_INDEX]);\r
-        return s->tcnt[TCU_INDEX];\r
-    case 0xc:\r
-        return s->tcsr[TCU_INDEX];\r
-    default:\r
-        cpu_abort(s->soc->env,\r
-                  "jz4740_tcu_read undefined addr %x timer %x \n", addr,\r
-                  TCU_INDEX);\r
-    }\r
-    return (0);\r
-}\r
-\r
-static void glue(jz4740_tcu_write, TCU_INDEX) (void *opaque,\r
-                                               target_phys_addr_t addr,\r
-                                               uint32_t value)\r
-{\r
-    struct jz4740_tcu_s *s = (struct jz4740_tcu_s *) opaque;\r
-\r
-    debug_out(DEBUG_TCU, "jz4740_tcu_write%x addr %x value %x \n", TCU_INDEX,\r
-              addr, value);\r
-printf( "jz4740_tcu_write%x addr %x value %x \n", TCU_INDEX,\r
-              addr, value);\r
-    addr -= 0x40 + TCU_INDEX * 0x10;\r
-\r
-    switch (addr)\r
-    {\r
-    case 0x0:\r
-         /*TDFR*/ \r
-         \r
-         s->tdfr[TCU_INDEX] = value & 0xffff;\r
-         printf("s->tdfr[TCU_INDEX]  %x \n",s->tdfr[TCU_INDEX] );\r
-        glue(jz4740_tcu_start_full, TCU_INDEX) (s);\r
-        break;\r
-    case 0x4:\r
-         /*TDHR*/ s->tdhr[TCU_INDEX] = value & 0xffff;\r
-        glue(jz4740_tcu_start_half, TCU_INDEX) (s);\r
-        break;\r
-    case 0x8:\r
-         /*TCNT*/ s->tcnt[TCU_INDEX] = value & 0xffff;\r
-        s->time[TCU_INDEX] = qemu_get_clock(vm_clock);\r
-        glue(jz4740_tcu_start_half, TCU_INDEX) (s);\r
-        glue(jz4740_tcu_start_full, TCU_INDEX) (s);\r
-        break;\r
-    case 0xc:\r
-        s->tcsr[TCU_INDEX] = value & 0x3bf;\r
-        switch (value & 0x7)\r
-        {\r
-        case 0x1:\r
-            s->freq[TCU_INDEX] = jz_clk_getrate(jz_findclk(s->soc, "pclk"));\r
-            break;\r
-        case 0x2:\r
-            s->freq[TCU_INDEX] = jz_clk_getrate(jz_findclk(s->soc, "osc_32K"));\r
-            break;\r
-        case 0x4:\r
-            s->freq[TCU_INDEX] =\r
-                jz_clk_getrate(jz_findclk(s->soc, "osc_extal"));\r
-            break;\r
-        default:\r
-            s->freq[TCU_INDEX] = 0x0;\r
-            break;\r
-        }\r
-        s->prescale[TCU_INDEX] = 1 << (((value & 0x38) >> 3) * 2);\r
-        printf("s->prescale[TCU_INDEX]  %x\n",s->prescale[TCU_INDEX] );\r
-        glue(jz4740_tcu_start_half, TCU_INDEX) (s);\r
-        glue(jz4740_tcu_start_full, TCU_INDEX) (s);\r
-        break;\r
-    default:\r
-        cpu_abort(s->soc->env,\r
-                  "jz4740_tcu_write undefined addr %x timer %x \n", addr,\r
-                  TCU_INDEX);\r
-\r
-    }\r
-}\r
-\r
-\r
-static CPUReadMemoryFunc *glue(jz4740_tcu_readfn, TCU_INDEX)[] =\r
-{\r
-jz4740_badwidth_read16,\r
-        glue(jz4740_tcu_read, TCU_INDEX), jz4740_badwidth_read16,};\r
-\r
-static CPUWriteMemoryFunc *glue(jz4740_tcu_writefn, TCU_INDEX)[] =\r
-{\r
-jz4740_badwidth_write16,\r
-        glue(jz4740_tcu_write, TCU_INDEX), jz4740_badwidth_write16,};\r
-\r
-static void glue(jz4740_tcu_init, TCU_INDEX) (struct jz_state_s * soc,\r
-                                              struct jz4740_tcu_s * s)\r
-{\r
-    int iomemtype;\r
-\r
-    s->half_timer[TCU_INDEX] =\r
-        qemu_new_timer(vm_clock, glue(jz4740_tcu_half_cb, TCU_INDEX), s);\r
-    s->full_timer[TCU_INDEX] =\r
-        qemu_new_timer(vm_clock, glue(jz4740_tcu_full_cb, TCU_INDEX), s);\r
-\r
-    iomemtype =\r
-        cpu_register_io_memory(0, glue(jz4740_tcu_readfn, TCU_INDEX),\r
-                               glue(jz4740_tcu_writefn, TCU_INDEX), s);\r
-    cpu_register_physical_memory(s->base + 0x00000040 + TCU_INDEX * 0x10,\r
-                                 0x00000010, iomemtype);\r
-}\r
-\r
-#undef TCU_INDEX\r
-#endif\r
-\r
-\r
-\r
-#ifdef JZ4740_LCD_PANEL\r
-\r
-#if DEPTH == 8\r
-# define BPP 1\r
-# define PIXEL_TYPE uint8_t\r
-#elif DEPTH == 15 || DEPTH == 16\r
-# define BPP 2\r
-# define PIXEL_TYPE uint16_t\r
-#elif DEPTH == 24\r
-# define BPP 3\r
-# define PIXEL_TYPE uint32_t\r
-#elif DEPTH == 32\r
-# define BPP 4\r
-# define PIXEL_TYPE uint32_t\r
-#else\r
-# error unsupport depth\r
-#endif\r
-\r
-/*\r
- * 2-bit colour\r
- */\r
-static void glue(draw_line2_, DEPTH) (uint8_t * d, const uint8_t * s, int width,\r
-                                      const uint16_t * pal)\r
-{\r
-    uint8_t v, r, g, b;\r
-\r
-    do\r
-    {\r
-        v = ldub_raw((void *) s);\r
-        r = (pal[v & 3] >> 4) & 0xf0;\r
-        g = pal[v & 3] & 0xf0;\r
-        b = (pal[v & 3] << 4) & 0xf0;\r
-        ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);\r
-        d += BPP;\r
-        v >>= 2;\r
-        r = (pal[v & 3] >> 4) & 0xf0;\r
-        g = pal[v & 3] & 0xf0;\r
-        b = (pal[v & 3] << 4) & 0xf0;\r
-        ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);\r
-        d += BPP;\r
-        v >>= 2;\r
-        r = (pal[v & 3] >> 4) & 0xf0;\r
-        g = pal[v & 3] & 0xf0;\r
-        b = (pal[v & 3] << 4) & 0xf0;\r
-        ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);\r
-        d += BPP;\r
-        v >>= 2;\r
-        r = (pal[v & 3] >> 4) & 0xf0;\r
-        g = pal[v & 3] & 0xf0;\r
-        b = (pal[v & 3] << 4) & 0xf0;\r
-        ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);\r
-        d += BPP;\r
-        s++;\r
-        width -= 4;\r
-    }\r
-    while (width > 0);\r
-}\r
-\r
-/*\r
- * 4-bit colour\r
- */\r
-static void glue(draw_line4_, DEPTH) (uint8_t * d, const uint8_t * s, int width,\r
-                                      const uint16_t * pal)\r
-{\r
-    uint8_t v, r, g, b;\r
-\r
-    do\r
-    {\r
-        v = ldub_raw((void *) s);\r
-        r = (pal[v & 0xf] >> 4) & 0xf0;\r
-        g = pal[v & 0xf] & 0xf0;\r
-        b = (pal[v & 0xf] << 4) & 0xf0;\r
-        ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);\r
-        d += BPP;\r
-        v >>= 4;\r
-        r = (pal[v & 0xf] >> 4) & 0xf0;\r
-        g = pal[v & 0xf] & 0xf0;\r
-        b = (pal[v & 0xf] << 4) & 0xf0;\r
-        ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);\r
-        d += BPP;\r
-        s++;\r
-        width -= 2;\r
-    }\r
-    while (width > 0);\r
-}\r
-\r
-/*\r
- * 8-bit colour\r
- */\r
-static void glue(draw_line8_, DEPTH) (uint8_t * d, const uint8_t * s, int width,\r
-                                      const uint16_t * pal)\r
-{\r
-    uint8_t v, r, g, b;\r
-\r
-    do\r
-    {\r
-        v = ldub_raw((void *) s);\r
-        r = (pal[v] >> 4) & 0xf0;\r
-        g = pal[v] & 0xf0;\r
-        b = (pal[v] << 4) & 0xf0;\r
-        ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);\r
-        s++;\r
-        d += BPP;\r
-    }\r
-    while (--width != 0);\r
-}\r
-\r
-\r
-/*\r
- * 16-bit colour\r
- */\r
-static void glue(draw_line16_, DEPTH) (uint8_t * d, const uint8_t * s,\r
-                                       int width, const uint16_t * pal)\r
-{\r
-#if DEPTH == 16 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)\r
-    memcpy(d, s, width * 2);\r
-#else\r
-    uint16_t v;\r
-    uint8_t r, g, b;\r
-\r
-    do\r
-    {\r
-        v = lduw_raw((void *) s);\r
-        r = (v >> 8) & 0xf8;\r
-        g = (v >> 3) & 0xfc;\r
-        b = (v << 3) & 0xf8;\r
-        ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);\r
-        s += 2;\r
-        d += BPP;\r
-    }\r
-    while (--width != 0);\r
-#endif\r
-}\r
-\r
-/*\r
- * 24-bit colour.  JZ4740 uses 4 bytes to store 18/24 bit color.\r
- */\r
-static void glue(draw_line24_, DEPTH) (uint8_t * d, const uint8_t * s,\r
-                                       int width, const uint16_t * pal)\r
-{\r
-#if DEPTH == 32 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)\r
-    memcpy(d, s, width * 4);\r
-#else\r
-    uint32_t v;\r
-    uint8_t r, g, b;\r
-\r
-    do\r
-    {\r
-        v = ldl_raw((void *) s);\r
-        r = (v >> 16) & 0xff;\r
-        g = (v >> 8) & 0xff;\r
-        b = (v >> 0) & 0xff;\r
-        ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);\r
-        s += 3;\r
-        d += BPP;\r
-    }\r
-    while (--width != 0);\r
-#endif\r
-}\r
-\r
-static jz4740_lcd_fn_t glue(jz4740_lcd_draw_fn_, DEPTH)[6] =\r
-{\r
-    NULL,                       /*0x0 *//*1 bit per pixel */\r
-        (jz4740_lcd_fn_t) glue(draw_line2_, DEPTH),     /*0x1 *//*2 bit per pixel */\r
-        (jz4740_lcd_fn_t) glue(draw_line4_, DEPTH),     /*0x2 *//*4 bit per pixel */\r
-        (jz4740_lcd_fn_t) glue(draw_line8_, DEPTH),     /*0x3 *//*8 bit per pixel */\r
-        (jz4740_lcd_fn_t) glue(draw_line16_, DEPTH),    /*0x4 *//*15/16 bit per pixel */\r
-        (jz4740_lcd_fn_t) glue(draw_line24_, DEPTH),    /*0x5 *//*18/24 bit per pixel */\r
-};\r
-\r
-\r
-#undef DEPTH\r
-#undef BPP\r
-#undef PIXEL_TYPE\r
-\r
-#endif\r
+/*
+ * QEMU JZ Soc emulation glue code
+ *
+ * Copyright (c) 2009 yajin (yajin@vm-kernel.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+
+#ifdef TCU_INDEX
+static inline void glue(jz4740_tcu_time_sync,
+                        TCU_INDEX) (struct jz4740_tcu_s * s)
+{
+    int64_t distance;
+    int64_t temp;
+
+    if ((!(s->tsr & (1 << TCU_INDEX))) && (s->ter & (1 << TCU_INDEX))
+        && (s->freq[TCU_INDEX] != 0))
+    {
+        //debug_out(DEBUG_TCU, "jz4740_tcu_time_sync%x \n", TCU_INDEX);
+        /*first enable timer */
+        if (s->time[TCU_INDEX] == 0)
+        {
+            s->time[TCU_INDEX] = qemu_get_clock(vm_clock);
+            s->tcnt[TCU_INDEX] = 0;
+            return;
+        }
+        distance = qemu_get_clock(vm_clock) - s->time[TCU_INDEX];
+        //debug_out(DEBUG_TCU,
+         //         "s->freq[TCU_INDEX]  %d s->prescale[TCU_INDEX] %d \n",
+         //         s->freq[TCU_INDEX], s->prescale[TCU_INDEX]);
+       // debug_out(DEBUG_TCU, "distance %lld s->time[TCU_INDEX] %lld \n",
+       //           distance, s->time[TCU_INDEX]);
+        //temp = muldiv64(distance,(s->freq[TCU_INDEX]/s->prescale[TCU_INDEX]),ticks_per_sec);
+        temp = muldiv64(distance, 46875, ticks_per_sec);
+        if (temp != 0)
+        {
+            /*distance is too short */
+            s->tcnt[TCU_INDEX] += temp;
+            s->time[TCU_INDEX] = qemu_get_clock(vm_clock);
+        }
+        else
+        {
+            /*distance is too short.
+             * Do not sync timer this timer.
+             */
+        }
+
+        //printf("%lld distance %lld \n",muldiv64(distance,(s->freq[TCU_INDEX]/s->prescale[TCU_INDEX]),ticks_per_sec),distance);
+
+        if (s->tcnt[TCU_INDEX] >= 0x10000)
+            s->tcnt[TCU_INDEX] = 0x0;
+
+
+    }
+}
+
+static inline void glue(jz4740_tcu_start_half,
+                        TCU_INDEX) (struct jz4740_tcu_s * s)
+{
+    int64_t next = qemu_get_clock(vm_clock);
+    int64_t count;
+
+    /*The timer has not beed initialized */
+    if (!s->half_timer[TCU_INDEX])
+        return;
+       
+    if ((!(s->tsr & (1 << (TCU_INDEX+16)))) && (s->ter & (1 << (TCU_INDEX+16)))
+        && (s->freq[TCU_INDEX] != 0))
+    {
+        glue(jz4740_tcu_time_sync, TCU_INDEX) (s);
+        /*calculate next fire time */
+        count =
+            (s->tdhr[TCU_INDEX] - s->tcnt[TCU_INDEX]) * s->prescale[TCU_INDEX];
+        next += muldiv64(count, ticks_per_sec, s->freq[TCU_INDEX]);
+        qemu_mod_timer(s->half_timer[TCU_INDEX], next);
+
+    }
+    else
+        qemu_del_timer(s->half_timer[TCU_INDEX]);
+
+}
+
+static inline void glue(jz4740_tcu_start_full,
+                        TCU_INDEX) (struct jz4740_tcu_s * s)
+{
+    int64_t next = qemu_get_clock(vm_clock);
+    int64_t count;
+
+    /*The timer has not beed initialized */
+    if (!s->full_timer[TCU_INDEX])
+        return;
+        
+       debug_out(DEBUG_TCU, "s->tsr %d  s->ter %d  s->freq[TCU_INDEX]  %d \n",
+                                         s->tsr ,  s->ter ,s->freq[TCU_INDEX]);
+printf("s->tsr %d  s->ter %d  s->freq[TCU_INDEX]  %d \n",
+                                         s->tsr ,  s->ter ,s->freq[TCU_INDEX]);
+    if ((!(s->tsr & (1 << TCU_INDEX))) && (s->ter & (1 << TCU_INDEX))
+        && (s->freq[TCU_INDEX] != 0))
+    {
+        glue(jz4740_tcu_time_sync, TCU_INDEX) (s);
+        printf("tdfr %x \n",s->tdfr[TCU_INDEX] );
+        /*calculate next fire time */
+        count =
+            (s->tdfr[TCU_INDEX] - s->tcnt[TCU_INDEX]) * s->prescale[TCU_INDEX];
+        printf("tdfr11 %x count %lld\n",s->tdfr[TCU_INDEX],count );
+        next += muldiv64(count, ticks_per_sec, s->freq[TCU_INDEX]);
+        qemu_mod_timer(s->full_timer[TCU_INDEX], next);
+                debug_out(DEBUG_TCU, "s->tdfr[TCU_INDEX]  %d  s->tcnt[TCU_INDEX] %d  next  %lld \n",
+                                         s->tdfr[TCU_INDEX] ,  s->tcnt[TCU_INDEX]  ,next);
+                       printf("s->tdfr[TCU_INDEX]22  %x  s->tcnt[TCU_INDEX] %x next  %lld \n",
+                                         s->tdfr[TCU_INDEX] ,  s->tcnt[TCU_INDEX]  ,next);
+
+    }
+    else
+        qemu_del_timer(s->full_timer[TCU_INDEX]);
+}
+
+
+/* 
+ *     TCNT will reset to 0 if it reach to TDFR.
+ *       So for the half compare, the next fire count is (TDFR-TDHR) + TDHR
+ *                                                                                            
+ */
+static void glue(jz4740_tcu_half_cb, TCU_INDEX) (void *opaque)
+{
+    struct jz4740_tcu_s *s = (struct jz4740_tcu_s *) opaque;
+    int64_t next = qemu_get_clock(vm_clock);
+    int64_t count;
+
+    if ((!(s->tsr & (1 << TCU_INDEX))) && (s->ter & (1 << TCU_INDEX))
+        && (s->freq[TCU_INDEX] != 0))
+    {
+        count = s->tdfr[TCU_INDEX] * s->prescale[TCU_INDEX];
+        next += muldiv64(count, ticks_per_sec, s->freq[TCU_INDEX]);
+        qemu_mod_timer(s->half_timer[TCU_INDEX], next);
+        s->tfr |= 1 << (16 + TCU_INDEX);
+        jz4740_tcu_update_interrupt(s);
+        s->tcnt[TCU_INDEX] = s->tdhr[TCU_INDEX];
+        s->time[TCU_INDEX] = qemu_get_clock(vm_clock);
+    }
+    else
+        qemu_del_timer(s->half_timer[TCU_INDEX]);
+}
+
+
+static void glue(jz4740_tcu_full_cb, TCU_INDEX) (void *opaque)
+{
+    struct jz4740_tcu_s *s = (struct jz4740_tcu_s *) opaque;
+    int64_t next = qemu_get_clock(vm_clock);
+    int64_t count;
+
+    if ((!(s->tsr & (1 << TCU_INDEX))) && (s->ter & (1 << TCU_INDEX))
+        && (s->freq[TCU_INDEX] != 0))
+    {
+        //printf("s->tdfr[TCU_INDEX]  %x s->prescale[TCU_INDEX]  %x \n",s->tdfr[TCU_INDEX] ,s->prescale[TCU_INDEX] );
+        count = s->tdfr[TCU_INDEX] * s->prescale[TCU_INDEX];
+        next += muldiv64(count, ticks_per_sec, s->freq[TCU_INDEX]);
+        //printf("count  %lld next  %lld \n",count,next);
+        qemu_mod_timer(s->full_timer[TCU_INDEX], next);
+        s->tfr |= 1 << TCU_INDEX;
+        jz4740_tcu_update_interrupt(s);
+        s->tcnt[TCU_INDEX] = 0;
+        s->time[TCU_INDEX] = qemu_get_clock(vm_clock);
+    }
+    else
+        qemu_del_timer(s->full_timer[TCU_INDEX]);
+}
+
+static uint32_t glue(jz4740_tcu_read, TCU_INDEX) (void *opaque,
+                                                  target_phys_addr_t addr)
+{
+    struct jz4740_tcu_s *s = (struct jz4740_tcu_s *) opaque;
+
+    debug_out(DEBUG_TCU, "jz4740_tcu_read%x addr %x\n", TCU_INDEX, addr);
+    addr -= 0x40 + TCU_INDEX * 0x10;
+
+    switch (addr)
+    {
+    case 0x0:
+        return s->tdfr[TCU_INDEX];
+    case 0x4:
+        return s->tdhr[TCU_INDEX];
+    case 0x8:
+        glue(jz4740_tcu_time_sync, TCU_INDEX) (s);
+        //debug_out(DEBUG_TCU, "s->tcnt  %x\n", s->tcnt[TCU_INDEX]);
+        //printf("s->tcnt  %x\n", s->tcnt[TCU_INDEX]);
+        return s->tcnt[TCU_INDEX];
+    case 0xc:
+        return s->tcsr[TCU_INDEX];
+    default:
+        cpu_abort(s->soc->env,
+                  "jz4740_tcu_read undefined addr %x timer %x \n", addr,
+                  TCU_INDEX);
+    }
+    return (0);
+}
+
+static void glue(jz4740_tcu_write, TCU_INDEX) (void *opaque,
+                                               target_phys_addr_t addr,
+                                               uint32_t value)
+{
+    struct jz4740_tcu_s *s = (struct jz4740_tcu_s *) opaque;
+
+    debug_out(DEBUG_TCU, "jz4740_tcu_write%x addr %x value %x \n", TCU_INDEX,
+              addr, value);
+printf( "jz4740_tcu_write%x addr %x value %x \n", TCU_INDEX,
+              addr, value);
+    addr -= 0x40 + TCU_INDEX * 0x10;
+
+    switch (addr)
+    {
+    case 0x0:
+         /*TDFR*/ 
+         
+         s->tdfr[TCU_INDEX] = value & 0xffff;
+         printf("s->tdfr[TCU_INDEX]  %x \n",s->tdfr[TCU_INDEX] );
+        glue(jz4740_tcu_start_full, TCU_INDEX) (s);
+        break;
+    case 0x4:
+         /*TDHR*/ s->tdhr[TCU_INDEX] = value & 0xffff;
+        glue(jz4740_tcu_start_half, TCU_INDEX) (s);
+        break;
+    case 0x8:
+         /*TCNT*/ s->tcnt[TCU_INDEX] = value & 0xffff;
+        s->time[TCU_INDEX] = qemu_get_clock(vm_clock);
+        glue(jz4740_tcu_start_half, TCU_INDEX) (s);
+        glue(jz4740_tcu_start_full, TCU_INDEX) (s);
+        break;
+    case 0xc:
+        s->tcsr[TCU_INDEX] = value & 0x3bf;
+        switch (value & 0x7)
+        {
+        case 0x1:
+            s->freq[TCU_INDEX] = jz_clk_getrate(jz_findclk(s->soc, "pclk"));
+            break;
+        case 0x2:
+            s->freq[TCU_INDEX] = jz_clk_getrate(jz_findclk(s->soc, "osc_32K"));
+            break;
+        case 0x4:
+            s->freq[TCU_INDEX] =
+                jz_clk_getrate(jz_findclk(s->soc, "osc_extal"));
+            break;
+        default:
+            s->freq[TCU_INDEX] = 0x0;
+            break;
+        }
+        s->prescale[TCU_INDEX] = 1 << (((value & 0x38) >> 3) * 2);
+        printf("s->prescale[TCU_INDEX]  %x\n",s->prescale[TCU_INDEX] );
+        glue(jz4740_tcu_start_half, TCU_INDEX) (s);
+        glue(jz4740_tcu_start_full, TCU_INDEX) (s);
+        break;
+    default:
+        cpu_abort(s->soc->env,
+                  "jz4740_tcu_write undefined addr %x timer %x \n", addr,
+                  TCU_INDEX);
+
+    }
+}
+
+
+static CPUReadMemoryFunc *glue(jz4740_tcu_readfn, TCU_INDEX)[] =
+{
+jz4740_badwidth_read16,
+        glue(jz4740_tcu_read, TCU_INDEX), jz4740_badwidth_read16,};
+
+static CPUWriteMemoryFunc *glue(jz4740_tcu_writefn, TCU_INDEX)[] =
+{
+jz4740_badwidth_write16,
+        glue(jz4740_tcu_write, TCU_INDEX), jz4740_badwidth_write16,};
+
+static void glue(jz4740_tcu_init, TCU_INDEX) (struct jz_state_s * soc,
+                                              struct jz4740_tcu_s * s)
+{
+    int iomemtype;
+
+    s->half_timer[TCU_INDEX] =
+        qemu_new_timer(vm_clock, glue(jz4740_tcu_half_cb, TCU_INDEX), s);
+    s->full_timer[TCU_INDEX] =
+        qemu_new_timer(vm_clock, glue(jz4740_tcu_full_cb, TCU_INDEX), s);
+
+    iomemtype =
+        cpu_register_io_memory(0, glue(jz4740_tcu_readfn, TCU_INDEX),
+                               glue(jz4740_tcu_writefn, TCU_INDEX), s);
+    cpu_register_physical_memory(s->base + 0x00000040 + TCU_INDEX * 0x10,
+                                 0x00000010, iomemtype);
+}
+
+#undef TCU_INDEX
+#endif
+
+
+
+#ifdef JZ4740_LCD_PANEL
+
+#if DEPTH == 8
+# define BPP 1
+# define PIXEL_TYPE uint8_t
+#elif DEPTH == 15 || DEPTH == 16
+# define BPP 2
+# define PIXEL_TYPE uint16_t
+#elif DEPTH == 24
+# define BPP 3
+# define PIXEL_TYPE uint32_t
+#elif DEPTH == 32
+# define BPP 4
+# define PIXEL_TYPE uint32_t
+#else
+# error unsupport depth
+#endif
+
+/*
+ * 2-bit colour
+ */
+static void glue(draw_line2_, DEPTH) (uint8_t * d, const uint8_t * s, int width,
+                                      const uint16_t * pal)
+{
+    uint8_t v, r, g, b;
+
+    do
+    {
+        v = ldub_raw((void *) s);
+        r = (pal[v & 3] >> 4) & 0xf0;
+        g = pal[v & 3] & 0xf0;
+        b = (pal[v & 3] << 4) & 0xf0;
+        ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);
+        d += BPP;
+        v >>= 2;
+        r = (pal[v & 3] >> 4) & 0xf0;
+        g = pal[v & 3] & 0xf0;
+        b = (pal[v & 3] << 4) & 0xf0;
+        ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);
+        d += BPP;
+        v >>= 2;
+        r = (pal[v & 3] >> 4) & 0xf0;
+        g = pal[v & 3] & 0xf0;
+        b = (pal[v & 3] << 4) & 0xf0;
+        ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);
+        d += BPP;
+        v >>= 2;
+        r = (pal[v & 3] >> 4) & 0xf0;
+        g = pal[v & 3] & 0xf0;
+        b = (pal[v & 3] << 4) & 0xf0;
+        ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);
+        d += BPP;
+        s++;
+        width -= 4;
+    }
+    while (width > 0);
+}
+
+/*
+ * 4-bit colour
+ */
+static void glue(draw_line4_, DEPTH) (uint8_t * d, const uint8_t * s, int width,
+                                      const uint16_t * pal)
+{
+    uint8_t v, r, g, b;
+
+    do
+    {
+        v = ldub_raw((void *) s);
+        r = (pal[v & 0xf] >> 4) & 0xf0;
+        g = pal[v & 0xf] & 0xf0;
+        b = (pal[v & 0xf] << 4) & 0xf0;
+        ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);
+        d += BPP;
+        v >>= 4;
+        r = (pal[v & 0xf] >> 4) & 0xf0;
+        g = pal[v & 0xf] & 0xf0;
+        b = (pal[v & 0xf] << 4) & 0xf0;
+        ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);
+        d += BPP;
+        s++;
+        width -= 2;
+    }
+    while (width > 0);
+}
+
+/*
+ * 8-bit colour
+ */
+static void glue(draw_line8_, DEPTH) (uint8_t * d, const uint8_t * s, int width,
+                                      const uint16_t * pal)
+{
+    uint8_t v, r, g, b;
+
+    do
+    {
+        v = ldub_raw((void *) s);
+        r = (pal[v] >> 4) & 0xf0;
+        g = pal[v] & 0xf0;
+        b = (pal[v] << 4) & 0xf0;
+        ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);
+        s++;
+        d += BPP;
+    }
+    while (--width != 0);
+}
+
+
+/*
+ * 16-bit colour
+ */
+static void glue(draw_line16_, DEPTH) (uint8_t * d, const uint8_t * s,
+                                       int width, const uint16_t * pal)
+{
+#if DEPTH == 16 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
+    memcpy(d, s, width * 2);
+#else
+    uint16_t v;
+    uint8_t r, g, b;
+
+    do
+    {
+        v = lduw_raw((void *) s);
+        r = (v >> 8) & 0xf8;
+        g = (v >> 3) & 0xfc;
+        b = (v << 3) & 0xf8;
+        ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);
+        s += 2;
+        d += BPP;
+    }
+    while (--width != 0);
+#endif
+}
+
+/*
+ * 24-bit colour.  JZ4740 uses 4 bytes to store 18/24 bit color.
+ */
+static void glue(draw_line24_, DEPTH) (uint8_t * d, const uint8_t * s,
+                                       int width, const uint16_t * pal)
+{
+#if DEPTH == 32 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
+    memcpy(d, s, width * 4);
+#else
+    uint32_t v;
+    uint8_t r, g, b;
+
+    do
+    {
+        v = ldl_raw((void *) s);
+        r = (v >> 16) & 0xff;
+        g = (v >> 8) & 0xff;
+        b = (v >> 0) & 0xff;
+        ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH) (r, g, b);
+        s += 3;
+        d += BPP;
+    }
+    while (--width != 0);
+#endif
+}
+
+static jz4740_lcd_fn_t glue(jz4740_lcd_draw_fn_, DEPTH)[6] =
+{
+    NULL,                       /*0x0 *//*1 bit per pixel */
+        (jz4740_lcd_fn_t) glue(draw_line2_, DEPTH),     /*0x1 *//*2 bit per pixel */
+        (jz4740_lcd_fn_t) glue(draw_line4_, DEPTH),     /*0x2 *//*4 bit per pixel */
+        (jz4740_lcd_fn_t) glue(draw_line8_, DEPTH),     /*0x3 *//*8 bit per pixel */
+        (jz4740_lcd_fn_t) glue(draw_line16_, DEPTH),    /*0x4 *//*15/16 bit per pixel */
+        (jz4740_lcd_fn_t) glue(draw_line24_, DEPTH),    /*0x5 *//*18/24 bit per pixel */
+};
+
+
+#undef DEPTH
+#undef BPP
+#undef PIXEL_TYPE
+
+#endif
index 972c71c..3ca036b 100644 (file)
@@ -487,19 +487,16 @@ static void audio_init (PCIBus *pci_bus)
 static void network_init (PCIBus *pci_bus)
 {
     int i;
-    NICInfo *nd;
 
     for(i = 0; i < nb_nics; i++) {
-        nd = &nd_table[i];
-        if (!nd->model) {
-            nd->model = "pcnet";
-        }
-        if (i == 0  && strcmp(nd->model, "pcnet") == 0) {
+        NICInfo *nd = &nd_table[i];
+        int devfn = -1;
+
+        if (i == 0 && (!nd->model || strcmp(nd->model, "pcnet") == 0))
             /* The malta board has a PCNet card using PCI SLOT 11 */
-            pci_nic_init(pci_bus, nd, 88);
-        } else {
-            pci_nic_init(pci_bus, nd, -1);
-        }
+            devfn = 88;
+
+        pci_nic_init(pci_bus, nd, devfn, "pcnet");
     }
 }
 
index dc62f69..83f1a63 100644 (file)
@@ -175,19 +175,9 @@ mips_mipssim_init (ram_addr_t ram_size, int vga_ram_size,
     if (serial_hds[0])
         serial_init(0x3f8, env->irq[4], 115200, serial_hds[0]);
 
-    if (nd_table[0].vlan) {
-        if (nd_table[0].model == NULL
-            || strcmp(nd_table[0].model, "mipsnet") == 0) {
-            /* MIPSnet uses the MIPS CPU INT0, which is interrupt 2. */
-            mipsnet_init(0x4200, env->irq[2], &nd_table[0]);
-        } else if (strcmp(nd_table[0].model, "?") == 0) {
-            fprintf(stderr, "qemu: Supported NICs: mipsnet\n");
-            exit (1);
-        } else {
-            fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model);
-            exit (1);
-        }
-    }
+    if (nd_table[0].vlan)
+        /* MIPSnet uses the MIPS CPU INT0, which is interrupt 2. */
+        mipsnet_init(0x4200, env->irq[2], &nd_table[0]);
 }
 
 QEMUMachine mips_mipssim_machine = {
index d925244..f98e7e9 100755 (executable)
 struct mips_pavo_s
 {
     struct jz_state_s *soc;
+
+    struct nand_bflash_s *nand;
 };
 
+static uint32_t pavo_nand_read8(void *opaque, target_phys_addr_t addr)
+{
+       struct mips_pavo_s *s = (struct mips_pavo_s *) opaque;
+
+       switch (addr)
+       {
+               case 0x8000: /*NAND_COMMAND*/
+               case 0x10000: /*NAND_ADDRESS*/
+                       jz4740_badwidth_read8(s,addr);
+                       break;
+               case 0x0: /*NAND_DATA*/
+                       return nandb_read_data8(s->nand);
+                       break;
+               default:
+                       jz4740_badwidth_read8(s,addr);
+                       break;
+       }
+    return 0;
+}
+
+static void pavo_nand_write8(void *opaque, target_phys_addr_t addr,
+                uint32_t value)
+{
+       struct mips_pavo_s *s = (struct mips_pavo_s *) opaque;
+
+       //printf("write addr %x value %x \n",addr,value);
+
+    switch (addr)
+       {
+               case 0x8000: /*NAND_COMMAND*/
+                       nandb_write_command(s->nand,value);
+                       break;
+               case 0x10000: /*NAND_ADDRESS*/
+                       nandb_write_address(s->nand,value);
+                       break;
+               case 0x0: /*NAND_DATA*/
+                       nandb_write_data8(s->nand,value);
+                       break;
+               default:
+                       jz4740_badwidth_write8(s,addr,value);
+                       break;
+       }
+}
+
+
+CPUReadMemoryFunc *pavo_nand_readfn[] = {
+        pavo_nand_read8,
+        jz4740_badwidth_read16,
+        jz4740_badwidth_read32,
+};
+CPUWriteMemoryFunc *pavo_nand_writefn[] = {
+        pavo_nand_write8,
+        jz4740_badwidth_write16,
+        jz4740_badwidth_write32,
+};
+    
+static void pavo_nand_setup(struct mips_pavo_s *s)
+{
+       int iomemtype;
+       
+       /*K9K8G08U0*/
+       s->nand = nandb_init(NAND_MFR_SAMSUNG,0xd3);
+
+       iomemtype = cpu_register_io_memory(0, pavo_nand_readfn,
+                    pavo_nand_writefn, s);
+    cpu_register_physical_memory(0x18000000, 0x20000, iomemtype);
+}
+
+static int pavo_nand_read_page(struct mips_pavo_s *s,uint8_t *buf, uint16_t page_addr)
+{
+       uint8_t *p;
+       int i;
+
+       p=(uint8_t *)buf;
+
+       /*send command 0x0*/
+       pavo_nand_write8(s,0x00008000,0);
+       /*send page address */
+       pavo_nand_write8(s,0x00010000,page_addr&0xff);
+       pavo_nand_write8(s,0x00010000,(page_addr>>8)&0x7);
+       pavo_nand_write8(s,0x00010000,(page_addr>>11)&0xff);
+       pavo_nand_write8(s,0x00010000,(page_addr>>19)&0xff);
+       pavo_nand_write8(s,0x00010000,(page_addr>>27)&0xff);
+       /*send command 0x30*/
+       pavo_nand_write8(s,0x00008000,0x30);
+
+       for (i=0;i<0x800;i++)
+       {
+               *p++ = pavo_nand_read8(s,0x00000000);
+       }
+       return 1;
+}
+
+/*read the u-boot from NAND Flash into internal RAM*/
+static int pavo_boot_from_nand(struct mips_pavo_s *s)
+{
+       uint32_t len;
+       uint8_t nand_page[0x800],*load_dest;
+       uint32_t nand_pages,i;
+
+       //int fd;
+       
+
+       len = 0x2000; /*8K*/
+       
+       /*put the first page into internal ram*/
+       load_dest = phys_ram_base;
+       
+       nand_pages = len/0x800;
+       //fd = open("u-boot.bin", O_RDWR | O_CREAT);
+       for (i=0;i<nand_pages;i++)
+       {
+               pavo_nand_read_page(s,nand_page,i*0x800);
+               memcpy(load_dest,nand_page,0x800);
+               //write(fd,nand_page,0x800);
+               load_dest += 0x800;
+       }
+       s->soc->env->active_tc.PC = 0x80000004;
+
+       //close(fd);
+       return 0;
+
+}
+
+
+ static int pavo_rom_emu(struct mips_pavo_s *s)
+{
+       if (pavo_boot_from_nand(s)<0)
+               return (-1); 
+       return (0);
+}
 
 static void mips_pavo_init(ram_addr_t ram_size, int vga_ram_size,
                     const char *boot_device, DisplayState * ds,
@@ -68,11 +201,17 @@ static void mips_pavo_init(ram_addr_t ram_size, int vga_ram_size,
 
     if (ram_size < PAVO_RAM_SIZE + JZ4740_SRAM_SIZE)
     {
-        fprintf(stderr, "This architecture uses %i bytes of memory\n",
+        fprintf(stderr, "This architecture uses %d bytes of memory\n",
                 PAVO_RAM_SIZE + JZ4740_SRAM_SIZE);
         exit(1);
     }
-    s->soc = jz4740_init(PAVO_RAM_SIZE, PAVO_OSC_EXTAL);
+    s->soc = jz4740_init(PAVO_RAM_SIZE, PAVO_OSC_EXTAL,ds);
+    pavo_nand_setup(s);
+    if (pavo_rom_emu(s)<0)
+       {
+               fprintf(stderr,"boot from nand failed \n");
+               exit(-1);
+       }
 
 }
 
index 6551b02..c12ab54 100644 (file)
@@ -247,18 +247,8 @@ void mips_r4k_init (ram_addr_t ram_size, int vga_ram_size,
     isa_vga_init(ds, phys_ram_base + ram_size, ram_size,
                  vga_ram_size);
 
-    if (nd_table[0].vlan) {
-        if (nd_table[0].model == NULL
-            || strcmp(nd_table[0].model, "ne2k_isa") == 0) {
-            isa_ne2000_init(0x300, i8259[9], &nd_table[0]);
-        } else if (strcmp(nd_table[0].model, "?") == 0) {
-            fprintf(stderr, "qemu: Supported NICs: ne2k_isa\n");
-            exit (1);
-        } else {
-            fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model);
-            exit (1);
-        }
-    }
+    if (nd_table[0].vlan)
+        isa_ne2000_init(0x300, i8259[9], &nd_table[0]);
 
     if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
         fprintf(stderr, "qemu: too many IDE bus\n");
index 13217b2..67b8735 100644 (file)
@@ -7,10 +7,15 @@
 /* XXX: do not use a global */
 uint32_t cpu_mips_get_random (CPUState *env)
 {
-    static uint32_t seed = 0;
+    static uint32_t lfsr = 1;
+    static uint32_t prev_idx = 0;
     uint32_t idx;
-    seed = seed * 314159 + 1;
-    idx = (seed >> 16) % (env->tlb->nb_tlb - env->CP0_Wired) + env->CP0_Wired;
+    /* Don't return same value twice, so get another value */
+    do {
+        lfsr = (lfsr >> 1) ^ (-(lfsr & 1u) & 0xd0000001u);
+        idx = lfsr % (env->tlb->nb_tlb - env->CP0_Wired) + env->CP0_Wired;
+    } while (idx == prev_idx);
+    prev_idx = idx;
     return idx;
 }
 
index 0eb4c1e..04ce322 100644 (file)
@@ -236,6 +236,8 @@ void mipsnet_init (int base, qemu_irq irq, NICInfo *nd)
 {
     MIPSnetState *s;
 
+    qemu_check_nic_model(nd, "mipsnet");
+
     s = qemu_mallocz(sizeof(MIPSnetState));
     if (!s)
         return;
index 1c932ec..f64bb1c 100644 (file)
@@ -714,6 +714,8 @@ static void mv88w8618_eth_init(NICInfo *nd, uint32_t base, qemu_irq irq)
     mv88w8618_eth_state *s;
     int iomemtype;
 
+    qemu_check_nic_model(nd, "mv88w8618");
+
     s = qemu_mallocz(sizeof(mv88w8618_eth_state));
     if (!s)
         return;
index 200db90..a85730f 100644 (file)
@@ -722,6 +722,8 @@ void isa_ne2000_init(int base, qemu_irq irq, NICInfo *nd)
 {
     NE2000State *s;
 
+    qemu_check_nic_model(nd, "ne2k_isa");
+
     s = qemu_mallocz(sizeof(NE2000State));
     if (!s)
         return;
diff --git a/hw/pc.c b/hw/pc.c
index 64c08a4..6a1c8ec 100644 (file)
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -764,7 +764,6 @@ static void pc_init1(ram_addr_t ram_size, int vga_ram_size,
     PCIBus *pci_bus;
     int piix3_devfn = -1;
     CPUState *env;
-    NICInfo *nd;
     qemu_irq *cpu_irq;
     qemu_irq *i8259;
     int index;
@@ -1000,27 +999,12 @@ static void pc_init1(ram_addr_t ram_size, int vga_ram_size,
     }
 
     for(i = 0; i < nb_nics; i++) {
-        nd = &nd_table[i];
-        if (!nd->model) {
-            if (pci_enabled) {
-                nd->model = "ne2k_pci";
-            } else {
-                nd->model = "ne2k_isa";
-            }
-        }
-        if (strcmp(nd->model, "ne2k_isa") == 0) {
+        NICInfo *nd = &nd_table[i];
+
+        if (!pci_enabled || (nd->model && strcmp(nd->model, "ne2k_isa") == 0))
             pc_init_ne2k_isa(nd, i8259);
-        } else if (pci_enabled) {
-            if (strcmp(nd->model, "?") == 0)
-                fprintf(stderr, "qemu: Supported ISA NICs: ne2k_isa\n");
-            pci_nic_init(pci_bus, nd, -1);
-        } else if (strcmp(nd->model, "?") == 0) {
-            fprintf(stderr, "qemu: Supported ISA NICs: ne2k_isa\n");
-            exit(1);
-        } else {
-            fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd->model);
-            exit(1);
-        }
+        else
+            pci_nic_init(pci_bus, nd, -1, "ne2k_pci");
     }
 
     if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
index 8252d21..bba50d0 100644 (file)
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -652,33 +652,43 @@ void pci_info(void)
     pci_for_each_device(0, pci_info_device);
 }
 
+static const char * const pci_nic_models[] = {
+    "ne2k_pci",
+    "i82551",
+    "i82557b",
+    "i82559er",
+    "rtl8139",
+    "e1000",
+    "pcnet",
+    "virtio",
+    NULL
+};
+
+typedef void (*PCINICInitFn)(PCIBus *, NICInfo *, int);
+
+static PCINICInitFn pci_nic_init_fns[] = {
+    pci_ne2000_init,
+    pci_i82551_init,
+    pci_i82557b_init,
+    pci_i82559er_init,
+    pci_rtl8139_init,
+    pci_e1000_init,
+    pci_pcnet_init,
+    virtio_net_init,
+    NULL
+};
+
 /* Initialize a PCI NIC.  */
-void pci_nic_init(PCIBus *bus, NICInfo *nd, int devfn)
+void pci_nic_init(PCIBus *bus, NICInfo *nd, int devfn,
+                  const char *default_model)
 {
-    if (strcmp(nd->model, "ne2k_pci") == 0) {
-        pci_ne2000_init(bus, nd, devfn);
-    } else if (strcmp(nd->model, "i82551") == 0) {
-        pci_i82551_init(bus, nd, devfn);
-    } else if (strcmp(nd->model, "i82557b") == 0) {
-        pci_i82557b_init(bus, nd, devfn);
-    } else if (strcmp(nd->model, "i82559er") == 0) {
-        pci_i82559er_init(bus, nd, devfn);
-    } else if (strcmp(nd->model, "rtl8139") == 0) {
-        pci_rtl8139_init(bus, nd, devfn);
-    } else if (strcmp(nd->model, "e1000") == 0) {
-        pci_e1000_init(bus, nd, devfn);
-    } else if (strcmp(nd->model, "pcnet") == 0) {
-        pci_pcnet_init(bus, nd, devfn);
-    } else if (strcmp(nd->model, "virtio") == 0) {
-        virtio_net_init(bus, nd, devfn);
-    } else if (strcmp(nd->model, "?") == 0) {
-        fprintf(stderr, "qemu: Supported PCI NICs: i82551 i82557b i82559er"
-                        " ne2k_pci pcnet rtl8139 e1000 virtio\n");
-        exit (1);
-    } else {
-        fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd->model);
-        exit (1);
-    }
+    int i;
+
+    qemu_check_nic_model_list(nd, pci_nic_models, default_model);
+
+    for (i = 0; pci_nic_models[i]; i++)
+        if (strcmp(nd->model, pci_nic_models[i]) == 0)
+            pci_nic_init_fns[i](bus, nd, devfn);
 }
 
 typedef struct {
index 3b1caf5..76f4474 100644 (file)
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -118,7 +118,8 @@ typedef int (*pci_map_irq_fn)(PCIDevice *pci_dev, int irq_num);
 PCIBus *pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
                          qemu_irq *pic, int devfn_min, int nirq);
 
-void pci_nic_init(PCIBus *bus, NICInfo *nd, int devfn);
+void pci_nic_init(PCIBus *bus, NICInfo *nd, int devfn,
+                  const char *default_model);
 void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len);
 uint32_t pci_data_read(void *opaque, uint32_t addr, int len);
 int pci_bus_num(PCIBus *s);
@@ -168,8 +169,9 @@ void pci_pcnet_init(PCIBus *bus, NICInfo *nd, int devfn);
 PCIBus *pci_prep_init(qemu_irq *pic);
 
 /* apb_pci.c */
-PCIBus *pci_apb_init(target_phys_addr_t special_base, target_phys_addr_t mem_base,
-                     qemu_irq *pic);
+PCIBus *pci_apb_init(target_phys_addr_t special_base,
+                     target_phys_addr_t mem_base,
+                     qemu_irq *pic, PCIBus **bus2, PCIBus **bus3);
 
 /* sh_pci.c */
 PCIBus *sh_pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
index e2e428a..c4f42a4 100644 (file)
 /* Worker routines for a PCI host controller that uses an {address,data}
    register pair to access PCI configuration space.  */
 
+/* debug PCI */
+//#define DEBUG_PCI
+
+#ifdef DEBUG_PCI
+#define PCI_DPRINTF(fmt, args...) \
+do { printf("pci_host_data: " fmt , ##args); } while (0)
+#else
+#define PCI_DPRINTF(fmt, args...)
+#endif
+
 typedef struct {
     uint32_t config_reg;
     PCIBus *bus;
@@ -33,6 +43,9 @@ typedef struct {
 static void pci_host_data_writeb(void* opaque, pci_addr_t addr, uint32_t val)
 {
     PCIHostState *s = opaque;
+
+    PCI_DPRINTF("writeb addr " TARGET_FMT_plx " val %x\n",
+                (target_phys_addr_t)addr, val);
     if (s->config_reg & (1u << 31))
         pci_data_write(s->bus, s->config_reg | (addr & 3), val, 1);
 }
@@ -43,6 +56,8 @@ static void pci_host_data_writew(void* opaque, pci_addr_t addr, uint32_t val)
 #ifdef TARGET_WORDS_BIGENDIAN
     val = bswap16(val);
 #endif
+    PCI_DPRINTF("writew addr " TARGET_FMT_plx " val %x\n",
+                (target_phys_addr_t)addr, val);
     if (s->config_reg & (1u << 31))
         pci_data_write(s->bus, s->config_reg | (addr & 3), val, 2);
 }
@@ -53,6 +68,8 @@ static void pci_host_data_writel(void* opaque, pci_addr_t addr, uint32_t val)
 #ifdef TARGET_WORDS_BIGENDIAN
     val = bswap32(val);
 #endif
+    PCI_DPRINTF("writel addr " TARGET_FMT_plx " val %x\n",
+                (target_phys_addr_t)addr, val);
     if (s->config_reg & (1u << 31))
         pci_data_write(s->bus, s->config_reg, val, 4);
 }
@@ -60,9 +77,14 @@ static void pci_host_data_writel(void* opaque, pci_addr_t addr, uint32_t val)
 static uint32_t pci_host_data_readb(void* opaque, pci_addr_t addr)
 {
     PCIHostState *s = opaque;
+    uint32_t val;
+
     if (!(s->config_reg & (1 << 31)))
         return 0xff;
-    return pci_data_read(s->bus, s->config_reg | (addr & 3), 1);
+    val = pci_data_read(s->bus, s->config_reg | (addr & 3), 1);
+    PCI_DPRINTF("readb addr " TARGET_FMT_plx " val %x\n",
+                (target_phys_addr_t)addr, val);
+    return val;
 }
 
 static uint32_t pci_host_data_readw(void* opaque, pci_addr_t addr)
@@ -72,6 +94,8 @@ static uint32_t pci_host_data_readw(void* opaque, pci_addr_t addr)
     if (!(s->config_reg & (1 << 31)))
         return 0xffff;
     val = pci_data_read(s->bus, s->config_reg | (addr & 3), 2);
+    PCI_DPRINTF("readw addr " TARGET_FMT_plx " val %x\n",
+                (target_phys_addr_t)addr, val);
 #ifdef TARGET_WORDS_BIGENDIAN
     val = bswap16(val);
 #endif
@@ -85,6 +109,8 @@ static uint32_t pci_host_data_readl(void* opaque, pci_addr_t addr)
     if (!(s->config_reg & (1 << 31)))
         return 0xffffffff;
     val = pci_data_read(s->bus, s->config_reg | (addr & 3), 4);
+    PCI_DPRINTF("readl addr " TARGET_FMT_plx " val %x\n",
+                (target_phys_addr_t)addr, val);
 #ifdef TARGET_WORDS_BIGENDIAN
     val = bswap32(val);
 #endif
index 102166e..6198968 100644 (file)
@@ -2087,6 +2087,8 @@ void lance_init(NICInfo *nd, target_phys_addr_t leaddr, void *dma_opaque,
     PCNetState *d;
     int lance_io_memory;
 
+    qemu_check_nic_model(nd, "lance");
+
     d = qemu_mallocz(sizeof(PCNetState));
     if (!d)
         return;
index 297f550..75eb11a 100644 (file)
--- a/hw/ppc.h
+++ b/hw/ppc.h
@@ -33,3 +33,11 @@ void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val);
 void ppc40x_irq_init (CPUState *env);
 void ppc6xx_irq_init (CPUState *env);
 void ppc970_irq_init (CPUState *env);
+
+/* PPC machines for OpenBIOS */
+enum {
+    ARCH_PREP = 0,
+    ARCH_MAC99,
+    ARCH_HEATHROW,
+};
+
index a6fc758..bc8a47b 100644 (file)
@@ -90,7 +90,6 @@ static void bamboo_init(ram_addr_t ram_size, int vga_ram_size,
                         const char *cpu_model)
 {
     unsigned int pci_irq_nrs[4] = { 28, 27, 26, 25 };
-    NICInfo *nd;
     PCIBus *pcibus;
     CPUState *env;
     uint64_t elf_entry;
@@ -118,13 +117,9 @@ static void bamboo_init(ram_addr_t ram_size, int vga_ram_size,
 
         /* Register network interfaces. */
         for (i = 0; i < nb_nics; i++) {
-            nd = &nd_table[i];
-            if (!nd->model) {
-                /* There are no PCI NICs on the Bamboo board, but there are
-                 * PCI slots, so we can pick model whatever we want. */
-                nd->model = "e1000";
-            }
-            pci_nic_init(pcibus, nd, -1);
+            /* There are no PCI NICs on the Bamboo board, but there are
+             * PCI slots, so we can pick whatever default model we want. */
+            pci_nic_init(pcibus, &nd_table[i], -1, "e1000");
         }
     }
 
index 5bdb805..e6fbfcf 100644 (file)
@@ -31,6 +31,7 @@
 #include "net.h"
 #include "sysemu.h"
 #include "boards.h"
+#include "escc.h"
 
 #define MAX_IDE_BUS 2
 
@@ -80,7 +81,7 @@ static void ppc_core99_init (ram_addr_t ram_size, int vga_ram_size,
     m48t59_t *m48t59;
     int vga_bios_size, bios_size;
     qemu_irq *dummy_irq;
-    int pic_mem_index, dbdma_mem_index, cuda_mem_index;
+    int pic_mem_index, dbdma_mem_index, cuda_mem_index, escc_mem_index;
     int ide_mem_index[2];
     int ppc_boot_device;
     int index;
@@ -262,13 +263,12 @@ static void ppc_core99_init (ram_addr_t ram_size, int vga_ram_size,
     /* XXX: suppress that */
     dummy_irq = i8259_init(NULL);
 
-    /* XXX: use Mac Serial port */
-    serial_init(0x3f8, dummy_irq[4], 115200, serial_hds[0]);
-    for(i = 0; i < nb_nics; i++) {
-        if (!nd_table[i].model)
-            nd_table[i].model = "ne2k_pci";
-        pci_nic_init(pci_bus, &nd_table[i], -1);
-    }
+    escc_mem_index = escc_init(0x80013000, dummy_irq[4], dummy_irq[5],
+                               serial_hds[0], serial_hds[1], ESCC_CLOCK, 4);
+
+    for(i = 0; i < nb_nics; i++)
+        pci_nic_init(pci_bus, &nd_table[i], -1, "ne2k_pci");
+
     if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
         fprintf(stderr, "qemu: too many IDE bus\n");
         exit(1);
@@ -295,7 +295,7 @@ static void ppc_core99_init (ram_addr_t ram_size, int vga_ram_size,
     dbdma_init(&dbdma_mem_index);
 
     macio_init(pci_bus, 0x0022, 0, pic_mem_index, dbdma_mem_index,
-               cuda_mem_index, NULL, 2, ide_mem_index);
+               cuda_mem_index, NULL, 2, ide_mem_index, escc_mem_index);
 
     if (usb_enabled) {
         usb_ohci_init_pci(pci_bus, 3, -1);
index c833d17..cc70fb7 100644 (file)
 #define BIOS_FILENAME "ppc_rom.bin"
 #define VGABIOS_FILENAME "video.x"
 #define NVRAM_SIZE        0x2000
-#define PROM_FILENAME    "openbios-ppc32"
+#define PROM_FILENAME    "openbios-ppc"
 #define PROM_ADDR         0xfff00000
 
 #define KERNEL_LOAD_ADDR 0x01000000
 #define INITRD_LOAD_ADDR 0x01800000
 
+#define ESCC_CLOCK 3686400
+
 /* DBDMA */
 void dbdma_init (int *dbdma_mem_index);
 
@@ -46,7 +48,7 @@ void cuda_init (int *cuda_mem_index, qemu_irq irq);
 /* MacIO */
 void macio_init (PCIBus *bus, int device_id, int is_oldworld, int pic_mem_index,
                  int dbdma_mem_index, int cuda_mem_index, void *nvram,
-                 int nb_ide, int *ide_mem_index);
+                 int nb_ide, int *ide_mem_index, int escc_mem_index);
 
 /* NewWorld PowerMac IDE */
 int pmac_ide_init (BlockDriverState **hd_table, qemu_irq irq);
index 1d5e9d6..3eb1061 100644 (file)
 #include "pci.h"
 #include "boards.h"
 #include "fw_cfg.h"
+#include "escc.h"
 
 #define MAX_IDE_BUS 2
 #define VGA_BIOS_SIZE 65536
 #define CFG_ADDR 0xf0000510
 
-enum {
-    ARCH_PREP = 0,
-    ARCH_MAC99,
-    ARCH_HEATHROW,
-};
-
 /* temporary frame buffer OSI calls for the video.x driver. The right
    solution is to modify the driver to use VGA PCI I/Os */
 /* XXX: to be removed. This is no way related to emulation */
@@ -132,7 +127,7 @@ static void ppc_heathrow_init (ram_addr_t ram_size, int vga_ram_size,
     int vga_bios_size, bios_size;
     qemu_irq *dummy_irq;
     int pic_mem_index, nvram_mem_index, dbdma_mem_index, cuda_mem_index;
-    int ide_mem_index[2];
+    int escc_mem_index, ide_mem_index[2];
     int ppc_boot_device;
     BlockDriverState *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
     int index;
@@ -149,8 +144,8 @@ static void ppc_heathrow_init (ram_addr_t ram_size, int vga_ram_size,
             fprintf(stderr, "Unable to find PowerPC CPU definition\n");
             exit(1);
         }
-        /* Set time-base frequency to 100 Mhz */
-        cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL);
+        /* Set time-base frequency to 16.6 Mhz */
+        cpu_ppc_tb_init(env,  16600000UL);
         env->osi_call = vga_osi_call;
         qemu_register_reset(&cpu_ppc_reset, env);
         envs[i] = env;
@@ -160,10 +155,17 @@ static void ppc_heathrow_init (ram_addr_t ram_size, int vga_ram_size,
          * the boot vector is at 0xFFF00100, then we need a 1MB BIOS.
          * But the NVRAM is located at 0xFFF04000...
          */
-        cpu_abort(env, "G3BW Mac hardware can not handle 1 MB BIOS\n");
+        cpu_abort(env, "G3 Beige Mac hardware can not handle 1 MB BIOS\n");
     }
 
     /* allocate RAM */
+    if (ram_size > (2047 << 20)) {
+        fprintf(stderr,
+                "qemu: Too much memory for this machine: %d MB, maximum 2047 MB\n",
+                ((unsigned int)ram_size / (1 << 20)));
+        exit(1);
+    }
+
     ram_offset = qemu_ram_alloc(ram_size);
     cpu_register_physical_memory(0, ram_size, ram_offset);
 
@@ -260,7 +262,7 @@ static void ppc_heathrow_init (ram_addr_t ram_size, int vga_ram_size,
 #endif
         }
         if (ppc_boot_device == '\0') {
-            fprintf(stderr, "No valid boot device for Mac99 machine\n");
+            fprintf(stderr, "No valid boot device for G3 Beige machine\n");
             exit(1);
         }
     }
@@ -302,14 +304,11 @@ static void ppc_heathrow_init (ram_addr_t ram_size, int vga_ram_size,
     /* XXX: suppress that */
     dummy_irq = i8259_init(NULL);
 
-    /* XXX: use Mac Serial port */
-    serial_init(0x3f8, dummy_irq[4], 115200, serial_hds[0]);
+    escc_mem_index = escc_init(0x80013000, pic[0x0f], pic[0x10], serial_hds[0],
+                               serial_hds[1], ESCC_CLOCK, 4);
 
-    for(i = 0; i < nb_nics; i++) {
-        if (!nd_table[i].model)
-            nd_table[i].model = "ne2k_pci";
-        pci_nic_init(pci_bus, &nd_table[i], -1);
-    }
+    for(i = 0; i < nb_nics; i++)
+        pci_nic_init(pci_bus, &nd_table[i], -1, "ne2k_pci");
 
     /* First IDE channel is a CMD646 on the PCI bus */
 
@@ -356,7 +355,7 @@ static void ppc_heathrow_init (ram_addr_t ram_size, int vga_ram_size,
     dbdma_init(&dbdma_mem_index);
 
     macio_init(pci_bus, 0x0010, 1, pic_mem_index, dbdma_mem_index,
-               cuda_mem_index, nvr, 2, ide_mem_index);
+               cuda_mem_index, nvr, 2, ide_mem_index, escc_mem_index);
 
     if (usb_enabled) {
         usb_ohci_init_pci(pci_bus, 3, -1);
index 571c48e..6c0d8fe 100644 (file)
@@ -671,11 +671,13 @@ static void ppc_prep_init (ram_addr_t ram_size, int vga_ram_size,
     if (nb_nics1 > NE2000_NB_MAX)
         nb_nics1 = NE2000_NB_MAX;
     for(i = 0; i < nb_nics1; i++) {
-        if (nd_table[i].model == NULL
-            || strcmp(nd_table[i].model, "ne2k_isa") == 0) {
+        if (nd_table[i].model == NULL) {
+           nd_table[i].model = "ne2k_isa";
+        }
+        if (strcmp(nd_table[i].model, "ne2k_isa") == 0) {
             isa_ne2000_init(ne2000_io[i], i8259[ne2000_irq[i]], &nd_table[i]);
         } else {
-            pci_nic_init(pci_bus, &nd_table[i], -1);
+            pci_nic_init(pci_bus, &nd_table[i], -1, "ne2k_pci");
         }
     }
 
index 5d5eb1e..88853e7 100644 (file)
--- a/hw/r2d.c
+++ b/hw/r2d.c
@@ -230,9 +230,9 @@ static void r2d_init(ram_addr_t ram_size, int vga_ram_size,
         drives_table[drive_get_index(IF_IDE, 0, 0)].bdrv, NULL);
 
     /* NIC: rtl8139 on-board, and 2 slots. */
-    pci_rtl8139_init(pci, &nd_table[0], 2 << 3);
+    pci_nic_init(pci, &nd_table[0], 2 << 3, "rtl8139");
     for (i = 1; i < nb_nics; i++)
-        pci_nic_init(pci, &nd_table[i], -1);
+        pci_nic_init(pci, &nd_table[i], -1, "ne2k_pci");
 
     /* Todo: register on board registers */
     {
index a9d20ed..e285338 100644 (file)
@@ -121,12 +121,12 @@ static void realview_init(ram_addr_t ram_size, int vga_ram_size,
     }
     for(n = 0; n < nb_nics; n++) {
         nd = &nd_table[n];
-        if (!nd->model)
-            nd->model = done_smc ? "rtl8139" : "smc91c111";
-        if (strcmp(nd->model, "smc91c111") == 0) {
+
+        if ((!nd->model && !done_smc) || strcmp(nd->model, "smc91c111") == 0) {
             smc91c111_init(nd, 0x4e000000, pic[28]);
+            done_smc = 1;
         } else {
-            pci_nic_init(pci_bus, nd, -1);
+            pci_nic_init(pci_bus, nd, -1, "rtl8139");
         }
     }
 
index 8be63c5..70cb080 100644 (file)
@@ -472,6 +472,8 @@ typedef struct RTL8139State {
     uint32_t   currTxDesc;
 
     /* C+ mode */
+    uint32_t   cplus_enabled;
+
     uint32_t   currCPlusRxDesc;
     uint32_t   currCPlusTxDesc;
 
@@ -1232,6 +1234,8 @@ static void rtl8139_reset(RTL8139State *s)
     s->CSCR = CSCR_F_LINK_100 | CSCR_HEART_BIT | CSCR_LD;
 
     s->CpCmd   = 0x0; /* reset C+ mode */
+    s->cplus_enabled = 0;
+
 
 //    s->BasicModeCtrl = 0x3100; // 100Mbps, full duplex, autonegotiation
 //    s->BasicModeCtrl = 0x2100; // 100Mbps, full duplex
@@ -1420,6 +1424,8 @@ static void rtl8139_CpCmd_write(RTL8139State *s, uint32_t val)
 
     DEBUG_PRINT(("RTL8139C+ command register write(w) val=0x%04x\n", val));
 
+    s->cplus_enabled = 1;
+
     /* mask unwriteable bits */
     val = SET_MASKED(val, 0xff84, s->CpCmd);
 
@@ -2367,7 +2373,7 @@ static void rtl8139_TxStatus_write(RTL8139State *s, uint32_t txRegOffset, uint32
 
     /* handle C+ transmit mode register configuration */
 
-    if (rtl8139_cp_transmitter_enabled(s))
+    if (s->cplus_enabled)
     {
         DEBUG_PRINT(("RTL8139C+ DTCCR write offset=0x%x val=0x%08x descriptor=%d\n", txRegOffset, val, descriptor));
 
@@ -3190,6 +3196,8 @@ static void rtl8139_save(QEMUFile* f,void* opaque)
     qemu_put_be64(f, s->TCTR_base);
 
     RTL8139TallyCounters_save(f, &s->tally_counters);
+
+    qemu_put_be32s(f, &s->cplus_enabled);
 }
 
 static int rtl8139_load(QEMUFile* f,void* opaque,int version_id)
@@ -3199,7 +3207,7 @@ static int rtl8139_load(QEMUFile* f,void* opaque,int version_id)
     int ret;
 
     /* just 2 versions for now */
-    if (version_id > 3)
+    if (version_id > 4)
             return -EINVAL;
 
     if (version_id >= 3) {
@@ -3299,6 +3307,12 @@ static int rtl8139_load(QEMUFile* f,void* opaque,int version_id)
         RTL8139TallyCounters_clear(&s->tally_counters);
     }
 
+    if (version_id >= 4) {
+        qemu_get_be32s(f, &s->cplus_enabled);
+    } else {
+        s->cplus_enabled = s->CpCmd != 0;
+    }
+
     return 0;
 }
 
@@ -3447,7 +3461,7 @@ void pci_rtl8139_init(PCIBus *bus, NICInfo *nd, int devfn)
     s->cplus_txbuffer_len = 0;
     s->cplus_txbuffer_offset = 0;
 
-    register_savevm("rtl8139", -1, 3, rtl8139_save, rtl8139_load, s);
+    register_savevm("rtl8139", -1, 4, rtl8139_save, rtl8139_load, s);
 
 #ifdef RTL8139_ONBOARD_TIMER
     s->timer = qemu_new_timer(vm_clock, rtl8139_timer, s);
index 27a3158..f5b29a7 100644 (file)
@@ -695,6 +695,8 @@ void smc91c111_init(NICInfo *nd, uint32_t base, qemu_irq irq)
     smc91c111_state *s;
     int iomemtype;
 
+    qemu_check_nic_model(nd, "smc91c111");
+
     s = (smc91c111_state *)qemu_mallocz(sizeof(smc91c111_state));
     iomemtype = cpu_register_io_memory(0, smc91c111_readfn,
                                        smc91c111_writefn, s);
index 703ef7e..7069518 100644 (file)
@@ -1361,10 +1361,8 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model,
             pl022_init(0x40008000, pic[7], NULL, NULL);
         }
     }
-    if (board->dc4 & (1 << 28)) {
-        /* FIXME: Obey network model.  */
+    if (board->dc4 & (1 << 28))
         stellaris_enet_init(&nd_table[0], 0x40048000, pic[42]);
-    }
     if (board->peripherals & BP_GAMEPAD) {
         qemu_irq gpad_irq[5];
         static const int gpad_keycode[5] = { 0xc8, 0xd0, 0xcb, 0xcd, 0x1d };
index a5cd163..88c5620 100644 (file)
@@ -389,6 +389,8 @@ void stellaris_enet_init(NICInfo *nd, uint32_t base, qemu_irq irq)
     stellaris_enet_state *s;
     int iomemtype;
 
+    qemu_check_nic_model(nd, "stellaris");
+
     s = (stellaris_enet_state *)qemu_mallocz(sizeof(stellaris_enet_state));
     iomemtype = cpu_register_io_memory(0, stellaris_enet_readfn,
                                        stellaris_enet_writefn, s);
index e6a538a..d3c1e19 100644 (file)
@@ -35,6 +35,7 @@
 #include "pc.h"
 #include "isa.h"
 #include "fw_cfg.h"
+#include "escc.h"
 
 //#define DEBUG_IRQ
 
@@ -88,6 +89,8 @@
 #define MAX_CPUS 16
 #define MAX_PILS 16
 
+#define ESCC_CLOCK 4915200
+
 struct sun4m_hwdef {
     target_phys_addr_t iommu_base, slavio_base;
     target_phys_addr_t intctl_base, counter_base, nvram_base, ms_kb_base;
@@ -533,16 +536,7 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, ram_addr_t RAM_size,
     tcx_init(ds, hwdef->tcx_base, phys_ram_base + tcx_offset, tcx_offset,
              hwdef->vram_size, graphic_width, graphic_height, graphic_depth);
 
-    if (nd_table[0].model == NULL
-        || strcmp(nd_table[0].model, "lance") == 0) {
-        lance_init(&nd_table[0], hwdef->le_base, ledma, *ledma_irq, le_reset);
-    } else if (strcmp(nd_table[0].model, "?") == 0) {
-        fprintf(stderr, "qemu: Supported NICs: lance\n");
-        exit (1);
-    } else {
-        fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model);
-        exit (1);
-    }
+    lance_init(&nd_table[0], hwdef->le_base, ledma, *ledma_irq, le_reset);
 
     nvram = m48t59_init(slavio_irq[0], hwdef->nvram_base, 0,
                         hwdef->nvram_size, 8);
@@ -551,11 +545,11 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, ram_addr_t RAM_size,
                           slavio_cpu_irq, smp_cpus);
 
     slavio_serial_ms_kbd_init(hwdef->ms_kb_base, slavio_irq[hwdef->ms_kb_irq],
-                              nographic);
+                              nographic, ESCC_CLOCK, 1);
     // Slavio TTYA (base+4, Linux ttyS0) is the first Qemu serial device
     // Slavio TTYB (base+0, Linux ttyS1) is the second Qemu serial device
-    slavio_serial_init(hwdef->serial_base, slavio_irq[hwdef->ser_irq],
-                       serial_hds[1], serial_hds[0]);
+    escc_init(hwdef->serial_base, slavio_irq[hwdef->ser_irq], slavio_irq[hwdef->ser_irq],
+              serial_hds[0], serial_hds[1], ESCC_CLOCK, 1);
 
     cpu_halt = qemu_allocate_irqs(cpu_halt_signal, NULL, 1);
     slavio_misc = slavio_misc_init(hwdef->slavio_base, hwdef->apc_base,
@@ -1325,16 +1319,7 @@ static void sun4d_hw_init(const struct sun4d_hwdef *hwdef, ram_addr_t RAM_size,
     tcx_init(ds, hwdef->tcx_base, phys_ram_base + tcx_offset, tcx_offset,
              hwdef->vram_size, graphic_width, graphic_height, graphic_depth);
 
-    if (nd_table[0].model == NULL
-        || strcmp(nd_table[0].model, "lance") == 0) {
-        lance_init(&nd_table[0], hwdef->le_base, ledma, *ledma_irq, le_reset);
-    } else if (strcmp(nd_table[0].model, "?") == 0) {
-        fprintf(stderr, "qemu: Supported NICs: lance\n");
-        exit (1);
-    } else {
-        fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model);
-        exit (1);
-    }
+    lance_init(&nd_table[0], hwdef->le_base, ledma, *ledma_irq, le_reset);
 
     nvram = m48t59_init(sbi_irq[0], hwdef->nvram_base, 0,
                         hwdef->nvram_size, 8);
@@ -1343,11 +1328,11 @@ static void sun4d_hw_init(const struct sun4d_hwdef *hwdef, ram_addr_t RAM_size,
                           sbi_cpu_irq, smp_cpus);
 
     slavio_serial_ms_kbd_init(hwdef->ms_kb_base, sbi_irq[hwdef->ms_kb_irq],
-                              nographic);
+                              nographic, ESCC_CLOCK, 1);
     // Slavio TTYA (base+4, Linux ttyS0) is the first Qemu serial device
     // Slavio TTYB (base+0, Linux ttyS1) is the second Qemu serial device
-    slavio_serial_init(hwdef->serial_base, sbi_irq[hwdef->ser_irq],
-                       serial_hds[1], serial_hds[0]);
+    escc_init(hwdef->serial_base, sbi_irq[hwdef->ser_irq], sbi_irq[hwdef->ser_irq],
+              serial_hds[0], serial_hds[1], ESCC_CLOCK, 1);
 
     if (drive_get_max_bus(IF_SCSI) > 0) {
         fprintf(stderr, "qemu: too many SCSI bus\n");
@@ -1540,26 +1525,18 @@ static void sun4c_hw_init(const struct sun4c_hwdef *hwdef, ram_addr_t RAM_size,
     tcx_init(ds, hwdef->tcx_base, phys_ram_base + tcx_offset, tcx_offset,
              hwdef->vram_size, graphic_width, graphic_height, graphic_depth);
 
-    if (nd_table[0].model == NULL
-        || strcmp(nd_table[0].model, "lance") == 0) {
-        lance_init(&nd_table[0], hwdef->le_base, ledma, *ledma_irq, le_reset);
-    } else if (strcmp(nd_table[0].model, "?") == 0) {
-        fprintf(stderr, "qemu: Supported NICs: lance\n");
-        exit (1);
-    } else {
-        fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model);
-        exit (1);
-    }
+    lance_init(&nd_table[0], hwdef->le_base, ledma, *ledma_irq, le_reset);
 
     nvram = m48t59_init(slavio_irq[0], hwdef->nvram_base, 0,
                         hwdef->nvram_size, 2);
 
     slavio_serial_ms_kbd_init(hwdef->ms_kb_base, slavio_irq[hwdef->ms_kb_irq],
-                              nographic);
+                              nographic, ESCC_CLOCK, 1);
     // Slavio TTYA (base+4, Linux ttyS0) is the first Qemu serial device
     // Slavio TTYB (base+0, Linux ttyS1) is the second Qemu serial device
-    slavio_serial_init(hwdef->serial_base, slavio_irq[hwdef->ser_irq],
-                       serial_hds[1], serial_hds[0]);
+    escc_init(hwdef->serial_base, slavio_irq[hwdef->ser_irq],
+              slavio_irq[hwdef->ser_irq], serial_hds[0], serial_hds[1],
+              ESCC_CLOCK, 1);
 
     slavio_misc = slavio_misc_init(0, 0, hwdef->aux1_base, 0,
                                    slavio_irq[hwdef->me_irq], NULL, &fdc_tc);
index f6d822e..c9601ed 100644 (file)
@@ -48,12 +48,6 @@ void sun4c_irq_info(void *opaque);
 void slavio_timer_init_all(target_phys_addr_t base, qemu_irq master_irq,
                            qemu_irq *cpu_irqs, unsigned int num_cpus);
 
-/* slavio_serial.c */
-SerialState *slavio_serial_init(target_phys_addr_t base, qemu_irq irq,
-                                CharDriverState *chr1, CharDriverState *chr2);
-void slavio_serial_ms_kbd_init(target_phys_addr_t base, qemu_irq irq,
-                               int disabled);
-
 /* slavio_misc.c */
 void *slavio_misc_init(target_phys_addr_t base, target_phys_addr_t power_base,
                        target_phys_addr_t aux1_base,
index b3ecc1e..91e7538 100644 (file)
@@ -344,6 +344,48 @@ static const int parallel_irq[MAX_PARALLEL_PORTS] = { 7, 7, 7 };
 
 static fdctrl_t *floppy_controller;
 
+static void ebus_mmio_mapfunc(PCIDevice *pci_dev, int region_num,
+                              uint32_t addr, uint32_t size, int type)
+{
+    DPRINTF("Mapping region %d registers at %08x\n", region_num, addr);
+    switch (region_num) {
+    case 0:
+        isa_mmio_init(addr, 0x1000000);
+        break;
+    case 1:
+        isa_mmio_init(addr, 0x800000);
+        break;
+    }
+}
+
+/* EBUS (Eight bit bus) bridge */
+static void
+pci_ebus_init(PCIBus *bus, int devfn)
+{
+    PCIDevice *s;
+
+    s = pci_register_device(bus, "EBUS", sizeof(*s), devfn, NULL, NULL);
+    s->config[0x00] = 0x8e; // vendor_id : Sun
+    s->config[0x01] = 0x10;
+    s->config[0x02] = 0x00; // device_id
+    s->config[0x03] = 0x10;
+    s->config[0x04] = 0x06; // command = bus master, pci mem
+    s->config[0x05] = 0x00;
+    s->config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error
+    s->config[0x07] = 0x03; // status = medium devsel
+    s->config[0x08] = 0x01; // revision
+    s->config[0x09] = 0x00; // programming i/f
+    s->config[0x0A] = 0x80; // class_sub = misc bridge
+    s->config[0x0B] = 0x06; // class_base = PCI_bridge
+    s->config[0x0D] = 0x0a; // latency_timer
+    s->config[0x0E] = 0x00; // header_type
+
+    pci_register_io_region(s, 0, 0x1000000, PCI_ADDRESS_SPACE_MEM,
+                           ebus_mmio_mapfunc);
+    pci_register_io_region(s, 1, 0x800000,  PCI_ADDRESS_SPACE_MEM,
+                           ebus_mmio_mapfunc);
+}
+
 static void sun4uv_init(ram_addr_t RAM_size, int vga_ram_size,
                         const char *boot_devices, DisplayState *ds,
                         const char *kernel_filename, const char *kernel_cmdline,
@@ -357,7 +399,7 @@ static void sun4uv_init(ram_addr_t RAM_size, int vga_ram_size,
     unsigned int i;
     ram_addr_t ram_offset, prom_offset, vga_ram_offset;
     long initrd_size, kernel_size;
-    PCIBus *pci_bus;
+    PCIBus *pci_bus, *pci_bus2, *pci_bus3;
     QEMUBH *bh;
     qemu_irq *irq;
     int drive_index;
@@ -462,11 +504,16 @@ static void sun4uv_init(ram_addr_t RAM_size, int vga_ram_size,
             }
         }
     }
-    pci_bus = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, NULL);
+    pci_bus = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, NULL, &pci_bus2,
+                           &pci_bus3);
     isa_mem_base = VGA_BASE;
     vga_ram_offset = qemu_ram_alloc(vga_ram_size);
-    pci_cirrus_vga_init(pci_bus, ds, phys_ram_base + vga_ram_offset,
-                        vga_ram_offset, vga_ram_size);
+    pci_vga_init(pci_bus, ds, phys_ram_base + vga_ram_offset,
+                 vga_ram_offset, vga_ram_size,
+                 0, 0);
+
+    // XXX Should be pci_bus3
+    pci_ebus_init(pci_bus, -1);
 
     i = 0;
     if (hwdef->console_serial_base) {
@@ -488,11 +535,8 @@ static void sun4uv_init(ram_addr_t RAM_size, int vga_ram_size,
         }
     }
 
-    for(i = 0; i < nb_nics; i++) {
-        if (!nd_table[i].model)
-            nd_table[i].model = "ne2k_pci";
-        pci_nic_init(pci_bus, &nd_table[i], -1);
-    }
+    for(i = 0; i < nb_nics; i++)
+        pci_nic_init(pci_bus, &nd_table[i], -1, "ne2k_pci");
 
     irq = qemu_allocate_irqs(cpu_set_irq, env, MAX_PILS);
     if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
index e5d02f2..267aa42 100644 (file)
@@ -194,12 +194,12 @@ static void versatile_init(ram_addr_t ram_size, int vga_ram_size,
        so many of the qemu PCI devices are not useable.  */
     for(n = 0; n < nb_nics; n++) {
         nd = &nd_table[n];
-        if (!nd->model)
-            nd->model = done_smc ? "rtl8139" : "smc91c111";
-        if (strcmp(nd->model, "smc91c111") == 0) {
+
+        if ((!nd->model && !done_smc) || strcmp(nd->model, "smc91c111") == 0) {
             smc91c111_init(nd, 0x10010000, sic[25]);
+            done_smc = 1;
         } else {
-            pci_nic_init(pci_bus, nd, -1);
+            pci_nic_init(pci_bus, nd, -1, "rtl8139");
         }
     }
     if (usb_enabled) {
index de1f7ce..54c0030 100644 (file)
@@ -20,6 +20,7 @@ typedef struct VirtIONet
 {
     VirtIODevice vdev;
     uint8_t mac[6];
+    uint16_t status;
     VirtQueue *rx_vq;
     VirtQueue *tx_vq;
     VLANClientState *vc;
@@ -42,13 +43,28 @@ static void virtio_net_update_config(VirtIODevice *vdev, uint8_t *config)
     VirtIONet *n = to_virtio_net(vdev);
     struct virtio_net_config netcfg;
 
+    netcfg.status = n->status;
     memcpy(netcfg.mac, n->mac, 6);
     memcpy(config, &netcfg, sizeof(netcfg));
 }
 
+static void virtio_net_set_link_status(VLANClientState *vc)
+{
+    VirtIONet *n = vc->opaque;
+    uint16_t old_status = n->status;
+
+    if (vc->link_down)
+        n->status &= ~VIRTIO_NET_S_LINK_UP;
+    else
+        n->status |= VIRTIO_NET_S_LINK_UP;
+
+    if (n->status != old_status)
+        virtio_notify_config(&n->vdev);
+}
+
 static uint32_t virtio_net_get_features(VirtIODevice *vdev)
 {
-    uint32_t features = (1 << VIRTIO_NET_F_MAC);
+    uint32_t features = (1 << VIRTIO_NET_F_MAC) | (1 << VIRTIO_NET_F_STATUS);
 
     return features;
 }
@@ -299,7 +315,7 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-PCIDevice *virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn)
+void virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn)
 {
     VirtIONet *n;
     static int virtio_net_id;
@@ -307,9 +323,10 @@ PCIDevice *virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn)
     n = (VirtIONet *)virtio_init_pci(bus, "virtio-net", 6900, 0x1000,
                                      0, VIRTIO_ID_NET,
                                      0x02, 0x00, 0x00,
-                                     6, sizeof(VirtIONet));
+                                     sizeof(struct virtio_net_config),
+                                     sizeof(VirtIONet));
     if (!n)
-        return NULL;
+        return;
 
     n->vdev.get_config = virtio_net_update_config;
     n->vdev.get_features = virtio_net_get_features;
@@ -317,8 +334,10 @@ PCIDevice *virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn)
     n->rx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_rx);
     n->tx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_tx);
     memcpy(n->mac, nd->macaddr, 6);
+    n->status = VIRTIO_NET_S_LINK_UP;
     n->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
                                  virtio_net_receive, virtio_net_can_receive, n);
+    n->vc->link_status_changed = virtio_net_set_link_status;
 
     qemu_format_nic_info_str(n->vc, n->mac);
 
@@ -328,6 +347,4 @@ PCIDevice *virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn)
 
     register_savevm("virtio-net", virtio_net_id++, 2,
                     virtio_net_save, virtio_net_load, n);
-
-    return (PCIDevice *)n;
 }
index 0d9f71b..148ec47 100644 (file)
 #define VIRTIO_NET_F_HOST_ECN   13      /* Host can handle TSO[6] w/ ECN in. */
 #define VIRTIO_NET_F_HOST_UFO   14      /* Host can handle UFO in. */
 #define VIRTIO_NET_F_MRG_RXBUF  15      /* Host can merge receive buffers. */
+#define VIRTIO_NET_F_STATUS     16      /* virtio_net_config.status available */
+
+#define VIRTIO_NET_S_LINK_UP    1       /* Link is up */
 
 #define TX_TIMER_INTERVAL 150000 /* 150 us */
 
 /* Maximum packet size we can receive from tap device: header + 64k */
 #define VIRTIO_NET_MAX_BUFSIZE (sizeof(struct virtio_net_hdr) + (64 << 10))
 
-/* The config defining mac address (6 bytes) */
 struct virtio_net_config
 {
+    /* The config defining mac address (6 bytes) */
     uint8_t mac[6];
+    /* See VIRTIO_NET_F_STATUS and VIRTIO_NET_S_* above */
+    uint16_t status;
 } __attribute__((packed));
 
 /* This is the first element of the scatter-gather list.  If you don't
@@ -75,6 +80,6 @@ struct virtio_net_hdr_mrg_rxbuf
     uint16_t num_buffers;   /* Number of merged rx buffers */
 };
 
-PCIDevice *virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn);
+void virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn);
 
 #endif
index 745c335..7ff9890 100644 (file)
--- a/monitor.c
+++ b/monitor.c
@@ -1516,6 +1516,7 @@ static const term_cmd_t term_cmds[] = {
       "value", "set maximum speed (in bytes) for migrations" },
     { "balloon", "i", do_balloon,
       "target", "request VM to change it's memory allocation (in MB)" },
+    { "set_link", "ss", do_set_link, "name [up|down]" },
     { NULL, NULL, },
 };
 
diff --git a/net.c b/net.c
index 15f9153..86ee7d5 100644 (file)
--- a/net.c
+++ b/net.c
@@ -299,7 +299,8 @@ static int parse_unix_path(struct sockaddr_un *uaddr, const char *str)
 void qemu_format_nic_info_str(VLANClientState *vc, uint8_t macaddr[6])
 {
     snprintf(vc->info_str, sizeof(vc->info_str),
-             "macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
+             "model=%s,macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
+             vc->model,
              macaddr[0], macaddr[1], macaddr[2],
              macaddr[3], macaddr[4], macaddr[5]);
 }
@@ -386,12 +387,15 @@ void qemu_send_packet(VLANClientState *vc1, const uint8_t *buf, int size)
     VLANState *vlan = vc1->vlan;
     VLANClientState *vc;
 
+    if (vc1->link_down)
+        return;
+
 #ifdef DEBUG_NET
     printf("vlan %d send:\n", vlan->id);
     hex_dump(stdout, buf, size);
 #endif
     for(vc = vlan->first_client; vc != NULL; vc = vc->next) {
-        if (vc != vc1) {
+        if (vc != vc1 && !vc->link_down) {
             vc->fd_read(vc->opaque, buf, size);
         }
     }
@@ -446,6 +450,8 @@ ssize_t qemu_sendv_packet(VLANClientState *vc1, const struct iovec *iov,
 /* slirp network adapter */
 
 static int slirp_inited;
+static int slirp_restrict;
+static char *slirp_ip;
 static VLANClientState *slirp_vc;
 
 int slirp_can_output(void)
@@ -482,7 +488,7 @@ static int net_slirp_init(VLANState *vlan, const char *model, const char *name)
 {
     if (!slirp_inited) {
         slirp_inited = 1;
-        slirp_init();
+        slirp_init(slirp_restrict, slirp_ip);
     }
     slirp_vc = qemu_new_vlan_client(vlan, model, name,
                                     slirp_receive, NULL, NULL);
@@ -500,7 +506,7 @@ void net_slirp_redir(const char *redir_str)
 
     if (!slirp_inited) {
         slirp_inited = 1;
-        slirp_init();
+        slirp_init(slirp_restrict, slirp_ip);
     }
 
     p = redir_str;
@@ -586,7 +592,7 @@ void net_slirp_smb(const char *exported_dir)
 
     if (!slirp_inited) {
         slirp_inited = 1;
-        slirp_init();
+        slirp_init(slirp_restrict, slirp_ip);
     }
 
     /* XXX: better tmp dir construction */
@@ -646,6 +652,7 @@ typedef struct TAPState {
     VLANClientState *vc;
     int fd;
     char down_script[1024];
+    char down_script_arg[128];
 } TAPState;
 
 #ifdef HAVE_IOVEC
@@ -972,8 +979,10 @@ static int net_tap_init(VLANState *vlan, const char *model,
     snprintf(s->vc->info_str, sizeof(s->vc->info_str),
              "ifname=%s,script=%s,downscript=%s",
              ifname, setup_script, down_script);
-    if (down_script && strcmp(down_script, "no"))
+    if (down_script && strcmp(down_script, "no")) {
         snprintf(s->down_script, sizeof(s->down_script), "%s", down_script);
+        snprintf(s->down_script_arg, sizeof(s->down_script_arg), "%s", ifname);
+    }
     return 0;
 }
 
@@ -1491,6 +1500,40 @@ VLANState *qemu_find_vlan(int id)
     return vlan;
 }
 
+void qemu_check_nic_model(NICInfo *nd, const char *model)
+{
+    const char *models[2];
+
+    models[0] = model;
+    models[1] = NULL;
+
+    qemu_check_nic_model_list(nd, models, model);
+}
+
+void qemu_check_nic_model_list(NICInfo *nd, const char * const *models,
+                               const char *default_model)
+{
+    int i, exit_status = 0;
+
+    if (!nd->model)
+        nd->model = strdup(default_model);
+
+    if (strcmp(nd->model, "?") != 0) {
+        for (i = 0 ; models[i]; i++)
+            if (strcmp(nd->model, models[i]) == 0)
+                return;
+
+        fprintf(stderr, "qemu: Unsupported NIC model: %s\n", nd->model);
+        exit_status = 1;
+    }
+
+    fprintf(stderr, "qemu: Supported NIC models: ");
+    for (i = 0 ; models[i]; i++)
+        fprintf(stderr, "%s%c", models[i], models[i+1] ? ',' : '\n');
+
+    exit(exit_status);
+}
+
 int net_client_init(const char *device, const char *p)
 {
     char buf[1024];
@@ -1553,6 +1596,12 @@ int net_client_init(const char *device, const char *p)
         if (get_param_value(buf, sizeof(buf), "hostname", p)) {
             pstrcpy(slirp_hostname, sizeof(slirp_hostname), buf);
         }
+        if (get_param_value(buf, sizeof(buf), "restrict", p)) {
+            slirp_restrict = (buf[0] == 'y') ? 1 : 0;
+        }
+        if (get_param_value(buf, sizeof(buf), "ip", p)) {
+            slirp_ip = strdup(buf);
+        }
         vlan->nb_host_devs++;
         ret = net_slirp_init(vlan, device, name);
     } else
@@ -1683,6 +1732,36 @@ void do_info_network(void)
     }
 }
 
+int do_set_link(const char *name, const char *up_or_down)
+{
+    VLANState *vlan;
+    VLANClientState *vc = NULL;
+
+    for (vlan = first_vlan; vlan != NULL; vlan = vlan->next)
+        for (vc = vlan->first_client; vc != NULL; vc = vc->next)
+            if (strcmp(vc->name, name) == 0)
+                goto done;
+done:
+
+    if (!vc) {
+        term_printf("could not find network device '%s'", name);
+        return 0;
+    }
+
+    if (strcmp(up_or_down, "up") == 0)
+        vc->link_down = 0;
+    else if (strcmp(up_or_down, "down") == 0)
+        vc->link_down = 1;
+    else
+        term_printf("invalid link status '%s'; only 'up' or 'down' valid\n",
+                    up_or_down);
+
+    if (vc->link_status_changed)
+        vc->link_status_changed(vc);
+
+    return 1;
+}
+
 void net_cleanup(void)
 {
     VLANState *vlan;
@@ -1694,13 +1773,10 @@ void net_cleanup(void)
 
         for(vc = vlan->first_client; vc != NULL; vc = vc->next) {
             if (vc->fd_read == tap_receive) {
-                char ifname[64];
                 TAPState *s = vc->opaque;
 
-                if (strcmp(vc->model, "tap") == 0 &&
-                    sscanf(vc->info_str, "ifname=%63s ", ifname) == 1 &&
-                    s->down_script[0])
-                    launch_script(s->down_script, ifname, s->fd);
+                if (s->down_script[0])
+                    launch_script(s->down_script, s->down_script_arg, s->fd);
             }
 #if defined(CONFIG_VDE)
             if (vc->fd_read == vde_from_qemu) {
diff --git a/net.h b/net.h
index b89d165..291807a 100644 (file)
--- a/net.h
+++ b/net.h
@@ -9,12 +9,16 @@ typedef ssize_t (IOReadvHandler)(void *, const struct iovec *, int);
 
 typedef struct VLANClientState VLANClientState;
 
+typedef void (LinkStatusChanged)(VLANClientState *);
+
 struct VLANClientState {
     IOReadHandler *fd_read;
     IOReadvHandler *fd_readv;
     /* Packets may still be sent if this returns zero.  It's used to
        rate-limit the slirp code.  */
     IOCanRWHandler *fd_can_read;
+    LinkStatusChanged *link_status_changed;
+    int link_down;
     void *opaque;
     struct VLANClientState *next;
     struct VLANState *vlan;
@@ -43,9 +47,13 @@ ssize_t qemu_sendv_packet(VLANClientState *vc, const struct iovec *iov,
                           int iovcnt);
 void qemu_send_packet(VLANClientState *vc, const uint8_t *buf, int size);
 void qemu_format_nic_info_str(VLANClientState *vc, uint8_t macaddr[6]);
+void qemu_check_nic_model(NICInfo *nd, const char *model);
+void qemu_check_nic_model_list(NICInfo *nd, const char * const *models,
+                               const char *default_model);
 void qemu_handler_true(void *opaque);
 
 void do_info_network(void);
+int do_set_link(const char *name, const char *up_or_down);
 
 /* NIC info */
 
index 665bd7d..8313638 100644 (file)
@@ -41,7 +41,8 @@
 - OpenBIOS (http://www.openbios.org/) is a free (GPL v2) portable
   firmware implementation. The goal is to implement a 100% IEEE
   1275-1994 (referred to as Open Firmware) compliant firmware.
-  The included Sparc32 and Sparc64 images are built from SVN revision 237.
+  The included Sparc32 and Sparc64 images are built from SVN revision 395.
+  The included PowerPC image is built from SVN revision 406.
 
 - The PXE roms come from Rom-o-Matic etherboot 5.4.2.
   pcnet32:pcnet32 -- [0x1022,0x2000]
diff --git a/pc-bios/bios-pq/0002_e820-high-mem.patch b/pc-bios/bios-pq/0002_e820-high-mem.patch
deleted file mode 100644 (file)
index 2886e85..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-From: Izik Eidus <izike@qumranet.com>
-
-add support to memory above the pci hole
-    
-the new memory region is mapped after address 0x100000000,
-the bios take the size of the memory after the 0x100000000 from
-three new cmos bytes.
-
-diff --git a/bios/rombios.c b/bios/rombios.c
-index 1be0816..b70f249 100644
---- a/bios/rombios.c
-+++ b/bios/rombios.c
-@@ -4442,22 +4442,25 @@ BX_DEBUG_INT15("case default:\n");
- #endif // BX_USE_PS2_MOUSE
--void set_e820_range(ES, DI, start, end, type)
-+void set_e820_range(ES, DI, start, end, extra_start, extra_end, type)
-      Bit16u ES;
-      Bit16u DI;
-      Bit32u start;
-      Bit32u end;
-+     Bit8u extra_start;
-+     Bit8u extra_end;
-      Bit16u type;
- {
-     write_word(ES, DI, start);
-     write_word(ES, DI+2, start >> 16);
--    write_word(ES, DI+4, 0x00);
-+    write_word(ES, DI+4, extra_start);
-     write_word(ES, DI+6, 0x00);
-     end -= start;
-+    extra_end -= extra_start;
-     write_word(ES, DI+8, end);
-     write_word(ES, DI+10, end >> 16);
--    write_word(ES, DI+12, 0x0000);
-+    write_word(ES, DI+12, extra_end);
-     write_word(ES, DI+14, 0x0000);
-     write_word(ES, DI+16, type);
-@@ -4470,7 +4473,9 @@ int15_function32(regs, ES, DS, FLAGS)
-   Bit16u ES, DS, FLAGS;
- {
-   Bit32u  extended_memory_size=0; // 64bits long
-+  Bit32u  extra_lowbits_memory_size=0;
-   Bit16u  CX,DX;
-+  Bit8u   extra_highbits_memory_size=0;
- BX_DEBUG_INT15("int15 AX=%04x\n",regs.u.r16.ax);
-@@ -4544,11 +4549,18 @@ ASM_END
-                     extended_memory_size += (1L * 1024 * 1024);
-                 }
-+                extra_lowbits_memory_size = inb_cmos(0x5c);
-+                extra_lowbits_memory_size <<= 8;
-+                extra_lowbits_memory_size |= inb_cmos(0x5b);
-+                extra_lowbits_memory_size *= 64;
-+                extra_lowbits_memory_size *= 1024;
-+                extra_highbits_memory_size = inb_cmos(0x5d);
-+
-                 switch(regs.u.r16.bx)
-                 {
-                     case 0:
-                         set_e820_range(ES, regs.u.r16.di,
--                                       0x0000000L, 0x0009f000L, 1);
-+                                       0x0000000L, 0x0009f000L, 0, 0, 1);
-                         regs.u.r32.ebx = 1;
-                         regs.u.r32.eax = 0x534D4150;
-                         regs.u.r32.ecx = 0x14;
-@@ -4557,7 +4569,7 @@ ASM_END
-                         break;
-                     case 1:
-                         set_e820_range(ES, regs.u.r16.di,
--                                       0x0009f000L, 0x000a0000L, 2);
-+                                       0x0009f000L, 0x000a0000L, 0, 0, 2);
-                         regs.u.r32.ebx = 2;
-                         regs.u.r32.eax = 0x534D4150;
-                         regs.u.r32.ecx = 0x14;
-@@ -4566,7 +4578,7 @@ ASM_END
-                         break;
-                     case 2:
-                         set_e820_range(ES, regs.u.r16.di,
--                                       0x000e8000L, 0x00100000L, 2);
-+                                       0x000e8000L, 0x00100000L, 0, 0, 2);
-                         regs.u.r32.ebx = 3;
-                         regs.u.r32.eax = 0x534D4150;
-                         regs.u.r32.ecx = 0x14;
-@@ -4577,7 +4589,7 @@ ASM_END
- #if BX_ROMBIOS32
-                         set_e820_range(ES, regs.u.r16.di,
-                                        0x00100000L,
--                                       extended_memory_size - ACPI_DATA_SIZE, 1);
-+                                       extended_memory_size - ACPI_DATA_SIZE ,0, 0, 1);
-                         regs.u.r32.ebx = 4;
- #else
-                         set_e820_range(ES, regs.u.r16.di,
-@@ -4593,7 +4605,7 @@ ASM_END
-                     case 4:
-                         set_e820_range(ES, regs.u.r16.di,
-                                        extended_memory_size - ACPI_DATA_SIZE,
--                                       extended_memory_size, 3); // ACPI RAM
-+                                       extended_memory_size ,0, 0, 3); // ACPI RAM
-                         regs.u.r32.ebx = 5;
-                         regs.u.r32.eax = 0x534D4150;
-                         regs.u.r32.ecx = 0x14;
-@@ -4603,7 +4615,20 @@ ASM_END
-                     case 5:
-                         /* 256KB BIOS area at the end of 4 GB */
-                         set_e820_range(ES, regs.u.r16.di,
--                                       0xfffc0000L, 0x00000000L, 2);
-+                                       0xfffc0000L, 0x00000000L ,0, 0, 2);
-+                        if (extra_highbits_memory_size || extra_lowbits_memory_size)
-+                            regs.u.r32.ebx = 6;
-+                        else
-+                            regs.u.r32.ebx = 0;
-+                        regs.u.r32.eax = 0x534D4150;
-+                        regs.u.r32.ecx = 0x14;
-+                        CLEAR_CF();
-+                        return;
-+                    case 6:
-+                        /* Maping of memory above 4 GB */
-+                        set_e820_range(ES, regs.u.r16.di, 0x00000000L,
-+                        extra_lowbits_memory_size, 1, extra_highbits_memory_size
-+                                       + 1, 1);
-                         regs.u.r32.ebx = 0;
-                         regs.u.r32.eax = 0x534D4150;
-                         regs.u.r32.ecx = 0x14;
diff --git a/pc-bios/bios-pq/0003_smp-startup-poll.patch b/pc-bios/bios-pq/0003_smp-startup-poll.patch
deleted file mode 100644 (file)
index cd1a3ff..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-From: Avi Kivity <avi@qumranet.com>
-
-instead of timing out, wait until all cpus are up
-
-diff --git a/bios/rombios32.c b/bios/rombios32.c
-index ef98a41..05ba40d 100644
---- a/bios/rombios32.c
-+++ b/bios/rombios32.c
-@@ -512,7 +512,12 @@ void smp_probe(void)
-         sipi_vector = AP_BOOT_ADDR >> 12;
-         writel(APIC_BASE + APIC_ICR_LOW, 0x000C4600 | sipi_vector);
-+#ifndef BX_QEMU
-         delay_ms(10);
-+#else
-+        while (cmos_readb(0x5f) + 1 != readw(&smp_cpus))
-+            ;
-+#endif
-     }
-     BX_INFO("Found %d cpu(s)\n", readw(&smp_cpus));
- }
diff --git a/pc-bios/bios-pq/0005_hpet.patch b/pc-bios/bios-pq/0005_hpet.patch
deleted file mode 100644 (file)
index 9347cb5..0000000
+++ /dev/null
@@ -1,190 +0,0 @@
-BOCHS BIOS changes to support HPET in QEMU.
-
-Signed-off-by Beth Kon <eak@us.ibm.com>
-
-Index: bochs-2.3.7/bios/acpi-dsdt.dsl
-===================================================================
---- bochs-2.3.7.orig/bios/acpi-dsdt.dsl        2008-10-15 12:39:14.000000000 -0500
-+++ bochs-2.3.7/bios/acpi-dsdt.dsl     2008-10-28 07:58:40.000000000 -0500
-@@ -159,6 +159,26 @@
-                 Return (MEMP)
-             }
-         }
-+#ifdef BX_QEMU
-+        Device(HPET) {
-+            Name(_HID,  EISAID("PNP0103"))
-+            Name(_UID, 0)
-+            Method (_STA, 0, NotSerialized) {
-+                    Return(0x0F)
-+            }
-+            Name(_CRS, ResourceTemplate() {
-+                DWordMemory(
-+                    ResourceConsumer, PosDecode, MinFixed, MaxFixed,
-+                    NonCacheable, ReadWrite,
-+                    0x00000000,
-+                    0xFED00000,
-+                    0xFED003FF,
-+                    0x00000000,
-+                    0x00000400 /* 1K memory: FED00000 - FED003FF */
-+                )
-+            })
-+        }
-+#endif
-     }
-     Scope(\_SB.PCI0) {
-Index: bochs-2.3.7/bios/rombios32.c
-===================================================================
---- bochs-2.3.7.orig/bios/rombios32.c  2008-10-15 12:39:36.000000000 -0500
-+++ bochs-2.3.7/bios/rombios32.c       2008-11-12 14:41:41.000000000 -0600
-@@ -1087,7 +1087,11 @@
- struct rsdt_descriptor_rev1
- {
-       ACPI_TABLE_HEADER_DEF                           /* ACPI common table header */
-+#ifdef BX_QEMU
-+      uint32_t                             table_offset_entry [4]; /* Array of pointers to other */
-+#else
-       uint32_t                             table_offset_entry [3]; /* Array of pointers to other */
-+#endif
-                        /* ACPI tables */
- };
-@@ -1227,6 +1231,32 @@
- #endif
- };
-+#ifdef BX_QEMU
-+/*
-+ *  * ACPI 2.0 Generic Address Space definition.
-+ *   */
-+struct acpi_20_generic_address {
-+    uint8_t  address_space_id;
-+    uint8_t  register_bit_width;
-+    uint8_t  register_bit_offset;
-+    uint8_t  reserved;
-+    uint64_t address;
-+};
-+
-+/*
-+ *  * HPET Description Table
-+ *   */
-+struct acpi_20_hpet {
-+    ACPI_TABLE_HEADER_DEF                           /* ACPI common table header */
-+    uint32_t           timer_block_id;
-+    struct acpi_20_generic_address addr;
-+    uint8_t            hpet_number;
-+    uint16_t           min_tick;
-+    uint8_t            page_protect;
-+};
-+#define ACPI_HPET_ADDRESS 0xFED00000UL
-+#endif
-+
- struct madt_io_apic
- {
-       APIC_HEADER_DEF
-@@ -1237,6 +1267,17 @@
-                         * lines start */
- };
-+#ifdef BX_QEMU
-+struct madt_int_override
-+{
-+      APIC_HEADER_DEF
-+      uint8_t                bus;     /* Identifies ISA Bus */
-+      uint8_t                source;  /* Bus-relative interrupt source */
-+      uint32_t               gsi;     /* GSI that source will signal */
-+      uint16_t               flags;   /* MPS INTI flags */
-+};
-+#endif
-+
- #include "acpi-dsdt.hex"
- static inline uint16_t cpu_to_le16(uint16_t x)
-@@ -1342,6 +1383,10 @@
-     struct facs_descriptor_rev1 *facs;
-     struct multiple_apic_table *madt;
-     uint8_t *dsdt, *ssdt;
-+#ifdef BX_QEMU
-+    struct acpi_20_hpet *hpet;
-+    uint32_t hpet_addr;
-+#endif
-     uint32_t base_addr, rsdt_addr, fadt_addr, addr, facs_addr, dsdt_addr, ssdt_addr;
-     uint32_t acpi_tables_size, madt_addr, madt_size;
-     int i;
-@@ -1384,10 +1429,21 @@
-     madt_addr = addr;
-     madt_size = sizeof(*madt) +
-         sizeof(struct madt_processor_apic) * smp_cpus +
-+#ifdef BX_QEMU
-+        sizeof(struct madt_io_apic) + sizeof(struct madt_int_override);
-+#else
-         sizeof(struct madt_io_apic);
-+#endif
-     madt = (void *)(addr);
-     addr += madt_size;
-+#ifdef BX_QEMU
-+    addr = (addr + 7) & ~7;
-+    hpet_addr = addr;
-+    hpet = (void *)(addr);
-+    addr += sizeof(*hpet);
-+#endif
-+
-     acpi_tables_size = addr - base_addr;
-     BX_INFO("ACPI tables: RSDP addr=0x%08lx ACPI DATA addr=0x%08lx size=0x%x\n",
-@@ -1410,6 +1466,9 @@
-     rsdt->table_offset_entry[0] = cpu_to_le32(fadt_addr);
-     rsdt->table_offset_entry[1] = cpu_to_le32(madt_addr);
-     rsdt->table_offset_entry[2] = cpu_to_le32(ssdt_addr);
-+#ifdef BX_QEMU
-+    rsdt->table_offset_entry[3] = cpu_to_le32(hpet_addr);
-+#endif
-     acpi_build_table_header((struct acpi_table_header *)rsdt,
-                             "RSDT", sizeof(*rsdt), 1);
-@@ -1448,6 +1507,9 @@
-     {
-         struct madt_processor_apic *apic;
-         struct madt_io_apic *io_apic;
-+#ifdef BX_QEMU
-+        struct madt_int_override *int_override;
-+#endif
-         memset(madt, 0, madt_size);
-         madt->local_apic_address = cpu_to_le32(0xfee00000);
-@@ -1467,10 +1529,34 @@
-         io_apic->io_apic_id = smp_cpus;
-         io_apic->address = cpu_to_le32(0xfec00000);
-         io_apic->interrupt = cpu_to_le32(0);
-+#ifdef BX_QEMU
-+        io_apic++;
-+
-+        int_override = (void *)io_apic;
-+        int_override->type = APIC_XRUPT_OVERRIDE;
-+        int_override->length = sizeof(*int_override);
-+        int_override->bus = cpu_to_le32(0);
-+        int_override->source = cpu_to_le32(0);
-+        int_override->gsi = cpu_to_le32(2);
-+        int_override->flags = cpu_to_le32(0);
-+#endif
-         acpi_build_table_header((struct acpi_table_header *)madt,
-                                 "APIC", madt_size, 1);
-     }
-+
-+#ifdef BX_QEMU
-+    /* HPET */
-+    memset(hpet, 0, sizeof(*hpet));
-+    /* Note timer_block_id value must be kept in sync with value advertised by
-+     * emulated hpet
-+     */
-+    hpet->timer_block_id = cpu_to_le32(0x8086a201);
-+    hpet->addr.address = cpu_to_le32(ACPI_HPET_ADDRESS);
-+    acpi_build_table_header((struct  acpi_table_header *)hpet,
-+                             "HPET", sizeof(*hpet), 1);
-+#endif
-+
- }
- /* SMBIOS entry point -- must be written to a 16-bit aligned address
index 928a233..1f604ae 100644 (file)
@@ -1 +1 @@
-370a7e0d8419bc05192d766c11b7221e5ffc0f75
+7342176bb0fa9d6cc63b37f6ac239e3f70b74219
index 0e7558c..556c0e4 100644 (file)
@@ -1,4 +1 @@
 0001_bx-qemu.patch
-0002_e820-high-mem.patch
-0003_smp-startup-poll.patch
-0005_hpet.patch
index 5120192..ac444c1 100644 (file)
Binary files a/pc-bios/bios.bin and b/pc-bios/bios.bin differ
diff --git a/pc-bios/openbios-ppc b/pc-bios/openbios-ppc
new file mode 100644 (file)
index 0000000..53cf42b
Binary files /dev/null and b/pc-bios/openbios-ppc differ
dissimilarity index 71%
index 7c5d012..8f4170b 100644 (file)
Binary files a/pc-bios/openbios-sparc32 and b/pc-bios/openbios-sparc32 differ
index 99e0d79..e00c5dd 100644 (file)
Binary files a/pc-bios/openbios-sparc64 and b/pc-bios/openbios-sparc64 differ
index 92ec234..c919e3b 100644 (file)
@@ -81,21 +81,16 @@ static void *aio_thread(void *unused)
             if (len == -1 && errno == EINTR)
                 continue;
             else if (len == -1) {
-                pthread_mutex_lock(&lock);
-                aiocb->ret = -errno;
-                pthread_mutex_unlock(&lock);
+                offset = -errno;
                 break;
             } else if (len == 0)
                 break;
 
             offset += len;
-
-            pthread_mutex_lock(&lock);
-            aiocb->ret = offset;
-            pthread_mutex_unlock(&lock);
         }
 
         pthread_mutex_lock(&lock);
+        aiocb->ret = offset;
         idle_threads++;
         pthread_mutex_unlock(&lock);
 
index aea4210..5a12dc9 100644 (file)
@@ -72,7 +72,7 @@ For system emulation, the following hardware targets are supported:
 @item PC (x86 or x86_64 processor)
 @item ISA PC (old style PC without PCI bus)
 @item PREP (PowerPC processor)
-@item G3 BW PowerMac (PowerPC processor)
+@item G3 Beige PowerMac (PowerPC processor)
 @item Mac99 PowerMac (PowerPC processor, in progress)
 @item Sun4m/Sun4c/Sun4d (32-bit Sparc processor)
 @item Sun4u/Sun4v (64-bit Sparc processor, in progress)
@@ -184,8 +184,8 @@ PCI UHCI USB controller and a virtual USB hub.
 
 SMP is supported with up to 255 CPUs.
 
-Note that adlib, ac97, gus and cs4231a are only available when QEMU
-was configured with --audio-card-list option containing the name(s) of
+Note that adlib, gus and cs4231a are only available when QEMU was
+configured with --audio-card-list option containing the name(s) of
 required card(s).
 
 QEMU uses the PC BIOS from the Bochs project and the Plex86/Bochs LGPL
index ed64b6b..59bd2f1 100644 (file)
@@ -190,7 +190,7 @@ int main(int argc, char **argv)
     char *device = NULL;
     char *socket = NULL;
     char sockpath[128];
-    const char *sopt = "hVbo:p:rsnP:c:dvk:e:t";
+    const char *sopt = "hVb:o:p:rsnP:c:dvk:e:t";
     struct option lopt[] = {
         { "help", 0, 0, 'h' },
         { "version", 0, 0, 'V' },
index 750fae3..bf704ab 100644 (file)
@@ -219,16 +219,18 @@ static void bootp_reply(struct bootp_t *bp)
         *q++ = 0xff;
         *q++ = 0x00;
 
-        *q++ = RFC1533_GATEWAY;
-        *q++ = 4;
-        memcpy(q, &saddr.sin_addr, 4);
-        q += 4;
-
-        *q++ = RFC1533_DNS;
-        *q++ = 4;
-        dns_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_DNS);
-        memcpy(q, &dns_addr, 4);
-        q += 4;
+        if (!slirp_restrict) {
+            *q++ = RFC1533_GATEWAY;
+            *q++ = 4;
+            memcpy(q, &saddr.sin_addr, 4);
+            q += 4;
+
+            *q++ = RFC1533_DNS;
+            *q++ = 4;
+            dns_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_DNS);
+            memcpy(q, &dns_addr, 4);
+            q += 4;
+        }
 
         *q++ = RFC2132_LEASE_TIME;
         *q++ = 4;
index a8cdb0d..3079f90 100644 (file)
@@ -183,35 +183,31 @@ struct    ip_timestamp {
 
 #define        IP_MSS          576             /* default maximum segment size */
 
-#ifdef HAVE_SYS_TYPES32_H  /* Overcome some Solaris 2.x junk */
-#include <sys/types32.h>
-#else
 #if SIZEOF_CHAR_P == 4
-typedef caddr_t caddr32_t;
-#else
-typedef u_int32_t caddr32_t;
-#endif
-#endif
-
-#if SIZEOF_CHAR_P == 4
-typedef struct ipq *ipqp_32;
-typedef struct ipasfrag *ipasfragp_32;
+struct mbuf_ptr {
+       struct mbuf *mptr;
+       uint32_t dummy;
+};
 #else
-typedef caddr32_t ipqp_32;
-typedef caddr32_t ipasfragp_32;
+struct mbuf_ptr {
+       struct mbuf *mptr;
+};
 #endif
+struct qlink {
+       void *next, *prev;
+};
 
 /*
  * Overlay for ip header used by other protocols (tcp, udp).
  */
 struct ipovly {
-       caddr32_t       ih_next, ih_prev;       /* for protocol sequence q's */
+       struct mbuf_ptr ih_mbuf;        /* backpointer to mbuf */
        u_int8_t        ih_x1;                  /* (unused) */
        u_int8_t        ih_pr;                  /* protocol */
        u_int16_t       ih_len;                 /* protocol length */
        struct  in_addr ih_src;         /* source internet address */
        struct  in_addr ih_dst;         /* destination internet address */
-};
+} __attribute__((packed));
 
 /*
  * Ip reassembly queue structure.  Each fragment
@@ -221,44 +217,30 @@ struct ipovly {
  * size 28 bytes
  */
 struct ipq {
-       ipqp_32 next,prev;      /* to other reass headers */
+        struct qlink frag_link;                        /* to ip headers of fragments */
+       struct qlink ip_link;                           /* to other reass headers */
        u_int8_t        ipq_ttl;                /* time for reass q to live */
        u_int8_t        ipq_p;                  /* protocol of this fragment */
        u_int16_t       ipq_id;                 /* sequence id for reassembly */
-       ipasfragp_32 ipq_next,ipq_prev;
-                                       /* to ip headers of fragments */
        struct  in_addr ipq_src,ipq_dst;
 };
 
 /*
  * Ip header, when holding a fragment.
  *
- * Note: ipf_next must be at same offset as ipq_next above
+ * Note: ipf_link must be at same offset as frag_link above
  */
 struct ipasfrag {
-#ifdef WORDS_BIGENDIAN
-       u_int   ip_v:4,
-               ip_hl:4;
-#else
-       u_int   ip_hl:4,
-               ip_v:4;
-#endif
-                                        /* BUG : u_int changed to u_int8_t.
-                                         * sizeof(u_int)==4 on linux 2.0
-                                        */
-        u_int8_t ipf_mff;              /* XXX overlays ip_tos: use low bit
-                                        * to avoid destroying tos (PPPDTRuu);
-                                        * copied from (ip_off&IP_MF) */
-       u_int16_t       ip_len;
-       u_int16_t       ip_id;
-       u_int16_t       ip_off;
-       u_int8_t        ip_ttl;
-       u_int8_t        ip_p;
-       u_int16_t       ip_sum;
-       ipasfragp_32 ipf_next;          /* next fragment */
-       ipasfragp_32 ipf_prev;          /* previous fragment */
+       struct qlink ipf_link;
+       struct ip ipf_ip;
 };
 
+#define ipf_off      ipf_ip.ip_off
+#define ipf_tos      ipf_ip.ip_tos
+#define ipf_len      ipf_ip.ip_len
+#define ipf_next     ipf_link.next
+#define ipf_prev     ipf_link.prev 
+
 /*
  * Structure stored in mbuf in inpcb.ip_options
  * and passed to ip_output when ip options are in use.
index b046840..116ee45 100644 (file)
@@ -43,6 +43,7 @@
  */
 
 #include <slirp.h>
+#include <osdep.h>
 #include "ip_icmp.h"
 
 #ifdef LOG_ENABLED
@@ -51,7 +52,7 @@ struct ipstat ipstat;
 
 struct ipq ipq;
 
-static struct ip *ip_reass(register struct ipasfrag *ip,
+static struct ip *ip_reass(register struct ip *ip,
                            register struct ipq *fp);
 static void ip_freef(struct ipq *fp);
 static void ip_enq(register struct ipasfrag *p,
@@ -65,7 +66,7 @@ static void ip_deq(register struct ipasfrag *p);
 void
 ip_init()
 {
-       ipq.next = ipq.prev = (ipqp_32)&ipq;
+       ipq.ip_link.next = ipq.ip_link.prev = &ipq.ip_link;
        ip_id = tt.tv_sec & 0xffff;
        udp_init();
        tcp_init();
@@ -136,6 +137,27 @@ ip_input(m)
                STAT(ipstat.ips_tooshort++);
                goto bad;
        }
+
+    if (slirp_restrict) {
+        if (memcmp(&ip->ip_dst.s_addr, &special_addr, 3)) {
+            if (ip->ip_dst.s_addr == 0xffffffff && ip->ip_p != IPPROTO_UDP)
+                goto bad;
+        } else {
+            int host = ntohl(ip->ip_dst.s_addr) & 0xff;
+            struct ex_list *ex_ptr;
+
+            if (host == 0xff)
+                goto bad;
+
+            for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next)
+                if (ex_ptr->ex_addr == host)
+                    break;
+
+            if (!ex_ptr)
+                goto bad;
+        }
+    }
+
        /* Should drop packet if mbuf too long? hmmm... */
        if (m->m_len > ip->ip_len)
           m_adj(m, ip->ip_len - m->m_len);
@@ -167,18 +189,20 @@ ip_input(m)
         */
        if (ip->ip_off &~ IP_DF) {
          register struct ipq *fp;
+      struct qlink *l;
                /*
                 * Look for queue of fragments
                 * of this datagram.
                 */
-               for (fp = (struct ipq *) ipq.next; fp != &ipq;
-                    fp = (struct ipq *) fp->next)
-                 if (ip->ip_id == fp->ipq_id &&
-                     ip->ip_src.s_addr == fp->ipq_src.s_addr &&
-                     ip->ip_dst.s_addr == fp->ipq_dst.s_addr &&
-                     ip->ip_p == fp->ipq_p)
+               for (l = ipq.ip_link.next; l != &ipq.ip_link; l = l->next) {
+            fp = container_of(l, struct ipq, ip_link);
+            if (ip->ip_id == fp->ipq_id &&
+                    ip->ip_src.s_addr == fp->ipq_src.s_addr &&
+                    ip->ip_dst.s_addr == fp->ipq_dst.s_addr &&
+                    ip->ip_p == fp->ipq_p)
                    goto found;
-               fp = 0;
+        }
+        fp = NULL;
        found:
 
                /*
@@ -188,9 +212,9 @@ ip_input(m)
                 */
                ip->ip_len -= hlen;
                if (ip->ip_off & IP_MF)
-                 ((struct ipasfrag *)ip)->ipf_mff |= 1;
+                 ip->ip_tos |= 1;
                else
-                 ((struct ipasfrag *)ip)->ipf_mff &= ~1;
+                 ip->ip_tos &= ~1;
 
                ip->ip_off <<= 3;
 
@@ -199,9 +223,9 @@ ip_input(m)
                 * or if this is not the first fragment,
                 * attempt reassembly; if it succeeds, proceed.
                 */
-               if (((struct ipasfrag *)ip)->ipf_mff & 1 || ip->ip_off) {
+               if (ip->ip_tos & 1 || ip->ip_off) {
                        STAT(ipstat.ips_fragments++);
-                       ip = ip_reass((struct ipasfrag *)ip, fp);
+                       ip = ip_reass(ip, fp);
                        if (ip == 0)
                                return;
                        STAT(ipstat.ips_reassembled++);
@@ -237,6 +261,8 @@ bad:
        return;
 }
 
+#define iptofrag(P) ((struct ipasfrag *)(((char*)(P)) - sizeof(struct qlink)))
+#define fragtoip(P) ((struct ip*)(((char*)(P)) + sizeof(struct qlink)))
 /*
  * Take incoming datagram fragment and try to
  * reassemble it into whole datagram.  If a chain for
@@ -244,7 +270,7 @@ bad:
  * is given as fp; otherwise have to make a chain.
  */
 static struct ip *
-ip_reass(register struct ipasfrag *ip, register struct ipq *fp)
+ip_reass(register struct ip *ip, register struct ipq *fp)
 {
        register struct mbuf *m = dtom(ip);
        register struct ipasfrag *q;
@@ -271,13 +297,13 @@ ip_reass(register struct ipasfrag *ip, register struct ipq *fp)
          struct mbuf *t;
          if ((t = m_get()) == NULL) goto dropfrag;
          fp = mtod(t, struct ipq *);
-         insque_32(fp, &ipq);
+         insque(&fp->ip_link, &ipq.ip_link);
          fp->ipq_ttl = IPFRAGTTL;
          fp->ipq_p = ip->ip_p;
          fp->ipq_id = ip->ip_id;
-         fp->ipq_next = fp->ipq_prev = (ipasfragp_32)fp;
-         fp->ipq_src = ((struct ip *)ip)->ip_src;
-         fp->ipq_dst = ((struct ip *)ip)->ip_dst;
+         fp->frag_link.next = fp->frag_link.prev = &fp->frag_link;
+         fp->ipq_src = ip->ip_src;
+         fp->ipq_dst = ip->ip_dst;
          q = (struct ipasfrag *)fp;
          goto insert;
        }
@@ -285,9 +311,9 @@ ip_reass(register struct ipasfrag *ip, register struct ipq *fp)
        /*
         * Find a segment which begins after this one does.
         */
-       for (q = (struct ipasfrag *)fp->ipq_next; q != (struct ipasfrag *)fp;
-           q = (struct ipasfrag *)q->ipf_next)
-               if (q->ip_off > ip->ip_off)
+       for (q = fp->frag_link.next; q != (struct ipasfrag *)&fp->frag_link;
+            q = q->ipf_next)
+               if (q->ipf_off > ip->ip_off)
                        break;
 
        /*
@@ -295,9 +321,9 @@ ip_reass(register struct ipasfrag *ip, register struct ipq *fp)
         * our data already.  If so, drop the data from the incoming
         * segment.  If it provides all of our data, drop us.
         */
-       if (q->ipf_prev != (ipasfragp_32)fp) {
-               i = ((struct ipasfrag *)(q->ipf_prev))->ip_off +
-                 ((struct ipasfrag *)(q->ipf_prev))->ip_len - ip->ip_off;
+       if (q->ipf_prev != &fp->frag_link) {
+        struct ipasfrag *pq = q->ipf_prev;
+               i = pq->ipf_off + pq->ipf_len - ip->ip_off;
                if (i > 0) {
                        if (i >= ip->ip_len)
                                goto dropfrag;
@@ -311,17 +337,18 @@ ip_reass(register struct ipasfrag *ip, register struct ipq *fp)
         * While we overlap succeeding segments trim them or,
         * if they are completely covered, dequeue them.
         */
-       while (q != (struct ipasfrag *)fp && ip->ip_off + ip->ip_len > q->ip_off) {
-               i = (ip->ip_off + ip->ip_len) - q->ip_off;
-               if (i < q->ip_len) {
-                       q->ip_len -= i;
-                       q->ip_off += i;
+       while (q != (struct ipasfrag*)&fp->frag_link &&
+            ip->ip_off + ip->ip_len > q->ipf_off) {
+               i = (ip->ip_off + ip->ip_len) - q->ipf_off;
+               if (i < q->ipf_len) {
+                       q->ipf_len -= i;
+                       q->ipf_off += i;
                        m_adj(dtom(q), i);
                        break;
                }
-               q = (struct ipasfrag *) q->ipf_next;
-               m_freem(dtom((struct ipasfrag *) q->ipf_prev));
-               ip_deq((struct ipasfrag *) q->ipf_prev);
+               q = q->ipf_next;
+               m_freem(dtom(q->ipf_prev));
+               ip_deq(q->ipf_prev);
        }
 
 insert:
@@ -329,27 +356,26 @@ insert:
         * Stick new segment in its place;
         * check for complete reassembly.
         */
-       ip_enq(ip, (struct ipasfrag *) q->ipf_prev);
+       ip_enq(iptofrag(ip), q->ipf_prev);
        next = 0;
-       for (q = (struct ipasfrag *) fp->ipq_next; q != (struct ipasfrag *)fp;
-            q = (struct ipasfrag *) q->ipf_next) {
-               if (q->ip_off != next)
+       for (q = fp->frag_link.next; q != (struct ipasfrag*)&fp->frag_link;
+            q = q->ipf_next) {
+               if (q->ipf_off != next)
                        return (0);
-               next += q->ip_len;
+               next += q->ipf_len;
        }
-       if (((struct ipasfrag *)(q->ipf_prev))->ipf_mff & 1)
+       if (((struct ipasfrag *)(q->ipf_prev))->ipf_tos & 1)
                return (0);
 
        /*
         * Reassembly is complete; concatenate fragments.
         */
-       q = (struct ipasfrag *) fp->ipq_next;
+    q = fp->frag_link.next;
        m = dtom(q);
 
        q = (struct ipasfrag *) q->ipf_next;
-       while (q != (struct ipasfrag *)fp) {
-         struct mbuf *t;
-         t = dtom(q);
+       while (q != (struct ipasfrag*)&fp->frag_link) {
+         struct mbuf *t = dtom(q);
          q = (struct ipasfrag *) q->ipf_next;
          m_cat(m, t);
        }
@@ -360,7 +386,7 @@ insert:
         * dequeue and discard fragment reassembly header.
         * Make header visible.
         */
-       ip = (struct ipasfrag *) fp->ipq_next;
+       q = fp->frag_link.next;
 
        /*
         * If the fragments concatenated to an mbuf that's
@@ -372,23 +398,23 @@ insert:
        if (m->m_flags & M_EXT) {
          int delta;
          delta = (char *)ip - m->m_dat;
-         ip = (struct ipasfrag *)(m->m_ext + delta);
+         q = (struct ipasfrag *)(m->m_ext + delta);
        }
 
        /* DEBUG_ARG("ip = %lx", (long)ip);
         * ip=(struct ipasfrag *)m->m_data; */
 
+    ip = fragtoip(q);
        ip->ip_len = next;
-       ip->ipf_mff &= ~1;
-       ((struct ip *)ip)->ip_src = fp->ipq_src;
-       ((struct ip *)ip)->ip_dst = fp->ipq_dst;
-       remque_32(fp);
+       ip->ip_tos &= ~1;
+       ip->ip_src = fp->ipq_src;
+       ip->ip_dst = fp->ipq_dst;
+       remque(&fp->ip_link);
        (void) m_free(dtom(fp));
-       m = dtom(ip);
        m->m_len += (ip->ip_hl << 2);
        m->m_data -= (ip->ip_hl << 2);
 
-       return ((struct ip *)ip);
+       return ip;
 
 dropfrag:
        STAT(ipstat.ips_fragdropped++);
@@ -405,13 +431,12 @@ ip_freef(struct ipq *fp)
 {
        register struct ipasfrag *q, *p;
 
-       for (q = (struct ipasfrag *) fp->ipq_next; q != (struct ipasfrag *)fp;
-           q = p) {
-               p = (struct ipasfrag *) q->ipf_next;
+       for (q = fp->frag_link.next; q != (struct ipasfrag*)&fp->frag_link; q = p) {
+               p = q->ipf_next;
                ip_deq(q);
                m_freem(dtom(q));
        }
-       remque_32(fp);
+       remque(&fp->ip_link);
        (void) m_free(dtom(fp));
 }
 
@@ -424,10 +449,10 @@ ip_enq(register struct ipasfrag *p, register struct ipasfrag *prev)
 {
        DEBUG_CALL("ip_enq");
        DEBUG_ARG("prev = %lx", (long)prev);
-       p->ipf_prev = (ipasfragp_32) prev;
+       p->ipf_prev =  prev;
        p->ipf_next = prev->ipf_next;
-       ((struct ipasfrag *)(prev->ipf_next))->ipf_prev = (ipasfragp_32) p;
-       prev->ipf_next = (ipasfragp_32) p;
+       ((struct ipasfrag *)(prev->ipf_next))->ipf_prev = p;
+       prev->ipf_next = p;
 }
 
 /*
@@ -448,20 +473,21 @@ ip_deq(register struct ipasfrag *p)
 void
 ip_slowtimo()
 {
-       register struct ipq *fp;
+    struct qlink *l;
 
        DEBUG_CALL("ip_slowtimo");
 
-       fp = (struct ipq *) ipq.next;
-       if (fp == 0)
+    l = ipq.ip_link.next;
+
+       if (l == 0)
           return;
 
-       while (fp != &ipq) {
-               --fp->ipq_ttl;
-               fp = (struct ipq *) fp->next;
-               if (((struct ipq *)(fp->prev))->ipq_ttl == 0) {
+       while (l != &ipq.ip_link) {
+        struct ipq *fp = container_of(l, struct ipq, ip_link);
+        l = l->next;
+               if (--fp->ipq_ttl == 0) {
                        STAT(ipstat.ips_fragtimeout++);
-                       ip_freef((struct ipq *) fp->prev);
+                       ip_freef(fp);
                }
        }
 }
index 7e4cfa9..6c5db54 100644 (file)
@@ -5,7 +5,7 @@
 extern "C" {
 #endif
 
-void slirp_init(void);
+void slirp_init(int restrict, char *special_ip);
 
 void slirp_select_fill(int *pnfds,
                        fd_set *readfds, fd_set *writefds, fd_set *xfds);
@@ -20,13 +20,16 @@ void slirp_output(const uint8_t *pkt, int pkt_len);
 
 int slirp_redir(int is_udp, int host_port,
                 struct in_addr guest_addr, int guest_port);
-int slirp_add_exec(int do_pty, const char *args, int addr_low_byte,
+int slirp_add_exec(int do_pty, const void *args, int addr_low_byte,
                    int guest_port);
 
 extern const char *tftp_prefix;
 extern char slirp_hostname[33];
 
 void slirp_stats(void);
+void slirp_socket_recv(int addr_low_byte, int guest_port, const uint8_t *buf,
+               int size);
+size_t slirp_socket_can_recv(int addr_low_byte, int guest_port);
 
 #ifdef __cplusplus
 }
index c01adda..ed51385 100644 (file)
@@ -44,6 +44,8 @@ extern int towrite_max;
 extern int ppp_exit;
 extern int tcp_keepintvl;
 extern uint8_t client_ethaddr[6];
+extern const char *slirp_special_ip;
+extern int slirp_restrict;
 
 #define PROTO_SLIP 0x1
 #ifdef USE_PPP
@@