Example #1
0
static boolean_t
acpi_sci_test(const struct acpi_sci_mode *mode)
{
	void *sci_desc;
	long last_cnt;

	FADT_VPRINTF("SCI testing %s/%s\n",
	    intr_str_trigger(mode->sci_trig),
	    intr_str_polarity(mode->sci_pola));

	last_cnt = get_interrupt_counter(acpi_sci_irq, 0);

	machintr_legacy_intr_config(acpi_sci_irq,
	    mode->sci_trig, mode->sci_pola);

	sci_desc = register_int(acpi_sci_irq,
	    acpi_sci_dummy_intr, NULL, "sci", NULL,
	    INTR_EXCL | INTR_CLOCK |
	    INTR_NOPOLL | INTR_MPSAFE | INTR_NOENTROPY, 0);

	DELAY(100 * 1000);

	unregister_int(sci_desc, 0);

	if (get_interrupt_counter(acpi_sci_irq, 0) - last_cnt < 20) {
		acpi_sci_trig = mode->sci_trig;
		acpi_sci_pola = mode->sci_pola;

		kprintf("ACPI FADT: SCI select %s/%s\n",
		    intr_str_trigger(acpi_sci_trig),
		    intr_str_polarity(acpi_sci_pola));
		return TRUE;
	}
	return FALSE;
}
Example #2
0
void
acpi_sci_config(void)
{
	const struct acpi_sci_mode *mode;

	KKASSERT(mycpuid == 0);

	if (acpi_sci_irq < 0)
		return;

	if (acpi_sci_trig != INTR_TRIGGER_CONFORM) {
		KKASSERT(acpi_sci_pola != INTR_POLARITY_CONFORM);
		machintr_legacy_intr_config(acpi_sci_irq,
		    acpi_sci_trig, acpi_sci_pola);
		return;
	}

	kprintf("ACPI FADT: SCI testing interrupt mode ...\n");
	for (mode = acpi_sci_modes; mode->sci_trig != INTR_TRIGGER_CONFORM;
	     ++mode) {
		void *sci_desc;
		long last_cnt;

		FADT_VPRINTF("SCI testing %s/%s\n",
		    intr_str_trigger(mode->sci_trig),
		    intr_str_polarity(mode->sci_pola));

		last_cnt = get_interrupt_counter(acpi_sci_irq, 0);

		machintr_legacy_intr_config(acpi_sci_irq,
		    mode->sci_trig, mode->sci_pola);

		sci_desc = register_int(acpi_sci_irq,
		    acpi_sci_dummy_intr, NULL, "sci", NULL,
		    INTR_EXCL | INTR_CLOCK |
		    INTR_NOPOLL | INTR_MPSAFE | INTR_NOENTROPY, 0);

		DELAY(100 * 1000);

		unregister_int(sci_desc, 0);

		if (get_interrupt_counter(acpi_sci_irq, 0) - last_cnt < 20) {
			acpi_sci_trig = mode->sci_trig;
			acpi_sci_pola = mode->sci_pola;

			kprintf("ACPI FADT: SCI select %s/%s\n",
			    intr_str_trigger(acpi_sci_trig),
			    intr_str_polarity(acpi_sci_pola));
			return;
		}
	}

	kprintf("ACPI FADT: no suitable interrupt mode for SCI, disable\n");
	acpi_sci_irq = -1;
}
Example #3
0
void
ioapic_set_legacy_irqmap(int irq, int gsi, enum intr_trigger trig,
    enum intr_polarity pola)
{
	struct ioapic_irqinfo *info;
	struct ioapic_irqmap *map;
	void *ioaddr;
	int pin, cpuid;

	KKASSERT(trig == INTR_TRIGGER_EDGE || trig == INTR_TRIGGER_LEVEL);
	KKASSERT(pola == INTR_POLARITY_HIGH || pola == INTR_POLARITY_LOW);

	KKASSERT(irq >= 0 && irq < IOAPIC_HWI_VECTORS);
	if (irq > ioapic_abi_legacy_irq_max)
		ioapic_abi_legacy_irq_max = irq;

	cpuid = ioapic_abi_gsi_cpuid(irq, gsi);

	map = &ioapic_irqmaps[cpuid][irq];

	KKASSERT(map->im_type == IOAPIC_IMT_UNUSED);
	map->im_type = IOAPIC_IMT_LEGACY;

	map->im_gsi = gsi;
	map->im_trig = trig;
	map->im_pola = pola;

	if (bootverbose) {
		kprintf("IOAPIC: irq %d -> gsi %d %s/%s\n",
			irq, map->im_gsi,
			intr_str_trigger(map->im_trig),
			intr_str_polarity(map->im_pola));
	}

