Commit 267002cd28318c6ca246205c9b8c42c3cca48960

Authored by bellard
1 parent 63066f4f

CUDA + ADB support


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@881 c046a42c-6fe2-441c-8c8c-71466251a162
hw/adb.c 0 → 100644
  1 +/*
  2 + * QEMU ADB support
  3 + *
  4 + * Copyright (c) 2004 Fabrice Bellard
  5 + *
  6 + * Permission is hereby granted, free of charge, to any person obtaining a copy
  7 + * of this software and associated documentation files (the "Software"), to deal
  8 + * in the Software without restriction, including without limitation the rights
  9 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 + * copies of the Software, and to permit persons to whom the Software is
  11 + * furnished to do so, subject to the following conditions:
  12 + *
  13 + * The above copyright notice and this permission notice shall be included in
  14 + * all copies or substantial portions of the Software.
  15 + *
  16 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 + * THE SOFTWARE.
  23 + */
  24 +#include "vl.h"
  25 +
  26 +/* ADB commands */
  27 +#define ADB_BUSRESET 0x00
  28 +#define ADB_FLUSH 0x01
  29 +#define ADB_WRITEREG 0x08
  30 +#define ADB_READREG 0x0c
  31 +
  32 +/* ADB device commands */
  33 +#define ADB_CMD_SELF_TEST 0xff
  34 +#define ADB_CMD_CHANGE_ID 0xfe
  35 +#define ADB_CMD_CHANGE_ID_AND_ACT 0xfd
  36 +#define ADB_CMD_CHANGE_ID_AND_ENABLE 0x00
  37 +
  38 +/* ADB default device IDs (upper 4 bits of ADB command byte) */
  39 +#define ADB_DONGLE 1
  40 +#define ADB_KEYBOARD 2
  41 +#define ADB_MOUSE 3
  42 +#define ADB_TABLET 4
  43 +#define ADB_MODEM 5
  44 +#define ADB_MISC 7
  45 +
  46 +#define ADB_RET_OK 0
  47 +#define ADB_RET_INUSE 1
  48 +#define ADB_RET_NOTPRESENT 2
  49 +#define ADB_RET_TIMEOUT 3
  50 +#define ADB_RET_UNEXPECTED_RESULT 4
  51 +#define ADB_RET_REQUEST_ERROR 5
  52 +#define ADB_RET_BUS_ERROR 6
  53 +
  54 +
  55 +static void adb_send_packet1(ADBBusState *s, uint8_t reply)
  56 +{
  57 + adb_send_packet(s, &reply, 1);
  58 +}
  59 +
  60 +void adb_receive_packet(ADBBusState *s, const uint8_t *buf, int len)
  61 +{
  62 + ADBDevice *d;
  63 + int devaddr, cmd, i;
  64 + uint8_t obuf[4];
  65 +
  66 + cmd = buf[1] & 0xf;
  67 + devaddr = buf[1] >> 4;
  68 + if (buf[1] == ADB_BUSRESET) {
  69 + obuf[0] = 0x00;
  70 + obuf[1] = 0x00;
  71 + adb_send_packet(s, obuf, 2);
  72 + return;
  73 + }
  74 + if (cmd == ADB_FLUSH) {
  75 + obuf[0] = 0x00;
  76 + obuf[1] = 0x00;
  77 + adb_send_packet(s, obuf, 2);
  78 + return;
  79 + }
  80 +
  81 + for(i = 0; i < s->nb_devices; i++) {
  82 + d = &s->devices[i];
  83 + if (d->devaddr == devaddr) {
  84 + d->receive_packet(d, buf, len);
  85 + return;
  86 + }
  87 + }
  88 + adb_send_packet1(s, ADB_RET_NOTPRESENT);
  89 +}
  90 +
  91 +ADBDevice *adb_register_device(ADBBusState *s, int devaddr,
  92 + ADBDeviceReceivePacket *receive_packet,
  93 + void *opaque)
  94 +{
  95 + ADBDevice *d;
  96 + if (s->nb_devices >= MAX_ADB_DEVICES)
  97 + return NULL;
  98 + d = &s->devices[s->nb_devices++];
  99 + d->bus = s;
  100 + d->devaddr = devaddr;
  101 + d->receive_packet = receive_packet;
  102 + d->opaque = opaque;
  103 + return d;
  104 +}
  105 +
  106 +/***************************************************************/
  107 +/* Keyboard ADB device */
  108 +
  109 +static const uint8_t pc_to_adb_keycode[256] = {
  110 + 0, 53, 18, 19, 20, 21, 23, 22, 26, 28, 25, 29, 27, 24, 51, 48,
  111 + 12, 13, 14, 15, 17, 16, 32, 34, 31, 35, 33, 30, 36, 54, 0, 1,
  112 + 2, 3, 5, 4, 38, 40, 37, 41, 39, 50, 56, 42, 6, 7, 8, 9,
  113 + 11, 45, 46, 43, 47, 44,123, 67, 58, 49, 57,122,120, 99,118, 96,
  114 + 97, 98,100,101,109, 71,107, 89, 91, 92, 78, 86, 87, 88, 69, 83,
  115 + 84, 85, 82, 65, 0, 0, 10,103,111, 0, 0, 0, 0, 0, 0, 0,
  116 + 76,125, 75,105,124,110,115, 62,116, 59, 60,119, 61,121,114,117,
  117 + 0, 0, 0, 0,127, 81, 0,113, 0, 0, 0, 0, 95, 55, 0, 0,
  118 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  119 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  120 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  121 + 0, 0, 0, 0, 0, 94, 0, 93, 0, 0, 0, 0, 0, 0,104,102,
  122 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  123 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  124 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  125 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  126 +};
  127 +
  128 +static void adb_kbd_put_keycode(void *opaque, int keycode)
  129 +{
  130 + static int ext_keycode;
  131 + ADBDevice *d = opaque;
  132 + uint8_t buf[4];
  133 + int adb_keycode;
  134 +
  135 + if (keycode == 0xe0) {
  136 + ext_keycode = 1;
  137 + } else {
  138 +
  139 + if (ext_keycode)
  140 + adb_keycode = pc_to_adb_keycode[keycode | 0x80];
  141 + else
  142 + adb_keycode = pc_to_adb_keycode[keycode & 0x7f];
  143 +
  144 + buf[0] = 0x40;
  145 + buf[1] = (d->devaddr << 4) | 0x0c;
  146 + buf[2] = adb_keycode | (keycode & 0x80);
  147 + buf[3] = 0xff;
  148 + adb_send_packet(d->bus, buf, 4);
  149 + ext_keycode = 0;
  150 + }
  151 +}
  152 +
  153 +static void adb_kbd_receive_packet(ADBDevice *d, const uint8_t *buf, int len)
  154 +{
  155 + int cmd, reg;
  156 + uint8_t obuf[4];
  157 +
  158 + cmd = buf[0] & 0xc;
  159 + reg = buf[0] & 0x3;
  160 + switch(cmd) {
  161 + case ADB_WRITEREG:
  162 + switch(reg) {
  163 + case 2:
  164 + /* LED status */
  165 + adb_send_packet1(d->bus, ADB_RET_OK);
  166 + break;
  167 + case 3:
  168 + switch(buf[2]) {
  169 + case ADB_CMD_SELF_TEST:
  170 + adb_send_packet1(d->bus, ADB_RET_OK);
  171 + break;
  172 + case ADB_CMD_CHANGE_ID:
  173 + case ADB_CMD_CHANGE_ID_AND_ACT:
  174 + case ADB_CMD_CHANGE_ID_AND_ENABLE:
  175 + d->devaddr = buf[1] & 0xf;
  176 + adb_send_packet1(d->bus, ADB_RET_OK);
  177 + break;
  178 + default:
  179 + /* XXX: check this */
  180 + d->devaddr = buf[1] & 0xf;
  181 + d->handler = buf[2];
  182 + adb_send_packet1(d->bus, ADB_RET_OK);
  183 + break;
  184 + }
  185 + }
  186 + break;
  187 + case ADB_READREG:
  188 + switch(reg) {
  189 + case 1:
  190 + adb_send_packet1(d->bus, ADB_RET_OK);
  191 + break;
  192 + case 2:
  193 + obuf[0] = ADB_RET_OK;
  194 + obuf[1] = 0x00; /* XXX: check this */
  195 + obuf[2] = 0x07; /* led status */
  196 + adb_send_packet(d->bus, obuf, 3);
  197 + break;
  198 + case 3:
  199 + obuf[0] = ADB_RET_OK;
  200 + obuf[1] = d->handler;
  201 + obuf[2] = d->devaddr;
  202 + adb_send_packet(d->bus, obuf, 3);
  203 + break;
  204 + }
  205 + break;
  206 + }
  207 +}
  208 +
  209 +void adb_kbd_init(ADBBusState *bus)
  210 +{
  211 + ADBDevice *d;
  212 +
  213 + d = adb_register_device(bus, ADB_KEYBOARD, adb_kbd_receive_packet, NULL);
  214 + qemu_add_kbd_event_handler(adb_kbd_put_keycode, d);
  215 +}
  216 +
  217 +/***************************************************************/
  218 +/* Mouse ADB device */
  219 +
  220 +static void adb_mouse_event(void *opaque,
  221 + int dx1, int dy1, int dz1, int buttons_state)
  222 +{
  223 + ADBDevice *d = opaque;
  224 + uint8_t buf[4];
  225 + int dx, dy;
  226 +
  227 + dx = dx1;
  228 + if (dx < -63)
  229 + dx = -63;
  230 + else if (dx > 63)
  231 + dx = 63;
  232 +
  233 + dy = dy1;
  234 + if (dy < -63)
  235 + dy = -63;
  236 + else if (dy > 63)
  237 + dy = 63;
  238 +
  239 + dx &= 0x7f;
  240 + dy &= 0x7f;
  241 +
  242 + if (buttons_state & MOUSE_EVENT_LBUTTON)
  243 + dy |= 0x80;
  244 + if (buttons_state & MOUSE_EVENT_RBUTTON)
  245 + dx |= 0x80;
  246 +
  247 + buf[0] = 0x40;
  248 + buf[1] = (d->devaddr << 4) | 0x0c;
  249 + buf[2] = dy;
  250 + buf[3] = dx;
  251 + adb_send_packet(d->bus, buf, 4);
  252 +}
  253 +
  254 +static void adb_mouse_receive_packet(ADBDevice *d, const uint8_t *buf, int len)
  255 +{
  256 + int cmd, reg;
  257 + uint8_t obuf[4];
  258 +
  259 + cmd = buf[0] & 0xc;
  260 + reg = buf[0] & 0x3;
  261 + switch(cmd) {
  262 + case ADB_WRITEREG:
  263 + switch(reg) {
  264 + case 2:
  265 + adb_send_packet1(d->bus, ADB_RET_OK);
  266 + break;
  267 + case 3:
  268 + switch(buf[2]) {
  269 + case ADB_CMD_SELF_TEST:
  270 + adb_send_packet1(d->bus, ADB_RET_OK);
  271 + break;
  272 + case ADB_CMD_CHANGE_ID:
  273 + case ADB_CMD_CHANGE_ID_AND_ACT:
  274 + case ADB_CMD_CHANGE_ID_AND_ENABLE:
  275 + d->devaddr = buf[1] & 0xf;
  276 + adb_send_packet1(d->bus, ADB_RET_OK);
  277 + break;
  278 + default:
  279 + /* XXX: check this */
  280 + d->devaddr = buf[1] & 0xf;
  281 + adb_send_packet1(d->bus, ADB_RET_OK);
  282 + break;
  283 + }
  284 + }
  285 + break;
  286 + case ADB_READREG:
  287 + switch(reg) {
  288 + case 1:
  289 + adb_send_packet1(d->bus, ADB_RET_OK);
  290 + break;
  291 + case 3:
  292 + obuf[0] = ADB_RET_OK;
  293 + obuf[1] = d->handler;
  294 + obuf[2] = d->devaddr;
  295 + adb_send_packet(d->bus, obuf, 3);
  296 + break;
  297 + }
  298 + break;
  299 + }
  300 +}
  301 +
  302 +void adb_mouse_init(ADBBusState *bus)
  303 +{
  304 + ADBDevice *d;
  305 +
  306 + d = adb_register_device(bus, ADB_MOUSE, adb_mouse_receive_packet, NULL);
  307 + qemu_add_mouse_event_handler(adb_mouse_event, d);
  308 +}
