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>
This commit is contained in:
BALATON Zoltan 2017-08-20 19:23:05 +02:00 committed by David Gibson
parent 517284a771
commit 0453428047
3 changed files with 70 additions and 106 deletions

View File

@ -2281,7 +2281,7 @@ CPUPPCState *ppc405ep_init(MemoryRegion *address_space_mem,
mal_irqs[1] = pic[12]; mal_irqs[1] = pic[12];
mal_irqs[2] = pic[13]; mal_irqs[2] = pic[13];
mal_irqs[3] = pic[14]; mal_irqs[3] = pic[14];
ppc405_mal_init(env, mal_irqs); ppc4xx_mal_init(env, 4, 2, mal_irqs);
/* Ethernet */ /* Ethernet */
/* Uses pic[9], pic[15], pic[17] */ /* Uses pic[9], pic[15], pic[17] */
/* CPU control */ /* CPU control */

View File

@ -737,6 +737,7 @@ ram_addr_t ppc4xx_sdram_adjust(ram_addr_t ram_size, int nr_banks,
/*****************************************************************************/ /*****************************************************************************/
/* MAL */ /* MAL */
enum { enum {
MAL0_CFG = 0x180, MAL0_CFG = 0x180,
MAL0_ESR = 0x181, MAL0_ESR = 0x181,
@ -750,17 +751,13 @@ enum {
MAL0_RXEOBISR = 0x192, MAL0_RXEOBISR = 0x192,
MAL0_RXDEIR = 0x193, MAL0_RXDEIR = 0x193,
MAL0_TXCTP0R = 0x1A0, MAL0_TXCTP0R = 0x1A0,
MAL0_TXCTP1R = 0x1A1,
MAL0_TXCTP2R = 0x1A2,
MAL0_TXCTP3R = 0x1A3,
MAL0_RXCTP0R = 0x1C0, MAL0_RXCTP0R = 0x1C0,
MAL0_RXCTP1R = 0x1C1,
MAL0_RCBS0 = 0x1E0, MAL0_RCBS0 = 0x1E0,
MAL0_RCBS1 = 0x1E1, MAL0_RCBS1 = 0x1E1,
}; };
typedef struct ppc40x_mal_t ppc40x_mal_t; typedef struct ppc4xx_mal_t ppc4xx_mal_t;
struct ppc40x_mal_t { struct ppc4xx_mal_t {
qemu_irq irqs[4]; qemu_irq irqs[4];
uint32_t cfg; uint32_t cfg;
uint32_t esr; uint32_t esr;
@ -773,16 +770,32 @@ struct ppc40x_mal_t {
uint32_t rxcarr; uint32_t rxcarr;
uint32_t rxeobisr; uint32_t rxeobisr;
uint32_t rxdeir; uint32_t rxdeir;
uint32_t txctpr[4]; uint32_t *txctpr;
uint32_t rxctpr[2]; uint32_t *rxctpr;
uint32_t rcbs[2]; 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) static uint32_t dcr_read_mal(void *opaque, int dcrn)
{ {
ppc40x_mal_t *mal; ppc4xx_mal_t *mal;
uint32_t ret; uint32_t ret;
mal = opaque; mal = opaque;
@ -820,48 +833,32 @@ static uint32_t dcr_read_mal(void *opaque, int dcrn)
case MAL0_RXDEIR: case MAL0_RXDEIR:
ret = mal->rxdeir; ret = mal->rxdeir;
break; 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: default:
ret = 0; ret = 0;
break; 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; return ret;
} }
static void dcr_write_mal(void *opaque, int dcrn, uint32_t val) static void dcr_write_mal(void *opaque, int dcrn, uint32_t val)
{ {
ppc40x_mal_t *mal; ppc4xx_mal_t *mal;
int idx;
mal = opaque; mal = opaque;
switch (dcrn) { switch (dcrn) {
case MAL0_CFG: case MAL0_CFG:
if (val & 0x80000000) { if (val & 0x80000000) {
ppc40x_mal_reset(mal); ppc4xx_mal_reset(mal);
} }
mal->cfg = val & 0x00FFC087; mal->cfg = val & 0x00FFC087;
break; break;
@ -900,65 +897,35 @@ static void dcr_write_mal(void *opaque, int dcrn, uint32_t val)
/* Read/clear */ /* Read/clear */
mal->rxdeir &= ~val; mal->rxdeir &= ~val;
break; break;
case MAL0_TXCTP0R: }
idx = 0; if (dcrn >= MAL0_TXCTP0R && dcrn < MAL0_TXCTP0R + mal->txcnum) {
goto update_tx_ptr; mal->txctpr[dcrn - MAL0_TXCTP0R] = val;
case MAL0_TXCTP1R: }
idx = 1; if (dcrn >= MAL0_RXCTP0R && dcrn < MAL0_RXCTP0R + mal->rxcnum) {
goto update_tx_ptr; mal->rxctpr[dcrn - MAL0_RXCTP0R] = val;
case MAL0_TXCTP2R: }
idx = 2; if (dcrn >= MAL0_RCBS0 && dcrn < MAL0_RCBS0 + mal->rxcnum) {
goto update_tx_ptr; mal->rcbs[dcrn - MAL0_RCBS0] = val & 0x000000FF;
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;
} }
} }
static void ppc40x_mal_reset(void *opaque) void ppc4xx_mal_init(CPUPPCState *env, uint8_t txcnum, uint8_t rxcnum,
qemu_irq irqs[4])
{ {
ppc40x_mal_t *mal; 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;
}
void ppc405_mal_init(CPUPPCState *env, qemu_irq irqs[4])
{
ppc40x_mal_t *mal;
int i; 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++) { for (i = 0; i < 4; i++) {
mal->irqs[i] = irqs[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, ppc_dcr_register(env, MAL0_CFG,
mal, &dcr_read_mal, &dcr_write_mal); mal, &dcr_read_mal, &dcr_write_mal);
ppc_dcr_register(env, MAL0_ESR, 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); mal, &dcr_read_mal, &dcr_write_mal);
ppc_dcr_register(env, MAL0_RXDEIR, ppc_dcr_register(env, MAL0_RXDEIR,
mal, &dcr_read_mal, &dcr_write_mal); mal, &dcr_read_mal, &dcr_write_mal);
ppc_dcr_register(env, MAL0_TXCTP0R, for (i = 0; i < txcnum; i++) {
mal, &dcr_read_mal, &dcr_write_mal); ppc_dcr_register(env, MAL0_TXCTP0R + i,
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); 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);
}
}

View File

@ -53,7 +53,8 @@ void ppc4xx_sdram_init (CPUPPCState *env, qemu_irq irq, int nbanks,
hwaddr *ram_sizes, hwaddr *ram_sizes,
int do_init); int do_init);
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]);
#define TYPE_PPC4xx_PCI_HOST_BRIDGE "ppc4xx-pcihost" #define TYPE_PPC4xx_PCI_HOST_BRIDGE "ppc4xx-pcihost"