Revision c70c59ee
b/hw/slavio_timer.c | ||
---|---|---|
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 "qemu-timer.h" |
27 |
#include "sysbus.h" |
|
27 | 28 |
|
28 | 29 |
//#define DEBUG_TIMER |
29 | 30 |
|
... | ... | |
52 | 53 |
#define MAX_CPUS 16 |
53 | 54 |
|
54 | 55 |
typedef struct SLAVIO_TIMERState { |
56 |
SysBusDevice busdev; |
|
55 | 57 |
qemu_irq irq; |
56 | 58 |
ptimer_state *timer; |
57 | 59 |
uint32_t count, counthigh, reached; |
... | ... | |
364 | 366 |
static SLAVIO_TIMERState *slavio_timer_init(target_phys_addr_t addr, |
365 | 367 |
qemu_irq irq, |
366 | 368 |
SLAVIO_TIMERState *master, |
367 |
uint32_t slave_index) |
|
369 |
uint32_t slave_index, |
|
370 |
uint32_t num_slaves) |
|
368 | 371 |
{ |
369 |
int slavio_timer_io_memory; |
|
370 |
SLAVIO_TIMERState *s; |
|
372 |
DeviceState *dev; |
|
373 |
SysBusDevice *s; |
|
374 |
SLAVIO_TIMERState *d; |
|
375 |
|
|
376 |
dev = qdev_create(NULL, "slavio_timer"); |
|
377 |
qdev_set_prop_int(dev, "slave_index", slave_index); |
|
378 |
qdev_set_prop_int(dev, "num_slaves", num_slaves); |
|
379 |
qdev_set_prop_ptr(dev, "master", master); |
|
380 |
qdev_init(dev); |
|
381 |
s = sysbus_from_qdev(dev); |
|
382 |
sysbus_connect_irq(s, 0, irq); |
|
383 |
sysbus_mmio_map(s, 0, addr); |
|
384 |
|
|
385 |
d = FROM_SYSBUS(SLAVIO_TIMERState, s); |
|
386 |
|
|
387 |
return d; |
|
388 |
} |
|
389 |
|
|
390 |
static void slavio_timer_init1(SysBusDevice *dev) |
|
391 |
{ |
|
392 |
int io; |
|
393 |
SLAVIO_TIMERState *s = FROM_SYSBUS(SLAVIO_TIMERState, dev); |
|
371 | 394 |
QEMUBH *bh; |
372 | 395 |
|
373 |
s = qemu_mallocz(sizeof(SLAVIO_TIMERState)); |
|
374 |
s->irq = irq; |
|
375 |
s->master = master; |
|
376 |
s->slave_index = slave_index; |
|
377 |
if (!master || slave_index < master->num_slaves) { |
|
396 |
sysbus_init_irq(dev, &s->irq); |
|
397 |
s->num_slaves = qdev_get_prop_int(&dev->qdev, "num_slaves", 0); |
|
398 |
s->slave_index = qdev_get_prop_int(&dev->qdev, "slave_index", 0); |
|
399 |
s->master = qdev_get_prop_ptr(&dev->qdev, "master"); |
|
400 |
|
|
401 |
if (!s->master || s->slave_index < s->master->num_slaves) { |
|
378 | 402 |
bh = qemu_bh_new(slavio_timer_irq, s); |
379 | 403 |
s->timer = ptimer_init(bh); |
380 | 404 |
ptimer_set_period(s->timer, TIMER_PERIOD); |
381 | 405 |
} |
382 | 406 |
|
383 |
slavio_timer_io_memory = cpu_register_io_memory(slavio_timer_mem_read,
|
|
384 |
slavio_timer_mem_write, s);
|
|
385 |
if (master)
|
|
386 |
cpu_register_physical_memory(addr, CPU_TIMER_SIZE,
|
|
387 |
slavio_timer_io_memory);
|
|
388 |
else
|
|
389 |
cpu_register_physical_memory(addr, SYS_TIMER_SIZE,
|
|
390 |
slavio_timer_io_memory); |
|
391 |
register_savevm("slavio_timer", addr, 3, slavio_timer_save,
|
|
407 |
io = cpu_register_io_memory(slavio_timer_mem_read, slavio_timer_mem_write,
|
|
408 |
s); |
|
409 |
if (s->master) {
|
|
410 |
sysbus_init_mmio(dev, CPU_TIMER_SIZE, io);
|
|
411 |
} else {
|
|
412 |
sysbus_init_mmio(dev, SYS_TIMER_SIZE, io);
|
|
413 |
}
|
|
414 |
|
|
415 |
register_savevm("slavio_timer", -1, 3, slavio_timer_save,
|
|
392 | 416 |
slavio_timer_load, s); |
393 | 417 |
qemu_register_reset(slavio_timer_reset, s); |
394 | 418 |
slavio_timer_reset(s); |
395 |
|
|
396 |
return s; |
|
397 | 419 |
} |
398 | 420 |
|
399 | 421 |
void slavio_timer_init_all(target_phys_addr_t base, qemu_irq master_irq, |
... | ... | |
402 | 424 |
SLAVIO_TIMERState *master; |
403 | 425 |
unsigned int i; |
404 | 426 |
|
405 |
master = slavio_timer_init(base + SYS_TIMER_OFFSET, master_irq, NULL, 0); |
|
406 |
|
|
407 |
master->num_slaves = num_cpus; |
|
427 |
master = slavio_timer_init(base + SYS_TIMER_OFFSET, master_irq, NULL, 0, |
|
428 |
num_cpus); |
|
408 | 429 |
|
409 | 430 |
for (i = 0; i < MAX_CPUS; i++) { |
410 | 431 |
master->slave[i] = slavio_timer_init(base + (target_phys_addr_t) |
411 | 432 |
CPU_TIMER_OFFSET(i), |
412 |
cpu_irqs[i], master, i); |
|
433 |
cpu_irqs[i], master, i, 0);
|
|
413 | 434 |
} |
414 | 435 |
} |
436 |
|
|
437 |
static SysBusDeviceInfo slavio_timer_info = { |
|
438 |
.init = slavio_timer_init1, |
|
439 |
.qdev.name = "slavio_timer", |
|
440 |
.qdev.size = sizeof(SLAVIO_TIMERState), |
|
441 |
.qdev.props = (DevicePropList[]) { |
|
442 |
{.name = "num_slaves", .type = PROP_TYPE_INT}, |
|
443 |
{.name = "slave_index", .type = PROP_TYPE_INT}, |
|
444 |
{.name = "master", .type = PROP_TYPE_PTR}, |
|
445 |
{.name = NULL} |
|
446 |
} |
|
447 |
}; |
|
448 |
|
|
449 |
static void slavio_timer_register_devices(void) |
|
450 |
{ |
|
451 |
sysbus_register_withprop(&slavio_timer_info); |
|
452 |
} |
|
453 |
|
|
454 |
device_init(slavio_timer_register_devices) |
Also available in: Unified diff