Ejemplo n.º 1
0
/*ARGSUSED*/
static int
smb_open(dev_t *dp, int flag, int otyp, cred_t *cred)
{
	minor_t c;

	if (ksmbios == NULL)
		return (ENXIO);

	/*
	 * Locate and reserve a clone structure.  We skip clone 0 as that is
	 * the real minor number, and we assign a new minor to each clone.
	 */
	for (c = 1; c < smb_nclones; c++) {
		if (casptr(&smb_clones[c].c_hdl, NULL, ksmbios) == NULL)
			break;
	}

	if (c >= smb_nclones)
		return (EAGAIN);

	smb_clones[c].c_eplen = P2ROUNDUP(sizeof (smbios_entry_t), 16);
	smb_clones[c].c_stlen = smbios_buflen(smb_clones[c].c_hdl);

	*dp = makedevice(getemajor(*dp), c);

	(void) ddi_prop_update_int(*dp, smb_devi, "size",
	    smb_clones[c].c_eplen + smb_clones[c].c_stlen);

	return (0);
}
Ejemplo n.º 2
0
/*
 * Create properties of various data types for testing devfs events.
 */
static int
gen_create_properties(dev_info_t *devi)
{
	int int_val = 3023;
	int int_array[] = { 3, 10, 304, 230, 4};
	int64_t int64_val = 20;
	int64_t int64_array[] = { 12, 24, 36, 48};
	char *string_val = "Dev_node_prop";
	char *string_array[] = {"Dev_node_prop:0",
	    "Dev_node_prop:1", "Dev_node_prop:2", "Dev_node_prop:3"};
	uchar_t byte_array[] = { (uchar_t)0xaa, (uchar_t)0x55,
	    (uchar_t)0x12, (uchar_t)0xcd };
	char bytes[] = { (char)0x00, (char)0xef, (char)0xff };

	if (ddi_prop_update_int(DDI_DEV_T_NONE, devi, "int", int_val)
	    != DDI_PROP_SUCCESS)
		return (DDI_FAILURE);

	if (ddi_prop_update_int_array(DDI_DEV_T_NONE, devi, "int-array",
	    int_array, sizeof (int_array) / sizeof (int)) != DDI_PROP_SUCCESS)
		return (DDI_FAILURE);

	if (ddi_prop_update_int64(DDI_DEV_T_NONE, devi, "int64", int64_val)
	    != DDI_PROP_SUCCESS)
		return (DDI_FAILURE);

	if (ddi_prop_update_int64_array(DDI_DEV_T_NONE, devi, "int64-array",
	    int64_array, sizeof (int64_array) / sizeof (int64_t))
	    != DDI_PROP_SUCCESS)
		return (DDI_FAILURE);

	if (ddi_prop_update_string(DDI_DEV_T_NONE, devi, "string", string_val)
	    != DDI_PROP_SUCCESS)
		return (DDI_FAILURE);

	if (ddi_prop_update_string_array(DDI_DEV_T_NONE, devi, "string-array",
	    string_array, sizeof (string_array) / sizeof (char *))
	    != DDI_PROP_SUCCESS)
		return (DDI_FAILURE);

	if (ddi_prop_create(DDI_DEV_T_NONE, devi, DDI_PROP_CANSLEEP,
	    "boolean", NULL, 0) != DDI_PROP_SUCCESS)
		return (DDI_FAILURE);

	if (ddi_prop_update_byte_array(DDI_DEV_T_NONE, devi, "byte-array",
	    byte_array, sizeof (byte_array)) != DDI_PROP_SUCCESS)
		return (DDI_FAILURE);

	/* untyped property */
	if (ddi_prop_create(DDI_DEV_T_NONE, devi, DDI_PROP_CANSLEEP, "untyped",
	    (caddr_t)bytes, sizeof (bytes)) != DDI_PROP_SUCCESS)
		return (DDI_FAILURE);

	return (DDI_SUCCESS);
}
Ejemplo n.º 3
0
/* ARGSUSED */
static int
ksyms_open(dev_t *devp, int flag, int otyp, struct cred *cred)
{
	minor_t clone;
	size_t size = 0;
	size_t realsize;
	char *addr;
	void *hptr = NULL;
	ksyms_buflist_hdr_t hdr;
	bzero(&hdr, sizeof (struct ksyms_buflist_hdr));
	list_create(&hdr.blist, PAGESIZE,
	    offsetof(ksyms_buflist_t, buflist_node));

	if (getminor(*devp) != 0)
		return (ENXIO);

	for (;;) {
		realsize = ksyms_snapshot(ksyms_bcopy, hptr, size);
		if (realsize <= size)
			break;
		size = realsize;
		size = ksyms_buflist_alloc(&hdr, size);
		if (size == 0)
			return (ENOMEM);
		hptr = (void *)&hdr;
	}

	addr = ksyms_mapin(&hdr, realsize);
	ksyms_buflist_free(&hdr);
	if (addr == NULL)
		return (EOVERFLOW);

	/*
	 * Reserve a clone entry.  Note that we don't use clone 0
	 * since that's the "real" minor number.
	 */
	for (clone = 1; clone < nksyms_clones; clone++) {
		if (atomic_cas_ptr(&ksyms_clones[clone].ksyms_base, 0, addr) ==
		    0) {
			ksyms_clones[clone].ksyms_size = realsize;
			*devp = makedevice(getemajor(*devp), clone);
			(void) ddi_prop_update_int(*devp, ksyms_devi,
			    "size", realsize);
			modunload_disable();
			return (0);
		}
	}
	cmn_err(CE_NOTE, "ksyms: too many open references");
	(void) as_unmap(curproc->p_as, addr, roundup(realsize, PAGESIZE));
	return (ENXIO);
}
Ejemplo n.º 4
0
static int
acpinex_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
{
	int instance;
	acpinex_softstate_t *softsp;

	instance = ddi_get_instance(devi);
	if (instance >= ACPINEX_INSTANCE_MAX) {
		cmn_err(CE_WARN, "acpinex: instance number %d is out of range "
		    "in acpinex_detach(), max %d.",
		    instance, ACPINEX_INSTANCE_MAX - 1);
		return (DDI_FAILURE);
	}

	softsp = ddi_get_soft_state(acpinex_softstates, instance);
	if (softsp == NULL) {
		ACPINEX_DEBUG(CE_WARN, "!acpinex: failed to get soft state "
		    "object for instance %d in acpinex_detach()", instance);
		return (DDI_FAILURE);
	}

	switch (cmd) {
	case DDI_DETACH:
		if (acpinex_event_scan(softsp, B_FALSE) != DDI_SUCCESS) {
			cmn_err(CE_WARN, "!acpinex: failed to uninstall event "
			    "handler for children of %s.", softsp->ans_path);
			return (DDI_FAILURE);
		}
		ddi_remove_minor_node(devi, NULL);
		acpinex_fm_fini(softsp);
		mutex_destroy(&softsp->ans_lock);
		ddi_soft_state_free(acpinex_softstates, instance);
		(void) ddi_prop_update_int(DDI_DEV_T_NONE, devi,
		    DDI_NO_AUTODETACH, 0);
		return (DDI_SUCCESS);

	case DDI_SUSPEND:
		return (DDI_SUCCESS);

	default:
		return (DDI_FAILURE);
	}
}
Ejemplo n.º 5
0
/*
 * save config regs for HyperTransport devices without drivers of classes:
 * memory controller and hostbridge
 */
