xref: /titanic_52/usr/src/uts/sun4u/montecarlo/io/scsb.c (revision f808c858fa61e7769218966759510a8b1190dfcf)
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 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * Netra ct800 and Netra ct400 (MonteCarlo/Tonga)
31  * System Controller and Status Boards STREAMS driver.
32  *
33  * This driver handles all communications with the Netra ct400 and ct800
34  * System Controller Boards.
35  * I/O to the SCB is through the PCF8584 I2C controller.
36  * The SCB I2C interface and driver interface are provided by the
37  * Xilinx XCS40XL.
38  *
39  * N.B.: The design choice of using STREAMS was dictated because
40  *	 the original system monitor card had to multiplex 2 pcf8574's
41  *	 as one device.
42  */
43 
44 #include <sys/types.h>
45 #include <sys/param.h>
46 #include <sys/cred.h>
47 #include <sys/log.h>
48 #include <sys/uio.h>
49 #include <sys/stat.h>
50 #include <sys/vnode.h>
51 #include <sys/file.h>
52 #include <sys/open.h>
53 #include <sys/kmem.h>
54 #include <sys/kstat.h>
55 #include <sys/signal.h>
56 
57 #include <sys/stream.h>
58 #include <sys/strsubr.h>
59 #include <sys/strsun.h>
60 #include <sys/poll.h>
61 
62 #include <sys/debug.h>
63 
64 #include <sys/conf.h>
65 #include <sys/ddi.h>
66 #include <sys/sunddi.h>
67 #include <sys/modctl.h>
68 
69 #include <sys/i2c/misc/i2c_svc.h>
70 
71 #include <sys/mct_topology.h>
72 #include <sys/netract_gen.h>
73 #include <sys/scsbioctl.h>
74 #include <sys/scsb.h>
75 #include <sys/scsb_cbi.h>
76 
77 #include <sys/hotplug/hpctrl.h>
78 #include <sys/hsc.h>
79 #include <sys/hscimpl.h>
80 
81 #define	CPCI_HOTSWAP_SUPPORT
82 
83 #define	ALARM_CARD_ON_SLOT	1
84 #define	SCSB_FRU_OP_GET_REG	1
85 #define	SCSB_FRU_OP_SET_REGBIT	2
86 #define	SCSB_FRU_OP_GET_BITVAL	3
87 #define	SCSB_FRU_OP_GET_REGDATA	4
88 
89 /*
90  * (internal only)
91  * scsb build version format is "CCYYMMDD"
92  * for integer compares.
93  */
94 #define	SCSB_BUILD_VERSION	"20001206"
95 
96 #define	MUTEX_UNINIT	0
97 #define	MUTEX_INIT	2
98 
99 static	int scsb_err_threshold = 0; /* max allowed i2c errors */
100 static	int scsb_freeze_count = 3; /* #I2C errors to indicate SCB removal */
101 static	int scsb_shutdown_count = 5; /* #polls before passing shutdown evt */
102 static	int scsb_in_postintr = 0;	/* 1 if scsb is processing intr */
103 static	kmutex_t *scb_intr_mutex;	 /* SCSB interrupt mutex */
104 static	int	nct_mutex_init = MUTEX_UNINIT;
105 
106 extern	int	scsb_hsc_board_healthy();
107 
108 static	char	*scsb_name = SCSB_DEVICE_NAME;
109 static	char	*scsb_clone_name = SCSB_DEVICE_NAME "clone";
110 static	char	*scsb_build_version = SCSB_BUILD_VERSION;
111 /*
112  * cb_ops section of scsb driver.
113  */
114 static	int	sm_open(queue_t *, dev_t *, int, int, cred_t *);
115 static	int	sm_close(queue_t *, int, int, cred_t *);
116 
117 static	int	sm_rput(queue_t *, mblk_t *);	/* from i2c below */
118 static	int	sm_wput(queue_t *, mblk_t *);	/* from above */
119 
120 uint_t	scsb_intr_preprocess(caddr_t arg);
121 void	scsb_intr(caddr_t arg);
122 static	void	smf_ioctl(queue_t *, mblk_t *);
123 static	void	sm_ioc_rdwr(queue_t *, mblk_t *, int);
124 
125 static int scsb_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
126 static int scsb_attach(dev_info_t *, ddi_attach_cmd_t);
127 static int scsb_detach(dev_info_t *, ddi_detach_cmd_t);
128 static int initialize_scb(scsb_state_t *);
129 
130 static dev_info_t *scsb_dip;		/* private copy of devinfo pointer */
131 
132 static struct module_info info = {
133 	0, SCSB_DEVICE_NAME, 0, INFPSZ, 512, 128
134 };
135 
136 static struct qinit sm_rinit = {
137 	sm_rput, NULL, sm_open, sm_close, NULL, &info
138 };
139 
140 static struct qinit sm_winit = {
141 	sm_wput, NULL, sm_open, sm_close, NULL, &info
142 };
143 
144 struct streamtab sm_st  = {
145 	&sm_rinit, &sm_winit, NULL, NULL
146 };
147 
148 static struct cb_ops scsb_cb_ops = {
149 
150 	nulldev,		/* open */
151 	nulldev,		/* close */
152 	nodev,			/* strategy */
153 	nodev,			/* print */
154 	nodev,			/* dump */
155 	nodev,			/* read */
156 	nodev,			/* write */
157 	nodev,			/* ioctl */
158 	nodev,			/* devmap */
159 	nodev,			/* mmap */
160 	nodev, 			/* segmap */
161 	nochpoll,		/* poll */
162 	ddi_prop_op,		/* cb_prop_op */
163 	&sm_st,			/* streamtab  */
164 	D_MP,			/* Driver compatibility flag */
165 	CB_REV,				/* rev */
166 	nodev,				/* int (*cb_aread)() */
167 	nodev				/* int (*cb_awrite)() */
168 };
169 
170 static struct dev_ops scsb_ops = {
171 
172 	DEVO_REV,		/* devo_rev, */
173 	0,			/* refcnt  */
174 	scsb_info,		/* info */
175 	nulldev,		/* identify */
176 	nulldev,		/* probe */
177 	scsb_attach,		/* attach */
178 	scsb_detach,		/* detach */
179 	nodev,			/* reset */
180 	&scsb_cb_ops,		/* driver operations */
181 	(struct bus_ops *)0	/* bus operations */
182 
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 	"v%I% 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(scsb_ps_auto_on,
2768 							&pao, (4 *
2769 							drv_usectohz(1000000)));
2770 					} else
2771 #endif	/* PS_ON_DELAY */
2772 						scsb_ps_auto_on((void *)&pao);
2773 				}
2774 				/*
2775 				 * Special SLOT handling.
2776 				 * Make sure the OK LED is on for the CPU Slot
2777 				 * and for the FTC (CFTM) Slot for MonteCarlo.
2778 				 * Both will report as FRU_PRESENT.
2779 				 */
2780 				if (fru_type != SLOT || (fru_type == SLOT &&
2781 						(fru_ptr->fru_type ==
2782 						(scsb_utype_t)OC_CPU ||
2783 						fru_ptr->fru_type ==
2784 						(scsb_utype_t)OC_CTC))) {
2785 					/*
2786 					 * Set OK (green) LED register bit
2787 					 */
2788 					led_data[led_idx] |= 1 << led_bit;
2789 				}
2790 				if (IS_SCB_P10)
2791 					continue;
2792 				/*
2793 				 * Turn off BLINK register bit.
2794 				 * If single register update, then save the
2795 				 * corresponding blink register in blink_reg.
2796 				 */
2797 				reg = fru_ptr->i2c_info->blink_reg;
2798 				if (!reg)
2799 					continue;
2800 				blink_bit = fru_ptr->i2c_info->blink_bit;
2801 				blink_idx = SCSB_REG_INDEX(reg) - bid;
2802 				blink[blink_idx] |= 1 << blink_bit;
2803 				if (update_reg && update_reg == led_reg)
2804 					blink_reg = reg;
2805 			}
2806 		}
2807 	}
2808 	if (update_reg) {
2809 		reg = update_reg;
2810 		i = SCSB_REG_INDEX(reg);
2811 		puc = &led_data[i - lid];
2812 		i = 1;
2813 	} else {
2814 		reg = SCSB_REG_ADDR(SCTRL_LED_OK_BASE);
2815 		puc = led_data;
2816 		i = SCTRL_LED_OK_NUMREGS;
2817 	}
2818 	if (scsb_debug & 0x0100) {
2819 		cmn_err(CE_NOTE, "scsb_set_scfg_pres(): writing %d bytes "
2820 				"to 0x%x", i, reg);
2821 	}
2822 	if ((error = scsb_rdwr_register(scsb, I2C_WR, reg, i, puc, 1)) != 0) {
2823 		if (scsb_debug & 0x0102)
2824 			cmn_err(CE_NOTE, "scsb_set_scfg_pres(): "
2825 					"I2C write to 0x%x failed", reg);
2826 		error = EIO;
2827 	} else {
2828 		/*
2829 		 * Now see which BLINK bits need to be turned off for the
2830 		 * corresponding OK LED bits.
2831 		 */
2832 		reg = SCSB_REG_ADDR(SCTRL_BLINK_OK_BASE);
2833 		for (i = 0; i < SCTRL_BLINK_NUMREGS; ++i, ++reg) {
2834 			if (blink_reg && blink_reg != reg)
2835 				continue;
2836 			if (!blink[i]) {
2837 				continue;
2838 			}
2839 			if (scsb_debug & 0x0100) {
2840 				cmn_err(CE_NOTE, "scsb_set_scfg_pres(): turn "
2841 						"OFF Blink bits 0x%x in 0x%x",
2842 							blink[i], reg);
2843 			}
2844 			if (scsb_write_mask(scsb, reg, 0, 0, blink[i])) {
2845 				if (scsb_debug & 0x0102)
2846 					cmn_err(CE_NOTE,
2847 						"scsb_set_scfg_pres(): "
2848 						"Write to 0x%x failed", reg);
2849 				error = EIO;
2850 				break;
2851 			}
2852 		}
2853 	}
2854 	return (error);
2855 }
2856 
2857 static int
2858 scsb_check_config_status(scsb_state_t *scsb)
2859 {
2860 	int		error;
2861 	uchar_t		reg;
2862 	int		index, p06;
2863 
2864 	if (scsb_debug & 0x0201) {
2865 		cmn_err(CE_NOTE, "scsb_check_config_status:");
2866 	}
2867 	/*
2868 	 * Base of register set
2869 	 */
2870 	reg = SCSB_REG_ADDR(SCTRL_SYSCFG_BASE);
2871 	index = SCSB_REG_INDEX(reg);
2872 	/*
2873 	 * SCB P0.6 workaround: read registers twice, use 2nd value set
2874 	 */
2875 	mutex_enter(&scsb->scsb_mutex);
2876 	p06 = 2;
2877 	do {
2878 		if (error = scsb_rdwr_register(scsb, I2C_WR_RD, reg,
2879 			SCTRL_CFG_NUMREGS, &scsb->scsb_data_reg[index], 1)) {
2880 			break;
2881 		}
2882 		if (p06 == 1) {
2883 			if (scsb_debug & 0x0200)
2884 				cmn_err(CE_NOTE,
2885 				"scsb_check_config_status: P0.6 workaround");
2886 		}
2887 		/*
2888 		 * If not P0.6 PROM, just break here
2889 		 */
2890 		if (!(scsb->scsb_state & SCSB_P06_PROM))
2891 			break;
2892 	} while (--p06);
2893 	mutex_exit(&scsb->scsb_mutex);
2894 
2895 	if (error == 0) {
2896 		if (!(scsb->scsb_state & SCSB_SCB_PRESENT))
2897 			scsb->scsb_state |= SCSB_SCB_PRESENT;
2898 		if (scsb_fru_op(scsb, SSB, 1, SCTRL_SYSCFG_BASE,
2899 						SCSB_FRU_OP_GET_BITVAL))
2900 			scsb->scsb_state |= SCSB_SSB_PRESENT;
2901 		else
2902 			scsb->scsb_state &= ~SCSB_SSB_PRESENT;
2903 	}
2904 	return (error);
2905 }
2906 
2907 static void
2908 scsb_set_topology(scsb_state_t *scsb)
2909 {
2910 	int		i, t, index, unit, is_tonga = 0;
2911 	int		alarm_slot_num, cpu_slot_num, ctc_slot_num;
2912 	fru_info_t	*fru_ptr, *last_ptr, *acslot_ptr, *ctcslot_ptr;
2913 	uchar_t		syscfg, led_reg, blink_reg, t_uchar;
2914 	uchar_t		bit_num, led_bit, blink_bit;
2915 	int		pad = 0;
2916 
2917 	/*
2918 	 * Get the presence status from the SysConfigStatus shadow registers
2919 	 * in scsb->scsb_data_reg[]
2920 	 */
2921 	/* Mid Plane */
2922 	i = SYS_REG_INDEX(SCTRL_CFG_MPID0, SCTRL_SYSCFG_BASE);
2923 	t_uchar = SCSB_REG_ADDR(i);
2924 	index = SCSB_REG_INDEX(t_uchar);
2925 	mct_system_info.mid_plane.fru_type = MIDPLANE;
2926 	mct_system_info.mid_plane.fru_version = (fru_version_t)0;
2927 	t = SYS_OFFSET(SCTRL_CFG_MPID0);
2928 	mct_system_info.mid_plane.fru_id = (int)((scsb->scsb_data_reg[index] &
2929 						(SCTRL_MPID_MASK << t)) >> t);
2930 	switch (mct_system_info.mid_plane.fru_id) {
2931 	case SCTRL_MPID_HALF:		/* Monte Carlo		*/
2932 		if (scsb_debug & 0x00100005)
2933 			cmn_err(CE_NOTE, "scsb_set_topology: Monte Carlo");
2934 		cpu_slot_num = SC_MC_CPU_SLOT;
2935 		ctc_slot_num = SC_MC_CTC_SLOT;
2936 		alarm_slot_num = scsb->ac_slotnum = SC_MC_AC_SLOT;
2937 		mct_system_info.max_units[SLOT] = MC_MAX_SLOTS;
2938 		mct_system_info.max_units[ALARM] = MC_MAX_AC;
2939 		mct_system_info.max_units[DISK] = MC_MAX_DISK;
2940 		mct_system_info.max_units[FAN] = MC_MAX_FAN;
2941 		mct_system_info.max_units[PS] = MC_MAX_PS;
2942 		mct_system_info.max_units[PDU] = MC_MAX_PDU;
2943 		mct_system_info.max_units[SCB] = MC_MAX_SCB;
2944 		mct_system_info.max_units[SSB] = MC_MAX_SCB;
2945 		mct_system_info.max_units[CFTM] = MC_MAX_CFTM;
2946 		mct_system_info.max_units[CRTM] = MC_MAX_CRTM;
2947 		mct_system_info.max_units[PRTM] = MC_MAX_PRTM;
2948 		break;
2949 	case SCTRL_MPID_QUARTER_NODSK:	/* Tonga w/o disk	*/
2950 	case SCTRL_MPID_QUARTER:	/* Tonga w/  disk	*/
2951 		scsb->scsb_state |= SCSB_IS_TONGA;
2952 		is_tonga = 1;
2953 		ctc_slot_num = -1;
2954 		ctcslot_ptr = NULL;
2955 		if (scsb_debug & 0x00100005)
2956 			cmn_err(CE_NOTE, "scsb_set_topology: Tonga%s",
2957 				mct_system_info.mid_plane.fru_id ==
2958 					SCTRL_MPID_QUARTER_NODSK ?
2959 				", no disk" : " with disk");
2960 		cpu_slot_num = SC_TG_CPU_SLOT;
2961 		alarm_slot_num = scsb->ac_slotnum = SC_TG_AC_SLOT;
2962 		mct_system_info.max_units[SLOT] = TG_MAX_SLOTS;
2963 		mct_system_info.max_units[ALARM] = TG_MAX_AC;
2964 		mct_system_info.max_units[DISK] = TG_MAX_DISK;
2965 		mct_system_info.max_units[FAN] = TG_MAX_FAN;
2966 		mct_system_info.max_units[PS] = TG_MAX_PS;
2967 		mct_system_info.max_units[PDU] = TG_MAX_PDU;
2968 		mct_system_info.max_units[SCB] = TG_MAX_SCB;
2969 		mct_system_info.max_units[SSB] = TG_MAX_SCB;
2970 		mct_system_info.max_units[CFTM] = TG_MAX_CFTM;
2971 		mct_system_info.max_units[CRTM] = TG_MAX_CRTM;
2972 		mct_system_info.max_units[PRTM] = TG_MAX_PRTM;
2973 		break;
2974 	default:
2975 		cmn_err(CE_WARN, "%s#%d: Unknown MidPlane Id %x",
2976 				ddi_driver_name(scsb->scsb_dev),
2977 				ddi_get_instance(scsb->scsb_dev),
2978 				mct_system_info.mid_plane.fru_id);
2979 		if (scsb_debug & 0x00100005)
2980 			cmn_err(CE_NOTE, "scsb_set_topology: 0x%x: unknown!",
2981 			mct_system_info.mid_plane.fru_id);
2982 		return;
2983 	}
2984 	/*
2985 	 * cPCI Slots
2986 	 *
2987 	 * NOTE: The Tonga slot fru_unit needs to get mapped to the logical
2988 	 * slot number in slot_table[].  The field is not in the slot_table
2989 	 * at least until we know the format of the OBP slot table for the FCS
2990 	 * release.
2991 	 */
2992 	mct_system_info.fru_info_list[SLOT] = (fru_info_t *)
2993 			kmem_zalloc(sizeof (fru_info_t) *
2994 				(mct_system_info.max_units[SLOT] + pad),
2995 				KM_SLEEP);
2996 	fru_ptr = mct_system_info.fru_info_list[SLOT];
2997 	for (unit = 1; unit <= mct_system_info.max_units[SLOT]; ++unit) {
2998 		int	iunit;
2999 		if (unit == cpu_slot_num) {
3000 			fru_ptr->fru_type = (scsb_utype_t)OC_CPU;
3001 		} else if (unit == ctc_slot_num) {
3002 			/* fru_ptr saved for Transition Card Presence check */
3003 			ctcslot_ptr = fru_ptr;
3004 			fru_ptr->fru_type = (scsb_utype_t)OC_UNKN;
3005 		} else if (unit == alarm_slot_num) {
3006 			/* fru_ptr saved for Alarm Card Presence check below */
3007 			acslot_ptr = fru_ptr;
3008 			fru_ptr->fru_type = (scsb_utype_t)OC_UNKN;
3009 		} else {
3010 			fru_ptr->fru_type = (scsb_utype_t)OC_UNKN;
3011 		}
3012 		/*
3013 		 * Get the slot event code (t), then use it to get the
3014 		 * slot bit-offsets for LED, BLINK, and SYSCFG registers.
3015 		 * On a P1.5 Tonga, the internal slot number must be used to
3016 		 * find the event code.
3017 		 * The P1.0 Tonga does not get mapped due to a SSB difference.
3018 		 */
3019 		if (IS_SCB_P15) {
3020 			iunit = tonga_psl_to_ssl(scsb, unit);
3021 			t = FRU_UNIT_TO_EVCODE(SLOT, iunit);
3022 		} else {
3023 			t = FRU_UNIT_TO_EVCODE(SLOT, unit);
3024 		}
3025 		led_bit = FRU_OFFSET(t, SCTRL_LED_OK_BASE);
3026 		blink_bit = FRU_OFFSET(t, SCTRL_BLINK_OK_BASE);
3027 		blink_reg = FRU_REG_ADDR(t, SCTRL_BLINK_OK_BASE);
3028 		if (is_tonga && unit <= TG_MAX_SLOTS) {
3029 			bit_num = tonga_pslotnum_to_cfgbit(scsb, unit);
3030 		} else {
3031 			bit_num = FRU_OFFSET(t, SCTRL_SYSCFG_BASE);
3032 		}
3033 		/*
3034 		 * get the registers addresses and shadow register index for
3035 		 * the SYSCFG register
3036 		 */
3037 		syscfg = FRU_REG_ADDR(t, SCTRL_SYSCFG_BASE);
3038 		index = SCSB_REG_INDEX(syscfg);
3039 		led_reg = FRU_REG_ADDR(t, SCTRL_LED_OK_BASE);
3040 		/*
3041 		 * check and set presence status
3042 		 */
3043 		if (scsb->scsb_state & SCSB_P06_PROM) {
3044 			fru_ptr->fru_status = FRU_NOT_PRESENT;
3045 		} else if (scsb->scsb_data_reg[index] & (1 << bit_num)) {
3046 			fru_ptr->fru_status = FRU_PRESENT;
3047 		} else {
3048 			fru_ptr->fru_status = FRU_NOT_PRESENT;
3049 		}
3050 		fru_ptr->fru_unit = (scsb_unum_t)unit;
3051 		fru_ptr->fru_id = fru_id_table[event_to_index(
3052 					FRU_UNIT_TO_EVCODE(SLOT, unit))];
3053 		fru_ptr->fru_version = (fru_version_t)0;
3054 		fru_ptr->type_list = (fru_options_t *)NULL;
3055 		fru_ptr->i2c_info = (fru_i2c_info_t *)
3056 				kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP);
3057 		fru_ptr->i2c_info->syscfg_reg = syscfg;
3058 		fru_ptr->i2c_info->syscfg_bit = bit_num;
3059 		fru_ptr->i2c_info->ledata_reg = led_reg;
3060 		fru_ptr->i2c_info->ledata_bit = led_bit;
3061 		fru_ptr->i2c_info->blink_reg = blink_reg;
3062 		fru_ptr->i2c_info->blink_bit = blink_bit;
3063 		last_ptr = fru_ptr;
3064 		fru_ptr++;
3065 		last_ptr->next = fru_ptr;
3066 	}
3067 	last_ptr->next = (fru_info_t *)NULL;
3068 	/*
3069 	 * PDU
3070 	 */
3071 	mct_system_info.fru_info_list[PDU] = (fru_info_t *)
3072 			kmem_zalloc(sizeof (fru_info_t) *
3073 				(mct_system_info.max_units[PDU] + pad),
3074 				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),
3135 				KM_SLEEP);
3136 	fru_ptr = mct_system_info.fru_info_list[PS];
3137 	for (unit = 1; unit <= mct_system_info.max_units[PS]; ++unit) {
3138 		/*
3139 		 * get the FRU event code (t), then use it to get the
3140 		 * FRU bit-offsets for LED and SYSCFG registers
3141 		 */
3142 		t = FRU_UNIT_TO_EVCODE(PS, unit);
3143 		led_bit = FRU_OFFSET(t, SCTRL_LED_OK_BASE);
3144 		bit_num = FRU_OFFSET(t, SCTRL_SYSCFG_BASE);
3145 		if (IS_SCB_P15) {
3146 			blink_bit = FRU_OFFSET(t, SCTRL_BLINK_OK_BASE);
3147 			i = FRU_REG_INDEX(t, SCTRL_BLINK_OK_BASE);
3148 			blink_reg = SCSB_REG_ADDR(i);
3149 		} else {
3150 			blink_bit = 0;
3151 			blink_reg = 0;
3152 		}
3153 		/*
3154 		 * get the registers addresses and shadow register index for
3155 		 * the SYSCFG register
3156 		 */
3157 		i = FRU_REG_INDEX(t, SCTRL_SYSCFG_BASE);
3158 		syscfg = SCSB_REG_ADDR(i);
3159 		index = SCSB_REG_INDEX(syscfg);
3160 		i = FRU_REG_INDEX(t, SCTRL_LED_OK_BASE);
3161 		led_reg = SCSB_REG_ADDR(i);
3162 		/*
3163 		 * check and set presence status
3164 		 */
3165 		if (scsb->scsb_data_reg[index] & (1 << bit_num)) {
3166 			fru_ptr->fru_status = FRU_PRESENT;
3167 		} else {
3168 			fru_ptr->fru_status = FRU_NOT_PRESENT;
3169 		}
3170 		fru_ptr->fru_type = PS;
3171 		fru_ptr->fru_unit = (scsb_unum_t)unit;
3172 		fru_ptr->fru_id = fru_id_table[event_to_index(t)];
3173 		fru_ptr->fru_version = (fru_version_t)0;
3174 		fru_ptr->type_list = (fru_options_t *)NULL;
3175 		fru_ptr->i2c_info = (fru_i2c_info_t *)
3176 				kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP);
3177 		fru_ptr->i2c_info->syscfg_reg = syscfg;
3178 		fru_ptr->i2c_info->syscfg_bit = bit_num;
3179 		fru_ptr->i2c_info->ledata_reg = led_reg;
3180 		fru_ptr->i2c_info->ledata_bit = led_bit;
3181 		fru_ptr->i2c_info->blink_reg = blink_reg;
3182 		fru_ptr->i2c_info->blink_bit = blink_bit;
3183 		last_ptr = fru_ptr;
3184 		fru_ptr++;
3185 		last_ptr->next = fru_ptr;
3186 	}
3187 	last_ptr->next = (fru_info_t *)NULL;
3188 	/*
3189 	 * SCSI Disks and removable media
3190 	 */
3191 	mct_system_info.fru_info_list[DISK] = (fru_info_t *)
3192 			kmem_zalloc(sizeof (fru_info_t) *
3193 				(mct_system_info.max_units[DISK] + pad),
3194 				KM_SLEEP);
3195 	fru_ptr = mct_system_info.fru_info_list[DISK];
3196 	for (unit = 1; unit <= mct_system_info.max_units[DISK]; ++unit) {
3197 		/* SCB15 */
3198 		/*
3199 		 * get the FRU event code (t), then use it to get the
3200 		 * FRU bit-offsets for LED and SYSCFG registers
3201 		 */
3202 		t = FRU_UNIT_TO_EVCODE(DISK, unit);
3203 		led_bit = FRU_OFFSET(t, SCTRL_LED_OK_BASE);
3204 		bit_num = FRU_OFFSET(t, SCTRL_SYSCFG_BASE);
3205 		if (IS_SCB_P15) {
3206 			blink_bit = FRU_OFFSET(t, SCTRL_BLINK_OK_BASE);
3207 			i = FRU_REG_INDEX(t, SCTRL_BLINK_OK_BASE);
3208 			blink_reg = SCSB_REG_ADDR(i);
3209 		} else {
3210 			blink_bit = 0;
3211 			blink_reg = 0;
3212 		}
3213 		/*
3214 		 * get the registers addresses and shadow register index for
3215 		 * the SYSCFG register
3216 		 */
3217 		i = FRU_REG_INDEX(t, SCTRL_SYSCFG_BASE);
3218 		syscfg = SCSB_REG_ADDR(i);
3219 		index = SCSB_REG_INDEX(syscfg);
3220 		i = FRU_REG_INDEX(t, SCTRL_LED_OK_BASE);
3221 		led_reg = SCSB_REG_ADDR(i);
3222 		/*
3223 		 * check and set presence status
3224 		 */
3225 		if (scsb->scsb_data_reg[index] & (1 << bit_num)) {
3226 			fru_ptr->fru_status = FRU_PRESENT;
3227 			fru_ptr->fru_version = (fru_version_t)0;
3228 		} else
3229 			fru_ptr->fru_status = FRU_NOT_PRESENT;
3230 		fru_ptr->fru_type = DISK;
3231 		fru_ptr->fru_unit = (scsb_unum_t)unit;
3232 		fru_ptr->fru_id = fru_id_table[event_to_index(t)];
3233 		fru_ptr->type_list = (fru_options_t *)NULL;
3234 		fru_ptr->i2c_info = (fru_i2c_info_t *)
3235 				kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP);
3236 		fru_ptr->i2c_info->syscfg_reg = syscfg;
3237 		fru_ptr->i2c_info->syscfg_bit = bit_num;
3238 		fru_ptr->i2c_info->ledata_reg = led_reg;
3239 		fru_ptr->i2c_info->ledata_bit = led_bit;
3240 		fru_ptr->i2c_info->blink_reg = blink_reg;
3241 		fru_ptr->i2c_info->blink_bit = blink_bit;
3242 		last_ptr = fru_ptr;
3243 		fru_ptr++;
3244 		last_ptr->next = fru_ptr;
3245 	}
3246 	last_ptr->next = (fru_info_t *)NULL;
3247 	/*
3248 	 * Fan Trays
3249 	 */
3250 	mct_system_info.fru_info_list[FAN] = (fru_info_t *)
3251 			kmem_zalloc(sizeof (fru_info_t) *
3252 				(mct_system_info.max_units[FAN] + pad),
3253 				KM_SLEEP);
3254 	fru_ptr = mct_system_info.fru_info_list[FAN];
3255 	for (unit = 1; unit <= mct_system_info.max_units[FAN]; ++unit) {
3256 		int		bit_num;
3257 		/* SCB15 */
3258 		/*
3259 		 * get the FRU event code (t), then use it to get the
3260 		 * FRU bit-offsets for LED and SYSCFG registers
3261 		 */
3262 		t = FRU_UNIT_TO_EVCODE(FAN, unit);
3263 		led_bit = FRU_OFFSET(t, SCTRL_LED_OK_BASE);
3264 		bit_num = FRU_OFFSET(t, SCTRL_SYSCFG_BASE);
3265 		if (IS_SCB_P15) {
3266 			blink_bit = FRU_OFFSET(t, SCTRL_BLINK_OK_BASE);
3267 			i = FRU_REG_INDEX(t, SCTRL_BLINK_OK_BASE);
3268 			blink_reg = SCSB_REG_ADDR(i);
3269 		} else {
3270 			blink_bit = 0;
3271 			blink_reg = 0;
3272 		}
3273 		/*
3274 		 * get the registers addresses and shadow register index for
3275 		 * the SYSCFG register
3276 		 */
3277 		i = FRU_REG_INDEX(t, SCTRL_SYSCFG_BASE);
3278 		syscfg = SCSB_REG_ADDR(i);
3279 		index = SCSB_REG_INDEX(syscfg);
3280 		i = FRU_REG_INDEX(t, SCTRL_LED_OK_BASE);
3281 		led_reg = SCSB_REG_ADDR(i);
3282 		/*
3283 		 * check and set presence status
3284 		 */
3285 		if (scsb->scsb_data_reg[index] & (1 << bit_num)) {
3286 			fru_ptr->fru_status = FRU_PRESENT;
3287 		} else {
3288 			fru_ptr->fru_status = FRU_NOT_PRESENT;
3289 		}
3290 		fru_ptr->fru_type = FAN;
3291 		fru_ptr->fru_unit = (scsb_unum_t)unit;
3292 		fru_ptr->fru_id = fru_id_table[event_to_index(t)];
3293 		fru_ptr->fru_version = (fru_version_t)0;
3294 		fru_ptr->type_list = (fru_options_t *)NULL;
3295 		fru_ptr->i2c_info = (fru_i2c_info_t *)
3296 				kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP);
3297 		fru_ptr->i2c_info->syscfg_reg = syscfg;
3298 		fru_ptr->i2c_info->syscfg_bit = bit_num;
3299 		fru_ptr->i2c_info->ledata_reg = led_reg;
3300 		fru_ptr->i2c_info->ledata_bit = led_bit;
3301 		fru_ptr->i2c_info->blink_reg = blink_reg;
3302 		fru_ptr->i2c_info->blink_bit = blink_bit;
3303 		last_ptr = fru_ptr;
3304 		fru_ptr++;
3305 		last_ptr->next = fru_ptr;
3306 	}
3307 	last_ptr->next = (fru_info_t *)NULL;
3308 	/*
3309 	 * Alarm Cards
3310 	 */
3311 	mct_system_info.fru_info_list[ALARM] = (fru_info_t *)
3312 			kmem_zalloc(sizeof (fru_info_t) *
3313 				(mct_system_info.max_units[ALARM] + pad),
3314 				KM_SLEEP);
3315 	fru_ptr = mct_system_info.fru_info_list[ALARM];
3316 	for (unit = 1; unit <= mct_system_info.max_units[ALARM]; ++unit) {
3317 		int		bit_num;
3318 
3319 		/*
3320 		 * get the FRU event code (t), then use it to get the
3321 		 * FRU bit-offsets for SYSCFG register
3322 		 */
3323 		t = FRU_UNIT_TO_EVCODE(ALARM, unit);
3324 		bit_num = FRU_OFFSET(t, SCTRL_SYSCFG_BASE);
3325 		/*
3326 		 * get the registers addresses and shadow register index for
3327 		 * the SYSCFG register
3328 		 */
3329 		i = FRU_REG_INDEX(t, SCTRL_SYSCFG_BASE);
3330 		syscfg = SCSB_REG_ADDR(i);
3331 		index = SCSB_REG_INDEX(syscfg);
3332 		/*
3333 		 * check and set presence status
3334 		 */
3335 		if (scsb->scsb_data_reg[index] & (1 << bit_num)) {
3336 			fru_ptr->fru_status = FRU_PRESENT;
3337 			if (acslot_ptr != NULL && acslot_ptr->fru_status ==
3338 								FRU_PRESENT) {
3339 				acslot_ptr->fru_type = (scsb_utype_t)OC_AC;
3340 				/*
3341 				 * acslot_ptr->fru_id =
3342 				 *		fru_id_table[event_to_index(t)];
3343 				 */
3344 			}
3345 		} else {
3346 			fru_ptr->fru_status = FRU_NOT_PRESENT;
3347 		}
3348 
3349 		fru_ptr->fru_type = ALARM;
3350 		fru_ptr->fru_unit = (scsb_unum_t)unit;
3351 		fru_ptr->fru_id = fru_id_table[event_to_index(t)];
3352 		fru_ptr->fru_version = (fru_version_t)0;
3353 		fru_ptr->type_list = (fru_options_t *)NULL;
3354 		fru_ptr->i2c_info = (fru_i2c_info_t *)
3355 				kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP);
3356 		fru_ptr->i2c_info->syscfg_reg = syscfg;
3357 		fru_ptr->i2c_info->syscfg_bit = bit_num;
3358 		fru_ptr->i2c_info->ledata_reg = 0;
3359 		fru_ptr->i2c_info->ledata_bit = 0;
3360 		fru_ptr->i2c_info->blink_reg = 0;
3361 		fru_ptr->i2c_info->blink_bit = 0;
3362 		last_ptr = fru_ptr;
3363 		fru_ptr++;
3364 		last_ptr->next = fru_ptr;
3365 	}
3366 	last_ptr->next = (fru_info_t *)NULL;
3367 	/*
3368 	 * SCB
3369 	 */
3370 	mct_system_info.fru_info_list[SCB] = (fru_info_t *)
3371 			kmem_zalloc(sizeof (fru_info_t) *
3372 				(mct_system_info.max_units[SCB] + pad),
3373 				KM_SLEEP);
3374 	fru_ptr = mct_system_info.fru_info_list[SCB];
3375 	unit = 1;
3376 	/* SCB15 */
3377 	/*
3378 	 * get the FRU event code (t), then use it to get the
3379 	 * FRU bit-offset for LED register
3380 	 */
3381 	t = FRU_UNIT_TO_EVCODE(SCB, unit);
3382 	led_bit = FRU_OFFSET(t, SCTRL_LED_OK_BASE);
3383 	i = FRU_REG_INDEX(t, SCTRL_LED_OK_BASE);
3384 	led_reg = SCSB_REG_ADDR(i);
3385 	if (IS_SCB_P15) {
3386 		blink_bit = FRU_OFFSET(t, SCTRL_BLINK_OK_BASE);
3387 		i = FRU_REG_INDEX(t, SCTRL_BLINK_OK_BASE);
3388 		blink_reg = SCSB_REG_ADDR(i);
3389 	} else {
3390 		blink_bit = 0;
3391 		blink_reg = 0;
3392 	}
3393 	i = SYS_REG_INDEX(SCTRL_SCBID0, SCTRL_SCBID_BASE);
3394 	index = SCSB_REG_ADDR(i);
3395 	/*
3396 	 * check and set presence status
3397 	 */
3398 	if (scsb->scsb_state & SCSB_SCB_PRESENT) {
3399 		fru_ptr->fru_status = FRU_PRESENT;
3400 	} else {
3401 		fru_ptr->fru_status = FRU_NOT_PRESENT;
3402 	}
3403 	fru_ptr->fru_type = SCB;
3404 	fru_ptr->fru_unit = (scsb_unum_t)unit;
3405 	fru_ptr->fru_id = fru_id_table[event_to_index(t)];
3406 	/* get PROM_VERSION from shadow registers */
3407 	if (scsb_rdwr_register(scsb, I2C_WR_RD, index, 1, &t_uchar, 1))
3408 		fru_ptr->fru_version = (fru_version_t)0;
3409 	else
3410 		fru_ptr->fru_version = (fru_version_t)t_uchar;
3411 	fru_ptr->type_list = (fru_options_t *)NULL;
3412 	fru_ptr->i2c_info = (fru_i2c_info_t *)
3413 			kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP);
3414 	fru_ptr->i2c_info->syscfg_reg = 0;
3415 	fru_ptr->i2c_info->syscfg_bit = 0;
3416 	fru_ptr->i2c_info->ledata_reg = led_reg;
3417 	fru_ptr->i2c_info->ledata_bit = led_bit;
3418 	fru_ptr->i2c_info->blink_reg = blink_reg;
3419 	fru_ptr->i2c_info->blink_bit = blink_bit;
3420 	fru_ptr->next = (fru_info_t *)NULL;
3421 	/*
3422 	 * SSB
3423 	 */
3424 	mct_system_info.fru_info_list[SSB] = (fru_info_t *)
3425 			kmem_zalloc(sizeof (fru_info_t) *
3426 				(mct_system_info.max_units[SSB] + pad),
3427 				KM_SLEEP);
3428 	fru_ptr = mct_system_info.fru_info_list[SSB];
3429 	unit = 1;
3430 	/* SCB15 */
3431 	/*
3432 	 * get the FRU event code (t), then use it to get the
3433 	 * FRU bit-offset for SYSCFG register
3434 	 */
3435 	t = FRU_UNIT_TO_EVCODE(SSB, unit);
3436 	bit_num = FRU_OFFSET(t, SCTRL_SYSCFG_BASE);
3437 	/*
3438 	 * get the registers addresses and shadow register index for
3439 	 * the SYSCFG register
3440 	 */
3441 	i = FRU_REG_INDEX(t, SCTRL_SYSCFG_BASE);
3442 	syscfg = SCSB_REG_ADDR(i);
3443 	index = SCSB_REG_INDEX(syscfg);
3444 	/*
3445 	 * check and set presence status
3446 	 */
3447 	if (scsb->scsb_data_reg[index] & (1 << bit_num)) {
3448 		fru_ptr->fru_status = FRU_PRESENT;
3449 	} else {
3450 		fru_ptr->fru_status = FRU_NOT_PRESENT;
3451 	}
3452 	fru_ptr->fru_type = SSB;
3453 	fru_ptr->fru_unit = (scsb_unum_t)unit;
3454 	fru_ptr->fru_id = fru_id_table[event_to_index(t)];
3455 	fru_ptr->fru_version = (fru_version_t)0;
3456 	fru_ptr->type_list = (fru_options_t *)NULL;
3457 	fru_ptr->i2c_info = (fru_i2c_info_t *)
3458 			kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP);
3459 	fru_ptr->i2c_info->syscfg_reg = syscfg;
3460 	fru_ptr->i2c_info->syscfg_bit = bit_num;
3461 	fru_ptr->i2c_info->ledata_reg = 0;
3462 	fru_ptr->i2c_info->ledata_bit = 0;
3463 	fru_ptr->i2c_info->blink_reg = 0;
3464 	fru_ptr->i2c_info->blink_bit = 0;
3465 	fru_ptr->next = (fru_info_t *)NULL;
3466 	/*
3467 	 * CFTM
3468 	 */
3469 	mct_system_info.fru_info_list[CFTM] = (fru_info_t *)
3470 			kmem_zalloc(sizeof (fru_info_t) *
3471 				(mct_system_info.max_units[CFTM] + pad),
3472 				KM_SLEEP);
3473 	fru_ptr = mct_system_info.fru_info_list[CFTM];
3474 	unit = 1;
3475 	/* SCB15 */
3476 	/*
3477 	 * get the FRU event code (t), then use it to get the
3478 	 * FRU bit-offsets for LED and SYSCFG registers
3479 	 */
3480 	t = FRU_UNIT_TO_EVCODE(CFTM, unit);
3481 	led_bit = FRU_OFFSET(t, SCTRL_LED_OK_BASE);
3482 	bit_num = FRU_OFFSET(t, SCTRL_SYSCFG_BASE);
3483 	if (IS_SCB_P15) {
3484 		blink_bit = FRU_OFFSET(t, SCTRL_BLINK_OK_BASE);
3485 		i = FRU_REG_INDEX(t, SCTRL_BLINK_OK_BASE);
3486 		blink_reg = SCSB_REG_ADDR(i);
3487 	} else {
3488 		blink_bit = 0;
3489 		blink_reg = 0;
3490 	}
3491 	/*
3492 	 * get the registers addresses and shadow register index for
3493 	 * the SYSCFG register
3494 	 */
3495 	i = FRU_REG_INDEX(t, SCTRL_SYSCFG_BASE);
3496 	syscfg = SCSB_REG_ADDR(i);
3497 	index = SCSB_REG_INDEX(syscfg);
3498 	i = FRU_REG_INDEX(t, SCTRL_LED_OK_BASE);
3499 	led_reg = SCSB_REG_ADDR(i);
3500 	/*
3501 	 * check and set presence status
3502 	 */
3503 	if (scsb->scsb_data_reg[index] & (1 << bit_num)) {
3504 		fru_ptr->fru_status = FRU_PRESENT;
3505 		if (ctcslot_ptr != NULL && ctcslot_ptr->fru_status ==
3506 								FRU_PRESENT) {
3507 			ctcslot_ptr->fru_type = (scsb_utype_t)OC_CTC;
3508 			scsb->scsb_hsc_state |= SCSB_HSC_CTC_PRES;
3509 		}
3510 	} else {
3511 		fru_ptr->fru_status = FRU_NOT_PRESENT;
3512 	}
3513 	fru_ptr->fru_type = CFTM;
3514 	fru_ptr->fru_unit = (scsb_unum_t)1;
3515 	fru_ptr->fru_id = fru_id_table[event_to_index(t)];
3516 	fru_ptr->fru_version = (fru_version_t)0;
3517 	fru_ptr->type_list = (fru_options_t *)NULL;
3518 	fru_ptr->i2c_info = (fru_i2c_info_t *)
3519 			kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP);
3520 	fru_ptr->i2c_info->syscfg_reg = syscfg;
3521 	fru_ptr->i2c_info->syscfg_bit = bit_num;
3522 	fru_ptr->i2c_info->ledata_reg = led_reg;
3523 	fru_ptr->i2c_info->ledata_bit = led_bit;
3524 	fru_ptr->i2c_info->blink_reg = blink_reg;
3525 	fru_ptr->i2c_info->blink_bit = blink_bit;
3526 	fru_ptr->next = (fru_info_t *)NULL;
3527 	/*
3528 	 * CRTM
3529 	 */
3530 	mct_system_info.fru_info_list[CRTM] = (fru_info_t *)
3531 			kmem_zalloc(sizeof (fru_info_t) *
3532 				(mct_system_info.max_units[CRTM] + pad),
3533 				KM_SLEEP);
3534 	fru_ptr = mct_system_info.fru_info_list[CRTM];
3535 	unit = 1;
3536 	/* SCB15 */
3537 	/*
3538 	 * get the FRU event code (t), then use it to get the
3539 	 * FRU bit-offsets for LED and SYSCFG registers
3540 	 */
3541 	t = FRU_UNIT_TO_EVCODE(CRTM, unit);
3542 	bit_num = FRU_OFFSET(t, SCTRL_SYSCFG_BASE);
3543 	/*
3544 	 * get the registers addresses and shadow register index for
3545 	 * the SYSCFG register
3546 	 */
3547 	i = FRU_REG_INDEX(t, SCTRL_SYSCFG_BASE);
3548 	syscfg = SCSB_REG_ADDR(i);
3549 	index = SCSB_REG_INDEX(syscfg);
3550 	/*
3551 	 * check and set presence status
3552 	 */
3553 	if (scsb->scsb_data_reg[index] & (1 << bit_num)) {
3554 		fru_ptr->fru_status = FRU_PRESENT;
3555 	} else {
3556 		fru_ptr->fru_status = FRU_NOT_PRESENT;
3557 	}
3558 	fru_ptr->fru_type = CRTM;
3559 	fru_ptr->fru_unit = (scsb_unum_t)unit;
3560 	fru_ptr->fru_id = fru_id_table[event_to_index(t)];
3561 	fru_ptr->fru_version = (fru_version_t)0;
3562 	fru_ptr->type_list = (fru_options_t *)NULL;
3563 	fru_ptr->i2c_info = (fru_i2c_info_t *)
3564 			kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP);
3565 	fru_ptr->i2c_info->syscfg_reg = syscfg;
3566 	fru_ptr->i2c_info->syscfg_bit = bit_num;
3567 	fru_ptr->i2c_info->ledata_reg = 0;
3568 	fru_ptr->i2c_info->ledata_bit = 0;
3569 	fru_ptr->i2c_info->blink_reg = 0;
3570 	fru_ptr->i2c_info->blink_bit = 0;
3571 	fru_ptr->next = (fru_info_t *)NULL;
3572 	/*
3573 	 * PRTM
3574 	 */
3575 	mct_system_info.fru_info_list[PRTM] = (fru_info_t *)
3576 			kmem_zalloc(sizeof (fru_info_t) *
3577 				(mct_system_info.max_units[PRTM] + pad),
3578 				KM_SLEEP);
3579 	fru_ptr = mct_system_info.fru_info_list[PRTM];
3580 	unit = 1;
3581 	/*
3582 	 * SCB15
3583 	 * get the FRU event code (t), then use it to get the
3584 	 * FRU bit-offsets for LED and SYSCFG registers
3585 	 */
3586 	t = FRU_UNIT_TO_EVCODE(PRTM, unit);
3587 	bit_num = FRU_OFFSET(t, SCTRL_SYSCFG_BASE);
3588 	/*
3589 	 * get the registers addresses and shadow register index for
3590 	 * the SYSCFG register
3591 	 */
3592 	i = FRU_REG_INDEX(t, SCTRL_SYSCFG_BASE);
3593 	syscfg = SCSB_REG_ADDR(i);
3594 	index = SCSB_REG_INDEX(syscfg);
3595 	/*
3596 	 * check and set presence status
3597 	 */
3598 	if (scsb->scsb_data_reg[index] & (1 << bit_num)) {
3599 		fru_ptr->fru_status = FRU_PRESENT;
3600 	} else {
3601 		fru_ptr->fru_status = FRU_NOT_PRESENT;
3602 	}
3603 	fru_ptr->fru_type = PRTM;
3604 	fru_ptr->fru_unit = (scsb_unum_t)unit;
3605 	fru_ptr->fru_id = fru_id_table[event_to_index(t)];
3606 	fru_ptr->fru_version = (fru_version_t)0;
3607 	fru_ptr->type_list = (fru_options_t *)NULL;
3608 	fru_ptr->i2c_info = (fru_i2c_info_t *)
3609 			kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP);
3610 	fru_ptr->i2c_info->syscfg_reg = syscfg;
3611 	fru_ptr->i2c_info->syscfg_bit = bit_num;
3612 	fru_ptr->i2c_info->ledata_reg = 0;
3613 	fru_ptr->i2c_info->ledata_bit = 0;
3614 	fru_ptr->i2c_info->blink_reg = 0;
3615 	fru_ptr->i2c_info->blink_bit = 0;
3616 	fru_ptr->next = (fru_info_t *)NULL;
3617 
3618 	scsb->scsb_state |= SCSB_TOPOLOGY;
3619 #ifdef DEBUG
3620 	mct_topology_dump(scsb, 0);
3621 #endif
3622 }
3623 
3624 /*ARGSUSED*/
3625 static void
3626 scsb_free_topology(scsb_state_t *scsb)
3627 {
3628 	int		i;
3629 	fru_info_t	*fru_ptr;
3630 
3631 	if (scsb_debug & 0x00100005)
3632 		cmn_err(CE_NOTE, "scsb_free_topology:");
3633 	for (i = 0; i < SCSB_UNIT_TYPES; ++i) {
3634 		fru_ptr = mct_system_info.fru_info_list[i];
3635 		while (fru_ptr != NULL) {
3636 			if (fru_ptr->i2c_info != (fru_i2c_info_t *)NULL)
3637 				kmem_free(fru_ptr->i2c_info,
3638 						sizeof (fru_i2c_info_t));
3639 			fru_ptr = fru_ptr->next;
3640 		}
3641 		if ((fru_ptr = mct_system_info.fru_info_list[i]) !=
3642 				(fru_info_t *)NULL) {
3643 			kmem_free(fru_ptr, sizeof (fru_info_t) *
3644 					mct_system_info.max_units[i]);
3645 			mct_system_info.fru_info_list[i] = (fru_info_t *)NULL;
3646 		}
3647 	}
3648 }
3649 
3650 #ifdef DEBUG
3651 static void
3652 mct_topology_dump(scsb_state_t *scsb, int force)
3653 {
3654 	int		i;
3655 	fru_info_t	*fru_ptr;
3656 
3657 	if (!force && !(scsb_debug & 0x00200000))
3658 		return;
3659 	if (force && !(scsb->scsb_state & (SCSB_DIAGS_MODE | SCSB_DEBUG_MODE)))
3660 		return;
3661 	if (!(scsb->scsb_state & SCSB_TOPOLOGY)) {
3662 		cmn_err(CE_NOTE, "mct_topology_dump: Topology not set!");
3663 		return;
3664 	}
3665 	for (i = 0; i < SCSB_UNIT_TYPES; ++i) {
3666 		fru_ptr = mct_system_info.fru_info_list[i];
3667 		switch ((scsb_utype_t)i) {
3668 		case SLOT:
3669 			cmn_err(CE_NOTE, "MCT: Number of Slots: %d",
3670 					mct_system_info.max_units[SLOT]);
3671 			break;
3672 		case ALARM:
3673 			cmn_err(CE_NOTE, "MCT: MAX Number of Alarm Cards: %d",
3674 					mct_system_info.max_units[ALARM]);
3675 			break;
3676 		case DISK:
3677 			cmn_err(CE_NOTE, "MCT: MAX Number of SCSI Devices: %d",
3678 					mct_system_info.max_units[DISK]);
3679 			break;
3680 		case FAN:
3681 			cmn_err(CE_NOTE, "MCT: MAX Number of Fan Trays: %d",
3682 					mct_system_info.max_units[FAN]);
3683 			break;
3684 		case PDU:
3685 			cmn_err(CE_NOTE, "MCT: MAX Number of PDUs: %d",
3686 					mct_system_info.max_units[PDU]);
3687 			break;
3688 		case PS:
3689 			cmn_err(CE_NOTE,
3690 					"MCT: MAX Number of Power Supplies: %d",
3691 					mct_system_info.max_units[PS]);
3692 			break;
3693 		case SCB:
3694 			cmn_err(CE_NOTE, "MCT: MAX Number of SCBs: %d",
3695 					mct_system_info.max_units[SCB]);
3696 			break;
3697 		case SSB:
3698 			cmn_err(CE_NOTE, "MCT: MAX Number of SSBs: %d",
3699 					mct_system_info.max_units[SSB]);
3700 			break;
3701 		}
3702 		while (fru_ptr != NULL) {
3703 			if (fru_ptr->fru_status & FRU_PRESENT) {
3704 				cmn_err(CE_NOTE,
3705 					"MCT:   type=%d, unit=%d, id=0x%x, "
3706 					"version=0x%x",
3707 					fru_ptr->fru_type,
3708 					fru_ptr->fru_unit,
3709 					fru_ptr->fru_id,
3710 					fru_ptr->fru_version);
3711 			}
3712 			fru_ptr = fru_ptr->next;
3713 		}
3714 	}
3715 }
3716 
3717 /*
3718  * Sends an event when the system controller board I2C errors
3719  * exceed the threshold.
3720  */
3721 static void
3722 scsb_failing_event(scsb_state_t *scsb)
3723 {
3724 	uint32_t scsb_event_code = SCTRL_EVENT_SCB;
3725 
3726 	add_event_code(scsb, scsb_event_code);
3727 	(void) scsb_queue_ops(scsb, QPUT_INT32, 1, &scsb_event_code,
3728 				"scsb_intr");
3729 }
3730 #endif
3731 
3732 int
3733 scsb_read_bhealthy(scsb_state_t *scsb)
3734 {
3735 	int		error;
3736 	uchar_t		reg;
3737 	int		index;
3738 
3739 	if (scsb_debug & 0x8001) {
3740 		cmn_err(CE_NOTE, "scsb_read_bhealthy()");
3741 	}
3742 	reg = SCSB_REG_ADDR(SCTRL_BHLTHY_BASE);
3743 	index = SCSB_REG_INDEX(reg);
3744 	error = scsb_rdwr_register(scsb, I2C_WR_RD, reg,
3745 			SCTRL_BHLTHY_NUMREGS, &scsb->scsb_data_reg[index], 1);
3746 	return (error);
3747 }
3748 
3749 /*
3750  * Returns the health status of a slot
3751  */
3752 int
3753 scsb_read_slot_health(scsb_state_t *scsb, int pslotnum)
3754 {
3755 	int slotnum = tonga_psl_to_ssl(scsb, pslotnum);
3756 	return (scsb_fru_op(scsb, SLOT, slotnum,
3757 			SCTRL_BHLTHY_BASE, SCSB_FRU_OP_GET_BITVAL));
3758 }
3759 
3760 /*
3761  * DIAGNOSTIC and DEBUG only.
3762  * Called from ioctl command (SCSBIOC_BHEALTHY_GET)
3763  */
3764 int
3765 scsb_bhealthy_slot(scsb_state_t *scsb, scsb_uinfo_t *suip)
3766 {
3767 	int		error = 0;
3768 	int		base, code, unit_number;
3769 	uchar_t		reg;
3770 	int		index;
3771 
3772 	if (scsb->scsb_state & SCSB_FROZEN)
3773 		return (EAGAIN);
3774 
3775 	/* operation valid for slots only */
3776 	if (suip == NULL || suip->unit_type != SLOT) {
3777 		return (EINVAL);
3778 	}
3779 
3780 	if (scsb_debug & 0x8001)
3781 		cmn_err(CE_NOTE, "scsb_bhealthy_slot: slot %d",
3782 			suip->unit_number);
3783 	if (suip->unit_number > mct_system_info.max_units[SLOT]) {
3784 		return (EINVAL);
3785 	}
3786 	/*
3787 	 * Map 1.0 Tonga Slot Number, if necessary
3788 	 */
3789 	tonga_slotnum_check(scsb, suip);
3790 	base = SCTRL_BHLTHY_BASE;
3791 	code = FRU_UNIT_TO_EVCODE(suip->unit_type, suip->unit_number);
3792 	unit_number = FRU_OFFSET(code, base);
3793 	index = FRU_REG_INDEX(code, base);
3794 	reg = SCSB_REG_ADDR(index);
3795 	index = SCSB_REG_INDEX(reg);		/* shadow index */
3796 
3797 	if (scsb->scsb_state & SCSB_P10_PROM) {
3798 		error = scsb_read_bhealthy(scsb);
3799 	}
3800 	/* else shadow regs are updated by interrupt handler */
3801 	if (error == 0) {
3802 		if (scsb->scsb_data_reg[index] & (1 << unit_number))
3803 			suip->unit_state = ON;
3804 		else
3805 			suip->unit_state = OFF;
3806 	}
3807 	return (error);
3808 }
3809 
3810 /*
3811  * Called from HSC and ioctl command (SCSBIOC_RESET_UNIT)
3812  * to reset one specified slot
3813  */
3814 int
3815 scsb_reset_unit(scsb_state_t *scsb, scsb_uinfo_t *suip)
3816 {
3817 	int		error;
3818 	int		unit_number;
3819 	uchar_t		reg;
3820 	int		index, slotnum, reset_state;
3821 
3822 	if (scsb->scsb_state & SCSB_FROZEN)
3823 		return (EAGAIN);
3824 	if (scsb_debug & 0x8001) {
3825 		cmn_err(CE_NOTE, "scsb_reset_slot(%d): slot %d, state %d\n",
3826 			scsb->scsb_instance, suip->unit_number,
3827 			suip->unit_state);
3828 	}
3829 	if (suip->unit_type != ALARM && !(scsb->scsb_state &
3830 				(SCSB_DIAGS_MODE | SCSB_DEBUG_MODE))) {
3831 		return (EINVAL);
3832 	}
3833 	if (suip->unit_state != ON && suip->unit_state != OFF) {
3834 		return (EINVAL);
3835 	}
3836 	error = 0;
3837 	switch (suip->unit_type) {
3838 	case ALARM:
3839 	{
3840 		int	i, code;
3841 		if (suip->unit_number != 1)
3842 			return (EINVAL);
3843 		code = FRU_UNIT_TO_EVCODE(suip->unit_type, suip->unit_number);
3844 		unit_number = FRU_OFFSET(code, SCTRL_RESET_BASE);
3845 		i = ALARM_RESET_REG_INDEX(code, SCTRL_RESET_BASE);
3846 		reg = SCSB_REG_ADDR(i);
3847 		break;
3848 	}
3849 	case SLOT:
3850 		slotnum = suip->unit_number;
3851 		reset_state = (suip->unit_state == ON) ? SCSB_RESET_SLOT :
3852 			SCSB_UNRESET_SLOT;
3853 		if (scsb->scsb_state & SCSB_IS_TONGA) {
3854 			if (slotnum > TG_MAX_SLOTS ||
3855 				slotnum == SC_TG_CPU_SLOT) {
3856 				return (EINVAL);
3857 			}
3858 		} else {
3859 			if (slotnum > MC_MAX_SLOTS ||
3860 				slotnum == SC_MC_CPU_SLOT ||
3861 				(scsb->scsb_hsc_state & SCSB_HSC_CTC_PRES &&
3862 				slotnum == SC_MC_CTC_SLOT)) {
3863 				return (EINVAL);
3864 			}
3865 		}
3866 		return (scsb_reset_slot(scsb, slotnum, reset_state));
3867 	default:
3868 		return (EINVAL);
3869 	}
3870 	index = SCSB_REG_INDEX(reg);
3871 	mutex_enter(&scsb->scsb_mutex);
3872 	if (suip->unit_state == ON)
3873 		scsb->scsb_data_reg[index] |= (1 << unit_number);
3874 	else /* OFF */
3875 		scsb->scsb_data_reg[index] &= ~(1 << unit_number);
3876 	if ((error = scsb_rdwr_register(scsb, I2C_WR, reg, 1,
3877 					&scsb->scsb_data_reg[index], 0)) != 0) {
3878 		if (scsb_debug & 0x8002)
3879 			cmn_err(CE_WARN,
3880 				"scsb_leds: write failure to 0x%x", reg);
3881 		return (error);
3882 	}
3883 	mutex_exit(&scsb->scsb_mutex);
3884 	return (error);
3885 }
3886 
3887 /*
3888  * Diagnostic and DEBUG
3889  * This is a helper function for the helper ioctl to pretend that
3890  * scsb h/w is doing its job!!!
3891  */
3892 int
3893 scsb_slot_occupancy(scsb_state_t *scsb, scsb_uinfo_t *suip)
3894 {
3895 	int		error;
3896 	int		saved_unit_number;
3897 
3898 	if (!(scsb->scsb_state & (SCSB_DEBUG_MODE | SCSB_DIAGS_MODE)))
3899 		return (EACCES);
3900 	if (scsb->scsb_state & SCSB_FROZEN) {
3901 		return (EAGAIN);
3902 	}
3903 	error = 0;
3904 	switch (suip->unit_type) {
3905 	case ALARM:
3906 		if (suip->unit_number !=
3907 			(mct_system_info.fru_info_list[ALARM])->fru_unit) {
3908 			return (EINVAL);
3909 		}
3910 		break;
3911 
3912 	case SLOT:
3913 		/*
3914 		 * All slots are acceptable, except slots 11 & 12.
3915 		 */
3916 		if (suip->unit_number < 1 || suip->unit_number >
3917 				mct_system_info.max_units[ALARM]) {
3918 			error = EINVAL;
3919 			break;
3920 		}
3921 		/* Map 1.0 Tonga Slot Numbers if necessary */
3922 		saved_unit_number = suip->unit_number;
3923 		tonga_slotnum_check(scsb, suip);
3924 		break;
3925 
3926 	default:
3927 		error = EINVAL;
3928 		break;
3929 	}
3930 
3931 	if (error)
3932 		return (error);
3933 	if (suip->unit_state == ON) {
3934 		if (hsc_slot_occupancy(saved_unit_number, B_TRUE, 0, B_TRUE)
3935 									!= 0)
3936 			error = EFAULT;
3937 	} else {
3938 		if (hsc_slot_occupancy(saved_unit_number, B_FALSE, 0, B_FALSE)
3939 									!= 0)
3940 			error = EFAULT;
3941 	}
3942 
3943 	return (error);
3944 }
3945 
3946 static int
3947 scsb_clear_intptrs(scsb_state_t *scsb)
3948 {
3949 	int		i, error;
3950 	uchar_t		wbuf[SCTRL_MAX_GROUP_NUMREGS];
3951 	error = 0;
3952 	for (i = 1; i <= SCTRL_INTR_NUMREGS; ++i) {
3953 		wbuf[i] = 0xff;
3954 	}
3955 	if (error = scsb_rdwr_register(scsb, I2C_WR,
3956 				SCSB_REG_ADDR(SCTRL_INTSRC_BASE),
3957 				SCTRL_INTR_NUMREGS, wbuf, 1)) {
3958 		if (scsb_debug & 0x0402)
3959 			cmn_err(CE_NOTE, "scsb_clear_intptrs(): "
3960 					"write to 0x%x failed",
3961 					SCSB_REG_ADDR(SCTRL_INTSRC_BASE));
3962 	}
3963 	return (error);
3964 }
3965 
3966 static int
3967 scsb_setall_intmasks(scsb_state_t *scsb)
3968 {
3969 	int		error;
3970 	uchar_t		reg, wdata, rmask;
3971 	int		i;
3972 
3973 	/*
3974 	 * write loop for Interrupt Mask registers
3975 	 */
3976 	if (scsb_debug & 0x0401)
3977 		cmn_err(CE_NOTE, "setall_intmasks()");
3978 	error = 0;
3979 	rmask = 0;
3980 	wdata = 0xff;
3981 	reg = SCSB_REG_ADDR(SCTRL_INTMASK_BASE);
3982 	for (i = 0; i < SCTRL_MASK_NUMREGS; ++i, ++reg) {
3983 		if (error = scsb_write_mask(scsb, reg, rmask, wdata, 0)) {
3984 			if (scsb_debug & 0x0402)
3985 				cmn_err(CE_NOTE, "scsb_setall_intmasks: "
3986 					"write to 0x%x failed: %d", reg, error);
3987 			error = EIO;
3988 			break;
3989 		}
3990 	}
3991 	return (error);
3992 }
3993 
3994 
3995 /*
3996  * Clear Interrupt masks based on the FRUs that could be installed
3997  * for this particular topology, determined by the MidPlane ID
3998  * from SCTRL_SYSCFG registers
3999  *	case SCTRL_MPID_HALF:
4000  *		1 CPU, 1 AlarmCard, 1 SCB/SSB, 2 PS, 3 FAN, 3 SCSI, 8 Slots
4001  *	case SCTRL_MPID_QUARTER:
4002  *		1 CPU, 1 AlarmCard, 1 SCB/SSB, 1 PS, 2 FAN, 1 SCSI, 4 Slots
4003  *	case SCTRL_MPID_QUARTER_NODSK:
4004  *		1 CPU, 1 AlarmCard, 1 SCB/SSB, 1 PS, 2 FAN, 0 SCSI, 4 Slots
4005  */
4006 static int
4007 scsb_clear_intmasks(scsb_state_t *scsb)
4008 {
4009 	int		error;
4010 	uchar_t		msk_reg, reg, wdata, rmask;
4011 	uchar_t		mask_data[SCTRL_MAX_GROUP_NUMREGS];
4012 	int		tmp, idx, code, unit, offset, mbid;
4013 	scsb_utype_t    fru_type;
4014 	fru_info_t	*fru_ptr;
4015 
4016 	if (scsb->scsb_state & SCSB_FROZEN &&
4017 			!(scsb->scsb_state & SCSB_IN_INTR)) {
4018 		return (EAGAIN);
4019 	}
4020 	error = 0;
4021 	for (tmp = 0; tmp < SCTRL_MASK_NUMREGS; ++tmp)
4022 		mask_data[tmp] = 0;
4023 	msk_reg = SCSB_REG_ADDR(SCTRL_INTMASK_BASE);
4024 	mbid    = SCSB_REG_INDEX(msk_reg); /* the Mask Base Index Delta */
4025 	if (scsb_debug & 0x0400) {
4026 		cmn_err(CE_NOTE, "clear_intmasks: msk_reg=0x%x; mbid=%d",
4027 				msk_reg, mbid);
4028 	}
4029 	for (fru_type = 0; fru_type < SCSB_UNIT_TYPES; ++fru_type) {
4030 		if (fru_type == SCB)
4031 			continue;	/* handle below, 2 reg offsets */
4032 		fru_ptr = mct_system_info.fru_info_list[fru_type];
4033 		for (; fru_ptr != NULL; fru_ptr = fru_ptr->next) {
4034 			unit = fru_ptr->fru_unit;
4035 			code   = FRU_UNIT_TO_EVCODE(fru_type, unit);
4036 			offset = FRU_OFFSET(code, SCTRL_INTMSK_BASE);
4037 			reg    = FRU_REG_ADDR(code, SCTRL_INTMSK_BASE);
4038 			idx    = SCSB_REG_INDEX(reg);
4039 			tmp = idx - mbid;
4040 			mask_data[tmp] |= (1 << offset);
4041 			if (scsb_debug & 0x0400)
4042 				cmn_err(CE_NOTE,
4043 				"clear_intmasks:%d:%d: PRES mask[%d]:0x%x",
4044 					fru_type, unit, tmp, mask_data[tmp]);
4045 			if ((fru_type == SLOT) && (IS_SCB_P15)) {
4046 				/*
4047 				 * Unmask the corresponding Slot HLTHY mask
4048 				 * Use Slot bit and register offsets,
4049 				 *  but with SCTRL_INTMASK_HLTHY_BASE
4050 				 */
4051 				reg = FRU_REG_ADDR(code,
4052 						SCTRL_INTMASK_HLTHY_BASE);
4053 				idx = SCSB_REG_INDEX(reg);
4054 				tmp = idx - mbid;
4055 				mask_data[tmp] |= (1 << offset);
4056 				if (scsb_debug & 0x0400) {
4057 					cmn_err(CE_NOTE,
4058 				"clear_intmasks:Slot:%d: HLTHY mask[%d]:0x%x"
4059 				"; reg=0x%x, idx=%d, mbid=%d",
4060 						unit, tmp, mask_data[tmp],
4061 						reg, idx, mbid);
4062 				}
4063 			}
4064 		}
4065 	}
4066 	/*
4067 	 * Now unmask these non-fru interrupt events
4068 	 *	SCTRL_EVENT_PWRDWN	(almost normal)
4069 	 *	SCTRL_EVENT_REPLACE	(not used)
4070 	 *	SCTRL_EVENT_ALARM_INT	(not working in P0.6/P1.0)
4071 	 *	SCTRL_EVENT_SCB		(SCB 1.5 ONLY; plus SCB_INT_OFFSET)
4072 	 */
4073 	code   = SCTRL_EVENT_PWRDWN;
4074 	offset = FRU_OFFSET(code, SCTRL_INTMSK_BASE);
4075 	reg    = FRU_REG_ADDR(code, SCTRL_INTMSK_BASE);
4076 	idx    = SCSB_REG_INDEX(reg);
4077 	tmp = idx - mbid;
4078 	mask_data[tmp] |= (1 << offset);
4079 	if (IS_SCB_P15) {
4080 		code   = SCTRL_EVENT_SCB;
4081 		offset = FRU_OFFSET(code, SCTRL_INTMSK_BASE);
4082 		reg    = FRU_REG_ADDR(code, SCTRL_INTMSK_BASE) + SCB_INT_OFFSET;
4083 		idx    = SCSB_REG_INDEX(reg);
4084 		tmp = idx - mbid;
4085 		mask_data[tmp] |= (1 << offset);
4086 		code   = SCTRL_EVENT_ALARM_INT;
4087 		offset = FRU_OFFSET(code, SCTRL_INTMSK_BASE);
4088 		reg    = FRU_REG_ADDR(code, SCTRL_INTMSK_BASE);
4089 		idx    = SCSB_REG_INDEX(reg);
4090 		tmp = idx - mbid;
4091 		mask_data[tmp] |= (1 << offset);
4092 	}
4093 	for (tmp = 0; tmp < SCTRL_MASK_NUMREGS; ++tmp) {
4094 		rmask = 0;
4095 		wdata = mask_data[tmp];
4096 		if (scsb_debug & 0x0400)
4097 			cmn_err(CE_NOTE, "clear_intmasks:0x%x: ~(0x%x),0x%x",
4098 					msk_reg, (~wdata) & 0xff, wdata);
4099 		mutex_enter(&scsb->scsb_mutex);
4100 		if (error = scsb_write_mask(scsb, msk_reg, rmask,
4101 						(~wdata) & 0xff, wdata)) {
4102 			mutex_exit(&scsb->scsb_mutex);
4103 			if (scsb_debug & 0x0402)
4104 				cmn_err(CE_NOTE, "scsb_clear_intmasks: "
4105 						"write to 0x%x failed: %d",
4106 						msk_reg, error);
4107 			error = EIO;
4108 			break;
4109 		}
4110 		mutex_exit(&scsb->scsb_mutex);
4111 		++msk_reg;
4112 	}
4113 	return (error);
4114 }
4115 
4116 static int
4117 scsb_get_status(scsb_state_t *scsb, scsb_status_t *smp)
4118 {
4119 	register int 	i;
4120 
4121 	if (smp == NULL) {
4122 		return (EFAULT);
4123 	}
4124 	if (scsb_debug & 0x40000000 &&
4125 			(scsb->scsb_state & SCSB_DEBUG_MODE ||
4126 			scsb->scsb_state & SCSB_DIAGS_MODE)) {
4127 		if (scsb->scsb_state & SCSB_FROZEN) {
4128 			return (EAGAIN);
4129 		}
4130 		mutex_enter(&scsb->scsb_mutex);
4131 		if (scsb_debug & 0x80000000) {
4132 			if ((i = scsb_readall_regs(scsb)) != 0 &&
4133 					scsb->scsb_state & SCSB_DEBUG_MODE)
4134 				cmn_err(CE_WARN, "scsb_get_status: "
4135 						"scsb_readall_regs() FAILED");
4136 		} else {
4137 			if ((i = scsb_check_config_status(scsb)) == 0) {
4138 				i = scsb_set_scfg_pres_leds(scsb, NULL);
4139 			}
4140 		}
4141 		mutex_exit(&scsb->scsb_mutex);
4142 		if (i) {
4143 			cmn_err(CE_WARN,
4144 				"scsb_get_status: FAILED Presence LEDs update");
4145 			return (EIO);
4146 		}
4147 	}
4148 	for (i = 0; i < SCSB_DATA_REGISTERS; ++i)
4149 		smp->scsb_reg[i] = scsb->scsb_data_reg[i];
4150 	return (0);
4151 }
4152 
4153 /*
4154  * scsb_freeze_check:
4155  *	Turn all the leds off on the system monitor card, without changing
4156  *	the state of what we have for scsb. This routine is called only when
4157  *	replacing system monitor card, so the state of the card leds could be
4158  *	restored, using scsb_restore().
4159  *	Also, set state to SCSB_FROZEN which denies access to scsb while in
4160  *	freeze mode.
4161  */
4162 static char  *BAD_BOARD_MSG =
4163 	"SCSB: Should NOT remove SCB(%d) while cPCI Slot %d is "
4164 	"in RESET with a possible bad board.";
4165 static int	slots_in_reset[SCTRL_MAX_GROUP_NUMREGS];
4166 
4167 static void
4168 scsb_freeze_check(scsb_state_t *scsb)
4169 {
4170 	register int	i;
4171 	int		offset;
4172 	int		unit, slotnum;
4173 	int		index;
4174 	fru_info_t	*fru_ptr;
4175 	uint32_t	code;
4176 	uchar_t		reg;
4177 
4178 	if (scsb_debug & 0x20001)
4179 		cmn_err(CE_NOTE, "scsb_freeze_check(%d):", scsb->scsb_instance);
4180 
4181 	if (scsb->scsb_state & SCSB_FROZEN) {
4182 		return;
4183 	}
4184 	mutex_enter(&scsb->scsb_mutex);
4185 	for (i = 0; i < SCTRL_MAX_GROUP_NUMREGS; ++i)
4186 		slots_in_reset[i] = 0;
4187 	/*
4188 	 * We allow the SCB to be removed only if none of
4189 	 * the cPCI resets are asserted for occupied slots.
4190 	 * There shouldn't be a bad board plugged in the system
4191 	 * while swapping the SCB.
4192 	 */
4193 	fru_ptr = mct_system_info.fru_info_list[SLOT];
4194 	for (unit = 1; unit <= mct_system_info.max_units[SLOT]; ++unit) {
4195 		if (IS_SCB_P15) {
4196 			slotnum = tonga_psl_to_ssl(scsb, unit);
4197 		} else {
4198 			slotnum = unit;
4199 		}
4200 		code = FRU_UNIT_TO_EVCODE(SLOT, slotnum);
4201 		offset = FRU_OFFSET(code, SCTRL_RESET_BASE);
4202 		reg = FRU_REG_ADDR(code, SCTRL_RESET_BASE);
4203 		index = SCSB_REG_INDEX(reg);
4204 		if (scsb->scsb_data_reg[index] & (1 << offset)) {
4205 			if (fru_ptr[unit - 1].fru_status == FRU_PRESENT) {
4206 				slots_in_reset[unit - 1] = unit;
4207 				cmn_err(CE_NOTE, BAD_BOARD_MSG,
4208 						scsb->scsb_instance, unit);
4209 			}
4210 		}
4211 	}
4212 	mutex_exit(&scsb->scsb_mutex);
4213 }
4214 
4215 static void
4216 scsb_freeze(scsb_state_t *scsb)
4217 {
4218 	uint32_t	code;
4219 	if (scsb_debug & 0x00020002) {
4220 		cmn_err(CE_WARN, "scsb_freeze: SCB%d possibly removed",
4221 					scsb->scsb_instance);
4222 	}
4223 	if (scsb->scsb_state & SCSB_FROZEN)
4224 		return;
4225 	scsb->scsb_state |= SCSB_FROZEN;
4226 	scsb->scsb_state &= ~SCSB_SCB_PRESENT;
4227 	scsb_hsc_freeze(scsb->scsb_dev);
4228 	/*
4229 	 * Send the EVENT_SCB since there is evidence that the
4230 	 * System Controller Board has been removed.
4231 	 */
4232 	code = SCTRL_EVENT_SCB;
4233 	if (!(scsb->scsb_state & SCSB_IN_INTR))
4234 		scsb_event_code = code;
4235 	check_fru_info(scsb, code);
4236 	add_event_code(scsb, code);
4237 	(void) scsb_queue_ops(scsb, QPUT_INT32, 1, &code, "scsb_freeze");
4238 }
4239 
4240 /*
4241  * scsb_restore will only be called from the interrupt handler context on
4242  * INIT_SCB interrupt for newly inserted SCB.
4243  * Called with mutex held.
4244  */
4245 static void
4246 scsb_restore(scsb_state_t *scsb)
4247 {
4248 	if (scsb_debug & 0x20001)
4249 		cmn_err(CE_NOTE, "scsb_restore(%d):", scsb->scsb_instance);
4250 
4251 	if (initialize_scb(scsb) != DDI_SUCCESS) {
4252 		if (scsb_debug & 0x00020002) {
4253 			cmn_err(CE_WARN, "scsb_restore: INIT Failed");
4254 		return;
4255 		}
4256 	}
4257 	/* 9. Clear all Interrupts */
4258 	if (scsb_clear_intmasks(scsb)) {
4259 		cmn_err(CE_WARN,
4260 			"scsb%d: I2C TRANSFER Failed", scsb->scsb_instance);
4261 		if (scsb_debug & 0x00020002) {
4262 			cmn_err(CE_WARN, "scsb_restore: clear_intmasks Failed");
4263 		}
4264 		return;
4265 	}
4266 
4267 	/* 10. */
4268 	/* Check if Alarm Card present at boot and set flags */
4269 	if (scsb_fru_op(scsb, ALARM, 1, SCTRL_SYSCFG_BASE,
4270 					SCSB_FRU_OP_GET_BITVAL))
4271 		scsb->scsb_hsc_state |= SCSB_ALARM_CARD_PRES;
4272 	else
4273 		scsb->scsb_hsc_state &= ~SCSB_ALARM_CARD_PRES;
4274 
4275 	scsb->scsb_state &= ~SCSB_FROZEN;
4276 	(void) scsb_hsc_restore(scsb->scsb_dev);
4277 }
4278 
4279 /*
4280  * Given an Event Code,
4281  * Return:
4282  *	FRU type    in LSByte
4283  *	unit number in MSByte
4284  */
4285 uint16_t
4286 event_to_type(uint32_t evcode)
4287 {
4288 	int		i, li, unit;
4289 	uint32_t	ec;
4290 	uint16_t	ret;
4291 	for (i = li = 0; i < SCSB_UNIT_TYPES; ++i) {
4292 		if (evcode == type_to_code1[i]) {
4293 			ret = (uint16_t)(0x0100 | i);
4294 			return (ret);
4295 		}
4296 		if (evcode < type_to_code1[i]) {
4297 			unit = 1;
4298 			ec = type_to_code1[li];
4299 			while (ec < evcode)
4300 				ec = ec << 1, ++unit;
4301 			ret = (unit << 8) | li;
4302 			return (ret);
4303 		}
4304 		li = i;
4305 	}
4306 	return ((uint16_t)0xffff);
4307 }
4308 
4309 /*
4310  * scsb interrupt handler for (MC) PSM_INT vector
4311  * P0.6: HW shipped to beta customers
4312  *	1. did not have Slot Occupant Presense support
4313  *	2. I2C interrupt-map properties not yet tested, using polling daemon
4314  *	3. Polling detects each event reliably twice.
4315  *	   clr_bits# are used to keep track of events to be ignored 2nd time
4316  *
4317  * retval flags allow all events to be checked, and still returning the
4318  * correct DDI value.
4319  *
4320  */
4321 #define	SCSB_INTR_CLAIMED	1
4322 #define	SCSB_INTR_UNCLAIMED	2
4323 #define	SCSB_INTR_EVENT		4
4324 
4325 /*
4326  * Does preprocessing of the interrupt. The only thing this
4327  * needs to do is to ask scsb to release the interrupt line.
4328  * and then schedule delayed actual processing using timeout()
4329  */
4330 uint_t
4331 scsb_intr_preprocess(caddr_t arg)
4332 {
4333 	scsb_state_t	*scsb = (scsb_state_t *)arg;
4334 
4335 	scb_pre_s = gethrtime();
4336 
4337 	/*
4338 	 * If SCSB_IN_INTR is already set in scsb_state,
4339 	 * it means we are being interrupted by someone else. This can
4340 	 * happen only if the interrupt does not belong to scsb, and some
4341 	 * other device, e.g. a FAN or PS is interrupting. So, we
4342 	 * cancel the previous timeout().
4343 	 */
4344 
4345 	if (scsb->scsb_state & SCSB_IN_INTR) {
4346 		untimeout(scsb_intr_tid);
4347 		scsb_invoke_intr_chain();
4348 		scsb_toggle_psmint(scsb, 1);
4349 		scsb->scsb_state &= ~SCSB_IN_INTR;
4350 		goto intr_end;
4351 	}
4352 	scsb->scsb_state |= SCSB_IN_INTR;
4353 
4354 	/*
4355 	 * Stop scsb from interrupting first.
4356 	 */
4357 	if (scsb_quiesce_psmint(scsb) != DDI_SUCCESS) {
4358 		goto intr_end;
4359 	}
4360 
4361 	/*
4362 	 * Schedule a timeout to actually process the
4363 	 * interrupt.
4364 	 */
4365 	scsb_intr_tid = timeout((void (*)(void *))scsb_intr, arg,
4366 					drv_usectohz(1000));
4367 
4368 intr_end:
4369 
4370 	scb_pre_e = gethrtime();
4371 	return (DDI_INTR_CLAIMED);
4372 }
4373 
4374 static void scsb_healthy_intr(scsb_state_t *scsb, int pslotnum);
4375 void
4376 scsb_intr(caddr_t arg)
4377 {
4378 	scsb_state_t	*scsb = (scsb_state_t *)arg;
4379 	int		i, idx, offset, unit, numregs, error;
4380 	int		intr_idx, index, offset_base, retval, slotnum, val;
4381 	uint32_t	code;
4382 	uchar_t		intr_reg, tmp_reg, intr_addr, clr_bits = 0;
4383 	uchar_t		ac_slot = B_FALSE;
4384 	uchar_t		*int_masks;
4385 	uchar_t		cstatus_regs[SCTRL_MAX_GROUP_NUMREGS];
4386 	scsb_utype_t	fru_type;
4387 	fru_info_t	*fru_ptr;
4388 	int		ac_present;
4389 
4390 	/*
4391 	 * Avoid mayhem, make sure we have only one timeout thread running.
4392 	 */
4393 	mutex_enter(&scsb->scsb_mutex);
4394 	while (scsb_in_postintr)
4395 		cv_wait(&scsb->scsb_cv, &scsb->scsb_mutex);
4396 	scsb_in_postintr = 1;
4397 	mutex_exit(&scsb->scsb_mutex);
4398 
4399 	scb_post_s = gethrtime();
4400 	if (scsb_debug & 0x00002000)
4401 		cmn_err(CE_NOTE, "scsb_intr(%d)", scsb->scsb_instance);
4402 	retval = 0;
4403 	tmp_reg = 0;
4404 	/*
4405 	 * XXX: Problem, when we want to support swapping between SCB
4406 	 * versions, then we need to check the SCB PROM ID (CF) register here
4407 	 * before assuming the same SCB version was re-inserted.
4408 	 * We will have to duplicate some of the scb_initialization()
4409 	 * code to set the scsb_state PROM ID bits and to set up the
4410 	 * register table pointers.
4411 	 *
4412 	 * Only if NOT SSB_PRESENT, check the SCB PROM ID
4413 	 */
4414 	if (!(scsb->scsb_state & SCSB_SSB_PRESENT)) {
4415 		if (scb_check_version(scsb) != DDI_SUCCESS) {
4416 #ifdef DEBUG
4417 			if (scsb->scsb_state & SCSB_SSB_PRESENT &&
4418 				scsb->scsb_i2c_errcnt > scsb_err_threshold)
4419 				scsb_failing_event(scsb);
4420 #endif
4421 			goto intr_error;
4422 		}
4423 	}
4424 	if (IS_SCB_P15) {
4425 		int_masks = scb_15_int_masks;
4426 	} else {
4427 		int_masks = scb_10_int_masks;
4428 	}
4429 	/*
4430 	 * Now check the INTSRC registers for set bits.
4431 	 * Do a quick check by OR'ing INTSRC registers together as we copy
4432 	 * them from the transfer buffer. For P1.0 or earlier we had already
4433 	 * read the interrupt source registers and wrote them back to stop
4434 	 * interrupt. So we need to do this step only for P1.5 or later.
4435 	 * We already read INTSRC6 to take care of SCB insertion case, so
4436 	 * do not read INTSRC6 again.
4437 	 */
4438 
4439 	if (IS_SCB_P15) {
4440 		intr_addr = SCSB_REG_ADDR(SCTRL_INTSRC_BASE);
4441 		/* read the interrupt register from scsb */
4442 		if (scsb_rdwr_register(scsb, I2C_WR_RD, intr_addr,
4443 				SCTRL_INTR_NUMREGS - 1, scb_intr_regs, 1)) {
4444 			cmn_err(CE_WARN, "scsb_intr: "
4445 				" Failed read of interrupt registers.");
4446 #ifdef DEBUG
4447 			if (scsb->scsb_state & SCSB_SSB_PRESENT &&
4448 				scsb->scsb_i2c_errcnt > scsb_err_threshold)
4449 				scsb_failing_event(scsb);
4450 #endif
4451 			goto intr_error;
4452 		}
4453 	}
4454 
4455 	/*
4456 	 * We have seen that an interrupt source bit can be set
4457 	 * even though the corresponding interrupt mask bit
4458 	 * has been set to mask the interrupt. So we must
4459 	 * clear all bits set in the interrupt source register.
4460 	 */
4461 	for (i = 0; i < SCTRL_INTR_NUMREGS; ++i) {
4462 		retval |= scb_intr_regs[i];		/* Quick INTSRC check */
4463 #ifdef DEBUG
4464 		if (scsb_debug & 0x08000000) {
4465 			if (tmp_reg || scb_intr_regs[i]) {
4466 				cmn_err(CE_NOTE, "scsb_intr: INTSRC%d=0x%x",
4467 					i + 1, scb_intr_regs[i]);
4468 				++tmp_reg;
4469 			}
4470 		}
4471 #endif
4472 	}
4473 	/*
4474 	 * Any bits from quick check? If this is not our interrupt,
4475 	 * something is wrong. FAN/PS interrupts are supposed to be
4476 	 * blocked, but we can not be sure. So, go ahead and call the
4477 	 * emergency interrupt handlers for FAN/PS devices and mask
4478 	 * their interrupts, if they aren't already masked.
4479 	 */
4480 	if (retval == 0) {
4481 		goto intr_error;
4482 	}
4483 
4484 	retval = 0;
4485 
4486 	/*
4487 	 * If SCB 1.5 or 2.0, check for the INIT_SCB Interrupt
4488 	 * to support Hot SCB Insertion.
4489 	 * The check was moved here during debugging of the SCB hot insertion.
4490 	 * Theoretically, this code could be moved back to the check for
4491 	 * SCTRL_EVENT_SCB in the processing loop below.
4492 	 */
4493 	if (IS_SCB_P15) {
4494 		int	iid;
4495 		iid = SCSB_REG_INDEX(intr_addr);
4496 		offset = FRU_OFFSET(SCTRL_EVENT_SCB, SCTRL_INTPTR_BASE);
4497 		tmp_reg = SCSB_REG_ADDR(SCTRL_INTSRC_SCB_P15);
4498 		intr_idx = SCSB_REG_INDEX(tmp_reg) - iid;
4499 		clr_bits = 1 << offset;
4500 		if (scb_intr_regs[intr_idx] & clr_bits) {
4501 			/*
4502 			 * Must be newly inserted SCB
4503 			 * Time to re-initialize.
4504 			 */
4505 			if (scsb_debug & 0x00023000) {
4506 				cmn_err(CE_NOTE,
4507 					"scsb_intr(%d): INIT_SCB INT",
4508 					scsb->scsb_instance);
4509 			}
4510 			scsb_restore(scsb);
4511 			retval |= (SCSB_INTR_CLAIMED | SCSB_INTR_EVENT);
4512 			/*
4513 			 * The INTSRC bit will be cleared by the
4514 			 * scsb_restore() function.
4515 			 * Also, leave the bit set in scb_intr_regs[] so we can
4516 			 * report the event code as we check for other
4517 			 * interrupt source bits.
4518 			 *
4519 			 * scsb_write_mask(scsb, tmp_reg, 0, clr_bits, 0);
4520 			 * scb_intr_regs[intr_idx] &= ~clr_bits;
4521 			 */
4522 		}
4523 		/*
4524 		 * In case this is a power down interrupt, check the validity
4525 		 * of the request to make sure it's not an I2C noise
4526 		 */
4527 		offset = FRU_OFFSET(SCTRL_EVENT_PWRDWN,
4528 				SCTRL_INTPTR_BASE);
4529 		clr_bits = 1 << offset;
4530 		intr_reg = scb_intr_regs[intr_idx];
4531 		if (intr_reg & clr_bits) {
4532 			/*
4533 			 * A shutdown request has been detected. Poll
4534 			 * the corresponding register ? more times to
4535 			 * make sure it's a genuine shutdown request.
4536 			 */
4537 			for (i = 0; i < scsb_shutdown_count; i++) {
4538 				drv_usecwait(1000);
4539 				if (scsb_rdwr_register(scsb, I2C_WR_RD, tmp_reg,
4540 						1, &intr_reg, 1)) {
4541 					cmn_err(CE_WARN, "Failed to read "
4542 						" interrupt register");
4543 					goto intr_error;
4544 				}
4545 				if (scsb_debug & 0x08000000) {
4546 					cmn_err(CE_NOTE, "scsb_intr: "
4547 						" INTSRC6[%d]=0x%x", i,
4548 						intr_reg);
4549 				}
4550 				if (!(intr_reg & clr_bits)) {
4551 					scb_intr_regs[intr_idx] &= ~clr_bits;
4552 					break;
4553 				}
4554 			}
4555 		}
4556 	}
4557 	/*
4558 	 * if retval == 0, then we didn't call scsb_restore,
4559 	 * so we update the shadow copy of SYSCFG registers
4560 	 * We *MUST* read the syscfg registers before any attempt
4561 	 * to clear the interrupt source registers is made.
4562 	 */
4563 	if (retval == 0 && scsb_check_config_status(scsb)) {
4564 		cmn_err(CE_WARN,
4565 			"scsb_intr: Failed read of config/status registers");
4566 		if (scsb->scsb_state & SCSB_P06_NOINT_KLUGE) {
4567 			if (!scsb_debug) {
4568 				goto intr_error;
4569 			}
4570 		}
4571 #ifdef DEBUG
4572 		if (scsb->scsb_state & SCSB_SSB_PRESENT &&
4573 			scsb->scsb_i2c_errcnt > scsb_err_threshold) {
4574 			scsb_failing_event(scsb);
4575 		}
4576 #endif
4577 		/*
4578 		 * Allow to go on so we clear the INTSRC bits
4579 		 */
4580 	}
4581 
4582 	/*
4583 	 * Read the board healthy registers here, if any of the healthy
4584 	 * interrupts are set.
4585 	 */
4586 	if (IS_SCB_P15) {
4587 		intr_idx = intr_reg = 0;
4588 		intr_addr = SCSB_REG_ADDR(SCTRL_INTSRC_BASE);
4589 		index = SCSB_REG_INDEX(intr_addr);
4590 		for (i = 0; i < SCTRL_BHLTHY_NUMREGS; ++i, ++intr_idx) {
4591 			scsb->scsb_data_reg[index++] =
4592 				scb_intr_regs[intr_idx] & int_masks[intr_idx];
4593 			intr_reg |= scb_intr_regs[i];
4594 		}
4595 
4596 		if (intr_reg &&	scsb_read_bhealthy(scsb) != 0) {
4597 			cmn_err(CE_WARN, "%s#%d: Error Reading Healthy# "
4598 				" Registers", ddi_driver_name(scsb->scsb_dev),
4599 				ddi_get_instance(scsb->scsb_dev));
4600 #ifdef DEBUG
4601 			if (scsb->scsb_state & SCSB_SSB_PRESENT &&
4602 				scsb->scsb_i2c_errcnt > scsb_err_threshold) {
4603 				scsb_failing_event(scsb);
4604 			}
4605 #endif
4606 			goto intr_error;
4607 		}
4608 	}
4609 
4610 	/*
4611 	 * We clear the interrupt source registers now itself so that
4612 	 * future interrupts can be latched quickly, instead of after
4613 	 * finishing processing of all interrupt conditions. The global
4614 	 * interrupt mask however remain disabled.
4615 	 */
4616 	if (IS_SCB_P15) {
4617 		if (scsb_rdwr_register(scsb, I2C_WR, intr_addr,
4618 			SCTRL_INTR_NUMREGS, scb_intr_regs, 1)) {
4619 			cmn_err(CE_WARN, "scsb_intr: Failed write to interrupt"
4620 					" registers.");
4621 #ifdef DEBUG
4622 			if (scsb->scsb_state & SCSB_SSB_PRESENT &&
4623 				scsb->scsb_i2c_errcnt > scsb_err_threshold) {
4624 				scsb_failing_event(scsb);
4625 			}
4626 #endif
4627 			goto intr_error;
4628 		}
4629 	}
4630 
4631 	/*
4632 	 * At this point, all interrupt source registers are read.
4633 	 * We only handle interrups which are not masked
4634 	 */
4635 	for (i = 0; i < SCTRL_INTR_NUMREGS; ++i) {
4636 		scb_intr_regs[i] &= int_masks[i];
4637 	}
4638 
4639 	/*
4640 	 * We are here means that there was some bit set in the interrupt
4641 	 * source register. So we must claim the interrupt no matter
4642 	 * whatever error we may encounter in the course of processing.
4643 	 */
4644 	retval |= SCSB_INTR_CLAIMED;
4645 
4646 	/* store config status data */
4647 	tmp_reg = SCSB_REG_ADDR(SCTRL_SYSCFG_BASE);
4648 	index = SCSB_REG_INDEX(tmp_reg);
4649 	for (i = 0; i < SCTRL_CFG_NUMREGS; ++i)
4650 		cstatus_regs[i] = scsb->scsb_data_reg[index + i];
4651 	/*
4652 	 * Clear the event code,
4653 	 * then check to see what kind(s) of events we were interrupted for.
4654 	 * Check all SCTRL_INTSRC registers
4655 	 */
4656 	scsb_event_code = 0;
4657 	clr_bits = 0;
4658 	intr_idx = 0;
4659 	numregs = SCTRL_INTR_NUMREGS;
4660 	index = SCSB_REG_INDEX(intr_addr);
4661 	/*
4662 	 * If SCB 1.5, adjust some variables to skip the SCTRL_BHLTHY_REGS
4663 	 * which will be handled last in this function.
4664 	 */
4665 	if (IS_SCB_P15) {
4666 		i = SCTRL_BHLTHY_NUMREGS;
4667 		intr_idx += i;
4668 		intr_addr += i;
4669 		index += i;
4670 	}
4671 	/*
4672 	 * For the rest of the INTSRC registers, we walk through the
4673 	 * scb_fru_offset[] table, matching register offsets with our offset
4674 	 * counter.  Then we check for the scb_fru_offset[] bit in intr_reg.
4675 	 * The scb_fru_offset[] index is now the SCTRL_EVENT code.
4676 	 * The code is then compared to type_to_code1[] entries to find the
4677 	 * fru_type.  The fru_type will help us recognize when to do
4678 	 * SLOT Hot Swap processing.
4679 	 *
4680 	 * offset_base:		the appropriate scb_fru_offset[] base index
4681 	 *			for the INTPTR_BASE register group
4682 	 * offset:		bit offset found in INTSRC register
4683 	 * intr_idx:		index to temporary INTSRC register copies
4684 	 * intr:		modified copy of current INTR register
4685 	 * intr_addr:		SCB register address of current INTR register
4686 	 * index:		index to current INTR shadow register
4687 	 * idx:			bit-number of current INTR event bit
4688 	 * uc:			uchar_t from scb_fru_offset[] table,
4689 	 *			containing register and FRU offsets.
4690 	 * j:			used to walk fru_offset[] table, which is also
4691 	 *			the bit-number of the current event code
4692 	 * code:		manufactured event code for current INT event
4693 	 */
4694 	offset_base = FRU_OFFSET_BASE(SCTRL_INTPTR_BASE);
4695 	for (offset = 0; intr_idx < numregs;
4696 				++offset, ++intr_idx, ++intr_addr, ++index) {
4697 		scsb->scsb_data_reg[index] = scb_intr_regs[intr_idx];
4698 		intr_reg = scb_intr_regs[intr_idx];
4699 		while (intr_reg) {	/* for each INTSRC bit that's set */
4700 			int		j;
4701 			uint16_t	ui;
4702 			uchar_t		uc;
4703 			idx = event_to_index((uint32_t)intr_reg); /* offset */
4704 			code = (1 << idx);		/* back to bit mask */
4705 			clr_bits |= code;
4706 			intr_reg = intr_reg & ~code;	/* clear this one   */
4707 			for (j = 0; j < MCT_MAX_FRUS; ++j) {
4708 				/*
4709 				 * Get register offset from table and check
4710 				 * for a match with our loop offset counter.
4711 				 * Then check for intr_reg bit-offset match
4712 				 * with bit-offset from table entry.
4713 				 */
4714 				uc = scb_fru_offset[offset_base + j];
4715 				if (offset != ((uc >> 4) & 0xf)) {
4716 					if (IS_SCB_P10)
4717 						continue;
4718 					if (j != FRU_INDEX(SCTRL_EVENT_SCB))
4719 						continue;
4720 					if (offset != ((uc >> 4) & 0xf)
4721 							+ SCB_INT_OFFSET)
4722 						continue;
4723 				}
4724 				if (idx == (uc & 0xf))
4725 					break;
4726 			}
4727 			if (uc == 0xff) {
4728 				/*
4729 				 * bit idx not recognized, check another.
4730 				 */
4731 				continue;
4732 			}
4733 			/*
4734 			 * We found the fru_offset[] entry, now use the index
4735 			 * to get the event code.
4736 			 */
4737 			code = (uint32_t)(1 << j);
4738 			if (scsb_debug & 0x00002000) {
4739 				cmn_err(CE_NOTE, "scsb_intr: code=0x%x", code);
4740 			}
4741 			/*
4742 			 * Now check for the NON-FRU type events.
4743 			 */
4744 			if (code ==  SCTRL_EVENT_PWRDWN) {
4745 				if (scsb_debug & 0x1002) {
4746 					cmn_err(CE_NOTE,
4747 						"scsb_intr(%d): power down req."
4748 						" INT.", scsb->scsb_instance);
4749 				}
4750 				scsb_event_code |= code;
4751 				if (scsb->scsb_state & SCSB_OPEN &&
4752 					scsb->scsb_rq != (queue_t *)NULL) {
4753 					/*
4754 					 * inform applications using poll(2)
4755 					 * about this event, and provide the
4756 					 * event code to EnvMon scsb policy
4757 					 */
4758 					if (!(scsb_debug & 0x00040000))
4759 					(void) scsb_queue_put(scsb->scsb_rq, 1,
4760 						&scsb_event_code, "scsb_intr");
4761 					goto intr_error;
4762 				}
4763 				continue;
4764 			} else if (code == SCTRL_EVENT_REPLACE) {
4765 				if (scsb_debug & 0x1002) {
4766 					cmn_err(CE_NOTE,
4767 						"scsb_intr(%d): replacement "
4768 						"req. INT.",
4769 						scsb->scsb_instance);
4770 				}
4771 				scsb_freeze_check(scsb);
4772 				scsb_freeze(scsb);
4773 				scsb_event_code |= code;
4774 				retval |= (SCSB_INTR_CLAIMED | SCSB_INTR_EVENT);
4775 				continue;
4776 			} else if (code == SCTRL_EVENT_SCB) {
4777 				int	tmp;
4778 				/*
4779 				 * Must be newly inserted SCB
4780 				 * Time to re-initialize.
4781 				 */
4782 				if (scsb_debug & 0x1002) {
4783 					cmn_err(CE_NOTE,
4784 						"scsb_intr(%d): INIT SCB INTR",
4785 						scsb->scsb_instance);
4786 				}
4787 				/*
4788 				 * SCB initialization already handled, but we
4789 				 * set the event code bit here in order to
4790 				 * report the event to interested utilities.
4791 				 *
4792 				 * scsb_restore(scsb);
4793 				 * The INTSRC bit is already cleared,
4794 				 * so we won't do it again.
4795 				 */
4796 				tmp = FRU_OFFSET(SCTRL_EVENT_SCB,
4797 							SCTRL_INTPTR_BASE);
4798 				clr_bits &= ~(1 << tmp);
4799 				scsb_event_code |= code;
4800 				retval |= (SCSB_INTR_CLAIMED | SCSB_INTR_EVENT);
4801 				continue;
4802 			} else if (code == SCTRL_EVENT_ALARM_INT) {
4803 				/*
4804 				 * P0.6/P1.0: SCTRL_INTR_ALARM_INT is always
4805 				 * set and cannot be cleared, so ignore it.
4806 				 */
4807 				if (!IS_SCB_P15) {
4808 					continue;
4809 				}
4810 				if (scsb_debug & 0x1002) {
4811 					cmn_err(CE_NOTE,
4812 						"scsb_intr(%d): Alarm INT.",
4813 						scsb->scsb_instance);
4814 				}
4815 				scsb_event_code |= code;
4816 				retval |= (SCSB_INTR_CLAIMED | SCSB_INTR_EVENT);
4817 				/*
4818 				 * XXX:
4819 				 * Must service the Alarm INT by clearing INT
4820 				 * condition on Alarm Card,
4821 				 * then clear the SCTRL_INTR_ALARM_INT bit here.
4822 				 * Waiting for specs and test environment.
4823 				 */
4824 				continue;
4825 			} else if ((ui = event_to_type(code)) == 0xffff) {
4826 				/*
4827 				 * FRU type not found
4828 				 */
4829 				break;
4830 			}
4831 			/*
4832 			 * Check for special processing
4833 			 * now that we found the FRU type.
4834 			 */
4835 			fru_type = (scsb_utype_t)(ui & 0xff);
4836 			unit = (ui >> 8) & 0xff;
4837 			if (scsb_debug & 0x00002000) {
4838 				cmn_err(CE_NOTE, "scsb_intr: "
4839 						"FRU type/unit/code %d/%d/0x%x",
4840 						fru_type, unit, code);
4841 			}
4842 			switch (fru_type) {
4843 			case PDU:
4844 				break;
4845 			case PS:
4846 				break;
4847 			case DISK:
4848 				break;
4849 			case FAN:
4850 				break;
4851 			case SSB:
4852 				/*
4853 				 * in check_fru_info() below, we see if the
4854 				 * SSB has been removed, then check for
4855 				 * occupied slots in reset to see if we should
4856 				 * WARN agains SCB removal
4857 				 */
4858 				break;
4859 			case CFTM:
4860 				break;
4861 			case CRTM:
4862 				break;
4863 			case PRTM:
4864 				break;
4865 			case SLOT:
4866 				slotnum = tonga_ssl_to_psl(scsb, unit);
4867 				if (scsb_debug & 0x00002000) {
4868 					cmn_err(CE_NOTE, "scsb_intr: "
4869 							"unit/slot %d/%d",
4870 							unit, slotnum);
4871 				}
4872 
4873 				/*
4874 				 * If the slot number is not valid, continue.
4875 				 */
4876 				if (scsb->scsb_state & SCSB_IS_TONGA) {
4877 					if (slotnum > TG_MAX_SLOTS ||
4878 						slotnum == SC_TG_CPU_SLOT) {
4879 						continue;
4880 					}
4881 					/*
4882 					 * For a tonga, we need to return
4883 					 * the code corresponding to the
4884 					 * actual physical slot
4885 					 */
4886 					code = FRU_UNIT_TO_EVCODE(SLOT,
4887 						slotnum);
4888 				} else {
4889 					if (slotnum > MC_MAX_SLOTS ||
4890 						slotnum == SC_MC_CPU_SLOT ||
4891 						(scsb->scsb_hsc_state &
4892 						SCSB_HSC_CTC_PRES &&
4893 						slotnum == SC_MC_CTC_SLOT)) {
4894 						continue;
4895 					}
4896 				}
4897 			/* FALLTHROUGH */
4898 			case ALARM:
4899 		/*
4900 		 * INDENT CHEATING, 2 indentations
4901 		 */
4902 		ac_present = 0;
4903 		/*
4904 		 * If it is an Alarm Card Interrupt, we just do some sanity
4905 		 * checks and then wait for the slot interrupt to take
4906 		 * connect or disconnect action.
4907 		 * XXX - Is there a gaurantee that ALARM int will occur first ?
4908 		 */
4909 		if (fru_type == ALARM) {
4910 			DEBUG2("AC Intr %d(%d)\n", scsb->ac_slotnum, idx+1);
4911 			val = scsb_fru_op(scsb, SLOT,
4912 				tonga_ssl_to_psl(scsb, scsb->ac_slotnum),
4913 				SCTRL_SYSCFG_BASE, SCSB_FRU_OP_GET_BITVAL);
4914 			ac_present = scsb_fru_op(scsb, ALARM, 1,
4915 					SCTRL_SYSCFG_BASE,
4916 					SCSB_FRU_OP_GET_BITVAL);
4917 			/*
4918 			 * It is observed that slot presence and Alarm
4919 			 * presence bits do not go ON at the same time.
4920 			 * Hence we wait till both events happen.
4921 			 */
4922 #ifdef DEBUG
4923 			if ((((val) && (!ac_present)) ||
4924 					((!val) && (ac_present))) &&
4925 					(scsb->scsb_hsc_state &
4926 						SCSB_AC_SLOT_INTR_DONE))
4927 
4928 				cmn_err(CE_WARN, "?Alarm and Slot presence "
4929 					"state bits do not match! (%x,%x)",
4930 					val, ac_present);
4931 #endif
4932 			if (scsb->scsb_hsc_state & SCSB_AC_SLOT_INTR_DONE)
4933 				scsb->scsb_hsc_state &= ~SCSB_AC_SLOT_INTR_DONE;
4934 			else
4935 				scsb->scsb_hsc_state |= SCSB_AC_SLOT_INTR_DONE;
4936 			break;	/* we break and wait for slot interrupt. */
4937 		}
4938 
4939 		/*
4940 		 * cPCI slot interrupt event
4941 		 */
4942 		if (scsb->scsb_state & SCSB_IS_TONGA) {
4943 			if (slotnum > TG_MAX_SLOTS ||
4944 				slotnum == SC_TG_CPU_SLOT) {
4945 				continue;
4946 			}
4947 		} else {
4948 			if (slotnum > MC_MAX_SLOTS ||
4949 				slotnum == SC_MC_CPU_SLOT ||
4950 				(scsb->scsb_hsc_state & SCSB_HSC_CTC_PRES &&
4951 				slotnum == SC_MC_CTC_SLOT)) {
4952 				continue;
4953 			}
4954 		}
4955 		if (scsb_is_alarm_card_slot(scsb, slotnum) == B_TRUE) {
4956 			DEBUG2("AC slot Intr %d(%d)\n", slotnum, idx+1);
4957 			ac_slot = B_TRUE;
4958 		}
4959 		val = scsb_fru_op(scsb, SLOT, unit, SCTRL_SYSCFG_BASE,
4960 					SCSB_FRU_OP_GET_BITVAL);
4961 		if (ac_slot == B_TRUE) {
4962 			ac_present = scsb_fru_op(scsb, ALARM, 1,
4963 					SCTRL_SYSCFG_BASE,
4964 					SCSB_FRU_OP_GET_BITVAL);
4965 #ifdef DEBUG
4966 			if ((((val) && (!ac_present)) ||
4967 					((!val) && (ac_present))) &&
4968 					(scsb->scsb_hsc_state &
4969 						SCSB_AC_SLOT_INTR_DONE)) {
4970 
4971 				cmn_err(CE_WARN, "?Alarm and Slot presence "
4972 					"state bits do not match! (%x,%x)",
4973 					val, ac_present);
4974 			}
4975 #endif
4976 			if (scsb->scsb_hsc_state & SCSB_AC_SLOT_INTR_DONE)
4977 				scsb->scsb_hsc_state &= ~SCSB_AC_SLOT_INTR_DONE;
4978 			else
4979 				scsb->scsb_hsc_state |= SCSB_AC_SLOT_INTR_DONE;
4980 		}
4981 		if (val) {
4982 			if (ac_present) {
4983 				DEBUG1("AC insertion on slot %d!\n", slotnum);
4984 				if (scsb_debug & 0x00010000) {
4985 					cmn_err(CE_NOTE, "scsb_intr: "
4986 						    "AC_PRES slot %d", slotnum);
4987 				}
4988 				scsb->scsb_hsc_state |= SCSB_ALARM_CARD_PRES;
4989 			}
4990 #ifndef	lint
4991 			else
4992 				DEBUG1("IO Insertion on slot %d!\n", slotnum);
4993 #endif
4994 			/*
4995 			 * Special case : check MPID type.
4996 			 * If MC midplane type,
4997 			 * check to make sure the Alarm Card present
4998 			 * bit is ON. If not, this is a regular IO card.
4999 			 */
5000 			(void) scsb_connect_slot(scsb, slotnum, B_FALSE);
5001 		} else {
5002 			if ((ac_slot == B_TRUE) &&
5003 				(scsb->scsb_hsc_state & SCSB_ALARM_CARD_PRES)) {
5004 
5005 				DEBUG1("AC Removal on slot %d!\n", slotnum);
5006 #ifdef DEBUG
5007 				if (scsb_debug & 0x00010000) {
5008 					cmn_err(CE_NOTE, "scsb_intr: "
5009 							"!AC_PRES slot %d",
5010 							slotnum);
5011 				}
5012 #endif /* DEBUG */
5013 				scsb->scsb_hsc_state &= ~SCSB_ALARM_CARD_PRES;
5014 			}
5015 #ifndef	lint
5016 			else
5017 				DEBUG1("IO Removal on slot %d!\n", slotnum);
5018 #endif
5019 			(void) scsb_disconnect_slot(scsb, B_FALSE, slotnum);
5020 		}
5021 		/*
5022 		 * END INDENT CHEATING, 2 indentations
5023 		 */
5024 
5025 				break;
5026 			default:
5027 				/*
5028 				 * ERROR: Did not find cause of INTSRC bit
5029 				 */
5030 				if (scsb_debug & 0x00000002) {
5031 					cmn_err(CE_WARN,
5032 						"scsb_intr: FRU type %d"
5033 						" not recognized", fru_type);
5034 				}
5035 				continue;
5036 			}
5037 			scsb_event_code |= code;
5038 			retval |= (SCSB_INTR_CLAIMED | SCSB_INTR_EVENT);
5039 			if (fru_type == SLOT)
5040 				continue;
5041 			error = 0;
5042 			fru_ptr = mct_system_info.fru_info_list[fru_type];
5043 			for (; fru_ptr != NULL; fru_ptr = fru_ptr->next) {
5044 				if (unit != fru_ptr->fru_unit)
5045 					continue;
5046 				if (fru_ptr->i2c_info == NULL ||
5047 						(tmp_reg = fru_ptr->i2c_info->
5048 							ledata_reg) == 0)
5049 					continue;
5050 				error = scsb_set_scfg_pres_leds(scsb, fru_ptr);
5051 				if (error) {
5052 					cmn_err(CE_WARN, "scsb_intr(): "
5053 						"I2C write error to 0x%x",
5054 						tmp_reg);
5055 					if (!(scsb->scsb_state &
5056 							SCSB_DEBUG_MODE)) {
5057 						goto intr_error;
5058 					}
5059 				}
5060 				break;
5061 			}
5062 		}
5063 		if (clr_bits) {
5064 			clr_bits = 0;
5065 		}
5066 	}
5067 	/*
5068 	 * Check for SCB 1.5 interrupt for SLOT HEALTHY changes
5069 	 */
5070 	clr_bits = 0;
5071 	intr_idx = 0;
5072 	numregs = SCTRL_INTR_NUMREGS;
5073 	intr_addr = SCSB_REG_ADDR(SCTRL_INTSRC_BASE);
5074 	index = SCSB_REG_INDEX(intr_addr);
5075 	if (IS_SCB_P15) {
5076 		for (i = 0; i < SCTRL_BHLTHY_NUMREGS;
5077 				++i, ++intr_idx, ++intr_addr) {
5078 			scsb->scsb_data_reg[index++] = scb_intr_regs[intr_idx];
5079 			intr_reg = scb_intr_regs[i];
5080 			while (intr_reg) {
5081 				idx = event_to_index((uint32_t)intr_reg);
5082 				code = (1 << idx);
5083 				clr_bits |= code;
5084 				intr_reg = intr_reg & ~code;
5085 				/* idx + 1 because bit 0 is for Slot 1 */
5086 				slotnum = tonga_ssl_to_psl(scsb, idx + 1);
5087 				if (scsb->scsb_state & SCSB_IS_TONGA) {
5088 					if (slotnum > TG_MAX_SLOTS ||
5089 						slotnum == SC_TG_CPU_SLOT) {
5090 						continue;
5091 					}
5092 				} else {
5093 					if (slotnum > MC_MAX_SLOTS ||
5094 						slotnum == SC_MC_CPU_SLOT ||
5095 						(scsb->scsb_hsc_state &
5096 						SCSB_HSC_CTC_PRES &&
5097 						slotnum == SC_MC_CTC_SLOT)) {
5098 						continue;
5099 					}
5100 				}
5101 				scsb_healthy_intr(scsb, slotnum);
5102 			}
5103 			if (clr_bits) {
5104 				clr_bits = 0;
5105 			}
5106 		}
5107 	}
5108 	code = scsb_event_code;
5109 	if (retval & SCSB_INTR_EVENT &&
5110 			!(scsb->scsb_state & SCSB_P06_NOINT_KLUGE)) {
5111 		check_fru_info(scsb, code);
5112 		add_event_code(scsb, code);
5113 		(void) scsb_queue_ops(scsb, QPUT_INT32, 1, &scsb_event_code,
5114 					"scsb_intr");
5115 	}
5116 intr_error:
5117 	scb_post_e = gethrtime();
5118 
5119 	if (scsb_debug & 0x8000000)
5120 		cmn_err(CE_NOTE, "Summary of times in nsec: pre_time %llu, \
5121 			post_time %llu", scb_pre_e - scb_pre_s,
5122 			scb_post_e - scb_post_s);
5123 
5124 
5125 	mutex_enter(&scsb->scsb_mutex);
5126 	scsb_in_postintr = 0;
5127 	cv_broadcast(&scsb->scsb_cv);
5128 	mutex_exit(&scsb->scsb_mutex);
5129 
5130 	/*
5131 	 * Re-enable interrupt now.
5132 	 */
5133 	scsb_toggle_psmint(scsb, 1);
5134 	scsb->scsb_state &= ~SCSB_IN_INTR;
5135 }
5136 
5137 static int
5138 scsb_polled_int(scsb_state_t *scsb, int cmd, uint32_t *set)
5139 {
5140 	if (scsb_debug & 0x4000)
5141 		cmn_err(CE_NOTE, "scsb_polled_int(scsb,0x%x)", cmd);
5142 	*set = 0;
5143 	if (cmd == SCSBIOC_SHUTDOWN_POLL) {
5144 		return (EINVAL);
5145 	}
5146 	if (cmd != SCSBIOC_INTEVENT_POLL) {
5147 		return (EINVAL);
5148 	}
5149 	if (scsb->scsb_state & SCSB_P06_NOINT_KLUGE) {
5150 		/*
5151 		 * scsb_intr() may modify scsb_event_code
5152 		 */
5153 		scsb_event_code = SCTRL_EVENT_NONE;
5154 		(void) scsb_intr((caddr_t)scsb);
5155 		*set = scsb_event_code;
5156 		scsb_event_code = 0;
5157 	} else {
5158 		/*
5159 		 * SCSB_P06_INTR_ON, we know there was an event
5160 		 * and we're retrieving the event code from the event FIFO.
5161 		 */
5162 		*set = get_event_code();
5163 	}
5164 	if (scsb_debug & 0x01004000) {
5165 		cmn_err(CE_NOTE, "scsb_polled_int: event_code = 0x%x", *set);
5166 	}
5167 	return (0);
5168 }
5169 
5170 static int
5171 scsb_leds_switch(scsb_state_t *scsb, scsb_ustate_t op)
5172 {
5173 	register int 	i;
5174 	int		index;
5175 	uchar_t		reg, idata, rwbuf[SCTRL_MAX_GROUP_NUMREGS];
5176 
5177 	if (scsb->scsb_state & SCSB_FROZEN &&
5178 			!(scsb->scsb_state & SCSB_IN_INTR)) {
5179 		return (EAGAIN);
5180 	}
5181 	if (scsb_debug & 0x0101) {
5182 		cmn_err(CE_NOTE, "scsb_leds_switch(%s):",
5183 				op == ON ? "ON" : "OFF");
5184 	}
5185 	/* Step 1: turn ON/OFF all NOK LEDs. */
5186 	if (scsb_debug & 0x0100) {
5187 		cmn_err(CE_NOTE, "scsb%d: turning all NOK LEDs %s",
5188 			scsb->scsb_instance,
5189 			op == ON ? "ON" : "OFF");
5190 	}
5191 	if (op == ON)
5192 		idata = 0xff;
5193 	else	/* off */
5194 		idata = 0x00;
5195 	reg = SCSB_REG_ADDR(SCTRL_LED_NOK_BASE);
5196 	index = SCSB_REG_INDEX(reg);
5197 	for (i = 0; i < SCTRL_LED_NOK_NUMREGS;  ++i) {
5198 		rwbuf[i] = idata;
5199 		scsb->scsb_data_reg[index + i] = idata;
5200 	}
5201 	mutex_enter(&scsb->scsb_mutex);
5202 	i = scsb_rdwr_register(scsb, I2C_WR, reg, SCTRL_LED_NOK_NUMREGS,
5203 			rwbuf, 1);
5204 	mutex_exit(&scsb->scsb_mutex);
5205 	if (i) {
5206 		if (scsb_debug & 0x0102)
5207 			cmn_err(CE_WARN, "scsb_leds_switch(): "
5208 				"Failed to turn %s NOK LEDs",
5209 				op == ON ? "ON" : "OFF");
5210 	}
5211 	/* Step 2: turn ON/OFF all OK LEDs. */
5212 	if (scsb_debug & 0x0100) {
5213 		cmn_err(CE_NOTE, "scsb%d: turning all OK LEDs %s",
5214 			scsb->scsb_instance,
5215 			op == ON ? "ON" : "OFF");
5216 	}
5217 	reg = SCSB_REG_ADDR(SCTRL_LED_OK_BASE);
5218 	index = SCSB_REG_INDEX(reg);
5219 	for (i = 0; i < SCTRL_LED_OK_NUMREGS;  ++i) {
5220 		rwbuf[i] = idata;
5221 		scsb->scsb_data_reg[index + i] = idata;
5222 	}
5223 	mutex_enter(&scsb->scsb_mutex);
5224 	i = scsb_rdwr_register(scsb, I2C_WR, reg, SCTRL_LED_OK_NUMREGS,
5225 			rwbuf, 1);
5226 	mutex_exit(&scsb->scsb_mutex);
5227 	if (i) {
5228 		if (scsb_debug & 0x0102)
5229 			cmn_err(CE_WARN, "scsb_leds_switch(): "
5230 				"Failed to turn %s NOK LEDs",
5231 				op == ON ? "ON" : "OFF");
5232 	}
5233 	/* Step 3: turn OFF all BLINK LEDs. */
5234 	if (op == OFF) {
5235 		reg = SCSB_REG_ADDR(SCTRL_BLINK_OK_BASE);
5236 		index = SCSB_REG_INDEX(reg);
5237 		for (i = 0; i < SCTRL_BLINK_NUMREGS;  ++i) {
5238 			rwbuf[i] = idata;
5239 			scsb->scsb_data_reg[index + i] = idata;
5240 		}
5241 		mutex_enter(&scsb->scsb_mutex);
5242 		i = scsb_rdwr_register(scsb, I2C_WR, reg, SCTRL_BLINK_NUMREGS,
5243 				rwbuf, 1);
5244 		mutex_exit(&scsb->scsb_mutex);
5245 		if (i) {
5246 			if (scsb_debug & 0x0102)
5247 				cmn_err(CE_WARN, "scsb_leds_switch(): "
5248 					"Failed to turn %s BLINK BITs",
5249 					op == ON ? "ON" : "OFF");
5250 		}
5251 	}
5252 	return (0);
5253 }
5254 
5255 static int
5256 scsb_readall_regs(scsb_state_t *scsb)
5257 {
5258 	int		error;
5259 	int		index;
5260 	uchar_t		reg;
5261 
5262 	if (!(scsb_debug & 0x40000000))
5263 		return (0);
5264 	if (scsb_debug & 0x0005) {
5265 		cmn_err(CE_NOTE, "scsb_readall_regs:");
5266 	}
5267 	if (scsb->scsb_state & SCSB_FROZEN) {
5268 		return (EAGAIN);
5269 	}
5270 	reg = SCSB_REG_ADDR_START;	/* 1st register in set */
5271 	index = SCSB_REG_INDEX(reg);
5272 	error = scsb_rdwr_register(scsb, I2C_WR_RD, reg, SCSB_DATA_REGISTERS,
5273 					&scsb->scsb_data_reg[index], 1);
5274 	return (error);
5275 }
5276 
5277 
5278 /*
5279  * read 1-byte register, mask with read bits (rmask),
5280  * turn ON bits in on_mask, turn OFF bits in off_mask
5281  * write the byte back to register
5282  * NOTE: MUST be called with mutex held
5283  */
5284 static int
5285 scsb_write_mask(scsb_state_t *scsb,
5286 		uchar_t reg,
5287 		uchar_t rmask,
5288 		uchar_t on_mask,
5289 		uchar_t off_mask)
5290 {
5291 	i2c_transfer_t	*i2cxferp;
5292 	int		index, error = 0;
5293 	uchar_t		reg_data;
5294 
5295 	if (scsb_debug & 0x0800) {
5296 		cmn_err(CE_NOTE, "scsb_write_mask(,%x,,%x,%x):",
5297 				reg, on_mask, off_mask);
5298 	}
5299 	if (scsb->scsb_state & SCSB_FROZEN &&
5300 			!(scsb->scsb_state & SCSB_IN_INTR)) {
5301 		return (EAGAIN);
5302 	}
5303 	/* select the register address and read the register */
5304 	i2cxferp = (i2c_transfer_t *)scsb->scsb_i2ctp;
5305 	i2cxferp->i2c_flags = I2C_WR_RD;
5306 	i2cxferp->i2c_wlen = 1;
5307 	i2cxferp->i2c_rlen = 1;
5308 	i2cxferp->i2c_wbuf[0] = reg;
5309 	i2cxferp->i2c_rbuf[0] = 0;
5310 	scsb->scsb_kstat_flag = B_TRUE;	/* we did a i2c transaction */
5311 	if (error = nct_i2c_transfer(scsb->scsb_phandle, i2cxferp)) {
5312 		error = EIO;
5313 		goto wm_error;
5314 	}
5315 	scsb->scsb_i2c_errcnt = 0;
5316 	if (scsb_debug & 0x0800)
5317 		cmn_err(CE_NOTE, "scsb_write_mask() read 0x%x",
5318 			i2cxferp->i2c_rbuf[0]);
5319 	reg_data = i2cxferp->i2c_rbuf[0];
5320 	if (rmask)
5321 		reg_data &= rmask;
5322 	if (off_mask)
5323 		reg_data &= ~off_mask;
5324 	if (on_mask)
5325 		reg_data |= on_mask;
5326 	i2cxferp->i2c_flags = I2C_WR;
5327 	i2cxferp->i2c_wlen = 2;
5328 	i2cxferp->i2c_wbuf[0] = reg;
5329 	i2cxferp->i2c_wbuf[1] = reg_data;
5330 	if (error = nct_i2c_transfer(scsb->scsb_phandle, i2cxferp)) {
5331 		error = EIO;
5332 		goto wm_error;
5333 	}
5334 	/* keep shadow registers updated */
5335 	index = SCSB_REG_INDEX(reg);
5336 	scsb->scsb_data_reg[index] = reg_data;
5337 	if (scsb_debug & 0x0800)
5338 		cmn_err(CE_NOTE, "scsb_write_mask() wrote 0x%x", reg_data);
5339 	scsb->scsb_i2c_errcnt = 0;
5340 	return (error);
5341 wm_error:
5342 	scsb->scsb_i2c_errcnt++;
5343 	if (scsb->scsb_i2c_errcnt > scsb_err_threshold)
5344 		scsb->scsb_err_flag = B_TRUE; /* latch error */
5345 	if (scsb->scsb_state & SCSB_SSB_PRESENT) {
5346 		if (scsb_debug & 0x0802)
5347 			cmn_err(CE_WARN,
5348 				"scsb_write_mask(): reg %x %s error, data=%x",
5349 				reg,
5350 				i2cxferp->i2c_flags & I2C_WR ? "write" : "read",
5351 				i2cxferp->i2c_flags & I2C_WR ?
5352 				i2cxferp->i2c_wbuf[1] : i2cxferp->i2c_rbuf[0]);
5353 	} else {
5354 		if (scsb->scsb_i2c_errcnt >= scsb_freeze_count)
5355 			scsb_freeze(scsb);
5356 		return (EAGAIN);
5357 	}
5358 	return (error);
5359 }
5360 
5361 /*
5362  * read/write len consecutive single byte registers to/from rbuf
5363  * NOTE: should be called with mutex held
5364  */
5365 static int
5366 scsb_rdwr_register(scsb_state_t *scsb, int op, uchar_t reg, int len,
5367 				uchar_t *rwbuf, int i2c_alloc)
5368 {
5369 	i2c_transfer_t	*i2cxferp;
5370 	int		i, rlen, wlen, index, error = 0;
5371 
5372 	if (scsb_debug & 0x0800) {
5373 		cmn_err(CE_NOTE, "scsb_rdwr_register(scsb,%s,%x,%x,buf):",
5374 				(op == I2C_WR) ? "write" : "read",  reg, len);
5375 	}
5376 	if (scsb->scsb_state & SCSB_FROZEN &&
5377 			!(scsb->scsb_state & SCSB_IN_INTR)) {
5378 		return (EAGAIN);
5379 	}
5380 	if (i2c_alloc) {
5381 		i2cxferp = scsb_alloc_i2ctx(scsb->scsb_phandle, I2C_NOSLEEP);
5382 		if (i2cxferp == NULL) {
5383 			if (scsb_debug & 0x0042)
5384 				cmn_err(CE_WARN, "scsb_rdwr_register: "
5385 						"i2ctx allocation failure");
5386 			return (ENOMEM);
5387 		}
5388 	} else {
5389 		i2cxferp = scsb->scsb_i2ctp;
5390 	}
5391 	index = SCSB_REG_INDEX(reg);
5392 	switch (op) {
5393 	case I2C_WR:
5394 		wlen = len + 1;	/* add the address */
5395 		rlen = 0;
5396 		i2cxferp->i2c_wbuf[0] = reg;
5397 		for (i = 0; i < len; ++i) {
5398 			scsb->scsb_data_reg[index + i] =
5399 					i2cxferp->i2c_wbuf[1 + i] = rwbuf[i];
5400 			if (scsb_debug & 0x0080)
5401 				cmn_err(CE_NOTE,
5402 				"scsb_rdwr_register: writing rwbuf[%d]=0x%x",
5403 						i, rwbuf[i]);
5404 		}
5405 		break;
5406 	case I2C_WR_RD:
5407 		wlen = 1;	/* for the address */
5408 		rlen = len;
5409 		i2cxferp->i2c_wbuf[0] = reg;
5410 		break;
5411 	default:
5412 		if (i2c_alloc)
5413 			scsb_free_i2ctx(scsb->scsb_phandle, i2cxferp);
5414 		return (EINVAL);
5415 	}
5416 	/* select the register address */
5417 	i2cxferp->i2c_flags = op;
5418 	i2cxferp->i2c_rlen = rlen;
5419 	i2cxferp->i2c_wlen = wlen;
5420 	i2cxferp->i2c_wbuf[0] = reg;
5421 	scsb->scsb_kstat_flag = B_TRUE;	/* we did a i2c transaction */
5422 	if (error = nct_i2c_transfer(scsb->scsb_phandle, i2cxferp)) {
5423 		error = EIO;
5424 	} else if (rlen) {
5425 		/* copy to rwbuf[] and keep shadow registers updated */
5426 		for (i = 0; i < len; ++i) {
5427 			scsb->scsb_data_reg[index + i] = rwbuf[i] =
5428 							i2cxferp->i2c_rbuf[i];
5429 			if (scsb_debug & 0x0080)
5430 				cmn_err(CE_NOTE,
5431 				"scsb_rdwr_register: read rwbuf[%d]=0x%x",
5432 						i, rwbuf[i]);
5433 		}
5434 	}
5435 	if (i2c_alloc)
5436 		scsb_free_i2ctx(scsb->scsb_phandle, i2cxferp);
5437 	if (error) {
5438 		scsb->scsb_i2c_errcnt++;
5439 		if (scsb->scsb_i2c_errcnt > scsb_err_threshold)
5440 			scsb->scsb_err_flag = B_TRUE; /* latch error */
5441 		if (!(scsb->scsb_state & SCSB_SSB_PRESENT)) {
5442 			if (scsb->scsb_i2c_errcnt >= scsb_freeze_count)
5443 				scsb_freeze(scsb);
5444 			return (EAGAIN);
5445 		} else {
5446 			cmn_err(CE_WARN,
5447 				"scsb_rdwr_register(): I2C read error from %x",
5448 					reg);
5449 		}
5450 	} else {
5451 		scsb->scsb_i2c_errcnt = 0;
5452 	}
5453 
5454 	return (error);
5455 }
5456 
5457 /*
5458  * Called from scsb_intr()
5459  * First find the fru_info for this fru_id, and set fru_status for callback.
5460  * Then check for a registered call_back entry for this fru_id,
5461  * and if found, call it.
5462  * Recursize call until no EVENTS left in evcode.
5463  */
5464 static	void
5465 check_fru_info(scsb_state_t *scsb, int evcode)
5466 {
5467 	struct scsb_cb_entry	*cbe_ptr;
5468 	fru_info_t		*fru_ptr;
5469 	fru_id_t		fru_id;
5470 	scsb_fru_status_t	fru_status;
5471 	int			i, new_evcode;
5472 
5473 	if (scsb_debug & 0x00100001)
5474 		cmn_err(CE_NOTE, "check_fru_info(scsb,0x%x)", evcode);
5475 	if (evcode == 0)
5476 		return;
5477 	i = event_to_index((uint32_t)evcode);
5478 	new_evcode = evcode & ~(1 << i);
5479 	if (i > MCT_MAX_FRUS) {
5480 		if (scsb_debug & 0x00100000)
5481 			cmn_err(CE_NOTE,
5482 				"check_fru_info: index %d out of range", i);
5483 		check_fru_info(scsb, new_evcode);
5484 		return;
5485 	}
5486 	fru_id = fru_id_table[i];
5487 	fru_ptr = find_fru_info(fru_id);
5488 	if (fru_ptr == (fru_info_t *)NULL) {
5489 		check_fru_info(scsb, new_evcode);
5490 		return;
5491 	}
5492 	update_fru_info(scsb, fru_ptr);
5493 	if (fru_ptr->fru_status & FRU_PRESENT) {
5494 		fru_status = FRU_PRESENT;
5495 	} else {
5496 		fru_status = FRU_NOT_PRESENT;
5497 		if (fru_ptr->fru_type == SSB) {
5498 			/*
5499 			 * WARN against SCB removal if any
5500 			 * occupied slots are in reset
5501 			 */
5502 			scsb_freeze_check(scsb);
5503 		}
5504 	}
5505 	/*
5506 	 * check for an entry in the CallBack table
5507 	 */
5508 	for (cbe_ptr = scsb_cb_table; cbe_ptr != NULL;
5509 			cbe_ptr = cbe_ptr->cb_next) {
5510 		if (cbe_ptr->cb_fru_id == fru_id &&
5511 				cbe_ptr->cb_fru_ptr == fru_ptr) {
5512 			if (scsb_debug & 0x00800000)
5513 				cmn_err(CE_NOTE,
5514 					"check_fru_info: callback for FRU_ID "
5515 					"0x%x; device is %spresent",
5516 					    (int)fru_id,
5517 					    fru_status == FRU_PRESENT ?
5518 						"" : "not ");
5519 			(*cbe_ptr->cb_func)(
5520 					cbe_ptr->cb_softstate_ptr,
5521 					cbe_ptr->cb_event,
5522 					fru_status);
5523 			break;
5524 		}
5525 	}
5526 	check_fru_info(scsb, new_evcode);
5527 }
5528 
5529 /*
5530  * -----------------------------
5531  * scsb kstat support functions.
5532  * -----------------------------
5533  */
5534 /*
5535  * Create and initialize the kstat data structures
5536  */
5537 static int
5538 scsb_alloc_kstats(scsb_state_t *scsb)
5539 {
5540 	kstat_named_t   *kn;
5541 	/*
5542 	 * scsb_ks_leddata_t for "scsb_leddata"
5543 	 */
5544 	if (scsb_debug & 0x00080001)
5545 		cmn_err(CE_NOTE,
5546 			"scsb_alloc_kstats: create scsb_leddata: %lu bytes",
5547 				sizeof (scsb_ks_leddata_t));
5548 	if ((scsb->ks_leddata = kstat_create(scsb_name, scsb->scsb_instance,
5549 			SCSB_KS_LEDDATA, "misc", KSTAT_TYPE_RAW,
5550 			sizeof (scsb_ks_leddata_t), KSTAT_FLAG_PERSISTENT))
5551 			== NULL) {
5552 		scsb->scsb_state |= SCSB_KSTATS;
5553 		scsb_free_kstats(scsb);
5554 		return (DDI_FAILURE);
5555 	}
5556 	scsb->ks_leddata->ks_update = update_ks_leddata;
5557 	scsb->ks_leddata->ks_private = (void *)scsb;
5558 	if (update_ks_leddata(scsb->ks_leddata, KSTAT_READ) != DDI_SUCCESS) {
5559 		scsb->scsb_state |= SCSB_KSTATS;
5560 		scsb_free_kstats(scsb);
5561 		return (DDI_FAILURE);
5562 	}
5563 	kstat_install(scsb->ks_leddata);
5564 	/*
5565 	 * scsb_ks_state_t for "scsb_state"
5566 	 */
5567 	if (scsb_debug & 0x00080000)
5568 		cmn_err(CE_NOTE,
5569 			"scsb_alloc_kstats: create scsb_state: %lu bytes",
5570 				sizeof (scsb_ks_state_t));
5571 	if ((scsb->ks_state = kstat_create(scsb_name, scsb->scsb_instance,
5572 			SCSB_KS_STATE, "misc", KSTAT_TYPE_RAW,
5573 			sizeof (scsb_ks_state_t), KSTAT_FLAG_PERSISTENT))
5574 			== NULL) {
5575 		scsb->scsb_state |= SCSB_KSTATS;
5576 		scsb_free_kstats(scsb);
5577 		return (DDI_FAILURE);
5578 	}
5579 	scsb->ks_state->ks_update = update_ks_state;
5580 	scsb->ks_state->ks_private = (void *)scsb;
5581 	if (update_ks_state(scsb->ks_state, KSTAT_READ) != DDI_SUCCESS) {
5582 		scsb->scsb_state |= SCSB_KSTATS;
5583 		scsb_free_kstats(scsb);
5584 		return (DDI_FAILURE);
5585 	}
5586 	kstat_install(scsb->ks_state);
5587 	/*
5588 	 * mct_topology_t for "env_topology"
5589 	 */
5590 	if (scsb_debug & 0x00080000)
5591 		cmn_err(CE_NOTE,
5592 			"scsb_alloc_kstats: create env_toploogy: %lu bytes",
5593 				sizeof (mct_topology_t));
5594 	if ((scsb->ks_topology = kstat_create(scsb_name, scsb->scsb_instance,
5595 			SCSB_KS_TOPOLOGY, "misc", KSTAT_TYPE_RAW,
5596 			sizeof (mct_topology_t), KSTAT_FLAG_PERSISTENT))
5597 			== NULL) {
5598 		scsb->scsb_state |= SCSB_KSTATS;
5599 		scsb_free_kstats(scsb);
5600 		return (DDI_FAILURE);
5601 	}
5602 	scsb->ks_topology->ks_update = update_ks_topology;
5603 	scsb->ks_topology->ks_private = (void *)scsb;
5604 	if (update_ks_topology(scsb->ks_topology, KSTAT_READ) != DDI_SUCCESS) {
5605 		scsb->scsb_state |= SCSB_KSTATS;
5606 		scsb_free_kstats(scsb);
5607 		return (DDI_FAILURE);
5608 	}
5609 	kstat_install(scsb->ks_topology);
5610 	/*
5611 	 * kstat_named_t * 2 for "scsb_evc_register"
5612 	 */
5613 	if (scsb_debug & 0x00080001)
5614 		cmn_err(CE_NOTE,
5615 		    "scsb_alloc_kstats: create scsb_evc_register: %lu bytes",
5616 			sizeof (kstat_named_t) * 2);
5617 	if ((scsb->ks_evcreg = kstat_create(scsb_name, scsb->scsb_instance,
5618 			SCSB_KS_EVC_REGISTER, "misc", KSTAT_TYPE_NAMED, 2,
5619 			KSTAT_FLAG_PERSISTENT|KSTAT_FLAG_WRITABLE)) == NULL) {
5620 		scsb->scsb_state |= SCSB_KSTATS;
5621 		scsb_free_kstats(scsb);
5622 		return (DDI_FAILURE);
5623 	}
5624 	scsb->ks_evcreg->ks_update = update_ks_evcreg;
5625 	scsb->ks_evcreg->ks_private = (void *)scsb;
5626 	kn = KSTAT_NAMED_PTR(scsb->ks_evcreg);
5627 	kstat_named_init(&kn[0], "pid_register", KSTAT_DATA_INT64);
5628 	kstat_named_init(&kn[1], "pid_unregister", KSTAT_DATA_INT64);
5629 	kstat_install(scsb->ks_evcreg);
5630 	/*
5631 	 * Done, set the flag for scsb_detach() and other checks
5632 	 */
5633 	scsb->scsb_state |= SCSB_KSTATS;
5634 	return (DDI_SUCCESS);
5635 }
5636 
5637 static int
5638 update_ks_leddata(kstat_t *ksp, int rw)
5639 {
5640 	scsb_state_t		*scsb;
5641 	scsb_ks_leddata_t	*pks_leddata;
5642 	int			i, numregs, index, error = DDI_SUCCESS;
5643 	uchar_t			reg;
5644 
5645 	scsb = (scsb_state_t *)ksp->ks_private;
5646 	if (scsb_debug & 0x00080001)
5647 		cmn_err(CE_NOTE, "update_ks_leddata: KS_UPDATE%sset",
5648 			scsb->scsb_state & SCSB_KS_UPDATE ? " " : " not ");
5649 	/*
5650 	 * Since this is satisfied from the shadow registers, let it succeed
5651 	 * even if the SCB is not present.  It would be nice to return the
5652 	 * shadow values with a warning.
5653 	 *
5654 	 * if (scsb->scsb_state & SCSB_FROZEN) {
5655 	 *	return (DDI_FAILURE);
5656 	 * }
5657 	 */
5658 	if (rw == KSTAT_WRITE) {
5659 		return (EACCES);
5660 	}
5661 	mutex_enter(&scsb->scsb_mutex);
5662 	while (scsb->scsb_state & SCSB_KS_UPDATE) {
5663 		if (cv_wait_sig(&scsb->scsb_cv, &scsb->scsb_mutex) <= 0) {
5664 			mutex_exit(&scsb->scsb_mutex);
5665 			return (EINTR);
5666 		}
5667 	}
5668 	scsb->scsb_state |= SCSB_KS_UPDATE;
5669 	mutex_exit(&scsb->scsb_mutex);
5670 	if (scsb_debug & 0x00080001)
5671 		cmn_err(CE_NOTE, "update_ks_leddata: updating data");
5672 	pks_leddata = (scsb_ks_leddata_t *)ksp->ks_data;
5673 	/*
5674 	 * Call tonga_slotnum_led_shift() for each register that
5675 	 * contains Slot 1-5 information, the first register at each base:
5676 	 * NOK_BASE, OK_BASE, BLINK_OK_BASE
5677 	 * XXX: breaking register table access rules by not using macros.
5678 	 */
5679 	/* NOK */
5680 	reg = SCSB_REG_ADDR(SCTRL_LED_NOK_BASE);
5681 	index = SCSB_REG_INDEX(reg);
5682 	numregs = SCTRL_LED_NOK_NUMREGS;
5683 	i = 0;
5684 	if (IS_SCB_P15)
5685 		reg = tonga_slotnum_led_shift(scsb, scsb->scsb_data_reg[index]);
5686 	else
5687 		reg = scsb->scsb_data_reg[index];
5688 	pks_leddata->scb_led_regs[i] = reg;
5689 	for (++i, ++index; i < numregs; ++i, ++index)
5690 		pks_leddata->scb_led_regs[i] = scsb->scsb_data_reg[index];
5691 	/* OK */
5692 	reg = SCSB_REG_ADDR(SCTRL_LED_OK_BASE);
5693 	index = SCSB_REG_INDEX(reg);
5694 	numregs += SCTRL_LED_OK_NUMREGS;
5695 	if (IS_SCB_P15)
5696 		reg = tonga_slotnum_led_shift(scsb, scsb->scsb_data_reg[index]);
5697 	else
5698 		reg = scsb->scsb_data_reg[index];
5699 	pks_leddata->scb_led_regs[i] = reg;
5700 	for (++i, ++index; i < numregs; ++i, ++index)
5701 		pks_leddata->scb_led_regs[i] = scsb->scsb_data_reg[index];
5702 	/* BLINK */
5703 	reg = SCSB_REG_ADDR(SCTRL_BLINK_OK_BASE);
5704 	index = SCSB_REG_INDEX(reg);
5705 	numregs += SCTRL_BLINK_NUMREGS;
5706 	if (IS_SCB_P15)
5707 		reg = tonga_slotnum_led_shift(scsb, scsb->scsb_data_reg[index]);
5708 	else
5709 		reg = scsb->scsb_data_reg[index];
5710 	pks_leddata->scb_led_regs[i] = reg;
5711 	for (++i, ++index; i < numregs; ++i, ++index)
5712 		pks_leddata->scb_led_regs[i] = scsb->scsb_data_reg[index];
5713 	mutex_enter(&scsb->scsb_mutex);
5714 	scsb->scsb_state &= ~SCSB_KS_UPDATE;
5715 	cv_signal(&scsb->scsb_cv);
5716 	mutex_exit(&scsb->scsb_mutex);
5717 	if (scsb_debug & 0x00080001)
5718 		cmn_err(CE_NOTE, "update_ks_leddata: returning");
5719 	return (error);
5720 }
5721 
5722 static int
5723 update_ks_evcreg(kstat_t *ksp, int rw)
5724 {
5725 	scsb_state_t		*scsb;
5726 	int			error = 0;
5727 	kstat_named_t		*kn = KSTAT_NAMED_PTR(ksp);
5728 	pid_t			pid;
5729 
5730 	scsb = (scsb_state_t *)ksp->ks_private;
5731 	if (scsb_debug & 0x00080001)
5732 		cmn_err(CE_NOTE, "update_ks_evcreg: %s(%d), KS_UPDATE%sset",
5733 				rw == KSTAT_READ ? "read" : "write", rw,
5734 			scsb->scsb_state & SCSB_KS_UPDATE ? " " : " not ");
5735 	/*
5736 	 * Let this registration succeed
5737 	 *
5738 	 * if (scsb->scsb_state & SCSB_FROZEN) {
5739 	 *	return (DDI_FAILURE);
5740 	 * }
5741 	 */
5742 	mutex_enter(&scsb->scsb_mutex);
5743 	while (scsb->scsb_state & SCSB_KS_UPDATE) {
5744 		if (cv_wait_sig(&scsb->scsb_cv, &scsb->scsb_mutex) <= 0) {
5745 			mutex_exit(&scsb->scsb_mutex);
5746 			return (EINTR);
5747 		}
5748 	}
5749 	scsb->scsb_state |= SCSB_KS_UPDATE;
5750 	mutex_exit(&scsb->scsb_mutex);
5751 	if (rw == KSTAT_READ) {
5752 		kn[0].value.i64 = (int64_t)0;
5753 		kn[1].value.i64 = (int64_t)0;
5754 	} else if (rw == KSTAT_WRITE) {
5755 		/*
5756 		 * kn[0] is "pid_register", kn[1] is "pid_unregister"
5757 		 */
5758 		if (kn[0].value.i64 != 0 && kn[1].value.i64 == 0) {
5759 			pid = (pid_t)kn[0].value.i64;
5760 			if (add_event_proc(scsb, pid)) {
5761 				if (scsb_debug & 0x02000002) {
5762 					cmn_err(CE_WARN,
5763 						"update_ks_evcreg: "
5764 						"process add failed for %d",
5765 							pid);
5766 				}
5767 				error = EOVERFLOW;
5768 			}
5769 		} else if (kn[0].value.i64 == 0 && kn[1].value.i64 != 0) {
5770 			pid = (pid_t)kn[1].value.i64;
5771 			if (del_event_proc(scsb, pid)) {
5772 				if (scsb_debug & 0x02000000) {
5773 					cmn_err(CE_NOTE,
5774 						"update_ks_evcreg: "
5775 						"process delete failed for %d",
5776 							pid);
5777 				}
5778 				error = EOVERFLOW;
5779 			}
5780 		} else if (kn[0].value.i64 == 0 && kn[1].value.i64 == 0) {
5781 			/*
5782 			 * rewind the pointers and counts, zero the table.
5783 			 */
5784 			rew_event_proc(scsb);
5785 		} else {
5786 			error = EINVAL;
5787 		}
5788 	} else {
5789 		error = EINVAL;
5790 	}
5791 	mutex_enter(&scsb->scsb_mutex);
5792 	scsb->scsb_state &= ~SCSB_KS_UPDATE;
5793 	cv_signal(&scsb->scsb_cv);
5794 	mutex_exit(&scsb->scsb_mutex);
5795 	return (error);
5796 }
5797 
5798 static int
5799 update_ks_state(kstat_t *ksp, int rw)
5800 {
5801 	scsb_state_t		*scsb;
5802 	scsb_ks_state_t		*pks_state;
5803 	int			error = DDI_SUCCESS;
5804 	uint32_t		current_evc;
5805 
5806 	scsb = (scsb_state_t *)ksp->ks_private;
5807 	if (scsb_debug & 0x00080001)
5808 		cmn_err(CE_NOTE, "update_ks_state: KS_UPDATE%sset",
5809 			scsb->scsb_state & SCSB_KS_UPDATE ? " " : " not ");
5810 	/*
5811 	 * Let this succeed based on last known data
5812 	 *
5813 	 * if (scsb->scsb_state & SCSB_FROZEN) {
5814 	 *	return (DDI_FAILURE);
5815 	 * }
5816 	 */
5817 	if (rw == KSTAT_WRITE) {
5818 		return (EACCES);
5819 	}
5820 	mutex_enter(&scsb->scsb_mutex);
5821 	while (scsb->scsb_state & SCSB_KS_UPDATE) {
5822 		if (cv_wait_sig(&scsb->scsb_cv, &scsb->scsb_mutex) <= 0) {
5823 			mutex_exit(&scsb->scsb_mutex);
5824 			return (EINTR);
5825 		}
5826 	}
5827 	scsb->scsb_state |= SCSB_KS_UPDATE;
5828 	/*
5829 	 * If SSB not present and scsb not SCSB_FROZEN, check for SCB presence
5830 	 * by initiating an I2C read from the SCB.  If an error occurs,
5831 	 * scsb_freeze() will be called to update SCB info and scsb state.
5832 	 */
5833 	if (!(scsb->scsb_state & SCSB_SSB_PRESENT) &&
5834 			!(scsb->scsb_state & SCSB_FROZEN)) {
5835 		uchar_t		data;
5836 		/* Read the SCB PROM ID */
5837 		if (data = scsb_rdwr_register(scsb, I2C_WR_RD,
5838 				(uchar_t)SCTRL_PROM_VERSION, 1, &data, 1))
5839 			if (scsb_debug & 0x00080002)
5840 				cmn_err(CE_NOTE, "update_ks_state: SCB/I2C "
5841 						"failure %d", data);
5842 	}
5843 	mutex_exit(&scsb->scsb_mutex);
5844 	pks_state = (scsb_ks_state_t *)ksp->ks_data;
5845 	pks_state->scb_present = (scsb->scsb_state & SCSB_SCB_PRESENT) ? 1 : 0;
5846 	pks_state->ssb_present = (scsb->scsb_state & SCSB_SSB_PRESENT) ? 1 : 0;
5847 	pks_state->scsb_frozen = (scsb->scsb_state & SCSB_FROZEN) ? 1 : 0;
5848 	if (scsb->scsb_state & SCSB_DEBUG_MODE)
5849 		pks_state->scsb_mode = (uint8_t)ENVC_DEBUG_MODE;
5850 	else if (scsb->scsb_state & SCSB_DIAGS_MODE)
5851 		pks_state->scsb_mode = (uint8_t)ENVCTRL_DIAG_MODE;
5852 	else
5853 		pks_state->scsb_mode = (uint8_t)ENVCTRL_NORMAL_MODE;
5854 	/*
5855 	 * If scsb_attach() has not completed the kstat installs,
5856 	 * then there are no event processes to check for.
5857 	 */
5858 	if (scsb->scsb_state & SCSB_KSTATS) {
5859 		switch (check_event_procs(&current_evc)) {
5860 		case EVC_NO_EVENT_CODE:
5861 			pks_state->event_code = 0;
5862 			break;
5863 		case EVC_NEW_EVENT_CODE:
5864 		/* FALLTHROUGH */
5865 		case EVC_NO_CURR_PROC:
5866 			pks_state->event_code = current_evc;
5867 			break;
5868 		case EVC_OR_EVENT_CODE:
5869 			pks_state->event_code |= current_evc;
5870 			break;
5871 		case EVC_FAILURE:
5872 			pks_state->event_code = 0;
5873 			error = DDI_FAILURE;
5874 			break;
5875 		}
5876 	} else {
5877 		pks_state->event_code = 0;
5878 	}
5879 	mutex_enter(&scsb->scsb_mutex);
5880 	scsb->scsb_state &= ~SCSB_KS_UPDATE;
5881 	cv_signal(&scsb->scsb_cv);
5882 	mutex_exit(&scsb->scsb_mutex);
5883 	return (error);
5884 }
5885 
5886 static int
5887 update_ks_topology(kstat_t *ksp, int rw)
5888 {
5889 	scsb_state_t		*scsb;
5890 	mct_topology_t		*pks_topo;
5891 	fru_info_t		*fru_ptr;
5892 	int			i, val, error = DDI_SUCCESS, slotnum;
5893 
5894 	scsb = (scsb_state_t *)ksp->ks_private;
5895 	if (scsb_debug & 0x00080001)
5896 		cmn_err(CE_NOTE, "update_ks_topology: KS_UPDATE%sset",
5897 			scsb->scsb_state & SCSB_KS_UPDATE ? " " : " not ");
5898 	/*
5899 	 * Let this succeed based on last known data
5900 	 *
5901 	 * if (scsb->scsb_state & SCSB_FROZEN) {
5902 	 *	return (DDI_FAILURE);
5903 	 * }
5904 	 */
5905 	if (rw == KSTAT_WRITE) {
5906 		return (EACCES);
5907 	}
5908 	mutex_enter(&scsb->scsb_mutex);
5909 	while (scsb->scsb_state & SCSB_KS_UPDATE) {
5910 		if (cv_wait_sig(&scsb->scsb_cv, &scsb->scsb_mutex) <= 0) {
5911 			mutex_exit(&scsb->scsb_mutex);
5912 			return (EINTR);
5913 		}
5914 	}
5915 	scsb->scsb_state |= SCSB_KS_UPDATE;
5916 	/*
5917 	 * If SSB not present and scsb not SCSB_FROZEN, check for SCB presence
5918 	 * by initiating an I2C read from the SCB.  If an error occurs,
5919 	 * scsb_freeze() will be called to update SCB info and scsb state.
5920 	 */
5921 	if (!(scsb->scsb_state & SCSB_SSB_PRESENT) &&
5922 			!(scsb->scsb_state & SCSB_FROZEN)) {
5923 		uchar_t		data;
5924 		/* Read the SCB PROM ID */
5925 		if (data = scsb_rdwr_register(scsb, I2C_WR_RD,
5926 				(uchar_t)SCTRL_PROM_VERSION, 1, &data, 1))
5927 			if (scsb_debug & 0x00080002)
5928 				cmn_err(CE_NOTE, "update_ks_topology: SCB/I2C "
5929 						"failure %d", data);
5930 	}
5931 	mutex_exit(&scsb->scsb_mutex);
5932 	pks_topo = (mct_topology_t *)ksp->ks_data;
5933 	for (i = SLOT; i < SCSB_UNIT_TYPES; ++i) {
5934 		pks_topo->max_units[i] = mct_system_info.max_units[i];
5935 	}
5936 
5937 	pks_topo->mid_plane.fru_status = FRU_PRESENT;
5938 	pks_topo->mid_plane.fru_unit = (scsb_unum_t)1;
5939 	pks_topo->mid_plane.fru_type = mct_system_info.mid_plane.fru_type;
5940 	pks_topo->mid_plane.fru_id = mct_system_info.mid_plane.fru_id;
5941 	pks_topo->mid_plane.fru_version = mct_system_info.mid_plane.fru_version;
5942 	pks_topo->mid_plane.fru_health = MCT_HEALTH_OK;
5943 	fru_ptr = mct_system_info.fru_info_list[SLOT];
5944 	for (i = 0; i < pks_topo->max_units[SLOT]; ++i, ++fru_ptr) {
5945 		pks_topo->mct_slots[i].fru_status = fru_ptr->fru_status;
5946 		pks_topo->mct_slots[i].fru_type = fru_ptr->fru_type;
5947 		pks_topo->mct_slots[i].fru_unit = fru_ptr->fru_unit;
5948 		pks_topo->mct_slots[i].fru_id = fru_ptr->fru_id;
5949 		pks_topo->mct_slots[i].fru_version = fru_ptr->fru_version;
5950 		/*
5951 		 * XXX: need to check healthy regs to set fru_health
5952 		 */
5953 		slotnum = tonga_psl_to_ssl(scsb, i+1);
5954 		val = scsb_fru_op(scsb, SLOT, slotnum, SCTRL_BHLTHY_BASE,
5955 						SCSB_FRU_OP_GET_BITVAL);
5956 		pks_topo->mct_slots[i].fru_health = (val) ?
5957 			MCT_HEALTH_OK : MCT_HEALTH_NOK;
5958 	}
5959 	fru_ptr = mct_system_info.fru_info_list[PDU];
5960 	for (i = 0; i < pks_topo->max_units[PDU]; ++i, ++fru_ptr) {
5961 		pks_topo->mct_pdu[i].fru_status = fru_ptr->fru_status;
5962 		pks_topo->mct_pdu[i].fru_type = fru_ptr->fru_type;
5963 		pks_topo->mct_pdu[i].fru_unit = fru_ptr->fru_unit;
5964 		pks_topo->mct_pdu[i].fru_id = fru_ptr->fru_id;
5965 		pks_topo->mct_pdu[i].fru_version = fru_ptr->fru_version;
5966 		pks_topo->mct_pdu[i].fru_health = MCT_HEALTH_NA;
5967 	}
5968 	fru_ptr = mct_system_info.fru_info_list[PS];
5969 	for (i = 0; i < pks_topo->max_units[PS]; ++i, ++fru_ptr) {
5970 		pks_topo->mct_ps[i].fru_status = fru_ptr->fru_status;
5971 		pks_topo->mct_ps[i].fru_type = fru_ptr->fru_type;
5972 		pks_topo->mct_ps[i].fru_unit = fru_ptr->fru_unit;
5973 		pks_topo->mct_ps[i].fru_id = fru_ptr->fru_id;
5974 		pks_topo->mct_ps[i].fru_version = fru_ptr->fru_version;
5975 		pks_topo->mct_ps[i].fru_health = MCT_HEALTH_NA;
5976 	}
5977 	fru_ptr = mct_system_info.fru_info_list[DISK];
5978 	for (i = 0; i < pks_topo->max_units[DISK]; ++i, ++fru_ptr) {
5979 		pks_topo->mct_disk[i].fru_status = fru_ptr->fru_status;
5980 		pks_topo->mct_disk[i].fru_type = fru_ptr->fru_type;
5981 		pks_topo->mct_disk[i].fru_unit = fru_ptr->fru_unit;
5982 		pks_topo->mct_disk[i].fru_id = fru_ptr->fru_id;
5983 		pks_topo->mct_disk[i].fru_version = fru_ptr->fru_version;
5984 		pks_topo->mct_disk[i].fru_health = MCT_HEALTH_NA;
5985 	}
5986 	fru_ptr = mct_system_info.fru_info_list[FAN];
5987 	for (i = 0; i < pks_topo->max_units[FAN]; ++i, ++fru_ptr) {
5988 		pks_topo->mct_fan[i].fru_status = fru_ptr->fru_status;
5989 		pks_topo->mct_fan[i].fru_type = fru_ptr->fru_type;
5990 		pks_topo->mct_fan[i].fru_unit = fru_ptr->fru_unit;
5991 		pks_topo->mct_fan[i].fru_id = fru_ptr->fru_id;
5992 		pks_topo->mct_fan[i].fru_version = fru_ptr->fru_version;
5993 		pks_topo->mct_fan[i].fru_health = MCT_HEALTH_NA;
5994 	}
5995 	fru_ptr = mct_system_info.fru_info_list[SCB];
5996 	for (i = 0; i < pks_topo->max_units[SCB]; ++i, ++fru_ptr) {
5997 		pks_topo->mct_scb[i].fru_status = fru_ptr->fru_status;
5998 		pks_topo->mct_scb[i].fru_type = fru_ptr->fru_type;
5999 		pks_topo->mct_scb[i].fru_unit = fru_ptr->fru_unit;
6000 		pks_topo->mct_scb[i].fru_id = fru_ptr->fru_id;
6001 		pks_topo->mct_scb[i].fru_version = fru_ptr->fru_version;
6002 		/*
6003 		 * To get the scsb health, if there was no i2c transaction
6004 		 * until this read, generate an i2c transaction.
6005 		 */
6006 		if (scsb->scsb_kstat_flag == B_FALSE) {
6007 			uchar_t		data;
6008 			scsb_blind_read(scsb, I2C_WR_RD,
6009 			(uchar_t)SCTRL_PROM_VERSION, 1, &data, 1);
6010 		}
6011 		pks_topo->mct_scb[i].fru_health = ((scsb->scsb_err_flag ==
6012 			B_TRUE || scsb->scsb_i2c_errcnt > scsb_err_threshold)
6013 			?  MCT_HEALTH_NOK : MCT_HEALTH_OK);
6014 #ifdef DEBUG
6015 		if (pks_topo->mct_scb[i].fru_health == MCT_HEALTH_NOK)
6016 			cmn_err(CE_WARN, "SCSB kstat health:%d", pks_topo->
6017 				mct_scb[i].fru_health);
6018 #endif
6019 		scsb->scsb_err_flag = B_FALSE; /* clear error flag once read */
6020 		scsb->scsb_kstat_flag = B_FALSE; /* false? read from i2c */
6021 	}
6022 	fru_ptr = mct_system_info.fru_info_list[SSB];
6023 	for (i = 0; i < pks_topo->max_units[SSB]; ++i, ++fru_ptr) {
6024 		pks_topo->mct_ssb[i].fru_status = fru_ptr->fru_status;
6025 		pks_topo->mct_ssb[i].fru_type = fru_ptr->fru_type;
6026 		pks_topo->mct_ssb[i].fru_unit = fru_ptr->fru_unit;
6027 		pks_topo->mct_ssb[i].fru_id = fru_ptr->fru_id;
6028 		pks_topo->mct_ssb[i].fru_version = fru_ptr->fru_version;
6029 		pks_topo->mct_ssb[i].fru_health = MCT_HEALTH_NA;
6030 	}
6031 	fru_ptr = mct_system_info.fru_info_list[ALARM];
6032 	for (i = 0; i < pks_topo->max_units[ALARM]; ++i, ++fru_ptr) {
6033 		pks_topo->mct_alarm[i].fru_status = fru_ptr->fru_status;
6034 		pks_topo->mct_alarm[i].fru_type = fru_ptr->fru_type;
6035 		pks_topo->mct_alarm[i].fru_unit = fru_ptr->fru_unit;
6036 		pks_topo->mct_alarm[i].fru_id = fru_ptr->fru_id;
6037 		pks_topo->mct_alarm[i].fru_version = fru_ptr->fru_version;
6038 		pks_topo->mct_alarm[i].fru_health = MCT_HEALTH_NA;
6039 	}
6040 	fru_ptr = mct_system_info.fru_info_list[CFTM];
6041 	for (i = 0; i < pks_topo->max_units[CFTM]; ++i, ++fru_ptr) {
6042 		pks_topo->mct_cftm[i].fru_status = fru_ptr->fru_status;
6043 		pks_topo->mct_cftm[i].fru_type = fru_ptr->fru_type;
6044 		pks_topo->mct_cftm[i].fru_unit = fru_ptr->fru_unit;
6045 		pks_topo->mct_cftm[i].fru_id = fru_ptr->fru_id;
6046 		pks_topo->mct_cftm[i].fru_version = fru_ptr->fru_version;
6047 		pks_topo->mct_cftm[i].fru_health = MCT_HEALTH_NA;
6048 	}
6049 	fru_ptr = mct_system_info.fru_info_list[CRTM];
6050 	for (i = 0; i < pks_topo->max_units[CRTM]; ++i, ++fru_ptr) {
6051 		pks_topo->mct_crtm[i].fru_status = fru_ptr->fru_status;
6052 		pks_topo->mct_crtm[i].fru_type = fru_ptr->fru_type;
6053 		pks_topo->mct_crtm[i].fru_unit = fru_ptr->fru_unit;
6054 		pks_topo->mct_crtm[i].fru_id = fru_ptr->fru_id;
6055 		pks_topo->mct_crtm[i].fru_version = fru_ptr->fru_version;
6056 		pks_topo->mct_crtm[i].fru_health = MCT_HEALTH_NA;
6057 	}
6058 	fru_ptr = mct_system_info.fru_info_list[PRTM];
6059 	for (i = 0; i < pks_topo->max_units[PRTM]; ++i, ++fru_ptr) {
6060 		pks_topo->mct_prtm[i].fru_status = fru_ptr->fru_status;
6061 		pks_topo->mct_prtm[i].fru_type = fru_ptr->fru_type;
6062 		pks_topo->mct_prtm[i].fru_unit = fru_ptr->fru_unit;
6063 		pks_topo->mct_prtm[i].fru_id = fru_ptr->fru_id;
6064 		pks_topo->mct_prtm[i].fru_version = fru_ptr->fru_version;
6065 		pks_topo->mct_prtm[i].fru_health = MCT_HEALTH_NA;
6066 	}
6067 	mutex_enter(&scsb->scsb_mutex);
6068 	scsb->scsb_state &= ~SCSB_KS_UPDATE;
6069 	cv_signal(&scsb->scsb_cv);
6070 	mutex_exit(&scsb->scsb_mutex);
6071 	return (error);
6072 }
6073 
6074 static void
6075 scsb_free_kstats(scsb_state_t *scsb)
6076 {
6077 	if (!(scsb->scsb_state & SCSB_KSTATS))
6078 		return;
6079 	/*
6080 	 * free the allocated kstat data
6081 	 */
6082 	if (scsb->ks_evcreg != NULL) {
6083 		kstat_delete(scsb->ks_evcreg);
6084 	}
6085 	if (scsb->ks_topology != NULL) {
6086 		kstat_delete(scsb->ks_topology);
6087 	}
6088 	if (scsb->ks_state != NULL) {
6089 		kstat_delete(scsb->ks_state);
6090 	}
6091 	if (scsb->ks_leddata != NULL) {
6092 		kstat_delete(scsb->ks_leddata);
6093 	}
6094 	scsb->ks_leddata = NULL;
6095 	scsb->ks_state = NULL;
6096 	scsb->ks_topology = NULL;
6097 	scsb->ks_evcreg = NULL;
6098 	scsb->scsb_state &= ~SCSB_KSTATS;
6099 }
6100 
6101 
6102 /*
6103  * --------------------------------------
6104  * Miscellaneous scsb internal functions.
6105  * --------------------------------------
6106  *
6107  * allocate I2C transfer structure
6108  */
6109 static i2c_transfer_t *
6110 scsb_alloc_i2ctx(i2c_client_hdl_t phandle, uint_t sleep)
6111 {
6112 	i2c_transfer_t	*tp;
6113 
6114 	if (i2c_transfer_alloc(phandle, &tp, SCSB_DATA_REGISTERS + 2,
6115 			SCSB_DATA_REGISTERS + 2, sleep) == I2C_FAILURE) {
6116 		return (NULL);
6117 	}
6118 	return (tp);
6119 }
6120 
6121 /*
6122  * free I2C transfer structure
6123  */
6124 static void
6125 scsb_free_i2ctx(i2c_client_hdl_t phandle, i2c_transfer_t *tp)
6126 {
6127 	i2c_transfer_free(phandle, tp);
6128 }
6129 
6130 static	void
6131 update_fru_info(scsb_state_t *scsb, fru_info_t *fru_ptr)
6132 {
6133 	int		index;
6134 	uchar_t		reg, bit;
6135 	fru_info_t	*acslot_ptr = NULL;
6136 	fru_id_t	acslot_id = 0;
6137 	if (scsb_debug & 0x00100001)
6138 		cmn_err(CE_NOTE, "update_fru_info(scsb,0x%p)", fru_ptr);
6139 	if (fru_ptr == (fru_info_t *)NULL ||
6140 			fru_ptr->i2c_info == (fru_i2c_info_t *)NULL)
6141 		return;
6142 	/*
6143 	 * If this is an Alarm Card update, then we also need to get
6144 	 * Alarm Card Slot fru_ptr to update it's fru_type, and maybe fru_id
6145 	 */
6146 	if (fru_ptr->fru_id == fru_id_table[FRU_INDEX(SCTRL_EVENT_ALARM)]) {
6147 		/*
6148 		 * SCTRL_EVENT_SLOT1 == 0x01 so
6149 		 * fru_id_table[] index for Slot 1 == 0
6150 		 */
6151 		acslot_id = fru_id_table[(scsb->ac_slotnum - 1)];
6152 		acslot_ptr = find_fru_info(acslot_id);
6153 	}
6154 	reg = fru_ptr->i2c_info->syscfg_reg;
6155 	bit = fru_ptr->i2c_info->syscfg_bit;
6156 	if (reg == 0 && fru_ptr->fru_type == SCB) {
6157 		if (scsb->scsb_state & SCSB_SCB_PRESENT)
6158 			fru_ptr->fru_status = FRU_PRESENT;
6159 		else
6160 			fru_ptr->fru_status = FRU_NOT_PRESENT;
6161 	} else if (reg) {
6162 		index = SCSB_REG_INDEX(reg);
6163 		if (scsb->scsb_data_reg[index] & (1 << bit)) {
6164 			fru_ptr->fru_status = FRU_PRESENT;
6165 			/*
6166 			 * XXX:	need to add version register, and maybe a
6167 			 *	 method, to the fru_ptr->i2c_info structure.
6168 			 *
6169 			 * fru_ptr->fru_version = (fru_version_t)0;
6170 			 */
6171 			/*
6172 			 * Because scsb_intr() sometimes gets the AC present
6173 			 * INT before the ACSLOT present INT,
6174 			 * do not check the ACSLOT fru_status
6175 			 *
6176 			 * if (acslot_ptr != NULL && acslot_ptr->fru_status ==
6177 			 *					FRU_PRESENT)
6178 			 */
6179 			if (acslot_ptr != NULL)
6180 				acslot_ptr->fru_type = (scsb_utype_t)OC_AC;
6181 		} else {
6182 			fru_ptr->fru_status = FRU_NOT_PRESENT;
6183 			/*
6184 			 * fru_ptr->fru_version = (fru_version_t)0;
6185 			 */
6186 			if (acslot_ptr != NULL) {
6187 				/* AC just removed, but AC Slot is occupied? */
6188 				if (acslot_ptr->fru_status == FRU_PRESENT)
6189 					/* for now it's unknown */
6190 					acslot_ptr->fru_type =
6191 							(scsb_utype_t)OC_UNKN;
6192 				else
6193 					acslot_ptr->fru_type =
6194 							(scsb_utype_t)OC_UNKN;
6195 			}
6196 		}
6197 	}
6198 	if (scsb_debug & 0x00100000)
6199 		cmn_err(CE_NOTE,
6200 			"update_fru_info: type %d unit %d is %spresent",
6201 				fru_ptr->fru_type, fru_ptr->fru_unit,
6202 				fru_ptr->fru_status == FRU_PRESENT
6203 					? "" : "not ");
6204 }
6205 
6206 /*
6207  * Convert EVENT code to FRU index
6208  * by finding the highest bit number in 32 bit word
6209  */
6210 static int
6211 event_to_index(uint32_t evcode)
6212 {
6213 	int	i = 0;
6214 	if (evcode == 0)
6215 		return (MCT_MAX_FRUS - 1);
6216 	for (; (evcode >>= 1); i++)
6217 		;
6218 	return (i);
6219 }
6220 
6221 #ifdef DEBUG
6222 void
6223 scsb_debug_prnt(char *fmt, uintptr_t a1, uintptr_t a2, uintptr_t a3,
6224 	uintptr_t a4, uintptr_t a5)
6225 {
6226 	if (scsb_debug & 0x8000 ||
6227 			(*fmt == 'X' && scsb_debug & 0x00010000)) {
6228 		if (*fmt == 'X')
6229 			++fmt;
6230 		prom_printf("scsb: ");
6231 		prom_printf(fmt, a1, a2, a3, a4, a5);
6232 		prom_printf("\n");
6233 	}
6234 }
6235 #endif
6236 
6237 /*
6238  * event code functions to deliver event codes
6239  * and to manage:
6240  *	the event code fifo
6241  *	the process handle table for registered processes interested in
6242  *	  event codes
6243  */
6244 /*
6245  * Send signal to processes registered for event code delivery
6246  */
6247 static void
6248 signal_evc_procs(scsb_state_t *scsb)
6249 {
6250 	int	i = 0, c = 0;
6251 	if (evc_proc_count == 0)
6252 		return;
6253 	for (; i < EVC_PROCS_MAX; ++i) {
6254 		if (evc_procs[i] != NULL) {
6255 			if (proc_signal(evc_procs[i], SIGPOLL)) {
6256 				if (scsb_debug & 0x02000002)
6257 					cmn_err(CE_WARN,
6258 						"scsb:signal_evc_procs: "
6259 						"signal to %d failed",
6260 					((struct pid *)evc_procs[i])->pid_id);
6261 				(void) del_event_proc(scsb,
6262 					((struct pid *)evc_procs[i])->pid_id);
6263 			}
6264 			if (++c >= evc_proc_count) {
6265 				if (scsb_debug & 0x02000000) {
6266 					cmn_err(CE_NOTE,
6267 						"signal_evc_procs: signaled "
6268 						"%d/%d processes", c,
6269 						evc_proc_count);
6270 				}
6271 				break;
6272 			}
6273 		}
6274 	}
6275 }
6276 
6277 /*
6278  * bump FIFO ptr, taking care of wrap around
6279  */
6280 static uint32_t *
6281 inc_fifo_ptr(uint32_t *ptr)
6282 {
6283 	if (++ptr >= evc_fifo + EVC_FIFO_SIZE)
6284 		ptr = evc_fifo;
6285 	return (ptr);
6286 }
6287 
6288 /* ARGSUSED */
6289 static void
6290 reset_evc_fifo(scsb_state_t *scsb)
6291 {
6292 	evc_wptr = evc_fifo;
6293 	evc_rptr = evc_fifo;
6294 	evc_fifo_count = 0;
6295 }
6296 
6297 /*
6298  * Called from scsb_intr() when a new event occurs, to put new code in FIFO,
6299  * and signal any interested processes in evc_procs[].
6300  * Always succeeds.
6301  */
6302 static void
6303 add_event_code(scsb_state_t *scsb, uint32_t event_code)
6304 {
6305 	if (event_proc_count(scsb) == 0) {
6306 		return;
6307 	}
6308 	*evc_wptr = event_code;
6309 	evc_wptr = inc_fifo_ptr(evc_wptr);
6310 	if (++evc_fifo_count > EVC_FIFO_SIZE) {
6311 		--evc_fifo_count;		/* lose the oldest event */
6312 		evc_rptr = inc_fifo_ptr(evc_rptr);
6313 	}
6314 	if (scsb_debug & 0x01000000) {
6315 		cmn_err(CE_NOTE, "add_event_code: 0x%x, FIFO size = %d",
6316 				event_code, evc_fifo_count);
6317 	}
6318 	signal_evc_procs(scsb);
6319 }
6320 
6321 /*
6322  * called from check_event_procs() when the last registered process
6323  * retrieved the oldest event
6324  */
6325 static uint32_t
6326 del_event_code()
6327 {
6328 	uint32_t evc = 0;
6329 	if (!evc_fifo_count)
6330 		return (scsb_event_code);
6331 	evc = *evc_rptr;
6332 	evc_rptr = inc_fifo_ptr(evc_rptr);
6333 	--evc_fifo_count;
6334 	if (scsb_debug & 0x01000000) {
6335 		cmn_err(CE_NOTE, "del_event_code: 0x%x, FIFO size = %d",
6336 				evc, evc_fifo_count);
6337 	}
6338 	return (evc);
6339 }
6340 
6341 /*
6342  * called from check_event_procs() to retrieve the current event code
6343  */
6344 static uint32_t
6345 get_event_code()
6346 {
6347 	if (!evc_fifo_count)
6348 		return (0);
6349 	return (*evc_rptr);
6350 }
6351 
6352 /*
6353  * called from an application interface (ie: an ioctl command)
6354  * to register a process id interested in SCB events.
6355  * NOTE: proc_ref() must be called from USER context, so since this is a
6356  * streams driver, a kstat interface is used for process registration.
6357  * return:
6358  *	0 = event_proc was added
6359  *	1 = out of space
6360  */
6361 /* ARGSUSED */
6362 static int
6363 add_event_proc(scsb_state_t *scsb, pid_t pid)
6364 {
6365 	int	i = 0;
6366 	void	*curr_proc;
6367 	pid_t	curr_pid;
6368 	if (evc_proc_count >= EVC_PROCS_MAX)
6369 		return (1);
6370 	curr_proc = proc_ref();
6371 	curr_pid = (pid_t)(((struct pid *)curr_proc)->pid_id);
6372 	if (curr_pid != pid) {
6373 		if (scsb_debug & 0x02000000) {
6374 			cmn_err(CE_WARN,
6375 				"add_event_proc: current %d != requestor %d",
6376 					curr_pid, pid);
6377 		} else {
6378 			proc_unref(curr_proc);
6379 			return (1);
6380 		}
6381 	}
6382 	for (; i < EVC_PROCS_MAX; ++i) {
6383 		if (evc_procs[i] == NULL) {
6384 			evc_procs[i] = curr_proc;
6385 			evc_proc_count++;
6386 			if (scsb_debug & 0x02000000) {
6387 				cmn_err(CE_NOTE,
6388 					"add_event_proc: %d; evc_proc_count=%d",
6389 						pid, evc_proc_count);
6390 			}
6391 			return (0);
6392 		}
6393 	}
6394 	proc_unref(curr_proc);
6395 	return (1);
6396 }
6397 
6398 /*
6399  * called from an application interface (ie: an ioctl command)
6400  * to unregister a process id interested in SCB events.
6401  * return:
6402  *	0 = event_proc was deleted
6403  *	1 = event_proc was not found, or table was empty
6404  */
6405 /* ARGSUSED */
6406 static int
6407 del_event_proc(scsb_state_t *scsb, pid_t pid)
6408 {
6409 	int	i = 0;
6410 	int	cnt = 0;
6411 	void	*this_proc;
6412 	if (evc_proc_count == 0)
6413 		return (1);
6414 	for (; i < EVC_PROCS_MAX; ++i) {
6415 		if (evc_procs[i] == NULL)
6416 			continue;
6417 		this_proc = evc_procs[i];
6418 		if (pid == ((struct pid *)this_proc)->pid_id) {
6419 			evc_procs[i] = NULL;
6420 			if (--evc_proc_count == 0) {
6421 				/*
6422 				 * reset evc fifo cound and pointers
6423 				 */
6424 				reset_evc_fifo(scsb);
6425 			}
6426 			if (scsb_debug & 0x02000000) {
6427 				cmn_err(CE_NOTE,
6428 					"del_event_proc: %d; evc_proc_count=%d",
6429 						pid, evc_proc_count);
6430 			}
6431 			proc_unref(this_proc);
6432 			return (0);
6433 		}
6434 		if (++cnt >= evc_proc_count)
6435 			break;
6436 	}
6437 	return (1);
6438 }
6439 
6440 /*
6441  * Can be called from an application interface
6442  * to rewind the pointers and counters, and zero the table
6443  * return:
6444  */
6445 /* ARGSUSED */
6446 static void
6447 rew_event_proc(scsb_state_t *scsb)
6448 {
6449 	int	i = 0;
6450 	if (scsb_debug & 0x02000001) {
6451 		cmn_err(CE_NOTE, "rew_event_proc: evc_proc_count=%d",
6452 				evc_proc_count);
6453 	}
6454 	for (; i < EVC_PROCS_MAX; ++i) {
6455 		if (evc_procs[i] != NULL) {
6456 			proc_unref(evc_procs[i]);
6457 			evc_procs[i] = NULL;
6458 		}
6459 	}
6460 	evc_proc_count = 0;
6461 }
6462 
6463 /* ARGSUSED */
6464 static int
6465 event_proc_count(scsb_state_t *scsb)
6466 {
6467 	return (evc_proc_count);
6468 }
6469 
6470 /*
6471  * return:
6472  *	1 = pid was found
6473  *	0 = pid was not found, or table was empty
6474  */
6475 static int
6476 find_evc_proc(pid_t pid)
6477 {
6478 	int	i = 0;
6479 	int	cnt = 0;
6480 	if (evc_proc_count == 0)
6481 		return (0);
6482 	for (; i < EVC_PROCS_MAX; ++i) {
6483 		if (evc_procs[i] == NULL)
6484 			continue;
6485 		if (pid == ((struct pid *)evc_procs[i])->pid_id)
6486 			return (1);
6487 		if (++cnt >= evc_proc_count)
6488 			break;
6489 	}
6490 	return (0);
6491 }
6492 
6493 /*
6494  * called from update_ks_state() to compare evc_proc_count with
6495  * evc_requests, also mainted by this same function
6496  * This function could check the current process id, since this will be a user
6497  * context call, and only bump evc_requests if the calling process is
6498  * registered for event code delivery.
6499  * return:
6500  *	EVC_NO_EVENT_CODE	: no event_code on fifo
6501  *	EVC_NO_CURR_PROC	: current process not in table,
6502  *				  but have an event_code
6503  *	EVC_NEW_EVENT_CODE	: return_evc is new ks_state->event_code
6504  *	EVC_OR_EVENT_CODE	: OR return_evc with ks_state->event_code
6505  *	EVC_FAILURE		: unrecoverable error condition.
6506  */
6507 static int
6508 check_event_procs(uint32_t *return_evc)
6509 {
6510 	void		*curr_proc;
6511 	pid_t		curr_pid = 0;
6512 	int		return_val = 0;
6513 	static int	evc_requests = 0;
6514 	/*
6515 	 * get current process handle, and check the event_procs table
6516 	 */
6517 	if (evc_proc_count == 0) {
6518 		*return_evc = del_event_code();
6519 		return_val = EVC_NO_CURR_PROC;
6520 	} else {
6521 		curr_proc = proc_ref();
6522 		curr_pid = ((struct pid *)curr_proc)->pid_id;
6523 		proc_unref(curr_proc);
6524 		if (!find_evc_proc(curr_pid)) {
6525 			*return_evc = get_event_code();
6526 			return_val = EVC_NO_CURR_PROC;
6527 		} else if (++evc_requests >= evc_proc_count) {
6528 			evc_requests = 0;
6529 			*return_evc = del_event_code();
6530 			return_val = EVC_NEW_EVENT_CODE;
6531 		} else {
6532 			*return_evc = get_event_code();
6533 		}
6534 		if (!return_val)
6535 			return_val = EVC_OR_EVENT_CODE;
6536 	}
6537 	if (scsb_debug & 0x02000000) {
6538 		cmn_err(CE_NOTE, "check_event_procs: pid=%d, evc=0x%x, "
6539 				"requests=%d, returning 0x%x", curr_pid,
6540 				*return_evc, evc_requests, return_val);
6541 	}
6542 	return (return_val);
6543 }
6544 
6545 static int
6546 scsb_queue_put(queue_t *rq, int count, uint32_t *data, char *caller)
6547 {
6548 	mblk_t		*mp;
6549 	if (scsb_debug & 0x4001) {
6550 		cmn_err(CE_NOTE, "scsb_queue_put(0x%p, %d, 0x%x, %s)",
6551 				rq, count, *data, caller);
6552 	}
6553 	mp = allocb(sizeof (uint32_t) * count, BPRI_HI);
6554 	if (mp == NULL) {
6555 		cmn_err(CE_WARN, "%s: allocb failed",
6556 				caller);
6557 		return (B_FALSE);
6558 	}
6559 	while (count--) {
6560 		*((uint32_t *)mp->b_wptr) = *data;
6561 		mp->b_wptr += sizeof (*data);
6562 		++data;
6563 	}
6564 	putnext(rq, mp);
6565 	return (B_TRUE);
6566 }
6567 
6568 /* CLONE */
6569 static int
6570 scsb_queue_ops(scsb_state_t	*scsb,
6571 		int		op,
6572 		int		oparg,
6573 		void		*opdata,
6574 		char		*caller)
6575 {
6576 	clone_dev_t	*clptr;
6577 	int		clone, find_open, find_available, retval = QOP_FAILED;
6578 
6579 	switch (op) {
6580 	case QPUT_INT32:
6581 		if (scsb->scsb_opens && scsb->scsb_rq != NULL &&
6582 				scsb_queue_put(scsb->scsb_rq, oparg,
6583 				(uint32_t *)opdata, caller) == B_FALSE) {
6584 			return (QOP_FAILED);
6585 		}
6586 	/*FALLTHROUGH*/	/* to look for opened clones */
6587 	case QPROCSOFF:
6588 		retval = QOP_OK;
6589 	/*FALLTHROUGH*/
6590 	case QFIRST_OPEN:
6591 	case QFIND_QUEUE:
6592 		find_open = 1;
6593 		find_available = 0;
6594 		break;
6595 	case QFIRST_AVAILABLE:
6596 		find_available = 1;
6597 		find_open = 0;
6598 		break;
6599 	}
6600 	for (clone = SCSB_CLONES_FIRST; clone < SCSB_CLONES_MAX; clone++) {
6601 		clptr = &scsb->clone_devs[clone];
6602 		if (find_open && clptr->cl_flags & SCSB_OPEN) {
6603 			if (clptr->cl_rq == NULL) {
6604 				cmn_err(CE_WARN, "%s: Clone %d has no queue",
6605 						caller, clptr->cl_minor);
6606 				return (QOP_FAILED);
6607 			}
6608 			switch (op) {
6609 			case QPROCSOFF:
6610 				qprocsoff(clptr->cl_rq);
6611 				break;
6612 			case QPUT_INT32:
6613 				if (scsb_queue_put(clptr->cl_rq, oparg,
6614 						(uint32_t *)opdata, caller)
6615 						== B_FALSE) {
6616 					retval = QOP_FAILED;
6617 				}
6618 				break;
6619 			case QFIRST_OPEN:
6620 				return (clone);
6621 			case QFIND_QUEUE:
6622 				if (clptr->cl_rq == (queue_t *)opdata) {
6623 					return (clone);
6624 				}
6625 				break;
6626 			}
6627 		} else if (find_available && clptr->cl_flags == 0) {
6628 			switch (op) {
6629 			case QFIRST_AVAILABLE:
6630 				return (clone);
6631 			}
6632 		}
6633 	}
6634 	return (retval);
6635 }
6636 
6637 /*
6638  * Find out if a bit is set for the FRU type and unit number in the register
6639  * set defined by the register base table index, base.
6640  * Returns TRUE if bit is set, or FALSE.
6641  */
6642 static int
6643 scsb_fru_op(scsb_state_t *scsb, scsb_utype_t fru_type, int unit, int base,
6644 									int op)
6645 {
6646 	int		rc;
6647 	uchar_t		reg;
6648 	int		tmp, idx, code, offset;
6649 
6650 #if 0
6651 		reg = SCSB_REG_ADDR(i);
6652 		ac_mask = 1 << FRU_OFFSET(SCTRL_EVENT_ALARM, SCTRL_RESET_BASE);
6653 		ac_val = scsb->scsb_data_reg[index+1] & ac_mask;
6654 #endif
6655 	/* get the event code based on which we get the reg and bit offsets */
6656 	code   = FRU_UNIT_TO_EVCODE(fru_type, unit);
6657 	/* get the bit offset in the 8bit register corresponding to the event */
6658 	offset = FRU_OFFSET(code, base);
6659 	/* register offset from the base register, based on the event code */
6660 	if ((fru_type == ALARM) && (base == SCTRL_RESET_BASE))
6661 		tmp = ALARM_RESET_REG_INDEX(code, base);
6662 	else
6663 		tmp = FRU_REG_INDEX(code, base);
6664 	/* get the global offset of the register in the parent address space */
6665 	reg    = SCSB_REG_ADDR(tmp);
6666 	/* get the global index of the register in this SCSB's address space */
6667 	idx    = SCSB_REG_INDEX(reg);
6668 	DEBUG4("scsb_fru_op(start): code=%x, offset=%x, tmp=%x, reg=%x\n",
6669 			code, offset, tmp, reg);
6670 	switch (op) {
6671 		case SCSB_FRU_OP_GET_REG:
6672 			rc = reg;
6673 			break;
6674 		case SCSB_FRU_OP_GET_BITVAL:
6675 			rc = (scsb->scsb_data_reg[idx] & (1 << offset))
6676 							>> offset;
6677 			break;
6678 		case SCSB_FRU_OP_GET_REGDATA:
6679 			rc = scsb->scsb_data_reg[idx];
6680 			break;
6681 		case SCSB_FRU_OP_SET_REGBIT:
6682 			rc = (1 << offset) & 0xff;
6683 			break;
6684 		default:
6685 			break;
6686 	}
6687 	DEBUG4("scsb_fru_op: unit=%x, base=%x, op=%d, rc=%x\n", unit, base,
6688 					op, rc);
6689 	return (rc);
6690 }
6691 
6692 /*
6693  * All HSC related functions can fail, but an attempt is made to atleast
6694  * return the right shadow state  on get-state function when SCB is removed.
6695  */
6696 int
6697 scsb_get_slot_state(scsb_state_t *scsb, int pslotnum, int *rstate)
6698 {
6699 	int		slotnum, val = 0, rc;
6700 
6701 	/*
6702 	 * When SCB is removed, we could be called with the lock held.
6703 	 * We call check_config_status anyway since it is a read-only operation
6704 	 * and HSC could be invoking this function at interrupt context.
6705 	 * If scsb is already in the doing interrupt postprocess, wait..
6706 	 */
6707 
6708 	rc = scsb_check_config_status(scsb);
6709 
6710 	/* check if error is because SCB is removed */
6711 	if ((rc != EAGAIN) && (rc != DDI_SUCCESS))
6712 		return (DDI_FAILURE);
6713 	slotnum = tonga_psl_to_ssl(scsb, pslotnum);
6714 	val = scsb_fru_op(scsb, SLOT, slotnum, SCTRL_SYSCFG_BASE,
6715 					SCSB_FRU_OP_GET_BITVAL);
6716 	if (! val) {
6717 		*rstate = HPC_SLOT_EMPTY;
6718 		return (0);
6719 	}
6720 	/*
6721 	 * now, lets determine if it is connected or disconnected.
6722 	 * If reset is asserted, then the slot is disconnected.
6723 	 */
6724 	rc = scsb_reset_slot(scsb, pslotnum, SCSB_GET_SLOT_RESET_STATUS);
6725 	/* check if error is because SCB is removed */
6726 	if ((rc != EAGAIN) && (rc != DDI_SUCCESS))
6727 		return (DDI_FAILURE);
6728 	val = scsb_fru_op(scsb, SLOT, slotnum, SCTRL_RESET_BASE,
6729 					SCSB_FRU_OP_GET_BITVAL);
6730 	if (val)
6731 		*rstate = HPC_SLOT_DISCONNECTED;
6732 	else {
6733 		if (scsb_fru_op(scsb, SLOT, slotnum, SCTRL_BHLTHY_BASE,
6734 					SCSB_FRU_OP_GET_BITVAL)) {
6735 			*rstate = HPC_SLOT_CONNECTED;
6736 		} else {
6737 			cmn_err(CE_WARN, "%s#%d: Reset Not Asserted on "
6738 				"Healthy# Failed slot %d!",
6739 				ddi_driver_name(scsb->scsb_dev),
6740 				ddi_get_instance(scsb->scsb_dev), slotnum);
6741 			*rstate = HPC_SLOT_DISCONNECTED;
6742 		}
6743 	}
6744 	return (0);
6745 }
6746 
6747 int
6748 scsb_reset_slot(scsb_state_t *scsb, int pslotnum, int reset_flag)
6749 {
6750 	int		slotnum, error, val, alarm_card = 0;
6751 	i2c_transfer_t	*i2cxferp;
6752 	uchar_t		reg;
6753 	int		index, condition_exists = 0, ac_val;
6754 
6755 	if (scsb_debug & 0x8001)
6756 		cmn_err(CE_NOTE, "scsb_reset_slot(%d), flag %x", pslotnum,
6757 						reset_flag);
6758 	if (scsb->scsb_state & SCSB_FROZEN)
6759 		return (EAGAIN);
6760 	if ((i2cxferp = scsb_alloc_i2ctx(scsb->scsb_phandle,
6761 		I2C_NOSLEEP)) == NULL) {
6762 		return (ENOMEM);
6763 	}
6764 	slotnum = tonga_psl_to_ssl(scsb, pslotnum);
6765 
6766 	if (scsb_is_alarm_card_slot(scsb, pslotnum) == B_TRUE) {
6767 		DEBUG0("alarm card  reset/unreset op:\n");
6768 		alarm_card = 1;
6769 	}
6770 	reg = SCSB_REG_ADDR(SCTRL_RESET_BASE);
6771 	index = SCSB_REG_INDEX(reg);
6772 
6773 	mutex_enter(&scsb->scsb_mutex);
6774 	i2cxferp->i2c_flags = I2C_WR_RD;
6775 	i2cxferp->i2c_rlen = SCTRL_RESET_NUMREGS;
6776 	i2cxferp->i2c_wbuf[0] = reg;
6777 	i2cxferp->i2c_wlen = 1;
6778 	scsb->scsb_kstat_flag = B_TRUE;	/* we did an i2c transaction */
6779 	if ((error = nct_i2c_transfer(scsb->scsb_phandle, i2cxferp)) == 0) {
6780 		scsb->scsb_i2c_errcnt = 0;
6781 		/*
6782 		 * XXX: following statements assume 2 reset registers,
6783 		 * which is the case for our current SCB revisions.
6784 		 */
6785 		scsb->scsb_data_reg[index]   = i2cxferp->i2c_rbuf[0];
6786 		scsb->scsb_data_reg[index+1] = i2cxferp->i2c_rbuf[1];
6787 	} else {
6788 		scsb->scsb_i2c_errcnt++;
6789 		if (scsb->scsb_i2c_errcnt > scsb_err_threshold)
6790 			scsb->scsb_err_flag = B_TRUE; /* latch until kstat */
6791 		if (!(scsb->scsb_state & SCSB_SSB_PRESENT)) {
6792 			if (scsb->scsb_i2c_errcnt >= scsb_freeze_count)
6793 				mutex_exit(&scsb->scsb_mutex);
6794 				scsb_freeze(scsb);
6795 				mutex_enter(&scsb->scsb_mutex);
6796 		}
6797 		cmn_err(CE_WARN, "%s#%d: scsb_reset_slot: error"
6798 			" reading Reset regs\n",
6799 				ddi_driver_name(scsb->scsb_dev),
6800 				ddi_get_instance(scsb->scsb_dev));
6801 		error = DDI_FAILURE;
6802 	}
6803 
6804 	DEBUG2("pre-reset regs = %x,%x\n", scsb->scsb_data_reg[index],
6805 					scsb->scsb_data_reg[index+1]);
6806 	if ((reset_flag == SCSB_GET_SLOT_RESET_STATUS) || (error)) {
6807 		mutex_exit(&scsb->scsb_mutex);
6808 		scsb_free_i2ctx(scsb->scsb_phandle, i2cxferp);
6809 		return (error);
6810 	}
6811 
6812 	val = scsb_fru_op(scsb, SLOT, slotnum, SCTRL_RESET_BASE,
6813 					SCSB_FRU_OP_GET_BITVAL);
6814 	if (alarm_card) {
6815 		ac_val = scsb_fru_op(scsb, ALARM, 1, SCTRL_RESET_BASE,
6816 					SCSB_FRU_OP_GET_BITVAL);
6817 	}
6818 	if (val && (reset_flag == SCSB_RESET_SLOT)) {
6819 		if (alarm_card) {
6820 			if (ac_val) {
6821 				condition_exists = 1;
6822 				DEBUG0("Alarm_RST# already active.\n");
6823 			}
6824 #ifndef	lint
6825 			else
6826 				DEBUG1("Alarm_RST# not active! "
6827 					"Slot%d_RST# active!\n", pslotnum);
6828 #endif
6829 		} else {
6830 			condition_exists = 1;
6831 			DEBUG1("Slot%d_RST# already active!\n", pslotnum);
6832 		}
6833 	}
6834 	else
6835 		if ((val == 0) && (reset_flag == SCSB_UNRESET_SLOT)) {
6836 			if (alarm_card) {
6837 				if (!ac_val) {
6838 					DEBUG0("Alarm_RST# not active.\n");
6839 					condition_exists = 1;
6840 				}
6841 #ifndef	lint
6842 				else
6843 					DEBUG1("Alarm_RST# active"
6844 						" Slot%d_RST# not active!\n",
6845 								pslotnum);
6846 #endif
6847 			} else {
6848 				condition_exists = 1;
6849 				DEBUG1("Slot%d_RST# already not active!\n",
6850 						pslotnum);
6851 			}
6852 		}
6853 
6854 	if (! condition_exists) {
6855 		i2cxferp->i2c_flags = I2C_WR;
6856 		i2cxferp->i2c_wlen = 2;
6857 		i2cxferp->i2c_wbuf[0] = scsb_fru_op(scsb, SLOT, slotnum,
6858 				SCTRL_RESET_BASE, SCSB_FRU_OP_GET_REG);
6859 		if (reset_flag == SCSB_RESET_SLOT) {
6860 			i2cxferp->i2c_wbuf[1] =
6861 				scsb_fru_op(scsb, SLOT, slotnum,
6862 					SCTRL_RESET_BASE,
6863 					SCSB_FRU_OP_GET_REGDATA) |
6864 					scsb_fru_op(scsb, SLOT, slotnum,
6865 					SCTRL_RESET_BASE,
6866 					SCSB_FRU_OP_SET_REGBIT);
6867 #ifdef	DEBUG		/* dont reset Alarm Card line unless in debug mode */
6868 			if (alarm_card)
6869 				i2cxferp->i2c_wbuf[1] |=
6870 					scsb_fru_op(scsb, ALARM, 1,
6871 						SCTRL_RESET_BASE,
6872 						SCSB_FRU_OP_SET_REGBIT);
6873 #endif
6874 		} else {
6875 			i2cxferp->i2c_wbuf[1] =
6876 				scsb_fru_op(scsb, SLOT, slotnum,
6877 					SCTRL_RESET_BASE,
6878 					SCSB_FRU_OP_GET_REGDATA) &
6879 					~(scsb_fru_op(scsb, SLOT, slotnum,
6880 					SCTRL_RESET_BASE,
6881 					SCSB_FRU_OP_SET_REGBIT));
6882 #ifdef	DEBUG		/* dont Unreset Alarm Card line unless in debug mode */
6883 			if (alarm_card)
6884 				i2cxferp->i2c_wbuf[1] &=
6885 					scsb_fru_op(scsb, ALARM, 1,
6886 						SCTRL_RESET_BASE,
6887 						SCSB_FRU_OP_SET_REGBIT);
6888 #endif
6889 		}
6890 
6891 		if (error = nct_i2c_transfer(scsb->scsb_phandle, i2cxferp)) {
6892 			scsb->scsb_i2c_errcnt++;
6893 			if (scsb->scsb_i2c_errcnt > scsb_err_threshold)
6894 				scsb->scsb_err_flag = B_TRUE; /* latch error */
6895 			mutex_exit(&scsb->scsb_mutex);
6896 			if (!(scsb->scsb_state & SCSB_SSB_PRESENT)) {
6897 				if (scsb->scsb_i2c_errcnt >= scsb_freeze_count)
6898 					scsb_freeze(scsb);
6899 			}
6900 			cmn_err(CE_WARN, "%s#%d: reset_slot: error writing to"
6901 				" Reset regs (op=%d, data=%x)\n",
6902 				ddi_driver_name(scsb->scsb_dev),
6903 				ddi_get_instance(scsb->scsb_dev),
6904 				reset_flag, i2cxferp->i2c_wbuf[1]);
6905 			scsb_free_i2ctx(scsb->scsb_phandle, i2cxferp);
6906 			return (DDI_FAILURE);
6907 		}
6908 
6909 		scsb->scsb_i2c_errcnt = 0;
6910 		/* now read back and update our scsb structure */
6911 		i2cxferp->i2c_flags = I2C_WR_RD;
6912 		i2cxferp->i2c_rlen = SCTRL_RESET_NUMREGS;
6913 		i2cxferp->i2c_wbuf[0] = reg;
6914 		i2cxferp->i2c_wlen = 1;
6915 		if ((error = nct_i2c_transfer(scsb->scsb_phandle,
6916 				i2cxferp)) == 0) {
6917 			scsb->scsb_i2c_errcnt = 0;
6918 			scsb->scsb_data_reg[index]   = i2cxferp->i2c_rbuf[0];
6919 			scsb->scsb_data_reg[index+1] = i2cxferp->i2c_rbuf[1];
6920 		} else {
6921 			scsb->scsb_i2c_errcnt++;
6922 			if (scsb->scsb_i2c_errcnt > scsb_err_threshold)
6923 				scsb->scsb_err_flag = B_TRUE; /* latch error */
6924 			mutex_exit(&scsb->scsb_mutex);
6925 			if (!(scsb->scsb_state & SCSB_SSB_PRESENT)) {
6926 				if (scsb->scsb_i2c_errcnt >= scsb_freeze_count)
6927 					scsb_freeze(scsb);
6928 			}
6929 			cmn_err(CE_WARN, "%s#%d: scsb_reset_slot: error"
6930 				" reading Reset regs (post reset)\n",
6931 				ddi_driver_name(scsb->scsb_dev),
6932 				ddi_get_instance(scsb->scsb_dev));
6933 			scsb_free_i2ctx(scsb->scsb_phandle, i2cxferp);
6934 			return (DDI_FAILURE);
6935 		}
6936 		/* XXX: P1.5 */
6937 		DEBUG2("post-reset regs = %x,%x\n", scsb->scsb_data_reg[index],
6938 					scsb->scsb_data_reg[index+1]);
6939 		val = scsb_fru_op(scsb, SLOT, slotnum, SCTRL_RESET_BASE,
6940 					SCSB_FRU_OP_GET_BITVAL);
6941 #ifdef	DEBUG
6942 		if (alarm_card)
6943 			ac_val = scsb_fru_op(scsb, ALARM, 1, SCTRL_RESET_BASE,
6944 					SCSB_FRU_OP_GET_BITVAL);
6945 #endif
6946 		if (val && (reset_flag == SCSB_UNRESET_SLOT)) {
6947 			cmn_err(CE_WARN, "Cannot UnReset Slot %d (reg=%x)\n",
6948 				pslotnum,
6949 				scsb_fru_op(scsb, SLOT, slotnum,
6950 					SCTRL_RESET_BASE,
6951 					SCSB_FRU_OP_GET_REGDATA));
6952 #ifdef	DEBUG
6953 			if (alarm_card) {
6954 				if (ac_val)
6955 					cmn_err(CE_WARN, "Cannot Unreset "
6956 							"Alarm_RST#.\n");
6957 			}
6958 #endif
6959 		}
6960 		else
6961 			if ((val == 0) && (reset_flag == SCSB_RESET_SLOT)) {
6962 				cmn_err(CE_WARN, "Cannot Reset Slot %d, "
6963 					"reg=%x\n", pslotnum,
6964 					scsb_fru_op(scsb, SLOT, slotnum,
6965 						SCTRL_RESET_BASE,
6966 						SCSB_FRU_OP_GET_REGDATA));
6967 #ifdef	DEBUG
6968 				if (alarm_card) {
6969 					if (!ac_val)
6970 						cmn_err(CE_WARN, "Cannot reset "
6971 							"Alarm_RST#.\n");
6972 				}
6973 #endif
6974 			}
6975 	}
6976 
6977 	mutex_exit(&scsb->scsb_mutex);
6978 	scsb_free_i2ctx(scsb->scsb_phandle, i2cxferp);
6979 
6980 	return (error);
6981 }
6982 
6983 int
6984 scsb_connect_slot(scsb_state_t *scsb, int pslotnum, int healthy)
6985 {
6986 	int slotnum, count = 0, val;
6987 	int slot_flag = 0;
6988 
6989 	/*
6990 	 * If Power needs to be handled, it should be done here.
6991 	 * Since there is no power handling for now, lets disable
6992 	 * reset, wait for healthy to come on and then call it
6993 	 * connected.
6994 	 * If HLTHY# does not come on (in how long is the question)
6995 	 * then we stay disconnected.
6996 	 */
6997 	slotnum = tonga_psl_to_ssl(scsb, pslotnum);
6998 
6999 	/*
7000 	 * P1.5 doesnt require polling healthy as we get an
7001 	 * interrupt. So we could just update our state as disconnected
7002 	 * and return waiting for the healthy# interrupt. To make it
7003 	 * more efficient, lets poll for healthy# a short while since we are
7004 	 * in the interrupt context anyway. If we dont get a healthy# we
7005 	 * return, and then wait for the interrupt. Probably the warning
7006 	 * message needs to be removed then. Need a PROM check flag here.
7007 	 */
7008 	while ((healthy == B_FALSE) && (count < scsb_healthy_poll_count)) {
7009 		if (scsb_read_bhealthy(scsb) != 0)
7010 			return (DDI_FAILURE);
7011 		val = scsb_fru_op(scsb, SLOT, slotnum, SCTRL_BHLTHY_BASE,
7012 					SCSB_FRU_OP_GET_BITVAL);
7013 		if (val) {
7014 			healthy = B_TRUE;
7015 			break;
7016 		}
7017 		count++;
7018 		drv_usecwait(100);	/* cant delay(9f) in intr context */
7019 	}
7020 
7021 	if (healthy == B_FALSE && count == scsb_healthy_poll_count) {
7022 		if (scsb_debug & 0x00004000)
7023 			cmn_err(CE_WARN, "%s#%d: no HEALTHY# signal on"
7024 				" slot %d", ddi_driver_name(scsb->scsb_dev),
7025 				ddi_get_instance(scsb->scsb_dev), pslotnum);
7026 	}
7027 
7028 	if ((scsb_is_alarm_card_slot(scsb, pslotnum) == B_TRUE) &&
7029 			(scsb->scsb_hsc_state & SCSB_ALARM_CARD_PRES))
7030 		slot_flag = ALARM_CARD_ON_SLOT;
7031 	return (hsc_slot_occupancy(pslotnum, 1, slot_flag, healthy));
7032 }
7033 
7034 int
7035 scsb_disconnect_slot(scsb_state_t *scsb, int occupied, int slotnum)
7036 {
7037 	int slot_flag = 0;
7038 
7039 	/* Reset is must at extraction. Move on even if failure. */
7040 	if (scsb_reset_slot(scsb, slotnum, SCSB_RESET_SLOT) != 0) {
7041 		/*
7042 		 * If board is still in slot, which means there is a manual
7043 		 * disconnection in progress, return failure.
7044 		 * Otherwise, a board was removed anyway; so we need to
7045 		 * update the status and move on.
7046 		 */
7047 		if (occupied == B_TRUE)
7048 			return (DDI_FAILURE);
7049 	}
7050 	/*
7051 	 * the following bug needs to be fixed.
7052 	 * When this function is called from scsb_intr, scsb_state already
7053 	 * clears the 'AC card present' bit.
7054 	 * However, hsc module doesn't depend on slot_flag during removal.
7055 	 */
7056 	if ((scsb_is_alarm_card_slot(scsb, slotnum) == B_TRUE) &&
7057 			(scsb->scsb_hsc_state & SCSB_ALARM_CARD_PRES))
7058 		slot_flag = ALARM_CARD_ON_SLOT;
7059 	return (hsc_slot_occupancy(slotnum, occupied, slot_flag, B_FALSE));
7060 }
7061 
7062 static int
7063 scsb_is_alarm_card_slot(scsb_state_t *scsb, int slotnum)
7064 {
7065 	return ((scsb->ac_slotnum == slotnum)? B_TRUE:B_FALSE);
7066 }
7067 
7068 /*
7069  * Invoked both by the hsc and the scsb module to exchanges necessary
7070  * information regarding the alarm card.
7071  * scsb calls this function to unconfigure the alarm card while the
7072  * hsc calls this function at different times to check busy status,
7073  * and during post hotswap insert operation so that the user process
7074  * if one waiting can configure the alarm card.
7075  */
7076 int
7077 scsb_hsc_ac_op(scsb_state_t *scsb, int pslotnum, int op)
7078 {
7079 	int		rc = B_FALSE;
7080 	uint32_t	event_code;
7081 
7082 	if (!(scsb->scsb_hsc_state & SCSB_HSC_INIT &&
7083 		scsb->scsb_hsc_state & SCSB_ALARM_CARD_PRES)) {
7084 		cmn_err(CE_WARN,
7085 			"scsb: HSC not initialized or AC not present!");
7086 		return (rc);
7087 	}
7088 	switch (op) {
7089 		/* hsc -> scsb */
7090 		case SCSB_HSC_AC_BUSY:
7091 			if (scsb->scsb_hsc_state & SCSB_ALARM_CARD_IN_USE)
7092 				rc = B_TRUE;
7093 			break;
7094 
7095 		/* API -> scsb */
7096 		/*
7097 		 * NOTE: this could be called multiple times from envmond if
7098 		 * the daemon is reinitialized with SIGHUP, or stopped and
7099 		 * restarted.
7100 		 */
7101 		case SCSB_HSC_AC_SET_BUSY:
7102 			DEBUG0("AC SET BUSY\n");
7103 			if (scsb_debug & 0x00010000) {
7104 				cmn_err(CE_NOTE,
7105 					"scsb_hsc_ac_op(SCSB_HSC_AC_SET_BUSY)");
7106 			}
7107 			scsb->scsb_hsc_state |= SCSB_ALARM_CARD_IN_USE;
7108 			rc = B_TRUE;
7109 			break;
7110 
7111 		/* hsc -> scsb */
7112 		case SCSB_HSC_AC_CONFIGURED:
7113 			DEBUG0("AC configured\n");
7114 			if (scsb_debug & 0x00010000) {
7115 				cmn_err(CE_NOTE,
7116 				"scsb_hsc_ac_op(SCSB_HSC_AC_CONFIGURED)");
7117 			}
7118 			/*
7119 			 * wakeup anyone waiting on AC to be configured
7120 			 * Send the ALARM_CARD_CONFIGURE Event to all scsb
7121 			 * open streams.
7122 			 */
7123 			event_code = SCTRL_EVENT_ALARM_INSERTION;
7124 			(void) scsb_queue_ops(scsb, QPUT_INT32, 1,
7125 						&event_code, "scsb_hsc_ac_op");
7126 			rc = B_TRUE;
7127 			break;
7128 
7129 		/* hsc -> scsb */
7130 		case SCSB_HSC_AC_REMOVAL_ALERT:
7131 			DEBUG0("AC removal alert\n");
7132 			if (scsb_debug & 0x00010000) {
7133 				cmn_err(CE_NOTE,
7134 				"scsb_hsc_ac_op(SCSB_HSC_AC_REMOVAL_ALERT)");
7135 			}
7136 			/*
7137 			 * Inform (envmond)alarmcard.so that it should save
7138 			 * the AC configuration, stop the
7139 			 * heartbeat, and shutdown the RSC link.
7140 			 */
7141 			event_code = SCTRL_EVENT_ALARM_REMOVAL;
7142 			(void) scsb_queue_ops(scsb, QPUT_INT32, 1,
7143 						&event_code, "scsb_hsc_ac_op");
7144 			rc = B_TRUE;
7145 			break;
7146 
7147 		/* API -> scsb -> hsc */
7148 		case SCSB_HSC_AC_UNCONFIGURE:
7149 			DEBUG0("AC unconfigure\n");
7150 			if (scsb_debug & 0x00010000) {
7151 				cmn_err(CE_NOTE,
7152 					"scsb_hsc_ac_op(SCSB_HSC_AC_UNCONFIG"
7153 					"URE), AC NOT BUSY");
7154 			}
7155 			/*
7156 			 * send notification back to HSC to
7157 			 * unconfigure the AC, now that the env monitor
7158 			 * has given permission to do so.
7159 			 */
7160 			scsb->scsb_hsc_state &= ~SCSB_ALARM_CARD_IN_USE;
7161 			hsc_ac_op(scsb->scsb_instance, pslotnum,
7162 					SCSB_HSC_AC_UNCONFIGURE, NULL);
7163 			rc = B_TRUE;
7164 			break;
7165 		default:
7166 			break;
7167 	}
7168 
7169 	return (rc);
7170 }
7171 
7172 static void
7173 scsb_healthy_intr(scsb_state_t *scsb, int pslotnum)
7174 {
7175 	int val, slotnum;
7176 	int healthy = B_FALSE;
7177 
7178 	DEBUG1("Healthy Intr on slot %d\n", pslotnum);
7179 	/*
7180 	 * The interrupt source register can have the healthy
7181 	 * bit set for non-existing slot, e.g slot 7 on Tonga.
7182 	 * It can also be seen on the Tonga CPU slot. So we make
7183 	 * sure we have a valid slot before proceeding.
7184 	 */
7185 	if (scsb->scsb_state & SCSB_IS_TONGA) {
7186 		if (pslotnum > TG_MAX_SLOTS || pslotnum == SC_TG_CPU_SLOT) {
7187 			if (scsb_debug & 0x08000000)
7188 				cmn_err(CE_NOTE, "Healthy interrupt bit set for"
7189 					" slot %d", pslotnum);
7190 		return;
7191 		}
7192 	} else {
7193 		if (pslotnum > MC_MAX_SLOTS || pslotnum == SC_MC_CPU_SLOT ||
7194 			(scsb->scsb_hsc_state & SCSB_HSC_CTC_PRES &&
7195 			pslotnum == SC_MC_CTC_SLOT)) {
7196 			if (scsb_debug & 0x08000000)
7197 				cmn_err(CE_NOTE, "Healthy interrupt bit set for"
7198 					" slot %d", pslotnum);
7199 		return;
7200 		}
7201 	}
7202 
7203 	/*
7204 	 * The board healthy registers are already read before entering
7205 	 * this routine
7206 	 */
7207 	slotnum = tonga_psl_to_ssl(scsb, pslotnum);
7208 
7209 	/*
7210 	 * P1.5. Following works since slots 1 through 8 are in the same reg
7211 	 */
7212 	val = scsb_fru_op(scsb, SLOT, slotnum, SCTRL_BHLTHY_BASE,
7213 					SCSB_FRU_OP_GET_BITVAL);
7214 	if (val)
7215 		healthy = B_TRUE;
7216 	scsb_hsc_board_healthy(pslotnum, healthy);
7217 }
7218 
7219 /*
7220  * This function will try to read from scsb irrespective of whether
7221  * SSB is present or SCB is frozen, to get the health kstat information.
7222  */
7223 static int
7224 scsb_blind_read(scsb_state_t *scsb, int op, uchar_t reg, int len,
7225 				uchar_t *rwbuf, int i2c_alloc)
7226 {
7227 	i2c_transfer_t	*i2cxferp;
7228 	int		i, rlen, wlen, error = 0;
7229 
7230 	if (scsb_debug & 0x0800) {
7231 		cmn_err(CE_NOTE, "scsb_rdwr_register(scsb,%s,%x,%x,buf):",
7232 				(op == I2C_WR) ? "write" : "read",  reg, len);
7233 	}
7234 
7235 	if (i2c_alloc) {
7236 		i2cxferp = scsb_alloc_i2ctx(scsb->scsb_phandle, I2C_NOSLEEP);
7237 		if (i2cxferp == NULL) {
7238 			if (scsb_debug & 0x0042)
7239 				cmn_err(CE_WARN, "scsb_rdwr_register: "
7240 						"i2ctx allocation failure");
7241 			return (ENOMEM);
7242 		}
7243 	} else {
7244 		i2cxferp = scsb->scsb_i2ctp;
7245 	}
7246 	switch (op) {
7247 	case I2C_WR:
7248 		wlen = len + 1;	/* add the address */
7249 		rlen = 0;
7250 		i2cxferp->i2c_wbuf[0] = reg;
7251 		for (i = 0; i < len; ++i) {
7252 				i2cxferp->i2c_wbuf[1 + i] = rwbuf[i];
7253 			if (scsb_debug & 0x0080)
7254 				cmn_err(CE_NOTE,
7255 				"scsb_rdwr_register: writing rwbuf[%d]=0x%x",
7256 						i, rwbuf[i]);
7257 		}
7258 		break;
7259 	case I2C_WR_RD:
7260 		wlen = 1;	/* for the address */
7261 		rlen = len;
7262 		i2cxferp->i2c_wbuf[0] = reg;
7263 		break;
7264 	default:
7265 		if (i2c_alloc)
7266 			scsb_free_i2ctx(scsb->scsb_phandle, i2cxferp);
7267 		return (EINVAL);
7268 	}
7269 	/* select the register address */
7270 	i2cxferp->i2c_flags = op;
7271 	i2cxferp->i2c_rlen = rlen;
7272 	i2cxferp->i2c_wlen = wlen;
7273 	i2cxferp->i2c_wbuf[0] = reg;
7274 	scsb->scsb_kstat_flag = B_TRUE;	/* we did a i2c transaction */
7275 	if (error = nct_i2c_transfer(scsb->scsb_phandle, i2cxferp)) {
7276 		error = EIO;
7277 	} else if (rlen) {
7278 		/* copy to rwbuf[] */
7279 		for (i = 0; i < len; ++i) {
7280 			rwbuf[i] = i2cxferp->i2c_rbuf[i];
7281 			if (scsb_debug & 0x0080)
7282 				cmn_err(CE_NOTE,
7283 				"scsb_rdwr_register: read rwbuf[%d]=0x%x",
7284 						i, rwbuf[i]);
7285 		}
7286 	}
7287 	if (i2c_alloc)
7288 		scsb_free_i2ctx(scsb->scsb_phandle, i2cxferp);
7289 	if (error) {
7290 		scsb->scsb_i2c_errcnt++;
7291 		if (scsb->scsb_i2c_errcnt > scsb_err_threshold)
7292 			scsb->scsb_err_flag = B_TRUE; /* latch error */
7293 	} else {
7294 		scsb->scsb_i2c_errcnt = 0;
7295 	}
7296 
7297 	return (error);
7298 }
7299 
7300 /*
7301  * This function will quiesce the PSM_INT line by masking the
7302  * global PSM_INT and writing 1 to SCB_INIT ( for P1.5 and later )
7303  * This effectively translates to writing 0x20 to 0xE1 register.
7304  */
7305 static int
7306 scsb_quiesce_psmint(scsb_state_t *scsb)
7307 {
7308 	register int	i;
7309 	uchar_t	reg, wdata = 0;
7310 	uchar_t	tmp_reg, intr_addr, clr_bits = 0;
7311 	int error, iid, intr_idx, offset;
7312 
7313 	/*
7314 	 * For P1.5, set the SCB_INIT bit in the System Command register,
7315 	 * and disable global PSM_INT. Before this we need to read the
7316 	 * interrupt source register corresponding to INIT_SCB and
7317 	 * clear if set.
7318 	 */
7319 	if (IS_SCB_P15) {
7320 		/*
7321 		 * Read INTSRC6 and write back 0x20 in case INIT_SCB is set
7322 		 */
7323 		intr_addr = SCSB_REG_ADDR(SCTRL_INTSRC_BASE);
7324 		tmp_reg = SCSB_REG_ADDR(SCTRL_INTSRC_SCB_P15);
7325 		iid = SCSB_REG_INDEX(intr_addr);
7326 		intr_idx = SCSB_REG_INDEX(tmp_reg) - iid;
7327 		offset = FRU_OFFSET(SCTRL_EVENT_SCB, SCTRL_INTPTR_BASE);
7328 		clr_bits = 1 << offset;
7329 
7330 		error = scsb_rdwr_register(scsb, I2C_WR_RD, tmp_reg,
7331 					1, &scb_intr_regs[intr_idx], 0);
7332 		/*
7333 		 * Now mask the global PSM_INT and write INIT_SCB in case
7334 		 * this is an INIT_SCB interrupt
7335 		 */
7336 		wdata = 1 << SYS_OFFSET(SCTRL_SYS_SCB_INIT);
7337 		i = SYS_REG_INDEX(SCTRL_SYS_SCB_INIT, SCTRL_SYS_CMD_BASE);
7338 		reg = SCSB_REG_ADDR(i);
7339 		error = scsb_rdwr_register(scsb, I2C_WR, reg, 1,
7340 					&wdata, 0);
7341 
7342 		if (scb_intr_regs[intr_idx] & clr_bits) {
7343 			/*
7344 			 * There is an SCB_INIT interrupt, which we must clear
7345 			 * first to keep SCB_INIT from keeping PSM_INT asserted.
7346 			 */
7347 			error = scsb_rdwr_register(scsb, I2C_WR, tmp_reg,
7348 						1, &clr_bits, 0);
7349 		}
7350 
7351 		if (error) {
7352 			cmn_err(CE_WARN, "scsb%d:scsb_quiesce_psmint: "
7353 				" I2C TRANSFER Failed", scsb->scsb_instance);
7354 			if (scsb_debug & 0x0006) {
7355 				cmn_err(CE_NOTE, "scsb_attach: "
7356 					" failed to set SCB_INIT");
7357 			}
7358 		}
7359 		scsb->scsb_state &= ~SCSB_PSM_INT_ENABLED;
7360 	} else { /* P1.0 or earlier */
7361 		/*
7362 		 * read the interrupt source registers, and then
7363 		 * write them back.
7364 		 */
7365 		/* read the interrupt register from scsb */
7366 		if (error = scsb_rdwr_register(scsb, I2C_WR_RD, intr_addr,
7367 					SCTRL_INTR_NUMREGS, scb_intr_regs, 0)) {
7368 			cmn_err(CE_WARN, "scsb_intr: "
7369 				" Failed read of interrupt registers.");
7370 			scsb->scsb_state &= ~SCSB_IN_INTR;
7371 		}
7372 
7373 		/*
7374 		 * Write to the interrupt source registers to stop scsb
7375 		 * from interrupting.
7376 		 */
7377 		if (error = scsb_rdwr_register(scsb, I2C_WR, intr_addr,
7378 					SCTRL_INTR_NUMREGS, scb_intr_regs, 0)) {
7379 			cmn_err(CE_WARN, "scsb_intr: Failed write to interrupt"
7380 					" registers.");
7381 			scsb->scsb_state &= ~SCSB_IN_INTR;
7382 		}
7383 
7384 	}
7385 
7386 	if (error)
7387 		return (DDI_FAILURE);
7388 	else
7389 		return (DDI_SUCCESS);
7390 }
7391 
7392 /*
7393  * Enables or disables the global PSM_INT interrupt for P1.5, depending
7394  * on the flag, flag = 0 => disable, else enable.
7395  */
7396 static int
7397 scsb_toggle_psmint(scsb_state_t *scsb, int enable)
7398 {
7399 	int i;
7400 	uchar_t reg, on = 0, rmask = 0x0, off = 0;
7401 
7402 	if (enable == B_TRUE) {
7403 		on = 1 << SYS_OFFSET(SCTRL_SYS_PSM_INT_ENABLE);
7404 	} else {
7405 		off = 1 << SYS_OFFSET(SCTRL_SYS_PSM_INT_ENABLE);
7406 	}
7407 
7408 	i = SYS_REG_INDEX(SCTRL_SYS_PSM_INT_ENABLE, SCTRL_SYS_CMD_BASE);
7409 	reg = SCSB_REG_ADDR(i);
7410 	if (scsb_write_mask(scsb, reg, rmask, on, off)) {
7411 		cmn_err(CE_WARN, "scsb_toggle_psmint: Cannot turn %s PSM_INT",
7412 			enable == 1 ? "on" : "off");
7413 		return (DDI_FAILURE);
7414 	}
7415 	if (enable == 0) {
7416 		scsb->scsb_state &= ~SCSB_PSM_INT_ENABLED;
7417 	} else {
7418 		scsb->scsb_state |= SCSB_PSM_INT_ENABLED;
7419 	}
7420 
7421 	return (DDI_SUCCESS);
7422 }
7423 
7424 /*
7425  * This routine is to be used by all the drivers using this i2c bus
7426  * to synchronize their transfer operations.
7427  */
7428 int
7429 nct_i2c_transfer(i2c_client_hdl_t i2c_hdl, i2c_transfer_t *i2c_tran)
7430 {
7431 	int retval, initmux = nct_mutex_init;
7432 
7433 	/*
7434 	 * If scsb interrupt mutex is initialized, also hold the
7435 	 * interrupt mutex to let the i2c_transfer() to complete
7436 	 */
7437 
7438 	if (initmux & MUTEX_INIT) {
7439 		mutex_enter(scb_intr_mutex);
7440 	}
7441 
7442 	retval = i2c_transfer(i2c_hdl, i2c_tran);
7443 
7444 	if (initmux & MUTEX_INIT) {
7445 		mutex_exit(scb_intr_mutex);
7446 	}
7447 
7448 	return (retval);
7449 }
7450