Hi,
Here's my first attempt to merge Lance to PCNet, doesn't work yet.
_________________________________________________________________
Don't just search. Find. Check out the new MSN Search!
http://search.msn.com/
Merge Lance and PCNet drivers.
Index: qemu/hw/pcnet.c
===================================================================
--- qemu.orig/hw/pcnet.c 2006-08-20 13:46:51.000000000 +0000
+++ qemu/hw/pcnet.c 2006-08-20 13:54:38.000000000 +0000
@@ -36,10 +36,13 @@
//#define PCNET_DEBUG_RMD
//#define PCNET_DEBUG_TMD
//#define PCNET_DEBUG_MATCH
+//#define PCNET_DEBUG_SPARC_IOMMU
#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 +52,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 +62,12 @@
int xmit_pos, recv_pos;
uint8_t buffer[4096];
int tx_busy;
+#if defined(TARGET_SPARC) && !defined (TARGET_SPARC64)
+ // Lance-specific
+ int irq;
+ target_phys_addr_t leptr;
+ uint32_t ledmaregs[LEDMA_REGS];
+#endif
};
/* XXX: using bitfields for target memory structures is almost surely
@@ -145,6 +155,17 @@
#define PHYSADDR(S,A) \
(BCR_SSIZE32(S) ? (A) : (A) | ((0xff00 & (uint32_t)(s)->csr[2])<<16))
+#if defined(PCNET_DEBUG_SPARC_IOMMU)
+#define iommu_translate(addr) \
+ (printf("PCNET: iommu_translate(0x%x)\n", (addr)),
iommu_translate(addr))
+#endif
+
+#if defined(TARGET_SPARC) && !defined (TARGET_SPARC64)
+#define SPARC_IOMMU_TRANSLATE(addr) iommu_translate(addr)
+#else
+#define SPARC_IOMMU_TRANSLATE(addr) (addr)
+#endif
+
struct pcnet_initblk16 {
uint16_t mode;
uint16_t padr1;
@@ -255,6 +276,7 @@
{
if (!BCR_SWSTYLE(s)) {
uint16_t xda[4];
+ addr = SPARC_IOMMU_TRANSLATE(addr);
cpu_physical_memory_read(addr,
(void *)&xda[0], sizeof(xda));
((uint32_t *)tmd)[0] = (xda[0]&0xffff) |
@@ -288,6 +310,7 @@
((((uint32_t *)tmd)[1]>>16)&0xff00);
xda[2] = ((uint32_t *)tmd)[1] & 0xffff;
xda[3] = ((uint32_t *)tmd)[2] >> 16;
+ addr = SPARC_IOMMU_TRANSLATE(addr);
cpu_physical_memory_write(addr,
(void *)&xda[0], sizeof(xda));
}
@@ -310,6 +333,7 @@
{
if (!BCR_SWSTYLE(s)) {
uint16_t rda[4];
+ addr = SPARC_IOMMU_TRANSLATE(addr);
cpu_physical_memory_read(addr,
(void *)&rda[0], sizeof(rda));
((uint32_t *)rmd)[0] = (rda[0]&0xffff)|
@@ -342,6 +366,7 @@
((((uint32_t *)rmd)[1]>>16)&0xff00);\
rda[2] = ((uint32_t *)rmd)[1] & 0xffff; \
rda[3] = ((uint32_t *)rmd)[2] & 0xffff; \
+ addr = SPARC_IOMMU_TRANSLATE(addr);
cpu_physical_memory_write(addr, \
(void *)&rda[0], sizeof(rda)); \
}
@@ -721,8 +746,12 @@
printf("pcnet: INTA=%d\n", isr);
#endif
}
- pci_set_irq(&s->dev, 0, isr);
- s->isr = isr;
+#if defined(TARGET_SPARC) && !defined (TARGET_SPARC64)
+ pic_set_irq(s->irq, isr);
+#else
+ pci_set_irq(&s->dev, 0, isr);
+#endif
+ s->isr = isr;
}
static void pcnet_init(PCNetState *s)
@@ -732,7 +761,7 @@
#endif
#define PCNET_INIT() do { \
- cpu_physical_memory_read(PHYSADDR(s,CSR_IADR(s)), \
+
cpu_physical_memory_read(SPARC_IOMMU_TRANSLATE(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; \
@@ -1035,6 +1064,7 @@
#define PCNET_RECV_STORE() do { \
int count = MIN(4096 - rmd.rmd1.bcnt,size); \
target_phys_addr_t rbadr = PHYSADDR(s, rmd.rmd0.rbadr); \
+ rbadr = SPARC_IOMMU_TRANSLATE(rbadr); \
cpu_physical_memory_write(rbadr, src, count); \
src += count; size -= count; \
rmd.rmd2.mcnt = count; rmd.rmd1.own = 0; \
@@ -1125,14 +1155,14 @@
if (tmd.tmd1.stp) {
s->xmit_pos = 0;
if (!tmd.tmd1.enp) {
- cpu_physical_memory_read(PHYSADDR(s, tmd.tmd0.tbadr),
+ cpu_physical_memory_read(SPARC_IOMMU_TRANSLATE(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),
+ cpu_physical_memory_read(SPARC_IOMMU_TRANSLATE(PHYSADDR(s,
tmd.tmd0.tbadr)),
s->buffer + s->xmit_pos, 4096 - tmd.tmd1.bcnt);
s->xmit_pos += 4096 - tmd.tmd1.bcnt;
#ifdef PCNET_DEBUG
@@ -1787,3 +1817,73 @@
pcnet_h_reset(d);
}
+
+#if defined(TARGET_SPARC) && !defined (TARGET_SPARC64)
+// 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;
+ 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;
+ global_pcnet->ledmaregs[saddr] = val;
+}
+
+static CPUWriteMemoryFunc *lance_mem_write[3] = {
+ pcnet_ioport_writew,
+ pcnet_ioport_writew,
+ pcnet_ioport_writew,
+};
+
+static CPUReadMemoryFunc *lance_mem_read[3] = {
+ pcnet_ioport_readw,
+ pcnet_ioport_readw,
+ pcnet_ioport_readw,
+};
+
+void lance_init(NICInfo *nd, int irq, uint32_t leaddr, uint32_t ledaddr)
+{
+ PCNetState *s;
+ int lance_io_memory;
+
+ s = qemu_mallocz(sizeof(PCNetState));
+ if (!s)
+ return;
+
+ global_pcnet = s;
+ s->irq = irq;
+
+ lance_io_memory =
+ cpu_register_io_memory(0, lance_mem_read, lance_mem_write, s);
+ cpu_register_physical_memory(leaddr, 4, lance_io_memory);
+
+ s->poll_timer = qemu_new_timer(vm_clock, pcnet_poll_timer, s);
+
+ s->nd = nd;
+
+ s->vc = qemu_new_vlan_client(nd->vlan, pcnet_receive,
+ pcnet_can_receive, s);
+
+
+ snprintf(s->vc->info_str, sizeof(s->vc->info_str),
+ "lance macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
+ s->nd->macaddr[0],
+ s->nd->macaddr[1],
+ s->nd->macaddr[2],
+ s->nd->macaddr[3],
+ s->nd->macaddr[4],
+ s->nd->macaddr[5]);
+
+ pcnet_h_reset(s);
+}
+#endif
Index: qemu/Makefile.target
===================================================================
--- qemu.orig/Makefile.target 2006-08-20 13:46:51.000000000 +0000
+++ qemu/Makefile.target 2006-08-20 13:54:38.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-20 13:46:51.000000000 +0000
+++ qemu/hw/esp.c 2006-08-20 13:54:38.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
@@ -474,12 +475,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 +496,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 +591,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);
_______________________________________________
Qemu-devel mailing list
Qemu-devel@nongnu.org
http://lists.nongnu.org/mailman/listinfo/qemu-devel