	pin = ioapic_gsi_pin(map->im_gsi);
	ioaddr = ioapic_gsi_ioaddr(map->im_gsi);

	info = &ioapic_irqs[irq];

	imen_lock();

	info->io_addr = ioaddr;
	info->io_idx = IOAPIC_REDTBL + (2 * pin);
	info->io_flags = IOAPIC_IRQI_FLAG_MASKED;
	if (map->im_trig == INTR_TRIGGER_LEVEL)
		info->io_flags |= IOAPIC_IRQI_FLAG_LEVEL;

	ioapic_pin_setup(ioaddr, pin, IDT_OFFSET + irq,
	    map->im_trig, map->im_pola, cpuid);

	imen_unlock();
}
Example #4
0
static void
fadt_probe(void)
{
	struct acpi_fadt *fadt;
	vm_paddr_t fadt_paddr;
	enum intr_trigger trig;
	enum intr_polarity pola;
	int enabled = 1;
	char *env;

	fadt_paddr = sdt_search(ACPI_FADT_SIG);
	if (fadt_paddr == 0) {
		kprintf("fadt_probe: can't locate FADT\n");
		return;
	}

	fadt = sdt_sdth_map(fadt_paddr);
	KKASSERT(fadt != NULL);

	/*
	 * FADT in ACPI specification 1.0 - 4.0
	 */
	if (fadt->fadt_hdr.sdth_rev < 1 || fadt->fadt_hdr.sdth_rev > 4) {
		kprintf("fadt_probe: unsupported FADT revision %d\n",
			fadt->fadt_hdr.sdth_rev);
		goto back;
	}

	if (fadt->fadt_hdr.sdth_len < sizeof(*fadt)) {
		kprintf("fadt_probe: invalid FADT length %u\n",
			fadt->fadt_hdr.sdth_len);
		goto back;
	}

	kgetenv_int("hw.acpi.sci.enabled", &enabled);
	if (!enabled)
		goto back;

	acpi_sci_irq = fadt->fadt_sci_int;

	env = kgetenv("hw.acpi.sci.trigger");
	if (env == NULL)
		goto back;

	trig = INTR_TRIGGER_CONFORM;
	if (strcmp(env, "edge") == 0)
		trig = INTR_TRIGGER_EDGE;
	else if (strcmp(env, "level") == 0)
		trig = INTR_TRIGGER_LEVEL;

	kfreeenv(env);

	if (trig == INTR_TRIGGER_CONFORM)
		goto back;

	env = kgetenv("hw.acpi.sci.polarity");
	if (env == NULL)
		goto back;

	pola = INTR_POLARITY_CONFORM;
	if (strcmp(env, "high") == 0)
		pola = INTR_POLARITY_HIGH;
	else if (strcmp(env, "low") == 0)
		pola = INTR_POLARITY_LOW;

	kfreeenv(env);

	if (pola == INTR_POLARITY_CONFORM)
		goto back;

	acpi_sci_trig = trig;
	acpi_sci_pola = pola;
back:
	if (acpi_sci_irq >= 0) {
		FADT_VPRINTF("SCI irq %d, %s/%s\n", acpi_sci_irq,
			     intr_str_trigger(acpi_sci_trig),
			     intr_str_polarity(acpi_sci_pola));
	} else {
		FADT_VPRINTF("SCI is disabled\n");
	}
	sdt_sdth_unmap(&fadt->fadt_hdr);
}
Example #5
0
int
ioapic_conf_legacy_extint(int irq)
{
	struct ioapic_irqinfo *info;
	struct ioapic_irqmap *map;
	void *ioaddr;
	int pin, error, vec;

	/* XXX only irq0 is allowed */
	KKASSERT(irq == 0);

	vec = IDT_OFFSET + irq;

	if (ioapic_abi_extint_irq == irq)
		return 0;
	else if (ioapic_abi_extint_irq >= 0)
		return EEXIST;

	error = icu_ioapic_extint(irq, vec);
	if (error)
		return error;

	/* ExtINT is always targeted to cpu0 */
	map = &ioapic_irqmaps[0][irq];

	KKASSERT(map->im_type == IOAPIC_IMT_RESERVED ||
		 map->im_type == IOAPIC_IMT_LEGACY);
	if (map->im_type == IOAPIC_IMT_LEGACY) {
		if (map->im_flags & IOAPIC_IMF_CONF)
			return EEXIST;
	}
	ioapic_abi_extint_irq = irq;

	map->im_type = IOAPIC_IMT_LEGACY;
	map->im_trig = INTR_TRIGGER_EDGE;
	map->im_pola = INTR_POLARITY_HIGH;
	map->im_flags = IOAPIC_IMF_CONF;

	map->im_gsi = ioapic_extpin_gsi();
	KKASSERT(map->im_gsi >= 0);

	if (bootverbose) {
		kprintf("IOAPIC: irq %d -> extint gsi %d %s/%s\n",
			irq, map->im_gsi,
			intr_str_trigger(map->im_trig),
			intr_str_polarity(map->im_pola));
	}

	pin = ioapic_gsi_pin(map->im_gsi);
	ioaddr = ioapic_gsi_ioaddr(map->im_gsi);

	info = &ioapic_irqs[irq];

	imen_lock();

	info->io_addr = ioaddr;
	info->io_idx = IOAPIC_REDTBL + (2 * pin);
	info->io_flags = IOAPIC_IRQI_FLAG_MASKED;

	ioapic_extpin_setup(ioaddr, pin, vec);

	imen_unlock();

	return 0;
}
Example #6
0
static void
ioapic_abi_legacy_intr_config(int irq, enum intr_trigger trig,
    enum intr_polarity pola)
{
	struct ioapic_irqinfo *info;
	struct ioapic_irqmap *map = NULL;
	void *ioaddr;
	int pin, cpuid;

