WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] merge?

# HG changeset patch
# User shand@xxxxxxxxxxxxxxxxxxxxxxxxxxx
# Node ID f0dc15fd3c1bcfc63e432e7fb365792cc671e955
# Parent  dd108e5ad24de2ccabc1fbf3a649d55754e5368c
# Parent  8af8ddf9107832cfe509ffe8e9f7ee65856b2fa3
merge?

diff -r dd108e5ad24d -r f0dc15fd3c1b 
linux-2.6-xen-sparse/arch/xen/i386/kernel/acpi/boot.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/acpi/boot.c     Wed Aug 31 
22:37:21 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/acpi/boot.c     Wed Aug 31 
23:22:45 2005
@@ -468,6 +468,18 @@
 {
        unsigned int irq;
        unsigned int plat_gsi = gsi;
+
+#ifdef CONFIG_PCI
+       /*
+        * Make sure all (legacy) PCI IRQs are set as level-triggered.
+        */
+       if (acpi_irq_model == ACPI_IRQ_MODEL_PIC) {
+               extern void eisa_set_level_irq(unsigned int irq);
+
+               if (edge_level == ACPI_LEVEL_SENSITIVE)
+                               eisa_set_level_irq(gsi);
+       }
+#endif
 
 #ifdef CONFIG_X86_IO_APIC
        if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC) {
diff -r dd108e5ad24d -r f0dc15fd3c1b 
linux-2.6-xen-sparse/include/asm-xen/asm-i386/system.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/system.h    Wed Aug 31 
22:37:21 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/system.h    Wed Aug 31 
23:22:45 2005
@@ -561,8 +561,14 @@
 #define local_irq_disable()    __cli()
 #define local_irq_enable()     __sti()
 
+/* Don't use smp_processor_id: this is called in debug versions of that fn. */
+#ifdef CONFIG_SMP
 #define irqs_disabled()                        \
-    HYPERVISOR_shared_info->vcpu_data[smp_processor_id()].evtchn_upcall_mask
+    HYPERVISOR_shared_info->vcpu_data[__smp_processor_id()].evtchn_upcall_mask
+#else
+#define irqs_disabled()                        \
+    HYPERVISOR_shared_info->vcpu_data[0].evtchn_upcall_mask
+#endif
 
 /*
  * disable hlt during certain critical i/o operations
diff -r dd108e5ad24d -r f0dc15fd3c1b 
linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/system.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/system.h  Wed Aug 31 
22:37:21 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/system.h  Wed Aug 31 
23:22:45 2005
@@ -387,8 +387,14 @@
 #define local_irq_disable()    __cli()
 #define local_irq_enable()     __sti()
 
+/* Don't use smp_processor_id: this is called in debug versions of that fn. */
+#ifdef CONFIG_SMP
 #define irqs_disabled()                        \
-    HYPERVISOR_shared_info->vcpu_data[smp_processor_id()].evtchn_upcall_mask
+    HYPERVISOR_shared_info->vcpu_data[__smp_processor_id()].evtchn_upcall_mask
+#else
+#define irqs_disabled()                        \
+    HYPERVISOR_shared_info->vcpu_data[0].evtchn_upcall_mask
+#endif
 
 /*
  * disable hlt during certain critical i/o operations
diff -r dd108e5ad24d -r f0dc15fd3c1b tools/console/client/main.c
--- a/tools/console/client/main.c       Wed Aug 31 22:37:21 2005
+++ b/tools/console/client/main.c       Wed Aug 31 23:22:45 2005
@@ -176,6 +176,7 @@
        unsigned int len = 0;
        struct xs_handle *xs;
        char *end;
+       time_t now;
 
        while((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) {
                switch(ch) {
@@ -215,13 +216,37 @@
 
        snprintf(path, sizeof(path), "/console/%d/tty", domid);
        str_pty = xs_read(xs, path, &len);
+
        /* FIXME consoled currently does not assume domain-0 doesn't have a
           console which is good when we break domain-0 up.  To keep us
           user friendly, we'll bail out here since no data will ever show
           up on domain-0. */
-       if (domid == 0 || str_pty == NULL) {
+       if (domid == 0) {
                err(errno, "Could not read tty from store");
        }
+
+       /* Wait a little bit for tty to appear.  There is a race
+          condition that occurs after xend creates a domain.  This
+          code might be running before consoled has noticed the new
+          domain and setup a pty for it.
+
+          A xenstore watch would slightly improve responsiveness but
+          a timeout would still be needed since we don't want to
+          block forever if given an invalid domain or worse yet, a
+          domain that someone else has connected to. */
+
+       now = time(0);
+       while (str_pty == NULL && (now + 5) > time(0)) {
+               struct timeval tv = { 0, 500 };
+               select(0, NULL, NULL, NULL, &tv); /* pause briefly */
+
+               str_pty = xs_read(xs, path, &len);
+       }
+
+       if (str_pty == NULL) {
+               err(errno, "Could not read tty from store");
+       }
+
        spty = open(str_pty, O_RDWR | O_NOCTTY);
        if (spty == -1) {
                err(errno, "Could not open tty `%s'", str_pty);
diff -r dd108e5ad24d -r f0dc15fd3c1b tools/console/daemon/io.c
--- a/tools/console/daemon/io.c Wed Aug 31 22:37:21 2005
+++ b/tools/console/daemon/io.c Wed Aug 31 23:22:45 2005
@@ -215,9 +215,6 @@
        char *dompath, *path;
        int err;
 
-       dom->page = NULL;
-       dom->evtchn_fd = -1;
-
        asprintf(&path, "/console/%d/domain", dom->domid);
        dompath = xs_read(xs, path, NULL);
        free(path);
@@ -232,28 +229,35 @@
        if (err)
                goto out;
 
-       dom->page = xc_map_foreign_range(xc, dom->domid, getpagesize(),
-                                        PROT_READ|PROT_WRITE, dom->mfn);
        if (dom->page == NULL) {
-               err = EINVAL;
-               goto out;
-       }
-
-       /* Opening evtchn independently for each console is a bit
-        * wastefule, but that's how the code is structured... */
-       err = open("/dev/xen/evtchn", O_RDWR);
-       if (err == -1) {
-               err = errno;
-               goto out;
-       }
-       dom->evtchn_fd = err;
-
-       if (ioctl(dom->evtchn_fd, EVENTCHN_BIND, dom->local_port) == -1) {
-               err = errno;
-               munmap(dom->page, getpagesize());
-               close(dom->evtchn_fd);
-               dom->evtchn_fd = -1;
-               goto out;
+               dom->page = xc_map_foreign_range(xc, dom->domid, getpagesize(),
+                                                PROT_READ|PROT_WRITE,
+                                                dom->mfn);
+               if (dom->page == NULL) {
+                       err = EINVAL;
+                       goto out;
+               }
+       }
+
+       if (dom->evtchn_fd == -1) {
+               /* Opening evtchn independently for each console is a bit
+                * wastefule, but that's how the code is structured... */
+               err = open("/dev/xen/evtchn", O_RDWR);
+               if (err == -1) {
+                       err = errno;
+                       goto out;
+               }
+               dom->evtchn_fd = err;
+ 
+               if (ioctl(dom->evtchn_fd, EVENTCHN_BIND,
+                         dom->local_port) == -1) {
+                       err = errno;
+                       munmap(dom->page, getpagesize());
+                       dom->page = NULL;
+                       close(dom->evtchn_fd);
+                       dom->evtchn_fd = -1;
+                       goto out;
+               }
        }
 
  out:
@@ -281,6 +285,9 @@
        dom->buffer.max_capacity = 0;
        dom->next = NULL;
 
+       dom->page = NULL;
+       dom->evtchn_fd = -1;
+
        domain_create_ring(dom);
 
        dolog(LOG_DEBUG, "New domain %d", domid);
@@ -290,22 +297,19 @@
 
 static struct domain *lookup_domain(int domid)
 {
-       struct domain **pp;
-
-       for (pp = &dom_head; *pp; pp = &(*pp)->next) {
-               struct domain *dom = *pp;
-
-               if (dom->domid == domid) {
+       struct domain *dom;
+
+       for (dom = dom_head; dom; dom = dom->next)
+               if (dom->domid == domid)
                        return dom;
-               } else if (dom->domid > domid) {
-                       *pp = create_domain(domid);
-                       (*pp)->next = dom;
-                       return *pp;
-               }
-       }
-
-       *pp = create_domain(domid);
-       return *pp;
+
+       dom = create_domain(domid);
+       if (!dom)
+               return NULL;
+       dom->next = dom_head;
+       dom_head = dom;
+
+       return dom;
 }
 
 static void remove_domain(struct domain *dom)
@@ -345,6 +349,20 @@
        }
 }
 
+void enum_domains(void)
+{
+       int domid = 1;
+       xc_dominfo_t dominfo;
+       struct domain *dom;
+
+       while (xc_domain_getinfo(xc, domid, 1, &dominfo) == 1) {
+               dom = lookup_domain(dominfo.domid);
+               if (dominfo.dying || dominfo.crashed || dominfo.shutdown)
+                       dom->is_dead = true;
+               domid = dominfo.domid + 1;
+       }
+}
+
 static void handle_tty_read(struct domain *dom)
 {
        ssize_t len;
@@ -353,7 +371,7 @@
                (struct ring_head *)(dom->page + PAGE_SIZE/2);
        int i;
 
-       len = read(dom->tty_fd, msg, MAX(XENCONS_SPACE(inring), sizeof(msg)));
+       len = read(dom->tty_fd, msg, MIN(XENCONS_SPACE(inring), sizeof(msg)));
        if (len < 1) {
                close(dom->tty_fd);
                dom->tty_fd = -1;
@@ -415,20 +433,28 @@
                dolog(LOG_ERR, "read from xcs failed! %m");
                exit(1);
        }
-}
-
-static void enum_domains(void)
-{
-       int domid = 0;
-       xc_dominfo_t dominfo;
+
+       enum_domains();
+}
+
+static void handle_xs(int fd)
+{
+       char **vec;
+       int domid;
        struct domain *dom;
 
-       while (xc_domain_getinfo(xc, domid, 1, &dominfo) == 1) {
-               dom = lookup_domain(dominfo.domid);
-               if (dominfo.dying || dominfo.crashed || dominfo.shutdown)
-                       dom->is_dead = true;
-               domid = dominfo.domid + 1;
-       }
+       vec = xs_read_watch(xs);
+       if (!vec)
+               return;
+
+       if (sscanf(vec[0], "/console/%d", &domid) == 1) {
+               dom = lookup_domain(domid);
+               if (dom && (dom->evtchn_fd == -1 || dom->page == NULL))
+                       domain_create_ring(dom);
+       }
+
+       xs_acknowledge_watch(xs, vec[1]);
+       free(vec);
 }
 
 void handle_io(void)
@@ -438,7 +464,7 @@
 
        do {
                struct domain *d;
-               struct timeval tv = { 1, 0 };
+               struct timeval tv = { 100, 0 };
                int max_fd = -1;
 
                FD_ZERO(&readfds);
@@ -446,6 +472,9 @@
 
                FD_SET(xcs_data_fd, &readfds);
                max_fd = MAX(xcs_data_fd, max_fd);
+
+               FD_SET(xs_fileno(xs), &readfds);
+               max_fd = MAX(xs_fileno(xs), max_fd);
 
                for (d = dom_head; d; d = d->next) {
                        if (d->tty_fd != -1) {
@@ -463,7 +492,9 @@
                }
 
                ret = select(max_fd + 1, &readfds, &writefds, 0, &tv);
-               enum_domains();
+
+               if (FD_ISSET(xs_fileno(xs), &readfds))
+                       handle_xs(xs_fileno(xs));
 
                if (FD_ISSET(xcs_data_fd, &readfds))
                        handle_xcs_msg(xcs_data_fd);
diff -r dd108e5ad24d -r f0dc15fd3c1b tools/console/daemon/io.h
--- a/tools/console/daemon/io.h Wed Aug 31 22:37:21 2005
+++ b/tools/console/daemon/io.h Wed Aug 31 23:22:45 2005
@@ -21,6 +21,7 @@
 #ifndef CONSOLED_IO_H
 #define CONSOLED_IO_H
 
+void enum_domains(void);
 void handle_io(void);
 
 #endif
diff -r dd108e5ad24d -r f0dc15fd3c1b tools/console/daemon/main.c
--- a/tools/console/daemon/main.c       Wed Aug 31 22:37:21 2005
+++ b/tools/console/daemon/main.c       Wed Aug 31 23:22:45 2005
@@ -85,6 +85,8 @@
 
        xen_setup();
 
+       enum_domains();
+
        handle_io();
 
        closelog();
diff -r dd108e5ad24d -r f0dc15fd3c1b tools/console/daemon/utils.c
--- a/tools/console/daemon/utils.c      Wed Aug 31 22:37:21 2005
+++ b/tools/console/daemon/utils.c      Wed Aug 31 23:22:45 2005
@@ -232,11 +232,16 @@
                dolog(LOG_ERR, "xcs virq bind failed.  Possible bug.");
                goto out_close_data;
        }
-       
+
+       if (!xs_watch(xs, "/console", "console")) {
+               dolog(LOG_ERR, "xenstore watch on /console failes.");
+               goto out_close_data;
+       }
+
        return true;
 
  out_close_data:
-       close(xcs_ctrl_fd);
+       close(xcs_data_fd);
        xcs_data_fd = -1;
  out_close_ctrl:
        close(xcs_ctrl_fd);
diff -r dd108e5ad24d -r f0dc15fd3c1b tools/examples/xmexample.vmx
--- a/tools/examples/xmexample.vmx      Wed Aug 31 22:37:21 2005
+++ b/tools/examples/xmexample.vmx      Wed Aug 31 23:22:45 2005
@@ -73,6 +73,10 @@
 vnc=1
 
 #----------------------------------------------------------------------------
+# enable spawning vncviewer(only valid when vnc=1), default = 1
+vncviewer=1
+
+#----------------------------------------------------------------------------
 # no graphics, use serial port
 #nographic=0
 
diff -r dd108e5ad24d -r f0dc15fd3c1b tools/ioemu/cpu-all.h
--- a/tools/ioemu/cpu-all.h     Wed Aug 31 22:37:21 2005
+++ b/tools/ioemu/cpu-all.h     Wed Aug 31 23:22:45 2005
@@ -672,6 +672,8 @@
 int cpu_memory_rw_debug(CPUState *env, target_ulong addr, 
                         uint8_t *buf, int len, int is_write);
 
+#define VGA_DIRTY_FLAG 0x01
+
 /* read dirty bit (return 0 or 1) */
 static inline int cpu_physical_memory_is_dirty(target_ulong addr)
 {
diff -r dd108e5ad24d -r f0dc15fd3c1b tools/ioemu/exec.c
--- a/tools/ioemu/exec.c        Wed Aug 31 22:37:21 2005
+++ b/tools/ioemu/exec.c        Wed Aug 31 23:22:45 2005
@@ -461,4 +461,14 @@
 
 void cpu_physical_memory_reset_dirty(target_ulong start, target_ulong end)
 {
-}
+       uint8_t *p;
+       int len;
+
+       if ((len = (end - start)) <= 0)
+               return;
+       p = phys_ram_dirty + (start >> TARGET_PAGE_BITS);
+       len = len >> TARGET_PAGE_BITS;
+       while (len > 0)
+               p[--len] &= ~VGA_DIRTY_FLAG;
+       return;
+}
diff -r dd108e5ad24d -r f0dc15fd3c1b tools/ioemu/hw/pc.c
--- a/tools/ioemu/hw/pc.c       Wed Aug 31 22:37:21 2005
+++ b/tools/ioemu/hw/pc.c       Wed Aug 31 23:22:45 2005
@@ -540,7 +540,10 @@
 
     if (pci_enabled) {
         for(i = 0; i < nb_nics; i++) {
-            pci_ne2000_init(pci_bus, &nd_table[i]);
+            if (nic_pcnet)
+                pci_pcnet_init(pci_bus, &nd_table[i]);
+            else
+                pci_ne2000_init(pci_bus, &nd_table[i]); 
         }
         pci_piix3_ide_init(pci_bus, bs_table);
 #ifdef APIC_SUPPORT
diff -r dd108e5ad24d -r f0dc15fd3c1b tools/ioemu/hw/vga.c
--- a/tools/ioemu/hw/vga.c      Wed Aug 31 22:37:21 2005
+++ b/tools/ioemu/hw/vga.c      Wed Aug 31 23:22:45 2005
@@ -1620,7 +1620,6 @@
 static void vga_save(QEMUFile *f, void *opaque)
 {
     VGAState *s = opaque;
-    int i;
 
     qemu_put_be32s(f, &s->latch);
     qemu_put_8s(f, &s->sr_index);
@@ -1661,7 +1660,7 @@
 static int vga_load(QEMUFile *f, void *opaque, int version_id)
 {
     VGAState *s = opaque;
-    int is_vbe, i;
+    int is_vbe;
 
     if (version_id != 1)
         return -EINVAL;
diff -r dd108e5ad24d -r f0dc15fd3c1b tools/ioemu/target-i386-dm/Makefile
--- a/tools/ioemu/target-i386-dm/Makefile       Wed Aug 31 22:37:21 2005
+++ b/tools/ioemu/target-i386-dm/Makefile       Wed Aug 31 23:22:45 2005
@@ -272,7 +272,7 @@
 # Hardware support
 VL_OBJS+= ide.o ne2000.o pckbd.o vga.o dma.o
 VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pc.o port-e9.o
-VL_OBJS+= cirrus_vga.o
+VL_OBJS+= cirrus_vga.o pcnet.o
 
 ifeq ($(TARGET_ARCH), ppc)
 VL_OBJS+= ppc.o ide.o ne2000.o pckbd.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
diff -r dd108e5ad24d -r f0dc15fd3c1b tools/ioemu/vl.c
--- a/tools/ioemu/vl.c  Wed Aug 31 22:37:21 2005
+++ b/tools/ioemu/vl.c  Wed Aug 31 23:22:45 2005
@@ -125,6 +125,7 @@
 QEMUTimer *polling_timer;
 int vm_running;
 int audio_enabled = 0;
+int nic_pcnet = 1;
 int sb16_enabled = 1;
 int adlib_enabled = 1;
 int gus_enabled = 1;
@@ -2115,6 +2116,7 @@
            "-prep           Simulate a PREP system (default is PowerMAC)\n"
            "-g WxH[xDEPTH]  Set the initial VGA graphic mode\n"
 #endif
+           "-nic-pcnet     simulate an AMD PC-Net PCI ethernet adaptor\n"
            "\n"
            "Network options:\n"
            "-nics n         simulate 'n' network cards [default=1]\n"
@@ -2229,6 +2231,7 @@
     QEMU_OPTION_L,
     QEMU_OPTION_no_code_copy,
     QEMU_OPTION_pci,
+    QEMU_OPTION_nic_pcnet,
     QEMU_OPTION_isa,
     QEMU_OPTION_prep,
     QEMU_OPTION_k,
@@ -2313,6 +2316,7 @@
     
     /* temporary options */
     { "pci", 0, QEMU_OPTION_pci },
+    { "nic-pcnet", 0, QEMU_OPTION_nic_pcnet },
     { "cirrusvga", 0, QEMU_OPTION_cirrusvga },
     { NULL },
 };
@@ -2639,6 +2643,9 @@
                 break;
             case QEMU_OPTION_pci:
                 pci_enabled = 1;
+                break;
+            case QEMU_OPTION_nic_pcnet:
+                nic_pcnet = 1;
                 break;
             case QEMU_OPTION_isa:
                 pci_enabled = 0;
diff -r dd108e5ad24d -r f0dc15fd3c1b tools/ioemu/vl.h
--- a/tools/ioemu/vl.h  Wed Aug 31 22:37:21 2005
+++ b/tools/ioemu/vl.h  Wed Aug 31 23:22:45 2005
@@ -600,6 +600,12 @@
 void isa_ne2000_init(int base, int irq, NetDriverState *nd);
 void pci_ne2000_init(PCIBus *bus, NetDriverState *nd);
 
+/* pcnet.c */
+
+extern int nic_pcnet;
+
+void pci_pcnet_init(PCIBus *bus, NetDriverState *nd);
+
 /* pckbd.c */
 
 void kbd_init(void);
diff -r dd108e5ad24d -r f0dc15fd3c1b tools/libxc/xc_load_aout9.c
--- a/tools/libxc/xc_load_aout9.c       Wed Aug 31 22:37:21 2005
+++ b/tools/libxc/xc_load_aout9.c       Wed Aug 31 23:22:45 2005
@@ -15,6 +15,8 @@
 
 #define round_pgup(_p)    (((_p)+(PAGE_SIZE-1))&PAGE_MASK)
 #define round_pgdown(_p)  ((_p)&PAGE_MASK)
+#define KZERO             0x80000000
+#define KOFFSET(_p)       ((_p)&~KZERO)
 
 static int parseaout9image(char *, unsigned long, struct domain_setup_info *);
 static int loadaout9image(char *, unsigned long, int, u32, unsigned long *, 
struct domain_setup_info *);
@@ -63,7 +65,7 @@
     txtsz = round_pgup(ehdr.text);
     end = start + txtsz + ehdr.data + ehdr.bss;
 
-    dsi->v_start       = start;
+    dsi->v_start       = KZERO;
     dsi->v_kernstart   = start;
     dsi->v_kernend     = end;
     dsi->v_kernentry   = ehdr.entry;
@@ -83,19 +85,19 @@
     struct domain_setup_info *dsi)
 {
     struct Exec ehdr;
-    unsigned long txtsz;
+    unsigned long start, txtsz;
 
     if (!get_header(image, image_size, &ehdr)) {
         ERROR("Kernel image does not have a a.out9 header.");
         return -EINVAL;
     }
 
+    start = round_pgdown(ehdr.entry);
     txtsz = round_pgup(ehdr.text);
     copyout(xch, dom, parray, 
-            0, image, sizeof ehdr + ehdr.text);
+            start, image, sizeof ehdr + ehdr.text);
     copyout(xch, dom, parray, 
-            txtsz, image + sizeof ehdr + ehdr.text, ehdr.data);
-    /* XXX zeroing of BSS needed? */
+            start+txtsz, image + sizeof ehdr + ehdr.text, ehdr.data);
 
     /* XXX load symbols */
 
@@ -110,13 +112,14 @@
 copyout(
     int xch, u32 dom,
     unsigned long *parray,
-    unsigned long off,
+    unsigned long addr,
     void *buf,
     int sz)
 {
-    unsigned long pgoff, chunksz;
+    unsigned long pgoff, chunksz, off;
     void *pg;
 
+    off = KOFFSET(addr);
     while (sz > 0) {
         pgoff = off & (PAGE_SIZE-1);
         chunksz = sz;
diff -r dd108e5ad24d -r f0dc15fd3c1b tools/libxc/xc_private.c
--- a/tools/libxc/xc_private.c  Wed Aug 31 22:37:21 2005
+++ b/tools/libxc/xc_private.c  Wed Aug 31 23:22:45 2005
@@ -422,3 +422,8 @@
 {
     return do_dom0_op(xc_handle, op);
 }
+
+int xc_version(int xc_handle, int cmd, void *arg)
+{
+    return do_xen_version(xc_handle, cmd, arg);
+}
diff -r dd108e5ad24d -r f0dc15fd3c1b tools/libxc/xc_private.h
--- a/tools/libxc/xc_private.h  Wed Aug 31 22:37:21 2005
+++ b/tools/libxc/xc_private.h  Wed Aug 31 23:22:45 2005
@@ -59,6 +59,17 @@
                       (unsigned long)hypercall);
 }
 
+static inline int do_xen_version(int xc_handle, int cmd, void *dest)
+{
+    privcmd_hypercall_t hypercall;
+
+    hypercall.op     = __HYPERVISOR_xen_version;
+    hypercall.arg[0] = (unsigned long) cmd;
+    hypercall.arg[1] = (unsigned long) dest;
+    
+    return do_xen_hypercall(xc_handle, &hypercall);
+}
+
 static inline int do_dom0_op(int xc_handle, dom0_op_t *op)
 {
     int ret = -1;
diff -r dd108e5ad24d -r f0dc15fd3c1b tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h     Wed Aug 31 22:37:21 2005
+++ b/tools/libxc/xenctrl.h     Wed Aug 31 23:22:45 2005
@@ -23,6 +23,7 @@
 #include <sys/ptrace.h>
 #include <xen/xen.h>
 #include <xen/dom0_ops.h>
+#include <xen/version.h>
 #include <xen/event_channel.h>
 #include <xen/sched_ctl.h>
 #include <xen/acm.h>
@@ -497,6 +498,8 @@
 /* Execute a privileged dom0 operation. */
 int xc_dom0_op(int xc_handle, dom0_op_t *op);
 
+int xc_version(int xc_handle, int cmd, void *arg);
+
 /* Initializes the store (for dom0)
    remote_port should be the remote end of a bound interdomain channel between
    the store and dom0.
diff -r dd108e5ad24d -r f0dc15fd3c1b tools/python/xen/lowlevel/xc/xc.c
--- a/tools/python/xen/lowlevel/xc/xc.c Wed Aug 31 22:37:21 2005
+++ b/tools/python/xen/lowlevel/xc/xc.c Wed Aug 31 23:22:45 2005
@@ -707,6 +707,39 @@
                          "cpu_khz",          info.cpu_khz);
 }
 
+static PyObject *pyxc_xeninfo(PyObject *self,
+                              PyObject *args,
+                              PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+    xen_extraversion_t xen_extra;
+    xen_compile_info_t xen_cc;
+    xen_changeset_info_t xen_chgset;
+    long xen_version;
+
+    xen_version = xc_version(xc->xc_handle, XENVER_version, NULL);
+
+    if ( xc_version(xc->xc_handle, XENVER_extraversion, &xen_extra) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+
+    if ( xc_version(xc->xc_handle, XENVER_compile_info, &xen_cc) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+
+    if ( xc_version(xc->xc_handle, XENVER_changeset, &xen_chgset) != 0 )
+        return PyErr_SetFromErrno(xc_error);
+
+    return Py_BuildValue("{s:i,s:i,s:s,s:s,s:s,s:s,s:s,s:s}",
+                         "xen_major", xen_version >> 16,
+                         "xen_minor", (xen_version & 0xffff),
+                         "xen_extra", xen_extra,
+                         "xen_changeset", xen_chgset,
+                         "cc_compiler", xen_cc.compiler,
+                         "cc_compile_by", xen_cc.compile_by,
+                         "cc_compile_domain", xen_cc.compile_domain,
+                         "cc_compile_date", xen_cc.compile_date);
+}
+
+
 static PyObject *pyxc_sedf_domain_set(PyObject *self,
                                          PyObject *args,
                                          PyObject *kwds)
@@ -1089,6 +1122,13 @@
       "Returns [dict]: information about the hardware"
       "        [None]: on failure.\n" },
 
+    { "xeninfo",
+      (PyCFunction)pyxc_xeninfo,
+      METH_VARARGS, "\n"
+      "Get information about the Xen host\n"
+      "Returns [dict]: information about Xen"
+      "        [None]: on failure.\n" },
+
     { "shadow_control", 
       (PyCFunction)pyxc_shadow_control, 
       METH_VARARGS | METH_KEYWORDS, "\n"
diff -r dd108e5ad24d -r f0dc15fd3c1b tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py   Wed Aug 31 22:37:21 2005
+++ b/tools/python/xen/xend/XendDomainInfo.py   Wed Aug 31 23:22:45 2005
@@ -1078,10 +1078,9 @@
 
     def publish_console(self):
         db = DBMap(db=XenNode("/console/%d" % self.id))
-        db.clear()
         db['domain'] = self.db.getPath()
         db.saveDB(save=True)
-        
+
     def configure_fields(self):
         """Process the vm configuration fields using the registered handlers.
         """
diff -r dd108e5ad24d -r f0dc15fd3c1b tools/python/xen/xend/XendNode.py
--- a/tools/python/xen/xend/XendNode.py Wed Aug 31 22:37:21 2005
+++ b/tools/python/xen/xend/XendNode.py Wed Aug 31 23:22:45 2005
@@ -46,7 +46,7 @@
         return self.xc.bvtsched_global_get()
     
     def info(self):
-        return self.nodeinfo() + self.physinfo()
+        return self.nodeinfo() + self.physinfo() + self.xeninfo()
 
     def nodeinfo(self):
         (sys, host, rel, ver, mch) = os.uname()
@@ -65,7 +65,16 @@
                 ['free_memory', pinfo['free_pages']/256]]
         return info
         
-        
+    def xeninfo(self):
+        xinfo = self.xc.xeninfo()
+       return [['xen_major', xinfo['xen_major']],
+               ['xen_minor', xinfo['xen_minor']],
+               ['xen_extra', xinfo['xen_extra']],
+               ['xen_changeset', xinfo['xen_changeset']],
+               ['cc_compiler', xinfo['cc_compiler']],
+                ['cc_compile_by', xinfo['cc_compile_by']],
+                ['cc_compile_domain', xinfo['cc_compile_domain']],
+                ['cc_compile_date', xinfo['cc_compile_date']]]
 
 def instance():
     global inst
diff -r dd108e5ad24d -r f0dc15fd3c1b tools/python/xen/xm/create.py
--- a/tools/python/xen/xm/create.py     Wed Aug 31 22:37:21 2005
+++ b/tools/python/xen/xm/create.py     Wed Aug 31 23:22:45 2005
@@ -103,12 +103,13 @@
           fn=set_true, default=0,
           use="Connect to the console after the domain is created.")
 
-gopts.var('vnc', val='no|yes',
+gopts.var('vncviewer', val='no|yes',
           fn=set_bool, default=None,
           use="""Spawn a vncviewer listening for a vnc server in the domain.
           The address of the vncviewer is passed to the domain on the kernel 
command
           line using 'VNC_SERVER=<host>:<port>'. The port used by vnc is 5500 
+ DISPLAY.
           A display value with a free port is chosen if possible.
+         Only valid when vnc=1.
           """)
 
 gopts.var('name', val='NAME',
@@ -320,6 +321,10 @@
 gopts.var('nographic', val='no|yes',
           fn=set_bool, default=0,
           use="Should device models use graphics?")
+
+gopts.var('vnc', val='',
+          fn=set_value, default=None,
+          use="""Should the device model use VNC?""")
 
 gopts.var('sdl', val='',
           fn=set_value, default=None,
@@ -494,7 +499,7 @@
     """
     args = [ 'memmap', 'device_model', 'cdrom',
             'boot', 'fda', 'fdb', 'localtime', 'serial', 'macaddr', 'stdvga', 
-             'isa', 'nographic', 'vnc', 'sdl', 'display']        
+             'isa', 'nographic', 'vnc', 'vncviewer', 'sdl', 'display']   
     for a in args:
        if (vals.__dict__[a]):
            config_devs.append([a, vals.__dict__[a]])
@@ -693,7 +698,7 @@
     """If vnc was specified, spawn a vncviewer in listen mode
     and pass its address to the domain on the kernel command line.
     """
-    if not vals.vnc or vals.dryrun: return
+    if not (vals.vnc and vals.vncviewer) or vals.dryrun: return
     vnc_display = choose_vnc_display()
     if not vnc_display:
         opts.warn("No free vnc display")
diff -r dd108e5ad24d -r f0dc15fd3c1b tools/xentrace/formats
--- a/tools/xentrace/formats    Wed Aug 31 22:37:21 2005
+++ b/tools/xentrace/formats    Wed Aug 31 23:22:45 2005
@@ -15,3 +15,7 @@
 0x00080001     CPU%(cpu)d      %(tsc)d         VMX_VMEXIT              [ domid 
= 0x%(1)08x, eip = 0x%(2)08x, reason = 0x%(3)08x ]
 0x00080002     CPU%(cpu)d      %(tsc)d         VMX_VECTOR              [ domid 
= 0x%(1)08x, eip = 0x%(2)08x, vector = 0x%(3)08x ]
 0x00080003     CPU%(cpu)d      %(tsc)d         VMX_INT                 [ domid 
= 0x%(1)08x, trap = 0x%(2)08x, va = 0x%(3)08x ]
+
+0x00090001      CPU%(cpu)d      %(tsc)d         VMENTRY                 
0x%(1)08x 0x%(2)08x 0x%(3)08x 0x%(4)08x 0x%(5)08x
+0x00090002      CPU%(cpu)d      %(tsc)d         VMEXIT                  
0x%(1)08x 0x%(2)08x 0x%(3)08x 
+
diff -r dd108e5ad24d -r f0dc15fd3c1b tools/xentrace/xentrace.c
--- a/tools/xentrace/xentrace.c Wed Aug 31 22:37:21 2005
+++ b/tools/xentrace/xentrace.c Wed Aug 31 23:22:45 2005
@@ -525,7 +525,7 @@
     }
 
     if (opts.cpu_mask != 0) {
-        set_mask(opts.evt_mask, 1);
+        set_mask(opts.cpu_mask, 1);
     }
 
     if ( opts.outfile )
diff -r dd108e5ad24d -r f0dc15fd3c1b xen/arch/x86/domain_build.c
--- a/xen/arch/x86/domain_build.c       Wed Aug 31 22:37:21 2005
+++ b/xen/arch/x86/domain_build.c       Wed Aug 31 23:22:45 2005
@@ -20,6 +20,7 @@
 #include <asm/processor.h>
 #include <asm/desc.h>
 #include <asm/i387.h>
+#include <asm/physdev.h>
 #include <asm/shadow.h>
 
 static long dom0_nrpages;
@@ -707,6 +708,18 @@
         printk("dom0: shadow setup done\n");
     }
 
+    /*
+     * Modify I/O port access permissions.
+     */
+    /* Master Interrupt Controller (PIC). */
+    physdev_modify_ioport_access_range(dom0, 0, 0x20, 2);
+    /* Slave Interrupt Controller (PIC). */
+    physdev_modify_ioport_access_range(dom0, 0, 0xA0, 2);
+    /* Interval Timer (PIT). */
+    physdev_modify_ioport_access_range(dom0, 0, 0x40, 4);
+    /* PIT Channel 2 / PC Speaker Control. */
+    physdev_modify_ioport_access_range(dom0, 0, 0x61, 1);
+
     return 0;
 }
 
diff -r dd108e5ad24d -r f0dc15fd3c1b xen/arch/x86/shadow.c
--- a/xen/arch/x86/shadow.c     Wed Aug 31 22:37:21 2005
+++ b/xen/arch/x86/shadow.c     Wed Aug 31 23:22:45 2005
@@ -671,6 +671,7 @@
                          sizeof(gpte))) {*/
     if (unlikely(!__guest_get_l1e(v, va, &gpte))) {
         perfc_incrc(shadow_invlpg_faults);
+        shadow_unlock(d);
         return;
     }
     l1pte_propagate_from_guest(d, gpte, &spte);
diff -r dd108e5ad24d -r f0dc15fd3c1b xen/arch/x86/shadow32.c
--- a/xen/arch/x86/shadow32.c   Wed Aug 31 22:37:21 2005
+++ b/xen/arch/x86/shadow32.c   Wed Aug 31 23:22:45 2005
@@ -1685,6 +1685,7 @@
     if (__copy_from_user(&gpte, &linear_pg_table[va >> PAGE_SHIFT],
                          sizeof(gpte))) {
         perfc_incrc(shadow_invlpg_faults);
+        shadow_unlock(d);
         return;
     }
     l1pte_propagate_from_guest(d, gpte, &spte);
@@ -1917,8 +1918,10 @@
     snapshot = map_domain_page(smfn);
 
     if (__copy_from_user(&gpte, &guest_pt[index],
-                         sizeof(gpte)))
+                         sizeof(gpte))) {
+        unmap_domain_page(snapshot);
         return 0;
+    }
 
     // This could probably be smarter, but this is sufficent for
     // our current needs.
