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,6 +25,8 @@
25 #if !defined(PPC_405_H) 25 #if !defined(PPC_405_H)
26 #define PPC_405_H 26 #define PPC_405_H
27 27
  28 +#include "ppc4xx.h"
  29 +
28 /* Bootinfo as set-up by u-boot */ 30 /* Bootinfo as set-up by u-boot */
29 typedef struct ppc4xx_bd_info_t ppc4xx_bd_info_t; 31 typedef struct ppc4xx_bd_info_t ppc4xx_bd_info_t;
30 struct ppc4xx_bd_info_t { 32 struct ppc4xx_bd_info_t {
@@ -54,19 +56,9 @@ struct ppc4xx_bd_info_t { @@ -54,19 +56,9 @@ struct ppc4xx_bd_info_t {
54 }; 56 };
55 57
56 /* PowerPC 405 core */ 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 ram_addr_t ppc405_set_bootinfo (CPUState *env, ppc4xx_bd_info_t *bd, 59 ram_addr_t ppc405_set_bootinfo (CPUState *env, ppc4xx_bd_info_t *bd,
61 uint32_t flags); 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 /* PowerPC 4xx peripheral local bus arbitrer */ 62 /* PowerPC 4xx peripheral local bus arbitrer */
71 void ppc4xx_plb_init (CPUState *env); 63 void ppc4xx_plb_init (CPUState *env);
72 /* PLB to OPB bridge */ 64 /* PLB to OPB bridge */
@@ -74,14 +66,6 @@ void ppc4xx_pob_init (CPUState *env); @@ -74,14 +66,6 @@ void ppc4xx_pob_init (CPUState *env);
74 /* OPB arbitrer */ 66 /* OPB arbitrer */
75 void ppc4xx_opba_init (CPUState *env, ppc4xx_mmio_t *mmio, 67 void ppc4xx_opba_init (CPUState *env, ppc4xx_mmio_t *mmio,
76 target_phys_addr_t offset); 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 /* SDRAM controller */ 69 /* SDRAM controller */
86 void ppc405_sdram_init (CPUState *env, qemu_irq irq, int nbanks, 70 void ppc405_sdram_init (CPUState *env, qemu_irq irq, int nbanks,
87 target_phys_addr_t *ram_bases, 71 target_phys_addr_t *ram_bases,
hw/ppc405_uc.c
@@ -27,7 +27,6 @@ @@ -27,7 +27,6 @@
27 extern int loglevel; 27 extern int loglevel;
28 extern FILE *logfile; 28 extern FILE *logfile;
29 29
30 -//#define DEBUG_MMIO  
31 #define DEBUG_OPBA 30 #define DEBUG_OPBA
32 #define DEBUG_SDRAM 31 #define DEBUG_SDRAM
33 #define DEBUG_GPIO 32 #define DEBUG_GPIO
@@ -36,41 +35,9 @@ extern FILE *logfile; @@ -36,41 +35,9 @@ extern FILE *logfile;
36 //#define DEBUG_I2C 35 //#define DEBUG_I2C
37 #define DEBUG_GPT 36 #define DEBUG_GPT
38 #define DEBUG_MAL 37 #define DEBUG_MAL
39 -#define DEBUG_UIC  
40 #define DEBUG_CLOCKS 38 #define DEBUG_CLOCKS
41 //#define DEBUG_UNASSIGNED 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 ram_addr_t ppc405_set_bootinfo (CPUState *env, ppc4xx_bd_info_t *bd, 41 ram_addr_t ppc405_set_bootinfo (CPUState *env, ppc4xx_bd_info_t *bd,
75 uint32_t flags) 42 uint32_t flags)
76 { 43 {
@@ -124,203 +91,6 @@ ram_addr_t ppc405_set_bootinfo (CPUState *env, ppc4xx_bd_info_t *bd, @@ -124,203 +91,6 @@ ram_addr_t ppc405_set_bootinfo (CPUState *env, ppc4xx_bd_info_t *bd,
124 /* Shared peripherals */ 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 /* Peripheral local bus arbitrer */ 94 /* Peripheral local bus arbitrer */
325 enum { 95 enum {
326 PLB0_BESR = 0x084, 96 PLB0_BESR = 0x084,
@@ -625,281 +395,6 @@ void ppc4xx_opba_init (CPUState *env, ppc4xx_mmio_t *mmio, @@ -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 /* Code decompression controller */ 398 /* Code decompression controller */
904 /* XXX: TODO */ 399 /* XXX: TODO */
905 400
@@ -3040,7 +2535,7 @@ CPUState *ppc405cr_init (target_phys_addr_t ram_bases[4], @@ -3040,7 +2535,7 @@ CPUState *ppc405cr_init (target_phys_addr_t ram_bases[4],
3040 int i; 2535 int i;
3041 2536
3042 memset(clk_setup, 0, sizeof(clk_setup)); 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 &clk_setup[PPC405CR_TMR_CLK], sysclk); 2539 &clk_setup[PPC405CR_TMR_CLK], sysclk);
3045 /* Memory mapped devices registers */ 2540 /* Memory mapped devices registers */
3046 mmio = ppc4xx_mmio_init(env, 0xEF600000); 2541 mmio = ppc4xx_mmio_init(env, 0xEF600000);
@@ -3390,7 +2885,7 @@ CPUState *ppc405ep_init (target_phys_addr_t ram_bases[2], @@ -3390,7 +2885,7 @@ CPUState *ppc405ep_init (target_phys_addr_t ram_bases[2],
3390 2885
3391 memset(clk_setup, 0, sizeof(clk_setup)); 2886 memset(clk_setup, 0, sizeof(clk_setup));
3392 /* init CPUs */ 2887 /* init CPUs */
3393 - env = ppc405_init("405ep", &clk_setup[PPC405EP_CPU_CLK], 2888 + env = ppc4xx_init("405ep", &clk_setup[PPC405EP_CPU_CLK],
3394 &tlb_clk_setup, sysclk); 2889 &tlb_clk_setup, sysclk);
3395 clk_setup[PPC405EP_CPU_CLK].cb = tlb_clk_setup.cb; 2890 clk_setup[PPC405EP_CPU_CLK].cb = tlb_clk_setup.cb;
3396 clk_setup[PPC405EP_CPU_CLK].opaque = tlb_clk_setup.opaque; 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 +}