예제 #1
0
파일: fipe_pm.c 프로젝트: bahamas10/openzfs
/*
 * Initialize memory controller's data structure and status.
 */
static int
fipe_mc_init(dev_info_t *dip)
{
	ddi_acc_handle_t handle;

	bzero(&fipe_mc_ctrl, sizeof (fipe_mc_ctrl));

	/* Hold one reference count and will be released in fipe_mc_fini. */
	ndi_hold_devi(dip);

	/* Setup pci configuration handler. */
	if (pci_config_setup(dip, &handle) != DDI_SUCCESS) {
		cmn_err(CE_WARN,
		    "!fipe: failed to setup pcicfg handler in mc_init.");
		ndi_rele_devi(dip);
		return (-1);
	}

	/* Save original configuration. */
	fipe_mc_ctrl.mc_thrtctrl = pci_config_get8(handle, FIPE_MC_THRTCTRL);
	fipe_mc_ctrl.mc_thrtlow = pci_config_get8(handle, FIPE_MC_THRTLOW);
	fipe_mc_ctrl.mc_gblact = pci_config_get8(handle, FIPE_MC_GBLACT);
	fipe_mc_ctrl.mc_dip = dip;
	fipe_mc_ctrl.mc_pci_hdl = handle;
	fipe_mc_ctrl.mc_initialized = B_TRUE;

	return (0);
}
예제 #2
0
void
rge_chip_cfg_init(rge_t *rgep, chip_id_t *cidp)
{
	ddi_acc_handle_t handle;
	uint16_t commd;

	handle = rgep->cfg_handle;

	/*
	 * Save PCI cache line size and subsystem vendor ID
	 */
	cidp->command = pci_config_get16(handle, PCI_CONF_COMM);
	cidp->vendor = pci_config_get16(handle, PCI_CONF_VENID);
	cidp->device = pci_config_get16(handle, PCI_CONF_DEVID);
	cidp->subven = pci_config_get16(handle, PCI_CONF_SUBVENID);
	cidp->subdev = pci_config_get16(handle, PCI_CONF_SUBSYSID);
	cidp->revision = pci_config_get8(handle, PCI_CONF_REVID);
	cidp->clsize = pci_config_get8(handle, PCI_CONF_CACHE_LINESZ);
	cidp->latency = pci_config_get8(handle, PCI_CONF_LATENCY_TIMER);

	/*
	 * Turn on Master Enable (DMA) and IO Enable bits.
	 * Enable PCI Memory Space accesses
	 */
	commd = cidp->command;
	commd |= PCI_COMM_ME | PCI_COMM_MAE | PCI_COMM_IO;
	pci_config_put16(handle, PCI_CONF_COMM, commd);

	RGE_DEBUG(("rge_chip_cfg_init: vendor 0x%x device 0x%x revision 0x%x",
	    cidp->vendor, cidp->device, cidp->revision));
	RGE_DEBUG(("rge_chip_cfg_init: subven 0x%x subdev 0x%x",
	    cidp->subven, cidp->subdev));
	RGE_DEBUG(("rge_chip_cfg_init: clsize %d latency %d command 0x%x",
	    cidp->clsize, cidp->latency, cidp->command));
}
예제 #3
0
/*
 * pcmu_init_child
 *
 * This function is called from our control ops routine on a
 * DDI_CTLOPS_INITCHILD request.  It builds and sets the device's
 * parent private data area.
 *
 * used by: pcmu_ctlops()
 *
 * return value: none
 */
int
pcmu_init_child(pcmu_t *pcmu_p, dev_info_t *child)
{
	char name[10];
	ddi_acc_handle_t config_handle;
	uint8_t bcr;
	uint8_t header_type;

	if (name_child(child, name, 10) != DDI_SUCCESS)
		return (DDI_FAILURE);
	ddi_set_name_addr(child, name);

	PCMU_DBG2(PCMU_DBG_PWR, ddi_get_parent(child),
	    "INITCHILD: config regs setup for %s@%s\n",
	    ddi_node_name(child), ddi_get_name_addr(child));

	/*
	 * Map the child configuration space to for initialization.
	 * We assume the obp will do the following in the devices
	 * config space:
	 *
	 *	Set the latency-timer register to values appropriate
	 *	for the devices on the bus (based on other devices
	 *	MIN_GNT and MAX_LAT registers.
	 *
	 *	Set the fast back-to-back enable bit in the command
	 *	register if it's supported and all devices on the bus
	 *	have the capability.
	 *
	 */
	if (pci_config_setup(child, &config_handle) != DDI_SUCCESS) {
		ddi_set_name_addr(child, NULL);
		return (DDI_FAILURE);
	}

	/*
	 * Determine the configuration header type.
	 */
	header_type = pci_config_get8(config_handle, PCI_CONF_HEADER);
	PCMU_DBG2(PCMU_DBG_INIT_CLD, pcmu_p->pcmu_dip, "%s: header_type=%x\n",
	    ddi_driver_name(child), header_type);

	/*
	 * If the device has a bus control register then program it
	 * based on the settings in the command register.
	 */
	if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_ONE) {
		bcr = pci_config_get8(config_handle, PCI_BCNF_BCNTRL);
		if (pcmu_command_default & PCI_COMM_PARITY_DETECT)
			bcr |= PCI_BCNF_BCNTRL_PARITY_ENABLE;
		if (pcmu_command_default & PCI_COMM_SERR_ENABLE)
			bcr |= PCI_BCNF_BCNTRL_SERR_ENABLE;
		bcr |= PCI_BCNF_BCNTRL_MAST_AB_MODE;
		pci_config_put8(config_handle, PCI_BCNF_BCNTRL, bcr);
	}

	pci_config_teardown(&config_handle);
	return (DDI_SUCCESS);
}
예제 #4
0
/*
 * Examine devinfo node to determine if it is a PCI-PCI bridge
 *
 * Returns:
 *	0 if not a bridge or error
 *	1 if a bridge
 */
static int
psm_is_pci_bridge(dev_info_t *dip)
{
	ddi_acc_handle_t cfg_handle;
	int rv = 0;

	if (pci_config_setup(dip, &cfg_handle) == DDI_SUCCESS) {
		rv = ((pci_config_get8(cfg_handle, PCI_CONF_BASCLASS) ==
		    PCI_CLASS_BRIDGE) && (pci_config_get8(cfg_handle,
		    PCI_CONF_SUBCLASS) == PCI_BRIDGE_PCI));
		pci_config_teardown(&cfg_handle);
	}

	return (rv);
}
예제 #5
0
파일: agptarget.c 프로젝트: andreiw/polaris
/*
 * agp_target_cap_find()
 *
 * Description:
 * 	This function searches the linked capability list to find the offset
 * 	of the AGP capability register. When it was not found, return 0.
 * 	This works for standard AGP chipsets, but not for some Intel chipsets,
 * 	like the I830M/I830MP/I852PM/I852GME/I855GME. It will return 0 for
 * 	these chipsets even if AGP is supported. So the offset of acapid
 * 	should be set manually in thoses cases.
 *
 * Arguments:
 * 	pci_handle		ddi acc handle of pci config
 *
 * Returns:
 * 	0			No capability pointer register found
 * 	nexcap			The AGP capability pointer register offset
 */
