qemu/hw/cuda.c
<<
>>
Prefs
   1/*
   2 * QEMU PowerMac CUDA device support
   3 *
   4 * Copyright (c) 2004-2007 Fabrice Bellard
   5 * Copyright (c) 2007 Jocelyn Mayer
   6 *
   7 * Permission is hereby granted, free of charge, to any person obtaining a copy
   8 * of this software and associated documentation files (the "Software"), to deal
   9 * in the Software without restriction, including without limitation the rights
  10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11 * copies of the Software, and to permit persons to whom the Software is
  12 * furnished to do so, subject to the following conditions:
  13 *
  14 * The above copyright notice and this permission notice shall be included in
  15 * all copies or substantial portions of the Software.
  16 *
  17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23 * THE SOFTWARE.
  24 */
  25#include "hw.h"
  26#include "ppc_mac.h"
  27#include "qemu-timer.h"
  28#include "sysemu.h"
  29
  30/* XXX: implement all timer modes */
  31
  32/* debug CUDA */
  33//#define DEBUG_CUDA
  34
  35/* debug CUDA packets */
  36//#define DEBUG_CUDA_PACKET
  37
  38#ifdef DEBUG_CUDA
  39#define CUDA_DPRINTF(fmt, ...)                                  \
  40    do { printf("CUDA: " fmt , ## __VA_ARGS__); } while (0)
  41#else
  42#define CUDA_DPRINTF(fmt, ...)
  43#endif
  44
  45/* Bits in B data register: all active low */
  46#define TREQ            0x08            /* Transfer request (input) */
  47#define TACK            0x10            /* Transfer acknowledge (output) */
  48#define TIP             0x20            /* Transfer in progress (output) */
  49
  50/* Bits in ACR */
  51#define SR_CTRL         0x1c            /* Shift register control bits */
  52#define SR_EXT          0x0c            /* Shift on external clock */
  53#define SR_OUT          0x10            /* Shift out if 1 */
  54
  55/* Bits in IFR and IER */
  56#define IER_SET         0x80            /* set bits in IER */
  57#define IER_CLR         0               /* clear bits in IER */
  58#define SR_INT          0x04            /* Shift register full/empty */
  59#define T1_INT          0x40            /* Timer 1 interrupt */
  60#define T2_INT          0x20            /* Timer 2 interrupt */
  61
  62/* Bits in ACR */
  63#define T1MODE          0xc0            /* Timer 1 mode */
  64#define T1MODE_CONT     0x40            /*  continuous interrupts */
  65
  66/* commands (1st byte) */
  67#define ADB_PACKET      0
  68#define CUDA_PACKET     1
  69#define ERROR_PACKET    2
  70#define TIMER_PACKET    3
  71#define POWER_PACKET    4
  72#define MACIIC_PACKET   5
  73#define PMU_PACKET      6
  74
  75
  76/* CUDA commands (2nd byte) */
  77#define CUDA_WARM_START                 0x0
  78#define CUDA_AUTOPOLL                   0x1
  79#define CUDA_GET_6805_ADDR              0x2
  80#define CUDA_GET_TIME                   0x3
  81#define CUDA_GET_PRAM                   0x7
  82#define CUDA_SET_6805_ADDR              0x8
  83#define CUDA_SET_TIME                   0x9
  84#define CUDA_POWERDOWN                  0xa
  85#define CUDA_POWERUP_TIME               0xb
  86#define CUDA_SET_PRAM                   0xc
  87#define CUDA_MS_RESET                   0xd
  88#define CUDA_SEND_DFAC                  0xe
  89#define CUDA_BATTERY_SWAP_SENSE         0x10
  90#define CUDA_RESET_SYSTEM               0x11
  91#define CUDA_SET_IPL                    0x12
  92#define CUDA_FILE_SERVER_FLAG           0x13
  93#define CUDA_SET_AUTO_RATE              0x14
  94#define CUDA_GET_AUTO_RATE              0x16
  95#define CUDA_SET_DEVICE_LIST            0x19
  96#define CUDA_GET_DEVICE_LIST            0x1a
  97#define CUDA_SET_ONE_SECOND_MODE        0x1b
  98#define CUDA_SET_POWER_MESSAGES         0x21
  99#define CUDA_GET_SET_IIC                0x22
 100#define CUDA_WAKEUP                     0x23
 101#define CUDA_TIMER_TICKLE               0x24
 102#define CUDA_COMBINED_FORMAT_IIC        0x25
 103
 104#define CUDA_TIMER_FREQ (4700000 / 6)
 105#define CUDA_ADB_POLL_FREQ 50
 106
 107/* CUDA returns time_t's offset from Jan 1, 1904, not 1970 */
 108#define RTC_OFFSET                      2082844800
 109
 110typedef struct CUDATimer {
 111    int index;
 112    uint16_t latch;
 113    uint16_t counter_value; /* counter value at load time */
 114    int64_t load_time;
 115    int64_t next_irq_time;
 116    QEMUTimer *timer;
 117} CUDATimer;
 118
 119typedef struct CUDAState {
 120    /* cuda registers */
 121    uint8_t b;      /* B-side data */
 122    uint8_t a;      /* A-side data */
 123    uint8_t dirb;   /* B-side direction (1=output) */
 124    uint8_t dira;   /* A-side direction (1=output) */
 125    uint8_t sr;     /* Shift register */
 126    uint8_t acr;    /* Auxiliary control register */
 127    uint8_t pcr;    /* Peripheral control register */
 128    uint8_t ifr;    /* Interrupt flag register */
 129    uint8_t ier;    /* Interrupt enable register */
 130    uint8_t anh;    /* A-side data, no handshake */
 131
 132    CUDATimer timers[2];
 133
 134    uint32_t tick_offset;
 135
 136    uint8_t last_b; /* last value of B register */
 137    uint8_t last_acr; /* last value of B register */
 138
 139    int data_in_size;
 140    int data_in_index;
 141    int data_out_index;
 142
 143    qemu_irq irq;
 144    uint8_t autopoll;
 145    uint8_t data_in[128];
 146    uint8_t data_out[16];
 147    QEMUTimer *adb_poll_timer;
 148} CUDAState;
 149
 150static CUDAState cuda_state;
 151ADBBusState adb_bus;
 152
 153static void cuda_update(CUDAState *s);
 154static void cuda_receive_packet_from_host(CUDAState *s,
 155                                          const uint8_t *data, int len);
 156static void cuda_timer_update(CUDAState *s, CUDATimer *ti,
 157                              int64_t current_time);
 158
 159static void cuda_update_irq(CUDAState *s)
 160{
 161    if (s->ifr & s->ier & (SR_INT | T1_INT)) {
 162        qemu_irq_raise(s->irq);
 163    } else {
 164        qemu_irq_lower(s->irq);
 165    }
 166}
 167
 168static unsigned int get_counter(CUDATimer *s)
 169{
 170    int64_t d;
 171    unsigned int counter;
 172
 173    d = muldiv64(qemu_get_clock(vm_clock) - s->load_time,
 174                 CUDA_TIMER_FREQ, get_ticks_per_sec());
 175    if (s->index == 0) {
 176        /* the timer goes down from latch to -1 (period of latch + 2) */
 177        if (d <= (s->counter_value + 1)) {
 178            counter = (s->counter_value - d) & 0xffff;
 179        } else {
 180            counter = (d - (s->counter_value + 1)) % (s->latch + 2);
 181            counter = (s->latch - counter) & 0xffff;
 182        }
 183    } else {
 184        counter = (s->counter_value - d) & 0xffff;
 185    }
 186    return counter;
 187}
 188
 189static void set_counter(CUDAState *s, CUDATimer *ti, unsigned int val)
 190{
 191    CUDA_DPRINTF("T%d.counter=%d\n", 1 + (ti->timer == NULL), val);
 192    ti->load_time = qemu_get_clock(vm_clock);
 193    ti->counter_value = val;
 194    cuda_timer_update(s, ti, ti->load_time);
 195}
 196
 197static int64_t get_next_irq_time(CUDATimer *s, int64_t current_time)
 198{
 199    int64_t d, next_time;
 200    unsigned int counter;
 201
 202    /* current counter value */
 203    d = muldiv64(current_time - s->load_time,
 204                 CUDA_TIMER_FREQ, get_ticks_per_sec());
 205    /* the timer goes down from latch to -1 (period of latch + 2) */
 206    if (d <= (s->counter_value + 1)) {
 207        counter = (s->counter_value - d) & 0xffff;
 208    } else {
 209        counter = (d - (s->counter_value + 1)) % (s->latch + 2);
 210        counter = (s->latch - counter) & 0xffff;
 211    }
 212
 213    /* Note: we consider the irq is raised on 0 */
 214    if (counter == 0xffff) {
 215        next_time = d + s->latch + 1;
 216    } else if (counter == 0) {
 217        next_time = d + s->latch + 2;
 218    } else {
 219        next_time = d + counter;
 220    }
 221    CUDA_DPRINTF("latch=%d counter=%" PRId64 " delta_next=%" PRId64 "\n",
 222                 s->latch, d, next_time - d);
 223    next_time = muldiv64(next_time, get_ticks_per_sec(), CUDA_TIMER_FREQ) +
 224        s->load_time;
 225    if (next_time <= current_time)
 226        next_time = current_time + 1;
 227    return next_time;
 228}
 229
 230static void cuda_timer_update(CUDAState *s, CUDATimer *ti,
 231                              int64_t current_time)
 232{
 233    if (!ti->timer)
 234        return;
 235    if ((s->acr & T1MODE) != T1MODE_CONT) {
 236        qemu_del_timer(ti->timer);
 237    } else {
 238        ti->next_irq_time = get_next_irq_time(ti, current_time);
 239        qemu_mod_timer(ti->timer, ti->next_irq_time);
 240    }
 241}
 242
 243static void cuda_timer1(void *opaque)
 244{
 245    CUDAState *s = opaque;
 246    CUDATimer *ti = &s->timers[0];
 247
 248    cuda_timer_update(s, ti, ti->next_irq_time);
 249    s->ifr |= T1_INT;
 250    cuda_update_irq(s);
 251}
 252
 253static uint32_t cuda_readb(void *opaque, target_phys_addr_t addr)
 254{
 255    CUDAState *s = opaque;
 256    uint32_t val;
 257
 258    addr = (addr >> 9) & 0xf;
 259    switch(addr) {
 260    case 0:
 261        val = s->b;
 262        break;
 263    case 1:
 264        val = s->a;
 265        break;
 266    case 2:
 267        val = s->dirb;
 268        break;
 269    case 3:
 270        val = s->dira;
 271        break;
 272    case 4:
 273        val = get_counter(&s->timers[0]) & 0xff;
 274        s->ifr &= ~T1_INT;
 275        cuda_update_irq(s);
 276        break;
 277    case 5:
 278        val = get_counter(&s->timers[0]) >> 8;
 279        cuda_update_irq(s);
 280        break;
 281    case 6:
 282        val = s->timers[0].latch & 0xff;
 283        break;
 284    case 7:
 285        /* XXX: check this */
 286        val = (s->timers[0].latch >> 8) & 0xff;
 287        break;
 288    case 8:
 289        val = get_counter(&s->timers[1]) & 0xff;
 290        s->ifr &= ~T2_INT;
 291        break;
 292    case 9:
 293        val = get_counter(&s->timers[1]) >> 8;
 294        break;
 295    case 10:
 296        val = s->sr;
 297        s->ifr &= ~SR_INT;
 298        cuda_update_irq(s);
 299        break;
 300    case 11:
 301        val = s->acr;
 302        break;
 303    case 12:
 304        val = s->pcr;
 305        break;
 306    case 13:
 307        val = s->ifr;
 308        if (s->ifr & s->ier)
 309            val |= 0x80;
 310        break;
 311    case 14:
 312        val = s->ier | 0x80;
 313        break;
 314    default:
 315    case 15:
 316        val = s->anh;
 317        break;
 318    }
 319    if (addr != 13 || val != 0) {
 320        CUDA_DPRINTF("read: reg=0x%x val=%02x\n", (int)addr, val);
 321    }
 322
 323    return val;
 324}
 325
 326static void cuda_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
 327{
 328    CUDAState *s = opaque;
 329
 330    addr = (addr >> 9) & 0xf;
 331    CUDA_DPRINTF("write: reg=0x%x val=%02x\n", (int)addr, val);
 332
 333    switch(addr) {
 334    case 0:
 335        s->b = val;
 336        cuda_update(s);
 337        break;
 338    case 1:
 339        s->a = val;
 340        break;
 341    case 2:
 342        s->dirb = val;
 343        break;
 344    case 3:
 345        s->dira = val;
 346        break;
 347    case 4:
 348        s->timers[0].latch = (s->timers[0].latch & 0xff00) | val;
 349        cuda_timer_update(s, &s->timers[0], qemu_get_clock(vm_clock));
 350        break;
 351    case 5:
 352        s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8);
 353        s->ifr &= ~T1_INT;
 354        set_counter(s, &s->timers[0], s->timers[0].latch);
 355        break;
 356    case 6:
 357        s->timers[0].latch = (s->timers[0].latch & 0xff00) | val;
 358        cuda_timer_update(s, &s->timers[0], qemu_get_clock(vm_clock));
 359        break;
 360    case 7:
 361        s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8);
 362        s->ifr &= ~T1_INT;
 363        cuda_timer_update(s, &s->timers[0], qemu_get_clock(vm_clock));
 364        break;
 365    case 8:
 366        s->timers[1].latch = val;
 367        set_counter(s, &s->timers[1], val);
 368        break;
 369    case 9:
 370        set_counter(s, &s->timers[1], (val << 8) | s->timers[1].latch);
 371        break;
 372    case 10:
 373        s->sr = val;
 374        break;
 375    case 11:
 376        s->acr = val;
 377        cuda_timer_update(s, &s->timers[0], qemu_get_clock(vm_clock));
 378        cuda_update(s);
 379        break;
 380    case 12:
 381        s->pcr = val;
 382        break;
 383    case 13:
 384        /* reset bits */
 385        s->ifr &= ~val;
 386        cuda_update_irq(s);
 387        break;
 388    case 14:
 389        if (val & IER_SET) {
 390            /* set bits */
 391            s->ier |= val & 0x7f;
 392        } else {
 393            /* reset bits */
 394            s->ier &= ~val;
 395        }
 396        cuda_update_irq(s);
 397        break;
 398    default:
 399    case 15:
 400        s->anh = val;
 401        break;
 402    }
 403}
 404
 405/* NOTE: TIP and TREQ are negated */
 406static void cuda_update(CUDAState *s)
 407{
 408    int packet_received, len;
 409
 410    packet_received = 0;
 411    if (!(s->b & TIP)) {
 412        /* transfer requested from host */
 413
 414        if (s->acr & SR_OUT) {
 415            /* data output */
 416            if ((s->b & (TACK | TIP)) != (s->last_b & (TACK | TIP))) {
 417                if (s->data_out_index < sizeof(s->data_out)) {
 418                    CUDA_DPRINTF("send: %02x\n", s->sr);
 419                    s->data_out[s->data_out_index++] = s->sr;
 420                    s->ifr |= SR_INT;
 421                    cuda_update_irq(s);
 422                }
 423            }
 424        } else {
 425            if (s->data_in_index < s->data_in_size) {
 426                /* data input */
 427                if ((s->b & (TACK | TIP)) != (s->last_b & (TACK | TIP))) {
 428                    s->sr = s->data_in[s->data_in_index++];
 429                    CUDA_DPRINTF("recv: %02x\n", s->sr);
 430                    /* indicate end of transfer */
 431                    if (s->data_in_index >= s->data_in_size) {
 432                        s->b = (s->b | TREQ);
 433                    }
 434                    s->ifr |= SR_INT;
 435                    cuda_update_irq(s);
 436                }
 437            }
 438        }
 439    } else {
 440        /* no transfer requested: handle sync case */
 441        if ((s->last_b & TIP) && (s->b & TACK) != (s->last_b & TACK)) {
 442            /* update TREQ state each time TACK change state */
 443            if (s->b & TACK)
 444                s->b = (s->b | TREQ);
 445            else
 446                s->b = (s->b & ~TREQ);
 447            s->ifr |= SR_INT;
 448            cuda_update_irq(s);
 449        } else {
 450            if (!(s->last_b & TIP)) {
 451                /* handle end of host to cuda transfer */
 452                packet_received = (s->data_out_index > 0);
 453                /* always an IRQ at the end of transfer */
 454                s->ifr |= SR_INT;
 455                cuda_update_irq(s);
 456            }
 457            /* signal if there is data to read */
 458            if (s->data_in_index < s->data_in_size) {
 459                s->b = (s->b & ~TREQ);
 460            }
 461        }
 462    }
 463
 464    s->last_acr = s->acr;
 465    s->last_b = s->b;
 466
 467    /* NOTE: cuda_receive_packet_from_host() can call cuda_update()
 468       recursively */
 469    if (packet_received) {
 470        len = s->data_out_index;
 471        s->data_out_index = 0;
 472        cuda_receive_packet_from_host(s, s->data_out, len);
 473    }
 474}
 475
 476static void cuda_send_packet_to_host(CUDAState *s,
 477                                     const uint8_t *data, int len)
 478{
 479#ifdef DEBUG_CUDA_PACKET
 480    {
 481        int i;
 482        printf("cuda_send_packet_to_host:\n");
 483        for(i = 0; i < len; i++)
 484            printf(" %02x", data[i]);
 485        printf("\n");
 486    }
 487#endif
 488    memcpy(s->data_in, data, len);
 489    s->data_in_size = len;
 490    s->data_in_index = 0;
 491    cuda_update(s);
 492    s->ifr |= SR_INT;
 493    cuda_update_irq(s);
 494}
 495
 496static void cuda_adb_poll(void *opaque)
 497{
 498    CUDAState *s = opaque;
 499    uint8_t obuf[ADB_MAX_OUT_LEN + 2];
 500    int olen;
 501
 502    olen = adb_poll(&adb_bus, obuf + 2);
 503    if (olen > 0) {
 504        obuf[0] = ADB_PACKET;
 505        obuf[1] = 0x40; /* polled data */
 506        cuda_send_packet_to_host(s, obuf, olen + 2);
 507    }
 508    qemu_mod_timer(s->adb_poll_timer,
 509                   qemu_get_clock(vm_clock) +
 510                   (get_ticks_per_sec() / CUDA_ADB_POLL_FREQ));
 511}
 512
 513static void cuda_receive_packet(CUDAState *s,
 514                                const uint8_t *data, int len)
 515{
 516    uint8_t obuf[16];
 517    int autopoll;
 518    uint32_t ti;
 519
 520    switch(data[0]) {
 521    case CUDA_AUTOPOLL:
 522        autopoll = (data[1] != 0);
 523        if (autopoll != s->autopoll) {
 524            s->autopoll = autopoll;
 525            if (autopoll) {
 526                qemu_mod_timer(s->adb_poll_timer,
 527                               qemu_get_clock(vm_clock) +
 528                               (get_ticks_per_sec() / CUDA_ADB_POLL_FREQ));
 529            } else {
 530                qemu_del_timer(s->adb_poll_timer);
 531            }
 532        }
 533        obuf[0] = CUDA_PACKET;
 534        obuf[1] = data[1];
 535        cuda_send_packet_to_host(s, obuf, 2);
 536        break;
 537    case CUDA_SET_TIME:
 538        ti = (((uint32_t)data[1]) << 24) + (((uint32_t)data[2]) << 16) + (((uint32_t)data[3]) << 8) + data[4];
 539        s->tick_offset = ti - (qemu_get_clock(vm_clock) / get_ticks_per_sec());
 540        obuf[0] = CUDA_PACKET;
 541        obuf[1] = 0;
 542        obuf[2] = 0;
 543        cuda_send_packet_to_host(s, obuf, 3);
 544        break;
 545    case CUDA_GET_TIME:
 546        ti = s->tick_offset + (qemu_get_clock(vm_clock) / get_ticks_per_sec());
 547        obuf[0] = CUDA_PACKET;
 548        obuf[1] = 0;
 549        obuf[2] = 0;
 550        obuf[3] = ti >> 24;
 551        obuf[4] = ti >> 16;
 552        obuf[5] = ti >> 8;
 553        obuf[6] = ti;
 554        cuda_send_packet_to_host(s, obuf, 7);
 555        break;
 556    case CUDA_FILE_SERVER_FLAG:
 557    case CUDA_SET_DEVICE_LIST:
 558    case CUDA_SET_AUTO_RATE:
 559    case CUDA_SET_POWER_MESSAGES:
 560        obuf[0] = CUDA_PACKET;
 561        obuf[1] = 0;
 562        cuda_send_packet_to_host(s, obuf, 2);
 563        break;
 564    case CUDA_POWERDOWN:
 565        obuf[0] = CUDA_PACKET;
 566        obuf[1] = 0;
 567        cuda_send_packet_to_host(s, obuf, 2);
 568        qemu_system_shutdown_request();
 569        break;
 570    case CUDA_RESET_SYSTEM:
 571        obuf[0] = CUDA_PACKET;
 572        obuf[1] = 0;
 573        cuda_send_packet_to_host(s, obuf, 2);
 574        qemu_system_reset_request();
 575        break;
 576    default:
 577        break;
 578    }
 579}
 580
 581static void cuda_receive_packet_from_host(CUDAState *s,
 582                                          const uint8_t *data, int len)
 583{
 584#ifdef DEBUG_CUDA_PACKET
 585    {
 586        int i;
 587        printf("cuda_receive_packet_from_host:\n");
 588        for(i = 0; i < len; i++)
 589            printf(" %02x", data[i]);
 590        printf("\n");
 591    }
 592#endif
 593    switch(data[0]) {
 594    case ADB_PACKET:
 595        {
 596            uint8_t obuf[ADB_MAX_OUT_LEN + 2];
 597            int olen;
 598            olen = adb_request(&adb_bus, obuf + 2, data + 1, len - 1);
 599            if (olen > 0) {
 600                obuf[0] = ADB_PACKET;
 601                obuf[1] = 0x00;
 602            } else {
 603                /* error */
 604                obuf[0] = ADB_PACKET;
 605                obuf[1] = -olen;
 606                olen = 0;
 607            }
 608            cuda_send_packet_to_host(s, obuf, olen + 2);
 609        }
 610        break;
 611    case CUDA_PACKET:
 612        cuda_receive_packet(s, data + 1, len - 1);
 613        break;
 614    }
 615}
 616
 617static void cuda_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
 618{
 619}
 620
 621static void cuda_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
 622{
 623}
 624
 625static uint32_t cuda_readw (void *opaque, target_phys_addr_t addr)
 626{
 627    return 0;
 628}
 629
 630static uint32_t cuda_readl (void *opaque, target_phys_addr_t addr)
 631{
 632    return 0;
 633}
 634
 635static CPUWriteMemoryFunc * const cuda_write[] = {
 636    &cuda_writeb,
 637    &cuda_writew,
 638    &cuda_writel,
 639};
 640
 641static CPUReadMemoryFunc * const cuda_read[] = {
 642    &cuda_readb,
 643    &cuda_readw,
 644    &cuda_readl,
 645};
 646
 647static void cuda_save_timer(QEMUFile *f, CUDATimer *s)
 648{
 649    qemu_put_be16s(f, &s->latch);
 650    qemu_put_be16s(f, &s->counter_value);
 651    qemu_put_sbe64s(f, &s->load_time);
 652    qemu_put_sbe64s(f, &s->next_irq_time);
 653    if (s->timer)
 654        qemu_put_timer(f, s->timer);
 655}
 656
 657static void cuda_save(QEMUFile *f, void *opaque)
 658{
 659    CUDAState *s = (CUDAState *)opaque;
 660
 661    qemu_put_ubyte(f, s->b);
 662    qemu_put_ubyte(f, s->a);
 663    qemu_put_ubyte(f, s->dirb);
 664    qemu_put_ubyte(f, s->dira);
 665    qemu_put_ubyte(f, s->sr);
 666    qemu_put_ubyte(f, s->acr);
 667    qemu_put_ubyte(f, s->pcr);
 668    qemu_put_ubyte(f, s->ifr);
 669    qemu_put_ubyte(f, s->ier);
 670    qemu_put_ubyte(f, s->anh);
 671    qemu_put_sbe32s(f, &s->data_in_size);
 672    qemu_put_sbe32s(f, &s->data_in_index);
 673    qemu_put_sbe32s(f, &s->data_out_index);
 674    qemu_put_ubyte(f, s->autopoll);
 675    qemu_put_buffer(f, s->data_in, sizeof(s->data_in));
 676    qemu_put_buffer(f, s->data_out, sizeof(s->data_out));
 677    qemu_put_be32s(f, &s->tick_offset);
 678    cuda_save_timer(f, &s->timers[0]);
 679    cuda_save_timer(f, &s->timers[1]);
 680}
 681
 682static void cuda_load_timer(QEMUFile *f, CUDATimer *s)
 683{
 684    qemu_get_be16s(f, &s->latch);
 685    qemu_get_be16s(f, &s->counter_value);
 686    qemu_get_sbe64s(f, &s->load_time);
 687    qemu_get_sbe64s(f, &s->next_irq_time);
 688    if (s->timer)
 689        qemu_get_timer(f, s->timer);
 690}
 691
 692static int cuda_load(QEMUFile *f, void *opaque, int version_id)
 693{
 694    CUDAState *s = (CUDAState *)opaque;
 695
 696    if (version_id != 1)
 697        return -EINVAL;
 698
 699    s->b = qemu_get_ubyte(f);
 700    s->a = qemu_get_ubyte(f);
 701    s->dirb = qemu_get_ubyte(f);
 702    s->dira = qemu_get_ubyte(f);
 703    s->sr = qemu_get_ubyte(f);
 704    s->acr = qemu_get_ubyte(f);
 705    s->pcr = qemu_get_ubyte(f);
 706    s->ifr = qemu_get_ubyte(f);
 707    s->ier = qemu_get_ubyte(f);
 708    s->anh = qemu_get_ubyte(f);
 709    qemu_get_sbe32s(f, &s->data_in_size);
 710    qemu_get_sbe32s(f, &s->data_in_index);
 711    qemu_get_sbe32s(f, &s->data_out_index);
 712    s->autopoll = qemu_get_ubyte(f);
 713    qemu_get_buffer(f, s->data_in, sizeof(s->data_in));
 714    qemu_get_buffer(f, s->data_out, sizeof(s->data_out));
 715    qemu_get_be32s(f, &s->tick_offset);
 716    cuda_load_timer(f, &s->timers[0]);
 717    cuda_load_timer(f, &s->timers[1]);
 718
 719    return 0;
 720}
 721
 722static void cuda_reset(void *opaque)
 723{
 724    CUDAState *s = opaque;
 725
 726    s->b = 0;
 727    s->a = 0;
 728    s->dirb = 0;
 729    s->dira = 0;
 730    s->sr = 0;
 731    s->acr = 0;
 732    s->pcr = 0;
 733    s->ifr = 0;
 734    s->ier = 0;
 735    //    s->ier = T1_INT | SR_INT;
 736    s->anh = 0;
 737    s->data_in_size = 0;
 738    s->data_in_index = 0;
 739    s->data_out_index = 0;
 740    s->autopoll = 0;
 741
 742    s->timers[0].latch = 0xffff;
 743    set_counter(s, &s->timers[0], 0xffff);
 744
 745    s->timers[1].latch = 0;
 746    set_counter(s, &s->timers[1], 0xffff);
 747}
 748
 749void cuda_init (int *cuda_mem_index, qemu_irq irq)
 750{
 751    struct tm tm;
 752    CUDAState *s = &cuda_state;
 753
 754    s->irq = irq;
 755
 756    s->timers[0].index = 0;
 757    s->timers[0].timer = qemu_new_timer(vm_clock, cuda_timer1, s);
 758
 759    s->timers[1].index = 1;
 760
 761    qemu_get_timedate(&tm, 0);
 762    s->tick_offset = (uint32_t)mktimegm(&tm) + RTC_OFFSET;
 763
 764    s->adb_poll_timer = qemu_new_timer(vm_clock, cuda_adb_poll, s);
 765    *cuda_mem_index = cpu_register_io_memory(cuda_read, cuda_write, s,
 766                                             DEVICE_NATIVE_ENDIAN);
 767    register_savevm(NULL, "cuda", -1, 1, cuda_save, cuda_load, s);
 768    qemu_register_reset(cuda_reset, s);
 769}
 770