int
npe_save_htconfig_children(dev_info_t *dip)
{
	dev_info_t *cdip = ddi_get_child(dip);
	ddi_acc_handle_t cfg_hdl;
	uint16_t ptr;
	int rval = DDI_SUCCESS;
	uint8_t cl, scl;

	for (; cdip != NULL; cdip = ddi_get_next_sibling(cdip)) {
		if (ddi_driver_major(cdip) != DDI_MAJOR_T_NONE)
			continue;

		if (pci_config_setup(cdip, &cfg_hdl) != DDI_SUCCESS)
			return (DDI_FAILURE);

		cl = pci_config_get8(cfg_hdl, PCI_CONF_BASCLASS);
		scl = pci_config_get8(cfg_hdl, PCI_CONF_SUBCLASS);

		if (((cl == PCI_CLASS_MEM && scl == PCI_MEM_RAM) ||
		    (cl == PCI_CLASS_BRIDGE && scl == PCI_BRIDGE_HOST)) &&
		    pci_htcap_locate(cfg_hdl, 0, 0, &ptr) == DDI_SUCCESS) {

			if (pci_save_config_regs(cdip) != DDI_SUCCESS) {
				cmn_err(CE_WARN, "Failed to save HT config "
				    "regs for %s\n", ddi_node_name(cdip));
				rval = DDI_FAILURE;

			} else if (ddi_prop_update_int(DDI_DEV_T_NONE, cdip,
			    "htconfig-saved", 1) != DDI_SUCCESS) {
				cmn_err(CE_WARN, "Failed to set htconfig-saved "
				    "property for %s\n", ddi_node_name(cdip));
				rval = DDI_FAILURE;
			}
		}

		pci_config_teardown(&cfg_hdl);
	}

	return (rval);
}
Ejemplo n.º 6
0
/*
 * Controller specific initialization
 */
