4496171313bed39e96f21bc2f9faf2868e267ae3girish * CDDL HEADER START
4496171313bed39e96f21bc2f9faf2868e267ae3girish * The contents of this file are subject to the terms of the
4496171313bed39e96f21bc2f9faf2868e267ae3girish * Common Development and Distribution License (the "License").
4496171313bed39e96f21bc2f9faf2868e267ae3girish * You may not use this file except in compliance with the License.
4496171313bed39e96f21bc2f9faf2868e267ae3girish * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
4496171313bed39e96f21bc2f9faf2868e267ae3girish * See the License for the specific language governing permissions
4496171313bed39e96f21bc2f9faf2868e267ae3girish * and limitations under the License.
4496171313bed39e96f21bc2f9faf2868e267ae3girish * When distributing Covered Code, include this CDDL HEADER in each
4496171313bed39e96f21bc2f9faf2868e267ae3girish * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
4496171313bed39e96f21bc2f9faf2868e267ae3girish * If applicable, add the following below this CDDL HEADER, with the
4496171313bed39e96f21bc2f9faf2868e267ae3girish * fields enclosed by brackets "[]" replaced with your own identifying
4496171313bed39e96f21bc2f9faf2868e267ae3girish * information: Portions Copyright [yyyy] [name of copyright owner]
4496171313bed39e96f21bc2f9faf2868e267ae3girish * CDDL HEADER END
657f87de670449e1422db4f51fb2880a7cb69d5agongtian zhao - Sun Microsystems - Beijing China * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
4496171313bed39e96f21bc2f9faf2868e267ae3girish * Niagara2 Network Interface Unit (NIU) Nexus Driver
8fca05700b4a8225bddecd0ca5028f512f483b36jfstatic int niumx_fm_init_child(dev_info_t *, dev_info_t *, int,
4496171313bed39e96f21bc2f9faf2868e267ae3girishstatic int niumx_intr_ops(dev_info_t *dip, dev_info_t *rdip,
4496171313bed39e96f21bc2f9faf2868e267ae3girish ddi_intr_op_t intr_op, ddi_intr_handle_impl_t *hdlp, void *result);
4496171313bed39e96f21bc2f9faf2868e267ae3girishstatic int niumx_attach(dev_info_t *devi, ddi_attach_cmd_t cmd);
4496171313bed39e96f21bc2f9faf2868e267ae3girishstatic int niumx_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
4496171313bed39e96f21bc2f9faf2868e267ae3girishstatic int niumx_set_intr(dev_info_t *dip, dev_info_t *rdip,
4496171313bed39e96f21bc2f9faf2868e267ae3girishstatic int niumx_add_intr(dev_info_t *dip, dev_info_t *rdip,
4496171313bed39e96f21bc2f9faf2868e267ae3girishstatic int niumx_rem_intr(dev_info_t *dip, dev_info_t *rdip,
4496171313bed39e96f21bc2f9faf2868e267ae3girishstatic int niumx_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
4496171313bed39e96f21bc2f9faf2868e267ae3girishstatic int niumx_dma_allochdl(dev_info_t *dip, dev_info_t *rdip,
4496171313bed39e96f21bc2f9faf2868e267ae3girish int (*waitfp)(caddr_t), caddr_t arg, ddi_dma_handle_t *handlep);
4496171313bed39e96f21bc2f9faf2868e267ae3girishstatic int niumx_dma_freehdl(dev_info_t *dip, dev_info_t *rdip,
4496171313bed39e96f21bc2f9faf2868e267ae3girishstatic int niumx_dma_bindhdl(dev_info_t *dip, dev_info_t *rdip,
4496171313bed39e96f21bc2f9faf2868e267ae3girishstatic int niumx_dma_unbindhdl(dev_info_t *dip, dev_info_t *rdip,
4496171313bed39e96f21bc2f9faf2868e267ae3girishstatic int niumx_ctlops(dev_info_t *dip, dev_info_t *rdip,
2de7adab54f9f3d152089a7ff5d6bfad81008231Alan Adamson, SD OSSDvoid niumxtool_uninit(dev_info_t *dip);
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSDint niumx_get_intr_target(niumx_devstate_t *niumxds_p, niudevino_t ino,
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSDint niumx_set_intr_target(niumx_devstate_t *niumxds_p, niudevino_t ino,
4496171313bed39e96f21bc2f9faf2868e267ae3girish 0, /* (*bus_get_eventcookie)(); */
4496171313bed39e96f21bc2f9faf2868e267ae3girish 0, /* (*bus_add_eventcall)(); */
4496171313bed39e96f21bc2f9faf2868e267ae3girish 0, /* (*bus_remove_eventcall)(); */
4496171313bed39e96f21bc2f9faf2868e267ae3girish 0, /* (*bus_post_event)(); */
4496171313bed39e96f21bc2f9faf2868e267ae3girish 0, /* (*bus_intr_ctl)(); */
4496171313bed39e96f21bc2f9faf2868e267ae3girish 0, /* (*bus_config)(); */
4496171313bed39e96f21bc2f9faf2868e267ae3girish 0, /* (*bus_unconfig)(); */
4496171313bed39e96f21bc2f9faf2868e267ae3girish 0, /* (*bus_fm_fini)(); */
4496171313bed39e96f21bc2f9faf2868e267ae3girish 0, /* (*bus_enter)() */
4496171313bed39e96f21bc2f9faf2868e267ae3girish 0, /* (*bus_exit)() */
4496171313bed39e96f21bc2f9faf2868e267ae3girish 0, /* (*bus_power)() */
4496171313bed39e96f21bc2f9faf2868e267ae3girish 0, /* refcnt */
4496171313bed39e96f21bc2f9faf2868e267ae3girish 0, /* probe */
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD &niumx_cb_ops, /* driver operations */
193974072f41a843678abf5f61979c748687e66bSherry Moore 0, /* power */
4496171313bed39e96f21bc2f9faf2868e267ae3girish/* Module linkage information for the kernel. */
193974072f41a843678abf5f61979c748687e66bSherry Moore "NIU Nexus Driver",
4496171313bed39e96f21bc2f9faf2868e267ae3girish * forward function declarations:
d66f83158d97c12b2a78b9363a07d9d365762606jb * Check HV intr group api versioning.
d66f83158d97c12b2a78b9363a07d9d365762606jb * This driver uses the old interrupt routines which are supported
d66f83158d97c12b2a78b9363a07d9d365762606jb * in old firmware in the CORE API group and in newer firmware in
d66f83158d97c12b2a78b9363a07d9d365762606jb * the INTR API group. Support for these calls will be dropped
d66f83158d97c12b2a78b9363a07d9d365762606jb * once the INTR API group major goes to 2.
d66f83158d97c12b2a78b9363a07d9d365762606jb if ((hsvc_version(HSVC_GROUP_INTR, &mjrnum, &mnrnum) == 0) &&
4496171313bed39e96f21bc2f9faf2868e267ae3girish if ((e = ddi_soft_state_init(&niumx_state, sizeof (niumx_devstate_t),
4496171313bed39e96f21bc2f9faf2868e267ae3girish return (e);
4496171313bed39e96f21bc2f9faf2868e267ae3girish return (e);
c165966d2681754edbe7637da5adf3e53b3f7132jfhrtime_t niumx_intr_timeout = 2ull * NANOSEC; /* 2 seconds in nanoseconds */
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu niumx_devstate_t *niumxds_p = (niumx_devstate_t *)arg;
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD DBG(NIUMX_DBG_A_INTX, NULL, "niumx_intr_dist entered\n");
e778ae4497a8de30b58b85bd187bf4ef4ba8cd47Raghuram Kothakota for (i = 0; i < NIUMX_MAX_INTRS; i++, ih_p++) {
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD if (!sysino || (cpuid = intr_dist_cpuid()) == ih_p->ih_cpuid)
c165966d2681754edbe7637da5adf3e53b3f7132jf /* check for pending interrupts, busy wait if so */
c165966d2681754edbe7637da5adf3e53b3f7132jf "pending interrupt (%x,%lx) timedout\n",
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD (void) hvio_intr_setvalid(sysino, HV_INTR_VALID);
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD (void) hvio_intr_setvalid(sysino, HV_INTR_NOTVALID);
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD DBG(NIUMX_DBG_ATTACH, dip, "reg lookup failed\n");
4496171313bed39e96f21bc2f9faf2868e267ae3girish * Allocate and get soft state structure.
4496171313bed39e96f21bc2f9faf2868e267ae3girish niumxds_p = (niumx_devstate_t *)ddi_get_soft_state(niumx_state,
4496171313bed39e96f21bc2f9faf2868e267ae3girish mutex_init(&niumxds_p->niumx_mutex, NULL, MUTEX_DRIVER, NULL);
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD DBG(NIUMX_DBG_ATTACH, dip, "soft state alloc'd instance = %d, "
4496171313bed39e96f21bc2f9faf2868e267ae3girish /* hv devhdl: low 28-bit of 1st "reg" entry's addr.hi */
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD niumxds_p->niumx_dev_hdl = (niudevhandle_t)(reg_p->addr_high &
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD for (i = 0; i < NIUMX_MAX_INTRS; i++, ih_p++) {
3266dff7c77b314b33c74fa8767437ffad5f4a01jf /* add interrupt redistribution callback */
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD if (niumxtool_init(dip) != DDI_SUCCESS) {
4496171313bed39e96f21bc2f9faf2868e267ae3girish ddi_soft_state_free(niumx_state, ddi_get_instance(dip));
4496171313bed39e96f21bc2f9faf2868e267ae3girish ddi_get_soft_state(niumx_state, ddi_get_instance(dip));
4496171313bed39e96f21bc2f9faf2868e267ae3girish ddi_soft_state_free(niumx_state, ddi_get_instance(dip));
8fca05700b4a8225bddecd0ca5028f512f483b36jf * Function used to initialize FMA for our children nodes. Called
8fca05700b4a8225bddecd0ca5028f512f483b36jf * through pci busops when child node calls ddi_fm_init.
8fca05700b4a8225bddecd0ca5028f512f483b36jf/*ARGSUSED*/
8fca05700b4a8225bddecd0ca5028f512f483b36jfniumx_fm_init_child(dev_info_t *dip, dev_info_t *cdip, int cap,
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD niumx_devstate_t *niumxds_p = NIUMX_DIP_TO_STATE(dip);
4496171313bed39e96f21bc2f9faf2868e267ae3girish/*ARGSUSED*/
4496171313bed39e96f21bc2f9faf2868e267ae3girishniumx_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
4496171313bed39e96f21bc2f9faf2868e267ae3girish int i, rn = mp->map_obj.rnumber, reglen, rnglen, rngnum, ret;
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD DBG(NIUMX_DBG_MAP, dip, "%s%d: mapping %s%d reg %d\n",
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD NIUMX_NAMEINST(dip), NIUMX_NAMEINST(rdip), rn);
4496171313bed39e96f21bc2f9faf2868e267ae3girish if (ddi_getlongprop(DDI_DEV_T_ANY, rdip, DDI_PROP_DONTPASS,
4496171313bed39e96f21bc2f9faf2868e267ae3girish if (rn < 0 || (rn >= reglen / sizeof (niu_regspec_t))) {
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD DBG(NIUMX_DBG_MAP, dip, "rnumber out of range: %d\n", rn);
4496171313bed39e96f21bc2f9faf2868e267ae3girish /* build regspec up for parent */
4496171313bed39e96f21bc2f9faf2868e267ae3girish if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "ranges",
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD DBG(NIUMX_DBG_MAP, dip, "%s%d: no ranges property\n",
4496171313bed39e96f21bc2f9faf2868e267ae3girish /* locate matching ranges record */
4496171313bed39e96f21bc2f9faf2868e267ae3girish if (i >= rngnum) {
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD DBG(NIUMX_DBG_MAP, dip, "ranges record for reg[%d] "
4496171313bed39e96f21bc2f9faf2868e267ae3girish * validate request has matching bus type and within 4G
4496171313bed39e96f21bc2f9faf2868e267ae3girish * limit by comparing addr.hi of "ranges" and child "reg".
4496171313bed39e96f21bc2f9faf2868e267ae3girish /* check to verify reg bounds are within rng bounds */
4496171313bed39e96f21bc2f9faf2868e267ae3girish if (reg_begin < rng_begin || (reg_begin + (reg_p->size_low - 1)) >
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD DBG(NIUMX_DBG_MAP, dip, "size out of range for reg[%d].\n", rn);
4496171313bed39e96f21bc2f9faf2868e267ae3girish p_regspec.regspec_addr = reg_begin - rng_begin + rng_p->parent_lo;
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD DBG(NIUMX_DBG_MAP, dip, "regspec:bus,addr,size = (%x,%x,%x)\n",
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD DBG(NIUMX_DBG_MAP, dip, "niumx_map: ret %d.\n", ret);
4496171313bed39e96f21bc2f9faf2868e267ae3girish * niumx_ctlops
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD DBG(NIUMX_DBG_CTLOPS, dip, "niumx_ctlops ctlop=%d.\n", ctlop);
4496171313bed39e96f21bc2f9faf2868e267ae3girish /* fall through */
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD DBG(NIUMX_DBG_CTLOPS, dip, "just pass to ddi_cltops.\n");
4496171313bed39e96f21bc2f9faf2868e267ae3girish *(int *)result = 0;
4496171313bed39e96f21bc2f9faf2868e267ae3girish if (ddi_getlongprop(DDI_DEV_T_NONE, rdip, DDI_PROP_DONTPASS |
adf6c93b5d9301a4bf74a4110edfd3ab1f94478bjf DDI_PROP_CANSLEEP, "reg", (caddr_t)®_p, ®len) != DDI_SUCCESS)
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD DBG(NIUMX_DBG_CTLOPS, (dev_info_t *)dip,
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD DBG(NIUMX_DBG_CTLOPS, (dev_info_t *)dip,
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD "rn = %d, REGSIZE=%x.\n", rn, *(off_t *)result);
adf6c93b5d9301a4bf74a4110edfd3ab1f94478bjf * niumx_name_child
adf6c93b5d9301a4bf74a4110edfd3ab1f94478bjf * This function is called from init_child to name a node. It is
adf6c93b5d9301a4bf74a4110edfd3ab1f94478bjf * also passed as a callback for node merging functions.
adf6c93b5d9301a4bf74a4110edfd3ab1f94478bjf * return value: DDI_SUCCESS, DDI_FAILURE
adf6c93b5d9301a4bf74a4110edfd3ab1f94478bjfniumx_name_child(dev_info_t *child, char *name, int namelen)
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD DBG(NIUMX_DBG_CHK_MOD, (dev_info_t *)child, "==> niumx_name_child\n");
adf6c93b5d9301a4bf74a4110edfd3ab1f94478bjf /* name .conf nodes by "unit-address" property */
adf6c93b5d9301a4bf74a4110edfd3ab1f94478bjf /* name hardware nodes by "reg" property */
4496171313bed39e96f21bc2f9faf2868e267ae3girish if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
678453a8ed49104d8adad58f3ba591bdc39883e8speer (void) snprintf(name, namelen, "%x", (r[0].addr_high));
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD DBG(NIUMX_DBG_CHK_MOD, (dev_info_t *)child, "==> niumx_initchild\n");
adf6c93b5d9301a4bf74a4110edfd3ab1f94478bjf * Non-peristent nodes indicate a prototype node with per-instance
adf6c93b5d9301a4bf74a4110edfd3ab1f94478bjf * properties to be merged into the real h/w device node.
adf6c93b5d9301a4bf74a4110edfd3ab1f94478bjf "cannot merge prototype from %s.conf",
adf6c93b5d9301a4bf74a4110edfd3ab1f94478bjf if (niumx_name_child(child, name, MAXNAMELEN) != DDI_SUCCESS)
adf6c93b5d9301a4bf74a4110edfd3ab1f94478bjf * Try to merge the properties from this prototype
adf6c93b5d9301a4bf74a4110edfd3ab1f94478bjf * node into real h/w nodes.
adf6c93b5d9301a4bf74a4110edfd3ab1f94478bjf if (ndi_merge_node(child, niumx_name_child) == DDI_SUCCESS) {
adf6c93b5d9301a4bf74a4110edfd3ab1f94478bjf * Merged ok - return failure to remove the node.
adf6c93b5d9301a4bf74a4110edfd3ab1f94478bjf * The child was not merged into a h/w node,
adf6c93b5d9301a4bf74a4110edfd3ab1f94478bjf * but there's not much we can do with it other
adf6c93b5d9301a4bf74a4110edfd3ab1f94478bjf * than return failure to cause the node to be removed.
adf6c93b5d9301a4bf74a4110edfd3ab1f94478bjf cmn_err(CE_WARN, "!%s@%s: %s.conf properties not merged",
adf6c93b5d9301a4bf74a4110edfd3ab1f94478bjf * Initialize real h/w nodes
adf6c93b5d9301a4bf74a4110edfd3ab1f94478bjf if (niumx_name_child(child, name, MAXNAMELEN) != DDI_SUCCESS)
4496171313bed39e96f21bc2f9faf2868e267ae3girish * bus dma alloc handle entry point:
4496171313bed39e96f21bc2f9faf2868e267ae3girish/*ARGSUSED*/
4496171313bed39e96f21bc2f9faf2868e267ae3girishniumx_dma_allochdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_attr_t *attrp,
4496171313bed39e96f21bc2f9faf2868e267ae3girish int (*waitfp)(caddr_t), caddr_t arg, ddi_dma_handle_t *handlep)
4496171313bed39e96f21bc2f9faf2868e267ae3girish int sleep = (waitfp == DDI_DMA_SLEEP) ? KM_SLEEP : KM_NOSLEEP;
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD DBG(NIUMX_DBG_DMA_ALLOCH, dip, "rdip=%s%d\n", NIUMX_NAMEINST(rdip));
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD (dev_info_t *)dip, "DDI_DMA_BADATTR\n");
4496171313bed39e96f21bc2f9faf2868e267ae3girish /* Caution: we don't use zalloc to enhance performance! */
4496171313bed39e96f21bc2f9faf2868e267ae3girish if ((mp = kmem_alloc(sizeof (ddi_dma_impl_t), sleep)) == 0) {
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD DBG(NIUMX_DBG_DMA_ALLOCH, dip, "can't alloc ddi_dma_impl_t\n");
4496171313bed39e96f21bc2f9faf2868e267ae3girish mp->dmai_attr = *attrp; /* set requestors attr info */
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD DBG(NIUMX_DBG_DMA_ALLOCH, dip, "mp=%p\n", mp);
4496171313bed39e96f21bc2f9faf2868e267ae3girish * bus dma free handle entry point:
4496171313bed39e96f21bc2f9faf2868e267ae3girish/*ARGSUSED*/
4496171313bed39e96f21bc2f9faf2868e267ae3girishniumx_dma_freehdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t handle)
4496171313bed39e96f21bc2f9faf2868e267ae3girish kmem_free(mp->dmai_cookie, sizeof (ddi_dma_cookie_t));
4496171313bed39e96f21bc2f9faf2868e267ae3girish * bus dma bind handle entry point:
4496171313bed39e96f21bc2f9faf2868e267ae3girish * check/enforce DMA type, setup pfn0 and some other key pieces
4496171313bed39e96f21bc2f9faf2868e267ae3girish * of this dma request.
4496171313bed39e96f21bc2f9faf2868e267ae3girish * Note: this only works with DMA_OTYP_VADDR, and makes use of the known
4496171313bed39e96f21bc2f9faf2868e267ae3girish * fact that only contiguous memory blocks will be passed in.
4496171313bed39e96f21bc2f9faf2868e267ae3girish * Therefore only one cookie will ever be returned.
4496171313bed39e96f21bc2f9faf2868e267ae3girish * return values:
4496171313bed39e96f21bc2f9faf2868e267ae3girish * DDI_DMA_NOMAPPING - can't get valid pfn0, or bad dma type
4496171313bed39e96f21bc2f9faf2868e267ae3girish * DDI_DMA_NORESOURCES
4496171313bed39e96f21bc2f9faf2868e267ae3girish * DDI_SUCCESS
4496171313bed39e96f21bc2f9faf2868e267ae3girish * dma handle members affected (set on exit):
4496171313bed39e96f21bc2f9faf2868e267ae3girish * mp->dmai_object - dmareq->dmar_object
4496171313bed39e96f21bc2f9faf2868e267ae3girish * mp->dmai_rflags - dmareq->dmar_flags
4496171313bed39e96f21bc2f9faf2868e267ae3girish * mp->dmai_pfn0 - 1st page pfn (if va/size pair and not shadow)
4496171313bed39e96f21bc2f9faf2868e267ae3girish * mp->dmai_roffset - initialized to starting page offset
4496171313bed39e96f21bc2f9faf2868e267ae3girish * mp->dmai_size - # of total pages of entire object
4496171313bed39e96f21bc2f9faf2868e267ae3girish * mp->dmai_cookie - new cookie alloc'd
4496171313bed39e96f21bc2f9faf2868e267ae3girish/*ARGSUSED*/
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD DBG(NIUMX_DBG_DMA_BINDH, dip, "rdip=%s%d mp=%p dmareq=%p\n",
4496171313bed39e96f21bc2f9faf2868e267ae3girish /* first check dma type */
4496171313bed39e96f21bc2f9faf2868e267ae3girish mp->dmai_rflags = dmareq->dmar_flags & DMP_DDIFLAGS | DMP_NOSYNC;
4496171313bed39e96f21bc2f9faf2868e267ae3girish cmn_err(CE_WARN, "%s%d requested unsupported dma type %x",
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD NIUMX_NAMEINST(mp->dmai_rdip), dobj_p->dmao_type);
4496171313bed39e96f21bc2f9faf2868e267ae3girish cmn_err(CE_WARN, "%s%d: invalid pfn0 for DMA object %p",
4496171313bed39e96f21bc2f9faf2868e267ae3girish mp->dmai_mapping = mp->dmai_roffset | NIUMX_PTOB(pfn0);
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD DBG(NIUMX_DBG_DMA_BINDH, dip, "check pfn: mp=%p pfn0=%x\n",
4496171313bed39e96f21bc2f9faf2868e267ae3girish if (!(mp->dmai_cookie = kmem_zalloc(sizeof (ddi_dma_cookie_t),
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD DBG(NIUMX_DBG_DMA_BINDH, dip, "cookie %" PRIx64 "+%x, count=%d\n",
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD DBG(NIUMX_DBG_DMA_BINDH, (dev_info_t *)dip,
4496171313bed39e96f21bc2f9faf2868e267ae3girish * bus dma unbind handle entry point:
4496171313bed39e96f21bc2f9faf2868e267ae3girish/*ARGSUSED*/
4496171313bed39e96f21bc2f9faf2868e267ae3girishniumx_dma_unbindhdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t handle)
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD DBG(NIUMX_DBG_DMA_UNBINDH, dip, "rdip=%s%d, mp=%p\n",
4496171313bed39e96f21bc2f9faf2868e267ae3girish kmem_free(mp->dmai_cookie, sizeof (ddi_dma_cookie_t));
4496171313bed39e96f21bc2f9faf2868e267ae3girish/*ARGSUSED*/
4496171313bed39e96f21bc2f9faf2868e267ae3girishniumx_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op,
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD DBG(NIUMX_DBG_INTROPS, dip, "niumx_intr_ops: dip=%p rdip=%p intr_op=%x "
657f87de670449e1422db4f51fb2880a7cb69d5agongtian zhao - Sun Microsystems - Beijing China *(int *)result = DDI_INTR_FLAG_LEVEL;
4496171313bed39e96f21bc2f9faf2868e267ae3girish /* scratch1 = count, # of intrs from DDI framework */
4496171313bed39e96f21bc2f9faf2868e267ae3girish /* Do we need to do anything here? */
4496171313bed39e96f21bc2f9faf2868e267ae3girish ret = niumx_set_intr(dip, rdip, hdlp, HV_INTR_VALID);
4496171313bed39e96f21bc2f9faf2868e267ae3girish ret = niumx_set_intr(dip, rdip, hdlp, HV_INTR_NOTVALID);
4496171313bed39e96f21bc2f9faf2868e267ae3girish if (ddi_getlongprop(DDI_DEV_T_ANY, rdip, DDI_PROP_DONTPASS,
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD niumxds_p = (niumx_devstate_t *)ddi_get_soft_state(niumx_state,
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD ret = niumx_get_intr_target(niumxds_p, hdlp->ih_vector,
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD niumxds_p = (niumx_devstate_t *)ddi_get_soft_state(niumx_state,
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD ret = niumx_set_intr_target(niumxds_p, hdlp->ih_vector,
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD DBG(NIUMX_DBG_INTROPS, dip, "niumx_intr_ops: ret=%d\n", ret);
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu niumx_devstate_t *niumxds_p; /* devstate pointer */
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu niumxds_p = (niumx_devstate_t *)ddi_get_soft_state(niumx_state,
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD ih_p = niumxds_p->niumx_ihtable + hdlp->ih_vector;
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD "niumx_set_intr: rdip=%s%d, valid=%d %s (%x,%x)\n",
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD NIUMX_NAMEINST(rdip), valid, valid ? "enabling" : "disabling",
cb343a2e20368d059fdcf8755367f43e747266f2speer (void) hvio_intr_setstate(ih_p->ih_sysino, HV_INTR_IDLE_STATE);
4496171313bed39e96f21bc2f9faf2868e267ae3girish if ((hvret = hvio_intr_setvalid(ih_p->ih_sysino, valid))
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD "hvio_intr_setvalid failed, ret 0x%x\n", hvret);
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSDniumx_get_intr_target(niumx_devstate_t *niumxds_p, niudevino_t ino,
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD ih_p = niumxds_p->niumx_ihtable + ino;
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD if (hvio_intr_gettarget(sysino, cpu_id) != H_EOK) {
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSDniumx_set_intr_target(niumx_devstate_t *niumxds_p, niudevino_t ino,
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD extern const int _ncpu;
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD ih_p = niumxds_p->niumx_ihtable + ino;
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD if (hvio_intr_gettarget(sysino, &old_cpu_id) != H_EOK) {
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD if ((cpu_id < _ncpu) && (cpu[cpu_id] && cpu_is_online(cpu[cpu_id]))) {
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD /* check for pending interrupts, busy wait if so */
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD for (start = gethrtime(); !panicstr &&
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD (hvio_intr_getstate(sysino, &state) == H_EOK) &&
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD (state == HV_INTR_DELIVERED_STATE); /* */) {
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD if (gethrtime() - start > niumx_intr_timeout) {
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD cmn_err(CE_WARN, "%s%d: niumx_intr_dist: "
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD "pending interrupt (%x,%lx) timedout\n",
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD ddi_driver_name(dip), ddi_get_instance(dip),
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD (void) hvio_intr_settarget(sysino, cpu_id);
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD (void) hvio_intr_setvalid(sysino, HV_INTR_VALID);
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD (void) hvio_intr_setvalid(sysino, HV_INTR_NOTVALID);
4496171313bed39e96f21bc2f9faf2868e267ae3girish * niumx_add_intr:
e778ae4497a8de30b58b85bd187bf4ef4ba8cd47Raghuram Kothakota * This function is called to register interrupts.
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu niumx_devstate_t *niumxds_p; /* devstate pointer */
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu niumxds_p = (niumx_devstate_t *)ddi_get_soft_state(niumx_state,
4496171313bed39e96f21bc2f9faf2868e267ae3girish /* get new ino */
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD DBG(NIUMX_DBG_INTR, dip, "error: inum %d out of range\n",
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD ih_p = niumxds_p->niumx_ihtable + hdlp->ih_vector;
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD if ((hvret = hvio_intr_devino_to_sysino(NIUMX_DIP_TO_HANDLE(dip),
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD hdlp->ih_vector, &sysino)) != H_EOK) {
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD DBG(NIUMX_DBG_INTR, dip, "hvio_intr_devino_to_sysino failed, "
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD DBG(NIUMX_DBG_A_INTX, dip, "niumx_add_intr: rdip=%s%d inum=0x%x "
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD "handler=%p arg1=%p arg2=%p, new ih_p = %p\n", NIUMX_NAMEINST(rdip),
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD DBG(NIUMX_DBG_A_INTX, dip, "for ino %x adding (%x,%x)\n",
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD hdlp->ih_vector, ih_p->ih_inum, ih_p->ih_sysino);
4496171313bed39e96f21bc2f9faf2868e267ae3girish /* Save sysino value in hdlp */
4496171313bed39e96f21bc2f9faf2868e267ae3girish /* swap in our handler & arg */
4496171313bed39e96f21bc2f9faf2868e267ae3girish DDI_INTR_ASSIGN_HDLR_N_ARGS(hdlp, (ddi_intr_handler_t *)niumx_intr_hdlr,
4496171313bed39e96f21bc2f9faf2868e267ae3girish /* Restore orig. interrupt handler & args in handle. */
4496171313bed39e96f21bc2f9faf2868e267ae3girish DDI_INTR_ASSIGN_HDLR_N_ARGS(hdlp, ih_p->ih_hdlr, ih_p->ih_arg1,
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD DBG(NIUMX_DBG_A_INTX, dip, "i_ddi_add_ivintr error ret=%x\n",
4496171313bed39e96f21bc2f9faf2868e267ae3girish /* select cpu, saving it for removal */
4496171313bed39e96f21bc2f9faf2868e267ae3girish if ((hvret = hvio_intr_settarget(ih_p->ih_sysino, ih_p->ih_cpuid))
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD "hvio_intr_settarget failed, ret 0x%x\n", hvret);
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD DBG(NIUMX_DBG_A_INTX, dip, "done, ret = %d, ih_p 0x%p, hdlp 0x%p\n",
4496171313bed39e96f21bc2f9faf2868e267ae3girish * niumx_rem_intr:
4496171313bed39e96f21bc2f9faf2868e267ae3girish * This function is called to unregister interrupts.
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu niumx_devstate_t *niumxds_p; /* devstate pointer */
4df55fde49134f9735f84011f23a767c75e393c7Janie Lu niumxds_p = (niumx_devstate_t *)ddi_get_soft_state(niumx_state,
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD ih_p = niumxds_p->niumx_ihtable + hdlp->ih_vector;
500b1e787b108592a37e3d54dc9b5e676de5386dAlan Adamson, SD OSSD DBG(NIUMX_DBG_R_INTX, dip, "removing (%x,%x)\n", ih_p->ih_inum, sysino);
c165966d2681754edbe7637da5adf3e53b3f7132jf /* check for pending interrupts, busy wait if so */
c165966d2681754edbe7637da5adf3e53b3f7132jf "pending interrupt (%x,%lx) timedout\n",
4496171313bed39e96f21bc2f9faf2868e267ae3girish * niumx_intr_hdlr (our interrupt handler)
4496171313bed39e96f21bc2f9faf2868e267ae3girish DTRACE_PROBE4(interrupt__start, dev_info_t, ih_p->ih_dip, void *,
adf6c93b5d9301a4bf74a4110edfd3ab1f94478bjf ih_p->ih_hdlr, caddr_t, ih_p->ih_arg1, caddr_t, ih_p->ih_arg2);
4496171313bed39e96f21bc2f9faf2868e267ae3girish DTRACE_PROBE4(interrupt__complete, dev_info_t, ih_p->ih_dip, void *,
cb343a2e20368d059fdcf8755367f43e747266f2speer (void) hvio_intr_setstate(ih_p->ih_sysino, HV_INTR_IDLE_STATE);
4496171313bed39e96f21bc2f9faf2868e267ae3girish return (r);
4496171313bed39e96f21bc2f9faf2868e267ae3girishstatic char *niumx_debug_sym [] = { /* same sequence as niumx_debug_bit */
4496171313bed39e96f21bc2f9faf2868e267ae3girish/*ARGSUSED*/
4496171313bed39e96f21bc2f9faf2868e267ae3girishniumx_dbg(niumx_debug_bit_t bit, dev_info_t *dip, char *fmt, ...)
4496171313bed39e96f21bc2f9faf2868e267ae3girish cmn_err(CE_NOTE, "%s: %s", niumx_debug_sym[bit], msgbuf);
4496171313bed39e96f21bc2f9faf2868e267ae3girish#endif /* DEBUG */