Index: qemu/hw/pcnet.c
===================================================================
--- qemu.orig/hw/pcnet.c	2008-04-16 18:49:20.000000000 +0000
+++ qemu/hw/pcnet.c	2008-04-16 19:45:11.000000000 +0000
@@ -71,10 +71,10 @@
     uint8_t buffer[4096];
     int tx_busy;
     qemu_irq irq;
-    void (*phys_mem_read)(void *dma_opaque, target_phys_addr_t addr,
-                         uint8_t *buf, int len, int do_bswap);
-    void (*phys_mem_write)(void *dma_opaque, target_phys_addr_t addr,
-                          uint8_t *buf, int len, int do_bswap);
+    DMAReadHandler *phys_mem_read;
+    DMAWriteHandler *phys_mem_write;
+    DMAReadHandler *phys_mem_read_bswap;
+    DMAWriteHandler *phys_mem_write_bswap;
     void *dma_opaque;
 };
 
@@ -341,14 +341,14 @@
             int16_t length;
             int16_t status;
 	} xda;
-        s->phys_mem_read(s->dma_opaque, addr, (void *)&xda, sizeof(xda), 0);
+        s->phys_mem_read(s->dma_opaque, addr, (void *)&xda, sizeof(xda));
         tmd->tbadr = le32_to_cpu(xda.tbadr) & 0xffffff;
         tmd->length = le16_to_cpu(xda.length);
         tmd->status = (le32_to_cpu(xda.tbadr) >> 16) & 0xff00;
         tmd->misc = le16_to_cpu(xda.status) << 16;
         tmd->res = 0;
     } else {
-        s->phys_mem_read(s->dma_opaque, addr, (void *)tmd, sizeof(*tmd), 0);
+        s->phys_mem_read(s->dma_opaque, addr, (void *)tmd, sizeof(*tmd));
         le32_to_cpus(&tmd->tbadr);
         le16_to_cpus((uint16_t *)&tmd->length);
         le16_to_cpus((uint16_t *)&tmd->status);
@@ -375,7 +375,7 @@
                                 ((tmd->status & 0xff00) << 16));
         xda.length = cpu_to_le16(tmd->length);
         xda.status = cpu_to_le16(tmd->misc >> 16);
-        s->phys_mem_write(s->dma_opaque, addr, (void *)&xda, sizeof(xda), 0);
+        s->phys_mem_write(s->dma_opaque, addr, (void *)&xda, sizeof(xda));
     } else {
         struct {
             uint32_t tbadr;
@@ -394,7 +394,7 @@
             xda.tbadr = xda.misc;
             xda.misc = tmp;
         }
-        s->phys_mem_write(s->dma_opaque, addr, (void *)&xda, sizeof(xda), 0);
+        s->phys_mem_write(s->dma_opaque, addr, (void *)&xda, sizeof(xda));
     }
 }
 
@@ -407,14 +407,14 @@
             int16_t buf_length;
             int16_t msg_length;
 	} rda;
-        s->phys_mem_read(s->dma_opaque, addr, (void *)&rda, sizeof(rda), 0);
+        s->phys_mem_read(s->dma_opaque, addr, (void *)&rda, sizeof(rda));
         rmd->rbadr = le32_to_cpu(rda.rbadr) & 0xffffff;
         rmd->buf_length = le16_to_cpu(rda.buf_length);
         rmd->status = (le32_to_cpu(rda.rbadr) >> 16) & 0xff00;
         rmd->msg_length = le16_to_cpu(rda.msg_length);
         rmd->res = 0;
     } else {
-        s->phys_mem_read(s->dma_opaque, addr, (void *)rmd, sizeof(*rmd), 0);
+        s->phys_mem_read(s->dma_opaque, addr, (void *)rmd, sizeof(*rmd));
         le32_to_cpus(&rmd->rbadr);
         le16_to_cpus((uint16_t *)&rmd->buf_length);
         le16_to_cpus((uint16_t *)&rmd->status);
@@ -441,7 +441,7 @@
                                 ((rmd->status & 0xff00) << 16));
         rda.buf_length = cpu_to_le16(rmd->buf_length);
         rda.msg_length = cpu_to_le16(rmd->msg_length);
-        s->phys_mem_write(s->dma_opaque, addr, (void *)&rda, sizeof(rda), 0);
+        s->phys_mem_write(s->dma_opaque, addr, (void *)&rda, sizeof(rda));
     } else {
         struct {
             uint32_t rbadr;
@@ -460,7 +460,7 @@
             rda.rbadr = rda.msg_length;
             rda.msg_length = tmp;
         }
-        s->phys_mem_write(s->dma_opaque, addr, (void *)&rda, sizeof(rda), 0);
+        s->phys_mem_write(s->dma_opaque, addr, (void *)&rda, sizeof(rda));
     }
 }
 
