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