03831d35f7499c87d51205817c93e9a8d42c4baestevel * CDDL HEADER START
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The contents of this file are subject to the terms of the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Common Development and Distribution License (the "License").
03831d35f7499c87d51205817c93e9a8d42c4baestevel * You may not use this file except in compliance with the License.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
03831d35f7499c87d51205817c93e9a8d42c4baestevel * See the License for the specific language governing permissions
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and limitations under the License.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * When distributing Covered Code, include this CDDL HEADER in each
03831d35f7499c87d51205817c93e9a8d42c4baestevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If applicable, add the following below this CDDL HEADER, with the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * fields enclosed by brackets "[]" replaced with your own identifying
03831d35f7499c87d51205817c93e9a8d42c4baestevel * information: Portions Copyright [yyyy] [name of copyright owner]
03831d35f7499c87d51205817c93e9a8d42c4baestevel * CDDL HEADER END
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Use is subject to license terms.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Netra ct800 and Netra ct400 (MonteCarlo/Tonga)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * System Controller and Status Boards STREAMS driver.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This driver handles all communications with the Netra ct400 and ct800
03831d35f7499c87d51205817c93e9a8d42c4baestevel * System Controller Boards.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * I/O to the SCB is through the PCF8584 I2C controller.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The SCB I2C interface and driver interface are provided by the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Xilinx XCS40XL.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * N.B.: The design choice of using STREAMS was dictated because
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the original system monitor card had to multiplex 2 pcf8574's
03831d35f7499c87d51205817c93e9a8d42c4baestevel * as one device.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * (internal only)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * scsb build version format is "CCYYMMDD"
03831d35f7499c87d51205817c93e9a8d42c4baestevel * for integer compares.
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int scsb_err_threshold = 0; /* max allowed i2c errors */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int scsb_freeze_count = 3; /* #I2C errors to indicate SCB removal */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int scsb_shutdown_count = 5; /* #polls before passing shutdown evt */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int scsb_in_postintr = 0; /* 1 if scsb is processing intr */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic kmutex_t *scb_intr_mutex; /* SCSB interrupt mutex */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic char *scsb_clone_name = SCSB_DEVICE_NAME "clone";
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cb_ops section of scsb driver.
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int sm_open(queue_t *, dev_t *, int, int, cred_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int sm_rput(queue_t *, mblk_t *); /* from i2c below */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int sm_wput(queue_t *, mblk_t *); /* from above */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int scsb_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int scsb_attach(dev_info_t *, ddi_attach_cmd_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int scsb_detach(dev_info_t *, ddi_detach_cmd_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic dev_info_t *scsb_dip; /* private copy of devinfo pointer */
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0, /* refcnt */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Module linkage information for the kernel.
03831d35f7499c87d51205817c93e9a8d42c4baestevel &mod_driverops, /* Type of module. This one is a pseudo driver */
193974072f41a843678abf5f61979c748687e66bSherry Moore "v1.33 Netra ct System Control/Status Board driver",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * local declarations and definitions
03831d35f7499c87d51205817c93e9a8d42c4baestevel#if defined(DEBUG)
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic hrtime_t scb_pre_s, scb_pre_e, scb_post_s, scb_post_e;
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic uint32_t scsb_event_code; /* for event polling */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic uchar_t scb_intr_regs[SCTRL_MAX_GROUP_NUMREGS];
03831d35f7499c87d51205817c93e9a8d42c4baestevelint nct_i2c_transfer(i2c_client_hdl_t i2c_hdl, i2c_transfer_t *i2c_tran);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * kstat functions
03831d35f7499c87d51205817c93e9a8d42c4baestevel * local functions
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void free_resources(dev_info_t *, scsb_state_t *, int);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic i2c_transfer_t *scsb_alloc_i2ctx(i2c_client_hdl_t, uint_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int scsb_get_status(scsb_state_t *, scsb_status_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int scsb_leds_switch(scsb_state_t *, scsb_ustate_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int scsb_polled_int(scsb_state_t *, int, uint32_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int scsb_check_config_status(scsb_state_t *scsb);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int scsb_set_scfg_pres_leds(scsb_state_t *, fru_info_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void tonga_slotnum_check(scsb_state_t *scsb, scsb_uinfo_t *suip);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int tonga_psl_to_ssl(scsb_state_t *scsb, int slotnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic uchar_t tonga_slotnum_led_shift(scsb_state_t *scsb, uchar_t data);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int scsb_write_mask(scsb_state_t *, uchar_t, uchar_t, uchar_t,
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int scsb_rdwr_register(scsb_state_t *, int, uchar_t, int,
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int scsb_get_led_regnum(scsb_state_t *, scsb_uinfo_t *, uchar_t *,
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void scsb_free_i2ctx(i2c_client_hdl_t, i2c_transfer_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void update_fru_info(scsb_state_t *, fru_info_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int scsb_is_alarm_card_slot(scsb_state_t *, int);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int scsb_fru_op(scsb_state_t *, scsb_utype_t, int, int, int);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int scsb_queue_put(queue_t *, int, uint32_t *, char *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int scsb_queue_ops(scsb_state_t *, int, int, void *, char *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int scsb_blind_read(scsb_state_t *, int, uchar_t, int, uchar_t *, int);
03831d35f7499c87d51205817c93e9a8d42c4baestevelint scsb_intr_register(int (*)(void *), void *, fru_id_t);
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) ddi_soft_state_init(&scsb_state, sizeof (scsb_state_t),
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb: _init(): mod_install failed");
03831d35f7499c87d51205817c93e9a8d42c4baestevel * initialize the FRU ID Table, using real FRU IDs where available
03831d35f7499c87d51205817c93e9a8d42c4baestevel * such as I2C Addresses for FRUs with I2C support
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < MCT_MAX_FRUS; ++i)
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_id_table[event_to_index(SCTRL_EVENT_PS1)] = (fru_id_t)MCT_I2C_PS1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_id_table[event_to_index(SCTRL_EVENT_PS2)] = (fru_id_t)MCT_I2C_PS2;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_id_table[event_to_index(SCTRL_EVENT_FAN1)] = (fru_id_t)MCT_I2C_FAN1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_id_table[event_to_index(SCTRL_EVENT_FAN2)] = (fru_id_t)MCT_I2C_FAN2;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_id_table[event_to_index(SCTRL_EVENT_FAN3)] = (fru_id_t)MCT_I2C_FAN3;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_id_table[event_to_index(SCTRL_EVENT_SCB)] = (fru_id_t)MCT_I2C_SCB;
03831d35f7499c87d51205817c93e9a8d42c4baestevel register int i;
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_attach[%d]: cmd 0x%x != DDI_ATTACH",
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_soft_state_zalloc(scsb_state, instance) != DDI_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "scsb%d: cannot allocate soft state",
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb = (scsb_state_t *)ddi_get_soft_state(scsb_state, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "scsb%d: cannot get soft state", instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state = 0; /* just checking strange mutex behavior */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * make sure this is the SCB's known address
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb%d: Failed to get \"reg\" property", instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "scsb%d: I2C Addr reg %x %x must be %x",
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* done with array lookup, free resource */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * initialize synchronization mutex and condition var.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * for this instance.
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_init(&scsb->scsb_mutex, NULL, MUTEX_DRIVER, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 1. Read interrupt property of the board and register its handler.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 2. Get scsb private handle for communication via I2C Services.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 3. Allocate and save an i2c_transfer_t for I2C transfers.
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) ddi_prop_update_int_array(DDI_DEV_T_NONE, dip,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Look for the device-err-threshold property which specifies
03831d35f7499c87d51205817c93e9a8d42c4baestevel * on how many errors will scsb send a warning event about it's
03831d35f7499c87d51205817c93e9a8d42c4baestevel * health. The scsb_err_threshold is 10 by default.
193974072f41a843678abf5f61979c748687e66bSherry Moore DDI_PROP_DONTPASS, "device-err-threshold", -1)) >= 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "?scsb_attach: Found device-err-threshold"
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If all went well, create the minor node for user level access.
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_create_minor_node(dip, scsb_name, S_IFCHR, instance,
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "scsb_attach: Failed to create minor node");
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_create_minor_node(dip, scsb_clone_name, S_IFCHR,
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "scsb_attach: Failed to create clone node");
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* CLONE */
03831d35f7499c87d51205817c93e9a8d42c4baestevel bzero(scsb->clone_devs, sizeof (clone_dev_t) * SCSB_CLONES_MAX);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (i2c_client_register(dip, &scsb->scsb_phandle) != I2C_SUCCESS) {
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_attach: Failed I2C Services registration");
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((scsb->scsb_i2ctp = scsb_alloc_i2ctx(scsb->scsb_phandle,
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb%d: i2c_transfer allocation failed", instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Now it's time to INITIALIZE the boards.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 1. make sure we can do I2C bus transfers to/from the SCB.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Read the SCB PROM version for a check.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 2. set SCB_INITIALIZED bit in SysCommand registers (SYS_CMD_BASE)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 3. clear all LED Data registers (8) by writing 0's to turn off
03831d35f7499c87d51205817c93e9a8d42c4baestevel * all LEDs on the SSB.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 4. read System Configuration Status registers (SCTRL_CFG)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to find present FRUs and set corresponding FRU bits at
03831d35f7499c87d51205817c93e9a8d42c4baestevel * LED_DATA_BASE.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Also enable devices in Topology map for the current MP_ID
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and set the OK LEDs on the SSB.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 5. read Brd_Hlthy registers (2 @ BRD_HLTHY_BASE)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 6. Disable PSM Interrupts during initialization, mask all
03831d35f7499c87d51205817c93e9a8d42c4baestevel * interrupts, and clear Interrupt Pointer registers
03831d35f7499c87d51205817c93e9a8d42c4baestevel * by writing 0xFF to each register.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 7. set SCB EEPROM address bits SPA2-SPA0 at SYS_CMD_BASE + 1
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 8. Install the interrupt handler if appropriate.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 9. clear appropriate bits in Interrupt Mask register for those
03831d35f7499c87d51205817c93e9a8d42c4baestevel * devices that can be present for this MP_ID Topology.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 10. enable PSM Interrupt by writing '1' to PSM_INT_EN bit at
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SYS_CMD_BASE + 1
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Also update all shadow registers for test utility
03831d35f7499c87d51205817c93e9a8d42c4baestevel * if scsb_debug is set.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 11. Check if Alarm Card present at boot and set flags
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 12. Call hsc_attach() for slot registration.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 13. Allocate, initialze, and install the kstat structures.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 14. Set scsb_state_t flags to indicate SCB is ready
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and announce the driver is loaded.
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* 1. through 7. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * P0.6 No Interrupt Support
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Instead of installing the handler, it will be called from a user
03831d35f7499c87d51205817c93e9a8d42c4baestevel * program via smf_ioctl(). This flag provides knowledge of the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * necessary workarounds to several scsb routines.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Now Install interrupt handler
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_attach: failed interrupt "
193974072f41a843678abf5f61979c748687e66bSherry Moore "handler registration");
193974072f41a843678abf5f61979c748687e66bSherry Moore "mutex initialization");
03831d35f7499c87d51205817c93e9a8d42c4baestevel * For P0.6 No Interrupt Support, don't enable PSM Interrupt
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (i = scsb_write_mask(scsb, reg, rmask, wdata, (uchar_t)0)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * For smctrl test utility,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * so all data is available in shadow registers
03831d35f7499c87d51205817c93e9a8d42c4baestevel * DEBUG_MODE enables private testing interfaces
03831d35f7499c87d51205817c93e9a8d42c4baestevel * DIAGS_MODE permits limited testing interfaces
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_attach: scsb_readall FAILED");
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Check if Alarm Card present at boot and set flags */
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_attach: registering cPCI slots");
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_hsc_attach(dip, scsb, instance) != DDI_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel "scsb: Hotswap controller initialisation"
193974072f41a843678abf5f61979c748687e66bSherry Moore " failed\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel * allocate and install the kstat data structures
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "scsb_attach: ERROR adding kstats");
03831d35f7499c87d51205817c93e9a8d42c4baestevel "Prom Version %s, Midplane Id %x\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore (scsb->scsb_state & SCSB_P20_PROM) ? "2.0" : "Unknown",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This funciton is called from scsb_attach(), and from scsb_intr() as part
03831d35f7499c87d51205817c93e9a8d42c4baestevel * of Hot Insertion support, to check the SCB PROM ID register and set
03831d35f7499c87d51205817c93e9a8d42c4baestevel * scsb_state bits and register table pointers as necessary.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If driver is UP, then this call is from scsb_intr()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * as part of Hot Insertion support.
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Read the SCB PROM ID */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_rdwr_register(scsb, I2C_WR_RD, (uchar_t)SCTRL_PROM_VERSION, 1,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "scsb_attach(%d): failed read of PROM ID",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * compare with stored version number, and if different,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * report a warning and keep the driver FROZEN
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (((mct_system_info.fru_info_list[SCB])[0].fru_version & 0xf)
193974072f41a843678abf5f61979c748687e66bSherry Moore "scb_check_version: SCB version %d "
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else { /* if (IS_SCB_P15) */
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "scsb%d: SCB Version %d not recognized",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * DEBUG: Assume SCB15
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SCB initialization steps to be called from scsb_attach()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * or from scsb_intr() calling scsb_restore() on Hot Insertion.
03831d35f7499c87d51205817c93e9a8d42c4baestevel register int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If called from scsb_intr(), we've already done this
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 2. Set the SCB_INIT bit in the System Command register
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = SYS_REG_INDEX(SCTRL_SYS_SCB_INIT, SCTRL_SYS_CMD_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (i = scsb_write_mask(scsb, reg, rmask, wdata, 0)) {
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb%d: I2C TRANSFER Failed", scsb->scsb_instance);
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_attach: failed to set SCB_INIT");
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* 3. For P1.0 and previous system, turn off all LEDs */
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_attach(%d): turning LEDs off",
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* 4. Read the SYSCFG registers, update FRU info and SSB LEDs */
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_attach(%d): reading config registers",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * walk through FRUs and update FRU info
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < SCSB_UNIT_TYPES; ++i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* 5. read the Board Healthy registers */
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_attach(%d): reading Brd_Hlthy registers",
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* 6. Clear Interrupt Source registers */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Due to some registration problems, we must first disable
03831d35f7499c87d51205817c93e9a8d42c4baestevel * global interrupts which may be the default reset value
03831d35f7499c87d51205817c93e9a8d42c4baestevel * itself. However, this is a safe step to do in case of
03831d35f7499c87d51205817c93e9a8d42c4baestevel * implementation changes.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Disable Global SCB Interrupts now
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = SYS_REG_INDEX(SCTRL_SYS_PSM_INT_ENABLE, SCTRL_SYS_CMD_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (i = scsb_write_mask(scsb, reg, rmask, (uchar_t)0, wdata)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Mask all interrupt sources */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Clear any latched interrupts */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* 7. set SCB EEPROM address: NOT USED */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Based on MC conditions, scsb_detach should eventually be made to always
03831d35f7499c87d51205817c93e9a8d42c4baestevel * return FAILURE, as the driver should not be allowed to detach after some
03831d35f7499c87d51205817c93e9a8d42c4baestevel * hs slots have been used.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * TBD: make sure there are no outstanding operations on the system
03831d35f7499c87d51205817c93e9a8d42c4baestevel * monitor card before detaching.
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_detach(%d): command %x is not DDI_DETACH\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb = (scsb_state_t *)ddi_get_soft_state(scsb_state, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Disable Global SCB Interrupts now
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_write_mask(scsb, reg, (uchar_t)0, (uchar_t)0, wdata)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Mask all interrupts */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Clear all latched interrupts */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* CLONE */
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) scsb_queue_ops(scsb, QPROCSOFF, 0, NULL, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * free the allocated resources
03831d35f7499c87d51205817c93e9a8d42c4baestevelfree_resources(dev_info_t *dip, scsb_state_t *scsb, int instance)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "free_resources[%d], scsb_state=0x%x",
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2c_transfer_free(scsb->scsb_phandle, scsb->scsb_i2ctp);
193974072f41a843678abf5f61979c748687e66bSherry Moore "interrupt-priorities");
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* ddi_prop_remove_all(dip); */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Just for testing scsb's poll function
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_fake_intr: event = 0x%x, scsb_rq=0x%p",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Allow access to shadow registers even though SCB is removed
03831d35f7499c87d51205817c93e9a8d42c4baestevel * if (scsb->scsb_state & SCSB_FROZEN) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * return (EAGAIN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* just inform user-level via poll about this event */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_queue_ops(scsb, QPUT_INT32, 1, &evcode, "scsb_fake_intr")
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
03831d35f7499c87d51205817c93e9a8d42c4baestevel *result = (void *)0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SCSB STREAMS routines
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelsm_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *credp)
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki cmn_err(CE_NOTE, "sm_open(%d) q=0x%p", instance, (void *)q);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Don't fail the open if SCB removed since we still want to satisfy
03831d35f7499c87d51205817c93e9a8d42c4baestevel * read requests from the shadow registers, the last know register
03831d35f7499c87d51205817c93e9a8d42c4baestevel * contents. On new SCB insertion, all will be re-initialized,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * including envmond and it's policies.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * if (scsb->scsb_state & SCSB_FROZEN) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * return (EAGAIN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * XXX check for root access here, return EPERM if not root open
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* scsb module is being pushed */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * this is no longer supported
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* scsb is being opened as a clonable driver */
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "sm_open(%d): CLONEOPEN", instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The cloned stream is not handled via the clone driver.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * See the minor device code below.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * First check for the SCSB_CLONE device.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Find an available clone_devs[] entry, or return ENXIO.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Make new dev_t and store in *devp.
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((clone = scsb_queue_ops(scsb, QFIRST_AVAILABLE, 0, NULL,
03831d35f7499c87d51205817c93e9a8d42c4baestevel *devp = makedevice(getmajor(*devp), clptr->cl_minor);
193974072f41a843678abf5f61979c748687e66bSherry Moore "sm_open(%d): new clone device minor: 0x%x"
193974072f41a843678abf5f61979c748687e66bSherry Moore " stream queue is 0x%p",
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* scsb is being opened as a regular driver */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "sm_open(%d): can't open, state is EXCL",
193974072f41a843678abf5f61979c748687e66bSherry Moore "sm_open(%d): cannot open EXCL",
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_rq (0x%p)",
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelsm_close(queue_t *q, int flag, int otyp, cred_t *credp)
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki cmn_err(CE_NOTE, "sm_close[%d](0x%p)", scsb->scsb_instance,
193974072f41a843678abf5f61979c748687e66bSherry Moore (void *) RD(q), "scsb_close")) != QOP_FAILED) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0008 && clone < SCSB_CLONES_MAX &&
193974072f41a843678abf5f61979c748687e66bSherry Moore "sm_close(%d): DEVOPEN, q != scsb_rq",
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_opens == 0 && scsb->scsb_clopens == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki cmn_err(CE_NOTE, "sm_wput(%d): mp %p", scsb->scsb_instance,
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* free any messages tied to scsb */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* do ioctl */
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * These are the system monitor upper ioctl functions.
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki scsb->scsb_instance, (void *)mp, iocp->ioc_cmd);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Don't fail ALL commands if the SCB removed, since we still want to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * satisfy some requests from the shadow registers, the last known
03831d35f7499c87d51205817c93e9a8d42c4baestevel * register contents.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * if (scsb->scsb_state & SCSB_FROZEN) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * iocp->ioc_error = EAGAIN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mp->b_datap->db_type = M_IOCNAK;
03831d35f7499c87d51205817c93e9a8d42c4baestevel * qreply(q, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* if we don't understand the ioctl */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "IOC_SETMODE: Invalid mode 0x%x",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Not an exposed interface, only used by development utilities.
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = miocpullup(mp, sizeof (scsb_ids_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel "IOC_GET_VERSIONS: sizeof(scsb_ids_t) "
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (add_event_proc(scsb, *(pid_t *)mp->b_cont->b_rptr))
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (del_event_proc(scsb, *(pid_t *)mp->b_cont->b_rptr))
03831d35f7499c87d51205817c93e9a8d42c4baestevel * check mode_vals[0] for get/set option. setting
03831d35f7499c87d51205817c93e9a8d42c4baestevel * scsb_state is not valid for now. 0 == GET, 1 == SET
03831d35f7499c87d51205817c93e9a8d42c4baestevel "0x%x/0x%x/0x%x; ioc_count = 0x%lx",
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = miocpullup(mp, sizeof (uint32_t) * 2);
03831d35f7499c87d51205817c93e9a8d42c4baestevel "0x%x/0x%x; ioc_count = 0x%lx",
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* for now we don't understand these ioctls */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state & (SCSB_DIAGS_MODE | SCSB_DEBUG_MODE))) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*FALLTHROUGH*/
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = miocpullup(mp, sizeof (scsb_uinfo_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = miocpullup(mp, sizeof (scsb_status_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state & (SCSB_DIAGS_MODE | SCSB_DEBUG_MODE)))
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state & (SCSB_DIAGS_MODE | SCSB_DEBUG_MODE)))
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state & (SCSB_DIAGS_MODE | SCSB_DEBUG_MODE))) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = miocpullup(mp, sizeof (*iocrdwrp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = scsb_polled_int(scsb, iocp->ioc_cmd,
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state & (SCSB_DIAGS_MODE | SCSB_DEBUG_MODE)))
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state & (SCSB_DIAGS_MODE | SCSB_DEBUG_MODE)))
03831d35f7499c87d51205817c93e9a8d42c4baestevel * envmond:alarmcard.so response to SCTRL_EVENT_ALARM_INSERTION
03831d35f7499c87d51205817c93e9a8d42c4baestevel * envmond:alarmcard.so response to SCTRL_EVENT_ALARM_REMOVAL
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < SCSB_UNIT_TYPES; ++i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * global function for interested FRU drivers to register a callback function,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to be called when FRU presence status changes.
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_fru_register(void (*cb_func)(void *, scsb_fru_event_t, scsb_fru_status_t),
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_fru_register: FRU_ID 0x%x", (int)fru_id);
193974072f41a843678abf5f61979c748687e66bSherry Moore kmem_zalloc(sizeof (struct scsb_cb_entry), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cbe_ptr->cb_next == (struct scsb_cb_entry *)NULL) {
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_fru_register: FRU_ID 0x%x, status=%d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((cbe_ptr = scsb_cb_table) == NULL || fru_id == (fru_id_t)0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * global function for interested FRU drivers to call to check
03831d35f7499c87d51205817c93e9a8d42c4baestevel * FRU presence status.
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_fru_status(0x%x): status=0x%x",
193974072f41a843678abf5f61979c748687e66bSherry Moore fru_id, (fru_ptr == (fru_info_t *)NULL) ? 0xff :
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Global function for the other interruptible FRU device sharing the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * same interrupt line to register the interrupt handler with scsb.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This enables all the handlers to be called whenever the interrupt
03831d35f7499c87d51205817c93e9a8d42c4baestevel * line is asserted by anyone shaing the interrupt line.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The interrupt handler table is currently a linked list. probably a
03831d35f7499c87d51205817c93e9a8d42c4baestevel * hash table will be more efficient. Usage of these facilities can
03831d35f7499c87d51205817c93e9a8d42c4baestevel * happen even before scsb is attached, so do not depend on scsb
03831d35f7499c87d51205817c93e9a8d42c4baestevel * structure being present.
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_intr_register(int (*intr_handler)(void *), void * soft_ptr,
193974072f41a843678abf5f61979c748687e66bSherry Moore kmem_zalloc(sizeof (struct fru_intr_entry), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (intr_handler == NULL || soft_ptr == NULL || fru_id == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(intr_table_entry, sizeof (struct fru_intr_entry));
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Removed interrupt_handler of fru from interrupt call chain
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (fru_id == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* found a match, remove entry */
193974072f41a843678abf5f61979c748687e66bSherry Moore sizeof (struct fru_intr_entry));
03831d35f7499c87d51205817c93e9a8d42c4baestevel } while ((intr_entry = intr_entry->fru_intr_next) != NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Invoke all the registered interrupt handlers, whenever scsb_intr
03831d35f7499c87d51205817c93e9a8d42c4baestevel * is called. This function will go through the list of entries
03831d35f7499c87d51205817c93e9a8d42c4baestevel * in the fru interrupt table and invoke each function. Returns
03831d35f7499c87d51205817c93e9a8d42c4baestevel * whether interrupt is claimed or unclaimed.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The scsb_ioc_rdwr_t is similar enough to an i2c_transfer_t that we can
03831d35f7499c87d51205817c93e9a8d42c4baestevel * translate the structures and use the i2c_transfer() service.
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "sm_ioc_rdwr[%d]:", scsb->scsb_instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check SCB register index boundries and requested len of read/write
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = scsb_rdwr_register(scsb, op, reg, len, uc, 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * names for (scsb_utype_t) FRU types
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic char *led_name[SCSB_LED_TYPES] = { "NOK", "OK" };
03831d35f7499c87d51205817c93e9a8d42c4baestevel "SLOT", "PDU", "POWER SUPPLY", "DISK", "FAN", "ALARM",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Discover the register and bit-offset for LEDs and Reset registers,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * according to unit_type, unit_number, and led_type.
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* OK here means presence (OK) LEDs */
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "get_led_regnum: suip <%x, %x, %x, %x>\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * It was requested that the scsb driver allow accesses to SCB device
03831d35f7499c87d51205817c93e9a8d42c4baestevel * registers for FRUs that cannot be present.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * So except for SLOTs, if the unit_number check fails, we now
03831d35f7499c87d51205817c93e9a8d42c4baestevel * just log a message, but ONLY if scsb_debug error messages are
193974072f41a843678abf5f61979c748687e66bSherry Moore "get_led_regnum: unit number %d "
193974072f41a843678abf5f61979c748687e66bSherry Moore "get_led_regnum: unit number %d "
193974072f41a843678abf5f61979c748687e66bSherry Moore "get_led_regnum: unit number %d "
193974072f41a843678abf5f61979c748687e66bSherry Moore "get_led_regnum: unit number %d "
193974072f41a843678abf5f61979c748687e66bSherry Moore "get_led_regnum: unit number %d "
193974072f41a843678abf5f61979c748687e66bSherry Moore "get_led_regnum: unit number %d "
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_get_led_regnum(): unknown unit type %d",
193974072f41a843678abf5f61979c748687e66bSherry Moore "regptr=%x, code = %x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * P1.0 and P1.5
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Map 1.0 Tonga Slot Numbers: SCB to user interface and back.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * User interface means positional slot numbers, as on P1.0 SSB,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * which are used by hpcsvc/hsc and kstat/ioctl interfaces.
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* HSC slotnum (Positional SLotnum) to SCB CFG bit-offset */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * MAP Positional (HSC) slot number to SCB CFG register bit-offset
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Should move this to _init(), but for now,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * check for initialized table
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "tonga_pslotnum_to_cfgbit: old/new: %d/%d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* positional slotnum to SCB slotnum */
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* SCB slotnum to positional slotnum */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * P1.0 and P1.5
03831d35f7499c87d51205817c93e9a8d42c4baestevel * HSC Slot numbers (physical positions or positional slotnum)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SCB slot numbers (reset,present,healthy)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * These requests come mainly from application interface and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * HSC using the scsb_uinfo_t structure.
03831d35f7499c87d51205817c93e9a8d42c4baesteveltonga_slotnum_check(scsb_state_t *scsb, scsb_uinfo_t *suip)
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state & SCSB_IS_TONGA && scsb->scsb_state &
193974072f41a843678abf5f61979c748687e66bSherry Moore (SCSB_P10_PROM | SCSB_P15_PROM | SCSB_P20_PROM))) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (suip->unit_number < 1 || suip->unit_number > TG_MAX_SLOTS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "tonga_slotnum_check: old/new: %d/%d",
193974072f41a843678abf5f61979c748687e66bSherry Moore suip->unit_number, psl2ssl[suip->unit_number]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * P1.0 and P1.5
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state & SCSB_IS_TONGA && scsb->scsb_state &
193974072f41a843678abf5f61979c748687e66bSherry Moore (SCSB_P10_PROM | SCSB_P15_PROM | SCSB_P20_PROM))) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * P1.0 and P1.5
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state & SCSB_IS_TONGA && scsb->scsb_state &
193974072f41a843678abf5f61979c748687e66bSherry Moore (SCSB_P10_PROM | SCSB_P15_PROM | SCSB_P20_PROM))) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * tonga_slotnum_led_shift: this function remaps slot bits ONLY for Slots 1-5
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and ONLY for the register sets in bit-offset groups 1,2:
03831d35f7499c87d51205817c93e9a8d42c4baestevel * LEDs, Confg/Status, Reset, BrdHlthy
03831d35f7499c87d51205817c93e9a8d42c4baestevel * IN bits: SCB slot numbers (led,reset,present,healthy)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * OUT bits: HSC Slot numbers (positional slot numbers as marked on the SSB)
03831d35f7499c87d51205817c93e9a8d42c4baesteveltonga_slotnum_led_shift(scsb_state_t *scsb, uchar_t data)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * P1.0 and P1.5 slot 1-5 offsets are the same
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "tonga_slotnum_led_shift: old/new: 0x%x/0x%x",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * P1.0 and P1.5
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_led_get(scsb_state_t *scsb, scsb_uinfo_t *suip, scsb_led_t led_type)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Allow access to shadow registers even though SCB is removed
03831d35f7499c87d51205817c93e9a8d42c4baestevel * if (scsb->scsb_state & SCSB_FROZEN) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * return (EAGAIN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_led_get(%d): unknown led type %x",
193974072f41a843678abf5f61979c748687e66bSherry Moore led_name[led_type], unit_type_name[suip->unit_type],
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Map to Tonga Slot Number, if NOT P1.0 SCB
03831d35f7499c87d51205817c93e9a8d42c4baestevel * P1.0 SSB workaround
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (suip->unit_type == SLOT && !(scsb->scsb_state & SCSB_P10_PROM)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* discover the register and index we need to operate on */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((error = scsb_get_led_regnum(scsb, suip, ®, &unit_number,
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_data_reg[index] & (1 << unit_number)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_led_set(scsb_state_t *scsb, scsb_uinfo_t *suip, scsb_led_t led_type)
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* we should really allow led state changes while frozen... */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Sanity check, make sure we got plausible values for set command.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Also check for application only control of slot leds using NOUSE
03831d35f7499c87d51205817c93e9a8d42c4baestevel * interface
03831d35f7499c87d51205817c93e9a8d42c4baestevel * kernel modules using this interface need to think they are
03831d35f7499c87d51205817c93e9a8d42c4baestevel * succeeding, so we won't return an error for this
03831d35f7499c87d51205817c93e9a8d42c4baestevel * application configuration
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (suip->unit_state != OFF && suip->unit_state != ON &&
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_led_set: led %s, type %s, unit %d, state %s",
193974072f41a843678abf5f61979c748687e66bSherry Moore unit_type_name[suip->unit_type], suip->unit_number,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Map to Tonga Slot Number, if NOT P1.0 SCB
03831d35f7499c87d51205817c93e9a8d42c4baestevel * P1.0 SSB workaround
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (suip->unit_type == SLOT && !(scsb->scsb_state & SCSB_P10_PROM)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * discover the register and index we need to access
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((error = scsb_get_led_regnum(scsb, suip, ®, &unit_number,
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (suip->unit_state == ON || suip->unit_state == BLINK)
03831d35f7499c87d51205817c93e9a8d42c4baestevel code = FRU_UNIT_TO_EVCODE(suip->unit_type, suip->unit_number);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Turn on the PSU.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Notice: not checking Power Supply unit number
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_write_mask(ppao->scsb, sysreg, rmask, ondata, (uchar_t)0)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * called with mutex held from
03831d35f7499c87d51205817c93e9a8d42c4baestevel * scsb_attach() with int_fru_ptr == NULL
03831d35f7499c87d51205817c93e9a8d42c4baestevel * scsb_intr() with int_fru_ptr == info for FRU that caused interrupt
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_set_scfg_pres_leds(scsb_state_t *scsb, fru_info_t *int_fru_ptr)
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t *puc, reg, led_reg, led_data[SCSB_LEDDATA_REGISTERS];
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t blink_bit, blink_reg, blink[SCSB_LEDDATA_REGISTERS];
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < SCTRL_LED_OK_NUMREGS; ++i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel lid = SCSB_REG_INDEX(led_reg); /* the LED Index Delta */
03831d35f7499c87d51205817c93e9a8d42c4baestevel bid = SCSB_REG_INDEX(reg); /* the Blink Index Delta */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (fru_type = 0; fru_type < SCSB_UNIT_TYPES; ++fru_type) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((led_reg = fru_ptr->i2c_info->ledata_reg) == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * No LED exceptions: SSB,CRTM,PRTM
03831d35f7499c87d51205817c93e9a8d42c4baestevel * exception: SCB
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If the FRU is a Power Supply, AND
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the call is from scsb_attach() OR
03831d35f7499c87d51205817c93e9a8d42c4baestevel * from scsb_intr() and FRUs match,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * turn it on.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * HW recommended not implementing
03831d35f7499c87d51205817c93e9a8d42c4baestevel * this delay for now.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The code is tested on PSUs:
03831d35f7499c87d51205817c93e9a8d42c4baestevel * -07 rev 2
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Hot insertion, so give it
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the 3 seconds it needs to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * become stable
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* PS_ON_DELAY */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Special SLOT handling.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Make sure the OK LED is on for the CPU Slot
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and for the FTC (CFTM) Slot for MonteCarlo.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Both will report as FRU_PRESENT.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Set OK (green) LED register bit
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Turn off BLINK register bit.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If single register update, then save the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * corresponding blink register in blink_reg.
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_set_scfg_pres(): writing %d bytes "
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((error = scsb_rdwr_register(scsb, I2C_WR, reg, i, puc, 1)) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Now see which BLINK bits need to be turned off for the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * corresponding OK LED bits.
193974072f41a843678abf5f61979c748687e66bSherry Moore "OFF Blink bits 0x%x in 0x%x",
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_set_scfg_pres(): "
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Base of register set
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SCB P0.6 workaround: read registers twice, use 2nd value set
193974072f41a843678abf5f61979c748687e66bSherry Moore SCTRL_CFG_NUMREGS, &scsb->scsb_data_reg[index], 1)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel "scsb_check_config_status: P0.6 workaround");
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If not P0.6 PROM, just break here
03831d35f7499c87d51205817c93e9a8d42c4baestevel } while (--p06);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_info_t *fru_ptr, *last_ptr, *acslot_ptr, *ctcslot_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Get the presence status from the SysConfigStatus shadow registers
03831d35f7499c87d51205817c93e9a8d42c4baestevel * in scsb->scsb_data_reg[]
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Mid Plane */
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = SYS_REG_INDEX(SCTRL_CFG_MPID0, SCTRL_SYSCFG_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mct_system_info.mid_plane.fru_version = (fru_version_t)0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mct_system_info.mid_plane.fru_id = (int)((scsb->scsb_data_reg[index] &
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_set_topology: 0x%x: unknown!",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cPCI Slots
03831d35f7499c87d51205817c93e9a8d42c4baestevel * NOTE: The Tonga slot fru_unit needs to get mapped to the logical
03831d35f7499c87d51205817c93e9a8d42c4baestevel * slot number in slot_table[]. The field is not in the slot_table
03831d35f7499c87d51205817c93e9a8d42c4baestevel * at least until we know the format of the OBP slot table for the FCS
193974072f41a843678abf5f61979c748687e66bSherry Moore (mct_system_info.max_units[SLOT] + pad), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (unit = 1; unit <= mct_system_info.max_units[SLOT]; ++unit) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* fru_ptr saved for Transition Card Presence check */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* fru_ptr saved for Alarm Card Presence check below */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Get the slot event code (t), then use it to get the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * slot bit-offsets for LED, BLINK, and SYSCFG registers.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * On a P1.5 Tonga, the internal slot number must be used to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * find the event code.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The P1.0 Tonga does not get mapped due to a SSB difference.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the registers addresses and shadow register index for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the SYSCFG register
03831d35f7499c87d51205817c93e9a8d42c4baestevel * check and set presence status
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (scsb->scsb_data_reg[index] & (1 << bit_num)) {
193974072f41a843678abf5f61979c748687e66bSherry Moore kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP);
193974072f41a843678abf5f61979c748687e66bSherry Moore (mct_system_info.max_units[PDU] + pad), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (unit = 1; unit <= mct_system_info.max_units[PDU]; ++unit) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* SCB15 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the FRU event code (t), then use it to get the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * FRU bit-offsets for LED and SYSCFG registers
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the registers addresses and shadow register index for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the SYSCFG register
03831d35f7499c87d51205817c93e9a8d42c4baestevel * check and set presence status
193974072f41a843678abf5f61979c748687e66bSherry Moore kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Power Supplies
193974072f41a843678abf5f61979c748687e66bSherry Moore (mct_system_info.max_units[PS] + pad), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (unit = 1; unit <= mct_system_info.max_units[PS]; ++unit) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the FRU event code (t), then use it to get the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * FRU bit-offsets for LED and SYSCFG registers
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the registers addresses and shadow register index for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the SYSCFG register
03831d35f7499c87d51205817c93e9a8d42c4baestevel * check and set presence status
193974072f41a843678abf5f61979c748687e66bSherry Moore kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SCSI Disks and removable media
193974072f41a843678abf5f61979c748687e66bSherry Moore (mct_system_info.max_units[DISK] + pad), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (unit = 1; unit <= mct_system_info.max_units[DISK]; ++unit) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* SCB15 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the FRU event code (t), then use it to get the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * FRU bit-offsets for LED and SYSCFG registers
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the registers addresses and shadow register index for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the SYSCFG register
03831d35f7499c87d51205817c93e9a8d42c4baestevel * check and set presence status
193974072f41a843678abf5f61979c748687e66bSherry Moore kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Fan Trays
193974072f41a843678abf5f61979c748687e66bSherry Moore (mct_system_info.max_units[FAN] + pad), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (unit = 1; unit <= mct_system_info.max_units[FAN]; ++unit) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* SCB15 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the FRU event code (t), then use it to get the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * FRU bit-offsets for LED and SYSCFG registers
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the registers addresses and shadow register index for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the SYSCFG register
03831d35f7499c87d51205817c93e9a8d42c4baestevel * check and set presence status
193974072f41a843678abf5f61979c748687e66bSherry Moore kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Alarm Cards
03831d35f7499c87d51205817c93e9a8d42c4baestevel mct_system_info.fru_info_list[ALARM] = (fru_info_t *)
193974072f41a843678abf5f61979c748687e66bSherry Moore (mct_system_info.max_units[ALARM] + pad), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (unit = 1; unit <= mct_system_info.max_units[ALARM]; ++unit) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the FRU event code (t), then use it to get the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * FRU bit-offsets for SYSCFG register
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the registers addresses and shadow register index for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the SYSCFG register
03831d35f7499c87d51205817c93e9a8d42c4baestevel * check and set presence status
03831d35f7499c87d51205817c93e9a8d42c4baestevel * acslot_ptr->fru_id =
193974072f41a843678abf5f61979c748687e66bSherry Moore * fru_id_table[event_to_index(t)];
193974072f41a843678abf5f61979c748687e66bSherry Moore kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP);
193974072f41a843678abf5f61979c748687e66bSherry Moore (mct_system_info.max_units[SCB] + pad), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* SCB15 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the FRU event code (t), then use it to get the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * FRU bit-offset for LED register
03831d35f7499c87d51205817c93e9a8d42c4baestevel * check and set presence status
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* get PROM_VERSION from shadow registers */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_rdwr_register(scsb, I2C_WR_RD, index, 1, &t_uchar, 1))
193974072f41a843678abf5f61979c748687e66bSherry Moore kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP);
193974072f41a843678abf5f61979c748687e66bSherry Moore (mct_system_info.max_units[SSB] + pad), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* SCB15 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the FRU event code (t), then use it to get the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * FRU bit-offset for SYSCFG register
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the registers addresses and shadow register index for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the SYSCFG register
03831d35f7499c87d51205817c93e9a8d42c4baestevel * check and set presence status
193974072f41a843678abf5f61979c748687e66bSherry Moore kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP);
193974072f41a843678abf5f61979c748687e66bSherry Moore (mct_system_info.max_units[CFTM] + pad), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* SCB15 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the FRU event code (t), then use it to get the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * FRU bit-offsets for LED and SYSCFG registers
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the registers addresses and shadow register index for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the SYSCFG register
03831d35f7499c87d51205817c93e9a8d42c4baestevel * check and set presence status
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ctcslot_ptr != NULL && ctcslot_ptr->fru_status ==
193974072f41a843678abf5f61979c748687e66bSherry Moore kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* SCB15 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the FRU event code (t), then use it to get the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * FRU bit-offsets for LED and SYSCFG registers
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the registers addresses and shadow register index for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the SYSCFG register
03831d35f7499c87d51205817c93e9a8d42c4baestevel * check and set presence status
193974072f41a843678abf5f61979c748687e66bSherry Moore kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP);
193974072f41a843678abf5f61979c748687e66bSherry Moore (mct_system_info.max_units[PRTM] + pad), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the FRU event code (t), then use it to get the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * FRU bit-offsets for LED and SYSCFG registers
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the registers addresses and shadow register index for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the SYSCFG register
03831d35f7499c87d51205817c93e9a8d42c4baestevel * check and set presence status
193974072f41a843678abf5f61979c748687e66bSherry Moore kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < SCSB_UNIT_TYPES; ++i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mct_system_info.fru_info_list[i] = (fru_info_t *)NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (force && !(scsb->scsb_state & (SCSB_DIAGS_MODE | SCSB_DEBUG_MODE)))
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "mct_topology_dump: Topology not set!");
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < SCSB_UNIT_TYPES; ++i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch ((scsb_utype_t)i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "MCT: MAX Number of Alarm Cards: %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "MCT: MAX Number of SCSI Devices: %d",
193974072f41a843678abf5f61979c748687e66bSherry Moore "MCT: MAX Number of Power Supplies: %d",
193974072f41a843678abf5f61979c748687e66bSherry Moore "MCT: type=%d, unit=%d, id=0x%x, "
193974072f41a843678abf5f61979c748687e66bSherry Moore "version=0x%x",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Sends an event when the system controller board I2C errors
03831d35f7499c87d51205817c93e9a8d42c4baestevel * exceed the threshold.
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) scsb_queue_ops(scsb, QPUT_INT32, 1, &scsb_event_code,
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_intr");
193974072f41a843678abf5f61979c748687e66bSherry Moore SCTRL_BHLTHY_NUMREGS, &scsb->scsb_data_reg[index], 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Returns the health status of a slot
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_read_slot_health(scsb_state_t *scsb, int pslotnum)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * DIAGNOSTIC and DEBUG only.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Called from ioctl command (SCSBIOC_BHEALTHY_GET)
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_bhealthy_slot(scsb_state_t *scsb, scsb_uinfo_t *suip)
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* operation valid for slots only */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (suip->unit_number > mct_system_info.max_units[SLOT]) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Map 1.0 Tonga Slot Number, if necessary
03831d35f7499c87d51205817c93e9a8d42c4baestevel code = FRU_UNIT_TO_EVCODE(suip->unit_type, suip->unit_number);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* else shadow regs are updated by interrupt handler */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Called from HSC and ioctl command (SCSBIOC_RESET_UNIT)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to reset one specified slot
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_reset_unit(scsb_state_t *scsb, scsb_uinfo_t *suip)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_reset_slot(%d): slot %d, state %d\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (suip->unit_state != ON && suip->unit_state != OFF) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel code = FRU_UNIT_TO_EVCODE(suip->unit_type, suip->unit_number);
03831d35f7499c87d51205817c93e9a8d42c4baestevel reset_state = (suip->unit_state == ON) ? SCSB_RESET_SLOT :
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (scsb_reset_slot(scsb, slotnum, reset_state));
03831d35f7499c87d51205817c93e9a8d42c4baestevel else /* OFF */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((error = scsb_rdwr_register(scsb, I2C_WR, reg, 1,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Diagnostic and DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This is a helper function for the helper ioctl to pretend that
03831d35f7499c87d51205817c93e9a8d42c4baestevel * scsb h/w is doing its job!!!
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_slot_occupancy(scsb_state_t *scsb, scsb_uinfo_t *suip)
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state & (SCSB_DEBUG_MODE | SCSB_DIAGS_MODE)))
193974072f41a843678abf5f61979c748687e66bSherry Moore (mct_system_info.fru_info_list[ALARM])->fru_unit) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * All slots are acceptable, except slots 11 & 12.
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Map 1.0 Tonga Slot Numbers if necessary */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (hsc_slot_occupancy(saved_unit_number, B_TRUE, 0, B_TRUE)
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (hsc_slot_occupancy(saved_unit_number, B_FALSE, 0, B_FALSE)
193974072f41a843678abf5f61979c748687e66bSherry Moore "write to 0x%x failed",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * write loop for Interrupt Mask registers
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error = scsb_write_mask(scsb, reg, rmask, wdata, 0)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Clear Interrupt masks based on the FRUs that could be installed
03831d35f7499c87d51205817c93e9a8d42c4baestevel * for this particular topology, determined by the MidPlane ID
03831d35f7499c87d51205817c93e9a8d42c4baestevel * from SCTRL_SYSCFG registers
03831d35f7499c87d51205817c93e9a8d42c4baestevel * case SCTRL_MPID_HALF:
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 1 CPU, 1 AlarmCard, 1 SCB/SSB, 2 PS, 3 FAN, 3 SCSI, 8 Slots
03831d35f7499c87d51205817c93e9a8d42c4baestevel * case SCTRL_MPID_QUARTER:
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 1 CPU, 1 AlarmCard, 1 SCB/SSB, 1 PS, 2 FAN, 1 SCSI, 4 Slots
03831d35f7499c87d51205817c93e9a8d42c4baestevel * case SCTRL_MPID_QUARTER_NODSK:
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 1 CPU, 1 AlarmCard, 1 SCB/SSB, 1 PS, 2 FAN, 0 SCSI, 4 Slots
03831d35f7499c87d51205817c93e9a8d42c4baestevel mbid = SCSB_REG_INDEX(msk_reg); /* the Mask Base Index Delta */
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "clear_intmasks: msk_reg=0x%x; mbid=%d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (fru_type = 0; fru_type < SCSB_UNIT_TYPES; ++fru_type) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue; /* handle below, 2 reg offsets */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "clear_intmasks:%d:%d: PRES mask[%d]:0x%x",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Unmask the corresponding Slot HLTHY mask
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Use Slot bit and register offsets,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * but with SCTRL_INTMASK_HLTHY_BASE
03831d35f7499c87d51205817c93e9a8d42c4baestevel "clear_intmasks:Slot:%d: HLTHY mask[%d]:0x%x"
03831d35f7499c87d51205817c93e9a8d42c4baestevel "; reg=0x%x, idx=%d, mbid=%d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Now unmask these non-fru interrupt events
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SCTRL_EVENT_PWRDWN (almost normal)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SCTRL_EVENT_REPLACE (not used)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SCTRL_EVENT_ALARM_INT (not working in P0.6/P1.0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SCTRL_EVENT_SCB (SCB 1.5 ONLY; plus SCB_INT_OFFSET)
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = FRU_REG_ADDR(code, SCTRL_INTMSK_BASE) + SCB_INT_OFFSET;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "clear_intmasks:0x%x: ~(0x%x),0x%x",
193974072f41a843678abf5f61979c748687e66bSherry Moore "write to 0x%x failed: %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_get_status(scsb_state_t *scsb, scsb_status_t *smp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel register int i;
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_readall_regs() FAILED");
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_get_status: FAILED Presence LEDs update");
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < SCSB_DATA_REGISTERS; ++i)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * scsb_freeze_check:
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Turn all the leds off on the system monitor card, without changing
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the state of what we have for scsb. This routine is called only when
03831d35f7499c87d51205817c93e9a8d42c4baestevel * replacing system monitor card, so the state of the card leds could be
03831d35f7499c87d51205817c93e9a8d42c4baestevel * restored, using scsb_restore().
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Also, set state to SCSB_FROZEN which denies access to scsb while in
03831d35f7499c87d51205817c93e9a8d42c4baestevel * freeze mode.
03831d35f7499c87d51205817c93e9a8d42c4baestevel "SCSB: Should NOT remove SCB(%d) while cPCI Slot %d is "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "in RESET with a possible bad board.";
03831d35f7499c87d51205817c93e9a8d42c4baestevel register int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_freeze_check(%d):", scsb->scsb_instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < SCTRL_MAX_GROUP_NUMREGS; ++i)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We allow the SCB to be removed only if none of
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the cPCI resets are asserted for occupied slots.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * There shouldn't be a bad board plugged in the system
03831d35f7499c87d51205817c93e9a8d42c4baestevel * while swapping the SCB.
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (unit = 1; unit <= mct_system_info.max_units[SLOT]; ++unit) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "scsb_freeze: SCB%d possibly removed",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Send the EVENT_SCB since there is evidence that the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * System Controller Board has been removed.
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) scsb_queue_ops(scsb, QPUT_INT32, 1, &code, "scsb_freeze");
03831d35f7499c87d51205817c93e9a8d42c4baestevel * scsb_restore will only be called from the interrupt handler context on
03831d35f7499c87d51205817c93e9a8d42c4baestevel * INIT_SCB interrupt for newly inserted SCB.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Called with mutex held.
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_restore(%d):", scsb->scsb_instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* 9. Clear all Interrupts */
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb%d: I2C TRANSFER Failed", scsb->scsb_instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "scsb_restore: clear_intmasks Failed");
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Check if Alarm Card present at boot and set flags */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Given an Event Code,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * FRU type in LSByte
03831d35f7499c87d51205817c93e9a8d42c4baestevel * unit number in MSByte
03831d35f7499c87d51205817c93e9a8d42c4baestevel * scsb interrupt handler for (MC) PSM_INT vector
03831d35f7499c87d51205817c93e9a8d42c4baestevel * P0.6: HW shipped to beta customers
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 1. did not have Slot Occupant Presense support
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 2. I2C interrupt-map properties not yet tested, using polling daemon
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 3. Polling detects each event reliably twice.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * clr_bits# are used to keep track of events to be ignored 2nd time
03831d35f7499c87d51205817c93e9a8d42c4baestevel * retval flags allow all events to be checked, and still returning the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * correct DDI value.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Does preprocessing of the interrupt. The only thing this
03831d35f7499c87d51205817c93e9a8d42c4baestevel * needs to do is to ask scsb to release the interrupt line.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and then schedule delayed actual processing using timeout()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If SCSB_IN_INTR is already set in scsb_state,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * it means we are being interrupted by someone else. This can
03831d35f7499c87d51205817c93e9a8d42c4baestevel * happen only if the interrupt does not belong to scsb, and some
03831d35f7499c87d51205817c93e9a8d42c4baestevel * other device, e.g. a FAN or PS is interrupting. So, we
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cancel the previous timeout().
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Stop scsb from interrupting first.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Schedule a timeout to actually process the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * interrupt.
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_intr_tid = timeout((void (*)(void *))scsb_intr, arg,
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void scsb_healthy_intr(scsb_state_t *scsb, int pslotnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel int intr_idx, index, offset_base, retval, slotnum, val;
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Avoid mayhem, make sure we have only one timeout thread running.
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_intr(%d)", scsb->scsb_instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * XXX: Problem, when we want to support swapping between SCB
03831d35f7499c87d51205817c93e9a8d42c4baestevel * versions, then we need to check the SCB PROM ID (CF) register here
03831d35f7499c87d51205817c93e9a8d42c4baestevel * before assuming the same SCB version was re-inserted.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We will have to duplicate some of the scb_initialization()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * code to set the scsb_state PROM ID bits and to set up the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * register table pointers.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Only if NOT SSB_PRESENT, check the SCB PROM ID
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Now check the INTSRC registers for set bits.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Do a quick check by OR'ing INTSRC registers together as we copy
03831d35f7499c87d51205817c93e9a8d42c4baestevel * them from the transfer buffer. For P1.0 or earlier we had already
03831d35f7499c87d51205817c93e9a8d42c4baestevel * read the interrupt source registers and wrote them back to stop
03831d35f7499c87d51205817c93e9a8d42c4baestevel * interrupt. So we need to do this step only for P1.5 or later.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We already read INTSRC6 to take care of SCB insertion case, so
03831d35f7499c87d51205817c93e9a8d42c4baestevel * do not read INTSRC6 again.
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* read the interrupt register from scsb */
193974072f41a843678abf5f61979c748687e66bSherry Moore " Failed read of interrupt registers.");
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We have seen that an interrupt source bit can be set
03831d35f7499c87d51205817c93e9a8d42c4baestevel * even though the corresponding interrupt mask bit
03831d35f7499c87d51205817c93e9a8d42c4baestevel * has been set to mask the interrupt. So we must
03831d35f7499c87d51205817c93e9a8d42c4baestevel * clear all bits set in the interrupt source register.
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < SCTRL_INTR_NUMREGS; ++i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Any bits from quick check? If this is not our interrupt,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * something is wrong. FAN/PS interrupts are supposed to be
03831d35f7499c87d51205817c93e9a8d42c4baestevel * blocked, but we can not be sure. So, go ahead and call the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * emergency interrupt handlers for FAN/PS devices and mask
03831d35f7499c87d51205817c93e9a8d42c4baestevel * their interrupts, if they aren't already masked.
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (retval == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If SCB 1.5 or 2.0, check for the INIT_SCB Interrupt
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to support Hot SCB Insertion.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The check was moved here during debugging of the SCB hot insertion.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Theoretically, this code could be moved back to the check for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SCTRL_EVENT_SCB in the processing loop below.
03831d35f7499c87d51205817c93e9a8d42c4baestevel offset = FRU_OFFSET(SCTRL_EVENT_SCB, SCTRL_INTPTR_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Must be newly inserted SCB
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Time to re-initialize.
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_intr(%d): INIT_SCB INT",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The INTSRC bit will be cleared by the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * scsb_restore() function.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Also, leave the bit set in scb_intr_regs[] so we can
03831d35f7499c87d51205817c93e9a8d42c4baestevel * report the event code as we check for other
03831d35f7499c87d51205817c93e9a8d42c4baestevel * interrupt source bits.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * scsb_write_mask(scsb, tmp_reg, 0, clr_bits, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * scb_intr_regs[intr_idx] &= ~clr_bits;
03831d35f7499c87d51205817c93e9a8d42c4baestevel * In case this is a power down interrupt, check the validity
03831d35f7499c87d51205817c93e9a8d42c4baestevel * of the request to make sure it's not an I2C noise
03831d35f7499c87d51205817c93e9a8d42c4baestevel * A shutdown request has been detected. Poll
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the corresponding register ? more times to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * make sure it's a genuine shutdown request.
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < scsb_shutdown_count; i++) {
193974072f41a843678abf5f61979c748687e66bSherry Moore " interrupt register");
193974072f41a843678abf5f61979c748687e66bSherry Moore " INTSRC6[%d]=0x%x", i,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * if retval == 0, then we didn't call scsb_restore,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * so we update the shadow copy of SYSCFG registers
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We *MUST* read the syscfg registers before any attempt
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to clear the interrupt source registers is made.
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_intr: Failed read of config/status registers");
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Allow to go on so we clear the INTSRC bits
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Read the board healthy registers here, if any of the healthy
03831d35f7499c87d51205817c93e9a8d42c4baestevel * interrupts are set.
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < SCTRL_BHLTHY_NUMREGS; ++i, ++intr_idx) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We clear the interrupt source registers now itself so that
03831d35f7499c87d51205817c93e9a8d42c4baestevel * future interrupts can be latched quickly, instead of after
03831d35f7499c87d51205817c93e9a8d42c4baestevel * finishing processing of all interrupt conditions. The global
03831d35f7499c87d51205817c93e9a8d42c4baestevel * interrupt mask however remain disabled.
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "scsb_intr: Failed write to interrupt"
193974072f41a843678abf5f61979c748687e66bSherry Moore " registers.");
03831d35f7499c87d51205817c93e9a8d42c4baestevel * At this point, all interrupt source registers are read.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We only handle interrups which are not masked
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < SCTRL_INTR_NUMREGS; ++i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We are here means that there was some bit set in the interrupt
03831d35f7499c87d51205817c93e9a8d42c4baestevel * source register. So we must claim the interrupt no matter
03831d35f7499c87d51205817c93e9a8d42c4baestevel * whatever error we may encounter in the course of processing.
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* store config status data */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < SCTRL_CFG_NUMREGS; ++i)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Clear the event code,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * then check to see what kind(s) of events we were interrupted for.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check all SCTRL_INTSRC registers
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If SCB 1.5, adjust some variables to skip the SCTRL_BHLTHY_REGS
03831d35f7499c87d51205817c93e9a8d42c4baestevel * which will be handled last in this function.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * For the rest of the INTSRC registers, we walk through the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * scb_fru_offset[] table, matching register offsets with our offset
03831d35f7499c87d51205817c93e9a8d42c4baestevel * counter. Then we check for the scb_fru_offset[] bit in intr_reg.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The scb_fru_offset[] index is now the SCTRL_EVENT code.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The code is then compared to type_to_code1[] entries to find the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * fru_type. The fru_type will help us recognize when to do
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SLOT Hot Swap processing.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * offset_base: the appropriate scb_fru_offset[] base index
03831d35f7499c87d51205817c93e9a8d42c4baestevel * for the INTPTR_BASE register group
03831d35f7499c87d51205817c93e9a8d42c4baestevel * offset: bit offset found in INTSRC register
03831d35f7499c87d51205817c93e9a8d42c4baestevel * intr_idx: index to temporary INTSRC register copies
03831d35f7499c87d51205817c93e9a8d42c4baestevel * intr: modified copy of current INTR register
03831d35f7499c87d51205817c93e9a8d42c4baestevel * intr_addr: SCB register address of current INTR register
03831d35f7499c87d51205817c93e9a8d42c4baestevel * index: index to current INTR shadow register
03831d35f7499c87d51205817c93e9a8d42c4baestevel * idx: bit-number of current INTR event bit
03831d35f7499c87d51205817c93e9a8d42c4baestevel * uc: uchar_t from scb_fru_offset[] table,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * containing register and FRU offsets.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * j: used to walk fru_offset[] table, which is also
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the bit-number of the current event code
03831d35f7499c87d51205817c93e9a8d42c4baestevel * code: manufactured event code for current INT event
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_data_reg[index] = scb_intr_regs[intr_idx];
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (intr_reg) { /* for each INTSRC bit that's set */
03831d35f7499c87d51205817c93e9a8d42c4baestevel idx = event_to_index((uint32_t)intr_reg); /* offset */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (j = 0; j < MCT_MAX_FRUS; ++j) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Get register offset from table and check
03831d35f7499c87d51205817c93e9a8d42c4baestevel * for a match with our loop offset counter.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Then check for intr_reg bit-offset match
03831d35f7499c87d51205817c93e9a8d42c4baestevel * with bit-offset from table entry.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * bit idx not recognized, check another.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We found the fru_offset[] entry, now use the index
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to get the event code.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Now check for the NON-FRU type events.
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_intr(%d): power down req."
03831d35f7499c87d51205817c93e9a8d42c4baestevel * inform applications using poll(2)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * about this event, and provide the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * event code to EnvMon scsb policy
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_intr(%d): replacement "
193974072f41a843678abf5f61979c748687e66bSherry Moore "req. INT.",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Must be newly inserted SCB
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Time to re-initialize.
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_intr(%d): INIT SCB INTR",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SCB initialization already handled, but we
03831d35f7499c87d51205817c93e9a8d42c4baestevel * set the event code bit here in order to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * report the event to interested utilities.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * scsb_restore(scsb);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The INTSRC bit is already cleared,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * so we won't do it again.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * P0.6/P1.0: SCTRL_INTR_ALARM_INT is always
03831d35f7499c87d51205817c93e9a8d42c4baestevel * set and cannot be cleared, so ignore it.
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_intr(%d): Alarm INT.",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Must service the Alarm INT by clearing INT
03831d35f7499c87d51205817c93e9a8d42c4baestevel * condition on Alarm Card,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * then clear the SCTRL_INTR_ALARM_INT bit here.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Waiting for specs and test environment.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * FRU type not found
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check for special processing
03831d35f7499c87d51205817c93e9a8d42c4baestevel * now that we found the FRU type.
193974072f41a843678abf5f61979c748687e66bSherry Moore "FRU type/unit/code %d/%d/0x%x",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * in check_fru_info() below, we see if the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SSB has been removed, then check for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * occupied slots in reset to see if we should
03831d35f7499c87d51205817c93e9a8d42c4baestevel * WARN agains SCB removal
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If the slot number is not valid, continue.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * For a tonga, we need to return
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the code corresponding to the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * actual physical slot
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* FALLTHROUGH */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * INDENT CHEATING, 2 indentations
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If it is an Alarm Card Interrupt, we just do some sanity
03831d35f7499c87d51205817c93e9a8d42c4baestevel * checks and then wait for the slot interrupt to take
03831d35f7499c87d51205817c93e9a8d42c4baestevel * connect or disconnect action.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * XXX - Is there a gaurantee that ALARM int will occur first ?
03831d35f7499c87d51205817c93e9a8d42c4baestevel * It is observed that slot presence and Alarm
03831d35f7499c87d51205817c93e9a8d42c4baestevel * presence bits do not go ON at the same time.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Hence we wait till both events happen.
193974072f41a843678abf5f61979c748687e66bSherry Moore "state bits do not match! (%x,%x)",
03831d35f7499c87d51205817c93e9a8d42c4baestevel break; /* we break and wait for slot interrupt. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cPCI slot interrupt event
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_is_alarm_card_slot(scsb, slotnum) == B_TRUE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel val = scsb_fru_op(scsb, SLOT, unit, SCTRL_SYSCFG_BASE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "state bits do not match! (%x,%x)",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Special case : check MPID type.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If MC midplane type,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * check to make sure the Alarm Card present
03831d35f7499c87d51205817c93e9a8d42c4baestevel * bit is ON. If not, this is a regular IO card.
193974072f41a843678abf5f61979c748687e66bSherry Moore (scsb->scsb_hsc_state & SCSB_ALARM_CARD_PRES)) {
193974072f41a843678abf5f61979c748687e66bSherry Moore "!AC_PRES slot %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * END INDENT CHEATING, 2 indentations
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ERROR: Did not find cause of INTSRC bit
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_intr: FRU type %d"
193974072f41a843678abf5f61979c748687e66bSherry Moore "I2C write error to 0x%x",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check for SCB 1.5 interrupt for SLOT HEALTHY changes
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < SCTRL_BHLTHY_NUMREGS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_data_reg[index++] = scb_intr_regs[intr_idx];
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* idx + 1 because bit 0 is for Slot 1 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) scsb_queue_ops(scsb, QPUT_INT32, 1, &scsb_event_code,
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_intr");
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "Summary of times in nsec: pre_time %llu, \
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Re-enable interrupt now.
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_polled_int(scsb_state_t *scsb, int cmd, uint32_t *set)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * scsb_intr() may modify scsb_event_code
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SCSB_P06_INTR_ON, we know there was an event
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and we're retrieving the event code from the event FIFO.
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_polled_int: event_code = 0x%x", *set);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_leds_switch(scsb_state_t *scsb, scsb_ustate_t op)
03831d35f7499c87d51205817c93e9a8d42c4baestevel register int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Step 1: turn ON/OFF all NOK LEDs. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel else /* off */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < SCTRL_LED_NOK_NUMREGS; ++i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = scsb_rdwr_register(scsb, I2C_WR, reg, SCTRL_LED_NOK_NUMREGS,
193974072f41a843678abf5f61979c748687e66bSherry Moore "Failed to turn %s NOK LEDs",
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Step 2: turn ON/OFF all OK LEDs. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < SCTRL_LED_OK_NUMREGS; ++i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = scsb_rdwr_register(scsb, I2C_WR, reg, SCTRL_LED_OK_NUMREGS,
193974072f41a843678abf5f61979c748687e66bSherry Moore "Failed to turn %s NOK LEDs",
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Step 3: turn OFF all BLINK LEDs. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < SCTRL_BLINK_NUMREGS; ++i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = scsb_rdwr_register(scsb, I2C_WR, reg, SCTRL_BLINK_NUMREGS,
193974072f41a843678abf5f61979c748687e66bSherry Moore "Failed to turn %s BLINK BITs",
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = scsb_rdwr_register(scsb, I2C_WR_RD, reg, SCSB_DATA_REGISTERS,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * read 1-byte register, mask with read bits (rmask),
03831d35f7499c87d51205817c93e9a8d42c4baestevel * turn ON bits in on_mask, turn OFF bits in off_mask
03831d35f7499c87d51205817c93e9a8d42c4baestevel * write the byte back to register
03831d35f7499c87d51205817c93e9a8d42c4baestevel * NOTE: MUST be called with mutex held
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* select the register address and read the register */
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_kstat_flag = B_TRUE; /* we did a i2c transaction */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error = nct_i2c_transfer(scsb->scsb_phandle, i2cxferp)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error = nct_i2c_transfer(scsb->scsb_phandle, i2cxferp)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* keep shadow registers updated */
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_write_mask() wrote 0x%x", reg_data);
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_write_mask(): reg %x %s error, data=%x",
193974072f41a843678abf5f61979c748687e66bSherry Moore i2cxferp->i2c_flags & I2C_WR ? "write" : "read",
193974072f41a843678abf5f61979c748687e66bSherry Moore i2cxferp->i2c_wbuf[1] : i2cxferp->i2c_rbuf[0]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * read/write len consecutive single byte registers to/from rbuf
03831d35f7499c87d51205817c93e9a8d42c4baestevel * NOTE: should be called with mutex held
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_rdwr_register(scsb_state_t *scsb, int op, uchar_t reg, int len,
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_rdwr_register(scsb,%s,%x,%x,buf):",
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2cxferp = scsb_alloc_i2ctx(scsb->scsb_phandle, I2C_NOSLEEP);
193974072f41a843678abf5f61979c748687e66bSherry Moore "i2ctx allocation failure");
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (op) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < len; ++i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel "scsb_rdwr_register: writing rwbuf[%d]=0x%x",
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* select the register address */
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_kstat_flag = B_TRUE; /* we did a i2c transaction */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error = nct_i2c_transfer(scsb->scsb_phandle, i2cxferp)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (rlen) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* copy to rwbuf[] and keep shadow registers updated */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < len; ++i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel "scsb_rdwr_register: read rwbuf[%d]=0x%x",
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_rdwr_register(): I2C read error from %x",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Called from scsb_intr()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * First find the fru_info for this fru_id, and set fru_status for callback.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Then check for a registered call_back entry for this fru_id,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and if found, call it.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Recursize call until no EVENTS left in evcode.
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "check_fru_info(scsb,0x%x)", evcode);
193974072f41a843678abf5f61979c748687e66bSherry Moore "check_fru_info: index %d out of range", i);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * WARN against SCB removal if any
03831d35f7499c87d51205817c93e9a8d42c4baestevel * occupied slots are in reset
03831d35f7499c87d51205817c93e9a8d42c4baestevel * check for an entry in the CallBack table
193974072f41a843678abf5f61979c748687e66bSherry Moore "check_fru_info: callback for FRU_ID "
193974072f41a843678abf5f61979c748687e66bSherry Moore "0x%x; device is %spresent",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * -----------------------------
03831d35f7499c87d51205817c93e9a8d42c4baestevel * scsb kstat support functions.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * -----------------------------
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Create and initialize the kstat data structures
03831d35f7499c87d51205817c93e9a8d42c4baestevel * scsb_ks_leddata_t for "scsb_leddata"
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_alloc_kstats: create scsb_leddata: %lu bytes",
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((scsb->ks_leddata = kstat_create(scsb_name, scsb->scsb_instance,
193974072f41a843678abf5f61979c748687e66bSherry Moore sizeof (scsb_ks_leddata_t), KSTAT_FLAG_PERSISTENT))
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (update_ks_leddata(scsb->ks_leddata, KSTAT_READ) != DDI_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * scsb_ks_state_t for "scsb_state"
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_alloc_kstats: create scsb_state: %lu bytes",
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((scsb->ks_state = kstat_create(scsb_name, scsb->scsb_instance,
193974072f41a843678abf5f61979c748687e66bSherry Moore sizeof (scsb_ks_state_t), KSTAT_FLAG_PERSISTENT))
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (update_ks_state(scsb->ks_state, KSTAT_READ) != DDI_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mct_topology_t for "env_topology"
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_alloc_kstats: create env_toploogy: %lu bytes",
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((scsb->ks_topology = kstat_create(scsb_name, scsb->scsb_instance,
193974072f41a843678abf5f61979c748687e66bSherry Moore sizeof (mct_topology_t), KSTAT_FLAG_PERSISTENT))
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (update_ks_topology(scsb->ks_topology, KSTAT_READ) != DDI_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * kstat_named_t * 2 for "scsb_evc_register"
03831d35f7499c87d51205817c93e9a8d42c4baestevel "scsb_alloc_kstats: create scsb_evc_register: %lu bytes",
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((scsb->ks_evcreg = kstat_create(scsb_name, scsb->scsb_instance,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCSB_KS_EVC_REGISTER, "misc", KSTAT_TYPE_NAMED, 2,
193974072f41a843678abf5f61979c748687e66bSherry Moore KSTAT_FLAG_PERSISTENT|KSTAT_FLAG_WRITABLE)) == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel kstat_named_init(&kn[0], "pid_register", KSTAT_DATA_INT64);
03831d35f7499c87d51205817c93e9a8d42c4baestevel kstat_named_init(&kn[1], "pid_unregister", KSTAT_DATA_INT64);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Done, set the flag for scsb_detach() and other checks
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "update_ks_leddata: KS_UPDATE%sset",
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_state & SCSB_KS_UPDATE ? " " : " not ");
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Since this is satisfied from the shadow registers, let it succeed
03831d35f7499c87d51205817c93e9a8d42c4baestevel * even if the SCB is not present. It would be nice to return the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * shadow values with a warning.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * if (scsb->scsb_state & SCSB_FROZEN) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cv_wait_sig(&scsb->scsb_cv, &scsb->scsb_mutex) <= 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "update_ks_leddata: updating data");
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Call tonga_slotnum_led_shift() for each register that
03831d35f7499c87d51205817c93e9a8d42c4baestevel * contains Slot 1-5 information, the first register at each base:
03831d35f7499c87d51205817c93e9a8d42c4baestevel * NOK_BASE, OK_BASE, BLINK_OK_BASE
03831d35f7499c87d51205817c93e9a8d42c4baestevel * XXX: breaking register table access rules by not using macros.
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = tonga_slotnum_led_shift(scsb, scsb->scsb_data_reg[index]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_leddata->scb_led_regs[i] = scsb->scsb_data_reg[index];
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = tonga_slotnum_led_shift(scsb, scsb->scsb_data_reg[index]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_leddata->scb_led_regs[i] = scsb->scsb_data_reg[index];
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* BLINK */
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = tonga_slotnum_led_shift(scsb, scsb->scsb_data_reg[index]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_leddata->scb_led_regs[i] = scsb->scsb_data_reg[index];
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "update_ks_evcreg: %s(%d), KS_UPDATE%sset",
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_state & SCSB_KS_UPDATE ? " " : " not ");
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Let this registration succeed
03831d35f7499c87d51205817c93e9a8d42c4baestevel * if (scsb->scsb_state & SCSB_FROZEN) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cv_wait_sig(&scsb->scsb_cv, &scsb->scsb_mutex) <= 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * kn[0] is "pid_register", kn[1] is "pid_unregister"
193974072f41a843678abf5f61979c748687e66bSherry Moore "update_ks_evcreg: "
193974072f41a843678abf5f61979c748687e66bSherry Moore "process add failed for %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (kn[0].value.i64 == 0 && kn[1].value.i64 != 0) {
193974072f41a843678abf5f61979c748687e66bSherry Moore "update_ks_evcreg: "
193974072f41a843678abf5f61979c748687e66bSherry Moore "process delete failed for %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (kn[0].value.i64 == 0 && kn[1].value.i64 == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * rewind the pointers and counts, zero the table.
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_state & SCSB_KS_UPDATE ? " " : " not ");
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Let this succeed based on last known data
03831d35f7499c87d51205817c93e9a8d42c4baestevel * if (scsb->scsb_state & SCSB_FROZEN) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cv_wait_sig(&scsb->scsb_cv, &scsb->scsb_mutex) <= 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If SSB not present and scsb not SCSB_FROZEN, check for SCB presence
03831d35f7499c87d51205817c93e9a8d42c4baestevel * by initiating an I2C read from the SCB. If an error occurs,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * scsb_freeze() will be called to update SCB info and scsb state.
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Read the SCB PROM ID */
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_state->scb_present = (scsb->scsb_state & SCSB_SCB_PRESENT) ? 1 : 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_state->ssb_present = (scsb->scsb_state & SCSB_SSB_PRESENT) ? 1 : 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_state->scsb_frozen = (scsb->scsb_state & SCSB_FROZEN) ? 1 : 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If scsb_attach() has not completed the kstat installs,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * then there are no event processes to check for.
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* FALLTHROUGH */
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "update_ks_topology: KS_UPDATE%sset",
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_state & SCSB_KS_UPDATE ? " " : " not ");
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Let this succeed based on last known data
03831d35f7499c87d51205817c93e9a8d42c4baestevel * if (scsb->scsb_state & SCSB_FROZEN) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cv_wait_sig(&scsb->scsb_cv, &scsb->scsb_mutex) <= 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If SSB not present and scsb not SCSB_FROZEN, check for SCB presence
03831d35f7499c87d51205817c93e9a8d42c4baestevel * by initiating an I2C read from the SCB. If an error occurs,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * scsb_freeze() will be called to update SCB info and scsb state.
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Read the SCB PROM ID */
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->max_units[i] = mct_system_info.max_units[i];
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mid_plane.fru_type = mct_system_info.mid_plane.fru_type;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mid_plane.fru_id = mct_system_info.mid_plane.fru_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mid_plane.fru_version = mct_system_info.mid_plane.fru_version;
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < pks_topo->max_units[SLOT]; ++i, ++fru_ptr) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_slots[i].fru_status = fru_ptr->fru_status;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_slots[i].fru_version = fru_ptr->fru_version;
03831d35f7499c87d51205817c93e9a8d42c4baestevel * XXX: need to check healthy regs to set fru_health
03831d35f7499c87d51205817c93e9a8d42c4baestevel val = scsb_fru_op(scsb, SLOT, slotnum, SCTRL_BHLTHY_BASE,
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < pks_topo->max_units[PDU]; ++i, ++fru_ptr) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_pdu[i].fru_status = fru_ptr->fru_status;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_pdu[i].fru_version = fru_ptr->fru_version;
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < pks_topo->max_units[PS]; ++i, ++fru_ptr) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_ps[i].fru_status = fru_ptr->fru_status;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_ps[i].fru_version = fru_ptr->fru_version;
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < pks_topo->max_units[DISK]; ++i, ++fru_ptr) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_disk[i].fru_status = fru_ptr->fru_status;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_disk[i].fru_version = fru_ptr->fru_version;
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < pks_topo->max_units[FAN]; ++i, ++fru_ptr) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_fan[i].fru_status = fru_ptr->fru_status;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_fan[i].fru_version = fru_ptr->fru_version;
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < pks_topo->max_units[SCB]; ++i, ++fru_ptr) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_scb[i].fru_status = fru_ptr->fru_status;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_scb[i].fru_version = fru_ptr->fru_version;
03831d35f7499c87d51205817c93e9a8d42c4baestevel * To get the scsb health, if there was no i2c transaction
03831d35f7499c87d51205817c93e9a8d42c4baestevel * until this read, generate an i2c transaction.
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_scb[i].fru_health = ((scsb->scsb_err_flag ==
193974072f41a843678abf5f61979c748687e66bSherry Moore B_TRUE || scsb->scsb_i2c_errcnt > scsb_err_threshold)
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (pks_topo->mct_scb[i].fru_health == MCT_HEALTH_NOK)
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_err_flag = B_FALSE; /* clear error flag once read */
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_kstat_flag = B_FALSE; /* false? read from i2c */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < pks_topo->max_units[SSB]; ++i, ++fru_ptr) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_ssb[i].fru_status = fru_ptr->fru_status;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_ssb[i].fru_version = fru_ptr->fru_version;
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < pks_topo->max_units[ALARM]; ++i, ++fru_ptr) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_alarm[i].fru_status = fru_ptr->fru_status;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_alarm[i].fru_version = fru_ptr->fru_version;
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < pks_topo->max_units[CFTM]; ++i, ++fru_ptr) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_cftm[i].fru_status = fru_ptr->fru_status;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_cftm[i].fru_version = fru_ptr->fru_version;
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < pks_topo->max_units[CRTM]; ++i, ++fru_ptr) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_crtm[i].fru_status = fru_ptr->fru_status;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_crtm[i].fru_version = fru_ptr->fru_version;
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < pks_topo->max_units[PRTM]; ++i, ++fru_ptr) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_prtm[i].fru_status = fru_ptr->fru_status;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_prtm[i].fru_version = fru_ptr->fru_version;
03831d35f7499c87d51205817c93e9a8d42c4baestevel * free the allocated kstat data
03831d35f7499c87d51205817c93e9a8d42c4baestevel * --------------------------------------
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Miscellaneous scsb internal functions.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * --------------------------------------
03831d35f7499c87d51205817c93e9a8d42c4baestevel * allocate I2C transfer structure
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_alloc_i2ctx(i2c_client_hdl_t phandle, uint_t sleep)
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (i2c_transfer_alloc(phandle, &tp, SCSB_DATA_REGISTERS + 2,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCSB_DATA_REGISTERS + 2, sleep) == I2C_FAILURE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * free I2C transfer structure
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_free_i2ctx(i2c_client_hdl_t phandle, i2c_transfer_t *tp)
03831d35f7499c87d51205817c93e9a8d42c4baestevelupdate_fru_info(scsb_state_t *scsb, fru_info_t *fru_ptr)
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki cmn_err(CE_NOTE, "update_fru_info(scsb,0x%p)", (void *)fru_ptr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If this is an Alarm Card update, then we also need to get
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Alarm Card Slot fru_ptr to update it's fru_type, and maybe fru_id
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (fru_ptr->fru_id == fru_id_table[FRU_INDEX(SCTRL_EVENT_ALARM)]) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SCTRL_EVENT_SLOT1 == 0x01 so
03831d35f7499c87d51205817c93e9a8d42c4baestevel * fru_id_table[] index for Slot 1 == 0
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (reg) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * XXX: need to add version register, and maybe a
03831d35f7499c87d51205817c93e9a8d42c4baestevel * method, to the fru_ptr->i2c_info structure.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * fru_ptr->fru_version = (fru_version_t)0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Because scsb_intr() sometimes gets the AC present
03831d35f7499c87d51205817c93e9a8d42c4baestevel * INT before the ACSLOT present INT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * do not check the ACSLOT fru_status
03831d35f7499c87d51205817c93e9a8d42c4baestevel * if (acslot_ptr != NULL && acslot_ptr->fru_status ==
03831d35f7499c87d51205817c93e9a8d42c4baestevel * FRU_PRESENT)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * fru_ptr->fru_version = (fru_version_t)0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* AC just removed, but AC Slot is occupied? */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* for now it's unknown */
193974072f41a843678abf5f61979c748687e66bSherry Moore "update_fru_info: type %d unit %d is %spresent",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Convert EVENT code to FRU index
03831d35f7499c87d51205817c93e9a8d42c4baestevel * by finding the highest bit number in 32 bit word
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (i);
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_debug_prnt(char *fmt, uintptr_t a1, uintptr_t a2, uintptr_t a3,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * event code functions to deliver event codes
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and to manage:
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the event code fifo
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the process handle table for registered processes interested in
03831d35f7499c87d51205817c93e9a8d42c4baestevel * event codes
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Send signal to processes registered for event code delivery
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i = 0, c = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (; i < EVC_PROCS_MAX; ++i) {
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb:signal_evc_procs: "
193974072f41a843678abf5f61979c748687e66bSherry Moore "signal to %d failed",
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (++c >= evc_proc_count) {
193974072f41a843678abf5f61979c748687e66bSherry Moore "signal_evc_procs: signaled "
193974072f41a843678abf5f61979c748687e66bSherry Moore "%d/%d processes", c,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * bump FIFO ptr, taking care of wrap around
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Called from scsb_intr() when a new event occurs, to put new code in FIFO,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and signal any interested processes in evc_procs[].
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Always succeeds.
03831d35f7499c87d51205817c93e9a8d42c4baesteveladd_event_code(scsb_state_t *scsb, uint32_t event_code)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "add_event_code: 0x%x, FIFO size = %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * called from check_event_procs() when the last registered process
03831d35f7499c87d51205817c93e9a8d42c4baestevel * retrieved the oldest event
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "del_event_code: 0x%x, FIFO size = %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * called from check_event_procs() to retrieve the current event code
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * called from an application interface (ie: an ioctl command)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to register a process id interested in SCB events.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * NOTE: proc_ref() must be called from USER context, so since this is a
03831d35f7499c87d51205817c93e9a8d42c4baestevel * streams driver, a kstat interface is used for process registration.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 0 = event_proc was added
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 1 = out of space
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel curr_pid = (pid_t)(((struct pid *)curr_proc)->pid_id);
193974072f41a843678abf5f61979c748687e66bSherry Moore "add_event_proc: current %d != requestor %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (; i < EVC_PROCS_MAX; ++i) {
193974072f41a843678abf5f61979c748687e66bSherry Moore "add_event_proc: %d; evc_proc_count=%d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * called from an application interface (ie: an ioctl command)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to unregister a process id interested in SCB events.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 0 = event_proc was deleted
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 1 = event_proc was not found, or table was empty
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (; i < EVC_PROCS_MAX; ++i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (--evc_proc_count == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * reset evc fifo cound and pointers
193974072f41a843678abf5f61979c748687e66bSherry Moore "del_event_proc: %d; evc_proc_count=%d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Can be called from an application interface
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to rewind the pointers and counters, and zero the table
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "rew_event_proc: evc_proc_count=%d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (; i < EVC_PROCS_MAX; ++i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 1 = pid was found
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 0 = pid was not found, or table was empty
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (; i < EVC_PROCS_MAX; ++i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * called from update_ks_state() to compare evc_proc_count with
03831d35f7499c87d51205817c93e9a8d42c4baestevel * evc_requests, also mainted by this same function
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This function could check the current process id, since this will be a user
03831d35f7499c87d51205817c93e9a8d42c4baestevel * context call, and only bump evc_requests if the calling process is
03831d35f7499c87d51205817c93e9a8d42c4baestevel * registered for event code delivery.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * EVC_NO_EVENT_CODE : no event_code on fifo
03831d35f7499c87d51205817c93e9a8d42c4baestevel * EVC_NO_CURR_PROC : current process not in table,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * but have an event_code
03831d35f7499c87d51205817c93e9a8d42c4baestevel * EVC_NEW_EVENT_CODE : return_evc is new ks_state->event_code
03831d35f7499c87d51205817c93e9a8d42c4baestevel * EVC_OR_EVENT_CODE : OR return_evc with ks_state->event_code
03831d35f7499c87d51205817c93e9a8d42c4baestevel * EVC_FAILURE : unrecoverable error condition.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get current process handle, and check the event_procs table
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "check_event_procs: pid=%d, evc=0x%x, "
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_queue_put(queue_t *rq, int count, uint32_t *data, char *caller)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_queue_put(0x%p, %d, 0x%x, %s)",
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (count--) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int clone, find_open, find_available, retval = QOP_FAILED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (op) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*FALLTHROUGH*/
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (clone = SCSB_CLONES_FIRST; clone < SCSB_CLONES_MAX; clone++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (op) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (op) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Find out if a bit is set for the FRU type and unit number in the register
03831d35f7499c87d51205817c93e9a8d42c4baestevel * set defined by the register base table index, base.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Returns TRUE if bit is set, or FALSE.
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_fru_op(scsb_state_t *scsb, scsb_utype_t fru_type, int unit, int base,
03831d35f7499c87d51205817c93e9a8d42c4baestevel ac_mask = 1 << FRU_OFFSET(SCTRL_EVENT_ALARM, SCTRL_RESET_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* get the event code based on which we get the reg and bit offsets */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* get the bit offset in the 8bit register corresponding to the event */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* register offset from the base register, based on the event code */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((fru_type == ALARM) && (base == SCTRL_RESET_BASE))
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* get the global offset of the register in the parent address space */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* get the global index of the register in this SCSB's address space */
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUG4("scsb_fru_op(start): code=%x, offset=%x, tmp=%x, reg=%x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (op) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUG4("scsb_fru_op: unit=%x, base=%x, op=%d, rc=%x\n", unit, base,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * All HSC related functions can fail, but an attempt is made to atleast
03831d35f7499c87d51205817c93e9a8d42c4baestevel * return the right shadow state on get-state function when SCB is removed.
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_get_slot_state(scsb_state_t *scsb, int pslotnum, int *rstate)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * When SCB is removed, we could be called with the lock held.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We call check_config_status anyway since it is a read-only operation
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and HSC could be invoking this function at interrupt context.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If scsb is already in the doing interrupt postprocess, wait..
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* check if error is because SCB is removed */
03831d35f7499c87d51205817c93e9a8d42c4baestevel val = scsb_fru_op(scsb, SLOT, slotnum, SCTRL_SYSCFG_BASE,
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * now, lets determine if it is connected or disconnected.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If reset is asserted, then the slot is disconnected.
03831d35f7499c87d51205817c93e9a8d42c4baestevel rc = scsb_reset_slot(scsb, pslotnum, SCSB_GET_SLOT_RESET_STATUS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* check if error is because SCB is removed */
03831d35f7499c87d51205817c93e9a8d42c4baestevel val = scsb_fru_op(scsb, SLOT, slotnum, SCTRL_RESET_BASE,
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_fru_op(scsb, SLOT, slotnum, SCTRL_BHLTHY_BASE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "Healthy# Failed slot %d!",
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_reset_slot(scsb_state_t *scsb, int pslotnum, int reset_flag)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_reset_slot(%d), flag %x", pslotnum,
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_is_alarm_card_slot(scsb, pslotnum) == B_TRUE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_kstat_flag = B_TRUE; /* we did an i2c transaction */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((error = nct_i2c_transfer(scsb->scsb_phandle, i2cxferp)) == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * XXX: following statements assume 2 reset registers,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * which is the case for our current SCB revisions.
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_data_reg[index+1] = i2cxferp->i2c_rbuf[1];
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_err_flag = B_TRUE; /* latch until kstat */
193974072f41a843678abf5f61979c748687e66bSherry Moore " reading Reset regs\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUG2("pre-reset regs = %x,%x\n", scsb->scsb_data_reg[index],
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((reset_flag == SCSB_GET_SLOT_RESET_STATUS) || (error)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel val = scsb_fru_op(scsb, SLOT, slotnum, SCTRL_RESET_BASE,
03831d35f7499c87d51205817c93e9a8d42c4baestevel ac_val = scsb_fru_op(scsb, ALARM, 1, SCTRL_RESET_BASE,
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((val == 0) && (reset_flag == SCSB_UNRESET_SLOT)) {
193974072f41a843678abf5f61979c748687e66bSherry Moore " Slot%d_RST# not active!\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2cxferp->i2c_wbuf[0] = scsb_fru_op(scsb, SLOT, slotnum,
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG /* dont reset Alarm Card line unless in debug mode */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG /* dont Unreset Alarm Card line unless in debug mode */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error = nct_i2c_transfer(scsb->scsb_phandle, i2cxferp)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "%s#%d: reset_slot: error writing to"
193974072f41a843678abf5f61979c748687e66bSherry Moore " Reset regs (op=%d, data=%x)\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* now read back and update our scsb structure */
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_data_reg[index+1] = i2cxferp->i2c_rbuf[1];
193974072f41a843678abf5f61979c748687e66bSherry Moore " reading Reset regs (post reset)\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* XXX: P1.5 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUG2("post-reset regs = %x,%x\n", scsb->scsb_data_reg[index],
03831d35f7499c87d51205817c93e9a8d42c4baestevel val = scsb_fru_op(scsb, SLOT, slotnum, SCTRL_RESET_BASE,
03831d35f7499c87d51205817c93e9a8d42c4baestevel ac_val = scsb_fru_op(scsb, ALARM, 1, SCTRL_RESET_BASE,
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "Cannot UnReset Slot %d (reg=%x)\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore "Alarm_RST#.\n");
193974072f41a843678abf5f61979c748687e66bSherry Moore "Alarm_RST#.\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_connect_slot(scsb_state_t *scsb, int pslotnum, int healthy)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If Power needs to be handled, it should be done here.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Since there is no power handling for now, lets disable
03831d35f7499c87d51205817c93e9a8d42c4baestevel * reset, wait for healthy to come on and then call it
03831d35f7499c87d51205817c93e9a8d42c4baestevel * connected.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If HLTHY# does not come on (in how long is the question)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * then we stay disconnected.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * P1.5 doesnt require polling healthy as we get an
03831d35f7499c87d51205817c93e9a8d42c4baestevel * interrupt. So we could just update our state as disconnected
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and return waiting for the healthy# interrupt. To make it
03831d35f7499c87d51205817c93e9a8d42c4baestevel * more efficient, lets poll for healthy# a short while since we are
03831d35f7499c87d51205817c93e9a8d42c4baestevel * in the interrupt context anyway. If we dont get a healthy# we
03831d35f7499c87d51205817c93e9a8d42c4baestevel * return, and then wait for the interrupt. Probably the warning
03831d35f7499c87d51205817c93e9a8d42c4baestevel * message needs to be removed then. Need a PROM check flag here.
03831d35f7499c87d51205817c93e9a8d42c4baestevel while ((healthy == B_FALSE) && (count < scsb_healthy_poll_count)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel val = scsb_fru_op(scsb, SLOT, slotnum, SCTRL_BHLTHY_BASE,
03831d35f7499c87d51205817c93e9a8d42c4baestevel drv_usecwait(100); /* cant delay(9f) in intr context */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (healthy == B_FALSE && count == scsb_healthy_poll_count) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((scsb_is_alarm_card_slot(scsb, pslotnum) == B_TRUE) &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (hsc_slot_occupancy(pslotnum, 1, slot_flag, healthy));
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_disconnect_slot(scsb_state_t *scsb, int occupied, int slotnum)
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Reset is must at extraction. Move on even if failure. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_reset_slot(scsb, slotnum, SCSB_RESET_SLOT) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If board is still in slot, which means there is a manual
03831d35f7499c87d51205817c93e9a8d42c4baestevel * disconnection in progress, return failure.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Otherwise, a board was removed anyway; so we need to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * update the status and move on.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the following bug needs to be fixed.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * When this function is called from scsb_intr, scsb_state already
03831d35f7499c87d51205817c93e9a8d42c4baestevel * clears the 'AC card present' bit.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * However, hsc module doesn't depend on slot_flag during removal.
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((scsb_is_alarm_card_slot(scsb, slotnum) == B_TRUE) &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (hsc_slot_occupancy(slotnum, occupied, slot_flag, B_FALSE));
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_is_alarm_card_slot(scsb_state_t *scsb, int slotnum)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return ((scsb->ac_slotnum == slotnum)? B_TRUE:B_FALSE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Invoked both by the hsc and the scsb module to exchanges necessary
03831d35f7499c87d51205817c93e9a8d42c4baestevel * information regarding the alarm card.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * scsb calls this function to unconfigure the alarm card while the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * hsc calls this function at different times to check busy status,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and during post hotswap insert operation so that the user process
03831d35f7499c87d51205817c93e9a8d42c4baestevel * if one waiting can configure the alarm card.
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_hsc_ac_op(scsb_state_t *scsb, int pslotnum, int op)
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_hsc_state & SCSB_ALARM_CARD_PRES)) {
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb: HSC not initialized or AC not present!");
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (op) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* hsc -> scsb */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* API -> scsb */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * NOTE: this could be called multiple times from envmond if
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the daemon is reinitialized with SIGHUP, or stopped and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * restarted.
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_hsc_ac_op(SCSB_HSC_AC_SET_BUSY)");
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* hsc -> scsb */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "scsb_hsc_ac_op(SCSB_HSC_AC_CONFIGURED)");
03831d35f7499c87d51205817c93e9a8d42c4baestevel * wakeup anyone waiting on AC to be configured
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Send the ALARM_CARD_CONFIGURE Event to all scsb
03831d35f7499c87d51205817c93e9a8d42c4baestevel * open streams.
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* hsc -> scsb */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "scsb_hsc_ac_op(SCSB_HSC_AC_REMOVAL_ALERT)");
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Inform (envmond)alarmcard.so that it should save
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the AC configuration, stop the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * heartbeat, and shutdown the RSC link.
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* API -> scsb -> hsc */
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_hsc_ac_op(SCSB_HSC_AC_UNCONFIG"
193974072f41a843678abf5f61979c748687e66bSherry Moore "URE), AC NOT BUSY");
03831d35f7499c87d51205817c93e9a8d42c4baestevel * send notification back to HSC to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * unconfigure the AC, now that the env monitor
03831d35f7499c87d51205817c93e9a8d42c4baestevel * has given permission to do so.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The interrupt source register can have the healthy
03831d35f7499c87d51205817c93e9a8d42c4baestevel * bit set for non-existing slot, e.g slot 7 on Tonga.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * It can also be seen on the Tonga CPU slot. So we make
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sure we have a valid slot before proceeding.
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (pslotnum > TG_MAX_SLOTS || pslotnum == SC_TG_CPU_SLOT) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (pslotnum > MC_MAX_SLOTS || pslotnum == SC_MC_CPU_SLOT ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The board healthy registers are already read before entering
03831d35f7499c87d51205817c93e9a8d42c4baestevel * this routine
03831d35f7499c87d51205817c93e9a8d42c4baestevel * P1.5. Following works since slots 1 through 8 are in the same reg
03831d35f7499c87d51205817c93e9a8d42c4baestevel val = scsb_fru_op(scsb, SLOT, slotnum, SCTRL_BHLTHY_BASE,
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) scsb_hsc_board_healthy(pslotnum, healthy);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This function will try to read from scsb irrespective of whether
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SSB is present or SCB is frozen, to get the health kstat information.
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_blind_read(scsb_state_t *scsb, int op, uchar_t reg, int len,
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_rdwr_register(scsb,%s,%x,%x,buf):",
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2cxferp = scsb_alloc_i2ctx(scsb->scsb_phandle, I2C_NOSLEEP);
193974072f41a843678abf5f61979c748687e66bSherry Moore "i2ctx allocation failure");
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (op) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < len; ++i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel "scsb_rdwr_register: writing rwbuf[%d]=0x%x",
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* select the register address */
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_kstat_flag = B_TRUE; /* we did a i2c transaction */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error = nct_i2c_transfer(scsb->scsb_phandle, i2cxferp)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (rlen) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* copy to rwbuf[] */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < len; ++i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel "scsb_rdwr_register: read rwbuf[%d]=0x%x",
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This function will quiesce the PSM_INT line by masking the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * global PSM_INT and writing 1 to SCB_INIT ( for P1.5 and later )
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This effectively translates to writing 0x20 to 0xE1 register.
03831d35f7499c87d51205817c93e9a8d42c4baestevel register int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel * For P1.5, set the SCB_INIT bit in the System Command register,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and disable global PSM_INT. Before this we need to read the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * interrupt source register corresponding to INIT_SCB and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * clear if set.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Read INTSRC6 and write back 0x20 in case INIT_SCB is set
03831d35f7499c87d51205817c93e9a8d42c4baestevel offset = FRU_OFFSET(SCTRL_EVENT_SCB, SCTRL_INTPTR_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Now mask the global PSM_INT and write INIT_SCB in case
03831d35f7499c87d51205817c93e9a8d42c4baestevel * this is an INIT_SCB interrupt
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = SYS_REG_INDEX(SCTRL_SYS_SCB_INIT, SCTRL_SYS_CMD_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * There is an SCB_INIT interrupt, which we must clear
03831d35f7499c87d51205817c93e9a8d42c4baestevel * first to keep SCB_INIT from keeping PSM_INT asserted.
193974072f41a843678abf5f61979c748687e66bSherry Moore " failed to set SCB_INIT");
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else { /* P1.0 or earlier */
03831d35f7499c87d51205817c93e9a8d42c4baestevel * read the interrupt source registers, and then
03831d35f7499c87d51205817c93e9a8d42c4baestevel * write them back.
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* read the interrupt register from scsb */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error = scsb_rdwr_register(scsb, I2C_WR_RD, intr_addr,
193974072f41a843678abf5f61979c748687e66bSherry Moore " Failed read of interrupt registers.");
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Write to the interrupt source registers to stop scsb
03831d35f7499c87d51205817c93e9a8d42c4baestevel * from interrupting.
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error = scsb_rdwr_register(scsb, I2C_WR, intr_addr,
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "scsb_intr: Failed write to interrupt"
193974072f41a843678abf5f61979c748687e66bSherry Moore " registers.");
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Enables or disables the global PSM_INT interrupt for P1.5, depending
03831d35f7499c87d51205817c93e9a8d42c4baestevel * on the flag, flag = 0 => disable, else enable.
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = SYS_REG_INDEX(SCTRL_SYS_PSM_INT_ENABLE, SCTRL_SYS_CMD_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "scsb_toggle_psmint: Cannot turn %s PSM_INT",
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (enable == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This routine is to be used by all the drivers using this i2c bus
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to synchronize their transfer operations.
03831d35f7499c87d51205817c93e9a8d42c4baestevelnct_i2c_transfer(i2c_client_hdl_t i2c_hdl, i2c_transfer_t *i2c_tran)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If scsb interrupt mutex is initialized, also hold the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * interrupt mutex to let the i2c_transfer() to complete