1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27
28 #include <sys/types.h>
29 #include <sys/conf.h>
30 #include <sys/ddi.h>
31 #include <sys/sunddi.h>
32 #include <sys/ddi_impldefs.h>
33 #include <sys/obpdefs.h>
34 #include <sys/promif.h>
35 #include <sys/cmn_err.h>
36 #include <sys/errno.h>
37 #include <sys/kmem.h>
38 #include <sys/vmem.h>
39 #include <sys/debug.h>
40 #include <sys/sysmacros.h>
41 #include <sys/intreg.h>
42 #include <sys/autoconf.h>
43 #include <sys/modctl.h>
44 #include <sys/spl.h>
45 #include <sys/time.h>
46 #include <sys/systm.h>
47 #include <sys/machsystm.h>
48 #include <sys/cpu.h>
49 #include <sys/cpuvar.h>
50 #include <sys/x_call.h> /* xt_one() */
51 #include <sys/membar.h>
52 #include <sys/vm.h>
53 #include <vm/seg_kmem.h>
54 #include <vm/hat_sfmmu.h>
55 #include <sys/promimpl.h>
56 #include <sys/prom_plat.h>
57 #include <sys/cpu_module.h> /* flush_instr_mem() */
58 #include <sys/procset.h>
59 #include <sys/fhc.h>
60 #include <sys/ac.h>
61 #include <sys/environ.h>
62 #include <sys/jtag.h>
63 #include <sys/nexusdebug.h>
64 #include <sys/ac.h>
65 #include <sys/ddi_subrdefs.h>
66 #include <sys/eeprom.h>
67 #include <sys/sdt.h>
68 #include <sys/ddi_implfuncs.h>
69 #include <sys/ontrap.h>
70
71 #ifndef TRUE
72 #define TRUE (1)
73 #endif
74 #ifndef FALSE
75 #define FALSE (0)
76 #endif
77
78 /*
79 * Function to register and deregister callbacks, for sunfire only.
80 */
81 extern void plat_register_tod_fault(void (*func)(enum tod_fault_type));
82
83 /*
84 * This table represents the FHC interrupt priorities. They range from
85 * 1-15, and have been modeled after the sun4d interrupts. The mondo
86 * number anded with 0x7 is used to index into this table. This was
87 * done to save table space.
88 */
89 static int fhc_int_priorities[] = {
90 PIL_15, /* System interrupt priority */
91 PIL_12, /* zs interrupt priority */
92 PIL_15, /* TOD interrupt priority */
93 PIL_15 /* Fan Fail priority */
94 };
95
96 static void fhc_tod_fault(enum tod_fault_type tod_bad);
97
98 /*
99 * The dont_calibrate variable is meant to be set to one in /etc/system
100 * or by boot -h so that the calibration tables are not used. This
101 * is useful for checking thermistors whose output seems to be incorrect.
102 */
103 static int dont_calibrate = 0;
104
105 /* Only one processor should powerdown the system. */
106 static int powerdown_started = 0;
107
108 /* Let user disable overtemp powerdown. */
109 int enable_overtemp_powerdown = 1;
110
111 /*
112 * The following tables correspond to the degress Celcius for each count
113 * value possible from the 8-bit A/C convertors on each type of system
114 * board for the UltraSPARC Server systems. To access a temperature,
115 * just index into the correct table using the count from the A/D convertor
116 * register, and that is the correct temperature in degress Celsius. These
117 * values can be negative.
118 */
119 static short cpu_table[] = {
120 -16, -14, -12, -10, -8, -6, -4, -2, /* 0-7 */
121 1, 4, 6, 8, 10, 12, 13, 15, /* 8-15 */
122 16, 18, 19, 20, 22, 23, 24, 25, /* 16-23 */
123 26, 27, 28, 29, 30, 31, 32, 33, /* 24-31 */
124 34, 35, 35, 36, 37, 38, 39, 39, /* 32-39 */
125 40, 41, 41, 42, 43, 44, 44, 45, /* 40-47 */
126 46, 46, 47, 47, 48, 49, 49, 50, /* 48-55 */
127 51, 51, 52, 53, 53, 54, 54, 55, /* 56-63 */
128 55, 56, 56, 57, 57, 58, 58, 59, /* 64-71 */
129 60, 60, 61, 61, 62, 62, 63, 63, /* 72-79 */
130 64, 64, 65, 65, 66, 66, 67, 67, /* 80-87 */
131 68, 68, 69, 69, 70, 70, 71, 71, /* 88-95 */
132 72, 72, 73, 73, 74, 74, 75, 75, /* 96-103 */
133 76, 76, 77, 77, 78, 78, 79, 79, /* 104-111 */
134 80, 80, 81, 81, 82, 82, 83, 83, /* 112-119 */
135 84, 84, 85, 85, 86, 86, 87, 87, /* 120-127 */
136 88, 88, 89, 89, 90, 90, 91, 91, /* 128-135 */
137 92, 92, 93, 93, 94, 94, 95, 95, /* 136-143 */
138 96, 96, 97, 98, 98, 99, 99, 100, /* 144-151 */
139 100, 101, 101, 102, 103, 103, 104, 104, /* 152-159 */
140 105, 106, 106, 107, 107, 108, 109, 109, /* 160-167 */
141 110, /* 168 */
142 };
143
144 #define CPU_MX_CNT (sizeof (cpu_table)/sizeof (short))
145
146 static short cpu2_table[] = {
147 -17, -16, -15, -14, -13, -12, -11, -10, /* 0-7 */
148 -9, -8, -7, -6, -5, -4, -3, -2, /* 8-15 */
149 -1, 0, 1, 2, 3, 4, 5, 6, /* 16-23 */
150 7, 8, 9, 10, 11, 12, 13, 13, /* 24-31 */
151 14, 15, 16, 16, 17, 18, 18, 19, /* 32-39 */
152 20, 20, 21, 22, 22, 23, 24, 24, /* 40-47 */
153 25, 25, 26, 26, 27, 27, 28, 28, /* 48-55 */
154 29, 30, 30, 31, 31, 32, 32, 33, /* 56-63 */
155 33, 34, 34, 35, 35, 36, 36, 37, /* 64-71 */
156 37, 37, 38, 38, 39, 39, 40, 40, /* 72-79 */
157 41, 41, 42, 42, 43, 43, 43, 44, /* 80-87 */
158 44, 45, 45, 46, 46, 46, 47, 47, /* 88-95 */
159 48, 48, 49, 49, 50, 50, 50, 51, /* 96-103 */
160 51, 52, 52, 53, 53, 53, 54, 54, /* 104-111 */
161 55, 55, 56, 56, 56, 57, 57, 58, /* 112-119 */
162 58, 59, 59, 59, 60, 60, 61, 61, /* 120-127 */
163 62, 62, 63, 63, 63, 64, 64, 65, /* 128-135 */
164 65, 66, 66, 67, 67, 68, 68, 68, /* 136-143 */
165 69, 69, 70, 70, 71, 71, 72, 72, /* 144-151 */
166 73, 73, 74, 74, 75, 75, 76, 76, /* 152-159 */
167 77, 77, 78, 78, 79, 79, 80, 80, /* 160-167 */
168 81, 81, 82, 83, 83, 84, 84, 85, /* 168-175 */
169 85, 86, 87, 87, 88, 88, 89, 90, /* 176-183 */
170 90, 91, 92, 92, 93, 94, 94, 95, /* 184-191 */
171 96, 96, 97, 98, 99, 99, 100, 101, /* 192-199 */
172 102, 103, 103, 104, 105, 106, 107, 108, /* 200-207 */
173 109, 110, /* 208-209 */
174 };
175
176 #define CPU2_MX_CNT (sizeof (cpu2_table)/sizeof (short))
177
178 static short io_table[] = {
179 0, 0, 0, 0, 0, 0, 0, 0, /* 0-7 */
180 0, 0, 0, 0, 0, 0, 0, 0, /* 8-15 */
181 0, 0, 0, 0, 0, 0, 0, 0, /* 16-23 */
182 0, 0, 0, 0, 0, 0, 0, 0, /* 24-31 */
183 0, 0, 0, 0, 0, 0, 0, 0, /* 32-39 */
184 0, 3, 7, 10, 13, 15, 17, 19, /* 40-47 */
185 21, 23, 25, 27, 28, 30, 31, 32, /* 48-55 */
186 34, 35, 36, 37, 38, 39, 41, 42, /* 56-63 */
187 43, 44, 45, 46, 46, 47, 48, 49, /* 64-71 */
188 50, 51, 52, 53, 53, 54, 55, 56, /* 72-79 */
189 57, 57, 58, 59, 60, 60, 61, 62, /* 80-87 */
190 62, 63, 64, 64, 65, 66, 66, 67, /* 88-95 */
191 68, 68, 69, 70, 70, 71, 72, 72, /* 96-103 */
192 73, 73, 74, 75, 75, 76, 77, 77, /* 104-111 */
193 78, 78, 79, 80, 80, 81, 81, 82, /* 112-119 */
194 };
195
196 #define IO_MN_CNT 40
197 #define IO_MX_CNT (sizeof (io_table)/sizeof (short))
198
199 static short clock_table[] = {
200 0, 0, 0, 0, 0, 0, 0, 0, /* 0-7 */
201 0, 0, 0, 0, 1, 2, 4, 5, /* 8-15 */
202 7, 8, 10, 11, 12, 13, 14, 15, /* 16-23 */
203 17, 18, 19, 20, 21, 22, 23, 24, /* 24-31 */
204 24, 25, 26, 27, 28, 29, 29, 30, /* 32-39 */
205 31, 32, 32, 33, 34, 35, 35, 36, /* 40-47 */
206 37, 38, 38, 39, 40, 40, 41, 42, /* 48-55 */
207 42, 43, 44, 44, 45, 46, 46, 47, /* 56-63 */
208 48, 48, 49, 50, 50, 51, 52, 52, /* 64-71 */
209 53, 54, 54, 55, 56, 57, 57, 58, /* 72-79 */
210 59, 59, 60, 60, 61, 62, 63, 63, /* 80-87 */
211 64, 65, 65, 66, 67, 68, 68, 69, /* 88-95 */
212 70, 70, 71, 72, 73, 74, 74, 75, /* 96-103 */
213 76, 77, 78, 78, 79, 80, 81, 82, /* 104-111 */
214 };
215
216 #define CLK_MN_CNT 11
217 #define CLK_MX_CNT (sizeof (clock_table)/sizeof (short))
218
219 /*
220 * System temperature limits.
221 *
222 * The following variables are the warning and danger limits for the
223 * different types of system boards. The limits are different because
224 * the various boards reach different nominal temperatures because
225 * of the different components that they contain.
226 *
227 * The warning limit is the temperature at which the user is warned.
228 * The danger limit is the temperature at which the system is shutdown.
229 * In the case of CPU/Memory system boards, the system will attempt
230 * to offline and power down processors on a board in an attempt to
231 * bring the board back into the nominal temperature range before
232 * shutting down the system.
233 *
234 * These values can be tuned via /etc/system or boot -h.
235 */
236 short cpu_warn_temp = 73; /* CPU/Memory Warning Temperature */
237 short cpu_danger_temp = 83; /* CPU/Memory Danger Temperature */
238 short io_warn_temp = 60; /* IO Board Warning Temperature */
239 short io_danger_temp = 68; /* IO Board Danger Temperature */
240 short clk_warn_temp = 60; /* Clock Board Warning Temperature */
241 short clk_danger_temp = 68; /* Clock Board Danger Temperature */
242
243 short dft_warn_temp = 60; /* default warning temp value */
244 short dft_danger_temp = 68; /* default danger temp value */
245
246 short cpu_warn_temp_4x = 60; /* CPU/Memory warning temp for 400 MHZ */
247 short cpu_danger_temp_4x = 68; /* CPU/Memory danger temp for 400 MHZ */
248
249 /*
250 * This variable tells us if we are in a heat chamber. It is set
251 * early on in boot, after we check the OBP 'mfg-mode' property in
252 * the options node.
253 */
254 static int temperature_chamber = -1;
255
256 /*
257 * The fhc memloc structure is protected under the bdlist lock
258 */
259 static struct fhc_memloc *fhc_base_memloc = NULL;
260
261 /*
262 * Driver global fault list mutex and list head pointer. The list is
263 * protected by the mutex and contains a record of all known faults.
264 * Faults can be inherited from the PROM or detected by the kernel.
265 */
266 static kmutex_t ftlist_mutex;
267 static struct ft_link_list *ft_list = NULL;
268 static int ft_nfaults = 0;
269
270 /*
271 * Table of all known fault strings. This table is indexed by the fault
272 * type. Do not change the ordering of the table without redefining the
273 * fault type enum list on fhc.h.
274 */
275 char *ft_str_table[] = {
276 "Core Power Supply", /* FT_CORE_PS */
277 "Overtemp", /* FT_OVERTEMP */
278 "AC Power", /* FT_AC_PWR */
279 "Peripheral Power Supply", /* FT_PPS */
280 "System 3.3 Volt Power", /* FT_CLK_33 */
281 "System 5.0 Volt Power", /* FT_CLK_50 */
282 "Peripheral 5.0 Volt Power", /* FT_V5_P */
283 "Peripheral 12 Volt Power", /* FT_V12_P */
284 "Auxiliary 5.0 Volt Power", /* FT_V5_AUX */
285 "Peripheral 5.0 Volt Precharge", /* FT_V5_P_PCH */
286 "Peripheral 12 Volt Precharge", /* FT_V12_P_PCH */
287 "System 3.3 Volt Precharge", /* FT_V3_PCH */
288 "System 5.0 Volt Precharge", /* FT_V5_PCH */
289 "Peripheral Power Supply Fans", /* FT_PPS_FAN */
290 "Rack Exhaust Fan", /* FT_RACK_EXH */
291 "Disk Drive Fan", /* FT_DSK_FAN */
292 "AC Box Fan", /* FT_AC_FAN */
293 "Key Switch Fan", /* FT_KEYSW_FAN */
294 "Minimum Power", /* FT_INSUFFICIENT_POWER */
295 "PROM detected", /* FT_PROM */
296 "Hot Plug Support System", /* FT_HOT_PLUG */
297 "TOD" /* FT_TODFAULT */
298 };
299
300 static int ft_max_index = (sizeof (ft_str_table) / sizeof (char *));
301
302 /*
303 * Function prototypes
304 */
305 static int fhc_ctlops(dev_info_t *, dev_info_t *, ddi_ctl_enum_t,
306 void *, void *);
307 static int fhc_intr_ops(dev_info_t *dip, dev_info_t *rdip,
308 ddi_intr_op_t intr_op, ddi_intr_handle_impl_t *hdlp, void *result);
309
310 static int fhc_add_intr_impl(dev_info_t *dip, dev_info_t *rdip,
311 ddi_intr_handle_impl_t *hdlp);
312 static void fhc_remove_intr_impl(dev_info_t *dip, dev_info_t *rdip,
313 ddi_intr_handle_impl_t *hdlp);
314
315 static int fhc_attach(dev_info_t *devi, ddi_attach_cmd_t cmd);
316 static int fhc_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
317 static int fhc_init(struct fhc_soft_state *softsp);
318 static void fhc_unmap_regs(struct fhc_soft_state *softsp);
319 static enum board_type fhc_board_type(struct fhc_soft_state *, int);
320
321 static void
322 fhc_xlate_intrs(ddi_intr_handle_impl_t *hdlp, uint32_t ign);
323
324 static int
325 fhc_ctlops_peekpoke(ddi_ctl_enum_t, peekpoke_ctlops_t *, void *result);
326
327 static void fhc_add_kstats(struct fhc_soft_state *);
328 static int fhc_kstat_update(kstat_t *, int);
329 static int check_for_chamber(void);
330 static int ft_ks_snapshot(struct kstat *, void *, int);
331 static int ft_ks_update(struct kstat *, int);
332 static int check_central(int board);
333
334 /*
335 * board type and A/D convertor output passed in and real temperature
336 * is returned.
337 */
338 static short calibrate_temp(enum board_type, uchar_t, uint_t);
339 static enum temp_state get_temp_state(enum board_type, short, int);
340
341 /* Routine to determine if there are CPUs on this board. */
342 static int cpu_on_board(int);
343
344 static void build_bd_display_str(char *, enum board_type, int);
345
346 /* Interrupt distribution callback function. */
347 static void fhc_intrdist(void *);
348
349 /* CPU power control */
350 int fhc_cpu_poweroff(struct cpu *); /* cpu_poweroff()->platform */
351 int fhc_cpu_poweron(struct cpu *); /* cpu_poweron()->platform */
352
353 extern struct cpu_node cpunodes[];
354 extern void halt(char *);
355
356 /*
357 * Configuration data structures
358 */
359 static struct bus_ops fhc_bus_ops = {
360 BUSO_REV,
361 ddi_bus_map, /* map */
362 0, /* get_intrspec */
363 0, /* add_intrspec */
364 0, /* remove_intrspec */
365 i_ddi_map_fault, /* map_fault */
366 ddi_no_dma_map, /* dma_map */
367 ddi_no_dma_allochdl,
368 ddi_no_dma_freehdl,
369 ddi_no_dma_bindhdl,
370 ddi_no_dma_unbindhdl,
371 ddi_no_dma_flush,
372 ddi_no_dma_win,
373 ddi_dma_mctl, /* dma_ctl */
374 fhc_ctlops, /* ctl */
375 ddi_bus_prop_op, /* prop_op */
376 0, /* (*bus_get_eventcookie)(); */
377 0, /* (*bus_add_eventcall)(); */
378 0, /* (*bus_remove_eventcall)(); */
379 0, /* (*bus_post_event)(); */
380 0, /* (*bus_intr_control)(); */
381 0, /* (*bus_config)(); */
382 0, /* (*bus_unconfig)(); */
383 0, /* (*bus_fm_init)(); */
384 0, /* (*bus_fm_fini)(); */
385 0, /* (*bus_fm_access_enter)(); */
386 0, /* (*bus_fm_access_exit)(); */
387 0, /* (*bus_power)(); */
388 fhc_intr_ops /* (*bus_intr_op)(); */
389 };
390
391 static struct cb_ops fhc_cb_ops = {
392 nulldev, /* open */
393 nulldev, /* close */
394 nulldev, /* strategy */
395 nulldev, /* print */
396 nulldev, /* dump */
397 nulldev, /* read */
398 nulldev, /* write */
399 nulldev, /* ioctl */
400 nodev, /* devmap */
401 nodev, /* mmap */
402 nodev, /* segmap */
403 nochpoll, /* poll */
404 ddi_prop_op, /* cb_prop_op */
405 0, /* streamtab */
406 D_MP|D_NEW|D_HOTPLUG, /* Driver compatibility flag */
407 CB_REV, /* rev */
408 nodev, /* cb_aread */
409 nodev /* cb_awrite */
410 };
411
412 static struct dev_ops fhc_ops = {
413 DEVO_REV, /* rev */
414 0, /* refcnt */
415 ddi_no_info, /* getinfo */
416 nulldev, /* identify */
417 nulldev, /* probe */
418 fhc_attach, /* attach */
419 fhc_detach, /* detach */
420 nulldev, /* reset */
421 &fhc_cb_ops, /* cb_ops */
422 &fhc_bus_ops, /* bus_ops */
423 nulldev, /* power */
424 ddi_quiesce_not_needed, /* quiesce */
425 };
426
427 /*
428 * Driver globals
429 * TODO - We need to investigate what locking needs to be done here.
430 */
431 void *fhcp; /* fhc soft state hook */
432
433 extern struct mod_ops mod_driverops;
434
435 static struct modldrv modldrv = {
436 &mod_driverops, /* Type of module. This one is a driver */
437 "FHC Nexus", /* Name of module. */
438 &fhc_ops, /* driver ops */
439 };
440
441 static struct modlinkage modlinkage = {
442 MODREV_1, /* rev */
443 (void *)&modldrv,
444 NULL
445 };
446
447
448 /*
449 * These are the module initialization routines.
450 */
451
452 static caddr_t shutdown_va;
453
454 int
_init(void)455 _init(void)
456 {
457 int error;
458
459 if ((error = ddi_soft_state_init(&fhcp,
460 sizeof (struct fhc_soft_state), 1)) != 0)
461 return (error);
462
463 fhc_bdlist_init();
464 mutex_init(&ftlist_mutex, NULL, MUTEX_DEFAULT, NULL);
465
466 shutdown_va = vmem_alloc(heap_arena, PAGESIZE, VM_SLEEP);
467 ASSERT(shutdown_va != NULL);
468
469 plat_register_tod_fault(fhc_tod_fault);
470
471 return (mod_install(&modlinkage));
472 }
473
474 int
_fini(void)475 _fini(void)
476 {
477 int error;
478
479 if ((error = mod_remove(&modlinkage)) != 0)
480 return (error);
481
482 plat_register_tod_fault(NULL);
483
484 mutex_destroy(&ftlist_mutex);
485
486 fhc_bdlist_fini();
487
488 ddi_soft_state_fini(&fhcp);
489
490 return (0);
491 }
492
493 int
_info(struct modinfo * modinfop)494 _info(struct modinfo *modinfop)
495 {
496 return (mod_info(&modlinkage, modinfop));
497 }
498
499 /*
500 * Reset the interrupt mapping registers.
501 * This function resets the values during DDI_RESUME.
502 *
503 * NOTE: This function will not work for a full CPR cycle
504 * and is currently designed to handle the RESUME after a connect.
505 *
506 * Note about the PROM handling of moving CENTRAL to another board:
507 * The PROM moves the IGN identity (igr register) from the
508 * original CENTRAL to the new one. This means that we do not
509 * duplicate the fhc_attach code that sets it to (board number * 2).
510 * We rely on only using FHC interrupts from one board only
511 * (the UART and SYS interrupts) so that the values of the other IGNs
512 * are irrelevant. The benefit of this approach is that we don't
513 * have to have to tear down and rebuild the interrupt records
514 * for UART and SYS. It is also why we don't try to change the
515 * board number in the fhc instance for the clock board.
516 */
517 static void
fhc_handle_imr(struct fhc_soft_state * softsp)518 fhc_handle_imr(struct fhc_soft_state *softsp)
519 {
520 int i;
521 int cent;
522 uint_t tmp_reg;
523
524
525 if (softsp->is_central) {
526 uint_t want_igr, act_igr;
527
528 want_igr = softsp->list->sc.board << 1;
529 act_igr = *softsp->igr & 0x1f;
530 if (want_igr != act_igr) {
531 *softsp->igr = want_igr;
532 tmp_reg = *softsp->igr;
533 #ifdef lint
534 tmp_reg = tmp_reg;
535 #endif
536 /* We must now re-issue any pending interrupts. */
537 for (i = 0; i < FHC_MAX_INO; i++) {
538 if (*(softsp->intr_regs[i].clear_reg) == 3) {
539 *(softsp->intr_regs[i].clear_reg) =
540 ISM_IDLE;
541
542 tmp_reg =
543 *(softsp->intr_regs[i].clear_reg);
544 #ifdef lint
545 tmp_reg = tmp_reg;
546 #endif
547 }
548 }
549 cmn_err(CE_NOTE, "central IGN corruption fixed: "
550 "got %x wanted %x", act_igr, want_igr);
551 }
552 return;
553 }
554
555 ASSERT(softsp->list->sc.board == FHC_BSR_TO_BD(*(softsp->bsr)));
556 cent = check_central(softsp->list->sc.board);
557
558 /* Loop through all 4 FHC interrupt mapping registers */
559 for (i = 0; i < FHC_MAX_INO; i++) {
560
561 if (i == FHC_SYS_INO &&
562 *(softsp->intr_regs[i].clear_reg) == 3) {
563 cmn_err(CE_NOTE,
564 "found lost system interrupt, resetting..");
565
566 *(softsp->intr_regs[i].clear_reg) = ISM_IDLE;
567
568 /*
569 * ensure atomic write with this read.
570 */
571 tmp_reg = *(softsp->intr_regs[i].clear_reg);
572 #ifdef lint
573 tmp_reg = tmp_reg;
574 #endif
575 }
576
577 /*
578 * The mapping registers on the board with the "central" bit
579 * set should not be touched as it has been taken care by POST.
580 */
581
582 if (cent)
583 continue;
584
585 *(softsp->intr_regs[i].mapping_reg) = 0;
586
587 /*
588 * ensure atomic write with this read.
589 */
590 tmp_reg = *(softsp->intr_regs[i].mapping_reg);
591 #ifdef lint
592 tmp_reg = tmp_reg;
593 #endif
594
595 }
596 }
597
598 static int
check_central(int board)599 check_central(int board)
600 {
601 uint_t cs_value;
602
603 /*
604 * This is the value of AC configuration and status reg
605 * in the Local Devices space. We access it as a physical
606 * address.
607 */
608 cs_value = ldphysio(AC_BCSR(board));
609 if (cs_value & AC_CENTRAL)
610 return (TRUE);
611 else
612 return (FALSE);
613 }
614
615 static int
fhc_attach(dev_info_t * devi,ddi_attach_cmd_t cmd)616 fhc_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
617 {
618 struct fhc_soft_state *softsp;
619 int instance;
620
621 instance = ddi_get_instance(devi);
622
623 switch (cmd) {
624 case DDI_ATTACH:
625 break;
626
627 case DDI_RESUME:
628 softsp = ddi_get_soft_state(fhcp, instance);
629 /* IGR, NOT_BRD_PRES handled by prom */
630 /* reset interrupt mapping registers */
631 fhc_handle_imr(softsp);
632
633 return (DDI_SUCCESS);
634
635 default:
636 return (DDI_FAILURE);
637 }
638
639
640 if (ddi_soft_state_zalloc(fhcp, instance) != DDI_SUCCESS)
641 return (DDI_FAILURE);
642
643 softsp = ddi_get_soft_state(fhcp, instance);
644
645 /* Set the dip in the soft state */
646 softsp->dip = devi;
647
648 if (fhc_init(softsp) != DDI_SUCCESS)
649 goto bad;
650
651 ddi_report_dev(devi);
652
653 return (DDI_SUCCESS);
654
655 bad:
656 ddi_soft_state_free(fhcp, instance);
657 return (DDI_FAILURE);
658 }
659
660 static int
fhc_detach(dev_info_t * devi,ddi_detach_cmd_t cmd)661 fhc_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
662 {
663 int board;
664 int instance;
665 struct fhc_soft_state *softsp;
666 fhc_bd_t *list = NULL;
667
668 /* get the instance of this devi */
669 instance = ddi_get_instance(devi);
670
671 /* get the soft state pointer for this device node */
672 softsp = ddi_get_soft_state(fhcp, instance);
673
674 board = softsp->list->sc.board;
675
676 switch (cmd) {
677 case DDI_SUSPEND:
678
679 return (DDI_SUCCESS);
680
681 case DDI_DETACH:
682 /* grab the lock on the board list */
683 list = fhc_bdlist_lock(board);
684
685 if (fhc_bd_detachable(board) &&
686 !fhc_bd_is_jtag_master(board))
687 break;
688 else
689 fhc_bdlist_unlock();
690 /* FALLTHROUGH */
691
692 default:
693 return (DDI_FAILURE);
694 }
695
696 /* Remove the interrupt redistribution callback. */
697 intr_dist_rem(fhc_intrdist, (void *)devi);
698
699 /* remove the soft state pointer from the board list */
700 list->softsp = NULL;
701
702 /* clear inherited faults from the PROM. */
703 clear_fault(list->sc.board, FT_PROM, FT_BOARD);
704
705 /* remove the kstat for this board */
706 kstat_delete(softsp->fhc_ksp);
707
708 /* destroy the mutexes in this soft state structure */
709 mutex_destroy(&softsp->poll_list_lock);
710 mutex_destroy(&softsp->ctrl_lock);
711
712 /* unmap all the register sets */
713 fhc_unmap_regs(softsp);
714
715 /* release the board list lock now */
716 fhc_bdlist_unlock();
717
718 /* free the soft state structure */
719 ddi_soft_state_free(fhcp, instance);
720
721 return (DDI_SUCCESS);
722 }
723
724 static enum board_type
fhc_board_type(struct fhc_soft_state * softsp,int board)725 fhc_board_type(struct fhc_soft_state *softsp, int board)
726 {
727 int proplen;
728 char *board_type;
729 enum board_type type;
730
731 if (softsp->is_central)
732 type = CLOCK_BOARD;
733 else if (ddi_getlongprop(DDI_DEV_T_ANY, softsp->dip,
734 DDI_PROP_DONTPASS, "board-type", (caddr_t)&board_type,
735 &proplen) == DDI_PROP_SUCCESS) {
736 /* match the board-type string */
737 if (strcmp(CPU_BD_NAME, board_type) == 0) {
738 type = CPU_BOARD;
739 } else if (strcmp(MEM_BD_NAME, board_type) == 0) {
740 type = MEM_BOARD;
741 } else if (strcmp(IO_2SBUS_BD_NAME, board_type) == 0) {
742 type = IO_2SBUS_BOARD;
743 } else if (strcmp(IO_SBUS_FFB_BD_NAME, board_type) == 0) {
744 type = IO_SBUS_FFB_BOARD;
745 } else if (strcmp(IO_2SBUS_SOCPLUS_BD_NAME, board_type) == 0) {
746 type = IO_2SBUS_SOCPLUS_BOARD;
747 } else if (strcmp(IO_SBUS_FFB_SOCPLUS_BD_NAME, board_type)
748 == 0) {
749 type = IO_SBUS_FFB_SOCPLUS_BOARD;
750 } else if (strcmp(IO_PCI_BD_NAME, board_type) == 0) {
751 type = IO_PCI_BOARD;
752 } else {
753 type = UNKNOWN_BOARD;
754 }
755 kmem_free(board_type, proplen);
756 } else
757 type = UNKNOWN_BOARD;
758
759 /*
760 * if the board type is indeterminate, it must be determined.
761 */
762 if (type == UNKNOWN_BOARD) {
763 /*
764 * Use the UPA64 bits from the FHC.
765 * This is not the best solution since we
766 * cannot fully type the IO boards.
767 */
768 if (cpu_on_board(board))
769 type = CPU_BOARD;
770 else if ((*(softsp->bsr) & FHC_UPADATA64A) ||
771 (*(softsp->bsr) & FHC_UPADATA64B))
772 type = IO_2SBUS_BOARD;
773 else
774 type = MEM_BOARD;
775 }
776
777 return (type);
778 }
779
780 static void
fhc_unmap_regs(struct fhc_soft_state * softsp)781 fhc_unmap_regs(struct fhc_soft_state *softsp)
782 {
783 dev_info_t *dip = softsp->dip;
784
785 if (softsp->id) {
786 ddi_unmap_regs(dip, 0, (caddr_t *)&softsp->id, 0, 0);
787 softsp->id = NULL;
788 }
789 if (softsp->igr) {
790 ddi_unmap_regs(dip, 1, (caddr_t *)&softsp->igr, 0, 0);
791 softsp->igr = NULL;
792 }
793 if (softsp->intr_regs[FHC_FANFAIL_INO].mapping_reg) {
794 ddi_unmap_regs(dip, 2,
795 (caddr_t *)&softsp->intr_regs[FHC_FANFAIL_INO].mapping_reg,
796 0, 0);
797 softsp->intr_regs[FHC_FANFAIL_INO].mapping_reg = NULL;
798 }
799 if (softsp->intr_regs[FHC_SYS_INO].mapping_reg) {
800 ddi_unmap_regs(dip, 3,
801 (caddr_t *)&softsp->intr_regs[FHC_SYS_INO].mapping_reg,
802 0, 0);
803 softsp->intr_regs[FHC_SYS_INO].mapping_reg = NULL;
804 }
805 if (softsp->intr_regs[FHC_UART_INO].mapping_reg) {
806 ddi_unmap_regs(dip, 4,
807 (caddr_t *)&softsp->intr_regs[FHC_UART_INO].mapping_reg,
808 0, 0);
809 softsp->intr_regs[FHC_UART_INO].mapping_reg = NULL;
810 }
811 if (softsp->intr_regs[FHC_TOD_INO].mapping_reg) {
812 ddi_unmap_regs(dip, 5,
813 (caddr_t *)&softsp->intr_regs[FHC_TOD_INO].mapping_reg,
814 0, 0);
815 softsp->intr_regs[FHC_TOD_INO].mapping_reg = NULL;
816 }
817 }
818
819 static int
fhc_init(struct fhc_soft_state * softsp)820 fhc_init(struct fhc_soft_state *softsp)
821 {
822 int i;
823 uint_t tmp_reg;
824 int board;
825
826 /*
827 * Map in the FHC registers. Specifying length and offset of
828 * zero maps in the entire OBP register set.
829 */
830
831 /* map in register set 0 */
832 if (ddi_map_regs(softsp->dip, 0,
833 (caddr_t *)&softsp->id, 0, 0)) {
834 cmn_err(CE_WARN, "fhc%d: unable to map internal "
835 "registers", ddi_get_instance(softsp->dip));
836 goto bad;
837 }
838
839 /*
840 * Fill in the virtual addresses of the registers in the
841 * fhc_soft_state structure.
842 */
843 softsp->rctrl = (uint_t *)((char *)(softsp->id) +
844 FHC_OFF_RCTRL);
845 softsp->ctrl = (uint_t *)((char *)(softsp->id) +
846 FHC_OFF_CTRL);
847 softsp->bsr = (uint_t *)((char *)(softsp->id) +
848 FHC_OFF_BSR);
849 softsp->jtag_ctrl = (uint_t *)((char *)(softsp->id) +
850 FHC_OFF_JTAG_CTRL);
851 softsp->jt_master.jtag_cmd = (uint_t *)((char *)(softsp->id) +
852 FHC_OFF_JTAG_CMD);
853
854 /* map in register set 1 */
855 if (ddi_map_regs(softsp->dip, 1,
856 (caddr_t *)&softsp->igr, 0, 0)) {
857 cmn_err(CE_WARN, "fhc%d: unable to map IGR "
858 "register", ddi_get_instance(softsp->dip));
859 goto bad;
860 }
861
862 /*
863 * map in register set 2
864 * XXX this can never be used as an interrupt generator
865 * (hardware queue overflow in fhc)
866 */
867 if (ddi_map_regs(softsp->dip, 2,
868 (caddr_t *)&softsp->intr_regs[FHC_FANFAIL_INO].mapping_reg,
869 0, 0)) {
870 cmn_err(CE_WARN, "fhc%d: unable to map Fan Fail "
871 "IMR register", ddi_get_instance(softsp->dip));
872 goto bad;
873 }
874
875 /* map in register set 3 */
876 if (ddi_map_regs(softsp->dip, 3,
877 (caddr_t *)&softsp->intr_regs[FHC_SYS_INO].mapping_reg,
878 0, 0)) {
879 cmn_err(CE_WARN, "fhc%d: unable to map System "
880 "IMR register\n", ddi_get_instance(softsp->dip));
881 goto bad;
882 }
883
884 /* map in register set 4 */
885 if (ddi_map_regs(softsp->dip, 4,
886 (caddr_t *)&softsp->intr_regs[FHC_UART_INO].mapping_reg,
887 0, 0)) {
888 cmn_err(CE_WARN, "fhc%d: unable to map UART "
889 "IMR register\n", ddi_get_instance(softsp->dip));
890 goto bad;
891 }
892
893 /* map in register set 5 */
894 if (ddi_map_regs(softsp->dip, 5,
895 (caddr_t *)&softsp->intr_regs[FHC_TOD_INO].mapping_reg,
896 0, 0)) {
897 cmn_err(CE_WARN, "fhc%d: unable to map FHC TOD "
898 "IMR register", ddi_get_instance(softsp->dip));
899 goto bad;
900 }
901
902 /* Loop over all intr sets and setup the VAs for the ISMR */
903 /* TODO - Make sure we are calculating the ISMR correctly. */
904 for (i = 0; i < FHC_MAX_INO; i++) {
905 softsp->intr_regs[i].clear_reg =
906 (uint_t *)((char *)(softsp->intr_regs[i].mapping_reg) +
907 FHC_OFF_ISMR);
908
909 /* Now clear the state machines to idle */
910 *(softsp->intr_regs[i].clear_reg) = ISM_IDLE;
911 }
912
913 /*
914 * It is OK to not have a OBP_BOARDNUM property. This happens for
915 * the board which is a child of central. However this FHC
916 * still needs a proper Interrupt Group Number programmed
917 * into the Interrupt Group register, because the other
918 * instance of FHC, which is not under central, will properly
919 * program the IGR. The numbers from the two settings of the
920 * IGR need to be the same. One driver cannot wait for the
921 * other to program the IGR, because there is no guarantee
922 * which instance of FHC will get attached first.
923 */
924 if ((board = (int)ddi_getprop(DDI_DEV_T_ANY, softsp->dip,
925 DDI_PROP_DONTPASS, OBP_BOARDNUM, -1)) == -1) {
926 /*
927 * Now determine the board number by reading the
928 * hardware register.
929 */
930 board = FHC_BSR_TO_BD(*(softsp->bsr));
931 softsp->is_central = 1;
932 }
933
934 /*
935 * If this fhc holds JTAG master line, and is not the central fhc,
936 * (this avoids two JTAG master nodes) then initialize the
937 * mutex and set the flag in the structure.
938 */
939 if ((*(softsp->jtag_ctrl) & JTAG_MASTER_EN) && !softsp->is_central) {
940 mutex_init(&(softsp->jt_master.lock), NULL, MUTEX_DEFAULT,
941 NULL);
942 softsp->jt_master.is_master = 1;
943 } else {
944 softsp->jt_master.is_master = 0;
945 }
946
947 fhc_bd_init(softsp, board, fhc_board_type(softsp, board));
948
949 /* Initialize the mutex guarding the poll_list. */
950 mutex_init(&softsp->poll_list_lock, NULL, MUTEX_DRIVER, NULL);
951
952 /* Initialize the mutex guarding the FHC CSR */
953 mutex_init(&softsp->ctrl_lock, NULL, MUTEX_DRIVER, NULL);
954
955 /* Initialize the poll_list to be empty */
956 for (i = 0; i < MAX_ZS_CNT; i++) {
957 softsp->poll_list[i].funcp = NULL;
958 }
959
960 /* Modify the various registers in the FHC now */
961
962 /*
963 * We know this board to be present now, record that state and
964 * remove the NOT_BRD_PRES condition
965 */
966 if (!(softsp->is_central)) {
967 mutex_enter(&softsp->ctrl_lock);
968 *(softsp->ctrl) |= FHC_NOT_BRD_PRES;
969 /* Now flush the hardware store buffers. */
970 tmp_reg = *(softsp->ctrl);
971 #ifdef lint
972 tmp_reg = tmp_reg;
973 #endif
974 /* XXX record the board state in global space */
975 mutex_exit(&softsp->ctrl_lock);
976
977 /* Add kstats for all non-central instances of the FHC. */
978 fhc_add_kstats(softsp);
979 }
980
981 /*
982 * Read the device tree to see if this system is in an environmental
983 * chamber.
984 */
985 if (temperature_chamber == -1) {
986 temperature_chamber = check_for_chamber();
987 }
988
989 /* Check for inherited faults from the PROM. */
990 if (*softsp->ctrl & FHC_LED_MID) {
991 reg_fault(softsp->list->sc.board, FT_PROM, FT_BOARD);
992 }
993
994 /*
995 * setup the IGR. Shift the board number over by one to get
996 * the UPA MID.
997 */
998 *(softsp->igr) = (softsp->list->sc.board) << 1;
999
1000 /* Now flush the hardware store buffers. */
1001 tmp_reg = *(softsp->id);
1002 #ifdef lint
1003 tmp_reg = tmp_reg;
1004 #endif
1005
1006 /* Add the interrupt redistribution callback. */
1007 intr_dist_add(fhc_intrdist, (void *)softsp->dip);
1008
1009 return (DDI_SUCCESS);
1010 bad:
1011 fhc_unmap_regs(softsp);
1012 return (DDI_FAILURE);
1013 }
1014
1015 static uint_t
fhc_intr_wrapper(caddr_t arg)1016 fhc_intr_wrapper(caddr_t arg)
1017 {
1018 uint_t intr_return;
1019 uint_t tmpreg;
1020 struct fhc_wrapper_arg *intr_info = (struct fhc_wrapper_arg *)arg;
1021 uint_t (*funcp)(caddr_t, caddr_t) = intr_info->funcp;
1022 caddr_t iarg1 = intr_info->arg1;
1023 caddr_t iarg2 = intr_info->arg2;
1024 dev_info_t *dip = intr_info->child;
1025
1026 tmpreg = ISM_IDLE;
1027
1028 DTRACE_PROBE4(interrupt__start, dev_info_t, dip,
1029 void *, funcp, caddr_t, iarg1, caddr_t, iarg2);
1030
1031 intr_return = (*funcp)(iarg1, iarg2);
1032
1033 DTRACE_PROBE4(interrupt__complete, dev_info_t, dip,
1034 void *, funcp, caddr_t, iarg1, int, intr_return);
1035
1036 /* Idle the state machine. */
1037 *(intr_info->clear_reg) = tmpreg;
1038
1039 /* Flush the hardware store buffers. */
1040 tmpreg = *(intr_info->clear_reg);
1041 #ifdef lint
1042 tmpreg = tmpreg;
1043 #endif /* lint */
1044
1045 return (intr_return);
1046 }
1047
1048 /*
1049 * fhc_zs_intr_wrapper
1050 *
1051 * This function handles intrerrupts where more than one device may interupt
1052 * the fhc with the same mondo.
1053 */
1054
1055 #define MAX_INTR_CNT 10
1056
1057 static uint_t
fhc_zs_intr_wrapper(caddr_t arg)1058 fhc_zs_intr_wrapper(caddr_t arg)
1059 {
1060 struct fhc_soft_state *softsp = (struct fhc_soft_state *)arg;
1061 uint_t (*funcp0)(caddr_t, caddr_t);
1062 uint_t (*funcp1)(caddr_t, caddr_t);
1063 caddr_t funcp0_arg1, funcp0_arg2, funcp1_arg1, funcp1_arg2;
1064 uint_t tmp_reg;
1065 uint_t result = DDI_INTR_UNCLAIMED;
1066 volatile uint_t *clear_reg;
1067 uchar_t *spurious_cntr = &softsp->spurious_zs_cntr;
1068
1069 funcp0 = softsp->poll_list[0].funcp;
1070 funcp1 = softsp->poll_list[1].funcp;
1071 funcp0_arg1 = softsp->poll_list[0].arg1;
1072 funcp0_arg2 = softsp->poll_list[0].arg2;
1073 funcp1_arg1 = softsp->poll_list[1].arg1;
1074 funcp1_arg2 = softsp->poll_list[1].arg2;
1075 clear_reg = softsp->intr_regs[FHC_UART_INO].clear_reg;
1076
1077 if (funcp0 != NULL) {
1078 if ((funcp0)(funcp0_arg1, funcp0_arg2) == DDI_INTR_CLAIMED) {
1079 result = DDI_INTR_CLAIMED;
1080 }
1081 }
1082
1083 if (funcp1 != NULL) {
1084 if ((funcp1)(funcp1_arg1, funcp1_arg2) == DDI_INTR_CLAIMED) {
1085 result = DDI_INTR_CLAIMED;
1086 }
1087 }
1088
1089 if (result == DDI_INTR_UNCLAIMED) {
1090 (*spurious_cntr)++;
1091
1092 if (*spurious_cntr < MAX_INTR_CNT) {
1093 result = DDI_INTR_CLAIMED;
1094 } else {
1095 *spurious_cntr = (uchar_t)0;
1096 }
1097 } else {
1098 *spurious_cntr = (uchar_t)0;
1099 }
1100
1101 /* Idle the state machine. */
1102 *(clear_reg) = ISM_IDLE;
1103
1104 /* flush the store buffers. */
1105 tmp_reg = *(clear_reg);
1106 #ifdef lint
1107 tmp_reg = tmp_reg;
1108 #endif
1109
1110 return (result);
1111 }
1112
1113
1114 /*
1115 * add_intrspec - Add an interrupt specification.
1116 */
1117 static int
fhc_add_intr_impl(dev_info_t * dip,dev_info_t * rdip,ddi_intr_handle_impl_t * hdlp)1118 fhc_add_intr_impl(dev_info_t *dip, dev_info_t *rdip,
1119 ddi_intr_handle_impl_t *hdlp)
1120 {
1121 int ino;
1122 struct fhc_wrapper_arg *fhc_arg;
1123 struct fhc_soft_state *softsp = (struct fhc_soft_state *)
1124 ddi_get_soft_state(fhcp, ddi_get_instance(dip));
1125 volatile uint_t *mondo_vec_reg;
1126 uint_t tmp_mondo_vec;
1127 uint_t tmpreg; /* HW flush reg */
1128 uint_t cpu_id;
1129 int ret = DDI_SUCCESS;
1130
1131 /* Xlate the interrupt */
1132 fhc_xlate_intrs(hdlp,
1133 (softsp->list->sc.board << BD_IVINTR_SHFT));
1134
1135 /* get the mondo number */
1136 ino = FHC_INO(hdlp->ih_vector);
1137 mondo_vec_reg = softsp->intr_regs[ino].mapping_reg;
1138
1139 ASSERT(ino < FHC_MAX_INO);
1140
1141 /* We don't use the two spare interrupts. */
1142 if (ino >= FHC_MAX_INO) {
1143 cmn_err(CE_WARN, "fhc%d: Spare interrupt %d not usable",
1144 ddi_get_instance(dip), ino);
1145 return (DDI_FAILURE);
1146 }
1147
1148 /* TOD and Fan Fail interrupts are not usable */
1149 if (ino == FHC_TOD_INO) {
1150 cmn_err(CE_WARN, "fhc%d: TOD interrupt not usable",
1151 ddi_get_instance(dip));
1152 return (DDI_FAILURE);
1153 }
1154 if (ino == FHC_FANFAIL_INO) {
1155 cmn_err(CE_WARN, "fhc%d: Fan fail interrupt not usable",
1156 ddi_get_instance(dip));
1157 return (DDI_FAILURE);
1158 }
1159
1160 /*
1161 * If the interrupt is for the zs chips, use the vector
1162 * polling lists. Otherwise use a straight handler.
1163 */
1164 if (ino == FHC_UART_INO) {
1165 int32_t zs_inst;
1166 /* First lock the mutex for this poll_list */
1167 mutex_enter(&softsp->poll_list_lock);
1168
1169 /*
1170 * Add this interrupt to the polling list.
1171 */
1172
1173 /* figure out where to add this item in the list */
1174 for (zs_inst = 0; zs_inst < MAX_ZS_CNT; zs_inst++) {
1175 if (softsp->poll_list[zs_inst].funcp == NULL) {
1176 softsp->poll_list[zs_inst].arg1 =
1177 hdlp->ih_cb_arg1;
1178 softsp->poll_list[zs_inst].arg2 =
1179 hdlp->ih_cb_arg2;
1180 softsp->poll_list[zs_inst].funcp =
1181 (ddi_intr_handler_t *)
1182 hdlp->ih_cb_func;
1183 softsp->poll_list[zs_inst].inum =
1184 hdlp->ih_inum;
1185 softsp->poll_list[zs_inst].child = rdip;
1186
1187 break;
1188 }
1189 }
1190
1191 if (zs_inst >= MAX_ZS_CNT) {
1192 cmn_err(CE_WARN,
1193 "fhc%d: poll list overflow",
1194 ddi_get_instance(dip));
1195 mutex_exit(&softsp->poll_list_lock);
1196 ret = DDI_FAILURE;
1197 goto done;
1198 }
1199
1200 /*
1201 * If polling list is empty, then install handler
1202 * and enable interrupts for this ino.
1203 */
1204 if (zs_inst == 0) {
1205 DDI_INTR_ASSIGN_HDLR_N_ARGS(hdlp,
1206 (ddi_intr_handler_t *)fhc_zs_intr_wrapper,
1207 (caddr_t)softsp, NULL);
1208
1209 ret = i_ddi_add_ivintr(hdlp);
1210
1211 DDI_INTR_ASSIGN_HDLR_N_ARGS(hdlp,
1212 softsp->poll_list[zs_inst].funcp,
1213 softsp->poll_list[zs_inst].arg1,
1214 softsp->poll_list[zs_inst].arg2);
1215
1216 if (ret != DDI_SUCCESS)
1217 goto done;
1218 }
1219
1220 /*
1221 * If both zs handlers are active, then this is the
1222 * second add_intrspec called, so do not enable
1223 * the IMR_VALID bit, it is already on.
1224 */
1225 if (zs_inst > 0) {
1226 /* now release the mutex and return */
1227 mutex_exit(&softsp->poll_list_lock);
1228
1229 goto done;
1230 } else {
1231 /* just release the mutex */
1232 mutex_exit(&softsp->poll_list_lock);
1233 }
1234 } else { /* normal interrupt installation */
1235 int32_t i;
1236
1237 /* Allocate a nexus interrupt data structure */
1238 fhc_arg = kmem_alloc(sizeof (struct fhc_wrapper_arg), KM_SLEEP);
1239 fhc_arg->child = rdip;
1240 fhc_arg->mapping_reg = mondo_vec_reg;
1241 fhc_arg->clear_reg = (softsp->intr_regs[ino].clear_reg);
1242 fhc_arg->softsp = softsp;
1243 fhc_arg->funcp =
1244 (ddi_intr_handler_t *)hdlp->ih_cb_func;
1245 fhc_arg->arg1 = hdlp->ih_cb_arg1;
1246 fhc_arg->arg2 = hdlp->ih_cb_arg2;
1247 fhc_arg->inum = hdlp->ih_inum;
1248
1249 for (i = 0; i < FHC_MAX_INO; i++) {
1250 if (softsp->intr_list[i] == 0) {
1251 softsp->intr_list[i] = fhc_arg;
1252 break;
1253 }
1254 }
1255
1256 /*
1257 * Save the fhc_arg in the ispec so we can use this info
1258 * later to uninstall this interrupt spec.
1259 */
1260 DDI_INTR_ASSIGN_HDLR_N_ARGS(hdlp,
1261 (ddi_intr_handler_t *)fhc_intr_wrapper,
1262 (caddr_t)fhc_arg, NULL);
1263
1264 ret = i_ddi_add_ivintr(hdlp);
1265
1266 DDI_INTR_ASSIGN_HDLR_N_ARGS(hdlp, fhc_arg->funcp,
1267 fhc_arg->arg1, fhc_arg->arg2);
1268
1269 if (ret != DDI_SUCCESS)
1270 goto done;
1271 }
1272
1273 /*
1274 * Clear out a stale 'pending' or 'transmit' state in
1275 * this device's ISM that might have been left from a
1276 * previous session.
1277 *
1278 * Since all FHC interrupts are level interrupts, any
1279 * real interrupting condition will immediately transition
1280 * the ISM back to pending.
1281 */
1282 *(softsp->intr_regs[ino].clear_reg) = ISM_IDLE;
1283
1284 /*
1285 * Program the mondo vector accordingly. This MUST be the
1286 * last thing we do. Once we program the ino, the device
1287 * may begin to interrupt.
1288 */
1289 cpu_id = intr_dist_cpuid();
1290
1291 tmp_mondo_vec = cpu_id << INR_PID_SHIFT;
1292
1293 /* don't do this for fan because fan has a special control */
1294 if (ino == FHC_FANFAIL_INO)
1295 panic("fhc%d: enabling fanfail interrupt",
1296 ddi_get_instance(dip));
1297 else
1298 tmp_mondo_vec |= IMR_VALID;
1299
1300 DPRINTF(FHC_INTERRUPT_DEBUG,
1301 ("Mondo 0x%x mapping reg: 0x%p", hdlp->ih_vector,
1302 (void *)mondo_vec_reg));
1303
1304 /* Store it in the hardware reg. */
1305 *mondo_vec_reg = tmp_mondo_vec;
1306
1307 /* Read a FHC register to flush store buffers */
1308 tmpreg = *(softsp->id);
1309 #ifdef lint
1310 tmpreg = tmpreg;
1311 #endif
1312
1313 done:
1314 return (ret);
1315 }
1316
1317 /*
1318 * remove_intrspec - Remove an interrupt specification.
1319 */
1320 static void
fhc_remove_intr_impl(dev_info_t * dip,dev_info_t * rdip,ddi_intr_handle_impl_t * hdlp)1321 fhc_remove_intr_impl(dev_info_t *dip, dev_info_t *rdip,
1322 ddi_intr_handle_impl_t *hdlp)
1323 {
1324 volatile uint_t *mondo_vec_reg;
1325 volatile uint_t tmpreg;
1326 int i;
1327 struct fhc_soft_state *softsp = (struct fhc_soft_state *)
1328 ddi_get_soft_state(fhcp, ddi_get_instance(dip));
1329 int ino;
1330
1331 /* Xlate the interrupt */
1332 fhc_xlate_intrs(hdlp,
1333 (softsp->list->sc.board << BD_IVINTR_SHFT));
1334
1335 /* get the mondo number */
1336 ino = FHC_INO(hdlp->ih_vector);
1337
1338 if (ino == FHC_UART_INO) {
1339 int intr_found = 0;
1340
1341 /* Lock the poll_list first */
1342 mutex_enter(&softsp->poll_list_lock);
1343
1344 /*
1345 * Find which entry in the poll list belongs to this
1346 * intrspec.
1347 */
1348 for (i = 0; i < MAX_ZS_CNT; i++) {
1349 if (softsp->poll_list[i].child == rdip &&
1350 softsp->poll_list[i].inum == hdlp->ih_inum) {
1351 softsp->poll_list[i].funcp = NULL;
1352 intr_found++;
1353 }
1354 }
1355
1356 /* If we did not find an entry, then we have a problem */
1357 if (!intr_found) {
1358 cmn_err(CE_WARN, "fhc%d: Intrspec not found in"
1359 " poll list", ddi_get_instance(dip));
1360 mutex_exit(&softsp->poll_list_lock);
1361 goto done;
1362 }
1363
1364 /*
1365 * If we have removed all active entries for the poll
1366 * list, then we have to disable interupts at this point.
1367 */
1368 if ((softsp->poll_list[0].funcp == NULL) &&
1369 (softsp->poll_list[1].funcp == NULL)) {
1370 mondo_vec_reg =
1371 softsp->intr_regs[FHC_UART_INO].mapping_reg;
1372 *mondo_vec_reg &= ~IMR_VALID;
1373
1374 /* flush the hardware buffers */
1375 tmpreg = *(softsp->ctrl);
1376
1377 /* Eliminate the particular handler from the system. */
1378 i_ddi_rem_ivintr(hdlp);
1379 }
1380
1381 mutex_exit(&softsp->poll_list_lock);
1382 } else {
1383 int32_t i;
1384
1385
1386 for (i = 0; i < FHC_MAX_INO; i++)
1387 if (softsp->intr_list[i]->child == rdip &&
1388 softsp->intr_list[i]->inum == hdlp->ih_inum)
1389 break;
1390
1391 if (i >= FHC_MAX_INO)
1392 goto done;
1393
1394 mondo_vec_reg = softsp->intr_list[i]->mapping_reg;
1395
1396 /* Turn off the valid bit in the mapping register. */
1397 /* XXX what about FHC_FANFAIL owned imr? */
1398 *mondo_vec_reg &= ~IMR_VALID;
1399
1400 /* flush the hardware store buffers */
1401 tmpreg = *(softsp->id);
1402 #ifdef lint
1403 tmpreg = tmpreg;
1404 #endif
1405
1406 /* Eliminate the particular handler from the system. */
1407 i_ddi_rem_ivintr(hdlp);
1408
1409 kmem_free(softsp->intr_list[i],
1410 sizeof (struct fhc_wrapper_arg));
1411 softsp->intr_list[i] = 0;
1412 }
1413
1414 done:
1415 ;
1416 }
1417
1418 /* new intr_ops structure */
1419 static int
fhc_intr_ops(dev_info_t * dip,dev_info_t * rdip,ddi_intr_op_t intr_op,ddi_intr_handle_impl_t * hdlp,void * result)1420 fhc_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t intr_op,
1421 ddi_intr_handle_impl_t *hdlp, void *result)
1422 {
1423 int ret = DDI_SUCCESS;
1424
1425 switch (intr_op) {
1426 case DDI_INTROP_GETCAP:
1427 *(int *)result = DDI_INTR_FLAG_LEVEL;
1428 break;
1429 case DDI_INTROP_ALLOC:
1430 *(int *)result = hdlp->ih_scratch1;
1431 break;
1432 case DDI_INTROP_FREE:
1433 break;
1434 case DDI_INTROP_GETPRI:
1435 if (hdlp->ih_pri == 0) {
1436 struct fhc_soft_state *softsp =
1437 (struct fhc_soft_state *)ddi_get_soft_state(fhcp,
1438 ddi_get_instance(dip));
1439
1440 /* Xlate the interrupt */
1441 fhc_xlate_intrs(hdlp,
1442 (softsp->list->sc.board << BD_IVINTR_SHFT));
1443 }
1444
1445 *(int *)result = hdlp->ih_pri;
1446 break;
1447 case DDI_INTROP_SETPRI:
1448 break;
1449 case DDI_INTROP_ADDISR:
1450 ret = fhc_add_intr_impl(dip, rdip, hdlp);
1451 break;
1452 case DDI_INTROP_REMISR:
1453 fhc_remove_intr_impl(dip, rdip, hdlp);
1454 break;
1455 case DDI_INTROP_ENABLE:
1456 case DDI_INTROP_DISABLE:
1457 break;
1458 case DDI_INTROP_NINTRS:
1459 case DDI_INTROP_NAVAIL:
1460 *(int *)result = i_ddi_get_intx_nintrs(rdip);
1461 break;
1462 case DDI_INTROP_SETCAP:
1463 case DDI_INTROP_SETMASK:
1464 case DDI_INTROP_CLRMASK:
1465 case DDI_INTROP_GETPENDING:
1466 ret = DDI_ENOTSUP;
1467 break;
1468 case DDI_INTROP_SUPPORTED_TYPES:
1469 /* only support fixed interrupts */
1470 *(int *)result = i_ddi_get_intx_nintrs(rdip) ?
1471 DDI_INTR_TYPE_FIXED : 0;
1472 break;
1473 default:
1474 ret = i_ddi_intr_ops(dip, rdip, intr_op, hdlp, result);
1475 break;
1476 }
1477
1478 return (ret);
1479 }
1480
1481 /*
1482 * FHC Control Ops routine
1483 *
1484 * Requests handled here:
1485 * DDI_CTLOPS_INITCHILD see impl_ddi_sunbus_initchild() for details
1486 * DDI_CTLOPS_UNINITCHILD see fhc_uninit_child() for details
1487 * DDI_CTLOPS_REPORTDEV TODO - need to implement this.
1488 */
1489 static int
fhc_ctlops(dev_info_t * dip,dev_info_t * rdip,ddi_ctl_enum_t op,void * arg,void * result)1490 fhc_ctlops(dev_info_t *dip, dev_info_t *rdip,
1491 ddi_ctl_enum_t op, void *arg, void *result)
1492 {
1493
1494 switch (op) {
1495 case DDI_CTLOPS_INITCHILD:
1496 DPRINTF(FHC_CTLOPS_DEBUG, ("DDI_CTLOPS_INITCHILD\n"));
1497 return (impl_ddi_sunbus_initchild((dev_info_t *)arg));
1498
1499 case DDI_CTLOPS_UNINITCHILD:
1500 impl_ddi_sunbus_removechild((dev_info_t *)arg);
1501 return (DDI_SUCCESS);
1502
1503 case DDI_CTLOPS_REPORTDEV:
1504 /*
1505 * TODO - Figure out what makes sense to report here.
1506 */
1507 return (DDI_SUCCESS);
1508
1509 case DDI_CTLOPS_POKE:
1510 case DDI_CTLOPS_PEEK:
1511 return (fhc_ctlops_peekpoke(op, (peekpoke_ctlops_t *)arg,
1512 result));
1513
1514 default:
1515 return (ddi_ctlops(dip, rdip, op, arg, result));
1516 }
1517 }
1518
1519
1520 /*
1521 * We're prepared to claim that the interrupt string is in
1522 * the form of a list of <FHCintr> specifications, or we're dealing
1523 * with on-board devices and we have an interrupt_number property which
1524 * gives us our mondo number.
1525 * Translate the mondos into fhcintrspecs.
1526 */
1527 /* ARGSUSED */
1528 static void
fhc_xlate_intrs(ddi_intr_handle_impl_t * hdlp,uint32_t ign)1529 fhc_xlate_intrs(ddi_intr_handle_impl_t *hdlp, uint32_t ign)
1530
1531 {
1532 uint32_t mondo;
1533
1534 mondo = hdlp->ih_vector;
1535
1536 hdlp->ih_vector = (mondo | ign);
1537 if (hdlp->ih_pri == 0)
1538 hdlp->ih_pri = fhc_int_priorities[FHC_INO(mondo)];
1539 }
1540
1541 static int
fhc_ctlops_peekpoke(ddi_ctl_enum_t cmd,peekpoke_ctlops_t * in_args,void * result)1542 fhc_ctlops_peekpoke(ddi_ctl_enum_t cmd, peekpoke_ctlops_t *in_args,
1543 void *result)
1544 {
1545 int err = DDI_SUCCESS;
1546 on_trap_data_t otd;
1547
1548 /* No safe access except for peek/poke is supported. */
1549 if (in_args->handle != NULL)
1550 return (DDI_FAILURE);
1551
1552 /* Set up protected environment. */
1553 if (!on_trap(&otd, OT_DATA_ACCESS)) {
1554 uintptr_t tramp = otd.ot_trampoline;
1555
1556 if (cmd == DDI_CTLOPS_POKE) {
1557 otd.ot_trampoline = (uintptr_t)&poke_fault;
1558 err = do_poke(in_args->size, (void *)in_args->dev_addr,
1559 (void *)in_args->host_addr);
1560 } else {
1561 otd.ot_trampoline = (uintptr_t)&peek_fault;
1562 err = do_peek(in_args->size, (void *)in_args->dev_addr,
1563 (void *)in_args->host_addr);
1564 result = (void *)in_args->host_addr;
1565 }
1566 otd.ot_trampoline = tramp;
1567 } else
1568 err = DDI_FAILURE;
1569
1570 /* Take down protected environment. */
1571 no_trap();
1572
1573 return (err);
1574 }
1575
1576 /*
1577 * This function initializes the temperature arrays for use. All
1578 * temperatures are set in to invalid value to start.
1579 */
1580 void
init_temp_arrays(struct temp_stats * envstat)1581 init_temp_arrays(struct temp_stats *envstat)
1582 {
1583 int i;
1584
1585 envstat->index = 0;
1586
1587 for (i = 0; i < L1_SZ; i++) {
1588 envstat->l1[i] = NA_TEMP;
1589 }
1590
1591 for (i = 0; i < L2_SZ; i++) {
1592 envstat->l2[i] = NA_TEMP;
1593 }
1594
1595 for (i = 0; i < L3_SZ; i++) {
1596 envstat->l3[i] = NA_TEMP;
1597 }
1598
1599 for (i = 0; i < L4_SZ; i++) {
1600 envstat->l4[i] = NA_TEMP;
1601 }
1602
1603 for (i = 0; i < L5_SZ; i++) {
1604 envstat->l5[i] = NA_TEMP;
1605 }
1606
1607 envstat->max = NA_TEMP;
1608 envstat->min = NA_TEMP;
1609 envstat->trend = TREND_UNKNOWN;
1610 envstat->version = TEMP_KSTAT_VERSION;
1611 envstat->override = NA_TEMP;
1612 }
1613
1614 /* Inhibit warning messages below this temperature, eg for CPU poweron. */
1615 static uint_t fhc_cpu_warning_temp_threshold = FHC_CPU_WARNING_TEMP_THRESHOLD;
1616
1617 /*
1618 * This function manages the temperature history in the temperature
1619 * statistics buffer passed in. It calls the temperature calibration
1620 * routines and maintains the time averaged temperature data.
1621 */
1622 void
update_temp(dev_info_t * pdip,struct temp_stats * envstat,uchar_t value)1623 update_temp(dev_info_t *pdip, struct temp_stats *envstat, uchar_t value)
1624 {
1625 uint_t index; /* The absolute temperature counter */
1626 uint_t tmp_index; /* temp index into upper level array */
1627 int count; /* Count of non-zero values in array */
1628 int total; /* sum total of non-zero values in array */
1629 short real_temp; /* calibrated temperature */
1630 int i;
1631 struct fhc_soft_state *softsp;
1632 char buffer[256]; /* buffer for warning of overtemp */
1633 enum temp_state temp_state; /* Temperature state */
1634
1635 /*
1636 * NOTE: This global counter is not protected since we're called
1637 * serially for each board.
1638 */
1639 static int shutdown_msg = 0; /* Flag if shutdown warning issued */
1640
1641 /* determine soft state pointer of parent */
1642 softsp = ddi_get_soft_state(fhcp, ddi_get_instance(pdip));
1643
1644 envstat->index++;
1645 index = envstat->index;
1646
1647 /*
1648 * You need to update the level 5 intervals first, since
1649 * they are based on the data from the level 4 intervals,
1650 * and so on, down to the level 1 intervals.
1651 */
1652
1653 /* update the level 5 intervals if it is time */
1654 if (((tmp_index = L5_INDEX(index)) > 0) && (L5_REM(index) == 0)) {
1655 /* Generate the index within the level 5 array */
1656 tmp_index -= 1; /* decrement by 1 for indexing */
1657 tmp_index = tmp_index % L5_SZ;
1658
1659 /* take an average of the level 4 array */
1660 for (i = 0, count = 0, total = 0; i < L4_SZ; i++) {
1661 /* Do not include zero values in average */
1662 if (envstat->l4[i] != NA_TEMP) {
1663 total += (int)envstat->l4[i];
1664 count++;
1665 }
1666 }
1667
1668 /*
1669 * If there were any level 4 data points to average,
1670 * do so.
1671 */
1672 if (count != 0) {
1673 envstat->l5[tmp_index] = total/count;
1674 } else {
1675 envstat->l5[tmp_index] = NA_TEMP;
1676 }
1677 }
1678
1679 /* update the level 4 intervals if it is time */
1680 if (((tmp_index = L4_INDEX(index)) > 0) && (L4_REM(index) == 0)) {
1681 /* Generate the index within the level 4 array */
1682 tmp_index -= 1; /* decrement by 1 for indexing */
1683 tmp_index = tmp_index % L4_SZ;
1684
1685 /* take an average of the level 3 array */
1686 for (i = 0, count = 0, total = 0; i < L3_SZ; i++) {
1687 /* Do not include zero values in average */
1688 if (envstat->l3[i] != NA_TEMP) {
1689 total += (int)envstat->l3[i];
1690 count++;
1691 }
1692 }
1693
1694 /*
1695 * If there were any level 3 data points to average,
1696 * do so.
1697 */
1698 if (count != 0) {
1699 envstat->l4[tmp_index] = total/count;
1700 } else {
1701 envstat->l4[tmp_index] = NA_TEMP;
1702 }
1703 }
1704
1705 /* update the level 3 intervals if it is time */
1706 if (((tmp_index = L3_INDEX(index)) > 0) && (L3_REM(index) == 0)) {
1707 /* Generate the index within the level 3 array */
1708 tmp_index -= 1; /* decrement by 1 for indexing */
1709 tmp_index = tmp_index % L3_SZ;
1710
1711 /* take an average of the level 2 array */
1712 for (i = 0, count = 0, total = 0; i < L2_SZ; i++) {
1713 /* Do not include zero values in average */
1714 if (envstat->l2[i] != NA_TEMP) {
1715 total += (int)envstat->l2[i];
1716 count++;
1717 }
1718 }
1719
1720 /*
1721 * If there were any level 2 data points to average,
1722 * do so.
1723 */
1724 if (count != 0) {
1725 envstat->l3[tmp_index] = total/count;
1726 } else {
1727 envstat->l3[tmp_index] = NA_TEMP;
1728 }
1729 }
1730
1731 /* update the level 2 intervals if it is time */
1732 if (((tmp_index = L2_INDEX(index)) > 0) && (L2_REM(index) == 0)) {
1733 /* Generate the index within the level 2 array */
1734 tmp_index -= 1; /* decrement by 1 for indexing */
1735 tmp_index = tmp_index % L2_SZ;
1736
1737 /* take an average of the level 1 array */
1738 for (i = 0, count = 0, total = 0; i < L1_SZ; i++) {
1739 /* Do not include zero values in average */
1740 if (envstat->l1[i] != NA_TEMP) {
1741 total += (int)envstat->l1[i];
1742 count++;
1743 }
1744 }
1745
1746 /*
1747 * If there were any level 1 data points to average,
1748 * do so.
1749 */
1750 if (count != 0) {
1751 envstat->l2[tmp_index] = total/count;
1752 } else {
1753 envstat->l2[tmp_index] = NA_TEMP;
1754 }
1755 }
1756
1757 /* determine the current temperature in degrees Celcius */
1758 if (envstat->override != NA_TEMP) {
1759 /* use override temperature for this board */
1760 real_temp = envstat->override;
1761 } else {
1762 /* Run the calibration function using this board type */
1763 real_temp = calibrate_temp(softsp->list->sc.type, value,
1764 softsp->list->sc.ac_compid);
1765 }
1766
1767 envstat->l1[index % L1_SZ] = real_temp;
1768
1769 /* check if the temperature state for this device needs to change */
1770 temp_state = get_temp_state(softsp->list->sc.type, real_temp,
1771 softsp->list->sc.board);
1772
1773 /* has the state changed? Then get the board string ready */
1774 if (temp_state != envstat->state) {
1775 int board = softsp->list->sc.board;
1776 enum board_type type = softsp->list->sc.type;
1777
1778 build_bd_display_str(buffer, type, board);
1779
1780 if (temp_state > envstat->state) {
1781 if (envstat->state == TEMP_OK) {
1782 if (type == CLOCK_BOARD) {
1783 reg_fault(0, FT_OVERTEMP, FT_SYSTEM);
1784 } else {
1785 reg_fault(board, FT_OVERTEMP,
1786 FT_BOARD);
1787 }
1788 }
1789
1790 /* heating up, change state now */
1791 envstat->temp_cnt = 0;
1792 envstat->state = temp_state;
1793
1794 if (temp_state == TEMP_WARN) {
1795 /* now warn the user of the problem */
1796 cmn_err(CE_WARN,
1797 "%s is warm (temperature: %dC). "
1798 "Please check system cooling", buffer,
1799 real_temp);
1800 fhc_bd_update(board, SYSC_EVT_BD_OVERTEMP);
1801 if (temperature_chamber == -1)
1802 temperature_chamber =
1803 check_for_chamber();
1804 } else if (temp_state == TEMP_DANGER) {
1805 cmn_err(CE_WARN,
1806 "%s is very hot (temperature: %dC)",
1807 buffer, real_temp);
1808
1809 envstat->shutdown_cnt = 1;
1810 if (temperature_chamber == -1)
1811 temperature_chamber =
1812 check_for_chamber();
1813 if ((temperature_chamber == 0) &&
1814 enable_overtemp_powerdown) {
1815 /*
1816 * NOTE: The "%d seconds" is not
1817 * necessarily accurate in the case
1818 * where we have multiple boards
1819 * overheating and subsequently cooling
1820 * down.
1821 */
1822 if (shutdown_msg == 0) {
1823 cmn_err(CE_WARN, "System "
1824 "shutdown scheduled "
1825 "in %d seconds due to "
1826 "over-temperature "
1827 "condition on %s",
1828 SHUTDOWN_TIMEOUT_SEC,
1829 buffer);
1830 }
1831 shutdown_msg++;
1832 }
1833 }
1834
1835 /*
1836 * If this is a cpu board, power them off.
1837 */
1838 if (temperature_chamber == 0) {
1839 mutex_enter(&cpu_lock);
1840 (void) fhc_board_poweroffcpus(board, NULL,
1841 CPU_FORCED);
1842 mutex_exit(&cpu_lock);
1843 }
1844 } else if (temp_state < envstat->state) {
1845 /*
1846 * Avert the sigpower that would
1847 * otherwise be sent to init.
1848 */
1849 envstat->shutdown_cnt = 0;
1850
1851 /* cooling down, use state counter */
1852 if (envstat->temp_cnt == 0) {
1853 envstat->temp_cnt = TEMP_STATE_COUNT;
1854 } else if (--envstat->temp_cnt == 0) {
1855 if (temp_state == TEMP_WARN) {
1856 cmn_err(CE_NOTE,
1857 "%s is cooling "
1858 "(temperature: %dC)", buffer,
1859 real_temp);
1860
1861 } else if (temp_state == TEMP_OK) {
1862 cmn_err(CE_NOTE,
1863 "%s has cooled down "
1864 "(temperature: %dC), system OK",
1865 buffer, real_temp);
1866
1867 if (type == CLOCK_BOARD) {
1868 clear_fault(0, FT_OVERTEMP,
1869 FT_SYSTEM);
1870 } else {
1871 clear_fault(board, FT_OVERTEMP,
1872 FT_BOARD);
1873 }
1874 }
1875
1876 /*
1877 * If we just came out of TEMP_DANGER, and
1878 * a warning was issued about shutting down,
1879 * let the user know it's been cancelled
1880 */
1881 if (envstat->state == TEMP_DANGER &&
1882 (temperature_chamber == 0) &&
1883 enable_overtemp_powerdown &&
1884 (powerdown_started == 0) &&
1885 (--shutdown_msg == 0)) {
1886 cmn_err(CE_NOTE, "System "
1887 "shutdown due to over-"
1888 "temperature "
1889 "condition cancelled");
1890 }
1891 envstat->state = temp_state;
1892
1893 fhc_bd_update(board, SYSC_EVT_BD_TEMP_OK);
1894 }
1895 }
1896 } else {
1897 envstat->temp_cnt = 0;
1898
1899 if (temp_state == TEMP_DANGER) {
1900 if (temperature_chamber == -1) {
1901 temperature_chamber = check_for_chamber();
1902 }
1903
1904 if ((envstat->shutdown_cnt++ >= SHUTDOWN_COUNT) &&
1905 (temperature_chamber == 0) &&
1906 enable_overtemp_powerdown &&
1907 (powerdown_started == 0)) {
1908 powerdown_started = 1;
1909
1910 /* the system is still too hot */
1911 build_bd_display_str(buffer,
1912 softsp->list->sc.type,
1913 softsp->list->sc.board);
1914
1915 cmn_err(CE_WARN, "%s still too hot "
1916 "(temperature: %dC)."
1917 " Overtemp shutdown started", buffer,
1918 real_temp);
1919
1920 fhc_reboot();
1921 }
1922 }
1923 }
1924
1925 /* update the maximum and minimum temperatures if necessary */
1926 if ((envstat->max == NA_TEMP) || (real_temp > envstat->max)) {
1927 envstat->max = real_temp;
1928 }
1929
1930 if ((envstat->min == NA_TEMP) || (real_temp < envstat->min)) {
1931 envstat->min = real_temp;
1932 }
1933
1934 /*
1935 * Update the temperature trend. Currently, the temperature
1936 * trend algorithm is based on the level 2 stats. So, we
1937 * only need to run every time the level 2 stats get updated.
1938 */
1939 if (((tmp_index = L2_INDEX(index)) > 0) && (L2_REM(index) == 0)) {
1940 enum board_type type = softsp->list->sc.type;
1941
1942 envstat->trend = temp_trend(envstat);
1943
1944 /* Issue a warning if the temperature is rising rapidly. */
1945 /* For CPU boards, don't warn if CPUs just powered on. */
1946 if (envstat->trend == TREND_RAPID_RISE &&
1947 (type != CPU_BOARD || real_temp >
1948 fhc_cpu_warning_temp_threshold)) {
1949 int board = softsp->list->sc.board;
1950
1951 build_bd_display_str(buffer, type, board);
1952 cmn_err(CE_WARN, "%s temperature is rising rapidly! "
1953 "Current temperature is %dC", buffer,
1954 real_temp);
1955 }
1956 }
1957 }
1958
1959 #define PREV_L2_INDEX(x) ((x) ? ((x) - 1) : (L2_SZ - 1))
1960
1961 /*
1962 * This routine determines if the temp of the device passed in is heating
1963 * up, cooling down, or staying stable.
1964 */
1965 enum temp_trend
temp_trend(struct temp_stats * tempstat)1966 temp_trend(struct temp_stats *tempstat)
1967 {
1968 int ii;
1969 uint_t curr_index;
1970 int curr_temp;
1971 uint_t prev_index;
1972 int prev_temp;
1973 int trail_temp;
1974 int delta;
1975 int read_cnt;
1976 enum temp_trend result = TREND_STABLE;
1977
1978 if (tempstat == NULL)
1979 return (TREND_UNKNOWN);
1980
1981 curr_index = (L2_INDEX(tempstat->index) - 1) % L2_SZ;
1982 curr_temp = tempstat->l2[curr_index];
1983
1984 /* Count how many temperature readings are available */
1985 prev_index = curr_index;
1986 for (read_cnt = 0; read_cnt < L2_SZ - 1; read_cnt++) {
1987 if (tempstat->l2[prev_index] == NA_TEMP)
1988 break;
1989 prev_index = PREV_L2_INDEX(prev_index);
1990 }
1991
1992 switch (read_cnt) {
1993 case 0:
1994 case 1:
1995 result = TREND_UNKNOWN;
1996 break;
1997
1998 default:
1999 delta = curr_temp - tempstat->l2[PREV_L2_INDEX(curr_index)];
2000 prev_index = curr_index;
2001 trail_temp = prev_temp = curr_temp;
2002 if (delta >= RAPID_RISE_THRESH) { /* rapid rise? */
2003 result = TREND_RAPID_RISE;
2004 } else if (delta > 0) { /* rise? */
2005 for (ii = 1; ii < read_cnt; ii++) {
2006 prev_index = PREV_L2_INDEX(prev_index);
2007 prev_temp = tempstat->l2[prev_index];
2008 if (prev_temp > trail_temp) {
2009 break;
2010 }
2011 trail_temp = prev_temp;
2012 if (prev_temp <= curr_temp - NOISE_THRESH) {
2013 result = TREND_RISE;
2014 break;
2015 }
2016 }
2017 } else if (delta <= -RAPID_FALL_THRESH) { /* rapid fall? */
2018 result = TREND_RAPID_FALL;
2019 } else if (delta < 0) { /* fall? */
2020 for (ii = 1; ii < read_cnt; ii++) {
2021 prev_index = PREV_L2_INDEX(prev_index);
2022 prev_temp = tempstat->l2[prev_index];
2023 if (prev_temp < trail_temp) {
2024 break;
2025 }
2026 trail_temp = prev_temp;
2027 if (prev_temp >= curr_temp + NOISE_THRESH) {
2028 result = TREND_FALL;
2029 break;
2030 }
2031 }
2032 }
2033 }
2034 return (result);
2035 }
2036
2037 /*
2038 * Reboot the system if we can, otherwise attempt a power down
2039 */
2040 void
fhc_reboot(void)2041 fhc_reboot(void)
2042 {
2043 proc_t *initpp;
2044
2045 /* send a SIGPWR to init process */
2046 mutex_enter(&pidlock);
2047 initpp = prfind(P_INITPID);
2048 mutex_exit(&pidlock);
2049
2050 /*
2051 * If we're still booting and init(1) isn't
2052 * set up yet, simply halt.
2053 */
2054 if (initpp != NULL) {
2055 psignal(initpp, SIGFPE); /* init 6 */
2056 } else {
2057 power_down("Environmental Shutdown");
2058 halt("Power off the System");
2059 }
2060 }
2061
2062 int
overtemp_kstat_update(kstat_t * ksp,int rw)2063 overtemp_kstat_update(kstat_t *ksp, int rw)
2064 {
2065 struct temp_stats *tempstat;
2066 char *kstatp;
2067 int i;
2068
2069 kstatp = (char *)ksp->ks_data;
2070 tempstat = (struct temp_stats *)ksp->ks_private;
2071
2072 /*
2073 * Kstat reads are used to retrieve the current system temperature
2074 * history. Kstat writes are used to reset the max and min
2075 * temperatures.
2076 */
2077 if (rw == KSTAT_WRITE) {
2078 short max; /* temporary copy of max temperature */
2079 short min; /* temporary copy of min temperature */
2080
2081 /*
2082 * search for and reset the max and min to the current
2083 * array contents. Old max and min values will get
2084 * averaged out as they move into the higher level arrays.
2085 */
2086 max = tempstat->l1[0];
2087 min = tempstat->l1[0];
2088
2089 /* Pull the max and min from Level 1 array */
2090 for (i = 0; i < L1_SZ; i++) {
2091 if ((tempstat->l1[i] != NA_TEMP) &&
2092 (tempstat->l1[i] > max)) {
2093 max = tempstat->l1[i];
2094 }
2095
2096 if ((tempstat->l1[i] != NA_TEMP) &&
2097 (tempstat->l1[i] < min)) {
2098 min = tempstat->l1[i];
2099 }
2100 }
2101
2102 /* Pull the max and min from Level 2 array */
2103 for (i = 0; i < L2_SZ; i++) {
2104 if ((tempstat->l2[i] != NA_TEMP) &&
2105 (tempstat->l2[i] > max)) {
2106 max = tempstat->l2[i];
2107 }
2108
2109 if ((tempstat->l2[i] != NA_TEMP) &&
2110 (tempstat->l2[i] < min)) {
2111 min = tempstat->l2[i];
2112 }
2113 }
2114
2115 /* Pull the max and min from Level 3 array */
2116 for (i = 0; i < L3_SZ; i++) {
2117 if ((tempstat->l3[i] != NA_TEMP) &&
2118 (tempstat->l3[i] > max)) {
2119 max = tempstat->l3[i];
2120 }
2121
2122 if ((tempstat->l3[i] != NA_TEMP) &&
2123 (tempstat->l3[i] < min)) {
2124 min = tempstat->l3[i];
2125 }
2126 }
2127
2128 /* Pull the max and min from Level 4 array */
2129 for (i = 0; i < L4_SZ; i++) {
2130 if ((tempstat->l4[i] != NA_TEMP) &&
2131 (tempstat->l4[i] > max)) {
2132 max = tempstat->l4[i];
2133 }
2134
2135 if ((tempstat->l4[i] != NA_TEMP) &&
2136 (tempstat->l4[i] < min)) {
2137 min = tempstat->l4[i];
2138 }
2139 }
2140
2141 /* Pull the max and min from Level 5 array */
2142 for (i = 0; i < L5_SZ; i++) {
2143 if ((tempstat->l5[i] != NA_TEMP) &&
2144 (tempstat->l5[i] > max)) {
2145 max = tempstat->l5[i];
2146 }
2147
2148 if ((tempstat->l5[i] != NA_TEMP) &&
2149 (tempstat->l5[i] < min)) {
2150 min = tempstat->l5[i];
2151 }
2152 }
2153 } else {
2154 /*
2155 * copy the temperature history buffer into the
2156 * kstat structure.
2157 */
2158 bcopy(tempstat, kstatp, sizeof (struct temp_stats));
2159 }
2160 return (0);
2161 }
2162
2163 int
temp_override_kstat_update(kstat_t * ksp,int rw)2164 temp_override_kstat_update(kstat_t *ksp, int rw)
2165 {
2166 short *over;
2167 short *kstatp;
2168
2169 kstatp = (short *)ksp->ks_data;
2170 over = (short *)ksp->ks_private;
2171
2172 /*
2173 * Kstat reads are used to get the temperature override setting.
2174 * Kstat writes are used to set the temperature override setting.
2175 */
2176 if (rw == KSTAT_WRITE) {
2177 *over = *kstatp;
2178 } else {
2179 *kstatp = *over;
2180 }
2181 return (0);
2182 }
2183
2184 /*
2185 * This function uses the calibration tables at the beginning of this file
2186 * to lookup the actual temperature of the thermistor in degrees Celcius.
2187 * If the measurement is out of the bounds of the acceptable values, the
2188 * closest boundary value is used instead.
2189 */
2190 static short
calibrate_temp(enum board_type type,uchar_t temp,uint_t ac_comp)2191 calibrate_temp(enum board_type type, uchar_t temp, uint_t ac_comp)
2192 {
2193 short result = NA_TEMP;
2194
2195 if (dont_calibrate == 1) {
2196 return ((short)temp);
2197 }
2198
2199 switch (type) {
2200 case CPU_BOARD:
2201 /*
2202 * If AC chip revision is >= 4 or if it is unitialized,
2203 * then use the new calibration tables.
2204 */
2205 if ((CHIP_REV(ac_comp) >= 4) || (CHIP_REV(ac_comp) == 0)) {
2206 if (temp >= CPU2_MX_CNT) {
2207 result = cpu2_table[CPU2_MX_CNT-1];
2208 } else {
2209 result = cpu2_table[temp];
2210 }
2211 } else {
2212 if (temp >= CPU_MX_CNT) {
2213 result = cpu_table[CPU_MX_CNT-1];
2214 } else {
2215 result = cpu_table[temp];
2216 }
2217 }
2218 break;
2219
2220 case IO_2SBUS_BOARD:
2221 case IO_SBUS_FFB_BOARD:
2222 case IO_PCI_BOARD:
2223 case IO_2SBUS_SOCPLUS_BOARD:
2224 case IO_SBUS_FFB_SOCPLUS_BOARD:
2225 if (temp < IO_MN_CNT) {
2226 result = io_table[IO_MN_CNT];
2227 } else if (temp >= IO_MX_CNT) {
2228 result = io_table[IO_MX_CNT-1];
2229 } else {
2230 result = io_table[temp];
2231 }
2232 break;
2233
2234 case CLOCK_BOARD:
2235 if (temp < CLK_MN_CNT) {
2236 result = clock_table[CLK_MN_CNT];
2237 } else if (temp >= CLK_MX_CNT) {
2238 result = clock_table[CLK_MX_CNT-1];
2239 } else {
2240 result = clock_table[temp];
2241 }
2242 break;
2243
2244 default:
2245 break;
2246 }
2247
2248 return (result);
2249 }
2250
2251 /*
2252 * Determine the temperature state of this board based on its type and
2253 * the actual temperature in degrees Celcius.
2254 */
2255 static enum temp_state
get_temp_state(enum board_type type,short temp,int board)2256 get_temp_state(enum board_type type, short temp, int board)
2257 {
2258 enum temp_state state = TEMP_OK;
2259 short warn_limit;
2260 short danger_limit;
2261 struct cpu *cpa, *cpb;
2262
2263 switch (type) {
2264 case CPU_BOARD:
2265 warn_limit = cpu_warn_temp;
2266 danger_limit = cpu_danger_temp;
2267
2268 /*
2269 * For CPU boards with frequency >= 400 MHZ,
2270 * temperature zones are different.
2271 */
2272
2273 mutex_enter(&cpu_lock);
2274
2275 if ((cpa = cpu_get(FHC_BOARD2CPU_A(board))) != NULL) {
2276 if ((cpa->cpu_type_info.pi_clock) >= 400) {
2277 warn_limit = cpu_warn_temp_4x;
2278 danger_limit = cpu_danger_temp_4x;
2279 }
2280 }
2281 if ((cpb = cpu_get(FHC_BOARD2CPU_B(board))) != NULL) {
2282 if ((cpb->cpu_type_info.pi_clock) >= 400) {
2283 warn_limit = cpu_warn_temp_4x;
2284 danger_limit = cpu_danger_temp_4x;
2285 }
2286 }
2287
2288 mutex_exit(&cpu_lock);
2289
2290 break;
2291
2292 case IO_2SBUS_BOARD:
2293 case IO_SBUS_FFB_BOARD:
2294 case IO_PCI_BOARD:
2295 case IO_2SBUS_SOCPLUS_BOARD:
2296 case IO_SBUS_FFB_SOCPLUS_BOARD:
2297 warn_limit = io_warn_temp;
2298 danger_limit = io_danger_temp;
2299 break;
2300
2301 case CLOCK_BOARD:
2302 warn_limit = clk_warn_temp;
2303 danger_limit = clk_danger_temp;
2304 break;
2305
2306 case UNINIT_BOARD:
2307 case UNKNOWN_BOARD:
2308 case MEM_BOARD:
2309 default:
2310 warn_limit = dft_warn_temp;
2311 danger_limit = dft_danger_temp;
2312 break;
2313 }
2314
2315 if (temp >= danger_limit) {
2316 state = TEMP_DANGER;
2317 } else if (temp >= warn_limit) {
2318 state = TEMP_WARN;
2319 }
2320
2321 return (state);
2322 }
2323
2324 static void
fhc_add_kstats(struct fhc_soft_state * softsp)2325 fhc_add_kstats(struct fhc_soft_state *softsp)
2326 {
2327 struct kstat *fhc_ksp;
2328 struct fhc_kstat *fhc_named_ksp;
2329
2330 if ((fhc_ksp = kstat_create("unix", softsp->list->sc.board,
2331 FHC_KSTAT_NAME, "misc", KSTAT_TYPE_NAMED,
2332 sizeof (struct fhc_kstat) / sizeof (kstat_named_t),
2333 KSTAT_FLAG_PERSISTENT)) == NULL) {
2334 cmn_err(CE_WARN, "fhc%d kstat_create failed",
2335 ddi_get_instance(softsp->dip));
2336 return;
2337 }
2338
2339 fhc_named_ksp = (struct fhc_kstat *)(fhc_ksp->ks_data);
2340
2341 /* initialize the named kstats */
2342 kstat_named_init(&fhc_named_ksp->csr,
2343 CSR_KSTAT_NAMED,
2344 KSTAT_DATA_UINT32);
2345
2346 kstat_named_init(&fhc_named_ksp->bsr,
2347 BSR_KSTAT_NAMED,
2348 KSTAT_DATA_UINT32);
2349
2350 fhc_ksp->ks_update = fhc_kstat_update;
2351 fhc_ksp->ks_private = (void *)softsp;
2352 softsp->fhc_ksp = fhc_ksp;
2353 kstat_install(fhc_ksp);
2354 }
2355
2356 static int
fhc_kstat_update(kstat_t * ksp,int rw)2357 fhc_kstat_update(kstat_t *ksp, int rw)
2358 {
2359 struct fhc_kstat *fhcksp;
2360 struct fhc_soft_state *softsp;
2361
2362 fhcksp = (struct fhc_kstat *)ksp->ks_data;
2363 softsp = (struct fhc_soft_state *)ksp->ks_private;
2364
2365 /* this is a read-only kstat. Bail out on a write */
2366 if (rw == KSTAT_WRITE) {
2367 return (EACCES);
2368 } else {
2369 /*
2370 * copy the current state of the hardware into the
2371 * kstat structure.
2372 */
2373 fhcksp->csr.value.ui32 = *softsp->ctrl;
2374 fhcksp->bsr.value.ui32 = *softsp->bsr;
2375 }
2376 return (0);
2377 }
2378
2379 static int
cpu_on_board(int board)2380 cpu_on_board(int board)
2381 {
2382 int upa_a = board << 1;
2383 int upa_b = (board << 1) + 1;
2384
2385 if ((cpunodes[upa_a].nodeid != NULL) ||
2386 (cpunodes[upa_b].nodeid != NULL)) {
2387 return (1);
2388 } else {
2389 return (0);
2390 }
2391 }
2392
2393 /*
2394 * This function uses the board list and toggles the OS green board
2395 * LED. The mask input tells which bit fields are being modified,
2396 * and the value input tells the states of the bits.
2397 */
2398 void
update_board_leds(fhc_bd_t * board,uint_t mask,uint_t value)2399 update_board_leds(fhc_bd_t *board, uint_t mask, uint_t value)
2400 {
2401 volatile uint_t temp;
2402
2403 ASSERT(fhc_bdlist_locked());
2404
2405 /* mask off mask and value for only the LED bits */
2406 mask &= (FHC_LED_LEFT|FHC_LED_MID|FHC_LED_RIGHT);
2407 value &= (FHC_LED_LEFT|FHC_LED_MID|FHC_LED_RIGHT);
2408
2409 if (board != NULL) {
2410 mutex_enter(&board->softsp->ctrl_lock);
2411
2412 /* read the current register state */
2413 temp = *board->softsp->ctrl;
2414
2415 /*
2416 * The EPDA bits are special since the register is
2417 * special. We don't want to set them, since setting
2418 * the bits on a shutdown cpu keeps the cpu permanently
2419 * powered off. Also, the CSR_SYNC bit must always be
2420 * set to 0 as it is an OBP semaphore that is expected to
2421 * be clear for cpu restart.
2422 */
2423 temp &= ~(FHC_CSR_SYNC | FHC_EPDA_OFF | FHC_EPDB_OFF);
2424
2425 /* mask off the bits to change */
2426 temp &= ~mask;
2427
2428 /* or in the new values of the bits. */
2429 temp |= value;
2430
2431 /* update the register */
2432 *board->softsp->ctrl = temp;
2433
2434 /* flush the hardware registers */
2435 temp = *board->softsp->ctrl;
2436 #ifdef lint
2437 temp = temp;
2438 #endif
2439
2440 mutex_exit(&board->softsp->ctrl_lock);
2441 }
2442 }
2443
2444 static int
check_for_chamber(void)2445 check_for_chamber(void)
2446 {
2447 int chamber = 0;
2448 dev_info_t *options_dip;
2449 pnode_t options_node_id;
2450 int mfgmode_len;
2451 int retval;
2452 char *mfgmode;
2453
2454 /*
2455 * The operator can disable overtemp powerdown from /etc/system or
2456 * boot -h.
2457 */
2458 if (!enable_overtemp_powerdown) {
2459 cmn_err(CE_WARN, "Operator has disabled overtemp powerdown");
2460 return (1);
2461 }
2462
2463 /*
2464 * An OBP option, 'mfg-mode' is being used to inform us as to
2465 * whether we are in an enviromental chamber. It exists in
2466 * the 'options' node. This is where all OBP 'setenv' (eeprom)
2467 * parameters live.
2468 */
2469 if ((options_dip = ddi_find_devinfo("options", -1, 0)) != NULL) {
2470 options_node_id = (pnode_t)ddi_get_nodeid(options_dip);
2471 mfgmode_len = prom_getproplen(options_node_id, "mfg-mode");
2472 if (mfgmode_len == -1) {
2473 return (chamber);
2474 }
2475 mfgmode = kmem_alloc(mfgmode_len+1, KM_SLEEP);
2476
2477 retval = prom_getprop(options_node_id, "mfg-mode", mfgmode);
2478 if (retval != -1) {
2479 mfgmode[retval] = 0;
2480 if (strcmp(mfgmode, CHAMBER_VALUE) == 0) {
2481 chamber = 1;
2482 cmn_err(CE_WARN, "System in Temperature"
2483 " Chamber Mode. Overtemperature"
2484 " Shutdown disabled");
2485 }
2486 }
2487 kmem_free(mfgmode, mfgmode_len+1);
2488 }
2489 return (chamber);
2490 }
2491
2492 static void
build_bd_display_str(char * buffer,enum board_type type,int board)2493 build_bd_display_str(char *buffer, enum board_type type, int board)
2494 {
2495 if (buffer == NULL) {
2496 return;
2497 }
2498
2499 /* fill in board type to display */
2500 switch (type) {
2501 case UNINIT_BOARD:
2502 (void) sprintf(buffer, "Uninitialized Board type board %d",
2503 board);
2504 break;
2505
2506 case UNKNOWN_BOARD:
2507 (void) sprintf(buffer, "Unknown Board type board %d", board);
2508 break;
2509
2510 case CPU_BOARD:
2511 case MEM_BOARD:
2512 (void) sprintf(buffer, "CPU/Memory board %d", board);
2513 break;
2514
2515 case IO_2SBUS_BOARD:
2516 (void) sprintf(buffer, "2 SBus IO board %d", board);
2517 break;
2518
2519 case IO_SBUS_FFB_BOARD:
2520 (void) sprintf(buffer, "SBus FFB IO board %d", board);
2521 break;
2522
2523 case IO_PCI_BOARD:
2524 (void) sprintf(buffer, "PCI IO board %d", board);
2525 break;
2526
2527 case CLOCK_BOARD:
2528 (void) sprintf(buffer, "Clock board");
2529 break;
2530
2531 case IO_2SBUS_SOCPLUS_BOARD:
2532 (void) sprintf(buffer, "2 SBus SOC+ IO board %d", board);
2533 break;
2534
2535 case IO_SBUS_FFB_SOCPLUS_BOARD:
2536 (void) sprintf(buffer, "SBus FFB SOC+ IO board %d", board);
2537 break;
2538
2539 default:
2540 (void) sprintf(buffer, "Unrecognized board type board %d",
2541 board);
2542 break;
2543 }
2544 }
2545
2546 void
fhc_intrdist(void * arg)2547 fhc_intrdist(void *arg)
2548 {
2549 struct fhc_soft_state *softsp;
2550 dev_info_t *dip = (dev_info_t *)arg;
2551 volatile uint_t *mondo_vec_reg;
2552 volatile uint_t *intr_state_reg;
2553 uint_t mondo_vec;
2554 uint_t tmp_reg;
2555 uint_t cpu_id;
2556 uint_t i;
2557
2558 /* extract the soft state pointer */
2559 softsp = ddi_get_soft_state(fhcp, ddi_get_instance(dip));
2560
2561 /*
2562 * Loop through all the interrupt mapping registers and reprogram
2563 * the target CPU for all valid registers.
2564 */
2565 for (i = 0; i < FHC_MAX_INO; i++) {
2566 mondo_vec_reg = softsp->intr_regs[i].mapping_reg;
2567 intr_state_reg = softsp->intr_regs[i].clear_reg;
2568
2569 if ((*mondo_vec_reg & IMR_VALID) == 0)
2570 continue;
2571
2572 cpu_id = intr_dist_cpuid();
2573
2574 /* Check the current target of the mondo */
2575 if (((*mondo_vec_reg & INR_PID_MASK) >> INR_PID_SHIFT) ==
2576 cpu_id) {
2577 /* It is the same, don't reprogram */
2578 return;
2579 }
2580
2581 /* So it's OK to reprogram the CPU target */
2582
2583 /* turn off the valid bit */
2584 *mondo_vec_reg &= ~IMR_VALID;
2585
2586 /* flush the hardware registers */
2587 tmp_reg = *softsp->id;
2588
2589 /*
2590 * wait for the state machine to idle. Do not loop on panic, so
2591 * that system does not hang.
2592 */
2593 while (((*intr_state_reg & INT_PENDING) == INT_PENDING) &&
2594 !panicstr)
2595 ;
2596
2597 /* re-target the mondo and turn it on */
2598 mondo_vec = (cpu_id << INR_PID_SHIFT) | IMR_VALID;
2599
2600 /* write it back to the hardware. */
2601 *mondo_vec_reg = mondo_vec;
2602
2603 /* flush the hardware buffers. */
2604 tmp_reg = *(softsp->id);
2605
2606 #ifdef lint
2607 tmp_reg = tmp_reg;
2608 #endif /* lint */
2609 }
2610 }
2611
2612 /*
2613 * reg_fault
2614 *
2615 * This routine registers a fault in the fault list. If the fault
2616 * is unique (does not exist in fault list) then a new fault is
2617 * added to the fault list, with the appropriate structure elements
2618 * filled in.
2619 */
2620 void
reg_fault(int unit,enum ft_type type,enum ft_class fclass)2621 reg_fault(int unit, enum ft_type type, enum ft_class fclass)
2622 {
2623 struct ft_link_list *list; /* temporary list pointer */
2624
2625 if (type >= ft_max_index) {
2626 cmn_err(CE_WARN, "Illegal Fault type %x", type);
2627 return;
2628 }
2629
2630 mutex_enter(&ftlist_mutex);
2631
2632 /* Search for the requested fault. If it already exists, return. */
2633 for (list = ft_list; list != NULL; list = list->next) {
2634 if ((list->f.unit == unit) && (list->f.type == type) &&
2635 (list->f.fclass == fclass)) {
2636 mutex_exit(&ftlist_mutex);
2637 return;
2638 }
2639 }
2640
2641 /* Allocate a new fault structure. */
2642 list = kmem_zalloc(sizeof (struct ft_link_list), KM_SLEEP);
2643
2644 /* fill in the fault list elements */
2645 list->f.unit = unit;
2646 list->f.type = type;
2647 list->f.fclass = fclass;
2648 list->f.create_time = (time32_t)gethrestime_sec(); /* XX64 */
2649 (void) strncpy(list->f.msg, ft_str_table[type], MAX_FT_DESC);
2650
2651 /* link it into the list. */
2652 list->next = ft_list;
2653 ft_list = list;
2654
2655 /* Update the total fault count */
2656 ft_nfaults++;
2657
2658 mutex_exit(&ftlist_mutex);
2659 }
2660
2661 /*
2662 * clear_fault
2663 *
2664 * This routine finds the fault list entry specified by the caller,
2665 * deletes it from the fault list, and frees up the memory used for
2666 * the entry. If the requested fault is not found, it exits silently.
2667 */
2668 void
clear_fault(int unit,enum ft_type type,enum ft_class fclass)2669 clear_fault(int unit, enum ft_type type, enum ft_class fclass)
2670 {
2671 struct ft_link_list *list; /* temporary list pointer */
2672 struct ft_link_list **vect;
2673
2674 mutex_enter(&ftlist_mutex);
2675
2676 list = ft_list;
2677 vect = &ft_list;
2678
2679 /*
2680 * Search for the requested fault. If it exists, delete it
2681 * and relink the fault list.
2682 */
2683 for (; list != NULL; vect = &list->next, list = list->next) {
2684 if ((list->f.unit == unit) && (list->f.type == type) &&
2685 (list->f.fclass == fclass)) {
2686 /* remove the item from the list */
2687 *vect = list->next;
2688
2689 /* free the memory allocated */
2690 kmem_free(list, sizeof (struct ft_link_list));
2691
2692 /* Update the total fault count */
2693 ft_nfaults--;
2694 break;
2695 }
2696 }
2697 mutex_exit(&ftlist_mutex);
2698 }
2699
2700 /*
2701 * process_fault_list
2702 *
2703 * This routine walks the global fault list and updates the board list
2704 * with the current status of each Yellow LED. If any faults are found
2705 * in the system, then a non-zero value is returned. Else zero is returned.
2706 */
2707 int
process_fault_list(void)2708 process_fault_list(void)
2709 {
2710 int fault = 0;
2711 struct ft_link_list *ftlist; /* fault list pointer */
2712 fhc_bd_t *bdlist; /* board list pointer */
2713
2714 /*
2715 * Note on locking. The bdlist mutex is always acquired and
2716 * held around the ftlist mutex when both are needed for an
2717 * operation. This is to avoid deadlock.
2718 */
2719
2720 /* First lock the board list */
2721 (void) fhc_bdlist_lock(-1);
2722
2723 /* Grab the fault list lock first */
2724 mutex_enter(&ftlist_mutex);
2725
2726 /* clear the board list of all faults first */
2727 for (bdlist = fhc_bd_first(); bdlist; bdlist = fhc_bd_next(bdlist))
2728 bdlist->fault = 0;
2729
2730 /* walk the fault list here */
2731 for (ftlist = ft_list; ftlist != NULL; ftlist = ftlist->next) {
2732 fault++;
2733
2734 /*
2735 * If this is a board level fault, find the board, The
2736 * unit number for all board class faults must be the
2737 * actual board number. The caller of reg_fault must
2738 * ensure this for FT_BOARD class faults.
2739 */
2740 if (ftlist->f.fclass == FT_BOARD) {
2741 /* Sanity check the board first */
2742 if (fhc_bd_valid(ftlist->f.unit)) {
2743 bdlist = fhc_bd(ftlist->f.unit);
2744 bdlist->fault = 1;
2745 } else {
2746 cmn_err(CE_WARN, "No board %d list entry found",
2747 ftlist->f.unit);
2748 }
2749 }
2750 }
2751
2752 /* now unlock the fault list */
2753 mutex_exit(&ftlist_mutex);
2754
2755 /* unlock the board list before leaving */
2756 fhc_bdlist_unlock();
2757
2758 return (fault);
2759 }
2760
2761 /*
2762 * Add a new memloc to the database (and keep 'em sorted by PA)
2763 */
2764 void
fhc_add_memloc(int board,uint64_t pa,uint_t size)2765 fhc_add_memloc(int board, uint64_t pa, uint_t size)
2766 {
2767 struct fhc_memloc *p, **pp;
2768 uint_t ipa = pa >> FHC_MEMLOC_SHIFT;
2769
2770 ASSERT(fhc_bdlist_locked());
2771 ASSERT((size & (size-1)) == 0); /* size must be power of 2 */
2772
2773 /* look for a comparable memloc (as long as new PA smaller) */
2774 for (p = fhc_base_memloc, pp = &fhc_base_memloc;
2775 p != NULL; pp = &p->next, p = p->next) {
2776 /* have we passed our place in the sort? */
2777 if (ipa < p->pa) {
2778 break;
2779 }
2780 }
2781 p = kmem_alloc(sizeof (struct fhc_memloc), KM_SLEEP);
2782 p->next = *pp;
2783 p->board = board;
2784 p->pa = ipa;
2785 p->size = size;
2786 #ifdef DEBUG_MEMDEC
2787 cmn_err(CE_NOTE, "fhc_add_memloc: adding %d 0x%x 0x%x",
2788 p->board, p->pa, p->size);
2789 #endif /* DEBUG_MEMDEC */
2790 *pp = p;
2791 }
2792
2793 /*
2794 * Delete all memloc records for a board from the database
2795 */
2796 void
fhc_del_memloc(int board)2797 fhc_del_memloc(int board)
2798 {
2799 struct fhc_memloc *p, **pp;
2800
2801 ASSERT(fhc_bdlist_locked());
2802
2803 /* delete all entries that match board */
2804 pp = &fhc_base_memloc;
2805 while ((p = *pp) != NULL) {
2806 if (p->board == board) {
2807 #ifdef DEBUG_MEMDEC
2808 cmn_err(CE_NOTE, "fhc_del_memloc: removing %d "
2809 "0x%x 0x%x", board, p->pa, p->size);
2810 #endif /* DEBUG_MEMDEC */
2811 *pp = p->next;
2812 kmem_free(p, sizeof (struct fhc_memloc));
2813 } else {
2814 pp = &(p->next);
2815 }
2816 }
2817 }
2818
2819 /*
2820 * Find a physical address range of sufficient size and return a starting PA
2821 */
2822 uint64_t
fhc_find_memloc_gap(uint_t size)2823 fhc_find_memloc_gap(uint_t size)
2824 {
2825 struct fhc_memloc *p;
2826 uint_t base_pa = 0;
2827 uint_t mask = ~(size-1);
2828
2829 ASSERT(fhc_bdlist_locked());
2830 ASSERT((size & (size-1)) == 0); /* size must be power of 2 */
2831
2832 /*
2833 * walk the list of known memlocs and measure the 'gaps'.
2834 * we will need a hole that can align the 'size' requested.
2835 * (e.g. a 256mb bank needs to be on a 256mb boundary).
2836 */
2837 for (p = fhc_base_memloc; p != NULL; p = p->next) {
2838 if (base_pa != (base_pa & mask))
2839 base_pa = (base_pa + size) & mask;
2840 if (base_pa + size <= p->pa)
2841 break;
2842 base_pa = p->pa + p->size;
2843 }
2844
2845 /*
2846 * At this point, we assume that base_pa is good enough.
2847 */
2848 ASSERT((base_pa + size) <= FHC_MEMLOC_MAX);
2849 if (base_pa != (base_pa & mask))
2850 base_pa = (base_pa + size) & mask; /* align */
2851 return ((uint64_t)base_pa << FHC_MEMLOC_SHIFT);
2852 }
2853
2854 /*
2855 * This simple function to write the MCRs can only be used when
2856 * the contents of memory are not valid as there is a bug in the AC
2857 * ASIC concerning refresh.
2858 */
2859 static void
fhc_write_mcrs(uint64_t cpa,uint64_t dpa0,uint64_t dpa1,uint64_t c,uint64_t d0,uint64_t d1)2860 fhc_write_mcrs(
2861 uint64_t cpa,
2862 uint64_t dpa0,
2863 uint64_t dpa1,
2864 uint64_t c,
2865 uint64_t d0,
2866 uint64_t d1)
2867 {
2868 stdphysio(cpa, c & ~AC_CSR_REFEN);
2869 (void) lddphysio(cpa);
2870 if (GRP_SIZE_IS_SET(d0)) {
2871 stdphysio(dpa0, d0);
2872 (void) lddphysio(dpa0);
2873 }
2874 if (GRP_SIZE_IS_SET(d1)) {
2875 stdphysio(dpa1, d1);
2876 (void) lddphysio(dpa1);
2877 }
2878 stdphysio(cpa, c);
2879 (void) lddphysio(cpa);
2880 }
2881
2882 /* compute the appropriate RASIZE for bank size */
2883 static uint_t
fhc_cvt_size(uint64_t bsz)2884 fhc_cvt_size(uint64_t bsz)
2885 {
2886 uint_t csz;
2887
2888 csz = 0;
2889 bsz /= 64;
2890 while (bsz) {
2891 csz++;
2892 bsz /= 2;
2893 }
2894 csz /= 2;
2895
2896 return (csz);
2897 }
2898
2899 void
fhc_program_memory(int board,uint64_t pa)2900 fhc_program_memory(int board, uint64_t pa)
2901 {
2902 uint64_t cpa, dpa0, dpa1;
2903 uint64_t c, d0, d1;
2904 uint64_t b0_pa, b1_pa;
2905 uint64_t memdec0, memdec1;
2906 uint_t b0_size, b1_size;
2907
2908 /* XXX gross hack to get to board via board number */
2909 cpa = 0x1c0f9000060ull + (board * 0x400000000ull);
2910 #ifdef DEBUG_MEMDEC
2911 prom_printf("cpa = 0x%llx\n", cpa);
2912 #endif /* DEBUG_MEMDEC */
2913 dpa0 = cpa + 0x10;
2914 dpa1 = cpa + 0x20;
2915
2916 /* assume size is set by connect */
2917 memdec0 = lddphysio(dpa0);
2918 #ifdef DEBUG_MEMDEC
2919 prom_printf("memdec0 = 0x%llx\n", memdec0);
2920 #endif /* DEBUG_MEMDEC */
2921 memdec1 = lddphysio(dpa1);
2922 #ifdef DEBUG_MEMDEC
2923 prom_printf("memdec1 = 0x%llx\n", memdec1);
2924 #endif /* DEBUG_MEMDEC */
2925 if (GRP_SIZE_IS_SET(memdec0)) {
2926 b0_size = GRP_SPANMB(memdec0);
2927 } else {
2928 b0_size = 0;
2929 }
2930 if (GRP_SIZE_IS_SET(memdec1)) {
2931 b1_size = GRP_SPANMB(memdec1);
2932 } else {
2933 b1_size = 0;
2934 }
2935
2936 c = lddphysio(cpa);
2937 #ifdef DEBUG_MEMDEC
2938 prom_printf("c = 0x%llx\n", c);
2939 #endif /* DEBUG_MEMDEC */
2940 if (b0_size) {
2941 b0_pa = pa;
2942 d0 = SETUP_DECODE(b0_pa, b0_size, 0, 0);
2943 d0 |= AC_MEM_VALID;
2944
2945 c &= ~0x7;
2946 c |= 0;
2947 c &= ~(0x7 << 8);
2948 c |= (fhc_cvt_size(b0_size) << 8); /* match row size */
2949 } else {
2950 d0 = memdec0;
2951 }
2952 if (b1_size) {
2953 b1_pa = pa + 0x80000000ull; /* XXX 2gb */
2954 d1 = SETUP_DECODE(b1_pa, b1_size, 0, 0);
2955 d1 |= AC_MEM_VALID;
2956
2957 c &= ~(0x7 << 3);
2958 c |= (0 << 3);
2959 c &= ~(0x7 << 11);
2960 c |= (fhc_cvt_size(b1_size) << 11); /* match row size */
2961 } else {
2962 d1 = memdec1;
2963 }
2964 #ifdef DEBUG_MEMDEC
2965 prom_printf("c 0x%llx, d0 0x%llx, d1 0x%llx\n", c, d0, d1);
2966 #endif /* DEBUG_MEMDEC */
2967 fhc_write_mcrs(cpa, dpa0, dpa1, c, d0, d1);
2968 }
2969
2970 /*
2971 * Creates a variable sized virtual kstat with a snapshot routine in order
2972 * to pass the linked list fault list up to userland. Also creates a
2973 * virtual kstat to pass up the string table for faults.
2974 */
2975 void
create_ft_kstats(int instance)2976 create_ft_kstats(int instance)
2977 {
2978 struct kstat *ksp;
2979
2980 ksp = kstat_create("unix", instance, FT_LIST_KSTAT_NAME, "misc",
2981 KSTAT_TYPE_RAW, 1, KSTAT_FLAG_VIRTUAL|KSTAT_FLAG_VAR_SIZE);
2982
2983 if (ksp != NULL) {
2984 ksp->ks_data = NULL;
2985 ksp->ks_update = ft_ks_update;
2986 ksp->ks_snapshot = ft_ks_snapshot;
2987 ksp->ks_data_size = 1;
2988 ksp->ks_lock = &ftlist_mutex;
2989 kstat_install(ksp);
2990 }
2991 }
2992
2993 /*
2994 * This routine creates a snapshot of all the fault list data. It is
2995 * called by the kstat framework when a kstat read is done.
2996 */
2997 static int
ft_ks_snapshot(struct kstat * ksp,void * buf,int rw)2998 ft_ks_snapshot(struct kstat *ksp, void *buf, int rw)
2999 {
3000 struct ft_link_list *ftlist;
3001
3002 if (rw == KSTAT_WRITE) {
3003 return (EACCES);
3004 }
3005
3006 ksp->ks_snaptime = gethrtime();
3007
3008 for (ftlist = ft_list; ftlist != NULL; ftlist = ftlist->next) {
3009 bcopy(&ftlist->f, buf, sizeof (struct ft_list));
3010 buf = ((struct ft_list *)buf) + 1;
3011 }
3012 return (0);
3013 }
3014
3015 /*
3016 * Setup the kstat data size for the kstat framework. This is used in
3017 * conjunction with the ks_snapshot routine. This routine sets the size,
3018 * the kstat framework allocates the memory, and ks_shapshot does the
3019 * data transfer.
3020 */
3021 static int
ft_ks_update(struct kstat * ksp,int rw)3022 ft_ks_update(struct kstat *ksp, int rw)
3023 {
3024 if (rw == KSTAT_WRITE) {
3025 return (EACCES);
3026 } else {
3027 if (ft_nfaults) {
3028 ksp->ks_data_size = ft_nfaults *
3029 sizeof (struct ft_list);
3030 } else {
3031 ksp->ks_data_size = 1;
3032 }
3033 }
3034
3035 return (0);
3036 }
3037
3038 /*
3039 * Power off any cpus on the board.
3040 */
3041 int
fhc_board_poweroffcpus(int board,char * errbuf,int cpu_flags)3042 fhc_board_poweroffcpus(int board, char *errbuf, int cpu_flags)
3043 {
3044 cpu_t *cpa, *cpb;
3045 enum board_type type;
3046 int error = 0;
3047
3048 ASSERT(MUTEX_HELD(&cpu_lock));
3049
3050 /*
3051 * what type of board are we dealing with?
3052 */
3053 type = fhc_bd_type(board);
3054
3055 switch (type) {
3056 case CPU_BOARD:
3057
3058 /*
3059 * the shutdown sequence will be:
3060 *
3061 * idle both cpus then shut them off.
3062 * it looks like the hardware gets corrupted if one
3063 * cpu is busy while the other is shutting down...
3064 */
3065
3066 if ((cpa = cpu_get(FHC_BOARD2CPU_A(board))) != NULL &&
3067 cpu_is_active(cpa)) {
3068 if (!cpu_intr_on(cpa)) {
3069 cpu_intr_enable(cpa);
3070 }
3071 if ((error = cpu_offline(cpa, cpu_flags)) != 0) {
3072 cmn_err(CE_WARN,
3073 "Processor %d failed to offline.",
3074 cpa->cpu_id);
3075 if (errbuf != NULL) {
3076 (void) snprintf(errbuf, SYSC_OUTPUT_LEN,
3077 "processor %d failed to offline",
3078 cpa->cpu_id);
3079 }
3080 }
3081 }
3082
3083 if (error == 0 &&
3084 (cpb = cpu_get(FHC_BOARD2CPU_B(board))) != NULL &&
3085 cpu_is_active(cpb)) {
3086 if (!cpu_intr_on(cpb)) {
3087 cpu_intr_enable(cpb);
3088 }
3089 if ((error = cpu_offline(cpb, cpu_flags)) != 0) {
3090 cmn_err(CE_WARN,
3091 "Processor %d failed to offline.",
3092 cpb->cpu_id);
3093
3094 if (errbuf != NULL) {
3095 (void) snprintf(errbuf, SYSC_OUTPUT_LEN,
3096 "processor %d failed to offline",
3097 cpb->cpu_id);
3098 }
3099 }
3100 }
3101
3102 if (error == 0 && cpa != NULL && cpu_is_offline(cpa)) {
3103 if ((error = cpu_poweroff(cpa)) != 0) {
3104 cmn_err(CE_WARN,
3105 "Processor %d failed to power off.",
3106 cpa->cpu_id);
3107 if (errbuf != NULL) {
3108 (void) snprintf(errbuf, SYSC_OUTPUT_LEN,
3109 "processor %d failed to power off",
3110 cpa->cpu_id);
3111 }
3112 } else {
3113 cmn_err(CE_NOTE, "Processor %d powered off.",
3114 cpa->cpu_id);
3115 }
3116 }
3117
3118 if (error == 0 && cpb != NULL && cpu_is_offline(cpb)) {
3119 if ((error = cpu_poweroff(cpb)) != 0) {
3120 cmn_err(CE_WARN,
3121 "Processor %d failed to power off.",
3122 cpb->cpu_id);
3123
3124 if (errbuf != NULL) {
3125 (void) snprintf(errbuf, SYSC_OUTPUT_LEN,
3126 "processor %d failed to power off",
3127 cpb->cpu_id);
3128 }
3129 } else {
3130 cmn_err(CE_NOTE, "Processor %d powered off.",
3131 cpb->cpu_id);
3132 }
3133 }
3134
3135 /*
3136 * If all the shutdowns completed, ONLY THEN, clear the
3137 * incorrectly valid dtags...
3138 *
3139 * IMPORTANT: it is an error to read or write dtags while
3140 * they are 'active'
3141 */
3142 if (error == 0 && (cpa != NULL || cpb != NULL)) {
3143 u_longlong_t base = 0;
3144 int i;
3145 #ifdef DEBUG
3146 int nonz0 = 0;
3147 int nonz1 = 0;
3148 #endif
3149 if (cpa != NULL)
3150 base = FHC_DTAG_BASE(cpa->cpu_id);
3151 if (cpb != NULL)
3152 base = FHC_DTAG_BASE(cpb->cpu_id);
3153 ASSERT(base != 0);
3154
3155 for (i = 0; i < FHC_DTAG_SIZE; i += FHC_DTAG_SKIP) {
3156 u_longlong_t value = lddphysio(base+i);
3157 #ifdef lint
3158 value = value;
3159 #endif
3160 #ifdef DEBUG
3161 if (cpa != NULL && (value & FHC_DTAG_LOW))
3162 nonz0++;
3163 if (cpb != NULL && (value & FHC_DTAG_HIGH))
3164 nonz1++;
3165 #endif
3166 /* always clear the dtags */
3167 stdphysio(base + i, 0ull);
3168 }
3169 #ifdef DEBUG
3170 if (nonz0 || nonz1) {
3171 cmn_err(CE_NOTE, "!dtag results: "
3172 "cpua valid %d, cpub valid %d",
3173 nonz0, nonz1);
3174 }
3175 #endif
3176 }
3177
3178 break;
3179
3180 default:
3181 break;
3182 }
3183
3184 return (error);
3185 }
3186
3187 /*
3188 * platform code for shutting down cpus.
3189 */
3190 int
fhc_cpu_poweroff(struct cpu * cp)3191 fhc_cpu_poweroff(struct cpu *cp)
3192 {
3193 int board;
3194 fhc_bd_t *bd_list;
3195 int delays;
3196 extern void idle_stop_xcall(void);
3197 static void fhc_cpu_shutdown_self(void);
3198
3199 ASSERT(MUTEX_HELD(&cpu_lock));
3200 ASSERT((cp->cpu_flags & (CPU_EXISTS | CPU_OFFLINE | CPU_QUIESCED)) ==
3201 (CPU_EXISTS | CPU_OFFLINE | CPU_QUIESCED));
3202
3203 /*
3204 * Lock the board so that we can safely access the
3205 * registers. This cannot be done inside the pause_cpus().
3206 */
3207 board = FHC_CPU2BOARD(cp->cpu_id);
3208 bd_list = fhc_bdlist_lock(board);
3209 ASSERT(fhc_bd_valid(board) && (bd_list->sc.type == CPU_BOARD));
3210
3211 /*
3212 * Capture all CPUs (except for detaching proc) to prevent
3213 * crosscalls to the detaching proc until it has cleared its
3214 * bit in cpu_ready_set.
3215 *
3216 * The CPU's remain paused and the prom_mutex is known to be free.
3217 * This prevents the x-trap victim from blocking when doing prom
3218 * IEEE-1275 calls at a high PIL level.
3219 */
3220 promsafe_pause_cpus();
3221
3222 /*
3223 * Quiesce interrupts on the target CPU. We do this by setting
3224 * the CPU 'not ready'- (i.e. removing the CPU from cpu_ready_set) to
3225 * prevent it from receiving cross calls and cross traps.
3226 * This prevents the processor from receiving any new soft interrupts.
3227 */
3228 mp_cpu_quiesce(cp);
3229
3230 xt_one_unchecked(cp->cpu_id, (xcfunc_t *)idle_stop_xcall,
3231 (uint64_t)fhc_cpu_shutdown_self, (uint64_t)NULL);
3232
3233 /*
3234 * Wait for slave cpu to shutdown.
3235 * Sense this by watching the hardware EPDx bit.
3236 */
3237 for (delays = FHC_SHUTDOWN_WAIT_MSEC; delays != 0; delays--) {
3238 uint_t temp;
3239
3240 DELAY(1000);
3241
3242 /* get the current cpu power status */
3243 temp = *bd_list->softsp->ctrl;
3244
3245 /* has the cpu actually signalled shutdown? */
3246 if (FHC_CPU_IS_A(cp->cpu_id)) {
3247 if (temp & FHC_EPDA_OFF)
3248 break;
3249 } else {
3250 if (temp & FHC_EPDB_OFF)
3251 break;
3252 }
3253 }
3254
3255 start_cpus();
3256
3257 fhc_bdlist_unlock();
3258
3259 /* A timeout means we've lost control of the cpu. */
3260 if (delays == 0)
3261 panic("Processor %d failed during shutdown", cp->cpu_id);
3262
3263 return (0);
3264 }
3265
3266 /*
3267 * shutdown_self
3268 * slave side shutdown. clean up and execute the shutdown sequence.
3269 */
3270 static void
fhc_cpu_shutdown_self(void)3271 fhc_cpu_shutdown_self(void)
3272 {
3273 extern void flush_windows(void);
3274 static void os_completes_shutdown(void);
3275
3276 flush_windows();
3277
3278 ASSERT(CPU->cpu_intr_actv == 0);
3279 ASSERT(CPU->cpu_thread == CPU->cpu_idle_thread ||
3280 CPU->cpu_thread == CPU->cpu_startup_thread);
3281
3282 CPU->cpu_flags = CPU_POWEROFF | CPU_OFFLINE | CPU_QUIESCED;
3283
3284 (void) prom_sunfire_cpu_off(); /* inform Ultra Enterprise prom */
3285
3286 os_completes_shutdown();
3287
3288 panic("fhc_cpu_shutdown_self: cannot return");
3289 /*NOTREACHED*/
3290 }
3291
3292 /*
3293 * Warm start CPU.
3294 */
3295 static int
fhc_cpu_start(struct cpu * cp)3296 fhc_cpu_start(struct cpu *cp)
3297 {
3298 int rv;
3299 int cpuid = cp->cpu_id;
3300 pnode_t nodeid;
3301 extern void restart_other_cpu(int);
3302
3303 ASSERT(MUTEX_HELD(&cpu_lock));
3304
3305 /* power on cpu */
3306 nodeid = cpunodes[cpuid].nodeid;
3307 ASSERT(nodeid != (pnode_t)0);
3308 rv = prom_wakeupcpu(nodeid);
3309 if (rv != 0) {
3310 cmn_err(CE_WARN, "Processor %d failed to power on.", cpuid);
3311 return (EBUSY);
3312 }
3313
3314 cp->cpu_flags &= ~CPU_POWEROFF;
3315
3316 /*
3317 * NOTE: restart_other_cpu pauses cpus during the slave cpu start.
3318 * This helps to quiesce the bus traffic a bit which makes
3319 * the tick sync routine in the prom more robust.
3320 */
3321 restart_other_cpu(cpuid);
3322
3323 return (0);
3324 }
3325
3326 /*
3327 * Power on CPU.
3328 */
3329 int
fhc_cpu_poweron(struct cpu * cp)3330 fhc_cpu_poweron(struct cpu *cp)
3331 {
3332 fhc_bd_t *bd_list;
3333 enum temp_state state;
3334 int board;
3335 int status;
3336 int status_other;
3337 struct cpu *cp_other;
3338
3339 ASSERT(MUTEX_HELD(&cpu_lock));
3340 ASSERT(cpu_is_poweredoff(cp));
3341
3342 /* do not power on overtemperature cpu */
3343 board = FHC_CPU2BOARD(cp->cpu_id);
3344 bd_list = fhc_bdlist_lock(board);
3345
3346 ASSERT(bd_list != NULL);
3347 ASSERT(bd_list->sc.type == CPU_BOARD);
3348 ASSERT(bd_list->dev_softsp != NULL);
3349
3350 state = ((struct environ_soft_state *)
3351 bd_list->dev_softsp)->tempstat.state;
3352
3353 fhc_bdlist_unlock();
3354 if ((state == TEMP_WARN) || (state == TEMP_DANGER))
3355 return (EBUSY);
3356
3357 status = fhc_cpu_start(cp);
3358
3359 /* policy for dual cpu boards */
3360
3361 if ((status == 0) &&
3362 ((cp_other = cpu_get(FHC_OTHER_CPU_ID(cp->cpu_id))) != NULL)) {
3363 /*
3364 * Do not leave board's other cpu idling in the prom.
3365 * Start the other cpu and set its state to P_OFFLINE.
3366 */
3367 status_other = fhc_cpu_start(cp_other);
3368 if (status_other != 0) {
3369 panic("fhc: failed to start second CPU"
3370 " in pair %d & %d, error %d",
3371 cp->cpu_id, cp_other->cpu_id, status_other);
3372 }
3373 }
3374
3375 return (status);
3376 }
3377
3378 /*
3379 * complete the shutdown sequence in case the firmware doesn't.
3380 *
3381 * If the firmware returns, then complete the shutdown code.
3382 * (sunfire firmware presently only updates its status. the
3383 * OS must flush the D-tags and execute the shutdown instruction.)
3384 */
3385 static void
os_completes_shutdown(void)3386 os_completes_shutdown(void)
3387 {
3388 pfn_t pfn;
3389 tte_t tte;
3390 volatile uint_t *src;
3391 volatile uint_t *dst;
3392 caddr_t copy_addr;
3393 extern void fhc_shutdown_asm(u_longlong_t, int);
3394 extern void fhc_shutdown_asm_end(void);
3395
3396 copy_addr = shutdown_va + FHC_SRAM_OS_OFFSET;
3397
3398 /* compute sram global address for this operation */
3399 pfn = FHC_LOCAL_OS_PAGEBASE >> MMU_PAGESHIFT;
3400
3401 /* force load i and d translations */
3402 tte.tte_inthi = TTE_VALID_INT | TTE_SZ_INT(TTE8K) |
3403 TTE_PFN_INTHI(pfn);
3404 tte.tte_intlo = TTE_PFN_INTLO(pfn) |
3405 TTE_HWWR_INT | TTE_PRIV_INT | TTE_LCK_INT; /* un$ */
3406 sfmmu_dtlb_ld_kva(shutdown_va, &tte); /* load dtlb */
3407 sfmmu_itlb_ld_kva(shutdown_va, &tte); /* load itlb */
3408
3409 /*
3410 * copy the special shutdown function to sram
3411 * (this is a special integer copy that synchronizes with localspace
3412 * accesses. we need special throttling to ensure copy integrity)
3413 */
3414 for (src = (uint_t *)fhc_shutdown_asm, dst = (uint_t *)copy_addr;
3415 src < (uint_t *)fhc_shutdown_asm_end;
3416 src++, dst++) {
3417 volatile uint_t dummy;
3418
3419 *dst = *src;
3420 /*
3421 * ensure non corrupting single write operations to
3422 * localspace sram by interleaving reads with writes.
3423 */
3424 dummy = *dst;
3425 #ifdef lint
3426 dummy = dummy;
3427 #endif
3428 }
3429
3430 /*
3431 * Call the shutdown sequencer.
3432 * NOTE: the base flush address must be unique for each MID.
3433 */
3434 ((void (*)(u_longlong_t, int))copy_addr)(
3435 FHC_BASE_NOMEM + CPU->cpu_id * FHC_MAX_ECACHE_SIZE,
3436 cpunodes[CPU->cpu_id].ecache_size);
3437 }
3438
3439 enum temp_state
fhc_env_temp_state(int board)3440 fhc_env_temp_state(int board)
3441 {
3442 fhc_bd_t *bdp;
3443 struct environ_soft_state *envp;
3444
3445 ASSERT(fhc_bd_valid(board));
3446
3447 bdp = fhc_bd(board);
3448
3449 /*
3450 * Due to asynchronous attach of environ, environ may
3451 * not be attached by the time we start calling this routine
3452 * to check the temperature state. Environ not attaching is
3453 * pathological so this will only cover the time between
3454 * board connect and environ attach.
3455 */
3456 if (!bdp->dev_softsp) {
3457 return (TEMP_OK);
3458 }
3459 envp = (struct environ_soft_state *)bdp->dev_softsp;
3460
3461 return (envp->tempstat.state);
3462 }
3463
3464 static void
fhc_tod_fault(enum tod_fault_type tod_bad)3465 fhc_tod_fault(enum tod_fault_type tod_bad)
3466 {
3467 int board_num = 0;
3468 enum ft_class class = FT_SYSTEM;
3469 uint64_t addr;
3470
3471 addr = (va_to_pa((void *)v_eeprom_addr)) >> BOARD_PHYADDR_SHIFT;
3472
3473 if ((addr & CLOCKBOARD_PHYADDR_BITS) != CLOCKBOARD_PHYADDR_BITS) {
3474 /* if tod is not on clock board, */
3475 /* it'd be on one of io boards */
3476 board_num = (addr >> IO_BOARD_NUMBER_SHIFT)
3477 & IO_BOARD_NUMBER_MASK;
3478 class = FT_BOARD;
3479 }
3480
3481 switch (tod_bad) {
3482 case TOD_NOFAULT:
3483 clear_fault(board_num, FT_TODFAULT, class);
3484 break;
3485 case TOD_REVERSED:
3486 case TOD_STALLED:
3487 case TOD_JUMPED:
3488 case TOD_RATECHANGED:
3489 reg_fault(board_num, FT_TODFAULT, class);
3490 break;
3491 default:
3492 break;
3493 }
3494 }
3495