static off_t
agp_target_cap_find(ddi_acc_handle_t pci_handle)
{
	off_t		nextcap = 0;
	uint32_t	ncapid = 0;
	uint8_t		value = 0;

	/* Check if this device supports the capability pointer */
	value = (uint8_t)(pci_config_get16(pci_handle, PCI_CONF_STAT)
	    & PCI_CONF_CAP_MASK);

	if (!value)
		return (0);
	/* Get the offset of the first capability pointer from CAPPTR */
	nextcap = (off_t)(pci_config_get8(pci_handle, AGP_CONF_CAPPTR));

	/* Check the AGP capability from the first capability pointer */
	while (nextcap) {
		ncapid = pci_config_get32(pci_handle, nextcap);
		/*
		 * AGP3.0 rev1.0 127  the capid was assigned by the PCI SIG,
		 * 845 data sheet page 69
		 */
		if ((ncapid & PCI_CONF_CAPID_MASK) ==
		    AGP_CAP_ID) /* The AGP cap was found */
			break;

		nextcap = (off_t)((ncapid & PCI_CONF_NCAPID_MASK) >> 8);
	}

	return (nextcap);

}
예제 #6
0
static void
rge_chip_peek_cfg(rge_t *rgep, rge_peekpoke_t *ppd)
{
	uint64_t regval;
	uint64_t regno;

	RGE_TRACE(("rge_chip_peek_cfg($%p, $%p)",
	    (void *)rgep, (void *)ppd));

	regno = ppd->pp_acc_offset;

	switch (ppd->pp_acc_size) {
	case 1:
		regval = pci_config_get8(rgep->cfg_handle, regno);
		break;

	case 2:
		regval = pci_config_get16(rgep->cfg_handle, regno);
		break;

	case 4:
		regval = pci_config_get32(rgep->cfg_handle, regno);
		break;

	case 8:
		regval = pci_config_get64(rgep->cfg_handle, regno);
		break;
	}

	ppd->pp_acc_data = regval;
}
예제 #7
0
/*ARGSUSED*/
uint8_t
pmubus_get8(ddi_acc_impl_t *hdlp, uint8_t *addr)
{
	ddi_acc_hdl_t *hp = (ddi_acc_hdl_t *)hdlp;
	pmubus_mapreq_t *pmubus_mapreqp = hp->ah_bus_private;
	pmubus_devstate_t *softsp = pmubus_mapreqp->mapreq_softsp;
	off_t offset;
	uint8_t value;
	uint8_t mask;

	offset = pmubus_mapreqp->mapreq_addr + (uintptr_t)addr;
	offset &= PMUBUS_REGOFFSET;

	if ((pmubus_mapreqp->mapreq_flags) & MAPREQ_SHARED_BITS) {
		if (addr != 0 ||
		    pmubus_mapreqp->mapreq_size != sizeof (value)) {
			cmn_err(CE_WARN, "pmubus_get8: load discarded, "
			    "incorrect access addr/size");
			return ((uint8_t)-1);
		}
		mask = pmubus_mapreqp->mapreq_mask;
	} else {
		mask = (uint8_t)-1;
	}

	/* gets are simple, we just issue them no locking necessary */
	value = pci_config_get8(softsp->pmubus_reghdl, offset) & mask;

	DPRINTF(PMUBUS_RW_DEBUG, ("pmubus_get8: addr=%p offset=%lx value=%x "
	    "mask=%x\n", (void *)addr, offset, value, mask));

	return (value);
}
예제 #8
0
/*ARGSUSED*/
void
pmubus_put8(ddi_acc_impl_t *hdlp, uint8_t *addr, uint8_t value)
{
	ddi_acc_hdl_t *hp = (ddi_acc_hdl_t *)hdlp;
	pmubus_mapreq_t *pmubus_mapreqp = hp->ah_bus_private;
	pmubus_devstate_t *softsp = pmubus_mapreqp->mapreq_softsp;
	off_t offset;
	uint8_t tmp;

	offset = pmubus_mapreqp->mapreq_addr + (uintptr_t)addr;
	offset &= PMUBUS_REGOFFSET;

	if ((pmubus_mapreqp->mapreq_flags) & MAPREQ_SHARED_BITS) {
		/*
		 * Process "bit lane" register
		 */
		DPRINTF(PMUBUS_RW_DEBUG, ("pmubus_put8: addr=%p offset=%lx "
		    "value=%x mask=%lx\n", (void *)addr, offset, value,
		    pmubus_mapreqp->mapreq_mask));

		if (addr != 0 ||
		    pmubus_mapreqp->mapreq_size != sizeof (value)) {
			cmn_err(CE_WARN, "pmubus_put8: store discarded, "
			    "incorrect access addr/size");
			return;
		}

		mutex_enter(&softsp->pmubus_reg_access_lock);
		tmp = pci_config_get8(softsp->pmubus_reghdl, offset);
		tmp &= ~pmubus_mapreqp->mapreq_mask;
		value &= pmubus_mapreqp->mapreq_mask;
		tmp |= value;
		pci_config_put8(softsp->pmubus_reghdl, offset, tmp);
		mutex_exit(&softsp->pmubus_reg_access_lock);
	} else {
		/*
		 * Process shared register
		 */
		DPRINTF(PMUBUS_RW_DEBUG, ("pmubus_put8: addr=%p offset=%lx "
		    "value=%x\n", (void *)addr, offset, value));
		pci_config_put8(softsp->pmubus_reghdl, offset, value);
	}

	/* Flush store buffers XXX Should let drivers do this. */
	tmp = pci_config_get8(softsp->pmubus_reghdl, offset);
}
예제 #9
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);
}
예제 #10
0
/*ARGSUSED*/
int
plat_ide_chipreset(dev_info_t *dip, int chno)
{
	uint8_t	val;
	int	ret = DDI_SUCCESS;

	if (isa_handle == NULL) {
		return (DDI_FAILURE);
	}

	val = pci_config_get8(isa_handle, 0x58);
	/*
	 * The dip passed as the argument is not used here.
	 * This will be needed for platforms which have multiple on-board SB,
	 * The dip passed will be used to match the corresponding ISA node.
	 */
	switch (chno) {
		case 0:
			/*
			 * First disable the primary channel then re-enable it.
			 * As per ALI no wait should be required in between have
			 * given 1ms delay in between to be on safer side.
			 * bit 2 of register 0x58 when 0 disable the channel 0.
			 * bit 2 of register 0x58 when 1 enables the channel 0.
			 */
			pci_config_put8(isa_handle, 0x58, val & 0xFB);
			drv_usecwait(1000);
			pci_config_put8(isa_handle, 0x58, val);
			break;
		case 1:
			/*
			 * bit 3 of register 0x58 when 0 disable the channel 1.
			 * bit 3 of register 0x58 when 1 enables the channel 1.
			 */
			pci_config_put8(isa_handle, 0x58, val & 0xF7);
			drv_usecwait(1000);
			pci_config_put8(isa_handle, 0x58, val);
			break;
		default:
			/*
			 * Unknown channel number passed. Return failure.
			 */
			ret = DDI_FAILURE;
	}

	return (ret);
}
예제 #11
0
/*
 * Enable reporting of AER capability next pointer.
 * This needs to be done only for CK8-04 devices
 * by setting NV_XVR_VEND_CYA1 (offset 0xf40) bit 13
 * NOTE: BIOS is disabling this, it needs to be enabled temporarily
 */
