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