	KKASSERT(trig == INTR_TRIGGER_EDGE || trig == INTR_TRIGGER_LEVEL);
	KKASSERT(pola == INTR_POLARITY_HIGH || pola == INTR_POLARITY_LOW);

	KKASSERT(irq >= 0 && irq < ioapic_abi_legacy_irq_max);
	for (cpuid = 0; cpuid < ncpus; ++cpuid) {
		map = &ioapic_irqmaps[cpuid][irq];
		if (map->im_type == IOAPIC_IMT_LEGACY)
			break;
	}
	KKASSERT(cpuid < ncpus);

#ifdef notyet
	if (map->im_flags & IOAPIC_IMF_CONF) {
		if (trig != map->im_trig) {
			panic("ioapic_intr_config: trig %s -> %s\n",
			      intr_str_trigger(map->im_trig),
			      intr_str_trigger(trig));
		}
		if (pola != map->im_pola) {
			panic("ioapic_intr_config: pola %s -> %s\n",
			      intr_str_polarity(map->im_pola),
			      intr_str_polarity(pola));
		}
		return;
	}
#endif
	map->im_flags |= IOAPIC_IMF_CONF;

	if (trig == map->im_trig && pola == map->im_pola)
		return;

	if (bootverbose) {
		kprintf("IOAPIC: irq %d, gsi %d %s/%s -> %s/%s\n",
			irq, map->im_gsi,
			intr_str_trigger(map->im_trig),
			intr_str_polarity(map->im_pola),
			intr_str_trigger(trig),
			intr_str_polarity(pola));
	}
	map->im_trig = trig;
	map->im_pola = pola;

	pin = ioapic_gsi_pin(map->im_gsi);
	ioaddr = ioapic_gsi_ioaddr(map->im_gsi);

	info = &ioapic_irqs[irq];

	imen_lock();

	info->io_flags &= ~IOAPIC_IRQI_FLAG_LEVEL;
	if (map->im_trig == INTR_TRIGGER_LEVEL)
		info->io_flags |= IOAPIC_IRQI_FLAG_LEVEL;

	ioapic_pin_setup(ioaddr, pin, IDT_OFFSET + irq,
	    map->im_trig, map->im_pola, cpuid);

	imen_unlock();
}
Example #7
0
void
ioapic_set_legacy_irqmap(int irq, int gsi, enum intr_trigger trig,
    enum intr_polarity pola)
{
	struct ioapic_irqinfo *info;
	struct ioapic_irqmap *map;
	void *ioaddr;
	int pin, cpuid;

	KKASSERT(trig == INTR_TRIGGER_EDGE || trig == INTR_TRIGGER_LEVEL);
	KKASSERT(pola == INTR_POLARITY_HIGH || pola == INTR_POLARITY_LOW);

	KKASSERT(irq >= 0);
	if (irq >= IOAPIC_HWI_VECTORS) {
		/*
		 * Some BIOSes seem to assume that all 256 IDT vectors
		 * could be used, while we limit the available IDT
		 * vectors to 192; find an unused IRQ for this GSI.
		 */
		irq = ioapic_find_unused_irqmap(gsi);
		if (irq < 0) {
			kprintf("failed to find unused irq for gsi %d, "
			    "overflow\n", gsi);
			return;
		}
	}
	KKASSERT(irq < IOAPIC_HWI_VECTORS);

	cpuid = ioapic_abi_gsi_cpuid(irq, gsi);
	map = &ioapic_irqmaps[cpuid][irq];

