Change the x86 interrupt code to suspend/resume interrupt controllers

(PICs) rather than interrupt sources.  This allows interrupt controllers
with no interrupt pics (such as the 8259As when APIC is in use) to
participate in suspend/resume.
- Always register the 8259A PICs even if we don't use any of their pins.
- Explicitly reset the 8259As on resume on amd64 if 'device atpic' isn't
  included.
- Add a "dummy" PIC for the local APIC on the BSP to reset the local APIC
  on resume.  This gets suspend/resume working with APIC on UP systems.
  SMP still needs more work to bring the APs back to life.

The MFC after is tentative.

Tested by:	anholt (i386)
Submitted by:	Andrea Bittau <a.bittau at cs.ucl.ac.uk> (3)
MFC after:	1 week
This commit is contained in:
John Baldwin 2006-10-10 23:23:12 +00:00
parent 4ef33d554a
commit 520ffff83e
15 changed files with 224 additions and 98 deletions

View File

@ -37,6 +37,7 @@
* that source.
*/
#include "opt_atpic.h"
#include "opt_ddb.h"
#include <sys/param.h>
@ -62,6 +63,7 @@ typedef void (*mask_fn)(void *);
static int intrcnt_index;
static struct intsrc *interrupt_sources[NUM_IO_INTS];
static struct mtx intr_table_lock;
static STAILQ_HEAD(, pic) pics;
#ifdef SMP
static int assign_cpu;
@ -70,10 +72,45 @@ static void intr_assign_next_cpu(struct intsrc *isrc);
#endif
static void intr_init(void *__dummy);
static int intr_pic_registered(struct pic *pic);
static void intrcnt_setname(const char *name, int index);
static void intrcnt_updatename(struct intsrc *is);
static void intrcnt_register(struct intsrc *is);
static int
intr_pic_registered(struct pic *pic)
{
struct pic *p;
STAILQ_FOREACH(p, &pics, pics) {
if (p == pic)
return (1);
}
return (0);
}
/*
* Register a new interrupt controller (PIC). This is to support suspend
* and resume where we suspend/resume controllers rather than individual
* sources. This also allows controllers with no active sources (such as
* 8259As in a system using the APICs) to participate in suspend and resume.
*/
int
intr_register_pic(struct pic *pic)
{
int error;
mtx_lock_spin(&intr_table_lock);
if (intr_pic_registered(pic))
error = EBUSY;
else {
STAILQ_INSERT_TAIL(&pics, pic, pics);
error = 0;
}
mtx_unlock_spin(&intr_table_lock);
return (error);
}
/*
* Register a new interrupt source with the global interrupt system.
* The global interrupts need to be disabled when this function is
@ -84,6 +121,7 @@ intr_register_source(struct intsrc *isrc)
{
int error, vector;
KASSERT(intr_pic_registered(isrc->is_pic), ("unregistered PIC"));
vector = isrc->is_pic->pic_vector(isrc);
if (interrupt_sources[vector] != NULL)
return (EEXIST);
@ -255,26 +293,29 @@ intr_execute_handlers(struct intsrc *isrc, struct trapframe *frame)
void
intr_resume(void)
{
struct intsrc **isrc;
int i;
struct pic *pic;
#ifndef DEV_ATPIC
atpic_reset();
#endif
mtx_lock_spin(&intr_table_lock);
for (i = 0, isrc = interrupt_sources; i < NUM_IO_INTS; i++, isrc++)
if (*isrc != NULL && (*isrc)->is_pic->pic_resume != NULL)
(*isrc)->is_pic->pic_resume(*isrc);
STAILQ_FOREACH(pic, &pics, pics) {
if (pic->pic_resume != NULL)
pic->pic_resume(pic);
}
mtx_unlock_spin(&intr_table_lock);
}
void
intr_suspend(void)
{
struct intsrc **isrc;
int i;
struct pic *pic;
mtx_lock_spin(&intr_table_lock);
for (i = 0, isrc = interrupt_sources; i < NUM_IO_INTS; i++, isrc++)
if (*isrc != NULL && (*isrc)->is_pic->pic_suspend != NULL)
(*isrc)->is_pic->pic_suspend(*isrc);
STAILQ_FOREACH(pic, &pics, pics) {
if (pic->pic_suspend != NULL)
pic->pic_suspend(pic);
}
mtx_unlock_spin(&intr_table_lock);
}
@ -327,10 +368,33 @@ intr_init(void *dummy __unused)
intrcnt_setname("???", 0);
intrcnt_index = 1;
STAILQ_INIT(&pics);
mtx_init(&intr_table_lock, "intr table", NULL, MTX_SPIN);
}
SYSINIT(intr_init, SI_SUB_INTR, SI_ORDER_FIRST, intr_init, NULL)
#ifndef DEV_ATPIC
/* Initialize the two 8259A's to a known-good shutdown state. */
void
atpic_reset(void)
{
outb(IO_ICU1, ICW1_RESET | ICW1_IC4);
outb(IO_ICU1 + ICU_IMR_OFFSET, IDT_IO_INTS);
outb(IO_ICU1 + ICU_IMR_OFFSET, 1 << 2);
outb(IO_ICU1 + ICU_IMR_OFFSET, ICW4_8086);
outb(IO_ICU1 + ICU_IMR_OFFSET, 0xff);
outb(IO_ICU1, OCW3_SEL | OCW3_RR);
outb(IO_ICU2, ICW1_RESET | ICW1_IC4);
outb(IO_ICU2 + ICU_IMR_OFFSET, IDT_IO_INTS + 8);
outb(IO_ICU2 + ICU_IMR_OFFSET, 2);
outb(IO_ICU2 + ICU_IMR_OFFSET, ICW4_8086);
outb(IO_ICU2 + ICU_IMR_OFFSET, 0xff);
outb(IO_ICU2, OCW3_SEL | OCW3_RR);
}
#endif
#ifdef DDB
/*
* Dump data about interrupt handlers

View File

@ -30,7 +30,6 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_atpic.h"
#include "opt_isa.h"
#include <sys/param.h>
@ -61,8 +60,6 @@ __FBSDID("$FreeBSD$");
#define IRQ_SMI (NUM_IO_INTS + 3)
#define IRQ_DISABLED (NUM_IO_INTS + 4)
#define TODO printf("%s: not implemented!\n", __func__)
static MALLOC_DEFINE(M_IOAPIC, "io_apic", "I/O APIC structures");
/*
@ -115,8 +112,7 @@ static int ioapic_vector(struct intsrc *isrc);
static int ioapic_source_pending(struct intsrc *isrc);
static int ioapic_config_intr(struct intsrc *isrc, enum intr_trigger trig,
enum intr_polarity pol);
static void ioapic_suspend(struct intsrc *isrc);
static void ioapic_resume(struct intsrc *isrc);
static void ioapic_resume(struct pic *pic);
static void ioapic_assign_cpu(struct intsrc *isrc, u_int apic_id);
static void ioapic_program_intpin(struct ioapic_intsrc *intpin);
@ -124,7 +120,7 @@ static STAILQ_HEAD(,ioapic) ioapic_list = STAILQ_HEAD_INITIALIZER(ioapic_list);
struct pic ioapic_template = { ioapic_enable_source, ioapic_disable_source,
ioapic_eoi_source, ioapic_enable_intr,
ioapic_vector, ioapic_source_pending,
ioapic_suspend, ioapic_resume,
NULL, ioapic_resume,
ioapic_config_intr, ioapic_assign_cpu };
static int next_ioapic_base;
@ -419,17 +415,13 @@ ioapic_config_intr(struct intsrc *isrc, enum intr_trigger trig,
}
static void
ioapic_suspend(struct intsrc *isrc)
ioapic_resume(struct pic *pic)
{
struct ioapic *io = (struct ioapic *)pic;
int i;
TODO;
}
static void
ioapic_resume(struct intsrc *isrc)
{
ioapic_program_intpin((struct ioapic_intsrc *)isrc);
for (i = 0; i < io->io_numintr; i++)
ioapic_program_intpin(&io->io_pins[i]);
}
/*
@ -727,6 +719,7 @@ ioapic_register(void *cookie)
io->io_intbase + io->io_numintr - 1);
/* Register valid pins as interrupt sources. */
intr_register_pic(&io->io_pic);
for (i = 0, pin = io->io_pins; i < io->io_numintr; i++, pin++)
if (pin->io_irq < NUM_IO_INTS)
intr_register_source(&pin->io_intsrc);

