(linenum→info "unix/slp.c:2238")

qemu/0.9.1/hw/etraxfs_timer.c

    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: }
Syntax (Markdown)