@@ -841,7 +841,7 @@
     if (BCR_SSIZE32(s)) {
         struct pcnet_initblk32 initblk;
         s->phys_mem_read(s->dma_opaque, PHYSADDR(s,CSR_IADR(s)),
-                (uint8_t *)&initblk, sizeof(initblk), 0);
+                (uint8_t *)&initblk, sizeof(initblk));
         mode = le16_to_cpu(initblk.mode);
         rlen = initblk.rlen >> 4;
         tlen = initblk.tlen >> 4;
@@ -857,7 +857,7 @@
     } else {
         struct pcnet_initblk16 initblk;
         s->phys_mem_read(s->dma_opaque, PHYSADDR(s,CSR_IADR(s)),
-                (uint8_t *)&initblk, sizeof(initblk), 0);
+                (uint8_t *)&initblk, sizeof(initblk));
         mode = le16_to_cpu(initblk.mode);
 	ladrf[0] = le16_to_cpu(initblk.ladrf[0]);
 	ladrf[1] = le16_to_cpu(initblk.ladrf[1]);
@@ -1159,7 +1159,11 @@
 #define PCNET_RECV_STORE() do {                                 \
     int count = MIN(4096 - GET_FIELD(rmd.buf_length, RMDL, BCNT),size); \
     target_phys_addr_t rbadr = PHYSADDR(s, rmd.rbadr);          \
-    s->phys_mem_write(s->dma_opaque, rbadr, src, count, CSR_BSWP(s)); \
+                                                                      \
+    if (CSR_BSWP(s))                                                  \
+        s->phys_mem_write_bswap(s->dma_opaque, rbadr, src, count);    \
+    else                                                              \
+        s->phys_mem_write(s->dma_opaque, rbadr, src, count);          \
     src += count; size -= count;                                \
     SET_FIELD(&rmd.msg_length, RMDM, MCNT, count);              \
     SET_FIELD(&rmd.status, RMDS, OWN, 0);                       \
@@ -1228,6 +1232,9 @@
 {
     target_phys_addr_t xmit_cxda = 0;
     int count = CSR_XMTRL(s)-1;
+    IOVector *ivec;
+    unsigned int nsg = 0;
+
     s->xmit_pos = -1;
 
     if (!CSR_TXON(s)) {
@@ -1247,29 +1254,40 @@
         printf("  TMDLOAD 0x%08x\n", PHYSADDR(s,CSR_CXDA(s)));
         PRINT_TMD(&tmd);
 #endif
+        if (CSR_BSWP(s))
+            ivec = iovector_new(2, s->phys_mem_read_bswap,
+                                s->phys_mem_write_bswap,
+                                s->dma_opaque);
+        else
+            ivec = iovector_new(2, s->phys_mem_read, s->phys_mem_write,
+                                s->dma_opaque);
         if (GET_FIELD(tmd.status, TMDS, STP)) {
             s->xmit_pos = 0;
             if (!GET_FIELD(tmd.status, TMDS, ENP)) {
                 int bcnt = 4096 - GET_FIELD(tmd.length, TMDL, BCNT);
-                s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tbadr),
-                                 s->buffer, bcnt, CSR_BSWP(s));
+
+                ivec->sg[nsg].base = PHYSADDR(s, tmd.tbadr);
+                ivec->sg[nsg].len = bcnt;
+                nsg++;
                 s->xmit_pos += bcnt;
             }
             xmit_cxda = PHYSADDR(s,CSR_CXDA(s));
         }
         if (GET_FIELD(tmd.status, TMDS, ENP) && (s->xmit_pos >= 0)) {
             int bcnt = 4096 - GET_FIELD(tmd.length, TMDL, BCNT);
-            s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tbadr),
-                             s->buffer + s->xmit_pos, bcnt, CSR_BSWP(s));
+
+            ivec->sg[nsg].base = PHYSADDR(s, tmd.tbadr);
+            ivec->sg[nsg].len = bcnt;
+            nsg++;
             s->xmit_pos += 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
+            // XXX if (CSR_LOOP(s))
+            //    pcnet_receive(s, s->buffer, s->xmit_pos);
+            //else
                 if (s->vc)