... ...
hw/cuda.c 0 → 100644
  1 +/*
  2 + * QEMU CUDA support
  3 + *
  4 + * Copyright (c) 2004 Fabrice Bellard
  5 + *
  6 + * Permission is hereby granted, free of charge, to any person obtaining a copy
  7 + * of this software and associated documentation files (the "Software"), to deal
  8 + * in the Software without restriction, including without limitation the rights
  9 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 + * copies of the Software, and to permit persons to whom the Software is
  11 + * furnished to do so, subject to the following conditions:
  12 + *
  13 + * The above copyright notice and this permission notice shall be included in
  14 + * all copies or substantial portions of the Software.
  15 + *
  16 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 + * THE SOFTWARE.
  23 + */
  24 +#include "vl.h"
  25 +
  26 +/* Bits in B data register: all active low */
  27 +#define TREQ 0x08 /* Transfer request (input) */
  28 +#define TACK 0x10 /* Transfer acknowledge (output) */
  29 +#define TIP 0x20 /* Transfer in progress (output) */
  30 +
  31 +/* Bits in ACR */
  32 +#define SR_CTRL 0x1c /* Shift register control bits */
  33 +#define SR_EXT 0x0c /* Shift on external clock */
  34 +#define SR_OUT 0x10 /* Shift out if 1 */
  35 +
  36 +/* Bits in IFR and IER */
  37 +#define IER_SET 0x80 /* set bits in IER */
  38 +#define IER_CLR 0 /* clear bits in IER */
  39 +#define SR_INT 0x04 /* Shift register full/empty */
  40 +#define T1_INT 0x40 /* Timer 1 interrupt */
  41 +
  42 +/* Bits in ACR */
  43 +#define T1MODE 0xc0 /* Timer 1 mode */
  44 +#define T1MODE_CONT 0x40 /* continuous interrupts */
  45 +
  46 +/* commands (1st byte) */
  47 +#define ADB_PACKET 0
  48 +#define CUDA_PACKET 1
  49 +#define ERROR_PACKET 2
  50 +#define TIMER_PACKET 3
  51 +#define POWER_PACKET 4
  52 +#define MACIIC_PACKET 5
  53 +#define PMU_PACKET 6
  54 +
  55 +
  56 +/* CUDA commands (2nd byte) */
  57 +#define CUDA_WARM_START 0x0
  58 +#define CUDA_AUTOPOLL 0x1
  59 +#define CUDA_GET_6805_ADDR 0x2
  60 +#define CUDA_GET_TIME 0x3
  61 +#define CUDA_GET_PRAM 0x7
  62 +#define CUDA_SET_6805_ADDR 0x8
  63 +#define CUDA_SET_TIME 0x9
  64 +#define CUDA_POWERDOWN 0xa
  65 +#define CUDA_POWERUP_TIME 0xb
  66 +#define CUDA_SET_PRAM 0xc
  67 +#define CUDA_MS_RESET 0xd
  68 +#define CUDA_SEND_DFAC 0xe
  69 +#define CUDA_BATTERY_SWAP_SENSE 0x10
  70 +#define CUDA_RESET_SYSTEM 0x11
  71 +#define CUDA_SET_IPL 0x12
  72 +#define CUDA_FILE_SERVER_FLAG 0x13
  73 +#define CUDA_SET_AUTO_RATE 0x14
  74 +#define CUDA_GET_AUTO_RATE 0x16
  75 +#define CUDA_SET_DEVICE_LIST 0x19
  76 +#define CUDA_GET_DEVICE_LIST 0x1a
  77 +#define CUDA_SET_ONE_SECOND_MODE 0x1b
  78 +#define CUDA_SET_POWER_MESSAGES 0x21
  79 +#define CUDA_GET_SET_IIC 0x22
  80 +#define CUDA_WAKEUP 0x23
  81 +#define CUDA_TIMER_TICKLE 0x24
  82 +#define CUDA_COMBINED_FORMAT_IIC 0x25
  83 +
  84 +#define CUDA_TIMER_FREQ (4700000 / 6)
  85 +
  86 +typedef struct CUDATimer {
  87 + unsigned int latch;
  88 + uint16_t counter_value; /* counter value at load time */
  89 + int64_t load_time;
  90 + int64_t next_irq_time;
  91 + QEMUTimer *timer;
  92 +} CUDATimer;
  93 +
  94 +typedef struct CUDAState {
  95 + /* cuda registers */
  96 + uint8_t b; /* B-side data */
  97 + uint8_t a; /* A-side data */
  98 + uint8_t dirb; /* B-side direction (1=output) */
  99 + uint8_t dira; /* A-side direction (1=output) */
  100 + uint8_t sr; /* Shift register */
  101 + uint8_t acr; /* Auxiliary control register */
  102 + uint8_t pcr; /* Peripheral control register */
  103 + uint8_t ifr; /* Interrupt flag register */
  104 + uint8_t ier; /* Interrupt enable register */
  105 + uint8_t anh; /* A-side data, no handshake */
  106 +
  107 + CUDATimer timers[2];
  108 +
  109 + uint8_t last_b; /* last value of B register */
  110 + uint8_t last_acr; /* last value of B register */
  111 +
  112 + int data_in_size;
  113 + int data_in_index;
  114 + int data_out_index;
  115 +
  116 + int irq;
  117 + uint8_t autopoll;
  118 + uint8_t data_in[128];
  119 + uint8_t data_out[16];
  120 +} CUDAState;
  121 +
  122 +static CUDAState cuda_state;
  123 +ADBBusState adb_bus;
  124 +
  125 +static void cuda_update(CUDAState *s);
  126 +static void cuda_receive_packet_from_host(CUDAState *s,
  127 + const uint8_t *data, int len);
  128 +
  129 +static void cuda_update_irq(CUDAState *s)
  130 +{
  131 + if (s->ifr & s->ier & SR_INT) {
  132 + pic_set_irq(s->irq, 1);
  133 + } else {
  134 + pic_set_irq(s->irq, 0);
  135 + }
  136 +}
  137 +
  138 +static unsigned int get_counter(CUDATimer *s)
  139 +{
  140 + int64_t d;
  141 + unsigned int counter;
  142 +
  143 + d = muldiv64(qemu_get_clock(vm_clock) - s->load_time,
  144 + CUDA_TIMER_FREQ, ticks_per_sec);
  145 + if (d <= s->counter_value) {
  146 + counter = d;
  147 + } else {
  148 + counter = s->latch - 1 - ((d - s->counter_value) % s->latch);
  149 + }
  150 + return counter;
  151 +}
  152 +
  153 +static void set_counter(CUDATimer *s, unsigned int val)
  154 +{
  155 + s->load_time = qemu_get_clock(vm_clock);
  156 + s->counter_value = val;
  157 +}
  158 +
  159 +static int64_t get_next_irq_time(CUDATimer *s, int64_t current_time)
  160 +{
  161 + int64_t d, next_time, base;
  162 + /* current counter value */
  163 + d = muldiv64(current_time - s->load_time,
  164 + CUDA_TIMER_FREQ, ticks_per_sec);
  165 + if (d <= s->counter_value) {
  166 + next_time = s->counter_value + 1;
  167 + } else {
  168 + base = ((d - s->counter_value) % s->latch);
  169 + base = (base * s->latch) + s->counter_value;
  170 + next_time = base + s->latch;
  171 + }
  172 + next_time = muldiv64(next_time, ticks_per_sec, CUDA_TIMER_FREQ) +
  173 + s->load_time;
  174 + if (next_time <= current_time)
  175 + next_time = current_time + 1;
  176 + return next_time;
  177 +}
  178 +
  179 +static void cuda_timer1(void *opaque)
  180 +{
  181 + CUDAState *s = opaque;
  182 + CUDATimer *ti = &s->timers[0];
  183 +
  184 + ti->next_irq_time = get_next_irq_time(ti, ti->next_irq_time);
  185 + qemu_mod_timer(ti->timer, ti->next_irq_time);
  186 + s->ifr |= T1_INT;
  187 + cuda_update_irq(s);
  188 +}
  189 +
  190 +static uint32_t cuda_readb(void *opaque, target_phys_addr_t addr)
  191 +{
  192 + CUDAState *s = opaque;
  193 + uint32_t val;
  194 +
  195 + addr = (addr >> 9) & 0xf;
  196 + switch(addr) {
  197 + case 0:
  198 + val = s->b;
  199 + break;
  200 + case 1:
  201 + val = s->a;
  202 + break;
  203 + case 2:
  204 + val = s->dirb;
  205 + break;
  206 + case 3:
  207 + val = s->dira;
  208 + break;
  209 + case 4:
  210 + val = get_counter(&s->timers[0]) & 0xff;
  211 + s->ifr &= ~T1_INT;
  212 + cuda_update_irq(s);
  213 + break;
  214 + case 5:
  215 + val = get_counter(&s->timers[0]) >> 8;
  216 + s->ifr &= ~T1_INT;
  217 + cuda_update_irq(s);
  218 + break;
  219 + case 6:
  220 + val = s->timers[0].latch & 0xff;
  221 + break;
  222 + case 7:
  223 + val = (s->timers[0].latch >> 8) & 0xff;
  224 + break;
  225 + case 8:
  226 + val = get_counter(&s->timers[1]) & 0xff;
  227 + break;
  228 + case 9:
  229 + val = get_counter(&s->timers[1]) >> 8;
  230 + break;
  231 + case 10:
  232 + if (s->data_in_index < s->data_in_size) {
  233 + val = s->data_in[s->data_in_index];
  234 + } else {
  235 + val = 0;
  236 + }
  237 + break;
  238 + case 11:
  239 + val = s->acr;
  240 + break;
  241 + case 12:
  242 + val = s->pcr;
  243 + break;
  244 + case 13:
  245 + val = s->ifr;
  246 + break;
  247 + case 14:
  248 + val = s->ier;
  249 + break;
  250 + default:
  251 + case 15:
  252 + val = s->anh;
  253 + break;
  254 + }
  255 +#ifdef DEBUG_CUDA
  256 + printf("cuda: read: reg=0x%x val=%02x\n", addr, val);
  257 +#endif
  258 + return val;
  259 +}
  260 +
  261 +static void cuda_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
  262 +{
  263 + CUDAState *s = opaque;
  264 +
  265 + addr = (addr >> 9) & 0xf;
  266 +#ifdef DEBUG_CUDA
  267 + printf("cuda: write: reg=0x%x val=%02x\n", addr, val);
  268 +#endif
  269 +
  270 + switch(addr) {
  271 + case 0:
  272 + s->b = val;
  273 + cuda_update(s);
  274 + break;
  275 + case 1:
  276 + s->a = val;
  277 + break;
  278 + case 2:
  279 + s->dirb = val;
  280 + break;
  281 + case 3:
  282 + s->dira = val;
  283 + break;
  284 + case 4:
  285 + val = val | (get_counter(&s->timers[0]) & 0xff00);
  286 + set_counter(&s->timers[0], val);
  287 + break;
  288 + case 5:
  289 + val = (val << 8) | (get_counter(&s->timers[0]) & 0xff);
  290 + set_counter(&s->timers[0], val);
  291 + break;
  292 + case 6:
  293 + s->timers[0].latch = (s->timers[0].latch & 0xff00) | val;
  294 + break;
  295 + case 7:
  296 + s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8);
  297 + break;
  298 + case 8:
  299 + val = val | (get_counter(&s->timers[1]) & 0xff00);
  300 + set_counter(&s->timers[1], val);
  301 + break;
  302 + case 9:
  303 + val = (val << 8) | (get_counter(&s->timers[1]) & 0xff);
  304 + set_counter(&s->timers[1], val);
  305 + break;
  306 + case 10:
  307 + s->sr = val;
  308 + break;
  309 + case 11:
  310 + s->acr = val;
  311 + if ((s->acr & T1MODE) == T1MODE_CONT) {
  312 + if ((s->last_acr & T1MODE) != T1MODE_CONT) {
  313 + CUDATimer *ti = &s->timers[0];
  314 + /* activate timer interrupt */
  315 + ti->next_irq_time = get_next_irq_time(ti, qemu_get_clock(vm_clock));
  316 + qemu_mod_timer(ti->timer, ti->next_irq_time);
  317 + }
  318 + } else {
  319 + if ((s->last_acr & T1MODE) == T1MODE_CONT) {
  320 + CUDATimer *ti = &s->timers[0];
  321 + qemu_del_timer(ti->timer);
  322 + }
  323 + }
  324 + cuda_update(s);
  325 + break;
  326 + case 12:
  327 + s->pcr = val;
  328 + break;
  329 + case 13:
  330 + /* reset bits */
  331 + s->ifr &= ~val;
  332 + cuda_update_irq(s);
  333 + break;
  334 + case 14:
  335 + if (val & IER_SET) {
  336 + /* set bits */
  337 + s->ier |= val & 0x7f;
  338 + } else {
  339 + /* reset bits */
  340 + s->ier &= ~val;
  341 + }
  342 + cuda_update_irq(s);
  343 + break;
  344 + default:
  345 + case 15:
  346 + s->anh = val;
  347 + break;
  348 + }
  349 +}
  350 +
  351 +/* NOTE: TIP and TREQ are negated */
  352 +static void cuda_update(CUDAState *s)
  353 +{
  354 + if (s->data_in_index < s->data_in_size) {
  355 + /* data input */
  356 + if (!(s->b & TIP) &&
  357 + (s->b & (TACK | TIP)) != (s->last_b & (TACK | TIP))) {
  358 + s->sr = s->data_in[s->data_in_index++];
  359 + s->ifr |= SR_INT;
  360 + cuda_update_irq(s);
  361 + }
  362 + }
  363 + if (s->data_in_index < s->data_in_size) {
  364 + /* there is some data to read */
  365 + s->b = (s->b & ~TREQ);
  366 + } else {
  367 + s->b = (s->b | TREQ);
  368 + }
  369 +
  370 + if (s->acr & SR_OUT) {
  371 + /* data output */
  372 + if (!(s->b & TIP) &&
  373 + (s->b & (TACK | TIP)) != (s->last_b & (TACK | TIP))) {
  374 + if (s->data_out_index < sizeof(s->data_out)) {
  375 + s->data_out[s->data_out_index++] = s->sr;
  376 + }
  377 + s->ifr |= SR_INT;
  378 + cuda_update_irq(s);
  379 + }
  380 + }
  381 +
  382 + /* check end of data output */
  383 + if (!(s->acr & SR_OUT) && (s->last_acr & SR_OUT)) {
  384 + if (s->data_out_index > 0)
  385 + cuda_receive_packet_from_host(s, s->data_out, s->data_out_index);
  386 + s->data_out_index = 0;
  387 + }
  388 + s->last_acr = s->acr;
  389 + s->last_b = s->b;
  390 +}
  391 +
  392 +static void cuda_send_packet_to_host(CUDAState *s,
  393 + const uint8_t *data, int len)
  394 +{
  395 + memcpy(s->data_in, data, len);
  396 + s->data_in_size = len;
  397 + s->data_in_index = 0;
  398 + cuda_update(s);
  399 + s->ifr |= SR_INT;
  400 + cuda_update_irq(s);
  401 +}
  402 +
  403 +void adb_send_packet(ADBBusState *bus, const uint8_t *buf, int len)
  404 +{
  405 + CUDAState *s = &cuda_state;
  406 + uint8_t data[16];
  407 +
  408 + memcpy(data + 1, buf, len);
  409 + data[0] = ADB_PACKET;
  410 + cuda_send_packet_to_host(s, data, len + 1);
  411 +}
  412 +
  413 +static void cuda_receive_packet(CUDAState *s,
  414 + const uint8_t *data, int len)
  415 +{
  416 + uint8_t obuf[16];
  417 + int ti;
  418 +
  419 + switch(data[0]) {
  420 + case CUDA_AUTOPOLL:
  421 + s->autopoll = data[1];
  422 + obuf[0] = CUDA_PACKET;
  423 + obuf[1] = data[1];
  424 + cuda_send_packet_to_host(s, obuf, 2);
  425 + break;
  426 + case CUDA_GET_TIME:
  427 + /* XXX: add time support ? */
  428 + ti = 0;
  429 + obuf[0] = CUDA_PACKET;
  430 + obuf[1] = 0;
  431 + obuf[2] = 0;
  432 + obuf[3] = ti >> 24;
  433 + obuf[4] = ti >> 16;
  434 + obuf[5] = ti >> 8;
  435 + obuf[6] = ti;
  436 + cuda_send_packet_to_host(s, obuf, 7);
  437 + break;
  438 + case CUDA_SET_TIME:
  439 + case CUDA_FILE_SERVER_FLAG:
  440 + case CUDA_SET_DEVICE_LIST:
  441 + case CUDA_SET_AUTO_RATE:
  442 + case CUDA_SET_POWER_MESSAGES:
  443 + obuf[0] = CUDA_PACKET;
  444 + obuf[1] = 0;
  445 + cuda_send_packet_to_host(s, obuf, 2);
  446 + break;
  447 + default:
  448 + break;
  449 + }
  450 +}
  451 +
  452 +static void cuda_receive_packet_from_host(CUDAState *s,
  453 + const uint8_t *data, int len)
  454 +{
  455 + switch(data[0]) {
  456 + case ADB_PACKET:
  457 + adb_receive_packet(&adb_bus, data + 1, len - 1);
  458 + break;
  459 + case CUDA_PACKET:
  460 + cuda_receive_packet(s, data + 1, len - 1);
  461 + break;
  462 + }
  463 +}
  464 +
  465 +static void cuda_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
  466 +{
  467 +}
  468 +
  469 +static void cuda_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
  470 +{
  471 +}
  472 +
  473 +static uint32_t cuda_readw (void *opaque, target_phys_addr_t addr)
  474 +{
  475 + return 0;
  476 +}
  477 +
  478 +static uint32_t cuda_readl (void *opaque, target_phys_addr_t addr)
  479 +{
  480 + return 0;
  481 +}
  482 +
  483 +static CPUWriteMemoryFunc *cuda_write[] = {
  484 + &cuda_writeb,
  485 + &cuda_writew,
  486 + &cuda_writel,
  487 +};
  488 +
  489 +static CPUReadMemoryFunc *cuda_read[] = {
  490 + &cuda_readb,
  491 + &cuda_readw,
  492 + &cuda_readl,
  493 +};
  494 +
  495 +int cuda_init(void)
  496 +{
  497 + CUDAState *s = &cuda_state;
  498 + int cuda_mem_index;
  499 +
  500 + s->timers[0].latch = 0x10000;
  501 + set_counter(&s->timers[0], 0xffff);
  502 + s->timers[0].timer = qemu_new_timer(vm_clock, cuda_timer1, s);
  503 + s->timers[1].latch = 0x10000;
  504 + set_counter(&s->timers[1], 0xffff);
  505 + cuda_mem_index = cpu_register_io_memory(0, cuda_read, cuda_write, s);
  506 + return cuda_mem_index;
  507 +}
