ddi_impl.c revision 15e1afcd5e908ae29b1e6018838638befdc225a2
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * CDDL HEADER START
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 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * See the License for the specific language governing permissions
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * and limitations under the License.
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 * CDDL HEADER END
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Use is subject to license terms.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * sun4 specific DDI implementation
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwint process_intr_ops(dev_info_t *, dev_info_t *, ddi_intr_op_t,
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 * 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.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwget_prop_int_array(dev_info_t *di, char *pname, int **pval, uint_t *plen)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw DDI_PROP_DONTPASS, pname, pval, plen)) == DDI_PROP_SUCCESS) {
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * SECTION: DDI Node Configuration
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * init_regspec_64:
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 * If there are no "reg"s in the child node, return.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (pd);
d3a612ca42c17c3baa6c96ded00f98db349cc881nw * We already looked the property up once before if
d3a612ca42c17c3baa6c96ded00f98db349cc881nw * pd is non-NULL.
d3a612ca42c17c3baa6c96ded00f98db349cc881nw n = sizeof (struct reg_64) / sizeof (int);
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.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (pd);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Create a ddi_parent_private_data structure from the ddi properties of
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * the dev_info node.
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 * <bustype, address, size>*1
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 * The "ranges" property describes the mapping of child addresses to parent
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * addresses.
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.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwmake_ddi_ppd(dev_info_t *child, struct ddi_parent_private_data **ppd)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * root node has no parent private data, so *ppd should
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * be initialized for naming to work properly.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Set reg field of parent data from "reg" property
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if ((get_prop_int_array(child, OBP_REG, ®_prop, ®_len)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw pdptr->par_nreg = (int)(reg_len / sizeof (struct regspec));
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * "ranges" property ...
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * This function does not handle cases where #address-cells != 2
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * and * min(parent, child) #size-cells != 1 (see bugid 4211124).
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 /* root node has no ranges */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw child_addr_cells = ddi_prop_get_int(DDI_DEV_T_ANY, child,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw child_size_cells = ddi_prop_get_int(DDI_DEV_T_ANY, child,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw parent_addr_cells = ddi_prop_get_int(DDI_DEV_T_ANY, parent,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw parent_size_cells = ddi_prop_get_int(DDI_DEV_T_ANY, parent,
8e22821528b08c6dba4e8176351560f316f6d0dedm NDI_CONFIG_DEBUG((CE_NOTE, "!ranges not made in parent data; "
8e22821528b08c6dba4e8176351560f316f6d0dedm "#address-cells or #size-cells have non-default value"));
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (get_prop_int_array(child, OBP_RANGES, &rng_prop, &rng_len)
8e22821528b08c6dba4e8176351560f316f6d0dedm pdptr->par_nrng = rng_len / (int)(sizeof (struct rangespec));
8e22821528b08c6dba4e8176351560f316f6d0dedm * Free ddi_parent_private_data structure
8e22821528b08c6dba4e8176351560f316f6d0dedm struct ddi_parent_private_data *pdptr = ddi_get_parent_data(dip);
8e22821528b08c6dba4e8176351560f316f6d0dedm * Name a child of sun busses based on the reg spec.
8e22821528b08c6dba4e8176351560f316f6d0dedm * Handles the following properties:
8e22821528b08c6dba4e8176351560f316f6d0dedm * Property value
8e22821528b08c6dba4e8176351560f316f6d0dedm * Name type
8e22821528b08c6dba4e8176351560f316f6d0dedm * reg register spec
8e22821528b08c6dba4e8176351560f316f6d0dedm * interrupts new (bus-oriented) interrupt spec
8e22821528b08c6dba4e8176351560f316f6d0dedm * ranges range spec
8e22821528b08c6dba4e8176351560f316f6d0dedm * This may be called multiple times, independent of
8e22821528b08c6dba4e8176351560f316f6d0dedm * initchild calls.
651c0131ccc65381cbda174bee44a4fd7a518d6bbabanimpl_sunbus_name_child(dev_info_t *child, char *name, int namelen)
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 * No reg property, return null string as address
8e22821528b08c6dba4e8176351560f316f6d0dedm * (e.g. root node)
8e22821528b08c6dba4e8176351560f316f6d0dedm * Called from the bus_ctl op of some drivers.
8e22821528b08c6dba4e8176351560f316f6d0dedm * to implement the DDI_CTLOPS_INITCHILD operation.
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 * Try to merge .conf node. If successful, return failure to
8e22821528b08c6dba4e8176351560f316f6d0dedm * remove this child.
8e22821528b08c6dba4e8176351560f316f6d0dedm (ndi_merge_node(child, impl_sunbus_name_child) == DDI_SUCCESS)) {
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 * Strip the node to properly convert it back to prototype form
8e22821528b08c6dba4e8176351560f316f6d0dedm * SECTION: DDI Interrupt
8e22821528b08c6dba4e8176351560f316f6d0dedmcells_1275_copy(prop_1275_cell_t *from, prop_1275_cell_t *to, int32_t len)
8e22821528b08c6dba4e8176351560f316f6d0dedm for (i = 0; i < len; i++)
8e22821528b08c6dba4e8176351560f316f6d0dedmcells_1275_cmp(prop_1275_cell_t *cell1, prop_1275_cell_t *cell2, int32_t len)
8e22821528b08c6dba4e8176351560f316f6d0dedm for (i = 0; i < len; i++)
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 * 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 * 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
8e22821528b08c6dba4e8176351560f316f6d0dedmget_intr_parent(dev_info_t *pdip, dev_info_t *dip, ddi_intr_handle_impl_t *hdlp)
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 static int debug = 0;
8e22821528b08c6dba4e8176351560f316f6d0dedm * If we have an interrupt-parent property, this property represents
8e22821528b08c6dba4e8176351560f316f6d0dedm * the nodeid of our interrupt parent.
8e22821528b08c6dba4e8176351560f316f6d0dedm * Attach the interrupt parent.
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 * Get interrupt map structure from PROM property
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (ddi_getlongprop(DDI_DEV_T_ANY, pdip, DDI_PROP_DONTPASS,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * If we don't have an imap property, default to using the
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * device tree.
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 * If we don't find this property, we have to fail the request
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * because the 1275 imap property wasn't defined correctly.
8e22821528b08c6dba4e8176351560f316f6d0dedm /* Get the address cell size */
8e22821528b08c6dba4e8176351560f316f6d0dedm /* Get the interrupts cell size */
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 if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "reg",
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw for (i = 0; i < addr_cells; i++)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw for (j = 0; j < intr_cells; i++, j++)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /* Calculate the imap size in cells */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw "match_request 0x%p, imap 0x%p\n", addr_cells, intr_cells,
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 imap_scan_cells < imap_cells; scan += i, imap_scan_cells += i) {
8e22821528b08c6dba4e8176351560f316f6d0dedm /* Set the index to the nodeid field */
8e22821528b08c6dba4e8176351560f316f6d0dedm * Translate the nodeid field to a dip
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw intr_parent_dip = e_ddi_nodeid_to_dip((uint_t)scan[i++]);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * The tmp_dip describes the new domain, get it's interrupt
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * cell size
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw new_intr_cells = ddi_getprop(DDI_DEV_T_ANY, intr_parent_dip, 0,
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban * See if we have a match on the interrupt unit specifier
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (cells_1275_cmp(match_req, scan, addr_cells + intr_cells)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * If we have an imap parent whose not in our device
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * tree path, we need to hold and install that driver.
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 /* Extract the translated interrupt information */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw for (j = 0; j < new_intr_cells; j++, i++)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * If we haven't found our interrupt parent at this point, fallback
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * to using the device tree.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * process_intr_ops:
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Process the interrupt op via the interrupt parent.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwprocess_intr_ops(dev_info_t *pdip, dev_info_t *rdip, ddi_intr_op_t op,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw "for %s%d due to down-rev nexus driver %s%d",
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*ARGSUSED*/
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (1);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * indirection table, to save us some large switch statements
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * NOTE: This must agree with "INTLEVEL_foo" constants in
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * This value is exported here for the functions in avintr.c
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwconst uint_t maxautovec = (sizeof (vectorlist) / sizeof (vectorlist[0]));
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Check for machine specific interrupt levels which cannot be reassigned by
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * settrap(), sun4u version.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * sun4u does not support V8 SPARC "fast trap" handlers.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*ARGSUSED*/
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (1);
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/*ARGSUSED*/
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Wrapper functions used by New DDI interrupt framework.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * i_ddi_intr_ops:
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwi_ddi_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t op,
8e22821528b08c6dba4e8176351560f316f6d0dedm * The following check is required to address
8e22821528b08c6dba4e8176351560f316f6d0dedm * one of the test case of ADDI test suite.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw switch (op) {
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Try and determine our parent and possibly an interrupt
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * translation. intr parent dip returned held
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw switch (op) {
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /* Release hold acquired in get_intr_parent() */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * i_ddi_add_ivintr:
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*ARGSUSED*/
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * If the PIL was set and is valid use it, otherwise
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * default it to 1
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * i_ddi_rem_ivintr:
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*ARGSUSED*/
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.
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS |
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /* adjust for number of bytes */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /* Calculate the number of interrupts */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /* Index into interrupt property */
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 * Use the "interrupt-priorities" property to determine the
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * the pil/ipl for the interrupt handler.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
8e22821528b08c6dba4e8176351560f316f6d0dedm if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS |
8e22821528b08c6dba4e8176351560f316f6d0dedm /* adjust for number of bytes */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * i_ddi_add_softint - allocate and add a software interrupt.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * NOTE: All software interrupts that are registered through DDI
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * should be triggered only on a single target or CPU.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if ((hdlp->ih_private = (void *)add_softintr(hdlp->ih_pri,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw hdlp->ih_cb_func, hdlp->ih_cb_arg1, SOFTINT_ST)) == NULL)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * i_ddi_remove_softint - remove and free a software interrupt.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * i_ddi_trigger_softint - trigger a software interrupt.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwi_ddi_trigger_softint(ddi_softint_hdl_impl_t *hdlp, void *arg2)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /* Update the second argument for the software interrupt */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if ((ret = update_softint_arg2((uint64_t)hdlp->ih_private, arg2)) == 0)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * i_ddi_set_softint_pri - change software interrupt priority.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/* ARGSUSED */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwi_ddi_set_softint_pri(ddi_softint_hdl_impl_t *hdlp, uint_t old_pri)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /* Update the interrupt priority for the software interrupt */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ret = update_softint_pri((uint64_t)hdlp->ih_private, hdlp->ih_pri);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*ARGSUSED*/
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*ARGSUSED*/
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * SECTION: DDI Memory/DMA
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/* set HAT endianess attributes from ddi_device_acc_attr */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwi_ddi_devacc_to_hatacc(ddi_device_acc_attr_t *devaccp, uint_t *hataccp)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (devaccp->devacc_attr_endian_flags == DDI_STRUCTURE_LE_ACC) {
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 * The cache attributes are mutually exclusive. Any combination of
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * the attributes leads to a failure.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if ((cache_attr != 0) && ((cache_attr & (cache_attr - 1)) != 0))
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * On the sparc architecture, only IOMEM_DATA_CACHED is meaningful,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * but others lead to a failure.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/* set HAT cache attributes from the cache attributes */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw#if defined(lint)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * set HAT attrs according to the cache attrs.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * The cache coherency is always maintained on SPARC, and
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * nothing is required.
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.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwstatic void *
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (segkmem_xalloc(vmp, NULL, size, flag, HAT_STRUCTURE_LE,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwstatic void *
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (segkmem_xalloc(vmp, NULL, size, flag, HAT_STRUCTURE_BE,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw little_endian_arena = vmem_create("little_endian", NULL, 0, 1,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw segkmem_alloc_le, segkmem_free, heap_arena, 0, VM_SLEEP);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw segkmem_alloc_be, segkmem_free, heap_arena, 0, VM_SLEEP);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Allocate from the system, aligned on a specific boundary.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * The alignment, if non-zero, must be a power of 2.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwstatic void *
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwkalloca(size_t size, size_t align, int cansleep, uint_t endian_flags)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw size_t hdrsize = 4 * sizeof (size_t); /* must be power of 2 */
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.
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 addr = (size_t *)P2ROUNDUP((uintptr_t)raddr + hdrsize, align);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ASSERT((uintptr_t)addr + size - (uintptr_t)raddr <= rsize);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwstatic void
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw vmem_free(little_endian_arena, (void *)saddr[-2], saddr[-1]);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw vmem_free(big_endian_arena, (void *)saddr[-2], saddr[-1]);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw caddr_t *kaddrp, size_t *real_length, ddi_acc_hdl_t *handlep)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw#if defined(lint)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Check legality of arguments
651c0131ccc65381cbda174bee44a4fd7a518d6bbaban if (attr->dma_attr_minxfer == 0 || attr->dma_attr_align == 0 ||
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw (attr->dma_attr_minxfer & (attr->dma_attr_minxfer - 1))) {
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * check if a streaming sequential xfer is requested.
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 * If a driver set burtsizes to 0, we give him byte alignment.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Otherwise align at the burtsizes boundary.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if ((*kaddrp = a) == 0) {
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * assign handle information
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * covert old DMA limits structure to DMA attribute structure
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * and continue
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwi_ddi_mem_alloc_lim(dev_info_t *dip, ddi_dma_lim_t *limits,
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_burstsizes = (uint_t)limits->dlim_burstsizes;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw attrp->dma_attr_minxfer = (uint32_t)limits->dlim_minxfer;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw ret = i_ddi_mem_alloc(dip, attrp, length, cansleep, streaming,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/* ARGSUSED */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * SECTION: DDI Data Access
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * access handle allocator
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Extract the access handle address from the DDI implemented
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * access handle
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw sleepflag = ((waitfp == (int (*)())KM_SLEEP) ? KM_SLEEP : KM_NOSLEEP);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Allocate and initialize the data access handle and error status.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if ((hp = kmem_zalloc(sizeof (ddi_acc_impl_t), sleepflag)) == NULL)
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.
62c6006265c37877b7a5b3c8ffce913ef559b955baban kmem_free(hp->ahi_err->err_ontrap, sizeof (on_trap_data_t));
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]))
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/* ARGSUSED */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwimpl_dma_check(dev_info_t *dip, const void *handle, const void *addr,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw const void *not_used)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * The driver has to set DDI_DMA_FLAGERR to recover from dma faults.
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/* ARGSUSED */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwimpl_acc_check(dev_info_t *dip, const void *handle, const void *addr,
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw const void *not_used)
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (handlep->ah_acc.devacc_attr_version < DDI_DEVICE_ATTR_V1 ||
62c6006265c37877b7a5b3c8ffce913ef559b955baban if (handlep->ah_acc.devacc_attr_access == DDI_DEFAULT_ACC) {
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * check for SW byte-swapping
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (handlep->ah_acc.devacc_attr_endian_flags & DDI_STRUCTURE_LE_ACC) {
8e22821528b08c6dba4e8176351560f316f6d0dedm /* Legacy fault flags and support */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/* ARGSUSED */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /* Default version, does nothing */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * SECTION: Misc functions
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * instance wrappers
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*ARGSUSED*/
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*ARGSUSED*/
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*ARGSUSED*/
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*ARGSUSED*/
c5c4113dfcabb1eed3d4bdf7609de5170027a794nwstatic const char *nocopydevs[] = {
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw "SUNW,ffb",
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw "SUNW,afb",
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.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw/*ARGSUSED*/
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw const char **argv;
8e22821528b08c6dba4e8176351560f316f6d0dedm return (0);
8e22821528b08c6dba4e8176351560f316f6d0dedm return (0);
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/*ARGSUSED*/
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw const char **argv;
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (1);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (0);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Boot Configuration
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Configure the hardware on the system.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Called before the rootfs is mounted
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw extern void i_ddi_init_root();
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw /* We better have released boot by this time! */
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#if 0 /* XXXQ - not necessary for sun4u */
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 * 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.
62c6006265c37877b7a5b3c8ffce913ef559b955baban (void) ddi_prop_debug(1); /* Enable property debugging */
62c6006265c37877b7a5b3c8ffce913ef559b955baban#endif /* DDI_PROP_DEBUG */
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 * "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 * The absence of this property means that the operational status is
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * unknown or okay.
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.
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 * 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 * NB: proplen, if it's a string, includes the NULL in the
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * the size of the property, and fail_len does not.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw if (proplen <= fail_len) /* nonexistent or uninteresting len */
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (1);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * if a buffer was provided, use it
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw *bufp = (char)0;
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 (void) prom_bounded_getprop((pnode_t)id, (caddr_t)status,
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 return (0);
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw return (1);
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 * We cache the idprom info early on so that we don't
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * rummage through the NVRAM unnecessarily later.
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw (void) prom_getidprom((caddr_t)&idprom, sizeof (idprom));
c5c4113dfcabb1eed3d4bdf7609de5170027a794nw * Here is where we actually infer meanings to the members of idprom_t
c5a946bac9ff4ebd4d874e1c94d41a5ffcbad287baban (void) localetheraddr((struct ether_addr *)idprom.id_ether,
8e22821528b08c6dba4e8176351560f316f6d0dedm * Allow for implementation specific correction of PROM property values.
8e22821528b08c6dba4e8176351560f316f6d0dedm/*ARGSUSED*/
8e22821528b08c6dba4e8176351560f316f6d0dedmimpl_fix_props(dev_info_t *dip, dev_info_t *ch_dip, char *name, int len,
8e22821528b08c6dba4e8176351560f316f6d0dedm * There are no adjustments needed in this implementation.
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.
8e22821528b08c6dba4e8176351560f316f6d0dedmstatic void
8e22821528b08c6dba4e8176351560f316f6d0dedm ddi_acc_impl_t *hp, uint64_t host_addr, uint64_t dev_addr, size_t size,
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban (void) ddi_ctlops(hp->ahi_common.ah_dip, hp->ahi_common.ah_dip, cmd,
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr,
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr,
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr,
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr,
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbabani_ddi_caut_put8(ddi_acc_impl_t *hp, uint8_t *addr, uint8_t value)
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr,
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbabani_ddi_caut_put16(ddi_acc_impl_t *hp, uint16_t *addr, uint16_t value)
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr,
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbabani_ddi_caut_put32(ddi_acc_impl_t *hp, uint32_t *addr, uint32_t value)
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr,
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbabani_ddi_caut_put64(ddi_acc_impl_t *hp, uint64_t *addr, uint64_t value)
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr,
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbabani_ddi_caut_rep_get8(ddi_acc_impl_t *hp, uint8_t *host_addr, uint8_t *dev_addr,
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban i_ddi_caut_getput_ctlops(hp, (uint64_t)host_addr, (uint64_t)dev_addr,
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbabani_ddi_caut_rep_get16(ddi_acc_impl_t *hp, uint16_t *host_addr,
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban i_ddi_caut_getput_ctlops(hp, (uint64_t)host_addr, (uint64_t)dev_addr,
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbabani_ddi_caut_rep_get32(ddi_acc_impl_t *hp, uint32_t *host_addr,
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban i_ddi_caut_getput_ctlops(hp, (uint64_t)host_addr, (uint64_t)dev_addr,
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbabani_ddi_caut_rep_get64(ddi_acc_impl_t *hp, uint64_t *host_addr,
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban i_ddi_caut_getput_ctlops(hp, (uint64_t)host_addr, (uint64_t)dev_addr,
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbabani_ddi_caut_rep_put8(ddi_acc_impl_t *hp, uint8_t *host_addr, uint8_t *dev_addr,
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban i_ddi_caut_getput_ctlops(hp, (uint64_t)host_addr, (uint64_t)dev_addr,
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbabani_ddi_caut_rep_put16(ddi_acc_impl_t *hp, uint16_t *host_addr,
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbaban i_ddi_caut_getput_ctlops(hp, (uint64_t)host_addr, (uint64_t)dev_addr,
dd5829d1456ba00e6f704e6a88e7eaae608e3c1bbabani_ddi_caut_rep_put32(ddi_acc_impl_t *hp, uint32_t *host_addr,
no_trap();
return (err);