/* ARGSUSED */ int px_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op, ddi_intr_handle_impl_t *hdlp, void *result) { int intr_types, ret = DDI_SUCCESS; px_t *px_p = DIP_TO_STATE(dip); DBG(DBG_INTROPS, dip, "px_intr_ops: rdip=%s%d\n", ddi_driver_name(rdip), ddi_get_instance(rdip)); /* Process DDI_INTROP_SUPPORTED_TYPES request here */ if (intr_op == DDI_INTROP_SUPPORTED_TYPES) { *(int *)result = i_ddi_get_intx_nintrs(rdip) ? DDI_INTR_TYPE_FIXED : 0; if ((pci_msi_get_supported_type(rdip, &intr_types)) == DDI_SUCCESS) { /* * Double check supported interrupt types vs. * what the host bridge supports. */ *(int *)result |= intr_types; } *(int *)result &= (px_force_intx_support ? (px_p->px_supp_intr_types | DDI_INTR_TYPE_FIXED) : px_p->px_supp_intr_types); return (*(int *)result ? DDI_SUCCESS : DDI_FAILURE); } /* * PCI-E nexus driver supports fixed, MSI and MSI-X interrupts. * Return failure if interrupt type is not supported. */ switch (hdlp->ih_type) { case DDI_INTR_TYPE_FIXED: ret = px_intx_ops(dip, rdip, intr_op, hdlp, result); break; case DDI_INTR_TYPE_MSI: case DDI_INTR_TYPE_MSIX: ret = px_msix_ops(dip, rdip, intr_op, hdlp, result); break; default: ret = DDI_ENOTSUP; break; } return (ret); }
static int acebus_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op, ddi_intr_handle_impl_t *hdlp, void *result) { #ifdef DEBUG ebus_devstate_t *ebus_p = get_acebus_soft_state(ddi_get_instance(dip)); #endif int8_t *name, *device_type; int32_t i, max_children, max_device_types, len; /* * NOTE: These ops below will never be supported in this nexus * driver, hence they always return immediately. */ switch (intr_op) { case DDI_INTROP_GETCAP: *(int *)result = DDI_INTR_FLAG_LEVEL; return (DDI_SUCCESS); case DDI_INTROP_SUPPORTED_TYPES: *(int *)result = i_ddi_get_intx_nintrs(rdip) ? DDI_INTR_TYPE_FIXED : 0; return (DDI_SUCCESS); case DDI_INTROP_SETCAP: case DDI_INTROP_SETMASK: case DDI_INTROP_CLRMASK: case DDI_INTROP_GETPENDING: return (DDI_ENOTSUP); default: break; } if (hdlp->ih_pri) goto done; /* * This is a hack to set the PIL for the devices under ebus. * We first look up a device by it's specific name, if we can't * match the name, we try and match it's device_type property. * Lastly we default a PIL level of 1. */ DBG1(D_INTR, ebus_p, "ebus_p %p\n", ebus_p); name = ddi_get_name(rdip); max_children = sizeof (acebus_name_to_pil) / sizeof (struct ebus_string_to_pil); for (i = 0; i < max_children; i++) { if (strcmp(acebus_name_to_pil[i].string, name) == 0) { DBG2(D_INTR, ebus_p, "child name %s; match PIL %d\n", acebus_name_to_pil[i].string, acebus_name_to_pil[i].pil); hdlp->ih_pri = acebus_name_to_pil[i].pil; goto done; } } if (ddi_getlongprop(DDI_DEV_T_ANY, rdip, DDI_PROP_DONTPASS, "device_type", (caddr_t)&device_type, &len) == DDI_SUCCESS) { max_device_types = sizeof (acebus_device_type_to_pil) / sizeof (struct ebus_string_to_pil); for (i = 0; i < max_device_types; i++) { if (strcmp(acebus_device_type_to_pil[i].string, device_type) == 0) { DBG2(D_INTR, ebus_p, "Device type %s; match PIL %d\n", acebus_device_type_to_pil[i].string, acebus_device_type_to_pil[i].pil); hdlp->ih_pri = acebus_device_type_to_pil[i].pil; break; } } kmem_free(device_type, len); } /* * If we get here, we need to set a default value * for the PIL. */ if (hdlp->ih_pri == 0) { hdlp->ih_pri = 1; cmn_err(CE_WARN, "%s%d assigning default interrupt level %d " "for device %s%d", ddi_driver_name(dip), ddi_get_instance(dip), hdlp->ih_pri, ddi_driver_name(rdip), ddi_get_instance(rdip)); } done: /* Pass up the request to our parent. */ return (i_ddi_intr_ops(dip, rdip, intr_op, hdlp, result)); }
static int isa_intr_ops(dev_info_t *pdip, dev_info_t *rdip, ddi_intr_op_t intr_op, ddi_intr_handle_impl_t *hdlp, void *result) { struct intrspec *ispec; #if defined(__xpv) int cons, ttyn; cons = console_hypervisor_dev_type(&ttyn); #endif if (pseudo_isa) return (i_ddi_intr_ops(pdip, rdip, intr_op, hdlp, result)); /* Process the interrupt operation */ switch (intr_op) { case DDI_INTROP_GETCAP: /* First check with pcplusmp */ if (psm_intr_ops == NULL) return (DDI_FAILURE); if ((*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_GET_CAP, result)) { *(int *)result = 0; return (DDI_FAILURE); } break; case DDI_INTROP_SETCAP: if (psm_intr_ops == NULL) return (DDI_FAILURE); if ((*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_SET_CAP, result)) return (DDI_FAILURE); break; case DDI_INTROP_ALLOC: ASSERT(hdlp->ih_type == DDI_INTR_TYPE_FIXED); return (isa_alloc_intr_fixed(rdip, hdlp, result)); case DDI_INTROP_FREE: ASSERT(hdlp->ih_type == DDI_INTR_TYPE_FIXED); return (isa_free_intr_fixed(rdip, hdlp)); case DDI_INTROP_GETPRI: if ((ispec = isa_get_ispec(rdip, hdlp->ih_inum)) == NULL) return (DDI_FAILURE); *(int *)result = ispec->intrspec_pri; break; case DDI_INTROP_SETPRI: /* Validate the interrupt priority passed to us */ if (*(int *)result > LOCK_LEVEL) return (DDI_FAILURE); /* Ensure that PSM is all initialized and ispec is ok */ if ((psm_intr_ops == NULL) || ((ispec = isa_get_ispec(rdip, hdlp->ih_inum)) == NULL)) return (DDI_FAILURE); /* update the ispec with the new priority */ ispec->intrspec_pri = *(int *)result; break; case DDI_INTROP_ADDISR: if ((ispec = isa_get_ispec(rdip, hdlp->ih_inum)) == NULL) return (DDI_FAILURE); ispec->intrspec_func = hdlp->ih_cb_func; break; case DDI_INTROP_REMISR: if (hdlp->ih_type != DDI_INTR_TYPE_FIXED) return (DDI_FAILURE); if ((ispec = isa_get_ispec(rdip, hdlp->ih_inum)) == NULL) return (DDI_FAILURE); ispec->intrspec_func = (uint_t (*)()) 0; break; case DDI_INTROP_ENABLE: if ((ispec = isa_get_ispec(rdip, hdlp->ih_inum)) == NULL) return (DDI_FAILURE); /* Call psmi to translate irq with the dip */ if (psm_intr_ops == NULL) return (DDI_FAILURE); #if defined(__xpv) /* * if the hypervisor is using an isa serial port for the * console, make sure we don't try to use that interrupt as * it will cause us to panic when xen_bind_pirq() fails. */ if (cons == CONS_TTY && ispec->intrspec_vec == asy_intrs[ttyn]) return (DDI_FAILURE); #endif ((ihdl_plat_t *)hdlp->ih_private)->ip_ispecp = ispec; if ((*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_XLATE_VECTOR, (int *)&hdlp->ih_vector) == PSM_FAILURE) return (DDI_FAILURE); /* Add the interrupt handler */ if (!add_avintr((void *)hdlp, ispec->intrspec_pri, hdlp->ih_cb_func, DEVI(rdip)->devi_name, hdlp->ih_vector, hdlp->ih_cb_arg1, hdlp->ih_cb_arg2, NULL, rdip)) return (DDI_FAILURE); break; case DDI_INTROP_DISABLE: if ((ispec = isa_get_ispec(rdip, hdlp->ih_inum)) == NULL) return (DDI_FAILURE); /* Call psm_ops() to translate irq with the dip */ if (psm_intr_ops == NULL) return (DDI_FAILURE); ((ihdl_plat_t *)hdlp->ih_private)->ip_ispecp = ispec; (void) (*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_XLATE_VECTOR, (int *)&hdlp->ih_vector); /* Remove the interrupt handler */ rem_avintr((void *)hdlp, ispec->intrspec_pri, hdlp->ih_cb_func, hdlp->ih_vector); break; case DDI_INTROP_SETMASK: if (psm_intr_ops == NULL) return (DDI_FAILURE); if ((*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_SET_MASK, NULL)) return (DDI_FAILURE); break; case DDI_INTROP_CLRMASK: if (psm_intr_ops == NULL) return (DDI_FAILURE); if ((*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_CLEAR_MASK, NULL)) return (DDI_FAILURE); break; case DDI_INTROP_GETPENDING: if (psm_intr_ops == NULL) return (DDI_FAILURE); if ((*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_GET_PENDING, result)) { *(int *)result = 0; return (DDI_FAILURE); } break; case DDI_INTROP_NAVAIL: case DDI_INTROP_NINTRS: *(int *)result = i_ddi_get_intx_nintrs(rdip); if (*(int *)result == 0) { return (DDI_FAILURE); } break; case DDI_INTROP_SUPPORTED_TYPES: *(int *)result = DDI_INTR_TYPE_FIXED; /* Always ... */ break; default: return (DDI_FAILURE); } return (DDI_SUCCESS); }