Ejemplo n.º 1
0
/*
 * get_pcmu_properties
 *
 * This function is called from the attach routine to get the key
 * properties of the pci nodes.
 *
 * used by: pcmu_attach()
 *
 * return value: DDI_FAILURE on failure
 */
int
get_pcmu_properties(pcmu_t *pcmu_p, dev_info_t *dip)
{
	int i;

	/*
	 * Get the device's port id.
	 */
	if ((pcmu_p->pcmu_id = (uint32_t)pcmu_get_portid(dip)) == -1u) {
		cmn_err(CE_WARN, "%s%d: no portid property\n",
		    ddi_driver_name(dip), ddi_get_instance(dip));
		return (DDI_FAILURE);
	}

	/*
	 * Get the bus-ranges property.
	 */
	i = sizeof (pcmu_p->pcmu_bus_range);
	if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
	    "bus-range", (caddr_t)&pcmu_p->pcmu_bus_range, &i) != DDI_SUCCESS) {
		cmn_err(CE_WARN, "%s%d: no bus-range property\n",
		    ddi_driver_name(dip), ddi_get_instance(dip));
		return (DDI_FAILURE);
	}
	PCMU_DBG2(PCMU_DBG_ATTACH, dip,
	    "get_pcmu_properties: bus-range (%x,%x)\n",
	    pcmu_p->pcmu_bus_range.lo, pcmu_p->pcmu_bus_range.hi);

	/*
	 * Get the ranges property.
	 */
	if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "ranges",
	    (caddr_t)&pcmu_p->pcmu_ranges, &pcmu_p->pcmu_ranges_length) !=
	    DDI_SUCCESS) {
		cmn_err(CE_WARN, "%s%d: no ranges property\n",
		    ddi_driver_name(dip), ddi_get_instance(dip));
		return (DDI_FAILURE);
	}
	pcmu_fix_ranges(pcmu_p->pcmu_ranges,
	    pcmu_p->pcmu_ranges_length / sizeof (pcmu_ranges_t));

	/*
	 * Determine the number upa slot interrupts.
	 */
	pcmu_p->pcmu_numproxy = pcmu_get_numproxy(pcmu_p->pcmu_dip);
	PCMU_DBG1(PCMU_DBG_ATTACH, dip, "get_pcmu_properties: numproxy=%d\n",
	    pcmu_p->pcmu_numproxy);
	return (DDI_SUCCESS);
}
Ejemplo n.º 2
0
/*
 * If the device is a PCI bus device (i.e bus-range property exists) then
 * claim the bus numbers used by the device from the specified bus
 * resource map.
 */
static int
claim_pci_busnum(dev_info_t *dip, void *arg)
{
	struct bus_range pci_bus_range;
	struct busnum_ctrl *ctrl;
	ndi_ra_request_t req;
	char bus_type[16] = "(unknown)";
	int len;
	uint64_t base;
	uint64_t retlen;

	ctrl = (struct busnum_ctrl *)arg;

	/* check if this is a PCI bus node */
	len = sizeof (bus_type);
	if (ddi_prop_op(DDI_DEV_T_ANY, dip, PROP_LEN_AND_VAL_BUF,
	    DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS, "device_type",
	    (caddr_t)&bus_type, &len) != DDI_SUCCESS)
		return (DDI_WALK_PRUNECHILD);

	/* it is not a pci/pci-ex bus type */
	if ((strcmp(bus_type, "pci") != 0) && (strcmp(bus_type, "pciex") != 0))
		return (DDI_WALK_PRUNECHILD);

	/* look for the bus-range property */
	len = sizeof (struct bus_range);
	if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
	    "bus-range", (caddr_t)&pci_bus_range, &len) == DDI_SUCCESS) {
		if ((pci_bus_range.lo >= ctrl->range->lo) &&
		    (pci_bus_range.hi <= ctrl->range->hi)) {

			/* claim the bus range from the bus resource map */
			bzero((caddr_t)&req, sizeof (req));
			req.ra_addr = (uint64_t)pci_bus_range.lo;
			req.ra_flags |= NDI_RA_ALLOC_SPECIFIED;
			req.ra_len = (uint64_t)pci_bus_range.hi -
			    (uint64_t)pci_bus_range.lo + 1;
			if (ndi_ra_alloc(ctrl->dip, &req, &base, &retlen,
			    NDI_RA_TYPE_PCI_BUSNUM, 0) == NDI_SUCCESS)
				return (DDI_WALK_PRUNECHILD);
		}
	}

	/*
	 * Error return.
	 */
	ctrl->rv = DDI_FAILURE;
	return (DDI_WALK_TERMINATE);
}
Ejemplo n.º 3
0
/*
 * Get boot property value for fastreboot_onpanic.
 *
 * NOTE: If fastreboot_onpanic is set to non-zero in /etc/system,
 * new setting passed in via "-B fastreboot_onpanic" is ignored.
 * This order of precedence is to enable developers debugging panics
 * that occur early in boot to utilize Fast Reboot on panic.
 */
