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