View File

@ -151,12 +151,15 @@ volatile lapic_t *lapic;
static u_long lapic_timer_divisor, lapic_timer_period, lapic_timer_hz;
static void lapic_enable(void);
static void lapic_resume(struct pic *pic);
static void lapic_timer_enable_intr(void);
static void lapic_timer_oneshot(u_int count);
static void lapic_timer_periodic(u_int count);
static void lapic_timer_set_divisor(u_int divisor);
static uint32_t lvt_mode(struct lapic *la, u_int pin, uint32_t value);
struct pic lapic_pic = { .pic_resume = lapic_resume };
static uint32_t
lvt_mode(struct lapic *la, u_int pin, uint32_t value)
{
@ -277,7 +280,7 @@ lapic_dump(const char* str)
}
void
lapic_setup(void)
lapic_setup(int boot)
{
struct lapic *la;
u_int32_t maxlvt;
@ -306,9 +309,13 @@ lapic_setup(void)
/* Program timer LVT and setup handler. */
lapic->lvt_timer = lvt_mode(la, LVT_TIMER, lapic->lvt_timer);
snprintf(buf, sizeof(buf), "cpu%d: timer", PCPU_GET(cpuid));
intrcnt_add(buf, &la->la_timer_count);
if (PCPU_GET(cpuid) != 0) {
if (boot) {
snprintf(buf, sizeof(buf), "cpu%d: timer", PCPU_GET(cpuid));
intrcnt_add(buf, &la->la_timer_count);
}
/* We don't setup the timer during boot on the BSP until later. */
if (!(boot && PCPU_GET(cpuid) == 0)) {
KASSERT(lapic_timer_period != 0, ("lapic%u: zero divisor",
lapic_id()));
lapic_timer_set_divisor(lapic_timer_divisor);
@ -398,6 +405,14 @@ lapic_enable(void)
lapic->svr = value;
}
/* Reset the local APIC on the BSP during resume. */
static void
lapic_resume(struct pic *pic)
{
lapic_setup(0);
}
int
lapic_id(void)
{
@ -983,7 +998,8 @@ apic_setup_io(void *dummy __unused)
* Finish setting up the local APIC on the BSP once we know how to
* properly program the LINT pins.
*/
lapic_setup();
lapic_setup(1);
intr_register_pic(&lapic_pic);
if (bootverbose)
lapic_dump("BSP");
}

View File

@ -1212,19 +1212,7 @@ hammer_time(u_int64_t modulep, u_int64_t physfree)
atpic_startup();
#else
/* Reset and mask the atpics and leave them shut down. */
outb(IO_ICU1, ICW1_RESET | ICW1_IC4);
outb(IO_ICU1 + ICU_IMR_OFFSET, IDT_IO_INTS);
outb(IO_ICU1 + ICU_IMR_OFFSET, 1 << 2);
outb(IO_ICU1 + ICU_IMR_OFFSET, ICW4_8086);
outb(IO_ICU1 + ICU_IMR_OFFSET, 0xff);
outb(IO_ICU1, OCW3_SEL | OCW3_RR);
outb(IO_ICU2, ICW1_RESET | ICW1_IC4);
outb(IO_ICU2 + ICU_IMR_OFFSET, IDT_IO_INTS + 8);
outb(IO_ICU2 + ICU_IMR_OFFSET, 2);
outb(IO_ICU2 + ICU_IMR_OFFSET, ICW4_8086);
outb(IO_ICU2 + ICU_IMR_OFFSET, 0xff);
outb(IO_ICU2, OCW3_SEL | OCW3_RR);
atpic_reset();
/*
* Point the ICU spurious interrupt vectors at the APIC spurious

View File

@ -543,7 +543,7 @@ init_secondary(void)
mtx_lock_spin(&ap_boot_mtx);
/* Init local apic for irq's */
lapic_setup();
lapic_setup(1);
/* Set memory range attributes for this CPU to match the BSP */
mem_range_AP_init();

View File

@ -211,7 +211,7 @@ int lapic_set_lvt_polarity(u_int apic_id, u_int lvt,
int lapic_set_lvt_triggermode(u_int apic_id, u_int lvt,
enum intr_trigger trigger);
void lapic_set_tpr(u_int vector);
void lapic_setup(void);
void lapic_setup(int boot);
int lapic_setup_clock(void);
#endif /* !LOCORE */

View File

@ -81,11 +81,12 @@ struct pic {
void (*pic_enable_intr)(struct intsrc *);
int (*pic_vector)(struct intsrc *);
int (*pic_source_pending)(struct intsrc *);
void (*pic_suspend)(struct intsrc *);
void (*pic_resume)(struct intsrc *);
void (*pic_suspend)(struct pic *);
void (*pic_resume)(struct pic *);
int (*pic_config_intr)(struct intsrc *, enum intr_trigger,
enum intr_polarity);
void (*pic_assign_cpu)(struct intsrc *, u_int apic_id);
STAILQ_ENTRY(pic) pics;
};
/* Flags for pic_disable_source() */
@ -114,6 +115,9 @@ struct trapframe;
extern struct mtx icu_lock;
extern int elcr_found;
#ifndef DEV_ATPIC
void atpic_reset(void);
#endif
/* XXX: The elcr_* prototypes probably belong somewhere else. */
int elcr_probe(void);
enum intr_trigger elcr_read_trigger(u_int irq);
@ -130,6 +134,7 @@ int intr_config_intr(int vector, enum intr_trigger trig,
enum intr_polarity pol);
void intr_execute_handlers(struct intsrc *isrc, struct trapframe *frame);
struct intsrc *intr_lookup_source(int vector);
int intr_register_pic(struct pic *pic);
int intr_register_source(struct intsrc *isrc);
int intr_remove_handler(void *cookie);
void intr_resume(void);

View File

@ -138,7 +138,7 @@ static void atpic_eoi_master(struct intsrc *isrc);
static void atpic_eoi_slave(struct intsrc *isrc);
static void atpic_enable_intr(struct intsrc *isrc);
static int atpic_vector(struct intsrc *isrc);
static void atpic_resume(struct intsrc *isrc);
static void atpic_resume(struct pic *pic);
static int atpic_source_pending(struct intsrc *isrc);
static int atpic_config_intr(struct intsrc *isrc, enum intr_trigger trig,
enum intr_polarity pol);
@ -285,16 +285,13 @@ atpic_source_pending(struct intsrc *isrc)
}
static void
atpic_resume(struct intsrc *isrc)
atpic_resume(struct pic *pic)
{
struct atpic_intsrc *ai = (struct atpic_intsrc *)isrc;
struct atpic *ap = (struct atpic *)isrc->is_pic;
struct atpic *ap = (struct atpic *)pic;
if (ai->at_irq == 0) {
i8259_init(ap, ap == &atpics[SLAVE]);
if (ap == &atpics[SLAVE] && elcr_found)
elcr_resume();
}
i8259_init(ap, ap == &atpics[SLAVE]);
if (ap == &atpics[SLAVE] && elcr_found)
elcr_resume();
}
static int
@ -464,6 +461,14 @@ atpic_init(void *dummy __unused)
struct atpic_intsrc *ai;
int i;
/*
* Register our PICs, even if we aren't going to use any of their
* pins so that they are suspended and resumed.
*/
if (intr_register_pic(&atpics[0].at_pic) != 0 ||
intr_register_pic(&atpics[1].at_pic) != 0)
panic("Unable to register ATPICs");
/*
* If any of the ISA IRQs have an interrupt source already, then
* assume that the APICs are being used and don't register any

View File

@ -62,6 +62,7 @@ typedef void (*mask_fn)(void *);
static int intrcnt_index;
static struct intsrc *interrupt_sources[NUM_IO_INTS];
static struct mtx intr_table_lock;
static STAILQ_HEAD(, pic) pics;
#ifdef SMP
static int assign_cpu;
@ -70,10 +71,45 @@ static void intr_assign_next_cpu(struct intsrc *isrc);
#endif
static void intr_init(void *__dummy);
static int intr_pic_registered(struct pic *pic);
static void intrcnt_setname(const char *name, int index);
static void intrcnt_updatename(struct intsrc *is);
static void intrcnt_register(struct intsrc *is);
static int
intr_pic_registered(struct pic *pic)
{
struct pic *p;
STAILQ_FOREACH(p, &pics, pics) {
if (p == pic)
return (1);
}
return (0);
}
/*
* Register a new interrupt controller (PIC). This is to support suspend
* and resume where we suspend/resume controllers rather than individual
* sources. This also allows controllers with no active sources (such as
* 8259As in a system using the APICs) to participate in suspend and resume.
*/
int
intr_register_pic(struct pic *pic)
{
int error;
mtx_lock_spin(&intr_table_lock);
if (intr_pic_registered(pic))
error = EBUSY;
else {
STAILQ_INSERT_TAIL(&pics, pic, pics);
error = 0;
}
mtx_unlock_spin(&intr_table_lock);
return (error);
}
/*
* Register a new interrupt source with the global interrupt system.
* The global interrupts need to be disabled when this function is
@ -84,6 +120,7 @@ intr_register_source(struct intsrc *isrc)
{
int error, vector;
KASSERT(intr_pic_registered(isrc->is_pic), ("unregistered PIC"));
vector = isrc->is_pic->pic_vector(isrc);
if (interrupt_sources[vector] != NULL)
return (EEXIST);
@ -255,26 +292,26 @@ intr_execute_handlers(struct intsrc *isrc, struct trapframe *frame)
void
intr_resume(void)
{
struct intsrc **isrc;
int i;
struct pic *pic;
mtx_lock_spin(&intr_table_lock);
for (i = 0, isrc = interrupt_sources; i < NUM_IO_INTS; i++, isrc++)
if (*isrc != NULL && (*isrc)->is_pic->pic_resume != NULL)
(*isrc)->is_pic->pic_resume(*isrc);
STAILQ_FOREACH(pic, &pics, pics) {
if (pic->pic_resume != NULL)
pic->pic_resume(pic);
}
mtx_unlock_spin(&intr_table_lock);
}
void
intr_suspend(void)
{
struct intsrc **isrc;
int i;
struct pic *pic;
mtx_lock_spin(&intr_table_lock);
for (i = 0, isrc = interrupt_sources; i < NUM_IO_INTS; i++, isrc++)
if (*isrc != NULL && (*isrc)->is_pic->pic_suspend != NULL)
(*isrc)->is_pic->pic_suspend(*isrc);
STAILQ_FOREACH(pic, &pics, pics) {
if (pic->pic_suspend != NULL)
pic->pic_suspend(pic);
}
mtx_unlock_spin(&intr_table_lock);
}
@ -327,6 +364,7 @@ intr_init(void *dummy __unused)
intrcnt_setname("???", 0);
intrcnt_index = 1;
STAILQ_INIT(&pics);
mtx_init(&intr_table_lock, "intr table", NULL, MTX_SPIN);
}
SYSINIT(intr_init, SI_SUB_INTR, SI_ORDER_FIRST, intr_init, NULL)

View File

@ -60,8 +60,6 @@ __FBSDID("$FreeBSD$");
#define IRQ_SMI (NUM_IO_INTS + 3)
#define IRQ_DISABLED (NUM_IO_INTS + 4)
#define TODO printf("%s: not implemented!\n", __func__)
static MALLOC_DEFINE(M_IOAPIC, "io_apic", "I/O APIC structures");
/*
@ -114,8 +112,7 @@ static int ioapic_vector(struct intsrc *isrc);
static int ioapic_source_pending(struct intsrc *isrc);
static int ioapic_config_intr(struct intsrc *isrc, enum intr_trigger trig,
enum intr_polarity pol);
static void ioapic_suspend(struct intsrc *isrc);
static void ioapic_resume(struct intsrc *isrc);
static void ioapic_resume(struct pic *pic);
static void ioapic_assign_cpu(struct intsrc *isrc, u_int apic_id);
static void ioapic_program_intpin(struct ioapic_intsrc *intpin);
@ -123,7 +120,7 @@ static STAILQ_HEAD(,ioapic) ioapic_list = STAILQ_HEAD_INITIALIZER(ioapic_list);
struct pic ioapic_template = { ioapic_enable_source, ioapic_disable_source,
ioapic_eoi_source, ioapic_enable_intr,
ioapic_vector, ioapic_source_pending,
ioapic_suspend, ioapic_resume,
NULL, ioapic_resume,
ioapic_config_intr, ioapic_assign_cpu };
static int next_ioapic_base;
@ -418,17 +415,13 @@ ioapic_config_intr(struct intsrc *isrc, enum intr_trigger trig,
}
static void
ioapic_suspend(struct intsrc *isrc)
ioapic_resume(struct pic *pic)
{
struct ioapic *io = (struct ioapic *)pic;
int i;
TODO;
}
static void
ioapic_resume(struct intsrc *isrc)
{
ioapic_program_intpin((struct ioapic_intsrc *)isrc);
for (i = 0; i < io->io_numintr; i++)
ioapic_program_intpin(&io->io_pins[i]);
}
/*
@ -726,6 +719,7 @@ ioapic_register(void *cookie)
io->io_intbase + io->io_numintr - 1);
/* Register valid pins as interrupt sources. */
intr_register_pic(&io->io_pic);
for (i = 0, pin = io->io_pins; i < io->io_numintr; i++, pin++)
if (pin->io_irq < NUM_IO_INTS)
intr_register_source(&pin->io_intsrc);

View File

@ -151,12 +151,15 @@ volatile lapic_t *lapic;
static u_long lapic_timer_divisor, lapic_timer_period, lapic_timer_hz;
static void lapic_enable(void);
static void lapic_resume(struct pic *pic);
static void lapic_timer_enable_intr(void);
static void lapic_timer_oneshot(u_int count);
static void lapic_timer_periodic(u_int count);
static void lapic_timer_set_divisor(u_int divisor);
static uint32_t lvt_mode(struct lapic *la, u_int pin, uint32_t value);
struct pic lapic_pic = { .pic_resume = lapic_resume };
static uint32_t
lvt_mode(struct lapic *la, u_int pin, uint32_t value)
{
@ -279,7 +282,7 @@ lapic_dump(const char* str)
}
void
lapic_setup(void)
lapic_setup(int boot)
{
struct lapic *la;
u_int32_t maxlvt;
@ -308,9 +311,13 @@ lapic_setup(void)
/* Program timer LVT and setup handler. */
lapic->lvt_timer = lvt_mode(la, LVT_TIMER, lapic->lvt_timer);
snprintf(buf, sizeof(buf), "cpu%d: timer", PCPU_GET(cpuid));
intrcnt_add(buf, &la->la_timer_count);
if (PCPU_GET(cpuid) != 0) {
if (boot) {
snprintf(buf, sizeof(buf), "cpu%d: timer", PCPU_GET(cpuid));
intrcnt_add(buf, &la->la_timer_count);
}
/* We don't setup the timer during boot on the BSP until later. */
if (!(boot && PCPU_GET(cpuid) == 0)) {
KASSERT(lapic_timer_period != 0, ("lapic%u: zero divisor",
lapic_id()));
lapic_timer_set_divisor(lapic_timer_divisor);
@ -400,6 +407,14 @@ lapic_enable(void)
lapic->svr = value;
}
/* Reset the local APIC on the BSP during resume. */
static void
lapic_resume(struct pic *pic)
{
lapic_setup(0);
}
int
lapic_id(void)
{
@ -986,7 +1001,8 @@ apic_setup_io(void *dummy __unused)
* Finish setting up the local APIC on the BSP once we know how to
* properly program the LINT pins.
*/
lapic_setup();
lapic_setup(1);
intr_register_pic(&lapic_pic);
if (bootverbose)
lapic_dump("BSP");
}

View File

@ -594,7 +594,7 @@ init_secondary(void)
mtx_lock_spin(&ap_boot_mtx);
/* Init local apic for irq's */
lapic_setup();
lapic_setup(1);
/* Set memory range attributes for this CPU to match the BSP */
mem_range_AP_init();

View File

@ -210,7 +210,7 @@ int lapic_set_lvt_polarity(u_int apic_id, u_int lvt,
int lapic_set_lvt_triggermode(u_int apic_id, u_int lvt,
enum intr_trigger trigger);
void lapic_set_tpr(u_int vector);
void lapic_setup(void);
void lapic_setup(int boot);
int lapic_setup_clock(void);
#endif /* !LOCORE */

View File

@ -81,11 +81,12 @@ struct pic {
void (*pic_enable_intr)(struct intsrc *);
int (*pic_vector)(struct intsrc *);
int (*pic_source_pending)(struct intsrc *);
void (*pic_suspend)(struct intsrc *);
void (*pic_resume)(struct intsrc *);
void (*pic_suspend)(struct pic *);
void (*pic_resume)(struct pic *);
int (*pic_config_intr)(struct intsrc *, enum intr_trigger,
enum intr_polarity);
void (*pic_assign_cpu)(struct intsrc *, u_int apic_id);
STAILQ_ENTRY(pic) pics;
};
/* Flags for pic_disable_source() */
@ -130,6 +131,7 @@ int intr_config_intr(int vector, enum intr_trigger trig,
enum intr_polarity pol);
void intr_execute_handlers(struct intsrc *isrc, struct trapframe *frame);
struct intsrc *intr_lookup_source(int vector);
int intr_register_pic(struct pic *pic);
int intr_register_source(struct intsrc *isrc);
int intr_remove_handler(void *cookie);
void intr_resume(void);

View File

@ -156,7 +156,7 @@ static void atpic_eoi_master(struct intsrc *isrc);
static void atpic_eoi_slave(struct intsrc *isrc);
static void atpic_enable_intr(struct intsrc *isrc);
static int atpic_vector(struct intsrc *isrc);
static void atpic_resume(struct intsrc *isrc);
static void atpic_resume(struct pic *pic);
static int atpic_source_pending(struct intsrc *isrc);
static int atpic_config_intr(struct intsrc *isrc, enum intr_trigger trig,
enum intr_polarity pol);
@ -303,18 +303,15 @@ atpic_source_pending(struct intsrc *isrc)
}
static void
atpic_resume(struct intsrc *isrc)
atpic_resume(struct pic *pic)
{
struct atpic_intsrc *ai = (struct atpic_intsrc *)isrc;
struct atpic *ap = (struct atpic *)isrc->is_pic;
struct atpic *ap = (struct atpic *)pic;
if (ai->at_irq == 0) {
i8259_init(ap, ap == &atpics[SLAVE]);
i8259_init(ap, ap == &atpics[SLAVE]);
#ifndef PC98
if (ap == &atpics[SLAVE] && elcr_found)
elcr_resume();
if (ap == &atpics[SLAVE] && elcr_found)
elcr_resume();
#endif
}
}
static int
@ -528,6 +525,14 @@ atpic_init(void *dummy __unused)
struct atpic_intsrc *ai;
int i;
/*
* Register our PICs, even if we aren't going to use any of their
* pins so that they are suspended and resumed.
*/
if (intr_register_pic(&atpics[0].at_pic) != 0 ||
intr_register_pic(&atpics[1].at_pic) != 0)
panic("Unable to register ATPICs");
/*
* If any of the ISA IRQs have an interrupt source already, then
* assume that the APICs are being used and don't register any