FreeBSD/sys/i386/pci/pci_pir.c
/*
 * Route a PCI interrupt using a link device from the $PIR.
 */
Route a PCI interrupt using a link device from the $PIR.
Route a PCI interrupt using a link device from the $PIR .
int
pci_pir_route_interrupt(int bus, int device, int func, int pin)
{
	struct pci_link_lookup lookup;
	struct pci_link *pci_link;
	int error, irq;
	if (pci_route_table == NULL)
		return (PCI_INVALID_IRQ);
	pci_link = NULL;
	lookup.bus = bus;
	lookup.device = device;
	lookup.pin = pin - 1;
	lookup.pci_link_ptr = &pci_link;
	pci_pir_walk_table(pci_pir_find_link_handler, &lookup);
	if (pci_link == NULL) {
		printf("$PIR: No matching entry for %d.%d.INT%c\n", bus,
		    device, pin - 1 + 'A');
		return (PCI_INVALID_IRQ);
	}
	if (!PCI_INTERRUPT_VALID(pci_link->pl_irq)) {
		if (pci_link->pl_irqmask != 0 && powerof2(pci_link->pl_irqmask))
			irq = ffs(pci_link->pl_irqmask) - 1;
		else
			irq = pci_pir_choose_irq(pci_link,
			    pci_route_table->pt_header.ph_pci_irqs);
		if (!PCI_INTERRUPT_VALID(irq))
			irq = pci_pir_choose_irq(pci_link, pir_bios_irqs);
		if (!PCI_INTERRUPT_VALID(irq))
			irq = pci_pir_choose_irq(pci_link,
			    pci_irq_override_mask);
		if (!PCI_INTERRUPT_VALID(irq)) {
			if (bootverbose)
				printf(
			"$PIR: Failed to route interrupt for %d:%d INT%c\n",
				    bus, device, pin - 1 + 'A');
			return (PCI_INVALID_IRQ);
		}
		pci_link->pl_irq = irq;
	}
	if (!pci_link->pl_routed) {
		error = pci_pir_biosroute(bus, device, func, pin - 1,
		    pci_link->pl_irq);
		if (error && !powerof2(pci_link->pl_irqmask)) {
			printf("$PIR: ROUTE_INTERRUPT failed.\n");
			return (PCI_INVALID_IRQ);
		}
		pci_link->pl_routed = 1;
		KASSERT(pir_device != NULL, ("missing pir device"));
		BUS_CONFIG_INTR(pir_device, pci_link->pl_irq,
		    INTR_TRIGGER_LEVEL, INTR_POLARITY_LOW);
	}
	if (bootverbose)
		printf("$PIR: %d:%d INT%c routed to irq %d\n", bus, device,
		    pin - 1 + 'A', pci_link->pl_irq);
	return (pci_link->pl_irq);
}
int pci_pir_route_interrupt ( int bus , int device , int func , int pin ) { struct pci_link_lookup lookup ; struct pci_link * pci_link ; int error , irq ; if ( pci_route_table == NULL ) return ( PCI_INVALID_IRQ ) ; pci_link = NULL ; lookup . bus = bus ; lookup . device = device ; lookup . pin = pin - 1 ; lookup . pci_link_ptr = & pci_link ; pci_pir_walk_table ( pci_pir_find_link_handler , & lookup ) ; if ( pci_link == NULL ) { printf ( " \n " , bus , device , pin - 1 + ' ' ) ; return ( PCI_INVALID_IRQ ) ; } if ( ! PCI_INTERRUPT_VALID ( pci_link -> pl_irq ) ) { if ( pci_link -> pl_irqmask != 0 && powerof2 ( pci_link -> pl_irqmask ) ) irq = ffs ( pci_link -> pl_irqmask ) - 1 ; else irq = pci_pir_choose_irq ( pci_link , pci_route_table -> pt_header . ph_pci_irqs ) ; if ( ! PCI_INTERRUPT_VALID ( irq ) ) irq = pci_pir_choose_irq ( pci_link , pir_bios_irqs ) ; if ( ! PCI_INTERRUPT_VALID ( irq ) ) irq = pci_pir_choose_irq ( pci_link , pci_irq_override_mask ) ; if ( ! PCI_INTERRUPT_VALID ( irq ) ) { if ( bootverbose ) printf ( " \n " , bus , device , pin - 1 + ' ' ) ; return ( PCI_INVALID_IRQ ) ; } pci_link -> pl_irq = irq ; } if ( ! pci_link -> pl_routed ) { error = pci_pir_biosroute ( bus , device , func , pin - 1 , pci_link -> pl_irq ) ; if ( error && ! powerof2 ( pci_link -> pl_irqmask ) ) { printf ( " \n " ) ; return ( PCI_INVALID_IRQ ) ; } pci_link -> pl_routed = 1 ; KASSERT ( pir_device != NULL , ( " " ) ) ; BUS_CONFIG_INTR ( pir_device , pci_link -> pl_irq , INTR_TRIGGER_LEVEL , INTR_POLARITY_LOW ) ; } if ( bootverbose ) printf ( " \n " , bus , device , pin - 1 + ' ' , pci_link -> pl_irq ) ; return ( pci_link -> pl_irq ) ; }
Route a PCI interrupt using a link device from the $PIR.
Route a PCI interrupt using a link device from the $PIR .
/* Lookup link device for this PCI device/pin. */ /*
	 * Pick a new interrupt if we don't have one already.  We look
	 * for an interrupt from several different sets.  First, if
	 * this link only has one valid IRQ, use that.  Second, we
	 * check the set of PCI only interrupts from the $PIR.  Third,
	 * we check the set of known-good interrupts that the BIOS has
	 * already used.  Lastly, we check the "all possible valid
	 * IRQs" set.
	 */ /* Ask the BIOS to route this IRQ if we haven't done so already. */ /* Ignore errors when routing a unique interrupt. */ /* Ensure the interrupt is set to level/low trigger. */