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);