-                    qemu_send_packet(s->vc, s->buffer, s->xmit_pos);
+                    qemu_sendv_packet(s->vc, ivec);
 
             s->csr[0] &= ~0x0008;   /* clear TDMD */
             s->csr[4] |= 0x0004;    /* set TXSTRT */
@@ -1946,18 +1964,6 @@
     cpu_register_physical_memory(addr, PCNET_PNPMMIO_SIZE, d->mmio_index);
 }
 
-static void pci_physical_memory_write(void *dma_opaque, target_phys_addr_t addr,
-                                      uint8_t *buf, int len, int do_bswap)
-{
-    cpu_physical_memory_write(addr, buf, len);
-}
-
-static void pci_physical_memory_read(void *dma_opaque, target_phys_addr_t addr,
-                                     uint8_t *buf, int len, int do_bswap)
-{
-    cpu_physical_memory_read(addr, buf, len);
-}
-
 void pci_pcnet_init(PCIBus *bus, NICInfo *nd, int devfn)
 {
     PCNetState *d;
@@ -2001,8 +2007,10 @@
                            PCI_ADDRESS_SPACE_MEM, pcnet_mmio_map);
 
     d->irq = d->dev.irq[0];
-    d->phys_mem_read = pci_physical_memory_read;
-    d->phys_mem_write = pci_physical_memory_write;
+    d->phys_mem_read = (DMAReadHandler *)pci_device_dma_read;
+    d->phys_mem_write = (DMAWriteHandler *)pci_device_dma_write;
+    d->phys_mem_read_bswap = (DMAReadHandler *)pci_device_dma_read;
+    d->phys_mem_write_bswap = (DMAWriteHandler *)pci_device_dma_write;
     d->pci_dev = &d->dev;
 
     pcnet_common_init(d, nd, "pcnet");
@@ -2074,8 +2082,10 @@
     cpu_register_physical_memory(leaddr, 4, lance_io_memory);
 
     d->irq = irq;
-    d->phys_mem_read = ledma_memory_read;
-    d->phys_mem_write = ledma_memory_write;
+    d->phys_mem_read = (DMAReadHandler *)ledma_memory_read;
+    d->phys_mem_write = (DMAWriteHandler *)ledma_memory_write;
+    d->phys_mem_read_bswap = (DMAReadHandler *)ledma_memory_read_bswap;
+    d->phys_mem_write_bswap = (DMAWriteHandler *)ledma_memory_write_bswap;
 
     pcnet_common_init(d, nd, "lance");
 }
