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

qemu/0.9.1/hw/mcf_intc.c

    1: /*
    2:  * ColdFire Interrupt Controller emulation.
    3:  *
    4:  * Copyright (c) 2007 CodeSourcery.
    5:  *
    6:  * This code is licenced under the GPL
    7:  */
    8: #include "hw.h"
    9: #include "mcf.h"
   10: 
   11: typedef struct {
   12:     uint64_t ipr;
   13:     uint64_t imr;
   14:     uint64_t ifr;
   15:     uint64_t enabled;
   16:     uint8_t icr[64];
   17:     CPUState *env;
   18:     int active_vector;
   19: } mcf_intc_state;
   20: 
   21: static void mcf_intc_update(mcf_intc_state *s)
   22: {
   23:     uint64_t active;
   24:     int i;
   25:     int best;
   26:     int best_level;
   27: 
   28:     active = (s->ipr | s->ifr) & s->enabled & ~s->imr;
   29:     best_level = 0;
   30:     best = 64;
   31:     if (active) {
   32:         for (i = 0; i < 64; i++) {
   33:             if ((active & 1) != 0 && s->icr[i] >= best_level) {
   34:                 best_level = s->icr[i];
   35:                 best = i;
   36:             }
   37:             active >>= 1;
   38:         }
   39:     }
   40:     s->active_vector = ((best == 64) ? 24 : (best + 64));
   41:     m68k_set_irq_level(s->env, best_level, s->active_vector);
   42: }
   43: 
   44: static uint32_t mcf_intc_read(void *opaque, target_phys_addr_t addr)
   45: {
   46:     int offset;
   47:     mcf_intc_state *s = (mcf_intc_state *)opaque;
   48:     offset = addr & 0xff;
   49:     if (offset >= 0x40 && offset < 0x80) {
   50:         return s->icr[offset - 0x40];
   51:     }
   52:     switch (offset) {
   53:     case 0x00:
   54:         return (uint32_t)(s->ipr >> 32);
   55:     case 0x04:
   56:         return (uint32_t)s->ipr;
   57:     case 0x08:
   58:         return (uint32_t)(s->imr >> 32);
   59:     case 0x0c:
   60:         return (uint32_t)s->imr;
   61:     case 0x10:
   62:         return (uint32_t)(s->ifr >> 32);
   63:     case 0x14:
   64:         return (uint32_t)s->ifr;
   65:     case 0xe0: /* SWIACK.  */
   66:         return s->active_vector;
   67:     case 0xe1: case 0xe2: case 0xe3: case 0xe4:
   68:     case 0xe5: case 0xe6: case 0xe7:
   69:         /* LnIACK */
   70:         cpu_abort(cpu_single_env, "mcf_intc_read: LnIACK not implemented\n");
   71:     default:
   72:         return 0;
   73:     }
   74: }
   75: 
   76: static void mcf_intc_write(void *opaque, target_phys_addr_t addr, uint32_t val)
   77: {
   78:     int offset;
   79:     mcf_intc_state *s = (mcf_intc_state *)opaque;
   80:     offset = addr & 0xff;
   81:     if (offset >= 0x40 && offset < 0x80) {
   82:         int n = offset - 0x40;
   83:         s->icr[n] = val;
   84:         if (val == 0)
   85:             s->enabled &= ~(1ull << n);
   86:         else
   87:             s->enabled |= (1ull << n);
   88:         mcf_intc_update(s);
   89:         return;
   90:     }
   91:     switch (offset) {
   92:     case 0x00: case 0x04:
   93:         /* Ignore IPR writes.  */
   94:         return;
   95:     case 0x08:
   96:         s->imr = (s->imr & 0xffffffff) | ((uint64_t)val << 32);
   97:         break;
   98:     case 0x0c:
   99:         s->imr = (s->imr & 0xffffffff00000000ull) | (uint32_t)val;
  100:         break;
  101:     default:
  102:         cpu_abort(cpu_single_env, "mcf_intc_write: Bad write offset %d\n",
  103:                   offset);
  104:         break;
  105:     }
  106:     mcf_intc_update(s);
  107: }
  108: 
  109: static void mcf_intc_set_irq(void *opaque, int irq, int level)
  110: {
  111:     mcf_intc_state *s = (mcf_intc_state *)opaque;
  112:     if (irq >= 64)
  113:         return;
  114:     if (level)
  115:         s->ipr |= 1ull << irq;
  116:     else
  117:         s->ipr &= ~(1ull << irq);
  118:     mcf_intc_update(s);
  119: }
  120: 
  121: static void mcf_intc_reset(mcf_intc_state *s)
  122: {
  123:     s->imr = ~0ull;
  124:     s->ipr = 0;
  125:     s->ifr = 0;
  126:     s->enabled = 0;
  127:     memset(s->icr, 0, 64);
  128:     s->active_vector = 24;
  129: }
  130: 
  131: static CPUReadMemoryFunc *mcf_intc_readfn[] = {
  132:    mcf_intc_read,
  133:    mcf_intc_read,
  134:    mcf_intc_read
  135: };
  136: 
  137: static CPUWriteMemoryFunc *mcf_intc_writefn[] = {
  138:    mcf_intc_write,
  139:    mcf_intc_write,
  140:    mcf_intc_write
  141: };
  142: 
  143: qemu_irq *mcf_intc_init(target_phys_addr_t base, CPUState *env)
  144: {
  145:     mcf_intc_state *s;
  146:     int iomemtype;
  147: 
  148:     s = qemu_mallocz(sizeof(mcf_intc_state));
  149:     s->env = env;
  150:     mcf_intc_reset(s);
  151: 
  152:     iomemtype = cpu_register_io_memory(0, mcf_intc_readfn,
  153:                                        mcf_intc_writefn, s);
  154:     cpu_register_physical_memory(base, 0x100, iomemtype);
  155: 
  156:     return qemu_allocate_irqs(mcf_intc_set_irq, s, 64);
  157: }
Syntax (Markdown)