aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorBALATON Zoltan <balaton@eik.bme.hu>2017-08-20 19:23:05 +0200
committerDavid Gibson <david@gibson.dropbear.id.au>2017-09-08 09:30:55 +1000
commit0453428047527ac778489a927b66d591ff3c450c (patch)
tree475e616de8f68e6a288d14a4bc0e0f9d65804b8a /hw
parent517284a77171af6f5676678aea15030ea1887842 (diff)
ppc4xx: Make MAL emulation more generic
Allow MAL with more RX and TX channels as found in newer versions. Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu> Reviewed-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Diffstat (limited to 'hw')
-rw-r--r--hw/ppc/ppc405_uc.c2
-rw-r--r--hw/ppc/ppc4xx_devs.c171
2 files changed, 68 insertions, 105 deletions
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index 3c744021d6..03856d573f 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -2281,7 +2281,7 @@ CPUPPCState *ppc405ep_init(MemoryRegion *address_space_mem,
mal_irqs[1] = pic[12];
mal_irqs[2] = pic[13];
mal_irqs[3] = pic[14];
- ppc405_mal_init(env, mal_irqs);
+ ppc4xx_mal_init(env, 4, 2, mal_irqs);
/* Ethernet */
/* Uses pic[9], pic[15], pic[17] */
/* CPU control */
diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c
index b296ea66c2..ec90f13295 100644
--- a/hw/ppc/ppc4xx_devs.c
+++ b/hw/ppc/ppc4xx_devs.c
@@ -737,6 +737,7 @@ ram_addr_t ppc4xx_sdram_adjust(ram_addr_t ram_size, int nr_banks,
/*****************************************************************************/
/* MAL */
+
enum {
MAL0_CFG = 0x180,
MAL0_ESR = 0x181,
@@ -750,17 +751,13 @@ enum {
MAL0_RXEOBISR = 0x192,
MAL0_RXDEIR = 0x193,
MAL0_TXCTP0R = 0x1A0,
- MAL0_TXCTP1R = 0x1A1,
- MAL0_TXCTP2R = 0x1A2,
- MAL0_TXCTP3R = 0x1A3,
MAL0_RXCTP0R = 0x1C0,
- MAL0_RXCTP1R = 0x1C1,
MAL0_RCBS0 = 0x1E0,
MAL0_RCBS1 = 0x1E1,
};
-typedef struct ppc40x_mal_t ppc40x_mal_t;
-struct ppc40x_mal_t {
+typedef struct ppc4xx_mal_t ppc4xx_mal_t;
+struct ppc4xx_mal_t {
qemu_irq irqs[4];
uint32_t cfg;
uint32_t esr;
@@ -773,16 +770,32 @@ struct ppc40x_mal_t {
uint32_t rxcarr;
uint32_t rxeobisr;
uint32_t rxdeir;
- uint32_t txctpr[4];
- uint32_t rxctpr[2];
- uint32_t rcbs[2];
+ uint32_t *txctpr;
+ uint32_t *rxctpr;
+ uint32_t *rcbs;
+ uint8_t txcnum;
+ uint8_t rxcnum;
};
-static void ppc40x_mal_reset(void *opaque);
+static void ppc4xx_mal_reset(void *opaque)
+{
+ ppc4xx_mal_t *mal;
+
+ mal = opaque;
+ mal->cfg = 0x0007C000;
+ mal->esr = 0x00000000;
+ mal->ier = 0x00000000;
+ mal->rxcasr = 0x00000000;
+ mal->rxdeir = 0x00000000;
+ mal->rxeobisr = 0x00000000;
+ mal->txcasr = 0x00000000;
+ mal->txdeir = 0x00000000;
+ mal->txeobisr = 0x00000000;
+}
static uint32_t dcr_read_mal(void *opaque, int dcrn)
{
- ppc40x_mal_t *mal;
+ ppc4xx_mal_t *mal;
uint32_t ret;
mal = opaque;
@@ -820,48 +833,32 @@ static uint32_t dcr_read_mal(void *opaque, int dcrn)
case MAL0_RXDEIR:
ret = mal->rxdeir;
break;
- case MAL0_TXCTP0R:
- ret = mal->txctpr[0];
- break;
- case MAL0_TXCTP1R:
- ret = mal->txctpr[1];
- break;
- case MAL0_TXCTP2R:
- ret = mal->txctpr[2];
- break;
- case MAL0_TXCTP3R:
- ret = mal->txctpr[3];
- break;
- case MAL0_RXCTP0R:
- ret = mal->rxctpr[0];
- break;
- case MAL0_RXCTP1R:
- ret = mal->rxctpr[1];
- break;
- case MAL0_RCBS0:
- ret = mal->rcbs[0];
- break;
- case MAL0_RCBS1:
- ret = mal->rcbs[1];
- break;
default:
ret = 0;
break;
}
+ if (dcrn >= MAL0_TXCTP0R && dcrn < MAL0_TXCTP0R + mal->txcnum) {
+ ret = mal->txctpr[dcrn - MAL0_TXCTP0R];
+ }
+ if (dcrn >= MAL0_RXCTP0R && dcrn < MAL0_RXCTP0R + mal->rxcnum) {
+ ret = mal->rxctpr[dcrn - MAL0_RXCTP0R];
+ }
+ if (dcrn >= MAL0_RCBS0 && dcrn < MAL0_RCBS0 + mal->rxcnum) {
+ ret = mal->rcbs[dcrn - MAL0_RCBS0];
+ }
return ret;
}
static void dcr_write_mal(void *opaque, int dcrn, uint32_t val)
{
- ppc40x_mal_t *mal;
- int idx;
+ ppc4xx_mal_t *mal;
mal = opaque;
switch (dcrn) {
case MAL0_CFG:
if (val & 0x80000000) {
- ppc40x_mal_reset(mal);
+ ppc4xx_mal_reset(mal);
}
mal->cfg = val & 0x00FFC087;
break;
@@ -900,65 +897,35 @@ static void dcr_write_mal(void *opaque, int dcrn, uint32_t val)
/* Read/clear */
mal->rxdeir &= ~val;
break;
- case MAL0_TXCTP0R:
- idx = 0;
- goto update_tx_ptr;
- case MAL0_TXCTP1R:
- idx = 1;
- goto update_tx_ptr;
- case MAL0_TXCTP2R:
- idx = 2;
- goto update_tx_ptr;
- case MAL0_TXCTP3R:
- idx = 3;
- update_tx_ptr:
- mal->txctpr[idx] = val;
- break;
- case MAL0_RXCTP0R:
- idx = 0;
- goto update_rx_ptr;
- case MAL0_RXCTP1R:
- idx = 1;
- update_rx_ptr:
- mal->rxctpr[idx] = val;
- break;
- case MAL0_RCBS0:
- idx = 0;
- goto update_rx_size;
- case MAL0_RCBS1:
- idx = 1;
- update_rx_size:
- mal->rcbs[idx] = val & 0x000000FF;
- break;
+ }
+ if (dcrn >= MAL0_TXCTP0R && dcrn < MAL0_TXCTP0R + mal->txcnum) {
+ mal->txctpr[dcrn - MAL0_TXCTP0R] = val;
+ }
+ if (dcrn >= MAL0_RXCTP0R && dcrn < MAL0_RXCTP0R + mal->rxcnum) {
+ mal->rxctpr[dcrn - MAL0_RXCTP0R] = val;
+ }
+ if (dcrn >= MAL0_RCBS0 && dcrn < MAL0_RCBS0 + mal->rxcnum) {
+ mal->rcbs[dcrn - MAL0_RCBS0] = val & 0x000000FF;
}
}
-static void ppc40x_mal_reset(void *opaque)
-{
- ppc40x_mal_t *mal;
-
- mal = opaque;
- mal->cfg = 0x0007C000;
- mal->esr = 0x00000000;
- mal->ier = 0x00000000;
- mal->rxcasr = 0x00000000;
- mal->rxdeir = 0x00000000;
- mal->rxeobisr = 0x00000000;
- mal->txcasr = 0x00000000;
- mal->txdeir = 0x00000000;
- mal->txeobisr = 0x00000000;
-}
-
-void ppc405_mal_init(CPUPPCState *env, qemu_irq irqs[4])
+void ppc4xx_mal_init(CPUPPCState *env, uint8_t txcnum, uint8_t rxcnum,
+ qemu_irq irqs[4])
{
- ppc40x_mal_t *mal;
+ ppc4xx_mal_t *mal;
int i;
- mal = g_malloc0(sizeof(ppc40x_mal_t));
+ assert(txcnum <= 32 && rxcnum <= 32);
+ mal = g_malloc0(sizeof(*mal));
+ mal->txcnum = txcnum;
+ mal->rxcnum = rxcnum;
+ mal->txctpr = g_new0(uint32_t, txcnum);
+ mal->rxctpr = g_new0(uint32_t, rxcnum);
+ mal->rcbs = g_new0(uint32_t, rxcnum);
for (i = 0; i < 4; i++) {
mal->irqs[i] = irqs[i];
}
- qemu_register_reset(&ppc40x_mal_reset, mal);
+ qemu_register_reset(&ppc4xx_mal_reset, mal);
ppc_dcr_register(env, MAL0_CFG,
mal, &dcr_read_mal, &dcr_write_mal);
ppc_dcr_register(env, MAL0_ESR,
@@ -981,20 +948,16 @@ void ppc405_mal_init(CPUPPCState *env, qemu_irq irqs[4])
mal, &dcr_read_mal, &dcr_write_mal);
ppc_dcr_register(env, MAL0_RXDEIR,
mal, &dcr_read_mal, &dcr_write_mal);
- ppc_dcr_register(env, MAL0_TXCTP0R,
- mal, &dcr_read_mal, &dcr_write_mal);
- ppc_dcr_register(env, MAL0_TXCTP1R,
- mal, &dcr_read_mal, &dcr_write_mal);
- ppc_dcr_register(env, MAL0_TXCTP2R,
- mal, &dcr_read_mal, &dcr_write_mal);
- ppc_dcr_register(env, MAL0_TXCTP3R,
- mal, &dcr_read_mal, &dcr_write_mal);
- ppc_dcr_register(env, MAL0_RXCTP0R,
- mal, &dcr_read_mal, &dcr_write_mal);
- ppc_dcr_register(env, MAL0_RXCTP1R,
- mal, &dcr_read_mal, &dcr_write_mal);
- ppc_dcr_register(env, MAL0_RCBS0,
- mal, &dcr_read_mal, &dcr_write_mal);
- ppc_dcr_register(env, MAL0_RCBS1,
- mal, &dcr_read_mal, &dcr_write_mal);
+ for (i = 0; i < txcnum; i++) {
+ ppc_dcr_register(env, MAL0_TXCTP0R + i,
+ mal, &dcr_read_mal, &dcr_write_mal);
+ }
+ for (i = 0; i < rxcnum; i++) {
+ ppc_dcr_register(env, MAL0_RXCTP0R + i,
+ mal, &dcr_read_mal, &dcr_write_mal);
+ }
+ for (i = 0; i < rxcnum; i++) {
+ ppc_dcr_register(env, MAL0_RCBS0 + i,
+ mal, &dcr_read_mal, &dcr_write_mal);
+ }
}