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,9 +21,10 @@ | ||
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
22 | * THE SOFTWARE. | 22 | * THE SOFTWARE. |
23 | */ | 23 | */ |
24 | -#include "hw.h" | 24 | + |
25 | #include "sun4m.h" | 25 | #include "sun4m.h" |
26 | #include "monitor.h" | 26 | #include "monitor.h" |
27 | +#include "sysbus.h" | ||
27 | 28 | ||
28 | //#define DEBUG_IRQ_COUNT | 29 | //#define DEBUG_IRQ_COUNT |
29 | //#define DEBUG_IRQ | 30 | //#define DEBUG_IRQ |
@@ -49,28 +50,29 @@ | @@ -49,28 +50,29 @@ | ||
49 | #define MAX_CPUS 16 | 50 | #define MAX_CPUS 16 |
50 | #define MAX_PILS 16 | 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 | typedef struct SLAVIO_INTCTLState { | 61 | typedef struct SLAVIO_INTCTLState { |
62 | + SysBusDevice busdev; | ||
55 | uint32_t intregm_pending; | 63 | uint32_t intregm_pending; |
56 | uint32_t intregm_disabled; | 64 | uint32_t intregm_disabled; |
57 | uint32_t target_cpu; | 65 | uint32_t target_cpu; |
58 | #ifdef DEBUG_IRQ_COUNT | 66 | #ifdef DEBUG_IRQ_COUNT |
59 | uint64_t irq_count[32]; | 67 | uint64_t irq_count[32]; |
60 | #endif | 68 | #endif |
61 | - qemu_irq *cpu_irqs[MAX_CPUS]; | 69 | + qemu_irq cpu_irqs[MAX_CPUS][MAX_PILS]; |
62 | const uint32_t *intbit_to_level; | 70 | const uint32_t *intbit_to_level; |
63 | uint32_t cputimer_lbit, cputimer_mbit; | 71 | uint32_t cputimer_lbit, cputimer_mbit; |
64 | uint32_t pil_out[MAX_CPUS]; | 72 | uint32_t pil_out[MAX_CPUS]; |
65 | - struct SLAVIO_CPUINTCTLState *slaves[MAX_CPUS]; | 73 | + SLAVIO_CPUINTCTLState slaves[MAX_CPUS]; |
66 | } SLAVIO_INTCTLState; | 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 | #define INTCTL_MAXADDR 0xf | 76 | #define INTCTL_MAXADDR 0xf |
75 | #define INTCTL_SIZE (INTCTL_MAXADDR + 1) | 77 | #define INTCTL_SIZE (INTCTL_MAXADDR + 1) |
76 | #define INTCTLM_SIZE 0x14 | 78 | #define INTCTLM_SIZE 0x14 |
@@ -225,7 +227,7 @@ void slavio_pic_info(Monitor *mon, void *opaque) | @@ -225,7 +227,7 @@ void slavio_pic_info(Monitor *mon, void *opaque) | ||
225 | 227 | ||
226 | for (i = 0; i < MAX_CPUS; i++) { | 228 | for (i = 0; i < MAX_CPUS; i++) { |
227 | monitor_printf(mon, "per-cpu %d: pending 0x%08x\n", i, | 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 | monitor_printf(mon, "master: pending 0x%08x, disabled 0x%08x\n", | 232 | monitor_printf(mon, "master: pending 0x%08x, disabled 0x%08x\n", |
231 | s->intregm_pending, s->intregm_disabled); | 233 | s->intregm_pending, s->intregm_disabled); |
@@ -266,7 +268,7 @@ static void slavio_check_interrupts(SLAVIO_INTCTLState *s, int set_irqs) | @@ -266,7 +268,7 @@ static void slavio_check_interrupts(SLAVIO_INTCTLState *s, int set_irqs) | ||
266 | pil_pending |= 1 << s->intbit_to_level[j]; | 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 | if (set_irqs) { | 273 | if (set_irqs) { |
272 | for (j = 0; j < MAX_PILS; j++) { | 274 | for (j = 0; j < MAX_PILS; j++) { |
@@ -303,10 +305,10 @@ static void slavio_set_irq(void *opaque, int irq, int level) | @@ -303,10 +305,10 @@ static void slavio_set_irq(void *opaque, int irq, int level) | ||
303 | s->irq_count[pil]++; | 305 | s->irq_count[pil]++; |
304 | #endif | 306 | #endif |
305 | s->intregm_pending |= mask; | 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 | } else { | 309 | } else { |
308 | s->intregm_pending &= ~mask; | 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 | slavio_check_interrupts(s, 1); | 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,22 +322,31 @@ static void slavio_set_timer_irq_cpu(void *opaque, int cpu, int level) | ||
320 | 322 | ||
321 | if (level) { | 323 | if (level) { |
322 | s->intregm_pending |= s->cputimer_mbit; | 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 | } else { | 326 | } else { |
325 | s->intregm_pending &= ~s->cputimer_mbit; | 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 | slavio_check_interrupts(s, 1); | 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 | static void slavio_intctl_save(QEMUFile *f, void *opaque) | 343 | static void slavio_intctl_save(QEMUFile *f, void *opaque) |
333 | { | 344 | { |
334 | SLAVIO_INTCTLState *s = opaque; | 345 | SLAVIO_INTCTLState *s = opaque; |
335 | int i; | 346 | int i; |
336 | 347 | ||
337 | for (i = 0; i < MAX_CPUS; i++) { | 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 | qemu_put_be32s(f, &s->intregm_pending); | 351 | qemu_put_be32s(f, &s->intregm_pending); |
341 | qemu_put_be32s(f, &s->intregm_disabled); | 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,7 +362,7 @@ static int slavio_intctl_load(QEMUFile *f, void *opaque, int version_id) | ||
351 | return -EINVAL; | 362 | return -EINVAL; |
352 | 363 | ||
353 | for (i = 0; i < MAX_CPUS; i++) { | 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 | qemu_get_be32s(f, &s->intregm_pending); | 367 | qemu_get_be32s(f, &s->intregm_pending); |
357 | qemu_get_be32s(f, &s->intregm_disabled); | 368 | qemu_get_be32s(f, &s->intregm_disabled); |
@@ -366,7 +377,7 @@ static void slavio_intctl_reset(void *opaque) | @@ -366,7 +377,7 @@ static void slavio_intctl_reset(void *opaque) | ||
366 | int i; | 377 | int i; |
367 | 378 | ||
368 | for (i = 0; i < MAX_CPUS; i++) { | 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 | s->intregm_disabled = ~MASTER_IRQ_MASK; | 382 | s->intregm_disabled = ~MASTER_IRQ_MASK; |
372 | s->intregm_pending = 0; | 383 | s->intregm_pending = 0; |
@@ -374,47 +385,81 @@ static void slavio_intctl_reset(void *opaque) | @@ -374,47 +385,81 @@ static void slavio_intctl_reset(void *opaque) | ||
374 | slavio_check_interrupts(s, 0); | 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 | for (i = 0; i < MAX_CPUS; i++) { | 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,7 +563,7 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, ram_addr_t RAM_size, | ||
563 | CPUState *envs[MAX_CPUS]; | 563 | CPUState *envs[MAX_CPUS]; |
564 | unsigned int i; | 564 | unsigned int i; |
565 | void *iommu, *espdma, *ledma, *nvram; | 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 | espdma_irq, ledma_irq; | 567 | espdma_irq, ledma_irq; |
568 | qemu_irq *esp_reset, *le_reset; | 568 | qemu_irq *esp_reset, *le_reset; |
569 | qemu_irq fdc_tc; | 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,6 +572,7 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, ram_addr_t RAM_size, | ||
572 | BlockDriverState *fd[MAX_FD]; | 572 | BlockDriverState *fd[MAX_FD]; |
573 | int drive_index; | 573 | int drive_index; |
574 | void *fw_cfg; | 574 | void *fw_cfg; |
575 | + DeviceState *dev; | ||
575 | 576 | ||
576 | /* init CPUs */ | 577 | /* init CPUs */ |
577 | if (!cpu_model) | 578 | if (!cpu_model) |
@@ -590,12 +591,18 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, ram_addr_t RAM_size, | @@ -590,12 +591,18 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, ram_addr_t RAM_size, | ||
590 | 591 | ||
591 | prom_init(hwdef->slavio_base, bios_name); | 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 | if (hwdef->idreg_base) { | 607 | if (hwdef->idreg_base) { |
601 | idreg_init(hwdef->idreg_base); | 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,10 +28,10 @@ void tcx_init(target_phys_addr_t addr, int vram_size, int width, int height, | ||
28 | int depth); | 28 | int depth); |
29 | 29 | ||
30 | /* slavio_intctl.c */ | 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 | void slavio_pic_info(Monitor *mon, void *opaque); | 35 | void slavio_pic_info(Monitor *mon, void *opaque); |
36 | void slavio_irq_info(Monitor *mon, void *opaque); | 36 | void slavio_irq_info(Monitor *mon, void *opaque); |
37 | 37 |
hw/sysbus.h
@@ -6,7 +6,7 @@ | @@ -6,7 +6,7 @@ | ||
6 | #include "qdev.h" | 6 | #include "qdev.h" |
7 | 7 | ||
8 | #define QDEV_MAX_MMIO 32 | 8 | #define QDEV_MAX_MMIO 32 |
9 | -#define QDEV_MAX_IRQ 32 | 9 | +#define QDEV_MAX_IRQ 256 |
10 | 10 | ||
11 | typedef struct SysBusDevice SysBusDevice; | 11 | typedef struct SysBusDevice SysBusDevice; |
12 | typedef void (*mmio_mapfunc)(SysBusDevice *dev, target_phys_addr_t addr); | 12 | typedef void (*mmio_mapfunc)(SysBusDevice *dev, target_phys_addr_t addr); |