uint_t
sil3xxx_init_controller(dev_info_t *dip,
	/* LINTED */
	ushort_t vendor_id, ushort_t device_id)
{
	ddi_acc_handle_t  pci_conf_handle; /* pci config space handle */
	uint8_t cache_lnsz, frrc = 0;
	uint32_t fifo_cnt_ctl;
	int ports, i;

#ifdef	DEBUG
	/* LINTED */
	ushort_t sfiscfg_val;
#endif

	/*
	 * Sil3114, Sil3512, Sil3112
	 * We want to perform this initialization only once per entire
	 * pciide controller (all channels)
	 */
	if (ddi_prop_exists(DDI_DEV_T_ANY, ddi_get_parent(dip),
		DDI_PROP_DONTPASS, "sil3xxx-initialized")) {
		return (TRUE);
	}

	if (pci_config_setup(ddi_get_parent(dip), &pci_conf_handle) !=
	    DDI_SUCCESS) {
		cmn_err(CE_WARN,
		    "sil3xxx_init_controller: Can't do pci_config_setup\n");
		return (FALSE);
	}

	/*
	 * Sil3114/3512/3112 incorrectly change between MR and back to
	 * MRM for same transaction, which violates the PCI spec and can
	 * lead to incorrect data reads.  The workaround
	 * is to set bits 2:0 in the FIFO count and control register so
	 * that its value, a multiple of 32 bytes starting at 32, not 0,
	 * is greater or equal to the cacheline size, a multiple of 4
	 * bytes.  This will prevent any reads until the FIFO free space
	 * is greater than a cacheline size, ensuring only MRM is issued.
	 */

	cache_lnsz = pci_config_get8(pci_conf_handle, PCI_CONF_CACHE_LINESZ);

	/*
	 * The cache line is specified in 32-bit words, so multiply by 4
	 * to get bytes.  Then divide by 32 bytes, the granularity of the
	 * FIFO control bits 2:0.  Add 1 if there is any remainder to
	 * account for a partial 32-byte block, then subtract 1 since for
	 * FIFO controls bits 2:0, 0 corresponds to 32, 1 corresponds to
	 * 64, and so on.  The calculation is expanded for clarity.
	 */
	if (cache_lnsz != 0) {
		frrc = (cache_lnsz * 4 / 32) +
			(((cache_lnsz * 4) % 32) ? 1 : 0) - 1;
	}

	if (device_id == SIL3114_DEVICE_ID) {
		ports = 4;
	} else {
		ports = 2;
	}

	/*
	 * The following BAR5 registers are accessed via an indirect register
	 * in the PCI configuration space rather than mapping BAR5.
	 */
	for (i = 0; i < ports; i++) {
		GET_BAR5_INDIRECT(pci_conf_handle, fifocntctl[i],
		    fifo_cnt_ctl);
		fifo_cnt_ctl = (fifo_cnt_ctl & ~0x7) | (frrc & 0x7);
		PUT_BAR5_INDIRECT(pci_conf_handle, fifocntctl[i],
		    fifo_cnt_ctl);
		/*
		 * Correct default setting for FIS0cfg
		 */
#ifdef	DEBUG
		GET_BAR5_INDIRECT(pci_conf_handle, sfiscfg[i],
			sfiscfg_val);
		ADBG_WARN(("sil3xxx_init_controller: old val SFISCfg "
			"ch%d: %x\n", i, sfiscfg_val));
#endif
		PUT_BAR5_INDIRECT(pci_conf_handle, sfiscfg[i],
			SFISCFG_ERRATA);
#ifdef	DEBUG
		GET_BAR5_INDIRECT(pci_conf_handle, sfiscfg[i],
			sfiscfg_val);
		ADBG_WARN(("sil3xxx_init_controller: new val SFISCfg "
			"ch%d: %x\n", i, sfiscfg_val));
#endif
	}

	/* Now tear down the pci config setup */
	pci_config_teardown(&pci_conf_handle);

	/* Create property indicating that initialization was done */
	(void) ddi_prop_update_int(DDI_DEV_T_NONE, ddi_get_parent(dip),
		"sil3xxx-initialized", 1);

	return (TRUE);
}
Ejemplo n.º 7
0
/*
 * attach the module
 */