... ...
hw/ppc_chrp.c
... ... @@ -26,6 +26,86 @@
26 26 #define BIOS_FILENAME "ppc_rom.bin"
27 27 #define NVRAM_SIZE 0x2000
28 28  
  29 +/* MacIO devices (mapped inside the MacIO address space): CUDA, DBDMA,
  30 + NVRAM (not implemented). */
  31 +
  32 +static int dbdma_mem_index;
  33 +static int cuda_mem_index;
  34 +
  35 +/* DBDMA: currently no op - should suffice right now */
  36 +
  37 +static void dbdma_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
  38 +{
  39 +}
  40 +
  41 +static void dbdma_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
  42 +{
  43 +}
  44 +
  45 +static void dbdma_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
  46 +{
  47 +}
  48 +
  49 +static uint32_t dbdma_readb (void *opaque, target_phys_addr_t addr)
  50 +{
  51 + return 0;
  52 +}
  53 +
  54 +static uint32_t dbdma_readw (void *opaque, target_phys_addr_t addr)
  55 +{
  56 + return 0;
  57 +}
  58 +
  59 +static uint32_t dbdma_readl (void *opaque, target_phys_addr_t addr)
  60 +{
  61 + return 0;
  62 +}
  63 +
  64 +static CPUWriteMemoryFunc *dbdma_write[] = {
  65 + &dbdma_writeb,
  66 + &dbdma_writew,
  67 + &dbdma_writel,
  68 +};
  69 +
  70 +static CPUReadMemoryFunc *dbdma_read[] = {
  71 + &dbdma_readb,
  72 + &dbdma_readw,
  73 + &dbdma_readl,
  74 +};
  75 +
  76 +static void macio_map(PCIDevice *pci_dev, int region_num,
  77 + uint32_t addr, uint32_t size, int type)
  78 +{
  79 + cpu_register_physical_memory(addr + 0x08000, 0x1000, dbdma_mem_index);
  80 + cpu_register_physical_memory(addr + 0x16000, 0x2000, cuda_mem_index);
  81 +}
  82 +
  83 +static void macio_init(void)
  84 +{
  85 + PCIDevice *d;
  86 +
  87 + d = pci_register_device("macio", sizeof(PCIDevice),
  88 + 0, -1,
  89 + NULL, NULL);
  90 + /* Note: this code is strongly inspirated from the corresponding code
  91 + in PearPC */
  92 + d->config[0x00] = 0x6b; // vendor_id
  93 + d->config[0x01] = 0x10;
  94 + d->config[0x02] = 0x17;
  95 + d->config[0x03] = 0x00;
  96 +
  97 + d->config[0x0a] = 0x00; // class_sub = pci2pci
  98 + d->config[0x0b] = 0xff; // class_base = bridge
  99 + d->config[0x0e] = 0x00; // header_type
  100 +
  101 + d->config[0x3d] = 0x01; // interrupt on pin 1
  102 +
  103 + dbdma_mem_index = cpu_register_io_memory(0, dbdma_read, dbdma_write, NULL);
  104 +
  105 + pci_register_io_region(d, 0, 0x80000,
  106 + PCI_ADDRESS_SPACE_MEM, macio_map);
  107 +}
  108 +
29 109 /* PowerPC PREP hardware initialisation */
30 110 void ppc_chrp_init(int ram_size, int vga_ram_size, int boot_device,
31 111 DisplayState *ds, const char **fd_filename, int snapshot,
... ... @@ -86,7 +166,13 @@ void ppc_chrp_init(int ram_size, int vga_ram_size, int boot_device,
86 166  
87 167 pci_ide_init(bs_table);
88 168  
89   - kbd_init();
  169 + /* cuda also initialize ADB */
  170 + cuda_mem_index = cuda_init();
  171 +
  172 + adb_kbd_init(&adb_bus);
  173 + adb_mouse_init(&adb_bus);
  174 +
  175 + macio_init();
90 176  
91 177 nvram = m48t59_init(8, 0x0074, NVRAM_SIZE);
92 178  
... ...