mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-17 10:26:15 +00:00
MFi386: apic intpin programming updates etc.
This commit is contained in:
parent
bfe14b3edc
commit
ea10166e8a
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=130035
@ -67,8 +67,8 @@ struct ioapic_info {
|
||||
struct lapic_info {
|
||||
u_int la_present:1;
|
||||
u_int la_enabled:1;
|
||||
u_int la_apic_id:8;
|
||||
} lapics[NLAPICS + 1];
|
||||
u_int la_acpi_id:8;
|
||||
} lapics[NLAPICS];
|
||||
|
||||
static int madt_found_sci_override;
|
||||
static MULTIPLE_APIC_TABLE *madt;
|
||||
@ -447,14 +447,14 @@ madt_probe_cpus_handler(APIC_HEADER *entry, void *arg)
|
||||
printf("MADT: Found CPU APIC ID %d ACPI ID %d: %s\n",
|
||||
proc->LocalApicId, proc->ProcessorId,
|
||||
proc->ProcessorEnabled ? "enabled" : "disabled");
|
||||
if (proc->ProcessorId > NLAPICS)
|
||||
if (proc->LocalApicId >= NLAPICS)
|
||||
panic("%s: CPU ID %d too high", __func__,
|
||||
proc->ProcessorId);
|
||||
la = &lapics[proc->ProcessorId];
|
||||
proc->LocalApicId);
|
||||
la = &lapics[proc->LocalApicId];
|
||||
KASSERT(la->la_present == 0,
|
||||
("Duplicate local ACPI ID %d", proc->ProcessorId));
|
||||
("Duplicate local APIC ID %d", proc->LocalApicId));
|
||||
la->la_present = 1;
|
||||
la->la_apic_id = proc->LocalApicId;
|
||||
la->la_acpi_id = proc->ProcessorId;
|
||||
if (proc->ProcessorEnabled) {
|
||||
la->la_enabled = 1;
|
||||
lapic_create(proc->LocalApicId, 0);
|
||||
@ -545,14 +545,20 @@ interrupt_trigger(UINT16 TriggerMode, UINT8 Source)
|
||||
static int
|
||||
madt_find_cpu(u_int acpi_id, u_int *apic_id)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!lapics[acpi_id].la_present)
|
||||
return (ENOENT);
|
||||
*apic_id = lapics[acpi_id].la_apic_id;
|
||||
if (lapics[acpi_id].la_enabled)
|
||||
return (0);
|
||||
else
|
||||
return (ENXIO);
|
||||
for (i = 0; i < NLAPICS; i++) {
|
||||
if (!lapics[i].la_present)
|
||||
continue;
|
||||
if (lapics[i].la_acpi_id != acpi_id)
|
||||
continue;
|
||||
*apic_id = i;
|
||||
if (lapics[i].la_enabled)
|
||||
return (0);
|
||||
else
|
||||
return (ENXIO);
|
||||
}
|
||||
return (ENOENT);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -752,8 +758,9 @@ madt_parse_ints(APIC_HEADER *entry, void *arg __unused)
|
||||
static void
|
||||
madt_set_ids(void *dummy)
|
||||
{
|
||||
struct lapic_info *la;
|
||||
struct pcpu *pc;
|
||||
u_int i, j;
|
||||
u_int i;
|
||||
|
||||
if (madt == NULL)
|
||||
return;
|
||||
@ -762,19 +769,14 @@ madt_set_ids(void *dummy)
|
||||
continue;
|
||||
pc = pcpu_find(i);
|
||||
KASSERT(pc != NULL, ("no pcpu data for CPU %d", i));
|
||||
for (j = 0; j < NLAPICS + 1; j++) {
|
||||
if (!lapics[j].la_present || !lapics[j].la_enabled)
|
||||
continue;
|
||||
if (lapics[j].la_apic_id == pc->pc_apic_id) {
|
||||
pc->pc_acpi_id = j;
|
||||
if (bootverbose)
|
||||
printf("APIC: CPU %u has ACPI ID %u\n",
|
||||
i, j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (j == NLAPICS + 1)
|
||||
panic("Unable to find ACPI ID for CPU %d", i);
|
||||
la = &lapics[pc->pc_apic_id];
|
||||
if (!la->la_present || !la->la_enabled)
|
||||
panic("APIC: CPU with APIC ID %u is not enabled",
|
||||
pc->pc_apic_id);
|
||||
pc->pc_acpi_id = la->la_acpi_id;
|
||||
if (bootverbose)
|
||||
printf("APIC: CPU %u has ACPI ID %u\n", i,
|
||||
la->la_acpi_id);
|
||||
}
|
||||
}
|
||||
SYSINIT(madt_set_ids, SI_SUB_CPU, SI_ORDER_ANY, madt_set_ids, NULL)
|
||||
|
@ -126,6 +126,7 @@ static int ioapic_config_intr(struct intsrc *isrc, enum intr_trigger trig,
|
||||
static void ioapic_suspend(struct intsrc *isrc);
|
||||
static void ioapic_resume(struct intsrc *isrc);
|
||||
static void ioapic_program_destination(struct ioapic_intsrc *intpin);
|
||||
static void ioapic_program_intpin(struct ioapic_intsrc *intpin);
|
||||
static void ioapic_setup_mixed_mode(struct ioapic_intsrc *intpin);
|
||||
|
||||
static STAILQ_HEAD(,ioapic) ioapic_list = STAILQ_HEAD_INITIALIZER(ioapic_list);
|
||||
@ -135,7 +136,7 @@ struct pic ioapic_template = { ioapic_enable_source, ioapic_disable_source,
|
||||
ioapic_suspend, ioapic_resume,
|
||||
ioapic_config_intr };
|
||||
|
||||
static int current_cluster, logical_clusters, next_ioapic_base;
|
||||
static int bsp_id, current_cluster, logical_clusters, next_ioapic_base;
|
||||
static u_int mixed_mode_enabled, next_id, program_logical_dest;
|
||||
#if defined(NO_MIXED_MODE) || !defined(DEV_ATPIC)
|
||||
static int mixed_mode_active = 0;
|
||||
@ -207,6 +208,82 @@ ioapic_eoi_source(struct intsrc *isrc)
|
||||
lapic_eoi();
|
||||
}
|
||||
|
||||
/*
|
||||
* Completely program an intpin based on the data in its interrupt source
|
||||
* structure.
|
||||
*/
|
||||
static void
|
||||
ioapic_program_intpin(struct ioapic_intsrc *intpin)
|
||||
{
|
||||
struct ioapic *io = (struct ioapic *)intpin->io_intsrc.is_pic;
|
||||
uint32_t low, high, value;
|
||||
|
||||
/*
|
||||
* For pins routed via mixed mode or disabled, just ensure that
|
||||
* they are masked.
|
||||
*/
|
||||
if (intpin->io_dest == DEST_EXTINT ||
|
||||
intpin->io_vector == VECTOR_DISABLED) {
|
||||
low = ioapic_read(io->io_addr,
|
||||
IOAPIC_REDTBL_LO(intpin->io_intpin));
|
||||
if ((low & IOART_INTMASK) == IOART_INTMCLR)
|
||||
ioapic_write(io->io_addr,
|
||||
IOAPIC_REDTBL_LO(intpin->io_intpin),
|
||||
low | IOART_INTMSET);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set the destination. */
|
||||
if (intpin->io_dest == DEST_NONE) {
|
||||
low = IOART_DESTPHY;
|
||||
high = bsp_id << APIC_ID_SHIFT;
|
||||
} else {
|
||||
low = IOART_DESTLOG;
|
||||
high = (intpin->io_dest << APIC_ID_CLUSTER_SHIFT |
|
||||
APIC_ID_CLUSTER_ID) << APIC_ID_SHIFT;
|
||||
}
|
||||
|
||||
/* Program the rest of the low word. */
|
||||
if (intpin->io_edgetrigger)
|
||||
low |= IOART_TRGREDG;
|
||||
else
|
||||
low |= IOART_TRGRLVL;
|
||||
if (intpin->io_activehi)
|
||||
low |= IOART_INTAHI;
|
||||
else
|
||||
low |= IOART_INTALO;
|
||||
if (intpin->io_masked)
|
||||
low |= IOART_INTMSET;
|
||||
switch (intpin->io_vector) {
|
||||
case VECTOR_EXTINT:
|
||||
KASSERT(intpin->io_edgetrigger,
|
||||
("EXTINT not edge triggered"));
|
||||
low |= IOART_DELEXINT;
|
||||
break;
|
||||
case VECTOR_NMI:
|
||||
KASSERT(intpin->io_edgetrigger,
|
||||
("NMI not edge triggered"));
|
||||
low |= IOART_DELNMI;
|
||||
break;
|
||||
case VECTOR_SMI:
|
||||
KASSERT(intpin->io_edgetrigger,
|
||||
("SMI not edge triggered"));
|
||||
low |= IOART_DELSMI;
|
||||
break;
|
||||
default:
|
||||
low |= IOART_DELLOPRI | apic_irq_to_idt(intpin->io_vector);
|
||||
}
|
||||
|
||||
/* Write the values to the APIC. */
|
||||
mtx_lock_spin(&icu_lock);
|
||||
ioapic_write(io->io_addr, IOAPIC_REDTBL_LO(intpin->io_intpin), low);
|
||||
value = ioapic_read(io->io_addr, IOAPIC_REDTBL_HI(intpin->io_intpin));
|
||||
value &= ~IOART_DEST;
|
||||
value |= high;
|
||||
ioapic_write(io->io_addr, IOAPIC_REDTBL_HI(intpin->io_intpin), value);
|
||||
mtx_unlock_spin(&icu_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Program an individual intpin's logical destination.
|
||||
*/
|
||||
@ -214,7 +291,6 @@ static void
|
||||
ioapic_program_destination(struct ioapic_intsrc *intpin)
|
||||
{
|
||||
struct ioapic *io = (struct ioapic *)intpin->io_intsrc.is_pic;
|
||||
uint32_t value;
|
||||
|
||||
KASSERT(intpin->io_dest != DEST_NONE,
|
||||
("intpin not assigned to a cluster"));
|
||||
@ -229,17 +305,7 @@ ioapic_program_destination(struct ioapic_intsrc *intpin)
|
||||
printf("IRQ %u", intpin->io_vector);
|
||||
printf(") to cluster %u\n", intpin->io_dest);
|
||||
}
|
||||
mtx_lock_spin(&icu_lock);
|
||||
value = ioapic_read(io->io_addr, IOAPIC_REDTBL_LO(intpin->io_intpin));
|
||||
value &= ~IOART_DESTMOD;
|
||||
value |= IOART_DESTLOG;
|
||||
ioapic_write(io->io_addr, IOAPIC_REDTBL_LO(intpin->io_intpin), value);
|
||||
value = ioapic_read(io->io_addr, IOAPIC_REDTBL_HI(intpin->io_intpin));
|
||||
value &= ~IOART_DEST;
|
||||
value |= (intpin->io_dest << APIC_ID_CLUSTER_SHIFT |
|
||||
APIC_ID_CLUSTER_ID) << APIC_ID_SHIFT;
|
||||
ioapic_write(io->io_addr, IOAPIC_REDTBL_HI(intpin->io_intpin), value);
|
||||
mtx_unlock_spin(&icu_lock);
|
||||
ioapic_program_intpin(intpin);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -339,7 +405,7 @@ static void
|
||||
ioapic_resume(struct intsrc *isrc)
|
||||
{
|
||||
|
||||
TODO;
|
||||
ioapic_program_intpin((struct ioapic_intsrc *)isrc);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -631,6 +697,7 @@ ioapic_register(void *cookie)
|
||||
printf("ioapic%u <Version %u.%u> irqs %u-%u on motherboard\n",
|
||||
io->io_id, flags >> 4, flags & 0xf, io->io_intbase,
|
||||
io->io_intbase + io->io_numintr - 1);
|
||||
bsp_id = PCPU_GET(apic_id);
|
||||
for (i = 0, pin = io->io_pins; i < io->io_numintr; i++, pin++) {
|
||||
/*
|
||||
* Finish initializing the pins by programming the vectors
|
||||
@ -638,63 +705,18 @@ ioapic_register(void *cookie)
|
||||
*/
|
||||
if (pin->io_vector == VECTOR_DISABLED)
|
||||
continue;
|
||||
flags = IOART_DESTPHY;
|
||||
if (pin->io_edgetrigger)
|
||||
flags |= IOART_TRGREDG;
|
||||
else
|
||||
flags |= IOART_TRGRLVL;
|
||||
if (pin->io_activehi)
|
||||
flags |= IOART_INTAHI;
|
||||
else
|
||||
flags |= IOART_INTALO;
|
||||
if (pin->io_masked)
|
||||
flags |= IOART_INTMSET;
|
||||
switch (pin->io_vector) {
|
||||
case VECTOR_EXTINT:
|
||||
KASSERT(pin->io_edgetrigger,
|
||||
("EXTINT not edge triggered"));
|
||||
flags |= IOART_DELEXINT;
|
||||
break;
|
||||
case VECTOR_NMI:
|
||||
KASSERT(pin->io_edgetrigger,
|
||||
("NMI not edge triggered"));
|
||||
flags |= IOART_DELNMI;
|
||||
break;
|
||||
case VECTOR_SMI:
|
||||
KASSERT(pin->io_edgetrigger,
|
||||
("SMI not edge triggered"));
|
||||
flags |= IOART_DELSMI;
|
||||
break;
|
||||
default:
|
||||
flags |= IOART_DELLOPRI |
|
||||
apic_irq_to_idt(pin->io_vector);
|
||||
}
|
||||
mtx_lock_spin(&icu_lock);
|
||||
ioapic_write(apic, IOAPIC_REDTBL_LO(i), flags);
|
||||
|
||||
ioapic_program_intpin(pin);
|
||||
if (pin->io_vector >= NUM_IO_INTS)
|
||||
continue;
|
||||
/*
|
||||
* Route interrupts to the BSP by default using physical
|
||||
* addressing. Vectored interrupts get readdressed using
|
||||
* logical IDs to CPU clusters when they are enabled.
|
||||
* Route IRQ0 via the 8259A using mixed mode if mixed mode
|
||||
* is available and turned on.
|
||||
*/
|
||||
flags = ioapic_read(apic, IOAPIC_REDTBL_HI(i));
|
||||
flags &= ~IOART_DEST;
|
||||
flags |= PCPU_GET(apic_id) << APIC_ID_SHIFT;
|
||||
ioapic_write(apic, IOAPIC_REDTBL_HI(i), flags);
|
||||
mtx_unlock_spin(&icu_lock);
|
||||
if (pin->io_vector < NUM_IO_INTS) {
|
||||
|
||||
/*
|
||||
* Route IRQ0 via the 8259A using mixed mode if
|
||||
* mixed mode is available and turned on.
|
||||
*/
|
||||
if (pin->io_vector == 0 && mixed_mode_active &&
|
||||
mixed_mode_enabled)
|
||||
ioapic_setup_mixed_mode(pin);
|
||||
else
|
||||
intr_register_source(&pin->io_intsrc);
|
||||
}
|
||||
|
||||
if (pin->io_vector == 0 && mixed_mode_active &&
|
||||
mixed_mode_enabled)
|
||||
ioapic_setup_mixed_mode(pin);
|
||||
else
|
||||
intr_register_source(&pin->io_intsrc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -222,17 +222,19 @@ legacy_add_child(device_t bus, int order, const char *name, int unit)
|
||||
|
||||
atdev = malloc(sizeof(struct legacy_device), M_LEGACYDEV,
|
||||
M_NOWAIT | M_ZERO);
|
||||
if (!atdev)
|
||||
return(0);
|
||||
if (atdev == NULL)
|
||||
return(NULL);
|
||||
resource_list_init(&atdev->lg_resources);
|
||||
atdev->lg_pcibus = -1;
|
||||
|
||||
child = device_add_child_ordered(bus, order, name, unit);
|
||||
child = device_add_child_ordered(bus, order, name, unit);
|
||||
if (child == NULL)
|
||||
free(atdev, M_LEGACYDEV);
|
||||
else
|
||||
/* should we free this in legacy_child_detached? */
|
||||
device_set_ivars(child, atdev);
|
||||
|
||||
/* should we free this in legacy_child_detached? */
|
||||
device_set_ivars(child, atdev);
|
||||
|
||||
return(child);
|
||||
return (child);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -544,15 +544,10 @@ conforming_polarity(u_char src_bus, u_char src_bus_irq)
|
||||
KASSERT(src_bus <= mptable_maxbusid, ("bus id %d too large", src_bus));
|
||||
switch (busses[src_bus].bus_type) {
|
||||
case ISA:
|
||||
case EISA:
|
||||
return (INTR_POLARITY_HIGH);
|
||||
case PCI:
|
||||
return (INTR_POLARITY_LOW);
|
||||
case EISA:
|
||||
KASSERT(src_bus_irq < 16, ("Invalid EISA IRQ %d", src_bus_irq));
|
||||
if (elcr_read_trigger(src_bus_irq) == INTR_TRIGGER_LEVEL)
|
||||
return (INTR_POLARITY_LOW);
|
||||
else
|
||||
return (INTR_POLARITY_HIGH);
|
||||
default:
|
||||
panic("%s: unknown bus type %d", __func__,
|
||||
busses[src_bus].bus_type);
|
||||
|
Loading…
Reference in New Issue
Block a user