static int
tvhci_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
{
	char *vclass;
	int instance, vhci_regis = 0;
	struct tvhci_state *vhci = NULL;
	dev_info_t *pdip;

	instance = ddi_get_instance(dip);

	switch (cmd) {
	case DDI_ATTACH:
		break;

	case DDI_RESUME:
	case DDI_PM_RESUME:
		return (0);	/* nothing to do */

	default:
		return (DDI_FAILURE);
	}

	/*
	 * Allocate vhci data structure.
	 */
	if (ddi_soft_state_zalloc(tvhci_state, instance) != DDI_SUCCESS) {
		return (DDI_FAILURE);
	}

	vhci = ddi_get_soft_state(tvhci_state, instance);
	ASSERT(vhci != NULL);
	vhci->dip = dip;

	/* parent must be /pshot */
	pdip = ddi_get_parent(dip);
	if (strcmp(ddi_driver_name(pdip), "pshot") != 0 ||
	    ddi_get_parent(pdip) != ddi_root_node()) {
		cmn_err(CE_NOTE, "tvhci must be under /pshot/");
		goto attach_fail;
	}

	/*
	 * XXX add mpxio-disable property. need to remove the check
	 *	from the framework
	 */
	(void) ddi_prop_update_string(DDI_DEV_T_NONE, dip,
	    "mpxio-disable", "no");

	/* bus_addr is the <vhci_class> */
	vclass = ddi_get_name_addr(dip);
	if (vclass == NULL || vclass[1] == '\0') {
		cmn_err(CE_NOTE, "tvhci invalid vhci class");
		goto attach_fail;
	}

	/*
	 * Attach this instance with the mpxio framework
	 */
	if (mdi_vhci_register(vclass, dip, &tvhci_opinfo, 0) != MDI_SUCCESS) {
		cmn_err(CE_WARN, "%s mdi_vhci_register failed",
		    ddi_node_name(dip));
		goto attach_fail;
	}
	vhci_regis++;

	if (ddi_create_minor_node(dip, "devctl", S_IFCHR,
	    instance, DDI_NT_SCSI_NEXUS, 0) != DDI_SUCCESS) {
		cmn_err(CE_NOTE, "%s ddi_create_minor_node failed",
		    ddi_node_name(dip));
		goto attach_fail;
	}

	(void) ddi_prop_update_int(DDI_DEV_T_NONE, dip, DDI_NO_AUTODETACH, 1);
	ddi_report_dev(dip);
	return (DDI_SUCCESS);

attach_fail:
	if (vhci_regis)
		(void) mdi_vhci_unregister(dip, 0);

	ddi_soft_state_free(tvhci_state, instance);
	return (DDI_FAILURE);
}
Ejemplo n.º 8
0
/*
 * attach the module
 */
