Statistics
| Branch: | Revision:

root / hw / i8259.c @ 0986ac3b

History | View | Annotate | Download (15 kB)

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