Annotation of qemu/hw/sh7750.c, revision 1.1.1.2

1.1       root        1: /*
                      2:  * SH7750 device
                      3:  * 
                      4:  * Copyright (c) 2005 Samuel Tardieu
                      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 <stdio.h>
                     25: #include <assert.h>
                     26: #include "vl.h"
                     27: #include "sh7750_regs.h"
                     28: #include "sh7750_regnames.h"
                     29: 
                     30: typedef struct {
                     31:     uint8_t data[16];
                     32:     uint8_t length;            /* Number of characters in the FIFO */
                     33:     uint8_t write_idx;         /* Index of first character to write */
                     34:     uint8_t read_idx;          /* Index of first character to read */
                     35: } fifo;
                     36: 
                     37: #define NB_DEVICES 4
                     38: 
                     39: typedef struct SH7750State {
                     40:     /* CPU */
                     41:     CPUSH4State *cpu;
                     42:     /* Peripheral frequency in Hz */
                     43:     uint32_t periph_freq;
                     44:     /* SDRAM controller */
                     45:     uint16_t rfcr;
                     46:     /* First serial port */
                     47:     CharDriverState *serial1;
                     48:     uint8_t scscr1;
                     49:     uint8_t scsmr1;
                     50:     uint8_t scbrr1;
                     51:     uint8_t scssr1;
                     52:     uint8_t scssr1_read;
                     53:     uint8_t sctsr1;
                     54:     uint8_t sctsr1_loaded;
                     55:     uint8_t sctdr1;
                     56:     uint8_t scrdr1;
                     57:     /* Second serial port */
                     58:     CharDriverState *serial2;
                     59:     uint16_t sclsr2;
                     60:     uint16_t scscr2;
                     61:     uint16_t scfcr2;
                     62:     uint16_t scfsr2;
                     63:     uint16_t scsmr2;
                     64:     uint8_t scbrr2;
                     65:     fifo serial2_receive_fifo;
                     66:     fifo serial2_transmit_fifo;
                     67:     /* Timers */
                     68:     uint8_t tstr;
                     69:     /* Timer 0 */
                     70:     QEMUTimer *timer0;
                     71:     uint16_t tcr0;
                     72:     uint32_t tcor0;
                     73:     uint32_t tcnt0;
                     74:     /* IO ports */
                     75:     uint16_t gpioic;
                     76:     uint32_t pctra;
                     77:     uint32_t pctrb;
                     78:     uint16_t portdira;         /* Cached */
                     79:     uint16_t portpullupa;      /* Cached */
                     80:     uint16_t portdirb;         /* Cached */
                     81:     uint16_t portpullupb;      /* Cached */
                     82:     uint16_t pdtra;
                     83:     uint16_t pdtrb;
                     84:     uint16_t periph_pdtra;     /* Imposed by the peripherals */
                     85:     uint16_t periph_portdira;  /* Direction seen from the peripherals */
                     86:     uint16_t periph_pdtrb;     /* Imposed by the peripherals */
                     87:     uint16_t periph_portdirb;  /* Direction seen from the peripherals */
                     88:     sh7750_io_device *devices[NB_DEVICES];     /* External peripherals */
                     89:     /* Cache */
                     90:     uint32_t ccr;
                     91: } SH7750State;
                     92: 
                     93: /**********************************************************************
                     94:  Timers
                     95: **********************************************************************/
                     96: 
                     97: /* XXXXX At this time, timer0 works in underflow only mode, that is
                     98:    the value of tcnt0 is read at alarm computation time and cannot
                     99:    be read back by the guest OS */
                    100: 
                    101: static void start_timer0(SH7750State * s)
                    102: {
                    103:     uint64_t now, next, prescaler;
                    104: 
                    105:     if ((s->tcr0 & 6) == 6) {
                    106:        fprintf(stderr, "rtc clock for timer 0 not supported\n");
                    107:        assert(0);
                    108:     }
                    109: 
                    110:     if ((s->tcr0 & 7) == 5) {
                    111:        fprintf(stderr, "timer 0 configuration not supported\n");
                    112:        assert(0);
                    113:     }
                    114: 
                    115:     if ((s->tcr0 & 4) == 4)
                    116:        prescaler = 1024;
                    117:     else
                    118:        prescaler = 4 << (s->tcr0 & 3);
                    119: 
                    120:     now = qemu_get_clock(vm_clock);
                    121:     /* XXXXX */
                    122:     next =
                    123:        now + muldiv64(prescaler * s->tcnt0, ticks_per_sec,
                    124:                       s->periph_freq);
                    125:     if (next == now)
                    126:        next = now + 1;
1.1.1.2 ! root      127:     fprintf(stderr, "now=%016" PRIx64 ", next=%016" PRIx64 "\n", now, next);
1.1       root      128:     fprintf(stderr, "timer will underflow in %f seconds\n",
                    129:            (float) (next - now) / (float) ticks_per_sec);
                    130: 
                    131:     qemu_mod_timer(s->timer0, next);
                    132: }
                    133: 
                    134: static void timer_start_changed(SH7750State * s)
                    135: {
                    136:     if (s->tstr & SH7750_TSTR_STR0) {
                    137:        start_timer0(s);
                    138:     } else {
                    139:        fprintf(stderr, "timer 0 is stopped\n");
                    140:        qemu_del_timer(s->timer0);
                    141:     }
                    142: }
                    143: 
                    144: static void timer0_cb(void *opaque)
                    145: {
                    146:     SH7750State *s = opaque;
                    147: 
                    148:     s->tcnt0 = (uint32_t) 0;   /* XXXXX */
                    149:     if (--s->tcnt0 == (uint32_t) - 1) {
                    150:        fprintf(stderr, "timer 0 underflow\n");
                    151:        s->tcnt0 = s->tcor0;
                    152:        s->tcr0 |= SH7750_TCR_UNF;
                    153:        if (s->tcr0 & SH7750_TCR_UNIE) {
                    154:            fprintf(stderr,
                    155:                    "interrupt generation for timer 0 not supported\n");
                    156:            assert(0);
                    157:        }
                    158:     }
                    159:     start_timer0(s);
                    160: }
                    161: 
                    162: static void init_timers(SH7750State * s)
                    163: {
                    164:     s->tcor0 = 0xffffffff;
                    165:     s->tcnt0 = 0xffffffff;
                    166:     s->timer0 = qemu_new_timer(vm_clock, &timer0_cb, s);
                    167: }
                    168: 
                    169: /**********************************************************************
                    170:  First serial port
                    171: **********************************************************************/
                    172: 
                    173: static int serial1_can_receive(void *opaque)
                    174: {
                    175:     SH7750State *s = opaque;
                    176: 
                    177:     return s->scscr1 & SH7750_SCSCR_RE;
                    178: }
                    179: 
                    180: static void serial1_receive_char(SH7750State * s, uint8_t c)
                    181: {
                    182:     if (s->scssr1 & SH7750_SCSSR1_RDRF) {
                    183:        s->scssr1 |= SH7750_SCSSR1_ORER;
                    184:        return;
                    185:     }
                    186: 
                    187:     s->scrdr1 = c;
                    188:     s->scssr1 |= SH7750_SCSSR1_RDRF;
                    189: }
                    190: 
                    191: static void serial1_receive(void *opaque, const uint8_t * buf, int size)
                    192: {
                    193:     SH7750State *s = opaque;
                    194:     int i;
                    195: 
                    196:     for (i = 0; i < size; i++) {
                    197:        serial1_receive_char(s, buf[i]);
                    198:     }
                    199: }
                    200: 
                    201: static void serial1_event(void *opaque, int event)
                    202: {
                    203:     assert(0);
                    204: }
                    205: 
                    206: static void serial1_maybe_send(SH7750State * s)
                    207: {
                    208:     uint8_t c;
                    209: 
                    210:     if (s->scssr1 & SH7750_SCSSR1_TDRE)
                    211:        return;
                    212:     c = s->sctdr1;
                    213:     s->scssr1 |= SH7750_SCSSR1_TDRE | SH7750_SCSSR1_TEND;
                    214:     if (s->scscr1 & SH7750_SCSCR_TIE) {
                    215:        fprintf(stderr, "interrupts for serial port 1 not implemented\n");
                    216:        assert(0);
                    217:     }
                    218:     /* XXXXX Check for errors in write */
                    219:     qemu_chr_write(s->serial1, &c, 1);
                    220: }
                    221: 
                    222: static void serial1_change_scssr1(SH7750State * s, uint8_t mem_value)
                    223: {
                    224:     uint8_t new_flags;
                    225: 
                    226:     /* If transmit disable, TDRE and TEND stays up */
                    227:     if ((s->scscr1 & SH7750_SCSCR_TE) == 0) {
                    228:        mem_value |= SH7750_SCSSR1_TDRE | SH7750_SCSSR1_TEND;
                    229:     }
                    230: 
                    231:     /* Only clear bits which have been read before and do not set any bit
                    232:        in the flags */
                    233:     new_flags = s->scssr1 & ~s->scssr1_read;   /* Preserve unread flags */
                    234:     new_flags &= mem_value | ~s->scssr1_read;  /* Clear read flags */
                    235: 
                    236:     s->scssr1 = (new_flags & 0xf8) | (mem_value & 1);
                    237:     s->scssr1_read &= mem_value;
                    238: 
                    239:     /* If TDRE has been cleared, TEND will also be cleared */
                    240:     if ((s->scssr1 & SH7750_SCSSR1_TDRE) == 0) {
                    241:        s->scssr1 &= ~SH7750_SCSSR1_TEND;
                    242:     }
                    243: 
                    244:     /* Check for transmission to start */
                    245:     serial1_maybe_send(s);
                    246: }
                    247: 
                    248: static void serial1_update_parameters(SH7750State * s)
                    249: {
                    250:     QEMUSerialSetParams ssp;
                    251: 
                    252:     if (s->scsmr1 & SH7750_SCSMR_CHR_7)
                    253:        ssp.data_bits = 7;
                    254:     else
                    255:        ssp.data_bits = 8;
                    256:     if (s->scsmr1 & SH7750_SCSMR_PE) {
                    257:        if (s->scsmr1 & SH7750_SCSMR_PM_ODD)
                    258:            ssp.parity = 'O';
                    259:        else
                    260:            ssp.parity = 'E';
                    261:     } else
                    262:        ssp.parity = 'N';
                    263:     if (s->scsmr1 & SH7750_SCSMR_STOP_2)
                    264:        ssp.stop_bits = 2;
                    265:     else
                    266:        ssp.stop_bits = 1;
                    267:     fprintf(stderr, "SCSMR1=%04x SCBRR1=%02x\n", s->scsmr1, s->scbrr1);
                    268:     ssp.speed = s->periph_freq /
                    269:        (32 * s->scbrr1 * (1 << (2 * (s->scsmr1 & 3)))) - 1;
                    270:     fprintf(stderr, "data bits=%d, stop bits=%d, parity=%c, speed=%d\n",
                    271:            ssp.data_bits, ssp.stop_bits, ssp.parity, ssp.speed);
                    272:     qemu_chr_ioctl(s->serial1, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
                    273: }
                    274: 
                    275: static void scscr1_changed(SH7750State * s)
                    276: {
                    277:     if (s->scscr1 & (SH7750_SCSCR_TE | SH7750_SCSCR_RE)) {
                    278:        if (!s->serial1) {
                    279:            fprintf(stderr, "serial port 1 not bound to anything\n");
                    280:            assert(0);
                    281:        }
                    282:        serial1_update_parameters(s);
                    283:     }
                    284:     if ((s->scscr1 & SH7750_SCSCR_RE) == 0) {
                    285:        s->scssr1 |= SH7750_SCSSR1_TDRE;
                    286:     }
                    287: }
                    288: 
                    289: static void init_serial1(SH7750State * s, int serial_nb)
                    290: {
                    291:     CharDriverState *chr;
                    292: 
                    293:     s->scssr1 = 0x84;
                    294:     chr = serial_hds[serial_nb];
                    295:     if (!chr) {
                    296:        fprintf(stderr,
                    297:                "no serial port associated to SH7750 first serial port\n");
                    298:        return;
                    299:     }
                    300: 
                    301:     s->serial1 = chr;
                    302:     qemu_chr_add_read_handler(chr, serial1_can_receive,
                    303:                              serial1_receive, s);
                    304:     qemu_chr_add_event_handler(chr, serial1_event);
                    305: }
                    306: 
                    307: /**********************************************************************
                    308:  Second serial port
                    309: **********************************************************************/
                    310: 
                    311: static int serial2_can_receive(void *opaque)
                    312: {
                    313:     SH7750State *s = opaque;
                    314:     static uint8_t max_fifo_size[] = { 15, 1, 4, 6, 8, 10, 12, 14 };
                    315: 
                    316:     return s->serial2_receive_fifo.length <
                    317:        max_fifo_size[(s->scfcr2 >> 9) & 7];
                    318: }
                    319: 
                    320: static void serial2_adjust_receive_flags(SH7750State * s)
                    321: {
                    322:     static uint8_t max_fifo_size[] = { 1, 4, 8, 14 };
                    323: 
                    324:     /* XXXXX Add interrupt generation */
                    325:     if (s->serial2_receive_fifo.length >=
                    326:        max_fifo_size[(s->scfcr2 >> 7) & 3]) {
                    327:        s->scfsr2 |= SH7750_SCFSR2_RDF;
                    328:        s->scfsr2 &= ~SH7750_SCFSR2_DR;
                    329:     } else {
                    330:        s->scfsr2 &= ~SH7750_SCFSR2_RDF;
                    331:        if (s->serial2_receive_fifo.length > 0)
                    332:            s->scfsr2 |= SH7750_SCFSR2_DR;
                    333:        else
                    334:            s->scfsr2 &= ~SH7750_SCFSR2_DR;
                    335:     }
                    336: }
                    337: 
                    338: static void serial2_append_char(SH7750State * s, uint8_t c)
                    339: {
                    340:     if (s->serial2_receive_fifo.length == 16) {
                    341:        /* Overflow */
                    342:        s->sclsr2 |= SH7750_SCLSR2_ORER;
                    343:        return;
                    344:     }
                    345: 
                    346:     s->serial2_receive_fifo.data[s->serial2_receive_fifo.write_idx++] = c;
                    347:     s->serial2_receive_fifo.length++;
                    348:     serial2_adjust_receive_flags(s);
                    349: }
                    350: 
                    351: static void serial2_receive(void *opaque, const uint8_t * buf, int size)
                    352: {
                    353:     SH7750State *s = opaque;
                    354:     int i;
                    355: 
                    356:     for (i = 0; i < size; i++)
                    357:        serial2_append_char(s, buf[i]);
                    358: }
                    359: 
                    360: static void serial2_event(void *opaque, int event)
                    361: {
                    362:     /* XXXXX */
                    363:     assert(0);
                    364: }
                    365: 
                    366: static void serial2_update_parameters(SH7750State * s)
                    367: {
                    368:     QEMUSerialSetParams ssp;
                    369: 
                    370:     if (s->scsmr2 & SH7750_SCSMR_CHR_7)
                    371:        ssp.data_bits = 7;
                    372:     else
                    373:        ssp.data_bits = 8;
                    374:     if (s->scsmr2 & SH7750_SCSMR_PE) {
                    375:        if (s->scsmr2 & SH7750_SCSMR_PM_ODD)
                    376:            ssp.parity = 'O';
                    377:        else
                    378:            ssp.parity = 'E';
                    379:     } else
                    380:        ssp.parity = 'N';
                    381:     if (s->scsmr2 & SH7750_SCSMR_STOP_2)
                    382:        ssp.stop_bits = 2;
                    383:     else
                    384:        ssp.stop_bits = 1;
                    385:     fprintf(stderr, "SCSMR2=%04x SCBRR2=%02x\n", s->scsmr2, s->scbrr2);
                    386:     ssp.speed = s->periph_freq /
                    387:        (32 * s->scbrr2 * (1 << (2 * (s->scsmr2 & 3)))) - 1;
                    388:     fprintf(stderr, "data bits=%d, stop bits=%d, parity=%c, speed=%d\n",
                    389:            ssp.data_bits, ssp.stop_bits, ssp.parity, ssp.speed);
                    390:     qemu_chr_ioctl(s->serial2, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
                    391: }
                    392: 
                    393: static void scscr2_changed(SH7750State * s)
                    394: {
                    395:     if (s->scscr2 & (SH7750_SCSCR_TE | SH7750_SCSCR_RE)) {
                    396:        if (!s->serial2) {
                    397:            fprintf(stderr, "serial port 2 not bound to anything\n");
                    398:            assert(0);
                    399:        }
                    400:        serial2_update_parameters(s);
                    401:     }
                    402: }
                    403: 
                    404: static void init_serial2(SH7750State * s, int serial_nb)
                    405: {
                    406:     CharDriverState *chr;
                    407: 
                    408:     s->scfsr2 = 0x0060;
                    409: 
                    410:     chr = serial_hds[serial_nb];
                    411:     if (!chr) {
                    412:        fprintf(stderr,
                    413:                "no serial port associated to SH7750 second serial port\n");
                    414:        return;
                    415:     }
                    416: 
                    417:     s->serial2 = chr;
                    418:     qemu_chr_add_read_handler(chr, serial2_can_receive,
                    419:                              serial2_receive, s);
                    420:     qemu_chr_add_event_handler(chr, serial2_event);
                    421: }
                    422: 
                    423: static void init_serial_ports(SH7750State * s)
                    424: {
                    425:     init_serial1(s, 0);
                    426:     init_serial2(s, 1);
                    427: }
                    428: 
                    429: /**********************************************************************
                    430:  I/O ports
                    431: **********************************************************************/
                    432: 
                    433: int sh7750_register_io_device(SH7750State * s, sh7750_io_device * device)
                    434: {
                    435:     int i;
                    436: 
                    437:     for (i = 0; i < NB_DEVICES; i++) {
                    438:        if (s->devices[i] == NULL) {
                    439:            s->devices[i] = device;
                    440:            return 0;
                    441:        }
                    442:     }
                    443:     return -1;
                    444: }
                    445: 
                    446: static uint16_t portdir(uint32_t v)
                    447: {
                    448: #define EVENPORTMASK(n) ((v & (1<<((n)<<1))) >> (n))
                    449:     return
                    450:        EVENPORTMASK(15) | EVENPORTMASK(14) | EVENPORTMASK(13) |
                    451:        EVENPORTMASK(12) | EVENPORTMASK(11) | EVENPORTMASK(10) |
                    452:        EVENPORTMASK(9) | EVENPORTMASK(8) | EVENPORTMASK(7) |
                    453:        EVENPORTMASK(6) | EVENPORTMASK(5) | EVENPORTMASK(4) |
                    454:        EVENPORTMASK(3) | EVENPORTMASK(2) | EVENPORTMASK(1) |
                    455:        EVENPORTMASK(0);
                    456: }
                    457: 
                    458: static uint16_t portpullup(uint32_t v)
                    459: {
                    460: #define ODDPORTMASK(n) ((v & (1<<(((n)<<1)+1))) >> (n))
                    461:     return
                    462:        ODDPORTMASK(15) | ODDPORTMASK(14) | ODDPORTMASK(13) |
                    463:        ODDPORTMASK(12) | ODDPORTMASK(11) | ODDPORTMASK(10) |
                    464:        ODDPORTMASK(9) | ODDPORTMASK(8) | ODDPORTMASK(7) | ODDPORTMASK(6) |
                    465:        ODDPORTMASK(5) | ODDPORTMASK(4) | ODDPORTMASK(3) | ODDPORTMASK(2) |
                    466:        ODDPORTMASK(1) | ODDPORTMASK(0);
                    467: }
                    468: 
                    469: static uint16_t porta_lines(SH7750State * s)
                    470: {
                    471:     return (s->portdira & s->pdtra) |  /* CPU */
                    472:        (s->periph_portdira & s->periph_pdtra) |        /* Peripherals */
                    473:        (~(s->portdira | s->periph_portdira) & s->portpullupa); /* Pullups */
                    474: }
                    475: 
                    476: static uint16_t portb_lines(SH7750State * s)
                    477: {
                    478:     return (s->portdirb & s->pdtrb) |  /* CPU */
                    479:        (s->periph_portdirb & s->periph_pdtrb) |        /* Peripherals */
                    480:        (~(s->portdirb | s->periph_portdirb) & s->portpullupb); /* Pullups */
                    481: }
                    482: 
                    483: static void gen_port_interrupts(SH7750State * s)
                    484: {
                    485:     /* XXXXX interrupts not generated */
                    486: }
                    487: 
                    488: static void porta_changed(SH7750State * s, uint16_t prev)
                    489: {
                    490:     uint16_t currenta, changes;
                    491:     int i, r = 0;
                    492: 
                    493: #if 0
                    494:     fprintf(stderr, "porta changed from 0x%04x to 0x%04x\n",
                    495:            prev, porta_lines(s));
                    496:     fprintf(stderr, "pdtra=0x%04x, pctra=0x%08x\n", s->pdtra, s->pctra);
                    497: #endif
                    498:     currenta = porta_lines(s);
                    499:     if (currenta == prev)
                    500:        return;
                    501:     changes = currenta ^ prev;
                    502: 
                    503:     for (i = 0; i < NB_DEVICES; i++) {
                    504:        if (s->devices[i] && (s->devices[i]->portamask_trigger & changes)) {
                    505:            r |= s->devices[i]->port_change_cb(currenta, portb_lines(s),
                    506:                                               &s->periph_pdtra,
                    507:                                               &s->periph_portdira,
                    508:                                               &s->periph_pdtrb,
                    509:                                               &s->periph_portdirb);
                    510:        }
                    511:     }
                    512: 
                    513:     if (r)
                    514:        gen_port_interrupts(s);
                    515: }
                    516: 
                    517: static void portb_changed(SH7750State * s, uint16_t prev)
                    518: {
                    519:     uint16_t currentb, changes;
                    520:     int i, r = 0;
                    521: 
                    522:     currentb = portb_lines(s);
                    523:     if (currentb == prev)
                    524:        return;
                    525:     changes = currentb ^ prev;
                    526: 
                    527:     for (i = 0; i < NB_DEVICES; i++) {
                    528:        if (s->devices[i] && (s->devices[i]->portbmask_trigger & changes)) {
                    529:            r |= s->devices[i]->port_change_cb(portb_lines(s), currentb,
                    530:                                               &s->periph_pdtra,
                    531:                                               &s->periph_portdira,
                    532:                                               &s->periph_pdtrb,
                    533:                                               &s->periph_portdirb);
                    534:        }
                    535:     }
                    536: 
                    537:     if (r)
                    538:        gen_port_interrupts(s);
                    539: }
                    540: 
                    541: /**********************************************************************
                    542:  Memory
                    543: **********************************************************************/
                    544: 
                    545: static void error_access(const char *kind, target_phys_addr_t addr)
                    546: {
                    547:     fprintf(stderr, "%s to %s (0x%08x) not supported\n",
                    548:            kind, regname(addr), addr);
                    549: }
                    550: 
                    551: static void ignore_access(const char *kind, target_phys_addr_t addr)
                    552: {
                    553:     fprintf(stderr, "%s to %s (0x%08x) ignored\n",
                    554:            kind, regname(addr), addr);
                    555: }
                    556: 
                    557: static uint32_t sh7750_mem_readb(void *opaque, target_phys_addr_t addr)
                    558: {
                    559:     SH7750State *s = opaque;
                    560:     uint8_t r;
                    561: 
                    562:     switch (addr) {
                    563:     case SH7750_SCSSR1_A7:
                    564:        r = s->scssr1;
                    565:        s->scssr1_read |= r;
                    566:        return s->scssr1;
                    567:     case SH7750_SCRDR1_A7:
                    568:        s->scssr1 &= ~SH7750_SCSSR1_RDRF;
                    569:        return s->scrdr1;
                    570:     default:
                    571:        error_access("byte read", addr);
                    572:        assert(0);
                    573:     }
                    574: }
                    575: 
                    576: static uint32_t sh7750_mem_readw(void *opaque, target_phys_addr_t addr)
                    577: {
                    578:     SH7750State *s = opaque;
                    579:     uint16_t r;
                    580: 
                    581:     switch (addr) {
                    582:     case SH7750_RFCR_A7:
                    583:        fprintf(stderr,
                    584:                "Read access to refresh count register, incrementing\n");
                    585:        return s->rfcr++;
                    586:     case SH7750_TCR0_A7:
                    587:        return s->tcr0;
                    588:     case SH7750_SCLSR2_A7:
                    589:        /* Read and clear overflow bit */
                    590:        r = s->sclsr2;
                    591:        s->sclsr2 = 0;
                    592:        return r;
                    593:     case SH7750_SCSFR2_A7:
                    594:        return s->scfsr2;
                    595:     case SH7750_PDTRA_A7:
                    596:        return porta_lines(s);
                    597:     case SH7750_PDTRB_A7:
                    598:        return portb_lines(s);
                    599:     default:
                    600:        error_access("word read", addr);
                    601:        assert(0);
                    602:     }
                    603: }
                    604: 
                    605: static uint32_t sh7750_mem_readl(void *opaque, target_phys_addr_t addr)
                    606: {
                    607:     SH7750State *s = opaque;
                    608: 
                    609:     switch (addr) {
                    610:     case SH7750_MMUCR_A7:
                    611:        return s->cpu->mmucr;
                    612:     case SH7750_PTEH_A7:
                    613:        return s->cpu->pteh;
                    614:     case SH7750_PTEL_A7:
                    615:        return s->cpu->ptel;
                    616:     case SH7750_TTB_A7:
                    617:        return s->cpu->ttb;
                    618:     case SH7750_TEA_A7:
                    619:        return s->cpu->tea;
                    620:     case SH7750_TRA_A7:
                    621:        return s->cpu->tra;
                    622:     case SH7750_EXPEVT_A7:
                    623:        return s->cpu->expevt;
                    624:     case SH7750_INTEVT_A7:
                    625:        return s->cpu->intevt;
                    626:     case SH7750_CCR_A7:
                    627:        return s->ccr;
                    628:     case 0x1f000030:           /* Processor version PVR */
                    629:        return 0x00050000;      /* SH7750R */
                    630:     case 0x1f000040:           /* Processor version CVR */
                    631:        return 0x00110000;      /* Minimum caches */
                    632:     case 0x1f000044:           /* Processor version PRR */
                    633:        return 0x00000100;      /* SH7750R */
                    634:     default:
                    635:        error_access("long read", addr);
                    636:        assert(0);
                    637:     }
                    638: }
                    639: 
                    640: static void sh7750_mem_writeb(void *opaque, target_phys_addr_t addr,
                    641:                              uint32_t mem_value)
                    642: {
                    643:     SH7750State *s = opaque;
                    644: 
                    645:     switch (addr) {
                    646:        /* PRECHARGE ? XXXXX */
                    647:     case SH7750_PRECHARGE0_A7:
                    648:     case SH7750_PRECHARGE1_A7:
                    649:        ignore_access("byte write", addr);
                    650:        return;
                    651:     case SH7750_SCBRR2_A7:
                    652:        s->scbrr2 = mem_value;
                    653:        return;
                    654:     case SH7750_TSTR_A7:
                    655:        s->tstr = mem_value;
                    656:        timer_start_changed(s);
                    657:        return;
                    658:     case SH7750_SCSCR1_A7:
                    659:        s->scscr1 = mem_value;
                    660:        scscr1_changed(s);
                    661:        return;
                    662:     case SH7750_SCSMR1_A7:
                    663:        s->scsmr1 = mem_value;
                    664:        return;
                    665:     case SH7750_SCBRR1_A7:
                    666:        s->scbrr1 = mem_value;
                    667:        return;
                    668:     case SH7750_SCTDR1_A7:
                    669:        s->scssr1 &= ~SH7750_SCSSR1_TEND;
                    670:        s->sctdr1 = mem_value;
                    671:        return;
                    672:     case SH7750_SCSSR1_A7:
                    673:        serial1_change_scssr1(s, mem_value);
                    674:        return;
                    675:     default:
                    676:        error_access("byte write", addr);
                    677:        assert(0);
                    678:     }
                    679: }
                    680: 
                    681: static void sh7750_mem_writew(void *opaque, target_phys_addr_t addr,
                    682:                              uint32_t mem_value)
                    683: {
                    684:     SH7750State *s = opaque;
                    685:     uint16_t temp;
                    686: 
                    687:     switch (addr) {
                    688:        /* SDRAM controller */
                    689:     case SH7750_SCBRR1_A7:
                    690:     case SH7750_SCBRR2_A7:
                    691:     case SH7750_BCR2_A7:
                    692:     case SH7750_BCR3_A7:
                    693:     case SH7750_RTCOR_A7:
                    694:     case SH7750_RTCNT_A7:
                    695:     case SH7750_RTCSR_A7:
                    696:        ignore_access("word write", addr);
                    697:        return;
                    698:        /* IO ports */
                    699:     case SH7750_PDTRA_A7:
                    700:        temp = porta_lines(s);
                    701:        s->pdtra = mem_value;
                    702:        porta_changed(s, temp);
                    703:        return;
                    704:     case SH7750_PDTRB_A7:
                    705:        temp = portb_lines(s);
                    706:        s->pdtrb = mem_value;
                    707:        portb_changed(s, temp);
                    708:        return;
                    709:     case SH7750_RFCR_A7:
                    710:        fprintf(stderr, "Write access to refresh count register\n");
                    711:        s->rfcr = mem_value;
                    712:        return;
                    713:     case SH7750_SCLSR2_A7:
                    714:        s->sclsr2 = mem_value;
                    715:        return;
                    716:     case SH7750_SCSCR2_A7:
                    717:        s->scscr2 = mem_value;
                    718:        scscr2_changed(s);
                    719:        return;
                    720:     case SH7750_SCFCR2_A7:
                    721:        s->scfcr2 = mem_value;
                    722:        return;
                    723:     case SH7750_SCSMR2_A7:
                    724:        s->scsmr2 = mem_value;
                    725:        return;
                    726:     case SH7750_TCR0_A7:
                    727:        s->tcr0 = mem_value;
                    728:        return;
                    729:     case SH7750_GPIOIC_A7:
                    730:        s->gpioic = mem_value;
                    731:        if (mem_value != 0) {
                    732:            fprintf(stderr, "I/O interrupts not implemented\n");
                    733:            assert(0);
                    734:        }
                    735:        return;
                    736:     default:
                    737:        error_access("word write", addr);
                    738:        assert(0);
                    739:     }
                    740: }
                    741: 
                    742: static void sh7750_mem_writel(void *opaque, target_phys_addr_t addr,
                    743:                              uint32_t mem_value)
                    744: {
                    745:     SH7750State *s = opaque;
                    746:     uint16_t temp;
                    747: 
                    748:     switch (addr) {
                    749:        /* SDRAM controller */
                    750:     case SH7750_BCR1_A7:
                    751:     case SH7750_BCR4_A7:
                    752:     case SH7750_WCR1_A7:
                    753:     case SH7750_WCR2_A7:
                    754:     case SH7750_WCR3_A7:
                    755:     case SH7750_MCR_A7:
                    756:        ignore_access("long write", addr);
                    757:        return;
                    758:        /* IO ports */
                    759:     case SH7750_PCTRA_A7:
                    760:        temp = porta_lines(s);
                    761:        s->pctra = mem_value;
                    762:        s->portdira = portdir(mem_value);
                    763:        s->portpullupa = portpullup(mem_value);
                    764:        porta_changed(s, temp);
                    765:        return;
                    766:     case SH7750_PCTRB_A7:
                    767:        temp = portb_lines(s);
                    768:        s->pctrb = mem_value;
                    769:        s->portdirb = portdir(mem_value);
                    770:        s->portpullupb = portpullup(mem_value);
                    771:        portb_changed(s, temp);
                    772:        return;
                    773:     case SH7750_TCNT0_A7:
                    774:        s->tcnt0 = mem_value & 0xf;
                    775:        return;
                    776:     case SH7750_MMUCR_A7:
                    777:        s->cpu->mmucr = mem_value;
                    778:        return;
                    779:     case SH7750_PTEH_A7:
                    780:        s->cpu->pteh = mem_value;
                    781:        return;
                    782:     case SH7750_PTEL_A7:
                    783:        s->cpu->ptel = mem_value;
                    784:        return;
                    785:     case SH7750_TTB_A7:
                    786:        s->cpu->ttb = mem_value;
                    787:        return;
                    788:     case SH7750_TEA_A7:
                    789:        s->cpu->tea = mem_value;
                    790:        return;
                    791:     case SH7750_TRA_A7:
                    792:        s->cpu->tra = mem_value & 0x000007ff;
                    793:        return;
                    794:     case SH7750_EXPEVT_A7:
                    795:        s->cpu->expevt = mem_value & 0x000007ff;
                    796:        return;
                    797:     case SH7750_INTEVT_A7:
                    798:        s->cpu->intevt = mem_value & 0x000007ff;
                    799:        return;
                    800:     case SH7750_CCR_A7:
                    801:        s->ccr = mem_value;
                    802:        return;
                    803:     default:
                    804:        error_access("long write", addr);
                    805:        assert(0);
                    806:     }
                    807: }
                    808: 
                    809: static CPUReadMemoryFunc *sh7750_mem_read[] = {
                    810:     sh7750_mem_readb,
                    811:     sh7750_mem_readw,
                    812:     sh7750_mem_readl
                    813: };
                    814: 
                    815: static CPUWriteMemoryFunc *sh7750_mem_write[] = {
                    816:     sh7750_mem_writeb,
                    817:     sh7750_mem_writew,
                    818:     sh7750_mem_writel
                    819: };
                    820: 
                    821: SH7750State *sh7750_init(CPUSH4State * cpu)
                    822: {
                    823:     SH7750State *s;
                    824:     int sh7750_io_memory;
                    825: 
                    826:     s = qemu_mallocz(sizeof(SH7750State));
                    827:     s->cpu = cpu;
                    828:     s->periph_freq = 60000000; /* 60MHz */
                    829:     sh7750_io_memory = cpu_register_io_memory(0,
                    830:                                              sh7750_mem_read,
                    831:                                              sh7750_mem_write, s);
                    832:     cpu_register_physical_memory(0x1c000000, 0x04000000, sh7750_io_memory);
                    833:     init_timers(s);
                    834:     init_serial_ports(s);
                    835:     return s;
                    836: }

unix.superglobalmegacorp.com