17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
57aadd8d4Skini * Common Development and Distribution License (the "License").
67aadd8d4Skini * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
22*89b42a21Sandrew.rutz@sun.com * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate */
247c478bd9Sstevel@tonic-gate
257c478bd9Sstevel@tonic-gate #include <sys/types.h>
267c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
277c478bd9Sstevel@tonic-gate #include <sys/conf.h>
287c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
297c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
30eae2e508Skrishnae #include <sys/sunndi.h>
31f8d2de6bSjchu #include <sys/fm/protocol.h>
32f8d2de6bSjchu #include <sys/fm/util.h>
337c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
347c478bd9Sstevel@tonic-gate #include <sys/disp.h>
357c478bd9Sstevel@tonic-gate #include <sys/stat.h>
367c478bd9Sstevel@tonic-gate #include <sys/ddi_impldefs.h>
377c478bd9Sstevel@tonic-gate #include <sys/vmem.h>
387c478bd9Sstevel@tonic-gate #include <sys/iommutsb.h>
397c478bd9Sstevel@tonic-gate #include <sys/cpuvar.h>
40f8d2de6bSjchu #include <sys/ivintr.h>
418bc7d88aSet142600 #include <sys/byteorder.h>
42a3c68edcSjchu #include <sys/spl.h>
437c478bd9Sstevel@tonic-gate #include <px_obj.h>
44d4bc0535SKrishna Elango #include <sys/pcie_pwr.h>
4525cf1a30Sjl139090 #include "px_tools_var.h"
467c478bd9Sstevel@tonic-gate #include <px_regs.h>
477c478bd9Sstevel@tonic-gate #include <px_csr.h>
48f8d2de6bSjchu #include <sys/machsystm.h>
497c478bd9Sstevel@tonic-gate #include "px_lib4u.h"
50f8d2de6bSjchu #include "px_err.h"
5125cf1a30Sjl139090 #include "oberon_regs.h"
5226947304SEvan Yan #include <sys/hotplug/pci/pcie_hp.h>
537c478bd9Sstevel@tonic-gate
547c478bd9Sstevel@tonic-gate #pragma weak jbus_stst_order
557c478bd9Sstevel@tonic-gate
567c478bd9Sstevel@tonic-gate extern void jbus_stst_order();
577c478bd9Sstevel@tonic-gate
587c478bd9Sstevel@tonic-gate ulong_t px_mmu_dvma_end = 0xfffffffful;
597c478bd9Sstevel@tonic-gate uint_t px_ranges_phi_mask = 0xfffffffful;
6025cf1a30Sjl139090 uint64_t *px_oberon_ubc_scratch_regs;
61f0a73f04Sschwartz uint64_t px_paddr_mask;
627c478bd9Sstevel@tonic-gate
637c478bd9Sstevel@tonic-gate static int px_goto_l23ready(px_t *px_p);
641a887b2eSjchu static int px_goto_l0(px_t *px_p);
651a887b2eSjchu static int px_pre_pwron_check(px_t *px_p);
667e1db6d2Sschwartz static uint32_t px_identity_init(px_t *px_p);
67817a6df8Sjchu static boolean_t px_cpr_callb(void *arg, int code);
6801689544Sjchu static uint_t px_cb_intr(caddr_t arg);
69f8d2de6bSjchu
70f8d2de6bSjchu /*
710114761dSAlan Adamson, SD OSSD * ACKNAK Latency Threshold Table.
720114761dSAlan Adamson, SD OSSD * See Fire PRM 2.0 section 1.2.12.2, table 1-17.
730114761dSAlan Adamson, SD OSSD */
740114761dSAlan Adamson, SD OSSD int px_acknak_timer_table[LINK_MAX_PKT_ARR_SIZE][LINK_WIDTH_ARR_SIZE] = {
750114761dSAlan Adamson, SD OSSD {0xED, 0x49, 0x43, 0x30},
760114761dSAlan Adamson, SD OSSD {0x1A0, 0x76, 0x6B, 0x48},
770114761dSAlan Adamson, SD OSSD {0x22F, 0x9A, 0x56, 0x56},
780114761dSAlan Adamson, SD OSSD {0x42F, 0x11A, 0x96, 0x96},
790114761dSAlan Adamson, SD OSSD {0x82F, 0x21A, 0x116, 0x116},
800114761dSAlan Adamson, SD OSSD {0x102F, 0x41A, 0x216, 0x216}
810114761dSAlan Adamson, SD OSSD };
820114761dSAlan Adamson, SD OSSD
830114761dSAlan Adamson, SD OSSD /*
840114761dSAlan Adamson, SD OSSD * TxLink Replay Timer Latency Table
850114761dSAlan Adamson, SD OSSD * See Fire PRM 2.0 sections 1.2.12.3, table 1-18.
860114761dSAlan Adamson, SD OSSD */
870114761dSAlan Adamson, SD OSSD int px_replay_timer_table[LINK_MAX_PKT_ARR_SIZE][LINK_WIDTH_ARR_SIZE] = {
880114761dSAlan Adamson, SD OSSD {0x379, 0x112, 0xFC, 0xB4},
890114761dSAlan Adamson, SD OSSD {0x618, 0x1BA, 0x192, 0x10E},
900114761dSAlan Adamson, SD OSSD {0x831, 0x242, 0x143, 0x143},
910114761dSAlan Adamson, SD OSSD {0xFB1, 0x422, 0x233, 0x233},
920114761dSAlan Adamson, SD OSSD {0x1EB0, 0x7E1, 0x412, 0x412},
930114761dSAlan Adamson, SD OSSD {0x3CB0, 0xF61, 0x7D2, 0x7D2}
940114761dSAlan Adamson, SD OSSD };
950114761dSAlan Adamson, SD OSSD /*
96f8d2de6bSjchu * px_lib_map_registers
97f8d2de6bSjchu *
98f8d2de6bSjchu * This function is called from the attach routine to map the registers
99f8d2de6bSjchu * accessed by this driver.
100f8d2de6bSjchu *
101f8d2de6bSjchu * used by: px_attach()
102f8d2de6bSjchu *
103f8d2de6bSjchu * return value: DDI_FAILURE on failure
104f8d2de6bSjchu */
105f8d2de6bSjchu int
px_lib_map_regs(pxu_t * pxu_p,dev_info_t * dip)106f8d2de6bSjchu px_lib_map_regs(pxu_t *pxu_p, dev_info_t *dip)
107f8d2de6bSjchu {
108f8d2de6bSjchu ddi_device_acc_attr_t attr;
109f8d2de6bSjchu px_reg_bank_t reg_bank = PX_REG_CSR;
110f8d2de6bSjchu
111f8d2de6bSjchu DBG(DBG_ATTACH, dip, "px_lib_map_regs: pxu_p:0x%p, dip 0x%p\n",
112f8d2de6bSjchu pxu_p, dip);
113f8d2de6bSjchu
114f8d2de6bSjchu attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
115f8d2de6bSjchu attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
116f8d2de6bSjchu attr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC;
117f8d2de6bSjchu
118f8d2de6bSjchu /*
119f8d2de6bSjchu * PCI CSR Base
120f8d2de6bSjchu */
121f8d2de6bSjchu if (ddi_regs_map_setup(dip, reg_bank, &pxu_p->px_address[reg_bank],
122f8d2de6bSjchu 0, 0, &attr, &pxu_p->px_ac[reg_bank]) != DDI_SUCCESS) {
123f8d2de6bSjchu goto fail;
124f8d2de6bSjchu }
125f8d2de6bSjchu
126f8d2de6bSjchu reg_bank++;
127f8d2de6bSjchu
128f8d2de6bSjchu /*
129f8d2de6bSjchu * XBUS CSR Base
130f8d2de6bSjchu */
131f8d2de6bSjchu if (ddi_regs_map_setup(dip, reg_bank, &pxu_p->px_address[reg_bank],
132f8d2de6bSjchu 0, 0, &attr, &pxu_p->px_ac[reg_bank]) != DDI_SUCCESS) {
133f8d2de6bSjchu goto fail;
134f8d2de6bSjchu }
135f8d2de6bSjchu
136f8d2de6bSjchu pxu_p->px_address[reg_bank] -= FIRE_CONTROL_STATUS;
137f8d2de6bSjchu
138f8d2de6bSjchu done:
139f8d2de6bSjchu for (; reg_bank >= PX_REG_CSR; reg_bank--) {
140f8d2de6bSjchu DBG(DBG_ATTACH, dip, "reg_bank 0x%x address 0x%p\n",
141f8d2de6bSjchu reg_bank, pxu_p->px_address[reg_bank]);
142f8d2de6bSjchu }
143f8d2de6bSjchu
144f8d2de6bSjchu return (DDI_SUCCESS);
145f8d2de6bSjchu
146f8d2de6bSjchu fail:
147f8d2de6bSjchu cmn_err(CE_WARN, "%s%d: unable to map reg entry %d\n",
148f8d2de6bSjchu ddi_driver_name(dip), ddi_get_instance(dip), reg_bank);
149f8d2de6bSjchu
150f8d2de6bSjchu for (reg_bank--; reg_bank >= PX_REG_CSR; reg_bank--) {
151f8d2de6bSjchu pxu_p->px_address[reg_bank] = NULL;
152f8d2de6bSjchu ddi_regs_map_free(&pxu_p->px_ac[reg_bank]);
153f8d2de6bSjchu }
154f8d2de6bSjchu
155f8d2de6bSjchu return (DDI_FAILURE);
156f8d2de6bSjchu }
157f8d2de6bSjchu
158f8d2de6bSjchu /*
159f8d2de6bSjchu * px_lib_unmap_regs:
160f8d2de6bSjchu *
161f8d2de6bSjchu * This routine unmaps the registers mapped by map_px_registers.
162f8d2de6bSjchu *
163f8d2de6bSjchu * used by: px_detach(), and error conditions in px_attach()
164f8d2de6bSjchu *
165f8d2de6bSjchu * return value: none
166f8d2de6bSjchu */
167f8d2de6bSjchu void
px_lib_unmap_regs(pxu_t * pxu_p)168f8d2de6bSjchu px_lib_unmap_regs(pxu_t *pxu_p)
169f8d2de6bSjchu {
170f8d2de6bSjchu int i;
171f8d2de6bSjchu
172f8d2de6bSjchu for (i = 0; i < PX_REG_MAX; i++) {
173f8d2de6bSjchu if (pxu_p->px_ac[i])
174f8d2de6bSjchu ddi_regs_map_free(&pxu_p->px_ac[i]);
175f8d2de6bSjchu }
176f8d2de6bSjchu }
1777c478bd9Sstevel@tonic-gate
1787c478bd9Sstevel@tonic-gate int
px_lib_dev_init(dev_info_t * dip,devhandle_t * dev_hdl)1797c478bd9Sstevel@tonic-gate px_lib_dev_init(dev_info_t *dip, devhandle_t *dev_hdl)
1807c478bd9Sstevel@tonic-gate {
18108a74c0dSschwartz
182f8d2de6bSjchu caddr_t xbc_csr_base, csr_base;
1837c478bd9Sstevel@tonic-gate px_dvma_range_prop_t px_dvma_range;
1847c478bd9Sstevel@tonic-gate pxu_t *pxu_p;
18508a74c0dSschwartz uint8_t chip_mask;
18608a74c0dSschwartz px_t *px_p = DIP_TO_STATE(dip);
18708a74c0dSschwartz px_chip_type_t chip_type = px_identity_init(px_p);
1887c478bd9Sstevel@tonic-gate
1897e1db6d2Sschwartz DBG(DBG_ATTACH, dip, "px_lib_dev_init: dip 0x%p", dip);
1907c478bd9Sstevel@tonic-gate
1917e1db6d2Sschwartz if (chip_type == PX_CHIP_UNIDENTIFIED) {
1927e1db6d2Sschwartz cmn_err(CE_WARN, "%s%d: Unrecognized Hardware Version\n",
1937e1db6d2Sschwartz NAMEINST(dip));
1947c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
1957c478bd9Sstevel@tonic-gate }
1967c478bd9Sstevel@tonic-gate
19708a74c0dSschwartz chip_mask = BITMASK(chip_type);
1987e1db6d2Sschwartz px_paddr_mask = (chip_type == PX_CHIP_FIRE) ? MMU_FIRE_PADDR_MASK :
1997e1db6d2Sschwartz MMU_OBERON_PADDR_MASK;
2007e1db6d2Sschwartz
2017c478bd9Sstevel@tonic-gate /*
2027c478bd9Sstevel@tonic-gate * Allocate platform specific structure and link it to
2037c478bd9Sstevel@tonic-gate * the px state structure.
2047c478bd9Sstevel@tonic-gate */
2057c478bd9Sstevel@tonic-gate pxu_p = kmem_zalloc(sizeof (pxu_t), KM_SLEEP);
2067e1db6d2Sschwartz pxu_p->chip_type = chip_type;
2077c478bd9Sstevel@tonic-gate pxu_p->portid = ddi_getprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
2087c478bd9Sstevel@tonic-gate "portid", -1);
2097c478bd9Sstevel@tonic-gate
210f8d2de6bSjchu /* Map in the registers */
211f8d2de6bSjchu if (px_lib_map_regs(pxu_p, dip) == DDI_FAILURE) {
212f8d2de6bSjchu kmem_free(pxu_p, sizeof (pxu_t));
213f8d2de6bSjchu
214f8d2de6bSjchu return (DDI_FAILURE);
215f8d2de6bSjchu }
216f8d2de6bSjchu
217f8d2de6bSjchu xbc_csr_base = (caddr_t)pxu_p->px_address[PX_REG_XBC];
218f8d2de6bSjchu csr_base = (caddr_t)pxu_p->px_address[PX_REG_CSR];
219f8d2de6bSjchu
2207c478bd9Sstevel@tonic-gate pxu_p->tsb_cookie = iommu_tsb_alloc(pxu_p->portid);
2217c478bd9Sstevel@tonic-gate pxu_p->tsb_size = iommu_tsb_cookie_to_size(pxu_p->tsb_cookie);
2227c478bd9Sstevel@tonic-gate pxu_p->tsb_vaddr = iommu_tsb_cookie_to_va(pxu_p->tsb_cookie);
2237c478bd9Sstevel@tonic-gate
22425cf1a30Sjl139090 pxu_p->tsb_paddr = va_to_pa(pxu_p->tsb_vaddr);
22525cf1a30Sjl139090
2267c478bd9Sstevel@tonic-gate /*
2277c478bd9Sstevel@tonic-gate * Create "virtual-dma" property to support child devices
2287c478bd9Sstevel@tonic-gate * needing to know DVMA range.
2297c478bd9Sstevel@tonic-gate */
2307c478bd9Sstevel@tonic-gate px_dvma_range.dvma_base = (uint32_t)px_mmu_dvma_end + 1
2317c478bd9Sstevel@tonic-gate - ((pxu_p->tsb_size >> 3) << MMU_PAGE_SHIFT);
2327c478bd9Sstevel@tonic-gate px_dvma_range.dvma_len = (uint32_t)
2337c478bd9Sstevel@tonic-gate px_mmu_dvma_end - px_dvma_range.dvma_base + 1;
2347c478bd9Sstevel@tonic-gate
2351f7be8d9Sdanice (void) ddi_prop_update_int_array(DDI_DEV_T_NONE, dip,
2361f7be8d9Sdanice "virtual-dma", (int *)&px_dvma_range,
2371f7be8d9Sdanice sizeof (px_dvma_range_prop_t) / sizeof (int));
2387c478bd9Sstevel@tonic-gate /*
2397c478bd9Sstevel@tonic-gate * Initilize all fire hardware specific blocks.
2407c478bd9Sstevel@tonic-gate */
2417c478bd9Sstevel@tonic-gate hvio_cb_init(xbc_csr_base, pxu_p);
2427c478bd9Sstevel@tonic-gate hvio_ib_init(csr_base, pxu_p);
2437c478bd9Sstevel@tonic-gate hvio_pec_init(csr_base, pxu_p);
2447c478bd9Sstevel@tonic-gate hvio_mmu_init(csr_base, pxu_p);
2457c478bd9Sstevel@tonic-gate
2467c478bd9Sstevel@tonic-gate px_p->px_plat_p = (void *)pxu_p;
2477c478bd9Sstevel@tonic-gate
248f8d2de6bSjchu /*
249f8d2de6bSjchu * Initialize all the interrupt handlers
250f8d2de6bSjchu */
25125cf1a30Sjl139090 switch (PX_CHIP_TYPE(pxu_p)) {
25225cf1a30Sjl139090 case PX_CHIP_OBERON:
253597077b2Sjj156685 /*
254597077b2Sjj156685 * Oberon hotplug uses SPARE3 field in ILU Error Log Enable
255597077b2Sjj156685 * register to indicate the status of leaf reset,
256597077b2Sjj156685 * we need to preserve the value of this bit, and keep it in
257597077b2Sjj156685 * px_ilu_log_mask to reflect the state of the bit
258597077b2Sjj156685 */
259597077b2Sjj156685 if (CSR_BR(csr_base, ILU_ERROR_LOG_ENABLE, SPARE3))
260597077b2Sjj156685 px_ilu_log_mask |= (1ull <<
261597077b2Sjj156685 ILU_ERROR_LOG_ENABLE_SPARE3);
262597077b2Sjj156685 else
263597077b2Sjj156685 px_ilu_log_mask &= ~(1ull <<
264597077b2Sjj156685 ILU_ERROR_LOG_ENABLE_SPARE3);
26525cf1a30Sjl139090
26608a74c0dSschwartz px_err_reg_setup_pcie(chip_mask, csr_base, PX_ERR_ENABLE);
26725cf1a30Sjl139090 break;
26825cf1a30Sjl139090
26925cf1a30Sjl139090 case PX_CHIP_FIRE:
27008a74c0dSschwartz px_err_reg_setup_pcie(chip_mask, csr_base, PX_ERR_ENABLE);
27125cf1a30Sjl139090 break;
27208a74c0dSschwartz
27325cf1a30Sjl139090 default:
27425cf1a30Sjl139090 cmn_err(CE_WARN, "%s%d: PX primary bus Unknown\n",
27525cf1a30Sjl139090 ddi_driver_name(dip), ddi_get_instance(dip));
27625cf1a30Sjl139090 return (DDI_FAILURE);
27725cf1a30Sjl139090 }
278f8d2de6bSjchu
2797c478bd9Sstevel@tonic-gate /* Initilize device handle */
2807c478bd9Sstevel@tonic-gate *dev_hdl = (devhandle_t)csr_base;
2817c478bd9Sstevel@tonic-gate
2827c478bd9Sstevel@tonic-gate DBG(DBG_ATTACH, dip, "px_lib_dev_init: dev_hdl 0x%llx\n", *dev_hdl);
2837c478bd9Sstevel@tonic-gate
284fc256490SJason Beloro /* Sun4u always support fixed interrupt */
285fc256490SJason Beloro px_p->px_supp_intr_types |= DDI_INTR_TYPE_FIXED;
286fc256490SJason Beloro
2877c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
2887c478bd9Sstevel@tonic-gate }
2897c478bd9Sstevel@tonic-gate
2907c478bd9Sstevel@tonic-gate int
px_lib_dev_fini(dev_info_t * dip)2917c478bd9Sstevel@tonic-gate px_lib_dev_fini(dev_info_t *dip)
2927c478bd9Sstevel@tonic-gate {
29308a74c0dSschwartz caddr_t csr_base;
29408a74c0dSschwartz uint8_t chip_mask;
2957c478bd9Sstevel@tonic-gate px_t *px_p = DIP_TO_STATE(dip);
2967c478bd9Sstevel@tonic-gate pxu_t *pxu_p = (pxu_t *)px_p->px_plat_p;
2977c478bd9Sstevel@tonic-gate
2987c478bd9Sstevel@tonic-gate DBG(DBG_DETACH, dip, "px_lib_dev_fini: dip 0x%p\n", dip);
2997c478bd9Sstevel@tonic-gate
300f8d2de6bSjchu /*
301f8d2de6bSjchu * Deinitialize all the interrupt handlers
302f8d2de6bSjchu */
30325cf1a30Sjl139090 switch (PX_CHIP_TYPE(pxu_p)) {
30425cf1a30Sjl139090 case PX_CHIP_OBERON:
30525cf1a30Sjl139090 case PX_CHIP_FIRE:
30608a74c0dSschwartz chip_mask = BITMASK(PX_CHIP_TYPE(pxu_p));
30708a74c0dSschwartz csr_base = (caddr_t)pxu_p->px_address[PX_REG_CSR];
30808a74c0dSschwartz px_err_reg_setup_pcie(chip_mask, csr_base, PX_ERR_DISABLE);
30925cf1a30Sjl139090 break;
31008a74c0dSschwartz
31125cf1a30Sjl139090 default:
31225cf1a30Sjl139090 cmn_err(CE_WARN, "%s%d: PX primary bus Unknown\n",
31325cf1a30Sjl139090 ddi_driver_name(dip), ddi_get_instance(dip));
31425cf1a30Sjl139090 return (DDI_FAILURE);
31525cf1a30Sjl139090 }
316f8d2de6bSjchu
3177c478bd9Sstevel@tonic-gate iommu_tsb_free(pxu_p->tsb_cookie);
3187c478bd9Sstevel@tonic-gate
319f8d2de6bSjchu px_lib_unmap_regs((pxu_t *)px_p->px_plat_p);
320f8d2de6bSjchu kmem_free(px_p->px_plat_p, sizeof (pxu_t));
3217c478bd9Sstevel@tonic-gate px_p->px_plat_p = NULL;
3221f7be8d9Sdanice (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "virtual-dma");
3237c478bd9Sstevel@tonic-gate
3247c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
3257c478bd9Sstevel@tonic-gate }
3267c478bd9Sstevel@tonic-gate
3277c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3287c478bd9Sstevel@tonic-gate int
px_lib_intr_devino_to_sysino(dev_info_t * dip,devino_t devino,sysino_t * sysino)3297c478bd9Sstevel@tonic-gate px_lib_intr_devino_to_sysino(dev_info_t *dip, devino_t devino,
3307c478bd9Sstevel@tonic-gate sysino_t *sysino)
3317c478bd9Sstevel@tonic-gate {
3327c478bd9Sstevel@tonic-gate px_t *px_p = DIP_TO_STATE(dip);
3337c478bd9Sstevel@tonic-gate pxu_t *pxu_p = (pxu_t *)px_p->px_plat_p;
3347c478bd9Sstevel@tonic-gate uint64_t ret;
3357c478bd9Sstevel@tonic-gate
3367c478bd9Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "px_lib_intr_devino_to_sysino: dip 0x%p "
3377c478bd9Sstevel@tonic-gate "devino 0x%x\n", dip, devino);
3387c478bd9Sstevel@tonic-gate
3397c478bd9Sstevel@tonic-gate if ((ret = hvio_intr_devino_to_sysino(DIP_TO_HANDLE(dip),
3407c478bd9Sstevel@tonic-gate pxu_p, devino, sysino)) != H_EOK) {
3417c478bd9Sstevel@tonic-gate DBG(DBG_LIB_INT, dip,
3427c478bd9Sstevel@tonic-gate "hvio_intr_devino_to_sysino failed, ret 0x%lx\n", ret);
3437c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
3447c478bd9Sstevel@tonic-gate }
3457c478bd9Sstevel@tonic-gate
3467c478bd9Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "px_lib_intr_devino_to_sysino: sysino 0x%llx\n",
3477c478bd9Sstevel@tonic-gate *sysino);
3487c478bd9Sstevel@tonic-gate
3497c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
3507c478bd9Sstevel@tonic-gate }
3517c478bd9Sstevel@tonic-gate
3527c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3537c478bd9Sstevel@tonic-gate int
px_lib_intr_getvalid(dev_info_t * dip,sysino_t sysino,intr_valid_state_t * intr_valid_state)3547c478bd9Sstevel@tonic-gate px_lib_intr_getvalid(dev_info_t *dip, sysino_t sysino,
3557c478bd9Sstevel@tonic-gate intr_valid_state_t *intr_valid_state)
3567c478bd9Sstevel@tonic-gate {
3577c478bd9Sstevel@tonic-gate uint64_t ret;
3587c478bd9Sstevel@tonic-gate
3597c478bd9Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "px_lib_intr_getvalid: dip 0x%p sysino 0x%llx\n",
3607c478bd9Sstevel@tonic-gate dip, sysino);
3617c478bd9Sstevel@tonic-gate
3627c478bd9Sstevel@tonic-gate if ((ret = hvio_intr_getvalid(DIP_TO_HANDLE(dip),
3637c478bd9Sstevel@tonic-gate sysino, intr_valid_state)) != H_EOK) {
3647c478bd9Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "hvio_intr_getvalid failed, ret 0x%lx\n",
3657c478bd9Sstevel@tonic-gate ret);
3667c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
3677c478bd9Sstevel@tonic-gate }
3687c478bd9Sstevel@tonic-gate
3697c478bd9Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "px_lib_intr_getvalid: intr_valid_state 0x%x\n",
3707c478bd9Sstevel@tonic-gate *intr_valid_state);
3717c478bd9Sstevel@tonic-gate
3727c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
3737c478bd9Sstevel@tonic-gate }
3747c478bd9Sstevel@tonic-gate
3757c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3767c478bd9Sstevel@tonic-gate int
px_lib_intr_setvalid(dev_info_t * dip,sysino_t sysino,intr_valid_state_t intr_valid_state)3777c478bd9Sstevel@tonic-gate px_lib_intr_setvalid(dev_info_t *dip, sysino_t sysino,
3787c478bd9Sstevel@tonic-gate intr_valid_state_t intr_valid_state)
3797c478bd9Sstevel@tonic-gate {
3807c478bd9Sstevel@tonic-gate uint64_t ret;
3817c478bd9Sstevel@tonic-gate
3827c478bd9Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "px_lib_intr_setvalid: dip 0x%p sysino 0x%llx "
3837c478bd9Sstevel@tonic-gate "intr_valid_state 0x%x\n", dip, sysino, intr_valid_state);
3847c478bd9Sstevel@tonic-gate
3857c478bd9Sstevel@tonic-gate if ((ret = hvio_intr_setvalid(DIP_TO_HANDLE(dip),
3867c478bd9Sstevel@tonic-gate sysino, intr_valid_state)) != H_EOK) {
3877c478bd9Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "hvio_intr_setvalid failed, ret 0x%lx\n",
3887c478bd9Sstevel@tonic-gate ret);
3897c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
3907c478bd9Sstevel@tonic-gate }
3917c478bd9Sstevel@tonic-gate
3927c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
3937c478bd9Sstevel@tonic-gate }
3947c478bd9Sstevel@tonic-gate
3957c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3967c478bd9Sstevel@tonic-gate int
px_lib_intr_getstate(dev_info_t * dip,sysino_t sysino,intr_state_t * intr_state)3977c478bd9Sstevel@tonic-gate px_lib_intr_getstate(dev_info_t *dip, sysino_t sysino,
3987c478bd9Sstevel@tonic-gate intr_state_t *intr_state)
3997c478bd9Sstevel@tonic-gate {
4007c478bd9Sstevel@tonic-gate uint64_t ret;
4017c478bd9Sstevel@tonic-gate
4027c478bd9Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "px_lib_intr_getstate: dip 0x%p sysino 0x%llx\n",
4037c478bd9Sstevel@tonic-gate dip, sysino);
4047c478bd9Sstevel@tonic-gate
4057c478bd9Sstevel@tonic-gate if ((ret = hvio_intr_getstate(DIP_TO_HANDLE(dip),
4067c478bd9Sstevel@tonic-gate sysino, intr_state)) != H_EOK) {
4077c478bd9Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "hvio_intr_getstate failed, ret 0x%lx\n",
4087c478bd9Sstevel@tonic-gate ret);
4097c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
4107c478bd9Sstevel@tonic-gate }
4117c478bd9Sstevel@tonic-gate
4127c478bd9Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "px_lib_intr_getstate: intr_state 0x%x\n",
4137c478bd9Sstevel@tonic-gate *intr_state);
4147c478bd9Sstevel@tonic-gate
4157c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
4167c478bd9Sstevel@tonic-gate }
4177c478bd9Sstevel@tonic-gate
4187c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4197c478bd9Sstevel@tonic-gate int
px_lib_intr_setstate(dev_info_t * dip,sysino_t sysino,intr_state_t intr_state)4207c478bd9Sstevel@tonic-gate px_lib_intr_setstate(dev_info_t *dip, sysino_t sysino,
4217c478bd9Sstevel@tonic-gate intr_state_t intr_state)
4227c478bd9Sstevel@tonic-gate {
4237c478bd9Sstevel@tonic-gate uint64_t ret;
4247c478bd9Sstevel@tonic-gate
4257c478bd9Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "px_lib_intr_setstate: dip 0x%p sysino 0x%llx "
4267c478bd9Sstevel@tonic-gate "intr_state 0x%x\n", dip, sysino, intr_state);
4277c478bd9Sstevel@tonic-gate
4287c478bd9Sstevel@tonic-gate if ((ret = hvio_intr_setstate(DIP_TO_HANDLE(dip),
4297c478bd9Sstevel@tonic-gate sysino, intr_state)) != H_EOK) {
4307c478bd9Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "hvio_intr_setstate failed, ret 0x%lx\n",
4317c478bd9Sstevel@tonic-gate ret);
4327c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
4337c478bd9Sstevel@tonic-gate }
4347c478bd9Sstevel@tonic-gate
4357c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
4367c478bd9Sstevel@tonic-gate }
4377c478bd9Sstevel@tonic-gate
4387c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4397c478bd9Sstevel@tonic-gate int
px_lib_intr_gettarget(dev_info_t * dip,sysino_t sysino,cpuid_t * cpuid)4407c478bd9Sstevel@tonic-gate px_lib_intr_gettarget(dev_info_t *dip, sysino_t sysino, cpuid_t *cpuid)
4417c478bd9Sstevel@tonic-gate {
44225cf1a30Sjl139090 px_t *px_p = DIP_TO_STATE(dip);
44325cf1a30Sjl139090 pxu_t *pxu_p = (pxu_t *)px_p->px_plat_p;
4447c478bd9Sstevel@tonic-gate uint64_t ret;
4457c478bd9Sstevel@tonic-gate
4467c478bd9Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "px_lib_intr_gettarget: dip 0x%p sysino 0x%llx\n",
4477c478bd9Sstevel@tonic-gate dip, sysino);
4487c478bd9Sstevel@tonic-gate
44925cf1a30Sjl139090 if ((ret = hvio_intr_gettarget(DIP_TO_HANDLE(dip), pxu_p,
4507c478bd9Sstevel@tonic-gate sysino, cpuid)) != H_EOK) {
4517c478bd9Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "hvio_intr_gettarget failed, ret 0x%lx\n",
4527c478bd9Sstevel@tonic-gate ret);
4537c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
4547c478bd9Sstevel@tonic-gate }
4557c478bd9Sstevel@tonic-gate
4567c478bd9Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "px_lib_intr_gettarget: cpuid 0x%x\n", cpuid);
4577c478bd9Sstevel@tonic-gate
4587c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
4597c478bd9Sstevel@tonic-gate }
4607c478bd9Sstevel@tonic-gate
4617c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4627c478bd9Sstevel@tonic-gate int
px_lib_intr_settarget(dev_info_t * dip,sysino_t sysino,cpuid_t cpuid)4637c478bd9Sstevel@tonic-gate px_lib_intr_settarget(dev_info_t *dip, sysino_t sysino, cpuid_t cpuid)
4647c478bd9Sstevel@tonic-gate {
46525cf1a30Sjl139090 px_t *px_p = DIP_TO_STATE(dip);
46625cf1a30Sjl139090 pxu_t *pxu_p = (pxu_t *)px_p->px_plat_p;
4677c478bd9Sstevel@tonic-gate uint64_t ret;
4687c478bd9Sstevel@tonic-gate
4697c478bd9Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "px_lib_intr_settarget: dip 0x%p sysino 0x%llx "
4707c478bd9Sstevel@tonic-gate "cpuid 0x%x\n", dip, sysino, cpuid);
4717c478bd9Sstevel@tonic-gate
47225cf1a30Sjl139090 if ((ret = hvio_intr_settarget(DIP_TO_HANDLE(dip), pxu_p,
4737c478bd9Sstevel@tonic-gate sysino, cpuid)) != H_EOK) {
4747c478bd9Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "hvio_intr_settarget failed, ret 0x%lx\n",
4757c478bd9Sstevel@tonic-gate ret);
4767c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
4777c478bd9Sstevel@tonic-gate }
4787c478bd9Sstevel@tonic-gate
4797c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
4807c478bd9Sstevel@tonic-gate }
4817c478bd9Sstevel@tonic-gate
4827c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4837c478bd9Sstevel@tonic-gate int
px_lib_intr_reset(dev_info_t * dip)4847c478bd9Sstevel@tonic-gate px_lib_intr_reset(dev_info_t *dip)
4857c478bd9Sstevel@tonic-gate {
4867c478bd9Sstevel@tonic-gate devino_t ino;
4877c478bd9Sstevel@tonic-gate sysino_t sysino;
4887c478bd9Sstevel@tonic-gate
4897c478bd9Sstevel@tonic-gate DBG(DBG_LIB_INT, dip, "px_lib_intr_reset: dip 0x%p\n", dip);
4907c478bd9Sstevel@tonic-gate
4917c478bd9Sstevel@tonic-gate /* Reset all Interrupts */
4927c478bd9Sstevel@tonic-gate for (ino = 0; ino < INTERRUPT_MAPPING_ENTRIES; ino++) {
4937c478bd9Sstevel@tonic-gate if (px_lib_intr_devino_to_sysino(dip, ino,
4947c478bd9Sstevel@tonic-gate &sysino) != DDI_SUCCESS)
4957c478bd9Sstevel@tonic-gate return (BF_FATAL);
4967c478bd9Sstevel@tonic-gate
4977c478bd9Sstevel@tonic-gate if (px_lib_intr_setstate(dip, sysino,
4987c478bd9Sstevel@tonic-gate INTR_IDLE_STATE) != DDI_SUCCESS)
4997c478bd9Sstevel@tonic-gate return (BF_FATAL);
5007c478bd9Sstevel@tonic-gate }
5017c478bd9Sstevel@tonic-gate
5027c478bd9Sstevel@tonic-gate return (BF_NONE);
5037c478bd9Sstevel@tonic-gate }
5047c478bd9Sstevel@tonic-gate
5057c478bd9Sstevel@tonic-gate /*ARGSUSED*/
5067c478bd9Sstevel@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)5077c478bd9Sstevel@tonic-gate px_lib_iommu_map(dev_info_t *dip, tsbid_t tsbid, pages_t pages,
50844bb982bSgovinda io_attributes_t attr, void *addr, size_t pfn_index, int flags)
5097c478bd9Sstevel@tonic-gate {
5107c478bd9Sstevel@tonic-gate px_t *px_p = DIP_TO_STATE(dip);
5117c478bd9Sstevel@tonic-gate pxu_t *pxu_p = (pxu_t *)px_p->px_plat_p;
5127c478bd9Sstevel@tonic-gate uint64_t ret;
5137c478bd9Sstevel@tonic-gate
5147c478bd9Sstevel@tonic-gate DBG(DBG_LIB_DMA, dip, "px_lib_iommu_map: dip 0x%p tsbid 0x%llx "
515ef2504f2SDaniel Ice "pages 0x%x attr 0x%llx addr 0x%p pfn_index 0x%llx flags 0x%x\n",
51644bb982bSgovinda dip, tsbid, pages, attr, addr, pfn_index, flags);
5177c478bd9Sstevel@tonic-gate
5187c478bd9Sstevel@tonic-gate if ((ret = hvio_iommu_map(px_p->px_dev_hdl, pxu_p, tsbid, pages,
51944bb982bSgovinda attr, addr, pfn_index, flags)) != H_EOK) {
5207c478bd9Sstevel@tonic-gate DBG(DBG_LIB_DMA, dip,
5217c478bd9Sstevel@tonic-gate "px_lib_iommu_map failed, ret 0x%lx\n", ret);
5227c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
5237c478bd9Sstevel@tonic-gate }
5247c478bd9Sstevel@tonic-gate
5257c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
5267c478bd9Sstevel@tonic-gate }
5277c478bd9Sstevel@tonic-gate
5287c478bd9Sstevel@tonic-gate /*ARGSUSED*/
5297c478bd9Sstevel@tonic-gate int
px_lib_iommu_demap(dev_info_t * dip,tsbid_t tsbid,pages_t pages)5307c478bd9Sstevel@tonic-gate px_lib_iommu_demap(dev_info_t *dip, tsbid_t tsbid, pages_t pages)
5317c478bd9Sstevel@tonic-gate {
5327c478bd9Sstevel@tonic-gate px_t *px_p = DIP_TO_STATE(dip);
5337c478bd9Sstevel@tonic-gate pxu_t *pxu_p = (pxu_t *)px_p->px_plat_p;
5347c478bd9Sstevel@tonic-gate uint64_t ret;
5357c478bd9Sstevel@tonic-gate
5367c478bd9Sstevel@tonic-gate DBG(DBG_LIB_DMA, dip, "px_lib_iommu_demap: dip 0x%p tsbid 0x%llx "
5377c478bd9Sstevel@tonic-gate "pages 0x%x\n", dip, tsbid, pages);
5387c478bd9Sstevel@tonic-gate
5397c478bd9Sstevel@tonic-gate if ((ret = hvio_iommu_demap(px_p->px_dev_hdl, pxu_p, tsbid, pages))
5407c478bd9Sstevel@tonic-gate != H_EOK) {
5417c478bd9Sstevel@tonic-gate DBG(DBG_LIB_DMA, dip,
5427c478bd9Sstevel@tonic-gate "px_lib_iommu_demap failed, ret 0x%lx\n", ret);
5437c478bd9Sstevel@tonic-gate
5447c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
5457c478bd9Sstevel@tonic-gate }
5467c478bd9Sstevel@tonic-gate
5477c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
5487c478bd9Sstevel@tonic-gate }
5497c478bd9Sstevel@tonic-gate
5507c478bd9Sstevel@tonic-gate /*ARGSUSED*/
5517c478bd9Sstevel@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)55244bb982bSgovinda px_lib_iommu_getmap(dev_info_t *dip, tsbid_t tsbid, io_attributes_t *attr_p,
55344bb982bSgovinda r_addr_t *r_addr_p)
5547c478bd9Sstevel@tonic-gate {
5557c478bd9Sstevel@tonic-gate px_t *px_p = DIP_TO_STATE(dip);
5567c478bd9Sstevel@tonic-gate pxu_t *pxu_p = (pxu_t *)px_p->px_plat_p;
5577c478bd9Sstevel@tonic-gate uint64_t ret;
5587c478bd9Sstevel@tonic-gate
5597c478bd9Sstevel@tonic-gate DBG(DBG_LIB_DMA, dip, "px_lib_iommu_getmap: dip 0x%p tsbid 0x%llx\n",
5607c478bd9Sstevel@tonic-gate dip, tsbid);
5617c478bd9Sstevel@tonic-gate
5627c478bd9Sstevel@tonic-gate if ((ret = hvio_iommu_getmap(DIP_TO_HANDLE(dip), pxu_p, tsbid,
56344bb982bSgovinda attr_p, r_addr_p)) != H_EOK) {
5647c478bd9Sstevel@tonic-gate DBG(DBG_LIB_DMA, dip,
5657c478bd9Sstevel@tonic-gate "hvio_iommu_getmap failed, ret 0x%lx\n", ret);
5667c478bd9Sstevel@tonic-gate
5677c478bd9Sstevel@tonic-gate return ((ret == H_ENOMAP) ? DDI_DMA_NOMAPPING:DDI_FAILURE);
5687c478bd9Sstevel@tonic-gate }
5697c478bd9Sstevel@tonic-gate
570ef2504f2SDaniel Ice DBG(DBG_LIB_DMA, dip, "px_lib_iommu_getmap: attr 0x%llx "
571ef2504f2SDaniel Ice "r_addr 0x%llx\n", *attr_p, *r_addr_p);
5727c478bd9Sstevel@tonic-gate
5737c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
5747c478bd9Sstevel@tonic-gate }
5757c478bd9Sstevel@tonic-gate
576*89b42a21Sandrew.rutz@sun.com int
px_lib_iommu_detach(px_t * px_p)577*89b42a21Sandrew.rutz@sun.com px_lib_iommu_detach(px_t *px_p)
578*89b42a21Sandrew.rutz@sun.com {
579*89b42a21Sandrew.rutz@sun.com /*
580*89b42a21Sandrew.rutz@sun.com * Deallocate DVMA addr space that was reserved for OBP TTE's
581*89b42a21Sandrew.rutz@sun.com * during Attach.
582*89b42a21Sandrew.rutz@sun.com */
583*89b42a21Sandrew.rutz@sun.com hvio_obptsb_detach(px_p);
584*89b42a21Sandrew.rutz@sun.com
585*89b42a21Sandrew.rutz@sun.com return (DDI_SUCCESS);
586*89b42a21Sandrew.rutz@sun.com }
5877c478bd9Sstevel@tonic-gate
5887c478bd9Sstevel@tonic-gate /*
5897c478bd9Sstevel@tonic-gate * Checks dma attributes against system bypass ranges
5907c478bd9Sstevel@tonic-gate * The bypass range is determined by the hardware. Return them so the
5917c478bd9Sstevel@tonic-gate * common code can do generic checking against them.
5927c478bd9Sstevel@tonic-gate */
5937c478bd9Sstevel@tonic-gate /*ARGSUSED*/
5947c478bd9Sstevel@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)59525cf1a30Sjl139090 px_lib_dma_bypass_rngchk(dev_info_t *dip, ddi_dma_attr_t *attr_p,
59625cf1a30Sjl139090 uint64_t *lo_p, uint64_t *hi_p)
5977c478bd9Sstevel@tonic-gate {
59825cf1a30Sjl139090 px_t *px_p = DIP_TO_STATE(dip);
59925cf1a30Sjl139090 pxu_t *pxu_p = (pxu_t *)px_p->px_plat_p;
60025cf1a30Sjl139090
60125cf1a30Sjl139090 *lo_p = hvio_get_bypass_base(pxu_p);
60225cf1a30Sjl139090 *hi_p = hvio_get_bypass_end(pxu_p);
6037c478bd9Sstevel@tonic-gate
6047c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
6057c478bd9Sstevel@tonic-gate }
6067c478bd9Sstevel@tonic-gate
6077c478bd9Sstevel@tonic-gate
6087c478bd9Sstevel@tonic-gate /*ARGSUSED*/
6097c478bd9Sstevel@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)61044bb982bSgovinda px_lib_iommu_getbypass(dev_info_t *dip, r_addr_t ra, io_attributes_t attr,
61144bb982bSgovinda io_addr_t *io_addr_p)
6127c478bd9Sstevel@tonic-gate {
6137c478bd9Sstevel@tonic-gate uint64_t ret;
61425cf1a30Sjl139090 px_t *px_p = DIP_TO_STATE(dip);
61525cf1a30Sjl139090 pxu_t *pxu_p = (pxu_t *)px_p->px_plat_p;
6167c478bd9Sstevel@tonic-gate
6177c478bd9Sstevel@tonic-gate DBG(DBG_LIB_DMA, dip, "px_lib_iommu_getbypass: dip 0x%p ra 0x%llx "
618ef2504f2SDaniel Ice "attr 0x%llx\n", dip, ra, attr);
6197c478bd9Sstevel@tonic-gate
62025cf1a30Sjl139090 if ((ret = hvio_iommu_getbypass(DIP_TO_HANDLE(dip), pxu_p, ra,
62125cf1a30Sjl139090 attr, io_addr_p)) != H_EOK) {
6227c478bd9Sstevel@tonic-gate DBG(DBG_LIB_DMA, dip,
6237c478bd9Sstevel@tonic-gate "hvio_iommu_getbypass failed, ret 0x%lx\n", ret);
6247c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
6257c478bd9Sstevel@tonic-gate }
6267c478bd9Sstevel@tonic-gate
6277c478bd9Sstevel@tonic-gate DBG(DBG_LIB_DMA, dip, "px_lib_iommu_getbypass: io_addr 0x%llx\n",
6287c478bd9Sstevel@tonic-gate *io_addr_p);
6297c478bd9Sstevel@tonic-gate
6307c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
6317c478bd9Sstevel@tonic-gate }
6327c478bd9Sstevel@tonic-gate
6337c478bd9Sstevel@tonic-gate /*
634a616a11eSLida.Horn * Returns any needed IO address bit(s) for relaxed ordering in IOMMU
635a616a11eSLida.Horn * bypass mode.
636a616a11eSLida.Horn */
637a616a11eSLida.Horn uint64_t
px_lib_ro_bypass(dev_info_t * dip,io_attributes_t attr,uint64_t ioaddr)638a616a11eSLida.Horn px_lib_ro_bypass(dev_info_t *dip, io_attributes_t attr, uint64_t ioaddr)
639a616a11eSLida.Horn {
640a616a11eSLida.Horn px_t *px_p = DIP_TO_STATE(dip);
641a616a11eSLida.Horn pxu_t *pxu_p = (pxu_t *)px_p->px_plat_p;
642a616a11eSLida.Horn
643a616a11eSLida.Horn if ((PX_CHIP_TYPE(pxu_p) == PX_CHIP_OBERON) && (attr & PCI_MAP_ATTR_RO))
644a616a11eSLida.Horn return (MMU_OBERON_BYPASS_RO | ioaddr);
645a616a11eSLida.Horn else
646a616a11eSLida.Horn return (ioaddr);
647a616a11eSLida.Horn }
648a616a11eSLida.Horn
649a616a11eSLida.Horn /*
6507c478bd9Sstevel@tonic-gate * bus dma sync entry point.
6517c478bd9Sstevel@tonic-gate */
6527c478bd9Sstevel@tonic-gate /*ARGSUSED*/
6537c478bd9Sstevel@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)6547c478bd9Sstevel@tonic-gate px_lib_dma_sync(dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t handle,
6557c478bd9Sstevel@tonic-gate off_t off, size_t len, uint_t cache_flags)
6567c478bd9Sstevel@tonic-gate {
6577c478bd9Sstevel@tonic-gate ddi_dma_impl_t *mp = (ddi_dma_impl_t *)handle;
65825cf1a30Sjl139090 px_t *px_p = DIP_TO_STATE(dip);
65925cf1a30Sjl139090 pxu_t *pxu_p = (pxu_t *)px_p->px_plat_p;
6607c478bd9Sstevel@tonic-gate
6617c478bd9Sstevel@tonic-gate DBG(DBG_LIB_DMA, dip, "px_lib_dma_sync: dip 0x%p rdip 0x%p "
6627c478bd9Sstevel@tonic-gate "handle 0x%llx off 0x%x len 0x%x flags 0x%x\n",
6637c478bd9Sstevel@tonic-gate dip, rdip, handle, off, len, cache_flags);
6647c478bd9Sstevel@tonic-gate
6657c478bd9Sstevel@tonic-gate /*
66625cf1a30Sjl139090 * No flush needed for Oberon
66725cf1a30Sjl139090 */
66825cf1a30Sjl139090 if (PX_CHIP_TYPE(pxu_p) == PX_CHIP_OBERON)
66925cf1a30Sjl139090 return (DDI_SUCCESS);
67025cf1a30Sjl139090
67125cf1a30Sjl139090 /*
6727c478bd9Sstevel@tonic-gate * jbus_stst_order is found only in certain cpu modules.
6737c478bd9Sstevel@tonic-gate * Just return success if not present.
6747c478bd9Sstevel@tonic-gate */
6757c478bd9Sstevel@tonic-gate if (&jbus_stst_order == NULL)
6767c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
6777c478bd9Sstevel@tonic-gate
67836fe4a92Segillett if (!(mp->dmai_flags & PX_DMAI_FLAGS_INUSE)) {
679f8d2de6bSjchu cmn_err(CE_WARN, "%s%d: Unbound dma handle %p.",
680f8d2de6bSjchu ddi_driver_name(rdip), ddi_get_instance(rdip), (void *)mp);
681f8d2de6bSjchu
6827c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
6837c478bd9Sstevel@tonic-gate }
6847c478bd9Sstevel@tonic-gate
68536fe4a92Segillett if (mp->dmai_flags & PX_DMAI_FLAGS_NOSYNC)
6867c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
6877c478bd9Sstevel@tonic-gate
6887c478bd9Sstevel@tonic-gate /*
6897c478bd9Sstevel@tonic-gate * No flush needed when sending data from memory to device.
6907c478bd9Sstevel@tonic-gate * Nothing to do to "sync" memory to what device would already see.
6917c478bd9Sstevel@tonic-gate */
6927c478bd9Sstevel@tonic-gate if (!(mp->dmai_rflags & DDI_DMA_READ) ||
6937c478bd9Sstevel@tonic-gate ((cache_flags & PX_DMA_SYNC_DDI_FLAGS) == DDI_DMA_SYNC_FORDEV))
6947c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
6957c478bd9Sstevel@tonic-gate
6967c478bd9Sstevel@tonic-gate /*
6977c478bd9Sstevel@tonic-gate * Perform necessary cpu workaround to ensure jbus ordering.
6987c478bd9Sstevel@tonic-gate * CPU's internal "invalidate FIFOs" are flushed.
6997c478bd9Sstevel@tonic-gate */
7007c478bd9Sstevel@tonic-gate
7017c478bd9Sstevel@tonic-gate #if !defined(lint)
7027c478bd9Sstevel@tonic-gate kpreempt_disable();
7037c478bd9Sstevel@tonic-gate #endif
7047c478bd9Sstevel@tonic-gate jbus_stst_order();
7057c478bd9Sstevel@tonic-gate #if !defined(lint)
7067c478bd9Sstevel@tonic-gate kpreempt_enable();
7077c478bd9Sstevel@tonic-gate #endif
7087c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
7097c478bd9Sstevel@tonic-gate }
7107c478bd9Sstevel@tonic-gate
7117c478bd9Sstevel@tonic-gate /*
7127c478bd9Sstevel@tonic-gate * MSIQ Functions:
7137c478bd9Sstevel@tonic-gate */
7147c478bd9Sstevel@tonic-gate /*ARGSUSED*/
7157c478bd9Sstevel@tonic-gate int
px_lib_msiq_init(dev_info_t * dip)7167c478bd9Sstevel@tonic-gate px_lib_msiq_init(dev_info_t *dip)
7177c478bd9Sstevel@tonic-gate {
7187c478bd9Sstevel@tonic-gate px_t *px_p = DIP_TO_STATE(dip);
7197c478bd9Sstevel@tonic-gate pxu_t *pxu_p = (pxu_t *)px_p->px_plat_p;
7207c478bd9Sstevel@tonic-gate px_msiq_state_t *msiq_state_p = &px_p->px_ib_p->ib_msiq_state;
7217c478bd9Sstevel@tonic-gate px_dvma_addr_t pg_index;
722348fdf9eSAlan Adamson, SD OSSD size_t q_sz = msiq_state_p->msiq_rec_cnt * sizeof (msiq_rec_t);
7237c478bd9Sstevel@tonic-gate size_t size;
724348fdf9eSAlan Adamson, SD OSSD int i, ret;
7257c478bd9Sstevel@tonic-gate
7267c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_init: dip 0x%p\n", dip);
7277c478bd9Sstevel@tonic-gate
728348fdf9eSAlan Adamson, SD OSSD /* must aligned on q_sz (happens to be !!! page) boundary */
729348fdf9eSAlan Adamson, SD OSSD ASSERT(q_sz == 8 * 1024);
730348fdf9eSAlan Adamson, SD OSSD
7317c478bd9Sstevel@tonic-gate /*
7327c478bd9Sstevel@tonic-gate * Map the EQ memory into the Fire MMU (has to be 512KB aligned)
7337c478bd9Sstevel@tonic-gate * and then initialize the base address register.
7347c478bd9Sstevel@tonic-gate *
7357c478bd9Sstevel@tonic-gate * Allocate entries from Fire IOMMU so that the resulting address
7367c478bd9Sstevel@tonic-gate * is properly aligned. Calculate the index of the first allocated
7377c478bd9Sstevel@tonic-gate * entry. Note: The size of the mapping is assumed to be a multiple
7387c478bd9Sstevel@tonic-gate * of the page size.
7397c478bd9Sstevel@tonic-gate */
740348fdf9eSAlan Adamson, SD OSSD size = msiq_state_p->msiq_cnt * q_sz;
741348fdf9eSAlan Adamson, SD OSSD
742348fdf9eSAlan Adamson, SD OSSD msiq_state_p->msiq_buf_p = kmem_zalloc(size, KM_SLEEP);
743348fdf9eSAlan Adamson, SD OSSD
744348fdf9eSAlan Adamson, SD OSSD for (i = 0; i < msiq_state_p->msiq_cnt; i++)
745348fdf9eSAlan Adamson, SD OSSD msiq_state_p->msiq_p[i].msiq_base_p = (msiqhead_t *)
746348fdf9eSAlan Adamson, SD OSSD ((caddr_t)msiq_state_p->msiq_buf_p + (i * q_sz));
7477c478bd9Sstevel@tonic-gate
7487c478bd9Sstevel@tonic-gate pxu_p->msiq_mapped_p = vmem_xalloc(px_p->px_mmu_p->mmu_dvma_map,
7497c478bd9Sstevel@tonic-gate size, (512 * 1024), 0, 0, NULL, NULL, VM_NOSLEEP | VM_BESTFIT);
7507c478bd9Sstevel@tonic-gate
7517c478bd9Sstevel@tonic-gate if (pxu_p->msiq_mapped_p == NULL)
7527c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
7537c478bd9Sstevel@tonic-gate
7547c478bd9Sstevel@tonic-gate pg_index = MMU_PAGE_INDEX(px_p->px_mmu_p,
7557c478bd9Sstevel@tonic-gate MMU_BTOP((ulong_t)pxu_p->msiq_mapped_p));
7567c478bd9Sstevel@tonic-gate
7577c478bd9Sstevel@tonic-gate if ((ret = px_lib_iommu_map(px_p->px_dip, PCI_TSBID(0, pg_index),
75895003185Segillett MMU_BTOP(size), PCI_MAP_ATTR_WRITE, msiq_state_p->msiq_buf_p,
75995003185Segillett 0, MMU_MAP_BUF)) != DDI_SUCCESS) {
7607c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip,
76156de8cb5Sanbui "px_lib_msiq_init: px_lib_iommu_map failed, "
76256de8cb5Sanbui "ret 0x%lx\n", ret);
7637c478bd9Sstevel@tonic-gate
7647c478bd9Sstevel@tonic-gate (void) px_lib_msiq_fini(dip);
7657c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
7667c478bd9Sstevel@tonic-gate }
7677c478bd9Sstevel@tonic-gate
768d8d130aeSanbui if ((ret = hvio_msiq_init(DIP_TO_HANDLE(dip),
769d8d130aeSanbui pxu_p)) != H_EOK) {
770d8d130aeSanbui DBG(DBG_LIB_MSIQ, dip,
771d8d130aeSanbui "hvio_msiq_init failed, ret 0x%lx\n", ret);
772d8d130aeSanbui
773d8d130aeSanbui (void) px_lib_msiq_fini(dip);
774d8d130aeSanbui return (DDI_FAILURE);
775d8d130aeSanbui }
7767c478bd9Sstevel@tonic-gate
7777c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
7787c478bd9Sstevel@tonic-gate }
7797c478bd9Sstevel@tonic-gate
7807c478bd9Sstevel@tonic-gate /*ARGSUSED*/
7817c478bd9Sstevel@tonic-gate int
px_lib_msiq_fini(dev_info_t * dip)7827c478bd9Sstevel@tonic-gate px_lib_msiq_fini(dev_info_t *dip)
7837c478bd9Sstevel@tonic-gate {
7847c478bd9Sstevel@tonic-gate px_t *px_p = DIP_TO_STATE(dip);
7857c478bd9Sstevel@tonic-gate pxu_t *pxu_p = (pxu_t *)px_p->px_plat_p;
7867c478bd9Sstevel@tonic-gate px_msiq_state_t *msiq_state_p = &px_p->px_ib_p->ib_msiq_state;
7877c478bd9Sstevel@tonic-gate px_dvma_addr_t pg_index;
7887c478bd9Sstevel@tonic-gate size_t size;
7897c478bd9Sstevel@tonic-gate
7907c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_fini: dip 0x%p\n", dip);
7917c478bd9Sstevel@tonic-gate
7927c478bd9Sstevel@tonic-gate /*
7937c478bd9Sstevel@tonic-gate * Unmap and free the EQ memory that had been mapped
7947c478bd9Sstevel@tonic-gate * into the Fire IOMMU.
7957c478bd9Sstevel@tonic-gate */
7967c478bd9Sstevel@tonic-gate size = msiq_state_p->msiq_cnt *
7977c478bd9Sstevel@tonic-gate msiq_state_p->msiq_rec_cnt * sizeof (msiq_rec_t);
7987c478bd9Sstevel@tonic-gate
7997c478bd9Sstevel@tonic-gate pg_index = MMU_PAGE_INDEX(px_p->px_mmu_p,
8007c478bd9Sstevel@tonic-gate MMU_BTOP((ulong_t)pxu_p->msiq_mapped_p));
8017c478bd9Sstevel@tonic-gate
8027c478bd9Sstevel@tonic-gate (void) px_lib_iommu_demap(px_p->px_dip,
8037c478bd9Sstevel@tonic-gate PCI_TSBID(0, pg_index), MMU_BTOP(size));
8047c478bd9Sstevel@tonic-gate
8057c478bd9Sstevel@tonic-gate /* Free the entries from the Fire MMU */
8067c478bd9Sstevel@tonic-gate vmem_xfree(px_p->px_mmu_p->mmu_dvma_map,
8077c478bd9Sstevel@tonic-gate (void *)pxu_p->msiq_mapped_p, size);
8087c478bd9Sstevel@tonic-gate
809348fdf9eSAlan Adamson, SD OSSD kmem_free(msiq_state_p->msiq_buf_p, msiq_state_p->msiq_cnt *
810348fdf9eSAlan Adamson, SD OSSD msiq_state_p->msiq_rec_cnt * sizeof (msiq_rec_t));
811348fdf9eSAlan Adamson, SD OSSD
8127c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
8137c478bd9Sstevel@tonic-gate }
8147c478bd9Sstevel@tonic-gate
8157c478bd9Sstevel@tonic-gate /*ARGSUSED*/
8167c478bd9Sstevel@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)8177c478bd9Sstevel@tonic-gate px_lib_msiq_info(dev_info_t *dip, msiqid_t msiq_id, r_addr_t *ra_p,
8187c478bd9Sstevel@tonic-gate uint_t *msiq_rec_cnt_p)
8197c478bd9Sstevel@tonic-gate {
8207c478bd9Sstevel@tonic-gate px_t *px_p = DIP_TO_STATE(dip);
8217c478bd9Sstevel@tonic-gate px_msiq_state_t *msiq_state_p = &px_p->px_ib_p->ib_msiq_state;
8227c478bd9Sstevel@tonic-gate size_t msiq_size;
8237c478bd9Sstevel@tonic-gate
8247c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_msiq_info: dip 0x%p msiq_id 0x%x\n",
8257c478bd9Sstevel@tonic-gate dip, msiq_id);
8267c478bd9Sstevel@tonic-gate
8277c478bd9Sstevel@tonic-gate msiq_size = msiq_state_p->msiq_rec_cnt * sizeof (msiq_rec_t);
82895003185Segillett ra_p = (r_addr_t *)((caddr_t)msiq_state_p->msiq_buf_p +
82995003185Segillett (msiq_id * msiq_size));
8307c478bd9Sstevel@tonic-gate
8317c478bd9Sstevel@tonic-gate *msiq_rec_cnt_p = msiq_state_p->msiq_rec_cnt;
8327c478bd9Sstevel@tonic-gate
8337c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_msiq_info: ra_p 0x%p msiq_rec_cnt 0x%x\n",
8347c478bd9Sstevel@tonic-gate ra_p, *msiq_rec_cnt_p);
8357c478bd9Sstevel@tonic-gate
8367c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
8377c478bd9Sstevel@tonic-gate }
8387c478bd9Sstevel@tonic-gate
8397c478bd9Sstevel@tonic-gate /*ARGSUSED*/
8407c478bd9Sstevel@tonic-gate int
px_lib_msiq_getvalid(dev_info_t * dip,msiqid_t msiq_id,pci_msiq_valid_state_t * msiq_valid_state)8417c478bd9Sstevel@tonic-gate px_lib_msiq_getvalid(dev_info_t *dip, msiqid_t msiq_id,
8427c478bd9Sstevel@tonic-gate pci_msiq_valid_state_t *msiq_valid_state)
8437c478bd9Sstevel@tonic-gate {
8447c478bd9Sstevel@tonic-gate uint64_t ret;
8457c478bd9Sstevel@tonic-gate
8467c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_getvalid: dip 0x%p msiq_id 0x%x\n",
8477c478bd9Sstevel@tonic-gate dip, msiq_id);
8487c478bd9Sstevel@tonic-gate
8497c478bd9Sstevel@tonic-gate if ((ret = hvio_msiq_getvalid(DIP_TO_HANDLE(dip),
8507c478bd9Sstevel@tonic-gate msiq_id, msiq_valid_state)) != H_EOK) {
8517c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip,
8527c478bd9Sstevel@tonic-gate "hvio_msiq_getvalid failed, ret 0x%lx\n", ret);
8537c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
8547c478bd9Sstevel@tonic-gate }
8557c478bd9Sstevel@tonic-gate
8567c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_getvalid: msiq_valid_state 0x%x\n",
8577c478bd9Sstevel@tonic-gate *msiq_valid_state);
8587c478bd9Sstevel@tonic-gate
8597c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
8607c478bd9Sstevel@tonic-gate }
8617c478bd9Sstevel@tonic-gate
8627c478bd9Sstevel@tonic-gate /*ARGSUSED*/
8637c478bd9Sstevel@tonic-gate int
px_lib_msiq_setvalid(dev_info_t * dip,msiqid_t msiq_id,pci_msiq_valid_state_t msiq_valid_state)8647c478bd9Sstevel@tonic-gate px_lib_msiq_setvalid(dev_info_t *dip, msiqid_t msiq_id,
8657c478bd9Sstevel@tonic-gate pci_msiq_valid_state_t msiq_valid_state)
8667c478bd9Sstevel@tonic-gate {
8677c478bd9Sstevel@tonic-gate uint64_t ret;
8687c478bd9Sstevel@tonic-gate
8697c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_setvalid: dip 0x%p msiq_id 0x%x "
8707c478bd9Sstevel@tonic-gate "msiq_valid_state 0x%x\n", dip, msiq_id, msiq_valid_state);
8717c478bd9Sstevel@tonic-gate
8727c478bd9Sstevel@tonic-gate if ((ret = hvio_msiq_setvalid(DIP_TO_HANDLE(dip),
8737c478bd9Sstevel@tonic-gate msiq_id, msiq_valid_state)) != H_EOK) {
8747c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip,
8757c478bd9Sstevel@tonic-gate "hvio_msiq_setvalid failed, ret 0x%lx\n", ret);
8767c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
8777c478bd9Sstevel@tonic-gate }
8787c478bd9Sstevel@tonic-gate
8797c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
8807c478bd9Sstevel@tonic-gate }
8817c478bd9Sstevel@tonic-gate
8827c478bd9Sstevel@tonic-gate /*ARGSUSED*/
8837c478bd9Sstevel@tonic-gate int
px_lib_msiq_getstate(dev_info_t * dip,msiqid_t msiq_id,pci_msiq_state_t * msiq_state)8847c478bd9Sstevel@tonic-gate px_lib_msiq_getstate(dev_info_t *dip, msiqid_t msiq_id,
8857c478bd9Sstevel@tonic-gate pci_msiq_state_t *msiq_state)
8867c478bd9Sstevel@tonic-gate {
8877c478bd9Sstevel@tonic-gate uint64_t ret;
8887c478bd9Sstevel@tonic-gate
8897c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_getstate: dip 0x%p msiq_id 0x%x\n",
8907c478bd9Sstevel@tonic-gate dip, msiq_id);
8917c478bd9Sstevel@tonic-gate
8927c478bd9Sstevel@tonic-gate if ((ret = hvio_msiq_getstate(DIP_TO_HANDLE(dip),
8937c478bd9Sstevel@tonic-gate msiq_id, msiq_state)) != H_EOK) {
8947c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip,
8957c478bd9Sstevel@tonic-gate "hvio_msiq_getstate failed, ret 0x%lx\n", ret);
8967c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
8977c478bd9Sstevel@tonic-gate }
8987c478bd9Sstevel@tonic-gate
8997c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_getstate: msiq_state 0x%x\n",
9007c478bd9Sstevel@tonic-gate *msiq_state);
9017c478bd9Sstevel@tonic-gate
9027c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
9037c478bd9Sstevel@tonic-gate }
9047c478bd9Sstevel@tonic-gate
9057c478bd9Sstevel@tonic-gate /*ARGSUSED*/
9067c478bd9Sstevel@tonic-gate int
px_lib_msiq_setstate(dev_info_t * dip,msiqid_t msiq_id,pci_msiq_state_t msiq_state)9077c478bd9Sstevel@tonic-gate px_lib_msiq_setstate(dev_info_t *dip, msiqid_t msiq_id,
9087c478bd9Sstevel@tonic-gate pci_msiq_state_t msiq_state)
9097c478bd9Sstevel@tonic-gate {
9107c478bd9Sstevel@tonic-gate uint64_t ret;
9117c478bd9Sstevel@tonic-gate
9127c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_setstate: dip 0x%p msiq_id 0x%x "
9137c478bd9Sstevel@tonic-gate "msiq_state 0x%x\n", dip, msiq_id, msiq_state);
9147c478bd9Sstevel@tonic-gate
9157c478bd9Sstevel@tonic-gate if ((ret = hvio_msiq_setstate(DIP_TO_HANDLE(dip),
9167c478bd9Sstevel@tonic-gate msiq_id, msiq_state)) != H_EOK) {
9177c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip,
9187c478bd9Sstevel@tonic-gate "hvio_msiq_setstate failed, ret 0x%lx\n", ret);
9197c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
9207c478bd9Sstevel@tonic-gate }
9217c478bd9Sstevel@tonic-gate
9227c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
9237c478bd9Sstevel@tonic-gate }
9247c478bd9Sstevel@tonic-gate
9257c478bd9Sstevel@tonic-gate /*ARGSUSED*/
9267c478bd9Sstevel@tonic-gate int
px_lib_msiq_gethead(dev_info_t * dip,msiqid_t msiq_id,msiqhead_t * msiq_head)9277c478bd9Sstevel@tonic-gate px_lib_msiq_gethead(dev_info_t *dip, msiqid_t msiq_id,
9287c478bd9Sstevel@tonic-gate msiqhead_t *msiq_head)
9297c478bd9Sstevel@tonic-gate {
9307c478bd9Sstevel@tonic-gate uint64_t ret;
9317c478bd9Sstevel@tonic-gate
9327c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_gethead: dip 0x%p msiq_id 0x%x\n",
9337c478bd9Sstevel@tonic-gate dip, msiq_id);
9347c478bd9Sstevel@tonic-gate
9357c478bd9Sstevel@tonic-gate if ((ret = hvio_msiq_gethead(DIP_TO_HANDLE(dip),
9367c478bd9Sstevel@tonic-gate msiq_id, msiq_head)) != H_EOK) {
9377c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip,
9387c478bd9Sstevel@tonic-gate "hvio_msiq_gethead failed, ret 0x%lx\n", ret);
9397c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
9407c478bd9Sstevel@tonic-gate }
9417c478bd9Sstevel@tonic-gate
9427c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_gethead: msiq_head 0x%x\n",
9437c478bd9Sstevel@tonic-gate *msiq_head);
9447c478bd9Sstevel@tonic-gate
9457c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
9467c478bd9Sstevel@tonic-gate }
9477c478bd9Sstevel@tonic-gate
9487c478bd9Sstevel@tonic-gate /*ARGSUSED*/
9497c478bd9Sstevel@tonic-gate int
px_lib_msiq_sethead(dev_info_t * dip,msiqid_t msiq_id,msiqhead_t msiq_head)9507c478bd9Sstevel@tonic-gate px_lib_msiq_sethead(dev_info_t *dip, msiqid_t msiq_id,
9517c478bd9Sstevel@tonic-gate msiqhead_t msiq_head)
9527c478bd9Sstevel@tonic-gate {
9537c478bd9Sstevel@tonic-gate uint64_t ret;
9547c478bd9Sstevel@tonic-gate
9557c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_sethead: dip 0x%p msiq_id 0x%x "
9567c478bd9Sstevel@tonic-gate "msiq_head 0x%x\n", dip, msiq_id, msiq_head);
9577c478bd9Sstevel@tonic-gate
9587c478bd9Sstevel@tonic-gate if ((ret = hvio_msiq_sethead(DIP_TO_HANDLE(dip),
9597c478bd9Sstevel@tonic-gate msiq_id, msiq_head)) != H_EOK) {
9607c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip,
9617c478bd9Sstevel@tonic-gate "hvio_msiq_sethead failed, ret 0x%lx\n", ret);
9627c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
9637c478bd9Sstevel@tonic-gate }
9647c478bd9Sstevel@tonic-gate
9657c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
9667c478bd9Sstevel@tonic-gate }
9677c478bd9Sstevel@tonic-gate
9687c478bd9Sstevel@tonic-gate /*ARGSUSED*/
9697c478bd9Sstevel@tonic-gate int
px_lib_msiq_gettail(dev_info_t * dip,msiqid_t msiq_id,msiqtail_t * msiq_tail)9707c478bd9Sstevel@tonic-gate px_lib_msiq_gettail(dev_info_t *dip, msiqid_t msiq_id,
9717c478bd9Sstevel@tonic-gate msiqtail_t *msiq_tail)
9727c478bd9Sstevel@tonic-gate {
9737c478bd9Sstevel@tonic-gate uint64_t ret;
9747c478bd9Sstevel@tonic-gate
9757c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_gettail: dip 0x%p msiq_id 0x%x\n",
9767c478bd9Sstevel@tonic-gate dip, msiq_id);
9777c478bd9Sstevel@tonic-gate
9787c478bd9Sstevel@tonic-gate if ((ret = hvio_msiq_gettail(DIP_TO_HANDLE(dip),
9797c478bd9Sstevel@tonic-gate msiq_id, msiq_tail)) != H_EOK) {
9807c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip,
9817c478bd9Sstevel@tonic-gate "hvio_msiq_gettail failed, ret 0x%lx\n", ret);
9827c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
9837c478bd9Sstevel@tonic-gate }
9847c478bd9Sstevel@tonic-gate
9857c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_lib_msiq_gettail: msiq_tail 0x%x\n",
9867c478bd9Sstevel@tonic-gate *msiq_tail);
9877c478bd9Sstevel@tonic-gate
9887c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
9897c478bd9Sstevel@tonic-gate }
9907c478bd9Sstevel@tonic-gate
9917c478bd9Sstevel@tonic-gate /*ARGSUSED*/
9927c478bd9Sstevel@tonic-gate void
px_lib_get_msiq_rec(dev_info_t * dip,msiqhead_t * msiq_head_p,msiq_rec_t * msiq_rec_p)993023ccc1eSegillett px_lib_get_msiq_rec(dev_info_t *dip, msiqhead_t *msiq_head_p,
994023ccc1eSegillett msiq_rec_t *msiq_rec_p)
9957c478bd9Sstevel@tonic-gate {
996023ccc1eSegillett eq_rec_t *eq_rec_p = (eq_rec_t *)msiq_head_p;
9977c478bd9Sstevel@tonic-gate
9987c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_lib_get_msiq_rec: dip 0x%p eq_rec_p 0x%p\n",
9997c478bd9Sstevel@tonic-gate dip, eq_rec_p);
10007c478bd9Sstevel@tonic-gate
10013ee8f295Smg140465 if (!eq_rec_p->eq_rec_fmt_type) {
10023ee8f295Smg140465 /* Set msiq_rec_type to zero */
10033ee8f295Smg140465 msiq_rec_p->msiq_rec_type = 0;
10047c478bd9Sstevel@tonic-gate
10057c478bd9Sstevel@tonic-gate return;
10067c478bd9Sstevel@tonic-gate }
10077c478bd9Sstevel@tonic-gate
10087c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_lib_get_msiq_rec: EQ RECORD, "
10097c478bd9Sstevel@tonic-gate "eq_rec_rid 0x%llx eq_rec_fmt_type 0x%llx "
10107c478bd9Sstevel@tonic-gate "eq_rec_len 0x%llx eq_rec_addr0 0x%llx "
10117c478bd9Sstevel@tonic-gate "eq_rec_addr1 0x%llx eq_rec_data0 0x%llx "
10127c478bd9Sstevel@tonic-gate "eq_rec_data1 0x%llx\n", eq_rec_p->eq_rec_rid,
10137c478bd9Sstevel@tonic-gate eq_rec_p->eq_rec_fmt_type, eq_rec_p->eq_rec_len,
10147c478bd9Sstevel@tonic-gate eq_rec_p->eq_rec_addr0, eq_rec_p->eq_rec_addr1,
10157c478bd9Sstevel@tonic-gate eq_rec_p->eq_rec_data0, eq_rec_p->eq_rec_data1);
10167c478bd9Sstevel@tonic-gate
10177c478bd9Sstevel@tonic-gate /*
10187c478bd9Sstevel@tonic-gate * Only upper 4 bits of eq_rec_fmt_type is used
10197c478bd9Sstevel@tonic-gate * to identify the EQ record type.
10207c478bd9Sstevel@tonic-gate */
10217c478bd9Sstevel@tonic-gate switch (eq_rec_p->eq_rec_fmt_type >> 3) {
10227c478bd9Sstevel@tonic-gate case EQ_REC_MSI32:
10237c478bd9Sstevel@tonic-gate msiq_rec_p->msiq_rec_type = MSI32_REC;
10247c478bd9Sstevel@tonic-gate
10257c478bd9Sstevel@tonic-gate msiq_rec_p->msiq_rec_data.msi.msi_data =
10267c478bd9Sstevel@tonic-gate eq_rec_p->eq_rec_data0;
10277c478bd9Sstevel@tonic-gate break;
10287c478bd9Sstevel@tonic-gate case EQ_REC_MSI64:
10297c478bd9Sstevel@tonic-gate msiq_rec_p->msiq_rec_type = MSI64_REC;
10307c478bd9Sstevel@tonic-gate
10317c478bd9Sstevel@tonic-gate msiq_rec_p->msiq_rec_data.msi.msi_data =
10327c478bd9Sstevel@tonic-gate eq_rec_p->eq_rec_data0;
10337c478bd9Sstevel@tonic-gate break;
10347c478bd9Sstevel@tonic-gate case EQ_REC_MSG:
10357c478bd9Sstevel@tonic-gate msiq_rec_p->msiq_rec_type = MSG_REC;
10367c478bd9Sstevel@tonic-gate
10377c478bd9Sstevel@tonic-gate msiq_rec_p->msiq_rec_data.msg.msg_route =
10387c478bd9Sstevel@tonic-gate eq_rec_p->eq_rec_fmt_type & 7;
10397c478bd9Sstevel@tonic-gate msiq_rec_p->msiq_rec_data.msg.msg_targ = eq_rec_p->eq_rec_rid;
10407c478bd9Sstevel@tonic-gate msiq_rec_p->msiq_rec_data.msg.msg_code = eq_rec_p->eq_rec_data0;
10417c478bd9Sstevel@tonic-gate break;
10427c478bd9Sstevel@tonic-gate default:
10437c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "%s%d: px_lib_get_msiq_rec: "
1044b40cec45Skrishnae "0x%x is an unknown EQ record type",
10457c478bd9Sstevel@tonic-gate ddi_driver_name(dip), ddi_get_instance(dip),
1046b40cec45Skrishnae (int)eq_rec_p->eq_rec_fmt_type);
10477c478bd9Sstevel@tonic-gate break;
10487c478bd9Sstevel@tonic-gate }
10497c478bd9Sstevel@tonic-gate
10507c478bd9Sstevel@tonic-gate msiq_rec_p->msiq_rec_rid = eq_rec_p->eq_rec_rid;
10517c478bd9Sstevel@tonic-gate msiq_rec_p->msiq_rec_msi_addr = ((eq_rec_p->eq_rec_addr1 << 16) |
10527c478bd9Sstevel@tonic-gate (eq_rec_p->eq_rec_addr0 << 2));
1053b0fc0e77Sgovinda }
10547c478bd9Sstevel@tonic-gate
1055b0fc0e77Sgovinda /*ARGSUSED*/
1056b0fc0e77Sgovinda void
px_lib_clr_msiq_rec(dev_info_t * dip,msiqhead_t * msiq_head_p)1057b0fc0e77Sgovinda px_lib_clr_msiq_rec(dev_info_t *dip, msiqhead_t *msiq_head_p)
1058b0fc0e77Sgovinda {
1059b0fc0e77Sgovinda eq_rec_t *eq_rec_p = (eq_rec_t *)msiq_head_p;
1060b0fc0e77Sgovinda
1061b0fc0e77Sgovinda DBG(DBG_LIB_MSIQ, dip, "px_lib_clr_msiq_rec: dip 0x%p eq_rec_p 0x%p\n",
1062b0fc0e77Sgovinda dip, eq_rec_p);
1063b0fc0e77Sgovinda
1064b0fc0e77Sgovinda if (eq_rec_p->eq_rec_fmt_type) {
10653ee8f295Smg140465 /* Zero out eq_rec_fmt_type field */
10663ee8f295Smg140465 eq_rec_p->eq_rec_fmt_type = 0;
10677c478bd9Sstevel@tonic-gate }
1068b0fc0e77Sgovinda }
10697c478bd9Sstevel@tonic-gate
10707c478bd9Sstevel@tonic-gate /*
10717c478bd9Sstevel@tonic-gate * MSI Functions:
10727c478bd9Sstevel@tonic-gate */
10737c478bd9Sstevel@tonic-gate /*ARGSUSED*/
10747c478bd9Sstevel@tonic-gate int
px_lib_msi_init(dev_info_t * dip)10757c478bd9Sstevel@tonic-gate px_lib_msi_init(dev_info_t *dip)
10767c478bd9Sstevel@tonic-gate {
10777c478bd9Sstevel@tonic-gate px_t *px_p = DIP_TO_STATE(dip);
10787c478bd9Sstevel@tonic-gate px_msi_state_t *msi_state_p = &px_p->px_ib_p->ib_msi_state;
10797c478bd9Sstevel@tonic-gate uint64_t ret;
10807c478bd9Sstevel@tonic-gate
10817c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip, "px_lib_msi_init: dip 0x%p\n", dip);
10827c478bd9Sstevel@tonic-gate
10837c478bd9Sstevel@tonic-gate if ((ret = hvio_msi_init(DIP_TO_HANDLE(dip),
10847c478bd9Sstevel@tonic-gate msi_state_p->msi_addr32, msi_state_p->msi_addr64)) != H_EOK) {
10857c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSIQ, dip, "px_lib_msi_init failed, ret 0x%lx\n",
10867c478bd9Sstevel@tonic-gate ret);
10877c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
10887c478bd9Sstevel@tonic-gate }
10897c478bd9Sstevel@tonic-gate
10907c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
10917c478bd9Sstevel@tonic-gate }
10927c478bd9Sstevel@tonic-gate
10937c478bd9Sstevel@tonic-gate /*ARGSUSED*/
10947c478bd9Sstevel@tonic-gate int
px_lib_msi_getmsiq(dev_info_t * dip,msinum_t msi_num,msiqid_t * msiq_id)10957c478bd9Sstevel@tonic-gate px_lib_msi_getmsiq(dev_info_t *dip, msinum_t msi_num,
10967c478bd9Sstevel@tonic-gate msiqid_t *msiq_id)
10977c478bd9Sstevel@tonic-gate {
10987c478bd9Sstevel@tonic-gate uint64_t ret;
10997c478bd9Sstevel@tonic-gate
11007c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip, "px_lib_msi_getmsiq: dip 0x%p msi_num 0x%x\n",
11017c478bd9Sstevel@tonic-gate dip, msi_num);
11027c478bd9Sstevel@tonic-gate
11037c478bd9Sstevel@tonic-gate if ((ret = hvio_msi_getmsiq(DIP_TO_HANDLE(dip),
11047c478bd9Sstevel@tonic-gate msi_num, msiq_id)) != H_EOK) {
11057c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip,
11067c478bd9Sstevel@tonic-gate "hvio_msi_getmsiq failed, ret 0x%lx\n", ret);
11077c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
11087c478bd9Sstevel@tonic-gate }
11097c478bd9Sstevel@tonic-gate
11107c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip, "px_lib_msi_getmsiq: msiq_id 0x%x\n",
11117c478bd9Sstevel@tonic-gate *msiq_id);
11127c478bd9Sstevel@tonic-gate
11137c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
11147c478bd9Sstevel@tonic-gate }
11157c478bd9Sstevel@tonic-gate
11167c478bd9Sstevel@tonic-gate /*ARGSUSED*/
11177c478bd9Sstevel@tonic-gate int
px_lib_msi_setmsiq(dev_info_t * dip,msinum_t msi_num,msiqid_t msiq_id,msi_type_t msitype)11187c478bd9Sstevel@tonic-gate px_lib_msi_setmsiq(dev_info_t *dip, msinum_t msi_num,
11197c478bd9Sstevel@tonic-gate msiqid_t msiq_id, msi_type_t msitype)
11207c478bd9Sstevel@tonic-gate {
11217c478bd9Sstevel@tonic-gate uint64_t ret;
11227c478bd9Sstevel@tonic-gate
11237c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip, "px_lib_msi_setmsiq: dip 0x%p msi_num 0x%x "
11247c478bd9Sstevel@tonic-gate "msq_id 0x%x\n", dip, msi_num, msiq_id);
11257c478bd9Sstevel@tonic-gate
11267c478bd9Sstevel@tonic-gate if ((ret = hvio_msi_setmsiq(DIP_TO_HANDLE(dip),
11277c478bd9Sstevel@tonic-gate msi_num, msiq_id)) != H_EOK) {
11287c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip,
11297c478bd9Sstevel@tonic-gate "hvio_msi_setmsiq failed, ret 0x%lx\n", ret);
11307c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
11317c478bd9Sstevel@tonic-gate }
11327c478bd9Sstevel@tonic-gate
11337c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
11347c478bd9Sstevel@tonic-gate }
11357c478bd9Sstevel@tonic-gate
11367c478bd9Sstevel@tonic-gate /*ARGSUSED*/
11377c478bd9Sstevel@tonic-gate int
px_lib_msi_getvalid(dev_info_t * dip,msinum_t msi_num,pci_msi_valid_state_t * msi_valid_state)11387c478bd9Sstevel@tonic-gate px_lib_msi_getvalid(dev_info_t *dip, msinum_t msi_num,
11397c478bd9Sstevel@tonic-gate pci_msi_valid_state_t *msi_valid_state)
11407c478bd9Sstevel@tonic-gate {
11417c478bd9Sstevel@tonic-gate uint64_t ret;
11427c478bd9Sstevel@tonic-gate
11437c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip, "px_lib_msi_getvalid: dip 0x%p msi_num 0x%x\n",
11447c478bd9Sstevel@tonic-gate dip, msi_num);
11457c478bd9Sstevel@tonic-gate
11467c478bd9Sstevel@tonic-gate if ((ret = hvio_msi_getvalid(DIP_TO_HANDLE(dip),
11477c478bd9Sstevel@tonic-gate msi_num, msi_valid_state)) != H_EOK) {
11487c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip,
11497c478bd9Sstevel@tonic-gate "hvio_msi_getvalid failed, ret 0x%lx\n", ret);
11507c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
11517c478bd9Sstevel@tonic-gate }
11527c478bd9Sstevel@tonic-gate
11537c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip, "px_lib_msi_getvalid: msiq_id 0x%x\n",
11547c478bd9Sstevel@tonic-gate *msi_valid_state);
11557c478bd9Sstevel@tonic-gate
11567c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
11577c478bd9Sstevel@tonic-gate }
11587c478bd9Sstevel@tonic-gate
11597c478bd9Sstevel@tonic-gate /*ARGSUSED*/
11607c478bd9Sstevel@tonic-gate int
px_lib_msi_setvalid(dev_info_t * dip,msinum_t msi_num,pci_msi_valid_state_t msi_valid_state)11617c478bd9Sstevel@tonic-gate px_lib_msi_setvalid(dev_info_t *dip, msinum_t msi_num,
11627c478bd9Sstevel@tonic-gate pci_msi_valid_state_t msi_valid_state)
11637c478bd9Sstevel@tonic-gate {
11647c478bd9Sstevel@tonic-gate uint64_t ret;
11657c478bd9Sstevel@tonic-gate
11667c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip, "px_lib_msi_setvalid: dip 0x%p msi_num 0x%x "
11677c478bd9Sstevel@tonic-gate "msi_valid_state 0x%x\n", dip, msi_num, msi_valid_state);
11687c478bd9Sstevel@tonic-gate
11697c478bd9Sstevel@tonic-gate if ((ret = hvio_msi_setvalid(DIP_TO_HANDLE(dip),
11707c478bd9Sstevel@tonic-gate msi_num, msi_valid_state)) != H_EOK) {
11717c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip,
11727c478bd9Sstevel@tonic-gate "hvio_msi_setvalid failed, ret 0x%lx\n", ret);
11737c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
11747c478bd9Sstevel@tonic-gate }
11757c478bd9Sstevel@tonic-gate
11767c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
11777c478bd9Sstevel@tonic-gate }
11787c478bd9Sstevel@tonic-gate
11797c478bd9Sstevel@tonic-gate /*ARGSUSED*/
11807c478bd9Sstevel@tonic-gate int
px_lib_msi_getstate(dev_info_t * dip,msinum_t msi_num,pci_msi_state_t * msi_state)11817c478bd9Sstevel@tonic-gate px_lib_msi_getstate(dev_info_t *dip, msinum_t msi_num,
11827c478bd9Sstevel@tonic-gate pci_msi_state_t *msi_state)
11837c478bd9Sstevel@tonic-gate {
11847c478bd9Sstevel@tonic-gate uint64_t ret;
11857c478bd9Sstevel@tonic-gate
11867c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip, "px_lib_msi_getstate: dip 0x%p msi_num 0x%x\n",
11877c478bd9Sstevel@tonic-gate dip, msi_num);
11887c478bd9Sstevel@tonic-gate
11897c478bd9Sstevel@tonic-gate if ((ret = hvio_msi_getstate(DIP_TO_HANDLE(dip),
11907c478bd9Sstevel@tonic-gate msi_num, msi_state)) != H_EOK) {
11917c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip,
11927c478bd9Sstevel@tonic-gate "hvio_msi_getstate failed, ret 0x%lx\n", ret);
11937c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
11947c478bd9Sstevel@tonic-gate }
11957c478bd9Sstevel@tonic-gate
11967c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip, "px_lib_msi_getstate: msi_state 0x%x\n",
11977c478bd9Sstevel@tonic-gate *msi_state);
11987c478bd9Sstevel@tonic-gate
11997c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
12007c478bd9Sstevel@tonic-gate }
12017c478bd9Sstevel@tonic-gate
12027c478bd9Sstevel@tonic-gate /*ARGSUSED*/
12037c478bd9Sstevel@tonic-gate int
px_lib_msi_setstate(dev_info_t * dip,msinum_t msi_num,pci_msi_state_t msi_state)12047c478bd9Sstevel@tonic-gate px_lib_msi_setstate(dev_info_t *dip, msinum_t msi_num,
12057c478bd9Sstevel@tonic-gate pci_msi_state_t msi_state)
12067c478bd9Sstevel@tonic-gate {
12077c478bd9Sstevel@tonic-gate uint64_t ret;
12087c478bd9Sstevel@tonic-gate
12097c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip, "px_lib_msi_setstate: dip 0x%p msi_num 0x%x "
12107c478bd9Sstevel@tonic-gate "msi_state 0x%x\n", dip, msi_num, msi_state);
12117c478bd9Sstevel@tonic-gate
12127c478bd9Sstevel@tonic-gate if ((ret = hvio_msi_setstate(DIP_TO_HANDLE(dip),
12137c478bd9Sstevel@tonic-gate msi_num, msi_state)) != H_EOK) {
12147c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip,
12157c478bd9Sstevel@tonic-gate "hvio_msi_setstate failed, ret 0x%lx\n", ret);
12167c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
12177c478bd9Sstevel@tonic-gate }
12187c478bd9Sstevel@tonic-gate
12197c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
12207c478bd9Sstevel@tonic-gate }
12217c478bd9Sstevel@tonic-gate
12227c478bd9Sstevel@tonic-gate /*
12237c478bd9Sstevel@tonic-gate * MSG Functions:
12247c478bd9Sstevel@tonic-gate */
12257c478bd9Sstevel@tonic-gate /*ARGSUSED*/
12267c478bd9Sstevel@tonic-gate int
px_lib_msg_getmsiq(dev_info_t * dip,pcie_msg_type_t msg_type,msiqid_t * msiq_id)12277c478bd9Sstevel@tonic-gate px_lib_msg_getmsiq(dev_info_t *dip, pcie_msg_type_t msg_type,
12287c478bd9Sstevel@tonic-gate msiqid_t *msiq_id)
12297c478bd9Sstevel@tonic-gate {
12307c478bd9Sstevel@tonic-gate uint64_t ret;
12317c478bd9Sstevel@tonic-gate
12327c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSG, dip, "px_lib_msg_getmsiq: dip 0x%p msg_type 0x%x\n",
12337c478bd9Sstevel@tonic-gate dip, msg_type);
12347c478bd9Sstevel@tonic-gate
12357c478bd9Sstevel@tonic-gate if ((ret = hvio_msg_getmsiq(DIP_TO_HANDLE(dip),
12367c478bd9Sstevel@tonic-gate msg_type, msiq_id)) != H_EOK) {
12377c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSG, dip,
12387c478bd9Sstevel@tonic-gate "hvio_msg_getmsiq failed, ret 0x%lx\n", ret);
12397c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
12407c478bd9Sstevel@tonic-gate }
12417c478bd9Sstevel@tonic-gate
12427c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip, "px_lib_msg_getmsiq: msiq_id 0x%x\n",
12437c478bd9Sstevel@tonic-gate *msiq_id);
12447c478bd9Sstevel@tonic-gate
12457c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
12467c478bd9Sstevel@tonic-gate }
12477c478bd9Sstevel@tonic-gate
12487c478bd9Sstevel@tonic-gate /*ARGSUSED*/
12497c478bd9Sstevel@tonic-gate int
px_lib_msg_setmsiq(dev_info_t * dip,pcie_msg_type_t msg_type,msiqid_t msiq_id)12507c478bd9Sstevel@tonic-gate px_lib_msg_setmsiq(dev_info_t *dip, pcie_msg_type_t msg_type,
12517c478bd9Sstevel@tonic-gate msiqid_t msiq_id)
12527c478bd9Sstevel@tonic-gate {
12537c478bd9Sstevel@tonic-gate uint64_t ret;
12547c478bd9Sstevel@tonic-gate
12557c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSG, dip, "px_lib_msi_setstate: dip 0x%p msg_type 0x%x "
12567c478bd9Sstevel@tonic-gate "msiq_id 0x%x\n", dip, msg_type, msiq_id);
12577c478bd9Sstevel@tonic-gate
12587c478bd9Sstevel@tonic-gate if ((ret = hvio_msg_setmsiq(DIP_TO_HANDLE(dip),
12597c478bd9Sstevel@tonic-gate msg_type, msiq_id)) != H_EOK) {
12607c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSG, dip,
12617c478bd9Sstevel@tonic-gate "hvio_msg_setmsiq failed, ret 0x%lx\n", ret);
12627c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
12637c478bd9Sstevel@tonic-gate }
12647c478bd9Sstevel@tonic-gate
12657c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
12667c478bd9Sstevel@tonic-gate }
12677c478bd9Sstevel@tonic-gate
12687c478bd9Sstevel@tonic-gate /*ARGSUSED*/
12697c478bd9Sstevel@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)12707c478bd9Sstevel@tonic-gate px_lib_msg_getvalid(dev_info_t *dip, pcie_msg_type_t msg_type,
12717c478bd9Sstevel@tonic-gate pcie_msg_valid_state_t *msg_valid_state)
12727c478bd9Sstevel@tonic-gate {
12737c478bd9Sstevel@tonic-gate uint64_t ret;
12747c478bd9Sstevel@tonic-gate
12757c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSG, dip, "px_lib_msg_getvalid: dip 0x%p msg_type 0x%x\n",
12767c478bd9Sstevel@tonic-gate dip, msg_type);
12777c478bd9Sstevel@tonic-gate
12787c478bd9Sstevel@tonic-gate if ((ret = hvio_msg_getvalid(DIP_TO_HANDLE(dip), msg_type,
12797c478bd9Sstevel@tonic-gate msg_valid_state)) != H_EOK) {
12807c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSG, dip,
12817c478bd9Sstevel@tonic-gate "hvio_msg_getvalid failed, ret 0x%lx\n", ret);
12827c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
12837c478bd9Sstevel@tonic-gate }
12847c478bd9Sstevel@tonic-gate
12857c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSI, dip, "px_lib_msg_getvalid: msg_valid_state 0x%x\n",
12867c478bd9Sstevel@tonic-gate *msg_valid_state);
12877c478bd9Sstevel@tonic-gate
12887c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
12897c478bd9Sstevel@tonic-gate }
12907c478bd9Sstevel@tonic-gate
12917c478bd9Sstevel@tonic-gate /*ARGSUSED*/
12927c478bd9Sstevel@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)12937c478bd9Sstevel@tonic-gate px_lib_msg_setvalid(dev_info_t *dip, pcie_msg_type_t msg_type,
12947c478bd9Sstevel@tonic-gate pcie_msg_valid_state_t msg_valid_state)
12957c478bd9Sstevel@tonic-gate {
12967c478bd9Sstevel@tonic-gate uint64_t ret;
12977c478bd9Sstevel@tonic-gate
12987c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSG, dip, "px_lib_msg_setvalid: dip 0x%p msg_type 0x%x "
12997c478bd9Sstevel@tonic-gate "msg_valid_state 0x%x\n", dip, msg_type, msg_valid_state);
13007c478bd9Sstevel@tonic-gate
13017c478bd9Sstevel@tonic-gate if ((ret = hvio_msg_setvalid(DIP_TO_HANDLE(dip), msg_type,
13027c478bd9Sstevel@tonic-gate msg_valid_state)) != H_EOK) {
13037c478bd9Sstevel@tonic-gate DBG(DBG_LIB_MSG, dip,
13047c478bd9Sstevel@tonic-gate "hvio_msg_setvalid failed, ret 0x%lx\n", ret);
13057c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
13067c478bd9Sstevel@tonic-gate }
13077c478bd9Sstevel@tonic-gate
13087c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
13097c478bd9Sstevel@tonic-gate }
13107c478bd9Sstevel@tonic-gate
1311fc256490SJason Beloro /*ARGSUSED*/
1312fc256490SJason Beloro void
px_panic_domain(px_t * px_p,pcie_req_id_t bdf)1313fc256490SJason Beloro px_panic_domain(px_t *px_p, pcie_req_id_t bdf)
1314fc256490SJason Beloro {
1315fc256490SJason Beloro }
1316fc256490SJason Beloro
13177c478bd9Sstevel@tonic-gate /*
13187c478bd9Sstevel@tonic-gate * Suspend/Resume Functions:
13197c478bd9Sstevel@tonic-gate * Currently unsupported by hypervisor
13207c478bd9Sstevel@tonic-gate */
13217c478bd9Sstevel@tonic-gate int
px_lib_suspend(dev_info_t * dip)13227c478bd9Sstevel@tonic-gate px_lib_suspend(dev_info_t *dip)
13237c478bd9Sstevel@tonic-gate {
13247c478bd9Sstevel@tonic-gate px_t *px_p = DIP_TO_STATE(dip);
13257c478bd9Sstevel@tonic-gate pxu_t *pxu_p = (pxu_t *)px_p->px_plat_p;
132601689544Sjchu px_cb_t *cb_p = PX2CB(px_p);
13277c478bd9Sstevel@tonic-gate devhandle_t dev_hdl, xbus_dev_hdl;
132801689544Sjchu uint64_t ret = H_EOK;
13297c478bd9Sstevel@tonic-gate
13307c478bd9Sstevel@tonic-gate DBG(DBG_DETACH, dip, "px_lib_suspend: dip 0x%p\n", dip);
13317c478bd9Sstevel@tonic-gate
1332f8d2de6bSjchu dev_hdl = (devhandle_t)pxu_p->px_address[PX_REG_CSR];
1333f8d2de6bSjchu xbus_dev_hdl = (devhandle_t)pxu_p->px_address[PX_REG_XBC];
13347c478bd9Sstevel@tonic-gate
133501689544Sjchu if ((ret = hvio_suspend(dev_hdl, pxu_p)) != H_EOK)
133601689544Sjchu goto fail;
133701689544Sjchu
133801689544Sjchu if (--cb_p->attachcnt == 0) {
133901689544Sjchu ret = hvio_cb_suspend(xbus_dev_hdl, pxu_p);
134001689544Sjchu if (ret != H_EOK)
134101689544Sjchu cb_p->attachcnt++;
13427c478bd9Sstevel@tonic-gate }
1343bf8fc234Set142600 pxu_p->cpr_flag = PX_ENTERED_CPR;
13447c478bd9Sstevel@tonic-gate
134501689544Sjchu fail:
13467c478bd9Sstevel@tonic-gate return ((ret != H_EOK) ? DDI_FAILURE: DDI_SUCCESS);
13477c478bd9Sstevel@tonic-gate }
13487c478bd9Sstevel@tonic-gate
13497c478bd9Sstevel@tonic-gate void
px_lib_resume(dev_info_t * dip)13507c478bd9Sstevel@tonic-gate px_lib_resume(dev_info_t *dip)
13517c478bd9Sstevel@tonic-gate {
13527c478bd9Sstevel@tonic-gate px_t *px_p = DIP_TO_STATE(dip);
13537c478bd9Sstevel@tonic-gate pxu_t *pxu_p = (pxu_t *)px_p->px_plat_p;
135401689544Sjchu px_cb_t *cb_p = PX2CB(px_p);
13557c478bd9Sstevel@tonic-gate devhandle_t dev_hdl, xbus_dev_hdl;
13567c478bd9Sstevel@tonic-gate devino_t pec_ino = px_p->px_inos[PX_INTR_PEC];
13577c478bd9Sstevel@tonic-gate devino_t xbc_ino = px_p->px_inos[PX_INTR_XBC];
13587c478bd9Sstevel@tonic-gate
13597c478bd9Sstevel@tonic-gate DBG(DBG_ATTACH, dip, "px_lib_resume: dip 0x%p\n", dip);
13607c478bd9Sstevel@tonic-gate
1361f8d2de6bSjchu dev_hdl = (devhandle_t)pxu_p->px_address[PX_REG_CSR];
1362f8d2de6bSjchu xbus_dev_hdl = (devhandle_t)pxu_p->px_address[PX_REG_XBC];
13637c478bd9Sstevel@tonic-gate
136401689544Sjchu if (++cb_p->attachcnt == 1)
13657c478bd9Sstevel@tonic-gate hvio_cb_resume(dev_hdl, xbus_dev_hdl, xbc_ino, pxu_p);
136601689544Sjchu
13677c478bd9Sstevel@tonic-gate hvio_resume(dev_hdl, pec_ino, pxu_p);
13687c478bd9Sstevel@tonic-gate }
13697c478bd9Sstevel@tonic-gate
137025cf1a30Sjl139090 /*
137125cf1a30Sjl139090 * Generate a unique Oberon UBC ID based on the Logicial System Board and
137225cf1a30Sjl139090 * the IO Channel from the portid property field.
137325cf1a30Sjl139090 */
137425cf1a30Sjl139090 static uint64_t
oberon_get_ubc_id(dev_info_t * dip)137525cf1a30Sjl139090 oberon_get_ubc_id(dev_info_t *dip)
137625cf1a30Sjl139090 {
137725cf1a30Sjl139090 px_t *px_p = DIP_TO_STATE(dip);
137825cf1a30Sjl139090 pxu_t *pxu_p = (pxu_t *)px_p->px_plat_p;
137925cf1a30Sjl139090 uint64_t ubc_id;
138025cf1a30Sjl139090
138125cf1a30Sjl139090 /*
138225cf1a30Sjl139090 * Generate a unique 6 bit UBC ID using the 2 IO_Channel#[1:0] bits and
138325cf1a30Sjl139090 * the 4 LSB_ID[3:0] bits from the Oberon's portid property.
138425cf1a30Sjl139090 */
138525cf1a30Sjl139090 ubc_id = (((pxu_p->portid >> OBERON_PORT_ID_IOC) &
138625cf1a30Sjl139090 OBERON_PORT_ID_IOC_MASK) | (((pxu_p->portid >>
138725cf1a30Sjl139090 OBERON_PORT_ID_LSB) & OBERON_PORT_ID_LSB_MASK)
138825cf1a30Sjl139090 << OBERON_UBC_ID_LSB));
138925cf1a30Sjl139090
139025cf1a30Sjl139090 return (ubc_id);
139125cf1a30Sjl139090 }
139225cf1a30Sjl139090
139325cf1a30Sjl139090 /*
139425cf1a30Sjl139090 * Oberon does not have a UBC scratch register, so alloc an array of scratch
139525cf1a30Sjl139090 * registers when needed and use a unique UBC ID as an index. This code
139625cf1a30Sjl139090 * can be simplified if we use a pre-allocated array. They are currently
139725cf1a30Sjl139090 * being dynamically allocated because it's only needed by the Oberon.
139825cf1a30Sjl139090 */
139925cf1a30Sjl139090 static void
oberon_set_cb(dev_info_t * dip,uint64_t val)140025cf1a30Sjl139090 oberon_set_cb(dev_info_t *dip, uint64_t val)
140125cf1a30Sjl139090 {
140225cf1a30Sjl139090 uint64_t ubc_id;
140325cf1a30Sjl139090
140425cf1a30Sjl139090 if (px_oberon_ubc_scratch_regs == NULL)
140525cf1a30Sjl139090 px_oberon_ubc_scratch_regs =
140625cf1a30Sjl139090 (uint64_t *)kmem_zalloc(sizeof (uint64_t)*
140725cf1a30Sjl139090 OBERON_UBC_ID_MAX, KM_SLEEP);
140825cf1a30Sjl139090
140925cf1a30Sjl139090 ubc_id = oberon_get_ubc_id(dip);
141025cf1a30Sjl139090
141125cf1a30Sjl139090 px_oberon_ubc_scratch_regs[ubc_id] = val;
141225cf1a30Sjl139090
141325cf1a30Sjl139090 /*
141425cf1a30Sjl139090 * Check if any scratch registers are still in use. If all scratch
141525cf1a30Sjl139090 * registers are currently set to zero, then deallocate the scratch
141625cf1a30Sjl139090 * register array.
141725cf1a30Sjl139090 */
141825cf1a30Sjl139090 for (ubc_id = 0; ubc_id < OBERON_UBC_ID_MAX; ubc_id++) {
141925cf1a30Sjl139090 if (px_oberon_ubc_scratch_regs[ubc_id] != NULL)
142025cf1a30Sjl139090 return;
142125cf1a30Sjl139090 }
142225cf1a30Sjl139090
142325cf1a30Sjl139090 /*
142425cf1a30Sjl139090 * All scratch registers are set to zero so deallocate the scratch
142525cf1a30Sjl139090 * register array and set the pointer to NULL.
142625cf1a30Sjl139090 */
142725cf1a30Sjl139090 kmem_free(px_oberon_ubc_scratch_regs,
142825cf1a30Sjl139090 (sizeof (uint64_t)*OBERON_UBC_ID_MAX));
142925cf1a30Sjl139090
143025cf1a30Sjl139090 px_oberon_ubc_scratch_regs = NULL;
143125cf1a30Sjl139090 }
143225cf1a30Sjl139090
143325cf1a30Sjl139090 /*
143425cf1a30Sjl139090 * Oberon does not have a UBC scratch register, so use an allocated array of
143525cf1a30Sjl139090 * scratch registers and use the unique UBC ID as an index into that array.
143625cf1a30Sjl139090 */
143725cf1a30Sjl139090 static uint64_t
oberon_get_cb(dev_info_t * dip)143825cf1a30Sjl139090 oberon_get_cb(dev_info_t *dip)
143925cf1a30Sjl139090 {
144025cf1a30Sjl139090 uint64_t ubc_id;
144125cf1a30Sjl139090
144225cf1a30Sjl139090 if (px_oberon_ubc_scratch_regs == NULL)
144325cf1a30Sjl139090 return (0);
144425cf1a30Sjl139090
144525cf1a30Sjl139090 ubc_id = oberon_get_ubc_id(dip);
144625cf1a30Sjl139090
144725cf1a30Sjl139090 return (px_oberon_ubc_scratch_regs[ubc_id]);
144825cf1a30Sjl139090 }
144925cf1a30Sjl139090
145025cf1a30Sjl139090 /*
145125cf1a30Sjl139090 * Misc Functions:
145225cf1a30Sjl139090 * Currently unsupported by hypervisor
145325cf1a30Sjl139090 */
145425cf1a30Sjl139090 static uint64_t
px_get_cb(dev_info_t * dip)145525cf1a30Sjl139090 px_get_cb(dev_info_t *dip)
145625cf1a30Sjl139090 {
145725cf1a30Sjl139090 px_t *px_p = DIP_TO_STATE(dip);
145825cf1a30Sjl139090 pxu_t *pxu_p = (pxu_t *)px_p->px_plat_p;
145925cf1a30Sjl139090
146025cf1a30Sjl139090 /*
146125cf1a30Sjl139090 * Oberon does not currently have Scratchpad registers.
146225cf1a30Sjl139090 */
146325cf1a30Sjl139090 if (PX_CHIP_TYPE(pxu_p) == PX_CHIP_OBERON)
146425cf1a30Sjl139090 return (oberon_get_cb(dip));
146525cf1a30Sjl139090
146625cf1a30Sjl139090 return (CSR_XR((caddr_t)pxu_p->px_address[PX_REG_XBC], JBUS_SCRATCH_1));
146725cf1a30Sjl139090 }
146825cf1a30Sjl139090
146925cf1a30Sjl139090 static void
px_set_cb(dev_info_t * dip,uint64_t val)147025cf1a30Sjl139090 px_set_cb(dev_info_t *dip, uint64_t val)
147125cf1a30Sjl139090 {
147225cf1a30Sjl139090 px_t *px_p = DIP_TO_STATE(dip);
147325cf1a30Sjl139090 pxu_t *pxu_p = (pxu_t *)px_p->px_plat_p;
147425cf1a30Sjl139090
147525cf1a30Sjl139090 /*
147625cf1a30Sjl139090 * Oberon does not currently have Scratchpad registers.
147725cf1a30Sjl139090 */
147825cf1a30Sjl139090 if (PX_CHIP_TYPE(pxu_p) == PX_CHIP_OBERON) {
147925cf1a30Sjl139090 oberon_set_cb(dip, val);
148025cf1a30Sjl139090 return;
148125cf1a30Sjl139090 }
148225cf1a30Sjl139090
148325cf1a30Sjl139090 CSR_XS((caddr_t)pxu_p->px_address[PX_REG_XBC], JBUS_SCRATCH_1, val);
148425cf1a30Sjl139090 }
148525cf1a30Sjl139090
14867c478bd9Sstevel@tonic-gate /*ARGSUSED*/
14877c478bd9Sstevel@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)14887c478bd9Sstevel@tonic-gate px_lib_map_vconfig(dev_info_t *dip,
14897c478bd9Sstevel@tonic-gate ddi_map_req_t *mp, pci_config_offset_t off,
14907c478bd9Sstevel@tonic-gate pci_regspec_t *rp, caddr_t *addrp)
14917c478bd9Sstevel@tonic-gate {
14927c478bd9Sstevel@tonic-gate /*
14937c478bd9Sstevel@tonic-gate * No special config space access services in this layer.
14947c478bd9Sstevel@tonic-gate */
14957c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
14967c478bd9Sstevel@tonic-gate }
14977c478bd9Sstevel@tonic-gate
149869cd775fSschwartz void
px_lib_map_attr_check(ddi_map_req_t * mp)14994fbb58f6Sjchu px_lib_map_attr_check(ddi_map_req_t *mp)
15004fbb58f6Sjchu {
15014fbb58f6Sjchu ddi_acc_hdl_t *hp = mp->map_handlep;
15024fbb58f6Sjchu
15034fbb58f6Sjchu /* fire does not accept byte masks from PIO store merge */
15044fbb58f6Sjchu if (hp->ah_acc.devacc_attr_dataorder == DDI_STORECACHING_OK_ACC)
15054fbb58f6Sjchu hp->ah_acc.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
15064fbb58f6Sjchu }
15074fbb58f6Sjchu
1508bf8fc234Set142600 /* This function is called only by poke, caut put and pxtool poke. */
15094fbb58f6Sjchu void
px_lib_clr_errs(px_t * px_p,dev_info_t * rdip,uint64_t addr)1510bf8fc234Set142600 px_lib_clr_errs(px_t *px_p, dev_info_t *rdip, uint64_t addr)
1511f8d2de6bSjchu {
151269cd775fSschwartz px_pec_t *pec_p = px_p->px_pec_p;
1513f8d2de6bSjchu dev_info_t *rpdip = px_p->px_dip;
1514bf8fc234Set142600 int rc_err, fab_err, i;
1515f8d2de6bSjchu int acctype = pec_p->pec_safeacc_type;
1516f8d2de6bSjchu ddi_fm_error_t derr;
151726947304SEvan Yan pci_ranges_t *ranges_p;
1518bf8fc234Set142600 int range_len;
1519bf8fc234Set142600 uint32_t addr_high, addr_low;
1520c85864d8SKrishna Elango pcie_req_id_t bdf = PCIE_INVALID_BDF;
1521f8d2de6bSjchu
1522f8d2de6bSjchu /* Create the derr */
1523f8d2de6bSjchu bzero(&derr, sizeof (ddi_fm_error_t));
1524f8d2de6bSjchu derr.fme_version = DDI_FME_VERSION;
1525f8d2de6bSjchu derr.fme_ena = fm_ena_generate(0, FM_ENA_FMT1);
1526f8d2de6bSjchu derr.fme_flag = acctype;
1527f8d2de6bSjchu
1528f8d2de6bSjchu if (acctype == DDI_FM_ERR_EXPECTED) {
1529f8d2de6bSjchu derr.fme_status = DDI_FM_NONFATAL;
1530f8d2de6bSjchu ndi_fm_acc_err_set(pec_p->pec_acc_hdl, &derr);
1531f8d2de6bSjchu }
1532f8d2de6bSjchu
1533eae2e508Skrishnae if (px_fm_enter(px_p) != DDI_SUCCESS)
1534eae2e508Skrishnae return;
1535f8d2de6bSjchu
1536f8d2de6bSjchu /* send ereport/handle/clear fire registers */
1537bf8fc234Set142600 rc_err = px_err_cmn_intr(px_p, &derr, PX_LIB_CALL, PX_FM_BLOCK_ALL);
1538f8d2de6bSjchu
1539bf8fc234Set142600 /* Figure out if this is a cfg or mem32 access */
1540bf8fc234Set142600 addr_high = (uint32_t)(addr >> 32);
1541bf8fc234Set142600 addr_low = (uint32_t)addr;
154226947304SEvan Yan range_len = px_p->px_ranges_length / sizeof (pci_ranges_t);
1543bf8fc234Set142600 i = 0;
1544bf8fc234Set142600 for (ranges_p = px_p->px_ranges_p; i < range_len; i++, ranges_p++) {
1545bf8fc234Set142600 if (ranges_p->parent_high == addr_high) {
1546bf8fc234Set142600 switch (ranges_p->child_high & PCI_ADDR_MASK) {
1547bf8fc234Set142600 case PCI_ADDR_CONFIG:
1548bf8fc234Set142600 bdf = (pcie_req_id_t)(addr_low >> 12);
1549bf8fc234Set142600 addr_low = 0;
1550bf8fc234Set142600 break;
1551bf8fc234Set142600 case PCI_ADDR_MEM32:
1552bf8fc234Set142600 if (rdip)
1553eae2e508Skrishnae bdf = PCI_GET_BDF(rdip);
1554bf8fc234Set142600 else
1555c85864d8SKrishna Elango bdf = PCIE_INVALID_BDF;
1556bf8fc234Set142600 break;
1557bf8fc234Set142600 }
1558bf8fc234Set142600 break;
1559bf8fc234Set142600 }
1560bf8fc234Set142600 }
1561bf8fc234Set142600
1562fc256490SJason Beloro (void) px_rp_en_q(px_p, bdf, addr_low, NULL);
1563bf8fc234Set142600
1564bf8fc234Set142600 /*
1565bf8fc234Set142600 * XXX - Current code scans the fabric for all px_tool accesses.
1566bf8fc234Set142600 * In future, do not scan fabric for px_tool access to IO Root Nexus
1567bf8fc234Set142600 */
1568eae2e508Skrishnae fab_err = px_scan_fabric(px_p, rpdip, &derr);
1569f8d2de6bSjchu
1570eae2e508Skrishnae px_err_panic(rc_err, PX_RC, fab_err, B_TRUE);
1571eae2e508Skrishnae px_fm_exit(px_p);
1572eae2e508Skrishnae px_err_panic(rc_err, PX_RC, fab_err, B_FALSE);
1573f8d2de6bSjchu }
1574f8d2de6bSjchu
15757c478bd9Sstevel@tonic-gate #ifdef DEBUG
15767c478bd9Sstevel@tonic-gate int px_peekfault_cnt = 0;
15777c478bd9Sstevel@tonic-gate int px_pokefault_cnt = 0;
15787c478bd9Sstevel@tonic-gate #endif /* DEBUG */
15797c478bd9Sstevel@tonic-gate
15807c478bd9Sstevel@tonic-gate /*ARGSUSED*/
15817c478bd9Sstevel@tonic-gate static int
px_lib_do_poke(dev_info_t * dip,dev_info_t * rdip,peekpoke_ctlops_t * in_args)15827c478bd9Sstevel@tonic-gate px_lib_do_poke(dev_info_t *dip, dev_info_t *rdip,
15837c478bd9Sstevel@tonic-gate peekpoke_ctlops_t *in_args)
15847c478bd9Sstevel@tonic-gate {
15857c478bd9Sstevel@tonic-gate px_t *px_p = DIP_TO_STATE(dip);
15867c478bd9Sstevel@tonic-gate px_pec_t *pec_p = px_p->px_pec_p;
15877c478bd9Sstevel@tonic-gate int err = DDI_SUCCESS;
15887c478bd9Sstevel@tonic-gate on_trap_data_t otd;
15897c478bd9Sstevel@tonic-gate
15907c478bd9Sstevel@tonic-gate mutex_enter(&pec_p->pec_pokefault_mutex);
15917c478bd9Sstevel@tonic-gate pec_p->pec_ontrap_data = &otd;
1592f8d2de6bSjchu pec_p->pec_safeacc_type = DDI_FM_ERR_POKE;
15937c478bd9Sstevel@tonic-gate
15947c478bd9Sstevel@tonic-gate /* Set up protected environment. */
15957c478bd9Sstevel@tonic-gate if (!on_trap(&otd, OT_DATA_ACCESS)) {
15967c478bd9Sstevel@tonic-gate uintptr_t tramp = otd.ot_trampoline;
15977c478bd9Sstevel@tonic-gate
15987c478bd9Sstevel@tonic-gate otd.ot_trampoline = (uintptr_t)&poke_fault;
15997c478bd9Sstevel@tonic-gate err = do_poke(in_args->size, (void *)in_args->dev_addr,
16007c478bd9Sstevel@tonic-gate (void *)in_args->host_addr);
16017c478bd9Sstevel@tonic-gate otd.ot_trampoline = tramp;
16027c478bd9Sstevel@tonic-gate } else
16037c478bd9Sstevel@tonic-gate err = DDI_FAILURE;
16047c478bd9Sstevel@tonic-gate
1605bf8fc234Set142600 px_lib_clr_errs(px_p, rdip, in_args->dev_addr);
1606f8d2de6bSjchu
16077c478bd9Sstevel@tonic-gate if (otd.ot_trap & OT_DATA_ACCESS)
16087c478bd9Sstevel@tonic-gate err = DDI_FAILURE;
16097c478bd9Sstevel@tonic-gate
16107c478bd9Sstevel@tonic-gate /* Take down protected environment. */
16117c478bd9Sstevel@tonic-gate no_trap();
16127c478bd9Sstevel@tonic-gate
16137c478bd9Sstevel@tonic-gate pec_p->pec_ontrap_data = NULL;
1614f8d2de6bSjchu pec_p->pec_safeacc_type = DDI_FM_ERR_UNEXPECTED;
16157c478bd9Sstevel@tonic-gate mutex_exit(&pec_p->pec_pokefault_mutex);
16167c478bd9Sstevel@tonic-gate
16177c478bd9Sstevel@tonic-gate #ifdef DEBUG
16187c478bd9Sstevel@tonic-gate if (err == DDI_FAILURE)
16197c478bd9Sstevel@tonic-gate px_pokefault_cnt++;
16207c478bd9Sstevel@tonic-gate #endif
16217c478bd9Sstevel@tonic-gate return (err);
16227c478bd9Sstevel@tonic-gate }
16237c478bd9Sstevel@tonic-gate
16247c478bd9Sstevel@tonic-gate /*ARGSUSED*/
16257c478bd9Sstevel@tonic-gate static int
px_lib_do_caut_put(dev_info_t * dip,dev_info_t * rdip,peekpoke_ctlops_t * cautacc_ctlops_arg)16267c478bd9Sstevel@tonic-gate px_lib_do_caut_put(dev_info_t *dip, dev_info_t *rdip,
16277c478bd9Sstevel@tonic-gate peekpoke_ctlops_t *cautacc_ctlops_arg)
16287c478bd9Sstevel@tonic-gate {
16297c478bd9Sstevel@tonic-gate size_t size = cautacc_ctlops_arg->size;
16307c478bd9Sstevel@tonic-gate uintptr_t dev_addr = cautacc_ctlops_arg->dev_addr;
16317c478bd9Sstevel@tonic-gate uintptr_t host_addr = cautacc_ctlops_arg->host_addr;
16327c478bd9Sstevel@tonic-gate ddi_acc_impl_t *hp = (ddi_acc_impl_t *)cautacc_ctlops_arg->handle;
16337c478bd9Sstevel@tonic-gate size_t repcount = cautacc_ctlops_arg->repcount;
16347c478bd9Sstevel@tonic-gate uint_t flags = cautacc_ctlops_arg->flags;
16357c478bd9Sstevel@tonic-gate
16367c478bd9Sstevel@tonic-gate px_t *px_p = DIP_TO_STATE(dip);
16377c478bd9Sstevel@tonic-gate px_pec_t *pec_p = px_p->px_pec_p;
16387c478bd9Sstevel@tonic-gate int err = DDI_SUCCESS;
16397c478bd9Sstevel@tonic-gate
1640f8d2de6bSjchu /*
1641f8d2de6bSjchu * Note that i_ndi_busop_access_enter ends up grabbing the pokefault
1642f8d2de6bSjchu * mutex.
1643f8d2de6bSjchu */
16447c478bd9Sstevel@tonic-gate i_ndi_busop_access_enter(hp->ahi_common.ah_dip, (ddi_acc_handle_t)hp);
16457c478bd9Sstevel@tonic-gate
1646f8d2de6bSjchu pec_p->pec_ontrap_data = (on_trap_data_t *)hp->ahi_err->err_ontrap;
1647f8d2de6bSjchu pec_p->pec_safeacc_type = DDI_FM_ERR_EXPECTED;
1648f8d2de6bSjchu hp->ahi_err->err_expected = DDI_FM_ERR_EXPECTED;
16497c478bd9Sstevel@tonic-gate
16507c478bd9Sstevel@tonic-gate if (!i_ddi_ontrap((ddi_acc_handle_t)hp)) {
16517c478bd9Sstevel@tonic-gate for (; repcount; repcount--) {
16527c478bd9Sstevel@tonic-gate switch (size) {
16537c478bd9Sstevel@tonic-gate
16547c478bd9Sstevel@tonic-gate case sizeof (uint8_t):
16557c478bd9Sstevel@tonic-gate i_ddi_put8(hp, (uint8_t *)dev_addr,
16567c478bd9Sstevel@tonic-gate *(uint8_t *)host_addr);
16577c478bd9Sstevel@tonic-gate break;
16587c478bd9Sstevel@tonic-gate
16597c478bd9Sstevel@tonic-gate case sizeof (uint16_t):
16607c478bd9Sstevel@tonic-gate i_ddi_put16(hp, (uint16_t *)dev_addr,
16617c478bd9Sstevel@tonic-gate *(uint16_t *)host_addr);
16627c478bd9Sstevel@tonic-gate break;
16637c478bd9Sstevel@tonic-gate
16647c478bd9Sstevel@tonic-gate case sizeof (uint32_t):
16657c478bd9Sstevel@tonic-gate i_ddi_put32(hp, (uint32_t *)dev_addr,
16667c478bd9Sstevel@tonic-gate *(uint32_t *)host_addr);
16677c478bd9Sstevel@tonic-gate break;
16687c478bd9Sstevel@tonic-gate
16697c478bd9Sstevel@tonic-gate case sizeof (uint64_t):
16707c478bd9Sstevel@tonic-gate i_ddi_put64(hp, (uint64_t *)dev_addr,
16717c478bd9Sstevel@tonic-gate *(uint64_t *)host_addr);
16727c478bd9Sstevel@tonic-gate break;
16737c478bd9Sstevel@tonic-gate }
16747c478bd9Sstevel@tonic-gate
16757c478bd9Sstevel@tonic-gate host_addr += size;
16767c478bd9Sstevel@tonic-gate
16777c478bd9Sstevel@tonic-gate if (flags == DDI_DEV_AUTOINCR)
16787c478bd9Sstevel@tonic-gate dev_addr += size;
16797c478bd9Sstevel@tonic-gate
1680bf8fc234Set142600 px_lib_clr_errs(px_p, rdip, dev_addr);
1681f8d2de6bSjchu
16827c478bd9Sstevel@tonic-gate if (pec_p->pec_ontrap_data->ot_trap & OT_DATA_ACCESS) {
16837c478bd9Sstevel@tonic-gate err = DDI_FAILURE;
16847c478bd9Sstevel@tonic-gate #ifdef DEBUG
16857c478bd9Sstevel@tonic-gate px_pokefault_cnt++;
16867c478bd9Sstevel@tonic-gate #endif
16877c478bd9Sstevel@tonic-gate break;
16887c478bd9Sstevel@tonic-gate }
16897c478bd9Sstevel@tonic-gate }
16907c478bd9Sstevel@tonic-gate }
16917c478bd9Sstevel@tonic-gate
16927c478bd9Sstevel@tonic-gate i_ddi_notrap((ddi_acc_handle_t)hp);
16937c478bd9Sstevel@tonic-gate pec_p->pec_ontrap_data = NULL;
1694f8d2de6bSjchu pec_p->pec_safeacc_type = DDI_FM_ERR_UNEXPECTED;
16957c478bd9Sstevel@tonic-gate i_ndi_busop_access_exit(hp->ahi_common.ah_dip, (ddi_acc_handle_t)hp);
16967c478bd9Sstevel@tonic-gate hp->ahi_err->err_expected = DDI_FM_ERR_UNEXPECTED;
16977c478bd9Sstevel@tonic-gate
16987c478bd9Sstevel@tonic-gate return (err);
16997c478bd9Sstevel@tonic-gate }
17007c478bd9Sstevel@tonic-gate
17017c478bd9Sstevel@tonic-gate
17027c478bd9Sstevel@tonic-gate int
px_lib_ctlops_poke(dev_info_t * dip,dev_info_t * rdip,peekpoke_ctlops_t * in_args)17037c478bd9Sstevel@tonic-gate px_lib_ctlops_poke(dev_info_t *dip, dev_info_t *rdip,
17047c478bd9Sstevel@tonic-gate peekpoke_ctlops_t *in_args)
17057c478bd9Sstevel@tonic-gate {
17067c478bd9Sstevel@tonic-gate return (in_args->handle ? px_lib_do_caut_put(dip, rdip, in_args) :
17077c478bd9Sstevel@tonic-gate px_lib_do_poke(dip, rdip, in_args));
17087c478bd9Sstevel@tonic-gate }
17097c478bd9Sstevel@tonic-gate
17107c478bd9Sstevel@tonic-gate
17117c478bd9Sstevel@tonic-gate /*ARGSUSED*/
17127c478bd9Sstevel@tonic-gate static int
px_lib_do_peek(dev_info_t * dip,peekpoke_ctlops_t * in_args)17137c478bd9Sstevel@tonic-gate px_lib_do_peek(dev_info_t *dip, peekpoke_ctlops_t *in_args)
17147c478bd9Sstevel@tonic-gate {
1715f8d2de6bSjchu px_t *px_p = DIP_TO_STATE(dip);
1716f8d2de6bSjchu px_pec_t *pec_p = px_p->px_pec_p;
17177c478bd9Sstevel@tonic-gate int err = DDI_SUCCESS;
17187c478bd9Sstevel@tonic-gate on_trap_data_t otd;
17197c478bd9Sstevel@tonic-gate
1720f8d2de6bSjchu mutex_enter(&pec_p->pec_pokefault_mutex);
1721fc256490SJason Beloro if (px_fm_enter(px_p) != DDI_SUCCESS) {
1722fc256490SJason Beloro mutex_exit(&pec_p->pec_pokefault_mutex);
1723eae2e508Skrishnae return (DDI_FAILURE);
1724fc256490SJason Beloro }
1725f8d2de6bSjchu pec_p->pec_safeacc_type = DDI_FM_ERR_PEEK;
1726eae2e508Skrishnae px_fm_exit(px_p);
1727f8d2de6bSjchu
17287c478bd9Sstevel@tonic-gate if (!on_trap(&otd, OT_DATA_ACCESS)) {
17297c478bd9Sstevel@tonic-gate uintptr_t tramp = otd.ot_trampoline;
17307c478bd9Sstevel@tonic-gate
17317c478bd9Sstevel@tonic-gate otd.ot_trampoline = (uintptr_t)&peek_fault;
17327c478bd9Sstevel@tonic-gate err = do_peek(in_args->size, (void *)in_args->dev_addr,
17337c478bd9Sstevel@tonic-gate (void *)in_args->host_addr);
17347c478bd9Sstevel@tonic-gate otd.ot_trampoline = tramp;
17357c478bd9Sstevel@tonic-gate } else
17367c478bd9Sstevel@tonic-gate err = DDI_FAILURE;
17377c478bd9Sstevel@tonic-gate
17387c478bd9Sstevel@tonic-gate no_trap();
1739f8d2de6bSjchu pec_p->pec_safeacc_type = DDI_FM_ERR_UNEXPECTED;
1740f8d2de6bSjchu mutex_exit(&pec_p->pec_pokefault_mutex);
17417c478bd9Sstevel@tonic-gate
17427c478bd9Sstevel@tonic-gate #ifdef DEBUG
17437c478bd9Sstevel@tonic-gate if (err == DDI_FAILURE)
17447c478bd9Sstevel@tonic-gate px_peekfault_cnt++;
17457c478bd9Sstevel@tonic-gate #endif
17467c478bd9Sstevel@tonic-gate return (err);
17477c478bd9Sstevel@tonic-gate }
17487c478bd9Sstevel@tonic-gate
17497c478bd9Sstevel@tonic-gate
17507c478bd9Sstevel@tonic-gate static int
px_lib_do_caut_get(dev_info_t * dip,peekpoke_ctlops_t * cautacc_ctlops_arg)17517c478bd9Sstevel@tonic-gate px_lib_do_caut_get(dev_info_t *dip, peekpoke_ctlops_t *cautacc_ctlops_arg)
17527c478bd9Sstevel@tonic-gate {
17537c478bd9Sstevel@tonic-gate size_t size = cautacc_ctlops_arg->size;
17547c478bd9Sstevel@tonic-gate uintptr_t dev_addr = cautacc_ctlops_arg->dev_addr;
17557c478bd9Sstevel@tonic-gate uintptr_t host_addr = cautacc_ctlops_arg->host_addr;
17567c478bd9Sstevel@tonic-gate ddi_acc_impl_t *hp = (ddi_acc_impl_t *)cautacc_ctlops_arg->handle;
17577c478bd9Sstevel@tonic-gate size_t repcount = cautacc_ctlops_arg->repcount;
17587c478bd9Sstevel@tonic-gate uint_t flags = cautacc_ctlops_arg->flags;
17597c478bd9Sstevel@tonic-gate
17607c478bd9Sstevel@tonic-gate px_t *px_p = DIP_TO_STATE(dip);
17617c478bd9Sstevel@tonic-gate px_pec_t *pec_p = px_p->px_pec_p;
17627c478bd9Sstevel@tonic-gate int err = DDI_SUCCESS;
17637c478bd9Sstevel@tonic-gate
1764f8d2de6bSjchu /*
1765f8d2de6bSjchu * Note that i_ndi_busop_access_enter ends up grabbing the pokefault
1766f8d2de6bSjchu * mutex.
1767f8d2de6bSjchu */
17687c478bd9Sstevel@tonic-gate i_ndi_busop_access_enter(hp->ahi_common.ah_dip, (ddi_acc_handle_t)hp);
17697c478bd9Sstevel@tonic-gate
1770f8d2de6bSjchu pec_p->pec_ontrap_data = (on_trap_data_t *)hp->ahi_err->err_ontrap;
1771f8d2de6bSjchu pec_p->pec_safeacc_type = DDI_FM_ERR_EXPECTED;
1772f8d2de6bSjchu hp->ahi_err->err_expected = DDI_FM_ERR_EXPECTED;
1773f8d2de6bSjchu
17747c478bd9Sstevel@tonic-gate if (repcount == 1) {
17757c478bd9Sstevel@tonic-gate if (!i_ddi_ontrap((ddi_acc_handle_t)hp)) {
17767c478bd9Sstevel@tonic-gate i_ddi_caut_get(size, (void *)dev_addr,
17777c478bd9Sstevel@tonic-gate (void *)host_addr);
17787c478bd9Sstevel@tonic-gate } else {
17797c478bd9Sstevel@tonic-gate int i;
17807c478bd9Sstevel@tonic-gate uint8_t *ff_addr = (uint8_t *)host_addr;
17817c478bd9Sstevel@tonic-gate for (i = 0; i < size; i++)
17827c478bd9Sstevel@tonic-gate *ff_addr++ = 0xff;
17837c478bd9Sstevel@tonic-gate
17847c478bd9Sstevel@tonic-gate err = DDI_FAILURE;
17857c478bd9Sstevel@tonic-gate #ifdef DEBUG
17867c478bd9Sstevel@tonic-gate px_peekfault_cnt++;
17877c478bd9Sstevel@tonic-gate #endif
17887c478bd9Sstevel@tonic-gate }
17897c478bd9Sstevel@tonic-gate } else {
17907c478bd9Sstevel@tonic-gate if (!i_ddi_ontrap((ddi_acc_handle_t)hp)) {
17917c478bd9Sstevel@tonic-gate for (; repcount; repcount--) {
17927c478bd9Sstevel@tonic-gate i_ddi_caut_get(size, (void *)dev_addr,
17937c478bd9Sstevel@tonic-gate (void *)host_addr);
17947c478bd9Sstevel@tonic-gate
17957c478bd9Sstevel@tonic-gate host_addr += size;
17967c478bd9Sstevel@tonic-gate
17977c478bd9Sstevel@tonic-gate if (flags == DDI_DEV_AUTOINCR)
17987c478bd9Sstevel@tonic-gate dev_addr += size;
17997c478bd9Sstevel@tonic-gate }
18007c478bd9Sstevel@tonic-gate } else {
18017c478bd9Sstevel@tonic-gate err = DDI_FAILURE;
18027c478bd9Sstevel@tonic-gate #ifdef DEBUG
18037c478bd9Sstevel@tonic-gate px_peekfault_cnt++;
18047c478bd9Sstevel@tonic-gate #endif
18057c478bd9Sstevel@tonic-gate }
18067c478bd9Sstevel@tonic-gate }
18077c478bd9Sstevel@tonic-gate
18087c478bd9Sstevel@tonic-gate i_ddi_notrap((ddi_acc_handle_t)hp);
18097c478bd9Sstevel@tonic-gate pec_p->pec_ontrap_data = NULL;
1810f8d2de6bSjchu pec_p->pec_safeacc_type = DDI_FM_ERR_UNEXPECTED;
18117c478bd9Sstevel@tonic-gate i_ndi_busop_access_exit(hp->ahi_common.ah_dip, (ddi_acc_handle_t)hp);
18127c478bd9Sstevel@tonic-gate hp->ahi_err->err_expected = DDI_FM_ERR_UNEXPECTED;
18137c478bd9Sstevel@tonic-gate
18147c478bd9Sstevel@tonic-gate return (err);
18157c478bd9Sstevel@tonic-gate }
18167c478bd9Sstevel@tonic-gate
18177c478bd9Sstevel@tonic-gate /*ARGSUSED*/
18187c478bd9Sstevel@tonic-gate int
px_lib_ctlops_peek(dev_info_t * dip,dev_info_t * rdip,peekpoke_ctlops_t * in_args,void * result)18197c478bd9Sstevel@tonic-gate px_lib_ctlops_peek(dev_info_t *dip, dev_info_t *rdip,
18207c478bd9Sstevel@tonic-gate peekpoke_ctlops_t *in_args, void *result)
18217c478bd9Sstevel@tonic-gate {
18227c478bd9Sstevel@tonic-gate result = (void *)in_args->host_addr;
18237c478bd9Sstevel@tonic-gate return (in_args->handle ? px_lib_do_caut_get(dip, in_args) :
18247c478bd9Sstevel@tonic-gate px_lib_do_peek(dip, in_args));
18257c478bd9Sstevel@tonic-gate }
18261a887b2eSjchu
18277c478bd9Sstevel@tonic-gate /*
18287c478bd9Sstevel@tonic-gate * implements PPM interface
18297c478bd9Sstevel@tonic-gate */
18307c478bd9Sstevel@tonic-gate int
px_lib_pmctl(int cmd,px_t * px_p)18317c478bd9Sstevel@tonic-gate px_lib_pmctl(int cmd, px_t *px_p)
18327c478bd9Sstevel@tonic-gate {
18337c478bd9Sstevel@tonic-gate ASSERT((cmd & ~PPMREQ_MASK) == PPMREQ);
18347c478bd9Sstevel@tonic-gate switch (cmd) {
18357c478bd9Sstevel@tonic-gate case PPMREQ_PRE_PWR_OFF:
18367c478bd9Sstevel@tonic-gate /*
18377c478bd9Sstevel@tonic-gate * Currently there is no device power management for
18387c478bd9Sstevel@tonic-gate * the root complex (fire). When there is we need to make
18397c478bd9Sstevel@tonic-gate * sure that it is at full power before trying to send the
18407c478bd9Sstevel@tonic-gate * PME_Turn_Off message.
18417c478bd9Sstevel@tonic-gate */
18427c478bd9Sstevel@tonic-gate DBG(DBG_PWR, px_p->px_dip,
18437c478bd9Sstevel@tonic-gate "ioctl: request to send PME_Turn_Off\n");
18447c478bd9Sstevel@tonic-gate return (px_goto_l23ready(px_p));
18457c478bd9Sstevel@tonic-gate
18467c478bd9Sstevel@tonic-gate case PPMREQ_PRE_PWR_ON:
18471a887b2eSjchu DBG(DBG_PWR, px_p->px_dip, "ioctl: PRE_PWR_ON request\n");
18481a887b2eSjchu return (px_pre_pwron_check(px_p));
18491a887b2eSjchu
18507c478bd9Sstevel@tonic-gate case PPMREQ_POST_PWR_ON:
18511a887b2eSjchu DBG(DBG_PWR, px_p->px_dip, "ioctl: POST_PWR_ON request\n");
18521a887b2eSjchu return (px_goto_l0(px_p));
18537c478bd9Sstevel@tonic-gate
18547c478bd9Sstevel@tonic-gate default:
18557c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
18567c478bd9Sstevel@tonic-gate }
18577c478bd9Sstevel@tonic-gate }
18587c478bd9Sstevel@tonic-gate
18597c478bd9Sstevel@tonic-gate /*
18607c478bd9Sstevel@tonic-gate * sends PME_Turn_Off message to put the link in L2/L3 ready state.
18617c478bd9Sstevel@tonic-gate * called by px_ioctl.
18627c478bd9Sstevel@tonic-gate * returns DDI_SUCCESS or DDI_FAILURE
18637c478bd9Sstevel@tonic-gate * 1. Wait for link to be in L1 state (link status reg)
18647c478bd9Sstevel@tonic-gate * 2. write to PME_Turn_off reg to boradcast
18657c478bd9Sstevel@tonic-gate * 3. set timeout
18667c478bd9Sstevel@tonic-gate * 4. If timeout, return failure.
18677c478bd9Sstevel@tonic-gate * 5. If PM_TO_Ack, wait till link is in L2/L3 ready
18687c478bd9Sstevel@tonic-gate */
18697c478bd9Sstevel@tonic-gate static int
px_goto_l23ready(px_t * px_p)18707c478bd9Sstevel@tonic-gate px_goto_l23ready(px_t *px_p)
18717c478bd9Sstevel@tonic-gate {
18727c478bd9Sstevel@tonic-gate pcie_pwr_t *pwr_p;
1873f8d2de6bSjchu pxu_t *pxu_p = (pxu_t *)px_p->px_plat_p;
1874f8d2de6bSjchu caddr_t csr_base = (caddr_t)pxu_p->px_address[PX_REG_CSR];
18757c478bd9Sstevel@tonic-gate int ret = DDI_SUCCESS;
18767c478bd9Sstevel@tonic-gate clock_t end, timeleft;
18771a887b2eSjchu int mutex_held = 1;
18787c478bd9Sstevel@tonic-gate
18797c478bd9Sstevel@tonic-gate /* If no PM info, return failure */
18807c478bd9Sstevel@tonic-gate if (!PCIE_PMINFO(px_p->px_dip) ||
18817c478bd9Sstevel@tonic-gate !(pwr_p = PCIE_NEXUS_PMINFO(px_p->px_dip)))
18827c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
18837c478bd9Sstevel@tonic-gate
18847c478bd9Sstevel@tonic-gate mutex_enter(&pwr_p->pwr_lock);
18851a887b2eSjchu mutex_enter(&px_p->px_l23ready_lock);
18867c478bd9Sstevel@tonic-gate /* Clear the PME_To_ACK receieved flag */
18871a887b2eSjchu px_p->px_pm_flags &= ~PX_PMETOACK_RECVD;
18883ee8f295Smg140465 /*
18893ee8f295Smg140465 * When P25 is the downstream device, after receiving
18903ee8f295Smg140465 * PME_To_ACK, fire will go to Detect state, which causes
18913ee8f295Smg140465 * the link down event. Inform FMA that this is expected.
18923ee8f295Smg140465 * In case of all other cards complaint with the pci express
18933ee8f295Smg140465 * spec, this will happen when the power is re-applied. FMA
18943ee8f295Smg140465 * code will clear this flag after one instance of LDN. Since
18953ee8f295Smg140465 * there will not be a LDN event for the spec compliant cards,
18963ee8f295Smg140465 * we need to clear the flag after receiving PME_To_ACK.
18973ee8f295Smg140465 */
18983ee8f295Smg140465 px_p->px_pm_flags |= PX_LDN_EXPECTED;
18997c478bd9Sstevel@tonic-gate if (px_send_pme_turnoff(csr_base) != DDI_SUCCESS) {
19007c478bd9Sstevel@tonic-gate ret = DDI_FAILURE;
19017c478bd9Sstevel@tonic-gate goto l23ready_done;
19027c478bd9Sstevel@tonic-gate }
19031a887b2eSjchu px_p->px_pm_flags |= PX_PME_TURNOFF_PENDING;
19047c478bd9Sstevel@tonic-gate
19057c478bd9Sstevel@tonic-gate end = ddi_get_lbolt() + drv_usectohz(px_pme_to_ack_timeout);
19061a887b2eSjchu while (!(px_p->px_pm_flags & PX_PMETOACK_RECVD)) {
19071a887b2eSjchu timeleft = cv_timedwait(&px_p->px_l23ready_cv,
19081a887b2eSjchu &px_p->px_l23ready_lock, end);
19097c478bd9Sstevel@tonic-gate /*
19107c478bd9Sstevel@tonic-gate * if cv_timedwait returns -1, it is either
19117c478bd9Sstevel@tonic-gate * 1) timed out or
19127c478bd9Sstevel@tonic-gate * 2) there was a pre-mature wakeup but by the time
19137c478bd9Sstevel@tonic-gate * cv_timedwait is called again end < lbolt i.e.
19147c478bd9Sstevel@tonic-gate * end is in the past.
19157c478bd9Sstevel@tonic-gate * 3) By the time we make first cv_timedwait call,
19167c478bd9Sstevel@tonic-gate * end < lbolt is true.
19177c478bd9Sstevel@tonic-gate */
19187c478bd9Sstevel@tonic-gate if (timeleft == -1)
19197c478bd9Sstevel@tonic-gate break;
19207c478bd9Sstevel@tonic-gate }
19211a887b2eSjchu if (!(px_p->px_pm_flags & PX_PMETOACK_RECVD)) {
19227c478bd9Sstevel@tonic-gate /*
19237c478bd9Sstevel@tonic-gate * Either timedout or interrupt didn't get a
19247c478bd9Sstevel@tonic-gate * chance to grab the mutex and set the flag.
19257c478bd9Sstevel@tonic-gate * release the mutex and delay for sometime.
19267c478bd9Sstevel@tonic-gate * This will 1) give a chance for interrupt to
19277c478bd9Sstevel@tonic-gate * set the flag 2) creates a delay between two
19287c478bd9Sstevel@tonic-gate * consequetive requests.
19297c478bd9Sstevel@tonic-gate */
19301a887b2eSjchu mutex_exit(&px_p->px_l23ready_lock);
1931f9721e07Sjchu delay(drv_usectohz(50 * PX_MSEC_TO_USEC));
19321a887b2eSjchu mutex_held = 0;
19331a887b2eSjchu if (!(px_p->px_pm_flags & PX_PMETOACK_RECVD)) {
19347c478bd9Sstevel@tonic-gate ret = DDI_FAILURE;
19357c478bd9Sstevel@tonic-gate DBG(DBG_PWR, px_p->px_dip, " Timed out while waiting"
19367c478bd9Sstevel@tonic-gate " for PME_TO_ACK\n");
19377c478bd9Sstevel@tonic-gate }
19387c478bd9Sstevel@tonic-gate }
19393ee8f295Smg140465 px_p->px_pm_flags &=
19403ee8f295Smg140465 ~(PX_PME_TURNOFF_PENDING | PX_PMETOACK_RECVD | PX_LDN_EXPECTED);
19417c478bd9Sstevel@tonic-gate
19427c478bd9Sstevel@tonic-gate l23ready_done:
19431a887b2eSjchu if (mutex_held)
19441a887b2eSjchu mutex_exit(&px_p->px_l23ready_lock);
19451a887b2eSjchu /*
19461a887b2eSjchu * Wait till link is in L1 idle, if sending PME_Turn_Off
19471a887b2eSjchu * was succesful.
19481a887b2eSjchu */
19491a887b2eSjchu if (ret == DDI_SUCCESS) {
19501a887b2eSjchu if (px_link_wait4l1idle(csr_base) != DDI_SUCCESS) {
19511a887b2eSjchu DBG(DBG_PWR, px_p->px_dip, " Link is not at L1"
19521a887b2eSjchu " even though we received PME_To_ACK.\n");
19533ee8f295Smg140465 /*
19543ee8f295Smg140465 * Workaround for hardware bug with P25.
19553ee8f295Smg140465 * Due to a hardware bug with P25, link state
19563ee8f295Smg140465 * will be Detect state rather than L1 after
19573ee8f295Smg140465 * link is transitioned to L23Ready state. Since
19583ee8f295Smg140465 * we don't know whether link is L23ready state
19593ee8f295Smg140465 * without Fire's state being L1_idle, we delay
19603ee8f295Smg140465 * here just to make sure that we wait till link
19613ee8f295Smg140465 * is transitioned to L23Ready state.
19623ee8f295Smg140465 */
1963f9721e07Sjchu delay(drv_usectohz(100 * PX_MSEC_TO_USEC));
19643ee8f295Smg140465 }
19651a887b2eSjchu pwr_p->pwr_link_lvl = PM_LEVEL_L3;
19661a887b2eSjchu
19671a887b2eSjchu }
19687c478bd9Sstevel@tonic-gate mutex_exit(&pwr_p->pwr_lock);
19697c478bd9Sstevel@tonic-gate return (ret);
19707c478bd9Sstevel@tonic-gate }
19717c478bd9Sstevel@tonic-gate
19721a887b2eSjchu /*
19731a887b2eSjchu * Message interrupt handler intended to be shared for both
19741a887b2eSjchu * PME and PME_TO_ACK msg handling, currently only handles
19751a887b2eSjchu * PME_To_ACK message.
19761a887b2eSjchu */
19771a887b2eSjchu uint_t
px_pmeq_intr(caddr_t arg)19781a887b2eSjchu px_pmeq_intr(caddr_t arg)
19791a887b2eSjchu {
19801a887b2eSjchu px_t *px_p = (px_t *)arg;
19811a887b2eSjchu
19823ee8f295Smg140465 DBG(DBG_PWR, px_p->px_dip, " PME_To_ACK received \n");
19831a887b2eSjchu mutex_enter(&px_p->px_l23ready_lock);
19841a887b2eSjchu cv_broadcast(&px_p->px_l23ready_cv);
19851a887b2eSjchu if (px_p->px_pm_flags & PX_PME_TURNOFF_PENDING) {
19861a887b2eSjchu px_p->px_pm_flags |= PX_PMETOACK_RECVD;
19871a887b2eSjchu } else {
19881a887b2eSjchu /*
19891a887b2eSjchu * This maybe the second ack received. If so then,
19901a887b2eSjchu * we should be receiving it during wait4L1 stage.
19911a887b2eSjchu */
19921a887b2eSjchu px_p->px_pmetoack_ignored++;
19931a887b2eSjchu }
19941a887b2eSjchu mutex_exit(&px_p->px_l23ready_lock);
19951a887b2eSjchu return (DDI_INTR_CLAIMED);
19961a887b2eSjchu }
19971a887b2eSjchu
19981a887b2eSjchu static int
px_pre_pwron_check(px_t * px_p)19991a887b2eSjchu px_pre_pwron_check(px_t *px_p)
20001a887b2eSjchu {
20011a887b2eSjchu pcie_pwr_t *pwr_p;
20021a887b2eSjchu
20031a887b2eSjchu /* If no PM info, return failure */
20041a887b2eSjchu if (!PCIE_PMINFO(px_p->px_dip) ||
20051a887b2eSjchu !(pwr_p = PCIE_NEXUS_PMINFO(px_p->px_dip)))
20061a887b2eSjchu return (DDI_FAILURE);
20071a887b2eSjchu
20083ee8f295Smg140465 /*
20093ee8f295Smg140465 * For the spec compliant downstream cards link down
20103ee8f295Smg140465 * is expected when the device is powered on.
20113ee8f295Smg140465 */
20123ee8f295Smg140465 px_p->px_pm_flags |= PX_LDN_EXPECTED;
20131a887b2eSjchu return (pwr_p->pwr_link_lvl == PM_LEVEL_L3 ? DDI_SUCCESS : DDI_FAILURE);
20141a887b2eSjchu }
20151a887b2eSjchu
20161a887b2eSjchu static int
px_goto_l0(px_t * px_p)20171a887b2eSjchu px_goto_l0(px_t *px_p)
20181a887b2eSjchu {
20191a887b2eSjchu pcie_pwr_t *pwr_p;
20201a887b2eSjchu pxu_t *pxu_p = (pxu_t *)px_p->px_plat_p;
20211a887b2eSjchu caddr_t csr_base = (caddr_t)pxu_p->px_address[PX_REG_CSR];
20221a887b2eSjchu int ret = DDI_SUCCESS;
2023f9721e07Sjchu uint64_t time_spent = 0;
20241a887b2eSjchu
20251a887b2eSjchu /* If no PM info, return failure */
20261a887b2eSjchu if (!PCIE_PMINFO(px_p->px_dip) ||
20271a887b2eSjchu !(pwr_p = PCIE_NEXUS_PMINFO(px_p->px_dip)))
20281a887b2eSjchu return (DDI_FAILURE);
20291a887b2eSjchu
20301a887b2eSjchu mutex_enter(&pwr_p->pwr_lock);
20313ee8f295Smg140465 /*
2032f9721e07Sjchu * The following link retrain activity will cause LDN and LUP event.
2033f9721e07Sjchu * Receiving LDN prior to receiving LUP is expected, not an error in
2034f9721e07Sjchu * this case. Receiving LUP indicates link is fully up to support
2035f9721e07Sjchu * powering up down stream device, and of course any further LDN and
2036f9721e07Sjchu * LUP outside this context will be error.
20373ee8f295Smg140465 */
2038f9721e07Sjchu px_p->px_lup_pending = 1;
20391a887b2eSjchu if (px_link_retrain(csr_base) != DDI_SUCCESS) {
20401a887b2eSjchu ret = DDI_FAILURE;
20411a887b2eSjchu goto l0_done;
20421a887b2eSjchu }
20431a887b2eSjchu
2044f9721e07Sjchu /* LUP event takes the order of 15ms amount of time to occur */
2045f9721e07Sjchu for (; px_p->px_lup_pending && (time_spent < px_lup_poll_to);
2046f9721e07Sjchu time_spent += px_lup_poll_interval)
2047f9721e07Sjchu drv_usecwait(px_lup_poll_interval);
2048f9721e07Sjchu if (px_p->px_lup_pending)
20491a887b2eSjchu ret = DDI_FAILURE;
20501a887b2eSjchu l0_done:
20511a887b2eSjchu px_enable_detect_quiet(csr_base);
20523ee8f295Smg140465 if (ret == DDI_SUCCESS)
20533ee8f295Smg140465 pwr_p->pwr_link_lvl = PM_LEVEL_L0;
20541a887b2eSjchu mutex_exit(&pwr_p->pwr_lock);
20551a887b2eSjchu return (ret);
20561a887b2eSjchu }
20571a887b2eSjchu
20587c478bd9Sstevel@tonic-gate /*
20597c478bd9Sstevel@tonic-gate * Extract the drivers binding name to identify which chip we're binding to.
20607c478bd9Sstevel@tonic-gate * Whenever a new bus bridge is created, the driver alias entry should be
20617c478bd9Sstevel@tonic-gate * added here to identify the device if needed. If a device isn't added,
20627c478bd9Sstevel@tonic-gate * the identity defaults to PX_CHIP_UNIDENTIFIED.
20637c478bd9Sstevel@tonic-gate */
20647c478bd9Sstevel@tonic-gate static uint32_t
px_identity_init(px_t * px_p)20657e1db6d2Sschwartz px_identity_init(px_t *px_p)
20667c478bd9Sstevel@tonic-gate {
20677c478bd9Sstevel@tonic-gate dev_info_t *dip = px_p->px_dip;
20687c478bd9Sstevel@tonic-gate char *name = ddi_binding_name(dip);
20697c478bd9Sstevel@tonic-gate uint32_t revision = 0;
20707c478bd9Sstevel@tonic-gate
20717c478bd9Sstevel@tonic-gate revision = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
20727c478bd9Sstevel@tonic-gate "module-revision#", 0);
20737c478bd9Sstevel@tonic-gate
20747c478bd9Sstevel@tonic-gate /* Check for Fire driver binding name */
20757e1db6d2Sschwartz if (strcmp(name, "pciex108e,80f0") == 0) {
20767e1db6d2Sschwartz DBG(DBG_ATTACH, dip, "px_identity_init: %s%d: "
20777e1db6d2Sschwartz "(FIRE), module-revision %d\n", NAMEINST(dip),
20787e1db6d2Sschwartz revision);
20797c478bd9Sstevel@tonic-gate
20807e1db6d2Sschwartz return ((revision >= FIRE_MOD_REV_20) ?
20817e1db6d2Sschwartz PX_CHIP_FIRE : PX_CHIP_UNIDENTIFIED);
20827c478bd9Sstevel@tonic-gate }
20837c478bd9Sstevel@tonic-gate
208425cf1a30Sjl139090 /* Check for Oberon driver binding name */
208525cf1a30Sjl139090 if (strcmp(name, "pciex108e,80f8") == 0) {
20867e1db6d2Sschwartz DBG(DBG_ATTACH, dip, "px_identity_init: %s%d: "
20877e1db6d2Sschwartz "(OBERON), module-revision %d\n", NAMEINST(dip),
20887e1db6d2Sschwartz revision);
208925cf1a30Sjl139090
20907e1db6d2Sschwartz return (PX_CHIP_OBERON);
209125cf1a30Sjl139090 }
209225cf1a30Sjl139090
20937c478bd9Sstevel@tonic-gate DBG(DBG_ATTACH, dip, "%s%d: Unknown PCI Express Host bridge %s %x\n",
20947c478bd9Sstevel@tonic-gate ddi_driver_name(dip), ddi_get_instance(dip), name, revision);
20957c478bd9Sstevel@tonic-gate
20967c478bd9Sstevel@tonic-gate return (PX_CHIP_UNIDENTIFIED);
20977c478bd9Sstevel@tonic-gate }
2098f8d2de6bSjchu
2099f8d2de6bSjchu int
px_err_add_intr(px_fault_t * px_fault_p)2100f8d2de6bSjchu px_err_add_intr(px_fault_t *px_fault_p)
2101f8d2de6bSjchu {
2102f8d2de6bSjchu dev_info_t *dip = px_fault_p->px_fh_dip;
2103f8d2de6bSjchu px_t *px_p = DIP_TO_STATE(dip);
2104f8d2de6bSjchu
2105f8d2de6bSjchu VERIFY(add_ivintr(px_fault_p->px_fh_sysino, PX_ERR_PIL,
2106b0fc0e77Sgovinda (intrfunc)px_fault_p->px_err_func, (caddr_t)px_fault_p,
2107b0fc0e77Sgovinda NULL, NULL) == 0);
2108f8d2de6bSjchu
2109f8d2de6bSjchu px_ib_intr_enable(px_p, intr_dist_cpuid(), px_fault_p->px_intr_ino);
2110f8d2de6bSjchu
2111f8d2de6bSjchu return (DDI_SUCCESS);
2112f8d2de6bSjchu }
2113f8d2de6bSjchu
2114f8d2de6bSjchu void
px_err_rem_intr(px_fault_t * px_fault_p)2115f8d2de6bSjchu px_err_rem_intr(px_fault_t *px_fault_p)
2116f8d2de6bSjchu {
2117f8d2de6bSjchu dev_info_t *dip = px_fault_p->px_fh_dip;
2118f8d2de6bSjchu px_t *px_p = DIP_TO_STATE(dip);
2119f8d2de6bSjchu
2120f8d2de6bSjchu px_ib_intr_disable(px_p->px_ib_p, px_fault_p->px_intr_ino,
2121f8d2de6bSjchu IB_INTR_WAIT);
21229c75c6bfSgovinda
2123b0fc0e77Sgovinda VERIFY(rem_ivintr(px_fault_p->px_fh_sysino, PX_ERR_PIL) == 0);
2124f8d2de6bSjchu }
2125f8d2de6bSjchu
212601689544Sjchu /*
2127a3c68edcSjchu * px_cb_intr_redist() - sun4u only, CB interrupt redistribution
2128a3c68edcSjchu */
2129a3c68edcSjchu void
px_cb_intr_redist(void * arg)2130a3c68edcSjchu px_cb_intr_redist(void *arg)
2131a3c68edcSjchu {
2132a3c68edcSjchu px_cb_t *cb_p = (px_cb_t *)arg;
2133a3c68edcSjchu px_cb_list_t *pxl;
2134a3c68edcSjchu px_t *pxp = NULL;
2135a3c68edcSjchu px_fault_t *f_p = NULL;
2136a3c68edcSjchu uint32_t new_cpuid;
2137a3c68edcSjchu intr_valid_state_t enabled = 0;
2138a3c68edcSjchu
2139a3c68edcSjchu mutex_enter(&cb_p->cb_mutex);
2140a3c68edcSjchu
2141a3c68edcSjchu pxl = cb_p->pxl;
2142a3c68edcSjchu if (!pxl)
2143a3c68edcSjchu goto cb_done;
2144a3c68edcSjchu
2145a3c68edcSjchu pxp = pxl->pxp;
2146a3c68edcSjchu f_p = &pxp->px_cb_fault;
2147a3c68edcSjchu for (; pxl && (f_p->px_fh_sysino != cb_p->sysino); ) {
2148a3c68edcSjchu pxl = pxl->next;
2149a3c68edcSjchu pxp = pxl->pxp;
2150a3c68edcSjchu f_p = &pxp->px_cb_fault;
2151a3c68edcSjchu }
2152a3c68edcSjchu if (pxl == NULL)
2153a3c68edcSjchu goto cb_done;
2154a3c68edcSjchu
2155a3c68edcSjchu new_cpuid = intr_dist_cpuid();
2156a3c68edcSjchu if (new_cpuid == cb_p->cpuid)
2157a3c68edcSjchu goto cb_done;
2158a3c68edcSjchu
2159a3c68edcSjchu if ((px_lib_intr_getvalid(pxp->px_dip, f_p->px_fh_sysino, &enabled)
2160a3c68edcSjchu != DDI_SUCCESS) || !enabled) {
2161a3c68edcSjchu DBG(DBG_IB, pxp->px_dip, "px_cb_intr_redist: CB not enabled, "
2162a3c68edcSjchu "sysino(0x%x)\n", f_p->px_fh_sysino);
2163a3c68edcSjchu goto cb_done;
2164a3c68edcSjchu }
2165a3c68edcSjchu
2166a3c68edcSjchu PX_INTR_DISABLE(pxp->px_dip, f_p->px_fh_sysino);
2167a3c68edcSjchu
2168a3c68edcSjchu cb_p->cpuid = new_cpuid;
2169a3c68edcSjchu cb_p->sysino = f_p->px_fh_sysino;
2170a3c68edcSjchu PX_INTR_ENABLE(pxp->px_dip, cb_p->sysino, cb_p->cpuid);
2171a3c68edcSjchu
2172a3c68edcSjchu cb_done:
2173a3c68edcSjchu mutex_exit(&cb_p->cb_mutex);
2174a3c68edcSjchu }
2175a3c68edcSjchu
2176a3c68edcSjchu /*
217701689544Sjchu * px_cb_add_intr() - Called from attach(9E) to create CB if not yet
217801689544Sjchu * created, to add CB interrupt vector always, but enable only once.
217901689544Sjchu */
218001689544Sjchu int
px_cb_add_intr(px_fault_t * fault_p)218101689544Sjchu px_cb_add_intr(px_fault_t *fault_p)
218201689544Sjchu {
218301689544Sjchu px_t *px_p = DIP_TO_STATE(fault_p->px_fh_dip);
218401689544Sjchu pxu_t *pxu_p = (pxu_t *)px_p->px_plat_p;
218525cf1a30Sjl139090 px_cb_t *cb_p = (px_cb_t *)px_get_cb(fault_p->px_fh_dip);
218601689544Sjchu px_cb_list_t *pxl, *pxl_new;
2187a3c68edcSjchu boolean_t is_proxy = B_FALSE;
218801689544Sjchu
2189a3c68edcSjchu /* create cb */
219001689544Sjchu if (cb_p == NULL) {
219101689544Sjchu cb_p = kmem_zalloc(sizeof (px_cb_t), KM_SLEEP);
2192a3c68edcSjchu
2193a3c68edcSjchu mutex_init(&cb_p->cb_mutex, NULL, MUTEX_DRIVER,
2194a3c68edcSjchu (void *) ipltospl(FM_ERR_PIL));
2195a3c68edcSjchu
219601689544Sjchu cb_p->px_cb_func = px_cb_intr;
219701689544Sjchu pxu_p->px_cb_p = cb_p;
219825cf1a30Sjl139090 px_set_cb(fault_p->px_fh_dip, (uint64_t)cb_p);
219908a74c0dSschwartz
220008a74c0dSschwartz /* px_lib_dev_init allows only FIRE and OBERON */
220108a74c0dSschwartz px_err_reg_enable(
220208a74c0dSschwartz (pxu_p->chip_type == PX_CHIP_FIRE) ?
220308a74c0dSschwartz PX_ERR_JBC : PX_ERR_UBC,
220408a74c0dSschwartz pxu_p->px_address[PX_REG_XBC]);
220501689544Sjchu } else
220601689544Sjchu pxu_p->px_cb_p = cb_p;
220701689544Sjchu
2208a3c68edcSjchu /* register cb interrupt */
220901689544Sjchu VERIFY(add_ivintr(fault_p->px_fh_sysino, PX_ERR_PIL,
2210b0fc0e77Sgovinda (intrfunc)cb_p->px_cb_func, (caddr_t)cb_p, NULL, NULL) == 0);
221101689544Sjchu
2212a3c68edcSjchu
2213a3c68edcSjchu /* update cb list */
2214a3c68edcSjchu mutex_enter(&cb_p->cb_mutex);
221501689544Sjchu if (cb_p->pxl == NULL) {
2216a3c68edcSjchu is_proxy = B_TRUE;
221701689544Sjchu pxl = kmem_zalloc(sizeof (px_cb_list_t), KM_SLEEP);
221801689544Sjchu pxl->pxp = px_p;
221901689544Sjchu cb_p->pxl = pxl;
222001689544Sjchu cb_p->sysino = fault_p->px_fh_sysino;
2221a3c68edcSjchu cb_p->cpuid = intr_dist_cpuid();
222201689544Sjchu } else {
222301689544Sjchu /*
222401689544Sjchu * Find the last pxl or
2225a3c68edcSjchu * stop short at encountering a redundent entry, or
222601689544Sjchu * both.
222701689544Sjchu */
222801689544Sjchu pxl = cb_p->pxl;
2229eae2e508Skrishnae for (; !(pxl->pxp == px_p) && pxl->next; pxl = pxl->next) {};
2230a3c68edcSjchu ASSERT(pxl->pxp != px_p);
223101689544Sjchu
223201689544Sjchu /* add to linked list */
223301689544Sjchu pxl_new = kmem_zalloc(sizeof (px_cb_list_t), KM_SLEEP);
223401689544Sjchu pxl_new->pxp = px_p;
223501689544Sjchu pxl->next = pxl_new;
223601689544Sjchu }
223701689544Sjchu cb_p->attachcnt++;
223801689544Sjchu mutex_exit(&cb_p->cb_mutex);
223901689544Sjchu
2240a3c68edcSjchu if (is_proxy) {
2241a3c68edcSjchu /* add to interrupt redistribution list */
2242a3c68edcSjchu intr_dist_add(px_cb_intr_redist, cb_p);
2243a3c68edcSjchu
2244a3c68edcSjchu /* enable cb hw interrupt */
2245a3c68edcSjchu px_ib_intr_enable(px_p, cb_p->cpuid, fault_p->px_intr_ino);
2246a3c68edcSjchu }
2247a3c68edcSjchu
224801689544Sjchu return (DDI_SUCCESS);
224901689544Sjchu }
225001689544Sjchu
225101689544Sjchu /*
225201689544Sjchu * px_cb_rem_intr() - Called from detach(9E) to remove its CB
225301689544Sjchu * interrupt vector, to shift proxy to the next available px,
225401689544Sjchu * or disable CB interrupt when itself is the last.
225501689544Sjchu */
225601689544Sjchu void
px_cb_rem_intr(px_fault_t * fault_p)225701689544Sjchu px_cb_rem_intr(px_fault_t *fault_p)
225801689544Sjchu {
225901689544Sjchu px_t *px_p = DIP_TO_STATE(fault_p->px_fh_dip), *pxp;
226001689544Sjchu pxu_t *pxu_p = (pxu_t *)px_p->px_plat_p;
226101689544Sjchu px_cb_t *cb_p = PX2CB(px_p);
226201689544Sjchu px_cb_list_t *pxl, *prev;
226301689544Sjchu px_fault_t *f_p;
226401689544Sjchu
226501689544Sjchu ASSERT(cb_p->pxl);
226601689544Sjchu
2267a3c68edcSjchu /* find and remove this px, and update cb list */
226801689544Sjchu mutex_enter(&cb_p->cb_mutex);
226901689544Sjchu
227001689544Sjchu pxl = cb_p->pxl;
227101689544Sjchu if (pxl->pxp == px_p) {
227201689544Sjchu cb_p->pxl = pxl->next;
227301689544Sjchu } else {
227401689544Sjchu prev = pxl;
227501689544Sjchu pxl = pxl->next;
2276eae2e508Skrishnae for (; pxl && (pxl->pxp != px_p); prev = pxl, pxl = pxl->next) {
2277eae2e508Skrishnae };
227801689544Sjchu if (!pxl) {
227901689544Sjchu cmn_err(CE_WARN, "px_cb_rem_intr: can't find px_p 0x%p "
22807389e29fSjchu "in registered CB list.", (void *)px_p);
2281a3c68edcSjchu mutex_exit(&cb_p->cb_mutex);
228201689544Sjchu return;
228301689544Sjchu }
228401689544Sjchu prev->next = pxl->next;
228501689544Sjchu }
2286a3c68edcSjchu pxu_p->px_cb_p = NULL;
2287a3c68edcSjchu cb_p->attachcnt--;
228801689544Sjchu kmem_free(pxl, sizeof (px_cb_list_t));
2289a3c68edcSjchu mutex_exit(&cb_p->cb_mutex);
229001689544Sjchu
2291a3c68edcSjchu /* disable cb hw interrupt */
2292a3c68edcSjchu if (fault_p->px_fh_sysino == cb_p->sysino)
229301689544Sjchu px_ib_intr_disable(px_p->px_ib_p, fault_p->px_intr_ino,
229401689544Sjchu IB_INTR_WAIT);
229501689544Sjchu
2296a3c68edcSjchu /* if last px, remove from interrupt redistribution list */
2297a3c68edcSjchu if (cb_p->pxl == NULL)
2298a3c68edcSjchu intr_dist_rem(px_cb_intr_redist, cb_p);
2299a3c68edcSjchu
2300a3c68edcSjchu /* de-register interrupt */
2301a3c68edcSjchu VERIFY(rem_ivintr(fault_p->px_fh_sysino, PX_ERR_PIL) == 0);
2302a3c68edcSjchu
2303a3c68edcSjchu /* if not last px, assign next px to manage cb */
2304a3c68edcSjchu mutex_enter(&cb_p->cb_mutex);
230501689544Sjchu if (cb_p->pxl) {
2306a3c68edcSjchu if (fault_p->px_fh_sysino == cb_p->sysino) {
230701689544Sjchu pxp = cb_p->pxl->pxp;
230801689544Sjchu f_p = &pxp->px_cb_fault;
230901689544Sjchu cb_p->sysino = f_p->px_fh_sysino;
231001689544Sjchu
231101689544Sjchu PX_INTR_ENABLE(pxp->px_dip, cb_p->sysino, cb_p->cpuid);
23127389e29fSjchu (void) px_lib_intr_setstate(pxp->px_dip, cb_p->sysino,
231301689544Sjchu INTR_IDLE_STATE);
231401689544Sjchu }
231501689544Sjchu mutex_exit(&cb_p->cb_mutex);
231601689544Sjchu return;
231701689544Sjchu }
2318a3c68edcSjchu
2319a3c68edcSjchu /* clean up after the last px */
232001689544Sjchu mutex_exit(&cb_p->cb_mutex);
232101689544Sjchu
232208a74c0dSschwartz /* px_lib_dev_init allows only FIRE and OBERON */
232308a74c0dSschwartz px_err_reg_disable(
232408a74c0dSschwartz (pxu_p->chip_type == PX_CHIP_FIRE) ? PX_ERR_JBC : PX_ERR_UBC,
232508a74c0dSschwartz pxu_p->px_address[PX_REG_XBC]);
232608a74c0dSschwartz
232701689544Sjchu mutex_destroy(&cb_p->cb_mutex);
232825cf1a30Sjl139090 px_set_cb(fault_p->px_fh_dip, 0ull);
232901689544Sjchu kmem_free(cb_p, sizeof (px_cb_t));
233001689544Sjchu }
233101689544Sjchu
233201689544Sjchu /*
233301689544Sjchu * px_cb_intr() - sun4u only, CB interrupt dispatcher
233401689544Sjchu */
233501689544Sjchu uint_t
px_cb_intr(caddr_t arg)233601689544Sjchu px_cb_intr(caddr_t arg)
233701689544Sjchu {
233801689544Sjchu px_cb_t *cb_p = (px_cb_t *)arg;
2339a3c68edcSjchu px_t *pxp;
2340a3c68edcSjchu px_fault_t *f_p;
2341a3c68edcSjchu int ret;
234268ac2337Sjl139090
234301689544Sjchu mutex_enter(&cb_p->cb_mutex);
234401689544Sjchu
2345a3c68edcSjchu if (!cb_p->pxl) {
234601689544Sjchu mutex_exit(&cb_p->cb_mutex);
2347a3c68edcSjchu return (DDI_INTR_UNCLAIMED);
234801689544Sjchu }
234901689544Sjchu
2350a3c68edcSjchu pxp = cb_p->pxl->pxp;
2351a3c68edcSjchu f_p = &pxp->px_cb_fault;
2352a3c68edcSjchu
2353a3c68edcSjchu ret = f_p->px_err_func((caddr_t)f_p);
235401689544Sjchu
235501689544Sjchu mutex_exit(&cb_p->cb_mutex);
2356a3c68edcSjchu return (ret);
235701689544Sjchu }
235801689544Sjchu
2359f8d2de6bSjchu #ifdef FMA
2360f8d2de6bSjchu void
px_fill_rc_status(px_fault_t * px_fault_p,pciex_rc_error_regs_t * rc_status)2361f8d2de6bSjchu px_fill_rc_status(px_fault_t *px_fault_p, pciex_rc_error_regs_t *rc_status)
2362f8d2de6bSjchu {
2363f8d2de6bSjchu /* populate the rc_status by reading the registers - TBD */
2364f8d2de6bSjchu }
2365f8d2de6bSjchu #endif /* FMA */
23668bc7d88aSet142600
23678bc7d88aSet142600 /*
2368817a6df8Sjchu * cpr callback
2369817a6df8Sjchu *
2370817a6df8Sjchu * disable fabric error msg interrupt prior to suspending
2371817a6df8Sjchu * all device drivers; re-enable fabric error msg interrupt
2372817a6df8Sjchu * after all devices are resumed.
2373817a6df8Sjchu */
2374817a6df8Sjchu static boolean_t
px_cpr_callb(void * arg,int code)2375817a6df8Sjchu px_cpr_callb(void *arg, int code)
2376817a6df8Sjchu {
2377817a6df8Sjchu px_t *px_p = (px_t *)arg;
2378817a6df8Sjchu px_ib_t *ib_p = px_p->px_ib_p;
2379817a6df8Sjchu px_pec_t *pec_p = px_p->px_pec_p;
2380817a6df8Sjchu pxu_t *pxu_p = (pxu_t *)px_p->px_plat_p;
2381817a6df8Sjchu caddr_t csr_base;
2382817a6df8Sjchu devino_t ce_ino, nf_ino, f_ino;
2383b0fc0e77Sgovinda px_ino_t *ce_ino_p, *nf_ino_p, *f_ino_p;
2384817a6df8Sjchu uint64_t imu_log_enable, imu_intr_enable;
2385817a6df8Sjchu uint64_t imu_log_mask, imu_intr_mask;
2386817a6df8Sjchu
2387817a6df8Sjchu ce_ino = px_msiqid_to_devino(px_p, pec_p->pec_corr_msg_msiq_id);
2388817a6df8Sjchu nf_ino = px_msiqid_to_devino(px_p, pec_p->pec_non_fatal_msg_msiq_id);
2389817a6df8Sjchu f_ino = px_msiqid_to_devino(px_p, pec_p->pec_fatal_msg_msiq_id);
2390817a6df8Sjchu csr_base = (caddr_t)pxu_p->px_address[PX_REG_CSR];
2391817a6df8Sjchu
2392817a6df8Sjchu imu_log_enable = CSR_XR(csr_base, IMU_ERROR_LOG_ENABLE);
2393817a6df8Sjchu imu_intr_enable = CSR_XR(csr_base, IMU_INTERRUPT_ENABLE);
2394817a6df8Sjchu
2395817a6df8Sjchu imu_log_mask = BITMASK(IMU_ERROR_LOG_ENABLE_FATAL_MES_NOT_EN_LOG_EN) |
2396817a6df8Sjchu BITMASK(IMU_ERROR_LOG_ENABLE_NONFATAL_MES_NOT_EN_LOG_EN) |
2397817a6df8Sjchu BITMASK(IMU_ERROR_LOG_ENABLE_COR_MES_NOT_EN_LOG_EN);
2398817a6df8Sjchu
2399817a6df8Sjchu imu_intr_mask =
2400817a6df8Sjchu BITMASK(IMU_INTERRUPT_ENABLE_FATAL_MES_NOT_EN_S_INT_EN) |
2401817a6df8Sjchu BITMASK(IMU_INTERRUPT_ENABLE_NONFATAL_MES_NOT_EN_S_INT_EN) |
2402817a6df8Sjchu BITMASK(IMU_INTERRUPT_ENABLE_COR_MES_NOT_EN_S_INT_EN) |
2403817a6df8Sjchu BITMASK(IMU_INTERRUPT_ENABLE_FATAL_MES_NOT_EN_P_INT_EN) |
2404817a6df8Sjchu BITMASK(IMU_INTERRUPT_ENABLE_NONFATAL_MES_NOT_EN_P_INT_EN) |
2405817a6df8Sjchu BITMASK(IMU_INTERRUPT_ENABLE_COR_MES_NOT_EN_P_INT_EN);
2406817a6df8Sjchu
2407817a6df8Sjchu switch (code) {
2408817a6df8Sjchu case CB_CODE_CPR_CHKPT:
2409817a6df8Sjchu /* disable imu rbne on corr/nonfatal/fatal errors */
2410817a6df8Sjchu CSR_XS(csr_base, IMU_ERROR_LOG_ENABLE,
2411817a6df8Sjchu imu_log_enable & (~imu_log_mask));
2412817a6df8Sjchu
2413817a6df8Sjchu CSR_XS(csr_base, IMU_INTERRUPT_ENABLE,
2414817a6df8Sjchu imu_intr_enable & (~imu_intr_mask));
2415817a6df8Sjchu
2416817a6df8Sjchu /* disable CORR intr mapping */
2417817a6df8Sjchu px_ib_intr_disable(ib_p, ce_ino, IB_INTR_NOWAIT);
2418817a6df8Sjchu
2419817a6df8Sjchu /* disable NON FATAL intr mapping */
2420817a6df8Sjchu px_ib_intr_disable(ib_p, nf_ino, IB_INTR_NOWAIT);
2421817a6df8Sjchu
2422817a6df8Sjchu /* disable FATAL intr mapping */
2423817a6df8Sjchu px_ib_intr_disable(ib_p, f_ino, IB_INTR_NOWAIT);
2424817a6df8Sjchu
2425817a6df8Sjchu break;
2426817a6df8Sjchu
2427817a6df8Sjchu case CB_CODE_CPR_RESUME:
2428bf8fc234Set142600 pxu_p->cpr_flag = PX_NOT_CPR;
2429817a6df8Sjchu mutex_enter(&ib_p->ib_ino_lst_mutex);
2430817a6df8Sjchu
2431817a6df8Sjchu ce_ino_p = px_ib_locate_ino(ib_p, ce_ino);
2432817a6df8Sjchu nf_ino_p = px_ib_locate_ino(ib_p, nf_ino);
2433817a6df8Sjchu f_ino_p = px_ib_locate_ino(ib_p, f_ino);
2434817a6df8Sjchu
2435817a6df8Sjchu /* enable CORR intr mapping */
2436817a6df8Sjchu if (ce_ino_p)
2437817a6df8Sjchu px_ib_intr_enable(px_p, ce_ino_p->ino_cpuid, ce_ino);
2438817a6df8Sjchu else
2439817a6df8Sjchu cmn_err(CE_WARN, "px_cpr_callb: RESUME unable to "
2440817a6df8Sjchu "reenable PCIe Correctable msg intr.\n");
2441817a6df8Sjchu
2442817a6df8Sjchu /* enable NON FATAL intr mapping */
2443817a6df8Sjchu if (nf_ino_p)
2444817a6df8Sjchu px_ib_intr_enable(px_p, nf_ino_p->ino_cpuid, nf_ino);
2445817a6df8Sjchu else
2446817a6df8Sjchu cmn_err(CE_WARN, "px_cpr_callb: RESUME unable to "
2447817a6df8Sjchu "reenable PCIe Non Fatal msg intr.\n");
2448817a6df8Sjchu
2449817a6df8Sjchu /* enable FATAL intr mapping */
2450817a6df8Sjchu if (f_ino_p)
2451817a6df8Sjchu px_ib_intr_enable(px_p, f_ino_p->ino_cpuid, f_ino);
2452817a6df8Sjchu else
2453817a6df8Sjchu cmn_err(CE_WARN, "px_cpr_callb: RESUME unable to "
2454817a6df8Sjchu "reenable PCIe Fatal msg intr.\n");
2455817a6df8Sjchu
2456817a6df8Sjchu mutex_exit(&ib_p->ib_ino_lst_mutex);
2457817a6df8Sjchu
2458817a6df8Sjchu /* enable corr/nonfatal/fatal not enable error */
2459817a6df8Sjchu CSR_XS(csr_base, IMU_ERROR_LOG_ENABLE, (imu_log_enable |
2460817a6df8Sjchu (imu_log_mask & px_imu_log_mask)));
2461817a6df8Sjchu CSR_XS(csr_base, IMU_INTERRUPT_ENABLE, (imu_intr_enable |
2462817a6df8Sjchu (imu_intr_mask & px_imu_intr_mask)));
2463817a6df8Sjchu
2464817a6df8Sjchu break;
2465817a6df8Sjchu }
2466817a6df8Sjchu
2467817a6df8Sjchu return (B_TRUE);
2468817a6df8Sjchu }
2469817a6df8Sjchu
247025cf1a30Sjl139090 uint64_t
px_get_rng_parent_hi_mask(px_t * px_p)2471d3533785Sschwartz px_get_rng_parent_hi_mask(px_t *px_p)
247225cf1a30Sjl139090 {
247325cf1a30Sjl139090 pxu_t *pxu_p = (pxu_t *)px_p->px_plat_p;
2474d3533785Sschwartz uint64_t mask;
247525cf1a30Sjl139090
247625cf1a30Sjl139090 switch (PX_CHIP_TYPE(pxu_p)) {
247725cf1a30Sjl139090 case PX_CHIP_OBERON:
247825cf1a30Sjl139090 mask = OBERON_RANGE_PROP_MASK;
247925cf1a30Sjl139090 break;
248025cf1a30Sjl139090 case PX_CHIP_FIRE:
2481d3533785Sschwartz mask = PX_RANGE_PROP_MASK;
248225cf1a30Sjl139090 break;
248325cf1a30Sjl139090 default:
2484d3533785Sschwartz mask = PX_RANGE_PROP_MASK;
248525cf1a30Sjl139090 }
2486d3533785Sschwartz
2487d3533785Sschwartz return (mask);
2488d3533785Sschwartz }
2489d3533785Sschwartz
2490d3533785Sschwartz /*
2491d3533785Sschwartz * fetch chip's range propery's value
2492d3533785Sschwartz */
2493d3533785Sschwartz uint64_t
px_get_range_prop(px_t * px_p,pci_ranges_t * rp,int bank)249426947304SEvan Yan px_get_range_prop(px_t *px_p, pci_ranges_t *rp, int bank)
2495d3533785Sschwartz {
2496d3533785Sschwartz uint64_t mask, range_prop;
2497d3533785Sschwartz
2498d3533785Sschwartz mask = px_get_rng_parent_hi_mask(px_p);
249925cf1a30Sjl139090 range_prop = (((uint64_t)(rp[bank].parent_high & mask)) << 32) |
250025cf1a30Sjl139090 rp[bank].parent_low;
250125cf1a30Sjl139090
250225cf1a30Sjl139090 return (range_prop);
250325cf1a30Sjl139090 }
250425cf1a30Sjl139090
250525cf1a30Sjl139090 /*
2506c0da6274SZhi-Jun Robin Fu * fetch the config space base addr of the root complex
2507c0da6274SZhi-Jun Robin Fu * note this depends on px structure being initialized
2508c0da6274SZhi-Jun Robin Fu */
2509c0da6274SZhi-Jun Robin Fu uint64_t
px_lib_get_cfgacc_base(dev_info_t * dip)2510c0da6274SZhi-Jun Robin Fu px_lib_get_cfgacc_base(dev_info_t *dip)
2511c0da6274SZhi-Jun Robin Fu {
2512c0da6274SZhi-Jun Robin Fu int instance = DIP_TO_INST(dip);
2513c0da6274SZhi-Jun Robin Fu px_t *px_p = INST_TO_STATE(instance);
2514c0da6274SZhi-Jun Robin Fu pci_ranges_t *rp = px_p->px_ranges_p;
2515c0da6274SZhi-Jun Robin Fu int bank = PCI_REG_ADDR_G(PCI_ADDR_CONFIG);
2516c0da6274SZhi-Jun Robin Fu
2517c0da6274SZhi-Jun Robin Fu /* Get Fire's Physical Base Address */
2518c0da6274SZhi-Jun Robin Fu return (px_get_range_prop(px_p, rp, bank));
2519c0da6274SZhi-Jun Robin Fu }
2520c0da6274SZhi-Jun Robin Fu
2521c0da6274SZhi-Jun Robin Fu /*
2522817a6df8Sjchu * add cpr callback
2523817a6df8Sjchu */
2524817a6df8Sjchu void
px_cpr_add_callb(px_t * px_p)2525817a6df8Sjchu px_cpr_add_callb(px_t *px_p)
2526817a6df8Sjchu {
2527817a6df8Sjchu px_p->px_cprcb_id = callb_add(px_cpr_callb, (void *)px_p,
2528817a6df8Sjchu CB_CL_CPR_POST_USER, "px_cpr");
2529817a6df8Sjchu }
2530817a6df8Sjchu
2531817a6df8Sjchu /*
2532817a6df8Sjchu * remove cpr callback
2533817a6df8Sjchu */
2534817a6df8Sjchu void
px_cpr_rem_callb(px_t * px_p)2535817a6df8Sjchu px_cpr_rem_callb(px_t *px_p)
2536817a6df8Sjchu {
2537817a6df8Sjchu (void) callb_delete(px_p->px_cprcb_id);
2538817a6df8Sjchu }
2539b65731f1Skini
2540b65731f1Skini /*ARGSUSED*/
254125cf1a30Sjl139090 static uint_t
px_hp_intr(caddr_t arg1,caddr_t arg2)254225cf1a30Sjl139090 px_hp_intr(caddr_t arg1, caddr_t arg2)
254325cf1a30Sjl139090 {
254425cf1a30Sjl139090 px_t *px_p = (px_t *)arg1;
25450d5b93d9Sgovinda pxu_t *pxu_p = (pxu_t *)px_p->px_plat_p;
254625cf1a30Sjl139090 int rval;
254725cf1a30Sjl139090
254826947304SEvan Yan rval = pcie_intr(px_p->px_dip);
254925cf1a30Sjl139090
255025cf1a30Sjl139090 #ifdef DEBUG
255125cf1a30Sjl139090 if (rval == DDI_INTR_UNCLAIMED)
255225cf1a30Sjl139090 cmn_err(CE_WARN, "%s%d: UNCLAIMED intr\n",
255325cf1a30Sjl139090 ddi_driver_name(px_p->px_dip),
255425cf1a30Sjl139090 ddi_get_instance(px_p->px_dip));
255525cf1a30Sjl139090 #endif
255625cf1a30Sjl139090
25570d5b93d9Sgovinda /* Set the interrupt state to idle */
25580d5b93d9Sgovinda if (px_lib_intr_setstate(px_p->px_dip,
25590d5b93d9Sgovinda pxu_p->hp_sysino, INTR_IDLE_STATE) != DDI_SUCCESS)
25600d5b93d9Sgovinda return (DDI_INTR_UNCLAIMED);
25610d5b93d9Sgovinda
256225cf1a30Sjl139090 return (rval);
256325cf1a30Sjl139090 }
256425cf1a30Sjl139090
2565b65731f1Skini int
px_lib_hotplug_init(dev_info_t * dip,void * arg)2566b65731f1Skini px_lib_hotplug_init(dev_info_t *dip, void *arg)
2567b65731f1Skini {
256825cf1a30Sjl139090 px_t *px_p = DIP_TO_STATE(dip);
25690d5b93d9Sgovinda pxu_t *pxu_p = (pxu_t *)px_p->px_plat_p;
257025cf1a30Sjl139090 uint64_t ret;
257125cf1a30Sjl139090
257226947304SEvan Yan if (ddi_prop_exists(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
257326947304SEvan Yan "hotplug-capable") == 0)
257426947304SEvan Yan return (DDI_FAILURE);
257526947304SEvan Yan
257625cf1a30Sjl139090 if ((ret = hvio_hotplug_init(dip, arg)) == DDI_SUCCESS) {
257725cf1a30Sjl139090 if (px_lib_intr_devino_to_sysino(px_p->px_dip,
25780d5b93d9Sgovinda px_p->px_inos[PX_INTR_HOTPLUG], &pxu_p->hp_sysino) !=
257925cf1a30Sjl139090 DDI_SUCCESS) {
258025cf1a30Sjl139090 #ifdef DEBUG
258125cf1a30Sjl139090 cmn_err(CE_WARN, "%s%d: devino_to_sysino fails\n",
258225cf1a30Sjl139090 ddi_driver_name(px_p->px_dip),
258325cf1a30Sjl139090 ddi_get_instance(px_p->px_dip));
258425cf1a30Sjl139090 #endif
258525cf1a30Sjl139090 return (DDI_FAILURE);
2586b65731f1Skini }
2587b65731f1Skini
258826947304SEvan Yan VERIFY(add_ivintr(pxu_p->hp_sysino, PCIE_INTR_PRI,
2589b0fc0e77Sgovinda (intrfunc)px_hp_intr, (caddr_t)px_p, NULL, NULL) == 0);
2590ab4471cdSscarter
2591ab4471cdSscarter px_ib_intr_enable(px_p, intr_dist_cpuid(),
2592ab4471cdSscarter px_p->px_inos[PX_INTR_HOTPLUG]);
259325cf1a30Sjl139090 }
259425cf1a30Sjl139090
259525cf1a30Sjl139090 return (ret);
259625cf1a30Sjl139090 }
259725cf1a30Sjl139090
2598b65731f1Skini void
px_lib_hotplug_uninit(dev_info_t * dip)2599b65731f1Skini px_lib_hotplug_uninit(dev_info_t *dip)
2600b65731f1Skini {
260125cf1a30Sjl139090 if (hvio_hotplug_uninit(dip) == DDI_SUCCESS) {
260225cf1a30Sjl139090 px_t *px_p = DIP_TO_STATE(dip);
26030d5b93d9Sgovinda pxu_t *pxu_p = (pxu_t *)px_p->px_plat_p;
260425cf1a30Sjl139090
2605ab4471cdSscarter px_ib_intr_disable(px_p->px_ib_p,
2606ab4471cdSscarter px_p->px_inos[PX_INTR_HOTPLUG], IB_INTR_WAIT);
2607ab4471cdSscarter
260826947304SEvan Yan VERIFY(rem_ivintr(pxu_p->hp_sysino, PCIE_INTR_PRI) == 0);
260925cf1a30Sjl139090 }
2610b65731f1Skini }
2611d60bae31Sdwoods
2612ab4471cdSscarter /*
2613ab4471cdSscarter * px_hp_intr_redist() - sun4u only, HP interrupt redistribution
2614ab4471cdSscarter */
2615ab4471cdSscarter void
px_hp_intr_redist(px_t * px_p)2616ab4471cdSscarter px_hp_intr_redist(px_t *px_p)
2617ab4471cdSscarter {
261826947304SEvan Yan pcie_bus_t *bus_p = PCIE_DIP2BUS(px_p->px_dip);
261926947304SEvan Yan
262026947304SEvan Yan if (px_p && PCIE_IS_PCIE_HOTPLUG_ENABLED(bus_p)) {
2621ab4471cdSscarter px_ib_intr_dist_en(px_p->px_dip, intr_dist_cpuid(),
2622ab4471cdSscarter px_p->px_inos[PX_INTR_HOTPLUG], B_FALSE);
2623ab4471cdSscarter }
2624ab4471cdSscarter }
2625ab4471cdSscarter
2626d60bae31Sdwoods boolean_t
px_lib_is_in_drain_state(px_t * px_p)2627d60bae31Sdwoods px_lib_is_in_drain_state(px_t *px_p)
2628d60bae31Sdwoods {
2629d60bae31Sdwoods pxu_t *pxu_p = (pxu_t *)px_p->px_plat_p;
2630d60bae31Sdwoods caddr_t csr_base = (caddr_t)pxu_p->px_address[PX_REG_CSR];
2631d60bae31Sdwoods uint64_t drain_status;
2632d60bae31Sdwoods
2633d60bae31Sdwoods if (PX_CHIP_TYPE(pxu_p) == PX_CHIP_OBERON) {
2634d60bae31Sdwoods drain_status = CSR_BR(csr_base, DRAIN_CONTROL_STATUS, DRAIN);
2635d60bae31Sdwoods } else {
2636d60bae31Sdwoods drain_status = CSR_BR(csr_base, TLU_STATUS, DRAIN);
2637d60bae31Sdwoods }
2638d60bae31Sdwoods
2639d60bae31Sdwoods return (drain_status);
2640d60bae31Sdwoods }
26417ea9b230Set142600
26427ea9b230Set142600 pcie_req_id_t
px_lib_get_bdf(px_t * px_p)26437ea9b230Set142600 px_lib_get_bdf(px_t *px_p)
26447ea9b230Set142600 {
26457ea9b230Set142600 pxu_t *pxu_p = (pxu_t *)px_p->px_plat_p;
26467ea9b230Set142600 caddr_t csr_base = (caddr_t)pxu_p->px_address[PX_REG_CSR];
26477ea9b230Set142600 pcie_req_id_t bdf;
26487ea9b230Set142600
26497ea9b230Set142600 bdf = CSR_BR(csr_base, DMC_PCI_EXPRESS_CONFIGURATION, REQ_ID);
26507ea9b230Set142600
26517ea9b230Set142600 return (bdf);
26527ea9b230Set142600 }
26530114761dSAlan Adamson, SD OSSD
26540114761dSAlan Adamson, SD OSSD /*ARGSUSED*/
26550114761dSAlan Adamson, SD OSSD int
px_lib_get_root_complex_mps(px_t * px_p,dev_info_t * dip,int * mps)26560114761dSAlan Adamson, SD OSSD px_lib_get_root_complex_mps(px_t *px_p, dev_info_t *dip, int *mps)
26570114761dSAlan Adamson, SD OSSD {
26580114761dSAlan Adamson, SD OSSD pxu_t *pxu_p;
26590114761dSAlan Adamson, SD OSSD caddr_t csr_base;
26600114761dSAlan Adamson, SD OSSD
26610114761dSAlan Adamson, SD OSSD pxu_p = (pxu_t *)px_p->px_plat_p;
26620114761dSAlan Adamson, SD OSSD
26630114761dSAlan Adamson, SD OSSD if (pxu_p == NULL)
26640114761dSAlan Adamson, SD OSSD return (DDI_FAILURE);
26650114761dSAlan Adamson, SD OSSD
26660114761dSAlan Adamson, SD OSSD csr_base = (caddr_t)pxu_p->px_address[PX_REG_CSR];
26670114761dSAlan Adamson, SD OSSD
26680114761dSAlan Adamson, SD OSSD
26690114761dSAlan Adamson, SD OSSD *mps = CSR_XR(csr_base, TLU_DEVICE_CAPABILITIES) &
26700114761dSAlan Adamson, SD OSSD TLU_DEVICE_CAPABILITIES_MPS_MASK;
26710114761dSAlan Adamson, SD OSSD
26720114761dSAlan Adamson, SD OSSD return (DDI_SUCCESS);
26730114761dSAlan Adamson, SD OSSD }
26740114761dSAlan Adamson, SD OSSD
26750114761dSAlan Adamson, SD OSSD /*ARGSUSED*/
26760114761dSAlan Adamson, SD OSSD int
px_lib_set_root_complex_mps(px_t * px_p,dev_info_t * dip,int mps)26770114761dSAlan Adamson, SD OSSD px_lib_set_root_complex_mps(px_t *px_p, dev_info_t *dip, int mps)
26780114761dSAlan Adamson, SD OSSD {
26790114761dSAlan Adamson, SD OSSD pxu_t *pxu_p;
26800114761dSAlan Adamson, SD OSSD caddr_t csr_base;
26810114761dSAlan Adamson, SD OSSD uint64_t dev_ctrl;
26820114761dSAlan Adamson, SD OSSD int link_width, val;
26830114761dSAlan Adamson, SD OSSD px_chip_type_t chip_type = px_identity_init(px_p);
26840114761dSAlan Adamson, SD OSSD
26850114761dSAlan Adamson, SD OSSD pxu_p = (pxu_t *)px_p->px_plat_p;
26860114761dSAlan Adamson, SD OSSD
26870114761dSAlan Adamson, SD OSSD if (pxu_p == NULL)
26880114761dSAlan Adamson, SD OSSD return (DDI_FAILURE);
26890114761dSAlan Adamson, SD OSSD
26900114761dSAlan Adamson, SD OSSD csr_base = (caddr_t)pxu_p->px_address[PX_REG_CSR];
26910114761dSAlan Adamson, SD OSSD
26920114761dSAlan Adamson, SD OSSD dev_ctrl = CSR_XR(csr_base, TLU_DEVICE_CONTROL);
26930114761dSAlan Adamson, SD OSSD dev_ctrl |= (mps << TLU_DEVICE_CONTROL_MPS);
26940114761dSAlan Adamson, SD OSSD
26950114761dSAlan Adamson, SD OSSD CSR_XS(csr_base, TLU_DEVICE_CONTROL, dev_ctrl);
26960114761dSAlan Adamson, SD OSSD
26970114761dSAlan Adamson, SD OSSD link_width = CSR_FR(csr_base, TLU_LINK_STATUS, WIDTH);
26980114761dSAlan Adamson, SD OSSD
26990114761dSAlan Adamson, SD OSSD /*
27000114761dSAlan Adamson, SD OSSD * Convert link_width to match timer array configuration.
27010114761dSAlan Adamson, SD OSSD */
27020114761dSAlan Adamson, SD OSSD switch (link_width) {
27030114761dSAlan Adamson, SD OSSD case 1:
27040114761dSAlan Adamson, SD OSSD link_width = 0;
27050114761dSAlan Adamson, SD OSSD break;
27060114761dSAlan Adamson, SD OSSD case 4:
27070114761dSAlan Adamson, SD OSSD link_width = 1;
27080114761dSAlan Adamson, SD OSSD break;
27090114761dSAlan Adamson, SD OSSD case 8:
27100114761dSAlan Adamson, SD OSSD link_width = 2;
27110114761dSAlan Adamson, SD OSSD break;
27120114761dSAlan Adamson, SD OSSD case 16:
27130114761dSAlan Adamson, SD OSSD link_width = 3;
27140114761dSAlan Adamson, SD OSSD break;
27150114761dSAlan Adamson, SD OSSD default:
27160114761dSAlan Adamson, SD OSSD link_width = 0;
27170114761dSAlan Adamson, SD OSSD }
27180114761dSAlan Adamson, SD OSSD
27190114761dSAlan Adamson, SD OSSD val = px_replay_timer_table[mps][link_width];
27200114761dSAlan Adamson, SD OSSD CSR_XS(csr_base, LPU_TXLINK_REPLAY_TIMER_THRESHOLD, val);
27210114761dSAlan Adamson, SD OSSD
27220114761dSAlan Adamson, SD OSSD if (chip_type == PX_CHIP_OBERON)
27230114761dSAlan Adamson, SD OSSD return (DDI_SUCCESS);
27240114761dSAlan Adamson, SD OSSD
27250114761dSAlan Adamson, SD OSSD val = px_acknak_timer_table[mps][link_width];
27260114761dSAlan Adamson, SD OSSD CSR_XS(csr_base, LPU_TXLINK_FREQUENT_NAK_LATENCY_TIMER_THRESHOLD, val);
27270114761dSAlan Adamson, SD OSSD
27280114761dSAlan Adamson, SD OSSD return (DDI_SUCCESS);
27290114761dSAlan Adamson, SD OSSD }
2730fc256490SJason Beloro
2731fc256490SJason Beloro /*ARGSUSED*/
2732fc256490SJason Beloro int
px_lib_fabric_sync(dev_info_t * dip)2733fc256490SJason Beloro px_lib_fabric_sync(dev_info_t *dip)
2734fc256490SJason Beloro {
2735fc256490SJason Beloro /* an no-op on sun4u platform */
2736fc256490SJason Beloro return (DDI_SUCCESS);
2737fc256490SJason Beloro }
2738