17596SAlan.Adamson@Sun.COM /*
27596SAlan.Adamson@Sun.COM * CDDL HEADER START
37596SAlan.Adamson@Sun.COM *
47596SAlan.Adamson@Sun.COM * The contents of this file are subject to the terms of the
57596SAlan.Adamson@Sun.COM * Common Development and Distribution License (the "License").
67596SAlan.Adamson@Sun.COM * You may not use this file except in compliance with the License.
77596SAlan.Adamson@Sun.COM *
87596SAlan.Adamson@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97596SAlan.Adamson@Sun.COM * or http://www.opensolaris.org/os/licensing.
107596SAlan.Adamson@Sun.COM * See the License for the specific language governing permissions
117596SAlan.Adamson@Sun.COM * and limitations under the License.
127596SAlan.Adamson@Sun.COM *
137596SAlan.Adamson@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
147596SAlan.Adamson@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157596SAlan.Adamson@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
167596SAlan.Adamson@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
177596SAlan.Adamson@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
187596SAlan.Adamson@Sun.COM *
197596SAlan.Adamson@Sun.COM * CDDL HEADER END
207596SAlan.Adamson@Sun.COM */
217596SAlan.Adamson@Sun.COM /*
2210595SShesha.Sreenivasamurthy@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
237596SAlan.Adamson@Sun.COM * Use is subject to license terms.
247596SAlan.Adamson@Sun.COM */
257596SAlan.Adamson@Sun.COM
267596SAlan.Adamson@Sun.COM #include <sys/types.h>
277596SAlan.Adamson@Sun.COM #include <sys/sysmacros.h>
287596SAlan.Adamson@Sun.COM #include <sys/ddi.h>
297596SAlan.Adamson@Sun.COM #include <sys/async.h>
307596SAlan.Adamson@Sun.COM #include <sys/sunddi.h>
317596SAlan.Adamson@Sun.COM #include <sys/ddifm.h>
327596SAlan.Adamson@Sun.COM #include <sys/fm/protocol.h>
337596SAlan.Adamson@Sun.COM #include <sys/vmem.h>
347596SAlan.Adamson@Sun.COM #include <sys/intr.h>
357596SAlan.Adamson@Sun.COM #include <sys/ivintr.h>
367596SAlan.Adamson@Sun.COM #include <sys/errno.h>
377596SAlan.Adamson@Sun.COM #include <sys/hypervisor_api.h>
387596SAlan.Adamson@Sun.COM #include <sys/hsvc.h>
39*11245SZhijun.Fu@Sun.COM #include <sys/pci_cfgacc.h>
40*11245SZhijun.Fu@Sun.COM #include <sys/pci_cfgacc_4v.h>
417596SAlan.Adamson@Sun.COM #include <px_obj.h>
427596SAlan.Adamson@Sun.COM #include <sys/machsystm.h>
437596SAlan.Adamson@Sun.COM #include "px_lib4v.h"
447596SAlan.Adamson@Sun.COM
457596SAlan.Adamson@Sun.COM #define MPS_SET 0
467596SAlan.Adamson@Sun.COM #define MPS_GET 1
477596SAlan.Adamson@Sun.COM
487596SAlan.Adamson@Sun.COM static uint64_t hvio_rp_mps(devhandle_t dev_hdl, pci_device_t bdf, int32_t *mps,
497596SAlan.Adamson@Sun.COM int op);
507596SAlan.Adamson@Sun.COM
517596SAlan.Adamson@Sun.COM uint64_t
hvio_get_rp_mps_cap(devhandle_t dev_hdl,pci_device_t bdf,int32_t * mps_cap)527596SAlan.Adamson@Sun.COM hvio_get_rp_mps_cap(devhandle_t dev_hdl, pci_device_t bdf, int32_t *mps_cap)
537596SAlan.Adamson@Sun.COM {
547596SAlan.Adamson@Sun.COM return (hvio_rp_mps(dev_hdl, bdf, mps_cap, MPS_GET));
557596SAlan.Adamson@Sun.COM }
567596SAlan.Adamson@Sun.COM
577596SAlan.Adamson@Sun.COM uint64_t
hvio_set_rp_mps(devhandle_t dev_hdl,pci_device_t bdf,int32_t mps)587596SAlan.Adamson@Sun.COM hvio_set_rp_mps(devhandle_t dev_hdl, pci_device_t bdf, int32_t mps)
597596SAlan.Adamson@Sun.COM {
607596SAlan.Adamson@Sun.COM return (hvio_rp_mps(dev_hdl, bdf, &mps, MPS_SET));
617596SAlan.Adamson@Sun.COM }
627596SAlan.Adamson@Sun.COM
637596SAlan.Adamson@Sun.COM uint64_t
hvio_rp_mps(devhandle_t dev_hdl,pci_device_t bdf,int32_t * mps,int op)647596SAlan.Adamson@Sun.COM hvio_rp_mps(devhandle_t dev_hdl, pci_device_t bdf, int32_t *mps, int op)
657596SAlan.Adamson@Sun.COM {
6610595SShesha.Sreenivasamurthy@Sun.COM uint64_t data, hdr, hdr_next_ptr, hdr_cap_id;
677596SAlan.Adamson@Sun.COM uint16_t offset = PCI_CONF_STAT;
687596SAlan.Adamson@Sun.COM int deadcount = 0;
697596SAlan.Adamson@Sun.COM pci_cfg_data_t dataw;
707596SAlan.Adamson@Sun.COM
717596SAlan.Adamson@Sun.COM if ((hvio_config_get(dev_hdl, bdf, PCI_CONF_VENID, 4,
727596SAlan.Adamson@Sun.COM (pci_cfg_data_t *)&data)) != H_EOK)
737596SAlan.Adamson@Sun.COM return (H_ENOACCESS);
747596SAlan.Adamson@Sun.COM
757596SAlan.Adamson@Sun.COM if ((data & 0xffff) != 0x108e)
767596SAlan.Adamson@Sun.COM return (H_ENOACCESS);
777596SAlan.Adamson@Sun.COM
787596SAlan.Adamson@Sun.COM if ((hvio_config_get(dev_hdl, bdf, PCI_CONF_COMM, 4,
797596SAlan.Adamson@Sun.COM (pci_cfg_data_t *)&hdr)) != H_EOK)
807596SAlan.Adamson@Sun.COM return (H_ENOACCESS);
817596SAlan.Adamson@Sun.COM
827596SAlan.Adamson@Sun.COM if (!(hdr & (PCI_STAT_CAP << 16)))
837596SAlan.Adamson@Sun.COM return (H_ENOACCESS);
847596SAlan.Adamson@Sun.COM
857596SAlan.Adamson@Sun.COM (void) hvio_config_get(dev_hdl, bdf, PCI_CONF_CAP_PTR, 4,
867596SAlan.Adamson@Sun.COM (pci_cfg_data_t *)&hdr);
877596SAlan.Adamson@Sun.COM
887596SAlan.Adamson@Sun.COM hdr_next_ptr = hdr & 0xFF;
897596SAlan.Adamson@Sun.COM hdr_cap_id = 0;
907596SAlan.Adamson@Sun.COM
917596SAlan.Adamson@Sun.COM while ((hdr_next_ptr != PCI_CAP_NEXT_PTR_NULL) &&
927596SAlan.Adamson@Sun.COM (hdr_cap_id != PCI_CAP_ID_PCI_E)) {
937596SAlan.Adamson@Sun.COM
947596SAlan.Adamson@Sun.COM offset = hdr_next_ptr;
957596SAlan.Adamson@Sun.COM
967596SAlan.Adamson@Sun.COM if (hdr_next_ptr < 0x40)
977596SAlan.Adamson@Sun.COM break;
987596SAlan.Adamson@Sun.COM
997596SAlan.Adamson@Sun.COM (void) hvio_config_get(dev_hdl, bdf, hdr_next_ptr, 4,
1007596SAlan.Adamson@Sun.COM (pci_cfg_data_t *)&hdr);
1017596SAlan.Adamson@Sun.COM
1027596SAlan.Adamson@Sun.COM hdr_next_ptr = (hdr >> 8) & 0xFF;
1037596SAlan.Adamson@Sun.COM hdr_cap_id = hdr & 0xFF;
1047596SAlan.Adamson@Sun.COM
1057596SAlan.Adamson@Sun.COM if (deadcount++ > 100)
1067596SAlan.Adamson@Sun.COM break;
1077596SAlan.Adamson@Sun.COM }
1087596SAlan.Adamson@Sun.COM
1097596SAlan.Adamson@Sun.COM if (hdr_cap_id != PCI_CAP_ID_PCI_E)
1107596SAlan.Adamson@Sun.COM return (H_ENOACCESS);
1117596SAlan.Adamson@Sun.COM
1127596SAlan.Adamson@Sun.COM if (op == MPS_SET) {
1137596SAlan.Adamson@Sun.COM
1147596SAlan.Adamson@Sun.COM /* Write the MPS */
1157596SAlan.Adamson@Sun.COM
1167596SAlan.Adamson@Sun.COM (void) hvio_config_get(dev_hdl, bdf, offset + PCIE_DEVCTL,
1177596SAlan.Adamson@Sun.COM 4, (pci_cfg_data_t *)&data);
1187596SAlan.Adamson@Sun.COM
1197596SAlan.Adamson@Sun.COM data = (data & 0xffffff1f) | (*mps << 5);
1207596SAlan.Adamson@Sun.COM
12110595SShesha.Sreenivasamurthy@Sun.COM dataw.qw = data;
1227596SAlan.Adamson@Sun.COM
1237596SAlan.Adamson@Sun.COM (void) hvio_config_put(dev_hdl, bdf, offset + PCIE_DEVCTL,
1247596SAlan.Adamson@Sun.COM 4, dataw);
1257596SAlan.Adamson@Sun.COM } else {
1267596SAlan.Adamson@Sun.COM
1277596SAlan.Adamson@Sun.COM /* Read the MPS Capabilities */
1287596SAlan.Adamson@Sun.COM
1297596SAlan.Adamson@Sun.COM (void) hvio_config_get(dev_hdl, bdf, offset + PCIE_DEVCAP,
1307596SAlan.Adamson@Sun.COM 4, (pci_cfg_data_t *)&data);
1317596SAlan.Adamson@Sun.COM
1327596SAlan.Adamson@Sun.COM *mps = data & 0x7;
1337596SAlan.Adamson@Sun.COM }
1347596SAlan.Adamson@Sun.COM
1357596SAlan.Adamson@Sun.COM return (H_EOK);
1367596SAlan.Adamson@Sun.COM }
137