Index: qemu/hw/sparc32_dma.c
===================================================================
--- qemu.orig/hw/sparc32_dma.c	2008-04-16 19:21:24.000000000 +0000
+++ qemu/hw/sparc32_dma.c	2008-04-16 19:45:20.000000000 +0000
@@ -66,7 +66,7 @@
 
 /* Note: on sparc, the lance 16 bit bus is swapped */
 void ledma_memory_read(void *opaque, target_phys_addr_t addr,
-                       uint8_t *buf, int len, int do_bswap)
+                       uint8_t *buf, int len)
 {
     DMAState *s = opaque;
     int i;
@@ -74,20 +74,27 @@
     DPRINTF("DMA write, direction: %c, addr 0x%8.8x\n",
             s->dmaregs[0] & DMA_WRITE_MEM ? 'w': 'r', s->dmaregs[1]);
     addr |= s->dmaregs[3];
-    if (do_bswap) {
-        sparc_iommu_memory_read(s->iommu, addr, buf, len);
-    } else {
-        addr &= ~1;
-        len &= ~1;
-        sparc_iommu_memory_read(s->iommu, addr, buf, len);
-        for(i = 0; i < len; i += 2) {
-            bswap16s((uint16_t *)(buf + i));
-        }
+    addr &= ~1;
+    len &= ~1;
+    sparc_iommu_memory_read(s->iommu, addr, buf, len);
+    for (i = 0; i < len; i += 2) {
+        bswap16s((uint16_t *)(buf + i));
     }
 }
 
+void ledma_memory_read_bswap(void *opaque, target_phys_addr_t addr,
+                             uint8_t *buf, int len)
+{
+    DMAState *s = opaque;
+
+    DPRINTF("DMA write bswapped, direction: %c, addr 0x%8.8x\n",
+            s->dmaregs[0] & DMA_WRITE_MEM ? 'w': 'r', s->dmaregs[1]);
+    addr |= s->dmaregs[3];
+    sparc_iommu_memory_read(s->iommu, addr, buf, len);
+}
+
 void ledma_memory_write(void *opaque, target_phys_addr_t addr,
-                        uint8_t *buf, int len, int do_bswap)
+                        uint8_t *buf, int len)
 {
     DMAState *s = opaque;
     int l, i;
@@ -96,26 +103,33 @@
     DPRINTF("DMA read, direction: %c, addr 0x%8.8x\n",
             s->dmaregs[0] & DMA_WRITE_MEM ? 'w': 'r', s->dmaregs[1]);
     addr |= s->dmaregs[3];
-    if (do_bswap) {
-        sparc_iommu_memory_write(s->iommu, addr, buf, len);
-    } else {
-        addr &= ~1;
-        len &= ~1;
-        while (len > 0) {
-            l = len;
-            if (l > sizeof(tmp_buf))
-                l = sizeof(tmp_buf);
-            for(i = 0; i < l; i += 2) {
-                tmp_buf[i >> 1] = bswap16(*(uint16_t *)(buf + i));
-            }
-            sparc_iommu_memory_write(s->iommu, addr, (uint8_t *)tmp_buf, l);
-            len -= l;
-            buf += l;
-            addr += l;
+    addr &= ~1;
+    len &= ~1;
+    while (len > 0) {
+        l = len;
+        if (l > sizeof(tmp_buf))
+            l = sizeof(tmp_buf);
+        for (i = 0; i < l; i += 2) {
+            tmp_buf[i >> 1] = bswap16(*(uint16_t *)(buf + i));
         }
+        sparc_iommu_memory_write(s->iommu, addr, (uint8_t *)tmp_buf, l);
+        len -= l;
+        buf += l;
+        addr += l;
     }
 }
 
+void ledma_memory_write_bswap(void *opaque, target_phys_addr_t addr,
+                              uint8_t *buf, int len)
+{
+    DMAState *s = opaque;
+
+    DPRINTF("DMA read bswapped, direction: %c, addr 0x%8.8x\n",
+            s->dmaregs[0] & DMA_WRITE_MEM ? 'w': 'r', s->dmaregs[1]);
+    addr |= s->dmaregs[3];
+    sparc_iommu_memory_write(s->iommu, addr, buf, len);
+}
+
 static void dma_set_irq(void *opaque, int irq, int level)
 {
     DMAState *s = opaque;
Index: qemu/hw/sparc32_dma.h
===================================================================
--- qemu.orig/hw/sparc32_dma.h	2008-04-16 19:21:27.000000000 +0000
+++ qemu/hw/sparc32_dma.h	2008-04-16 19:25:04.000000000 +0000
@@ -5,9 +5,13 @@
 void *sparc32_dma_init(target_phys_addr_t daddr, qemu_irq parent_irq,
                        void *iommu, qemu_irq **dev_irq, qemu_irq **reset);
 void ledma_memory_read(void *opaque, target_phys_addr_t addr,
-                       uint8_t *buf, int len, int do_bswap);
+                       uint8_t *buf, int len);
+void ledma_memory_read_bswap(void *opaque, target_phys_addr_t addr,
+                             uint8_t *buf, int len);
 void ledma_memory_write(void *opaque, target_phys_addr_t addr,
-                        uint8_t *buf, int len, int do_bswap);
+                        uint8_t *buf, int len);
+void ledma_memory_write_bswap(void *opaque, target_phys_addr_t addr,
+                              uint8_t *buf, int len);
 void espdma_memory_read(void *opaque, uint8_t *buf, int len);
 void espdma_memory_write(void *opaque, uint8_t *buf, int len);
 
Index: qemu/hw/sun4m.h
===================================================================
--- qemu.orig/hw/sun4m.h	2008-04-16 19:30:21.000000000 +0000
+++ qemu/hw/sun4m.h	2008-04-16 19:30:56.000000000 +0000
@@ -63,14 +63,7 @@
 void cs_init(target_phys_addr_t base, int irq, void *intctl);
 
 /* sparc32_dma.c */
-void *sparc32_dma_init(target_phys_addr_t daddr, qemu_irq parent_irq,
-                       void *iommu, qemu_irq **dev_irq, qemu_irq **reset);
-void ledma_memory_read(void *opaque, target_phys_addr_t addr,
-                       uint8_t *buf, int len, int do_bswap);
-void ledma_memory_write(void *opaque, target_phys_addr_t addr,
-                        uint8_t *buf, int len, int do_bswap);
-void espdma_memory_read(void *opaque, uint8_t *buf, int len);
-void espdma_memory_write(void *opaque, uint8_t *buf, int len);
+#include "sparc32_dma.h"
 
 /* pcnet.c */
 void lance_init(NICInfo *nd, target_phys_addr_t leaddr, void *dma_opaque,
