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 5*d3d50737SRafael Vanoni * Common Development and Distribution License (the "License"). 6*d3d50737SRafael Vanoni * 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*d3d50737SRafael Vanoni * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23*d3d50737SRafael Vanoni * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #include <sys/types.h> 277c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 287c478bd9Sstevel@tonic-gate #include <sys/open.h> 297c478bd9Sstevel@tonic-gate #include <sys/param.h> 307c478bd9Sstevel@tonic-gate #include <sys/vm_machparam.h> 317c478bd9Sstevel@tonic-gate #include <sys/machparam.h> 327c478bd9Sstevel@tonic-gate #include <sys/systm.h> 337c478bd9Sstevel@tonic-gate #include <sys/signal.h> 347c478bd9Sstevel@tonic-gate #include <sys/cred.h> 357c478bd9Sstevel@tonic-gate #include <sys/user.h> 367c478bd9Sstevel@tonic-gate #include <sys/proc.h> 377c478bd9Sstevel@tonic-gate #include <sys/vnode.h> 387c478bd9Sstevel@tonic-gate #include <sys/uio.h> 397c478bd9Sstevel@tonic-gate #include <sys/buf.h> 407c478bd9Sstevel@tonic-gate #include <sys/file.h> 417c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 427c478bd9Sstevel@tonic-gate #include <sys/stat.h> 437c478bd9Sstevel@tonic-gate #include <sys/stream.h> 447c478bd9Sstevel@tonic-gate #include <sys/stropts.h> 457c478bd9Sstevel@tonic-gate #include <sys/strsubr.h> 467c478bd9Sstevel@tonic-gate #include <sys/poll.h> 477c478bd9Sstevel@tonic-gate #include <sys/debug.h> 487c478bd9Sstevel@tonic-gate #include <sys/conf.h> 497c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 507c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 517c478bd9Sstevel@tonic-gate #include <sys/errno.h> 527c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 537c478bd9Sstevel@tonic-gate #include <sys/x_call.h> 547c478bd9Sstevel@tonic-gate #include <sys/cpuvar.h> 557c478bd9Sstevel@tonic-gate #include <sys/machcpuvar.h> 567c478bd9Sstevel@tonic-gate #include <sys/machsystm.h> 577c478bd9Sstevel@tonic-gate 587c478bd9Sstevel@tonic-gate #include <sys/pda.h> 597c478bd9Sstevel@tonic-gate #include <sys/starfire.h> 607c478bd9Sstevel@tonic-gate #include <sys/idn.h> 617c478bd9Sstevel@tonic-gate #include <sys/idn_xf.h> 627c478bd9Sstevel@tonic-gate 637c478bd9Sstevel@tonic-gate kmutex_t idn_xf_mutex; /* to serialize hardware access */ 647c478bd9Sstevel@tonic-gate /* 657c478bd9Sstevel@tonic-gate * This data structure is referenced during the cross-call 667c478bd9Sstevel@tonic-gate * update of the CICs. The semaphore is used for synchronization 677c478bd9Sstevel@tonic-gate * when waiting for completion of the respective operation. 687c478bd9Sstevel@tonic-gate * We want IDNCIC_TIMEOUT ticks for all the cpus to check-in 697c478bd9Sstevel@tonic-gate * before we bail out and fail the operation. 707c478bd9Sstevel@tonic-gate */ 717c478bd9Sstevel@tonic-gate #define IDNCIC_TIMEOUT (30*hz) 727c478bd9Sstevel@tonic-gate #define IDNCIC_TIMECHK (hz/3) 737c478bd9Sstevel@tonic-gate #define IDNCIC_UNKNOWN 0 747c478bd9Sstevel@tonic-gate #define IDNCIC_OK 1 /* values for xf_errcic */ 757c478bd9Sstevel@tonic-gate #define IDNCIC_ERR 2 767c478bd9Sstevel@tonic-gate #define IDNCIC_BUSY 3 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate #ifdef DEBUG 797c478bd9Sstevel@tonic-gate #define NCICREGS 3 /* smmask, smbar, smlar */ 807c478bd9Sstevel@tonic-gate #define CICREG_SMMASK 0 817c478bd9Sstevel@tonic-gate #define CICREG_SMBAR 1 827c478bd9Sstevel@tonic-gate #define CICREG_SMLAR 2 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate #define RESET_CIC_HISTORY() \ 857c478bd9Sstevel@tonic-gate (xf_cicboards = xf_cicbuses = 0, \ 867c478bd9Sstevel@tonic-gate bzero(xf_cicregs, sizeof (xf_cicregs))) 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate #define UPDATE_CIC_HISTORY(reg, brd, bus, val) \ 897c478bd9Sstevel@tonic-gate (BOARDSET_ADD(xf_cicboards, (brd)), \ 907c478bd9Sstevel@tonic-gate BOARDSET_ADD(xf_cicbuses, (bus)), \ 917c478bd9Sstevel@tonic-gate xf_cicregs[brd][bus][reg] = (val)) 927c478bd9Sstevel@tonic-gate 937c478bd9Sstevel@tonic-gate #define DUMP_CIC_HISTORY() \ 947c478bd9Sstevel@tonic-gate { \ 957c478bd9Sstevel@tonic-gate if (idn_debug & IDNDBG_XF) { \ 967c478bd9Sstevel@tonic-gate int _bd, _bs; \ 977c478bd9Sstevel@tonic-gate procname_t _proc = "dump_cic_history"; \ 987c478bd9Sstevel@tonic-gate for (_bd = 0; _bd < MAX_BOARDS; _bd++) { \ 997c478bd9Sstevel@tonic-gate if (!BOARD_IN_SET(xf_cicboards, _bd)) \ 1007c478bd9Sstevel@tonic-gate continue; \ 1017c478bd9Sstevel@tonic-gate for (_bs = 0; _bs < MAX_ABUSES; _bs++) { \ 1027c478bd9Sstevel@tonic-gate if (!BOARD_IN_SET(xf_cicbuses, _bs)) \ 1037c478bd9Sstevel@tonic-gate continue; \ 1047c478bd9Sstevel@tonic-gate printf("%s: (bd.bs = %d.%d) m/b/l = " \ 1057c478bd9Sstevel@tonic-gate "%x/%x/%x\n", _proc, _bd, _bs, \ 1067c478bd9Sstevel@tonic-gate xf_cicregs[_bd][_bs][CICREG_SMMASK], \ 1077c478bd9Sstevel@tonic-gate xf_cicregs[_bd][_bs][CICREG_SMBAR], \ 1087c478bd9Sstevel@tonic-gate xf_cicregs[_bd][_bs][CICREG_SMLAR]); \ 1097c478bd9Sstevel@tonic-gate } \ 1107c478bd9Sstevel@tonic-gate } \ 1117c478bd9Sstevel@tonic-gate DEBUG_DELAY(); \ 1127c478bd9Sstevel@tonic-gate } \ 1137c478bd9Sstevel@tonic-gate } 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate /* 1167c478bd9Sstevel@tonic-gate * Globally updated during CIC reg updates. Everybody has 1177c478bd9Sstevel@tonic-gate * a unique location, so no concern about updates stepping 1187c478bd9Sstevel@tonic-gate * on each other. 1197c478bd9Sstevel@tonic-gate */ 1207c478bd9Sstevel@tonic-gate static ushort_t xf_cicboards, xf_cicbuses; 1217c478bd9Sstevel@tonic-gate static uint_t xf_cicregs[MAX_BOARDS][MAX_ABUSES][NCICREGS]; 1227c478bd9Sstevel@tonic-gate #else /* DEBUG */ 1237c478bd9Sstevel@tonic-gate #define RESET_CIC_HISTORY() 1247c478bd9Sstevel@tonic-gate #define UPDATE_CIC_HISTORY(reg, brd, bus, val) 1257c478bd9Sstevel@tonic-gate #define DUMP_CIC_HISTORY() 1267c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 1277c478bd9Sstevel@tonic-gate 1287c478bd9Sstevel@tonic-gate struct idnxf_cic_info { /* protected by idn_xf_mutex */ 1297c478bd9Sstevel@tonic-gate /* 0 */ short xf_abus_mask; 1307c478bd9Sstevel@tonic-gate /* 2 */ boardset_t xf_boardset; 1317c478bd9Sstevel@tonic-gate /* 4 */ uint_t xf_smbase; 1327c478bd9Sstevel@tonic-gate /* 8 */ uint_t xf_smlimit; 1337c478bd9Sstevel@tonic-gate /* c */ int xf_doadd; 1347c478bd9Sstevel@tonic-gate 1357c478bd9Sstevel@tonic-gate /* 10 */ int xf_count; /* atomically updated */ 1367c478bd9Sstevel@tonic-gate /* 14 */ time_t xf_start_time; 1377c478bd9Sstevel@tonic-gate /* 18 */ kcondvar_t xf_cv; 1387c478bd9Sstevel@tonic-gate /* 1a */ short xf_errtimer; 1397c478bd9Sstevel@tonic-gate /* 1c */ int xf_errcnt; /* atomically updated */ 1407c478bd9Sstevel@tonic-gate 1417c478bd9Sstevel@tonic-gate /* 20 */ uchar_t xf_errcic[MAX_BOARDS][MAX_ABUSES]; 1427c478bd9Sstevel@tonic-gate 1437c478bd9Sstevel@tonic-gate /* 60 */ kmutex_t xf_mutex; 1447c478bd9Sstevel@tonic-gate }; /* sizeof = 0x68 = 104 (26X) */ 1457c478bd9Sstevel@tonic-gate 1467c478bd9Sstevel@tonic-gate static struct idnxf_cic_info idnxf_cic_info; 1477c478bd9Sstevel@tonic-gate #ifdef DEBUG 1487c478bd9Sstevel@tonic-gate static uint_t o_idn_debug; 1497c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate int idn_check_cpu_per_board = 1; 1527c478bd9Sstevel@tonic-gate 1537c478bd9Sstevel@tonic-gate static int pc_prep_cic_buffer(int cpuid, uint_t cicdata); 1547c478bd9Sstevel@tonic-gate static int cic_write_sm_mask(int board, int bus, boardset_t sm_mask); 1557c478bd9Sstevel@tonic-gate static int cic_write_sm_bar(int board, int bus, uint_t sm_bar); 1567c478bd9Sstevel@tonic-gate static int cic_write_sm_lar(int board, int bus, uint_t sm_lar); 1577c478bd9Sstevel@tonic-gate static int cic_get_smmask_bit(void); 1587c478bd9Sstevel@tonic-gate static int pc_write_madr(pda_handle_t ph, 1597c478bd9Sstevel@tonic-gate int lboard, int rboard, uint_t madr); 1607c478bd9Sstevel@tonic-gate static boardset_t get_boardset(pda_handle_t ph, int *nboards); 1617c478bd9Sstevel@tonic-gate static int verify_smregs(int brd, int bus, boardset_t smmask, 1627c478bd9Sstevel@tonic-gate uint_t smbase, uint_t smlimit); 1637c478bd9Sstevel@tonic-gate static void idnxf_shmem_wakeup(void *arg); 1647c478bd9Sstevel@tonic-gate static void idnxf_shmem_update_one(uint64_t arg1, uint64_t arg2); 1657c478bd9Sstevel@tonic-gate static int idnxf_shmem_update_all(pda_handle_t ph, 1667c478bd9Sstevel@tonic-gate boardset_t boardset, uint_t smbase, 1677c478bd9Sstevel@tonic-gate uint_t smlimit, int doadd); 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate #define PHYSIO_ST(paddr, val) (stphysio((paddr), (val))) 1707c478bd9Sstevel@tonic-gate #define PHYSIO_LD(paddr) (ldphysio(paddr)) 1717c478bd9Sstevel@tonic-gate #define PHYSIO_STH(paddr, val) (sthphysio((paddr), (val))) 1727c478bd9Sstevel@tonic-gate #define PHYSIO_LDH(paddr) (ldhphysio(paddr)) 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate #ifdef DEBUG 1757c478bd9Sstevel@tonic-gate #define DEBUG_DELAY() (drv_usecwait(5000)) /* 5 ms */ 1767c478bd9Sstevel@tonic-gate #else /* DEBUG */ 1777c478bd9Sstevel@tonic-gate #define DEBUG_DELAY() 1787c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate /* 1827c478bd9Sstevel@tonic-gate * --------------------------------------------------------------------- 1837c478bd9Sstevel@tonic-gate */ 1847c478bd9Sstevel@tonic-gate boardset_t 1857c478bd9Sstevel@tonic-gate cic_read_domain_mask(int board, int bus) 1867c478bd9Sstevel@tonic-gate { 1877c478bd9Sstevel@tonic-gate u_longlong_t csr_addr; 1887c478bd9Sstevel@tonic-gate boardset_t domain_mask; 1897c478bd9Sstevel@tonic-gate procname_t proc = "cic_read_domain_mask"; 1907c478bd9Sstevel@tonic-gate 1917c478bd9Sstevel@tonic-gate ASSERT(CPUID_TO_BOARDID(CPU->cpu_id) == board); 1927c478bd9Sstevel@tonic-gate 193*d3d50737SRafael Vanoni csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_DOMAIN_MASK_ADDR, 1947c478bd9Sstevel@tonic-gate bus); 1957c478bd9Sstevel@tonic-gate PR_XF("%s: (bd=%d, bs=%d) csr_addr = 0x%llx\n", 1967c478bd9Sstevel@tonic-gate proc, board, bus, csr_addr); 1977c478bd9Sstevel@tonic-gate 1987c478bd9Sstevel@tonic-gate domain_mask = (boardset_t)PHYSIO_LDH(csr_addr); 1997c478bd9Sstevel@tonic-gate 2007c478bd9Sstevel@tonic-gate return (domain_mask); 2017c478bd9Sstevel@tonic-gate } 2027c478bd9Sstevel@tonic-gate 2037c478bd9Sstevel@tonic-gate boardset_t 2047c478bd9Sstevel@tonic-gate cic_read_sm_mask(int board, int bus) 2057c478bd9Sstevel@tonic-gate { 2067c478bd9Sstevel@tonic-gate u_longlong_t csr_addr; 2077c478bd9Sstevel@tonic-gate boardset_t sm_mask; 2087c478bd9Sstevel@tonic-gate procname_t proc = "cic_read_sm_mask"; 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate ASSERT(CPUID_TO_BOARDID(CPU->cpu_id) == board); 2117c478bd9Sstevel@tonic-gate 212*d3d50737SRafael Vanoni csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_MASK_ADDR, 2137c478bd9Sstevel@tonic-gate bus); 2147c478bd9Sstevel@tonic-gate PR_XF("%s: (bd=%d, bs=%d) csr_addr = 0x%llx\n", 2157c478bd9Sstevel@tonic-gate proc, board, bus, csr_addr); 2167c478bd9Sstevel@tonic-gate 2177c478bd9Sstevel@tonic-gate sm_mask = (boardset_t)PHYSIO_LDH(csr_addr); 2187c478bd9Sstevel@tonic-gate 2197c478bd9Sstevel@tonic-gate return (sm_mask); 2207c478bd9Sstevel@tonic-gate } 2217c478bd9Sstevel@tonic-gate 2227c478bd9Sstevel@tonic-gate static int 2237c478bd9Sstevel@tonic-gate cic_write_sm_mask(int board, int bus, boardset_t sm_mask) 2247c478bd9Sstevel@tonic-gate { 2257c478bd9Sstevel@tonic-gate u_longlong_t csr_addr; 2267c478bd9Sstevel@tonic-gate int cnt; 2277c478bd9Sstevel@tonic-gate procname_t proc = "cic_write_sm_mask"; 2287c478bd9Sstevel@tonic-gate 2297c478bd9Sstevel@tonic-gate ASSERT(CPUID_TO_BOARDID(CPU->cpu_id) == board); 2307c478bd9Sstevel@tonic-gate 2317c478bd9Sstevel@tonic-gate sm_mask &= 0xffff; 2327c478bd9Sstevel@tonic-gate /* 2337c478bd9Sstevel@tonic-gate * Before we can write to the CIC, we need to set 2347c478bd9Sstevel@tonic-gate * up the CIC write data buffer in the PC. 2357c478bd9Sstevel@tonic-gate */ 2367c478bd9Sstevel@tonic-gate if (pc_prep_cic_buffer(CPU->cpu_id, (uint_t)sm_mask) < 0) 2377c478bd9Sstevel@tonic-gate return (-1); 2387c478bd9Sstevel@tonic-gate 2397c478bd9Sstevel@tonic-gate /* 2407c478bd9Sstevel@tonic-gate * Now we can write to the CIC. 2417c478bd9Sstevel@tonic-gate */ 242*d3d50737SRafael Vanoni csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_MASK_ADDR, 2437c478bd9Sstevel@tonic-gate bus); 2447c478bd9Sstevel@tonic-gate PR_XF("%s: (bd=%d, bs=%d) csr_addr = 0x%llx\n", 2457c478bd9Sstevel@tonic-gate proc, board, bus, csr_addr); 2467c478bd9Sstevel@tonic-gate PR_XF("%s: writing sm_mask = 0x%x\n", 2477c478bd9Sstevel@tonic-gate proc, (ushort_t)sm_mask); 2487c478bd9Sstevel@tonic-gate 2497c478bd9Sstevel@tonic-gate UPDATE_CIC_HISTORY(CICREG_SMMASK, board, bus, sm_mask); 2507c478bd9Sstevel@tonic-gate 2517c478bd9Sstevel@tonic-gate PHYSIO_STH(csr_addr, (ushort_t)sm_mask); 2527c478bd9Sstevel@tonic-gate /* 2537c478bd9Sstevel@tonic-gate * Read back for verification. 2547c478bd9Sstevel@tonic-gate */ 2557c478bd9Sstevel@tonic-gate for (cnt = 0; (PHYSIO_LDH(csr_addr) != sm_mask) && (cnt < 10); cnt++) 2567c478bd9Sstevel@tonic-gate ; 2577c478bd9Sstevel@tonic-gate 2587c478bd9Sstevel@tonic-gate return ((cnt == 10) ? -1 : 0); 2597c478bd9Sstevel@tonic-gate } 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate uint_t 2627c478bd9Sstevel@tonic-gate cic_read_sm_bar(int board, int bus) 2637c478bd9Sstevel@tonic-gate { 2647c478bd9Sstevel@tonic-gate u_longlong_t csr_addr; 2657c478bd9Sstevel@tonic-gate uint_t sm_bar; 2667c478bd9Sstevel@tonic-gate procname_t proc = "cic_read_sm_bar"; 2677c478bd9Sstevel@tonic-gate 2687c478bd9Sstevel@tonic-gate ASSERT(CPUID_TO_BOARDID(CPU->cpu_id) == board); 2697c478bd9Sstevel@tonic-gate 270*d3d50737SRafael Vanoni csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_BAR_MSB_ADDR, 2717c478bd9Sstevel@tonic-gate bus); 2727c478bd9Sstevel@tonic-gate PR_XF("%s:MSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n", 2737c478bd9Sstevel@tonic-gate proc, board, bus, csr_addr); 2747c478bd9Sstevel@tonic-gate 2757c478bd9Sstevel@tonic-gate sm_bar = (uint_t)PHYSIO_LDH(csr_addr); 2767c478bd9Sstevel@tonic-gate sm_bar <<= 16; 2777c478bd9Sstevel@tonic-gate 278*d3d50737SRafael Vanoni csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_BAR_LSB_ADDR, 2797c478bd9Sstevel@tonic-gate bus); 2807c478bd9Sstevel@tonic-gate PR_XF("%s:LSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n", 2817c478bd9Sstevel@tonic-gate proc, board, bus, csr_addr); 2827c478bd9Sstevel@tonic-gate 2837c478bd9Sstevel@tonic-gate sm_bar |= (uint_t)PHYSIO_LDH(csr_addr); 2847c478bd9Sstevel@tonic-gate 2857c478bd9Sstevel@tonic-gate return (sm_bar); 2867c478bd9Sstevel@tonic-gate } 2877c478bd9Sstevel@tonic-gate 2887c478bd9Sstevel@tonic-gate static int 2897c478bd9Sstevel@tonic-gate cic_write_sm_bar(int board, int bus, uint_t sm_bar) 2907c478bd9Sstevel@tonic-gate { 2917c478bd9Sstevel@tonic-gate int cnt; 2927c478bd9Sstevel@tonic-gate u_longlong_t csr_addr; 2937c478bd9Sstevel@tonic-gate uint_t sm_bar_lsb, sm_bar_msb; 2947c478bd9Sstevel@tonic-gate procname_t proc = "cic_write_sm_bar"; 2957c478bd9Sstevel@tonic-gate 2967c478bd9Sstevel@tonic-gate ASSERT(CPUID_TO_BOARDID(CPU->cpu_id) == board); 2977c478bd9Sstevel@tonic-gate 2987c478bd9Sstevel@tonic-gate sm_bar_lsb = sm_bar & 0xffff; 2997c478bd9Sstevel@tonic-gate sm_bar_msb = (sm_bar >> 16) & 0xffff; 3007c478bd9Sstevel@tonic-gate 3017c478bd9Sstevel@tonic-gate /* 3027c478bd9Sstevel@tonic-gate * Before we can write to the CIC, we need to set 3037c478bd9Sstevel@tonic-gate * up the CIC write data buffer in the PC. 3047c478bd9Sstevel@tonic-gate */ 3057c478bd9Sstevel@tonic-gate if (pc_prep_cic_buffer(CPU->cpu_id, sm_bar_msb) < 0) 3067c478bd9Sstevel@tonic-gate return (-1); 3077c478bd9Sstevel@tonic-gate 308*d3d50737SRafael Vanoni csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_BAR_MSB_ADDR, 3097c478bd9Sstevel@tonic-gate bus); 3107c478bd9Sstevel@tonic-gate PR_XF("%s:MSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n", 3117c478bd9Sstevel@tonic-gate proc, board, bus, csr_addr); 3127c478bd9Sstevel@tonic-gate PR_XF("%s:MSB: sm_bar[31:16] = 0x%x\n", 3137c478bd9Sstevel@tonic-gate proc, (ushort_t)sm_bar_msb); 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate UPDATE_CIC_HISTORY(CICREG_SMBAR, board, bus, sm_bar); 3167c478bd9Sstevel@tonic-gate 3177c478bd9Sstevel@tonic-gate PHYSIO_STH(csr_addr, (ushort_t)sm_bar_msb); 3187c478bd9Sstevel@tonic-gate for (cnt = 0; 3197c478bd9Sstevel@tonic-gate ((uint_t)PHYSIO_LDH(csr_addr) != sm_bar_msb) && (cnt < 10); 3207c478bd9Sstevel@tonic-gate cnt++) 3217c478bd9Sstevel@tonic-gate ; 3227c478bd9Sstevel@tonic-gate if (cnt == 10) { 3237c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 3247c478bd9Sstevel@tonic-gate "IDN: 500: failed to write sm_bar (msb) (0x%x)", 3257c478bd9Sstevel@tonic-gate (uint_t)sm_bar_msb); 3267c478bd9Sstevel@tonic-gate return (-1); 3277c478bd9Sstevel@tonic-gate } 3287c478bd9Sstevel@tonic-gate 3297c478bd9Sstevel@tonic-gate /* 3307c478bd9Sstevel@tonic-gate * Now to LSB portion. 3317c478bd9Sstevel@tonic-gate */ 3327c478bd9Sstevel@tonic-gate if (pc_prep_cic_buffer(CPU->cpu_id, sm_bar_lsb) < 0) 3337c478bd9Sstevel@tonic-gate return (-1); 3347c478bd9Sstevel@tonic-gate 335*d3d50737SRafael Vanoni csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_BAR_LSB_ADDR, 3367c478bd9Sstevel@tonic-gate bus); 3377c478bd9Sstevel@tonic-gate PR_XF("%s:LSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n", 3387c478bd9Sstevel@tonic-gate proc, board, bus, csr_addr); 3397c478bd9Sstevel@tonic-gate PR_XF("%s:LSB: sm_bar[15:0] = 0x%x\n", 3407c478bd9Sstevel@tonic-gate proc, (ushort_t)sm_bar_lsb); 3417c478bd9Sstevel@tonic-gate 3427c478bd9Sstevel@tonic-gate PHYSIO_STH(csr_addr, (ushort_t)sm_bar_lsb); 3437c478bd9Sstevel@tonic-gate for (cnt = 0; 3447c478bd9Sstevel@tonic-gate ((uint_t)PHYSIO_LDH(csr_addr) != sm_bar_lsb) && (cnt < 10); 3457c478bd9Sstevel@tonic-gate cnt++) 3467c478bd9Sstevel@tonic-gate ; 3477c478bd9Sstevel@tonic-gate if (cnt == 10) { 3487c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 3497c478bd9Sstevel@tonic-gate "IDN: 500: failed to write sm_bar (lsb) (0x%x)", 3507c478bd9Sstevel@tonic-gate (uint_t)sm_bar_lsb); 3517c478bd9Sstevel@tonic-gate return (-1); 3527c478bd9Sstevel@tonic-gate } 3537c478bd9Sstevel@tonic-gate 3547c478bd9Sstevel@tonic-gate return (0); 3557c478bd9Sstevel@tonic-gate } 3567c478bd9Sstevel@tonic-gate 3577c478bd9Sstevel@tonic-gate uint_t 3587c478bd9Sstevel@tonic-gate cic_read_sm_lar(int board, int bus) 3597c478bd9Sstevel@tonic-gate { 3607c478bd9Sstevel@tonic-gate u_longlong_t csr_addr; 3617c478bd9Sstevel@tonic-gate uint_t sm_lar; 3627c478bd9Sstevel@tonic-gate procname_t proc = "cic_read_sm_lar"; 3637c478bd9Sstevel@tonic-gate 3647c478bd9Sstevel@tonic-gate ASSERT(CPUID_TO_BOARDID(CPU->cpu_id) == board); 3657c478bd9Sstevel@tonic-gate 366*d3d50737SRafael Vanoni csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_LAR_MSB_ADDR, 3677c478bd9Sstevel@tonic-gate bus); 3687c478bd9Sstevel@tonic-gate PR_XF("%s:MSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n", 3697c478bd9Sstevel@tonic-gate proc, board, bus, csr_addr); 3707c478bd9Sstevel@tonic-gate 3717c478bd9Sstevel@tonic-gate sm_lar = (uint_t)PHYSIO_LDH(csr_addr); 3727c478bd9Sstevel@tonic-gate sm_lar <<= 16; 3737c478bd9Sstevel@tonic-gate 374*d3d50737SRafael Vanoni csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_LAR_LSB_ADDR, 3757c478bd9Sstevel@tonic-gate bus); 3767c478bd9Sstevel@tonic-gate PR_XF("%s:LSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n", 3777c478bd9Sstevel@tonic-gate proc, board, bus, csr_addr); 3787c478bd9Sstevel@tonic-gate 3797c478bd9Sstevel@tonic-gate sm_lar |= (uint_t)PHYSIO_LDH(csr_addr); 3807c478bd9Sstevel@tonic-gate 3817c478bd9Sstevel@tonic-gate return (sm_lar); 3827c478bd9Sstevel@tonic-gate } 3837c478bd9Sstevel@tonic-gate 3847c478bd9Sstevel@tonic-gate static int 3857c478bd9Sstevel@tonic-gate cic_write_sm_lar(int board, int bus, uint_t sm_lar) 3867c478bd9Sstevel@tonic-gate { 3877c478bd9Sstevel@tonic-gate int cnt; 3887c478bd9Sstevel@tonic-gate u_longlong_t csr_addr; 3897c478bd9Sstevel@tonic-gate uint_t sm_lar_lsb, sm_lar_msb; 3907c478bd9Sstevel@tonic-gate procname_t proc = "cic_write_sm_lar"; 3917c478bd9Sstevel@tonic-gate 3927c478bd9Sstevel@tonic-gate ASSERT(CPUID_TO_BOARDID(CPU->cpu_id) == board); 3937c478bd9Sstevel@tonic-gate 3947c478bd9Sstevel@tonic-gate sm_lar_lsb = sm_lar & 0xffff; 3957c478bd9Sstevel@tonic-gate sm_lar_msb = (sm_lar >> 16) & 0xffff; 3967c478bd9Sstevel@tonic-gate 3977c478bd9Sstevel@tonic-gate /* 3987c478bd9Sstevel@tonic-gate * Before we can write to the CIC, we need to set 3997c478bd9Sstevel@tonic-gate * up the CIC write data buffer in the PC. 4007c478bd9Sstevel@tonic-gate */ 4017c478bd9Sstevel@tonic-gate if (pc_prep_cic_buffer(CPU->cpu_id, sm_lar_msb) < 0) 4027c478bd9Sstevel@tonic-gate return (-1); 4037c478bd9Sstevel@tonic-gate 404*d3d50737SRafael Vanoni csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_LAR_MSB_ADDR, 4057c478bd9Sstevel@tonic-gate bus); 4067c478bd9Sstevel@tonic-gate PR_XF("%s:MSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n", 4077c478bd9Sstevel@tonic-gate proc, board, bus, csr_addr); 4087c478bd9Sstevel@tonic-gate PR_XF("%s:MSB: sm_lar[31:16] = 0x%x\n", 4097c478bd9Sstevel@tonic-gate proc, (ushort_t)sm_lar_msb); 4107c478bd9Sstevel@tonic-gate 4117c478bd9Sstevel@tonic-gate UPDATE_CIC_HISTORY(CICREG_SMLAR, board, bus, sm_lar); 4127c478bd9Sstevel@tonic-gate 4137c478bd9Sstevel@tonic-gate PHYSIO_STH(csr_addr, (ushort_t)sm_lar_msb); 4147c478bd9Sstevel@tonic-gate for (cnt = 0; 4157c478bd9Sstevel@tonic-gate ((uint_t)PHYSIO_LDH(csr_addr) != sm_lar_msb) && (cnt < 10); 4167c478bd9Sstevel@tonic-gate cnt++) 4177c478bd9Sstevel@tonic-gate ; 4187c478bd9Sstevel@tonic-gate if (cnt == 10) { 4197c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 4207c478bd9Sstevel@tonic-gate "IDN: 501: failed to write sm_lar (msb) (0x%x)", 4217c478bd9Sstevel@tonic-gate (uint_t)sm_lar_msb); 4227c478bd9Sstevel@tonic-gate return (-1); 4237c478bd9Sstevel@tonic-gate } 4247c478bd9Sstevel@tonic-gate 4257c478bd9Sstevel@tonic-gate /* 4267c478bd9Sstevel@tonic-gate * Now to LSB portion. 4277c478bd9Sstevel@tonic-gate */ 4287c478bd9Sstevel@tonic-gate if (pc_prep_cic_buffer(CPU->cpu_id, sm_lar_lsb) < 0) 4297c478bd9Sstevel@tonic-gate return (-1); 4307c478bd9Sstevel@tonic-gate 431*d3d50737SRafael Vanoni csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_LAR_LSB_ADDR, 4327c478bd9Sstevel@tonic-gate bus); 4337c478bd9Sstevel@tonic-gate PR_XF("%s:LSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n", 4347c478bd9Sstevel@tonic-gate proc, board, bus, csr_addr); 4357c478bd9Sstevel@tonic-gate PR_XF("%s:LSB: sm_lar[15:0] = 0x%x\n", 4367c478bd9Sstevel@tonic-gate proc, (ushort_t)sm_lar_lsb); 4377c478bd9Sstevel@tonic-gate 4387c478bd9Sstevel@tonic-gate PHYSIO_STH(csr_addr, (ushort_t)sm_lar_lsb); 4397c478bd9Sstevel@tonic-gate for (cnt = 0; 4407c478bd9Sstevel@tonic-gate ((uint_t)PHYSIO_LDH(csr_addr) != sm_lar_lsb) && (cnt < 10); 4417c478bd9Sstevel@tonic-gate cnt++) 4427c478bd9Sstevel@tonic-gate ; 4437c478bd9Sstevel@tonic-gate if (cnt == 10) { 4447c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 4457c478bd9Sstevel@tonic-gate "IDN: 501: failed to write sm_lar (lsb) (0x%x)", 4467c478bd9Sstevel@tonic-gate (uint_t)sm_lar_lsb); 4477c478bd9Sstevel@tonic-gate return (-1); 4487c478bd9Sstevel@tonic-gate } 4497c478bd9Sstevel@tonic-gate 4507c478bd9Sstevel@tonic-gate return (0); 4517c478bd9Sstevel@tonic-gate } 4527c478bd9Sstevel@tonic-gate 4537c478bd9Sstevel@tonic-gate static int 4547c478bd9Sstevel@tonic-gate cic_get_smmask_bit(void) 4557c478bd9Sstevel@tonic-gate { 4567c478bd9Sstevel@tonic-gate u_longlong_t csr_addr; 4577c478bd9Sstevel@tonic-gate int board; 4587c478bd9Sstevel@tonic-gate uint_t config1; 4597c478bd9Sstevel@tonic-gate procname_t proc = "cic_get_smmask_bit"; 4607c478bd9Sstevel@tonic-gate 4617c478bd9Sstevel@tonic-gate affinity_set(CPU_CURRENT); 4627c478bd9Sstevel@tonic-gate 4637c478bd9Sstevel@tonic-gate board = CPUID_TO_BOARDID(CPU->cpu_id); 4647c478bd9Sstevel@tonic-gate /* 4657c478bd9Sstevel@tonic-gate * Now that I'm stuck on this cpu I can go look at this 4667c478bd9Sstevel@tonic-gate * board's CIC registers. 4677c478bd9Sstevel@tonic-gate */ 468*d3d50737SRafael Vanoni csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_CONFIG1_ADDR, 0); 4697c478bd9Sstevel@tonic-gate PR_XF("%s: (bd=%d) csr_addr = 0x%llx (via cpu %d)\n", 4707c478bd9Sstevel@tonic-gate proc, board, csr_addr, (int)CPU->cpu_id); 4717c478bd9Sstevel@tonic-gate 4727c478bd9Sstevel@tonic-gate config1 = (uint_t)PHYSIO_LDH(csr_addr); 4737c478bd9Sstevel@tonic-gate 4747c478bd9Sstevel@tonic-gate config1 = CIC_CONFIG1_SMMASK_BIT(config1); 4757c478bd9Sstevel@tonic-gate 4767c478bd9Sstevel@tonic-gate affinity_clear(); 4777c478bd9Sstevel@tonic-gate 4787c478bd9Sstevel@tonic-gate return (config1); 4797c478bd9Sstevel@tonic-gate } 4807c478bd9Sstevel@tonic-gate 4817c478bd9Sstevel@tonic-gate static int 4827c478bd9Sstevel@tonic-gate pc_prep_cic_buffer(int cpuid, uint_t cicdata) 4837c478bd9Sstevel@tonic-gate { 4847c478bd9Sstevel@tonic-gate int rv; 4857c478bd9Sstevel@tonic-gate int brd, port; 4867c478bd9Sstevel@tonic-gate u_longlong_t csr_addr; 4877c478bd9Sstevel@tonic-gate register int cnt; 4887c478bd9Sstevel@tonic-gate procname_t proc = "pc_prep_cic_buffer"; 4897c478bd9Sstevel@tonic-gate 4907c478bd9Sstevel@tonic-gate 4917c478bd9Sstevel@tonic-gate ASSERT(CPU->cpu_id == cpuid); 4927c478bd9Sstevel@tonic-gate 4937c478bd9Sstevel@tonic-gate port = cpuid % plat_max_cpu_units_per_board(); 4947c478bd9Sstevel@tonic-gate brd = CPUID_TO_BOARDID(cpuid); 4957c478bd9Sstevel@tonic-gate 4967c478bd9Sstevel@tonic-gate csr_addr = STARFIRE_PC_CICBUF_ADDR(brd, port); 4977c478bd9Sstevel@tonic-gate 4987c478bd9Sstevel@tonic-gate /* 4997c478bd9Sstevel@tonic-gate * csr_addr now points to CIC write buffer which resides 5007c478bd9Sstevel@tonic-gate * in PC register space. 5017c478bd9Sstevel@tonic-gate */ 5027c478bd9Sstevel@tonic-gate PR_XF("%s: (cpu=%d) csr_addr = 0x%llx\n", proc, cpuid, csr_addr); 5037c478bd9Sstevel@tonic-gate 5047c478bd9Sstevel@tonic-gate PHYSIO_ST(csr_addr, cicdata); 5057c478bd9Sstevel@tonic-gate 5067c478bd9Sstevel@tonic-gate /* 5077c478bd9Sstevel@tonic-gate * Now we need to read back the data to guarantee 5087c478bd9Sstevel@tonic-gate * it got there. Part of the PC protocol. 5097c478bd9Sstevel@tonic-gate */ 5107c478bd9Sstevel@tonic-gate for (cnt = 0; (PHYSIO_LD(csr_addr) != cicdata) && (cnt < 10); 5117c478bd9Sstevel@tonic-gate cnt++) 5127c478bd9Sstevel@tonic-gate ; 5137c478bd9Sstevel@tonic-gate 5147c478bd9Sstevel@tonic-gate rv = 0; 5157c478bd9Sstevel@tonic-gate if (cnt == 10) { 5167c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 5177c478bd9Sstevel@tonic-gate "IDN: 502: unable to store data (0x%x) to " 5187c478bd9Sstevel@tonic-gate "CIC buffer (0x%llx)", 5197c478bd9Sstevel@tonic-gate cicdata, csr_addr); 5207c478bd9Sstevel@tonic-gate rv = -1; 5217c478bd9Sstevel@tonic-gate } else if (cnt >= 1) { 5227c478bd9Sstevel@tonic-gate PR_XF("%s: MULTIPLE READS (cpu=%d) cnt = %d\n", 5237c478bd9Sstevel@tonic-gate proc, cpuid, cnt); 5247c478bd9Sstevel@tonic-gate } 5257c478bd9Sstevel@tonic-gate 5267c478bd9Sstevel@tonic-gate return (rv); 5277c478bd9Sstevel@tonic-gate } 5287c478bd9Sstevel@tonic-gate 5297c478bd9Sstevel@tonic-gate /* 5307c478bd9Sstevel@tonic-gate * -------------------------------------------------- 5317c478bd9Sstevel@tonic-gate * Write the given MC address decoding register contents (madr) of 5327c478bd9Sstevel@tonic-gate * the respective remote board (rboard) into all the PCs located on 5337c478bd9Sstevel@tonic-gate * the local board (lboard). 5347c478bd9Sstevel@tonic-gate * -------------------------------------------------- 5357c478bd9Sstevel@tonic-gate */ 5367c478bd9Sstevel@tonic-gate static int 5377c478bd9Sstevel@tonic-gate pc_write_madr(pda_handle_t ph, int lboard, int rboard, uint_t madr) 5387c478bd9Sstevel@tonic-gate { 5397c478bd9Sstevel@tonic-gate u_longlong_t pc_madr_addr; 5407c478bd9Sstevel@tonic-gate register int p, ioc; 5417c478bd9Sstevel@tonic-gate register ushort_t procset, iocset; 5427c478bd9Sstevel@tonic-gate int rv = 0; 5437c478bd9Sstevel@tonic-gate uint_t rd_madr; 5447c478bd9Sstevel@tonic-gate board_desc_t *lbp; 5457c478bd9Sstevel@tonic-gate procname_t proc = "pc_write_madr"; 5467c478bd9Sstevel@tonic-gate 5477c478bd9Sstevel@tonic-gate lbp = pda_get_board_info(ph, lboard); 5487c478bd9Sstevel@tonic-gate 5497c478bd9Sstevel@tonic-gate ASSERT(lbp); 5507c478bd9Sstevel@tonic-gate ASSERT((lbp->bda_board & BDAN_MASK) == BDAN_GOOD); 5517c478bd9Sstevel@tonic-gate 5527c478bd9Sstevel@tonic-gate procset = lbp->bda_proc; 5537c478bd9Sstevel@tonic-gate iocset = lbp->bda_ioc; 5547c478bd9Sstevel@tonic-gate 5557c478bd9Sstevel@tonic-gate /* 5567c478bd9Sstevel@tonic-gate * Update the PCs for the cpus. 5577c478bd9Sstevel@tonic-gate */ 5587c478bd9Sstevel@tonic-gate for (p = 0; p < MAX_PROCMODS; procset >>= 4, p++) { 5597c478bd9Sstevel@tonic-gate int i; 5607c478bd9Sstevel@tonic-gate 5617c478bd9Sstevel@tonic-gate if (!((procset & BDAN_MASK) == BDAN_GOOD)) 5627c478bd9Sstevel@tonic-gate continue; 5637c478bd9Sstevel@tonic-gate 5647c478bd9Sstevel@tonic-gate pc_madr_addr = (u_longlong_t)STARFIRE_PC_MADR_ADDR(lboard, 5657c478bd9Sstevel@tonic-gate rboard, p); 5667c478bd9Sstevel@tonic-gate 5677c478bd9Sstevel@tonic-gate /* 5687c478bd9Sstevel@tonic-gate * On this first iteration of updating the PC 5697c478bd9Sstevel@tonic-gate * we need to turn off the MADR VALID bit so that 5707c478bd9Sstevel@tonic-gate * there's no accidental usage of the entry before 5717c478bd9Sstevel@tonic-gate * all four bytes have been updated in the PC. 5727c478bd9Sstevel@tonic-gate */ 5737c478bd9Sstevel@tonic-gate if (madr != 0) { 5747c478bd9Sstevel@tonic-gate /* 5757c478bd9Sstevel@tonic-gate * Need to clear valid bit on first 5767c478bd9Sstevel@tonic-gate * go around. 5777c478bd9Sstevel@tonic-gate */ 5787c478bd9Sstevel@tonic-gate madr &= ~STARFIRE_PC_MADR_VALIDBIT; 5797c478bd9Sstevel@tonic-gate } 5807c478bd9Sstevel@tonic-gate PR_XF("%s: write madr(0x%x) to pc_addr(0x%llx) " 5817c478bd9Sstevel@tonic-gate "[lb=%d, rb=%d, cpu=%d]\n", 5827c478bd9Sstevel@tonic-gate proc, madr, pc_madr_addr, lboard, rboard, p); 5837c478bd9Sstevel@tonic-gate DEBUG_DELAY(); 5847c478bd9Sstevel@tonic-gate 5857c478bd9Sstevel@tonic-gate for (i = 0; i < 20; i++) { 5867c478bd9Sstevel@tonic-gate PHYSIO_ST(pc_madr_addr, madr); 5877c478bd9Sstevel@tonic-gate /* 5887c478bd9Sstevel@tonic-gate * Read back for sanity check. 5897c478bd9Sstevel@tonic-gate */ 5907c478bd9Sstevel@tonic-gate rd_madr = PHYSIO_LD(pc_madr_addr); 5917c478bd9Sstevel@tonic-gate if (madr == rd_madr) 5927c478bd9Sstevel@tonic-gate break; 5937c478bd9Sstevel@tonic-gate } 5947c478bd9Sstevel@tonic-gate if (i > 0) { 5957c478bd9Sstevel@tonic-gate PR_XF("%s: WARNING: (1) lb=%d, rb=%d, " 5967c478bd9Sstevel@tonic-gate "madr=0x%x (i=%d)\n", 5977c478bd9Sstevel@tonic-gate proc, lboard, rboard, madr, i); 5987c478bd9Sstevel@tonic-gate } 5997c478bd9Sstevel@tonic-gate if (rd_madr != madr) { 6007c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 6017c478bd9Sstevel@tonic-gate "IDN: 503: (invalidate) failed to update " 6027c478bd9Sstevel@tonic-gate "PC madr (expected 0x%x, actual 0x%x)", 6037c478bd9Sstevel@tonic-gate madr, rd_madr); 6047c478bd9Sstevel@tonic-gate rv++; 6057c478bd9Sstevel@tonic-gate continue; 6067c478bd9Sstevel@tonic-gate } 6077c478bd9Sstevel@tonic-gate if (madr == 0) { 6087c478bd9Sstevel@tonic-gate continue; 6097c478bd9Sstevel@tonic-gate } else { 6107c478bd9Sstevel@tonic-gate /* 6117c478bd9Sstevel@tonic-gate * Turn the valid bit back on. 6127c478bd9Sstevel@tonic-gate */ 6137c478bd9Sstevel@tonic-gate madr |= STARFIRE_PC_MADR_VALIDBIT; 6147c478bd9Sstevel@tonic-gate } 6157c478bd9Sstevel@tonic-gate PR_XF("%s: write madr(0x%x) to pc_addr(0x%llx) " 6167c478bd9Sstevel@tonic-gate "[lb=%d, rb=%d, cpu=%d]\n", 6177c478bd9Sstevel@tonic-gate proc, madr, pc_madr_addr, lboard, rboard, p); 6187c478bd9Sstevel@tonic-gate DEBUG_DELAY(); 6197c478bd9Sstevel@tonic-gate 6207c478bd9Sstevel@tonic-gate for (i = 0; i < 20; i++) { 6217c478bd9Sstevel@tonic-gate PHYSIO_ST(pc_madr_addr, madr); 6227c478bd9Sstevel@tonic-gate /* 6237c478bd9Sstevel@tonic-gate * Read back for sanity check. 6247c478bd9Sstevel@tonic-gate */ 6257c478bd9Sstevel@tonic-gate rd_madr = PHYSIO_LD(pc_madr_addr); 6267c478bd9Sstevel@tonic-gate if (madr == rd_madr) 6277c478bd9Sstevel@tonic-gate break; 6287c478bd9Sstevel@tonic-gate } 6297c478bd9Sstevel@tonic-gate if (i > 0) { 6307c478bd9Sstevel@tonic-gate PR_XF("%s: WARNING: (2) lb=%d, rb=%d, " 6317c478bd9Sstevel@tonic-gate "madr=0x%x (i=%d)\n", 6327c478bd9Sstevel@tonic-gate proc, lboard, rboard, madr, i); 6337c478bd9Sstevel@tonic-gate } 6347c478bd9Sstevel@tonic-gate if (rd_madr != madr) { 6357c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 6367c478bd9Sstevel@tonic-gate "IDN: 503: (validate) failed to update " 6377c478bd9Sstevel@tonic-gate "PC madr (expected 0x%x, actual 0x%x)", 6387c478bd9Sstevel@tonic-gate madr, rd_madr); 6397c478bd9Sstevel@tonic-gate rv++; 6407c478bd9Sstevel@tonic-gate } 6417c478bd9Sstevel@tonic-gate } 6427c478bd9Sstevel@tonic-gate /* 6437c478bd9Sstevel@tonic-gate * Update the PCs for the iocs. 6447c478bd9Sstevel@tonic-gate */ 6457c478bd9Sstevel@tonic-gate for (ioc = 0; ioc < MAX_IOCS; iocset >>= 4, ioc++) { 6467c478bd9Sstevel@tonic-gate int i; 6477c478bd9Sstevel@tonic-gate 6487c478bd9Sstevel@tonic-gate if (!((iocset & BDAN_MASK) == BDAN_GOOD)) 6497c478bd9Sstevel@tonic-gate continue; 6507c478bd9Sstevel@tonic-gate 6517c478bd9Sstevel@tonic-gate pc_madr_addr = (u_longlong_t)STARFIRE_PC_MADR_ADDR(lboard, 6527c478bd9Sstevel@tonic-gate rboard, ioc + 4); 6537c478bd9Sstevel@tonic-gate 6547c478bd9Sstevel@tonic-gate if (madr != 0) { 6557c478bd9Sstevel@tonic-gate /* 6567c478bd9Sstevel@tonic-gate * Need to clear valid bit on first 6577c478bd9Sstevel@tonic-gate * go around. 6587c478bd9Sstevel@tonic-gate */ 6597c478bd9Sstevel@tonic-gate madr &= ~STARFIRE_PC_MADR_VALIDBIT; 6607c478bd9Sstevel@tonic-gate } 6617c478bd9Sstevel@tonic-gate PR_XF("%s: write madr(0x%x) to iopc_madr_addr(0x%llx) " 6627c478bd9Sstevel@tonic-gate "[lb=%d, rb=%d, ioc=%d]\n", 6637c478bd9Sstevel@tonic-gate proc, madr, pc_madr_addr, lboard, rboard, ioc); 6647c478bd9Sstevel@tonic-gate DEBUG_DELAY(); 6657c478bd9Sstevel@tonic-gate 6667c478bd9Sstevel@tonic-gate for (i = 0; i < 20; i++) { 6677c478bd9Sstevel@tonic-gate PHYSIO_ST(pc_madr_addr, madr); 6687c478bd9Sstevel@tonic-gate /* 6697c478bd9Sstevel@tonic-gate * Read back for sanity check. 6707c478bd9Sstevel@tonic-gate */ 6717c478bd9Sstevel@tonic-gate rd_madr = PHYSIO_LD(pc_madr_addr); 6727c478bd9Sstevel@tonic-gate if (madr == rd_madr) 6737c478bd9Sstevel@tonic-gate break; 6747c478bd9Sstevel@tonic-gate } 6757c478bd9Sstevel@tonic-gate if (i > 0) { 6767c478bd9Sstevel@tonic-gate PR_XF("%s: WARNING: (3) lb=%d, rb=%d, " 6777c478bd9Sstevel@tonic-gate "madr=0x%x (i=%d)\n", 6787c478bd9Sstevel@tonic-gate proc, lboard, rboard, madr, i); 6797c478bd9Sstevel@tonic-gate } 6807c478bd9Sstevel@tonic-gate if (rd_madr != madr) { 6817c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 6827c478bd9Sstevel@tonic-gate "IDN: 504: (invalidate) failed to update " 6837c478bd9Sstevel@tonic-gate "IOPC madr (expected 0x%x, actual 0x%x)", 6847c478bd9Sstevel@tonic-gate madr, rd_madr); 6857c478bd9Sstevel@tonic-gate rv++; 6867c478bd9Sstevel@tonic-gate continue; 6877c478bd9Sstevel@tonic-gate } 6887c478bd9Sstevel@tonic-gate 6897c478bd9Sstevel@tonic-gate if (madr == 0) { 6907c478bd9Sstevel@tonic-gate continue; 6917c478bd9Sstevel@tonic-gate } else { 6927c478bd9Sstevel@tonic-gate /* 6937c478bd9Sstevel@tonic-gate * Turn the valid bit back on. 6947c478bd9Sstevel@tonic-gate */ 6957c478bd9Sstevel@tonic-gate madr |= STARFIRE_PC_MADR_VALIDBIT; 6967c478bd9Sstevel@tonic-gate } 6977c478bd9Sstevel@tonic-gate 6987c478bd9Sstevel@tonic-gate PR_XF("%s: write madr(0x%x) to iopc_madr_addr(0x%llx) " 6997c478bd9Sstevel@tonic-gate "[lb=%d, rb=%d, ioc=%d]\n", 7007c478bd9Sstevel@tonic-gate proc, madr, pc_madr_addr, lboard, rboard, ioc); 7017c478bd9Sstevel@tonic-gate DEBUG_DELAY(); 7027c478bd9Sstevel@tonic-gate 7037c478bd9Sstevel@tonic-gate for (i = 0; i < 20; i++) { 7047c478bd9Sstevel@tonic-gate PHYSIO_ST(pc_madr_addr, madr); 7057c478bd9Sstevel@tonic-gate /* 7067c478bd9Sstevel@tonic-gate * Read back for sanity check. 7077c478bd9Sstevel@tonic-gate */ 7087c478bd9Sstevel@tonic-gate rd_madr = PHYSIO_LD(pc_madr_addr); 7097c478bd9Sstevel@tonic-gate if (madr == rd_madr) 7107c478bd9Sstevel@tonic-gate break; 7117c478bd9Sstevel@tonic-gate } 7127c478bd9Sstevel@tonic-gate if (i > 0) { 7137c478bd9Sstevel@tonic-gate PR_XF("%s: WARNING: (4) lb=%d, rb=%d, " 7147c478bd9Sstevel@tonic-gate "madr=0x%x (i=%d)\n", 7157c478bd9Sstevel@tonic-gate proc, lboard, rboard, madr, i); 7167c478bd9Sstevel@tonic-gate } 7177c478bd9Sstevel@tonic-gate if (rd_madr != madr) { 7187c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 7197c478bd9Sstevel@tonic-gate "IDN: 504: (validate) failed to update " 7207c478bd9Sstevel@tonic-gate "IOPC madr (expected 0x%x, actual 0x%x)", 7217c478bd9Sstevel@tonic-gate madr, rd_madr); 7227c478bd9Sstevel@tonic-gate rv++; 7237c478bd9Sstevel@tonic-gate } 7247c478bd9Sstevel@tonic-gate } 7257c478bd9Sstevel@tonic-gate 7267c478bd9Sstevel@tonic-gate return (rv ? -1 : 0); 7277c478bd9Sstevel@tonic-gate } 7287c478bd9Sstevel@tonic-gate 7297c478bd9Sstevel@tonic-gate /* 7307c478bd9Sstevel@tonic-gate * -------------------------------------------------- 7317c478bd9Sstevel@tonic-gate * Read the array of MC address decoding registers from one of the 7327c478bd9Sstevel@tonic-gate * PCs on the local board (lboard) into the given in array (mc_adr). 7337c478bd9Sstevel@tonic-gate * -------------------------------------------------- 7347c478bd9Sstevel@tonic-gate */ 7357c478bd9Sstevel@tonic-gate void 7367c478bd9Sstevel@tonic-gate pc_read_madr(pda_handle_t ph, int lboard, uint_t mc_adr[], int local_only) 7377c478bd9Sstevel@tonic-gate { 7387c478bd9Sstevel@tonic-gate u_longlong_t pc_madr_addr; 7397c478bd9Sstevel@tonic-gate register int p, ioc; 7407c478bd9Sstevel@tonic-gate register ushort_t procset, iocset; 7417c478bd9Sstevel@tonic-gate int brd; 7427c478bd9Sstevel@tonic-gate board_desc_t *lbp; 7437c478bd9Sstevel@tonic-gate 7447c478bd9Sstevel@tonic-gate lbp = pda_get_board_info(ph, lboard); 7457c478bd9Sstevel@tonic-gate 7467c478bd9Sstevel@tonic-gate ASSERT(lbp); 7477c478bd9Sstevel@tonic-gate ASSERT((lbp->bda_board & BDAN_MASK) == BDAN_GOOD); 7487c478bd9Sstevel@tonic-gate 7497c478bd9Sstevel@tonic-gate procset = lbp->bda_proc; 7507c478bd9Sstevel@tonic-gate iocset = lbp->bda_ioc; 7517c478bd9Sstevel@tonic-gate 7527c478bd9Sstevel@tonic-gate for (p = 0; p < MAX_PROCMODS; procset >>= 4, p++) 7537c478bd9Sstevel@tonic-gate if ((procset & BDAN_MASK) == BDAN_GOOD) 7547c478bd9Sstevel@tonic-gate break; 7557c478bd9Sstevel@tonic-gate 7567c478bd9Sstevel@tonic-gate if (p == MAX_PROCMODS) { 7577c478bd9Sstevel@tonic-gate /* 7587c478bd9Sstevel@tonic-gate * Couldn't find a PC off a cpu, let's check the 7597c478bd9Sstevel@tonic-gate * IOCs. 7607c478bd9Sstevel@tonic-gate */ 7617c478bd9Sstevel@tonic-gate for (ioc = 0; ioc < MAX_IOCS; iocset >>= 4, ioc++) 7627c478bd9Sstevel@tonic-gate if ((iocset & BDAN_MASK) == BDAN_GOOD) 7637c478bd9Sstevel@tonic-gate break; 7647c478bd9Sstevel@tonic-gate if (ioc == MAX_IOCS) { 7657c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 7667c478bd9Sstevel@tonic-gate "IDN: 505: board %d missing any valid PCs", 7677c478bd9Sstevel@tonic-gate lboard); 7687c478bd9Sstevel@tonic-gate return; 7697c478bd9Sstevel@tonic-gate } 7707c478bd9Sstevel@tonic-gate p = ioc + 4; 7717c478bd9Sstevel@tonic-gate } 7727c478bd9Sstevel@tonic-gate 7737c478bd9Sstevel@tonic-gate pc_madr_addr = (u_longlong_t)STARFIRE_PC_MADR_ADDR(lboard, 0, p); 7747c478bd9Sstevel@tonic-gate /* 7757c478bd9Sstevel@tonic-gate * pc_madr_addr = Starts at entry for board 0. 7767c478bd9Sstevel@tonic-gate */ 7777c478bd9Sstevel@tonic-gate for (brd = 0; brd < MAX_BOARDS; brd++) { 7787c478bd9Sstevel@tonic-gate /* 7797c478bd9Sstevel@tonic-gate * It's possible our local PC may have old entries to 7807c478bd9Sstevel@tonic-gate * AWOL domains. Only want to pay attention to PC 7817c478bd9Sstevel@tonic-gate * entries corresponding to our boards. 7827c478bd9Sstevel@tonic-gate */ 7837c478bd9Sstevel@tonic-gate lbp = pda_get_board_info(ph, brd); 784*d3d50737SRafael Vanoni if (!local_only || ((lbp->bda_board & BDAN_MASK) == BDAN_GOOD)) 7857c478bd9Sstevel@tonic-gate mc_adr[brd] = PHYSIO_LD(pc_madr_addr); 7867c478bd9Sstevel@tonic-gate else 7877c478bd9Sstevel@tonic-gate mc_adr[brd] = 0; 7887c478bd9Sstevel@tonic-gate 7897c478bd9Sstevel@tonic-gate pc_madr_addr += ((u_longlong_t)1 << 7907c478bd9Sstevel@tonic-gate STARFIRE_PC_MADR_BOARD_SHIFT); 7917c478bd9Sstevel@tonic-gate } 7927c478bd9Sstevel@tonic-gate } 7937c478bd9Sstevel@tonic-gate 7947c478bd9Sstevel@tonic-gate /* 7957c478bd9Sstevel@tonic-gate * -------------------------------------------------- 7967c478bd9Sstevel@tonic-gate * Read the MC address decoding register contents for all 7977c478bd9Sstevel@tonic-gate * possible boards and store the results in their respective 7987c478bd9Sstevel@tonic-gate * slot in mc_adr. Keep a count of non-zero MC ADRs and 7997c478bd9Sstevel@tonic-gate * return that. 8007c478bd9Sstevel@tonic-gate * -------------------------------------------------- 8017c478bd9Sstevel@tonic-gate */ 8027c478bd9Sstevel@tonic-gate void 8037c478bd9Sstevel@tonic-gate mc_get_adr_all(pda_handle_t ph, uint_t mc_adr[], int *nmcadr) 8047c478bd9Sstevel@tonic-gate { 8057c478bd9Sstevel@tonic-gate int brd; 8067c478bd9Sstevel@tonic-gate uint_t madr[MAX_BOARDS]; 8077c478bd9Sstevel@tonic-gate 8087c478bd9Sstevel@tonic-gate /* 8097c478bd9Sstevel@tonic-gate * Note that each PC has a complete copy of all MC contents 8107c478bd9Sstevel@tonic-gate * and so all we have to do is read one PC rather than 8117c478bd9Sstevel@tonic-gate * each of the MCs in the system. 8127c478bd9Sstevel@tonic-gate */ 8137c478bd9Sstevel@tonic-gate brd = CPUID_TO_BOARDID(CPU->cpu_id); 8147c478bd9Sstevel@tonic-gate pc_read_madr(ph, brd, madr, 1); 8157c478bd9Sstevel@tonic-gate 8167c478bd9Sstevel@tonic-gate *nmcadr = 0; 8177c478bd9Sstevel@tonic-gate for (brd = 0; brd < MAX_BOARDS; brd++) 8187c478bd9Sstevel@tonic-gate if ((mc_adr[brd] = madr[brd]) != 0) 8197c478bd9Sstevel@tonic-gate (*nmcadr)++; 8207c478bd9Sstevel@tonic-gate } 8217c478bd9Sstevel@tonic-gate 8227c478bd9Sstevel@tonic-gate static boardset_t 8237c478bd9Sstevel@tonic-gate get_boardset(pda_handle_t ph, int *nboards) 8247c478bd9Sstevel@tonic-gate { 8257c478bd9Sstevel@tonic-gate int brd; 8267c478bd9Sstevel@tonic-gate int nbrds = 0; 8277c478bd9Sstevel@tonic-gate boardset_t bmask; 8287c478bd9Sstevel@tonic-gate 8297c478bd9Sstevel@tonic-gate if (nboards != NULL) 8307c478bd9Sstevel@tonic-gate *nboards = 0; 8317c478bd9Sstevel@tonic-gate 8327c478bd9Sstevel@tonic-gate bmask = 0; 8337c478bd9Sstevel@tonic-gate for (brd = 0; brd < MAX_BOARDS; brd++) { 8347c478bd9Sstevel@tonic-gate if (pda_board_present(ph, brd)) { 8357c478bd9Sstevel@tonic-gate bmask |= 1 << brd; 8367c478bd9Sstevel@tonic-gate nbrds++; 8377c478bd9Sstevel@tonic-gate } 8387c478bd9Sstevel@tonic-gate } 8397c478bd9Sstevel@tonic-gate if (nboards != NULL) 8407c478bd9Sstevel@tonic-gate *nboards = (short)nbrds; 8417c478bd9Sstevel@tonic-gate 8427c478bd9Sstevel@tonic-gate return (bmask); 8437c478bd9Sstevel@tonic-gate } 8447c478bd9Sstevel@tonic-gate 8457c478bd9Sstevel@tonic-gate int 8467c478bd9Sstevel@tonic-gate update_local_hw_config(idn_domain_t *ldp, struct hwconfig *loc_hw) 8477c478bd9Sstevel@tonic-gate { 8487c478bd9Sstevel@tonic-gate procname_t proc = "update_local_hw_config"; 8497c478bd9Sstevel@tonic-gate 8507c478bd9Sstevel@tonic-gate ASSERT(IDN_DLOCK_IS_EXCL(ldp->domid)); 8517c478bd9Sstevel@tonic-gate ASSERT(IDN_GLOCK_IS_EXCL()); 8527c478bd9Sstevel@tonic-gate ASSERT(ldp == &idn_domain[idn.localid]); 8537c478bd9Sstevel@tonic-gate 8547c478bd9Sstevel@tonic-gate if (ldp->dhw.dh_boardset != loc_hw->dh_boardset) { 8557c478bd9Sstevel@tonic-gate int c; 8567c478bd9Sstevel@tonic-gate 8577c478bd9Sstevel@tonic-gate PR_PROTO("%s: NEW HW CONFIG (old_bset = 0x%x, " 8587c478bd9Sstevel@tonic-gate "new_bset = 0x%x)\n", 8597c478bd9Sstevel@tonic-gate proc, ldp->dhw.dh_boardset, loc_hw->dh_boardset); 8607c478bd9Sstevel@tonic-gate 8617c478bd9Sstevel@tonic-gate PR_PROTO("%s: clearing boardset 0x%x\n", proc, 8627c478bd9Sstevel@tonic-gate ldp->dhw.dh_boardset & ~loc_hw->dh_boardset); 8637c478bd9Sstevel@tonic-gate PR_PROTO("%s: setting boardset 0x%x\n", proc, 8647c478bd9Sstevel@tonic-gate loc_hw->dh_boardset & ~ldp->dhw.dh_boardset); 8657c478bd9Sstevel@tonic-gate 8667c478bd9Sstevel@tonic-gate idn.dc_boardset &= ~ldp->dhw.dh_boardset; 8677c478bd9Sstevel@tonic-gate idn.dc_boardset |= loc_hw->dh_boardset; 8687c478bd9Sstevel@tonic-gate for (c = 0; c < NCPU; c++) { 8697c478bd9Sstevel@tonic-gate if (CPU_IN_SET(ldp->dcpuset, c)) { 8707c478bd9Sstevel@tonic-gate CPUSET_DEL(idn.dc_cpuset, c); 8717c478bd9Sstevel@tonic-gate } 8727c478bd9Sstevel@tonic-gate } 8737c478bd9Sstevel@tonic-gate CPUSET_OR(idn.dc_cpuset, cpu_ready_set); 8747c478bd9Sstevel@tonic-gate 8757c478bd9Sstevel@tonic-gate bcopy(loc_hw, &ldp->dhw, sizeof (ldp->dhw)); 8767c478bd9Sstevel@tonic-gate ldp->dcpuset = cpu_ready_set; 8777c478bd9Sstevel@tonic-gate ldp->dcpu = cpu0.cpu_id; 8787c478bd9Sstevel@tonic-gate ldp->dncpus = (int)ncpus; 8797c478bd9Sstevel@tonic-gate ldp->dvote.v.nmembrds = ldp->dhw.dh_nmcadr - 1; 8807c478bd9Sstevel@tonic-gate ldp->dvote.v.ncpus = (int)ldp->dncpus - 1; 8817c478bd9Sstevel@tonic-gate ldp->dvote.v.board = CPUID_TO_BOARDID(CPU->cpu_id); 8827c478bd9Sstevel@tonic-gate 8837c478bd9Sstevel@tonic-gate return (1); 8847c478bd9Sstevel@tonic-gate } else { 8857c478bd9Sstevel@tonic-gate PR_PROTO("%s: NO change detected\n", proc); 8867c478bd9Sstevel@tonic-gate return (0); 8877c478bd9Sstevel@tonic-gate } 8887c478bd9Sstevel@tonic-gate } 8897c478bd9Sstevel@tonic-gate 8907c478bd9Sstevel@tonic-gate int 8917c478bd9Sstevel@tonic-gate get_hw_config(struct hwconfig *loc_hw) 8927c478bd9Sstevel@tonic-gate { 8937c478bd9Sstevel@tonic-gate pda_handle_t ph; 8947c478bd9Sstevel@tonic-gate boardset_t domainset; 8957c478bd9Sstevel@tonic-gate int bd; 8967c478bd9Sstevel@tonic-gate int nmcadr; 8977c478bd9Sstevel@tonic-gate int nboards; 8987c478bd9Sstevel@tonic-gate procname_t proc = "get_hw_config"; 8997c478bd9Sstevel@tonic-gate 9007c478bd9Sstevel@tonic-gate ASSERT(loc_hw != NULL); 9017c478bd9Sstevel@tonic-gate 9027c478bd9Sstevel@tonic-gate bzero(loc_hw, sizeof (*loc_hw)); 9037c478bd9Sstevel@tonic-gate /* 9047c478bd9Sstevel@tonic-gate * See if sm_mask is writable. 9057c478bd9Sstevel@tonic-gate * XXX - Should be the same for all CIC's. Do we 9067c478bd9Sstevel@tonic-gate * we need to verify? 9077c478bd9Sstevel@tonic-gate */ 9087c478bd9Sstevel@tonic-gate if (cic_get_smmask_bit() == 0) { 9097c478bd9Sstevel@tonic-gate /* 9107c478bd9Sstevel@tonic-gate * If smmask is not writable, we can not allow 9117c478bd9Sstevel@tonic-gate * IDN operations. 9127c478bd9Sstevel@tonic-gate */ 9137c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 9147c478bd9Sstevel@tonic-gate "IDN: 506: cic sm_mask is not writeable"); 9157c478bd9Sstevel@tonic-gate return (-1); 9167c478bd9Sstevel@tonic-gate } 9177c478bd9Sstevel@tonic-gate /* 9187c478bd9Sstevel@tonic-gate * Map in the post2obp structure so we can find 9197c478bd9Sstevel@tonic-gate * valid boards and hardware asics. 9207c478bd9Sstevel@tonic-gate */ 9217c478bd9Sstevel@tonic-gate ph = pda_open(); 9227c478bd9Sstevel@tonic-gate if (ph == (pda_handle_t)NULL) { 9237c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 9247c478bd9Sstevel@tonic-gate "IDN: 507: failed to map-in post2obp structure"); 9257c478bd9Sstevel@tonic-gate return (-1); 9267c478bd9Sstevel@tonic-gate } else if (!pda_is_valid(ph)) { 9277c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "IDN: 508: post2obp checksum invalid"); 9287c478bd9Sstevel@tonic-gate pda_close(ph); 9297c478bd9Sstevel@tonic-gate return (-1); 9307c478bd9Sstevel@tonic-gate } 9317c478bd9Sstevel@tonic-gate /* 9327c478bd9Sstevel@tonic-gate * Need to read the MC address decoding registers 9337c478bd9Sstevel@tonic-gate * so that they can be given to other domains. 9347c478bd9Sstevel@tonic-gate */ 9357c478bd9Sstevel@tonic-gate loc_hw->dh_boardset = get_boardset(ph, &nboards); 9367c478bd9Sstevel@tonic-gate loc_hw->dh_nboards = (short)nboards; 9377c478bd9Sstevel@tonic-gate ASSERT(loc_hw->dh_boardset & (1 << CPUID_TO_BOARDID(CPU->cpu_id))); 9387c478bd9Sstevel@tonic-gate 9397c478bd9Sstevel@tonic-gate mc_get_adr_all(ph, loc_hw->dh_mcadr, &nmcadr); 9407c478bd9Sstevel@tonic-gate loc_hw->dh_nmcadr = (short)nmcadr; 9417c478bd9Sstevel@tonic-gate 9427c478bd9Sstevel@tonic-gate affinity_set(CPU_CURRENT); 9437c478bd9Sstevel@tonic-gate /* 9447c478bd9Sstevel@tonic-gate * There will always be a bus 0 (logical). 9457c478bd9Sstevel@tonic-gate */ 9467c478bd9Sstevel@tonic-gate bd = CPUID_TO_BOARDID(CPU->cpu_id); 9477c478bd9Sstevel@tonic-gate domainset = (boardset_t)cic_read_domain_mask(bd, 0); 9487c478bd9Sstevel@tonic-gate affinity_clear(); 9497c478bd9Sstevel@tonic-gate 9507c478bd9Sstevel@tonic-gate if (!idn_cpu_per_board(ph, cpu_ready_set, loc_hw)) { 9517c478bd9Sstevel@tonic-gate pda_close(ph); 9527c478bd9Sstevel@tonic-gate return (-1); 9537c478bd9Sstevel@tonic-gate } 9547c478bd9Sstevel@tonic-gate 9557c478bd9Sstevel@tonic-gate pda_close(ph); 9567c478bd9Sstevel@tonic-gate 9577c478bd9Sstevel@tonic-gate 9587c478bd9Sstevel@tonic-gate #ifdef DEBUG 9597c478bd9Sstevel@tonic-gate { 9607c478bd9Sstevel@tonic-gate int brd; 9617c478bd9Sstevel@tonic-gate 9627c478bd9Sstevel@tonic-gate for (brd = 0; brd < MAX_BOARDS; brd++) 9637c478bd9Sstevel@tonic-gate if (loc_hw->dh_mcadr[brd] != 0) { 9647c478bd9Sstevel@tonic-gate PR_XF("%s: brd %d, mc = 0x%x\n", 9657c478bd9Sstevel@tonic-gate proc, brd, loc_hw->dh_mcadr[brd]); 9667c478bd9Sstevel@tonic-gate } 9677c478bd9Sstevel@tonic-gate } 9687c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 9697c478bd9Sstevel@tonic-gate 9707c478bd9Sstevel@tonic-gate if ((loc_hw->dh_boardset != domainset) || (loc_hw->dh_nmcadr < 1)) 9717c478bd9Sstevel@tonic-gate return (-1); 9727c478bd9Sstevel@tonic-gate else 9737c478bd9Sstevel@tonic-gate return (0); 9747c478bd9Sstevel@tonic-gate } 9757c478bd9Sstevel@tonic-gate 9767c478bd9Sstevel@tonic-gate /* 9777c478bd9Sstevel@tonic-gate * Function called via timeout() to wakeup a possibly stuck 9787c478bd9Sstevel@tonic-gate * idnxf_shmem_update_all() should not all cpus check-in after a 9797c478bd9Sstevel@tonic-gate * x-call to update their respective CICs. 9807c478bd9Sstevel@tonic-gate */ 9817c478bd9Sstevel@tonic-gate /*ARGSUSED0*/ 9827c478bd9Sstevel@tonic-gate static void 9837c478bd9Sstevel@tonic-gate idnxf_shmem_wakeup(void *arg) 9847c478bd9Sstevel@tonic-gate { 9857c478bd9Sstevel@tonic-gate struct idnxf_cic_info *idnxfp = (struct idnxf_cic_info *)arg; 9867c478bd9Sstevel@tonic-gate int count; 9877c478bd9Sstevel@tonic-gate int expired; 9887c478bd9Sstevel@tonic-gate procname_t proc = "idnxf_shmem_wakeup"; 9897c478bd9Sstevel@tonic-gate 990*d3d50737SRafael Vanoni expired = ((ddi_get_lbolt() - idnxfp->xf_start_time) >= 991*d3d50737SRafael Vanoni IDNCIC_TIMEOUT) ? 1 : 0; 9927c478bd9Sstevel@tonic-gate 9937c478bd9Sstevel@tonic-gate if ((count = idnxfp->xf_count) == 0) { 9947c478bd9Sstevel@tonic-gate /* 9957c478bd9Sstevel@tonic-gate * Everybody has finished. Wakeup the requester. 9967c478bd9Sstevel@tonic-gate */ 9977c478bd9Sstevel@tonic-gate mutex_enter(&idnxfp->xf_mutex); 9987c478bd9Sstevel@tonic-gate cv_signal(&idnxfp->xf_cv); 9997c478bd9Sstevel@tonic-gate mutex_exit(&idnxfp->xf_mutex); 10007c478bd9Sstevel@tonic-gate 10017c478bd9Sstevel@tonic-gate } else if ((count > 0) && expired) { 10027c478bd9Sstevel@tonic-gate /* 10037c478bd9Sstevel@tonic-gate * There are still active cic updaters and time 10047c478bd9Sstevel@tonic-gate * has expired. Bail on them. 10057c478bd9Sstevel@tonic-gate */ 10067c478bd9Sstevel@tonic-gate idnxfp->xf_errtimer = 1; 10077c478bd9Sstevel@tonic-gate #ifdef DEBUG 10087c478bd9Sstevel@tonic-gate /* 10097c478bd9Sstevel@tonic-gate * Special debug case since idn_debug 10107c478bd9Sstevel@tonic-gate * may have been temporarily cleared 10117c478bd9Sstevel@tonic-gate * during xc_some. 10127c478bd9Sstevel@tonic-gate */ 10137c478bd9Sstevel@tonic-gate if ((idn_debug | o_idn_debug) & IDNDBG_REGS) 10147c478bd9Sstevel@tonic-gate printf("%s: TIMEOUT...bailing on %d lost CIC " 10157c478bd9Sstevel@tonic-gate "updates...\n", proc, count); 10167c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 10177c478bd9Sstevel@tonic-gate 10187c478bd9Sstevel@tonic-gate ATOMIC_SUB(idnxfp->xf_count, count); 10197c478bd9Sstevel@tonic-gate 10207c478bd9Sstevel@tonic-gate mutex_enter(&idnxfp->xf_mutex); 10217c478bd9Sstevel@tonic-gate cv_signal(&idnxfp->xf_cv); 10227c478bd9Sstevel@tonic-gate mutex_exit(&idnxfp->xf_mutex); 10237c478bd9Sstevel@tonic-gate 10247c478bd9Sstevel@tonic-gate } else { 10257c478bd9Sstevel@tonic-gate (void) timeout(idnxf_shmem_wakeup, (caddr_t)idnxfp, 10267c478bd9Sstevel@tonic-gate (clock_t)IDNCIC_TIMECHK); 10277c478bd9Sstevel@tonic-gate } 10287c478bd9Sstevel@tonic-gate } 10297c478bd9Sstevel@tonic-gate 10307c478bd9Sstevel@tonic-gate /* 10317c478bd9Sstevel@tonic-gate * Called indirectly from idnxf_shmem_update_all() via a xcall 10327c478bd9Sstevel@tonic-gate * for the recepient cpu to update the CICs on its respective 10337c478bd9Sstevel@tonic-gate * board. 10347c478bd9Sstevel@tonic-gate * IMPORTANT: NO console output from this routine!! 10357c478bd9Sstevel@tonic-gate */ 10367c478bd9Sstevel@tonic-gate static void 10377c478bd9Sstevel@tonic-gate idnxf_shmem_update_one(uint64_t arg1, uint64_t arg2) 10387c478bd9Sstevel@tonic-gate { 10397c478bd9Sstevel@tonic-gate struct idnxf_cic_info *idnxfp = (struct idnxf_cic_info *)arg1; 10407c478bd9Sstevel@tonic-gate time_t start_time = (time_t)arg2; 10417c478bd9Sstevel@tonic-gate int rv, cpuid, brd, bus; 10427c478bd9Sstevel@tonic-gate boardset_t smmask; 10437c478bd9Sstevel@tonic-gate 10447c478bd9Sstevel@tonic-gate 10457c478bd9Sstevel@tonic-gate cpuid = CPU->cpu_id; 10467c478bd9Sstevel@tonic-gate brd = CPUID_TO_BOARDID(cpuid); 10477c478bd9Sstevel@tonic-gate 10487c478bd9Sstevel@tonic-gate if (idnxfp->xf_start_time != start_time) { 10497c478bd9Sstevel@tonic-gate /* 10507c478bd9Sstevel@tonic-gate * Ooops! Not my place to intrude. 10517c478bd9Sstevel@tonic-gate */ 10527c478bd9Sstevel@tonic-gate idnxf_cic_info.xf_errcic[brd][0] = IDNCIC_BUSY; 10537c478bd9Sstevel@tonic-gate ATOMIC_INC(idnxf_cic_info.xf_errcnt); 10547c478bd9Sstevel@tonic-gate 10557c478bd9Sstevel@tonic-gate goto done; 10567c478bd9Sstevel@tonic-gate } 10577c478bd9Sstevel@tonic-gate 10587c478bd9Sstevel@tonic-gate /* 10597c478bd9Sstevel@tonic-gate * We're executing out of the context of a cross-call 10607c478bd9Sstevel@tonic-gate * so we're effectively bound! :) 10617c478bd9Sstevel@tonic-gate */ 10627c478bd9Sstevel@tonic-gate for (bus = 0; bus < MAX_ABUSES; bus++) { 10637c478bd9Sstevel@tonic-gate /* 10647c478bd9Sstevel@tonic-gate * XXX - need to worry about shuffle?? 10657c478bd9Sstevel@tonic-gate */ 10667c478bd9Sstevel@tonic-gate if (!(idnxfp->xf_abus_mask & (1 << bus))) 10677c478bd9Sstevel@tonic-gate continue; 10687c478bd9Sstevel@tonic-gate smmask = cic_read_sm_mask(brd, bus); 10697c478bd9Sstevel@tonic-gate 10707c478bd9Sstevel@tonic-gate if (idnxfp->xf_doadd) { 10717c478bd9Sstevel@tonic-gate smmask |= idnxfp->xf_boardset; 10727c478bd9Sstevel@tonic-gate (void) cic_write_sm_mask(brd, bus, smmask); 10737c478bd9Sstevel@tonic-gate 10747c478bd9Sstevel@tonic-gate if (idnxfp->xf_smbase != (uint_t)-1) { 10757c478bd9Sstevel@tonic-gate (void) cic_write_sm_bar(brd, bus, 10767c478bd9Sstevel@tonic-gate idnxfp->xf_smbase); 10777c478bd9Sstevel@tonic-gate (void) cic_write_sm_lar(brd, bus, 10787c478bd9Sstevel@tonic-gate idnxfp->xf_smlimit); 10797c478bd9Sstevel@tonic-gate } 10807c478bd9Sstevel@tonic-gate /* 10817c478bd9Sstevel@tonic-gate * Verify data got there! 10827c478bd9Sstevel@tonic-gate */ 10837c478bd9Sstevel@tonic-gate rv = verify_smregs(brd, bus, smmask, idnxfp->xf_smbase, 10847c478bd9Sstevel@tonic-gate idnxfp->xf_smlimit); 10857c478bd9Sstevel@tonic-gate } else { 10867c478bd9Sstevel@tonic-gate smmask &= ~idnxfp->xf_boardset; 10877c478bd9Sstevel@tonic-gate (void) cic_write_sm_mask(brd, bus, smmask); 10887c478bd9Sstevel@tonic-gate 10897c478bd9Sstevel@tonic-gate if (!smmask) { 10907c478bd9Sstevel@tonic-gate /* 10917c478bd9Sstevel@tonic-gate * Update the LAR first so that we effectively 10927c478bd9Sstevel@tonic-gate * disable the register without possibly 10937c478bd9Sstevel@tonic-gate * opening the window to transaction we 10947c478bd9Sstevel@tonic-gate * don't care about. Updating the LAR first 10957c478bd9Sstevel@tonic-gate * will guarantee we effectively turn it 10967c478bd9Sstevel@tonic-gate * off immediately. 10977c478bd9Sstevel@tonic-gate */ 10987c478bd9Sstevel@tonic-gate (void) cic_write_sm_lar(brd, bus, 0); 10997c478bd9Sstevel@tonic-gate (void) cic_write_sm_bar(brd, bus, 1); 11007c478bd9Sstevel@tonic-gate 11017c478bd9Sstevel@tonic-gate rv = verify_smregs(brd, bus, smmask, 1, 0); 11027c478bd9Sstevel@tonic-gate } else { 11037c478bd9Sstevel@tonic-gate rv = verify_smregs(brd, bus, smmask, 11047c478bd9Sstevel@tonic-gate (uint_t)-1, (uint_t)-1); 11057c478bd9Sstevel@tonic-gate } 11067c478bd9Sstevel@tonic-gate } 11077c478bd9Sstevel@tonic-gate if (rv) { 11087c478bd9Sstevel@tonic-gate idnxf_cic_info.xf_errcic[brd][bus] = IDNCIC_ERR; 11097c478bd9Sstevel@tonic-gate ATOMIC_INC(idnxf_cic_info.xf_errcnt); 11107c478bd9Sstevel@tonic-gate } else { 11117c478bd9Sstevel@tonic-gate idnxf_cic_info.xf_errcic[brd][bus] = IDNCIC_OK; 11127c478bd9Sstevel@tonic-gate } 11137c478bd9Sstevel@tonic-gate } 11147c478bd9Sstevel@tonic-gate 11157c478bd9Sstevel@tonic-gate done: 11167c478bd9Sstevel@tonic-gate ATOMIC_DEC(idnxf_cic_info.xf_count); 11177c478bd9Sstevel@tonic-gate } 11187c478bd9Sstevel@tonic-gate 11197c478bd9Sstevel@tonic-gate static int 11207c478bd9Sstevel@tonic-gate idnxf_shmem_update_all(pda_handle_t ph, boardset_t boardset, 11217c478bd9Sstevel@tonic-gate uint_t smbase, uint_t smlimit, int doadd) 11227c478bd9Sstevel@tonic-gate { 11237c478bd9Sstevel@tonic-gate cpuset_t target_cpuset; 11247c478bd9Sstevel@tonic-gate int target_count; 11257c478bd9Sstevel@tonic-gate int rv = 0; 11267c478bd9Sstevel@tonic-gate int c, brd, bus; 11277c478bd9Sstevel@tonic-gate short abus_mask; 11287c478bd9Sstevel@tonic-gate time_t start_time; 11297c478bd9Sstevel@tonic-gate procname_t proc = "idnxf_shmem_update_all"; 11307c478bd9Sstevel@tonic-gate 11317c478bd9Sstevel@tonic-gate 11327c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&idn_xf_mutex)); 11337c478bd9Sstevel@tonic-gate 11347c478bd9Sstevel@tonic-gate pda_get_busmask(ph, &abus_mask, NULL); 11357c478bd9Sstevel@tonic-gate 11367c478bd9Sstevel@tonic-gate CPUSET_ZERO(target_cpuset); 11377c478bd9Sstevel@tonic-gate target_count = 0; 11387c478bd9Sstevel@tonic-gate /* 11397c478bd9Sstevel@tonic-gate * Build a cpuset of target cpus (one per board) to 11407c478bd9Sstevel@tonic-gate * be used to send the CIC update xcall. 11417c478bd9Sstevel@tonic-gate */ 11427c478bd9Sstevel@tonic-gate for (brd = 0; brd < MAX_BOARDS; brd++) { 11437c478bd9Sstevel@tonic-gate /* 11447c478bd9Sstevel@tonic-gate * Need to target an available cpu on the target board 11457c478bd9Sstevel@tonic-gate * so that we can look at the CICs on that board. 11467c478bd9Sstevel@tonic-gate */ 11477c478bd9Sstevel@tonic-gate c = board_to_ready_cpu(brd, cpu_ready_set); 11487c478bd9Sstevel@tonic-gate 11497c478bd9Sstevel@tonic-gate if (c == -1) { 11507c478bd9Sstevel@tonic-gate /* 11517c478bd9Sstevel@tonic-gate * If there's no cpu on this board, no 11527c478bd9Sstevel@tonic-gate * need to update the CICs. 11537c478bd9Sstevel@tonic-gate */ 11547c478bd9Sstevel@tonic-gate continue; 11557c478bd9Sstevel@tonic-gate } 11567c478bd9Sstevel@tonic-gate CPUSET_ADD(target_cpuset, c); 11577c478bd9Sstevel@tonic-gate target_count++; 11587c478bd9Sstevel@tonic-gate } 11597c478bd9Sstevel@tonic-gate 11607c478bd9Sstevel@tonic-gate if (CPUSET_ISNULL(target_cpuset)) { 11617c478bd9Sstevel@tonic-gate PR_REGS("%s: NO target cpus to update!!\n", proc); 11627c478bd9Sstevel@tonic-gate return (0); 11637c478bd9Sstevel@tonic-gate } 11647c478bd9Sstevel@tonic-gate 11657c478bd9Sstevel@tonic-gate RESET_CIC_HISTORY(); 11667c478bd9Sstevel@tonic-gate 11677c478bd9Sstevel@tonic-gate /* 11687c478bd9Sstevel@tonic-gate * Broadcast out the CIC update request and then 11697c478bd9Sstevel@tonic-gate * sit back and wait for dinner to arrive! 11707c478bd9Sstevel@tonic-gate * Let's set up the global structure all the xcall 11717c478bd9Sstevel@tonic-gate * recepients will read. 11727c478bd9Sstevel@tonic-gate */ 1173*d3d50737SRafael Vanoni start_time = ddi_get_lbolt(); 11747c478bd9Sstevel@tonic-gate /* 11757c478bd9Sstevel@tonic-gate * Set the start time. Make sure it's different 11767c478bd9Sstevel@tonic-gate * then the previous run. 11777c478bd9Sstevel@tonic-gate */ 11787c478bd9Sstevel@tonic-gate if (start_time <= idnxf_cic_info.xf_start_time) 11797c478bd9Sstevel@tonic-gate start_time++; 11807c478bd9Sstevel@tonic-gate idnxf_cic_info.xf_start_time = start_time; 11817c478bd9Sstevel@tonic-gate 11827c478bd9Sstevel@tonic-gate idnxf_cic_info.xf_abus_mask = abus_mask; 11837c478bd9Sstevel@tonic-gate idnxf_cic_info.xf_boardset = boardset; 11847c478bd9Sstevel@tonic-gate idnxf_cic_info.xf_smbase = smbase; 11857c478bd9Sstevel@tonic-gate idnxf_cic_info.xf_smlimit = smlimit; 11867c478bd9Sstevel@tonic-gate idnxf_cic_info.xf_doadd = doadd; 11877c478bd9Sstevel@tonic-gate idnxf_cic_info.xf_count = target_count; 11887c478bd9Sstevel@tonic-gate idnxf_cic_info.xf_errcnt = 0; 11897c478bd9Sstevel@tonic-gate idnxf_cic_info.xf_errtimer = 0; 11907c478bd9Sstevel@tonic-gate bzero(&idnxf_cic_info.xf_errcic, sizeof (idnxf_cic_info.xf_errcic)); 11917c478bd9Sstevel@tonic-gate 11927c478bd9Sstevel@tonic-gate /* 11937c478bd9Sstevel@tonic-gate * Broadcast out the xcall to do the task. 11947c478bd9Sstevel@tonic-gate */ 11957c478bd9Sstevel@tonic-gate #ifdef DEBUG 11967c478bd9Sstevel@tonic-gate { 11977c478bd9Sstevel@tonic-gate uint_t tu32, tl32; 11987c478bd9Sstevel@tonic-gate 11997c478bd9Sstevel@tonic-gate tu32 = UPPER32_CPUMASK(target_cpuset); 12007c478bd9Sstevel@tonic-gate tl32 = LOWER32_CPUMASK(target_cpuset); 12017c478bd9Sstevel@tonic-gate PR_REGS("%s: (start %ld) broadcasting CIC - " 12027c478bd9Sstevel@tonic-gate "%s to cpus 0x%x.%0x\n", 12037c478bd9Sstevel@tonic-gate proc, start_time, doadd ? "LINK" : "UNLINK", 12047c478bd9Sstevel@tonic-gate tu32, tl32); 12057c478bd9Sstevel@tonic-gate } 12067c478bd9Sstevel@tonic-gate 12077c478bd9Sstevel@tonic-gate /* 12087c478bd9Sstevel@tonic-gate * Can't dump debug during cross-calls. 12097c478bd9Sstevel@tonic-gate */ 12107c478bd9Sstevel@tonic-gate o_idn_debug = idn_debug; 12117c478bd9Sstevel@tonic-gate idn_debug = 0; 12127c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 12137c478bd9Sstevel@tonic-gate 12147c478bd9Sstevel@tonic-gate xc_attention(target_cpuset); 12157c478bd9Sstevel@tonic-gate 12167c478bd9Sstevel@tonic-gate xc_some(target_cpuset, idnxf_shmem_update_one, 12177c478bd9Sstevel@tonic-gate (uint64_t)&idnxf_cic_info, (uint64_t)start_time); 12187c478bd9Sstevel@tonic-gate 12197c478bd9Sstevel@tonic-gate xc_dismissed(target_cpuset); 12207c478bd9Sstevel@tonic-gate 12217c478bd9Sstevel@tonic-gate ASSERT(idnxf_cic_info.xf_count == 0); 12227c478bd9Sstevel@tonic-gate 12237c478bd9Sstevel@tonic-gate #ifdef DEBUG 12247c478bd9Sstevel@tonic-gate idn_debug = o_idn_debug; 12257c478bd9Sstevel@tonic-gate o_idn_debug = 0; 12267c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 12277c478bd9Sstevel@tonic-gate 12287c478bd9Sstevel@tonic-gate PR_REGS("%s: waiting for completion of %d CIC - %s...\n", 12297c478bd9Sstevel@tonic-gate proc, idnxf_cic_info.xf_count, doadd ? "LINKS" : "UNLINKS"); 12307c478bd9Sstevel@tonic-gate PR_REGS("%s: CIC - %s have checked IN.\n", 12317c478bd9Sstevel@tonic-gate proc, doadd ? "LINKS" : "UNLINKS"); 12327c478bd9Sstevel@tonic-gate 12337c478bd9Sstevel@tonic-gate /* 12347c478bd9Sstevel@tonic-gate * Modifying xf_start_time effectively disables any 12357c478bd9Sstevel@tonic-gate * possible outstanding xcall's since they don't touch 12367c478bd9Sstevel@tonic-gate * idnxf_cic_info unless their given start_time matches 12377c478bd9Sstevel@tonic-gate * that in the idnxf_cic_info structure. 12387c478bd9Sstevel@tonic-gate */ 12397c478bd9Sstevel@tonic-gate idnxf_cic_info.xf_start_time++; 12407c478bd9Sstevel@tonic-gate 12417c478bd9Sstevel@tonic-gate PR_REGS("%s: xf_errcnt = %d, xf_errtimer = %d\n", 12427c478bd9Sstevel@tonic-gate proc, idnxf_cic_info.xf_errcnt, idnxf_cic_info.xf_errtimer); 12437c478bd9Sstevel@tonic-gate DUMP_CIC_HISTORY(); 12447c478bd9Sstevel@tonic-gate /* 12457c478bd9Sstevel@tonic-gate * Should errors be fatal? (panic). 12467c478bd9Sstevel@tonic-gate */ 12477c478bd9Sstevel@tonic-gate rv = 0; 12487c478bd9Sstevel@tonic-gate for (c = 0; c < NCPU; c++) { 12497c478bd9Sstevel@tonic-gate if (!CPU_IN_SET(target_cpuset, c)) 12507c478bd9Sstevel@tonic-gate continue; 12517c478bd9Sstevel@tonic-gate brd = CPUID_TO_BOARDID(c); 12527c478bd9Sstevel@tonic-gate 12537c478bd9Sstevel@tonic-gate for (bus = 0; bus < MAX_ABUSES; bus++) { 12547c478bd9Sstevel@tonic-gate 12557c478bd9Sstevel@tonic-gate if (!(abus_mask & (1 << bus))) 12567c478bd9Sstevel@tonic-gate continue; 12577c478bd9Sstevel@tonic-gate 12587c478bd9Sstevel@tonic-gate switch (idnxf_cic_info.xf_errcic[brd][bus]) { 12597c478bd9Sstevel@tonic-gate case IDNCIC_UNKNOWN: 12607c478bd9Sstevel@tonic-gate /* 12617c478bd9Sstevel@tonic-gate * Unknown is only an error if the 12627c478bd9Sstevel@tonic-gate * timer expired. 12637c478bd9Sstevel@tonic-gate */ 12647c478bd9Sstevel@tonic-gate if (!idnxf_cic_info.xf_errtimer) 12657c478bd9Sstevel@tonic-gate break; 12667c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 12677c478bd9Sstevel@tonic-gate "IDN: 509: CPU %d never responded " 12687c478bd9Sstevel@tonic-gate "to CIC update", c); 12697c478bd9Sstevel@tonic-gate /*FALLTHROUGH*/ 12707c478bd9Sstevel@tonic-gate 12717c478bd9Sstevel@tonic-gate case IDNCIC_ERR: 12727c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 12737c478bd9Sstevel@tonic-gate "IDN: 510: failed write-smregs " 12747c478bd9Sstevel@tonic-gate "(bd=%d, bs=%d, sm(bar=0x%x, " 12757c478bd9Sstevel@tonic-gate "lar=0x%x))", 12767c478bd9Sstevel@tonic-gate brd, bus, smbase, smlimit); 12777c478bd9Sstevel@tonic-gate rv++; 12787c478bd9Sstevel@tonic-gate break; 12797c478bd9Sstevel@tonic-gate 12807c478bd9Sstevel@tonic-gate case IDNCIC_BUSY: 12817c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "IDN: 511: update-one " 12827c478bd9Sstevel@tonic-gate "(cpu=%d, bd=%d) time conflict", 12837c478bd9Sstevel@tonic-gate c, brd); 12847c478bd9Sstevel@tonic-gate /* 12857c478bd9Sstevel@tonic-gate * Should never occur. Not fatal, 12867c478bd9Sstevel@tonic-gate * just continue. 12877c478bd9Sstevel@tonic-gate */ 12887c478bd9Sstevel@tonic-gate break; 12897c478bd9Sstevel@tonic-gate 12907c478bd9Sstevel@tonic-gate default: 12917c478bd9Sstevel@tonic-gate PR_REGS("%s: board %d, bus %d " 12927c478bd9Sstevel@tonic-gate "(bar=0x%x,lar=0x%x) - update OK\n", 12937c478bd9Sstevel@tonic-gate proc, brd, bus, smbase, smlimit); 12947c478bd9Sstevel@tonic-gate break; 12957c478bd9Sstevel@tonic-gate } 12967c478bd9Sstevel@tonic-gate } 12977c478bd9Sstevel@tonic-gate } 12987c478bd9Sstevel@tonic-gate 12997c478bd9Sstevel@tonic-gate return (rv ? -1 : 0); 13007c478bd9Sstevel@tonic-gate } 13017c478bd9Sstevel@tonic-gate 13027c478bd9Sstevel@tonic-gate /* 13037c478bd9Sstevel@tonic-gate * Add the respective boardset/base/limit/mcadr's to the local 13047c478bd9Sstevel@tonic-gate * domain's hardware configuration with respect to the SMR. 13057c478bd9Sstevel@tonic-gate * 13067c478bd9Sstevel@tonic-gate * is_master Indicates remote domain is a master. 13077c478bd9Sstevel@tonic-gate */ 13087c478bd9Sstevel@tonic-gate int 1309*d3d50737SRafael Vanoni idnxf_shmem_add(int is_master, boardset_t boardset, pfn_t pfnbase, 1310*d3d50737SRafael Vanoni pfn_t pfnlimit, uint_t *mcadr) 13117c478bd9Sstevel@tonic-gate { 13127c478bd9Sstevel@tonic-gate int rv = 0; 13137c478bd9Sstevel@tonic-gate register int brd, rbrd; 13147c478bd9Sstevel@tonic-gate register boardset_t localboardset; 13157c478bd9Sstevel@tonic-gate uint_t madr; 13167c478bd9Sstevel@tonic-gate uint_t smbase, smlimit; 13177c478bd9Sstevel@tonic-gate pda_handle_t ph; 13187c478bd9Sstevel@tonic-gate procname_t proc = "idnxf_shmem_add"; 13197c478bd9Sstevel@tonic-gate 13207c478bd9Sstevel@tonic-gate 13217c478bd9Sstevel@tonic-gate localboardset = idn_domain[idn.localid].dhw.dh_boardset; 13227c478bd9Sstevel@tonic-gate 13237c478bd9Sstevel@tonic-gate ASSERT(localboardset && boardset && ((localboardset & boardset) == 0)); 13247c478bd9Sstevel@tonic-gate ASSERT(is_master ? (pfnbase && pfnlimit && mcadr) : 1); 13257c478bd9Sstevel@tonic-gate 13267c478bd9Sstevel@tonic-gate if (pfnbase != PFN_INVALID) { 13277c478bd9Sstevel@tonic-gate smbase = (uint_t)PFN_TO_SMADDR(pfnbase); 13287c478bd9Sstevel@tonic-gate smlimit = (uint_t)PFN_TO_SMADDR(pfnlimit); 13297c478bd9Sstevel@tonic-gate } else { 13307c478bd9Sstevel@tonic-gate smbase = smlimit = (uint_t)-1; 13317c478bd9Sstevel@tonic-gate } 13327c478bd9Sstevel@tonic-gate PR_REGS("%s: is_master=%d, boardset=0x%x, smbase=0x%x, smlimit=%x\n", 13337c478bd9Sstevel@tonic-gate proc, is_master, boardset, smbase, smlimit); 13347c478bd9Sstevel@tonic-gate 13357c478bd9Sstevel@tonic-gate /* 13367c478bd9Sstevel@tonic-gate * Need to serialize hardware access so we don't have multiple 13377c478bd9Sstevel@tonic-gate * threads attempting to access hardware regs simulataneously. 13387c478bd9Sstevel@tonic-gate * This should not be a significant performance penalty since 13397c478bd9Sstevel@tonic-gate * the hardware is only touched when domains are linking or 13407c478bd9Sstevel@tonic-gate * unlinking. 13417c478bd9Sstevel@tonic-gate */ 13427c478bd9Sstevel@tonic-gate mutex_enter(&idn_xf_mutex); 13437c478bd9Sstevel@tonic-gate 13447c478bd9Sstevel@tonic-gate /* 13457c478bd9Sstevel@tonic-gate * Map in the post2obp structure so we can find 13467c478bd9Sstevel@tonic-gate * bus config information. 13477c478bd9Sstevel@tonic-gate */ 13487c478bd9Sstevel@tonic-gate ph = pda_open(); 13497c478bd9Sstevel@tonic-gate if (ph == (pda_handle_t)NULL) { 13507c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 13517c478bd9Sstevel@tonic-gate "IDN: 507: failed to map-in post2obp structure"); 13527c478bd9Sstevel@tonic-gate rv = -1; 13537c478bd9Sstevel@tonic-gate goto done; 13547c478bd9Sstevel@tonic-gate 13557c478bd9Sstevel@tonic-gate } else if (!pda_is_valid(ph)) { 13567c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "IDN: 508: post2obp checksum invalid"); 13577c478bd9Sstevel@tonic-gate rv = -1; 13587c478bd9Sstevel@tonic-gate goto done; 13597c478bd9Sstevel@tonic-gate } 13607c478bd9Sstevel@tonic-gate /* 13617c478bd9Sstevel@tonic-gate * Take a checkpoint in bbsram for diagnostic purposes. 13627c478bd9Sstevel@tonic-gate */ 13637c478bd9Sstevel@tonic-gate CHECKPOINT_OPENED(IDNSB_CHKPT_SMR, boardset, 1); 13647c478bd9Sstevel@tonic-gate 13657c478bd9Sstevel@tonic-gate rv = idnxf_shmem_update_all(ph, boardset, smbase, smlimit, 1); 13667c478bd9Sstevel@tonic-gate 13677c478bd9Sstevel@tonic-gate if (rv || (is_master == 0)) 13687c478bd9Sstevel@tonic-gate goto done; 13697c478bd9Sstevel@tonic-gate 13707c478bd9Sstevel@tonic-gate /* 13717c478bd9Sstevel@tonic-gate * If this is a slave (i.e. remote domain is_master), 13727c478bd9Sstevel@tonic-gate * then we need to deprogram our PCs. 13737c478bd9Sstevel@tonic-gate */ 13747c478bd9Sstevel@tonic-gate PR_REGS("%s: updating PC regs (lboardset=0x%x, rboardset=0x%x)\n", 13757c478bd9Sstevel@tonic-gate proc, localboardset, boardset); 13767c478bd9Sstevel@tonic-gate 13777c478bd9Sstevel@tonic-gate for (brd = 0; brd < MAX_BOARDS; brd++) { 13787c478bd9Sstevel@tonic-gate 13797c478bd9Sstevel@tonic-gate if (!BOARD_IN_SET(localboardset, brd)) 13807c478bd9Sstevel@tonic-gate continue; 13817c478bd9Sstevel@tonic-gate /* 13827c478bd9Sstevel@tonic-gate * If this is a slave (i.e. remote domain is_master), 13837c478bd9Sstevel@tonic-gate * then we need to program our PCs. 13847c478bd9Sstevel@tonic-gate */ 13857c478bd9Sstevel@tonic-gate for (rbrd = 0; rbrd < MAX_BOARDS; rbrd++) { 13867c478bd9Sstevel@tonic-gate 13877c478bd9Sstevel@tonic-gate if ((madr = mcadr[rbrd]) == 0) 13887c478bd9Sstevel@tonic-gate continue; 13897c478bd9Sstevel@tonic-gate 13907c478bd9Sstevel@tonic-gate ASSERT(BOARD_IN_SET(boardset, rbrd)); 13917c478bd9Sstevel@tonic-gate /* 13927c478bd9Sstevel@tonic-gate * Write the MC adr for the respective 13937c478bd9Sstevel@tonic-gate * remote board (rbrd) into the PCs of 13947c478bd9Sstevel@tonic-gate * the given local board (brd). 13957c478bd9Sstevel@tonic-gate */ 13967c478bd9Sstevel@tonic-gate if (pc_write_madr(ph, brd, rbrd, madr) < 0) { 13977c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 13987c478bd9Sstevel@tonic-gate "IDN: 512: failed [add] write-madr " 13997c478bd9Sstevel@tonic-gate "(bd=%d, rbd=%d, madr=0x%x)", 14007c478bd9Sstevel@tonic-gate brd, rbrd, madr); 14017c478bd9Sstevel@tonic-gate rv = -1; 14027c478bd9Sstevel@tonic-gate goto done; 14037c478bd9Sstevel@tonic-gate } 14047c478bd9Sstevel@tonic-gate } 14057c478bd9Sstevel@tonic-gate } 14067c478bd9Sstevel@tonic-gate 14077c478bd9Sstevel@tonic-gate done: 14087c478bd9Sstevel@tonic-gate if (ph) 14097c478bd9Sstevel@tonic-gate pda_close(ph); 14107c478bd9Sstevel@tonic-gate 14117c478bd9Sstevel@tonic-gate mutex_exit(&idn_xf_mutex); 14127c478bd9Sstevel@tonic-gate /* 14137c478bd9Sstevel@tonic-gate * XXX 14147c478bd9Sstevel@tonic-gate * 14157c478bd9Sstevel@tonic-gate * Failure here is fatal. Disable IDN? 14167c478bd9Sstevel@tonic-gate * NOn-zero return value will at least prevent 14177c478bd9Sstevel@tonic-gate * linkage with domain - probably sufficient. 14187c478bd9Sstevel@tonic-gate */ 14197c478bd9Sstevel@tonic-gate return (rv); 14207c478bd9Sstevel@tonic-gate } 14217c478bd9Sstevel@tonic-gate 14227c478bd9Sstevel@tonic-gate /* 14237c478bd9Sstevel@tonic-gate * Remove the respective boardset from the local domain's 14247c478bd9Sstevel@tonic-gate * hardware configuration with respect to the SMR. 14257c478bd9Sstevel@tonic-gate * 14267c478bd9Sstevel@tonic-gate * is_master Indicates remote domain is a master. 14277c478bd9Sstevel@tonic-gate */ 14287c478bd9Sstevel@tonic-gate int 14297c478bd9Sstevel@tonic-gate idnxf_shmem_sub(int is_master, boardset_t boardset) 14307c478bd9Sstevel@tonic-gate { 14317c478bd9Sstevel@tonic-gate int rv = 0; 14327c478bd9Sstevel@tonic-gate register int brd, rbrd; 14337c478bd9Sstevel@tonic-gate register boardset_t localboardset; 14347c478bd9Sstevel@tonic-gate pda_handle_t ph; 14357c478bd9Sstevel@tonic-gate procname_t proc = "idnxf_shmem_sub"; 14367c478bd9Sstevel@tonic-gate 14377c478bd9Sstevel@tonic-gate localboardset = idn_domain[idn.localid].dhw.dh_boardset; 14387c478bd9Sstevel@tonic-gate 14397c478bd9Sstevel@tonic-gate ASSERT(localboardset && boardset && ((localboardset & boardset) == 0)); 14407c478bd9Sstevel@tonic-gate 14417c478bd9Sstevel@tonic-gate PR_REGS("%s: is_master=%d, boardset=0x%x\n", 14427c478bd9Sstevel@tonic-gate proc, is_master, boardset); 14437c478bd9Sstevel@tonic-gate 14447c478bd9Sstevel@tonic-gate /* 14457c478bd9Sstevel@tonic-gate * Need to serialize hardware access so we don't have multiple 14467c478bd9Sstevel@tonic-gate * threads attempting to access hardware regs simulataneously. 14477c478bd9Sstevel@tonic-gate * This should not be a significant performance penalty since 14487c478bd9Sstevel@tonic-gate * the hardware is only touched when domains are linking or 14497c478bd9Sstevel@tonic-gate * unlinking. 14507c478bd9Sstevel@tonic-gate */ 14517c478bd9Sstevel@tonic-gate mutex_enter(&idn_xf_mutex); 14527c478bd9Sstevel@tonic-gate 14537c478bd9Sstevel@tonic-gate /* 14547c478bd9Sstevel@tonic-gate * Map in the post2obp structure so we can find 14557c478bd9Sstevel@tonic-gate * bus config information. 14567c478bd9Sstevel@tonic-gate */ 14577c478bd9Sstevel@tonic-gate ph = pda_open(); 14587c478bd9Sstevel@tonic-gate if (ph == (pda_handle_t)NULL) { 14597c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 14607c478bd9Sstevel@tonic-gate "IDN: 507: failed to map-in post2obp structure"); 14617c478bd9Sstevel@tonic-gate rv = -1; 14627c478bd9Sstevel@tonic-gate goto done; 14637c478bd9Sstevel@tonic-gate 14647c478bd9Sstevel@tonic-gate } else if (!pda_is_valid(ph)) { 14657c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "IDN: 508: post2obp checksum invalid"); 14667c478bd9Sstevel@tonic-gate rv = -1; 14677c478bd9Sstevel@tonic-gate goto done; 14687c478bd9Sstevel@tonic-gate } 14697c478bd9Sstevel@tonic-gate /* 14707c478bd9Sstevel@tonic-gate * Take a checkpoint in bbsram for diagnostic purposes. 14717c478bd9Sstevel@tonic-gate */ 14727c478bd9Sstevel@tonic-gate CHECKPOINT_CLOSED(IDNSB_CHKPT_SMR, boardset, 2); 14737c478bd9Sstevel@tonic-gate 14747c478bd9Sstevel@tonic-gate rv = idnxf_shmem_update_all(ph, boardset, (uint_t)-1, (uint_t)-1, 0); 14757c478bd9Sstevel@tonic-gate 14767c478bd9Sstevel@tonic-gate if (rv || (is_master == 0)) 14777c478bd9Sstevel@tonic-gate goto done; 14787c478bd9Sstevel@tonic-gate 14797c478bd9Sstevel@tonic-gate /* 14807c478bd9Sstevel@tonic-gate * If this is a slave (i.e. remote domain is_master), 14817c478bd9Sstevel@tonic-gate * then we need to deprogram our PCs. 14827c478bd9Sstevel@tonic-gate */ 14837c478bd9Sstevel@tonic-gate PR_REGS("%s: reseting PC regs (lboardset=0x%x, rboardset=0x%x)\n", 14847c478bd9Sstevel@tonic-gate proc, localboardset, boardset); 14857c478bd9Sstevel@tonic-gate 14867c478bd9Sstevel@tonic-gate for (brd = 0; brd < MAX_BOARDS; brd++) { 14877c478bd9Sstevel@tonic-gate 14887c478bd9Sstevel@tonic-gate if (!BOARD_IN_SET(localboardset, brd)) 14897c478bd9Sstevel@tonic-gate continue; 14907c478bd9Sstevel@tonic-gate 14917c478bd9Sstevel@tonic-gate for (rbrd = 0; rbrd < MAX_BOARDS; rbrd++) { 14927c478bd9Sstevel@tonic-gate 14937c478bd9Sstevel@tonic-gate if (!BOARD_IN_SET(boardset, rbrd)) 14947c478bd9Sstevel@tonic-gate continue; 14957c478bd9Sstevel@tonic-gate /* 14967c478bd9Sstevel@tonic-gate * Clear the MC adr for the respective 14977c478bd9Sstevel@tonic-gate * remote board (rbrd) into the PCs of 14987c478bd9Sstevel@tonic-gate * the given local board (brd). 14997c478bd9Sstevel@tonic-gate */ 15007c478bd9Sstevel@tonic-gate if (pc_write_madr(ph, brd, rbrd, 0) < 0) { 15017c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 15027c478bd9Sstevel@tonic-gate "IDN: 512: failed [del] write-madr " 15037c478bd9Sstevel@tonic-gate "(bd=%d, rbd=%d, madr=0x%x)", 15047c478bd9Sstevel@tonic-gate brd, rbrd, 0); 15057c478bd9Sstevel@tonic-gate rv = -1; 15067c478bd9Sstevel@tonic-gate goto done; 15077c478bd9Sstevel@tonic-gate } 15087c478bd9Sstevel@tonic-gate } 15097c478bd9Sstevel@tonic-gate } 15107c478bd9Sstevel@tonic-gate 15117c478bd9Sstevel@tonic-gate done: 15127c478bd9Sstevel@tonic-gate if (ph) 15137c478bd9Sstevel@tonic-gate pda_close(ph); 15147c478bd9Sstevel@tonic-gate mutex_exit(&idn_xf_mutex); 15157c478bd9Sstevel@tonic-gate 15167c478bd9Sstevel@tonic-gate return (rv); 15177c478bd9Sstevel@tonic-gate } 15187c478bd9Sstevel@tonic-gate 15197c478bd9Sstevel@tonic-gate /* 15207c478bd9Sstevel@tonic-gate * We cannot cross-trap cpu_flush_ecache since it references 15217c478bd9Sstevel@tonic-gate * %g7 via CPU. It's possible that %g7 may not be set up 15227c478bd9Sstevel@tonic-gate * when the trap comes in, and could thus cause a crash. 15237c478bd9Sstevel@tonic-gate * Well...at least that's what has been happening when I 15247c478bd9Sstevel@tonic-gate * tried x-calls within an xc_attention (KMISS) panic. 15257c478bd9Sstevel@tonic-gate * Instead we use cross-calls. However, since we can't 15267c478bd9Sstevel@tonic-gate * xc_attention around a cross-call, we have not guaranteed 15277c478bd9Sstevel@tonic-gate * way of knowing the operation succeeded. To synchronize 15287c478bd9Sstevel@tonic-gate * this flush operation across cpus, we use a semaphore 15297c478bd9Sstevel@tonic-gate * which is V'd by the receiving cpus and P'd by the caller 15307c478bd9Sstevel@tonic-gate * initiating the all-cpus flush. 15317c478bd9Sstevel@tonic-gate */ 15327c478bd9Sstevel@tonic-gate /*ARGSUSED0*/ 15337c478bd9Sstevel@tonic-gate void 15347c478bd9Sstevel@tonic-gate idn_flush_ecache(uint64_t arg1, uint64_t arg2) 15357c478bd9Sstevel@tonic-gate { 15367c478bd9Sstevel@tonic-gate extern void cpu_flush_ecache(void); 15377c478bd9Sstevel@tonic-gate 15387c478bd9Sstevel@tonic-gate cpu_flush_ecache(); 15397c478bd9Sstevel@tonic-gate /* 15407c478bd9Sstevel@tonic-gate * Paranoia...Give things a chance to drain. 15417c478bd9Sstevel@tonic-gate */ 15427c478bd9Sstevel@tonic-gate drv_usecwait(500000); /* 500 msec */ 15437c478bd9Sstevel@tonic-gate } 15447c478bd9Sstevel@tonic-gate /* 15457c478bd9Sstevel@tonic-gate * Flush the ecache's of all the cpus within this domain of 15467c478bd9Sstevel@tonic-gate * any possible SMR references. 15477c478bd9Sstevel@tonic-gate * This logic is borrowed from ecc.c:cpu_flush_ecache(). 15487c478bd9Sstevel@tonic-gate */ 15497c478bd9Sstevel@tonic-gate void 15507c478bd9Sstevel@tonic-gate idnxf_flushall_ecache() 15517c478bd9Sstevel@tonic-gate { 15527c478bd9Sstevel@tonic-gate cpuset_t local_cpuset; 15537c478bd9Sstevel@tonic-gate procname_t proc = "idnxf_flushall_ecache"; 15547c478bd9Sstevel@tonic-gate 15557c478bd9Sstevel@tonic-gate 1556*d3d50737SRafael Vanoni PR_XF("%s: flushing ecache (cpu_ready_set = 0x%x.%x)\n", proc, 1557*d3d50737SRafael Vanoni UPPER32_CPUMASK(cpu_ready_set), LOWER32_CPUMASK(cpu_ready_set)); 15587c478bd9Sstevel@tonic-gate 15597c478bd9Sstevel@tonic-gate CHECKPOINT_CACHE_CLEAR_DEBUG(1); 15607c478bd9Sstevel@tonic-gate CHECKPOINT_CACHE_STEP_DEBUG(0x1, 2); 15617c478bd9Sstevel@tonic-gate 15627c478bd9Sstevel@tonic-gate local_cpuset = cpu_ready_set; 15637c478bd9Sstevel@tonic-gate 15647c478bd9Sstevel@tonic-gate xc_attention(local_cpuset); 15657c478bd9Sstevel@tonic-gate 15667c478bd9Sstevel@tonic-gate /* 15677c478bd9Sstevel@tonic-gate * We tell each cpu to do a flush and then we hit 15687c478bd9Sstevel@tonic-gate * a semaphore to synchronize with all of them 15697c478bd9Sstevel@tonic-gate * to guarantee they have completed the flush before 15707c478bd9Sstevel@tonic-gate * we continue on. We have to do this type of 15717c478bd9Sstevel@tonic-gate * sychronization since we can't xc_attention around 15727c478bd9Sstevel@tonic-gate * a cross-call. 15737c478bd9Sstevel@tonic-gate */ 15747c478bd9Sstevel@tonic-gate CHECKPOINT_CACHE_STEP_DEBUG(0x2, 3); 15757c478bd9Sstevel@tonic-gate 15767c478bd9Sstevel@tonic-gate xc_all(idn_flush_ecache, 0, 0); 15777c478bd9Sstevel@tonic-gate 15787c478bd9Sstevel@tonic-gate CHECKPOINT_CACHE_STEP_DEBUG(0x4, 4); 15797c478bd9Sstevel@tonic-gate 15807c478bd9Sstevel@tonic-gate xc_dismissed(local_cpuset); 15817c478bd9Sstevel@tonic-gate 15827c478bd9Sstevel@tonic-gate CHECKPOINT_CACHE_STEP_DEBUG(0x8, 5); 15837c478bd9Sstevel@tonic-gate } 15847c478bd9Sstevel@tonic-gate 15857c478bd9Sstevel@tonic-gate /* 15867c478bd9Sstevel@tonic-gate * -------------------------------------------------- 15877c478bd9Sstevel@tonic-gate */ 15887c478bd9Sstevel@tonic-gate static int 1589*d3d50737SRafael Vanoni verify_smregs(int brd, int bus, boardset_t smmask, uint_t smbase, uint_t 1590*d3d50737SRafael Vanoni smlimit) 15917c478bd9Sstevel@tonic-gate { 15927c478bd9Sstevel@tonic-gate int rv = 0; 15937c478bd9Sstevel@tonic-gate uint_t smreg; 15947c478bd9Sstevel@tonic-gate 15957c478bd9Sstevel@tonic-gate if (smmask != (boardset_t)-1) { 15967c478bd9Sstevel@tonic-gate smreg = (uint_t)cic_read_sm_mask(brd, bus); 15977c478bd9Sstevel@tonic-gate if (smreg != (uint_t)smmask) { 15987c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 15997c478bd9Sstevel@tonic-gate "IDN: 513: sm-mask error " 16007c478bd9Sstevel@tonic-gate "(expected = 0x%x, actual = 0x%x)", 16017c478bd9Sstevel@tonic-gate (uint_t)smmask, smreg); 16027c478bd9Sstevel@tonic-gate rv++; 16037c478bd9Sstevel@tonic-gate } 16047c478bd9Sstevel@tonic-gate } 16057c478bd9Sstevel@tonic-gate 16067c478bd9Sstevel@tonic-gate if (smbase != (uint_t)-1) { 16077c478bd9Sstevel@tonic-gate smreg = cic_read_sm_bar(brd, bus); 16087c478bd9Sstevel@tonic-gate if (smreg != smbase) { 16097c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 16107c478bd9Sstevel@tonic-gate "IDN: 514: sm-base error " 16117c478bd9Sstevel@tonic-gate "(expected = 0x%x, actual = 0x%x)", 16127c478bd9Sstevel@tonic-gate smbase, smreg); 16137c478bd9Sstevel@tonic-gate rv++; 16147c478bd9Sstevel@tonic-gate } 16157c478bd9Sstevel@tonic-gate } 16167c478bd9Sstevel@tonic-gate 16177c478bd9Sstevel@tonic-gate if (smlimit != (uint_t)-1) { 16187c478bd9Sstevel@tonic-gate smreg = cic_read_sm_lar(brd, bus); 16197c478bd9Sstevel@tonic-gate if (smreg != smlimit) { 16207c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 16217c478bd9Sstevel@tonic-gate "IDN: 515: sm-limit error " 16227c478bd9Sstevel@tonic-gate "(expected = 0x%x, actual = 0x%x)", 16237c478bd9Sstevel@tonic-gate smlimit, smreg); 16247c478bd9Sstevel@tonic-gate rv++; 16257c478bd9Sstevel@tonic-gate } 16267c478bd9Sstevel@tonic-gate } 16277c478bd9Sstevel@tonic-gate 16287c478bd9Sstevel@tonic-gate return (rv ? -1 : 0); 16297c478bd9Sstevel@tonic-gate } 16307c478bd9Sstevel@tonic-gate 16317c478bd9Sstevel@tonic-gate /* 16327c478bd9Sstevel@tonic-gate * ------------------------------------------------------------- 16337c478bd9Sstevel@tonic-gate */ 16347c478bd9Sstevel@tonic-gate int 16357c478bd9Sstevel@tonic-gate idn_cpu_per_board(pda_handle_t ph, cpuset_t cset, struct hwconfig *hwp) 16367c478bd9Sstevel@tonic-gate { 16377c478bd9Sstevel@tonic-gate int b, err = 0; 16387c478bd9Sstevel@tonic-gate boardset_t bset, cpu_bset; 16397c478bd9Sstevel@tonic-gate board_desc_t *lbp; 16407c478bd9Sstevel@tonic-gate 16417c478bd9Sstevel@tonic-gate if (!idn_check_cpu_per_board) 16427c478bd9Sstevel@tonic-gate return (1); 16437c478bd9Sstevel@tonic-gate 16447c478bd9Sstevel@tonic-gate bset = hwp->dh_boardset; 16457c478bd9Sstevel@tonic-gate CPUSET_TO_BOARDSET(cset, cpu_bset); 16467c478bd9Sstevel@tonic-gate 16477c478bd9Sstevel@tonic-gate /* 16487c478bd9Sstevel@tonic-gate * Every board has at least one cpu, we're happy. 16497c478bd9Sstevel@tonic-gate */ 16507c478bd9Sstevel@tonic-gate if (cpu_bset == bset) 16517c478bd9Sstevel@tonic-gate return (1); 16527c478bd9Sstevel@tonic-gate 16537c478bd9Sstevel@tonic-gate /* 16547c478bd9Sstevel@tonic-gate * Well, not all boards had cpus. That's okay so 16557c478bd9Sstevel@tonic-gate * long as they don't have memory also. 16567c478bd9Sstevel@tonic-gate * Get rid of the boards that have a cpu. 16577c478bd9Sstevel@tonic-gate */ 16587c478bd9Sstevel@tonic-gate bset &= ~cpu_bset; 16597c478bd9Sstevel@tonic-gate /* 16607c478bd9Sstevel@tonic-gate * None of the remaining boards in the set shold have mem. 16617c478bd9Sstevel@tonic-gate */ 16627c478bd9Sstevel@tonic-gate err = 0; 16637c478bd9Sstevel@tonic-gate 16647c478bd9Sstevel@tonic-gate /* 16657c478bd9Sstevel@tonic-gate * A NULL post2obp pointer indicates we're checking 16667c478bd9Sstevel@tonic-gate * the config of a remote domain. Since we can't 16677c478bd9Sstevel@tonic-gate * look at the post2obp of the remote domain, we'll 16687c478bd9Sstevel@tonic-gate * have to trust what he passed us in his config. 16697c478bd9Sstevel@tonic-gate */ 16707c478bd9Sstevel@tonic-gate if (ph && !pda_is_valid(ph)) { 16717c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "IDN: 508: post2obp checksum invalid"); 16727c478bd9Sstevel@tonic-gate return (0); 16737c478bd9Sstevel@tonic-gate } 16747c478bd9Sstevel@tonic-gate 16757c478bd9Sstevel@tonic-gate for (b = 0; b < MAX_BOARDS; b++) { 16767c478bd9Sstevel@tonic-gate if (!BOARD_IN_SET(bset, b)) 16777c478bd9Sstevel@tonic-gate continue; 16787c478bd9Sstevel@tonic-gate 16797c478bd9Sstevel@tonic-gate lbp = ph ? pda_get_board_info(ph, b) : NULL; 16807c478bd9Sstevel@tonic-gate 16817c478bd9Sstevel@tonic-gate if ((lbp && 16827c478bd9Sstevel@tonic-gate (BDA_NBL(lbp->bda_board, BDA_MC_NBL) == BDAN_GOOD)) || 16837c478bd9Sstevel@tonic-gate (!lbp && hwp->dh_mcadr[b])) { 16847c478bd9Sstevel@tonic-gate err++; 16857c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, 16867c478bd9Sstevel@tonic-gate "IDN: 516: (%s) board %d has memory, " 16877c478bd9Sstevel@tonic-gate "but no CPUs - CPU per memory board REQUIRED", 16887c478bd9Sstevel@tonic-gate ph ? "local" : "remote", b); 16897c478bd9Sstevel@tonic-gate } 16907c478bd9Sstevel@tonic-gate } 16917c478bd9Sstevel@tonic-gate 16927c478bd9Sstevel@tonic-gate return (err ? 0 : 1); 16937c478bd9Sstevel@tonic-gate } 1694