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