version 1.5.4.2, 2010/08/11 22:52:36 |
version 1.6, 2008/04/29 06:53:02 |
Line 51 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 51 __KERNEL_RCSID(0, "$NetBSD$"); |
|
|
|
#define MAX_PICS 8 /* 8 PICs ought to be enough for everyone */ |
#define MAX_PICS 8 /* 8 PICs ought to be enough for everyone */ |
|
|
|
#define NVIRQ 32 /* 32 virtual IRQs */ |
|
#define NIRQ 128 /* up to 128 HW IRQs */ |
|
|
|
#define HWIRQ_MAX (NVIRQ - 4 - 1) |
|
#define HWIRQ_MASK 0x0fffffff |
#define LEGAL_VIRQ(x) ((x) >= 0 && (x) < NVIRQ) |
#define LEGAL_VIRQ(x) ((x) >= 0 && (x) < NVIRQ) |
|
|
struct pic_ops *pics[MAX_PICS]; |
struct pic_ops *pics[MAX_PICS]; |
Line 58 int num_pics = 0; |
|
Line 63 int num_pics = 0; |
|
int max_base = 0; |
int max_base = 0; |
uint8_t virq[NIRQ]; |
uint8_t virq[NIRQ]; |
int virq_max = 0; |
int virq_max = 0; |
imask_t imask[NIPL]; |
int imask[NIPL]; |
int primary_pic = 0; |
int primary_pic = 0; |
|
|
static int fakeintr(void *); |
static int fakeintr(void *); |
Line 89 pic_add(struct pic_ops *pic) |
|
Line 94 pic_add(struct pic_ops *pic) |
|
pic->pic_intrbase = max_base; |
pic->pic_intrbase = max_base; |
max_base += pic->pic_numintrs; |
max_base += pic->pic_numintrs; |
num_pics++; |
num_pics++; |
|
|
return pic->pic_intrbase; |
return pic->pic_intrbase; |
} |
} |
|
|
Line 347 intr_calculatemasks(void) |
|
Line 352 intr_calculatemasks(void) |
|
|
|
/* Then figure out which IRQs use each level. */ |
/* Then figure out which IRQs use each level. */ |
for (level = 0; level < NIPL; level++) { |
for (level = 0; level < NIPL; level++) { |
register imask_t irqs = 0; |
register int irqs = 0; |
for (irq = 0, is = intrsources; irq < NVIRQ; irq++, is++) |
for (irq = 0, is = intrsources; irq < NVIRQ; irq++, is++) |
if (is->is_level & (1 << level)) |
if (is->is_level & (1 << level)) |
irqs |= 1ULL << irq; |
irqs |= 1 << irq; |
imask[level] = irqs; |
imask[level] = irqs; |
} |
} |
|
|
Line 358 intr_calculatemasks(void) |
|
Line 363 intr_calculatemasks(void) |
|
* IPL_CLOCK should mask clock interrupt even if interrupt handler |
* IPL_CLOCK should mask clock interrupt even if interrupt handler |
* is not registered. |
* is not registered. |
*/ |
*/ |
imask[IPL_CLOCK] |= 1ULL << SPL_CLOCK; |
imask[IPL_CLOCK] |= 1 << SPL_CLOCK; |
|
|
/* |
/* |
* Initialize soft interrupt masks to block themselves. |
* Initialize soft interrupt masks to block themselves. |
*/ |
*/ |
imask[IPL_SOFTCLOCK] = 1ULL << SIR_CLOCK; |
imask[IPL_SOFTCLOCK] = 1 << SIR_CLOCK; |
imask[IPL_SOFTNET] = 1ULL << SIR_NET; |
imask[IPL_SOFTNET] = 1 << SIR_NET; |
imask[IPL_SOFTSERIAL] = 1ULL << SIR_SERIAL; |
imask[IPL_SOFTSERIAL] = 1 << SIR_SERIAL; |
|
|
/* |
/* |
* IPL_NONE is used for hardware interrupts that are never blocked, |
* IPL_NONE is used for hardware interrupts that are never blocked, |
Line 394 intr_calculatemasks(void) |
|
Line 399 intr_calculatemasks(void) |
|
/* IPL_SERIAL must block IPL_TTY */ |
/* IPL_SERIAL must block IPL_TTY */ |
imask[IPL_SERIAL] |= imask[IPL_TTY]; |
imask[IPL_SERIAL] |= imask[IPL_TTY]; |
|
|
/* IPL_HIGH must block all other priority levels */ |
/* IPL_HIGH must block all other priority levels */ |
for (i = IPL_NONE; i < IPL_HIGH; i++) |
for (i = IPL_NONE; i < IPL_HIGH; i++) |
imask[IPL_HIGH] |= imask[i]; |
imask[IPL_HIGH] |= imask[i]; |
#else /* !SLOPPY_IPLS */ |
#else /* !SLOPPY_IPLS */ |
Line 414 intr_calculatemasks(void) |
|
Line 419 intr_calculatemasks(void) |
|
|
|
/* And eventually calculate the complete masks. */ |
/* And eventually calculate the complete masks. */ |
for (irq = 0, is = intrsources; irq < NVIRQ; irq++, is++) { |
for (irq = 0, is = intrsources; irq < NVIRQ; irq++, is++) { |
register imask_t irqs = 1ULL << irq; |
register int irqs = 1 << irq; |
for (q = is->is_hand; q; q = q->ih_next) |
for (q = is->is_hand; q; q = q->ih_next) |
irqs |= imask[q->ih_level]; |
irqs |= imask[q->ih_level]; |
is->is_mask = irqs; |
is->is_mask = irqs; |
Line 426 intr_calculatemasks(void) |
|
Line 431 intr_calculatemasks(void) |
|
for (i = 0; i < current->pic_numintrs; i++) |
for (i = 0; i < current->pic_numintrs; i++) |
current->pic_disable_irq(current, i); |
current->pic_disable_irq(current, i); |
} |
} |
|
|
for (irq = 0, is = intrsources; irq < NVIRQ; irq++, is++) { |
for (irq = 0, is = intrsources; irq < NVIRQ; irq++, is++) { |
if (is->is_hand) |
if (is->is_hand) |
pic_enable_irq(is->is_hwirq); |
pic_enable_irq(is->is_hwirq); |
Line 454 pic_mark_pending(int irq) |
|
Line 459 pic_mark_pending(int irq) |
|
|
|
v = virq[irq]; |
v = virq[irq]; |
if (v == 0) |
if (v == 0) |
printf("IRQ %d maps to 0\n", irq); |
printf("IRQ %d maps to 0\n", irq); |
|
|
msr = mfmsr(); |
msr = mfmsr(); |
mtmsr(msr & ~PSL_EE); |
mtmsr(msr & ~PSL_EE); |
ci->ci_ipending |= 1ULL << v; |
ci->ci_ipending |= 1 << v; |
mtmsr(msr); |
mtmsr(msr); |
} |
} |
|
|
void |
void |
pic_do_pending_int(void) |
pic_do_pending_int(void) |
Line 471 pic_do_pending_int(void) |
|
Line 476 pic_do_pending_int(void) |
|
struct pic_ops *pic; |
struct pic_ops *pic; |
int irq; |
int irq; |
int pcpl; |
int pcpl; |
imask_t hwpend; |
int hwpend; |
int emsr, dmsr; |
int emsr, dmsr; |
|
|
if (ci->ci_iactive) |
if (ci->ci_iactive) |
|
|
/* Do now unmasked pendings */ |
/* Do now unmasked pendings */ |
ci->ci_idepth++; |
ci->ci_idepth++; |
while ((hwpend = (ci->ci_ipending & ~pcpl & HWIRQ_MASK)) != 0) { |
while ((hwpend = (ci->ci_ipending & ~pcpl & HWIRQ_MASK)) != 0) { |
/* Get most significant pending bit */ |
irq = 31 - cntlzw(hwpend); |
irq = MS_PENDING(hwpend); |
|
KASSERT(irq <= virq_max); |
KASSERT(irq <= virq_max); |
ci->ci_ipending &= ~(1ULL << irq); |
ci->ci_ipending &= ~(1 << irq); |
if (irq == 0) { |
if (irq == 0) { |
printf("VIRQ0"); |
printf("VIRQ0"); |
continue; |
continue; |
|
|
ci->ci_idepth--; |
ci->ci_idepth--; |
|
|
#ifdef __HAVE_FAST_SOFTINTS |
#ifdef __HAVE_FAST_SOFTINTS |
if ((ci->ci_ipending & ~pcpl) & (1ULL << SIR_SERIAL)) { |
if ((ci->ci_ipending & ~pcpl) & (1 << SIR_SERIAL)) { |
ci->ci_ipending &= ~(1ULL << SIR_SERIAL); |
ci->ci_ipending &= ~(1 << SIR_SERIAL); |
splsoftserial(); |
splsoftserial(); |
mtmsr(emsr); |
mtmsr(emsr); |
softintr__run(IPL_SOFTSERIAL); |
softintr__run(IPL_SOFTSERIAL); |
|
|
ci->ci_ev_softserial.ev_count++; |
ci->ci_ev_softserial.ev_count++; |
goto again; |
goto again; |
} |
} |
if ((ci->ci_ipending & ~pcpl) & (1ULL << SIR_NET)) { |
if ((ci->ci_ipending & ~pcpl) & (1 << SIR_NET)) { |
ci->ci_ipending &= ~(1ULL << SIR_NET); |
ci->ci_ipending &= ~(1 << SIR_NET); |
splsoftnet(); |
splsoftnet(); |
mtmsr(emsr); |
mtmsr(emsr); |
softintr__run(IPL_SOFTNET); |
softintr__run(IPL_SOFTNET); |
|
|
ci->ci_ev_softnet.ev_count++; |
ci->ci_ev_softnet.ev_count++; |
goto again; |
goto again; |
} |
} |
if ((ci->ci_ipending & ~pcpl) & (1ULL << SIR_CLOCK)) { |
if ((ci->ci_ipending & ~pcpl) & (1 << SIR_CLOCK)) { |
ci->ci_ipending &= ~(1ULL << SIR_CLOCK); |
ci->ci_ipending &= ~(1 << SIR_CLOCK); |
splsoftclock(); |
splsoftclock(); |
mtmsr(emsr); |
mtmsr(emsr); |
softintr__run(IPL_SOFTCLOCK); |
softintr__run(IPL_SOFTCLOCK); |
Line 577 pic_handle_intr(void *cookie) |
|
Line 581 pic_handle_intr(void *cookie) |
|
struct intr_source *is; |
struct intr_source *is; |
struct intrhand *ih; |
struct intrhand *ih; |
int irq, realirq; |
int irq, realirq; |
int pcpl, msr, bail; |
int pcpl, msr, r_imen, bail; |
imask_t r_imen; |
|
|
|
realirq = pic->pic_get_irq(pic, PIC_GET_IRQ); |
realirq = pic->pic_get_irq(pic, PIC_GET_IRQ); |
if (realirq == 255) |
if (realirq == 255) |
|
|
} |
} |
#endif /* PIC_DEBUG */ |
#endif /* PIC_DEBUG */ |
KASSERT(realirq < pic->pic_numintrs); |
KASSERT(realirq < pic->pic_numintrs); |
r_imen = 1ULL << irq; |
r_imen = 1 << irq; |
is = &intrsources[irq]; |
is = &intrsources[irq]; |
|
|
if ((pcpl & r_imen) != 0) { |
if ((pcpl & r_imen) != 0) { |
|
|
/* this interrupt is no longer pending */ |
/* this interrupt is no longer pending */ |
ci->ci_ipending &= ~r_imen; |
ci->ci_ipending &= ~r_imen; |
ci->ci_idepth++; |
ci->ci_idepth++; |
|
|
splraise(is->is_mask); |
splraise(is->is_mask); |
mtmsr(msr | PSL_EE); |
mtmsr(msr | PSL_EE); |
ih = is->is_hand; |
ih = is->is_hand; |
|
|
} |
} |
mtmsr(msr); |
mtmsr(msr); |
ci->ci_cpl = pcpl; |
ci->ci_cpl = pcpl; |
|
|
uvmexp.intrs++; |
uvmexp.intrs++; |
is->is_ev.ev_count++; |
is->is_ev.ev_count++; |
ci->ci_idepth--; |
ci->ci_idepth--; |
Line 680 splraise(int ncpl) |
|
Line 683 splraise(int ncpl) |
|
int ocpl; |
int ocpl; |
|
|
__asm volatile("sync; eieio"); /* don't reorder.... */ |
__asm volatile("sync; eieio"); /* don't reorder.... */ |
|
|
ocpl = ci->ci_cpl; |
ocpl = ci->ci_cpl; |
ci->ci_cpl = ocpl | ncpl; |
ci->ci_cpl = ocpl | ncpl; |
__asm volatile("sync; eieio"); /* reorder protect */ |
__asm volatile("sync; eieio"); /* reorder protect */ |
|
|
splx(int ncpl) |
splx(int ncpl) |
{ |
{ |
struct cpu_info *ci = curcpu(); |
struct cpu_info *ci = curcpu(); |
|
|
__asm volatile("sync; eieio"); /* reorder protect */ |
__asm volatile("sync; eieio"); /* reorder protect */ |
ci->ci_cpl = ncpl; |
ci->ci_cpl = ncpl; |
if (ci->ci_ipending & ~ncpl) |
if (ci->ci_ipending & ~ncpl) |
Line 723 softintr(int ipl) |
|
Line 726 softintr(int ipl) |
|
|
|
msrsave = mfmsr(); |
msrsave = mfmsr(); |
mtmsr(msrsave & ~PSL_EE); |
mtmsr(msrsave & ~PSL_EE); |
curcpu()->ci_ipending |= 1ULL << ipl; |
curcpu()->ci_ipending |= 1 << ipl; |
mtmsr(msrsave); |
mtmsr(msrsave); |
} |
} |
|
|
|
|
genppc_cpu_configure(void) |
genppc_cpu_configure(void) |
{ |
{ |
aprint_normal("biomask %x netmask %x ttymask %x\n", |
aprint_normal("biomask %x netmask %x ttymask %x\n", |
(u_int)imask[IPL_BIO] & 0x1fffffff, |
imask[IPL_BIO] & 0x1fffffff, |
(u_int)imask[IPL_NET] & 0x1fffffff, |
imask[IPL_NET] & 0x1fffffff, |
(u_int)imask[IPL_TTY] & 0x1fffffff); |
imask[IPL_TTY] & 0x1fffffff); |
|
|
spl0(); |
spl0(); |
} |
} |