Revision 611493d9

b/hw/openpic.c
34 34
 */
35 35
#include "vl.h"
36 36

  
37
#define DEBUG_OPENPIC
37
//#define DEBUG_OPENPIC
38 38

  
39 39
#ifdef DEBUG_OPENPIC
40 40
#define DPRINTF(fmt, args...) do { printf(fmt , ##args); } while (0)
......
65 65

  
66 66
#define MAX_CPU     2
67 67
#define MAX_IRQ    64
68
#define EXT_IRQ    16
68
#define EXT_IRQ    48
69 69
#define MAX_DBL     0
70 70
#define MAX_MBX     0
71 71
#define MAX_TMR     4
......
139 139
    uint32_t ide;   /* IRQ destination register */
140 140
    int type;
141 141
    int last_cpu;
142
    int waited_acks;
142
    int pending;    /* TRUE if IRQ is pending */
143 143
} IRQ_src_t;
144 144

  
145 145
enum IPVP_bits {
......
150 150
    IPVP_SENSE    = 22,
151 151
};
152 152
#define IPVP_PRIORITY_MASK     (0x1F << 16)
153
#define IPVP_PRIORITY(_ipvpr_) (((_ipvpr_) & IPVP_PRIORITY_MASK) >> 16)
153
#define IPVP_PRIORITY(_ipvpr_) ((int)(((_ipvpr_) & IPVP_PRIORITY_MASK) >> 16))
154 154
#define IPVP_VECTOR_MASK       ((1 << VECTOR_BITS) - 1)
155 155
#define IPVP_VECTOR(_ipvpr_)   ((_ipvpr_) & IPVP_VECTOR_MASK)
156 156

  
......
162 162
    CPUState *env; /* Needed if we did SMP */
