Statistics
| Branch: | Revision:

root / hw / i8259.c @ b60c470b

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