void
npe_ck804_fix_aer_ptr(ddi_acc_handle_t cfg_hdl)
{
	ushort_t cya1;

	if ((pci_config_get16(cfg_hdl, PCI_CONF_VENID) == NVIDIA_VENDOR_ID) &&
	    (pci_config_get16(cfg_hdl, PCI_CONF_DEVID) ==
	    NVIDIA_CK804_DEVICE_ID) &&
	    (pci_config_get8(cfg_hdl, PCI_CONF_REVID) >=
	    NVIDIA_CK804_AER_VALID_REVID)) {
		cya1 =  pci_config_get16(cfg_hdl, NVIDIA_CK804_VEND_CYA1_OFF);
		if (!(cya1 & ~NVIDIA_CK804_VEND_CYA1_ERPT_MASK))
			(void) pci_config_put16(cfg_hdl,
			    NVIDIA_CK804_VEND_CYA1_OFF,
			    cya1 | NVIDIA_CK804_VEND_CYA1_ERPT_VAL);
	}
}
예제 #12
0
void
pci_dump(void *arg)
{
	igb_t *igb = (igb_t *)arg;
	ddi_acc_handle_t handle;
	uint8_t cap_ptr;
	uint8_t next_ptr;
	uint32_t msix_bar;
	uint32_t msix_ctrl;
	uint32_t msix_tbl_sz;
	uint32_t tbl_offset;
	uint32_t tbl_bir;
	uint32_t pba_offset;
	uint32_t pba_bir;
	off_t offset;
	off_t mem_size;
	uintptr_t base;
	ddi_acc_handle_t acc_hdl;
	int i;

	handle = igb->osdep.cfg_handle;

	igb_log(igb, "Begin dump PCI config space");

	igb_log(igb,
	    "PCI_CONF_VENID:\t0x%x\n",
	    pci_config_get16(handle, PCI_CONF_VENID));
	igb_log(igb,
	    "PCI_CONF_DEVID:\t0x%x\n",
	    pci_config_get16(handle, PCI_CONF_DEVID));
	igb_log(igb,
	    "PCI_CONF_COMMAND:\t0x%x\n",
	    pci_config_get16(handle, PCI_CONF_COMM));
	igb_log(igb,
	    "PCI_CONF_STATUS:\t0x%x\n",
	    pci_config_get16(handle, PCI_CONF_STAT));
	igb_log(igb,
	    "PCI_CONF_REVID:\t0x%x\n",
	    pci_config_get8(handle, PCI_CONF_REVID));
	igb_log(igb,
	    "PCI_CONF_PROG_CLASS:\t0x%x\n",
	    pci_config_get8(handle, PCI_CONF_PROGCLASS));
	igb_log(igb,
	    "PCI_CONF_SUB_CLASS:\t0x%x\n",
	    pci_config_get8(handle, PCI_CONF_SUBCLASS));
	igb_log(igb,
	    "PCI_CONF_BAS_CLASS:\t0x%x\n",
	    pci_config_get8(handle, PCI_CONF_BASCLASS));
	igb_log(igb,
	    "PCI_CONF_CACHE_LINESZ:\t0x%x\n",
	    pci_config_get8(handle, PCI_CONF_CACHE_LINESZ));
	igb_log(igb,
	    "PCI_CONF_LATENCY_TIMER:\t0x%x\n",
	    pci_config_get8(handle, PCI_CONF_LATENCY_TIMER));
	igb_log(igb,
	    "PCI_CONF_HEADER_TYPE:\t0x%x\n",
	    pci_config_get8(handle, PCI_CONF_HEADER));
	igb_log(igb,
	    "PCI_CONF_BIST:\t0x%x\n",
	    pci_config_get8(handle, PCI_CONF_BIST));
	igb_log(igb,
	    "PCI_CONF_BASE0:\t0x%x\n",
	    pci_config_get32(handle, PCI_CONF_BASE0));
	igb_log(igb,
	    "PCI_CONF_BASE1:\t0x%x\n",
	    pci_config_get32(handle, PCI_CONF_BASE1));
	igb_log(igb,
	    "PCI_CONF_BASE2:\t0x%x\n",
	    pci_config_get32(handle, PCI_CONF_BASE2));

	/* MSI-X BAR */
	msix_bar = pci_config_get32(handle, PCI_CONF_BASE3);
	igb_log(igb,
	    "PCI_CONF_BASE3:\t0x%x\n", msix_bar);

	igb_log(igb,
	    "PCI_CONF_BASE4:\t0x%x\n",
	    pci_config_get32(handle, PCI_CONF_BASE4));
	igb_log(igb,
	    "PCI_CONF_BASE5:\t0x%x\n",
	    pci_config_get32(handle, PCI_CONF_BASE5));
	igb_log(igb,
	    "PCI_CONF_CIS:\t0x%x\n",
	    pci_config_get32(handle, PCI_CONF_CIS));
	igb_log(igb,
	    "PCI_CONF_SUBVENID:\t0x%x\n",
	    pci_config_get16(handle, PCI_CONF_SUBVENID));
	igb_log(igb,
	    "PCI_CONF_SUBSYSID:\t0x%x\n",
	    pci_config_get16(handle, PCI_CONF_SUBSYSID));
	igb_log(igb,
	    "PCI_CONF_ROM:\t0x%x\n",
	    pci_config_get32(handle, PCI_CONF_ROM));

	cap_ptr = pci_config_get8(handle, PCI_CONF_CAP_PTR);

	igb_log(igb,
	    "PCI_CONF_CAP_PTR:\t0x%x\n", cap_ptr);
	igb_log(igb,
	    "PCI_CONF_ILINE:\t0x%x\n",
	    pci_config_get8(handle, PCI_CONF_ILINE));
	igb_log(igb,
	    "PCI_CONF_IPIN:\t0x%x\n",
	    pci_config_get8(handle, PCI_CONF_IPIN));
	igb_log(igb,
	    "PCI_CONF_MIN_G:\t0x%x\n",
	    pci_config_get8(handle, PCI_CONF_MIN_G));
	igb_log(igb,
	    "PCI_CONF_MAX_L:\t0x%x\n",
	    pci_config_get8(handle, PCI_CONF_MAX_L));

	/* Power Management */
	offset = cap_ptr;

	igb_log(igb,
	    "PCI_PM_CAP_ID:\t0x%x\n",
	    pci_config_get8(handle, offset));

	next_ptr = pci_config_get8(handle, offset + 1);

	igb_log(igb,
	    "PCI_PM_NEXT_PTR:\t0x%x\n", next_ptr);
	igb_log(igb,
	    "PCI_PM_CAP:\t0x%x\n",
	    pci_config_get16(handle, offset + PCI_PMCAP));
	igb_log(igb,
	    "PCI_PM_CSR:\t0x%x\n",
	    pci_config_get16(handle, offset + PCI_PMCSR));
	igb_log(igb,
	    "PCI_PM_CSR_BSE:\t0x%x\n",
	    pci_config_get8(handle, offset + PCI_PMCSR_BSE));
	igb_log(igb,
	    "PCI_PM_DATA:\t0x%x\n",
	    pci_config_get8(handle, offset + PCI_PMDATA));

	/* MSI Configuration */
	offset = next_ptr;

	igb_log(igb,
	    "PCI_MSI_CAP_ID:\t0x%x\n",
	    pci_config_get8(handle, offset));

	next_ptr = pci_config_get8(handle, offset + 1);

	igb_log(igb,
	    "PCI_MSI_NEXT_PTR:\t0x%x\n", next_ptr);
	igb_log(igb,
	    "PCI_MSI_CTRL:\t0x%x\n",
	    pci_config_get16(handle, offset + PCI_MSI_CTRL));
	igb_log(igb,
	    "PCI_MSI_ADDR:\t0x%x\n",
	    pci_config_get32(handle, offset + PCI_MSI_ADDR_OFFSET));
	igb_log(igb,
	    "PCI_MSI_ADDR_HI:\t0x%x\n",
	    pci_config_get32(handle, offset + 0x8));
	igb_log(igb,
	    "PCI_MSI_DATA:\t0x%x\n",
	    pci_config_get16(handle, offset + 0xC));

	/* MSI-X Configuration */
	offset = next_ptr;

	igb_log(igb,
	    "PCI_MSIX_CAP_ID:\t0x%x\n",
	    pci_config_get8(handle, offset));

	next_ptr = pci_config_get8(handle, offset + 1);
	igb_log(igb,
	    "PCI_MSIX_NEXT_PTR:\t0x%x\n", next_ptr);

	msix_ctrl = pci_config_get16(handle, offset + PCI_MSIX_CTRL);
	msix_tbl_sz = msix_ctrl & 0x7ff;
	igb_log(igb,
	    "PCI_MSIX_CTRL:\t0x%x\n", msix_ctrl);

	tbl_offset = pci_config_get32(handle, offset + PCI_MSIX_TBL_OFFSET);
	tbl_bir = tbl_offset & PCI_MSIX_TBL_BIR_MASK;
	tbl_offset = tbl_offset & ~PCI_MSIX_TBL_BIR_MASK;
	igb_log(igb,
	    "PCI_MSIX_TBL_OFFSET:\t0x%x\n", tbl_offset);
	igb_log(igb,
	    "PCI_MSIX_TBL_BIR:\t0x%x\n", tbl_bir);

	pba_offset = pci_config_get32(handle, offset + PCI_MSIX_PBA_OFFSET);
	pba_bir = pba_offset & PCI_MSIX_PBA_BIR_MASK;
	pba_offset = pba_offset & ~PCI_MSIX_PBA_BIR_MASK;
	igb_log(igb,
	    "PCI_MSIX_PBA_OFFSET:\t0x%x\n", pba_offset);
	igb_log(igb,
	    "PCI_MSIX_PBA_BIR:\t0x%x\n", pba_bir);

	/* PCI Express Configuration */
	offset = next_ptr;

	igb_log(igb,
	    "PCIE_CAP_ID:\t0x%x\n",
	    pci_config_get8(handle, offset + PCIE_CAP_ID));

	next_ptr = pci_config_get8(handle, offset + PCIE_CAP_NEXT_PTR);

	igb_log(igb,
	    "PCIE_CAP_NEXT_PTR:\t0x%x\n", next_ptr);
	igb_log(igb,
	    "PCIE_PCIECAP:\t0x%x\n",
	    pci_config_get16(handle, offset + PCIE_PCIECAP));
	igb_log(igb,
	    "PCIE_DEVCAP:\t0x%x\n",
	    pci_config_get32(handle, offset + PCIE_DEVCAP));
	igb_log(igb,
	    "PCIE_DEVCTL:\t0x%x\n",
	    pci_config_get16(handle, offset + PCIE_DEVCTL));
	igb_log(igb,
	    "PCIE_DEVSTS:\t0x%x\n",
	    pci_config_get16(handle, offset + PCIE_DEVSTS));
	igb_log(igb,
	    "PCIE_LINKCAP:\t0x%x\n",
	    pci_config_get32(handle, offset + PCIE_LINKCAP));
	igb_log(igb,
	    "PCIE_LINKCTL:\t0x%x\n",
	    pci_config_get16(handle, offset + PCIE_LINKCTL));
	igb_log(igb,
	    "PCIE_LINKSTS:\t0x%x\n",
	    pci_config_get16(handle, offset + PCIE_LINKSTS));

	/* MSI-X Memory Space */
	if (ddi_dev_regsize(igb->dip, IGB_ADAPTER_MSIXTAB, &mem_size) !=
	    DDI_SUCCESS) {
		igb_log(igb, "ddi_dev_regsize() failed");
		return;
	}

	if ((ddi_regs_map_setup(igb->dip, IGB_ADAPTER_MSIXTAB, (caddr_t *)&base,
	    0, mem_size, &igb_regs_acc_attr, &acc_hdl)) != DDI_SUCCESS) {
		igb_log(igb, "ddi_regs_map_setup() failed");
		return;
	}

	igb_log(igb, "MSI-X Memory Space: (mem_size = %d, base = %x)",
	    mem_size, base);

	for (i = 0; i <= msix_tbl_sz; i++) {
		igb_log(igb, "MSI-X Table Entry(%d):", i);
		igb_log(igb, "lo_addr:\t%x",
		    ddi_get32(acc_hdl,
		    (uint32_t *)(base + tbl_offset + (i * 16))));
		igb_log(igb, "up_addr:\t%x",
		    ddi_get32(acc_hdl,
		    (uint32_t *)(base + tbl_offset + (i * 16) + 4)));
		igb_log(igb, "msg_data:\t%x",
		    ddi_get32(acc_hdl,
		    (uint32_t *)(base + tbl_offset + (i * 16) + 8)));
		igb_log(igb, "vct_ctrl:\t%x",
		    ddi_get32(acc_hdl,
		    (uint32_t *)(base + tbl_offset + (i * 16) + 12)));
	}

	igb_log(igb, "MSI-X Pending Bits:\t%x",
	    ddi_get32(acc_hdl, (uint32_t *)(base + pba_offset)));

	ddi_regs_map_free(&acc_hdl);
}
예제 #13
0
파일: agptarget.c 프로젝트: andreiw/polaris
static size_t
i8xx_biosmem_detect(agp_target_softstate_t *softstate)
{
	uint8_t memval;
	size_t kbytes;

	switch (softstate->tsoft_devid) {
	case INTEL_BR_810:
	case INTEL_BR_810DC:
	case INTEL_BR_810E:
		memval = pci_config_get8(softstate->tsoft_pcihdl,
		    I810_CONF_SMRAM);
		switch (memval & I810_GMS_MASK) {
		case 0x80:
			kbytes = 512; /* 512K preallocated memory */
			break;
		case 0xc0:
			kbytes = 1024; /* 1024K preallocated memory */
			break;
		default:
			kbytes = 0; /* an unexpected case */
		}
		break;
	case INTEL_BR_830M:
	case INTEL_BR_845:
		memval = pci_config_get8(softstate->tsoft_pcihdl, I8XX_CONF_GC);
		switch (memval & I8XX_GC_MODE_MASK) {
		case I8XX_GC_MODE2:
			kbytes = 512; /* 512K preallocated memory */
			break;
		case I8XX_GC_MODE3:
			kbytes = 1024; /* 1M preallocated memory */
			break;
		case I8XX_GC_MODE4:
			kbytes = 8 * 1024; /* 8M preallocated memory */
			break;
		default:
			kbytes = 0; /* an unexpected case */
		}
		break;
	case INTEL_BR_855GM:
		memval = pci_config_get8(softstate->tsoft_pcihdl, I8XX_CONF_GC);
		switch (memval & I8XX_GC_MODE_MASK) {
		case I8XX_GC_MODE1:
			kbytes = 1024; /* 1M preallocated memory */
			break;
		case I8XX_GC_MODE2:
			kbytes = 4 * 1024; /* 4M preallocated memory */
			break;
		case I8XX_GC_MODE3:
			kbytes = 8 * 1024; /* 8M preallocated memory */
			break;
		case I8XX_GC_MODE4:
			kbytes = 16 * 1024; /* 16M preallocated memory */
			break;
		case I8XX_GC_MODE5:
			kbytes = 32 * 1024; /* 32M preallocated memory */
			break;
		default:
			kbytes = 0; /* an unexpected case */
		}
		break;
	case INTEL_BR_865:
		memval = pci_config_get8(softstate->tsoft_pcihdl, I8XX_CONF_GC);
		switch (memval & I8XX_GC_MODE_MASK) {
		case I8XX_GC_MODE1:
			kbytes = 1024; /* 1M preallocated memory */
			break;
		case I8XX_GC_MODE3:
			kbytes = 8 * 1024; /* 8M preallocated memory */
			break;
		case I8XX_GC_MODE4:
			kbytes = 16 * 1024; /* 16M preallocated memory */
			break;
		default:
			kbytes = 0; /* an unexpected case */
		}
		break;
	case INTEL_BR_910:
	case INTEL_BR_910M:
		memval = pci_config_get8(softstate->tsoft_pcihdl, I8XX_CONF_GC);
		switch (memval & I8XX_GC_MODE_MASK) {
		case I8XX_GC_MODE1:
			kbytes = 1024; /* 1M preallocated memory */
			break;
		case I8XX_GC_MODE3:
			kbytes = 8 * 1024; /* 8M preallocated memory */
			break;
		default:
			kbytes = 0; /* an unexpected case */
		}
		break;
	default:
		kbytes = 0;
	}

	return (kbytes);
}
예제 #14
0
파일: agptarget.c 프로젝트: andreiw/polaris
/*ARGSUSED*/
static int
agp_target_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
    cred_t *cred, int *rval)
{
	int instance = DEV2INST(dev);
	agp_target_softstate_t *st;
	static char kernel_only[] =
	    "amd64_gart_ioctl: is a kernel only ioctl";

	if (!(mode & FKIOCTL)) {
		TARGETDB_PRINT2((CE_CONT, kernel_only));
		return (ENXIO);
	}
	st = GETSOFTC(instance);

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

	mutex_enter(&st->tsoft_lock);

	switch (cmd) {
	case CHIP_DETECT:
	{
		int type;
		switch (st->tsoft_devid & VENDOR_ID_MASK) {
		case INTEL_VENDOR_ID:
			type = CHIP_IS_INTEL;
			break;
		case AMD_VENDOR_ID:
			type = CHIP_IS_AMD;
			break;
		default:
			type = 0;
		}
		if (ddi_copyout(&type, (void *)data, sizeof (int), mode)) {
			mutex_exit(&st->tsoft_lock);
			return (EFAULT);
		}

		break;
	}
	case I8XX_GET_PREALLOC_SIZE:
	{
		size_t prealloc_size;

		if ((st->tsoft_devid & VENDOR_ID_MASK) !=
		    INTEL_VENDOR_ID) {
			mutex_exit(&st->tsoft_lock);
			return (EINVAL);
		}

		prealloc_size = i8xx_biosmem_detect(st);
		if (ddi_copyout(&prealloc_size, (void *)data,
		    sizeof (size_t), mode)) {
			mutex_exit(&st->tsoft_lock);
			return (EFAULT);
		}

		break;
	}
	case AGP_TARGET_GETINFO:
	{
		i_agp_info_t info;
		uint32_t value;
		off_t cap;

		ASSERT(st->tsoft_acaptr);

		cap = st->tsoft_acaptr;
		value = pci_config_get32(st->tsoft_pcihdl, cap);
		info.iagp_ver.agpv_major = (uint16_t)((value >> 20) & 0xf);
		info.iagp_ver.agpv_minor = (uint16_t)((value >> 16) & 0xf);
		info.iagp_devid = st->tsoft_devid;
		info.iagp_mode = pci_config_get32(st->tsoft_pcihdl,
			    cap + AGP_CONF_STATUS);
		info.iagp_aperbase = agp_target_get_apbase(st);
		info.iagp_apersize = agp_target_get_apsize(st);

		if (ddi_copyout(&info, (void *)data,
		    sizeof (i_agp_info_t), mode)) {
			mutex_exit(&st->tsoft_lock);
			return (EFAULT);
		}
		break;

	}
	/*
	 * This ioctl is only for Intel AGP chipsets.
	 * It is not necessary for the AMD8151 AGP bridge, because
	 * this register in the AMD8151 does not control any hardware.
	 * It is only provided for compatibility with an Intel AGP bridge.
	 * Please refer to the <<AMD8151 data sheet>> page 24,
	 * AGP device GART pointer.
	 */
	case AGP_TARGET_SET_GATTADDR:
	{
		uint32_t gartaddr;

		if (ddi_copyin((void *)data, &gartaddr,
		    sizeof (uint32_t), mode)) {
			mutex_exit(&st->tsoft_lock);
			return (EFAULT);
		}

		agp_target_set_gartaddr(st, gartaddr);
		break;
	}
	case AGP_TARGET_SETCMD:
	{
		uint32_t command;

		if (ddi_copyin((void *)data, &command,
		    sizeof (uint32_t), mode)) {
			mutex_exit(&st->tsoft_lock);
			return (EFAULT);
		}

		ASSERT(st->tsoft_acaptr);

		pci_config_put32(st->tsoft_pcihdl,
		    st->tsoft_acaptr + AGP_CONF_COMMAND,
		    command);
		break;

	}
	case AGP_TARGET_FLUSH_GTLB:
	{
		uint16_t value;

		ASSERT(st->tsoft_acaptr);

		value = pci_config_get16(st->tsoft_pcihdl,
		    st->tsoft_acaptr + AGP_CONF_CONTROL);
		value &= ~AGPCTRL_GTLBEN;
		pci_config_put16(st->tsoft_pcihdl,
		    st->tsoft_acaptr + AGP_CONF_CONTROL, value);
		value |= AGPCTRL_GTLBEN;
		pci_config_put16(st->tsoft_pcihdl,
		    st->tsoft_acaptr + AGP_CONF_CONTROL, value);

		break;
	}
	case AGP_TARGET_CONFIGURE:
	{
		uint8_t value;

		ASSERT(st->tsoft_acaptr);

		value = pci_config_get8(st->tsoft_pcihdl,
		    st->tsoft_acaptr + AGP_CONF_MISC);
		value |= AGP_MISC_APEN;
		pci_config_put8(st->tsoft_pcihdl,
		    st->tsoft_acaptr + AGP_CONF_MISC, value);
		break;

	}
	case AGP_TARGET_UNCONFIG:
	{
		uint32_t value1;
		uint8_t value2;

		ASSERT(st->tsoft_acaptr);

		pci_config_put16(st->tsoft_pcihdl,
		    st->tsoft_acaptr + AGP_CONF_CONTROL, 0x0);

		value2 = pci_config_get8(st->tsoft_pcihdl,
		    st->tsoft_acaptr + AGP_CONF_MISC);
		value2 &= ~AGP_MISC_APEN;
		pci_config_put8(st->tsoft_pcihdl,
		    st->tsoft_acaptr + AGP_CONF_MISC, value2);

		value1 = pci_config_get32(st->tsoft_pcihdl,
		    st->tsoft_acaptr + AGP_CONF_COMMAND);
		value1 &= ~AGPCMD_AGPEN;
		pci_config_put32(st->tsoft_pcihdl,
		    st->tsoft_acaptr + AGP_CONF_COMMAND,
		    value1);

		pci_config_put32(st->tsoft_pcihdl,
		    st->tsoft_acaptr + AGP_CONF_ATTBASE, 0x0);

		break;
	}

	default:
		mutex_exit(&st->tsoft_lock);
		return (ENXIO);
	} /* end switch */

	mutex_exit(&st->tsoft_lock);

	return (0);
}
예제 #15
0
/*
 * audio1575_chip_init()
 *
 * Description:
 *	This routine initializes the M1575 AC97 audio controller and the AC97
 *	codec.	The AC97 codec registers are programmed from codec_shadow[].
 *	If we are not doing a restore, we initialize codec_shadow[], otherwise
 *	we use the current values of shadow.	This routine expects that the
 *	PCI IO and Memory spaces have been mapped and enabled already.
 * Arguments:
 *	audio1575_state_t	*state		The device's state structure
 *						restore	from codec_shadow[]
 * Returns:
 *	DDI_SUCCESS	The hardware was initialized properly
 *	DDI_FAILURE	The hardware couldn't be initialized properly
 */
