ddi_impl.c revision 15e1afcd5e908ae29b1e6018838638befdc225a2
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * CDDL HEADER START
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw *
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * The contents of this file are subject to the terms of the
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Common Development and Distribution License (the "License").
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * You may not use this file except in compliance with the License.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw *
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * or http://www.opensolaris.org/os/licensing.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * See the License for the specific language governing permissions
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * and limitations under the License.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw *
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * When distributing Covered Code, include this CDDL HEADER in each
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * If applicable, add the following below this CDDL HEADER, with the
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * fields enclosed by brackets "[]" replaced with your own identifying
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * information: Portions Copyright [yyyy] [name of copyright owner]
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw *
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * CDDL HEADER END
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Use is subject to license terms.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * sun4 specific DDI implementation
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw#include <sys/cpuvar.h>
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw#include <sys/ddi_subrdefs.h>
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw#include <sys/machsystm.h>
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw#include <sys/sunndi.h>
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw#include <sys/sysmacros.h>
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw#include <sys/ontrap.h>
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw#include <vm/seg_kmem.h>
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw#include <sys/membar.h>
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw#include <sys/dditypes.h>
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw#include <sys/ndifm.h>
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw#include <sys/fm/io/ddi.h>
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw#include <sys/ivintr.h>
d3a612ca42c17c3baa6c96ded00f98db349cc881nw#include <sys/bootconf.h>
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw#include <sys/conf.h>
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw#include <sys/ethernet.h>
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw#include <sys/idprom.h>
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw#include <sys/promif.h>
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw#include <sys/prom_plat.h>
8e22821528b08c6dba4e8176351560f316f6d0dedm#include <sys/systeminfo.h>
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw#include <sys/fpu/fpusystm.h>
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw#include <sys/vm.h>
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw#include <sys/ddi_isa.h>
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw#include <sys/modctl.h>
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwdev_info_t *get_intr_parent(dev_info_t *, dev_info_t *,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ddi_intr_handle_impl_t *);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw#pragma weak get_intr_parent
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwint process_intr_ops(dev_info_t *, dev_info_t *, ddi_intr_op_t,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ddi_intr_handle_impl_t *, void *);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw#pragma weak process_intr_ops
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwvoid cells_1275_copy(prop_1275_cell_t *, prop_1275_cell_t *, int32_t);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw prop_1275_cell_t *cells_1275_cmp(prop_1275_cell_t *, prop_1275_cell_t *,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw int32_t len);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw#pragma weak cells_1275_copy
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Wrapper for ddi_prop_lookup_int_array().
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * This is handy because it returns the prop length in
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * bytes which is what most of the callers require.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwstatic int
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwget_prop_int_array(dev_info_t *di, char *pname, int **pval, uint_t *plen)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw{
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw int ret;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if ((ret = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, di,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw DDI_PROP_DONTPASS, pname, pval, plen)) == DDI_PROP_SUCCESS) {
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw *plen = (*plen) * (uint_t)sizeof (int);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw }
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (ret);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * SECTION: DDI Node Configuration
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * init_regspec_64:
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw *
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * If the parent #size-cells is 2, convert the upa-style or
8e22821528b08c6dba4e8176351560f316f6d0dedm * safari-style reg property from 2-size cells to 1 size cell
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * format, ignoring the size_hi, which must be zero for devices.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * (It won't be zero in the memory list properties in the memory
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * nodes, but that doesn't matter here.)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwstruct ddi_parent_private_data *
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwinit_regspec_64(dev_info_t *dip)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw{
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw struct ddi_parent_private_data *pd;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw dev_info_t *parent;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw int size_cells;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * If there are no "reg"s in the child node, return.
d3a612ca42c17c3baa6c96ded00f98db349cc881nw */
d3a612ca42c17c3baa6c96ded00f98db349cc881nw pd = ddi_get_parent_data(dip);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if ((pd == NULL) || (pd->par_nreg == 0)) {
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (pd);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw }
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw parent = ddi_get_parent(dip);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw size_cells = ddi_prop_get_int(DDI_DEV_T_ANY, parent,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw DDI_PROP_DONTPASS, "#size-cells", 1);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (size_cells != 1) {
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
d3a612ca42c17c3baa6c96ded00f98db349cc881nw int n, j;
d3a612ca42c17c3baa6c96ded00f98db349cc881nw struct regspec *irp;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw struct reg_64 {
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw uint_t addr_hi, addr_lo, size_hi, size_lo;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw };
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw struct reg_64 *r64_rp;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw struct regspec *rp;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw uint_t len = 0;
d3a612ca42c17c3baa6c96ded00f98db349cc881nw int *reg_prop;
d3a612ca42c17c3baa6c96ded00f98db349cc881nw
d3a612ca42c17c3baa6c96ded00f98db349cc881nw ASSERT(size_cells == 2);
d3a612ca42c17c3baa6c96ded00f98db349cc881nw
d3a612ca42c17c3baa6c96ded00f98db349cc881nw /*
d3a612ca42c17c3baa6c96ded00f98db349cc881nw * We already looked the property up once before if
d3a612ca42c17c3baa6c96ded00f98db349cc881nw * pd is non-NULL.
d3a612ca42c17c3baa6c96ded00f98db349cc881nw */
d3a612ca42c17c3baa6c96ded00f98db349cc881nw (void) ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
d3a612ca42c17c3baa6c96ded00f98db349cc881nw DDI_PROP_DONTPASS, OBP_REG, &reg_prop, &len);
d3a612ca42c17c3baa6c96ded00f98db349cc881nw ASSERT(len != 0);
d3a612ca42c17c3baa6c96ded00f98db349cc881nw
d3a612ca42c17c3baa6c96ded00f98db349cc881nw n = sizeof (struct reg_64) / sizeof (int);
d3a612ca42c17c3baa6c96ded00f98db349cc881nw n = len / n;
d3a612ca42c17c3baa6c96ded00f98db349cc881nw
d3a612ca42c17c3baa6c96ded00f98db349cc881nw /*
d3a612ca42c17c3baa6c96ded00f98db349cc881nw * We're allocating a buffer the size of the PROM's property,
d3a612ca42c17c3baa6c96ded00f98db349cc881nw * but we're only using a smaller portion when we assign it
d3a612ca42c17c3baa6c96ded00f98db349cc881nw * to a regspec. We do this so that in the
d3a612ca42c17c3baa6c96ded00f98db349cc881nw * impl_ddi_sunbus_removechild function, we will
d3a612ca42c17c3baa6c96ded00f98db349cc881nw * always free the right amount of memory.
d3a612ca42c17c3baa6c96ded00f98db349cc881nw */
d3a612ca42c17c3baa6c96ded00f98db349cc881nw irp = rp = (struct regspec *)reg_prop;
d3a612ca42c17c3baa6c96ded00f98db349cc881nw r64_rp = (struct reg_64 *)pd->par_reg;
d3a612ca42c17c3baa6c96ded00f98db349cc881nw
d3a612ca42c17c3baa6c96ded00f98db349cc881nw for (j = 0; j < n; ++j, ++rp, ++r64_rp) {
d3a612ca42c17c3baa6c96ded00f98db349cc881nw ASSERT(r64_rp->size_hi == 0);
d3a612ca42c17c3baa6c96ded00f98db349cc881nw rp->regspec_bustype = r64_rp->addr_hi;
d3a612ca42c17c3baa6c96ded00f98db349cc881nw rp->regspec_addr = r64_rp->addr_lo;
d3a612ca42c17c3baa6c96ded00f98db349cc881nw rp->regspec_size = r64_rp->size_lo;
d3a612ca42c17c3baa6c96ded00f98db349cc881nw }
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ddi_prop_free((void *)pd->par_reg);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw pd->par_nreg = n;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw pd->par_reg = irp;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw }
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (pd);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Create a ddi_parent_private_data structure from the ddi properties of
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * the dev_info node.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw *
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * The "reg" is required if the driver wishes to create mappings on behalf
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * of the device. The "reg" property is assumed to be a list of at least
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * one triplet
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw *
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * <bustype, address, size>*1
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw *
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * The "interrupt" property is no longer part of parent private data on
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * sun4u. The interrupt parent is may not be the device tree parent.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw *
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * The "ranges" property describes the mapping of child addresses to parent
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * addresses.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw *
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * N.B. struct rangespec is defined for the following default values:
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * parent child
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * #address-cells 2 2
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * #size-cells 1 1
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * This function doesn't deal with non-default cells and will not create
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * ranges in such cases.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwvoid
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwmake_ddi_ppd(dev_info_t *child, struct ddi_parent_private_data **ppd)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw{
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw struct ddi_parent_private_data *pdptr;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw int *reg_prop, *rng_prop;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw uint_t reg_len = 0, rng_len = 0;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw dev_info_t *parent;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw int parent_addr_cells, parent_size_cells;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw int child_addr_cells, child_size_cells;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw *ppd = pdptr = kmem_zalloc(sizeof (*pdptr), KM_SLEEP);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * root node has no parent private data, so *ppd should
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * be initialized for naming to work properly.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if ((parent = ddi_get_parent(child)) == NULL)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Set reg field of parent data from "reg" property
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if ((get_prop_int_array(child, OBP_REG, &reg_prop, &reg_len)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw == DDI_PROP_SUCCESS) && (reg_len != 0)) {
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw pdptr->par_nreg = (int)(reg_len / sizeof (struct regspec));
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw pdptr->par_reg = (struct regspec *)reg_prop;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw }
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * "ranges" property ...
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw *
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * This function does not handle cases where #address-cells != 2
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * and * min(parent, child) #size-cells != 1 (see bugid 4211124).
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw *
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Nexus drivers with such exceptions (e.g. pci ranges)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * should either create a separate function for handling
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * ranges or not use parent private data to store ranges.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /* root node has no ranges */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if ((parent = ddi_get_parent(child)) == NULL)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw child_addr_cells = ddi_prop_get_int(DDI_DEV_T_ANY, child,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw DDI_PROP_DONTPASS, "#address-cells", 2);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw child_size_cells = ddi_prop_get_int(DDI_DEV_T_ANY, child,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw DDI_PROP_DONTPASS, "#size-cells", 1);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw parent_addr_cells = ddi_prop_get_int(DDI_DEV_T_ANY, parent,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw DDI_PROP_DONTPASS, "#address-cells", 2);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw parent_size_cells = ddi_prop_get_int(DDI_DEV_T_ANY, parent,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw DDI_PROP_DONTPASS, "#size-cells", 1);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (child_addr_cells != 2 || parent_addr_cells != 2 ||
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw (child_size_cells != 1 && parent_size_cells != 1)) {
8e22821528b08c6dba4e8176351560f316f6d0dedm NDI_CONFIG_DEBUG((CE_NOTE, "!ranges not made in parent data; "
8e22821528b08c6dba4e8176351560f316f6d0dedm "#address-cells or #size-cells have non-default value"));
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw }
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (get_prop_int_array(child, OBP_RANGES, &rng_prop, &rng_len)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw == DDI_PROP_SUCCESS) {
8e22821528b08c6dba4e8176351560f316f6d0dedm pdptr->par_nrng = rng_len / (int)(sizeof (struct rangespec));
8e22821528b08c6dba4e8176351560f316f6d0dedm pdptr->par_rng = (struct rangespec *)rng_prop;
8e22821528b08c6dba4e8176351560f316f6d0dedm }
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*
8e22821528b08c6dba4e8176351560f316f6d0dedm * Free ddi_parent_private_data structure
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
651c0131ccc65381cbda174bee44a4fd7a518d6bbabanvoid
8e22821528b08c6dba4e8176351560f316f6d0dedmimpl_free_ddi_ppd(dev_info_t *dip)
8e22821528b08c6dba4e8176351560f316f6d0dedm{
8e22821528b08c6dba4e8176351560f316f6d0dedm struct ddi_parent_private_data *pdptr = ddi_get_parent_data(dip);
8e22821528b08c6dba4e8176351560f316f6d0dedm
8e22821528b08c6dba4e8176351560f316f6d0dedm if (pdptr == NULL)
8e22821528b08c6dba4e8176351560f316f6d0dedm return;
8e22821528b08c6dba4e8176351560f316f6d0dedm
8e22821528b08c6dba4e8176351560f316f6d0dedm if (pdptr->par_nrng != 0)
8e22821528b08c6dba4e8176351560f316f6d0dedm ddi_prop_free((void *)pdptr->par_rng);
8e22821528b08c6dba4e8176351560f316f6d0dedm
8e22821528b08c6dba4e8176351560f316f6d0dedm if (pdptr->par_nreg != 0)
8e22821528b08c6dba4e8176351560f316f6d0dedm ddi_prop_free((void *)pdptr->par_reg);
8e22821528b08c6dba4e8176351560f316f6d0dedm
8e22821528b08c6dba4e8176351560f316f6d0dedm kmem_free(pdptr, sizeof (*pdptr));
8e22821528b08c6dba4e8176351560f316f6d0dedm ddi_set_parent_data(dip, NULL);
8e22821528b08c6dba4e8176351560f316f6d0dedm}
8e22821528b08c6dba4e8176351560f316f6d0dedm
8e22821528b08c6dba4e8176351560f316f6d0dedm/*
8e22821528b08c6dba4e8176351560f316f6d0dedm * Name a child of sun busses based on the reg spec.
8e22821528b08c6dba4e8176351560f316f6d0dedm * Handles the following properties:
8e22821528b08c6dba4e8176351560f316f6d0dedm *
8e22821528b08c6dba4e8176351560f316f6d0dedm * Property value
8e22821528b08c6dba4e8176351560f316f6d0dedm * Name type
8e22821528b08c6dba4e8176351560f316f6d0dedm *
8e22821528b08c6dba4e8176351560f316f6d0dedm * reg register spec
8e22821528b08c6dba4e8176351560f316f6d0dedm * interrupts new (bus-oriented) interrupt spec
8e22821528b08c6dba4e8176351560f316f6d0dedm * ranges range spec
8e22821528b08c6dba4e8176351560f316f6d0dedm *
8e22821528b08c6dba4e8176351560f316f6d0dedm * This may be called multiple times, independent of
8e22821528b08c6dba4e8176351560f316f6d0dedm * initchild calls.
8e22821528b08c6dba4e8176351560f316f6d0dedm */
8e22821528b08c6dba4e8176351560f316f6d0dedmstatic int
651c0131ccc65381cbda174bee44a4fd7a518d6bbabanimpl_sunbus_name_child(dev_info_t *child, char *name, int namelen)
8e22821528b08c6dba4e8176351560f316f6d0dedm{
8e22821528b08c6dba4e8176351560f316f6d0dedm struct ddi_parent_private_data *pdptr;
8e22821528b08c6dba4e8176351560f316f6d0dedm struct regspec *rp;
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban
8e22821528b08c6dba4e8176351560f316f6d0dedm /*
8e22821528b08c6dba4e8176351560f316f6d0dedm * Fill in parent-private data and this function returns to us
8e22821528b08c6dba4e8176351560f316f6d0dedm * an indication if it used "registers" to fill in the data.
8e22821528b08c6dba4e8176351560f316f6d0dedm */
8e22821528b08c6dba4e8176351560f316f6d0dedm if (ddi_get_parent_data(child) == NULL) {
8e22821528b08c6dba4e8176351560f316f6d0dedm make_ddi_ppd(child, &pdptr);
8e22821528b08c6dba4e8176351560f316f6d0dedm ddi_set_parent_data(child, pdptr);
8e22821528b08c6dba4e8176351560f316f6d0dedm }
8e22821528b08c6dba4e8176351560f316f6d0dedm
8e22821528b08c6dba4e8176351560f316f6d0dedm /*
8e22821528b08c6dba4e8176351560f316f6d0dedm * No reg property, return null string as address
8e22821528b08c6dba4e8176351560f316f6d0dedm * (e.g. root node)
8e22821528b08c6dba4e8176351560f316f6d0dedm */
8e22821528b08c6dba4e8176351560f316f6d0dedm name[0] = '\0';
8e22821528b08c6dba4e8176351560f316f6d0dedm if (sparc_pd_getnreg(child) == 0) {
8e22821528b08c6dba4e8176351560f316f6d0dedm return (DDI_SUCCESS);
8e22821528b08c6dba4e8176351560f316f6d0dedm }
8e22821528b08c6dba4e8176351560f316f6d0dedm
8e22821528b08c6dba4e8176351560f316f6d0dedm rp = sparc_pd_getreg(child, 0);
8e22821528b08c6dba4e8176351560f316f6d0dedm (void) snprintf(name, namelen, "%x,%x",
8e22821528b08c6dba4e8176351560f316f6d0dedm rp->regspec_bustype, rp->regspec_addr);
8e22821528b08c6dba4e8176351560f316f6d0dedm return (DDI_SUCCESS);
8e22821528b08c6dba4e8176351560f316f6d0dedm}
8e22821528b08c6dba4e8176351560f316f6d0dedm
8e22821528b08c6dba4e8176351560f316f6d0dedm
8e22821528b08c6dba4e8176351560f316f6d0dedm/*
8e22821528b08c6dba4e8176351560f316f6d0dedm * Called from the bus_ctl op of some drivers.
8e22821528b08c6dba4e8176351560f316f6d0dedm * to implement the DDI_CTLOPS_INITCHILD operation.
8e22821528b08c6dba4e8176351560f316f6d0dedm *
8e22821528b08c6dba4e8176351560f316f6d0dedm * NEW drivers should NOT use this function, but should declare
8e22821528b08c6dba4e8176351560f316f6d0dedm * there own initchild/uninitchild handlers. (This function assumes
8e22821528b08c6dba4e8176351560f316f6d0dedm * the layout of the parent private data and the format of "reg",
8e22821528b08c6dba4e8176351560f316f6d0dedm * "ranges", "interrupts" properties and that #address-cells and
8e22821528b08c6dba4e8176351560f316f6d0dedm * #size-cells of the parent bus are defined to be default values.)
8e22821528b08c6dba4e8176351560f316f6d0dedm */
8e22821528b08c6dba4e8176351560f316f6d0dedmint
8e22821528b08c6dba4e8176351560f316f6d0dedmimpl_ddi_sunbus_initchild(dev_info_t *child)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw{
8e22821528b08c6dba4e8176351560f316f6d0dedm char name[MAXNAMELEN];
8e22821528b08c6dba4e8176351560f316f6d0dedm
8e22821528b08c6dba4e8176351560f316f6d0dedm (void) impl_sunbus_name_child(child, name, MAXNAMELEN);
8e22821528b08c6dba4e8176351560f316f6d0dedm ddi_set_name_addr(child, name);
8e22821528b08c6dba4e8176351560f316f6d0dedm
8e22821528b08c6dba4e8176351560f316f6d0dedm /*
8e22821528b08c6dba4e8176351560f316f6d0dedm * Try to merge .conf node. If successful, return failure to
8e22821528b08c6dba4e8176351560f316f6d0dedm * remove this child.
8e22821528b08c6dba4e8176351560f316f6d0dedm */
8e22821528b08c6dba4e8176351560f316f6d0dedm if ((ndi_dev_is_persistent_node(child) == 0) &&
8e22821528b08c6dba4e8176351560f316f6d0dedm (ndi_merge_node(child, impl_sunbus_name_child) == DDI_SUCCESS)) {
8e22821528b08c6dba4e8176351560f316f6d0dedm impl_ddi_sunbus_removechild(child);
8e22821528b08c6dba4e8176351560f316f6d0dedm return (DDI_FAILURE);
8e22821528b08c6dba4e8176351560f316f6d0dedm }
8e22821528b08c6dba4e8176351560f316f6d0dedm return (DDI_SUCCESS);
8e22821528b08c6dba4e8176351560f316f6d0dedm}
8e22821528b08c6dba4e8176351560f316f6d0dedm
8e22821528b08c6dba4e8176351560f316f6d0dedm/*
8e22821528b08c6dba4e8176351560f316f6d0dedm * A better name for this function would be impl_ddi_sunbus_uninitchild()
8e22821528b08c6dba4e8176351560f316f6d0dedm * It does not remove the child, it uninitializes it, reclaiming the
8e22821528b08c6dba4e8176351560f316f6d0dedm * resources taken by impl_ddi_sunbus_initchild.
8e22821528b08c6dba4e8176351560f316f6d0dedm */
8e22821528b08c6dba4e8176351560f316f6d0dedmvoid
8e22821528b08c6dba4e8176351560f316f6d0dedmimpl_ddi_sunbus_removechild(dev_info_t *dip)
8e22821528b08c6dba4e8176351560f316f6d0dedm{
8e22821528b08c6dba4e8176351560f316f6d0dedm impl_free_ddi_ppd(dip);
8e22821528b08c6dba4e8176351560f316f6d0dedm ddi_set_name_addr(dip, NULL);
8e22821528b08c6dba4e8176351560f316f6d0dedm /*
8e22821528b08c6dba4e8176351560f316f6d0dedm * Strip the node to properly convert it back to prototype form
8e22821528b08c6dba4e8176351560f316f6d0dedm */
8e22821528b08c6dba4e8176351560f316f6d0dedm impl_rem_dev_props(dip);
8e22821528b08c6dba4e8176351560f316f6d0dedm}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
8e22821528b08c6dba4e8176351560f316f6d0dedm/*
8e22821528b08c6dba4e8176351560f316f6d0dedm * SECTION: DDI Interrupt
8e22821528b08c6dba4e8176351560f316f6d0dedm */
8e22821528b08c6dba4e8176351560f316f6d0dedm
8e22821528b08c6dba4e8176351560f316f6d0dedmvoid
8e22821528b08c6dba4e8176351560f316f6d0dedmcells_1275_copy(prop_1275_cell_t *from, prop_1275_cell_t *to, int32_t len)
8e22821528b08c6dba4e8176351560f316f6d0dedm{
8e22821528b08c6dba4e8176351560f316f6d0dedm int i;
8e22821528b08c6dba4e8176351560f316f6d0dedm for (i = 0; i < len; i++)
8e22821528b08c6dba4e8176351560f316f6d0dedm *to = *from;
8e22821528b08c6dba4e8176351560f316f6d0dedm}
8e22821528b08c6dba4e8176351560f316f6d0dedm
8e22821528b08c6dba4e8176351560f316f6d0dedmprop_1275_cell_t *
8e22821528b08c6dba4e8176351560f316f6d0dedmcells_1275_cmp(prop_1275_cell_t *cell1, prop_1275_cell_t *cell2, int32_t len)
8e22821528b08c6dba4e8176351560f316f6d0dedm{
8e22821528b08c6dba4e8176351560f316f6d0dedm prop_1275_cell_t *match_cell = 0;
8e22821528b08c6dba4e8176351560f316f6d0dedm int32_t i;
8e22821528b08c6dba4e8176351560f316f6d0dedm
8e22821528b08c6dba4e8176351560f316f6d0dedm for (i = 0; i < len; i++)
8e22821528b08c6dba4e8176351560f316f6d0dedm if (cell1[i] != cell2[i]) {
8e22821528b08c6dba4e8176351560f316f6d0dedm match_cell = &cell1[i];
8e22821528b08c6dba4e8176351560f316f6d0dedm break;
8e22821528b08c6dba4e8176351560f316f6d0dedm }
8e22821528b08c6dba4e8176351560f316f6d0dedm
8e22821528b08c6dba4e8176351560f316f6d0dedm return (match_cell);
8e22821528b08c6dba4e8176351560f316f6d0dedm}
8e22821528b08c6dba4e8176351560f316f6d0dedm
8e22821528b08c6dba4e8176351560f316f6d0dedm/*
8e22821528b08c6dba4e8176351560f316f6d0dedm * get_intr_parent() is a generic routine that process a 1275 interrupt
8e22821528b08c6dba4e8176351560f316f6d0dedm * map (imap) property. This function returns a dev_info_t structure
8e22821528b08c6dba4e8176351560f316f6d0dedm * which claims ownership of the interrupt domain.
8e22821528b08c6dba4e8176351560f316f6d0dedm * It also returns the new interrupt translation within this new domain.
8e22821528b08c6dba4e8176351560f316f6d0dedm * If an interrupt-parent or interrupt-map property are not found,
8e22821528b08c6dba4e8176351560f316f6d0dedm * then we fallback to using the device tree's parent.
8e22821528b08c6dba4e8176351560f316f6d0dedm *
8e22821528b08c6dba4e8176351560f316f6d0dedm * imap entry format:
8e22821528b08c6dba4e8176351560f316f6d0dedm * <reg>,<interrupt>,<phandle>,<translated interrupt>
8e22821528b08c6dba4e8176351560f316f6d0dedm * reg - The register specification in the interrupts domain
8e22821528b08c6dba4e8176351560f316f6d0dedm * interrupt - The interrupt specification
8e22821528b08c6dba4e8176351560f316f6d0dedm * phandle - PROM handle of the device that owns the xlated interrupt domain
8e22821528b08c6dba4e8176351560f316f6d0dedm * translated interrupt - interrupt specifier in the parents domain
8e22821528b08c6dba4e8176351560f316f6d0dedm * note: <reg>,<interrupt> - The reg and interrupt can be combined to create
8e22821528b08c6dba4e8176351560f316f6d0dedm * a unique entry called a unit interrupt specifier.
8e22821528b08c6dba4e8176351560f316f6d0dedm *
8e22821528b08c6dba4e8176351560f316f6d0dedm * Here's the processing steps:
8e22821528b08c6dba4e8176351560f316f6d0dedm * step1 - If the interrupt-parent property exists, create the ispec and
8e22821528b08c6dba4e8176351560f316f6d0dedm * return the dip of the interrupt parent.
8e22821528b08c6dba4e8176351560f316f6d0dedm * step2 - Extract the interrupt-map property and the interrupt-map-mask
8e22821528b08c6dba4e8176351560f316f6d0dedm * If these don't exist, just return the device tree parent.
8e22821528b08c6dba4e8176351560f316f6d0dedm * step3 - build up the unit interrupt specifier to match against the
8e22821528b08c6dba4e8176351560f316f6d0dedm * interrupt map property
8e22821528b08c6dba4e8176351560f316f6d0dedm * step4 - Scan the interrupt-map property until a match is found
8e22821528b08c6dba4e8176351560f316f6d0dedm * step4a - Extract the interrupt parent
8e22821528b08c6dba4e8176351560f316f6d0dedm * step4b - Compare the unit interrupt specifier
8e22821528b08c6dba4e8176351560f316f6d0dedm */
8e22821528b08c6dba4e8176351560f316f6d0dedmdev_info_t *
8e22821528b08c6dba4e8176351560f316f6d0dedmget_intr_parent(dev_info_t *pdip, dev_info_t *dip, ddi_intr_handle_impl_t *hdlp)
8e22821528b08c6dba4e8176351560f316f6d0dedm{
8e22821528b08c6dba4e8176351560f316f6d0dedm prop_1275_cell_t *imap, *imap_mask, *scan, *reg_p, *match_req;
8e22821528b08c6dba4e8176351560f316f6d0dedm int32_t imap_sz, imap_cells, imap_scan_cells, imap_mask_sz,
8e22821528b08c6dba4e8176351560f316f6d0dedm addr_cells, intr_cells, reg_len, i, j;
8e22821528b08c6dba4e8176351560f316f6d0dedm int32_t match_found = 0;
8e22821528b08c6dba4e8176351560f316f6d0dedm dev_info_t *intr_parent_dip = NULL;
8e22821528b08c6dba4e8176351560f316f6d0dedm uint32_t *intr = &hdlp->ih_vector;
8e22821528b08c6dba4e8176351560f316f6d0dedm uint32_t nodeid;
8e22821528b08c6dba4e8176351560f316f6d0dedm#ifdef DEBUG
8e22821528b08c6dba4e8176351560f316f6d0dedm static int debug = 0;
8e22821528b08c6dba4e8176351560f316f6d0dedm#endif
8e22821528b08c6dba4e8176351560f316f6d0dedm
8e22821528b08c6dba4e8176351560f316f6d0dedm /*
8e22821528b08c6dba4e8176351560f316f6d0dedm * step1
8e22821528b08c6dba4e8176351560f316f6d0dedm * If we have an interrupt-parent property, this property represents
8e22821528b08c6dba4e8176351560f316f6d0dedm * the nodeid of our interrupt parent.
8e22821528b08c6dba4e8176351560f316f6d0dedm */
8e22821528b08c6dba4e8176351560f316f6d0dedm if ((nodeid = ddi_getprop(DDI_DEV_T_ANY, dip, 0,
8e22821528b08c6dba4e8176351560f316f6d0dedm "interrupt-parent", -1)) != -1) {
8e22821528b08c6dba4e8176351560f316f6d0dedm intr_parent_dip = e_ddi_nodeid_to_dip(nodeid);
8e22821528b08c6dba4e8176351560f316f6d0dedm ASSERT(intr_parent_dip);
8e22821528b08c6dba4e8176351560f316f6d0dedm
8e22821528b08c6dba4e8176351560f316f6d0dedm /*
8e22821528b08c6dba4e8176351560f316f6d0dedm * Attach the interrupt parent.
8e22821528b08c6dba4e8176351560f316f6d0dedm *
8e22821528b08c6dba4e8176351560f316f6d0dedm * N.B. e_ddi_nodeid_to_dip() isn't safe under DR.
8e22821528b08c6dba4e8176351560f316f6d0dedm * Also, interrupt parent isn't held. This needs
8e22821528b08c6dba4e8176351560f316f6d0dedm * to be revisited if DR-capable platforms implement
8e22821528b08c6dba4e8176351560f316f6d0dedm * interrupt redirection.
8e22821528b08c6dba4e8176351560f316f6d0dedm */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (i_ddi_attach_node_hierarchy(intr_parent_dip)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw != DDI_SUCCESS) {
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ndi_rele_devi(intr_parent_dip);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (NULL);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw }
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (intr_parent_dip);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw }
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * step2
8e22821528b08c6dba4e8176351560f316f6d0dedm * Get interrupt map structure from PROM property
8e22821528b08c6dba4e8176351560f316f6d0dedm */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (ddi_getlongprop(DDI_DEV_T_ANY, pdip, DDI_PROP_DONTPASS,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw "interrupt-map", (caddr_t)&imap, &imap_sz)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw != DDI_PROP_SUCCESS) {
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * If we don't have an imap property, default to using the
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * device tree.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ndi_hold_devi(pdip);
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban return (pdip);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw }
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /* Get the interrupt mask property */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (ddi_getlongprop(DDI_DEV_T_ANY, pdip, DDI_PROP_DONTPASS,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw "interrupt-map-mask", (caddr_t)&imap_mask, &imap_mask_sz)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw != DDI_PROP_SUCCESS) {
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * If we don't find this property, we have to fail the request
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * because the 1275 imap property wasn't defined correctly.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ASSERT(intr_parent_dip == NULL);
8e22821528b08c6dba4e8176351560f316f6d0dedm goto exit2;
8e22821528b08c6dba4e8176351560f316f6d0dedm }
8e22821528b08c6dba4e8176351560f316f6d0dedm
8e22821528b08c6dba4e8176351560f316f6d0dedm /* Get the address cell size */
8e22821528b08c6dba4e8176351560f316f6d0dedm addr_cells = ddi_getprop(DDI_DEV_T_ANY, pdip, 0,
8e22821528b08c6dba4e8176351560f316f6d0dedm "#address-cells", 2);
8e22821528b08c6dba4e8176351560f316f6d0dedm
8e22821528b08c6dba4e8176351560f316f6d0dedm /* Get the interrupts cell size */
8e22821528b08c6dba4e8176351560f316f6d0dedm intr_cells = ddi_getprop(DDI_DEV_T_ANY, pdip, 0,
8e22821528b08c6dba4e8176351560f316f6d0dedm "#interrupt-cells", 1);
8e22821528b08c6dba4e8176351560f316f6d0dedm
8e22821528b08c6dba4e8176351560f316f6d0dedm /*
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban * step3
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban * Now lets build up the unit interrupt specifier e.g. reg,intr
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban * and apply the imap mask. match_req will hold this when we're
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * through.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "reg",
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw (caddr_t)&reg_p, &reg_len) != DDI_SUCCESS) {
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban ASSERT(intr_parent_dip == NULL);
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban goto exit3;
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban }
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw match_req = kmem_alloc(CELLS_1275_TO_BYTES(addr_cells) +
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw CELLS_1275_TO_BYTES(intr_cells), KM_SLEEP);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw for (i = 0; i < addr_cells; i++)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw match_req[i] = (reg_p[i] & imap_mask[i]);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw for (j = 0; j < intr_cells; i++, j++)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw match_req[i] = (intr[j] & imap_mask[i]);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /* Calculate the imap size in cells */
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban imap_cells = BYTES_TO_1275_CELLS(imap_sz);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban#ifdef DEBUG
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (debug)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw prom_printf("reg cell size 0x%x, intr cell size 0x%x, "
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw "match_request 0x%p, imap 0x%p\n", addr_cells, intr_cells,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw (void *)match_req, (void *)imap);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw#endif
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Scan the imap property looking for a match of the interrupt unit
8e22821528b08c6dba4e8176351560f316f6d0dedm * specifier. This loop is rather complex since the data within the
8e22821528b08c6dba4e8176351560f316f6d0dedm * imap property may vary in size.
8e22821528b08c6dba4e8176351560f316f6d0dedm */
8e22821528b08c6dba4e8176351560f316f6d0dedm for (scan = imap, imap_scan_cells = i = 0;
8e22821528b08c6dba4e8176351560f316f6d0dedm imap_scan_cells < imap_cells; scan += i, imap_scan_cells += i) {
8e22821528b08c6dba4e8176351560f316f6d0dedm int new_intr_cells;
8e22821528b08c6dba4e8176351560f316f6d0dedm
8e22821528b08c6dba4e8176351560f316f6d0dedm /* Set the index to the nodeid field */
8e22821528b08c6dba4e8176351560f316f6d0dedm i = addr_cells + intr_cells;
8e22821528b08c6dba4e8176351560f316f6d0dedm
8e22821528b08c6dba4e8176351560f316f6d0dedm /*
8e22821528b08c6dba4e8176351560f316f6d0dedm * step4a
8e22821528b08c6dba4e8176351560f316f6d0dedm * Translate the nodeid field to a dip
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban */
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban ASSERT(intr_parent_dip == NULL);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw intr_parent_dip = e_ddi_nodeid_to_dip((uint_t)scan[i++]);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ASSERT(intr_parent_dip != 0);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw#ifdef DEBUG
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban if (debug)
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban prom_printf("scan 0x%p\n", (void *)scan);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw#endif
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * The tmp_dip describes the new domain, get it's interrupt
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * cell size
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw new_intr_cells = ddi_getprop(DDI_DEV_T_ANY, intr_parent_dip, 0,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw "#interrupts-cells", 1);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * step4b
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban * See if we have a match on the interrupt unit specifier
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (cells_1275_cmp(match_req, scan, addr_cells + intr_cells)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw == 0) {
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw uint32_t *intr;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw match_found = 1;
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban /*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * If we have an imap parent whose not in our device
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * tree path, we need to hold and install that driver.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (i_ddi_attach_node_hierarchy(intr_parent_dip)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw != DDI_SUCCESS) {
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ndi_rele_devi(intr_parent_dip);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw intr_parent_dip = (dev_info_t *)NULL;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw goto exit4;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw }
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * We need to handcraft an ispec along with a bus
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * interrupt value, so we can dup it into our
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * standard ispec structure.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /* Extract the translated interrupt information */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw intr = kmem_alloc(
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw CELLS_1275_TO_BYTES(new_intr_cells), KM_SLEEP);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw for (j = 0; j < new_intr_cells; j++, i++)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw intr[j] = scan[i];
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw cells_1275_copy(intr, &hdlp->ih_vector, new_intr_cells);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw kmem_free(intr, CELLS_1275_TO_BYTES(new_intr_cells));
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw#ifdef DEBUG
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (debug)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw prom_printf("dip 0x%p\n",
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw (void *)intr_parent_dip);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw#endif
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw break;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw } else {
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw#ifdef DEBUG
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (debug)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw prom_printf("dip 0x%p\n",
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw (void *)intr_parent_dip);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw#endif
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ndi_rele_devi(intr_parent_dip);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw intr_parent_dip = NULL;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw i += new_intr_cells;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw }
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw }
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * If we haven't found our interrupt parent at this point, fallback
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * to using the device tree.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (!match_found) {
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ndi_hold_devi(pdip);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ASSERT(intr_parent_dip == NULL);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw intr_parent_dip = pdip;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw }
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban
8e22821528b08c6dba4e8176351560f316f6d0dedm ASSERT(intr_parent_dip != NULL);
8e22821528b08c6dba4e8176351560f316f6d0dedm
8e22821528b08c6dba4e8176351560f316f6d0dedmexit4:
8e22821528b08c6dba4e8176351560f316f6d0dedm kmem_free(reg_p, reg_len);
8e22821528b08c6dba4e8176351560f316f6d0dedm kmem_free(match_req, CELLS_1275_TO_BYTES(addr_cells) +
8e22821528b08c6dba4e8176351560f316f6d0dedm CELLS_1275_TO_BYTES(intr_cells));
8e22821528b08c6dba4e8176351560f316f6d0dedm
8e22821528b08c6dba4e8176351560f316f6d0dedmexit3:
8e22821528b08c6dba4e8176351560f316f6d0dedm kmem_free(imap_mask, imap_mask_sz);
8e22821528b08c6dba4e8176351560f316f6d0dedm
8e22821528b08c6dba4e8176351560f316f6d0dedmexit2:
8e22821528b08c6dba4e8176351560f316f6d0dedm kmem_free(imap, imap_sz);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (intr_parent_dip);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * process_intr_ops:
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw *
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Process the interrupt op via the interrupt parent.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwint
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwprocess_intr_ops(dev_info_t *pdip, dev_info_t *rdip, ddi_intr_op_t op,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ddi_intr_handle_impl_t *hdlp, void *result)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw{
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw int ret = DDI_FAILURE;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (NEXUS_HAS_INTR_OP(pdip)) {
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ret = (*(DEVI(pdip)->devi_ops->devo_bus_ops->
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw bus_intr_op)) (pdip, rdip, op, hdlp, result);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw } else {
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw cmn_err(CE_WARN, "Failed to process interrupt "
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw "for %s%d due to down-rev nexus driver %s%d",
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ddi_get_name(rdip), ddi_get_instance(rdip),
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ddi_get_name(pdip), ddi_get_instance(pdip));
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw }
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (ret);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*ARGSUSED*/
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwuint_t
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwsoftlevel1(caddr_t arg)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw{
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw softint();
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (1);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * indirection table, to save us some large switch statements
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * NOTE: This must agree with "INTLEVEL_foo" constants in
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * <sys/avintr.h>
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwstruct autovec *const vectorlist[] = { 0 };
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * This value is exported here for the functions in avintr.c
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwconst uint_t maxautovec = (sizeof (vectorlist) / sizeof (vectorlist[0]));
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Check for machine specific interrupt levels which cannot be reassigned by
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * settrap(), sun4u version.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw *
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * sun4u does not support V8 SPARC "fast trap" handlers.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*ARGSUSED*/
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwint
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwexclude_settrap(int lvl)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw{
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (1);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Check for machine specific interrupt levels which cannot have interrupt
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * handlers added. We allow levels 1 through 15; level 0 is nonsense.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*ARGSUSED*/
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwint
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwexclude_level(int lvl)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw{
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return ((lvl < 1) || (lvl > 15));
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Wrapper functions used by New DDI interrupt framework.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * i_ddi_intr_ops:
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwint
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwi_ddi_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t op,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ddi_intr_handle_impl_t *hdlp, void *result)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw{
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw dev_info_t *pdip = ddi_get_parent(dip);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw int ret = DDI_FAILURE;
8e22821528b08c6dba4e8176351560f316f6d0dedm
8e22821528b08c6dba4e8176351560f316f6d0dedm /*
8e22821528b08c6dba4e8176351560f316f6d0dedm * The following check is required to address
8e22821528b08c6dba4e8176351560f316f6d0dedm * one of the test case of ADDI test suite.
8e22821528b08c6dba4e8176351560f316f6d0dedm */
8e22821528b08c6dba4e8176351560f316f6d0dedm if (pdip == NULL)
8e22821528b08c6dba4e8176351560f316f6d0dedm return (DDI_FAILURE);
8e22821528b08c6dba4e8176351560f316f6d0dedm
8e22821528b08c6dba4e8176351560f316f6d0dedm if (hdlp->ih_type != DDI_INTR_TYPE_FIXED)
8e22821528b08c6dba4e8176351560f316f6d0dedm return (process_intr_ops(pdip, rdip, op, hdlp, result));
8e22821528b08c6dba4e8176351560f316f6d0dedm
8e22821528b08c6dba4e8176351560f316f6d0dedm if (hdlp->ih_vector == 0)
8e22821528b08c6dba4e8176351560f316f6d0dedm hdlp->ih_vector = i_ddi_get_inum(rdip, hdlp->ih_inum);
8e22821528b08c6dba4e8176351560f316f6d0dedm
8e22821528b08c6dba4e8176351560f316f6d0dedm if (hdlp->ih_pri == 0)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw hdlp->ih_pri = i_ddi_get_intr_pri(rdip, hdlp->ih_inum);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw switch (op) {
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw case DDI_INTROP_ADDISR:
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw case DDI_INTROP_REMISR:
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw case DDI_INTROP_GETTARGET:
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw case DDI_INTROP_SETTARGET:
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw case DDI_INTROP_ENABLE:
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw case DDI_INTROP_DISABLE:
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw case DDI_INTROP_BLOCKENABLE:
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw case DDI_INTROP_BLOCKDISABLE:
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Try and determine our parent and possibly an interrupt
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * translation. intr parent dip returned held
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if ((pdip = get_intr_parent(pdip, dip, hdlp)) == NULL)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw goto done;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw }
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ret = process_intr_ops(pdip, rdip, op, hdlp, result);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwdone:
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw switch (op) {
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw case DDI_INTROP_ADDISR:
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw case DDI_INTROP_REMISR:
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw case DDI_INTROP_ENABLE:
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw case DDI_INTROP_DISABLE:
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw case DDI_INTROP_BLOCKENABLE:
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw case DDI_INTROP_BLOCKDISABLE:
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /* Release hold acquired in get_intr_parent() */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (pdip)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ndi_rele_devi(pdip);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw }
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw hdlp->ih_vector = 0;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (ret);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * i_ddi_add_ivintr:
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*ARGSUSED*/
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwint
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwi_ddi_add_ivintr(ddi_intr_handle_impl_t *hdlp)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw{
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * If the PIL was set and is valid use it, otherwise
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * default it to 1
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if ((hdlp->ih_pri < 1) || (hdlp->ih_pri > PIL_MAX))
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw hdlp->ih_pri = 1;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw VERIFY(add_ivintr(hdlp->ih_vector, hdlp->ih_pri,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw (intrfunc)hdlp->ih_cb_func, hdlp->ih_cb_arg1,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw hdlp->ih_cb_arg2, NULL) == 0);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (DDI_SUCCESS);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * i_ddi_rem_ivintr:
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*ARGSUSED*/
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwvoid
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwi_ddi_rem_ivintr(ddi_intr_handle_impl_t *hdlp)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw{
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw VERIFY(rem_ivintr(hdlp->ih_vector, hdlp->ih_pri) == 0);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * i_ddi_get_inum - Get the interrupt number property from the
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * specified device. Note that this function is called only for
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * the FIXED interrupt type.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwuint32_t
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwi_ddi_get_inum(dev_info_t *dip, uint_t inumber)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw{
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw int32_t intrlen, intr_cells, max_intrs;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw prop_1275_cell_t *ip, intr_sz;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw uint32_t intr = 0;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS |
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw DDI_PROP_CANSLEEP,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw "interrupts", (caddr_t)&ip, &intrlen) == DDI_SUCCESS) {
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw intr_cells = ddi_getprop(DDI_DEV_T_ANY, dip, 0,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw "#interrupt-cells", 1);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /* adjust for number of bytes */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw intr_sz = CELLS_1275_TO_BYTES(intr_cells);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /* Calculate the number of interrupts */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw max_intrs = intrlen / intr_sz;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (inumber < max_intrs) {
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw prop_1275_cell_t *intrp = ip;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /* Index into interrupt property */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw intrp += (inumber * intr_cells);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw cells_1275_copy(intrp, &intr, intr_cells);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw }
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw kmem_free(ip, intrlen);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw }
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (intr);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * i_ddi_get_intr_pri - Get the interrupt-priorities property from
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * the specified device. Note that this function is called only for
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * the FIXED interrupt type.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwuint32_t
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwi_ddi_get_intr_pri(dev_info_t *dip, uint_t inumber)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw{
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw uint32_t *intr_prio_p;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw uint32_t pri = 0;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw int32_t i;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Use the "interrupt-priorities" property to determine the
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * the pil/ipl for the interrupt handler.
8edda6281c84e0632a22f9c8dbf0d6f1558878ebbaban */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
9581d9f4f3b1515f88149f920c7e786b4fb901d4baban "interrupt-priorities", (caddr_t)&intr_prio_p,
9581d9f4f3b1515f88149f920c7e786b4fb901d4baban &i) == DDI_SUCCESS) {
9581d9f4f3b1515f88149f920c7e786b4fb901d4baban if (inumber < (i / sizeof (int32_t)))
9581d9f4f3b1515f88149f920c7e786b4fb901d4baban pri = intr_prio_p[inumber];
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw kmem_free(intr_prio_p, i);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw }
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (pri);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw}
8e22821528b08c6dba4e8176351560f316f6d0dedm
8e22821528b08c6dba4e8176351560f316f6d0dedmint
8e22821528b08c6dba4e8176351560f316f6d0dedmi_ddi_get_intx_nintrs(dev_info_t *dip)
8e22821528b08c6dba4e8176351560f316f6d0dedm{
8e22821528b08c6dba4e8176351560f316f6d0dedm int32_t intrlen;
8e22821528b08c6dba4e8176351560f316f6d0dedm prop_1275_cell_t intr_sz;
8e22821528b08c6dba4e8176351560f316f6d0dedm prop_1275_cell_t *ip;
8e22821528b08c6dba4e8176351560f316f6d0dedm int32_t ret = 0;
8e22821528b08c6dba4e8176351560f316f6d0dedm
8e22821528b08c6dba4e8176351560f316f6d0dedm if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS |
8e22821528b08c6dba4e8176351560f316f6d0dedm DDI_PROP_CANSLEEP,
8e22821528b08c6dba4e8176351560f316f6d0dedm "interrupts", (caddr_t)&ip, &intrlen) == DDI_SUCCESS) {
8e22821528b08c6dba4e8176351560f316f6d0dedm
8e22821528b08c6dba4e8176351560f316f6d0dedm intr_sz = ddi_getprop(DDI_DEV_T_ANY, dip, 0,
8e22821528b08c6dba4e8176351560f316f6d0dedm "#interrupt-cells", 1);
8e22821528b08c6dba4e8176351560f316f6d0dedm /* adjust for number of bytes */
8e22821528b08c6dba4e8176351560f316f6d0dedm intr_sz = CELLS_1275_TO_BYTES(intr_sz);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ret = intrlen / intr_sz;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw kmem_free(ip, intrlen);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw }
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (ret);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * i_ddi_add_softint - allocate and add a software interrupt.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw *
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * NOTE: All software interrupts that are registered through DDI
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * should be triggered only on a single target or CPU.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwint
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwi_ddi_add_softint(ddi_softint_hdl_impl_t *hdlp)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw{
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if ((hdlp->ih_private = (void *)add_softintr(hdlp->ih_pri,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw hdlp->ih_cb_func, hdlp->ih_cb_arg1, SOFTINT_ST)) == NULL)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (DDI_FAILURE);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (DDI_SUCCESS);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * i_ddi_remove_softint - remove and free a software interrupt.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwvoid
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwi_ddi_remove_softint(ddi_softint_hdl_impl_t *hdlp)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw{
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ASSERT(hdlp->ih_private != NULL);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (rem_softintr((uint64_t)hdlp->ih_private) == 0)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw hdlp->ih_private = NULL;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * i_ddi_trigger_softint - trigger a software interrupt.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwint
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwi_ddi_trigger_softint(ddi_softint_hdl_impl_t *hdlp, void *arg2)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw{
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw int ret;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ASSERT(hdlp->ih_private != NULL);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /* Update the second argument for the software interrupt */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if ((ret = update_softint_arg2((uint64_t)hdlp->ih_private, arg2)) == 0)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw setsoftint((uint64_t)hdlp->ih_private);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (ret ? DDI_EPENDING : DDI_SUCCESS);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * i_ddi_set_softint_pri - change software interrupt priority.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/* ARGSUSED */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwint
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwi_ddi_set_softint_pri(ddi_softint_hdl_impl_t *hdlp, uint_t old_pri)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw{
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw int ret;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ASSERT(hdlp->ih_private != NULL);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /* Update the interrupt priority for the software interrupt */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ret = update_softint_pri((uint64_t)hdlp->ih_private, hdlp->ih_pri);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (ret ? DDI_FAILURE : DDI_SUCCESS);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*ARGSUSED*/
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwvoid
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwi_ddi_alloc_intr_phdl(ddi_intr_handle_impl_t *hdlp)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw{
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*ARGSUSED*/
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwvoid
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwi_ddi_free_intr_phdl(ddi_intr_handle_impl_t *hdlp)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw{
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * SECTION: DDI Memory/DMA
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/* set HAT endianess attributes from ddi_device_acc_attr */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwvoid
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwi_ddi_devacc_to_hatacc(ddi_device_acc_attr_t *devaccp, uint_t *hataccp)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw{
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (devaccp != NULL) {
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (devaccp->devacc_attr_endian_flags == DDI_STRUCTURE_LE_ACC) {
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw *hataccp &= ~HAT_ENDIAN_MASK;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw *hataccp |= HAT_STRUCTURE_LE;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw }
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw }
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Check if the specified cache attribute is supported on the platform.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * This function must be called before i_ddi_cacheattr_to_hatacc().
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwboolean_t
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwi_ddi_check_cache_attr(uint_t flags)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw{
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * The cache attributes are mutually exclusive. Any combination of
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * the attributes leads to a failure.
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw uint_t cache_attr = IOMEM_CACHE_ATTR(flags);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if ((cache_attr != 0) && ((cache_attr & (cache_attr - 1)) != 0))
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (B_FALSE);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * On the sparc architecture, only IOMEM_DATA_CACHED is meaningful,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * but others lead to a failure.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (cache_attr & IOMEM_DATA_CACHED)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (B_TRUE);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw else
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (B_FALSE);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/* set HAT cache attributes from the cache attributes */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwvoid
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwi_ddi_cacheattr_to_hatacc(uint_t flags, uint_t *hataccp)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw{
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw uint_t cache_attr = IOMEM_CACHE_ATTR(flags);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw static char *fname = "i_ddi_cacheattr_to_hatacc";
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw#if defined(lint)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw *hataccp = *hataccp;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw#endif
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * set HAT attrs according to the cache attrs.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw switch (cache_attr) {
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * The cache coherency is always maintained on SPARC, and
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * nothing is required.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban case IOMEM_DATA_CACHED:
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban break;
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban /*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Both IOMEM_DATA_UC_WRITE_COMBINED and IOMEM_DATA_UNCACHED are
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * not supported on SPARC -- this case must not occur because the
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * cache attribute is scrutinized before this function is called.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw case IOMEM_DATA_UNCACHED:
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw case IOMEM_DATA_UC_WR_COMBINE:
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw default:
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw cmn_err(CE_WARN, "%s: cache_attr=0x%x is ignored.",
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw fname, cache_attr);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw }
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwstatic vmem_t *little_endian_arena;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwstatic vmem_t *big_endian_arena;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwstatic void *
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwsegkmem_alloc_le(vmem_t *vmp, size_t size, int flag)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw{
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (segkmem_xalloc(vmp, NULL, size, flag, HAT_STRUCTURE_LE,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw segkmem_page_create, NULL));
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwstatic void *
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwsegkmem_alloc_be(vmem_t *vmp, size_t size, int flag)
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban{
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (segkmem_xalloc(vmp, NULL, size, flag, HAT_STRUCTURE_BE,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw segkmem_page_create, NULL));
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwvoid
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwka_init(void)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw{
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw little_endian_arena = vmem_create("little_endian", NULL, 0, 1,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw segkmem_alloc_le, segkmem_free, heap_arena, 0, VM_SLEEP);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw big_endian_arena = vmem_create("big_endian", NULL, 0, 1,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw segkmem_alloc_be, segkmem_free, heap_arena, 0, VM_SLEEP);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Allocate from the system, aligned on a specific boundary.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * The alignment, if non-zero, must be a power of 2.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwstatic void *
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwkalloca(size_t size, size_t align, int cansleep, uint_t endian_flags)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw{
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw size_t *addr, *raddr, rsize;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw size_t hdrsize = 4 * sizeof (size_t); /* must be power of 2 */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw align = MAX(align, hdrsize);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ASSERT((align & (align - 1)) == 0);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * We need to allocate
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * rsize = size + hdrsize + align - MIN(hdrsize, buffer_alignment)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * bytes to be sure we have enough freedom to satisfy the request.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Since the buffer alignment depends on the request size, this is
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban * not straightforward to use directly.
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban *
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * kmem guarantees that any allocation of a 64-byte multiple will be
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * 64-byte aligned. Since rounding up the request could add more
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * than we save, we compute the size with and without alignment, and
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * use the smaller of the two.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw rsize = size + hdrsize + align;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (endian_flags == DDI_STRUCTURE_LE_ACC) {
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw raddr = vmem_alloc(little_endian_arena, rsize,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw cansleep ? VM_SLEEP : VM_NOSLEEP);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw } else {
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw raddr = vmem_alloc(big_endian_arena, rsize,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw cansleep ? VM_SLEEP : VM_NOSLEEP);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw }
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (raddr == NULL)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (NULL);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw addr = (size_t *)P2ROUNDUP((uintptr_t)raddr + hdrsize, align);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ASSERT((uintptr_t)addr + size - (uintptr_t)raddr <= rsize);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw addr[-3] = (size_t)endian_flags;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw addr[-2] = (size_t)raddr;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw addr[-1] = rsize;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban return (addr);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwstatic void
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwkfreea(void *addr)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw{
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw size_t *saddr = addr;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (saddr[-3] == DDI_STRUCTURE_LE_ACC)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw vmem_free(little_endian_arena, (void *)saddr[-2], saddr[-1]);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw else
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw vmem_free(big_endian_arena, (void *)saddr[-2], saddr[-1]);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwint
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwi_ddi_mem_alloc(dev_info_t *dip, ddi_dma_attr_t *attr,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw size_t length, int cansleep, int flags,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ddi_device_acc_attr_t *accattrp,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw caddr_t *kaddrp, size_t *real_length, ddi_acc_hdl_t *handlep)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw{
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw caddr_t a;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw int iomin, align, streaming;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw uint_t endian_flags = DDI_NEVERSWAP_ACC;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw#if defined(lint)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw *handlep = *handlep;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw#endif
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Check legality of arguments
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (length == 0 || kaddrp == NULL || attr == NULL) {
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (DDI_FAILURE);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw }
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban if (attr->dma_attr_minxfer == 0 || attr->dma_attr_align == 0 ||
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw (attr->dma_attr_align & (attr->dma_attr_align - 1)) ||
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw (attr->dma_attr_minxfer & (attr->dma_attr_minxfer - 1))) {
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (DDI_FAILURE);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw }
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * check if a streaming sequential xfer is requested.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw streaming = (flags & DDI_DMA_STREAMING) ? 1 : 0;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Drivers for 64-bit capable SBus devices will encode
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * the burtsizes for 64-bit xfers in the upper 16-bits.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * For DMA alignment, we use the most restrictive
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * alignment of 32-bit and 64-bit xfers.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw iomin = (attr->dma_attr_burstsizes & 0xffff) |
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ((attr->dma_attr_burstsizes >> 16) & 0xffff);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * If a driver set burtsizes to 0, we give him byte alignment.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Otherwise align at the burtsizes boundary.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (iomin == 0)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw iomin = 1;
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban else
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw iomin = 1 << (ddi_fls(iomin) - 1);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw iomin = maxbit(iomin, attr->dma_attr_minxfer);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw iomin = maxbit(iomin, attr->dma_attr_align);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw iomin = ddi_iomin(dip, iomin, streaming);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (iomin == 0)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (DDI_FAILURE);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ASSERT((iomin & (iomin - 1)) == 0);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ASSERT(iomin >= attr->dma_attr_minxfer);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ASSERT(iomin >= attr->dma_attr_align);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw length = P2ROUNDUP(length, iomin);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw align = iomin;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (accattrp != NULL)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw endian_flags = accattrp->devacc_attr_endian_flags;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw a = kalloca(length, align, cansleep, endian_flags);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if ((*kaddrp = a) == 0) {
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (DDI_FAILURE);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw } else {
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (real_length) {
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw *real_length = length;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw }
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (handlep) {
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * assign handle information
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban impl_acc_hdl_init(handlep);
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban }
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (DDI_SUCCESS);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw }
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * covert old DMA limits structure to DMA attribute structure
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * and continue
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwint
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwi_ddi_mem_alloc_lim(dev_info_t *dip, ddi_dma_lim_t *limits,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw size_t length, int cansleep, int streaming,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ddi_device_acc_attr_t *accattrp, caddr_t *kaddrp,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw uint_t *real_length, ddi_acc_hdl_t *ap)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw{
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ddi_dma_attr_t dma_attr, *attrp;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw size_t rlen;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw int ret;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ASSERT(limits);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw attrp = &dma_attr;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw attrp->dma_attr_version = DMA_ATTR_V0;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw attrp->dma_attr_addr_lo = (uint64_t)limits->dlim_addr_lo;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw attrp->dma_attr_addr_hi = (uint64_t)limits->dlim_addr_hi;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw attrp->dma_attr_count_max = (uint64_t)-1;
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban attrp->dma_attr_align = 1;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw attrp->dma_attr_burstsizes = (uint_t)limits->dlim_burstsizes;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw attrp->dma_attr_minxfer = (uint32_t)limits->dlim_minxfer;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw attrp->dma_attr_maxxfer = (uint64_t)-1;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw attrp->dma_attr_seg = (uint64_t)limits->dlim_cntr_max;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw attrp->dma_attr_sgllen = 1;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw attrp->dma_attr_granular = 1;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw attrp->dma_attr_flags = 0;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ret = i_ddi_mem_alloc(dip, attrp, length, cansleep, streaming,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw accattrp, kaddrp, &rlen, ap);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (ret == DDI_SUCCESS) {
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (real_length)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw *real_length = (uint_t)rlen;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw }
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (ret);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/* ARGSUSED */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwvoid
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwi_ddi_mem_free(caddr_t kaddr, ddi_acc_hdl_t *ap)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw{
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw kfreea(kaddr);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * SECTION: DDI Data Access
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
651c0131ccc65381cbda174bee44a4fd7a518d6bbabanstatic uintptr_t impl_acc_hdl_id = 0;
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * access handle allocator
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwddi_acc_hdl_t *
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwimpl_acc_hdl_get(ddi_acc_handle_t hdl)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw{
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Extract the access handle address from the DDI implemented
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * access handle
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (&((ddi_acc_impl_t *)hdl)->ahi_common);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwddi_acc_handle_t
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwimpl_acc_hdl_alloc(int (*waitfp)(caddr_t), caddr_t arg)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw{
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ddi_acc_impl_t *hp;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw on_trap_data_t *otp;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw int sleepflag;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw sleepflag = ((waitfp == (int (*)())KM_SLEEP) ? KM_SLEEP : KM_NOSLEEP);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Allocate and initialize the data access handle and error status.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if ((hp = kmem_zalloc(sizeof (ddi_acc_impl_t), sleepflag)) == NULL)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw goto fail;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if ((hp->ahi_err = (ndi_err_t *)kmem_zalloc(
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw sizeof (ndi_err_t), sleepflag)) == NULL) {
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw kmem_free(hp, sizeof (ddi_acc_impl_t));
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw goto fail;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw }
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if ((otp = (on_trap_data_t *)kmem_zalloc(
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban sizeof (on_trap_data_t), sleepflag)) == NULL) {
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw kmem_free(hp->ahi_err, sizeof (ndi_err_t));
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw kmem_free(hp, sizeof (ddi_acc_impl_t));
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw goto fail;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw }
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw hp->ahi_err->err_ontrap = otp;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw hp->ahi_common.ah_platform_private = (void *)hp;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return ((ddi_acc_handle_t)hp);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwfail:
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if ((waitfp != (int (*)())KM_SLEEP) &&
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw (waitfp != (int (*)())KM_NOSLEEP))
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ddi_set_callback(waitfp, arg, &impl_acc_hdl_id);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (NULL);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwvoid
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwimpl_acc_hdl_free(ddi_acc_handle_t handle)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw{
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ddi_acc_impl_t *hp;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * The supplied (ddi_acc_handle_t) is actually a (ddi_acc_impl_t *),
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * because that's what we allocated in impl_acc_hdl_alloc() above.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw hp = (ddi_acc_impl_t *)handle;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (hp) {
62c6006265c37877b7a5b3c8ffce913ef559b955baban kmem_free(hp->ahi_err->err_ontrap, sizeof (on_trap_data_t));
62c6006265c37877b7a5b3c8ffce913ef559b955baban kmem_free(hp->ahi_err, sizeof (ndi_err_t));
62c6006265c37877b7a5b3c8ffce913ef559b955baban kmem_free(hp, sizeof (ddi_acc_impl_t));
62c6006265c37877b7a5b3c8ffce913ef559b955baban if (impl_acc_hdl_id)
62c6006265c37877b7a5b3c8ffce913ef559b955baban ddi_run_callback(&impl_acc_hdl_id);
62c6006265c37877b7a5b3c8ffce913ef559b955baban }
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw#define PCI_GET_MP_PFN(mp, page_no) ((mp)->dmai_ndvmapages == 1 ? \
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw (pfn_t)(mp)->dmai_iopte:(((pfn_t *)(mp)->dmai_iopte)[page_no]))
8edda6281c84e0632a22f9c8dbf0d6f1558878ebbaban
8edda6281c84e0632a22f9c8dbf0d6f1558878ebbaban/*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Function called after a dma fault occurred to find out whether the
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * fault address is associated with a driver that is able to handle faults
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * and recover from faults.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/* ARGSUSED */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwint
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwimpl_dma_check(dev_info_t *dip, const void *handle, const void *addr,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw const void *not_used)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw{
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ddi_dma_impl_t *mp = (ddi_dma_impl_t *)handle;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw pfn_t fault_pfn = mmu_btop(*(uint64_t *)addr);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw pfn_t comp_pfn;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * The driver has to set DDI_DMA_FLAGERR to recover from dma faults.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw int page;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ASSERT(mp);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw for (page = 0; page < mp->dmai_ndvmapages; page++) {
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban comp_pfn = PCI_GET_MP_PFN(mp, page);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (fault_pfn == comp_pfn)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (DDI_FM_NONFATAL);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw }
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (DDI_FM_UNKNOWN);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Function used to check if a given access handle owns the failing address.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Called by ndi_fmc_error, when we detect a PIO error.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/* ARGSUSED */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwstatic int
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwimpl_acc_check(dev_info_t *dip, const void *handle, const void *addr,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw const void *not_used)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw{
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw pfn_t pfn, fault_pfn;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ddi_acc_hdl_t *hp;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw hp = impl_acc_hdl_get((ddi_acc_handle_t)handle);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ASSERT(hp);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (addr != NULL) {
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw pfn = hp->ah_pfn;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw fault_pfn = mmu_btop(*(uint64_t *)addr);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (fault_pfn >= pfn && fault_pfn < (pfn + hp->ah_pnum))
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (DDI_FM_NONFATAL);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw }
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (DDI_FM_UNKNOWN);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwvoid
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwimpl_acc_err_init(ddi_acc_hdl_t *handlep)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw{
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw int fmcap;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ndi_err_t *errp;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw on_trap_data_t *otp;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ddi_acc_impl_t *hp = (ddi_acc_impl_t *)handlep;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw fmcap = ddi_fm_capable(handlep->ah_dip);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (handlep->ah_acc.devacc_attr_version < DDI_DEVICE_ATTR_V1 ||
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw !DDI_FM_ACC_ERR_CAP(fmcap)) {
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw handlep->ah_acc.devacc_attr_access = DDI_DEFAULT_ACC;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw } else if (DDI_FM_ACC_ERR_CAP(fmcap)) {
62c6006265c37877b7a5b3c8ffce913ef559b955baban if (handlep->ah_acc.devacc_attr_access == DDI_DEFAULT_ACC) {
62c6006265c37877b7a5b3c8ffce913ef559b955baban if (handlep->ah_xfermodes)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw i_ddi_drv_ereport_post(handlep->ah_dip, DVR_EFMCAP,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw NULL, DDI_NOSLEEP);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw } else {
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw errp = hp->ahi_err;
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban otp = (on_trap_data_t *)errp->err_ontrap;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw otp->ot_handle = (void *)(hp);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw otp->ot_prot = OT_DATA_ACCESS;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (handlep->ah_acc.devacc_attr_access ==
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw DDI_CAUTIOUS_ACC)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw otp->ot_trampoline =
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw (uintptr_t)&i_ddi_caut_trampoline;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw else
8e22821528b08c6dba4e8176351560f316f6d0dedm otp->ot_trampoline =
c5a946bac9ff4ebd4d874e1c94d41a5ffcbad287baban (uintptr_t)&i_ddi_prot_trampoline;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw errp->err_status = DDI_FM_OK;
8e22821528b08c6dba4e8176351560f316f6d0dedm errp->err_expected = DDI_FM_ERR_UNEXPECTED;
8e22821528b08c6dba4e8176351560f316f6d0dedm errp->err_cf = impl_acc_check;
c5a946bac9ff4ebd4d874e1c94d41a5ffcbad287baban }
8e22821528b08c6dba4e8176351560f316f6d0dedm }
8e22821528b08c6dba4e8176351560f316f6d0dedm}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwvoid
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwimpl_acc_hdl_init(ddi_acc_hdl_t *handlep)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw{
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ddi_acc_impl_t *hp;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ASSERT(handlep);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw hp = (ddi_acc_impl_t *)handlep;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * check for SW byte-swapping
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw hp->ahi_get8 = i_ddi_get8;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw hp->ahi_put8 = i_ddi_put8;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw hp->ahi_rep_get8 = i_ddi_rep_get8;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw hp->ahi_rep_put8 = i_ddi_rep_put8;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (handlep->ah_acc.devacc_attr_endian_flags & DDI_STRUCTURE_LE_ACC) {
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw hp->ahi_get16 = i_ddi_swap_get16;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw hp->ahi_get32 = i_ddi_swap_get32;
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban hp->ahi_get64 = i_ddi_swap_get64;
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban hp->ahi_put16 = i_ddi_swap_put16;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw hp->ahi_put32 = i_ddi_swap_put32;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw hp->ahi_put64 = i_ddi_swap_put64;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw hp->ahi_rep_get16 = i_ddi_swap_rep_get16;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw hp->ahi_rep_get32 = i_ddi_swap_rep_get32;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw hp->ahi_rep_get64 = i_ddi_swap_rep_get64;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw hp->ahi_rep_put16 = i_ddi_swap_rep_put16;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw hp->ahi_rep_put32 = i_ddi_swap_rep_put32;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw hp->ahi_rep_put64 = i_ddi_swap_rep_put64;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw } else {
62c6006265c37877b7a5b3c8ffce913ef559b955baban hp->ahi_get16 = i_ddi_get16;
62c6006265c37877b7a5b3c8ffce913ef559b955baban hp->ahi_get32 = i_ddi_get32;
62c6006265c37877b7a5b3c8ffce913ef559b955baban hp->ahi_get64 = i_ddi_get64;
62c6006265c37877b7a5b3c8ffce913ef559b955baban hp->ahi_put16 = i_ddi_put16;
62c6006265c37877b7a5b3c8ffce913ef559b955baban hp->ahi_put32 = i_ddi_put32;
62c6006265c37877b7a5b3c8ffce913ef559b955baban hp->ahi_put64 = i_ddi_put64;
62c6006265c37877b7a5b3c8ffce913ef559b955baban hp->ahi_rep_get16 = i_ddi_rep_get16;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw hp->ahi_rep_get32 = i_ddi_rep_get32;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw hp->ahi_rep_get64 = i_ddi_rep_get64;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw hp->ahi_rep_put16 = i_ddi_rep_put16;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw hp->ahi_rep_put32 = i_ddi_rep_put32;
8e22821528b08c6dba4e8176351560f316f6d0dedm hp->ahi_rep_put64 = i_ddi_rep_put64;
8e22821528b08c6dba4e8176351560f316f6d0dedm }
8e22821528b08c6dba4e8176351560f316f6d0dedm
8e22821528b08c6dba4e8176351560f316f6d0dedm /* Legacy fault flags and support */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw hp->ahi_fault_check = i_ddi_acc_fault_check;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw hp->ahi_fault_notify = i_ddi_acc_fault_notify;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw hp->ahi_fault = 0;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw impl_acc_err_init(handlep);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwvoid
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwi_ddi_acc_set_fault(ddi_acc_handle_t handle)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw{
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ddi_acc_impl_t *hp = (ddi_acc_impl_t *)handle;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (!hp->ahi_fault) {
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw hp->ahi_fault = 1;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw (*hp->ahi_fault_notify)(hp);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw }
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwvoid
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwi_ddi_acc_clr_fault(ddi_acc_handle_t handle)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw{
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ddi_acc_impl_t *hp = (ddi_acc_impl_t *)handle;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (hp->ahi_fault) {
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw hp->ahi_fault = 0;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw (*hp->ahi_fault_notify)(hp);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw }
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/* ARGSUSED */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwvoid
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwi_ddi_acc_fault_notify(ddi_acc_impl_t *hp)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw{
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /* Default version, does nothing */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * SECTION: Misc functions
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * instance wrappers
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*ARGSUSED*/
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwuint_t
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwimpl_assign_instance(dev_info_t *dip)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw{
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return ((uint_t)-1);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*ARGSUSED*/
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwint
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwimpl_keep_instance(dev_info_t *dip)
8e22821528b08c6dba4e8176351560f316f6d0dedm{
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (DDI_FAILURE);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*ARGSUSED*/
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwint
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwimpl_free_instance(dev_info_t *dip)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw{
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (DDI_FAILURE);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*ARGSUSED*/
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwint
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwimpl_check_cpu(dev_info_t *devi)
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban{
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban return (DDI_SUCCESS);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwstatic const char *nocopydevs[] = {
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw "SUNW,ffb",
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw "SUNW,afb",
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw NULL
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw};
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Perform a copy from a memory mapped device (whose devinfo pointer is devi)
8edda6281c84e0632a22f9c8dbf0d6f1558878ebbaban * separately mapped at devaddr in the kernel to a kernel buffer at kaddr.
8edda6281c84e0632a22f9c8dbf0d6f1558878ebbaban */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*ARGSUSED*/
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwint
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwe_ddi_copyfromdev(dev_info_t *devi,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw off_t off, const void *devaddr, void *kaddr, size_t len)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw{
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw const char **argv;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw for (argv = nocopydevs; *argv; argv++)
8e22821528b08c6dba4e8176351560f316f6d0dedm if (strcmp(ddi_binding_name(devi), *argv) == 0) {
8e22821528b08c6dba4e8176351560f316f6d0dedm bzero(kaddr, len);
8e22821528b08c6dba4e8176351560f316f6d0dedm return (0);
8e22821528b08c6dba4e8176351560f316f6d0dedm }
8e22821528b08c6dba4e8176351560f316f6d0dedm
8e22821528b08c6dba4e8176351560f316f6d0dedm bcopy(devaddr, kaddr, len);
8e22821528b08c6dba4e8176351560f316f6d0dedm return (0);
8e22821528b08c6dba4e8176351560f316f6d0dedm}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Perform a copy to a memory mapped device (whose devinfo pointer is devi)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * separately mapped at devaddr in the kernel from a kernel buffer at kaddr.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*ARGSUSED*/
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwint
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwe_ddi_copytodev(dev_info_t *devi,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw off_t off, const void *kaddr, void *devaddr, size_t len)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw{
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw const char **argv;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw for (argv = nocopydevs; *argv; argv++)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (strcmp(ddi_binding_name(devi), *argv) == 0)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (1);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw bcopy(kaddr, devaddr, len);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (0);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Boot Configuration
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwidprom_t idprom;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Configure the hardware on the system.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Called before the rootfs is mounted
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwvoid
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwconfigure(void)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw{
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw extern void i_ddi_init_root();
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /* We better have released boot by this time! */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ASSERT(!bootops);
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Determine whether or not to use the fpu, V9 SPARC cpus
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * always have one. Could check for existence of a fp queue,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Ultra I, II and IIa do not have a fp queue.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (fpu_exists)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw fpu_probe();
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw else
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw cmn_err(CE_CONT, "FPU not in use\n");
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw#if 0 /* XXXQ - not necessary for sun4u */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /*
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban * This following line fixes bugid 1041296; we need to do a
8edda6281c84e0632a22f9c8dbf0d6f1558878ebbaban * prom_nextnode(0) because this call ALSO patches the DMA+
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * bug in Campus-B and Phoenix. The prom uncaches the traptable
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * page as a side-effect of devr_next(0) (which prom_nextnode calls),
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * so this *must* be executed early on. (XXX This is untrue for sun4u)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw (void) prom_nextnode((pnode_t)0);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw#endif
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Initialize devices on the machine.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Uses configuration tree built by the PROMs to determine what
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * is present, and builds a tree of prototype dev_info nodes
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * corresponding to the hardware which identified itself.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw i_ddi_init_root();
62c6006265c37877b7a5b3c8ffce913ef559b955baban
62c6006265c37877b7a5b3c8ffce913ef559b955baban#ifdef DDI_PROP_DEBUG
62c6006265c37877b7a5b3c8ffce913ef559b955baban (void) ddi_prop_debug(1); /* Enable property debugging */
62c6006265c37877b7a5b3c8ffce913ef559b955baban#endif /* DDI_PROP_DEBUG */
62c6006265c37877b7a5b3c8ffce913ef559b955baban}
62c6006265c37877b7a5b3c8ffce913ef559b955baban
62c6006265c37877b7a5b3c8ffce913ef559b955baban/*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * The "status" property indicates the operational status of a device.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * If this property is present, the value is a string indicating the
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * status of the device as follows:
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw *
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * "okay" operational.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * "disabled" not operational, but might become operational.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * "fail" not operational because a fault has been detected,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * and it is unlikely that the device will become
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * operational without repair. no additional details
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * are available.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * "fail-xxx" not operational because a fault has been detected,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * and it is unlikely that the device will become
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * operational without repair. "xxx" is additional
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * human-readable information about the particular
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * fault condition that was detected.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw *
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * The absence of this property means that the operational status is
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * unknown or okay.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw *
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * This routine checks the status property of the specified device node
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * and returns 0 if the operational status indicates failure, and 1 otherwise.
9581d9f4f3b1515f88149f920c7e786b4fb901d4baban *
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * The property may exist on plug-in cards the existed before IEEE 1275-1994.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * And, in that case, the property may not even be a string. So we carefully
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * check for the value "fail", in the beginning of the string, noting
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * the property length.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwint
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwstatus_okay(int id, char *buf, int buflen)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw{
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw char status_buf[OBP_MAXPROPNAME];
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw char *bufp = buf;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw int len = buflen;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw int proplen;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw static const char *status = "status";
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw static const char *fail = "fail";
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw size_t fail_len = strlen(fail);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Get the proplen ... if it's smaller than "fail",
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * or doesn't exist ... then we don't care, since
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * the value can't begin with the char string "fail".
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw *
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * NB: proplen, if it's a string, includes the NULL in the
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * the size of the property, and fail_len does not.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw proplen = prom_getproplen((pnode_t)id, (caddr_t)status);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (proplen <= fail_len) /* nonexistent or uninteresting len */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (1);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * if a buffer was provided, use it
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if ((buf == (char *)NULL) || (buflen <= 0)) {
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw bufp = status_buf;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw len = sizeof (status_buf);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw }
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw *bufp = (char)0;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Get the property into the buffer, to the extent of the buffer,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * and in case the buffer is smaller than the property size,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * NULL terminate the buffer. (This handles the case where
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * a buffer was passed in and the caller wants to print the
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * value, but the buffer was too small).
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw (void) prom_bounded_getprop((pnode_t)id, (caddr_t)status,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw (caddr_t)bufp, len);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw *(bufp + len - 1) = (char)0;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * If the value begins with the char string "fail",
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * then it means the node is failed. We don't care
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * about any other values. We assume the node is ok
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * although it might be 'disabled'.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (strncmp(bufp, fail, fail_len) == 0)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (0);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (1);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw}
62c6006265c37877b7a5b3c8ffce913ef559b955baban
62c6006265c37877b7a5b3c8ffce913ef559b955baban
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * We set the cpu type from the idprom, if we can.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Note that we just read out the contents of it, for the most part.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwvoid
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwsetcputype(void)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw{
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * We cache the idprom info early on so that we don't
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * rummage through the NVRAM unnecessarily later.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw (void) prom_getidprom((caddr_t)&idprom, sizeof (idprom));
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw}
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Here is where we actually infer meanings to the members of idprom_t
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwvoid
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbabanparse_idprom(void)
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban{
8e22821528b08c6dba4e8176351560f316f6d0dedm if (idprom.id_format == IDFORM_1) {
c5a946bac9ff4ebd4d874e1c94d41a5ffcbad287baban (void) localetheraddr((struct ether_addr *)idprom.id_ether,
c5a946bac9ff4ebd4d874e1c94d41a5ffcbad287baban (struct ether_addr *)NULL);
c5a946bac9ff4ebd4d874e1c94d41a5ffcbad287baban (void) snprintf(hw_serial, HW_HOSTID_LEN, "%u",
8e22821528b08c6dba4e8176351560f316f6d0dedm (idprom.id_machine << 24) + idprom.id_serial);
8e22821528b08c6dba4e8176351560f316f6d0dedm } else
8e22821528b08c6dba4e8176351560f316f6d0dedm prom_printf("Invalid format code in IDprom.\n");
c5a946bac9ff4ebd4d874e1c94d41a5ffcbad287baban}
c5a946bac9ff4ebd4d874e1c94d41a5ffcbad287baban
c5a946bac9ff4ebd4d874e1c94d41a5ffcbad287baban/*
8e22821528b08c6dba4e8176351560f316f6d0dedm * Allow for implementation specific correction of PROM property values.
8e22821528b08c6dba4e8176351560f316f6d0dedm */
8e22821528b08c6dba4e8176351560f316f6d0dedm/*ARGSUSED*/
8e22821528b08c6dba4e8176351560f316f6d0dedmvoid
8e22821528b08c6dba4e8176351560f316f6d0dedmimpl_fix_props(dev_info_t *dip, dev_info_t *ch_dip, char *name, int len,
8e22821528b08c6dba4e8176351560f316f6d0dedm caddr_t buffer)
8e22821528b08c6dba4e8176351560f316f6d0dedm{
8e22821528b08c6dba4e8176351560f316f6d0dedm /*
8e22821528b08c6dba4e8176351560f316f6d0dedm * There are no adjustments needed in this implementation.
8e22821528b08c6dba4e8176351560f316f6d0dedm */
8e22821528b08c6dba4e8176351560f316f6d0dedm}
8e22821528b08c6dba4e8176351560f316f6d0dedm
8e22821528b08c6dba4e8176351560f316f6d0dedm/*
8e22821528b08c6dba4e8176351560f316f6d0dedm * The following functions ready a cautious request to go up to the nexus
8e22821528b08c6dba4e8176351560f316f6d0dedm * driver. It is up to the nexus driver to decide how to process the request.
8e22821528b08c6dba4e8176351560f316f6d0dedm * It may choose to call i_ddi_do_caut_get/put in this file, or do it
8e22821528b08c6dba4e8176351560f316f6d0dedm * differently.
8e22821528b08c6dba4e8176351560f316f6d0dedm */
8e22821528b08c6dba4e8176351560f316f6d0dedm
8e22821528b08c6dba4e8176351560f316f6d0dedmstatic void
8e22821528b08c6dba4e8176351560f316f6d0dedmi_ddi_caut_getput_ctlops(
8e22821528b08c6dba4e8176351560f316f6d0dedm ddi_acc_impl_t *hp, uint64_t host_addr, uint64_t dev_addr, size_t size,
8e22821528b08c6dba4e8176351560f316f6d0dedm size_t repcount, uint_t flags, ddi_ctl_enum_t cmd)
8e22821528b08c6dba4e8176351560f316f6d0dedm{
8e22821528b08c6dba4e8176351560f316f6d0dedm peekpoke_ctlops_t cautacc_ctlops_arg;
8e22821528b08c6dba4e8176351560f316f6d0dedm
8e22821528b08c6dba4e8176351560f316f6d0dedm cautacc_ctlops_arg.size = size;
8e22821528b08c6dba4e8176351560f316f6d0dedm cautacc_ctlops_arg.dev_addr = dev_addr;
8e22821528b08c6dba4e8176351560f316f6d0dedm cautacc_ctlops_arg.host_addr = host_addr;
8e22821528b08c6dba4e8176351560f316f6d0dedm cautacc_ctlops_arg.handle = (ddi_acc_handle_t)hp;
8e22821528b08c6dba4e8176351560f316f6d0dedm cautacc_ctlops_arg.repcount = repcount;
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban cautacc_ctlops_arg.flags = flags;
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban (void) ddi_ctlops(hp->ahi_common.ah_dip, hp->ahi_common.ah_dip, cmd,
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban &cautacc_ctlops_arg, NULL);
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban}
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbabanuint8_t
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbabani_ddi_caut_get8(ddi_acc_impl_t *hp, uint8_t *addr)
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban{
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban uint8_t value;
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr,
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban sizeof (uint8_t), 1, 0, DDI_CTLOPS_PEEK);
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban return (value);
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban}
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbabanuint16_t
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbabani_ddi_caut_get16(ddi_acc_impl_t *hp, uint16_t *addr)
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban{
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban uint16_t value;
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr,
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban sizeof (uint16_t), 1, 0, DDI_CTLOPS_PEEK);
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban return (value);
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban}
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbabanuint32_t
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbabani_ddi_caut_get32(ddi_acc_impl_t *hp, uint32_t *addr)
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban{
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban uint32_t value;
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr,
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban sizeof (uint32_t), 1, 0, DDI_CTLOPS_PEEK);
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban return (value);
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban}
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbabanuint64_t
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbabani_ddi_caut_get64(ddi_acc_impl_t *hp, uint64_t *addr)
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban{
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban uint64_t value;
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr,
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban sizeof (uint64_t), 1, 0, DDI_CTLOPS_PEEK);
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban return (value);
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban}
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbabanvoid
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbabani_ddi_caut_put8(ddi_acc_impl_t *hp, uint8_t *addr, uint8_t value)
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban{
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr,
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban sizeof (uint8_t), 1, 0, DDI_CTLOPS_POKE);
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban}
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbabanvoid
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbabani_ddi_caut_put16(ddi_acc_impl_t *hp, uint16_t *addr, uint16_t value)
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban{
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr,
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban sizeof (uint16_t), 1, 0, DDI_CTLOPS_POKE);
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban}
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbabanvoid
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbabani_ddi_caut_put32(ddi_acc_impl_t *hp, uint32_t *addr, uint32_t value)
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban{
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr,
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban sizeof (uint32_t), 1, 0, DDI_CTLOPS_POKE);
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban}
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbabanvoid
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbabani_ddi_caut_put64(ddi_acc_impl_t *hp, uint64_t *addr, uint64_t value)
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban{
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr,
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban sizeof (uint64_t), 1, 0, DDI_CTLOPS_POKE);
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban}
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbabanvoid
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbabani_ddi_caut_rep_get8(ddi_acc_impl_t *hp, uint8_t *host_addr, uint8_t *dev_addr,
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban size_t repcount, uint_t flags)
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban{
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban i_ddi_caut_getput_ctlops(hp, (uint64_t)host_addr, (uint64_t)dev_addr,
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban sizeof (uint8_t), repcount, flags, DDI_CTLOPS_PEEK);
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban}
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbabanvoid
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbabani_ddi_caut_rep_get16(ddi_acc_impl_t *hp, uint16_t *host_addr,
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban uint16_t *dev_addr, size_t repcount, uint_t flags)
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban{
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban i_ddi_caut_getput_ctlops(hp, (uint64_t)host_addr, (uint64_t)dev_addr,
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban sizeof (uint16_t), repcount, flags, DDI_CTLOPS_PEEK);
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban}
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbabanvoid
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbabani_ddi_caut_rep_get32(ddi_acc_impl_t *hp, uint32_t *host_addr,
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban uint32_t *dev_addr, size_t repcount, uint_t flags)
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban{
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban i_ddi_caut_getput_ctlops(hp, (uint64_t)host_addr, (uint64_t)dev_addr,
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban sizeof (uint32_t), repcount, flags, DDI_CTLOPS_PEEK);
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban}
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbabanvoid
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbabani_ddi_caut_rep_get64(ddi_acc_impl_t *hp, uint64_t *host_addr,
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban uint64_t *dev_addr, size_t repcount, uint_t flags)
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban{
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban i_ddi_caut_getput_ctlops(hp, (uint64_t)host_addr, (uint64_t)dev_addr,
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban sizeof (uint64_t), repcount, flags, DDI_CTLOPS_PEEK);
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban}
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbabanvoid
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbabani_ddi_caut_rep_put8(ddi_acc_impl_t *hp, uint8_t *host_addr, uint8_t *dev_addr,
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban size_t repcount, uint_t flags)
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban{
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban i_ddi_caut_getput_ctlops(hp, (uint64_t)host_addr, (uint64_t)dev_addr,
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban sizeof (uint8_t), repcount, flags, DDI_CTLOPS_POKE);
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban}
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbabanvoid
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbabani_ddi_caut_rep_put16(ddi_acc_impl_t *hp, uint16_t *host_addr,
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban uint16_t *dev_addr, size_t repcount, uint_t flags)
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban{
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban i_ddi_caut_getput_ctlops(hp, (uint64_t)host_addr, (uint64_t)dev_addr,
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban sizeof (uint16_t), repcount, flags, DDI_CTLOPS_POKE);
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban}
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbabanvoid
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbabani_ddi_caut_rep_put32(ddi_acc_impl_t *hp, uint32_t *host_addr,
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban uint32_t *dev_addr, size_t repcount, uint_t flags)
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban{
i_ddi_caut_getput_ctlops(hp, (uint64_t)host_addr, (uint64_t)dev_addr,
sizeof (uint32_t), repcount, flags, DDI_CTLOPS_POKE);
}
void
i_ddi_caut_rep_put64(ddi_acc_impl_t *hp, uint64_t *host_addr,
uint64_t *dev_addr, size_t repcount, uint_t flags)
{
i_ddi_caut_getput_ctlops(hp, (uint64_t)host_addr, (uint64_t)dev_addr,
sizeof (uint64_t), repcount, flags, DDI_CTLOPS_POKE);
}
/*
* This is called only to process peek/poke when the DIP is NULL.
* Assume that this is for memory, as nexi take care of device safe accesses.
*/
int
peekpoke_mem(ddi_ctl_enum_t cmd, peekpoke_ctlops_t *in_args)
{
int err = DDI_SUCCESS;
on_trap_data_t otd;
/* Set up protected environment. */
if (!on_trap(&otd, OT_DATA_ACCESS)) {
uintptr_t tramp = otd.ot_trampoline;
if (cmd == DDI_CTLOPS_POKE) {
otd.ot_trampoline = (uintptr_t)&poke_fault;
err = do_poke(in_args->size, (void *)in_args->dev_addr,
(void *)in_args->host_addr);
} else {
otd.ot_trampoline = (uintptr_t)&peek_fault;
err = do_peek(in_args->size, (void *)in_args->dev_addr,
(void *)in_args->host_addr);
}
otd.ot_trampoline = tramp;
} else
err = DDI_FAILURE;
/* Take down protected environment. */
no_trap();
return (err);
}