Statistics
| Branch: | Revision:

root / hw / rc4030.c @ 21cafd08

History | View | Annotate | Download (14.9 kB)

1 4ce7ff6e aurel32
/*
2 4ce7ff6e aurel32
 * QEMU JAZZ RC4030 chipset
3 4ce7ff6e aurel32
 *
4 4ce7ff6e aurel32
 * Copyright (c) 2007-2008 Hervé Poussineau
5 4ce7ff6e aurel32
 *
6 4ce7ff6e aurel32
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 4ce7ff6e aurel32
 * of this software and associated documentation files (the "Software"), to deal
8 4ce7ff6e aurel32
 * in the Software without restriction, including without limitation the rights
9 4ce7ff6e aurel32
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 4ce7ff6e aurel32
 * copies of the Software, and to permit persons to whom the Software is
11 4ce7ff6e aurel32
 * furnished to do so, subject to the following conditions:
12 4ce7ff6e aurel32
 *
13 4ce7ff6e aurel32
 * The above copyright notice and this permission notice shall be included in
14 4ce7ff6e aurel32
 * all copies or substantial portions of the Software.
15 4ce7ff6e aurel32
 *
16 4ce7ff6e aurel32
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 4ce7ff6e aurel32
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 4ce7ff6e aurel32
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 4ce7ff6e aurel32
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 4ce7ff6e aurel32
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 4ce7ff6e aurel32
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 4ce7ff6e aurel32
 * THE SOFTWARE.
23 4ce7ff6e aurel32
 */
24 4ce7ff6e aurel32
25 4ce7ff6e aurel32
#include "hw.h"
26 4ce7ff6e aurel32
#include "qemu-timer.h"
27 4ce7ff6e aurel32
28 4ce7ff6e aurel32
//#define DEBUG_RC4030
29 4ce7ff6e aurel32
30 4ce7ff6e aurel32
#ifdef DEBUG_RC4030
31 4ce7ff6e aurel32
static const char* irq_names[] = { "parallel", "floppy", "sound", "video",
32 4ce7ff6e aurel32
            "network", "scsi", "keyboard", "mouse", "serial0", "serial1" };
33 4ce7ff6e aurel32
#endif
34 4ce7ff6e aurel32
35 4ce7ff6e aurel32
typedef struct rc4030State
36 4ce7ff6e aurel32
{
37 4ce7ff6e aurel32
    uint32_t config; /* 0x0000: RC4030 config register */
38 4ce7ff6e aurel32
    uint32_t invalid_address_register; /* 0x0010: Invalid Address register */
39 4ce7ff6e aurel32
40 4ce7ff6e aurel32
    /* DMA */
41 4ce7ff6e aurel32
    uint32_t dma_regs[8][4];
42 4ce7ff6e aurel32
    uint32_t dma_tl_base; /* 0x0018: DMA transl. table base */
43 4ce7ff6e aurel32
    uint32_t dma_tl_limit; /* 0x0020: DMA transl. table limit */
44 4ce7ff6e aurel32
45 4ce7ff6e aurel32
    /* cache */
46 4ce7ff6e aurel32
    uint32_t remote_failed_address; /* 0x0038: Remote Failed Address */
47 4ce7ff6e aurel32
    uint32_t memory_failed_address; /* 0x0040: Memory Failed Address */
48 4ce7ff6e aurel32
    uint32_t cache_ptag; /* 0x0048: I/O Cache Physical Tag */
49 4ce7ff6e aurel32
    uint32_t cache_ltag; /* 0x0050: I/O Cache Logical Tag */
50 4ce7ff6e aurel32
    uint32_t cache_bmask; /* 0x0058: I/O Cache Byte Mask */
51 4ce7ff6e aurel32
    uint32_t cache_bwin; /* 0x0060: I/O Cache Buffer Window */
52 4ce7ff6e aurel32
53 4ce7ff6e aurel32
    uint32_t offset208;
54 4ce7ff6e aurel32
    uint32_t offset210;
55 4ce7ff6e aurel32
    uint32_t nvram_protect; /* 0x0220: NV ram protect register */
56 4ce7ff6e aurel32
    uint32_t offset238;
57 4ce7ff6e aurel32
    uint32_t rem_speed[15];
58 4ce7ff6e aurel32
    uint32_t imr_jazz; /* Local bus int enable mask */
59 4ce7ff6e aurel32
    uint32_t isr_jazz; /* Local bus int source */
60 4ce7ff6e aurel32
61 4ce7ff6e aurel32
    /* timer */
62 4ce7ff6e aurel32
    QEMUTimer *periodic_timer;
63 4ce7ff6e aurel32
    uint32_t itr; /* Interval timer reload */
64 4ce7ff6e aurel32
65 4ce7ff6e aurel32
    uint32_t dummy32;
66 4ce7ff6e aurel32
    qemu_irq timer_irq;
67 4ce7ff6e aurel32
    qemu_irq jazz_bus_irq;
68 4ce7ff6e aurel32
} rc4030State;
69 4ce7ff6e aurel32
70 4ce7ff6e aurel32
static void set_next_tick(rc4030State *s)
71 4ce7ff6e aurel32
{
72 4ce7ff6e aurel32
    qemu_irq_lower(s->timer_irq);
73 b0f74c87 balrog
    uint32_t tm_hz;
74 4ce7ff6e aurel32
75 b0f74c87 balrog
    tm_hz = 1000 / (s->itr + 1);
76 4ce7ff6e aurel32
77 b0f74c87 balrog
    qemu_mod_timer(s->periodic_timer, qemu_get_clock(vm_clock) + ticks_per_sec / tm_hz);
78 4ce7ff6e aurel32
}
79 4ce7ff6e aurel32
80 4ce7ff6e aurel32
/* called for accesses to rc4030 */
81 4ce7ff6e aurel32
static uint32_t rc4030_readl(void *opaque, target_phys_addr_t addr)
82 4ce7ff6e aurel32
{
83 4ce7ff6e aurel32
    rc4030State *s = opaque;
84 4ce7ff6e aurel32
    uint32_t val;
85 4ce7ff6e aurel32
86 4ce7ff6e aurel32
    addr &= 0x3fff;
87 4ce7ff6e aurel32
    switch (addr & ~0x3) {
88 4ce7ff6e aurel32
    /* Global config register */
89 4ce7ff6e aurel32
    case 0x0000:
90 4ce7ff6e aurel32
        val = s->config;
91 4ce7ff6e aurel32
        break;
92 4ce7ff6e aurel32
    /* Invalid Address register */
93 4ce7ff6e aurel32
    case 0x0010:
94 4ce7ff6e aurel32
        val = s->invalid_address_register;
95 4ce7ff6e aurel32
        break;
96 4ce7ff6e aurel32
    /* DMA transl. table base */
97 4ce7ff6e aurel32
    case 0x0018:
98 4ce7ff6e aurel32
        val = s->dma_tl_base;
99 4ce7ff6e aurel32
        break;
100 4ce7ff6e aurel32
    /* DMA transl. table limit */
101 4ce7ff6e aurel32
    case 0x0020:
102 4ce7ff6e aurel32
        val = s->dma_tl_limit;
103 4ce7ff6e aurel32
        break;
104 4ce7ff6e aurel32
    /* Remote Failed Address */
105 4ce7ff6e aurel32
    case 0x0038:
106 4ce7ff6e aurel32
        val = s->remote_failed_address;
107 4ce7ff6e aurel32
        break;
108 4ce7ff6e aurel32
    /* Memory Failed Address */
109 4ce7ff6e aurel32
    case 0x0040:
110 4ce7ff6e aurel32
        val = s->memory_failed_address;
111 4ce7ff6e aurel32
        break;
112 4ce7ff6e aurel32
    /* I/O Cache Byte Mask */
113 4ce7ff6e aurel32
    case 0x0058:
114 4ce7ff6e aurel32
        val = s->cache_bmask;
115 4ce7ff6e aurel32
        /* HACK */
116 4ce7ff6e aurel32
        if (s->cache_bmask == (uint32_t)-1)
117 4ce7ff6e aurel32
            s->cache_bmask = 0;
118 4ce7ff6e aurel32
        break;
119 4ce7ff6e aurel32
    /* Remote Speed Registers */
120 4ce7ff6e aurel32
    case 0x0070:
121 4ce7ff6e aurel32
    case 0x0078:
122 4ce7ff6e aurel32
    case 0x0080:
123 4ce7ff6e aurel32
    case 0x0088:
124 4ce7ff6e aurel32
    case 0x0090:
125 4ce7ff6e aurel32
    case 0x0098:
126 4ce7ff6e aurel32
    case 0x00a0:
127 4ce7ff6e aurel32
    case 0x00a8:
128 4ce7ff6e aurel32
    case 0x00b0:
129 4ce7ff6e aurel32
    case 0x00b8:
130 4ce7ff6e aurel32
    case 0x00c0:
131 4ce7ff6e aurel32
    case 0x00c8:
132 4ce7ff6e aurel32
    case 0x00d0:
133 4ce7ff6e aurel32
    case 0x00d8:
134 4ce7ff6e aurel32
    case 0x00e0:
135 4ce7ff6e aurel32
        val = s->rem_speed[(addr - 0x0070) >> 3];
136 4ce7ff6e aurel32
        break;
137 4ce7ff6e aurel32
    /* DMA channel base address */
138 4ce7ff6e aurel32
    case 0x0100:
139 4ce7ff6e aurel32
    case 0x0108:
140 4ce7ff6e aurel32
    case 0x0110:
141 4ce7ff6e aurel32
    case 0x0118:
142 4ce7ff6e aurel32
    case 0x0120:
143 4ce7ff6e aurel32
    case 0x0128:
144 4ce7ff6e aurel32
    case 0x0130:
145 4ce7ff6e aurel32
    case 0x0138:
146 4ce7ff6e aurel32
    case 0x0140:
147 4ce7ff6e aurel32
    case 0x0148:
148 4ce7ff6e aurel32
    case 0x0150:
149 4ce7ff6e aurel32
    case 0x0158:
150 4ce7ff6e aurel32
    case 0x0160:
151 4ce7ff6e aurel32
    case 0x0168:
152 4ce7ff6e aurel32
    case 0x0170:
153 4ce7ff6e aurel32
    case 0x0178:
154 4ce7ff6e aurel32
    case 0x0180:
155 4ce7ff6e aurel32
    case 0x0188:
156 4ce7ff6e aurel32
    case 0x0190:
157 4ce7ff6e aurel32
    case 0x0198:
158 4ce7ff6e aurel32
    case 0x01a0:
159 4ce7ff6e aurel32
    case 0x01a8:
160 4ce7ff6e aurel32
    case 0x01b0:
161 4ce7ff6e aurel32
    case 0x01b8:
162 4ce7ff6e aurel32
    case 0x01c0:
163 4ce7ff6e aurel32
    case 0x01c8:
164 4ce7ff6e aurel32
    case 0x01d0:
165 4ce7ff6e aurel32
    case 0x01d8:
166 4ce7ff6e aurel32
    case 0x01e0:
167 4ce7ff6e aurel32
    case 0x1e8:
168 4ce7ff6e aurel32
    case 0x01f0:
169 4ce7ff6e aurel32
    case 0x01f8:
170 4ce7ff6e aurel32
        {
171 4ce7ff6e aurel32
            int entry = (addr - 0x0100) >> 5;
172 4ce7ff6e aurel32
            int idx = (addr & 0x1f) >> 3;
173 4ce7ff6e aurel32
            val = s->dma_regs[entry][idx];
174 4ce7ff6e aurel32
        }
175 4ce7ff6e aurel32
        break;
176 4ce7ff6e aurel32
    /* Offset 0x0208 */
177 4ce7ff6e aurel32
    case 0x0208:
178 4ce7ff6e aurel32
        val = s->offset208;
179 4ce7ff6e aurel32
        break;
180 4ce7ff6e aurel32
    /* Offset 0x0210 */
181 4ce7ff6e aurel32
    case 0x0210:
182 4ce7ff6e aurel32
        val = s->offset210;
183 4ce7ff6e aurel32
        break;
184 4ce7ff6e aurel32
    /* NV ram protect register */
185 4ce7ff6e aurel32
    case 0x0220:
186 4ce7ff6e aurel32
        val = s->nvram_protect;
187 4ce7ff6e aurel32
        break;
188 4ce7ff6e aurel32
    /* Interval timer count */
189 4ce7ff6e aurel32
    case 0x0230:
190 4ce7ff6e aurel32
        val = s->dummy32;
191 4ce7ff6e aurel32
        qemu_irq_lower(s->timer_irq);
192 4ce7ff6e aurel32
        break;
193 4ce7ff6e aurel32
    /* Offset 0x0238 */
194 4ce7ff6e aurel32
    case 0x0238:
195 4ce7ff6e aurel32
        val = s->offset238;
196 4ce7ff6e aurel32
        break;
197 4ce7ff6e aurel32
    default:
198 4ce7ff6e aurel32
#ifdef DEBUG_RC4030
199 4ce7ff6e aurel32
        printf("rc4030: invalid read [" TARGET_FMT_lx "]\n", addr);
200 4ce7ff6e aurel32
#endif
201 4ce7ff6e aurel32
        val = 0;
202 4ce7ff6e aurel32
        break;
203 4ce7ff6e aurel32
    }
204 4ce7ff6e aurel32
205 4ce7ff6e aurel32
#ifdef DEBUG_RC4030
206 4ce7ff6e aurel32
    if ((addr & ~3) != 0x230)
207 4ce7ff6e aurel32
        printf("rc4030: read 0x%02x at " TARGET_FMT_lx "\n", val, addr);
208 4ce7ff6e aurel32
#endif
209 4ce7ff6e aurel32
210 4ce7ff6e aurel32
    return val;
211 4ce7ff6e aurel32
}
212 4ce7ff6e aurel32
213 4ce7ff6e aurel32
static uint32_t rc4030_readw(void *opaque, target_phys_addr_t addr)
214 4ce7ff6e aurel32
{
215 4ce7ff6e aurel32
    uint32_t v = rc4030_readl(opaque, addr & ~0x3);
216 4ce7ff6e aurel32
    if (addr & 0x2)
217 4ce7ff6e aurel32
        return v >> 16;
218 4ce7ff6e aurel32
    else
219 4ce7ff6e aurel32
        return v & 0xffff;
220 4ce7ff6e aurel32
}
221 4ce7ff6e aurel32
222 4ce7ff6e aurel32
static uint32_t rc4030_readb(void *opaque, target_phys_addr_t addr)
223 4ce7ff6e aurel32
{
224 4ce7ff6e aurel32
    uint32_t v = rc4030_readl(opaque, addr & ~0x3);
225 4ce7ff6e aurel32
    return (v >> (8 * (addr & 0x3))) & 0xff;
226 4ce7ff6e aurel32
}
227 4ce7ff6e aurel32
228 4ce7ff6e aurel32
static void rc4030_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
229 4ce7ff6e aurel32
{
230 4ce7ff6e aurel32
    rc4030State *s = opaque;
231 4ce7ff6e aurel32
    addr &= 0x3fff;
232 4ce7ff6e aurel32
233 4ce7ff6e aurel32
#ifdef DEBUG_RC4030
234 4ce7ff6e aurel32
    printf("rc4030: write 0x%02x at " TARGET_FMT_lx "\n", val, addr);
235 4ce7ff6e aurel32
#endif
236 4ce7ff6e aurel32
237 4ce7ff6e aurel32
    switch (addr & ~0x3) {
238 4ce7ff6e aurel32
    /* Global config register */
239 4ce7ff6e aurel32
    case 0x0000:
240 4ce7ff6e aurel32
        s->config = val;
241 4ce7ff6e aurel32
        break;
242 4ce7ff6e aurel32
    /* DMA transl. table base */
243 4ce7ff6e aurel32
    case 0x0018:
244 4ce7ff6e aurel32
        s->dma_tl_base = val;
245 4ce7ff6e aurel32
        break;
246 4ce7ff6e aurel32
    /* DMA transl. table limit */
247 4ce7ff6e aurel32
    case 0x0020:
248 4ce7ff6e aurel32
        s->dma_tl_limit = val;
249 4ce7ff6e aurel32
        break;
250 4ce7ff6e aurel32
    /* I/O Cache Physical Tag */
251 4ce7ff6e aurel32
    case 0x0048:
252 4ce7ff6e aurel32
        s->cache_ptag = val;
253 4ce7ff6e aurel32
        break;
254 4ce7ff6e aurel32
    /* I/O Cache Logical Tag */
255 4ce7ff6e aurel32
    case 0x0050:
256 4ce7ff6e aurel32
        s->cache_ltag = val;
257 4ce7ff6e aurel32
        break;
258 4ce7ff6e aurel32
    /* I/O Cache Byte Mask */
259 4ce7ff6e aurel32
    case 0x0058:
260 4ce7ff6e aurel32
        s->cache_bmask |= val; /* HACK */
261 4ce7ff6e aurel32
        break;
262 4ce7ff6e aurel32
    /* I/O Cache Buffer Window */
263 4ce7ff6e aurel32
    case 0x0060:
264 4ce7ff6e aurel32
        s->cache_bwin = val;
265 4ce7ff6e aurel32
        /* HACK */
266 4ce7ff6e aurel32
        if (s->cache_ltag == 0x80000001 && s->cache_bmask == 0xf0f0f0f) {
267 4ce7ff6e aurel32
            target_phys_addr_t dests[] = { 4, 0, 8, 0x10 };
268 4ce7ff6e aurel32
            static int current = 0;
269 4ce7ff6e aurel32
            target_phys_addr_t dest = 0 + dests[current];
270 4ce7ff6e aurel32
            uint8_t buf;
271 4ce7ff6e aurel32
            current = (current + 1) % (sizeof(dests)/sizeof(dests[0]));
272 4ce7ff6e aurel32
            buf = s->cache_bwin - 1;
273 4ce7ff6e aurel32
            cpu_physical_memory_rw(dest, &buf, 1, 1);
274 4ce7ff6e aurel32
        }
275 4ce7ff6e aurel32
        break;
276 4ce7ff6e aurel32
    /* Remote Speed Registers */
277 4ce7ff6e aurel32
    case 0x0070:
278 4ce7ff6e aurel32
    case 0x0078:
279 4ce7ff6e aurel32
    case 0x0080:
280 4ce7ff6e aurel32
    case 0x0088:
281 4ce7ff6e aurel32
    case 0x0090:
282 4ce7ff6e aurel32
    case 0x0098:
283 4ce7ff6e aurel32
    case 0x00a0:
284 4ce7ff6e aurel32
    case 0x00a8:
285 4ce7ff6e aurel32
    case 0x00b0:
286 4ce7ff6e aurel32
    case 0x00b8:
287 4ce7ff6e aurel32
    case 0x00c0:
288 4ce7ff6e aurel32
    case 0x00c8:
289 4ce7ff6e aurel32
    case 0x00d0:
290 4ce7ff6e aurel32
    case 0x00d8:
291 4ce7ff6e aurel32
    case 0x00e0:
292 4ce7ff6e aurel32
        s->rem_speed[(addr - 0x0070) >> 3] = val;
293 4ce7ff6e aurel32
        break;
294 4ce7ff6e aurel32
    /* DMA channel base address */
295 4ce7ff6e aurel32
    case 0x0100:
296 4ce7ff6e aurel32
    case 0x0108:
297 4ce7ff6e aurel32
    case 0x0110:
298 4ce7ff6e aurel32
    case 0x0118:
299 4ce7ff6e aurel32
    case 0x0120:
300 4ce7ff6e aurel32
    case 0x0128:
301 4ce7ff6e aurel32
    case 0x0130:
302 4ce7ff6e aurel32
    case 0x0138:
303 4ce7ff6e aurel32
    case 0x0140:
304 4ce7ff6e aurel32
    case 0x0148:
305 4ce7ff6e aurel32
    case 0x0150:
306 4ce7ff6e aurel32
    case 0x0158:
307 4ce7ff6e aurel32
    case 0x0160:
308 4ce7ff6e aurel32
    case 0x0168:
309 4ce7ff6e aurel32
    case 0x0170:
310 4ce7ff6e aurel32
    case 0x0178:
311 4ce7ff6e aurel32
    case 0x0180:
312 4ce7ff6e aurel32
    case 0x0188:
313 4ce7ff6e aurel32
    case 0x0190:
314 4ce7ff6e aurel32
    case 0x0198:
315 4ce7ff6e aurel32
    case 0x01a0:
316 4ce7ff6e aurel32
    case 0x01a8:
317 4ce7ff6e aurel32
    case 0x01b0:
318 4ce7ff6e aurel32
    case 0x01b8:
319 4ce7ff6e aurel32
    case 0x01c0:
320 4ce7ff6e aurel32
    case 0x01c8:
321 4ce7ff6e aurel32
    case 0x01d0:
322 4ce7ff6e aurel32
    case 0x01d8:
323 4ce7ff6e aurel32
    case 0x01e0:
324 4ce7ff6e aurel32
    case 0x1e8:
325 4ce7ff6e aurel32
    case 0x01f0:
326 4ce7ff6e aurel32
    case 0x01f8:
327 4ce7ff6e aurel32
        {
328 4ce7ff6e aurel32
            int entry = (addr - 0x0100) >> 5;
329 4ce7ff6e aurel32
            int idx = (addr & 0x1f) >> 3;
330 4ce7ff6e aurel32
            s->dma_regs[entry][idx] = val;
331 4ce7ff6e aurel32
        }
332 4ce7ff6e aurel32
        break;
333 4ce7ff6e aurel32
    /* Offset 0x0210 */
334 4ce7ff6e aurel32
    case 0x0210:
335 4ce7ff6e aurel32
        s->offset210 = val;
336 4ce7ff6e aurel32
        break;
337 4ce7ff6e aurel32
    /* Interval timer reload */
338 4ce7ff6e aurel32
    case 0x0228:
339 4ce7ff6e aurel32
        s->itr = val;
340 4ce7ff6e aurel32
        qemu_irq_lower(s->timer_irq);
341 4ce7ff6e aurel32
        set_next_tick(s);
342 4ce7ff6e aurel32
        break;
343 4ce7ff6e aurel32
    default:
344 4ce7ff6e aurel32
#ifdef DEBUG_RC4030
345 4ce7ff6e aurel32
        printf("rc4030: invalid write of 0x%02x at [" TARGET_FMT_lx "]\n", val, addr);
346 4ce7ff6e aurel32
#endif
347 4ce7ff6e aurel32
        break;
348 4ce7ff6e aurel32
    }
349 4ce7ff6e aurel32
}
350 4ce7ff6e aurel32
351 4ce7ff6e aurel32
static void rc4030_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
352 4ce7ff6e aurel32
{
353 4ce7ff6e aurel32
    uint32_t old_val = rc4030_readl(opaque, addr & ~0x3);
354 4ce7ff6e aurel32
355 4ce7ff6e aurel32
    if (addr & 0x2)
356 4ce7ff6e aurel32
        val = (val << 16) | (old_val & 0x0000ffff);
357 4ce7ff6e aurel32
    else
358 4ce7ff6e aurel32
        val = val | (old_val & 0xffff0000);
359 4ce7ff6e aurel32
    rc4030_writel(opaque, addr & ~0x3, val);
360 4ce7ff6e aurel32
}
361 4ce7ff6e aurel32
362 4ce7ff6e aurel32
static void rc4030_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
363 4ce7ff6e aurel32
{
364 4ce7ff6e aurel32
    uint32_t old_val = rc4030_readl(opaque, addr & ~0x3);
365 4ce7ff6e aurel32
366 4ce7ff6e aurel32
    switch (addr & 3) {
367 4ce7ff6e aurel32
    case 0:
368 4ce7ff6e aurel32
        val = val | (old_val & 0xffffff00);
369 4ce7ff6e aurel32
        break;
370 4ce7ff6e aurel32
    case 1:
371 4ce7ff6e aurel32
        val = (val << 8) | (old_val & 0xffff00ff);
372 4ce7ff6e aurel32
        break;
373 4ce7ff6e aurel32
    case 2:
374 4ce7ff6e aurel32
        val = (val << 16) | (old_val & 0xff00ffff);
375 4ce7ff6e aurel32
        break;
376 4ce7ff6e aurel32
    case 3:
377 4ce7ff6e aurel32
        val = (val << 24) | (old_val & 0x00ffffff);
378 4ce7ff6e aurel32
        break;
379 4ce7ff6e aurel32
    }
380 4ce7ff6e aurel32
    rc4030_writel(opaque, addr & ~0x3, val);
381 4ce7ff6e aurel32
}
382 4ce7ff6e aurel32
383 4ce7ff6e aurel32
static CPUReadMemoryFunc *rc4030_read[3] = {
384 4ce7ff6e aurel32
    rc4030_readb,
385 4ce7ff6e aurel32
    rc4030_readw,
386 4ce7ff6e aurel32
    rc4030_readl,
387 4ce7ff6e aurel32
};
388 4ce7ff6e aurel32
389 4ce7ff6e aurel32
static CPUWriteMemoryFunc *rc4030_write[3] = {
390 4ce7ff6e aurel32
    rc4030_writeb,
391 4ce7ff6e aurel32
    rc4030_writew,
392 4ce7ff6e aurel32
    rc4030_writel,
393 4ce7ff6e aurel32
};
394 4ce7ff6e aurel32
395 4ce7ff6e aurel32
static void update_jazz_irq(rc4030State *s)
396 4ce7ff6e aurel32
{
397 4ce7ff6e aurel32
    uint16_t pending;
398 4ce7ff6e aurel32
399 4ce7ff6e aurel32
    pending = s->isr_jazz & s->imr_jazz;
400 4ce7ff6e aurel32
401 4ce7ff6e aurel32
#ifdef DEBUG_RC4030
402 4ce7ff6e aurel32
    if (s->isr_jazz != 0) {
403 4ce7ff6e aurel32
        uint32_t irq = 0;
404 4ce7ff6e aurel32
        printf("jazz pending:");
405 4ce7ff6e aurel32
        for (irq = 0; irq < sizeof(irq_names)/sizeof(irq_names[0]); irq++) {
406 4ce7ff6e aurel32
            if (s->isr_jazz & (1 << irq)) {
407 4ce7ff6e aurel32
                printf(" %s", irq_names[irq]);
408 4ce7ff6e aurel32
                if (!(s->imr_jazz & (1 << irq))) {
409 4ce7ff6e aurel32
                    printf("(ignored)");
410 4ce7ff6e aurel32
                }
411 4ce7ff6e aurel32
            }
412 4ce7ff6e aurel32
        }
413 4ce7ff6e aurel32
        printf("\n");
414 4ce7ff6e aurel32
    }
415 4ce7ff6e aurel32
#endif
416 4ce7ff6e aurel32
417 4ce7ff6e aurel32
    if (pending != 0)
418 4ce7ff6e aurel32
        qemu_irq_raise(s->jazz_bus_irq);
419 4ce7ff6e aurel32
    else
420 4ce7ff6e aurel32
        qemu_irq_lower(s->jazz_bus_irq);
421 4ce7ff6e aurel32
}
422 4ce7ff6e aurel32
423 4ce7ff6e aurel32
static void rc4030_irq_jazz_request(void *opaque, int irq, int level)
424 4ce7ff6e aurel32
{
425 4ce7ff6e aurel32
    rc4030State *s = opaque;
426 4ce7ff6e aurel32
427 4ce7ff6e aurel32
    if (level) {
428 4ce7ff6e aurel32
        s->isr_jazz |= 1 << irq;
429 4ce7ff6e aurel32
    } else {
430 4ce7ff6e aurel32
        s->isr_jazz &= ~(1 << irq);
431 4ce7ff6e aurel32
    }
432 4ce7ff6e aurel32
433 4ce7ff6e aurel32
    update_jazz_irq(s);
434 4ce7ff6e aurel32
}
435 4ce7ff6e aurel32
436 4ce7ff6e aurel32
static void rc4030_periodic_timer(void *opaque)
437 4ce7ff6e aurel32
{
438 4ce7ff6e aurel32
    rc4030State *s = opaque;
439 4ce7ff6e aurel32
440 4ce7ff6e aurel32
    set_next_tick(s);
441 4ce7ff6e aurel32
    qemu_irq_raise(s->timer_irq);
442 4ce7ff6e aurel32
}
443 4ce7ff6e aurel32
444 4ce7ff6e aurel32
static uint32_t int_readb(void *opaque, target_phys_addr_t addr)
445 4ce7ff6e aurel32
{
446 4ce7ff6e aurel32
    rc4030State *s = opaque;
447 4ce7ff6e aurel32
    uint32_t val;
448 4ce7ff6e aurel32
    uint32_t irq;
449 4ce7ff6e aurel32
    addr &= 0xfff;
450 4ce7ff6e aurel32
451 4ce7ff6e aurel32
    switch (addr) {
452 4ce7ff6e aurel32
    case 0x00: {
453 4ce7ff6e aurel32
        /* Local bus int source */
454 4ce7ff6e aurel32
        uint32_t pending = s->isr_jazz & s->imr_jazz;
455 4ce7ff6e aurel32
        val = 0;
456 4ce7ff6e aurel32
        irq = 0;
457 4ce7ff6e aurel32
        while (pending) {
458 4ce7ff6e aurel32
            if (pending & 1) {
459 4ce7ff6e aurel32
                //printf("returning irq %s\n", irq_names[irq]);
460 4ce7ff6e aurel32
                val = (irq + 1) << 2;
461 4ce7ff6e aurel32
                break;
462 4ce7ff6e aurel32
            }
463 4ce7ff6e aurel32
            irq++;
464 4ce7ff6e aurel32
            pending >>= 1;
465 4ce7ff6e aurel32
        }
466 4ce7ff6e aurel32
        break;
467 4ce7ff6e aurel32
    }
468 4ce7ff6e aurel32
    default:
469 4ce7ff6e aurel32
#ifdef DEBUG_RC4030
470 4ce7ff6e aurel32
            printf("rc4030: (interrupt controller) invalid read [" TARGET_FMT_lx "]\n", addr);
471 4ce7ff6e aurel32
#endif
472 4ce7ff6e aurel32
            val = 0;
473 4ce7ff6e aurel32
    }
474 4ce7ff6e aurel32
475 4ce7ff6e aurel32
#ifdef DEBUG_RC4030
476 4ce7ff6e aurel32
    printf("rc4030: (interrupt controller) read 0x%02x at " TARGET_FMT_lx "\n", val, addr);
477 4ce7ff6e aurel32
#endif
478 4ce7ff6e aurel32
479 4ce7ff6e aurel32
    return val;
480 4ce7ff6e aurel32
}
481 4ce7ff6e aurel32
482 4ce7ff6e aurel32
static uint32_t int_readw(void *opaque, target_phys_addr_t addr)
483 4ce7ff6e aurel32
{
484 4ce7ff6e aurel32
    uint32_t v;
485 4ce7ff6e aurel32
    v = int_readb(opaque, addr);
486 4ce7ff6e aurel32
    v |= int_readb(opaque, addr + 1) << 8;
487 4ce7ff6e aurel32
    return v;
488 4ce7ff6e aurel32
}
489 4ce7ff6e aurel32
490 4ce7ff6e aurel32
static uint32_t int_readl(void *opaque, target_phys_addr_t addr)
491 4ce7ff6e aurel32
{
492 4ce7ff6e aurel32
    uint32_t v;
493 4ce7ff6e aurel32
    v = int_readb(opaque, addr);
494 4ce7ff6e aurel32
    v |= int_readb(opaque, addr + 1) << 8;
495 4ce7ff6e aurel32
    v |= int_readb(opaque, addr + 2) << 16;
496 4ce7ff6e aurel32
    v |= int_readb(opaque, addr + 3) << 24;
497 4ce7ff6e aurel32
    return v;
498 4ce7ff6e aurel32
}
499 4ce7ff6e aurel32
500 4ce7ff6e aurel32
static void int_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
501 4ce7ff6e aurel32
{
502 4ce7ff6e aurel32
    rc4030State *s = opaque;
503 4ce7ff6e aurel32
    addr &= 0xfff;
504 4ce7ff6e aurel32
505 4ce7ff6e aurel32
#ifdef DEBUG_RC4030
506 4ce7ff6e aurel32
    printf("rc4030: (interrupt controller) write 0x%02x at " TARGET_FMT_lx "\n", val, addr);
507 4ce7ff6e aurel32
#endif
508 4ce7ff6e aurel32
509 4ce7ff6e aurel32
    switch (addr) {
510 4ce7ff6e aurel32
    /* Local bus int enable mask */
511 4ce7ff6e aurel32
    case 0x02:
512 4ce7ff6e aurel32
        s->imr_jazz = (s->imr_jazz & 0xff00) | (val << 0); update_jazz_irq(s);
513 4ce7ff6e aurel32
        break;
514 4ce7ff6e aurel32
    case 0x03:
515 4ce7ff6e aurel32
        s->imr_jazz = (s->imr_jazz & 0x00ff) | (val << 8); update_jazz_irq(s);
516 4ce7ff6e aurel32
        break;
517 4ce7ff6e aurel32
    default:
518 4ce7ff6e aurel32
#ifdef DEBUG_RC4030
519 4ce7ff6e aurel32
        printf("rc4030: (interrupt controller) invalid write of 0x%02x at [" TARGET_FMT_lx "]\n", val, addr);
520 4ce7ff6e aurel32
#endif
521 4ce7ff6e aurel32
        break;
522 4ce7ff6e aurel32
    }
523 4ce7ff6e aurel32
}
524 4ce7ff6e aurel32
525 4ce7ff6e aurel32
static void int_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
526 4ce7ff6e aurel32
{
527 4ce7ff6e aurel32
    int_writeb(opaque, addr, val & 0xff);
528 4ce7ff6e aurel32
    int_writeb(opaque, addr + 1, (val >> 8) & 0xff);
529 4ce7ff6e aurel32
}
530 4ce7ff6e aurel32
531 4ce7ff6e aurel32
static void int_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
532 4ce7ff6e aurel32
{
533 4ce7ff6e aurel32
    int_writeb(opaque, addr, val & 0xff);
534 4ce7ff6e aurel32
    int_writeb(opaque, addr + 1, (val >> 8) & 0xff);
535 4ce7ff6e aurel32
    int_writeb(opaque, addr + 2, (val >> 16) & 0xff);
536 4ce7ff6e aurel32
    int_writeb(opaque, addr + 3, (val >> 24) & 0xff);
537 4ce7ff6e aurel32
}
538 4ce7ff6e aurel32
539 4ce7ff6e aurel32
static CPUReadMemoryFunc *int_read[3] = {
540 4ce7ff6e aurel32
    int_readb,
541 4ce7ff6e aurel32
    int_readw,
542 4ce7ff6e aurel32
    int_readl,
543 4ce7ff6e aurel32
};
544 4ce7ff6e aurel32
545 4ce7ff6e aurel32
static CPUWriteMemoryFunc *int_write[3] = {
546 4ce7ff6e aurel32
    int_writeb,
547 4ce7ff6e aurel32
    int_writew,
548 4ce7ff6e aurel32
    int_writel,
549 4ce7ff6e aurel32
};
550 4ce7ff6e aurel32
551 4ce7ff6e aurel32
#define G364_512KB_RAM (0x0)
552 4ce7ff6e aurel32
#define G364_2MB_RAM   (0x1)
553 4ce7ff6e aurel32
#define G364_8MB_RAM   (0x2)
554 4ce7ff6e aurel32
#define G364_32MB_RAM  (0x3)
555 4ce7ff6e aurel32
556 4ce7ff6e aurel32
static void rc4030_reset(void *opaque)
557 4ce7ff6e aurel32
{
558 4ce7ff6e aurel32
    rc4030State *s = opaque;
559 4ce7ff6e aurel32
    int i;
560 4ce7ff6e aurel32
561 4ce7ff6e aurel32
    s->config = (G364_2MB_RAM << 8) | 0x04;
562 4ce7ff6e aurel32
    s->invalid_address_register = 0;
563 4ce7ff6e aurel32
564 4ce7ff6e aurel32
    memset(s->dma_regs, 0, sizeof(s->dma_regs));
565 4ce7ff6e aurel32
    s->dma_tl_base = s->dma_tl_limit = 0;
566 4ce7ff6e aurel32
567 4ce7ff6e aurel32
    s->remote_failed_address = s->memory_failed_address = 0;
568 4ce7ff6e aurel32
    s->cache_ptag = s->cache_ltag = 0;
569 4ce7ff6e aurel32
    s->cache_bmask = s->cache_bwin = 0;
570 4ce7ff6e aurel32
571 4ce7ff6e aurel32
    s->offset208 = 0;
572 4ce7ff6e aurel32
    s->offset210 = 0x18186;
573 4ce7ff6e aurel32
    s->nvram_protect = 7;
574 4ce7ff6e aurel32
    s->offset238 = 7;
575 4ce7ff6e aurel32
    for (i = 0; i < 15; i++)
576 4ce7ff6e aurel32
        s->rem_speed[i] = 7;
577 4ce7ff6e aurel32
    s->imr_jazz = s->isr_jazz = 0;
578 4ce7ff6e aurel32
579 4ce7ff6e aurel32
    s->itr = 0;
580 4ce7ff6e aurel32
    s->dummy32 = 0;
581 4ce7ff6e aurel32
582 4ce7ff6e aurel32
    qemu_irq_lower(s->timer_irq);
583 4ce7ff6e aurel32
    qemu_irq_lower(s->jazz_bus_irq);
584 4ce7ff6e aurel32
}
585 4ce7ff6e aurel32
586 4ce7ff6e aurel32
qemu_irq *rc4030_init(qemu_irq timer, qemu_irq jazz_bus)
587 4ce7ff6e aurel32
{
588 4ce7ff6e aurel32
    rc4030State *s;
589 4ce7ff6e aurel32
    int s_chipset, s_int;
590 4ce7ff6e aurel32
591 4ce7ff6e aurel32
    s = qemu_mallocz(sizeof(rc4030State));
592 4ce7ff6e aurel32
    if (!s)
593 4ce7ff6e aurel32
        return NULL;
594 4ce7ff6e aurel32
595 4ce7ff6e aurel32
    s->periodic_timer = qemu_new_timer(vm_clock, rc4030_periodic_timer, s);
596 4ce7ff6e aurel32
    s->timer_irq = timer;
597 4ce7ff6e aurel32
    s->jazz_bus_irq = jazz_bus;
598 4ce7ff6e aurel32
599 4ce7ff6e aurel32
    qemu_register_reset(rc4030_reset, s);
600 4ce7ff6e aurel32
    rc4030_reset(s);
601 4ce7ff6e aurel32
602 4ce7ff6e aurel32
    s_chipset = cpu_register_io_memory(0, rc4030_read, rc4030_write, s);
603 4ce7ff6e aurel32
    cpu_register_physical_memory(0x80000000, 0x300, s_chipset);
604 4ce7ff6e aurel32
    s_int = cpu_register_io_memory(0, int_read, int_write, s);
605 4ce7ff6e aurel32
    cpu_register_physical_memory(0xf0000000, 0x00001000, s_int);
606 4ce7ff6e aurel32
607 4ce7ff6e aurel32
    return qemu_allocate_irqs(rc4030_irq_jazz_request, s, 16);
608 4ce7ff6e aurel32
}