qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] PCNet & Lance merge
@ 2006-08-27  9:44 Blue Swirl
  2006-08-27 11:08 ` [Qemu-devel] " Fabrice Bellard
  2006-08-29 13:32 ` [Qemu-devel] " Paul Brook
  0 siblings, 2 replies; 4+ messages in thread
From: Blue Swirl @ 2006-08-27  9:44 UTC (permalink / raw)
  To: fabrice; +Cc: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 424 bytes --]

Hi,

These patches merge PCNet and Lance, implement the new IOMMU access method 
and convert ESP and PCNet to use the new method.

At least Sparc works as before. I think the changes should not change PC use 
of PCNet.

Please apply.

_________________________________________________________________
FREE pop-up blocking with the new MSN Toolbar - get it now! 
http://toolbar.msn.click-url.com/go/onm00200415ave/direct/01/

[-- Attachment #2: iommu_new_access.diff --]
[-- Type: text/plain, Size: 3621 bytes --]

Implement a better IOMMU access method.

Index: qemu/hw/iommu.c
===================================================================
--- qemu.orig/hw/iommu.c	2006-08-27 09:33:35.000000000 +0000
+++ qemu/hw/iommu.c	2006-08-27 09:33:45.000000000 +0000
@@ -186,21 +186,55 @@
     iommu_mem_writew,
};

-uint32_t iommu_translate_local(void *opaque, uint32_t addr)
+static uint32_t iommu_page_get_flags(IOMMUState *s, uint32_t addr)
{
-    IOMMUState *s = opaque;
-    uint32_t iopte, pa, tmppte;
+    uint32_t iopte;

     iopte = s->regs[1] << 4;
     addr &= ~s->iostart;
     iopte += (addr >> (PAGE_SHIFT - 2)) & ~3;
-    pa = ldl_phys(iopte);
+    return ldl_phys(iopte);
+}
+
+static uint32_t iommu_translate(IOMMUState *s, uint32_t addr, uint32_t pa)
+{
+    uint32_t tmppte;
+
     tmppte = pa;
     pa = ((pa & IOPTE_PAGE) << 4) + (addr & PAGE_MASK);
-    DPRINTF("xlate dva %x => pa %x (iopte[%x] = %x)\n", addr, pa, iopte, 
tmppte);
+    DPRINTF("xlate dva %x => pa %x (iopte = %x)\n", addr, pa, tmppte);
     return pa;
}