static int
audio1575_chip_init(audio1575_state_t *statep)
{
	uint32_t		ssr;
	uint32_t		rtsr;
	uint32_t		intrsr;
	int 			i;
	int			j;
#ifdef	__sparc
	uint8_t			clk_detect;
	ddi_acc_handle_t	pcih;
#endif
	clock_t			ticks;

	/*
	 * clear the interrupt control and status register
	 * READ/WRITE/READ workaround required
	 * for buggy hardware
	 */

	PUT32(M1575_INTRCR_REG, 0);
	(void) GET32(M1575_INTRCR_REG);

	intrsr = GET32(M1575_INTRSR_REG);
	PUT32(M1575_INTRSR_REG, (intrsr & M1575_INTR_MASK));
	(void) GET32(M1575_INTRSR_REG);

	ticks = drv_usectohz(M1575_LOOP_CTR);

	/*
	 * SADA only supports stereo, so we set the channel bits
	 * to "00" to select 2 channels.
	 * will also set the following:
	 *
	 * Disable double rate enable
	 * no SPDIF output selected
	 * 16 bit audio record mode
	 * 16 bit pcm out mode
	 * PCM Out 6 chan mode FL FR CEN BL BR LFE
	 * PCM Out 2 channel mode (00)
	 */
	for (i = 0; i < M1575_LOOP_CTR; i++) {
		/* Reset the AC97 Codec	and default to 2 channel 16 bit mode */
		PUT32(M1575_SCR_REG, M1575_SCR_COLDRST);
		delay(ticks<<1);

		/* Read the System Status Reg */
		ssr = GET32(M1575_SSR_REG);

		/* make sure and release the blocked reset bit */
		if (ssr & M1575_SSR_RSTBLK) {
			SET32(M1575_INTFCR_REG, M1575_INTFCR_RSTREL);
			delay(ticks);

			/* Read the System Status Reg */
			ssr = GET32(M1575_SSR_REG);

			/* make sure and release the blocked reset bit */
			if (ssr & M1575_SSR_RSTBLK) {
				return (DDI_FAILURE);
			}

			/* Reset the controller */
			PUT32(M1575_SCR_REG, M1575_SCR_COLDRST);
			delay(ticks);
		}

		/* according AC'97 spec, wait for codec reset */
		for (j = 0; j < M1575_LOOP_CTR; j++) {
			if ((GET32(M1575_SCR_REG) & M1575_SCR_COLDRST) == 0) {
				break;
			}
			delay(ticks);
		}

		/* codec reset failed */
		if (j >= M1575_LOOP_CTR) {
			audio_dev_warn(statep->adev,
			    "failure to reset codec");
			return (DDI_FAILURE);
		}

		/*
		 * Wait for FACRDY First codec ready. The hardware can
		 * provide the state of
		 * codec ready bit on SDATA_IN[0] and as reflected in
		 * the Recv Tag Slot Reg.
		 */
		rtsr = GET32(M1575_RTSR_REG);
		if (rtsr & M1575_RTSR_FACRDY) {
			break;
		} else { /* reset the status and wait for new status to set */
			rtsr |= M1575_RTSR_FACRDY;
			PUT32(M1575_RTSR_REG, rtsr);
			drv_usecwait(10);
		}
	}

	/* if we could not reset the AC97 codec then report failure */
	if (i >= M1575_LOOP_CTR) {
		audio_dev_warn(statep->adev,
		    "no codec ready signal received");
		return (DDI_FAILURE);
	}

#ifdef	__sparc
	/* Magic code from ULi to Turn on the AC_LINK clock */
	pcih = statep->pcih;
	pci_config_put8(pcih, M1575_PCIACD_REG, 0);
	pci_config_put8(pcih, M1575_PCIACD_REG, 4);
	pci_config_put8(pcih, M1575_PCIACD_REG, 0);
	(void) pci_config_get8(pcih, M1575_PCIACD_REG);
	pci_config_put8(pcih, M1575_PCIACD_REG, 2);
	pci_config_put8(pcih, M1575_PCIACD_REG, 0);
	clk_detect = pci_config_get8(pcih, M1575_PCIACD_REG);

	if (clk_detect != 1) {
		audio_dev_warn(statep->adev, "No AC97 Clock Detected");
		return (DDI_FAILURE);
	}
#endif

	/* Magic code from Uli to Init FIFO1 and FIFO2 */
	PUT32(M1575_FIFOCR1_REG, 0x81818181);
	PUT32(M1575_FIFOCR2_REG, 0x81818181);
	PUT32(M1575_FIFOCR3_REG, 0x81818181);

	/* Make sure that PCM in and PCM out are enabled */
	SET32(M1575_INTFCR_REG, (M1575_INTFCR_PCMIENB | M1575_INTFCR_PCMOENB));

	audio1575_dma_stop(statep, B_FALSE);

	return (DDI_SUCCESS);
}
예제 #16
0
파일: ehci.c 프로젝트: andreiw/polaris
/*
 * ehci_attach:
 *
 * Description: Attach entry point is called by the Kernel.
 *		Allocates resources for each EHCI host controller instance.
 *		Initializes the EHCI Host Controller.
 *
 * Return     : DDI_SUCCESS / DDI_FAILURE.
 */
