Commit 008ff9d756fb8e33e7a799e47d03faac503f8b2e

Authored by j_mayer
1 parent 115646b6

Share devices that might be useful for all PowerPC 40x & 440 implementations

(mostly CPU registration and UIC, for now).


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3340 c046a42c-6fe2-441c-8c8c-71466251a162
hw/ppc405.h
... ... @@ -25,6 +25,8 @@
25 25 #if !defined(PPC_405_H)
26 26 #define PPC_405_H
27 27  
  28 +#include "ppc4xx.h"
  29 +
28 30 /* Bootinfo as set-up by u-boot */
29 31 typedef struct ppc4xx_bd_info_t ppc4xx_bd_info_t;
30 32 struct ppc4xx_bd_info_t {
... ... @@ -54,19 +56,9 @@ struct ppc4xx_bd_info_t {
54 56 };
55 57  
56 58 /* PowerPC 405 core */
57   -CPUState *ppc405_init (const unsigned char *cpu_model,
58   - clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
59   - uint32_t sysclk);
60 59 ram_addr_t ppc405_set_bootinfo (CPUState *env, ppc4xx_bd_info_t *bd,
61 60 uint32_t flags);
62 61  
63   -/* */
64   -typedef struct ppc4xx_mmio_t ppc4xx_mmio_t;
65   -int ppc4xx_mmio_register (CPUState *env, ppc4xx_mmio_t *mmio,
66   - target_phys_addr_t offset, uint32_t len,
67   - CPUReadMemoryFunc **mem_read,
68   - CPUWriteMemoryFunc **mem_write, void *opaque);
69   -ppc4xx_mmio_t *ppc4xx_mmio_init (CPUState *env, target_phys_addr_t base);
70 62 /* PowerPC 4xx peripheral local bus arbitrer */
71 63 void ppc4xx_plb_init (CPUState *env);
72 64 /* PLB to OPB bridge */
... ... @@ -74,14 +66,6 @@ void ppc4xx_pob_init (CPUState *env);
74 66 /* OPB arbitrer */
75 67 void ppc4xx_opba_init (CPUState *env, ppc4xx_mmio_t *mmio,
76 68 target_phys_addr_t offset);
77   -/* PowerPC 4xx universal interrupt controller */
78   -enum {
79   - PPCUIC_OUTPUT_INT = 0,
80   - PPCUIC_OUTPUT_CINT = 1,
81   - PPCUIC_OUTPUT_NB,
82   -};
83   -qemu_irq *ppcuic_init (CPUState *env, qemu_irq *irqs,
84   - uint32_t dcr_base, int has_ssr, int has_vr);
85 69 /* SDRAM controller */
86 70 void ppc405_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
87 71 target_phys_addr_t *ram_bases,
... ...
hw/ppc405_uc.c
... ... @@ -27,7 +27,6 @@
27 27 extern int loglevel;
28 28 extern FILE *logfile;
29 29  
30   -//#define DEBUG_MMIO
31 30 #define DEBUG_OPBA
32 31 #define DEBUG_SDRAM
33 32 #define DEBUG_GPIO
... ... @@ -36,41 +35,9 @@ extern FILE *logfile;
36 35 //#define DEBUG_I2C
37 36 #define DEBUG_GPT
38 37 #define DEBUG_MAL
39   -#define DEBUG_UIC
40 38 #define DEBUG_CLOCKS
41 39 //#define DEBUG_UNASSIGNED
42 40  
43   -/*****************************************************************************/
44   -/* Generic PowerPC 405 processor instanciation */
45   -CPUState *ppc405_init (const unsigned char *cpu_model,
46   - clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
47   - uint32_t sysclk)
48   -{
49   - CPUState *env;
50   - ppc_def_t *def;
51   -
52   - /* init CPUs */
53   - env = cpu_init();
54   - ppc_find_by_name(cpu_model, &def);
55   - if (def == NULL) {
56   - cpu_abort(env, "Unable to find PowerPC %s CPU definition\n",
57   - cpu_model);
58   - }
59   - cpu_ppc_register(env, def);
60   - cpu_ppc_reset(env);
61   - cpu_clk->cb = NULL; /* We don't care about CPU clock frequency changes */
62   - cpu_clk->opaque = env;
63   - /* Set time-base frequency to sysclk */
64   - tb_clk->cb = ppc_emb_timers_init(env, sysclk);
65   - tb_clk->opaque = env;
66   - ppc_dcr_init(env, NULL, NULL);
67   - /* Register Qemu callbacks */
68   - qemu_register_reset(&cpu_ppc_reset, env);
69   - register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
70   -
71   - return env;
72   -}
73   -
74 41 ram_addr_t ppc405_set_bootinfo (CPUState *env, ppc4xx_bd_info_t *bd,
75 42 uint32_t flags)
76 43 {
... ... @@ -124,203 +91,6 @@ ram_addr_t ppc405_set_bootinfo (CPUState *env, ppc4xx_bd_info_t *bd,
124 91 /* Shared peripherals */
125 92  
126 93 /*****************************************************************************/
127   -/* Fake device used to map multiple devices in a single memory page */
128   -#define MMIO_AREA_BITS 8
129   -#define MMIO_AREA_LEN (1 << MMIO_AREA_BITS)
130   -#define MMIO_AREA_NB (1 << (TARGET_PAGE_BITS - MMIO_AREA_BITS))
131   -#define MMIO_IDX(addr) (((addr) >> MMIO_AREA_BITS) & (MMIO_AREA_NB - 1))
132   -struct ppc4xx_mmio_t {
133   - target_phys_addr_t base;
134   - CPUReadMemoryFunc **mem_read[MMIO_AREA_NB];
135   - CPUWriteMemoryFunc **mem_write[MMIO_AREA_NB];
136   - void *opaque[MMIO_AREA_NB];
137   -};
138   -
139   -static uint32_t unassigned_mmio_readb (void *opaque, target_phys_addr_t addr)
140   -{
141   -#ifdef DEBUG_UNASSIGNED
142   - ppc4xx_mmio_t *mmio;
143   -
144   - mmio = opaque;
145   - printf("Unassigned mmio read 0x" PADDRX " base " PADDRX "\n",
146   - addr, mmio->base);
147   -#endif
148   -
149   - return 0;
150   -}
151   -
152   -static void unassigned_mmio_writeb (void *opaque,
153   - target_phys_addr_t addr, uint32_t val)
154   -{
155   -#ifdef DEBUG_UNASSIGNED
156   - ppc4xx_mmio_t *mmio;
157   -
158   - mmio = opaque;
159   - printf("Unassigned mmio write 0x" PADDRX " = 0x%x base " PADDRX "\n",
160   - addr, val, mmio->base);
161   -#endif
162   -}
163   -
164   -static CPUReadMemoryFunc *unassigned_mmio_read[3] = {
165   - unassigned_mmio_readb,
166   - unassigned_mmio_readb,
167   - unassigned_mmio_readb,
168   -};
169   -
170   -static CPUWriteMemoryFunc *unassigned_mmio_write[3] = {
171   - unassigned_mmio_writeb,
172   - unassigned_mmio_writeb,
173   - unassigned_mmio_writeb,
174   -};
175   -
176   -static uint32_t mmio_readlen (ppc4xx_mmio_t *mmio,
177   - target_phys_addr_t addr, int len)
178   -{
179   - CPUReadMemoryFunc **mem_read;
180   - uint32_t ret;
181   - int idx;
182   -
183   - idx = MMIO_IDX(addr - mmio->base);
184   -#if defined(DEBUG_MMIO)
185   - printf("%s: mmio %p len %d addr " PADDRX " idx %d\n", __func__,
186   - mmio, len, addr, idx);
187   -#endif
188   - mem_read = mmio->mem_read[idx];
189   - ret = (*mem_read[len])(mmio->opaque[idx], addr - mmio->base);
190   -
191   - return ret;
192   -}
193   -
194   -static void mmio_writelen (ppc4xx_mmio_t *mmio,
195   - target_phys_addr_t addr, uint32_t value, int len)
196   -{
197   - CPUWriteMemoryFunc **mem_write;
198   - int idx;
199   -
200   - idx = MMIO_IDX(addr - mmio->base);
201   -#if defined(DEBUG_MMIO)
202   - printf("%s: mmio %p len %d addr " PADDRX " idx %d value %08x\n", __func__,
203   - mmio, len, addr, idx, value);
204   -#endif
205   - mem_write = mmio->mem_write[idx];
206   - (*mem_write[len])(mmio->opaque[idx], addr - mmio->base, value);
207   -}
208   -
209   -static uint32_t mmio_readb (void *opaque, target_phys_addr_t addr)
210   -{
211   -#if defined(DEBUG_MMIO)
212   - printf("%s: addr " PADDRX "\n", __func__, addr);
213   -#endif
214   -
215   - return mmio_readlen(opaque, addr, 0);
216   -}
217   -
218   -static void mmio_writeb (void *opaque,
219   - target_phys_addr_t addr, uint32_t value)
220   -{
221   -#if defined(DEBUG_MMIO)
222   - printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
223   -#endif
224   - mmio_writelen(opaque, addr, value, 0);
225   -}
226   -
227   -static uint32_t mmio_readw (void *opaque, target_phys_addr_t addr)
228   -{
229   -#if defined(DEBUG_MMIO)
230   - printf("%s: addr " PADDRX "\n", __func__, addr);
231   -#endif
232   -
233   - return mmio_readlen(opaque, addr, 1);
234   -}
235   -
236   -static void mmio_writew (void *opaque,
237   - target_phys_addr_t addr, uint32_t value)
238   -{
239   -#if defined(DEBUG_MMIO)
240   - printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
241   -#endif
242   - mmio_writelen(opaque, addr, value, 1);
243   -}
244   -
245   -static uint32_t mmio_readl (void *opaque, target_phys_addr_t addr)
246   -{
247   -#if defined(DEBUG_MMIO)
248   - printf("%s: addr " PADDRX "\n", __func__, addr);
249   -#endif
250   -
251   - return mmio_readlen(opaque, addr, 2);
252   -}
253   -
254   -static void mmio_writel (void *opaque,
255   - target_phys_addr_t addr, uint32_t value)
256   -{
257   -#if defined(DEBUG_MMIO)
258   - printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
259   -#endif
260   - mmio_writelen(opaque, addr, value, 2);
261   -}
262   -
263   -static CPUReadMemoryFunc *mmio_read[] = {
264   - &mmio_readb,
265   - &mmio_readw,
266   - &mmio_readl,
267   -};
268   -
269   -static CPUWriteMemoryFunc *mmio_write[] = {
270   - &mmio_writeb,
271   - &mmio_writew,
272   - &mmio_writel,
273   -};
274   -
275   -int ppc4xx_mmio_register (CPUState *env, ppc4xx_mmio_t *mmio,
276   - target_phys_addr_t offset, uint32_t len,
277   - CPUReadMemoryFunc **mem_read,
278   - CPUWriteMemoryFunc **mem_write, void *opaque)
279   -{
280   - uint32_t end;
281   - int idx, eidx;
282   -
283   - if ((offset + len) > TARGET_PAGE_SIZE)
284   - return -1;
285   - idx = MMIO_IDX(offset);
286   - end = offset + len - 1;
287   - eidx = MMIO_IDX(end);
288   -#if defined(DEBUG_MMIO)
289   - printf("%s: offset %08x len %08x %08x %d %d\n", __func__, offset, len,
290   - end, idx, eidx);
291   -#endif
292   - for (; idx <= eidx; idx++) {
293   - mmio->mem_read[idx] = mem_read;
294   - mmio->mem_write[idx] = mem_write;
295   - mmio->opaque[idx] = opaque;
296   - }
297   -
298   - return 0;
299   -}
300   -
301   -ppc4xx_mmio_t *ppc4xx_mmio_init (CPUState *env, target_phys_addr_t base)
302   -{
303   - ppc4xx_mmio_t *mmio;
304   - int mmio_memory;
305   -
306   - mmio = qemu_mallocz(sizeof(ppc4xx_mmio_t));
307   - if (mmio != NULL) {
308   - mmio->base = base;
309   - mmio_memory = cpu_register_io_memory(0, mmio_read, mmio_write, mmio);
310   -#if defined(DEBUG_MMIO)
311   - printf("%s: %p base %08x len %08x %d\n", __func__,
312   - mmio, base, TARGET_PAGE_SIZE, mmio_memory);
313   -#endif
314   - cpu_register_physical_memory(base, TARGET_PAGE_SIZE, mmio_memory);
315   - ppc4xx_mmio_register(env, mmio, 0, TARGET_PAGE_SIZE,
316   - unassigned_mmio_read, unassigned_mmio_write,
317   - mmio);
318   - }
319   -
320   - return mmio;
321   -}
322   -
323   -/*****************************************************************************/
324 94 /* Peripheral local bus arbitrer */
325 95 enum {
326 96 PLB0_BESR = 0x084,
... ... @@ -625,281 +395,6 @@ void ppc4xx_opba_init (CPUState *env, ppc4xx_mmio_t *mmio,
625 395 }
626 396  
627 397 /*****************************************************************************/
628   -/* "Universal" Interrupt controller */
629   -enum {
630   - DCR_UICSR = 0x000,
631   - DCR_UICSRS = 0x001,
632   - DCR_UICER = 0x002,
633   - DCR_UICCR = 0x003,
634   - DCR_UICPR = 0x004,
635   - DCR_UICTR = 0x005,
636   - DCR_UICMSR = 0x006,
637   - DCR_UICVR = 0x007,
638   - DCR_UICVCR = 0x008,
639   - DCR_UICMAX = 0x009,
640   -};
641   -
642   -#define UIC_MAX_IRQ 32
643   -typedef struct ppcuic_t ppcuic_t;
644   -struct ppcuic_t {
645   - uint32_t dcr_base;
646   - int use_vectors;
647   - uint32_t uicsr; /* Status register */
648   - uint32_t uicer; /* Enable register */
649   - uint32_t uiccr; /* Critical register */
650   - uint32_t uicpr; /* Polarity register */
651   - uint32_t uictr; /* Triggering register */
652   - uint32_t uicvcr; /* Vector configuration register */
653   - uint32_t uicvr;
654   - qemu_irq *irqs;
655   -};
656   -
657   -static void ppcuic_trigger_irq (ppcuic_t *uic)
658   -{
659   - uint32_t ir, cr;
660   - int start, end, inc, i;
661   -
662   - /* Trigger interrupt if any is pending */
663   - ir = uic->uicsr & uic->uicer & (~uic->uiccr);
664   - cr = uic->uicsr & uic->uicer & uic->uiccr;
665   -#ifdef DEBUG_UIC
666   - if (loglevel & CPU_LOG_INT) {
667   - fprintf(logfile, "%s: uicsr %08x uicer %08x uiccr %08x\n"
668   - " %08x ir %08x cr %08x\n", __func__,
669   - uic->uicsr, uic->uicer, uic->uiccr,
670   - uic->uicsr & uic->uicer, ir, cr);
671   - }
672   -#endif
673   - if (ir != 0x0000000) {
674   -#ifdef DEBUG_UIC
675   - if (loglevel & CPU_LOG_INT) {
676   - fprintf(logfile, "Raise UIC interrupt\n");
677   - }
678   -#endif
679   - qemu_irq_raise(uic->irqs[PPCUIC_OUTPUT_INT]);
680   - } else {
681   -#ifdef DEBUG_UIC
682   - if (loglevel & CPU_LOG_INT) {
683   - fprintf(logfile, "Lower UIC interrupt\n");
684   - }
685   -#endif
686   - qemu_irq_lower(uic->irqs[PPCUIC_OUTPUT_INT]);
687   - }
688   - /* Trigger critical interrupt if any is pending and update vector */
689   - if (cr != 0x0000000) {
690   - qemu_irq_raise(uic->irqs[PPCUIC_OUTPUT_CINT]);
691   - if (uic->use_vectors) {
692   - /* Compute critical IRQ vector */
693   - if (uic->uicvcr & 1) {
694   - start = 31;
695   - end = 0;
696   - inc = -1;
697   - } else {
698   - start = 0;
699   - end = 31;
700   - inc = 1;
701   - }
702   - uic->uicvr = uic->uicvcr & 0xFFFFFFFC;
703   - for (i = start; i <= end; i += inc) {
704   - if (cr & (1 << i)) {
705   - uic->uicvr += (i - start) * 512 * inc;
706   - break;
707   - }
708   - }
709   - }
710   -#ifdef DEBUG_UIC
711   - if (loglevel & CPU_LOG_INT) {
712   - fprintf(logfile, "Raise UIC critical interrupt - vector %08x\n",
713   - uic->uicvr);
714   - }
715   -#endif
716   - } else {
717   -#ifdef DEBUG_UIC
718   - if (loglevel & CPU_LOG_INT) {
719   - fprintf(logfile, "Lower UIC critical interrupt\n");
720   - }
721   -#endif
722   - qemu_irq_lower(uic->irqs[PPCUIC_OUTPUT_CINT]);
723   - uic->uicvr = 0x00000000;
724   - }
725   -}
726   -
727   -static void ppcuic_set_irq (void *opaque, int irq_num, int level)
728   -{
729   - ppcuic_t *uic;
730   - uint32_t mask, sr;
731   -
732   - uic = opaque;
733   - mask = 1 << irq_num;
734   -#ifdef DEBUG_UIC
735   - if (loglevel & CPU_LOG_INT) {
736   - fprintf(logfile, "%s: irq %d level %d uicsr %08x mask %08x => %08x "
737   - "%08x\n", __func__, irq_num, level,
738   - uic->uicsr, mask, uic->uicsr & mask, level << irq_num);
739   - }
740   -#endif
741   - if (irq_num < 0 || irq_num > 31)
742   - return;
743   - sr = uic->uicsr;
744   - if (!(uic->uicpr & mask)) {
745   - /* Negatively asserted IRQ */
746   - level = level == 0 ? 1 : 0;
747   - }
748   - /* Update status register */
749   - if (uic->uictr & mask) {
750   - /* Edge sensitive interrupt */
751   - if (level == 1)
752   - uic->uicsr |= mask;
753   - } else {
754   - /* Level sensitive interrupt */
755   - if (level == 1)
756   - uic->uicsr |= mask;
757   - else
758   - uic->uicsr &= ~mask;
759   - }
760   -#ifdef DEBUG_UIC
761   - if (loglevel & CPU_LOG_INT) {
762   - fprintf(logfile, "%s: irq %d level %d sr %08x => %08x\n", __func__,
763   - irq_num, level, uic->uicsr, sr);
764   - }
765   -#endif
766   - if (sr != uic->uicsr)
767   - ppcuic_trigger_irq(uic);
768   -}
769   -
770   -static target_ulong dcr_read_uic (void *opaque, int dcrn)
771   -{
772   - ppcuic_t *uic;
773   - target_ulong ret;
774   -
775   - uic = opaque;
776   - dcrn -= uic->dcr_base;
777   - switch (dcrn) {
778   - case DCR_UICSR:
779   - case DCR_UICSRS:
780   - ret = uic->uicsr;
781   - break;
782   - case DCR_UICER:
783   - ret = uic->uicer;
784   - break;
785   - case DCR_UICCR:
786   - ret = uic->uiccr;
787   - break;
788   - case DCR_UICPR:
789   - ret = uic->uicpr;
790   - break;
791   - case DCR_UICTR:
792   - ret = uic->uictr;
793   - break;
794   - case DCR_UICMSR:
795   - ret = uic->uicsr & uic->uicer;
796   - break;
797   - case DCR_UICVR:
798   - if (!uic->use_vectors)
799   - goto no_read;
800   - ret = uic->uicvr;
801   - break;
802   - case DCR_UICVCR:
803   - if (!uic->use_vectors)
804   - goto no_read;
805   - ret = uic->uicvcr;
806   - break;
807   - default:
808   - no_read:
809   - ret = 0x00000000;
810   - break;
811   - }
812   -
813   - return ret;
814   -}
815   -
816   -static void dcr_write_uic (void *opaque, int dcrn, target_ulong val)
817   -{
818   - ppcuic_t *uic;
819   -
820   - uic = opaque;
821   - dcrn -= uic->dcr_base;
822   -#ifdef DEBUG_UIC
823   - if (loglevel & CPU_LOG_INT) {
824   - fprintf(logfile, "%s: dcr %d val " ADDRX "\n", __func__, dcrn, val);
825   - }
826   -#endif
827   - switch (dcrn) {
828   - case DCR_UICSR:
829   - uic->uicsr &= ~val;
830   - ppcuic_trigger_irq(uic);
831   - break;
832   - case DCR_UICSRS:
833   - uic->uicsr |= val;
834   - ppcuic_trigger_irq(uic);
835   - break;
836   - case DCR_UICER:
837   - uic->uicer = val;
838   - ppcuic_trigger_irq(uic);
839   - break;
840   - case DCR_UICCR:
841   - uic->uiccr = val;
842   - ppcuic_trigger_irq(uic);
843   - break;
844   - case DCR_UICPR:
845   - uic->uicpr = val;
846   - ppcuic_trigger_irq(uic);
847   - break;
848   - case DCR_UICTR:
849   - uic->uictr = val;
850   - ppcuic_trigger_irq(uic);
851   - break;
852   - case DCR_UICMSR:
853   - break;
854   - case DCR_UICVR:
855   - break;
856   - case DCR_UICVCR:
857   - uic->uicvcr = val & 0xFFFFFFFD;
858   - ppcuic_trigger_irq(uic);
859   - break;
860   - }
861   -}
862   -
863   -static void ppcuic_reset (void *opaque)
864   -{
865   - ppcuic_t *uic;
866   -
867   - uic = opaque;
868   - uic->uiccr = 0x00000000;
869   - uic->uicer = 0x00000000;
870   - uic->uicpr = 0x00000000;
871   - uic->uicsr = 0x00000000;
872   - uic->uictr = 0x00000000;
873   - if (uic->use_vectors) {
874   - uic->uicvcr = 0x00000000;
875   - uic->uicvr = 0x0000000;
876   - }
877   -}
878   -
879   -qemu_irq *ppcuic_init (CPUState *env, qemu_irq *irqs,
880   - uint32_t dcr_base, int has_ssr, int has_vr)
881   -{
882   - ppcuic_t *uic;
883   - int i;
884   -
885   - uic = qemu_mallocz(sizeof(ppcuic_t));
886   - if (uic != NULL) {
887   - uic->dcr_base = dcr_base;
888   - uic->irqs = irqs;
889   - if (has_vr)
890   - uic->use_vectors = 1;
891   - for (i = 0; i < DCR_UICMAX; i++) {
892   - ppc_dcr_register(env, dcr_base + i, uic,
893   - &dcr_read_uic, &dcr_write_uic);
894   - }
895   - qemu_register_reset(ppcuic_reset, uic);
896   - ppcuic_reset(uic);
897   - }
898   -
899   - return qemu_allocate_irqs(&ppcuic_set_irq, uic, UIC_MAX_IRQ);
900   -}
901   -
902   -/*****************************************************************************/
903 398 /* Code decompression controller */
904 399 /* XXX: TODO */
905 400  
... ... @@ -3040,7 +2535,7 @@ CPUState *ppc405cr_init (target_phys_addr_t ram_bases[4],
3040 2535 int i;
3041 2536  
3042 2537 memset(clk_setup, 0, sizeof(clk_setup));
3043   - env = ppc405_init("405cr", &clk_setup[PPC405CR_CPU_CLK],
  2538 + env = ppc4xx_init("405cr", &clk_setup[PPC405CR_CPU_CLK],
3044 2539 &clk_setup[PPC405CR_TMR_CLK], sysclk);
3045 2540 /* Memory mapped devices registers */
3046 2541 mmio = ppc4xx_mmio_init(env, 0xEF600000);
... ... @@ -3390,7 +2885,7 @@ CPUState *ppc405ep_init (target_phys_addr_t ram_bases[2],
3390 2885  
3391 2886 memset(clk_setup, 0, sizeof(clk_setup));
3392 2887 /* init CPUs */
3393   - env = ppc405_init("405ep", &clk_setup[PPC405EP_CPU_CLK],
  2888 + env = ppc4xx_init("405ep", &clk_setup[PPC405EP_CPU_CLK],
3394 2889 &tlb_clk_setup, sysclk);
3395 2890 clk_setup[PPC405EP_CPU_CLK].cb = tlb_clk_setup.cb;
3396 2891 clk_setup[PPC405EP_CPU_CLK].opaque = tlb_clk_setup.opaque;
... ...
hw/ppc4xx.h 0 โ†’ 100644
  1 +/*
  2 + * QEMU PowerPC 4xx emulation shared definitions
  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 +#if !defined(PPC_4XX_H)
  26 +#define PPC_4XX_H
  27 +
  28 +/* PowerPC 4xx core initialization */
  29 +CPUState *ppc4xx_init (const unsigned char *cpu_model,
  30 + clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
  31 + uint32_t sysclk);
  32 +
  33 +typedef struct ppc4xx_mmio_t ppc4xx_mmio_t;
  34 +int ppc4xx_mmio_register (CPUState *env, ppc4xx_mmio_t *mmio,
  35 + target_phys_addr_t offset, uint32_t len,
  36 + CPUReadMemoryFunc **mem_read,
  37 + CPUWriteMemoryFunc **mem_write, void *opaque);
  38 +ppc4xx_mmio_t *ppc4xx_mmio_init (CPUState *env, target_phys_addr_t base);
  39 +
  40 +/* PowerPC 4xx universal interrupt controller */
  41 +enum {
  42 + PPCUIC_OUTPUT_INT = 0,
  43 + PPCUIC_OUTPUT_CINT = 1,
  44 + PPCUIC_OUTPUT_NB,
  45 +};
  46 +qemu_irq *ppcuic_init (CPUState *env, qemu_irq *irqs,
  47 + uint32_t dcr_base, int has_ssr, int has_vr);
  48 +
  49 +#endif /* !defined(PPC_4XX_H) */
... ...
hw/ppc4xx_devs.c 0 โ†’ 100644
  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 +#include "vl.h"
  25 +#include "ppc4xx.h"
  26 +
  27 +extern int loglevel;
  28 +extern FILE *logfile;
  29 +
  30 +//#define DEBUG_MMIO
  31 +#define DEBUG_UIC
  32 +
  33 +/*****************************************************************************/
  34 +/* Generic PowerPC 4xx processor instanciation */
  35 +CPUState *ppc4xx_init (const unsigned char *cpu_model,
  36 + clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
  37 + uint32_t sysclk)
  38 +{
  39 + CPUState *env;
  40 + ppc_def_t *def;
  41 +
  42 + /* init CPUs */
  43 + env = cpu_init();
  44 + ppc_find_by_name(cpu_model, &def);
  45 + if (def == NULL) {
  46 + cpu_abort(env, "Unable to find PowerPC %s CPU definition\n",
  47 + cpu_model);
  48 + }
  49 + cpu_ppc_register(env, def);
  50 + cpu_ppc_reset(env);
  51 + cpu_clk->cb = NULL; /* We don't care about CPU clock frequency changes */
  52 + cpu_clk->opaque = env;
  53 + /* Set time-base frequency to sysclk */
  54 + tb_clk->cb = ppc_emb_timers_init(env, sysclk);
  55 + tb_clk->opaque = env;
  56 + ppc_dcr_init(env, NULL, NULL);
  57 + /* Register qemu callbacks */
  58 + qemu_register_reset(&cpu_ppc_reset, env);
  59 + register_savevm("cpu", 0, 3, cpu_save, cpu_load, env);
  60 +
  61 + return env;
  62 +}
  63 +
  64 +/*****************************************************************************/
  65 +/* Fake device used to map multiple devices in a single memory page */
  66 +#define MMIO_AREA_BITS 8
  67 +#define MMIO_AREA_LEN (1 << MMIO_AREA_BITS)
  68 +#define MMIO_AREA_NB (1 << (TARGET_PAGE_BITS - MMIO_AREA_BITS))
  69 +#define MMIO_IDX(addr) (((addr) >> MMIO_AREA_BITS) & (MMIO_AREA_NB - 1))
  70 +struct ppc4xx_mmio_t {
  71 + target_phys_addr_t base;
  72 + CPUReadMemoryFunc **mem_read[MMIO_AREA_NB];
  73 + CPUWriteMemoryFunc **mem_write[MMIO_AREA_NB];
  74 + void *opaque[MMIO_AREA_NB];
  75 +};
  76 +
  77 +static uint32_t unassigned_mmio_readb (void *opaque, target_phys_addr_t addr)
  78 +{
  79 +#ifdef DEBUG_UNASSIGNED
  80 + ppc4xx_mmio_t *mmio;
  81 +
  82 + mmio = opaque;
  83 + printf("Unassigned mmio read 0x" PADDRX " base " PADDRX "\n",
  84 + addr, mmio->base);
  85 +#endif
  86 +
  87 + return 0;
  88 +}
  89 +
  90 +static void unassigned_mmio_writeb (void *opaque,
  91 + target_phys_addr_t addr, uint32_t val)
  92 +{
  93 +#ifdef DEBUG_UNASSIGNED
  94 + ppc4xx_mmio_t *mmio;
  95 +
  96 + mmio = opaque;
  97 + printf("Unassigned mmio write 0x" PADDRX " = 0x%x base " PADDRX "\n",
  98 + addr, val, mmio->base);
  99 +#endif
  100 +}
  101 +
  102 +static CPUReadMemoryFunc *unassigned_mmio_read[3] = {
  103 + unassigned_mmio_readb,
  104 + unassigned_mmio_readb,
  105 + unassigned_mmio_readb,
  106 +};
  107 +
  108 +static CPUWriteMemoryFunc *unassigned_mmio_write[3] = {
  109 + unassigned_mmio_writeb,
  110 + unassigned_mmio_writeb,
  111 + unassigned_mmio_writeb,
  112 +};
  113 +
  114 +static uint32_t mmio_readlen (ppc4xx_mmio_t *mmio,
  115 + target_phys_addr_t addr, int len)
  116 +{
  117 + CPUReadMemoryFunc **mem_read;
  118 + uint32_t ret;
  119 + int idx;
  120 +
  121 + idx = MMIO_IDX(addr - mmio->base);
  122 +#if defined(DEBUG_MMIO)
  123 + printf("%s: mmio %p len %d addr " PADDRX " idx %d\n", __func__,
  124 + mmio, len, addr, idx);
  125 +#endif
  126 + mem_read = mmio->mem_read[idx];
  127 + ret = (*mem_read[len])(mmio->opaque[idx], addr - mmio->base);
  128 +
  129 + return ret;
  130 +}
  131 +
  132 +static void mmio_writelen (ppc4xx_mmio_t *mmio,
  133 + target_phys_addr_t addr, uint32_t value, int len)
  134 +{
  135 + CPUWriteMemoryFunc **mem_write;
  136 + int idx;
  137 +
  138 + idx = MMIO_IDX(addr - mmio->base);
  139 +#if defined(DEBUG_MMIO)
  140 + printf("%s: mmio %p len %d addr " PADDRX " idx %d value %08x\n", __func__,
  141 + mmio, len, addr, idx, value);
  142 +#endif
  143 + mem_write = mmio->mem_write[idx];
  144 + (*mem_write[len])(mmio->opaque[idx], addr - mmio->base, value);
  145 +}
  146 +
  147 +static uint32_t mmio_readb (void *opaque, target_phys_addr_t addr)
  148 +{
  149 +#if defined(DEBUG_MMIO)
  150 + printf("%s: addr " PADDRX "\n", __func__, addr);
  151 +#endif
  152 +
  153 + return mmio_readlen(opaque, addr, 0);
  154 +}
  155 +
  156 +static void mmio_writeb (void *opaque,
  157 + target_phys_addr_t addr, uint32_t value)
  158 +{
  159 +#if defined(DEBUG_MMIO)
  160 + printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
  161 +#endif
  162 + mmio_writelen(opaque, addr, value, 0);
  163 +}
  164 +
  165 +static uint32_t mmio_readw (void *opaque, target_phys_addr_t addr)
  166 +{
  167 +#if defined(DEBUG_MMIO)
  168 + printf("%s: addr " PADDRX "\n", __func__, addr);
  169 +#endif
  170 +
  171 + return mmio_readlen(opaque, addr, 1);
  172 +}
  173 +
  174 +static void mmio_writew (void *opaque,
  175 + target_phys_addr_t addr, uint32_t value)
  176 +{
  177 +#if defined(DEBUG_MMIO)
  178 + printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
  179 +#endif
  180 + mmio_writelen(opaque, addr, value, 1);
  181 +}
  182 +
  183 +static uint32_t mmio_readl (void *opaque, target_phys_addr_t addr)
  184 +{
  185 +#if defined(DEBUG_MMIO)
  186 + printf("%s: addr " PADDRX "\n", __func__, addr);
  187 +#endif
  188 +
  189 + return mmio_readlen(opaque, addr, 2);
  190 +}
  191 +
  192 +static void mmio_writel (void *opaque,
  193 + target_phys_addr_t addr, uint32_t value)
  194 +{
  195 +#if defined(DEBUG_MMIO)
  196 + printf("%s: addr " PADDRX " val %08x\n", __func__, addr, value);
  197 +#endif
  198 + mmio_writelen(opaque, addr, value, 2);
  199 +}
  200 +
  201 +static CPUReadMemoryFunc *mmio_read[] = {
  202 + &mmio_readb,
  203 + &mmio_readw,
  204 + &mmio_readl,
  205 +};
  206 +
  207 +static CPUWriteMemoryFunc *mmio_write[] = {
  208 + &mmio_writeb,
  209 + &mmio_writew,
  210 + &mmio_writel,
  211 +};
  212 +
  213 +int ppc4xx_mmio_register (CPUState *env, ppc4xx_mmio_t *mmio,
  214 + target_phys_addr_t offset, uint32_t len,
  215 + CPUReadMemoryFunc **mem_read,
  216 + CPUWriteMemoryFunc **mem_write, void *opaque)
  217 +{
  218 + uint32_t end;
  219 + int idx, eidx;
  220 +
  221 + if ((offset + len) > TARGET_PAGE_SIZE)
  222 + return -1;
  223 + idx = MMIO_IDX(offset);
  224 + end = offset + len - 1;
  225 + eidx = MMIO_IDX(end);
  226 +#if defined(DEBUG_MMIO)
  227 + printf("%s: offset %08x len %08x %08x %d %d\n", __func__, offset, len,
  228 + end, idx, eidx);
  229 +#endif
  230 + for (; idx <= eidx; idx++) {
  231 + mmio->mem_read[idx] = mem_read;
  232 + mmio->mem_write[idx] = mem_write;
  233 + mmio->opaque[idx] = opaque;
  234 + }
  235 +
  236 + return 0;
  237 +}
  238 +
  239 +ppc4xx_mmio_t *ppc4xx_mmio_init (CPUState *env, target_phys_addr_t base)
  240 +{
  241 + ppc4xx_mmio_t *mmio;
  242 + int mmio_memory;
  243 +
  244 + mmio = qemu_mallocz(sizeof(ppc4xx_mmio_t));
  245 + if (mmio != NULL) {
  246 + mmio->base = base;
  247 + mmio_memory = cpu_register_io_memory(0, mmio_read, mmio_write, mmio);
  248 +#if defined(DEBUG_MMIO)
  249 + printf("%s: %p base %08x len %08x %d\n", __func__,
  250 + mmio, base, TARGET_PAGE_SIZE, mmio_memory);
  251 +#endif
  252 + cpu_register_physical_memory(base, TARGET_PAGE_SIZE, mmio_memory);
  253 + ppc4xx_mmio_register(env, mmio, 0, TARGET_PAGE_SIZE,
  254 + unassigned_mmio_read, unassigned_mmio_write,
  255 + mmio);
  256 + }
  257 +
  258 + return mmio;
  259 +}
  260 +
  261 +/*****************************************************************************/
  262 +/* "Universal" Interrupt controller */
  263 +enum {
  264 + DCR_UICSR = 0x000,
  265 + DCR_UICSRS = 0x001,
  266 + DCR_UICER = 0x002,
  267 + DCR_UICCR = 0x003,
  268 + DCR_UICPR = 0x004,
  269 + DCR_UICTR = 0x005,
  270 + DCR_UICMSR = 0x006,
  271 + DCR_UICVR = 0x007,
  272 + DCR_UICVCR = 0x008,
  273 + DCR_UICMAX = 0x009,
  274 +};
  275 +
  276 +#define UIC_MAX_IRQ 32
  277 +typedef struct ppcuic_t ppcuic_t;
  278 +struct ppcuic_t {
  279 + uint32_t dcr_base;
  280 + int use_vectors;
  281 + uint32_t uicsr; /* Status register */
  282 + uint32_t uicer; /* Enable register */
  283 + uint32_t uiccr; /* Critical register */
  284 + uint32_t uicpr; /* Polarity register */
  285 + uint32_t uictr; /* Triggering register */
  286 + uint32_t uicvcr; /* Vector configuration register */
  287 + uint32_t uicvr;
  288 + qemu_irq *irqs;
  289 +};
  290 +
  291 +static void ppcuic_trigger_irq (ppcuic_t *uic)
  292 +{
  293 + uint32_t ir, cr;
  294 + int start, end, inc, i;
  295 +
  296 + /* Trigger interrupt if any is pending */
  297 + ir = uic->uicsr & uic->uicer & (~uic->uiccr);
  298 + cr = uic->uicsr & uic->uicer & uic->uiccr;
  299 +#ifdef DEBUG_UIC
  300 + if (loglevel & CPU_LOG_INT) {
  301 + fprintf(logfile, "%s: uicsr %08x uicer %08x uiccr %08x\n"
  302 + " %08x ir %08x cr %08x\n", __func__,
  303 + uic->uicsr, uic->uicer, uic->uiccr,
  304 + uic->uicsr & uic->uicer, ir, cr);
  305 + }
  306 +#endif
  307 + if (ir != 0x0000000) {
  308 +#ifdef DEBUG_UIC
  309 + if (loglevel & CPU_LOG_INT) {
  310 + fprintf(logfile, "Raise UIC interrupt\n");
  311 + }
  312 +#endif
  313 + qemu_irq_raise(uic->irqs[PPCUIC_OUTPUT_INT]);
  314 + } else {
  315 +#ifdef DEBUG_UIC
  316 + if (loglevel & CPU_LOG_INT) {
  317 + fprintf(logfile, "Lower UIC interrupt\n");
  318 + }
  319 +#endif
  320 + qemu_irq_lower(uic->irqs[PPCUIC_OUTPUT_INT]);
  321 + }
  322 + /* Trigger critical interrupt if any is pending and update vector */
  323 + if (cr != 0x0000000) {
  324 + qemu_irq_raise(uic->irqs[PPCUIC_OUTPUT_CINT]);
  325 + if (uic->use_vectors) {
  326 + /* Compute critical IRQ vector */
  327 + if (uic->uicvcr & 1) {
  328 + start = 31;
  329 + end = 0;
  330 + inc = -1;
  331 + } else {
  332 + start = 0;
  333 + end = 31;
  334 + inc = 1;
  335 + }
  336 + uic->uicvr = uic->uicvcr & 0xFFFFFFFC;
  337 + for (i = start; i <= end; i += inc) {
  338 + if (cr & (1 << i)) {
  339 + uic->uicvr += (i - start) * 512 * inc;
  340 + break;
  341 + }
  342 + }
  343 + }
  344 +#ifdef DEBUG_UIC
  345 + if (loglevel & CPU_LOG_INT) {
  346 + fprintf(logfile, "Raise UIC critical interrupt - vector %08x\n",
  347 + uic->uicvr);
  348 + }
  349 +#endif
  350 + } else {
  351 +#ifdef DEBUG_UIC
  352 + if (loglevel & CPU_LOG_INT) {
  353 + fprintf(logfile, "Lower UIC critical interrupt\n");
  354 + }
  355 +#endif
  356 + qemu_irq_lower(uic->irqs[PPCUIC_OUTPUT_CINT]);
  357 + uic->uicvr = 0x00000000;
  358 + }
  359 +}
  360 +
  361 +static void ppcuic_set_irq (void *opaque, int irq_num, int level)
  362 +{
  363 + ppcuic_t *uic;
  364 + uint32_t mask, sr;
  365 +
  366 + uic = opaque;
  367 + mask = 1 << irq_num;
  368 +#ifdef DEBUG_UIC
  369 + if (loglevel & CPU_LOG_INT) {
  370 + fprintf(logfile, "%s: irq %d level %d uicsr %08x mask %08x => %08x "
  371 + "%08x\n", __func__, irq_num, level,
  372 + uic->uicsr, mask, uic->uicsr & mask, level << irq_num);
  373 + }
  374 +#endif
  375 + if (irq_num < 0 || irq_num > 31)
  376 + return;
  377 + sr = uic->uicsr;
  378 + if (!(uic->uicpr & mask)) {
  379 + /* Negatively asserted IRQ */
  380 + level = level == 0 ? 1 : 0;
  381 + }
  382 + /* Update status register */
  383 + if (uic->uictr & mask) {
  384 + /* Edge sensitive interrupt */
  385 + if (level == 1)
  386 + uic->uicsr |= mask;
  387 + } else {
  388 + /* Level sensitive interrupt */
  389 + if (level == 1)
  390 + uic->uicsr |= mask;
  391 + else
  392 + uic->uicsr &= ~mask;
  393 + }
  394 +#ifdef DEBUG_UIC
  395 + if (loglevel & CPU_LOG_INT) {
  396 + fprintf(logfile, "%s: irq %d level %d sr %08x => %08x\n", __func__,
  397 + irq_num, level, uic->uicsr, sr);
  398 + }
  399 +#endif
  400 + if (sr != uic->uicsr)
  401 + ppcuic_trigger_irq(uic);
  402 +}
  403 +
  404 +static target_ulong dcr_read_uic (void *opaque, int dcrn)
  405 +{
  406 + ppcuic_t *uic;
  407 + target_ulong ret;
  408 +
  409 + uic = opaque;
  410 + dcrn -= uic->dcr_base;
  411 + switch (dcrn) {
  412 + case DCR_UICSR:
  413 + case DCR_UICSRS:
  414 + ret = uic->uicsr;
  415 + break;
  416 + case DCR_UICER:
  417 + ret = uic->uicer;
  418 + break;
  419 + case DCR_UICCR:
  420 + ret = uic->uiccr;
  421 + break;
  422 + case DCR_UICPR:
  423 + ret = uic->uicpr;
  424 + break;
  425 + case DCR_UICTR:
  426 + ret = uic->uictr;
  427 + break;
  428 + case DCR_UICMSR:
  429 + ret = uic->uicsr & uic->uicer;
  430 + break;
  431 + case DCR_UICVR:
  432 + if (!uic->use_vectors)
  433 + goto no_read;
  434 + ret = uic->uicvr;
  435 + break;
  436 + case DCR_UICVCR:
  437 + if (!uic->use_vectors)
  438 + goto no_read;
  439 + ret = uic->uicvcr;
  440 + break;
  441 + default:
  442 + no_read:
  443 + ret = 0x00000000;
  444 + break;
  445 + }
  446 +
  447 + return ret;
  448 +}
  449 +
  450 +static void dcr_write_uic (void *opaque, int dcrn, target_ulong val)
  451 +{
  452 + ppcuic_t *uic;
  453 +
  454 + uic = opaque;
  455 + dcrn -= uic->dcr_base;
  456 +#ifdef DEBUG_UIC
  457 + if (loglevel & CPU_LOG_INT) {
  458 + fprintf(logfile, "%s: dcr %d val " ADDRX "\n", __func__, dcrn, val);
  459 + }
  460 +#endif
  461 + switch (dcrn) {
  462 + case DCR_UICSR:
  463 + uic->uicsr &= ~val;
  464 + ppcuic_trigger_irq(uic);
  465 + break;
  466 + case DCR_UICSRS:
  467 + uic->uicsr |= val;
  468 + ppcuic_trigger_irq(uic);
  469 + break;
  470 + case DCR_UICER:
  471 + uic->uicer = val;
  472 + ppcuic_trigger_irq(uic);
  473 + break;
  474 + case DCR_UICCR:
  475 + uic->uiccr = val;
  476 + ppcuic_trigger_irq(uic);
  477 + break;
  478 + case DCR_UICPR:
  479 + uic->uicpr = val;
  480 + ppcuic_trigger_irq(uic);
  481 + break;
  482 + case DCR_UICTR:
  483 + uic->uictr = val;
  484 + ppcuic_trigger_irq(uic);
  485 + break;
  486 + case DCR_UICMSR:
  487 + break;
  488 + case DCR_UICVR:
  489 + break;
  490 + case DCR_UICVCR:
  491 + uic->uicvcr = val & 0xFFFFFFFD;
  492 + ppcuic_trigger_irq(uic);
  493 + break;
  494 + }
  495 +}
  496 +
  497 +static void ppcuic_reset (void *opaque)
  498 +{
  499 + ppcuic_t *uic;
  500 +
  501 + uic = opaque;
  502 + uic->uiccr = 0x00000000;
  503 + uic->uicer = 0x00000000;
  504 + uic->uicpr = 0x00000000;
  505 + uic->uicsr = 0x00000000;
  506 + uic->uictr = 0x00000000;
  507 + if (uic->use_vectors) {
  508 + uic->uicvcr = 0x00000000;
  509 + uic->uicvr = 0x0000000;
  510 + }
  511 +}
  512 +
  513 +qemu_irq *ppcuic_init (CPUState *env, qemu_irq *irqs,
  514 + uint32_t dcr_base, int has_ssr, int has_vr)
  515 +{
  516 + ppcuic_t *uic;
  517 + int i;
  518 +
  519 + uic = qemu_mallocz(sizeof(ppcuic_t));
  520 + if (uic != NULL) {
  521 + uic->dcr_base = dcr_base;
  522 + uic->irqs = irqs;
  523 + if (has_vr)
  524 + uic->use_vectors = 1;
  525 + for (i = 0; i < DCR_UICMAX; i++) {
  526 + ppc_dcr_register(env, dcr_base + i, uic,
  527 + &dcr_read_uic, &dcr_write_uic);
  528 + }
  529 + qemu_register_reset(ppcuic_reset, uic);
  530 + ppcuic_reset(uic);
  531 + }
  532 +
  533 + return qemu_allocate_irqs(&ppcuic_set_irq, uic, UIC_MAX_IRQ);
  534 +}
... ...