1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 * Copyright (c) 2019 Peter Tribble.
26 */
27
28 /*
29 * Netra ct800 and Netra ct400 (MonteCarlo/Tonga)
30 * System Controller and Status Boards STREAMS driver.
31 *
32 * This driver handles all communications with the Netra ct400 and ct800
33 * System Controller Boards.
34 * I/O to the SCB is through the PCF8584 I2C controller.
35 * The SCB I2C interface and driver interface are provided by the
36 * Xilinx XCS40XL.
37 *
38 * N.B.: The design choice of using STREAMS was dictated because
39 * the original system monitor card had to multiplex 2 pcf8574's
40 * as one device.
41 */
42
43 #include <sys/types.h>
44 #include <sys/param.h>
45 #include <sys/cred.h>
46 #include <sys/log.h>
47 #include <sys/uio.h>
48 #include <sys/stat.h>
49 #include <sys/vnode.h>
50 #include <sys/file.h>
51 #include <sys/open.h>
52 #include <sys/kmem.h>
53 #include <sys/kstat.h>
54 #include <sys/signal.h>
55
56 #include <sys/stream.h>
57 #include <sys/strsubr.h>
58 #include <sys/strsun.h>
59 #include <sys/poll.h>
60
61 #include <sys/debug.h>
62
63 #include <sys/conf.h>
64 #include <sys/ddi.h>
65 #include <sys/sunddi.h>
66 #include <sys/modctl.h>
67
68 #include <sys/i2c/misc/i2c_svc.h>
69
70 #include <sys/mct_topology.h>
71 #include <sys/netract_gen.h>
72 #include <sys/scsbioctl.h>
73 #include <sys/scsb.h>
74 #include <sys/scsb_cbi.h>
75
76 #include <sys/hotplug/hpctrl.h>
77 #include <sys/hsc.h>
78 #include <sys/hscimpl.h>
79
80 #define CPCI_HOTSWAP_SUPPORT
81
82 #define ALARM_CARD_ON_SLOT 1
83 #define SCSB_FRU_OP_GET_REG 1
84 #define SCSB_FRU_OP_SET_REGBIT 2
85 #define SCSB_FRU_OP_GET_BITVAL 3
86 #define SCSB_FRU_OP_GET_REGDATA 4
87
88 /*
89 * (internal only)
90 * scsb build version format is "CCYYMMDD"
91 * for integer compares.
92 */
93 #define SCSB_BUILD_VERSION "20001206"
94
95 #define MUTEX_UNINIT 0
96 #define MUTEX_INIT 2
97
98 static int scsb_err_threshold = 0; /* max allowed i2c errors */
99 static int scsb_freeze_count = 3; /* #I2C errors to indicate SCB removal */
100 static int scsb_shutdown_count = 5; /* #polls before passing shutdown evt */
101 static int scsb_in_postintr = 0; /* 1 if scsb is processing intr */
102 static kmutex_t *scb_intr_mutex; /* SCSB interrupt mutex */
103 static int nct_mutex_init = MUTEX_UNINIT;
104
105 extern int scsb_hsc_board_healthy();
106
107 static char *scsb_name = SCSB_DEVICE_NAME;
108 static char *scsb_clone_name = SCSB_DEVICE_NAME "clone";
109 static char *scsb_build_version = SCSB_BUILD_VERSION;
110 /*
111 * cb_ops section of scsb driver.
112 */
113 static int sm_open(queue_t *, dev_t *, int, int, cred_t *);
114 static int sm_close(queue_t *, int, cred_t *);
115
116 static int sm_rput(queue_t *, mblk_t *); /* from i2c below */
117 static int sm_wput(queue_t *, mblk_t *); /* from above */
118
119 uint_t scsb_intr_preprocess(caddr_t arg);
120 void scsb_intr(caddr_t arg);
121 static void smf_ioctl(queue_t *, mblk_t *);
122 static void sm_ioc_rdwr(queue_t *, mblk_t *, int);
123
124 static int scsb_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
125 static int scsb_attach(dev_info_t *, ddi_attach_cmd_t);
126 static int scsb_detach(dev_info_t *, ddi_detach_cmd_t);
127 static int initialize_scb(scsb_state_t *);
128
129 static dev_info_t *scsb_dip; /* private copy of devinfo pointer */
130
131 static struct module_info info = {
132 0, SCSB_DEVICE_NAME, 0, INFPSZ, 512, 128
133 };
134
135 static struct qinit sm_rinit = {
136 sm_rput, NULL, sm_open, sm_close, NULL, &info
137 };
138
139 static struct qinit sm_winit = {
140 sm_wput, NULL, sm_open, sm_close, NULL, &info
141 };
142
143 struct streamtab sm_st = {
144 &sm_rinit, &sm_winit, NULL, NULL
145 };
146
147 static struct cb_ops scsb_cb_ops = {
148
149 nulldev, /* open */
150 nulldev, /* close */
151 nodev, /* strategy */
152 nodev, /* print */
153 nodev, /* dump */
154 nodev, /* read */
155 nodev, /* write */
156 nodev, /* ioctl */
157 nodev, /* devmap */
158 nodev, /* mmap */
159 nodev, /* segmap */
160 nochpoll, /* poll */
161 ddi_prop_op, /* cb_prop_op */
162 &sm_st, /* streamtab */
163 D_MP, /* Driver compatibility flag */
164 CB_REV, /* rev */
165 nodev, /* int (*cb_aread)() */
166 nodev /* int (*cb_awrite)() */
167 };
168
169 static struct dev_ops scsb_ops = {
170
171 DEVO_REV, /* devo_rev, */
172 0, /* refcnt */
173 scsb_info, /* info */
174 nulldev, /* identify */
175 nulldev, /* probe */
176 scsb_attach, /* attach */
177 scsb_detach, /* detach */
178 nodev, /* reset */
179 &scsb_cb_ops, /* driver operations */
180 (struct bus_ops *)0, /* bus operations */
181 NULL, /* power */
182 ddi_quiesce_not_supported, /* devo_quiesce */
183 };
184
185 /*
186 * Module linkage information for the kernel.
187 */
188
189 static struct modldrv modldrv = {
190 &mod_driverops, /* Type of module. This one is a pseudo driver */
191 #ifdef DEBUG
192 "SCB/SSB driver DBG" SCSB_BUILD_VERSION,
193 #else
194 "v1.33 Netra ct System Control/Status Board driver",
195 #endif
196 &scsb_ops, /* driver ops */
197 };
198
199 static struct modlinkage modlinkage = {
200 MODREV_1,
201 (void *)&modldrv,
202 NULL
203 };
204
205 /*
206 * local declarations and definitions
207 */
208 #if defined(DEBUG)
209 uint32_t scsb_debug = 0x00000000;
210 #else
211 static uint32_t scsb_debug = 0;
212 #endif
213
214 static hrtime_t scb_pre_s, scb_pre_e, scb_post_s, scb_post_e;
215
216 static int scsb_pil = SCSB_INTR_PIL;
217 static int hsc_pil = SCSB_INTR_PIL;
218 static void *scsb_state;
219 static uint32_t scsb_global_state;
220 static uint32_t scsb_event_code; /* for event polling */
221 static struct system_info mct_system_info;
222 static int scsb_healthy_poll_count = 16;
223
224 static fru_id_t fru_id_table[MCT_MAX_FRUS];
225 static uchar_t scb_intr_regs[SCTRL_MAX_GROUP_NUMREGS];
226
227 static uint32_t evc_fifo[EVC_FIFO_SIZE];
228 static uint32_t evc_fifo_count = 0;
229 static uint32_t *evc_rptr = evc_fifo;
230 static uint32_t *evc_wptr = evc_fifo;
231 static void *evc_procs[EVC_PROCS_MAX];
232 static int evc_proc_count = 0;
233 static timeout_id_t scsb_intr_tid;
234
235 int nct_i2c_transfer(i2c_client_hdl_t i2c_hdl, i2c_transfer_t *i2c_tran);
236
237 /*
238 * kstat functions
239 */
240 static int scsb_alloc_kstats(scsb_state_t *);
241 static void scsb_free_kstats(scsb_state_t *);
242 static int update_ks_leddata(kstat_t *, int);
243 static int update_ks_state(kstat_t *, int);
244 static int update_ks_topology(kstat_t *, int);
245 static int update_ks_evcreg(kstat_t *, int);
246
247 /*
248 * local functions
249 */
250 static void free_resources(dev_info_t *, scsb_state_t *, int);
251 static i2c_transfer_t *scsb_alloc_i2ctx(i2c_client_hdl_t, uint_t);
252 static fru_info_t *find_fru_info(fru_id_t fru_id);
253 static int scsb_fake_intr(scsb_state_t *, uint32_t);
254 static int scsb_get_status(scsb_state_t *, scsb_status_t *);
255 static int scsb_leds_switch(scsb_state_t *, scsb_ustate_t);
256 static void scsb_freeze(scsb_state_t *scsb);
257 static void scsb_freeze_check(scsb_state_t *scsb);
258 static void scsb_restore(scsb_state_t *scsb);
259 static int scsb_polled_int(scsb_state_t *, int, uint32_t *);
260 static int scsb_check_config_status(scsb_state_t *scsb);
261 static int scsb_set_scfg_pres_leds(scsb_state_t *, fru_info_t *);
262 static void scsb_set_topology(scsb_state_t *);
263 static void scsb_free_topology(scsb_state_t *);
264 int scsb_read_bhealthy(scsb_state_t *scsb);
265 int scsb_read_slot_health(scsb_state_t *, int);
266 static void tonga_slotnum_check(scsb_state_t *scsb, scsb_uinfo_t *suip);
267 static int tonga_psl_to_ssl(scsb_state_t *scsb, int slotnum);
268 static uchar_t tonga_slotnum_led_shift(scsb_state_t *scsb, uchar_t data);
269 static int scsb_clear_intptrs(scsb_state_t *scsb);
270 static int scsb_clear_intmasks(scsb_state_t *scsb);
271 static int scsb_setall_intmasks(scsb_state_t *scsb);
272 static int scsb_write_mask(scsb_state_t *, uchar_t, uchar_t, uchar_t,
273 uchar_t);
274 static int scsb_rdwr_register(scsb_state_t *, int, uchar_t, int,
275 uchar_t *, int);
276 static int scsb_readall_regs(scsb_state_t *);
277 static int scsb_get_led_regnum(scsb_state_t *, scsb_uinfo_t *, uchar_t *,
278 int *, scsb_led_t);
279 static void scsb_free_i2ctx(i2c_client_hdl_t, i2c_transfer_t *);
280 static void check_fru_info(scsb_state_t *, int);
281 static void update_fru_info(scsb_state_t *, fru_info_t *);
282 static int event_to_index(uint32_t);
283 static void add_event_code(scsb_state_t *, uint32_t);
284 static uint32_t del_event_code();
285 static uint32_t get_event_code();
286 static int add_event_proc(scsb_state_t *, pid_t);
287 static int del_event_proc(scsb_state_t *, pid_t);
288 static void rew_event_proc(scsb_state_t *);
289 static int event_proc_count(scsb_state_t *);
290 static int find_evc_proc(pid_t pid);
291 static void signal_evc_procs(scsb_state_t *);
292 static int check_event_procs();
293 static int scsb_is_alarm_card_slot(scsb_state_t *, int);
294 int scsb_get_slot_state(scsb_state_t *, int, int *);
295 static int scsb_fru_op(scsb_state_t *, scsb_utype_t, int, int, int);
296 static int scsb_queue_put(queue_t *, int, uint32_t *, char *);
297 static int scsb_queue_ops(scsb_state_t *, int, int, void *, char *);
298 static int scsb_blind_read(scsb_state_t *, int, uchar_t, int, uchar_t *, int);
299 static int scsb_toggle_psmint(scsb_state_t *, int);
300 static int scsb_quiesce_psmint(scsb_state_t *);
301 static int scsb_invoke_intr_chain();
302 int scsb_intr_register(int (*)(void *), void *, fru_id_t);
303 void scsb_intr_unregister(fru_id_t);
304
305 #ifdef DEBUG
306 static void mct_topology_dump(scsb_state_t *, int);
307 static void scsb_failing_event(scsb_state_t *scsb);
308 #endif
309
310 int
311 _init(void)
312 {
313 int i, status;
314
315 if (scsb_debug & 0x0005)
316 cmn_err(CE_NOTE, "scsb: _init()");
317 (void) ddi_soft_state_init(&scsb_state, sizeof (scsb_state_t),
318 SCSB_NO_OF_BOARDS);
319 (void) hsc_init();
320 if ((status = mod_install(&modlinkage)) != 0) {
321 if (scsb_debug & 0x0006)
322 cmn_err(CE_NOTE, "scsb: _init(): mod_install failed");
323 ddi_soft_state_fini(&scsb_state);
324 (void) hsc_fini();
325 return (status);
326 }
327 /*
328 * initialize the FRU ID Table, using real FRU IDs where available
329 * such as I2C Addresses for FRUs with I2C support
330 */
331 for (i = 0; i < MCT_MAX_FRUS; ++i)
332 fru_id_table[i] = i + 1;
333 fru_id_table[event_to_index(SCTRL_EVENT_PS1)] = (fru_id_t)MCT_I2C_PS1;
334 fru_id_table[event_to_index(SCTRL_EVENT_PS2)] = (fru_id_t)MCT_I2C_PS2;
335 fru_id_table[event_to_index(SCTRL_EVENT_FAN1)] = (fru_id_t)MCT_I2C_FAN1;
336 fru_id_table[event_to_index(SCTRL_EVENT_FAN2)] = (fru_id_t)MCT_I2C_FAN2;
337 fru_id_table[event_to_index(SCTRL_EVENT_FAN3)] = (fru_id_t)MCT_I2C_FAN3;
338 fru_id_table[event_to_index(SCTRL_EVENT_SCB)] = (fru_id_t)MCT_I2C_SCB;
339 return (status);
340 }
341
342 int
343 _fini(void)
344 {
345 int status;
346
347 if (scsb_debug & 0x0005)
348 cmn_err(CE_NOTE, "scsb: _fini()");
349
350 if ((status = mod_remove(&modlinkage)) == 0) {
351 ddi_soft_state_fini(&scsb_state);
352 (void) hsc_fini();
353 }
354 if (scsb_debug & 0x0006)
355 cmn_err(CE_NOTE, "scsb: _fini, error %x\n", status);
356
357 return (status);
358 }
359
360 int
361 _info(struct modinfo *modinfop)
362 {
363 if (scsb_debug & 0x0005)
364 cmn_err(CE_NOTE, "scsb: _info()");
365
366 return (mod_info(&modlinkage, modinfop));
367 }
368
369 static int
370 scsb_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
371 {
372 int instance;
373 scsb_state_t *scsb;
374 register int i;
375 int *regs;
376 uint_t len;
377 uchar_t reg, wdata, rmask;
378
379 instance = ddi_get_instance(dip);
380
381 if (scsb_debug & 0x0005)
382 cmn_err(CE_NOTE, "scsb_attach[%d]", instance);
383
384 if (cmd != DDI_ATTACH) {
385 if (scsb_debug & 0x0006)
386 cmn_err(CE_NOTE,
387 "scsb_attach[%d]: cmd 0x%x != DDI_ATTACH",
388 instance, cmd);
389 return (DDI_FAILURE);
390 }
391
392 if (ddi_soft_state_zalloc(scsb_state, instance) != DDI_SUCCESS) {
393 cmn_err(CE_WARN, "scsb%d: cannot allocate soft state",
394 instance);
395 return (DDI_FAILURE);
396 }
397
398 scsb = (scsb_state_t *)ddi_get_soft_state(scsb_state, instance);
399 if (scsb == NULL) {
400 cmn_err(CE_WARN, "scsb%d: cannot get soft state", instance);
401 ddi_soft_state_free(scsb_state, instance);
402 return (DDI_FAILURE);
403 }
404 scsb->scsb_instance = instance;
405 scsb->scsb_state = 0; /* just checking strange mutex behavior */
406
407 /*
408 * make sure this is the SCB's known address
409 */
410 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
411 "reg", ®s, &len) != DDI_PROP_SUCCESS) {
412 cmn_err(CE_WARN,
413 "scsb%d: Failed to get \"reg\" property", instance);
414 ddi_soft_state_free(scsb_state, instance);
415 return (DDI_FAILURE);
416 }
417 scsb->scsb_i2c_addr = regs[1] & SCSB_I2C_ADDR_MASK;
418 if (scsb->scsb_i2c_addr != SCSB_I2C_ADDR) {
419 cmn_err(CE_WARN, "scsb%d: I2C Addr reg %x %x must be %x",
420 instance, regs[0], regs[1], SCSB_I2C_ADDR);
421 ddi_soft_state_free(scsb_state, instance);
422 ddi_prop_free(regs);
423 return (DDI_FAILURE);
424 }
425 /* done with array lookup, free resource */
426 ddi_prop_free(regs);
427 /*
428 * initialize synchronization mutex and condition var.
429 * for this instance.
430 */
431 mutex_init(&scsb->scsb_mutex, NULL, MUTEX_DRIVER, NULL);
432 scsb->scsb_state |= SCSB_UMUTEX;
433 cv_init(&scsb->scsb_cv, NULL, CV_DRIVER, NULL);
434 scsb->scsb_state |= SCSB_CONDVAR;
435
436 /*
437 * 1. Read interrupt property of the board and register its handler.
438 * 2. Get scsb private handle for communication via I2C Services.
439 * 3. Allocate and save an i2c_transfer_t for I2C transfers.
440 */
441 /* 1 */
442 if (ddi_prop_exists(DDI_DEV_T_ANY, dip,
443 DDI_PROP_NOTPROM | DDI_PROP_DONTPASS,
444 "interrupt-priorities") != 1) {
445 int tmp[2];
446 tmp[0] = scsb_pil;
447 tmp[1] = hsc_pil;
448 (void) ddi_prop_update_int_array(DDI_DEV_T_NONE, dip,
449 "interrupt-priorities", tmp, 2);
450 scsb->scsb_state |= SCSB_PROP_CREATE;
451 }
452 if ((i = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
453 DDI_PROP_DONTPASS, "interrupts", -1)) >= 0)
454 scsb->scsb_state |= SCSB_P06_INTR_ON;
455 else
456 scsb->scsb_state |= SCSB_P06_NOINT_KLUGE;
457
458 /*
459 * Look for the device-err-threshold property which specifies
460 * on how many errors will scsb send a warning event about it's
461 * health. The scsb_err_threshold is 10 by default.
462 */
463 if ((i = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
464 DDI_PROP_DONTPASS, "device-err-threshold", -1)) >= 0) {
465 scsb_err_threshold = i;
466 #ifdef DEBUG
467 cmn_err(CE_NOTE, "?scsb_attach: Found device-err-threshold"
468 " property, value %d", scsb_err_threshold);
469 #endif
470 }
471 scsb->scsb_i2c_errcnt = 0;
472 scsb->scsb_err_flag = B_FALSE;
473 scsb->scsb_kstat_flag = B_FALSE;
474
475 /*
476 * If all went well, create the minor node for user level access.
477 */
478 if (ddi_create_minor_node(dip, scsb_name, S_IFCHR, instance,
479 "ddi_ctl:pcihpc", NULL) == DDI_FAILURE) {
480 cmn_err(CE_WARN, "scsb_attach: Failed to create minor node");
481 free_resources(dip, scsb, instance);
482 return (DDI_FAILURE);
483 }
484 scsb->scsb_state |= SCSB_MINOR_NODE;
485 scsb->scsb_dev = dip;
486 if (ddi_create_minor_node(dip, scsb_clone_name, S_IFCHR,
487 instance|SCSB_CLONE, "ddi_ctl:pcihpc", NULL)
488 == DDI_FAILURE) {
489 cmn_err(CE_WARN, "scsb_attach: Failed to create clone node");
490 free_resources(dip, scsb, instance);
491 return (DDI_FAILURE);
492 }
493 /* CLONE */
494 bzero(scsb->clone_devs, sizeof (clone_dev_t) * SCSB_CLONES_MAX);
495 /* 2 */
496 if (i2c_client_register(dip, &scsb->scsb_phandle) != I2C_SUCCESS) {
497 cmn_err(CE_WARN,
498 "scsb_attach: Failed I2C Services registration");
499 free_resources(dip, scsb, instance);
500 return (DDI_FAILURE);
501 }
502 scsb->scsb_state |= SCSB_I2C_PHANDLE;
503 /* 3 */
504 if ((scsb->scsb_i2ctp = scsb_alloc_i2ctx(scsb->scsb_phandle,
505 I2C_SLEEP)) == NULL) {
506 cmn_err(CE_WARN,
507 "scsb%d: i2c_transfer allocation failed", instance);
508 free_resources(dip, scsb, instance);
509 return (DDI_FAILURE);
510 }
511 scsb->scsb_state |= SCSB_I2C_TRANSFER;
512 /*
513 * Now it's time to INITIALIZE the boards.
514 *
515 * 1. make sure we can do I2C bus transfers to/from the SCB.
516 * Read the SCB PROM version for a check.
517 * 2. set SCB_INITIALIZED bit in SysCommand registers (SYS_CMD_BASE)
518 * 3. clear all LED Data registers (8) by writing 0's to turn off
519 * all LEDs on the SSB.
520 * 4. read System Configuration Status registers (SCTRL_CFG)
521 * to find present FRUs and set corresponding FRU bits at
522 * LED_DATA_BASE.
523 * Also enable devices in Topology map for the current MP_ID
524 * and set the OK LEDs on the SSB.
525 * 5. read Brd_Hlthy registers (2 @ BRD_HLTHY_BASE)
526 * 6. Disable PSM Interrupts during initialization, mask all
527 * interrupts, and clear Interrupt Pointer registers
528 * by writing 0xFF to each register.
529 * 7. set SCB EEPROM address bits SPA2-SPA0 at SYS_CMD_BASE + 1
530 * 8. Install the interrupt handler if appropriate.
531 * 9. clear appropriate bits in Interrupt Mask register for those
532 * devices that can be present for this MP_ID Topology.
533 * 10. enable PSM Interrupt by writing '1' to PSM_INT_EN bit at
534 * SYS_CMD_BASE + 1
535 * Also update all shadow registers for test utility
536 * if scsb_debug is set.
537 * 11. Check if Alarm Card present at boot and set flags
538 * 12. Call hsc_attach() for slot registration.
539 * 13. Allocate, initialze, and install the kstat structures.
540 * 14. Set scsb_state_t flags to indicate SCB is ready
541 * and announce the driver is loaded.
542 */
543
544 /* 1. through 7. */
545 if (initialize_scb(scsb) != DDI_SUCCESS) {
546 if (!(scsb_debug)) {
547 free_resources(dip, scsb, instance);
548 return (DDI_FAILURE);
549 }
550 }
551 /* 8. */
552 /*
553 * P0.6 No Interrupt Support
554 * Instead of installing the handler, it will be called from a user
555 * program via smf_ioctl(). This flag provides knowledge of the
556 * necessary workarounds to several scsb routines.
557 */
558 /*
559 * Now Install interrupt handler
560 */
561 if (scsb->scsb_state & SCSB_P06_INTR_ON) {
562 if (ddi_get_iblock_cookie(dip, instance,
563 &scsb->scsb_iblock) == DDI_SUCCESS) {
564 mutex_init(&scsb->scsb_imutex, NULL, MUTEX_DRIVER,
565 (void *)scsb->scsb_iblock);
566 scsb->scsb_state |= SCSB_IMUTEX;
567 if (ddi_add_intr(dip, instance, &scsb->scsb_iblock,
568 NULL, scsb_intr_preprocess,
569 (caddr_t)scsb) != DDI_SUCCESS) {
570 cmn_err(CE_WARN,
571 "scsb_attach: failed interrupt "
572 "handler registration");
573 free_resources(dip, scsb, instance);
574 return (DDI_FAILURE);
575 }
576 scb_intr_mutex = &scsb->scsb_imutex;
577 nct_mutex_init |= MUTEX_INIT;
578 } else {
579 cmn_err(CE_WARN, "scsb_attach: failed interrupt "
580 "mutex initialization");
581 if (scsb_debug) {
582 scsb->scsb_state |= SCSB_P06_NOINT_KLUGE;
583 scsb->scsb_state &= ~SCSB_P06_INTR_ON;
584 } else {
585 free_resources(dip, scsb, instance);
586 return (DDI_FAILURE);
587 }
588 }
589 }
590 /* 9. */
591 if (i = scsb_clear_intmasks(scsb)) {
592 cmn_err(CE_WARN,
593 "scsb%d: I2C TRANSFER Failed", instance);
594 if (!scsb_debug) {
595 free_resources(dip, scsb, instance);
596 return (DDI_FAILURE);
597 }
598 }
599
600 /* 10. */
601 /*
602 * For P0.6 No Interrupt Support, don't enable PSM Interrupt
603 */
604 if (!(scsb->scsb_state & SCSB_P06_NOINT_KLUGE)) {
605 rmask = 0x00;
606 wdata = 1 << SYS_OFFSET(SCTRL_SYS_PSM_INT_ENABLE);
607 i = SYS_REG_INDEX(SCTRL_SYS_PSM_INT_ENABLE,
608 SCTRL_SYS_CMD_BASE);
609 reg = SCSB_REG_ADDR(i);
610 if (i = scsb_write_mask(scsb, reg, rmask, wdata, (uchar_t)0)) {
611 cmn_err(CE_WARN,
612 "scsb%d: I2C TRANSFER Failed", instance);
613 if (!scsb_debug) {
614 free_resources(dip, scsb, instance);
615 return (DDI_FAILURE);
616 }
617 } else
618 scsb->scsb_state |= SCSB_PSM_INT_ENABLED;
619 }
620 if (scsb_debug) {
621 /*
622 * For smctrl test utility,
623 * so all data is available in shadow registers
624 *
625 * DEBUG_MODE enables private testing interfaces
626 * DIAGS_MODE permits limited testing interfaces
627 */
628 scsb->scsb_state |= SCSB_DEBUG_MODE;
629 mutex_enter(&scsb->scsb_mutex);
630 if (scsb_readall_regs(scsb))
631 cmn_err(CE_WARN,
632 "scsb_attach: scsb_readall FAILED");
633 mutex_exit(&scsb->scsb_mutex);
634 }
635 /* 11. */
636 /* Check if Alarm Card present at boot and set flags */
637 if (scsb_fru_op(scsb, ALARM, 1, SCTRL_SYSCFG_BASE,
638 SCSB_FRU_OP_GET_BITVAL))
639 scsb->scsb_hsc_state |= SCSB_ALARM_CARD_PRES;
640
641 /* 12. */
642 if (scsb_debug & 0x0004)
643 cmn_err(CE_NOTE,
644 "scsb_attach: registering cPCI slots");
645 if (scsb_hsc_attach(dip, scsb, instance) != DDI_SUCCESS) {
646 if (scsb_debug & 0x00008000) {
647 cmn_err(CE_WARN,
648 "scsb: Hotswap controller initialisation"
649 " failed\n");
650 }
651 } else
652 scsb->scsb_hsc_state |= SCSB_HSC_INIT;
653 /* 13. */
654 /*
655 * allocate and install the kstat data structures
656 */
657 if (scsb_alloc_kstats(scsb) != DDI_SUCCESS) {
658 if (scsb_debug & 0x0006)
659 cmn_err(CE_WARN, "scsb_attach: ERROR adding kstats");
660 }
661 /* 14. */
662 scsb->scsb_state |= SCSB_UP;
663 scsb_global_state |= SCSB_UP;
664 ddi_report_dev(scsb->scsb_dev);
665 cmn_err(CE_CONT, "?%s%d: "
666 "Prom Version %s, Midplane Id %x\n",
667 ddi_driver_name(scsb->scsb_dev),
668 scsb->scsb_instance,
669 (scsb->scsb_state & SCSB_P06_PROM) ? "0.6" :
670 (scsb->scsb_state & SCSB_P10_PROM) ? "1.0" :
671 (scsb->scsb_state & SCSB_P15_PROM) ? "1.5" :
672 (scsb->scsb_state & SCSB_P20_PROM) ? "2.0" : "Unknown",
673 mct_system_info.mid_plane.fru_id);
674 return (DDI_SUCCESS);
675 }
676
677 /*
678 * This funciton is called from scsb_attach(), and from scsb_intr() as part
679 * of Hot Insertion support, to check the SCB PROM ID register and set
680 * scsb_state bits and register table pointers as necessary.
681 */
682 static int
683 scb_check_version(scsb_state_t *scsb)
684 {
685 int hotswap = 0;
686 uchar_t data;
687 if (scsb->scsb_state & SCSB_UP) {
688 /*
689 * If driver is UP, then this call is from scsb_intr()
690 * as part of Hot Insertion support.
691 */
692 hotswap = 1;
693 }
694 /* Read the SCB PROM ID */
695 if (scsb_rdwr_register(scsb, I2C_WR_RD, (uchar_t)SCTRL_PROM_VERSION, 1,
696 &data, 1)) {
697 if (!(hotswap && scsb->scsb_state & SCSB_FROZEN))
698 cmn_err(CE_WARN, "scsb%d: I2C TRANSFER Failed",
699 scsb->scsb_instance);
700 if (scsb_debug & 0x0006) {
701 cmn_err(CE_WARN,
702 "scsb_attach(%d): failed read of PROM ID",
703 scsb->scsb_instance);
704 }
705 return (DDI_FAILURE);
706 }
707 /*
708 * compare with stored version number, and if different,
709 * report a warning and keep the driver FROZEN
710 */
711 if (hotswap) {
712 if (((mct_system_info.fru_info_list[SCB])[0].fru_version & 0xf)
713 == (data & 0xf)) {
714 return (DDI_SUCCESS);
715 }
716 if (scsb_debug & 0x00020000) {
717 cmn_err(CE_NOTE,
718 "scb_check_version: SCB version %d "
719 "replacing version %d", data,
720 (mct_system_info.fru_info_list[SCB])[0].
721 fru_version & 0xf);
722 }
723 }
724 if ((data & 0xf) == SCTRL_PROM_P06) {
725 scsb->scsb_state |= SCSB_P06_PROM;
726 } else if ((data & 0xf) == SCTRL_PROM_P10) {
727 scsb->scsb_state |= SCSB_P10_PROM;
728 } else if ((data & 0xf) == SCTRL_PROM_P15) {
729 scsb->scsb_state |= SCSB_P15_PROM;
730 } else if ((data & 0xf) == SCTRL_PROM_P20) {
731 scsb->scsb_state |= SCSB_P20_PROM;
732 }
733 if (!(scsb->scsb_state & SCSB_SCB_PRESENT))
734 scsb->scsb_state |= SCSB_SCB_PRESENT;
735 if (IS_SCB_P10) {
736 scb_reg_index = scb_10_reg_index;
737 scb_numregs = scb_10_numregs;
738 scb_fru_offset = scb_10_fru_offset;
739 scb_sys_offset = scb_10_sys_offset;
740 } else { /* if (IS_SCB_P15) */
741 scb_reg_index = scb_15_reg_index;
742 scb_numregs = scb_15_numregs;
743 scb_fru_offset = scb_15_fru_offset;
744 scb_sys_offset = scb_15_sys_offset;
745 }
746 if (!(IS_SCB_P15) && !(IS_SCB_P10)) {
747 cmn_err(CE_WARN, "scsb%d: SCB Version %d not recognized",
748 scsb->scsb_instance, data);
749 if (hotswap)
750 scsb->scsb_state |= SCSB_FROZEN;
751 if (!(scsb_debug)) {
752 return (DDI_FAILURE);
753 }
754 /*
755 * DEBUG: Assume SCB15
756 */
757 scsb->scsb_state |= SCSB_P15_PROM;
758 }
759 return (DDI_SUCCESS);
760 }
761
762 /*
763 * SCB initialization steps to be called from scsb_attach()
764 * or from scsb_intr() calling scsb_restore() on Hot Insertion.
765 */
766 static int
767 initialize_scb(scsb_state_t *scsb)
768 {
769 register int i;
770 uchar_t reg, wdata, rmask;
771 /*
772 * If called from scsb_intr(), we've already done this
773 */
774 if (!(scsb->scsb_state & SCSB_IN_INTR))
775 if (scb_check_version(scsb) != DDI_SUCCESS)
776 return (DDI_FAILURE);
777 /*
778 * 2. Set the SCB_INIT bit in the System Command register
779 */
780 rmask = 0x00; /* P1.0: 0x60; */
781 wdata = 1 << SYS_OFFSET(SCTRL_SYS_SCB_INIT);
782 i = SYS_REG_INDEX(SCTRL_SYS_SCB_INIT, SCTRL_SYS_CMD_BASE);
783 reg = SCSB_REG_ADDR(i);
784 if (i = scsb_write_mask(scsb, reg, rmask, wdata, 0)) {
785 cmn_err(CE_WARN,
786 "scsb%d: I2C TRANSFER Failed", scsb->scsb_instance);
787 if (scsb_debug & 0x0006) {
788 cmn_err(CE_NOTE,
789 "scsb_attach: failed to set SCB_INIT");
790 }
791 return (DDI_FAILURE);
792 }
793 /* 3. For P1.0 and previous system, turn off all LEDs */
794 if (IS_SCB_P10) {
795 if (scsb_debug & 0x0004) {
796 cmn_err(CE_NOTE, "scsb_attach(%d): turning LEDs off",
797 scsb->scsb_instance);
798 }
799 if (i = scsb_leds_switch(scsb, OFF)) {
800 cmn_err(CE_WARN, "scsb%d: I2C TRANSFER Failed",
801 scsb->scsb_instance);
802 return (DDI_FAILURE);
803 }
804 }
805 /* 4. Read the SYSCFG registers, update FRU info and SSB LEDs */
806 if (scsb_debug & 0x0004)
807 cmn_err(CE_NOTE, "scsb_attach(%d): reading config registers",
808 scsb->scsb_instance);
809 if ((i = scsb_check_config_status(scsb)) == 0) {
810 if (!(scsb->scsb_state & SCSB_TOPOLOGY)) {
811 scsb_set_topology(scsb);
812 if (scsb_debug & 0x0004)
813 cmn_err(CE_NOTE, "scsb_attach(%d): mpid = 0x%x",
814 scsb->scsb_instance,
815 mct_system_info.mid_plane.fru_id);
816 } else {
817 fru_info_t *fru_ptr;
818 /*
819 * walk through FRUs and update FRU info
820 */
821 for (i = 0; i < SCSB_UNIT_TYPES; ++i) {
822 fru_ptr = mct_system_info.fru_info_list[i];
823 while (fru_ptr != NULL) {
824 update_fru_info(scsb, fru_ptr);
825 fru_ptr = fru_ptr->next;
826 }
827 }
828 }
829 i = scsb_set_scfg_pres_leds(scsb, NULL);
830 }
831 if (i) {
832 cmn_err(CE_WARN, "scsb%d: I2C TRANSFER Failed",
833 scsb->scsb_instance);
834 return (DDI_FAILURE);
835 }
836 /* 5. read the Board Healthy registers */
837 if (scsb_debug & 0x0004)
838 cmn_err(CE_NOTE, "scsb_attach(%d): reading Brd_Hlthy registers",
839 scsb->scsb_instance);
840 i = scsb_read_bhealthy(scsb);
841 if (i) {
842 cmn_err(CE_WARN, "scsb%d: I2C TRANSFER Failed",
843 scsb->scsb_instance);
844 return (DDI_FAILURE);
845 }
846 /* 6. Clear Interrupt Source registers */
847 /*
848 * Due to some registration problems, we must first disable
849 * global interrupts which may be the default reset value
850 * itself. However, this is a safe step to do in case of
851 * implementation changes.
852 *
853 * Disable Global SCB Interrupts now
854 */
855 rmask = 0x00; /* P1.0: 0x60; */
856 wdata = 1 << SYS_OFFSET(SCTRL_SYS_PSM_INT_ENABLE);
857 i = SYS_REG_INDEX(SCTRL_SYS_PSM_INT_ENABLE, SCTRL_SYS_CMD_BASE);
858 reg = SCSB_REG_ADDR(i);
859 if (i = scsb_write_mask(scsb, reg, rmask, (uchar_t)0, wdata)) {
860 cmn_err(CE_WARN, "scsb%d: Cannot turn off PSM_INT",
861 scsb->scsb_instance);
862 return (DDI_FAILURE);
863 }
864 /* Mask all interrupt sources */
865 if (i = scsb_setall_intmasks(scsb)) {
866 cmn_err(CE_WARN, "scsb%d: I2C TRANSFER Failed",
867 scsb->scsb_instance);
868 return (DDI_FAILURE);
869 }
870 /* Clear any latched interrupts */
871 if (i = scsb_clear_intptrs(scsb)) {
872 cmn_err(CE_WARN, "scsb%d: I2C TRANSFER Failed",
873 scsb->scsb_instance);
874 return (DDI_FAILURE);
875 }
876 /* 7. set SCB EEPROM address: NOT USED */
877 return (DDI_SUCCESS);
878 }
879
880 /*
881 * Based on MC conditions, scsb_detach should eventually be made to always
882 * return FAILURE, as the driver should not be allowed to detach after some
883 * hs slots have been used.
884 */
885 static int
886 scsb_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
887 {
888 int instance;
889 scsb_state_t *scsb;
890 uchar_t reg, wdata;
891
892 /*
893 * TBD: make sure there are no outstanding operations on the system
894 * monitor card before detaching.
895 */
896 instance = ddi_get_instance(dip);
897 if (scsb_debug & 0x0005)
898 cmn_err(CE_NOTE, "scsb_detach[%d]", instance);
899 if (cmd != DDI_DETACH) {
900 if (scsb_debug & 0x0006)
901 cmn_err(CE_NOTE,
902 "scsb_detach(%d): command %x is not DDI_DETACH\n",
903 instance, cmd);
904 return (DDI_FAILURE);
905 }
906 scsb = (scsb_state_t *)ddi_get_soft_state(scsb_state, instance);
907 scsb->scsb_state &= ~SCSB_UP;
908 scsb_global_state &= ~SCSB_UP;
909 if (scsb->scsb_hsc_state & SCSB_HSC_INIT) {
910 (void) scsb_hsc_detach(dip, scsb, instance);
911 scsb->scsb_hsc_state &= ~SCSB_HSC_INIT;
912 }
913 if (scsb->scsb_state & SCSB_PSM_INT_ENABLED) {
914 /*
915 * Disable Global SCB Interrupts now
916 */
917 wdata = 1 << SYS_OFFSET(SCTRL_SYS_PSM_INT_ENABLE);
918 reg = SYS_REG_INDEX(SCTRL_SYS_PSM_INT_ENABLE,
919 SCTRL_SYS_CMD_BASE);
920 if (scsb_write_mask(scsb, reg, (uchar_t)0, (uchar_t)0, wdata)) {
921 cmn_err(CE_WARN,
922 "scsb%d: Cannot turn off PSM_INT", instance);
923 if (!scsb_debug) {
924 (void) free_resources(dip, scsb, instance);
925 return (DDI_FAILURE);
926 }
927 }
928 /* Mask all interrupts */
929 if (scsb_setall_intmasks(scsb)) {
930 cmn_err(CE_WARN,
931 "scsb%d: I2C TRANSFER Failed", instance);
932 if (!scsb_debug) {
933 (void) free_resources(dip, scsb, instance);
934 return (DDI_FAILURE);
935 }
936 }
937 /* Clear all latched interrupts */
938 if (scsb_clear_intptrs(scsb)) {
939 cmn_err(CE_WARN,
940 "scsb%d: I2C TRANSFER Failed", instance);
941 if (!scsb_debug) {
942 (void) free_resources(dip, scsb, instance);
943 return (DDI_FAILURE);
944 }
945 }
946 }
947 if (scsb->scsb_opens && scsb->scsb_rq != NULL)
948 qprocsoff(scsb->scsb_rq);
949 /* CLONE */
950 (void) scsb_queue_ops(scsb, QPROCSOFF, 0, NULL, NULL);
951 /*
952 * free the allocated resources
953 */
954 free_resources(dip, scsb, instance);
955 return (DDI_SUCCESS);
956 }
957
958 static void
959 free_resources(dev_info_t *dip, scsb_state_t *scsb, int instance)
960 {
961 if (scsb_debug & 0x0005) {
962 cmn_err(CE_NOTE, "free_resources[%d], scsb_state=0x%x",
963 instance, scsb->scsb_state);
964 drv_usecwait(500000);
965 }
966 if (scsb->scsb_state & SCSB_P06_INTR_ON &&
967 scsb->scsb_state & SCSB_IMUTEX) {
968 scsb->scsb_state &= ~SCSB_P06_INTR_ON;
969 ddi_remove_intr(dip, 0, scsb->scsb_iblock);
970 }
971 if (scsb->scsb_state & SCSB_KSTATS) {
972 scsb_free_kstats(scsb);
973 scsb->scsb_state &= ~SCSB_KSTATS;
974 }
975 if (scsb->scsb_state & SCSB_TOPOLOGY) {
976 scsb_free_topology(scsb);
977 scsb->scsb_state &= ~SCSB_TOPOLOGY;
978 }
979
980 nct_mutex_init = MUTEX_UNINIT;
981 if (scsb->scsb_state & SCSB_IMUTEX) {
982 scsb->scsb_state &= ~SCSB_IMUTEX;
983 mutex_destroy(&scsb->scsb_imutex);
984 }
985 if (scsb->scsb_state & SCSB_I2C_TRANSFER) {
986 scsb->scsb_state &= ~SCSB_I2C_TRANSFER;
987 i2c_transfer_free(scsb->scsb_phandle, scsb->scsb_i2ctp);
988 }
989 if (scsb->scsb_state & SCSB_I2C_PHANDLE) {
990 scsb->scsb_state &= ~SCSB_I2C_PHANDLE;
991 i2c_client_unregister(scsb->scsb_phandle);
992 }
993 if (scsb->scsb_state & SCSB_MINOR_NODE) {
994 scsb->scsb_state &= ~SCSB_MINOR_NODE;
995 ddi_remove_minor_node(dip, NULL);
996 }
997 if (scsb->scsb_state & SCSB_PROP_CREATE) {
998 scsb->scsb_state &= ~SCSB_PROP_CREATE;
999 (void) ddi_prop_remove(DDI_DEV_T_NONE, dip,
1000 "interrupt-priorities");
1001 }
1002 /* ddi_prop_remove_all(dip); */
1003 if (scsb->scsb_state & SCSB_CONDVAR) {
1004 scsb->scsb_state &= ~SCSB_CONDVAR;
1005 cv_destroy(&scsb->scsb_cv);
1006 }
1007 if (scsb->scsb_state & SCSB_UMUTEX) {
1008 scsb->scsb_state &= ~SCSB_UMUTEX;
1009 mutex_destroy(&scsb->scsb_mutex);
1010 }
1011 ddi_soft_state_free(scsb_state, instance);
1012 }
1013
1014 /*
1015 * Just for testing scsb's poll function
1016 */
1017 static int
1018 scsb_fake_intr(scsb_state_t *scsb, uint32_t evcode)
1019 {
1020 if (evcode == 0)
1021 evcode = scsb_event_code;
1022 else
1023 scsb_event_code = evcode;
1024 if (scsb_debug & 0x4001) {
1025 cmn_err(CE_NOTE, "scsb_fake_intr: event = 0x%x, scsb_rq=0x%p",
1026 scsb_event_code, (void *)scsb->scsb_rq);
1027 }
1028 /*
1029 * Allow access to shadow registers even though SCB is removed
1030 *
1031 * if (scsb->scsb_state & SCSB_FROZEN) {
1032 * return (EAGAIN);
1033 * }
1034 */
1035 if (scsb_debug & 0x00040000) {
1036 check_fru_info(scsb, evcode);
1037 add_event_code(scsb, evcode);
1038 }
1039 /* just inform user-level via poll about this event */
1040 if (scsb_queue_ops(scsb, QPUT_INT32, 1, &evcode, "scsb_fake_intr")
1041 == QOP_FAILED)
1042 return (ENOMEM);
1043 return (0);
1044 }
1045
1046 /* ARGSUSED */
1047 static int
1048 scsb_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
1049 {
1050 int retval = DDI_FAILURE;
1051
1052 if (scsb_debug & 0x0001)
1053 cmn_err(CE_NOTE, "scsb_info()");
1054
1055 switch (infocmd) {
1056 case DDI_INFO_DEVT2DEVINFO:
1057 if (getminor((dev_t)arg) == 0 && scsb_dip != NULL) {
1058 *result = (void *) scsb_dip;
1059 retval = DDI_SUCCESS;
1060 }
1061 break;
1062
1063 case DDI_INFO_DEVT2INSTANCE:
1064 if (getminor((dev_t)arg) == 0) {
1065 *result = (void *)0;
1066 retval = DDI_SUCCESS;
1067 }
1068 break;
1069
1070 default:
1071 break;
1072 }
1073
1074 return (retval);
1075 }
1076
1077
1078 /*
1079 * SCSB STREAMS routines
1080 */
1081 /*ARGSUSED*/
1082 static int
1083 sm_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *credp)
1084 {
1085 int instance, clone;
1086 minor_t minor_dev;
1087 clone_dev_t *clptr;
1088 scsb_state_t *scsb;
1089
1090 minor_dev = getminor(*devp);
1091 instance = SCSB_GET_INSTANCE(minor_dev);
1092 scsb = ddi_get_soft_state(scsb_state, instance);
1093 if (scsb == NULL)
1094 return (ENXIO);
1095
1096 if (scsb_debug & 0x0009) {
1097 cmn_err(CE_NOTE, "sm_open(%d) q=0x%p", instance, (void *)q);
1098 }
1099 if (!(scsb->scsb_state & SCSB_UP)) {
1100 return (ENODEV);
1101 }
1102 /*
1103 * Don't fail the open if SCB removed since we still want to satisfy
1104 * read requests from the shadow registers, the last know register
1105 * contents. On new SCB insertion, all will be re-initialized,
1106 * including envmond and it's policies.
1107 *
1108 * if (scsb->scsb_state & SCSB_FROZEN) {
1109 * return (EAGAIN);
1110 * }
1111 */
1112 ASSERT(credp != NULL);
1113 /*
1114 * XXX check for root access here, return EPERM if not root open
1115 */
1116 if (sflag == MODOPEN) {
1117 /* scsb module is being pushed */
1118 if (scsb_debug & 0x0008)
1119 cmn_err(CE_NOTE, "sm_open(%d): MODOPEN", instance);
1120 /*
1121 * this is no longer supported
1122 */
1123 return (ENXIO);
1124 } else if (sflag == CLONEOPEN) {
1125 /* scsb is being opened as a clonable driver */
1126 if (scsb_debug & 0x0008)
1127 cmn_err(CE_NOTE, "sm_open(%d): CLONEOPEN", instance);
1128 /*
1129 * The cloned stream is not handled via the clone driver.
1130 * See the minor device code below.
1131 */
1132 return (ENXIO);
1133 } else if (minor_dev & SCSB_CLONE) {
1134 /*
1135 * First check for the SCSB_CLONE device.
1136 * Find an available clone_devs[] entry, or return ENXIO.
1137 * Make new dev_t and store in *devp.
1138 */
1139 if (scsb_debug & 0x0008)
1140 cmn_err(CE_NOTE,
1141 "sm_open(%d): SCSB_CLONE OPEN", instance);
1142 mutex_enter(&scsb->scsb_mutex);
1143 if ((clone = scsb_queue_ops(scsb, QFIRST_AVAILABLE, 0, NULL,
1144 "scsb_open")) == QOP_FAILED) {
1145 mutex_exit(&scsb->scsb_mutex);
1146 return (ENXIO);
1147 }
1148 clptr = &scsb->clone_devs[clone];
1149 clptr->cl_flags = SCSB_OPEN;
1150 clptr->cl_rq = RD(q);
1151 clptr->cl_minor = SCSB_MAKE_MINOR(instance, clone);
1152 *devp = makedevice(getmajor(*devp), clptr->cl_minor);
1153 scsb->scsb_clopens++;
1154 if (scsb_debug & 0x0008)
1155 cmn_err(CE_NOTE,
1156 "sm_open(%d): new clone device minor: 0x%x"
1157 " stream queue is 0x%p",
1158 instance, clptr->cl_minor, (void *)q);
1159 } else {
1160 /* scsb is being opened as a regular driver */
1161 if (scsb_debug & 0x0008)
1162 cmn_err(CE_NOTE, "sm_open(%d): DEVOPEN", instance);
1163 mutex_enter(&scsb->scsb_mutex);
1164 if (scsb->scsb_state & SCSB_EXCL) {
1165 if (scsb_debug & 0x0008)
1166 cmn_err(CE_NOTE,
1167 "sm_open(%d): can't open, state is EXCL",
1168 instance);
1169 mutex_exit(&scsb->scsb_mutex);
1170 return (EBUSY);
1171 }
1172 if (flag & FEXCL) {
1173 if (scsb_debug & 0x0008)
1174 cmn_err(CE_NOTE, "sm_open(%d): is EXCL",
1175 instance);
1176 if (scsb->scsb_state & SCSB_OPEN) {
1177 if (scsb_debug & 0x0008)
1178 cmn_err(CE_NOTE,
1179 "sm_open(%d): cannot open EXCL",
1180 instance);
1181 mutex_exit(&scsb->scsb_mutex);
1182 return (EBUSY);
1183 }
1184 scsb->scsb_state |= SCSB_EXCL;
1185 }
1186 if (scsb->scsb_opens && scsb->scsb_rq != NULL &&
1187 scsb->scsb_rq != RD(q)) {
1188 if (scsb_debug & 0x000a)
1189 cmn_err(CE_WARN, "sm_open[%d]: q (0x%p) != "
1190 "scsb_rq (0x%p)",
1191 instance, (void *)RD(q),
1192 (void *)scsb->scsb_rq);
1193 }
1194 scsb->scsb_rq = RD(q);
1195 scsb->scsb_opens++;
1196 }
1197 scsb->scsb_state |= SCSB_OPEN;
1198 mutex_exit(&scsb->scsb_mutex);
1199 RD(q)->q_ptr = WR(q)->q_ptr = scsb;
1200 qprocson(q);
1201 return (0);
1202 }
1203
1204 /*ARGSUSED*/
1205 static int
1206 sm_close(queue_t *q, int flag, cred_t *credp)
1207 {
1208 scsb_state_t *scsb;
1209 int clone;
1210 clone_dev_t *clptr = NULL;
1211
1212 scsb = (scsb_state_t *)q->q_ptr;
1213 if (scsb_debug & 0x0009)
1214 cmn_err(CE_NOTE, "sm_close[%d](0x%p)", scsb->scsb_instance,
1215 (void *)q);
1216 if (scsb->scsb_clopens) {
1217 mutex_enter(&scsb->scsb_mutex);
1218 if ((clone = scsb_queue_ops(scsb, QFIND_QUEUE, 0,
1219 (void *) RD(q), "scsb_close")) != QOP_FAILED) {
1220 clptr = &scsb->clone_devs[clone];
1221 clptr->cl_flags = 0;
1222 clptr->cl_rq = NULL;
1223 scsb->scsb_clopens--;
1224 }
1225 mutex_exit(&scsb->scsb_mutex);
1226 if (scsb_debug & 0x0008 && clone < SCSB_CLONES_MAX &&
1227 clone >= SCSB_CLONES_FIRST)
1228 cmn_err(CE_NOTE, "sm_close(%d): SCSB_CLONE 0x%x",
1229 scsb->scsb_instance, clptr->cl_minor);
1230 }
1231 if (clptr == NULL && scsb->scsb_opens) {
1232 if (scsb_debug & 0x0008)
1233 cmn_err(CE_NOTE, "sm_close(%d): DEVOPEN, opens=%d",
1234 scsb->scsb_instance, scsb->scsb_opens);
1235 if (RD(q) != scsb->scsb_rq) {
1236 if (scsb_debug & 0x0008)
1237 cmn_err(CE_WARN,
1238 "sm_close(%d): DEVOPEN, q != scsb_rq",
1239 scsb->scsb_instance);
1240 }
1241 mutex_enter(&scsb->scsb_mutex);
1242 scsb->scsb_opens = 0;
1243 if (scsb->scsb_state & SCSB_EXCL) {
1244 scsb->scsb_state &= ~SCSB_EXCL;
1245 }
1246 scsb->scsb_rq = (queue_t *)NULL;
1247 mutex_exit(&scsb->scsb_mutex);
1248 }
1249 if (scsb->scsb_opens == 0 && scsb->scsb_clopens == 0) {
1250 scsb->scsb_state &= ~SCSB_OPEN;
1251 }
1252 RD(q)->q_ptr = WR(q)->q_ptr = NULL;
1253 qprocsoff(q);
1254 return (0);
1255 }
1256
1257 /*ARGSUSED*/
1258 static int
1259 sm_rput(queue_t *q, mblk_t *mp)
1260 {
1261 if (scsb_debug & 0x0010)
1262 cmn_err(CE_NOTE, "sm_rput");
1263 return (0);
1264 }
1265
1266 static int
1267 sm_wput(queue_t *q, mblk_t *mp)
1268 {
1269 scsb_state_t *scsb = (scsb_state_t *)WR(q)->q_ptr;
1270
1271 if (scsb_debug & 0x0010)
1272 cmn_err(CE_NOTE, "sm_wput(%d): mp %p", scsb->scsb_instance,
1273 (void *)mp);
1274
1275 switch (mp->b_datap->db_type) {
1276 default:
1277 freemsg(mp);
1278 break;
1279
1280 case M_FLUSH: /* canonical flush handling */
1281 if (*mp->b_rptr & FLUSHW) {
1282 flushq(q, FLUSHDATA);
1283 /* free any messages tied to scsb */
1284 }
1285
1286 if (*mp->b_rptr & FLUSHR) {
1287 *mp->b_rptr &= ~FLUSHW;
1288 qreply(q, mp);
1289 } else
1290 freemsg(mp);
1291 break;
1292
1293 case M_IOCTL:
1294 if (scsb_debug & 0x0010)
1295 cmn_err(CE_NOTE, "sm_wput(%d): M_IOCTL",
1296 scsb->scsb_instance);
1297 /* do ioctl */
1298 smf_ioctl(q, mp);
1299 break;
1300
1301 case M_DATA:
1302 if (scsb_debug & 0x0010)
1303 cmn_err(CE_NOTE, "sm_wput(%d): M_DATA",
1304 scsb->scsb_instance);
1305 if (!(scsb->scsb_state & SCSB_UP)) {
1306 freemsg(mp);
1307 return (0);
1308 }
1309 freemsg(mp);
1310 break;
1311
1312 case M_CTL:
1313 if (scsb_debug & 0x0010)
1314 cmn_err(CE_NOTE, "sm_wput(%d): M_CTL",
1315 scsb->scsb_instance);
1316 freemsg(mp);
1317 break;
1318 }
1319
1320 return (0);
1321 }
1322
1323
1324 /*
1325 * These are the system monitor upper ioctl functions.
1326 */
1327 static void
1328 smf_ioctl(queue_t *q, mblk_t *mp)
1329 {
1330 scsb_state_t *scsb = (scsb_state_t *)q->q_ptr;
1331 struct iocblk *iocp = (struct iocblk *)mp->b_rptr;
1332
1333 if (scsb_debug & 0x0020)
1334 cmn_err(CE_NOTE, "smf_ioctl(%d): (%p)->cmd=%x",
1335 scsb->scsb_instance, (void *)mp, iocp->ioc_cmd);
1336
1337 if (!(scsb->scsb_state & SCSB_UP)) {
1338 miocnak(q, mp, 0, ENXIO);
1339 return;
1340 }
1341 /*
1342 * Don't fail ALL commands if the SCB removed, since we still want to
1343 * satisfy some requests from the shadow registers, the last known
1344 * register contents.
1345 *
1346 * if (scsb->scsb_state & SCSB_FROZEN) {
1347 * iocp->ioc_error = EAGAIN;
1348 * mp->b_datap->db_type = M_IOCNAK;
1349 * qreply(q, mp);
1350 * return;
1351 * }
1352 */
1353
1354 iocp->ioc_error = 0;
1355 switch (iocp->ioc_cmd) {
1356 default:
1357 /* if we don't understand the ioctl */
1358 if (scsb_debug & 0x0022)
1359 cmn_err(CE_NOTE, "smf_ioctl(%d):unkown ioctl %x",
1360 scsb->scsb_instance, iocp->ioc_cmd);
1361 iocp->ioc_error = EINVAL;
1362 break;
1363
1364 case ENVC_IOC_GETMODE:
1365 {
1366 uint8_t *curr_mode;
1367
1368 iocp->ioc_error = miocpullup(mp, sizeof (uint8_t));
1369 if (iocp->ioc_error != 0)
1370 break;
1371
1372 curr_mode = (uint8_t *)mp->b_cont->b_rptr;
1373 if (scsb->scsb_state & SCSB_DEBUG_MODE)
1374 *curr_mode = (uint8_t)ENVC_DEBUG_MODE;
1375 else if (scsb->scsb_state & SCSB_DIAGS_MODE)
1376 *curr_mode = (uint8_t)ENVCTRL_DIAG_MODE;
1377 else
1378 *curr_mode = (uint8_t)ENVCTRL_NORMAL_MODE;
1379
1380 if (scsb_debug & 0x20) {
1381 cmn_err(CE_NOTE, "IOC_GETMODE: returning mode 0x%x",
1382 *curr_mode);
1383 }
1384 break;
1385 }
1386
1387 case ENVC_IOC_SETMODE:
1388 {
1389 uint8_t *curr_mode;
1390
1391 iocp->ioc_error = miocpullup(mp, sizeof (uint8_t));
1392 if (iocp->ioc_error != 0)
1393 break;
1394
1395 curr_mode = (uint8_t *)mp->b_cont->b_rptr;
1396 switch (*curr_mode) {
1397 case ENVCTRL_NORMAL_MODE:
1398 scsb->scsb_state &=
1399 ~(SCSB_DEBUG_MODE | SCSB_DIAGS_MODE);
1400 break;
1401 case ENVCTRL_DIAG_MODE:
1402 scsb->scsb_state |= SCSB_DIAGS_MODE;
1403 scsb->scsb_state &= ~SCSB_DEBUG_MODE;
1404 break;
1405 case ENVC_DEBUG_MODE:
1406 if (scsb->scsb_state &
1407 (SCSB_DIAGS_MODE | SCSB_DEBUG_MODE)) {
1408 scsb->scsb_state &= ~SCSB_DIAGS_MODE;
1409 scsb->scsb_state |= SCSB_DEBUG_MODE;
1410 } else {
1411 iocp->ioc_error = EACCES;
1412 }
1413 break;
1414 default:
1415 if (scsb_debug & 0x22) {
1416 cmn_err(CE_WARN,
1417 "IOC_SETMODE: Invalid mode 0x%x",
1418 *curr_mode);
1419 }
1420 iocp->ioc_error = EINVAL;
1421 break;
1422 }
1423 break;
1424 }
1425
1426 case ENVC_IOC_ACQUIRE_SLOT_LED_CTRL:
1427 if (scsb->scsb_state & SCSB_APP_SLOTLED_CTRL)
1428 iocp->ioc_error = EAGAIN;
1429 else {
1430 scsb->scsb_state |= SCSB_APP_SLOTLED_CTRL;
1431 iocp->ioc_error = 0;
1432 }
1433 break;
1434
1435 case ENVC_IOC_RELEASE_SLOT_LED_CTRL:
1436 scsb->scsb_state &= ~SCSB_APP_SLOTLED_CTRL;
1437 iocp->ioc_error = 0;
1438 break;
1439
1440 /*
1441 * Not an exposed interface, only used by development utilities.
1442 */
1443 case SCSBIOC_GET_VERSIONS:
1444 {
1445 uint8_t *ppromid, promid;
1446 scsb_ids_t *sids;
1447
1448 if (iocp->ioc_count == sizeof (uint8_t)) {
1449 iocp->ioc_error = miocpullup(mp, sizeof (uint8_t));
1450 if (iocp->ioc_error != 0)
1451 break;
1452
1453 ppromid = (uint8_t *)mp->b_cont->b_rptr;
1454 *ppromid = (uint8_t)(mct_system_info.
1455 fru_info_list[SCB])->fru_version;
1456 promid = *ppromid;
1457 } else {
1458 iocp->ioc_error = miocpullup(mp, sizeof (scsb_ids_t));
1459 if (iocp->ioc_error != 0)
1460 break;
1461
1462 sids = (scsb_ids_t *)mp->b_cont->b_rptr;
1463 bcopy(modldrv.drv_linkinfo, sids->modldrv_string,
1464 SCSB_MODSTR_LEN);
1465 bcopy(scsb_build_version, sids->scsb_version,
1466 SCSB_VERSTR_LEN);
1467 sids->promid = (uint8_t)(mct_system_info.
1468 fru_info_list[SCB])->fru_version;
1469
1470 promid = sids->promid;
1471 if (scsb_debug & 0x20) {
1472 cmn_err(CE_NOTE,
1473 "IOC_GET_VERSIONS: sizeof(scsb_ids_t) "
1474 "= %lu", sizeof (scsb_ids_t));
1475 }
1476 }
1477 if (scsb_debug & 0x20) {
1478 cmn_err(CE_NOTE,
1479 "IOC_GET_VERSIONS: SCB PROMID = 0x%x", promid);
1480 }
1481 break;
1482 }
1483
1484 #ifdef DEBUG
1485 case ENVC_IOC_REGISTER_PID:
1486 iocp->ioc_error = miocpullup(mp, sizeof (pid_t));
1487 if (iocp->ioc_error == 0) {
1488 if (add_event_proc(scsb, *(pid_t *)mp->b_cont->b_rptr))
1489 iocp->ioc_error = ENOMEM;
1490 }
1491 break;
1492
1493 case ENVC_IOC_UNREGISTER_PID:
1494 iocp->ioc_error = miocpullup(mp, sizeof (pid_t));
1495 if (iocp->ioc_error == 0) {
1496 if (del_event_proc(scsb, *(pid_t *)mp->b_cont->b_rptr))
1497 iocp->ioc_error = EINVAL;
1498 }
1499 break;
1500
1501 case SCSBIOC_VALUE_MODE:
1502 {
1503 uint32_t *mode_vals;
1504 int three_vals = 0;
1505
1506 if (!(scsb->scsb_state & SCSB_DEBUG_MODE)) {
1507 iocp->ioc_error = EINVAL;
1508 break;
1509 }
1510
1511 if (iocp->ioc_count == sizeof (uint32_t) * 3)
1512 three_vals = 1;
1513 else if (iocp->ioc_count != sizeof (uint32_t) * 2) {
1514 iocp->ioc_error = EINVAL;
1515 break;
1516 }
1517
1518 iocp->ioc_error = miocpullup(mp, iocp->ioc_count);
1519 if (iocp->ioc_error != 0)
1520 break;
1521
1522 /*
1523 * check mode_vals[0] for get/set option. setting
1524 * scsb_state is not valid for now. 0 == GET, 1 == SET
1525 */
1526 mode_vals = (uint32_t *)mp->b_cont->b_rptr;
1527 if (mode_vals[0]) {
1528 scsb_debug = mode_vals[1];
1529 } else {
1530 mode_vals[0] = scsb->scsb_state;
1531 if (three_vals) {
1532 mode_vals[1] = scsb->scsb_hsc_state;
1533 mode_vals[2] = scsb_debug;
1534 } else
1535 mode_vals[1] = scsb_debug;
1536 }
1537 if ((scsb_debug & 0x20) && three_vals) {
1538 cmn_err(CE_NOTE, "IOC_VALUE_MODE: mode_vals: "
1539 "0x%x/0x%x/0x%x; ioc_count = 0x%lx",
1540 mode_vals[0], mode_vals[1], mode_vals[2],
1541 iocp->ioc_count);
1542 }
1543 break;
1544 }
1545
1546 #ifdef DEBUG
1547 case SCSBIOC_GET_SLOT_INFO:
1548 {
1549 hsc_slot_t *slot_info = NULL;
1550 uint32_t *slot_vals;
1551 int pslotnum;
1552
1553 if (!(scsb->scsb_state & SCSB_DEBUG_MODE)) {
1554 iocp->ioc_error = EINVAL;
1555 break;
1556 }
1557
1558 iocp->ioc_error = miocpullup(mp, sizeof (uint32_t) * 2);
1559 if (iocp->ioc_error != 0)
1560 break;
1561
1562 slot_vals = (uint32_t *)mp->b_cont->b_rptr;
1563 pslotnum = (int)*slot_vals;
1564 hsc_ac_op((int)scsb->scsb_instance, pslotnum,
1565 SCSB_HSC_AC_GET_SLOT_INFO, &slot_info);
1566 if (slot_info == NULL) {
1567 iocp->ioc_error = ENODEV;
1568 break;
1569 }
1570 *slot_vals = (uint32_t)slot_info->hs_flags;
1571 *(++slot_vals) = (uint32_t)slot_info->hs_slot_state;
1572 if (scsb_debug & 0x20) {
1573 cmn_err(CE_NOTE, "IOC_GET_SLOT_STATE: slot_vals: "
1574 "0x%x/0x%x; ioc_count = 0x%lx",
1575 slot_vals[0], slot_vals[1], iocp->ioc_count);
1576 }
1577 break;
1578 }
1579 #endif /* DEBUG */
1580
1581 case SCSBIOC_GET_FAN_STATUS:
1582 case SCSBIOC_GET_INTR_ARRAY:
1583 /* for now we don't understand these ioctls */
1584 if (scsb_debug & 0x0022)
1585 cmn_err(CE_NOTE, "smf_ioctl(%d):unknown ioctl %x",
1586 scsb->scsb_instance, iocp->ioc_cmd);
1587 iocp->ioc_error = EINVAL;
1588 break;
1589 #endif /* DEBUG */
1590
1591 case SCSBIOC_LED_OK_GET:
1592 case SCSBIOC_LED_NOK_GET:
1593 case SCSBIOC_LED_OK_SET:
1594 case SCSBIOC_LED_NOK_SET:
1595 case SCSBIOC_BHEALTHY_GET:
1596 case SCSBIOC_SLOT_OCCUPANCY:
1597 case SCSBIOC_RESET_UNIT:
1598 if (!(scsb->scsb_state & (SCSB_DIAGS_MODE | SCSB_DEBUG_MODE))) {
1599 iocp->ioc_error = EACCES;
1600 break;
1601 }
1602 /*FALLTHROUGH*/
1603
1604 case ENVC_IOC_GETDSKLED:
1605 case ENVC_IOC_SETDSKLED:
1606 case ENVC_IOC_SETFSP:
1607 {
1608 scsb_uinfo_t *suip;
1609
1610 iocp->ioc_error = miocpullup(mp, sizeof (scsb_uinfo_t));
1611 if (iocp->ioc_error != 0)
1612 break;
1613
1614 suip = (scsb_uinfo_t *)mp->b_cont->b_rptr;
1615 switch (iocp->ioc_cmd) {
1616 case SCSBIOC_LED_OK_GET:
1617 iocp->ioc_error = scsb_led_get(scsb, suip, OK);
1618 break;
1619 case SCSBIOC_LED_NOK_GET:
1620 iocp->ioc_error = scsb_led_get(scsb, suip, NOK);
1621 break;
1622 case SCSBIOC_LED_OK_SET:
1623 iocp->ioc_error = scsb_led_set(scsb, suip, OK);
1624 break;
1625 case SCSBIOC_LED_NOK_SET:
1626 iocp->ioc_error = scsb_led_set(scsb, suip, NOK);
1627 break;
1628 case SCSBIOC_BHEALTHY_GET:
1629 iocp->ioc_error = scsb_bhealthy_slot(scsb, suip);
1630 break;
1631 case SCSBIOC_SLOT_OCCUPANCY:
1632 iocp->ioc_error = scsb_slot_occupancy(scsb, suip);
1633 break;
1634 case SCSBIOC_RESET_UNIT:
1635 iocp->ioc_error = scsb_reset_unit(scsb, suip);
1636 break;
1637 case ENVC_IOC_GETDSKLED:
1638 if (suip->unit_type != DISK) {
1639 iocp->ioc_error = EINVAL;
1640 break;
1641 }
1642 iocp->ioc_error = scsb_led_get(scsb, suip, NOUSE);
1643 break;
1644 case ENVC_IOC_SETDSKLED:
1645 if (suip->unit_type != DISK) {
1646 iocp->ioc_error = EINVAL;
1647 break;
1648 }
1649 iocp->ioc_error = scsb_led_set(scsb, suip, NOUSE);
1650 break;
1651 case ENVC_IOC_SETFSP:
1652 if (scsb->scsb_state & SCSB_FROZEN) {
1653 iocp->ioc_error = EAGAIN;
1654 break;
1655 }
1656 iocp->ioc_error = scsb_led_set(scsb, suip, NOUSE);
1657 break;
1658 }
1659 break;
1660 }
1661
1662 case SCSBIOC_FAKE_INTR: {
1663 uint32_t ui;
1664
1665 if (!(scsb->scsb_state & SCSB_DEBUG_MODE)) {
1666 iocp->ioc_error = EINVAL;
1667 break;
1668 }
1669 if (mp->b_cont == NULL)
1670 ui = 0;
1671 else {
1672 iocp->ioc_error = miocpullup(mp, sizeof (uint32_t));
1673 if (iocp->ioc_error != 0)
1674 break;
1675 ui = *(uint32_t *)mp->b_cont->b_rptr;
1676 }
1677 iocp->ioc_error = scsb_fake_intr(scsb, ui);
1678 break;
1679 }
1680
1681 case SCSBIOC_GET_STATUS :
1682 if (!(scsb->scsb_state & SCSB_DEBUG_MODE)) {
1683 iocp->ioc_error = EINVAL;
1684 break;
1685 }
1686 iocp->ioc_error = miocpullup(mp, sizeof (scsb_status_t));
1687 if (iocp->ioc_error == 0)
1688 iocp->ioc_error = scsb_get_status(scsb,
1689 (scsb_status_t *)mp->b_cont->b_rptr);
1690 break;
1691
1692 case SCSBIOC_ALL_LEDS_ON :
1693 if (!(scsb->scsb_state & (SCSB_DIAGS_MODE | SCSB_DEBUG_MODE)))
1694 iocp->ioc_error = EACCES;
1695 else
1696 iocp->ioc_error = scsb_leds_switch(scsb, ON);
1697 break;
1698
1699 case SCSBIOC_ALL_LEDS_OFF :
1700 if (!(scsb->scsb_state & (SCSB_DIAGS_MODE | SCSB_DEBUG_MODE)))
1701 iocp->ioc_error = EACCES;
1702 else
1703 iocp->ioc_error = scsb_leds_switch(scsb, OFF);
1704 break;
1705
1706 case SCSBIOC_REG_READ:
1707 case SCSBIOC_REG_WRITE:
1708 if (!(scsb->scsb_state & (SCSB_DIAGS_MODE | SCSB_DEBUG_MODE))) {
1709 iocp->ioc_error = EACCES;
1710 } else {
1711 scsb_ioc_rdwr_t *iocrdwrp;
1712
1713 if (scsb->scsb_state & SCSB_FROZEN &&
1714 !(scsb->scsb_state & SCSB_DEBUG_MODE)) {
1715 iocp->ioc_error = EAGAIN;
1716 break;
1717 }
1718
1719 iocp->ioc_error = miocpullup(mp, sizeof (*iocrdwrp));
1720 if (iocp->ioc_error == 0) {
1721 iocrdwrp =
1722 (scsb_ioc_rdwr_t *)mp->b_cont->b_rptr;
1723
1724 if (iocp->ioc_cmd == SCSBIOC_REG_READ) {
1725 if (iocrdwrp->ioc_rlen > 0) {
1726 sm_ioc_rdwr(q, mp, I2C_WR_RD);
1727 return;
1728 }
1729 } else {
1730 if (iocrdwrp->ioc_wlen > 0) {
1731 sm_ioc_rdwr(q, mp, I2C_WR);
1732 return;
1733 }
1734 }
1735 iocp->ioc_error = EINVAL;
1736 break;
1737 }
1738 }
1739 break;
1740
1741 case SCSBIOC_SHUTDOWN_POLL:
1742 case SCSBIOC_INTEVENT_POLL:
1743 if (!(scsb->scsb_state & SCSB_DEBUG_MODE)) {
1744 iocp->ioc_error = EINVAL;
1745 break;
1746 }
1747 iocp->ioc_error = miocpullup(mp, sizeof (uint32_t));
1748 if (iocp->ioc_error == 0)
1749 iocp->ioc_error = scsb_polled_int(scsb, iocp->ioc_cmd,
1750 (uint32_t *)mp->b_cont->b_rptr);
1751 break;
1752
1753 case SCSBIOC_RESTORE :
1754 if (!(scsb->scsb_state & (SCSB_DIAGS_MODE | SCSB_DEBUG_MODE)))
1755 iocp->ioc_error = EACCES;
1756 else {
1757 scsb_restore(scsb);
1758 (void) scsb_toggle_psmint(scsb, 1);
1759 iocp->ioc_error = 0;
1760 }
1761 break;
1762
1763 case SCSBIOC_FREEZE :
1764 if (!(scsb->scsb_state & (SCSB_DIAGS_MODE | SCSB_DEBUG_MODE)))
1765 iocp->ioc_error = EACCES;
1766 else {
1767 scsb_freeze_check(scsb);
1768 scsb_freeze(scsb);
1769 iocp->ioc_error = 0;
1770 }
1771 break;
1772
1773 /*
1774 * envmond:alarmcard.so response to SCTRL_EVENT_ALARM_INSERTION
1775 */
1776 case ENVC_IOC_ACCONF_RESTORED:
1777 (void) scsb_hsc_ac_op(scsb, scsb->ac_slotnum,
1778 SCSB_HSC_AC_SET_BUSY);
1779 break;
1780
1781 /*
1782 * envmond:alarmcard.so response to SCTRL_EVENT_ALARM_REMOVAL
1783 */
1784 case ENVC_IOC_ACCONF_STORED:
1785 if (scsb->scsb_state & SCSB_FROZEN) {
1786 iocp->ioc_error = EAGAIN;
1787 break;
1788 }
1789 (void) scsb_hsc_ac_op(scsb, scsb->ac_slotnum,
1790 SCSB_HSC_AC_UNCONFIGURE);
1791 break;
1792
1793 #ifdef DEBUG
1794 case SCSBIOC_TOPOLOGY_DUMP:
1795 if (!(scsb->scsb_state & SCSB_DEBUG_MODE))
1796 iocp->ioc_error = EINVAL;
1797 else {
1798 mct_topology_dump(scsb, 1);
1799 iocp->ioc_error = 0;
1800 }
1801 break;
1802 #endif
1803 }
1804 if (iocp->ioc_error)
1805 mp->b_datap->db_type = M_IOCNAK;
1806 else
1807 mp->b_datap->db_type = M_IOCACK;
1808 qreply(q, mp);
1809 }
1810
1811 static fru_info_t *
1812 find_fru_info(fru_id_t fru_id)
1813 {
1814 int i;
1815 fru_info_t *fru_ptr;
1816
1817 if (scsb_debug & 0x00100001)
1818 cmn_err(CE_NOTE, "find_fru_info(0x%x)", fru_id);
1819 if (fru_id == (fru_id_t)0)
1820 return ((fru_info_t *)NULL);
1821 for (i = 0; i < SCSB_UNIT_TYPES; ++i) {
1822 fru_ptr = mct_system_info.fru_info_list[i];
1823 while (fru_ptr != NULL) {
1824 if (fru_ptr->fru_id == fru_id)
1825 return (fru_ptr);
1826 fru_ptr = fru_ptr->next;
1827 }
1828 }
1829 return ((fru_info_t *)NULL);
1830 }
1831
1832
1833 struct scsb_cb_entry {
1834 void *cb_softstate_ptr;
1835 fru_id_t cb_fru_id;
1836 scsb_fru_event_t cb_event;
1837 void (*cb_func)
1838 (void *, scsb_fru_event_t, scsb_fru_status_t);
1839 fru_info_t *cb_fru_ptr;
1840 struct scsb_cb_entry *cb_next;
1841 };
1842
1843 #ifdef DEBUG
1844 int scsb_cb_count = 0;
1845 #else
1846 static
1847 #endif
1848 struct scsb_cb_entry *scsb_cb_table;
1849
1850 /*
1851 * global function for interested FRU drivers to register a callback function,
1852 * to be called when FRU presence status changes.
1853 */
1854 scsb_fru_status_t
1855 scsb_fru_register(void (*cb_func)(void *, scsb_fru_event_t, scsb_fru_status_t),
1856 void *soft_ptr, fru_id_t fru_id)
1857 {
1858 struct scsb_cb_entry *cbe_ptr;
1859
1860 if (scsb_debug & 0x00800001) {
1861 cmn_err(CE_NOTE,
1862 "scsb_fru_register: FRU_ID 0x%x", (int)fru_id);
1863 }
1864 if (!(scsb_global_state & SCSB_UP)) {
1865 return (FRU_NOT_AVAILABLE);
1866 }
1867 if (cb_func == NULL || fru_id == (fru_id_t)0)
1868 return (FRU_NOT_AVAILABLE);
1869 if (scsb_cb_table == NULL)
1870 scsb_cb_table = (struct scsb_cb_entry *)
1871 kmem_zalloc(sizeof (struct scsb_cb_entry), KM_SLEEP);
1872 cbe_ptr = scsb_cb_table;
1873 while (cbe_ptr->cb_softstate_ptr != NULL) {
1874 if (cbe_ptr->cb_next == (struct scsb_cb_entry *)NULL) {
1875 cbe_ptr->cb_next = (struct scsb_cb_entry *)
1876 kmem_zalloc(sizeof (struct scsb_cb_entry),
1877 KM_SLEEP);
1878 cbe_ptr = cbe_ptr->cb_next;
1879 break;
1880 }
1881 cbe_ptr = cbe_ptr->cb_next;
1882 }
1883 cbe_ptr->cb_softstate_ptr = soft_ptr;
1884 cbe_ptr->cb_fru_id = fru_id;
1885 cbe_ptr->cb_func = cb_func;
1886 cbe_ptr->cb_next = (struct scsb_cb_entry *)NULL;
1887 cbe_ptr->cb_fru_ptr = find_fru_info(fru_id);
1888 #ifdef DEBUG
1889 scsb_cb_count++;
1890 #endif
1891 if (scsb_debug & 0x00800000) {
1892 cmn_err(CE_NOTE,
1893 "scsb_fru_register: FRU_ID 0x%x, status=%d",
1894 (int)fru_id,
1895 (cbe_ptr->cb_fru_ptr == (fru_info_t *)NULL) ?
1896 0xff : cbe_ptr->cb_fru_ptr->fru_status);
1897 }
1898 if (cbe_ptr->cb_fru_ptr == (fru_info_t *)NULL)
1899 return (FRU_NOT_AVAILABLE);
1900 if (cbe_ptr->cb_fru_ptr->fru_status & FRU_PRESENT)
1901 return (FRU_PRESENT);
1902 return (FRU_NOT_PRESENT);
1903 }
1904
1905 void
1906 scsb_fru_unregister(void *soft_ptr, fru_id_t fru_id)
1907 {
1908 struct scsb_cb_entry *prev_ptr, *cbe_ptr;
1909
1910 if (scsb_debug & 0x00800001) {
1911 cmn_err(CE_NOTE, "scsb_fru_unregister(0x%p, 0x%x)",
1912 soft_ptr, (int)fru_id);
1913 }
1914 if ((cbe_ptr = scsb_cb_table) == NULL || fru_id == (fru_id_t)0)
1915 return;
1916 prev_ptr = cbe_ptr;
1917 do {
1918 if (cbe_ptr->cb_softstate_ptr == soft_ptr &&
1919 cbe_ptr->cb_fru_id == fru_id) {
1920 if (cbe_ptr == scsb_cb_table)
1921 scsb_cb_table = cbe_ptr->cb_next;
1922 else
1923 prev_ptr->cb_next = cbe_ptr->cb_next;
1924 kmem_free(cbe_ptr, sizeof (struct scsb_cb_entry));
1925 #ifdef DEBUG
1926 scsb_cb_count--;
1927 #endif
1928 return;
1929 }
1930 prev_ptr = cbe_ptr;
1931 } while ((cbe_ptr = cbe_ptr->cb_next) != NULL);
1932 }
1933
1934 /*
1935 * global function for interested FRU drivers to call to check
1936 * FRU presence status.
1937 */
1938 scsb_fru_status_t
1939 scsb_fru_status(uchar_t fru_id)
1940 {
1941 fru_info_t *fru_ptr;
1942
1943 fru_ptr = find_fru_info(fru_id);
1944 if (scsb_debug & 0x00800001) {
1945 cmn_err(CE_NOTE, "scsb_fru_status(0x%x): status=0x%x",
1946 fru_id, (fru_ptr == (fru_info_t *)NULL) ? 0xff :
1947 (int)fru_ptr->fru_status);
1948 }
1949 if (fru_ptr == (fru_info_t *)NULL)
1950 return (FRU_NOT_AVAILABLE);
1951 return (fru_ptr->fru_status);
1952 }
1953
1954 /*
1955 * Global function for the other interruptible FRU device sharing the
1956 * same interrupt line to register the interrupt handler with scsb.
1957 * This enables all the handlers to be called whenever the interrupt
1958 * line is asserted by anyone shaing the interrupt line.
1959 */
1960
1961 /*
1962 * The interrupt handler table is currently a linked list. probably a
1963 * hash table will be more efficient. Usage of these facilities can
1964 * happen even before scsb is attached, so do not depend on scsb
1965 * structure being present.
1966 */
1967 struct fru_intr_entry {
1968 void *softstate_ptr;
1969 int (*fru_intr_handler)(void *);
1970 fru_id_t fru_id;
1971 struct fru_intr_entry *fru_intr_next;
1972 } *fru_intr_table = NULL;
1973
1974 int
1975 scsb_intr_register(int (*intr_handler)(void *), void * soft_ptr,
1976 fru_id_t fru_id)
1977 {
1978 struct fru_intr_entry *intr_table_entry;
1979 intr_table_entry = (struct fru_intr_entry *)
1980 kmem_zalloc(sizeof (struct fru_intr_entry), KM_SLEEP);
1981
1982 if (intr_table_entry == NULL) {
1983 return (DDI_FAILURE);
1984 }
1985
1986 if (intr_handler == NULL || soft_ptr == NULL || fru_id == 0) {
1987 kmem_free(intr_table_entry, sizeof (struct fru_intr_entry));
1988 return (DDI_FAILURE);
1989 }
1990
1991 intr_table_entry->softstate_ptr = soft_ptr;
1992 intr_table_entry->fru_intr_handler = intr_handler;
1993 intr_table_entry->fru_id = fru_id;
1994 intr_table_entry->fru_intr_next = fru_intr_table;
1995 fru_intr_table = intr_table_entry;
1996
1997 return (DDI_SUCCESS);
1998 }
1999
2000 /*
2001 * Removed interrupt_handler of fru from interrupt call chain
2002 */
2003 void
2004 scsb_intr_unregister(fru_id_t fru_id)
2005 {
2006 struct fru_intr_entry *intr_entry = fru_intr_table,
2007 *prev_entry = intr_entry;
2008
2009 if (fru_id == 0) {
2010 return;
2011 }
2012
2013 do {
2014 if (intr_entry->fru_id == fru_id) {
2015 /* found a match, remove entry */
2016 if (intr_entry == fru_intr_table)
2017 fru_intr_table = intr_entry->fru_intr_next;
2018 else
2019 prev_entry->fru_intr_next =
2020 intr_entry->fru_intr_next;
2021
2022 kmem_free(intr_entry,
2023 sizeof (struct fru_intr_entry));
2024 return;
2025 }
2026 prev_entry = intr_entry;
2027
2028 } while ((intr_entry = intr_entry->fru_intr_next) != NULL);
2029 }
2030
2031 /*
2032 * Invoke all the registered interrupt handlers, whenever scsb_intr
2033 * is called. This function will go through the list of entries
2034 * in the fru interrupt table and invoke each function. Returns
2035 * whether interrupt is claimed or unclaimed.
2036 */
2037 static int
2038 scsb_invoke_intr_chain()
2039 {
2040 int retval = DDI_INTR_UNCLAIMED;
2041 struct fru_intr_entry *intr_entry = fru_intr_table;
2042
2043 while (intr_entry != NULL) {
2044 retval = (*intr_entry->
2045 fru_intr_handler)(intr_entry->softstate_ptr);
2046 if (retval == DDI_INTR_CLAIMED) {
2047 return (retval);
2048 }
2049
2050 intr_entry = intr_entry->fru_intr_next;
2051 }
2052
2053 return (retval);
2054 }
2055
2056
2057 /*
2058 * The scsb_ioc_rdwr_t is similar enough to an i2c_transfer_t that we can
2059 * translate the structures and use the i2c_transfer() service.
2060 */
2061 static void
2062 sm_ioc_rdwr(queue_t *q, mblk_t *mp, int op)
2063 {
2064 scsb_state_t *scsb = (scsb_state_t *)q->q_ptr;
2065 struct iocblk *iocp = (struct iocblk *)mp->b_rptr;
2066 scsb_ioc_rdwr_t *iocrdwrp;
2067 int len, error;
2068 uchar_t *uc, reg;
2069
2070 if (scsb_debug & 0x0040)
2071 cmn_err(CE_CONT, "sm_ioc_rdwr[%d]:", scsb->scsb_instance);
2072 iocrdwrp = (scsb_ioc_rdwr_t *)mp->b_cont->b_rptr;
2073 if (op == I2C_WR) {
2074 len = iocrdwrp->ioc_wlen;
2075 uc = iocrdwrp->ioc_wbuf;
2076 } else {
2077 len = iocrdwrp->ioc_rlen;
2078 uc = iocrdwrp->ioc_rbuf;
2079 }
2080 /*
2081 * Check SCB register index boundries and requested len of read/write
2082 */
2083 reg = iocrdwrp->ioc_regindex;
2084 if (reg < SCSB_REG_ADDR_START || (reg + len) >
2085 (SCSB_REG_ADDR_START + SCTRL_TOTAL_NUMREGS))
2086 error = EINVAL;
2087 else
2088 error = scsb_rdwr_register(scsb, op, reg, len, uc, 1);
2089 if (error) {
2090 if (scsb_debug & 0x0042)
2091 cmn_err(CE_WARN,
2092 "sm_ioc_rdwr: rdwr_register failure: %d", error);
2093 mp->b_datap->db_type = M_IOCNAK;
2094 } else
2095 mp->b_datap->db_type = M_IOCACK;
2096 iocp->ioc_error = error;
2097 qreply(q, mp);
2098 }
2099
2100 /*
2101 * names for (scsb_utype_t) FRU types
2102 */
2103 static char *led_name[SCSB_LED_TYPES] = { "NOK", "OK" };
2104 static char *unit_type_name[SCSB_UNIT_TYPES] = {
2105 "SLOT", "PDU", "POWER SUPPLY", "DISK", "FAN", "ALARM",
2106 "SCB", "SSB", "CFTM", "CRTM", "PRTM"
2107 };
2108
2109 /*
2110 * Discover the register and bit-offset for LEDs and Reset registers,
2111 * according to unit_type, unit_number, and led_type.
2112 */
2113 static int
2114 scsb_get_led_regnum(scsb_state_t *scsb,
2115 scsb_uinfo_t *suip,
2116 uchar_t *regptr,
2117 int *unitptr,
2118 scsb_led_t led_type)
2119 {
2120 int code, base, error;
2121
2122 /* OK here means presence (OK) LEDs */
2123 if (led_type == OK)
2124 base = (SCTRL_LED_OK_BASE);
2125 else
2126 base = (SCTRL_LED_NOK_BASE);
2127 error = 0;
2128 if (scsb_debug & 0x0100) {
2129 cmn_err(CE_NOTE, "get_led_regnum: suip <%x, %x, %x, %x>\n",
2130 suip->unit_type, suip->unit_number,
2131 led_type, suip->unit_state);
2132 }
2133 /*
2134 * It was requested that the scsb driver allow accesses to SCB device
2135 * registers for FRUs that cannot be present.
2136 * So except for SLOTs, if the unit_number check fails, we now
2137 * just log a message, but ONLY if scsb_debug error messages are
2138 * enabled.
2139 */
2140 switch (suip->unit_type) {
2141 case SLOT:
2142 if (suip->unit_number < 1 || suip->unit_number >
2143 ((scsb->scsb_state & SCSB_IS_TONGA) ?
2144 TG_MAX_SLOTS : MC_MAX_SLOTS)) {
2145 error = EINVAL;
2146 break;
2147 }
2148 code = FRU_UNIT_TO_EVCODE(SLOT, suip->unit_number);
2149 break;
2150
2151 case PDU:
2152 if (suip->unit_number < 1 || suip->unit_number >
2153 ((scsb->scsb_state & SCSB_IS_TONGA) ?
2154 TG_MAX_PDU : MC_MAX_PDU)) {
2155 if (scsb_debug & 0x0002) {
2156 cmn_err(CE_WARN,
2157 "get_led_regnum: unit number %d "
2158 "is out of range", suip->unit_number);
2159 }
2160 error = EINVAL;
2161 break;
2162 }
2163 code = FRU_UNIT_TO_EVCODE(PDU, suip->unit_number);
2164 break;
2165
2166 case PS:
2167 if ((suip->unit_number < 1 || suip->unit_number >
2168 ((scsb->scsb_state & SCSB_IS_TONGA) ?
2169 TG_MAX_PS : MC_MAX_PS))) {
2170 if (scsb_debug & 0x0002) {
2171 cmn_err(CE_WARN,
2172 "get_led_regnum: unit number %d "
2173 "is out of range", suip->unit_number);
2174 }
2175 error = EINVAL;
2176 break;
2177 }
2178 code = FRU_UNIT_TO_EVCODE(PS, suip->unit_number);
2179 break;
2180
2181 case DISK:
2182 if ((suip->unit_number < 1 || suip->unit_number >
2183 ((scsb->scsb_state & SCSB_IS_TONGA) ?
2184 TG_MAX_DISK : MC_MAX_DISK))) {
2185 if (scsb_debug & 0x0002) {
2186 cmn_err(CE_WARN,
2187 "get_led_regnum: unit number %d "
2188 "is out of range", suip->unit_number);
2189 }
2190 if (!(scsb_debug & 0x20000000)) {
2191 error = EINVAL;
2192 break;
2193 }
2194 }
2195 code = FRU_UNIT_TO_EVCODE(DISK, suip->unit_number);
2196 break;
2197
2198 case FAN:
2199 if (suip->unit_number < 1 || suip->unit_number >
2200 ((scsb->scsb_state & SCSB_IS_TONGA) ?
2201 TG_MAX_FAN : MC_MAX_FAN)) {
2202 if (scsb_debug & 0x0002) {
2203 cmn_err(CE_WARN,
2204 "get_led_regnum: unit number %d "
2205 "is out of range", suip->unit_number);
2206 }
2207 error = EINVAL;
2208 break;
2209 }
2210 code = FRU_UNIT_TO_EVCODE(FAN, suip->unit_number);
2211 break;
2212
2213 case CFTM:
2214 if (suip->unit_number < 1 || suip->unit_number >
2215 ((scsb->scsb_state & SCSB_IS_TONGA) ?
2216 TG_MAX_CFTM : MC_MAX_CFTM)) {
2217 if (scsb_debug & 0x0002) {
2218 cmn_err(CE_WARN,
2219 "get_led_regnum: unit number %d "
2220 "is out of range", suip->unit_number);
2221 }
2222 error = EINVAL;
2223 break;
2224 }
2225 code = FRU_UNIT_TO_EVCODE(CFTM, suip->unit_number);
2226 break;
2227
2228 case SCB:
2229 if (suip->unit_number < 1 || suip->unit_number >
2230 ((scsb->scsb_state & SCSB_IS_TONGA) ?
2231 TG_MAX_SCB : MC_MAX_SCB)) {
2232 if (scsb_debug & 0x0002) {
2233 cmn_err(CE_WARN,
2234 "get_led_regnum: unit number %d "
2235 "is out of range", suip->unit_number);
2236 }
2237 error = EINVAL;
2238 break;
2239 }
2240 code = FRU_UNIT_TO_EVCODE(SCB, suip->unit_number);
2241 break;
2242
2243 case ALARM:
2244 error = EINVAL;
2245 break;
2246
2247 default:
2248 if (scsb_debug & 0x0102) {
2249 cmn_err(CE_WARN,
2250 "scsb_get_led_regnum(): unknown unit type %d",
2251 suip->unit_type);
2252 }
2253 error = EINVAL;
2254 break;
2255 }
2256 if (!error) {
2257 *unitptr = FRU_OFFSET(code, base);
2258 *regptr = FRU_REG_ADDR(code, base);
2259 if (scsb_debug & 0x0100) {
2260 cmn_err(CE_NOTE, "get_led_regnum: unitptr=%x, "
2261 "regptr=%x, code = %x\n",
2262 *unitptr, *regptr, code);
2263 }
2264 }
2265 return (error);
2266 }
2267
2268 /*
2269 * P1.0 and P1.5
2270 * Map 1.0 Tonga Slot Numbers: SCB to user interface and back.
2271 * User interface means positional slot numbers, as on P1.0 SSB,
2272 * which are used by hpcsvc/hsc and kstat/ioctl interfaces.
2273 */
2274
2275 /* HSC slotnum (Positional SLotnum) to SCB CFG bit-offset */
2276 static int psl2sco[TG_MAX_SLOTS + 1] = { -1 };
2277
2278 /*
2279 * MAP Positional (HSC) slot number to SCB CFG register bit-offset
2280 */
2281 static int
2282 tonga_pslotnum_to_cfgbit(scsb_state_t *scsb, int sln)
2283 {
2284 int base = SCTRL_SYSCFG_BASE;
2285 if (!(scsb->scsb_state & SCSB_IS_TONGA)) {
2286 return (sln);
2287 }
2288 if (sln < 1 || sln > TG_MAX_SLOTS) {
2289 return (sln);
2290 }
2291 /*
2292 * Should move this to _init(), but for now,
2293 * check for initialized table
2294 */
2295 if (psl2sco[0]) {
2296 psl2sco[0] = 0;
2297 psl2sco[1] = FRU_OFFSET(SCTRL_EVENT_SLOT5, base);
2298 psl2sco[2] = FRU_OFFSET(SCTRL_EVENT_SLOT2, base);
2299 psl2sco[3] = FRU_OFFSET(SCTRL_EVENT_SLOT1, base);
2300 psl2sco[4] = FRU_OFFSET(SCTRL_EVENT_SLOT3, base);
2301 psl2sco[5] = FRU_OFFSET(SCTRL_EVENT_SLOT4, base);
2302 }
2303 #ifdef DEBUG
2304 if (scsb_debug & 0x10000000) {
2305 cmn_err(CE_NOTE, "tonga_pslotnum_to_cfgbit: old/new: %d/%d",
2306 sln, psl2sco[sln]);
2307 }
2308 #endif
2309 return (psl2sco[sln]);
2310 }
2311
2312 /* positional slotnum to SCB slotnum */
2313 static int psl2ssl[6] = {
2314 0, 5, 2, 1, 3, 4
2315 };
2316
2317 /* SCB slotnum to positional slotnum */
2318 static int ssl2psl[6] = {
2319 0, 3, 2, 4, 5, 1
2320 };
2321
2322 /*
2323 * P1.0 and P1.5
2324 * HSC Slot numbers (physical positions or positional slotnum)
2325 * to
2326 * SCB slot numbers (reset,present,healthy)
2327 *
2328 * These requests come mainly from application interface and
2329 * HSC using the scsb_uinfo_t structure.
2330 */
2331 static void
2332 tonga_slotnum_check(scsb_state_t *scsb, scsb_uinfo_t *suip)
2333 {
2334 if (!(scsb->scsb_state & SCSB_IS_TONGA && scsb->scsb_state &
2335 (SCSB_P10_PROM | SCSB_P15_PROM | SCSB_P20_PROM))) {
2336 return;
2337 }
2338 if (suip->unit_number < 1 || suip->unit_number > TG_MAX_SLOTS) {
2339 return;
2340 }
2341 #ifdef DEBUG
2342 if (scsb_debug & 0x10000000) {
2343 cmn_err(CE_NOTE, "tonga_slotnum_check: old/new: %d/%d",
2344 suip->unit_number, psl2ssl[suip->unit_number]);
2345 }
2346 #endif
2347 suip->unit_number = psl2ssl[suip->unit_number];
2348 }
2349
2350 /*
2351 * P1.0 and P1.5
2352 */
2353 static int
2354 tonga_psl_to_ssl(scsb_state_t *scsb, int slotnum)
2355 {
2356 if (!(scsb->scsb_state & SCSB_IS_TONGA && scsb->scsb_state &
2357 (SCSB_P10_PROM | SCSB_P15_PROM | SCSB_P20_PROM))) {
2358 return (slotnum);
2359 }
2360 if (slotnum < 1 || slotnum > TG_MAX_SLOTS) {
2361 return (slotnum);
2362 }
2363 #ifdef DEBUG
2364 if (scsb_debug & 0x10000000) {
2365 cmn_err(CE_NOTE, "tonga_psl_to_ssl: old/new: %d/%d",
2366 slotnum, psl2ssl[slotnum]);
2367 }
2368 #endif
2369 return (psl2ssl[slotnum]);
2370 }
2371
2372 /*
2373 * P1.0 and P1.5
2374 */
2375 static int
2376 tonga_ssl_to_psl(scsb_state_t *scsb, int slotnum)
2377 {
2378 if (!(scsb->scsb_state & SCSB_IS_TONGA && scsb->scsb_state &
2379 (SCSB_P10_PROM | SCSB_P15_PROM | SCSB_P20_PROM))) {
2380 return (slotnum);
2381 }
2382 if (slotnum < 1 || slotnum > TG_MAX_SLOTS) {
2383 return (slotnum);
2384 }
2385 #ifdef DEBUG
2386 if (scsb_debug & 0x10000000) {
2387 cmn_err(CE_NOTE, "tonga_ssl_to_psl: old/new: %d/%d",
2388 slotnum, ssl2psl[slotnum]);
2389 }
2390 #endif
2391 return (ssl2psl[slotnum]);
2392 }
2393 /*
2394 * tonga_slotnum_led_shift: this function remaps slot bits ONLY for Slots 1-5
2395 * and ONLY for the register sets in bit-offset groups 1,2:
2396 * LEDs, Confg/Status, Reset, BrdHlthy
2397 *
2398 * IN bits: SCB slot numbers (led,reset,present,healthy)
2399 * to
2400 * OUT bits: HSC Slot numbers (positional slot numbers as marked on the SSB)
2401 */
2402 static uchar_t
2403 tonga_slotnum_led_shift(scsb_state_t *scsb, uchar_t data)
2404 {
2405 int i;
2406 uchar_t mask, new_data = 0;
2407 #ifdef DEBUG
2408 uchar_t old_data = data;
2409 #endif
2410 if (!(scsb->scsb_state & SCSB_IS_TONGA)) {
2411 return (data);
2412 }
2413 /*
2414 * P1.0 and P1.5 slot 1-5 offsets are the same
2415 */
2416 for (i = 1; i <= TG_MAX_SLOTS; ++i) {
2417 mask = 1 << (i - 1);
2418 switch (i) {
2419 case 1: /* map to slot 3 */
2420 new_data |= (data & mask) << 2;
2421 data &= ~(mask);
2422 break;
2423 case 2: /* map to slot 2 */
2424 new_data |= (data & mask);
2425 data &= ~(mask);
2426 break;
2427 case 3: /* map to slot 4 */
2428 case 4: /* map to slot 5 */
2429 new_data |= (data & mask) << 1;
2430 data &= ~(mask);
2431 break;
2432 case 5: /* map to slot 1 */
2433 new_data |= (data & mask) >> 4;
2434 data &= ~(mask);
2435 break;
2436 }
2437 }
2438 new_data |= data; /* set any remaining bits */
2439 #ifdef DEBUG
2440 if (scsb_debug & 0x10000000) {
2441 cmn_err(CE_NOTE, "tonga_slotnum_led_shift: old/new: 0x%x/0x%x",
2442 old_data, new_data);
2443 }
2444 #endif
2445 return (new_data);
2446 }
2447
2448 /*
2449 * P1.0 and P1.5
2450 */
2451 int
2452 scsb_led_get(scsb_state_t *scsb, scsb_uinfo_t *suip, scsb_led_t led_type)
2453 {
2454 int error;
2455 int unit_number;
2456 uchar_t reg;
2457 int index;
2458
2459 /*
2460 * Allow access to shadow registers even though SCB is removed
2461 *
2462 * if (scsb->scsb_state & SCSB_FROZEN) {
2463 * return (EAGAIN);
2464 * }
2465 */
2466 if (suip == NULL) {
2467 return (EFAULT);
2468 }
2469 if (led_type == NOUSE) {
2470 led_type = suip->led_type;
2471 }
2472 if (led_type != OK && led_type != NOK) {
2473 cmn_err(CE_NOTE, "scsb_led_get(%d): unknown led type %x",
2474 scsb->scsb_instance, led_type);
2475 return (EINVAL);
2476 }
2477 error = 0;
2478 if (scsb_debug & 0x0100) {
2479 cmn_err(CE_NOTE, "scsb_led_get: %s %s %d",
2480 led_name[led_type], unit_type_name[suip->unit_type],
2481 suip->unit_number);
2482 }
2483 /*
2484 * Map to Tonga Slot Number, if NOT P1.0 SCB
2485 * P1.0 SSB workaround
2486 */
2487 if (suip->unit_type == SLOT && !(scsb->scsb_state & SCSB_P10_PROM)) {
2488 tonga_slotnum_check(scsb, suip);
2489 }
2490 /* discover the register and index we need to operate on */
2491 if ((error = scsb_get_led_regnum(scsb, suip, ®, &unit_number,
2492 led_type)) == 0) {
2493 index = SCSB_REG_INDEX(reg);
2494 mutex_enter(&scsb->scsb_mutex);
2495 if (scsb->scsb_data_reg[index] & (1 << unit_number)) {
2496 suip->unit_state = ON;
2497 if (led_type == OK) {
2498 int code = FRU_UNIT_TO_EVCODE(suip->unit_type,
2499 suip->unit_number);
2500 reg = FRU_REG_ADDR(code, SCTRL_BLINK_OK_BASE);
2501 index = SCSB_REG_INDEX(reg);
2502 if (scsb->scsb_data_reg[index] &
2503 (1 << unit_number))
2504 suip->unit_state = BLINK;
2505 }
2506 } else {
2507 suip->unit_state = OFF;
2508 }
2509 mutex_exit(&scsb->scsb_mutex);
2510 }
2511 return (error);
2512 }
2513
2514 int
2515 scsb_led_set(scsb_state_t *scsb, scsb_uinfo_t *suip, scsb_led_t led_type)
2516 {
2517 int error;
2518 int unit_number;
2519 uchar_t reg;
2520 int code, index;
2521
2522 /* we should really allow led state changes while frozen... */
2523 if (scsb->scsb_state & SCSB_FROZEN)
2524 return (EAGAIN);
2525
2526 if (suip == NULL) {
2527 return (EFAULT);
2528 }
2529
2530 /*
2531 * Sanity check, make sure we got plausible values for set command.
2532 * Also check for application only control of slot leds using NOUSE
2533 * interface
2534 */
2535 if (led_type == NOUSE) {
2536 led_type = suip->led_type;
2537 } else if (suip->unit_type == SLOT &&
2538 scsb->scsb_state & SCSB_APP_SLOTLED_CTRL &&
2539 !(scsb->scsb_state &
2540 (SCSB_DIAGS_MODE | SCSB_DEBUG_MODE))) {
2541 /*
2542 * kernel modules using this interface need to think they are
2543 * succeeding, so we won't return an error for this
2544 * application configuration
2545 */
2546 return (0);
2547 }
2548 if (led_type != OK && led_type != NOK) {
2549 return (EINVAL);
2550 }
2551 if (suip->unit_state != OFF && suip->unit_state != ON &&
2552 suip->unit_state != BLINK) {
2553 return (EINVAL);
2554 }
2555 if (suip->unit_state == BLINK) {
2556 if (led_type != OK)
2557 return (EINVAL);
2558 if (suip->unit_type != SLOT && scsb->scsb_state &
2559 (SCSB_P06_PROM | SCSB_P10_PROM))
2560 return (EINVAL);
2561 }
2562 if (scsb_debug & 0x0100) {
2563 cmn_err(CE_NOTE,
2564 "scsb_led_set: led %s, type %s, unit %d, state %s",
2565 led_name[led_type],
2566 unit_type_name[suip->unit_type], suip->unit_number,
2567 suip->unit_state == ON ? "ON":
2568 suip->unit_state == OFF ? "OFF": "BLINK");
2569 }
2570 /*
2571 * Map to Tonga Slot Number, if NOT P1.0 SCB
2572 * P1.0 SSB workaround
2573 */
2574 if (suip->unit_type == SLOT && !(scsb->scsb_state & SCSB_P10_PROM)) {
2575 tonga_slotnum_check(scsb, suip);
2576 }
2577 /*
2578 * discover the register and index we need to access
2579 */
2580 if ((error = scsb_get_led_regnum(scsb, suip, ®, &unit_number,
2581 led_type)) == 0) {
2582 index = SCSB_REG_INDEX(reg);
2583 mutex_enter(&scsb->scsb_mutex);
2584 if (suip->unit_state == ON || suip->unit_state == BLINK)
2585 scsb->scsb_data_reg[index] |= (1 << unit_number);
2586 else
2587 scsb->scsb_data_reg[index] &= ~(1 << unit_number);
2588
2589 if (scsb_debug & 0x0100) {
2590 cmn_err(CE_NOTE, "Writing %x to Reg %x",
2591 scsb->scsb_data_reg[index], reg);
2592 }
2593 error = scsb_rdwr_register(scsb, I2C_WR, reg, 1,
2594 &scsb->scsb_data_reg[index], 1);
2595 if (error) {
2596 cmn_err(CE_WARN, "%s#%d: Could not Update %s LEDs.",
2597 ddi_driver_name(scsb->scsb_dev),
2598 ddi_get_instance(scsb->scsb_dev),
2599 led_name[led_type]);
2600 goto ledset_done;
2601 }
2602 if (led_type != OK ||
2603 (IS_SCB_P10 && suip->unit_type != SLOT) ||
2604 suip->unit_type == ALARM ||
2605 suip->unit_type == SSB ||
2606 suip->unit_type == CRTM ||
2607 suip->unit_type == PRTM) {
2608 goto ledset_done;
2609 }
2610 code = FRU_UNIT_TO_EVCODE(suip->unit_type, suip->unit_number);
2611 reg = FRU_REG_ADDR(code, SCTRL_BLINK_OK_BASE);
2612 index = SCSB_REG_INDEX(reg);
2613 if (suip->unit_state == BLINK)
2614 scsb->scsb_data_reg[index] |= (1 << unit_number);
2615 else
2616 scsb->scsb_data_reg[index] &= ~(1 << unit_number);
2617 if (scsb_debug & 0x0100) {
2618 cmn_err(CE_NOTE, "Writing %x to Reg %x",
2619 scsb->scsb_data_reg[index], reg);
2620 }
2621 error = scsb_rdwr_register(scsb, I2C_WR, reg, 1,
2622 &scsb->scsb_data_reg[index], 1);
2623 if (error) {
2624 cmn_err(CE_WARN, "%s#%d: Could not Blink %s LEDs.",
2625 ddi_driver_name(scsb->scsb_dev),
2626 ddi_get_instance(scsb->scsb_dev),
2627 led_name[led_type]);
2628 }
2629 ledset_done:
2630 mutex_exit(&scsb->scsb_mutex);
2631 }
2632 return (error);
2633 }
2634
2635 struct ps_auto_on {
2636 scsb_state_t *scsb;
2637 scsb_utype_t utype;
2638 scsb_unum_t unit;
2639 };
2640
2641 static struct ps_auto_on pao;
2642
2643 static void
2644 scsb_ps_auto_on(void *arg)
2645 {
2646 struct ps_auto_on *ppao = (struct ps_auto_on *)arg;
2647 uchar_t rmask = 0;
2648 uchar_t ondata, sysreg;
2649 int tmp, bit_index;
2650 /*
2651 * Turn on the PSU.
2652 * Notice: not checking Power Supply unit number
2653 */
2654 bit_index = SCTRL_SYS_PS_ON_BASE + (ppao->unit - 1);
2655 ondata = 1 << SYS_OFFSET(bit_index);
2656 tmp = SYS_REG_INDEX(bit_index, SCTRL_SYS_CMD_BASE);
2657 sysreg = SCSB_REG_ADDR(tmp);
2658 if (scsb_write_mask(ppao->scsb, sysreg, rmask, ondata, (uchar_t)0)) {
2659 cmn_err(CE_WARN, "scsb%d: " "I2C TRANSFER Failed",
2660 ppao->scsb->scsb_instance);
2661 }
2662 ppao->scsb->scsb_btid = 0;
2663 }
2664
2665 /*
2666 * called with mutex held from
2667 * scsb_attach() with int_fru_ptr == NULL
2668 * scsb_intr() with int_fru_ptr == info for FRU that caused interrupt
2669 */
2670 static int
2671 scsb_set_scfg_pres_leds(scsb_state_t *scsb, fru_info_t *int_fru_ptr)
2672 {
2673 int i, error = 0;
2674 int cfg_idx, led_idx, blink_idx, lid, bid;
2675 int cfg_bit, led_bit;
2676 uchar_t *puc, reg, led_reg, led_data[SCSB_LEDDATA_REGISTERS];
2677 uchar_t blink_bit, blink_reg, blink[SCSB_LEDDATA_REGISTERS];
2678 uchar_t update_reg = 0;
2679 scsb_utype_t fru_type;
2680 fru_info_t *fru_ptr;
2681
2682 if (scsb->scsb_state & SCSB_FROZEN &&
2683 !(scsb->scsb_state & SCSB_IN_INTR)) {
2684 return (EAGAIN);
2685 }
2686 for (i = 0; i < SCTRL_LED_OK_NUMREGS; ++i) {
2687 led_data[i] = 0;
2688 blink[i] = 0;
2689 }
2690 led_reg = SCSB_REG_ADDR(SCTRL_LED_OK_BASE);
2691 reg = SCSB_REG_ADDR(SCTRL_BLINK_OK_BASE);
2692 lid = SCSB_REG_INDEX(led_reg); /* the LED Index Delta */
2693 bid = SCSB_REG_INDEX(reg); /* the Blink Index Delta */
2694 blink_reg = 0;
2695 if (int_fru_ptr != NULL) {
2696 update_reg = int_fru_ptr->i2c_info->ledata_reg;
2697 }
2698 for (fru_type = 0; fru_type < SCSB_UNIT_TYPES; ++fru_type) {
2699 int is_present;
2700 fru_ptr = mct_system_info.fru_info_list[fru_type];
2701 for (; fru_ptr != NULL; fru_ptr = fru_ptr->next) {
2702 is_present = 0;
2703 if (fru_type == SLOT && (scsb->scsb_state &
2704 SCSB_APP_SLOTLED_CTRL))
2705 break;
2706 if (fru_ptr->i2c_info == NULL)
2707 continue;
2708 if ((led_reg = fru_ptr->i2c_info->ledata_reg) == 0) {
2709 /*
2710 * No LED exceptions: SSB,CRTM,PRTM
2711 */
2712 continue;
2713 }
2714 if (update_reg && update_reg != led_reg)
2715 continue;
2716 led_idx = SCSB_REG_INDEX(led_reg) - lid;
2717 led_bit = fru_ptr->i2c_info->ledata_bit;
2718 if ((reg = fru_ptr->i2c_info->syscfg_reg) == 0) {
2719 if (fru_type != SCB)
2720 continue;
2721 /*
2722 * exception: SCB
2723 */
2724 if (scsb->scsb_state & SCSB_SCB_PRESENT) {
2725 led_data[led_idx] |= 1 << led_bit;
2726 is_present = 1;
2727 } else {
2728 led_data[led_idx] &= ~(1 << led_bit);
2729 }
2730 if (IS_SCB_P10)
2731 continue;
2732 } else {
2733 cfg_idx = SCSB_REG_INDEX(reg);
2734 cfg_bit = fru_ptr->i2c_info->syscfg_bit;
2735 if (scsb->scsb_data_reg[cfg_idx] &
2736 (1 << cfg_bit)) {
2737 is_present = 1;
2738 }
2739 }
2740 if (is_present) {
2741 /*
2742 * If the FRU is a Power Supply, AND
2743 * the call is from scsb_attach() OR
2744 * from scsb_intr() and FRUs match,
2745 * turn it on.
2746 */
2747 if (fru_type == PS && (int_fru_ptr == NULL ||
2748 (int_fru_ptr == fru_ptr))) {
2749 pao.scsb = scsb;
2750 pao.utype = fru_type;
2751 pao.unit = fru_ptr->fru_unit;
2752 #ifdef PS_ON_DELAY
2753 /*
2754 * HW recommended not implementing
2755 * this delay for now.
2756 * The code is tested on PSUs:
2757 * -06
2758 * -07 rev 2
2759 * -08 plus
2760 */
2761 if (int_fru_ptr) {
2762 /*
2763 * Hot insertion, so give it
2764 * the 3 seconds it needs to
2765 * become stable
2766 */
2767 if (!scsb->scsb_btid)
2768 scsb->scsb_btid =
2769 timeout(
2770 scsb_ps_auto_on,
2771 &pao, (4 *
2772 drv_usectohz(
2773 1000000)));
2774 } else
2775 #endif /* PS_ON_DELAY */
2776 scsb_ps_auto_on((void *)&pao);
2777 }
2778 /*
2779 * Special SLOT handling.
2780 * Make sure the OK LED is on for the CPU Slot
2781 * and for the FTC (CFTM) Slot for MonteCarlo.
2782 * Both will report as FRU_PRESENT.
2783 */
2784 if (fru_type != SLOT || (fru_type == SLOT &&
2785 (fru_ptr->fru_type ==
2786 (scsb_utype_t)OC_CPU ||
2787 fru_ptr->fru_type ==
2788 (scsb_utype_t)OC_CTC))) {
2789 /*
2790 * Set OK (green) LED register bit
2791 */
2792 led_data[led_idx] |= 1 << led_bit;
2793 }
2794 if (IS_SCB_P10)
2795 continue;
2796 /*
2797 * Turn off BLINK register bit.
2798 * If single register update, then save the
2799 * corresponding blink register in blink_reg.
2800 */
2801 reg = fru_ptr->i2c_info->blink_reg;
2802 if (!reg)
2803 continue;
2804 blink_bit = fru_ptr->i2c_info->blink_bit;
2805 blink_idx = SCSB_REG_INDEX(reg) - bid;
2806 blink[blink_idx] |= 1 << blink_bit;
2807 if (update_reg && update_reg == led_reg)
2808 blink_reg = reg;
2809 }
2810 }
2811 }
2812 if (update_reg) {
2813 reg = update_reg;
2814 i = SCSB_REG_INDEX(reg);
2815 puc = &led_data[i - lid];
2816 i = 1;
2817 } else {
2818 reg = SCSB_REG_ADDR(SCTRL_LED_OK_BASE);
2819 puc = led_data;
2820 i = SCTRL_LED_OK_NUMREGS;
2821 }
2822 if (scsb_debug & 0x0100) {
2823 cmn_err(CE_NOTE, "scsb_set_scfg_pres(): writing %d bytes "
2824 "to 0x%x", i, reg);
2825 }
2826 if ((error = scsb_rdwr_register(scsb, I2C_WR, reg, i, puc, 1)) != 0) {
2827 if (scsb_debug & 0x0102)
2828 cmn_err(CE_NOTE, "scsb_set_scfg_pres(): "
2829 "I2C write to 0x%x failed", reg);
2830 error = EIO;
2831 } else {
2832 /*
2833 * Now see which BLINK bits need to be turned off for the
2834 * corresponding OK LED bits.
2835 */
2836 reg = SCSB_REG_ADDR(SCTRL_BLINK_OK_BASE);
2837 for (i = 0; i < SCTRL_BLINK_NUMREGS; ++i, ++reg) {
2838 if (blink_reg && blink_reg != reg)
2839 continue;
2840 if (!blink[i]) {
2841 continue;
2842 }
2843 if (scsb_debug & 0x0100) {
2844 cmn_err(CE_NOTE, "scsb_set_scfg_pres(): turn "
2845 "OFF Blink bits 0x%x in 0x%x",
2846 blink[i], reg);
2847 }
2848 if (scsb_write_mask(scsb, reg, 0, 0, blink[i])) {
2849 if (scsb_debug & 0x0102)
2850 cmn_err(CE_NOTE,
2851 "scsb_set_scfg_pres(): "
2852 "Write to 0x%x failed", reg);
2853 error = EIO;
2854 break;
2855 }
2856 }
2857 }
2858 return (error);
2859 }
2860
2861 static int
2862 scsb_check_config_status(scsb_state_t *scsb)
2863 {
2864 int error;
2865 uchar_t reg;
2866 int index, p06;
2867
2868 if (scsb_debug & 0x0201) {
2869 cmn_err(CE_NOTE, "scsb_check_config_status:");
2870 }
2871 /*
2872 * Base of register set
2873 */
2874 reg = SCSB_REG_ADDR(SCTRL_SYSCFG_BASE);
2875 index = SCSB_REG_INDEX(reg);
2876 /*
2877 * SCB P0.6 workaround: read registers twice, use 2nd value set
2878 */
2879 mutex_enter(&scsb->scsb_mutex);
2880 p06 = 2;
2881 do {
2882 if (error = scsb_rdwr_register(scsb, I2C_WR_RD, reg,
2883 SCTRL_CFG_NUMREGS, &scsb->scsb_data_reg[index], 1)) {
2884 break;
2885 }
2886 if (p06 == 1) {
2887 if (scsb_debug & 0x0200)
2888 cmn_err(CE_NOTE,
2889 "scsb_check_config_status: P0.6 workaround");
2890 }
2891 /*
2892 * If not P0.6 PROM, just break here
2893 */
2894 if (!(scsb->scsb_state & SCSB_P06_PROM))
2895 break;
2896 } while (--p06);
2897 mutex_exit(&scsb->scsb_mutex);
2898
2899 if (error == 0) {
2900 if (!(scsb->scsb_state & SCSB_SCB_PRESENT))
2901 scsb->scsb_state |= SCSB_SCB_PRESENT;
2902 if (scsb_fru_op(scsb, SSB, 1, SCTRL_SYSCFG_BASE,
2903 SCSB_FRU_OP_GET_BITVAL))
2904 scsb->scsb_state |= SCSB_SSB_PRESENT;
2905 else
2906 scsb->scsb_state &= ~SCSB_SSB_PRESENT;
2907 }
2908 return (error);
2909 }
2910
2911 static void
2912 scsb_set_topology(scsb_state_t *scsb)
2913 {
2914 int i, t, index, unit, is_tonga = 0;
2915 int alarm_slot_num, cpu_slot_num, ctc_slot_num;
2916 fru_info_t *fru_ptr, *last_ptr, *acslot_ptr, *ctcslot_ptr;
2917 uchar_t syscfg, led_reg, blink_reg, t_uchar;
2918 uchar_t bit_num, led_bit, blink_bit;
2919 int pad = 0;
2920
2921 /*
2922 * Get the presence status from the SysConfigStatus shadow registers
2923 * in scsb->scsb_data_reg[]
2924 */
2925 /* Mid Plane */
2926 i = SYS_REG_INDEX(SCTRL_CFG_MPID0, SCTRL_SYSCFG_BASE);
2927 t_uchar = SCSB_REG_ADDR(i);
2928 index = SCSB_REG_INDEX(t_uchar);
2929 mct_system_info.mid_plane.fru_type = MIDPLANE;
2930 mct_system_info.mid_plane.fru_version = (fru_version_t)0;
2931 t = SYS_OFFSET(SCTRL_CFG_MPID0);
2932 mct_system_info.mid_plane.fru_id = (int)((scsb->scsb_data_reg[index] &
2933 (SCTRL_MPID_MASK << t)) >> t);
2934 switch (mct_system_info.mid_plane.fru_id) {
2935 case SCTRL_MPID_HALF: /* Monte Carlo */
2936 if (scsb_debug & 0x00100005)
2937 cmn_err(CE_NOTE, "scsb_set_topology: Monte Carlo");
2938 cpu_slot_num = SC_MC_CPU_SLOT;
2939 ctc_slot_num = SC_MC_CTC_SLOT;
2940 alarm_slot_num = scsb->ac_slotnum = SC_MC_AC_SLOT;
2941 mct_system_info.max_units[SLOT] = MC_MAX_SLOTS;
2942 mct_system_info.max_units[ALARM] = MC_MAX_AC;
2943 mct_system_info.max_units[DISK] = MC_MAX_DISK;
2944 mct_system_info.max_units[FAN] = MC_MAX_FAN;
2945 mct_system_info.max_units[PS] = MC_MAX_PS;
2946 mct_system_info.max_units[PDU] = MC_MAX_PDU;
2947 mct_system_info.max_units[SCB] = MC_MAX_SCB;
2948 mct_system_info.max_units[SSB] = MC_MAX_SCB;
2949 mct_system_info.max_units[CFTM] = MC_MAX_CFTM;
2950 mct_system_info.max_units[CRTM] = MC_MAX_CRTM;
2951 mct_system_info.max_units[PRTM] = MC_MAX_PRTM;
2952 break;
2953 case SCTRL_MPID_QUARTER_NODSK: /* Tonga w/o disk */
2954 case SCTRL_MPID_QUARTER: /* Tonga w/ disk */
2955 scsb->scsb_state |= SCSB_IS_TONGA;
2956 is_tonga = 1;
2957 ctc_slot_num = -1;
2958 ctcslot_ptr = NULL;
2959 if (scsb_debug & 0x00100005)
2960 cmn_err(CE_NOTE, "scsb_set_topology: Tonga%s",
2961 mct_system_info.mid_plane.fru_id ==
2962 SCTRL_MPID_QUARTER_NODSK ?
2963 ", no disk" : " with disk");
2964 cpu_slot_num = SC_TG_CPU_SLOT;
2965 alarm_slot_num = scsb->ac_slotnum = SC_TG_AC_SLOT;
2966 mct_system_info.max_units[SLOT] = TG_MAX_SLOTS;
2967 mct_system_info.max_units[ALARM] = TG_MAX_AC;
2968 mct_system_info.max_units[DISK] = TG_MAX_DISK;
2969 mct_system_info.max_units[FAN] = TG_MAX_FAN;
2970 mct_system_info.max_units[PS] = TG_MAX_PS;
2971 mct_system_info.max_units[PDU] = TG_MAX_PDU;
2972 mct_system_info.max_units[SCB] = TG_MAX_SCB;
2973 mct_system_info.max_units[SSB] = TG_MAX_SCB;
2974 mct_system_info.max_units[CFTM] = TG_MAX_CFTM;
2975 mct_system_info.max_units[CRTM] = TG_MAX_CRTM;
2976 mct_system_info.max_units[PRTM] = TG_MAX_PRTM;
2977 break;
2978 default:
2979 cmn_err(CE_WARN, "%s#%d: Unknown MidPlane Id %x",
2980 ddi_driver_name(scsb->scsb_dev),
2981 ddi_get_instance(scsb->scsb_dev),
2982 mct_system_info.mid_plane.fru_id);
2983 if (scsb_debug & 0x00100005)
2984 cmn_err(CE_NOTE, "scsb_set_topology: 0x%x: unknown!",
2985 mct_system_info.mid_plane.fru_id);
2986 return;
2987 }
2988 /*
2989 * cPCI Slots
2990 *
2991 * NOTE: The Tonga slot fru_unit needs to get mapped to the logical
2992 * slot number in slot_table[]. The field is not in the slot_table
2993 * at least until we know the format of the OBP slot table for the FCS
2994 * release.
2995 */
2996 mct_system_info.fru_info_list[SLOT] = (fru_info_t *)
2997 kmem_zalloc(sizeof (fru_info_t) *
2998 (mct_system_info.max_units[SLOT] + pad), KM_SLEEP);
2999 fru_ptr = mct_system_info.fru_info_list[SLOT];
3000 for (unit = 1; unit <= mct_system_info.max_units[SLOT]; ++unit) {
3001 int iunit;
3002 if (unit == cpu_slot_num) {
3003 fru_ptr->fru_type = (scsb_utype_t)OC_CPU;
3004 } else if (unit == ctc_slot_num) {
3005 /* fru_ptr saved for Transition Card Presence check */
3006 ctcslot_ptr = fru_ptr;
3007 fru_ptr->fru_type = (scsb_utype_t)OC_UNKN;
3008 } else if (unit == alarm_slot_num) {
3009 /* fru_ptr saved for Alarm Card Presence check below */
3010 acslot_ptr = fru_ptr;
3011 fru_ptr->fru_type = (scsb_utype_t)OC_UNKN;
3012 } else {
3013 fru_ptr->fru_type = (scsb_utype_t)OC_UNKN;
3014 }
3015 /*
3016 * Get the slot event code (t), then use it to get the
3017 * slot bit-offsets for LED, BLINK, and SYSCFG registers.
3018 * On a P1.5 Tonga, the internal slot number must be used to
3019 * find the event code.
3020 * The P1.0 Tonga does not get mapped due to a SSB difference.
3021 */
3022 if (IS_SCB_P15) {
3023 iunit = tonga_psl_to_ssl(scsb, unit);
3024 t = FRU_UNIT_TO_EVCODE(SLOT, iunit);
3025 } else {
3026 t = FRU_UNIT_TO_EVCODE(SLOT, unit);
3027 }
3028 led_bit = FRU_OFFSET(t, SCTRL_LED_OK_BASE);
3029 blink_bit = FRU_OFFSET(t, SCTRL_BLINK_OK_BASE);
3030 blink_reg = FRU_REG_ADDR(t, SCTRL_BLINK_OK_BASE);
3031 if (is_tonga && unit <= TG_MAX_SLOTS) {
3032 bit_num = tonga_pslotnum_to_cfgbit(scsb, unit);
3033 } else {
3034 bit_num = FRU_OFFSET(t, SCTRL_SYSCFG_BASE);
3035 }
3036 /*
3037 * get the registers addresses and shadow register index for
3038 * the SYSCFG register
3039 */
3040 syscfg = FRU_REG_ADDR(t, SCTRL_SYSCFG_BASE);
3041 index = SCSB_REG_INDEX(syscfg);
3042 led_reg = FRU_REG_ADDR(t, SCTRL_LED_OK_BASE);
3043 /*
3044 * check and set presence status
3045 */
3046 if (scsb->scsb_state & SCSB_P06_PROM) {
3047 fru_ptr->fru_status = FRU_NOT_PRESENT;
3048 } else if (scsb->scsb_data_reg[index] & (1 << bit_num)) {
3049 fru_ptr->fru_status = FRU_PRESENT;
3050 } else {
3051 fru_ptr->fru_status = FRU_NOT_PRESENT;
3052 }
3053 fru_ptr->fru_unit = (scsb_unum_t)unit;
3054 fru_ptr->fru_id = fru_id_table[event_to_index(
3055 FRU_UNIT_TO_EVCODE(SLOT, unit))];
3056 fru_ptr->fru_version = (fru_version_t)0;
3057 fru_ptr->type_list = (fru_options_t *)NULL;
3058 fru_ptr->i2c_info = (fru_i2c_info_t *)
3059 kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP);
3060 fru_ptr->i2c_info->syscfg_reg = syscfg;
3061 fru_ptr->i2c_info->syscfg_bit = bit_num;
3062 fru_ptr->i2c_info->ledata_reg = led_reg;
3063 fru_ptr->i2c_info->ledata_bit = led_bit;
3064 fru_ptr->i2c_info->blink_reg = blink_reg;
3065 fru_ptr->i2c_info->blink_bit = blink_bit;
3066 last_ptr = fru_ptr;
3067 fru_ptr++;
3068 last_ptr->next = fru_ptr;
3069 }
3070 last_ptr->next = (fru_info_t *)NULL;
3071 /*
3072 * PDU
3073 */
3074 mct_system_info.fru_info_list[PDU] = (fru_info_t *)
3075 kmem_zalloc(sizeof (fru_info_t) *
3076 (mct_system_info.max_units[PDU] + pad), KM_SLEEP);
3077 fru_ptr = mct_system_info.fru_info_list[PDU];
3078 for (unit = 1; unit <= mct_system_info.max_units[PDU]; ++unit) {
3079 fru_ptr->fru_type = PDU;
3080 /* SCB15 */
3081 /*
3082 * get the FRU event code (t), then use it to get the
3083 * FRU bit-offsets for LED and SYSCFG registers
3084 */
3085 t = FRU_UNIT_TO_EVCODE(PDU, unit);
3086 led_bit = FRU_OFFSET(t, SCTRL_LED_OK_BASE);
3087 bit_num = FRU_OFFSET(t, SCTRL_SYSCFG_BASE);
3088 if (IS_SCB_P15) {
3089 blink_bit = FRU_OFFSET(t, SCTRL_BLINK_OK_BASE);
3090 i = FRU_REG_INDEX(t, SCTRL_BLINK_OK_BASE);
3091 blink_reg = SCSB_REG_ADDR(i);
3092 } else {
3093 blink_bit = 0;
3094 blink_reg = 0;
3095 }
3096 /*
3097 * get the registers addresses and shadow register index for
3098 * the SYSCFG register
3099 */
3100 i = FRU_REG_INDEX(t, SCTRL_SYSCFG_BASE);
3101 syscfg = SCSB_REG_ADDR(i);
3102 index = SCSB_REG_INDEX(syscfg);
3103 i = FRU_REG_INDEX(t, SCTRL_LED_OK_BASE);
3104 led_reg = SCSB_REG_ADDR(i);
3105 /*
3106 * check and set presence status
3107 */
3108 if (scsb->scsb_data_reg[index] & (1 << bit_num)) {
3109 fru_ptr->fru_status = FRU_PRESENT;
3110 fru_ptr->fru_version = (fru_version_t)0;
3111 } else {
3112 fru_ptr->fru_status = FRU_NOT_PRESENT;
3113 fru_ptr->fru_version = (fru_version_t)0;
3114 }
3115 fru_ptr->fru_unit = (scsb_unum_t)unit;
3116 fru_ptr->fru_id = fru_id_table[event_to_index(t)];
3117 fru_ptr->type_list = (fru_options_t *)NULL;
3118 fru_ptr->i2c_info = (fru_i2c_info_t *)
3119 kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP);
3120 fru_ptr->i2c_info->syscfg_reg = syscfg;
3121 fru_ptr->i2c_info->syscfg_bit = bit_num;
3122 fru_ptr->i2c_info->ledata_reg = led_reg;
3123 fru_ptr->i2c_info->ledata_bit = led_bit;
3124 fru_ptr->i2c_info->blink_reg = blink_reg;
3125 fru_ptr->i2c_info->blink_bit = blink_bit;
3126 last_ptr = fru_ptr;
3127 fru_ptr++;
3128 last_ptr->next = fru_ptr;
3129 }
3130 last_ptr->next = (fru_info_t *)NULL;
3131 /*
3132 * Power Supplies
3133 */
3134 mct_system_info.fru_info_list[PS] = (fru_info_t *)
3135 kmem_zalloc(sizeof (fru_info_t) *
3136 (mct_system_info.max_units[PS] + pad), KM_SLEEP);
3137 fru_ptr = mct_system_info.fru_info_list[PS];
3138 for (unit = 1; unit <= mct_system_info.max_units[PS]; ++unit) {
3139 /*
3140 * get the FRU event code (t), then use it to get the
3141 * FRU bit-offsets for LED and SYSCFG registers
3142 */
3143 t = FRU_UNIT_TO_EVCODE(PS, unit);
3144 led_bit = FRU_OFFSET(t, SCTRL_LED_OK_BASE);
3145 bit_num = FRU_OFFSET(t, SCTRL_SYSCFG_BASE);
3146 if (IS_SCB_P15) {
3147 blink_bit = FRU_OFFSET(t, SCTRL_BLINK_OK_BASE);
3148 i = FRU_REG_INDEX(t, SCTRL_BLINK_OK_BASE);
3149 blink_reg = SCSB_REG_ADDR(i);
3150 } else {
3151 blink_bit = 0;
3152 blink_reg = 0;
3153 }
3154 /*
3155 * get the registers addresses and shadow register index for
3156 * the SYSCFG register
3157 */
3158 i = FRU_REG_INDEX(t, SCTRL_SYSCFG_BASE);
3159 syscfg = SCSB_REG_ADDR(i);
3160 index = SCSB_REG_INDEX(syscfg);
3161 i = FRU_REG_INDEX(t, SCTRL_LED_OK_BASE);
3162 led_reg = SCSB_REG_ADDR(i);
3163 /*
3164 * check and set presence status
3165 */
3166 if (scsb->scsb_data_reg[index] & (1 << bit_num)) {
3167 fru_ptr->fru_status = FRU_PRESENT;
3168 } else {
3169 fru_ptr->fru_status = FRU_NOT_PRESENT;
3170 }
3171 fru_ptr->fru_type = PS;
3172 fru_ptr->fru_unit = (scsb_unum_t)unit;
3173 fru_ptr->fru_id = fru_id_table[event_to_index(t)];
3174 fru_ptr->fru_version = (fru_version_t)0;
3175 fru_ptr->type_list = (fru_options_t *)NULL;
3176 fru_ptr->i2c_info = (fru_i2c_info_t *)
3177 kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP);
3178 fru_ptr->i2c_info->syscfg_reg = syscfg;
3179 fru_ptr->i2c_info->syscfg_bit = bit_num;
3180 fru_ptr->i2c_info->ledata_reg = led_reg;
3181 fru_ptr->i2c_info->ledata_bit = led_bit;
3182 fru_ptr->i2c_info->blink_reg = blink_reg;
3183 fru_ptr->i2c_info->blink_bit = blink_bit;
3184 last_ptr = fru_ptr;
3185 fru_ptr++;
3186 last_ptr->next = fru_ptr;
3187 }
3188 last_ptr->next = (fru_info_t *)NULL;
3189 /*
3190 * SCSI Disks and removable media
3191 */
3192 mct_system_info.fru_info_list[DISK] = (fru_info_t *)
3193 kmem_zalloc(sizeof (fru_info_t) *
3194 (mct_system_info.max_units[DISK] + pad), KM_SLEEP);
3195 fru_ptr = mct_system_info.fru_info_list[DISK];
3196 for (unit = 1; unit <= mct_system_info.max_units[DISK]; ++unit) {
3197 /* SCB15 */
3198 /*
3199 * get the FRU event code (t), then use it to get the
3200 * FRU bit-offsets for LED and SYSCFG registers
3201 */
3202 t = FRU_UNIT_TO_EVCODE(DISK, unit);
3203 led_bit = FRU_OFFSET(t, SCTRL_LED_OK_BASE);
3204 bit_num = FRU_OFFSET(t, SCTRL_SYSCFG_BASE);
3205 if (IS_SCB_P15) {
3206 blink_bit = FRU_OFFSET(t, SCTRL_BLINK_OK_BASE);
3207 i = FRU_REG_INDEX(t, SCTRL_BLINK_OK_BASE);
3208 blink_reg = SCSB_REG_ADDR(i);
3209 } else {
3210 blink_bit = 0;
3211 blink_reg = 0;
3212 }
3213 /*
3214 * get the registers addresses and shadow register index for
3215 * the SYSCFG register
3216 */
3217 i = FRU_REG_INDEX(t, SCTRL_SYSCFG_BASE);
3218 syscfg = SCSB_REG_ADDR(i);
3219 index = SCSB_REG_INDEX(syscfg);
3220 i = FRU_REG_INDEX(t, SCTRL_LED_OK_BASE);
3221 led_reg = SCSB_REG_ADDR(i);
3222 /*
3223 * check and set presence status
3224 */
3225 if (scsb->scsb_data_reg[index] & (1 << bit_num)) {
3226 fru_ptr->fru_status = FRU_PRESENT;
3227 fru_ptr->fru_version = (fru_version_t)0;
3228 } else
3229 fru_ptr->fru_status = FRU_NOT_PRESENT;
3230 fru_ptr->fru_type = DISK;
3231 fru_ptr->fru_unit = (scsb_unum_t)unit;
3232 fru_ptr->fru_id = fru_id_table[event_to_index(t)];
3233 fru_ptr->type_list = (fru_options_t *)NULL;
3234 fru_ptr->i2c_info = (fru_i2c_info_t *)
3235 kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP);
3236 fru_ptr->i2c_info->syscfg_reg = syscfg;
3237 fru_ptr->i2c_info->syscfg_bit = bit_num;
3238 fru_ptr->i2c_info->ledata_reg = led_reg;
3239 fru_ptr->i2c_info->ledata_bit = led_bit;
3240 fru_ptr->i2c_info->blink_reg = blink_reg;
3241 fru_ptr->i2c_info->blink_bit = blink_bit;
3242 last_ptr = fru_ptr;
3243 fru_ptr++;
3244 last_ptr->next = fru_ptr;
3245 }
3246 last_ptr->next = (fru_info_t *)NULL;
3247 /*
3248 * Fan Trays
3249 */
3250 mct_system_info.fru_info_list[FAN] = (fru_info_t *)
3251 kmem_zalloc(sizeof (fru_info_t) *
3252 (mct_system_info.max_units[FAN] + pad), KM_SLEEP);
3253 fru_ptr = mct_system_info.fru_info_list[FAN];
3254 for (unit = 1; unit <= mct_system_info.max_units[FAN]; ++unit) {
3255 int bit_num;
3256 /* SCB15 */
3257 /*
3258 * get the FRU event code (t), then use it to get the
3259 * FRU bit-offsets for LED and SYSCFG registers
3260 */
3261 t = FRU_UNIT_TO_EVCODE(FAN, unit);
3262 led_bit = FRU_OFFSET(t, SCTRL_LED_OK_BASE);
3263 bit_num = FRU_OFFSET(t, SCTRL_SYSCFG_BASE);
3264 if (IS_SCB_P15) {
3265 blink_bit = FRU_OFFSET(t, SCTRL_BLINK_OK_BASE);
3266 i = FRU_REG_INDEX(t, SCTRL_BLINK_OK_BASE);
3267 blink_reg = SCSB_REG_ADDR(i);
3268 } else {
3269 blink_bit = 0;
3270 blink_reg = 0;
3271 }
3272 /*
3273 * get the registers addresses and shadow register index for
3274 * the SYSCFG register
3275 */
3276 i = FRU_REG_INDEX(t, SCTRL_SYSCFG_BASE);
3277 syscfg = SCSB_REG_ADDR(i);
3278 index = SCSB_REG_INDEX(syscfg);
3279 i = FRU_REG_INDEX(t, SCTRL_LED_OK_BASE);
3280 led_reg = SCSB_REG_ADDR(i);
3281 /*
3282 * check and set presence status
3283 */
3284 if (scsb->scsb_data_reg[index] & (1 << bit_num)) {
3285 fru_ptr->fru_status = FRU_PRESENT;
3286 } else {
3287 fru_ptr->fru_status = FRU_NOT_PRESENT;
3288 }
3289 fru_ptr->fru_type = FAN;
3290 fru_ptr->fru_unit = (scsb_unum_t)unit;
3291 fru_ptr->fru_id = fru_id_table[event_to_index(t)];
3292 fru_ptr->fru_version = (fru_version_t)0;
3293 fru_ptr->type_list = (fru_options_t *)NULL;
3294 fru_ptr->i2c_info = (fru_i2c_info_t *)
3295 kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP);
3296 fru_ptr->i2c_info->syscfg_reg = syscfg;
3297 fru_ptr->i2c_info->syscfg_bit = bit_num;
3298 fru_ptr->i2c_info->ledata_reg = led_reg;
3299 fru_ptr->i2c_info->ledata_bit = led_bit;
3300 fru_ptr->i2c_info->blink_reg = blink_reg;
3301 fru_ptr->i2c_info->blink_bit = blink_bit;
3302 last_ptr = fru_ptr;
3303 fru_ptr++;
3304 last_ptr->next = fru_ptr;
3305 }
3306 last_ptr->next = (fru_info_t *)NULL;
3307 /*
3308 * Alarm Cards
3309 */
3310 mct_system_info.fru_info_list[ALARM] = (fru_info_t *)
3311 kmem_zalloc(sizeof (fru_info_t) *
3312 (mct_system_info.max_units[ALARM] + pad), KM_SLEEP);
3313 fru_ptr = mct_system_info.fru_info_list[ALARM];
3314 for (unit = 1; unit <= mct_system_info.max_units[ALARM]; ++unit) {
3315 int bit_num;
3316
3317 /*
3318 * get the FRU event code (t), then use it to get the
3319 * FRU bit-offsets for SYSCFG register
3320 */
3321 t = FRU_UNIT_TO_EVCODE(ALARM, unit);
3322 bit_num = FRU_OFFSET(t, SCTRL_SYSCFG_BASE);
3323 /*
3324 * get the registers addresses and shadow register index for
3325 * the SYSCFG register
3326 */
3327 i = FRU_REG_INDEX(t, SCTRL_SYSCFG_BASE);
3328 syscfg = SCSB_REG_ADDR(i);
3329 index = SCSB_REG_INDEX(syscfg);
3330 /*
3331 * check and set presence status
3332 */
3333 if (scsb->scsb_data_reg[index] & (1 << bit_num)) {
3334 fru_ptr->fru_status = FRU_PRESENT;
3335 if (acslot_ptr != NULL && acslot_ptr->fru_status ==
3336 FRU_PRESENT) {
3337 acslot_ptr->fru_type = (scsb_utype_t)OC_AC;
3338 /*
3339 * acslot_ptr->fru_id =
3340 * fru_id_table[event_to_index(t)];
3341 */
3342 }
3343 } else {
3344 fru_ptr->fru_status = FRU_NOT_PRESENT;
3345 }
3346
3347 fru_ptr->fru_type = ALARM;
3348 fru_ptr->fru_unit = (scsb_unum_t)unit;
3349 fru_ptr->fru_id = fru_id_table[event_to_index(t)];
3350 fru_ptr->fru_version = (fru_version_t)0;
3351 fru_ptr->type_list = (fru_options_t *)NULL;
3352 fru_ptr->i2c_info = (fru_i2c_info_t *)
3353 kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP);
3354 fru_ptr->i2c_info->syscfg_reg = syscfg;
3355 fru_ptr->i2c_info->syscfg_bit = bit_num;
3356 fru_ptr->i2c_info->ledata_reg = 0;
3357 fru_ptr->i2c_info->ledata_bit = 0;
3358 fru_ptr->i2c_info->blink_reg = 0;
3359 fru_ptr->i2c_info->blink_bit = 0;
3360 last_ptr = fru_ptr;
3361 fru_ptr++;
3362 last_ptr->next = fru_ptr;
3363 }
3364 last_ptr->next = (fru_info_t *)NULL;
3365 /*
3366 * SCB
3367 */
3368 mct_system_info.fru_info_list[SCB] = (fru_info_t *)
3369 kmem_zalloc(sizeof (fru_info_t) *
3370 (mct_system_info.max_units[SCB] + pad), KM_SLEEP);
3371 fru_ptr = mct_system_info.fru_info_list[SCB];
3372 unit = 1;
3373 /* SCB15 */
3374 /*
3375 * get the FRU event code (t), then use it to get the
3376 * FRU bit-offset for LED register
3377 */
3378 t = FRU_UNIT_TO_EVCODE(SCB, unit);
3379 led_bit = FRU_OFFSET(t, SCTRL_LED_OK_BASE);
3380 i = FRU_REG_INDEX(t, SCTRL_LED_OK_BASE);
3381 led_reg = SCSB_REG_ADDR(i);
3382 if (IS_SCB_P15) {
3383 blink_bit = FRU_OFFSET(t, SCTRL_BLINK_OK_BASE);
3384 i = FRU_REG_INDEX(t, SCTRL_BLINK_OK_BASE);
3385 blink_reg = SCSB_REG_ADDR(i);
3386 } else {
3387 blink_bit = 0;
3388 blink_reg = 0;
3389 }
3390 i = SYS_REG_INDEX(SCTRL_SCBID0, SCTRL_SCBID_BASE);
3391 index = SCSB_REG_ADDR(i);
3392 /*
3393 * check and set presence status
3394 */
3395 if (scsb->scsb_state & SCSB_SCB_PRESENT) {
3396 fru_ptr->fru_status = FRU_PRESENT;
3397 } else {
3398 fru_ptr->fru_status = FRU_NOT_PRESENT;
3399 }
3400 fru_ptr->fru_type = SCB;
3401 fru_ptr->fru_unit = (scsb_unum_t)unit;
3402 fru_ptr->fru_id = fru_id_table[event_to_index(t)];
3403 /* get PROM_VERSION from shadow registers */
3404 if (scsb_rdwr_register(scsb, I2C_WR_RD, index, 1, &t_uchar, 1))
3405 fru_ptr->fru_version = (fru_version_t)0;
3406 else
3407 fru_ptr->fru_version = (fru_version_t)t_uchar;
3408 fru_ptr->type_list = (fru_options_t *)NULL;
3409 fru_ptr->i2c_info = (fru_i2c_info_t *)
3410 kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP);
3411 fru_ptr->i2c_info->syscfg_reg = 0;
3412 fru_ptr->i2c_info->syscfg_bit = 0;
3413 fru_ptr->i2c_info->ledata_reg = led_reg;
3414 fru_ptr->i2c_info->ledata_bit = led_bit;
3415 fru_ptr->i2c_info->blink_reg = blink_reg;
3416 fru_ptr->i2c_info->blink_bit = blink_bit;
3417 fru_ptr->next = (fru_info_t *)NULL;
3418 /*
3419 * SSB
3420 */
3421 mct_system_info.fru_info_list[SSB] = (fru_info_t *)
3422 kmem_zalloc(sizeof (fru_info_t) *
3423 (mct_system_info.max_units[SSB] + pad), KM_SLEEP);
3424 fru_ptr = mct_system_info.fru_info_list[SSB];
3425 unit = 1;
3426 /* SCB15 */
3427 /*
3428 * get the FRU event code (t), then use it to get the
3429 * FRU bit-offset for SYSCFG register
3430 */
3431 t = FRU_UNIT_TO_EVCODE(SSB, unit);
3432 bit_num = FRU_OFFSET(t, SCTRL_SYSCFG_BASE);
3433 /*
3434 * get the registers addresses and shadow register index for
3435 * the SYSCFG register
3436 */
3437 i = FRU_REG_INDEX(t, SCTRL_SYSCFG_BASE);
3438 syscfg = SCSB_REG_ADDR(i);
3439 index = SCSB_REG_INDEX(syscfg);
3440 /*
3441 * check and set presence status
3442 */
3443 if (scsb->scsb_data_reg[index] & (1 << bit_num)) {
3444 fru_ptr->fru_status = FRU_PRESENT;
3445 } else {
3446 fru_ptr->fru_status = FRU_NOT_PRESENT;
3447 }
3448 fru_ptr->fru_type = SSB;
3449 fru_ptr->fru_unit = (scsb_unum_t)unit;
3450 fru_ptr->fru_id = fru_id_table[event_to_index(t)];
3451 fru_ptr->fru_version = (fru_version_t)0;
3452 fru_ptr->type_list = (fru_options_t *)NULL;
3453 fru_ptr->i2c_info = (fru_i2c_info_t *)
3454 kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP);
3455 fru_ptr->i2c_info->syscfg_reg = syscfg;
3456 fru_ptr->i2c_info->syscfg_bit = bit_num;
3457 fru_ptr->i2c_info->ledata_reg = 0;
3458 fru_ptr->i2c_info->ledata_bit = 0;
3459 fru_ptr->i2c_info->blink_reg = 0;
3460 fru_ptr->i2c_info->blink_bit = 0;
3461 fru_ptr->next = (fru_info_t *)NULL;
3462 /*
3463 * CFTM
3464 */
3465 mct_system_info.fru_info_list[CFTM] = (fru_info_t *)
3466 kmem_zalloc(sizeof (fru_info_t) *
3467 (mct_system_info.max_units[CFTM] + pad), KM_SLEEP);
3468 fru_ptr = mct_system_info.fru_info_list[CFTM];
3469 unit = 1;
3470 /* SCB15 */
3471 /*
3472 * get the FRU event code (t), then use it to get the
3473 * FRU bit-offsets for LED and SYSCFG registers
3474 */
3475 t = FRU_UNIT_TO_EVCODE(CFTM, unit);
3476 led_bit = FRU_OFFSET(t, SCTRL_LED_OK_BASE);
3477 bit_num = FRU_OFFSET(t, SCTRL_SYSCFG_BASE);
3478 if (IS_SCB_P15) {
3479 blink_bit = FRU_OFFSET(t, SCTRL_BLINK_OK_BASE);
3480 i = FRU_REG_INDEX(t, SCTRL_BLINK_OK_BASE);
3481 blink_reg = SCSB_REG_ADDR(i);
3482 } else {
3483 blink_bit = 0;
3484 blink_reg = 0;
3485 }
3486 /*
3487 * get the registers addresses and shadow register index for
3488 * the SYSCFG register
3489 */
3490 i = FRU_REG_INDEX(t, SCTRL_SYSCFG_BASE);
3491 syscfg = SCSB_REG_ADDR(i);
3492 index = SCSB_REG_INDEX(syscfg);
3493 i = FRU_REG_INDEX(t, SCTRL_LED_OK_BASE);
3494 led_reg = SCSB_REG_ADDR(i);
3495 /*
3496 * check and set presence status
3497 */
3498 if (scsb->scsb_data_reg[index] & (1 << bit_num)) {
3499 fru_ptr->fru_status = FRU_PRESENT;
3500 if (ctcslot_ptr != NULL && ctcslot_ptr->fru_status ==
3501 FRU_PRESENT) {
3502 ctcslot_ptr->fru_type = (scsb_utype_t)OC_CTC;
3503 scsb->scsb_hsc_state |= SCSB_HSC_CTC_PRES;
3504 }
3505 } else {
3506 fru_ptr->fru_status = FRU_NOT_PRESENT;
3507 }
3508 fru_ptr->fru_type = CFTM;
3509 fru_ptr->fru_unit = (scsb_unum_t)1;
3510 fru_ptr->fru_id = fru_id_table[event_to_index(t)];
3511 fru_ptr->fru_version = (fru_version_t)0;
3512 fru_ptr->type_list = (fru_options_t *)NULL;
3513 fru_ptr->i2c_info = (fru_i2c_info_t *)
3514 kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP);
3515 fru_ptr->i2c_info->syscfg_reg = syscfg;
3516 fru_ptr->i2c_info->syscfg_bit = bit_num;
3517 fru_ptr->i2c_info->ledata_reg = led_reg;
3518 fru_ptr->i2c_info->ledata_bit = led_bit;
3519 fru_ptr->i2c_info->blink_reg = blink_reg;
3520 fru_ptr->i2c_info->blink_bit = blink_bit;
3521 fru_ptr->next = (fru_info_t *)NULL;
3522 /*
3523 * CRTM
3524 */
3525 mct_system_info.fru_info_list[CRTM] = (fru_info_t *)
3526 kmem_zalloc(sizeof (fru_info_t) *
3527 (mct_system_info.max_units[CRTM] + pad),
3528 KM_SLEEP);
3529 fru_ptr = mct_system_info.fru_info_list[CRTM];
3530 unit = 1;
3531 /* SCB15 */
3532 /*
3533 * get the FRU event code (t), then use it to get the
3534 * FRU bit-offsets for LED and SYSCFG registers
3535 */
3536 t = FRU_UNIT_TO_EVCODE(CRTM, unit);
3537 bit_num = FRU_OFFSET(t, SCTRL_SYSCFG_BASE);
3538 /*
3539 * get the registers addresses and shadow register index for
3540 * the SYSCFG register
3541 */
3542 i = FRU_REG_INDEX(t, SCTRL_SYSCFG_BASE);
3543 syscfg = SCSB_REG_ADDR(i);
3544 index = SCSB_REG_INDEX(syscfg);
3545 /*
3546 * check and set presence status
3547 */
3548 if (scsb->scsb_data_reg[index] & (1 << bit_num)) {
3549 fru_ptr->fru_status = FRU_PRESENT;
3550 } else {
3551 fru_ptr->fru_status = FRU_NOT_PRESENT;
3552 }
3553 fru_ptr->fru_type = CRTM;
3554 fru_ptr->fru_unit = (scsb_unum_t)unit;
3555 fru_ptr->fru_id = fru_id_table[event_to_index(t)];
3556 fru_ptr->fru_version = (fru_version_t)0;
3557 fru_ptr->type_list = (fru_options_t *)NULL;
3558 fru_ptr->i2c_info = (fru_i2c_info_t *)
3559 kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP);
3560 fru_ptr->i2c_info->syscfg_reg = syscfg;
3561 fru_ptr->i2c_info->syscfg_bit = bit_num;
3562 fru_ptr->i2c_info->ledata_reg = 0;
3563 fru_ptr->i2c_info->ledata_bit = 0;
3564 fru_ptr->i2c_info->blink_reg = 0;
3565 fru_ptr->i2c_info->blink_bit = 0;
3566 fru_ptr->next = (fru_info_t *)NULL;
3567 /*
3568 * PRTM
3569 */
3570 mct_system_info.fru_info_list[PRTM] = (fru_info_t *)
3571 kmem_zalloc(sizeof (fru_info_t) *
3572 (mct_system_info.max_units[PRTM] + pad), KM_SLEEP);
3573 fru_ptr = mct_system_info.fru_info_list[PRTM];
3574 unit = 1;
3575 /*
3576 * SCB15
3577 * get the FRU event code (t), then use it to get the
3578 * FRU bit-offsets for LED and SYSCFG registers
3579 */
3580 t = FRU_UNIT_TO_EVCODE(PRTM, unit);
3581 bit_num = FRU_OFFSET(t, SCTRL_SYSCFG_BASE);
3582 /*
3583 * get the registers addresses and shadow register index for
3584 * the SYSCFG register
3585 */
3586 i = FRU_REG_INDEX(t, SCTRL_SYSCFG_BASE);
3587 syscfg = SCSB_REG_ADDR(i);
3588 index = SCSB_REG_INDEX(syscfg);
3589 /*
3590 * check and set presence status
3591 */
3592 if (scsb->scsb_data_reg[index] & (1 << bit_num)) {
3593 fru_ptr->fru_status = FRU_PRESENT;
3594 } else {
3595 fru_ptr->fru_status = FRU_NOT_PRESENT;
3596 }
3597 fru_ptr->fru_type = PRTM;
3598 fru_ptr->fru_unit = (scsb_unum_t)unit;
3599 fru_ptr->fru_id = fru_id_table[event_to_index(t)];
3600 fru_ptr->fru_version = (fru_version_t)0;
3601 fru_ptr->type_list = (fru_options_t *)NULL;
3602 fru_ptr->i2c_info = (fru_i2c_info_t *)
3603 kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP);
3604 fru_ptr->i2c_info->syscfg_reg = syscfg;
3605 fru_ptr->i2c_info->syscfg_bit = bit_num;
3606 fru_ptr->i2c_info->ledata_reg = 0;
3607 fru_ptr->i2c_info->ledata_bit = 0;
3608 fru_ptr->i2c_info->blink_reg = 0;
3609 fru_ptr->i2c_info->blink_bit = 0;
3610 fru_ptr->next = (fru_info_t *)NULL;
3611
3612 scsb->scsb_state |= SCSB_TOPOLOGY;
3613 #ifdef DEBUG
3614 mct_topology_dump(scsb, 0);
3615 #endif
3616 }
3617
3618 /*ARGSUSED*/
3619 static void
3620 scsb_free_topology(scsb_state_t *scsb)
3621 {
3622 int i;
3623 fru_info_t *fru_ptr;
3624
3625 if (scsb_debug & 0x00100005)
3626 cmn_err(CE_NOTE, "scsb_free_topology:");
3627 for (i = 0; i < SCSB_UNIT_TYPES; ++i) {
3628 fru_ptr = mct_system_info.fru_info_list[i];
3629 while (fru_ptr != NULL) {
3630 if (fru_ptr->i2c_info != (fru_i2c_info_t *)NULL)
3631 kmem_free(fru_ptr->i2c_info,
3632 sizeof (fru_i2c_info_t));
3633 fru_ptr = fru_ptr->next;
3634 }
3635 if ((fru_ptr = mct_system_info.fru_info_list[i]) !=
3636 (fru_info_t *)NULL) {
3637 kmem_free(fru_ptr, sizeof (fru_info_t) *
3638 mct_system_info.max_units[i]);
3639 mct_system_info.fru_info_list[i] = (fru_info_t *)NULL;
3640 }
3641 }
3642 }
3643
3644 #ifdef DEBUG
3645 static void
3646 mct_topology_dump(scsb_state_t *scsb, int force)
3647 {
3648 int i;
3649 fru_info_t *fru_ptr;
3650
3651 if (!force && !(scsb_debug & 0x00200000))
3652 return;
3653 if (force && !(scsb->scsb_state & (SCSB_DIAGS_MODE | SCSB_DEBUG_MODE)))
3654 return;
3655 if (!(scsb->scsb_state & SCSB_TOPOLOGY)) {
3656 cmn_err(CE_NOTE, "mct_topology_dump: Topology not set!");
3657 return;
3658 }
3659 for (i = 0; i < SCSB_UNIT_TYPES; ++i) {
3660 fru_ptr = mct_system_info.fru_info_list[i];
3661 switch ((scsb_utype_t)i) {
3662 case SLOT:
3663 cmn_err(CE_NOTE, "MCT: Number of Slots: %d",
3664 mct_system_info.max_units[SLOT]);
3665 break;
3666 case ALARM:
3667 cmn_err(CE_NOTE, "MCT: MAX Number of Alarm Cards: %d",
3668 mct_system_info.max_units[ALARM]);
3669 break;
3670 case DISK:
3671 cmn_err(CE_NOTE, "MCT: MAX Number of SCSI Devices: %d",
3672 mct_system_info.max_units[DISK]);
3673 break;
3674 case FAN:
3675 cmn_err(CE_NOTE, "MCT: MAX Number of Fan Trays: %d",
3676 mct_system_info.max_units[FAN]);
3677 break;
3678 case PDU:
3679 cmn_err(CE_NOTE, "MCT: MAX Number of PDUs: %d",
3680 mct_system_info.max_units[PDU]);
3681 break;
3682 case PS:
3683 cmn_err(CE_NOTE,
3684 "MCT: MAX Number of Power Supplies: %d",
3685 mct_system_info.max_units[PS]);
3686 break;
3687 case SCB:
3688 cmn_err(CE_NOTE, "MCT: MAX Number of SCBs: %d",
3689 mct_system_info.max_units[SCB]);
3690 break;
3691 case SSB:
3692 cmn_err(CE_NOTE, "MCT: MAX Number of SSBs: %d",
3693 mct_system_info.max_units[SSB]);
3694 break;
3695 }
3696 while (fru_ptr != NULL) {
3697 if (fru_ptr->fru_status & FRU_PRESENT) {
3698 cmn_err(CE_NOTE,
3699 "MCT: type=%d, unit=%d, id=0x%x, "
3700 "version=0x%x",
3701 fru_ptr->fru_type,
3702 fru_ptr->fru_unit,
3703 fru_ptr->fru_id,
3704 fru_ptr->fru_version);
3705 }
3706 fru_ptr = fru_ptr->next;
3707 }
3708 }
3709 }
3710
3711 /*
3712 * Sends an event when the system controller board I2C errors
3713 * exceed the threshold.
3714 */
3715 static void
3716 scsb_failing_event(scsb_state_t *scsb)
3717 {
3718 uint32_t scsb_event_code = SCTRL_EVENT_SCB;
3719
3720 add_event_code(scsb, scsb_event_code);
3721 (void) scsb_queue_ops(scsb, QPUT_INT32, 1, &scsb_event_code,
3722 "scsb_intr");
3723 }
3724 #endif
3725
3726 int
3727 scsb_read_bhealthy(scsb_state_t *scsb)
3728 {
3729 int error;
3730 uchar_t reg;
3731 int index;
3732
3733 if (scsb_debug & 0x8001) {
3734 cmn_err(CE_NOTE, "scsb_read_bhealthy()");
3735 }
3736 reg = SCSB_REG_ADDR(SCTRL_BHLTHY_BASE);
3737 index = SCSB_REG_INDEX(reg);
3738 error = scsb_rdwr_register(scsb, I2C_WR_RD, reg,
3739 SCTRL_BHLTHY_NUMREGS, &scsb->scsb_data_reg[index], 1);
3740 return (error);
3741 }
3742
3743 /*
3744 * Returns the health status of a slot
3745 */
3746 int
3747 scsb_read_slot_health(scsb_state_t *scsb, int pslotnum)
3748 {
3749 int slotnum = tonga_psl_to_ssl(scsb, pslotnum);
3750 return (scsb_fru_op(scsb, SLOT, slotnum,
3751 SCTRL_BHLTHY_BASE, SCSB_FRU_OP_GET_BITVAL));
3752 }
3753
3754 /*
3755 * DIAGNOSTIC and DEBUG only.
3756 * Called from ioctl command (SCSBIOC_BHEALTHY_GET)
3757 */
3758 int
3759 scsb_bhealthy_slot(scsb_state_t *scsb, scsb_uinfo_t *suip)
3760 {
3761 int error = 0;
3762 int base, code, unit_number;
3763 uchar_t reg;
3764 int index;
3765
3766 if (scsb->scsb_state & SCSB_FROZEN)
3767 return (EAGAIN);
3768
3769 /* operation valid for slots only */
3770 if (suip == NULL || suip->unit_type != SLOT) {
3771 return (EINVAL);
3772 }
3773
3774 if (scsb_debug & 0x8001)
3775 cmn_err(CE_NOTE, "scsb_bhealthy_slot: slot %d",
3776 suip->unit_number);
3777 if (suip->unit_number > mct_system_info.max_units[SLOT]) {
3778 return (EINVAL);
3779 }
3780 /*
3781 * Map 1.0 Tonga Slot Number, if necessary
3782 */
3783 tonga_slotnum_check(scsb, suip);
3784 base = SCTRL_BHLTHY_BASE;
3785 code = FRU_UNIT_TO_EVCODE(suip->unit_type, suip->unit_number);
3786 unit_number = FRU_OFFSET(code, base);
3787 index = FRU_REG_INDEX(code, base);
3788 reg = SCSB_REG_ADDR(index);
3789 index = SCSB_REG_INDEX(reg); /* shadow index */
3790
3791 if (scsb->scsb_state & SCSB_P10_PROM) {
3792 error = scsb_read_bhealthy(scsb);
3793 }
3794 /* else shadow regs are updated by interrupt handler */
3795 if (error == 0) {
3796 if (scsb->scsb_data_reg[index] & (1 << unit_number))
3797 suip->unit_state = ON;
3798 else
3799 suip->unit_state = OFF;
3800 }
3801 return (error);
3802 }
3803
3804 /*
3805 * Called from HSC and ioctl command (SCSBIOC_RESET_UNIT)
3806 * to reset one specified slot
3807 */
3808 int
3809 scsb_reset_unit(scsb_state_t *scsb, scsb_uinfo_t *suip)
3810 {
3811 int error;
3812 int unit_number;
3813 uchar_t reg;
3814 int index, slotnum, reset_state;
3815
3816 if (scsb->scsb_state & SCSB_FROZEN)
3817 return (EAGAIN);
3818 if (scsb_debug & 0x8001) {
3819 cmn_err(CE_NOTE, "scsb_reset_slot(%d): slot %d, state %d\n",
3820 scsb->scsb_instance, suip->unit_number,
3821 suip->unit_state);
3822 }
3823 if (suip->unit_type != ALARM && !(scsb->scsb_state &
3824 (SCSB_DIAGS_MODE | SCSB_DEBUG_MODE))) {
3825 return (EINVAL);
3826 }
3827 if (suip->unit_state != ON && suip->unit_state != OFF) {
3828 return (EINVAL);
3829 }
3830 error = 0;
3831 switch (suip->unit_type) {
3832 case ALARM:
3833 {
3834 int i, code;
3835 if (suip->unit_number != 1)
3836 return (EINVAL);
3837 code = FRU_UNIT_TO_EVCODE(suip->unit_type, suip->unit_number);
3838 unit_number = FRU_OFFSET(code, SCTRL_RESET_BASE);
3839 i = ALARM_RESET_REG_INDEX(code, SCTRL_RESET_BASE);
3840 reg = SCSB_REG_ADDR(i);
3841 break;
3842 }
3843 case SLOT:
3844 slotnum = suip->unit_number;
3845 reset_state = (suip->unit_state == ON) ? SCSB_RESET_SLOT :
3846 SCSB_UNRESET_SLOT;
3847 if (scsb->scsb_state & SCSB_IS_TONGA) {
3848 if (slotnum > TG_MAX_SLOTS ||
3849 slotnum == SC_TG_CPU_SLOT) {
3850 return (EINVAL);
3851 }
3852 } else {
3853 if (slotnum > MC_MAX_SLOTS ||
3854 slotnum == SC_MC_CPU_SLOT ||
3855 (scsb->scsb_hsc_state & SCSB_HSC_CTC_PRES &&
3856 slotnum == SC_MC_CTC_SLOT)) {
3857 return (EINVAL);
3858 }
3859 }
3860 return (scsb_reset_slot(scsb, slotnum, reset_state));
3861 default:
3862 return (EINVAL);
3863 }
3864 index = SCSB_REG_INDEX(reg);
3865 mutex_enter(&scsb->scsb_mutex);
3866 if (suip->unit_state == ON)
3867 scsb->scsb_data_reg[index] |= (1 << unit_number);
3868 else /* OFF */
3869 scsb->scsb_data_reg[index] &= ~(1 << unit_number);
3870 if ((error = scsb_rdwr_register(scsb, I2C_WR, reg, 1,
3871 &scsb->scsb_data_reg[index], 0)) != 0) {
3872 if (scsb_debug & 0x8002)
3873 cmn_err(CE_WARN,
3874 "scsb_leds: write failure to 0x%x", reg);
3875 return (error);
3876 }
3877 mutex_exit(&scsb->scsb_mutex);
3878 return (error);
3879 }
3880
3881 /*
3882 * Diagnostic and DEBUG
3883 * This is a helper function for the helper ioctl to pretend that
3884 * scsb h/w is doing its job!!!
3885 */
3886 int
3887 scsb_slot_occupancy(scsb_state_t *scsb, scsb_uinfo_t *suip)
3888 {
3889 int error;
3890 int saved_unit_number;
3891
3892 if (!(scsb->scsb_state & (SCSB_DEBUG_MODE | SCSB_DIAGS_MODE)))
3893 return (EACCES);
3894 if (scsb->scsb_state & SCSB_FROZEN) {
3895 return (EAGAIN);
3896 }
3897 error = 0;
3898 switch (suip->unit_type) {
3899 case ALARM:
3900 if (suip->unit_number !=
3901 (mct_system_info.fru_info_list[ALARM])->fru_unit) {
3902 return (EINVAL);
3903 }
3904 break;
3905
3906 case SLOT:
3907 /*
3908 * All slots are acceptable, except slots 11 & 12.
3909 */
3910 if (suip->unit_number < 1 || suip->unit_number >
3911 mct_system_info.max_units[ALARM]) {
3912 error = EINVAL;
3913 break;
3914 }
3915 /* Map 1.0 Tonga Slot Numbers if necessary */
3916 saved_unit_number = suip->unit_number;
3917 tonga_slotnum_check(scsb, suip);
3918 break;
3919
3920 default:
3921 error = EINVAL;
3922 break;
3923 }
3924
3925 if (error)
3926 return (error);
3927 if (suip->unit_state == ON) {
3928 if (hsc_slot_occupancy(saved_unit_number, B_TRUE, 0, B_TRUE)
3929 != 0)
3930 error = EFAULT;
3931 } else {
3932 if (hsc_slot_occupancy(saved_unit_number, B_FALSE, 0, B_FALSE)
3933 != 0)
3934 error = EFAULT;
3935 }
3936
3937 return (error);
3938 }
3939
3940 static int
3941 scsb_clear_intptrs(scsb_state_t *scsb)
3942 {
3943 int i, error;
3944 uchar_t wbuf[SCTRL_MAX_GROUP_NUMREGS];
3945 error = 0;
3946 for (i = 1; i <= SCTRL_INTR_NUMREGS; ++i) {
3947 wbuf[i] = 0xff;
3948 }
3949 if (error = scsb_rdwr_register(scsb, I2C_WR,
3950 SCSB_REG_ADDR(SCTRL_INTSRC_BASE),
3951 SCTRL_INTR_NUMREGS, wbuf, 1)) {
3952 if (scsb_debug & 0x0402)
3953 cmn_err(CE_NOTE, "scsb_clear_intptrs(): "
3954 "write to 0x%x failed",
3955 SCSB_REG_ADDR(SCTRL_INTSRC_BASE));
3956 }
3957 return (error);
3958 }
3959
3960 static int
3961 scsb_setall_intmasks(scsb_state_t *scsb)
3962 {
3963 int error;
3964 uchar_t reg, wdata, rmask;
3965 int i;
3966
3967 /*
3968 * write loop for Interrupt Mask registers
3969 */
3970 if (scsb_debug & 0x0401)
3971 cmn_err(CE_NOTE, "setall_intmasks()");
3972 error = 0;
3973 rmask = 0;
3974 wdata = 0xff;
3975 reg = SCSB_REG_ADDR(SCTRL_INTMASK_BASE);
3976 for (i = 0; i < SCTRL_MASK_NUMREGS; ++i, ++reg) {
3977 if (error = scsb_write_mask(scsb, reg, rmask, wdata, 0)) {
3978 if (scsb_debug & 0x0402)
3979 cmn_err(CE_NOTE, "scsb_setall_intmasks: "
3980 "write to 0x%x failed: %d", reg, error);
3981 error = EIO;
3982 break;
3983 }
3984 }
3985 return (error);
3986 }
3987
3988
3989 /*
3990 * Clear Interrupt masks based on the FRUs that could be installed
3991 * for this particular topology, determined by the MidPlane ID
3992 * from SCTRL_SYSCFG registers
3993 * case SCTRL_MPID_HALF:
3994 * 1 CPU, 1 AlarmCard, 1 SCB/SSB, 2 PS, 3 FAN, 3 SCSI, 8 Slots
3995 * case SCTRL_MPID_QUARTER:
3996 * 1 CPU, 1 AlarmCard, 1 SCB/SSB, 1 PS, 2 FAN, 1 SCSI, 4 Slots
3997 * case SCTRL_MPID_QUARTER_NODSK:
3998 * 1 CPU, 1 AlarmCard, 1 SCB/SSB, 1 PS, 2 FAN, 0 SCSI, 4 Slots
3999 */
4000 static int
4001 scsb_clear_intmasks(scsb_state_t *scsb)
4002 {
4003 int error;
4004 uchar_t msk_reg, reg, wdata, rmask;
4005 uchar_t mask_data[SCTRL_MAX_GROUP_NUMREGS];
4006 int tmp, idx, code, unit, offset, mbid;
4007 scsb_utype_t fru_type;
4008 fru_info_t *fru_ptr;
4009
4010 if (scsb->scsb_state & SCSB_FROZEN &&
4011 !(scsb->scsb_state & SCSB_IN_INTR)) {
4012 return (EAGAIN);
4013 }
4014 error = 0;
4015 for (tmp = 0; tmp < SCTRL_MASK_NUMREGS; ++tmp)
4016 mask_data[tmp] = 0;
4017 msk_reg = SCSB_REG_ADDR(SCTRL_INTMASK_BASE);
4018 mbid = SCSB_REG_INDEX(msk_reg); /* the Mask Base Index Delta */
4019 if (scsb_debug & 0x0400) {
4020 cmn_err(CE_NOTE, "clear_intmasks: msk_reg=0x%x; mbid=%d",
4021 msk_reg, mbid);
4022 }
4023 for (fru_type = 0; fru_type < SCSB_UNIT_TYPES; ++fru_type) {
4024 if (fru_type == SCB)
4025 continue; /* handle below, 2 reg offsets */
4026 fru_ptr = mct_system_info.fru_info_list[fru_type];
4027 for (; fru_ptr != NULL; fru_ptr = fru_ptr->next) {
4028 unit = fru_ptr->fru_unit;
4029 code = FRU_UNIT_TO_EVCODE(fru_type, unit);
4030 offset = FRU_OFFSET(code, SCTRL_INTMSK_BASE);
4031 reg = FRU_REG_ADDR(code, SCTRL_INTMSK_BASE);
4032 idx = SCSB_REG_INDEX(reg);
4033 tmp = idx - mbid;
4034 mask_data[tmp] |= (1 << offset);
4035 if (scsb_debug & 0x0400)
4036 cmn_err(CE_NOTE,
4037 "clear_intmasks:%d:%d: PRES mask[%d]:0x%x",
4038 fru_type, unit, tmp, mask_data[tmp]);
4039 if ((fru_type == SLOT) && (IS_SCB_P15)) {
4040 /*
4041 * Unmask the corresponding Slot HLTHY mask
4042 * Use Slot bit and register offsets,
4043 * but with SCTRL_INTMASK_HLTHY_BASE
4044 */
4045 reg = FRU_REG_ADDR(code,
4046 SCTRL_INTMASK_HLTHY_BASE);
4047 idx = SCSB_REG_INDEX(reg);
4048 tmp = idx - mbid;
4049 mask_data[tmp] |= (1 << offset);
4050 if (scsb_debug & 0x0400) {
4051 cmn_err(CE_NOTE,
4052 "clear_intmasks:Slot:%d: HLTHY mask[%d]:0x%x"
4053 "; reg=0x%x, idx=%d, mbid=%d",
4054 unit, tmp, mask_data[tmp],
4055 reg, idx, mbid);
4056 }
4057 }
4058 }
4059 }
4060 /*
4061 * Now unmask these non-fru interrupt events
4062 * SCTRL_EVENT_PWRDWN (almost normal)
4063 * SCTRL_EVENT_REPLACE (not used)
4064 * SCTRL_EVENT_ALARM_INT (not working in P0.6/P1.0)
4065 * SCTRL_EVENT_SCB (SCB 1.5 ONLY; plus SCB_INT_OFFSET)
4066 */
4067 code = SCTRL_EVENT_PWRDWN;
4068 offset = FRU_OFFSET(code, SCTRL_INTMSK_BASE);
4069 reg = FRU_REG_ADDR(code, SCTRL_INTMSK_BASE);
4070 idx = SCSB_REG_INDEX(reg);
4071 tmp = idx - mbid;
4072 mask_data[tmp] |= (1 << offset);
4073 if (IS_SCB_P15) {
4074 code = SCTRL_EVENT_SCB;
4075 offset = FRU_OFFSET(code, SCTRL_INTMSK_BASE);
4076 reg = FRU_REG_ADDR(code, SCTRL_INTMSK_BASE) + SCB_INT_OFFSET;
4077 idx = SCSB_REG_INDEX(reg);
4078 tmp = idx - mbid;
4079 mask_data[tmp] |= (1 << offset);
4080 code = SCTRL_EVENT_ALARM_INT;
4081 offset = FRU_OFFSET(code, SCTRL_INTMSK_BASE);
4082 reg = FRU_REG_ADDR(code, SCTRL_INTMSK_BASE);
4083 idx = SCSB_REG_INDEX(reg);
4084 tmp = idx - mbid;
4085 mask_data[tmp] |= (1 << offset);
4086 }
4087 for (tmp = 0; tmp < SCTRL_MASK_NUMREGS; ++tmp) {
4088 rmask = 0;
4089 wdata = mask_data[tmp];
4090 if (scsb_debug & 0x0400)
4091 cmn_err(CE_NOTE, "clear_intmasks:0x%x: ~(0x%x),0x%x",
4092 msk_reg, (~wdata) & 0xff, wdata);
4093 mutex_enter(&scsb->scsb_mutex);
4094 if (error = scsb_write_mask(scsb, msk_reg, rmask,
4095 (~wdata) & 0xff, wdata)) {
4096 mutex_exit(&scsb->scsb_mutex);
4097 if (scsb_debug & 0x0402)
4098 cmn_err(CE_NOTE, "scsb_clear_intmasks: "
4099 "write to 0x%x failed: %d",
4100 msk_reg, error);
4101 error = EIO;
4102 break;
4103 }
4104 mutex_exit(&scsb->scsb_mutex);
4105 ++msk_reg;
4106 }
4107 return (error);
4108 }
4109
4110 static int
4111 scsb_get_status(scsb_state_t *scsb, scsb_status_t *smp)
4112 {
4113 register int i;
4114
4115 if (smp == NULL) {
4116 return (EFAULT);
4117 }
4118 if (scsb_debug & 0x40000000 &&
4119 (scsb->scsb_state & SCSB_DEBUG_MODE ||
4120 scsb->scsb_state & SCSB_DIAGS_MODE)) {
4121 if (scsb->scsb_state & SCSB_FROZEN) {
4122 return (EAGAIN);
4123 }
4124 mutex_enter(&scsb->scsb_mutex);
4125 if (scsb_debug & 0x80000000) {
4126 if ((i = scsb_readall_regs(scsb)) != 0 &&
4127 scsb->scsb_state & SCSB_DEBUG_MODE)
4128 cmn_err(CE_WARN, "scsb_get_status: "
4129 "scsb_readall_regs() FAILED");
4130 } else {
4131 if ((i = scsb_check_config_status(scsb)) == 0) {
4132 i = scsb_set_scfg_pres_leds(scsb, NULL);
4133 }
4134 }
4135 mutex_exit(&scsb->scsb_mutex);
4136 if (i) {
4137 cmn_err(CE_WARN,
4138 "scsb_get_status: FAILED Presence LEDs update");
4139 return (EIO);
4140 }
4141 }
4142 for (i = 0; i < SCSB_DATA_REGISTERS; ++i)
4143 smp->scsb_reg[i] = scsb->scsb_data_reg[i];
4144 return (0);
4145 }
4146
4147 /*
4148 * scsb_freeze_check:
4149 * Turn all the leds off on the system monitor card, without changing
4150 * the state of what we have for scsb. This routine is called only when
4151 * replacing system monitor card, so the state of the card leds could be
4152 * restored, using scsb_restore().
4153 * Also, set state to SCSB_FROZEN which denies access to scsb while in
4154 * freeze mode.
4155 */
4156 static char *BAD_BOARD_MSG =
4157 "SCSB: Should NOT remove SCB(%d) while cPCI Slot %d is "
4158 "in RESET with a possible bad board.";
4159 static int slots_in_reset[SCTRL_MAX_GROUP_NUMREGS];
4160
4161 static void
4162 scsb_freeze_check(scsb_state_t *scsb)
4163 {
4164 register int i;
4165 int offset;
4166 int unit, slotnum;
4167 int index;
4168 fru_info_t *fru_ptr;
4169 uint32_t code;
4170 uchar_t reg;
4171
4172 if (scsb_debug & 0x20001)
4173 cmn_err(CE_NOTE, "scsb_freeze_check(%d):", scsb->scsb_instance);
4174
4175 if (scsb->scsb_state & SCSB_FROZEN) {
4176 return;
4177 }
4178 mutex_enter(&scsb->scsb_mutex);
4179 for (i = 0; i < SCTRL_MAX_GROUP_NUMREGS; ++i)
4180 slots_in_reset[i] = 0;
4181 /*
4182 * We allow the SCB to be removed only if none of
4183 * the cPCI resets are asserted for occupied slots.
4184 * There shouldn't be a bad board plugged in the system
4185 * while swapping the SCB.
4186 */
4187 fru_ptr = mct_system_info.fru_info_list[SLOT];
4188 for (unit = 1; unit <= mct_system_info.max_units[SLOT]; ++unit) {
4189 if (IS_SCB_P15) {
4190 slotnum = tonga_psl_to_ssl(scsb, unit);
4191 } else {
4192 slotnum = unit;
4193 }
4194 code = FRU_UNIT_TO_EVCODE(SLOT, slotnum);
4195 offset = FRU_OFFSET(code, SCTRL_RESET_BASE);
4196 reg = FRU_REG_ADDR(code, SCTRL_RESET_BASE);
4197 index = SCSB_REG_INDEX(reg);
4198 if (scsb->scsb_data_reg[index] & (1 << offset)) {
4199 if (fru_ptr[unit - 1].fru_status == FRU_PRESENT) {
4200 slots_in_reset[unit - 1] = unit;
4201 cmn_err(CE_NOTE, BAD_BOARD_MSG,
4202 scsb->scsb_instance, unit);
4203 }
4204 }
4205 }
4206 mutex_exit(&scsb->scsb_mutex);
4207 }
4208
4209 static void
4210 scsb_freeze(scsb_state_t *scsb)
4211 {
4212 uint32_t code;
4213 if (scsb_debug & 0x00020002) {
4214 cmn_err(CE_WARN, "scsb_freeze: SCB%d possibly removed",
4215 scsb->scsb_instance);
4216 }
4217 if (scsb->scsb_state & SCSB_FROZEN)
4218 return;
4219 scsb->scsb_state |= SCSB_FROZEN;
4220 scsb->scsb_state &= ~SCSB_SCB_PRESENT;
4221 (void) scsb_hsc_freeze(scsb->scsb_dev);
4222 /*
4223 * Send the EVENT_SCB since there is evidence that the
4224 * System Controller Board has been removed.
4225 */
4226 code = SCTRL_EVENT_SCB;
4227 if (!(scsb->scsb_state & SCSB_IN_INTR))
4228 scsb_event_code = code;
4229 check_fru_info(scsb, code);
4230 add_event_code(scsb, code);
4231 (void) scsb_queue_ops(scsb, QPUT_INT32, 1, &code, "scsb_freeze");
4232 }
4233
4234 /*
4235 * scsb_restore will only be called from the interrupt handler context on
4236 * INIT_SCB interrupt for newly inserted SCB.
4237 * Called with mutex held.
4238 */
4239 static void
4240 scsb_restore(scsb_state_t *scsb)
4241 {
4242 if (scsb_debug & 0x20001)
4243 cmn_err(CE_NOTE, "scsb_restore(%d):", scsb->scsb_instance);
4244
4245 if (initialize_scb(scsb) != DDI_SUCCESS) {
4246 if (scsb_debug & 0x00020002) {
4247 cmn_err(CE_WARN, "scsb_restore: INIT Failed");
4248 return;
4249 }
4250 }
4251 /* 9. Clear all Interrupts */
4252 if (scsb_clear_intmasks(scsb)) {
4253 cmn_err(CE_WARN,
4254 "scsb%d: I2C TRANSFER Failed", scsb->scsb_instance);
4255 if (scsb_debug & 0x00020002) {
4256 cmn_err(CE_WARN, "scsb_restore: clear_intmasks Failed");
4257 }
4258 return;
4259 }
4260
4261 /* 10. */
4262 /* Check if Alarm Card present at boot and set flags */
4263 if (scsb_fru_op(scsb, ALARM, 1, SCTRL_SYSCFG_BASE,
4264 SCSB_FRU_OP_GET_BITVAL))
4265 scsb->scsb_hsc_state |= SCSB_ALARM_CARD_PRES;
4266 else
4267 scsb->scsb_hsc_state &= ~SCSB_ALARM_CARD_PRES;
4268
4269 scsb->scsb_state &= ~SCSB_FROZEN;
4270 (void) scsb_hsc_restore(scsb->scsb_dev);
4271 }
4272
4273 /*
4274 * Given an Event Code,
4275 * Return:
4276 * FRU type in LSByte
4277 * unit number in MSByte
4278 */
4279 uint16_t
4280 event_to_type(uint32_t evcode)
4281 {
4282 int i, li, unit;
4283 uint32_t ec;
4284 uint16_t ret;
4285 for (i = li = 0; i < SCSB_UNIT_TYPES; ++i) {
4286 if (evcode == type_to_code1[i]) {
4287 ret = (uint16_t)(0x0100 | i);
4288 return (ret);
4289 }
4290 if (evcode < type_to_code1[i]) {
4291 unit = 1;
4292 ec = type_to_code1[li];
4293 while (ec < evcode)
4294 ec = ec << 1, ++unit;
4295 ret = (unit << 8) | li;
4296 return (ret);
4297 }
4298 li = i;
4299 }
4300 return ((uint16_t)0xffff);
4301 }
4302
4303 /*
4304 * scsb interrupt handler for (MC) PSM_INT vector
4305 * P0.6: HW shipped to beta customers
4306 * 1. did not have Slot Occupant Presense support
4307 * 2. I2C interrupt-map properties not yet tested, using polling daemon
4308 * 3. Polling detects each event reliably twice.
4309 * clr_bits# are used to keep track of events to be ignored 2nd time
4310 *
4311 * retval flags allow all events to be checked, and still returning the
4312 * correct DDI value.
4313 *
4314 */
4315 #define SCSB_INTR_CLAIMED 1
4316 #define SCSB_INTR_UNCLAIMED 2
4317 #define SCSB_INTR_EVENT 4
4318
4319 /*
4320 * Does preprocessing of the interrupt. The only thing this
4321 * needs to do is to ask scsb to release the interrupt line.
4322 * and then schedule delayed actual processing using timeout()
4323 */
4324 uint_t
4325 scsb_intr_preprocess(caddr_t arg)
4326 {
4327 scsb_state_t *scsb = (scsb_state_t *)arg;
4328
4329 scb_pre_s = gethrtime();
4330
4331 /*
4332 * If SCSB_IN_INTR is already set in scsb_state,
4333 * it means we are being interrupted by someone else. This can
4334 * happen only if the interrupt does not belong to scsb, and some
4335 * other device, e.g. a FAN or PS is interrupting. So, we
4336 * cancel the previous timeout().
4337 */
4338
4339 if (scsb->scsb_state & SCSB_IN_INTR) {
4340 (void) untimeout(scsb_intr_tid);
4341 (void) scsb_invoke_intr_chain();
4342 (void) scsb_toggle_psmint(scsb, 1);
4343 scsb->scsb_state &= ~SCSB_IN_INTR;
4344 goto intr_end;
4345 }
4346 scsb->scsb_state |= SCSB_IN_INTR;
4347
4348 /*
4349 * Stop scsb from interrupting first.
4350 */
4351 if (scsb_quiesce_psmint(scsb) != DDI_SUCCESS) {
4352 goto intr_end;
4353 }
4354
4355 /*
4356 * Schedule a timeout to actually process the
4357 * interrupt.
4358 */
4359 scsb_intr_tid = timeout((void (*)(void *))scsb_intr, arg,
4360 drv_usectohz(1000));
4361
4362 intr_end:
4363
4364 scb_pre_e = gethrtime();
4365 return (DDI_INTR_CLAIMED);
4366 }
4367
4368 static void scsb_healthy_intr(scsb_state_t *scsb, int pslotnum);
4369 void
4370 scsb_intr(caddr_t arg)
4371 {
4372 scsb_state_t *scsb = (scsb_state_t *)arg;
4373 int i, idx, offset, unit, numregs, error;
4374 int intr_idx, index, offset_base, retval, slotnum, val;
4375 uint32_t code;
4376 uchar_t intr_reg, tmp_reg, intr_addr, clr_bits = 0;
4377 uchar_t ac_slot = B_FALSE;
4378 uchar_t *int_masks;
4379 uchar_t cstatus_regs[SCTRL_MAX_GROUP_NUMREGS];
4380 scsb_utype_t fru_type;
4381 fru_info_t *fru_ptr;
4382 int ac_present;
4383
4384 /*
4385 * Avoid mayhem, make sure we have only one timeout thread running.
4386 */
4387 mutex_enter(&scsb->scsb_mutex);
4388 while (scsb_in_postintr)
4389 cv_wait(&scsb->scsb_cv, &scsb->scsb_mutex);
4390 scsb_in_postintr = 1;
4391 mutex_exit(&scsb->scsb_mutex);
4392
4393 scb_post_s = gethrtime();
4394 if (scsb_debug & 0x00002000)
4395 cmn_err(CE_NOTE, "scsb_intr(%d)", scsb->scsb_instance);
4396 retval = 0;
4397 tmp_reg = 0;
4398 /*
4399 * XXX: Problem, when we want to support swapping between SCB
4400 * versions, then we need to check the SCB PROM ID (CF) register here
4401 * before assuming the same SCB version was re-inserted.
4402 * We will have to duplicate some of the scb_initialization()
4403 * code to set the scsb_state PROM ID bits and to set up the
4404 * register table pointers.
4405 *
4406 * Only if NOT SSB_PRESENT, check the SCB PROM ID
4407 */
4408 if (!(scsb->scsb_state & SCSB_SSB_PRESENT)) {
4409 if (scb_check_version(scsb) != DDI_SUCCESS) {
4410 #ifdef DEBUG
4411 if (scsb->scsb_state & SCSB_SSB_PRESENT &&
4412 scsb->scsb_i2c_errcnt > scsb_err_threshold)
4413 scsb_failing_event(scsb);
4414 #endif
4415 goto intr_error;
4416 }
4417 }
4418 if (IS_SCB_P15) {
4419 int_masks = scb_15_int_masks;
4420 } else {
4421 int_masks = scb_10_int_masks;
4422 }
4423 /*
4424 * Now check the INTSRC registers for set bits.
4425 * Do a quick check by OR'ing INTSRC registers together as we copy
4426 * them from the transfer buffer. For P1.0 or earlier we had already
4427 * read the interrupt source registers and wrote them back to stop
4428 * interrupt. So we need to do this step only for P1.5 or later.
4429 * We already read INTSRC6 to take care of SCB insertion case, so
4430 * do not read INTSRC6 again.
4431 */
4432
4433 if (IS_SCB_P15) {
4434 intr_addr = SCSB_REG_ADDR(SCTRL_INTSRC_BASE);
4435 /* read the interrupt register from scsb */
4436 if (scsb_rdwr_register(scsb, I2C_WR_RD, intr_addr,
4437 SCTRL_INTR_NUMREGS - 1, scb_intr_regs, 1)) {
4438 cmn_err(CE_WARN, "scsb_intr: "
4439 " Failed read of interrupt registers.");
4440 #ifdef DEBUG
4441 if (scsb->scsb_state & SCSB_SSB_PRESENT &&
4442 scsb->scsb_i2c_errcnt > scsb_err_threshold)
4443 scsb_failing_event(scsb);
4444 #endif
4445 goto intr_error;
4446 }
4447 }
4448
4449 /*
4450 * We have seen that an interrupt source bit can be set
4451 * even though the corresponding interrupt mask bit
4452 * has been set to mask the interrupt. So we must
4453 * clear all bits set in the interrupt source register.
4454 */
4455 for (i = 0; i < SCTRL_INTR_NUMREGS; ++i) {
4456 retval |= scb_intr_regs[i]; /* Quick INTSRC check */
4457 #ifdef DEBUG
4458 if (scsb_debug & 0x08000000) {
4459 if (tmp_reg || scb_intr_regs[i]) {
4460 cmn_err(CE_NOTE, "scsb_intr: INTSRC%d=0x%x",
4461 i + 1, scb_intr_regs[i]);
4462 ++tmp_reg;
4463 }
4464 }
4465 #endif
4466 }
4467 /*
4468 * Any bits from quick check? If this is not our interrupt,
4469 * something is wrong. FAN/PS interrupts are supposed to be
4470 * blocked, but we can not be sure. So, go ahead and call the
4471 * emergency interrupt handlers for FAN/PS devices and mask
4472 * their interrupts, if they aren't already masked.
4473 */
4474 if (retval == 0) {
4475 goto intr_error;
4476 }
4477
4478 retval = 0;
4479
4480 /*
4481 * If SCB 1.5 or 2.0, check for the INIT_SCB Interrupt
4482 * to support Hot SCB Insertion.
4483 * The check was moved here during debugging of the SCB hot insertion.
4484 * Theoretically, this code could be moved back to the check for
4485 * SCTRL_EVENT_SCB in the processing loop below.
4486 */
4487 if (IS_SCB_P15) {
4488 int iid;
4489 iid = SCSB_REG_INDEX(intr_addr);
4490 offset = FRU_OFFSET(SCTRL_EVENT_SCB, SCTRL_INTPTR_BASE);
4491 tmp_reg = SCSB_REG_ADDR(SCTRL_INTSRC_SCB_P15);
4492 intr_idx = SCSB_REG_INDEX(tmp_reg) - iid;
4493 clr_bits = 1 << offset;
4494 if (scb_intr_regs[intr_idx] & clr_bits) {
4495 /*
4496 * Must be newly inserted SCB
4497 * Time to re-initialize.
4498 */
4499 if (scsb_debug & 0x00023000) {
4500 cmn_err(CE_NOTE,
4501 "scsb_intr(%d): INIT_SCB INT",
4502 scsb->scsb_instance);
4503 }
4504 scsb_restore(scsb);
4505 retval |= (SCSB_INTR_CLAIMED | SCSB_INTR_EVENT);
4506 /*
4507 * The INTSRC bit will be cleared by the
4508 * scsb_restore() function.
4509 * Also, leave the bit set in scb_intr_regs[] so we can
4510 * report the event code as we check for other
4511 * interrupt source bits.
4512 *
4513 * scsb_write_mask(scsb, tmp_reg, 0, clr_bits, 0);
4514 * scb_intr_regs[intr_idx] &= ~clr_bits;
4515 */
4516 }
4517 /*
4518 * In case this is a power down interrupt, check the validity
4519 * of the request to make sure it's not an I2C noise
4520 */
4521 offset = FRU_OFFSET(SCTRL_EVENT_PWRDWN,
4522 SCTRL_INTPTR_BASE);
4523 clr_bits = 1 << offset;
4524 intr_reg = scb_intr_regs[intr_idx];
4525 if (intr_reg & clr_bits) {
4526 /*
4527 * A shutdown request has been detected. Poll
4528 * the corresponding register ? more times to
4529 * make sure it's a genuine shutdown request.
4530 */
4531 for (i = 0; i < scsb_shutdown_count; i++) {
4532 drv_usecwait(1000);
4533 if (scsb_rdwr_register(scsb, I2C_WR_RD, tmp_reg,
4534 1, &intr_reg, 1)) {
4535 cmn_err(CE_WARN, "Failed to read "
4536 " interrupt register");
4537 goto intr_error;
4538 }
4539 if (scsb_debug & 0x08000000) {
4540 cmn_err(CE_NOTE, "scsb_intr: "
4541 " INTSRC6[%d]=0x%x", i,
4542 intr_reg);
4543 }
4544 if (!(intr_reg & clr_bits)) {
4545 scb_intr_regs[intr_idx] &= ~clr_bits;
4546 break;
4547 }
4548 }
4549 }
4550 }
4551 /*
4552 * if retval == 0, then we didn't call scsb_restore,
4553 * so we update the shadow copy of SYSCFG registers
4554 * We *MUST* read the syscfg registers before any attempt
4555 * to clear the interrupt source registers is made.
4556 */
4557 if (retval == 0 && scsb_check_config_status(scsb)) {
4558 cmn_err(CE_WARN,
4559 "scsb_intr: Failed read of config/status registers");
4560 if (scsb->scsb_state & SCSB_P06_NOINT_KLUGE) {
4561 if (!scsb_debug) {
4562 goto intr_error;
4563 }
4564 }
4565 #ifdef DEBUG
4566 if (scsb->scsb_state & SCSB_SSB_PRESENT &&
4567 scsb->scsb_i2c_errcnt > scsb_err_threshold) {
4568 scsb_failing_event(scsb);
4569 }
4570 #endif
4571 /*
4572 * Allow to go on so we clear the INTSRC bits
4573 */
4574 }
4575
4576 /*
4577 * Read the board healthy registers here, if any of the healthy
4578 * interrupts are set.
4579 */
4580 if (IS_SCB_P15) {
4581 intr_idx = intr_reg = 0;
4582 intr_addr = SCSB_REG_ADDR(SCTRL_INTSRC_BASE);
4583 index = SCSB_REG_INDEX(intr_addr);
4584 for (i = 0; i < SCTRL_BHLTHY_NUMREGS; ++i, ++intr_idx) {
4585 scsb->scsb_data_reg[index++] =
4586 scb_intr_regs[intr_idx] & int_masks[intr_idx];
4587 intr_reg |= scb_intr_regs[i];
4588 }
4589
4590 if (intr_reg && scsb_read_bhealthy(scsb) != 0) {
4591 cmn_err(CE_WARN, "%s#%d: Error Reading Healthy# "
4592 " Registers", ddi_driver_name(scsb->scsb_dev),
4593 ddi_get_instance(scsb->scsb_dev));
4594 #ifdef DEBUG
4595 if (scsb->scsb_state & SCSB_SSB_PRESENT &&
4596 scsb->scsb_i2c_errcnt > scsb_err_threshold) {
4597 scsb_failing_event(scsb);
4598 }
4599 #endif
4600 goto intr_error;
4601 }
4602 }
4603
4604 /*
4605 * We clear the interrupt source registers now itself so that
4606 * future interrupts can be latched quickly, instead of after
4607 * finishing processing of all interrupt conditions. The global
4608 * interrupt mask however remain disabled.
4609 */
4610 if (IS_SCB_P15) {
4611 if (scsb_rdwr_register(scsb, I2C_WR, intr_addr,
4612 SCTRL_INTR_NUMREGS, scb_intr_regs, 1)) {
4613 cmn_err(CE_WARN, "scsb_intr: Failed write to interrupt"
4614 " registers.");
4615 #ifdef DEBUG
4616 if (scsb->scsb_state & SCSB_SSB_PRESENT &&
4617 scsb->scsb_i2c_errcnt > scsb_err_threshold) {
4618 scsb_failing_event(scsb);
4619 }
4620 #endif
4621 goto intr_error;
4622 }
4623 }
4624
4625 /*
4626 * At this point, all interrupt source registers are read.
4627 * We only handle interrups which are not masked
4628 */
4629 for (i = 0; i < SCTRL_INTR_NUMREGS; ++i) {
4630 scb_intr_regs[i] &= int_masks[i];
4631 }
4632
4633 /*
4634 * We are here means that there was some bit set in the interrupt
4635 * source register. So we must claim the interrupt no matter
4636 * whatever error we may encounter in the course of processing.
4637 */
4638 retval |= SCSB_INTR_CLAIMED;
4639
4640 /* store config status data */
4641 tmp_reg = SCSB_REG_ADDR(SCTRL_SYSCFG_BASE);
4642 index = SCSB_REG_INDEX(tmp_reg);
4643 for (i = 0; i < SCTRL_CFG_NUMREGS; ++i)
4644 cstatus_regs[i] = scsb->scsb_data_reg[index + i];
4645 /*
4646 * Clear the event code,
4647 * then check to see what kind(s) of events we were interrupted for.
4648 * Check all SCTRL_INTSRC registers
4649 */
4650 scsb_event_code = 0;
4651 clr_bits = 0;
4652 intr_idx = 0;
4653 numregs = SCTRL_INTR_NUMREGS;
4654 index = SCSB_REG_INDEX(intr_addr);
4655 /*
4656 * If SCB 1.5, adjust some variables to skip the SCTRL_BHLTHY_REGS
4657 * which will be handled last in this function.
4658 */
4659 if (IS_SCB_P15) {
4660 i = SCTRL_BHLTHY_NUMREGS;
4661 intr_idx += i;
4662 intr_addr += i;
4663 index += i;
4664 }
4665 /*
4666 * For the rest of the INTSRC registers, we walk through the
4667 * scb_fru_offset[] table, matching register offsets with our offset
4668 * counter. Then we check for the scb_fru_offset[] bit in intr_reg.
4669 * The scb_fru_offset[] index is now the SCTRL_EVENT code.
4670 * The code is then compared to type_to_code1[] entries to find the
4671 * fru_type. The fru_type will help us recognize when to do
4672 * SLOT Hot Swap processing.
4673 *
4674 * offset_base: the appropriate scb_fru_offset[] base index
4675 * for the INTPTR_BASE register group
4676 * offset: bit offset found in INTSRC register
4677 * intr_idx: index to temporary INTSRC register copies
4678 * intr: modified copy of current INTR register
4679 * intr_addr: SCB register address of current INTR register
4680 * index: index to current INTR shadow register
4681 * idx: bit-number of current INTR event bit
4682 * uc: uchar_t from scb_fru_offset[] table,
4683 * containing register and FRU offsets.
4684 * j: used to walk fru_offset[] table, which is also
4685 * the bit-number of the current event code
4686 * code: manufactured event code for current INT event
4687 */
4688 offset_base = FRU_OFFSET_BASE(SCTRL_INTPTR_BASE);
4689 for (offset = 0; intr_idx < numregs;
4690 ++offset, ++intr_idx, ++intr_addr, ++index) {
4691 scsb->scsb_data_reg[index] = scb_intr_regs[intr_idx];
4692 intr_reg = scb_intr_regs[intr_idx];
4693 while (intr_reg) { /* for each INTSRC bit that's set */
4694 int j;
4695 uint16_t ui;
4696 uchar_t uc;
4697 idx = event_to_index((uint32_t)intr_reg); /* offset */
4698 code = (1 << idx); /* back to bit mask */
4699 clr_bits |= code;
4700 intr_reg = intr_reg & ~code; /* clear this one */
4701 for (j = 0; j < MCT_MAX_FRUS; ++j) {
4702 /*
4703 * Get register offset from table and check
4704 * for a match with our loop offset counter.
4705 * Then check for intr_reg bit-offset match
4706 * with bit-offset from table entry.
4707 */
4708 uc = scb_fru_offset[offset_base + j];
4709 if (offset != ((uc >> 4) & 0xf)) {
4710 if (IS_SCB_P10)
4711 continue;
4712 if (j != FRU_INDEX(SCTRL_EVENT_SCB))
4713 continue;
4714 if (offset != ((uc >> 4) & 0xf)
4715 + SCB_INT_OFFSET)
4716 continue;
4717 }
4718 if (idx == (uc & 0xf))
4719 break;
4720 }
4721 if (uc == 0xff) {
4722 /*
4723 * bit idx not recognized, check another.
4724 */
4725 continue;
4726 }
4727 /*
4728 * We found the fru_offset[] entry, now use the index
4729 * to get the event code.
4730 */
4731 code = (uint32_t)(1 << j);
4732 if (scsb_debug & 0x00002000) {
4733 cmn_err(CE_NOTE, "scsb_intr: code=0x%x", code);
4734 }
4735 /*
4736 * Now check for the NON-FRU type events.
4737 */
4738 if (code == SCTRL_EVENT_PWRDWN) {
4739 if (scsb_debug & 0x1002) {
4740 cmn_err(CE_NOTE,
4741 "scsb_intr(%d): power down req."
4742 " INT.", scsb->scsb_instance);
4743 }
4744 scsb_event_code |= code;
4745 if (scsb->scsb_state & SCSB_OPEN &&
4746 scsb->scsb_rq != (queue_t *)NULL) {
4747 /*
4748 * inform applications using poll(2)
4749 * about this event, and provide the
4750 * event code to EnvMon scsb policy
4751 */
4752 if (!(scsb_debug & 0x00040000))
4753 (void) scsb_queue_put(scsb->scsb_rq, 1,
4754 &scsb_event_code, "scsb_intr");
4755 goto intr_error;
4756 }
4757 continue;
4758 } else if (code == SCTRL_EVENT_REPLACE) {
4759 if (scsb_debug & 0x1002) {
4760 cmn_err(CE_NOTE,
4761 "scsb_intr(%d): replacement "
4762 "req. INT.",
4763 scsb->scsb_instance);
4764 }
4765 scsb_freeze_check(scsb);
4766 scsb_freeze(scsb);
4767 scsb_event_code |= code;
4768 retval |= (SCSB_INTR_CLAIMED | SCSB_INTR_EVENT);
4769 continue;
4770 } else if (code == SCTRL_EVENT_SCB) {
4771 int tmp;
4772 /*
4773 * Must be newly inserted SCB
4774 * Time to re-initialize.
4775 */
4776 if (scsb_debug & 0x1002) {
4777 cmn_err(CE_NOTE,
4778 "scsb_intr(%d): INIT SCB INTR",
4779 scsb->scsb_instance);
4780 }
4781 /*
4782 * SCB initialization already handled, but we
4783 * set the event code bit here in order to
4784 * report the event to interested utilities.
4785 *
4786 * scsb_restore(scsb);
4787 * The INTSRC bit is already cleared,
4788 * so we won't do it again.
4789 */
4790 tmp = FRU_OFFSET(SCTRL_EVENT_SCB,
4791 SCTRL_INTPTR_BASE);
4792 clr_bits &= ~(1 << tmp);
4793 scsb_event_code |= code;
4794 retval |= (SCSB_INTR_CLAIMED | SCSB_INTR_EVENT);
4795 continue;
4796 } else if (code == SCTRL_EVENT_ALARM_INT) {
4797 /*
4798 * P0.6/P1.0: SCTRL_INTR_ALARM_INT is always
4799 * set and cannot be cleared, so ignore it.
4800 */
4801 if (!IS_SCB_P15) {
4802 continue;
4803 }
4804 if (scsb_debug & 0x1002) {
4805 cmn_err(CE_NOTE,
4806 "scsb_intr(%d): Alarm INT.",
4807 scsb->scsb_instance);
4808 }
4809 scsb_event_code |= code;
4810 retval |= (SCSB_INTR_CLAIMED | SCSB_INTR_EVENT);
4811 /*
4812 * XXX:
4813 * Must service the Alarm INT by clearing INT
4814 * condition on Alarm Card,
4815 * then clear the SCTRL_INTR_ALARM_INT bit here.
4816 * Waiting for specs and test environment.
4817 */
4818 continue;
4819 } else if ((ui = event_to_type(code)) == 0xffff) {
4820 /*
4821 * FRU type not found
4822 */
4823 break;
4824 }
4825 /*
4826 * Check for special processing
4827 * now that we found the FRU type.
4828 */
4829 fru_type = (scsb_utype_t)(ui & 0xff);
4830 unit = (ui >> 8) & 0xff;
4831 if (scsb_debug & 0x00002000) {
4832 cmn_err(CE_NOTE, "scsb_intr: "
4833 "FRU type/unit/code %d/%d/0x%x",
4834 fru_type, unit, code);
4835 }
4836 switch (fru_type) {
4837 case PDU:
4838 break;
4839 case PS:
4840 break;
4841 case DISK:
4842 break;
4843 case FAN:
4844 break;
4845 case SSB:
4846 /*
4847 * in check_fru_info() below, we see if the
4848 * SSB has been removed, then check for
4849 * occupied slots in reset to see if we should
4850 * WARN agains SCB removal
4851 */
4852 break;
4853 case CFTM:
4854 break;
4855 case CRTM:
4856 break;
4857 case PRTM:
4858 break;
4859 case SLOT:
4860 slotnum = tonga_ssl_to_psl(scsb, unit);
4861 if (scsb_debug & 0x00002000) {
4862 cmn_err(CE_NOTE, "scsb_intr: "
4863 "unit/slot %d/%d",
4864 unit, slotnum);
4865 }
4866
4867 /*
4868 * If the slot number is not valid, continue.
4869 */
4870 if (scsb->scsb_state & SCSB_IS_TONGA) {
4871 if (slotnum > TG_MAX_SLOTS ||
4872 slotnum == SC_TG_CPU_SLOT) {
4873 continue;
4874 }
4875 /*
4876 * For a tonga, we need to return
4877 * the code corresponding to the
4878 * actual physical slot
4879 */
4880 code = FRU_UNIT_TO_EVCODE(SLOT,
4881 slotnum);
4882 } else {
4883 if (slotnum > MC_MAX_SLOTS ||
4884 slotnum == SC_MC_CPU_SLOT ||
4885 (scsb->scsb_hsc_state &
4886 SCSB_HSC_CTC_PRES &&
4887 slotnum == SC_MC_CTC_SLOT)) {
4888 continue;
4889 }
4890 }
4891 /* FALLTHROUGH */
4892 case ALARM:
4893 /*
4894 * INDENT CHEATING, 2 indentations
4895 */
4896 ac_present = 0;
4897 /*
4898 * If it is an Alarm Card Interrupt, we just do some sanity
4899 * checks and then wait for the slot interrupt to take
4900 * connect or disconnect action.
4901 * XXX - Is there a gaurantee that ALARM int will occur first ?
4902 */
4903 if (fru_type == ALARM) {
4904 DEBUG2("AC Intr %d(%d)\n", scsb->ac_slotnum, idx+1);
4905 val = scsb_fru_op(scsb, SLOT,
4906 tonga_ssl_to_psl(scsb, scsb->ac_slotnum),
4907 SCTRL_SYSCFG_BASE, SCSB_FRU_OP_GET_BITVAL);
4908 ac_present = scsb_fru_op(scsb, ALARM, 1,
4909 SCTRL_SYSCFG_BASE,
4910 SCSB_FRU_OP_GET_BITVAL);
4911 /*
4912 * It is observed that slot presence and Alarm
4913 * presence bits do not go ON at the same time.
4914 * Hence we wait till both events happen.
4915 */
4916 #ifdef DEBUG
4917 if ((((val) && (!ac_present)) ||
4918 ((!val) && (ac_present))) &&
4919 (scsb->scsb_hsc_state &
4920 SCSB_AC_SLOT_INTR_DONE))
4921
4922 cmn_err(CE_WARN, "?Alarm and Slot presence "
4923 "state bits do not match! (%x,%x)",
4924 val, ac_present);
4925 #endif
4926 if (scsb->scsb_hsc_state & SCSB_AC_SLOT_INTR_DONE)
4927 scsb->scsb_hsc_state &= ~SCSB_AC_SLOT_INTR_DONE;
4928 else
4929 scsb->scsb_hsc_state |= SCSB_AC_SLOT_INTR_DONE;
4930 break; /* we break and wait for slot interrupt. */
4931 }
4932
4933 /*
4934 * cPCI slot interrupt event
4935 */
4936 if (scsb->scsb_state & SCSB_IS_TONGA) {
4937 if (slotnum > TG_MAX_SLOTS ||
4938 slotnum == SC_TG_CPU_SLOT) {
4939 continue;
4940 }
4941 } else {
4942 if (slotnum > MC_MAX_SLOTS ||
4943 slotnum == SC_MC_CPU_SLOT ||
4944 (scsb->scsb_hsc_state & SCSB_HSC_CTC_PRES &&
4945 slotnum == SC_MC_CTC_SLOT)) {
4946 continue;
4947 }
4948 }
4949 if (scsb_is_alarm_card_slot(scsb, slotnum) == B_TRUE) {
4950 DEBUG2("AC slot Intr %d(%d)\n", slotnum, idx+1);
4951 ac_slot = B_TRUE;
4952 }
4953 val = scsb_fru_op(scsb, SLOT, unit, SCTRL_SYSCFG_BASE,
4954 SCSB_FRU_OP_GET_BITVAL);
4955 if (ac_slot == B_TRUE) {
4956 ac_present = scsb_fru_op(scsb, ALARM, 1,
4957 SCTRL_SYSCFG_BASE,
4958 SCSB_FRU_OP_GET_BITVAL);
4959 #ifdef DEBUG
4960 if ((((val) && (!ac_present)) ||
4961 ((!val) && (ac_present))) &&
4962 (scsb->scsb_hsc_state &
4963 SCSB_AC_SLOT_INTR_DONE)) {
4964
4965 cmn_err(CE_WARN, "?Alarm and Slot presence "
4966 "state bits do not match! (%x,%x)",
4967 val, ac_present);
4968 }
4969 #endif
4970 if (scsb->scsb_hsc_state & SCSB_AC_SLOT_INTR_DONE)
4971 scsb->scsb_hsc_state &= ~SCSB_AC_SLOT_INTR_DONE;
4972 else
4973 scsb->scsb_hsc_state |= SCSB_AC_SLOT_INTR_DONE;
4974 }
4975 if (val) {
4976 if (ac_present) {
4977 DEBUG1("AC insertion on slot %d!\n", slotnum);
4978 if (scsb_debug & 0x00010000) {
4979 cmn_err(CE_NOTE, "scsb_intr: "
4980 "AC_PRES slot %d", slotnum);
4981 }
4982 scsb->scsb_hsc_state |= SCSB_ALARM_CARD_PRES;
4983 }
4984 #ifndef lint
4985 else
4986 DEBUG1("IO Insertion on slot %d!\n", slotnum);
4987 #endif
4988 /*
4989 * Special case : check MPID type.
4990 * If MC midplane type,
4991 * check to make sure the Alarm Card present
4992 * bit is ON. If not, this is a regular IO card.
4993 */
4994 (void) scsb_connect_slot(scsb, slotnum, B_FALSE);
4995 } else {
4996 if ((ac_slot == B_TRUE) &&
4997 (scsb->scsb_hsc_state & SCSB_ALARM_CARD_PRES)) {
4998
4999 DEBUG1("AC Removal on slot %d!\n", slotnum);
5000 #ifdef DEBUG
5001 if (scsb_debug & 0x00010000) {
5002 cmn_err(CE_NOTE, "scsb_intr: "
5003 "!AC_PRES slot %d",
5004 slotnum);
5005 }
5006 #endif /* DEBUG */
5007 scsb->scsb_hsc_state &= ~SCSB_ALARM_CARD_PRES;
5008 }
5009 #ifndef lint
5010 else
5011 DEBUG1("IO Removal on slot %d!\n", slotnum);
5012 #endif
5013 (void) scsb_disconnect_slot(scsb, B_FALSE, slotnum);
5014 }
5015 /*
5016 * END INDENT CHEATING, 2 indentations
5017 */
5018
5019 break;
5020 default:
5021 /*
5022 * ERROR: Did not find cause of INTSRC bit
5023 */
5024 if (scsb_debug & 0x00000002) {
5025 cmn_err(CE_WARN,
5026 "scsb_intr: FRU type %d"
5027 " not recognized", fru_type);
5028 }
5029 continue;
5030 }
5031 scsb_event_code |= code;
5032 retval |= (SCSB_INTR_CLAIMED | SCSB_INTR_EVENT);
5033 if (fru_type == SLOT)
5034 continue;
5035 error = 0;
5036 fru_ptr = mct_system_info.fru_info_list[fru_type];
5037 for (; fru_ptr != NULL; fru_ptr = fru_ptr->next) {
5038 if (unit != fru_ptr->fru_unit)
5039 continue;
5040 if (fru_ptr->i2c_info == NULL ||
5041 (tmp_reg = fru_ptr->i2c_info->
5042 ledata_reg) == 0)
5043 continue;
5044 error = scsb_set_scfg_pres_leds(scsb, fru_ptr);
5045 if (error) {
5046 cmn_err(CE_WARN, "scsb_intr(): "
5047 "I2C write error to 0x%x",
5048 tmp_reg);
5049 if (!(scsb->scsb_state &
5050 SCSB_DEBUG_MODE)) {
5051 goto intr_error;
5052 }
5053 }
5054 break;
5055 }
5056 }
5057 if (clr_bits) {
5058 clr_bits = 0;
5059 }
5060 }
5061 /*
5062 * Check for SCB 1.5 interrupt for SLOT HEALTHY changes
5063 */
5064 clr_bits = 0;
5065 intr_idx = 0;
5066 numregs = SCTRL_INTR_NUMREGS;
5067 intr_addr = SCSB_REG_ADDR(SCTRL_INTSRC_BASE);
5068 index = SCSB_REG_INDEX(intr_addr);
5069 if (IS_SCB_P15) {
5070 for (i = 0; i < SCTRL_BHLTHY_NUMREGS;
5071 ++i, ++intr_idx, ++intr_addr) {
5072 scsb->scsb_data_reg[index++] = scb_intr_regs[intr_idx];
5073 intr_reg = scb_intr_regs[i];
5074 while (intr_reg) {
5075 idx = event_to_index((uint32_t)intr_reg);
5076 code = (1 << idx);
5077 clr_bits |= code;
5078 intr_reg = intr_reg & ~code;
5079 /* idx + 1 because bit 0 is for Slot 1 */
5080 slotnum = tonga_ssl_to_psl(scsb, idx + 1);
5081 if (scsb->scsb_state & SCSB_IS_TONGA) {
5082 if (slotnum > TG_MAX_SLOTS ||
5083 slotnum == SC_TG_CPU_SLOT) {
5084 continue;
5085 }
5086 } else {
5087 if (slotnum > MC_MAX_SLOTS ||
5088 slotnum == SC_MC_CPU_SLOT ||
5089 (scsb->scsb_hsc_state &
5090 SCSB_HSC_CTC_PRES &&
5091 slotnum == SC_MC_CTC_SLOT)) {
5092 continue;
5093 }
5094 }
5095 scsb_healthy_intr(scsb, slotnum);
5096 }
5097 if (clr_bits) {
5098 clr_bits = 0;
5099 }
5100 }
5101 }
5102 code = scsb_event_code;
5103 if (retval & SCSB_INTR_EVENT &&
5104 !(scsb->scsb_state & SCSB_P06_NOINT_KLUGE)) {
5105 check_fru_info(scsb, code);
5106 add_event_code(scsb, code);
5107 (void) scsb_queue_ops(scsb, QPUT_INT32, 1, &scsb_event_code,
5108 "scsb_intr");
5109 }
5110 intr_error:
5111 scb_post_e = gethrtime();
5112
5113 if (scsb_debug & 0x8000000)
5114 cmn_err(CE_NOTE, "Summary of times in nsec: pre_time %llu, \
5115 post_time %llu", scb_pre_e - scb_pre_s,
5116 scb_post_e - scb_post_s);
5117
5118
5119 mutex_enter(&scsb->scsb_mutex);
5120 scsb_in_postintr = 0;
5121 cv_broadcast(&scsb->scsb_cv);
5122 mutex_exit(&scsb->scsb_mutex);
5123
5124 /*
5125 * Re-enable interrupt now.
5126 */
5127 (void) scsb_toggle_psmint(scsb, 1);
5128 scsb->scsb_state &= ~SCSB_IN_INTR;
5129 }
5130
5131 static int
5132 scsb_polled_int(scsb_state_t *scsb, int cmd, uint32_t *set)
5133 {
5134 if (scsb_debug & 0x4000)
5135 cmn_err(CE_NOTE, "scsb_polled_int(scsb,0x%x)", cmd);
5136 *set = 0;
5137 if (cmd == SCSBIOC_SHUTDOWN_POLL) {
5138 return (EINVAL);
5139 }
5140 if (cmd != SCSBIOC_INTEVENT_POLL) {
5141 return (EINVAL);
5142 }
5143 if (scsb->scsb_state & SCSB_P06_NOINT_KLUGE) {
5144 /*
5145 * scsb_intr() may modify scsb_event_code
5146 */
5147 scsb_event_code = SCTRL_EVENT_NONE;
5148 (void) scsb_intr((caddr_t)scsb);
5149 *set = scsb_event_code;
5150 scsb_event_code = 0;
5151 } else {
5152 /*
5153 * SCSB_P06_INTR_ON, we know there was an event
5154 * and we're retrieving the event code from the event FIFO.
5155 */
5156 *set = get_event_code();
5157 }
5158 if (scsb_debug & 0x01004000) {
5159 cmn_err(CE_NOTE, "scsb_polled_int: event_code = 0x%x", *set);
5160 }
5161 return (0);
5162 }
5163
5164 static int
5165 scsb_leds_switch(scsb_state_t *scsb, scsb_ustate_t op)
5166 {
5167 register int i;
5168 int index;
5169 uchar_t reg, idata, rwbuf[SCTRL_MAX_GROUP_NUMREGS];
5170
5171 if (scsb->scsb_state & SCSB_FROZEN &&
5172 !(scsb->scsb_state & SCSB_IN_INTR)) {
5173 return (EAGAIN);
5174 }
5175 if (scsb_debug & 0x0101) {
5176 cmn_err(CE_NOTE, "scsb_leds_switch(%s):",
5177 op == ON ? "ON" : "OFF");
5178 }
5179 /* Step 1: turn ON/OFF all NOK LEDs. */
5180 if (scsb_debug & 0x0100) {
5181 cmn_err(CE_NOTE, "scsb%d: turning all NOK LEDs %s",
5182 scsb->scsb_instance,
5183 op == ON ? "ON" : "OFF");
5184 }
5185 if (op == ON)
5186 idata = 0xff;
5187 else /* off */
5188 idata = 0x00;
5189 reg = SCSB_REG_ADDR(SCTRL_LED_NOK_BASE);
5190 index = SCSB_REG_INDEX(reg);
5191 for (i = 0; i < SCTRL_LED_NOK_NUMREGS; ++i) {
5192 rwbuf[i] = idata;
5193 scsb->scsb_data_reg[index + i] = idata;
5194 }
5195 mutex_enter(&scsb->scsb_mutex);
5196 i = scsb_rdwr_register(scsb, I2C_WR, reg, SCTRL_LED_NOK_NUMREGS,
5197 rwbuf, 1);
5198 mutex_exit(&scsb->scsb_mutex);
5199 if (i) {
5200 if (scsb_debug & 0x0102)
5201 cmn_err(CE_WARN, "scsb_leds_switch(): "
5202 "Failed to turn %s NOK LEDs",
5203 op == ON ? "ON" : "OFF");
5204 }
5205 /* Step 2: turn ON/OFF all OK LEDs. */
5206 if (scsb_debug & 0x0100) {
5207 cmn_err(CE_NOTE, "scsb%d: turning all OK LEDs %s",
5208 scsb->scsb_instance,
5209 op == ON ? "ON" : "OFF");
5210 }
5211 reg = SCSB_REG_ADDR(SCTRL_LED_OK_BASE);
5212 index = SCSB_REG_INDEX(reg);
5213 for (i = 0; i < SCTRL_LED_OK_NUMREGS; ++i) {
5214 rwbuf[i] = idata;
5215 scsb->scsb_data_reg[index + i] = idata;
5216 }
5217 mutex_enter(&scsb->scsb_mutex);
5218 i = scsb_rdwr_register(scsb, I2C_WR, reg, SCTRL_LED_OK_NUMREGS,
5219 rwbuf, 1);
5220 mutex_exit(&scsb->scsb_mutex);
5221 if (i) {
5222 if (scsb_debug & 0x0102)
5223 cmn_err(CE_WARN, "scsb_leds_switch(): "
5224 "Failed to turn %s NOK LEDs",
5225 op == ON ? "ON" : "OFF");
5226 }
5227 /* Step 3: turn OFF all BLINK LEDs. */
5228 if (op == OFF) {
5229 reg = SCSB_REG_ADDR(SCTRL_BLINK_OK_BASE);
5230 index = SCSB_REG_INDEX(reg);
5231 for (i = 0; i < SCTRL_BLINK_NUMREGS; ++i) {
5232 rwbuf[i] = idata;
5233 scsb->scsb_data_reg[index + i] = idata;
5234 }
5235 mutex_enter(&scsb->scsb_mutex);
5236 i = scsb_rdwr_register(scsb, I2C_WR, reg, SCTRL_BLINK_NUMREGS,
5237 rwbuf, 1);
5238 mutex_exit(&scsb->scsb_mutex);
5239 if (i) {
5240 if (scsb_debug & 0x0102)
5241 cmn_err(CE_WARN, "scsb_leds_switch(): "
5242 "Failed to turn %s BLINK BITs",
5243 op == ON ? "ON" : "OFF");
5244 }
5245 }
5246 return (0);
5247 }
5248
5249 static int
5250 scsb_readall_regs(scsb_state_t *scsb)
5251 {
5252 int error;
5253 int index;
5254 uchar_t reg;
5255
5256 if (!(scsb_debug & 0x40000000))
5257 return (0);
5258 if (scsb_debug & 0x0005) {
5259 cmn_err(CE_NOTE, "scsb_readall_regs:");
5260 }
5261 if (scsb->scsb_state & SCSB_FROZEN) {
5262 return (EAGAIN);
5263 }
5264 reg = SCSB_REG_ADDR_START; /* 1st register in set */
5265 index = SCSB_REG_INDEX(reg);
5266 error = scsb_rdwr_register(scsb, I2C_WR_RD, reg, SCSB_DATA_REGISTERS,
5267 &scsb->scsb_data_reg[index], 1);
5268 return (error);
5269 }
5270
5271
5272 /*
5273 * read 1-byte register, mask with read bits (rmask),
5274 * turn ON bits in on_mask, turn OFF bits in off_mask
5275 * write the byte back to register
5276 * NOTE: MUST be called with mutex held
5277 */
5278 static int
5279 scsb_write_mask(scsb_state_t *scsb,
5280 uchar_t reg,
5281 uchar_t rmask,
5282 uchar_t on_mask,
5283 uchar_t off_mask)
5284 {
5285 i2c_transfer_t *i2cxferp;
5286 int index, error = 0;
5287 uchar_t reg_data;
5288
5289 if (scsb_debug & 0x0800) {
5290 cmn_err(CE_NOTE, "scsb_write_mask(,%x,,%x,%x):",
5291 reg, on_mask, off_mask);
5292 }
5293 if (scsb->scsb_state & SCSB_FROZEN &&
5294 !(scsb->scsb_state & SCSB_IN_INTR)) {
5295 return (EAGAIN);
5296 }
5297 /* select the register address and read the register */
5298 i2cxferp = (i2c_transfer_t *)scsb->scsb_i2ctp;
5299 i2cxferp->i2c_flags = I2C_WR_RD;
5300 i2cxferp->i2c_wlen = 1;
5301 i2cxferp->i2c_rlen = 1;
5302 i2cxferp->i2c_wbuf[0] = reg;
5303 i2cxferp->i2c_rbuf[0] = 0;
5304 scsb->scsb_kstat_flag = B_TRUE; /* we did a i2c transaction */
5305 if (error = nct_i2c_transfer(scsb->scsb_phandle, i2cxferp)) {
5306 error = EIO;
5307 goto wm_error;
5308 }
5309 scsb->scsb_i2c_errcnt = 0;
5310 if (scsb_debug & 0x0800)
5311 cmn_err(CE_NOTE, "scsb_write_mask() read 0x%x",
5312 i2cxferp->i2c_rbuf[0]);
5313 reg_data = i2cxferp->i2c_rbuf[0];
5314 if (rmask)
5315 reg_data &= rmask;
5316 if (off_mask)
5317 reg_data &= ~off_mask;
5318 if (on_mask)
5319 reg_data |= on_mask;
5320 i2cxferp->i2c_flags = I2C_WR;
5321 i2cxferp->i2c_wlen = 2;
5322 i2cxferp->i2c_wbuf[0] = reg;
5323 i2cxferp->i2c_wbuf[1] = reg_data;
5324 if (error = nct_i2c_transfer(scsb->scsb_phandle, i2cxferp)) {
5325 error = EIO;
5326 goto wm_error;
5327 }
5328 /* keep shadow registers updated */
5329 index = SCSB_REG_INDEX(reg);
5330 scsb->scsb_data_reg[index] = reg_data;
5331 if (scsb_debug & 0x0800)
5332 cmn_err(CE_NOTE, "scsb_write_mask() wrote 0x%x", reg_data);
5333 scsb->scsb_i2c_errcnt = 0;
5334 return (error);
5335 wm_error:
5336 scsb->scsb_i2c_errcnt++;
5337 if (scsb->scsb_i2c_errcnt > scsb_err_threshold)
5338 scsb->scsb_err_flag = B_TRUE; /* latch error */
5339 if (scsb->scsb_state & SCSB_SSB_PRESENT) {
5340 if (scsb_debug & 0x0802)
5341 cmn_err(CE_WARN,
5342 "scsb_write_mask(): reg %x %s error, data=%x",
5343 reg,
5344 i2cxferp->i2c_flags & I2C_WR ? "write" : "read",
5345 i2cxferp->i2c_flags & I2C_WR ?
5346 i2cxferp->i2c_wbuf[1] : i2cxferp->i2c_rbuf[0]);
5347 } else {
5348 if (scsb->scsb_i2c_errcnt >= scsb_freeze_count)
5349 scsb_freeze(scsb);
5350 return (EAGAIN);
5351 }
5352 return (error);
5353 }
5354
5355 /*
5356 * read/write len consecutive single byte registers to/from rbuf
5357 * NOTE: should be called with mutex held
5358 */
5359 static int
5360 scsb_rdwr_register(scsb_state_t *scsb, int op, uchar_t reg, int len,
5361 uchar_t *rwbuf, int i2c_alloc)
5362 {
5363 i2c_transfer_t *i2cxferp;
5364 int i, rlen, wlen, index, error = 0;
5365
5366 if (scsb_debug & 0x0800) {
5367 cmn_err(CE_NOTE, "scsb_rdwr_register(scsb,%s,%x,%x,buf):",
5368 (op == I2C_WR) ? "write" : "read", reg, len);
5369 }
5370 if (scsb->scsb_state & SCSB_FROZEN &&
5371 !(scsb->scsb_state & SCSB_IN_INTR)) {
5372 return (EAGAIN);
5373 }
5374 if (i2c_alloc) {
5375 i2cxferp = scsb_alloc_i2ctx(scsb->scsb_phandle, I2C_NOSLEEP);
5376 if (i2cxferp == NULL) {
5377 if (scsb_debug & 0x0042)
5378 cmn_err(CE_WARN, "scsb_rdwr_register: "
5379 "i2ctx allocation failure");
5380 return (ENOMEM);
5381 }
5382 } else {
5383 i2cxferp = scsb->scsb_i2ctp;
5384 }
5385 index = SCSB_REG_INDEX(reg);
5386 switch (op) {
5387 case I2C_WR:
5388 wlen = len + 1; /* add the address */
5389 rlen = 0;
5390 i2cxferp->i2c_wbuf[0] = reg;
5391 for (i = 0; i < len; ++i) {
5392 scsb->scsb_data_reg[index + i] =
5393 i2cxferp->i2c_wbuf[1 + i] = rwbuf[i];
5394 if (scsb_debug & 0x0080)
5395 cmn_err(CE_NOTE,
5396 "scsb_rdwr_register: writing rwbuf[%d]=0x%x",
5397 i, rwbuf[i]);
5398 }
5399 break;
5400 case I2C_WR_RD:
5401 wlen = 1; /* for the address */
5402 rlen = len;
5403 i2cxferp->i2c_wbuf[0] = reg;
5404 break;
5405 default:
5406 if (i2c_alloc)
5407 scsb_free_i2ctx(scsb->scsb_phandle, i2cxferp);
5408 return (EINVAL);
5409 }
5410 /* select the register address */
5411 i2cxferp->i2c_flags = op;
5412 i2cxferp->i2c_rlen = rlen;
5413 i2cxferp->i2c_wlen = wlen;
5414 i2cxferp->i2c_wbuf[0] = reg;
5415 scsb->scsb_kstat_flag = B_TRUE; /* we did a i2c transaction */
5416 if (error = nct_i2c_transfer(scsb->scsb_phandle, i2cxferp)) {
5417 error = EIO;
5418 } else if (rlen) {
5419 /* copy to rwbuf[] and keep shadow registers updated */
5420 for (i = 0; i < len; ++i) {
5421 scsb->scsb_data_reg[index + i] = rwbuf[i] =
5422 i2cxferp->i2c_rbuf[i];
5423 if (scsb_debug & 0x0080)
5424 cmn_err(CE_NOTE,
5425 "scsb_rdwr_register: read rwbuf[%d]=0x%x",
5426 i, rwbuf[i]);
5427 }
5428 }
5429 if (i2c_alloc)
5430 scsb_free_i2ctx(scsb->scsb_phandle, i2cxferp);
5431 if (error) {
5432 scsb->scsb_i2c_errcnt++;
5433 if (scsb->scsb_i2c_errcnt > scsb_err_threshold)
5434 scsb->scsb_err_flag = B_TRUE; /* latch error */
5435 if (!(scsb->scsb_state & SCSB_SSB_PRESENT)) {
5436 if (scsb->scsb_i2c_errcnt >= scsb_freeze_count)
5437 scsb_freeze(scsb);
5438 return (EAGAIN);
5439 } else {
5440 cmn_err(CE_WARN,
5441 "scsb_rdwr_register(): I2C read error from %x",
5442 reg);
5443 }
5444 } else {
5445 scsb->scsb_i2c_errcnt = 0;
5446 }
5447
5448 return (error);
5449 }
5450
5451 /*
5452 * Called from scsb_intr()
5453 * First find the fru_info for this fru_id, and set fru_status for callback.
5454 * Then check for a registered call_back entry for this fru_id,
5455 * and if found, call it.
5456 * Recursize call until no EVENTS left in evcode.
5457 */
5458 static void
5459 check_fru_info(scsb_state_t *scsb, int evcode)
5460 {
5461 struct scsb_cb_entry *cbe_ptr;
5462 fru_info_t *fru_ptr;
5463 fru_id_t fru_id;
5464 scsb_fru_status_t fru_status;
5465 int i, new_evcode;
5466
5467 if (scsb_debug & 0x00100001)
5468 cmn_err(CE_NOTE, "check_fru_info(scsb,0x%x)", evcode);
5469 if (evcode == 0)
5470 return;
5471 i = event_to_index((uint32_t)evcode);
5472 new_evcode = evcode & ~(1 << i);
5473 if (i > MCT_MAX_FRUS) {
5474 if (scsb_debug & 0x00100000)
5475 cmn_err(CE_NOTE,
5476 "check_fru_info: index %d out of range", i);
5477 check_fru_info(scsb, new_evcode);
5478 return;
5479 }
5480 fru_id = fru_id_table[i];
5481 fru_ptr = find_fru_info(fru_id);
5482 if (fru_ptr == (fru_info_t *)NULL) {
5483 check_fru_info(scsb, new_evcode);
5484 return;
5485 }
5486 update_fru_info(scsb, fru_ptr);
5487 if (fru_ptr->fru_status & FRU_PRESENT) {
5488 fru_status = FRU_PRESENT;
5489 } else {
5490 fru_status = FRU_NOT_PRESENT;
5491 if (fru_ptr->fru_type == SSB) {
5492 /*
5493 * WARN against SCB removal if any
5494 * occupied slots are in reset
5495 */
5496 scsb_freeze_check(scsb);
5497 }
5498 }
5499 /*
5500 * check for an entry in the CallBack table
5501 */
5502 for (cbe_ptr = scsb_cb_table; cbe_ptr != NULL;
5503 cbe_ptr = cbe_ptr->cb_next) {
5504 if (cbe_ptr->cb_fru_id == fru_id &&
5505 cbe_ptr->cb_fru_ptr == fru_ptr) {
5506 if (scsb_debug & 0x00800000)
5507 cmn_err(CE_NOTE,
5508 "check_fru_info: callback for FRU_ID "
5509 "0x%x; device is %spresent",
5510 (int)fru_id,
5511 fru_status == FRU_PRESENT ?
5512 "" : "not ");
5513 (*cbe_ptr->cb_func)(
5514 cbe_ptr->cb_softstate_ptr,
5515 cbe_ptr->cb_event,
5516 fru_status);
5517 break;
5518 }
5519 }
5520 check_fru_info(scsb, new_evcode);
5521 }
5522
5523 /*
5524 * -----------------------------
5525 * scsb kstat support functions.
5526 * -----------------------------
5527 */
5528 /*
5529 * Create and initialize the kstat data structures
5530 */
5531 static int
5532 scsb_alloc_kstats(scsb_state_t *scsb)
5533 {
5534 kstat_named_t *kn;
5535 /*
5536 * scsb_ks_leddata_t for "scsb_leddata"
5537 */
5538 if (scsb_debug & 0x00080001)
5539 cmn_err(CE_NOTE,
5540 "scsb_alloc_kstats: create scsb_leddata: %lu bytes",
5541 sizeof (scsb_ks_leddata_t));
5542 if ((scsb->ks_leddata = kstat_create(scsb_name, scsb->scsb_instance,
5543 SCSB_KS_LEDDATA, "misc", KSTAT_TYPE_RAW,
5544 sizeof (scsb_ks_leddata_t), KSTAT_FLAG_PERSISTENT))
5545 == NULL) {
5546 scsb->scsb_state |= SCSB_KSTATS;
5547 scsb_free_kstats(scsb);
5548 return (DDI_FAILURE);
5549 }
5550 scsb->ks_leddata->ks_update = update_ks_leddata;
5551 scsb->ks_leddata->ks_private = (void *)scsb;
5552 if (update_ks_leddata(scsb->ks_leddata, KSTAT_READ) != DDI_SUCCESS) {
5553 scsb->scsb_state |= SCSB_KSTATS;
5554 scsb_free_kstats(scsb);
5555 return (DDI_FAILURE);
5556 }
5557 kstat_install(scsb->ks_leddata);
5558 /*
5559 * scsb_ks_state_t for "scsb_state"
5560 */
5561 if (scsb_debug & 0x00080000)
5562 cmn_err(CE_NOTE,
5563 "scsb_alloc_kstats: create scsb_state: %lu bytes",
5564 sizeof (scsb_ks_state_t));
5565 if ((scsb->ks_state = kstat_create(scsb_name, scsb->scsb_instance,
5566 SCSB_KS_STATE, "misc", KSTAT_TYPE_RAW,
5567 sizeof (scsb_ks_state_t), KSTAT_FLAG_PERSISTENT))
5568 == NULL) {
5569 scsb->scsb_state |= SCSB_KSTATS;
5570 scsb_free_kstats(scsb);
5571 return (DDI_FAILURE);
5572 }
5573 scsb->ks_state->ks_update = update_ks_state;
5574 scsb->ks_state->ks_private = (void *)scsb;
5575 if (update_ks_state(scsb->ks_state, KSTAT_READ) != DDI_SUCCESS) {
5576 scsb->scsb_state |= SCSB_KSTATS;
5577 scsb_free_kstats(scsb);
5578 return (DDI_FAILURE);
5579 }
5580 kstat_install(scsb->ks_state);
5581 /*
5582 * mct_topology_t for "env_topology"
5583 */
5584 if (scsb_debug & 0x00080000)
5585 cmn_err(CE_NOTE,
5586 "scsb_alloc_kstats: create env_toploogy: %lu bytes",
5587 sizeof (mct_topology_t));
5588 if ((scsb->ks_topology = kstat_create(scsb_name, scsb->scsb_instance,
5589 SCSB_KS_TOPOLOGY, "misc", KSTAT_TYPE_RAW,
5590 sizeof (mct_topology_t), KSTAT_FLAG_PERSISTENT))
5591 == NULL) {
5592 scsb->scsb_state |= SCSB_KSTATS;
5593 scsb_free_kstats(scsb);
5594 return (DDI_FAILURE);
5595 }
5596 scsb->ks_topology->ks_update = update_ks_topology;
5597 scsb->ks_topology->ks_private = (void *)scsb;
5598 if (update_ks_topology(scsb->ks_topology, KSTAT_READ) != DDI_SUCCESS) {
5599 scsb->scsb_state |= SCSB_KSTATS;
5600 scsb_free_kstats(scsb);
5601 return (DDI_FAILURE);
5602 }
5603 kstat_install(scsb->ks_topology);
5604 /*
5605 * kstat_named_t * 2 for "scsb_evc_register"
5606 */
5607 if (scsb_debug & 0x00080001)
5608 cmn_err(CE_NOTE,
5609 "scsb_alloc_kstats: create scsb_evc_register: %lu bytes",
5610 sizeof (kstat_named_t) * 2);
5611 if ((scsb->ks_evcreg = kstat_create(scsb_name, scsb->scsb_instance,
5612 SCSB_KS_EVC_REGISTER, "misc", KSTAT_TYPE_NAMED, 2,
5613 KSTAT_FLAG_PERSISTENT|KSTAT_FLAG_WRITABLE)) == NULL) {
5614 scsb->scsb_state |= SCSB_KSTATS;
5615 scsb_free_kstats(scsb);
5616 return (DDI_FAILURE);
5617 }
5618 scsb->ks_evcreg->ks_update = update_ks_evcreg;
5619 scsb->ks_evcreg->ks_private = (void *)scsb;
5620 kn = KSTAT_NAMED_PTR(scsb->ks_evcreg);
5621 kstat_named_init(&kn[0], "pid_register", KSTAT_DATA_INT64);
5622 kstat_named_init(&kn[1], "pid_unregister", KSTAT_DATA_INT64);
5623 kstat_install(scsb->ks_evcreg);
5624 /*
5625 * Done, set the flag for scsb_detach() and other checks
5626 */
5627 scsb->scsb_state |= SCSB_KSTATS;
5628 return (DDI_SUCCESS);
5629 }
5630
5631 static int
5632 update_ks_leddata(kstat_t *ksp, int rw)
5633 {
5634 scsb_state_t *scsb;
5635 scsb_ks_leddata_t *pks_leddata;
5636 int i, numregs, index, error = DDI_SUCCESS;
5637 uchar_t reg;
5638
5639 scsb = (scsb_state_t *)ksp->ks_private;
5640 if (scsb_debug & 0x00080001)
5641 cmn_err(CE_NOTE, "update_ks_leddata: KS_UPDATE%sset",
5642 scsb->scsb_state & SCSB_KS_UPDATE ? " " : " not ");
5643 /*
5644 * Since this is satisfied from the shadow registers, let it succeed
5645 * even if the SCB is not present. It would be nice to return the
5646 * shadow values with a warning.
5647 *
5648 * if (scsb->scsb_state & SCSB_FROZEN) {
5649 * return (DDI_FAILURE);
5650 * }
5651 */
5652 if (rw == KSTAT_WRITE) {
5653 return (EACCES);
5654 }
5655 mutex_enter(&scsb->scsb_mutex);
5656 while (scsb->scsb_state & SCSB_KS_UPDATE) {
5657 if (cv_wait_sig(&scsb->scsb_cv, &scsb->scsb_mutex) <= 0) {
5658 mutex_exit(&scsb->scsb_mutex);
5659 return (EINTR);
5660 }
5661 }
5662 scsb->scsb_state |= SCSB_KS_UPDATE;
5663 mutex_exit(&scsb->scsb_mutex);
5664 if (scsb_debug & 0x00080001)
5665 cmn_err(CE_NOTE, "update_ks_leddata: updating data");
5666 pks_leddata = (scsb_ks_leddata_t *)ksp->ks_data;
5667 /*
5668 * Call tonga_slotnum_led_shift() for each register that
5669 * contains Slot 1-5 information, the first register at each base:
5670 * NOK_BASE, OK_BASE, BLINK_OK_BASE
5671 * XXX: breaking register table access rules by not using macros.
5672 */
5673 /* NOK */
5674 reg = SCSB_REG_ADDR(SCTRL_LED_NOK_BASE);
5675 index = SCSB_REG_INDEX(reg);
5676 numregs = SCTRL_LED_NOK_NUMREGS;
5677 i = 0;
5678 if (IS_SCB_P15)
5679 reg = tonga_slotnum_led_shift(scsb, scsb->scsb_data_reg[index]);
5680 else
5681 reg = scsb->scsb_data_reg[index];
5682 pks_leddata->scb_led_regs[i] = reg;
5683 for (++i, ++index; i < numregs; ++i, ++index)
5684 pks_leddata->scb_led_regs[i] = scsb->scsb_data_reg[index];
5685 /* OK */
5686 reg = SCSB_REG_ADDR(SCTRL_LED_OK_BASE);
5687 index = SCSB_REG_INDEX(reg);
5688 numregs += SCTRL_LED_OK_NUMREGS;
5689 if (IS_SCB_P15)
5690 reg = tonga_slotnum_led_shift(scsb, scsb->scsb_data_reg[index]);
5691 else
5692 reg = scsb->scsb_data_reg[index];
5693 pks_leddata->scb_led_regs[i] = reg;
5694 for (++i, ++index; i < numregs; ++i, ++index)
5695 pks_leddata->scb_led_regs[i] = scsb->scsb_data_reg[index];
5696 /* BLINK */
5697 reg = SCSB_REG_ADDR(SCTRL_BLINK_OK_BASE);
5698 index = SCSB_REG_INDEX(reg);
5699 numregs += SCTRL_BLINK_NUMREGS;
5700 if (IS_SCB_P15)
5701 reg = tonga_slotnum_led_shift(scsb, scsb->scsb_data_reg[index]);
5702 else
5703 reg = scsb->scsb_data_reg[index];
5704 pks_leddata->scb_led_regs[i] = reg;
5705 for (++i, ++index; i < numregs; ++i, ++index)
5706 pks_leddata->scb_led_regs[i] = scsb->scsb_data_reg[index];
5707 mutex_enter(&scsb->scsb_mutex);
5708 scsb->scsb_state &= ~SCSB_KS_UPDATE;
5709 cv_signal(&scsb->scsb_cv);
5710 mutex_exit(&scsb->scsb_mutex);
5711 if (scsb_debug & 0x00080001)
5712 cmn_err(CE_NOTE, "update_ks_leddata: returning");
5713 return (error);
5714 }
5715
5716 static int
5717 update_ks_evcreg(kstat_t *ksp, int rw)
5718 {
5719 scsb_state_t *scsb;
5720 int error = 0;
5721 kstat_named_t *kn = KSTAT_NAMED_PTR(ksp);
5722 pid_t pid;
5723
5724 scsb = (scsb_state_t *)ksp->ks_private;
5725 if (scsb_debug & 0x00080001)
5726 cmn_err(CE_NOTE, "update_ks_evcreg: %s(%d), KS_UPDATE%sset",
5727 rw == KSTAT_READ ? "read" : "write", rw,
5728 scsb->scsb_state & SCSB_KS_UPDATE ? " " : " not ");
5729 /*
5730 * Let this registration succeed
5731 *
5732 * if (scsb->scsb_state & SCSB_FROZEN) {
5733 * return (DDI_FAILURE);
5734 * }
5735 */
5736 mutex_enter(&scsb->scsb_mutex);
5737 while (scsb->scsb_state & SCSB_KS_UPDATE) {
5738 if (cv_wait_sig(&scsb->scsb_cv, &scsb->scsb_mutex) <= 0) {
5739 mutex_exit(&scsb->scsb_mutex);
5740 return (EINTR);
5741 }
5742 }
5743 scsb->scsb_state |= SCSB_KS_UPDATE;
5744 mutex_exit(&scsb->scsb_mutex);
5745 if (rw == KSTAT_READ) {
5746 kn[0].value.i64 = (int64_t)0;
5747 kn[1].value.i64 = (int64_t)0;
5748 } else if (rw == KSTAT_WRITE) {
5749 /*
5750 * kn[0] is "pid_register", kn[1] is "pid_unregister"
5751 */
5752 if (kn[0].value.i64 != 0 && kn[1].value.i64 == 0) {
5753 pid = (pid_t)kn[0].value.i64;
5754 if (add_event_proc(scsb, pid)) {
5755 if (scsb_debug & 0x02000002) {
5756 cmn_err(CE_WARN,
5757 "update_ks_evcreg: "
5758 "process add failed for %d",
5759 pid);
5760 }
5761 error = EOVERFLOW;
5762 }
5763 } else if (kn[0].value.i64 == 0 && kn[1].value.i64 != 0) {
5764 pid = (pid_t)kn[1].value.i64;
5765 if (del_event_proc(scsb, pid)) {
5766 if (scsb_debug & 0x02000000) {
5767 cmn_err(CE_NOTE,
5768 "update_ks_evcreg: "
5769 "process delete failed for %d",
5770 pid);
5771 }
5772 error = EOVERFLOW;
5773 }
5774 } else if (kn[0].value.i64 == 0 && kn[1].value.i64 == 0) {
5775 /*
5776 * rewind the pointers and counts, zero the table.
5777 */
5778 rew_event_proc(scsb);
5779 } else {
5780 error = EINVAL;
5781 }
5782 } else {
5783 error = EINVAL;
5784 }
5785 mutex_enter(&scsb->scsb_mutex);
5786 scsb->scsb_state &= ~SCSB_KS_UPDATE;
5787 cv_signal(&scsb->scsb_cv);
5788 mutex_exit(&scsb->scsb_mutex);
5789 return (error);
5790 }
5791
5792 static int
5793 update_ks_state(kstat_t *ksp, int rw)
5794 {
5795 scsb_state_t *scsb;
5796 scsb_ks_state_t *pks_state;
5797 int error = DDI_SUCCESS;
5798 uint32_t current_evc;
5799
5800 scsb = (scsb_state_t *)ksp->ks_private;
5801 if (scsb_debug & 0x00080001)
5802 cmn_err(CE_NOTE, "update_ks_state: KS_UPDATE%sset",
5803 scsb->scsb_state & SCSB_KS_UPDATE ? " " : " not ");
5804 /*
5805 * Let this succeed based on last known data
5806 *
5807 * if (scsb->scsb_state & SCSB_FROZEN) {
5808 * return (DDI_FAILURE);
5809 * }
5810 */
5811 if (rw == KSTAT_WRITE) {
5812 return (EACCES);
5813 }
5814 mutex_enter(&scsb->scsb_mutex);
5815 while (scsb->scsb_state & SCSB_KS_UPDATE) {
5816 if (cv_wait_sig(&scsb->scsb_cv, &scsb->scsb_mutex) <= 0) {
5817 mutex_exit(&scsb->scsb_mutex);
5818 return (EINTR);
5819 }
5820 }
5821 scsb->scsb_state |= SCSB_KS_UPDATE;
5822 /*
5823 * If SSB not present and scsb not SCSB_FROZEN, check for SCB presence
5824 * by initiating an I2C read from the SCB. If an error occurs,
5825 * scsb_freeze() will be called to update SCB info and scsb state.
5826 */
5827 if (!(scsb->scsb_state & SCSB_SSB_PRESENT) &&
5828 !(scsb->scsb_state & SCSB_FROZEN)) {
5829 uchar_t data;
5830 /* Read the SCB PROM ID */
5831 if (data = scsb_rdwr_register(scsb, I2C_WR_RD,
5832 (uchar_t)SCTRL_PROM_VERSION, 1, &data, 1))
5833 if (scsb_debug & 0x00080002)
5834 cmn_err(CE_NOTE, "update_ks_state: SCB/I2C "
5835 "failure %d", data);
5836 }
5837 mutex_exit(&scsb->scsb_mutex);
5838 pks_state = (scsb_ks_state_t *)ksp->ks_data;
5839 pks_state->scb_present = (scsb->scsb_state & SCSB_SCB_PRESENT) ? 1 : 0;
5840 pks_state->ssb_present = (scsb->scsb_state & SCSB_SSB_PRESENT) ? 1 : 0;
5841 pks_state->scsb_frozen = (scsb->scsb_state & SCSB_FROZEN) ? 1 : 0;
5842 if (scsb->scsb_state & SCSB_DEBUG_MODE)
5843 pks_state->scsb_mode = (uint8_t)ENVC_DEBUG_MODE;
5844 else if (scsb->scsb_state & SCSB_DIAGS_MODE)
5845 pks_state->scsb_mode = (uint8_t)ENVCTRL_DIAG_MODE;
5846 else
5847 pks_state->scsb_mode = (uint8_t)ENVCTRL_NORMAL_MODE;
5848 /*
5849 * If scsb_attach() has not completed the kstat installs,
5850 * then there are no event processes to check for.
5851 */
5852 if (scsb->scsb_state & SCSB_KSTATS) {
5853 switch (check_event_procs(¤t_evc)) {
5854 case EVC_NO_EVENT_CODE:
5855 pks_state->event_code = 0;
5856 break;
5857 case EVC_NEW_EVENT_CODE:
5858 /* FALLTHROUGH */
5859 case EVC_NO_CURR_PROC:
5860 pks_state->event_code = current_evc;
5861 break;
5862 case EVC_OR_EVENT_CODE:
5863 pks_state->event_code |= current_evc;
5864 break;
5865 case EVC_FAILURE:
5866 pks_state->event_code = 0;
5867 error = DDI_FAILURE;
5868 break;
5869 }
5870 } else {
5871 pks_state->event_code = 0;
5872 }
5873 mutex_enter(&scsb->scsb_mutex);
5874 scsb->scsb_state &= ~SCSB_KS_UPDATE;
5875 cv_signal(&scsb->scsb_cv);
5876 mutex_exit(&scsb->scsb_mutex);
5877 return (error);
5878 }
5879
5880 static int
5881 update_ks_topology(kstat_t *ksp, int rw)
5882 {
5883 scsb_state_t *scsb;
5884 mct_topology_t *pks_topo;
5885 fru_info_t *fru_ptr;
5886 int i, val, error = DDI_SUCCESS, slotnum;
5887
5888 scsb = (scsb_state_t *)ksp->ks_private;
5889 if (scsb_debug & 0x00080001)
5890 cmn_err(CE_NOTE, "update_ks_topology: KS_UPDATE%sset",
5891 scsb->scsb_state & SCSB_KS_UPDATE ? " " : " not ");
5892 /*
5893 * Let this succeed based on last known data
5894 *
5895 * if (scsb->scsb_state & SCSB_FROZEN) {
5896 * return (DDI_FAILURE);
5897 * }
5898 */
5899 if (rw == KSTAT_WRITE) {
5900 return (EACCES);
5901 }
5902 mutex_enter(&scsb->scsb_mutex);
5903 while (scsb->scsb_state & SCSB_KS_UPDATE) {
5904 if (cv_wait_sig(&scsb->scsb_cv, &scsb->scsb_mutex) <= 0) {
5905 mutex_exit(&scsb->scsb_mutex);
5906 return (EINTR);
5907 }
5908 }
5909 scsb->scsb_state |= SCSB_KS_UPDATE;
5910 /*
5911 * If SSB not present and scsb not SCSB_FROZEN, check for SCB presence
5912 * by initiating an I2C read from the SCB. If an error occurs,
5913 * scsb_freeze() will be called to update SCB info and scsb state.
5914 */
5915 if (!(scsb->scsb_state & SCSB_SSB_PRESENT) &&
5916 !(scsb->scsb_state & SCSB_FROZEN)) {
5917 uchar_t data;
5918 /* Read the SCB PROM ID */
5919 if (data = scsb_rdwr_register(scsb, I2C_WR_RD,
5920 (uchar_t)SCTRL_PROM_VERSION, 1, &data, 1))
5921 if (scsb_debug & 0x00080002)
5922 cmn_err(CE_NOTE, "update_ks_topology: SCB/I2C "
5923 "failure %d", data);
5924 }
5925 mutex_exit(&scsb->scsb_mutex);
5926 pks_topo = (mct_topology_t *)ksp->ks_data;
5927 for (i = SLOT; i < SCSB_UNIT_TYPES; ++i) {
5928 pks_topo->max_units[i] = mct_system_info.max_units[i];
5929 }
5930
5931 pks_topo->mid_plane.fru_status = FRU_PRESENT;
5932 pks_topo->mid_plane.fru_unit = (scsb_unum_t)1;
5933 pks_topo->mid_plane.fru_type = mct_system_info.mid_plane.fru_type;
5934 pks_topo->mid_plane.fru_id = mct_system_info.mid_plane.fru_id;
5935 pks_topo->mid_plane.fru_version = mct_system_info.mid_plane.fru_version;
5936 pks_topo->mid_plane.fru_health = MCT_HEALTH_OK;
5937 fru_ptr = mct_system_info.fru_info_list[SLOT];
5938 for (i = 0; i < pks_topo->max_units[SLOT]; ++i, ++fru_ptr) {
5939 pks_topo->mct_slots[i].fru_status = fru_ptr->fru_status;
5940 pks_topo->mct_slots[i].fru_type = fru_ptr->fru_type;
5941 pks_topo->mct_slots[i].fru_unit = fru_ptr->fru_unit;
5942 pks_topo->mct_slots[i].fru_id = fru_ptr->fru_id;
5943 pks_topo->mct_slots[i].fru_version = fru_ptr->fru_version;
5944 /*
5945 * XXX: need to check healthy regs to set fru_health
5946 */
5947 slotnum = tonga_psl_to_ssl(scsb, i+1);
5948 val = scsb_fru_op(scsb, SLOT, slotnum, SCTRL_BHLTHY_BASE,
5949 SCSB_FRU_OP_GET_BITVAL);
5950 pks_topo->mct_slots[i].fru_health = (val) ?
5951 MCT_HEALTH_OK : MCT_HEALTH_NOK;
5952 }
5953 fru_ptr = mct_system_info.fru_info_list[PDU];
5954 for (i = 0; i < pks_topo->max_units[PDU]; ++i, ++fru_ptr) {
5955 pks_topo->mct_pdu[i].fru_status = fru_ptr->fru_status;
5956 pks_topo->mct_pdu[i].fru_type = fru_ptr->fru_type;
5957 pks_topo->mct_pdu[i].fru_unit = fru_ptr->fru_unit;
5958 pks_topo->mct_pdu[i].fru_id = fru_ptr->fru_id;
5959 pks_topo->mct_pdu[i].fru_version = fru_ptr->fru_version;
5960 pks_topo->mct_pdu[i].fru_health = MCT_HEALTH_NA;
5961 }
5962 fru_ptr = mct_system_info.fru_info_list[PS];
5963 for (i = 0; i < pks_topo->max_units[PS]; ++i, ++fru_ptr) {
5964 pks_topo->mct_ps[i].fru_status = fru_ptr->fru_status;
5965 pks_topo->mct_ps[i].fru_type = fru_ptr->fru_type;
5966 pks_topo->mct_ps[i].fru_unit = fru_ptr->fru_unit;
5967 pks_topo->mct_ps[i].fru_id = fru_ptr->fru_id;
5968 pks_topo->mct_ps[i].fru_version = fru_ptr->fru_version;
5969 pks_topo->mct_ps[i].fru_health = MCT_HEALTH_NA;
5970 }
5971 fru_ptr = mct_system_info.fru_info_list[DISK];
5972 for (i = 0; i < pks_topo->max_units[DISK]; ++i, ++fru_ptr) {
5973 pks_topo->mct_disk[i].fru_status = fru_ptr->fru_status;
5974 pks_topo->mct_disk[i].fru_type = fru_ptr->fru_type;
5975 pks_topo->mct_disk[i].fru_unit = fru_ptr->fru_unit;
5976 pks_topo->mct_disk[i].fru_id = fru_ptr->fru_id;
5977 pks_topo->mct_disk[i].fru_version = fru_ptr->fru_version;
5978 pks_topo->mct_disk[i].fru_health = MCT_HEALTH_NA;
5979 }
5980 fru_ptr = mct_system_info.fru_info_list[FAN];
5981 for (i = 0; i < pks_topo->max_units[FAN]; ++i, ++fru_ptr) {
5982 pks_topo->mct_fan[i].fru_status = fru_ptr->fru_status;
5983 pks_topo->mct_fan[i].fru_type = fru_ptr->fru_type;
5984 pks_topo->mct_fan[i].fru_unit = fru_ptr->fru_unit;
5985 pks_topo->mct_fan[i].fru_id = fru_ptr->fru_id;
5986 pks_topo->mct_fan[i].fru_version = fru_ptr->fru_version;
5987 pks_topo->mct_fan[i].fru_health = MCT_HEALTH_NA;
5988 }
5989 fru_ptr = mct_system_info.fru_info_list[SCB];
5990 for (i = 0; i < pks_topo->max_units[SCB]; ++i, ++fru_ptr) {
5991 pks_topo->mct_scb[i].fru_status = fru_ptr->fru_status;
5992 pks_topo->mct_scb[i].fru_type = fru_ptr->fru_type;
5993 pks_topo->mct_scb[i].fru_unit = fru_ptr->fru_unit;
5994 pks_topo->mct_scb[i].fru_id = fru_ptr->fru_id;
5995 pks_topo->mct_scb[i].fru_version = fru_ptr->fru_version;
5996 /*
5997 * To get the scsb health, if there was no i2c transaction
5998 * until this read, generate an i2c transaction.
5999 */
6000 if (scsb->scsb_kstat_flag == B_FALSE) {
6001 uchar_t data;
6002 (void) scsb_blind_read(scsb, I2C_WR_RD,
6003 (uchar_t)SCTRL_PROM_VERSION, 1, &data, 1);
6004 }
6005 pks_topo->mct_scb[i].fru_health = ((scsb->scsb_err_flag ==
6006 B_TRUE || scsb->scsb_i2c_errcnt > scsb_err_threshold)
6007 ? MCT_HEALTH_NOK : MCT_HEALTH_OK);
6008 #ifdef DEBUG
6009 if (pks_topo->mct_scb[i].fru_health == MCT_HEALTH_NOK)
6010 cmn_err(CE_WARN, "SCSB kstat health:%d", pks_topo->
6011 mct_scb[i].fru_health);
6012 #endif
6013 scsb->scsb_err_flag = B_FALSE; /* clear error flag once read */
6014 scsb->scsb_kstat_flag = B_FALSE; /* false? read from i2c */
6015 }
6016 fru_ptr = mct_system_info.fru_info_list[SSB];
6017 for (i = 0; i < pks_topo->max_units[SSB]; ++i, ++fru_ptr) {
6018 pks_topo->mct_ssb[i].fru_status = fru_ptr->fru_status;
6019 pks_topo->mct_ssb[i].fru_type = fru_ptr->fru_type;
6020 pks_topo->mct_ssb[i].fru_unit = fru_ptr->fru_unit;
6021 pks_topo->mct_ssb[i].fru_id = fru_ptr->fru_id;
6022 pks_topo->mct_ssb[i].fru_version = fru_ptr->fru_version;
6023 pks_topo->mct_ssb[i].fru_health = MCT_HEALTH_NA;
6024 }
6025 fru_ptr = mct_system_info.fru_info_list[ALARM];
6026 for (i = 0; i < pks_topo->max_units[ALARM]; ++i, ++fru_ptr) {
6027 pks_topo->mct_alarm[i].fru_status = fru_ptr->fru_status;
6028 pks_topo->mct_alarm[i].fru_type = fru_ptr->fru_type;
6029 pks_topo->mct_alarm[i].fru_unit = fru_ptr->fru_unit;
6030 pks_topo->mct_alarm[i].fru_id = fru_ptr->fru_id;
6031 pks_topo->mct_alarm[i].fru_version = fru_ptr->fru_version;
6032 pks_topo->mct_alarm[i].fru_health = MCT_HEALTH_NA;
6033 }
6034 fru_ptr = mct_system_info.fru_info_list[CFTM];
6035 for (i = 0; i < pks_topo->max_units[CFTM]; ++i, ++fru_ptr) {
6036 pks_topo->mct_cftm[i].fru_status = fru_ptr->fru_status;
6037 pks_topo->mct_cftm[i].fru_type = fru_ptr->fru_type;
6038 pks_topo->mct_cftm[i].fru_unit = fru_ptr->fru_unit;
6039 pks_topo->mct_cftm[i].fru_id = fru_ptr->fru_id;
6040 pks_topo->mct_cftm[i].fru_version = fru_ptr->fru_version;
6041 pks_topo->mct_cftm[i].fru_health = MCT_HEALTH_NA;
6042 }
6043 fru_ptr = mct_system_info.fru_info_list[CRTM];
6044 for (i = 0; i < pks_topo->max_units[CRTM]; ++i, ++fru_ptr) {
6045 pks_topo->mct_crtm[i].fru_status = fru_ptr->fru_status;
6046 pks_topo->mct_crtm[i].fru_type = fru_ptr->fru_type;
6047 pks_topo->mct_crtm[i].fru_unit = fru_ptr->fru_unit;
6048 pks_topo->mct_crtm[i].fru_id = fru_ptr->fru_id;
6049 pks_topo->mct_crtm[i].fru_version = fru_ptr->fru_version;
6050 pks_topo->mct_crtm[i].fru_health = MCT_HEALTH_NA;
6051 }
6052 fru_ptr = mct_system_info.fru_info_list[PRTM];
6053 for (i = 0; i < pks_topo->max_units[PRTM]; ++i, ++fru_ptr) {
6054 pks_topo->mct_prtm[i].fru_status = fru_ptr->fru_status;
6055 pks_topo->mct_prtm[i].fru_type = fru_ptr->fru_type;
6056 pks_topo->mct_prtm[i].fru_unit = fru_ptr->fru_unit;
6057 pks_topo->mct_prtm[i].fru_id = fru_ptr->fru_id;
6058 pks_topo->mct_prtm[i].fru_version = fru_ptr->fru_version;
6059 pks_topo->mct_prtm[i].fru_health = MCT_HEALTH_NA;
6060 }
6061 mutex_enter(&scsb->scsb_mutex);
6062 scsb->scsb_state &= ~SCSB_KS_UPDATE;
6063 cv_signal(&scsb->scsb_cv);
6064 mutex_exit(&scsb->scsb_mutex);
6065 return (error);
6066 }
6067
6068 static void
6069 scsb_free_kstats(scsb_state_t *scsb)
6070 {
6071 if (!(scsb->scsb_state & SCSB_KSTATS))
6072 return;
6073 /*
6074 * free the allocated kstat data
6075 */
6076 if (scsb->ks_evcreg != NULL) {
6077 kstat_delete(scsb->ks_evcreg);
6078 }
6079 if (scsb->ks_topology != NULL) {
6080 kstat_delete(scsb->ks_topology);
6081 }
6082 if (scsb->ks_state != NULL) {
6083 kstat_delete(scsb->ks_state);
6084 }
6085 if (scsb->ks_leddata != NULL) {
6086 kstat_delete(scsb->ks_leddata);
6087 }
6088 scsb->ks_leddata = NULL;
6089 scsb->ks_state = NULL;
6090 scsb->ks_topology = NULL;
6091 scsb->ks_evcreg = NULL;
6092 scsb->scsb_state &= ~SCSB_KSTATS;
6093 }
6094
6095
6096 /*
6097 * --------------------------------------
6098 * Miscellaneous scsb internal functions.
6099 * --------------------------------------
6100 *
6101 * allocate I2C transfer structure
6102 */
6103 static i2c_transfer_t *
6104 scsb_alloc_i2ctx(i2c_client_hdl_t phandle, uint_t sleep)
6105 {
6106 i2c_transfer_t *tp;
6107
6108 if (i2c_transfer_alloc(phandle, &tp, SCSB_DATA_REGISTERS + 2,
6109 SCSB_DATA_REGISTERS + 2, sleep) == I2C_FAILURE) {
6110 return (NULL);
6111 }
6112 return (tp);
6113 }
6114
6115 /*
6116 * free I2C transfer structure
6117 */
6118 static void
6119 scsb_free_i2ctx(i2c_client_hdl_t phandle, i2c_transfer_t *tp)
6120 {
6121 i2c_transfer_free(phandle, tp);
6122 }
6123
6124 static void
6125 update_fru_info(scsb_state_t *scsb, fru_info_t *fru_ptr)
6126 {
6127 int index;
6128 uchar_t reg, bit;
6129 fru_info_t *acslot_ptr = NULL;
6130 fru_id_t acslot_id = 0;
6131 if (scsb_debug & 0x00100001)
6132 cmn_err(CE_NOTE, "update_fru_info(scsb,0x%p)", (void *)fru_ptr);
6133 if (fru_ptr == (fru_info_t *)NULL ||
6134 fru_ptr->i2c_info == (fru_i2c_info_t *)NULL)
6135 return;
6136 /*
6137 * If this is an Alarm Card update, then we also need to get
6138 * Alarm Card Slot fru_ptr to update it's fru_type, and maybe fru_id
6139 */
6140 if (fru_ptr->fru_id == fru_id_table[FRU_INDEX(SCTRL_EVENT_ALARM)]) {
6141 /*
6142 * SCTRL_EVENT_SLOT1 == 0x01 so
6143 * fru_id_table[] index for Slot 1 == 0
6144 */
6145 acslot_id = fru_id_table[(scsb->ac_slotnum - 1)];
6146 acslot_ptr = find_fru_info(acslot_id);
6147 }
6148 reg = fru_ptr->i2c_info->syscfg_reg;
6149 bit = fru_ptr->i2c_info->syscfg_bit;
6150 if (reg == 0 && fru_ptr->fru_type == SCB) {
6151 if (scsb->scsb_state & SCSB_SCB_PRESENT)
6152 fru_ptr->fru_status = FRU_PRESENT;
6153 else
6154 fru_ptr->fru_status = FRU_NOT_PRESENT;
6155 } else if (reg) {
6156 index = SCSB_REG_INDEX(reg);
6157 if (scsb->scsb_data_reg[index] & (1 << bit)) {
6158 fru_ptr->fru_status = FRU_PRESENT;
6159 /*
6160 * XXX: need to add version register, and maybe a
6161 * method, to the fru_ptr->i2c_info structure.
6162 *
6163 * fru_ptr->fru_version = (fru_version_t)0;
6164 */
6165 /*
6166 * Because scsb_intr() sometimes gets the AC present
6167 * INT before the ACSLOT present INT,
6168 * do not check the ACSLOT fru_status
6169 *
6170 * if (acslot_ptr != NULL && acslot_ptr->fru_status ==
6171 * FRU_PRESENT)
6172 */
6173 if (acslot_ptr != NULL)
6174 acslot_ptr->fru_type = (scsb_utype_t)OC_AC;
6175 } else {
6176 fru_ptr->fru_status = FRU_NOT_PRESENT;
6177 /*
6178 * fru_ptr->fru_version = (fru_version_t)0;
6179 */
6180 if (acslot_ptr != NULL) {
6181 /* AC just removed, but AC Slot is occupied? */
6182 if (acslot_ptr->fru_status == FRU_PRESENT)
6183 /* for now it's unknown */
6184 acslot_ptr->fru_type =
6185 (scsb_utype_t)OC_UNKN;
6186 else
6187 acslot_ptr->fru_type =
6188 (scsb_utype_t)OC_UNKN;
6189 }
6190 }
6191 }
6192 if (scsb_debug & 0x00100000)
6193 cmn_err(CE_NOTE,
6194 "update_fru_info: type %d unit %d is %spresent",
6195 fru_ptr->fru_type, fru_ptr->fru_unit,
6196 fru_ptr->fru_status == FRU_PRESENT
6197 ? "" : "not ");
6198 }
6199
6200 /*
6201 * Convert EVENT code to FRU index
6202 * by finding the highest bit number in 32 bit word
6203 */
6204 static int
6205 event_to_index(uint32_t evcode)
6206 {
6207 int i = 0;
6208 if (evcode == 0)
6209 return (MCT_MAX_FRUS - 1);
6210 for (; (evcode >>= 1); i++)
6211 ;
6212 return (i);
6213 }
6214
6215 #ifdef DEBUG
6216 void
6217 scsb_debug_prnt(char *fmt, uintptr_t a1, uintptr_t a2, uintptr_t a3,
6218 uintptr_t a4, uintptr_t a5)
6219 {
6220 if (scsb_debug & 0x8000 ||
6221 (*fmt == 'X' && scsb_debug & 0x00010000)) {
6222 if (*fmt == 'X')
6223 ++fmt;
6224 prom_printf("scsb: ");
6225 prom_printf(fmt, a1, a2, a3, a4, a5);
6226 prom_printf("\n");
6227 }
6228 }
6229 #endif
6230
6231 /*
6232 * event code functions to deliver event codes
6233 * and to manage:
6234 * the event code fifo
6235 * the process handle table for registered processes interested in
6236 * event codes
6237 */
6238 /*
6239 * Send signal to processes registered for event code delivery
6240 */
6241 static void
6242 signal_evc_procs(scsb_state_t *scsb)
6243 {
6244 int i = 0, c = 0;
6245 if (evc_proc_count == 0)
6246 return;
6247 for (; i < EVC_PROCS_MAX; ++i) {
6248 if (evc_procs[i] != NULL) {
6249 if (proc_signal(evc_procs[i], SIGPOLL)) {
6250 if (scsb_debug & 0x02000002)
6251 cmn_err(CE_WARN,
6252 "scsb:signal_evc_procs: "
6253 "signal to %d failed",
6254 ((struct pid *)
6255 evc_procs[i])->pid_id);
6256 (void) del_event_proc(scsb,
6257 ((struct pid *)evc_procs[i])->pid_id);
6258 }
6259 if (++c >= evc_proc_count) {
6260 if (scsb_debug & 0x02000000) {
6261 cmn_err(CE_NOTE,
6262 "signal_evc_procs: signaled "
6263 "%d/%d processes", c,
6264 evc_proc_count);
6265 }
6266 break;
6267 }
6268 }
6269 }
6270 }
6271
6272 /*
6273 * bump FIFO ptr, taking care of wrap around
6274 */
6275 static uint32_t *
6276 inc_fifo_ptr(uint32_t *ptr)
6277 {
6278 if (++ptr >= evc_fifo + EVC_FIFO_SIZE)
6279 ptr = evc_fifo;
6280 return (ptr);
6281 }
6282
6283 /* ARGSUSED */
6284 static void
6285 reset_evc_fifo(scsb_state_t *scsb)
6286 {
6287 evc_wptr = evc_fifo;
6288 evc_rptr = evc_fifo;
6289 evc_fifo_count = 0;
6290 }
6291
6292 /*
6293 * Called from scsb_intr() when a new event occurs, to put new code in FIFO,
6294 * and signal any interested processes in evc_procs[].
6295 * Always succeeds.
6296 */
6297 static void
6298 add_event_code(scsb_state_t *scsb, uint32_t event_code)
6299 {
6300 if (event_proc_count(scsb) == 0) {
6301 return;
6302 }
6303 *evc_wptr = event_code;
6304 evc_wptr = inc_fifo_ptr(evc_wptr);
6305 if (++evc_fifo_count > EVC_FIFO_SIZE) {
6306 --evc_fifo_count; /* lose the oldest event */
6307 evc_rptr = inc_fifo_ptr(evc_rptr);
6308 }
6309 if (scsb_debug & 0x01000000) {
6310 cmn_err(CE_NOTE, "add_event_code: 0x%x, FIFO size = %d",
6311 event_code, evc_fifo_count);
6312 }
6313 signal_evc_procs(scsb);
6314 }
6315
6316 /*
6317 * called from check_event_procs() when the last registered process
6318 * retrieved the oldest event
6319 */
6320 static uint32_t
6321 del_event_code()
6322 {
6323 uint32_t evc = 0;
6324 if (!evc_fifo_count)
6325 return (scsb_event_code);
6326 evc = *evc_rptr;
6327 evc_rptr = inc_fifo_ptr(evc_rptr);
6328 --evc_fifo_count;
6329 if (scsb_debug & 0x01000000) {
6330 cmn_err(CE_NOTE, "del_event_code: 0x%x, FIFO size = %d",
6331 evc, evc_fifo_count);
6332 }
6333 return (evc);
6334 }
6335
6336 /*
6337 * called from check_event_procs() to retrieve the current event code
6338 */
6339 static uint32_t
6340 get_event_code()
6341 {
6342 if (!evc_fifo_count)
6343 return (0);
6344 return (*evc_rptr);
6345 }
6346
6347 /*
6348 * called from an application interface (ie: an ioctl command)
6349 * to register a process id interested in SCB events.
6350 * NOTE: proc_ref() must be called from USER context, so since this is a
6351 * streams driver, a kstat interface is used for process registration.
6352 * return:
6353 * 0 = event_proc was added
6354 * 1 = out of space
6355 */
6356 /* ARGSUSED */
6357 static int
6358 add_event_proc(scsb_state_t *scsb, pid_t pid)
6359 {
6360 int i = 0;
6361 void *curr_proc;
6362 pid_t curr_pid;
6363 if (evc_proc_count >= EVC_PROCS_MAX)
6364 return (1);
6365 curr_proc = proc_ref();
6366 curr_pid = (pid_t)(((struct pid *)curr_proc)->pid_id);
6367 if (curr_pid != pid) {
6368 if (scsb_debug & 0x02000000) {
6369 cmn_err(CE_WARN,
6370 "add_event_proc: current %d != requestor %d",
6371 curr_pid, pid);
6372 } else {
6373 proc_unref(curr_proc);
6374 return (1);
6375 }
6376 }
6377 for (; i < EVC_PROCS_MAX; ++i) {
6378 if (evc_procs[i] == NULL) {
6379 evc_procs[i] = curr_proc;
6380 evc_proc_count++;
6381 if (scsb_debug & 0x02000000) {
6382 cmn_err(CE_NOTE,
6383 "add_event_proc: %d; evc_proc_count=%d",
6384 pid, evc_proc_count);
6385 }
6386 return (0);
6387 }
6388 }
6389 proc_unref(curr_proc);
6390 return (1);
6391 }
6392
6393 /*
6394 * called from an application interface (ie: an ioctl command)
6395 * to unregister a process id interested in SCB events.
6396 * return:
6397 * 0 = event_proc was deleted
6398 * 1 = event_proc was not found, or table was empty
6399 */
6400 /* ARGSUSED */
6401 static int
6402 del_event_proc(scsb_state_t *scsb, pid_t pid)
6403 {
6404 int i = 0;
6405 int cnt = 0;
6406 void *this_proc;
6407 if (evc_proc_count == 0)
6408 return (1);
6409 for (; i < EVC_PROCS_MAX; ++i) {
6410 if (evc_procs[i] == NULL)
6411 continue;
6412 this_proc = evc_procs[i];
6413 if (pid == ((struct pid *)this_proc)->pid_id) {
6414 evc_procs[i] = NULL;
6415 if (--evc_proc_count == 0) {
6416 /*
6417 * reset evc fifo cound and pointers
6418 */
6419 reset_evc_fifo(scsb);
6420 }
6421 if (scsb_debug & 0x02000000) {
6422 cmn_err(CE_NOTE,
6423 "del_event_proc: %d; evc_proc_count=%d",
6424 pid, evc_proc_count);
6425 }
6426 proc_unref(this_proc);
6427 return (0);
6428 }
6429 if (++cnt >= evc_proc_count)
6430 break;
6431 }
6432 return (1);
6433 }
6434
6435 /*
6436 * Can be called from an application interface
6437 * to rewind the pointers and counters, and zero the table
6438 * return:
6439 */
6440 /* ARGSUSED */
6441 static void
6442 rew_event_proc(scsb_state_t *scsb)
6443 {
6444 int i = 0;
6445 if (scsb_debug & 0x02000001) {
6446 cmn_err(CE_NOTE, "rew_event_proc: evc_proc_count=%d",
6447 evc_proc_count);
6448 }
6449 for (; i < EVC_PROCS_MAX; ++i) {
6450 if (evc_procs[i] != NULL) {
6451 proc_unref(evc_procs[i]);
6452 evc_procs[i] = NULL;
6453 }
6454 }
6455 evc_proc_count = 0;
6456 }
6457
6458 /* ARGSUSED */
6459 static int
6460 event_proc_count(scsb_state_t *scsb)
6461 {
6462 return (evc_proc_count);
6463 }
6464
6465 /*
6466 * return:
6467 * 1 = pid was found
6468 * 0 = pid was not found, or table was empty
6469 */
6470 static int
6471 find_evc_proc(pid_t pid)
6472 {
6473 int i = 0;
6474 int cnt = 0;
6475 if (evc_proc_count == 0)
6476 return (0);
6477 for (; i < EVC_PROCS_MAX; ++i) {
6478 if (evc_procs[i] == NULL)
6479 continue;
6480 if (pid == ((struct pid *)evc_procs[i])->pid_id)
6481 return (1);
6482 if (++cnt >= evc_proc_count)
6483 break;
6484 }
6485 return (0);
6486 }
6487
6488 /*
6489 * called from update_ks_state() to compare evc_proc_count with
6490 * evc_requests, also mainted by this same function
6491 * This function could check the current process id, since this will be a user
6492 * context call, and only bump evc_requests if the calling process is
6493 * registered for event code delivery.
6494 * return:
6495 * EVC_NO_EVENT_CODE : no event_code on fifo
6496 * EVC_NO_CURR_PROC : current process not in table,
6497 * but have an event_code
6498 * EVC_NEW_EVENT_CODE : return_evc is new ks_state->event_code
6499 * EVC_OR_EVENT_CODE : OR return_evc with ks_state->event_code
6500 * EVC_FAILURE : unrecoverable error condition.
6501 */
6502 static int
6503 check_event_procs(uint32_t *return_evc)
6504 {
6505 void *curr_proc;
6506 pid_t curr_pid = 0;
6507 int return_val = 0;
6508 static int evc_requests = 0;
6509 /*
6510 * get current process handle, and check the event_procs table
6511 */
6512 if (evc_proc_count == 0) {
6513 *return_evc = del_event_code();
6514 return_val = EVC_NO_CURR_PROC;
6515 } else {
6516 curr_proc = proc_ref();
6517 curr_pid = ((struct pid *)curr_proc)->pid_id;
6518 proc_unref(curr_proc);
6519 if (!find_evc_proc(curr_pid)) {
6520 *return_evc = get_event_code();
6521 return_val = EVC_NO_CURR_PROC;
6522 } else if (++evc_requests >= evc_proc_count) {
6523 evc_requests = 0;
6524 *return_evc = del_event_code();
6525 return_val = EVC_NEW_EVENT_CODE;
6526 } else {
6527 *return_evc = get_event_code();
6528 }
6529 if (!return_val)
6530 return_val = EVC_OR_EVENT_CODE;
6531 }
6532 if (scsb_debug & 0x02000000) {
6533 cmn_err(CE_NOTE, "check_event_procs: pid=%d, evc=0x%x, "
6534 "requests=%d, returning 0x%x", curr_pid,
6535 *return_evc, evc_requests, return_val);
6536 }
6537 return (return_val);
6538 }
6539
6540 static int
6541 scsb_queue_put(queue_t *rq, int count, uint32_t *data, char *caller)
6542 {
6543 mblk_t *mp;
6544 if (scsb_debug & 0x4001) {
6545 cmn_err(CE_NOTE, "scsb_queue_put(0x%p, %d, 0x%x, %s)",
6546 (void *)rq, count, *data, caller);
6547 }
6548 mp = allocb(sizeof (uint32_t) * count, BPRI_HI);
6549 if (mp == NULL) {
6550 cmn_err(CE_WARN, "%s: allocb failed",
6551 caller);
6552 return (B_FALSE);
6553 }
6554 while (count--) {
6555 *((uint32_t *)mp->b_wptr) = *data;
6556 mp->b_wptr += sizeof (*data);
6557 ++data;
6558 }
6559 putnext(rq, mp);
6560 return (B_TRUE);
6561 }
6562
6563 /* CLONE */
6564 static int
6565 scsb_queue_ops(scsb_state_t *scsb,
6566 int op,
6567 int oparg,
6568 void *opdata,
6569 char *caller)
6570 {
6571 clone_dev_t *clptr;
6572 int clone, find_open, find_available, retval = QOP_FAILED;
6573
6574 switch (op) {
6575 case QPUT_INT32:
6576 if (scsb->scsb_opens && scsb->scsb_rq != NULL &&
6577 scsb_queue_put(scsb->scsb_rq, oparg,
6578 (uint32_t *)opdata, caller) == B_FALSE) {
6579 return (QOP_FAILED);
6580 }
6581 /*FALLTHROUGH*/ /* to look for opened clones */
6582 case QPROCSOFF:
6583 retval = QOP_OK;
6584 /*FALLTHROUGH*/
6585 case QFIRST_OPEN:
6586 case QFIND_QUEUE:
6587 find_open = 1;
6588 find_available = 0;
6589 break;
6590 case QFIRST_AVAILABLE:
6591 find_available = 1;
6592 find_open = 0;
6593 break;
6594 }
6595 for (clone = SCSB_CLONES_FIRST; clone < SCSB_CLONES_MAX; clone++) {
6596 clptr = &scsb->clone_devs[clone];
6597 if (find_open && clptr->cl_flags & SCSB_OPEN) {
6598 if (clptr->cl_rq == NULL) {
6599 cmn_err(CE_WARN, "%s: Clone %d has no queue",
6600 caller, clptr->cl_minor);
6601 return (QOP_FAILED);
6602 }
6603 switch (op) {
6604 case QPROCSOFF:
6605 qprocsoff(clptr->cl_rq);
6606 break;
6607 case QPUT_INT32:
6608 if (scsb_queue_put(clptr->cl_rq, oparg,
6609 (uint32_t *)opdata, caller)
6610 == B_FALSE) {
6611 retval = QOP_FAILED;
6612 }
6613 break;
6614 case QFIRST_OPEN:
6615 return (clone);
6616 case QFIND_QUEUE:
6617 if (clptr->cl_rq == (queue_t *)opdata) {
6618 return (clone);
6619 }
6620 break;
6621 }
6622 } else if (find_available && clptr->cl_flags == 0) {
6623 switch (op) {
6624 case QFIRST_AVAILABLE:
6625 return (clone);
6626 }
6627 }
6628 }
6629 return (retval);
6630 }
6631
6632 /*
6633 * Find out if a bit is set for the FRU type and unit number in the register
6634 * set defined by the register base table index, base.
6635 * Returns TRUE if bit is set, or FALSE.
6636 */
6637 static int
6638 scsb_fru_op(scsb_state_t *scsb, scsb_utype_t fru_type, int unit, int base,
6639 int op)
6640 {
6641 int rc;
6642 uchar_t reg;
6643 int tmp, idx, code, offset;
6644
6645 #if 0
6646 reg = SCSB_REG_ADDR(i);
6647 ac_mask = 1 << FRU_OFFSET(SCTRL_EVENT_ALARM, SCTRL_RESET_BASE);
6648 ac_val = scsb->scsb_data_reg[index+1] & ac_mask;
6649 #endif
6650 /* get the event code based on which we get the reg and bit offsets */
6651 code = FRU_UNIT_TO_EVCODE(fru_type, unit);
6652 /* get the bit offset in the 8bit register corresponding to the event */
6653 offset = FRU_OFFSET(code, base);
6654 /* register offset from the base register, based on the event code */
6655 if ((fru_type == ALARM) && (base == SCTRL_RESET_BASE))
6656 tmp = ALARM_RESET_REG_INDEX(code, base);
6657 else
6658 tmp = FRU_REG_INDEX(code, base);
6659 /* get the global offset of the register in the parent address space */
6660 reg = SCSB_REG_ADDR(tmp);
6661 /* get the global index of the register in this SCSB's address space */
6662 idx = SCSB_REG_INDEX(reg);
6663 DEBUG4("scsb_fru_op(start): code=%x, offset=%x, tmp=%x, reg=%x\n",
6664 code, offset, tmp, reg);
6665 switch (op) {
6666 case SCSB_FRU_OP_GET_REG:
6667 rc = reg;
6668 break;
6669 case SCSB_FRU_OP_GET_BITVAL:
6670 rc = (scsb->scsb_data_reg[idx] & (1 << offset))
6671 >> offset;
6672 break;
6673 case SCSB_FRU_OP_GET_REGDATA:
6674 rc = scsb->scsb_data_reg[idx];
6675 break;
6676 case SCSB_FRU_OP_SET_REGBIT:
6677 rc = (1 << offset) & 0xff;
6678 break;
6679 default:
6680 break;
6681 }
6682 DEBUG4("scsb_fru_op: unit=%x, base=%x, op=%d, rc=%x\n", unit, base,
6683 op, rc);
6684 return (rc);
6685 }
6686
6687 /*
6688 * All HSC related functions can fail, but an attempt is made to atleast
6689 * return the right shadow state on get-state function when SCB is removed.
6690 */
6691 int
6692 scsb_get_slot_state(scsb_state_t *scsb, int pslotnum, int *rstate)
6693 {
6694 int slotnum, val = 0, rc;
6695
6696 /*
6697 * When SCB is removed, we could be called with the lock held.
6698 * We call check_config_status anyway since it is a read-only operation
6699 * and HSC could be invoking this function at interrupt context.
6700 * If scsb is already in the doing interrupt postprocess, wait..
6701 */
6702
6703 rc = scsb_check_config_status(scsb);
6704
6705 /* check if error is because SCB is removed */
6706 if ((rc != EAGAIN) && (rc != DDI_SUCCESS))
6707 return (DDI_FAILURE);
6708 slotnum = tonga_psl_to_ssl(scsb, pslotnum);
6709 val = scsb_fru_op(scsb, SLOT, slotnum, SCTRL_SYSCFG_BASE,
6710 SCSB_FRU_OP_GET_BITVAL);
6711 if (! val) {
6712 *rstate = HPC_SLOT_EMPTY;
6713 return (0);
6714 }
6715 /*
6716 * now, lets determine if it is connected or disconnected.
6717 * If reset is asserted, then the slot is disconnected.
6718 */
6719 rc = scsb_reset_slot(scsb, pslotnum, SCSB_GET_SLOT_RESET_STATUS);
6720 /* check if error is because SCB is removed */
6721 if ((rc != EAGAIN) && (rc != DDI_SUCCESS))
6722 return (DDI_FAILURE);
6723 val = scsb_fru_op(scsb, SLOT, slotnum, SCTRL_RESET_BASE,
6724 SCSB_FRU_OP_GET_BITVAL);
6725 if (val)
6726 *rstate = HPC_SLOT_DISCONNECTED;
6727 else {
6728 if (scsb_fru_op(scsb, SLOT, slotnum, SCTRL_BHLTHY_BASE,
6729 SCSB_FRU_OP_GET_BITVAL)) {
6730 *rstate = HPC_SLOT_CONNECTED;
6731 } else {
6732 cmn_err(CE_WARN, "%s#%d: Reset Not Asserted on "
6733 "Healthy# Failed slot %d!",
6734 ddi_driver_name(scsb->scsb_dev),
6735 ddi_get_instance(scsb->scsb_dev), slotnum);
6736 *rstate = HPC_SLOT_DISCONNECTED;
6737 }
6738 }
6739 return (0);
6740 }
6741
6742 int
6743 scsb_reset_slot(scsb_state_t *scsb, int pslotnum, int reset_flag)
6744 {
6745 int slotnum, error, val, alarm_card = 0;
6746 i2c_transfer_t *i2cxferp;
6747 uchar_t reg;
6748 int index, condition_exists = 0, ac_val;
6749
6750 if (scsb_debug & 0x8001)
6751 cmn_err(CE_NOTE, "scsb_reset_slot(%d), flag %x", pslotnum,
6752 reset_flag);
6753 if (scsb->scsb_state & SCSB_FROZEN)
6754 return (EAGAIN);
6755 if ((i2cxferp = scsb_alloc_i2ctx(scsb->scsb_phandle,
6756 I2C_NOSLEEP)) == NULL) {
6757 return (ENOMEM);
6758 }
6759 slotnum = tonga_psl_to_ssl(scsb, pslotnum);
6760
6761 if (scsb_is_alarm_card_slot(scsb, pslotnum) == B_TRUE) {
6762 DEBUG0("alarm card reset/unreset op:\n");
6763 alarm_card = 1;
6764 }
6765 reg = SCSB_REG_ADDR(SCTRL_RESET_BASE);
6766 index = SCSB_REG_INDEX(reg);
6767
6768 mutex_enter(&scsb->scsb_mutex);
6769 i2cxferp->i2c_flags = I2C_WR_RD;
6770 i2cxferp->i2c_rlen = SCTRL_RESET_NUMREGS;
6771 i2cxferp->i2c_wbuf[0] = reg;
6772 i2cxferp->i2c_wlen = 1;
6773 scsb->scsb_kstat_flag = B_TRUE; /* we did an i2c transaction */
6774 if ((error = nct_i2c_transfer(scsb->scsb_phandle, i2cxferp)) == 0) {
6775 scsb->scsb_i2c_errcnt = 0;
6776 /*
6777 * XXX: following statements assume 2 reset registers,
6778 * which is the case for our current SCB revisions.
6779 */
6780 scsb->scsb_data_reg[index] = i2cxferp->i2c_rbuf[0];
6781 scsb->scsb_data_reg[index+1] = i2cxferp->i2c_rbuf[1];
6782 } else {
6783 scsb->scsb_i2c_errcnt++;
6784 if (scsb->scsb_i2c_errcnt > scsb_err_threshold)
6785 scsb->scsb_err_flag = B_TRUE; /* latch until kstat */
6786 if (!(scsb->scsb_state & SCSB_SSB_PRESENT)) {
6787 if (scsb->scsb_i2c_errcnt >= scsb_freeze_count)
6788 mutex_exit(&scsb->scsb_mutex);
6789 scsb_freeze(scsb);
6790 mutex_enter(&scsb->scsb_mutex);
6791 }
6792 cmn_err(CE_WARN, "%s#%d: scsb_reset_slot: error"
6793 " reading Reset regs\n",
6794 ddi_driver_name(scsb->scsb_dev),
6795 ddi_get_instance(scsb->scsb_dev));
6796 error = DDI_FAILURE;
6797 }
6798
6799 DEBUG2("pre-reset regs = %x,%x\n", scsb->scsb_data_reg[index],
6800 scsb->scsb_data_reg[index+1]);
6801 if ((reset_flag == SCSB_GET_SLOT_RESET_STATUS) || (error)) {
6802 mutex_exit(&scsb->scsb_mutex);
6803 scsb_free_i2ctx(scsb->scsb_phandle, i2cxferp);
6804 return (error);
6805 }
6806
6807 val = scsb_fru_op(scsb, SLOT, slotnum, SCTRL_RESET_BASE,
6808 SCSB_FRU_OP_GET_BITVAL);
6809 if (alarm_card) {
6810 ac_val = scsb_fru_op(scsb, ALARM, 1, SCTRL_RESET_BASE,
6811 SCSB_FRU_OP_GET_BITVAL);
6812 }
6813 if (val && (reset_flag == SCSB_RESET_SLOT)) {
6814 if (alarm_card) {
6815 if (ac_val) {
6816 condition_exists = 1;
6817 DEBUG0("Alarm_RST# already active.\n");
6818 }
6819 #ifndef lint
6820 else
6821 DEBUG1("Alarm_RST# not active! "
6822 "Slot%d_RST# active!\n", pslotnum);
6823 #endif
6824 } else {
6825 condition_exists = 1;
6826 DEBUG1("Slot%d_RST# already active!\n", pslotnum);
6827 }
6828 }
6829 else
6830 if ((val == 0) && (reset_flag == SCSB_UNRESET_SLOT)) {
6831 if (alarm_card) {
6832 if (!ac_val) {
6833 DEBUG0("Alarm_RST# not active.\n");
6834 condition_exists = 1;
6835 }
6836 #ifndef lint
6837 else
6838 DEBUG1("Alarm_RST# active"
6839 " Slot%d_RST# not active!\n",
6840 pslotnum);
6841 #endif
6842 } else {
6843 condition_exists = 1;
6844 DEBUG1("Slot%d_RST# already not active!\n",
6845 pslotnum);
6846 }
6847 }
6848
6849 if (! condition_exists) {
6850 i2cxferp->i2c_flags = I2C_WR;
6851 i2cxferp->i2c_wlen = 2;
6852 i2cxferp->i2c_wbuf[0] = scsb_fru_op(scsb, SLOT, slotnum,
6853 SCTRL_RESET_BASE, SCSB_FRU_OP_GET_REG);
6854 if (reset_flag == SCSB_RESET_SLOT) {
6855 i2cxferp->i2c_wbuf[1] =
6856 scsb_fru_op(scsb, SLOT, slotnum,
6857 SCTRL_RESET_BASE,
6858 SCSB_FRU_OP_GET_REGDATA) |
6859 scsb_fru_op(scsb, SLOT, slotnum,
6860 SCTRL_RESET_BASE,
6861 SCSB_FRU_OP_SET_REGBIT);
6862 #ifdef DEBUG /* dont reset Alarm Card line unless in debug mode */
6863 if (alarm_card)
6864 i2cxferp->i2c_wbuf[1] |=
6865 scsb_fru_op(scsb, ALARM, 1,
6866 SCTRL_RESET_BASE,
6867 SCSB_FRU_OP_SET_REGBIT);
6868 #endif
6869 } else {
6870 i2cxferp->i2c_wbuf[1] =
6871 scsb_fru_op(scsb, SLOT, slotnum,
6872 SCTRL_RESET_BASE,
6873 SCSB_FRU_OP_GET_REGDATA) &
6874 ~(scsb_fru_op(scsb, SLOT, slotnum,
6875 SCTRL_RESET_BASE,
6876 SCSB_FRU_OP_SET_REGBIT));
6877 #ifdef DEBUG /* dont Unreset Alarm Card line unless in debug mode */
6878 if (alarm_card)
6879 i2cxferp->i2c_wbuf[1] &=
6880 scsb_fru_op(scsb, ALARM, 1,
6881 SCTRL_RESET_BASE,
6882 SCSB_FRU_OP_SET_REGBIT);
6883 #endif
6884 }
6885
6886 if (error = nct_i2c_transfer(scsb->scsb_phandle, i2cxferp)) {
6887 scsb->scsb_i2c_errcnt++;
6888 if (scsb->scsb_i2c_errcnt > scsb_err_threshold)
6889 scsb->scsb_err_flag = B_TRUE; /* latch error */
6890 mutex_exit(&scsb->scsb_mutex);
6891 if (!(scsb->scsb_state & SCSB_SSB_PRESENT)) {
6892 if (scsb->scsb_i2c_errcnt >= scsb_freeze_count)
6893 scsb_freeze(scsb);
6894 }
6895 cmn_err(CE_WARN, "%s#%d: reset_slot: error writing to"
6896 " Reset regs (op=%d, data=%x)\n",
6897 ddi_driver_name(scsb->scsb_dev),
6898 ddi_get_instance(scsb->scsb_dev),
6899 reset_flag, i2cxferp->i2c_wbuf[1]);
6900 scsb_free_i2ctx(scsb->scsb_phandle, i2cxferp);
6901 return (DDI_FAILURE);
6902 }
6903
6904 scsb->scsb_i2c_errcnt = 0;
6905 /* now read back and update our scsb structure */
6906 i2cxferp->i2c_flags = I2C_WR_RD;
6907 i2cxferp->i2c_rlen = SCTRL_RESET_NUMREGS;
6908 i2cxferp->i2c_wbuf[0] = reg;
6909 i2cxferp->i2c_wlen = 1;
6910 if ((error = nct_i2c_transfer(scsb->scsb_phandle,
6911 i2cxferp)) == 0) {
6912 scsb->scsb_i2c_errcnt = 0;
6913 scsb->scsb_data_reg[index] = i2cxferp->i2c_rbuf[0];
6914 scsb->scsb_data_reg[index+1] = i2cxferp->i2c_rbuf[1];
6915 } else {
6916 scsb->scsb_i2c_errcnt++;
6917 if (scsb->scsb_i2c_errcnt > scsb_err_threshold)
6918 scsb->scsb_err_flag = B_TRUE; /* latch error */
6919 mutex_exit(&scsb->scsb_mutex);
6920 if (!(scsb->scsb_state & SCSB_SSB_PRESENT)) {
6921 if (scsb->scsb_i2c_errcnt >= scsb_freeze_count)
6922 scsb_freeze(scsb);
6923 }
6924 cmn_err(CE_WARN, "%s#%d: scsb_reset_slot: error"
6925 " reading Reset regs (post reset)\n",
6926 ddi_driver_name(scsb->scsb_dev),
6927 ddi_get_instance(scsb->scsb_dev));
6928 scsb_free_i2ctx(scsb->scsb_phandle, i2cxferp);
6929 return (DDI_FAILURE);
6930 }
6931 /* XXX: P1.5 */
6932 DEBUG2("post-reset regs = %x,%x\n", scsb->scsb_data_reg[index],
6933 scsb->scsb_data_reg[index+1]);
6934 val = scsb_fru_op(scsb, SLOT, slotnum, SCTRL_RESET_BASE,
6935 SCSB_FRU_OP_GET_BITVAL);
6936 #ifdef DEBUG
6937 if (alarm_card)
6938 ac_val = scsb_fru_op(scsb, ALARM, 1, SCTRL_RESET_BASE,
6939 SCSB_FRU_OP_GET_BITVAL);
6940 #endif
6941 if (val && (reset_flag == SCSB_UNRESET_SLOT)) {
6942 cmn_err(CE_WARN, "Cannot UnReset Slot %d (reg=%x)\n",
6943 pslotnum,
6944 scsb_fru_op(scsb, SLOT, slotnum,
6945 SCTRL_RESET_BASE,
6946 SCSB_FRU_OP_GET_REGDATA));
6947 #ifdef DEBUG
6948 if (alarm_card) {
6949 if (ac_val)
6950 cmn_err(CE_WARN, "Cannot Unreset "
6951 "Alarm_RST#.\n");
6952 }
6953 #endif
6954 }
6955 else
6956 if ((val == 0) && (reset_flag == SCSB_RESET_SLOT)) {
6957 cmn_err(CE_WARN, "Cannot Reset Slot %d, "
6958 "reg=%x\n", pslotnum,
6959 scsb_fru_op(scsb, SLOT, slotnum,
6960 SCTRL_RESET_BASE,
6961 SCSB_FRU_OP_GET_REGDATA));
6962 #ifdef DEBUG
6963 if (alarm_card) {
6964 if (!ac_val)
6965 cmn_err(CE_WARN, "Cannot reset "
6966 "Alarm_RST#.\n");
6967 }
6968 #endif
6969 }
6970 }
6971
6972 mutex_exit(&scsb->scsb_mutex);
6973 scsb_free_i2ctx(scsb->scsb_phandle, i2cxferp);
6974
6975 return (error);
6976 }
6977
6978 int
6979 scsb_connect_slot(scsb_state_t *scsb, int pslotnum, int healthy)
6980 {
6981 int slotnum, count = 0, val;
6982 int slot_flag = 0;
6983
6984 /*
6985 * If Power needs to be handled, it should be done here.
6986 * Since there is no power handling for now, lets disable
6987 * reset, wait for healthy to come on and then call it
6988 * connected.
6989 * If HLTHY# does not come on (in how long is the question)
6990 * then we stay disconnected.
6991 */
6992 slotnum = tonga_psl_to_ssl(scsb, pslotnum);
6993
6994 /*
6995 * P1.5 doesnt require polling healthy as we get an
6996 * interrupt. So we could just update our state as disconnected
6997 * and return waiting for the healthy# interrupt. To make it
6998 * more efficient, lets poll for healthy# a short while since we are
6999 * in the interrupt context anyway. If we dont get a healthy# we
7000 * return, and then wait for the interrupt. Probably the warning
7001 * message needs to be removed then. Need a PROM check flag here.
7002 */
7003 while ((healthy == B_FALSE) && (count < scsb_healthy_poll_count)) {
7004 if (scsb_read_bhealthy(scsb) != 0)
7005 return (DDI_FAILURE);
7006 val = scsb_fru_op(scsb, SLOT, slotnum, SCTRL_BHLTHY_BASE,
7007 SCSB_FRU_OP_GET_BITVAL);
7008 if (val) {
7009 healthy = B_TRUE;
7010 break;
7011 }
7012 count++;
7013 drv_usecwait(100); /* cant delay(9f) in intr context */
7014 }
7015
7016 if (healthy == B_FALSE && count == scsb_healthy_poll_count) {
7017 if (scsb_debug & 0x00004000)
7018 cmn_err(CE_WARN, "%s#%d: no HEALTHY# signal on"
7019 " slot %d", ddi_driver_name(scsb->scsb_dev),
7020 ddi_get_instance(scsb->scsb_dev), pslotnum);
7021 }
7022
7023 if ((scsb_is_alarm_card_slot(scsb, pslotnum) == B_TRUE) &&
7024 (scsb->scsb_hsc_state & SCSB_ALARM_CARD_PRES))
7025 slot_flag = ALARM_CARD_ON_SLOT;
7026 return (hsc_slot_occupancy(pslotnum, 1, slot_flag, healthy));
7027 }
7028
7029 int
7030 scsb_disconnect_slot(scsb_state_t *scsb, int occupied, int slotnum)
7031 {
7032 int slot_flag = 0;
7033
7034 /* Reset is must at extraction. Move on even if failure. */
7035 if (scsb_reset_slot(scsb, slotnum, SCSB_RESET_SLOT) != 0) {
7036 /*
7037 * If board is still in slot, which means there is a manual
7038 * disconnection in progress, return failure.
7039 * Otherwise, a board was removed anyway; so we need to
7040 * update the status and move on.
7041 */
7042 if (occupied == B_TRUE)
7043 return (DDI_FAILURE);
7044 }
7045 /*
7046 * the following bug needs to be fixed.
7047 * When this function is called from scsb_intr, scsb_state already
7048 * clears the 'AC card present' bit.
7049 * However, hsc module doesn't depend on slot_flag during removal.
7050 */
7051 if ((scsb_is_alarm_card_slot(scsb, slotnum) == B_TRUE) &&
7052 (scsb->scsb_hsc_state & SCSB_ALARM_CARD_PRES))
7053 slot_flag = ALARM_CARD_ON_SLOT;
7054 return (hsc_slot_occupancy(slotnum, occupied, slot_flag, B_FALSE));
7055 }
7056
7057 static int
7058 scsb_is_alarm_card_slot(scsb_state_t *scsb, int slotnum)
7059 {
7060 return ((scsb->ac_slotnum == slotnum)? B_TRUE:B_FALSE);
7061 }
7062
7063 /*
7064 * Invoked both by the hsc and the scsb module to exchanges necessary
7065 * information regarding the alarm card.
7066 * scsb calls this function to unconfigure the alarm card while the
7067 * hsc calls this function at different times to check busy status,
7068 * and during post hotswap insert operation so that the user process
7069 * if one waiting can configure the alarm card.
7070 */
7071 int
7072 scsb_hsc_ac_op(scsb_state_t *scsb, int pslotnum, int op)
7073 {
7074 int rc = B_FALSE;
7075 uint32_t event_code;
7076
7077 if (!(scsb->scsb_hsc_state & SCSB_HSC_INIT &&
7078 scsb->scsb_hsc_state & SCSB_ALARM_CARD_PRES)) {
7079 cmn_err(CE_WARN,
7080 "scsb: HSC not initialized or AC not present!");
7081 return (rc);
7082 }
7083 switch (op) {
7084 /* hsc -> scsb */
7085 case SCSB_HSC_AC_BUSY:
7086 if (scsb->scsb_hsc_state & SCSB_ALARM_CARD_IN_USE)
7087 rc = B_TRUE;
7088 break;
7089
7090 /* API -> scsb */
7091 /*
7092 * NOTE: this could be called multiple times from envmond if
7093 * the daemon is reinitialized with SIGHUP, or stopped and
7094 * restarted.
7095 */
7096 case SCSB_HSC_AC_SET_BUSY:
7097 DEBUG0("AC SET BUSY\n");
7098 if (scsb_debug & 0x00010000) {
7099 cmn_err(CE_NOTE,
7100 "scsb_hsc_ac_op(SCSB_HSC_AC_SET_BUSY)");
7101 }
7102 scsb->scsb_hsc_state |= SCSB_ALARM_CARD_IN_USE;
7103 rc = B_TRUE;
7104 break;
7105
7106 /* hsc -> scsb */
7107 case SCSB_HSC_AC_CONFIGURED:
7108 DEBUG0("AC configured\n");
7109 if (scsb_debug & 0x00010000) {
7110 cmn_err(CE_NOTE,
7111 "scsb_hsc_ac_op(SCSB_HSC_AC_CONFIGURED)");
7112 }
7113 /*
7114 * wakeup anyone waiting on AC to be configured
7115 * Send the ALARM_CARD_CONFIGURE Event to all scsb
7116 * open streams.
7117 */
7118 event_code = SCTRL_EVENT_ALARM_INSERTION;
7119 (void) scsb_queue_ops(scsb, QPUT_INT32, 1,
7120 &event_code, "scsb_hsc_ac_op");
7121 rc = B_TRUE;
7122 break;
7123
7124 /* hsc -> scsb */
7125 case SCSB_HSC_AC_REMOVAL_ALERT:
7126 DEBUG0("AC removal alert\n");
7127 if (scsb_debug & 0x00010000) {
7128 cmn_err(CE_NOTE,
7129 "scsb_hsc_ac_op(SCSB_HSC_AC_REMOVAL_ALERT)");
7130 }
7131 /*
7132 * Inform (envmond)alarmcard.so that it should save
7133 * the AC configuration, stop the
7134 * heartbeat, and shutdown the RSC link.
7135 */
7136 event_code = SCTRL_EVENT_ALARM_REMOVAL;
7137 (void) scsb_queue_ops(scsb, QPUT_INT32, 1,
7138 &event_code, "scsb_hsc_ac_op");
7139 rc = B_TRUE;
7140 break;
7141
7142 /* API -> scsb -> hsc */
7143 case SCSB_HSC_AC_UNCONFIGURE:
7144 DEBUG0("AC unconfigure\n");
7145 if (scsb_debug & 0x00010000) {
7146 cmn_err(CE_NOTE,
7147 "scsb_hsc_ac_op(SCSB_HSC_AC_UNCONFIG"
7148 "URE), AC NOT BUSY");
7149 }
7150 /*
7151 * send notification back to HSC to
7152 * unconfigure the AC, now that the env monitor
7153 * has given permission to do so.
7154 */
7155 scsb->scsb_hsc_state &= ~SCSB_ALARM_CARD_IN_USE;
7156 hsc_ac_op((int)scsb->scsb_instance, pslotnum,
7157 SCSB_HSC_AC_UNCONFIGURE, NULL);
7158 rc = B_TRUE;
7159 break;
7160 default:
7161 break;
7162 }
7163
7164 return (rc);
7165 }
7166
7167 static void
7168 scsb_healthy_intr(scsb_state_t *scsb, int pslotnum)
7169 {
7170 int val, slotnum;
7171 int healthy = B_FALSE;
7172
7173 DEBUG1("Healthy Intr on slot %d\n", pslotnum);
7174 /*
7175 * The interrupt source register can have the healthy
7176 * bit set for non-existing slot, e.g slot 7 on Tonga.
7177 * It can also be seen on the Tonga CPU slot. So we make
7178 * sure we have a valid slot before proceeding.
7179 */
7180 if (scsb->scsb_state & SCSB_IS_TONGA) {
7181 if (pslotnum > TG_MAX_SLOTS || pslotnum == SC_TG_CPU_SLOT) {
7182 if (scsb_debug & 0x08000000)
7183 cmn_err(CE_NOTE, "Healthy interrupt bit set for"
7184 " slot %d", pslotnum);
7185 return;
7186 }
7187 } else {
7188 if (pslotnum > MC_MAX_SLOTS || pslotnum == SC_MC_CPU_SLOT ||
7189 (scsb->scsb_hsc_state & SCSB_HSC_CTC_PRES &&
7190 pslotnum == SC_MC_CTC_SLOT)) {
7191 if (scsb_debug & 0x08000000)
7192 cmn_err(CE_NOTE, "Healthy interrupt bit set for"
7193 " slot %d", pslotnum);
7194 return;
7195 }
7196 }
7197
7198 /*
7199 * The board healthy registers are already read before entering
7200 * this routine
7201 */
7202 slotnum = tonga_psl_to_ssl(scsb, pslotnum);
7203
7204 /*
7205 * P1.5. Following works since slots 1 through 8 are in the same reg
7206 */
7207 val = scsb_fru_op(scsb, SLOT, slotnum, SCTRL_BHLTHY_BASE,
7208 SCSB_FRU_OP_GET_BITVAL);
7209 if (val)
7210 healthy = B_TRUE;
7211 (void) scsb_hsc_board_healthy(pslotnum, healthy);
7212 }
7213
7214 /*
7215 * This function will try to read from scsb irrespective of whether
7216 * SSB is present or SCB is frozen, to get the health kstat information.
7217 */
7218 static int
7219 scsb_blind_read(scsb_state_t *scsb, int op, uchar_t reg, int len,
7220 uchar_t *rwbuf, int i2c_alloc)
7221 {
7222 i2c_transfer_t *i2cxferp;
7223 int i, rlen, wlen, error = 0;
7224
7225 if (scsb_debug & 0x0800) {
7226 cmn_err(CE_NOTE, "scsb_rdwr_register(scsb,%s,%x,%x,buf):",
7227 (op == I2C_WR) ? "write" : "read", reg, len);
7228 }
7229
7230 if (i2c_alloc) {
7231 i2cxferp = scsb_alloc_i2ctx(scsb->scsb_phandle, I2C_NOSLEEP);
7232 if (i2cxferp == NULL) {
7233 if (scsb_debug & 0x0042)
7234 cmn_err(CE_WARN, "scsb_rdwr_register: "
7235 "i2ctx allocation failure");
7236 return (ENOMEM);
7237 }
7238 } else {
7239 i2cxferp = scsb->scsb_i2ctp;
7240 }
7241 switch (op) {
7242 case I2C_WR:
7243 wlen = len + 1; /* add the address */
7244 rlen = 0;
7245 i2cxferp->i2c_wbuf[0] = reg;
7246 for (i = 0; i < len; ++i) {
7247 i2cxferp->i2c_wbuf[1 + i] = rwbuf[i];
7248 if (scsb_debug & 0x0080)
7249 cmn_err(CE_NOTE,
7250 "scsb_rdwr_register: writing rwbuf[%d]=0x%x",
7251 i, rwbuf[i]);
7252 }
7253 break;
7254 case I2C_WR_RD:
7255 wlen = 1; /* for the address */
7256 rlen = len;
7257 i2cxferp->i2c_wbuf[0] = reg;
7258 break;
7259 default:
7260 if (i2c_alloc)
7261 scsb_free_i2ctx(scsb->scsb_phandle, i2cxferp);
7262 return (EINVAL);
7263 }
7264 /* select the register address */
7265 i2cxferp->i2c_flags = op;
7266 i2cxferp->i2c_rlen = rlen;
7267 i2cxferp->i2c_wlen = wlen;
7268 i2cxferp->i2c_wbuf[0] = reg;
7269 scsb->scsb_kstat_flag = B_TRUE; /* we did a i2c transaction */
7270 if (error = nct_i2c_transfer(scsb->scsb_phandle, i2cxferp)) {
7271 error = EIO;
7272 } else if (rlen) {
7273 /* copy to rwbuf[] */
7274 for (i = 0; i < len; ++i) {
7275 rwbuf[i] = i2cxferp->i2c_rbuf[i];
7276 if (scsb_debug & 0x0080)
7277 cmn_err(CE_NOTE,
7278 "scsb_rdwr_register: read rwbuf[%d]=0x%x",
7279 i, rwbuf[i]);
7280 }
7281 }
7282 if (i2c_alloc)
7283 scsb_free_i2ctx(scsb->scsb_phandle, i2cxferp);
7284 if (error) {
7285 scsb->scsb_i2c_errcnt++;
7286 if (scsb->scsb_i2c_errcnt > scsb_err_threshold)
7287 scsb->scsb_err_flag = B_TRUE; /* latch error */
7288 } else {
7289 scsb->scsb_i2c_errcnt = 0;
7290 }
7291
7292 return (error);
7293 }
7294
7295 /*
7296 * This function will quiesce the PSM_INT line by masking the
7297 * global PSM_INT and writing 1 to SCB_INIT ( for P1.5 and later )
7298 * This effectively translates to writing 0x20 to 0xE1 register.
7299 */
7300 static int
7301 scsb_quiesce_psmint(scsb_state_t *scsb)
7302 {
7303 register int i;
7304 uchar_t reg, wdata = 0;
7305 uchar_t tmp_reg, intr_addr, clr_bits = 0;
7306 int error, iid, intr_idx, offset;
7307
7308 /*
7309 * For P1.5, set the SCB_INIT bit in the System Command register,
7310 * and disable global PSM_INT. Before this we need to read the
7311 * interrupt source register corresponding to INIT_SCB and
7312 * clear if set.
7313 */
7314 if (IS_SCB_P15) {
7315 /*
7316 * Read INTSRC6 and write back 0x20 in case INIT_SCB is set
7317 */
7318 intr_addr = SCSB_REG_ADDR(SCTRL_INTSRC_BASE);
7319 tmp_reg = SCSB_REG_ADDR(SCTRL_INTSRC_SCB_P15);
7320 iid = SCSB_REG_INDEX(intr_addr);
7321 intr_idx = SCSB_REG_INDEX(tmp_reg) - iid;
7322 offset = FRU_OFFSET(SCTRL_EVENT_SCB, SCTRL_INTPTR_BASE);
7323 clr_bits = 1 << offset;
7324
7325 error = scsb_rdwr_register(scsb, I2C_WR_RD, tmp_reg,
7326 1, &scb_intr_regs[intr_idx], 0);
7327 /*
7328 * Now mask the global PSM_INT and write INIT_SCB in case
7329 * this is an INIT_SCB interrupt
7330 */
7331 wdata = 1 << SYS_OFFSET(SCTRL_SYS_SCB_INIT);
7332 i = SYS_REG_INDEX(SCTRL_SYS_SCB_INIT, SCTRL_SYS_CMD_BASE);
7333 reg = SCSB_REG_ADDR(i);
7334 error = scsb_rdwr_register(scsb, I2C_WR, reg, 1,
7335 &wdata, 0);
7336
7337 if (scb_intr_regs[intr_idx] & clr_bits) {
7338 /*
7339 * There is an SCB_INIT interrupt, which we must clear
7340 * first to keep SCB_INIT from keeping PSM_INT asserted.
7341 */
7342 error = scsb_rdwr_register(scsb, I2C_WR, tmp_reg,
7343 1, &clr_bits, 0);
7344 }
7345
7346 if (error) {
7347 cmn_err(CE_WARN, "scsb%d:scsb_quiesce_psmint: "
7348 " I2C TRANSFER Failed", scsb->scsb_instance);
7349 if (scsb_debug & 0x0006) {
7350 cmn_err(CE_NOTE, "scsb_attach: "
7351 " failed to set SCB_INIT");
7352 }
7353 }
7354 scsb->scsb_state &= ~SCSB_PSM_INT_ENABLED;
7355 } else { /* P1.0 or earlier */
7356 /*
7357 * read the interrupt source registers, and then
7358 * write them back.
7359 */
7360 /* read the interrupt register from scsb */
7361 if (error = scsb_rdwr_register(scsb, I2C_WR_RD, intr_addr,
7362 SCTRL_INTR_NUMREGS, scb_intr_regs, 0)) {
7363 cmn_err(CE_WARN, "scsb_intr: "
7364 " Failed read of interrupt registers.");
7365 scsb->scsb_state &= ~SCSB_IN_INTR;
7366 }
7367
7368 /*
7369 * Write to the interrupt source registers to stop scsb
7370 * from interrupting.
7371 */
7372 if (error = scsb_rdwr_register(scsb, I2C_WR, intr_addr,
7373 SCTRL_INTR_NUMREGS, scb_intr_regs, 0)) {
7374 cmn_err(CE_WARN, "scsb_intr: Failed write to interrupt"
7375 " registers.");
7376 scsb->scsb_state &= ~SCSB_IN_INTR;
7377 }
7378
7379 }
7380
7381 if (error)
7382 return (DDI_FAILURE);
7383 else
7384 return (DDI_SUCCESS);
7385 }
7386
7387 /*
7388 * Enables or disables the global PSM_INT interrupt for P1.5, depending
7389 * on the flag, flag = 0 => disable, else enable.
7390 */
7391 static int
7392 scsb_toggle_psmint(scsb_state_t *scsb, int enable)
7393 {
7394 int i;
7395 uchar_t reg, on = 0, rmask = 0x0, off = 0;
7396
7397 if (enable == B_TRUE) {
7398 on = 1 << SYS_OFFSET(SCTRL_SYS_PSM_INT_ENABLE);
7399 } else {
7400 off = 1 << SYS_OFFSET(SCTRL_SYS_PSM_INT_ENABLE);
7401 }
7402
7403 i = SYS_REG_INDEX(SCTRL_SYS_PSM_INT_ENABLE, SCTRL_SYS_CMD_BASE);
7404 reg = SCSB_REG_ADDR(i);
7405 if (scsb_write_mask(scsb, reg, rmask, on, off)) {
7406 cmn_err(CE_WARN, "scsb_toggle_psmint: Cannot turn %s PSM_INT",
7407 enable == 1 ? "on" : "off");
7408 return (DDI_FAILURE);
7409 }
7410 if (enable == 0) {
7411 scsb->scsb_state &= ~SCSB_PSM_INT_ENABLED;
7412 } else {
7413 scsb->scsb_state |= SCSB_PSM_INT_ENABLED;
7414 }
7415
7416 return (DDI_SUCCESS);
7417 }
7418
7419 /*
7420 * This routine is to be used by all the drivers using this i2c bus
7421 * to synchronize their transfer operations.
7422 */
7423 int
7424 nct_i2c_transfer(i2c_client_hdl_t i2c_hdl, i2c_transfer_t *i2c_tran)
7425 {
7426 int retval, initmux = nct_mutex_init;
7427
7428 /*
7429 * If scsb interrupt mutex is initialized, also hold the
7430 * interrupt mutex to let the i2c_transfer() to complete
7431 */
7432
7433 if (initmux & MUTEX_INIT) {
7434 mutex_enter(scb_intr_mutex);
7435 }
7436
7437 retval = i2c_transfer(i2c_hdl, i2c_tran);
7438
7439 if (initmux & MUTEX_INIT) {
7440 mutex_exit(scb_intr_mutex);
7441 }
7442
7443 return (retval);
7444 }