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-24 17:22:19.000000000 +0000 @@ -36,10 +36,27 @@ //#define PCNET_DEBUG_RMD //#define PCNET_DEBUG_TMD //#define PCNET_DEBUG_MATCH +//#define PCNET_DEBUG_SPARC_IOMMU +//#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 +#if defined(PCNET_DEBUG_SPARC_IOMMU) +#define iommu_translate(addr) \ + (printf("PCNET: iommu_translate(0x%x) -> 0x%x\n", (addr), \ + iommu_translate(addr)), iommu_translate(addr)) +#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 +66,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 +76,11 @@ int xmit_pos, recv_pos; uint8_t buffer[4096]; int tx_busy; +#if defined(TARGET_SPARC) && !defined (TARGET_SPARC64) + // Lance-specific + int irq; + uint32_t ledmaregs[LEDMA_REGS]; +#endif }; /* XXX: using bitfields for target memory structures is almost surely @@ -90,7 +113,11 @@ #define BCR_DWIO(S) !!((S)->bcr[BCR_BSBC] & 0x0080) #define BCR_SSIZE32(S) !!((S)->bcr[BCR_SWS ] & 0x0100) +#if defined(TARGET_SPARC) && !defined (TARGET_SPARC64) +#define BCR_SWSTYLE(S) (0) +#else #define BCR_SWSTYLE(S) ((S)->bcr[BCR_SWS ] & 0x00FF) +#endif #define CSR_INIT(S) !!(((S)->csr[0])&0x0001) #define CSR_STRT(S) !!(((S)->csr[0])&0x0002) @@ -142,14 +169,28 @@ #define CSR_PXDA(S) ((S)->csr[60] | ((S)->csr[61] << 16)) #define CSR_NXBA(S) ((S)->csr[64] | ((S)->csr[65] << 16)) +#if defined(TARGET_SPARC) && !defined (TARGET_SPARC64) +#define PHYSADDR(S,A) ((A) | (S)->ledmaregs[3]) +#define SPARC_IOMMU_TRANSLATE(addr) iommu_translate(addr) +#define SPARC_FIX_INITBLK(initblk) do{ bswap16s((uint16_t *)&initblk.ladrf4 + 1); \ + bswap16s((uint16_t *)&initblk.ladrf4 + 2); \ + bswap16s((uint16_t *)&initblk.ladrf4 + 3); \ + bswap16s((uint16_t *)&initblk.ladrf4 + 4);} while(0) +#define SPARC_FIX_DESC(desc) do{ bswap16s((uint16_t *)&desc); \ + bswap16s((uint16_t *)&desc + 1); \ + bswap16s((uint16_t *)&desc + 2); \ + bswap16s((uint16_t *)&desc + 3); } while(0) +#else #define PHYSADDR(S,A) \ (BCR_SSIZE32(S) ? (A) : (A) | ((0xff00 & (uint32_t)(s)->csr[2])<<16)) +#define SPARC_IOMMU_TRANSLATE(addr) (addr) +#define SPARC_FIX_INITBLK(initblk) do{}while(0) +#define SPARC_FIX_DESC(desc) do{}while(0) +#endif struct pcnet_initblk16 { uint16_t mode; - uint16_t padr1; - uint16_t padr2; - uint16_t padr3; + uint8_t padr[6]; uint16_t ladrf1; uint16_t ladrf2; uint16_t ladrf3; @@ -168,9 +209,7 @@ 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; @@ -255,8 +294,10 @@ { if (!BCR_SWSTYLE(s)) { uint16_t xda[4]; + addr = SPARC_IOMMU_TRANSLATE(addr); cpu_physical_memory_read(addr, (void *)&xda[0], sizeof(xda)); + SPARC_FIX_DESC(xda); ((uint32_t *)tmd)[0] = (xda[0]&0xffff) | ((xda[1]&0x00ff) << 16); ((uint32_t *)tmd)[1] = (xda[2]&0xffff)| @@ -288,6 +329,8 @@ ((((uint32_t *)tmd)[1]>>16)&0xff00); xda[2] = ((uint32_t *)tmd)[1] & 0xffff; xda[3] = ((uint32_t *)tmd)[2] >> 16; + SPARC_FIX_DESC(xda); + addr = SPARC_IOMMU_TRANSLATE(addr); cpu_physical_memory_write(addr, (void *)&xda[0], sizeof(xda)); } @@ -310,8 +353,10 @@ { if (!BCR_SWSTYLE(s)) { uint16_t rda[4]; + addr = SPARC_IOMMU_TRANSLATE(addr); cpu_physical_memory_read(addr, (void *)&rda[0], sizeof(rda)); + SPARC_FIX_DESC(rda); ((uint32_t *)rmd)[0] = (rda[0]&0xffff)| ((rda[1] & 0x00ff) << 16); ((uint32_t *)rmd)[1] = (rda[2]&0xffff)| @@ -342,6 +387,8 @@ ((((uint32_t *)rmd)[1]>>16)&0xff00);\ rda[2] = ((uint32_t *)rmd)[1] & 0xffff; \ rda[3] = ((uint32_t *)rmd)[2] & 0xffff; \ + SPARC_FIX_DESC(rda); + addr = SPARC_IOMMU_TRANSLATE(addr); cpu_physical_memory_write(addr, \ (void *)&rda[0], sizeof(rda)); \ } @@ -448,14 +495,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 @@ -564,6 +610,7 @@ 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("csr[12]=%x, lo %x hi %x\n", s->csr[12], s->csr[12] & 0xff, s->csr[12]>>8); printf("padr_match result=%d\n", result); #endif return result; @@ -643,9 +690,9 @@ 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); s->csr[15] &= 0x21c4; s->csr[72] = 1; s->csr[74] = 1; @@ -721,8 +768,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,19 +783,20 @@ #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)); \ + SPARC_FIX_INITBLK(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->csr[ 8] = initblk.ladrf1; \ + s->csr[ 9] = initblk.ladrf2; \ + s->csr[10] = initblk.ladrf3; \ + s->csr[11] = initblk.ladrf4; \ + s->csr[12] = initblk.padr[0] | (initblk.padr[1] << 8); \ + s->csr[13] = initblk.padr[2] | (initblk.padr[3] << 8); \ + s->csr[14] = initblk.padr[4] | (initblk.padr[5] << 8); \ s->rdra = PHYSADDR(s,initblk.rdra); \ s->tdra = PHYSADDR(s,initblk.tdra); \ } while (0) @@ -954,11 +1006,13 @@ buf = buf1; size = MIN_BUF_SIZE; } - +#if 0 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))) { + || (is_ladr=ladr_match(s, buf, size))) +#endif + { pcnet_rdte_poll(s); @@ -1035,6 +1089,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 +1180,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 @@ -1727,6 +1782,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 +1845,65 @@ 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_common_init(d, nd, "pcnet"); +} - 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]); +#if defined(TARGET_SPARC) && !defined (TARGET_SPARC64) +// Due to Qemu limitations, Lance DMA registers are accessed via ESP +// DMA registers +static PCNetState *global_pcnet; - pcnet_h_reset(d); +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] = { + 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 *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); + + pcnet_common_init(d, nd, "lance"); +} +#endif Index: qemu/Makefile.target =================================================================== --- qemu.orig/Makefile.target 2006-08-20 13:46:51.000000000 +0000 +++ qemu/Makefile.target 2006-08-22 17:36:23.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);