static void
fastboot_get_bootprop(void)
{
	int		val = 0xaa, len, ret;
	dev_info_t	*devi;
	char		*propstr = NULL;

	devi = ddi_root_node();

	ret = ddi_prop_lookup_string(DDI_DEV_T_ANY, devi, DDI_PROP_DONTPASS,
	    FASTREBOOT_ONPANIC, &propstr);

	if (ret == DDI_PROP_SUCCESS) {
		if (FASTREBOOT_ONPANIC_NOTSET(propstr))
			val = 0;
		else if (FASTREBOOT_ONPANIC_ISSET(propstr))
			val = UA_FASTREBOOT_ONPANIC;

		/*
		 * Only set fastreboot_onpanic to the value passed in
		 * if it's not already set to non-zero, and the value
		 * has indeed been passed in via command line.
		 */
		if (!fastreboot_onpanic && val != 0xaa)
			fastreboot_onpanic = val;
		ddi_prop_free(propstr);
	} else if (ret != DDI_PROP_NOT_FOUND && ret != DDI_PROP_UNDEFINED) {
		cmn_err(CE_NOTE, "!%s value is invalid, will be ignored",
		    FASTREBOOT_ONPANIC);
	}

	len = sizeof (fastreboot_onpanic_cmdline);
	ret = ddi_getlongprop_buf(DDI_DEV_T_ANY, devi, DDI_PROP_DONTPASS,
	    FASTREBOOT_ONPANIC_CMDLINE, fastreboot_onpanic_cmdline, &len);

	if (ret == DDI_PROP_BUF_TOO_SMALL)
		cmn_err(CE_NOTE, "!%s value is too long, will be ignored",
		    FASTREBOOT_ONPANIC_CMDLINE);
}
Ejemplo n.º 4
0
/*
 * Setup resource map for the pci bus node based on the "available"
 * property and "bus-range" property.
 */
