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