diff -r dd108e5ad24d -r f0dc15fd3c1b xen/arch/x86/vmx.c
--- a/xen/arch/x86/vmx.c        Wed Aug 31 22:37:21 2005
+++ b/xen/arch/x86/vmx.c        Wed Aug 31 23:22:45 2005
@@ -49,6 +49,13 @@
 int vmcs_size;
 unsigned int opt_vmx_debug_level = 0;
 integer_param("vmx_debug", opt_vmx_debug_level);
+
+#ifdef TRACE_BUFFER
+static unsigned long trace_values[NR_CPUS][4];
+#define TRACE_VMEXIT(index,value) trace_values[current->processor][index]=value
+#else
+#define TRACE_VMEXIT(index,value) ((void)0)
+#endif
 
 #ifdef __x86_64__
 static struct msr_state percpu_msr[NR_CPUS];
@@ -351,7 +358,7 @@
  * Not all cases receive valid value in the VM-exit instruction length field.
  */
 #define __get_instruction_length(len) \
-    __vmread(INSTRUCTION_LEN, &(len)); \
+    __vmread(VM_EXIT_INSTRUCTION_LEN, &(len)); \
      if ((len) < 1 || (len) > 15) \
         __vmx_bug(&regs);
 
@@ -381,6 +388,7 @@
 
     if (!vmx_paging_enabled(current)){
         handle_mmio(va, va);
+        TRACE_VMEXIT (2,2);
         return 1;
     }
     gpa = gva_to_gpa(va);