static int
ehci_attach(dev_info_t		*dip,
	ddi_attach_cmd_t	cmd)
{
	int			instance;
	ehci_state_t		*ehcip = NULL;
	usba_hcdi_register_args_t hcdi_args;

	switch (cmd) {
	case DDI_ATTACH:
		break;
	case DDI_RESUME:
		ehcip = ehci_obtain_state(dip);

		return (ehci_cpr_resume(ehcip));
	default:
		return (DDI_FAILURE);
	}

	/* Get the instance and create soft state */
	instance = ddi_get_instance(dip);

	if (ddi_soft_state_zalloc(ehci_statep, instance) != 0) {

		return (DDI_FAILURE);
	}

	ehcip = ddi_get_soft_state(ehci_statep, instance);
	if (ehcip == NULL) {

		return (DDI_FAILURE);
	}

	ehcip->ehci_flags = EHCI_ATTACH;

	ehcip->ehci_log_hdl = usb_alloc_log_hdl(dip, "ehci", &ehci_errlevel,
	    &ehci_errmask, &ehci_instance_debug, 0);

	ehcip->ehci_flags |= EHCI_ZALLOC;

	/* Set host controller soft state to initialization */
	ehcip->ehci_hc_soft_state = EHCI_CTLR_INIT_STATE;

	USB_DPRINTF_L4(PRINT_MASK_ATTA, ehcip->ehci_log_hdl,
	    "ehcip = 0x%p", (void *)ehcip);

	/* Initialize the DMA attributes */
	ehci_set_dma_attributes(ehcip);

	/* Save the dip and instance */
	ehcip->ehci_dip = dip;
	ehcip->ehci_instance = instance;

	/* Initialize the DMA attributes */
	ehci_create_stats(ehcip);

	/* Create the qtd and qh pools */
	if (ehci_allocate_pools(ehcip) != DDI_SUCCESS) {
		(void) ehci_cleanup(ehcip);

		return (DDI_FAILURE);
	}

	/* Initialize the isochronous resources */
	if (ehci_isoc_init(ehcip) != DDI_SUCCESS) {
		(void) ehci_cleanup(ehcip);

		return (DDI_FAILURE);
	}

	/* Map the registers */
	if (ehci_map_regs(ehcip) != DDI_SUCCESS) {
		(void) ehci_cleanup(ehcip);

		return (DDI_FAILURE);
	}

	/* Get the ehci chip vendor and device id */
	ehcip->ehci_vendor_id = pci_config_get16(
	    ehcip->ehci_config_handle, PCI_CONF_VENID);
	ehcip->ehci_device_id = pci_config_get16(
	    ehcip->ehci_config_handle, PCI_CONF_DEVID);
	ehcip->ehci_rev_id = pci_config_get8(
	    ehcip->ehci_config_handle, PCI_CONF_REVID);

	/* Register interrupts */
	if (ehci_register_intrs_and_init_mutex(ehcip) != DDI_SUCCESS) {
		(void) ehci_cleanup(ehcip);

		return (DDI_FAILURE);
	}

	mutex_enter(&ehcip->ehci_int_mutex);

	/* Initialize the controller */
	if (ehci_init_ctlr(ehcip, EHCI_NORMAL_INITIALIZATION) != DDI_SUCCESS) {
		mutex_exit(&ehcip->ehci_int_mutex);
		(void) ehci_cleanup(ehcip);

		return (DDI_FAILURE);
	}

	/*
	 * At this point, the hardware will be okay.
	 * Initialize the usba_hcdi structure
	 */
	ehcip->ehci_hcdi_ops = ehci_alloc_hcdi_ops(ehcip);

	mutex_exit(&ehcip->ehci_int_mutex);

	/*
	 * Make this HCD instance known to USBA
	 * (dma_attr must be passed for USBA busctl's)
	 */
	hcdi_args.usba_hcdi_register_version = HCDI_REGISTER_VERSION;
	hcdi_args.usba_hcdi_register_dip = dip;
	hcdi_args.usba_hcdi_register_ops = ehcip->ehci_hcdi_ops;
	hcdi_args.usba_hcdi_register_dma_attr = &ehcip->ehci_dma_attr;

	/*
	 * Priority and iblock_cookie are one and the same
	 * (However, retaining hcdi_soft_iblock_cookie for now
	 * assigning it w/ priority. In future all iblock_cookie
	 * could just go)
	 */
	hcdi_args.usba_hcdi_register_iblock_cookie =
	    (ddi_iblock_cookie_t)(uintptr_t)ehcip->ehci_intr_pri;

	if (usba_hcdi_register(&hcdi_args, 0) != DDI_SUCCESS) {
		(void) ehci_cleanup(ehcip);

		return (DDI_FAILURE);
	}

	ehcip->ehci_flags |= EHCI_USBAREG;

	mutex_enter(&ehcip->ehci_int_mutex);

	if ((ehci_init_root_hub(ehcip)) != USB_SUCCESS) {
		mutex_exit(&ehcip->ehci_int_mutex);
		(void) ehci_cleanup(ehcip);

		return (DDI_FAILURE);
	}

	mutex_exit(&ehcip->ehci_int_mutex);

	/* Finally load the root hub driver */
	if (ehci_load_root_hub_driver(ehcip) != USB_SUCCESS) {
		(void) ehci_cleanup(ehcip);

		return (DDI_FAILURE);
	}
	ehcip->ehci_flags |= EHCI_RHREG;

	/* Display information in the banner */
	ddi_report_dev(dip);

	mutex_enter(&ehcip->ehci_int_mutex);

	/* Reset the ehci initialization flag */
	ehcip->ehci_flags &= ~EHCI_ATTACH;

	/* Print the Host Control's Operational registers */
	ehci_print_caps(ehcip);
	ehci_print_regs(ehcip);

	(void) pci_report_pmcap(dip, PCI_PM_IDLESPEED, (void *)4000);

	mutex_exit(&ehcip->ehci_int_mutex);

	USB_DPRINTF_L4(PRINT_MASK_ATTA, ehcip->ehci_log_hdl,
	    "ehci_attach: dip = 0x%p done", (void *)dip);

	return (DDI_SUCCESS);
}
예제 #17
0
/*
 * Save the configuration registers for cdip as a property
 * so that it persists after detach/uninitchild.
 */