int
pci_resource_setup(dev_info_t *dip)
{
	pci_regspec_t *regs;
	int rlen, rcount, i;
	char bus_type[16] = "(unknown)";
	int len;
	struct busnum_ctrl ctrl;
	int circular_count;
	int rval = NDI_SUCCESS;

	/*
	 * If this is a pci bus node then look for "available" property
	 * to find the available resources on this bus.
	 */
	len = sizeof (bus_type);
	if (ddi_prop_op(DDI_DEV_T_ANY, dip, PROP_LEN_AND_VAL_BUF,
	    DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS, "device_type",
	    (caddr_t)&bus_type, &len) != DDI_SUCCESS)
		return (NDI_FAILURE);

	/* it is not a pci/pci-ex bus type */
	if ((strcmp(bus_type, "pci") != 0) && (strcmp(bus_type, "pciex") != 0))
		return (NDI_FAILURE);

	/*
	 * The pci-hotplug project addresses adding the call
	 * to pci_resource_setup from pci nexus driver.
	 * However that project would initially be only for x86,
	 * so for sparc pcmcia-pci support we still need to call
	 * pci_resource_setup in pcic driver. Once all pci nexus drivers
	 * are updated to call pci_resource_setup this portion of the
	 * code would really become an assert to make sure this
	 * function is not called for the same dip twice.
	 */
	{
		if (ra_map_exist(dip, NDI_RA_TYPE_MEM) == NDI_SUCCESS) {
			return (NDI_FAILURE);
		}
	}


	/*
	 * Create empty resource maps first.
	 *
	 * NOTE: If all the allocated resources are already assigned to
	 * device(s) in the hot plug slot then "available" property may not
	 * be present. But, subsequent hot plug operation may unconfigure
	 * the device in the slot and try to free up it's resources. So,
	 * at the minimum we should create empty maps here.
	 */
	if (ndi_ra_map_setup(dip, NDI_RA_TYPE_MEM) == NDI_FAILURE) {
		return (NDI_FAILURE);
	}

	if (ndi_ra_map_setup(dip, NDI_RA_TYPE_IO) == NDI_FAILURE) {
		return (NDI_FAILURE);
	}

	if (ndi_ra_map_setup(dip, NDI_RA_TYPE_PCI_BUSNUM) == NDI_FAILURE) {
		return (NDI_FAILURE);
	}

	if (ndi_ra_map_setup(dip, NDI_RA_TYPE_PCI_PREFETCH_MEM) ==
	    NDI_FAILURE) {
		return (NDI_FAILURE);
	}

	/* read the "available" property if it is available */
	if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
	    "available", (caddr_t)&regs, &rlen) == DDI_SUCCESS) {
		/*
		 * create the available resource list for both memory and
		 * io space
		 */
		rcount = rlen / sizeof (pci_regspec_t);
		for (i = 0; i < rcount; i++) {
		    switch (PCI_REG_ADDR_G(regs[i].pci_phys_hi)) {
		    case PCI_REG_ADDR_G(PCI_ADDR_MEM32):
			(void) ndi_ra_free(dip,
			    (uint64_t)regs[i].pci_phys_low,
			    (uint64_t)regs[i].pci_size_low,
			    (regs[i].pci_phys_hi & PCI_REG_PF_M) ?
			    NDI_RA_TYPE_PCI_PREFETCH_MEM : NDI_RA_TYPE_MEM,
			    0);
			break;
		    case PCI_REG_ADDR_G(PCI_ADDR_MEM64):
			(void) ndi_ra_free(dip,
			    ((uint64_t)(regs[i].pci_phys_mid) << 32) |
			    ((uint64_t)(regs[i].pci_phys_low)),
			    ((uint64_t)(regs[i].pci_size_hi) << 32) |
			    ((uint64_t)(regs[i].pci_size_low)),
			    (regs[i].pci_phys_hi & PCI_REG_PF_M) ?
			    NDI_RA_TYPE_PCI_PREFETCH_MEM : NDI_RA_TYPE_MEM,
			    0);
			break;
		    case PCI_REG_ADDR_G(PCI_ADDR_IO):
			(void) ndi_ra_free(dip,
			    (uint64_t)regs[i].pci_phys_low,
			    (uint64_t)regs[i].pci_size_low,
			    NDI_RA_TYPE_IO,
			    0);
			break;
		    case PCI_REG_ADDR_G(PCI_ADDR_CONFIG):
			break;
		    default:
			cmn_err(CE_WARN,
			    "pci_resource_setup: bad addr type: %x\n",
			    PCI_REG_ADDR_G(regs[i].pci_phys_hi));
			break;
		    }
		}
		kmem_free((caddr_t)regs, rlen);
	}

	/*
	 * update resource map for available bus numbers if the node
	 * has available-bus-range or bus-range property.
	 */
	len = sizeof (struct bus_range);
	if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
	    "available-bus-range", (caddr_t)&pci_bus_range, &len) ==
	    DDI_SUCCESS) {
		/*
		 * Add bus numbers in the range to the free list.
		 */
		(void) ndi_ra_free(dip, (uint64_t)pci_bus_range.lo,
		    (uint64_t)pci_bus_range.hi - (uint64_t)pci_bus_range.lo +
		    1, NDI_RA_TYPE_PCI_BUSNUM, 0);
	} else {
		/*
		 * We don't have an available-bus-range property. If, instead,
		 * we have a bus-range property we add all the bus numbers
		 * in that range to the free list but we must then scan
		 * for pci-pci bridges on this bus to find out the if there
		 * are any of those bus numbers already in use. If so, we can
		 * reclaim them.
		 */
		len = sizeof (struct bus_range);
		if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip,
		    DDI_PROP_DONTPASS, "bus-range", (caddr_t)&pci_bus_range,
		    &len) == DDI_SUCCESS) {
			if (pci_bus_range.lo != pci_bus_range.hi) {
				/*
				 * Add bus numbers other than the secondary
				 * bus number to the free list.
				 */
				(void) ndi_ra_free(dip,
				    (uint64_t)pci_bus_range.lo + 1,
				    (uint64_t)pci_bus_range.hi -
				    (uint64_t)pci_bus_range.lo,
				    NDI_RA_TYPE_PCI_BUSNUM, 0);

				/* scan for pci-pci bridges */
				ctrl.rv = DDI_SUCCESS;
				ctrl.dip = dip;
				ctrl.range = &pci_bus_range;
				ndi_devi_enter(dip, &circular_count);
				ddi_walk_devs(ddi_get_child(dip),
				    claim_pci_busnum, (void *)&ctrl);
				ndi_devi_exit(dip, circular_count);
				if (ctrl.rv != DDI_SUCCESS) {
					/* failed to create the map */
					(void) ndi_ra_map_destroy(dip,
					    NDI_RA_TYPE_PCI_BUSNUM);
					rval = NDI_FAILURE;
				}
			}
		}
	}

