xref: /qemu/hw/ppc/ppc4xx_devs.c (revision d0fb9657)
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 
47 static 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 */
56 PowerPCCPU *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 */
81 typedef struct ppc4xx_sdram_t ppc4xx_sdram_t;
82 struct 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 
103 enum {
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  */
112 static 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 
150 static inline hwaddr sdram_base(uint32_t bcr)
151 {
152     return bcr & 0xFF800000;
153 }
154 
155 static 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 
169 static 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 
200 static 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 
214 static 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 
228 static 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 
296 static 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 
381 static 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 
401 void 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  */
438 void 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 
493 enum {
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 
511 typedef struct ppc4xx_mal_t ppc4xx_mal_t;
512 struct 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 
532 static 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 
548 static 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 
605 static 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 
664 void 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 }
716