1*29949e86Sstevel /*
2*29949e86Sstevel * CDDL HEADER START
3*29949e86Sstevel *
4*29949e86Sstevel * The contents of this file are subject to the terms of the
5*29949e86Sstevel * Common Development and Distribution License (the "License").
6*29949e86Sstevel * You may not use this file except in compliance with the License.
7*29949e86Sstevel *
8*29949e86Sstevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*29949e86Sstevel * or http://www.opensolaris.org/os/licensing.
10*29949e86Sstevel * See the License for the specific language governing permissions
11*29949e86Sstevel * and limitations under the License.
12*29949e86Sstevel *
13*29949e86Sstevel * When distributing Covered Code, include this CDDL HEADER in each
14*29949e86Sstevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*29949e86Sstevel * If applicable, add the following below this CDDL HEADER, with the
16*29949e86Sstevel * fields enclosed by brackets "[]" replaced with your own identifying
17*29949e86Sstevel * information: Portions Copyright [yyyy] [name of copyright owner]
18*29949e86Sstevel *
19*29949e86Sstevel * CDDL HEADER END
20*29949e86Sstevel */
21*29949e86Sstevel
22*29949e86Sstevel /*
23*29949e86Sstevel * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24*29949e86Sstevel * Use is subject to license terms.
25*29949e86Sstevel */
26*29949e86Sstevel
27*29949e86Sstevel #pragma ident "%Z%%M% %I% %E% SMI"
28*29949e86Sstevel
29*29949e86Sstevel #include <sys/types.h>
30*29949e86Sstevel #include <sys/conf.h>
31*29949e86Sstevel #include <sys/ddi.h>
32*29949e86Sstevel #include <sys/sunddi.h>
33*29949e86Sstevel #include <sys/sunndi.h>
34*29949e86Sstevel #include <sys/ddi_impldefs.h>
35*29949e86Sstevel #include <sys/ndi_impldefs.h>
36*29949e86Sstevel #include <sys/obpdefs.h>
37*29949e86Sstevel #include <sys/cmn_err.h>
38*29949e86Sstevel #include <sys/errno.h>
39*29949e86Sstevel #include <sys/kmem.h>
40*29949e86Sstevel #include <sys/debug.h>
41*29949e86Sstevel #include <sys/sysmacros.h>
42*29949e86Sstevel #include <sys/ivintr.h>
43*29949e86Sstevel #include <sys/autoconf.h>
44*29949e86Sstevel #include <sys/intreg.h>
45*29949e86Sstevel #include <sys/proc.h>
46*29949e86Sstevel #include <sys/machsystm.h>
47*29949e86Sstevel #include <sys/modctl.h>
48*29949e86Sstevel #include <sys/callb.h>
49*29949e86Sstevel #include <sys/file.h>
50*29949e86Sstevel #include <sys/open.h>
51*29949e86Sstevel #include <sys/stat.h>
52*29949e86Sstevel #include <sys/fhc.h>
53*29949e86Sstevel #include <sys/sysctrl.h>
54*29949e86Sstevel #include <sys/jtag.h>
55*29949e86Sstevel #include <sys/ac.h>
56*29949e86Sstevel #include <sys/simmstat.h>
57*29949e86Sstevel #include <sys/clock.h>
58*29949e86Sstevel #include <sys/promif.h>
59*29949e86Sstevel #include <sys/promimpl.h>
60*29949e86Sstevel #include <sys/cpr.h>
61*29949e86Sstevel #include <sys/cpuvar.h>
62*29949e86Sstevel #include <sys/machcpuvar.h>
63*29949e86Sstevel #include <sys/x_call.h>
64*29949e86Sstevel
65*29949e86Sstevel #ifdef DEBUG
66*29949e86Sstevel struct regs_data {
67*29949e86Sstevel caddr_t msg;
68*29949e86Sstevel u_longlong_t physaddr;
69*29949e86Sstevel uint_t pre_dsct;
70*29949e86Sstevel uint_t post_dsct;
71*29949e86Sstevel uint_t eflag;
72*29949e86Sstevel uint_t oflag;
73*29949e86Sstevel };
74*29949e86Sstevel
75*29949e86Sstevel static struct regs_data reg_tmpl[] = {
76*29949e86Sstevel "AC Control and Status reg = 0x", AC_BCSR(0), 0, 0, 0, 0,
77*29949e86Sstevel "FHC Control and Status reg = 0x", FHC_CTRL(0), 0, 0, 0, 0,
78*29949e86Sstevel "JTAG Control reg = 0x", FHC_JTAG_CTRL(0), 0, 0, 0, 0,
79*29949e86Sstevel "Interrupt Group Number reg = 0x", FHC_IGN(0), 0, 0, 0, 0,
80*29949e86Sstevel "System Interrupt Mapping reg = 0x", FHC_SIM(0), 0, 0, 0, 0,
81*29949e86Sstevel "System Interrupt State reg = 0x", FHC_SSM(0), 0, 0, 0, 0,
82*29949e86Sstevel "UART Interrupt Mapping reg = 0x", FHC_UIM(0), 0, 0, 0, 0,
83*29949e86Sstevel "UART Interrupt State reg = 0x", FHC_USM(0), 0, 0, 0, 0
84*29949e86Sstevel };
85*29949e86Sstevel
86*29949e86Sstevel #define NUM_REG (sizeof (reg_tmpl)/sizeof (reg_tmpl[0]))
87*29949e86Sstevel static struct regs_data reg_dt[MAX_BOARDS][NUM_REG];
88*29949e86Sstevel
89*29949e86Sstevel int sysctrl_enable_regdump = 0;
90*29949e86Sstevel
91*29949e86Sstevel static void precache_regdump(int board);
92*29949e86Sstevel static void display_regdump(void);
93*29949e86Sstevel static void boardstat_regdump(void);
94*29949e86Sstevel
95*29949e86Sstevel #endif /* DEBUG */
96*29949e86Sstevel
97*29949e86Sstevel extern void bd_remove_poll(struct sysctrl_soft_state *);
98*29949e86Sstevel extern int sysctrl_getsystem_freq(void);
99*29949e86Sstevel extern enum power_state compute_power_state(struct sysctrl_soft_state *, int);
100*29949e86Sstevel extern enum temp_state fhc_env_temp_state(int);
101*29949e86Sstevel extern int sysctrl_hotplug_disabled;
102*29949e86Sstevel /* Let user disable Sunfire Dynamic Reconfiguration */
103*29949e86Sstevel int enable_dynamic_reconfiguration = 1;
104*29949e86Sstevel
105*29949e86Sstevel int enable_redist = 1;
106*29949e86Sstevel
107*29949e86Sstevel static void sysc_dr_err_decode(sysc_dr_handle_t *, dev_info_t *, int);
108*29949e86Sstevel static uint_t
109*29949e86Sstevel sysc_policy_enough_cooling(struct sysctrl_soft_state *softsp,
110*29949e86Sstevel sysc_cfga_stat_t *sysc_stat, uint_t ps_mutex_is_held);
111*29949e86Sstevel static uint_t
112*29949e86Sstevel sysc_policy_enough_precharge(struct sysctrl_soft_state *softsp,
113*29949e86Sstevel sysc_cfga_stat_t *sysc_stat);
114*29949e86Sstevel static uint_t
115*29949e86Sstevel sysc_policy_enough_power(struct sysctrl_soft_state *softsp,
116*29949e86Sstevel int plus_load, uint_t ps_mutex_is_held);
117*29949e86Sstevel static uint_t
118*29949e86Sstevel sysc_policy_hardware_compatible(struct sysctrl_soft_state *softsp,
119*29949e86Sstevel sysc_cfga_stat_t *sysc_stat, sysc_cfga_pkt_t *pkt);
120*29949e86Sstevel static void sysc_policy_empty_condition(
121*29949e86Sstevel struct sysctrl_soft_state *softsp,
122*29949e86Sstevel sysc_cfga_stat_t *sysc_stat, uint_t failure,
123*29949e86Sstevel uint_t ps_mutex_is_held);
124*29949e86Sstevel static void sysc_policy_disconnected_condition(
125*29949e86Sstevel struct sysctrl_soft_state *softsp,
126*29949e86Sstevel sysc_cfga_stat_t *sysc_stat, uint_t failure,
127*29949e86Sstevel uint_t ps_mutex_is_held);
128*29949e86Sstevel static void sysc_policy_connected_condition(struct sysctrl_soft_state *softsp,
129*29949e86Sstevel sysc_cfga_stat_t *sysc_stat,
130*29949e86Sstevel uint_t ps_mutex_is_held);
131*29949e86Sstevel static void sysc_policy_set_condition(void *sp, sysc_cfga_stat_t *sysc_stat,
132*29949e86Sstevel uint_t ps_mutex_is_held);
133*29949e86Sstevel static void sysc_policy_audit_messages(sysc_audit_evt_t event,
134*29949e86Sstevel sysc_cfga_stat_t *sysc_stat);
135*29949e86Sstevel
136*29949e86Sstevel static void sysctrl_post_config_change(struct sysctrl_soft_state *softsp);
137*29949e86Sstevel static int sysc_bd_connect(int, sysc_cfga_pkt_t *);
138*29949e86Sstevel static int sysc_bd_disconnect(int, sysc_cfga_pkt_t *);
139*29949e86Sstevel static int sysc_bd_configure(int, sysc_cfga_pkt_t *);
140*29949e86Sstevel static int sysc_bd_unconfigure(int, sysc_cfga_pkt_t *);
141*29949e86Sstevel
142*29949e86Sstevel static void sysc_dr_init(sysc_dr_handle_t *handle);
143*29949e86Sstevel static void sysc_dr_uninit(sysc_dr_handle_t *handle);
144*29949e86Sstevel static int sysc_dr_attach(sysc_dr_handle_t *handle, int board);
145*29949e86Sstevel static int sysc_dr_detach(sysc_dr_handle_t *handle, int board);
146*29949e86Sstevel
147*29949e86Sstevel static int sysc_prom_select(pnode_t pnode, void *arg, uint_t flag);
148*29949e86Sstevel static void sysc_branch_callback(dev_info_t *rdip, void *arg, uint_t flags);
149*29949e86Sstevel
150*29949e86Sstevel static int find_and_setup_cpu(int);
151*29949e86Sstevel
152*29949e86Sstevel static int sysc_board_connect_supported(enum board_type);
153*29949e86Sstevel
154*29949e86Sstevel static int find_and_setup_cpu_start(void *cpuid_arg, int has_changed);
155*29949e86Sstevel /*
156*29949e86Sstevel * This function will basically do a prediction on the power state
157*29949e86Sstevel * based on adding one additional load to the equation implemented
158*29949e86Sstevel * by the function compute_power_state.
159*29949e86Sstevel */
160*29949e86Sstevel /*ARGSUSED*/
161*29949e86Sstevel static uint_t
sysc_policy_enough_power(struct sysctrl_soft_state * softsp,int plus_load,uint_t ps_mutex_is_held)162*29949e86Sstevel sysc_policy_enough_power(struct sysctrl_soft_state *softsp,
163*29949e86Sstevel int plus_load, uint_t ps_mutex_is_held)
164*29949e86Sstevel {
165*29949e86Sstevel int retval = 0;
166*29949e86Sstevel
167*29949e86Sstevel ASSERT(softsp);
168*29949e86Sstevel
169*29949e86Sstevel if (!ps_mutex_is_held) {
170*29949e86Sstevel mutex_enter(&softsp->ps_fail_lock);
171*29949e86Sstevel }
172*29949e86Sstevel
173*29949e86Sstevel /*
174*29949e86Sstevel * note that we add one more load
175*29949e86Sstevel * to the equation in compute_power_state
176*29949e86Sstevel * and the answer better be REDUNDANT or
177*29949e86Sstevel * MINIMUM before proceeding.
178*29949e86Sstevel */
179*29949e86Sstevel switch (compute_power_state(softsp, plus_load)) {
180*29949e86Sstevel case REDUNDANT:
181*29949e86Sstevel case MINIMUM:
182*29949e86Sstevel retval = 1;
183*29949e86Sstevel break;
184*29949e86Sstevel case BELOW_MINIMUM:
185*29949e86Sstevel default:
186*29949e86Sstevel break;
187*29949e86Sstevel }
188*29949e86Sstevel
189*29949e86Sstevel if (!ps_mutex_is_held) {
190*29949e86Sstevel mutex_exit(&softsp->ps_fail_lock);
191*29949e86Sstevel }
192*29949e86Sstevel return (retval);
193*29949e86Sstevel }
194*29949e86Sstevel
195*29949e86Sstevel /*
196*29949e86Sstevel * This function gropes through the shadow registers in the sysctrl soft_state
197*29949e86Sstevel * for the core power supply status, since fan status for them are ORed into
198*29949e86Sstevel * the same status bit, and all other remaining fans.
199*29949e86Sstevel */
200*29949e86Sstevel static uint_t
sysc_policy_enough_cooling(struct sysctrl_soft_state * softsp,sysc_cfga_stat_t * sysc_stat,uint_t ps_mutex_is_held)201*29949e86Sstevel sysc_policy_enough_cooling(struct sysctrl_soft_state *softsp,
202*29949e86Sstevel sysc_cfga_stat_t *sysc_stat, uint_t ps_mutex_is_held)
203*29949e86Sstevel {
204*29949e86Sstevel int retval = 0;
205*29949e86Sstevel
206*29949e86Sstevel if (!ps_mutex_is_held) {
207*29949e86Sstevel mutex_enter(&softsp->ps_fail_lock);
208*29949e86Sstevel }
209*29949e86Sstevel
210*29949e86Sstevel /*
211*29949e86Sstevel * check the power supply in the slot in question
212*29949e86Sstevel * for fans then check all the common fans.
213*29949e86Sstevel */
214*29949e86Sstevel retval = ((softsp->ps_stats[FHC_BOARD2PS(sysc_stat->board)].pshadow ==
215*29949e86Sstevel PRES_IN) &&
216*29949e86Sstevel (softsp->ps_stats[FHC_BOARD2PS(sysc_stat->board)].dcshadow ==
217*29949e86Sstevel PS_OK));
218*29949e86Sstevel if (!ps_mutex_is_held) {
219*29949e86Sstevel mutex_exit(&softsp->ps_fail_lock);
220*29949e86Sstevel }
221*29949e86Sstevel return (retval);
222*29949e86Sstevel }
223*29949e86Sstevel
224*29949e86Sstevel /*
225*29949e86Sstevel * This function will check all precharge voltage status.
226*29949e86Sstevel */
227*29949e86Sstevel /*ARGSUSED*/
228*29949e86Sstevel static uint_t
sysc_policy_enough_precharge(struct sysctrl_soft_state * softsp,sysc_cfga_stat_t * sysc_stat)229*29949e86Sstevel sysc_policy_enough_precharge(struct sysctrl_soft_state *softsp,
230*29949e86Sstevel sysc_cfga_stat_t *sysc_stat)
231*29949e86Sstevel {
232*29949e86Sstevel int retval = 0;
233*29949e86Sstevel int ppsval = 0;
234*29949e86Sstevel
235*29949e86Sstevel mutex_enter(&softsp->ps_fail_lock);
236*29949e86Sstevel
237*29949e86Sstevel /*
238*29949e86Sstevel * note that we always have to explicitly check
239*29949e86Sstevel * the peripheral power supply for precharge since it
240*29949e86Sstevel * supplies all of the precharge voltages.
241*29949e86Sstevel */
242*29949e86Sstevel ppsval = (softsp->ps_stats[SYS_PPS0_INDEX].pshadow == PRES_IN) &&
243*29949e86Sstevel (softsp->ps_stats[SYS_PPS0_INDEX].dcshadow == PS_OK);
244*29949e86Sstevel
245*29949e86Sstevel /*
246*29949e86Sstevel * check all the precharge status
247*29949e86Sstevel */
248*29949e86Sstevel retval = ((softsp->ps_stats[SYS_V3_PCH_INDEX].pshadow == PRES_IN) &&
249*29949e86Sstevel (softsp->ps_stats[SYS_V3_PCH_INDEX].dcshadow == PS_OK) &&
250*29949e86Sstevel (softsp->ps_stats[SYS_V5_PCH_INDEX].pshadow == PRES_IN) &&
251*29949e86Sstevel (softsp->ps_stats[SYS_V5_PCH_INDEX].dcshadow == PS_OK));
252*29949e86Sstevel
253*29949e86Sstevel mutex_exit(&softsp->ps_fail_lock);
254*29949e86Sstevel return (retval&&ppsval);
255*29949e86Sstevel }
256*29949e86Sstevel
257*29949e86Sstevel static int Fsys;
258*29949e86Sstevel
259*29949e86Sstevel /*
260*29949e86Sstevel * This function should only be called once as we may
261*29949e86Sstevel * zero the clock board registers to indicate a configuration change.
262*29949e86Sstevel * The code to calculate the bus frequency has been removed and we
263*29949e86Sstevel * read the eeprom property instead. Another static Fmod (module
264*29949e86Sstevel * frequency may be needed later but so far it is commented out.
265*29949e86Sstevel */
266*29949e86Sstevel void
set_clockbrd_info(void)267*29949e86Sstevel set_clockbrd_info(void)
268*29949e86Sstevel {
269*29949e86Sstevel uint_t clock_freq = 0;
270*29949e86Sstevel
271*29949e86Sstevel pnode_t root = prom_nextnode((pnode_t)0);
272*29949e86Sstevel (void) prom_getprop(root, "clock-frequency", (caddr_t)&clock_freq);
273*29949e86Sstevel Fsys = clock_freq / 1000000;
274*29949e86Sstevel }
275*29949e86Sstevel
276*29949e86Sstevel #define abs(x) ((x) < 0 ? -(x) : (x))
277*29949e86Sstevel
278*29949e86Sstevel /*ARGSUSED*/
279*29949e86Sstevel static uint_t
sysc_policy_hardware_compatible(struct sysctrl_soft_state * softsp,sysc_cfga_stat_t * sysc_stat,sysc_cfga_pkt_t * pkt)280*29949e86Sstevel sysc_policy_hardware_compatible(struct sysctrl_soft_state *softsp,
281*29949e86Sstevel sysc_cfga_stat_t *sysc_stat, sysc_cfga_pkt_t *pkt)
282*29949e86Sstevel {
283*29949e86Sstevel int status;
284*29949e86Sstevel
285*29949e86Sstevel ASSERT(Fsys > 0);
286*29949e86Sstevel
287*29949e86Sstevel /* Only allow DR operations on supported hardware */
288*29949e86Sstevel switch (sysc_stat->type) {
289*29949e86Sstevel case CPU_BOARD: {
290*29949e86Sstevel #ifdef RFE_4174486
291*29949e86Sstevel int i;
292*29949e86Sstevel int cpu_freq;
293*29949e86Sstevel int sram_mode;
294*29949e86Sstevel
295*29949e86Sstevel ASSERT(Fmod > 0);
296*29949e86Sstevel
297*29949e86Sstevel cpu_freq = CPU->cpu_type_info.pi_clock;
298*29949e86Sstevel
299*29949e86Sstevel if (abs(cpu_freq - Fmod) < 8)
300*29949e86Sstevel sram_mode = 1;
301*29949e86Sstevel else
302*29949e86Sstevel sram_mode = 2;
303*29949e86Sstevel
304*29949e86Sstevel status = TRUE;
305*29949e86Sstevel for (i = 0; i < 2; i++) {
306*29949e86Sstevel /*
307*29949e86Sstevel * XXX: Add jtag code which rescans disabled boards.
308*29949e86Sstevel * For the time being disabled boards are not
309*29949e86Sstevel * checked for compatibility when cpu_speed is 0.
310*29949e86Sstevel */
311*29949e86Sstevel if (sysc_stat->bd.cpu[i].cpu_speed == 0)
312*29949e86Sstevel continue;
313*29949e86Sstevel
314*29949e86Sstevel if (sysc_stat->bd.cpu[i].cpu_speed < cpu_freq) {
315*29949e86Sstevel cmn_err(CE_WARN, "board %d, cpu module %c "
316*29949e86Sstevel "rated at %d Mhz, system freq %d Mhz",
317*29949e86Sstevel sysc_stat->board, (i == 0) ? 'A' : 'B',
318*29949e86Sstevel sysc_stat->bd.cpu[i].cpu_speed,
319*29949e86Sstevel cpu_freq);
320*29949e86Sstevel status = FALSE;
321*29949e86Sstevel }
322*29949e86Sstevel
323*29949e86Sstevel if (sram_mode != sysc_stat->bd.cpu[i].cpu_sram_mode) {
324*29949e86Sstevel cmn_err(CE_WARN, "board %d, cpu module %c "
325*29949e86Sstevel "incompatible sram mode of %dx, "
326*29949e86Sstevel "system is %dx", sysc_stat->board,
327*29949e86Sstevel (i == 0) ? 'A' : 'B',
328*29949e86Sstevel sysc_stat->bd.cpu[i].cpu_sram_mode,
329*29949e86Sstevel sram_mode);
330*29949e86Sstevel status = FALSE;
331*29949e86Sstevel }
332*29949e86Sstevel }
333*29949e86Sstevel break;
334*29949e86Sstevel #endif /* RFE_4174486 */
335*29949e86Sstevel }
336*29949e86Sstevel
337*29949e86Sstevel case MEM_BOARD:
338*29949e86Sstevel case IO_2SBUS_BOARD:
339*29949e86Sstevel case IO_SBUS_FFB_BOARD:
340*29949e86Sstevel case IO_PCI_BOARD:
341*29949e86Sstevel case IO_2SBUS_SOCPLUS_BOARD:
342*29949e86Sstevel case IO_SBUS_FFB_SOCPLUS_BOARD:
343*29949e86Sstevel status = TRUE;
344*29949e86Sstevel break;
345*29949e86Sstevel
346*29949e86Sstevel case CLOCK_BOARD:
347*29949e86Sstevel case DISK_BOARD:
348*29949e86Sstevel default:
349*29949e86Sstevel status = FALSE; /* default is not supported */
350*29949e86Sstevel break;
351*29949e86Sstevel }
352*29949e86Sstevel
353*29949e86Sstevel if (status == FALSE)
354*29949e86Sstevel return (status);
355*29949e86Sstevel
356*29949e86Sstevel /* Check for Sunfire boards in a Sunfire+ system */
357*29949e86Sstevel if (status == TRUE && Fsys > 84 && !fhc_bd_is_plus(sysc_stat->board)) {
358*29949e86Sstevel (void) snprintf(pkt->errbuf, SYSC_OUTPUT_LEN,
359*29949e86Sstevel "not 100 MHz capable ");
360*29949e86Sstevel cmn_err(CE_WARN, "board %d, is not capable of running at "
361*29949e86Sstevel "current system clock (%dMhz)", sysc_stat->board, Fsys);
362*29949e86Sstevel
363*29949e86Sstevel status = FALSE;
364*29949e86Sstevel }
365*29949e86Sstevel
366*29949e86Sstevel return (status);
367*29949e86Sstevel }
368*29949e86Sstevel
369*29949e86Sstevel /*
370*29949e86Sstevel * This function is called to check the policy for a request to transition
371*29949e86Sstevel * to the connected state from the disconnected state. The generic policy
372*29949e86Sstevel * is to do sanity checks again before going live.
373*29949e86Sstevel */
374*29949e86Sstevel /*ARGSUSED*/
375*29949e86Sstevel int
sysc_policy_connect(struct sysctrl_soft_state * softsp,sysc_cfga_pkt_t * pkt,sysc_cfga_stat_t * sysc_stat)376*29949e86Sstevel sysc_policy_connect(struct sysctrl_soft_state *softsp,
377*29949e86Sstevel sysc_cfga_pkt_t *pkt, sysc_cfga_stat_t *sysc_stat)
378*29949e86Sstevel {
379*29949e86Sstevel int retval;
380*29949e86Sstevel
381*29949e86Sstevel ASSERT(fhc_bdlist_locked());
382*29949e86Sstevel
383*29949e86Sstevel DPRINTF(SYSC_DEBUG, ("Previous RState: %d\n", sysc_stat->rstate));
384*29949e86Sstevel DPRINTF(SYSC_DEBUG, ("Previous OState: %d\n", sysc_stat->ostate));
385*29949e86Sstevel
386*29949e86Sstevel switch (sysc_stat->rstate) {
387*29949e86Sstevel case SYSC_CFGA_RSTATE_DISCONNECTED:
388*29949e86Sstevel /*
389*29949e86Sstevel * Safety policy: only allow connect if board is UNKNOWN cond.
390*29949e86Sstevel * cold start board will be demoted to UNKNOWN cond when
391*29949e86Sstevel * disconnected
392*29949e86Sstevel */
393*29949e86Sstevel if (sysc_stat->condition != SYSC_CFGA_COND_UNKNOWN) {
394*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_COND);
395*29949e86Sstevel return (EINVAL);
396*29949e86Sstevel }
397*29949e86Sstevel
398*29949e86Sstevel if (!enable_dynamic_reconfiguration) {
399*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_NON_DR_PROM);
400*29949e86Sstevel return (ENOTSUP);
401*29949e86Sstevel }
402*29949e86Sstevel
403*29949e86Sstevel if (sysctrl_hotplug_disabled) {
404*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_HOTPLUG);
405*29949e86Sstevel return (ENOTSUP);
406*29949e86Sstevel }
407*29949e86Sstevel
408*29949e86Sstevel /* Check PROM support. */
409*29949e86Sstevel if (!sysc_board_connect_supported(sysc_stat->type)) {
410*29949e86Sstevel cmn_err(CE_WARN, "%s board %d connect"
411*29949e86Sstevel " is not supported by firmware.",
412*29949e86Sstevel fhc_bd_typestr(sysc_stat->type), sysc_stat->board);
413*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_HW_COMPAT);
414*29949e86Sstevel return (ENOTSUP);
415*29949e86Sstevel }
416*29949e86Sstevel
417*29949e86Sstevel if (!sysc_policy_enough_power(softsp, TRUE, FALSE)) {
418*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_POWER);
419*29949e86Sstevel return (EAGAIN);
420*29949e86Sstevel }
421*29949e86Sstevel
422*29949e86Sstevel if (!sysc_policy_enough_precharge(softsp, sysc_stat)) {
423*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_PRECHARGE);
424*29949e86Sstevel return (EAGAIN);
425*29949e86Sstevel }
426*29949e86Sstevel
427*29949e86Sstevel if (!sysc_policy_enough_cooling(softsp, sysc_stat, FALSE)) {
428*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_COOLING);
429*29949e86Sstevel return (EAGAIN);
430*29949e86Sstevel }
431*29949e86Sstevel
432*29949e86Sstevel if (!sysc_policy_hardware_compatible(softsp, sysc_stat, pkt)) {
433*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_HW_COMPAT);
434*29949e86Sstevel return (ENOTSUP);
435*29949e86Sstevel }
436*29949e86Sstevel sysc_policy_audit_messages(SYSC_AUDIT_RSTATE_CONNECT,
437*29949e86Sstevel sysc_stat);
438*29949e86Sstevel
439*29949e86Sstevel retval = sysc_bd_connect(sysc_stat->board, pkt);
440*29949e86Sstevel if (!retval) {
441*29949e86Sstevel sysc_stat->rstate = SYSC_CFGA_RSTATE_CONNECTED;
442*29949e86Sstevel sysc_policy_connected_condition(softsp,
443*29949e86Sstevel sysc_stat, FALSE);
444*29949e86Sstevel sysc_policy_audit_messages(SYSC_AUDIT_RSTATE_SUCCEEDED,
445*29949e86Sstevel sysc_stat);
446*29949e86Sstevel } else {
447*29949e86Sstevel uint_t prom_failure;
448*29949e86Sstevel
449*29949e86Sstevel prom_failure = (retval == EIO &&
450*29949e86Sstevel pkt->cmd_cfga.errtype == SYSC_ERR_PROM) ?
451*29949e86Sstevel TRUE : FALSE;
452*29949e86Sstevel sysc_policy_disconnected_condition(softsp,
453*29949e86Sstevel sysc_stat, prom_failure, FALSE);
454*29949e86Sstevel sysc_policy_audit_messages(
455*29949e86Sstevel SYSC_AUDIT_RSTATE_CONNECT_FAILED,
456*29949e86Sstevel sysc_stat);
457*29949e86Sstevel }
458*29949e86Sstevel break;
459*29949e86Sstevel case SYSC_CFGA_RSTATE_EMPTY:
460*29949e86Sstevel case SYSC_CFGA_RSTATE_CONNECTED:
461*29949e86Sstevel default:
462*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_RSTATE);
463*29949e86Sstevel retval = EINVAL;
464*29949e86Sstevel break;
465*29949e86Sstevel }
466*29949e86Sstevel
467*29949e86Sstevel DPRINTF(SYSC_DEBUG, ("Current RState: %d\n", sysc_stat->rstate));
468*29949e86Sstevel DPRINTF(SYSC_DEBUG, ("Current OState: %d\n", sysc_stat->ostate));
469*29949e86Sstevel DPRINTF(SYSC_DEBUG, ("Current Condition: %d\n", sysc_stat->condition));
470*29949e86Sstevel
471*29949e86Sstevel return (retval);
472*29949e86Sstevel }
473*29949e86Sstevel
474*29949e86Sstevel /*
475*29949e86Sstevel * This function is called to check the policy for a request to transition
476*29949e86Sstevel * to the disconnected state from the connected/unconfigured state only.
477*29949e86Sstevel * All other requests are invalid.
478*29949e86Sstevel */
479*29949e86Sstevel /*ARGSUSED*/
480*29949e86Sstevel int
sysc_policy_disconnect(struct sysctrl_soft_state * softsp,sysc_cfga_pkt_t * pkt,sysc_cfga_stat_t * sysc_stat)481*29949e86Sstevel sysc_policy_disconnect(struct sysctrl_soft_state *softsp,
482*29949e86Sstevel sysc_cfga_pkt_t *pkt, sysc_cfga_stat_t *sysc_stat)
483*29949e86Sstevel {
484*29949e86Sstevel int retval;
485*29949e86Sstevel
486*29949e86Sstevel ASSERT(fhc_bdlist_locked());
487*29949e86Sstevel
488*29949e86Sstevel DPRINTF(SYSC_DEBUG, ("Previous RState: %d\n", sysc_stat->rstate));
489*29949e86Sstevel DPRINTF(SYSC_DEBUG, ("Previous OState: %d\n", sysc_stat->ostate));
490*29949e86Sstevel
491*29949e86Sstevel switch (sysc_stat->rstate) {
492*29949e86Sstevel case SYSC_CFGA_RSTATE_CONNECTED:
493*29949e86Sstevel switch (sysc_stat->ostate) {
494*29949e86Sstevel case SYSC_CFGA_OSTATE_UNCONFIGURED:
495*29949e86Sstevel if (!enable_dynamic_reconfiguration) {
496*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_NON_DR_PROM);
497*29949e86Sstevel return (ENOTSUP);
498*29949e86Sstevel }
499*29949e86Sstevel
500*29949e86Sstevel /* Check PROM support. */
501*29949e86Sstevel if (!sysc_board_connect_supported(sysc_stat->type)) {
502*29949e86Sstevel cmn_err(CE_WARN, "%s board %d disconnect"
503*29949e86Sstevel " is not supported by firmware.",
504*29949e86Sstevel fhc_bd_typestr(sysc_stat->type),
505*29949e86Sstevel sysc_stat->board);
506*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_HW_COMPAT);
507*29949e86Sstevel return (ENOTSUP);
508*29949e86Sstevel }
509*29949e86Sstevel
510*29949e86Sstevel if (!sysc_policy_hardware_compatible(softsp,
511*29949e86Sstevel sysc_stat, pkt)) {
512*29949e86Sstevel cmn_err(CE_WARN, "%s board %d disconnect"
513*29949e86Sstevel " is not yet supported.",
514*29949e86Sstevel fhc_bd_typestr(sysc_stat->type),
515*29949e86Sstevel sysc_stat->board);
516*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_HW_COMPAT);
517*29949e86Sstevel return (ENOTSUP);
518*29949e86Sstevel }
519*29949e86Sstevel
520*29949e86Sstevel if (fhc_bd_is_jtag_master(sysc_stat->board)) {
521*29949e86Sstevel sysc_policy_update(softsp, sysc_stat,
522*29949e86Sstevel SYSC_EVT_BD_CORE_RESOURCE_DISCONNECT);
523*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_CORE_RESOURCE);
524*29949e86Sstevel return (EINVAL);
525*29949e86Sstevel }
526*29949e86Sstevel
527*29949e86Sstevel sysc_policy_audit_messages(SYSC_AUDIT_RSTATE_DISCONNECT,
528*29949e86Sstevel sysc_stat);
529*29949e86Sstevel
530*29949e86Sstevel retval = sysc_bd_disconnect(sysc_stat->board, pkt);
531*29949e86Sstevel if (!retval) {
532*29949e86Sstevel sysc_stat->rstate =
533*29949e86Sstevel SYSC_CFGA_RSTATE_DISCONNECTED;
534*29949e86Sstevel DPRINTF(SYSCTRL_ATTACH_DEBUG,
535*29949e86Sstevel ("disconnect starting bd_remove_poll()"));
536*29949e86Sstevel bd_remove_poll(softsp);
537*29949e86Sstevel sysc_policy_disconnected_condition(
538*29949e86Sstevel softsp,
539*29949e86Sstevel sysc_stat, FALSE, FALSE);
540*29949e86Sstevel sysc_policy_audit_messages(
541*29949e86Sstevel SYSC_AUDIT_RSTATE_SUCCEEDED,
542*29949e86Sstevel sysc_stat);
543*29949e86Sstevel cmn_err(CE_NOTE,
544*29949e86Sstevel "board %d is ready to remove",
545*29949e86Sstevel sysc_stat->board);
546*29949e86Sstevel } else {
547*29949e86Sstevel sysc_policy_connected_condition(
548*29949e86Sstevel softsp, sysc_stat, FALSE);
549*29949e86Sstevel sysc_policy_audit_messages(
550*29949e86Sstevel SYSC_AUDIT_RSTATE_DISCONNECT_FAILED,
551*29949e86Sstevel sysc_stat);
552*29949e86Sstevel }
553*29949e86Sstevel break;
554*29949e86Sstevel case SYSC_CFGA_OSTATE_CONFIGURED:
555*29949e86Sstevel default:
556*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_OSTATE);
557*29949e86Sstevel retval = EINVAL;
558*29949e86Sstevel break;
559*29949e86Sstevel }
560*29949e86Sstevel break;
561*29949e86Sstevel case SYSC_CFGA_RSTATE_EMPTY:
562*29949e86Sstevel case SYSC_CFGA_RSTATE_DISCONNECTED:
563*29949e86Sstevel default:
564*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_RSTATE);
565*29949e86Sstevel retval = EINVAL;
566*29949e86Sstevel break;
567*29949e86Sstevel }
568*29949e86Sstevel
569*29949e86Sstevel DPRINTF(SYSC_DEBUG, ("Current RState: %d\n", sysc_stat->rstate));
570*29949e86Sstevel DPRINTF(SYSC_DEBUG, ("Current OState: %d\n", sysc_stat->ostate));
571*29949e86Sstevel DPRINTF(SYSC_DEBUG, ("Current Condition: %d\n", sysc_stat->condition));
572*29949e86Sstevel
573*29949e86Sstevel return (retval);
574*29949e86Sstevel }
575*29949e86Sstevel
576*29949e86Sstevel /*
577*29949e86Sstevel * This function is called to check the policy for a request to transition
578*29949e86Sstevel * from the connected/configured state to the connected/unconfigured state only.
579*29949e86Sstevel * All other requests are invalid.
580*29949e86Sstevel */
581*29949e86Sstevel /*ARGSUSED*/
582*29949e86Sstevel int
sysc_policy_unconfigure(struct sysctrl_soft_state * softsp,sysc_cfga_pkt_t * pkt,sysc_cfga_stat_t * sysc_stat)583*29949e86Sstevel sysc_policy_unconfigure(struct sysctrl_soft_state *softsp,
584*29949e86Sstevel sysc_cfga_pkt_t *pkt, sysc_cfga_stat_t *sysc_stat)
585*29949e86Sstevel {
586*29949e86Sstevel int retval;
587*29949e86Sstevel
588*29949e86Sstevel ASSERT(fhc_bdlist_locked());
589*29949e86Sstevel
590*29949e86Sstevel DPRINTF(SYSC_DEBUG, ("Previous RState: %d\n", sysc_stat->rstate));
591*29949e86Sstevel DPRINTF(SYSC_DEBUG, ("Previous OState: %d\n", sysc_stat->ostate));
592*29949e86Sstevel
593*29949e86Sstevel switch (sysc_stat->ostate) {
594*29949e86Sstevel case SYSC_CFGA_OSTATE_CONFIGURED:
595*29949e86Sstevel if (!enable_dynamic_reconfiguration) {
596*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_NON_DR_PROM);
597*29949e86Sstevel return (ENOTSUP);
598*29949e86Sstevel }
599*29949e86Sstevel
600*29949e86Sstevel if (!sysc_policy_hardware_compatible(softsp, sysc_stat, pkt)) {
601*29949e86Sstevel cmn_err(CE_WARN, "%s board %d unconfigure"
602*29949e86Sstevel " is not yet supported.",
603*29949e86Sstevel fhc_bd_typestr(sysc_stat->type), sysc_stat->board);
604*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_HW_COMPAT);
605*29949e86Sstevel return (ENOTSUP);
606*29949e86Sstevel }
607*29949e86Sstevel
608*29949e86Sstevel sysc_policy_audit_messages(SYSC_AUDIT_OSTATE_UNCONFIGURE,
609*29949e86Sstevel sysc_stat);
610*29949e86Sstevel
611*29949e86Sstevel retval = sysc_bd_unconfigure(sysc_stat->board, pkt);
612*29949e86Sstevel if (!retval) {
613*29949e86Sstevel sysc_stat->ostate = SYSC_CFGA_OSTATE_UNCONFIGURED;
614*29949e86Sstevel sysc_policy_audit_messages(
615*29949e86Sstevel SYSC_AUDIT_OSTATE_SUCCEEDED,
616*29949e86Sstevel sysc_stat);
617*29949e86Sstevel } else {
618*29949e86Sstevel sysc_policy_audit_messages(
619*29949e86Sstevel SYSC_AUDIT_OSTATE_UNCONFIGURE_FAILED,
620*29949e86Sstevel sysc_stat);
621*29949e86Sstevel }
622*29949e86Sstevel sysc_policy_connected_condition(softsp, sysc_stat, FALSE);
623*29949e86Sstevel break;
624*29949e86Sstevel case SYSC_CFGA_OSTATE_UNCONFIGURED:
625*29949e86Sstevel default:
626*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_OSTATE);
627*29949e86Sstevel retval = EINVAL;
628*29949e86Sstevel break;
629*29949e86Sstevel }
630*29949e86Sstevel
631*29949e86Sstevel DPRINTF(SYSC_DEBUG, ("Current RState: %d\n", sysc_stat->rstate));
632*29949e86Sstevel DPRINTF(SYSC_DEBUG, ("Current OState: %d\n", sysc_stat->ostate));
633*29949e86Sstevel DPRINTF(SYSC_DEBUG, ("Current Condition: %d\n", sysc_stat->condition));
634*29949e86Sstevel
635*29949e86Sstevel return (retval);
636*29949e86Sstevel }
637*29949e86Sstevel
638*29949e86Sstevel /*
639*29949e86Sstevel * This function is called to check the policy for a requested transition
640*29949e86Sstevel * from either the connected/unconfigured state or the connected/configured
641*29949e86Sstevel * state to the connected/configured state. The redundant state transition
642*29949e86Sstevel * is permitted for partially configured set of devices. Basically, we
643*29949e86Sstevel * retry the configure.
644*29949e86Sstevel */
645*29949e86Sstevel /*ARGSUSED*/
646*29949e86Sstevel int
sysc_policy_configure(struct sysctrl_soft_state * softsp,sysc_cfga_pkt_t * pkt,sysc_cfga_stat_t * sysc_stat)647*29949e86Sstevel sysc_policy_configure(struct sysctrl_soft_state *softsp,
648*29949e86Sstevel sysc_cfga_pkt_t *pkt, sysc_cfga_stat_t *sysc_stat)
649*29949e86Sstevel {
650*29949e86Sstevel int retval;
651*29949e86Sstevel
652*29949e86Sstevel ASSERT(fhc_bdlist_locked());
653*29949e86Sstevel
654*29949e86Sstevel DPRINTF(SYSC_DEBUG, ("Previous RState: %d\n", sysc_stat->rstate));
655*29949e86Sstevel DPRINTF(SYSC_DEBUG, ("Previous OState: %d\n", sysc_stat->ostate));
656*29949e86Sstevel
657*29949e86Sstevel switch (sysc_stat->rstate) {
658*29949e86Sstevel case SYSC_CFGA_RSTATE_CONNECTED:
659*29949e86Sstevel switch (sysc_stat->ostate) {
660*29949e86Sstevel case SYSC_CFGA_OSTATE_UNCONFIGURED:
661*29949e86Sstevel if (sysc_stat->condition != SYSC_CFGA_COND_OK) {
662*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_COND);
663*29949e86Sstevel return (EINVAL);
664*29949e86Sstevel }
665*29949e86Sstevel
666*29949e86Sstevel sysc_policy_audit_messages(SYSC_AUDIT_OSTATE_CONFIGURE,
667*29949e86Sstevel sysc_stat);
668*29949e86Sstevel retval = sysc_bd_configure(sysc_stat->board, pkt);
669*29949e86Sstevel sysc_stat->ostate = SYSC_CFGA_OSTATE_CONFIGURED;
670*29949e86Sstevel sysc_policy_connected_condition(softsp,
671*29949e86Sstevel sysc_stat, FALSE);
672*29949e86Sstevel if (!retval) {
673*29949e86Sstevel sysc_policy_audit_messages(
674*29949e86Sstevel SYSC_AUDIT_OSTATE_SUCCEEDED,
675*29949e86Sstevel sysc_stat);
676*29949e86Sstevel } else {
677*29949e86Sstevel sysc_policy_audit_messages(
678*29949e86Sstevel SYSC_AUDIT_OSTATE_CONFIGURE_FAILED,
679*29949e86Sstevel sysc_stat);
680*29949e86Sstevel }
681*29949e86Sstevel break;
682*29949e86Sstevel case SYSC_CFGA_OSTATE_CONFIGURED:
683*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_OSTATE);
684*29949e86Sstevel retval = ENOTSUP;
685*29949e86Sstevel break;
686*29949e86Sstevel default:
687*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_OSTATE);
688*29949e86Sstevel retval = EINVAL;
689*29949e86Sstevel break;
690*29949e86Sstevel }
691*29949e86Sstevel break;
692*29949e86Sstevel case SYSC_CFGA_RSTATE_EMPTY:
693*29949e86Sstevel case SYSC_CFGA_RSTATE_DISCONNECTED:
694*29949e86Sstevel default:
695*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_RSTATE);
696*29949e86Sstevel retval = EINVAL;
697*29949e86Sstevel break;
698*29949e86Sstevel }
699*29949e86Sstevel
700*29949e86Sstevel
701*29949e86Sstevel DPRINTF(SYSC_DEBUG, ("Current RState: %d\n", sysc_stat->rstate));
702*29949e86Sstevel DPRINTF(SYSC_DEBUG, ("Current OState: %d\n", sysc_stat->ostate));
703*29949e86Sstevel DPRINTF(SYSC_DEBUG, ("Current Condition: %d\n", sysc_stat->condition));
704*29949e86Sstevel
705*29949e86Sstevel return (retval);
706*29949e86Sstevel }
707*29949e86Sstevel
708*29949e86Sstevel /*ARGSUSED*/
709*29949e86Sstevel static void
sysc_policy_empty_condition(struct sysctrl_soft_state * softsp,sysc_cfga_stat_t * sysc_stat,uint_t failure,uint_t ps_mutex_is_held)710*29949e86Sstevel sysc_policy_empty_condition(struct sysctrl_soft_state *softsp,
711*29949e86Sstevel sysc_cfga_stat_t *sysc_stat, uint_t failure,
712*29949e86Sstevel uint_t ps_mutex_is_held)
713*29949e86Sstevel {
714*29949e86Sstevel ASSERT(fhc_bdlist_locked());
715*29949e86Sstevel
716*29949e86Sstevel switch (sysc_stat->condition) {
717*29949e86Sstevel case SYSC_CFGA_COND_UNKNOWN:
718*29949e86Sstevel case SYSC_CFGA_COND_OK:
719*29949e86Sstevel case SYSC_CFGA_COND_FAILING:
720*29949e86Sstevel case SYSC_CFGA_COND_FAILED:
721*29949e86Sstevel /* nothing in the slot so just check power supplies */
722*29949e86Sstevel case SYSC_CFGA_COND_UNUSABLE:
723*29949e86Sstevel if (sysc_policy_enough_cooling(softsp, sysc_stat,
724*29949e86Sstevel ps_mutex_is_held) &&
725*29949e86Sstevel sysc_policy_enough_power(softsp, FALSE,
726*29949e86Sstevel ps_mutex_is_held)) {
727*29949e86Sstevel sysc_stat->condition = SYSC_CFGA_COND_UNKNOWN;
728*29949e86Sstevel } else {
729*29949e86Sstevel sysc_stat->condition = SYSC_CFGA_COND_UNUSABLE;
730*29949e86Sstevel }
731*29949e86Sstevel sysc_stat->last_change = gethrestime_sec();
732*29949e86Sstevel break;
733*29949e86Sstevel default:
734*29949e86Sstevel ASSERT(FALSE);
735*29949e86Sstevel break;
736*29949e86Sstevel }
737*29949e86Sstevel }
738*29949e86Sstevel /*ARGSUSED*/
739*29949e86Sstevel static void
sysc_policy_disconnected_condition(struct sysctrl_soft_state * softsp,sysc_cfga_stat_t * sysc_stat,uint_t failure,uint_t ps_mutex_is_held)740*29949e86Sstevel sysc_policy_disconnected_condition(struct sysctrl_soft_state *softsp,
741*29949e86Sstevel sysc_cfga_stat_t *sysc_stat, uint_t failure,
742*29949e86Sstevel uint_t ps_mutex_is_held)
743*29949e86Sstevel {
744*29949e86Sstevel ASSERT(fhc_bdlist_locked());
745*29949e86Sstevel
746*29949e86Sstevel if (failure) {
747*29949e86Sstevel sysc_stat->condition = SYSC_CFGA_COND_FAILED;
748*29949e86Sstevel sysc_stat->last_change = gethrestime_sec();
749*29949e86Sstevel return;
750*29949e86Sstevel }
751*29949e86Sstevel switch (sysc_stat->condition) {
752*29949e86Sstevel /*
753*29949e86Sstevel * if unknown, we have come from hotplug case so do a quick
754*29949e86Sstevel * reevaluation.
755*29949e86Sstevel */
756*29949e86Sstevel case SYSC_CFGA_COND_UNKNOWN:
757*29949e86Sstevel /*
758*29949e86Sstevel * if ok, we have come from connected to disconnected and we stay
759*29949e86Sstevel * ok until removed or reevaluate when reconnect. We might have
760*29949e86Sstevel * experienced a ps fail so reevaluate the condition.
761*29949e86Sstevel */
762*29949e86Sstevel case SYSC_CFGA_COND_OK:
763*29949e86Sstevel /*
764*29949e86Sstevel * if unsuable, either power supply was missing or
765*29949e86Sstevel * hardware was not compatible. Check to see if
766*29949e86Sstevel * this is still true.
767*29949e86Sstevel */
768*29949e86Sstevel case SYSC_CFGA_COND_UNUSABLE:
769*29949e86Sstevel /*
770*29949e86Sstevel * failing must transition in the disconnected state
771*29949e86Sstevel * to either unusable or unknown. We may have come here
772*29949e86Sstevel * from cfgadm -f -c disconnect after a power supply failure
773*29949e86Sstevel * in an attempt to protect the board.
774*29949e86Sstevel */
775*29949e86Sstevel case SYSC_CFGA_COND_FAILING:
776*29949e86Sstevel if (sysc_policy_enough_cooling(softsp, sysc_stat,
777*29949e86Sstevel ps_mutex_is_held) &&
778*29949e86Sstevel sysc_policy_enough_power(softsp, FALSE,
779*29949e86Sstevel ps_mutex_is_held)) {
780*29949e86Sstevel sysc_stat->condition = SYSC_CFGA_COND_UNKNOWN;
781*29949e86Sstevel } else {
782*29949e86Sstevel sysc_stat->condition = SYSC_CFGA_COND_UNUSABLE;
783*29949e86Sstevel }
784*29949e86Sstevel sysc_stat->last_change = gethrestime_sec();
785*29949e86Sstevel break;
786*29949e86Sstevel /*
787*29949e86Sstevel * if failed, we have failed POST and must stay in this
788*29949e86Sstevel * condition until the board has been removed
789*29949e86Sstevel * before ever coming back into another condition
790*29949e86Sstevel */
791*29949e86Sstevel case SYSC_CFGA_COND_FAILED:
792*29949e86Sstevel break;
793*29949e86Sstevel default:
794*29949e86Sstevel ASSERT(FALSE);
795*29949e86Sstevel break;
796*29949e86Sstevel }
797*29949e86Sstevel }
798*29949e86Sstevel
799*29949e86Sstevel /*ARGSUSED*/
800*29949e86Sstevel static void
sysc_policy_connected_condition(struct sysctrl_soft_state * softsp,sysc_cfga_stat_t * sysc_stat,uint_t ps_mutex_is_held)801*29949e86Sstevel sysc_policy_connected_condition(struct sysctrl_soft_state *softsp,
802*29949e86Sstevel sysc_cfga_stat_t *sysc_stat,
803*29949e86Sstevel uint_t ps_mutex_is_held)
804*29949e86Sstevel {
805*29949e86Sstevel ASSERT(fhc_bdlist_locked());
806*29949e86Sstevel
807*29949e86Sstevel switch (sysc_stat->condition) {
808*29949e86Sstevel case SYSC_CFGA_COND_UNKNOWN:
809*29949e86Sstevel case SYSC_CFGA_COND_OK:
810*29949e86Sstevel case SYSC_CFGA_COND_FAILING:
811*29949e86Sstevel case SYSC_CFGA_COND_UNUSABLE:
812*29949e86Sstevel if (sysc_policy_enough_cooling(softsp, sysc_stat,
813*29949e86Sstevel ps_mutex_is_held) &&
814*29949e86Sstevel sysc_policy_enough_power(softsp, FALSE,
815*29949e86Sstevel ps_mutex_is_held) &&
816*29949e86Sstevel (fhc_env_temp_state(sysc_stat->board) == TEMP_OK)) {
817*29949e86Sstevel sysc_stat->condition = SYSC_CFGA_COND_OK;
818*29949e86Sstevel } else {
819*29949e86Sstevel sysc_stat->condition = SYSC_CFGA_COND_FAILING;
820*29949e86Sstevel }
821*29949e86Sstevel sysc_stat->last_change = gethrestime_sec();
822*29949e86Sstevel break;
823*29949e86Sstevel case SYSC_CFGA_COND_FAILED:
824*29949e86Sstevel break;
825*29949e86Sstevel default:
826*29949e86Sstevel ASSERT(FALSE);
827*29949e86Sstevel break;
828*29949e86Sstevel }
829*29949e86Sstevel }
830*29949e86Sstevel
831*29949e86Sstevel static void
sysc_policy_set_condition(void * sp,sysc_cfga_stat_t * sysc_stat,uint_t ps_mutex_is_held)832*29949e86Sstevel sysc_policy_set_condition(void *sp, sysc_cfga_stat_t *sysc_stat,
833*29949e86Sstevel uint_t ps_mutex_is_held)
834*29949e86Sstevel {
835*29949e86Sstevel struct sysctrl_soft_state *softsp = (struct sysctrl_soft_state *)sp;
836*29949e86Sstevel
837*29949e86Sstevel ASSERT(fhc_bdlist_locked());
838*29949e86Sstevel
839*29949e86Sstevel switch (sysc_stat->rstate) {
840*29949e86Sstevel case SYSC_CFGA_RSTATE_EMPTY:
841*29949e86Sstevel sysc_policy_empty_condition(softsp, sysc_stat,
842*29949e86Sstevel FALSE, ps_mutex_is_held);
843*29949e86Sstevel break;
844*29949e86Sstevel case SYSC_CFGA_RSTATE_DISCONNECTED:
845*29949e86Sstevel sysc_policy_disconnected_condition(softsp, sysc_stat,
846*29949e86Sstevel FALSE, ps_mutex_is_held);
847*29949e86Sstevel break;
848*29949e86Sstevel case SYSC_CFGA_RSTATE_CONNECTED:
849*29949e86Sstevel sysc_policy_connected_condition(softsp, sysc_stat,
850*29949e86Sstevel ps_mutex_is_held);
851*29949e86Sstevel break;
852*29949e86Sstevel default:
853*29949e86Sstevel ASSERT(FALSE);
854*29949e86Sstevel break;
855*29949e86Sstevel }
856*29949e86Sstevel }
857*29949e86Sstevel
858*29949e86Sstevel void
sysc_policy_update(void * softsp,sysc_cfga_stat_t * sysc_stat,sysc_evt_t event)859*29949e86Sstevel sysc_policy_update(void *softsp, sysc_cfga_stat_t *sysc_stat,
860*29949e86Sstevel sysc_evt_t event)
861*29949e86Sstevel {
862*29949e86Sstevel fhc_bd_t *list;
863*29949e86Sstevel
864*29949e86Sstevel ASSERT(event == SYSC_EVT_BD_HP_DISABLED || fhc_bdlist_locked());
865*29949e86Sstevel
866*29949e86Sstevel switch (event) {
867*29949e86Sstevel case SYSC_EVT_BD_EMPTY:
868*29949e86Sstevel sysc_stat->rstate = SYSC_CFGA_RSTATE_EMPTY;
869*29949e86Sstevel sysc_stat->ostate = SYSC_CFGA_OSTATE_UNCONFIGURED;
870*29949e86Sstevel sysc_stat->condition = SYSC_CFGA_COND_UNKNOWN;
871*29949e86Sstevel sysc_policy_empty_condition(softsp, sysc_stat, FALSE, FALSE);
872*29949e86Sstevel break;
873*29949e86Sstevel case SYSC_EVT_BD_PRESENT:
874*29949e86Sstevel if (sysc_stat->type == DISK_BOARD) {
875*29949e86Sstevel sysc_stat->rstate = SYSC_CFGA_RSTATE_DISCONNECTED;
876*29949e86Sstevel sysc_stat->ostate = SYSC_CFGA_OSTATE_UNCONFIGURED;
877*29949e86Sstevel sysc_stat->condition = SYSC_CFGA_COND_UNKNOWN;
878*29949e86Sstevel } else {
879*29949e86Sstevel sysc_stat->rstate = SYSC_CFGA_RSTATE_CONNECTED;
880*29949e86Sstevel sysc_stat->ostate = SYSC_CFGA_OSTATE_CONFIGURED;
881*29949e86Sstevel sysc_stat->condition = SYSC_CFGA_COND_OK;
882*29949e86Sstevel }
883*29949e86Sstevel sysc_stat->last_change = gethrestime_sec();
884*29949e86Sstevel break;
885*29949e86Sstevel case SYSC_EVT_BD_DISABLED:
886*29949e86Sstevel sysc_stat->rstate = SYSC_CFGA_RSTATE_DISCONNECTED;
887*29949e86Sstevel sysc_stat->ostate = SYSC_CFGA_OSTATE_UNCONFIGURED;
888*29949e86Sstevel sysc_stat->condition = SYSC_CFGA_COND_UNKNOWN;
889*29949e86Sstevel sysc_policy_disconnected_condition(softsp,
890*29949e86Sstevel sysc_stat, FALSE, FALSE);
891*29949e86Sstevel cmn_err(CE_NOTE,
892*29949e86Sstevel "disabled %s board in slot %d",
893*29949e86Sstevel fhc_bd_typestr(sysc_stat->type),
894*29949e86Sstevel sysc_stat->board);
895*29949e86Sstevel break;
896*29949e86Sstevel case SYSC_EVT_BD_FAILED:
897*29949e86Sstevel sysc_stat->rstate = SYSC_CFGA_RSTATE_DISCONNECTED;
898*29949e86Sstevel sysc_stat->ostate = SYSC_CFGA_OSTATE_UNCONFIGURED;
899*29949e86Sstevel sysc_stat->condition = SYSC_CFGA_COND_UNUSABLE;
900*29949e86Sstevel sysc_policy_disconnected_condition(softsp, sysc_stat,
901*29949e86Sstevel TRUE, FALSE);
902*29949e86Sstevel cmn_err(CE_WARN,
903*29949e86Sstevel "failed %s board in slot %d",
904*29949e86Sstevel fhc_bd_typestr(sysc_stat->type),
905*29949e86Sstevel sysc_stat->board);
906*29949e86Sstevel break;
907*29949e86Sstevel case SYSC_EVT_BD_OVERTEMP:
908*29949e86Sstevel case SYSC_EVT_BD_TEMP_OK:
909*29949e86Sstevel sysc_policy_set_condition((void *)softsp, sysc_stat, FALSE);
910*29949e86Sstevel break;
911*29949e86Sstevel case SYSC_EVT_BD_PS_CHANGE:
912*29949e86Sstevel for (list = fhc_bd_first(); list; list = fhc_bd_next(list)) {
913*29949e86Sstevel sysc_stat = &(list->sc);
914*29949e86Sstevel sysc_policy_set_condition((void *)softsp,
915*29949e86Sstevel sysc_stat, TRUE);
916*29949e86Sstevel }
917*29949e86Sstevel break;
918*29949e86Sstevel case SYSC_EVT_BD_INS_FAILED:
919*29949e86Sstevel cmn_err(CE_WARN, "powerdown of board %d failed",
920*29949e86Sstevel sysc_stat->board);
921*29949e86Sstevel break;
922*29949e86Sstevel case SYSC_EVT_BD_INSERTED:
923*29949e86Sstevel sysc_stat->rstate = SYSC_CFGA_RSTATE_DISCONNECTED;
924*29949e86Sstevel sysc_stat->ostate = SYSC_CFGA_OSTATE_UNCONFIGURED;
925*29949e86Sstevel sysctrl_post_config_change(softsp);
926*29949e86Sstevel sysc_policy_disconnected_condition(softsp,
927*29949e86Sstevel sysc_stat, FALSE, FALSE);
928*29949e86Sstevel cmn_err(CE_NOTE, "%s board has been inserted into slot %d",
929*29949e86Sstevel fhc_bd_typestr(sysc_stat->type), sysc_stat->board);
930*29949e86Sstevel cmn_err(CE_NOTE,
931*29949e86Sstevel "board %d can be removed", sysc_stat->board);
932*29949e86Sstevel break;
933*29949e86Sstevel case SYSC_EVT_BD_REMOVED:
934*29949e86Sstevel sysc_stat->rstate = SYSC_CFGA_RSTATE_EMPTY;
935*29949e86Sstevel sysc_stat->ostate = SYSC_CFGA_OSTATE_UNCONFIGURED;
936*29949e86Sstevel sysc_stat->condition = SYSC_CFGA_COND_UNKNOWN;
937*29949e86Sstevel
938*29949e86Sstevel /* now it is ok to free the ac pa memory database */
939*29949e86Sstevel fhc_del_memloc(sysc_stat->board);
940*29949e86Sstevel
941*29949e86Sstevel /* reinitialize sysc_cfga_stat structure */
942*29949e86Sstevel sysc_stat->type = UNKNOWN_BOARD;
943*29949e86Sstevel sysc_stat->fhc_compid = 0;
944*29949e86Sstevel sysc_stat->ac_compid = 0;
945*29949e86Sstevel (void) bzero(&(sysc_stat->prom_rev),
946*29949e86Sstevel sizeof (sysc_stat->prom_rev));
947*29949e86Sstevel (void) bzero(&(sysc_stat->bd),
948*29949e86Sstevel sizeof (union bd_un));
949*29949e86Sstevel sysc_stat->no_detach = sysc_stat->plus_board = 0;
950*29949e86Sstevel sysc_policy_disconnected_condition(softsp,
951*29949e86Sstevel sysc_stat, FALSE, FALSE);
952*29949e86Sstevel cmn_err(CE_NOTE, "board %d has been removed",
953*29949e86Sstevel sysc_stat->board);
954*29949e86Sstevel break;
955*29949e86Sstevel case SYSC_EVT_BD_HP_DISABLED:
956*29949e86Sstevel cmn_err(CE_NOTE, "Hot Plug not supported in this system");
957*29949e86Sstevel break;
958*29949e86Sstevel case SYSC_EVT_BD_CORE_RESOURCE_DISCONNECT:
959*29949e86Sstevel cmn_err(CE_WARN, "board %d cannot be disconnected because it"
960*29949e86Sstevel " is a core system resource", sysc_stat->board);
961*29949e86Sstevel break;
962*29949e86Sstevel default:
963*29949e86Sstevel ASSERT(FALSE);
964*29949e86Sstevel break;
965*29949e86Sstevel }
966*29949e86Sstevel
967*29949e86Sstevel }
968*29949e86Sstevel
969*29949e86Sstevel /*
970*29949e86Sstevel * signal to POST that the system has been reconfigured and that
971*29949e86Sstevel * the system configuration status information should be invalidated
972*29949e86Sstevel * the next time through POST
973*29949e86Sstevel */
974*29949e86Sstevel static void
sysctrl_post_config_change(struct sysctrl_soft_state * softsp)975*29949e86Sstevel sysctrl_post_config_change(struct sysctrl_soft_state *softsp)
976*29949e86Sstevel {
977*29949e86Sstevel /*
978*29949e86Sstevel * We are heading into a configuration change!
979*29949e86Sstevel * Tell post to invalidate its notion of the system configuration.
980*29949e86Sstevel * This is done by clearing the clock registers...
981*29949e86Sstevel */
982*29949e86Sstevel *softsp->clk_freq1 = 0;
983*29949e86Sstevel *softsp->clk_freq2 &=
984*29949e86Sstevel ~(CLOCK_FREQ_8 | CLOCK_DIV_1 | CLOCK_RANGE | CLOCK_DIV_0);
985*29949e86Sstevel }
986*29949e86Sstevel
987*29949e86Sstevel static int
sysc_attach_board(void * arg)988*29949e86Sstevel sysc_attach_board(void *arg)
989*29949e86Sstevel {
990*29949e86Sstevel int board = *(int *)arg;
991*29949e86Sstevel
992*29949e86Sstevel return (prom_sunfire_attach_board((uint_t)board));
993*29949e86Sstevel }
994*29949e86Sstevel
995*29949e86Sstevel static int
sysc_bd_connect(int board,sysc_cfga_pkt_t * pkt)996*29949e86Sstevel sysc_bd_connect(int board, sysc_cfga_pkt_t *pkt)
997*29949e86Sstevel {
998*29949e86Sstevel int error = 0;
999*29949e86Sstevel fhc_bd_t *bdp;
1000*29949e86Sstevel sysc_dr_handle_t *sh;
1001*29949e86Sstevel uint64_t mempa;
1002*29949e86Sstevel int del_kstat = 0;
1003*29949e86Sstevel
1004*29949e86Sstevel ASSERT(fhc_bd_busy(board));
1005*29949e86Sstevel
1006*29949e86Sstevel bdp = fhc_bd(board);
1007*29949e86Sstevel
1008*29949e86Sstevel /* find gap for largest supported simm in advance */
1009*29949e86Sstevel #define MAX_BANK_SIZE_MB (2 * 1024)
1010*29949e86Sstevel #define BANKS_PER_BOARD 2
1011*29949e86Sstevel mempa = fhc_find_memloc_gap(BANKS_PER_BOARD * MAX_BANK_SIZE_MB);
1012*29949e86Sstevel
1013*29949e86Sstevel fhc_bdlist_unlock();
1014*29949e86Sstevel
1015*29949e86Sstevel /* TODO: Is mempa vulnerable to re-use here? */
1016*29949e86Sstevel
1017*29949e86Sstevel sysctrl_suspend_prepare();
1018*29949e86Sstevel
1019*29949e86Sstevel if ((error = sysctrl_suspend(pkt)) == DDI_SUCCESS) {
1020*29949e86Sstevel /* ASSERT(jtag not held) */
1021*29949e86Sstevel error = prom_tree_update(sysc_attach_board, &board);
1022*29949e86Sstevel if (error) {
1023*29949e86Sstevel error = EIO;
1024*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_PROM);
1025*29949e86Sstevel } else {
1026*29949e86Sstevel /* attempt to program the memory while frozen */
1027*29949e86Sstevel fhc_program_memory(board, mempa);
1028*29949e86Sstevel }
1029*29949e86Sstevel sysctrl_resume(pkt);
1030*29949e86Sstevel }
1031*29949e86Sstevel
1032*29949e86Sstevel if (error) {
1033*29949e86Sstevel goto done;
1034*29949e86Sstevel }
1035*29949e86Sstevel
1036*29949e86Sstevel /*
1037*29949e86Sstevel * Must not delete kstat used by prtdiag until the PROM
1038*29949e86Sstevel * has successfully connected to board.
1039*29949e86Sstevel */
1040*29949e86Sstevel del_kstat = 1;
1041*29949e86Sstevel
1042*29949e86Sstevel sh = &bdp->sh[SYSC_DR_HANDLE_FHC];
1043*29949e86Sstevel sh->flags |= SYSC_DR_FHC;
1044*29949e86Sstevel sh->errstr = pkt->errbuf;
1045*29949e86Sstevel
1046*29949e86Sstevel sysc_dr_init(sh);
1047*29949e86Sstevel
1048*29949e86Sstevel error = sysc_dr_attach(sh, board);
1049*29949e86Sstevel if (error)
1050*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_NDI_ATTACH);
1051*29949e86Sstevel
1052*29949e86Sstevel sysc_dr_uninit(sh);
1053*29949e86Sstevel
1054*29949e86Sstevel if (enable_redist) {
1055*29949e86Sstevel mutex_enter(&cpu_lock);
1056*29949e86Sstevel intr_redist_all_cpus();
1057*29949e86Sstevel mutex_exit(&cpu_lock);
1058*29949e86Sstevel }
1059*29949e86Sstevel done:
1060*29949e86Sstevel if (del_kstat && bdp->ksp) {
1061*29949e86Sstevel kstat_delete(bdp->ksp);
1062*29949e86Sstevel bdp->ksp = NULL;
1063*29949e86Sstevel }
1064*29949e86Sstevel
1065*29949e86Sstevel (void) fhc_bdlist_lock(-1);
1066*29949e86Sstevel
1067*29949e86Sstevel return (error);
1068*29949e86Sstevel }
1069*29949e86Sstevel
1070*29949e86Sstevel static int
sysc_detach_board(void * arg)1071*29949e86Sstevel sysc_detach_board(void * arg)
1072*29949e86Sstevel {
1073*29949e86Sstevel int rt;
1074*29949e86Sstevel cpuset_t xcset;
1075*29949e86Sstevel struct jt_mstr *jtm;
1076*29949e86Sstevel int board = *(int *)arg;
1077*29949e86Sstevel
1078*29949e86Sstevel (void) fhc_bdlist_lock(-1);
1079*29949e86Sstevel
1080*29949e86Sstevel #ifdef DEBUG
1081*29949e86Sstevel /* it is important to have fhc_bdlist_lock() earlier */
1082*29949e86Sstevel if (sysctrl_enable_regdump)
1083*29949e86Sstevel precache_regdump(board);
1084*29949e86Sstevel #endif /* DEBUG */
1085*29949e86Sstevel
1086*29949e86Sstevel jtm = jtag_master_lock();
1087*29949e86Sstevel CPUSET_ALL(xcset);
1088*29949e86Sstevel promsafe_xc_attention(xcset);
1089*29949e86Sstevel
1090*29949e86Sstevel #ifdef DEBUG
1091*29949e86Sstevel if (sysctrl_enable_regdump)
1092*29949e86Sstevel boardstat_regdump();
1093*29949e86Sstevel #endif /* DEBUG */
1094*29949e86Sstevel
1095*29949e86Sstevel rt = prom_sunfire_detach_board((uint_t)board);
1096*29949e86Sstevel
1097*29949e86Sstevel #ifdef DEBUG
1098*29949e86Sstevel if (sysctrl_enable_regdump)
1099*29949e86Sstevel display_regdump();
1100*29949e86Sstevel #endif /* DEBUG */
1101*29949e86Sstevel
1102*29949e86Sstevel xc_dismissed(xcset);
1103*29949e86Sstevel jtag_master_unlock(jtm);
1104*29949e86Sstevel fhc_bdlist_unlock();
1105*29949e86Sstevel return (rt);
1106*29949e86Sstevel }
1107*29949e86Sstevel
1108*29949e86Sstevel static int
sysc_bd_disconnect(int board,sysc_cfga_pkt_t * pkt)1109*29949e86Sstevel sysc_bd_disconnect(int board, sysc_cfga_pkt_t *pkt)
1110*29949e86Sstevel {
1111*29949e86Sstevel int error;
1112*29949e86Sstevel fhc_bd_t *bdp;
1113*29949e86Sstevel sysc_dr_handle_t *sh;
1114*29949e86Sstevel void fhc_bd_ks_alloc(fhc_bd_t *);
1115*29949e86Sstevel
1116*29949e86Sstevel ASSERT(fhc_bd_busy(board));
1117*29949e86Sstevel ASSERT(!fhc_bd_is_jtag_master(board));
1118*29949e86Sstevel
1119*29949e86Sstevel
1120*29949e86Sstevel bdp = fhc_bd(board);
1121*29949e86Sstevel
1122*29949e86Sstevel bdp->flags |= BDF_DETACH;
1123*29949e86Sstevel
1124*29949e86Sstevel fhc_bdlist_unlock();
1125*29949e86Sstevel
1126*29949e86Sstevel sh = &bdp->sh[SYSC_DR_HANDLE_FHC];
1127*29949e86Sstevel sh->errstr = pkt->errbuf;
1128*29949e86Sstevel
1129*29949e86Sstevel ASSERT(sh->dip_list == NULL);
1130*29949e86Sstevel
1131*29949e86Sstevel sh->flags |= SYSC_DR_FHC;
1132*29949e86Sstevel sysc_dr_init(sh);
1133*29949e86Sstevel
1134*29949e86Sstevel error = sysc_dr_detach(sh, board);
1135*29949e86Sstevel sh->flags &= ~SYSC_DR_REMOVE;
1136*29949e86Sstevel
1137*29949e86Sstevel sysc_dr_uninit(sh);
1138*29949e86Sstevel if (error) {
1139*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_NDI_DETACH);
1140*29949e86Sstevel goto done;
1141*29949e86Sstevel }
1142*29949e86Sstevel error = prom_tree_update(sysc_detach_board, &board);
1143*29949e86Sstevel
1144*29949e86Sstevel if (error) {
1145*29949e86Sstevel error = EIO;
1146*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_PROM);
1147*29949e86Sstevel goto done;
1148*29949e86Sstevel }
1149*29949e86Sstevel
1150*29949e86Sstevel if (enable_redist) {
1151*29949e86Sstevel mutex_enter(&cpu_lock);
1152*29949e86Sstevel intr_redist_all_cpus();
1153*29949e86Sstevel mutex_exit(&cpu_lock);
1154*29949e86Sstevel }
1155*29949e86Sstevel
1156*29949e86Sstevel fhc_bd_ks_alloc(bdp);
1157*29949e86Sstevel done:
1158*29949e86Sstevel (void) fhc_bdlist_lock(-1);
1159*29949e86Sstevel
1160*29949e86Sstevel return (error);
1161*29949e86Sstevel }
1162*29949e86Sstevel
1163*29949e86Sstevel static int
sysc_bd_configure(int board,sysc_cfga_pkt_t * pkt)1164*29949e86Sstevel sysc_bd_configure(int board, sysc_cfga_pkt_t *pkt)
1165*29949e86Sstevel {
1166*29949e86Sstevel int error = 0;
1167*29949e86Sstevel fhc_bd_t *bdp;
1168*29949e86Sstevel sysc_dr_handle_t *sh;
1169*29949e86Sstevel
1170*29949e86Sstevel ASSERT(fhc_bd_busy(board));
1171*29949e86Sstevel
1172*29949e86Sstevel bdp = fhc_bd(board);
1173*29949e86Sstevel
1174*29949e86Sstevel fhc_bdlist_unlock();
1175*29949e86Sstevel
1176*29949e86Sstevel
1177*29949e86Sstevel sh = &bdp->sh[SYSC_DR_HANDLE_DEVS];
1178*29949e86Sstevel sh->errstr = pkt->errbuf;
1179*29949e86Sstevel
1180*29949e86Sstevel ASSERT(sh->dip_list == NULL);
1181*29949e86Sstevel
1182*29949e86Sstevel sysc_dr_init(sh);
1183*29949e86Sstevel
1184*29949e86Sstevel sh->flags |= SYSC_DR_DEVS;
1185*29949e86Sstevel error = sysc_dr_attach(sh, board);
1186*29949e86Sstevel if (error) {
1187*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_NDI_ATTACH);
1188*29949e86Sstevel sysc_dr_uninit(sh);
1189*29949e86Sstevel goto done;
1190*29949e86Sstevel }
1191*29949e86Sstevel
1192*29949e86Sstevel sysc_dr_uninit(sh);
1193*29949e86Sstevel
1194*29949e86Sstevel if (enable_redist) {
1195*29949e86Sstevel mutex_enter(&cpu_lock);
1196*29949e86Sstevel intr_redist_all_cpus();
1197*29949e86Sstevel mutex_exit(&cpu_lock);
1198*29949e86Sstevel }
1199*29949e86Sstevel done:
1200*29949e86Sstevel if (bdp->sc.type == CPU_BOARD) {
1201*29949e86Sstevel /*
1202*29949e86Sstevel * Value of error gets lost for CPU boards.
1203*29949e86Sstevel */
1204*29949e86Sstevel mutex_enter(&cpu_lock);
1205*29949e86Sstevel
1206*29949e86Sstevel error = find_and_setup_cpu(FHC_BOARD2CPU_A(board));
1207*29949e86Sstevel if ((error == 0) || (error == ENODEV)) {
1208*29949e86Sstevel int retval_b;
1209*29949e86Sstevel
1210*29949e86Sstevel retval_b = find_and_setup_cpu(FHC_BOARD2CPU_B(board));
1211*29949e86Sstevel if (retval_b != ENODEV)
1212*29949e86Sstevel error = retval_b;
1213*29949e86Sstevel }
1214*29949e86Sstevel
1215*29949e86Sstevel mutex_exit(&cpu_lock);
1216*29949e86Sstevel }
1217*29949e86Sstevel
1218*29949e86Sstevel (void) fhc_bdlist_lock(-1);
1219*29949e86Sstevel
1220*29949e86Sstevel return (error);
1221*29949e86Sstevel }
1222*29949e86Sstevel
1223*29949e86Sstevel static int
sysc_bd_unconfigure(int board,sysc_cfga_pkt_t * pkt)1224*29949e86Sstevel sysc_bd_unconfigure(int board, sysc_cfga_pkt_t *pkt)
1225*29949e86Sstevel {
1226*29949e86Sstevel int error;
1227*29949e86Sstevel fhc_bd_t *bdp;
1228*29949e86Sstevel sysc_dr_handle_t *sh;
1229*29949e86Sstevel
1230*29949e86Sstevel ASSERT(fhc_bdlist_locked());
1231*29949e86Sstevel ASSERT(fhc_bd_busy(board));
1232*29949e86Sstevel
1233*29949e86Sstevel bdp = fhc_bd(board);
1234*29949e86Sstevel
1235*29949e86Sstevel if (bdp->sc.type == CPU_BOARD || bdp->sc.type == MEM_BOARD) {
1236*29949e86Sstevel struct ac_soft_state *acsp;
1237*29949e86Sstevel
1238*29949e86Sstevel /*
1239*29949e86Sstevel * Check that any memory on board is not in use.
1240*29949e86Sstevel * This must be done while the board list lock is held
1241*29949e86Sstevel * as memory state can change while fhc_bd_busy() is true
1242*29949e86Sstevel * even though a memory operation cannot be started
1243*29949e86Sstevel * if fhc_bd_busy() is true.
1244*29949e86Sstevel */
1245*29949e86Sstevel if ((acsp = (struct ac_soft_state *)bdp->ac_softsp) != NULL) {
1246*29949e86Sstevel if (acsp->bank[Bank0].busy != 0 ||
1247*29949e86Sstevel acsp->bank[Bank0].ostate ==
1248*29949e86Sstevel SYSC_CFGA_OSTATE_CONFIGURED) {
1249*29949e86Sstevel cmn_err(CE_WARN, "memory bank %d in "
1250*29949e86Sstevel "slot %d is in use.", Bank0, board);
1251*29949e86Sstevel (void) snprintf(pkt->errbuf,
1252*29949e86Sstevel SYSC_OUTPUT_LEN,
1253*29949e86Sstevel "memory bank %d in use",
1254*29949e86Sstevel Bank0);
1255*29949e86Sstevel return (EBUSY);
1256*29949e86Sstevel }
1257*29949e86Sstevel
1258*29949e86Sstevel if (acsp->bank[Bank1].busy != 0 ||
1259*29949e86Sstevel acsp->bank[Bank1].ostate ==
1260*29949e86Sstevel SYSC_CFGA_OSTATE_CONFIGURED) {
1261*29949e86Sstevel cmn_err(CE_WARN, "memory bank %d in "
1262*29949e86Sstevel "slot %d is in use.", Bank1, board);
1263*29949e86Sstevel (void) snprintf(pkt->errbuf,
1264*29949e86Sstevel SYSC_OUTPUT_LEN,
1265*29949e86Sstevel "memory bank %d in use",
1266*29949e86Sstevel Bank1);
1267*29949e86Sstevel return (EBUSY);
1268*29949e86Sstevel }
1269*29949e86Sstevel /*
1270*29949e86Sstevel * Nothing more to do here. The memory interface
1271*29949e86Sstevel * will not make any transitions while
1272*29949e86Sstevel * fhc_bd_busy() is true. Once the ostate
1273*29949e86Sstevel * becomes unconfigured, the memory becomes
1274*29949e86Sstevel * invisible.
1275*29949e86Sstevel */
1276*29949e86Sstevel }
1277*29949e86Sstevel error = 0;
1278*29949e86Sstevel if (bdp->sc.type == CPU_BOARD) {
1279*29949e86Sstevel struct cpu *cpua, *cpub;
1280*29949e86Sstevel int cpu_flags = 0;
1281*29949e86Sstevel
1282*29949e86Sstevel if (pkt->cmd_cfga.force)
1283*29949e86Sstevel cpu_flags = CPU_FORCED;
1284*29949e86Sstevel
1285*29949e86Sstevel fhc_bdlist_unlock();
1286*29949e86Sstevel
1287*29949e86Sstevel mutex_enter(&cpu_lock); /* protects CPU states */
1288*29949e86Sstevel
1289*29949e86Sstevel error = fhc_board_poweroffcpus(board, pkt->errbuf,
1290*29949e86Sstevel cpu_flags);
1291*29949e86Sstevel
1292*29949e86Sstevel cpua = cpu_get(FHC_BOARD2CPU_A(board));
1293*29949e86Sstevel cpub = cpu_get(FHC_BOARD2CPU_B(board));
1294*29949e86Sstevel
1295*29949e86Sstevel if ((error == 0) && (cpua != NULL)) {
1296*29949e86Sstevel error = cpu_unconfigure(cpua->cpu_id);
1297*29949e86Sstevel if (error != 0) {
1298*29949e86Sstevel (void) snprintf(pkt->errbuf,
1299*29949e86Sstevel SYSC_OUTPUT_LEN,
1300*29949e86Sstevel "processor %d unconfigure failed",
1301*29949e86Sstevel cpua->cpu_id);
1302*29949e86Sstevel }
1303*29949e86Sstevel }
1304*29949e86Sstevel if ((error == 0) && (cpub != NULL)) {
1305*29949e86Sstevel error = cpu_unconfigure(cpub->cpu_id);
1306*29949e86Sstevel if (error != 0) {
1307*29949e86Sstevel (void) snprintf(pkt->errbuf,
1308*29949e86Sstevel SYSC_OUTPUT_LEN,
1309*29949e86Sstevel "processor %d unconfigure failed",
1310*29949e86Sstevel cpub->cpu_id);
1311*29949e86Sstevel }
1312*29949e86Sstevel }
1313*29949e86Sstevel
1314*29949e86Sstevel mutex_exit(&cpu_lock);
1315*29949e86Sstevel
1316*29949e86Sstevel (void) fhc_bdlist_lock(-1);
1317*29949e86Sstevel }
1318*29949e86Sstevel
1319*29949e86Sstevel if (error != 0)
1320*29949e86Sstevel return (error);
1321*29949e86Sstevel }
1322*29949e86Sstevel
1323*29949e86Sstevel fhc_bdlist_unlock();
1324*29949e86Sstevel
1325*29949e86Sstevel sh = &bdp->sh[SYSC_DR_HANDLE_DEVS];
1326*29949e86Sstevel sh->errstr = pkt->errbuf;
1327*29949e86Sstevel
1328*29949e86Sstevel ASSERT(sh->dip_list == NULL);
1329*29949e86Sstevel
1330*29949e86Sstevel sysc_dr_init(sh);
1331*29949e86Sstevel
1332*29949e86Sstevel sh->flags |= SYSC_DR_DEVS;
1333*29949e86Sstevel error = sysc_dr_detach(sh, board);
1334*29949e86Sstevel sh->flags &= ~SYSC_DR_REMOVE;
1335*29949e86Sstevel if (error) {
1336*29949e86Sstevel SYSC_ERR_SET(pkt, SYSC_ERR_NDI_DETACH);
1337*29949e86Sstevel sysc_dr_uninit(sh);
1338*29949e86Sstevel goto done;
1339*29949e86Sstevel }
1340*29949e86Sstevel
1341*29949e86Sstevel sysc_dr_uninit(sh);
1342*29949e86Sstevel
1343*29949e86Sstevel if (enable_redist) {
1344*29949e86Sstevel mutex_enter(&cpu_lock);
1345*29949e86Sstevel intr_redist_all_cpus();
1346*29949e86Sstevel mutex_exit(&cpu_lock);
1347*29949e86Sstevel }
1348*29949e86Sstevel
1349*29949e86Sstevel done:
1350*29949e86Sstevel (void) fhc_bdlist_lock(-1);
1351*29949e86Sstevel
1352*29949e86Sstevel return (error);
1353*29949e86Sstevel }
1354*29949e86Sstevel
1355*29949e86Sstevel
1356*29949e86Sstevel typedef struct sysc_prom {
1357*29949e86Sstevel sysc_dr_handle_t *handle; /* DR handle */
1358*29949e86Sstevel int board; /* board id */
1359*29949e86Sstevel dev_info_t **dipp; /* next slot for storing dip */
1360*29949e86Sstevel } sysc_prom_t;
1361*29949e86Sstevel
1362*29949e86Sstevel /*
1363*29949e86Sstevel * Attaching devices on a board.
1364*29949e86Sstevel */
1365*29949e86Sstevel static int
sysc_dr_attach(sysc_dr_handle_t * handle,int board)1366*29949e86Sstevel sysc_dr_attach(sysc_dr_handle_t *handle, int board)
1367*29949e86Sstevel {
1368*29949e86Sstevel int i;
1369*29949e86Sstevel int err;
1370*29949e86Sstevel sysc_prom_t arg;
1371*29949e86Sstevel devi_branch_t b = {0};
1372*29949e86Sstevel
1373*29949e86Sstevel arg.handle = handle;
1374*29949e86Sstevel arg.board = board;
1375*29949e86Sstevel arg.dipp = handle->dip_list;
1376*29949e86Sstevel
1377*29949e86Sstevel b.arg = &arg;
1378*29949e86Sstevel b.type = DEVI_BRANCH_PROM;
1379*29949e86Sstevel b.create.prom_branch_select = sysc_prom_select;
1380*29949e86Sstevel b.devi_branch_callback = sysc_branch_callback;
1381*29949e86Sstevel
1382*29949e86Sstevel handle->error = e_ddi_branch_create(ddi_root_node(), &b,
1383*29949e86Sstevel NULL, DEVI_BRANCH_CHILD);
1384*29949e86Sstevel
1385*29949e86Sstevel if (handle->error)
1386*29949e86Sstevel return (handle->error);
1387*29949e86Sstevel
1388*29949e86Sstevel for (i = 0, arg.dipp = handle->dip_list;
1389*29949e86Sstevel i < handle->dip_list_len; i++, arg.dipp++) {
1390*29949e86Sstevel
1391*29949e86Sstevel err = e_ddi_branch_configure(*arg.dipp, NULL, 0);
1392*29949e86Sstevel /*
1393*29949e86Sstevel * Error only if we fail for fhc dips
1394*29949e86Sstevel */
1395*29949e86Sstevel if (err && (handle->flags & SYSC_DR_FHC)) {
1396*29949e86Sstevel handle->error = err;
1397*29949e86Sstevel sysc_dr_err_decode(handle, *arg.dipp, TRUE);
1398*29949e86Sstevel return (handle->error);
1399*29949e86Sstevel }
1400*29949e86Sstevel }
1401*29949e86Sstevel
1402*29949e86Sstevel return (0);
1403*29949e86Sstevel }
1404*29949e86Sstevel
1405*29949e86Sstevel /*ARGSUSED*/
1406*29949e86Sstevel static int
sysc_make_list(void * arg,int has_changed)1407*29949e86Sstevel sysc_make_list(void *arg, int has_changed)
1408*29949e86Sstevel {
1409*29949e86Sstevel dev_info_t *rdip;
1410*29949e86Sstevel sysc_prom_t *wp = (sysc_prom_t *)arg;
1411*29949e86Sstevel pnode_t nid = prom_childnode(prom_rootnode());
1412*29949e86Sstevel
1413*29949e86Sstevel if (wp == NULL)
1414*29949e86Sstevel return (EINVAL);
1415*29949e86Sstevel
1416*29949e86Sstevel for (; nid != OBP_NONODE && nid != OBP_BADNODE;
1417*29949e86Sstevel nid = prom_nextnode(nid)) {
1418*29949e86Sstevel if (sysc_prom_select(nid, arg, 0) != DDI_SUCCESS)
1419*29949e86Sstevel continue;
1420*29949e86Sstevel if (wp->handle->dip_list_len < SYSC_DR_MAX_NODE) {
1421*29949e86Sstevel rdip = wp->handle->dip_list[wp->handle->dip_list_len] =
1422*29949e86Sstevel e_ddi_nodeid_to_dip(nid);
1423*29949e86Sstevel if (rdip != NULL) {
1424*29949e86Sstevel wp->handle->dip_list_len++;
1425*29949e86Sstevel /*
1426*29949e86Sstevel * Branch rooted at dip already held, so
1427*29949e86Sstevel * release hold acquired in e_ddi_nodeid_to_dip
1428*29949e86Sstevel */
1429*29949e86Sstevel ddi_release_devi(rdip);
1430*29949e86Sstevel ASSERT(e_ddi_branch_held(rdip));
1431*29949e86Sstevel #ifdef DEBUG
1432*29949e86Sstevel } else {
1433*29949e86Sstevel DPRINTF(SYSC_DEBUG, ("sysc_make_list:"
1434*29949e86Sstevel " e_ddi_nodeid_to_dip() failed for"
1435*29949e86Sstevel " nodeid: %d\n", nid));
1436*29949e86Sstevel #endif
1437*29949e86Sstevel }
1438*29949e86Sstevel } else {
1439*29949e86Sstevel #ifdef DEBUG
1440*29949e86Sstevel cmn_err(CE_WARN, "sysc_make_list: list overflow\n");
1441*29949e86Sstevel #endif
1442*29949e86Sstevel return (EFAULT);
1443*29949e86Sstevel }
1444*29949e86Sstevel }
1445*29949e86Sstevel
1446*29949e86Sstevel return (0);
1447*29949e86Sstevel }
1448*29949e86Sstevel
1449*29949e86Sstevel /*
1450*29949e86Sstevel * Detaching devices on a board.
1451*29949e86Sstevel */
1452*29949e86Sstevel static int
sysc_dr_detach(sysc_dr_handle_t * handle,int board)1453*29949e86Sstevel sysc_dr_detach(sysc_dr_handle_t *handle, int board)
1454*29949e86Sstevel {
1455*29949e86Sstevel int i;
1456*29949e86Sstevel uint_t flags;
1457*29949e86Sstevel sysc_prom_t arg;
1458*29949e86Sstevel
1459*29949e86Sstevel ASSERT(handle->dip_list);
1460*29949e86Sstevel ASSERT(handle->dip_list_len == 0);
1461*29949e86Sstevel ASSERT(*handle->dip_list == NULL);
1462*29949e86Sstevel
1463*29949e86Sstevel arg.handle = handle;
1464*29949e86Sstevel arg.board = board;
1465*29949e86Sstevel arg.dipp = NULL;
1466*29949e86Sstevel
1467*29949e86Sstevel handle->error = prom_tree_access(sysc_make_list, &arg, NULL);
1468*29949e86Sstevel if (handle->error)
1469*29949e86Sstevel return (handle->error);
1470*29949e86Sstevel
1471*29949e86Sstevel flags = DEVI_BRANCH_DESTROY | DEVI_BRANCH_EVENT;
1472*29949e86Sstevel
1473*29949e86Sstevel for (i = handle->dip_list_len; i > 0; i--) {
1474*29949e86Sstevel ASSERT(e_ddi_branch_held(handle->dip_list[i - 1]));
1475*29949e86Sstevel handle->error = e_ddi_branch_unconfigure(
1476*29949e86Sstevel handle->dip_list[i - 1], NULL, flags);
1477*29949e86Sstevel if (handle->error)
1478*29949e86Sstevel return (handle->error);
1479*29949e86Sstevel }
1480*29949e86Sstevel
1481*29949e86Sstevel return (0);
1482*29949e86Sstevel }
1483*29949e86Sstevel
1484*29949e86Sstevel static void
sysc_dr_init(sysc_dr_handle_t * handle)1485*29949e86Sstevel sysc_dr_init(sysc_dr_handle_t *handle)
1486*29949e86Sstevel {
1487*29949e86Sstevel handle->dip_list = kmem_zalloc(sizeof (dev_info_t *) * SYSC_DR_MAX_NODE,
1488*29949e86Sstevel KM_SLEEP);
1489*29949e86Sstevel handle->dip_list_len = 0;
1490*29949e86Sstevel }
1491*29949e86Sstevel
1492*29949e86Sstevel /*ARGSUSED2*/
1493*29949e86Sstevel static int
sysc_prom_select(pnode_t pnode,void * arg,uint_t flag)1494*29949e86Sstevel sysc_prom_select(pnode_t pnode, void *arg, uint_t flag)
1495*29949e86Sstevel {
1496*29949e86Sstevel int bd_id;
1497*29949e86Sstevel char name[OBP_MAXDRVNAME];
1498*29949e86Sstevel int len;
1499*29949e86Sstevel int *regp;
1500*29949e86Sstevel sysc_prom_t *wp = (sysc_prom_t *)arg;
1501*29949e86Sstevel
1502*29949e86Sstevel bd_id = -1;
1503*29949e86Sstevel len = prom_getproplen(pnode, OBP_REG);
1504*29949e86Sstevel if (len > 0) {
1505*29949e86Sstevel regp = kmem_alloc(len, KM_SLEEP);
1506*29949e86Sstevel (void) prom_getprop(pnode, OBP_REG, (caddr_t)regp);
1507*29949e86Sstevel /*
1508*29949e86Sstevel * Get board id for EXXXX platforms where
1509*29949e86Sstevel * 0x1c0 is EXXXX platform specific data to
1510*29949e86Sstevel * acquire board id.
1511*29949e86Sstevel */
1512*29949e86Sstevel bd_id = (*regp - 0x1c0) >> 2;
1513*29949e86Sstevel kmem_free(regp, len);
1514*29949e86Sstevel }
1515*29949e86Sstevel
1516*29949e86Sstevel (void) prom_getprop(pnode, OBP_NAME, (caddr_t)name);
1517*29949e86Sstevel if ((bd_id == wp->board) &&
1518*29949e86Sstevel ((wp->handle->flags & SYSC_DR_FHC) ?
1519*29949e86Sstevel (strcmp(name, "fhc") == 0):
1520*29949e86Sstevel (strcmp(name, "fhc") != 0)) &&
1521*29949e86Sstevel (strcmp(name, "central") != 0)) {
1522*29949e86Sstevel return (DDI_SUCCESS);
1523*29949e86Sstevel }
1524*29949e86Sstevel
1525*29949e86Sstevel return (DDI_FAILURE);
1526*29949e86Sstevel }
1527*29949e86Sstevel
1528*29949e86Sstevel /*ARGSUSED*/
1529*29949e86Sstevel static void
sysc_branch_callback(dev_info_t * rdip,void * arg,uint_t flags)1530*29949e86Sstevel sysc_branch_callback(dev_info_t *rdip, void *arg, uint_t flags)
1531*29949e86Sstevel {
1532*29949e86Sstevel sysc_prom_t *wp = (sysc_prom_t *)arg;
1533*29949e86Sstevel
1534*29949e86Sstevel ASSERT(wp->dipp != NULL);
1535*29949e86Sstevel ASSERT(*wp->dipp == NULL);
1536*29949e86Sstevel ASSERT((wp->handle->flags & SYSC_DR_REMOVE) == 0);
1537*29949e86Sstevel
1538*29949e86Sstevel if (wp->handle->dip_list_len < SYSC_DR_MAX_NODE) {
1539*29949e86Sstevel *wp->dipp = rdip;
1540*29949e86Sstevel wp->dipp++;
1541*29949e86Sstevel wp->handle->dip_list_len++;
1542*29949e86Sstevel } else {
1543*29949e86Sstevel cmn_err(CE_PANIC, "sysc_branch_callback: list overflow");
1544*29949e86Sstevel }
1545*29949e86Sstevel }
1546*29949e86Sstevel
1547*29949e86Sstevel /*
1548*29949e86Sstevel * Uninitialize devices for the state of a board.
1549*29949e86Sstevel */
1550*29949e86Sstevel static void
sysc_dr_uninit(sysc_dr_handle_t * handle)1551*29949e86Sstevel sysc_dr_uninit(sysc_dr_handle_t *handle)
1552*29949e86Sstevel {
1553*29949e86Sstevel kmem_free(handle->dip_list,
1554*29949e86Sstevel sizeof (dev_info_t *) * SYSC_DR_MAX_NODE);
1555*29949e86Sstevel handle->dip_list = NULL;
1556*29949e86Sstevel handle->dip_list_len = 0;
1557*29949e86Sstevel }
1558*29949e86Sstevel
1559*29949e86Sstevel static void
sysc_dr_err_decode(sysc_dr_handle_t * handle,dev_info_t * dip,int attach)1560*29949e86Sstevel sysc_dr_err_decode(sysc_dr_handle_t *handle, dev_info_t *dip, int attach)
1561*29949e86Sstevel {
1562*29949e86Sstevel char *p;
1563*29949e86Sstevel
1564*29949e86Sstevel ASSERT(handle->error != 0);
1565*29949e86Sstevel
1566*29949e86Sstevel switch (handle->error) {
1567*29949e86Sstevel case ENOMEM:
1568*29949e86Sstevel break;
1569*29949e86Sstevel case EBUSY:
1570*29949e86Sstevel (void) ddi_pathname(dip, handle->errstr);
1571*29949e86Sstevel break;
1572*29949e86Sstevel default:
1573*29949e86Sstevel handle->error = EFAULT;
1574*29949e86Sstevel if (attach)
1575*29949e86Sstevel (void) ddi_pathname(ddi_get_parent(dip),
1576*29949e86Sstevel handle->errstr);
1577*29949e86Sstevel else
1578*29949e86Sstevel (void) ddi_pathname(dip, handle->errstr);
1579*29949e86Sstevel if (attach) {
1580*29949e86Sstevel p = "/";
1581*29949e86Sstevel (void) strcat(handle->errstr, p);
1582*29949e86Sstevel (void) strcat(handle->errstr, ddi_node_name(dip));
1583*29949e86Sstevel }
1584*29949e86Sstevel break;
1585*29949e86Sstevel }
1586*29949e86Sstevel }
1587*29949e86Sstevel
1588*29949e86Sstevel static char *
sysc_rstate_typestr(sysc_cfga_rstate_t rstate,sysc_audit_evt_t event)1589*29949e86Sstevel sysc_rstate_typestr(sysc_cfga_rstate_t rstate, sysc_audit_evt_t event)
1590*29949e86Sstevel {
1591*29949e86Sstevel char *type_str;
1592*29949e86Sstevel
1593*29949e86Sstevel switch (rstate) {
1594*29949e86Sstevel case SYSC_CFGA_RSTATE_EMPTY:
1595*29949e86Sstevel switch (event) {
1596*29949e86Sstevel case SYSC_AUDIT_RSTATE_EMPTY:
1597*29949e86Sstevel type_str = "emptying";
1598*29949e86Sstevel break;
1599*29949e86Sstevel case SYSC_AUDIT_RSTATE_SUCCEEDED:
1600*29949e86Sstevel type_str = "emptied";
1601*29949e86Sstevel break;
1602*29949e86Sstevel case SYSC_AUDIT_RSTATE_EMPTY_FAILED:
1603*29949e86Sstevel type_str = "empty";
1604*29949e86Sstevel break;
1605*29949e86Sstevel default:
1606*29949e86Sstevel type_str = "empty?";
1607*29949e86Sstevel break;
1608*29949e86Sstevel }
1609*29949e86Sstevel break;
1610*29949e86Sstevel case SYSC_CFGA_RSTATE_DISCONNECTED:
1611*29949e86Sstevel switch (event) {
1612*29949e86Sstevel case SYSC_AUDIT_RSTATE_DISCONNECT:
1613*29949e86Sstevel type_str = "disconnecting";
1614*29949e86Sstevel break;
1615*29949e86Sstevel case SYSC_AUDIT_RSTATE_SUCCEEDED:
1616*29949e86Sstevel type_str = "disconnected";
1617*29949e86Sstevel break;
1618*29949e86Sstevel case SYSC_AUDIT_RSTATE_DISCONNECT_FAILED:
1619*29949e86Sstevel type_str = "disconnect";
1620*29949e86Sstevel break;
1621*29949e86Sstevel default:
1622*29949e86Sstevel type_str = "disconnect?";
1623*29949e86Sstevel break;
1624*29949e86Sstevel }
1625*29949e86Sstevel break;
1626*29949e86Sstevel case SYSC_CFGA_RSTATE_CONNECTED:
1627*29949e86Sstevel switch (event) {
1628*29949e86Sstevel case SYSC_AUDIT_RSTATE_CONNECT:
1629*29949e86Sstevel type_str = "connecting";
1630*29949e86Sstevel break;
1631*29949e86Sstevel case SYSC_AUDIT_RSTATE_SUCCEEDED:
1632*29949e86Sstevel type_str = "connected";
1633*29949e86Sstevel break;
1634*29949e86Sstevel case SYSC_AUDIT_RSTATE_CONNECT_FAILED:
1635*29949e86Sstevel type_str = "connect";
1636*29949e86Sstevel break;
1637*29949e86Sstevel default:
1638*29949e86Sstevel type_str = "connect?";
1639*29949e86Sstevel break;
1640*29949e86Sstevel }
1641*29949e86Sstevel break;
1642*29949e86Sstevel default:
1643*29949e86Sstevel type_str = "undefined receptacle state";
1644*29949e86Sstevel break;
1645*29949e86Sstevel }
1646*29949e86Sstevel return (type_str);
1647*29949e86Sstevel }
1648*29949e86Sstevel
1649*29949e86Sstevel static char *
sysc_ostate_typestr(sysc_cfga_ostate_t ostate,sysc_audit_evt_t event)1650*29949e86Sstevel sysc_ostate_typestr(sysc_cfga_ostate_t ostate, sysc_audit_evt_t event)
1651*29949e86Sstevel {
1652*29949e86Sstevel char *type_str;
1653*29949e86Sstevel
1654*29949e86Sstevel switch (ostate) {
1655*29949e86Sstevel case SYSC_CFGA_OSTATE_UNCONFIGURED:
1656*29949e86Sstevel switch (event) {
1657*29949e86Sstevel case SYSC_AUDIT_OSTATE_UNCONFIGURE:
1658*29949e86Sstevel type_str = "unconfiguring";
1659*29949e86Sstevel break;
1660*29949e86Sstevel case SYSC_AUDIT_OSTATE_SUCCEEDED:
1661*29949e86Sstevel case SYSC_AUDIT_OSTATE_UNCONFIGURE_FAILED:
1662*29949e86Sstevel type_str = "unconfigured";
1663*29949e86Sstevel break;
1664*29949e86Sstevel default:
1665*29949e86Sstevel type_str = "unconfigure?";
1666*29949e86Sstevel break;
1667*29949e86Sstevel }
1668*29949e86Sstevel break;
1669*29949e86Sstevel case SYSC_CFGA_OSTATE_CONFIGURED:
1670*29949e86Sstevel switch (event) {
1671*29949e86Sstevel case SYSC_AUDIT_OSTATE_CONFIGURE:
1672*29949e86Sstevel type_str = "configuring";
1673*29949e86Sstevel break;
1674*29949e86Sstevel case SYSC_AUDIT_OSTATE_SUCCEEDED:
1675*29949e86Sstevel case SYSC_AUDIT_OSTATE_CONFIGURE_FAILED:
1676*29949e86Sstevel type_str = "configured";
1677*29949e86Sstevel break;
1678*29949e86Sstevel default:
1679*29949e86Sstevel type_str = "configure?";
1680*29949e86Sstevel break;
1681*29949e86Sstevel }
1682*29949e86Sstevel break;
1683*29949e86Sstevel
1684*29949e86Sstevel default:
1685*29949e86Sstevel type_str = "undefined occupant state";
1686*29949e86Sstevel break;
1687*29949e86Sstevel }
1688*29949e86Sstevel return (type_str);
1689*29949e86Sstevel }
1690*29949e86Sstevel
1691*29949e86Sstevel static void
sysc_policy_audit_messages(sysc_audit_evt_t event,sysc_cfga_stat_t * sysc_stat)1692*29949e86Sstevel sysc_policy_audit_messages(sysc_audit_evt_t event, sysc_cfga_stat_t *sysc_stat)
1693*29949e86Sstevel {
1694*29949e86Sstevel switch (event) {
1695*29949e86Sstevel case SYSC_AUDIT_RSTATE_CONNECT:
1696*29949e86Sstevel cmn_err(CE_NOTE,
1697*29949e86Sstevel "%s %s board in slot %d",
1698*29949e86Sstevel sysc_rstate_typestr(SYSC_CFGA_RSTATE_CONNECTED,
1699*29949e86Sstevel event),
1700*29949e86Sstevel fhc_bd_typestr(sysc_stat->type),
1701*29949e86Sstevel sysc_stat->board);
1702*29949e86Sstevel break;
1703*29949e86Sstevel case SYSC_AUDIT_RSTATE_DISCONNECT:
1704*29949e86Sstevel cmn_err(CE_NOTE,
1705*29949e86Sstevel "%s %s board in slot %d",
1706*29949e86Sstevel sysc_rstate_typestr(
1707*29949e86Sstevel SYSC_CFGA_RSTATE_DISCONNECTED,
1708*29949e86Sstevel event),
1709*29949e86Sstevel fhc_bd_typestr(sysc_stat->type),
1710*29949e86Sstevel sysc_stat->board);
1711*29949e86Sstevel break;
1712*29949e86Sstevel case SYSC_AUDIT_RSTATE_SUCCEEDED:
1713*29949e86Sstevel cmn_err(CE_NOTE,
1714*29949e86Sstevel "%s board in slot %d is %s",
1715*29949e86Sstevel fhc_bd_typestr(sysc_stat->type),
1716*29949e86Sstevel sysc_stat->board,
1717*29949e86Sstevel sysc_rstate_typestr(sysc_stat->rstate,
1718*29949e86Sstevel event));
1719*29949e86Sstevel break;
1720*29949e86Sstevel case SYSC_AUDIT_RSTATE_CONNECT_FAILED:
1721*29949e86Sstevel cmn_err(CE_NOTE,
1722*29949e86Sstevel "%s board in slot %d failed to %s",
1723*29949e86Sstevel fhc_bd_typestr(sysc_stat->type),
1724*29949e86Sstevel sysc_stat->board,
1725*29949e86Sstevel sysc_rstate_typestr(SYSC_CFGA_RSTATE_CONNECTED,
1726*29949e86Sstevel event));
1727*29949e86Sstevel break;
1728*29949e86Sstevel case SYSC_AUDIT_RSTATE_DISCONNECT_FAILED:
1729*29949e86Sstevel cmn_err(CE_NOTE,
1730*29949e86Sstevel "%s board in slot %d failed to %s",
1731*29949e86Sstevel fhc_bd_typestr(sysc_stat->type),
1732*29949e86Sstevel sysc_stat->board,
1733*29949e86Sstevel sysc_rstate_typestr(
1734*29949e86Sstevel SYSC_CFGA_RSTATE_DISCONNECTED,
1735*29949e86Sstevel event));
1736*29949e86Sstevel break;
1737*29949e86Sstevel case SYSC_AUDIT_OSTATE_CONFIGURE:
1738*29949e86Sstevel cmn_err(CE_NOTE,
1739*29949e86Sstevel "%s %s board in slot %d",
1740*29949e86Sstevel sysc_ostate_typestr(SYSC_CFGA_OSTATE_CONFIGURED,
1741*29949e86Sstevel event),
1742*29949e86Sstevel fhc_bd_typestr(sysc_stat->type),
1743*29949e86Sstevel sysc_stat->board);
1744*29949e86Sstevel break;
1745*29949e86Sstevel case SYSC_AUDIT_OSTATE_UNCONFIGURE:
1746*29949e86Sstevel cmn_err(CE_NOTE,
1747*29949e86Sstevel "%s %s board in slot %d",
1748*29949e86Sstevel sysc_ostate_typestr(
1749*29949e86Sstevel SYSC_CFGA_OSTATE_UNCONFIGURED,
1750*29949e86Sstevel event),
1751*29949e86Sstevel fhc_bd_typestr(sysc_stat->type),
1752*29949e86Sstevel sysc_stat->board);
1753*29949e86Sstevel break;
1754*29949e86Sstevel case SYSC_AUDIT_OSTATE_SUCCEEDED:
1755*29949e86Sstevel cmn_err(CE_NOTE,
1756*29949e86Sstevel "%s board in slot %d is %s",
1757*29949e86Sstevel fhc_bd_typestr(sysc_stat->type),
1758*29949e86Sstevel sysc_stat->board,
1759*29949e86Sstevel sysc_ostate_typestr(sysc_stat->ostate,
1760*29949e86Sstevel event));
1761*29949e86Sstevel break;
1762*29949e86Sstevel case SYSC_AUDIT_OSTATE_CONFIGURE_FAILED:
1763*29949e86Sstevel cmn_err(CE_NOTE,
1764*29949e86Sstevel "%s board in slot %d partially %s",
1765*29949e86Sstevel fhc_bd_typestr(sysc_stat->type),
1766*29949e86Sstevel sysc_stat->board,
1767*29949e86Sstevel sysc_ostate_typestr(
1768*29949e86Sstevel SYSC_CFGA_OSTATE_CONFIGURED,
1769*29949e86Sstevel event));
1770*29949e86Sstevel break;
1771*29949e86Sstevel case SYSC_AUDIT_OSTATE_UNCONFIGURE_FAILED:
1772*29949e86Sstevel cmn_err(CE_NOTE,
1773*29949e86Sstevel "%s board in slot %d partially %s",
1774*29949e86Sstevel fhc_bd_typestr(sysc_stat->type),
1775*29949e86Sstevel sysc_stat->board,
1776*29949e86Sstevel sysc_ostate_typestr(
1777*29949e86Sstevel SYSC_CFGA_OSTATE_UNCONFIGURED,
1778*29949e86Sstevel event));
1779*29949e86Sstevel break;
1780*29949e86Sstevel default:
1781*29949e86Sstevel cmn_err(CE_NOTE,
1782*29949e86Sstevel "unknown audit of a %s %s board in"
1783*29949e86Sstevel " slot %d",
1784*29949e86Sstevel sysc_rstate_typestr(sysc_stat->rstate,
1785*29949e86Sstevel event),
1786*29949e86Sstevel fhc_bd_typestr(sysc_stat->type),
1787*29949e86Sstevel sysc_stat->board);
1788*29949e86Sstevel break;
1789*29949e86Sstevel }
1790*29949e86Sstevel }
1791*29949e86Sstevel
1792*29949e86Sstevel #define MAX_PROP_LEN 33 /* must be > strlen("cpu") */
1793*29949e86Sstevel
1794*29949e86Sstevel static int
find_and_setup_cpu(int cpuid)1795*29949e86Sstevel find_and_setup_cpu(int cpuid)
1796*29949e86Sstevel {
1797*29949e86Sstevel return (prom_tree_access(find_and_setup_cpu_start, &cpuid, NULL));
1798*29949e86Sstevel }
1799*29949e86Sstevel
1800*29949e86Sstevel /* ARGSUSED */
1801*29949e86Sstevel static int
find_and_setup_cpu_start(void * cpuid_arg,int has_changed)1802*29949e86Sstevel find_and_setup_cpu_start(void *cpuid_arg, int has_changed)
1803*29949e86Sstevel {
1804*29949e86Sstevel pnode_t nodeid;
1805*29949e86Sstevel int upaid;
1806*29949e86Sstevel char type[MAX_PROP_LEN];
1807*29949e86Sstevel int cpuid = *(int *)cpuid_arg;
1808*29949e86Sstevel
1809*29949e86Sstevel nodeid = prom_childnode(prom_rootnode());
1810*29949e86Sstevel while (nodeid != OBP_NONODE) {
1811*29949e86Sstevel if (prom_getproplen(nodeid, "device_type") < MAX_PROP_LEN)
1812*29949e86Sstevel (void) prom_getprop(nodeid, "device_type",
1813*29949e86Sstevel (caddr_t)type);
1814*29949e86Sstevel else
1815*29949e86Sstevel type[0] = '\0';
1816*29949e86Sstevel (void) prom_getprop(nodeid, "upa-portid", (caddr_t)&upaid);
1817*29949e86Sstevel if ((strcmp(type, "cpu") == 0) && (upaid == cpuid)) {
1818*29949e86Sstevel return (cpu_configure(cpuid));
1819*29949e86Sstevel }
1820*29949e86Sstevel nodeid = prom_nextnode(nodeid);
1821*29949e86Sstevel }
1822*29949e86Sstevel return (ENODEV);
1823*29949e86Sstevel }
1824*29949e86Sstevel
1825*29949e86Sstevel #define MAX_BOARD_TYPE IO_SBUS_FFB_SOCPLUS_BOARD
1826*29949e86Sstevel
1827*29949e86Sstevel static char sysc_supp_conn[MAX_BOARD_TYPE + 1];
1828*29949e86Sstevel
1829*29949e86Sstevel static int
sysc_board_connect_supported(enum board_type type)1830*29949e86Sstevel sysc_board_connect_supported(enum board_type type)
1831*29949e86Sstevel {
1832*29949e86Sstevel if (type > MAX_BOARD_TYPE)
1833*29949e86Sstevel return (0);
1834*29949e86Sstevel return (sysc_supp_conn[type]);
1835*29949e86Sstevel }
1836*29949e86Sstevel
1837*29949e86Sstevel void
sysc_board_connect_supported_init(void)1838*29949e86Sstevel sysc_board_connect_supported_init(void)
1839*29949e86Sstevel {
1840*29949e86Sstevel pnode_t openprom_node;
1841*29949e86Sstevel char sup_list[16];
1842*29949e86Sstevel int proplen;
1843*29949e86Sstevel int i;
1844*29949e86Sstevel char tstr[3 * 5 + 1];
1845*29949e86Sstevel
1846*29949e86Sstevel /* Check the firmware for Dynamic Reconfiguration support */
1847*29949e86Sstevel if (prom_test("SUNW,Ultra-Enterprise,rm-brd") != 0) {
1848*29949e86Sstevel /* The message was printed in platmod:set_platform_defaults */
1849*29949e86Sstevel enable_dynamic_reconfiguration = 0;
1850*29949e86Sstevel }
1851*29949e86Sstevel
1852*29949e86Sstevel openprom_node = prom_finddevice("/openprom");
1853*29949e86Sstevel if (openprom_node != OBP_BADNODE) {
1854*29949e86Sstevel proplen = prom_bounded_getprop(openprom_node,
1855*29949e86Sstevel "add-brd-supported-types",
1856*29949e86Sstevel sup_list, sizeof (sup_list) - 1);
1857*29949e86Sstevel } else {
1858*29949e86Sstevel proplen = -1;
1859*29949e86Sstevel }
1860*29949e86Sstevel
1861*29949e86Sstevel if (proplen < 0) {
1862*29949e86Sstevel /*
1863*29949e86Sstevel * This is an old prom which may cause a fatal reset,
1864*29949e86Sstevel * so don't allow any DR operations.
1865*29949e86Sstevel * If enable_dynamic_reconfiguration is 0
1866*29949e86Sstevel * we have already printed a similar message.
1867*29949e86Sstevel */
1868*29949e86Sstevel if (enable_dynamic_reconfiguration) {
1869*29949e86Sstevel cmn_err(CE_WARN, "Firmware does not support"
1870*29949e86Sstevel " Dynamic Reconfiguration");
1871*29949e86Sstevel enable_dynamic_reconfiguration = 0;
1872*29949e86Sstevel }
1873*29949e86Sstevel return;
1874*29949e86Sstevel }
1875*29949e86Sstevel for (i = 0; i < proplen; i++) {
1876*29949e86Sstevel switch (sup_list[i]) {
1877*29949e86Sstevel case '0':
1878*29949e86Sstevel sysc_supp_conn[CPU_BOARD] = 1;
1879*29949e86Sstevel sysc_supp_conn[MEM_BOARD] = 1;
1880*29949e86Sstevel break;
1881*29949e86Sstevel case '1':
1882*29949e86Sstevel sysc_supp_conn[IO_2SBUS_BOARD] = 1;
1883*29949e86Sstevel break;
1884*29949e86Sstevel case '2':
1885*29949e86Sstevel sysc_supp_conn[IO_SBUS_FFB_BOARD] = 1;
1886*29949e86Sstevel break;
1887*29949e86Sstevel case '3':
1888*29949e86Sstevel sysc_supp_conn[IO_PCI_BOARD] = 1;
1889*29949e86Sstevel break;
1890*29949e86Sstevel case '4':
1891*29949e86Sstevel sysc_supp_conn[IO_2SBUS_SOCPLUS_BOARD] = 1;
1892*29949e86Sstevel break;
1893*29949e86Sstevel case '5':
1894*29949e86Sstevel sysc_supp_conn[IO_SBUS_FFB_SOCPLUS_BOARD] = 1;
1895*29949e86Sstevel break;
1896*29949e86Sstevel default:
1897*29949e86Sstevel /* Ignore other characters. */
1898*29949e86Sstevel break;
1899*29949e86Sstevel }
1900*29949e86Sstevel }
1901*29949e86Sstevel if (sysc_supp_conn[CPU_BOARD]) {
1902*29949e86Sstevel cmn_err(CE_NOTE, "!Firmware supports Dynamic Reconfiguration"
1903*29949e86Sstevel " of CPU/Memory boards.");
1904*29949e86Sstevel } else {
1905*29949e86Sstevel cmn_err(CE_NOTE, "Firmware does not support Dynamic"
1906*29949e86Sstevel " Reconfiguration of CPU/Memory boards.");
1907*29949e86Sstevel }
1908*29949e86Sstevel
1909*29949e86Sstevel tstr[0] = '\0';
1910*29949e86Sstevel if (sysc_supp_conn[IO_2SBUS_BOARD])
1911*29949e86Sstevel (void) strcat(tstr, ", 1");
1912*29949e86Sstevel if (sysc_supp_conn[IO_SBUS_FFB_BOARD])
1913*29949e86Sstevel (void) strcat(tstr, ", 2");
1914*29949e86Sstevel if (sysc_supp_conn[IO_PCI_BOARD])
1915*29949e86Sstevel (void) strcat(tstr, ", 3");
1916*29949e86Sstevel if (sysc_supp_conn[IO_2SBUS_SOCPLUS_BOARD])
1917*29949e86Sstevel (void) strcat(tstr, ", 4");
1918*29949e86Sstevel if (sysc_supp_conn[IO_SBUS_FFB_SOCPLUS_BOARD])
1919*29949e86Sstevel (void) strcat(tstr, ", 5");
1920*29949e86Sstevel if (tstr[0] != '\0') {
1921*29949e86Sstevel /* Skip leading ", " using &tstr[2]. */
1922*29949e86Sstevel cmn_err(CE_NOTE, "!Firmware supports Dynamic Reconfiguration"
1923*29949e86Sstevel " of I/O board types %s.", &tstr[2]);
1924*29949e86Sstevel } else {
1925*29949e86Sstevel cmn_err(CE_NOTE, "Firmware does not support Dynamic"
1926*29949e86Sstevel " Reconfiguration of I/O boards.");
1927*29949e86Sstevel }
1928*29949e86Sstevel }
1929*29949e86Sstevel
1930*29949e86Sstevel #ifdef DEBUG
1931*29949e86Sstevel
1932*29949e86Sstevel static void
precache_regdump(int board)1933*29949e86Sstevel precache_regdump(int board)
1934*29949e86Sstevel {
1935*29949e86Sstevel fhc_bd_t *curr_bdp;
1936*29949e86Sstevel int bd_idx;
1937*29949e86Sstevel int reg_idx;
1938*29949e86Sstevel
1939*29949e86Sstevel for (bd_idx = 0; bd_idx < fhc_max_boards(); bd_idx++) {
1940*29949e86Sstevel bcopy((void *) reg_tmpl, (void *) ®_dt[bd_idx][0],
1941*29949e86Sstevel (sizeof (struct regs_data))*NUM_REG);
1942*29949e86Sstevel curr_bdp = fhc_bd(bd_idx);
1943*29949e86Sstevel if (curr_bdp->sc.rstate == SYSC_CFGA_RSTATE_CONNECTED) {
1944*29949e86Sstevel for (reg_idx = 0; reg_idx < NUM_REG; reg_idx++) {
1945*29949e86Sstevel reg_dt[bd_idx][reg_idx].eflag = TRUE;
1946*29949e86Sstevel if (bd_idx != board)
1947*29949e86Sstevel reg_dt[bd_idx][reg_idx].oflag = TRUE;
1948*29949e86Sstevel reg_dt[bd_idx][reg_idx].physaddr +=
1949*29949e86Sstevel (FHC_BOARD_SPAN*2*bd_idx);
1950*29949e86Sstevel reg_dt[bd_idx][reg_idx].pre_dsct =
1951*29949e86Sstevel ldphysio(reg_dt[bd_idx][reg_idx].physaddr);
1952*29949e86Sstevel }
1953*29949e86Sstevel }
1954*29949e86Sstevel }
1955*29949e86Sstevel
1956*29949e86Sstevel
1957*29949e86Sstevel }
1958*29949e86Sstevel
1959*29949e86Sstevel static void
boardstat_regdump(void)1960*29949e86Sstevel boardstat_regdump(void)
1961*29949e86Sstevel {
1962*29949e86Sstevel int bd_idx;
1963*29949e86Sstevel
1964*29949e86Sstevel prom_printf("\nBoard status before disconnect.\n");
1965*29949e86Sstevel for (bd_idx = 0; bd_idx < fhc_max_boards(); bd_idx++) {
1966*29949e86Sstevel if (reg_dt[bd_idx][0].eflag == 0) {
1967*29949e86Sstevel prom_printf("Board #%d is idle.\n", bd_idx);
1968*29949e86Sstevel } else {
1969*29949e86Sstevel prom_printf("Board #%d is on.\n", bd_idx);
1970*29949e86Sstevel }
1971*29949e86Sstevel }
1972*29949e86Sstevel
1973*29949e86Sstevel for (bd_idx = 0; bd_idx < fhc_max_boards(); bd_idx++) {
1974*29949e86Sstevel if (reg_dt[bd_idx][0].eflag) {
1975*29949e86Sstevel prom_printf("\nRegisters for Board #%d", bd_idx);
1976*29949e86Sstevel prom_printf(" (before disconnect).\n");
1977*29949e86Sstevel prom_printf("AC_BCSR FHC_CTRL JTAG IGN SIM"
1978*29949e86Sstevel " SISM UIM USM\n");
1979*29949e86Sstevel prom_printf("%08x %08x %08x %04x"
1980*29949e86Sstevel " %08x %04x %08x %04x\n",
1981*29949e86Sstevel reg_dt[bd_idx][0].pre_dsct,
1982*29949e86Sstevel reg_dt[bd_idx][1].pre_dsct,
1983*29949e86Sstevel reg_dt[bd_idx][2].pre_dsct,
1984*29949e86Sstevel reg_dt[bd_idx][3].pre_dsct,
1985*29949e86Sstevel reg_dt[bd_idx][4].pre_dsct,
1986*29949e86Sstevel reg_dt[bd_idx][5].pre_dsct,
1987*29949e86Sstevel reg_dt[bd_idx][6].pre_dsct,
1988*29949e86Sstevel reg_dt[bd_idx][7].pre_dsct);
1989*29949e86Sstevel }
1990*29949e86Sstevel }
1991*29949e86Sstevel
1992*29949e86Sstevel }
1993*29949e86Sstevel
1994*29949e86Sstevel static void
display_regdump(void)1995*29949e86Sstevel display_regdump(void)
1996*29949e86Sstevel {
1997*29949e86Sstevel int bd_idx;
1998*29949e86Sstevel int reg_idx;
1999*29949e86Sstevel
2000*29949e86Sstevel prom_printf("Board status after disconnect.\n");
2001*29949e86Sstevel for (bd_idx = 0; bd_idx < fhc_max_boards(); bd_idx++) {
2002*29949e86Sstevel if (reg_dt[bd_idx][0].oflag == 0) {
2003*29949e86Sstevel prom_printf("Board #%d is idle.\n", bd_idx);
2004*29949e86Sstevel } else {
2005*29949e86Sstevel prom_printf("Board #%d is on.\n", bd_idx);
2006*29949e86Sstevel for (reg_idx = 0; reg_idx < NUM_REG; reg_idx++)
2007*29949e86Sstevel reg_dt[bd_idx][reg_idx].post_dsct =
2008*29949e86Sstevel ldphysio(reg_dt[bd_idx][reg_idx].physaddr);
2009*29949e86Sstevel }
2010*29949e86Sstevel }
2011*29949e86Sstevel
2012*29949e86Sstevel for (bd_idx = 0; bd_idx < fhc_max_boards(); bd_idx++) {
2013*29949e86Sstevel if (reg_dt[bd_idx][0].eflag) {
2014*29949e86Sstevel prom_printf("\nRegisters for Board #%d", bd_idx);
2015*29949e86Sstevel prom_printf(" (before and after disconnect).\n");
2016*29949e86Sstevel prom_printf("AC_BCSR FHC_CTRL JTAG IGN SIM"
2017*29949e86Sstevel " SISM UIM USM\n");
2018*29949e86Sstevel prom_printf("%08x %08x %08x %04x"
2019*29949e86Sstevel " %08x %04x %08x %04x\n",
2020*29949e86Sstevel reg_dt[bd_idx][0].pre_dsct,
2021*29949e86Sstevel reg_dt[bd_idx][1].pre_dsct,
2022*29949e86Sstevel reg_dt[bd_idx][2].pre_dsct,
2023*29949e86Sstevel reg_dt[bd_idx][3].pre_dsct,
2024*29949e86Sstevel reg_dt[bd_idx][4].pre_dsct,
2025*29949e86Sstevel reg_dt[bd_idx][5].pre_dsct,
2026*29949e86Sstevel reg_dt[bd_idx][6].pre_dsct,
2027*29949e86Sstevel reg_dt[bd_idx][7].pre_dsct);
2028*29949e86Sstevel if (reg_dt[bd_idx][0].oflag) {
2029*29949e86Sstevel prom_printf("%08x %08x %08x %04x"
2030*29949e86Sstevel " %08x %04x %08x %04x\n",
2031*29949e86Sstevel reg_dt[bd_idx][0].post_dsct,
2032*29949e86Sstevel reg_dt[bd_idx][1].post_dsct,
2033*29949e86Sstevel reg_dt[bd_idx][2].post_dsct,
2034*29949e86Sstevel reg_dt[bd_idx][3].post_dsct,
2035*29949e86Sstevel reg_dt[bd_idx][4].post_dsct,
2036*29949e86Sstevel reg_dt[bd_idx][5].post_dsct,
2037*29949e86Sstevel reg_dt[bd_idx][6].post_dsct,
2038*29949e86Sstevel reg_dt[bd_idx][7].post_dsct);
2039*29949e86Sstevel } else {
2040*29949e86Sstevel prom_printf("no data (board got"
2041*29949e86Sstevel " disconnected)-------------------"
2042*29949e86Sstevel "---------------\n");
2043*29949e86Sstevel }
2044*29949e86Sstevel }
2045*29949e86Sstevel
2046*29949e86Sstevel }
2047*29949e86Sstevel
2048*29949e86Sstevel }
2049*29949e86Sstevel
2050*29949e86Sstevel #endif /* DEBUG */
2051