Annotation of qemu/hw/etraxfs_timer.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * QEMU ETRAX System Emulator
                      3:  *
                      4:  * Copyright (c) 2007 Edgar E. Iglesias, Axis Communications AB.
                      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 <sys/time.h>
                     26: #include "hw.h"
                     27: #include "qemu-timer.h"
                     28: 
                     29: void etrax_ack_irq(CPUState *env, uint32_t mask);
                     30: 
                     31: #define R_TIME 0xb001e038
                     32: #define RW_TMR0_DIV 0xb001e000
                     33: #define R_TMR0_DATA 0xb001e004
                     34: #define RW_TMR0_CTRL 0xb001e008
                     35: #define RW_TMR1_DIV 0xb001e010
                     36: #define R_TMR1_DATA 0xb001e014
                     37: #define RW_TMR1_CTRL 0xb001e018
                     38: 
                     39: #define RW_INTR_MASK 0xb001e048
                     40: #define RW_ACK_INTR 0xb001e04c
                     41: #define R_INTR 0xb001e050
                     42: #define R_MASKED_INTR 0xb001e054
                     43: 
                     44: 
                     45: uint32_t rw_intr_mask;
                     46: uint32_t rw_ack_intr;
                     47: uint32_t r_intr;
                     48: 
                     49: struct fs_timer_t {
                     50:        QEMUBH *bh;
                     51:        unsigned int limit;
                     52:        int scale;
                     53:        ptimer_state *ptimer;
                     54:        CPUState *env;
                     55:        qemu_irq *irq;
                     56:        uint32_t mask;
                     57: };
                     58: 
                     59: static struct fs_timer_t timer0;
                     60: 
                     61: /* diff two timevals.  Return a single int in us. */
                     62: int diff_timeval_us(struct timeval *a, struct timeval *b)
                     63: {
                     64:         int diff;
                     65: 
                     66:         /* assume these values are signed.  */
                     67:         diff = (a->tv_sec - b->tv_sec) * 1000 * 1000;
                     68:         diff += (a->tv_usec - b->tv_usec);
                     69:         return diff;
                     70: }
                     71: 
                     72: static uint32_t timer_readb (void *opaque, target_phys_addr_t addr)
                     73: {
                     74:        CPUState *env = opaque;
                     75:        uint32_t r = 0;
                     76:        printf ("%s %x pc=%x\n", __func__, addr, env->pc);
                     77:        return r;
                     78: }
                     79: static uint32_t timer_readw (void *opaque, target_phys_addr_t addr)
                     80: {
                     81:        CPUState *env = opaque;
                     82:        uint32_t r = 0;
                     83:        printf ("%s %x pc=%x\n", __func__, addr, env->pc);
                     84:        return r;
                     85: }
                     86: 
                     87: static uint32_t timer_readl (void *opaque, target_phys_addr_t addr)
                     88: {
                     89:        CPUState *env = opaque;
                     90:        uint32_t r = 0;
                     91: 
                     92:        switch (addr) {
                     93:        case R_TMR0_DATA:
                     94:                break;
                     95:        case R_TMR1_DATA:
                     96:                printf ("R_TMR1_DATA\n");
                     97:                break;
                     98:        case R_TIME:
                     99:        {
                    100:                static struct timeval last;
                    101:                struct timeval now;
                    102:                gettimeofday(&now, NULL);
                    103:                if (!(last.tv_sec == 0 && last.tv_usec == 0)) {
                    104:                        r = diff_timeval_us(&now, &last);
                    105:                        r *= 1000; /* convert to ns.  */
                    106:                        r++; /* make sure we increase for each call.  */
                    107:                }
                    108:                last = now;
                    109:                break;
                    110:        }
                    111: 
                    112:        case RW_INTR_MASK:
                    113:                r = rw_intr_mask;
                    114:                break;
                    115:        case R_MASKED_INTR:
                    116:                r = r_intr & rw_intr_mask;
                    117:                break;
                    118:        default:
                    119:                printf ("%s %x p=%x\n", __func__, addr, env->pc);
                    120:                break;
                    121:        }
                    122:        return r;
                    123: }
                    124: 
                    125: static void
                    126: timer_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
                    127: {
                    128:        CPUState *env = opaque;
                    129:        printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc);
                    130: }
                    131: static void
                    132: timer_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
                    133: {
                    134:        CPUState *env = opaque;
                    135:        printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc);
                    136: }
                    137: 
                    138: static void write_ctrl(struct fs_timer_t *t, uint32_t v)
                    139: {
                    140:        int op;
                    141:        int freq;
                    142:        int freq_hz;
                    143: 
                    144:        op = v & 3;
                    145:        freq = v >> 2;
                    146:        freq_hz = 32000000;
                    147: 
                    148:        switch (freq)
                    149:        {
                    150:        case 0:
                    151:        case 1:
                    152:                printf ("extern or disabled timer clock?\n");
                    153:                break;
                    154:        case 4: freq_hz =  29493000; break;
                    155:        case 5: freq_hz =  32000000; break;
                    156:        case 6: freq_hz =  32768000; break;
                    157:        case 7: freq_hz = 100000000; break;
                    158:        default:
                    159:                abort();
                    160:                break;
                    161:        }
                    162: 
                    163:        printf ("freq_hz=%d limit=%d\n", freq_hz, t->limit);
                    164:        t->scale = 0;
                    165:        if (t->limit > 2048)
                    166:        {
                    167:                t->scale = 2048;
                    168:                ptimer_set_period(timer0.ptimer, freq_hz / t->scale);
                    169:        }
                    170: 
                    171:        printf ("op=%d\n", op);
                    172:        switch (op)
                    173:        {
                    174:                case 0:
                    175:                        printf ("limit=%d %d\n", t->limit, t->limit/t->scale);
                    176:                        ptimer_set_limit(t->ptimer, t->limit / t->scale, 1);
                    177:                        break;
                    178:                case 1:
                    179:                        ptimer_stop(t->ptimer);
                    180:                        break;
                    181:                case 2:
                    182:                        ptimer_run(t->ptimer, 0);
                    183:                        break;
                    184:                default:
                    185:                        abort();
                    186:                        break;
                    187:        }
                    188: }
                    189: 
                    190: static void timer_ack_irq(void)
                    191: {
                    192:        if (!(r_intr & timer0.mask & rw_intr_mask)) {
                    193:                qemu_irq_lower(timer0.irq[0]);
                    194:                etrax_ack_irq(timer0.env, 1 << 0x1b);
                    195:        }
                    196: }
                    197: 
                    198: static void
                    199: timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
                    200: {
                    201:        CPUState *env = opaque;
                    202:        printf ("%s %x %x pc=%x\n",
                    203:                __func__, addr, value, env->pc);
                    204:        switch (addr)
                    205:        {
                    206:                case RW_TMR0_DIV:
                    207:                        printf ("RW_TMR0_DIV=%x\n", value);
                    208:                        timer0.limit = value;
                    209:                        break;
                    210:                case RW_TMR0_CTRL:
                    211:                        printf ("RW_TMR0_CTRL=%x\n", value);
                    212:                        write_ctrl(&timer0, value);
                    213:                        break;
                    214:                case RW_TMR1_DIV:
                    215:                        printf ("RW_TMR1_DIV=%x\n", value);
                    216:                        break;
                    217:                case RW_TMR1_CTRL:
                    218:                        printf ("RW_TMR1_CTRL=%x\n", value);
                    219:                        break;
                    220:                case RW_INTR_MASK:
                    221:                        printf ("RW_INTR_MASK=%x\n", value);
                    222:                        rw_intr_mask = value;
                    223:                        break;
                    224:                case RW_ACK_INTR:
                    225:                        r_intr &= ~value;
                    226:                        timer_ack_irq();
                    227:                        break;
                    228:                default:
                    229:                        printf ("%s %x %x pc=%x\n",
                    230:                                __func__, addr, value, env->pc);
                    231:                        break;
                    232:        }
                    233: }
                    234: 
                    235: static CPUReadMemoryFunc *timer_read[] = {
                    236:     &timer_readb,
                    237:     &timer_readw,
                    238:     &timer_readl,
                    239: };
                    240: 
                    241: static CPUWriteMemoryFunc *timer_write[] = {
                    242:     &timer_writeb,
                    243:     &timer_writew,
                    244:     &timer_writel,
                    245: };
                    246: 
                    247: static void timer_irq(void *opaque)
                    248: {
                    249:        struct fs_timer_t *t = opaque;
                    250: 
                    251:        r_intr |= t->mask;
                    252:        if (t->mask & rw_intr_mask) {
                    253:                qemu_irq_raise(t->irq[0]);
                    254:        }
                    255: }
                    256: 
                    257: void etraxfs_timer_init(CPUState *env, qemu_irq *irqs)
                    258: {
                    259:        int timer_regs;
                    260: 
                    261:        timer0.bh = qemu_bh_new(timer_irq, &timer0);
                    262:        timer0.ptimer = ptimer_init(timer0.bh);
                    263:        timer0.irq = irqs + 0x1b;
                    264:        timer0.mask = 1;
                    265:        timer0.env = env;
                    266: 
                    267:        timer_regs = cpu_register_io_memory(0, timer_read, timer_write, env);
                    268:        cpu_register_physical_memory (0xb001e000, 0x5c, timer_regs);
                    269: }

unix.superglobalmegacorp.com

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