int pci_intr_alloc(const struct pci_attach_args *pa, pci_intr_handle_t **ihps, int *counts, pci_intr_type_t max_type) { if (counts != NULL && counts[PCI_INTR_TYPE_INTX] == 0) return EINVAL; return pci_intx_alloc(pa, ihps); }
/* * Interrupt handler allocation utility. This function calls each allocation * function as specified by arguments. * Currently callee functions are pci_intx_alloc(), pci_msi_alloc_exact(), * and pci_msix_alloc_exact(). * pa : pci_attach_args * ihps : interrupt handlers * counts : The array of number of required interrupt handlers. * It is overwritten by allocated the number of handlers. * CAUTION: The size of counts[] must be PCI_INTR_TYPE_SIZE. * max_type : "max" type of using interrupts. See below. * e.g. * If you want to use 5 MSI-X, 1 MSI, or INTx, you use "counts" as * int counts[PCI_INTR_TYPE_SIZE]; * counts[PCI_INTR_TYPE_MSIX] = 5; * counts[PCI_INTR_TYPE_MSI] = 1; * counts[PCI_INTR_TYPE_INTX] = 1; * error = pci_intr_alloc(pa, ihps, counts, PCI_INTR_TYPE_MSIX); * * If you want to use hardware max number MSI-X or 1 MSI, * and not to use INTx, you use "counts" as * int counts[PCI_INTR_TYPE_SIZE]; * counts[PCI_INTR_TYPE_MSIX] = -1; * counts[PCI_INTR_TYPE_MSI] = 1; * counts[PCI_INTR_TYPE_INTX] = 0; * error = pci_intr_alloc(pa, ihps, counts, PCI_INTR_TYPE_MSIX); * * If you want to use 3 MSI or INTx, you can use "counts" as * int counts[PCI_INTR_TYPE_SIZE]; * counts[PCI_INTR_TYPE_MSI] = 3; * counts[PCI_INTR_TYPE_INTX] = 1; * error = pci_intr_alloc(pa, ihps, counts, PCI_INTR_TYPE_MSI); * * If you want to use 1 MSI or INTx (probably most general usage), * you can simply use this API like * below * error = pci_intr_alloc(pa, ihps, NULL, 0); * ^ ignored */ int pci_intr_alloc(const struct pci_attach_args *pa, pci_intr_handle_t **ihps, int *counts, pci_intr_type_t max_type) { int error; int intx_count, msi_count, msix_count; intx_count = msi_count = msix_count = 0; if (counts == NULL) { /* simple pattern */ msi_count = 1; intx_count = 1; } else { switch(max_type) { case PCI_INTR_TYPE_MSIX: msix_count = counts[PCI_INTR_TYPE_MSIX]; /* FALLTHROUGH */ case PCI_INTR_TYPE_MSI: msi_count = counts[PCI_INTR_TYPE_MSI]; /* FALLTHROUGH */ case PCI_INTR_TYPE_INTX: intx_count = counts[PCI_INTR_TYPE_INTX]; break; default: return EINVAL; } } if (counts != NULL) memset(counts, 0, sizeof(counts[0]) * PCI_INTR_TYPE_SIZE); error = EINVAL; /* try MSI-X */ if (msix_count == -1) /* use hardware max */ msix_count = pci_msix_count(pa->pa_pc, pa->pa_tag); if (msix_count > 0) { error = pci_msix_alloc_exact(pa, ihps, msix_count); if (error == 0) { KASSERTMSG(counts != NULL, "If MSI-X is used, counts must not be NULL."); counts[PCI_INTR_TYPE_MSIX] = msix_count; goto out; } } /* try MSI */ if (msi_count == -1) /* use hardware max */ msi_count = pci_msi_count(pa->pa_pc, pa->pa_tag); if (msi_count > 0) { error = pci_msi_alloc_exact(pa, ihps, msi_count); if (error == 0) { if (counts != NULL) counts[PCI_INTR_TYPE_MSI] = msi_count; goto out; } } /* try INTx */ if (intx_count != 0) { /* The number of INTx is always 1. */ error = pci_intx_alloc(pa, ihps); if (error == 0) { if (counts != NULL) counts[PCI_INTR_TYPE_INTX] = 1; } } out: return error; }