+void sparc_iommu_memory_rw_local(void *opaque, target_phys_addr_t addr,
+                                 uint8_t *buf, int len, int is_write)
+{
+    int l, flags;
+    target_ulong page, phys_addr;
+    void * p;
+
+    while (len > 0) {
+        page = addr & TARGET_PAGE_MASK;
+        l = (page + TARGET_PAGE_SIZE) - addr;
+        if (l > len)
+            l = len;
+        flags = iommu_page_get_flags(opaque, page);
+        if (!(flags & IOPTE_VALID))
+            return;
+        phys_addr = iommu_translate(opaque, addr, flags);
+        if (is_write) {
+            if (!(flags & IOPTE_WRITE))
+                return;
+            cpu_physical_memory_write(phys_addr, buf, len);
+        } else {
+            cpu_physical_memory_read(phys_addr, buf, len);
+        }
+        len -= l;
+        buf += l;
+        addr += l;
+    }
+}
+
static void iommu_save(QEMUFile *f, void *opaque)
{
     IOMMUState *s = opaque;
Index: qemu/hw/sun4m.c
===================================================================
--- qemu.orig/hw/sun4m.c	2006-08-27 09:33:35.000000000 +0000
+++ qemu/hw/sun4m.c	2006-08-27 09:33:45.000000000 +0000
@@ -194,9 +194,16 @@

static void *iommu;

-uint32_t iommu_translate(uint32_t addr)
+void sparc_iommu_memory_read(target_phys_addr_t addr,
+                           uint8_t *buf, int len)
{
-    return iommu_translate_local(iommu, addr);
+    return sparc_iommu_memory_rw_local(iommu, addr, buf, len, 0);
+}
+
+void sparc_iommu_memory_write(target_phys_addr_t addr,
+                           uint8_t *buf, int len)
+{
+    return sparc_iommu_memory_rw_local(iommu, addr, buf, len, 1);
}

static void *slavio_misc;
Index: qemu/vl.h
===================================================================
--- qemu.orig/vl.h	2006-08-27 09:33:35.000000000 +0000
+++ qemu/vl.h	2006-08-27 09:33:45.000000000 +0000
@@ -1025,12 +1025,16 @@

/* sun4m.c */
extern QEMUMachine sun4m_machine;
-uint32_t iommu_translate(uint32_t addr);
void pic_set_irq_cpu(int irq, int level, unsigned int cpu);
+void sparc_iommu_memory_read(target_phys_addr_t addr,
+                             uint8_t *buf, int len);
+void sparc_iommu_memory_write(target_phys_addr_t addr,
+                              uint8_t *buf, int len);

/* iommu.c */
void *iommu_init(uint32_t addr);
-uint32_t iommu_translate_local(void *opaque, uint32_t addr);
+void sparc_iommu_memory_rw_local(void *opaque, target_phys_addr_t addr,
+                                 uint8_t *buf, int len, int is_write);

/* lance.c */
void lance_init(NICInfo *nd, int irq, uint32_t leaddr, uint32_t ledaddr);


[-- Attachment #3: pcnet-lance-merge.diff --]
[-- Type: text/plain, Size: 30816 bytes --]

Merge Lance and PCNet drivers. Convert ESP to new IOMMU methods.

Index: qemu/hw/pcnet.c
===================================================================
--- qemu.orig/hw/pcnet.c	2006-08-27 09:33:15.000000000 +0000
+++ qemu/hw/pcnet.c	2006-08-27 09:33:50.000000000 +0000
@@ -36,10 +36,21 @@
//#define PCNET_DEBUG_RMD
//#define PCNET_DEBUG_TMD
//#define PCNET_DEBUG_MATCH
+//#define PCNET_DEBUG_SPARC_LEDMA

+#ifdef PCNET_DEBUG_SPARC_LEDMA
+#define DPRINTF(fmt, args...) \
+do { printf("PCNET: " fmt , ##args); } while (0)
+#define pic_set_irq(irq, level)                                       \
+do { printf("PCNET: set_irq(%d): %d\n", (irq), (level)); 
pic_set_irq((irq),(level));} while (0)
+#else
+#define DPRINTF(fmt, args...)
+#endif

#define PCNET_IOPORT_SIZE       0x20
#define PCNET_PNPMMIO_SIZE      0x20
+#define LEDMA_REGS 4
+#define LEDMA_MAXADDR (LEDMA_REGS * 4 - 1)


typedef struct PCNetState_st PCNetState;
@@ -49,7 +60,8 @@
     VLANClientState *vc;
     NICInfo *nd;
     QEMUTimer *poll_timer;
-    int mmio_io_addr, rap, isr, lnkst;
+    target_phys_addr_t mmio_io_addr;
+    int rap, isr, lnkst;
     target_phys_addr_t rdra, tdra;
     uint8_t prom[16];
     uint16_t csr[128];
@@ -58,6 +70,17 @@
     int xmit_pos, recv_pos;
     uint8_t buffer[4096];
     int tx_busy;
+    uint8_t macaddr[8];
+    uint8_t logical_address_filter[8];
+    int big_endian;
+    void (*set_irq_cb)(PCNetState *s, int isr);
+    void (*phys_mem_read)(target_phys_addr_t addr,
+                         uint8_t *buf, int len);
+    void (*phys_mem_write)(target_phys_addr_t addr,
+                          uint8_t *buf, int len);
+    // Lance-specific
+    int irq;
+    uint32_t ledmaregs[LEDMA_REGS];
};

/* XXX: using bitfields for target memory structures is almost surely
@@ -142,24 +165,19 @@
#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))
+#define PHYSADDR(S,A)                                                   \
+    (BCR_SSIZE32(S) ?                                                   \
+     (A):                                                               \
+     (A) | ((0xff00 & (uint32_t)(S)->csr[2]) << 16) | (S)->ledmaregs[3])

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_FIELD(rdra:24);
-    unsigned PACKED_FIELD(res1:5);
-    unsigned PACKED_FIELD(rlen:3);
-    unsigned PACKED_FIELD(tdra:24);
-    unsigned PACKED_FIELD(res2:5);
-    unsigned PACKED_FIELD(tlen:3);
+    uint8_t padr[6];
+    uint8_t ladrf[8];
+    uint8_t rdra[3];
+    uint8_t rlen;
+    uint8_t tdra[3];
+    uint8_t tlen;
};

struct pcnet_initblk32 {
@@ -168,14 +186,9 @@
     unsigned PACKED_FIELD(rlen:4);
     unsigned PACKED_FIELD(res2:4);
     unsigned PACKED_FIELD(tlen:4);
-    uint16_t padr1;
-    uint16_t padr2;
-    uint16_t padr3;
+    uint8_t padr[6];
     uint16_t _res;
-    uint16_t ladrf1;
-    uint16_t ladrf2;
-    uint16_t ladrf3;
-    uint16_t ladrf4;
+    uint8_t ladrf[8];
     uint32_t rdra;
     uint32_t tdra;
};
@@ -251,12 +264,36 @@
         (R)->rmd2.rcc, (R)->rmd2.rpc, (R)->rmd2.mcnt,   \
         (R)->rmd2.zeros)

+static inline void bswap_desc(PCNetState *s, void *desc, unsigned int 
nbytes)
+{
+    if (s->big_endian) {
+        unsigned int i;
+        uint16_t *dptr = (uint16_t *)desc;
+
+        for (i = 0; i < nbytes / 2; i++)
+            bswap16s(&dptr[i]);
+    }
+}
+
+static void pci_physical_memory_write(target_phys_addr_t addr,
+                           uint8_t *buf, int len)
+{
+    cpu_physical_memory_write(addr, buf, len);
+}
+
+static void pci_physical_memory_read(target_phys_addr_t addr,
+                           uint8_t *buf, int len)
+{
+    cpu_physical_memory_read(addr, buf, len);
+}
+
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));
+
+        s->phys_mem_read(addr, (void *)&xda[0], sizeof(xda));
+        bswap_desc(s, (void *)&xda[0], sizeof(xda));
         ((uint32_t *)tmd)[0] = (xda[0]&0xffff) |
                 ((xda[1]&0x00ff) << 16);
         ((uint32_t *)tmd)[1] = (xda[2]&0xffff)|
@@ -265,13 +302,14 @@
                 (xda[3] & 0xffff) << 16;
         ((uint32_t *)tmd)[3] = 0;
     }
-    else
-    if (BCR_SWSTYLE(s) != 3)
-        cpu_physical_memory_read(addr, (void *)tmd, 16);
-    else {
+    else if (BCR_SWSTYLE(s) != 3) {
+        s->phys_mem_read(addr, (void *)tmd, 16);
+        bswap_desc(s, (void *)tmd, 16);
+    } else {
         uint32_t xda[4];
-        cpu_physical_memory_read(addr,
-                (void *)&xda[0], sizeof(xda));
+
+        s->phys_mem_read(addr, (void *)&xda[0], sizeof(xda));
+        bswap_desc(s, (void *)&xda[0], sizeof(xda));
         ((uint32_t *)tmd)[0] = xda[2];
         ((uint32_t *)tmd)[1] = xda[1];
         ((uint32_t *)tmd)[2] = xda[0];
@@ -288,20 +326,21 @@
             ((((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));
+        bswap_desc(s, (void *)&xda[0], sizeof(xda));
+        s->phys_mem_write(addr, (void *)&xda[0], sizeof(xda));
     }
     else {
-        if (BCR_SWSTYLE(s) != 3)
-            cpu_physical_memory_write(addr, (void *)tmd, 16);
-        else {
+        if (BCR_SWSTYLE(s) != 3) {
+            bswap_desc(s, (void *)tmd, 16);
+            s->phys_mem_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));
+            bswap_desc(s, (void *)&xda[0], sizeof(xda));
+            s->phys_mem_write(addr, (void *)&xda[0], sizeof(xda));
         }
     }
}
@@ -310,8 +349,8 @@
{
     if (!BCR_SWSTYLE(s)) {
         uint16_t rda[4];
-        cpu_physical_memory_read(addr,
-                (void *)&rda[0], sizeof(rda));
+        s->phys_mem_read(addr, (void *)&rda[0], sizeof(rda));
+        bswap_desc(s, (void *)&rda[0], sizeof(rda));
         ((uint32_t *)rmd)[0] = (rda[0]&0xffff)|
                 ((rda[1] & 0x00ff) << 16);
         ((uint32_t *)rmd)[1] = (rda[2]&0xffff)|
@@ -319,13 +358,14 @@
         ((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 {
+    else if (BCR_SWSTYLE(s) != 3) {
+        s->phys_mem_read(addr, (void *)rmd, 16);
+        bswap_desc(s, (void *)rmd, 16);
+    } else {
         uint32_t rda[4];
-        cpu_physical_memory_read(addr,
-                (void *)&rda[0], sizeof(rda));
+
+        s->phys_mem_read(addr, (void *)&rda[0], sizeof(rda));
+        bswap_desc(s, rda, sizeof(rda));
         ((uint32_t *)rmd)[0] = rda[2];
         ((uint32_t *)rmd)[1] = rda[1];
         ((uint32_t *)rmd)[2] = rda[0];
@@ -336,26 +376,27 @@
static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd, 
target_phys_addr_t 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));  \
+        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;
+        bswap_desc(s, (void *)&rda[0], sizeof(rda));
+        s->phys_mem_write(addr, (void *)&rda[0], sizeof(rda));
     }
     else {
-        if (BCR_SWSTYLE(s) != 3)
-            cpu_physical_memory_write(addr, (void *)rmd, 16);
-        else {
+        if (BCR_SWSTYLE(s) != 3) {
+            bswap_desc(s, (void *)rmd, 16);
+            s->phys_mem_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));
+            bswap_desc(s, (void *)&rda[0], sizeof(rda));
+            s->phys_mem_write(addr, (void *)&rda[0], sizeof(rda));
         }
     }
}
@@ -391,7 +432,7 @@
     case 0x00:                                  \
         do {                                    \
             uint16_t rda[4];                    \
-            cpu_physical_memory_read((ADDR),    \
+            s->phys_mem_read((ADDR),            \
                 (void *)&rda[0], sizeof(rda));  \
             (RES) |= (rda[2] & 0xf000)!=0xf000; \
             (RES) |= (rda[3] & 0xf000)!=0x0000; \
@@ -401,7 +442,7 @@
     case 0x02:                                  \
         do {                                    \
             uint32_t rda[4];                    \
-            cpu_physical_memory_read((ADDR),    \
+            s->phys_mem_read((ADDR),            \
                 (void *)&rda[0], sizeof(rda)); \
             (RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \
             (RES) |= (rda[2] & 0x0000f000L)!=0x00000000L; \
@@ -410,7 +451,7 @@
     case 0x03:                                  \
         do {                                    \
             uint32_t rda[4];                    \
-            cpu_physical_memory_read((ADDR),    \
+            s->phys_mem_read((ADDR),            \
                 (void *)&rda[0], sizeof(rda)); \
             (RES) |= (rda[0] & 0x0000f000L)!=0x00000000L; \
             (RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \
@@ -424,7 +465,7 @@
     case 0x00:                                  \
         do {                                    \
             uint16_t xda[4];                    \
-            cpu_physical_memory_read((ADDR),    \
+            s->phys_mem_read((ADDR),            \
                 (void *)&xda[0], sizeof(xda));  \
             (RES) |= (xda[2] & 0xf000)!=0xf000;\
         } while (0);                            \
@@ -434,7 +475,7 @@
     case 0x03:                                  \
         do {                                    \
             uint32_t xda[4];                    \
-            cpu_physical_memory_read((ADDR),    \
+            s->phys_mem_read((ADDR),            \
                 (void *)&xda[0], sizeof(xda));  \
             (RES) |= (xda[1] & 0x0000f000L)!=0x0000f000L; \
         } while (0);                            \
@@ -448,14 +489,13 @@
     struct qemu_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",                          \
+           "type=0x%04x\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], \
-           be16_to_cpu(hdr->ether_type),                                \
-           !!ETHER_IS_MULTICAST(hdr->ether_dhost));                     \
-} while (0)
+           be16_to_cpu(hdr->ether_type));                               \
+    } while (0)

#define MULTICAST_FILTER_LEN 8

@@ -552,18 +592,13 @@
static inline int padr_match(PCNetState *s, const uint8_t *buf, int size)
{
     struct qemu_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)) && !memcmp(hdr->ether_dhost, padr, 6);
+    int result = (!CSR_DRCVPA(s)) && !memcmp(hdr->ether_dhost, s->macaddr, 
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]);
+           
s->macaddr[0],s->macaddr[1],s->macaddr[2],s->macaddr[3],s->macaddr[4],s->macaddr[5]);
     printf("padr_match result=%d\n", result);
#endif
     return result;
@@ -571,8 +606,9 @@

static inline int padr_bcast(PCNetState *s, const uint8_t *buf, int size)
{
-    static uint8_t BCAST[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+    static const uint8_t BCAST[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
     struct qemu_ether_header *hdr = (void *)buf;
+
     int result = !CSR_DRCVBC(s) && !memcmp(hdr->ether_dhost, BCAST, 6);
#ifdef PCNET_DEBUG_MATCH
     printf("padr_bcast result=%d\n", result);
@@ -583,16 +619,11 @@
static inline int ladr_match(PCNetState *s, const uint8_t *buf, int size)
{
     struct qemu_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
-        };
+
+    if ((*(hdr->ether_dhost) & 0x01) &&
+        (*(uint64_t *)&s->logical_address_filter[0]) != 0LL) {
         int index = lnc_mchash(hdr->ether_dhost) >> 26;
-        return !!(ladr[index >> 3] & (1 << (index & 7)));
+        return !!(s->logical_address_filter[index >> 3] & (1 << (index & 
7)));
     }
     return 0;
}
@@ -643,9 +674,10 @@
     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[12]  = s->prom[0] | (s->prom[1] << 8);
+    s->csr[13]  = s->prom[2] | (s->prom[3] << 8);
+    s->csr[14]  = s->prom[4] | (s->prom[5] << 8);
+    memcpy(s->macaddr, s->prom, 6);
     s->csr[15] &= 0x21c4;
     s->csr[72]  = 1;
     s->csr[74]  = 1;
@@ -666,6 +698,16 @@
     s->tx_busy = 0;
}

+static void pcnet_pci_set_irq_cb(PCNetState *s, int isr)
+{
+    pci_set_irq(&s->dev, 0, isr);
+}
+
+static void pcnet_sbus_set_irq_cb(PCNetState *s, int isr)
+{
+    pic_set_irq(s->irq, isr);
+}
+
static void pcnet_update_irq(PCNetState *s)
{
     int isr = 0;
@@ -721,8 +763,8 @@
         printf("pcnet: INTA=%d\n", isr);
#endif
     }
-        pci_set_irq(&s->dev, 0, isr);
-        s->isr = isr;
+    s->set_irq_cb(s, isr);
+    s->isr = isr;
}

static void pcnet_init(PCNetState *s)
@@ -732,33 +774,33 @@
#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);                 \
+        s->phys_mem_read(PHYSADDR(s,CSR_IADR(s)),                       \
+                                 (uint8_t *)&initblk, sizeof(initblk)); \
+        bswap_desc(s, &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);                             \
+        memcpy(s->logical_address_filter, &initblk.ladrf[0], 8);        \
+        memcpy(s->macaddr, &initblk.padr[0], 6);                        \
} while (0)

     if (BCR_SSIZE32(s)) {
         struct pcnet_initblk32 initblk;
+
         PCNET_INIT();
+        s->rdra = PHYSADDR(s,initblk.rdra);
+        s->tdra = PHYSADDR(s,initblk.tdra);
#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();
+        s->rdra = PHYSADDR(s,initblk.rdra[0] | (initblk.rdra[1] << 8) | 
(initblk.rdra[2] << 16));
+        s->tdra = PHYSADDR(s,initblk.tdra[0] | (initblk.tdra[1] << 8) | 
(initblk.tdra[2] << 16));
#ifdef PCNET_DEBUG
         printf("initblk.rlen=0x%02x, initblk.tlen=0x%02x\n",
                 initblk.rlen, initblk.tlen);
@@ -1035,7 +1077,7 @@
#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);               \
+    s->phys_mem_write(rbadr, src, count);                       \
     src += count; size -= count;                                \
     rmd.rmd2.mcnt = count; rmd.rmd1.own = 0;                    \
     RMDSTORE(&rmd, PHYSADDR(s,crda));                           \
@@ -1125,14 +1167,14 @@
         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->phys_mem_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->phys_mem_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
@@ -1256,15 +1298,39 @@
             pcnet_transmit(s);

         return;
-    case 1:
-    case 2:
+    case 3:
+        s->big_endian = val & 4;
+        break;
     case 8:
+        s->logical_address_filter[0] = val & 0xff;
+        s->logical_address_filter[1] = val >> 8;
+        goto check_stop;
     case 9:
+        s->logical_address_filter[2] = val & 0xff;
+        s->logical_address_filter[3] = val >> 8;
+        goto check_stop;
     case 10:
+        s->logical_address_filter[4] = val & 0xff;
+        s->logical_address_filter[5] = val >> 8;
+        goto check_stop;
     case 11:
+        s->logical_address_filter[6] = val & 0xff;
+        s->logical_address_filter[7] = val >> 8;
+        goto check_stop;
     case 12:
+        s->macaddr[0] = val & 0xff;
+        s->macaddr[1] = val >> 8;
+        goto check_stop;
     case 13:
+        s->macaddr[2] = val & 0xff;
+        s->macaddr[3] = val >> 8;
+        goto check_stop;
     case 14:
+        s->macaddr[4] = val & 0xff;
+        s->macaddr[5] = val >> 8;
+        goto check_stop;
+    case 1:
+    case 2:
     case 15:
     case 18: /* CRBAL */
     case 19: /* CRBAU */
@@ -1301,11 +1367,10 @@
     case 76: /* RCVRL */
     case 78: /* XMTRL */
     case 112:
+    check_stop:
        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;
@@ -1338,6 +1403,27 @@
         val = s->csr[0];
         val |= (val & 0x7800) ? 0x8000 : 0;
         break;
+    case 8:
+        val = s->logical_address_filter[0] | (s->logical_address_filter[1] 
<< 8);
+        break;
+    case 9:
+        val = s->logical_address_filter[2] | (s->logical_address_filter[3] 
<< 8);
+        break;
+    case 10:
+        val = s->logical_address_filter[4] | (s->logical_address_filter[5] 
<< 8);
+        break;
+    case 11:
+        val = s->logical_address_filter[6] | (s->logical_address_filter[7] 
<< 8);
+        break;
+    case 12:
+        val = s->macaddr[0] | (s->macaddr[1] << 8);
+        break;
+    case 13:
+        val = s->macaddr[2] | (s->macaddr[3] << 8);
+        break;
+    case 14:
+        val = s->macaddr[4] | (s->macaddr[5] << 8);
+        break;
     case 16:
         return pcnet_csr_readw(s,1);
     case 17:
@@ -1727,6 +1813,28 @@
     cpu_register_physical_memory(addr, PCNET_PNPMMIO_SIZE, 
d->mmio_io_addr);
}

+static void pcnet_common_init(PCNetState *d, NICInfo *nd, const char 
*info_str)
+{
+    d->poll_timer = qemu_new_timer(vm_clock, pcnet_poll_timer, d);
+
+    d->nd = nd;
+
+    d->vc = qemu_new_vlan_client(nd->vlan, pcnet_receive,
+                                 pcnet_can_receive, d);
+
+    snprintf(d->vc->info_str, sizeof(d->vc->info_str),
+             "%s macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
+             info_str,
+             d->nd->macaddr[0],
+             d->nd->macaddr[1],
+             d->nd->macaddr[2],
+             d->nd->macaddr[3],
+             d->nd->macaddr[4],
+             d->nd->macaddr[5]);
+
+    pcnet_h_reset(d);
+}
+
void pci_pcnet_init(PCIBus *bus, NICInfo *nd)
{
     PCNetState *d;
@@ -1768,22 +1876,73 @@

     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;
+    d->set_irq_cb = pcnet_pci_set_irq_cb;
+    d->phys_mem_read = pci_physical_memory_read;
+    d->phys_mem_write = pci_physical_memory_write;

-    d->vc = qemu_new_vlan_client(nd->vlan, pcnet_receive,
-                                 pcnet_can_receive, d);
-
-    snprintf(d->vc->info_str, sizeof(d->vc->info_str),
-             "pcnet macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
-             d->nd->macaddr[0],
-             d->nd->macaddr[1],
-             d->nd->macaddr[2],
-             d->nd->macaddr[3],
-             d->nd->macaddr[4],
-             d->nd->macaddr[5]);
+    pcnet_common_init(d, nd, "pcnet");
+}

-    pcnet_h_reset(d);
+// Due to Qemu limitations, Lance DMA registers are accessed via ESP
+// DMA registers
+static PCNetState *global_pcnet;
+
+uint32_t ledma_mem_readl(target_phys_addr_t addr)
+{
+    uint32_t saddr;
+
+    saddr = (addr & LEDMA_MAXADDR) >> 2;
+    DPRINTF("read dmareg[%d]: 0x%8.8x\n", saddr,
+            global_pcnet->ledmaregs[saddr]);
+
+    return global_pcnet->ledmaregs[saddr];
+}
+
+void ledma_mem_writel(target_phys_addr_t addr, uint32_t val)
+{
+    uint32_t saddr;
+
+    saddr = (addr & LEDMA_MAXADDR) >> 2;
+    DPRINTF("write dmareg[%d]: 0x%8.8x -> 0x%8.8x\n", saddr,
+            global_pcnet->ledmaregs[saddr], val);
+    global_pcnet->ledmaregs[saddr] = val;
+}
+
+static CPUWriteMemoryFunc *lance_mem_write[3] = {
+    (CPUWriteMemoryFunc *)&pcnet_ioport_writew,
+    (CPUWriteMemoryFunc *)&pcnet_ioport_writew,
+    (CPUWriteMemoryFunc *)&pcnet_ioport_writew,
+};
+
+static CPUReadMemoryFunc *lance_mem_read[3] = {
+    (CPUReadMemoryFunc *)&pcnet_ioport_readw,
+    (CPUReadMemoryFunc *)&pcnet_ioport_readw,
+    (CPUReadMemoryFunc *)&pcnet_ioport_readw,
+};
+
+#if defined (TARGET_SPARC) && !defined(TARGET_SPARC64) // Avoid compile 
failure
+void lance_init(NICInfo *nd, int irq, uint32_t leaddr, uint32_t ledaddr)
+{
+    PCNetState *d;
+    int lance_io_memory;
+
+    d = qemu_mallocz(sizeof(PCNetState));
+    if (!d)
+        return;
+
+    global_pcnet = d;
+    d->irq = irq;
+
+    lance_io_memory =
+        cpu_register_io_memory(0, lance_mem_read, lance_mem_write, d);
+
+    cpu_register_physical_memory(leaddr, 4, lance_io_memory);
+
+    d->set_irq_cb = pcnet_sbus_set_irq_cb;
+    d->phys_mem_read = sparc_iommu_memory_read;
+    d->phys_mem_write = sparc_iommu_memory_write;
+
+    pcnet_common_init(d, nd, "lance");
}
+#endif
Index: qemu/Makefile.target
===================================================================
--- qemu.orig/Makefile.target	2006-08-27 09:33:15.000000000 +0000
+++ qemu/Makefile.target	2006-08-27 09:33:50.000000000 +0000
@@ -359,7 +359,7 @@
VL_OBJS+= fdc.o mc146818rtc.o serial.o m48t59.o
VL_OBJS+= cirrus_vga.o parallel.o
else
-VL_OBJS+= sun4m.o tcx.o lance.o iommu.o m48t59.o slavio_intctl.o
+VL_OBJS+= sun4m.o tcx.o pcnet.o iommu.o m48t59.o slavio_intctl.o
VL_OBJS+= slavio_timer.o slavio_serial.o slavio_misc.o fdc.o esp.o
endif
endif
Index: qemu/hw/esp.c
===================================================================
--- qemu.orig/hw/esp.c	2006-08-27 09:33:15.000000000 +0000
+++ qemu/hw/esp.c	2006-08-27 09:33:50.000000000 +0000
@@ -37,6 +37,7 @@

#define ESPDMA_REGS 4
#define ESPDMA_MAXADDR (ESPDMA_REGS * 4 - 1)
+#define DMA_MAXADDR (ESPDMA_REGS * 4 * 2 - 1)
#define ESP_MAXREG 0x3f
#define TI_BUFSZ 32
#define DMA_VER 0xa0000000
@@ -91,17 +92,16 @@

static int get_cmd(ESPState *s, uint8_t *buf)
{
-    uint32_t dmaptr, dmalen;
+    uint32_t dmalen;
     int target;

     dmalen = s->wregs[0] | (s->wregs[1] << 8);
     target = s->wregs[4] & 7;
     DPRINTF("get_cmd: len %d target %d\n", dmalen, target);
     if (s->dma) {
-	dmaptr = iommu_translate(s->espdmaregs[1]);
	DPRINTF("DMA Direction: %c, addr 0x%8.8x\n",
-                s->espdmaregs[0] & DMA_WRITE_MEM ? 'w': 'r', dmaptr);
-	cpu_physical_memory_read(dmaptr, buf, dmalen);
+                s->espdmaregs[0] & DMA_WRITE_MEM ? 'w': 'r', 
s->espdmaregs[1]);
+	sparc_iommu_memory_read(s->espdmaregs[1], buf, dmalen);
     } else {
	buf[0] = 0;
	memcpy(&buf[1], s->ti_buf, dmalen);
@@ -178,16 +178,13 @@

static void write_response(ESPState *s)
{
-    uint32_t dmaptr;
-
     DPRINTF("Transfer status (sense=%d)\n", s->sense);
     s->ti_buf[0] = s->sense;
     s->ti_buf[1] = 0;
     if (s->dma) {
-	dmaptr = iommu_translate(s->espdmaregs[1]);
	DPRINTF("DMA Direction: %c\n",
                 s->espdmaregs[0] & DMA_WRITE_MEM ? 'w': 'r');
-	cpu_physical_memory_write(dmaptr, s->ti_buf, 2);
+	sparc_iommu_memory_write(s->espdmaregs[1], s->ti_buf, 2);
	s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
	s->rregs[5] = INTR_BS | INTR_FC;
	s->rregs[6] = SEQ_CD;
@@ -204,24 +201,24 @@

static void esp_do_dma(ESPState *s)
{
-    uint32_t dmaptr, minlen, len, from, to;
+    uint32_t minlen, len, from, to;
     int to_device;
+
     to_device = (s->espdmaregs[0] & DMA_WRITE_MEM) == 0;
     from = s->espdmaregs[1];
     minlen = s->dma_left;
     to = from + minlen;
-    dmaptr = iommu_translate(s->espdmaregs[1]);
     if ((from & TARGET_PAGE_MASK) != (to & TARGET_PAGE_MASK)) {
        len = TARGET_PAGE_SIZE - (from & ~TARGET_PAGE_MASK);
     } else {
        len = to - from;
     }
-    DPRINTF("DMA address p %08x v %08x len %08x, from %08x, to %08x\n", 
dmaptr, s->espdmaregs[1], len, from, to);
+    DPRINTF("DMA address v %08x len %08x, from %08x, to %08x\n", 
s->espdmaregs[1], len, from, to);
     if (s->do_cmd) {
         s->espdmaregs[1] += len;
         s->ti_size -= len;
         DPRINTF("command len %d + %d\n", s->cmdlen, len);
-        cpu_physical_memory_read(dmaptr, &s->cmdbuf[s->cmdlen], len);
+        sparc_iommu_memory_read(s->espdmaregs[1], &s->cmdbuf[s->cmdlen], 
len);
         s->ti_size = 0;
         s->cmdlen = 0;
         s->do_cmd = 0;
@@ -232,10 +229,10 @@
         s->dma_left -= len;
         if (to_device) {
             s->async_ptr = -1;
-            cpu_physical_memory_read(dmaptr, s->async_buf, len);
+            sparc_iommu_memory_read(s->espdmaregs[1], s->async_buf, len);
             scsi_write_data(s->current_dev, s->async_buf, len);
         } else {
-            s->async_ptr = dmaptr;
+            s->async_ptr = s->espdmaregs[1];
             scsi_read_data(s->current_dev, s->async_buf, len);
         }
     }
@@ -248,7 +245,7 @@
     s->ti_size -= s->async_len;
     s->espdmaregs[1] += s->async_len;
     if (s->async_ptr != (uint32_t)-1) {
-        cpu_physical_memory_write(s->async_ptr, s->async_buf, 
s->async_len);
+        sparc_iommu_memory_write(s->async_ptr, s->async_buf, s->async_len);
     }
     if (reason == SCSI_REASON_DONE) {
         DPRINTF("SCSI Command complete\n");
@@ -474,12 +471,17 @@
     esp_mem_writeb,
};

+extern uint32_t ledma_mem_readl(target_phys_addr_t addr);
+extern void ledma_mem_writel(target_phys_addr_t addr, uint32_t val);
+
static uint32_t espdma_mem_readl(void *opaque, target_phys_addr_t addr)
{
     ESPState *s = opaque;
     uint32_t saddr;

-    saddr = (addr & ESPDMA_MAXADDR) >> 2;
+    saddr = (addr & DMA_MAXADDR) >> 2;
+    if (saddr > ESPDMA_REGS)
+        return ledma_mem_readl(addr);
     DPRINTF("read dmareg[%d]: 0x%8.8x\n", saddr, s->espdmaregs[saddr]);

     return s->espdmaregs[saddr];
@@ -490,7 +492,11 @@
     ESPState *s = opaque;
     uint32_t saddr;

-    saddr = (addr & ESPDMA_MAXADDR) >> 2;
+    saddr = (addr & DMA_MAXADDR) >> 2;
+    if (saddr > ESPDMA_REGS) {
+        ledma_mem_writel(addr, val);
+        return;
+    }
     DPRINTF("write dmareg[%d]: 0x%8.8x -> 0x%8.8x\n", saddr, 
s->espdmaregs[saddr], val);
     switch (saddr) {
     case 0:
@@ -581,8 +587,10 @@
     esp_io_memory = cpu_register_io_memory(0, esp_mem_read, esp_mem_write, 
s);
     cpu_register_physical_memory(espaddr, ESP_MAXREG*4, esp_io_memory);

+    // Due to Qemu limitations, Lance DMA registers are accessed via ESP
+    // DMA registers
     espdma_io_memory = cpu_register_io_memory(0, espdma_mem_read, 
espdma_mem_write, s);
-    cpu_register_physical_memory(espdaddr, 16, espdma_io_memory);
+    cpu_register_physical_memory(espdaddr, 16 * 2, espdma_io_memory);

     esp_reset(s);



^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2006-08-29 16:27 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-08-27  9:44 [Qemu-devel] PCNet & Lance merge Blue Swirl
2006-08-27 11:08 ` [Qemu-devel] " Fabrice Bellard
2006-08-29 13:32 ` [Qemu-devel] " Paul Brook
2006-08-29 16:27   ` Blue Swirl

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).