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