Print this page
XXXX introduce drv_sectohz
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/sun4u/sunfire/io/sysctrl.c
+++ new/usr/src/uts/sun4u/sunfire/io/sysctrl.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 * Copyright (c) 2011 Bayard G. Bell. All rights reserved.
26 26 */
27 27
28 28
29 29 #include <sys/types.h>
30 30 #include <sys/conf.h>
31 31 #include <sys/ddi.h>
32 32 #include <sys/sunddi.h>
33 33 #include <sys/ddi_impldefs.h>
34 34 #include <sys/sunndi.h>
35 35 #include <sys/ndi_impldefs.h>
36 36 #include <sys/obpdefs.h>
37 37 #include <sys/cmn_err.h>
38 38 #include <sys/errno.h>
39 39 #include <sys/kmem.h>
40 40 #include <sys/debug.h>
41 41 #include <sys/sysmacros.h>
42 42 #include <sys/ivintr.h>
43 43 #include <sys/autoconf.h>
44 44 #include <sys/intreg.h>
45 45 #include <sys/proc.h>
46 46 #include <sys/modctl.h>
47 47 #include <sys/callb.h>
48 48 #include <sys/file.h>
49 49 #include <sys/open.h>
50 50 #include <sys/stat.h>
51 51 #include <sys/fhc.h>
52 52 #include <sys/sysctrl.h>
53 53 #include <sys/jtag.h>
54 54 #include <sys/ac.h>
55 55 #include <sys/simmstat.h>
56 56 #include <sys/clock.h>
57 57 #include <sys/promif.h>
58 58 #include <sys/promimpl.h>
59 59 #include <sys/sunndi.h>
60 60 #include <sys/machsystm.h>
61 61
62 62 /* Useful debugging Stuff */
63 63 #ifdef DEBUG
64 64 int sysc_debug_info = 1;
65 65 int sysc_debug_print_level = 0;
66 66 #endif
67 67
68 68 /*
69 69 * Function prototypes
70 70 */
71 71 static int sysctrl_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
72 72 void **result);
73 73
74 74 static int sysctrl_attach(dev_info_t *devi, ddi_attach_cmd_t cmd);
75 75
76 76 static int sysctrl_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
77 77
78 78 static int sysctrl_open(dev_t *, int, int, cred_t *);
79 79
80 80 static int sysctrl_close(dev_t, int, int, cred_t *);
81 81
82 82 static int sysctrl_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
83 83
84 84 static uint_t system_high_handler(caddr_t arg);
85 85
86 86 static uint_t spur_delay(caddr_t arg);
87 87
88 88 static void spur_retry(void *);
89 89
90 90 static uint_t spur_reenable(caddr_t arg);
91 91
92 92 static void spur_long_timeout(void *);
93 93
94 94 static uint_t spur_clear_count(caddr_t arg);
95 95
96 96 static uint_t ac_fail_handler(caddr_t arg);
97 97
98 98 static void ac_fail_retry(void *);
99 99
100 100 static uint_t ac_fail_reenable(caddr_t arg);
101 101
102 102 static uint_t ps_fail_int_handler(caddr_t arg);
103 103
104 104 static uint_t ps_fail_poll_handler(caddr_t arg);
105 105
106 106 static uint_t ps_fail_handler(struct sysctrl_soft_state *softsp, int fromint);
107 107
108 108 enum power_state compute_power_state(struct sysctrl_soft_state *softsp,
109 109 int plus_load);
110 110
111 111 static void ps_log_state_change(struct sysctrl_soft_state *softsp,
112 112 int index, int present);
113 113
114 114 static void ps_log_pres_change(struct sysctrl_soft_state *softsp,
115 115 int index, int present);
116 116
117 117 static void ps_fail_retry(void *);
118 118
119 119 static uint_t pps_fanfail_handler(caddr_t arg);
120 120
121 121 static void pps_fanfail_retry(void *);
122 122
123 123 static uint_t pps_fanfail_reenable(caddr_t arg);
124 124
125 125 static void pps_fan_poll(void *);
126 126
127 127 static void pps_fan_state_change(struct sysctrl_soft_state *softsp,
128 128 int index, int fan_ok);
129 129
130 130 static uint_t bd_insert_handler(caddr_t arg);
131 131
132 132 static void bd_insert_timeout(void *);
133 133
134 134 static void bd_remove_timeout(void *);
135 135
136 136 static uint_t bd_insert_normal(caddr_t arg);
137 137
138 138 static void sysctrl_add_kstats(struct sysctrl_soft_state *softsp);
139 139
140 140 static int sysctrl_kstat_update(kstat_t *ksp, int rw);
141 141
142 142 static int psstat_kstat_update(kstat_t *, int);
143 143
144 144 static void init_remote_console_uart(struct sysctrl_soft_state *);
145 145
146 146 static void blink_led_timeout(void *);
147 147
148 148 static uint_t blink_led_handler(caddr_t arg);
149 149
150 150 static void sysctrl_thread_wakeup(void *type);
151 151
152 152 static void sysctrl_overtemp_poll(void);
153 153
154 154 static void sysctrl_keyswitch_poll(void);
155 155
156 156 static void update_key_state(struct sysctrl_soft_state *);
157 157
158 158 static void sysctrl_abort_seq_handler(char *msg);
159 159
160 160 static void nvram_update_powerfail(struct sysctrl_soft_state *softsp);
161 161
162 162 static void toggle_board_green_leds(int);
163 163
164 164 void bd_remove_poll(struct sysctrl_soft_state *);
165 165
166 166 static void sysc_slot_info(int nslots, int *start, int *limit, int *incr);
167 167
168 168 extern void sysc_board_connect_supported_init(void);
169 169
170 170 static void rcons_reinit(struct sysctrl_soft_state *softsp);
171 171
172 172 /*
173 173 * Configuration data structures
174 174 */
175 175 static struct cb_ops sysctrl_cb_ops = {
176 176 sysctrl_open, /* open */
177 177 sysctrl_close, /* close */
178 178 nulldev, /* strategy */
179 179 nulldev, /* print */
180 180 nulldev, /* dump */
181 181 nulldev, /* read */
182 182 nulldev, /* write */
183 183 sysctrl_ioctl, /* ioctl */
184 184 nodev, /* devmap */
185 185 nodev, /* mmap */
186 186 nodev, /* segmap */
187 187 nochpoll, /* poll */
188 188 ddi_prop_op, /* cb_prop_op */
189 189 0, /* streamtab */
190 190 D_MP|D_NEW, /* Driver compatibility flag */
191 191 CB_REV, /* rev */
192 192 nodev, /* cb_aread */
193 193 nodev /* cb_awrite */
194 194 };
195 195
196 196 static struct dev_ops sysctrl_ops = {
197 197 DEVO_REV, /* devo_rev */
198 198 0, /* refcnt */
199 199 sysctrl_info, /* getinfo */
200 200 nulldev, /* identify */
201 201 nulldev, /* probe */
202 202 sysctrl_attach, /* attach */
203 203 sysctrl_detach, /* detach */
204 204 nulldev, /* reset */
205 205 &sysctrl_cb_ops, /* cb_ops */
206 206 (struct bus_ops *)0, /* bus_ops */
207 207 nulldev, /* power */
208 208 ddi_quiesce_not_supported, /* devo_quiesce */
209 209 };
210 210
211 211 void *sysctrlp; /* sysctrl soft state hook */
212 212
213 213 /* # of ticks to silence spurious interrupts */
214 214 static clock_t spur_timeout_hz;
215 215
216 216 /* # of ticks to count spurious interrupts to print message */
217 217 static clock_t spur_long_timeout_hz;
218 218
219 219 /* # of ticks between AC failure polling */
220 220 static clock_t ac_timeout_hz;
221 221
222 222 /* # of ticks between Power Supply Failure polling */
223 223 static clock_t ps_fail_timeout_hz;
224 224
225 225 /*
226 226 * # of ticks between Peripheral Power Supply failure polling
227 227 * (used both for interrupt retry timeout and polling function)
228 228 */
229 229 static clock_t pps_fan_timeout_hz;
230 230
231 231 /* # of ticks delay after board insert interrupt */
232 232 static clock_t bd_insert_delay_hz;
233 233
234 234 /* # of secs to wait before restarting poll if we cannot clear interrupts */
235 235 static clock_t bd_insert_retry_hz;
236 236
237 237 /* # of secs between Board Removal polling */
238 238 static clock_t bd_remove_timeout_hz;
239 239
240 240 /* # of secs between toggle of OS LED */
241 241 static clock_t blink_led_timeout_hz;
242 242
243 243 /* overtemp polling routine timeout delay */
244 244 static clock_t overtemp_timeout_hz;
245 245
246 246 /* key switch polling routine timeout delay */
247 247 static clock_t keyswitch_timeout_hz;
248 248
249 249 /* Specify which system interrupt condition to monitor */
250 250 int enable_sys_interrupt = SYS_AC_PWR_FAIL_EN | SYS_PPS_FAN_FAIL_EN |
251 251 SYS_PS_FAIL_EN | SYS_SBRD_PRES_EN;
252 252
253 253 /* Should the overtemp_poll thread be running? */
254 254 static int sysctrl_do_overtemp_thread = 1;
255 255
256 256 /* Should the keyswitch_poll thread be running? */
257 257 static int sysctrl_do_keyswitch_thread = 1;
258 258
259 259 /*
260 260 * This timeout ID is for board remove polling routine. It is
261 261 * protected by the fhc_bdlist mutex.
262 262 * XXX - This will not work for wildfire. A different scheme must be
263 263 * used since there will be multiple sysctrl nodes, each with its
264 264 * own list of hotplugged boards to scan.
265 265 */
266 266 static timeout_id_t bd_remove_to_id = 0;
267 267
268 268 /*
269 269 * If this is set, the system will not shutdown when insufficient power
270 270 * condition persists.
271 271 */
272 272 int disable_insufficient_power_reboot = 0;
273 273
274 274 /*
275 275 * Set this to enable suspend/resume
276 276 */
277 277 int sysctrl_enable_detach_suspend = 0;
278 278
279 279 /*
280 280 * Set this to reflect the OBP initialized HOTPLUG_DISABLED_PROPERTY and
281 281 * during dynamic detection
282 282 */
283 283 int sysctrl_hotplug_disabled = FALSE;
284 284
285 285 /* Indicates whether or not the overtemp thread has been started */
286 286 static int sysctrl_overtemp_thread_started = 0;
287 287
288 288 /* Indicates whether or not the key switch thread has been started */
289 289 static int sysctrl_keyswitch_thread_started = 0;
290 290
291 291 /* *Mutex used to protect the soft state list */
292 292 static kmutex_t sslist_mutex;
293 293
294 294 /* The CV is used to wakeup the overtemp thread when needed. */
295 295 static kcondvar_t overtemp_cv;
296 296
297 297 /* The CV is used to wakeup the key switch thread when needed. */
298 298 static kcondvar_t keyswitch_cv;
299 299
300 300 /* This mutex is used to protect the sysctrl_ddi_branch_init variable */
301 301 static kmutex_t sysctrl_branch_mutex;
302 302
303 303 /*
304 304 * This variable is set after all existing branches in the system have
305 305 * been discovered and held via e_ddi_branch_hold(). This happens on
306 306 * first open() of any sysctrl minor node.
307 307 */
308 308 static int sysctrl_ddi_branch_init;
309 309
310 310 /*
311 311 * Linked list of all syctrl soft state structures.
312 312 * Used for polling sysctrl state changes, i.e. temperature.
313 313 */
314 314 struct sysctrl_soft_state *sys_list = NULL;
315 315
316 316 extern struct mod_ops mod_driverops;
317 317
318 318 static struct modldrv modldrv = {
319 319 &mod_driverops, /* Type of module. This one is a driver */
320 320 "Clock Board", /* name of module */
321 321 &sysctrl_ops, /* driver ops */
322 322 };
323 323
324 324 static struct modlinkage modlinkage = {
325 325 MODREV_1, /* rev */
326 326 (void *)&modldrv,
327 327 NULL
328 328 };
329 329
330 330 /*
331 331 * These are the module initialization routines.
332 332 */
333 333
334 334 int
335 335 _init(void)
336 336 {
337 337 int error;
338 338
339 339 if ((error = ddi_soft_state_init(&sysctrlp,
340 340 sizeof (struct sysctrl_soft_state), 1)) != 0)
341 341 return (error);
342 342
343 343 error = mod_install(&modlinkage);
344 344 if (error != 0) {
345 345 ddi_soft_state_fini(&sysctrlp);
346 346 return (error);
347 347 }
348 348
349 349 mutex_init(&sysctrl_branch_mutex, NULL, MUTEX_DRIVER, NULL);
350 350
351 351 return (0);
352 352 }
353 353
354 354 int
355 355 _fini(void)
356 356 {
357 357 int error;
358 358
359 359 if ((error = mod_remove(&modlinkage)) != 0)
360 360 return (error);
361 361
362 362 ddi_soft_state_fini(&sysctrlp);
363 363
364 364 mutex_destroy(&sysctrl_branch_mutex);
365 365
366 366 return (0);
367 367 }
368 368
369 369 int
370 370 _info(struct modinfo *modinfop)
371 371 {
372 372 return (mod_info(&modlinkage, modinfop));
373 373 }
374 374
375 375 /* ARGSUSED */
376 376 static int
377 377 sysctrl_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
378 378 {
379 379 dev_t dev;
380 380 int instance;
381 381
382 382 if (infocmd == DDI_INFO_DEVT2INSTANCE) {
383 383 dev = (dev_t)arg;
384 384 instance = GETINSTANCE(dev);
385 385 *result = (void *)(uintptr_t)instance;
386 386 return (DDI_SUCCESS);
387 387 }
388 388 return (DDI_FAILURE);
389 389 }
390 390
391 391 static int
392 392 sysctrl_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
393 393 {
394 394 struct sysctrl_soft_state *softsp;
395 395 int instance;
396 396 uchar_t tmp_reg;
397 397 dev_info_t *dip;
398 398 char *propval;
399 399 int proplen;
400 400 int slot_num;
401 401 int start; /* start index for scan loop */
402 402 int limit; /* board number limit for scan loop */
403 403 int incr; /* amount to incr each pass thru loop */
404 404 void set_clockbrd_info(void);
405 405
406 406
407 407 switch (cmd) {
408 408 case DDI_ATTACH:
409 409 break;
410 410
411 411 case DDI_RESUME:
412 412 /* XXX see sysctrl:DDI_SUSPEND for special h/w treatment */
413 413 return (DDI_SUCCESS);
414 414
415 415 default:
416 416 return (DDI_FAILURE);
417 417 }
418 418
419 419 instance = ddi_get_instance(devi);
420 420
421 421 if (ddi_soft_state_zalloc(sysctrlp, instance) != DDI_SUCCESS)
422 422 return (DDI_FAILURE);
423 423
424 424 softsp = GETSOFTC(instance);
425 425
426 426 /* Set the dip in the soft state */
427 427 softsp->dip = devi;
428 428
429 429 /* Set up the parent dip */
430 430 softsp->pdip = ddi_get_parent(softsp->dip);
431 431
432 432 DPRINTF(SYSCTRL_ATTACH_DEBUG, ("sysctrl: devi= 0x%p\n, softsp=0x%p\n",
433 433 (void *)devi, (void *)softsp));
434 434
↓ open down ↓ |
434 lines elided |
↑ open up ↑ |
435 435 /* First set all of the timeout values */
436 436 spur_timeout_hz = drv_usectohz(SPUR_TIMEOUT_USEC);
437 437 spur_long_timeout_hz = drv_usectohz(SPUR_LONG_TIMEOUT_USEC);
438 438 ac_timeout_hz = drv_usectohz(AC_TIMEOUT_USEC);
439 439 ps_fail_timeout_hz = drv_usectohz(PS_FAIL_TIMEOUT_USEC);
440 440 pps_fan_timeout_hz = drv_usectohz(PPS_FAN_TIMEOUT_USEC);
441 441 bd_insert_delay_hz = drv_usectohz(BRD_INSERT_DELAY_USEC);
442 442 bd_insert_retry_hz = drv_usectohz(BRD_INSERT_RETRY_USEC);
443 443 bd_remove_timeout_hz = drv_usectohz(BRD_REMOVE_TIMEOUT_USEC);
444 444 blink_led_timeout_hz = drv_usectohz(BLINK_LED_TIMEOUT_USEC);
445 - overtemp_timeout_hz = drv_usectohz(OVERTEMP_TIMEOUT_SEC * MICROSEC);
445 + overtemp_timeout_hz = drv_sectohz(OVERTEMP_TIMEOUT_SEC);
446 446 keyswitch_timeout_hz = drv_usectohz(KEYSWITCH_TIMEOUT_USEC);
447 447
448 448 /*
449 449 * Map in the registers sets that OBP hands us. According
450 450 * to the sun4u device tree spec., the register sets are as
451 451 * follows:
452 452 *
453 453 * 0 Clock Frequency Registers (contains the bit
454 454 * for enabling the remote console reset)
455 455 * 1 Misc (has all the registers that we need
456 456 * 2 Clock Version Register
457 457 */
458 458 if (ddi_map_regs(softsp->dip, 0,
459 459 (caddr_t *)&softsp->clk_freq1, 0, 0)) {
460 460 cmn_err(CE_WARN, "sysctrl%d: unable to map clock frequency "
461 461 "registers", instance);
462 462 goto bad0;
463 463 }
464 464
465 465 if (ddi_map_regs(softsp->dip, 1,
466 466 (caddr_t *)&softsp->csr, 0, 0)) {
467 467 cmn_err(CE_WARN, "sysctrl%d: unable to map internal"
468 468 "registers", instance);
469 469 goto bad1;
470 470 }
471 471
472 472 /*
473 473 * There is a new register for newer vintage clock board nodes,
474 474 * OBP register set 2 in the clock board node.
475 475 *
476 476 */
477 477 (void) ddi_map_regs(softsp->dip, 2, (caddr_t *)&softsp->clk_ver, 0, 0);
478 478
479 479 /*
480 480 * Fill in the virtual addresses of the registers in the
481 481 * sysctrl_soft_state structure. We do not want to calculate
482 482 * them on the fly. This way we waste a little memory, but
483 483 * avoid bugs down the road.
484 484 */
485 485 softsp->clk_freq2 = (uchar_t *)((caddr_t)softsp->clk_freq1 +
486 486 SYS_OFF_CLK_FREQ2);
487 487
488 488 softsp->status1 = (uchar_t *)((caddr_t)softsp->csr +
489 489 SYS_OFF_STAT1);
490 490
491 491 softsp->status2 = (uchar_t *)((caddr_t)softsp->csr +
492 492 SYS_OFF_STAT2);
493 493
494 494 softsp->ps_stat = (uchar_t *)((caddr_t)softsp->csr +
495 495 SYS_OFF_PSSTAT);
496 496
497 497 softsp->ps_pres = (uchar_t *)((caddr_t)softsp->csr +
498 498 SYS_OFF_PSPRES);
499 499
500 500 softsp->pppsr = (uchar_t *)((caddr_t)softsp->csr +
501 501 SYS_OFF_PPPSR);
502 502
503 503 softsp->temp_reg = (uchar_t *)((caddr_t)softsp->csr +
504 504 SYS_OFF_TEMP);
505 505
506 506 set_clockbrd_info();
507 507
508 508 /*
509 509 * Enable the hardware watchdog gate on the clock board if
510 510 * map_wellknown has detected that watchdog timer is available
511 511 * and user wants it to be enabled.
512 512 */
513 513 if (watchdog_available && watchdog_enable)
514 514 *(softsp->clk_freq2) |= TOD_RESET_EN;
515 515 else
516 516 *(softsp->clk_freq2) &= ~TOD_RESET_EN;
517 517
518 518 /* Check for inherited faults from the PROM. */
519 519 if (*softsp->csr & SYS_LED_MID) {
520 520 reg_fault(0, FT_PROM, FT_SYSTEM);
521 521 }
522 522
523 523 /*
524 524 * calculate and cache the number of slots on this system
525 525 */
526 526 switch (SYS_TYPE(*softsp->status1)) {
527 527 case SYS_16_SLOT:
528 528 softsp->nslots = 16;
529 529 break;
530 530
531 531 case SYS_8_SLOT:
532 532 softsp->nslots = 8;
533 533 break;
534 534
535 535 case SYS_4_SLOT:
536 536 /* check the clk_version register - if the ptr is valid */
537 537 if ((softsp->clk_ver != NULL) &&
538 538 (SYS_TYPE2(*softsp->clk_ver) == SYS_PLUS_SYSTEM)) {
539 539 softsp->nslots = 5;
540 540 } else {
541 541 softsp->nslots = 4;
542 542 }
543 543 break;
544 544
545 545 case SYS_TESTBED:
546 546 default:
547 547 softsp->nslots = 0;
548 548 break;
549 549 }
550 550
551 551
552 552 /* create the fault list kstat */
553 553 create_ft_kstats(instance);
554 554
555 555 /*
556 556 * Do a priming read on the ADC, and throw away the first value
557 557 * read. This is a feature of the ADC hardware. After a power cycle
558 558 * it does not contains valid data until a read occurs.
559 559 */
560 560 tmp_reg = *(softsp->temp_reg);
561 561
562 562 /* Wait 30 usec for ADC hardware to stabilize. */
563 563 DELAY(30);
564 564
565 565 /* shut off all interrupt sources */
566 566 *(softsp->csr) &= ~(SYS_PPS_FAN_FAIL_EN | SYS_PS_FAIL_EN |
567 567 SYS_AC_PWR_FAIL_EN | SYS_SBRD_PRES_EN);
568 568 tmp_reg = *(softsp->csr);
569 569 #ifdef lint
570 570 tmp_reg = tmp_reg;
571 571 #endif
572 572
573 573 /*
574 574 * Now register our high interrupt with the system.
575 575 */
576 576 if (ddi_add_intr(devi, 0, &softsp->iblock,
577 577 &softsp->idevice, (uint_t (*)(caddr_t))nulldev, NULL) !=
578 578 DDI_SUCCESS)
579 579 goto bad2;
580 580
581 581 mutex_init(&softsp->csr_mutex, NULL, MUTEX_DRIVER,
582 582 (void *)softsp->iblock);
583 583
584 584 ddi_remove_intr(devi, 0, softsp->iblock);
585 585
586 586 if (ddi_add_intr(devi, 0, &softsp->iblock,
587 587 &softsp->idevice, system_high_handler, (caddr_t)softsp) !=
588 588 DDI_SUCCESS)
589 589 goto bad3;
590 590
591 591 if (ddi_add_softintr(devi, DDI_SOFTINT_LOW, &softsp->spur_id,
592 592 &softsp->spur_int_c, NULL, spur_delay, (caddr_t)softsp) !=
593 593 DDI_SUCCESS)
594 594 goto bad4;
595 595
596 596 mutex_init(&softsp->spur_int_lock, NULL, MUTEX_DRIVER,
597 597 (void *)softsp->spur_int_c);
598 598
599 599
600 600 if (ddi_add_softintr(devi, DDI_SOFTINT_LOW, &softsp->spur_high_id,
601 601 NULL, NULL, spur_reenable, (caddr_t)softsp) != DDI_SUCCESS)
602 602 goto bad5;
603 603
604 604 if (ddi_add_softintr(devi, DDI_SOFTINT_LOW, &softsp->spur_long_to_id,
605 605 NULL, NULL, spur_clear_count, (caddr_t)softsp) != DDI_SUCCESS)
606 606 goto bad6;
607 607
608 608 /*
609 609 * Now register low-level ac fail handler
610 610 */
611 611 if (ddi_add_softintr(devi, DDI_SOFTINT_HIGH, &softsp->ac_fail_id,
612 612 NULL, NULL, ac_fail_handler, (caddr_t)softsp) != DDI_SUCCESS)
613 613 goto bad7;
614 614
615 615 if (ddi_add_softintr(devi, DDI_SOFTINT_LOW, &softsp->ac_fail_high_id,
616 616 NULL, NULL, ac_fail_reenable, (caddr_t)softsp) != DDI_SUCCESS)
617 617 goto bad8;
618 618
619 619 /*
620 620 * Now register low-level ps fail handler
621 621 */
622 622
623 623 if (ddi_add_softintr(devi, DDI_SOFTINT_HIGH, &softsp->ps_fail_int_id,
624 624 &softsp->ps_fail_c, NULL, ps_fail_int_handler, (caddr_t)softsp) !=
625 625 DDI_SUCCESS)
626 626 goto bad9;
627 627
628 628 mutex_init(&softsp->ps_fail_lock, NULL, MUTEX_DRIVER,
629 629 (void *)softsp->ps_fail_c);
630 630
631 631 if (ddi_add_softintr(devi, DDI_SOFTINT_LOW, &softsp->ps_fail_poll_id,
632 632 NULL, NULL, ps_fail_poll_handler, (caddr_t)softsp) !=
633 633 DDI_SUCCESS)
634 634 goto bad10;
635 635
636 636 /*
637 637 * Now register low-level pps fan fail handler
638 638 */
639 639 if (ddi_add_softintr(devi, DDI_SOFTINT_LOW, &softsp->pps_fan_id,
640 640 NULL, NULL, pps_fanfail_handler, (caddr_t)softsp) !=
641 641 DDI_SUCCESS)
642 642 goto bad11;
643 643
644 644 if (ddi_add_softintr(devi, DDI_SOFTINT_LOW, &softsp->pps_fan_high_id,
645 645 NULL, NULL, pps_fanfail_reenable, (caddr_t)softsp) !=
646 646 DDI_SUCCESS)
647 647 goto bad12;
648 648
649 649 /*
650 650 * Based upon a check for a current share backplane, advise
651 651 * that system does not support hot plug
652 652 *
653 653 */
654 654 if ((*(softsp->pppsr) & SYS_NOT_CURRENT_S) != 0) {
655 655 cmn_err(CE_NOTE, "Hot Plug not supported in this system");
656 656 sysctrl_hotplug_disabled = TRUE;
657 657 }
658 658
659 659 /*
660 660 * If the trigger circuit is busted or the NOT_BRD_PRES line
661 661 * is stuck then OBP will publish this property stating that
662 662 * hot plug is not available. If this happens we will complain
663 663 * to the console and register a system fault. We will also
664 664 * not enable the board insert interrupt for this session.
665 665 */
666 666 if (ddi_prop_op(DDI_DEV_T_ANY, softsp->dip, PROP_LEN_AND_VAL_ALLOC,
667 667 DDI_PROP_DONTPASS, HOTPLUG_DISABLED_PROPERTY,
668 668 (caddr_t)&propval, &proplen) == DDI_PROP_SUCCESS) {
669 669 cmn_err(CE_WARN, "Hot Plug Unavailable [%s]", propval);
670 670 reg_fault(0, FT_HOT_PLUG, FT_SYSTEM);
671 671 sysctrl_hotplug_disabled = TRUE;
672 672 enable_sys_interrupt &= ~SYS_SBRD_PRES_EN;
673 673 kmem_free(propval, proplen);
674 674 }
675 675
676 676 sysc_board_connect_supported_init();
677 677
678 678 fhc_bd_sc_register(sysc_policy_update, softsp);
679 679
680 680 sysc_slot_info(softsp->nslots, &start, &limit, &incr);
681 681
682 682 /* Prime the board list. */
683 683 fhc_bdlist_prime(start, limit, incr);
684 684
685 685 /*
686 686 * Set up a board remove timeout call.
687 687 */
688 688 (void) fhc_bdlist_lock(-1);
689 689
690 690 DPRINTF(SYSCTRL_ATTACH_DEBUG,
691 691 ("attach: start bd_remove_poll()..."));
692 692
693 693 bd_remove_poll(softsp);
694 694 fhc_bdlist_unlock();
695 695
696 696 /*
697 697 * Now register low-level board insert handler
698 698 */
699 699 if (ddi_add_softintr(devi, DDI_SOFTINT_LOW, &softsp->sbrd_pres_id,
700 700 NULL, NULL, bd_insert_handler, (caddr_t)softsp) != DDI_SUCCESS)
701 701 goto bad13;
702 702
703 703 if (ddi_add_softintr(devi, DDI_SOFTINT_LOW, &softsp->sbrd_gone_id,
704 704 NULL, NULL, bd_insert_normal, (caddr_t)softsp) != DDI_SUCCESS)
705 705 goto bad14;
706 706
707 707 /*
708 708 * Now register led blink handler (interrupt level)
709 709 */
710 710 if (ddi_add_softintr(devi, DDI_SOFTINT_LOW, &softsp->blink_led_id,
711 711 &softsp->sys_led_c, NULL, blink_led_handler, (caddr_t)softsp) !=
712 712 DDI_SUCCESS)
713 713 goto bad15;
714 714 mutex_init(&softsp->sys_led_lock, NULL, MUTEX_DRIVER,
715 715 (void *)softsp->sys_led_c);
716 716
717 717 /* initialize the bit field for all pps fans to assumed good */
718 718 softsp->pps_fan_saved = softsp->pps_fan_external_state =
719 719 SYS_AC_FAN_OK | SYS_KEYSW_FAN_OK;
720 720
721 721 /* prime the power supply state machines */
722 722 if (enable_sys_interrupt & SYS_PS_FAIL_EN)
723 723 ddi_trigger_softintr(softsp->ps_fail_poll_id);
724 724
725 725
726 726 /* kick off the OS led blinker */
727 727 softsp->sys_led = FALSE;
728 728 ddi_trigger_softintr(softsp->blink_led_id);
729 729
730 730 /* Now enable selected interrupt sources */
731 731 mutex_enter(&softsp->csr_mutex);
732 732 *(softsp->csr) |= enable_sys_interrupt &
733 733 (SYS_AC_PWR_FAIL_EN | SYS_PS_FAIL_EN |
734 734 SYS_PPS_FAN_FAIL_EN | SYS_SBRD_PRES_EN);
735 735 tmp_reg = *(softsp->csr);
736 736 #ifdef lint
737 737 tmp_reg = tmp_reg;
738 738 #endif
739 739 mutex_exit(&softsp->csr_mutex);
740 740
741 741 /* Initialize the temperature */
742 742 init_temp_arrays(&softsp->tempstat);
743 743
744 744 /*
745 745 * initialize key switch shadow state
746 746 */
747 747 softsp->key_shadow = KEY_BOOT;
748 748
749 749 /*
750 750 * Now add this soft state structure to the front of the linked list
751 751 * of soft state structures.
752 752 */
753 753 if (sys_list == (struct sysctrl_soft_state *)NULL) {
754 754 mutex_init(&sslist_mutex, NULL, MUTEX_DEFAULT, NULL);
755 755 }
756 756 mutex_enter(&sslist_mutex);
757 757 softsp->next = sys_list;
758 758 sys_list = softsp;
759 759 mutex_exit(&sslist_mutex);
760 760
761 761 /* Setup the kstats for this device */
762 762 sysctrl_add_kstats(softsp);
763 763
764 764 /* kick off the PPS fan poll routine */
765 765 pps_fan_poll(softsp);
766 766
767 767 if (sysctrl_overtemp_thread_started == 0) {
768 768 /*
769 769 * set up the overtemp condition variable before
770 770 * starting the thread.
771 771 */
772 772 cv_init(&overtemp_cv, NULL, CV_DRIVER, NULL);
773 773
774 774 /*
775 775 * start up the overtemp polling thread
776 776 */
777 777 (void) thread_create(NULL, 0, (void (*)())sysctrl_overtemp_poll,
778 778 NULL, 0, &p0, TS_RUN, minclsyspri);
779 779 sysctrl_overtemp_thread_started++;
780 780 }
781 781
782 782 if (sysctrl_keyswitch_thread_started == 0) {
783 783 extern void (*abort_seq_handler)();
784 784
785 785 /*
786 786 * interpose sysctrl's abort sequence handler
787 787 */
788 788 abort_seq_handler = sysctrl_abort_seq_handler;
789 789
790 790 /*
791 791 * set up the key switch condition variable before
792 792 * starting the thread
793 793 */
794 794 cv_init(&keyswitch_cv, NULL, CV_DRIVER, NULL);
795 795
796 796 /*
797 797 * start up the key switch polling thread
798 798 */
799 799 (void) thread_create(NULL, 0,
800 800 (void (*)())sysctrl_keyswitch_poll, NULL, 0, &p0,
801 801 TS_RUN, minclsyspri);
802 802 sysctrl_keyswitch_thread_started++;
803 803 }
804 804
805 805 /*
806 806 * perform initialization to allow setting of powerfail-time
807 807 */
808 808 if ((dip = ddi_find_devinfo("options", -1, 0)) == NULL)
809 809 softsp->options_nodeid = (pnode_t)NULL;
810 810 else
811 811 softsp->options_nodeid = (pnode_t)ddi_get_nodeid(dip);
812 812
813 813 DPRINTF(SYSCTRL_ATTACH_DEBUG,
814 814 ("sysctrl: Creating devices start:%d, limit:%d, incr:%d\n",
815 815 start, limit, incr));
816 816
817 817 /*
818 818 * Create minor node for each system attachment points
819 819 */
820 820 for (slot_num = start; slot_num < limit; slot_num = slot_num + incr) {
821 821 char name[30];
822 822 (void) sprintf(name, "slot%d", slot_num);
823 823 if (ddi_create_minor_node(devi, name, S_IFCHR,
824 824 (PUTINSTANCE(instance) | slot_num),
825 825 DDI_NT_ATTACHMENT_POINT, 0) == DDI_FAILURE) {
826 826 cmn_err(CE_WARN, "sysctrl%d: \"%s\" "
827 827 "ddi_create_minor_node failed",
828 828 instance, name);
829 829 goto bad16;
830 830 }
831 831 }
832 832
833 833 ddi_report_dev(devi);
834 834
835 835 /*
836 836 * Remote console is inherited from POST
837 837 */
838 838 if ((*(softsp->clk_freq2) & RCONS_UART_EN) == 0) {
839 839 softsp->enable_rcons_atboot = FALSE;
840 840 cmn_err(CE_WARN, "Remote console not active");
841 841 } else
842 842 softsp->enable_rcons_atboot = TRUE;
843 843
844 844 return (DDI_SUCCESS);
845 845
846 846 bad16:
847 847 cv_destroy(&keyswitch_cv);
848 848 cv_destroy(&overtemp_cv);
849 849 mutex_destroy(&sslist_mutex);
850 850 mutex_destroy(&softsp->sys_led_lock);
851 851 ddi_remove_softintr(softsp->blink_led_id);
852 852 bad15:
853 853 ddi_remove_softintr(softsp->sbrd_gone_id);
854 854 bad14:
855 855 ddi_remove_softintr(softsp->sbrd_pres_id);
856 856 bad13:
857 857 ddi_remove_softintr(softsp->pps_fan_high_id);
858 858 bad12:
859 859 ddi_remove_softintr(softsp->pps_fan_id);
860 860 bad11:
861 861 ddi_remove_softintr(softsp->ps_fail_poll_id);
862 862 bad10:
863 863 mutex_destroy(&softsp->ps_fail_lock);
864 864 ddi_remove_softintr(softsp->ps_fail_int_id);
865 865 bad9:
866 866 ddi_remove_softintr(softsp->ac_fail_high_id);
867 867 bad8:
868 868 ddi_remove_softintr(softsp->ac_fail_id);
869 869 bad7:
870 870 ddi_remove_softintr(softsp->spur_long_to_id);
871 871 bad6:
872 872 ddi_remove_softintr(softsp->spur_high_id);
873 873 bad5:
874 874 mutex_destroy(&softsp->spur_int_lock);
875 875 ddi_remove_softintr(softsp->spur_id);
876 876 bad4:
877 877 ddi_remove_intr(devi, 0, softsp->iblock);
878 878 bad3:
879 879 mutex_destroy(&softsp->csr_mutex);
880 880 bad2:
881 881 ddi_unmap_regs(softsp->dip, 1, (caddr_t *)&softsp->csr, 0, 0);
882 882 if (softsp->clk_ver != NULL)
883 883 ddi_unmap_regs(softsp->dip, 2, (caddr_t *)&softsp->clk_ver,
884 884 0, 0);
885 885 bad1:
886 886 ddi_unmap_regs(softsp->dip, 0, (caddr_t *)&softsp->clk_freq1, 0, 0);
887 887
888 888 bad0:
889 889 ddi_soft_state_free(sysctrlp, instance);
890 890 ddi_remove_minor_node(dip, NULL);
891 891 cmn_err(CE_WARN,
892 892 "sysctrl%d: Initialization failure. Some system level events,"
893 893 " {AC Fail, Fan Failure, PS Failure} not detected", instance);
894 894 return (DDI_FAILURE);
895 895 }
896 896
897 897 struct sysc_hold {
898 898 int start;
899 899 int limit;
900 900 int incr;
901 901 int hold;
902 902 };
903 903
904 904 static int
905 905 sysctrl_hold_rele_branches(dev_info_t *dip, void *arg)
906 906 {
907 907 int *rp, len, slot, i;
908 908 struct sysc_hold *ap = (struct sysc_hold *)arg;
909 909
910 910 /*
911 911 * For Sunfire, top nodes on board are always children of root dip
912 912 */
913 913 ASSERT(ddi_get_parent(dip) == ddi_root_node());
914 914
915 915 /*
916 916 * Skip non-PROM and "central" nodes
917 917 */
918 918 if (!ndi_dev_is_prom_node(dip) ||
919 919 strcmp(ddi_node_name(dip), "central") == 0)
920 920 return (DDI_WALK_PRUNECHILD);
921 921
922 922 /*
923 923 * Extract board # from reg property.
924 924 */
925 925 if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
926 926 DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, "reg", (caddr_t)&rp, &len)
927 927 != DDI_SUCCESS) {
928 928 DPRINTF(SYSC_DEBUG, ("devinfo node %s(%p) has no reg"
929 929 " property\n", ddi_node_name(dip), (void *)dip));
930 930 return (DDI_WALK_PRUNECHILD);
931 931 }
932 932
933 933 slot = (*rp - 0x1c0) >> 2;
934 934 kmem_free(rp, len);
935 935
936 936 ASSERT(ap->start >= 0 && ap->start < ap->limit);
937 937
938 938 for (i = ap->start; i < ap->limit; i = i + ap->incr) {
939 939 if (i == slot)
940 940 break;
941 941 }
942 942
943 943 if (i >= ap->limit) {
944 944 DPRINTF(SYSC_DEBUG, ("sysctrl_hold_rele: Invalid board # (%d)"
945 945 " for node %s(%p)\n", slot, ddi_node_name(dip),
946 946 (void *)dip));
947 947 return (DDI_WALK_PRUNECHILD);
948 948 }
949 949
950 950 if (ap->hold) {
951 951 ASSERT(!e_ddi_branch_held(dip));
952 952 e_ddi_branch_hold(dip);
953 953 } else {
954 954 ASSERT(e_ddi_branch_held(dip));
955 955 e_ddi_branch_rele(dip);
956 956 }
957 957
958 958 return (DDI_WALK_PRUNECHILD);
959 959 }
960 960
961 961 /* ARGSUSED */
962 962 static int
963 963 sysctrl_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
964 964 {
965 965 #ifdef SYSCTRL_SUPPORTS_DETACH
966 966 dev_info_t *rdip;
967 967 struct sysc_hold arg = {0};
968 968 struct sysctrl_soft_state *softsp;
969 969 #endif /* SYSCTRL_SUPPORTS_DETACH */
970 970
971 971 if (sysctrl_enable_detach_suspend == FALSE)
972 972 return (DDI_FAILURE);
973 973
974 974 switch (cmd) {
975 975 case DDI_SUSPEND:
976 976 /*
977 977 * XXX we don't presently save the state of the remote
978 978 * console because it is a constant function of POST.
979 979 * XXX we don't deal with the hardware watchdog here
980 980 * either. It should be handled in hardclk.
981 981 */
982 982 return (DDI_SUCCESS);
983 983
984 984 case DDI_DETACH:
985 985 break;
986 986 default:
987 987 return (DDI_FAILURE);
988 988 }
989 989
990 990 #ifdef SYSCTRL_SUPPORTS_DETACH
991 991
992 992 /*
993 993 * XXX If sysctrl ever supports detach, this code should be enabled
994 994 * This is only the portion of the detach code dealing with
995 995 * the DDI branch routines. Other parts of detach will need
996 996 * to be added.
997 997 */
998 998
999 999 /*
1000 1000 * Walk immediate children of root devinfo node, releasing holds
1001 1001 * on branches acquired in first sysctrl_open().
1002 1002 */
1003 1003
1004 1004 instance = ddi_get_instance(dip);
1005 1005 softsp = GETSOFTC(instance);
1006 1006
1007 1007 if (softsp == NULL) {
1008 1008 cmn_err(CE_WARN, "sysctrl%d device not attached", instance);
1009 1009 return (DDI_FAILURE);
1010 1010 }
1011 1011
1012 1012 sysc_slot_info(softsp->nslots, &arg.start, &arg.limit, &arg.incr);
1013 1013
1014 1014 arg.hold = 0;
1015 1015
1016 1016 rdip = ddi_root_node();
1017 1017
1018 1018 ndi_devi_enter(rdip, &circ);
1019 1019 ddi_walk_devs(ddi_get_child(rdip), sysctrl_hold_rele_branches, &arg);
1020 1020 ndi_devi_exit(rdip, circ);
1021 1021
1022 1022 sysctrl_ddi_branch_init = 0;
1023 1023
1024 1024 return (DDI_SUCCESS);
1025 1025 #endif /* SYSCTRL_SUPPORTS_DETACH */
1026 1026
1027 1027 return (DDI_FAILURE);
1028 1028 }
1029 1029
1030 1030 /* ARGSUSED */
1031 1031 static int
1032 1032 sysctrl_open(dev_t *devp, int flag, int otyp, cred_t *credp)
1033 1033 {
1034 1034 int instance;
1035 1035 int slot;
1036 1036 dev_t dev;
1037 1037 int circ;
1038 1038 dev_info_t *rdip;
1039 1039 struct sysc_hold arg = {0};
1040 1040 struct sysctrl_soft_state *softsp;
1041 1041
1042 1042 dev = *devp;
1043 1043
1044 1044 /*
1045 1045 * We checked against the instance softstate structure since there
1046 1046 * will only be one instance of sysctrl (clock board) in UEXX00
1047 1047 *
1048 1048 * Since we only create minor devices for existing slots on a
1049 1049 * particular system, we don't need to worry about non-exist slot.
1050 1050 */
1051 1051
1052 1052 instance = GETINSTANCE(dev);
1053 1053 slot = GETSLOT(dev);
1054 1054
1055 1055 /* Is the instance attached? */
1056 1056 if ((softsp = GETSOFTC(instance)) == NULL) {
1057 1057 cmn_err(CE_WARN, "sysctrl%d device not attached", instance);
1058 1058 return (ENXIO);
1059 1059 }
1060 1060
1061 1061 /* verify that otyp is appropriate */
1062 1062 if (otyp != OTYP_CHR) {
1063 1063 return (EINVAL);
1064 1064 }
1065 1065
1066 1066 if (!fhc_bd_valid(slot))
1067 1067 return (ENXIO);
1068 1068
1069 1069 /*
1070 1070 * On first open of a sysctrl minor walk immediate children of the
1071 1071 * devinfo root node and hold all branches of interest.
1072 1072 */
1073 1073 mutex_enter(&sysctrl_branch_mutex);
1074 1074 if (!sysctrl_ddi_branch_init) {
1075 1075
1076 1076 sysctrl_ddi_branch_init = 1;
1077 1077
1078 1078 sysc_slot_info(softsp->nslots, &arg.start, &arg.limit,
1079 1079 &arg.incr);
1080 1080 arg.hold = 1;
1081 1081
1082 1082 rdip = ddi_root_node();
1083 1083
1084 1084 ndi_devi_enter(rdip, &circ);
1085 1085 ddi_walk_devs(ddi_get_child(rdip), sysctrl_hold_rele_branches,
1086 1086 &arg);
1087 1087 ndi_devi_exit(rdip, circ);
1088 1088 }
1089 1089 mutex_exit(&sysctrl_branch_mutex);
1090 1090
1091 1091 return (DDI_SUCCESS);
1092 1092 }
1093 1093
1094 1094 /* ARGSUSED */
1095 1095 static int
1096 1096 sysctrl_close(dev_t devp, int flag, int otyp, cred_t *credp)
1097 1097 {
1098 1098 return (DDI_SUCCESS);
1099 1099 }
1100 1100
1101 1101 /*
1102 1102 * This function will acquire the lock and set the in_transition
1103 1103 * bit for the specified slot. If the slot is being used,
1104 1104 * we return FALSE; else set in_transition and return TRUE.
1105 1105 */
1106 1106 static int
1107 1107 sysc_enter_transition(int slot)
1108 1108 {
1109 1109 fhc_bd_t *list;
1110 1110 sysc_cfga_stat_t *sysc_stat_lk;
1111 1111 fhc_bd_t *glist;
1112 1112 sysc_cfga_stat_t *sysc_stat_gk;
1113 1113
1114 1114 /* mutex lock the structure */
1115 1115 list = fhc_bdlist_lock(slot);
1116 1116 if ((slot != -1) && (list == NULL)) {
1117 1117 fhc_bdlist_unlock();
1118 1118 return (FALSE);
1119 1119 }
1120 1120
1121 1121 glist = fhc_bd_clock();
1122 1122 if (slot == -1)
1123 1123 list = glist;
1124 1124
1125 1125 /* change the in_transition bit */
1126 1126 sysc_stat_lk = &list->sc;
1127 1127 sysc_stat_gk = &glist->sc;
1128 1128 if ((sysc_stat_lk->in_transition == TRUE) ||
1129 1129 (sysc_stat_gk->in_transition == TRUE)) {
1130 1130 fhc_bdlist_unlock();
1131 1131 return (FALSE);
1132 1132 } else {
1133 1133 sysc_stat_lk->in_transition = TRUE;
1134 1134 return (TRUE);
1135 1135 }
1136 1136 }
1137 1137
1138 1138 /*
1139 1139 * This function will release the lock and clear the in_transition
1140 1140 * bit for the specified slot.
1141 1141 */
1142 1142 static void
1143 1143 sysc_exit_transition(int slot)
1144 1144 {
1145 1145 fhc_bd_t *list;
1146 1146 sysc_cfga_stat_t *sysc_stat_lk;
1147 1147
1148 1148 ASSERT(fhc_bdlist_locked());
1149 1149
1150 1150 if (slot == -1)
1151 1151 list = fhc_bd_clock();
1152 1152 else
1153 1153 list = fhc_bd(slot);
1154 1154 sysc_stat_lk = &list->sc;
1155 1155 ASSERT(sysc_stat_lk->in_transition == TRUE);
1156 1156 sysc_stat_lk->in_transition = FALSE;
1157 1157 fhc_bdlist_unlock();
1158 1158 }
1159 1159
1160 1160 static int
1161 1161 sysc_pkt_init(sysc_cfga_pkt_t *pkt, intptr_t arg, int flag)
1162 1162 {
1163 1163 #ifdef _MULTI_DATAMODEL
1164 1164 if (ddi_model_convert_from(flag & FMODELS) == DDI_MODEL_ILP32) {
1165 1165 sysc_cfga_cmd32_t sysc_cmd32;
1166 1166
1167 1167 if (ddi_copyin((void *)arg, &sysc_cmd32,
1168 1168 sizeof (sysc_cfga_cmd32_t), flag) != 0) {
1169 1169 return (EFAULT);
1170 1170 }
1171 1171 pkt->cmd_cfga.force = sysc_cmd32.force;
1172 1172 pkt->cmd_cfga.test = sysc_cmd32.test;
1173 1173 pkt->cmd_cfga.arg = sysc_cmd32.arg;
1174 1174 pkt->cmd_cfga.errtype = sysc_cmd32.errtype;
1175 1175 pkt->cmd_cfga.outputstr =
1176 1176 (char *)(uintptr_t)sysc_cmd32.outputstr;
1177 1177 } else
1178 1178 #endif /* _MULTI_DATAMODEL */
1179 1179 if (ddi_copyin((void *)arg, &(pkt->cmd_cfga),
1180 1180 sizeof (sysc_cfga_cmd_t), flag) != 0) {
1181 1181 return (EFAULT);
1182 1182 }
1183 1183 pkt->errbuf = kmem_zalloc(SYSC_OUTPUT_LEN, KM_SLEEP);
1184 1184 return (0);
1185 1185 }
1186 1186
1187 1187 static int
1188 1188 sysc_pkt_fini(sysc_cfga_pkt_t *pkt, intptr_t arg, int flag)
1189 1189 {
1190 1190 int ret = TRUE;
1191 1191
1192 1192 #ifdef _MULTI_DATAMODEL
1193 1193 if (ddi_model_convert_from(flag & FMODELS) == DDI_MODEL_ILP32) {
1194 1194
1195 1195 if (ddi_copyout(&(pkt->cmd_cfga.errtype),
1196 1196 (void *)&(((sysc_cfga_cmd32_t *)arg)->errtype),
1197 1197 sizeof (sysc_err_t), flag) != 0) {
1198 1198 ret = FALSE;
1199 1199 }
1200 1200 } else
1201 1201 #endif
1202 1202 if (ddi_copyout(&(pkt->cmd_cfga.errtype),
1203 1203 (void *)&(((sysc_cfga_cmd_t *)arg)->errtype),
1204 1204 sizeof (sysc_err_t), flag) != 0) {
1205 1205 ret = FALSE;
1206 1206 }
1207 1207
1208 1208 if ((ret != FALSE) && ((pkt->cmd_cfga.outputstr != NULL) &&
1209 1209 (ddi_copyout(pkt->errbuf, pkt->cmd_cfga.outputstr,
1210 1210 SYSC_OUTPUT_LEN, flag) != 0))) {
1211 1211 ret = FALSE;
1212 1212 }
1213 1213
1214 1214 kmem_free(pkt->errbuf, SYSC_OUTPUT_LEN);
1215 1215 return (ret);
1216 1216 }
1217 1217
1218 1218 /* ARGSUSED */
1219 1219 static int
1220 1220 sysctrl_ioctl(dev_t devt, int cmd, intptr_t arg, int flag, cred_t *cred_p,
1221 1221 int *rval_p)
1222 1222 {
1223 1223 struct sysctrl_soft_state *softsp;
1224 1224 sysc_cfga_pkt_t sysc_pkt;
1225 1225 fhc_bd_t *fhc_list = NULL;
1226 1226 sysc_cfga_stat_t *sc_list = NULL;
1227 1227 fhc_bd_t *bdp;
1228 1228 sysc_cfga_stat_t *sc = NULL;
1229 1229 int instance;
1230 1230 int slot;
1231 1231 int retval = 0;
1232 1232 int i;
1233 1233
1234 1234 instance = GETINSTANCE(devt);
1235 1235 softsp = GETSOFTC(instance);
1236 1236 if (softsp == NULL) {
1237 1237 cmn_err(CE_CONT,
1238 1238 "sysctrl_ioctl(%d): NULL softstate ptr!\n",
1239 1239 (int)GETSLOT(devt));
1240 1240 return (ENXIO);
1241 1241 }
1242 1242
1243 1243 slot = GETSLOT(devt);
1244 1244
1245 1245 /*
1246 1246 * First switch is to do correct locking and do ddi_copyin()
1247 1247 */
1248 1248 switch (cmd) {
1249 1249 case SYSC_CFGA_CMD_GETSTATUS:
1250 1250 /* mutex lock the whole list */
1251 1251 if (sysc_enter_transition(-1) != TRUE) {
1252 1252 retval = EBUSY;
1253 1253 goto cleanup_exit;
1254 1254 }
1255 1255
1256 1256 /* allocate the memory before acquiring mutex */
1257 1257 fhc_list = kmem_zalloc(sizeof (fhc_bd_t) * fhc_max_boards(),
1258 1258 KM_SLEEP);
1259 1259
1260 1260 sc_list = kmem_zalloc(sizeof (sysc_cfga_stat_t) *
1261 1261 fhc_max_boards(), KM_SLEEP);
1262 1262
1263 1263 break;
1264 1264
1265 1265 case SYSC_CFGA_CMD_EJECT:
1266 1266 case SYSC_CFGA_CMD_INSERT:
1267 1267 retval = ENOTSUP;
1268 1268 goto cleanup_exit;
1269 1269
1270 1270 case SYSC_CFGA_CMD_CONNECT:
1271 1271 case SYSC_CFGA_CMD_DISCONNECT:
1272 1272 case SYSC_CFGA_CMD_UNCONFIGURE:
1273 1273 case SYSC_CFGA_CMD_CONFIGURE:
1274 1274 case SYSC_CFGA_CMD_TEST:
1275 1275 case SYSC_CFGA_CMD_TEST_SET_COND:
1276 1276 case SYSC_CFGA_CMD_QUIESCE_TEST:
1277 1277
1278 1278 /* ioctls allowed if caller has write permission */
1279 1279 if (!(flag & FWRITE)) {
1280 1280 retval = EPERM;
1281 1281 goto cleanup_exit;
1282 1282 }
1283 1283
1284 1284 retval = sysc_pkt_init(&sysc_pkt, arg, flag);
1285 1285 if (retval != 0)
1286 1286 goto cleanup_exit;
1287 1287
1288 1288 /* grasp lock and set in_transition bit */
1289 1289 if (sysc_enter_transition(cmd == SYSC_CFGA_CMD_QUIESCE_TEST
1290 1290 ? -1 : slot) != TRUE) {
1291 1291 retval = EBUSY;
1292 1292 SYSC_ERR_SET(&sysc_pkt, SYSC_ERR_INTRANS);
1293 1293 goto cleanup_copyout;
1294 1294 }
1295 1295
1296 1296 /* get the status structure for the slot */
1297 1297 bdp = fhc_bd(slot);
1298 1298 sc = &bdp->sc;
1299 1299 break;
1300 1300
1301 1301 /* POSIX definition: return ENOTTY if unsupported command */
1302 1302 default:
1303 1303 retval = ENOTTY;
1304 1304 goto cleanup_exit;
1305 1305 }
1306 1306
1307 1307 /*
1308 1308 * Second switch is to call the underlayer workhorse.
1309 1309 */
1310 1310 switch (cmd) {
1311 1311 case SYSC_CFGA_CMD_GETSTATUS:
1312 1312 for (i = 0; i < fhc_max_boards(); i++) {
1313 1313 if (fhc_bd_valid(i)) {
1314 1314 bdp = fhc_bd(i);
1315 1315 if (fhc_bd_is_jtag_master(i))
1316 1316 bdp->sc.no_detach = 1;
1317 1317 else
1318 1318 bdp->sc.no_detach = 0;
1319 1319 bcopy((caddr_t)&bdp->sc,
1320 1320 &sc_list[i], sizeof (sysc_cfga_stat_t));
1321 1321 } else {
1322 1322 sc_list[i].board = -1;
1323 1323 sc_list[i].rstate = SYSC_CFGA_RSTATE_EMPTY;
1324 1324 }
1325 1325 }
1326 1326
1327 1327 sysc_exit_transition(-1);
1328 1328
1329 1329 break;
1330 1330
1331 1331 case SYSC_CFGA_CMD_EJECT:
1332 1332 case SYSC_CFGA_CMD_INSERT:
1333 1333 retval = ENOTSUP;
1334 1334 goto cleanup_exit;
1335 1335
1336 1336 case SYSC_CFGA_CMD_CONNECT:
1337 1337 retval = sysc_policy_connect(softsp, &sysc_pkt, sc);
1338 1338 sysc_exit_transition(slot);
1339 1339 break;
1340 1340
1341 1341 case SYSC_CFGA_CMD_DISCONNECT:
1342 1342 retval = sysc_policy_disconnect(softsp, &sysc_pkt, sc);
1343 1343 sysc_exit_transition(slot);
1344 1344 break;
1345 1345
1346 1346 case SYSC_CFGA_CMD_UNCONFIGURE:
1347 1347 retval = sysc_policy_unconfigure(softsp, &sysc_pkt, sc);
1348 1348 sysc_exit_transition(slot);
1349 1349 break;
1350 1350
1351 1351 case SYSC_CFGA_CMD_CONFIGURE:
1352 1352 retval = sysc_policy_configure(softsp, &sysc_pkt, sc);
1353 1353 sysc_exit_transition(slot);
1354 1354 break;
1355 1355
1356 1356 case SYSC_CFGA_CMD_TEST:
1357 1357 retval = fhc_bd_test(slot, &sysc_pkt);
1358 1358 sysc_exit_transition(slot);
1359 1359 break;
1360 1360
1361 1361 case SYSC_CFGA_CMD_TEST_SET_COND:
1362 1362 retval = fhc_bd_test_set_cond(slot, &sysc_pkt);
1363 1363 sysc_exit_transition(slot);
1364 1364 break;
1365 1365
1366 1366 case SYSC_CFGA_CMD_QUIESCE_TEST:
1367 1367 sysctrl_suspend_prepare();
1368 1368 fhc_bdlist_unlock();
1369 1369
1370 1370 if (sysctrl_suspend(&sysc_pkt) == DDI_SUCCESS) {
1371 1371 sysctrl_resume(&sysc_pkt);
1372 1372 } else {
1373 1373 retval = EBUSY;
1374 1374 }
1375 1375
1376 1376 (void) fhc_bdlist_lock(-1);
1377 1377 sysc_exit_transition(-1);
1378 1378 break;
1379 1379
1380 1380 default:
1381 1381 retval = ENOTTY;
1382 1382 goto cleanup_exit;
1383 1383 }
1384 1384
1385 1385 cleanup_copyout:
1386 1386 /*
1387 1387 * 3rd switch is to do appropriate copyout and reset locks
1388 1388 */
1389 1389 switch (cmd) {
1390 1390 case SYSC_CFGA_CMD_GETSTATUS:
1391 1391 if (ddi_copyout(sc_list, (void *)arg,
1392 1392 sizeof (sysc_cfga_stat_t) * fhc_max_boards(),
1393 1393 flag) != 0) {
1394 1394 retval = EFAULT;
1395 1395 }
1396 1396
1397 1397 /* cleanup memory */
1398 1398 kmem_free(fhc_list, sizeof (fhc_bd_t) * fhc_max_boards());
1399 1399 kmem_free(sc_list, sizeof (sysc_cfga_stat_t) *
1400 1400 fhc_max_boards());
1401 1401 break;
1402 1402
1403 1403 case SYSC_CFGA_CMD_EJECT:
1404 1404 case SYSC_CFGA_CMD_INSERT:
1405 1405 retval = ENOTSUP;
1406 1406 break;
1407 1407
1408 1408 case SYSC_CFGA_CMD_CONNECT:
1409 1409 case SYSC_CFGA_CMD_DISCONNECT:
1410 1410 case SYSC_CFGA_CMD_UNCONFIGURE:
1411 1411 case SYSC_CFGA_CMD_CONFIGURE:
1412 1412 case SYSC_CFGA_CMD_TEST:
1413 1413 case SYSC_CFGA_CMD_TEST_SET_COND:
1414 1414 case SYSC_CFGA_CMD_QUIESCE_TEST:
1415 1415 if (sysc_pkt_fini(&sysc_pkt, arg, flag) != TRUE)
1416 1416 return (EFAULT);
1417 1417 break;
1418 1418
1419 1419 default:
1420 1420 retval = ENOTTY;
1421 1421 break;
1422 1422 }
1423 1423
1424 1424 cleanup_exit:
1425 1425 return (retval);
1426 1426 }
1427 1427
1428 1428 /*
1429 1429 * system_high_handler()
1430 1430 * This routine handles system interrupts.
1431 1431 *
1432 1432 * This routine goes through all the interrupt sources and masks
1433 1433 * off the enable bit if interrupting. Because of the special
1434 1434 * nature of the pps fan source bits, we also cache the state
1435 1435 * of the fan bits for that special case.
1436 1436 *
1437 1437 * The rest of the work is done in the low level handlers
1438 1438 */
1439 1439 static uint_t
1440 1440 system_high_handler(caddr_t arg)
1441 1441 {
1442 1442 struct sysctrl_soft_state *softsp = (struct sysctrl_soft_state *)arg;
1443 1443 uchar_t csr;
1444 1444 uchar_t status2;
1445 1445 uchar_t tmp_reg;
1446 1446 int serviced = 0;
1447 1447
1448 1448 ASSERT(softsp);
1449 1449
1450 1450 mutex_enter(&softsp->csr_mutex);
1451 1451
1452 1452 /* read in the hardware registers */
1453 1453 csr = *(softsp->csr);
1454 1454 status2 = *(softsp->status2);
1455 1455
1456 1456 if (csr & SYS_AC_PWR_FAIL_EN) {
1457 1457 if (status2 & SYS_AC_FAIL) {
1458 1458
1459 1459 /* save the powerfail state in nvram */
1460 1460 nvram_update_powerfail(softsp);
1461 1461
1462 1462 /* disable this interrupt source */
1463 1463 csr &= ~SYS_AC_PWR_FAIL_EN;
1464 1464
1465 1465 ddi_trigger_softintr(softsp->ac_fail_id);
1466 1466 serviced++;
1467 1467 }
1468 1468 }
1469 1469
1470 1470 if (csr & SYS_PS_FAIL_EN) {
1471 1471 if ((*(softsp->ps_stat) != 0xff) ||
1472 1472 ((~status2) & (SYS_PPS0_OK | SYS_CLK_33_OK |
1473 1473 SYS_CLK_50_OK)) ||
1474 1474 (~(*(softsp->pppsr)) & SYS_PPPSR_BITS)) {
1475 1475
1476 1476 /* disable this interrupt source */
1477 1477 csr &= ~SYS_PS_FAIL_EN;
1478 1478
1479 1479 ddi_trigger_softintr(softsp->ps_fail_int_id);
1480 1480 serviced++;
1481 1481 }
1482 1482 }
1483 1483
1484 1484 if (csr & SYS_PPS_FAN_FAIL_EN) {
1485 1485 if (status2 & SYS_RACK_FANFAIL ||
1486 1486 !(status2 & SYS_AC_FAN_OK) ||
1487 1487 !(status2 & SYS_KEYSW_FAN_OK)) {
1488 1488
1489 1489 /*
1490 1490 * we must cache the fan status because it goes
1491 1491 * away when we disable interrupts !?!?!
1492 1492 */
1493 1493 softsp->pps_fan_saved = status2;
1494 1494
1495 1495 /* disable this interrupt source */
1496 1496 csr &= ~SYS_PPS_FAN_FAIL_EN;
1497 1497
1498 1498 ddi_trigger_softintr(softsp->pps_fan_id);
1499 1499 serviced++;
1500 1500 }
1501 1501 }
1502 1502
1503 1503 if (csr & SYS_SBRD_PRES_EN) {
1504 1504 if (!(*(softsp->status1) & SYS_NOT_BRD_PRES)) {
1505 1505
1506 1506 /* disable this interrupt source */
1507 1507 csr &= ~SYS_SBRD_PRES_EN;
1508 1508
1509 1509 ddi_trigger_softintr(softsp->sbrd_pres_id);
1510 1510 serviced++;
1511 1511 }
1512 1512 }
1513 1513
1514 1514 if (!serviced) {
1515 1515
1516 1516 /*
1517 1517 * if we get here than it is likely that contact bounce
1518 1518 * is messing with us. so, we need to shut this interrupt
1519 1519 * up for a while to let the contacts settle down.
1520 1520 * Then we will re-enable the interrupts that are enabled
1521 1521 * right now. The trick is to disable the appropriate
1522 1522 * interrupts and then to re-enable them correctly, even
1523 1523 * though intervening handlers might have been working.
1524 1524 */
1525 1525
1526 1526 /* remember all interrupts that could have caused it */
1527 1527 softsp->saved_en_state |= csr &
1528 1528 (SYS_AC_PWR_FAIL_EN | SYS_PS_FAIL_EN |
1529 1529 SYS_PPS_FAN_FAIL_EN | SYS_SBRD_PRES_EN);
1530 1530
1531 1531 /* and then turn them off */
1532 1532 csr &= ~(SYS_AC_PWR_FAIL_EN | SYS_PS_FAIL_EN |
1533 1533 SYS_PPS_FAN_FAIL_EN | SYS_SBRD_PRES_EN);
1534 1534
1535 1535 /* and then bump the counter */
1536 1536 softsp->spur_count++;
1537 1537
1538 1538 /* and kick off the timeout */
1539 1539 ddi_trigger_softintr(softsp->spur_id);
1540 1540 }
1541 1541
1542 1542 /* update the real csr */
1543 1543 *(softsp->csr) = csr;
1544 1544 tmp_reg = *(softsp->csr);
1545 1545 #ifdef lint
1546 1546 tmp_reg = tmp_reg;
1547 1547 #endif
1548 1548 mutex_exit(&softsp->csr_mutex);
1549 1549
1550 1550 return (DDI_INTR_CLAIMED);
1551 1551 }
1552 1552
1553 1553 /*
1554 1554 * we've detected a spurious interrupt.
1555 1555 * determine if we should log a message and if we need another timeout
1556 1556 */
1557 1557 static uint_t
1558 1558 spur_delay(caddr_t arg)
1559 1559 {
1560 1560 struct sysctrl_soft_state *softsp = (struct sysctrl_soft_state *)arg;
1561 1561
1562 1562 ASSERT(softsp);
1563 1563
1564 1564 /* do we need to complain? */
1565 1565 mutex_enter(&softsp->csr_mutex);
1566 1566
1567 1567 /* NOTE: this is == because we want one message per long timeout */
1568 1568 if (softsp->spur_count == MAX_SPUR_COUNT) {
1569 1569 char buf[128];
1570 1570
1571 1571 /* print out the candidates known at this time */
1572 1572 /* XXX not perfect because of re-entrant nature but close */
1573 1573 buf[0] = '\0';
1574 1574 if (softsp->saved_en_state & SYS_AC_PWR_FAIL_EN)
1575 1575 (void) strcat(buf, "AC FAIL");
1576 1576 if (softsp->saved_en_state & SYS_PPS_FAN_FAIL_EN)
1577 1577 (void) strcat(buf, buf[0] ? "|PPS FANS" : "PPS FANS");
1578 1578 if (softsp->saved_en_state & SYS_PS_FAIL_EN)
1579 1579 (void) strcat(buf, buf[0] ? "|PS FAIL" : "PS FAIL");
1580 1580 if (softsp->saved_en_state & SYS_SBRD_PRES_EN)
1581 1581 (void) strcat(buf,
1582 1582 buf[0] ? "|BOARD INSERT" : "BOARD INSERT");
1583 1583
1584 1584 /*
1585 1585 * This is a high level mutex, therefore it needs to be
1586 1586 * dropped before calling cmn_err.
1587 1587 */
1588 1588 mutex_exit(&softsp->csr_mutex);
1589 1589
1590 1590 cmn_err(CE_WARN, "sysctrl%d: unserviced interrupt."
1591 1591 " possible sources [%s].",
1592 1592 ddi_get_instance(softsp->dip), buf);
1593 1593 } else
1594 1594 mutex_exit(&softsp->csr_mutex);
1595 1595
1596 1596 mutex_enter(&softsp->spur_int_lock);
1597 1597
1598 1598 /* do we need to start the short timeout? */
1599 1599 if (softsp->spur_timeout_id == 0) {
1600 1600 softsp->spur_timeout_id = timeout(spur_retry, softsp,
1601 1601 spur_timeout_hz);
1602 1602 }
1603 1603
1604 1604 /* do we need to start the long timeout? */
1605 1605 if (softsp->spur_long_timeout_id == 0) {
1606 1606 softsp->spur_long_timeout_id = timeout(spur_long_timeout,
1607 1607 softsp, spur_long_timeout_hz);
1608 1608 }
1609 1609
1610 1610 mutex_exit(&softsp->spur_int_lock);
1611 1611
1612 1612 return (DDI_INTR_CLAIMED);
1613 1613 }
1614 1614
1615 1615 /*
1616 1616 * spur_retry
1617 1617 *
1618 1618 * this routine simply triggers the interrupt which will re-enable
1619 1619 * the interrupts disabled by the spurious int detection.
1620 1620 */
1621 1621 static void
1622 1622 spur_retry(void *arg)
1623 1623 {
1624 1624 struct sysctrl_soft_state *softsp = arg;
1625 1625
1626 1626 ASSERT(softsp);
1627 1627
1628 1628 ddi_trigger_softintr(softsp->spur_high_id);
1629 1629
1630 1630 mutex_enter(&softsp->spur_int_lock);
1631 1631 softsp->spur_timeout_id = 0;
1632 1632 mutex_exit(&softsp->spur_int_lock);
1633 1633 }
1634 1634
1635 1635 /*
1636 1636 * spur_reenable
1637 1637 *
1638 1638 * OK, we've been slient for a while. Go ahead and re-enable the
1639 1639 * interrupts that were enabled at the time of the spurious detection.
1640 1640 */
1641 1641 static uint_t
1642 1642 spur_reenable(caddr_t arg)
1643 1643 {
1644 1644 struct sysctrl_soft_state *softsp = (struct sysctrl_soft_state *)arg;
1645 1645 uchar_t tmp_reg;
1646 1646
1647 1647 ASSERT(softsp);
1648 1648
1649 1649 mutex_enter(&softsp->csr_mutex);
1650 1650
1651 1651 /* reenable those who were spurious candidates */
1652 1652 *(softsp->csr) |= softsp->saved_en_state &
1653 1653 (SYS_AC_PWR_FAIL_EN | SYS_PS_FAIL_EN |
1654 1654 SYS_PPS_FAN_FAIL_EN | SYS_SBRD_PRES_EN);
1655 1655 tmp_reg = *(softsp->csr);
1656 1656 #ifdef lint
1657 1657 tmp_reg = tmp_reg;
1658 1658 #endif
1659 1659
1660 1660 /* clear out the saved state */
1661 1661 softsp->saved_en_state = 0;
1662 1662
1663 1663 mutex_exit(&softsp->csr_mutex);
1664 1664
1665 1665 return (DDI_INTR_CLAIMED);
1666 1666 }
1667 1667
1668 1668 /*
1669 1669 * spur_long_timeout
1670 1670 *
1671 1671 * this routine merely resets the spurious interrupt counter thus ending
1672 1672 * the interval of interest. of course this is done by triggering a
1673 1673 * softint because the counter is protected by an interrupt mutex.
1674 1674 */
1675 1675 static void
1676 1676 spur_long_timeout(void *arg)
1677 1677 {
1678 1678 struct sysctrl_soft_state *softsp = arg;
1679 1679
1680 1680 ASSERT(softsp);
1681 1681
1682 1682 ddi_trigger_softintr(softsp->spur_long_to_id);
1683 1683
1684 1684 mutex_enter(&softsp->spur_int_lock);
1685 1685 softsp->spur_long_timeout_id = 0;
1686 1686 mutex_exit(&softsp->spur_int_lock);
1687 1687 }
1688 1688
1689 1689 /*
1690 1690 * spur_clear_count
1691 1691 *
1692 1692 * simply clear out the spurious interrupt counter.
1693 1693 *
1694 1694 * softint level only
1695 1695 */
1696 1696 static uint_t
1697 1697 spur_clear_count(caddr_t arg)
1698 1698 {
1699 1699 struct sysctrl_soft_state *softsp = (struct sysctrl_soft_state *)arg;
1700 1700
1701 1701 ASSERT(softsp);
1702 1702
1703 1703 mutex_enter(&softsp->csr_mutex);
1704 1704 softsp->spur_count = 0;
1705 1705 mutex_exit(&softsp->csr_mutex);
1706 1706
1707 1707 return (DDI_INTR_CLAIMED);
1708 1708 }
1709 1709
1710 1710 /*
1711 1711 * ac_fail_handler
1712 1712 *
1713 1713 * This routine polls the AC power failure bit in the system status2
1714 1714 * register. If we get to this routine, then we sensed an ac fail
1715 1715 * condition. Note the fact and check again in a few.
1716 1716 *
1717 1717 * Called as softint from high interrupt.
1718 1718 */
1719 1719 static uint_t
1720 1720 ac_fail_handler(caddr_t arg)
1721 1721 {
1722 1722 struct sysctrl_soft_state *softsp = (struct sysctrl_soft_state *)arg;
1723 1723
1724 1724 ASSERT(softsp);
1725 1725
1726 1726 cmn_err(CE_WARN, "%s failure detected", ft_str_table[FT_AC_PWR]);
1727 1727 reg_fault(0, FT_AC_PWR, FT_SYSTEM);
1728 1728 (void) timeout(ac_fail_retry, softsp, ac_timeout_hz);
1729 1729
1730 1730 return (DDI_INTR_CLAIMED);
1731 1731 }
1732 1732
1733 1733 /*
1734 1734 * The timeout from ac_fail_handler() that checks to see if the
1735 1735 * condition persists.
1736 1736 */
1737 1737 static void
1738 1738 ac_fail_retry(void *arg)
1739 1739 {
1740 1740 struct sysctrl_soft_state *softsp = arg;
1741 1741
1742 1742 ASSERT(softsp);
1743 1743
1744 1744 if (*softsp->status2 & SYS_AC_FAIL) { /* still bad? */
1745 1745 (void) timeout(ac_fail_retry, softsp, ac_timeout_hz);
1746 1746 } else {
1747 1747 cmn_err(CE_NOTE, "%s failure no longer detected",
1748 1748 ft_str_table[FT_AC_PWR]);
1749 1749 clear_fault(0, FT_AC_PWR, FT_SYSTEM);
1750 1750 ddi_trigger_softintr(softsp->ac_fail_high_id);
1751 1751 }
1752 1752 }
1753 1753
1754 1754 /*
1755 1755 * The interrupt routine that we use to re-enable the interrupt.
1756 1756 * Called from ddi_trigger_softint() in the ac_fail_retry() when
1757 1757 * the AC is better.
1758 1758 */
1759 1759 static uint_t
1760 1760 ac_fail_reenable(caddr_t arg)
1761 1761 {
1762 1762 struct sysctrl_soft_state *softsp = (struct sysctrl_soft_state *)arg;
1763 1763 uchar_t tmp_reg;
1764 1764
1765 1765 ASSERT(softsp);
1766 1766
1767 1767 mutex_enter(&softsp->csr_mutex);
1768 1768 *(softsp->csr) |= SYS_AC_PWR_FAIL_EN;
1769 1769 tmp_reg = *(softsp->csr);
1770 1770 #ifdef lint
1771 1771 tmp_reg = tmp_reg;
1772 1772 #endif
1773 1773 mutex_exit(&softsp->csr_mutex);
1774 1774
1775 1775 return (DDI_INTR_CLAIMED);
1776 1776 }
1777 1777
1778 1778 /*
1779 1779 * ps_fail_int_handler
1780 1780 *
1781 1781 * Handle power supply failure interrupt.
1782 1782 *
1783 1783 * This wrapper is called as softint from hardware interrupt routine.
1784 1784 */
1785 1785 static uint_t
1786 1786 ps_fail_int_handler(caddr_t arg)
1787 1787 {
1788 1788 return (ps_fail_handler((struct sysctrl_soft_state *)arg, 1));
1789 1789 }
1790 1790
1791 1791 /*
1792 1792 * ps_fail_poll_handler
1793 1793 *
1794 1794 * Handle power supply failure interrupt.
1795 1795 *
1796 1796 * This wrapper is called as softint from power supply poll routine.
1797 1797 */
1798 1798 static uint_t
1799 1799 ps_fail_poll_handler(caddr_t arg)
1800 1800 {
1801 1801 return (ps_fail_handler((struct sysctrl_soft_state *)arg, 0));
1802 1802 }
1803 1803
1804 1804 /*
1805 1805 * ps_fail_handler
1806 1806 *
1807 1807 * This routine checks all eight of the board power supplies that are
1808 1808 * installed plus the Peripheral power supply and the two DC OK. Since the
1809 1809 * hardware bits are not enough to indicate Power Supply failure
1810 1810 * vs. being turned off via software, the driver must maintain a
1811 1811 * shadow state for the Power Supply status and monitor all changes.
1812 1812 *
1813 1813 * Called as a softint only.
1814 1814 */
1815 1815 static uint_t
1816 1816 ps_fail_handler(struct sysctrl_soft_state *softsp, int fromint)
1817 1817 {
1818 1818 int i;
1819 1819 struct ps_state *pstatp;
1820 1820 int poll_needed = 0;
1821 1821 uchar_t ps_stat, ps_pres, status1, status2, pppsr;
1822 1822 uchar_t tmp_reg;
1823 1823 enum power_state current_power_state;
1824 1824
1825 1825 ASSERT(softsp);
1826 1826
1827 1827 /* pre-read the hardware state */
1828 1828 ps_stat = *softsp->ps_stat;
1829 1829 ps_pres = *softsp->ps_pres;
1830 1830 status1 = *softsp->status1;
1831 1831 status2 = *softsp->status2;
1832 1832 pppsr = *softsp->pppsr;
1833 1833
1834 1834 (void) fhc_bdlist_lock(-1);
1835 1835
1836 1836 mutex_enter(&softsp->ps_fail_lock);
1837 1837
1838 1838 for (i = 0, pstatp = &softsp->ps_stats[0]; i < SYS_PS_COUNT;
1839 1839 i++, pstatp++) {
1840 1840 int temp_psok;
1841 1841 int temp_pres;
1842 1842 int is_precharge = FALSE;
1843 1843 int is_fan_assy = FALSE;
1844 1844
1845 1845 /*
1846 1846 * pre-compute the presence and ok bits for this
1847 1847 * power supply from the hardware registers.
1848 1848 * NOTE: 4-slot pps1 is the same as core ps 7...
1849 1849 */
1850 1850 switch (i) {
1851 1851 /* the core power supplies */
1852 1852 case 0: case 1: case 2: case 3:
1853 1853 case 4: case 5: case 6: case 7:
1854 1854 temp_pres = !((ps_pres >> i) & 0x1);
1855 1855 temp_psok = (ps_stat >> i) & 0x1;
1856 1856 break;
1857 1857
1858 1858 /* the first peripheral power supply */
1859 1859 case SYS_PPS0_INDEX:
1860 1860 temp_pres = !(status1 & SYS_NOT_PPS0_PRES);
1861 1861 temp_psok = status2 & SYS_PPS0_OK;
1862 1862 break;
1863 1863
1864 1864 /* shared 3.3v clock power */
1865 1865 case SYS_CLK_33_INDEX:
1866 1866 temp_pres = TRUE;
1867 1867 temp_psok = status2 & SYS_CLK_33_OK;
1868 1868 break;
1869 1869
1870 1870 /* shared 5.0v clock power */
1871 1871 case SYS_CLK_50_INDEX:
1872 1872 temp_pres = TRUE;
1873 1873 temp_psok = status2 & SYS_CLK_50_OK;
1874 1874 break;
1875 1875
1876 1876 /* peripheral 5v */
1877 1877 case SYS_V5_P_INDEX:
1878 1878 temp_pres = !(status1 & SYS_NOT_PPS0_PRES) ||
1879 1879 ((IS4SLOT(softsp->nslots) ||
1880 1880 IS5SLOT(softsp->nslots)) &&
1881 1881 !(ps_pres & SYS_NOT_PPS1_PRES));
1882 1882 temp_psok = pppsr & SYS_V5_P_OK;
1883 1883 break;
1884 1884
1885 1885 /* peripheral 12v */
1886 1886 case SYS_V12_P_INDEX:
1887 1887 temp_pres = !(status1 & SYS_NOT_PPS0_PRES) ||
1888 1888 ((IS4SLOT(softsp->nslots) ||
1889 1889 IS5SLOT(softsp->nslots)) &&
1890 1890 !(ps_pres & SYS_NOT_PPS1_PRES));
1891 1891 temp_psok = pppsr & SYS_V12_P_OK;
1892 1892 break;
1893 1893
1894 1894 /* aux 5v */
1895 1895 case SYS_V5_AUX_INDEX:
1896 1896 temp_pres = !(status1 & SYS_NOT_PPS0_PRES);
1897 1897 temp_psok = pppsr & SYS_V5_AUX_OK;
1898 1898 break;
1899 1899
1900 1900 /* peripheral 5v precharge */
1901 1901 case SYS_V5_P_PCH_INDEX:
1902 1902 temp_pres = !(status1 & SYS_NOT_PPS0_PRES);
1903 1903 temp_psok = pppsr & SYS_V5_P_PCH_OK;
1904 1904 is_precharge = TRUE;
1905 1905 break;
1906 1906
1907 1907 /* peripheral 12v precharge */
1908 1908 case SYS_V12_P_PCH_INDEX:
1909 1909 temp_pres = !(status1 & SYS_NOT_PPS0_PRES);
1910 1910 temp_psok = pppsr & SYS_V12_P_PCH_OK;
1911 1911 is_precharge = TRUE;
1912 1912 break;
1913 1913
1914 1914 /* 3.3v precharge */
1915 1915 case SYS_V3_PCH_INDEX:
1916 1916 temp_pres = !(status1 & SYS_NOT_PPS0_PRES);
1917 1917 temp_psok = pppsr & SYS_V3_PCH_OK;
1918 1918 is_precharge = TRUE;
1919 1919 break;
1920 1920
1921 1921 /* 5v precharge */
1922 1922 case SYS_V5_PCH_INDEX:
1923 1923 temp_pres = !(status1 & SYS_NOT_PPS0_PRES);
1924 1924 temp_psok = pppsr & SYS_V5_PCH_OK;
1925 1925 is_precharge = TRUE;
1926 1926 break;
1927 1927
1928 1928 /* peripheral fan assy */
1929 1929 case SYS_P_FAN_INDEX:
1930 1930 temp_pres = (IS4SLOT(softsp->nslots) ||
1931 1931 IS5SLOT(softsp->nslots)) &&
1932 1932 !(status1 & SYS_NOT_P_FAN_PRES);
1933 1933 temp_psok = softsp->pps_fan_saved &
1934 1934 SYS_AC_FAN_OK;
1935 1935 is_fan_assy = TRUE;
1936 1936 break;
1937 1937 }
1938 1938
1939 1939 /* *** Phase 1 -- power supply presence tests *** */
1940 1940
1941 1941 /* do we know the presence status for this power supply? */
1942 1942 if (pstatp->pshadow == PRES_UNKNOWN) {
1943 1943 pstatp->pshadow = temp_pres ? PRES_IN : PRES_OUT;
1944 1944 pstatp->dcshadow = temp_pres ? PS_BOOT : PS_OUT;
1945 1945 } else {
1946 1946 /* has the ps presence state changed? */
1947 1947 if (!temp_pres ^ (pstatp->pshadow == PRES_IN)) {
1948 1948 pstatp->pctr = 0;
1949 1949 } else {
1950 1950 /* a change! are we counting? */
1951 1951 if (pstatp->pctr == 0) {
1952 1952 pstatp->pctr = PS_PRES_CHANGE_TICKS;
1953 1953 } else if (--pstatp->pctr == 0) {
1954 1954 pstatp->pshadow = temp_pres ?
1955 1955 PRES_IN : PRES_OUT;
1956 1956 pstatp->dcshadow = temp_pres ?
1957 1957 PS_UNKNOWN : PS_OUT;
1958 1958
1959 1959 /*
1960 1960 * Now we know the state has
1961 1961 * changed, so we should log it.
1962 1962 */
1963 1963 ps_log_pres_change(softsp,
1964 1964 i, temp_pres);
1965 1965 }
1966 1966 }
1967 1967 }
1968 1968
1969 1969 /* *** Phase 2 -- power supply status tests *** */
1970 1970
1971 1971 /* check if the Power Supply is removed or same as before */
1972 1972 if ((pstatp->dcshadow == PS_OUT) ||
1973 1973 ((pstatp->dcshadow == PS_OK) && temp_psok) ||
1974 1974 ((pstatp->dcshadow == PS_FAIL) && !temp_psok)) {
1975 1975 pstatp->dcctr = 0;
1976 1976 } else {
1977 1977
1978 1978 /* OK, a change, do we start the timer? */
1979 1979 if (pstatp->dcctr == 0) {
1980 1980 switch (pstatp->dcshadow) {
1981 1981 case PS_BOOT:
1982 1982 pstatp->dcctr = PS_FROM_BOOT_TICKS;
1983 1983 break;
1984 1984
1985 1985 case PS_UNKNOWN:
1986 1986 pstatp->dcctr = is_fan_assy ?
1987 1987 PS_P_FAN_FROM_UNKNOWN_TICKS :
1988 1988 PS_FROM_UNKNOWN_TICKS;
1989 1989 break;
1990 1990
1991 1991 case PS_OK:
1992 1992 pstatp->dcctr = is_precharge ?
1993 1993 PS_PCH_FROM_OK_TICKS :
1994 1994 PS_FROM_OK_TICKS;
1995 1995 break;
1996 1996
1997 1997 case PS_FAIL:
1998 1998 pstatp->dcctr = PS_FROM_FAIL_TICKS;
1999 1999 break;
2000 2000
2001 2001 default:
2002 2002 panic("sysctrl%d: Unknown Power "
2003 2003 "Supply State %d", pstatp->dcshadow,
2004 2004 ddi_get_instance(softsp->dip));
2005 2005 }
2006 2006 }
2007 2007
2008 2008 /* has the ticker expired? */
2009 2009 if (--pstatp->dcctr == 0) {
2010 2010
2011 2011 /* we'll skip OK messages during boot */
2012 2012 if (!((pstatp->dcshadow == PS_BOOT) &&
2013 2013 temp_psok)) {
2014 2014 ps_log_state_change(softsp,
2015 2015 i, temp_psok);
2016 2016 }
2017 2017
2018 2018 /*
2019 2019 * remote console interface has to be
2020 2020 * reinitialized on the rising edge V5_AUX
2021 2021 * when it is NOT boot. At the boot time an
2022 2022 * an error condition exists if it was not
2023 2023 * enabled before.
2024 2024 */
2025 2025 if ((i == SYS_V5_AUX_INDEX) &&
2026 2026 (pstatp->dcshadow != PS_BOOT) &&
2027 2027 (softsp->enable_rcons_atboot)) {
2028 2028 if (temp_psok)
2029 2029 rcons_reinit(softsp);
2030 2030 else
2031 2031 /* disable rconsole */
2032 2032 *(softsp->clk_freq2) &=
2033 2033 ~RCONS_UART_EN;
2034 2034 tmp_reg = *(softsp->csr);
2035 2035 #ifdef lint
2036 2036 tmp_reg = tmp_reg;
2037 2037 #endif
2038 2038
2039 2039 }
2040 2040
2041 2041 /* regardless, update the shadow state */
2042 2042 pstatp->dcshadow = temp_psok ? PS_OK : PS_FAIL;
2043 2043
2044 2044 /* always update board condition */
2045 2045 sysc_policy_update(softsp, NULL,
2046 2046 SYSC_EVT_BD_PS_CHANGE);
2047 2047
2048 2048 }
2049 2049 }
2050 2050
2051 2051 /*
2052 2052 * We will need to continue polling for three reasons:
2053 2053 * - a failing power supply is detected and we haven't yet
2054 2054 * determined the power supplies existence.
2055 2055 * - the power supply is just installed and we're waiting
2056 2056 * to give it a change to power up,
2057 2057 * - a failed power supply state is recognized
2058 2058 *
2059 2059 * NOTE: PS_FAIL shadow state is not the same as !temp_psok
2060 2060 * because of the persistence of PS_FAIL->PS_OK.
2061 2061 */
2062 2062 if (!temp_psok ||
2063 2063 (pstatp->dcshadow == PS_UNKNOWN) ||
2064 2064 (pstatp->dcshadow == PS_FAIL)) {
2065 2065 poll_needed++;
2066 2066 }
2067 2067 }
2068 2068
2069 2069 /*
2070 2070 * Now, get the current power state for this instance.
2071 2071 * If the current state is different than what was known, complain.
2072 2072 */
2073 2073 current_power_state = compute_power_state(softsp, 0);
2074 2074
2075 2075 if (softsp->power_state != current_power_state) {
2076 2076 switch (current_power_state) {
2077 2077 case BELOW_MINIMUM:
2078 2078 cmn_err(CE_WARN,
2079 2079 "Insufficient power available to system");
2080 2080 if (!disable_insufficient_power_reboot) {
2081 2081 cmn_err(CE_WARN, "System reboot in %d seconds",
2082 2082 PS_INSUFFICIENT_COUNTDOWN_SEC);
2083 2083 }
2084 2084 reg_fault(1, FT_INSUFFICIENT_POWER, FT_SYSTEM);
2085 2085 softsp->power_countdown = PS_POWER_COUNTDOWN_TICKS;
2086 2086 break;
2087 2087
2088 2088 case MINIMUM:
2089 2089 /* If we came from REDUNDANT, complain */
2090 2090 if (softsp->power_state == REDUNDANT) {
2091 2091 cmn_err(CE_WARN, "Redundant power lost");
2092 2092 /* If we came from BELOW_MINIMUM, hurrah! */
2093 2093 } else if (softsp->power_state == BELOW_MINIMUM) {
2094 2094 cmn_err(CE_NOTE, "Minimum power available");
2095 2095 clear_fault(1, FT_INSUFFICIENT_POWER,
2096 2096 FT_SYSTEM);
2097 2097 }
2098 2098 break;
2099 2099
2100 2100 case REDUNDANT:
2101 2101 /* If we aren't from boot, spread the good news */
2102 2102 if (softsp->power_state != BOOT) {
2103 2103 cmn_err(CE_NOTE, "Redundant power available");
2104 2104 clear_fault(1, FT_INSUFFICIENT_POWER,
2105 2105 FT_SYSTEM);
2106 2106 }
2107 2107 break;
2108 2108
2109 2109 default:
2110 2110 break;
2111 2111 }
2112 2112 softsp->power_state = current_power_state;
2113 2113 sysc_policy_update(softsp, NULL, SYSC_EVT_BD_PS_CHANGE);
2114 2114 }
2115 2115
2116 2116 mutex_exit(&softsp->ps_fail_lock);
2117 2117
2118 2118 fhc_bdlist_unlock();
2119 2119
2120 2120 /*
2121 2121 * Are we in insufficient powerstate?
2122 2122 * If so, is it time to take action?
2123 2123 */
2124 2124 if (softsp->power_state == BELOW_MINIMUM &&
2125 2125 softsp->power_countdown > 0 && --(softsp->power_countdown) == 0 &&
2126 2126 !disable_insufficient_power_reboot) {
2127 2127 cmn_err(CE_WARN,
2128 2128 "Insufficient power. System Reboot Started...");
2129 2129
2130 2130 fhc_reboot();
2131 2131 }
2132 2132
2133 2133 /*
2134 2134 * If we don't have ps problems that need to be polled for, then
2135 2135 * enable interrupts.
2136 2136 */
2137 2137 if (!poll_needed) {
2138 2138 mutex_enter(&softsp->csr_mutex);
2139 2139 *(softsp->csr) |= SYS_PS_FAIL_EN;
2140 2140 tmp_reg = *(softsp->csr);
2141 2141 #ifdef lint
2142 2142 tmp_reg = tmp_reg;
2143 2143 #endif
2144 2144 mutex_exit(&softsp->csr_mutex);
2145 2145 }
2146 2146
2147 2147 /*
2148 2148 * Only the polling loop re-triggers the polling loop timeout
2149 2149 */
2150 2150 if (!fromint) {
2151 2151 (void) timeout(ps_fail_retry, softsp, ps_fail_timeout_hz);
2152 2152 }
2153 2153
2154 2154 return (DDI_INTR_CLAIMED);
2155 2155 }
2156 2156
2157 2157 /*
2158 2158 * Compute the current power configuration for this system.
2159 2159 * Disk boards and Clock boards are not counted.
2160 2160 *
2161 2161 * This function must be called with the ps_fail_lock held.
2162 2162 */
2163 2163 enum power_state
2164 2164 compute_power_state(struct sysctrl_soft_state *softsp, int plus_load)
2165 2165 {
2166 2166 int i;
2167 2167 int ok_supply_count = 0;
2168 2168 int load_count = 0;
2169 2169 int minimum_power_count;
2170 2170 int pps_ok;
2171 2171 fhc_bd_t *list;
2172 2172
2173 2173 ASSERT(mutex_owned(&softsp->ps_fail_lock));
2174 2174
2175 2175 /*
2176 2176 * Walk down the interesting power supplies and
2177 2177 * count the operational power units
2178 2178 */
2179 2179 for (i = 0; i < 8; i++) {
2180 2180 /*
2181 2181 * power supply id 7 on a 4 or 5 slot system is PPS1.
2182 2182 * don't include it in the redundant core power calculation.
2183 2183 */
2184 2184 if (i == 7 &&
2185 2185 (IS4SLOT(softsp->nslots) || IS5SLOT(softsp->nslots)))
2186 2186 continue;
2187 2187
2188 2188 if (softsp->ps_stats[i].dcshadow == PS_OK)
2189 2189 ok_supply_count++;
2190 2190 }
2191 2191
2192 2192 /* Note the state of the PPS... */
2193 2193 pps_ok = (softsp->ps_stats[SYS_PPS0_INDEX].dcshadow == PS_OK);
2194 2194
2195 2195 /*
2196 2196 * Dynamically compute the load count in the system.
2197 2197 * Don't count disk boards or boards in low power state.
2198 2198 */
2199 2199 for (list = fhc_bd_first(); list; list = fhc_bd_next(list)) {
2200 2200 ASSERT(list->sc.type != CLOCK_BOARD);
2201 2201 if (list->sc.rstate == SYSC_CFGA_RSTATE_CONNECTED) {
2202 2202 load_count++;
2203 2203 }
2204 2204 }
2205 2205
2206 2206 load_count += plus_load;
2207 2207 /*
2208 2208 * If we are 8 slot and we have 7 or 8 boards, then the PPS
2209 2209 * can count as a power supply...
2210 2210 */
2211 2211 if (IS8SLOT(softsp->nslots) && load_count >= 7 && pps_ok)
2212 2212 ok_supply_count++;
2213 2213
2214 2214 /*
2215 2215 * This is to cover the corner case of a UE3500 having 5
2216 2216 * boards installed and still giving it N+1 power status.
2217 2217 */
2218 2218 if (IS5SLOT(softsp->nslots) && (load_count >= 5))
2219 2219 ok_supply_count++;
2220 2220
2221 2221 /*
2222 2222 * Determine our power situation. This is a simple step
2223 2223 * function right now:
2224 2224 *
2225 2225 * minimum power count = min(7, floor((board count + 1) / 2))
2226 2226 */
2227 2227 minimum_power_count = (load_count + 1) / 2;
2228 2228 if (minimum_power_count > 7)
2229 2229 minimum_power_count = 7;
2230 2230
2231 2231 if (ok_supply_count > minimum_power_count)
2232 2232 return (REDUNDANT);
2233 2233 else if (ok_supply_count == minimum_power_count)
2234 2234 return (MINIMUM);
2235 2235 else
2236 2236 return (BELOW_MINIMUM);
2237 2237 }
2238 2238
2239 2239 /*
2240 2240 * log the change of power supply presence
2241 2241 */
2242 2242 static void
2243 2243 ps_log_pres_change(struct sysctrl_soft_state *softsp, int index, int present)
2244 2244 {
2245 2245 char *trans = present ? "Installed" : "Removed";
2246 2246
2247 2247 switch (index) {
2248 2248 /* the core power supplies (except for 7) */
2249 2249 case 0: case 1: case 2: case 3:
2250 2250 case 4: case 5: case 6:
2251 2251 cmn_err(CE_NOTE, "%s %d %s", ft_str_table[FT_CORE_PS], index,
2252 2252 trans);
2253 2253 if (!present) {
2254 2254 clear_fault(index, FT_CORE_PS, FT_SYSTEM);
2255 2255 sysc_policy_update(softsp, NULL, SYSC_EVT_BD_PS_CHANGE);
2256 2256 }
2257 2257 break;
2258 2258
2259 2259 /* power supply 7 / pps 1 */
2260 2260 case 7:
2261 2261 if (IS4SLOT(softsp->nslots) || IS5SLOT(softsp->nslots)) {
2262 2262 cmn_err(CE_NOTE, "%s 1 %s", ft_str_table[FT_PPS],
2263 2263 trans);
2264 2264 if (!present) {
2265 2265 clear_fault(1, FT_PPS, FT_SYSTEM);
2266 2266 }
2267 2267 } else {
2268 2268 cmn_err(CE_NOTE, "%s %d %s", ft_str_table[FT_CORE_PS],
2269 2269 index, trans);
2270 2270 if (!present) {
2271 2271 clear_fault(7, FT_CORE_PS, FT_SYSTEM);
2272 2272 sysc_policy_update(softsp, NULL, SYSC_EVT_BD_PS_CHANGE);
2273 2273 }
2274 2274 }
2275 2275 break;
2276 2276
2277 2277 /* the peripheral power supply 0 */
2278 2278 case SYS_PPS0_INDEX:
2279 2279 cmn_err(CE_NOTE, "%s 0 %s", ft_str_table[FT_PPS], trans);
2280 2280 if (!present) {
2281 2281 clear_fault(0, FT_PPS, FT_SYSTEM);
2282 2282 sysc_policy_update(softsp, NULL, SYSC_EVT_BD_PS_CHANGE);
2283 2283 }
2284 2284 break;
2285 2285
2286 2286 /* the peripheral rack fan assy */
2287 2287 case SYS_P_FAN_INDEX:
2288 2288 cmn_err(CE_NOTE, "%s %s", ft_str_table[FT_PPS_FAN], trans);
2289 2289 if (!present) {
2290 2290 clear_fault(0, FT_PPS_FAN, FT_SYSTEM);
2291 2291 }
2292 2292 break;
2293 2293
2294 2294 /* we don't mention a change of presence state for any other power */
2295 2295 }
2296 2296 }
2297 2297
2298 2298 /*
2299 2299 * log the change of power supply status
2300 2300 */
2301 2301 static void
2302 2302 ps_log_state_change(struct sysctrl_soft_state *softsp, int index, int ps_ok)
2303 2303 {
2304 2304 int level = ps_ok ? CE_NOTE : CE_WARN;
2305 2305 char *s = ps_ok ? "OK" : "Failing";
2306 2306
2307 2307 switch (index) {
2308 2308 /* the core power supplies (except 7) */
2309 2309 case 0: case 1: case 2: case 3:
2310 2310 case 4: case 5: case 6:
2311 2311 cmn_err(level, "%s %d %s", ft_str_table[FT_CORE_PS], index, s);
2312 2312 if (ps_ok) {
2313 2313 clear_fault(index, FT_CORE_PS, FT_SYSTEM);
2314 2314 } else {
2315 2315 reg_fault(index, FT_CORE_PS, FT_SYSTEM);
2316 2316 }
2317 2317 break;
2318 2318
2319 2319 /* power supply 7 / pps 1 */
2320 2320 case 7:
2321 2321 if (IS4SLOT(softsp->nslots) || IS5SLOT(softsp->nslots)) {
2322 2322 cmn_err(level, "%s 1 %s", ft_str_table[FT_PPS], s);
2323 2323 if (ps_ok) {
2324 2324 clear_fault(1, FT_PPS, FT_SYSTEM);
2325 2325 } else {
2326 2326 reg_fault(1, FT_PPS, FT_SYSTEM);
2327 2327 }
2328 2328 } else {
2329 2329 cmn_err(level, "%s %d %s", ft_str_table[FT_CORE_PS],
2330 2330 index, s);
2331 2331 if (ps_ok) {
2332 2332 clear_fault(index, FT_CORE_PS, FT_SYSTEM);
2333 2333 } else {
2334 2334 reg_fault(index, FT_CORE_PS, FT_SYSTEM);
2335 2335 }
2336 2336 }
2337 2337 break;
2338 2338
2339 2339 /* the peripheral power supply */
2340 2340 case SYS_PPS0_INDEX:
2341 2341 cmn_err(level, "%s %s", ft_str_table[FT_PPS], s);
2342 2342 if (ps_ok) {
2343 2343 clear_fault(0, FT_PPS, FT_SYSTEM);
2344 2344 } else {
2345 2345 reg_fault(0, FT_PPS, FT_SYSTEM);
2346 2346 }
2347 2347 break;
2348 2348
2349 2349 /* shared 3.3v clock power */
2350 2350 case SYS_CLK_33_INDEX:
2351 2351 cmn_err(level, "%s %s", ft_str_table[FT_CLK_33], s);
2352 2352 if (ps_ok) {
2353 2353 clear_fault(0, FT_CLK_33, FT_SYSTEM);
2354 2354 } else {
2355 2355 reg_fault(0, FT_CLK_33, FT_SYSTEM);
2356 2356 }
2357 2357 break;
2358 2358
2359 2359 /* shared 5.0v clock power */
2360 2360 case SYS_CLK_50_INDEX:
2361 2361 cmn_err(level, "%s %s", ft_str_table[FT_CLK_50], s);
2362 2362 if (ps_ok) {
2363 2363 clear_fault(0, FT_CLK_50, FT_SYSTEM);
2364 2364 } else {
2365 2365 reg_fault(0, FT_CLK_50, FT_SYSTEM);
2366 2366 }
2367 2367 break;
2368 2368
2369 2369 /* peripheral 5v */
2370 2370 case SYS_V5_P_INDEX:
2371 2371 cmn_err(level, "%s %s", ft_str_table[FT_V5_P], s);
2372 2372 if (ps_ok) {
2373 2373 clear_fault(0, FT_V5_P, FT_SYSTEM);
2374 2374 } else {
2375 2375 reg_fault(0, FT_V5_P, FT_SYSTEM);
2376 2376 }
2377 2377 break;
2378 2378
2379 2379 /* peripheral 12v */
2380 2380 case SYS_V12_P_INDEX:
2381 2381 cmn_err(level, "%s %s", ft_str_table[FT_V12_P], s);
2382 2382 if (ps_ok) {
2383 2383 clear_fault(0, FT_V12_P, FT_SYSTEM);
2384 2384 } else {
2385 2385 reg_fault(0, FT_V12_P, FT_SYSTEM);
2386 2386 }
2387 2387 break;
2388 2388
2389 2389 /* aux 5v */
2390 2390 case SYS_V5_AUX_INDEX:
2391 2391 cmn_err(level, "%s %s", ft_str_table[FT_V5_AUX], s);
2392 2392 if (ps_ok) {
2393 2393 clear_fault(0, FT_V5_AUX, FT_SYSTEM);
2394 2394 } else {
2395 2395 reg_fault(0, FT_V5_AUX, FT_SYSTEM);
2396 2396 }
2397 2397 break;
2398 2398
2399 2399 /* peripheral 5v precharge */
2400 2400 case SYS_V5_P_PCH_INDEX:
2401 2401 cmn_err(level, "%s %s", ft_str_table[FT_V5_P_PCH], s);
2402 2402 if (ps_ok) {
2403 2403 clear_fault(0, FT_V5_P_PCH, FT_SYSTEM);
2404 2404 } else {
2405 2405 reg_fault(0, FT_V5_P_PCH, FT_SYSTEM);
2406 2406 }
2407 2407 break;
2408 2408
2409 2409 /* peripheral 12v precharge */
2410 2410 case SYS_V12_P_PCH_INDEX:
2411 2411 cmn_err(level, "%s %s", ft_str_table[FT_V12_P_PCH], s);
2412 2412 if (ps_ok) {
2413 2413 clear_fault(0, FT_V12_P_PCH, FT_SYSTEM);
2414 2414 } else {
2415 2415 reg_fault(0, FT_V12_P_PCH, FT_SYSTEM);
2416 2416 }
2417 2417 break;
2418 2418
2419 2419 /* 3.3v precharge */
2420 2420 case SYS_V3_PCH_INDEX:
2421 2421 cmn_err(level, "%s %s", ft_str_table[FT_V3_PCH], s);
2422 2422 if (ps_ok) {
2423 2423 clear_fault(0, FT_V3_PCH, FT_SYSTEM);
2424 2424 } else {
2425 2425 reg_fault(0, FT_V3_PCH, FT_SYSTEM);
2426 2426 }
2427 2427 break;
2428 2428
2429 2429 /* 5v precharge */
2430 2430 case SYS_V5_PCH_INDEX:
2431 2431 cmn_err(level, "%s %s", ft_str_table[FT_V5_PCH], s);
2432 2432 if (ps_ok) {
2433 2433 clear_fault(0, FT_V5_PCH, FT_SYSTEM);
2434 2434 } else {
2435 2435 reg_fault(0, FT_V5_PCH, FT_SYSTEM);
2436 2436 }
2437 2437 break;
2438 2438
2439 2439 /* peripheral power supply fans */
2440 2440 case SYS_P_FAN_INDEX:
2441 2441 cmn_err(level, "%s %s", ft_str_table[FT_PPS_FAN], s);
2442 2442 if (ps_ok) {
2443 2443 clear_fault(0, FT_PPS_FAN, FT_SYSTEM);
2444 2444 } else {
2445 2445 reg_fault(0, FT_PPS_FAN, FT_SYSTEM);
2446 2446 }
2447 2447 break;
2448 2448 }
2449 2449 }
2450 2450
2451 2451 /*
2452 2452 * The timeout from ps_fail_handler() that simply re-triggers a check
2453 2453 * of the ps condition.
2454 2454 */
2455 2455 static void
2456 2456 ps_fail_retry(void *arg)
2457 2457 {
2458 2458 struct sysctrl_soft_state *softsp = arg;
2459 2459
2460 2460 ASSERT(softsp);
2461 2461
2462 2462 ddi_trigger_softintr(softsp->ps_fail_poll_id);
2463 2463 }
2464 2464
2465 2465 /*
2466 2466 * pps_fanfail_handler
2467 2467 *
2468 2468 * This routine is called from the high level handler.
2469 2469 */
2470 2470 static uint_t
2471 2471 pps_fanfail_handler(caddr_t arg)
2472 2472 {
2473 2473 struct sysctrl_soft_state *softsp = (struct sysctrl_soft_state *)arg;
2474 2474
2475 2475 ASSERT(softsp);
2476 2476
2477 2477 /* always check again in a bit by re-enabling the fan interrupt */
2478 2478 (void) timeout(pps_fanfail_retry, softsp, pps_fan_timeout_hz);
2479 2479
2480 2480 return (DDI_INTR_CLAIMED);
2481 2481 }
2482 2482
2483 2483 /*
2484 2484 * After a bit of waiting, we simply re-enable the interrupt to
2485 2485 * see if we get another one. The softintr triggered routine does
2486 2486 * the dirty work for us since it runs in the interrupt context.
2487 2487 */
2488 2488 static void
2489 2489 pps_fanfail_retry(void *arg)
2490 2490 {
2491 2491 struct sysctrl_soft_state *softsp = arg;
2492 2492
2493 2493 ASSERT(softsp);
2494 2494
2495 2495 ddi_trigger_softintr(softsp->pps_fan_high_id);
2496 2496 }
2497 2497
2498 2498 /*
2499 2499 * The other half of the retry handler run from the interrupt context
2500 2500 */
2501 2501 static uint_t
2502 2502 pps_fanfail_reenable(caddr_t arg)
2503 2503 {
2504 2504 struct sysctrl_soft_state *softsp = (struct sysctrl_soft_state *)arg;
2505 2505 uchar_t tmp_reg;
2506 2506
2507 2507 ASSERT(softsp);
2508 2508
2509 2509 mutex_enter(&softsp->csr_mutex);
2510 2510
2511 2511 /*
2512 2512 * re-initialize the bit field for all pps fans to assumed good.
2513 2513 * If the fans are still bad, we're going to get an immediate system
2514 2514 * interrupt which will put the correct state back anyway.
2515 2515 *
2516 2516 * NOTE: the polling routines that use this state understand the
2517 2517 * pulse resulting from above...
2518 2518 */
2519 2519 softsp->pps_fan_saved = SYS_AC_FAN_OK | SYS_KEYSW_FAN_OK;
2520 2520
2521 2521 *(softsp->csr) |= SYS_PPS_FAN_FAIL_EN;
2522 2522 tmp_reg = *(softsp->csr);
2523 2523 #ifdef lint
2524 2524 tmp_reg = tmp_reg;
2525 2525 #endif
2526 2526 mutex_exit(&softsp->csr_mutex);
2527 2527
2528 2528 return (DDI_INTR_CLAIMED);
2529 2529 }
2530 2530
2531 2531 /*
2532 2532 *
2533 2533 * Poll the hardware shadow state to determine the pps fan status.
2534 2534 * The shadow state is maintained by the system_high handler and its
2535 2535 * associated pps_* functions (above).
2536 2536 *
2537 2537 * There is a short time interval where the shadow state is pulsed to
2538 2538 * the OK state even when the fans are bad. However, this polling
2539 2539 * routine has some built in hysteresis to filter out those _normal_
2540 2540 * events.
2541 2541 */
2542 2542 static void
2543 2543 pps_fan_poll(void *arg)
2544 2544 {
2545 2545 struct sysctrl_soft_state *softsp = arg;
2546 2546 int i;
2547 2547
2548 2548 ASSERT(softsp);
2549 2549
2550 2550 for (i = 0; i < SYS_PPS_FAN_COUNT; i++) {
2551 2551 int fanfail = FALSE;
2552 2552
2553 2553 /* determine fan status */
2554 2554 switch (i) {
2555 2555 case RACK:
2556 2556 fanfail = softsp->pps_fan_saved & SYS_RACK_FANFAIL;
2557 2557 break;
2558 2558
2559 2559 case AC:
2560 2560 /*
2561 2561 * Don't bother polling the AC fan on 4 and 5 slot
2562 2562 * systems.
2563 2563 * Rather, it is handled by the power supply loop.
2564 2564 */
2565 2565 fanfail = !(IS4SLOT(softsp->nslots) ||
2566 2566 IS5SLOT(softsp->nslots)) &&
2567 2567 !(softsp->pps_fan_saved & SYS_AC_FAN_OK);
2568 2568 break;
2569 2569
2570 2570 case KEYSW:
2571 2571 /*
2572 2572 * This signal is not usable if aux5v is missing
2573 2573 * so we will synthesize a failed fan when aux5v
2574 2574 * fails or when pps0 is out.
2575 2575 * The 4 and 5 slot systems behave the same.
2576 2576 */
2577 2577 fanfail = (!(IS4SLOT(softsp->nslots) ||
2578 2578 IS5SLOT(softsp->nslots)) &&
2579 2579 (softsp->ps_stats[SYS_V5_AUX_INDEX].dcshadow !=
2580 2580 PS_OK)) ||
2581 2581 !(softsp->pps_fan_saved & SYS_KEYSW_FAN_OK);
2582 2582 break;
2583 2583
2584 2584 }
2585 2585
2586 2586 /* is the fan bad? */
2587 2587 if (fanfail) {
2588 2588
2589 2589 /* is this condition different than we know? */
2590 2590 if (softsp->pps_fan_state_count[i] == 0) {
2591 2591
2592 2592 /* log the change to failed */
2593 2593 pps_fan_state_change(softsp, i, FALSE);
2594 2594 }
2595 2595
2596 2596 /* always restart the fan OK counter */
2597 2597 softsp->pps_fan_state_count[i] = PPS_FROM_FAIL_TICKS;
2598 2598 } else {
2599 2599
2600 2600 /* do we currently know the fan is bad? */
2601 2601 if (softsp->pps_fan_state_count[i]) {
2602 2602
2603 2603 /* yes, but has it been stable? */
2604 2604 if (--softsp->pps_fan_state_count[i] == 0) {
2605 2605
2606 2606 /* log the change to OK */
2607 2607 pps_fan_state_change(softsp, i, TRUE);
2608 2608 }
2609 2609 }
2610 2610 }
2611 2611 }
2612 2612
2613 2613 /* always check again in a bit by re-enabling the fan interrupt */
2614 2614 (void) timeout(pps_fan_poll, softsp, pps_fan_timeout_hz);
2615 2615 }
2616 2616
2617 2617 /*
2618 2618 * pps_fan_state_change()
2619 2619 *
2620 2620 * Log the changed fan condition and update the external status.
2621 2621 */
2622 2622 static void
2623 2623 pps_fan_state_change(struct sysctrl_soft_state *softsp, int index, int fan_ok)
2624 2624 {
2625 2625 char *fan_type;
2626 2626 char *state = fan_ok ? "fans OK" : "fan failure detected";
2627 2627
2628 2628 switch (index) {
2629 2629 case RACK:
2630 2630 /* 4 and 5 slot systems behave the same */
2631 2631 fan_type = (IS4SLOT(softsp->nslots) ||
2632 2632 IS5SLOT(softsp->nslots)) ?
2633 2633 "Disk Drive" : "Rack Exhaust";
2634 2634 if (fan_ok) {
2635 2635 softsp->pps_fan_external_state &= ~SYS_RACK_FANFAIL;
2636 2636 clear_fault(0, (IS4SLOT(softsp->nslots) ||
2637 2637 IS5SLOT(softsp->nslots)) ? FT_DSK_FAN :
2638 2638 FT_RACK_EXH, FT_SYSTEM);
2639 2639 } else {
2640 2640 softsp->pps_fan_external_state |= SYS_RACK_FANFAIL;
2641 2641 reg_fault(0, (IS4SLOT(softsp->nslots) ||
2642 2642 IS5SLOT(softsp->nslots)) ? FT_DSK_FAN :
2643 2643 FT_RACK_EXH, FT_SYSTEM);
2644 2644 }
2645 2645 break;
2646 2646
2647 2647 case AC:
2648 2648 fan_type = "AC Box";
2649 2649 if (fan_ok) {
2650 2650 softsp->pps_fan_external_state |= SYS_AC_FAN_OK;
2651 2651 clear_fault(0, FT_AC_FAN, FT_SYSTEM);
2652 2652 } else {
2653 2653 softsp->pps_fan_external_state &= ~SYS_AC_FAN_OK;
2654 2654 reg_fault(0, FT_AC_FAN, FT_SYSTEM);
2655 2655 }
2656 2656 break;
2657 2657
2658 2658 case KEYSW:
2659 2659 fan_type = "Keyswitch";
2660 2660 if (fan_ok) {
2661 2661 softsp->pps_fan_external_state |= SYS_KEYSW_FAN_OK;
2662 2662 clear_fault(0, FT_KEYSW_FAN, FT_SYSTEM);
2663 2663 } else {
2664 2664 softsp->pps_fan_external_state &= ~SYS_KEYSW_FAN_OK;
2665 2665 reg_fault(0, FT_KEYSW_FAN, FT_SYSTEM);
2666 2666 }
2667 2667 break;
2668 2668 default:
2669 2669 fan_type = "[invalid fan id]";
2670 2670 break;
2671 2671 }
2672 2672
2673 2673 /* now log the state change */
2674 2674 cmn_err(fan_ok ? CE_NOTE : CE_WARN, "%s %s", fan_type, state);
2675 2675 }
2676 2676
2677 2677 static uint_t
2678 2678 bd_insert_handler(caddr_t arg)
2679 2679 {
2680 2680 struct sysctrl_soft_state *softsp = (struct sysctrl_soft_state *)arg;
2681 2681
2682 2682 ASSERT(softsp);
2683 2683
2684 2684 DPRINTF(SYSCTRL_ATTACH_DEBUG, ("bd_insert_handler()"));
2685 2685
2686 2686 (void) timeout(bd_insert_timeout, softsp, bd_insert_delay_hz);
2687 2687
2688 2688 return (DDI_INTR_CLAIMED);
2689 2689 }
2690 2690
2691 2691 void
2692 2692 bd_remove_poll(struct sysctrl_soft_state *softsp)
2693 2693 {
2694 2694 ASSERT(fhc_bdlist_locked());
2695 2695
2696 2696 if (!bd_remove_to_id) {
2697 2697 bd_remove_to_id = timeout(bd_remove_timeout, softsp,
2698 2698 bd_remove_timeout_hz);
2699 2699 } else {
2700 2700 DPRINTF(SYSCTRL_ATTACH_DEBUG,
2701 2701 ("bd_remove_poll ignoring start request"));
2702 2702 }
2703 2703 }
2704 2704
2705 2705 /*
2706 2706 * bd_insert_timeout()
2707 2707 *
2708 2708 * This routine handles the board insert interrupt. It is called from a
2709 2709 * timeout so that it does not run at interrupt level. The main job
2710 2710 * of this routine is to find hotplugged boards and de-assert the
2711 2711 * board insert interrupt coming from the board. For hotplug phase I,
2712 2712 * the routine also powers down the board.
2713 2713 * JTAG scan is used to find boards which have been inserted.
2714 2714 * All other control of the boards is also done by JTAG scan.
2715 2715 */
2716 2716 static void
2717 2717 bd_insert_timeout(void *arg)
2718 2718 {
2719 2719 struct sysctrl_soft_state *softsp = arg;
2720 2720 int found;
2721 2721
2722 2722 ASSERT(softsp);
2723 2723
2724 2724 if (sysctrl_hotplug_disabled) {
2725 2725 sysc_policy_update(softsp, NULL, SYSC_EVT_BD_HP_DISABLED);
2726 2726 } else {
2727 2727 /*
2728 2728 * Lock the board list mutex. Keep it locked until all work
2729 2729 * is done.
2730 2730 */
2731 2731 (void) fhc_bdlist_lock(-1);
2732 2732
2733 2733 found = fhc_bd_insert_scan();
2734 2734
2735 2735 if (found) {
2736 2736 DPRINTF(SYSCTRL_ATTACH_DEBUG,
2737 2737 ("bd_insert_timeout starting bd_remove_poll()"));
2738 2738 bd_remove_poll(softsp);
2739 2739 }
2740 2740
2741 2741 fhc_bdlist_unlock();
2742 2742 }
2743 2743
2744 2744 /*
2745 2745 * Enable interrupts.
2746 2746 */
2747 2747 ddi_trigger_softintr(softsp->sbrd_gone_id);
2748 2748 }
2749 2749
2750 2750 static void
2751 2751 bd_remove_timeout(void *arg)
2752 2752 {
2753 2753 struct sysctrl_soft_state *softsp = arg;
2754 2754 int keep_polling;
2755 2755
2756 2756 ASSERT(softsp);
2757 2757
2758 2758 /*
2759 2759 * Lock the board list mutex. Keep it locked until all work
2760 2760 * is done.
2761 2761 */
2762 2762 (void) fhc_bdlist_lock(-1);
2763 2763
2764 2764 bd_remove_to_id = 0; /* delete our timeout ID */
2765 2765
2766 2766 keep_polling = fhc_bd_remove_scan();
2767 2767
2768 2768 if (keep_polling) {
2769 2769 bd_remove_poll(softsp);
2770 2770 } else {
2771 2771 DPRINTF(SYSCTRL_ATTACH_DEBUG, ("exiting bd_remove_poll."));
2772 2772 }
2773 2773
2774 2774 fhc_bdlist_unlock();
2775 2775 }
2776 2776
2777 2777 static uint_t
2778 2778 bd_insert_normal(caddr_t arg)
2779 2779 {
2780 2780 struct sysctrl_soft_state *softsp = (struct sysctrl_soft_state *)arg;
2781 2781 uchar_t tmp_reg;
2782 2782
2783 2783 ASSERT(softsp);
2784 2784
2785 2785 /* has the condition been removed? */
2786 2786 /* XXX add deglitch state machine here */
2787 2787 if (!(*(softsp->status1) & SYS_NOT_BRD_PRES)) {
2788 2788 /* check again in a few */
2789 2789 (void) timeout(bd_insert_timeout, softsp, bd_insert_retry_hz);
2790 2790 } else {
2791 2791 /* Turn on the enable bit for this interrupt */
2792 2792 mutex_enter(&softsp->csr_mutex);
2793 2793 *(softsp->csr) |= SYS_SBRD_PRES_EN;
2794 2794 /* flush the hardware store buffer */
2795 2795 tmp_reg = *(softsp->csr);
2796 2796 #ifdef lint
2797 2797 tmp_reg = tmp_reg;
2798 2798 #endif
2799 2799 mutex_exit(&softsp->csr_mutex);
2800 2800 }
2801 2801
2802 2802 return (DDI_INTR_CLAIMED);
2803 2803 }
2804 2804
2805 2805 /*
2806 2806 * blink LED handler.
2807 2807 *
2808 2808 * The actual bit manipulation needs to occur at interrupt level
2809 2809 * because we need access to the CSR with its CSR mutex
2810 2810 */
2811 2811 static uint_t
2812 2812 blink_led_handler(caddr_t arg)
2813 2813 {
2814 2814 struct sysctrl_soft_state *softsp = (struct sysctrl_soft_state *)arg;
2815 2815 uchar_t tmp_reg;
2816 2816
2817 2817 ASSERT(softsp);
2818 2818
2819 2819 mutex_enter(&softsp->csr_mutex);
2820 2820
2821 2821 /*
2822 2822 * XXX - The lock for the sys_led is not held here. If more
2823 2823 * complicated tasks are done with the System LED, then
2824 2824 * locking should be done here.
2825 2825 */
2826 2826
2827 2827 /* read the hardware register. */
2828 2828 tmp_reg = *(softsp->csr);
2829 2829
2830 2830 /* Only turn on the OS System LED bit if the softsp state is on. */
2831 2831 if (softsp->sys_led) {
2832 2832 tmp_reg |= SYS_LED_RIGHT;
2833 2833 } else {
2834 2834 tmp_reg &= ~SYS_LED_RIGHT;
2835 2835 }
2836 2836
2837 2837 /* Turn on the yellow LED if system fault status is set. */
2838 2838 if (softsp->sys_fault) {
2839 2839 tmp_reg |= SYS_LED_MID;
2840 2840 } else {
2841 2841 tmp_reg &= ~SYS_LED_MID;
2842 2842 }
2843 2843
2844 2844 /* write to the hardware register */
2845 2845 *(softsp->csr) = tmp_reg;
2846 2846
2847 2847 /* flush the hardware store buffer */
2848 2848 tmp_reg = *(softsp->csr);
2849 2849 #ifdef lint
2850 2850 tmp_reg = tmp_reg;
2851 2851 #endif
2852 2852 mutex_exit(&softsp->csr_mutex);
2853 2853
2854 2854 (void) timeout(blink_led_timeout, softsp, blink_led_timeout_hz);
2855 2855
2856 2856 return (DDI_INTR_CLAIMED);
2857 2857 }
2858 2858
2859 2859 /*
2860 2860 * simply re-trigger the interrupt handler on led timeout
2861 2861 */
2862 2862 static void
2863 2863 blink_led_timeout(void *arg)
2864 2864 {
2865 2865 struct sysctrl_soft_state *softsp = arg;
2866 2866 int led_state;
2867 2867
2868 2868 ASSERT(softsp);
2869 2869
2870 2870 /*
2871 2871 * Process the system fault list here. This is where the driver
2872 2872 * must decide what yellow LEDs to turn on if any. The fault
2873 2873 * list is walked and each fhc_list entry is updated with it's
2874 2874 * yellow LED status. This info is used later by the routine
2875 2875 * toggle_board_green_leds().
2876 2876 *
2877 2877 * The variable system_fault is non-zero if any non-
2878 2878 * suppressed faults are found in the system.
2879 2879 */
2880 2880 softsp->sys_fault = process_fault_list();
2881 2881
2882 2882 /* blink the system board OS LED */
2883 2883 mutex_enter(&softsp->sys_led_lock);
2884 2884 softsp->sys_led = !softsp->sys_led;
2885 2885 led_state = softsp->sys_led;
2886 2886 mutex_exit(&softsp->sys_led_lock);
2887 2887
2888 2888 toggle_board_green_leds(led_state);
2889 2889
2890 2890 ddi_trigger_softintr(softsp->blink_led_id);
2891 2891 }
2892 2892
2893 2893 void
2894 2894 toggle_board_green_leds(int led_state)
2895 2895 {
2896 2896 fhc_bd_t *list;
2897 2897
2898 2898 (void) fhc_bdlist_lock(-1);
2899 2899 for (list = fhc_bd_first(); list; list = fhc_bd_next(list)) {
2900 2900 uint_t value = 0;
2901 2901
2902 2902 if (list->sc.in_transition ||
2903 2903 (list->sc.rstate != SYSC_CFGA_RSTATE_CONNECTED))
2904 2904 continue;
2905 2905
2906 2906 ASSERT(list->sc.type != CLOCK_BOARD);
2907 2907 ASSERT(list->sc.type != DISK_BOARD);
2908 2908 ASSERT(list->softsp);
2909 2909
2910 2910 if ((list->sc.ostate == SYSC_CFGA_OSTATE_CONFIGURED) &&
2911 2911 led_state)
2912 2912 value |= FHC_LED_RIGHT;
2913 2913
2914 2914 if (list->fault)
2915 2915 value |= FHC_LED_MID;
2916 2916 else
2917 2917 value &= ~FHC_LED_MID;
2918 2918
2919 2919 update_board_leds(list, FHC_LED_RIGHT|FHC_LED_MID, value);
2920 2920 }
2921 2921 fhc_bdlist_unlock();
2922 2922 }
2923 2923
2924 2924 /*
2925 2925 * timestamp an AC power failure in nvram
2926 2926 */
2927 2927 static void
2928 2928 nvram_update_powerfail(struct sysctrl_soft_state *softsp)
2929 2929 {
2930 2930 char buf[80];
2931 2931 int len = 0;
2932 2932
2933 2933 numtos(gethrestime_sec(), buf);
2934 2934
2935 2935 if (softsp->options_nodeid) {
2936 2936 len = prom_setprop(softsp->options_nodeid, "powerfail-time",
2937 2937 buf, strlen(buf)+1);
2938 2938 }
2939 2939
2940 2940 if (len <= 0) {
2941 2941 cmn_err(CE_WARN, "sysctrl%d: failed to set powerfail-time "
2942 2942 "to %s\n", ddi_get_instance(softsp->dip), buf);
2943 2943 }
2944 2944 }
2945 2945
2946 2946 void
2947 2947 sysctrl_add_kstats(struct sysctrl_soft_state *softsp)
2948 2948 {
2949 2949 struct kstat *ksp; /* Generic sysctrl kstats */
2950 2950 struct kstat *pksp; /* Power Supply kstat */
2951 2951 struct kstat *tksp; /* Sysctrl temperatrure kstat */
2952 2952 struct kstat *ttsp; /* Sysctrl temperature test kstat */
2953 2953
2954 2954 if ((ksp = kstat_create("unix", ddi_get_instance(softsp->dip),
2955 2955 SYSCTRL_KSTAT_NAME, "misc", KSTAT_TYPE_NAMED,
2956 2956 sizeof (struct sysctrl_kstat) / sizeof (kstat_named_t),
2957 2957 KSTAT_FLAG_PERSISTENT)) == NULL) {
2958 2958 cmn_err(CE_WARN, "sysctrl%d: kstat_create failed",
2959 2959 ddi_get_instance(softsp->dip));
2960 2960 } else {
2961 2961 struct sysctrl_kstat *sysksp;
2962 2962
2963 2963 sysksp = (struct sysctrl_kstat *)(ksp->ks_data);
2964 2964
2965 2965 /* now init the named kstats */
2966 2966 kstat_named_init(&sysksp->csr, CSR_KSTAT_NAMED,
2967 2967 KSTAT_DATA_CHAR);
2968 2968
2969 2969 kstat_named_init(&sysksp->status1, STAT1_KSTAT_NAMED,
2970 2970 KSTAT_DATA_CHAR);
2971 2971
2972 2972 kstat_named_init(&sysksp->status2, STAT2_KSTAT_NAMED,
2973 2973 KSTAT_DATA_CHAR);
2974 2974
2975 2975 kstat_named_init(&sysksp->clk_freq2, CLK_FREQ2_KSTAT_NAMED,
2976 2976 KSTAT_DATA_CHAR);
2977 2977
2978 2978 kstat_named_init(&sysksp->fan_status, FAN_KSTAT_NAMED,
2979 2979 KSTAT_DATA_CHAR);
2980 2980
2981 2981 kstat_named_init(&sysksp->key_status, KEY_KSTAT_NAMED,
2982 2982 KSTAT_DATA_CHAR);
2983 2983
2984 2984 kstat_named_init(&sysksp->power_state, POWER_KSTAT_NAMED,
2985 2985 KSTAT_DATA_INT32);
2986 2986
2987 2987 kstat_named_init(&sysksp->clk_ver, CLK_VER_KSTAT_NAME,
2988 2988 KSTAT_DATA_CHAR);
2989 2989
2990 2990 ksp->ks_update = sysctrl_kstat_update;
2991 2991 ksp->ks_private = (void *)softsp;
2992 2992 kstat_install(ksp);
2993 2993 }
2994 2994
2995 2995 if ((tksp = kstat_create("unix", CLOCK_BOARD_INDEX,
2996 2996 OVERTEMP_KSTAT_NAME, "misc", KSTAT_TYPE_RAW,
2997 2997 sizeof (struct temp_stats), KSTAT_FLAG_PERSISTENT)) == NULL) {
2998 2998 cmn_err(CE_WARN, "sysctrl%d: kstat_create failed",
2999 2999 ddi_get_instance(softsp->dip));
3000 3000 } else {
3001 3001 tksp->ks_update = overtemp_kstat_update;
3002 3002 tksp->ks_private = (void *)&softsp->tempstat;
3003 3003 kstat_install(tksp);
3004 3004 }
3005 3005
3006 3006 if ((ttsp = kstat_create("unix", CLOCK_BOARD_INDEX,
3007 3007 TEMP_OVERRIDE_KSTAT_NAME, "misc", KSTAT_TYPE_RAW, sizeof (short),
3008 3008 KSTAT_FLAG_PERSISTENT | KSTAT_FLAG_WRITABLE)) == NULL) {
3009 3009 cmn_err(CE_WARN, "sysctrl%d: kstat_create failed",
3010 3010 ddi_get_instance(softsp->dip));
3011 3011 } else {
3012 3012 ttsp->ks_update = temp_override_kstat_update;
3013 3013 ttsp->ks_private = (void *)&softsp->tempstat.override;
3014 3014 kstat_install(ttsp);
3015 3015 }
3016 3016
3017 3017 if ((pksp = kstat_create("unix", ddi_get_instance(softsp->dip),
3018 3018 PSSHAD_KSTAT_NAME, "misc", KSTAT_TYPE_RAW,
3019 3019 SYS_PS_COUNT, KSTAT_FLAG_PERSISTENT)) == NULL) {
3020 3020 cmn_err(CE_WARN, "sysctrl%d: kstat_create failed",
3021 3021 ddi_get_instance(softsp->dip));
3022 3022 } else {
3023 3023 pksp->ks_update = psstat_kstat_update;
3024 3024 pksp->ks_private = (void *)softsp;
3025 3025 kstat_install(pksp);
3026 3026 }
3027 3027 }
3028 3028
3029 3029 static int
3030 3030 sysctrl_kstat_update(kstat_t *ksp, int rw)
3031 3031 {
3032 3032 struct sysctrl_kstat *sysksp;
3033 3033 struct sysctrl_soft_state *softsp;
3034 3034
3035 3035 sysksp = (struct sysctrl_kstat *)(ksp->ks_data);
3036 3036 softsp = (struct sysctrl_soft_state *)(ksp->ks_private);
3037 3037
3038 3038 /* this is a read-only kstat. Exit on a write */
3039 3039
3040 3040 if (rw == KSTAT_WRITE) {
3041 3041 return (EACCES);
3042 3042 } else {
3043 3043 /*
3044 3044 * copy the current state of the hardware into the
3045 3045 * kstat structure.
3046 3046 */
3047 3047 sysksp->csr.value.c[0] = *(softsp->csr);
3048 3048 sysksp->status1.value.c[0] = *(softsp->status1);
3049 3049 sysksp->status2.value.c[0] = *(softsp->status2);
3050 3050 sysksp->clk_freq2.value.c[0] = *(softsp->clk_freq2);
3051 3051
3052 3052 sysksp->fan_status.value.c[0] = softsp->pps_fan_external_state;
3053 3053 sysksp->key_status.value.c[0] = softsp->key_shadow;
3054 3054 sysksp->power_state.value.i32 = softsp->power_state;
3055 3055
3056 3056 /*
3057 3057 * non-existence of the clock version register returns the
3058 3058 * value 0xff when the hardware register location is read
3059 3059 */
3060 3060 if (softsp->clk_ver != NULL)
3061 3061 sysksp->clk_ver.value.c[0] = *(softsp->clk_ver);
3062 3062 else
3063 3063 sysksp->clk_ver.value.c[0] = (char)0xff;
3064 3064 }
3065 3065 return (0);
3066 3066 }
3067 3067
3068 3068 static int
3069 3069 psstat_kstat_update(kstat_t *ksp, int rw)
3070 3070 {
3071 3071 struct sysctrl_soft_state *softsp;
3072 3072 uchar_t *ptr = (uchar_t *)(ksp->ks_data);
3073 3073 int ps;
3074 3074
3075 3075 softsp = (struct sysctrl_soft_state *)(ksp->ks_private);
3076 3076
3077 3077 if (rw == KSTAT_WRITE) {
3078 3078 return (EACCES);
3079 3079 } else {
3080 3080 for (ps = 0; ps < SYS_PS_COUNT; ps++) {
3081 3081 *ptr++ = softsp->ps_stats[ps].dcshadow;
3082 3082 }
3083 3083 }
3084 3084 return (0);
3085 3085 }
3086 3086
3087 3087 static void
3088 3088 sysctrl_thread_wakeup(void *arg)
3089 3089 {
3090 3090 int type = (int)(uintptr_t)arg;
3091 3091
3092 3092 /*
3093 3093 * grab mutex to guarantee that our wakeup call
3094 3094 * arrives after we go to sleep -- so we can't sleep forever.
3095 3095 */
3096 3096 mutex_enter(&sslist_mutex);
3097 3097 switch (type) {
3098 3098 case OVERTEMP_POLL:
3099 3099 cv_signal(&overtemp_cv);
3100 3100 break;
3101 3101 case KEYSWITCH_POLL:
3102 3102 cv_signal(&keyswitch_cv);
3103 3103 break;
3104 3104 default:
3105 3105 cmn_err(CE_WARN, "sysctrl: invalid type %d to wakeup\n", type);
3106 3106 break;
3107 3107 }
3108 3108 mutex_exit(&sslist_mutex);
3109 3109 }
3110 3110
3111 3111 static void
3112 3112 sysctrl_overtemp_poll(void)
3113 3113 {
3114 3114 struct sysctrl_soft_state *list;
3115 3115 callb_cpr_t cprinfo;
3116 3116
3117 3117 CALLB_CPR_INIT(&cprinfo, &sslist_mutex, callb_generic_cpr, "overtemp");
3118 3118
3119 3119 /* The overtemp data structures are protected by a mutex. */
3120 3120 mutex_enter(&sslist_mutex);
3121 3121
3122 3122 while (sysctrl_do_overtemp_thread) {
3123 3123
3124 3124 for (list = sys_list; list != NULL; list = list->next) {
3125 3125 if (list->temp_reg != NULL) {
3126 3126 update_temp(list->pdip, &list->tempstat,
3127 3127 *(list->temp_reg));
3128 3128 }
3129 3129 }
3130 3130
3131 3131 CALLB_CPR_SAFE_BEGIN(&cprinfo);
3132 3132
3133 3133 /* now have this thread sleep for a while */
3134 3134 (void) timeout(sysctrl_thread_wakeup, (void *)OVERTEMP_POLL,
3135 3135 overtemp_timeout_hz);
3136 3136
3137 3137 cv_wait(&overtemp_cv, &sslist_mutex);
3138 3138
3139 3139 CALLB_CPR_SAFE_END(&cprinfo, &sslist_mutex);
3140 3140 }
3141 3141 CALLB_CPR_EXIT(&cprinfo);
3142 3142 thread_exit();
3143 3143 /* NOTREACHED */
3144 3144 }
3145 3145
3146 3146 static void
3147 3147 sysctrl_keyswitch_poll(void)
3148 3148 {
3149 3149 struct sysctrl_soft_state *list;
3150 3150 callb_cpr_t cprinfo;
3151 3151
3152 3152 CALLB_CPR_INIT(&cprinfo, &sslist_mutex, callb_generic_cpr, "keyswitch");
3153 3153
3154 3154 /* The keyswitch data strcutures are protected by a mutex. */
3155 3155 mutex_enter(&sslist_mutex);
3156 3156
3157 3157 while (sysctrl_do_keyswitch_thread) {
3158 3158
3159 3159 for (list = sys_list; list != NULL; list = list->next) {
3160 3160 if (list->status1 != NULL)
3161 3161 update_key_state(list);
3162 3162 }
3163 3163
3164 3164 CALLB_CPR_SAFE_BEGIN(&cprinfo);
3165 3165
3166 3166 /* now have this thread sleep for a while */
3167 3167 (void) timeout(sysctrl_thread_wakeup, (void *)KEYSWITCH_POLL,
3168 3168 keyswitch_timeout_hz);
3169 3169
3170 3170 cv_wait(&keyswitch_cv, &sslist_mutex);
3171 3171
3172 3172 CALLB_CPR_SAFE_END(&cprinfo, &sslist_mutex);
3173 3173 }
3174 3174 CALLB_CPR_EXIT(&cprinfo);
3175 3175 thread_exit();
3176 3176 /* NOTREACHED */
3177 3177 }
3178 3178
3179 3179 /*
3180 3180 * check the key switch position for state changes
3181 3181 */
3182 3182 static void
3183 3183 update_key_state(struct sysctrl_soft_state *list)
3184 3184 {
3185 3185 enum keyswitch_state key;
3186 3186
3187 3187 /*
3188 3188 * snapshot current hardware key position
3189 3189 */
3190 3190 if (*(list->status1) & SYS_NOT_SECURE)
3191 3191 key = KEY_NOT_SECURE;
3192 3192 else
3193 3193 key = KEY_SECURE;
3194 3194
3195 3195 /*
3196 3196 * check for state transition
3197 3197 */
3198 3198 if (key != list->key_shadow) {
3199 3199
3200 3200 /*
3201 3201 * handle state transition
3202 3202 */
3203 3203 switch (list->key_shadow) {
3204 3204 case KEY_BOOT:
3205 3205 cmn_err(CE_CONT, "?sysctrl%d: Key switch is%sin the "
3206 3206 "secure position\n", ddi_get_instance(list->dip),
3207 3207 (key == KEY_SECURE) ? " " : " not ");
3208 3208 list->key_shadow = key;
3209 3209 break;
3210 3210 case KEY_SECURE:
3211 3211 case KEY_NOT_SECURE:
3212 3212 cmn_err(CE_NOTE, "sysctrl%d: Key switch has changed"
3213 3213 " to the %s position",
3214 3214 ddi_get_instance(list->dip),
3215 3215 (key == KEY_SECURE) ? "secure" : "not-secure");
3216 3216 list->key_shadow = key;
3217 3217 break;
3218 3218 default:
3219 3219 cmn_err(CE_CONT,
3220 3220 "?sysctrl%d: Key switch is in an unknown position,"
3221 3221 "treated as being in the %s position\n",
3222 3222 ddi_get_instance(list->dip),
3223 3223 (list->key_shadow == KEY_SECURE) ?
3224 3224 "secure" : "not-secure");
3225 3225 break;
3226 3226 }
3227 3227 }
3228 3228 }
3229 3229
3230 3230 /*
3231 3231 * consider key switch position when handling an abort sequence
3232 3232 */
3233 3233 static void
3234 3234 sysctrl_abort_seq_handler(char *msg)
3235 3235 {
3236 3236 struct sysctrl_soft_state *list;
3237 3237 uint_t secure = 0;
3238 3238 char buf[64], inst[4];
3239 3239
3240 3240
3241 3241 /*
3242 3242 * if any of the key switch positions are secure,
3243 3243 * then disallow entry to the prom/debugger
3244 3244 */
3245 3245 mutex_enter(&sslist_mutex);
3246 3246 buf[0] = (char)0;
3247 3247 for (list = sys_list; list != NULL; list = list->next) {
3248 3248 if (!(*(list->status1) & SYS_NOT_SECURE)) {
3249 3249 if (secure++)
3250 3250 (void) strcat(buf, ",");
3251 3251 /*
3252 3252 * XXX: later, replace instance number with nodeid
3253 3253 */
3254 3254 (void) sprintf(inst, "%d", ddi_get_instance(list->dip));
3255 3255 (void) strcat(buf, inst);
3256 3256 }
3257 3257 }
3258 3258 mutex_exit(&sslist_mutex);
3259 3259
3260 3260 if (secure) {
3261 3261 cmn_err(CE_CONT,
3262 3262 "!sysctrl(%s): ignoring debug enter sequence\n", buf);
3263 3263 } else {
3264 3264 cmn_err(CE_CONT, "!sysctrl: allowing debug enter\n");
3265 3265 debug_enter(msg);
3266 3266 }
3267 3267 }
3268 3268
3269 3269 #define TABLE_END 0xFF
3270 3270
3271 3271 struct uart_cmd {
3272 3272 uchar_t reg;
3273 3273 uchar_t data;
3274 3274 };
3275 3275
3276 3276 /*
3277 3277 * Time constant defined by this formula:
3278 3278 * ((4915200/32)/(baud) -2)
3279 3279 */
3280 3280
3281 3281 struct uart_cmd uart_table[] = {
3282 3282 { 0x09, 0xc0 }, /* Force hardware reset */
3283 3283 { 0x04, 0x46 }, /* X16 clock mode, 1 stop bit/char, no parity */
3284 3284 { 0x03, 0xc0 }, /* Rx is 8 bits/char */
3285 3285 { 0x05, 0xe2 }, /* DTR, Tx is 8 bits/char, RTS */
3286 3286 { 0x09, 0x02 }, /* No vector returned on interrupt */
3287 3287 { 0x0b, 0x55 }, /* Rx Clock = Tx Clock = BR generator = ~TRxC OUT */
3288 3288 { 0x0c, 0x0e }, /* Time Constant = 0x000e for 9600 baud */
3289 3289 { 0x0d, 0x00 }, /* High byte of time constant */
3290 3290 { 0x0e, 0x02 }, /* BR generator comes from Z-SCC's PCLK input */
3291 3291 { 0x03, 0xc1 }, /* Rx is 8 bits/char, Rx is enabled */
3292 3292 { 0x05, 0xea }, /* DTR, Tx is 8 bits/char, Tx is enabled, RTS */
3293 3293 { 0x0e, 0x03 }, /* BR comes from PCLK, BR generator is enabled */
3294 3294 { 0x00, 0x30 }, /* Error reset */
3295 3295 { 0x00, 0x30 }, /* Error reset */
3296 3296 { 0x00, 0x10 }, /* external status reset */
3297 3297 { 0x03, 0xc1 }, /* Rx is 8 bits/char, Rx is enabled */
3298 3298 { TABLE_END, 0x0 }
3299 3299 };
3300 3300
3301 3301 static void
3302 3302 init_remote_console_uart(struct sysctrl_soft_state *softsp)
3303 3303 {
3304 3304 int i = 0;
3305 3305
3306 3306 /*
3307 3307 * Serial chip expects software to write to the control
3308 3308 * register first with the desired register number. Then
3309 3309 * write to the control register with the desired data.
3310 3310 * So walk thru table writing the register/data pairs to
3311 3311 * the serial port chip.
3312 3312 */
3313 3313 while (uart_table[i].reg != TABLE_END) {
3314 3314 *(softsp->rcons_ctl) = uart_table[i].reg;
3315 3315 *(softsp->rcons_ctl) = uart_table[i].data;
3316 3316 i++;
3317 3317 }
3318 3318 }
3319 3319
3320 3320 /*
3321 3321 * return the slot information of the system
3322 3322 *
3323 3323 * function take a sysctrl_soft_state, so it's ready for sunfire+
3324 3324 * change which requires 2 registers to decide the system type.
3325 3325 */
3326 3326 static void
3327 3327 sysc_slot_info(int nslots, int *start, int *limit, int *incr)
3328 3328 {
3329 3329 switch (nslots) {
3330 3330 case 8:
3331 3331 *start = 0;
3332 3332 *limit = 8;
3333 3333 *incr = 1;
3334 3334 break;
3335 3335 case 5:
3336 3336 *start = 1;
3337 3337 *limit = 10;
3338 3338 *incr = 2;
3339 3339 break;
3340 3340 case 4:
3341 3341 *start = 1;
3342 3342 *limit = 8;
3343 3343 *incr = 2;
3344 3344 break;
3345 3345 case 0:
3346 3346 case 16:
3347 3347 default:
3348 3348 *start = 0;
3349 3349 *limit = 16;
3350 3350 *incr = 1;
3351 3351 break;
3352 3352 }
3353 3353 }
3354 3354
3355 3355 /*
3356 3356 * reinitialize the Remote Console on the clock board
3357 3357 *
3358 3358 * with V5_AUX power outage the Remote Console ends up in
3359 3359 * unknown state and has to be reinitilized if it was enabled
3360 3360 * initially.
3361 3361 */
3362 3362 static void
3363 3363 rcons_reinit(struct sysctrl_soft_state *softsp)
3364 3364 {
3365 3365 uchar_t tmp_reg;
3366 3366
3367 3367 if (!(softsp->rcons_ctl))
3368 3368 /*
3369 3369 * There is no OBP register set for the remote console UART,
3370 3370 * so offset from the last register set, the misc register
3371 3371 * set, in order to map in the remote console UART.
3372 3372 */
3373 3373 if (ddi_map_regs(softsp->dip, 1, (caddr_t *)&softsp->rcons_ctl,
3374 3374 RMT_CONS_OFFSET, RMT_CONS_LEN)) {
3375 3375 cmn_err(CE_WARN, "Unable to reinitialize "
3376 3376 "remote console.");
3377 3377 return;
3378 3378 }
3379 3379
3380 3380
3381 3381 /* Disable the remote console reset control bits. */
3382 3382 *(softsp->clk_freq2) &= ~RCONS_UART_EN;
3383 3383
3384 3384 /* flush the hardware buffers */
3385 3385 tmp_reg = *(softsp->csr);
3386 3386
3387 3387 /*
3388 3388 * Program the UART to watch ttya console.
3389 3389 */
3390 3390 init_remote_console_uart(softsp);
3391 3391
3392 3392 /* Now enable the remote console reset control bits. */
3393 3393 *(softsp->clk_freq2) |= RCONS_UART_EN;
3394 3394
3395 3395 /* flush the hardware buffers */
3396 3396 tmp_reg = *(softsp->csr);
3397 3397
3398 3398 /* print some info for user to watch */
3399 3399 cmn_err(CE_NOTE, "Remote console reinitialized");
3400 3400 #ifdef lint
3401 3401 tmp_reg = tmp_reg;
3402 3402 #endif
3403 3403 }
↓ open down ↓ |
2948 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX