Commit a1961a4b313b346213439ca0e3e1e9ea69169bf4
1 parent
666713c0
Sparc32: convert slavio interrupt controller to qdev
Also increase QDEV_MAX_IRQ. Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Showing
4 changed files
with
115 additions
and
63 deletions
hw/slavio_intctl.c
... | ... | @@ -21,9 +21,10 @@ |
21 | 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
22 | 22 | * THE SOFTWARE. |
23 | 23 | */ |
24 | -#include "hw.h" | |
24 | + | |
25 | 25 | #include "sun4m.h" |
26 | 26 | #include "monitor.h" |
27 | +#include "sysbus.h" | |
27 | 28 | |
28 | 29 | //#define DEBUG_IRQ_COUNT |
29 | 30 | //#define DEBUG_IRQ |
... | ... | @@ -49,28 +50,29 @@ |
49 | 50 | #define MAX_CPUS 16 |
50 | 51 | #define MAX_PILS 16 |
51 | 52 | |
52 | -struct SLAVIO_CPUINTCTLState; | |
53 | +struct SLAVIO_INTCTLState; | |
54 | + | |
55 | +typedef struct SLAVIO_CPUINTCTLState { | |
56 | + uint32_t intreg_pending; | |
57 | + struct SLAVIO_INTCTLState *master; | |
58 | + uint32_t cpu; | |
59 | +} SLAVIO_CPUINTCTLState; | |
53 | 60 | |
54 | 61 | typedef struct SLAVIO_INTCTLState { |
62 | + SysBusDevice busdev; | |
55 | 63 | uint32_t intregm_pending; |
56 | 64 | uint32_t intregm_disabled; |
57 | 65 | uint32_t target_cpu; |
58 | 66 | #ifdef DEBUG_IRQ_COUNT |
59 | 67 | uint64_t irq_count[32]; |
60 | 68 | #endif |
61 | - qemu_irq *cpu_irqs[MAX_CPUS]; | |
69 | + qemu_irq cpu_irqs[MAX_CPUS][MAX_PILS]; | |
62 | 70 | const uint32_t *intbit_to_level; |
63 | 71 | uint32_t cputimer_lbit, cputimer_mbit; |
64 | 72 | uint32_t pil_out[MAX_CPUS]; |
65 | - struct SLAVIO_CPUINTCTLState *slaves[MAX_CPUS]; | |
73 | + SLAVIO_CPUINTCTLState slaves[MAX_CPUS]; | |
66 | 74 | } SLAVIO_INTCTLState; |
67 | 75 | |
68 | -typedef struct SLAVIO_CPUINTCTLState { | |
69 | - uint32_t intreg_pending; | |
70 | - SLAVIO_INTCTLState *master; | |
71 | - uint32_t cpu; | |
72 | -} SLAVIO_CPUINTCTLState; | |
73 | - | |
74 | 76 | #define INTCTL_MAXADDR 0xf |
75 | 77 | #define INTCTL_SIZE (INTCTL_MAXADDR + 1) |
76 | 78 | #define INTCTLM_SIZE 0x14 |
... | ... | @@ -225,7 +227,7 @@ void slavio_pic_info(Monitor *mon, void *opaque) |
225 | 227 | |
226 | 228 | for (i = 0; i < MAX_CPUS; i++) { |
227 | 229 | monitor_printf(mon, "per-cpu %d: pending 0x%08x\n", i, |
228 | - s->slaves[i]->intreg_pending); | |
230 | + s->slaves[i].intreg_pending); | |
229 | 231 | } |
230 | 232 | monitor_printf(mon, "master: pending 0x%08x, disabled 0x%08x\n", |
231 | 233 | s->intregm_pending, s->intregm_disabled); |
... | ... | @@ -266,7 +268,7 @@ static void slavio_check_interrupts(SLAVIO_INTCTLState *s, int set_irqs) |
266 | 268 | pil_pending |= 1 << s->intbit_to_level[j]; |
267 | 269 | } |
268 | 270 | } |
269 | - pil_pending |= (s->slaves[i]->intreg_pending & CPU_SOFTIRQ_MASK) >> 16; | |
271 | + pil_pending |= (s->slaves[i].intreg_pending & CPU_SOFTIRQ_MASK) >> 16; | |
270 | 272 | |
271 | 273 | if (set_irqs) { |
272 | 274 | for (j = 0; j < MAX_PILS; j++) { |
... | ... | @@ -303,10 +305,10 @@ static void slavio_set_irq(void *opaque, int irq, int level) |
303 | 305 | s->irq_count[pil]++; |
304 | 306 | #endif |
305 | 307 | s->intregm_pending |= mask; |
306 | - s->slaves[s->target_cpu]->intreg_pending |= 1 << pil; | |
308 | + s->slaves[s->target_cpu].intreg_pending |= 1 << pil; | |
307 | 309 | } else { |
308 | 310 | s->intregm_pending &= ~mask; |
309 | - s->slaves[s->target_cpu]->intreg_pending &= ~(1 << pil); | |
311 | + s->slaves[s->target_cpu].intreg_pending &= ~(1 << pil); | |
310 | 312 | } |
311 | 313 | slavio_check_interrupts(s, 1); |
312 | 314 | } |
... | ... | @@ -320,22 +322,31 @@ static void slavio_set_timer_irq_cpu(void *opaque, int cpu, int level) |
320 | 322 | |
321 | 323 | if (level) { |
322 | 324 | s->intregm_pending |= s->cputimer_mbit; |
323 | - s->slaves[cpu]->intreg_pending |= s->cputimer_lbit; | |
325 | + s->slaves[cpu].intreg_pending |= s->cputimer_lbit; | |
324 | 326 | } else { |
325 | 327 | s->intregm_pending &= ~s->cputimer_mbit; |
326 | - s->slaves[cpu]->intreg_pending &= ~s->cputimer_lbit; | |
328 | + s->slaves[cpu].intreg_pending &= ~s->cputimer_lbit; | |
327 | 329 | } |
328 | 330 | |
329 | 331 | slavio_check_interrupts(s, 1); |
330 | 332 | } |
331 | 333 | |
334 | +static void slavio_set_irq_all(void *opaque, int irq, int level) | |
335 | +{ | |
336 | + if (irq < 32) { | |
337 | + slavio_set_irq(opaque, irq, level); | |
338 | + } else { | |
339 | + slavio_set_timer_irq_cpu(opaque, irq - 32, level); | |
340 | + } | |
341 | +} | |
342 | + | |
332 | 343 | static void slavio_intctl_save(QEMUFile *f, void *opaque) |
333 | 344 | { |
334 | 345 | SLAVIO_INTCTLState *s = opaque; |
335 | 346 | int i; |
336 | 347 | |
337 | 348 | for (i = 0; i < MAX_CPUS; i++) { |
338 | - qemu_put_be32s(f, &s->slaves[i]->intreg_pending); | |
349 | + qemu_put_be32s(f, &s->slaves[i].intreg_pending); | |
339 | 350 | } |
340 | 351 | qemu_put_be32s(f, &s->intregm_pending); |
341 | 352 | qemu_put_be32s(f, &s->intregm_disabled); |
... | ... | @@ -351,7 +362,7 @@ static int slavio_intctl_load(QEMUFile *f, void *opaque, int version_id) |
351 | 362 | return -EINVAL; |
352 | 363 | |
353 | 364 | for (i = 0; i < MAX_CPUS; i++) { |
354 | - qemu_get_be32s(f, &s->slaves[i]->intreg_pending); | |
365 | + qemu_get_be32s(f, &s->slaves[i].intreg_pending); | |
355 | 366 | } |
356 | 367 | qemu_get_be32s(f, &s->intregm_pending); |
357 | 368 | qemu_get_be32s(f, &s->intregm_disabled); |
... | ... | @@ -366,7 +377,7 @@ static void slavio_intctl_reset(void *opaque) |
366 | 377 | int i; |
367 | 378 | |
368 | 379 | for (i = 0; i < MAX_CPUS; i++) { |
369 | - s->slaves[i]->intreg_pending = 0; | |
380 | + s->slaves[i].intreg_pending = 0; | |
370 | 381 | } |
371 | 382 | s->intregm_disabled = ~MASTER_IRQ_MASK; |
372 | 383 | s->intregm_pending = 0; |
... | ... | @@ -374,47 +385,81 @@ static void slavio_intctl_reset(void *opaque) |
374 | 385 | slavio_check_interrupts(s, 0); |
375 | 386 | } |
376 | 387 | |
377 | -void *slavio_intctl_init(target_phys_addr_t addr, target_phys_addr_t addrg, | |
378 | - const uint32_t *intbit_to_level, | |
379 | - qemu_irq **irq, qemu_irq **cpu_irq, | |
380 | - qemu_irq **parent_irq, unsigned int cputimer) | |
388 | +static void slavio_intctl_init1(SysBusDevice *dev) | |
381 | 389 | { |
382 | - int slavio_intctl_io_memory, slavio_intctlm_io_memory, i; | |
383 | - SLAVIO_INTCTLState *s; | |
384 | - SLAVIO_CPUINTCTLState *slave; | |
390 | + SLAVIO_INTCTLState *s = FROM_SYSBUS(SLAVIO_INTCTLState, dev); | |
391 | + int io_memory, cputimer; | |
392 | + unsigned int i, j; | |
385 | 393 | |
386 | - s = qemu_mallocz(sizeof(SLAVIO_INTCTLState)); | |
394 | + qdev_init_gpio_in(&dev->qdev, slavio_set_irq_all, 32 + MAX_CPUS); | |
395 | + io_memory = cpu_register_io_memory(slavio_intctlm_mem_read, | |
396 | + slavio_intctlm_mem_write, s); | |
397 | + sysbus_init_mmio(dev, INTCTLM_SIZE, io_memory); | |
398 | + s->intbit_to_level = qdev_get_prop_ptr(&dev->qdev, "intbit_to_level"); | |
399 | + cputimer = qdev_get_prop_int(&dev->qdev, "cputimer_bit", -1); | |
400 | + s->cputimer_mbit = 1 << cputimer; | |
401 | + s->cputimer_lbit = 1 << s->intbit_to_level[cputimer]; | |
387 | 402 | |
388 | - s->intbit_to_level = intbit_to_level; | |
389 | 403 | for (i = 0; i < MAX_CPUS; i++) { |
390 | - slave = qemu_mallocz(sizeof(SLAVIO_CPUINTCTLState)); | |
404 | + for (j = 0; j < MAX_PILS; j++) { | |
405 | + sysbus_init_irq(dev, &s->cpu_irqs[i][j]); | |
406 | + } | |
407 | + io_memory = cpu_register_io_memory(slavio_intctl_mem_read, | |
408 | + slavio_intctl_mem_write, | |
409 | + &s->slaves[i]); | |
410 | + sysbus_init_mmio(dev, INTCTL_SIZE, io_memory); | |
411 | + s->slaves[i].cpu = i; | |
412 | + s->slaves[i].master = s; | |
413 | + } | |
414 | + register_savevm("slavio_intctl", -1, 1, slavio_intctl_save, | |
415 | + slavio_intctl_load, s); | |
416 | + qemu_register_reset(slavio_intctl_reset, s); | |
417 | + slavio_intctl_reset(s); | |
418 | +} | |
419 | + | |
420 | +DeviceState *slavio_intctl_init(target_phys_addr_t addr, | |
421 | + target_phys_addr_t addrg, | |
422 | + const uint32_t *intbit_to_level, | |
423 | + qemu_irq **parent_irq, unsigned int cputimer) | |
424 | +{ | |
425 | + DeviceState *dev; | |
426 | + SysBusDevice *s; | |
427 | + unsigned int i, j; | |
391 | 428 | |
392 | - slave->cpu = i; | |
393 | - slave->master = s; | |
429 | + dev = qdev_create(NULL, "slavio_intctl"); | |
430 | + qdev_set_prop_ptr(dev, "intbit_to_level", (void *)intbit_to_level); | |
431 | + qdev_set_prop_int(dev, "cputimer_bit", cputimer); | |
432 | + qdev_init(dev); | |
394 | 433 | |
395 | - slavio_intctl_io_memory = cpu_register_io_memory(slavio_intctl_mem_read, | |
396 | - slavio_intctl_mem_write, | |
397 | - slave); | |
398 | - cpu_register_physical_memory(addr + i * TARGET_PAGE_SIZE, INTCTL_SIZE, | |
399 | - slavio_intctl_io_memory); | |
434 | + s = sysbus_from_qdev(dev); | |
400 | 435 | |
401 | - s->slaves[i] = slave; | |
402 | - s->cpu_irqs[i] = parent_irq[i]; | |
436 | + for (i = 0; i < MAX_CPUS; i++) { | |
437 | + for (j = 0; j < MAX_PILS; j++) { | |
438 | + sysbus_connect_irq(s, i * MAX_PILS + j, parent_irq[i][j]); | |
439 | + } | |
440 | + } | |
441 | + sysbus_mmio_map(s, 0, addrg); | |
442 | + for (i = 0; i < MAX_CPUS; i++) { | |
443 | + sysbus_mmio_map(s, i + 1, addr + i * TARGET_PAGE_SIZE); | |
403 | 444 | } |
404 | 445 | |
405 | - slavio_intctlm_io_memory = cpu_register_io_memory(slavio_intctlm_mem_read, | |
406 | - slavio_intctlm_mem_write, | |
407 | - s); | |
408 | - cpu_register_physical_memory(addrg, INTCTLM_SIZE, slavio_intctlm_io_memory); | |
446 | + return dev; | |
447 | +} | |
409 | 448 | |
410 | - register_savevm("slavio_intctl", addr, 1, slavio_intctl_save, | |
411 | - slavio_intctl_load, s); | |
412 | - qemu_register_reset(slavio_intctl_reset, s); | |
413 | - *irq = qemu_allocate_irqs(slavio_set_irq, s, 32); | |
449 | +static SysBusDeviceInfo slavio_intctl_info = { | |
450 | + .init = slavio_intctl_init1, | |
451 | + .qdev.name = "slavio_intctl", | |
452 | + .qdev.size = sizeof(SLAVIO_INTCTLState), | |
453 | + .qdev.props = (DevicePropList[]) { | |
454 | + {.name = "intbit_to_level", .type = PROP_TYPE_PTR}, | |
455 | + {.name = "cputimer_bit", .type = PROP_TYPE_INT}, | |
456 | + {.name = NULL} | |
457 | + } | |
458 | +}; | |
414 | 459 | |
415 | - *cpu_irq = qemu_allocate_irqs(slavio_set_timer_irq_cpu, s, MAX_CPUS); | |
416 | - s->cputimer_mbit = 1 << cputimer; | |
417 | - s->cputimer_lbit = 1 << intbit_to_level[cputimer]; | |
418 | - slavio_intctl_reset(s); | |
419 | - return s; | |
460 | +static void slavio_intctl_register_devices(void) | |
461 | +{ | |
462 | + sysbus_register_withprop(&slavio_intctl_info); | |
420 | 463 | } |
464 | + | |
465 | +device_init(slavio_intctl_register_devices) | ... | ... |
hw/sun4m.c
... | ... | @@ -563,7 +563,7 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, ram_addr_t RAM_size, |
563 | 563 | CPUState *envs[MAX_CPUS]; |
564 | 564 | unsigned int i; |
565 | 565 | void *iommu, *espdma, *ledma, *nvram; |
566 | - qemu_irq *cpu_irqs[MAX_CPUS], *slavio_irq, *slavio_cpu_irq, | |
566 | + qemu_irq *cpu_irqs[MAX_CPUS], slavio_irq[32], slavio_cpu_irq[MAX_CPUS], | |
567 | 567 | espdma_irq, ledma_irq; |
568 | 568 | qemu_irq *esp_reset, *le_reset; |
569 | 569 | qemu_irq fdc_tc; |
... | ... | @@ -572,6 +572,7 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, ram_addr_t RAM_size, |
572 | 572 | BlockDriverState *fd[MAX_FD]; |
573 | 573 | int drive_index; |
574 | 574 | void *fw_cfg; |
575 | + DeviceState *dev; | |
575 | 576 | |
576 | 577 | /* init CPUs */ |
577 | 578 | if (!cpu_model) |
... | ... | @@ -590,12 +591,18 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, ram_addr_t RAM_size, |
590 | 591 | |
591 | 592 | prom_init(hwdef->slavio_base, bios_name); |
592 | 593 | |
593 | - slavio_intctl = slavio_intctl_init(hwdef->intctl_base, | |
594 | - hwdef->intctl_base + 0x10000ULL, | |
595 | - &hwdef->intbit_to_level[0], | |
596 | - &slavio_irq, &slavio_cpu_irq, | |
597 | - cpu_irqs, | |
598 | - hwdef->clock_irq); | |
594 | + dev = slavio_intctl_init(hwdef->intctl_base, | |
595 | + hwdef->intctl_base + 0x10000ULL, | |
596 | + &hwdef->intbit_to_level[0], | |
597 | + cpu_irqs, | |
598 | + hwdef->clock_irq); | |
599 | + | |
600 | + for (i = 0; i < 32; i++) { | |
601 | + slavio_irq[i] = qdev_get_gpio_in(dev, i); | |
602 | + } | |
603 | + for (i = 0; i < MAX_CPUS; i++) { | |
604 | + slavio_cpu_irq[i] = qdev_get_gpio_in(dev, 32 + i); | |
605 | + } | |
599 | 606 | |
600 | 607 | if (hwdef->idreg_base) { |
601 | 608 | idreg_init(hwdef->idreg_base); | ... | ... |
hw/sun4m.h
... | ... | @@ -28,10 +28,10 @@ void tcx_init(target_phys_addr_t addr, int vram_size, int width, int height, |
28 | 28 | int depth); |
29 | 29 | |
30 | 30 | /* slavio_intctl.c */ |
31 | -void *slavio_intctl_init(target_phys_addr_t addr, target_phys_addr_t addrg, | |
32 | - const uint32_t *intbit_to_level, | |
33 | - qemu_irq **irq, qemu_irq **cpu_irq, | |
34 | - qemu_irq **parent_irq, unsigned int cputimer); | |
31 | +DeviceState *slavio_intctl_init(target_phys_addr_t addr, | |
32 | + target_phys_addr_t addrg, | |
33 | + const uint32_t *intbit_to_level, | |
34 | + qemu_irq **parent_irq, unsigned int cputimer); | |
35 | 35 | void slavio_pic_info(Monitor *mon, void *opaque); |
36 | 36 | void slavio_irq_info(Monitor *mon, void *opaque); |
37 | 37 | ... | ... |
hw/sysbus.h