186797937017f52bff088d02edf64fb931177a7eaJun Nakajima/* 286797937017f52bff088d02edf64fb931177a7eaJun Nakajima * QEMU 8259 interrupt controller emulation 386797937017f52bff088d02edf64fb931177a7eaJun Nakajima * 486797937017f52bff088d02edf64fb931177a7eaJun Nakajima * Copyright (c) 2003-2004 Fabrice Bellard 586797937017f52bff088d02edf64fb931177a7eaJun Nakajima * 686797937017f52bff088d02edf64fb931177a7eaJun Nakajima * Permission is hereby granted, free of charge, to any person obtaining a copy 786797937017f52bff088d02edf64fb931177a7eaJun Nakajima * of this software and associated documentation files (the "Software"), to deal 886797937017f52bff088d02edf64fb931177a7eaJun Nakajima * in the Software without restriction, including without limitation the rights 986797937017f52bff088d02edf64fb931177a7eaJun Nakajima * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 1086797937017f52bff088d02edf64fb931177a7eaJun Nakajima * copies of the Software, and to permit persons to whom the Software is 1186797937017f52bff088d02edf64fb931177a7eaJun Nakajima * furnished to do so, subject to the following conditions: 1286797937017f52bff088d02edf64fb931177a7eaJun Nakajima * 1386797937017f52bff088d02edf64fb931177a7eaJun Nakajima * The above copyright notice and this permission notice shall be included in 1486797937017f52bff088d02edf64fb931177a7eaJun Nakajima * all copies or substantial portions of the Software. 1586797937017f52bff088d02edf64fb931177a7eaJun Nakajima * 1686797937017f52bff088d02edf64fb931177a7eaJun Nakajima * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1786797937017f52bff088d02edf64fb931177a7eaJun Nakajima * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1886797937017f52bff088d02edf64fb931177a7eaJun Nakajima * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1986797937017f52bff088d02edf64fb931177a7eaJun Nakajima * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 2086797937017f52bff088d02edf64fb931177a7eaJun Nakajima * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 2186797937017f52bff088d02edf64fb931177a7eaJun Nakajima * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 2286797937017f52bff088d02edf64fb931177a7eaJun Nakajima * THE SOFTWARE. 2386797937017f52bff088d02edf64fb931177a7eaJun Nakajima */ 2486797937017f52bff088d02edf64fb931177a7eaJun Nakajima#include "hw.h" 2586797937017f52bff088d02edf64fb931177a7eaJun Nakajima#include "pc.h" 2686797937017f52bff088d02edf64fb931177a7eaJun Nakajima#include "isa.h" 2786797937017f52bff088d02edf64fb931177a7eaJun Nakajima#include "monitor.h" 28d0b482eb3e8cb699a2090bc773364d3a7d369a25Vladimir Chtchetkine#include "goldfish_device.h" 2986797937017f52bff088d02edf64fb931177a7eaJun Nakajima 3086797937017f52bff088d02edf64fb931177a7eaJun Nakajima/* debug PIC */ 3186797937017f52bff088d02edf64fb931177a7eaJun Nakajima//#define DEBUG_PIC 3286797937017f52bff088d02edf64fb931177a7eaJun Nakajima 3386797937017f52bff088d02edf64fb931177a7eaJun Nakajima//#define DEBUG_IRQ_LATENCY 3486797937017f52bff088d02edf64fb931177a7eaJun Nakajima//#define DEBUG_IRQ_COUNT 3586797937017f52bff088d02edf64fb931177a7eaJun Nakajima 3686797937017f52bff088d02edf64fb931177a7eaJun Nakajimatypedef struct PicState { 3786797937017f52bff088d02edf64fb931177a7eaJun Nakajima uint8_t last_irr; /* edge detection */ 3886797937017f52bff088d02edf64fb931177a7eaJun Nakajima uint8_t irr; /* interrupt request register */ 3986797937017f52bff088d02edf64fb931177a7eaJun Nakajima uint8_t imr; /* interrupt mask register */ 4086797937017f52bff088d02edf64fb931177a7eaJun Nakajima uint8_t isr; /* interrupt service register */ 4186797937017f52bff088d02edf64fb931177a7eaJun Nakajima uint8_t priority_add; /* highest irq priority */ 4286797937017f52bff088d02edf64fb931177a7eaJun Nakajima uint8_t irq_base; 4386797937017f52bff088d02edf64fb931177a7eaJun Nakajima uint8_t read_reg_select; 4486797937017f52bff088d02edf64fb931177a7eaJun Nakajima uint8_t poll; 4586797937017f52bff088d02edf64fb931177a7eaJun Nakajima uint8_t special_mask; 4686797937017f52bff088d02edf64fb931177a7eaJun Nakajima uint8_t init_state; 4786797937017f52bff088d02edf64fb931177a7eaJun Nakajima uint8_t auto_eoi; 4886797937017f52bff088d02edf64fb931177a7eaJun Nakajima uint8_t rotate_on_auto_eoi; 4986797937017f52bff088d02edf64fb931177a7eaJun Nakajima uint8_t special_fully_nested_mode; 5086797937017f52bff088d02edf64fb931177a7eaJun Nakajima uint8_t init4; /* true if 4 byte init */ 5186797937017f52bff088d02edf64fb931177a7eaJun Nakajima uint8_t single_mode; /* true if slave pic is not initialized */ 5286797937017f52bff088d02edf64fb931177a7eaJun Nakajima uint8_t elcr; /* PIIX edge/trigger selection*/ 5386797937017f52bff088d02edf64fb931177a7eaJun Nakajima uint8_t elcr_mask; 5486797937017f52bff088d02edf64fb931177a7eaJun Nakajima PicState2 *pics_state; 5586797937017f52bff088d02edf64fb931177a7eaJun Nakajima} PicState; 5686797937017f52bff088d02edf64fb931177a7eaJun Nakajima 5786797937017f52bff088d02edf64fb931177a7eaJun Nakajimastruct PicState2 { 5886797937017f52bff088d02edf64fb931177a7eaJun Nakajima /* 0 is master pic, 1 is slave pic */ 5986797937017f52bff088d02edf64fb931177a7eaJun Nakajima /* XXX: better separation between the two pics */ 6086797937017f52bff088d02edf64fb931177a7eaJun Nakajima PicState pics[2]; 6186797937017f52bff088d02edf64fb931177a7eaJun Nakajima qemu_irq parent_irq; 6286797937017f52bff088d02edf64fb931177a7eaJun Nakajima void *irq_request_opaque; 6386797937017f52bff088d02edf64fb931177a7eaJun Nakajima /* IOAPIC callback support */ 6486797937017f52bff088d02edf64fb931177a7eaJun Nakajima SetIRQFunc *alt_irq_func; 6586797937017f52bff088d02edf64fb931177a7eaJun Nakajima void *alt_irq_opaque; 6686797937017f52bff088d02edf64fb931177a7eaJun Nakajima}; 6786797937017f52bff088d02edf64fb931177a7eaJun Nakajima 6886797937017f52bff088d02edf64fb931177a7eaJun Nakajima#if defined(DEBUG_PIC) || defined (DEBUG_IRQ_COUNT) 6986797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic int irq_level[16]; 7086797937017f52bff088d02edf64fb931177a7eaJun Nakajima#endif 7186797937017f52bff088d02edf64fb931177a7eaJun Nakajima#ifdef DEBUG_IRQ_COUNT 7286797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic uint64_t irq_count[16]; 7386797937017f52bff088d02edf64fb931177a7eaJun Nakajima#endif 7486797937017f52bff088d02edf64fb931177a7eaJun Nakajima 7586797937017f52bff088d02edf64fb931177a7eaJun Nakajima/* set irq level. If an edge is detected, then the IRR is set to 1 */ 7686797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic inline void pic_set_irq1(PicState *s, int irq, int level) 7786797937017f52bff088d02edf64fb931177a7eaJun Nakajima{ 7886797937017f52bff088d02edf64fb931177a7eaJun Nakajima int mask; 7986797937017f52bff088d02edf64fb931177a7eaJun Nakajima mask = 1 << irq; 8086797937017f52bff088d02edf64fb931177a7eaJun Nakajima if (s->elcr & mask) { 8186797937017f52bff088d02edf64fb931177a7eaJun Nakajima /* level triggered */ 8286797937017f52bff088d02edf64fb931177a7eaJun Nakajima if (level) { 8386797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->irr |= mask; 8486797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->last_irr |= mask; 8586797937017f52bff088d02edf64fb931177a7eaJun Nakajima } else { 8686797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->irr &= ~mask; 8786797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->last_irr &= ~mask; 8886797937017f52bff088d02edf64fb931177a7eaJun Nakajima } 8986797937017f52bff088d02edf64fb931177a7eaJun Nakajima } else { 9086797937017f52bff088d02edf64fb931177a7eaJun Nakajima /* edge triggered */ 9186797937017f52bff088d02edf64fb931177a7eaJun Nakajima if (level) { 9286797937017f52bff088d02edf64fb931177a7eaJun Nakajima if ((s->last_irr & mask) == 0) 9386797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->irr |= mask; 9486797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->last_irr |= mask; 9586797937017f52bff088d02edf64fb931177a7eaJun Nakajima } else { 9686797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->last_irr &= ~mask; 9786797937017f52bff088d02edf64fb931177a7eaJun Nakajima } 9886797937017f52bff088d02edf64fb931177a7eaJun Nakajima } 9986797937017f52bff088d02edf64fb931177a7eaJun Nakajima} 10086797937017f52bff088d02edf64fb931177a7eaJun Nakajima 10186797937017f52bff088d02edf64fb931177a7eaJun Nakajima/* return the highest priority found in mask (highest = smallest 10286797937017f52bff088d02edf64fb931177a7eaJun Nakajima number). Return 8 if no irq */ 10386797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic inline int get_priority(PicState *s, int mask) 10486797937017f52bff088d02edf64fb931177a7eaJun Nakajima{ 10586797937017f52bff088d02edf64fb931177a7eaJun Nakajima int priority; 10686797937017f52bff088d02edf64fb931177a7eaJun Nakajima if (mask == 0) 10786797937017f52bff088d02edf64fb931177a7eaJun Nakajima return 8; 10886797937017f52bff088d02edf64fb931177a7eaJun Nakajima priority = 0; 10986797937017f52bff088d02edf64fb931177a7eaJun Nakajima while ((mask & (1 << ((priority + s->priority_add) & 7))) == 0) 11086797937017f52bff088d02edf64fb931177a7eaJun Nakajima priority++; 11186797937017f52bff088d02edf64fb931177a7eaJun Nakajima return priority; 11286797937017f52bff088d02edf64fb931177a7eaJun Nakajima} 11386797937017f52bff088d02edf64fb931177a7eaJun Nakajima 11486797937017f52bff088d02edf64fb931177a7eaJun Nakajima/* return the pic wanted interrupt. return -1 if none */ 11586797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic int pic_get_irq(PicState *s) 11686797937017f52bff088d02edf64fb931177a7eaJun Nakajima{ 11786797937017f52bff088d02edf64fb931177a7eaJun Nakajima int mask, cur_priority, priority; 11886797937017f52bff088d02edf64fb931177a7eaJun Nakajima 11986797937017f52bff088d02edf64fb931177a7eaJun Nakajima mask = s->irr & ~s->imr; 12086797937017f52bff088d02edf64fb931177a7eaJun Nakajima priority = get_priority(s, mask); 12186797937017f52bff088d02edf64fb931177a7eaJun Nakajima if (priority == 8) 12286797937017f52bff088d02edf64fb931177a7eaJun Nakajima return -1; 12386797937017f52bff088d02edf64fb931177a7eaJun Nakajima /* compute current priority. If special fully nested mode on the 12486797937017f52bff088d02edf64fb931177a7eaJun Nakajima master, the IRQ coming from the slave is not taken into account 12586797937017f52bff088d02edf64fb931177a7eaJun Nakajima for the priority computation. */ 12686797937017f52bff088d02edf64fb931177a7eaJun Nakajima mask = s->isr; 12786797937017f52bff088d02edf64fb931177a7eaJun Nakajima if (s->special_mask) 12886797937017f52bff088d02edf64fb931177a7eaJun Nakajima mask &= ~s->imr; 12986797937017f52bff088d02edf64fb931177a7eaJun Nakajima if (s->special_fully_nested_mode && s == &s->pics_state->pics[0]) 13086797937017f52bff088d02edf64fb931177a7eaJun Nakajima mask &= ~(1 << 2); 13186797937017f52bff088d02edf64fb931177a7eaJun Nakajima cur_priority = get_priority(s, mask); 13286797937017f52bff088d02edf64fb931177a7eaJun Nakajima if (priority < cur_priority) { 13386797937017f52bff088d02edf64fb931177a7eaJun Nakajima /* higher priority found: an irq should be generated */ 13486797937017f52bff088d02edf64fb931177a7eaJun Nakajima return (priority + s->priority_add) & 7; 13586797937017f52bff088d02edf64fb931177a7eaJun Nakajima } else { 13686797937017f52bff088d02edf64fb931177a7eaJun Nakajima return -1; 13786797937017f52bff088d02edf64fb931177a7eaJun Nakajima } 13886797937017f52bff088d02edf64fb931177a7eaJun Nakajima} 13986797937017f52bff088d02edf64fb931177a7eaJun Nakajima 14086797937017f52bff088d02edf64fb931177a7eaJun Nakajima/* raise irq to CPU if necessary. must be called every time the active 14186797937017f52bff088d02edf64fb931177a7eaJun Nakajima irq may change */ 14286797937017f52bff088d02edf64fb931177a7eaJun Nakajima/* XXX: should not export it, but it is needed for an APIC kludge */ 14386797937017f52bff088d02edf64fb931177a7eaJun Nakajimavoid pic_update_irq(PicState2 *s) 14486797937017f52bff088d02edf64fb931177a7eaJun Nakajima{ 14586797937017f52bff088d02edf64fb931177a7eaJun Nakajima int irq2, irq; 14686797937017f52bff088d02edf64fb931177a7eaJun Nakajima 14786797937017f52bff088d02edf64fb931177a7eaJun Nakajima /* first look at slave pic */ 14886797937017f52bff088d02edf64fb931177a7eaJun Nakajima irq2 = pic_get_irq(&s->pics[1]); 14986797937017f52bff088d02edf64fb931177a7eaJun Nakajima if (irq2 >= 0) { 15086797937017f52bff088d02edf64fb931177a7eaJun Nakajima /* if irq request by slave pic, signal master PIC */ 15186797937017f52bff088d02edf64fb931177a7eaJun Nakajima pic_set_irq1(&s->pics[0], 2, 1); 15286797937017f52bff088d02edf64fb931177a7eaJun Nakajima pic_set_irq1(&s->pics[0], 2, 0); 15386797937017f52bff088d02edf64fb931177a7eaJun Nakajima } 15486797937017f52bff088d02edf64fb931177a7eaJun Nakajima /* look at requested irq */ 15586797937017f52bff088d02edf64fb931177a7eaJun Nakajima irq = pic_get_irq(&s->pics[0]); 15686797937017f52bff088d02edf64fb931177a7eaJun Nakajima if (irq >= 0) { 15786797937017f52bff088d02edf64fb931177a7eaJun Nakajima#if defined(DEBUG_PIC) 15886797937017f52bff088d02edf64fb931177a7eaJun Nakajima { 15986797937017f52bff088d02edf64fb931177a7eaJun Nakajima int i; 16086797937017f52bff088d02edf64fb931177a7eaJun Nakajima for(i = 0; i < 2; i++) { 16186797937017f52bff088d02edf64fb931177a7eaJun Nakajima printf("pic%d: imr=%x irr=%x padd=%d\n", 16286797937017f52bff088d02edf64fb931177a7eaJun Nakajima i, s->pics[i].imr, s->pics[i].irr, 16386797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->pics[i].priority_add); 16486797937017f52bff088d02edf64fb931177a7eaJun Nakajima 16586797937017f52bff088d02edf64fb931177a7eaJun Nakajima } 16686797937017f52bff088d02edf64fb931177a7eaJun Nakajima } 16786797937017f52bff088d02edf64fb931177a7eaJun Nakajima printf("pic: cpu_interrupt\n"); 16886797937017f52bff088d02edf64fb931177a7eaJun Nakajima#endif 16986797937017f52bff088d02edf64fb931177a7eaJun Nakajima qemu_irq_raise(s->parent_irq); 17086797937017f52bff088d02edf64fb931177a7eaJun Nakajima } 17186797937017f52bff088d02edf64fb931177a7eaJun Nakajima 17286797937017f52bff088d02edf64fb931177a7eaJun Nakajima/* all targets should do this rather than acking the IRQ in the cpu */ 17386797937017f52bff088d02edf64fb931177a7eaJun Nakajima#if defined(TARGET_MIPS) || defined(TARGET_PPC) || defined(TARGET_ALPHA) 17486797937017f52bff088d02edf64fb931177a7eaJun Nakajima else { 17586797937017f52bff088d02edf64fb931177a7eaJun Nakajima qemu_irq_lower(s->parent_irq); 17686797937017f52bff088d02edf64fb931177a7eaJun Nakajima } 17786797937017f52bff088d02edf64fb931177a7eaJun Nakajima#endif 17886797937017f52bff088d02edf64fb931177a7eaJun Nakajima} 17986797937017f52bff088d02edf64fb931177a7eaJun Nakajima 18086797937017f52bff088d02edf64fb931177a7eaJun Nakajima#ifdef DEBUG_IRQ_LATENCY 18186797937017f52bff088d02edf64fb931177a7eaJun Nakajimaint64_t irq_time[16]; 18286797937017f52bff088d02edf64fb931177a7eaJun Nakajima#endif 18386797937017f52bff088d02edf64fb931177a7eaJun Nakajima 18486797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void i8259_set_irq(void *opaque, int irq, int level) 18586797937017f52bff088d02edf64fb931177a7eaJun Nakajima{ 18686797937017f52bff088d02edf64fb931177a7eaJun Nakajima PicState2 *s = opaque; 18786797937017f52bff088d02edf64fb931177a7eaJun Nakajima 18886797937017f52bff088d02edf64fb931177a7eaJun Nakajima#if defined(DEBUG_PIC) || defined(DEBUG_IRQ_COUNT) 18986797937017f52bff088d02edf64fb931177a7eaJun Nakajima if (level != irq_level[irq]) { 19086797937017f52bff088d02edf64fb931177a7eaJun Nakajima#if defined(DEBUG_PIC) 19186797937017f52bff088d02edf64fb931177a7eaJun Nakajima printf("i8259_set_irq: irq=%d level=%d\n", irq, level); 19286797937017f52bff088d02edf64fb931177a7eaJun Nakajima#endif 19386797937017f52bff088d02edf64fb931177a7eaJun Nakajima irq_level[irq] = level; 19486797937017f52bff088d02edf64fb931177a7eaJun Nakajima#ifdef DEBUG_IRQ_COUNT 19586797937017f52bff088d02edf64fb931177a7eaJun Nakajima if (level == 1) 19686797937017f52bff088d02edf64fb931177a7eaJun Nakajima irq_count[irq]++; 19786797937017f52bff088d02edf64fb931177a7eaJun Nakajima#endif 19886797937017f52bff088d02edf64fb931177a7eaJun Nakajima } 19986797937017f52bff088d02edf64fb931177a7eaJun Nakajima#endif 20086797937017f52bff088d02edf64fb931177a7eaJun Nakajima#ifdef DEBUG_IRQ_LATENCY 20186797937017f52bff088d02edf64fb931177a7eaJun Nakajima if (level) { 20286797937017f52bff088d02edf64fb931177a7eaJun Nakajima irq_time[irq] = qemu_get_clock(vm_clock); 20386797937017f52bff088d02edf64fb931177a7eaJun Nakajima } 20486797937017f52bff088d02edf64fb931177a7eaJun Nakajima#endif 20586797937017f52bff088d02edf64fb931177a7eaJun Nakajima pic_set_irq1(&s->pics[irq >> 3], irq & 7, level); 20686797937017f52bff088d02edf64fb931177a7eaJun Nakajima /* used for IOAPIC irqs */ 20786797937017f52bff088d02edf64fb931177a7eaJun Nakajima if (s->alt_irq_func) 20886797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->alt_irq_func(s->alt_irq_opaque, irq, level); 20986797937017f52bff088d02edf64fb931177a7eaJun Nakajima pic_update_irq(s); 21086797937017f52bff088d02edf64fb931177a7eaJun Nakajima} 21186797937017f52bff088d02edf64fb931177a7eaJun Nakajima 21286797937017f52bff088d02edf64fb931177a7eaJun Nakajima/* acknowledge interrupt 'irq' */ 21386797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic inline void pic_intack(PicState *s, int irq) 21486797937017f52bff088d02edf64fb931177a7eaJun Nakajima{ 21586797937017f52bff088d02edf64fb931177a7eaJun Nakajima if (s->auto_eoi) { 21686797937017f52bff088d02edf64fb931177a7eaJun Nakajima if (s->rotate_on_auto_eoi) 21786797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->priority_add = (irq + 1) & 7; 21886797937017f52bff088d02edf64fb931177a7eaJun Nakajima } else { 21986797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->isr |= (1 << irq); 22086797937017f52bff088d02edf64fb931177a7eaJun Nakajima } 22186797937017f52bff088d02edf64fb931177a7eaJun Nakajima /* We don't clear a level sensitive interrupt here */ 22286797937017f52bff088d02edf64fb931177a7eaJun Nakajima if (!(s->elcr & (1 << irq))) 22386797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->irr &= ~(1 << irq); 22486797937017f52bff088d02edf64fb931177a7eaJun Nakajima} 22586797937017f52bff088d02edf64fb931177a7eaJun Nakajima 22686797937017f52bff088d02edf64fb931177a7eaJun Nakajimaint pic_read_irq(PicState2 *s) 22786797937017f52bff088d02edf64fb931177a7eaJun Nakajima{ 22886797937017f52bff088d02edf64fb931177a7eaJun Nakajima int irq, irq2, intno; 22986797937017f52bff088d02edf64fb931177a7eaJun Nakajima 23086797937017f52bff088d02edf64fb931177a7eaJun Nakajima irq = pic_get_irq(&s->pics[0]); 23186797937017f52bff088d02edf64fb931177a7eaJun Nakajima if (irq >= 0) { 23286797937017f52bff088d02edf64fb931177a7eaJun Nakajima pic_intack(&s->pics[0], irq); 23386797937017f52bff088d02edf64fb931177a7eaJun Nakajima if (irq == 2) { 23486797937017f52bff088d02edf64fb931177a7eaJun Nakajima irq2 = pic_get_irq(&s->pics[1]); 23586797937017f52bff088d02edf64fb931177a7eaJun Nakajima if (irq2 >= 0) { 23686797937017f52bff088d02edf64fb931177a7eaJun Nakajima pic_intack(&s->pics[1], irq2); 23786797937017f52bff088d02edf64fb931177a7eaJun Nakajima } else { 23886797937017f52bff088d02edf64fb931177a7eaJun Nakajima /* spurious IRQ on slave controller */ 23986797937017f52bff088d02edf64fb931177a7eaJun Nakajima irq2 = 7; 24086797937017f52bff088d02edf64fb931177a7eaJun Nakajima } 24186797937017f52bff088d02edf64fb931177a7eaJun Nakajima intno = s->pics[1].irq_base + irq2; 24286797937017f52bff088d02edf64fb931177a7eaJun Nakajima irq = irq2 + 8; 24386797937017f52bff088d02edf64fb931177a7eaJun Nakajima } else { 24486797937017f52bff088d02edf64fb931177a7eaJun Nakajima intno = s->pics[0].irq_base + irq; 24586797937017f52bff088d02edf64fb931177a7eaJun Nakajima } 24686797937017f52bff088d02edf64fb931177a7eaJun Nakajima } else { 24786797937017f52bff088d02edf64fb931177a7eaJun Nakajima /* spurious IRQ on host controller */ 24886797937017f52bff088d02edf64fb931177a7eaJun Nakajima irq = 7; 24986797937017f52bff088d02edf64fb931177a7eaJun Nakajima intno = s->pics[0].irq_base + irq; 25086797937017f52bff088d02edf64fb931177a7eaJun Nakajima } 25186797937017f52bff088d02edf64fb931177a7eaJun Nakajima pic_update_irq(s); 25286797937017f52bff088d02edf64fb931177a7eaJun Nakajima 25386797937017f52bff088d02edf64fb931177a7eaJun Nakajima#ifdef DEBUG_IRQ_LATENCY 25486797937017f52bff088d02edf64fb931177a7eaJun Nakajima printf("IRQ%d latency=%0.3fus\n", 25586797937017f52bff088d02edf64fb931177a7eaJun Nakajima irq, 25686797937017f52bff088d02edf64fb931177a7eaJun Nakajima (double)(qemu_get_clock(vm_clock) - irq_time[irq]) * 1000000.0 / get_ticks_per_sec); 25786797937017f52bff088d02edf64fb931177a7eaJun Nakajima#endif 25886797937017f52bff088d02edf64fb931177a7eaJun Nakajima#if defined(DEBUG_PIC) 25986797937017f52bff088d02edf64fb931177a7eaJun Nakajima printf("pic_interrupt: irq=%d\n", irq); 26086797937017f52bff088d02edf64fb931177a7eaJun Nakajima#endif 26186797937017f52bff088d02edf64fb931177a7eaJun Nakajima return intno; 26286797937017f52bff088d02edf64fb931177a7eaJun Nakajima} 26386797937017f52bff088d02edf64fb931177a7eaJun Nakajima 26486797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void pic_reset(void *opaque) 26586797937017f52bff088d02edf64fb931177a7eaJun Nakajima{ 26686797937017f52bff088d02edf64fb931177a7eaJun Nakajima PicState *s = opaque; 26786797937017f52bff088d02edf64fb931177a7eaJun Nakajima 26886797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->last_irr = 0; 26986797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->irr = 0; 27086797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->imr = 0; 27186797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->isr = 0; 27286797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->priority_add = 0; 27386797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->irq_base = 0; 27486797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->read_reg_select = 0; 27586797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->poll = 0; 27686797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->special_mask = 0; 27786797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->init_state = 0; 27886797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->auto_eoi = 0; 27986797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->rotate_on_auto_eoi = 0; 28086797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->special_fully_nested_mode = 0; 28186797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->init4 = 0; 28286797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->single_mode = 0; 28386797937017f52bff088d02edf64fb931177a7eaJun Nakajima /* Note: ELCR is not reset */ 28486797937017f52bff088d02edf64fb931177a7eaJun Nakajima} 28586797937017f52bff088d02edf64fb931177a7eaJun Nakajima 28686797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void pic_ioport_write(void *opaque, uint32_t addr, uint32_t val) 28786797937017f52bff088d02edf64fb931177a7eaJun Nakajima{ 28886797937017f52bff088d02edf64fb931177a7eaJun Nakajima PicState *s = opaque; 28986797937017f52bff088d02edf64fb931177a7eaJun Nakajima int priority, cmd, irq; 29086797937017f52bff088d02edf64fb931177a7eaJun Nakajima 29186797937017f52bff088d02edf64fb931177a7eaJun Nakajima#ifdef DEBUG_PIC 29286797937017f52bff088d02edf64fb931177a7eaJun Nakajima printf("pic_write: addr=0x%02x val=0x%02x\n", addr, val); 29386797937017f52bff088d02edf64fb931177a7eaJun Nakajima#endif 29486797937017f52bff088d02edf64fb931177a7eaJun Nakajima addr &= 1; 29586797937017f52bff088d02edf64fb931177a7eaJun Nakajima if (addr == 0) { 29686797937017f52bff088d02edf64fb931177a7eaJun Nakajima if (val & 0x10) { 29786797937017f52bff088d02edf64fb931177a7eaJun Nakajima /* init */ 29886797937017f52bff088d02edf64fb931177a7eaJun Nakajima pic_reset(s); 29986797937017f52bff088d02edf64fb931177a7eaJun Nakajima /* deassert a pending interrupt */ 30086797937017f52bff088d02edf64fb931177a7eaJun Nakajima qemu_irq_lower(s->pics_state->parent_irq); 30186797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->init_state = 1; 30286797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->init4 = val & 1; 30386797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->single_mode = val & 2; 30486797937017f52bff088d02edf64fb931177a7eaJun Nakajima if (val & 0x08) 30586797937017f52bff088d02edf64fb931177a7eaJun Nakajima hw_error("level sensitive irq not supported"); 30686797937017f52bff088d02edf64fb931177a7eaJun Nakajima } else if (val & 0x08) { 30786797937017f52bff088d02edf64fb931177a7eaJun Nakajima if (val & 0x04) 30886797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->poll = 1; 30986797937017f52bff088d02edf64fb931177a7eaJun Nakajima if (val & 0x02) 31086797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->read_reg_select = val & 1; 31186797937017f52bff088d02edf64fb931177a7eaJun Nakajima if (val & 0x40) 31286797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->special_mask = (val >> 5) & 1; 31386797937017f52bff088d02edf64fb931177a7eaJun Nakajima } else { 31486797937017f52bff088d02edf64fb931177a7eaJun Nakajima cmd = val >> 5; 31586797937017f52bff088d02edf64fb931177a7eaJun Nakajima switch(cmd) { 31686797937017f52bff088d02edf64fb931177a7eaJun Nakajima case 0: 31786797937017f52bff088d02edf64fb931177a7eaJun Nakajima case 4: 31886797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->rotate_on_auto_eoi = cmd >> 2; 31986797937017f52bff088d02edf64fb931177a7eaJun Nakajima break; 32086797937017f52bff088d02edf64fb931177a7eaJun Nakajima case 1: /* end of interrupt */ 32186797937017f52bff088d02edf64fb931177a7eaJun Nakajima case 5: 32286797937017f52bff088d02edf64fb931177a7eaJun Nakajima priority = get_priority(s, s->isr); 32386797937017f52bff088d02edf64fb931177a7eaJun Nakajima if (priority != 8) { 32486797937017f52bff088d02edf64fb931177a7eaJun Nakajima irq = (priority + s->priority_add) & 7; 32586797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->isr &= ~(1 << irq); 32686797937017f52bff088d02edf64fb931177a7eaJun Nakajima if (cmd == 5) 32786797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->priority_add = (irq + 1) & 7; 32886797937017f52bff088d02edf64fb931177a7eaJun Nakajima pic_update_irq(s->pics_state); 32986797937017f52bff088d02edf64fb931177a7eaJun Nakajima } 33086797937017f52bff088d02edf64fb931177a7eaJun Nakajima break; 33186797937017f52bff088d02edf64fb931177a7eaJun Nakajima case 3: 33286797937017f52bff088d02edf64fb931177a7eaJun Nakajima irq = val & 7; 33386797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->isr &= ~(1 << irq); 33486797937017f52bff088d02edf64fb931177a7eaJun Nakajima pic_update_irq(s->pics_state); 33586797937017f52bff088d02edf64fb931177a7eaJun Nakajima break; 33686797937017f52bff088d02edf64fb931177a7eaJun Nakajima case 6: 33786797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->priority_add = (val + 1) & 7; 33886797937017f52bff088d02edf64fb931177a7eaJun Nakajima pic_update_irq(s->pics_state); 33986797937017f52bff088d02edf64fb931177a7eaJun Nakajima break; 34086797937017f52bff088d02edf64fb931177a7eaJun Nakajima case 7: 34186797937017f52bff088d02edf64fb931177a7eaJun Nakajima irq = val & 7; 34286797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->isr &= ~(1 << irq); 34386797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->priority_add = (irq + 1) & 7; 34486797937017f52bff088d02edf64fb931177a7eaJun Nakajima pic_update_irq(s->pics_state); 34586797937017f52bff088d02edf64fb931177a7eaJun Nakajima break; 34686797937017f52bff088d02edf64fb931177a7eaJun Nakajima default: 34786797937017f52bff088d02edf64fb931177a7eaJun Nakajima /* no operation */ 34886797937017f52bff088d02edf64fb931177a7eaJun Nakajima break; 34986797937017f52bff088d02edf64fb931177a7eaJun Nakajima } 35086797937017f52bff088d02edf64fb931177a7eaJun Nakajima } 35186797937017f52bff088d02edf64fb931177a7eaJun Nakajima } else { 35286797937017f52bff088d02edf64fb931177a7eaJun Nakajima switch(s->init_state) { 35386797937017f52bff088d02edf64fb931177a7eaJun Nakajima case 0: 35486797937017f52bff088d02edf64fb931177a7eaJun Nakajima /* normal mode */ 35586797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->imr = val; 35686797937017f52bff088d02edf64fb931177a7eaJun Nakajima pic_update_irq(s->pics_state); 35786797937017f52bff088d02edf64fb931177a7eaJun Nakajima break; 35886797937017f52bff088d02edf64fb931177a7eaJun Nakajima case 1: 35986797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->irq_base = val & 0xf8; 36086797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->init_state = s->single_mode ? (s->init4 ? 3 : 0) : 2; 36186797937017f52bff088d02edf64fb931177a7eaJun Nakajima break; 36286797937017f52bff088d02edf64fb931177a7eaJun Nakajima case 2: 36386797937017f52bff088d02edf64fb931177a7eaJun Nakajima if (s->init4) { 36486797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->init_state = 3; 36586797937017f52bff088d02edf64fb931177a7eaJun Nakajima } else { 36686797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->init_state = 0; 36786797937017f52bff088d02edf64fb931177a7eaJun Nakajima } 36886797937017f52bff088d02edf64fb931177a7eaJun Nakajima break; 36986797937017f52bff088d02edf64fb931177a7eaJun Nakajima case 3: 37086797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->special_fully_nested_mode = (val >> 4) & 1; 37186797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->auto_eoi = (val >> 1) & 1; 37286797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->init_state = 0; 37386797937017f52bff088d02edf64fb931177a7eaJun Nakajima break; 37486797937017f52bff088d02edf64fb931177a7eaJun Nakajima } 37586797937017f52bff088d02edf64fb931177a7eaJun Nakajima } 37686797937017f52bff088d02edf64fb931177a7eaJun Nakajima} 37786797937017f52bff088d02edf64fb931177a7eaJun Nakajima 37886797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic uint32_t pic_poll_read (PicState *s, uint32_t addr1) 37986797937017f52bff088d02edf64fb931177a7eaJun Nakajima{ 38086797937017f52bff088d02edf64fb931177a7eaJun Nakajima int ret; 38186797937017f52bff088d02edf64fb931177a7eaJun Nakajima 38286797937017f52bff088d02edf64fb931177a7eaJun Nakajima ret = pic_get_irq(s); 38386797937017f52bff088d02edf64fb931177a7eaJun Nakajima if (ret >= 0) { 38486797937017f52bff088d02edf64fb931177a7eaJun Nakajima if (addr1 >> 7) { 38586797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->pics_state->pics[0].isr &= ~(1 << 2); 38686797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->pics_state->pics[0].irr &= ~(1 << 2); 38786797937017f52bff088d02edf64fb931177a7eaJun Nakajima } 38886797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->irr &= ~(1 << ret); 38986797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->isr &= ~(1 << ret); 39086797937017f52bff088d02edf64fb931177a7eaJun Nakajima if (addr1 >> 7 || ret != 2) 39186797937017f52bff088d02edf64fb931177a7eaJun Nakajima pic_update_irq(s->pics_state); 39286797937017f52bff088d02edf64fb931177a7eaJun Nakajima } else { 39386797937017f52bff088d02edf64fb931177a7eaJun Nakajima ret = 0x07; 39486797937017f52bff088d02edf64fb931177a7eaJun Nakajima pic_update_irq(s->pics_state); 39586797937017f52bff088d02edf64fb931177a7eaJun Nakajima } 39686797937017f52bff088d02edf64fb931177a7eaJun Nakajima 39786797937017f52bff088d02edf64fb931177a7eaJun Nakajima return ret; 39886797937017f52bff088d02edf64fb931177a7eaJun Nakajima} 39986797937017f52bff088d02edf64fb931177a7eaJun Nakajima 40086797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic uint32_t pic_ioport_read(void *opaque, uint32_t addr1) 40186797937017f52bff088d02edf64fb931177a7eaJun Nakajima{ 40286797937017f52bff088d02edf64fb931177a7eaJun Nakajima PicState *s = opaque; 40386797937017f52bff088d02edf64fb931177a7eaJun Nakajima unsigned int addr; 40486797937017f52bff088d02edf64fb931177a7eaJun Nakajima int ret; 40586797937017f52bff088d02edf64fb931177a7eaJun Nakajima 40686797937017f52bff088d02edf64fb931177a7eaJun Nakajima addr = addr1; 40786797937017f52bff088d02edf64fb931177a7eaJun Nakajima addr &= 1; 40886797937017f52bff088d02edf64fb931177a7eaJun Nakajima if (s->poll) { 40986797937017f52bff088d02edf64fb931177a7eaJun Nakajima ret = pic_poll_read(s, addr1); 41086797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->poll = 0; 41186797937017f52bff088d02edf64fb931177a7eaJun Nakajima } else { 41286797937017f52bff088d02edf64fb931177a7eaJun Nakajima if (addr == 0) { 41386797937017f52bff088d02edf64fb931177a7eaJun Nakajima if (s->read_reg_select) 41486797937017f52bff088d02edf64fb931177a7eaJun Nakajima ret = s->isr; 41586797937017f52bff088d02edf64fb931177a7eaJun Nakajima else 41686797937017f52bff088d02edf64fb931177a7eaJun Nakajima ret = s->irr; 41786797937017f52bff088d02edf64fb931177a7eaJun Nakajima } else { 41886797937017f52bff088d02edf64fb931177a7eaJun Nakajima ret = s->imr; 41986797937017f52bff088d02edf64fb931177a7eaJun Nakajima } 42086797937017f52bff088d02edf64fb931177a7eaJun Nakajima } 42186797937017f52bff088d02edf64fb931177a7eaJun Nakajima#ifdef DEBUG_PIC 42286797937017f52bff088d02edf64fb931177a7eaJun Nakajima printf("pic_read: addr=0x%02x val=0x%02x\n", addr1, ret); 42386797937017f52bff088d02edf64fb931177a7eaJun Nakajima#endif 42486797937017f52bff088d02edf64fb931177a7eaJun Nakajima return ret; 42586797937017f52bff088d02edf64fb931177a7eaJun Nakajima} 42686797937017f52bff088d02edf64fb931177a7eaJun Nakajima 42786797937017f52bff088d02edf64fb931177a7eaJun Nakajima/* memory mapped interrupt status */ 42886797937017f52bff088d02edf64fb931177a7eaJun Nakajima/* XXX: may be the same than pic_read_irq() */ 42986797937017f52bff088d02edf64fb931177a7eaJun Nakajimauint32_t pic_intack_read(PicState2 *s) 43086797937017f52bff088d02edf64fb931177a7eaJun Nakajima{ 43186797937017f52bff088d02edf64fb931177a7eaJun Nakajima int ret; 43286797937017f52bff088d02edf64fb931177a7eaJun Nakajima 43386797937017f52bff088d02edf64fb931177a7eaJun Nakajima ret = pic_poll_read(&s->pics[0], 0x00); 43486797937017f52bff088d02edf64fb931177a7eaJun Nakajima if (ret == 2) 43586797937017f52bff088d02edf64fb931177a7eaJun Nakajima ret = pic_poll_read(&s->pics[1], 0x80) + 8; 43686797937017f52bff088d02edf64fb931177a7eaJun Nakajima /* Prepare for ISR read */ 43786797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->pics[0].read_reg_select = 1; 43886797937017f52bff088d02edf64fb931177a7eaJun Nakajima 43986797937017f52bff088d02edf64fb931177a7eaJun Nakajima return ret; 44086797937017f52bff088d02edf64fb931177a7eaJun Nakajima} 44186797937017f52bff088d02edf64fb931177a7eaJun Nakajima 44286797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void elcr_ioport_write(void *opaque, uint32_t addr, uint32_t val) 44386797937017f52bff088d02edf64fb931177a7eaJun Nakajima{ 44486797937017f52bff088d02edf64fb931177a7eaJun Nakajima PicState *s = opaque; 44586797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->elcr = val & s->elcr_mask; 44686797937017f52bff088d02edf64fb931177a7eaJun Nakajima} 44786797937017f52bff088d02edf64fb931177a7eaJun Nakajima 44886797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic uint32_t elcr_ioport_read(void *opaque, uint32_t addr1) 44986797937017f52bff088d02edf64fb931177a7eaJun Nakajima{ 45086797937017f52bff088d02edf64fb931177a7eaJun Nakajima PicState *s = opaque; 45186797937017f52bff088d02edf64fb931177a7eaJun Nakajima return s->elcr; 45286797937017f52bff088d02edf64fb931177a7eaJun Nakajima} 45386797937017f52bff088d02edf64fb931177a7eaJun Nakajima 45486797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void pic_save(QEMUFile *f, void *opaque) 45586797937017f52bff088d02edf64fb931177a7eaJun Nakajima{ 45686797937017f52bff088d02edf64fb931177a7eaJun Nakajima PicState *s = opaque; 45786797937017f52bff088d02edf64fb931177a7eaJun Nakajima 45886797937017f52bff088d02edf64fb931177a7eaJun Nakajima qemu_put_8s(f, &s->last_irr); 45986797937017f52bff088d02edf64fb931177a7eaJun Nakajima qemu_put_8s(f, &s->irr); 46086797937017f52bff088d02edf64fb931177a7eaJun Nakajima qemu_put_8s(f, &s->imr); 46186797937017f52bff088d02edf64fb931177a7eaJun Nakajima qemu_put_8s(f, &s->isr); 46286797937017f52bff088d02edf64fb931177a7eaJun Nakajima qemu_put_8s(f, &s->priority_add); 46386797937017f52bff088d02edf64fb931177a7eaJun Nakajima qemu_put_8s(f, &s->irq_base); 46486797937017f52bff088d02edf64fb931177a7eaJun Nakajima qemu_put_8s(f, &s->read_reg_select); 46586797937017f52bff088d02edf64fb931177a7eaJun Nakajima qemu_put_8s(f, &s->poll); 46686797937017f52bff088d02edf64fb931177a7eaJun Nakajima qemu_put_8s(f, &s->special_mask); 46786797937017f52bff088d02edf64fb931177a7eaJun Nakajima qemu_put_8s(f, &s->init_state); 46886797937017f52bff088d02edf64fb931177a7eaJun Nakajima qemu_put_8s(f, &s->auto_eoi); 46986797937017f52bff088d02edf64fb931177a7eaJun Nakajima qemu_put_8s(f, &s->rotate_on_auto_eoi); 47086797937017f52bff088d02edf64fb931177a7eaJun Nakajima qemu_put_8s(f, &s->special_fully_nested_mode); 47186797937017f52bff088d02edf64fb931177a7eaJun Nakajima qemu_put_8s(f, &s->init4); 47286797937017f52bff088d02edf64fb931177a7eaJun Nakajima qemu_put_8s(f, &s->single_mode); 47386797937017f52bff088d02edf64fb931177a7eaJun Nakajima qemu_put_8s(f, &s->elcr); 47486797937017f52bff088d02edf64fb931177a7eaJun Nakajima} 47586797937017f52bff088d02edf64fb931177a7eaJun Nakajima 47686797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic int pic_load(QEMUFile *f, void *opaque, int version_id) 47786797937017f52bff088d02edf64fb931177a7eaJun Nakajima{ 47886797937017f52bff088d02edf64fb931177a7eaJun Nakajima PicState *s = opaque; 47986797937017f52bff088d02edf64fb931177a7eaJun Nakajima 48086797937017f52bff088d02edf64fb931177a7eaJun Nakajima if (version_id != 1) 48186797937017f52bff088d02edf64fb931177a7eaJun Nakajima return -EINVAL; 48286797937017f52bff088d02edf64fb931177a7eaJun Nakajima 48386797937017f52bff088d02edf64fb931177a7eaJun Nakajima qemu_get_8s(f, &s->last_irr); 48486797937017f52bff088d02edf64fb931177a7eaJun Nakajima qemu_get_8s(f, &s->irr); 48586797937017f52bff088d02edf64fb931177a7eaJun Nakajima qemu_get_8s(f, &s->imr); 48686797937017f52bff088d02edf64fb931177a7eaJun Nakajima qemu_get_8s(f, &s->isr); 48786797937017f52bff088d02edf64fb931177a7eaJun Nakajima qemu_get_8s(f, &s->priority_add); 48886797937017f52bff088d02edf64fb931177a7eaJun Nakajima qemu_get_8s(f, &s->irq_base); 48986797937017f52bff088d02edf64fb931177a7eaJun Nakajima qemu_get_8s(f, &s->read_reg_select); 49086797937017f52bff088d02edf64fb931177a7eaJun Nakajima qemu_get_8s(f, &s->poll); 49186797937017f52bff088d02edf64fb931177a7eaJun Nakajima qemu_get_8s(f, &s->special_mask); 49286797937017f52bff088d02edf64fb931177a7eaJun Nakajima qemu_get_8s(f, &s->init_state); 49386797937017f52bff088d02edf64fb931177a7eaJun Nakajima qemu_get_8s(f, &s->auto_eoi); 49486797937017f52bff088d02edf64fb931177a7eaJun Nakajima qemu_get_8s(f, &s->rotate_on_auto_eoi); 49586797937017f52bff088d02edf64fb931177a7eaJun Nakajima qemu_get_8s(f, &s->special_fully_nested_mode); 49686797937017f52bff088d02edf64fb931177a7eaJun Nakajima qemu_get_8s(f, &s->init4); 49786797937017f52bff088d02edf64fb931177a7eaJun Nakajima qemu_get_8s(f, &s->single_mode); 49886797937017f52bff088d02edf64fb931177a7eaJun Nakajima qemu_get_8s(f, &s->elcr); 49986797937017f52bff088d02edf64fb931177a7eaJun Nakajima return 0; 50086797937017f52bff088d02edf64fb931177a7eaJun Nakajima} 50186797937017f52bff088d02edf64fb931177a7eaJun Nakajima 50286797937017f52bff088d02edf64fb931177a7eaJun Nakajima/* XXX: add generic master/slave system */ 50386797937017f52bff088d02edf64fb931177a7eaJun Nakajimastatic void pic_init1(int io_addr, int elcr_addr, PicState *s) 50486797937017f52bff088d02edf64fb931177a7eaJun Nakajima{ 50586797937017f52bff088d02edf64fb931177a7eaJun Nakajima register_ioport_write(io_addr, 2, 1, pic_ioport_write, s); 50686797937017f52bff088d02edf64fb931177a7eaJun Nakajima register_ioport_read(io_addr, 2, 1, pic_ioport_read, s); 50786797937017f52bff088d02edf64fb931177a7eaJun Nakajima if (elcr_addr >= 0) { 50886797937017f52bff088d02edf64fb931177a7eaJun Nakajima register_ioport_write(elcr_addr, 1, 1, elcr_ioport_write, s); 50986797937017f52bff088d02edf64fb931177a7eaJun Nakajima register_ioport_read(elcr_addr, 1, 1, elcr_ioport_read, s); 51086797937017f52bff088d02edf64fb931177a7eaJun Nakajima } 51186797937017f52bff088d02edf64fb931177a7eaJun Nakajima register_savevm("i8259", io_addr, 1, pic_save, pic_load, s); 51286797937017f52bff088d02edf64fb931177a7eaJun Nakajima qemu_register_reset(pic_reset, 0, s); 51386797937017f52bff088d02edf64fb931177a7eaJun Nakajima} 51486797937017f52bff088d02edf64fb931177a7eaJun Nakajima 51586797937017f52bff088d02edf64fb931177a7eaJun Nakajimavoid pic_info(Monitor *mon) 51686797937017f52bff088d02edf64fb931177a7eaJun Nakajima{ 51786797937017f52bff088d02edf64fb931177a7eaJun Nakajima int i; 51886797937017f52bff088d02edf64fb931177a7eaJun Nakajima PicState *s; 51986797937017f52bff088d02edf64fb931177a7eaJun Nakajima 52086797937017f52bff088d02edf64fb931177a7eaJun Nakajima if (!isa_pic) 52186797937017f52bff088d02edf64fb931177a7eaJun Nakajima return; 52286797937017f52bff088d02edf64fb931177a7eaJun Nakajima 52386797937017f52bff088d02edf64fb931177a7eaJun Nakajima for(i=0;i<2;i++) { 52486797937017f52bff088d02edf64fb931177a7eaJun Nakajima s = &isa_pic->pics[i]; 52586797937017f52bff088d02edf64fb931177a7eaJun Nakajima monitor_printf(mon, "pic%d: irr=%02x imr=%02x isr=%02x hprio=%d " 52686797937017f52bff088d02edf64fb931177a7eaJun Nakajima "irq_base=%02x rr_sel=%d elcr=%02x fnm=%d\n", 52786797937017f52bff088d02edf64fb931177a7eaJun Nakajima i, s->irr, s->imr, s->isr, s->priority_add, 52886797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->irq_base, s->read_reg_select, s->elcr, 52986797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->special_fully_nested_mode); 53086797937017f52bff088d02edf64fb931177a7eaJun Nakajima } 53186797937017f52bff088d02edf64fb931177a7eaJun Nakajima} 53286797937017f52bff088d02edf64fb931177a7eaJun Nakajima 53386797937017f52bff088d02edf64fb931177a7eaJun Nakajimavoid irq_info(Monitor *mon) 53486797937017f52bff088d02edf64fb931177a7eaJun Nakajima{ 53586797937017f52bff088d02edf64fb931177a7eaJun Nakajima#ifndef DEBUG_IRQ_COUNT 53686797937017f52bff088d02edf64fb931177a7eaJun Nakajima monitor_printf(mon, "irq statistic code not compiled.\n"); 53786797937017f52bff088d02edf64fb931177a7eaJun Nakajima#else 53886797937017f52bff088d02edf64fb931177a7eaJun Nakajima int i; 53986797937017f52bff088d02edf64fb931177a7eaJun Nakajima int64_t count; 54086797937017f52bff088d02edf64fb931177a7eaJun Nakajima 54186797937017f52bff088d02edf64fb931177a7eaJun Nakajima monitor_printf(mon, "IRQ statistics:\n"); 54286797937017f52bff088d02edf64fb931177a7eaJun Nakajima for (i = 0; i < 16; i++) { 54386797937017f52bff088d02edf64fb931177a7eaJun Nakajima count = irq_count[i]; 54486797937017f52bff088d02edf64fb931177a7eaJun Nakajima if (count > 0) 54586797937017f52bff088d02edf64fb931177a7eaJun Nakajima monitor_printf(mon, "%2d: %" PRId64 "\n", i, count); 54686797937017f52bff088d02edf64fb931177a7eaJun Nakajima } 54786797937017f52bff088d02edf64fb931177a7eaJun Nakajima#endif 54886797937017f52bff088d02edf64fb931177a7eaJun Nakajima} 54986797937017f52bff088d02edf64fb931177a7eaJun Nakajima 55086797937017f52bff088d02edf64fb931177a7eaJun Nakajimaqemu_irq *i8259_init(qemu_irq parent_irq) 55186797937017f52bff088d02edf64fb931177a7eaJun Nakajima{ 55286797937017f52bff088d02edf64fb931177a7eaJun Nakajima PicState2 *s; 55386797937017f52bff088d02edf64fb931177a7eaJun Nakajima 55486797937017f52bff088d02edf64fb931177a7eaJun Nakajima s = qemu_mallocz(sizeof(PicState2)); 55586797937017f52bff088d02edf64fb931177a7eaJun Nakajima pic_init1(0x20, 0x4d0, &s->pics[0]); 55686797937017f52bff088d02edf64fb931177a7eaJun Nakajima pic_init1(0xa0, 0x4d1, &s->pics[1]); 55786797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->pics[0].elcr_mask = 0xf8; 55886797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->pics[1].elcr_mask = 0xde; 55986797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->parent_irq = parent_irq; 56086797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->pics[0].pics_state = s; 56186797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->pics[1].pics_state = s; 56286797937017f52bff088d02edf64fb931177a7eaJun Nakajima isa_pic = s; 563d0b482eb3e8cb699a2090bc773364d3a7d369a25Vladimir Chtchetkine return qemu_allocate_irqs(i8259_set_irq, s, GFD_MAX_IRQ); 56486797937017f52bff088d02edf64fb931177a7eaJun Nakajima} 56586797937017f52bff088d02edf64fb931177a7eaJun Nakajima 56686797937017f52bff088d02edf64fb931177a7eaJun Nakajimavoid pic_set_alt_irq_func(PicState2 *s, SetIRQFunc *alt_irq_func, 56786797937017f52bff088d02edf64fb931177a7eaJun Nakajima void *alt_irq_opaque) 56886797937017f52bff088d02edf64fb931177a7eaJun Nakajima{ 56986797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->alt_irq_func = alt_irq_func; 57086797937017f52bff088d02edf64fb931177a7eaJun Nakajima s->alt_irq_opaque = alt_irq_opaque; 57186797937017f52bff088d02edf64fb931177a7eaJun Nakajima} 572