summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvi Kivity <avi@redhat.com>2009-01-14 13:18:20 +0200
committerAvi Kivity <avi@redhat.com>2009-01-14 13:18:20 +0200
commitce1dfb7a1078decf340714eaec57db9533dc8af6 (patch)
treeb37e11381f56087ea4dc652c2a5b0b8d66f24fe2
parentDisable special ioapic inti0 routing (diff)
parentDo not rely on __powerpc__ being defined as a feature test macro (diff)
downloadqemu-kvm-ce1dfb7a1078decf340714eaec57db9533dc8af6.tar.gz
qemu-kvm-ce1dfb7a1078decf340714eaec57db9533dc8af6.tar.bz2
qemu-kvm-ce1dfb7a1078decf340714eaec57db9533dc8af6.zip
Merge branch 'qemu-cvs'
Conflicts: qemu/Makefile qemu/hw/mips_malta.c qemu/hw/pc.c qemu/hw/pci.c qemu/hw/pci.h qemu/hw/ppc_chrp.c qemu/hw/ppc_prep.c qemu/hw/realview.c qemu/hw/sun4u.c qemu/hw/versatilepb.c qemu/hw/virtio-net.c qemu/monitor.c qemu/net.c qemu/net.h qemu/pc-bios/bios.bin Signed-off-by: Avi Kivity <avi@redhat.com>
-rw-r--r--Makefile6
-rw-r--r--Makefile.target9
-rw-r--r--block-qcow.c45
-rw-r--r--block-qcow2.c1
-rw-r--r--cache-utils.c4
-rw-r--r--cache-utils.h4
-rwxr-xr-xconfigure13
-rw-r--r--gdbstub.c4
-rw-r--r--hw/alpha_palcode.c6
-rw-r--r--hw/apb_pci.c47
-rw-r--r--hw/axis_dev88.c10
-rw-r--r--hw/device-hotplug.c2
-rw-r--r--hw/e1000.c16
-rw-r--r--hw/escc.c (renamed from hw/slavio_serial.c)151
-rw-r--r--hw/escc.h7
-rw-r--r--hw/etraxfs.c10
-rw-r--r--hw/etraxfs.h2
-rw-r--r--hw/etraxfs_eth.c25
-rw-r--r--hw/ide.c10
-rw-r--r--hw/integratorcp.c14
-rw-r--r--hw/macio.c9
-rw-r--r--hw/mcf5208.c14
-rw-r--r--hw/mcf_fec.c2
-rw-r--r--hw/mips_malta.c19
-rw-r--r--hw/mips_mipssim.c16
-rw-r--r--hw/mips_r4k.c14
-rw-r--r--hw/mips_timer.c11
-rw-r--r--hw/mipsnet.c2
-rw-r--r--hw/musicpal.c2
-rw-r--r--hw/ne2000.c2
-rw-r--r--hw/pc.c27
-rw-r--r--hw/pci.c70
-rw-r--r--hw/pci.h8
-rw-r--r--hw/pci_host.h28
-rw-r--r--hw/pcnet.c2
-rw-r--r--hw/ppc.h8
-rw-r--r--hw/ppc440_bamboo.c11
-rw-r--r--hw/ppc_chrp.c19
-rw-r--r--hw/ppc_mac.h6
-rw-r--r--hw/ppc_oldworld.c33
-rw-r--r--hw/ppc_prep.c9
-rw-r--r--hw/r2d.c4
-rw-r--r--hw/realview.c9
-rw-r--r--hw/rtl8139.c20
-rw-r--r--hw/smc91c111.c2
-rw-r--r--hw/stellaris.c4
-rw-r--r--hw/stellaris_enet.c2
-rw-r--r--hw/sun4m.c54
-rw-r--r--hw/sun4m.h6
-rw-r--r--hw/sun4u.c63
-rw-r--r--hw/versatilepb.c9
-rw-r--r--hw/virtio-net.c29
-rw-r--r--hw/virtio-net.h9
-rw-r--r--monitor.c1
-rw-r--r--net.c98
-rw-r--r--net.h7
-rw-r--r--pc-bios/README3
-rw-r--r--pc-bios/bios-pq/0002_e820-high-mem.patch129
-rw-r--r--pc-bios/bios-pq/0003_smp-startup-poll.patch21
-rw-r--r--pc-bios/bios-pq/0005_hpet.patch190
-rw-r--r--pc-bios/bios-pq/HEAD2
-rw-r--r--pc-bios/bios-pq/series3
-rw-r--r--pc-bios/openbios-ppcbin0 -> 259168 bytes
-rw-r--r--pc-bios/openbios-sparc32bin272948 -> 234084 bytes
-rw-r--r--pc-bios/openbios-sparc64bin541600 -> 476000 bytes
-rw-r--r--posix-aio-compat.c9
-rw-r--r--qemu-doc.texi6
-rw-r--r--qemu-nbd.c2
-rw-r--r--slirp/bootp.c22
-rw-r--r--slirp/ip.h64
-rw-r--r--slirp/ip_input.c156
-rw-r--r--slirp/libslirp.h7
-rw-r--r--slirp/main.h3
-rw-r--r--slirp/misc.c35
-rw-r--r--slirp/sbuf.c2
-rw-r--r--slirp/slirp.c303
-rw-r--r--slirp/slirp.h8
-rw-r--r--slirp/socket.c101
-rw-r--r--slirp/socket.h2
-rw-r--r--slirp/tcp_input.c54
-rw-r--r--slirp/tcp_subr.c21
-rw-r--r--slirp/tcp_var.h25
-rw-r--r--slirp/tcpip.h11
-rw-r--r--slirp/udp.c8
-rw-r--r--slirp/udp.h3
-rw-r--r--target-mips/helper.c443
-rw-r--r--target-mips/translate.c86
-rw-r--r--target-mips/translate_init.c20
-rw-r--r--target-ppc/helper.h35
-rw-r--r--target-ppc/op_helper.c128
-rw-r--r--target-ppc/translate.c92
-rw-r--r--target-sparc/helper.c20
-rw-r--r--vl.c6
93 files changed, 1749 insertions, 1286 deletions
diff --git a/Makefile b/Makefile
index 86f1f3c0b..4212cb551 100644
--- a/Makefile
+++ b/Makefile
@@ -225,8 +225,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
BLOBS += extboot.bin
else
BLOBS=
@@ -360,6 +361,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 \
diff --git a/Makefile.target b/Makefile.target
index c3542b11b..2b1aa37c9 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -646,10 +646,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
@@ -732,7 +729,7 @@ OBJS+= cirrus_vga.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
@@ -779,7 +776,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
diff --git a/block-qcow.c b/block-qcow.c
index 1fecf3078..91c53b1b8 100644
--- a/block-qcow.c
+++ b/block-qcow.c
@@ -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 */
diff --git a/block-qcow2.c b/block-qcow2.c
index 707109e44..9aa7261e3 100644
--- a/block-qcow2.c
+++ b/block-qcow2.c
@@ -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;
diff --git a/cache-utils.c b/cache-utils.c
index 7c98144ae..73a824a07 100644
--- a/cache-utils.c
+++ b/cache-utils.c
@@ -1,6 +1,6 @@
#include "cache-utils.h"
-#ifdef __powerpc__
+#ifdef HOST_PPC
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 */
diff --git a/cache-utils.h b/cache-utils.h
index 0598b96eb..19b24ab4e 100644
--- a/cache-utils.h
+++ b/cache-utils.h
@@ -1,7 +1,9 @@
#ifndef QEMU_CACHE_UTILS_H
#define QEMU_CACHE_UTILS_H
-#ifdef __powerpc__
+#include "config-host.h"
+
+#ifdef HOST_PPC
struct qemu_cache_conf {
unsigned long dcache_bsize;
unsigned long icache_bsize;
diff --git a/configure b/configure
index 4e67a39b0..e2c83fdf6 100755
--- 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"
@@ -537,8 +538,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"
@@ -1014,6 +1015,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
diff --git a/gdbstub.c b/gdbstub.c
index 9e6f44bda..470138265 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -695,7 +695,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
@@ -729,7 +729,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) {
diff --git a/hw/alpha_palcode.c b/hw/alpha_palcode.c
index 70d4af6b2..151f3c2ab 100644
--- a/hw/alpha_palcode.c
+++ b/hw/alpha_palcode.c
@@ -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 */
diff --git a/hw/apb_pci.c b/hw/apb_pci.c
index d84788854..f222f3c0e 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -22,12 +22,23 @@
* 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;
}
diff --git a/hw/axis_dev88.c b/hw/axis_dev88.c
index f7bdd1465..066b96944 100644
--- a/hw/axis_dev88.c
+++ b/hw/axis_dev88.c
@@ -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]);
diff --git a/hw/device-hotplug.c b/hw/device-hotplug.c
index 0bcac601b..56172e114 100644
--- a/hw/device-hotplug.c
+++ b/hw/device-hotplug.c
@@ -26,7 +26,7 @@ static PCIDevice *qemu_system_hot_add_nic(const char *opts, int bus_nr)
ret = net_client_init ("nic", opts);
if (ret < 0 || !nd_table[ret].model)
return NULL;
- return pci_nic_init (pci_bus, &nd_table[ret], -1);
+ return pci_nic_init (pci_bus, &nd_table[ret], -1, "rtl8139");
}
#ifdef USE_KVM_DEVICE_ASSIGNMENT
diff --git a/hw/e1000.c b/hw/e1000.c
index 9de057d5f..eaed351f1 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -571,6 +571,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)
{
@@ -1087,6 +1102,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);
diff --git a/hw/slavio_serial.c b/hw/escc.c
index 1028ed944..d68f90b54 100644
--- a/hw/slavio_serial.c
+++ 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
*
@@ -44,6 +44,14 @@
* 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,36 +706,39 @@ 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 irq, 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;
@@ -735,6 +746,7 @@ SerialState *slavio_serial_init(target_phys_addr_t base, qemu_irq irq,
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 +754,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 +901,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 +909,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 +924,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
index 000000000..2f3ae3116
--- /dev/null
+++ b/hw/escc.h
@@ -0,0 +1,7 @@
+/* escc.c */
+#define ESCC_SIZE 4
+int escc_init(target_phys_addr_t base, qemu_irq irq, 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);
diff --git a/hw/etraxfs.c b/hw/etraxfs.c
index 01b5a6e6f..e409a94e2 100644
--- a/hw/etraxfs.c
+++ b/hw/etraxfs.c
@@ -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]);
diff --git a/hw/etraxfs.h b/hw/etraxfs.h
index 0c9fdbb60..17dca29a4 100644
--- a/hw/etraxfs.h
+++ b/hw/etraxfs.h
@@ -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);
diff --git a/hw/etraxfs_eth.c b/hw/etraxfs_eth.c
index 239e0d872..cce89178a 100644
--- a/hw/etraxfs_eth.c
+++ b/hw/etraxfs_eth.c
@@ -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:
diff --git a/hw/ide.c b/hw/ide.c
index b74b3b3cb..92ef4a513 100644
--- a/hw/ide.c
+++ b/hw/ide.c
@@ -956,7 +956,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);
@@ -1068,7 +1068,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);
@@ -2468,7 +2468,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;
@@ -3186,9 +3187,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,
diff --git a/hw/integratorcp.c b/hw/integratorcp.c
index a2d3d4306..fdbfe202f 100644
--- a/hw/integratorcp.c
+++ b/hw/integratorcp.c
@@ -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;
diff --git a/hw/macio.c b/hw/macio.c
index 7f0d9f791..2a98dfb31 100644
--- a/hw/macio.c
+++ b/hw/macio.c
@@ -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;
diff --git a/hw/mcf5208.c b/hw/mcf5208.c
index 71ba3fb0a..f06c25a54 100644
--- a/hw/mcf5208.c
+++ b/hw/mcf5208.c
@@ -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. */
diff --git a/hw/mcf_fec.c b/hw/mcf_fec.c
index 49ae69bd5..413c5694d 100644
--- a/hw/mcf_fec.c
+++ b/hw/mcf_fec.c
@@ -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,
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index dea9b589f..3ca036bba 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -487,21 +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 */
- if (!pci_nic_init(pci_bus, nd, 88))
- exit(1);
- } else {
- if (!pci_nic_init(pci_bus, nd, -1))
- exit(1);
- }
+ devfn = 88;
+
+ pci_nic_init(pci_bus, nd, devfn, "pcnet");
}
}
diff --git a/hw/mips_mipssim.c b/hw/mips_mipssim.c
index dc62f696a..83f1a63e5 100644
--- a/hw/mips_mipssim.c
+++ b/hw/mips_mipssim.c
@@ -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 = {
diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c
index 6551b02e0..c12ab54b0 100644
--- a/hw/mips_r4k.c
+++ b/hw/mips_r4k.c
@@ -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");
diff --git a/hw/mips_timer.c b/hw/mips_timer.c
index 13217b2da..67b873511 100644
--- a/hw/mips_timer.c
+++ b/hw/mips_timer.c
@@ -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;
}
diff --git a/hw/mipsnet.c b/hw/mipsnet.c
index 0eb4c1ed1..04ce32287 100644
--- a/hw/mipsnet.c
+++ b/hw/mipsnet.c
@@ -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;
diff --git a/hw/musicpal.c b/hw/musicpal.c
index 1c932ec3f..f64bb1c89 100644
--- a/hw/musicpal.c
+++ b/hw/musicpal.c
@@ -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;
diff --git a/hw/ne2000.c b/hw/ne2000.c
index a6d0eecae..7c000176f 100644
--- a/hw/ne2000.c
+++ b/hw/ne2000.c
@@ -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 c470646d4..3038cd3e2 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -814,7 +814,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;
@@ -1062,28 +1061,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 = "rtl8139";
- } 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");
- if (!pci_nic_init(pci_bus, nd, -1))
- exit(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, "rtl8139");
}
qemu_system_hot_add_init(cpu_model);
diff --git a/hw/pci.c b/hw/pci.c
index 8589dfa8c..ae5dd5386 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -715,43 +715,51 @@ 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 PCIDevice *(*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. */
-PCIDevice *pci_nic_init(PCIBus *bus, NICInfo *nd, int devfn)
+PCIDevice *pci_nic_init(PCIBus *bus, NICInfo *nd, int devfn,
+ const char *default_model)
{
PCIDevice *pci_dev;
+ int i;
- if (strcmp(nd->model, "ne2k_pci") == 0) {
- pci_dev = pci_ne2000_init(bus, nd, devfn);
- } else if (strcmp(nd->model, "i82551") == 0) {
- pci_dev = pci_i82551_init(bus, nd, devfn);
- } else if (strcmp(nd->model, "i82557b") == 0) {
- pci_dev = pci_i82557b_init(bus, nd, devfn);
- } else if (strcmp(nd->model, "i82559er") == 0) {
- pci_dev = pci_i82559er_init(bus, nd, devfn);
- } else if (strcmp(nd->model, "rtl8139") == 0) {
- pci_dev = pci_rtl8139_init(bus, nd, devfn);
- } else if (strcmp(nd->model, "e1000") == 0) {
- pci_dev = pci_e1000_init(bus, nd, devfn);
- } else if (strcmp(nd->model, "pcnet") == 0) {
- pci_dev = pci_pcnet_init(bus, nd, devfn);
- } else if (strcmp(nd->model, "virtio") == 0) {
- pci_dev = 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");
- return NULL;
- } else {
- fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd->model);
- return NULL;
- }
+ qemu_check_nic_model_list(nd, pci_nic_models, default_model);
- if (!pci_dev) {
- fprintf(stderr, "qemu: Unable to initialze NIC: %s\n", nd->model);
- return NULL;
- }
+ for (i = 0; pci_nic_models[i]; i++)
+ if (strcmp(nd->model, pci_nic_models[i]) == 0) {
+ pci_dev = pci_nic_init_fns[i](bus, nd, devfn);
+ if (pci_dev) {
+ nd->devfn = pci_dev->devfn;
+ }
+ return pci_dev;
+ }
- nd->devfn = pci_dev->devfn;
- return pci_dev;
+ return NULL;
}
typedef struct {
diff --git a/hw/pci.h b/hw/pci.h
index 1f33819fe..060183a57 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -126,7 +126,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);
-PCIDevice *pci_nic_init(PCIBus *bus, NICInfo *nd, int devfn);
+PCIDevice *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);
@@ -178,8 +179,9 @@ PCIDevice *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,
diff --git a/hw/pci_host.h b/hw/pci_host.h
index e2e428a27..c4f42a40e 100644
--- a/hw/pci_host.h
+++ b/hw/pci_host.h
@@ -25,6 +25,16 @@
/* 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
diff --git a/hw/pcnet.c b/hw/pcnet.c
index e92960a95..f5bf15d64 100644
--- a/hw/pcnet.c
+++ b/hw/pcnet.c
@@ -2090,6 +2090,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;
diff --git a/hw/ppc.h b/hw/ppc.h
index 297f55060..75eb11a32 100644
--- 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,
+};
+
diff --git a/hw/ppc440_bamboo.c b/hw/ppc440_bamboo.c
index a6fc75823..bc8a47b46 100644
--- a/hw/ppc440_bamboo.c
+++ b/hw/ppc440_bamboo.c
@@ -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");
}
}
diff --git a/hw/ppc_chrp.c b/hw/ppc_chrp.c
index daa3aeb95..7625cd131 100644
--- a/hw/ppc_chrp.c
+++ b/hw/ppc_chrp.c
@@ -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,14 +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";
- if (!pci_nic_init(pci_bus, &nd_table[i], -1))
- exit(1);
- }
+ escc_mem_index = escc_init(0x80013000, dummy_irq[4], 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);
@@ -296,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);
diff --git a/hw/ppc_mac.h b/hw/ppc_mac.h
index c833d1758..cc70fb7dc 100644
--- a/hw/ppc_mac.h
+++ b/hw/ppc_mac.h
@@ -31,12 +31,14 @@
#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);
diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c
index 1d5e9d67f..cf8b24f58 100644
--- a/hw/ppc_oldworld.c
+++ b/hw/ppc_oldworld.c
@@ -33,17 +33,12 @@
#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;
@@ -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[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);
diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
index e315028a5..6c0d8fe7c 100644
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@ -671,12 +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 {
- if (!pci_nic_init(pci_bus, &nd_table[i], -1))
- exit(1);
+ pci_nic_init(pci_bus, &nd_table[i], -1, "ne2k_pci");
}
}
diff --git a/hw/r2d.c b/hw/r2d.c
index 5d5eb1e49..88853e710 100644
--- 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 */
{
diff --git a/hw/realview.c b/hw/realview.c
index eb98099c0..e28533800 100644
--- a/hw/realview.c
+++ b/hw/realview.c
@@ -121,13 +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 {
- if (!pci_nic_init(pci_bus, nd, -1))
- exit(1);
+ pci_nic_init(pci_bus, nd, -1, "rtl8139");
}
}
diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index 687667a64..2527d9bfb 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -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;
}
@@ -3450,7 +3464,7 @@ PCIDevice *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);
diff --git a/hw/smc91c111.c b/hw/smc91c111.c
index 27a3158f9..f5b29a704 100644
--- a/hw/smc91c111.c
+++ b/hw/smc91c111.c
@@ -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);
diff --git a/hw/stellaris.c b/hw/stellaris.c
index 703ef7e42..7069518bd 100644
--- a/hw/stellaris.c
+++ b/hw/stellaris.c
@@ -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 };
diff --git a/hw/stellaris_enet.c b/hw/stellaris_enet.c
index a5cd16389..88c56204e 100644
--- a/hw/stellaris_enet.c
+++ b/hw/stellaris_enet.c
@@ -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);
diff --git a/hw/sun4m.c b/hw/sun4m.c
index e6a538a9f..eb6733c0c 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -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], 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], 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,17 @@ 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], 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);
diff --git a/hw/sun4m.h b/hw/sun4m.h
index f6d822ee3..c9601ed32 100644
--- a/hw/sun4m.h
+++ b/hw/sun4m.h
@@ -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,
diff --git a/hw/sun4u.c b/hw/sun4u.c
index 0c1e1a24c..91e7538da 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -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,12 +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";
- if (!pci_nic_init(pci_bus, &nd_table[i], -1))
- exit(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) {
diff --git a/hw/versatilepb.c b/hw/versatilepb.c
index 527f65eff..267aa42d6 100644
--- a/hw/versatilepb.c
+++ b/hw/versatilepb.c
@@ -194,13 +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 {
- if (!pci_nic_init(pci_bus, nd, -1))
- exit(1);
+ pci_nic_init(pci_bus, nd, -1, "rtl8139");
}
}
if (usb_enabled) {
diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index 1f9dc16bf..28337c3a3 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -25,6 +25,7 @@ typedef struct VirtIONet
{
VirtIODevice vdev;
uint8_t mac[6];
+ uint16_t status;
VirtQueue *rx_vq;
VirtQueue *tx_vq;
VLANClientState *vc;
@@ -47,13 +48,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);
#ifdef TAP_VNET_HDR
VirtIONet *n = to_virtio_net(vdev);
VLANClientState *host = n->vc->vlan->first_client;
@@ -393,7 +409,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;
@@ -401,9 +417,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;
@@ -411,8 +428,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);
@@ -422,6 +441,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;
}
diff --git a/hw/virtio-net.h b/hw/virtio-net.h
index 0d9f71ba1..148ec4712 100644
--- a/hw/virtio-net.h
+++ b/hw/virtio-net.h
@@ -37,16 +37,21 @@
#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
diff --git a/monitor.c b/monitor.c
index d3d097f34..1bc46f461 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1543,6 +1543,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]" },
{ "cpu_set", "is", do_cpu_set_nr, "cpu [online|offline]", "change cpu state" },
#if defined(TARGET_I386) || defined(TARGET_X86_64)
{ "drive_add", "iss", drive_hot_add, "pcibus pcidevfn [file=file][,if=type][,bus=n]\n"
diff --git a/net.c b/net.c
index 77bf15335..f9b239fdc 100644
--- a/net.c
+++ b/net.c
@@ -301,7 +301,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]);
}
@@ -389,12 +390,15 @@ int qemu_send_packet(VLANClientState *vc1, const uint8_t *buf, int size)
VLANClientState *vc;
int ret = -EAGAIN;
+ 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) {
if (!vc->fd_can_read || vc->fd_can_read(vc->opaque)) {
vc->fd_read(vc->opaque, buf, size);
ret = 0;
@@ -453,6 +457,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)
@@ -489,7 +495,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);
@@ -507,7 +513,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;
@@ -593,7 +599,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 */
@@ -673,6 +679,7 @@ typedef struct TAPState {
VLANClientState *vc;
int fd;
char down_script[1024];
+ char down_script_arg[128];
char buf[TAP_BUFSIZE];
int size;
unsigned int has_vnet_hdr : 1;
@@ -1155,8 +1162,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;
}
@@ -1674,6 +1683,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];
@@ -1736,6 +1779,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
@@ -1875,6 +1924,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;
@@ -1886,13 +1965,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 9232fd6c0..35d478888 100644
--- a/net.h
+++ b/net.h
@@ -9,6 +9,7 @@ typedef ssize_t (IOReadvHandler)(void *, const struct iovec *, int);
typedef struct VLANClientState VLANClientState;
+typedef void (LinkStatusChanged)(VLANClientState *);
typedef void (SetOffload)(VLANClientState *, int, int, int, int);
struct VLANClientState {
@@ -17,6 +18,8 @@ struct VLANClientState {
/* 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;
SetOffload *set_offload;
void *opaque;
struct VLANClientState *next;
@@ -46,9 +49,13 @@ ssize_t qemu_sendv_packet(VLANClientState *vc, const struct iovec *iov,
int iovcnt);
int 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);
int tap_has_vnet_hdr(void *opaque);
void tap_using_vnet_hdr(void *opaque, int using_vnet_hdr);
diff --git a/pc-bios/README b/pc-bios/README
index 665bd7d59..1fabe0e84 100644
--- a/pc-bios/README
+++ b/pc-bios/README
@@ -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 373.
- 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
index 2886e8566..000000000
--- a/pc-bios/bios-pq/0002_e820-high-mem.patch
+++ /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
index cd1a3ff03..000000000
--- a/pc-bios/bios-pq/0003_smp-startup-poll.patch
+++ /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
index 9347cb501..000000000
--- a/pc-bios/bios-pq/0005_hpet.patch
+++ /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
diff --git a/pc-bios/bios-pq/HEAD b/pc-bios/bios-pq/HEAD
index 928a2334b..1f604ae82 100644
--- a/pc-bios/bios-pq/HEAD
+++ b/pc-bios/bios-pq/HEAD
@@ -1 +1 @@
-370a7e0d8419bc05192d766c11b7221e5ffc0f75
+7342176bb0fa9d6cc63b37f6ac239e3f70b74219
diff --git a/pc-bios/bios-pq/series b/pc-bios/bios-pq/series
index 0e7558c47..556c0e48d 100644
--- a/pc-bios/bios-pq/series
+++ b/pc-bios/bios-pq/series
@@ -1,4 +1 @@
0001_bx-qemu.patch
-0002_e820-high-mem.patch
-0003_smp-startup-poll.patch
-0005_hpet.patch
diff --git a/pc-bios/openbios-ppc b/pc-bios/openbios-ppc
new file mode 100644
index 000000000..e597269dd
--- /dev/null
+++ b/pc-bios/openbios-ppc
Binary files differ
diff --git a/pc-bios/openbios-sparc32 b/pc-bios/openbios-sparc32
index 7c5d0127b..8f4170b55 100644
--- a/pc-bios/openbios-sparc32
+++ b/pc-bios/openbios-sparc32
Binary files differ
diff --git a/pc-bios/openbios-sparc64 b/pc-bios/openbios-sparc64
index 99e0d790e..e00c5ddbb 100644
--- a/pc-bios/openbios-sparc64
+++ b/pc-bios/openbios-sparc64
Binary files differ
diff --git a/posix-aio-compat.c b/posix-aio-compat.c
index 92ec23457..c919e3b22 100644
--- a/posix-aio-compat.c
+++ b/posix-aio-compat.c
@@ -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);
diff --git a/qemu-doc.texi b/qemu-doc.texi
index 2ebc5dbf8..bd3a7f1f0 100644
--- a/qemu-doc.texi
+++ b/qemu-doc.texi
@@ -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
diff --git a/qemu-nbd.c b/qemu-nbd.c
index ed64b6b2d..59bd2f14f 100644
--- a/qemu-nbd.c
+++ b/qemu-nbd.c
@@ -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' },
diff --git a/slirp/bootp.c b/slirp/bootp.c
index 750fae3d0..bf704abf5 100644
--- a/slirp/bootp.c
+++ b/slirp/bootp.c
@@ -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;
diff --git a/slirp/ip.h b/slirp/ip.h
index a8cdb0d3f..3079f90f9 100644
--- a/slirp/ip.h
+++ b/slirp/ip.h
@@ -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.
diff --git a/slirp/ip_input.c b/slirp/ip_input.c
index b04684027..116ee4565 100644
--- a/slirp/ip_input.c
+++ b/slirp/ip_input.c
@@ -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);
}
}
}
diff --git a/slirp/libslirp.h b/slirp/libslirp.h
index 7e4cfa98a..6c5db54c9 100644
--- a/slirp/libslirp.h
+++ b/slirp/libslirp.h
@@ -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
}
diff --git a/slirp/main.h b/slirp/main.h
index c01addac4..ed5138559 100644
--- a/slirp/main.h
+++ b/slirp/main.h
@@ -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
@@ -51,3 +53,4 @@ extern uint8_t client_ethaddr[6];
#endif
void if_encap(const uint8_t *ip_data, int ip_data_len);
+ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags);
diff --git a/slirp/misc.c b/slirp/misc.c
index 9ff317639..f558b3c0f 100644
--- a/slirp/misc.c
+++ b/slirp/misc.c
@@ -83,39 +83,6 @@ getouraddr()
our_addr.s_addr = loopback_addr.s_addr;
}
-#if SIZEOF_CHAR_P == 8
-
-struct quehead_32 {
- u_int32_t qh_link;
- u_int32_t qh_rlink;
-};
-
-inline void
-insque_32(a, b)
- void *a;
- void *b;
-{
- register struct quehead_32 *element = (struct quehead_32 *) a;
- register struct quehead_32 *head = (struct quehead_32 *) b;
- element->qh_link = head->qh_link;
- head->qh_link = (u_int32_t)element;
- element->qh_rlink = (u_int32_t)head;
- ((struct quehead_32 *)(element->qh_link))->qh_rlink
- = (u_int32_t)element;
-}
-
-inline void
-remque_32(a)
- void *a;
-{
- register struct quehead_32 *element = (struct quehead_32 *) a;
- ((struct quehead_32 *)(element->qh_link))->qh_rlink = element->qh_rlink;
- ((struct quehead_32 *)(element->qh_rlink))->qh_link = element->qh_link;
- element->qh_rlink = 0;
-}
-
-#endif /* SIZEOF_CHAR_P == 8 */
-
struct quehead {
struct quehead *qh_link;
struct quehead *qh_rlink;
@@ -169,7 +136,7 @@ add_exec(ex_ptr, do_pty, exec, addr, port)
(*ex_ptr)->ex_fport = port;
(*ex_ptr)->ex_addr = addr;
(*ex_ptr)->ex_pty = do_pty;
- (*ex_ptr)->ex_exec = strdup(exec);
+ (*ex_ptr)->ex_exec = (do_pty == 3) ? exec : strdup(exec);
(*ex_ptr)->ex_next = tmp_ptr;
return 0;
}
diff --git a/slirp/sbuf.c b/slirp/sbuf.c
index b0e083840..2e6e2b214 100644
--- a/slirp/sbuf.c
+++ b/slirp/sbuf.c
@@ -108,7 +108,7 @@ sbappend(so, m)
* ottherwise it'll arrive out of order, and hence corrupt
*/
if (!so->so_rcv.sb_cc)
- ret = send(so->s, m->m_data, m->m_len, 0);
+ ret = slirp_send(so, m->m_data, m->m_len, 0);
if (ret <= 0) {
/*
diff --git a/slirp/slirp.c b/slirp/slirp.c
index 17b40e249..0394496ab 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -21,7 +21,10 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
+#include "qemu-common.h"
+#include "qemu-char.h"
#include "slirp.h"
+#include "hw/hw.h"
/* host address */
struct in_addr our_addr;
@@ -45,6 +48,8 @@ static struct in_addr client_ipaddr;
static const uint8_t zero_ethaddr[6] = { 0, 0, 0, 0, 0, 0 };
+const char *slirp_special_ip = CTL_SPECIAL;
+int slirp_restrict;
int do_slowtimo;
int link_up;
struct timeval tt;
@@ -163,7 +168,10 @@ static void slirp_cleanup(void)
}
#endif
-void slirp_init(void)
+static void slirp_state_save(QEMUFile *f, void *opaque);
+static int slirp_state_load(QEMUFile *f, void *opaque, int version_id);
+
+void slirp_init(int restrict, char *special_ip)
{
// debug_init("/tmp/slirp.log", DEBUG_DEFAULT);
@@ -176,6 +184,7 @@ void slirp_init(void)
#endif
link_up = 1;
+ slirp_restrict = restrict;
if_init();
ip_init();
@@ -191,9 +200,13 @@ void slirp_init(void)
fprintf (stderr, "Warning: No DNS servers found\n");
}
- inet_aton(CTL_SPECIAL, &special_addr);
+ if (special_ip)
+ slirp_special_ip = special_ip;
+
+ inet_aton(slirp_special_ip, &special_addr);
alias_addr.s_addr = special_addr.s_addr | htonl(CTL_ALIAS);
getouraddr();
+ register_savevm("slirp", 0, 1, slirp_state_save, slirp_state_load, NULL);
}
#define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
@@ -249,7 +262,7 @@ void slirp_select_fill(int *pnfds,
* in the fragment queue, or there are TCP connections active
*/
do_slowtimo = ((tcb.so_next != &tcb) ||
- ((struct ipasfrag *)&ipq != (struct ipasfrag *)ipq.next));
+ (&ipq.ip_link != ipq.ip_link.next));
for (so = tcb.so_next; so != &tcb; so = so_next) {
so_next = so->so_next;
@@ -736,9 +749,291 @@ int slirp_redir(int is_udp, int host_port,
return 0;
}
-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)
{
return add_exec(&exec_list, do_pty, (char *)args,
addr_low_byte, htons(guest_port));
}
+
+ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags)
+{
+ if (so->s == -1 && so->extra) {
+ qemu_chr_write(so->extra, buf, len);
+ return len;
+ }
+
+ return send(so->s, buf, len, flags);
+}
+
+static struct socket *slirp_find_ctl_socket(int addr_low_byte, int guest_port)
+{
+ struct socket *so;
+
+ for (so = tcb.so_next; so != &tcb; so = so->so_next) {
+ if ((so->so_faddr.s_addr & htonl(0xffffff00)) ==
+ special_addr.s_addr
+ && (ntohl(so->so_faddr.s_addr) & 0xff) ==
+ addr_low_byte
+ && htons(so->so_fport) == guest_port)
+ return so;
+ }
+
+ return NULL;
+}
+
+size_t slirp_socket_can_recv(int addr_low_byte, int guest_port)
+{
+ struct iovec iov[2];
+ struct socket *so;
+
+ if (!link_up)
+ return 0;
+
+ so = slirp_find_ctl_socket(addr_low_byte, guest_port);
+
+ if (!so || so->so_state & SS_NOFDREF)
+ return 0;
+
+ if (!CONN_CANFRCV(so) || so->so_snd.sb_cc >= (so->so_snd.sb_datalen/2))
+ return 0;
+
+ return sopreprbuf(so, iov, NULL);
+}
+
+void slirp_socket_recv(int addr_low_byte, int guest_port, const uint8_t *buf,
+ int size)
+{
+ int ret;
+ struct socket *so = slirp_find_ctl_socket(addr_low_byte, guest_port);
+
+ if (!so)
+ return;
+
+ ret = soreadbuf(so, (const char *)buf, size);
+
+ if (ret > 0)
+ tcp_output(sototcpcb(so));
+}
+
+static void slirp_tcp_save(QEMUFile *f, struct tcpcb *tp)
+{
+ int i;
+
+ qemu_put_sbe16(f, tp->t_state);
+ for (i = 0; i < TCPT_NTIMERS; i++)
+ qemu_put_sbe16(f, tp->t_timer[i]);
+ qemu_put_sbe16(f, tp->t_rxtshift);
+ qemu_put_sbe16(f, tp->t_rxtcur);
+ qemu_put_sbe16(f, tp->t_dupacks);
+ qemu_put_be16(f, tp->t_maxseg);
+ qemu_put_sbyte(f, tp->t_force);
+ qemu_put_be16(f, tp->t_flags);
+ qemu_put_be32(f, tp->snd_una);
+ qemu_put_be32(f, tp->snd_nxt);
+ qemu_put_be32(f, tp->snd_up);
+ qemu_put_be32(f, tp->snd_wl1);
+ qemu_put_be32(f, tp->snd_wl2);
+ qemu_put_be32(f, tp->iss);
+ qemu_put_be32(f, tp->snd_wnd);
+ qemu_put_be32(f, tp->rcv_wnd);
+ qemu_put_be32(f, tp->rcv_nxt);
+ qemu_put_be32(f, tp->rcv_up);
+ qemu_put_be32(f, tp->irs);
+ qemu_put_be32(f, tp->rcv_adv);
+ qemu_put_be32(f, tp->snd_max);
+ qemu_put_be32(f, tp->snd_cwnd);
+ qemu_put_be32(f, tp->snd_ssthresh);
+ qemu_put_sbe16(f, tp->t_idle);
+ qemu_put_sbe16(f, tp->t_rtt);
+ qemu_put_be32(f, tp->t_rtseq);
+ qemu_put_sbe16(f, tp->t_srtt);
+ qemu_put_sbe16(f, tp->t_rttvar);
+ qemu_put_be16(f, tp->t_rttmin);
+ qemu_put_be32(f, tp->max_sndwnd);
+ qemu_put_byte(f, tp->t_oobflags);
+ qemu_put_byte(f, tp->t_iobc);
+ qemu_put_sbe16(f, tp->t_softerror);
+ qemu_put_byte(f, tp->snd_scale);
+ qemu_put_byte(f, tp->rcv_scale);
+ qemu_put_byte(f, tp->request_r_scale);
+ qemu_put_byte(f, tp->requested_s_scale);
+ qemu_put_be32(f, tp->ts_recent);
+ qemu_put_be32(f, tp->ts_recent_age);
+ qemu_put_be32(f, tp->last_ack_sent);
+}
+
+static void slirp_sbuf_save(QEMUFile *f, struct sbuf *sbuf)
+{
+ uint32_t off;
+
+ qemu_put_be32(f, sbuf->sb_cc);
+ qemu_put_be32(f, sbuf->sb_datalen);
+ off = (uint32_t)(sbuf->sb_wptr - sbuf->sb_data);
+ qemu_put_sbe32(f, off);
+ off = (uint32_t)(sbuf->sb_rptr - sbuf->sb_data);
+ qemu_put_sbe32(f, off);
+ qemu_put_buffer(f, (unsigned char*)sbuf->sb_data, sbuf->sb_datalen);
+}
+
+static void slirp_socket_save(QEMUFile *f, struct socket *so)
+{
+ qemu_put_be32(f, so->so_urgc);
+ qemu_put_be32(f, so->so_faddr.s_addr);
+ qemu_put_be32(f, so->so_laddr.s_addr);
+ qemu_put_be16(f, so->so_fport);
+ qemu_put_be16(f, so->so_lport);
+ qemu_put_byte(f, so->so_iptos);
+ qemu_put_byte(f, so->so_emu);
+ qemu_put_byte(f, so->so_type);
+ qemu_put_be32(f, so->so_state);
+ slirp_sbuf_save(f, &so->so_rcv);
+ slirp_sbuf_save(f, &so->so_snd);
+ slirp_tcp_save(f, so->so_tcpcb);
+}
+
+static void slirp_state_save(QEMUFile *f, void *opaque)
+{
+ struct ex_list *ex_ptr;
+
+ for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next)
+ if (ex_ptr->ex_pty == 3) {
+ struct socket *so;
+ so = slirp_find_ctl_socket(ex_ptr->ex_addr, ntohs(ex_ptr->ex_fport));
+ if (!so)
+ continue;
+
+ qemu_put_byte(f, 42);
+ slirp_socket_save(f, so);
+ }
+ qemu_put_byte(f, 0);
+}
+
+static void slirp_tcp_load(QEMUFile *f, struct tcpcb *tp)
+{
+ int i;
+
+ tp->t_state = qemu_get_sbe16(f);
+ for (i = 0; i < TCPT_NTIMERS; i++)
+ tp->t_timer[i] = qemu_get_sbe16(f);
+ tp->t_rxtshift = qemu_get_sbe16(f);
+ tp->t_rxtcur = qemu_get_sbe16(f);
+ tp->t_dupacks = qemu_get_sbe16(f);
+ tp->t_maxseg = qemu_get_be16(f);
+ tp->t_force = qemu_get_sbyte(f);
+ tp->t_flags = qemu_get_be16(f);
+ tp->snd_una = qemu_get_be32(f);
+ tp->snd_nxt = qemu_get_be32(f);
+ tp->snd_up = qemu_get_be32(f);
+ tp->snd_wl1 = qemu_get_be32(f);
+ tp->snd_wl2 = qemu_get_be32(f);
+ tp->iss = qemu_get_be32(f);
+ tp->snd_wnd = qemu_get_be32(f);
+ tp->rcv_wnd = qemu_get_be32(f);
+ tp->rcv_nxt = qemu_get_be32(f);
+ tp->rcv_up = qemu_get_be32(f);
+ tp->irs = qemu_get_be32(f);
+ tp->rcv_adv = qemu_get_be32(f);
+ tp->snd_max = qemu_get_be32(f);
+ tp->snd_cwnd = qemu_get_be32(f);
+ tp->snd_ssthresh = qemu_get_be32(f);
+ tp->t_idle = qemu_get_sbe16(f);
+ tp->t_rtt = qemu_get_sbe16(f);
+ tp->t_rtseq = qemu_get_be32(f);
+ tp->t_srtt = qemu_get_sbe16(f);
+ tp->t_rttvar = qemu_get_sbe16(f);
+ tp->t_rttmin = qemu_get_be16(f);
+ tp->max_sndwnd = qemu_get_be32(f);
+ tp->t_oobflags = qemu_get_byte(f);
+ tp->t_iobc = qemu_get_byte(f);
+ tp->t_softerror = qemu_get_sbe16(f);
+ tp->snd_scale = qemu_get_byte(f);
+ tp->rcv_scale = qemu_get_byte(f);
+ tp->request_r_scale = qemu_get_byte(f);
+ tp->requested_s_scale = qemu_get_byte(f);
+ tp->ts_recent = qemu_get_be32(f);
+ tp->ts_recent_age = qemu_get_be32(f);
+ tp->last_ack_sent = qemu_get_be32(f);
+ tcp_template(tp);
+}
+
+static int slirp_sbuf_load(QEMUFile *f, struct sbuf *sbuf)
+{
+ uint32_t off, sb_cc, sb_datalen;
+
+ sb_cc = qemu_get_be32(f);
+ sb_datalen = qemu_get_be32(f);
+
+ sbreserve(sbuf, sb_datalen);
+
+ if (sbuf->sb_datalen != sb_datalen)
+ return -ENOMEM;
+
+ sbuf->sb_cc = sb_cc;
+
+ off = qemu_get_sbe32(f);
+ sbuf->sb_wptr = sbuf->sb_data + off;
+ off = qemu_get_sbe32(f);
+ sbuf->sb_rptr = sbuf->sb_data + off;
+ qemu_get_buffer(f, (unsigned char*)sbuf->sb_data, sbuf->sb_datalen);
+
+ return 0;
+}
+
+static int slirp_socket_load(QEMUFile *f, struct socket *so)
+{
+ if (tcp_attach(so) < 0)
+ return -ENOMEM;
+
+ so->so_urgc = qemu_get_be32(f);
+ so->so_faddr.s_addr = qemu_get_be32(f);
+ so->so_laddr.s_addr = qemu_get_be32(f);
+ so->so_fport = qemu_get_be16(f);
+ so->so_lport = qemu_get_be16(f);
+ so->so_iptos = qemu_get_byte(f);
+ so->so_emu = qemu_get_byte(f);
+ so->so_type = qemu_get_byte(f);
+ so->so_state = qemu_get_be32(f);
+ if (slirp_sbuf_load(f, &so->so_rcv) < 0)
+ return -ENOMEM;
+ if (slirp_sbuf_load(f, &so->so_snd) < 0)
+ return -ENOMEM;
+ slirp_tcp_load(f, so->so_tcpcb);
+
+ return 0;
+}
+
+static int slirp_state_load(QEMUFile *f, void *opaque, int version_id)
+{
+ struct ex_list *ex_ptr;
+ int r;
+
+ while ((r = qemu_get_byte(f))) {
+ int ret;
+ struct socket *so = socreate();
+
+ if (!so)
+ return -ENOMEM;
+
+ ret = slirp_socket_load(f, so);
+
+ if (ret < 0)
+ return ret;
+
+ if ((so->so_faddr.s_addr & htonl(0xffffff00)) != special_addr.s_addr)
+ return -EINVAL;
+
+ for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next)
+ if (ex_ptr->ex_pty == 3 &&
+ (ntohl(so->so_faddr.s_addr) & 0xff) == ex_ptr->ex_addr &&
+ so->so_fport == ex_ptr->ex_fport)
+ break;
+
+ if (!ex_ptr)
+ return -EINVAL;
+
+ so->extra = (void *)ex_ptr->ex_exec;
+ }
+
+ return 0;
+}
diff --git a/slirp/slirp.h b/slirp/slirp.h
index 3002e0bb0..d57fb1236 100644
--- a/slirp/slirp.h
+++ b/slirp/slirp.h
@@ -266,14 +266,6 @@ void if_start _P((struct ttys *));
void lprint _P((const char *, ...));
-#if SIZEOF_CHAR_P == 4
-# define insque_32 insque
-# define remque_32 remque
-#else
- void insque_32 _P((void *, void *));
- void remque_32 _P((void *));
-#endif
-
#ifndef _WIN32
#include <netdb.h>
#endif
diff --git a/slirp/socket.c b/slirp/socket.c
index 00694e2c7..9def541da 100644
--- a/slirp/socket.c
+++ b/slirp/socket.c
@@ -5,13 +5,13 @@
* terms and conditions of the copyright.
*/
+#include "qemu-common.h"
#define WANT_SYS_IOCTL_H
#include <slirp.h>
#include "ip_icmp.h"
#ifdef __sun__
#include <sys/filio.h>
#endif
-#include "qemu-common.h"
static void sofcantrcvmore(struct socket *so);
static void sofcantsendmore(struct socket *so);
@@ -91,31 +91,21 @@ sofree(so)
free(so);
}
-/*
- * Read from so's socket into sb_snd, updating all relevant sbuf fields
- * NOTE: This will only be called if it is select()ed for reading, so
- * a read() of 0 (or less) means it's disconnected
- */
-int
-soread(so)
- struct socket *so;
+size_t sopreprbuf(struct socket *so, struct iovec *iov, int *np)
{
- int n, nn, lss, total;
+ int n, lss, total;
struct sbuf *sb = &so->so_snd;
int len = sb->sb_datalen - sb->sb_cc;
- struct iovec iov[2];
int mss = so->so_tcpcb->t_maxseg;
- DEBUG_CALL("soread");
+ DEBUG_CALL("sopreprbuf");
DEBUG_ARG("so = %lx", (long )so);
- /*
- * No need to check if there's enough room to read.
- * soread wouldn't have been called if there weren't
- */
-
len = sb->sb_datalen - sb->sb_cc;
+ if (len <= 0)
+ return 0;
+
iov[0].iov_base = sb->sb_wptr;
iov[1].iov_base = NULL;
iov[1].iov_len = 0;
@@ -156,6 +146,33 @@ soread(so)
n = 1;
}
}
+ if (np)
+ *np = n;
+
+ return iov[0].iov_len + (n - 1) * iov[1].iov_len;
+}
+
+/*
+ * Read from so's socket into sb_snd, updating all relevant sbuf fields
+ * NOTE: This will only be called if it is select()ed for reading, so
+ * a read() of 0 (or less) means it's disconnected
+ */
+int
+soread(so)
+ struct socket *so;
+{
+ int n, nn;
+ struct sbuf *sb = &so->so_snd;
+ struct iovec iov[2];
+
+ DEBUG_CALL("soread");
+ DEBUG_ARG("so = %lx", (long )so);
+
+ /*
+ * No need to check if there's enough room to read.
+ * soread wouldn't have been called if there weren't
+ */
+ sopreprbuf(so, iov, &n);
#ifdef HAVE_READV
nn = readv(so->s, (struct iovec *)iov, n);
@@ -202,6 +219,48 @@ soread(so)
return nn;
}
+int soreadbuf(struct socket *so, const char *buf, int size)
+{
+ int n, nn, copy = size;
+ struct sbuf *sb = &so->so_snd;
+ struct iovec iov[2];
+
+ DEBUG_CALL("soreadbuf");
+ DEBUG_ARG("so = %lx", (long )so);
+
+ /*
+ * No need to check if there's enough room to read.
+ * soread wouldn't have been called if there weren't
+ */
+ if (sopreprbuf(so, iov, &n) < size)
+ goto err;
+
+ nn = MIN(iov[0].iov_len, copy);
+ memcpy(iov[0].iov_base, buf, nn);
+
+ copy -= nn;
+ buf += nn;
+
+ if (copy == 0)
+ goto done;
+
+ memcpy(iov[1].iov_base, buf, copy);
+
+done:
+ /* Update fields */
+ sb->sb_cc += size;
+ sb->sb_wptr += size;
+ if (sb->sb_wptr >= (sb->sb_data + sb->sb_datalen))
+ sb->sb_wptr -= sb->sb_datalen;
+ return size;
+err:
+
+ sofcantrcvmore(so);
+ tcp_sockclosed(sototcpcb(so));
+ fprintf(stderr, "soreadbuf buffer to small");
+ return -1;
+}
+
/*
* Get urgent data
*
@@ -255,7 +314,7 @@ sosendoob(so)
if (sb->sb_rptr < sb->sb_wptr) {
/* We can send it directly */
- n = send(so->s, sb->sb_rptr, so->so_urgc, (MSG_OOB)); /* |MSG_DONTWAIT)); */
+ n = slirp_send(so, sb->sb_rptr, so->so_urgc, (MSG_OOB)); /* |MSG_DONTWAIT)); */
so->so_urgc -= n;
DEBUG_MISC((dfd, " --- sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc));
@@ -276,7 +335,7 @@ sosendoob(so)
so->so_urgc -= n;
len += n;
}
- n = send(so->s, buff, len, (MSG_OOB)); /* |MSG_DONTWAIT)); */
+ n = slirp_send(so, buff, len, (MSG_OOB)); /* |MSG_DONTWAIT)); */
#ifdef DEBUG
if (n != len)
DEBUG_ERROR((dfd, "Didn't send all data urgently XXXXX\n"));
@@ -348,7 +407,7 @@ sowrite(so)
DEBUG_MISC((dfd, " ... wrote nn = %d bytes\n", nn));
#else
- nn = send(so->s, iov[0].iov_base, iov[0].iov_len,0);
+ nn = slirp_send(so, iov[0].iov_base, iov[0].iov_len,0);
#endif
/* This should never happen, but people tell me it does *shrug* */
if (nn < 0 && (errno == EAGAIN || errno == EINTR))
@@ -365,7 +424,7 @@ sowrite(so)
#ifndef HAVE_READV
if (n == 2 && nn == iov[0].iov_len) {
int ret;
- ret = send(so->s, iov[1].iov_base, iov[1].iov_len,0);
+ ret = slirp_send(so, iov[1].iov_base, iov[1].iov_len,0);
if (ret > 0)
nn += ret;
}
diff --git a/slirp/socket.h b/slirp/socket.h
index 5edea90c9..72b473d63 100644
--- a/slirp/socket.h
+++ b/slirp/socket.h
@@ -87,5 +87,7 @@ void soisfconnecting _P((register struct socket *));
void soisfconnected _P((register struct socket *));
void soisfdisconnected _P((struct socket *));
void sofwdrain _P((struct socket *));
+size_t sopreprbuf(struct socket *so, struct iovec *iov, int *np);
+int soreadbuf(struct socket *so, const char *buf, int size);
#endif /* _SOCKET_H_ */
diff --git a/slirp/tcp_input.c b/slirp/tcp_input.c
index 17a9387f0..f324adb1d 100644
--- a/slirp/tcp_input.c
+++ b/slirp/tcp_input.c
@@ -71,7 +71,7 @@ tcp_seq tcp_iss; /* tcp initial send seq # */
#ifdef TCP_ACK_HACK
#define TCP_REASS(tp, ti, m, so, flags) {\
if ((ti)->ti_seq == (tp)->rcv_nxt && \
- (tp)->seg_next == (tcpiphdrp_32)(tp) && \
+ tcpfrag_list_empty(tp) && \
(tp)->t_state == TCPS_ESTABLISHED) {\
if (ti->ti_flags & TH_PUSH) \
tp->t_flags |= TF_ACKNOW; \
@@ -94,7 +94,7 @@ tcp_seq tcp_iss; /* tcp initial send seq # */
#else
#define TCP_REASS(tp, ti, m, so, flags) { \
if ((ti)->ti_seq == (tp)->rcv_nxt && \
- (tp)->seg_next == (tcpiphdrp_32)(tp) && \
+ tcpfrag_list_empty(tp) && \
(tp)->t_state == TCPS_ESTABLISHED) { \
tp->t_flags |= TF_DELACK; \
(tp)->rcv_nxt += (ti)->ti_len; \
@@ -134,8 +134,8 @@ tcp_reass(register struct tcpcb *tp, register struct tcpiphdr *ti,
/*
* Find a segment which begins after this one does.
*/
- for (q = (struct tcpiphdr *)tp->seg_next; q != (struct tcpiphdr *)tp;
- q = (struct tcpiphdr *)q->ti_next)
+ for (q = tcpfrag_list_first(tp); !tcpfrag_list_end(q, tp);
+ q = tcpiphdr_next(q))
if (SEQ_GT(q->ti_seq, ti->ti_seq))
break;
@@ -144,9 +144,9 @@ tcp_reass(register struct tcpcb *tp, register struct tcpiphdr *ti,
* our data already. If so, drop the data from the incoming
* segment. If it provides all of our data, drop us.
*/
- if ((struct tcpiphdr *)q->ti_prev != (struct tcpiphdr *)tp) {
+ if (!tcpfrag_list_end(tcpiphdr_prev(q), tp)) {
register int i;
- q = (struct tcpiphdr *)q->ti_prev;
+ q = tcpiphdr_prev(q);
/* conversion to int (in i) handles seq wraparound */
i = q->ti_seq + q->ti_len - ti->ti_seq;
if (i > 0) {
@@ -166,36 +166,36 @@ tcp_reass(register struct tcpcb *tp, register struct tcpiphdr *ti,
ti->ti_len -= i;
ti->ti_seq += i;
}
- q = (struct tcpiphdr *)(q->ti_next);
+ q = tcpiphdr_next(q);
}
STAT(tcpstat.tcps_rcvoopack++);
STAT(tcpstat.tcps_rcvoobyte += ti->ti_len);
- REASS_MBUF(ti) = (mbufp_32) m; /* XXX */
+ ti->ti_mbuf = m;
/*
* While we overlap succeeding segments trim them or,
* if they are completely covered, dequeue them.
*/
- while (q != (struct tcpiphdr *)tp) {
+ while (!tcpfrag_list_end(q, tp)) {
register int i = (ti->ti_seq + ti->ti_len) - q->ti_seq;
if (i <= 0)
break;
if (i < q->ti_len) {
q->ti_seq += i;
q->ti_len -= i;
- m_adj((struct mbuf *) REASS_MBUF(q), i);
+ m_adj(q->ti_mbuf, i);
break;
}
- q = (struct tcpiphdr *)q->ti_next;
- m = (struct mbuf *) REASS_MBUF((struct tcpiphdr *)q->ti_prev);
- remque_32((void *)(q->ti_prev));
+ q = tcpiphdr_next(q);
+ m = tcpiphdr_prev(q)->ti_mbuf;
+ remque(tcpiphdr2qlink(tcpiphdr_prev(q)));
m_freem(m);
}
/*
* Stick new segment in its place.
*/
- insque_32(ti, (void *)(q->ti_prev));
+ insque(tcpiphdr2qlink(ti), tcpiphdr2qlink(tcpiphdr_prev(q)));
present:
/*
@@ -204,17 +204,17 @@ present:
*/
if (!TCPS_HAVEESTABLISHED(tp->t_state))
return (0);
- ti = (struct tcpiphdr *) tp->seg_next;
- if (ti == (struct tcpiphdr *)tp || ti->ti_seq != tp->rcv_nxt)
+ ti = tcpfrag_list_first(tp);
+ if (tcpfrag_list_end(ti, tp) || ti->ti_seq != tp->rcv_nxt)
return (0);
if (tp->t_state == TCPS_SYN_RECEIVED && ti->ti_len)
return (0);
do {
tp->rcv_nxt += ti->ti_len;
flags = ti->ti_flags & TH_FIN;
- remque_32(ti);
- m = (struct mbuf *) REASS_MBUF(ti); /* XXX */
- ti = (struct tcpiphdr *)ti->ti_next;
+ remque(tcpiphdr2qlink(ti));
+ m = ti->ti_mbuf;
+ ti = tcpiphdr_next(ti);
/* if (so->so_state & SS_FCANTRCVMORE) */
if (so->so_state & SS_FCANTSENDMORE)
m_freem(m);
@@ -253,6 +253,7 @@ tcp_input(m, iphlen, inso)
u_long tiwin;
int ret;
/* int ts_present = 0; */
+ struct ex_list *ex_ptr;
DEBUG_CALL("tcp_input");
DEBUG_ARGS((dfd," m = %8lx iphlen = %2d inso = %lx\n",
@@ -301,7 +302,8 @@ tcp_input(m, iphlen, inso)
* Checksum extended TCP header and data.
*/
tlen = ((struct ip *)ti)->ip_len;
- ti->ti_next = ti->ti_prev = 0;
+ tcpiphdr2qlink(ti)->next = tcpiphdr2qlink(ti)->prev = 0;
+ memset(&ti->ti_i.ih_mbuf, 0 , sizeof(struct mbuf_ptr));
ti->ti_x1 = 0;
ti->ti_len = htons((u_int16_t)tlen);
len = sizeof(struct ip ) + tlen;
@@ -363,6 +365,15 @@ tcp_input(m, iphlen, inso)
m->m_data += sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);
m->m_len -= sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);
+ if (slirp_restrict) {
+ for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next)
+ if (ex_ptr->ex_fport == ti->ti_dport &&
+ (ntohl(ti->ti_dst.s_addr) & 0xff) == ex_ptr->ex_addr)
+ break;
+
+ if (!ex_ptr)
+ goto drop;
+ }
/*
* Locate pcb for segment.
*/
@@ -550,7 +561,7 @@ findso:
return;
}
} else if (ti->ti_ack == tp->snd_una &&
- tp->seg_next == (tcpiphdrp_32)tp &&
+ tcpfrag_list_empty(tp) &&
ti->ti_len <= sbspace(&so->so_rcv)) {
/*
* this is a pure, in-sequence data packet
@@ -646,7 +657,6 @@ findso:
#endif
{
/* May be an add exec */
- struct ex_list *ex_ptr;
for(ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
if(ex_ptr->ex_fport == so->so_fport &&
lastbyte == ex_ptr->ex_addr) {
diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c
index bce07a6cb..497b98822 100644
--- a/slirp/tcp_subr.c
+++ b/slirp/tcp_subr.c
@@ -73,7 +73,7 @@ tcp_template(tp)
struct socket *so = tp->t_socket;
register struct tcpiphdr *n = &tp->t_template;
- n->ti_next = n->ti_prev = 0;
+ n->ti_mbuf = NULL;
n->ti_x1 = 0;
n->ti_pr = IPPROTO_TCP;
n->ti_len = htons(sizeof (struct tcpiphdr) - sizeof (struct ip));
@@ -156,7 +156,7 @@ tcp_respond(tp, ti, m, ack, seq, flags)
tlen += sizeof (struct tcpiphdr);
m->m_len = tlen;
- ti->ti_next = ti->ti_prev = 0;
+ ti->ti_mbuf = 0;
ti->ti_x1 = 0;
ti->ti_seq = htonl(seq);
ti->ti_ack = htonl(ack);
@@ -196,7 +196,7 @@ tcp_newtcpcb(so)
return ((struct tcpcb *)0);
memset((char *) tp, 0, sizeof(struct tcpcb));
- tp->seg_next = tp->seg_prev = (tcpiphdrp_32)tp;
+ tp->seg_next = tp->seg_prev = (struct tcpiphdr*)tp;
tp->t_maxseg = TCP_MSS;
tp->t_flags = TCP_DO_RFC1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0;
@@ -272,11 +272,11 @@ tcp_close(tp)
DEBUG_ARG("tp = %lx", (long )tp);
/* free the reassembly queue, if any */
- t = (struct tcpiphdr *) tp->seg_next;
- while (t != (struct tcpiphdr *)tp) {
- t = (struct tcpiphdr *)t->ti_next;
- m = (struct mbuf *) REASS_MBUF((struct tcpiphdr *)t->ti_prev);
- remque_32((struct tcpiphdr *) t->ti_prev);
+ t = tcpfrag_list_first(tp);
+ while (!tcpfrag_list_end(t, tp)) {
+ t = tcpiphdr_next(t);
+ m = tcpiphdr_prev(t)->ti_mbuf;
+ remque(tcpiphdr2qlink(tcpiphdr_prev(t)));
m_freem(m);
}
/* It's static */
@@ -1281,6 +1281,11 @@ tcp_ctl(so)
for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
if (ex_ptr->ex_fport == so->so_fport &&
command == ex_ptr->ex_addr) {
+ if (ex_ptr->ex_pty == 3) {
+ so->s = -1;
+ so->extra = (void *)ex_ptr->ex_exec;
+ return 1;
+ }
do_pty = ex_ptr->ex_pty;
goto do_exec;
}
diff --git a/slirp/tcp_var.h b/slirp/tcp_var.h
index 82380f936..99d18fdf1 100644
--- a/slirp/tcp_var.h
+++ b/slirp/tcp_var.h
@@ -40,18 +40,12 @@
#include "tcpip.h"
#include "tcp_timer.h"
-#if SIZEOF_CHAR_P == 4
- typedef struct tcpiphdr *tcpiphdrp_32;
-#else
- typedef u_int32_t tcpiphdrp_32;
-#endif
-
/*
* Tcp control block, one per tcp; fields:
*/
struct tcpcb {
- tcpiphdrp_32 seg_next; /* sequencing queue */
- tcpiphdrp_32 seg_prev;
+ struct tcpiphdr *seg_next; /* sequencing queue */
+ struct tcpiphdr *seg_prev;
short t_state; /* state of this connection */
short t_timer[TCPT_NTIMERS]; /* tcp timers */
short t_rxtshift; /* log(2) of rexmt exp. backoff */
@@ -170,21 +164,6 @@ struct tcpcb {
#define TCP_REXMTVAL(tp) \
(((tp)->t_srtt >> TCP_RTT_SHIFT) + (tp)->t_rttvar)
-/* XXX
- * We want to avoid doing m_pullup on incoming packets but that
- * means avoiding dtom on the tcp reassembly code. That in turn means
- * keeping an mbuf pointer in the reassembly queue (since we might
- * have a cluster). As a quick hack, the source & destination
- * port numbers (which are no longer needed once we've located the
- * tcpcb) are overlayed with an mbuf pointer.
- */
-#if SIZEOF_CHAR_P == 4
-typedef struct mbuf *mbufp_32;
-#else
-typedef u_int32_t mbufp_32;
-#endif
-#define REASS_MBUF(ti) (*(mbufp_32 *)&((ti)->ti_t))
-
#ifdef LOG_ENABLED
/*
* TCP statistics.
diff --git a/slirp/tcpip.h b/slirp/tcpip.h
index 82708b09c..b98cdb30d 100644
--- a/slirp/tcpip.h
+++ b/slirp/tcpip.h
@@ -44,8 +44,7 @@ struct tcpiphdr {
struct ipovly ti_i; /* overlaid ip structure */
struct tcphdr ti_t; /* tcp header */
};
-#define ti_next ti_i.ih_next
-#define ti_prev ti_i.ih_prev
+#define ti_mbuf ti_i.ih_mbuf.mptr
#define ti_x1 ti_i.ih_x1
#define ti_pr ti_i.ih_pr
#define ti_len ti_i.ih_len
@@ -62,6 +61,14 @@ struct tcpiphdr {
#define ti_sum ti_t.th_sum
#define ti_urp ti_t.th_urp
+#define tcpiphdr2qlink(T) ((struct qlink*)(((char*)(T)) - sizeof(struct qlink)))
+#define qlink2tcpiphdr(Q) ((struct tcpiphdr*)(((char*)(Q)) + sizeof(struct qlink)))
+#define tcpiphdr_next(T) qlink2tcpiphdr(tcpiphdr2qlink(T)->next)
+#define tcpiphdr_prev(T) qlink2tcpiphdr(tcpiphdr2qlink(T)->prev)
+#define tcpfrag_list_first(T) qlink2tcpiphdr((T)->seg_next)
+#define tcpfrag_list_end(F, T) (tcpiphdr2qlink(F) == (struct qlink*)(T))
+#define tcpfrag_list_empty(T) ((T)->seg_next == (struct tcpiphdr*)(T))
+
/*
* Just a clean way to get to the first byte
* of the packet
diff --git a/slirp/udp.c b/slirp/udp.c
index 8030326ad..c9926181a 100644
--- a/slirp/udp.c
+++ b/slirp/udp.c
@@ -136,8 +136,7 @@ udp_input(m, iphlen)
* Checksum extended UDP header and data.
*/
if (UDPCKSUM && uh->uh_sum) {
- ((struct ipovly *)ip)->ih_next = 0;
- ((struct ipovly *)ip)->ih_prev = 0;
+ memset(&((struct ipovly *)ip)->ih_mbuf, 0, sizeof(struct mbuf_ptr));
((struct ipovly *)ip)->ih_x1 = 0;
((struct ipovly *)ip)->ih_len = uh->uh_ulen;
/* keep uh_sum for ICMP reply
@@ -158,6 +157,9 @@ udp_input(m, iphlen)
goto bad;
}
+ if (slirp_restrict)
+ goto bad;
+
/*
* handle TFTP
*/
@@ -280,7 +282,7 @@ int udp_output2(struct socket *so, struct mbuf *m,
* and addresses and length put into network format.
*/
ui = mtod(m, struct udpiphdr *);
- ui->ui_next = ui->ui_prev = 0;
+ memset(&ui->ui_i.ih_mbuf, 0 , sizeof(struct mbuf_ptr));
ui->ui_x1 = 0;
ui->ui_pr = IPPROTO_UDP;
ui->ui_len = htons(m->m_len - sizeof(struct ip)); /* + sizeof (struct udphdr)); */
diff --git a/slirp/udp.h b/slirp/udp.h
index 4f69b098c..e2ca54645 100644
--- a/slirp/udp.h
+++ b/slirp/udp.h
@@ -60,8 +60,7 @@ struct udpiphdr {
struct ipovly ui_i; /* overlaid ip structure */
struct udphdr ui_u; /* udp header */
};
-#define ui_next ui_i.ih_next
-#define ui_prev ui_i.ih_prev
+#define ui_mbuf ui_i.ih_mbuf.mptr
#define ui_x1 ui_i.ih_x1
#define ui_pr ui_i.ih_pr
#define ui_len ui_i.ih_len
diff --git a/target-mips/helper.c b/target-mips/helper.c
index 0a3b913f1..c4fd9574e 100644
--- a/target-mips/helper.c
+++ b/target-mips/helper.c
@@ -100,6 +100,7 @@ int r4k_map_address (CPUState *env, target_ulong *physical, int *prot,
return TLBRET_NOMATCH;
}
+#if !defined(CONFIG_USER_ONLY)
static int get_physical_address (CPUState *env, target_ulong *physical,
int *prot, target_ulong address,
int rw, int access_type)
@@ -205,26 +206,29 @@ static int get_physical_address (CPUState *env, target_ulong *physical,
return ret;
}
+#endif
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
{
- if (env->user_mode_only)
- return addr;
- else {
- target_ulong phys_addr;
- int prot;
+#if defined(CONFIG_USER_ONLY)
+ return addr;
+#else
+ target_ulong phys_addr;
+ int prot;
- if (get_physical_address(env, &phys_addr, &prot, addr, 0, ACCESS_INT) != 0)
- return -1;
- return phys_addr;
- }
+ if (get_physical_address(env, &phys_addr, &prot, addr, 0, ACCESS_INT) != 0)
+ return -1;
+ return phys_addr;
+#endif
}
int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
int mmu_idx, int is_softmmu)
{
+#if !defined(CONFIG_USER_ONLY)
target_ulong physical;
int prot;
+#endif
int exception = 0, error_code = 0;
int access_type;
int ret = 0;
@@ -243,11 +247,9 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
/* XXX: put correct access by using cpu_restore_state()
correctly */
access_type = ACCESS_INT;
- if (env->user_mode_only) {
- /* user mode only emulation */
- ret = TLBRET_NOMATCH;
- goto do_fault;
- }
+#if defined(CONFIG_USER_ONLY)
+ ret = TLBRET_NOMATCH;
+#else
ret = get_physical_address(env, &physical, &prot,
address, rw, access_type);
if (logfile) {
@@ -258,8 +260,9 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
ret = tlb_set_page(env, address & TARGET_PAGE_MASK,
physical & TARGET_PAGE_MASK, prot,
mmu_idx, is_softmmu);
- } else if (ret < 0) {
- do_fault:
+ } else if (ret < 0)
+#endif
+ {
switch (ret) {
default:
case TLBRET_BADADDR:
@@ -349,227 +352,227 @@ static const char * const excp_names[EXCP_LAST + 1] = {
void do_interrupt (CPUState *env)
{
- if (!env->user_mode_only) {
- target_ulong offset;
- int cause = -1;
- const char *name;
+#if !defined(CONFIG_USER_ONLY)
+ target_ulong offset;
+ int cause = -1;
+ const char *name;
- if (logfile && env->exception_index != EXCP_EXT_INTERRUPT) {
- if (env->exception_index < 0 || env->exception_index > EXCP_LAST)
- name = "unknown";
- else
- name = excp_names[env->exception_index];
+ if (logfile && env->exception_index != EXCP_EXT_INTERRUPT) {
+ if (env->exception_index < 0 || env->exception_index > EXCP_LAST)
+ name = "unknown";
+ else
+ name = excp_names[env->exception_index];
- fprintf(logfile, "%s enter: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx " %s exception\n",
- __func__, env->active_tc.PC, env->CP0_EPC, name);
- }
- if (env->exception_index == EXCP_EXT_INTERRUPT &&
- (env->hflags & MIPS_HFLAG_DM))
- env->exception_index = EXCP_DINT;
- offset = 0x180;
- switch (env->exception_index) {
- case EXCP_DSS:
- env->CP0_Debug |= 1 << CP0DB_DSS;
- /* Debug single step cannot be raised inside a delay slot and
- resume will always occur on the next instruction
- (but we assume the pc has always been updated during
- code translation). */
+ fprintf(logfile, "%s enter: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx " %s exception\n",
+ __func__, env->active_tc.PC, env->CP0_EPC, name);
+ }
+ if (env->exception_index == EXCP_EXT_INTERRUPT &&
+ (env->hflags & MIPS_HFLAG_DM))
+ env->exception_index = EXCP_DINT;
+ offset = 0x180;
+ switch (env->exception_index) {
+ case EXCP_DSS:
+ env->CP0_Debug |= 1 << CP0DB_DSS;
+ /* Debug single step cannot be raised inside a delay slot and
+ resume will always occur on the next instruction
+ (but we assume the pc has always been updated during
+ code translation). */
+ env->CP0_DEPC = env->active_tc.PC;
+ goto enter_debug_mode;
+ case EXCP_DINT:
+ env->CP0_Debug |= 1 << CP0DB_DINT;
+ goto set_DEPC;
+ case EXCP_DIB:
+ env->CP0_Debug |= 1 << CP0DB_DIB;
+ goto set_DEPC;
+ case EXCP_DBp:
+ env->CP0_Debug |= 1 << CP0DB_DBp;
+ goto set_DEPC;
+ case EXCP_DDBS:
+ env->CP0_Debug |= 1 << CP0DB_DDBS;
+ goto set_DEPC;
+ case EXCP_DDBL:
+ env->CP0_Debug |= 1 << CP0DB_DDBL;
+ set_DEPC:
+ if (env->hflags & MIPS_HFLAG_BMASK) {
+ /* If the exception was raised from a delay slot,
+ come back to the jump. */
+ env->CP0_DEPC = env->active_tc.PC - 4;
+ env->hflags &= ~MIPS_HFLAG_BMASK;
+ } else {
env->CP0_DEPC = env->active_tc.PC;
- goto enter_debug_mode;
- case EXCP_DINT:
- env->CP0_Debug |= 1 << CP0DB_DINT;
- goto set_DEPC;
- case EXCP_DIB:
- env->CP0_Debug |= 1 << CP0DB_DIB;
- goto set_DEPC;
- case EXCP_DBp:
- env->CP0_Debug |= 1 << CP0DB_DBp;
- goto set_DEPC;
- case EXCP_DDBS:
- env->CP0_Debug |= 1 << CP0DB_DDBS;
- goto set_DEPC;
- case EXCP_DDBL:
- env->CP0_Debug |= 1 << CP0DB_DDBL;
- set_DEPC:
- if (env->hflags & MIPS_HFLAG_BMASK) {
- /* If the exception was raised from a delay slot,
- come back to the jump. */
- env->CP0_DEPC = env->active_tc.PC - 4;
- env->hflags &= ~MIPS_HFLAG_BMASK;
- } else {
- env->CP0_DEPC = env->active_tc.PC;
- }
+ }
enter_debug_mode:
- env->hflags |= MIPS_HFLAG_DM | MIPS_HFLAG_64 | MIPS_HFLAG_CP0;
- env->hflags &= ~(MIPS_HFLAG_KSU);
- /* EJTAG probe trap enable is not implemented... */
- if (!(env->CP0_Status & (1 << CP0St_EXL)))
- env->CP0_Cause &= ~(1 << CP0Ca_BD);
- env->active_tc.PC = (int32_t)0xBFC00480;
- break;
- case EXCP_RESET:
- cpu_reset(env);
- break;
- case EXCP_SRESET:
- env->CP0_Status |= (1 << CP0St_SR);
- memset(env->CP0_WatchLo, 0, sizeof(*env->CP0_WatchLo));
- goto set_error_EPC;
- case EXCP_NMI:
- env->CP0_Status |= (1 << CP0St_NMI);
+ env->hflags |= MIPS_HFLAG_DM | MIPS_HFLAG_64 | MIPS_HFLAG_CP0;
+ env->hflags &= ~(MIPS_HFLAG_KSU);
+ /* EJTAG probe trap enable is not implemented... */
+ if (!(env->CP0_Status & (1 << CP0St_EXL)))
+ env->CP0_Cause &= ~(1 << CP0Ca_BD);
+ env->active_tc.PC = (int32_t)0xBFC00480;
+ break;
+ case EXCP_RESET:
+ cpu_reset(env);
+ break;
+ case EXCP_SRESET:
+ env->CP0_Status |= (1 << CP0St_SR);
+ memset(env->CP0_WatchLo, 0, sizeof(*env->CP0_WatchLo));
+ goto set_error_EPC;
+ case EXCP_NMI:
+ env->CP0_Status |= (1 << CP0St_NMI);
set_error_EPC:
- if (env->hflags & MIPS_HFLAG_BMASK) {
- /* If the exception was raised from a delay slot,
- come back to the jump. */
- env->CP0_ErrorEPC = env->active_tc.PC - 4;
- env->hflags &= ~MIPS_HFLAG_BMASK;
- } else {
- env->CP0_ErrorEPC = env->active_tc.PC;
- }
- env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV);
- env->hflags |= MIPS_HFLAG_64 | MIPS_HFLAG_CP0;
- env->hflags &= ~(MIPS_HFLAG_KSU);
- if (!(env->CP0_Status & (1 << CP0St_EXL)))
- env->CP0_Cause &= ~(1 << CP0Ca_BD);
- env->active_tc.PC = (int32_t)0xBFC00000;
- break;
- case EXCP_EXT_INTERRUPT:
- cause = 0;
- if (env->CP0_Cause & (1 << CP0Ca_IV))
- offset = 0x200;
- goto set_EPC;
- case EXCP_LTLBL:
- cause = 1;
- goto set_EPC;
- case EXCP_TLBL:
- cause = 2;
- if (env->error_code == 1 && !(env->CP0_Status & (1 << CP0St_EXL))) {
+ if (env->hflags & MIPS_HFLAG_BMASK) {
+ /* If the exception was raised from a delay slot,
+ come back to the jump. */
+ env->CP0_ErrorEPC = env->active_tc.PC - 4;
+ env->hflags &= ~MIPS_HFLAG_BMASK;
+ } else {
+ env->CP0_ErrorEPC = env->active_tc.PC;
+ }
+ env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV);
+ env->hflags |= MIPS_HFLAG_64 | MIPS_HFLAG_CP0;
+ env->hflags &= ~(MIPS_HFLAG_KSU);
+ if (!(env->CP0_Status & (1 << CP0St_EXL)))
+ env->CP0_Cause &= ~(1 << CP0Ca_BD);
+ env->active_tc.PC = (int32_t)0xBFC00000;
+ break;
+ case EXCP_EXT_INTERRUPT:
+ cause = 0;
+ if (env->CP0_Cause & (1 << CP0Ca_IV))
+ offset = 0x200;
+ goto set_EPC;
+ case EXCP_LTLBL:
+ cause = 1;
+ goto set_EPC;
+ case EXCP_TLBL:
+ cause = 2;
+ if (env->error_code == 1 && !(env->CP0_Status & (1 << CP0St_EXL))) {
#if defined(TARGET_MIPS64)
- int R = env->CP0_BadVAddr >> 62;
- int UX = (env->CP0_Status & (1 << CP0St_UX)) != 0;
- int SX = (env->CP0_Status & (1 << CP0St_SX)) != 0;
- int KX = (env->CP0_Status & (1 << CP0St_KX)) != 0;
+ int R = env->CP0_BadVAddr >> 62;
+ int UX = (env->CP0_Status & (1 << CP0St_UX)) != 0;
+ int SX = (env->CP0_Status & (1 << CP0St_SX)) != 0;
+ int KX = (env->CP0_Status & (1 << CP0St_KX)) != 0;
- if ((R == 0 && UX) || (R == 1 && SX) || (R == 3 && KX))
- offset = 0x080;
- else
+ if ((R == 0 && UX) || (R == 1 && SX) || (R == 3 && KX))
+ offset = 0x080;
+ else
#endif
- offset = 0x000;
- }
- goto set_EPC;
- case EXCP_TLBS:
- cause = 3;
- if (env->error_code == 1 && !(env->CP0_Status & (1 << CP0St_EXL))) {
+ offset = 0x000;
+ }
+ goto set_EPC;
+ case EXCP_TLBS:
+ cause = 3;
+ if (env->error_code == 1 && !(env->CP0_Status & (1 << CP0St_EXL))) {
#if defined(TARGET_MIPS64)
- int R = env->CP0_BadVAddr >> 62;
- int UX = (env->CP0_Status & (1 << CP0St_UX)) != 0;
- int SX = (env->CP0_Status & (1 << CP0St_SX)) != 0;
- int KX = (env->CP0_Status & (1 << CP0St_KX)) != 0;
+ int R = env->CP0_BadVAddr >> 62;
+ int UX = (env->CP0_Status & (1 << CP0St_UX)) != 0;
+ int SX = (env->CP0_Status & (1 << CP0St_SX)) != 0;
+ int KX = (env->CP0_Status & (1 << CP0St_KX)) != 0;
- if ((R == 0 && UX) || (R == 1 && SX) || (R == 3 && KX))
- offset = 0x080;
- else
+ if ((R == 0 && UX) || (R == 1 && SX) || (R == 3 && KX))
+ offset = 0x080;
+ else
#endif
- offset = 0x000;
- }
- goto set_EPC;
- case EXCP_AdEL:
- cause = 4;
- goto set_EPC;
- case EXCP_AdES:
- cause = 5;
- goto set_EPC;
- case EXCP_IBE:
- cause = 6;
- goto set_EPC;
- case EXCP_DBE:
- cause = 7;
- goto set_EPC;
- case EXCP_SYSCALL:
- cause = 8;
- goto set_EPC;
- case EXCP_BREAK:
- cause = 9;
- goto set_EPC;
- case EXCP_RI:
- cause = 10;
- goto set_EPC;
- case EXCP_CpU:
- cause = 11;
- env->CP0_Cause = (env->CP0_Cause & ~(0x3 << CP0Ca_CE)) |
- (env->error_code << CP0Ca_CE);
- goto set_EPC;
- case EXCP_OVERFLOW:
- cause = 12;
- goto set_EPC;
- case EXCP_TRAP:
- cause = 13;
- goto set_EPC;
- case EXCP_FPE:
- cause = 15;
- goto set_EPC;
- case EXCP_C2E:
- cause = 18;
- goto set_EPC;
- case EXCP_MDMX:
- cause = 22;
- goto set_EPC;
- case EXCP_DWATCH:
- cause = 23;
- /* XXX: TODO: manage defered watch exceptions */
- goto set_EPC;
- case EXCP_MCHECK:
- cause = 24;
- goto set_EPC;
- case EXCP_THREAD:
- cause = 25;
- goto set_EPC;
- case EXCP_CACHE:
- cause = 30;
- if (env->CP0_Status & (1 << CP0St_BEV)) {
- offset = 0x100;
- } else {
- offset = 0x20000100;
- }
+ offset = 0x000;
+ }
+ goto set_EPC;
+ case EXCP_AdEL:
+ cause = 4;
+ goto set_EPC;
+ case EXCP_AdES:
+ cause = 5;
+ goto set_EPC;
+ case EXCP_IBE:
+ cause = 6;
+ goto set_EPC;
+ case EXCP_DBE:
+ cause = 7;
+ goto set_EPC;
+ case EXCP_SYSCALL:
+ cause = 8;
+ goto set_EPC;
+ case EXCP_BREAK:
+ cause = 9;
+ goto set_EPC;
+ case EXCP_RI:
+ cause = 10;
+ goto set_EPC;
+ case EXCP_CpU:
+ cause = 11;
+ env->CP0_Cause = (env->CP0_Cause & ~(0x3 << CP0Ca_CE)) |
+ (env->error_code << CP0Ca_CE);
+ goto set_EPC;
+ case EXCP_OVERFLOW:
+ cause = 12;
+ goto set_EPC;
+ case EXCP_TRAP:
+ cause = 13;
+ goto set_EPC;
+ case EXCP_FPE:
+ cause = 15;
+ goto set_EPC;
+ case EXCP_C2E:
+ cause = 18;
+ goto set_EPC;
+ case EXCP_MDMX:
+ cause = 22;
+ goto set_EPC;
+ case EXCP_DWATCH:
+ cause = 23;
+ /* XXX: TODO: manage defered watch exceptions */
+ goto set_EPC;
+ case EXCP_MCHECK:
+ cause = 24;
+ goto set_EPC;
+ case EXCP_THREAD:
+ cause = 25;
+ goto set_EPC;
+ case EXCP_CACHE:
+ cause = 30;
+ if (env->CP0_Status & (1 << CP0St_BEV)) {
+ offset = 0x100;
+ } else {
+ offset = 0x20000100;
+ }
set_EPC:
- if (!(env->CP0_Status & (1 << CP0St_EXL))) {
- if (env->hflags & MIPS_HFLAG_BMASK) {
- /* If the exception was raised from a delay slot,
- come back to the jump. */
- env->CP0_EPC = env->active_tc.PC - 4;
- env->CP0_Cause |= (1 << CP0Ca_BD);
- } else {
- env->CP0_EPC = env->active_tc.PC;
- env->CP0_Cause &= ~(1 << CP0Ca_BD);
- }
- env->CP0_Status |= (1 << CP0St_EXL);
- env->hflags |= MIPS_HFLAG_64 | MIPS_HFLAG_CP0;
- env->hflags &= ~(MIPS_HFLAG_KSU);
- }
- env->hflags &= ~MIPS_HFLAG_BMASK;
- if (env->CP0_Status & (1 << CP0St_BEV)) {
- env->active_tc.PC = (int32_t)0xBFC00200;
+ if (!(env->CP0_Status & (1 << CP0St_EXL))) {
+ if (env->hflags & MIPS_HFLAG_BMASK) {
+ /* If the exception was raised from a delay slot,
+ come back to the jump. */
+ env->CP0_EPC = env->active_tc.PC - 4;
+ env->CP0_Cause |= (1 << CP0Ca_BD);
} else {
- env->active_tc.PC = (int32_t)(env->CP0_EBase & ~0x3ff);
- }
- env->active_tc.PC += offset;
- env->CP0_Cause = (env->CP0_Cause & ~(0x1f << CP0Ca_EC)) | (cause << CP0Ca_EC);
- break;
- default:
- if (logfile) {
- fprintf(logfile, "Invalid MIPS exception %d. Exiting\n",
- env->exception_index);
+ env->CP0_EPC = env->active_tc.PC;
+ env->CP0_Cause &= ~(1 << CP0Ca_BD);
}
- printf("Invalid MIPS exception %d. Exiting\n", env->exception_index);
- exit(1);
+ env->CP0_Status |= (1 << CP0St_EXL);
+ env->hflags |= MIPS_HFLAG_64 | MIPS_HFLAG_CP0;
+ env->hflags &= ~(MIPS_HFLAG_KSU);
}
- if (logfile && env->exception_index != EXCP_EXT_INTERRUPT) {
- fprintf(logfile, "%s: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx " cause %d\n"
- " S %08x C %08x A " TARGET_FMT_lx " D " TARGET_FMT_lx "\n",
- __func__, env->active_tc.PC, env->CP0_EPC, cause,
- env->CP0_Status, env->CP0_Cause, env->CP0_BadVAddr,
- env->CP0_DEPC);
+ env->hflags &= ~MIPS_HFLAG_BMASK;
+ if (env->CP0_Status & (1 << CP0St_BEV)) {
+ env->active_tc.PC = (int32_t)0xBFC00200;
+ } else {
+ env->active_tc.PC = (int32_t)(env->CP0_EBase & ~0x3ff);
}
+ env->active_tc.PC += offset;
+ env->CP0_Cause = (env->CP0_Cause & ~(0x1f << CP0Ca_EC)) | (cause << CP0Ca_EC);
+ break;
+ default:
+ if (logfile) {
+ fprintf(logfile, "Invalid MIPS exception %d. Exiting\n",
+ env->exception_index);
+ }
+ printf("Invalid MIPS exception %d. Exiting\n", env->exception_index);
+ exit(1);
+ }
+ if (logfile && env->exception_index != EXCP_EXT_INTERRUPT) {
+ fprintf(logfile, "%s: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx " cause %d\n"
+ " S %08x C %08x A " TARGET_FMT_lx " D " TARGET_FMT_lx "\n",
+ __func__, env->active_tc.PC, env->CP0_EPC, cause,
+ env->CP0_Status, env->CP0_Cause, env->CP0_BadVAddr,
+ env->CP0_DEPC);
}
+#endif
env->exception_index = EXCP_NONE;
}
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 7bca5bc91..4a1861f7e 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -7859,13 +7859,13 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
gen_helper_rdhwr_ccres(t0);
break;
case 29:
- if (env->user_mode_only) {
- tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, tls_value));
- break;
- } else {
- /* XXX: Some CPUs implement this in hardware.
- Not supported yet. */
- }
+#if defined(CONFIG_USER_ONLY)
+ tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, tls_value));
+ break;
+#else
+ /* XXX: Some CPUs implement this in hardware.
+ Not supported yet. */
+#endif
default: /* Invalid */
MIPS_INVAL("rdhwr");
generate_exception(ctx, EXCP_RI);
@@ -7953,19 +7953,17 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
case OPC_DMTC0:
#endif
#ifndef CONFIG_USER_ONLY
- if (!env->user_mode_only)
- gen_cp0(env, ctx, op1, rt, rd);
+ gen_cp0(env, ctx, op1, rt, rd);
#endif /* !CONFIG_USER_ONLY */
break;
case OPC_C0_FIRST ... OPC_C0_LAST:
#ifndef CONFIG_USER_ONLY
- if (!env->user_mode_only)
- gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
+ gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
#endif /* !CONFIG_USER_ONLY */
break;
case OPC_MFMC0:
#ifndef CONFIG_USER_ONLY
- if (!env->user_mode_only) {
+ {
TCGv t0 = tcg_temp_local_new();
op2 = MASK_MFMC0(ctx->opcode);
@@ -8264,10 +8262,11 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
/* Restore delay slot state from the tb context. */
ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
restore_cpu_state(env, &ctx);
- if (env->user_mode_only)
+#ifdef CONFIG_USER_ONLY
ctx.mem_idx = MIPS_HFLAG_UM;
- else
+#else
ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
+#endif
num_insns = 0;
max_insns = tb->cflags & CF_COUNT_MASK;
if (max_insns == 0)
@@ -8583,40 +8582,37 @@ void cpu_reset (CPUMIPSState *env)
/* Minimal init */
#if defined(CONFIG_USER_ONLY)
- env->user_mode_only = 1;
-#endif
- if (env->user_mode_only) {
- env->hflags = MIPS_HFLAG_UM;
+ env->hflags = MIPS_HFLAG_UM;
+#else
+ if (env->hflags & MIPS_HFLAG_BMASK) {
+ /* If the exception was raised from a delay slot,
+ come back to the jump. */
+ env->CP0_ErrorEPC = env->active_tc.PC - 4;
} else {
- if (env->hflags & MIPS_HFLAG_BMASK) {
- /* If the exception was raised from a delay slot,
- come back to the jump. */
- env->CP0_ErrorEPC = env->active_tc.PC - 4;
- } else {
- env->CP0_ErrorEPC = env->active_tc.PC;
- }
- env->active_tc.PC = (int32_t)0xBFC00000;
- env->CP0_Wired = 0;
- /* SMP not implemented */
- env->CP0_EBase = 0x80000000;
- env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
- /* vectored interrupts not implemented, timer on int 7,
- no performance counters. */
- env->CP0_IntCtl = 0xe0000000;
- {
- int i;
-
- for (i = 0; i < 7; i++) {
- env->CP0_WatchLo[i] = 0;
- env->CP0_WatchHi[i] = 0x80000000;
- }
- env->CP0_WatchLo[7] = 0;
- env->CP0_WatchHi[7] = 0;
+ env->CP0_ErrorEPC = env->active_tc.PC;
+ }
+ env->active_tc.PC = (int32_t)0xBFC00000;
+ env->CP0_Wired = 0;
+ /* SMP not implemented */
+ env->CP0_EBase = 0x80000000;
+ env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
+ /* vectored interrupts not implemented, timer on int 7,
+ no performance counters. */
+ env->CP0_IntCtl = 0xe0000000;
+ {
+ int i;
+
+ for (i = 0; i < 7; i++) {
+ env->CP0_WatchLo[i] = 0;
+ env->CP0_WatchHi[i] = 0x80000000;
}
- /* Count register increments in debug mode, EJTAG version 1 */
- env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
- env->hflags = MIPS_HFLAG_CP0;
+ env->CP0_WatchLo[7] = 0;
+ env->CP0_WatchHi[7] = 0;
}
+ /* Count register increments in debug mode, EJTAG version 1 */
+ env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
+ env->hflags = MIPS_HFLAG_CP0;
+#endif
env->exception_index = EXCP_NONE;
cpu_mips_register(env, env->cpu_model);
}
diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c
index 7ec82b0d2..d0243aa1d 100644
--- a/target-mips/translate_init.c
+++ b/target-mips/translate_init.c
@@ -495,14 +495,14 @@ static void fpu_init (CPUMIPSState *env, const mips_def_t *def)
env->fpus[i].fcr0 = def->CP1_fcr0;
memcpy(&env->active_fpu, &env->fpus[0], sizeof(env->active_fpu));
- if (env->user_mode_only) {
- if (env->CP0_Config1 & (1 << CP0C1_FP))
- env->hflags |= MIPS_HFLAG_FPU;
+#if defined(CONFIG_USER_ONLY)
+ if (env->CP0_Config1 & (1 << CP0C1_FP))
+ env->hflags |= MIPS_HFLAG_FPU;
#ifdef TARGET_MIPS64
- if (env->active_fpu.fcr0 & (1 << FCR0_F64))
- env->hflags |= MIPS_HFLAG_F64;
+ if (env->active_fpu.fcr0 & (1 << FCR0_F64))
+ env->hflags |= MIPS_HFLAG_F64;
+#endif
#endif
- }
}
static void mvp_init (CPUMIPSState *env, const mips_def_t *def)
@@ -520,9 +520,10 @@ static void mvp_init (CPUMIPSState *env, const mips_def_t *def)
// (0x04 << CP0MVPC0_PTC);
(1 << CP0MVPC0_TCA) | (0x0 << CP0MVPC0_PVPE) |
(0x04 << CP0MVPC0_PTC);
+#if !defined(CONFIG_USER_ONLY)
/* Usermode has no TLB support */
- if (!env->user_mode_only)
- env->mvp->CP0_MVPConf0 |= (env->tlb->nb_tlb << CP0MVPC0_PTLBE);
+ env->mvp->CP0_MVPConf0 |= (env->tlb->nb_tlb << CP0MVPC0_PTLBE);
+#endif
/* Allocatable CP1 have media extensions, allocatable CP1 have FP support,
no UDI implemented, no CP2 implemented, 1 CP1 implemented. */
@@ -572,8 +573,7 @@ static int cpu_mips_register (CPUMIPSState *env, const mips_def_t *def)
env->insn_flags = def->insn_flags;
#ifndef CONFIG_USER_ONLY
- if (!env->user_mode_only)
- mmu_init(env, def);
+ mmu_init(env, def);
#endif
fpu_init(env, def);
mvp_init(env, def);
diff --git a/target-ppc/helper.h b/target-ppc/helper.h
index f319fdb5e..755bfbae4 100644
--- a/target-ppc/helper.h
+++ b/target-ppc/helper.h
@@ -123,6 +123,24 @@ DEF_HELPER_3(vminuw, void, avr, avr, avr)
DEF_HELPER_3(vmaxub, void, avr, avr, avr)
DEF_HELPER_3(vmaxuh, void, avr, avr, avr)
DEF_HELPER_3(vmaxuw, void, avr, avr, avr)
+DEF_HELPER_3(vcmpequb, void, avr, avr, avr)
+DEF_HELPER_3(vcmpequh, void, avr, avr, avr)
+DEF_HELPER_3(vcmpequw, void, avr, avr, avr)
+DEF_HELPER_3(vcmpgtub, void, avr, avr, avr)
+DEF_HELPER_3(vcmpgtuh, void, avr, avr, avr)
+DEF_HELPER_3(vcmpgtuw, void, avr, avr, avr)
+DEF_HELPER_3(vcmpgtsb, void, avr, avr, avr)
+DEF_HELPER_3(vcmpgtsh, void, avr, avr, avr)
+DEF_HELPER_3(vcmpgtsw, void, avr, avr, avr)
+DEF_HELPER_3(vcmpequb_dot, void, avr, avr, avr)
+DEF_HELPER_3(vcmpequh_dot, void, avr, avr, avr)
+DEF_HELPER_3(vcmpequw_dot, void, avr, avr, avr)
+DEF_HELPER_3(vcmpgtub_dot, void, avr, avr, avr)
+DEF_HELPER_3(vcmpgtuh_dot, void, avr, avr, avr)
+DEF_HELPER_3(vcmpgtuw_dot, void, avr, avr, avr)
+DEF_HELPER_3(vcmpgtsb_dot, void, avr, avr, avr)
+DEF_HELPER_3(vcmpgtsh_dot, void, avr, avr, avr)
+DEF_HELPER_3(vcmpgtsw_dot, void, avr, avr, avr)
DEF_HELPER_3(vmrglb, void, avr, avr, avr)
DEF_HELPER_3(vmrglh, void, avr, avr, avr)
DEF_HELPER_3(vmrglw, void, avr, avr, avr)
@@ -152,10 +170,27 @@ DEF_HELPER_3(vaddcuw, void, avr, avr, avr)
DEF_HELPER_3(vsubcuw, void, avr, avr, avr)
DEF_HELPER_2(lvsl, void, avr, tl);
DEF_HELPER_2(lvsr, void, avr, tl);
+DEF_HELPER_3(vaddsbs, void, avr, avr, avr)
+DEF_HELPER_3(vaddshs, void, avr, avr, avr)
+DEF_HELPER_3(vaddsws, void, avr, avr, avr)
+DEF_HELPER_3(vsubsbs, void, avr, avr, avr)
+DEF_HELPER_3(vsubshs, void, avr, avr, avr)
+DEF_HELPER_3(vsubsws, void, avr, avr, avr)
+DEF_HELPER_3(vaddubs, void, avr, avr, avr)
+DEF_HELPER_3(vadduhs, void, avr, avr, avr)
+DEF_HELPER_3(vadduws, void, avr, avr, avr)
+DEF_HELPER_3(vsububs, void, avr, avr, avr)
+DEF_HELPER_3(vsubuhs, void, avr, avr, avr)
+DEF_HELPER_3(vsubuws, void, avr, avr, avr)
DEF_HELPER_3(vrlb, void, avr, avr, avr)
DEF_HELPER_3(vrlh, void, avr, avr, avr)
DEF_HELPER_3(vrlw, void, avr, avr, avr)
+DEF_HELPER_3(vsl, void, avr, avr, avr)
+DEF_HELPER_3(vsr, void, avr, avr, avr)
DEF_HELPER_4(vsldoi, void, avr, avr, avr, i32)
+DEF_HELPER_2(vspltisb, void, avr, i32)
+DEF_HELPER_2(vspltish, void, avr, i32)
+DEF_HELPER_2(vspltisw, void, avr, i32)
DEF_HELPER_3(vspltb, void, avr, avr, i32)
DEF_HELPER_3(vsplth, void, avr, avr, i32)
DEF_HELPER_3(vspltw, void, avr, avr, i32)
diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
index 5e40e42ea..c931adbd9 100644
--- a/target-ppc/op_helper.c
+++ b/target-ppc/op_helper.c
@@ -2082,6 +2082,45 @@ VARITH(uwm, u32)
#undef VARITH_DO
#undef VARITH
+#define VARITHSAT_CASE(type, op, cvt, element) \
+ { \
+ type result = (type)a->element[i] op (type)b->element[i]; \
+ r->element[i] = cvt(result, &sat); \
+ }
+
+#define VARITHSAT_DO(name, op, optype, cvt, element) \
+ void helper_v##name (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
+ { \
+ int sat = 0; \
+ int i; \
+ for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
+ switch (sizeof(r->element[0])) { \
+ case 1: VARITHSAT_CASE(optype, op, cvt, element); break; \
+ case 2: VARITHSAT_CASE(optype, op, cvt, element); break; \
+ case 4: VARITHSAT_CASE(optype, op, cvt, element); break; \
+ } \
+ } \
+ if (sat) { \
+ env->vscr |= (1 << VSCR_SAT); \
+ } \
+ }
+#define VARITHSAT_SIGNED(suffix, element, optype, cvt) \
+ VARITHSAT_DO(adds##suffix##s, +, optype, cvt, element) \
+ VARITHSAT_DO(subs##suffix##s, -, optype, cvt, element)
+#define VARITHSAT_UNSIGNED(suffix, element, optype, cvt) \
+ VARITHSAT_DO(addu##suffix##s, +, optype, cvt, element) \
+ VARITHSAT_DO(subu##suffix##s, -, optype, cvt, element)
+VARITHSAT_SIGNED(b, s8, int16_t, cvtshsb)
+VARITHSAT_SIGNED(h, s16, int32_t, cvtswsh)
+VARITHSAT_SIGNED(w, s32, int64_t, cvtsdsw)
+VARITHSAT_UNSIGNED(b, u8, uint16_t, cvtshub)
+VARITHSAT_UNSIGNED(h, u16, uint32_t, cvtswuh)
+VARITHSAT_UNSIGNED(w, u32, uint64_t, cvtsduw)
+#undef VARITHSAT_CASE
+#undef VARITHSAT_DO
+#undef VARITHSAT_SIGNED
+#undef VARITHSAT_UNSIGNED
+
#define VAVG_DO(name, element, etype) \
void helper_v##name (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
{ \
@@ -2101,6 +2140,42 @@ VAVG(w, s32, int64_t, u32, uint64_t)
#undef VAVG_DO
#undef VAVG
+#define VCMP_DO(suffix, compare, element, record) \
+ void helper_vcmp##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
+ { \
+ uint32_t ones = (uint32_t)-1; \
+ uint32_t all = ones; \
+ uint32_t none = 0; \
+ int i; \
+ for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
+ uint32_t result = (a->element[i] compare b->element[i] ? ones : 0x0); \
+ switch (sizeof (a->element[0])) { \
+ case 4: r->u32[i] = result; break; \
+ case 2: r->u16[i] = result; break; \
+ case 1: r->u8[i] = result; break; \
+ } \
+ all &= result; \
+ none |= result; \
+ } \
+ if (record) { \
+ env->crf[6] = ((all != 0) << 3) | ((none == 0) << 1); \
+ } \
+ }
+#define VCMP(suffix, compare, element) \
+ VCMP_DO(suffix, compare, element, 0) \
+ VCMP_DO(suffix##_dot, compare, element, 1)
+VCMP(equb, ==, u8)
+VCMP(equh, ==, u16)
+VCMP(equw, ==, u32)
+VCMP(gtub, >, u8)
+VCMP(gtuh, >, u16)
+VCMP(gtuw, >, u32)
+VCMP(gtsb, >, s8)
+VCMP(gtsh, >, s16)
+VCMP(gtsw, >, s32)
+#undef VCMP_DO
+#undef VCMP
+
void helper_vmhaddshs (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
{
int sat = 0;
@@ -2416,6 +2491,45 @@ void helper_vsel (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
r->u64[1] = (a->u64[1] & ~c->u64[1]) | (b->u64[1] & c->u64[1]);
}
+#if defined(WORDS_BIGENDIAN)
+#define LEFT 0
+#define RIGHT 1
+#else
+#define LEFT 1
+#define RIGHT 0
+#endif
+/* The specification says that the results are undefined if all of the
+ * shift counts are not identical. We check to make sure that they are
+ * to conform to what real hardware appears to do. */
+#define VSHIFT(suffix, leftp) \
+ void helper_vs##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
+ { \
+ int shift = b->u8[LO_IDX*0x15] & 0x7; \
+ int doit = 1; \
+ int i; \
+ for (i = 0; i < ARRAY_SIZE(r->u8); i++) { \
+ doit = doit && ((b->u8[i] & 0x7) == shift); \
+ } \
+ if (doit) { \
+ if (shift == 0) { \
+ *r = *a; \
+ } else if (leftp) { \
+ uint64_t carry = a->u64[LO_IDX] >> (64 - shift); \
+ r->u64[HI_IDX] = (a->u64[HI_IDX] << shift) | carry; \
+ r->u64[LO_IDX] = a->u64[LO_IDX] << shift; \
+ } else { \
+ uint64_t carry = a->u64[HI_IDX] << (64 - shift); \
+ r->u64[LO_IDX] = (a->u64[LO_IDX] >> shift) | carry; \
+ r->u64[HI_IDX] = a->u64[HI_IDX] >> shift; \
+ } \
+ } \
+ }
+VSHIFT(l, LEFT)
+VSHIFT(r, RIGHT)
+#undef VSHIFT
+#undef LEFT
+#undef RIGHT
+
#define VSL(suffix, element) \
void helper_vsl##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
{ \
@@ -2495,6 +2609,20 @@ VSPLT(w, u32)
#undef SPLAT_ELEMENT
#undef _SPLAT_MASKED
+#define VSPLTI(suffix, element, splat_type) \
+ void helper_vspltis##suffix (ppc_avr_t *r, uint32_t splat) \
+ { \
+ splat_type x = (int8_t)(splat << 3) >> 3; \
+ int i; \
+ for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
+ r->element[i] = x; \
+ } \
+ }
+VSPLTI(b, s8, int8_t)
+VSPLTI(h, s16, int16_t)
+VSPLTI(w, s32, int32_t)
+#undef VSPLTI
+
#define VSR(suffix, element) \
void helper_vsr##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
{ \
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 03dac58e7..0cfcc0872 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -4152,6 +4152,33 @@ GEN_HANDLER2(dcbz_970, "dcbz", 0x1F, 0x16, 0x1F, 0x03C00001, PPC_CACHE_DCBZT)
tcg_temp_free(t0);
}
+/* dst / dstt */
+GEN_HANDLER(dst, 0x1F, 0x16, 0x0A, 0x01800001, PPC_ALTIVEC)
+{
+ if (rA(ctx->opcode) == 0) {
+ gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
+ } else {
+ /* interpreted as no-op */
+ }
+}
+
+/* dstst /dststt */
+GEN_HANDLER(dstst, 0x1F, 0x16, 0x0B, 0x02000001, PPC_ALTIVEC)
+{
+ if (rA(ctx->opcode) == 0) {
+ gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
+ } else {
+ /* interpreted as no-op */
+ }
+
+}
+
+/* dss / dssall */
+GEN_HANDLER(dss, 0x1F, 0x16, 0x19, 0x019FF801, PPC_ALTIVEC)
+{
+ /* interpreted as no-op */
+}
+
/* icbi */
GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE_ICBI)
{
@@ -6341,9 +6368,23 @@ GEN_VXFORM(vslo, 6, 16);
GEN_VXFORM(vsro, 6, 17);
GEN_VXFORM(vaddcuw, 0, 6);
GEN_VXFORM(vsubcuw, 0, 22);
+GEN_VXFORM(vaddubs, 0, 8);
+GEN_VXFORM(vadduhs, 0, 9);
+GEN_VXFORM(vadduws, 0, 10);
+GEN_VXFORM(vaddsbs, 0, 12);
+GEN_VXFORM(vaddshs, 0, 13);
+GEN_VXFORM(vaddsws, 0, 14);
+GEN_VXFORM(vsububs, 0, 24);
+GEN_VXFORM(vsubuhs, 0, 25);
+GEN_VXFORM(vsubuws, 0, 26);
+GEN_VXFORM(vsubsbs, 0, 28);
+GEN_VXFORM(vsubshs, 0, 29);
+GEN_VXFORM(vsubsws, 0, 30);
GEN_VXFORM(vrlb, 2, 0);
GEN_VXFORM(vrlh, 2, 1);
GEN_VXFORM(vrlw, 2, 2);
+GEN_VXFORM(vsl, 2, 7);
+GEN_VXFORM(vsr, 2, 11);
GEN_VXFORM(vpkuhum, 7, 0);
GEN_VXFORM(vpkuwum, 7, 1);
GEN_VXFORM(vpkuhus, 7, 2);
@@ -6359,6 +6400,57 @@ GEN_VXFORM(vsum4shs, 4, 25);
GEN_VXFORM(vsum2sws, 4, 26);
GEN_VXFORM(vsumsws, 4, 30);
+#define GEN_VXRFORM1(opname, name, str, opc2, opc3) \
+ GEN_HANDLER2(name, str, 0x4, opc2, opc3, 0x00000000, PPC_ALTIVEC) \
+ { \
+ TCGv_ptr ra, rb, rd; \
+ if (unlikely(!ctx->altivec_enabled)) { \
+ gen_exception(ctx, POWERPC_EXCP_VPU); \
+ return; \
+ } \
+ ra = gen_avr_ptr(rA(ctx->opcode)); \
+ rb = gen_avr_ptr(rB(ctx->opcode)); \
+ rd = gen_avr_ptr(rD(ctx->opcode)); \
+ gen_helper_##opname (rd, ra, rb); \
+ tcg_temp_free_ptr(ra); \
+ tcg_temp_free_ptr(rb); \
+ tcg_temp_free_ptr(rd); \
+ }
+
+#define GEN_VXRFORM(name, opc2, opc3) \
+ GEN_VXRFORM1(name, name, #name, opc2, opc3) \
+ GEN_VXRFORM1(name##_dot, name##_, #name ".", opc2, (opc3 | (0x1 << 4)))
+
+GEN_VXRFORM(vcmpequb, 3, 0)
+GEN_VXRFORM(vcmpequh, 3, 1)
+GEN_VXRFORM(vcmpequw, 3, 2)
+GEN_VXRFORM(vcmpgtsb, 3, 12)
+GEN_VXRFORM(vcmpgtsh, 3, 13)
+GEN_VXRFORM(vcmpgtsw, 3, 14)
+GEN_VXRFORM(vcmpgtub, 3, 8)
+GEN_VXRFORM(vcmpgtuh, 3, 9)
+GEN_VXRFORM(vcmpgtuw, 3, 10)
+
+#define GEN_VXFORM_SIMM(name, opc2, opc3) \
+ GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC) \
+ { \
+ TCGv_ptr rd; \
+ TCGv_i32 simm; \
+ if (unlikely(!ctx->altivec_enabled)) { \
+ gen_exception(ctx, POWERPC_EXCP_VPU); \
+ return; \
+ } \
+ simm = tcg_const_i32(SIMM5(ctx->opcode)); \
+ rd = gen_avr_ptr(rD(ctx->opcode)); \
+ gen_helper_##name (rd, simm); \
+ tcg_temp_free_i32(simm); \
+ tcg_temp_free_ptr(rd); \
+ }
+
+GEN_VXFORM_SIMM(vspltisb, 6, 12);
+GEN_VXFORM_SIMM(vspltish, 6, 13);
+GEN_VXFORM_SIMM(vspltisw, 6, 14);
+
#define GEN_VXFORM_NOA(name, opc2, opc3) \
GEN_HANDLER(name, 0x04, opc2, opc3, 0x001f0000, PPC_ALTIVEC) \
{ \
diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index 7943e12bf..d2865ee7d 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -402,12 +402,12 @@ static int get_physical_address_data(CPUState *env,
mask = 0xffffffffffc00000ULL;
break;
}
- // ctx match, vaddr match?
+ // ctx match, vaddr match, valid?
if (env->dmmuregs[1] == (env->dtlb_tag[i] & 0x1fff) &&
- (address & mask) == (env->dtlb_tag[i] & ~0x1fffULL)) {
- // valid, access ok?
- if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0 ||
- ((env->dtlb_tte[i] & 0x4) && is_user) ||
+ (address & mask) == (env->dtlb_tag[i] & ~0x1fffULL) &&
+ (env->dtlb_tte[i] & 0x8000000000000000ULL)) {
+ // access ok?
+ if (((env->dtlb_tte[i] & 0x4) && is_user) ||
(!(env->dtlb_tte[i] & 0x2) && (rw == 1))) {
if (env->dmmuregs[3]) /* Fault status register */
env->dmmuregs[3] = 2; /* overflow (not read before
@@ -465,12 +465,12 @@ static int get_physical_address_code(CPUState *env,
mask = 0xffffffffffc00000ULL;
break;
}
- // ctx match, vaddr match?
+ // ctx match, vaddr match, valid?
if (env->dmmuregs[1] == (env->itlb_tag[i] & 0x1fff) &&
- (address & mask) == (env->itlb_tag[i] & ~0x1fffULL)) {
- // valid, access ok?
- if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0 ||
- ((env->itlb_tte[i] & 0x4) && is_user)) {
+ (address & mask) == (env->itlb_tag[i] & ~0x1fffULL) &&
+ (env->itlb_tte[i] & 0x8000000000000000ULL)) {
+ // access ok?
+ if ((env->itlb_tte[i] & 0x4) && is_user) {
if (env->immuregs[3]) /* Fault status register */
env->immuregs[3] = 2; /* overflow (not read before
another fault) */
diff --git a/vl.c b/vl.c
index d0660aba1..7a36870fe 100644
--- a/vl.c
+++ b/vl.c
@@ -4435,6 +4435,8 @@ struct soundhw soundhw[] = {
{ .init_isa = pcspk_audio_init }
},
#endif
+
+#ifdef CONFIG_SB16
{
"sb16",
"Creative Sound Blaster 16",
@@ -4442,6 +4444,7 @@ struct soundhw soundhw[] = {
1,
{ .init_isa = SB16_init }
},
+#endif
#ifdef CONFIG_CS4231A
{
@@ -4487,6 +4490,7 @@ struct soundhw soundhw[] = {
},
#endif
+#ifdef CONFIG_ES1370
{
"es1370",
"ENSONIQ AudioPCI ES1370",
@@ -4496,6 +4500,8 @@ struct soundhw soundhw[] = {
},
#endif
+#endif /* HAS_AUDIO_CHOICE */
+
{ NULL, NULL, 0, 0, { NULL } }
};