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