cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

ppc4xx_devs.c (20876B)


      1/*
      2 * QEMU PowerPC 4xx embedded processors shared devices emulation
      3 *
      4 * Copyright (c) 2007 Jocelyn Mayer
      5 *
      6 * Permission is hereby granted, free of charge, to any person obtaining a copy
      7 * of this software and associated documentation files (the "Software"), to deal
      8 * in the Software without restriction, including without limitation the rights
      9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     10 * copies of the Software, and to permit persons to whom the Software is
     11 * furnished to do so, subject to the following conditions:
     12 *
     13 * The above copyright notice and this permission notice shall be included in
     14 * all copies or substantial portions of the Software.
     15 *
     16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     22 * THE SOFTWARE.
     23 */
     24
     25#include "qemu/osdep.h"
     26#include "qemu/units.h"
     27#include "sysemu/reset.h"
     28#include "cpu.h"
     29#include "hw/irq.h"
     30#include "hw/ppc/ppc.h"
     31#include "hw/ppc/ppc4xx.h"
     32#include "hw/intc/ppc-uic.h"
     33#include "hw/qdev-properties.h"
     34#include "qemu/log.h"
     35#include "exec/address-spaces.h"
     36#include "qemu/error-report.h"
     37#include "qapi/error.h"
     38
     39/*#define DEBUG_UIC*/
     40
     41#ifdef DEBUG_UIC
     42#  define LOG_UIC(...) qemu_log_mask(CPU_LOG_INT, ## __VA_ARGS__)
     43#else
     44#  define LOG_UIC(...) do { } while (0)
     45#endif
     46
     47static void ppc4xx_reset(void *opaque)
     48{
     49    PowerPCCPU *cpu = opaque;
     50
     51    cpu_reset(CPU(cpu));
     52}
     53
     54/*****************************************************************************/
     55/* Generic PowerPC 4xx processor instantiation */
     56PowerPCCPU *ppc4xx_init(const char *cpu_type,
     57                        clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
     58                        uint32_t sysclk)
     59{
     60    PowerPCCPU *cpu;
     61    CPUPPCState *env;
     62
     63    /* init CPUs */
     64    cpu = POWERPC_CPU(cpu_create(cpu_type));
     65    env = &cpu->env;
     66
     67    cpu_clk->cb = NULL; /* We don't care about CPU clock frequency changes */
     68    cpu_clk->opaque = env;
     69    /* Set time-base frequency to sysclk */
     70    tb_clk->cb = ppc_40x_timers_init(env, sysclk, PPC_INTERRUPT_PIT);
     71    tb_clk->opaque = env;
     72    ppc_dcr_init(env, NULL, NULL);
     73    /* Register qemu callbacks */
     74    qemu_register_reset(ppc4xx_reset, cpu);
     75
     76    return cpu;
     77}
     78
     79/*****************************************************************************/
     80/* SDRAM controller */
     81typedef struct ppc4xx_sdram_t ppc4xx_sdram_t;
     82struct ppc4xx_sdram_t {
     83    uint32_t addr;
     84    int nbanks;
     85    MemoryRegion containers[4]; /* used for clipping */
     86    MemoryRegion *ram_memories;
     87    hwaddr ram_bases[4];
     88    hwaddr ram_sizes[4];
     89    uint32_t besr0;
     90    uint32_t besr1;
     91    uint32_t bear;
     92    uint32_t cfg;
     93    uint32_t status;
     94    uint32_t rtr;
     95    uint32_t pmit;
     96    uint32_t bcr[4];
     97    uint32_t tr;
     98    uint32_t ecccfg;
     99    uint32_t eccesr;
    100    qemu_irq irq;
    101};
    102
    103enum {
    104    SDRAM0_CFGADDR = 0x010,
    105    SDRAM0_CFGDATA = 0x011,
    106};
    107
    108/* XXX: TOFIX: some patches have made this code become inconsistent:
    109 *      there are type inconsistencies, mixing hwaddr, target_ulong
    110 *      and uint32_t
    111 */
    112static uint32_t sdram_bcr (hwaddr ram_base,
    113                           hwaddr ram_size)
    114{
    115    uint32_t bcr;
    116
    117    switch (ram_size) {
    118    case 4 * MiB:
    119        bcr = 0x00000000;
    120        break;
    121    case 8 * MiB:
    122        bcr = 0x00020000;
    123        break;
    124    case 16 * MiB:
    125        bcr = 0x00040000;
    126        break;
    127    case 32 * MiB:
    128        bcr = 0x00060000;
    129        break;
    130    case 64 * MiB:
    131        bcr = 0x00080000;
    132        break;
    133    case 128 * MiB:
    134        bcr = 0x000A0000;
    135        break;
    136    case 256 * MiB:
    137        bcr = 0x000C0000;
    138        break;
    139    default:
    140        printf("%s: invalid RAM size " TARGET_FMT_plx "\n", __func__,
    141               ram_size);
    142        return 0x00000000;
    143    }
    144    bcr |= ram_base & 0xFF800000;
    145    bcr |= 1;
    146
    147    return bcr;
    148}
    149
    150static inline hwaddr sdram_base(uint32_t bcr)
    151{
    152    return bcr & 0xFF800000;
    153}
    154
    155static target_ulong sdram_size (uint32_t bcr)
    156{
    157    target_ulong size;
    158    int sh;
    159
    160    sh = (bcr >> 17) & 0x7;
    161    if (sh == 7)
    162        size = -1;
    163    else
    164        size = (4 * MiB) << sh;
    165
    166    return size;
    167}
    168
    169static void sdram_set_bcr(ppc4xx_sdram_t *sdram, int i,
    170                          uint32_t bcr, int enabled)
    171{
    172    if (sdram->bcr[i] & 0x00000001) {
    173        /* Unmap RAM */
    174#ifdef DEBUG_SDRAM
    175        printf("%s: unmap RAM area " TARGET_FMT_plx " " TARGET_FMT_lx "\n",
    176               __func__, sdram_base(sdram->bcr[i]), sdram_size(sdram->bcr[i]));
    177#endif
    178        memory_region_del_subregion(get_system_memory(),
    179                                    &sdram->containers[i]);
    180        memory_region_del_subregion(&sdram->containers[i],
    181                                    &sdram->ram_memories[i]);
    182        object_unparent(OBJECT(&sdram->containers[i]));
    183    }
    184    sdram->bcr[i] = bcr & 0xFFDEE001;
    185    if (enabled && (bcr & 0x00000001)) {
    186#ifdef DEBUG_SDRAM
    187        printf("%s: Map RAM area " TARGET_FMT_plx " " TARGET_FMT_lx "\n",
    188               __func__, sdram_base(bcr), sdram_size(bcr));
    189#endif
    190        memory_region_init(&sdram->containers[i], NULL, "sdram-containers",
    191                           sdram_size(bcr));
    192        memory_region_add_subregion(&sdram->containers[i], 0,
    193                                    &sdram->ram_memories[i]);
    194        memory_region_add_subregion(get_system_memory(),
    195                                    sdram_base(bcr),
    196                                    &sdram->containers[i]);
    197    }
    198}
    199
    200static void sdram_map_bcr (ppc4xx_sdram_t *sdram)
    201{
    202    int i;
    203
    204    for (i = 0; i < sdram->nbanks; i++) {
    205        if (sdram->ram_sizes[i] != 0) {
    206            sdram_set_bcr(sdram, i, sdram_bcr(sdram->ram_bases[i],
    207                                              sdram->ram_sizes[i]), 1);
    208        } else {
    209            sdram_set_bcr(sdram, i, 0x00000000, 0);
    210        }
    211    }
    212}
    213
    214static void sdram_unmap_bcr (ppc4xx_sdram_t *sdram)
    215{
    216    int i;
    217
    218    for (i = 0; i < sdram->nbanks; i++) {
    219#ifdef DEBUG_SDRAM
    220        printf("%s: Unmap RAM area " TARGET_FMT_plx " " TARGET_FMT_lx "\n",
    221               __func__, sdram_base(sdram->bcr[i]), sdram_size(sdram->bcr[i]));
    222#endif
    223        memory_region_del_subregion(get_system_memory(),
    224                                    &sdram->ram_memories[i]);
    225    }
    226}
    227
    228static uint32_t dcr_read_sdram (void *opaque, int dcrn)
    229{
    230    ppc4xx_sdram_t *sdram;
    231    uint32_t ret;
    232
    233    sdram = opaque;
    234    switch (dcrn) {
    235    case SDRAM0_CFGADDR:
    236        ret = sdram->addr;
    237        break;
    238    case SDRAM0_CFGDATA:
    239        switch (sdram->addr) {
    240        case 0x00: /* SDRAM_BESR0 */
    241            ret = sdram->besr0;
    242            break;
    243        case 0x08: /* SDRAM_BESR1 */
    244            ret = sdram->besr1;
    245            break;
    246        case 0x10: /* SDRAM_BEAR */
    247            ret = sdram->bear;
    248            break;
    249        case 0x20: /* SDRAM_CFG */
    250            ret = sdram->cfg;
    251            break;
    252        case 0x24: /* SDRAM_STATUS */
    253            ret = sdram->status;
    254            break;
    255        case 0x30: /* SDRAM_RTR */
    256            ret = sdram->rtr;
    257            break;
    258        case 0x34: /* SDRAM_PMIT */
    259            ret = sdram->pmit;
    260            break;
    261        case 0x40: /* SDRAM_B0CR */
    262            ret = sdram->bcr[0];
    263            break;
    264        case 0x44: /* SDRAM_B1CR */
    265            ret = sdram->bcr[1];
    266            break;
    267        case 0x48: /* SDRAM_B2CR */
    268            ret = sdram->bcr[2];
    269            break;
    270        case 0x4C: /* SDRAM_B3CR */
    271            ret = sdram->bcr[3];
    272            break;
    273        case 0x80: /* SDRAM_TR */
    274            ret = -1; /* ? */
    275            break;
    276        case 0x94: /* SDRAM_ECCCFG */
    277            ret = sdram->ecccfg;
    278            break;
    279        case 0x98: /* SDRAM_ECCESR */
    280            ret = sdram->eccesr;
    281            break;
    282        default: /* Error */
    283            ret = -1;
    284            break;
    285        }
    286        break;
    287    default:
    288        /* Avoid gcc warning */
    289        ret = 0x00000000;
    290        break;
    291    }
    292
    293    return ret;
    294}
    295
    296static void dcr_write_sdram (void *opaque, int dcrn, uint32_t val)
    297{
    298    ppc4xx_sdram_t *sdram;
    299
    300    sdram = opaque;
    301    switch (dcrn) {
    302    case SDRAM0_CFGADDR:
    303        sdram->addr = val;
    304        break;
    305    case SDRAM0_CFGDATA:
    306        switch (sdram->addr) {
    307        case 0x00: /* SDRAM_BESR0 */
    308            sdram->besr0 &= ~val;
    309            break;
    310        case 0x08: /* SDRAM_BESR1 */
    311            sdram->besr1 &= ~val;
    312            break;
    313        case 0x10: /* SDRAM_BEAR */
    314            sdram->bear = val;
    315            break;
    316        case 0x20: /* SDRAM_CFG */
    317            val &= 0xFFE00000;
    318            if (!(sdram->cfg & 0x80000000) && (val & 0x80000000)) {
    319#ifdef DEBUG_SDRAM
    320                printf("%s: enable SDRAM controller\n", __func__);
    321#endif
    322                /* validate all RAM mappings */
    323                sdram_map_bcr(sdram);
    324                sdram->status &= ~0x80000000;
    325            } else if ((sdram->cfg & 0x80000000) && !(val & 0x80000000)) {
    326#ifdef DEBUG_SDRAM
    327                printf("%s: disable SDRAM controller\n", __func__);
    328#endif
    329                /* invalidate all RAM mappings */
    330                sdram_unmap_bcr(sdram);
    331                sdram->status |= 0x80000000;
    332            }
    333            if (!(sdram->cfg & 0x40000000) && (val & 0x40000000))
    334                sdram->status |= 0x40000000;
    335            else if ((sdram->cfg & 0x40000000) && !(val & 0x40000000))
    336                sdram->status &= ~0x40000000;
    337            sdram->cfg = val;
    338            break;
    339        case 0x24: /* SDRAM_STATUS */
    340            /* Read-only register */
    341            break;
    342        case 0x30: /* SDRAM_RTR */
    343            sdram->rtr = val & 0x3FF80000;
    344            break;
    345        case 0x34: /* SDRAM_PMIT */
    346            sdram->pmit = (val & 0xF8000000) | 0x07C00000;
    347            break;
    348        case 0x40: /* SDRAM_B0CR */
    349            sdram_set_bcr(sdram, 0, val, sdram->cfg & 0x80000000);
    350            break;
    351        case 0x44: /* SDRAM_B1CR */
    352            sdram_set_bcr(sdram, 1, val, sdram->cfg & 0x80000000);
    353            break;
    354        case 0x48: /* SDRAM_B2CR */
    355            sdram_set_bcr(sdram, 2, val, sdram->cfg & 0x80000000);
    356            break;
    357        case 0x4C: /* SDRAM_B3CR */
    358            sdram_set_bcr(sdram, 3, val, sdram->cfg & 0x80000000);
    359            break;
    360        case 0x80: /* SDRAM_TR */
    361            sdram->tr = val & 0x018FC01F;
    362            break;
    363        case 0x94: /* SDRAM_ECCCFG */
    364            sdram->ecccfg = val & 0x00F00000;
    365            break;
    366        case 0x98: /* SDRAM_ECCESR */
    367            val &= 0xFFF0F000;
    368            if (sdram->eccesr == 0 && val != 0)
    369                qemu_irq_raise(sdram->irq);
    370            else if (sdram->eccesr != 0 && val == 0)
    371                qemu_irq_lower(sdram->irq);
    372            sdram->eccesr = val;
    373            break;
    374        default: /* Error */
    375            break;
    376        }
    377        break;
    378    }
    379}
    380
    381static void sdram_reset (void *opaque)
    382{
    383    ppc4xx_sdram_t *sdram;
    384
    385    sdram = opaque;
    386    sdram->addr = 0x00000000;
    387    sdram->bear = 0x00000000;
    388    sdram->besr0 = 0x00000000; /* No error */
    389    sdram->besr1 = 0x00000000; /* No error */
    390    sdram->cfg = 0x00000000;
    391    sdram->ecccfg = 0x00000000; /* No ECC */
    392    sdram->eccesr = 0x00000000; /* No error */
    393    sdram->pmit = 0x07C00000;
    394    sdram->rtr = 0x05F00000;
    395    sdram->tr = 0x00854009;
    396    /* We pre-initialize RAM banks */
    397    sdram->status = 0x00000000;
    398    sdram->cfg = 0x00800000;
    399}
    400
    401void ppc4xx_sdram_init (CPUPPCState *env, qemu_irq irq, int nbanks,
    402                        MemoryRegion *ram_memories,
    403                        hwaddr *ram_bases,
    404                        hwaddr *ram_sizes,
    405                        int do_init)
    406{
    407    ppc4xx_sdram_t *sdram;
    408
    409    sdram = g_malloc0(sizeof(ppc4xx_sdram_t));
    410    sdram->irq = irq;
    411    sdram->nbanks = nbanks;
    412    sdram->ram_memories = ram_memories;
    413    memset(sdram->ram_bases, 0, 4 * sizeof(hwaddr));
    414    memcpy(sdram->ram_bases, ram_bases,
    415           nbanks * sizeof(hwaddr));
    416    memset(sdram->ram_sizes, 0, 4 * sizeof(hwaddr));
    417    memcpy(sdram->ram_sizes, ram_sizes,
    418           nbanks * sizeof(hwaddr));
    419    qemu_register_reset(&sdram_reset, sdram);
    420    ppc_dcr_register(env, SDRAM0_CFGADDR,
    421                     sdram, &dcr_read_sdram, &dcr_write_sdram);
    422    ppc_dcr_register(env, SDRAM0_CFGDATA,
    423                     sdram, &dcr_read_sdram, &dcr_write_sdram);
    424    if (do_init)
    425        sdram_map_bcr(sdram);
    426}
    427
    428/*
    429 * Split RAM between SDRAM banks.
    430 *
    431 * sdram_bank_sizes[] must be in descending order, that is sizes[i] > sizes[i+1]
    432 * and must be 0-terminated.
    433 *
    434 * The 4xx SDRAM controller supports a small number of banks, and each bank
    435 * must be one of a small set of sizes. The number of banks and the supported
    436 * sizes varies by SoC.
    437 */
    438void ppc4xx_sdram_banks(MemoryRegion *ram, int nr_banks,
    439                        MemoryRegion ram_memories[],
    440                        hwaddr ram_bases[], hwaddr ram_sizes[],
    441                        const ram_addr_t sdram_bank_sizes[])
    442{
    443    ram_addr_t size_left = memory_region_size(ram);
    444    ram_addr_t base = 0;
    445    ram_addr_t bank_size;
    446    int i;
    447    int j;
    448
    449    for (i = 0; i < nr_banks; i++) {
    450        for (j = 0; sdram_bank_sizes[j] != 0; j++) {
    451            bank_size = sdram_bank_sizes[j];
    452            if (bank_size <= size_left) {
    453                char name[32];
    454
    455                ram_bases[i] = base;
    456                ram_sizes[i] = bank_size;
    457                base += bank_size;
    458                size_left -= bank_size;
    459                snprintf(name, sizeof(name), "ppc4xx.sdram%d", i);
    460                memory_region_init_alias(&ram_memories[i], NULL, name, ram,
    461                                         ram_bases[i], ram_sizes[i]);
    462                break;
    463            }
    464        }
    465        if (!size_left) {
    466            /* No need to use the remaining banks. */
    467            break;
    468        }
    469    }
    470
    471    if (size_left) {
    472        ram_addr_t used_size = memory_region_size(ram) - size_left;
    473        GString *s = g_string_new(NULL);
    474
    475        for (i = 0; sdram_bank_sizes[i]; i++) {
    476            g_string_append_printf(s, "%" PRIi64 "%s",
    477                                   sdram_bank_sizes[i] / MiB,
    478                                   sdram_bank_sizes[i + 1] ? ", " : "");
    479        }
    480        error_report("at most %d bank%s of %s MiB each supported",
    481                     nr_banks, nr_banks == 1 ? "" : "s", s->str);
    482        error_printf("Possible valid RAM size: %" PRIi64 " MiB \n",
    483            used_size ? used_size / MiB : sdram_bank_sizes[i - 1] / MiB);
    484
    485        g_string_free(s, true);
    486        exit(EXIT_FAILURE);
    487    }
    488}
    489
    490/*****************************************************************************/
    491/* MAL */
    492
    493enum {
    494    MAL0_CFG      = 0x180,
    495    MAL0_ESR      = 0x181,
    496    MAL0_IER      = 0x182,
    497    MAL0_TXCASR   = 0x184,
    498    MAL0_TXCARR   = 0x185,
    499    MAL0_TXEOBISR = 0x186,
    500    MAL0_TXDEIR   = 0x187,
    501    MAL0_RXCASR   = 0x190,
    502    MAL0_RXCARR   = 0x191,
    503    MAL0_RXEOBISR = 0x192,
    504    MAL0_RXDEIR   = 0x193,
    505    MAL0_TXCTP0R  = 0x1A0,
    506    MAL0_RXCTP0R  = 0x1C0,
    507    MAL0_RCBS0    = 0x1E0,
    508    MAL0_RCBS1    = 0x1E1,
    509};
    510
    511typedef struct ppc4xx_mal_t ppc4xx_mal_t;
    512struct ppc4xx_mal_t {
    513    qemu_irq irqs[4];
    514    uint32_t cfg;
    515    uint32_t esr;
    516    uint32_t ier;
    517    uint32_t txcasr;
    518    uint32_t txcarr;
    519    uint32_t txeobisr;
    520    uint32_t txdeir;
    521    uint32_t rxcasr;
    522    uint32_t rxcarr;
    523    uint32_t rxeobisr;
    524    uint32_t rxdeir;
    525    uint32_t *txctpr;
    526    uint32_t *rxctpr;
    527    uint32_t *rcbs;
    528    uint8_t  txcnum;
    529    uint8_t  rxcnum;
    530};
    531
    532static void ppc4xx_mal_reset(void *opaque)
    533{
    534    ppc4xx_mal_t *mal;
    535
    536    mal = opaque;
    537    mal->cfg = 0x0007C000;
    538    mal->esr = 0x00000000;
    539    mal->ier = 0x00000000;
    540    mal->rxcasr = 0x00000000;
    541    mal->rxdeir = 0x00000000;
    542    mal->rxeobisr = 0x00000000;
    543    mal->txcasr = 0x00000000;
    544    mal->txdeir = 0x00000000;
    545    mal->txeobisr = 0x00000000;
    546}
    547
    548static uint32_t dcr_read_mal(void *opaque, int dcrn)
    549{
    550    ppc4xx_mal_t *mal;
    551    uint32_t ret;
    552
    553    mal = opaque;
    554    switch (dcrn) {
    555    case MAL0_CFG:
    556        ret = mal->cfg;
    557        break;
    558    case MAL0_ESR:
    559        ret = mal->esr;
    560        break;
    561    case MAL0_IER:
    562        ret = mal->ier;
    563        break;
    564    case MAL0_TXCASR:
    565        ret = mal->txcasr;
    566        break;
    567    case MAL0_TXCARR:
    568        ret = mal->txcarr;
    569        break;
    570    case MAL0_TXEOBISR:
    571        ret = mal->txeobisr;
    572        break;
    573    case MAL0_TXDEIR:
    574        ret = mal->txdeir;
    575        break;
    576    case MAL0_RXCASR:
    577        ret = mal->rxcasr;
    578        break;
    579    case MAL0_RXCARR:
    580        ret = mal->rxcarr;
    581        break;
    582    case MAL0_RXEOBISR:
    583        ret = mal->rxeobisr;
    584        break;
    585    case MAL0_RXDEIR:
    586        ret = mal->rxdeir;
    587        break;
    588    default:
    589        ret = 0;
    590        break;
    591    }
    592    if (dcrn >= MAL0_TXCTP0R && dcrn < MAL0_TXCTP0R + mal->txcnum) {
    593        ret = mal->txctpr[dcrn - MAL0_TXCTP0R];
    594    }
    595    if (dcrn >= MAL0_RXCTP0R && dcrn < MAL0_RXCTP0R + mal->rxcnum) {
    596        ret = mal->rxctpr[dcrn - MAL0_RXCTP0R];
    597    }
    598    if (dcrn >= MAL0_RCBS0 && dcrn < MAL0_RCBS0 + mal->rxcnum) {
    599        ret = mal->rcbs[dcrn - MAL0_RCBS0];
    600    }
    601
    602    return ret;
    603}
    604
    605static void dcr_write_mal(void *opaque, int dcrn, uint32_t val)
    606{
    607    ppc4xx_mal_t *mal;
    608
    609    mal = opaque;
    610    switch (dcrn) {
    611    case MAL0_CFG:
    612        if (val & 0x80000000) {
    613            ppc4xx_mal_reset(mal);
    614        }
    615        mal->cfg = val & 0x00FFC087;
    616        break;
    617    case MAL0_ESR:
    618        /* Read/clear */
    619        mal->esr &= ~val;
    620        break;
    621    case MAL0_IER:
    622        mal->ier = val & 0x0000001F;
    623        break;
    624    case MAL0_TXCASR:
    625        mal->txcasr = val & 0xF0000000;
    626        break;
    627    case MAL0_TXCARR:
    628        mal->txcarr = val & 0xF0000000;
    629        break;
    630    case MAL0_TXEOBISR:
    631        /* Read/clear */
    632        mal->txeobisr &= ~val;
    633        break;
    634    case MAL0_TXDEIR:
    635        /* Read/clear */
    636        mal->txdeir &= ~val;
    637        break;
    638    case MAL0_RXCASR:
    639        mal->rxcasr = val & 0xC0000000;
    640        break;
    641    case MAL0_RXCARR:
    642        mal->rxcarr = val & 0xC0000000;
    643        break;
    644    case MAL0_RXEOBISR:
    645        /* Read/clear */
    646        mal->rxeobisr &= ~val;
    647        break;
    648    case MAL0_RXDEIR:
    649        /* Read/clear */
    650        mal->rxdeir &= ~val;
    651        break;
    652    }
    653    if (dcrn >= MAL0_TXCTP0R && dcrn < MAL0_TXCTP0R + mal->txcnum) {
    654        mal->txctpr[dcrn - MAL0_TXCTP0R] = val;
    655    }
    656    if (dcrn >= MAL0_RXCTP0R && dcrn < MAL0_RXCTP0R + mal->rxcnum) {
    657        mal->rxctpr[dcrn - MAL0_RXCTP0R] = val;
    658    }
    659    if (dcrn >= MAL0_RCBS0 && dcrn < MAL0_RCBS0 + mal->rxcnum) {
    660        mal->rcbs[dcrn - MAL0_RCBS0] = val & 0x000000FF;
    661    }
    662}
    663
    664void ppc4xx_mal_init(CPUPPCState *env, uint8_t txcnum, uint8_t rxcnum,
    665                     qemu_irq irqs[4])
    666{
    667    ppc4xx_mal_t *mal;
    668    int i;
    669
    670    assert(txcnum <= 32 && rxcnum <= 32);
    671    mal = g_malloc0(sizeof(*mal));
    672    mal->txcnum = txcnum;
    673    mal->rxcnum = rxcnum;
    674    mal->txctpr = g_new0(uint32_t, txcnum);
    675    mal->rxctpr = g_new0(uint32_t, rxcnum);
    676    mal->rcbs = g_new0(uint32_t, rxcnum);
    677    for (i = 0; i < 4; i++) {
    678        mal->irqs[i] = irqs[i];
    679    }
    680    qemu_register_reset(&ppc4xx_mal_reset, mal);
    681    ppc_dcr_register(env, MAL0_CFG,
    682                     mal, &dcr_read_mal, &dcr_write_mal);
    683    ppc_dcr_register(env, MAL0_ESR,
    684                     mal, &dcr_read_mal, &dcr_write_mal);
    685    ppc_dcr_register(env, MAL0_IER,
    686                     mal, &dcr_read_mal, &dcr_write_mal);
    687    ppc_dcr_register(env, MAL0_TXCASR,
    688                     mal, &dcr_read_mal, &dcr_write_mal);
    689    ppc_dcr_register(env, MAL0_TXCARR,
    690                     mal, &dcr_read_mal, &dcr_write_mal);
    691    ppc_dcr_register(env, MAL0_TXEOBISR,
    692                     mal, &dcr_read_mal, &dcr_write_mal);
    693    ppc_dcr_register(env, MAL0_TXDEIR,
    694                     mal, &dcr_read_mal, &dcr_write_mal);
    695    ppc_dcr_register(env, MAL0_RXCASR,
    696                     mal, &dcr_read_mal, &dcr_write_mal);
    697    ppc_dcr_register(env, MAL0_RXCARR,
    698                     mal, &dcr_read_mal, &dcr_write_mal);
    699    ppc_dcr_register(env, MAL0_RXEOBISR,
    700                     mal, &dcr_read_mal, &dcr_write_mal);
    701    ppc_dcr_register(env, MAL0_RXDEIR,
    702                     mal, &dcr_read_mal, &dcr_write_mal);
    703    for (i = 0; i < txcnum; i++) {
    704        ppc_dcr_register(env, MAL0_TXCTP0R + i,
    705                         mal, &dcr_read_mal, &dcr_write_mal);
    706    }
    707    for (i = 0; i < rxcnum; i++) {
    708        ppc_dcr_register(env, MAL0_RXCTP0R + i,
    709                         mal, &dcr_read_mal, &dcr_write_mal);
    710    }
    711    for (i = 0; i < rxcnum; i++) {
    712        ppc_dcr_register(env, MAL0_RCBS0 + i,
    713                         mal, &dcr_read_mal, &dcr_write_mal);
    714    }
    715}