mirror of
https://github.com/qemu/qemu.git
synced 2024-11-25 03:43:37 +08:00
Sparc32: convert slavio interrupt controller to qdev
Also increase QDEV_MAX_IRQ. Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
This commit is contained in:
parent
666713c071
commit
a1961a4b31
@ -21,9 +21,10 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include "hw.h"
|
||||
|
||||
#include "sun4m.h"
|
||||
#include "monitor.h"
|
||||
#include "sysbus.h"
|
||||
|
||||
//#define DEBUG_IRQ_COUNT
|
||||
//#define DEBUG_IRQ
|
||||
@ -49,28 +50,29 @@
|
||||
#define MAX_CPUS 16
|
||||
#define MAX_PILS 16
|
||||
|
||||
struct SLAVIO_CPUINTCTLState;
|
||||
struct SLAVIO_INTCTLState;
|
||||
|
||||
typedef struct SLAVIO_CPUINTCTLState {
|
||||
uint32_t intreg_pending;
|
||||
struct SLAVIO_INTCTLState *master;
|
||||
uint32_t cpu;
|
||||
} SLAVIO_CPUINTCTLState;
|
||||
|
||||
typedef struct SLAVIO_INTCTLState {
|
||||
SysBusDevice busdev;
|
||||
uint32_t intregm_pending;
|
||||
uint32_t intregm_disabled;
|
||||
uint32_t target_cpu;
|
||||
#ifdef DEBUG_IRQ_COUNT
|
||||
uint64_t irq_count[32];
|
||||
#endif
|
||||
qemu_irq *cpu_irqs[MAX_CPUS];
|
||||
qemu_irq cpu_irqs[MAX_CPUS][MAX_PILS];
|
||||
const uint32_t *intbit_to_level;
|
||||
uint32_t cputimer_lbit, cputimer_mbit;
|
||||
uint32_t pil_out[MAX_CPUS];
|
||||
struct SLAVIO_CPUINTCTLState *slaves[MAX_CPUS];
|
||||
SLAVIO_CPUINTCTLState slaves[MAX_CPUS];
|
||||
} SLAVIO_INTCTLState;
|
||||
|
||||
typedef struct SLAVIO_CPUINTCTLState {
|
||||
uint32_t intreg_pending;
|
||||
SLAVIO_INTCTLState *master;
|
||||
uint32_t cpu;
|
||||
} SLAVIO_CPUINTCTLState;
|
||||
|
||||
#define INTCTL_MAXADDR 0xf
|
||||
#define INTCTL_SIZE (INTCTL_MAXADDR + 1)
|
||||
#define INTCTLM_SIZE 0x14
|
||||
@ -225,7 +227,7 @@ void slavio_pic_info(Monitor *mon, void *opaque)
|
||||
|
||||
for (i = 0; i < MAX_CPUS; i++) {
|
||||
monitor_printf(mon, "per-cpu %d: pending 0x%08x\n", i,
|
||||
s->slaves[i]->intreg_pending);
|
||||
s->slaves[i].intreg_pending);
|
||||
}
|
||||
monitor_printf(mon, "master: pending 0x%08x, disabled 0x%08x\n",
|
||||
s->intregm_pending, s->intregm_disabled);
|
||||
@ -266,7 +268,7 @@ static void slavio_check_interrupts(SLAVIO_INTCTLState *s, int set_irqs)
|
||||
pil_pending |= 1 << s->intbit_to_level[j];
|
||||
}
|
||||
}
|
||||
pil_pending |= (s->slaves[i]->intreg_pending & CPU_SOFTIRQ_MASK) >> 16;
|
||||
pil_pending |= (s->slaves[i].intreg_pending & CPU_SOFTIRQ_MASK) >> 16;
|
||||
|
||||
if (set_irqs) {
|
||||
for (j = 0; j < MAX_PILS; j++) {
|
||||
@ -303,10 +305,10 @@ static void slavio_set_irq(void *opaque, int irq, int level)
|
||||
s->irq_count[pil]++;
|
||||
#endif
|
||||
s->intregm_pending |= mask;
|
||||
s->slaves[s->target_cpu]->intreg_pending |= 1 << pil;
|
||||
s->slaves[s->target_cpu].intreg_pending |= 1 << pil;
|
||||
} else {
|
||||
s->intregm_pending &= ~mask;
|
||||
s->slaves[s->target_cpu]->intreg_pending &= ~(1 << pil);
|
||||
s->slaves[s->target_cpu].intreg_pending &= ~(1 << pil);
|
||||
}
|
||||
slavio_check_interrupts(s, 1);
|
||||
}
|
||||
@ -320,22 +322,31 @@ static void slavio_set_timer_irq_cpu(void *opaque, int cpu, int level)
|
||||
|
||||
if (level) {
|
||||
s->intregm_pending |= s->cputimer_mbit;
|
||||
s->slaves[cpu]->intreg_pending |= s->cputimer_lbit;
|
||||
s->slaves[cpu].intreg_pending |= s->cputimer_lbit;
|
||||
} else {
|
||||
s->intregm_pending &= ~s->cputimer_mbit;
|
||||
s->slaves[cpu]->intreg_pending &= ~s->cputimer_lbit;
|
||||
s->slaves[cpu].intreg_pending &= ~s->cputimer_lbit;
|
||||
}
|
||||
|
||||
slavio_check_interrupts(s, 1);
|
||||
}
|
||||
|
||||
static void slavio_set_irq_all(void *opaque, int irq, int level)
|
||||
{
|
||||
if (irq < 32) {
|
||||
slavio_set_irq(opaque, irq, level);
|
||||
} else {
|
||||
slavio_set_timer_irq_cpu(opaque, irq - 32, level);
|
||||
}
|
||||
}
|
||||
|
||||
static void slavio_intctl_save(QEMUFile *f, void *opaque)
|
||||
{
|
||||
SLAVIO_INTCTLState *s = opaque;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_CPUS; i++) {
|
||||
qemu_put_be32s(f, &s->slaves[i]->intreg_pending);
|
||||
qemu_put_be32s(f, &s->slaves[i].intreg_pending);
|
||||
}
|
||||
qemu_put_be32s(f, &s->intregm_pending);
|
||||
qemu_put_be32s(f, &s->intregm_disabled);
|
||||
@ -351,7 +362,7 @@ static int slavio_intctl_load(QEMUFile *f, void *opaque, int version_id)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < MAX_CPUS; i++) {
|
||||
qemu_get_be32s(f, &s->slaves[i]->intreg_pending);
|
||||
qemu_get_be32s(f, &s->slaves[i].intreg_pending);
|
||||
}
|
||||
qemu_get_be32s(f, &s->intregm_pending);
|
||||
qemu_get_be32s(f, &s->intregm_disabled);
|
||||
@ -366,7 +377,7 @@ static void slavio_intctl_reset(void *opaque)
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_CPUS; i++) {
|
||||
s->slaves[i]->intreg_pending = 0;
|
||||
s->slaves[i].intreg_pending = 0;
|
||||
}
|
||||
s->intregm_disabled = ~MASTER_IRQ_MASK;
|
||||
s->intregm_pending = 0;
|
||||
@ -374,47 +385,81 @@ static void slavio_intctl_reset(void *opaque)
|
||||
slavio_check_interrupts(s, 0);
|
||||
}
|
||||
|
||||
void *slavio_intctl_init(target_phys_addr_t addr, target_phys_addr_t addrg,
|
||||
const uint32_t *intbit_to_level,
|
||||
qemu_irq **irq, qemu_irq **cpu_irq,
|
||||
qemu_irq **parent_irq, unsigned int cputimer)
|
||||
static void slavio_intctl_init1(SysBusDevice *dev)
|
||||
{
|
||||
int slavio_intctl_io_memory, slavio_intctlm_io_memory, i;
|
||||
SLAVIO_INTCTLState *s;
|
||||
SLAVIO_CPUINTCTLState *slave;
|
||||
SLAVIO_INTCTLState *s = FROM_SYSBUS(SLAVIO_INTCTLState, dev);
|
||||
int io_memory, cputimer;
|
||||
unsigned int i, j;
|
||||
|
||||
s = qemu_mallocz(sizeof(SLAVIO_INTCTLState));
|
||||
qdev_init_gpio_in(&dev->qdev, slavio_set_irq_all, 32 + MAX_CPUS);
|
||||
io_memory = cpu_register_io_memory(slavio_intctlm_mem_read,
|
||||
slavio_intctlm_mem_write, s);
|
||||
sysbus_init_mmio(dev, INTCTLM_SIZE, io_memory);
|
||||
s->intbit_to_level = qdev_get_prop_ptr(&dev->qdev, "intbit_to_level");
|
||||
cputimer = qdev_get_prop_int(&dev->qdev, "cputimer_bit", -1);
|
||||
s->cputimer_mbit = 1 << cputimer;
|
||||
s->cputimer_lbit = 1 << s->intbit_to_level[cputimer];
|
||||
|
||||
s->intbit_to_level = intbit_to_level;
|
||||
for (i = 0; i < MAX_CPUS; i++) {
|
||||
slave = qemu_mallocz(sizeof(SLAVIO_CPUINTCTLState));
|
||||
|
||||
slave->cpu = i;
|
||||
slave->master = s;
|
||||
|
||||
slavio_intctl_io_memory = cpu_register_io_memory(slavio_intctl_mem_read,
|
||||
slavio_intctl_mem_write,
|
||||
slave);
|
||||
cpu_register_physical_memory(addr + i * TARGET_PAGE_SIZE, INTCTL_SIZE,
|
||||
slavio_intctl_io_memory);
|
||||
|
||||
s->slaves[i] = slave;
|
||||
s->cpu_irqs[i] = parent_irq[i];
|
||||
for (j = 0; j < MAX_PILS; j++) {
|
||||
sysbus_init_irq(dev, &s->cpu_irqs[i][j]);
|
||||
}
|
||||
io_memory = cpu_register_io_memory(slavio_intctl_mem_read,
|
||||
slavio_intctl_mem_write,
|
||||
&s->slaves[i]);
|
||||
sysbus_init_mmio(dev, INTCTL_SIZE, io_memory);
|
||||
s->slaves[i].cpu = i;
|
||||
s->slaves[i].master = s;
|
||||
}
|
||||
|
||||
slavio_intctlm_io_memory = cpu_register_io_memory(slavio_intctlm_mem_read,
|
||||
slavio_intctlm_mem_write,
|
||||
s);
|
||||
cpu_register_physical_memory(addrg, INTCTLM_SIZE, slavio_intctlm_io_memory);
|
||||
|
||||
register_savevm("slavio_intctl", addr, 1, slavio_intctl_save,
|
||||
register_savevm("slavio_intctl", -1, 1, slavio_intctl_save,
|
||||
slavio_intctl_load, s);
|
||||
qemu_register_reset(slavio_intctl_reset, s);
|
||||
*irq = qemu_allocate_irqs(slavio_set_irq, s, 32);
|
||||
|
||||
*cpu_irq = qemu_allocate_irqs(slavio_set_timer_irq_cpu, s, MAX_CPUS);
|
||||
s->cputimer_mbit = 1 << cputimer;
|
||||
s->cputimer_lbit = 1 << intbit_to_level[cputimer];
|
||||
slavio_intctl_reset(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
DeviceState *slavio_intctl_init(target_phys_addr_t addr,
|
||||
target_phys_addr_t addrg,
|
||||
const uint32_t *intbit_to_level,
|
||||
qemu_irq **parent_irq, unsigned int cputimer)
|
||||
{
|
||||
DeviceState *dev;
|
||||
SysBusDevice *s;
|
||||
unsigned int i, j;
|
||||
|
||||
dev = qdev_create(NULL, "slavio_intctl");
|
||||
qdev_set_prop_ptr(dev, "intbit_to_level", (void *)intbit_to_level);
|
||||
qdev_set_prop_int(dev, "cputimer_bit", cputimer);
|
||||
qdev_init(dev);
|
||||
|
||||
s = sysbus_from_qdev(dev);
|
||||
|
||||
for (i = 0; i < MAX_CPUS; i++) {
|
||||
for (j = 0; j < MAX_PILS; j++) {
|
||||
sysbus_connect_irq(s, i * MAX_PILS + j, parent_irq[i][j]);
|
||||
}
|
||||
}
|
||||
sysbus_mmio_map(s, 0, addrg);
|
||||
for (i = 0; i < MAX_CPUS; i++) {
|
||||
sysbus_mmio_map(s, i + 1, addr + i * TARGET_PAGE_SIZE);
|
||||
}
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
static SysBusDeviceInfo slavio_intctl_info = {
|
||||
.init = slavio_intctl_init1,
|
||||
.qdev.name = "slavio_intctl",
|
||||
.qdev.size = sizeof(SLAVIO_INTCTLState),
|
||||
.qdev.props = (DevicePropList[]) {
|
||||
{.name = "intbit_to_level", .type = PROP_TYPE_PTR},
|
||||
{.name = "cputimer_bit", .type = PROP_TYPE_INT},
|
||||
{.name = NULL}
|
||||
}
|
||||
};
|
||||
|
||||
static void slavio_intctl_register_devices(void)
|
||||
{
|
||||
sysbus_register_withprop(&slavio_intctl_info);
|
||||
}
|
||||
|
||||
device_init(slavio_intctl_register_devices)
|
||||
|
21
hw/sun4m.c
21
hw/sun4m.c
@ -563,7 +563,7 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, ram_addr_t RAM_size,
|
||||
CPUState *envs[MAX_CPUS];
|
||||
unsigned int i;
|
||||
void *iommu, *espdma, *ledma, *nvram;
|
||||
qemu_irq *cpu_irqs[MAX_CPUS], *slavio_irq, *slavio_cpu_irq,
|
||||
qemu_irq *cpu_irqs[MAX_CPUS], slavio_irq[32], slavio_cpu_irq[MAX_CPUS],
|
||||
espdma_irq, ledma_irq;
|
||||
qemu_irq *esp_reset, *le_reset;
|
||||
qemu_irq fdc_tc;
|
||||
@ -572,6 +572,7 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, ram_addr_t RAM_size,
|
||||
BlockDriverState *fd[MAX_FD];
|
||||
int drive_index;
|
||||
void *fw_cfg;
|
||||
DeviceState *dev;
|
||||
|
||||
/* init CPUs */
|
||||
if (!cpu_model)
|
||||
@ -590,12 +591,18 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, ram_addr_t RAM_size,
|
||||
|
||||
prom_init(hwdef->slavio_base, bios_name);
|
||||
|
||||
slavio_intctl = slavio_intctl_init(hwdef->intctl_base,
|
||||
hwdef->intctl_base + 0x10000ULL,
|
||||
&hwdef->intbit_to_level[0],
|
||||
&slavio_irq, &slavio_cpu_irq,
|
||||
cpu_irqs,
|
||||
hwdef->clock_irq);
|
||||
dev = slavio_intctl_init(hwdef->intctl_base,
|
||||
hwdef->intctl_base + 0x10000ULL,
|
||||
&hwdef->intbit_to_level[0],
|
||||
cpu_irqs,
|
||||
hwdef->clock_irq);
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
slavio_irq[i] = qdev_get_gpio_in(dev, i);
|
||||
}
|
||||
for (i = 0; i < MAX_CPUS; i++) {
|
||||
slavio_cpu_irq[i] = qdev_get_gpio_in(dev, 32 + i);
|
||||
}
|
||||
|
||||
if (hwdef->idreg_base) {
|
||||
idreg_init(hwdef->idreg_base);
|
||||
|
@ -28,10 +28,10 @@ void tcx_init(target_phys_addr_t addr, int vram_size, int width, int height,
|
||||
int depth);
|
||||
|
||||
/* slavio_intctl.c */
|
||||
void *slavio_intctl_init(target_phys_addr_t addr, target_phys_addr_t addrg,
|
||||
const uint32_t *intbit_to_level,
|
||||
qemu_irq **irq, qemu_irq **cpu_irq,
|
||||
qemu_irq **parent_irq, unsigned int cputimer);
|
||||
DeviceState *slavio_intctl_init(target_phys_addr_t addr,
|
||||
target_phys_addr_t addrg,
|
||||
const uint32_t *intbit_to_level,
|
||||
qemu_irq **parent_irq, unsigned int cputimer);
|
||||
void slavio_pic_info(Monitor *mon, void *opaque);
|
||||
void slavio_irq_info(Monitor *mon, void *opaque);
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include "qdev.h"
|
||||
|
||||
#define QDEV_MAX_MMIO 32
|
||||
#define QDEV_MAX_IRQ 32
|
||||
#define QDEV_MAX_IRQ 256
|
||||
|
||||
typedef struct SysBusDevice SysBusDevice;
|
||||
typedef void (*mmio_mapfunc)(SysBusDevice *dev, target_phys_addr_t addr);
|
||||
|
Loading…
Reference in New Issue
Block a user