xref: /titanic_50/usr/src/uts/sun4u/montecarlo/io/scsb.c (revision 385cc6b4ad1792caef3f84eb61eed3f27085801f)
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
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
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
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
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", &regs, &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
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
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
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
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
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
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
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
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
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
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
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 *
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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, &reg, &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
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, &reg, &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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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(&current_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
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
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 *
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
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
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
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
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
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 *
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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