static int
tphci_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
{
	char *vclass;
	int instance, phci_regis = 0;
	struct tphci_state *phci = NULL;

	instance = ddi_get_instance(dip);

	switch (cmd) {
	case DDI_ATTACH:
		break;

	case DDI_RESUME:
	case DDI_PM_RESUME:
		return (0);	/* nothing to do */

	default:
		return (DDI_FAILURE);
	}

	/*
	 * Allocate phci data structure.
	 */
	if (ddi_soft_state_zalloc(tphci_state, instance) != DDI_SUCCESS) {
		return (DDI_FAILURE);
	}

	phci = ddi_get_soft_state(tphci_state, instance);
	ASSERT(phci != NULL);
	phci->dip = dip;

	/* bus_addr has the form #,<vhci_class> */
	vclass = strchr(ddi_get_name_addr(dip), ',');
	if (vclass == NULL || vclass[1] == '\0') {
		cmn_err(CE_NOTE, "tphci invalid bus_addr %s",
		    ddi_get_name_addr(dip));
		goto attach_fail;
	}

	/*
	 * Attach this instance with the mpxio framework
	 */
	if (mdi_phci_register(vclass + 1, dip, 0) != MDI_SUCCESS) {
		cmn_err(CE_WARN, "%s mdi_phci_register failed",
		    ddi_node_name(dip));
		goto attach_fail;
	}
	phci_regis++;

	if (ddi_create_minor_node(dip, "devctl", S_IFCHR,
	    instance, DDI_NT_SCSI_NEXUS, 0) != DDI_SUCCESS) {
		cmn_err(CE_NOTE, "%s ddi_create_minor_node failed",
		    ddi_node_name(dip));
		goto attach_fail;
	}

	(void) ddi_prop_update_int(DDI_DEV_T_NONE, dip, DDI_NO_AUTODETACH, 1);
	ddi_report_dev(dip);
	return (DDI_SUCCESS);

attach_fail:
	if (phci_regis)
		(void) mdi_phci_unregister(dip, 0);

	ddi_soft_state_free(tphci_state, instance);
	return (DDI_FAILURE);
}
Ejemplo n.º 9
0
int
gfxp_vgatext_attach(dev_info_t *devi, ddi_attach_cmd_t cmd,
	gfxp_vgatext_softc_ptr_t ptr)
{
	struct vgatext_softc *softc = (struct vgatext_softc *)ptr;
	int	unit = ddi_get_instance(devi);
	int	error;
	char	*parent_type = NULL;
	int	reg_rnumber;
	off_t	reg_offset;
	off_t	mem_offset;
	char	*cons;
	int pci_pcie_bus = 0;
	int value;

	switch (cmd) {
	case DDI_ATTACH:
		break;

	case DDI_RESUME:
		vgatext_resume(softc);
		return (DDI_SUCCESS);

	default:
		return (DDI_FAILURE);
	}

	/* DDI_ATTACH */

	softc->devi = devi; /* Copy and init DEVI */

	softc->polledio.arg = (struct vis_polledio_arg *)softc;
	softc->polledio.display = vgatext_polled_display;
	softc->polledio.copy = vgatext_polled_copy;
	softc->polledio.cursor = vgatext_polled_cursor;

	mutex_init(&(softc->lock), NULL, MUTEX_DRIVER, NULL);

	error = ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_get_parent(devi),
	    DDI_PROP_DONTPASS, "device_type", &parent_type);
	if (error != DDI_SUCCESS) {
		cmn_err(CE_WARN, MYNAME ": can't determine parent type.");
		goto fail;
	}

	/* Not enable AGP and DRM by default */
	if (STREQ(parent_type, "isa") || STREQ(parent_type, "eisa")) {
		reg_rnumber = vgatext_get_isa_reg_index(devi, 1, VGA_REG_ADDR,
		    &reg_offset);
		if (reg_rnumber < 0) {
			cmn_err(CE_WARN,
			    MYNAME
			    ": can't find reg entry for registers");
			error = DDI_FAILURE;
			goto fail;
		}
		softc->fb_regno = vgatext_get_isa_reg_index(devi, 0,
		    VGA_MEM_ADDR, &mem_offset);
		if (softc->fb_regno < 0) {
			cmn_err(CE_WARN,
			    MYNAME
			    ": can't find reg entry for memory");
			error = DDI_FAILURE;
			goto fail;
		}
	} else if (STREQ(parent_type, "pci") || STREQ(parent_type, "pciex")) {
		pci_pcie_bus = 1;
		reg_rnumber = vgatext_get_pci_reg_index(devi,
		    PCI_REG_ADDR_M|PCI_REG_REL_M,
		    PCI_ADDR_IO|PCI_RELOCAT_B, VGA_REG_ADDR,
		    &reg_offset);
		if (reg_rnumber < 0) {
			cmn_err(CE_WARN,
			    MYNAME
			    ": can't find reg entry for registers");
			error = DDI_FAILURE;
			goto fail;
		}
		softc->fb_regno = vgatext_get_pci_reg_index(devi,
		    PCI_REG_ADDR_M|PCI_REG_REL_M,
		    PCI_ADDR_MEM32|PCI_RELOCAT_B, VGA_MEM_ADDR,
		    &mem_offset);
		if (softc->fb_regno < 0) {
			cmn_err(CE_WARN,
			    MYNAME
			    ": can't find reg entry for memory");
			error = DDI_FAILURE;
			goto fail;
		}
	} else {
		cmn_err(CE_WARN, MYNAME ": unknown parent type \"%s\".",
		    parent_type);
		error = DDI_FAILURE;
		goto fail;
	}
	ddi_prop_free(parent_type);
	parent_type = NULL;

	error = ddi_regs_map_setup(devi, reg_rnumber,
	    (caddr_t *)&softc->regs.addr, reg_offset, VGA_REG_SIZE,
	    &dev_attr, &softc->regs.handle);
	if (error != DDI_SUCCESS)
		goto fail;
	softc->regs.mapped = B_TRUE;

	softc->fb_size = VGA_MEM_SIZE;

	error = ddi_regs_map_setup(devi, softc->fb_regno,
	    (caddr_t *)&softc->fb.addr,
	    mem_offset, softc->fb_size,
	    &dev_attr, &softc->fb.handle);
	if (error != DDI_SUCCESS)
		goto fail;
	softc->fb.mapped = B_TRUE;

	if (ddi_get8(softc->regs.handle,
	    softc->regs.addr + VGA_MISC_R) & VGA_MISC_IOA_SEL)
		softc->text_base = (caddr_t)softc->fb.addr + VGA_COLOR_BASE;
	else
		softc->text_base = (caddr_t)softc->fb.addr + VGA_MONO_BASE;

	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(),
	    DDI_PROP_DONTPASS, "console", &cons) == DDI_SUCCESS) {
		if (strcmp(cons, "graphics") == 0) {
			happyface_boot = 1;
			vgatext_silent = 1;
			softc->current_base = softc->shadow;
		} else {
			softc->current_base = softc->text_base;
		}
		ddi_prop_free(cons);
	} else {
		softc->current_base = softc->text_base;
	}

	error = ddi_prop_create(makedevice(DDI_MAJOR_T_UNKNOWN, unit),
	    devi, DDI_PROP_CANSLEEP, DDI_KERNEL_IOCTL, NULL, 0);
	if (error != DDI_SUCCESS)
		goto fail;

	gfxp_check_for_console(devi, softc, pci_pcie_bus);

	value = GFXP_IS_CONSOLE(softc) ? 1 : 0;
	if (ddi_prop_update_int(DDI_DEV_T_NONE, devi,
	    "primary-controller", value) != DDI_SUCCESS) {
		cmn_err(CE_WARN,
		    "Can not %s primary-controller "
		    "property for driver", value ? "set" : "clear");
	}

	/* only do this if not in graphics mode */
	if ((vgatext_silent == 0) && (GFXP_IS_CONSOLE(softc))) {
		vgatext_init(softc);
		vgatext_save_colormap(softc);
	}

	return (DDI_SUCCESS);

