Ejemplo n.º 1
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();
}
Ejemplo n.º 2
0
static int
ioapic_find_unused_irqmap(int gsi)
{
	int cpuid, i;

	cpuid = ioapic_abi_gsi_cpuid(-1, gsi);

	for (i = ISA_IRQ_CNT; i < IOAPIC_HWI_VECTORS; ++i) {
		if (i == acpi_sci_irqno())
			continue;
		if (ioapic_irqmaps[cpuid][i].im_type == IOAPIC_IMT_UNUSED)
			return i;
	}
	return -1;
}
Ejemplo n.º 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);
	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();
}