Annotation of qemu/hw/cuda.c, revision 1.1.1.10

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.