summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjasonwu <none@none>2005-09-16 12:46:15 -0700
committerjasonwu <none@none>2005-09-16 12:46:15 -0700
commitc4485e78b2d4c8dc6cd82088d3a862e9ed1e645b (patch)
treedf1a94efdba1e154bd76535e64790ae5a7429f59
parentfde3102f1c8dab43af9075a6e9cdabedec6ca9d7 (diff)
downloadillumos-gate-c4485e78b2d4c8dc6cd82088d3a862e9ed1e645b.tar.gz
FWARC 2005/512 sun4v ebus driver binding
6313488 ebus driver does not work on erie
-rw-r--r--usr/src/uts/sparc/os/driver_aliases1
-rw-r--r--usr/src/uts/sun4/io/ebus.c490
-rw-r--r--usr/src/uts/sun4/sys/ebus.h81
3 files changed, 231 insertions, 341 deletions
diff --git a/usr/src/uts/sparc/os/driver_aliases b/usr/src/uts/sparc/os/driver_aliases
index 409ce29cd3..906e9c40a9 100644
--- a/usr/src/uts/sparc/os/driver_aliases
+++ b/usr/src/uts/sparc/os/driver_aliases
@@ -17,6 +17,7 @@ ssd SUNW,ssd
fas SUNW,fas
hme SUNW,hme
ebus SUNW,ebus
+ebus SUNW,sun4v-ebus
fd fdthree
glm "pci1000,f"
pci_pci "pci1011,21"
diff --git a/usr/src/uts/sun4/io/ebus.c b/usr/src/uts/sun4/io/ebus.c
index 42630f1f48..b474d12b27 100644
--- a/usr/src/uts/sun4/io/ebus.c
+++ b/usr/src/uts/sun4/io/ebus.c
@@ -84,10 +84,10 @@ static int ebus_info(dev_info_t *dip, ddi_info_cmd_t infocmd,
*/
static int ebus_config(ebus_devstate_t *ebus_p);
static int ebus_apply_range(ebus_devstate_t *ebus_p, dev_info_t *rdip,
- ebus_regspec_t *ebus_rp, pci_regspec_t *rp);
-static int febus_apply_range(ebus_devstate_t *ebus_p, dev_info_t *rdip,
- ebus_regspec_t *ebus_rp, struct regspec *rp);
-int get_ranges_prop(ebus_devstate_t *ebus_p);
+ ebus_regspec_t *ebus_rp, vregspec_t *rp);
+int ebus_get_ranges_prop(ebus_devstate_t *ebus_p);
+static void ebus_get_cells_prop(ebus_devstate_t *ebus_p);
+static void ebus_vreg_dump(ebus_devstate_t *ebus_p, vregspec_t *rp);
#define getprop(dip, name, addr, intp) \
ddi_getlongprop(DDI_DEV_T_ANY, (dip), DDI_PROP_DONTPASS, \
@@ -247,19 +247,19 @@ ebus_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
ebus_p = get_ebus_soft_state(instance);
switch (infocmd) {
- default:
- return (DDI_FAILURE);
-
case DDI_INFO_DEVT2INSTANCE:
*result = (void *)instance;
- return (DDI_SUCCESS);
-
+ break;
case DDI_INFO_DEVT2DEVINFO:
if (ebus_p == NULL)
return (DDI_FAILURE);
*result = (void *)ebus_p->dip;
- return (DDI_SUCCESS);
+ break;
+ default:
+ return (DDI_FAILURE);
}
+
+ return (DDI_SUCCESS);
}
/*
@@ -288,7 +288,7 @@ ebus_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
*/
instance = ddi_get_instance(dip);
if (ddi_soft_state_zalloc(per_ebus_state, instance)
- != DDI_SUCCESS) {
+ != DDI_SUCCESS) {
DBG(D_ATTACH, NULL, "failed to alloc soft state\n");
return (DDI_FAILURE);
}
@@ -297,42 +297,26 @@ ebus_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
mutex_init(&ebus_p->ebus_mutex, NULL, MUTEX_DRIVER, NULL);
ebus_p->ebus_soft_state = EBUS_SOFT_STATE_CLOSED;
- /* Set ebus type field based on ddi name info */
- if (strcmp(ddi_get_name(dip), "jbus-ebus") == 0) {
- ebus_p->type = FEBUS_TYPE;
- } else {
- ebus_p->type = EBUS_TYPE;
- }
+ ebus_get_cells_prop(ebus_p);
(void) ddi_prop_create(DDI_DEV_T_NONE, dip,
- DDI_PROP_CANSLEEP, "no-dma-interrupt-sync", NULL, 0);
+ DDI_PROP_CANSLEEP, "no-dma-interrupt-sync", NULL, 0);
/* Get our ranges property for mapping child registers. */
- if (get_ranges_prop(ebus_p) != DDI_SUCCESS) {
- mutex_destroy(&ebus_p->ebus_mutex);
- free_ebus_soft_state(instance);
- return (DDI_FAILURE);
+ if (ebus_get_ranges_prop(ebus_p) != DDI_SUCCESS) {
+ goto attach_fail;
}
/*
* create minor node for devctl interfaces
*/
if (ddi_create_minor_node(dip, "devctl", S_IFCHR, instance,
- DDI_NT_NEXUS, 0) != DDI_SUCCESS) {
- mutex_destroy(&ebus_p->ebus_mutex);
- free_ebus_soft_state(instance);
- return (DDI_FAILURE);
+ DDI_NT_NEXUS, 0) != DDI_SUCCESS) {
+ goto attach_fail;
}
- /*
- * Make sure the master enable and memory access enable
- * bits are set in the config command register.
- */
- if (ebus_p->type == EBUS_TYPE) {
- if (!ebus_config(ebus_p)) {
- ddi_remove_minor_node(dip, "devctl");
- mutex_destroy(&ebus_p->ebus_mutex);
- free_ebus_soft_state(instance);
- return (DDI_FAILURE);
- }
+
+ if (ebus_config(ebus_p) != DDI_SUCCESS) {
+ ddi_remove_minor_node(dip, "devctl");
+ goto attach_fail;
}
/*
@@ -350,28 +334,24 @@ ebus_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
ebus_p->state = ATTACHED;
ddi_report_dev(dip);
DBG(D_ATTACH, ebus_p, "returning\n");
-
- return (DDI_SUCCESS);
+ break;
case DDI_RESUME:
instance = ddi_get_instance(dip);
ebus_p = get_ebus_soft_state(instance);
- /*
- * Make sure the master enable and memory access enable
- * bits are set in the config command register.
- */
- if (ebus_p->type == EBUS_TYPE) {
- if (!ebus_config(ebus_p)) {
- free_ebus_soft_state(instance);
- return (DDI_FAILURE);
- }
- }
+ (void) ebus_config(ebus_p);
ebus_p->state = RESUMED;
- return (DDI_SUCCESS);
+ break;
}
+
+ return (DDI_SUCCESS);
+
+attach_fail:
+ mutex_destroy(&ebus_p->ebus_mutex);
+ free_ebus_soft_state(instance);
return (DDI_FAILURE);
}
@@ -388,127 +368,77 @@ ebus_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
case DDI_DETACH:
DBG1(D_DETACH, ebus_p, "DDI_DETACH dip=%p\n", dip);
- switch (ebus_p->type) {
- case EBUS_TYPE:
- kmem_free(ebus_p->rangespec.rangep, ebus_p->range_cnt *
- sizeof (struct ebus_pci_rangespec));
- break;
- case FEBUS_TYPE:
- kmem_free(ebus_p->rangespec.ferangep,
- ebus_p->range_cnt *
- sizeof (struct febus_rangespec));
- break;
- default:
- DBG(D_ATTACH, NULL, "failed to recognize ebus type\n");
- return (DDI_FAILURE);
- }
+ kmem_free(ebus_p->vrangep, ebus_p->vrange_len);
ddi_remove_minor_node(dip, "devctl");
mutex_destroy(&ebus_p->ebus_mutex);
free_ebus_soft_state(instance);
- return (DDI_SUCCESS);
-
+ break;
case DDI_SUSPEND:
DBG1(D_DETACH, ebus_p, "DDI_SUSPEND dip=%p\n", dip);
ebus_p->state = SUSPENDED;
- return (DDI_SUCCESS);
+ break;
+ default:
+ DBG(D_ATTACH, NULL,
+ "failed to recognize ebus detach command\n");
+ return (DDI_FAILURE);
}
- DBG(D_ATTACH, NULL, "failed to recognize ebus detach command\n");
- return (DDI_FAILURE);
+ return (DDI_SUCCESS);
}
int
-get_ranges_prop(ebus_devstate_t *ebus_p)
+ebus_get_ranges_prop(ebus_devstate_t *ebus_p)
{
- int nrange, range_len;
- struct ebus_pci_rangespec *rangep;
- struct febus_rangespec *ferangep;
-
- switch (ebus_p->type) {
- case EBUS_TYPE:
- if (ddi_getlongprop(DDI_DEV_T_ANY,
- ebus_p->dip, DDI_PROP_DONTPASS,
- "ranges", (caddr_t)&rangep,
- &range_len) != DDI_SUCCESS) {
- cmn_err(CE_WARN, "Can't get %s ranges property",
- ddi_get_name(ebus_p->dip));
- return (DDI_ME_REGSPEC_RANGE);
- }
+ if (ddi_getlongprop(DDI_DEV_T_ANY, ebus_p->dip, DDI_PROP_DONTPASS,
+ "ranges", (caddr_t)&ebus_p->vrangep, &ebus_p->vrange_len)
+ != DDI_SUCCESS) {
+ cmn_err(CE_WARN, "Can't get %s ranges property",
+ ddi_get_name(ebus_p->dip));
+ return (DDI_ME_REGSPEC_RANGE);
+ }
- nrange = range_len / sizeof (struct ebus_pci_rangespec);
+ ebus_p->vrange_cnt = ebus_p->vrange_len /
+ (ebus_p->ebus_paddr_cells + ebus_p->ebus_addr_cells +
+ ebus_p->ebus_psz_cells);
- if (nrange == 0) {
- kmem_free(rangep, range_len);
- DBG(D_ATTACH, NULL, "range is equal to zero\n");
- return (DDI_FAILURE);
- }
+ if (ebus_p->vrange_cnt == 0) {
+ kmem_free(ebus_p->vrangep, ebus_p->vrange_len);
+ DBG(D_ATTACH, NULL, "range is equal to zero\n");
+ return (DDI_FAILURE);
+ }
-#ifdef DEBUG
- {
- int i;
-
- for (i = 0; i < nrange; i++) {
- DBG5(D_MAP, ebus_p,
- "ebus range addr 0x%x.0x%x PCI range "
- "addr 0x%x.0x%x.0x%x ",
- rangep[i].ebus_phys_hi,
- rangep[i].ebus_phys_low,
- rangep[i].pci_phys_hi,
- rangep[i].pci_phys_mid,
- rangep[i].pci_phys_low);
- DBG1(D_MAP, ebus_p,
- "Size 0x%x\n", rangep[i].rng_size);
- }
- }
-#endif /* DEBUG */
+ return (DDI_SUCCESS);
+}
- ebus_p->rangespec.rangep = rangep;
- ebus_p->range_cnt = nrange;
- return (DDI_SUCCESS);
+static void
+ebus_get_cells_prop(ebus_devstate_t *ebus_p)
+{
+ dev_info_t *dip = ebus_p->dip;
+ dev_info_t *pdip;
- case FEBUS_TYPE:
- if (ddi_getlongprop(DDI_DEV_T_ANY, ebus_p->dip,
- DDI_PROP_DONTPASS, "ranges",
- (caddr_t)&ferangep, &range_len) != DDI_SUCCESS) {
- cmn_err(CE_WARN, "Can't get %s ranges property",
- ddi_get_name(ebus_p->dip));
- return (DDI_ME_REGSPEC_RANGE);
- }
+ ebus_p->ebus_addr_cells = ddi_getprop(DDI_DEV_T_ANY,
+ dip, DDI_PROP_DONTPASS, "#address-cells", 2);
- nrange = range_len / sizeof (struct febus_rangespec);
+ pdip = ddi_get_parent(dip);
+ ebus_p->ebus_paddr_cells = ddi_getprop(DDI_DEV_T_ANY,
+ pdip, DDI_PROP_DONTPASS, "#address-cells", 2);
- if (nrange == 0) {
- kmem_free(ferangep, range_len);
- return (DDI_FAILURE);
- }
+ ASSERT((ebus_p->ebus_paddr_cells == 3) ||
+ (ebus_p->ebus_paddr_cells == 2));
-#ifdef DEBUG
- {
- int i;
-
- for (i = 0; i < nrange; i++) {
- DBG4(D_MAP, ebus_p,
- "ebus range addr 0x%x.0x%x"
- " Parent range "
- "addr 0x%x.0x%x ",
- ferangep[i].febus_phys_hi,
- ferangep[i].febus_phys_low,
- ferangep[i].parent_phys_hi,
- ferangep[i].parent_phys_low);
- DBG1(D_MAP, ebus_p, "Size 0x%x\n",
- ferangep[i].rng_size);
- }
- }
-#endif /* DEBUG */
- ebus_p->rangespec.ferangep = ferangep;
- ebus_p->range_cnt = nrange;
- return (DDI_SUCCESS);
+ ebus_p->ebus_sz_cells = ddi_getprop(DDI_DEV_T_ANY,
+ dip, DDI_PROP_DONTPASS, "#size-cells", 2);
+ ebus_p->ebus_psz_cells = ddi_getprop(DDI_DEV_T_ANY,
+ pdip, DDI_PROP_DONTPASS, "#size-cells", 1);
+
+ /* XXX rootnex assumes 1 cell and does not respect #size-cells */
+ if (ddi_root_node() == pdip)
+ ebus_p->ebus_psz_cells = 1;
+
+ ASSERT((ebus_p->ebus_psz_cells == 2) ||
+ (ebus_p->ebus_psz_cells == 1));
- default:
- DBG(D_MAP, NULL, "failed to recognize ebus type\n");
- return (DDI_FAILURE);
- }
}
/* bus driver entry points */
@@ -528,8 +458,7 @@ ebus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
{
ebus_devstate_t *ebus_p = get_ebus_soft_state(ddi_get_instance(dip));
ebus_regspec_t *ebus_rp, *ebus_regs;
- struct regspec reg;
- pci_regspec_t pci_reg;
+ vregspec_t vreg;
ddi_map_req_t p_map_request;
int rnumber, i, n;
int rval = DDI_SUCCESS;
@@ -568,6 +497,7 @@ ebus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
DBG(D_MAP, ebus_p, "can't get reg property\n");
return (DDI_ME_RNUMBER_RANGE);
}
+
n = i / sizeof (ebus_regspec_t);
if (rnumber < 0 || rnumber >= n) {
@@ -587,22 +517,7 @@ ebus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
if (len)
ebus_rp->size = len;
- /*
- * Now we have a copy the "reg" entry we're attempting to map.
- * Translate this into our parents PCI address using the ranges
- * property.
- */
- switch (ebus_p->type) {
- case EBUS_TYPE:
- rval = ebus_apply_range(ebus_p, rdip, ebus_rp, &pci_reg);
- break;
- case FEBUS_TYPE:
- rval = febus_apply_range(ebus_p, rdip, ebus_rp, &reg);
- break;
- default:
- DBG(D_MAP, NULL, "failed to recognize ebus type\n");
- rval = DDI_FAILURE;
- }
+ rval = ebus_apply_range(ebus_p, rdip, ebus_rp, &vreg);
if (mp->map_type == DDI_MT_RNUMBER)
kmem_free(ebus_regs, i);
@@ -610,159 +525,86 @@ ebus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
if (rval != DDI_SUCCESS)
return (rval);
-#ifdef DEBUG
- switch (ebus_p->type) {
- case EBUS_TYPE:
- DBG5(D_MAP, ebus_p, "(%x,%x,%x)(%x,%x)\n",
- pci_reg.pci_phys_hi,
- pci_reg.pci_phys_mid,
- pci_reg.pci_phys_low,
- pci_reg.pci_size_hi,
- pci_reg.pci_size_low);
- break;
-
- case FEBUS_TYPE:
- DBG3(D_MAP, ebus_p, "%x,%x,%x\n",
- reg.regspec_bustype,
- reg.regspec_addr,
- reg.regspec_size);
- break;
- }
-#endif
-
p_map_request = *mp;
p_map_request.map_type = DDI_MT_REGSPEC;
- switch (ebus_p->type) {
- case EBUS_TYPE:
- p_map_request.map_obj.rp = (struct regspec *)&pci_reg;
- break;
- case FEBUS_TYPE:
- p_map_request.map_obj.rp = &reg;
- break;
- default:
- DBG(D_MAP, NULL, "failed to recognize ebus type\n");
- return (DDI_FAILURE);
- }
+ p_map_request.map_obj.rp = (struct regspec *)&vreg;
rval = ddi_map(dip, &p_map_request, 0, 0, addrp);
DBG1(D_MAP, ebus_p, "parent returned %x\n", rval);
return (rval);
}
-
+/*
+ * ebus_apply_range generically relocates child's regspec to
+ * parent's format according to ebus' range spec
+ *
+ * Assumptions:
+ * - rng_caddr_hi is the space type
+ * - rng_caddr_low is the base address
+ * - ebus address is 32 bit and ebus entirely lives between 0-4G of
+ * parent space, so maths on preg/rng_cell_p[ebus_p->ebus_paddr_cells - 1],
+ * preg_cell_p[i], rng_caddr_low and ebus_rp->size are sufficient.
+ */
static int
ebus_apply_range(ebus_devstate_t *ebus_p, dev_info_t *rdip,
- ebus_regspec_t *ebus_rp, pci_regspec_t *rp)
-{
- int b;
- int rval = DDI_SUCCESS;
- struct ebus_pci_rangespec *rangep = ebus_p->rangespec.rangep;
- int nrange = ebus_p->range_cnt;
+ ebus_regspec_t *ebus_rp, vregspec_t *rp) {
+ int b, i;
+ int nrange = ebus_p->vrange_cnt;
+ uint32_t addr_offset, rng_caddr_hi, rng_caddr_low, rng_sz;
+ uint32_t req_addr = ebus_rp->addr_low;
+
+ uint32_t *rng_cell_p = (uint32_t *)ebus_p->vrangep;
+ int rng_rec_sz = ebus_p->ebus_paddr_cells + ebus_p->ebus_addr_cells +
+ ebus_p->ebus_sz_cells;
+ uint32_t *preg_cell_p = (uint32_t *)rp;
+ int preg_rec_sz = ebus_p->ebus_paddr_cells + ebus_p->ebus_psz_cells;
+
static char out_of_range[] =
"Out of range register specification from device node <%s>";
DBG3(D_MAP, ebus_p, "Range Matching Addr 0x%x.%x size 0x%x\n",
- ebus_rp->addr_hi, ebus_rp->addr_low, ebus_rp->size);
-
- for (b = 0; b < nrange; ++b, ++rangep) {
-
- /* Check for the correct space */
- if (ebus_rp->addr_hi == rangep->ebus_phys_hi)
- /* See if we fit in this range */
- if ((ebus_rp->addr_low >=
- rangep->ebus_phys_low) &&
- ((ebus_rp->addr_low + ebus_rp->size - 1)
- <= (rangep->ebus_phys_low +
- rangep->rng_size - 1))) {
- uint_t addr_offset = ebus_rp->addr_low -
- rangep->ebus_phys_low;
- /*
- * Use the range entry to translate
- * the EBUS physical address into the
- * parents PCI space.
- */
- rp->pci_phys_hi =
- rangep->pci_phys_hi;
- rp->pci_phys_mid = rangep->pci_phys_mid;
- rp->pci_phys_low =
- rangep->pci_phys_low + addr_offset;
- rp->pci_size_hi = 0;
- rp->pci_size_low =
- min(ebus_rp->size, (rangep->rng_size -
- addr_offset));
-
- DBG2(D_MAP, ebus_p, "Child hi0x%x lo0x%x ",
- rangep->ebus_phys_hi,
- rangep->ebus_phys_low);
- DBG4(D_MAP, ebus_p, "Parent hi0x%x "
- "mid0x%x lo0x%x size 0x%x\n",
- rangep->pci_phys_hi,
- rangep->pci_phys_mid,
- rangep->pci_phys_low,
- rangep->rng_size);
+ ebus_rp->addr_hi, req_addr, ebus_rp->size);
- break;
- }
- }
+ for (b = 0; b < nrange; b++, rng_cell_p += rng_rec_sz) {
- if (b == nrange) {
- cmn_err(CE_WARN, out_of_range, ddi_get_name(rdip));
- return (DDI_ME_REGSPEC_RANGE);
- }
+ rng_caddr_hi = rng_cell_p[0];
+ rng_caddr_low = rng_cell_p[1];
+ rng_sz = rng_cell_p[rng_rec_sz-1];
- return (rval);
-}
+ /* Check for correct space */
+ if (ebus_rp->addr_hi != rng_caddr_hi)
+ continue;
-static int
-febus_apply_range(ebus_devstate_t *ebus_p, dev_info_t *rdip,
- ebus_regspec_t *ebus_rp, struct regspec *rp) {
- int b;
- int rval = DDI_SUCCESS;
- struct febus_rangespec *rangep = ebus_p->rangespec.ferangep;
- int nrange = ebus_p->range_cnt;
- static char out_of_range[] =
- "Out of range register specification from device node <%s>";
+ /* Detect whether request entirely fits within a range */
+ if (req_addr < rng_caddr_low)
+ continue;
- DBG3(D_MAP, ebus_p, "Range Matching Addr 0x%x.%x size 0x%x\n",
- ebus_rp->addr_hi, ebus_rp->addr_low, ebus_rp->size);
-
- for (b = 0; b < nrange; ++b, ++rangep) {
- /* Check for the correct space */
- if (ebus_rp->addr_hi == rangep->febus_phys_hi)
- /* See if we fit in this range */
- if ((ebus_rp->addr_low >=
- rangep->febus_phys_low) &&
- ((ebus_rp->addr_low + ebus_rp->size - 1)
- <= (rangep->febus_phys_low +
- rangep->rng_size - 1))) {
- uint_t addr_offset = ebus_rp->addr_low -
- rangep->febus_phys_low;
-
- /*
- * Use the range entry to translate
- * the FEBUS physical address into the
- * parents space.
- */
- rp->regspec_bustype =
- rangep->parent_phys_hi;
- rp->regspec_addr =
- rangep->parent_phys_low + addr_offset;
- rp->regspec_size =
- min(ebus_rp->size, (rangep->rng_size -
- addr_offset));
-
- DBG2(D_MAP, ebus_p, "Child hi0x%x lo0x%x ",
- rangep->febus_phys_hi,
- rangep->febus_phys_low);
- DBG3(D_MAP, ebus_p, "Parent hi0x%x "
- "lo0x%x size 0x%x\n",
- rangep->parent_phys_hi,
- rangep->parent_phys_low,
- rangep->rng_size);
+ if ((req_addr + ebus_rp->size - 1)
+ > (rng_caddr_low + rng_sz - 1))
+ continue;
- break;
- }
+ addr_offset = req_addr - rng_caddr_low;
+
+ /* parent addr = child addr + offset from ranges */
+ for (i = 0; i < preg_rec_sz; i++)
+ preg_cell_p[i] = 0;
+
+ /* Copy the physical address */
+ for (i = 0; i < ebus_p->ebus_paddr_cells; i++)
+ preg_cell_p[i] = rng_cell_p[ebus_p->ebus_addr_cells+i];
+
+ preg_cell_p[ebus_p->ebus_paddr_cells-1] += addr_offset;
+
+ /* Copy the size */
+ preg_cell_p[preg_rec_sz-1] = min(ebus_rp->size,
+ rng_sz - addr_offset);
+
+#ifdef DEBUG
+ ebus_vreg_dump(ebus_p, (vregspec_t *)preg_cell_p);
+#endif /* DEBUG */
+
+ break;
}
if (b == nrange) {
@@ -770,10 +612,9 @@ febus_apply_range(ebus_devstate_t *ebus_p, dev_info_t *rdip,
return (DDI_ME_REGSPEC_RANGE);
}
- return (rval);
+ return (DDI_SUCCESS);
}
-
static int
ebus_name_child(dev_info_t *child, char *name, int namelen)
{
@@ -1008,19 +849,40 @@ done:
return (i_ddi_intr_ops(dip, rdip, intr_op, hdlp, result));
}
-
+/*
+ * ebus_config: setup pci config space registers:
+ * enable bus mastering, memory access and error reporting
+ */
static int
ebus_config(ebus_devstate_t *ebus_p)
{
ddi_acc_handle_t conf_handle;
uint16_t comm;
+ dev_info_t *dip = ebus_p->dip;
+ char *devtype_str;
+ int devtype_len;
+
+ if (ddi_getlongprop(DDI_DEV_T_ANY, ddi_get_parent(dip),
+ DDI_PROP_DONTPASS, "device_type", (caddr_t)&devtype_str,
+ &devtype_len) != DDI_SUCCESS) {
+ cmn_err(CE_WARN, "Can't get %s device_type property",
+ ddi_get_name(ddi_get_parent(dip)));
+
+ return (DDI_FAILURE);
+ }
+
+ comm = strcmp(devtype_str, "pci");
+ kmem_free(devtype_str, devtype_len);
+
+ if (comm)
+ return (DDI_SUCCESS);
/*
* Make sure the master enable and memory access enable
* bits are set in the config command register.
*/
if (pci_config_setup(ebus_p->dip, &conf_handle) != DDI_SUCCESS)
- return (0);
+ return (DDI_FAILURE);
comm = pci_config_get16(conf_handle, PCI_CONF_COMM),
#ifdef DEBUG
@@ -1037,7 +899,7 @@ ebus_config(ebus_devstate_t *ebus_p)
pci_config_put8(conf_handle, PCI_CONF_LATENCY_TIMER,
(uchar_t)ebus_latency_timer);
pci_config_teardown(&conf_handle);
- return (1);
+ return (DDI_SUCCESS);
}
#ifdef DEBUG
@@ -1071,7 +933,25 @@ ebus_debug(uint_t flag, ebus_devstate_t *ebus_p, char *fmt,
cmn_err(CE_CONT, fmt, a1, a2, a3, a4, a5);
}
}
-#endif
+
+static void
+ebus_vreg_dump(ebus_devstate_t *ebus_p, vregspec_t *rp)
+{
+ if (ebus_p->ebus_paddr_cells == 3) {
+ DBG5(D_MAP, ebus_p, "(%x,%x,%x)(%x,%x)\n",
+ rp->pci_regspec.pci_phys_hi,
+ rp->pci_regspec.pci_phys_mid,
+ rp->pci_regspec.pci_phys_low,
+ rp->pci_regspec.pci_size_hi,
+ rp->pci_regspec.pci_size_low);
+ } else if (ebus_p->ebus_paddr_cells == 2) {
+ DBG3(D_MAP, ebus_p, "%x,%x,%x\n",
+ rp->jbus_regspec.regspec_bustype,
+ rp->jbus_regspec.regspec_addr,
+ rp->jbus_regspec.regspec_size);
+ }
+}
+#endif /* DEBUG */
/* ARGSUSED3 */
static int
diff --git a/usr/src/uts/sun4/sys/ebus.h b/usr/src/uts/sun4/sys/ebus.h
index a1b8fbc4bb..92f193b92e 100644
--- a/usr/src/uts/sun4/sys/ebus.h
+++ b/usr/src/uts/sun4/sys/ebus.h
@@ -76,6 +76,44 @@ struct ebus_intr_map_mask {
};
/*
+ * definition of ebus reg spec entry:
+ */
+typedef struct {
+ uint32_t addr_hi;
+ uint32_t addr_low;
+ uint32_t size;
+} ebus_regspec_t;
+
+/* Range entry for 3-cell parent address */
+struct ebus_pci_rangespec {
+ uint32_t phys_hi; /* Child hi range address */
+ uint32_t phys_low; /* Child low range address */
+ uint32_t par_phys_hi; /* Parent hi rng addr */
+ uint32_t par_phys_mid; /* Parent mid rng addr */
+ uint32_t par_phys_low; /* Parent low rng addr */
+ uint32_t rng_size; /* Range size */
+};
+
+/* Range entry for 2-cell parent address */
+struct ebus_jbus_rangespec {
+ uint32_t phys_hi; /* Child hi range address */
+ uint32_t phys_low; /* Child low range address */
+ uint32_t par_phys_hi; /* Parent hi rng addr */
+ uint32_t par_phys_low; /* Parent low rng addr */
+ uint32_t rng_size; /* Range size */
+};
+
+typedef union vrangespec {
+ struct ebus_pci_rangespec pci_rangespec;
+ struct ebus_jbus_rangespec jbus_rangespec;
+} vrangespec_t;
+
+typedef union vregspec {
+ struct pci_phys_spec pci_regspec;
+ struct regspec jbus_regspec;
+} vregspec_t;
+
+/*
* driver soft state structure:
*/
typedef struct {
@@ -84,12 +122,10 @@ typedef struct {
pci_regspec_t *reg;
int nreg;
- union {
- struct ebus_pci_rangespec *rangep;
- struct febus_rangespec *ferangep;
- } rangespec;
+ vrangespec_t *vrangep;
+ int vrange_len;
+ int vrange_cnt;
- int range_cnt;
kmutex_t ebus_mutex;
uint_t ebus_soft_state;
#define EBUS_SOFT_STATE_CLOSED 0x00
@@ -107,39 +143,12 @@ typedef struct {
struct ebus_intr_map *intr_map;
struct ebus_intr_map_mask *intr_map_mask;
#endif
-
- uint_t type;
-#define EBUS_TYPE 0x00
-#define FEBUS_TYPE 0x01
+ int ebus_addr_cells;
+ int ebus_paddr_cells;
+ int ebus_psz_cells;
+ int ebus_sz_cells;
} ebus_devstate_t;
-/*
- * definition of ebus reg spec entry:
- */
-typedef struct {
- uint32_t addr_hi;
- uint32_t addr_low;
- uint32_t size;
-} ebus_regspec_t;
-
-/* EBUS range entry */
-struct ebus_pci_rangespec {
- uint32_t ebus_phys_hi; /* Child hi range address */
- uint32_t ebus_phys_low; /* Child low range address */
- uint32_t pci_phys_hi; /* Parent hi rng addr */
- uint32_t pci_phys_mid; /* Parent mid rng addr */
- uint32_t pci_phys_low; /* Parent low rng addr */
- uint32_t rng_size; /* Range size */
-};
-
-/* FEBUS range entry */
-struct febus_rangespec {
- uint32_t febus_phys_hi; /* Child hi range address */
- uint32_t febus_phys_low; /* Child low range address */
- uint32_t parent_phys_hi; /* Parent hi rng addr */
- uint32_t parent_phys_low; /* Parent low rng addr */
- uint32_t rng_size; /* Range size */
-};
/*
* use macros for soft state and driver properties: