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