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", ®s, &len) != DDI_PROP_SUCCESS) { 412 cmn_err(CE_WARN, 413 "scsb%d: Failed to get \"reg\" property", instance); 414 ddi_soft_state_free(scsb_state, instance); 415 return (DDI_FAILURE); 416 } 417 scsb->scsb_i2c_addr = regs[1] & SCSB_I2C_ADDR_MASK; 418 if (scsb->scsb_i2c_addr != SCSB_I2C_ADDR) { 419 cmn_err(CE_WARN, "scsb%d: I2C Addr reg %x %x must be %x", 420 instance, regs[0], regs[1], SCSB_I2C_ADDR); 421 ddi_soft_state_free(scsb_state, instance); 422 ddi_prop_free(regs); 423 return (DDI_FAILURE); 424 } 425 /* done with array lookup, free resource */ 426 ddi_prop_free(regs); 427 /* 428 * initialize synchronization mutex and condition var. 429 * for this instance. 430 */ 431 mutex_init(&scsb->scsb_mutex, NULL, MUTEX_DRIVER, NULL); 432 scsb->scsb_state |= SCSB_UMUTEX; 433 cv_init(&scsb->scsb_cv, NULL, CV_DRIVER, NULL); 434 scsb->scsb_state |= SCSB_CONDVAR; 435 436 /* 437 * 1. Read interrupt property of the board and register its handler. 438 * 2. Get scsb private handle for communication via I2C Services. 439 * 3. Allocate and save an i2c_transfer_t for I2C transfers. 440 */ 441 /* 1 */ 442 if (ddi_prop_exists(DDI_DEV_T_ANY, dip, 443 DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, 444 "interrupt-priorities") != 1) { 445 int tmp[2]; 446 tmp[0] = scsb_pil; 447 tmp[1] = hsc_pil; 448 (void) ddi_prop_update_int_array(DDI_DEV_T_NONE, dip, 449 "interrupt-priorities", tmp, 2); 450 scsb->scsb_state |= SCSB_PROP_CREATE; 451 } 452 if ((i = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 453 DDI_PROP_DONTPASS, "interrupts", -1)) >= 0) 454 scsb->scsb_state |= SCSB_P06_INTR_ON; 455 else 456 scsb->scsb_state |= SCSB_P06_NOINT_KLUGE; 457 458 /* 459 * Look for the device-err-threshold property which specifies 460 * on how many errors will scsb send a warning event about it's 461 * health. The scsb_err_threshold is 10 by default. 462 */ 463 if ((i = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 464 DDI_PROP_DONTPASS, "device-err-threshold", -1)) >= 0) { 465 scsb_err_threshold = i; 466 #ifdef DEBUG 467 cmn_err(CE_NOTE, "?scsb_attach: Found device-err-threshold" 468 " property, value %d", scsb_err_threshold); 469 #endif 470 } 471 scsb->scsb_i2c_errcnt = 0; 472 scsb->scsb_err_flag = B_FALSE; 473 scsb->scsb_kstat_flag = B_FALSE; 474 475 /* 476 * If all went well, create the minor node for user level access. 477 */ 478 if (ddi_create_minor_node(dip, scsb_name, S_IFCHR, instance, 479 "ddi_ctl:pcihpc", NULL) == DDI_FAILURE) { 480 cmn_err(CE_WARN, "scsb_attach: Failed to create minor node"); 481 free_resources(dip, scsb, instance); 482 return (DDI_FAILURE); 483 } 484 scsb->scsb_state |= SCSB_MINOR_NODE; 485 scsb->scsb_dev = dip; 486 if (ddi_create_minor_node(dip, scsb_clone_name, S_IFCHR, 487 instance|SCSB_CLONE, "ddi_ctl:pcihpc", NULL) 488 == DDI_FAILURE) { 489 cmn_err(CE_WARN, "scsb_attach: Failed to create clone node"); 490 free_resources(dip, scsb, instance); 491 return (DDI_FAILURE); 492 } 493 /* CLONE */ 494 bzero(scsb->clone_devs, sizeof (clone_dev_t) * SCSB_CLONES_MAX); 495 /* 2 */ 496 if (i2c_client_register(dip, &scsb->scsb_phandle) != I2C_SUCCESS) { 497 cmn_err(CE_WARN, 498 "scsb_attach: Failed I2C Services registration"); 499 free_resources(dip, scsb, instance); 500 return (DDI_FAILURE); 501 } 502 scsb->scsb_state |= SCSB_I2C_PHANDLE; 503 /* 3 */ 504 if ((scsb->scsb_i2ctp = scsb_alloc_i2ctx(scsb->scsb_phandle, 505 I2C_SLEEP)) == NULL) { 506 cmn_err(CE_WARN, 507 "scsb%d: i2c_transfer allocation failed", instance); 508 free_resources(dip, scsb, instance); 509 return (DDI_FAILURE); 510 } 511 scsb->scsb_state |= SCSB_I2C_TRANSFER; 512 /* 513 * Now it's time to INITIALIZE the boards. 514 * 515 * 1. make sure we can do I2C bus transfers to/from the SCB. 516 * Read the SCB PROM version for a check. 517 * 2. set SCB_INITIALIZED bit in SysCommand registers (SYS_CMD_BASE) 518 * 3. clear all LED Data registers (8) by writing 0's to turn off 519 * all LEDs on the SSB. 520 * 4. read System Configuration Status registers (SCTRL_CFG) 521 * to find present FRUs and set corresponding FRU bits at 522 * LED_DATA_BASE. 523 * Also enable devices in Topology map for the current MP_ID 524 * and set the OK LEDs on the SSB. 525 * 5. read Brd_Hlthy registers (2 @ BRD_HLTHY_BASE) 526 * 6. Disable PSM Interrupts during initialization, mask all 527 * interrupts, and clear Interrupt Pointer registers 528 * by writing 0xFF to each register. 529 * 7. set SCB EEPROM address bits SPA2-SPA0 at SYS_CMD_BASE + 1 530 * 8. Install the interrupt handler if appropriate. 531 * 9. clear appropriate bits in Interrupt Mask register for those 532 * devices that can be present for this MP_ID Topology. 533 * 10. enable PSM Interrupt by writing '1' to PSM_INT_EN bit at 534 * SYS_CMD_BASE + 1 535 * Also update all shadow registers for test utility 536 * if scsb_debug is set. 537 * 11. Check if Alarm Card present at boot and set flags 538 * 12. Call hsc_attach() for slot registration. 539 * 13. Allocate, initialze, and install the kstat structures. 540 * 14. Set scsb_state_t flags to indicate SCB is ready 541 * and announce the driver is loaded. 542 */ 543 544 /* 1. through 7. */ 545 if (initialize_scb(scsb) != DDI_SUCCESS) { 546 if (!(scsb_debug)) { 547 free_resources(dip, scsb, instance); 548 return (DDI_FAILURE); 549 } 550 } 551 /* 8. */ 552 /* 553 * P0.6 No Interrupt Support 554 * Instead of installing the handler, it will be called from a user 555 * program via smf_ioctl(). This flag provides knowledge of the 556 * necessary workarounds to several scsb routines. 557 */ 558 /* 559 * Now Install interrupt handler 560 */ 561 if (scsb->scsb_state & SCSB_P06_INTR_ON) { 562 if (ddi_get_iblock_cookie(dip, instance, 563 &scsb->scsb_iblock) == DDI_SUCCESS) { 564 mutex_init(&scsb->scsb_imutex, NULL, MUTEX_DRIVER, 565 (void *)scsb->scsb_iblock); 566 scsb->scsb_state |= SCSB_IMUTEX; 567 if (ddi_add_intr(dip, instance, &scsb->scsb_iblock, 568 NULL, scsb_intr_preprocess, 569 (caddr_t)scsb) != DDI_SUCCESS) { 570 cmn_err(CE_WARN, 571 "scsb_attach: failed interrupt " 572 "handler registration"); 573 free_resources(dip, scsb, instance); 574 return (DDI_FAILURE); 575 } 576 scb_intr_mutex = &scsb->scsb_imutex; 577 nct_mutex_init |= MUTEX_INIT; 578 } else { 579 cmn_err(CE_WARN, "scsb_attach: failed interrupt " 580 "mutex initialization"); 581 if (scsb_debug) { 582 scsb->scsb_state |= SCSB_P06_NOINT_KLUGE; 583 scsb->scsb_state &= ~SCSB_P06_INTR_ON; 584 } else { 585 free_resources(dip, scsb, instance); 586 return (DDI_FAILURE); 587 } 588 } 589 } 590 /* 9. */ 591 if (i = scsb_clear_intmasks(scsb)) { 592 cmn_err(CE_WARN, 593 "scsb%d: I2C TRANSFER Failed", instance); 594 if (!scsb_debug) { 595 free_resources(dip, scsb, instance); 596 return (DDI_FAILURE); 597 } 598 } 599 600 /* 10. */ 601 /* 602 * For P0.6 No Interrupt Support, don't enable PSM Interrupt 603 */ 604 if (!(scsb->scsb_state & SCSB_P06_NOINT_KLUGE)) { 605 rmask = 0x00; 606 wdata = 1 << SYS_OFFSET(SCTRL_SYS_PSM_INT_ENABLE); 607 i = SYS_REG_INDEX(SCTRL_SYS_PSM_INT_ENABLE, 608 SCTRL_SYS_CMD_BASE); 609 reg = SCSB_REG_ADDR(i); 610 if (i = scsb_write_mask(scsb, reg, rmask, wdata, (uchar_t)0)) { 611 cmn_err(CE_WARN, 612 "scsb%d: I2C TRANSFER Failed", instance); 613 if (!scsb_debug) { 614 free_resources(dip, scsb, instance); 615 return (DDI_FAILURE); 616 } 617 } else 618 scsb->scsb_state |= SCSB_PSM_INT_ENABLED; 619 } 620 if (scsb_debug) { 621 /* 622 * For smctrl test utility, 623 * so all data is available in shadow registers 624 * 625 * DEBUG_MODE enables private testing interfaces 626 * DIAGS_MODE permits limited testing interfaces 627 */ 628 scsb->scsb_state |= SCSB_DEBUG_MODE; 629 mutex_enter(&scsb->scsb_mutex); 630 if (scsb_readall_regs(scsb)) 631 cmn_err(CE_WARN, 632 "scsb_attach: scsb_readall FAILED"); 633 mutex_exit(&scsb->scsb_mutex); 634 } 635 /* 11. */ 636 /* Check if Alarm Card present at boot and set flags */ 637 if (scsb_fru_op(scsb, ALARM, 1, SCTRL_SYSCFG_BASE, 638 SCSB_FRU_OP_GET_BITVAL)) 639 scsb->scsb_hsc_state |= SCSB_ALARM_CARD_PRES; 640 641 /* 12. */ 642 if (scsb_debug & 0x0004) 643 cmn_err(CE_NOTE, 644 "scsb_attach: registering cPCI slots"); 645 if (scsb_hsc_attach(dip, scsb, instance) != DDI_SUCCESS) { 646 if (scsb_debug & 0x00008000) { 647 cmn_err(CE_WARN, 648 "scsb: Hotswap controller initialisation" 649 " failed\n"); 650 } 651 } else 652 scsb->scsb_hsc_state |= SCSB_HSC_INIT; 653 /* 13. */ 654 /* 655 * allocate and install the kstat data structures 656 */ 657 if (scsb_alloc_kstats(scsb) != DDI_SUCCESS) { 658 if (scsb_debug & 0x0006) 659 cmn_err(CE_WARN, "scsb_attach: ERROR adding kstats"); 660 } 661 /* 14. */ 662 scsb->scsb_state |= SCSB_UP; 663 scsb_global_state |= SCSB_UP; 664 ddi_report_dev(scsb->scsb_dev); 665 cmn_err(CE_CONT, "?%s%d: " 666 "Prom Version %s, Midplane Id %x\n", 667 ddi_driver_name(scsb->scsb_dev), 668 scsb->scsb_instance, 669 (scsb->scsb_state & SCSB_P06_PROM) ? "0.6" : 670 (scsb->scsb_state & SCSB_P10_PROM) ? "1.0" : 671 (scsb->scsb_state & SCSB_P15_PROM) ? "1.5" : 672 (scsb->scsb_state & SCSB_P20_PROM) ? "2.0" : "Unknown", 673 mct_system_info.mid_plane.fru_id); 674 return (DDI_SUCCESS); 675 } 676 677 /* 678 * This funciton is called from scsb_attach(), and from scsb_intr() as part 679 * of Hot Insertion support, to check the SCB PROM ID register and set 680 * scsb_state bits and register table pointers as necessary. 681 */ 682 static int 683 scb_check_version(scsb_state_t *scsb) 684 { 685 int hotswap = 0; 686 uchar_t data; 687 if (scsb->scsb_state & SCSB_UP) { 688 /* 689 * If driver is UP, then this call is from scsb_intr() 690 * as part of Hot Insertion support. 691 */ 692 hotswap = 1; 693 } 694 /* Read the SCB PROM ID */ 695 if (scsb_rdwr_register(scsb, I2C_WR_RD, (uchar_t)SCTRL_PROM_VERSION, 1, 696 &data, 1)) { 697 if (!(hotswap && scsb->scsb_state & SCSB_FROZEN)) 698 cmn_err(CE_WARN, "scsb%d: I2C TRANSFER Failed", 699 scsb->scsb_instance); 700 if (scsb_debug & 0x0006) { 701 cmn_err(CE_WARN, 702 "scsb_attach(%d): failed read of PROM ID", 703 scsb->scsb_instance); 704 } 705 return (DDI_FAILURE); 706 } 707 /* 708 * compare with stored version number, and if different, 709 * report a warning and keep the driver FROZEN 710 */ 711 if (hotswap) { 712 if (((mct_system_info.fru_info_list[SCB])[0].fru_version & 0xf) 713 == (data & 0xf)) { 714 return (DDI_SUCCESS); 715 } 716 if (scsb_debug & 0x00020000) { 717 cmn_err(CE_NOTE, 718 "scb_check_version: SCB version %d " 719 "replacing version %d", data, 720 (mct_system_info.fru_info_list[SCB])[0]. 721 fru_version & 0xf); 722 } 723 } 724 if ((data & 0xf) == SCTRL_PROM_P06) { 725 scsb->scsb_state |= SCSB_P06_PROM; 726 } else if ((data & 0xf) == SCTRL_PROM_P10) { 727 scsb->scsb_state |= SCSB_P10_PROM; 728 } else if ((data & 0xf) == SCTRL_PROM_P15) { 729 scsb->scsb_state |= SCSB_P15_PROM; 730 } else if ((data & 0xf) == SCTRL_PROM_P20) { 731 scsb->scsb_state |= SCSB_P20_PROM; 732 } 733 if (!(scsb->scsb_state & SCSB_SCB_PRESENT)) 734 scsb->scsb_state |= SCSB_SCB_PRESENT; 735 if (IS_SCB_P10) { 736 scb_reg_index = scb_10_reg_index; 737 scb_numregs = scb_10_numregs; 738 scb_fru_offset = scb_10_fru_offset; 739 scb_sys_offset = scb_10_sys_offset; 740 } else { /* if (IS_SCB_P15) */ 741 scb_reg_index = scb_15_reg_index; 742 scb_numregs = scb_15_numregs; 743 scb_fru_offset = scb_15_fru_offset; 744 scb_sys_offset = scb_15_sys_offset; 745 } 746 if (!(IS_SCB_P15) && !(IS_SCB_P10)) { 747 cmn_err(CE_WARN, "scsb%d: SCB Version %d not recognized", 748 scsb->scsb_instance, data); 749 if (hotswap) 750 scsb->scsb_state |= SCSB_FROZEN; 751 if (!(scsb_debug)) { 752 return (DDI_FAILURE); 753 } 754 /* 755 * DEBUG: Assume SCB15 756 */ 757 scsb->scsb_state |= SCSB_P15_PROM; 758 } 759 return (DDI_SUCCESS); 760 } 761 762 /* 763 * SCB initialization steps to be called from scsb_attach() 764 * or from scsb_intr() calling scsb_restore() on Hot Insertion. 765 */ 766 static int 767 initialize_scb(scsb_state_t *scsb) 768 { 769 register int i; 770 uchar_t reg, wdata, rmask; 771 /* 772 * If called from scsb_intr(), we've already done this 773 */ 774 if (!(scsb->scsb_state & SCSB_IN_INTR)) 775 if (scb_check_version(scsb) != DDI_SUCCESS) 776 return (DDI_FAILURE); 777 /* 778 * 2. Set the SCB_INIT bit in the System Command register 779 */ 780 rmask = 0x00; /* P1.0: 0x60; */ 781 wdata = 1 << SYS_OFFSET(SCTRL_SYS_SCB_INIT); 782 i = SYS_REG_INDEX(SCTRL_SYS_SCB_INIT, SCTRL_SYS_CMD_BASE); 783 reg = SCSB_REG_ADDR(i); 784 if (i = scsb_write_mask(scsb, reg, rmask, wdata, 0)) { 785 cmn_err(CE_WARN, 786 "scsb%d: I2C TRANSFER Failed", scsb->scsb_instance); 787 if (scsb_debug & 0x0006) { 788 cmn_err(CE_NOTE, 789 "scsb_attach: failed to set SCB_INIT"); 790 } 791 return (DDI_FAILURE); 792 } 793 /* 3. For P1.0 and previous system, turn off all LEDs */ 794 if (IS_SCB_P10) { 795 if (scsb_debug & 0x0004) { 796 cmn_err(CE_NOTE, "scsb_attach(%d): turning LEDs off", 797 scsb->scsb_instance); 798 } 799 if (i = scsb_leds_switch(scsb, OFF)) { 800 cmn_err(CE_WARN, "scsb%d: I2C TRANSFER Failed", 801 scsb->scsb_instance); 802 return (DDI_FAILURE); 803 } 804 } 805 /* 4. Read the SYSCFG registers, update FRU info and SSB LEDs */ 806 if (scsb_debug & 0x0004) 807 cmn_err(CE_NOTE, "scsb_attach(%d): reading config registers", 808 scsb->scsb_instance); 809 if ((i = scsb_check_config_status(scsb)) == 0) { 810 if (!(scsb->scsb_state & SCSB_TOPOLOGY)) { 811 scsb_set_topology(scsb); 812 if (scsb_debug & 0x0004) 813 cmn_err(CE_NOTE, "scsb_attach(%d): mpid = 0x%x", 814 scsb->scsb_instance, 815 mct_system_info.mid_plane.fru_id); 816 } else { 817 fru_info_t *fru_ptr; 818 /* 819 * walk through FRUs and update FRU info 820 */ 821 for (i = 0; i < SCSB_UNIT_TYPES; ++i) { 822 fru_ptr = mct_system_info.fru_info_list[i]; 823 while (fru_ptr != NULL) { 824 update_fru_info(scsb, fru_ptr); 825 fru_ptr = fru_ptr->next; 826 } 827 } 828 } 829 i = scsb_set_scfg_pres_leds(scsb, NULL); 830 } 831 if (i) { 832 cmn_err(CE_WARN, "scsb%d: I2C TRANSFER Failed", 833 scsb->scsb_instance); 834 return (DDI_FAILURE); 835 } 836 /* 5. read the Board Healthy registers */ 837 if (scsb_debug & 0x0004) 838 cmn_err(CE_NOTE, "scsb_attach(%d): reading Brd_Hlthy registers", 839 scsb->scsb_instance); 840 i = scsb_read_bhealthy(scsb); 841 if (i) { 842 cmn_err(CE_WARN, "scsb%d: I2C TRANSFER Failed", 843 scsb->scsb_instance); 844 return (DDI_FAILURE); 845 } 846 /* 6. Clear Interrupt Source registers */ 847 /* 848 * Due to some registration problems, we must first disable 849 * global interrupts which may be the default reset value 850 * itself. However, this is a safe step to do in case of 851 * implementation changes. 852 * 853 * Disable Global SCB Interrupts now 854 */ 855 rmask = 0x00; /* P1.0: 0x60; */ 856 wdata = 1 << SYS_OFFSET(SCTRL_SYS_PSM_INT_ENABLE); 857 i = SYS_REG_INDEX(SCTRL_SYS_PSM_INT_ENABLE, SCTRL_SYS_CMD_BASE); 858 reg = SCSB_REG_ADDR(i); 859 if (i = scsb_write_mask(scsb, reg, rmask, (uchar_t)0, wdata)) { 860 cmn_err(CE_WARN, "scsb%d: Cannot turn off PSM_INT", 861 scsb->scsb_instance); 862 return (DDI_FAILURE); 863 } 864 /* Mask all interrupt sources */ 865 if (i = scsb_setall_intmasks(scsb)) { 866 cmn_err(CE_WARN, "scsb%d: I2C TRANSFER Failed", 867 scsb->scsb_instance); 868 return (DDI_FAILURE); 869 } 870 /* Clear any latched interrupts */ 871 if (i = scsb_clear_intptrs(scsb)) { 872 cmn_err(CE_WARN, "scsb%d: I2C TRANSFER Failed", 873 scsb->scsb_instance); 874 return (DDI_FAILURE); 875 } 876 /* 7. set SCB EEPROM address: NOT USED */ 877 return (DDI_SUCCESS); 878 } 879 880 /* 881 * Based on MC conditions, scsb_detach should eventually be made to always 882 * return FAILURE, as the driver should not be allowed to detach after some 883 * hs slots have been used. 884 */ 885 static int 886 scsb_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 887 { 888 int instance; 889 scsb_state_t *scsb; 890 uchar_t reg, wdata; 891 892 /* 893 * TBD: make sure there are no outstanding operations on the system 894 * monitor card before detaching. 895 */ 896 instance = ddi_get_instance(dip); 897 if (scsb_debug & 0x0005) 898 cmn_err(CE_NOTE, "scsb_detach[%d]", instance); 899 if (cmd != DDI_DETACH) { 900 if (scsb_debug & 0x0006) 901 cmn_err(CE_NOTE, 902 "scsb_detach(%d): command %x is not DDI_DETACH\n", 903 instance, cmd); 904 return (DDI_FAILURE); 905 } 906 scsb = (scsb_state_t *)ddi_get_soft_state(scsb_state, instance); 907 scsb->scsb_state &= ~SCSB_UP; 908 scsb_global_state &= ~SCSB_UP; 909 if (scsb->scsb_hsc_state & SCSB_HSC_INIT) { 910 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, ®, &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, ®, &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(¤t_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