@@ -389,16 +397,17 @@
     if ( mmio_space(gpa) ){
         if (gpa >= 0xFEE00000) { /* workaround for local APIC */
             u32 inst_len;
-            __vmread(INSTRUCTION_LEN, &(inst_len));
+            __vmread(VM_EXIT_INSTRUCTION_LEN, &(inst_len));
             __update_guest_eip(inst_len);
             return 1;
         }
+        TRACE_VMEXIT (2,2);
         handle_mmio(va, gpa);
         return 1;
     }
 
     result = shadow_fault(va, regs);
-
+    TRACE_VMEXIT (2,result);
 #if 0
     if ( !result )
     {
@@ -542,7 +551,7 @@
     int i, inst_len;
     int inst_copy_from_guest(unsigned char *, unsigned long, int);
 
-    __vmread(INSTRUCTION_LEN, &inst_len);
+    __vmread(VM_EXIT_INSTRUCTION_LEN, &inst_len);
     memset(inst, 0, MAX_INST_LEN);
     if (inst_copy_from_guest(inst, eip, inst_len) != inst_len) {
         printf("check_for_null_selector: get guest instruction failed\n");
@@ -608,6 +617,7 @@
         addr = (exit_qualification >> 16) & (0xffff);
     else
         addr = regs->edx & 0xffff;
+    TRACE_VMEXIT (2,addr);
 
     vio = get_vio(d->domain, d->vcpu_id);
     if (vio == 0) {
@@ -712,7 +722,7 @@
     unsigned long inst_len;
     int error = 0;
 
-    error |= __vmread(INSTRUCTION_LEN, &inst_len);
+    error |= __vmread(VM_EXIT_INSTRUCTION_LEN, &inst_len);
     error |= __vmread(GUEST_RIP, &c->eip);
     c->eip += inst_len; /* skip transition instruction */
     error |= __vmread(GUEST_RSP, &c->esp);
@@ -1282,13 +1292,20 @@
     case TYPE_MOV_TO_CR:
         gp = exit_qualification & CONTROL_REG_ACCESS_REG;
         cr = exit_qualification & CONTROL_REG_ACCESS_NUM;
+        TRACE_VMEXIT(1,TYPE_MOV_TO_CR);
+        TRACE_VMEXIT(2,cr);
+        TRACE_VMEXIT(3,gp);
         return mov_to_cr(gp, cr, regs);
     case TYPE_MOV_FROM_CR:
         gp = exit_qualification & CONTROL_REG_ACCESS_REG;
         cr = exit_qualification & CONTROL_REG_ACCESS_NUM;
+        TRACE_VMEXIT(1,TYPE_MOV_FROM_CR);
+        TRACE_VMEXIT(2,cr);
+        TRACE_VMEXIT(3,gp);
         mov_from_cr(cr, gp, regs);
         break;
     case TYPE_CLTS:
+        TRACE_VMEXIT(1,TYPE_CLTS);
         clts();
         setup_fpu(current);
 
@@ -1301,6 +1318,7 @@
         __vmwrite(CR0_READ_SHADOW, value);
         break;
     case TYPE_LMSW:
+        TRACE_VMEXIT(1,TYPE_LMSW);
         __vmread(CR0_READ_SHADOW, &value);
        value = (value & ~0xF) |
                (((exit_qualification & LMSW_SOURCE_DATA) >> 16) & 0xF);
@@ -1544,6 +1562,7 @@
 
     __vmread(GUEST_RIP, &eip);
     TRACE_3D(TRC_VMX_VMEXIT, v->domain->domain_id, eip, exit_reason);
+    TRACE_VMEXIT(0,exit_reason);
 
     switch (exit_reason) {
     case EXIT_REASON_EXCEPTION_NMI:
@@ -1562,6 +1581,7 @@
             __vmx_bug(&regs);
         vector &= 0xff;
 
+        TRACE_VMEXIT(1,vector);
         perfc_incra(cause_vector, vector);
 
         TRACE_3D(TRC_VMX_VECTOR, v->domain->domain_id, eip, vector);
@@ -1606,6 +1626,10 @@
         {
             __vmread(EXIT_QUALIFICATION, &va);
             __vmread(VM_EXIT_INTR_ERROR_CODE, &regs.error_code);
+            
+           TRACE_VMEXIT(3,regs.error_code);
+           TRACE_VMEXIT(4,va);
+
             VMX_DBG_LOG(DBG_LEVEL_VMMU, 
                         "eax=%lx, ebx=%lx, ecx=%lx, edx=%lx, esi=%lx, edi=%lx",
                         (unsigned long)regs.eax, (unsigned long)regs.ebx,
@@ -1680,6 +1704,8 @@
                 eip, inst_len, exit_qualification);
         if (vmx_cr_access(exit_qualification, &regs))
            __update_guest_eip(inst_len);
+        TRACE_VMEXIT(3,regs.error_code);
+        TRACE_VMEXIT(4,exit_qualification);
         break;
     }
     case EXIT_REASON_DR_ACCESS:
@@ -1692,6 +1718,7 @@
         __vmread(EXIT_QUALIFICATION, &exit_qualification);
         __get_instruction_length(inst_len);
         vmx_io_instruction(&regs, exit_qualification, inst_len);
+        TRACE_VMEXIT(4,exit_qualification);
         break;
     case EXIT_REASON_MSR_READ:
         __get_instruction_length(inst_len);
@@ -1726,6 +1753,25 @@
 #endif
 }
 
+#ifdef TRACE_BUFFER
+asmlinkage void trace_vmentry (void)
+{
+    TRACE_5D(TRC_VMENTRY,trace_values[current->processor][0],
+          
trace_values[current->processor][1],trace_values[current->processor][2],
+          
trace_values[current->processor][3],trace_values[current->processor][4]);
+    TRACE_VMEXIT(0,9);
+    TRACE_VMEXIT(1,9);
+    TRACE_VMEXIT(2,9);
+    TRACE_VMEXIT(3,9);
+    TRACE_VMEXIT(4,9);
+    return;
+}
+asmlinkage void trace_vmexit (void)
+{
+    TRACE_3D(TRC_VMEXIT,0,0,0);
+    return;
+}
+#endif 
 #endif /* CONFIG_VMX */
 
 /*
diff -r dd108e5ad24d -r f0dc15fd3c1b xen/arch/x86/vmx_platform.c
--- a/xen/arch/x86/vmx_platform.c       Wed Aug 31 22:37:21 2005
+++ b/xen/arch/x86/vmx_platform.c       Wed Aug 31 23:22:45 2005
@@ -639,7 +639,7 @@
     inst_decoder_regs = mpci_p->inst_decoder_regs;
 
     __vmread(GUEST_RIP, &eip);
-    __vmread(INSTRUCTION_LEN, &inst_len);
+    __vmread(VM_EXIT_INSTRUCTION_LEN, &inst_len);
     __vmread(GUEST_RFLAGS, &eflags);
     vm86 = eflags & X86_EFLAGS_VM;
 
diff -r dd108e5ad24d -r f0dc15fd3c1b xen/arch/x86/x86_32/entry.S
--- a/xen/arch/x86/x86_32/entry.S       Wed Aug 31 22:37:21 2005
+++ b/xen/arch/x86/x86_32/entry.S       Wed Aug 31 23:22:45 2005
@@ -126,6 +126,9 @@
 ENTRY(vmx_asm_vmexit_handler)
         /* selectors are restored/saved by VMX */
         VMX_SAVE_ALL_NOSEGREGS
+#ifdef TRACE_BUFFER
+        call trace_vmexit
+#endif
         call vmx_vmexit_handler
         jmp vmx_asm_do_resume
 
@@ -147,6 +150,9 @@
 /* vmx_restore_all_guest */
         call vmx_intr_assist
         call load_cr2
+#ifdef TRACE_BUFFER
+        call trace_vmentry
+#endif
         .endif
         VMX_RESTORE_ALL_NOSEGREGS
         /* 
diff -r dd108e5ad24d -r f0dc15fd3c1b xen/common/domain.c
--- a/xen/common/domain.c       Wed Aug 31 22:37:21 2005
+++ b/xen/common/domain.c       Wed Aug 31 23:22:45 2005
@@ -114,6 +114,8 @@
             sched_rem_domain(v);
         domain_relinquish_resources(d);
         put_domain(d);
+
+        send_guest_virq(dom0->vcpu[0], VIRQ_DOM_EXC);
     }
 }
 
diff -r dd108e5ad24d -r f0dc15fd3c1b xen/common/kernel.c
--- a/xen/common/kernel.c       Wed Aug 31 22:37:21 2005
+++ b/xen/common/kernel.c       Wed Aug 31 23:22:45 2005
@@ -46,7 +46,7 @@
         if ( optval != NULL )
             *optval++ = '\0';
 
-        for ( param = &__setup_start; param != &__setup_end; param++ )
+        for ( param = &__setup_start; param <= &__setup_end; param++ )
         {
             if ( strcmp(param->name, opt ) != 0 )
                 continue;
@@ -110,6 +110,27 @@
             return -EFAULT;
         return 0;
     }
+
+    case XENVER_capabilities:
+    {
+        struct xen_capabilities_info info;
+        
+        /* FIXME */
+        info.arch = 0;
+        info.pae = 0;
+        if ( copy_to_user(arg, &info, sizeof(info)) )
+            return -EFAULT;
+        return 0;
+    }
+    
+    case XENVER_changeset:
+    {
+        xen_changeset_info_t chgset;
+        safe_strcpy(chgset, XEN_CHANGESET);
+        if ( copy_to_user(arg, chgset, sizeof(chgset)) )
+            return -EFAULT;
+        return 0;
+    }
     }
 
     return -ENOSYS;
diff -r dd108e5ad24d -r f0dc15fd3c1b xen/include/asm-x86/vmx.h
--- a/xen/include/asm-x86/vmx.h Wed Aug 31 22:37:21 2005
+++ b/xen/include/asm-x86/vmx.h Wed Aug 31 23:22:45 2005
@@ -275,7 +275,9 @@
     return 0;
 }
 
