コード例 #1
0
ファイル: pci_pci.c プロジェクト: apprisi/illumos-gate
/*ARGSUSED*/
static int
ppb_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
{
	dev_info_t *root = ddi_root_node();
	int instance;
	ppb_devstate_t *ppb;
	dev_info_t *pdip;
	ddi_acc_handle_t config_handle;
	char *bus;

	switch (cmd) {
	case DDI_ATTACH:

		/*
		 * Make sure the "device_type" property exists.
		 */
		(void) ddi_prop_update_string(DDI_DEV_T_NONE, devi,
		    "device_type", "pci");

		/*
		 * Allocate and get soft state structure.
		 */
		instance = ddi_get_instance(devi);
		if (ddi_soft_state_zalloc(ppb_state, instance) != DDI_SUCCESS)
			return (DDI_FAILURE);
		ppb = (ppb_devstate_t *)ddi_get_soft_state(ppb_state, instance);
		ppb->dip = devi;
		mutex_init(&ppb->ppb_mutex, NULL, MUTEX_DRIVER, NULL);
		ppb->ppb_soft_state = PCI_SOFT_STATE_CLOSED;
		if (pci_config_setup(devi, &config_handle) != DDI_SUCCESS) {
			mutex_destroy(&ppb->ppb_mutex);
			ddi_soft_state_free(ppb_state, instance);
			return (DDI_FAILURE);
		}
		ppb_pwr_setup(ppb, devi);

		if (PM_CAPABLE(ppb->ppb_pwr_p)) {
			mutex_enter(&ppb->ppb_pwr_p->pwr_mutex);

			/*
			 * Before reading config registers, make sure power is
			 * on, and remains on.
			 */
			ppb->ppb_pwr_p->pwr_fp++;

			pci_pwr_change(ppb->ppb_pwr_p,
			    ppb->ppb_pwr_p->current_lvl,
			    pci_pwr_new_lvl(ppb->ppb_pwr_p));
		}

		ppb->ppb_cache_line_size =
		    pci_config_get8(config_handle, PCI_CONF_CACHE_LINESZ);
		ppb->ppb_latency_timer =
		    pci_config_get8(config_handle, PCI_CONF_LATENCY_TIMER);

		/*
		 * Check whether the "ranges" property is present.
		 * Otherwise create the ranges property by reading
		 * the configuration registers
		 */
		if (ddi_prop_exists(DDI_DEV_T_ANY, devi, DDI_PROP_DONTPASS,
		    "ranges") == 0) {
			ppb_create_ranges_prop(devi, config_handle);
		}

		pci_config_teardown(&config_handle);

		if (PM_CAPABLE(ppb->ppb_pwr_p)) {
			ppb->ppb_pwr_p->pwr_fp--;

			pci_pwr_change(ppb->ppb_pwr_p,
			    ppb->ppb_pwr_p->current_lvl,
			    pci_pwr_new_lvl(ppb->ppb_pwr_p));

			mutex_exit(&ppb->ppb_pwr_p->pwr_mutex);
		}

		ppb->parent_bus = PCIE_PCIECAP_DEV_TYPE_PCI_PSEUDO;
		for (pdip = ddi_get_parent(ppb->dip); pdip && (pdip != root) &&
		    (ppb->parent_bus != PCIE_PCIECAP_DEV_TYPE_PCIE_DEV);
		    pdip = ddi_get_parent(pdip)) {
			if (ddi_prop_lookup_string(DDI_DEV_T_ANY, pdip,
			    DDI_PROP_DONTPASS, "device_type", &bus) !=
			    DDI_PROP_SUCCESS)
				break;

			if (strcmp(bus, "pciex") == 0)
				ppb->parent_bus =
				    PCIE_PCIECAP_DEV_TYPE_PCIE_DEV;

			ddi_prop_free(bus);
		}

		/*
		 * Initialize hotplug support on this bus.
		 */
		if (ppb->parent_bus == PCIE_PCIECAP_DEV_TYPE_PCIE_DEV)
			if (pcie_init(devi, NULL) != DDI_SUCCESS) {
				(void) ppb_detach(devi, DDI_DETACH);
				return (DDI_FAILURE);
			}
		else
			ppb_init_hotplug(ppb);

		DEBUG1(DBG_ATTACH, devi,
		    "ppb_attach(): this nexus %s hotplug slots\n",
		    ppb->hotplug_capable == B_TRUE ? "has":"has no");

		ppb_fm_init(ppb);
		ddi_report_dev(devi);

		return (DDI_SUCCESS);

	case DDI_RESUME:
		/*
		 * Get the soft state structure for the bridge.
		 */
		ppb = (ppb_devstate_t *)
		    ddi_get_soft_state(ppb_state, ddi_get_instance(devi));

		pci_pwr_resume(devi, ppb->ppb_pwr_p);

		return (DDI_SUCCESS);
	}
	return (DDI_FAILURE);
}
コード例 #2
0
ファイル: pci_pci.c プロジェクト: metricinc/illumos-gate
/*ARGSUSED*/
static int
ppb_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
{
	dev_info_t *root = ddi_root_node();
	int instance;
	ppb_devstate_t *ppb;
	dev_info_t *pdip;
	ddi_acc_handle_t config_handle;
	char *bus;
	int ret;

	switch (cmd) {
	case DDI_ATTACH:

		/*
		 * Make sure the "device_type" property exists.
		 */
		(void) ddi_prop_update_string(DDI_DEV_T_NONE, devi,
		    "device_type", "pci");

		/*
		 * Allocate and get soft state structure.
		 */
		instance = ddi_get_instance(devi);
		if (ddi_soft_state_zalloc(ppb_state, instance) != DDI_SUCCESS)
			return (DDI_FAILURE);
		ppb = ddi_get_soft_state(ppb_state, instance);
		ppb->dip = devi;

		/*
		 * don't enable ereports if immediate child of npe
		 */
		if (strcmp(ddi_driver_name(ddi_get_parent(devi)), "npe") == 0)
			ppb->ppb_fmcap = DDI_FM_ERRCB_CAPABLE |
			    DDI_FM_ACCCHK_CAPABLE | DDI_FM_DMACHK_CAPABLE;
		else
			ppb->ppb_fmcap = DDI_FM_EREPORT_CAPABLE |
			    DDI_FM_ERRCB_CAPABLE | DDI_FM_ACCCHK_CAPABLE |
			    DDI_FM_DMACHK_CAPABLE;

		ddi_fm_init(devi, &ppb->ppb_fmcap, &ppb->ppb_fm_ibc);
		mutex_init(&ppb->ppb_mutex, NULL, MUTEX_DRIVER, NULL);
		mutex_init(&ppb->ppb_err_mutex, NULL, MUTEX_DRIVER,
		    (void *)ppb->ppb_fm_ibc);
		mutex_init(&ppb->ppb_peek_poke_mutex, NULL, MUTEX_DRIVER,
		    (void *)ppb->ppb_fm_ibc);

		if (ppb->ppb_fmcap & (DDI_FM_ERRCB_CAPABLE |
		    DDI_FM_EREPORT_CAPABLE))
			pci_ereport_setup(devi);
		if (ppb->ppb_fmcap & DDI_FM_ERRCB_CAPABLE)
			ddi_fm_handler_register(devi, ppb_fm_callback, NULL);

		if (pci_config_setup(devi, &config_handle) != DDI_SUCCESS) {
			if (ppb->ppb_fmcap & DDI_FM_ERRCB_CAPABLE)
				ddi_fm_handler_unregister(devi);
			if (ppb->ppb_fmcap & (DDI_FM_ERRCB_CAPABLE |
			    DDI_FM_EREPORT_CAPABLE))
				pci_ereport_teardown(devi);
			ddi_fm_fini(devi);
			ddi_soft_state_free(ppb_state, instance);
			return (DDI_FAILURE);
		}

		ppb->parent_bus = PCIE_PCIECAP_DEV_TYPE_PCI_PSEUDO;
		for (pdip = ddi_get_parent(devi); pdip && (pdip != root) &&
		    (ppb->parent_bus != PCIE_PCIECAP_DEV_TYPE_PCIE_DEV);
		    pdip = ddi_get_parent(pdip)) {
			if (ddi_prop_lookup_string(DDI_DEV_T_ANY, pdip,
			    DDI_PROP_DONTPASS, "device_type", &bus) !=
			    DDI_PROP_SUCCESS)
				break;

			if (strcmp(bus, "pciex") == 0)
				ppb->parent_bus =
				    PCIE_PCIECAP_DEV_TYPE_PCIE_DEV;

			ddi_prop_free(bus);
		}

		if (ppb_support_ht_msimap == 1)
			(void) ppb_ht_msimap_set(config_handle,
			    HT_MSIMAP_ENABLE);
		else if (ppb_support_ht_msimap == -1)
			(void) ppb_ht_msimap_set(config_handle,
			    HT_MSIMAP_DISABLE);

		pci_config_teardown(&config_handle);

		/*
		 * Initialize hotplug support on this bus.
		 */
		if (ppb->parent_bus == PCIE_PCIECAP_DEV_TYPE_PCIE_DEV)
			ret = pcie_init(devi, NULL);
		else
			ret = pcihp_init(devi);

		if (ret != DDI_SUCCESS) {
			cmn_err(CE_WARN,
			    "pci: Failed to setup hotplug framework");
			(void) ppb_detach(devi, DDI_DETACH);
			return (ret);
		}

		ddi_report_dev(devi);
		return (DDI_SUCCESS);

	case DDI_RESUME:

		/*
		 * Get the soft state structure for the bridge.
		 */
		ppb = ddi_get_soft_state(ppb_state, ddi_get_instance(devi));
		ppb_restore_config_regs(ppb);
		return (DDI_SUCCESS);

	default:
		break;
	}
	return (DDI_FAILURE);
}