Annotation of qemu/hw/etraxfs_timer.c, revision 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.