-static inline int __vmread (unsigned long field, void *value)
+#define __vmread(x, ptr) ___vmread((x), (ptr), sizeof(*(ptr)))
+
+static always_inline int ___vmread (const unsigned long field,  void *ptr, 
const int size)
 {
     unsigned long eflags;
     unsigned long ecx = 0;
@@ -286,7 +288,23 @@
                            : "a" (field)
                            : "memory");
 
-    *((long *) value) = ecx;
+    switch (size) {
+    case 1:
+        *((u8 *) (ptr)) = ecx;
+        break;
+    case 2:
+        *((u16 *) (ptr)) = ecx;
+        break;
+    case 4:
+        *((u32 *) (ptr)) = ecx;
+        break;
+    case 8:
+        *((u64 *) (ptr)) = ecx;
+        break;
+    default:
+        domain_crash_synchronous();
+        break;
+    }
 
     __save_flags(eflags);
     if (eflags & X86_EFLAGS_ZF || eflags & X86_EFLAGS_CF)
diff -r dd108e5ad24d -r f0dc15fd3c1b xen/include/asm-x86/vmx_vmcs.h
--- a/xen/include/asm-x86/vmx_vmcs.h    Wed Aug 31 22:37:21 2005
+++ b/xen/include/asm-x86/vmx_vmcs.h    Wed Aug 31 23:22:45 2005
@@ -183,7 +183,7 @@
     VM_ENTRY_MSR_LOAD_COUNT         = 0x00004014,
     VM_ENTRY_INTR_INFO_FIELD        = 0x00004016,
     VM_ENTRY_EXCEPTION_ERROR_CODE   = 0x00004018,
-    VM_ENTRY_INSTRUCTION_LENGTH     = 0x0000401a,
+    VM_ENTRY_INSTRUCTION_LEN        = 0x0000401a,
     TPR_THRESHOLD                   = 0x0000401c,
     SECONDARY_VM_EXEC_CONTROL       = 0x0000401e,
     VM_INSTRUCTION_ERROR            = 0x00004400,
@@ -192,7 +192,7 @@
     VM_EXIT_INTR_ERROR_CODE         = 0x00004406,
     IDT_VECTORING_INFO_FIELD        = 0x00004408,
     IDT_VECTORING_ERROR_CODE        = 0x0000440a,
-    INSTRUCTION_LEN                 = 0x0000440c,
+    VM_EXIT_INSTRUCTION_LEN         = 0x0000440c,
     VMX_INSTRUCTION_INFO            = 0x0000440e,
     GUEST_ES_LIMIT                  = 0x00004800,
     GUEST_CS_LIMIT                  = 0x00004802,
diff -r dd108e5ad24d -r f0dc15fd3c1b xen/include/public/trace.h
--- a/xen/include/public/trace.h        Wed Aug 31 22:37:21 2005
+++ b/xen/include/public/trace.h        Wed Aug 31 23:22:45 2005
@@ -23,7 +23,7 @@
 #define TRC_VMXTIMER 0x00082000   /* VMX timer trace           */
 #define TRC_VMXINT   0x00084000   /* VMX interrupt trace       */
 #define TRC_VMXIO    0x00088000   /* VMX io emulation trace  */
-
+#define TRC_VMEXIT_HANDLER    0x00090000   /* VMX handler trace  */
 
 /* Trace events per class */
 
@@ -49,6 +49,10 @@
 
 #define TRC_VMX_INT             (TRC_VMXINT + 1)
 
+#define TRC_VMEXIT              (TRC_VMEXIT_HANDLER + 1)
+#define TRC_VMENTRY             (TRC_VMEXIT_HANDLER + 2)
+
+
 /* This structure represents a single trace buffer record. */
 struct t_rec {
     u64 cycles;               /* cycle counter timestamp */
diff -r dd108e5ad24d -r f0dc15fd3c1b xen/include/public/version.h
--- a/xen/include/public/version.h      Wed Aug 31 22:37:21 2005
+++ b/xen/include/public/version.h      Wed Aug 31 23:22:45 2005
@@ -28,4 +28,13 @@
     char compile_date[32];
 } xen_compile_info_t;
 
+#define XENVER_capabilities 3
+typedef struct xen_capabilities_info {
+    int pae;
+    int arch;
+} xen_capabilities_info_t;
+
+#define XENVER_changeset 4
+typedef char xen_changeset_info_t[64];
+
 #endif /* __XEN_PUBLIC_VERSION_H__ */
