summaryrefslogtreecommitdiff
path: root/usr/src/uts/i86pc/io/rootnex.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/i86pc/io/rootnex.c')
-rw-r--r--usr/src/uts/i86pc/io/rootnex.c125
1 files changed, 60 insertions, 65 deletions
diff --git a/usr/src/uts/i86pc/io/rootnex.c b/usr/src/uts/i86pc/io/rootnex.c
index 81b87c4520..6cbc2132c1 100644
--- a/usr/src/uts/i86pc/io/rootnex.c
+++ b/usr/src/uts/i86pc/io/rootnex.c
@@ -819,9 +819,9 @@ static int
rootnex_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp, off_t offset,
off_t len, caddr_t *vaddrp)
{
- struct regspec *rp, tmp_reg;
+ struct regspec *orp = NULL;
+ struct regspec64 rp = { 0 };
ddi_map_req_t mr = *mp; /* Get private copy of request */
- int error;
mp = &mr;
@@ -846,10 +846,10 @@ rootnex_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp, off_t offset,
}
/*
- * First, if given an rnumber, convert it to a regspec...
- * (Presumably, this is on behalf of a child of the root node?)
+ * First, we need to get the original regspec out before we convert it
+ * to the extended format. If we have a register number, then we need to
+ * convert that to a regspec.
*/
-
if (mp->map_type == DDI_MT_RNUMBER) {
int rnumber = mp->map_obj.rnumber;
@@ -858,36 +858,48 @@ rootnex_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp, off_t offset,
"rootnex_map: Out of range rnumber <%d>, device <%s>";
#endif /* DDI_MAP_DEBUG */
- rp = i_ddi_rnumber_to_regspec(rdip, rnumber);
- if (rp == NULL) {
+ orp = i_ddi_rnumber_to_regspec(rdip, rnumber);
+ if (orp == NULL) {
#ifdef DDI_MAP_DEBUG
cmn_err(CE_WARN, out_of_range, rnumber,
ddi_get_name(rdip));
#endif /* DDI_MAP_DEBUG */
return (DDI_ME_RNUMBER_RANGE);
}
+ } else if (!(mp->map_flags & DDI_MF_EXT_REGSPEC)) {
+ orp = mp->map_obj.rp;
+ }
- /*
- * Convert the given ddi_map_req_t from rnumber to regspec...
- */
-
- mp->map_type = DDI_MT_REGSPEC;
- mp->map_obj.rp = rp;
+ /*
+ * Ensure that we are always using a 64-bit extended regspec regardless
+ * of what was passed into us. If the child driver is using a 64-bit
+ * regspec, then we need to make sure that we copy this to the local
+ * regspec64, rp.
+ */
+ if (orp != NULL) {
+ rp.regspec_bustype = orp->regspec_bustype;
+ rp.regspec_addr = orp->regspec_addr;
+ rp.regspec_size = orp->regspec_size;
+ } else {
+ struct regspec64 *rp64;
+ rp64 = (struct regspec64 *)mp->map_obj.rp;
+ rp = *rp64;
}
+ mp->map_type = DDI_MT_REGSPEC;
+ mp->map_flags |= DDI_MF_EXT_REGSPEC;
+ mp->map_obj.rp = (struct regspec *)&rp;
+
/*
* Adjust offset and length correspnding to called values...
* XXX: A non-zero length means override the one in the regspec
* XXX: (regardless of what's in the parent's range?)
*/
- tmp_reg = *(mp->map_obj.rp); /* Preserve underlying data */
- rp = mp->map_obj.rp = &tmp_reg; /* Use tmp_reg in request */
-
#ifdef DDI_MAP_DEBUG
cmn_err(CE_CONT, "rootnex: <%s,%s> <0x%x, 0x%x, 0x%d> offset %d len %d "
"handle 0x%x\n", ddi_get_name(dip), ddi_get_name(rdip),
- rp->regspec_bustype, rp->regspec_addr, rp->regspec_size, offset,
+ rp.regspec_bustype, rp.regspec_addr, rp.regspec_size, offset,
len, mp->map_handlep);
#endif /* DDI_MAP_DEBUG */
@@ -899,50 +911,44 @@ rootnex_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp, off_t offset,
* <bustype>1, addr=0, len=x>: x86-compatibility i/o
*/
- if (rp->regspec_bustype > 1 && rp->regspec_addr != 0) {
+ if (rp.regspec_bustype > 1 && rp.regspec_addr != 0) {
cmn_err(CE_WARN, "<%s,%s> invalid register spec"
- " <0x%x, 0x%x, 0x%x>", ddi_get_name(dip),
- ddi_get_name(rdip), rp->regspec_bustype,
- rp->regspec_addr, rp->regspec_size);
+ " <0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRIx64 ">",
+ ddi_get_name(dip), ddi_get_name(rdip), rp.regspec_bustype,
+ rp.regspec_addr, rp.regspec_size);
return (DDI_ME_INVAL);
}
- if (rp->regspec_bustype > 1 && rp->regspec_addr == 0) {
+ if (rp.regspec_bustype > 1 && rp.regspec_addr == 0) {
/*
* compatibility i/o mapping
*/
- rp->regspec_bustype += (uint_t)offset;
+ rp.regspec_bustype += offset;
} else {
/*
* Normal memory or i/o mapping
*/
- rp->regspec_addr += (uint_t)offset;
+ rp.regspec_addr += offset;
}
if (len != 0)
- rp->regspec_size = (uint_t)len;
+ rp.regspec_size = len;
#ifdef DDI_MAP_DEBUG
- cmn_err(CE_CONT, " <%s,%s> <0x%x, 0x%x, 0x%d> offset %d "
- "len %d handle 0x%x\n", ddi_get_name(dip), ddi_get_name(rdip),
- rp->regspec_bustype, rp->regspec_addr, rp->regspec_size,
- offset, len, mp->map_handlep);
+ cmn_err(CE_CONT, " <%s,%s> <0x%" PRIx64 ", 0x%" PRIx64
+ ", 0x%" PRId64 "> offset %d len %d handle 0x%x\n",
+ ddi_get_name(dip), ddi_get_name(rdip), rp.regspec_bustype,
+ rp.regspec_addr, rp.regspec_size, offset, len, mp->map_handlep);
#endif /* DDI_MAP_DEBUG */
+
/*
- * Apply any parent ranges at this level, if applicable.
- * (This is where nexus specific regspec translation takes place.
- * Use of this function is implicit agreement that translation is
- * provided via ddi_apply_range.)
+ * The x86 root nexus does not have any notion of valid ranges of
+ * addresses. Its children have valid ranges, but because there are none
+ * for the nexus, we don't need to call i_ddi_apply_range(). Verify
+ * that is the case.
*/
-
-#ifdef DDI_MAP_DEBUG
- ddi_map_debug("applying range of parent <%s> to child <%s>...\n",
- ddi_get_name(dip), ddi_get_name(rdip));
-#endif /* DDI_MAP_DEBUG */
-
- if ((error = i_ddi_apply_range(dip, rdip, mp->map_obj.rp)) != 0)
- return (error);
+ ASSERT0(sparc_pd_getnrng(dip));
switch (mp->map_op) {
case DDI_MO_MAP_LOCKED:
@@ -1023,23 +1029,20 @@ rootnex_map_fault(dev_info_t *dip, dev_info_t *rdip, struct hat *hat,
}
-/*
- * rootnex_map_regspec()
- * we don't support mapping of I/O cards above 4Gb
- */
static int
rootnex_map_regspec(ddi_map_req_t *mp, caddr_t *vaddrp)
{
rootnex_addr_t rbase;
void *cvaddr;
- uint_t npages, pgoffset;
- struct regspec *rp;
+ uint64_t npages, pgoffset;
+ struct regspec64 *rp;
ddi_acc_hdl_t *hp;
ddi_acc_impl_t *ap;
uint_t hat_acc_flags;
paddr_t pbase;
- rp = mp->map_obj.rp;
+ ASSERT(mp->map_flags & DDI_MF_EXT_REGSPEC);
+ rp = (struct regspec64 *)mp->map_obj.rp;
hp = mp->map_handlep;
#ifdef DDI_MAP_DEBUG
@@ -1059,8 +1062,8 @@ rootnex_map_regspec(ddi_map_req_t *mp, caddr_t *vaddrp)
if (rp->regspec_bustype > 1 && rp->regspec_addr != 0) {
cmn_err(CE_WARN, "rootnex: invalid register spec"
- " <0x%x, 0x%x, 0x%x>", rp->regspec_bustype,
- rp->regspec_addr, rp->regspec_size);
+ " <0x%" PRIx64 ", 0x%" PRIx64", 0x%" PRIx64">",
+ rp->regspec_bustype, rp->regspec_addr, rp->regspec_size);
return (DDI_FAILURE);
}
@@ -1209,21 +1212,18 @@ rootnex_map_regspec(ddi_map_req_t *mp, caddr_t *vaddrp)
}
-/*
- * rootnex_unmap_regspec()
- *
- */
static int
rootnex_unmap_regspec(ddi_map_req_t *mp, caddr_t *vaddrp)
{
caddr_t addr = (caddr_t)*vaddrp;
- uint_t npages, pgoffset;
- struct regspec *rp;
+ uint64_t npages, pgoffset;
+ struct regspec64 *rp;
if (mp->map_flags & DDI_MF_DEVICE_MAPPING)
return (0);
- rp = mp->map_obj.rp;
+ ASSERT(mp->map_flags & DDI_MF_EXT_REGSPEC);
+ rp = (struct regspec64 *)mp->map_obj.rp;
if (rp->regspec_size == 0) {
#ifdef DDI_MAP_DEBUG
@@ -1264,21 +1264,16 @@ rootnex_unmap_regspec(ddi_map_req_t *mp, caddr_t *vaddrp)
return (DDI_SUCCESS);
}
-
-/*
- * rootnex_map_handle()
- *
- */
static int
rootnex_map_handle(ddi_map_req_t *mp)
{
rootnex_addr_t rbase;
ddi_acc_hdl_t *hp;
- uint_t pgoffset;
- struct regspec *rp;
+ uint64_t pgoffset;
+ struct regspec64 *rp;
paddr_t pbase;
- rp = mp->map_obj.rp;
+ rp = (struct regspec64 *)mp->map_obj.rp;
#ifdef DDI_MAP_DEBUG
ddi_map_debug(