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