Statistics
| Branch: | Revision:

root / hw / i8259.c @ 95499a1d

History | View | Annotate | Download (14.7 kB)

1 80cabfad bellard
/*
2 80cabfad bellard
 * QEMU 8259 interrupt controller emulation
3 5fafdf24 ths
 *
4 80cabfad bellard
 * Copyright (c) 2003-2004 Fabrice Bellard
5 5fafdf24 ths
 *
6 80cabfad bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 80cabfad bellard
 * of this software and associated documentation files (the "Software"), to deal
8 80cabfad bellard
 * in the Software without restriction, including without limitation the rights
9 80cabfad bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 80cabfad bellard
 * copies of the Software, and to permit persons to whom the Software is
11 80cabfad bellard
 * furnished to do so, subject to the following conditions:
12 80cabfad bellard
 *
13 80cabfad bellard
 * The above copyright notice and this permission notice shall be included in
14 80cabfad bellard
 * all copies or substantial portions of the Software.
15 80cabfad bellard
 *
16 80cabfad bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 80cabfad bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 80cabfad bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 80cabfad bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 80cabfad bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 80cabfad bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 80cabfad bellard
 * THE SOFTWARE.
23 80cabfad bellard
 */
24 87ecb68b pbrook
#include "hw.h"
25 87ecb68b pbrook
#include "pc.h"
26 87ecb68b pbrook
#include "isa.h"
27 376253ec aliguori
#include "monitor.h"
28 0bf9e31a Blue Swirl
#include "qemu-timer.h"
29 80cabfad bellard
30 80cabfad bellard
/* debug PIC */
31 80cabfad bellard
//#define DEBUG_PIC
32 80cabfad bellard
33 8ac02ff8 Blue Swirl
#ifdef DEBUG_PIC
34 8ac02ff8 Blue Swirl
#define DPRINTF(fmt, ...)                                       \
35 8ac02ff8 Blue Swirl
    do { printf("pic: " fmt , ## __VA_ARGS__); } while (0)
36 8ac02ff8 Blue Swirl
#else
37 8ac02ff8 Blue Swirl
#define DPRINTF(fmt, ...)
38 8ac02ff8 Blue Swirl
#endif
39 8ac02ff8 Blue Swirl
40 b41a2cd1 bellard
//#define DEBUG_IRQ_LATENCY
41 4a0fb71e bellard
//#define DEBUG_IRQ_COUNT
42 b41a2cd1 bellard
43 80cabfad bellard
typedef struct PicState {
44 80cabfad bellard
    uint8_t last_irr; /* edge detection */
45 80cabfad bellard
    uint8_t irr; /* interrupt request register */
46 80cabfad bellard
    uint8_t imr; /* interrupt mask register */
47 80cabfad bellard
    uint8_t isr; /* interrupt service register */
48 80cabfad bellard
    uint8_t priority_add; /* highest irq priority */
49 80cabfad bellard
    uint8_t irq_base;
50 80cabfad bellard
    uint8_t read_reg_select;
51 80cabfad bellard
    uint8_t poll;
52 80cabfad bellard
    uint8_t special_mask;
53 80cabfad bellard
    uint8_t init_state;
54 80cabfad bellard
    uint8_t auto_eoi;
55 80cabfad bellard
    uint8_t rotate_on_auto_eoi;
56 80cabfad bellard
    uint8_t special_fully_nested_mode;
57 80cabfad bellard
    uint8_t init4; /* true if 4 byte init */
58 2053152b ths
    uint8_t single_mode; /* true if slave pic is not initialized */
59 660de336 bellard
    uint8_t elcr; /* PIIX edge/trigger selection*/
60 660de336 bellard
    uint8_t elcr_mask;
61 3de388f6 bellard
    PicState2 *pics_state;
62 80cabfad bellard
} PicState;
63 80cabfad bellard
64 3de388f6 bellard
struct PicState2 {
65 3de388f6 bellard
    /* 0 is master pic, 1 is slave pic */
66 3de388f6 bellard
    /* XXX: better separation between the two pics */
67 3de388f6 bellard
    PicState pics[2];
68 d537cf6c pbrook
    qemu_irq parent_irq;
69 3de388f6 bellard
    void *irq_request_opaque;
70 3de388f6 bellard
};
71 80cabfad bellard
72 4a0fb71e bellard
#if defined(DEBUG_PIC) || defined (DEBUG_IRQ_COUNT)
73 4a0fb71e bellard
static int irq_level[16];
74 4a0fb71e bellard
#endif
75 4a0fb71e bellard
#ifdef DEBUG_IRQ_COUNT
76 4a0fb71e bellard
static uint64_t irq_count[16];
77 4a0fb71e bellard
#endif
78 fbe3288d Paolo Bonzini
PicState2 *isa_pic;
79 4a0fb71e bellard
80 80cabfad bellard
/* set irq level. If an edge is detected, then the IRR is set to 1 */
81 80cabfad bellard
static inline void pic_set_irq1(PicState *s, int irq, int level)
82 80cabfad bellard
{
83 80cabfad bellard
    int mask;
84 80cabfad bellard
    mask = 1 << irq;
85 660de336 bellard
    if (s->elcr & mask) {
86 660de336 bellard
        /* level triggered */
87 660de336 bellard
        if (level) {
88 80cabfad bellard
            s->irr |= mask;
89 660de336 bellard
            s->last_irr |= mask;
90 660de336 bellard
        } else {
91 660de336 bellard
            s->irr &= ~mask;
92 660de336 bellard
            s->last_irr &= ~mask;
93 660de336 bellard
        }
94 80cabfad bellard
    } else {
95 660de336 bellard
        /* edge triggered */
96 660de336 bellard
        if (level) {
97 660de336 bellard
            if ((s->last_irr & mask) == 0)
98 660de336 bellard
                s->irr |= mask;
99 660de336 bellard
            s->last_irr |= mask;
100 660de336 bellard
        } else {
101 660de336 bellard
            s->last_irr &= ~mask;
102 660de336 bellard
        }
103 80cabfad bellard
    }
104 80cabfad bellard
}
105 80cabfad bellard
106 80cabfad bellard
/* return the highest priority found in mask (highest = smallest
107 80cabfad bellard
   number). Return 8 if no irq */
108 80cabfad bellard
static inline int get_priority(PicState *s, int mask)
109 80cabfad bellard
{
110 80cabfad bellard
    int priority;
111 80cabfad bellard
    if (mask == 0)
112 80cabfad bellard
        return 8;
113 80cabfad bellard
    priority = 0;
114 80cabfad bellard
    while ((mask & (1 << ((priority + s->priority_add) & 7))) == 0)
115 80cabfad bellard
        priority++;
116 80cabfad bellard
    return priority;
117 80cabfad bellard
}
118 80cabfad bellard
119 80cabfad bellard
/* return the pic wanted interrupt. return -1 if none */
120 80cabfad bellard
static int pic_get_irq(PicState *s)
121 80cabfad bellard
{
122 80cabfad bellard
    int mask, cur_priority, priority;
123 80cabfad bellard
124 80cabfad bellard
    mask = s->irr & ~s->imr;
125 80cabfad bellard
    priority = get_priority(s, mask);
126 80cabfad bellard
    if (priority == 8)
127 80cabfad bellard
        return -1;
128 80cabfad bellard
    /* compute current priority. If special fully nested mode on the
129 80cabfad bellard
       master, the IRQ coming from the slave is not taken into account
130 80cabfad bellard
       for the priority computation. */
131 80cabfad bellard
    mask = s->isr;
132 84678711 balrog
    if (s->special_mask)
133 84678711 balrog
        mask &= ~s->imr;
134 3de388f6 bellard
    if (s->special_fully_nested_mode && s == &s->pics_state->pics[0])
135 80cabfad bellard
        mask &= ~(1 << 2);
136 80cabfad bellard
    cur_priority = get_priority(s, mask);
137 80cabfad bellard
    if (priority < cur_priority) {
138 80cabfad bellard
        /* higher priority found: an irq should be generated */
139 80cabfad bellard
        return (priority + s->priority_add) & 7;
140 80cabfad bellard
    } else {
141 80cabfad bellard
        return -1;
142 80cabfad bellard
    }
143 80cabfad bellard
}
144 80cabfad bellard
145 80cabfad bellard
/* raise irq to CPU if necessary. must be called every time the active
146 80cabfad bellard
   irq may change */
147 3de388f6 bellard
/* XXX: should not export it, but it is needed for an APIC kludge */
148 3de388f6 bellard
void pic_update_irq(PicState2 *s)
149 80cabfad bellard
{
150 80cabfad bellard
    int irq2, irq;
151 80cabfad bellard
152 80cabfad bellard
    /* first look at slave pic */
153 3de388f6 bellard
    irq2 = pic_get_irq(&s->pics[1]);
154 80cabfad bellard
    if (irq2 >= 0) {
155 80cabfad bellard
        /* if irq request by slave pic, signal master PIC */
156 3de388f6 bellard
        pic_set_irq1(&s->pics[0], 2, 1);
157 3de388f6 bellard
        pic_set_irq1(&s->pics[0], 2, 0);
158 80cabfad bellard
    }
159 80cabfad bellard
    /* look at requested irq */
160 3de388f6 bellard
    irq = pic_get_irq(&s->pics[0]);
161 80cabfad bellard
    if (irq >= 0) {
162 80cabfad bellard
#if defined(DEBUG_PIC)
163 80cabfad bellard
        {
164 80cabfad bellard
            int i;
165 80cabfad bellard
            for(i = 0; i < 2; i++) {
166 5fafdf24 ths
                printf("pic%d: imr=%x irr=%x padd=%d\n",
167 5fafdf24 ths
                       i, s->pics[i].imr, s->pics[i].irr,
168 3de388f6 bellard
                       s->pics[i].priority_add);
169 3b46e624 ths
170 80cabfad bellard
            }
171 80cabfad bellard
        }
172 2444ca41 bellard
        printf("pic: cpu_interrupt\n");
173 80cabfad bellard
#endif
174 d537cf6c pbrook
        qemu_irq_raise(s->parent_irq);
175 80cabfad bellard
    }
176 4de9b249 ths
177 4de9b249 ths
/* all targets should do this rather than acking the IRQ in the cpu */
178 29463b24 aurel32
#if defined(TARGET_MIPS) || defined(TARGET_PPC) || defined(TARGET_ALPHA)
179 4de9b249 ths
    else {
180 d537cf6c pbrook
        qemu_irq_lower(s->parent_irq);
181 4de9b249 ths
    }
182 4de9b249 ths
#endif
183 80cabfad bellard
}
184 80cabfad bellard
185 80cabfad bellard
#ifdef DEBUG_IRQ_LATENCY
186 80cabfad bellard
int64_t irq_time[16];
187 80cabfad bellard
#endif
188 80cabfad bellard
189 9596ebb7 pbrook
static void i8259_set_irq(void *opaque, int irq, int level)
190 80cabfad bellard
{
191 3de388f6 bellard
    PicState2 *s = opaque;
192 3de388f6 bellard
193 4a0fb71e bellard
#if defined(DEBUG_PIC) || defined(DEBUG_IRQ_COUNT)
194 80cabfad bellard
    if (level != irq_level[irq]) {
195 8ac02ff8 Blue Swirl
        DPRINTF("i8259_set_irq: irq=%d level=%d\n", irq, level);
196 80cabfad bellard
        irq_level[irq] = level;
197 4a0fb71e bellard
#ifdef DEBUG_IRQ_COUNT
198 4a0fb71e bellard
        if (level == 1)
199 4a0fb71e bellard
            irq_count[irq]++;
200 4a0fb71e bellard
#endif
201 80cabfad bellard
    }
202 80cabfad bellard
#endif
203 80cabfad bellard
#ifdef DEBUG_IRQ_LATENCY
204 80cabfad bellard
    if (level) {
205 2444ca41 bellard
        irq_time[irq] = qemu_get_clock(vm_clock);
206 80cabfad bellard
    }
207 80cabfad bellard
#endif
208 3de388f6 bellard
    pic_set_irq1(&s->pics[irq >> 3], irq & 7, level);
209 3de388f6 bellard
    pic_update_irq(s);
210 80cabfad bellard
}
211 80cabfad bellard
212 80cabfad bellard
/* acknowledge interrupt 'irq' */
213 80cabfad bellard
static inline void pic_intack(PicState *s, int irq)
214 80cabfad bellard
{
215 80cabfad bellard
    if (s->auto_eoi) {
216 80cabfad bellard
        if (s->rotate_on_auto_eoi)
217 80cabfad bellard
            s->priority_add = (irq + 1) & 7;
218 80cabfad bellard
    } else {
219 80cabfad bellard
        s->isr |= (1 << irq);
220 80cabfad bellard
    }
221 0ecf89aa bellard
    /* We don't clear a level sensitive interrupt here */
222 0ecf89aa bellard
    if (!(s->elcr & (1 << irq)))
223 0ecf89aa bellard
        s->irr &= ~(1 << irq);
224 80cabfad bellard
}
225 80cabfad bellard
226 3de388f6 bellard
int pic_read_irq(PicState2 *s)
227 80cabfad bellard
{
228 80cabfad bellard
    int irq, irq2, intno;
229 80cabfad bellard
230 3de388f6 bellard
    irq = pic_get_irq(&s->pics[0]);
231 15aeac38 bellard
    if (irq >= 0) {
232 3de388f6 bellard
        pic_intack(&s->pics[0], irq);
233 15aeac38 bellard
        if (irq == 2) {
234 3de388f6 bellard
            irq2 = pic_get_irq(&s->pics[1]);
235 15aeac38 bellard
            if (irq2 >= 0) {
236 3de388f6 bellard
                pic_intack(&s->pics[1], irq2);
237 15aeac38 bellard
            } else {
238 15aeac38 bellard
                /* spurious IRQ on slave controller */
239 15aeac38 bellard
                irq2 = 7;
240 15aeac38 bellard
            }
241 3de388f6 bellard
            intno = s->pics[1].irq_base + irq2;
242 7f5b7d3e Blue Swirl
#if defined(DEBUG_PIC) || defined(DEBUG_IRQ_LATENCY)
243 15aeac38 bellard
            irq = irq2 + 8;
244 7f5b7d3e Blue Swirl
#endif
245 15aeac38 bellard
        } else {
246 3de388f6 bellard
            intno = s->pics[0].irq_base + irq;
247 15aeac38 bellard
        }
248 15aeac38 bellard
    } else {
249 15aeac38 bellard
        /* spurious IRQ on host controller */
250 15aeac38 bellard
        irq = 7;
251 3de388f6 bellard
        intno = s->pics[0].irq_base + irq;
252 15aeac38 bellard
    }
253 3de388f6 bellard
    pic_update_irq(s);
254 3b46e624 ths
255 80cabfad bellard
#ifdef DEBUG_IRQ_LATENCY
256 5fafdf24 ths
    printf("IRQ%d latency=%0.3fus\n",
257 5fafdf24 ths
           irq,
258 6ee093c9 Juan Quintela
           (double)(qemu_get_clock(vm_clock) -
259 6ee093c9 Juan Quintela
                    irq_time[irq]) * 1000000.0 / get_ticks_per_sec());
260 80cabfad bellard
#endif
261 8ac02ff8 Blue Swirl
    DPRINTF("pic_interrupt: irq=%d\n", irq);
262 80cabfad bellard
    return intno;
263 80cabfad bellard
}
264 80cabfad bellard
265 d7d02e3c bellard
static void pic_reset(void *opaque)
266 d7d02e3c bellard
{
267 d7d02e3c bellard
    PicState *s = opaque;
268 d7d02e3c bellard
269 3de388f6 bellard
    s->last_irr = 0;
270 3de388f6 bellard
    s->irr = 0;
271 3de388f6 bellard
    s->imr = 0;
272 3de388f6 bellard
    s->isr = 0;
273 3de388f6 bellard
    s->priority_add = 0;
274 3de388f6 bellard
    s->irq_base = 0;
275 3de388f6 bellard
    s->read_reg_select = 0;
276 3de388f6 bellard
    s->poll = 0;
277 3de388f6 bellard
    s->special_mask = 0;
278 3de388f6 bellard
    s->init_state = 0;
279 3de388f6 bellard
    s->auto_eoi = 0;
280 3de388f6 bellard
    s->rotate_on_auto_eoi = 0;
281 3de388f6 bellard
    s->special_fully_nested_mode = 0;
282 3de388f6 bellard
    s->init4 = 0;
283 2053152b ths
    s->single_mode = 0;
284 4dbe19e1 bellard
    /* Note: ELCR is not reset */
285 d7d02e3c bellard
}
286 d7d02e3c bellard
287 b41a2cd1 bellard
static void pic_ioport_write(void *opaque, uint32_t addr, uint32_t val)
288 80cabfad bellard
{
289 b41a2cd1 bellard
    PicState *s = opaque;
290 d7d02e3c bellard
    int priority, cmd, irq;
291 80cabfad bellard
292 8ac02ff8 Blue Swirl
    DPRINTF("write: addr=0x%02x val=0x%02x\n", addr, val);
293 80cabfad bellard
    addr &= 1;
294 80cabfad bellard
    if (addr == 0) {
295 80cabfad bellard
        if (val & 0x10) {
296 80cabfad bellard
            /* init */
297 d7d02e3c bellard
            pic_reset(s);
298 b54ad049 bellard
            /* deassert a pending interrupt */
299 d537cf6c pbrook
            qemu_irq_lower(s->pics_state->parent_irq);
300 80cabfad bellard
            s->init_state = 1;
301 80cabfad bellard
            s->init4 = val & 1;
302 2053152b ths
            s->single_mode = val & 2;
303 80cabfad bellard
            if (val & 0x08)
304 80cabfad bellard
                hw_error("level sensitive irq not supported");
305 80cabfad bellard
        } else if (val & 0x08) {
306 80cabfad bellard
            if (val & 0x04)
307 80cabfad bellard
                s->poll = 1;
308 80cabfad bellard
            if (val & 0x02)
309 80cabfad bellard
                s->read_reg_select = val & 1;
310 80cabfad bellard
            if (val & 0x40)
311 80cabfad bellard
                s->special_mask = (val >> 5) & 1;
312 80cabfad bellard
        } else {
313 80cabfad bellard
            cmd = val >> 5;
314 80cabfad bellard
            switch(cmd) {
315 80cabfad bellard
            case 0:
316 80cabfad bellard
            case 4:
317 80cabfad bellard
                s->rotate_on_auto_eoi = cmd >> 2;
318 80cabfad bellard
                break;
319 80cabfad bellard
            case 1: /* end of interrupt */
320 80cabfad bellard
            case 5:
321 80cabfad bellard
                priority = get_priority(s, s->isr);
322 80cabfad bellard
                if (priority != 8) {
323 80cabfad bellard
                    irq = (priority + s->priority_add) & 7;
324 80cabfad bellard
                    s->isr &= ~(1 << irq);
325 80cabfad bellard
                    if (cmd == 5)
326 80cabfad bellard
                        s->priority_add = (irq + 1) & 7;
327 3de388f6 bellard
                    pic_update_irq(s->pics_state);
328 80cabfad bellard
                }
329 80cabfad bellard
                break;
330 80cabfad bellard
            case 3:
331 80cabfad bellard
                irq = val & 7;
332 80cabfad bellard
                s->isr &= ~(1 << irq);
333 3de388f6 bellard
                pic_update_irq(s->pics_state);
334 80cabfad bellard
                break;
335 80cabfad bellard
            case 6:
336 80cabfad bellard
                s->priority_add = (val + 1) & 7;
337 3de388f6 bellard
                pic_update_irq(s->pics_state);
338 80cabfad bellard
                break;
339 80cabfad bellard
            case 7:
340 80cabfad bellard
                irq = val & 7;
341 80cabfad bellard
                s->isr &= ~(1 << irq);
342 80cabfad bellard
                s->priority_add = (irq + 1) & 7;
343 3de388f6 bellard
                pic_update_irq(s->pics_state);
344 80cabfad bellard
                break;
345 80cabfad bellard
            default:
346 80cabfad bellard
                /* no operation */
347 80cabfad bellard
                break;
348 80cabfad bellard
            }
349 80cabfad bellard
        }
350 80cabfad bellard
    } else {
351 80cabfad bellard
        switch(s->init_state) {
352 80cabfad bellard
        case 0:
353 80cabfad bellard
            /* normal mode */
354 80cabfad bellard
            s->imr = val;
355 3de388f6 bellard
            pic_update_irq(s->pics_state);
356 80cabfad bellard
            break;
357 80cabfad bellard
        case 1:
358 80cabfad bellard
            s->irq_base = val & 0xf8;
359 2bb081f7 ths
            s->init_state = s->single_mode ? (s->init4 ? 3 : 0) : 2;
360 80cabfad bellard
            break;
361 80cabfad bellard
        case 2:
362 80cabfad bellard
            if (s->init4) {
363 80cabfad bellard
                s->init_state = 3;
364 80cabfad bellard
            } else {
365 80cabfad bellard
                s->init_state = 0;
366 80cabfad bellard
            }
367 80cabfad bellard
            break;
368 80cabfad bellard
        case 3:
369 80cabfad bellard
            s->special_fully_nested_mode = (val >> 4) & 1;
370 80cabfad bellard
            s->auto_eoi = (val >> 1) & 1;
371 80cabfad bellard
            s->init_state = 0;
372 80cabfad bellard
            break;
373 80cabfad bellard
        }
374 80cabfad bellard
    }
375 80cabfad bellard
}
376 80cabfad bellard
377 80cabfad bellard
static uint32_t pic_poll_read (PicState *s, uint32_t addr1)
378 80cabfad bellard
{
379 80cabfad bellard
    int ret;
380 80cabfad bellard
381 80cabfad bellard
    ret = pic_get_irq(s);
382 80cabfad bellard
    if (ret >= 0) {
383 80cabfad bellard
        if (addr1 >> 7) {
384 3de388f6 bellard
            s->pics_state->pics[0].isr &= ~(1 << 2);
385 3de388f6 bellard
            s->pics_state->pics[0].irr &= ~(1 << 2);
386 80cabfad bellard
        }
387 80cabfad bellard
        s->irr &= ~(1 << ret);
388 80cabfad bellard
        s->isr &= ~(1 << ret);
389 80cabfad bellard
        if (addr1 >> 7 || ret != 2)
390 3de388f6 bellard
            pic_update_irq(s->pics_state);
391 80cabfad bellard
    } else {
392 80cabfad bellard
        ret = 0x07;
393 3de388f6 bellard
        pic_update_irq(s->pics_state);
394 80cabfad bellard
    }
395 80cabfad bellard
396 80cabfad bellard
    return ret;
397 80cabfad bellard
}
398 80cabfad bellard
399 b41a2cd1 bellard
static uint32_t pic_ioport_read(void *opaque, uint32_t addr1)
400 80cabfad bellard
{
401 b41a2cd1 bellard
    PicState *s = opaque;
402 80cabfad bellard
    unsigned int addr;
403 80cabfad bellard
    int ret;
404 80cabfad bellard
405 80cabfad bellard
    addr = addr1;
406 80cabfad bellard
    addr &= 1;
407 80cabfad bellard
    if (s->poll) {
408 80cabfad bellard
        ret = pic_poll_read(s, addr1);
409 80cabfad bellard
        s->poll = 0;
410 80cabfad bellard
    } else {
411 80cabfad bellard
        if (addr == 0) {
412 80cabfad bellard
            if (s->read_reg_select)
413 80cabfad bellard
                ret = s->isr;
414 80cabfad bellard
            else
415 80cabfad bellard
                ret = s->irr;
416 80cabfad bellard
        } else {
417 80cabfad bellard
            ret = s->imr;
418 80cabfad bellard
        }
419 80cabfad bellard
    }
420 8ac02ff8 Blue Swirl
    DPRINTF("read: addr=0x%02x val=0x%02x\n", addr1, ret);
421 80cabfad bellard
    return ret;
422 80cabfad bellard
}
423 80cabfad bellard
424 80cabfad bellard
/* memory mapped interrupt status */
425 3de388f6 bellard
/* XXX: may be the same than pic_read_irq() */
426 3de388f6 bellard
uint32_t pic_intack_read(PicState2 *s)
427 80cabfad bellard
{
428 80cabfad bellard
    int ret;
429 80cabfad bellard
430 3de388f6 bellard
    ret = pic_poll_read(&s->pics[0], 0x00);
431 80cabfad bellard
    if (ret == 2)
432 3de388f6 bellard
        ret = pic_poll_read(&s->pics[1], 0x80) + 8;
433 80cabfad bellard
    /* Prepare for ISR read */
434 3de388f6 bellard
    s->pics[0].read_reg_select = 1;
435 3b46e624 ths
436 80cabfad bellard
    return ret;
437 80cabfad bellard
}
438 80cabfad bellard
439 660de336 bellard
static void elcr_ioport_write(void *opaque, uint32_t addr, uint32_t val)
440 660de336 bellard
{
441 660de336 bellard
    PicState *s = opaque;
442 660de336 bellard
    s->elcr = val & s->elcr_mask;
443 660de336 bellard
}
444 660de336 bellard
445 660de336 bellard
static uint32_t elcr_ioport_read(void *opaque, uint32_t addr1)
446 660de336 bellard
{
447 660de336 bellard
    PicState *s = opaque;
448 660de336 bellard
    return s->elcr;
449 660de336 bellard
}
450 660de336 bellard
451 77eea838 Juan Quintela
static const VMStateDescription vmstate_pic = {
452 77eea838 Juan Quintela
    .name = "i8259",
453 77eea838 Juan Quintela
    .version_id = 1,
454 77eea838 Juan Quintela
    .minimum_version_id = 1,
455 77eea838 Juan Quintela
    .minimum_version_id_old = 1,
456 77eea838 Juan Quintela
    .fields      = (VMStateField []) {
457 77eea838 Juan Quintela
        VMSTATE_UINT8(last_irr, PicState),
458 77eea838 Juan Quintela
        VMSTATE_UINT8(irr, PicState),
459 77eea838 Juan Quintela
        VMSTATE_UINT8(imr, PicState),
460 77eea838 Juan Quintela
        VMSTATE_UINT8(isr, PicState),
461 77eea838 Juan Quintela
        VMSTATE_UINT8(priority_add, PicState),
462 77eea838 Juan Quintela
        VMSTATE_UINT8(irq_base, PicState),
463 77eea838 Juan Quintela
        VMSTATE_UINT8(read_reg_select, PicState),
464 77eea838 Juan Quintela
        VMSTATE_UINT8(poll, PicState),
465 77eea838 Juan Quintela
        VMSTATE_UINT8(special_mask, PicState),
466 77eea838 Juan Quintela
        VMSTATE_UINT8(init_state, PicState),
467 77eea838 Juan Quintela
        VMSTATE_UINT8(auto_eoi, PicState),
468 77eea838 Juan Quintela
        VMSTATE_UINT8(rotate_on_auto_eoi, PicState),
469 77eea838 Juan Quintela
        VMSTATE_UINT8(special_fully_nested_mode, PicState),
470 77eea838 Juan Quintela
        VMSTATE_UINT8(init4, PicState),
471 77eea838 Juan Quintela
        VMSTATE_UINT8(single_mode, PicState),
472 77eea838 Juan Quintela
        VMSTATE_UINT8(elcr, PicState),
473 77eea838 Juan Quintela
        VMSTATE_END_OF_LIST()
474 77eea838 Juan Quintela
    }
475 77eea838 Juan Quintela
};
476 b0a21b53 bellard
477 b0a21b53 bellard
/* XXX: add generic master/slave system */
478 660de336 bellard
static void pic_init1(int io_addr, int elcr_addr, PicState *s)
479 b0a21b53 bellard
{
480 b0a21b53 bellard
    register_ioport_write(io_addr, 2, 1, pic_ioport_write, s);
481 b0a21b53 bellard
    register_ioport_read(io_addr, 2, 1, pic_ioport_read, s);
482 660de336 bellard
    if (elcr_addr >= 0) {
483 660de336 bellard
        register_ioport_write(elcr_addr, 1, 1, elcr_ioport_write, s);
484 660de336 bellard
        register_ioport_read(elcr_addr, 1, 1, elcr_ioport_read, s);
485 660de336 bellard
    }
486 0be71e32 Alex Williamson
    vmstate_register(NULL, io_addr, &vmstate_pic, s);
487 a08d4367 Jan Kiszka
    qemu_register_reset(pic_reset, s);
488 b0a21b53 bellard
}
489 b0a21b53 bellard
490 376253ec aliguori
void pic_info(Monitor *mon)
491 ba91cd80 bellard
{
492 ba91cd80 bellard
    int i;
493 ba91cd80 bellard
    PicState *s;
494 3b46e624 ths
495 3de388f6 bellard
    if (!isa_pic)
496 3de388f6 bellard
        return;
497 ba91cd80 bellard
498 ba91cd80 bellard
    for(i=0;i<2;i++) {
499 3de388f6 bellard
        s = &isa_pic->pics[i];
500 376253ec aliguori
        monitor_printf(mon, "pic%d: irr=%02x imr=%02x isr=%02x hprio=%d "
501 376253ec aliguori
                       "irq_base=%02x rr_sel=%d elcr=%02x fnm=%d\n",
502 376253ec aliguori
                       i, s->irr, s->imr, s->isr, s->priority_add,
503 376253ec aliguori
                       s->irq_base, s->read_reg_select, s->elcr,
504 376253ec aliguori
                       s->special_fully_nested_mode);
505 ba91cd80 bellard
    }
506 ba91cd80 bellard
}
507 ba91cd80 bellard
508 376253ec aliguori
void irq_info(Monitor *mon)
509 4a0fb71e bellard
{
510 4a0fb71e bellard
#ifndef DEBUG_IRQ_COUNT
511 376253ec aliguori
    monitor_printf(mon, "irq statistic code not compiled.\n");
512 4a0fb71e bellard
#else
513 4a0fb71e bellard
    int i;
514 4a0fb71e bellard
    int64_t count;
515 4a0fb71e bellard
516 376253ec aliguori
    monitor_printf(mon, "IRQ statistics:\n");
517 4a0fb71e bellard
    for (i = 0; i < 16; i++) {
518 4a0fb71e bellard
        count = irq_count[i];
519 4a0fb71e bellard
        if (count > 0)
520 376253ec aliguori
            monitor_printf(mon, "%2d: %" PRId64 "\n", i, count);
521 4a0fb71e bellard
    }
522 4a0fb71e bellard
#endif
523 4a0fb71e bellard
}
524 ba91cd80 bellard
525 d537cf6c pbrook
qemu_irq *i8259_init(qemu_irq parent_irq)
526 80cabfad bellard
{
527 3de388f6 bellard
    PicState2 *s;
528 d537cf6c pbrook
529 3de388f6 bellard
    s = qemu_mallocz(sizeof(PicState2));
530 3de388f6 bellard
    pic_init1(0x20, 0x4d0, &s->pics[0]);
531 3de388f6 bellard
    pic_init1(0xa0, 0x4d1, &s->pics[1]);
532 3de388f6 bellard
    s->pics[0].elcr_mask = 0xf8;
533 3de388f6 bellard
    s->pics[1].elcr_mask = 0xde;
534 d537cf6c pbrook
    s->parent_irq = parent_irq;
535 3de388f6 bellard
    s->pics[0].pics_state = s;
536 3de388f6 bellard
    s->pics[1].pics_state = s;
537 d537cf6c pbrook
    isa_pic = s;
538 d537cf6c pbrook
    return qemu_allocate_irqs(i8259_set_irq, s, 16);
539 80cabfad bellard
}