#ifdef BUSRA_DEBUG
	if (busra_debug) {
		(void) ra_dump_all(NULL, dip);
	}
#endif

	return (rval);
}
Ejemplo n.º 5
0
/*ARGSUSED*/
static int
xen_uppc_translate_irq(dev_info_t *dip, int irqno)
{
	char dev_type[16];
	int dev_len, pci_irq, devid, busid;
	ddi_acc_handle_t cfg_handle;
	uchar_t ipin, iline;
	iflag_t intr_flag;

	if (dip == NULL) {
		XEN_UPPC_VERBOSE_IRQ((CE_CONT, "!xVM_uppc: irqno = %d"
		    " dip = NULL\n", irqno));
		return (irqno);
	}

	if (!xen_uppc_enable_acpi) {
		return (irqno);
	}

	dev_len = sizeof (dev_type);
	if (ddi_getlongprop_buf(DDI_DEV_T_ANY, ddi_get_parent(dip),
	    DDI_PROP_DONTPASS, "device_type", (caddr_t)dev_type,
	    &dev_len) != DDI_PROP_SUCCESS) {
		XEN_UPPC_VERBOSE_IRQ((CE_CONT, "!xVM_uppc: irqno %d"
		    " device %s instance %d no device_type\n", irqno,
		    ddi_get_name(dip), ddi_get_instance(dip)));
		return (irqno);
	}

	if ((strcmp(dev_type, "pci") == 0) ||
	    (strcmp(dev_type, "pciex") == 0)) {

		/* pci device */
		if (acpica_get_bdf(dip, &busid, &devid, NULL) != 0)
			return (irqno);

		if (pci_config_setup(dip, &cfg_handle) != DDI_SUCCESS)
			return (irqno);

		ipin = pci_config_get8(cfg_handle, PCI_CONF_IPIN) - PCI_INTA;
		iline = pci_config_get8(cfg_handle, PCI_CONF_ILINE);
		if (xen_uppc_acpi_translate_pci_irq(dip, busid, devid,
		    ipin, &pci_irq, &intr_flag) == ACPI_PSM_SUCCESS) {

			XEN_UPPC_VERBOSE_IRQ((CE_CONT, "!xVM_uppc: [ACPI] "
			    "new irq %d old irq %d device %s, instance %d\n",
			    pci_irq, irqno, ddi_get_name(dip),
			    ddi_get_instance(dip)));

			/*
			 * Make sure pci_irq is within range.
			 * Otherwise, fall through and return irqno.
			 */
			if (pci_irq <= MAX_ISA_IRQ) {
				if (iline != pci_irq) {
					/*
					 * Update the device's ILINE byte,
					 * in case uppc_acpi_translate_pci_irq
					 * has choosen a different pci_irq
					 * than the BIOS has configured.
					 * Some chipsets use the value in
					 * ILINE to control interrupt routing,
					 * in conflict with the PCI spec.
					 */
					pci_config_put8(cfg_handle,
					    PCI_CONF_ILINE, pci_irq);
				}
				pci_config_teardown(&cfg_handle);
				return (pci_irq);
			}
		}
		pci_config_teardown(&cfg_handle);

		/* FALLTHRU to common case - returning irqno */
	} else {
		/* non-PCI; assumes ISA-style edge-triggered */
		psm_set_elcr(irqno, 0); 	/* set IRQ to ISA mode */

		XEN_UPPC_VERBOSE_IRQ((CE_CONT, "!xVM_uppc: non-pci,"
		    "irqno %d device %s instance %d\n", irqno,
		    ddi_get_name(dip), ddi_get_instance(dip)));
	}

	return (irqno);
}