fail:
	if (parent_type != NULL)
		ddi_prop_free(parent_type);
	(void) gfxp_vgatext_detach(devi, DDI_DETACH, (void *)softc);
	return (error);
}
Ejemplo n.º 10
0
static int
acebus_update_props(ebus_devstate_t *ebus_p)
{
	dev_info_t *dip = ebus_p->dip;
	struct ebus_pci_rangespec er[2], *erp;
	pci_regspec_t *pci_rp, *prp;
	int length, rnums, imask[3], i, found = 0;

	/*
	 * If "ranges" property is found, then the device is initialized
	 * by OBP, hence simply return.
	 * Otherwise we create all the properties here.
	 */
	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
	    "ranges", (int **)&erp, (uint_t *)&length) == DDI_PROP_SUCCESS) {
		ddi_prop_free(erp);
		return (DDI_SUCCESS);
	}

	/*
	 * interrupt-map is the only property that comes from a .conf file.
	 * Since it doesn't have the nodeid field set, it must be done here.
	 * Other properties can come from OBP or created here.
	 */
	if (acebus_set_imap(dip) != DDI_SUCCESS) {
		return (DDI_FAILURE);
	}

	/*
	 * Create the "ranges" property.
	 * Ebus has BAR0 and BAR1 allocated (both in memory space).
	 * Other BARs are 0.
	 * Hence there are 2 memory ranges it operates in. (one for each BAR).
	 * ie. there are 2 entries in its ranges property.
	 */
	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
	    DDI_PROP_DONTPASS, "assigned-addresses",
	    (int **)&pci_rp, (uint_t *)&length) != DDI_PROP_SUCCESS) {
		cmn_err(CE_WARN, "%s%d: Could not get assigned-addresses",
		    ddi_driver_name(dip), ddi_get_instance(dip));
		return (DDI_FAILURE);
	}
	/*
	 * Create the 1st mem range in which it operates corresponding
	 * to BAR0
	 */
	er[0].ebus_phys_hi = EBUS_CHILD_PHYS_LOW_RANGE;
	rnums = (length * sizeof (int))/sizeof (pci_regspec_t);
	for (i = 0; i < rnums; i++) {
		prp = pci_rp + i;
		if (PCI_REG_REG_G(prp->pci_phys_hi) == er[0].ebus_phys_hi) {
			found = 1;
			break;
		}
	}
	if (!found) {
		cmn_err(CE_WARN, "No assigned space for memory range 0.");
		ddi_prop_free(pci_rp);
		return (DDI_FAILURE);
	}
	found = 0;
	er[0].ebus_phys_low = 0;
	er[0].pci_phys_hi = prp->pci_phys_hi;
	er[0].pci_phys_mid = prp->pci_phys_mid;
	er[0].pci_phys_low = prp->pci_phys_low;
	er[0].rng_size = prp->pci_size_low;

	/*
	 * Create the 2nd mem range in which it operates corresponding
	 * to BAR1
	 */
	er[1].ebus_phys_hi = EBUS_CHILD_PHYS_HI_RANGE;
	for (i = 0; i < rnums; i++) {
		prp = pci_rp + i;
		if (PCI_REG_REG_G(prp->pci_phys_hi) == er[1].ebus_phys_hi) {
			found = 1;
			break;
		}
	}
	if (!found) {
		cmn_err(CE_WARN, "No assigned space for memory range 1.");
		ddi_prop_free(pci_rp);
		return (DDI_FAILURE);
	}
	er[1].ebus_phys_low = 0;
	er[1].pci_phys_hi = prp->pci_phys_hi;
	er[1].pci_phys_mid = prp->pci_phys_mid;
	er[1].pci_phys_low = prp->pci_phys_low;
	er[1].rng_size = prp->pci_size_low;

	ddi_prop_free(pci_rp);
	length = sizeof (er) / sizeof (int);
	if (ddi_prop_update_int_array(DDI_DEV_T_NONE, dip,
	    "ranges", (int *)er, length) != DDI_PROP_SUCCESS) {
		cmn_err(CE_WARN, "%s%d: Could not create ranges property",
		    ddi_driver_name(dip), ddi_get_instance(dip));
		return (DDI_FAILURE);
	}
	/* The following properties are as defined by PCI 1275 bindings. */
	if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
	    "#address-cells", 2) != DDI_PROP_SUCCESS)
			return (DDI_FAILURE);
	if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
	    "#size-cells", 1) != DDI_PROP_SUCCESS)
			return (DDI_FAILURE);
	if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
	    "#interrupt-cells", 1) != DDI_PROP_SUCCESS)
			return (DDI_FAILURE);

	imask[0] = 0x1f;
	imask[1] = 0x00ffffff;
	imask[2] = 0x00000003;
	length = sizeof (imask) / sizeof (int);
	if (ddi_prop_update_int_array(DDI_DEV_T_NONE, dip,
	    "interrupt-map-mask", (int *)imask, length) != DDI_PROP_SUCCESS) {
		cmn_err(CE_WARN, "%s%d: Could not update imap mask property",
		    ddi_driver_name(dip), ddi_get_instance(dip));
		return (DDI_FAILURE);
	}

	return (DDI_SUCCESS);
}
Ejemplo n.º 11
0
/*
 * audio1575_attach()
 *
 * Description:
 *	Attach an instance of the audio1575 driver. This routine does the
 * 	device dependent attach tasks. When it is completed, it registers
 *	with the audio framework.
 *
 * Arguments:
 *	dev_info_t	*dip	Pointer to the device's dev_info struct
 *
 * Returns:
 *	DDI_SUCCESS		The driver was initialized properly
 *	DDI_FAILURE		The driver couldn't be initialized properly
 */
