Home | History | Annotate | Download | only in px
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 #include <sys/types.h>
     27 #include <sys/sysmacros.h>
     28 #include <sys/ddi.h>
     29 #include <sys/async.h>
     30 #include <sys/sunddi.h>
     31 #include <sys/ddifm.h>
     32 #include <sys/fm/protocol.h>
     33 #include <sys/vmem.h>
     34 #include <sys/intr.h>
     35 #include <sys/ivintr.h>
     36 #include <sys/errno.h>
     37 #include <sys/hypervisor_api.h>
     38 #include <sys/hsvc.h>
     39 #include <px_obj.h>
     40 #include <sys/machsystm.h>
     41 #include "px_lib4v.h"
     42 #include "px_err.h"
     43 
     44 /* mask for the ranges property in calculating the real PFN range */
     45 uint_t px_ranges_phi_mask = ((1 << 28) -1);
     46 
     47 /*
     48  * Hypervisor VPCI services information for the px nexus driver.
     49  */
     50 static	uint64_t	px_vpci_min_ver; /* Negotiated VPCI API minor version */
     51 static	uint_t		px_vpci_users = 0; /* VPCI API users */
     52 
     53 static hsvc_info_t px_hsvc = {
     54 	HSVC_REV_1, NULL, HSVC_GROUP_VPCI, PX_VPCI_MAJOR_VER,
     55 	PX_VPCI_MINOR_VER, "PX"
     56 };
     57 
     58 int
     59 px_lib_dev_init(dev_info_t *dip, devhandle_t *dev_hdl)
     60 {
     61 	px_nexus_regspec_t	*rp;
     62 	uint_t			reglen;
     63 	int			ret;
     64 
     65 	uint64_t mjrnum;
     66 	uint64_t mnrnum;
     67 
     68 	DBG(DBG_ATTACH, dip, "px_lib_dev_init: dip 0x%p\n", dip);
     69 
     70 	/*
     71 	 * Check HV intr group api versioning.
     72 	 * This driver uses the old interrupt routines which are supported
     73 	 * in old firmware in the CORE API group and in newer firmware in
     74 	 * the INTR API group.  Support for these calls will be dropped
     75 	 * once the INTR API group major goes to 2.
     76 	 */
     77 	if ((hsvc_version(HSVC_GROUP_INTR, &mjrnum, &mnrnum) == 0) &&
     78 	    (mjrnum > 1)) {
     79 		cmn_err(CE_WARN, "px: unsupported intr api group: "
     80 		    "maj:0x%lx, min:0x%lx", mjrnum, mnrnum);
     81 		return (ENOTSUP);
     82 	}
     83 
     84 	ret = ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
     85 	    "reg", (uchar_t **)&rp, &reglen);
     86 	if (ret != DDI_PROP_SUCCESS) {
     87 		DBG(DBG_ATTACH, dip, "px_lib_dev_init failed ret=%d\n", ret);
     88 		return (DDI_FAILURE);
     89 	}
     90 
     91 	/*
     92 	 * Initilize device handle. The device handle uniquely identifies
     93 	 * a SUN4V device. It consists of the lower 28-bits of the hi-cell
     94 	 * of the first entry of the SUN4V device's "reg" property as
     95 	 * defined by the SUN4V Bus Binding to Open Firmware.
     96 	 */
     97 	*dev_hdl = (devhandle_t)((rp->phys_addr >> 32) & DEVHDLE_MASK);
     98 	ddi_prop_free(rp);
     99 
    100 	/*
    101 	 * hotplug implementation requires this property to be associated with
    102 	 * any indirect PCI config access services
    103 	 */
    104 	(void) ddi_prop_update_int(makedevice(ddi_driver_major(dip),
    105 	    PCI_MINOR_NUM(ddi_get_instance(dip), PCI_DEVCTL_MINOR)), dip,
    106 	    PCI_BUS_CONF_MAP_PROP, 1);
    107 
    108 	DBG(DBG_ATTACH, dip, "px_lib_dev_init: dev_hdl 0x%llx\n", *dev_hdl);
    109 
    110 	/*
    111 	 * Negotiate the API version for VPCI hypervisor services.
    112 	 */
    113 	if (px_vpci_users++)
    114 		return (DDI_SUCCESS);
    115 
    116 	if ((ret = hsvc_register(&px_hsvc, &px_vpci_min_ver)) != 0) {
    117 		cmn_err(CE_WARN, "%s: cannot negotiate hypervisor services "
    118 		    "group: 0x%lx major: 0x%lx minor: 0x%lx errno: %d\n",
    119 		    px_hsvc.hsvc_modname, px_hsvc.hsvc_group,
    120 		    px_hsvc.hsvc_major, px_hsvc.hsvc_minor, ret);
    121 
    122 		return (DDI_FAILURE);
    123 	}
    124 
    125 	DBG(DBG_ATTACH, dip, "px_lib_dev_init: negotiated VPCI API version, "
    126 	    "major 0x%lx minor 0x%lx\n", px_hsvc.hsvc_major, px_vpci_min_ver);
    127 
    128 	return (DDI_SUCCESS);
    129 }
    130 
    131 /*ARGSUSED*/
    132 int
    133 px_lib_dev_fini(dev_info_t *dip)
    134 {
    135 	DBG(DBG_DETACH, dip, "px_lib_dev_fini: dip 0x%p\n", dip);
    136 
    137 	(void) ddi_prop_remove(makedevice(ddi_driver_major(dip),
    138 	    PCI_MINOR_NUM(ddi_get_instance(dip), PCI_DEVCTL_MINOR)), dip,
    139 	    PCI_BUS_CONF_MAP_PROP);
    140 
    141 	if (--px_vpci_users == 0)
    142 		(void) hsvc_unregister(&px_hsvc);
    143 
    144 	return (DDI_SUCCESS);
    145 }
    146 
    147 /*ARGSUSED*/
    148 int
    149 px_lib_intr_devino_to_sysino(dev_info_t *dip, devino_t devino,
    150     sysino_t *sysino)
    151 {
    152 	uint64_t	ret;
    153 
    154 	DBG(DBG_LIB_INT, dip, "px_lib_intr_devino_to_sysino: dip 0x%p "
    155 	    "devino 0x%x\n", dip, devino);
    156 
    157 	if ((ret = hvio_intr_devino_to_sysino(DIP_TO_HANDLE(dip),
    158 	    devino, sysino)) != H_EOK) {
    159 		DBG(DBG_LIB_INT, dip,
    160 		    "hvio_intr_devino_to_sysino failed, ret 0x%lx\n", ret);
    161 		return (DDI_FAILURE);
    162 	}
    163 
    164 	DBG(DBG_LIB_INT, dip, "px_lib_intr_devino_to_sysino: sysino 0x%llx\n",
    165 	    *sysino);
    166 
    167 	return (DDI_SUCCESS);
    168 }
    169 
    170 /*ARGSUSED*/
    171 int
    172 px_lib_intr_getvalid(dev_info_t *dip, sysino_t sysino,
    173     intr_valid_state_t *intr_valid_state)
    174 {
    175 	uint64_t	ret;
    176 
    177 	DBG(DBG_LIB_INT, dip, "px_lib_intr_getvalid: dip 0x%p sysino 0x%llx\n",
    178 	    dip, sysino);
    179 
    180 	if ((ret = hvio_intr_getvalid(sysino,
    181 	    (int *)intr_valid_state)) != H_EOK) {
    182 		DBG(DBG_LIB_INT, dip, "hvio_intr_getvalid failed, ret 0x%lx\n",
    183 		    ret);
    184 		return (DDI_FAILURE);
    185 	}
    186 
    187 	DBG(DBG_LIB_INT, dip, "px_lib_intr_getvalid: intr_valid_state 0x%x\n",
    188 	    *intr_valid_state);
    189 
    190 	return (DDI_SUCCESS);
    191 }
    192 
    193 /*ARGSUSED*/
    194 int
    195 px_lib_intr_setvalid(dev_info_t *dip, sysino_t sysino,
    196     intr_valid_state_t intr_valid_state)
    197 {
    198 	uint64_t	ret;
    199 
    200 	DBG(DBG_LIB_INT, dip, "px_lib_intr_setvalid: dip 0x%p sysino 0x%llx "
    201 	    "intr_valid_state 0x%x\n", dip, sysino, intr_valid_state);
    202 
    203 	if ((ret = hvio_intr_setvalid(sysino, intr_valid_state)) != H_EOK) {
    204 		DBG(DBG_LIB_INT, dip, "hvio_intr_setvalid failed, ret 0x%lx\n",
    205 		    ret);
    206 		return (DDI_FAILURE);
    207 	}
    208 
    209 	return (DDI_SUCCESS);
    210 }
    211 
    212 /*ARGSUSED*/
    213 int
    214 px_lib_intr_getstate(dev_info_t *dip, sysino_t sysino,
    215     intr_state_t *intr_state)
    216 {
    217 	uint64_t	ret;
    218 
    219 	DBG(DBG_LIB_INT, dip, "px_lib_intr_getstate: dip 0x%p sysino 0x%llx\n",
    220 	    dip, sysino);
    221 
    222 	if ((ret = hvio_intr_getstate(sysino, (int *)intr_state)) != H_EOK) {
    223 		DBG(DBG_LIB_INT, dip, "hvio_intr_getstate failed, ret 0x%lx\n",
    224 		    ret);
    225 		return (DDI_FAILURE);
    226 	}
    227 
    228 	DBG(DBG_LIB_INT, dip, "px_lib_intr_getstate: intr_state 0x%x\n",
    229 	    *intr_state);
    230 
    231 	return (DDI_SUCCESS);
    232 }
    233 
    234 /*ARGSUSED*/
    235 int
    236 px_lib_intr_setstate(dev_info_t *dip, sysino_t sysino,
    237     intr_state_t intr_state)
    238 {
    239 	uint64_t	ret;
    240 
    241 	DBG(DBG_LIB_INT, dip, "px_lib_intr_setstate: dip 0x%p sysino 0x%llx "
    242 	    "intr_state 0x%x\n", dip, sysino, intr_state);
    243 
    244 	if ((ret = hvio_intr_setstate(sysino, intr_state)) != H_EOK) {
    245 		DBG(DBG_LIB_INT, dip, "hvio_intr_setstate failed, ret 0x%lx\n",
    246 		    ret);
    247 		return (DDI_FAILURE);
    248 	}
    249 
    250 	return (DDI_SUCCESS);
    251 }
    252 
    253 /*ARGSUSED*/
    254 int
    255 px_lib_intr_gettarget(dev_info_t *dip, sysino_t sysino, cpuid_t *cpuid)
    256 {
    257 	uint64_t	ret;
    258 
    259 	DBG(DBG_LIB_INT, dip, "px_lib_intr_gettarget: dip 0x%p sysino 0x%llx\n",
    260 	    dip, sysino);
    261 
    262 	if ((ret = hvio_intr_gettarget(sysino, cpuid)) != H_EOK) {
    263 		DBG(DBG_LIB_INT, dip,
    264 		    "hvio_intr_gettarget failed, ret 0x%lx\n", ret);
    265 		return (DDI_FAILURE);
    266 	}
    267 
    268 	DBG(DBG_LIB_INT, dip, "px_lib_intr_gettarget: cpuid 0x%x\n", *cpuid);
    269 
    270 	return (DDI_SUCCESS);
    271 }
    272 
    273 /*ARGSUSED*/
    274 int
    275 px_lib_intr_settarget(dev_info_t *dip, sysino_t sysino, cpuid_t cpuid)
    276 {
    277 	uint64_t	ret;
    278 
    279 	DBG(DBG_LIB_INT, dip, "px_lib_intr_settarget: dip 0x%p sysino 0x%llx "
    280 	    "cpuid 0x%x\n", dip, sysino, cpuid);
    281 
    282 	ret = hvio_intr_settarget(sysino, cpuid);
    283 	if (ret == H_ECPUERROR) {
    284 		cmn_err(CE_PANIC,
    285 		    "px_lib_intr_settarget: hvio_intr_settarget failed, "
    286 		    "ret = 0x%lx, cpuid = 0x%x, sysino = 0x%lx\n", ret,
    287 		    cpuid, sysino);
    288 	} else if (ret != H_EOK) {
    289 		DBG(DBG_LIB_INT, dip,
    290 		    "hvio_intr_settarget failed, ret 0x%lx\n", ret);
    291 		return (DDI_FAILURE);
    292 	}
    293 
    294 	return (DDI_SUCCESS);
    295 }
    296 
    297 /*ARGSUSED*/
    298 int
    299 px_lib_intr_reset(dev_info_t *dip)
    300 {
    301 	px_t		*px_p = DIP_TO_STATE(dip);
    302 	px_ib_t		*ib_p = px_p->px_ib_p;
    303 	px_ino_t	*ino_p;
    304 
    305 	DBG(DBG_LIB_INT, dip, "px_lib_intr_reset: dip 0x%p\n", dip);
    306 
    307 	mutex_enter(&ib_p->ib_ino_lst_mutex);
    308 
    309 	/* Reset all Interrupts */
    310 	for (ino_p = ib_p->ib_ino_lst; ino_p; ino_p = ino_p->ino_next_p) {
    311 		if (px_lib_intr_setstate(dip, ino_p->ino_sysino,
    312 		    INTR_IDLE_STATE) != DDI_SUCCESS)
    313 			return (BF_FATAL);
    314 	}
    315 
    316 	mutex_exit(&ib_p->ib_ino_lst_mutex);
    317 
    318 	return (BF_NONE);
    319 }
    320 
    321 /*ARGSUSED*/
    322 int
    323 px_lib_iommu_map(dev_info_t *dip, tsbid_t tsbid, pages_t pages,
    324     io_attributes_t attr, void *addr, size_t pfn_index, int flags)
    325 {
    326 	tsbnum_t	tsb_num = PCI_TSBID_TO_TSBNUM(tsbid);
    327 	tsbindex_t	tsb_index = PCI_TSBID_TO_TSBINDEX(tsbid);
    328 	io_page_list_t	*pfns, *pfn_p;
    329 	pages_t		ttes_mapped = 0;
    330 	int		i, err = DDI_SUCCESS;
    331 
    332 	DBG(DBG_LIB_DMA, dip, "px_lib_iommu_map: dip 0x%p tsbid 0x%llx "
    333 	    "pages 0x%x attr 0x%llx addr 0x%p pfn_index 0x%llx flags 0x%x\n",
    334 	    dip, tsbid, pages, attr, addr, pfn_index, flags);
    335 
    336 	if ((pfns = pfn_p = kmem_zalloc((pages * sizeof (io_page_list_t)),
    337 	    KM_NOSLEEP)) == NULL) {
    338 		DBG(DBG_LIB_DMA, dip, "px_lib_iommu_map: kmem_zalloc failed\n");
    339 		return (DDI_FAILURE);
    340 	}
    341 
    342 	for (i = 0; i < pages; i++)
    343 		pfns[i] = MMU_PTOB(PX_ADDR2PFN(addr, pfn_index, flags, i));
    344 
    345 	/*
    346 	 * If HV VPCI version is 1.1 and higher, pass BDF, phantom function,
    347 	 * and relaxed ordering attributes. Otherwise, pass only read or write
    348 	 * attribute.
    349 	 */
    350 	if (px_vpci_min_ver == PX_VPCI_MINOR_VER_0)
    351 		attr = attr & (PCI_MAP_ATTR_READ | PCI_MAP_ATTR_WRITE);
    352 
    353 	while ((ttes_mapped = pfn_p - pfns) < pages) {
    354 		uintptr_t	ra = va_to_pa(pfn_p);
    355 		pages_t		ttes2map;
    356 		uint64_t	ret;
    357 
    358 		ttes2map = (MMU_PAGE_SIZE - P2PHASE(ra, MMU_PAGE_SIZE)) >> 3;
    359 		ra = MMU_PTOB(MMU_BTOP(ra));
    360 
    361 		for (ttes2map = MIN(ttes2map, pages - ttes_mapped); ttes2map;
    362 		    ttes2map -= ttes_mapped, pfn_p += ttes_mapped) {
    363 
    364 			ttes_mapped = 0;
    365 			if ((ret = hvio_iommu_map(DIP_TO_HANDLE(dip),
    366 			    PCI_TSBID(tsb_num, tsb_index + (pfn_p - pfns)),
    367 			    ttes2map, attr, (io_page_list_t *)(ra |
    368 			    ((uintptr_t)pfn_p & MMU_PAGE_OFFSET)),
    369 			    &ttes_mapped)) != H_EOK) {
    370 				DBG(DBG_LIB_DMA, dip, "hvio_iommu_map failed "
    371 				    "ret 0x%lx\n", ret);
    372 
    373 				ttes_mapped = pfn_p - pfns;
    374 				err = DDI_FAILURE;
    375 				goto cleanup;
    376 			}
    377 
    378 			DBG(DBG_LIB_DMA, dip, "px_lib_iommu_map: tsb_num 0x%x "
    379 			    "tsb_index 0x%lx ttes_to_map 0x%lx attr 0x%llx "
    380 			    "ra 0x%p ttes_mapped 0x%x\n", tsb_num,
    381 			    tsb_index + (pfn_p - pfns), ttes2map, attr,
    382 			    ra | ((uintptr_t)pfn_p & MMU_PAGE_OFFSET),
    383 			    ttes_mapped);
    384 		}
    385 	}
    386 
    387 cleanup:
    388 	if ((err == DDI_FAILURE) && ttes_mapped)
    389 		(void) px_lib_iommu_demap(dip, tsbid, ttes_mapped);
    390 
    391 	kmem_free(pfns, pages * sizeof (io_page_list_t));
    392 	return (err);
    393 }
    394 
    395 /*ARGSUSED*/
    396 int
    397 px_lib_iommu_demap(dev_info_t *dip, tsbid_t tsbid, pages_t pages)
    398 {
    399 	tsbnum_t	tsb_num = PCI_TSBID_TO_TSBNUM(tsbid);
    400 	tsbindex_t	tsb_index = PCI_TSBID_TO_TSBINDEX(tsbid);
    401 	pages_t		ttes2demap, ttes_demapped = 0;
    402 	uint64_t	ret;
    403 
    404 	DBG(DBG_LIB_DMA, dip, "px_lib_iommu_demap: dip 0x%p tsbid 0x%llx "
    405 	    "pages 0x%x\n", dip, tsbid, pages);
    406 
    407 	for (ttes2demap = pages; ttes2demap;
    408 	    ttes2demap -= ttes_demapped, tsb_index += ttes_demapped) {
    409 		if ((ret = hvio_iommu_demap(DIP_TO_HANDLE(dip),
    410 		    PCI_TSBID(tsb_num, tsb_index), ttes2demap,
    411 		    &ttes_demapped)) != H_EOK) {
    412 			DBG(DBG_LIB_DMA, dip, "hvio_iommu_demap failed, "
    413 			    "ret 0x%lx\n", ret);
    414 
    415 			return (DDI_FAILURE);
    416 		}
    417 
    418 		DBG(DBG_LIB_DMA, dip, "px_lib_iommu_demap: tsb_num 0x%x "
    419 		    "tsb_index 0x%lx ttes_to_demap 0x%lx ttes_demapped 0x%x\n",
    420 		    tsb_num, tsb_index, ttes2demap, ttes_demapped);
    421 	}
    422 
    423 	return (DDI_SUCCESS);
    424 }
    425 
    426 /*ARGSUSED*/
    427 int
    428 px_lib_iommu_getmap(dev_info_t *dip, tsbid_t tsbid, io_attributes_t *attr_p,
    429     r_addr_t *r_addr_p)
    430 {
    431 	uint64_t	ret;
    432 
    433 	DBG(DBG_LIB_DMA, dip, "px_lib_iommu_getmap: dip 0x%p tsbid 0x%llx\n",
    434 	    dip, tsbid);
    435 
    436 	if ((ret = hvio_iommu_getmap(DIP_TO_HANDLE(dip), tsbid,
    437 	    attr_p, r_addr_p)) != H_EOK) {
    438 		DBG(DBG_LIB_DMA, dip,
    439 		    "hvio_iommu_getmap failed, ret 0x%lx\n", ret);
    440 
    441 		return ((ret == H_ENOMAP) ? DDI_DMA_NOMAPPING:DDI_FAILURE);
    442 	}
    443 
    444 	DBG(DBG_LIB_DMA, dip, "px_lib_iommu_getmap: attr 0x%llx "
    445 	    "r_addr 0x%llx\n", *attr_p, *r_addr_p);
    446 
    447 	return (DDI_SUCCESS);
    448 }
    449 
    450 /*ARGSUSED*/
    451 uint64_t
    452 px_get_rng_parent_hi_mask(px_t *px_p)
    453 {
    454 	return (PX_RANGE_PROP_MASK);
    455 }
    456 
    457 /*
    458  * Checks dma attributes against system bypass ranges
    459  * A sun4v device must be capable of generating the entire 64-bit
    460  * address in order to perform bypass DMA.
    461  */
    462 /*ARGSUSED*/
    463 int
    464 px_lib_dma_bypass_rngchk(dev_info_t *dip, ddi_dma_attr_t *attr_p,
    465     uint64_t *lo_p, uint64_t *hi_p)
    466 {
    467 	if ((attr_p->dma_attr_addr_lo != 0ull) ||
    468 	    (attr_p->dma_attr_addr_hi != UINT64_MAX)) {
    469 
    470 		return (DDI_DMA_BADATTR);
    471 	}
    472 
    473 	*lo_p = 0ull;
    474 	*hi_p = UINT64_MAX;
    475 
    476 	return (DDI_SUCCESS);
    477 }
    478 
    479 
    480 /*ARGSUSED*/
    481 int
    482 px_lib_iommu_getbypass(dev_info_t *dip, r_addr_t ra, io_attributes_t attr,
    483     io_addr_t *io_addr_p)
    484 {
    485 	uint64_t	ret;
    486 
    487 	DBG(DBG_LIB_DMA, dip, "px_lib_iommu_getbypass: dip 0x%p ra 0x%llx "
    488 	    "attr 0x%llx\n", dip, ra, attr);
    489 
    490 	if ((ret = hvio_iommu_getbypass(DIP_TO_HANDLE(dip), ra,
    491 	    attr, io_addr_p)) != H_EOK) {
    492 		DBG(DBG_LIB_DMA, dip,
    493 		    "hvio_iommu_getbypass failed, ret 0x%lx\n", ret);
    494 		return (ret == H_ENOTSUPPORTED ? DDI_ENOTSUP : DDI_FAILURE);
    495 	}
    496 
    497 	DBG(DBG_LIB_DMA, dip, "px_lib_iommu_getbypass: io_addr 0x%llx\n",
    498 	    *io_addr_p);
    499 
    500 	return (DDI_SUCCESS);
    501 }
    502 
    503 /*
    504  * Returns any needed IO address bit(s) for relaxed ordering in IOMMU
    505  * bypass mode.
    506  */
    507 /* ARGSUSED */
    508 uint64_t
    509 px_lib_ro_bypass(dev_info_t *dip, io_attributes_t attr, uint64_t ioaddr)
    510 {
    511 	return (ioaddr);
    512 }
    513 
    514 /*ARGSUSED*/
    515 int
    516 px_lib_dma_sync(dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t handle,
    517 	off_t off, size_t len, uint_t cache_flags)
    518 {
    519 	ddi_dma_impl_t *mp = (ddi_dma_impl_t *)handle;
    520 	uint64_t sync_dir;
    521 	size_t bytes_synced;
    522 	int end, idx;
    523 	off_t pg_off;
    524 	devhandle_t hdl = DIP_TO_HANDLE(dip); /* need to cache hdl */
    525 
    526 	DBG(DBG_LIB_DMA, dip, "px_lib_dma_sync: dip 0x%p rdip 0x%p "
    527 	    "handle 0x%llx off 0x%x len 0x%x flags 0x%x\n",
    528 	    dip, rdip, handle, off, len, cache_flags);
    529 
    530 	if (!(mp->dmai_flags & PX_DMAI_FLAGS_INUSE)) {
    531 		cmn_err(CE_WARN, "%s%d: Unbound dma handle %p.",
    532 		    ddi_driver_name(rdip), ddi_get_instance(rdip), (void *)mp);
    533 		return (DDI_FAILURE);
    534 	}
    535 
    536 	if (mp->dmai_flags & PX_DMAI_FLAGS_NOSYNC)
    537 		return (DDI_SUCCESS);
    538 
    539 	if (!len)
    540 		len = mp->dmai_size;
    541 
    542 	if (mp->dmai_rflags & DDI_DMA_READ)
    543 		sync_dir = HVIO_DMA_SYNC_DIR_FROM_DEV;
    544 	else
    545 		sync_dir = HVIO_DMA_SYNC_DIR_TO_DEV;
    546 
    547 	off += mp->dmai_offset;
    548 	pg_off = off & MMU_PAGEOFFSET;
    549 
    550 	DBG(DBG_LIB_DMA, dip, "px_lib_dma_sync: page offset %x size %x\n",
    551 	    pg_off, len);
    552 
    553 	/* sync on page basis */
    554 	end = MMU_BTOPR(off + len - 1);
    555 	for (idx = MMU_BTOP(off); idx < end; idx++,
    556 	    len -= bytes_synced, pg_off = 0) {
    557 		size_t bytes_to_sync = bytes_to_sync =
    558 		    MIN(len, MMU_PAGESIZE - pg_off);
    559 
    560 		if (hvio_dma_sync(hdl, MMU_PTOB(PX_GET_MP_PFN(mp, idx)) +
    561 		    pg_off, bytes_to_sync, sync_dir, &bytes_synced) != H_EOK)
    562 			break;
    563 
    564 		DBG(DBG_LIB_DMA, dip, "px_lib_dma_sync: Called hvio_dma_sync "
    565 		    "ra = %p bytes to sync = %x bytes synced %x\n",
    566 		    MMU_PTOB(PX_GET_MP_PFN(mp, idx)) + pg_off, bytes_to_sync,
    567 		    bytes_synced);
    568 
    569 		if (bytes_to_sync != bytes_synced)
    570 			break;
    571 	}
    572 
    573 	return (len ? DDI_FAILURE : DDI_SUCCESS);
    574 }
    575 
    576 
    577 /*
    578  * MSIQ Functions:
    579  */
    580 
    581 /*ARGSUSED*/
    582 int
    583 px_lib_msiq_init(dev_info_t *dip)
    584 {
    585 	px_t		*px_p = DIP_TO_STATE(dip);
    586 	px_msiq_state_t	*msiq_state_p = &px_p->px_ib_p->ib_msiq_state;
    587 	r_addr_t	ra;
    588 	size_t		msiq_size;
    589 	uint_t		rec_cnt;
    590 	int		i, err = DDI_SUCCESS;
    591 	uint64_t	ret;
    592 
    593 	DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_init: dip 0x%p\n", dip);
    594 
    595 	msiq_size = msiq_state_p->msiq_rec_cnt * sizeof (msiq_rec_t);
    596 
    597 	/* sun4v requires all EQ allocation to be on q size boundary */
    598 	if ((msiq_state_p->msiq_buf_p = contig_mem_alloc_align(
    599 	    msiq_state_p->msiq_cnt * msiq_size, msiq_size)) == NULL) {
    600 		DBG(DBG_LIB_MSIQ, dip,
    601 		    "px_lib_msiq_init: Contig alloc failed\n");
    602 
    603 		return (DDI_FAILURE);
    604 	}
    605 
    606 	for (i = 0; i < msiq_state_p->msiq_cnt; i++) {
    607 		msiq_state_p->msiq_p[i].msiq_base_p = (msiqhead_t *)
    608 		    ((caddr_t)msiq_state_p->msiq_buf_p + (i * msiq_size));
    609 
    610 		ra = (r_addr_t)va_to_pa((caddr_t)msiq_state_p->msiq_buf_p +
    611 		    (i * msiq_size));
    612 
    613 		if ((ret = hvio_msiq_conf(DIP_TO_HANDLE(dip),
    614 		    (i + msiq_state_p->msiq_1st_msiq_id),
    615 		    ra, msiq_state_p->msiq_rec_cnt)) != H_EOK) {
    616 			DBG(DBG_LIB_MSIQ, dip,
    617 			    "hvio_msiq_conf failed, ret 0x%lx\n", ret);
    618 			err = DDI_FAILURE;
    619 			break;
    620 		}
    621 
    622 		if ((err = px_lib_msiq_info(dip,
    623 		    (i + msiq_state_p->msiq_1st_msiq_id),
    624 		    &ra, &rec_cnt)) != DDI_SUCCESS) {
    625 			DBG(DBG_LIB_MSIQ, dip,
    626 			    "px_lib_msiq_info failed, ret 0x%x\n", err);
    627 			err = DDI_FAILURE;
    628 			break;
    629 		}
    630 
    631 		DBG(DBG_LIB_MSIQ, dip,
    632 		    "px_lib_msiq_init: ra 0x%p rec_cnt 0x%x\n", ra, rec_cnt);
    633 	}
    634 
    635 	return (err);
    636 }
    637 
    638 /*ARGSUSED*/
    639 int
    640 px_lib_msiq_fini(dev_info_t *dip)
    641 {
    642 	px_t		*px_p = DIP_TO_STATE(dip);
    643 	px_msiq_state_t	*msiq_state_p = &px_p->px_ib_p->ib_msiq_state;
    644 	size_t		msiq_size;
    645 
    646 	DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_fini: dip 0x%p\n", dip);
    647 	msiq_size = msiq_state_p->msiq_rec_cnt * sizeof (msiq_rec_t);
    648 
    649 	if (msiq_state_p->msiq_buf_p != NULL)
    650 		contig_mem_free(msiq_state_p->msiq_buf_p,
    651 		    msiq_state_p->msiq_cnt * msiq_size);
    652 
    653 	return (DDI_SUCCESS);
    654 }
    655 
    656 /*ARGSUSED*/
    657 int
    658 px_lib_msiq_info(dev_info_t *dip, msiqid_t msiq_id, r_addr_t *ra_p,
    659     uint_t *msiq_rec_cnt_p)
    660 {
    661 	uint64_t	ret;
    662 
    663 	DBG(DBG_LIB_MSIQ, dip, "px_msiq_info: dip 0x%p msiq_id 0x%x\n",
    664 	    dip, msiq_id);
    665 
    666 	if ((ret = hvio_msiq_info(DIP_TO_HANDLE(dip),
    667 	    msiq_id, ra_p, msiq_rec_cnt_p)) != H_EOK) {
    668 		DBG(DBG_LIB_MSIQ, dip,
    669 		    "hvio_msiq_info failed, ret 0x%lx\n", ret);
    670 		return (DDI_FAILURE);
    671 	}
    672 
    673 	DBG(DBG_LIB_MSIQ, dip, "px_msiq_info: ra_p 0x%p msiq_rec_cnt 0x%x\n",
    674 	    ra_p, *msiq_rec_cnt_p);
    675 
    676 	return (DDI_SUCCESS);
    677 }
    678 
    679 /*ARGSUSED*/
    680 int
    681 px_lib_msiq_getvalid(dev_info_t *dip, msiqid_t msiq_id,
    682     pci_msiq_valid_state_t *msiq_valid_state)
    683 {
    684 	uint64_t	ret;
    685 
    686 	DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_getvalid: dip 0x%p msiq_id 0x%x\n",
    687 	    dip, msiq_id);
    688 
    689 	if ((ret = hvio_msiq_getvalid(DIP_TO_HANDLE(dip),
    690 	    msiq_id, msiq_valid_state)) != H_EOK) {
    691 		DBG(DBG_LIB_MSIQ, dip,
    692 		    "hvio_msiq_getvalid failed, ret 0x%lx\n", ret);
    693 		return (DDI_FAILURE);
    694 	}
    695 
    696 	DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_getvalid: msiq_valid_state 0x%x\n",
    697 	    *msiq_valid_state);
    698 
    699 	return (DDI_SUCCESS);
    700 }
    701 
    702 /*ARGSUSED*/
    703 int
    704 px_lib_msiq_setvalid(dev_info_t *dip, msiqid_t msiq_id,
    705     pci_msiq_valid_state_t msiq_valid_state)
    706 {
    707 	uint64_t	ret;
    708 
    709 	DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_setvalid: dip 0x%p msiq_id 0x%x "
    710 	    "msiq_valid_state 0x%x\n", dip, msiq_id, msiq_valid_state);
    711 
    712 	if ((ret = hvio_msiq_setvalid(DIP_TO_HANDLE(dip),
    713 	    msiq_id, msiq_valid_state)) != H_EOK) {
    714 		DBG(DBG_LIB_MSIQ, dip,
    715 		    "hvio_msiq_setvalid failed, ret 0x%lx\n", ret);
    716 		return (DDI_FAILURE);
    717 	}
    718 
    719 	return (DDI_SUCCESS);
    720 }
    721 
    722 /*ARGSUSED*/
    723 int
    724 px_lib_msiq_getstate(dev_info_t *dip, msiqid_t msiq_id,
    725     pci_msiq_state_t *msiq_state)
    726 {
    727 	uint64_t	ret;
    728 
    729 	DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_getstate: dip 0x%p msiq_id 0x%x\n",
    730 	    dip, msiq_id);
    731 
    732 	if ((ret = hvio_msiq_getstate(DIP_TO_HANDLE(dip),
    733 	    msiq_id, msiq_state)) != H_EOK) {
    734 		DBG(DBG_LIB_MSIQ, dip,
    735 		    "hvio_msiq_getstate failed, ret 0x%lx\n", ret);
    736 		return (DDI_FAILURE);
    737 	}
    738 
    739 	DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_getstate: msiq_state 0x%x\n",
    740 	    *msiq_state);
    741 
    742 	return (DDI_SUCCESS);
    743 }
    744 
    745 /*ARGSUSED*/
    746 int
    747 px_lib_msiq_setstate(dev_info_t *dip, msiqid_t msiq_id,
    748     pci_msiq_state_t msiq_state)
    749 {
    750 	uint64_t	ret;
    751 
    752 	DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_setstate: dip 0x%p msiq_id 0x%x "
    753 	    "msiq_state 0x%x\n", dip, msiq_id, msiq_state);
    754 
    755 	if ((ret = hvio_msiq_setstate(DIP_TO_HANDLE(dip),
    756 	    msiq_id, msiq_state)) != H_EOK) {
    757 		DBG(DBG_LIB_MSIQ, dip,
    758 		    "hvio_msiq_setstate failed, ret 0x%lx\n", ret);
    759 		return (DDI_FAILURE);
    760 	}
    761 
    762 	return (DDI_SUCCESS);
    763 }
    764 
    765 /*ARGSUSED*/
    766 int
    767 px_lib_msiq_gethead(dev_info_t *dip, msiqid_t msiq_id,
    768     msiqhead_t *msiq_head_p)
    769 {
    770 	uint64_t	ret;
    771 
    772 	DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_gethead: dip 0x%p msiq_id 0x%x\n",
    773 	    dip, msiq_id);
    774 
    775 	if ((ret = hvio_msiq_gethead(DIP_TO_HANDLE(dip),
    776 	    msiq_id, msiq_head_p)) != H_EOK) {
    777 		DBG(DBG_LIB_MSIQ, dip,
    778 		    "hvio_msiq_gethead failed, ret 0x%lx\n", ret);
    779 		return (DDI_FAILURE);
    780 	}
    781 
    782 	*msiq_head_p =  (*msiq_head_p / sizeof (msiq_rec_t));
    783 
    784 	DBG(DBG_LIB_MSIQ, dip, "px_msiq_gethead: msiq_head 0x%x\n",
    785 	    *msiq_head_p);
    786 
    787 	return (DDI_SUCCESS);
    788 }
    789 
    790 /*ARGSUSED*/
    791 int
    792 px_lib_msiq_sethead(dev_info_t *dip, msiqid_t msiq_id,
    793     msiqhead_t msiq_head)
    794 {
    795 	uint64_t	ret;
    796 
    797 	DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_sethead: dip 0x%p msiq_id 0x%x "
    798 	    "msiq_head 0x%x\n", dip, msiq_id, msiq_head);
    799 
    800 	if ((ret = hvio_msiq_sethead(DIP_TO_HANDLE(dip),
    801 	    msiq_id, msiq_head * sizeof (msiq_rec_t))) != H_EOK) {
    802 		DBG(DBG_LIB_MSIQ, dip,
    803 		    "hvio_msiq_sethead failed, ret 0x%lx\n", ret);
    804 		return (DDI_FAILURE);
    805 	}
    806 
    807 	return (DDI_SUCCESS);
    808 }
    809 
    810 /*ARGSUSED*/
    811 int
    812 px_lib_msiq_gettail(dev_info_t *dip, msiqid_t msiq_id,
    813     msiqtail_t *msiq_tail_p)
    814 {
    815 	uint64_t	ret;
    816 
    817 	DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_gettail: dip 0x%p msiq_id 0x%x\n",
    818 	    dip, msiq_id);
    819 
    820 	if ((ret = hvio_msiq_gettail(DIP_TO_HANDLE(dip),
    821 	    msiq_id, msiq_tail_p)) != H_EOK) {
    822 		DBG(DBG_LIB_MSIQ, dip,
    823 		    "hvio_msiq_gettail failed, ret 0x%lx\n", ret);
    824 		return (DDI_FAILURE);
    825 	}
    826 
    827 	*msiq_tail_p =  (*msiq_tail_p / sizeof (msiq_rec_t));
    828 	DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_gettail: msiq_tail 0x%x\n",
    829 	    *msiq_tail_p);
    830 
    831 	return (DDI_SUCCESS);
    832 }
    833 
    834 /*ARGSUSED*/
    835 void
    836 px_lib_get_msiq_rec(dev_info_t *dip, msiqhead_t *msiq_head_p,
    837     msiq_rec_t *msiq_rec_p)
    838 {
    839 	msiq_rec_t	*curr_msiq_rec_p = (msiq_rec_t *)msiq_head_p;
    840 
    841 	DBG(DBG_LIB_MSIQ, dip, "px_lib_get_msiq_rec: dip 0x%p\n", dip);
    842 
    843 	if (!curr_msiq_rec_p->msiq_rec_type) {
    844 		/* Set msiq_rec_type to zero */
    845 		msiq_rec_p->msiq_rec_type = 0;
    846 
    847 		return;
    848 	}
    849 
    850 	*msiq_rec_p = *curr_msiq_rec_p;
    851 }
    852 
    853 /*ARGSUSED*/
    854 void
    855 px_lib_clr_msiq_rec(dev_info_t *dip, msiqhead_t *msiq_head_p)
    856 {
    857 	msiq_rec_t	*curr_msiq_rec_p = (msiq_rec_t *)msiq_head_p;
    858 
    859 	DBG(DBG_LIB_MSIQ, dip, "px_lib_clr_msiq_rec: dip 0x%p\n", dip);
    860 
    861 	/* Zero out msiq_rec_type field */
    862 	curr_msiq_rec_p->msiq_rec_type  = 0;
    863 }
    864 
    865 /*
    866  * MSI Functions:
    867  */
    868 
    869 /*ARGSUSED*/
    870 int
    871 px_lib_msi_init(dev_info_t *dip)
    872 {
    873 	DBG(DBG_LIB_MSI, dip, "px_lib_msi_init: dip 0x%p\n", dip);
    874 
    875 	/* Noop */
    876 	return (DDI_SUCCESS);
    877 }
    878 
    879 /*ARGSUSED*/
    880 int
    881 px_lib_msi_getmsiq(dev_info_t *dip, msinum_t msi_num,
    882     msiqid_t *msiq_id)
    883 {
    884 	uint64_t	ret;
    885 
    886 	DBG(DBG_LIB_MSI, dip, "px_lib_msi_getmsiq: dip 0x%p msi_num 0x%x\n",
    887 	    dip, msi_num);
    888 
    889 	if ((ret = hvio_msi_getmsiq(DIP_TO_HANDLE(dip),
    890 	    msi_num, msiq_id)) != H_EOK) {
    891 		DBG(DBG_LIB_MSI, dip,
    892 		    "hvio_msi_getmsiq failed, ret 0x%lx\n", ret);
    893 		return (DDI_FAILURE);
    894 	}
    895 
    896 	DBG(DBG_LIB_MSI, dip, "px_lib_msi_getmsiq: msiq_id 0x%x\n",
    897 	    *msiq_id);
    898 
    899 	return (DDI_SUCCESS);
    900 }
    901 
    902 /*ARGSUSED*/
    903 int
    904 px_lib_msi_setmsiq(dev_info_t *dip, msinum_t msi_num,
    905     msiqid_t msiq_id, msi_type_t msitype)
    906 {
    907 	uint64_t	ret;
    908 
    909 	DBG(DBG_LIB_MSI, dip, "px_lib_msi_setmsiq: dip 0x%p msi_num 0x%x "
    910 	    "msq_id 0x%x\n", dip, msi_num, msiq_id);
    911 
    912 	if ((ret = hvio_msi_setmsiq(DIP_TO_HANDLE(dip),
    913 	    msi_num, msiq_id, msitype)) != H_EOK) {
    914 		DBG(DBG_LIB_MSI, dip,
    915 		    "hvio_msi_setmsiq failed, ret 0x%lx\n", ret);
    916 		return (DDI_FAILURE);
    917 	}
    918 
    919 	return (DDI_SUCCESS);
    920 }
    921 
    922 /*ARGSUSED*/
    923 int
    924 px_lib_msi_getvalid(dev_info_t *dip, msinum_t msi_num,
    925     pci_msi_valid_state_t *msi_valid_state)
    926 {
    927 	uint64_t	ret;
    928 
    929 	DBG(DBG_LIB_MSI, dip, "px_lib_msi_getvalid: dip 0x%p msi_num 0x%x\n",
    930 	    dip, msi_num);
    931 
    932 	if ((ret = hvio_msi_getvalid(DIP_TO_HANDLE(dip),
    933 	    msi_num, msi_valid_state)) != H_EOK) {
    934 		DBG(DBG_LIB_MSI, dip,
    935 		    "hvio_msi_getvalid failed, ret 0x%lx\n", ret);
    936 		return (DDI_FAILURE);
    937 	}
    938 
    939 	DBG(DBG_LIB_MSI, dip, "px_lib_msi_getvalid: msiq_id 0x%x\n",
    940 	    *msi_valid_state);
    941 
    942 	return (DDI_SUCCESS);
    943 }
    944 
    945 /*ARGSUSED*/
    946 int
    947 px_lib_msi_setvalid(dev_info_t *dip, msinum_t msi_num,
    948     pci_msi_valid_state_t msi_valid_state)
    949 {
    950 	uint64_t	ret;
    951 
    952 	DBG(DBG_LIB_MSI, dip, "px_lib_msi_setvalid: dip 0x%p msi_num 0x%x "
    953 	    "msi_valid_state 0x%x\n", dip, msi_num, msi_valid_state);
    954 
    955 	if ((ret = hvio_msi_setvalid(DIP_TO_HANDLE(dip),
    956 	    msi_num, msi_valid_state)) != H_EOK) {
    957 		DBG(DBG_LIB_MSI, dip,
    958 		    "hvio_msi_setvalid failed, ret 0x%lx\n", ret);
    959 		return (DDI_FAILURE);
    960 	}
    961 
    962 	return (DDI_SUCCESS);
    963 }
    964 
    965 /*ARGSUSED*/
    966 int
    967 px_lib_msi_getstate(dev_info_t *dip, msinum_t msi_num,
    968     pci_msi_state_t *msi_state)
    969 {
    970 	uint64_t	ret;
    971 
    972 	DBG(DBG_LIB_MSI, dip, "px_lib_msi_getstate: dip 0x%p msi_num 0x%x\n",
    973 	    dip, msi_num);
    974 
    975 	if ((ret = hvio_msi_getstate(DIP_TO_HANDLE(dip),
    976 	    msi_num, msi_state)) != H_EOK) {
    977 		DBG(DBG_LIB_MSI, dip,
    978 		    "hvio_msi_getstate failed, ret 0x%lx\n", ret);
    979 		return (DDI_FAILURE);
    980 	}
    981 
    982 	DBG(DBG_LIB_MSI, dip, "px_lib_msi_getstate: msi_state 0x%x\n",
    983 	    *msi_state);
    984 
    985 	return (DDI_SUCCESS);
    986 }
    987 
    988 /*ARGSUSED*/
    989 int
    990 px_lib_msi_setstate(dev_info_t *dip, msinum_t msi_num,
    991     pci_msi_state_t msi_state)
    992 {
    993 	uint64_t	ret;
    994 
    995 	DBG(DBG_LIB_MSI, dip, "px_lib_msi_setstate: dip 0x%p msi_num 0x%x "
    996 	    "msi_state 0x%x\n", dip, msi_num, msi_state);
    997 
    998 	if ((ret = hvio_msi_setstate(DIP_TO_HANDLE(dip),
    999 	    msi_num, msi_state)) != H_EOK) {
   1000 		DBG(DBG_LIB_MSI, dip,
   1001 		    "hvio_msi_setstate failed, ret 0x%lx\n", ret);
   1002 		return (DDI_FAILURE);
   1003 	}
   1004 
   1005 	return (DDI_SUCCESS);
   1006 }
   1007 
   1008 /*
   1009  * MSG Functions:
   1010  */
   1011 
   1012 /*ARGSUSED*/
   1013 int
   1014 px_lib_msg_getmsiq(dev_info_t *dip, pcie_msg_type_t msg_type,
   1015     msiqid_t *msiq_id)
   1016 {
   1017 	uint64_t	ret;
   1018 
   1019 	DBG(DBG_LIB_MSG, dip, "px_lib_msg_getmsiq: dip 0x%p msg_type 0x%x\n",
   1020 	    dip, msg_type);
   1021 
   1022 	if ((ret = hvio_msg_getmsiq(DIP_TO_HANDLE(dip),
   1023 	    msg_type, msiq_id)) != H_EOK) {
   1024 		DBG(DBG_LIB_MSG, dip,
   1025 		    "hvio_msg_getmsiq failed, ret 0x%lx\n", ret);
   1026 		return (DDI_FAILURE);
   1027 	}
   1028 
   1029 	DBG(DBG_LIB_MSI, dip, "px_lib_msg_getmsiq: msiq_id 0x%x\n",
   1030 	    *msiq_id);
   1031 
   1032 	return (DDI_SUCCESS);
   1033 }
   1034 
   1035 /*ARGSUSED*/
   1036 int
   1037 px_lib_msg_setmsiq(dev_info_t *dip, pcie_msg_type_t msg_type,
   1038     msiqid_t msiq_id)
   1039 {
   1040 	uint64_t	ret;
   1041 
   1042 	DBG(DBG_LIB_MSG, dip, "px_lib_msg_setmsiq: dip 0x%p msg_type 0x%x "
   1043 	    "msq_id 0x%x\n", dip, msg_type, msiq_id);
   1044 
   1045 	if ((ret = hvio_msg_setmsiq(DIP_TO_HANDLE(dip),
   1046 	    msg_type, msiq_id)) != H_EOK) {
   1047 		DBG(DBG_LIB_MSG, dip,
   1048 		    "hvio_msg_setmsiq failed, ret 0x%lx\n", ret);
   1049 		return (DDI_FAILURE);
   1050 	}
   1051 
   1052 	return (DDI_SUCCESS);
   1053 }
   1054 
   1055 /*ARGSUSED*/
   1056 int
   1057 px_lib_msg_getvalid(dev_info_t *dip, pcie_msg_type_t msg_type,
   1058     pcie_msg_valid_state_t *msg_valid_state)
   1059 {
   1060 	uint64_t	ret;
   1061 
   1062 	DBG(DBG_LIB_MSG, dip, "px_lib_msg_getvalid: dip 0x%p msg_type 0x%x\n",
   1063 	    dip, msg_type);
   1064 
   1065 	if ((ret = hvio_msg_getvalid(DIP_TO_HANDLE(dip), msg_type,
   1066 	    msg_valid_state)) != H_EOK) {
   1067 		DBG(DBG_LIB_MSG, dip,
   1068 		    "hvio_msg_getvalid failed, ret 0x%lx\n", ret);
   1069 		return (DDI_FAILURE);
   1070 	}
   1071 
   1072 	DBG(DBG_LIB_MSI, dip, "px_lib_msg_getvalid: msg_valid_state 0x%x\n",
   1073 	    *msg_valid_state);
   1074 
   1075 	return (DDI_SUCCESS);
   1076 }
   1077 
   1078 /*ARGSUSED*/
   1079 int
   1080 px_lib_msg_setvalid(dev_info_t *dip, pcie_msg_type_t msg_type,
   1081     pcie_msg_valid_state_t msg_valid_state)
   1082 {
   1083 	uint64_t	ret;
   1084 
   1085 	DBG(DBG_LIB_MSG, dip, "px_lib_msg_setvalid: dip 0x%p msg_type 0x%x "
   1086 	    "msg_valid_state 0x%x\n", dip, msg_type, msg_valid_state);
   1087 
   1088 	if ((ret = hvio_msg_setvalid(DIP_TO_HANDLE(dip), msg_type,
   1089 	    msg_valid_state)) != H_EOK) {
   1090 		DBG(DBG_LIB_MSG, dip,
   1091 		    "hvio_msg_setvalid failed, ret 0x%lx\n", ret);
   1092 		return (DDI_FAILURE);
   1093 	}
   1094 
   1095 	return (DDI_SUCCESS);
   1096 }
   1097 
   1098 /*
   1099  * Suspend/Resume Functions:
   1100  * Currently unsupported by hypervisor and all functions are noops.
   1101  */
   1102 /*ARGSUSED*/
   1103 int
   1104 px_lib_suspend(dev_info_t *dip)
   1105 {
   1106 	DBG(DBG_ATTACH, dip, "px_lib_suspend: Not supported\n");
   1107 
   1108 	/* Not supported */
   1109 	return (DDI_FAILURE);
   1110 }
   1111 
   1112 /*ARGSUSED*/
   1113 void
   1114 px_lib_resume(dev_info_t *dip)
   1115 {
   1116 	DBG(DBG_ATTACH, dip, "px_lib_resume: Not supported\n");
   1117 
   1118 	/* Noop */
   1119 }
   1120 
   1121 /*
   1122  * Misc Functions:
   1123  * Currently unsupported by hypervisor and all functions are noops.
   1124  */
   1125 /*ARGSUSED*/
   1126 static int
   1127 px_lib_config_get(dev_info_t *dip, pci_device_t bdf, pci_config_offset_t off,
   1128     uint8_t size, pci_cfg_data_t *data_p)
   1129 {
   1130 	uint64_t	ret;
   1131 
   1132 	DBG(DBG_LIB_CFG, dip, "px_lib_config_get: dip 0x%p, bdf 0x%llx "
   1133 	    "off 0x%x size 0x%x\n", dip, bdf, off, size);
   1134 
   1135 	if ((ret = hvio_config_get(DIP_TO_HANDLE(dip), bdf, off,
   1136 	    size, data_p)) != H_EOK) {
   1137 		DBG(DBG_LIB_CFG, dip,
   1138 		    "hvio_config_get failed, ret 0x%lx\n", ret);
   1139 		return (DDI_FAILURE);
   1140 	}
   1141 	DBG(DBG_LIB_CFG, dip, "px_config_get: data 0x%x\n", data_p->dw);
   1142 
   1143 	return (DDI_SUCCESS);
   1144 }
   1145 
   1146 /*ARGSUSED*/
   1147 static int
   1148 px_lib_config_put(dev_info_t *dip, pci_device_t bdf, pci_config_offset_t off,
   1149     uint8_t size, pci_cfg_data_t data)
   1150 {
   1151 	uint64_t	ret;
   1152 
   1153 	DBG(DBG_LIB_CFG, dip, "px_lib_config_put: dip 0x%p, bdf 0x%llx "
   1154 	    "off 0x%x size 0x%x data 0x%llx\n", dip, bdf, off, size, data.qw);
   1155 
   1156 	if ((ret = hvio_config_put(DIP_TO_HANDLE(dip), bdf, off,
   1157 	    size, data)) != H_EOK) {
   1158 		DBG(DBG_LIB_CFG, dip,
   1159 		    "hvio_config_put failed, ret 0x%lx\n", ret);
   1160 		return (DDI_FAILURE);
   1161 	}
   1162 
   1163 	return (DDI_SUCCESS);
   1164 }
   1165 
   1166 static uint32_t
   1167 px_pci_config_get(ddi_acc_impl_t *handle, uint32_t *addr, int size)
   1168 {
   1169 	px_config_acc_pvt_t *px_pvt = (px_config_acc_pvt_t *)
   1170 	    handle->ahi_common.ah_bus_private;
   1171 	uint32_t pci_dev_addr = px_pvt->raddr;
   1172 	uint32_t vaddr = px_pvt->vaddr;
   1173 	uint16_t off = (uint16_t)(uintptr_t)(addr - vaddr) & 0xfff;
   1174 	uint64_t rdata = 0;
   1175 
   1176 	if (px_lib_config_get(px_pvt->dip, pci_dev_addr, off,
   1177 	    size, (pci_cfg_data_t *)&rdata) != DDI_SUCCESS)
   1178 		/* XXX update error kstats */
   1179 		return (0xffffffff);
   1180 	return ((uint32_t)rdata);
   1181 }
   1182 
   1183 static void
   1184 px_pci_config_put(ddi_acc_impl_t *handle, uint32_t *addr,
   1185 		int size, pci_cfg_data_t wdata)
   1186 {
   1187 	px_config_acc_pvt_t *px_pvt = (px_config_acc_pvt_t *)
   1188 	    handle->ahi_common.ah_bus_private;
   1189 	uint32_t pci_dev_addr = px_pvt->raddr;
   1190 	uint32_t vaddr = px_pvt->vaddr;
   1191 	uint16_t off = (uint16_t)(uintptr_t)(addr - vaddr) & 0xfff;
   1192 
   1193 	if (px_lib_config_put(px_pvt->dip, pci_dev_addr, off,
   1194 	    size, wdata) != DDI_SUCCESS) {
   1195 		/*EMPTY*/
   1196 		/* XXX update error kstats */
   1197 	}
   1198 }
   1199 
   1200 static uint8_t
   1201 px_pci_config_get8(ddi_acc_impl_t *handle, uint8_t *addr)
   1202 {
   1203 	return ((uint8_t)px_pci_config_get(handle, (uint32_t *)addr, 1));
   1204 }
   1205 
   1206 static uint16_t
   1207 px_pci_config_get16(ddi_acc_impl_t *handle, uint16_t *addr)
   1208 {
   1209 	return ((uint16_t)px_pci_config_get(handle, (uint32_t *)addr, 2));
   1210 }
   1211 
   1212 static uint32_t
   1213 px_pci_config_get32(ddi_acc_impl_t *handle, uint32_t *addr)
   1214 {
   1215 	return ((uint32_t)px_pci_config_get(handle, (uint32_t *)addr, 4));
   1216 }
   1217 
   1218 static uint64_t
   1219 px_pci_config_get64(ddi_acc_impl_t *handle, uint64_t *addr)
   1220 {
   1221 	uint32_t rdatah, rdatal;
   1222 
   1223 	rdatal = (uint32_t)px_pci_config_get(handle, (uint32_t *)addr, 4);
   1224 	rdatah = (uint32_t)px_pci_config_get(handle,
   1225 	    (uint32_t *)((char *)addr+4), 4);
   1226 	return (((uint64_t)rdatah << 32) | rdatal);
   1227 }
   1228 
   1229 static void
   1230 px_pci_config_put8(ddi_acc_impl_t *handle, uint8_t *addr, uint8_t data)
   1231 {
   1232 	pci_cfg_data_t wdata = { 0 };
   1233 
   1234 	wdata.qw = (uint8_t)data;
   1235 	px_pci_config_put(handle, (uint32_t *)addr, 1, wdata);
   1236 }
   1237 
   1238 static void
   1239 px_pci_config_put16(ddi_acc_impl_t *handle, uint16_t *addr, uint16_t data)
   1240 {
   1241 	pci_cfg_data_t wdata = { 0 };
   1242 
   1243 	wdata.qw = (uint16_t)data;
   1244 	px_pci_config_put(handle, (uint32_t *)addr, 2, wdata);
   1245 }
   1246 
   1247 static void
   1248 px_pci_config_put32(ddi_acc_impl_t *handle, uint32_t *addr, uint32_t data)
   1249 {
   1250 	pci_cfg_data_t wdata = { 0 };
   1251 
   1252 	wdata.qw = (uint32_t)data;
   1253 	px_pci_config_put(handle, (uint32_t *)addr, 4, wdata);
   1254 }
   1255 
   1256 static void
   1257 px_pci_config_put64(ddi_acc_impl_t *handle, uint64_t *addr, uint64_t data)
   1258 {
   1259 	pci_cfg_data_t wdata = { 0 };
   1260 
   1261 	wdata.qw = (uint32_t)(data & 0xffffffff);
   1262 	px_pci_config_put(handle, (uint32_t *)addr, 4, wdata);
   1263 	wdata.qw = (uint32_t)((data >> 32) & 0xffffffff);
   1264 	px_pci_config_put(handle, (uint32_t *)((char *)addr+4), 4, wdata);
   1265 }
   1266 
   1267 static void
   1268 px_pci_config_rep_get8(ddi_acc_impl_t *handle, uint8_t *host_addr,
   1269 			uint8_t *dev_addr, size_t repcount, uint_t flags)
   1270 {
   1271 	if (flags == DDI_DEV_AUTOINCR)
   1272 		for (; repcount; repcount--)
   1273 			*host_addr++ = px_pci_config_get8(handle, dev_addr++);
   1274 	else
   1275 		for (; repcount; repcount--)
   1276 			*host_addr++ = px_pci_config_get8(handle, dev_addr);
   1277 }
   1278 
   1279 /*
   1280  * Function to rep read 16 bit data off the PCI configuration space behind
   1281  * the 21554's host interface.
   1282  */
   1283 static void
   1284 px_pci_config_rep_get16(ddi_acc_impl_t *handle, uint16_t *host_addr,
   1285 			uint16_t *dev_addr, size_t repcount, uint_t flags)
   1286 {
   1287 	if (flags == DDI_DEV_AUTOINCR)
   1288 		for (; repcount; repcount--)
   1289 			*host_addr++ = px_pci_config_get16(handle, dev_addr++);
   1290 	else
   1291 		for (; repcount; repcount--)
   1292 			*host_addr++ = px_pci_config_get16(handle, dev_addr);
   1293 }
   1294 
   1295 /*
   1296  * Function to rep read 32 bit data off the PCI configuration space behind
   1297  * the 21554's host interface.
   1298  */
   1299 static void
   1300 px_pci_config_rep_get32(ddi_acc_impl_t *handle, uint32_t *host_addr,
   1301 			uint32_t *dev_addr, size_t repcount, uint_t flags)
   1302 {
   1303 	if (flags == DDI_DEV_AUTOINCR)
   1304 		for (; repcount; repcount--)
   1305 			*host_addr++ = px_pci_config_get32(handle, dev_addr++);
   1306 	else
   1307 		for (; repcount; repcount--)
   1308 			*host_addr++ = px_pci_config_get32(handle, dev_addr);
   1309 }
   1310 
   1311 /*
   1312  * Function to rep read 64 bit data off the PCI configuration space behind
   1313  * the 21554's host interface.
   1314  */
   1315 static void
   1316 px_pci_config_rep_get64(ddi_acc_impl_t *handle, uint64_t *host_addr,
   1317 			uint64_t *dev_addr, size_t repcount, uint_t flags)
   1318 {
   1319 	if (flags == DDI_DEV_AUTOINCR)
   1320 		for (; repcount; repcount--)
   1321 			*host_addr++ = px_pci_config_get64(handle, dev_addr++);
   1322 	else
   1323 		for (; repcount; repcount--)
   1324 			*host_addr++ = px_pci_config_get64(handle, dev_addr);
   1325 }
   1326 
   1327 /*
   1328  * Function to rep write 8 bit data into the PCI configuration space behind
   1329  * the 21554's host interface.
   1330  */
   1331 static void
   1332 px_pci_config_rep_put8(ddi_acc_impl_t *handle, uint8_t *host_addr,
   1333 			uint8_t *dev_addr, size_t repcount, uint_t flags)
   1334 {
   1335 	if (flags == DDI_DEV_AUTOINCR)
   1336 		for (; repcount; repcount--)
   1337 			px_pci_config_put8(handle, dev_addr++, *host_addr++);
   1338 	else
   1339 		for (; repcount; repcount--)
   1340 			px_pci_config_put8(handle, dev_addr, *host_addr++);
   1341 }
   1342 
   1343 /*
   1344  * Function to rep write 16 bit data into the PCI configuration space behind
   1345  * the 21554's host interface.
   1346  */
   1347 static void
   1348 px_pci_config_rep_put16(ddi_acc_impl_t *handle, uint16_t *host_addr,
   1349 			uint16_t *dev_addr, size_t repcount, uint_t flags)
   1350 {
   1351 	if (flags == DDI_DEV_AUTOINCR)
   1352 		for (; repcount; repcount--)
   1353 			px_pci_config_put16(handle, dev_addr++, *host_addr++);
   1354 	else
   1355 		for (; repcount; repcount--)
   1356 			px_pci_config_put16(handle, dev_addr, *host_addr++);
   1357 }
   1358 
   1359 /*
   1360  * Function to rep write 32 bit data into the PCI configuration space behind
   1361  * the 21554's host interface.
   1362  */
   1363 static void
   1364 px_pci_config_rep_put32(ddi_acc_impl_t *handle, uint32_t *host_addr,
   1365 			uint32_t *dev_addr, size_t repcount, uint_t flags)
   1366 {
   1367 	if (flags == DDI_DEV_AUTOINCR)
   1368 		for (; repcount; repcount--)
   1369 			px_pci_config_put32(handle, dev_addr++, *host_addr++);
   1370 	else
   1371 		for (; repcount; repcount--)
   1372 			px_pci_config_put32(handle, dev_addr, *host_addr++);
   1373 }
   1374 
   1375 /*
   1376  * Function to rep write 64 bit data into the PCI configuration space behind
   1377  * the 21554's host interface.
   1378  */
   1379 static void
   1380 px_pci_config_rep_put64(ddi_acc_impl_t *handle, uint64_t *host_addr,
   1381 			uint64_t *dev_addr, size_t repcount, uint_t flags)
   1382 {
   1383 	if (flags == DDI_DEV_AUTOINCR)
   1384 		for (; repcount; repcount--)
   1385 			px_pci_config_put64(handle, dev_addr++, *host_addr++);
   1386 	else
   1387 		for (; repcount; repcount--)
   1388 			px_pci_config_put64(handle, dev_addr, *host_addr++);
   1389 }
   1390 
   1391 /*
   1392  * Provide a private access handle to route config access calls to Hypervisor.
   1393  * Beware: Do all error checking for config space accesses before calling
   1394  * this function. ie. do error checking from the calling function.
   1395  * Due to a lack of meaningful error code in DDI, the gauranteed return of
   1396  * DDI_SUCCESS from here makes the code organization readable/easier from
   1397  * the generic code.
   1398  */
   1399 /*ARGSUSED*/
   1400 int
   1401 px_lib_map_vconfig(dev_info_t *dip,
   1402 	ddi_map_req_t *mp, pci_config_offset_t off,
   1403 	pci_regspec_t *rp, caddr_t *addrp)
   1404 {
   1405 	int fmcap;
   1406 	ndi_err_t *errp;
   1407 	on_trap_data_t *otp;
   1408 	ddi_acc_hdl_t *hp;
   1409 	ddi_acc_impl_t *ap;
   1410 	uchar_t busnum;	/* bus number */
   1411 	uchar_t devnum;	/* device number */
   1412 	uchar_t funcnum; /* function number */
   1413 	px_config_acc_pvt_t *px_pvt;
   1414 
   1415 	hp = (ddi_acc_hdl_t *)mp->map_handlep;
   1416 	ap = (ddi_acc_impl_t *)hp->ah_platform_private;
   1417 
   1418 	/* Check for mapping teardown operation */
   1419 	if ((mp->map_op == DDI_MO_UNMAP) ||
   1420 	    (mp->map_op == DDI_MO_UNLOCK)) {
   1421 		/* free up memory allocated for the private access handle. */
   1422 		px_pvt = (px_config_acc_pvt_t *)hp->ah_bus_private;
   1423 		kmem_free((void *)px_pvt, sizeof (px_config_acc_pvt_t));
   1424 
   1425 		/* unmap operation of PCI IO/config space. */
   1426 		return (DDI_SUCCESS);
   1427 	}
   1428 
   1429 	fmcap = ddi_fm_capable(dip);
   1430 	if (DDI_FM_ACC_ERR_CAP(fmcap)) {
   1431 		errp = ((ddi_acc_impl_t *)hp)->ahi_err;
   1432 		otp = (on_trap_data_t *)errp->err_ontrap;
   1433 		otp->ot_handle = (void *)(hp);
   1434 		otp->ot_prot = OT_DATA_ACCESS;
   1435 		errp->err_status = DDI_FM_OK;
   1436 		errp->err_expected = DDI_FM_ERR_UNEXPECTED;
   1437 		errp->err_cf = px_err_cfg_hdl_check;
   1438 	}
   1439 
   1440 	ap->ahi_get8 = px_pci_config_get8;
   1441 	ap->ahi_get16 = px_pci_config_get16;
   1442 	ap->ahi_get32 = px_pci_config_get32;
   1443 	ap->ahi_get64 = px_pci_config_get64;
   1444 	ap->ahi_put8 = px_pci_config_put8;
   1445 	ap->ahi_put16 = px_pci_config_put16;
   1446 	ap->ahi_put32 = px_pci_config_put32;
   1447 	ap->ahi_put64 = px_pci_config_put64;
   1448 	ap->ahi_rep_get8 = px_pci_config_rep_get8;
   1449 	ap->ahi_rep_get16 = px_pci_config_rep_get16;
   1450 	ap->ahi_rep_get32 = px_pci_config_rep_get32;
   1451 	ap->ahi_rep_get64 = px_pci_config_rep_get64;
   1452 	ap->ahi_rep_put8 = px_pci_config_rep_put8;
   1453 	ap->ahi_rep_put16 = px_pci_config_rep_put16;
   1454 	ap->ahi_rep_put32 = px_pci_config_rep_put32;
   1455 	ap->ahi_rep_put64 = px_pci_config_rep_put64;
   1456 
   1457 	/* Initialize to default check/notify functions */
   1458 	ap->ahi_fault = 0;
   1459 	ap->ahi_fault_check = i_ddi_acc_fault_check;
   1460 	ap->ahi_fault_notify = i_ddi_acc_fault_notify;
   1461 
   1462 	/* allocate memory for our private handle */
   1463 	px_pvt = (px_config_acc_pvt_t *)
   1464 	    kmem_zalloc(sizeof (px_config_acc_pvt_t), KM_SLEEP);
   1465 	hp->ah_bus_private = (void *)px_pvt;
   1466 
   1467 	busnum = PCI_REG_BUS_G(rp->pci_phys_hi);
   1468 	devnum = PCI_REG_DEV_G(rp->pci_phys_hi);
   1469 	funcnum = PCI_REG_FUNC_G(rp->pci_phys_hi);
   1470 
   1471 	/* set up private data for use during IO routines */
   1472 
   1473 	/* addr needed by the HV APIs */
   1474 	px_pvt->raddr = busnum << 16 | devnum << 11 | funcnum << 8;
   1475 	/*
   1476 	 * Address that specifies the actual offset into the 256MB
   1477 	 * memory mapped configuration space, 4K per device.
   1478 	 * First 12bits form the offset into 4K config space.
   1479 	 * This address is only used during the IO routines to calculate
   1480 	 * the offset at which the transaction must be performed.
   1481 	 * Drivers bypassing DDI functions to access PCI config space will
   1482 	 * panic the system since the following is a bogus virtual address.
   1483 	 */
   1484 	px_pvt->vaddr = busnum << 20 | devnum << 15 | funcnum << 12 | off;
   1485 	px_pvt->dip = dip;
   1486 
   1487 	DBG(DBG_LIB_CFG, dip, "px_config_setup: raddr 0x%x, vaddr 0x%x\n",
   1488 	    px_pvt->raddr, px_pvt->vaddr);
   1489 	*addrp = (caddr_t)(uintptr_t)px_pvt->vaddr;
   1490 	return (DDI_SUCCESS);
   1491 }
   1492 
   1493 /*ARGSUSED*/
   1494 void
   1495 px_lib_map_attr_check(ddi_map_req_t *mp)
   1496 {
   1497 }
   1498 
   1499 /*
   1500  * px_lib_log_safeacc_err:
   1501  * Imitate a cpu/mem trap call when a peek/poke fails.
   1502  * This will initiate something similar to px_fm_callback.
   1503  */
   1504 static void
   1505 px_lib_log_safeacc_err(px_t *px_p, ddi_acc_handle_t handle, int fme_flag,
   1506     r_addr_t addr)
   1507 {
   1508 	uint32_t	addr_high, addr_low;
   1509 	pcie_req_id_t	bdf = PCIE_INVALID_BDF;
   1510 	pci_ranges_t	*ranges_p;
   1511 	int		range_len, i;
   1512 	ddi_acc_impl_t *hp = (ddi_acc_impl_t *)handle;
   1513 	ddi_fm_error_t derr;
   1514 
   1515 	derr.fme_status = DDI_FM_NONFATAL;
   1516 	derr.fme_version = DDI_FME_VERSION;
   1517 	derr.fme_flag = fme_flag;
   1518 	derr.fme_ena = fm_ena_generate(0, FM_ENA_FMT1);
   1519 	derr.fme_acc_handle = handle;
   1520 	if (hp)
   1521 		hp->ahi_err->err_expected = DDI_FM_ERR_EXPECTED;
   1522 
   1523 	addr_high = (uint32_t)(addr >> 32);
   1524 	addr_low = (uint32_t)addr;
   1525 
   1526 	/*
   1527 	 * Make sure this failed load came from this PCIe port.  Check by
   1528 	 * matching the upper 32 bits of the address with the ranges property.
   1529 	 */
   1530 	range_len = px_p->px_ranges_length / sizeof (pci_ranges_t);
   1531 	i = 0;
   1532 	for (ranges_p = px_p->px_ranges_p; i < range_len; i++, ranges_p++) {
   1533 		if (ranges_p->parent_high == addr_high) {
   1534 			switch (ranges_p->child_high & PCI_ADDR_MASK) {
   1535 			case PCI_ADDR_CONFIG:
   1536 				bdf = (pcie_req_id_t)(addr_low >> 12);
   1537 				break;
   1538 			default:
   1539 				bdf = PCIE_INVALID_BDF;
   1540 				break;
   1541 			}
   1542 			break;
   1543 		}
   1544 	}
   1545 
   1546 	px_rp_en_q(px_p, bdf, addr, NULL);
   1547 
   1548 	if (px_fm_enter(px_p) == DDI_SUCCESS) {
   1549 		(void) px_scan_fabric(px_p, px_p->px_dip, &derr);
   1550 		px_fm_exit(px_p);
   1551 	}
   1552 }
   1553 
   1554 
   1555 #ifdef  DEBUG
   1556 int	px_peekfault_cnt = 0;
   1557 int	px_pokefault_cnt = 0;
   1558 #endif  /* DEBUG */
   1559 
   1560 /*
   1561  * Do a safe write to a device.
   1562  *
   1563  * When this function is given a handle (cautious access), all errors are
   1564  * suppressed.
   1565  *
   1566  * When this function is not given a handle (poke), only Unsupported Request
   1567  * and Completer Abort errors are suppressed.
   1568  *
   1569  * In all cases, all errors are returned in the function return status.
   1570  */
   1571 
   1572 int
   1573 px_lib_ctlops_poke(dev_info_t *dip, dev_info_t *rdip,
   1574     peekpoke_ctlops_t *in_args)
   1575 {
   1576 	px_t *px_p = DIP_TO_STATE(dip);
   1577 	px_pec_t *pec_p = px_p->px_pec_p;
   1578 	ddi_acc_impl_t *hp = (ddi_acc_impl_t *)in_args->handle;
   1579 
   1580 	size_t repcount = in_args->repcount;
   1581 	size_t size = in_args->size;
   1582 	uintptr_t dev_addr = in_args->dev_addr;
   1583 	uintptr_t host_addr = in_args->host_addr;
   1584 
   1585 	int err	= DDI_SUCCESS;
   1586 	uint64_t hvio_poke_status;
   1587 	uint32_t wrt_stat;
   1588 
   1589 	r_addr_t ra;
   1590 	uint64_t pokeval;
   1591 	pcie_req_id_t bdf;
   1592 
   1593 	ra = (r_addr_t)va_to_pa((void *)dev_addr);
   1594 	for (; repcount; repcount--) {
   1595 
   1596 		switch (size) {
   1597 		case sizeof (uint8_t):
   1598 			pokeval = *(uint8_t *)host_addr;
   1599 			break;
   1600 		case sizeof (uint16_t):
   1601 			pokeval = *(uint16_t *)host_addr;
   1602 			break;
   1603 		case sizeof (uint32_t):
   1604 			pokeval = *(uint32_t *)host_addr;
   1605 			break;
   1606 		case sizeof (uint64_t):
   1607 			pokeval = *(uint64_t *)host_addr;
   1608 			break;
   1609 		default:
   1610 			DBG(DBG_MAP, px_p->px_dip,
   1611 			    "poke: invalid size %d passed\n", size);
   1612 			err = DDI_FAILURE;
   1613 			goto done;
   1614 		}
   1615 
   1616 		/*
   1617 		 * Grab pokefault mutex since hypervisor does not guarantee
   1618 		 * poke serialization.
   1619 		 */
   1620 		if (hp) {
   1621 			i_ndi_busop_access_enter(hp->ahi_common.ah_dip,
   1622 			    (ddi_acc_handle_t)hp);
   1623 			pec_p->pec_safeacc_type = DDI_FM_ERR_EXPECTED;
   1624 		} else {
   1625 			mutex_enter(&pec_p->pec_pokefault_mutex);
   1626 			pec_p->pec_safeacc_type = DDI_FM_ERR_POKE;
   1627 		}
   1628 
   1629 		if (pcie_get_bdf_from_dip(rdip, &bdf) != DDI_SUCCESS) {
   1630 			err = DDI_FAILURE;
   1631 			goto done;
   1632 		}
   1633 
   1634 		hvio_poke_status = hvio_poke(px_p->px_dev_hdl, ra, size,
   1635 		    pokeval, bdf << 8, &wrt_stat);
   1636 
   1637 		if ((hvio_poke_status != H_EOK) || (wrt_stat != H_EOK)) {
   1638 			err = DDI_FAILURE;
   1639 #ifdef  DEBUG
   1640 			px_pokefault_cnt++;
   1641 #endif
   1642 			/*
   1643 			 * For CAUTIOUS and POKE access, notify FMA to
   1644 			 * cleanup.  Imitate a cpu/mem trap call like in sun4u.
   1645 			 */
   1646 			px_lib_log_safeacc_err(px_p, (ddi_acc_handle_t)hp,
   1647 			    (hp ? DDI_FM_ERR_EXPECTED :
   1648 			    DDI_FM_ERR_POKE), ra);
   1649 
   1650 			pec_p->pec_ontrap_data = NULL;
   1651 			pec_p->pec_safeacc_type = DDI_FM_ERR_UNEXPECTED;
   1652 			if (hp) {
   1653 				i_ndi_busop_access_exit(hp->ahi_common.ah_dip,
   1654 				    (ddi_acc_handle_t)hp);
   1655 			} else {
   1656 				mutex_exit(&pec_p->pec_pokefault_mutex);
   1657 			}
   1658 			goto done;
   1659 		}
   1660 
   1661 		pec_p->pec_ontrap_data = NULL;
   1662 		pec_p->pec_safeacc_type = DDI_FM_ERR_UNEXPECTED;
   1663 		if (hp) {
   1664 			i_ndi_busop_access_exit(hp->ahi_common.ah_dip,
   1665 			    (ddi_acc_handle_t)hp);
   1666 		} else {
   1667 			mutex_exit(&pec_p->pec_pokefault_mutex);
   1668 		}
   1669 
   1670 		host_addr += size;
   1671 
   1672 		if (in_args->flags == DDI_DEV_AUTOINCR) {
   1673 			dev_addr += size;
   1674 			ra = (r_addr_t)va_to_pa((void *)dev_addr);
   1675 		}
   1676 	}
   1677 
   1678 done:
   1679 	return (err);
   1680 }
   1681 
   1682 
   1683 /*ARGSUSED*/
   1684 int
   1685 px_lib_ctlops_peek(dev_info_t *dip, dev_info_t *rdip,
   1686     peekpoke_ctlops_t *in_args, void *result)
   1687 {
   1688 	px_t *px_p = DIP_TO_STATE(dip);
   1689 	px_pec_t *pec_p = px_p->px_pec_p;
   1690 	ddi_acc_impl_t *hp = (ddi_acc_impl_t *)in_args->handle;
   1691 
   1692 	size_t repcount = in_args->repcount;
   1693 	uintptr_t dev_addr = in_args->dev_addr;
   1694 	uintptr_t host_addr = in_args->host_addr;
   1695 
   1696 	r_addr_t ra;
   1697 	uint32_t read_status;
   1698 	uint64_t hvio_peek_status;
   1699 	uint64_t peekval;
   1700 	int err = DDI_SUCCESS;
   1701 
   1702 	result = (void *)in_args->host_addr;
   1703 
   1704 	ra = (r_addr_t)va_to_pa((void *)dev_addr);
   1705 	for (; repcount; repcount--) {
   1706 
   1707 		/* Lock pokefault mutex so read doesn't mask a poke fault. */
   1708 		if (hp) {
   1709 			i_ndi_busop_access_enter(hp->ahi_common.ah_dip,
   1710 			    (ddi_acc_handle_t)hp);
   1711 			pec_p->pec_safeacc_type = DDI_FM_ERR_EXPECTED;
   1712 		} else {
   1713 			mutex_enter(&pec_p->pec_pokefault_mutex);
   1714 			pec_p->pec_safeacc_type = DDI_FM_ERR_PEEK;
   1715 		}
   1716 
   1717 		hvio_peek_status = hvio_peek(px_p->px_dev_hdl, ra,
   1718 		    in_args->size, &read_status, &peekval);
   1719 
   1720 		if ((hvio_peek_status != H_EOK) || (read_status != H_EOK)) {
   1721 			err = DDI_FAILURE;
   1722 
   1723 			/*
   1724 			 * For CAUTIOUS and PEEK access, notify FMA to
   1725 			 * cleanup.  Imitate a cpu/mem trap call like in sun4u.
   1726 			 */
   1727 			px_lib_log_safeacc_err(px_p, (ddi_acc_handle_t)hp,
   1728 			    (hp ? DDI_FM_ERR_EXPECTED :
   1729 			    DDI_FM_ERR_PEEK), ra);
   1730 
   1731 			/* Stuff FFs in host addr if peek. */
   1732 			if (hp == NULL) {
   1733 				int i;
   1734 				uint8_t *ff_addr = (uint8_t *)host_addr;
   1735 				for (i = 0; i < in_args->size; i++)
   1736 					*ff_addr++ = 0xff;
   1737 			}
   1738 #ifdef  DEBUG
   1739 			px_peekfault_cnt++;
   1740 #endif
   1741 			pec_p->pec_ontrap_data = NULL;
   1742 			pec_p->pec_safeacc_type = DDI_FM_ERR_UNEXPECTED;
   1743 			if (hp) {
   1744 				i_ndi_busop_access_exit(hp->ahi_common.ah_dip,
   1745 				    (ddi_acc_handle_t)hp);
   1746 			} else {
   1747 				mutex_exit(&pec_p->pec_pokefault_mutex);
   1748 			}
   1749 			goto done;
   1750 
   1751 		}
   1752 		pec_p->pec_ontrap_data = NULL;
   1753 		pec_p->pec_safeacc_type = DDI_FM_ERR_UNEXPECTED;
   1754 		if (hp) {
   1755 			i_ndi_busop_access_exit(hp->ahi_common.ah_dip,
   1756 			    (ddi_acc_handle_t)hp);
   1757 		} else {
   1758 			mutex_exit(&pec_p->pec_pokefault_mutex);
   1759 		}
   1760 
   1761 		switch (in_args->size) {
   1762 		case sizeof (uint8_t):
   1763 			*(uint8_t *)host_addr = (uint8_t)peekval;
   1764 			break;
   1765 		case sizeof (uint16_t):
   1766 			*(uint16_t *)host_addr = (uint16_t)peekval;
   1767 			break;
   1768 		case sizeof (uint32_t):
   1769 			*(uint32_t *)host_addr = (uint32_t)peekval;
   1770 			break;
   1771 		case sizeof (uint64_t):
   1772 			*(uint64_t *)host_addr = (uint64_t)peekval;
   1773 			break;
   1774 		default:
   1775 			DBG(DBG_MAP, px_p->px_dip,
   1776 			    "peek: invalid size %d passed\n",
   1777 			    in_args->size);
   1778 			err = DDI_FAILURE;
   1779 			goto done;
   1780 		}
   1781 
   1782 		host_addr += in_args->size;
   1783 
   1784 		if (in_args->flags == DDI_DEV_AUTOINCR) {
   1785 			dev_addr += in_args->size;
   1786 			ra = (r_addr_t)va_to_pa((void *)dev_addr);
   1787 		}
   1788 	}
   1789 done:
   1790 	return (err);
   1791 }
   1792 
   1793 
   1794 /* add interrupt vector */
   1795 int
   1796 px_err_add_intr(px_fault_t *px_fault_p)
   1797 {
   1798 	px_t	*px_p = DIP_TO_STATE(px_fault_p->px_fh_dip);
   1799 
   1800 	DBG(DBG_LIB_INT, px_p->px_dip,
   1801 	    "px_err_add_intr: calling add_ivintr");
   1802 
   1803 	VERIFY(add_ivintr(px_fault_p->px_fh_sysino, PX_ERR_PIL,
   1804 	    (intrfunc)px_fault_p->px_err_func, (caddr_t)px_fault_p, NULL,
   1805 	    (caddr_t)&px_fault_p->px_intr_payload[0]) == 0);
   1806 
   1807 	DBG(DBG_LIB_INT, px_p->px_dip,
   1808 	    "px_err_add_intr: ib_intr_enable ");
   1809 
   1810 	px_ib_intr_enable(px_p, intr_dist_cpuid(), px_fault_p->px_intr_ino);
   1811 
   1812 	return (DDI_SUCCESS);
   1813 }
   1814 
   1815 /* remove interrupt vector */
   1816 void
   1817 px_err_rem_intr(px_fault_t *px_fault_p)
   1818 {
   1819 	px_t	*px_p = DIP_TO_STATE(px_fault_p->px_fh_dip);
   1820 
   1821 	px_ib_intr_disable(px_p->px_ib_p, px_fault_p->px_intr_ino,
   1822 	    IB_INTR_WAIT);
   1823 
   1824 	VERIFY(rem_ivintr(px_fault_p->px_fh_sysino, PX_ERR_PIL) == 0);
   1825 }
   1826 
   1827 void
   1828 px_cb_intr_redist(void *arg)
   1829 {
   1830 	px_t	*px_p = (px_t *)arg;
   1831 	px_ib_intr_dist_en(px_p->px_dip, intr_dist_cpuid(),
   1832 	    px_p->px_inos[PX_INTR_XBC], B_FALSE);
   1833 }
   1834 
   1835 int
   1836 px_cb_add_intr(px_fault_t *f_p)
   1837 {
   1838 	px_t	*px_p = DIP_TO_STATE(f_p->px_fh_dip);
   1839 
   1840 	DBG(DBG_LIB_INT, px_p->px_dip,
   1841 	    "px_err_add_intr: calling add_ivintr");
   1842 
   1843 	VERIFY(add_ivintr(f_p->px_fh_sysino, PX_ERR_PIL,
   1844 	    (intrfunc)f_p->px_err_func, (caddr_t)f_p, NULL,
   1845 	    (caddr_t)&f_p->px_intr_payload[0]) == 0);
   1846 
   1847 	intr_dist_add(px_cb_intr_redist, px_p);
   1848 
   1849 	DBG(DBG_LIB_INT, px_p->px_dip,
   1850 	    "px_err_add_intr: ib_intr_enable ");
   1851 
   1852 	px_ib_intr_enable(px_p, intr_dist_cpuid(), f_p->px_intr_ino);
   1853 
   1854 	return (DDI_SUCCESS);
   1855 }
   1856 
   1857 void
   1858 px_cb_rem_intr(px_fault_t *f_p)
   1859 {
   1860 	intr_dist_rem(px_cb_intr_redist, DIP_TO_STATE(f_p->px_fh_dip));
   1861 	px_err_rem_intr(f_p);
   1862 }
   1863 
   1864 #ifdef FMA
   1865 void
   1866 px_fill_rc_status(px_fault_t *px_fault_p, pciex_rc_error_regs_t *rc_status)
   1867 {
   1868 	px_pec_err_t	*err_pkt;
   1869 
   1870 	err_pkt = (px_pec_err_t *)px_fault_p->px_intr_payload;
   1871 
   1872 	/* initialise all the structure members */
   1873 	rc_status->status_valid = 0;
   1874 
   1875 	if (err_pkt->pec_descr.P) {
   1876 		/* PCI Status Register */
   1877 		rc_status->pci_err_status = err_pkt->pci_err_status;
   1878 		rc_status->status_valid |= PCI_ERR_STATUS_VALID;
   1879 	}
   1880 
   1881 	if (err_pkt->pec_descr.E) {
   1882 		/* PCIe Status Register */
   1883 		rc_status->pcie_err_status = err_pkt->pcie_err_status;
   1884 		rc_status->status_valid |= PCIE_ERR_STATUS_VALID;
   1885 	}
   1886 
   1887 	if (err_pkt->pec_descr.U) {
   1888 		rc_status->ue_status = err_pkt->ue_reg_status;
   1889 		rc_status->status_valid |= UE_STATUS_VALID;
   1890 	}
   1891 
   1892 	if (err_pkt->pec_descr.H) {
   1893 		rc_status->ue_hdr1 = err_pkt->hdr[0];
   1894 		rc_status->status_valid |= UE_HDR1_VALID;
   1895 	}
   1896 
   1897 	if (err_pkt->pec_descr.I) {
   1898 		rc_status->ue_hdr2 = err_pkt->hdr[1];
   1899 		rc_status->status_valid |= UE_HDR2_VALID;
   1900 	}
   1901 
   1902 	/* ue_fst_err_ptr - not available for sun4v?? */
   1903 
   1904 
   1905 	if (err_pkt->pec_descr.S) {
   1906 		rc_status->source_id = err_pkt->err_src_reg;
   1907 		rc_status->status_valid |= SOURCE_ID_VALID;
   1908 	}
   1909 
   1910 	if (err_pkt->pec_descr.R) {
   1911 		rc_status->root_err_status = err_pkt->root_err_status;
   1912 		rc_status->status_valid |= CE_STATUS_VALID;
   1913 	}
   1914 }
   1915 #endif
   1916 
   1917 /*ARGSUSED*/
   1918 int
   1919 px_lib_pmctl(int cmd, px_t *px_p)
   1920 {
   1921 	return (DDI_FAILURE);
   1922 }
   1923 
   1924 /*ARGSUSED*/
   1925 uint_t
   1926 px_pmeq_intr(caddr_t arg)
   1927 {
   1928 	return (DDI_INTR_CLAIMED);
   1929 }
   1930 
   1931 /*
   1932  * Unprotected raw reads/writes of fabric device's config space.
   1933  * Only used for temporary PCI-E Fabric Error Handling.
   1934  */
   1935 uint32_t
   1936 px_fab_get(px_t *px_p, pcie_req_id_t bdf, uint16_t offset) {
   1937 	uint64_t 	data = 0;
   1938 
   1939 	(void) hvio_config_get(px_p->px_dev_hdl,
   1940 	    (bdf << PX_RA_BDF_SHIFT), offset, 4,
   1941 	    (pci_cfg_data_t *)&data);
   1942 
   1943 	return ((uint32_t)data);
   1944 }
   1945 
   1946 void
   1947 px_fab_set(px_t *px_p, pcie_req_id_t bdf, uint16_t offset,
   1948     uint32_t val) {
   1949 	pci_cfg_data_t	wdata = { 0 };
   1950 
   1951 	wdata.qw = (uint32_t)val;
   1952 	(void) hvio_config_put(px_p->px_dev_hdl,
   1953 	    (bdf << PX_RA_BDF_SHIFT), offset, 4, wdata);
   1954 }
   1955 
   1956 /*ARGSUSED*/
   1957 int
   1958 px_lib_hotplug_init(dev_info_t *dip, void *arg)
   1959 {
   1960 	return (DDI_ENOTSUP);
   1961 }
   1962 
   1963 /*ARGSUSED*/
   1964 void
   1965 px_lib_hotplug_uninit(dev_info_t *dip)
   1966 {
   1967 }
   1968 
   1969 /*ARGSUSED*/
   1970 void
   1971 px_hp_intr_redist(px_t *px_p)
   1972 {
   1973 }
   1974 
   1975 /* Dummy cpr add callback */
   1976 /*ARGSUSED*/
   1977 void
   1978 px_cpr_add_callb(px_t *px_p)
   1979 {
   1980 }
   1981 
   1982 /* Dummy cpr rem callback */
   1983 /*ARGSUSED*/
   1984 void
   1985 px_cpr_rem_callb(px_t *px_p)
   1986 {
   1987 }
   1988 
   1989 /*ARGSUSED*/
   1990 boolean_t
   1991 px_lib_is_in_drain_state(px_t *px_p)
   1992 {
   1993 	return (B_FALSE);
   1994 }
   1995 
   1996 /*
   1997  * There is no IOAPI to get the BDF of the pcie root port nexus at this moment.
   1998  * Assume it is 0x0000, until otherwise noted.  For now, all sun4v platforms
   1999  * have programmed the BDF to be 0x0000.
   2000  */
   2001 /*ARGSUSED*/
   2002 pcie_req_id_t
   2003 px_lib_get_bdf(px_t *px_p)
   2004 {
   2005 	return (0x0000);
   2006 }
   2007 
   2008 int
   2009 px_lib_get_root_complex_mps(px_t *px_p, dev_info_t *dip, int *mps)
   2010 {
   2011 	pci_device_t	bdf = px_lib_get_bdf(px_p);
   2012 
   2013 	if (hvio_get_rp_mps_cap(DIP_TO_HANDLE(dip), bdf, mps) == H_EOK)
   2014 		return (DDI_SUCCESS);
   2015 	else
   2016 		return (DDI_FAILURE);
   2017 }
   2018 
   2019 int
   2020 px_lib_set_root_complex_mps(px_t *px_p,  dev_info_t *dip, int mps)
   2021 {
   2022 	pci_device_t	bdf = px_lib_get_bdf(px_p);
   2023 
   2024 	if (hvio_set_rp_mps(DIP_TO_HANDLE(dip), bdf, mps) == H_EOK)
   2025 		return (DDI_SUCCESS);
   2026 	else
   2027 		return (DDI_FAILURE);
   2028 }
   2029