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