10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
51540Skini * Common Development and Distribution License (the "License").
61540Skini * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
2212262SAlan.Adamson@Sun.COM * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate */
240Sstevel@tonic-gate
250Sstevel@tonic-gate #include <sys/types.h>
260Sstevel@tonic-gate #include <sys/sysmacros.h>
270Sstevel@tonic-gate #include <sys/ddi.h>
28965Sgovinda #include <sys/async.h>
290Sstevel@tonic-gate #include <sys/sunddi.h>
300Sstevel@tonic-gate #include <sys/ddifm.h>
310Sstevel@tonic-gate #include <sys/fm/protocol.h>
320Sstevel@tonic-gate #include <sys/vmem.h>
3327Sjchu #include <sys/intr.h>
3427Sjchu #include <sys/ivintr.h>
3527Sjchu #include <sys/errno.h>
360Sstevel@tonic-gate #include <sys/hypervisor_api.h>
371617Sgovinda #include <sys/hsvc.h>
380Sstevel@tonic-gate #include <px_obj.h>
3927Sjchu #include <sys/machsystm.h>
4011596SJason.Beloro@Sun.COM #include <sys/sunndi.h>
4111596SJason.Beloro@Sun.COM #include <sys/pcie_impl.h>
420Sstevel@tonic-gate #include "px_lib4v.h"
4327Sjchu #include "px_err.h"
4411245SZhijun.Fu@Sun.COM #include <sys/pci_cfgacc.h>
4511245SZhijun.Fu@Sun.COM #include <sys/pci_cfgacc_4v.h>
4611245SZhijun.Fu@Sun.COM
470Sstevel@tonic-gate
480Sstevel@tonic-gate /* mask for the ranges property in calculating the real PFN range */
490Sstevel@tonic-gate uint_t px_ranges_phi_mask = ((1 << 28) -1);
500Sstevel@tonic-gate
511617Sgovinda /*
521617Sgovinda * Hypervisor VPCI services information for the px nexus driver.
531617Sgovinda */
5412262SAlan.Adamson@Sun.COM static uint64_t px_vpci_maj_ver; /* Negotiated VPCI API major version */
551617Sgovinda static uint64_t px_vpci_min_ver; /* Negotiated VPCI API minor version */
561617Sgovinda static uint_t px_vpci_users = 0; /* VPCI API users */
5711596SJason.Beloro@Sun.COM static hsvc_info_t px_hsvc_vpci = {
581617Sgovinda HSVC_REV_1, NULL, HSVC_GROUP_VPCI, PX_VPCI_MAJOR_VER,
591617Sgovinda PX_VPCI_MINOR_VER, "PX"
601617Sgovinda };
611617Sgovinda
6211596SJason.Beloro@Sun.COM /*
6311596SJason.Beloro@Sun.COM * Hypervisor SDIO services information for the px nexus driver.
6411596SJason.Beloro@Sun.COM */
6511596SJason.Beloro@Sun.COM static uint64_t px_sdio_min_ver; /* Negotiated SDIO API minor version */
6611596SJason.Beloro@Sun.COM static uint_t px_sdio_users = 0; /* SDIO API users */
6711596SJason.Beloro@Sun.COM static hsvc_info_t px_hsvc_sdio = {
6811596SJason.Beloro@Sun.COM HSVC_REV_1, NULL, HSVC_GROUP_SDIO, PX_SDIO_MAJOR_VER,
6911596SJason.Beloro@Sun.COM PX_SDIO_MINOR_VER, "PX"
7011596SJason.Beloro@Sun.COM };
7111596SJason.Beloro@Sun.COM
7211596SJason.Beloro@Sun.COM /*
7311596SJason.Beloro@Sun.COM * Hypervisor SDIO ERR services information for the px nexus driver.
7411596SJason.Beloro@Sun.COM */
7511596SJason.Beloro@Sun.COM static uint64_t px_sdio_err_min_ver; /* Negotiated SDIO ERR API */
7611596SJason.Beloro@Sun.COM /* minor version */
7711596SJason.Beloro@Sun.COM static uint_t px_sdio_err_users = 0; /* SDIO ERR API users */
7811596SJason.Beloro@Sun.COM static hsvc_info_t px_hsvc_sdio_err = {
7911596SJason.Beloro@Sun.COM HSVC_REV_1, NULL, HSVC_GROUP_SDIO_ERR, PX_SDIO_ERR_MAJOR_VER,
8011596SJason.Beloro@Sun.COM PX_SDIO_ERR_MINOR_VER, "PX"
8111596SJason.Beloro@Sun.COM };
8211596SJason.Beloro@Sun.COM
8311596SJason.Beloro@Sun.COM #define CHILD_LOANED "child_loaned"
8411596SJason.Beloro@Sun.COM static int px_lib_count_waiting_dev(dev_info_t *);
8511596SJason.Beloro@Sun.COM
860Sstevel@tonic-gate int
px_lib_dev_init(dev_info_t * dip,devhandle_t * dev_hdl)870Sstevel@tonic-gate px_lib_dev_init(dev_info_t *dip, devhandle_t *dev_hdl)
880Sstevel@tonic-gate {
890Sstevel@tonic-gate px_nexus_regspec_t *rp;
90226Set142600 uint_t reglen;
91226Set142600 int ret;
9211596SJason.Beloro@Sun.COM px_t *px_p = DIP_TO_STATE(dip);
934423Sjb145095 uint64_t mjrnum;
944423Sjb145095 uint64_t mnrnum;
954423Sjb145095
960Sstevel@tonic-gate DBG(DBG_ATTACH, dip, "px_lib_dev_init: dip 0x%p\n", dip);
970Sstevel@tonic-gate
984423Sjb145095 /*
994423Sjb145095 * Check HV intr group api versioning.
1004423Sjb145095 * This driver uses the old interrupt routines which are supported
1014423Sjb145095 * in old firmware in the CORE API group and in newer firmware in
1024423Sjb145095 * the INTR API group. Support for these calls will be dropped
1034423Sjb145095 * once the INTR API group major goes to 2.
1044423Sjb145095 */
1054423Sjb145095 if ((hsvc_version(HSVC_GROUP_INTR, &mjrnum, &mnrnum) == 0) &&
1064423Sjb145095 (mjrnum > 1)) {
10711074SZachary.Kissel@Sun.COM cmn_err(CE_WARN, "px: unsupported intr api group: "
1084423Sjb145095 "maj:0x%lx, min:0x%lx", mjrnum, mnrnum);
1094423Sjb145095 return (ENOTSUP);
1104423Sjb145095 }
1114423Sjb145095
112226Set142600 ret = ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
113226Set142600 "reg", (uchar_t **)&rp, ®len);
114226Set142600 if (ret != DDI_PROP_SUCCESS) {
115226Set142600 DBG(DBG_ATTACH, dip, "px_lib_dev_init failed ret=%d\n", ret);
1160Sstevel@tonic-gate return (DDI_FAILURE);
1170Sstevel@tonic-gate }
1180Sstevel@tonic-gate
1190Sstevel@tonic-gate /*
1200Sstevel@tonic-gate * Initilize device handle. The device handle uniquely identifies
1210Sstevel@tonic-gate * a SUN4V device. It consists of the lower 28-bits of the hi-cell
1220Sstevel@tonic-gate * of the first entry of the SUN4V device's "reg" property as
1230Sstevel@tonic-gate * defined by the SUN4V Bus Binding to Open Firmware.
1240Sstevel@tonic-gate */
1250Sstevel@tonic-gate *dev_hdl = (devhandle_t)((rp->phys_addr >> 32) & DEVHDLE_MASK);
126226Set142600 ddi_prop_free(rp);
127226Set142600
1281531Skini /*
1291531Skini * hotplug implementation requires this property to be associated with
1301531Skini * any indirect PCI config access services
1311531Skini */
1321531Skini (void) ddi_prop_update_int(makedevice(ddi_driver_major(dip),
13310923SEvan.Yan@Sun.COM PCI_MINOR_NUM(ddi_get_instance(dip), PCI_DEVCTL_MINOR)), dip,
1341531Skini PCI_BUS_CONF_MAP_PROP, 1);
1351531Skini
1360Sstevel@tonic-gate DBG(DBG_ATTACH, dip, "px_lib_dev_init: dev_hdl 0x%llx\n", *dev_hdl);
1370Sstevel@tonic-gate
1381617Sgovinda /*
13911596SJason.Beloro@Sun.COM * If a /pci node has a pci-intx-not-supported property, this property
14011596SJason.Beloro@Sun.COM * represents that the fabric doesn't support fixed interrupt.
14111596SJason.Beloro@Sun.COM */
14211596SJason.Beloro@Sun.COM if (!ddi_prop_exists(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
14311596SJason.Beloro@Sun.COM "pci-intx-not-supported")) {
14411596SJason.Beloro@Sun.COM DBG(DBG_ATTACH, dip, "px_lib_dev_init: "
14511596SJason.Beloro@Sun.COM "pci-intx-not-supported is not found, dip=0x%p\n", dip);
14611596SJason.Beloro@Sun.COM px_p->px_supp_intr_types |= DDI_INTR_TYPE_FIXED;
14711596SJason.Beloro@Sun.COM }
14811596SJason.Beloro@Sun.COM
14911596SJason.Beloro@Sun.COM /*
1501617Sgovinda * Negotiate the API version for VPCI hypervisor services.
1511617Sgovinda */
15212262SAlan.Adamson@Sun.COM if (px_vpci_users == 0) {
15312262SAlan.Adamson@Sun.COM if ((ret = hsvc_register(&px_hsvc_vpci, &px_vpci_min_ver))
15412262SAlan.Adamson@Sun.COM == 0) {
15512262SAlan.Adamson@Sun.COM px_vpci_maj_ver = px_hsvc_vpci.hsvc_major;
15612262SAlan.Adamson@Sun.COM goto hv_negotiation_complete;
15712262SAlan.Adamson@Sun.COM }
15812262SAlan.Adamson@Sun.COM /*
15912262SAlan.Adamson@Sun.COM * Negotiation with the latest known VPCI hypervisor services
16012262SAlan.Adamson@Sun.COM * failed. Fallback to version 1.0.
16112262SAlan.Adamson@Sun.COM */
16212262SAlan.Adamson@Sun.COM px_hsvc_vpci.hsvc_major = PX_HSVC_MAJOR_VER_1;
16312262SAlan.Adamson@Sun.COM px_hsvc_vpci.hsvc_minor = PX_HSVC_MINOR_VER_0;
16412262SAlan.Adamson@Sun.COM
16512262SAlan.Adamson@Sun.COM if ((ret = hsvc_register(&px_hsvc_vpci, &px_vpci_min_ver))
16612262SAlan.Adamson@Sun.COM == 0) {
16712262SAlan.Adamson@Sun.COM px_vpci_maj_ver = px_hsvc_vpci.hsvc_major;
16812262SAlan.Adamson@Sun.COM goto hv_negotiation_complete;
16912262SAlan.Adamson@Sun.COM }
17012262SAlan.Adamson@Sun.COM
1711617Sgovinda cmn_err(CE_WARN, "%s: cannot negotiate hypervisor services "
1721617Sgovinda "group: 0x%lx major: 0x%lx minor: 0x%lx errno: %d\n",
17311596SJason.Beloro@Sun.COM px_hsvc_vpci.hsvc_modname, px_hsvc_vpci.hsvc_group,
17411596SJason.Beloro@Sun.COM px_hsvc_vpci.hsvc_major, px_hsvc_vpci.hsvc_minor, ret);
17512262SAlan.Adamson@Sun.COM
1761617Sgovinda return (DDI_FAILURE);
1771617Sgovinda }
17812262SAlan.Adamson@Sun.COM hv_negotiation_complete:
17912262SAlan.Adamson@Sun.COM
18011596SJason.Beloro@Sun.COM px_vpci_users++;
18112262SAlan.Adamson@Sun.COM
1821617Sgovinda DBG(DBG_ATTACH, dip, "px_lib_dev_init: negotiated VPCI API version, "
18312262SAlan.Adamson@Sun.COM "major 0x%lx minor 0x%lx\n", px_vpci_maj_ver,
18411596SJason.Beloro@Sun.COM px_vpci_min_ver);
18511596SJason.Beloro@Sun.COM
18611596SJason.Beloro@Sun.COM /*
18711596SJason.Beloro@Sun.COM * Negotiate the API version for SDIO hypervisor services.
18811596SJason.Beloro@Sun.COM */
18911596SJason.Beloro@Sun.COM if ((px_sdio_users == 0) &&
19011596SJason.Beloro@Sun.COM ((ret = hsvc_register(&px_hsvc_sdio, &px_sdio_min_ver)) != 0)) {
19111596SJason.Beloro@Sun.COM DBG(DBG_ATTACH, dip, "%s: cannot negotiate hypervisor "
19211596SJason.Beloro@Sun.COM "services group: 0x%lx major: 0x%lx minor: 0x%lx "
19311596SJason.Beloro@Sun.COM "errno: %d\n", px_hsvc_sdio.hsvc_modname,
19411596SJason.Beloro@Sun.COM px_hsvc_sdio.hsvc_group, px_hsvc_sdio.hsvc_major,
19511596SJason.Beloro@Sun.COM px_hsvc_sdio.hsvc_minor, ret);
19611596SJason.Beloro@Sun.COM } else {
19711596SJason.Beloro@Sun.COM px_sdio_users++;
19811596SJason.Beloro@Sun.COM DBG(DBG_ATTACH, dip, "px_lib_dev_init: negotiated SDIO API"
19911596SJason.Beloro@Sun.COM "version, major 0x%lx minor 0x%lx\n",
20011596SJason.Beloro@Sun.COM px_hsvc_sdio.hsvc_major, px_sdio_min_ver);
20111596SJason.Beloro@Sun.COM }
2021617Sgovinda
20311596SJason.Beloro@Sun.COM /*
20411596SJason.Beloro@Sun.COM * Negotiate the API version for SDIO ERR hypervisor services.
20511596SJason.Beloro@Sun.COM */
20611596SJason.Beloro@Sun.COM if ((px_sdio_err_users == 0) &&
20711596SJason.Beloro@Sun.COM ((ret = hsvc_register(&px_hsvc_sdio_err,
20811596SJason.Beloro@Sun.COM &px_sdio_err_min_ver)) != 0)) {
20911596SJason.Beloro@Sun.COM DBG(DBG_ATTACH, dip, "%s: cannot negotiate SDIO ERR hypervisor "
21011596SJason.Beloro@Sun.COM "services group: 0x%lx major: 0x%lx minor: 0x%lx "
21111596SJason.Beloro@Sun.COM "errno: %d\n", px_hsvc_sdio_err.hsvc_modname,
21211596SJason.Beloro@Sun.COM px_hsvc_sdio_err.hsvc_group, px_hsvc_sdio_err.hsvc_major,
21311596SJason.Beloro@Sun.COM px_hsvc_sdio_err.hsvc_minor, ret);
21411596SJason.Beloro@Sun.COM } else {
21511596SJason.Beloro@Sun.COM px_sdio_err_users++;
21611596SJason.Beloro@Sun.COM DBG(DBG_ATTACH, dip, "px_lib_dev_init: negotiated SDIO ERR API "
21711596SJason.Beloro@Sun.COM "version, major 0x%lx minor 0x%lx\n",
21811596SJason.Beloro@Sun.COM px_hsvc_sdio_err.hsvc_major, px_sdio_err_min_ver);
21911596SJason.Beloro@Sun.COM }
22011596SJason.Beloro@Sun.COM
22111596SJason.Beloro@Sun.COM /*
22211596SJason.Beloro@Sun.COM * Find out the number of dev we need to wait under this RC
22311596SJason.Beloro@Sun.COM * before we issue fabric sync hypercall
22411596SJason.Beloro@Sun.COM */
22511596SJason.Beloro@Sun.COM px_p->px_plat_p = (void *)(uintptr_t)px_lib_count_waiting_dev(dip);
22611596SJason.Beloro@Sun.COM DBG(DBG_ATTACH, dip, "Found %d bridges need waiting under RC %p",
22711596SJason.Beloro@Sun.COM (int)(uintptr_t)px_p->px_plat_p, dip);
2280Sstevel@tonic-gate return (DDI_SUCCESS);
2290Sstevel@tonic-gate }
2300Sstevel@tonic-gate
2310Sstevel@tonic-gate /*ARGSUSED*/
2320Sstevel@tonic-gate int
px_lib_dev_fini(dev_info_t * dip)2330Sstevel@tonic-gate px_lib_dev_fini(dev_info_t *dip)
2340Sstevel@tonic-gate {
2350Sstevel@tonic-gate DBG(DBG_DETACH, dip, "px_lib_dev_fini: dip 0x%p\n", dip);
2360Sstevel@tonic-gate
2371531Skini (void) ddi_prop_remove(makedevice(ddi_driver_major(dip),
23810923SEvan.Yan@Sun.COM PCI_MINOR_NUM(ddi_get_instance(dip), PCI_DEVCTL_MINOR)), dip,
2391531Skini PCI_BUS_CONF_MAP_PROP);
2401531Skini
2411617Sgovinda if (--px_vpci_users == 0)
24211596SJason.Beloro@Sun.COM (void) hsvc_unregister(&px_hsvc_vpci);
24311596SJason.Beloro@Sun.COM
24411596SJason.Beloro@Sun.COM if (--px_sdio_users == 0)
24511596SJason.Beloro@Sun.COM (void) hsvc_unregister(&px_hsvc_sdio);
24611596SJason.Beloro@Sun.COM
24711596SJason.Beloro@Sun.COM if (--px_sdio_err_users == 0)
24811596SJason.Beloro@Sun.COM (void) hsvc_unregister(&px_hsvc_sdio_err);
2491617Sgovinda
2500Sstevel@tonic-gate return (DDI_SUCCESS);
2510Sstevel@tonic-gate }
2520Sstevel@tonic-gate
2530Sstevel@tonic-gate /*ARGSUSED*/
2540Sstevel@tonic-gate int
px_lib_intr_devino_to_sysino(dev_info_t * dip,devino_t devino,sysino_t * sysino)2550Sstevel@tonic-gate px_lib_intr_devino_to_sysino(dev_info_t *dip, devino_t devino,
2560Sstevel@tonic-gate sysino_t *sysino)
2570Sstevel@tonic-gate {
2580Sstevel@tonic-gate uint64_t ret;
2590Sstevel@tonic-gate
2600Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "px_lib_intr_devino_to_sysino: dip 0x%p "
2610Sstevel@tonic-gate "devino 0x%x\n", dip, devino);
2620Sstevel@tonic-gate
2630Sstevel@tonic-gate if ((ret = hvio_intr_devino_to_sysino(DIP_TO_HANDLE(dip),
2640Sstevel@tonic-gate devino, sysino)) != H_EOK) {
2650Sstevel@tonic-gate DBG(DBG_LIB_INT, dip,
2660Sstevel@tonic-gate "hvio_intr_devino_to_sysino failed, ret 0x%lx\n", ret);
2670Sstevel@tonic-gate return (DDI_FAILURE);
2680Sstevel@tonic-gate }
2690Sstevel@tonic-gate
2700Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "px_lib_intr_devino_to_sysino: sysino 0x%llx\n",
2710Sstevel@tonic-gate *sysino);
2720Sstevel@tonic-gate
2730Sstevel@tonic-gate return (DDI_SUCCESS);
2740Sstevel@tonic-gate }
2750Sstevel@tonic-gate
2760Sstevel@tonic-gate /*ARGSUSED*/
2770Sstevel@tonic-gate int
px_lib_intr_getvalid(dev_info_t * dip,sysino_t sysino,intr_valid_state_t * intr_valid_state)2780Sstevel@tonic-gate px_lib_intr_getvalid(dev_info_t *dip, sysino_t sysino,
2790Sstevel@tonic-gate intr_valid_state_t *intr_valid_state)
2800Sstevel@tonic-gate {
2810Sstevel@tonic-gate uint64_t ret;
2820Sstevel@tonic-gate
2830Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "px_lib_intr_getvalid: dip 0x%p sysino 0x%llx\n",
2840Sstevel@tonic-gate dip, sysino);
2850Sstevel@tonic-gate
2860Sstevel@tonic-gate if ((ret = hvio_intr_getvalid(sysino,
2870Sstevel@tonic-gate (int *)intr_valid_state)) != H_EOK) {
2880Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "hvio_intr_getvalid failed, ret 0x%lx\n",
2890Sstevel@tonic-gate ret);
2900Sstevel@tonic-gate return (DDI_FAILURE);
2910Sstevel@tonic-gate }
2920Sstevel@tonic-gate
2930Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "px_lib_intr_getvalid: intr_valid_state 0x%x\n",
2940Sstevel@tonic-gate *intr_valid_state);
2950Sstevel@tonic-gate
2960Sstevel@tonic-gate return (DDI_SUCCESS);
2970Sstevel@tonic-gate }
2980Sstevel@tonic-gate
2990Sstevel@tonic-gate /*ARGSUSED*/
3000Sstevel@tonic-gate int
px_lib_intr_setvalid(dev_info_t * dip,sysino_t sysino,intr_valid_state_t intr_valid_state)3010Sstevel@tonic-gate px_lib_intr_setvalid(dev_info_t *dip, sysino_t sysino,
3020Sstevel@tonic-gate intr_valid_state_t intr_valid_state)
3030Sstevel@tonic-gate {
3040Sstevel@tonic-gate uint64_t ret;
3050Sstevel@tonic-gate
3060Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "px_lib_intr_setvalid: dip 0x%p sysino 0x%llx "
3070Sstevel@tonic-gate "intr_valid_state 0x%x\n", dip, sysino, intr_valid_state);
3080Sstevel@tonic-gate
3090Sstevel@tonic-gate if ((ret = hvio_intr_setvalid(sysino, intr_valid_state)) != H_EOK) {
3100Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "hvio_intr_setvalid failed, ret 0x%lx\n",
3110Sstevel@tonic-gate ret);
3120Sstevel@tonic-gate return (DDI_FAILURE);
3130Sstevel@tonic-gate }
3140Sstevel@tonic-gate
3150Sstevel@tonic-gate return (DDI_SUCCESS);
3160Sstevel@tonic-gate }
3170Sstevel@tonic-gate
3180Sstevel@tonic-gate /*ARGSUSED*/
3190Sstevel@tonic-gate int
px_lib_intr_getstate(dev_info_t * dip,sysino_t sysino,intr_state_t * intr_state)3200Sstevel@tonic-gate px_lib_intr_getstate(dev_info_t *dip, sysino_t sysino,
3210Sstevel@tonic-gate intr_state_t *intr_state)
3220Sstevel@tonic-gate {
3230Sstevel@tonic-gate uint64_t ret;
3240Sstevel@tonic-gate
3250Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "px_lib_intr_getstate: dip 0x%p sysino 0x%llx\n",
3260Sstevel@tonic-gate dip, sysino);
3270Sstevel@tonic-gate
3280Sstevel@tonic-gate if ((ret = hvio_intr_getstate(sysino, (int *)intr_state)) != H_EOK) {
3290Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "hvio_intr_getstate failed, ret 0x%lx\n",
3300Sstevel@tonic-gate ret);
3310Sstevel@tonic-gate return (DDI_FAILURE);
3320Sstevel@tonic-gate }
3330Sstevel@tonic-gate
3340Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "px_lib_intr_getstate: intr_state 0x%x\n",
3350Sstevel@tonic-gate *intr_state);
3360Sstevel@tonic-gate
3370Sstevel@tonic-gate return (DDI_SUCCESS);
3380Sstevel@tonic-gate }
3390Sstevel@tonic-gate
3400Sstevel@tonic-gate /*ARGSUSED*/
3410Sstevel@tonic-gate int
px_lib_intr_setstate(dev_info_t * dip,sysino_t sysino,intr_state_t intr_state)3420Sstevel@tonic-gate px_lib_intr_setstate(dev_info_t *dip, sysino_t sysino,
3430Sstevel@tonic-gate intr_state_t intr_state)
3440Sstevel@tonic-gate {
3450Sstevel@tonic-gate uint64_t ret;
3460Sstevel@tonic-gate
3470Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "px_lib_intr_setstate: dip 0x%p sysino 0x%llx "
3480Sstevel@tonic-gate "intr_state 0x%x\n", dip, sysino, intr_state);
3490Sstevel@tonic-gate
3500Sstevel@tonic-gate if ((ret = hvio_intr_setstate(sysino, intr_state)) != H_EOK) {
3510Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "hvio_intr_setstate failed, ret 0x%lx\n",
3520Sstevel@tonic-gate ret);
3530Sstevel@tonic-gate return (DDI_FAILURE);
3540Sstevel@tonic-gate }
3550Sstevel@tonic-gate
3560Sstevel@tonic-gate return (DDI_SUCCESS);
3570Sstevel@tonic-gate }
3580Sstevel@tonic-gate
3590Sstevel@tonic-gate /*ARGSUSED*/
3600Sstevel@tonic-gate int
px_lib_intr_gettarget(dev_info_t * dip,sysino_t sysino,cpuid_t * cpuid)3610Sstevel@tonic-gate px_lib_intr_gettarget(dev_info_t *dip, sysino_t sysino, cpuid_t *cpuid)
3620Sstevel@tonic-gate {
3630Sstevel@tonic-gate uint64_t ret;
3640Sstevel@tonic-gate
3650Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "px_lib_intr_gettarget: dip 0x%p sysino 0x%llx\n",
3660Sstevel@tonic-gate dip, sysino);
3670Sstevel@tonic-gate
3680Sstevel@tonic-gate if ((ret = hvio_intr_gettarget(sysino, cpuid)) != H_EOK) {
3690Sstevel@tonic-gate DBG(DBG_LIB_INT, dip,
3700Sstevel@tonic-gate "hvio_intr_gettarget failed, ret 0x%lx\n", ret);
3710Sstevel@tonic-gate return (DDI_FAILURE);
3720Sstevel@tonic-gate }
3730Sstevel@tonic-gate
37410053SEvan.Yan@Sun.COM DBG(DBG_LIB_INT, dip, "px_lib_intr_gettarget: cpuid 0x%x\n", *cpuid);
3750Sstevel@tonic-gate
3760Sstevel@tonic-gate return (DDI_SUCCESS);
3770Sstevel@tonic-gate }
3780Sstevel@tonic-gate
3790Sstevel@tonic-gate /*ARGSUSED*/
3800Sstevel@tonic-gate int
px_lib_intr_settarget(dev_info_t * dip,sysino_t sysino,cpuid_t cpuid)3810Sstevel@tonic-gate px_lib_intr_settarget(dev_info_t *dip, sysino_t sysino, cpuid_t cpuid)
3820Sstevel@tonic-gate {
3830Sstevel@tonic-gate uint64_t ret;
3840Sstevel@tonic-gate
3850Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "px_lib_intr_settarget: dip 0x%p sysino 0x%llx "
3860Sstevel@tonic-gate "cpuid 0x%x\n", dip, sysino, cpuid);
3870Sstevel@tonic-gate
3887124Sanbui ret = hvio_intr_settarget(sysino, cpuid);
3897124Sanbui if (ret == H_ECPUERROR) {
3907124Sanbui cmn_err(CE_PANIC,
3917124Sanbui "px_lib_intr_settarget: hvio_intr_settarget failed, "
3927124Sanbui "ret = 0x%lx, cpuid = 0x%x, sysino = 0x%lx\n", ret,
3937124Sanbui cpuid, sysino);
3947124Sanbui } else if (ret != H_EOK) {
3950Sstevel@tonic-gate DBG(DBG_LIB_INT, dip,
3960Sstevel@tonic-gate "hvio_intr_settarget failed, ret 0x%lx\n", ret);
3970Sstevel@tonic-gate return (DDI_FAILURE);
3980Sstevel@tonic-gate }
3990Sstevel@tonic-gate
4000Sstevel@tonic-gate return (DDI_SUCCESS);
4010Sstevel@tonic-gate }
4020Sstevel@tonic-gate
4030Sstevel@tonic-gate /*ARGSUSED*/
4040Sstevel@tonic-gate int
px_lib_intr_reset(dev_info_t * dip)4050Sstevel@tonic-gate px_lib_intr_reset(dev_info_t *dip)
4060Sstevel@tonic-gate {
4072973Sgovinda px_t *px_p = DIP_TO_STATE(dip);
4082973Sgovinda px_ib_t *ib_p = px_p->px_ib_p;
4092973Sgovinda px_ino_t *ino_p;
410965Sgovinda
4110Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "px_lib_intr_reset: dip 0x%p\n", dip);
4120Sstevel@tonic-gate
413965Sgovinda mutex_enter(&ib_p->ib_ino_lst_mutex);
414965Sgovinda
415965Sgovinda /* Reset all Interrupts */
4162973Sgovinda for (ino_p = ib_p->ib_ino_lst; ino_p; ino_p = ino_p->ino_next_p) {
417965Sgovinda if (px_lib_intr_setstate(dip, ino_p->ino_sysino,
418965Sgovinda INTR_IDLE_STATE) != DDI_SUCCESS)
419965Sgovinda return (BF_FATAL);
420965Sgovinda }
421965Sgovinda
422965Sgovinda mutex_exit(&ib_p->ib_ino_lst_mutex);
423965Sgovinda
424965Sgovinda return (BF_NONE);
4250Sstevel@tonic-gate }
4260Sstevel@tonic-gate
4270Sstevel@tonic-gate /*ARGSUSED*/
4280Sstevel@tonic-gate int
px_lib_iommu_map(dev_info_t * dip,tsbid_t tsbid,pages_t pages,io_attributes_t attr,void * addr,size_t pfn_index,int flags)4290Sstevel@tonic-gate px_lib_iommu_map(dev_info_t *dip, tsbid_t tsbid, pages_t pages,
4301617Sgovinda io_attributes_t attr, void *addr, size_t pfn_index, int flags)
4310Sstevel@tonic-gate {
4320Sstevel@tonic-gate tsbnum_t tsb_num = PCI_TSBID_TO_TSBNUM(tsbid);
4331057Sgovinda tsbindex_t tsb_index = PCI_TSBID_TO_TSBINDEX(tsbid);
4341057Sgovinda io_page_list_t *pfns, *pfn_p;
4351057Sgovinda pages_t ttes_mapped = 0;
4360Sstevel@tonic-gate int i, err = DDI_SUCCESS;
4370Sstevel@tonic-gate
4380Sstevel@tonic-gate DBG(DBG_LIB_DMA, dip, "px_lib_iommu_map: dip 0x%p tsbid 0x%llx "
4399707SDaniel.Ice@Sun.COM "pages 0x%x attr 0x%llx addr 0x%p pfn_index 0x%llx flags 0x%x\n",
4401617Sgovinda dip, tsbid, pages, attr, addr, pfn_index, flags);
4410Sstevel@tonic-gate
4421057Sgovinda if ((pfns = pfn_p = kmem_zalloc((pages * sizeof (io_page_list_t)),
4430Sstevel@tonic-gate KM_NOSLEEP)) == NULL) {
4440Sstevel@tonic-gate DBG(DBG_LIB_DMA, dip, "px_lib_iommu_map: kmem_zalloc failed\n");
4450Sstevel@tonic-gate return (DDI_FAILURE);
4460Sstevel@tonic-gate }
4470Sstevel@tonic-gate
4481057Sgovinda for (i = 0; i < pages; i++)
4491617Sgovinda pfns[i] = MMU_PTOB(PX_ADDR2PFN(addr, pfn_index, flags, i));
4500Sstevel@tonic-gate
4511857Sam139583 /*
45212262SAlan.Adamson@Sun.COM * If HV VPCI version is 2.0 and higher, pass BDF, phantom function,
4533156Sgirish * and relaxed ordering attributes. Otherwise, pass only read or write
4543156Sgirish * attribute.
4551857Sam139583 */
45612262SAlan.Adamson@Sun.COM if ((px_vpci_maj_ver == PX_HSVC_MAJOR_VER_1) &&
45712262SAlan.Adamson@Sun.COM (px_vpci_min_ver == PX_HSVC_MINOR_VER_0))
4581857Sam139583 attr = attr & (PCI_MAP_ATTR_READ | PCI_MAP_ATTR_WRITE);
4591857Sam139583
4601057Sgovinda while ((ttes_mapped = pfn_p - pfns) < pages) {
4611057Sgovinda uintptr_t ra = va_to_pa(pfn_p);
4621057Sgovinda pages_t ttes2map;
4631057Sgovinda uint64_t ret;
4641057Sgovinda
4651057Sgovinda ttes2map = (MMU_PAGE_SIZE - P2PHASE(ra, MMU_PAGE_SIZE)) >> 3;
4661057Sgovinda ra = MMU_PTOB(MMU_BTOP(ra));
4671057Sgovinda
4681057Sgovinda for (ttes2map = MIN(ttes2map, pages - ttes_mapped); ttes2map;
4691057Sgovinda ttes2map -= ttes_mapped, pfn_p += ttes_mapped) {
4700Sstevel@tonic-gate
4711057Sgovinda ttes_mapped = 0;
4721057Sgovinda if ((ret = hvio_iommu_map(DIP_TO_HANDLE(dip),
4731057Sgovinda PCI_TSBID(tsb_num, tsb_index + (pfn_p - pfns)),
4741617Sgovinda ttes2map, attr, (io_page_list_t *)(ra |
4751057Sgovinda ((uintptr_t)pfn_p & MMU_PAGE_OFFSET)),
4761057Sgovinda &ttes_mapped)) != H_EOK) {
4771057Sgovinda DBG(DBG_LIB_DMA, dip, "hvio_iommu_map failed "
4781057Sgovinda "ret 0x%lx\n", ret);
4790Sstevel@tonic-gate
4801057Sgovinda ttes_mapped = pfn_p - pfns;
4811057Sgovinda err = DDI_FAILURE;
4821057Sgovinda goto cleanup;
4831057Sgovinda }
4841057Sgovinda
4851057Sgovinda DBG(DBG_LIB_DMA, dip, "px_lib_iommu_map: tsb_num 0x%x "
4869707SDaniel.Ice@Sun.COM "tsb_index 0x%lx ttes_to_map 0x%lx attr 0x%llx "
4871057Sgovinda "ra 0x%p ttes_mapped 0x%x\n", tsb_num,
4881617Sgovinda tsb_index + (pfn_p - pfns), ttes2map, attr,
4891057Sgovinda ra | ((uintptr_t)pfn_p & MMU_PAGE_OFFSET),
4901057Sgovinda ttes_mapped);
4910Sstevel@tonic-gate }
4920Sstevel@tonic-gate }
4930Sstevel@tonic-gate
4941057Sgovinda cleanup:
4951057Sgovinda if ((err == DDI_FAILURE) && ttes_mapped)
4961057Sgovinda (void) px_lib_iommu_demap(dip, tsbid, ttes_mapped);
4970Sstevel@tonic-gate
4981057Sgovinda kmem_free(pfns, pages * sizeof (io_page_list_t));
4990Sstevel@tonic-gate return (err);
5000Sstevel@tonic-gate }
5010Sstevel@tonic-gate
5020Sstevel@tonic-gate /*ARGSUSED*/
5030Sstevel@tonic-gate int
px_lib_iommu_demap(dev_info_t * dip,tsbid_t tsbid,pages_t pages)5040Sstevel@tonic-gate px_lib_iommu_demap(dev_info_t *dip, tsbid_t tsbid, pages_t pages)
5050Sstevel@tonic-gate {
5060Sstevel@tonic-gate tsbnum_t tsb_num = PCI_TSBID_TO_TSBNUM(tsbid);
5071057Sgovinda tsbindex_t tsb_index = PCI_TSBID_TO_TSBINDEX(tsbid);
5081057Sgovinda pages_t ttes2demap, ttes_demapped = 0;
5090Sstevel@tonic-gate uint64_t ret;
5100Sstevel@tonic-gate
5110Sstevel@tonic-gate DBG(DBG_LIB_DMA, dip, "px_lib_iommu_demap: dip 0x%p tsbid 0x%llx "
5120Sstevel@tonic-gate "pages 0x%x\n", dip, tsbid, pages);
5130Sstevel@tonic-gate
5141057Sgovinda for (ttes2demap = pages; ttes2demap;
5151057Sgovinda ttes2demap -= ttes_demapped, tsb_index += ttes_demapped) {
5160Sstevel@tonic-gate if ((ret = hvio_iommu_demap(DIP_TO_HANDLE(dip),
5171057Sgovinda PCI_TSBID(tsb_num, tsb_index), ttes2demap,
5181057Sgovinda &ttes_demapped)) != H_EOK) {
5191057Sgovinda DBG(DBG_LIB_DMA, dip, "hvio_iommu_demap failed, "
5201057Sgovinda "ret 0x%lx\n", ret);
5211057Sgovinda
5220Sstevel@tonic-gate return (DDI_FAILURE);
5230Sstevel@tonic-gate }
5240Sstevel@tonic-gate
5251057Sgovinda DBG(DBG_LIB_DMA, dip, "px_lib_iommu_demap: tsb_num 0x%x "
5261057Sgovinda "tsb_index 0x%lx ttes_to_demap 0x%lx ttes_demapped 0x%x\n",
5271057Sgovinda tsb_num, tsb_index, ttes2demap, ttes_demapped);
5280Sstevel@tonic-gate }
5290Sstevel@tonic-gate
5300Sstevel@tonic-gate return (DDI_SUCCESS);
5310Sstevel@tonic-gate }
5320Sstevel@tonic-gate
5330Sstevel@tonic-gate /*ARGSUSED*/
5340Sstevel@tonic-gate int
px_lib_iommu_getmap(dev_info_t * dip,tsbid_t tsbid,io_attributes_t * attr_p,r_addr_t * r_addr_p)5351617Sgovinda px_lib_iommu_getmap(dev_info_t *dip, tsbid_t tsbid, io_attributes_t *attr_p,
5361617Sgovinda r_addr_t *r_addr_p)
5370Sstevel@tonic-gate {
5380Sstevel@tonic-gate uint64_t ret;
5390Sstevel@tonic-gate
5400Sstevel@tonic-gate DBG(DBG_LIB_DMA, dip, "px_lib_iommu_getmap: dip 0x%p tsbid 0x%llx\n",
5410Sstevel@tonic-gate dip, tsbid);
5420Sstevel@tonic-gate
5430Sstevel@tonic-gate if ((ret = hvio_iommu_getmap(DIP_TO_HANDLE(dip), tsbid,
5441617Sgovinda attr_p, r_addr_p)) != H_EOK) {
5450Sstevel@tonic-gate DBG(DBG_LIB_DMA, dip,
5460Sstevel@tonic-gate "hvio_iommu_getmap failed, ret 0x%lx\n", ret);
5470Sstevel@tonic-gate
5480Sstevel@tonic-gate return ((ret == H_ENOMAP) ? DDI_DMA_NOMAPPING:DDI_FAILURE);
5490Sstevel@tonic-gate }
5500Sstevel@tonic-gate
5519707SDaniel.Ice@Sun.COM DBG(DBG_LIB_DMA, dip, "px_lib_iommu_getmap: attr 0x%llx "
5529707SDaniel.Ice@Sun.COM "r_addr 0x%llx\n", *attr_p, *r_addr_p);
5530Sstevel@tonic-gate
5540Sstevel@tonic-gate return (DDI_SUCCESS);
5550Sstevel@tonic-gate }
5560Sstevel@tonic-gate
5571772Sjl139090 /*ARGSUSED*/
558*12619Sandrew.rutz@sun.com int
px_lib_iommu_detach(px_t * px_p)559*12619Sandrew.rutz@sun.com px_lib_iommu_detach(px_t *px_p)
560*12619Sandrew.rutz@sun.com {
561*12619Sandrew.rutz@sun.com return (DDI_SUCCESS);
562*12619Sandrew.rutz@sun.com }
563*12619Sandrew.rutz@sun.com
564*12619Sandrew.rutz@sun.com /*ARGSUSED*/
5651772Sjl139090 uint64_t
px_get_rng_parent_hi_mask(px_t * px_p)5662053Sschwartz px_get_rng_parent_hi_mask(px_t *px_p)
5671772Sjl139090 {
5682053Sschwartz return (PX_RANGE_PROP_MASK);
5691772Sjl139090 }
5700Sstevel@tonic-gate
5710Sstevel@tonic-gate /*
5720Sstevel@tonic-gate * Checks dma attributes against system bypass ranges
5730Sstevel@tonic-gate * A sun4v device must be capable of generating the entire 64-bit
5740Sstevel@tonic-gate * address in order to perform bypass DMA.
5750Sstevel@tonic-gate */
5760Sstevel@tonic-gate /*ARGSUSED*/
5770Sstevel@tonic-gate int
px_lib_dma_bypass_rngchk(dev_info_t * dip,ddi_dma_attr_t * attr_p,uint64_t * lo_p,uint64_t * hi_p)5781772Sjl139090 px_lib_dma_bypass_rngchk(dev_info_t *dip, ddi_dma_attr_t *attr_p,
5791772Sjl139090 uint64_t *lo_p, uint64_t *hi_p)
5800Sstevel@tonic-gate {
5811617Sgovinda if ((attr_p->dma_attr_addr_lo != 0ull) ||
5821617Sgovinda (attr_p->dma_attr_addr_hi != UINT64_MAX)) {
5830Sstevel@tonic-gate
5840Sstevel@tonic-gate return (DDI_DMA_BADATTR);
5850Sstevel@tonic-gate }
5860Sstevel@tonic-gate
5870Sstevel@tonic-gate *lo_p = 0ull;
5880Sstevel@tonic-gate *hi_p = UINT64_MAX;
5890Sstevel@tonic-gate
5900Sstevel@tonic-gate return (DDI_SUCCESS);
5910Sstevel@tonic-gate }
5920Sstevel@tonic-gate
5930Sstevel@tonic-gate
5940Sstevel@tonic-gate /*ARGSUSED*/
5950Sstevel@tonic-gate int
px_lib_iommu_getbypass(dev_info_t * dip,r_addr_t ra,io_attributes_t attr,io_addr_t * io_addr_p)5961617Sgovinda px_lib_iommu_getbypass(dev_info_t *dip, r_addr_t ra, io_attributes_t attr,
5971617Sgovinda io_addr_t *io_addr_p)
5980Sstevel@tonic-gate {
5990Sstevel@tonic-gate uint64_t ret;
6000Sstevel@tonic-gate
6010Sstevel@tonic-gate DBG(DBG_LIB_DMA, dip, "px_lib_iommu_getbypass: dip 0x%p ra 0x%llx "
6029707SDaniel.Ice@Sun.COM "attr 0x%llx\n", dip, ra, attr);
60311630Sandrew.rutz@sun.com /*
60412262SAlan.Adamson@Sun.COM * If HV VPCI version is 2.0 and higher, pass BDF, phantom function,
60511630Sandrew.rutz@sun.com * and relaxed ordering attributes. Otherwise, pass only read or write
60611630Sandrew.rutz@sun.com * attribute.
60711630Sandrew.rutz@sun.com */
60812262SAlan.Adamson@Sun.COM if ((px_vpci_maj_ver == PX_HSVC_MAJOR_VER_1) &&
60912262SAlan.Adamson@Sun.COM (px_vpci_min_ver == PX_HSVC_MINOR_VER_0))
61011630Sandrew.rutz@sun.com attr &= PCI_MAP_ATTR_READ | PCI_MAP_ATTR_WRITE;
6110Sstevel@tonic-gate
6120Sstevel@tonic-gate if ((ret = hvio_iommu_getbypass(DIP_TO_HANDLE(dip), ra,
6131617Sgovinda attr, io_addr_p)) != H_EOK) {
6140Sstevel@tonic-gate DBG(DBG_LIB_DMA, dip,
6150Sstevel@tonic-gate "hvio_iommu_getbypass failed, ret 0x%lx\n", ret);
6160Sstevel@tonic-gate return (ret == H_ENOTSUPPORTED ? DDI_ENOTSUP : DDI_FAILURE);
6170Sstevel@tonic-gate }
6180Sstevel@tonic-gate
6190Sstevel@tonic-gate DBG(DBG_LIB_DMA, dip, "px_lib_iommu_getbypass: io_addr 0x%llx\n",
6200Sstevel@tonic-gate *io_addr_p);
6210Sstevel@tonic-gate
6220Sstevel@tonic-gate return (DDI_SUCCESS);
6230Sstevel@tonic-gate }
6240Sstevel@tonic-gate
6258691SLida.Horn@Sun.COM /*
6268691SLida.Horn@Sun.COM * Returns any needed IO address bit(s) for relaxed ordering in IOMMU
6278691SLida.Horn@Sun.COM * bypass mode.
6288691SLida.Horn@Sun.COM */
6298691SLida.Horn@Sun.COM /* ARGSUSED */
6308691SLida.Horn@Sun.COM uint64_t
px_lib_ro_bypass(dev_info_t * dip,io_attributes_t attr,uint64_t ioaddr)6318691SLida.Horn@Sun.COM px_lib_ro_bypass(dev_info_t *dip, io_attributes_t attr, uint64_t ioaddr)
6328691SLida.Horn@Sun.COM {
6338691SLida.Horn@Sun.COM return (ioaddr);
6348691SLida.Horn@Sun.COM }
6358691SLida.Horn@Sun.COM
6360Sstevel@tonic-gate /*ARGSUSED*/
6370Sstevel@tonic-gate int
px_lib_dma_sync(dev_info_t * dip,dev_info_t * rdip,ddi_dma_handle_t handle,off_t off,size_t len,uint_t cache_flags)6380Sstevel@tonic-gate px_lib_dma_sync(dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t handle,
6390Sstevel@tonic-gate off_t off, size_t len, uint_t cache_flags)
6400Sstevel@tonic-gate {
6410Sstevel@tonic-gate ddi_dma_impl_t *mp = (ddi_dma_impl_t *)handle;
6420Sstevel@tonic-gate uint64_t sync_dir;
6433107Saa72041 size_t bytes_synced;
6443107Saa72041 int end, idx;
6453107Saa72041 off_t pg_off;
6463107Saa72041 devhandle_t hdl = DIP_TO_HANDLE(dip); /* need to cache hdl */
6470Sstevel@tonic-gate
6480Sstevel@tonic-gate DBG(DBG_LIB_DMA, dip, "px_lib_dma_sync: dip 0x%p rdip 0x%p "
6490Sstevel@tonic-gate "handle 0x%llx off 0x%x len 0x%x flags 0x%x\n",
6500Sstevel@tonic-gate dip, rdip, handle, off, len, cache_flags);
6510Sstevel@tonic-gate
652909Segillett if (!(mp->dmai_flags & PX_DMAI_FLAGS_INUSE)) {
65327Sjchu cmn_err(CE_WARN, "%s%d: Unbound dma handle %p.",
65427Sjchu ddi_driver_name(rdip), ddi_get_instance(rdip), (void *)mp);
6550Sstevel@tonic-gate return (DDI_FAILURE);
6560Sstevel@tonic-gate }
6570Sstevel@tonic-gate
658909Segillett if (mp->dmai_flags & PX_DMAI_FLAGS_NOSYNC)
6590Sstevel@tonic-gate return (DDI_SUCCESS);
6600Sstevel@tonic-gate
6610Sstevel@tonic-gate if (!len)
6620Sstevel@tonic-gate len = mp->dmai_size;
6630Sstevel@tonic-gate
6640Sstevel@tonic-gate if (mp->dmai_rflags & DDI_DMA_READ)
6650Sstevel@tonic-gate sync_dir = HVIO_DMA_SYNC_DIR_FROM_DEV;
6660Sstevel@tonic-gate else
6670Sstevel@tonic-gate sync_dir = HVIO_DMA_SYNC_DIR_TO_DEV;
6680Sstevel@tonic-gate
6693107Saa72041 off += mp->dmai_offset;
6703107Saa72041 pg_off = off & MMU_PAGEOFFSET;
6713107Saa72041
6723107Saa72041 DBG(DBG_LIB_DMA, dip, "px_lib_dma_sync: page offset %x size %x\n",
6733107Saa72041 pg_off, len);
6743107Saa72041
6753107Saa72041 /* sync on page basis */
6763107Saa72041 end = MMU_BTOPR(off + len - 1);
6773107Saa72041 for (idx = MMU_BTOP(off); idx < end; idx++,
6783107Saa72041 len -= bytes_synced, pg_off = 0) {
67910271SJason.Beloro@Sun.COM size_t bytes_to_sync = bytes_to_sync =
68010271SJason.Beloro@Sun.COM MIN(len, MMU_PAGESIZE - pg_off);
6813107Saa72041
68210271SJason.Beloro@Sun.COM if (hvio_dma_sync(hdl, MMU_PTOB(PX_GET_MP_PFN(mp, idx)) +
68310271SJason.Beloro@Sun.COM pg_off, bytes_to_sync, sync_dir, &bytes_synced) != H_EOK)
68410271SJason.Beloro@Sun.COM break;
6853107Saa72041
6863107Saa72041 DBG(DBG_LIB_DMA, dip, "px_lib_dma_sync: Called hvio_dma_sync "
6873107Saa72041 "ra = %p bytes to sync = %x bytes synced %x\n",
6883107Saa72041 MMU_PTOB(PX_GET_MP_PFN(mp, idx)) + pg_off, bytes_to_sync,
6893107Saa72041 bytes_synced);
6903107Saa72041
6913107Saa72041 if (bytes_to_sync != bytes_synced)
6923107Saa72041 break;
6930Sstevel@tonic-gate }
6940Sstevel@tonic-gate
6953107Saa72041 return (len ? DDI_FAILURE : DDI_SUCCESS);
6960Sstevel@tonic-gate }
6970Sstevel@tonic-gate
6980Sstevel@tonic-gate
6990Sstevel@tonic-gate /*
7000Sstevel@tonic-gate * MSIQ Functions:
7010Sstevel@tonic-gate */
7020Sstevel@tonic-gate
7030Sstevel@tonic-gate /*ARGSUSED*/
7040Sstevel@tonic-gate int
px_lib_msiq_init(dev_info_t * dip)7050Sstevel@tonic-gate px_lib_msiq_init(dev_info_t *dip)
7060Sstevel@tonic-gate {
7070Sstevel@tonic-gate px_t *px_p = DIP_TO_STATE(dip);
7080Sstevel@tonic-gate px_msiq_state_t *msiq_state_p = &px_p->px_ib_p->ib_msiq_state;
7092755Segillett r_addr_t ra;
7100Sstevel@tonic-gate size_t msiq_size;
7110Sstevel@tonic-gate uint_t rec_cnt;
7120Sstevel@tonic-gate int i, err = DDI_SUCCESS;
7130Sstevel@tonic-gate uint64_t ret;
7140Sstevel@tonic-gate
7150Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_init: dip 0x%p\n", dip);
7160Sstevel@tonic-gate
7170Sstevel@tonic-gate msiq_size = msiq_state_p->msiq_rec_cnt * sizeof (msiq_rec_t);
7180Sstevel@tonic-gate
7197403SAlan.Adamson@Sun.COM /* sun4v requires all EQ allocation to be on q size boundary */
7207403SAlan.Adamson@Sun.COM if ((msiq_state_p->msiq_buf_p = contig_mem_alloc_align(
7217403SAlan.Adamson@Sun.COM msiq_state_p->msiq_cnt * msiq_size, msiq_size)) == NULL) {
7227403SAlan.Adamson@Sun.COM DBG(DBG_LIB_MSIQ, dip,
7237403SAlan.Adamson@Sun.COM "px_lib_msiq_init: Contig alloc failed\n");
7247403SAlan.Adamson@Sun.COM
7257403SAlan.Adamson@Sun.COM return (DDI_FAILURE);
7267403SAlan.Adamson@Sun.COM }
7277403SAlan.Adamson@Sun.COM
7280Sstevel@tonic-gate for (i = 0; i < msiq_state_p->msiq_cnt; i++) {
7297403SAlan.Adamson@Sun.COM msiq_state_p->msiq_p[i].msiq_base_p = (msiqhead_t *)
7307403SAlan.Adamson@Sun.COM ((caddr_t)msiq_state_p->msiq_buf_p + (i * msiq_size));
7317403SAlan.Adamson@Sun.COM
7322755Segillett ra = (r_addr_t)va_to_pa((caddr_t)msiq_state_p->msiq_buf_p +
7332755Segillett (i * msiq_size));
7340Sstevel@tonic-gate
7350Sstevel@tonic-gate if ((ret = hvio_msiq_conf(DIP_TO_HANDLE(dip),
7360Sstevel@tonic-gate (i + msiq_state_p->msiq_1st_msiq_id),
7370Sstevel@tonic-gate ra, msiq_state_p->msiq_rec_cnt)) != H_EOK) {
7380Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip,
7390Sstevel@tonic-gate "hvio_msiq_conf failed, ret 0x%lx\n", ret);
7400Sstevel@tonic-gate err = DDI_FAILURE;
7410Sstevel@tonic-gate break;
7420Sstevel@tonic-gate }
7430Sstevel@tonic-gate
7440Sstevel@tonic-gate if ((err = px_lib_msiq_info(dip,
7450Sstevel@tonic-gate (i + msiq_state_p->msiq_1st_msiq_id),
7460Sstevel@tonic-gate &ra, &rec_cnt)) != DDI_SUCCESS) {
7470Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip,
7480Sstevel@tonic-gate "px_lib_msiq_info failed, ret 0x%x\n", err);
7490Sstevel@tonic-gate err = DDI_FAILURE;
7500Sstevel@tonic-gate break;
7510Sstevel@tonic-gate }
7520Sstevel@tonic-gate
7530Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip,
7540Sstevel@tonic-gate "px_lib_msiq_init: ra 0x%p rec_cnt 0x%x\n", ra, rec_cnt);
7550Sstevel@tonic-gate }
7560Sstevel@tonic-gate
7570Sstevel@tonic-gate return (err);
7580Sstevel@tonic-gate }
7590Sstevel@tonic-gate
7600Sstevel@tonic-gate /*ARGSUSED*/
7610Sstevel@tonic-gate int
px_lib_msiq_fini(dev_info_t * dip)7620Sstevel@tonic-gate px_lib_msiq_fini(dev_info_t *dip)
7630Sstevel@tonic-gate {
7647403SAlan.Adamson@Sun.COM px_t *px_p = DIP_TO_STATE(dip);
7657403SAlan.Adamson@Sun.COM px_msiq_state_t *msiq_state_p = &px_p->px_ib_p->ib_msiq_state;
7667403SAlan.Adamson@Sun.COM size_t msiq_size;
7677403SAlan.Adamson@Sun.COM
7680Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_fini: dip 0x%p\n", dip);
7697403SAlan.Adamson@Sun.COM msiq_size = msiq_state_p->msiq_rec_cnt * sizeof (msiq_rec_t);
7707403SAlan.Adamson@Sun.COM
7717403SAlan.Adamson@Sun.COM if (msiq_state_p->msiq_buf_p != NULL)
7727403SAlan.Adamson@Sun.COM contig_mem_free(msiq_state_p->msiq_buf_p,
7737403SAlan.Adamson@Sun.COM msiq_state_p->msiq_cnt * msiq_size);
7740Sstevel@tonic-gate
7750Sstevel@tonic-gate return (DDI_SUCCESS);
7760Sstevel@tonic-gate }
7770Sstevel@tonic-gate
7780Sstevel@tonic-gate /*ARGSUSED*/
7790Sstevel@tonic-gate int
px_lib_msiq_info(dev_info_t * dip,msiqid_t msiq_id,r_addr_t * ra_p,uint_t * msiq_rec_cnt_p)7800Sstevel@tonic-gate px_lib_msiq_info(dev_info_t *dip, msiqid_t msiq_id, r_addr_t *ra_p,
7810Sstevel@tonic-gate uint_t *msiq_rec_cnt_p)
7820Sstevel@tonic-gate {
7830Sstevel@tonic-gate uint64_t ret;
7840Sstevel@tonic-gate
7850Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_msiq_info: dip 0x%p msiq_id 0x%x\n",
7860Sstevel@tonic-gate dip, msiq_id);
7870Sstevel@tonic-gate
7880Sstevel@tonic-gate if ((ret = hvio_msiq_info(DIP_TO_HANDLE(dip),
7890Sstevel@tonic-gate msiq_id, ra_p, msiq_rec_cnt_p)) != H_EOK) {
7900Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip,
7910Sstevel@tonic-gate "hvio_msiq_info failed, ret 0x%lx\n", ret);
7920Sstevel@tonic-gate return (DDI_FAILURE);
7930Sstevel@tonic-gate }
7940Sstevel@tonic-gate
7950Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_msiq_info: ra_p 0x%p msiq_rec_cnt 0x%x\n",
7960Sstevel@tonic-gate ra_p, *msiq_rec_cnt_p);
7970Sstevel@tonic-gate
7980Sstevel@tonic-gate return (DDI_SUCCESS);
7990Sstevel@tonic-gate }
8000Sstevel@tonic-gate
8010Sstevel@tonic-gate /*ARGSUSED*/
8020Sstevel@tonic-gate int
px_lib_msiq_getvalid(dev_info_t * dip,msiqid_t msiq_id,pci_msiq_valid_state_t * msiq_valid_state)8030Sstevel@tonic-gate px_lib_msiq_getvalid(dev_info_t *dip, msiqid_t msiq_id,
8040Sstevel@tonic-gate pci_msiq_valid_state_t *msiq_valid_state)
8050Sstevel@tonic-gate {
8060Sstevel@tonic-gate uint64_t ret;
8070Sstevel@tonic-gate
8080Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_getvalid: dip 0x%p msiq_id 0x%x\n",
8090Sstevel@tonic-gate dip, msiq_id);
8100Sstevel@tonic-gate
8110Sstevel@tonic-gate if ((ret = hvio_msiq_getvalid(DIP_TO_HANDLE(dip),
8120Sstevel@tonic-gate msiq_id, msiq_valid_state)) != H_EOK) {
8130Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip,
8140Sstevel@tonic-gate "hvio_msiq_getvalid failed, ret 0x%lx\n", ret);
8150Sstevel@tonic-gate return (DDI_FAILURE);
8160Sstevel@tonic-gate }
8170Sstevel@tonic-gate
8180Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_getvalid: msiq_valid_state 0x%x\n",
8190Sstevel@tonic-gate *msiq_valid_state);
8200Sstevel@tonic-gate
8210Sstevel@tonic-gate return (DDI_SUCCESS);
8220Sstevel@tonic-gate }
8230Sstevel@tonic-gate
8240Sstevel@tonic-gate /*ARGSUSED*/
8250Sstevel@tonic-gate int
px_lib_msiq_setvalid(dev_info_t * dip,msiqid_t msiq_id,pci_msiq_valid_state_t msiq_valid_state)8260Sstevel@tonic-gate px_lib_msiq_setvalid(dev_info_t *dip, msiqid_t msiq_id,
8270Sstevel@tonic-gate pci_msiq_valid_state_t msiq_valid_state)
8280Sstevel@tonic-gate {
8290Sstevel@tonic-gate uint64_t ret;
8300Sstevel@tonic-gate
8310Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_setvalid: dip 0x%p msiq_id 0x%x "
8320Sstevel@tonic-gate "msiq_valid_state 0x%x\n", dip, msiq_id, msiq_valid_state);
8330Sstevel@tonic-gate
8340Sstevel@tonic-gate if ((ret = hvio_msiq_setvalid(DIP_TO_HANDLE(dip),
8350Sstevel@tonic-gate msiq_id, msiq_valid_state)) != H_EOK) {
8360Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip,
8370Sstevel@tonic-gate "hvio_msiq_setvalid failed, ret 0x%lx\n", ret);
8380Sstevel@tonic-gate return (DDI_FAILURE);
8390Sstevel@tonic-gate }
8400Sstevel@tonic-gate
8410Sstevel@tonic-gate return (DDI_SUCCESS);
8420Sstevel@tonic-gate }
8430Sstevel@tonic-gate
8440Sstevel@tonic-gate /*ARGSUSED*/
8450Sstevel@tonic-gate int
px_lib_msiq_getstate(dev_info_t * dip,msiqid_t msiq_id,pci_msiq_state_t * msiq_state)8460Sstevel@tonic-gate px_lib_msiq_getstate(dev_info_t *dip, msiqid_t msiq_id,
8470Sstevel@tonic-gate pci_msiq_state_t *msiq_state)
8480Sstevel@tonic-gate {
8490Sstevel@tonic-gate uint64_t ret;
8500Sstevel@tonic-gate
8510Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_getstate: dip 0x%p msiq_id 0x%x\n",
8520Sstevel@tonic-gate dip, msiq_id);
8530Sstevel@tonic-gate
8540Sstevel@tonic-gate if ((ret = hvio_msiq_getstate(DIP_TO_HANDLE(dip),
8550Sstevel@tonic-gate msiq_id, msiq_state)) != H_EOK) {
8560Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip,
8570Sstevel@tonic-gate "hvio_msiq_getstate failed, ret 0x%lx\n", ret);
8580Sstevel@tonic-gate return (DDI_FAILURE);
8590Sstevel@tonic-gate }
8600Sstevel@tonic-gate
8610Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_getstate: msiq_state 0x%x\n",
8620Sstevel@tonic-gate *msiq_state);
8630Sstevel@tonic-gate
8640Sstevel@tonic-gate return (DDI_SUCCESS);
8650Sstevel@tonic-gate }
8660Sstevel@tonic-gate
8670Sstevel@tonic-gate /*ARGSUSED*/
8680Sstevel@tonic-gate int
px_lib_msiq_setstate(dev_info_t * dip,msiqid_t msiq_id,pci_msiq_state_t msiq_state)8690Sstevel@tonic-gate px_lib_msiq_setstate(dev_info_t *dip, msiqid_t msiq_id,
8700Sstevel@tonic-gate pci_msiq_state_t msiq_state)
8710Sstevel@tonic-gate {
8720Sstevel@tonic-gate uint64_t ret;
8730Sstevel@tonic-gate
8740Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_setstate: dip 0x%p msiq_id 0x%x "
8750Sstevel@tonic-gate "msiq_state 0x%x\n", dip, msiq_id, msiq_state);
8760Sstevel@tonic-gate
8770Sstevel@tonic-gate if ((ret = hvio_msiq_setstate(DIP_TO_HANDLE(dip),
8780Sstevel@tonic-gate msiq_id, msiq_state)) != H_EOK) {
8790Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip,
8800Sstevel@tonic-gate "hvio_msiq_setstate failed, ret 0x%lx\n", ret);
8810Sstevel@tonic-gate return (DDI_FAILURE);
8820Sstevel@tonic-gate }
8830Sstevel@tonic-gate
8840Sstevel@tonic-gate return (DDI_SUCCESS);
8850Sstevel@tonic-gate }
8860Sstevel@tonic-gate
8870Sstevel@tonic-gate /*ARGSUSED*/
8880Sstevel@tonic-gate int
px_lib_msiq_gethead(dev_info_t * dip,msiqid_t msiq_id,msiqhead_t * msiq_head_p)8890Sstevel@tonic-gate px_lib_msiq_gethead(dev_info_t *dip, msiqid_t msiq_id,
8900Sstevel@tonic-gate msiqhead_t *msiq_head_p)
8910Sstevel@tonic-gate {
8920Sstevel@tonic-gate uint64_t ret;
8930Sstevel@tonic-gate
8940Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_gethead: dip 0x%p msiq_id 0x%x\n",
8950Sstevel@tonic-gate dip, msiq_id);
8960Sstevel@tonic-gate
8970Sstevel@tonic-gate if ((ret = hvio_msiq_gethead(DIP_TO_HANDLE(dip),
8980Sstevel@tonic-gate msiq_id, msiq_head_p)) != H_EOK) {
8990Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip,
9000Sstevel@tonic-gate "hvio_msiq_gethead failed, ret 0x%lx\n", ret);
9010Sstevel@tonic-gate return (DDI_FAILURE);
9020Sstevel@tonic-gate }
9030Sstevel@tonic-gate
9040Sstevel@tonic-gate *msiq_head_p = (*msiq_head_p / sizeof (msiq_rec_t));
9050Sstevel@tonic-gate
9060Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_msiq_gethead: msiq_head 0x%x\n",
9070Sstevel@tonic-gate *msiq_head_p);
9080Sstevel@tonic-gate
9090Sstevel@tonic-gate return (DDI_SUCCESS);
9100Sstevel@tonic-gate }
9110Sstevel@tonic-gate
9120Sstevel@tonic-gate /*ARGSUSED*/
9130Sstevel@tonic-gate int
px_lib_msiq_sethead(dev_info_t * dip,msiqid_t msiq_id,msiqhead_t msiq_head)9140Sstevel@tonic-gate px_lib_msiq_sethead(dev_info_t *dip, msiqid_t msiq_id,
9150Sstevel@tonic-gate msiqhead_t msiq_head)
9160Sstevel@tonic-gate {
9170Sstevel@tonic-gate uint64_t ret;
9180Sstevel@tonic-gate
9190Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_sethead: dip 0x%p msiq_id 0x%x "
9200Sstevel@tonic-gate "msiq_head 0x%x\n", dip, msiq_id, msiq_head);
9210Sstevel@tonic-gate
9220Sstevel@tonic-gate if ((ret = hvio_msiq_sethead(DIP_TO_HANDLE(dip),
9230Sstevel@tonic-gate msiq_id, msiq_head * sizeof (msiq_rec_t))) != H_EOK) {
9240Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip,
9250Sstevel@tonic-gate "hvio_msiq_sethead failed, ret 0x%lx\n", ret);
9260Sstevel@tonic-gate return (DDI_FAILURE);
9270Sstevel@tonic-gate }
9280Sstevel@tonic-gate
9290Sstevel@tonic-gate return (DDI_SUCCESS);
9300Sstevel@tonic-gate }
9310Sstevel@tonic-gate
9320Sstevel@tonic-gate /*ARGSUSED*/
9330Sstevel@tonic-gate int
px_lib_msiq_gettail(dev_info_t * dip,msiqid_t msiq_id,msiqtail_t * msiq_tail_p)9340Sstevel@tonic-gate px_lib_msiq_gettail(dev_info_t *dip, msiqid_t msiq_id,
9350Sstevel@tonic-gate msiqtail_t *msiq_tail_p)
9360Sstevel@tonic-gate {
9370Sstevel@tonic-gate uint64_t ret;
9380Sstevel@tonic-gate
9390Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_gettail: dip 0x%p msiq_id 0x%x\n",
9400Sstevel@tonic-gate dip, msiq_id);
9410Sstevel@tonic-gate
9420Sstevel@tonic-gate if ((ret = hvio_msiq_gettail(DIP_TO_HANDLE(dip),
9430Sstevel@tonic-gate msiq_id, msiq_tail_p)) != H_EOK) {
9440Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip,
9450Sstevel@tonic-gate "hvio_msiq_gettail failed, ret 0x%lx\n", ret);
9460Sstevel@tonic-gate return (DDI_FAILURE);
9470Sstevel@tonic-gate }
9480Sstevel@tonic-gate
9490Sstevel@tonic-gate *msiq_tail_p = (*msiq_tail_p / sizeof (msiq_rec_t));
9500Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_gettail: msiq_tail 0x%x\n",
9510Sstevel@tonic-gate *msiq_tail_p);
9520Sstevel@tonic-gate
9530Sstevel@tonic-gate return (DDI_SUCCESS);
9540Sstevel@tonic-gate }
9550Sstevel@tonic-gate
9560Sstevel@tonic-gate /*ARGSUSED*/
9570Sstevel@tonic-gate void
px_lib_get_msiq_rec(dev_info_t * dip,msiqhead_t * msiq_head_p,msiq_rec_t * msiq_rec_p)9582588Segillett px_lib_get_msiq_rec(dev_info_t *dip, msiqhead_t *msiq_head_p,
9592588Segillett msiq_rec_t *msiq_rec_p)
9600Sstevel@tonic-gate {
9612588Segillett msiq_rec_t *curr_msiq_rec_p = (msiq_rec_t *)msiq_head_p;
9620Sstevel@tonic-gate
9630Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_lib_get_msiq_rec: dip 0x%p\n", dip);
9640Sstevel@tonic-gate
9652973Sgovinda if (!curr_msiq_rec_p->msiq_rec_type) {
9662973Sgovinda /* Set msiq_rec_type to zero */
9672973Sgovinda msiq_rec_p->msiq_rec_type = 0;
9682973Sgovinda
9690Sstevel@tonic-gate return;
9702973Sgovinda }
9710Sstevel@tonic-gate
9720Sstevel@tonic-gate *msiq_rec_p = *curr_msiq_rec_p;
9732973Sgovinda }
9742973Sgovinda
9752973Sgovinda /*ARGSUSED*/
9762973Sgovinda void
px_lib_clr_msiq_rec(dev_info_t * dip,msiqhead_t * msiq_head_p)9772973Sgovinda px_lib_clr_msiq_rec(dev_info_t *dip, msiqhead_t *msiq_head_p)
9782973Sgovinda {
9792973Sgovinda msiq_rec_t *curr_msiq_rec_p = (msiq_rec_t *)msiq_head_p;
9802973Sgovinda
9812973Sgovinda DBG(DBG_LIB_MSIQ, dip, "px_lib_clr_msiq_rec: dip 0x%p\n", dip);
9820Sstevel@tonic-gate
983287Smg140465 /* Zero out msiq_rec_type field */
984287Smg140465 curr_msiq_rec_p->msiq_rec_type = 0;
9850Sstevel@tonic-gate }
9860Sstevel@tonic-gate
9870Sstevel@tonic-gate /*
9880Sstevel@tonic-gate * MSI Functions:
9890Sstevel@tonic-gate */
9900Sstevel@tonic-gate
9910Sstevel@tonic-gate /*ARGSUSED*/
9920Sstevel@tonic-gate int
px_lib_msi_init(dev_info_t * dip)9930Sstevel@tonic-gate px_lib_msi_init(dev_info_t *dip)
9940Sstevel@tonic-gate {
9950Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip, "px_lib_msi_init: dip 0x%p\n", dip);
9960Sstevel@tonic-gate
9970Sstevel@tonic-gate /* Noop */
9980Sstevel@tonic-gate return (DDI_SUCCESS);
9990Sstevel@tonic-gate }
10000Sstevel@tonic-gate
10010Sstevel@tonic-gate /*ARGSUSED*/
10020Sstevel@tonic-gate int
px_lib_msi_getmsiq(dev_info_t * dip,msinum_t msi_num,msiqid_t * msiq_id)10030Sstevel@tonic-gate px_lib_msi_getmsiq(dev_info_t *dip, msinum_t msi_num,
10040Sstevel@tonic-gate msiqid_t *msiq_id)
10050Sstevel@tonic-gate {
10060Sstevel@tonic-gate uint64_t ret;
10070Sstevel@tonic-gate
10080Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip, "px_lib_msi_getmsiq: dip 0x%p msi_num 0x%x\n",
10090Sstevel@tonic-gate dip, msi_num);
10100Sstevel@tonic-gate
10110Sstevel@tonic-gate if ((ret = hvio_msi_getmsiq(DIP_TO_HANDLE(dip),
10120Sstevel@tonic-gate msi_num, msiq_id)) != H_EOK) {
10130Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip,
10140Sstevel@tonic-gate "hvio_msi_getmsiq failed, ret 0x%lx\n", ret);
10150Sstevel@tonic-gate return (DDI_FAILURE);
10160Sstevel@tonic-gate }
10170Sstevel@tonic-gate
10180Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip, "px_lib_msi_getmsiq: msiq_id 0x%x\n",
10190Sstevel@tonic-gate *msiq_id);
10200Sstevel@tonic-gate
10210Sstevel@tonic-gate return (DDI_SUCCESS);
10220Sstevel@tonic-gate }
10230Sstevel@tonic-gate
10240Sstevel@tonic-gate /*ARGSUSED*/
10250Sstevel@tonic-gate int
px_lib_msi_setmsiq(dev_info_t * dip,msinum_t msi_num,msiqid_t msiq_id,msi_type_t msitype)10260Sstevel@tonic-gate px_lib_msi_setmsiq(dev_info_t *dip, msinum_t msi_num,
10270Sstevel@tonic-gate msiqid_t msiq_id, msi_type_t msitype)
10280Sstevel@tonic-gate {
10290Sstevel@tonic-gate uint64_t ret;
10300Sstevel@tonic-gate
10310Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip, "px_lib_msi_setmsiq: dip 0x%p msi_num 0x%x "
10320Sstevel@tonic-gate "msq_id 0x%x\n", dip, msi_num, msiq_id);
10330Sstevel@tonic-gate
10340Sstevel@tonic-gate if ((ret = hvio_msi_setmsiq(DIP_TO_HANDLE(dip),
10350Sstevel@tonic-gate msi_num, msiq_id, msitype)) != H_EOK) {
10360Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip,
10370Sstevel@tonic-gate "hvio_msi_setmsiq failed, ret 0x%lx\n", ret);
10380Sstevel@tonic-gate return (DDI_FAILURE);
10390Sstevel@tonic-gate }
10400Sstevel@tonic-gate
10410Sstevel@tonic-gate return (DDI_SUCCESS);
10420Sstevel@tonic-gate }
10430Sstevel@tonic-gate
10440Sstevel@tonic-gate /*ARGSUSED*/
10450Sstevel@tonic-gate int
px_lib_msi_getvalid(dev_info_t * dip,msinum_t msi_num,pci_msi_valid_state_t * msi_valid_state)10460Sstevel@tonic-gate px_lib_msi_getvalid(dev_info_t *dip, msinum_t msi_num,
10470Sstevel@tonic-gate pci_msi_valid_state_t *msi_valid_state)
10480Sstevel@tonic-gate {
10490Sstevel@tonic-gate uint64_t ret;
10500Sstevel@tonic-gate
10510Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip, "px_lib_msi_getvalid: dip 0x%p msi_num 0x%x\n",
10520Sstevel@tonic-gate dip, msi_num);
10530Sstevel@tonic-gate
10540Sstevel@tonic-gate if ((ret = hvio_msi_getvalid(DIP_TO_HANDLE(dip),
10550Sstevel@tonic-gate msi_num, msi_valid_state)) != H_EOK) {
10560Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip,
10570Sstevel@tonic-gate "hvio_msi_getvalid failed, ret 0x%lx\n", ret);
10580Sstevel@tonic-gate return (DDI_FAILURE);
10590Sstevel@tonic-gate }
10600Sstevel@tonic-gate
10610Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip, "px_lib_msi_getvalid: msiq_id 0x%x\n",
10620Sstevel@tonic-gate *msi_valid_state);
10630Sstevel@tonic-gate
10640Sstevel@tonic-gate return (DDI_SUCCESS);
10650Sstevel@tonic-gate }
10660Sstevel@tonic-gate
10670Sstevel@tonic-gate /*ARGSUSED*/
10680Sstevel@tonic-gate int
px_lib_msi_setvalid(dev_info_t * dip,msinum_t msi_num,pci_msi_valid_state_t msi_valid_state)10690Sstevel@tonic-gate px_lib_msi_setvalid(dev_info_t *dip, msinum_t msi_num,
10700Sstevel@tonic-gate pci_msi_valid_state_t msi_valid_state)
10710Sstevel@tonic-gate {
10720Sstevel@tonic-gate uint64_t ret;
10730Sstevel@tonic-gate
10740Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip, "px_lib_msi_setvalid: dip 0x%p msi_num 0x%x "
10750Sstevel@tonic-gate "msi_valid_state 0x%x\n", dip, msi_num, msi_valid_state);
10760Sstevel@tonic-gate
10770Sstevel@tonic-gate if ((ret = hvio_msi_setvalid(DIP_TO_HANDLE(dip),
10780Sstevel@tonic-gate msi_num, msi_valid_state)) != H_EOK) {
10790Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip,
10800Sstevel@tonic-gate "hvio_msi_setvalid failed, ret 0x%lx\n", ret);
10810Sstevel@tonic-gate return (DDI_FAILURE);
10820Sstevel@tonic-gate }
10830Sstevel@tonic-gate
10840Sstevel@tonic-gate return (DDI_SUCCESS);
10850Sstevel@tonic-gate }
10860Sstevel@tonic-gate
10870Sstevel@tonic-gate /*ARGSUSED*/
10880Sstevel@tonic-gate int
px_lib_msi_getstate(dev_info_t * dip,msinum_t msi_num,pci_msi_state_t * msi_state)10890Sstevel@tonic-gate px_lib_msi_getstate(dev_info_t *dip, msinum_t msi_num,
10900Sstevel@tonic-gate pci_msi_state_t *msi_state)
10910Sstevel@tonic-gate {
10920Sstevel@tonic-gate uint64_t ret;
10930Sstevel@tonic-gate
10940Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip, "px_lib_msi_getstate: dip 0x%p msi_num 0x%x\n",
10950Sstevel@tonic-gate dip, msi_num);
10960Sstevel@tonic-gate
10970Sstevel@tonic-gate if ((ret = hvio_msi_getstate(DIP_TO_HANDLE(dip),
10980Sstevel@tonic-gate msi_num, msi_state)) != H_EOK) {
10990Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip,
11000Sstevel@tonic-gate "hvio_msi_getstate failed, ret 0x%lx\n", ret);
11010Sstevel@tonic-gate return (DDI_FAILURE);
11020Sstevel@tonic-gate }
11030Sstevel@tonic-gate
11040Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip, "px_lib_msi_getstate: msi_state 0x%x\n",
11050Sstevel@tonic-gate *msi_state);
11060Sstevel@tonic-gate
11070Sstevel@tonic-gate return (DDI_SUCCESS);
11080Sstevel@tonic-gate }
11090Sstevel@tonic-gate
11100Sstevel@tonic-gate /*ARGSUSED*/
11110Sstevel@tonic-gate int
px_lib_msi_setstate(dev_info_t * dip,msinum_t msi_num,pci_msi_state_t msi_state)11120Sstevel@tonic-gate px_lib_msi_setstate(dev_info_t *dip, msinum_t msi_num,
11130Sstevel@tonic-gate pci_msi_state_t msi_state)
11140Sstevel@tonic-gate {
11150Sstevel@tonic-gate uint64_t ret;
11160Sstevel@tonic-gate
11170Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip, "px_lib_msi_setstate: dip 0x%p msi_num 0x%x "
11180Sstevel@tonic-gate "msi_state 0x%x\n", dip, msi_num, msi_state);
11190Sstevel@tonic-gate
11200Sstevel@tonic-gate if ((ret = hvio_msi_setstate(DIP_TO_HANDLE(dip),
11210Sstevel@tonic-gate msi_num, msi_state)) != H_EOK) {
11220Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip,
11230Sstevel@tonic-gate "hvio_msi_setstate failed, ret 0x%lx\n", ret);
11240Sstevel@tonic-gate return (DDI_FAILURE);
11250Sstevel@tonic-gate }
11260Sstevel@tonic-gate
11270Sstevel@tonic-gate return (DDI_SUCCESS);
11280Sstevel@tonic-gate }
11290Sstevel@tonic-gate
11300Sstevel@tonic-gate /*
11310Sstevel@tonic-gate * MSG Functions:
11320Sstevel@tonic-gate */
11330Sstevel@tonic-gate
11340Sstevel@tonic-gate /*ARGSUSED*/
11350Sstevel@tonic-gate int
px_lib_msg_getmsiq(dev_info_t * dip,pcie_msg_type_t msg_type,msiqid_t * msiq_id)11360Sstevel@tonic-gate px_lib_msg_getmsiq(dev_info_t *dip, pcie_msg_type_t msg_type,
11370Sstevel@tonic-gate msiqid_t *msiq_id)
11380Sstevel@tonic-gate {
11390Sstevel@tonic-gate uint64_t ret;
11400Sstevel@tonic-gate
11410Sstevel@tonic-gate DBG(DBG_LIB_MSG, dip, "px_lib_msg_getmsiq: dip 0x%p msg_type 0x%x\n",
11420Sstevel@tonic-gate dip, msg_type);
11430Sstevel@tonic-gate
11440Sstevel@tonic-gate if ((ret = hvio_msg_getmsiq(DIP_TO_HANDLE(dip),
11450Sstevel@tonic-gate msg_type, msiq_id)) != H_EOK) {
11460Sstevel@tonic-gate DBG(DBG_LIB_MSG, dip,
11470Sstevel@tonic-gate "hvio_msg_getmsiq failed, ret 0x%lx\n", ret);
11480Sstevel@tonic-gate return (DDI_FAILURE);
11490Sstevel@tonic-gate }
11500Sstevel@tonic-gate
11510Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip, "px_lib_msg_getmsiq: msiq_id 0x%x\n",
11520Sstevel@tonic-gate *msiq_id);
11530Sstevel@tonic-gate
11540Sstevel@tonic-gate return (DDI_SUCCESS);
11550Sstevel@tonic-gate }
11560Sstevel@tonic-gate
11570Sstevel@tonic-gate /*ARGSUSED*/
11580Sstevel@tonic-gate int
px_lib_msg_setmsiq(dev_info_t * dip,pcie_msg_type_t msg_type,msiqid_t msiq_id)11590Sstevel@tonic-gate px_lib_msg_setmsiq(dev_info_t *dip, pcie_msg_type_t msg_type,
11600Sstevel@tonic-gate msiqid_t msiq_id)
11610Sstevel@tonic-gate {
11620Sstevel@tonic-gate uint64_t ret;
11630Sstevel@tonic-gate
11640Sstevel@tonic-gate DBG(DBG_LIB_MSG, dip, "px_lib_msg_setmsiq: dip 0x%p msg_type 0x%x "
11650Sstevel@tonic-gate "msq_id 0x%x\n", dip, msg_type, msiq_id);
11660Sstevel@tonic-gate
11670Sstevel@tonic-gate if ((ret = hvio_msg_setmsiq(DIP_TO_HANDLE(dip),
11680Sstevel@tonic-gate msg_type, msiq_id)) != H_EOK) {
11690Sstevel@tonic-gate DBG(DBG_LIB_MSG, dip,
11700Sstevel@tonic-gate "hvio_msg_setmsiq failed, ret 0x%lx\n", ret);
11710Sstevel@tonic-gate return (DDI_FAILURE);
11720Sstevel@tonic-gate }
11730Sstevel@tonic-gate
11740Sstevel@tonic-gate return (DDI_SUCCESS);
11750Sstevel@tonic-gate }
11760Sstevel@tonic-gate
11770Sstevel@tonic-gate /*ARGSUSED*/
11780Sstevel@tonic-gate int
px_lib_msg_getvalid(dev_info_t * dip,pcie_msg_type_t msg_type,pcie_msg_valid_state_t * msg_valid_state)11790Sstevel@tonic-gate px_lib_msg_getvalid(dev_info_t *dip, pcie_msg_type_t msg_type,
11800Sstevel@tonic-gate pcie_msg_valid_state_t *msg_valid_state)
11810Sstevel@tonic-gate {
11820Sstevel@tonic-gate uint64_t ret;
11830Sstevel@tonic-gate
11840Sstevel@tonic-gate DBG(DBG_LIB_MSG, dip, "px_lib_msg_getvalid: dip 0x%p msg_type 0x%x\n",
11850Sstevel@tonic-gate dip, msg_type);
11860Sstevel@tonic-gate
11870Sstevel@tonic-gate if ((ret = hvio_msg_getvalid(DIP_TO_HANDLE(dip), msg_type,
11880Sstevel@tonic-gate msg_valid_state)) != H_EOK) {
11890Sstevel@tonic-gate DBG(DBG_LIB_MSG, dip,
11900Sstevel@tonic-gate "hvio_msg_getvalid failed, ret 0x%lx\n", ret);
11910Sstevel@tonic-gate return (DDI_FAILURE);
11920Sstevel@tonic-gate }
11930Sstevel@tonic-gate
11940Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip, "px_lib_msg_getvalid: msg_valid_state 0x%x\n",
11950Sstevel@tonic-gate *msg_valid_state);
11960Sstevel@tonic-gate
11970Sstevel@tonic-gate return (DDI_SUCCESS);
11980Sstevel@tonic-gate }
11990Sstevel@tonic-gate
12000Sstevel@tonic-gate /*ARGSUSED*/
12010Sstevel@tonic-gate int
px_lib_msg_setvalid(dev_info_t * dip,pcie_msg_type_t msg_type,pcie_msg_valid_state_t msg_valid_state)12020Sstevel@tonic-gate px_lib_msg_setvalid(dev_info_t *dip, pcie_msg_type_t msg_type,
12030Sstevel@tonic-gate pcie_msg_valid_state_t msg_valid_state)
12040Sstevel@tonic-gate {
12050Sstevel@tonic-gate uint64_t ret;
12060Sstevel@tonic-gate
12070Sstevel@tonic-gate DBG(DBG_LIB_MSG, dip, "px_lib_msg_setvalid: dip 0x%p msg_type 0x%x "
12080Sstevel@tonic-gate "msg_valid_state 0x%x\n", dip, msg_type, msg_valid_state);
12090Sstevel@tonic-gate
12100Sstevel@tonic-gate if ((ret = hvio_msg_setvalid(DIP_TO_HANDLE(dip), msg_type,
12110Sstevel@tonic-gate msg_valid_state)) != H_EOK) {
12120Sstevel@tonic-gate DBG(DBG_LIB_MSG, dip,
12130Sstevel@tonic-gate "hvio_msg_setvalid failed, ret 0x%lx\n", ret);
12140Sstevel@tonic-gate return (DDI_FAILURE);
12150Sstevel@tonic-gate }
12160Sstevel@tonic-gate
12170Sstevel@tonic-gate return (DDI_SUCCESS);
12180Sstevel@tonic-gate }
12190Sstevel@tonic-gate
12200Sstevel@tonic-gate /*
12210Sstevel@tonic-gate * Suspend/Resume Functions:
12220Sstevel@tonic-gate * Currently unsupported by hypervisor and all functions are noops.
12230Sstevel@tonic-gate */
12240Sstevel@tonic-gate /*ARGSUSED*/
12250Sstevel@tonic-gate int
px_lib_suspend(dev_info_t * dip)12260Sstevel@tonic-gate px_lib_suspend(dev_info_t *dip)
12270Sstevel@tonic-gate {
12280Sstevel@tonic-gate DBG(DBG_ATTACH, dip, "px_lib_suspend: Not supported\n");
12290Sstevel@tonic-gate
12300Sstevel@tonic-gate /* Not supported */
12310Sstevel@tonic-gate return (DDI_FAILURE);
12320Sstevel@tonic-gate }
12330Sstevel@tonic-gate
12340Sstevel@tonic-gate /*ARGSUSED*/
12350Sstevel@tonic-gate void
px_lib_resume(dev_info_t * dip)12360Sstevel@tonic-gate px_lib_resume(dev_info_t *dip)
12370Sstevel@tonic-gate {
12380Sstevel@tonic-gate DBG(DBG_ATTACH, dip, "px_lib_resume: Not supported\n");
12390Sstevel@tonic-gate
12400Sstevel@tonic-gate /* Noop */
12410Sstevel@tonic-gate }
12420Sstevel@tonic-gate
12430Sstevel@tonic-gate /*
12440Sstevel@tonic-gate * Misc Functions:
12450Sstevel@tonic-gate * Currently unsupported by hypervisor and all functions are noops.
12460Sstevel@tonic-gate */
12470Sstevel@tonic-gate /*ARGSUSED*/
12480Sstevel@tonic-gate static int
px_lib_config_get(dev_info_t * dip,pci_device_t bdf,pci_config_offset_t off,uint8_t size,pci_cfg_data_t * data_p)12490Sstevel@tonic-gate px_lib_config_get(dev_info_t *dip, pci_device_t bdf, pci_config_offset_t off,
12500Sstevel@tonic-gate uint8_t size, pci_cfg_data_t *data_p)
12510Sstevel@tonic-gate {
12520Sstevel@tonic-gate uint64_t ret;
12530Sstevel@tonic-gate
12540Sstevel@tonic-gate DBG(DBG_LIB_CFG, dip, "px_lib_config_get: dip 0x%p, bdf 0x%llx "
12550Sstevel@tonic-gate "off 0x%x size 0x%x\n", dip, bdf, off, size);
12560Sstevel@tonic-gate
12570Sstevel@tonic-gate if ((ret = hvio_config_get(DIP_TO_HANDLE(dip), bdf, off,
12580Sstevel@tonic-gate size, data_p)) != H_EOK) {
12590Sstevel@tonic-gate DBG(DBG_LIB_CFG, dip,
12600Sstevel@tonic-gate "hvio_config_get failed, ret 0x%lx\n", ret);
12610Sstevel@tonic-gate return (DDI_FAILURE);
12620Sstevel@tonic-gate }
12630Sstevel@tonic-gate DBG(DBG_LIB_CFG, dip, "px_config_get: data 0x%x\n", data_p->dw);
12640Sstevel@tonic-gate
12650Sstevel@tonic-gate return (DDI_SUCCESS);
12660Sstevel@tonic-gate }
12670Sstevel@tonic-gate
12680Sstevel@tonic-gate /*ARGSUSED*/
12690Sstevel@tonic-gate static int
px_lib_config_put(dev_info_t * dip,pci_device_t bdf,pci_config_offset_t off,uint8_t size,pci_cfg_data_t data)12700Sstevel@tonic-gate px_lib_config_put(dev_info_t *dip, pci_device_t bdf, pci_config_offset_t off,
12710Sstevel@tonic-gate uint8_t size, pci_cfg_data_t data)
12720Sstevel@tonic-gate {
12730Sstevel@tonic-gate uint64_t ret;
12740Sstevel@tonic-gate
12750Sstevel@tonic-gate DBG(DBG_LIB_CFG, dip, "px_lib_config_put: dip 0x%p, bdf 0x%llx "
12760Sstevel@tonic-gate "off 0x%x size 0x%x data 0x%llx\n", dip, bdf, off, size, data.qw);
12770Sstevel@tonic-gate
12780Sstevel@tonic-gate if ((ret = hvio_config_put(DIP_TO_HANDLE(dip), bdf, off,
12790Sstevel@tonic-gate size, data)) != H_EOK) {
12800Sstevel@tonic-gate DBG(DBG_LIB_CFG, dip,
12810Sstevel@tonic-gate "hvio_config_put failed, ret 0x%lx\n", ret);
12820Sstevel@tonic-gate return (DDI_FAILURE);
12830Sstevel@tonic-gate }
12840Sstevel@tonic-gate
12850Sstevel@tonic-gate return (DDI_SUCCESS);
12860Sstevel@tonic-gate }
12870Sstevel@tonic-gate
12880Sstevel@tonic-gate static uint32_t
px_pci_config_get(ddi_acc_impl_t * handle,uint32_t * addr,int size)12890Sstevel@tonic-gate px_pci_config_get(ddi_acc_impl_t *handle, uint32_t *addr, int size)
12900Sstevel@tonic-gate {
12916313Skrishnae px_config_acc_pvt_t *px_pvt = (px_config_acc_pvt_t *)
12926313Skrishnae handle->ahi_common.ah_bus_private;
129311596SJason.Beloro@Sun.COM pcie_bus_t *busp = NULL;
129411596SJason.Beloro@Sun.COM dev_info_t *cdip = NULL;
12950Sstevel@tonic-gate uint32_t pci_dev_addr = px_pvt->raddr;
12960Sstevel@tonic-gate uint32_t vaddr = px_pvt->vaddr;
1297671Skrishnae uint16_t off = (uint16_t)(uintptr_t)(addr - vaddr) & 0xfff;
129810595SShesha.Sreenivasamurthy@Sun.COM uint64_t rdata = 0;
12990Sstevel@tonic-gate
13000Sstevel@tonic-gate if (px_lib_config_get(px_pvt->dip, pci_dev_addr, off,
13016313Skrishnae size, (pci_cfg_data_t *)&rdata) != DDI_SUCCESS)
13020Sstevel@tonic-gate /* XXX update error kstats */
13030Sstevel@tonic-gate return (0xffffffff);
130411596SJason.Beloro@Sun.COM
130511596SJason.Beloro@Sun.COM if (cdip = pcie_find_dip_by_bdf(px_pvt->dip, pci_dev_addr >> 8))
130611596SJason.Beloro@Sun.COM busp = PCIE_DIP2BUS(cdip);
130711596SJason.Beloro@Sun.COM /*
130811596SJason.Beloro@Sun.COM * This can be called early, before busp or busp->bus_dom has
130911596SJason.Beloro@Sun.COM * been initialized, so check both before invoking
131011596SJason.Beloro@Sun.COM * PCIE_IS_ASSIGNED.
131111596SJason.Beloro@Sun.COM */
131211596SJason.Beloro@Sun.COM if (busp && PCIE_BUS2DOM(busp) && PCIE_IS_ASSIGNED(busp)) {
131311596SJason.Beloro@Sun.COM if (off == PCI_CONF_VENID && size == 2)
131411596SJason.Beloro@Sun.COM rdata = busp->bus_dev_ven_id & 0xffff;
131511596SJason.Beloro@Sun.COM else if (off == PCI_CONF_DEVID && size == 2)
131611596SJason.Beloro@Sun.COM rdata = busp->bus_dev_ven_id >> 16;
131711596SJason.Beloro@Sun.COM else if (off == PCI_CONF_VENID && size == 4)
131811596SJason.Beloro@Sun.COM rdata = busp->bus_dev_ven_id;
131911596SJason.Beloro@Sun.COM }
132010595SShesha.Sreenivasamurthy@Sun.COM return ((uint32_t)rdata);
13210Sstevel@tonic-gate }
13220Sstevel@tonic-gate
13230Sstevel@tonic-gate static void
px_pci_config_put(ddi_acc_impl_t * handle,uint32_t * addr,int size,pci_cfg_data_t wdata)13240Sstevel@tonic-gate px_pci_config_put(ddi_acc_impl_t *handle, uint32_t *addr,
13250Sstevel@tonic-gate int size, pci_cfg_data_t wdata)
13260Sstevel@tonic-gate {
13276313Skrishnae px_config_acc_pvt_t *px_pvt = (px_config_acc_pvt_t *)
13286313Skrishnae handle->ahi_common.ah_bus_private;
13290Sstevel@tonic-gate uint32_t pci_dev_addr = px_pvt->raddr;
13300Sstevel@tonic-gate uint32_t vaddr = px_pvt->vaddr;
1331671Skrishnae uint16_t off = (uint16_t)(uintptr_t)(addr - vaddr) & 0xfff;
13320Sstevel@tonic-gate
13330Sstevel@tonic-gate if (px_lib_config_put(px_pvt->dip, pci_dev_addr, off,
13346313Skrishnae size, wdata) != DDI_SUCCESS) {
13350Sstevel@tonic-gate /*EMPTY*/
13360Sstevel@tonic-gate /* XXX update error kstats */
13370Sstevel@tonic-gate }
13380Sstevel@tonic-gate }
13390Sstevel@tonic-gate
13400Sstevel@tonic-gate static uint8_t
px_pci_config_get8(ddi_acc_impl_t * handle,uint8_t * addr)13410Sstevel@tonic-gate px_pci_config_get8(ddi_acc_impl_t *handle, uint8_t *addr)
13420Sstevel@tonic-gate {
13430Sstevel@tonic-gate return ((uint8_t)px_pci_config_get(handle, (uint32_t *)addr, 1));
13440Sstevel@tonic-gate }
13450Sstevel@tonic-gate
13460Sstevel@tonic-gate static uint16_t
px_pci_config_get16(ddi_acc_impl_t * handle,uint16_t * addr)13470Sstevel@tonic-gate px_pci_config_get16(ddi_acc_impl_t *handle, uint16_t *addr)
13480Sstevel@tonic-gate {
13490Sstevel@tonic-gate return ((uint16_t)px_pci_config_get(handle, (uint32_t *)addr, 2));
13500Sstevel@tonic-gate }
13510Sstevel@tonic-gate
13520Sstevel@tonic-gate static uint32_t
px_pci_config_get32(ddi_acc_impl_t * handle,uint32_t * addr)13530Sstevel@tonic-gate px_pci_config_get32(ddi_acc_impl_t *handle, uint32_t *addr)
13540Sstevel@tonic-gate {
13550Sstevel@tonic-gate return ((uint32_t)px_pci_config_get(handle, (uint32_t *)addr, 4));
13560Sstevel@tonic-gate }
13570Sstevel@tonic-gate
13580Sstevel@tonic-gate static uint64_t
px_pci_config_get64(ddi_acc_impl_t * handle,uint64_t * addr)13590Sstevel@tonic-gate px_pci_config_get64(ddi_acc_impl_t *handle, uint64_t *addr)
13600Sstevel@tonic-gate {
13610Sstevel@tonic-gate uint32_t rdatah, rdatal;
13620Sstevel@tonic-gate
13630Sstevel@tonic-gate rdatal = (uint32_t)px_pci_config_get(handle, (uint32_t *)addr, 4);
13640Sstevel@tonic-gate rdatah = (uint32_t)px_pci_config_get(handle,
13656313Skrishnae (uint32_t *)((char *)addr+4), 4);
13660Sstevel@tonic-gate return (((uint64_t)rdatah << 32) | rdatal);
13670Sstevel@tonic-gate }
13680Sstevel@tonic-gate
13690Sstevel@tonic-gate static void
px_pci_config_put8(ddi_acc_impl_t * handle,uint8_t * addr,uint8_t data)13700Sstevel@tonic-gate px_pci_config_put8(ddi_acc_impl_t *handle, uint8_t *addr, uint8_t data)
13710Sstevel@tonic-gate {
13720Sstevel@tonic-gate pci_cfg_data_t wdata = { 0 };
13730Sstevel@tonic-gate
13740Sstevel@tonic-gate wdata.qw = (uint8_t)data;
13750Sstevel@tonic-gate px_pci_config_put(handle, (uint32_t *)addr, 1, wdata);
13760Sstevel@tonic-gate }
13770Sstevel@tonic-gate
13780Sstevel@tonic-gate static void
px_pci_config_put16(ddi_acc_impl_t * handle,uint16_t * addr,uint16_t data)13790Sstevel@tonic-gate px_pci_config_put16(ddi_acc_impl_t *handle, uint16_t *addr, uint16_t data)
13800Sstevel@tonic-gate {
13810Sstevel@tonic-gate pci_cfg_data_t wdata = { 0 };
13820Sstevel@tonic-gate
13830Sstevel@tonic-gate wdata.qw = (uint16_t)data;
13840Sstevel@tonic-gate px_pci_config_put(handle, (uint32_t *)addr, 2, wdata);
13850Sstevel@tonic-gate }
13860Sstevel@tonic-gate
13870Sstevel@tonic-gate static void
px_pci_config_put32(ddi_acc_impl_t * handle,uint32_t * addr,uint32_t data)13880Sstevel@tonic-gate px_pci_config_put32(ddi_acc_impl_t *handle, uint32_t *addr, uint32_t data)
13890Sstevel@tonic-gate {
13900Sstevel@tonic-gate pci_cfg_data_t wdata = { 0 };
13910Sstevel@tonic-gate
13920Sstevel@tonic-gate wdata.qw = (uint32_t)data;
13930Sstevel@tonic-gate px_pci_config_put(handle, (uint32_t *)addr, 4, wdata);
13940Sstevel@tonic-gate }
13950Sstevel@tonic-gate
13960Sstevel@tonic-gate static void
px_pci_config_put64(ddi_acc_impl_t * handle,uint64_t * addr,uint64_t data)13970Sstevel@tonic-gate px_pci_config_put64(ddi_acc_impl_t *handle, uint64_t *addr, uint64_t data)
13980Sstevel@tonic-gate {
13990Sstevel@tonic-gate pci_cfg_data_t wdata = { 0 };
14000Sstevel@tonic-gate
14010Sstevel@tonic-gate wdata.qw = (uint32_t)(data & 0xffffffff);
14020Sstevel@tonic-gate px_pci_config_put(handle, (uint32_t *)addr, 4, wdata);
14030Sstevel@tonic-gate wdata.qw = (uint32_t)((data >> 32) & 0xffffffff);
14040Sstevel@tonic-gate px_pci_config_put(handle, (uint32_t *)((char *)addr+4), 4, wdata);
14050Sstevel@tonic-gate }
14060Sstevel@tonic-gate
14070Sstevel@tonic-gate static void
px_pci_config_rep_get8(ddi_acc_impl_t * handle,uint8_t * host_addr,uint8_t * dev_addr,size_t repcount,uint_t flags)14080Sstevel@tonic-gate px_pci_config_rep_get8(ddi_acc_impl_t *handle, uint8_t *host_addr,
14090Sstevel@tonic-gate uint8_t *dev_addr, size_t repcount, uint_t flags)
14100Sstevel@tonic-gate {
14110Sstevel@tonic-gate if (flags == DDI_DEV_AUTOINCR)
14120Sstevel@tonic-gate for (; repcount; repcount--)
14130Sstevel@tonic-gate *host_addr++ = px_pci_config_get8(handle, dev_addr++);
14140Sstevel@tonic-gate else
14150Sstevel@tonic-gate for (; repcount; repcount--)
14160Sstevel@tonic-gate *host_addr++ = px_pci_config_get8(handle, dev_addr);
14170Sstevel@tonic-gate }
14180Sstevel@tonic-gate
14190Sstevel@tonic-gate /*
14200Sstevel@tonic-gate * Function to rep read 16 bit data off the PCI configuration space behind
14210Sstevel@tonic-gate * the 21554's host interface.
14220Sstevel@tonic-gate */
14230Sstevel@tonic-gate static void
px_pci_config_rep_get16(ddi_acc_impl_t * handle,uint16_t * host_addr,uint16_t * dev_addr,size_t repcount,uint_t flags)14240Sstevel@tonic-gate px_pci_config_rep_get16(ddi_acc_impl_t *handle, uint16_t *host_addr,
14250Sstevel@tonic-gate uint16_t *dev_addr, size_t repcount, uint_t flags)
14260Sstevel@tonic-gate {
14270Sstevel@tonic-gate if (flags == DDI_DEV_AUTOINCR)
14280Sstevel@tonic-gate for (; repcount; repcount--)
14290Sstevel@tonic-gate *host_addr++ = px_pci_config_get16(handle, dev_addr++);
14300Sstevel@tonic-gate else
14310Sstevel@tonic-gate for (; repcount; repcount--)
14320Sstevel@tonic-gate *host_addr++ = px_pci_config_get16(handle, dev_addr);
14330Sstevel@tonic-gate }
14340Sstevel@tonic-gate
14350Sstevel@tonic-gate /*
14360Sstevel@tonic-gate * Function to rep read 32 bit data off the PCI configuration space behind
14370Sstevel@tonic-gate * the 21554's host interface.
14380Sstevel@tonic-gate */
14390Sstevel@tonic-gate static void
px_pci_config_rep_get32(ddi_acc_impl_t * handle,uint32_t * host_addr,uint32_t * dev_addr,size_t repcount,uint_t flags)14400Sstevel@tonic-gate px_pci_config_rep_get32(ddi_acc_impl_t *handle, uint32_t *host_addr,
14410Sstevel@tonic-gate uint32_t *dev_addr, size_t repcount, uint_t flags)
14420Sstevel@tonic-gate {
14430Sstevel@tonic-gate if (flags == DDI_DEV_AUTOINCR)
14440Sstevel@tonic-gate for (; repcount; repcount--)
14450Sstevel@tonic-gate *host_addr++ = px_pci_config_get32(handle, dev_addr++);
14460Sstevel@tonic-gate else
14470Sstevel@tonic-gate for (; repcount; repcount--)
14480Sstevel@tonic-gate *host_addr++ = px_pci_config_get32(handle, dev_addr);
14490Sstevel@tonic-gate }
14500Sstevel@tonic-gate
14510Sstevel@tonic-gate /*
14520Sstevel@tonic-gate * Function to rep read 64 bit data off the PCI configuration space behind
14530Sstevel@tonic-gate * the 21554's host interface.
14540Sstevel@tonic-gate */
14550Sstevel@tonic-gate static void
px_pci_config_rep_get64(ddi_acc_impl_t * handle,uint64_t * host_addr,uint64_t * dev_addr,size_t repcount,uint_t flags)14560Sstevel@tonic-gate px_pci_config_rep_get64(ddi_acc_impl_t *handle, uint64_t *host_addr,
14570Sstevel@tonic-gate uint64_t *dev_addr, size_t repcount, uint_t flags)
14580Sstevel@tonic-gate {
14590Sstevel@tonic-gate if (flags == DDI_DEV_AUTOINCR)
14600Sstevel@tonic-gate for (; repcount; repcount--)
14610Sstevel@tonic-gate *host_addr++ = px_pci_config_get64(handle, dev_addr++);
14620Sstevel@tonic-gate else
14630Sstevel@tonic-gate for (; repcount; repcount--)
14640Sstevel@tonic-gate *host_addr++ = px_pci_config_get64(handle, dev_addr);
14650Sstevel@tonic-gate }
14660Sstevel@tonic-gate
14670Sstevel@tonic-gate /*
14680Sstevel@tonic-gate * Function to rep write 8 bit data into the PCI configuration space behind
14690Sstevel@tonic-gate * the 21554's host interface.
14700Sstevel@tonic-gate */
14710Sstevel@tonic-gate static void
px_pci_config_rep_put8(ddi_acc_impl_t * handle,uint8_t * host_addr,uint8_t * dev_addr,size_t repcount,uint_t flags)14720Sstevel@tonic-gate px_pci_config_rep_put8(ddi_acc_impl_t *handle, uint8_t *host_addr,
14730Sstevel@tonic-gate uint8_t *dev_addr, size_t repcount, uint_t flags)
14740Sstevel@tonic-gate {
14750Sstevel@tonic-gate if (flags == DDI_DEV_AUTOINCR)
14760Sstevel@tonic-gate for (; repcount; repcount--)
14770Sstevel@tonic-gate px_pci_config_put8(handle, dev_addr++, *host_addr++);
14780Sstevel@tonic-gate else
14790Sstevel@tonic-gate for (; repcount; repcount--)
14800Sstevel@tonic-gate px_pci_config_put8(handle, dev_addr, *host_addr++);
14810Sstevel@tonic-gate }
14820Sstevel@tonic-gate
14830Sstevel@tonic-gate /*
14840Sstevel@tonic-gate * Function to rep write 16 bit data into the PCI configuration space behind
14850Sstevel@tonic-gate * the 21554's host interface.
14860Sstevel@tonic-gate */
14870Sstevel@tonic-gate static void
px_pci_config_rep_put16(ddi_acc_impl_t * handle,uint16_t * host_addr,uint16_t * dev_addr,size_t repcount,uint_t flags)14880Sstevel@tonic-gate px_pci_config_rep_put16(ddi_acc_impl_t *handle, uint16_t *host_addr,
14890Sstevel@tonic-gate uint16_t *dev_addr, size_t repcount, uint_t flags)
14900Sstevel@tonic-gate {
14910Sstevel@tonic-gate if (flags == DDI_DEV_AUTOINCR)
14920Sstevel@tonic-gate for (; repcount; repcount--)
14930Sstevel@tonic-gate px_pci_config_put16(handle, dev_addr++, *host_addr++);
14940Sstevel@tonic-gate else
14950Sstevel@tonic-gate for (; repcount; repcount--)
14960Sstevel@tonic-gate px_pci_config_put16(handle, dev_addr, *host_addr++);
14970Sstevel@tonic-gate }
14980Sstevel@tonic-gate
14990Sstevel@tonic-gate /*
15000Sstevel@tonic-gate * Function to rep write 32 bit data into the PCI configuration space behind
15010Sstevel@tonic-gate * the 21554's host interface.
15020Sstevel@tonic-gate */
15030Sstevel@tonic-gate static void
px_pci_config_rep_put32(ddi_acc_impl_t * handle,uint32_t * host_addr,uint32_t * dev_addr,size_t repcount,uint_t flags)15040Sstevel@tonic-gate px_pci_config_rep_put32(ddi_acc_impl_t *handle, uint32_t *host_addr,
15050Sstevel@tonic-gate uint32_t *dev_addr, size_t repcount, uint_t flags)
15060Sstevel@tonic-gate {
15070Sstevel@tonic-gate if (flags == DDI_DEV_AUTOINCR)
15080Sstevel@tonic-gate for (; repcount; repcount--)
15090Sstevel@tonic-gate px_pci_config_put32(handle, dev_addr++, *host_addr++);
15100Sstevel@tonic-gate else
15110Sstevel@tonic-gate for (; repcount; repcount--)
15120Sstevel@tonic-gate px_pci_config_put32(handle, dev_addr, *host_addr++);
15130Sstevel@tonic-gate }
15140Sstevel@tonic-gate
15150Sstevel@tonic-gate /*
15160Sstevel@tonic-gate * Function to rep write 64 bit data into the PCI configuration space behind
15170Sstevel@tonic-gate * the 21554's host interface.
15180Sstevel@tonic-gate */
15190Sstevel@tonic-gate static void
px_pci_config_rep_put64(ddi_acc_impl_t * handle,uint64_t * host_addr,uint64_t * dev_addr,size_t repcount,uint_t flags)15200Sstevel@tonic-gate px_pci_config_rep_put64(ddi_acc_impl_t *handle, uint64_t *host_addr,
15210Sstevel@tonic-gate uint64_t *dev_addr, size_t repcount, uint_t flags)
15220Sstevel@tonic-gate {
15230Sstevel@tonic-gate if (flags == DDI_DEV_AUTOINCR)
15240Sstevel@tonic-gate for (; repcount; repcount--)
15250Sstevel@tonic-gate px_pci_config_put64(handle, dev_addr++, *host_addr++);
15260Sstevel@tonic-gate else
15270Sstevel@tonic-gate for (; repcount; repcount--)
15280Sstevel@tonic-gate px_pci_config_put64(handle, dev_addr, *host_addr++);
15290Sstevel@tonic-gate }
15300Sstevel@tonic-gate
15310Sstevel@tonic-gate /*
15320Sstevel@tonic-gate * Provide a private access handle to route config access calls to Hypervisor.
15330Sstevel@tonic-gate * Beware: Do all error checking for config space accesses before calling
15340Sstevel@tonic-gate * this function. ie. do error checking from the calling function.
15350Sstevel@tonic-gate * Due to a lack of meaningful error code in DDI, the gauranteed return of
15360Sstevel@tonic-gate * DDI_SUCCESS from here makes the code organization readable/easier from
15370Sstevel@tonic-gate * the generic code.
15380Sstevel@tonic-gate */
15390Sstevel@tonic-gate /*ARGSUSED*/
15400Sstevel@tonic-gate int
px_lib_map_vconfig(dev_info_t * dip,ddi_map_req_t * mp,pci_config_offset_t off,pci_regspec_t * rp,caddr_t * addrp)15410Sstevel@tonic-gate px_lib_map_vconfig(dev_info_t *dip,
15420Sstevel@tonic-gate ddi_map_req_t *mp, pci_config_offset_t off,
15430Sstevel@tonic-gate pci_regspec_t *rp, caddr_t *addrp)
15440Sstevel@tonic-gate {
15456313Skrishnae int fmcap;
15466313Skrishnae ndi_err_t *errp;
15476313Skrishnae on_trap_data_t *otp;
15480Sstevel@tonic-gate ddi_acc_hdl_t *hp;
15490Sstevel@tonic-gate ddi_acc_impl_t *ap;
15500Sstevel@tonic-gate uchar_t busnum; /* bus number */
15510Sstevel@tonic-gate uchar_t devnum; /* device number */
15520Sstevel@tonic-gate uchar_t funcnum; /* function number */
15530Sstevel@tonic-gate px_config_acc_pvt_t *px_pvt;
15540Sstevel@tonic-gate
15550Sstevel@tonic-gate hp = (ddi_acc_hdl_t *)mp->map_handlep;
15560Sstevel@tonic-gate ap = (ddi_acc_impl_t *)hp->ah_platform_private;
15570Sstevel@tonic-gate
15580Sstevel@tonic-gate /* Check for mapping teardown operation */
15590Sstevel@tonic-gate if ((mp->map_op == DDI_MO_UNMAP) ||
15606313Skrishnae (mp->map_op == DDI_MO_UNLOCK)) {
15610Sstevel@tonic-gate /* free up memory allocated for the private access handle. */
15620Sstevel@tonic-gate px_pvt = (px_config_acc_pvt_t *)hp->ah_bus_private;
15630Sstevel@tonic-gate kmem_free((void *)px_pvt, sizeof (px_config_acc_pvt_t));
15640Sstevel@tonic-gate
15650Sstevel@tonic-gate /* unmap operation of PCI IO/config space. */
15660Sstevel@tonic-gate return (DDI_SUCCESS);
15670Sstevel@tonic-gate }
15680Sstevel@tonic-gate
15696313Skrishnae fmcap = ddi_fm_capable(dip);
15706313Skrishnae if (DDI_FM_ACC_ERR_CAP(fmcap)) {
15716313Skrishnae errp = ((ddi_acc_impl_t *)hp)->ahi_err;
15726313Skrishnae otp = (on_trap_data_t *)errp->err_ontrap;
15736313Skrishnae otp->ot_handle = (void *)(hp);
15746313Skrishnae otp->ot_prot = OT_DATA_ACCESS;
15756313Skrishnae errp->err_status = DDI_FM_OK;
15766313Skrishnae errp->err_expected = DDI_FM_ERR_UNEXPECTED;
15776313Skrishnae errp->err_cf = px_err_cfg_hdl_check;
15786313Skrishnae }
15796313Skrishnae
15800Sstevel@tonic-gate ap->ahi_get8 = px_pci_config_get8;
15810Sstevel@tonic-gate ap->ahi_get16 = px_pci_config_get16;
15820Sstevel@tonic-gate ap->ahi_get32 = px_pci_config_get32;
15830Sstevel@tonic-gate ap->ahi_get64 = px_pci_config_get64;
15840Sstevel@tonic-gate ap->ahi_put8 = px_pci_config_put8;
15850Sstevel@tonic-gate ap->ahi_put16 = px_pci_config_put16;
15860Sstevel@tonic-gate ap->ahi_put32 = px_pci_config_put32;
15870Sstevel@tonic-gate ap->ahi_put64 = px_pci_config_put64;
15880Sstevel@tonic-gate ap->ahi_rep_get8 = px_pci_config_rep_get8;
15890Sstevel@tonic-gate ap->ahi_rep_get16 = px_pci_config_rep_get16;
15900Sstevel@tonic-gate ap->ahi_rep_get32 = px_pci_config_rep_get32;
15910Sstevel@tonic-gate ap->ahi_rep_get64 = px_pci_config_rep_get64;
15920Sstevel@tonic-gate ap->ahi_rep_put8 = px_pci_config_rep_put8;
15930Sstevel@tonic-gate ap->ahi_rep_put16 = px_pci_config_rep_put16;
15940Sstevel@tonic-gate ap->ahi_rep_put32 = px_pci_config_rep_put32;
15950Sstevel@tonic-gate ap->ahi_rep_put64 = px_pci_config_rep_put64;
15960Sstevel@tonic-gate
15970Sstevel@tonic-gate /* Initialize to default check/notify functions */
15980Sstevel@tonic-gate ap->ahi_fault = 0;
15990Sstevel@tonic-gate ap->ahi_fault_check = i_ddi_acc_fault_check;
16000Sstevel@tonic-gate ap->ahi_fault_notify = i_ddi_acc_fault_notify;
16010Sstevel@tonic-gate
16020Sstevel@tonic-gate /* allocate memory for our private handle */
16030Sstevel@tonic-gate px_pvt = (px_config_acc_pvt_t *)
16046313Skrishnae kmem_zalloc(sizeof (px_config_acc_pvt_t), KM_SLEEP);
16050Sstevel@tonic-gate hp->ah_bus_private = (void *)px_pvt;
16060Sstevel@tonic-gate
16070Sstevel@tonic-gate busnum = PCI_REG_BUS_G(rp->pci_phys_hi);
16080Sstevel@tonic-gate devnum = PCI_REG_DEV_G(rp->pci_phys_hi);
16090Sstevel@tonic-gate funcnum = PCI_REG_FUNC_G(rp->pci_phys_hi);
16100Sstevel@tonic-gate
16110Sstevel@tonic-gate /* set up private data for use during IO routines */
16120Sstevel@tonic-gate
16130Sstevel@tonic-gate /* addr needed by the HV APIs */
16140Sstevel@tonic-gate px_pvt->raddr = busnum << 16 | devnum << 11 | funcnum << 8;
16150Sstevel@tonic-gate /*
16160Sstevel@tonic-gate * Address that specifies the actual offset into the 256MB
16170Sstevel@tonic-gate * memory mapped configuration space, 4K per device.
16180Sstevel@tonic-gate * First 12bits form the offset into 4K config space.
16190Sstevel@tonic-gate * This address is only used during the IO routines to calculate
16200Sstevel@tonic-gate * the offset at which the transaction must be performed.
16210Sstevel@tonic-gate * Drivers bypassing DDI functions to access PCI config space will
16220Sstevel@tonic-gate * panic the system since the following is a bogus virtual address.
16230Sstevel@tonic-gate */
16240Sstevel@tonic-gate px_pvt->vaddr = busnum << 20 | devnum << 15 | funcnum << 12 | off;
16250Sstevel@tonic-gate px_pvt->dip = dip;
16260Sstevel@tonic-gate
16270Sstevel@tonic-gate DBG(DBG_LIB_CFG, dip, "px_config_setup: raddr 0x%x, vaddr 0x%x\n",
16286313Skrishnae px_pvt->raddr, px_pvt->vaddr);
1629671Skrishnae *addrp = (caddr_t)(uintptr_t)px_pvt->vaddr;
16300Sstevel@tonic-gate return (DDI_SUCCESS);
16310Sstevel@tonic-gate }
16320Sstevel@tonic-gate
1633677Sjchu /*ARGSUSED*/
1634677Sjchu void
px_lib_map_attr_check(ddi_map_req_t * mp)1635677Sjchu px_lib_map_attr_check(ddi_map_req_t *mp)
1636677Sjchu {
1637677Sjchu }
1638677Sjchu
163927Sjchu /*
164027Sjchu * px_lib_log_safeacc_err:
164127Sjchu * Imitate a cpu/mem trap call when a peek/poke fails.
164227Sjchu * This will initiate something similar to px_fm_callback.
164327Sjchu */
16440Sstevel@tonic-gate static void
px_lib_log_safeacc_err(px_t * px_p,ddi_acc_handle_t handle,int fme_flag,r_addr_t addr)16453274Set142600 px_lib_log_safeacc_err(px_t *px_p, ddi_acc_handle_t handle, int fme_flag,
16463274Set142600 r_addr_t addr)
16470Sstevel@tonic-gate {
16483274Set142600 uint32_t addr_high, addr_low;
16499921SKrishna.Elango@Sun.COM pcie_req_id_t bdf = PCIE_INVALID_BDF;
165010923SEvan.Yan@Sun.COM pci_ranges_t *ranges_p;
16513274Set142600 int range_len, i;
16520Sstevel@tonic-gate ddi_acc_impl_t *hp = (ddi_acc_impl_t *)handle;
16530Sstevel@tonic-gate ddi_fm_error_t derr;
16540Sstevel@tonic-gate
165511596SJason.Beloro@Sun.COM if (px_fm_enter(px_p) != DDI_SUCCESS)
165611596SJason.Beloro@Sun.COM return;
165711596SJason.Beloro@Sun.COM
16580Sstevel@tonic-gate derr.fme_status = DDI_FM_NONFATAL;
16590Sstevel@tonic-gate derr.fme_version = DDI_FME_VERSION;
16600Sstevel@tonic-gate derr.fme_flag = fme_flag;
16610Sstevel@tonic-gate derr.fme_ena = fm_ena_generate(0, FM_ENA_FMT1);
16620Sstevel@tonic-gate derr.fme_acc_handle = handle;
16630Sstevel@tonic-gate if (hp)
16640Sstevel@tonic-gate hp->ahi_err->err_expected = DDI_FM_ERR_EXPECTED;
16650Sstevel@tonic-gate
16663274Set142600 addr_high = (uint32_t)(addr >> 32);
16673274Set142600 addr_low = (uint32_t)addr;
16683274Set142600
16693274Set142600 /*
16703274Set142600 * Make sure this failed load came from this PCIe port. Check by
16713274Set142600 * matching the upper 32 bits of the address with the ranges property.
16723274Set142600 */
167310923SEvan.Yan@Sun.COM range_len = px_p->px_ranges_length / sizeof (pci_ranges_t);
16743274Set142600 i = 0;
16753274Set142600 for (ranges_p = px_p->px_ranges_p; i < range_len; i++, ranges_p++) {
16763274Set142600 if (ranges_p->parent_high == addr_high) {
16773274Set142600 switch (ranges_p->child_high & PCI_ADDR_MASK) {
16783274Set142600 case PCI_ADDR_CONFIG:
16793274Set142600 bdf = (pcie_req_id_t)(addr_low >> 12);
16803274Set142600 break;
16813274Set142600 default:
16829921SKrishna.Elango@Sun.COM bdf = PCIE_INVALID_BDF;
16833274Set142600 break;
16843274Set142600 }
16853274Set142600 break;
16863274Set142600 }
16873274Set142600 }
16883274Set142600
168911596SJason.Beloro@Sun.COM (void) px_rp_en_q(px_p, bdf, addr, NULL);
169011596SJason.Beloro@Sun.COM (void) px_scan_fabric(px_p, px_p->px_dip, &derr);
169111596SJason.Beloro@Sun.COM px_fm_exit(px_p);
16920Sstevel@tonic-gate }
16930Sstevel@tonic-gate
16940Sstevel@tonic-gate
16950Sstevel@tonic-gate #ifdef DEBUG
16960Sstevel@tonic-gate int px_peekfault_cnt = 0;
16970Sstevel@tonic-gate int px_pokefault_cnt = 0;
16980Sstevel@tonic-gate #endif /* DEBUG */
16990Sstevel@tonic-gate
17000Sstevel@tonic-gate /*
17010Sstevel@tonic-gate * Do a safe write to a device.
17020Sstevel@tonic-gate *
17030Sstevel@tonic-gate * When this function is given a handle (cautious access), all errors are
17040Sstevel@tonic-gate * suppressed.
17050Sstevel@tonic-gate *
17060Sstevel@tonic-gate * When this function is not given a handle (poke), only Unsupported Request
17070Sstevel@tonic-gate * and Completer Abort errors are suppressed.
17080Sstevel@tonic-gate *
17090Sstevel@tonic-gate * In all cases, all errors are returned in the function return status.
17100Sstevel@tonic-gate */
17110Sstevel@tonic-gate
17120Sstevel@tonic-gate int
px_lib_ctlops_poke(dev_info_t * dip,dev_info_t * rdip,peekpoke_ctlops_t * in_args)17130Sstevel@tonic-gate px_lib_ctlops_poke(dev_info_t *dip, dev_info_t *rdip,
17140Sstevel@tonic-gate peekpoke_ctlops_t *in_args)
17150Sstevel@tonic-gate {
17160Sstevel@tonic-gate px_t *px_p = DIP_TO_STATE(dip);
17170Sstevel@tonic-gate px_pec_t *pec_p = px_p->px_pec_p;
171827Sjchu ddi_acc_impl_t *hp = (ddi_acc_impl_t *)in_args->handle;
17190Sstevel@tonic-gate
17200Sstevel@tonic-gate size_t repcount = in_args->repcount;
17210Sstevel@tonic-gate size_t size = in_args->size;
17220Sstevel@tonic-gate uintptr_t dev_addr = in_args->dev_addr;
17230Sstevel@tonic-gate uintptr_t host_addr = in_args->host_addr;
17240Sstevel@tonic-gate
17250Sstevel@tonic-gate int err = DDI_SUCCESS;
17260Sstevel@tonic-gate uint64_t hvio_poke_status;
17270Sstevel@tonic-gate uint32_t wrt_stat;
17280Sstevel@tonic-gate
17290Sstevel@tonic-gate r_addr_t ra;
17300Sstevel@tonic-gate uint64_t pokeval;
17313503Saa72041 pcie_req_id_t bdf;
173227Sjchu
17330Sstevel@tonic-gate ra = (r_addr_t)va_to_pa((void *)dev_addr);
17340Sstevel@tonic-gate for (; repcount; repcount--) {
17350Sstevel@tonic-gate
17360Sstevel@tonic-gate switch (size) {
17370Sstevel@tonic-gate case sizeof (uint8_t):
17380Sstevel@tonic-gate pokeval = *(uint8_t *)host_addr;
17390Sstevel@tonic-gate break;
17400Sstevel@tonic-gate case sizeof (uint16_t):
17410Sstevel@tonic-gate pokeval = *(uint16_t *)host_addr;
17420Sstevel@tonic-gate break;
17430Sstevel@tonic-gate case sizeof (uint32_t):
17440Sstevel@tonic-gate pokeval = *(uint32_t *)host_addr;
17450Sstevel@tonic-gate break;
17460Sstevel@tonic-gate case sizeof (uint64_t):
17470Sstevel@tonic-gate pokeval = *(uint64_t *)host_addr;
17480Sstevel@tonic-gate break;
17490Sstevel@tonic-gate default:
17500Sstevel@tonic-gate DBG(DBG_MAP, px_p->px_dip,
17510Sstevel@tonic-gate "poke: invalid size %d passed\n", size);
17520Sstevel@tonic-gate err = DDI_FAILURE;
17530Sstevel@tonic-gate goto done;
17540Sstevel@tonic-gate }
17550Sstevel@tonic-gate
175627Sjchu /*
175727Sjchu * Grab pokefault mutex since hypervisor does not guarantee
175827Sjchu * poke serialization.
175927Sjchu */
176027Sjchu if (hp) {
176127Sjchu i_ndi_busop_access_enter(hp->ahi_common.ah_dip,
176227Sjchu (ddi_acc_handle_t)hp);
176327Sjchu pec_p->pec_safeacc_type = DDI_FM_ERR_EXPECTED;
176427Sjchu } else {
176527Sjchu mutex_enter(&pec_p->pec_pokefault_mutex);
176627Sjchu pec_p->pec_safeacc_type = DDI_FM_ERR_POKE;
176727Sjchu }
17683503Saa72041
17693503Saa72041 if (pcie_get_bdf_from_dip(rdip, &bdf) != DDI_SUCCESS) {
17703503Saa72041 err = DDI_FAILURE;
17713503Saa72041 goto done;
17723503Saa72041 }
17730Sstevel@tonic-gate
17740Sstevel@tonic-gate hvio_poke_status = hvio_poke(px_p->px_dev_hdl, ra, size,
17753503Saa72041 pokeval, bdf << 8, &wrt_stat);
17760Sstevel@tonic-gate
17770Sstevel@tonic-gate if ((hvio_poke_status != H_EOK) || (wrt_stat != H_EOK)) {
17780Sstevel@tonic-gate err = DDI_FAILURE;
17790Sstevel@tonic-gate #ifdef DEBUG
17800Sstevel@tonic-gate px_pokefault_cnt++;
17810Sstevel@tonic-gate #endif
17820Sstevel@tonic-gate /*
17830Sstevel@tonic-gate * For CAUTIOUS and POKE access, notify FMA to
178427Sjchu * cleanup. Imitate a cpu/mem trap call like in sun4u.
17850Sstevel@tonic-gate */
178627Sjchu px_lib_log_safeacc_err(px_p, (ddi_acc_handle_t)hp,
178727Sjchu (hp ? DDI_FM_ERR_EXPECTED :
17883274Set142600 DDI_FM_ERR_POKE), ra);
17890Sstevel@tonic-gate
179027Sjchu pec_p->pec_ontrap_data = NULL;
179127Sjchu pec_p->pec_safeacc_type = DDI_FM_ERR_UNEXPECTED;
179227Sjchu if (hp) {
179327Sjchu i_ndi_busop_access_exit(hp->ahi_common.ah_dip,
179427Sjchu (ddi_acc_handle_t)hp);
179527Sjchu } else {
179627Sjchu mutex_exit(&pec_p->pec_pokefault_mutex);
179727Sjchu }
17980Sstevel@tonic-gate goto done;
17990Sstevel@tonic-gate }
18000Sstevel@tonic-gate
180127Sjchu pec_p->pec_ontrap_data = NULL;
180227Sjchu pec_p->pec_safeacc_type = DDI_FM_ERR_UNEXPECTED;
180327Sjchu if (hp) {
180427Sjchu i_ndi_busop_access_exit(hp->ahi_common.ah_dip,
180527Sjchu (ddi_acc_handle_t)hp);
180627Sjchu } else {
180727Sjchu mutex_exit(&pec_p->pec_pokefault_mutex);
180827Sjchu }
180927Sjchu
18100Sstevel@tonic-gate host_addr += size;
18110Sstevel@tonic-gate
18120Sstevel@tonic-gate if (in_args->flags == DDI_DEV_AUTOINCR) {
18130Sstevel@tonic-gate dev_addr += size;
18140Sstevel@tonic-gate ra = (r_addr_t)va_to_pa((void *)dev_addr);
18150Sstevel@tonic-gate }
18160Sstevel@tonic-gate }
18170Sstevel@tonic-gate
18180Sstevel@tonic-gate done:
18190Sstevel@tonic-gate return (err);
18200Sstevel@tonic-gate }
18210Sstevel@tonic-gate
18220Sstevel@tonic-gate
18230Sstevel@tonic-gate /*ARGSUSED*/
18240Sstevel@tonic-gate int
px_lib_ctlops_peek(dev_info_t * dip,dev_info_t * rdip,peekpoke_ctlops_t * in_args,void * result)18250Sstevel@tonic-gate px_lib_ctlops_peek(dev_info_t *dip, dev_info_t *rdip,
18260Sstevel@tonic-gate peekpoke_ctlops_t *in_args, void *result)
18270Sstevel@tonic-gate {
18280Sstevel@tonic-gate px_t *px_p = DIP_TO_STATE(dip);
18290Sstevel@tonic-gate px_pec_t *pec_p = px_p->px_pec_p;
183027Sjchu ddi_acc_impl_t *hp = (ddi_acc_impl_t *)in_args->handle;
18310Sstevel@tonic-gate
18320Sstevel@tonic-gate size_t repcount = in_args->repcount;
18330Sstevel@tonic-gate uintptr_t dev_addr = in_args->dev_addr;
18340Sstevel@tonic-gate uintptr_t host_addr = in_args->host_addr;
18350Sstevel@tonic-gate
18360Sstevel@tonic-gate r_addr_t ra;
18370Sstevel@tonic-gate uint32_t read_status;
18380Sstevel@tonic-gate uint64_t hvio_peek_status;
18390Sstevel@tonic-gate uint64_t peekval;
184027Sjchu int err = DDI_SUCCESS;
18410Sstevel@tonic-gate
18420Sstevel@tonic-gate result = (void *)in_args->host_addr;
18430Sstevel@tonic-gate
18440Sstevel@tonic-gate ra = (r_addr_t)va_to_pa((void *)dev_addr);
18450Sstevel@tonic-gate for (; repcount; repcount--) {
18460Sstevel@tonic-gate
18470Sstevel@tonic-gate /* Lock pokefault mutex so read doesn't mask a poke fault. */
184827Sjchu if (hp) {
184927Sjchu i_ndi_busop_access_enter(hp->ahi_common.ah_dip,
185027Sjchu (ddi_acc_handle_t)hp);
185127Sjchu pec_p->pec_safeacc_type = DDI_FM_ERR_EXPECTED;
185227Sjchu } else {
185327Sjchu mutex_enter(&pec_p->pec_pokefault_mutex);
185427Sjchu pec_p->pec_safeacc_type = DDI_FM_ERR_PEEK;
185527Sjchu }
18560Sstevel@tonic-gate
18570Sstevel@tonic-gate hvio_peek_status = hvio_peek(px_p->px_dev_hdl, ra,
18580Sstevel@tonic-gate in_args->size, &read_status, &peekval);
18590Sstevel@tonic-gate
18600Sstevel@tonic-gate if ((hvio_peek_status != H_EOK) || (read_status != H_EOK)) {
18610Sstevel@tonic-gate err = DDI_FAILURE;
18620Sstevel@tonic-gate
18630Sstevel@tonic-gate /*
18640Sstevel@tonic-gate * For CAUTIOUS and PEEK access, notify FMA to
186527Sjchu * cleanup. Imitate a cpu/mem trap call like in sun4u.
18660Sstevel@tonic-gate */
186727Sjchu px_lib_log_safeacc_err(px_p, (ddi_acc_handle_t)hp,
186827Sjchu (hp ? DDI_FM_ERR_EXPECTED :
18693274Set142600 DDI_FM_ERR_PEEK), ra);
18700Sstevel@tonic-gate
18710Sstevel@tonic-gate /* Stuff FFs in host addr if peek. */
187227Sjchu if (hp == NULL) {
18730Sstevel@tonic-gate int i;
18740Sstevel@tonic-gate uint8_t *ff_addr = (uint8_t *)host_addr;
18750Sstevel@tonic-gate for (i = 0; i < in_args->size; i++)
18760Sstevel@tonic-gate *ff_addr++ = 0xff;
18770Sstevel@tonic-gate }
18780Sstevel@tonic-gate #ifdef DEBUG
18790Sstevel@tonic-gate px_peekfault_cnt++;
18800Sstevel@tonic-gate #endif
188127Sjchu pec_p->pec_ontrap_data = NULL;
188227Sjchu pec_p->pec_safeacc_type = DDI_FM_ERR_UNEXPECTED;
188327Sjchu if (hp) {
188427Sjchu i_ndi_busop_access_exit(hp->ahi_common.ah_dip,
188527Sjchu (ddi_acc_handle_t)hp);
188627Sjchu } else {
188727Sjchu mutex_exit(&pec_p->pec_pokefault_mutex);
188827Sjchu }
18890Sstevel@tonic-gate goto done;
18900Sstevel@tonic-gate
189127Sjchu }
189227Sjchu pec_p->pec_ontrap_data = NULL;
189327Sjchu pec_p->pec_safeacc_type = DDI_FM_ERR_UNEXPECTED;
189427Sjchu if (hp) {
189527Sjchu i_ndi_busop_access_exit(hp->ahi_common.ah_dip,
189627Sjchu (ddi_acc_handle_t)hp);
18970Sstevel@tonic-gate } else {
189827Sjchu mutex_exit(&pec_p->pec_pokefault_mutex);
189927Sjchu }
19000Sstevel@tonic-gate
190127Sjchu switch (in_args->size) {
190227Sjchu case sizeof (uint8_t):
190327Sjchu *(uint8_t *)host_addr = (uint8_t)peekval;
190427Sjchu break;
190527Sjchu case sizeof (uint16_t):
190627Sjchu *(uint16_t *)host_addr = (uint16_t)peekval;
190727Sjchu break;
190827Sjchu case sizeof (uint32_t):
190927Sjchu *(uint32_t *)host_addr = (uint32_t)peekval;
191027Sjchu break;
191127Sjchu case sizeof (uint64_t):
191227Sjchu *(uint64_t *)host_addr = (uint64_t)peekval;
191327Sjchu break;
191427Sjchu default:
191527Sjchu DBG(DBG_MAP, px_p->px_dip,
191627Sjchu "peek: invalid size %d passed\n",
191727Sjchu in_args->size);
191827Sjchu err = DDI_FAILURE;
191927Sjchu goto done;
19200Sstevel@tonic-gate }
19210Sstevel@tonic-gate
19220Sstevel@tonic-gate host_addr += in_args->size;
19230Sstevel@tonic-gate
19240Sstevel@tonic-gate if (in_args->flags == DDI_DEV_AUTOINCR) {
19250Sstevel@tonic-gate dev_addr += in_args->size;
19260Sstevel@tonic-gate ra = (r_addr_t)va_to_pa((void *)dev_addr);
19270Sstevel@tonic-gate }
19280Sstevel@tonic-gate }
19290Sstevel@tonic-gate done:
19300Sstevel@tonic-gate return (err);
19310Sstevel@tonic-gate }
19320Sstevel@tonic-gate
193327Sjchu
193427Sjchu /* add interrupt vector */
193527Sjchu int
px_err_add_intr(px_fault_t * px_fault_p)193627Sjchu px_err_add_intr(px_fault_t *px_fault_p)
193727Sjchu {
193827Sjchu px_t *px_p = DIP_TO_STATE(px_fault_p->px_fh_dip);
193927Sjchu
194027Sjchu DBG(DBG_LIB_INT, px_p->px_dip,
194127Sjchu "px_err_add_intr: calling add_ivintr");
194227Sjchu
19432973Sgovinda VERIFY(add_ivintr(px_fault_p->px_fh_sysino, PX_ERR_PIL,
19442973Sgovinda (intrfunc)px_fault_p->px_err_func, (caddr_t)px_fault_p, NULL,
19452973Sgovinda (caddr_t)&px_fault_p->px_intr_payload[0]) == 0);
194627Sjchu
194727Sjchu DBG(DBG_LIB_INT, px_p->px_dip,
194827Sjchu "px_err_add_intr: ib_intr_enable ");
194927Sjchu
195027Sjchu px_ib_intr_enable(px_p, intr_dist_cpuid(), px_fault_p->px_intr_ino);
195127Sjchu
19522973Sgovinda return (DDI_SUCCESS);
195327Sjchu }
195427Sjchu
195527Sjchu /* remove interrupt vector */
195627Sjchu void
px_err_rem_intr(px_fault_t * px_fault_p)195727Sjchu px_err_rem_intr(px_fault_t *px_fault_p)
195827Sjchu {
195927Sjchu px_t *px_p = DIP_TO_STATE(px_fault_p->px_fh_dip);
196027Sjchu
196127Sjchu px_ib_intr_disable(px_p->px_ib_p, px_fault_p->px_intr_ino,
196227Sjchu IB_INTR_WAIT);
1963965Sgovinda
19642973Sgovinda VERIFY(rem_ivintr(px_fault_p->px_fh_sysino, PX_ERR_PIL) == 0);
196527Sjchu }
196627Sjchu
19673623Sjchu void
px_cb_intr_redist(void * arg)19683623Sjchu px_cb_intr_redist(void *arg)
19693623Sjchu {
19703623Sjchu px_t *px_p = (px_t *)arg;
19713623Sjchu px_ib_intr_dist_en(px_p->px_dip, intr_dist_cpuid(),
19723623Sjchu px_p->px_inos[PX_INTR_XBC], B_FALSE);
19733623Sjchu }
19743623Sjchu
19751648Sjchu int
px_cb_add_intr(px_fault_t * f_p)19761648Sjchu px_cb_add_intr(px_fault_t *f_p)
19771648Sjchu {
19783623Sjchu px_t *px_p = DIP_TO_STATE(f_p->px_fh_dip);
19793623Sjchu
19803623Sjchu DBG(DBG_LIB_INT, px_p->px_dip,
19813623Sjchu "px_err_add_intr: calling add_ivintr");
19823623Sjchu
19833623Sjchu VERIFY(add_ivintr(f_p->px_fh_sysino, PX_ERR_PIL,
19843623Sjchu (intrfunc)f_p->px_err_func, (caddr_t)f_p, NULL,
19853623Sjchu (caddr_t)&f_p->px_intr_payload[0]) == 0);
19863623Sjchu
19873623Sjchu intr_dist_add(px_cb_intr_redist, px_p);
19883623Sjchu
19893623Sjchu DBG(DBG_LIB_INT, px_p->px_dip,
19903623Sjchu "px_err_add_intr: ib_intr_enable ");
19913623Sjchu
19923623Sjchu px_ib_intr_enable(px_p, intr_dist_cpuid(), f_p->px_intr_ino);
19933623Sjchu
19943623Sjchu return (DDI_SUCCESS);
19951648Sjchu }
19961648Sjchu
19971648Sjchu void
px_cb_rem_intr(px_fault_t * f_p)19981648Sjchu px_cb_rem_intr(px_fault_t *f_p)
19991648Sjchu {
20003623Sjchu intr_dist_rem(px_cb_intr_redist, DIP_TO_STATE(f_p->px_fh_dip));
20011648Sjchu px_err_rem_intr(f_p);
20021648Sjchu }
20031648Sjchu
200427Sjchu #ifdef FMA
200527Sjchu void
px_fill_rc_status(px_fault_t * px_fault_p,pciex_rc_error_regs_t * rc_status)200627Sjchu px_fill_rc_status(px_fault_t *px_fault_p, pciex_rc_error_regs_t *rc_status)
200727Sjchu {
200827Sjchu px_pec_err_t *err_pkt;
200927Sjchu
201027Sjchu err_pkt = (px_pec_err_t *)px_fault_p->px_intr_payload;
201127Sjchu
201227Sjchu /* initialise all the structure members */
201327Sjchu rc_status->status_valid = 0;
201427Sjchu
201527Sjchu if (err_pkt->pec_descr.P) {
201627Sjchu /* PCI Status Register */
201727Sjchu rc_status->pci_err_status = err_pkt->pci_err_status;
201827Sjchu rc_status->status_valid |= PCI_ERR_STATUS_VALID;
201927Sjchu }
202027Sjchu
202127Sjchu if (err_pkt->pec_descr.E) {
202227Sjchu /* PCIe Status Register */
202327Sjchu rc_status->pcie_err_status = err_pkt->pcie_err_status;
202427Sjchu rc_status->status_valid |= PCIE_ERR_STATUS_VALID;
202527Sjchu }
202627Sjchu
202727Sjchu if (err_pkt->pec_descr.U) {
202827Sjchu rc_status->ue_status = err_pkt->ue_reg_status;
202927Sjchu rc_status->status_valid |= UE_STATUS_VALID;
203027Sjchu }
203127Sjchu
203227Sjchu if (err_pkt->pec_descr.H) {
203327Sjchu rc_status->ue_hdr1 = err_pkt->hdr[0];
203427Sjchu rc_status->status_valid |= UE_HDR1_VALID;
203527Sjchu }
203627Sjchu
203727Sjchu if (err_pkt->pec_descr.I) {
203827Sjchu rc_status->ue_hdr2 = err_pkt->hdr[1];
203927Sjchu rc_status->status_valid |= UE_HDR2_VALID;
204027Sjchu }
204127Sjchu
204227Sjchu /* ue_fst_err_ptr - not available for sun4v?? */
204327Sjchu
204427Sjchu
204527Sjchu if (err_pkt->pec_descr.S) {
204627Sjchu rc_status->source_id = err_pkt->err_src_reg;
204727Sjchu rc_status->status_valid |= SOURCE_ID_VALID;
204827Sjchu }
204927Sjchu
205027Sjchu if (err_pkt->pec_descr.R) {
205127Sjchu rc_status->root_err_status = err_pkt->root_err_status;
205227Sjchu rc_status->status_valid |= CE_STATUS_VALID;
205327Sjchu }
205427Sjchu }
205527Sjchu #endif
205627Sjchu
20570Sstevel@tonic-gate /*ARGSUSED*/
20580Sstevel@tonic-gate int
px_lib_pmctl(int cmd,px_t * px_p)20590Sstevel@tonic-gate px_lib_pmctl(int cmd, px_t *px_p)
20600Sstevel@tonic-gate {
20610Sstevel@tonic-gate return (DDI_FAILURE);
20620Sstevel@tonic-gate }
2063118Sjchu
2064118Sjchu /*ARGSUSED*/
2065118Sjchu uint_t
px_pmeq_intr(caddr_t arg)2066118Sjchu px_pmeq_intr(caddr_t arg)
2067118Sjchu {
2068118Sjchu return (DDI_INTR_CLAIMED);
2069118Sjchu }
2070383Set142600
2071383Set142600 /*
207211245SZhijun.Fu@Sun.COM * fetch the config space base addr of the root complex
207311245SZhijun.Fu@Sun.COM * note this depends on px structure being initialized
2074383Set142600 */
207511245SZhijun.Fu@Sun.COM uint64_t
px_lib_get_cfgacc_base(dev_info_t * dip)207611245SZhijun.Fu@Sun.COM px_lib_get_cfgacc_base(dev_info_t *dip)
207711245SZhijun.Fu@Sun.COM {
207811245SZhijun.Fu@Sun.COM int instance = DIP_TO_INST(dip);
207911245SZhijun.Fu@Sun.COM px_t *px_p = INST_TO_STATE(instance);
2080383Set142600
208111245SZhijun.Fu@Sun.COM return (px_p->px_dev_hdl);
2082383Set142600 }
2083435Sjchu
208411596SJason.Beloro@Sun.COM void
px_panic_domain(px_t * px_p,pcie_req_id_t bdf)208511596SJason.Beloro@Sun.COM px_panic_domain(px_t *px_p, pcie_req_id_t bdf)
208611596SJason.Beloro@Sun.COM {
208711596SJason.Beloro@Sun.COM uint64_t ret;
208811596SJason.Beloro@Sun.COM dev_info_t *dip = px_p->px_dip;
208911596SJason.Beloro@Sun.COM
209011596SJason.Beloro@Sun.COM DBG(DBG_ERR_INTR, dip, "px_panic_domain: handle 0x%lx, ino %d, "
209111596SJason.Beloro@Sun.COM "bdf<<8 0x%lx\n",
209211596SJason.Beloro@Sun.COM (uint64_t)DIP_TO_HANDLE(dip), px_p->px_cb_fault.px_intr_ino,
209311596SJason.Beloro@Sun.COM (pci_device_t)bdf << 8);
209411596SJason.Beloro@Sun.COM if ((ret = pci_error_send(DIP_TO_HANDLE(dip),
209511596SJason.Beloro@Sun.COM px_p->px_cb_fault.px_intr_ino, (pci_device_t)bdf << 8)) != H_EOK) {
209611596SJason.Beloro@Sun.COM DBG(DBG_ERR_INTR, dip, "pci_error_send failed, ret 0x%lx\n",
209711596SJason.Beloro@Sun.COM ret);
209811596SJason.Beloro@Sun.COM } else
209911596SJason.Beloro@Sun.COM DBG(DBG_ERR_INTR, dip, "pci_error_send worked\n");
210011596SJason.Beloro@Sun.COM }
210111596SJason.Beloro@Sun.COM
21021531Skini /*ARGSUSED*/
21031531Skini int
px_lib_hotplug_init(dev_info_t * dip,void * arg)21041531Skini px_lib_hotplug_init(dev_info_t *dip, void *arg)
21051531Skini {
21061531Skini return (DDI_ENOTSUP);
21071531Skini }
21081531Skini
21091531Skini /*ARGSUSED*/
21101531Skini void
px_lib_hotplug_uninit(dev_info_t * dip)21111531Skini px_lib_hotplug_uninit(dev_info_t *dip)
21121531Skini {
21131531Skini }
21141531Skini
21153953Sscarter /*ARGSUSED*/
21163953Sscarter void
px_hp_intr_redist(px_t * px_p)21173953Sscarter px_hp_intr_redist(px_t *px_p)
21183953Sscarter {
21193953Sscarter }
21203953Sscarter
2121435Sjchu /* Dummy cpr add callback */
2122435Sjchu /*ARGSUSED*/
2123435Sjchu void
px_cpr_add_callb(px_t * px_p)2124435Sjchu px_cpr_add_callb(px_t *px_p)
2125435Sjchu {
2126435Sjchu }
2127435Sjchu
2128435Sjchu /* Dummy cpr rem callback */
2129435Sjchu /*ARGSUSED*/
2130435Sjchu void
px_cpr_rem_callb(px_t * px_p)2131435Sjchu px_cpr_rem_callb(px_t *px_p)
2132435Sjchu {
2133435Sjchu }
21342476Sdwoods
21352476Sdwoods /*ARGSUSED*/
21362476Sdwoods boolean_t
px_lib_is_in_drain_state(px_t * px_p)21372476Sdwoods px_lib_is_in_drain_state(px_t *px_p)
21382476Sdwoods {
21392476Sdwoods return (B_FALSE);
21402476Sdwoods }
21413613Set142600
21423613Set142600 /*
21433613Set142600 * There is no IOAPI to get the BDF of the pcie root port nexus at this moment.
21443613Set142600 * Assume it is 0x0000, until otherwise noted. For now, all sun4v platforms
21453613Set142600 * have programmed the BDF to be 0x0000.
21463613Set142600 */
21473613Set142600 /*ARGSUSED*/
21483613Set142600 pcie_req_id_t
px_lib_get_bdf(px_t * px_p)21493613Set142600 px_lib_get_bdf(px_t *px_p)
21503613Set142600 {
21513613Set142600 return (0x0000);
21523613Set142600 }
21537596SAlan.Adamson@Sun.COM
21547596SAlan.Adamson@Sun.COM int
px_lib_get_root_complex_mps(px_t * px_p,dev_info_t * dip,int * mps)21557596SAlan.Adamson@Sun.COM px_lib_get_root_complex_mps(px_t *px_p, dev_info_t *dip, int *mps)
21567596SAlan.Adamson@Sun.COM {
21577596SAlan.Adamson@Sun.COM pci_device_t bdf = px_lib_get_bdf(px_p);
21587596SAlan.Adamson@Sun.COM
21597596SAlan.Adamson@Sun.COM if (hvio_get_rp_mps_cap(DIP_TO_HANDLE(dip), bdf, mps) == H_EOK)
21607596SAlan.Adamson@Sun.COM return (DDI_SUCCESS);
21617596SAlan.Adamson@Sun.COM else
21627596SAlan.Adamson@Sun.COM return (DDI_FAILURE);
21637596SAlan.Adamson@Sun.COM }
21647596SAlan.Adamson@Sun.COM
21657596SAlan.Adamson@Sun.COM int
px_lib_set_root_complex_mps(px_t * px_p,dev_info_t * dip,int mps)21667596SAlan.Adamson@Sun.COM px_lib_set_root_complex_mps(px_t *px_p, dev_info_t *dip, int mps)
21677596SAlan.Adamson@Sun.COM {
21687596SAlan.Adamson@Sun.COM pci_device_t bdf = px_lib_get_bdf(px_p);
21697596SAlan.Adamson@Sun.COM
21707596SAlan.Adamson@Sun.COM if (hvio_set_rp_mps(DIP_TO_HANDLE(dip), bdf, mps) == H_EOK)
21717596SAlan.Adamson@Sun.COM return (DDI_SUCCESS);
21727596SAlan.Adamson@Sun.COM else
21737596SAlan.Adamson@Sun.COM return (DDI_FAILURE);
21747596SAlan.Adamson@Sun.COM }
217511596SJason.Beloro@Sun.COM
217611596SJason.Beloro@Sun.COM static int
px_lib_do_count_waiting_dev(dev_info_t * dip,void * arg)217711596SJason.Beloro@Sun.COM px_lib_do_count_waiting_dev(dev_info_t *dip, void *arg)
217811596SJason.Beloro@Sun.COM {
217911596SJason.Beloro@Sun.COM int *count = (int *)arg;
218011596SJason.Beloro@Sun.COM dev_info_t *cdip = ddi_get_child(dip);
218111596SJason.Beloro@Sun.COM
218211596SJason.Beloro@Sun.COM while (cdip != NULL) {
218311596SJason.Beloro@Sun.COM /* check if this is an assigned device */
218411596SJason.Beloro@Sun.COM if (ddi_prop_exists(DDI_DEV_T_NONE, cdip, DDI_PROP_DONTPASS,
218511596SJason.Beloro@Sun.COM "ddi-assigned")) {
218611596SJason.Beloro@Sun.COM DBG(DBG_ATTACH, dip, "px_lib_do_count_waiting_dev: "
218711596SJason.Beloro@Sun.COM "Found an assigned dev %p, under bridge %p",
218811596SJason.Beloro@Sun.COM cdip, dip);
218911596SJason.Beloro@Sun.COM
219011596SJason.Beloro@Sun.COM /*
219111596SJason.Beloro@Sun.COM * Mark this bridge as needing waiting for
219211596SJason.Beloro@Sun.COM * CHILD_LOANED will be removed after bridge reports
219311596SJason.Beloro@Sun.COM * its readyness back to px driver
219411596SJason.Beloro@Sun.COM */
219511596SJason.Beloro@Sun.COM if (ddi_prop_update_int(DDI_DEV_T_NONE, dip,
219611596SJason.Beloro@Sun.COM CHILD_LOANED, 1) == DDI_PROP_SUCCESS)
219711596SJason.Beloro@Sun.COM (*count)++;
219811596SJason.Beloro@Sun.COM break;
219911596SJason.Beloro@Sun.COM }
220011596SJason.Beloro@Sun.COM cdip = ddi_get_next_sibling(cdip);
220111596SJason.Beloro@Sun.COM }
220211596SJason.Beloro@Sun.COM
220311596SJason.Beloro@Sun.COM return (DDI_WALK_CONTINUE);
220411596SJason.Beloro@Sun.COM }
220511596SJason.Beloro@Sun.COM
220611596SJason.Beloro@Sun.COM static int
px_lib_count_waiting_dev(dev_info_t * dip)220711596SJason.Beloro@Sun.COM px_lib_count_waiting_dev(dev_info_t *dip)
220811596SJason.Beloro@Sun.COM {
220911596SJason.Beloro@Sun.COM int circular_count;
221011596SJason.Beloro@Sun.COM int count = 0;
221111596SJason.Beloro@Sun.COM
221211596SJason.Beloro@Sun.COM /* No need to continue if this system is not SDIO capable */
221311596SJason.Beloro@Sun.COM if (px_sdio_users == 0)
221411596SJason.Beloro@Sun.COM return (0);
221511596SJason.Beloro@Sun.COM
221611596SJason.Beloro@Sun.COM /* see if px iteslf has assigned children */
221711596SJason.Beloro@Sun.COM (void) px_lib_do_count_waiting_dev(dip, &count);
221811596SJason.Beloro@Sun.COM
221911596SJason.Beloro@Sun.COM /* scan dev under this px */
222011596SJason.Beloro@Sun.COM ndi_devi_enter(dip, &circular_count);
222111596SJason.Beloro@Sun.COM ddi_walk_devs(ddi_get_child(dip), px_lib_do_count_waiting_dev, &count);
222211596SJason.Beloro@Sun.COM ndi_devi_exit(dip, circular_count);
222311596SJason.Beloro@Sun.COM return (count);
222411596SJason.Beloro@Sun.COM }
222511596SJason.Beloro@Sun.COM
222611596SJason.Beloro@Sun.COM /* Called from px/bridge driver directly to report its readyness */
222711596SJason.Beloro@Sun.COM int
px_lib_fabric_sync(dev_info_t * dip)222811596SJason.Beloro@Sun.COM px_lib_fabric_sync(dev_info_t *dip)
222911596SJason.Beloro@Sun.COM {
223011596SJason.Beloro@Sun.COM px_t *px;
223111596SJason.Beloro@Sun.COM dev_info_t *rcdip;
223211596SJason.Beloro@Sun.COM int waitdev;
223311596SJason.Beloro@Sun.COM
223411596SJason.Beloro@Sun.COM /* No need to continue if this system is not SDIO capable */
223511596SJason.Beloro@Sun.COM if (px_sdio_users == 0)
223611596SJason.Beloro@Sun.COM return (DDI_SUCCESS);
223711596SJason.Beloro@Sun.COM
223811596SJason.Beloro@Sun.COM /* a valid bridge w/ assigned dev under it? */
223911596SJason.Beloro@Sun.COM if (ddi_prop_remove(DDI_DEV_T_NONE, dip, CHILD_LOANED) !=
224011596SJason.Beloro@Sun.COM DDI_PROP_SUCCESS)
224111596SJason.Beloro@Sun.COM return (DDI_FAILURE);
224211596SJason.Beloro@Sun.COM
224311596SJason.Beloro@Sun.COM /* find out RC dip */
224411596SJason.Beloro@Sun.COM for (rcdip = dip; rcdip != NULL; rcdip = ddi_get_parent(rcdip)) {
224511596SJason.Beloro@Sun.COM if (PCIE_DIP2BUS(rcdip) && PCIE_IS_RC(PCIE_DIP2BUS(rcdip)))
224611596SJason.Beloro@Sun.COM break;
224711596SJason.Beloro@Sun.COM }
224811596SJason.Beloro@Sun.COM if ((rcdip == NULL) || ((px = (px_t *)DIP_TO_STATE(rcdip)) == NULL))
224911596SJason.Beloro@Sun.COM return (DDI_FAILURE);
225011596SJason.Beloro@Sun.COM
225111596SJason.Beloro@Sun.COM /* are we ready? */
225211596SJason.Beloro@Sun.COM waitdev = (int)(uintptr_t)px->px_plat_p;
225311596SJason.Beloro@Sun.COM ASSERT(waitdev);
225411596SJason.Beloro@Sun.COM DBG(DBG_CTLOPS, rcdip, "px_lib_fabric_sync: "
225511596SJason.Beloro@Sun.COM "Px/bridge %p is ready, %d left", rcdip, waitdev - 1);
225611596SJason.Beloro@Sun.COM --waitdev;
225711596SJason.Beloro@Sun.COM px->px_plat_p = (void *)(uintptr_t)waitdev;
225811596SJason.Beloro@Sun.COM if (waitdev != 0)
225911596SJason.Beloro@Sun.COM return (DDI_SUCCESS);
226011596SJason.Beloro@Sun.COM
226111596SJason.Beloro@Sun.COM /* notify hpyervisor */
226211596SJason.Beloro@Sun.COM DBG(DBG_CTLOPS, rcdip, "px_lib_fabric_sync: "
226311596SJason.Beloro@Sun.COM "Notifying HV that RC %p is ready users=%d", rcdip, px_sdio_users);
226411596SJason.Beloro@Sun.COM
226511596SJason.Beloro@Sun.COM if (pci_iov_root_configured(px->px_dev_hdl) != H_EOK)
226611596SJason.Beloro@Sun.COM return (DDI_FAILURE);
226711596SJason.Beloro@Sun.COM
226811596SJason.Beloro@Sun.COM return (DDI_SUCCESS);
226911596SJason.Beloro@Sun.COM }
2270