|
|
1.1 ! root 1: /* ! 2: * QEMU ETRAX Interrupt Controller. ! 3: * ! 4: * Copyright (c) 2008 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: ! 25: #include <stdio.h> ! 26: #include "hw.h" ! 27: #include "etraxfs.h" ! 28: ! 29: #define D(x) ! 30: ! 31: struct fs_pic_state_t ! 32: { ! 33: CPUState *env; ! 34: ! 35: uint32_t rw_mask; ! 36: /* Active interrupt lines. */ ! 37: uint32_t r_vect; ! 38: /* Active lines, gated through the mask. */ ! 39: uint32_t r_masked_vect; ! 40: uint32_t r_nmi; ! 41: uint32_t r_guru; ! 42: }; ! 43: ! 44: static void pic_update(struct fs_pic_state_t *fs) ! 45: { ! 46: CPUState *env = fs->env; ! 47: int i; ! 48: uint32_t vector = 0; ! 49: ! 50: fs->r_masked_vect = fs->r_vect & fs->rw_mask; ! 51: ! 52: /* The ETRAX interrupt controller signals interrupts to teh core ! 53: through an interrupt request wire and an irq vector bus. If ! 54: multiple interrupts are simultaneously active it chooses vector ! 55: 0x30 and lets the sw choose the priorities. */ ! 56: if (fs->r_masked_vect) { ! 57: uint32_t mv = fs->r_masked_vect; ! 58: for (i = 0; i < 31; i++) { ! 59: if (mv & 1) { ! 60: vector = 0x31 + i; ! 61: /* Check for multiple interrupts. */ ! 62: if (mv > 1) ! 63: vector = 0x30; ! 64: break; ! 65: } ! 66: mv >>= 1; ! 67: } ! 68: if (vector) { ! 69: env->interrupt_vector = vector; ! 70: D(printf("%s vector=%x\n", __func__, vector)); ! 71: cpu_interrupt(env, CPU_INTERRUPT_HARD); ! 72: } ! 73: } else { ! 74: env->interrupt_vector = 0; ! 75: cpu_reset_interrupt(env, CPU_INTERRUPT_HARD); ! 76: D(printf("%s reset irqs\n", __func__)); ! 77: } ! 78: } ! 79: ! 80: static uint32_t pic_readl (void *opaque, target_phys_addr_t addr) ! 81: { ! 82: struct fs_pic_state_t *fs = opaque; ! 83: uint32_t rval; ! 84: ! 85: switch (addr) ! 86: { ! 87: case 0x0: ! 88: rval = fs->rw_mask; ! 89: break; ! 90: case 0x4: ! 91: rval = fs->r_vect; ! 92: break; ! 93: case 0x8: ! 94: rval = fs->r_masked_vect; ! 95: break; ! 96: case 0xc: ! 97: rval = fs->r_nmi; ! 98: break; ! 99: case 0x10: ! 100: rval = fs->r_guru; ! 101: break; ! 102: default: ! 103: cpu_abort(fs->env, "invalid PIC register.\n"); ! 104: break; ! 105: ! 106: } ! 107: D(printf("%s %x=%x\n", __func__, addr, rval)); ! 108: return rval; ! 109: } ! 110: ! 111: static void ! 112: pic_writel (void *opaque, target_phys_addr_t addr, uint32_t value) ! 113: { ! 114: struct fs_pic_state_t *fs = opaque; ! 115: D(printf("%s addr=%x val=%x\n", __func__, addr, value)); ! 116: switch (addr) ! 117: { ! 118: case 0x0: ! 119: fs->rw_mask = value; ! 120: pic_update(fs); ! 121: break; ! 122: default: ! 123: cpu_abort(fs->env, "invalid PIC register.\n"); ! 124: break; ! 125: } ! 126: } ! 127: ! 128: static CPUReadMemoryFunc *pic_read[] = { ! 129: NULL, NULL, ! 130: &pic_readl, ! 131: }; ! 132: ! 133: static CPUWriteMemoryFunc *pic_write[] = { ! 134: NULL, NULL, ! 135: &pic_writel, ! 136: }; ! 137: ! 138: void pic_info(void) ! 139: { ! 140: } ! 141: ! 142: void irq_info(void) ! 143: { ! 144: } ! 145: ! 146: static void irq_handler(void *opaque, int irq, int level) ! 147: { ! 148: struct fs_pic_state_t *fs = (void *)opaque; ! 149: ! 150: D(printf("%s irq=%d level=%d mask=%x v=%x mv=%x\n", ! 151: __func__, irq, level, ! 152: fs->rw_mask, fs->r_vect, fs->r_masked_vect)); ! 153: ! 154: irq -= 1; ! 155: fs->r_vect &= ~(1 << irq); ! 156: fs->r_vect |= (!!level << irq); ! 157: ! 158: pic_update(fs); ! 159: } ! 160: ! 161: static void nmi_handler(void *opaque, int irq, int level) ! 162: { ! 163: struct fs_pic_state_t *fs = (void *)opaque; ! 164: CPUState *env = fs->env; ! 165: uint32_t mask; ! 166: ! 167: mask = 1 << irq; ! 168: if (level) ! 169: fs->r_nmi |= mask; ! 170: else ! 171: fs->r_nmi &= ~mask; ! 172: ! 173: if (fs->r_nmi) ! 174: cpu_interrupt(env, CPU_INTERRUPT_NMI); ! 175: else ! 176: cpu_reset_interrupt(env, CPU_INTERRUPT_NMI); ! 177: } ! 178: ! 179: static void guru_handler(void *opaque, int irq, int level) ! 180: { ! 181: struct fs_pic_state_t *fs = (void *)opaque; ! 182: CPUState *env = fs->env; ! 183: cpu_abort(env, "%s unsupported exception\n", __func__); ! 184: ! 185: } ! 186: ! 187: struct etraxfs_pic *etraxfs_pic_init(CPUState *env, target_phys_addr_t base) ! 188: { ! 189: struct fs_pic_state_t *fs = NULL; ! 190: struct etraxfs_pic *pic = NULL; ! 191: int intr_vect_regs; ! 192: ! 193: pic = qemu_mallocz(sizeof *pic); ! 194: pic->internal = fs = qemu_mallocz(sizeof *fs); ! 195: ! 196: fs->env = env; ! 197: pic->irq = qemu_allocate_irqs(irq_handler, fs, 30); ! 198: pic->nmi = qemu_allocate_irqs(nmi_handler, fs, 2); ! 199: pic->guru = qemu_allocate_irqs(guru_handler, fs, 1); ! 200: ! 201: intr_vect_regs = cpu_register_io_memory(0, pic_read, pic_write, fs); ! 202: cpu_register_physical_memory(base, 0x14, intr_vect_regs); ! 203: ! 204: return pic; ! 205: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.