static int
audio1575_attach(dev_info_t *dip)
{
	audio1575_state_t	*statep;
	audio_dev_t		*adev;
	uint32_t		devid;
	const char		*name;
	const char		*rev;
	int			maxch;

	/* allocate the soft state structure */
	statep = kmem_zalloc(sizeof (*statep), KM_SLEEP);
	ddi_set_driver_private(dip, statep);
	statep->dip = dip;

	/*
	 * We want the micboost enabled by default as well.
	 */
	(void) ddi_prop_update_int(DDI_DEV_T_NONE, dip, AC97_PROP_MICBOOST, 1);

	/* allocate common audio dev structure */
	adev = audio_dev_alloc(dip, 0);
	if (adev == NULL) {
		audio_dev_warn(NULL, "unable to allocate audio dev");
		goto error;
	}
	statep->adev = adev;

	/* map in the audio registers */
	if (audio1575_map_regs(statep) != DDI_SUCCESS) {
		audio_dev_warn(adev, "couldn't map registers");
		goto error;
	}

	/* Enable PCI I/O and Memory Spaces */
	audio1575_pci_enable(statep);

	devid = (pci_config_get16(statep->pcih, PCI_CONF_VENID) << 16) |
	    pci_config_get16(statep->pcih, PCI_CONF_DEVID);
	switch (devid) {
	case 0x10b95455:
		name = "Uli M1575 AC'97";
		rev = "M5455";
		break;
	default:
		name = "Uli AC'97";
		rev = "Unknown";
		break;
	}
	/* set device information -- this should check PCI config space */
	audio_dev_set_description(adev, name);
	audio_dev_set_version(adev, rev);

	statep->ac97 = ac97_alloc(dip, audio1575_read_ac97,
	    audio1575_write_ac97, statep);
	ASSERT(statep->ac97 != NULL);

	/*
	 * Override "max-channels" property to prevent configuration
	 * of 4 or 6 (or possibly even 8!) channel audio.  The default
	 * is to support as many channels as the hardware can do.
	 */
	maxch = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
	    "max-channels", ac97_num_channels(statep->ac97));
	if (maxch < 2) {
		maxch = 2;
	}

	statep->maxch = min(maxch, 6) & ~1;

	/* allocate port structures */
	if ((audio1575_alloc_port(statep, M1575_PLAY, statep->maxch) !=
	    DDI_SUCCESS) ||
	    (audio1575_alloc_port(statep, M1575_REC, 2) != DDI_SUCCESS)) {
		goto error;
	}

	if (audio1575_chip_init(statep) != DDI_SUCCESS) {
		audio_dev_warn(adev, "failed to init chip");
		goto error;
	}

	if (ac97_init(statep->ac97, adev) != DDI_SUCCESS) {
		audio_dev_warn(adev, "ac'97 initialization failed");
		goto error;
	}

	/* register with the framework */
	if (audio_dev_register(adev) != DDI_SUCCESS) {
		audio_dev_warn(adev, "unable to register with framework");
		goto error;
	}

	/* everything worked out, so report the device */
	ddi_report_dev(dip);

	return (DDI_SUCCESS);