int
pci_save_config_regs(dev_info_t *dip)
{
	ddi_acc_handle_t confhdl;
	pci_config_header_state_t *chsp;
	pci_cap_save_desc_t *pci_cap_descp;
	int ret;
	uint32_t i, ncaps, nwords;
	uint32_t *regbuf, *p;
	uint8_t *maskbuf;
	size_t maskbufsz, regbufsz, capbufsz;
	ddi_acc_hdl_t *hp;
	off_t offset = 0;
	uint8_t cap_ptr, cap_id;
	int pcie = 0;
	PMD(PMD_SX, ("pci_save_config_regs %s:%d\n", ddi_driver_name(dip),
	    ddi_get_instance(dip)))

	if (pci_config_setup(dip, &confhdl) != DDI_SUCCESS) {
		cmn_err(CE_WARN, "%s%d can't get config handle",
		    ddi_driver_name(dip), ddi_get_instance(dip));

		return (DDI_FAILURE);
	}
	/*
	 * Determine if it is a pci express device. If it is, save entire
	 * 4k config space treating it as a array of 32 bit integers.
	 * If it is not, do it in a usual PCI way.
	 */
	cap_ptr = pci_config_get8(confhdl, PCI_BCNF_CAP_PTR);
	/*
	 * Walk the capabilities searching for pci express capability
	 */
	while (cap_ptr != PCI_CAP_NEXT_PTR_NULL) {
		cap_id = pci_config_get8(confhdl,
		    cap_ptr + PCI_CAP_ID);
		if (cap_id == PCI_CAP_ID_PCI_E) {
			pcie = 1;
			break;
		}
		cap_ptr = pci_config_get8(confhdl,
		    cap_ptr + PCI_CAP_NEXT_PTR);
	}

	if (pcie) {
		/* PCI express device. Can have data in all 4k space */
		regbuf = (uint32_t *)kmem_zalloc((size_t)PCIE_CONF_HDR_SIZE,
		    KM_SLEEP);
		p = regbuf;
		/*
		 * Allocate space for mask.
		 * mask size is 128 bytes (4096 / 4 / 8 )
		 */
		maskbufsz = (size_t)((PCIE_CONF_HDR_SIZE/ sizeof (uint32_t)) >>
		    INDEX_SHIFT);
		maskbuf = (uint8_t *)kmem_zalloc(maskbufsz, KM_SLEEP);
		hp = impl_acc_hdl_get(confhdl);
		for (i = 0; i < (PCIE_CONF_HDR_SIZE / sizeof (uint32_t)); i++) {
			if (ddi_peek32(dip, (int32_t *)(hp->ah_addr + offset),
			    (int32_t *)p) == DDI_SUCCESS) {
				/* it is readable register. set the bit */
				maskbuf[i >> INDEX_SHIFT] |=
				    (uint8_t)(1 << (i & BITMASK));
			}
			p++;
			offset += sizeof (uint32_t);
		}

		if ((ret = ndi_prop_update_byte_array(DDI_DEV_T_NONE, dip,
		    SAVED_CONFIG_REGS_MASK, (uchar_t *)maskbuf,
		    maskbufsz)) != DDI_PROP_SUCCESS) {
			cmn_err(CE_WARN, "couldn't create %s property while"
			    "saving config space for %s@%d\n",
			    SAVED_CONFIG_REGS_MASK, ddi_driver_name(dip),
			    ddi_get_instance(dip));
		} else if ((ret = ndi_prop_update_byte_array(DDI_DEV_T_NONE,
		    dip, SAVED_CONFIG_REGS, (uchar_t *)regbuf,
		    (size_t)PCIE_CONF_HDR_SIZE)) != DDI_PROP_SUCCESS) {
			(void) ddi_prop_remove(DDI_DEV_T_NONE, dip,
			    SAVED_CONFIG_REGS_MASK);
			cmn_err(CE_WARN, "%s%d can't update prop %s",
			    ddi_driver_name(dip), ddi_get_instance(dip),
			    SAVED_CONFIG_REGS);
		}

		kmem_free(maskbuf, (size_t)maskbufsz);
		kmem_free(regbuf, (size_t)PCIE_CONF_HDR_SIZE);
	} else {
예제 #18
0
static int
ppb_initchild(dev_info_t *child)
{
	char name[MAXNAMELEN];
	ddi_acc_handle_t config_handle;
	ushort_t command_preserve, command;
	uint_t n;
	ushort_t bcr;
	uchar_t header_type;
	uchar_t min_gnt, latency_timer;
	ppb_devstate_t *ppb;

	/*
	 * Name the child
	 */
	if (ppb_name_child(child, name, MAXNAMELEN) != DDI_SUCCESS)
		return (DDI_FAILURE);

	ddi_set_name_addr(child, name);
	ddi_set_parent_data(child, NULL);

	/*
	 * Pseudo nodes indicate a prototype node with per-instance
	 * properties to be merged into the real h/w device node.
	 * The interpretation of the unit-address is DD[,F]
	 * where DD is the device id and F is the function.
	 */
	if (ndi_dev_is_persistent_node(child) == 0) {
		extern int pci_allow_pseudo_children;

		/*
		 * Try to merge the properties from this prototype
		 * node into real h/w nodes.
		 */
		if (ndi_merge_node(child, ppb_name_child) == DDI_SUCCESS) {
			/*
			 * Merged ok - return failure to remove the node.
			 */
			ppb_removechild(child);
			return (DDI_FAILURE);
		}

		/* workaround for ddivs to run under PCI */
		if (pci_allow_pseudo_children)
			return (DDI_SUCCESS);

		/*
		 * The child was not merged into a h/w node,
		 * but there's not much we can do with it other
		 * than return failure to cause the node to be removed.
		 */
		cmn_err(CE_WARN, "!%s@%s: %s.conf properties not merged",
		    ddi_driver_name(child), ddi_get_name_addr(child),
		    ddi_driver_name(child));
		ppb_removechild(child);
		return (DDI_NOT_WELL_FORMED);
	}

	ppb = (ppb_devstate_t *)ddi_get_soft_state(ppb_state,
	    ddi_get_instance(ddi_get_parent(child)));

	ddi_set_parent_data(child, NULL);

	/*
	 * If hardware is PM capable, set up the power info structure.
	 * This also ensures the the bus will not be off (0MHz) otherwise
	 * system panics during a bus access.
	 */
	if (PM_CAPABLE(ppb->ppb_pwr_p)) {
		/*
		 * Create a pwr_info struct for child.  Bus will be
		 * at full speed after creating info.
		 */
		pci_pwr_create_info(ppb->ppb_pwr_p, child);
#ifdef DEBUG
		ASSERT(ppb->ppb_pwr_p->current_lvl == PM_LEVEL_B0);
#endif
	}

	/*
	 * If configuration registers were previously saved by
	 * child (before it entered D3), then let the child do the
	 * restore to set up the config regs as it'll first need to
	 * power the device out of D3.
	 */
	if (ddi_prop_exists(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
	    "config-regs-saved-by-child") == 1) {
		DEBUG2(DBG_PWR, ddi_get_parent(child),
		    "INITCHILD: config regs to be restored by child"
		    " for %s@%s\n", ddi_node_name(child),
		    ddi_get_name_addr(child));

		return (DDI_SUCCESS);
	}

	DEBUG2(DBG_PWR, ddi_get_parent(child),
	    "INITCHILD: config regs setup for %s@%s\n",
	    ddi_node_name(child), ddi_get_name_addr(child));

	if (pci_config_setup(child, &config_handle) != DDI_SUCCESS) {
		if (PM_CAPABLE(ppb->ppb_pwr_p)) {
			pci_pwr_rm_info(ppb->ppb_pwr_p, child);
		}

		return (DDI_FAILURE);
	}

	/*
	 * Determine the configuration header type.
	 */
	header_type = pci_config_get8(config_handle, PCI_CONF_HEADER);

	/*
	 * Support for the "command-preserve" property.
	 */
	command_preserve = ddi_prop_get_int(DDI_DEV_T_ANY, child,
	    DDI_PROP_DONTPASS, "command-preserve", 0);
	command = pci_config_get16(config_handle, PCI_CONF_COMM);
	command &= (command_preserve | PCI_COMM_BACK2BACK_ENAB);
	command |= (ppb_command_default & ~command_preserve);
	pci_config_put16(config_handle, PCI_CONF_COMM, command);

	/*
	 * If the device has a bus control register then program it
	 * based on the settings in the command register.
	 */
	if ((header_type  & PCI_HEADER_TYPE_M) == PCI_HEADER_ONE) {
		bcr = pci_config_get8(config_handle, PCI_BCNF_BCNTRL);
		if (ppb_command_default & PCI_COMM_PARITY_DETECT)
			bcr |= PCI_BCNF_BCNTRL_PARITY_ENABLE;
		if (ppb_command_default & PCI_COMM_SERR_ENABLE)
			bcr |= PCI_BCNF_BCNTRL_SERR_ENABLE;
		bcr |= PCI_BCNF_BCNTRL_MAST_AB_MODE;
		pci_config_put8(config_handle, PCI_BCNF_BCNTRL, bcr);
	}

	/*
	 * Initialize cache-line-size configuration register if needed.
	 */
	if (ppb_set_cache_line_size_register &&
	    ddi_getprop(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
	    "cache-line-size", 0) == 0) {
		pci_config_put8(config_handle, PCI_CONF_CACHE_LINESZ,
		    ppb->ppb_cache_line_size);
		n = pci_config_get8(config_handle, PCI_CONF_CACHE_LINESZ);
		if (n != 0) {
			(void) ndi_prop_update_int(DDI_DEV_T_NONE, child,
			    "cache-line-size", n);
		}
	}

	/*
	 * Initialize latency timer configuration registers if needed.
	 */
	if (ppb_set_latency_timer_register &&
	    ddi_getprop(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
	    "latency-timer", 0) == 0) {

		if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_ONE) {
			latency_timer = ppb->ppb_latency_timer;
			pci_config_put8(config_handle, PCI_BCNF_LATENCY_TIMER,
			    ppb->ppb_latency_timer);
		} else {
			min_gnt = pci_config_get8(config_handle,
			    PCI_CONF_MIN_G);
			latency_timer = min_gnt * 8;
		}
		pci_config_put8(config_handle, PCI_CONF_LATENCY_TIMER,
		    latency_timer);
		n = pci_config_get8(config_handle, PCI_CONF_LATENCY_TIMER);
		if (n != 0) {
			(void) ndi_prop_update_int(DDI_DEV_T_NONE, child,
			    "latency-timer", n);
		}
	}

	/*
	 * SPARC PCIe FMA specific
	 *
	 * Note: parent_data for parent is created only if this is sparc PCI-E
	 * platform, for which, SG take a different route to handle device
	 * errors.
	 */
	if (ppb->parent_bus == PCIE_PCIECAP_DEV_TYPE_PCIE_DEV) {
		if (pcie_init_cfghdl(child) != DDI_SUCCESS) {
			pci_config_teardown(&config_handle);
			return (DDI_FAILURE);
		}
		pcie_init_dom(child);
	}

	/*
	 * Check to see if the XMITS/PCI-X workaround applies.
	 */
	n = ddi_getprop(DDI_DEV_T_ANY, child, DDI_PROP_NOTPROM,
	    "pcix-update-cmd-reg", -1);

	if (n != -1) {
		extern void pcix_set_cmd_reg(dev_info_t *child, uint16_t value);
		DEBUG1(DBG_INIT_CLD, child, "Turning on XMITS NCPQ "
		    "Workaround: value = %x\n", n);
		pcix_set_cmd_reg(child, n);
	}
	pci_config_teardown(&config_handle);
	return (DDI_SUCCESS);
}
예제 #19
0
파일: agptarget.c 프로젝트: andreiw/polaris
/*
 * agp_target_get_apsize()
 *
 * Description:
 * 	This function gets the AGP aperture size by reading the AGP aperture
 * 	size register.
 * Arguments:
 * 	softstate		driver soft state pointer
 *
 * Return:
 * 	size		The AGP aperture size in megabytes
 * 	0		an unexpected error
 */
static size_t
agp_target_get_apsize(agp_target_softstate_t *softstate)
{
	off_t cap;
	uint16_t value;
	size_t size, regsize;

	ASSERT(softstate->tsoft_acaptr);
	cap = softstate->tsoft_acaptr;

	if ((softstate->tsoft_devid & VENDOR_ID_MASK) == INTEL_VENDOR_ID) {
		/* extend this value to 16 bit for later tests */
		value = (uint16_t)pci_config_get8(softstate->tsoft_pcihdl,
		    cap + AGP_CONF_APERSIZE) | AGP_APER_SIZE_MASK;
	} else {
		value = pci_config_get16(softstate->tsoft_pcihdl,
		    cap + AGP_CONF_APERSIZE);
	}

	if (value & AGP_APER_128M_MASK) {
		switch (value & AGP_APER_128M_MASK) {
			case AGP_APER_4M:
				size = 4; /* 4M */
				break;
			case AGP_APER_8M:
				size = 8; /* 8M */
				break;
			case AGP_APER_16M:
				size = 16; /* 16M */
				break;
			case AGP_APER_32M:
				size = 32; /* 32M */
				break;
			case AGP_APER_64M:
				size = 64; /* 64M */
				break;
			case AGP_APER_128M:
				size = 128; /* 128M */
				break;
			default:
				size = 0; /* not true */
		}
	} else {
		switch (value & AGP_APER_4G_MASK) {
			case AGP_APER_256M:
				size = 256; /* 256 M */
				break;
			case AGP_APER_512M:
				size = 512; /* 512 M */
				break;
			case AGP_APER_1024M:
				size = 1024; /* 1024 M */
				break;
			case AGP_APER_2048M:
				size = 2048; /* 2048 M */
				break;
			case AGP_APER_4G:
				size = 4096; /* 4096 M */
				break;
			default:
				size = 0; /* not true */
		}
	}
	/*
	 * In some cases, there is no APSIZE register, so the size value
	 * of 256M could be wrong. Check the value by reading the size of
	 * the first register which was set in the PCI configuration space.
	 */
	if (size == 256) {
		if (ddi_dev_regsize(softstate->tsoft_dip,
		    AGP_TARGET_BAR1, (off_t *)&regsize) == DDI_FAILURE)
			return (0);

		if (MB2BYTES(size) != regsize) {
			TARGETDB_PRINT2((CE_WARN,
			    "APSIZE 256M doesn't match regsize %lx",
			    regsize));
			TARGETDB_PRINT2((CE_WARN, "Use regsize instead"));
			size = BYTES2MB(regsize);
		}
	}

	return (size);
}
예제 #20
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);
}
예제 #21
0
/*
 * audioixp_attach()
 *
 * Description:
 *	Attach an instance of the audioixp driver. This routine does
 * 	the device dependent attach tasks.
 *
 * Arguments:
 *	dev_info_t	*dip	Pointer to the device's dev_info struct
 *	ddi_attach_cmd_t cmd	Attach command
 *
 * Returns:
 *	DDI_SUCCESS		The driver was initialized properly
 *	DDI_FAILURE		The driver couldn't be initialized properly
 */