163 163
} IRQ_dst_t;
164 164

  
165
typedef struct openpic_t {
165
struct openpic_t {
166 166
    PCIDevice pci_dev;
167 167
    /* Global registers */
168 168
    uint32_t frep; /* Feature reporting register */
......
194 194
	uint32_t mbr;    /* Mailbox register */
195 195
    } mailboxes[MAX_MAILBOXES];
196 196
#endif
197
} openpic_t;
197
};
198 198

  
199 199
static inline void IRQ_setbit (IRQ_queue_t *q, int n_IRQ)
200 200
{
......
220 220
    priority = -1;
221 221
    for (i = 0; i < MAX_IRQ; i++) {
222 222
	if (IRQ_testbit(q, i)) {
223
            DPRINTF("IRQ_check: irq %d set ipvp_pr=%d pr=%d\n", 
224
                    i, IPVP_PRIORITY(opp->src[i].ipvp), priority);
223 225
	    if (IPVP_PRIORITY(opp->src[i].ipvp) > priority) {
224 226
		next = i;
225 227
		priority = IPVP_PRIORITY(opp->src[i].ipvp);
......
233 235
static int IRQ_get_next (openpic_t *opp, IRQ_queue_t *q)
234 236
{
235 237
    if (q->next == -1) {
236
	if (q->queue == 0) {
237
	    /* No more IRQ */
238
	    return -1;
239
	}
238
        /* XXX: optimize */
240 239
	IRQ_check(opp, q);
241 240
    }
242 241

  
......
269 268
    }
270 269
}
271 270

  
272
void openpic_set_IRQ (openpic_t *opp, int n_IRQ, int level)
271
/* update pic state because registers for n_IRQ have changed value */
272
static void openpic_update_irq(openpic_t *opp, int n_IRQ)
273 273
{
274 274
    IRQ_src_t *src;
275 275
    int i;
276 276

  
277 277
    src = &opp->src[n_IRQ];
278
    if (!test_bit(&src->ipvp, IPVP_MASK)) {
278

  
279
    if (!src->pending) {
280
        /* no irq pending */
281
        return;
282
    }
283
    if (test_bit(&src->ipvp, IPVP_MASK)) {
279 284
	/* Interrupt source is disabled */
280 285
	return;
281 286
    }
......
283 288
	/* Priority set to zero */
284 289
	return;
285 290
    }
291
    if (test_bit(&src->ipvp, IPVP_ACTIVITY)) {
292
        /* IRQ already active */
293
        return;
294
    }
286 295
    if (src->ide == 0x00000000) {
287 296
	/* No target */
288 297
	return;
289 298
    }
290
    if (level == 0) {
291
	if (test_bit(&src->ipvp, IPVP_ACTIVITY) &&
292
	    test_bit(&src->ipvp, IPVP_SENSE)) {
293
	    /* Inactivate a active level-sensitive IRQ */
294
	    reset_bit(&src->ipvp, IPVP_ACTIVITY);
295
	}
299

  
300
    if (!test_bit(&src->ipvp, IPVP_MODE) ||
301
        src->ide == (1 << src->last_cpu)) {
302
        /* Directed delivery mode */
303
        for (i = 0; i < opp->nb_cpus; i++) {
304
            if (test_bit(&src->ide, i))
305
                IRQ_local_pipe(opp, i, n_IRQ);
306
        }
296 307
    } else {
297
	if (test_bit(&src->ipvp, IPVP_ACTIVITY)) {
298
	    /* Interrupt already pending */
299
	    return;
300
	}
301
	if (!test_bit(&src->ipvp, IPVP_MODE) ||
302
	    src->ide == (1 << src->last_cpu)) {
303
	    /* Directed delivery mode */
304
	    for (i = 0; i < opp->nb_cpus; i++) {
305
		if (test_bit(&src->ide, i))
306
		    IRQ_local_pipe(opp, i, n_IRQ);
307
	    }
308
	} else {
309
	    /* Distributed delivery mode */
310
	    for (i = src->last_cpu; i < src->last_cpu; i++) {
311
		if (i == MAX_IRQ)
312
		    i = 0;
313
		if (test_bit(&src->ide, i)) {
314
		    IRQ_local_pipe(opp, i, n_IRQ);
315
		    src->last_cpu = i;
316
		    break;
317
		}
318
	    }
319
	}
308
        /* Distributed delivery mode */
309
        /* XXX: incorrect code */
310
        for (i = src->last_cpu; i < src->last_cpu; i++) {
311
            if (i == MAX_IRQ)
312
                i = 0;
313
            if (test_bit(&src->ide, i)) {
314
                IRQ_local_pipe(opp, i, n_IRQ);
315
                src->last_cpu = i;
316
                break;
317
            }
318
        }
319
    }
320
}
321

  
322
void openpic_set_irq(openpic_t *opp, int n_IRQ, int level)
323
{
324
    IRQ_src_t *src;
325

  
326
    src = &opp->src[n_IRQ];
327
    DPRINTF("openpic: set irq %d = %d ipvp=%08x\n", 
328
            n_IRQ, level, src->ipvp);
329
    if (test_bit(&src->ipvp, IPVP_SENSE)) {
330
        /* level-sensitive irq */
331
        src->pending = level;
332
        if (!level)
333
            reset_bit(&src->ipvp, IPVP_ACTIVITY);
334
    } else {
335
        /* edge-sensitive irq */
336
        if (level)
337
            src->pending = 1;
320 338
    }
339
    openpic_update_irq(opp, n_IRQ);
321 340
}
322 341

  
323 342
static void openpic_reset (openpic_t *opp)
......
389 408

  
390 409
    switch (reg) {
391 410
    case IRQ_IPVP:
392
	tmp = opp->src[n_IRQ].ipvp & 0x40000000;
393
	if (tmp == 0) {
394
	    tmp |= val & 0x80000000;
395
	    if ((opp->src[n_IRQ].type & IRQ_EXTERNAL) != 0)
396
		tmp |= val & 0x40C00000;
397
	    else if ((opp->src[n_IRQ].type & IRQ_TIMER) != 0)
398
		tmp |= val & 0x00F00000;
399
	} else {
400
	    tmp |= val & 0x80000000;
401
	}
402
	opp->src[n_IRQ].ipvp = tmp | (val & 0x000F00FF);
403
        DPRINTF("Set IPVP %d to 0x%08x\n", n_IRQ, opp->src[n_IRQ].ipvp);
411
        /* NOTE: not fully accurate for special IRQs, but simple and
412
           sufficient */
413
        /* ACTIVITY bit is read-only */
414
	opp->src[n_IRQ].ipvp = 
415
            (opp->src[n_IRQ].ipvp & 0x40000000) |
416
            (val & 0x800F00FF);
417
        openpic_update_irq(opp, n_IRQ);
418
        DPRINTF("Set IPVP %d to 0x%08x -> 0x%08x\n", 
419
                n_IRQ, val, opp->src[n_IRQ].ipvp);
404 420
	break;
405 421
    case IRQ_IDE:
406 422
	tmp = val & 0xC0000000;
......
736 752
    case 0x70:
737 753
        idx = (addr - 0x40) >> 4;
738 754
        write_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IDE, val);
739
        openpic_set_IRQ(opp, IRQ_IPI0 + idx, 1);
740
        openpic_set_IRQ(opp, IRQ_IPI0 + idx, 0);
755
        openpic_set_irq(opp, IRQ_IPI0 + idx, 1);
756
        openpic_set_irq(opp, IRQ_IPI0 + idx, 0);
741 757
        break;
742 758
#endif
743 759
    case 0x80: /* PCTP */
......
818 834
	    }
819 835
	    IRQ_resetbit(&dst->raised, n_IRQ);
820 836
	    dst->raised.next = -1;
821
	    if (!test_bit(&src->ipvp, IPVP_SENSE))
837
	    if (!test_bit(&src->ipvp, IPVP_SENSE)) {
838
                /* edge-sensitive IRQ */
822 839
		reset_bit(&src->ipvp, IPVP_ACTIVITY);
840
                src->pending = 0;
841
            }
823 842
	}
824 843
	break;
825 844
    case 0xB0: /* PEOI */
......
862 881
    openpic_t *opp = opaque;
863 882

  
864 883
    addr &= 0x3FFFF;
865
    DPRINTF("%s: offset %08lx val: %08x\n", __func__, addr, val);
884
    DPRINTF("%s: offset %08x val: %08x\n", __func__, (int)addr, val);
866 885
    if (addr < 0x1100) {
867 886
        /* Global registers */
868 887
        openpic_gbl_write(opp, addr, val);
......
884 903
    uint32_t retval;
885 904

  
886 905
    addr &= 0x3FFFF;
887
    DPRINTF("%s: offset %08lx\n", __func__, addr);
906
    DPRINTF("%s: offset %08x\n", __func__, (int)addr);
888 907
    if (addr < 0x1100) {
889 908
        /* Global registers */
890 909
        retval = openpic_gbl_read(opp, addr);

Also available in: Unified diff