error:
	audio1575_destroy(statep);
	return (DDI_FAILURE);
}
Ejemplo n.º 12
0
static int
acpinex_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
{
	int instance;
	acpinex_softstate_t *softsp;

	switch (cmd) {
	case DDI_ATTACH:
		break;

	case DDI_RESUME:
		return (DDI_SUCCESS);

	default:
		return (DDI_FAILURE);
	}

	/* Get and check instance number. */
	instance = ddi_get_instance(devi);
	if (instance >= ACPINEX_INSTANCE_MAX) {
		cmn_err(CE_WARN, "acpinex: instance number %d is out of range "
		    "in acpinex_attach(), max %d.",
		    instance, ACPINEX_INSTANCE_MAX - 1);
		return (DDI_FAILURE);
	}

	/* Get soft state structure. */
	if (ddi_soft_state_zalloc(acpinex_softstates, instance)
	    != DDI_SUCCESS) {
		cmn_err(CE_WARN, "!acpinex: failed to allocate soft state "
		    "object in acpinex_attach().");
		return (DDI_FAILURE);
	}
	softsp = ddi_get_soft_state(acpinex_softstates, instance);

	/* Initialize soft state structure */
	softsp->ans_dip = devi;
	(void) ddi_pathname(devi, softsp->ans_path);
	if (ACPI_FAILURE(acpica_get_handle(devi, &softsp->ans_hdl))) {
		ACPINEX_DEBUG(CE_WARN,
		    "!acpinex: failed to get ACPI handle for %s.",
		    softsp->ans_path);
		ddi_soft_state_free(acpinex_softstates, instance);
		return (DDI_FAILURE);
	}
	mutex_init(&softsp->ans_lock, NULL, MUTEX_DRIVER, NULL);

	/* Install event handler for child/descendant objects. */
	if (acpinex_event_scan(softsp, B_TRUE) != DDI_SUCCESS) {
		cmn_err(CE_WARN, "!acpinex: failed to install event handler "
		    "for children of %s.", softsp->ans_path);
	}

	/* nothing to suspend/resume here */
	(void) ddi_prop_update_string(DDI_DEV_T_NONE, devi,
	    "pm-hardware-state", "no-suspend-resume");
	(void) ddi_prop_update_int(DDI_DEV_T_NONE, devi,
	    DDI_NO_AUTODETACH, 1);

	acpinex_fm_init(softsp);
	ddi_report_dev(devi);

	return (DDI_SUCCESS);
}