/*
- * QEMU CUDA support
- *
- * Copyright (c) 2004 Fabrice Bellard
- *
+ * QEMU PowerMac CUDA device support
+ *
+ * Copyright (c) 2004-2007 Fabrice Bellard
+ * Copyright (c) 2007 Jocelyn Mayer
+ *
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-#include "vl.h"
+#include "hw.h"
+#include "ppc_mac.h"
+#include "qemu-timer.h"
+#include "sysemu.h"
/* XXX: implement all timer modes */
#define RTC_OFFSET 2082844800
typedef struct CUDATimer {
- int index;
+ int index;
uint16_t latch;
uint16_t counter_value; /* counter value at load time */
int64_t load_time;
uint8_t anh; /* A-side data, no handshake */
CUDATimer timers[2];
-
+
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;
- SetIRQFunc *set_irq;
- int irq;
- void *irq_opaque;
+ qemu_irq irq;
uint8_t autopoll;
uint8_t data_in[128];
uint8_t data_out[16];
ADBBusState adb_bus;
static void cuda_update(CUDAState *s);
-static void cuda_receive_packet_from_host(CUDAState *s,
+static void cuda_receive_packet_from_host(CUDAState *s,
const uint8_t *data, int len);
-static void cuda_timer_update(CUDAState *s, CUDATimer *ti,
+static void cuda_timer_update(CUDAState *s, CUDATimer *ti,
int64_t current_time);
static void cuda_update_irq(CUDAState *s)
{
if (s->ifr & s->ier & (SR_INT | T1_INT)) {
- s->set_irq(s->irq_opaque, s->irq, 1);
+ qemu_irq_raise(s->irq);
} else {
- s->set_irq(s->irq_opaque, s->irq, 0);
+ qemu_irq_lower(s->irq);
}
}
int64_t d;
unsigned int counter;
- d = muldiv64(qemu_get_clock(vm_clock) - s->load_time,
+ d = muldiv64(qemu_get_clock(vm_clock) - s->load_time,
CUDA_TIMER_FREQ, ticks_per_sec);
if (s->index == 0) {
/* the timer goes down from latch to -1 (period of latch + 2) */
counter = (s->counter_value - d) & 0xffff;
} else {
counter = (d - (s->counter_value + 1)) % (s->latch + 2);
- counter = (s->latch - counter) & 0xffff;
+ counter = (s->latch - counter) & 0xffff;
}
} else {
counter = (s->counter_value - d) & 0xffff;
unsigned int counter;
/* current counter value */
- d = muldiv64(current_time - s->load_time,
+ d = muldiv64(current_time - s->load_time,
CUDA_TIMER_FREQ, 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;
} else {
counter = (d - (s->counter_value + 1)) % (s->latch + 2);
- counter = (s->latch - counter) & 0xffff;
+ counter = (s->latch - counter) & 0xffff;
}
-
+
/* Note: we consider the irq is raised on 0 */
if (counter == 0xffff) {
next_time = d + s->latch + 1;
}
#if 0
#ifdef DEBUG_CUDA
- printf("latch=%d counter=%" PRId64 " delta_next=%" PRId64 "\n",
+ printf("latch=%d counter=%" PRId64 " delta_next=%" PRId64 "\n",
s->latch, d, next_time - d);
#endif
#endif
- next_time = muldiv64(next_time, ticks_per_sec, CUDA_TIMER_FREQ) +
+ next_time = muldiv64(next_time, ticks_per_sec, CUDA_TIMER_FREQ) +
s->load_time;
if (next_time <= current_time)
next_time = current_time + 1;
return next_time;
}
-static void cuda_timer_update(CUDAState *s, CUDATimer *ti,
+static void cuda_timer_update(CUDAState *s, CUDATimer *ti,
int64_t current_time)
{
if (!ti->timer)
break;
case 13:
val = s->ifr;
- if (s->ifr & s->ier)
+ if (s->ifr & s->ier)
val |= 0x80;
break;
case 14:
static void cuda_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
{
CUDAState *s = opaque;
-
+
addr = (addr >> 9) & 0xf;
#ifdef DEBUG_CUDA
printf("cuda: write: reg=0x%x val=%02x\n", addr, val);
cuda_update_irq(s);
} else {
if (!(s->last_b & TIP)) {
- /* handle end of host to cuda transfert */
+ /* handle end of host to cuda transfer */
packet_received = (s->data_out_index > 0);
- /* always an IRQ at the end of transfert */
+ /* always an IRQ at the end of transfer */
s->ifr |= SR_INT;
cuda_update_irq(s);
}
}
}
-static void cuda_send_packet_to_host(CUDAState *s,
+static void cuda_send_packet_to_host(CUDAState *s,
const uint8_t *data, int len)
{
#ifdef DEBUG_CUDA_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) +
+ qemu_mod_timer(s->adb_poll_timer,
+ qemu_get_clock(vm_clock) +
(ticks_per_sec / CUDA_ADB_POLL_FREQ));
}
-static void cuda_receive_packet(CUDAState *s,
+static void cuda_receive_packet(CUDAState *s,
const uint8_t *data, int len)
{
uint8_t obuf[16];
if (autopoll != s->autopoll) {
s->autopoll = autopoll;
if (autopoll) {
- qemu_mod_timer(s->adb_poll_timer,
- qemu_get_clock(vm_clock) +
+ qemu_mod_timer(s->adb_poll_timer,
+ qemu_get_clock(vm_clock) +
(ticks_per_sec / CUDA_ADB_POLL_FREQ));
} else {
qemu_del_timer(s->adb_poll_timer);
cuda_send_packet_to_host(s, obuf, 2);
qemu_system_shutdown_request();
break;
+ case CUDA_RESET_SYSTEM:
+ obuf[0] = CUDA_PACKET;
+ obuf[1] = 0;
+ cuda_send_packet_to_host(s, obuf, 2);
+ qemu_system_reset_request();
+ break;
default:
break;
}
}
-static void cuda_receive_packet_from_host(CUDAState *s,
+static void cuda_receive_packet_from_host(CUDAState *s,
const uint8_t *data, int len)
{
#ifdef DEBUG_CUDA_PACKET
&cuda_readl,
};
-int cuda_init(SetIRQFunc *set_irq, void *irq_opaque, int irq)
+void cuda_init (int *cuda_mem_index, qemu_irq irq)
{
CUDAState *s = &cuda_state;
- int cuda_mem_index;
- s->set_irq = set_irq;
- s->irq_opaque = irq_opaque;
s->irq = irq;
s->timers[0].index = 0;
set_counter(s, &s->timers[1], 0xffff);
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);
- return cuda_mem_index;
+ *cuda_mem_index = cpu_register_io_memory(0, cuda_read, cuda_write, s);
}