static int
audioixp_attach(dev_info_t *dip)
{
	uint16_t		cmdeg;
	audioixp_state_t	*statep;
	audio_dev_t		*adev;
	uint32_t		devid;
	const char		*name;
	const char		*rev;

	/* we don't support high level interrupts in the driver */
	if (ddi_intr_hilevel(dip, 0) != 0) {
		cmn_err(CE_WARN,
		    "!%s%d: unsupported high level interrupt",
		    ddi_driver_name(dip), ddi_get_instance(dip));
		return (DDI_FAILURE);
	}

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

	if (ddi_get_iblock_cookie(dip, 0, &statep->iblock) != DDI_SUCCESS) {
		cmn_err(CE_WARN,
		    "!%s%d: cannot get iblock cookie",
		    ddi_driver_name(dip), ddi_get_instance(dip));
		kmem_free(statep, sizeof (*statep));
		return (DDI_FAILURE);
	}
	mutex_init(&statep->inst_lock, NULL, MUTEX_DRIVER, statep->iblock);

	/* allocate framework audio device */
	if ((adev = audio_dev_alloc(dip, 0)) == NULL) {
		cmn_err(CE_WARN, "!%s%d: unable to allocate audio dev",
		    ddi_driver_name(dip), ddi_get_instance(dip));
		goto error;
	}
	statep->adev = adev;

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

	/* set device information -- this could be smarter */
	devid = ((pci_config_get16(statep->pcih, PCI_CONF_VENID)) << 16) |
	    pci_config_get16(statep->pcih, PCI_CONF_DEVID);

	name = "ATI AC'97";
	switch (devid) {
	case IXP_PCI_ID_200:
		rev = "IXP150";
		break;
	case IXP_PCI_ID_300:
		rev = "SB300";
		break;
	case IXP_PCI_ID_400:
		if (pci_config_get8(statep->pcih, PCI_CONF_REVID) & 0x80) {
			rev = "SB450";
		} else {
			rev = "SB400";
		}
		break;
	case IXP_PCI_ID_SB600:
		rev = "SB600";
		break;
	default:
		rev = "Unknown";
		break;
	}
	audio_dev_set_description(adev, name);
	audio_dev_set_version(adev, rev);

	/* allocate port structures */
	if ((audioixp_alloc_port(statep, IXP_PLAY) != DDI_SUCCESS) ||
	    (audioixp_alloc_port(statep, IXP_REC) != DDI_SUCCESS)) {
		goto error;
	}

	statep->ac97 = ac97_alloc(dip, audioixp_rd97, audioixp_wr97, statep);
	if (statep->ac97 == NULL) {
		audio_dev_warn(adev, "failed to allocate ac97 handle");
		goto error;
	}

	/* set PCI command register */
	cmdeg = pci_config_get16(statep->pcih, PCI_CONF_COMM);
	pci_config_put16(statep->pcih, PCI_CONF_COMM,
	    cmdeg | PCI_COMM_IO | PCI_COMM_MAE);

	/* set up kernel statistics */
	if ((statep->ksp = kstat_create(IXP_NAME, ddi_get_instance(dip),
	    IXP_NAME, "controller", KSTAT_TYPE_INTR, 1,
	    KSTAT_FLAG_PERSISTENT)) != NULL) {
		kstat_install(statep->ksp);
	}


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

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

	/* set up the interrupt handler */
	if (ddi_add_intr(dip, 0, &statep->iblock, NULL, audioixp_intr,
	    (caddr_t)statep) != DDI_SUCCESS) {
		audio_dev_warn(adev, "bad interrupt specification");
	}
	statep->intr_added = B_TRUE;

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

	ddi_report_dev(dip);

	return (DDI_SUCCESS);

error:
	audioixp_destroy(statep);
	return (DDI_FAILURE);
}
예제 #22
0
void
t4_os_pci_read_cfg1(struct adapter *sc, int reg, uint8_t *val)
{
    *val = pci_config_get8(sc->pci_regh, reg);
}
예제 #23
0
파일: smcp.c 프로젝트: andreiw/polaris
int
UM_PCI_Services(Adapter_Struc *pAd, union REGS *pregs)
{
	int func = (int)pregs->h.al;
	unsigned long regnum; /* register number */
	unsigned short vendid;
	unsigned short devid;
	unsigned long compval;

	switch (func) {
		case PCI_BIOS_PRESENT:
			/* return PCI present with rev 2.1 */
			pregs->h.ah = 0;
			pregs->h.al = 0;
			pregs->h.bh = 2;
			pregs->h.bl = 1;
			pregs->h.cl = 1;
			pregs->e.edx = 0x20494350;
			pregs->x.cflag = 0;
			break;
		case FIND_PCI_DEVICE:
			vendid = pregs->x.dx;
			devid = pregs->x.cx;
			compval = (((ulong_t)devid) << 16) | ((ulong_t)vendid);
			if (vendid == 0xffff) { /* bad vendor id */
				pregs->x.cflag = 1;
				pregs->h.ah = PCI_BAD_VENDOR_ID;
			} else {
				if (pci_config_get32(
				    (ddi_acc_handle_t)pAd->pcihandle, 0) ==
				    compval) {
					pregs->h.bh = 0; /* put 0 to fake it */
					pregs->h.bl = 0; /* put 0 to fake it */
					pregs->h.ah = PCI_SUCCESSFUL;
					pregs->x.cflag = 0;
				} else {
					pregs->h.ah = PCI_DEVICE_NOT_FOUND;
					pregs->x.cflag = 1;
				}
			}
			break;
		case PCI_READ_CONFIG_BYTE:
			regnum = (unsigned long) pregs->h.di;
			pregs->h.cl = pci_config_get8(
			    (ddi_acc_handle_t)pAd->pcihandle, regnum);
			pregs->x.cflag = 0;
			pregs->h.ah = PCI_SUCCESSFUL;
			break;
		case PCI_READ_CONFIG_WORD:
			regnum = (unsigned long)pregs->h.di;
			if (regnum & 0x1) {
				pregs->x.cflag = 1;
				pregs->h.ah = PCI_BAD_REGISTER_NUMBER;
			} else {
				pregs->x.cx = pci_config_get16(
				    (ddi_acc_handle_t)pAd->pcihandle, regnum);
				pregs->x.cflag = 0;
				pregs->h.ah = PCI_SUCCESSFUL;
			}
			break;
		case PCI_READ_CONFIG_DWORD:
			regnum = (unsigned long)pregs->h.di;
			if (regnum & 0x3) {
				pregs->x.cflag = 1;
				pregs->h.ah = PCI_BAD_REGISTER_NUMBER;
			} else {
				pregs->e.ecx = pci_config_get32(
				    (ddi_acc_handle_t)pAd->pcihandle, regnum);
				pregs->x.cflag = 0;
				pregs->h.ah = PCI_SUCCESSFUL;
			}
			break;
		case PCI_WRITE_CONFIG_BYTE:
			regnum = (unsigned long) pregs->h.di;
			pci_config_put8((ddi_acc_handle_t)pAd->pcihandle,
			    regnum, pregs->h.cl);
			pregs->x.cflag = 0;
			pregs->h.ah = PCI_SUCCESSFUL;
			break;
		case PCI_WRITE_CONFIG_WORD:
			regnum = (unsigned long)pregs->h.di;
			if (regnum & 0x1) {
				pregs->x.cflag = 1;
				pregs->h.ah = PCI_BAD_REGISTER_NUMBER;
			} else {
				pci_config_put16(
				    (ddi_acc_handle_t)pAd->pcihandle,
				    regnum, pregs->x.cx);
				pregs->x.cflag = 0;
				pregs->h.ah = PCI_SUCCESSFUL;
			}
			break;
		case PCI_WRITE_CONFIG_DWORD:
			regnum = (unsigned long)pregs->h.di;
			if (regnum & 0x1) {
				pregs->x.cflag = 1;
				pregs->h.ah = PCI_BAD_REGISTER_NUMBER;
			} else {
				pci_config_put32(
				    (ddi_acc_handle_t)pAd->pcihandle,
				    regnum, pregs->e.ecx);
				pregs->x.cflag = 0;
				pregs->h.ah = PCI_SUCCESSFUL;
			}
			break;
		default:
			pregs->x.cflag = 1;	/* set error */
			pregs->h.ah = PCI_FUNC_NOT_SUPPORTED;
			break;
	}
	return (0);
}
예제 #24
0
static void
ppb_create_ranges_prop(dev_info_t *dip,
	ddi_acc_handle_t config_handle)
{
	uint32_t base, limit;
	ppb_ranges_t	ranges[PPB_RANGE_LEN];
	uint8_t io_base_lo, io_limit_lo;
	uint16_t io_base_hi, io_limit_hi, mem_base, mem_limit;
	int i = 0, rangelen = sizeof (ppb_ranges_t)/sizeof (int);

	io_base_lo = pci_config_get8(config_handle, PCI_BCNF_IO_BASE_LOW);
	io_limit_lo = pci_config_get8(config_handle, PCI_BCNF_IO_LIMIT_LOW);
	io_base_hi = pci_config_get16(config_handle, PCI_BCNF_IO_BASE_HI);
	io_limit_hi = pci_config_get16(config_handle, PCI_BCNF_IO_LIMIT_HI);
	mem_base = pci_config_get16(config_handle, PCI_BCNF_MEM_BASE);
	mem_limit = pci_config_get16(config_handle, PCI_BCNF_MEM_LIMIT);

	/*
	 * Create ranges for IO space
	 */
	ranges[i].size_low = ranges[i].size_high = 0;
	ranges[i].parent_mid = ranges[i].child_mid =
	    ranges[i].parent_high = 0;
	ranges[i].child_high = ranges[i].parent_high |=
	    (PCI_REG_REL_M | PCI_ADDR_IO);
	base = PPB_16bit_IOADDR(io_base_lo);
	limit = PPB_16bit_IOADDR(io_limit_lo);

	/*
	 * Check for 32-bit I/O support as per PCI-to-PCI Bridge Arch Spec
	 */
	if ((io_base_lo & 0xf) == PPB_32BIT_IO) {
		base = PPB_LADDR(base, io_base_hi);
		limit = PPB_LADDR(limit, io_limit_hi);
	}

	/*
	 * Check if the bridge implements an I/O address range as per
	 * PCI-to-PCI Bridge Arch Spec
	 */
	if ((io_base_lo != 0 || io_limit_lo != 0) && limit >= base) {
		ranges[i].parent_low = ranges[i].child_low =
		    base;
		ranges[i].size_low = limit - base + PPB_IOGRAIN;
		i++;
	}

	/*
	 * Create ranges for 32bit memory space
	 */
	base = PPB_32bit_MEMADDR(mem_base);
	limit = PPB_32bit_MEMADDR(mem_limit);
	ranges[i].size_low = ranges[i].size_high = 0;
	ranges[i].parent_mid = ranges[i].child_mid =
	    ranges[i].parent_high = 0;
	ranges[i].child_high = ranges[i].parent_high |=
	    (PCI_REG_REL_M | PCI_ADDR_MEM32);
	ranges[i].child_low = ranges[i].parent_low = base;
	if (limit >= base) {
		ranges[i].size_low = limit - base + PPB_MEMGRAIN;
		i++;
	}

	if (i) {
		(void) ndi_prop_update_int_array(DDI_DEV_T_NONE, dip, "ranges",
		    (int *)ranges, i * rangelen);
	}
}
예제 #25
0
/*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);
}
예제 #26
0
파일: sil3xxx.c 프로젝트: andreiw/polaris
/*
 * 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);
}
예제 #27
0
void
pciconfig_dump(void *instance)
{
    struct e1000g *Adapter = (struct e1000g *)instance;
    ddi_acc_handle_t handle;
    uint8_t cap_ptr;
    uint8_t next_ptr;
    off_t offset;

    handle = Adapter->osdep.cfg_handle;

    e1000g_log(Adapter, CE_CONT, "Begin dump PCI config space\n");

    e1000g_log(Adapter, CE_CONT,
               "PCI_CONF_VENID:\t0x%x\n",
               pci_config_get16(handle, PCI_CONF_VENID));
    e1000g_log(Adapter, CE_CONT,
               "PCI_CONF_DEVID:\t0x%x\n",
               pci_config_get16(handle, PCI_CONF_DEVID));
    e1000g_log(Adapter, CE_CONT,
               "PCI_CONF_COMMAND:\t0x%x\n",
               pci_config_get16(handle, PCI_CONF_COMM));
    e1000g_log(Adapter, CE_CONT,
               "PCI_CONF_STATUS:\t0x%x\n",
               pci_config_get16(handle, PCI_CONF_STAT));
    e1000g_log(Adapter, CE_CONT,
               "PCI_CONF_REVID:\t0x%x\n",
               pci_config_get8(handle, PCI_CONF_REVID));
    e1000g_log(Adapter, CE_CONT,
               "PCI_CONF_PROG_CLASS:\t0x%x\n",
               pci_config_get8(handle, PCI_CONF_PROGCLASS));
    e1000g_log(Adapter, CE_CONT,
               "PCI_CONF_SUB_CLASS:\t0x%x\n",
               pci_config_get8(handle, PCI_CONF_SUBCLASS));
    e1000g_log(Adapter, CE_CONT,
               "PCI_CONF_BAS_CLASS:\t0x%x\n",
               pci_config_get8(handle, PCI_CONF_BASCLASS));
    e1000g_log(Adapter, CE_CONT,
               "PCI_CONF_CACHE_LINESZ:\t0x%x\n",
               pci_config_get8(handle, PCI_CONF_CACHE_LINESZ));
    e1000g_log(Adapter, CE_CONT,
               "PCI_CONF_LATENCY_TIMER:\t0x%x\n",
               pci_config_get8(handle, PCI_CONF_LATENCY_TIMER));
    e1000g_log(Adapter, CE_CONT,
               "PCI_CONF_HEADER_TYPE:\t0x%x\n",
               pci_config_get8(handle, PCI_CONF_HEADER));
    e1000g_log(Adapter, CE_CONT,
               "PCI_CONF_BIST:\t0x%x\n",
               pci_config_get8(handle, PCI_CONF_BIST));

    pciconfig_bar(Adapter, PCI_CONF_BASE0, "PCI_CONF_BASE0");
    pciconfig_bar(Adapter, PCI_CONF_BASE1, "PCI_CONF_BASE1");
    pciconfig_bar(Adapter, PCI_CONF_BASE2, "PCI_CONF_BASE2");
    pciconfig_bar(Adapter, PCI_CONF_BASE3, "PCI_CONF_BASE3");
    pciconfig_bar(Adapter, PCI_CONF_BASE4, "PCI_CONF_BASE4");
    pciconfig_bar(Adapter, PCI_CONF_BASE5, "PCI_CONF_BASE5");

    e1000g_log(Adapter, CE_CONT,
               "PCI_CONF_CIS:\t0x%x\n",
               pci_config_get32(handle, PCI_CONF_CIS));
    e1000g_log(Adapter, CE_CONT,
               "PCI_CONF_SUBVENID:\t0x%x\n",
               pci_config_get16(handle, PCI_CONF_SUBVENID));
    e1000g_log(Adapter, CE_CONT,
               "PCI_CONF_SUBSYSID:\t0x%x\n",
               pci_config_get16(handle, PCI_CONF_SUBSYSID));
    e1000g_log(Adapter, CE_CONT,
               "PCI_CONF_ROM:\t0x%x\n",
               pci_config_get32(handle, PCI_CONF_ROM));

    cap_ptr = pci_config_get8(handle, PCI_CONF_CAP_PTR);

    e1000g_log(Adapter, CE_CONT,
               "PCI_CONF_CAP_PTR:\t0x%x\n", cap_ptr);
    e1000g_log(Adapter, CE_CONT,
               "PCI_CONF_ILINE:\t0x%x\n",
               pci_config_get8(handle, PCI_CONF_ILINE));
    e1000g_log(Adapter, CE_CONT,
               "PCI_CONF_IPIN:\t0x%x\n",
               pci_config_get8(handle, PCI_CONF_IPIN));
    e1000g_log(Adapter, CE_CONT,
               "PCI_CONF_MIN_G:\t0x%x\n",
               pci_config_get8(handle, PCI_CONF_MIN_G));
    e1000g_log(Adapter, CE_CONT,
               "PCI_CONF_MAX_L:\t0x%x\n",
               pci_config_get8(handle, PCI_CONF_MAX_L));

    /* Power Management */
    offset = cap_ptr;

    e1000g_log(Adapter, CE_CONT,
               "PCI_PM_CAP_ID:\t0x%x\n",
               pci_config_get8(handle, offset));

    next_ptr = pci_config_get8(handle, offset + 1);

    e1000g_log(Adapter, CE_CONT,
               "PCI_PM_NEXT_PTR:\t0x%x\n", next_ptr);
    e1000g_log(Adapter, CE_CONT,
               "PCI_PM_CAP:\t0x%x\n",
               pci_config_get16(handle, offset + PCI_PMCAP));
    e1000g_log(Adapter, CE_CONT,
               "PCI_PM_CSR:\t0x%x\n",
               pci_config_get16(handle, offset + PCI_PMCSR));
    e1000g_log(Adapter, CE_CONT,
               "PCI_PM_CSR_BSE:\t0x%x\n",
               pci_config_get8(handle, offset + PCI_PMCSR_BSE));
    e1000g_log(Adapter, CE_CONT,
               "PCI_PM_DATA:\t0x%x\n",
               pci_config_get8(handle, offset + PCI_PMDATA));

    /* MSI Configuration */
    offset = next_ptr;

    e1000g_log(Adapter, CE_CONT,
               "PCI_MSI_CAP_ID:\t0x%x\n",
               pci_config_get8(handle, offset));

    next_ptr = pci_config_get8(handle, offset + 1);

    e1000g_log(Adapter, CE_CONT,
               "PCI_MSI_NEXT_PTR:\t0x%x\n", next_ptr);
    e1000g_log(Adapter, CE_CONT,
               "PCI_MSI_CTRL:\t0x%x\n",
               pci_config_get16(handle, offset + PCI_MSI_CTRL));
    e1000g_log(Adapter, CE_CONT,
               "PCI_MSI_ADDR:\t0x%x\n",
               pci_config_get32(handle, offset + PCI_MSI_ADDR_OFFSET));
    e1000g_log(Adapter, CE_CONT,
               "PCI_MSI_ADDR_HI:\t0x%x\n",
               pci_config_get32(handle, offset + 0x8));
    e1000g_log(Adapter, CE_CONT,
               "PCI_MSI_DATA:\t0x%x\n",
               pci_config_get16(handle, offset + 0xC));

    /* PCI Express Configuration */
    offset = next_ptr;

    e1000g_log(Adapter, CE_CONT,
               "PCIE_CAP_ID:\t0x%x\n",
               pci_config_get8(handle, offset + PCIE_CAP_ID));

    next_ptr = pci_config_get8(handle, offset + PCIE_CAP_NEXT_PTR);

    e1000g_log(Adapter, CE_CONT,
               "PCIE_CAP_NEXT_PTR:\t0x%x\n", next_ptr);
    e1000g_log(Adapter, CE_CONT,
               "PCIE_PCIECAP:\t0x%x\n",
               pci_config_get16(handle, offset + PCIE_PCIECAP));
    e1000g_log(Adapter, CE_CONT,
               "PCIE_DEVCAP:\t0x%x\n",
               pci_config_get32(handle, offset + PCIE_DEVCAP));
    e1000g_log(Adapter, CE_CONT,
               "PCIE_DEVCTL:\t0x%x\n",
               pci_config_get16(handle, offset + PCIE_DEVCTL));
    e1000g_log(Adapter, CE_CONT,
               "PCIE_DEVSTS:\t0x%x\n",
               pci_config_get16(handle, offset + PCIE_DEVSTS));
    e1000g_log(Adapter, CE_CONT,
               "PCIE_LINKCAP:\t0x%x\n",
               pci_config_get32(handle, offset + PCIE_LINKCAP));
    e1000g_log(Adapter, CE_CONT,
               "PCIE_LINKCTL:\t0x%x\n",
               pci_config_get16(handle, offset + PCIE_LINKCTL));
    e1000g_log(Adapter, CE_CONT,
               "PCIE_LINKSTS:\t0x%x\n",
               pci_config_get16(handle, offset + PCIE_LINKSTS));
}