|
1 /* |
|
2 * Heathrow PIC support (OldWorld PowerMac) |
|
3 * |
|
4 * Copyright (c) 2005-2007 Fabrice Bellard |
|
5 * Copyright (c) 2007 Jocelyn Mayer |
|
6 * |
|
7 * Permission is hereby granted, free of charge, to any person obtaining a copy |
|
8 * of this software and associated documentation files (the "Software"), to deal |
|
9 * in the Software without restriction, including without limitation the rights |
|
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
11 * copies of the Software, and to permit persons to whom the Software is |
|
12 * furnished to do so, subject to the following conditions: |
|
13 * |
|
14 * The above copyright notice and this permission notice shall be included in |
|
15 * all copies or substantial portions of the Software. |
|
16 * |
|
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
|
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
|
23 * THE SOFTWARE. |
|
24 */ |
|
25 #include "hw.h" |
|
26 #include "ppc_mac.h" |
|
27 |
|
28 //#define DEBUG |
|
29 |
|
30 typedef struct HeathrowPIC { |
|
31 uint32_t events; |
|
32 uint32_t mask; |
|
33 uint32_t levels; |
|
34 uint32_t level_triggered; |
|
35 } HeathrowPIC; |
|
36 |
|
37 typedef struct HeathrowPICS { |
|
38 HeathrowPIC pics[2]; |
|
39 qemu_irq *irqs; |
|
40 } HeathrowPICS; |
|
41 |
|
42 static inline int check_irq(HeathrowPIC *pic) |
|
43 { |
|
44 return (pic->events | (pic->levels & pic->level_triggered)) & pic->mask; |
|
45 } |
|
46 |
|
47 /* update the CPU irq state */ |
|
48 static void heathrow_pic_update(HeathrowPICS *s) |
|
49 { |
|
50 if (check_irq(&s->pics[0]) || check_irq(&s->pics[1])) { |
|
51 qemu_irq_raise(s->irqs[0]); |
|
52 } else { |
|
53 qemu_irq_lower(s->irqs[0]); |
|
54 } |
|
55 } |
|
56 |
|
57 static void pic_writel (void *opaque, target_phys_addr_t addr, uint32_t value) |
|
58 { |
|
59 HeathrowPICS *s = opaque; |
|
60 HeathrowPIC *pic; |
|
61 unsigned int n; |
|
62 |
|
63 #ifdef TARGET_WORDS_BIGENDIAN |
|
64 value = bswap32(value); |
|
65 #endif |
|
66 n = ((addr & 0xfff) - 0x10) >> 4; |
|
67 #ifdef DEBUG |
|
68 printf("pic_writel: " PADDRX " %u: %08x\n", addr, n, value); |
|
69 #endif |
|
70 if (n >= 2) |
|
71 return; |
|
72 pic = &s->pics[n]; |
|
73 switch(addr & 0xf) { |
|
74 case 0x04: |
|
75 pic->mask = value; |
|
76 heathrow_pic_update(s); |
|
77 break; |
|
78 case 0x08: |
|
79 /* do not reset level triggered IRQs */ |
|
80 value &= ~pic->level_triggered; |
|
81 pic->events &= ~value; |
|
82 heathrow_pic_update(s); |
|
83 break; |
|
84 default: |
|
85 break; |
|
86 } |
|
87 } |
|
88 |
|
89 static uint32_t pic_readl (void *opaque, target_phys_addr_t addr) |
|
90 { |
|
91 HeathrowPICS *s = opaque; |
|
92 HeathrowPIC *pic; |
|
93 unsigned int n; |
|
94 uint32_t value; |
|
95 |
|
96 n = ((addr & 0xfff) - 0x10) >> 4; |
|
97 if (n >= 2) { |
|
98 value = 0; |
|
99 } else { |
|
100 pic = &s->pics[n]; |
|
101 switch(addr & 0xf) { |
|
102 case 0x0: |
|
103 value = pic->events; |
|
104 break; |
|
105 case 0x4: |
|
106 value = pic->mask; |
|
107 break; |
|
108 case 0xc: |
|
109 value = pic->levels; |
|
110 break; |
|
111 default: |
|
112 value = 0; |
|
113 break; |
|
114 } |
|
115 } |
|
116 #ifdef DEBUG |
|
117 printf("pic_readl: " PADDRX " %u: %08x\n", addr, n, value); |
|
118 #endif |
|
119 #ifdef TARGET_WORDS_BIGENDIAN |
|
120 value = bswap32(value); |
|
121 #endif |
|
122 return value; |
|
123 } |
|
124 |
|
125 static CPUWriteMemoryFunc *pic_write[] = { |
|
126 &pic_writel, |
|
127 &pic_writel, |
|
128 &pic_writel, |
|
129 }; |
|
130 |
|
131 static CPUReadMemoryFunc *pic_read[] = { |
|
132 &pic_readl, |
|
133 &pic_readl, |
|
134 &pic_readl, |
|
135 }; |
|
136 |
|
137 |
|
138 static void heathrow_pic_set_irq(void *opaque, int num, int level) |
|
139 { |
|
140 HeathrowPICS *s = opaque; |
|
141 HeathrowPIC *pic; |
|
142 unsigned int irq_bit; |
|
143 |
|
144 #if defined(DEBUG) |
|
145 { |
|
146 static int last_level[64]; |
|
147 if (last_level[num] != level) { |
|
148 printf("set_irq: num=0x%02x level=%d\n", num, level); |
|
149 last_level[num] = level; |
|
150 } |
|
151 } |
|
152 #endif |
|
153 pic = &s->pics[1 - (num >> 5)]; |
|
154 irq_bit = 1 << (num & 0x1f); |
|
155 if (level) { |
|
156 pic->events |= irq_bit & ~pic->level_triggered; |
|
157 pic->levels |= irq_bit; |
|
158 } else { |
|
159 pic->levels &= ~irq_bit; |
|
160 } |
|
161 heathrow_pic_update(s); |
|
162 } |
|
163 |
|
164 qemu_irq *heathrow_pic_init(int *pmem_index, |
|
165 int nb_cpus, qemu_irq **irqs) |
|
166 { |
|
167 HeathrowPICS *s; |
|
168 |
|
169 s = qemu_mallocz(sizeof(HeathrowPICS)); |
|
170 s->pics[0].level_triggered = 0; |
|
171 s->pics[1].level_triggered = 0x1ff00000; |
|
172 /* only 1 CPU */ |
|
173 s->irqs = irqs[0]; |
|
174 *pmem_index = cpu_register_io_memory(0, pic_read, pic_write, s); |
|
175 |
|
176 return qemu_allocate_irqs(heathrow_pic_set_irq, s, 64); |
|
177 } |