Wire up most of the interrupt handling infrastructure. Not sure it works

right yet but its enough for the ATA probe to work. The SCSI probes which
follow are broken though.
This commit is contained in:
Doug Rabson 2001-10-05 10:30:09 +00:00
parent ae0d75fe5f
commit 7a7029581c
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=84541
6 changed files with 342 additions and 40 deletions

View File

@ -94,41 +94,46 @@ typedef struct /* PLATFORM INTERRUPT SOURCE */
static void
parse_interrupt_override(INTERRUPT_SOURCE_OVERRIDE *override)
{
printf("\t\tBus=%d, Source=%d, Irq=0x%x\n",
override->Bus,
override->Source,
override->GlobalSystemInterrupt);
if (bootverbose)
printf("\t\tBus=%d, Source=%d, Irq=0x%x\n",
override->Bus,
override->Source,
override->GlobalSystemInterrupt);
}
static void
parse_io_sapic(IO_SAPIC *sapic)
{
printf("\t\tId=0x%x, Vector=0x%x, Address=0x%lx\n",
sapic->IoSapicId,
sapic->Vector,
sapic->IoSapicAddress);
if (bootverbose)
printf("\t\tId=0x%x, Vector=0x%x, Address=0x%lx\n",
sapic->IoSapicId,
sapic->Vector,
sapic->IoSapicAddress);
sapic_create(sapic->IoSapicId, sapic->Vector, sapic->IoSapicAddress);
}
static void
parse_local_sapic(LOCAL_SAPIC *sapic)
{
printf("\t\tProcessorId=0x%x, Id=0x%x, Eid=0x%x\n",
sapic->ProcessorId,
sapic->LocalSapicId,
sapic->LocalSapicEid);
if (bootverbose)
printf("\t\tProcessorId=0x%x, Id=0x%x, Eid=0x%x\n",
sapic->ProcessorId,
sapic->LocalSapicId,
sapic->LocalSapicEid);
}
static void
parse_platform_interrupt(PLATFORM_INTERRUPT_SOURCE *source)
{
printf("\t\tPolarity=%d, TriggerMode=%d, Id=0x%x, "
"Eid=0x%x, Vector=0x%x, Irq=%d\n",
source->Polarity,
source->TriggerMode,
source->ProcessorId,
source->ProcessorEid,
source->IoSapicVector,
source->GlobalSystemInterrupt);
if (bootverbose)
printf("\t\tPolarity=%d, TriggerMode=%d, Id=0x%x, "
"Eid=0x%x, Vector=0x%x, Irq=%d\n",
source->Polarity,
source->TriggerMode,
source->ProcessorId,
source->ProcessorEid,
source->IoSapicVector,
source->GlobalSystemInterrupt);
}
static void
@ -144,7 +149,8 @@ parse_madt(APIC_TABLE *madt)
for (p = (char *) (madt + 1); p < end; ) {
APIC_HEADER *head = (APIC_HEADER *) p;
printf("\t");
if (bootverbose)
printf("\t");
switch (head->Type) {
case APIC_PROC:
if (bootverbose)

View File

@ -41,6 +41,7 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/proc.h>
#include <sys/vmmeter.h>
#include <sys/bus.h>
@ -53,6 +54,7 @@
#include <machine/reg.h>
#include <machine/frame.h>
#include <machine/intr.h>
#include <machine/sapicvar.h>
#ifdef EVCNT_COUNTERS
struct evcnt clock_intr_evcnt; /* event counter for clock intrs. */
@ -82,12 +84,23 @@ void
interrupt(u_int64_t vector, struct trapframe *framep)
{
struct thread *td;
volatile struct ia64_interrupt_block *ib = IA64_INTERRUPT_BLOCK;
td = curthread;
atomic_add_int(&td->td_intr_nesting_level, 1);
switch (vector) {
case 240: /* clock interrupt */
CTR0(KTR_INTR, "clock interrupt");
/*
* Handle ExtINT interrupts by generating an INTA cycle to
* read the vector.
*/
if (vector == 0) {
vector = ib->ib_inta;
printf("ExtINT interrupt: vector=%ld\n", vector);
goto out; /* XXX */
}
if (vector == 240) {/* clock interrupt */
/* CTR0(KTR_INTR, "clock interrupt"); */
cnt.v_intr++;
#ifdef EVCNT_COUNTERS
@ -100,17 +113,14 @@ interrupt(u_int64_t vector, struct trapframe *framep)
/* divide hz (1024) by 8 to get stathz (128) */
if((++schedclk2 & 0x7) == 0)
statclock((struct clockframe *)framep);
break;
default:
mtx_lock(&Giant);
panic("unexpected interrupt: vec %ld\n", vector);
/* NOTREACHED */
} else {
ia64_dispatch_intr(framep, vector);
}
out:
atomic_subtract_int(&td->td_intr_nesting_level, 1);
}
int
badaddr(addr, size)
void *addr;
@ -127,3 +137,165 @@ badaddr_read(addr, size, rptr)
{
return (1); /* XXX implement */
}
/*
* Hardware irqs have vectors starting at this offset.
*/
#define IA64_HARDWARE_IRQ_BASE 0x20
struct ia64_intr {
struct ithd *ithd; /* interrupt thread */
volatile long *cntp; /* interrupt counter */
};
static struct sapic *ia64_sapics[16]; /* XXX make this resizable */
static int ia64_sapic_count;
static struct mtx ia64_intrs_lock;
static struct ia64_intr *ia64_intrs[256];
static void ithds_init(void *dummy);
static void
ithds_init(void *dummy)
{
mtx_init(&ia64_intrs_lock, "ithread table lock", MTX_SPIN);
}
SYSINIT(ithds_init, SI_SUB_INTR, SI_ORDER_SECOND, ithds_init, NULL);
void
ia64_add_sapic(struct sapic *sa)
{
ia64_sapics[ia64_sapic_count++] = sa;
}
static void
ia64_enable(int vector)
{
int irq, i;
irq = vector - IA64_HARDWARE_IRQ_BASE;
for (i = 0; i < ia64_sapic_count; i++) {
struct sapic *sa = ia64_sapics[i];
if (irq >= sa->sa_base && irq <= sa->sa_limit)
sapic_enable(sa, irq - sa->sa_base, vector,
(irq < 16
? SAPIC_TRIGGER_EDGE
: SAPIC_TRIGGER_LEVEL),
(irq < 16
? SAPIC_POLARITY_HIGH
: SAPIC_POLARITY_LOW));
}
}
static void
ia64_send_eoi(int vector)
{
int irq, i;
irq = vector - IA64_HARDWARE_IRQ_BASE;
for (i = 0; i < ia64_sapic_count; i++) {
struct sapic *sa = ia64_sapics[i];
if (irq >= sa->sa_base && irq <= sa->sa_limit)
sapic_eoi(sa, vector);
}
}
int
ia64_setup_intr(const char *name, int irq, driver_intr_t handler, void *arg,
enum intr_type flags, void **cookiep, volatile long *cntp)
{
struct ia64_intr *i;
int errcode;
int vector = irq + IA64_HARDWARE_IRQ_BASE;
/*
* XXX - Can we have more than one device on a vector? If so, we have
* a race condition here that needs to be worked around similar to
* the fashion done in the i386 inthand_add() function.
*/
/* First, check for an existing hash table entry for this vector. */
mtx_lock_spin(&ia64_intrs_lock);
i = ia64_intrs[vector];
mtx_unlock_spin(&ia64_intrs_lock);
if (i == NULL) {
/* None was found, so create an entry. */
i = malloc(sizeof(struct ia64_intr), M_DEVBUF, M_NOWAIT);
if (i == NULL)
return ENOMEM;
i->cntp = cntp;
errcode = ithread_create(&i->ithd, vector, 0, 0,
ia64_send_eoi, "intr:");
if (errcode) {
free(i, M_DEVBUF);
return errcode;
}
mtx_lock_spin(&ia64_intrs_lock);
ia64_intrs[vector] = i;
mtx_unlock_spin(&ia64_intrs_lock);
}
/* Second, add this handler. */
errcode = ithread_add_handler(i->ithd, name, handler, arg,
ithread_priority(flags), flags, cookiep);
if (errcode)
return errcode;
ia64_enable(vector);
return 0;
}
int
ia64_teardown_intr(void *cookie)
{
return (ithread_remove_handler(cookie));
}
void
ia64_dispatch_intr(void *frame, unsigned long vector)
{
struct ia64_intr *i;
struct ithd *ithd; /* our interrupt thread */
struct intrhand *ih;
int error;
/*
* Find the interrupt thread for this vector.
*/
i = ia64_intrs[vector];
if (i == NULL)
return; /* no ithread for this vector */
ithd = i->ithd;
KASSERT(ithd != NULL, ("interrupt vector without a thread"));
/*
* As an optomization, if an ithread has no handlers, don't
* schedule it to run.
*/
if (TAILQ_EMPTY(&ithd->it_handlers))
return;
if (i->cntp)
atomic_add_long(i->cntp, 1);
/*
* Handle a fast interrupt if there is no actual thread for this
* interrupt by calling the handler directly without Giant. Note
* that this means that any fast interrupt handler must be MP safe.
*/
ih = TAILQ_FIRST(&ithd->it_handlers);
if ((ih->ih_flags & IH_FAST) != 0) {
ih->ih_handler(ih->ih_argument);
ia64_send_eoi(vector);
return;
}
error = ithread_schedule(ithd, 0); /* XXX:no preemption for now */
KASSERT(error == 0, ("got an impossible stray interrupt"));
}

View File

@ -59,6 +59,7 @@
#include <machine/resource.h>
#include <isa/isavar.h>
#include <isa/isareg.h>
#include <sys/rtprio.h>
static MALLOC_DEFINE(M_NEXUSDEV, "nexusdev", "Nexus device");
@ -163,7 +164,7 @@ nexus_probe(device_t dev)
irq_rman.rm_start = 0;
irq_rman.rm_type = RMAN_ARRAY;
irq_rman.rm_descr = "Interrupt request lines";
irq_rman.rm_end = 15;
irq_rman.rm_end = 63;
if (rman_init(&irq_rman)
|| rman_manage_region(&irq_rman,
irq_rman.rm_start, irq_rman.rm_end))
@ -211,6 +212,12 @@ nexus_probe(device_t dev)
static int
nexus_attach(device_t dev)
{
/*
* Mask the legacy PICs - we will use the I/O SAPIC for interrupt.
*/
outb(IO_ICU1+1, 0xff);
outb(IO_ICU2+1, 0xff);
bus_generic_attach(dev);
return 0;
}
@ -472,10 +479,8 @@ nexus_setup_intr(device_t bus, device_t child, struct resource *irq,
if (error)
return (error);
#if 0
error = inthand_add(device_get_nameunit(child), irq->r_start,
ihand, arg, flags, cookiep);
#endif
error = ia64_setup_intr(device_get_nameunit(child), irq->r_start,
ihand, arg, flags, cookiep, 0);
return (error);
}

View File

@ -29,9 +29,30 @@
#ifndef _MACHINE_INTR_H_
#define _MACHINE_INTR_H_
int alpha_setup_intr(int vector, driver_intr_t *intr, void *arg,
void **cookiep, volatile long *cntp);
int alpha_teardown_intr(void *cookie);
void alpha_dispatch_intr(void *frame, unsigned long vector);
/*
* Layout of the Processor Interrupt Block.
*/
struct ia64_interrupt_block
{
u_int64_t ib_ipi[0x20000]; /* 1Mb of IPI interrupts */
u_int8_t ib_reserved1[0xe0000];
u_int8_t ib_inta; /* Generate INTA cycle */
u_int8_t ib_reserved2[7];
u_int8_t ib_xtp; /* XTP cycle */
u_int8_t ib_reserved3[7];
u_int8_t ib_reserved4[0x1fff0];
};
#define IA64_INTERRUPT_BLOCK \
(struct ia64_interrupt_block *)IA64_PHYS_TO_RR6(0xfee00000)
struct sapic;
void ia64_add_sapic(struct sapic *sa);
int ia64_setup_intr(const char *name, int irq, driver_intr_t handler,
void *arg, enum intr_type flags, void **cookiep,
volatile long *cntp);
int ia64_teardown_intr(void *cookie);
void ia64_dispatch_intr(void *frame, unsigned long vector);
#endif /* !_MACHINE_INTR_H_ */

View File

@ -0,0 +1,48 @@
/*-
* Copyright (c) 2001 Doug Rabson
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _MACHINE_SAPICREG_H_
#define _MACHINE_SAPICREG_H_
/*
* Offsets from the SAPIC base in memory. Most registers are accessed
* by indexing using the SAPIC_IO_SELECT register.
*/
#define SAPIC_IO_SELECT 0x00
#define SAPIC_IO_WINDOW 0x10
#define SAPIC_APIC_EOI 0x40
/*
* Indexed registers.
*/
#define SAPIC_ID 0x00
#define SAPIC_VERSION 0x01
#define SAPIC_ARBITRATION_ID 0x02
#define SAPIC_RTE_BASE 0x10
#endif /* ! _MACHINE_SAPICREG_H_ */

View File

@ -0,0 +1,50 @@
/*-
* Copyright (c) 2001 Doug Rabson
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _MACHINE_SAPICVAR_H_
#define _MACHINE_SAPICVAR_H_
struct sapic {
int sa_id; /* I/O SAPIC Id */
int sa_base; /* ACPI vector base */
int sa_limit; /* last ACPI vector handled here */
vm_offset_t sa_registers; /* virtual address of sapic */
};
#define SAPIC_TRIGGER_EDGE 0
#define SAPIC_TRIGGER_LEVEL 1
#define SAPIC_POLARITY_HIGH 0
#define SAPIC_POLARITY_LOW 1
struct sapic *sapic_create(int id, int base, u_int64_t address);
void sapic_enable(struct sapic *sa, int input, int vector,
int trigger_mode, int polarity);
void sapic_eoi(struct sapic *sa, int vector);
#endif /* ! _MACHINE_SAPICVAR_H_ */