static int dr_is_real_device(dev_info_t *dip) { struct regspec *regbuf = NULL; int length = 0; int rc; if (ddi_get_driver(dip) == NULL) return (0); if (DEVI(dip)->devi_pm_flags & (PMC_NEEDS_SR|PMC_PARENTAL_SR)) return (1); if (DEVI(dip)->devi_pm_flags & PMC_NO_SR) return (0); /* * now the general case */ rc = ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "reg", (caddr_t)®buf, &length); ASSERT(rc != DDI_PROP_NO_MEMORY); if (rc != DDI_PROP_SUCCESS) { return (0); } else { if ((length > 0) && (regbuf != NULL)) kmem_free(regbuf, length); return (1); } }
/* * Configuration-related entry points for nexus and leaf drivers */ int devi_identify(dev_info_t *devi) { struct dev_ops *ops; int (*fn)(dev_info_t *); if ((ops = ddi_get_driver(devi)) == NULL || (fn = ops->devo_identify) == NULL) return (-1); return ((*fn)(devi)); }
int devi_quiesce(dev_info_t *devi) { struct dev_ops *ops; int (*fn)(dev_info_t *); if (((ops = ddi_get_driver(devi)) == NULL) || (ops->devo_rev < 4) || ((fn = ops->devo_quiesce) == NULL)) return (DDI_FAILURE); return ((*fn)(devi)); }
/* * This entry point not defined by Solaris 2.0 DDI/DKI, so * its inclusion here is somewhat moot. */ int devi_reset(dev_info_t *devi, ddi_reset_cmd_t cmd) { struct dev_ops *ops; int (*fn)(dev_info_t *, ddi_reset_cmd_t); if ((ops = ddi_get_driver(devi)) == NULL || (fn = ops->devo_reset) == NULL) return (DDI_FAILURE); return ((*fn)(devi, cmd)); }
int devi_probe(dev_info_t *devi) { int rv, probe_failed; pm_ppm_cookie_t ppm_cookie; struct dev_ops *ops; int (*fn)(dev_info_t *); ops = ddi_get_driver(devi); ASSERT(ops); pm_pre_probe(devi, &ppm_cookie); /* * probe(9E) in 2.0 implies that you can get * away with not writing one of these .. so we * pretend we're 'nulldev' if we don't find one (sigh). */ if ((fn = ops->devo_probe) == NULL) { if (ddi_dev_is_sid(devi) == DDI_SUCCESS) rv = DDI_PROBE_DONTCARE; else rv = DDI_PROBE_FAILURE; } else rv = (*fn)(devi); switch (rv) { case DDI_PROBE_DONTCARE: case DDI_PROBE_SUCCESS: probe_failed = 0; break; default: probe_failed = 1; break; } pm_post_probe(&ppm_cookie, rv, probe_failed); return (rv); }
/* * devi_attach() * attach a device instance to the system if the driver supplies an * attach(9E) entrypoint. */ int devi_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) { struct dev_ops *ops; int error; int (*fn)(dev_info_t *, ddi_attach_cmd_t); pm_ppm_cookie_t pc; if ((error = mdi_pre_attach(devi, cmd)) != DDI_SUCCESS) { return (error); } pm_pre_attach(devi, &pc, cmd); if ((cmd == DDI_RESUME || cmd == DDI_PM_RESUME) && e_ddi_parental_suspend_resume(devi)) { error = e_ddi_resume(devi, cmd); goto done; } ops = ddi_get_driver(devi); ASSERT(ops); if ((fn = ops->devo_attach) == NULL) { error = DDI_FAILURE; goto done; } /* * Call the driver's attach(9e) entrypoint */ i_attach_ctlop(devi, cmd, DDI_PRE, 0); error = (*fn)(devi, cmd); i_attach_ctlop(devi, cmd, DDI_POST, error); done: pm_post_attach(&pc, error); mdi_post_attach(devi, cmd, error); return (error); }
/* * devi_detach() * detach a device instance from the system if the driver supplies a * detach(9E) entrypoint. */ int devi_detach(dev_info_t *devi, ddi_detach_cmd_t cmd) { struct dev_ops *ops; int error; int (*fn)(dev_info_t *, ddi_detach_cmd_t); pm_ppm_cookie_t pc; ASSERT(cmd == DDI_SUSPEND || cmd == DDI_PM_SUSPEND || cmd == DDI_DETACH); if ((cmd == DDI_SUSPEND || cmd == DDI_PM_SUSPEND) && e_ddi_parental_suspend_resume(devi)) { return (e_ddi_suspend(devi, cmd)); } ops = ddi_get_driver(devi); ASSERT(ops); if ((fn = ops->devo_detach) == NULL) return (DDI_FAILURE); if ((error = mdi_pre_detach(devi, cmd)) != DDI_SUCCESS) { return (error); } i_detach_ctlop(devi, cmd, DDI_PRE, 0); pm_pre_detach(devi, cmd, &pc); /* * Call the driver's detach routine */ error = (*fn)(devi, cmd); pm_post_detach(&pc, error); i_detach_ctlop(devi, cmd, DDI_POST, error); mdi_post_detach(devi, cmd, error); return (error); }
int xen_suspend_devices(dev_info_t *dip) { int error; char buf[XPV_BUFSIZE]; SUSPEND_DEBUG("xen_suspend_devices\n"); for (; dip != NULL; dip = ddi_get_next_sibling(dip)) { if (xen_suspend_devices(ddi_get_child(dip))) return (ENXIO); if (ddi_get_driver(dip) == NULL) continue; SUSPEND_DEBUG("Suspending device %s\n", ddi_deviname(dip, buf)); ASSERT((DEVI(dip)->devi_cpr_flags & DCF_CPR_SUSPENDED) == 0); if (!i_ddi_devi_attached(dip)) { error = DDI_FAILURE; } else { error = devi_detach(dip, DDI_SUSPEND); } if (error == DDI_SUCCESS) { DEVI(dip)->devi_cpr_flags |= DCF_CPR_SUSPENDED; } else { SUSPEND_DEBUG("WARNING: Unable to suspend device %s\n", ddi_deviname(dip, buf)); cmn_err(CE_WARN, "Unable to suspend device %s.", ddi_deviname(dip, buf)); cmn_err(CE_WARN, "Device is busy or does not " "support suspend/resume."); return (ENXIO); } } return (0); }