diff -r dd108e5ad24d -r f0dc15fd3c1b tools/ioemu/hw/pcnet.c
--- /dev/null   Wed Aug 31 22:37:21 2005
+++ b/tools/ioemu/hw/pcnet.c    Wed Aug 31 23:22:45 2005
@@ -0,0 +1,1205 @@
+/*
+ * QEMU AMD PC-Net II (Am79C970A) emulation
+ * 
+ * Copyright (c) 2004 Antony T Curtis
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+ 
+/* This software was written to be compatible with the specification:
+ * AMD Am79C970A PCnet-PCI II Ethernet Controller Data-Sheet
+ * AMD Publication# 19436  Rev:E  Amendment/0  Issue Date: June 2000
+ */
+ 
+#include "vl.h"
+#include <sys/times.h>
+#include <arpa/inet.h>
+#include <net/ethernet.h>
+
+//#define PCNET_DEBUG
+//#define PCNET_DEBUG_IO
+//#define PCNET_DEBUG_BCR
+//#define PCNET_DEBUG_CSR
+//#define PCNET_DEBUG_RMD
+//#define PCNET_DEBUG_TMD
+//#define PCNET_DEBUG_MATCH
+
+
+#define PCNET_IOPORT_SIZE       0x20
+#define PCNET_PNPMMIO_SIZE      0x20
+
+
+typedef struct PCNetState_st PCNetState;
+
+struct PCNetState_st {
+    PCIDevice dev;
+    NetDriverState *nd;
+    QEMUTimer *poll_timer;
+    int mmio_io_addr, rap, isr, lnkst;
+    target_phys_addr_t rdra, tdra;
+    uint8_t prom[16];
+    uint16_t csr[128];
+    uint16_t bcr[32];
+    uint64_t timer;
+    int xmit_pos, recv_pos;
+    uint8_t buffer[4096];
+};
+
+#include "pcnet.h"
+
+static void pcnet_poll(PCNetState *s);
+static void pcnet_poll_timer(void *opaque);
+
+static uint32_t pcnet_csr_readw(PCNetState *s, uint32_t rap);
+static void pcnet_csr_writew(PCNetState *s, uint32_t rap, uint32_t new_value);
+static void pcnet_bcr_writew(PCNetState *s, uint32_t rap, uint32_t val);
+static uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap);
+
+static void pcnet_s_reset(PCNetState *s)
+{
+#ifdef PCNET_DEBUG
+    printf("pcnet_s_reset\n");
+#endif
+
+    s->lnkst = 0x40;
+    s->rdra = 0;
+    s->tdra = 0;
+    s->rap = 0;
+    
+    s->bcr[BCR_BSBC] &= ~0x0080;
+
+    s->csr[0]   = 0x0004;
+    s->csr[3]   = 0x0000;
+    s->csr[4]   = 0x0115;
+    s->csr[5]   = 0x0000;
+    s->csr[6]   = 0x0000;
+    s->csr[8]   = 0;
+    s->csr[9]   = 0;
+    s->csr[10]  = 0;
+    s->csr[11]  = 0;
+    s->csr[12]  = le16_to_cpu(((uint16_t *)&s->prom[0])[0]);
+    s->csr[13]  = le16_to_cpu(((uint16_t *)&s->prom[0])[1]);
+    s->csr[14]  = le16_to_cpu(((uint16_t *)&s->prom[0])[2]);
+    s->csr[15] &= 0x21c4;
+    s->csr[72]  = 1;
+    s->csr[74]  = 1;
+    s->csr[76]  = 1;
+    s->csr[78]  = 1;
+    s->csr[80]  = 0x1410;
+    s->csr[88]  = 0x1003;
+    s->csr[89]  = 0x0262;
+    s->csr[94]  = 0x0000;
+    s->csr[100] = 0x0200;
+    s->csr[103] = 0x0105;
+    s->csr[103] = 0x0105;
+    s->csr[112] = 0x0000;
+    s->csr[114] = 0x0000;
+    s->csr[122] = 0x0000;
+    s->csr[124] = 0x0000;
+}
+
+static void pcnet_update_irq(PCNetState *s)
+{
+    int isr = 0;
+    s->csr[0] &= ~0x0080;
+    
+#if 1
+    if (((s->csr[0] & ~s->csr[3]) & 0x5f00) ||
+        (((s->csr[4]>>1) & ~s->csr[4]) & 0x0115) ||
+        (((s->csr[5]>>1) & s->csr[5]) & 0x0048))
+#else
+    if ((!(s->csr[3] & 0x4000) && !!(s->csr[0] & 0x4000)) /* BABL */ ||
+        (!(s->csr[3] & 0x1000) && !!(s->csr[0] & 0x1000)) /* MISS */ ||
+        (!(s->csr[3] & 0x0100) && !!(s->csr[0] & 0x0100)) /* IDON */ ||
+        (!(s->csr[3] & 0x0200) && !!(s->csr[0] & 0x0200)) /* TINT */ ||
+        (!(s->csr[3] & 0x0400) && !!(s->csr[0] & 0x0400)) /* RINT */ ||
+        (!(s->csr[3] & 0x0800) && !!(s->csr[0] & 0x0800)) /* MERR */ ||
+        (!(s->csr[4] & 0x0001) && !!(s->csr[4] & 0x0002)) /* JAB */ ||
+        (!(s->csr[4] & 0x0004) && !!(s->csr[4] & 0x0008)) /* TXSTRT */ ||
+        (!(s->csr[4] & 0x0010) && !!(s->csr[4] & 0x0020)) /* RCVO */ ||
+        (!(s->csr[4] & 0x0100) && !!(s->csr[4] & 0x0200)) /* MFCO */ ||
+        (!!(s->csr[5] & 0x0040) && !!(s->csr[5] & 0x0080)) /* EXDINT */ ||
+        (!!(s->csr[5] & 0x0008) && !!(s->csr[5] & 0x0010)) /* MPINT */)
+#endif
+    {
+       
+        isr = CSR_INEA(s);
+        s->csr[0] |= 0x0080;
+    }
+    
+    if (!!(s->csr[4] & 0x0080) && CSR_INEA(s)) { /* UINT */
+        s->csr[4] &= ~0x0080;
+        s->csr[4] |= 0x0040;
+        s->csr[0] |= 0x0080;
+        isr = 1;
+#ifdef PCNET_DEBUG
+        printf("pcnet user int\n");
+#endif
+    }
+
+#if 1
+    if (((s->csr[5]>>1) & s->csr[5]) & 0x0500) 
+#else
+    if ((!!(s->csr[5] & 0x0400) && !!(s->csr[5] & 0x0800)) /* SINT */ ||
+        (!!(s->csr[5] & 0x0100) && !!(s->csr[5] & 0x0200)) /* SLPINT */ )
+#endif
+    {
+        isr = 1;
+        s->csr[0] |= 0x0080;
+    }
+
+    if (isr != s->isr) {
+#ifdef PCNET_DEBUG
+        printf("pcnet: INTA=%d\n", isr);
+#endif
+    }
+        pci_set_irq(&s->dev, 0, isr);
+        s->isr = isr;
+}
+
+static void pcnet_init(PCNetState *s)
+{
+#ifdef PCNET_DEBUG
+    printf("pcnet_init init_addr=0x%08x\n", PHYSADDR(s,CSR_IADR(s)));
+#endif
+    
+#define PCNET_INIT() do { \
+        cpu_physical_memory_read(PHYSADDR(s,CSR_IADR(s)),       \
+                (uint8_t *)&initblk, sizeof(initblk));          \
+        s->csr[15] = le16_to_cpu(initblk.mode);                 \
+        CSR_RCVRL(s) = (initblk.rlen < 9) ? (1 << initblk.rlen) : 512;  \
+        CSR_XMTRL(s) = (initblk.tlen < 9) ? (1 << initblk.tlen) : 512;  \
+        s->csr[ 6] = (initblk.tlen << 12) | (initblk.rlen << 8);        \
+        s->csr[ 8] = le16_to_cpu(initblk.ladrf1);                       \
+        s->csr[ 9] = le16_to_cpu(initblk.ladrf2);                       \
+        s->csr[10] = le16_to_cpu(initblk.ladrf3);                       \
+        s->csr[11] = le16_to_cpu(initblk.ladrf4);                       \
+        s->csr[12] = le16_to_cpu(initblk.padr1);                        \
+        s->csr[13] = le16_to_cpu(initblk.padr2);                        \
+        s->csr[14] = le16_to_cpu(initblk.padr3);                        \
+        s->rdra = PHYSADDR(s,initblk.rdra);                             \
+        s->tdra = PHYSADDR(s,initblk.tdra);                             \
+} while (0)
+    
+    if (BCR_SSIZE32(s)) {
+        struct pcnet_initblk32 initblk;
+        PCNET_INIT();
+#ifdef PCNET_DEBUG
+        printf("initblk.rlen=0x%02x, initblk.tlen=0x%02x\n",
+                initblk.rlen, initblk.tlen);
+#endif
+    } else {
+        struct pcnet_initblk16 initblk;
+        PCNET_INIT();
+#ifdef PCNET_DEBUG
+        printf("initblk.rlen=0x%02x, initblk.tlen=0x%02x\n",
+                initblk.rlen, initblk.tlen);
+#endif
+    }
+
+#undef PCNET_INIT
+
+    CSR_RCVRC(s) = CSR_RCVRL(s);
+    CSR_XMTRC(s) = CSR_XMTRL(s);
+
+#ifdef PCNET_DEBUG
+    printf("pcnet ss32=%d rdra=0x%08x[%d] tdra=0x%08x[%d]\n", 
+        BCR_SSIZE32(s),
+        s->rdra, CSR_RCVRL(s), s->tdra, CSR_XMTRL(s));
+#endif
+
+    s->csr[0] |= 0x0101;    
+    s->csr[0] &= ~0x0004;       /* clear STOP bit */
+}
+
+static void pcnet_start(PCNetState *s)
+{
+#ifdef PCNET_DEBUG
+    printf("pcnet_start\n");
+#endif
+
+    if (!CSR_DTX(s))
+        s->csr[0] |= 0x0010;    /* set TXON */
+        
+    if (!CSR_DRX(s))
+        s->csr[0] |= 0x0020;    /* set RXON */
+
+    s->csr[0] &= ~0x0004;       /* clear STOP bit */
+    s->csr[0] |= 0x0002;
+}
+
+static void pcnet_stop(PCNetState *s)
+{
+#ifdef PCNET_DEBUG
+    printf("pcnet_stop\n");
+#endif
+    s->csr[0] &= ~0x7feb;
+    s->csr[0] |= 0x0014;
+    s->csr[4] &= ~0x02c2;
+    s->csr[5] &= ~0x0011;
+    pcnet_poll_timer(s);
+}
+
+static void pcnet_rdte_poll(PCNetState *s)
+{
+    s->csr[28] = s->csr[29] = 0;
+    if (s->rdra) {
+        int bad = 0;
+#if 1
+        target_phys_addr_t crda = pcnet_rdra_addr(s, CSR_RCVRC(s));
+        target_phys_addr_t nrda = pcnet_rdra_addr(s, -1 + CSR_RCVRC(s));
+        target_phys_addr_t nnrd = pcnet_rdra_addr(s, -2 + CSR_RCVRC(s));
+#else
+        target_phys_addr_t crda = s->rdra + 
+            (CSR_RCVRL(s) - CSR_RCVRC(s)) *
+            (BCR_SWSTYLE(s) ? 16 : 8 );
+        int nrdc = CSR_RCVRC(s)<=1 ? CSR_RCVRL(s) : CSR_RCVRC(s)-1;
+        target_phys_addr_t nrda = s->rdra + 
+            (CSR_RCVRL(s) - nrdc) *
+            (BCR_SWSTYLE(s) ? 16 : 8 );
+        int nnrc = nrdc<=1 ? CSR_RCVRL(s) : nrdc-1;
+        target_phys_addr_t nnrd = s->rdra + 
+            (CSR_RCVRL(s) - nnrc) *
+            (BCR_SWSTYLE(s) ? 16 : 8 );
+#endif
+
+        CHECK_RMD(PHYSADDR(s,crda), bad);
+        if (!bad) {
+            CHECK_RMD(PHYSADDR(s,nrda), bad);
+            if (bad || (nrda == crda)) nrda = 0;
+            CHECK_RMD(PHYSADDR(s,nnrd), bad);
+            if (bad || (nnrd == crda)) nnrd = 0;
+
+            s->csr[28] = crda & 0xffff;
+            s->csr[29] = crda >> 16;
+            s->csr[26] = nrda & 0xffff;
+            s->csr[27] = nrda >> 16;
+            s->csr[36] = nnrd & 0xffff;
+            s->csr[37] = nnrd >> 16;
+#ifdef PCNET_DEBUG
+            if (bad) {
+                printf("pcnet: BAD RMD RECORDS AFTER 0x%08x\n",
+                       PHYSADDR(s,crda));
+            }
+        } else {
+            printf("pcnet: BAD RMD RDA=0x%08x\n", PHYSADDR(s,crda));
+#endif
+        }
+    }
+    
+    if (CSR_CRDA(s)) {
+        struct pcnet_RMD rmd;
+        RMDLOAD(&rmd, PHYSADDR(s,CSR_CRDA(s)));
+        CSR_CRBC(s) = rmd.rmd1.bcnt;
+        CSR_CRST(s) = ((uint32_t *)&rmd)[1] >> 16;
+#ifdef PCNET_DEBUG_RMD_X
+        printf("CRDA=0x%08x CRST=0x%04x RCVRC=%d RMD1=0x%08x RMD2=0x%08x\n",
+                PHYSADDR(s,CSR_CRDA(s)), CSR_CRST(s), CSR_RCVRC(s),
+                ((uint32_t *)&rmd)[1], ((uint32_t *)&rmd)[2]);
+        PRINT_RMD(&rmd);
+#endif
+    } else {
+        CSR_CRBC(s) = CSR_CRST(s) = 0;
+    }
+    
+    if (CSR_NRDA(s)) {
+        struct pcnet_RMD rmd;
+        RMDLOAD(&rmd, PHYSADDR(s,CSR_NRDA(s)));
+        CSR_NRBC(s) = rmd.rmd1.bcnt;
+        CSR_NRST(s) = ((uint32_t *)&rmd)[1] >> 16;
+    } else {
+        CSR_NRBC(s) = CSR_NRST(s) = 0;
+    }
+
+}
+
+static int pcnet_tdte_poll(PCNetState *s)
+{
+    s->csr[34] = s->csr[35] = 0;
+    if (s->tdra) {
+        target_phys_addr_t cxda = s->tdra + 
+            (CSR_XMTRL(s) - CSR_XMTRC(s)) *
+            (BCR_SWSTYLE(s) ? 16 : 8 );
+        int bad = 0;
+        CHECK_TMD(PHYSADDR(s, cxda),bad);
+        if (!bad) {
+            if (CSR_CXDA(s) != cxda) {
+                s->csr[60] = s->csr[34];
+                s->csr[61] = s->csr[35];
+                s->csr[62] = CSR_CXBC(s);
+                s->csr[63] = CSR_CXST(s);
+            }
+            s->csr[34] = cxda & 0xffff;
+            s->csr[35] = cxda >> 16;
+#ifdef PCNET_DEBUG
+        } else {
+            printf("pcnet: BAD TMD XDA=0x%08x\n", PHYSADDR(s,cxda));
+#endif
+        }
+    }
+
+    if (CSR_CXDA(s)) {
+        struct pcnet_TMD tmd;
+
+        TMDLOAD(&tmd, PHYSADDR(s,CSR_CXDA(s)));                
+
+        CSR_CXBC(s) = tmd.tmd1.bcnt;
+        CSR_CXST(s) = ((uint32_t *)&tmd)[1] >> 16;
+    } else {
+        CSR_CXBC(s) = CSR_CXST(s) = 0;
+    }
+    
+    return !!(CSR_CXST(s) & 0x8000);
+}
+
+static int pcnet_can_receive(void *opaque)
+{
+    PCNetState *s = opaque;
+    if (CSR_STOP(s) || CSR_SPND(s))
+        return 0;
+        
+    if (s->recv_pos > 0)
+        return 0;
+
+    return sizeof(s->buffer)-16;
+}
+
+static void pcnet_receive(void *opaque, const uint8_t *buf, int size)
+{
+    PCNetState *s = opaque;
+    int is_padr = 0, is_bcast = 0, is_ladr = 0;
+
+    if (CSR_DRX(s) || CSR_STOP(s) || CSR_SPND(s) || !size)
+        return;
+
+#ifdef PCNET_DEBUG
+    printf("pcnet_receive size=%d\n", size);
+#endif
+
+    if (CSR_PROM(s) 
+        || (is_padr=padr_match(s, buf, size)) 
+        || (is_bcast=padr_bcast(s, buf, size))
+        || (is_ladr=ladr_match(s, buf, size))) {
+
+        pcnet_rdte_poll(s);
+
+        if (!(CSR_CRST(s) & 0x8000) && s->rdra) {
+            struct pcnet_RMD rmd;
+            int rcvrc = CSR_RCVRC(s)-1,i;
+            target_phys_addr_t nrda;
+            for (i = CSR_RCVRL(s)-1; i > 0; i--, rcvrc--) {
+                if (rcvrc <= 1)
+                    rcvrc = CSR_RCVRL(s);
+                nrda = s->rdra +
+                    (CSR_RCVRL(s) - rcvrc) *
+                    (BCR_SWSTYLE(s) ? 16 : 8 );
+                RMDLOAD(&rmd, PHYSADDR(s,nrda));                  
+                if (rmd.rmd1.own) {                
+#ifdef PCNET_DEBUG_RMD
+                    printf("pcnet - scan buffer: RCVRC=%d PREV_RCVRC=%d\n", 
+                                rcvrc, CSR_RCVRC(s));
+#endif
+                    CSR_RCVRC(s) = rcvrc;
+                    pcnet_rdte_poll(s);
+                    break;
+                }
+            }
+        }
+
+        if (!(CSR_CRST(s) & 0x8000)) {
+#ifdef PCNET_DEBUG_RMD
+            printf("pcnet - no buffer: RCVRC=%d\n", CSR_RCVRC(s));
+#endif
+            s->csr[0] |= 0x1000; /* Set MISS flag */
+            CSR_MISSC(s)++;
+        } else {
+            uint8_t *src = &s->buffer[8];
+            target_phys_addr_t crda = CSR_CRDA(s);
+            struct pcnet_RMD rmd;
+            int pktcount = 0;
+
+            memcpy(src, buf, size);
+            
+            if (!CSR_ASTRP_RCV(s)) {
+                uint32_t fcs = ~0;
+#if 0            
+                uint8_t *p = s->buffer;
+                
+                ((uint32_t *)p)[0] = ((uint32_t *)p)[1] = 0xaaaaaaaa;
+                p[7] = 0xab;
+#else
+                uint8_t *p = src;
+#endif
+
+                while (size < 46) {
+                    src[size++] = 0;
+                }
+                
+                while (p != &src[size]) {
+                    CRC(fcs, *p++);
+                }
+                ((uint32_t *)&src[size])[0] = htonl(fcs);
+                size += 4; /* FCS at end of packet */
+            } else size += 4;
+
+#ifdef PCNET_DEBUG_MATCH
+            PRINT_PKTHDR(buf);
+#endif
+
+            RMDLOAD(&rmd, PHYSADDR(s,crda));
+            /*if (!CSR_LAPPEN(s))*/
+                rmd.rmd1.stp = 1;
+
+#define PCNET_RECV_STORE() do {                                 \
+    int count = MIN(4096 - rmd.rmd1.bcnt,size);                 \
+    target_phys_addr_t rbadr = PHYSADDR(s, rmd.rmd0.rbadr);     \
+    cpu_physical_memory_write(rbadr, src, count);               \
+    cpu_physical_memory_set_dirty(rbadr);                       \
+    cpu_physical_memory_set_dirty(rbadr+count);                 \
+    src += count; size -= count;                                \
+    rmd.rmd2.mcnt = count; rmd.rmd1.own = 0;                    \
+    RMDSTORE(&rmd, PHYSADDR(s,crda));                           \
+    pktcount++;                                                 \
+} while (0)
+
+            PCNET_RECV_STORE();
+            if ((size > 0) && CSR_NRDA(s)) {
+                target_phys_addr_t nrda = CSR_NRDA(s);
+                RMDLOAD(&rmd, PHYSADDR(s,nrda));
+                if (rmd.rmd1.own) {
+                    crda = nrda;
+                    PCNET_RECV_STORE();
+                    if ((size > 0) && (nrda=CSR_NNRD(s))) {
+                        RMDLOAD(&rmd, PHYSADDR(s,nrda));
+                        if (rmd.rmd1.own) {
+                            crda = nrda;
+                            PCNET_RECV_STORE();
+                        }
+                    }
+                }                
+            }
+
+#undef PCNET_RECV_STORE
+
+            RMDLOAD(&rmd, PHYSADDR(s,crda));
+            if (size == 0) {
+                rmd.rmd1.enp = 1;
+                rmd.rmd1.pam = !CSR_PROM(s) && is_padr;
+                rmd.rmd1.lafm = !CSR_PROM(s) && is_ladr;
+                rmd.rmd1.bam = !CSR_PROM(s) && is_bcast;
+            } else {
+                rmd.rmd1.oflo = 1;
+                rmd.rmd1.buff = 1;
+                rmd.rmd1.err = 1;
+            }
+            RMDSTORE(&rmd, PHYSADDR(s,crda));
+            s->csr[0] |= 0x0400;
+
+#ifdef PCNET_DEBUG
+            printf("RCVRC=%d CRDA=0x%08x BLKS=%d\n", 
+                CSR_RCVRC(s), PHYSADDR(s,CSR_CRDA(s)), pktcount);
+#endif
+#ifdef PCNET_DEBUG_RMD
+            PRINT_RMD(&rmd);
+#endif        
+
+            while (pktcount--) {
+                if (CSR_RCVRC(s) <= 1)
+                    CSR_RCVRC(s) = CSR_RCVRL(s);
+                else
+                    CSR_RCVRC(s)--;            
+            }
+            
+            pcnet_rdte_poll(s);
+
+        }        
+    }
+
+    pcnet_poll(s);
+    pcnet_update_irq(s);    
+}
+
+static void pcnet_transmit(PCNetState *s)
+{
+    target_phys_addr_t xmit_cxda = 0;
+    int count = CSR_XMTRL(s)-1;
+    s->xmit_pos = -1;
+    
+    if (!CSR_TXON(s)) {
+        s->csr[0] &= ~0x0008;
+        return;
+    }
+    
+    txagain:
+    if (pcnet_tdte_poll(s)) {
+        struct pcnet_TMD tmd;
+
+        TMDLOAD(&tmd, PHYSADDR(s,CSR_CXDA(s)));                
+
+#ifdef PCNET_DEBUG_TMD
+        printf("  TMDLOAD 0x%08x\n", PHYSADDR(s,CSR_CXDA(s)));
+        PRINT_TMD(&tmd);
+#endif
+        if (tmd.tmd1.stp) {
+            s->xmit_pos = 0;                
+            if (!tmd.tmd1.enp) {
+                cpu_physical_memory_read(PHYSADDR(s, tmd.tmd0.tbadr),
+                        s->buffer, 4096 - tmd.tmd1.bcnt);
+                s->xmit_pos += 4096 - tmd.tmd1.bcnt;
+            } 
+            xmit_cxda = PHYSADDR(s,CSR_CXDA(s));
+        }
+        if (tmd.tmd1.enp && (s->xmit_pos >= 0)) {
+            cpu_physical_memory_read(PHYSADDR(s, tmd.tmd0.tbadr),
+                    s->buffer + s->xmit_pos, 4096 - tmd.tmd1.bcnt);
+            s->xmit_pos += 4096 - tmd.tmd1.bcnt;
+#ifdef PCNET_DEBUG
+            printf("pcnet_transmit size=%d\n", s->xmit_pos);
+#endif            
+            if (CSR_LOOP(s))
+                pcnet_receive(s, s->buffer, s->xmit_pos);
+            else
+                qemu_send_packet(s->nd, s->buffer, s->xmit_pos);
+
+            s->csr[0] &= ~0x0008;   /* clear TDMD */
+            s->csr[4] |= 0x0004;    /* set TXSTRT */
+            s->xmit_pos = -1;
+        }
+
+        tmd.tmd1.own = 0;
+        TMDSTORE(&tmd, PHYSADDR(s,CSR_CXDA(s)));
+        if (!CSR_TOKINTD(s) || (CSR_LTINTEN(s) && tmd.tmd1.ltint))
+            s->csr[0] |= 0x0200;    /* set TINT */
+
+        if (CSR_XMTRC(s)<=1)
+            CSR_XMTRC(s) = CSR_XMTRL(s);
+        else
+            CSR_XMTRC(s)--;
+        if (count--)
+            goto txagain;
+
+    } else 
+    if (s->xmit_pos >= 0) {
+        struct pcnet_TMD tmd;
+        TMDLOAD(&tmd, PHYSADDR(s,xmit_cxda));                
+        tmd.tmd2.buff = tmd.tmd2.uflo = tmd.tmd1.err = 1;
+        tmd.tmd1.own = 0;
+        TMDSTORE(&tmd, PHYSADDR(s,xmit_cxda));
+        s->csr[0] |= 0x0200;    /* set TINT */
+        if (!CSR_DXSUFLO(s)) {
+            s->csr[0] &= ~0x0010;
+        } else
+        if (count--)
+          goto txagain;
+    }
+}
+
+static void pcnet_poll(PCNetState *s)
+{
+    if (CSR_RXON(s)) {
+        pcnet_rdte_poll(s);
+    }
+
+    if (CSR_TDMD(s) || 
+        (CSR_TXON(s) && !CSR_DPOLL(s) && pcnet_tdte_poll(s)))
+        pcnet_transmit(s);
+}
+
+static void pcnet_poll_timer(void *opaque)
+{
+    PCNetState *s = opaque;
+
+    qemu_del_timer(s->poll_timer);
+
+    if (CSR_TDMD(s)) {
+        pcnet_transmit(s);
+    }
+
+    pcnet_update_irq(s);    
+
+    if (!CSR_STOP(s) && !CSR_SPND(s) && !CSR_DPOLL(s)) {
+        uint64_t now = qemu_get_clock(vm_clock) * 33;
+        if (!s->timer || !now)
+            s->timer = now;
+        else {
+            uint64_t t = now - s->timer + CSR_POLL(s);
+            if (t > 0xffffLL) {
+                pcnet_poll(s);
+                CSR_POLL(s) = CSR_PINT(s);
+            } else
+                CSR_POLL(s) = t;
+        }
+        qemu_mod_timer(s->poll_timer, 
+            pcnet_get_next_poll_time(s,qemu_get_clock(vm_clock)));
+    }
+}
+
+
+static void pcnet_csr_writew(PCNetState *s, uint32_t rap, uint32_t new_value)
+{
+    uint16_t val = new_value;
+#ifdef PCNET_DEBUG_CSR
+    printf("pcnet_csr_writew rap=%d val=0x%04x\n", rap, val);
+#endif
+    switch (rap) {
+    case 0:
+        s->csr[0] &= ~(val & 0x7f00); /* Clear any interrupt flags */
+
+        s->csr[0] = (s->csr[0] & ~0x0040) | (val & 0x0048);
+
+        val = (val & 0x007f) | (s->csr[0] & 0x7f00);
+
+        /* IFF STOP, STRT and INIT are set, clear STRT and INIT */
+        if ((val&7) == 7)
+          val &= ~3;
+
+        if (!CSR_STOP(s) && (val & 4))
+            pcnet_stop(s);
+
+        if (!CSR_INIT(s) && (val & 1))
+            pcnet_init(s);
+
+        if (!CSR_STRT(s) && (val & 2))
+            pcnet_start(s);
+
+        if (CSR_TDMD(s)) 
+            pcnet_transmit(s);
+
+        return;
+    case 1:
+    case 2:
+    case 8:
+    case 9:
+    case 10:
+    case 11:
+    case 12:
+    case 13:
+    case 14:
+    case 15:
+    case 18: /* CRBAL */
+    case 19: /* CRBAU */
+    case 20: /* CXBAL */
+    case 21: /* CXBAU */
+    case 22: /* NRBAU */
+    case 23: /* NRBAU */
+    case 24:
+    case 25:
+    case 26:
+    case 27:
+    case 28:
+    case 29:
+    case 30:
+    case 31:
+    case 32:
+    case 33:
+    case 34:
+    case 35:
+    case 36:
+    case 37:
+    case 38:
+    case 39:
+    case 40: /* CRBC */
+    case 41:
+    case 42: /* CXBC */
+    case 43:
+    case 44:
+    case 45:
+    case 46: /* POLL */
+    case 47: /* POLLINT */
+    case 72:
+    case 74:
+    case 76: /* RCVRL */
+    case 78: /* XMTRL */
+    case 112:
+       if (CSR_STOP(s) || CSR_SPND(s))
+           break;
+       return;
+    case 3:
+        break;
+    case 4:
+        s->csr[4] &= ~(val & 0x026a); 
+        val &= ~0x026a; val |= s->csr[4] & 0x026a;
+        break;
+    case 5:
+        s->csr[5] &= ~(val & 0x0a90); 
+        val &= ~0x0a90; val |= s->csr[5] & 0x0a90;
+        break;
+    case 16:
+        pcnet_csr_writew(s,1,val);
+        return;
+    case 17:
+        pcnet_csr_writew(s,2,val);
+        return;
+    case 58:
+        pcnet_bcr_writew(s,BCR_SWS,val);
+        break;
+    default:
+        return;
+    }
+    s->csr[rap] = val;
+}
+
+static uint32_t pcnet_csr_readw(PCNetState *s, uint32_t rap)
+{
+    uint32_t val;
+    switch (rap) {
+    case 0:
+        pcnet_update_irq(s);
+        val = s->csr[0];
+        val |= (val & 0x7800) ? 0x8000 : 0;
+        break;
+    case 16:
+        return pcnet_csr_readw(s,1);
+    case 17:
+        return pcnet_csr_readw(s,2);
+    case 58:
+        return pcnet_bcr_readw(s,BCR_SWS);
+    case 88:
+        val = s->csr[89];
+        val <<= 16;
+        val |= s->csr[88];
+        break;
+    default:
+        val = s->csr[rap];
+    }
+#ifdef PCNET_DEBUG_CSR
+    printf("pcnet_csr_readw rap=%d val=0x%04x\n", rap, val);
+#endif
+    return val;
+}
+
+static void pcnet_bcr_writew(PCNetState *s, uint32_t rap, uint32_t val)
+{
+    rap &= 127;
+#ifdef PCNET_DEBUG_BCR
+    printf("pcnet_bcr_writew rap=%d val=0x%04x\n", rap, val);
+#endif
+    switch (rap) {
+    case BCR_SWS:
+        if (!(CSR_STOP(s) || CSR_SPND(s)))
+            return;
+        val &= ~0x0300;
+        switch (val & 0x00ff) {
+        case 0:
+            val |= 0x0200;
+            break;
+        case 1:
+            val |= 0x0100;
+            break;
+        case 2:
+        case 3:
+            val |= 0x0300;
+            break;
+        default:
+            printf("Bad SWSTYLE=0x%02x\n", val & 0xff);
+            val = 0x0200;
+            break;
+        }
+#ifdef PCNET_DEBUG
+       printf("BCR_SWS=0x%04x\n", val);
+#endif
+    case BCR_LNKST:
+    case BCR_LED1:
+    case BCR_LED2:
+    case BCR_LED3:
+    case BCR_MC:
+    case BCR_FDC:
+    case BCR_BSBC:
+    case BCR_EECAS:
+    case BCR_PLAT:
+        s->bcr[rap] = val;
+        break;
+    default:
+        break;
+    }
+}
+
+static uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap)
+{
+    uint32_t val;
+    rap &= 127;
+    switch (rap) {
+    case BCR_LNKST:
+    case BCR_LED1:
+    case BCR_LED2:
+    case BCR_LED3:
+        val = s->bcr[rap] & ~0x8000;
+        val |= (val & 0x017f & s->lnkst) ? 0x8000 : 0;
+        break;
+    default:
+        val = rap < 32 ? s->bcr[rap] : 0;
+        break;
+    }
+#ifdef PCNET_DEBUG_BCR
+    printf("pcnet_bcr_readw rap=%d val=0x%04x\n", rap, val);
+#endif
+    return val;
+}
+
+static void pcnet_h_reset(PCNetState *s)
+{
+    int i;
+    uint16_t checksum;
+
+    /* Initialize the PROM */
+
+    memcpy(s->prom, s->nd->macaddr, 6);
+    s->prom[12] = s->prom[13] = 0x00;
+    s->prom[14] = s->prom[15] = 0x57;
+
+    for (i = 0,checksum = 0; i < 16; i++)
+        checksum += s->prom[i];
+    *(uint16_t *)&s->prom[12] = cpu_to_le16(checksum);
+
+
+    s->bcr[BCR_MSRDA] = 0x0005;
+    s->bcr[BCR_MSWRA] = 0x0005;
+    s->bcr[BCR_MC   ] = 0x0002;
+    s->bcr[BCR_LNKST] = 0x00c0;
+    s->bcr[BCR_LED1 ] = 0x0084;
+    s->bcr[BCR_LED2 ] = 0x0088;
+    s->bcr[BCR_LED3 ] = 0x0090;
+    s->bcr[BCR_FDC  ] = 0x0000;
+    s->bcr[BCR_BSBC ] = 0x9001;
+    s->bcr[BCR_EECAS] = 0x0002;
+    s->bcr[BCR_SWS  ] = 0x0200;
+    s->bcr[BCR_PLAT ] = 0xff06;
+
+    pcnet_s_reset(s);
+}
+
+static void pcnet_aprom_writeb(void *opaque, uint32_t addr, uint32_t val)
+{
+    PCNetState *s = opaque;
+#ifdef PCNET_DEBUG
+    printf("pcnet_aprom_writeb addr=0x%08x val=0x%02x\n", addr, val);
+#endif    
+    /* Check APROMWE bit to enable write access */
+    if (pcnet_bcr_readw(s,2) & 0x80)
+        s->prom[addr & 15] = val;
+}       
+
+static uint32_t pcnet_aprom_readb(void *opaque, uint32_t addr)
+{
+    PCNetState *s = opaque;
+    uint32_t val = s->prom[addr &= 15];
+#ifdef PCNET_DEBUG
+    printf("pcnet_aprom_readb addr=0x%08x val=0x%02x\n", addr, val);
+#endif
+    return val;
+}
+
+static void pcnet_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
+{
+    PCNetState *s = opaque;
+    pcnet_poll_timer(s);
+#ifdef PCNET_DEBUG_IO
+    printf("pcnet_ioport_writew addr=0x%08x val=0x%04x\n", addr, val);
+#endif
+    if (!BCR_DWIO(s)) {
+        switch (addr & 0x0f) {
+        case 0x00: /* RDP */
+            pcnet_csr_writew(s, s->rap, val);
+            break;
+        case 0x02:
+            s->rap = val & 0x7f;
+            break;
+        case 0x06:
+            pcnet_bcr_writew(s, s->rap, val);
+            break;
+        }
+    }
+    pcnet_update_irq(s);
+}
+
+static uint32_t pcnet_ioport_readw(void *opaque, uint32_t addr)
+{
+    PCNetState *s = opaque;
+    uint32_t val = -1;
+    pcnet_poll_timer(s);
+    if (!BCR_DWIO(s)) {
+        switch (addr & 0x0f) {
+        case 0x00: /* RDP */
+            val = pcnet_csr_readw(s, s->rap);
+            break;
+        case 0x02:
+            val = s->rap;
+            break;
+        case 0x04:
+            pcnet_s_reset(s);
+            val = 0;
+            break;
+        case 0x06:
+            val = pcnet_bcr_readw(s, s->rap);
+            break;
+        }
+    }
+    pcnet_update_irq(s);
+#ifdef PCNET_DEBUG_IO
+    printf("pcnet_ioport_readw addr=0x%08x val=0x%04x\n", addr, val & 0xffff);
+#endif
+    return val;
+}
+
+static void pcnet_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
+{
+    PCNetState *s = opaque;
+    pcnet_poll_timer(s);
+#ifdef PCNET_DEBUG_IO
+    printf("pcnet_ioport_writel addr=0x%08x val=0x%08x\n", addr, val);
+#endif
+    if (BCR_DWIO(s)) {
+        switch (addr & 0x0f) {
+        case 0x00: /* RDP */
+            pcnet_csr_writew(s, s->rap, val & 0xffff);
+            break;
+        case 0x04:
+            s->rap = val & 0x7f;
+            break;
+        case 0x0c:
+            pcnet_bcr_writew(s, s->rap, val & 0xffff);
+            break;
+        }
+    } else
+    if ((addr & 0x0f) == 0) {
+        /* switch device to dword i/o mode */
+        pcnet_bcr_writew(s, BCR_BSBC, pcnet_bcr_readw(s, BCR_BSBC) | 0x0080);
+#ifdef PCNET_DEBUG_IO
+        printf("device switched into dword i/o mode\n");
+#endif        
+    }
+    pcnet_update_irq(s);
+}
+
+static uint32_t pcnet_ioport_readl(void *opaque, uint32_t addr)
+{
+    PCNetState *s = opaque;
+    uint32_t val = -1;
+    pcnet_poll_timer(s);
+    if (BCR_DWIO(s)) {  
+        switch (addr & 0x0f) {
+        case 0x00: /* RDP */
+            val = pcnet_csr_readw(s, s->rap);
+            break;
+        case 0x04:
+            val = s->rap;
+            break;
+        case 0x08:
+            pcnet_s_reset(s);
+            val = 0;
+            break;
+        case 0x0c:
+            val = pcnet_bcr_readw(s, s->rap);
+            break;
+        }
+    }
+    pcnet_update_irq(s);
+#ifdef PCNET_DEBUG_IO
+    printf("pcnet_ioport_readl addr=0x%08x val=0x%08x\n", addr, val);
+#endif
+    return val;
+}
+
+static void pcnet_ioport_map(PCIDevice *pci_dev, int region_num, 
+                             uint32_t addr, uint32_t size, int type)
+{
+    PCNetState *d = (PCNetState *)pci_dev;
+
+#ifdef PCNET_DEBUG_IO
+    printf("pcnet_ioport_map addr=0x%04x size=0x%04x\n", addr, size);
+#endif
+
+    register_ioport_write(addr, 16, 1, pcnet_aprom_writeb, d);
+    register_ioport_read(addr, 16, 1, pcnet_aprom_readb, d);
+    
+    register_ioport_write(addr + 0x10, 0x10, 2, pcnet_ioport_writew, d);
+    register_ioport_read(addr + 0x10, 0x10, 2, pcnet_ioport_readw, d);
+    register_ioport_write(addr + 0x10, 0x10, 4, pcnet_ioport_writel, d);
+    register_ioport_read(addr + 0x10, 0x10, 4, pcnet_ioport_readl, d);
+}
+
+static void pcnet_mmio_writeb(void *opaque, target_phys_addr_t addr, uint32_t 
val)
+{
+    PCNetState *d = opaque;
+#ifdef PCNET_DEBUG_IO
+    printf("pcnet_mmio_writeb addr=0x%08x val=0x%02x\n", addr, val);
+#endif
+    if (!(addr & 0x10))
+        pcnet_aprom_writeb(d, addr & 0x0f, val);
+}
+
+static uint32_t pcnet_mmio_readb(void *opaque, target_phys_addr_t addr) 
+{
+    PCNetState *d = opaque;
+    uint32_t val = -1;
+    if (!(addr & 0x10))
+        val = pcnet_aprom_readb(d, addr & 0x0f);
+#ifdef PCNET_DEBUG_IO
+    printf("pcnet_mmio_readb addr=0x%08x val=0x%02x\n", addr, val & 0xff);
+#endif
+    return val;
+}
+
+static void pcnet_mmio_writew(void *opaque, target_phys_addr_t addr, uint32_t 
val)
+{
+    PCNetState *d = opaque;
+#ifdef PCNET_DEBUG_IO
+    printf("pcnet_mmio_writew addr=0x%08x val=0x%04x\n", addr, val);
+#endif
+    if (addr & 0x10)
+        pcnet_ioport_writew(d, addr & 0x0f, val);
+    else {
+        addr &= 0x0f;
+        pcnet_aprom_writeb(d, addr, val & 0xff);
+        pcnet_aprom_writeb(d, addr+1, (val & 0xff00) >> 8);
+    }
+}
+
+static uint32_t pcnet_mmio_readw(void *opaque, target_phys_addr_t addr) 
+{
+    PCNetState *d = opaque;
+    uint32_t val = -1;
+    if (addr & 0x10)
+        val = pcnet_ioport_readw(d, addr & 0x0f);
+    else {
+        addr &= 0x0f;
+        val = pcnet_aprom_readb(d, addr+1);
+        val <<= 8;
+        val |= pcnet_aprom_readb(d, addr);
+    }
+#ifdef PCNET_DEBUG_IO
+    printf("pcnet_mmio_readw addr=0x%08x val = 0x%04x\n", addr, val & 0xffff);
+#endif
+    return val;
+}
+
+static void pcnet_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t 
val)
+{
+    PCNetState *d = opaque;
+#ifdef PCNET_DEBUG_IO
+    printf("pcnet_mmio_writel addr=0x%08x val=0x%08x\n", addr, val);
+#endif
+    if (addr & 0x10)
+        pcnet_ioport_writel(d, addr & 0x0f, val);
+    else {
+        addr &= 0x0f;
+        pcnet_aprom_writeb(d, addr, val & 0xff);
+        pcnet_aprom_writeb(d, addr+1, (val & 0xff00) >> 8);
+        pcnet_aprom_writeb(d, addr+2, (val & 0xff0000) >> 16);
+        pcnet_aprom_writeb(d, addr+3, (val & 0xff000000) >> 24);
+    }
+}
+
+static uint32_t pcnet_mmio_readl(void *opaque, target_phys_addr_t addr) 
+{
+    PCNetState *d = opaque;
+    uint32_t val;
+    if (addr & 0x10)
+        val = pcnet_ioport_readl(d, addr & 0x0f);
+    else {
+        addr &= 0x0f;
+        val = pcnet_aprom_readb(d, addr+3);
+        val <<= 8;
+        val |= pcnet_aprom_readb(d, addr+2);
+        val <<= 8;
+        val |= pcnet_aprom_readb(d, addr+1);
+        val <<= 8;
+        val |= pcnet_aprom_readb(d, addr);
+    }
+#ifdef PCNET_DEBUG_IO
+    printf("pcnet_mmio_readl addr=0x%08x val=0x%08x\n", addr, val);
+#endif
+    return val;
+}
+
+
+static CPUWriteMemoryFunc *pcnet_mmio_write[] = {
+    (CPUWriteMemoryFunc *)&pcnet_mmio_writeb,
+    (CPUWriteMemoryFunc *)&pcnet_mmio_writew,
+    (CPUWriteMemoryFunc *)&pcnet_mmio_writel
+};
+
+static CPUReadMemoryFunc *pcnet_mmio_read[] = {
+    (CPUReadMemoryFunc *)&pcnet_mmio_readb,
+    (CPUReadMemoryFunc *)&pcnet_mmio_readw,
+    (CPUReadMemoryFunc *)&pcnet_mmio_readl
+};
+
+static void pcnet_mmio_map(PCIDevice *pci_dev, int region_num, 
+                            uint32_t addr, uint32_t size, int type)
+{
+    PCNetState *d = (PCNetState *)pci_dev;
+
+#ifdef PCNET_DEBUG_IO
+    printf("pcnet_ioport_map addr=0x%08x 0x%08x\n", addr, size);
+#endif
+
+    cpu_register_physical_memory(addr, PCNET_PNPMMIO_SIZE, d->mmio_io_addr);
+}
+
+void pci_pcnet_init(PCIBus *bus, NetDriverState *nd)
+{
+    PCNetState *d;
+    uint8_t *pci_conf;
+
+#if 0
+    printf("sizeof(RMD)=%d, sizeof(TMD)=%d\n", 
+        sizeof(struct pcnet_RMD), sizeof(struct pcnet_TMD));
+#endif
+
+    d = (PCNetState *)pci_register_device(bus, "PCNet", sizeof(PCNetState),
+                                          -1, NULL, NULL);
+                                          
+    pci_conf = d->dev.config;
+    
+    *(uint16_t *)&pci_conf[0x00] = cpu_to_le16(0x1022);
+    *(uint16_t *)&pci_conf[0x02] = cpu_to_le16(0x2000);    
+    *(uint16_t *)&pci_conf[0x04] = cpu_to_le16(0x0007); 
+    *(uint16_t *)&pci_conf[0x06] = cpu_to_le16(0x0280);
+    pci_conf[0x08] = 0x10;
+    pci_conf[0x09] = 0x00;
+    pci_conf[0x0a] = 0x00; // ethernet network controller 
+    pci_conf[0x0b] = 0x02;
+    pci_conf[0x0e] = 0x00; // header_type
+    
+    *(uint32_t *)&pci_conf[0x10] = cpu_to_le32(0x00000001);
+    *(uint32_t *)&pci_conf[0x14] = cpu_to_le32(0x00000000);
+    
+    pci_conf[0x3d] = 1; // interrupt pin 0
+    pci_conf[0x3e] = 0x06;
+    pci_conf[0x3f] = 0xff;
+
+    /* Handler for memory-mapped I/O */
+    d->mmio_io_addr =
+      cpu_register_io_memory(0, pcnet_mmio_read, pcnet_mmio_write, d);
+
+    pci_register_io_region((PCIDevice *)d, 0, PCNET_IOPORT_SIZE, 
+                           PCI_ADDRESS_SPACE_IO, pcnet_ioport_map);
+                           
+    pci_register_io_region((PCIDevice *)d, 1, PCNET_PNPMMIO_SIZE, 
+                           PCI_ADDRESS_SPACE_MEM, pcnet_mmio_map);
+                           
+    d->poll_timer = qemu_new_timer(vm_clock, pcnet_poll_timer, d);
+
+    d->nd = nd;
+
+    pcnet_h_reset(d);
+
+    qemu_add_read_packet(nd, pcnet_can_receive, pcnet_receive, d);
+}
diff -r dd108e5ad24d -r f0dc15fd3c1b tools/ioemu/hw/pcnet.h
--- /dev/null   Wed Aug 31 22:37:21 2005
+++ b/tools/ioemu/hw/pcnet.h    Wed Aug 31 23:22:45 2005
@@ -0,0 +1,583 @@
+/*
+ * QEMU AMD PC-Net II (Am79C970A) emulation
+ * 
+ * Copyright (c) 2004 Antony T Curtis
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/* This software was written to be compatible with the specification:
+ * AMD Am79C970A PCnet-PCI II Ethernet Controller Data-Sheet
+ * AMD Publication# 19436  Rev:E  Amendment/0  Issue Date: June 2000
+ */
+
+#ifdef __GNUC__
+#define PACKED(A) A __attribute__ ((packed))
+#else
+#error FixMe
+#endif
+
+/* BUS CONFIGURATION REGISTERS */
+#define BCR_MSRDA    0
+#define BCR_MSWRA    1
+#define BCR_MC       2
+#define BCR_LNKST    4
+#define BCR_LED1     5
+#define BCR_LED2     6
+#define BCR_LED3     7
+#define BCR_FDC      9
+#define BCR_BSBC     18
+#define BCR_EECAS    19
+#define BCR_SWS      20
+#define BCR_PLAT     22
+
+#define BCR_DWIO(S)      !!((S)->bcr[BCR_BSBC] & 0x0080)
+#define BCR_SSIZE32(S)   !!((S)->bcr[BCR_SWS ] & 0x0100)
+#define BCR_SWSTYLE(S)     ((S)->bcr[BCR_SWS ] & 0x00FF)
+
+#define CSR_INIT(S)      !!(((S)->csr[0])&0x0001)
+#define CSR_STRT(S)      !!(((S)->csr[0])&0x0002)
+#define CSR_STOP(S)      !!(((S)->csr[0])&0x0004)
+#define CSR_TDMD(S)      !!(((S)->csr[0])&0x0008)
+#define CSR_TXON(S)      !!(((S)->csr[0])&0x0010)
+#define CSR_RXON(S)      !!(((S)->csr[0])&0x0020)
+#define CSR_INEA(S)      !!(((S)->csr[0])&0x0040)
+#define CSR_LAPPEN(S)    !!(((S)->csr[3])&0x0020)
+#define CSR_DXSUFLO(S)   !!(((S)->csr[3])&0x0040)
+#define CSR_ASTRP_RCV(S) !!(((S)->csr[4])&0x0800)
+#define CSR_DPOLL(S)     !!(((S)->csr[4])&0x1000)
+#define CSR_SPND(S)      !!(((S)->csr[5])&0x0001)
+#define CSR_LTINTEN(S)   !!(((S)->csr[5])&0x4000)
+#define CSR_TOKINTD(S)   !!(((S)->csr[5])&0x8000)
+#define CSR_DRX(S)       !!(((S)->csr[15])&0x0001)
+#define CSR_DTX(S)       !!(((S)->csr[15])&0x0002)
+#define CSR_LOOP(S)      !!(((S)->csr[15])&0x0004)
+#define CSR_DRCVPA(S)    !!(((S)->csr[15])&0x2000)
+#define CSR_DRCVBC(S)    !!(((S)->csr[15])&0x4000)
+#define CSR_PROM(S)      !!(((S)->csr[15])&0x8000)
+
+#define CSR_CRBC(S)      ((S)->csr[40])
+#define CSR_CRST(S)      ((S)->csr[41])
+#define CSR_CXBC(S)      ((S)->csr[42])
+#define CSR_CXST(S)      ((S)->csr[43])
+#define CSR_NRBC(S)      ((S)->csr[44])
+#define CSR_NRST(S)      ((S)->csr[45])
+#define CSR_POLL(S)      ((S)->csr[46])
+#define CSR_PINT(S)      ((S)->csr[47])
+#define CSR_RCVRC(S)     ((S)->csr[72])
+#define CSR_XMTRC(S)     ((S)->csr[74])
+#define CSR_RCVRL(S)     ((S)->csr[76])
+#define CSR_XMTRL(S)     ((S)->csr[78])
+#define CSR_MISSC(S)     ((S)->csr[112])
+
+#define CSR_IADR(S)      ((S)->csr[ 1] | ((S)->csr[ 2] << 16))
+#define CSR_CRBA(S)      ((S)->csr[18] | ((S)->csr[19] << 16))
+#define CSR_CXBA(S)      ((S)->csr[20] | ((S)->csr[21] << 16))
+#define CSR_NRBA(S)      ((S)->csr[22] | ((S)->csr[23] << 16))
+#define CSR_BADR(S)      ((S)->csr[24] | ((S)->csr[25] << 16))
+#define CSR_NRDA(S)      ((S)->csr[26] | ((S)->csr[27] << 16))
+#define CSR_CRDA(S)      ((S)->csr[28] | ((S)->csr[29] << 16))
+#define CSR_BADX(S)      ((S)->csr[30] | ((S)->csr[31] << 16))
+#define CSR_NXDA(S)      ((S)->csr[32] | ((S)->csr[33] << 16))
+#define CSR_CXDA(S)      ((S)->csr[34] | ((S)->csr[35] << 16))
+#define CSR_NNRD(S)      ((S)->csr[36] | ((S)->csr[37] << 16))
+#define CSR_NNXD(S)      ((S)->csr[38] | ((S)->csr[39] << 16))
+#define CSR_PXDA(S)      ((S)->csr[60] | ((S)->csr[61] << 16))
+#define CSR_NXBA(S)      ((S)->csr[64] | ((S)->csr[65] << 16))
+
+#define PHYSADDR(S,A) \
+  (BCR_SSIZE32(S) ? (A) : (A) | ((0xff00 & (uint32_t)(s)->csr[2])<<16))
+
+struct pcnet_initblk16 {
+    uint16_t mode;
+    uint16_t padr1;
+    uint16_t padr2;
+    uint16_t padr3;
+    uint16_t ladrf1;
+    uint16_t ladrf2;
+    uint16_t ladrf3;
+    uint16_t ladrf4;
+    unsigned PACKED(rdra:24);
+    unsigned PACKED(res1:5);
+    unsigned PACKED(rlen:3);
+    unsigned PACKED(tdra:24);
+    unsigned PACKED(res2:5);
+    unsigned PACKED(tlen:3);
+};
+
+struct pcnet_initblk32 {
+    uint16_t mode;
+    unsigned PACKED(res1:4);
+    unsigned PACKED(rlen:4);
+    unsigned PACKED(res2:4);
+    unsigned PACKED(tlen:4);
+    uint16_t padr1;
+    uint16_t padr2;
+    uint16_t padr3;
+    uint16_t _res;
+    uint16_t ladrf1;
+    uint16_t ladrf2;
+    uint16_t ladrf3;
+    uint16_t ladrf4;
+    uint32_t rdra;
+    uint32_t tdra;
+};
+
+struct pcnet_TMD {
+    struct {
+        unsigned tbadr:32;
+    } tmd0;
+    struct {
+        unsigned PACKED(bcnt:12), PACKED(ones:4), PACKED(res:7), PACKED(bpe:1);
+        unsigned PACKED(enp:1), PACKED(stp:1), PACKED(def:1), PACKED(one:1);
+        unsigned PACKED(ltint:1), PACKED(nofcs:1), PACKED(err:1), 
PACKED(own:1);
+    } tmd1;
+    struct {
+        unsigned PACKED(trc:4), PACKED(res:12);
+        unsigned PACKED(tdr:10), PACKED(rtry:1), PACKED(lcar:1);
+        unsigned PACKED(lcol:1), PACKED(exdef:1), PACKED(uflo:1), 
PACKED(buff:1);
+    } tmd2;
+    struct {
+        unsigned res:32;
+    } tmd3;    
+};
+
+struct pcnet_RMD {
+    struct {
+        unsigned rbadr:32;
+    } rmd0;
+    struct {
+        unsigned PACKED(bcnt:12), PACKED(ones:4), PACKED(res:4);
+        unsigned PACKED(bam:1), PACKED(lafm:1), PACKED(pam:1), PACKED(bpe:1);
+        unsigned PACKED(enp:1), PACKED(stp:1), PACKED(buff:1), PACKED(crc:1);
+        unsigned PACKED(oflo:1), PACKED(fram:1), PACKED(err:1), PACKED(own:1);
+    } rmd1;
+    struct {
+        unsigned PACKED(mcnt:12), PACKED(zeros:4);
+        unsigned PACKED(rpc:8), PACKED(rcc:8);
+    } rmd2;    
+    struct {
+        unsigned res:32;
+    } rmd3;    
+};
+
+
+#define PRINT_TMD(T) printf(    \
+        "TMD0 : TBADR=0x%08x\n" \
+        "TMD1 : OWN=%d, ERR=%d, FCS=%d, LTI=%d, "       \
+        "ONE=%d, DEF=%d, STP=%d, ENP=%d,\n"             \
+        "       BPE=%d, BCNT=%d\n"                      \
+        "TMD2 : BUF=%d, UFL=%d, EXD=%d, LCO=%d, "       \
+        "LCA=%d, RTR=%d,\n"                             \
+        "       TDR=%d, TRC=%d\n",                      \
+        (T)->tmd0.tbadr,                                \
+        (T)->tmd1.own, (T)->tmd1.err, (T)->tmd1.nofcs,  \
+        (T)->tmd1.ltint, (T)->tmd1.one, (T)->tmd1.def,  \
+        (T)->tmd1.stp, (T)->tmd1.enp, (T)->tmd1.bpe,    \
+        4096-(T)->tmd1.bcnt,                            \
+        (T)->tmd2.buff, (T)->tmd2.uflo, (T)->tmd2.exdef,\
+        (T)->tmd2.lcol, (T)->tmd2.lcar, (T)->tmd2.rtry, \
+        (T)->tmd2.tdr, (T)->tmd2.trc)
+
+#define PRINT_RMD(R) printf(    \
+        "RMD0 : RBADR=0x%08x\n" \
+        "RMD1 : OWN=%d, ERR=%d, FRAM=%d, OFLO=%d, "     \
+        "CRC=%d, BUFF=%d, STP=%d, ENP=%d,\n       "     \
+        "BPE=%d, PAM=%d, LAFM=%d, BAM=%d, ONES=%d, BCNT=%d\n"    \
+        "RMD2 : RCC=%d, RPC=%d, MCNT=%d, ZEROS=%d\n",   \
+        (R)->rmd0.rbadr,                                \
+        (R)->rmd1.own, (R)->rmd1.err, (R)->rmd1.fram,   \
+        (R)->rmd1.oflo, (R)->rmd1.crc, (R)->rmd1.buff,  \
+        (R)->rmd1.stp, (R)->rmd1.enp, (R)->rmd1.bpe,    \
+        (R)->rmd1.pam, (R)->rmd1.lafm, (R)->rmd1.bam,   \
+        (R)->rmd1.ones, 4096-(R)->rmd1.bcnt,            \
+        (R)->rmd2.rcc, (R)->rmd2.rpc, (R)->rmd2.mcnt,   \
+        (R)->rmd2.zeros)
+
+static inline void pcnet_tmd_load(PCNetState *s, struct pcnet_TMD *tmd, 
target_phys_addr_t addr)
+{
+    if (!BCR_SWSTYLE(s)) {
+        uint16_t xda[4];
+        cpu_physical_memory_read(addr,
+                (void *)&xda[0], sizeof(xda));
+        ((uint32_t *)tmd)[0] = (xda[0]&0xffff) |
+                ((xda[1]&0x00ff) << 16);
+        ((uint32_t *)tmd)[1] = (xda[2]&0xffff)|
+                ((xda[1] & 0xff00) << 16);
+        ((uint32_t *)tmd)[2] =
+                (xda[3] & 0xffff) << 16;
+        ((uint32_t *)tmd)[3] = 0;
+    }
+    else
+    if (BCR_SWSTYLE(s) != 3)
+        cpu_physical_memory_read(addr, (void *)tmd, 16);
+    else {
+        uint32_t xda[4];
+        cpu_physical_memory_read(addr,
+                (void *)&xda[0], sizeof(xda));
+        ((uint32_t *)tmd)[0] = xda[2];
+        ((uint32_t *)tmd)[1] = xda[1];
+        ((uint32_t *)tmd)[2] = xda[0];
+        ((uint32_t *)tmd)[3] = xda[3];
+    }
+}
+
+static inline void pcnet_tmd_store(PCNetState *s, struct pcnet_TMD *tmd, 
target_phys_addr_t addr)
+{
+    cpu_physical_memory_set_dirty(addr);
+    if (!BCR_SWSTYLE(s)) {
+        uint16_t xda[4];
+        xda[0] = ((uint32_t *)tmd)[0] & 0xffff;
+        xda[1] = ((((uint32_t *)tmd)[0]>>16)&0x00ff) |
+            ((((uint32_t *)tmd)[1]>>16)&0xff00);
+        xda[2] = ((uint32_t *)tmd)[1] & 0xffff;
+        xda[3] = ((uint32_t *)tmd)[2] >> 16;
+        cpu_physical_memory_write(addr,
+                (void *)&xda[0], sizeof(xda));
+        cpu_physical_memory_set_dirty(addr+7);
+    }
+    else {
+        if (BCR_SWSTYLE(s) != 3)
+            cpu_physical_memory_write(addr, (void *)tmd, 16);
+        else {
+            uint32_t xda[4];
+            xda[0] = ((uint32_t *)tmd)[2];
+            xda[1] = ((uint32_t *)tmd)[1];
+            xda[2] = ((uint32_t *)tmd)[0];
+            xda[3] = ((uint32_t *)tmd)[3];
+            cpu_physical_memory_write(addr,
+                    (void *)&xda[0], sizeof(xda));
+        }
+        cpu_physical_memory_set_dirty(addr+15);
+    }
+}
+
+static inline void pcnet_rmd_load(PCNetState *s, struct pcnet_RMD *rmd, 
target_phys_addr_t addr)
+{
+    if (!BCR_SWSTYLE(s)) {
+        uint16_t rda[4];
+        cpu_physical_memory_read(addr,
+                (void *)&rda[0], sizeof(rda));
+        ((uint32_t *)rmd)[0] = (rda[0]&0xffff)|
+                ((rda[1] & 0x00ff) << 16);
+        ((uint32_t *)rmd)[1] = (rda[2]&0xffff)|
+                ((rda[1] & 0xff00) << 16);
+        ((uint32_t *)rmd)[2] = rda[3] & 0xffff;
+        ((uint32_t *)rmd)[3] = 0;
+    }
+    else
+    if (BCR_SWSTYLE(s) != 3)
+        cpu_physical_memory_read(addr, (void *)rmd, 16);
+    else {
+        uint32_t rda[4];
+        cpu_physical_memory_read(addr,
+                (void *)&rda[0], sizeof(rda));
+        ((uint32_t *)rmd)[0] = rda[2];
+        ((uint32_t *)rmd)[1] = rda[1];
+        ((uint32_t *)rmd)[2] = rda[0];
+        ((uint32_t *)rmd)[3] = rda[3];
+    }
+}
+
+static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd, 
target_phys_addr_t addr)
+{
+    cpu_physical_memory_set_dirty(addr);
+    if (!BCR_SWSTYLE(s)) {
+        uint16_t rda[4];                        \
+        rda[0] = ((uint32_t *)rmd)[0] & 0xffff; \
+        rda[1] = ((((uint32_t *)rmd)[0]>>16)&0xff)|\
+            ((((uint32_t *)rmd)[1]>>16)&0xff00);\
+        rda[2] = ((uint32_t *)rmd)[1] & 0xffff; \
+        rda[3] = ((uint32_t *)rmd)[2] & 0xffff; \
+        cpu_physical_memory_write(addr,         \
+                (void *)&rda[0], sizeof(rda));  \
+        cpu_physical_memory_set_dirty(addr+7);
+    }
+    else {
+        if (BCR_SWSTYLE(s) != 3)
+            cpu_physical_memory_write(addr, (void *)rmd, 16);
+        else {
+            uint32_t rda[4];
+            rda[0] = ((uint32_t *)rmd)[2];
+            rda[1] = ((uint32_t *)rmd)[1];
+            rda[2] = ((uint32_t *)rmd)[0];
+            rda[3] = ((uint32_t *)rmd)[3];
+            cpu_physical_memory_write(addr,
+                    (void *)&rda[0], sizeof(rda));
+        }
+        cpu_physical_memory_set_dirty(addr+15);
+    }
+}
+
+
+#define TMDLOAD(TMD,ADDR) pcnet_tmd_load(s,TMD,ADDR)
+
+#define TMDSTORE(TMD,ADDR) pcnet_tmd_store(s,TMD,ADDR)
+
+#define RMDLOAD(RMD,ADDR) pcnet_rmd_load(s,RMD,ADDR)
+
+#define RMDSTORE(RMD,ADDR) pcnet_rmd_store(s,RMD,ADDR)
+
+#if 1
+
+#define CHECK_RMD(ADDR,RES) do {                \
+    struct pcnet_RMD rmd;                       \
+    RMDLOAD(&rmd,(ADDR));                       \
+    (RES) |= (rmd.rmd1.ones != 15)              \
+          || (rmd.rmd2.zeros != 0);             \
+} while (0)
+
+#define CHECK_TMD(ADDR,RES) do {                \
+    struct pcnet_TMD tmd;                       \
+    TMDLOAD(&tmd,(ADDR));                       \
+    (RES) |= (tmd.tmd1.ones != 15);             \
+} while (0)
+
+#else
+
+#define CHECK_RMD(ADDR,RES) do {                \
+    switch (BCR_SWSTYLE(s)) {                   \
+    case 0x00:                                  \
+        do {                                    \
+            uint16_t rda[4];                    \
+            cpu_physical_memory_read((ADDR),    \
+                (void *)&rda[0], sizeof(rda));  \
+            (RES) |= (rda[2] & 0xf000)!=0xf000; \
+            (RES) |= (rda[3] & 0xf000)!=0x0000; \
+        } while (0);                            \
+        break;                                  \
+    case 0x01:                                  \
+    case 0x02:                                  \
+        do {                                    \
+            uint32_t rda[4];                    \
+            cpu_physical_memory_read((ADDR),    \
+                (void *)&rda[0], sizeof(rda)); \
+            (RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \
+            (RES) |= (rda[2] & 0x0000f000L)!=0x00000000L; \
+        } while (0);                            \
+        break;                                  \
+    case 0x03:                                  \
+        do {                                    \
+            uint32_t rda[4];                    \
+            cpu_physical_memory_read((ADDR),    \
+                (void *)&rda[0], sizeof(rda)); \
+            (RES) |= (rda[0] & 0x0000f000L)!=0x00000000L; \
+            (RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \
+        } while (0);                            \
+        break;                                  \
+    }                                           \
+} while (0)
+
+#define CHECK_TMD(ADDR,RES) do {                \
+    switch (BCR_SWSTYLE(s)) {                   \
+    case 0x00:                                  \
+        do {                                    \
+            uint16_t xda[4];                    \
+            cpu_physical_memory_read((ADDR),    \
+                (void *)&xda[0], sizeof(xda));  \
+            (RES) |= (xda[2] & 0xf000)!=0xf000;\
+        } while (0);                            \
+        break;                                  \
+    case 0x01:                                  \
+    case 0x02:                                  \
+    case 0x03:                                  \
+        do {                                    \
+            uint32_t xda[4];                    \
+            cpu_physical_memory_read((ADDR),    \
+                (void *)&xda[0], sizeof(xda));  \
+            (RES) |= (xda[1] & 0x0000f000L)!=0x0000f000L; \
+        } while (0);                            \
+        break;                                  \
+    }                                           \
+} while (0)
+
+#endif
+
+#define PRINT_PKTHDR(BUF) do {                  \
+    struct ether_header *hdr = (void *)(BUF);   \
+    printf("packet dhost=%02x:%02x:%02x:%02x:%02x:%02x, "       \
+           "shost=%02x:%02x:%02x:%02x:%02x:%02x, "              \
+           "type=0x%04x (bcast=%d)\n",                          \
+           hdr->ether_dhost[0],hdr->ether_dhost[1],hdr->ether_dhost[2], \
+           hdr->ether_dhost[3],hdr->ether_dhost[4],hdr->ether_dhost[5], \
+           hdr->ether_shost[0],hdr->ether_shost[1],hdr->ether_shost[2], \
+           hdr->ether_shost[3],hdr->ether_shost[4],hdr->ether_shost[5], \
+           htons(hdr->ether_type),                                      \
+           !!ETHER_IS_MULTICAST(hdr->ether_dhost));                     \
+} while (0)
+
+#define MULTICAST_FILTER_LEN 8
+
+static inline uint32_t lnc_mchash(const uint8_t *ether_addr)
+{
+#define LNC_POLYNOMIAL          0xEDB88320UL
+    uint32_t crc = 0xFFFFFFFF;
+    int idx, bit;
+    uint8_t data;
+
+    for (idx = 0; idx < ETHER_ADDR_LEN; idx++) {
+        for (data = *ether_addr++, bit = 0; bit < MULTICAST_FILTER_LEN; bit++) 
{
+            crc = (crc >> 1) ^ (((crc ^ data) & 1) ? LNC_POLYNOMIAL : 0);
+            data >>= 1;
+        }
+    }
+    return crc;
+#undef LNC_POLYNOMIAL
+}
+
+#define MIN(X,Y) ((X>Y) ? (Y) : (X))
+
+#define CRC(crc, ch)    (crc = (crc >> 8) ^ crctab[(crc ^ (ch)) & 0xff])
+
+/* generated using the AUTODIN II polynomial
+ *     x^32 + x^26 + x^23 + x^22 + x^16 +
+ *     x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + 1
+ */
+static const uint32_t crctab[256] = {
+       0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
+       0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
+       0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+       0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
+       0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+       0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+       0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
+       0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
+       0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+       0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+       0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
+       0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+       0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
+       0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+       0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+       0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
+       0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
+       0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+       0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
+       0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+       0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+       0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
+       0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
+       0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+       0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+       0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
+       0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+       0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+       0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
+       0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+       0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
+       0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
+       0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+       0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
+       0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+       0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+       0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
+       0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
+       0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+       0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+       0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
+       0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+       0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
+       0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
+       0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+       0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
+       0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
+       0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+       0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
+       0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+       0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+       0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
+       0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
+       0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+       0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+       0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+       0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+       0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
+       0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
+       0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+       0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
+       0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
+       0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+       0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
+};
+
+static inline int padr_match(PCNetState *s, const uint8_t *buf, int size)
+{
+    struct ether_header *hdr = (void *)buf;
+    uint8_t padr[6] = { 
+        s->csr[12] & 0xff, s->csr[12] >> 8,
+        s->csr[13] & 0xff, s->csr[13] >> 8,
+        s->csr[14] & 0xff, s->csr[14] >> 8 
+    };
+    int result = (!CSR_DRCVPA(s)) && !bcmp(hdr->ether_dhost, padr, 6);
+#ifdef PCNET_DEBUG_MATCH
+    printf("packet dhost=%02x:%02x:%02x:%02x:%02x:%02x, "
+           "padr=%02x:%02x:%02x:%02x:%02x:%02x\n",
+           hdr->ether_dhost[0],hdr->ether_dhost[1],hdr->ether_dhost[2],
+           hdr->ether_dhost[3],hdr->ether_dhost[4],hdr->ether_dhost[5],
+           padr[0],padr[1],padr[2],padr[3],padr[4],padr[5]);
+    printf("padr_match result=%d\n", result);
+#endif
+    return result;
+}
+
+static inline int padr_bcast(PCNetState *s, const uint8_t *buf, int size)
+{
+    static uint8_t BCAST[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+    struct ether_header *hdr = (void *)buf;
+    int result = !CSR_DRCVBC(s) && !bcmp(hdr->ether_dhost, BCAST, 6);
+#ifdef PCNET_DEBUG_MATCH
+    printf("padr_bcast result=%d\n", result);
+#endif
+    return result;
+}
+
+static inline int ladr_match(PCNetState *s, const uint8_t *buf, int size)
+{
+    struct ether_header *hdr = (void *)buf;
+    if ((*(hdr->ether_dhost)&0x01) && 
+        ((uint64_t *)&s->csr[8])[0] != 0LL) {
+        uint8_t ladr[8] = { 
+            s->csr[8] & 0xff, s->csr[8] >> 8,
+            s->csr[9] & 0xff, s->csr[9] >> 8,
+            s->csr[10] & 0xff, s->csr[10] >> 8, 
+            s->csr[11] & 0xff, s->csr[11] >> 8 
+        };
+        int index = lnc_mchash(hdr->ether_dhost) >> 26;
+        return !!(ladr[index >> 3] & (1 << (index & 7)));
+    }
+    return 0;
+}
+
+static inline target_phys_addr_t pcnet_rdra_addr(PCNetState *s, int idx) 
+{
+    while (idx < 1) idx += CSR_RCVRL(s);
+    return s->rdra + ((CSR_RCVRL(s) - idx) * (BCR_SWSTYLE(s) ? 16 : 8));
+}
+
+static inline int64_t pcnet_get_next_poll_time(PCNetState *s, int64_t 
current_time)
+{
+    int64_t next_time = current_time + 
+        muldiv64(65536 - (CSR_SPND(s) ? 0 : CSR_POLL(s)), 
+                 ticks_per_sec, 33000000L);
+    if (next_time <= current_time)
+        next_time = current_time + 1;
+    return next_time;
+}
+
+

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>