	if (map->im_type != IOAPIC_IMT_UNUSED) {
		/*
		 * There are so many IOAPICs, that 1:1 mapping
		 * of GSI and IRQ hits SYSCALL entry.
		 */
		irq = ioapic_find_unused_irqmap(gsi);
		if (irq < 0) {
			kprintf("failed to find unused irq for gsi %d, "
			    "conflict\n", gsi);
			return;
		}
		KKASSERT(irq < IOAPIC_HWI_VECTORS);

		cpuid = ioapic_abi_gsi_cpuid(irq, gsi);
		map = &ioapic_irqmaps[cpuid][irq];
	}

	if (irq > ioapic_abi_legacy_irq_max)
		ioapic_abi_legacy_irq_max = irq;

	KKASSERT(map->im_type == IOAPIC_IMT_UNUSED);
	map->im_type = IOAPIC_IMT_LEGACY;

	map->im_gsi = gsi;
	map->im_trig = trig;
	map->im_pola = pola;

	if (bootverbose) {
		kprintf("IOAPIC: irq %d -> gsi %d %s/%s\n",
			irq, map->im_gsi,
			intr_str_trigger(map->im_trig),
			intr_str_polarity(map->im_pola));
	}

	pin = ioapic_gsi_pin(map->im_gsi);
	ioaddr = ioapic_gsi_ioaddr(map->im_gsi);

	info = &ioapic_irqs[irq];

	imen_lock();

	info->io_addr = ioaddr;
	info->io_idx = IOAPIC_REDTBL + (2 * pin);
	info->io_flags = IOAPIC_IRQI_FLAG_MASKED;
	if (map->im_trig == INTR_TRIGGER_LEVEL)
		info->io_flags |= IOAPIC_IRQI_FLAG_LEVEL;

	ioapic_pin_setup(ioaddr, pin, IDT_OFFSET + irq,
	    map->im_trig, map->im_pola, cpuid);

	imen_unlock();
}
Example #8
0
static void
fadt_probe(void)
{
	ACPI_TABLE_FADT *fadt;
	vm_paddr_t fadt_paddr;
	enum intr_trigger trig;
	enum intr_polarity pola;
	int enabled = 1;
	char *env;

	fadt_paddr = sdt_search(ACPI_SIG_FADT);
	if (fadt_paddr == 0) {
		kprintf("fadt_probe: can't locate FADT\n");
		return;
	}

	fadt = sdt_sdth_map(fadt_paddr);
	KKASSERT(fadt != NULL);

	/*
	 * FADT in ACPI specification 1.0 - 6.0
	 */
	if (fadt->Header.Revision < 1 || fadt->Header.Revision > 6) {
		kprintf("fadt_probe: unknown FADT revision %d\n",
			fadt->Header.Revision);
	}

	if (fadt->Header.Length < ACPI_FADT_V1_SIZE) {
		kprintf("fadt_probe: invalid FADT length %u (< %u)\n",
		    fadt->Header.Length, ACPI_FADT_V1_SIZE);
		goto back;
	}

	kgetenv_int("hw.acpi.sci.enabled", &enabled);
	if (!enabled)
		goto back;

	acpi_sci_irq = fadt->SciInterrupt;

	env = kgetenv("hw.acpi.sci.trigger");
	if (env == NULL)
		goto back;

	trig = INTR_TRIGGER_CONFORM;
	if (strcmp(env, "edge") == 0)
		trig = INTR_TRIGGER_EDGE;
	else if (strcmp(env, "level") == 0)
		trig = INTR_TRIGGER_LEVEL;

	kfreeenv(env);

	if (trig == INTR_TRIGGER_CONFORM)
		goto back;

	env = kgetenv("hw.acpi.sci.polarity");
	if (env == NULL)
		goto back;

	pola = INTR_POLARITY_CONFORM;
	if (strcmp(env, "high") == 0)
		pola = INTR_POLARITY_HIGH;
	else if (strcmp(env, "low") == 0)
		pola = INTR_POLARITY_LOW;

	kfreeenv(env);

	if (pola == INTR_POLARITY_CONFORM)
		goto back;

	acpi_sci_trig = trig;
	acpi_sci_pola = pola;
back:
	if (acpi_sci_irq >= 0) {
		FADT_VPRINTF("SCI irq %d, %s/%s\n", acpi_sci_irq,
			     intr_str_trigger(acpi_sci_trig),
			     intr_str_polarity(acpi_sci_pola));
	} else {
		FADT_VPRINTF("SCI is disabled\n");
	}
	sdt_sdth_unmap(&fadt->Header);
}