* THE SOFTWARE.
*/
#include "hw.h"
-#include "ppc_mac.h"
-#include "qemu-timer.h"
-#include "sysemu.h"
+#include "ppc/mac.h"
+#include "adb.h"
+#include "qemu/timer.h"
+#include "sysemu/sysemu.h"
/* XXX: implement all timer modes */
//#define DEBUG_CUDA_PACKET
#ifdef DEBUG_CUDA
-#define CUDA_DPRINTF(fmt, args...) \
-do { printf("CUDA: " fmt , ##args); } while (0)
+#define CUDA_DPRINTF(fmt, ...) \
+ do { printf("CUDA: " fmt , ## __VA_ARGS__); } while (0)
#else
-#define CUDA_DPRINTF(fmt, args...)
+#define CUDA_DPRINTF(fmt, ...)
#endif
/* Bits in B data register: all active low */
/* CUDA returns time_t's offset from Jan 1, 1904, not 1970 */
#define RTC_OFFSET 2082844800
-typedef struct CUDATimer {
- int index;
- uint16_t latch;
- uint16_t counter_value; /* counter value at load time */
- int64_t load_time;
- int64_t next_irq_time;
- QEMUTimer *timer;
-} CUDATimer;
-
-typedef struct CUDAState {
- /* cuda registers */
- uint8_t b; /* B-side data */
- uint8_t a; /* A-side data */
- uint8_t dirb; /* B-side direction (1=output) */
- uint8_t dira; /* A-side direction (1=output) */
- uint8_t sr; /* Shift register */
- uint8_t acr; /* Auxiliary control register */
- uint8_t pcr; /* Peripheral control register */
- uint8_t ifr; /* Interrupt flag register */
- uint8_t ier; /* Interrupt enable register */
- uint8_t anh; /* A-side data, no handshake */
-
- CUDATimer timers[2];
-
- uint32_t tick_offset;
-
- uint8_t last_b; /* last value of B register */
- uint8_t last_acr; /* last value of B register */
-
- int data_in_size;
- int data_in_index;
- int data_out_index;
-
- qemu_irq irq;
- uint8_t autopoll;
- uint8_t data_in[128];
- uint8_t data_out[16];
- QEMUTimer *adb_poll_timer;
-} CUDAState;
-
-static CUDAState cuda_state;
-ADBBusState adb_bus;
-
static void cuda_update(CUDAState *s);
static void cuda_receive_packet_from_host(CUDAState *s,
const uint8_t *data, int len);
int64_t d;
unsigned int counter;
- d = muldiv64(qemu_get_clock(vm_clock) - s->load_time,
- CUDA_TIMER_FREQ, ticks_per_sec);
+ d = muldiv64(qemu_get_clock_ns(vm_clock) - s->load_time,
+ CUDA_TIMER_FREQ, get_ticks_per_sec());
if (s->index == 0) {
/* the timer goes down from latch to -1 (period of latch + 2) */
if (d <= (s->counter_value + 1)) {
static void set_counter(CUDAState *s, CUDATimer *ti, unsigned int val)
{
CUDA_DPRINTF("T%d.counter=%d\n", 1 + (ti->timer == NULL), val);
- ti->load_time = qemu_get_clock(vm_clock);
+ ti->load_time = qemu_get_clock_ns(vm_clock);
ti->counter_value = val;
cuda_timer_update(s, ti, ti->load_time);
}
/* current counter value */
d = muldiv64(current_time - s->load_time,
- CUDA_TIMER_FREQ, ticks_per_sec);
+ CUDA_TIMER_FREQ, get_ticks_per_sec());
/* the timer goes down from latch to -1 (period of latch + 2) */
if (d <= (s->counter_value + 1)) {
counter = (s->counter_value - d) & 0xffff;
}
CUDA_DPRINTF("latch=%d counter=%" PRId64 " delta_next=%" PRId64 "\n",
s->latch, d, next_time - d);
- next_time = muldiv64(next_time, ticks_per_sec, CUDA_TIMER_FREQ) +
+ next_time = muldiv64(next_time, get_ticks_per_sec(), CUDA_TIMER_FREQ) +
s->load_time;
if (next_time <= current_time)
next_time = current_time + 1;
cuda_update_irq(s);
}
-static uint32_t cuda_readb(void *opaque, target_phys_addr_t addr)
+static uint32_t cuda_readb(void *opaque, hwaddr addr)
{
CUDAState *s = opaque;
uint32_t val;
val = s->anh;
break;
}
- if (addr != 13 || val != 0)
+ if (addr != 13 || val != 0) {
CUDA_DPRINTF("read: reg=0x%x val=%02x\n", (int)addr, val);
+ }
+
return val;
}
-static void cuda_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
+static void cuda_writeb(void *opaque, hwaddr addr, uint32_t val)
{
CUDAState *s = opaque;
break;
case 4:
s->timers[0].latch = (s->timers[0].latch & 0xff00) | val;
- cuda_timer_update(s, &s->timers[0], qemu_get_clock(vm_clock));
+ cuda_timer_update(s, &s->timers[0], qemu_get_clock_ns(vm_clock));
break;
case 5:
s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8);
break;
case 6:
s->timers[0].latch = (s->timers[0].latch & 0xff00) | val;
- cuda_timer_update(s, &s->timers[0], qemu_get_clock(vm_clock));
+ cuda_timer_update(s, &s->timers[0], qemu_get_clock_ns(vm_clock));
break;
case 7:
s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8);
s->ifr &= ~T1_INT;
- cuda_timer_update(s, &s->timers[0], qemu_get_clock(vm_clock));
+ cuda_timer_update(s, &s->timers[0], qemu_get_clock_ns(vm_clock));
break;
case 8:
s->timers[1].latch = val;
break;
case 11:
s->acr = val;
- cuda_timer_update(s, &s->timers[0], qemu_get_clock(vm_clock));
+ cuda_timer_update(s, &s->timers[0], qemu_get_clock_ns(vm_clock));
cuda_update(s);
break;
case 12:
uint8_t obuf[ADB_MAX_OUT_LEN + 2];
int olen;
- olen = adb_poll(&adb_bus, obuf + 2);
+ olen = adb_poll(&s->adb_bus, obuf + 2);
if (olen > 0) {
obuf[0] = ADB_PACKET;
obuf[1] = 0x40; /* polled data */
cuda_send_packet_to_host(s, obuf, olen + 2);
}
qemu_mod_timer(s->adb_poll_timer,
- qemu_get_clock(vm_clock) +
- (ticks_per_sec / CUDA_ADB_POLL_FREQ));
+ qemu_get_clock_ns(vm_clock) +
+ (get_ticks_per_sec() / CUDA_ADB_POLL_FREQ));
}
static void cuda_receive_packet(CUDAState *s,
s->autopoll = autopoll;
if (autopoll) {
qemu_mod_timer(s->adb_poll_timer,
- qemu_get_clock(vm_clock) +
- (ticks_per_sec / CUDA_ADB_POLL_FREQ));
+ qemu_get_clock_ns(vm_clock) +
+ (get_ticks_per_sec() / CUDA_ADB_POLL_FREQ));
} else {
qemu_del_timer(s->adb_poll_timer);
}
break;
case CUDA_SET_TIME:
ti = (((uint32_t)data[1]) << 24) + (((uint32_t)data[2]) << 16) + (((uint32_t)data[3]) << 8) + data[4];
- s->tick_offset = ti - (qemu_get_clock(vm_clock) / ticks_per_sec);
+ s->tick_offset = ti - (qemu_get_clock_ns(vm_clock) / get_ticks_per_sec());
obuf[0] = CUDA_PACKET;
obuf[1] = 0;
obuf[2] = 0;
cuda_send_packet_to_host(s, obuf, 3);
break;
case CUDA_GET_TIME:
- ti = s->tick_offset + (qemu_get_clock(vm_clock) / ticks_per_sec);
+ ti = s->tick_offset + (qemu_get_clock_ns(vm_clock) / get_ticks_per_sec());
obuf[0] = CUDA_PACKET;
obuf[1] = 0;
obuf[2] = 0;
{
uint8_t obuf[ADB_MAX_OUT_LEN + 2];
int olen;
- olen = adb_request(&adb_bus, obuf + 2, data + 1, len - 1);
+ olen = adb_request(&s->adb_bus, obuf + 2, data + 1, len - 1);
if (olen > 0) {
obuf[0] = ADB_PACKET;
obuf[1] = 0x00;
}
}
-static void cuda_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
+static void cuda_writew (void *opaque, hwaddr addr, uint32_t value)
{
}
-static void cuda_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
+static void cuda_writel (void *opaque, hwaddr addr, uint32_t value)
{
}
-static uint32_t cuda_readw (void *opaque, target_phys_addr_t addr)
+static uint32_t cuda_readw (void *opaque, hwaddr addr)
{
return 0;
}
-static uint32_t cuda_readl (void *opaque, target_phys_addr_t addr)
+static uint32_t cuda_readl (void *opaque, hwaddr addr)
{
return 0;
}
-static CPUWriteMemoryFunc *cuda_write[] = {
- &cuda_writeb,
- &cuda_writew,
- &cuda_writel,
-};
-
-static CPUReadMemoryFunc *cuda_read[] = {
- &cuda_readb,
- &cuda_readw,
- &cuda_readl,
+static const MemoryRegionOps cuda_ops = {
+ .old_mmio = {
+ .write = {
+ cuda_writeb,
+ cuda_writew,
+ cuda_writel,
+ },
+ .read = {
+ cuda_readb,
+ cuda_readw,
+ cuda_readl,
+ },
+ },
+ .endianness = DEVICE_NATIVE_ENDIAN,
};
-static void cuda_save_timer(QEMUFile *f, CUDATimer *s)
+static bool cuda_timer_exist(void *opaque, int version_id)
{
- qemu_put_be16s(f, &s->latch);
- qemu_put_be16s(f, &s->counter_value);
- qemu_put_sbe64s(f, &s->load_time);
- qemu_put_sbe64s(f, &s->next_irq_time);
- if (s->timer)
- qemu_put_timer(f, s->timer);
-}
+ CUDATimer *s = opaque;
-static void cuda_save(QEMUFile *f, void *opaque)
-{
- CUDAState *s = (CUDAState *)opaque;
-
- qemu_put_ubyte(f, s->b);
- qemu_put_ubyte(f, s->a);
- qemu_put_ubyte(f, s->dirb);
- qemu_put_ubyte(f, s->dira);
- qemu_put_ubyte(f, s->sr);
- qemu_put_ubyte(f, s->acr);
- qemu_put_ubyte(f, s->pcr);
- qemu_put_ubyte(f, s->ifr);
- qemu_put_ubyte(f, s->ier);
- qemu_put_ubyte(f, s->anh);
- qemu_put_sbe32s(f, &s->data_in_size);
- qemu_put_sbe32s(f, &s->data_in_index);
- qemu_put_sbe32s(f, &s->data_out_index);
- qemu_put_ubyte(f, s->autopoll);
- qemu_put_buffer(f, s->data_in, sizeof(s->data_in));
- qemu_put_buffer(f, s->data_out, sizeof(s->data_out));
- qemu_put_be32s(f, &s->tick_offset);
- cuda_save_timer(f, &s->timers[0]);
- cuda_save_timer(f, &s->timers[1]);
+ return s->timer != NULL;
}
-static void cuda_load_timer(QEMUFile *f, CUDATimer *s)
-{
- qemu_get_be16s(f, &s->latch);
- qemu_get_be16s(f, &s->counter_value);
- qemu_get_sbe64s(f, &s->load_time);
- qemu_get_sbe64s(f, &s->next_irq_time);
- if (s->timer)
- qemu_get_timer(f, s->timer);
-}
-
-static int cuda_load(QEMUFile *f, void *opaque, int version_id)
-{
- CUDAState *s = (CUDAState *)opaque;
-
- if (version_id != 1)
- return -EINVAL;
-
- s->b = qemu_get_ubyte(f);
- s->a = qemu_get_ubyte(f);
- s->dirb = qemu_get_ubyte(f);
- s->dira = qemu_get_ubyte(f);
- s->sr = qemu_get_ubyte(f);
- s->acr = qemu_get_ubyte(f);
- s->pcr = qemu_get_ubyte(f);
- s->ifr = qemu_get_ubyte(f);
- s->ier = qemu_get_ubyte(f);
- s->anh = qemu_get_ubyte(f);
- qemu_get_sbe32s(f, &s->data_in_size);
- qemu_get_sbe32s(f, &s->data_in_index);
- qemu_get_sbe32s(f, &s->data_out_index);
- s->autopoll = qemu_get_ubyte(f);
- qemu_get_buffer(f, s->data_in, sizeof(s->data_in));
- qemu_get_buffer(f, s->data_out, sizeof(s->data_out));
- qemu_get_be32s(f, &s->tick_offset);
- cuda_load_timer(f, &s->timers[0]);
- cuda_load_timer(f, &s->timers[1]);
+static const VMStateDescription vmstate_cuda_timer = {
+ .name = "cuda_timer",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT16(latch, CUDATimer),
+ VMSTATE_UINT16(counter_value, CUDATimer),
+ VMSTATE_INT64(load_time, CUDATimer),
+ VMSTATE_INT64(next_irq_time, CUDATimer),
+ VMSTATE_TIMER_TEST(timer, CUDATimer, cuda_timer_exist),
+ VMSTATE_END_OF_LIST()
+ }
+};
- return 0;
-}
+static const VMStateDescription vmstate_cuda = {
+ .name = "cuda",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT8(a, CUDAState),
+ VMSTATE_UINT8(b, CUDAState),
+ VMSTATE_UINT8(dira, CUDAState),
+ VMSTATE_UINT8(dirb, CUDAState),
+ VMSTATE_UINT8(sr, CUDAState),
+ VMSTATE_UINT8(acr, CUDAState),
+ VMSTATE_UINT8(pcr, CUDAState),
+ VMSTATE_UINT8(ifr, CUDAState),
+ VMSTATE_UINT8(ier, CUDAState),
+ VMSTATE_UINT8(anh, CUDAState),
+ VMSTATE_INT32(data_in_size, CUDAState),
+ VMSTATE_INT32(data_in_index, CUDAState),
+ VMSTATE_INT32(data_out_index, CUDAState),
+ VMSTATE_UINT8(autopoll, CUDAState),
+ VMSTATE_BUFFER(data_in, CUDAState),
+ VMSTATE_BUFFER(data_out, CUDAState),
+ VMSTATE_UINT32(tick_offset, CUDAState),
+ VMSTATE_STRUCT_ARRAY(timers, CUDAState, 2, 1,
+ vmstate_cuda_timer, CUDATimer),
+ VMSTATE_END_OF_LIST()
+ }
+};
-static void cuda_reset(void *opaque)
+static void cuda_reset(DeviceState *dev)
{
- CUDAState *s = opaque;
+ CUDAState *s = CUDA(dev);
s->b = 0;
s->a = 0;
set_counter(s, &s->timers[1], 0xffff);
}
-void cuda_init (int *cuda_mem_index, qemu_irq irq)
+static void cuda_realizefn(DeviceState *dev, Error **errp)
{
+ CUDAState *s = CUDA(dev);
struct tm tm;
- CUDAState *s = &cuda_state;
- s->irq = irq;
+ s->timers[0].timer = qemu_new_timer_ns(vm_clock, cuda_timer1, s);
+
+ qemu_get_timedate(&tm, 0);
+ s->tick_offset = (uint32_t)mktimegm(&tm) + RTC_OFFSET;
+
+ s->adb_poll_timer = qemu_new_timer_ns(vm_clock, cuda_adb_poll, s);
+}
+
+static void cuda_initfn(Object *obj)
+{
+ SysBusDevice *d = SYS_BUS_DEVICE(obj);
+ CUDAState *s = CUDA(obj);
+ int i;
+
+ memory_region_init_io(&s->mem, &cuda_ops, s, "cuda", 0x2000);
+ sysbus_init_mmio(d, &s->mem);
+ sysbus_init_irq(d, &s->irq);
+
+ for (i = 0; i < ARRAY_SIZE(s->timers); i++) {
+ s->timers[i].index = i;
+ }
+
+ qbus_create_inplace((BusState *)&s->adb_bus, TYPE_ADB_BUS, DEVICE(obj),
+ "adb.0");
+}
- s->timers[0].index = 0;
- s->timers[0].timer = qemu_new_timer(vm_clock, cuda_timer1, s);
+static void cuda_class_init(ObjectClass *oc, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(oc);
- s->timers[1].index = 1;
+ dc->realize = cuda_realizefn;
+ dc->reset = cuda_reset;
+ dc->vmsd = &vmstate_cuda;
+}
- qemu_get_timedate(&tm, RTC_OFFSET);
- s->tick_offset = mktimegm(&tm);
+static const TypeInfo cuda_type_info = {
+ .name = TYPE_CUDA,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(CUDAState),
+ .instance_init = cuda_initfn,
+ .class_init = cuda_class_init,
+};
- s->adb_poll_timer = qemu_new_timer(vm_clock, cuda_adb_poll, s);
- *cuda_mem_index = cpu_register_io_memory(0, cuda_read, cuda_write, s);
- register_savevm("cuda", -1, 1, cuda_save, cuda_load, s);
- qemu_register_reset(cuda_reset, s);
- cuda_reset(s);
+static void cuda_register_types(void)
+{
+ type_register_static(&cuda_type_info);
}
+
+type_init(cuda_register_types)