Statistics
| Branch: | Revision:

root / hw / i8259.c @ 54fa5af5

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