px_util.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* PCI nexus utility routines:
* property and config routines for attach()
* reg/intr/range/assigned-address property routines for bus_map()
* init_child()
* fault handling
*/
#include <sys/sysmacros.h>
#include <sys/ddi_impldefs.h>
#include "px_obj.h"
#include "pcie_pwr.h"
#include <px_regs.h>
#include <px_csr.h>
/*LINTLIBRARY*/
/*
* px_get_props
*
* This function is called from the attach routine to get the key
* properties of the pci nodes.
*
* used by: px_attach()
*
* return value: DDI_FAILURE on failure
*/
int
{
int i, no_of_intrs;
/*
* Get the bus-ranges property.
*/
i = sizeof (px_p->px_bus_range);
return (DDI_FAILURE);
}
/*
* Get the interrupts property.
*/
return (DDI_FAILURE);
}
/*
* figure out number of interrupts in the "interrupts" property
* and convert them all into ino.
*/
i = CELLS_1275_TO_BYTES(i);
for (i = 0; i < no_of_intrs; i++)
/*
* Get the ranges property.
*/
DDI_SUCCESS) {
return (DDI_FAILURE);
}
"thermal-interrupt", -1);
return (DDI_SUCCESS);
}
/*
* px_free_props:
*
* This routine frees the memory used to cache the "interrupts"
* and "ranges" properties of the pci bus device node.
*
* used by: px_detach()
*
* return value: none
*/
void
{
}
/*
* px_reloc_reg
*
* If the "reg" entry (*px_rp) is relocatable, lookup "assigned-addresses"
* property to fetch corresponding relocated address.
*
* used by: px_map()
*
* return value:
*
* DDI_SUCCESS - on success
* DDI_ME_INVAL - regspec is invalid
*/
int
{
int assign_len, assign_entries, i;
return (DDI_SUCCESS);
/*
* Hot plug will be taken care of later
* if (px_p->hotplug_capable == B_FALSE)
*/
{
return (DDI_ME_INVAL);
}
}
if (i) {
return (DDI_ME_INVAL);
}
for (i = 0; i < assign_entries; i++, assign_p++) {
continue;
break;
}
if (space_type == PCI_ADDR_MEM64 &&
assign_type == PCI_ADDR_MEM32) {
break;
}
}
}
/*
* use "ranges" to translate relocated pci regspec into parent space
*/
int
{
int n;
if (reg_begin > PCI_CONF_HDR_SIZE)
return (DDI_ME_INVAL);
}
continue; /* not the same space type */
break;
}
if (n >= rng_n)
return (DDI_ME_REGSPEC_RANGE);
"\tpx_xlate_reg: entry %d new_rp %x.%x %x\n",
return (DDI_SUCCESS);
}
/*
* px_map_registers
*
* This function is called from the attach routine to map the registers
* accessed by this driver.
*
* used by: px_attach()
*
* return value: DDI_FAILURE on failure
*
* Remove px_map_regs() from here and move them to SUN4U library code,
* after complete virtualization (after porting MSI and Error handling code).
*/
int
{
/*
* PCI CSR Base
*/
goto fail;
}
reg_bank++;
/*
* XBUS CSR Base
*/
goto fail;
}
done:
}
return (DDI_SUCCESS);
fail:
}
return (DDI_FAILURE);
}
/*
* px_unmap_regs:
*
* This routine unmap the registers mapped by map_px_registers.
*
* used by: px_detach(), and error conditions in px_attach()
*
* return value: none
*/
void
{
int i;
for (i = 0; i < 4; i++) {
}
}
/*
* px_report_dev
*
* This function is called from our control ops routine on a
* DDI_CTLOPS_REPORTDEV request.
*
* The display format is
*
* <name><inst> at <pname><pinst> device <dev> function <func>
*
* where
*
* <name> this device's name property
* <inst> this device's instance number
* <name> parent device's name property
* <inst> parent device's instance number
* <dev> this device's device number
* <func> this device's function number
*/
int
{
if (dip == (dev_info_t *)0)
return (DDI_FAILURE);
return (DDI_SUCCESS);
}
/*
* reg property for pcimem nodes that covers the entire address
* space for the node: config, io, or memory.
*/
{
{PCI_ADDR_CONFIG, 0, 0, 0, 0x800000 },
};
/*
* px_name_child
*
* This function is called from init_child to name a node. It is
* also passed as a callback for node merging functions.
*
* return value: DDI_SUCCESS, DDI_FAILURE
*/
static int
{
int reglen;
char **unit_addr;
uint_t n;
/*
* Set the address portion of the node name based on
* unit-address property, if it exists.
* The interpretation of the unit-address is DD[,F]
* where DD is the device id and F is the function.
*/
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
/*
* The unit-address property is does not exist. Set the address
* portion of the node name based on the function and device number.
*/
if (((reglen * sizeof (int)) % sizeof (pci_regspec_t)) != 0) {
return (DDI_FAILURE);
}
if (func != 0)
else
return (DDI_SUCCESS);
}
return (DDI_FAILURE);
}
int
{
"DDI_CTLOPS_UNINITCHILD: arg=%s%d\n",
return (DDI_SUCCESS);
}
/*ARGSUSED*/
void
{
/* Add px specific PEC code */
}
/*
* px_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: pci_ctlops()
*
* return value: none
*/
int
{
char name[10];
uint_t n;
int i, no_config;
/*
* The following is a special case for pcimem nodes.
* For these nodes we create a reg property with a
* single entry that covers the entire address space
* for the node (config, io or memory).
*/
sizeof (pci_pcimem_reg));
return (DDI_SUCCESS);
}
/*
* Check whether the node has config space or is a hard decode
* node (possibly created by a driver.conf file).
*/
"no-config", 0);
/*
* Pseudo nodes indicate a prototype node with per-instance
* properties to be merged into the real h/w device node.
* However, do not merge if the no-config property is set
* (see PSARC 2000/088).
*/
extern int pci_allow_pseudo_children;
DDI_SUCCESS) {
return (DDI_NOT_WELL_FORMED);
}
/*
* Name the child
*/
return (DDI_FAILURE);
/*
* Try to merge the properties from this prototype
* node into real h/w nodes.
*/
/*
* Merged ok - return failure to remove the node.
*/
return (DDI_FAILURE);
}
/* workaround for ddivs to run under PCI */
return (DDI_SUCCESS);
return (DDI_NOT_WELL_FORMED);
}
return (DDI_FAILURE);
if (no_config != 0) {
/*
* There is no config space so there's nothing more to do.
*/
return (DDI_SUCCESS);
}
"INITCHILD: px_pm_hold failed\n");
return (DDI_FAILURE);
}
/* Any return of DDI_FAILURE after this must call px_pm_release */
/*
* If configuration registers were previously saved by
* child (before it went to 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.
*/
"config-regs-saved-by-child") == 1) {
"INITCHILD: config regs to be restored by child\n");
return (DDI_SUCCESS);
}
"INITCHILD: config regs setup for %s@%s\n",
/*
* 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.
*
*/
return (DDI_FAILURE);
}
/*
* Determine the configuration header type.
*/
/*
* Support for "command-preserve" property. Note that we
* add PCI_COMM_BACK2BACK_ENAB to the bits to be preserved
* since the obp will set this if the device supports and
* all targets on the same bus support it. Since psycho
* doesn't support PCI_COMM_BACK2BACK_ENAB, it will never
* be set. This is just here in case future revs do support
* PCI_COMM_BACK2BACK_ENAB.
*/
"command-preserve", 0);
/*
* If the device has a bus control register then program it
* based on the settings in the command register.
*/
}
/*
* Initialize latency timer registers if needed.
*/
"latency-timer", 0) == 0) {
} else {
}
if (n != 0)
"latency-timer", n);
}
/*
* Handle chip specific init-child tasks.
*/
return (DDI_SUCCESS);
}
/*
* px_get_reg_set_size
*
* Given a dev info pointer to a pci child and a register number, this
* routine returns the size element of that reg set property.
*
* used by: pci_ctlops() - DDI_CTLOPS_REGSIZE
*
* return value: size of reg set on success, -1 on error
*/
{
int i;
if (rnumber < 0)
return (-1);
/*
* Get the reg property for the device.
*/
return (-1);
if (rnumber >= (i / (int)sizeof (pci_regspec_t)))
goto done;
done:
return (size);
}
/*
* px_get_nreg_set
*
* Given a dev info pointer to a pci child, this routine returns the
* number of sets in its "reg" property.
*
* used by: pci_ctlops() - DDI_CTLOPS_NREGS
*
* return value: # of reg sets on success, zero on error
*/
{
int i, n;
/*
* Get the reg property for the device.
*/
return (0);
n = i / (int)sizeof (pci_regspec_t);
return (n);
}
/*
* px_get_nintr
*
* Given a dev info pointer to a pci child, this routine returns the
* number of items in its "interrupts" property.
*
* used by: pci_ctlops() - DDI_CTLOPS_NREGS
*
* return value: # of interrupts on success, zero on error
*/
{
int *pci_ip;
int i, n;
return (0);
n = i / (int)sizeof (uint_t);
return (n);
}
{
int i;
ASSERT(cfg_space_type == 0);
break;
}
if (i >= nrange)
(void *)px_p);
}
/*
* decodes standard PCI config space 16bit error status reg
*/
int
{
nerr = 0;
nerr++;
nerr++;
if (status_reg & PCI_STAT_R_MAST_AB)
nerr++;
nerr++;
return (nerr);
}
/*
* remove the following functions once we port error handling and other
* misc functionalities based on new VPCI interfaces.
*/
{
}
void
{
}