03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * CDDL HEADER START
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
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 *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
03831d35f7499c87d51205817c93e9a8d42c4baestevel * or http://www.opensolaris.org/os/licensing.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * See the License for the specific language governing permissions
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and limitations under the License.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
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 *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * CDDL HEADER END
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Use is subject to license terms.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Netra ct800 and Netra ct400 (MonteCarlo/Tonga)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * System Controller and Status Boards STREAMS driver.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
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 *
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/types.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/param.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/cred.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/log.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/uio.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/stat.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/vnode.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/file.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/open.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/kmem.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/kstat.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/signal.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/stream.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/strsubr.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/strsun.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/poll.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/debug.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/conf.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/ddi.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sunddi.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/modctl.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/i2c/misc/i2c_svc.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/mct_topology.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/netract_gen.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/scsbioctl.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/scsb.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/scsb_cbi.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/hotplug/hpctrl.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/hsc.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/hscimpl.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define CPCI_HOTSWAP_SUPPORT
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define ALARM_CARD_ON_SLOT 1
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SCSB_FRU_OP_GET_REG 1
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SCSB_FRU_OP_SET_REGBIT 2
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SCSB_FRU_OP_GET_BITVAL 3
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SCSB_FRU_OP_GET_REGDATA 4
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * (internal only)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * scsb build version format is "CCYYMMDD"
03831d35f7499c87d51205817c93e9a8d42c4baestevel * for integer compares.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SCSB_BUILD_VERSION "20001206"
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define MUTEX_UNINIT 0
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define MUTEX_INIT 2
03831d35f7499c87d51205817c93e9a8d42c4baestevel
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 int nct_mutex_init = MUTEX_UNINIT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern int scsb_hsc_board_healthy();
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic char *scsb_name = SCSB_DEVICE_NAME;
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic char *scsb_clone_name = SCSB_DEVICE_NAME "clone";
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic char *scsb_build_version = SCSB_BUILD_VERSION;
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cb_ops section of scsb driver.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int sm_open(queue_t *, dev_t *, int, int, cred_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int sm_close(queue_t *, int, int, cred_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int sm_rput(queue_t *, mblk_t *); /* from i2c below */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int sm_wput(queue_t *, mblk_t *); /* from above */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baesteveluint_t scsb_intr_preprocess(caddr_t arg);
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid scsb_intr(caddr_t arg);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void smf_ioctl(queue_t *, mblk_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void sm_ioc_rdwr(queue_t *, mblk_t *, int);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
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 int initialize_scb(scsb_state_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic dev_info_t *scsb_dip; /* private copy of devinfo pointer */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct module_info info = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0, SCSB_DEVICE_NAME, 0, INFPSZ, 512, 128
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct qinit sm_rinit = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel sm_rput, NULL, sm_open, sm_close, NULL, &info
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct qinit sm_winit = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel sm_wput, NULL, sm_open, sm_close, NULL, &info
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstruct streamtab sm_st = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel &sm_rinit, &sm_winit, NULL, NULL
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct cb_ops scsb_cb_ops = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel nulldev, /* open */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nulldev, /* close */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodev, /* strategy */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodev, /* print */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodev, /* dump */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodev, /* read */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodev, /* write */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodev, /* ioctl */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodev, /* devmap */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodev, /* mmap */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodev, /* segmap */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nochpoll, /* poll */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_prop_op, /* cb_prop_op */
03831d35f7499c87d51205817c93e9a8d42c4baestevel &sm_st, /* streamtab */
03831d35f7499c87d51205817c93e9a8d42c4baestevel D_MP, /* Driver compatibility flag */
03831d35f7499c87d51205817c93e9a8d42c4baestevel CB_REV, /* rev */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodev, /* int (*cb_aread)() */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodev /* int (*cb_awrite)() */
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct dev_ops scsb_ops = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEVO_REV, /* devo_rev, */
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0, /* refcnt */
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_info, /* info */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nulldev, /* identify */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nulldev, /* probe */
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_attach, /* attach */
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_detach, /* detach */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodev, /* reset */
03831d35f7499c87d51205817c93e9a8d42c4baestevel &scsb_cb_ops, /* driver operations */
193974072f41a843678abf5f61979c748687e66bSherry Moore (struct bus_ops *)0, /* bus operations */
193974072f41a843678abf5f61979c748687e66bSherry Moore NULL, /* power */
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_quiesce_not_supported, /* devo_quiesce */
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Module linkage information for the kernel.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct modldrv modldrv = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel &mod_driverops, /* Type of module. This one is a pseudo driver */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel "SCB/SSB driver DBG" SCSB_BUILD_VERSION,
03831d35f7499c87d51205817c93e9a8d42c4baestevel#else
193974072f41a843678abf5f61979c748687e66bSherry Moore "v1.33 Netra ct System Control/Status Board driver",
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel &scsb_ops, /* driver ops */
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct modlinkage modlinkage = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel MODREV_1,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void *)&modldrv,
03831d35f7499c87d51205817c93e9a8d42c4baestevel NULL
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * local declarations and definitions
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#if defined(DEBUG)
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t scsb_debug = 0x00000000;
03831d35f7499c87d51205817c93e9a8d42c4baestevel#else
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic uint32_t scsb_debug = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic hrtime_t scb_pre_s, scb_pre_e, scb_post_s, scb_post_e;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int scsb_pil = SCSB_INTR_PIL;
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int hsc_pil = SCSB_INTR_PIL;
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void *scsb_state;
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic uint32_t scsb_global_state;
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic uint32_t scsb_event_code; /* for event polling */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct system_info mct_system_info;
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int scsb_healthy_poll_count = 16;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic fru_id_t fru_id_table[MCT_MAX_FRUS];
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic uchar_t scb_intr_regs[SCTRL_MAX_GROUP_NUMREGS];
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic uint32_t evc_fifo[EVC_FIFO_SIZE];
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic uint32_t evc_fifo_count = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic uint32_t *evc_rptr = evc_fifo;
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic uint32_t *evc_wptr = evc_fifo;
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void *evc_procs[EVC_PROCS_MAX];
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int evc_proc_count = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic timeout_id_t scsb_intr_tid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint nct_i2c_transfer(i2c_client_hdl_t i2c_hdl, i2c_transfer_t *i2c_tran);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * kstat functions
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int scsb_alloc_kstats(scsb_state_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void scsb_free_kstats(scsb_state_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int update_ks_leddata(kstat_t *, int);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int update_ks_state(kstat_t *, int);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int update_ks_topology(kstat_t *, int);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int update_ks_evcreg(kstat_t *, int);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * local functions
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
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 fru_info_t *find_fru_info(fru_id_t fru_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int scsb_fake_intr(scsb_state_t *, uint32_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int scsb_get_status(scsb_state_t *, scsb_status_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int scsb_leds_switch(scsb_state_t *, scsb_ustate_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void scsb_freeze(scsb_state_t *scsb);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void scsb_freeze_check(scsb_state_t *scsb);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void scsb_restore(scsb_state_t *scsb);
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 scsb_set_topology(scsb_state_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void scsb_free_topology(scsb_state_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelint scsb_read_bhealthy(scsb_state_t *scsb);
03831d35f7499c87d51205817c93e9a8d42c4baestevelint scsb_read_slot_health(scsb_state_t *, int);
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_clear_intptrs(scsb_state_t *scsb);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int scsb_clear_intmasks(scsb_state_t *scsb);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int scsb_setall_intmasks(scsb_state_t *scsb);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int scsb_write_mask(scsb_state_t *, uchar_t, uchar_t, uchar_t,
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int scsb_rdwr_register(scsb_state_t *, int, uchar_t, int,
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t *, int);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int scsb_readall_regs(scsb_state_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int scsb_get_led_regnum(scsb_state_t *, scsb_uinfo_t *, uchar_t *,
03831d35f7499c87d51205817c93e9a8d42c4baestevel int *, scsb_led_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void scsb_free_i2ctx(i2c_client_hdl_t, i2c_transfer_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void check_fru_info(scsb_state_t *, int);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void update_fru_info(scsb_state_t *, fru_info_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int event_to_index(uint32_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void add_event_code(scsb_state_t *, uint32_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic uint32_t del_event_code();
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic uint32_t get_event_code();
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int add_event_proc(scsb_state_t *, pid_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int del_event_proc(scsb_state_t *, pid_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void rew_event_proc(scsb_state_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int event_proc_count(scsb_state_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int find_evc_proc(pid_t pid);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void signal_evc_procs(scsb_state_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int check_event_procs();
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int scsb_is_alarm_card_slot(scsb_state_t *, int);
03831d35f7499c87d51205817c93e9a8d42c4baestevel int scsb_get_slot_state(scsb_state_t *, int, 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);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int scsb_toggle_psmint(scsb_state_t *, int);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int scsb_quiesce_psmint(scsb_state_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int scsb_invoke_intr_chain();
03831d35f7499c87d51205817c93e9a8d42c4baestevelint scsb_intr_register(int (*)(void *), void *, fru_id_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid scsb_intr_unregister(fru_id_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void mct_topology_dump(scsb_state_t *, int);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void scsb_failing_event(scsb_state_t *scsb);
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevel_init(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i, status;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0005)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb: _init()");
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) ddi_soft_state_init(&scsb_state, sizeof (scsb_state_t),
193974072f41a843678abf5f61979c748687e66bSherry Moore SCSB_NO_OF_BOARDS);
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) hsc_init();
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((status = mod_install(&modlinkage)) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0006)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb: _init(): mod_install failed");
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_soft_state_fini(&scsb_state);
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) hsc_fini();
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * initialize the FRU ID Table, using real FRU IDs where available
03831d35f7499c87d51205817c93e9a8d42c4baestevel * such as I2C Addresses for FRUs with I2C support
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < MCT_MAX_FRUS; ++i)
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_id_table[i] = i + 1;
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 return (status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevel_fini(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int status;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0005)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb: _fini()");
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((status = mod_remove(&modlinkage)) == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_soft_state_fini(&scsb_state);
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) hsc_fini();
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0006)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb: _fini, error %x\n", status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevel_info(struct modinfo *modinfop)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0005)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb: _info()");
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (mod_info(&modlinkage, modinfop));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int instance;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_state_t *scsb;
03831d35f7499c87d51205817c93e9a8d42c4baestevel register int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int *regs;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint_t len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t reg, wdata, rmask;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance = ddi_get_instance(dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0005)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_attach[%d]", instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cmd != DDI_ATTACH) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0006)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_attach[%d]: cmd 0x%x != DDI_ATTACH",
193974072f41a843678abf5f61979c748687e66bSherry Moore instance, cmd);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_soft_state_zalloc(scsb_state, instance) != DDI_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "scsb%d: cannot allocate soft state",
193974072f41a843678abf5f61979c748687e66bSherry Moore instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb = (scsb_state_t *)ddi_get_soft_state(scsb_state, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "scsb%d: cannot get soft state", instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_soft_state_free(scsb_state, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_instance = instance;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state = 0; /* just checking strange mutex behavior */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * make sure this is the SCB's known address
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
193974072f41a843678abf5f61979c748687e66bSherry Moore "reg", &regs, &len) != DDI_PROP_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb%d: Failed to get \"reg\" property", instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_soft_state_free(scsb_state, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_i2c_addr = regs[1] & SCSB_I2C_ADDR_MASK;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_i2c_addr != SCSB_I2C_ADDR) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "scsb%d: I2C Addr reg %x %x must be %x",
193974072f41a843678abf5f61979c748687e66bSherry Moore instance, regs[0], regs[1], SCSB_I2C_ADDR);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_soft_state_free(scsb_state, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_prop_free(regs);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* done with array lookup, free resource */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_prop_free(regs);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * initialize synchronization mutex and condition var.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * for this instance.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_init(&scsb->scsb_mutex, NULL, MUTEX_DRIVER, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state |= SCSB_UMUTEX;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_init(&scsb->scsb_cv, NULL, CV_DRIVER, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state |= SCSB_CONDVAR;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* 1 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_prop_exists(DDI_DEV_T_ANY, dip,
193974072f41a843678abf5f61979c748687e66bSherry Moore DDI_PROP_NOTPROM | DDI_PROP_DONTPASS,
193974072f41a843678abf5f61979c748687e66bSherry Moore "interrupt-priorities") != 1) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int tmp[2];
03831d35f7499c87d51205817c93e9a8d42c4baestevel tmp[0] = scsb_pil;
03831d35f7499c87d51205817c93e9a8d42c4baestevel tmp[1] = hsc_pil;
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) ddi_prop_update_int_array(DDI_DEV_T_NONE, dip,
193974072f41a843678abf5f61979c748687e66bSherry Moore "interrupt-priorities", tmp, 2);
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state |= SCSB_PROP_CREATE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((i = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
193974072f41a843678abf5f61979c748687e66bSherry Moore DDI_PROP_DONTPASS, "interrupts", -1)) >= 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state |= SCSB_P06_INTR_ON;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state |= SCSB_P06_NOINT_KLUGE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((i = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
193974072f41a843678abf5f61979c748687e66bSherry Moore DDI_PROP_DONTPASS, "device-err-threshold", -1)) >= 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_err_threshold = i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "?scsb_attach: Found device-err-threshold"
193974072f41a843678abf5f61979c748687e66bSherry Moore " property, value %d", scsb_err_threshold);
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_i2c_errcnt = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_err_flag = B_FALSE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_kstat_flag = B_FALSE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If all went well, create the minor node for user level access.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_create_minor_node(dip, scsb_name, S_IFCHR, instance,
193974072f41a843678abf5f61979c748687e66bSherry Moore "ddi_ctl:pcihpc", NULL) == DDI_FAILURE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "scsb_attach: Failed to create minor node");
03831d35f7499c87d51205817c93e9a8d42c4baestevel free_resources(dip, scsb, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state |= SCSB_MINOR_NODE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_dev = dip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_create_minor_node(dip, scsb_clone_name, S_IFCHR,
193974072f41a843678abf5f61979c748687e66bSherry Moore instance|SCSB_CLONE, "ddi_ctl:pcihpc", NULL)
193974072f41a843678abf5f61979c748687e66bSherry Moore == DDI_FAILURE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "scsb_attach: Failed to create clone node");
03831d35f7499c87d51205817c93e9a8d42c4baestevel free_resources(dip, scsb, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* CLONE */
03831d35f7499c87d51205817c93e9a8d42c4baestevel bzero(scsb->clone_devs, sizeof (clone_dev_t) * SCSB_CLONES_MAX);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* 2 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (i2c_client_register(dip, &scsb->scsb_phandle) != I2C_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_attach: Failed I2C Services registration");
03831d35f7499c87d51205817c93e9a8d42c4baestevel free_resources(dip, scsb, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state |= SCSB_I2C_PHANDLE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* 3 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((scsb->scsb_i2ctp = scsb_alloc_i2ctx(scsb->scsb_phandle,
193974072f41a843678abf5f61979c748687e66bSherry Moore I2C_SLEEP)) == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb%d: i2c_transfer allocation failed", instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel free_resources(dip, scsb, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state |= SCSB_I2C_TRANSFER;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Now it's time to INITIALIZE the boards.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* 1. through 7. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (initialize_scb(scsb) != DDI_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb_debug)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel free_resources(dip, scsb, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* 8. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Now Install interrupt handler
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_P06_INTR_ON) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_get_iblock_cookie(dip, instance,
193974072f41a843678abf5f61979c748687e66bSherry Moore &scsb->scsb_iblock) == DDI_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_init(&scsb->scsb_imutex, NULL, MUTEX_DRIVER,
193974072f41a843678abf5f61979c748687e66bSherry Moore (void *)scsb->scsb_iblock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state |= SCSB_IMUTEX;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_add_intr(dip, instance, &scsb->scsb_iblock,
193974072f41a843678abf5f61979c748687e66bSherry Moore NULL, scsb_intr_preprocess,
193974072f41a843678abf5f61979c748687e66bSherry Moore (caddr_t)scsb) != DDI_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_attach: failed interrupt "
193974072f41a843678abf5f61979c748687e66bSherry Moore "handler registration");
03831d35f7499c87d51205817c93e9a8d42c4baestevel free_resources(dip, scsb, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel scb_intr_mutex = &scsb->scsb_imutex;
03831d35f7499c87d51205817c93e9a8d42c4baestevel nct_mutex_init |= MUTEX_INIT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "scsb_attach: failed interrupt "
193974072f41a843678abf5f61979c748687e66bSherry Moore "mutex initialization");
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state |= SCSB_P06_NOINT_KLUGE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state &= ~SCSB_P06_INTR_ON;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel free_resources(dip, scsb, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* 9. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (i = scsb_clear_intmasks(scsb)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb%d: I2C TRANSFER Failed", instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!scsb_debug) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel free_resources(dip, scsb, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* 10. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * For P0.6 No Interrupt Support, don't enable PSM Interrupt
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state & SCSB_P06_NOINT_KLUGE)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel rmask = 0x00;
03831d35f7499c87d51205817c93e9a8d42c4baestevel wdata = 1 << SYS_OFFSET(SCTRL_SYS_PSM_INT_ENABLE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = SYS_REG_INDEX(SCTRL_SYS_PSM_INT_ENABLE,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCTRL_SYS_CMD_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = SCSB_REG_ADDR(i);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (i = scsb_write_mask(scsb, reg, rmask, wdata, (uchar_t)0)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb%d: I2C TRANSFER Failed", instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!scsb_debug) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel free_resources(dip, scsb, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state |= SCSB_PSM_INT_ENABLED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * For smctrl test utility,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * so all data is available in shadow registers
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * DEBUG_MODE enables private testing interfaces
03831d35f7499c87d51205817c93e9a8d42c4baestevel * DIAGS_MODE permits limited testing interfaces
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state |= SCSB_DEBUG_MODE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_readall_regs(scsb))
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_attach: scsb_readall FAILED");
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* 11. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Check if Alarm Card present at boot and set flags */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_fru_op(scsb, ALARM, 1, SCTRL_SYSCFG_BASE,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCSB_FRU_OP_GET_BITVAL))
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_hsc_state |= SCSB_ALARM_CARD_PRES;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* 12. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0004)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_attach: registering cPCI slots");
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_hsc_attach(dip, scsb, instance) != DDI_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x00008000) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "scsb: Hotswap controller initialisation"
193974072f41a843678abf5f61979c748687e66bSherry Moore " failed\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_hsc_state |= SCSB_HSC_INIT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* 13. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * allocate and install the kstat data structures
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_alloc_kstats(scsb) != DDI_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0006)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "scsb_attach: ERROR adding kstats");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* 14. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state |= SCSB_UP;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_global_state |= SCSB_UP;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_report_dev(scsb->scsb_dev);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "?%s%d: "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "Prom Version %s, Midplane Id %x\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_driver_name(scsb->scsb_dev),
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_instance,
193974072f41a843678abf5f61979c748687e66bSherry Moore (scsb->scsb_state & SCSB_P06_PROM) ? "0.6" :
193974072f41a843678abf5f61979c748687e66bSherry Moore (scsb->scsb_state & SCSB_P10_PROM) ? "1.0" :
193974072f41a843678abf5f61979c748687e66bSherry Moore (scsb->scsb_state & SCSB_P15_PROM) ? "1.5" :
193974072f41a843678abf5f61979c748687e66bSherry Moore (scsb->scsb_state & SCSB_P20_PROM) ? "2.0" : "Unknown",
193974072f41a843678abf5f61979c748687e66bSherry Moore mct_system_info.mid_plane.fru_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelscb_check_version(scsb_state_t *scsb)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int hotswap = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t data;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_UP) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If driver is UP, then this call is from scsb_intr()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * as part of Hot Insertion support.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel hotswap = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Read the SCB PROM ID */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_rdwr_register(scsb, I2C_WR_RD, (uchar_t)SCTRL_PROM_VERSION, 1,
193974072f41a843678abf5f61979c748687e66bSherry Moore &data, 1)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(hotswap && scsb->scsb_state & SCSB_FROZEN))
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "scsb%d: I2C TRANSFER Failed",
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0006) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "scsb_attach(%d): failed read of PROM ID",
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * compare with stored version number, and if different,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * report a warning and keep the driver FROZEN
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (hotswap) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (((mct_system_info.fru_info_list[SCB])[0].fru_version & 0xf)
193974072f41a843678abf5f61979c748687e66bSherry Moore == (data & 0xf)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x00020000) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "scb_check_version: SCB version %d "
193974072f41a843678abf5f61979c748687e66bSherry Moore "replacing version %d", data,
193974072f41a843678abf5f61979c748687e66bSherry Moore (mct_system_info.fru_info_list[SCB])[0].
193974072f41a843678abf5f61979c748687e66bSherry Moore fru_version & 0xf);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((data & 0xf) == SCTRL_PROM_P06) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state |= SCSB_P06_PROM;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if ((data & 0xf) == SCTRL_PROM_P10) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state |= SCSB_P10_PROM;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if ((data & 0xf) == SCTRL_PROM_P15) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state |= SCSB_P15_PROM;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if ((data & 0xf) == SCTRL_PROM_P20) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state |= SCSB_P20_PROM;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state & SCSB_SCB_PRESENT))
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state |= SCSB_SCB_PRESENT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (IS_SCB_P10) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scb_reg_index = scb_10_reg_index;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scb_numregs = scb_10_numregs;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scb_fru_offset = scb_10_fru_offset;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scb_sys_offset = scb_10_sys_offset;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else { /* if (IS_SCB_P15) */
03831d35f7499c87d51205817c93e9a8d42c4baestevel scb_reg_index = scb_15_reg_index;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scb_numregs = scb_15_numregs;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scb_fru_offset = scb_15_fru_offset;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scb_sys_offset = scb_15_sys_offset;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(IS_SCB_P15) && !(IS_SCB_P10)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "scsb%d: SCB Version %d not recognized",
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_instance, data);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (hotswap)
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state |= SCSB_FROZEN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb_debug)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * DEBUG: Assume SCB15
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state |= SCSB_P15_PROM;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SCB initialization steps to be called from scsb_attach()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * or from scsb_intr() calling scsb_restore() on Hot Insertion.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelinitialize_scb(scsb_state_t *scsb)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel register int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t reg, wdata, rmask;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If called from scsb_intr(), we've already done this
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state & SCSB_IN_INTR))
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scb_check_version(scsb) != DDI_SUCCESS)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 2. Set the SCB_INIT bit in the System Command register
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel rmask = 0x00; /* P1.0: 0x60; */
03831d35f7499c87d51205817c93e9a8d42c4baestevel wdata = 1 << SYS_OFFSET(SCTRL_SYS_SCB_INIT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = SYS_REG_INDEX(SCTRL_SYS_SCB_INIT, SCTRL_SYS_CMD_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = SCSB_REG_ADDR(i);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (i = scsb_write_mask(scsb, reg, rmask, wdata, 0)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb%d: I2C TRANSFER Failed", scsb->scsb_instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0006) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_attach: failed to set SCB_INIT");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* 3. For P1.0 and previous system, turn off all LEDs */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (IS_SCB_P10) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0004) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_attach(%d): turning LEDs off",
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (i = scsb_leds_switch(scsb, OFF)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "scsb%d: I2C TRANSFER Failed",
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* 4. Read the SYSCFG registers, update FRU info and SSB LEDs */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0004)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_attach(%d): reading config registers",
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((i = scsb_check_config_status(scsb)) == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state & SCSB_TOPOLOGY)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_set_topology(scsb);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0004)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_attach(%d): mpid = 0x%x",
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_instance,
193974072f41a843678abf5f61979c748687e66bSherry Moore mct_system_info.mid_plane.fru_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_info_t *fru_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * walk through FRUs and update FRU info
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < SCSB_UNIT_TYPES; ++i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr = mct_system_info.fru_info_list[i];
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (fru_ptr != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel update_fru_info(scsb, fru_ptr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr = fru_ptr->next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = scsb_set_scfg_pres_leds(scsb, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "scsb%d: I2C TRANSFER Failed",
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* 5. read the Board Healthy registers */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0004)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_attach(%d): reading Brd_Hlthy registers",
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = scsb_read_bhealthy(scsb);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "scsb%d: I2C TRANSFER Failed",
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* 6. Clear Interrupt Source registers */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Disable Global SCB Interrupts now
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel rmask = 0x00; /* P1.0: 0x60; */
03831d35f7499c87d51205817c93e9a8d42c4baestevel wdata = 1 << SYS_OFFSET(SCTRL_SYS_PSM_INT_ENABLE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = SYS_REG_INDEX(SCTRL_SYS_PSM_INT_ENABLE, SCTRL_SYS_CMD_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = SCSB_REG_ADDR(i);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (i = scsb_write_mask(scsb, reg, rmask, (uchar_t)0, wdata)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "scsb%d: Cannot turn off PSM_INT",
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Mask all interrupt sources */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (i = scsb_setall_intmasks(scsb)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "scsb%d: I2C TRANSFER Failed",
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Clear any latched interrupts */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (i = scsb_clear_intptrs(scsb)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "scsb%d: I2C TRANSFER Failed",
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* 7. set SCB EEPROM address: NOT USED */
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int instance;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_state_t *scsb;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t reg, wdata;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * TBD: make sure there are no outstanding operations on the system
03831d35f7499c87d51205817c93e9a8d42c4baestevel * monitor card before detaching.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance = ddi_get_instance(dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0005)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_detach[%d]", instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cmd != DDI_DETACH) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0006)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_detach(%d): command %x is not DDI_DETACH\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore instance, cmd);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb = (scsb_state_t *)ddi_get_soft_state(scsb_state, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state &= ~SCSB_UP;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_global_state &= ~SCSB_UP;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_hsc_state & SCSB_HSC_INIT) {
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) scsb_hsc_detach(dip, scsb, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_hsc_state &= ~SCSB_HSC_INIT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_PSM_INT_ENABLED) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Disable Global SCB Interrupts now
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel wdata = 1 << SYS_OFFSET(SCTRL_SYS_PSM_INT_ENABLE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = SYS_REG_INDEX(SCTRL_SYS_PSM_INT_ENABLE,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCTRL_SYS_CMD_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_write_mask(scsb, reg, (uchar_t)0, (uchar_t)0, wdata)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb%d: Cannot turn off PSM_INT", instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!scsb_debug) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) free_resources(dip, scsb, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Mask all interrupts */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_setall_intmasks(scsb)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb%d: I2C TRANSFER Failed", instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!scsb_debug) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) free_resources(dip, scsb, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Clear all latched interrupts */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_clear_intptrs(scsb)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb%d: I2C TRANSFER Failed", instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!scsb_debug) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) free_resources(dip, scsb, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_opens && scsb->scsb_rq != NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel qprocsoff(scsb->scsb_rq);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* CLONE */
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) scsb_queue_ops(scsb, QPROCSOFF, 0, NULL, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * free the allocated resources
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel free_resources(dip, scsb, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelfree_resources(dev_info_t *dip, scsb_state_t *scsb, int instance)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0005) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "free_resources[%d], scsb_state=0x%x",
193974072f41a843678abf5f61979c748687e66bSherry Moore instance, scsb->scsb_state);
03831d35f7499c87d51205817c93e9a8d42c4baestevel drv_usecwait(500000);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_P06_INTR_ON &&
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_state & SCSB_IMUTEX) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state &= ~SCSB_P06_INTR_ON;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_remove_intr(dip, 0, scsb->scsb_iblock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_KSTATS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_free_kstats(scsb);
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state &= ~SCSB_KSTATS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_TOPOLOGY) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_free_topology(scsb);
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state &= ~SCSB_TOPOLOGY;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel nct_mutex_init = MUTEX_UNINIT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_IMUTEX) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state &= ~SCSB_IMUTEX;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_destroy(&scsb->scsb_imutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_I2C_TRANSFER) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state &= ~SCSB_I2C_TRANSFER;
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2c_transfer_free(scsb->scsb_phandle, scsb->scsb_i2ctp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_I2C_PHANDLE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state &= ~SCSB_I2C_PHANDLE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2c_client_unregister(scsb->scsb_phandle);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_MINOR_NODE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state &= ~SCSB_MINOR_NODE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_remove_minor_node(dip, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_PROP_CREATE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state &= ~SCSB_PROP_CREATE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) ddi_prop_remove(DDI_DEV_T_NONE, dip,
193974072f41a843678abf5f61979c748687e66bSherry Moore "interrupt-priorities");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* ddi_prop_remove_all(dip); */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_CONDVAR) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state &= ~SCSB_CONDVAR;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_destroy(&scsb->scsb_cv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_UMUTEX) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state &= ~SCSB_UMUTEX;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_destroy(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_soft_state_free(scsb_state, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Just for testing scsb's poll function
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_fake_intr(scsb_state_t *scsb, uint32_t evcode)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (evcode == 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel evcode = scsb_event_code;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_event_code = evcode;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x4001) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_fake_intr: event = 0x%x, scsb_rq=0x%p",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki scsb_event_code, (void *)scsb->scsb_rq);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Allow access to shadow registers even though SCB is removed
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * if (scsb->scsb_state & SCSB_FROZEN) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * return (EAGAIN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * }
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x00040000) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel check_fru_info(scsb, evcode);
03831d35f7499c87d51205817c93e9a8d42c4baestevel add_event_code(scsb, evcode);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* just inform user-level via poll about this event */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_queue_ops(scsb, QPUT_INT32, 1, &evcode, "scsb_fake_intr")
193974072f41a843678abf5f61979c748687e66bSherry Moore == QOP_FAILED)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ENOMEM);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int retval = DDI_FAILURE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0001)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_info()");
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (infocmd) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DDI_INFO_DEVT2DEVINFO:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (getminor((dev_t)arg) == 0 && scsb_dip != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel *result = (void *) scsb_dip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel retval = DDI_SUCCESS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DDI_INFO_DEVT2INSTANCE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (getminor((dev_t)arg) == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel *result = (void *)0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel retval = DDI_SUCCESS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (retval);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SCSB STREAMS routines
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelsm_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *credp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int instance, clone;
03831d35f7499c87d51205817c93e9a8d42c4baestevel minor_t minor_dev;
03831d35f7499c87d51205817c93e9a8d42c4baestevel clone_dev_t *clptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_state_t *scsb;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel minor_dev = getminor(*devp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance = SCSB_GET_INSTANCE(minor_dev);
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb = ddi_get_soft_state(scsb_state, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ENXIO);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0009) {
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki cmn_err(CE_NOTE, "sm_open(%d) q=0x%p", instance, (void *)q);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state & SCSB_UP)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ENODEV);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * if (scsb->scsb_state & SCSB_FROZEN) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * return (EAGAIN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * }
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(credp != NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * XXX check for root access here, return EPERM if not root open
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sflag == MODOPEN) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* scsb module is being pushed */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0008)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "sm_open(%d): MODOPEN", instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * this is no longer supported
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ENXIO);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (sflag == CLONEOPEN) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* scsb is being opened as a clonable driver */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0008)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "sm_open(%d): CLONEOPEN", instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The cloned stream is not handled via the clone driver.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * See the minor device code below.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ENXIO);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (minor_dev & SCSB_CLONE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0008)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "sm_open(%d): SCSB_CLONE OPEN", instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((clone = scsb_queue_ops(scsb, QFIRST_AVAILABLE, 0, NULL,
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_open")) == QOP_FAILED) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ENXIO);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel clptr = &scsb->clone_devs[clone];
03831d35f7499c87d51205817c93e9a8d42c4baestevel clptr->cl_flags = SCSB_OPEN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel clptr->cl_rq = RD(q);
03831d35f7499c87d51205817c93e9a8d42c4baestevel clptr->cl_minor = SCSB_MAKE_MINOR(instance, clone);
03831d35f7499c87d51205817c93e9a8d42c4baestevel *devp = makedevice(getmajor(*devp), clptr->cl_minor);
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_clopens++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0008)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "sm_open(%d): new clone device minor: 0x%x"
193974072f41a843678abf5f61979c748687e66bSherry Moore " stream queue is 0x%p",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki instance, clptr->cl_minor, (void *)q);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* scsb is being opened as a regular driver */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0008)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "sm_open(%d): DEVOPEN", instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_EXCL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0008)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "sm_open(%d): can't open, state is EXCL",
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EBUSY);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (flag & FEXCL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0008)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "sm_open(%d): is EXCL",
193974072f41a843678abf5f61979c748687e66bSherry Moore instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_OPEN) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0008)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "sm_open(%d): cannot open EXCL",
193974072f41a843678abf5f61979c748687e66bSherry Moore instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EBUSY);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state |= SCSB_EXCL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_opens && scsb->scsb_rq != NULL &&
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_rq != RD(q)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x000a)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "sm_open[%d]: q (0x%p) != "
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_rq (0x%p)",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki instance, (void *)RD(q),
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void *)scsb->scsb_rq);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_rq = RD(q);
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_opens++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state |= SCSB_OPEN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel RD(q)->q_ptr = WR(q)->q_ptr = scsb;
03831d35f7499c87d51205817c93e9a8d42c4baestevel qprocson(q);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelsm_close(queue_t *q, int flag, int otyp, cred_t *credp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_state_t *scsb;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int clone;
03831d35f7499c87d51205817c93e9a8d42c4baestevel clone_dev_t *clptr = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb = (scsb_state_t *)q->q_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0009)
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki cmn_err(CE_NOTE, "sm_close[%d](0x%p)", scsb->scsb_instance,
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void *)q);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_clopens) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((clone = scsb_queue_ops(scsb, QFIND_QUEUE, 0,
193974072f41a843678abf5f61979c748687e66bSherry Moore (void *) RD(q), "scsb_close")) != QOP_FAILED) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel clptr = &scsb->clone_devs[clone];
03831d35f7499c87d51205817c93e9a8d42c4baestevel clptr->cl_flags = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel clptr->cl_rq = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_clopens--;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0008 && clone < SCSB_CLONES_MAX &&
193974072f41a843678abf5f61979c748687e66bSherry Moore clone >= SCSB_CLONES_FIRST)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "sm_close(%d): SCSB_CLONE 0x%x",
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_instance, clptr->cl_minor);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (clptr == NULL && scsb->scsb_opens) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0008)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "sm_close(%d): DEVOPEN, opens=%d",
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_instance, scsb->scsb_opens);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (RD(q) != scsb->scsb_rq) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0008)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "sm_close(%d): DEVOPEN, q != scsb_rq",
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_opens = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_EXCL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state &= ~SCSB_EXCL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_rq = (queue_t *)NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_opens == 0 && scsb->scsb_clopens == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state &= ~SCSB_OPEN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel RD(q)->q_ptr = WR(q)->q_ptr = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel qprocsoff(q);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelsm_rput(queue_t *q, mblk_t *mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0010)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "sm_rput");
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelsm_wput(queue_t *q, mblk_t *mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_state_t *scsb = (scsb_state_t *)WR(q)->q_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0010)
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki cmn_err(CE_NOTE, "sm_wput(%d): mp %p", scsb->scsb_instance,
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void *)mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (mp->b_datap->db_type) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel freemsg(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case M_FLUSH: /* canonical flush handling */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (*mp->b_rptr & FLUSHW) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel flushq(q, FLUSHDATA);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* free any messages tied to scsb */
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (*mp->b_rptr & FLUSHR) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel *mp->b_rptr &= ~FLUSHW;
03831d35f7499c87d51205817c93e9a8d42c4baestevel qreply(q, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else
03831d35f7499c87d51205817c93e9a8d42c4baestevel freemsg(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case M_IOCTL:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0010)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "sm_wput(%d): M_IOCTL",
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* do ioctl */
03831d35f7499c87d51205817c93e9a8d42c4baestevel smf_ioctl(q, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case M_DATA:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0010)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "sm_wput(%d): M_DATA",
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state & SCSB_UP)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel freemsg(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel freemsg(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case M_CTL:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0010)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "sm_wput(%d): M_CTL",
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel freemsg(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * These are the system monitor upper ioctl functions.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelsmf_ioctl(queue_t *q, mblk_t *mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_state_t *scsb = (scsb_state_t *)q->q_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct iocblk *iocp = (struct iocblk *)mp->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0020)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "smf_ioctl(%d): (%p)->cmd=%x",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki scsb->scsb_instance, (void *)mp, iocp->ioc_cmd);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state & SCSB_UP)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel miocnak(q, mp, 0, ENXIO);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 *
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 * return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel * }
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (iocp->ioc_cmd) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* if we don't understand the ioctl */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0022)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "smf_ioctl(%d):unkown ioctl %x",
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_instance, iocp->ioc_cmd);
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case ENVC_IOC_GETMODE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel {
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint8_t *curr_mode;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = miocpullup(mp, sizeof (uint8_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iocp->ioc_error != 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel curr_mode = (uint8_t *)mp->b_cont->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_DEBUG_MODE)
03831d35f7499c87d51205817c93e9a8d42c4baestevel *curr_mode = (uint8_t)ENVC_DEBUG_MODE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else if (scsb->scsb_state & SCSB_DIAGS_MODE)
03831d35f7499c87d51205817c93e9a8d42c4baestevel *curr_mode = (uint8_t)ENVCTRL_DIAG_MODE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel *curr_mode = (uint8_t)ENVCTRL_NORMAL_MODE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x20) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "IOC_GETMODE: returning mode 0x%x",
193974072f41a843678abf5f61979c748687e66bSherry Moore *curr_mode);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case ENVC_IOC_SETMODE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel {
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint8_t *curr_mode;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = miocpullup(mp, sizeof (uint8_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iocp->ioc_error != 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel curr_mode = (uint8_t *)mp->b_cont->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (*curr_mode) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case ENVCTRL_NORMAL_MODE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state &=
193974072f41a843678abf5f61979c748687e66bSherry Moore ~(SCSB_DEBUG_MODE | SCSB_DIAGS_MODE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case ENVCTRL_DIAG_MODE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state |= SCSB_DIAGS_MODE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state &= ~SCSB_DEBUG_MODE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case ENVC_DEBUG_MODE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state &
193974072f41a843678abf5f61979c748687e66bSherry Moore (SCSB_DIAGS_MODE | SCSB_DEBUG_MODE)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state &= ~SCSB_DIAGS_MODE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state |= SCSB_DEBUG_MODE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = EACCES;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x22) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "IOC_SETMODE: Invalid mode 0x%x",
03831d35f7499c87d51205817c93e9a8d42c4baestevel *curr_mode);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case ENVC_IOC_ACQUIRE_SLOT_LED_CTRL:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_APP_SLOTLED_CTRL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = EAGAIN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state |= SCSB_APP_SLOTLED_CTRL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case ENVC_IOC_RELEASE_SLOT_LED_CTRL:
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state &= ~SCSB_APP_SLOTLED_CTRL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Not an exposed interface, only used by development utilities.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCSBIOC_GET_VERSIONS:
03831d35f7499c87d51205817c93e9a8d42c4baestevel {
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint8_t *ppromid, promid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_ids_t *sids;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iocp->ioc_count == sizeof (uint8_t)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = miocpullup(mp, sizeof (uint8_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iocp->ioc_error != 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ppromid = (uint8_t *)mp->b_cont->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel *ppromid = (uint8_t)(mct_system_info.
193974072f41a843678abf5f61979c748687e66bSherry Moore fru_info_list[SCB])->fru_version;
03831d35f7499c87d51205817c93e9a8d42c4baestevel promid = *ppromid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = miocpullup(mp, sizeof (scsb_ids_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iocp->ioc_error != 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel sids = (scsb_ids_t *)mp->b_cont->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel bcopy(modldrv.drv_linkinfo, sids->modldrv_string,
03831d35f7499c87d51205817c93e9a8d42c4baestevel SCSB_MODSTR_LEN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel bcopy(scsb_build_version, sids->scsb_version,
03831d35f7499c87d51205817c93e9a8d42c4baestevel SCSB_VERSTR_LEN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sids->promid = (uint8_t)(mct_system_info.
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_info_list[SCB])->fru_version;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel promid = sids->promid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x20) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "IOC_GET_VERSIONS: sizeof(scsb_ids_t) "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "= %lu", sizeof (scsb_ids_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x20) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "IOC_GET_VERSIONS: SCB PROMID = 0x%x", promid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel case ENVC_IOC_REGISTER_PID:
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = miocpullup(mp, sizeof (pid_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iocp->ioc_error == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (add_event_proc(scsb, *(pid_t *)mp->b_cont->b_rptr))
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = ENOMEM;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case ENVC_IOC_UNREGISTER_PID:
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = miocpullup(mp, sizeof (pid_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iocp->ioc_error == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (del_event_proc(scsb, *(pid_t *)mp->b_cont->b_rptr))
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCSBIOC_VALUE_MODE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel {
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t *mode_vals;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int three_vals = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state & SCSB_DEBUG_MODE)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iocp->ioc_count == sizeof (uint32_t) * 3)
03831d35f7499c87d51205817c93e9a8d42c4baestevel three_vals = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else if (iocp->ioc_count != sizeof (uint32_t) * 2) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = miocpullup(mp, iocp->ioc_count);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iocp->ioc_error != 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * check mode_vals[0] for get/set option. setting
03831d35f7499c87d51205817c93e9a8d42c4baestevel * scsb_state is not valid for now. 0 == GET, 1 == SET
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mode_vals = (uint32_t *)mp->b_cont->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mode_vals[0]) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_debug = mode_vals[1];
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mode_vals[0] = scsb->scsb_state;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (three_vals) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mode_vals[1] = scsb->scsb_hsc_state;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mode_vals[2] = scsb_debug;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else
03831d35f7499c87d51205817c93e9a8d42c4baestevel mode_vals[1] = scsb_debug;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((scsb_debug & 0x20) && three_vals) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "IOC_VALUE_MODE: mode_vals: "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "0x%x/0x%x/0x%x; ioc_count = 0x%lx",
03831d35f7499c87d51205817c93e9a8d42c4baestevel mode_vals[0], mode_vals[1], mode_vals[2],
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_count);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCSBIOC_GET_SLOT_INFO:
03831d35f7499c87d51205817c93e9a8d42c4baestevel {
03831d35f7499c87d51205817c93e9a8d42c4baestevel hsc_slot_t *slot_info = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t *slot_vals;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int pslotnum;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state & SCSB_DEBUG_MODE)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = miocpullup(mp, sizeof (uint32_t) * 2);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iocp->ioc_error != 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot_vals = (uint32_t *)mp->b_cont->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pslotnum = (int)*slot_vals;
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki hsc_ac_op((int)scsb->scsb_instance, pslotnum,
03831d35f7499c87d51205817c93e9a8d42c4baestevel SCSB_HSC_AC_GET_SLOT_INFO, &slot_info);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (slot_info == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = ENODEV;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel *slot_vals = (uint32_t)slot_info->hs_flags;
03831d35f7499c87d51205817c93e9a8d42c4baestevel *(++slot_vals) = (uint32_t)slot_info->hs_slot_state;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x20) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "IOC_GET_SLOT_STATE: slot_vals: "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "0x%x/0x%x; ioc_count = 0x%lx",
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot_vals[0], slot_vals[1], iocp->ioc_count);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCSBIOC_GET_FAN_STATUS:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCSBIOC_GET_INTR_ARRAY:
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* for now we don't understand these ioctls */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0022)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "smf_ioctl(%d):unknown ioctl %x",
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_instance, iocp->ioc_cmd);
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCSBIOC_LED_OK_GET:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCSBIOC_LED_NOK_GET:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCSBIOC_LED_OK_SET:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCSBIOC_LED_NOK_SET:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCSBIOC_BHEALTHY_GET:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCSBIOC_SLOT_OCCUPANCY:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCSBIOC_RESET_UNIT:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state & (SCSB_DIAGS_MODE | SCSB_DEBUG_MODE))) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = EACCES;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*FALLTHROUGH*/
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case ENVC_IOC_GETDSKLED:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case ENVC_IOC_SETDSKLED:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case ENVC_IOC_SETFSP:
03831d35f7499c87d51205817c93e9a8d42c4baestevel {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_uinfo_t *suip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = miocpullup(mp, sizeof (scsb_uinfo_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iocp->ioc_error != 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel suip = (scsb_uinfo_t *)mp->b_cont->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (iocp->ioc_cmd) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCSBIOC_LED_OK_GET:
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = scsb_led_get(scsb, suip, OK);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCSBIOC_LED_NOK_GET:
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = scsb_led_get(scsb, suip, NOK);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCSBIOC_LED_OK_SET:
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = scsb_led_set(scsb, suip, OK);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCSBIOC_LED_NOK_SET:
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = scsb_led_set(scsb, suip, NOK);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCSBIOC_BHEALTHY_GET:
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = scsb_bhealthy_slot(scsb, suip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCSBIOC_SLOT_OCCUPANCY:
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = scsb_slot_occupancy(scsb, suip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCSBIOC_RESET_UNIT:
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = scsb_reset_unit(scsb, suip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case ENVC_IOC_GETDSKLED:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (suip->unit_type != DISK) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = scsb_led_get(scsb, suip, NOUSE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case ENVC_IOC_SETDSKLED:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (suip->unit_type != DISK) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = scsb_led_set(scsb, suip, NOUSE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case ENVC_IOC_SETFSP:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_FROZEN) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = EAGAIN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = scsb_led_set(scsb, suip, NOUSE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCSBIOC_FAKE_INTR: {
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t ui;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state & SCSB_DEBUG_MODE)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mp->b_cont == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel ui = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = miocpullup(mp, sizeof (uint32_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iocp->ioc_error != 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ui = *(uint32_t *)mp->b_cont->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = scsb_fake_intr(scsb, ui);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCSBIOC_GET_STATUS :
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state & SCSB_DEBUG_MODE)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = miocpullup(mp, sizeof (scsb_status_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iocp->ioc_error == 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = scsb_get_status(scsb,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (scsb_status_t *)mp->b_cont->b_rptr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCSBIOC_ALL_LEDS_ON :
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state & (SCSB_DIAGS_MODE | SCSB_DEBUG_MODE)))
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = EACCES;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = scsb_leds_switch(scsb, ON);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCSBIOC_ALL_LEDS_OFF :
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state & (SCSB_DIAGS_MODE | SCSB_DEBUG_MODE)))
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = EACCES;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = scsb_leds_switch(scsb, OFF);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCSBIOC_REG_READ:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCSBIOC_REG_WRITE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state & (SCSB_DIAGS_MODE | SCSB_DEBUG_MODE))) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = EACCES;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_ioc_rdwr_t *iocrdwrp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_FROZEN &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel !(scsb->scsb_state & SCSB_DEBUG_MODE)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = EAGAIN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = miocpullup(mp, sizeof (*iocrdwrp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iocp->ioc_error == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocrdwrp =
03831d35f7499c87d51205817c93e9a8d42c4baestevel (scsb_ioc_rdwr_t *)mp->b_cont->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iocp->ioc_cmd == SCSBIOC_REG_READ) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iocrdwrp->ioc_rlen > 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel sm_ioc_rdwr(q, mp, I2C_WR_RD);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iocrdwrp->ioc_wlen > 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel sm_ioc_rdwr(q, mp, I2C_WR);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCSBIOC_SHUTDOWN_POLL:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCSBIOC_INTEVENT_POLL:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state & SCSB_DEBUG_MODE)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = miocpullup(mp, sizeof (uint32_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iocp->ioc_error == 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = scsb_polled_int(scsb, iocp->ioc_cmd,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (uint32_t *)mp->b_cont->b_rptr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCSBIOC_RESTORE :
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state & (SCSB_DIAGS_MODE | SCSB_DEBUG_MODE)))
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = EACCES;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_restore(scsb);
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) scsb_toggle_psmint(scsb, 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCSBIOC_FREEZE :
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state & (SCSB_DIAGS_MODE | SCSB_DEBUG_MODE)))
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = EACCES;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_freeze_check(scsb);
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_freeze(scsb);
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * envmond:alarmcard.so response to SCTRL_EVENT_ALARM_INSERTION
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel case ENVC_IOC_ACCONF_RESTORED:
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) scsb_hsc_ac_op(scsb, scsb->ac_slotnum,
03831d35f7499c87d51205817c93e9a8d42c4baestevel SCSB_HSC_AC_SET_BUSY);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * envmond:alarmcard.so response to SCTRL_EVENT_ALARM_REMOVAL
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel case ENVC_IOC_ACCONF_STORED:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_FROZEN) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = EAGAIN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) scsb_hsc_ac_op(scsb, scsb->ac_slotnum,
03831d35f7499c87d51205817c93e9a8d42c4baestevel SCSB_HSC_AC_UNCONFIGURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCSBIOC_TOPOLOGY_DUMP:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state & SCSB_DEBUG_MODE))
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mct_topology_dump(scsb, 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iocp->ioc_error)
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->b_datap->db_type = M_IOCNAK;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->b_datap->db_type = M_IOCACK;
03831d35f7499c87d51205817c93e9a8d42c4baestevel qreply(q, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic fru_info_t *
03831d35f7499c87d51205817c93e9a8d42c4baestevelfind_fru_info(fru_id_t fru_id)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_info_t *fru_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x00100001)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "find_fru_info(0x%x)", fru_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (fru_id == (fru_id_t)0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return ((fru_info_t *)NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < SCSB_UNIT_TYPES; ++i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr = mct_system_info.fru_info_list[i];
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (fru_ptr != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (fru_ptr->fru_id == fru_id)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (fru_ptr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr = fru_ptr->next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return ((fru_info_t *)NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstruct scsb_cb_entry {
03831d35f7499c87d51205817c93e9a8d42c4baestevel void *cb_softstate_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_id_t cb_fru_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_fru_event_t cb_event;
03831d35f7499c87d51205817c93e9a8d42c4baestevel void (*cb_func)
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void *, scsb_fru_event_t, scsb_fru_status_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_info_t *cb_fru_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct scsb_cb_entry *cb_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevelint scsb_cb_count = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel#else
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevelstruct scsb_cb_entry *scsb_cb_table;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * global function for interested FRU drivers to register a callback function,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to be called when FRU presence status changes.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_fru_status_t
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_fru_register(void (*cb_func)(void *, scsb_fru_event_t, scsb_fru_status_t),
03831d35f7499c87d51205817c93e9a8d42c4baestevel void *soft_ptr, fru_id_t fru_id)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct scsb_cb_entry *cbe_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x00800001) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_fru_register: FRU_ID 0x%x", (int)fru_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb_global_state & SCSB_UP)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (FRU_NOT_AVAILABLE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cb_func == NULL || fru_id == (fru_id_t)0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (FRU_NOT_AVAILABLE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_cb_table == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_cb_table = (struct scsb_cb_entry *)
193974072f41a843678abf5f61979c748687e66bSherry Moore kmem_zalloc(sizeof (struct scsb_cb_entry), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cbe_ptr = scsb_cb_table;
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (cbe_ptr->cb_softstate_ptr != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cbe_ptr->cb_next == (struct scsb_cb_entry *)NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cbe_ptr->cb_next = (struct scsb_cb_entry *)
193974072f41a843678abf5f61979c748687e66bSherry Moore kmem_zalloc(sizeof (struct scsb_cb_entry),
193974072f41a843678abf5f61979c748687e66bSherry Moore KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cbe_ptr = cbe_ptr->cb_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel cbe_ptr = cbe_ptr->cb_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel cbe_ptr->cb_softstate_ptr = soft_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cbe_ptr->cb_fru_id = fru_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cbe_ptr->cb_func = cb_func;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cbe_ptr->cb_next = (struct scsb_cb_entry *)NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cbe_ptr->cb_fru_ptr = find_fru_info(fru_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_cb_count++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x00800000) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_fru_register: FRU_ID 0x%x, status=%d",
193974072f41a843678abf5f61979c748687e66bSherry Moore (int)fru_id,
193974072f41a843678abf5f61979c748687e66bSherry Moore (cbe_ptr->cb_fru_ptr == (fru_info_t *)NULL) ?
193974072f41a843678abf5f61979c748687e66bSherry Moore 0xff : cbe_ptr->cb_fru_ptr->fru_status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cbe_ptr->cb_fru_ptr == (fru_info_t *)NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (FRU_NOT_AVAILABLE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cbe_ptr->cb_fru_ptr->fru_status & FRU_PRESENT)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (FRU_PRESENT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (FRU_NOT_PRESENT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_fru_unregister(void *soft_ptr, fru_id_t fru_id)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct scsb_cb_entry *prev_ptr, *cbe_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x00800001) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_fru_unregister(0x%p, 0x%x)",
193974072f41a843678abf5f61979c748687e66bSherry Moore soft_ptr, (int)fru_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((cbe_ptr = scsb_cb_table) == NULL || fru_id == (fru_id_t)0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel prev_ptr = cbe_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel do {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cbe_ptr->cb_softstate_ptr == soft_ptr &&
193974072f41a843678abf5f61979c748687e66bSherry Moore cbe_ptr->cb_fru_id == fru_id) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cbe_ptr == scsb_cb_table)
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_cb_table = cbe_ptr->cb_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel prev_ptr->cb_next = cbe_ptr->cb_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(cbe_ptr, sizeof (struct scsb_cb_entry));
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_cb_count--;
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel prev_ptr = cbe_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } while ((cbe_ptr = cbe_ptr->cb_next) != NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * global function for interested FRU drivers to call to check
03831d35f7499c87d51205817c93e9a8d42c4baestevel * FRU presence status.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_fru_status_t
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_fru_status(uchar_t fru_id)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_info_t *fru_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr = find_fru_info(fru_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x00800001) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_fru_status(0x%x): status=0x%x",
193974072f41a843678abf5f61979c748687e66bSherry Moore fru_id, (fru_ptr == (fru_info_t *)NULL) ? 0xff :
193974072f41a843678abf5f61979c748687e66bSherry Moore (int)fru_ptr->fru_status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (fru_ptr == (fru_info_t *)NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (FRU_NOT_AVAILABLE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (fru_ptr->fru_status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstruct fru_intr_entry {
03831d35f7499c87d51205817c93e9a8d42c4baestevel void *softstate_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int (*fru_intr_handler)(void *);
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_id_t fru_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct fru_intr_entry *fru_intr_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel} *fru_intr_table = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_intr_register(int (*intr_handler)(void *), void * soft_ptr,
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_id_t fru_id)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct fru_intr_entry *intr_table_entry;
03831d35f7499c87d51205817c93e9a8d42c4baestevel intr_table_entry = (struct fru_intr_entry *)
193974072f41a843678abf5f61979c748687e66bSherry Moore kmem_zalloc(sizeof (struct fru_intr_entry), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (intr_table_entry == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (intr_handler == NULL || soft_ptr == NULL || fru_id == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(intr_table_entry, sizeof (struct fru_intr_entry));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel intr_table_entry->softstate_ptr = soft_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel intr_table_entry->fru_intr_handler = intr_handler;
03831d35f7499c87d51205817c93e9a8d42c4baestevel intr_table_entry->fru_id = fru_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel intr_table_entry->fru_intr_next = fru_intr_table;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_intr_table = intr_table_entry;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Removed interrupt_handler of fru from interrupt call chain
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_intr_unregister(fru_id_t fru_id)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct fru_intr_entry *intr_entry = fru_intr_table,
193974072f41a843678abf5f61979c748687e66bSherry Moore *prev_entry = intr_entry;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (fru_id == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel do {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (intr_entry->fru_id == fru_id) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* found a match, remove entry */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (intr_entry == fru_intr_table)
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_intr_table = intr_entry->fru_intr_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel prev_entry->fru_intr_next =
193974072f41a843678abf5f61979c748687e66bSherry Moore intr_entry->fru_intr_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(intr_entry,
193974072f41a843678abf5f61979c748687e66bSherry Moore sizeof (struct fru_intr_entry));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel prev_entry = intr_entry;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel } while ((intr_entry = intr_entry->fru_intr_next) != NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_invoke_intr_chain()
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int retval = DDI_INTR_UNCLAIMED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct fru_intr_entry *intr_entry = fru_intr_table;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (intr_entry != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel retval = (*intr_entry->
193974072f41a843678abf5f61979c748687e66bSherry Moore fru_intr_handler)(intr_entry->softstate_ptr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (retval == DDI_INTR_CLAIMED) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (retval);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel intr_entry = intr_entry->fru_intr_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (retval);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelsm_ioc_rdwr(queue_t *q, mblk_t *mp, int op)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_state_t *scsb = (scsb_state_t *)q->q_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct iocblk *iocp = (struct iocblk *)mp->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_ioc_rdwr_t *iocrdwrp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int len, error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t *uc, reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0040)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "sm_ioc_rdwr[%d]:", scsb->scsb_instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocrdwrp = (scsb_ioc_rdwr_t *)mp->b_cont->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (op == I2C_WR) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel len = iocrdwrp->ioc_wlen;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uc = iocrdwrp->ioc_wbuf;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel len = iocrdwrp->ioc_rlen;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uc = iocrdwrp->ioc_rbuf;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check SCB register index boundries and requested len of read/write
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = iocrdwrp->ioc_regindex;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (reg < SCSB_REG_ADDR_START || (reg + len) >
193974072f41a843678abf5f61979c748687e66bSherry Moore (SCSB_REG_ADDR_START + SCTRL_TOTAL_NUMREGS))
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = scsb_rdwr_register(scsb, op, reg, len, uc, 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0042)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "sm_ioc_rdwr: rdwr_register failure: %d", error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->b_datap->db_type = M_IOCNAK;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->b_datap->db_type = M_IOCACK;
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp->ioc_error = error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel qreply(q, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * names for (scsb_utype_t) FRU types
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic char *led_name[SCSB_LED_TYPES] = { "NOK", "OK" };
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic char *unit_type_name[SCSB_UNIT_TYPES] = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel "SLOT", "PDU", "POWER SUPPLY", "DISK", "FAN", "ALARM",
03831d35f7499c87d51205817c93e9a8d42c4baestevel "SCB", "SSB", "CFTM", "CRTM", "PRTM"
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Discover the register and bit-offset for LEDs and Reset registers,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * according to unit_type, unit_number, and led_type.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_get_led_regnum(scsb_state_t *scsb,
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_uinfo_t *suip,
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t *regptr,
03831d35f7499c87d51205817c93e9a8d42c4baestevel int *unitptr,
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_led_t led_type)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int code, base, error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* OK here means presence (OK) LEDs */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (led_type == OK)
03831d35f7499c87d51205817c93e9a8d42c4baestevel base = (SCTRL_LED_OK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel base = (SCTRL_LED_NOK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0100) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "get_led_regnum: suip <%x, %x, %x, %x>\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore suip->unit_type, suip->unit_number,
193974072f41a843678abf5f61979c748687e66bSherry Moore led_type, suip->unit_state);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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
03831d35f7499c87d51205817c93e9a8d42c4baestevel * enabled.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (suip->unit_type) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SLOT:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (suip->unit_number < 1 || suip->unit_number >
193974072f41a843678abf5f61979c748687e66bSherry Moore ((scsb->scsb_state & SCSB_IS_TONGA) ?
193974072f41a843678abf5f61979c748687e66bSherry Moore TG_MAX_SLOTS : MC_MAX_SLOTS)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel code = FRU_UNIT_TO_EVCODE(SLOT, suip->unit_number);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case PDU:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (suip->unit_number < 1 || suip->unit_number >
193974072f41a843678abf5f61979c748687e66bSherry Moore ((scsb->scsb_state & SCSB_IS_TONGA) ?
193974072f41a843678abf5f61979c748687e66bSherry Moore TG_MAX_PDU : MC_MAX_PDU)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0002) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "get_led_regnum: unit number %d "
193974072f41a843678abf5f61979c748687e66bSherry Moore "is out of range", suip->unit_number);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel code = FRU_UNIT_TO_EVCODE(PDU, suip->unit_number);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case PS:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((suip->unit_number < 1 || suip->unit_number >
193974072f41a843678abf5f61979c748687e66bSherry Moore ((scsb->scsb_state & SCSB_IS_TONGA) ?
193974072f41a843678abf5f61979c748687e66bSherry Moore TG_MAX_PS : MC_MAX_PS))) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0002) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "get_led_regnum: unit number %d "
193974072f41a843678abf5f61979c748687e66bSherry Moore "is out of range", suip->unit_number);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel code = FRU_UNIT_TO_EVCODE(PS, suip->unit_number);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DISK:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((suip->unit_number < 1 || suip->unit_number >
193974072f41a843678abf5f61979c748687e66bSherry Moore ((scsb->scsb_state & SCSB_IS_TONGA) ?
193974072f41a843678abf5f61979c748687e66bSherry Moore TG_MAX_DISK : MC_MAX_DISK))) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0002) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "get_led_regnum: unit number %d "
193974072f41a843678abf5f61979c748687e66bSherry Moore "is out of range", suip->unit_number);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb_debug & 0x20000000)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel code = FRU_UNIT_TO_EVCODE(DISK, suip->unit_number);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case FAN:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (suip->unit_number < 1 || suip->unit_number >
193974072f41a843678abf5f61979c748687e66bSherry Moore ((scsb->scsb_state & SCSB_IS_TONGA) ?
193974072f41a843678abf5f61979c748687e66bSherry Moore TG_MAX_FAN : MC_MAX_FAN)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0002) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "get_led_regnum: unit number %d "
193974072f41a843678abf5f61979c748687e66bSherry Moore "is out of range", suip->unit_number);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel code = FRU_UNIT_TO_EVCODE(FAN, suip->unit_number);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case CFTM:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (suip->unit_number < 1 || suip->unit_number >
193974072f41a843678abf5f61979c748687e66bSherry Moore ((scsb->scsb_state & SCSB_IS_TONGA) ?
193974072f41a843678abf5f61979c748687e66bSherry Moore TG_MAX_CFTM : MC_MAX_CFTM)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0002) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "get_led_regnum: unit number %d "
193974072f41a843678abf5f61979c748687e66bSherry Moore "is out of range", suip->unit_number);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel code = FRU_UNIT_TO_EVCODE(CFTM, suip->unit_number);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCB:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (suip->unit_number < 1 || suip->unit_number >
193974072f41a843678abf5f61979c748687e66bSherry Moore ((scsb->scsb_state & SCSB_IS_TONGA) ?
193974072f41a843678abf5f61979c748687e66bSherry Moore TG_MAX_SCB : MC_MAX_SCB)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0002) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "get_led_regnum: unit number %d "
193974072f41a843678abf5f61979c748687e66bSherry Moore "is out of range", suip->unit_number);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel code = FRU_UNIT_TO_EVCODE(SCB, suip->unit_number);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case ALARM:
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0102) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_get_led_regnum(): unknown unit type %d",
193974072f41a843678abf5f61979c748687e66bSherry Moore suip->unit_type);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!error) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel *unitptr = FRU_OFFSET(code, base);
03831d35f7499c87d51205817c93e9a8d42c4baestevel *regptr = FRU_REG_ADDR(code, base);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0100) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "get_led_regnum: unitptr=%x, "
193974072f41a843678abf5f61979c748687e66bSherry Moore "regptr=%x, code = %x\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore *unitptr, *regptr, code);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* HSC slotnum (Positional SLotnum) to SCB CFG bit-offset */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int psl2sco[TG_MAX_SLOTS + 1] = { -1 };
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * MAP Positional (HSC) slot number to SCB CFG register bit-offset
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveltonga_pslotnum_to_cfgbit(scsb_state_t *scsb, int sln)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int base = SCTRL_SYSCFG_BASE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state & SCSB_IS_TONGA)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (sln);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sln < 1 || sln > TG_MAX_SLOTS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (sln);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Should move this to _init(), but for now,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * check for initialized table
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (psl2sco[0]) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel psl2sco[0] = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel psl2sco[1] = FRU_OFFSET(SCTRL_EVENT_SLOT5, base);
03831d35f7499c87d51205817c93e9a8d42c4baestevel psl2sco[2] = FRU_OFFSET(SCTRL_EVENT_SLOT2, base);
03831d35f7499c87d51205817c93e9a8d42c4baestevel psl2sco[3] = FRU_OFFSET(SCTRL_EVENT_SLOT1, base);
03831d35f7499c87d51205817c93e9a8d42c4baestevel psl2sco[4] = FRU_OFFSET(SCTRL_EVENT_SLOT3, base);
03831d35f7499c87d51205817c93e9a8d42c4baestevel psl2sco[5] = FRU_OFFSET(SCTRL_EVENT_SLOT4, base);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x10000000) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "tonga_pslotnum_to_cfgbit: old/new: %d/%d",
193974072f41a843678abf5f61979c748687e66bSherry Moore sln, psl2sco[sln]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (psl2sco[sln]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* positional slotnum to SCB slotnum */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int psl2ssl[6] = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0, 5, 2, 1, 3, 4
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* SCB slotnum to positional slotnum */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int ssl2psl[6] = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0, 3, 2, 4, 5, 1
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * P1.0 and P1.5
03831d35f7499c87d51205817c93e9a8d42c4baestevel * HSC Slot numbers (physical positions or positional slotnum)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SCB slot numbers (reset,present,healthy)
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * These requests come mainly from application interface and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * HSC using the scsb_uinfo_t structure.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveltonga_slotnum_check(scsb_state_t *scsb, scsb_uinfo_t *suip)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state & SCSB_IS_TONGA && scsb->scsb_state &
193974072f41a843678abf5f61979c748687e66bSherry Moore (SCSB_P10_PROM | SCSB_P15_PROM | SCSB_P20_PROM))) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (suip->unit_number < 1 || suip->unit_number > TG_MAX_SLOTS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x10000000) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "tonga_slotnum_check: old/new: %d/%d",
193974072f41a843678abf5f61979c748687e66bSherry Moore suip->unit_number, psl2ssl[suip->unit_number]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel suip->unit_number = psl2ssl[suip->unit_number];
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * P1.0 and P1.5
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveltonga_psl_to_ssl(scsb_state_t *scsb, int slotnum)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state & SCSB_IS_TONGA && scsb->scsb_state &
193974072f41a843678abf5f61979c748687e66bSherry Moore (SCSB_P10_PROM | SCSB_P15_PROM | SCSB_P20_PROM))) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (slotnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (slotnum < 1 || slotnum > TG_MAX_SLOTS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (slotnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x10000000) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "tonga_psl_to_ssl: old/new: %d/%d",
193974072f41a843678abf5f61979c748687e66bSherry Moore slotnum, psl2ssl[slotnum]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (psl2ssl[slotnum]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * P1.0 and P1.5
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveltonga_ssl_to_psl(scsb_state_t *scsb, int slotnum)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state & SCSB_IS_TONGA && scsb->scsb_state &
193974072f41a843678abf5f61979c748687e66bSherry Moore (SCSB_P10_PROM | SCSB_P15_PROM | SCSB_P20_PROM))) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (slotnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (slotnum < 1 || slotnum > TG_MAX_SLOTS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (slotnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x10000000) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "tonga_ssl_to_psl: old/new: %d/%d",
193974072f41a843678abf5f61979c748687e66bSherry Moore slotnum, ssl2psl[slotnum]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ssl2psl[slotnum]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * IN bits: SCB slot numbers (led,reset,present,healthy)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * OUT bits: HSC Slot numbers (positional slot numbers as marked on the SSB)
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic uchar_t
03831d35f7499c87d51205817c93e9a8d42c4baesteveltonga_slotnum_led_shift(scsb_state_t *scsb, uchar_t data)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t mask, new_data = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t old_data = data;
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state & SCSB_IS_TONGA)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (data);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * P1.0 and P1.5 slot 1-5 offsets are the same
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 1; i <= TG_MAX_SLOTS; ++i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mask = 1 << (i - 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case 1: /* map to slot 3 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel new_data |= (data & mask) << 2;
03831d35f7499c87d51205817c93e9a8d42c4baestevel data &= ~(mask);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case 2: /* map to slot 2 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel new_data |= (data & mask);
03831d35f7499c87d51205817c93e9a8d42c4baestevel data &= ~(mask);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case 3: /* map to slot 4 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel case 4: /* map to slot 5 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel new_data |= (data & mask) << 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel data &= ~(mask);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case 5: /* map to slot 1 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel new_data |= (data & mask) >> 4;
03831d35f7499c87d51205817c93e9a8d42c4baestevel data &= ~(mask);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel new_data |= data; /* set any remaining bits */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x10000000) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "tonga_slotnum_led_shift: old/new: 0x%x/0x%x",
193974072f41a843678abf5f61979c748687e66bSherry Moore old_data, new_data);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (new_data);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * P1.0 and P1.5
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_led_get(scsb_state_t *scsb, scsb_uinfo_t *suip, scsb_led_t led_type)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int unit_number;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int index;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Allow access to shadow registers even though SCB is removed
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * if (scsb->scsb_state & SCSB_FROZEN) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * return (EAGAIN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * }
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (suip == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EFAULT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (led_type == NOUSE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel led_type = suip->led_type;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (led_type != OK && led_type != NOK) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_led_get(%d): unknown led type %x",
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_instance, led_type);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EINVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0100) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_led_get: %s %s %d",
193974072f41a843678abf5f61979c748687e66bSherry Moore led_name[led_type], unit_type_name[suip->unit_type],
193974072f41a843678abf5f61979c748687e66bSherry Moore suip->unit_number);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Map to Tonga Slot Number, if NOT P1.0 SCB
03831d35f7499c87d51205817c93e9a8d42c4baestevel * P1.0 SSB workaround
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (suip->unit_type == SLOT && !(scsb->scsb_state & SCSB_P10_PROM)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel tonga_slotnum_check(scsb, suip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* discover the register and index we need to operate on */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((error = scsb_get_led_regnum(scsb, suip, &reg, &unit_number,
193974072f41a843678abf5f61979c748687e66bSherry Moore led_type)) == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel index = SCSB_REG_INDEX(reg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_data_reg[index] & (1 << unit_number)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel suip->unit_state = ON;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (led_type == OK) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int code = FRU_UNIT_TO_EVCODE(suip->unit_type,
193974072f41a843678abf5f61979c748687e66bSherry Moore suip->unit_number);
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = FRU_REG_ADDR(code, SCTRL_BLINK_OK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel index = SCSB_REG_INDEX(reg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_data_reg[index] &
193974072f41a843678abf5f61979c748687e66bSherry Moore (1 << unit_number))
03831d35f7499c87d51205817c93e9a8d42c4baestevel suip->unit_state = BLINK;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel suip->unit_state = OFF;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_led_set(scsb_state_t *scsb, scsb_uinfo_t *suip, scsb_led_t led_type)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int unit_number;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int code, index;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* we should really allow led state changes while frozen... */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_FROZEN)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EAGAIN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (suip == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EFAULT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (led_type == NOUSE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel led_type = suip->led_type;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (suip->unit_type == SLOT &&
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_state & SCSB_APP_SLOTLED_CTRL &&
193974072f41a843678abf5f61979c748687e66bSherry Moore !(scsb->scsb_state &
193974072f41a843678abf5f61979c748687e66bSherry Moore (SCSB_DIAGS_MODE | SCSB_DEBUG_MODE))) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (led_type != OK && led_type != NOK) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EINVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (suip->unit_state != OFF && suip->unit_state != ON &&
193974072f41a843678abf5f61979c748687e66bSherry Moore suip->unit_state != BLINK) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EINVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (suip->unit_state == BLINK) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (led_type != OK)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EINVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (suip->unit_type != SLOT && scsb->scsb_state &
193974072f41a843678abf5f61979c748687e66bSherry Moore (SCSB_P06_PROM | SCSB_P10_PROM))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EINVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0100) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_led_set: led %s, type %s, unit %d, state %s",
193974072f41a843678abf5f61979c748687e66bSherry Moore led_name[led_type],
193974072f41a843678abf5f61979c748687e66bSherry Moore unit_type_name[suip->unit_type], suip->unit_number,
193974072f41a843678abf5f61979c748687e66bSherry Moore suip->unit_state == ON ? "ON":
193974072f41a843678abf5f61979c748687e66bSherry Moore suip->unit_state == OFF ? "OFF": "BLINK");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Map to Tonga Slot Number, if NOT P1.0 SCB
03831d35f7499c87d51205817c93e9a8d42c4baestevel * P1.0 SSB workaround
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (suip->unit_type == SLOT && !(scsb->scsb_state & SCSB_P10_PROM)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel tonga_slotnum_check(scsb, suip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * discover the register and index we need to access
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((error = scsb_get_led_regnum(scsb, suip, &reg, &unit_number,
193974072f41a843678abf5f61979c748687e66bSherry Moore led_type)) == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel index = SCSB_REG_INDEX(reg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (suip->unit_state == ON || suip->unit_state == BLINK)
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_data_reg[index] |= (1 << unit_number);
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_data_reg[index] &= ~(1 << unit_number);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0100) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "Writing %x to Reg %x",
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_data_reg[index], reg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = scsb_rdwr_register(scsb, I2C_WR, reg, 1,
193974072f41a843678abf5f61979c748687e66bSherry Moore &scsb->scsb_data_reg[index], 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "%s#%d: Could not Update %s LEDs.",
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_driver_name(scsb->scsb_dev),
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_get_instance(scsb->scsb_dev),
193974072f41a843678abf5f61979c748687e66bSherry Moore led_name[led_type]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto ledset_done;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (led_type != OK ||
193974072f41a843678abf5f61979c748687e66bSherry Moore (IS_SCB_P10 && suip->unit_type != SLOT) ||
193974072f41a843678abf5f61979c748687e66bSherry Moore suip->unit_type == ALARM ||
193974072f41a843678abf5f61979c748687e66bSherry Moore suip->unit_type == SSB ||
193974072f41a843678abf5f61979c748687e66bSherry Moore suip->unit_type == CRTM ||
193974072f41a843678abf5f61979c748687e66bSherry Moore suip->unit_type == PRTM) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto ledset_done;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel code = FRU_UNIT_TO_EVCODE(suip->unit_type, suip->unit_number);
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = FRU_REG_ADDR(code, SCTRL_BLINK_OK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel index = SCSB_REG_INDEX(reg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (suip->unit_state == BLINK)
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_data_reg[index] |= (1 << unit_number);
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_data_reg[index] &= ~(1 << unit_number);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0100) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "Writing %x to Reg %x",
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_data_reg[index], reg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = scsb_rdwr_register(scsb, I2C_WR, reg, 1,
193974072f41a843678abf5f61979c748687e66bSherry Moore &scsb->scsb_data_reg[index], 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "%s#%d: Could not Blink %s LEDs.",
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_driver_name(scsb->scsb_dev),
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_get_instance(scsb->scsb_dev),
193974072f41a843678abf5f61979c748687e66bSherry Moore led_name[led_type]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevelledset_done:
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstruct ps_auto_on {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_state_t *scsb;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_utype_t utype;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_unum_t unit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct ps_auto_on pao;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_ps_auto_on(void *arg)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct ps_auto_on *ppao = (struct ps_auto_on *)arg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t rmask = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t ondata, sysreg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int tmp, bit_index;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Turn on the PSU.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Notice: not checking Power Supply unit number
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel bit_index = SCTRL_SYS_PS_ON_BASE + (ppao->unit - 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ondata = 1 << SYS_OFFSET(bit_index);
03831d35f7499c87d51205817c93e9a8d42c4baestevel tmp = SYS_REG_INDEX(bit_index, SCTRL_SYS_CMD_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sysreg = SCSB_REG_ADDR(tmp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_write_mask(ppao->scsb, sysreg, rmask, ondata, (uchar_t)0)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "scsb%d: " "I2C TRANSFER Failed",
193974072f41a843678abf5f61979c748687e66bSherry Moore ppao->scsb->scsb_instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel ppao->scsb->scsb_btid = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_set_scfg_pres_leds(scsb_state_t *scsb, fru_info_t *int_fru_ptr)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i, error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int cfg_idx, led_idx, blink_idx, lid, bid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int cfg_bit, led_bit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t *puc, reg, led_reg, led_data[SCSB_LEDDATA_REGISTERS];
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t blink_bit, blink_reg, blink[SCSB_LEDDATA_REGISTERS];
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t update_reg = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_utype_t fru_type;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_info_t *fru_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_FROZEN &&
193974072f41a843678abf5f61979c748687e66bSherry Moore !(scsb->scsb_state & SCSB_IN_INTR)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EAGAIN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < SCTRL_LED_OK_NUMREGS; ++i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel led_data[i] = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel blink[i] = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel led_reg = SCSB_REG_ADDR(SCTRL_LED_OK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = SCSB_REG_ADDR(SCTRL_BLINK_OK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel lid = SCSB_REG_INDEX(led_reg); /* the LED Index Delta */
03831d35f7499c87d51205817c93e9a8d42c4baestevel bid = SCSB_REG_INDEX(reg); /* the Blink Index Delta */
03831d35f7499c87d51205817c93e9a8d42c4baestevel blink_reg = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (int_fru_ptr != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel update_reg = int_fru_ptr->i2c_info->ledata_reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (fru_type = 0; fru_type < SCSB_UNIT_TYPES; ++fru_type) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int is_present;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr = mct_system_info.fru_info_list[fru_type];
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (; fru_ptr != NULL; fru_ptr = fru_ptr->next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel is_present = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (fru_type == SLOT && (scsb->scsb_state &
193974072f41a843678abf5f61979c748687e66bSherry Moore SCSB_APP_SLOTLED_CTRL))
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (fru_ptr->i2c_info == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((led_reg = fru_ptr->i2c_info->ledata_reg) == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * No LED exceptions: SSB,CRTM,PRTM
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (update_reg && update_reg != led_reg)
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel led_idx = SCSB_REG_INDEX(led_reg) - lid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel led_bit = fru_ptr->i2c_info->ledata_bit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((reg = fru_ptr->i2c_info->syscfg_reg) == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (fru_type != SCB)
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * exception: SCB
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_SCB_PRESENT) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel led_data[led_idx] |= 1 << led_bit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel is_present = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel led_data[led_idx] &= ~(1 << led_bit);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (IS_SCB_P10)
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cfg_idx = SCSB_REG_INDEX(reg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cfg_bit = fru_ptr->i2c_info->syscfg_bit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_data_reg[cfg_idx] &
193974072f41a843678abf5f61979c748687e66bSherry Moore (1 << cfg_bit)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel is_present = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (is_present) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (fru_type == PS && (int_fru_ptr == NULL ||
193974072f41a843678abf5f61979c748687e66bSherry Moore (int_fru_ptr == fru_ptr))) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel pao.scsb = scsb;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pao.utype = fru_type;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pao.unit = fru_ptr->fru_unit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef PS_ON_DELAY
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * HW recommended not implementing
03831d35f7499c87d51205817c93e9a8d42c4baestevel * this delay for now.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The code is tested on PSUs:
03831d35f7499c87d51205817c93e9a8d42c4baestevel * -06
03831d35f7499c87d51205817c93e9a8d42c4baestevel * -07 rev 2
03831d35f7499c87d51205817c93e9a8d42c4baestevel * -08 plus
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (int_fru_ptr) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Hot insertion, so give it
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the 3 seconds it needs to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * become stable
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!scsb->scsb_btid)
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_btid =
193974072f41a843678abf5f61979c748687e66bSherry Moore timeout(
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb_ps_auto_on,
193974072f41a843678abf5f61979c748687e66bSherry Moore &pao, (4 *
193974072f41a843678abf5f61979c748687e66bSherry Moore drv_usectohz(
193974072f41a843678abf5f61979c748687e66bSherry Moore 1000000)));
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* PS_ON_DELAY */
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_ps_auto_on((void *)&pao);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (fru_type != SLOT || (fru_type == SLOT &&
193974072f41a843678abf5f61979c748687e66bSherry Moore (fru_ptr->fru_type ==
193974072f41a843678abf5f61979c748687e66bSherry Moore (scsb_utype_t)OC_CPU ||
193974072f41a843678abf5f61979c748687e66bSherry Moore fru_ptr->fru_type ==
193974072f41a843678abf5f61979c748687e66bSherry Moore (scsb_utype_t)OC_CTC))) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Set OK (green) LED register bit
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel led_data[led_idx] |= 1 << led_bit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (IS_SCB_P10)
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Turn off BLINK register bit.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If single register update, then save the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * corresponding blink register in blink_reg.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = fru_ptr->i2c_info->blink_reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!reg)
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel blink_bit = fru_ptr->i2c_info->blink_bit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel blink_idx = SCSB_REG_INDEX(reg) - bid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel blink[blink_idx] |= 1 << blink_bit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (update_reg && update_reg == led_reg)
03831d35f7499c87d51205817c93e9a8d42c4baestevel blink_reg = reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (update_reg) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = update_reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = SCSB_REG_INDEX(reg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel puc = &led_data[i - lid];
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = SCSB_REG_ADDR(SCTRL_LED_OK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel puc = led_data;
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = SCTRL_LED_OK_NUMREGS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0100) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_set_scfg_pres(): writing %d bytes "
193974072f41a843678abf5f61979c748687e66bSherry Moore "to 0x%x", i, reg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((error = scsb_rdwr_register(scsb, I2C_WR, reg, i, puc, 1)) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0102)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_set_scfg_pres(): "
193974072f41a843678abf5f61979c748687e66bSherry Moore "I2C write to 0x%x failed", reg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EIO;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Now see which BLINK bits need to be turned off for the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * corresponding OK LED bits.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = SCSB_REG_ADDR(SCTRL_BLINK_OK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < SCTRL_BLINK_NUMREGS; ++i, ++reg) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (blink_reg && blink_reg != reg)
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!blink[i]) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0100) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_set_scfg_pres(): turn "
193974072f41a843678abf5f61979c748687e66bSherry Moore "OFF Blink bits 0x%x in 0x%x",
193974072f41a843678abf5f61979c748687e66bSherry Moore blink[i], reg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_write_mask(scsb, reg, 0, 0, blink[i])) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0102)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_set_scfg_pres(): "
193974072f41a843678abf5f61979c748687e66bSherry Moore "Write to 0x%x failed", reg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EIO;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_check_config_status(scsb_state_t *scsb)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int index, p06;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0201) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_check_config_status:");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Base of register set
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = SCSB_REG_ADDR(SCTRL_SYSCFG_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel index = SCSB_REG_INDEX(reg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SCB P0.6 workaround: read registers twice, use 2nd value set
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel p06 = 2;
03831d35f7499c87d51205817c93e9a8d42c4baestevel do {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error = scsb_rdwr_register(scsb, I2C_WR_RD, reg,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCTRL_CFG_NUMREGS, &scsb->scsb_data_reg[index], 1)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (p06 == 1) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0200)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "scsb_check_config_status: P0.6 workaround");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If not P0.6 PROM, just break here
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state & SCSB_P06_PROM))
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } while (--p06);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state & SCSB_SCB_PRESENT))
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state |= SCSB_SCB_PRESENT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_fru_op(scsb, SSB, 1, SCTRL_SYSCFG_BASE,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCSB_FRU_OP_GET_BITVAL))
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state |= SCSB_SSB_PRESENT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state &= ~SCSB_SSB_PRESENT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_set_topology(scsb_state_t *scsb)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i, t, index, unit, is_tonga = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int alarm_slot_num, cpu_slot_num, ctc_slot_num;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_info_t *fru_ptr, *last_ptr, *acslot_ptr, *ctcslot_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t syscfg, led_reg, blink_reg, t_uchar;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t bit_num, led_bit, blink_bit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int pad = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Get the presence status from the SysConfigStatus shadow registers
03831d35f7499c87d51205817c93e9a8d42c4baestevel * in scsb->scsb_data_reg[]
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Mid Plane */
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = SYS_REG_INDEX(SCTRL_CFG_MPID0, SCTRL_SYSCFG_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel t_uchar = SCSB_REG_ADDR(i);
03831d35f7499c87d51205817c93e9a8d42c4baestevel index = SCSB_REG_INDEX(t_uchar);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mct_system_info.mid_plane.fru_type = MIDPLANE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mct_system_info.mid_plane.fru_version = (fru_version_t)0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel t = SYS_OFFSET(SCTRL_CFG_MPID0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mct_system_info.mid_plane.fru_id = (int)((scsb->scsb_data_reg[index] &
193974072f41a843678abf5f61979c748687e66bSherry Moore (SCTRL_MPID_MASK << t)) >> t);
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (mct_system_info.mid_plane.fru_id) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCTRL_MPID_HALF: /* Monte Carlo */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x00100005)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_set_topology: Monte Carlo");
03831d35f7499c87d51205817c93e9a8d42c4baestevel cpu_slot_num = SC_MC_CPU_SLOT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ctc_slot_num = SC_MC_CTC_SLOT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel alarm_slot_num = scsb->ac_slotnum = SC_MC_AC_SLOT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mct_system_info.max_units[SLOT] = MC_MAX_SLOTS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mct_system_info.max_units[ALARM] = MC_MAX_AC;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mct_system_info.max_units[DISK] = MC_MAX_DISK;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mct_system_info.max_units[FAN] = MC_MAX_FAN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mct_system_info.max_units[PS] = MC_MAX_PS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mct_system_info.max_units[PDU] = MC_MAX_PDU;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mct_system_info.max_units[SCB] = MC_MAX_SCB;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mct_system_info.max_units[SSB] = MC_MAX_SCB;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mct_system_info.max_units[CFTM] = MC_MAX_CFTM;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mct_system_info.max_units[CRTM] = MC_MAX_CRTM;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mct_system_info.max_units[PRTM] = MC_MAX_PRTM;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCTRL_MPID_QUARTER_NODSK: /* Tonga w/o disk */
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCTRL_MPID_QUARTER: /* Tonga w/ disk */
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state |= SCSB_IS_TONGA;
03831d35f7499c87d51205817c93e9a8d42c4baestevel is_tonga = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ctc_slot_num = -1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ctcslot_ptr = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x00100005)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_set_topology: Tonga%s",
193974072f41a843678abf5f61979c748687e66bSherry Moore mct_system_info.mid_plane.fru_id ==
193974072f41a843678abf5f61979c748687e66bSherry Moore SCTRL_MPID_QUARTER_NODSK ?
193974072f41a843678abf5f61979c748687e66bSherry Moore ", no disk" : " with disk");
03831d35f7499c87d51205817c93e9a8d42c4baestevel cpu_slot_num = SC_TG_CPU_SLOT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel alarm_slot_num = scsb->ac_slotnum = SC_TG_AC_SLOT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mct_system_info.max_units[SLOT] = TG_MAX_SLOTS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mct_system_info.max_units[ALARM] = TG_MAX_AC;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mct_system_info.max_units[DISK] = TG_MAX_DISK;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mct_system_info.max_units[FAN] = TG_MAX_FAN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mct_system_info.max_units[PS] = TG_MAX_PS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mct_system_info.max_units[PDU] = TG_MAX_PDU;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mct_system_info.max_units[SCB] = TG_MAX_SCB;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mct_system_info.max_units[SSB] = TG_MAX_SCB;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mct_system_info.max_units[CFTM] = TG_MAX_CFTM;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mct_system_info.max_units[CRTM] = TG_MAX_CRTM;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mct_system_info.max_units[PRTM] = TG_MAX_PRTM;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "%s#%d: Unknown MidPlane Id %x",
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_driver_name(scsb->scsb_dev),
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_get_instance(scsb->scsb_dev),
193974072f41a843678abf5f61979c748687e66bSherry Moore mct_system_info.mid_plane.fru_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x00100005)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_set_topology: 0x%x: unknown!",
193974072f41a843678abf5f61979c748687e66bSherry Moore mct_system_info.mid_plane.fru_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cPCI Slots
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
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
03831d35f7499c87d51205817c93e9a8d42c4baestevel * release.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mct_system_info.fru_info_list[SLOT] = (fru_info_t *)
193974072f41a843678abf5f61979c748687e66bSherry Moore kmem_zalloc(sizeof (fru_info_t) *
193974072f41a843678abf5f61979c748687e66bSherry Moore (mct_system_info.max_units[SLOT] + pad), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr = mct_system_info.fru_info_list[SLOT];
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (unit = 1; unit <= mct_system_info.max_units[SLOT]; ++unit) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int iunit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (unit == cpu_slot_num) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_type = (scsb_utype_t)OC_CPU;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (unit == ctc_slot_num) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* fru_ptr saved for Transition Card Presence check */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ctcslot_ptr = fru_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_type = (scsb_utype_t)OC_UNKN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (unit == alarm_slot_num) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* fru_ptr saved for Alarm Card Presence check below */
03831d35f7499c87d51205817c93e9a8d42c4baestevel acslot_ptr = fru_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_type = (scsb_utype_t)OC_UNKN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_type = (scsb_utype_t)OC_UNKN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (IS_SCB_P15) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel iunit = tonga_psl_to_ssl(scsb, unit);
03831d35f7499c87d51205817c93e9a8d42c4baestevel t = FRU_UNIT_TO_EVCODE(SLOT, iunit);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel t = FRU_UNIT_TO_EVCODE(SLOT, unit);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel led_bit = FRU_OFFSET(t, SCTRL_LED_OK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel blink_bit = FRU_OFFSET(t, SCTRL_BLINK_OK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel blink_reg = FRU_REG_ADDR(t, SCTRL_BLINK_OK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (is_tonga && unit <= TG_MAX_SLOTS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel bit_num = tonga_pslotnum_to_cfgbit(scsb, unit);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel bit_num = FRU_OFFSET(t, SCTRL_SYSCFG_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the registers addresses and shadow register index for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the SYSCFG register
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel syscfg = FRU_REG_ADDR(t, SCTRL_SYSCFG_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel index = SCSB_REG_INDEX(syscfg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel led_reg = FRU_REG_ADDR(t, SCTRL_LED_OK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * check and set presence status
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_P06_PROM) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_status = FRU_NOT_PRESENT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (scsb->scsb_data_reg[index] & (1 << bit_num)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_status = FRU_PRESENT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_status = FRU_NOT_PRESENT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_unit = (scsb_unum_t)unit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_id = fru_id_table[event_to_index(
193974072f41a843678abf5f61979c748687e66bSherry Moore FRU_UNIT_TO_EVCODE(SLOT, unit))];
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_version = (fru_version_t)0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->type_list = (fru_options_t *)NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info = (fru_i2c_info_t *)
193974072f41a843678abf5f61979c748687e66bSherry Moore kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->syscfg_reg = syscfg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->syscfg_bit = bit_num;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->ledata_reg = led_reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->ledata_bit = led_bit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->blink_reg = blink_reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->blink_bit = blink_bit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel last_ptr = fru_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel last_ptr->next = fru_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel last_ptr->next = (fru_info_t *)NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * PDU
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mct_system_info.fru_info_list[PDU] = (fru_info_t *)
193974072f41a843678abf5f61979c748687e66bSherry Moore kmem_zalloc(sizeof (fru_info_t) *
193974072f41a843678abf5f61979c748687e66bSherry Moore (mct_system_info.max_units[PDU] + pad), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr = mct_system_info.fru_info_list[PDU];
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (unit = 1; unit <= mct_system_info.max_units[PDU]; ++unit) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_type = PDU;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* SCB15 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the FRU event code (t), then use it to get the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * FRU bit-offsets for LED and SYSCFG registers
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel t = FRU_UNIT_TO_EVCODE(PDU, unit);
03831d35f7499c87d51205817c93e9a8d42c4baestevel led_bit = FRU_OFFSET(t, SCTRL_LED_OK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel bit_num = FRU_OFFSET(t, SCTRL_SYSCFG_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (IS_SCB_P15) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel blink_bit = FRU_OFFSET(t, SCTRL_BLINK_OK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = FRU_REG_INDEX(t, SCTRL_BLINK_OK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel blink_reg = SCSB_REG_ADDR(i);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel blink_bit = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel blink_reg = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the registers addresses and shadow register index for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the SYSCFG register
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = FRU_REG_INDEX(t, SCTRL_SYSCFG_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel syscfg = SCSB_REG_ADDR(i);
03831d35f7499c87d51205817c93e9a8d42c4baestevel index = SCSB_REG_INDEX(syscfg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = FRU_REG_INDEX(t, SCTRL_LED_OK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel led_reg = SCSB_REG_ADDR(i);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * check and set presence status
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_data_reg[index] & (1 << bit_num)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_status = FRU_PRESENT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_version = (fru_version_t)0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_status = FRU_NOT_PRESENT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_version = (fru_version_t)0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_unit = (scsb_unum_t)unit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_id = fru_id_table[event_to_index(t)];
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->type_list = (fru_options_t *)NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info = (fru_i2c_info_t *)
193974072f41a843678abf5f61979c748687e66bSherry Moore kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->syscfg_reg = syscfg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->syscfg_bit = bit_num;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->ledata_reg = led_reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->ledata_bit = led_bit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->blink_reg = blink_reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->blink_bit = blink_bit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel last_ptr = fru_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel last_ptr->next = fru_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel last_ptr->next = (fru_info_t *)NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Power Supplies
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mct_system_info.fru_info_list[PS] = (fru_info_t *)
193974072f41a843678abf5f61979c748687e66bSherry Moore kmem_zalloc(sizeof (fru_info_t) *
193974072f41a843678abf5f61979c748687e66bSherry Moore (mct_system_info.max_units[PS] + pad), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr = mct_system_info.fru_info_list[PS];
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (unit = 1; unit <= mct_system_info.max_units[PS]; ++unit) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the FRU event code (t), then use it to get the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * FRU bit-offsets for LED and SYSCFG registers
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel t = FRU_UNIT_TO_EVCODE(PS, unit);
03831d35f7499c87d51205817c93e9a8d42c4baestevel led_bit = FRU_OFFSET(t, SCTRL_LED_OK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel bit_num = FRU_OFFSET(t, SCTRL_SYSCFG_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (IS_SCB_P15) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel blink_bit = FRU_OFFSET(t, SCTRL_BLINK_OK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = FRU_REG_INDEX(t, SCTRL_BLINK_OK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel blink_reg = SCSB_REG_ADDR(i);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel blink_bit = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel blink_reg = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the registers addresses and shadow register index for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the SYSCFG register
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = FRU_REG_INDEX(t, SCTRL_SYSCFG_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel syscfg = SCSB_REG_ADDR(i);
03831d35f7499c87d51205817c93e9a8d42c4baestevel index = SCSB_REG_INDEX(syscfg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = FRU_REG_INDEX(t, SCTRL_LED_OK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel led_reg = SCSB_REG_ADDR(i);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * check and set presence status
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_data_reg[index] & (1 << bit_num)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_status = FRU_PRESENT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_status = FRU_NOT_PRESENT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_type = PS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_unit = (scsb_unum_t)unit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_id = fru_id_table[event_to_index(t)];
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_version = (fru_version_t)0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->type_list = (fru_options_t *)NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info = (fru_i2c_info_t *)
193974072f41a843678abf5f61979c748687e66bSherry Moore kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->syscfg_reg = syscfg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->syscfg_bit = bit_num;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->ledata_reg = led_reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->ledata_bit = led_bit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->blink_reg = blink_reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->blink_bit = blink_bit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel last_ptr = fru_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel last_ptr->next = fru_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel last_ptr->next = (fru_info_t *)NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SCSI Disks and removable media
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mct_system_info.fru_info_list[DISK] = (fru_info_t *)
193974072f41a843678abf5f61979c748687e66bSherry Moore kmem_zalloc(sizeof (fru_info_t) *
193974072f41a843678abf5f61979c748687e66bSherry Moore (mct_system_info.max_units[DISK] + pad), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr = mct_system_info.fru_info_list[DISK];
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (unit = 1; unit <= mct_system_info.max_units[DISK]; ++unit) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* SCB15 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the FRU event code (t), then use it to get the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * FRU bit-offsets for LED and SYSCFG registers
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel t = FRU_UNIT_TO_EVCODE(DISK, unit);
03831d35f7499c87d51205817c93e9a8d42c4baestevel led_bit = FRU_OFFSET(t, SCTRL_LED_OK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel bit_num = FRU_OFFSET(t, SCTRL_SYSCFG_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (IS_SCB_P15) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel blink_bit = FRU_OFFSET(t, SCTRL_BLINK_OK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = FRU_REG_INDEX(t, SCTRL_BLINK_OK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel blink_reg = SCSB_REG_ADDR(i);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel blink_bit = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel blink_reg = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the registers addresses and shadow register index for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the SYSCFG register
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = FRU_REG_INDEX(t, SCTRL_SYSCFG_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel syscfg = SCSB_REG_ADDR(i);
03831d35f7499c87d51205817c93e9a8d42c4baestevel index = SCSB_REG_INDEX(syscfg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = FRU_REG_INDEX(t, SCTRL_LED_OK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel led_reg = SCSB_REG_ADDR(i);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * check and set presence status
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_data_reg[index] & (1 << bit_num)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_status = FRU_PRESENT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_version = (fru_version_t)0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_status = FRU_NOT_PRESENT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_type = DISK;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_unit = (scsb_unum_t)unit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_id = fru_id_table[event_to_index(t)];
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->type_list = (fru_options_t *)NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info = (fru_i2c_info_t *)
193974072f41a843678abf5f61979c748687e66bSherry Moore kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->syscfg_reg = syscfg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->syscfg_bit = bit_num;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->ledata_reg = led_reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->ledata_bit = led_bit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->blink_reg = blink_reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->blink_bit = blink_bit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel last_ptr = fru_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel last_ptr->next = fru_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel last_ptr->next = (fru_info_t *)NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Fan Trays
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mct_system_info.fru_info_list[FAN] = (fru_info_t *)
193974072f41a843678abf5f61979c748687e66bSherry Moore kmem_zalloc(sizeof (fru_info_t) *
193974072f41a843678abf5f61979c748687e66bSherry Moore (mct_system_info.max_units[FAN] + pad), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr = mct_system_info.fru_info_list[FAN];
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (unit = 1; unit <= mct_system_info.max_units[FAN]; ++unit) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int bit_num;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* SCB15 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the FRU event code (t), then use it to get the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * FRU bit-offsets for LED and SYSCFG registers
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel t = FRU_UNIT_TO_EVCODE(FAN, unit);
03831d35f7499c87d51205817c93e9a8d42c4baestevel led_bit = FRU_OFFSET(t, SCTRL_LED_OK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel bit_num = FRU_OFFSET(t, SCTRL_SYSCFG_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (IS_SCB_P15) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel blink_bit = FRU_OFFSET(t, SCTRL_BLINK_OK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = FRU_REG_INDEX(t, SCTRL_BLINK_OK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel blink_reg = SCSB_REG_ADDR(i);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel blink_bit = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel blink_reg = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the registers addresses and shadow register index for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the SYSCFG register
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = FRU_REG_INDEX(t, SCTRL_SYSCFG_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel syscfg = SCSB_REG_ADDR(i);
03831d35f7499c87d51205817c93e9a8d42c4baestevel index = SCSB_REG_INDEX(syscfg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = FRU_REG_INDEX(t, SCTRL_LED_OK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel led_reg = SCSB_REG_ADDR(i);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * check and set presence status
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_data_reg[index] & (1 << bit_num)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_status = FRU_PRESENT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_status = FRU_NOT_PRESENT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_type = FAN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_unit = (scsb_unum_t)unit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_id = fru_id_table[event_to_index(t)];
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_version = (fru_version_t)0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->type_list = (fru_options_t *)NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info = (fru_i2c_info_t *)
193974072f41a843678abf5f61979c748687e66bSherry Moore kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->syscfg_reg = syscfg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->syscfg_bit = bit_num;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->ledata_reg = led_reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->ledata_bit = led_bit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->blink_reg = blink_reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->blink_bit = blink_bit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel last_ptr = fru_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel last_ptr->next = fru_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel last_ptr->next = (fru_info_t *)NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Alarm Cards
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mct_system_info.fru_info_list[ALARM] = (fru_info_t *)
193974072f41a843678abf5f61979c748687e66bSherry Moore kmem_zalloc(sizeof (fru_info_t) *
193974072f41a843678abf5f61979c748687e66bSherry Moore (mct_system_info.max_units[ALARM] + pad), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr = mct_system_info.fru_info_list[ALARM];
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (unit = 1; unit <= mct_system_info.max_units[ALARM]; ++unit) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int bit_num;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the FRU event code (t), then use it to get the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * FRU bit-offsets for SYSCFG register
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel t = FRU_UNIT_TO_EVCODE(ALARM, unit);
03831d35f7499c87d51205817c93e9a8d42c4baestevel bit_num = FRU_OFFSET(t, SCTRL_SYSCFG_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the registers addresses and shadow register index for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the SYSCFG register
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = FRU_REG_INDEX(t, SCTRL_SYSCFG_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel syscfg = SCSB_REG_ADDR(i);
03831d35f7499c87d51205817c93e9a8d42c4baestevel index = SCSB_REG_INDEX(syscfg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * check and set presence status
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_data_reg[index] & (1 << bit_num)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_status = FRU_PRESENT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (acslot_ptr != NULL && acslot_ptr->fru_status ==
193974072f41a843678abf5f61979c748687e66bSherry Moore FRU_PRESENT) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel acslot_ptr->fru_type = (scsb_utype_t)OC_AC;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * acslot_ptr->fru_id =
193974072f41a843678abf5f61979c748687e66bSherry Moore * fru_id_table[event_to_index(t)];
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_status = FRU_NOT_PRESENT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_type = ALARM;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_unit = (scsb_unum_t)unit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_id = fru_id_table[event_to_index(t)];
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_version = (fru_version_t)0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->type_list = (fru_options_t *)NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info = (fru_i2c_info_t *)
193974072f41a843678abf5f61979c748687e66bSherry Moore kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->syscfg_reg = syscfg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->syscfg_bit = bit_num;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->ledata_reg = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->ledata_bit = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->blink_reg = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->blink_bit = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel last_ptr = fru_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel last_ptr->next = fru_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel last_ptr->next = (fru_info_t *)NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SCB
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mct_system_info.fru_info_list[SCB] = (fru_info_t *)
193974072f41a843678abf5f61979c748687e66bSherry Moore kmem_zalloc(sizeof (fru_info_t) *
193974072f41a843678abf5f61979c748687e66bSherry Moore (mct_system_info.max_units[SCB] + pad), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr = mct_system_info.fru_info_list[SCB];
03831d35f7499c87d51205817c93e9a8d42c4baestevel unit = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* SCB15 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the FRU event code (t), then use it to get the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * FRU bit-offset for LED register
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel t = FRU_UNIT_TO_EVCODE(SCB, unit);
03831d35f7499c87d51205817c93e9a8d42c4baestevel led_bit = FRU_OFFSET(t, SCTRL_LED_OK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = FRU_REG_INDEX(t, SCTRL_LED_OK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel led_reg = SCSB_REG_ADDR(i);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (IS_SCB_P15) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel blink_bit = FRU_OFFSET(t, SCTRL_BLINK_OK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = FRU_REG_INDEX(t, SCTRL_BLINK_OK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel blink_reg = SCSB_REG_ADDR(i);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel blink_bit = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel blink_reg = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = SYS_REG_INDEX(SCTRL_SCBID0, SCTRL_SCBID_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel index = SCSB_REG_ADDR(i);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * check and set presence status
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_SCB_PRESENT) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_status = FRU_PRESENT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_status = FRU_NOT_PRESENT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_type = SCB;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_unit = (scsb_unum_t)unit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_id = fru_id_table[event_to_index(t)];
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* get PROM_VERSION from shadow registers */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_rdwr_register(scsb, I2C_WR_RD, index, 1, &t_uchar, 1))
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_version = (fru_version_t)0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_version = (fru_version_t)t_uchar;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->type_list = (fru_options_t *)NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info = (fru_i2c_info_t *)
193974072f41a843678abf5f61979c748687e66bSherry Moore kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->syscfg_reg = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->syscfg_bit = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->ledata_reg = led_reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->ledata_bit = led_bit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->blink_reg = blink_reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->blink_bit = blink_bit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->next = (fru_info_t *)NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SSB
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mct_system_info.fru_info_list[SSB] = (fru_info_t *)
193974072f41a843678abf5f61979c748687e66bSherry Moore kmem_zalloc(sizeof (fru_info_t) *
193974072f41a843678abf5f61979c748687e66bSherry Moore (mct_system_info.max_units[SSB] + pad), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr = mct_system_info.fru_info_list[SSB];
03831d35f7499c87d51205817c93e9a8d42c4baestevel unit = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* SCB15 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the FRU event code (t), then use it to get the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * FRU bit-offset for SYSCFG register
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel t = FRU_UNIT_TO_EVCODE(SSB, unit);
03831d35f7499c87d51205817c93e9a8d42c4baestevel bit_num = FRU_OFFSET(t, SCTRL_SYSCFG_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the registers addresses and shadow register index for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the SYSCFG register
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = FRU_REG_INDEX(t, SCTRL_SYSCFG_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel syscfg = SCSB_REG_ADDR(i);
03831d35f7499c87d51205817c93e9a8d42c4baestevel index = SCSB_REG_INDEX(syscfg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * check and set presence status
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_data_reg[index] & (1 << bit_num)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_status = FRU_PRESENT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_status = FRU_NOT_PRESENT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_type = SSB;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_unit = (scsb_unum_t)unit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_id = fru_id_table[event_to_index(t)];
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_version = (fru_version_t)0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->type_list = (fru_options_t *)NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info = (fru_i2c_info_t *)
193974072f41a843678abf5f61979c748687e66bSherry Moore kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->syscfg_reg = syscfg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->syscfg_bit = bit_num;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->ledata_reg = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->ledata_bit = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->blink_reg = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->blink_bit = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->next = (fru_info_t *)NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * CFTM
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mct_system_info.fru_info_list[CFTM] = (fru_info_t *)
193974072f41a843678abf5f61979c748687e66bSherry Moore kmem_zalloc(sizeof (fru_info_t) *
193974072f41a843678abf5f61979c748687e66bSherry Moore (mct_system_info.max_units[CFTM] + pad), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr = mct_system_info.fru_info_list[CFTM];
03831d35f7499c87d51205817c93e9a8d42c4baestevel unit = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* SCB15 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the FRU event code (t), then use it to get the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * FRU bit-offsets for LED and SYSCFG registers
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel t = FRU_UNIT_TO_EVCODE(CFTM, unit);
03831d35f7499c87d51205817c93e9a8d42c4baestevel led_bit = FRU_OFFSET(t, SCTRL_LED_OK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel bit_num = FRU_OFFSET(t, SCTRL_SYSCFG_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (IS_SCB_P15) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel blink_bit = FRU_OFFSET(t, SCTRL_BLINK_OK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = FRU_REG_INDEX(t, SCTRL_BLINK_OK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel blink_reg = SCSB_REG_ADDR(i);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel blink_bit = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel blink_reg = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the registers addresses and shadow register index for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the SYSCFG register
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = FRU_REG_INDEX(t, SCTRL_SYSCFG_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel syscfg = SCSB_REG_ADDR(i);
03831d35f7499c87d51205817c93e9a8d42c4baestevel index = SCSB_REG_INDEX(syscfg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = FRU_REG_INDEX(t, SCTRL_LED_OK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel led_reg = SCSB_REG_ADDR(i);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * check and set presence status
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_data_reg[index] & (1 << bit_num)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_status = FRU_PRESENT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ctcslot_ptr != NULL && ctcslot_ptr->fru_status ==
193974072f41a843678abf5f61979c748687e66bSherry Moore FRU_PRESENT) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ctcslot_ptr->fru_type = (scsb_utype_t)OC_CTC;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_hsc_state |= SCSB_HSC_CTC_PRES;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_status = FRU_NOT_PRESENT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_type = CFTM;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_unit = (scsb_unum_t)1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_id = fru_id_table[event_to_index(t)];
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_version = (fru_version_t)0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->type_list = (fru_options_t *)NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info = (fru_i2c_info_t *)
193974072f41a843678abf5f61979c748687e66bSherry Moore kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->syscfg_reg = syscfg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->syscfg_bit = bit_num;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->ledata_reg = led_reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->ledata_bit = led_bit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->blink_reg = blink_reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->blink_bit = blink_bit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->next = (fru_info_t *)NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * CRTM
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mct_system_info.fru_info_list[CRTM] = (fru_info_t *)
193974072f41a843678abf5f61979c748687e66bSherry Moore kmem_zalloc(sizeof (fru_info_t) *
193974072f41a843678abf5f61979c748687e66bSherry Moore (mct_system_info.max_units[CRTM] + pad),
193974072f41a843678abf5f61979c748687e66bSherry Moore KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr = mct_system_info.fru_info_list[CRTM];
03831d35f7499c87d51205817c93e9a8d42c4baestevel unit = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* SCB15 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the FRU event code (t), then use it to get the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * FRU bit-offsets for LED and SYSCFG registers
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel t = FRU_UNIT_TO_EVCODE(CRTM, unit);
03831d35f7499c87d51205817c93e9a8d42c4baestevel bit_num = FRU_OFFSET(t, SCTRL_SYSCFG_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the registers addresses and shadow register index for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the SYSCFG register
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = FRU_REG_INDEX(t, SCTRL_SYSCFG_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel syscfg = SCSB_REG_ADDR(i);
03831d35f7499c87d51205817c93e9a8d42c4baestevel index = SCSB_REG_INDEX(syscfg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * check and set presence status
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_data_reg[index] & (1 << bit_num)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_status = FRU_PRESENT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_status = FRU_NOT_PRESENT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_type = CRTM;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_unit = (scsb_unum_t)unit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_id = fru_id_table[event_to_index(t)];
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_version = (fru_version_t)0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->type_list = (fru_options_t *)NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info = (fru_i2c_info_t *)
193974072f41a843678abf5f61979c748687e66bSherry Moore kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->syscfg_reg = syscfg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->syscfg_bit = bit_num;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->ledata_reg = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->ledata_bit = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->blink_reg = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->blink_bit = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->next = (fru_info_t *)NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * PRTM
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mct_system_info.fru_info_list[PRTM] = (fru_info_t *)
193974072f41a843678abf5f61979c748687e66bSherry Moore kmem_zalloc(sizeof (fru_info_t) *
193974072f41a843678abf5f61979c748687e66bSherry Moore (mct_system_info.max_units[PRTM] + pad), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr = mct_system_info.fru_info_list[PRTM];
03831d35f7499c87d51205817c93e9a8d42c4baestevel unit = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel t = FRU_UNIT_TO_EVCODE(PRTM, unit);
03831d35f7499c87d51205817c93e9a8d42c4baestevel bit_num = FRU_OFFSET(t, SCTRL_SYSCFG_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the registers addresses and shadow register index for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the SYSCFG register
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = FRU_REG_INDEX(t, SCTRL_SYSCFG_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel syscfg = SCSB_REG_ADDR(i);
03831d35f7499c87d51205817c93e9a8d42c4baestevel index = SCSB_REG_INDEX(syscfg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * check and set presence status
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_data_reg[index] & (1 << bit_num)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_status = FRU_PRESENT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_status = FRU_NOT_PRESENT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_type = PRTM;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_unit = (scsb_unum_t)unit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_id = fru_id_table[event_to_index(t)];
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_version = (fru_version_t)0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->type_list = (fru_options_t *)NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info = (fru_i2c_info_t *)
193974072f41a843678abf5f61979c748687e66bSherry Moore kmem_zalloc(sizeof (fru_i2c_info_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->syscfg_reg = syscfg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->syscfg_bit = bit_num;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->ledata_reg = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->ledata_bit = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->blink_reg = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->i2c_info->blink_bit = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->next = (fru_info_t *)NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state |= SCSB_TOPOLOGY;
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel mct_topology_dump(scsb, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_free_topology(scsb_state_t *scsb)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_info_t *fru_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x00100005)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_free_topology:");
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < SCSB_UNIT_TYPES; ++i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr = mct_system_info.fru_info_list[i];
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (fru_ptr != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (fru_ptr->i2c_info != (fru_i2c_info_t *)NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(fru_ptr->i2c_info,
193974072f41a843678abf5f61979c748687e66bSherry Moore sizeof (fru_i2c_info_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr = fru_ptr->next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((fru_ptr = mct_system_info.fru_info_list[i]) !=
193974072f41a843678abf5f61979c748687e66bSherry Moore (fru_info_t *)NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(fru_ptr, sizeof (fru_info_t) *
193974072f41a843678abf5f61979c748687e66bSherry Moore mct_system_info.max_units[i]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mct_system_info.fru_info_list[i] = (fru_info_t *)NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelmct_topology_dump(scsb_state_t *scsb, int force)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_info_t *fru_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!force && !(scsb_debug & 0x00200000))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (force && !(scsb->scsb_state & (SCSB_DIAGS_MODE | SCSB_DEBUG_MODE)))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state & SCSB_TOPOLOGY)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "mct_topology_dump: Topology not set!");
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < SCSB_UNIT_TYPES; ++i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr = mct_system_info.fru_info_list[i];
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch ((scsb_utype_t)i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SLOT:
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "MCT: Number of Slots: %d",
193974072f41a843678abf5f61979c748687e66bSherry Moore mct_system_info.max_units[SLOT]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case ALARM:
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "MCT: MAX Number of Alarm Cards: %d",
193974072f41a843678abf5f61979c748687e66bSherry Moore mct_system_info.max_units[ALARM]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DISK:
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "MCT: MAX Number of SCSI Devices: %d",
193974072f41a843678abf5f61979c748687e66bSherry Moore mct_system_info.max_units[DISK]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case FAN:
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "MCT: MAX Number of Fan Trays: %d",
193974072f41a843678abf5f61979c748687e66bSherry Moore mct_system_info.max_units[FAN]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case PDU:
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "MCT: MAX Number of PDUs: %d",
193974072f41a843678abf5f61979c748687e66bSherry Moore mct_system_info.max_units[PDU]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case PS:
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "MCT: MAX Number of Power Supplies: %d",
193974072f41a843678abf5f61979c748687e66bSherry Moore mct_system_info.max_units[PS]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCB:
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "MCT: MAX Number of SCBs: %d",
193974072f41a843678abf5f61979c748687e66bSherry Moore mct_system_info.max_units[SCB]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SSB:
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "MCT: MAX Number of SSBs: %d",
193974072f41a843678abf5f61979c748687e66bSherry Moore mct_system_info.max_units[SSB]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (fru_ptr != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (fru_ptr->fru_status & FRU_PRESENT) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "MCT: type=%d, unit=%d, id=0x%x, "
193974072f41a843678abf5f61979c748687e66bSherry Moore "version=0x%x",
193974072f41a843678abf5f61979c748687e66bSherry Moore fru_ptr->fru_type,
193974072f41a843678abf5f61979c748687e66bSherry Moore fru_ptr->fru_unit,
193974072f41a843678abf5f61979c748687e66bSherry Moore fru_ptr->fru_id,
193974072f41a843678abf5f61979c748687e66bSherry Moore fru_ptr->fru_version);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr = fru_ptr->next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Sends an event when the system controller board I2C errors
03831d35f7499c87d51205817c93e9a8d42c4baestevel * exceed the threshold.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_failing_event(scsb_state_t *scsb)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t scsb_event_code = SCTRL_EVENT_SCB;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel add_event_code(scsb, scsb_event_code);
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) scsb_queue_ops(scsb, QPUT_INT32, 1, &scsb_event_code,
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_intr");
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_read_bhealthy(scsb_state_t *scsb)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int index;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x8001) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_read_bhealthy()");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = SCSB_REG_ADDR(SCTRL_BHLTHY_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel index = SCSB_REG_INDEX(reg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = scsb_rdwr_register(scsb, I2C_WR_RD, reg,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCTRL_BHLTHY_NUMREGS, &scsb->scsb_data_reg[index], 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Returns the health status of a slot
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_read_slot_health(scsb_state_t *scsb, int pslotnum)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int slotnum = tonga_psl_to_ssl(scsb, pslotnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (scsb_fru_op(scsb, SLOT, slotnum,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCTRL_BHLTHY_BASE, SCSB_FRU_OP_GET_BITVAL));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * DIAGNOSTIC and DEBUG only.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Called from ioctl command (SCSBIOC_BHEALTHY_GET)
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_bhealthy_slot(scsb_state_t *scsb, scsb_uinfo_t *suip)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int base, code, unit_number;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int index;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_FROZEN)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EAGAIN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* operation valid for slots only */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (suip == NULL || suip->unit_type != SLOT) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EINVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x8001)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_bhealthy_slot: slot %d",
193974072f41a843678abf5f61979c748687e66bSherry Moore suip->unit_number);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (suip->unit_number > mct_system_info.max_units[SLOT]) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EINVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Map 1.0 Tonga Slot Number, if necessary
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel tonga_slotnum_check(scsb, suip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel base = SCTRL_BHLTHY_BASE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel code = FRU_UNIT_TO_EVCODE(suip->unit_type, suip->unit_number);
03831d35f7499c87d51205817c93e9a8d42c4baestevel unit_number = FRU_OFFSET(code, base);
03831d35f7499c87d51205817c93e9a8d42c4baestevel index = FRU_REG_INDEX(code, base);
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = SCSB_REG_ADDR(index);
03831d35f7499c87d51205817c93e9a8d42c4baestevel index = SCSB_REG_INDEX(reg); /* shadow index */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_P10_PROM) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = scsb_read_bhealthy(scsb);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* else shadow regs are updated by interrupt handler */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_data_reg[index] & (1 << unit_number))
03831d35f7499c87d51205817c93e9a8d42c4baestevel suip->unit_state = ON;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel suip->unit_state = OFF;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Called from HSC and ioctl command (SCSBIOC_RESET_UNIT)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to reset one specified slot
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_reset_unit(scsb_state_t *scsb, scsb_uinfo_t *suip)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int unit_number;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int index, slotnum, reset_state;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_FROZEN)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EAGAIN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x8001) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_reset_slot(%d): slot %d, state %d\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_instance, suip->unit_number,
193974072f41a843678abf5f61979c748687e66bSherry Moore suip->unit_state);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (suip->unit_type != ALARM && !(scsb->scsb_state &
193974072f41a843678abf5f61979c748687e66bSherry Moore (SCSB_DIAGS_MODE | SCSB_DEBUG_MODE))) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EINVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (suip->unit_state != ON && suip->unit_state != OFF) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EINVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (suip->unit_type) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case ALARM:
03831d35f7499c87d51205817c93e9a8d42c4baestevel {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i, code;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (suip->unit_number != 1)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EINVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel code = FRU_UNIT_TO_EVCODE(suip->unit_type, suip->unit_number);
03831d35f7499c87d51205817c93e9a8d42c4baestevel unit_number = FRU_OFFSET(code, SCTRL_RESET_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = ALARM_RESET_REG_INDEX(code, SCTRL_RESET_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = SCSB_REG_ADDR(i);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SLOT:
03831d35f7499c87d51205817c93e9a8d42c4baestevel slotnum = suip->unit_number;
03831d35f7499c87d51205817c93e9a8d42c4baestevel reset_state = (suip->unit_state == ON) ? SCSB_RESET_SLOT :
193974072f41a843678abf5f61979c748687e66bSherry Moore SCSB_UNRESET_SLOT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_IS_TONGA) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (slotnum > TG_MAX_SLOTS ||
193974072f41a843678abf5f61979c748687e66bSherry Moore slotnum == SC_TG_CPU_SLOT) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EINVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (slotnum > MC_MAX_SLOTS ||
193974072f41a843678abf5f61979c748687e66bSherry Moore slotnum == SC_MC_CPU_SLOT ||
193974072f41a843678abf5f61979c748687e66bSherry Moore (scsb->scsb_hsc_state & SCSB_HSC_CTC_PRES &&
193974072f41a843678abf5f61979c748687e66bSherry Moore slotnum == SC_MC_CTC_SLOT)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EINVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (scsb_reset_slot(scsb, slotnum, reset_state));
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EINVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel index = SCSB_REG_INDEX(reg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (suip->unit_state == ON)
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_data_reg[index] |= (1 << unit_number);
03831d35f7499c87d51205817c93e9a8d42c4baestevel else /* OFF */
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_data_reg[index] &= ~(1 << unit_number);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((error = scsb_rdwr_register(scsb, I2C_WR, reg, 1,
193974072f41a843678abf5f61979c748687e66bSherry Moore &scsb->scsb_data_reg[index], 0)) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x8002)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_leds: write failure to 0x%x", reg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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!!!
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_slot_occupancy(scsb_state_t *scsb, scsb_uinfo_t *suip)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int saved_unit_number;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state & (SCSB_DEBUG_MODE | SCSB_DIAGS_MODE)))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EACCES);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_FROZEN) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EAGAIN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (suip->unit_type) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case ALARM:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (suip->unit_number !=
193974072f41a843678abf5f61979c748687e66bSherry Moore (mct_system_info.fru_info_list[ALARM])->fru_unit) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EINVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SLOT:
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * All slots are acceptable, except slots 11 & 12.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (suip->unit_number < 1 || suip->unit_number >
193974072f41a843678abf5f61979c748687e66bSherry Moore mct_system_info.max_units[ALARM]) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Map 1.0 Tonga Slot Numbers if necessary */
03831d35f7499c87d51205817c93e9a8d42c4baestevel saved_unit_number = suip->unit_number;
03831d35f7499c87d51205817c93e9a8d42c4baestevel tonga_slotnum_check(scsb, suip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (suip->unit_state == ON) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (hsc_slot_occupancy(saved_unit_number, B_TRUE, 0, B_TRUE)
193974072f41a843678abf5f61979c748687e66bSherry Moore != 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EFAULT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (hsc_slot_occupancy(saved_unit_number, B_FALSE, 0, B_FALSE)
193974072f41a843678abf5f61979c748687e66bSherry Moore != 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EFAULT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_clear_intptrs(scsb_state_t *scsb)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i, error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t wbuf[SCTRL_MAX_GROUP_NUMREGS];
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 1; i <= SCTRL_INTR_NUMREGS; ++i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel wbuf[i] = 0xff;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error = scsb_rdwr_register(scsb, I2C_WR,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCSB_REG_ADDR(SCTRL_INTSRC_BASE),
193974072f41a843678abf5f61979c748687e66bSherry Moore SCTRL_INTR_NUMREGS, wbuf, 1)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0402)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_clear_intptrs(): "
193974072f41a843678abf5f61979c748687e66bSherry Moore "write to 0x%x failed",
193974072f41a843678abf5f61979c748687e66bSherry Moore SCSB_REG_ADDR(SCTRL_INTSRC_BASE));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_setall_intmasks(scsb_state_t *scsb)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t reg, wdata, rmask;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * write loop for Interrupt Mask registers
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0401)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "setall_intmasks()");
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel rmask = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel wdata = 0xff;
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = SCSB_REG_ADDR(SCTRL_INTMASK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < SCTRL_MASK_NUMREGS; ++i, ++reg) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error = scsb_write_mask(scsb, reg, rmask, wdata, 0)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0402)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_setall_intmasks: "
193974072f41a843678abf5f61979c748687e66bSherry Moore "write to 0x%x failed: %d", reg, error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EIO;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_clear_intmasks(scsb_state_t *scsb)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t msk_reg, reg, wdata, rmask;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t mask_data[SCTRL_MAX_GROUP_NUMREGS];
03831d35f7499c87d51205817c93e9a8d42c4baestevel int tmp, idx, code, unit, offset, mbid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_utype_t fru_type;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_info_t *fru_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_FROZEN &&
193974072f41a843678abf5f61979c748687e66bSherry Moore !(scsb->scsb_state & SCSB_IN_INTR)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EAGAIN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (tmp = 0; tmp < SCTRL_MASK_NUMREGS; ++tmp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel mask_data[tmp] = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msk_reg = SCSB_REG_ADDR(SCTRL_INTMASK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mbid = SCSB_REG_INDEX(msk_reg); /* the Mask Base Index Delta */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0400) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "clear_intmasks: msk_reg=0x%x; mbid=%d",
193974072f41a843678abf5f61979c748687e66bSherry Moore msk_reg, mbid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (fru_type = 0; fru_type < SCSB_UNIT_TYPES; ++fru_type) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (fru_type == SCB)
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue; /* handle below, 2 reg offsets */
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr = mct_system_info.fru_info_list[fru_type];
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (; fru_ptr != NULL; fru_ptr = fru_ptr->next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel unit = fru_ptr->fru_unit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel code = FRU_UNIT_TO_EVCODE(fru_type, unit);
03831d35f7499c87d51205817c93e9a8d42c4baestevel offset = FRU_OFFSET(code, SCTRL_INTMSK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = FRU_REG_ADDR(code, SCTRL_INTMSK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel idx = SCSB_REG_INDEX(reg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel tmp = idx - mbid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mask_data[tmp] |= (1 << offset);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0400)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "clear_intmasks:%d:%d: PRES mask[%d]:0x%x",
193974072f41a843678abf5f61979c748687e66bSherry Moore fru_type, unit, tmp, mask_data[tmp]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((fru_type == SLOT) && (IS_SCB_P15)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Unmask the corresponding Slot HLTHY mask
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Use Slot bit and register offsets,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * but with SCTRL_INTMASK_HLTHY_BASE
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = FRU_REG_ADDR(code,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCTRL_INTMASK_HLTHY_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel idx = SCSB_REG_INDEX(reg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel tmp = idx - mbid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mask_data[tmp] |= (1 << offset);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0400) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "clear_intmasks:Slot:%d: HLTHY mask[%d]:0x%x"
03831d35f7499c87d51205817c93e9a8d42c4baestevel "; reg=0x%x, idx=%d, mbid=%d",
193974072f41a843678abf5f61979c748687e66bSherry Moore unit, tmp, mask_data[tmp],
193974072f41a843678abf5f61979c748687e66bSherry Moore reg, idx, mbid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel code = SCTRL_EVENT_PWRDWN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel offset = FRU_OFFSET(code, SCTRL_INTMSK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = FRU_REG_ADDR(code, SCTRL_INTMSK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel idx = SCSB_REG_INDEX(reg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel tmp = idx - mbid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mask_data[tmp] |= (1 << offset);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (IS_SCB_P15) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel code = SCTRL_EVENT_SCB;
03831d35f7499c87d51205817c93e9a8d42c4baestevel offset = FRU_OFFSET(code, SCTRL_INTMSK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = FRU_REG_ADDR(code, SCTRL_INTMSK_BASE) + SCB_INT_OFFSET;
03831d35f7499c87d51205817c93e9a8d42c4baestevel idx = SCSB_REG_INDEX(reg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel tmp = idx - mbid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mask_data[tmp] |= (1 << offset);
03831d35f7499c87d51205817c93e9a8d42c4baestevel code = SCTRL_EVENT_ALARM_INT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel offset = FRU_OFFSET(code, SCTRL_INTMSK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = FRU_REG_ADDR(code, SCTRL_INTMSK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel idx = SCSB_REG_INDEX(reg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel tmp = idx - mbid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mask_data[tmp] |= (1 << offset);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (tmp = 0; tmp < SCTRL_MASK_NUMREGS; ++tmp) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel rmask = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel wdata = mask_data[tmp];
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0400)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "clear_intmasks:0x%x: ~(0x%x),0x%x",
193974072f41a843678abf5f61979c748687e66bSherry Moore msk_reg, (~wdata) & 0xff, wdata);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error = scsb_write_mask(scsb, msk_reg, rmask,
193974072f41a843678abf5f61979c748687e66bSherry Moore (~wdata) & 0xff, wdata)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0402)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_clear_intmasks: "
193974072f41a843678abf5f61979c748687e66bSherry Moore "write to 0x%x failed: %d",
193974072f41a843678abf5f61979c748687e66bSherry Moore msk_reg, error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EIO;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ++msk_reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_get_status(scsb_state_t *scsb, scsb_status_t *smp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel register int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (smp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EFAULT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x40000000 &&
193974072f41a843678abf5f61979c748687e66bSherry Moore (scsb->scsb_state & SCSB_DEBUG_MODE ||
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_state & SCSB_DIAGS_MODE)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_FROZEN) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EAGAIN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x80000000) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((i = scsb_readall_regs(scsb)) != 0 &&
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_state & SCSB_DEBUG_MODE)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "scsb_get_status: "
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_readall_regs() FAILED");
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((i = scsb_check_config_status(scsb)) == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = scsb_set_scfg_pres_leds(scsb, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_get_status: FAILED Presence LEDs update");
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EIO);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < SCSB_DATA_REGISTERS; ++i)
03831d35f7499c87d51205817c93e9a8d42c4baestevel smp->scsb_reg[i] = scsb->scsb_data_reg[i];
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic char *BAD_BOARD_MSG =
03831d35f7499c87d51205817c93e9a8d42c4baestevel "SCSB: Should NOT remove SCB(%d) while cPCI Slot %d is "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "in RESET with a possible bad board.";
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int slots_in_reset[SCTRL_MAX_GROUP_NUMREGS];
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_freeze_check(scsb_state_t *scsb)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel register int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int offset;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int unit, slotnum;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int index;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_info_t *fru_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t code;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x20001)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_freeze_check(%d):", scsb->scsb_instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_FROZEN) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < SCTRL_MAX_GROUP_NUMREGS; ++i)
03831d35f7499c87d51205817c93e9a8d42c4baestevel slots_in_reset[i] = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr = mct_system_info.fru_info_list[SLOT];
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (unit = 1; unit <= mct_system_info.max_units[SLOT]; ++unit) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (IS_SCB_P15) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel slotnum = tonga_psl_to_ssl(scsb, unit);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel slotnum = unit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel code = FRU_UNIT_TO_EVCODE(SLOT, slotnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel offset = FRU_OFFSET(code, SCTRL_RESET_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = FRU_REG_ADDR(code, SCTRL_RESET_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel index = SCSB_REG_INDEX(reg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_data_reg[index] & (1 << offset)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (fru_ptr[unit - 1].fru_status == FRU_PRESENT) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel slots_in_reset[unit - 1] = unit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, BAD_BOARD_MSG,
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_instance, unit);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_freeze(scsb_state_t *scsb)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t code;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x00020002) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "scsb_freeze: SCB%d possibly removed",
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_FROZEN)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state |= SCSB_FROZEN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state &= ~SCSB_SCB_PRESENT;
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) scsb_hsc_freeze(scsb->scsb_dev);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Send the EVENT_SCB since there is evidence that the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * System Controller Board has been removed.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel code = SCTRL_EVENT_SCB;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state & SCSB_IN_INTR))
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_event_code = code;
03831d35f7499c87d51205817c93e9a8d42c4baestevel check_fru_info(scsb, code);
03831d35f7499c87d51205817c93e9a8d42c4baestevel add_event_code(scsb, code);
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) scsb_queue_ops(scsb, QPUT_INT32, 1, &code, "scsb_freeze");
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_restore(scsb_state_t *scsb)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x20001)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_restore(%d):", scsb->scsb_instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (initialize_scb(scsb) != DDI_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x00020002) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "scsb_restore: INIT Failed");
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* 9. Clear all Interrupts */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_clear_intmasks(scsb)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb%d: I2C TRANSFER Failed", scsb->scsb_instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x00020002) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "scsb_restore: clear_intmasks Failed");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* 10. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Check if Alarm Card present at boot and set flags */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_fru_op(scsb, ALARM, 1, SCTRL_SYSCFG_BASE,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCSB_FRU_OP_GET_BITVAL))
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_hsc_state |= SCSB_ALARM_CARD_PRES;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_hsc_state &= ~SCSB_ALARM_CARD_PRES;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state &= ~SCSB_FROZEN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) scsb_hsc_restore(scsb->scsb_dev);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Given an Event Code,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Return:
03831d35f7499c87d51205817c93e9a8d42c4baestevel * FRU type in LSByte
03831d35f7499c87d51205817c93e9a8d42c4baestevel * unit number in MSByte
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baesteveluint16_t
03831d35f7499c87d51205817c93e9a8d42c4baestevelevent_to_type(uint32_t evcode)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i, li, unit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t ec;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint16_t ret;
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = li = 0; i < SCSB_UNIT_TYPES; ++i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (evcode == type_to_code1[i]) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ret = (uint16_t)(0x0100 | i);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ret);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (evcode < type_to_code1[i]) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel unit = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ec = type_to_code1[li];
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (ec < evcode)
03831d35f7499c87d51205817c93e9a8d42c4baestevel ec = ec << 1, ++unit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ret = (unit << 8) | li;
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ret);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel li = i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return ((uint16_t)0xffff);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * retval flags allow all events to be checked, and still returning the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * correct DDI value.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SCSB_INTR_CLAIMED 1
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SCSB_INTR_UNCLAIMED 2
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SCSB_INTR_EVENT 4
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baesteveluint_t
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_intr_preprocess(caddr_t arg)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_state_t *scsb = (scsb_state_t *)arg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel scb_pre_s = gethrtime();
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_IN_INTR) {
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) untimeout(scsb_intr_tid);
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) scsb_invoke_intr_chain();
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) scsb_toggle_psmint(scsb, 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state &= ~SCSB_IN_INTR;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto intr_end;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state |= SCSB_IN_INTR;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Stop scsb from interrupting first.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_quiesce_psmint(scsb) != DDI_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto intr_end;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Schedule a timeout to actually process the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * interrupt.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_intr_tid = timeout((void (*)(void *))scsb_intr, arg,
193974072f41a843678abf5f61979c748687e66bSherry Moore drv_usectohz(1000));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelintr_end:
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel scb_pre_e = gethrtime();
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_INTR_CLAIMED);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void scsb_healthy_intr(scsb_state_t *scsb, int pslotnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_intr(caddr_t arg)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_state_t *scsb = (scsb_state_t *)arg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i, idx, offset, unit, numregs, error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int intr_idx, index, offset_base, retval, slotnum, val;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t code;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t intr_reg, tmp_reg, intr_addr, clr_bits = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t ac_slot = B_FALSE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t *int_masks;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t cstatus_regs[SCTRL_MAX_GROUP_NUMREGS];
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_utype_t fru_type;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_info_t *fru_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int ac_present;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Avoid mayhem, make sure we have only one timeout thread running.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (scsb_in_postintr)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_wait(&scsb->scsb_cv, &scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_in_postintr = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel scb_post_s = gethrtime();
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x00002000)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_intr(%d)", scsb->scsb_instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel retval = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel tmp_reg = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Only if NOT SSB_PRESENT, check the SCB PROM ID
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state & SCSB_SSB_PRESENT)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scb_check_version(scsb) != DDI_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_SSB_PRESENT &&
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_i2c_errcnt > scsb_err_threshold)
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_failing_event(scsb);
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto intr_error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (IS_SCB_P15) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int_masks = scb_15_int_masks;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int_masks = scb_10_int_masks;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (IS_SCB_P15) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel intr_addr = SCSB_REG_ADDR(SCTRL_INTSRC_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* read the interrupt register from scsb */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_rdwr_register(scsb, I2C_WR_RD, intr_addr,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCTRL_INTR_NUMREGS - 1, scb_intr_regs, 1)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "scsb_intr: "
193974072f41a843678abf5f61979c748687e66bSherry Moore " Failed read of interrupt registers.");
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_SSB_PRESENT &&
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_i2c_errcnt > scsb_err_threshold)
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_failing_event(scsb);
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto intr_error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < SCTRL_INTR_NUMREGS; ++i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel retval |= scb_intr_regs[i]; /* Quick INTSRC check */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x08000000) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (tmp_reg || scb_intr_regs[i]) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_intr: INTSRC%d=0x%x",
193974072f41a843678abf5f61979c748687e66bSherry Moore i + 1, scb_intr_regs[i]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ++tmp_reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (retval == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto intr_error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel retval = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (IS_SCB_P15) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int iid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel iid = SCSB_REG_INDEX(intr_addr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel offset = FRU_OFFSET(SCTRL_EVENT_SCB, SCTRL_INTPTR_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel tmp_reg = SCSB_REG_ADDR(SCTRL_INTSRC_SCB_P15);
03831d35f7499c87d51205817c93e9a8d42c4baestevel intr_idx = SCSB_REG_INDEX(tmp_reg) - iid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel clr_bits = 1 << offset;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scb_intr_regs[intr_idx] & clr_bits) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Must be newly inserted SCB
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Time to re-initialize.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x00023000) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_intr(%d): INIT_SCB INT",
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_restore(scsb);
03831d35f7499c87d51205817c93e9a8d42c4baestevel retval |= (SCSB_INTR_CLAIMED | SCSB_INTR_EVENT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * scsb_write_mask(scsb, tmp_reg, 0, clr_bits, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * scb_intr_regs[intr_idx] &= ~clr_bits;
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel offset = FRU_OFFSET(SCTRL_EVENT_PWRDWN,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCTRL_INTPTR_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel clr_bits = 1 << offset;
03831d35f7499c87d51205817c93e9a8d42c4baestevel intr_reg = scb_intr_regs[intr_idx];
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (intr_reg & clr_bits) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < scsb_shutdown_count; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel drv_usecwait(1000);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_rdwr_register(scsb, I2C_WR_RD, tmp_reg,
193974072f41a843678abf5f61979c748687e66bSherry Moore 1, &intr_reg, 1)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "Failed to read "
193974072f41a843678abf5f61979c748687e66bSherry Moore " interrupt register");
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto intr_error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x08000000) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_intr: "
193974072f41a843678abf5f61979c748687e66bSherry Moore " INTSRC6[%d]=0x%x", i,
193974072f41a843678abf5f61979c748687e66bSherry Moore intr_reg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(intr_reg & clr_bits)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scb_intr_regs[intr_idx] &= ~clr_bits;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (retval == 0 && scsb_check_config_status(scsb)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_intr: Failed read of config/status registers");
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_P06_NOINT_KLUGE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!scsb_debug) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto intr_error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_SSB_PRESENT &&
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_i2c_errcnt > scsb_err_threshold) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_failing_event(scsb);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Allow to go on so we clear the INTSRC bits
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Read the board healthy registers here, if any of the healthy
03831d35f7499c87d51205817c93e9a8d42c4baestevel * interrupts are set.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (IS_SCB_P15) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel intr_idx = intr_reg = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel intr_addr = SCSB_REG_ADDR(SCTRL_INTSRC_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel index = SCSB_REG_INDEX(intr_addr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < SCTRL_BHLTHY_NUMREGS; ++i, ++intr_idx) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_data_reg[index++] =
193974072f41a843678abf5f61979c748687e66bSherry Moore scb_intr_regs[intr_idx] & int_masks[intr_idx];
03831d35f7499c87d51205817c93e9a8d42c4baestevel intr_reg |= scb_intr_regs[i];
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (intr_reg && scsb_read_bhealthy(scsb) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "%s#%d: Error Reading Healthy# "
193974072f41a843678abf5f61979c748687e66bSherry Moore " Registers", ddi_driver_name(scsb->scsb_dev),
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_get_instance(scsb->scsb_dev));
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_SSB_PRESENT &&
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_i2c_errcnt > scsb_err_threshold) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_failing_event(scsb);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto intr_error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (IS_SCB_P15) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_rdwr_register(scsb, I2C_WR, intr_addr,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCTRL_INTR_NUMREGS, scb_intr_regs, 1)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "scsb_intr: Failed write to interrupt"
193974072f41a843678abf5f61979c748687e66bSherry Moore " registers.");
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_SSB_PRESENT &&
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_i2c_errcnt > scsb_err_threshold) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_failing_event(scsb);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto intr_error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * At this point, all interrupt source registers are read.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We only handle interrups which are not masked
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < SCTRL_INTR_NUMREGS; ++i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scb_intr_regs[i] &= int_masks[i];
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel retval |= SCSB_INTR_CLAIMED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* store config status data */
03831d35f7499c87d51205817c93e9a8d42c4baestevel tmp_reg = SCSB_REG_ADDR(SCTRL_SYSCFG_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel index = SCSB_REG_INDEX(tmp_reg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < SCTRL_CFG_NUMREGS; ++i)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cstatus_regs[i] = scsb->scsb_data_reg[index + i];
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_event_code = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel clr_bits = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel intr_idx = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel numregs = SCTRL_INTR_NUMREGS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel index = SCSB_REG_INDEX(intr_addr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If SCB 1.5, adjust some variables to skip the SCTRL_BHLTHY_REGS
03831d35f7499c87d51205817c93e9a8d42c4baestevel * which will be handled last in this function.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (IS_SCB_P15) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = SCTRL_BHLTHY_NUMREGS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel intr_idx += i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel intr_addr += i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel index += i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 *
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel offset_base = FRU_OFFSET_BASE(SCTRL_INTPTR_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (offset = 0; intr_idx < numregs;
193974072f41a843678abf5f61979c748687e66bSherry Moore ++offset, ++intr_idx, ++intr_addr, ++index) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_data_reg[index] = scb_intr_regs[intr_idx];
03831d35f7499c87d51205817c93e9a8d42c4baestevel intr_reg = scb_intr_regs[intr_idx];
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (intr_reg) { /* for each INTSRC bit that's set */
03831d35f7499c87d51205817c93e9a8d42c4baestevel int j;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint16_t ui;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t uc;
03831d35f7499c87d51205817c93e9a8d42c4baestevel idx = event_to_index((uint32_t)intr_reg); /* offset */
03831d35f7499c87d51205817c93e9a8d42c4baestevel code = (1 << idx); /* back to bit mask */
03831d35f7499c87d51205817c93e9a8d42c4baestevel clr_bits |= code;
03831d35f7499c87d51205817c93e9a8d42c4baestevel intr_reg = intr_reg & ~code; /* clear this one */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (j = 0; j < MCT_MAX_FRUS; ++j) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel uc = scb_fru_offset[offset_base + j];
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (offset != ((uc >> 4) & 0xf)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (IS_SCB_P10)
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (j != FRU_INDEX(SCTRL_EVENT_SCB))
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (offset != ((uc >> 4) & 0xf)
193974072f41a843678abf5f61979c748687e66bSherry Moore + SCB_INT_OFFSET)
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (idx == (uc & 0xf))
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (uc == 0xff) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * bit idx not recognized, check another.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We found the fru_offset[] entry, now use the index
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to get the event code.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel code = (uint32_t)(1 << j);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x00002000) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_intr: code=0x%x", code);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Now check for the NON-FRU type events.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (code == SCTRL_EVENT_PWRDWN) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x1002) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_intr(%d): power down req."
193974072f41a843678abf5f61979c748687e66bSherry Moore " INT.", scsb->scsb_instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_event_code |= code;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_OPEN &&
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_rq != (queue_t *)NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * inform applications using poll(2)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * about this event, and provide the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * event code to EnvMon scsb policy
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb_debug & 0x00040000))
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) scsb_queue_put(scsb->scsb_rq, 1,
193974072f41a843678abf5f61979c748687e66bSherry Moore &scsb_event_code, "scsb_intr");
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto intr_error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (code == SCTRL_EVENT_REPLACE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x1002) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_intr(%d): replacement "
193974072f41a843678abf5f61979c748687e66bSherry Moore "req. INT.",
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_freeze_check(scsb);
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_freeze(scsb);
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_event_code |= code;
03831d35f7499c87d51205817c93e9a8d42c4baestevel retval |= (SCSB_INTR_CLAIMED | SCSB_INTR_EVENT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (code == SCTRL_EVENT_SCB) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int tmp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Must be newly inserted SCB
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Time to re-initialize.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x1002) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_intr(%d): INIT SCB INTR",
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * scsb_restore(scsb);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The INTSRC bit is already cleared,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * so we won't do it again.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel tmp = FRU_OFFSET(SCTRL_EVENT_SCB,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCTRL_INTPTR_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel clr_bits &= ~(1 << tmp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_event_code |= code;
03831d35f7499c87d51205817c93e9a8d42c4baestevel retval |= (SCSB_INTR_CLAIMED | SCSB_INTR_EVENT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (code == SCTRL_EVENT_ALARM_INT) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * P0.6/P1.0: SCTRL_INTR_ALARM_INT is always
03831d35f7499c87d51205817c93e9a8d42c4baestevel * set and cannot be cleared, so ignore it.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!IS_SCB_P15) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x1002) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_intr(%d): Alarm INT.",
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_event_code |= code;
03831d35f7499c87d51205817c93e9a8d42c4baestevel retval |= (SCSB_INTR_CLAIMED | SCSB_INTR_EVENT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * XXX:
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if ((ui = event_to_type(code)) == 0xffff) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * FRU type not found
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check for special processing
03831d35f7499c87d51205817c93e9a8d42c4baestevel * now that we found the FRU type.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_type = (scsb_utype_t)(ui & 0xff);
03831d35f7499c87d51205817c93e9a8d42c4baestevel unit = (ui >> 8) & 0xff;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x00002000) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_intr: "
193974072f41a843678abf5f61979c748687e66bSherry Moore "FRU type/unit/code %d/%d/0x%x",
193974072f41a843678abf5f61979c748687e66bSherry Moore fru_type, unit, code);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (fru_type) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case PDU:
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case PS:
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DISK:
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case FAN:
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SSB:
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case CFTM:
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case CRTM:
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case PRTM:
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SLOT:
03831d35f7499c87d51205817c93e9a8d42c4baestevel slotnum = tonga_ssl_to_psl(scsb, unit);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x00002000) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_intr: "
193974072f41a843678abf5f61979c748687e66bSherry Moore "unit/slot %d/%d",
193974072f41a843678abf5f61979c748687e66bSherry Moore unit, slotnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If the slot number is not valid, continue.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_IS_TONGA) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (slotnum > TG_MAX_SLOTS ||
193974072f41a843678abf5f61979c748687e66bSherry Moore slotnum == SC_TG_CPU_SLOT) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * For a tonga, we need to return
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the code corresponding to the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * actual physical slot
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel code = FRU_UNIT_TO_EVCODE(SLOT,
193974072f41a843678abf5f61979c748687e66bSherry Moore slotnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (slotnum > MC_MAX_SLOTS ||
193974072f41a843678abf5f61979c748687e66bSherry Moore slotnum == SC_MC_CPU_SLOT ||
193974072f41a843678abf5f61979c748687e66bSherry Moore (scsb->scsb_hsc_state &
193974072f41a843678abf5f61979c748687e66bSherry Moore SCSB_HSC_CTC_PRES &&
193974072f41a843678abf5f61979c748687e66bSherry Moore slotnum == SC_MC_CTC_SLOT)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* FALLTHROUGH */
03831d35f7499c87d51205817c93e9a8d42c4baestevel case ALARM:
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * INDENT CHEATING, 2 indentations
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ac_present = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (fru_type == ALARM) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUG2("AC Intr %d(%d)\n", scsb->ac_slotnum, idx+1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel val = scsb_fru_op(scsb, SLOT,
193974072f41a843678abf5f61979c748687e66bSherry Moore tonga_ssl_to_psl(scsb, scsb->ac_slotnum),
193974072f41a843678abf5f61979c748687e66bSherry Moore SCTRL_SYSCFG_BASE, SCSB_FRU_OP_GET_BITVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ac_present = scsb_fru_op(scsb, ALARM, 1,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCTRL_SYSCFG_BASE,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCSB_FRU_OP_GET_BITVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((((val) && (!ac_present)) ||
193974072f41a843678abf5f61979c748687e66bSherry Moore ((!val) && (ac_present))) &&
193974072f41a843678abf5f61979c748687e66bSherry Moore (scsb->scsb_hsc_state &
193974072f41a843678abf5f61979c748687e66bSherry Moore SCSB_AC_SLOT_INTR_DONE))
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "?Alarm and Slot presence "
193974072f41a843678abf5f61979c748687e66bSherry Moore "state bits do not match! (%x,%x)",
193974072f41a843678abf5f61979c748687e66bSherry Moore val, ac_present);
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_hsc_state & SCSB_AC_SLOT_INTR_DONE)
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_hsc_state &= ~SCSB_AC_SLOT_INTR_DONE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_hsc_state |= SCSB_AC_SLOT_INTR_DONE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break; /* we break and wait for slot interrupt. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cPCI slot interrupt event
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_IS_TONGA) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (slotnum > TG_MAX_SLOTS ||
193974072f41a843678abf5f61979c748687e66bSherry Moore slotnum == SC_TG_CPU_SLOT) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (slotnum > MC_MAX_SLOTS ||
193974072f41a843678abf5f61979c748687e66bSherry Moore slotnum == SC_MC_CPU_SLOT ||
193974072f41a843678abf5f61979c748687e66bSherry Moore (scsb->scsb_hsc_state & SCSB_HSC_CTC_PRES &&
193974072f41a843678abf5f61979c748687e66bSherry Moore slotnum == SC_MC_CTC_SLOT)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_is_alarm_card_slot(scsb, slotnum) == B_TRUE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUG2("AC slot Intr %d(%d)\n", slotnum, idx+1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ac_slot = B_TRUE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel val = scsb_fru_op(scsb, SLOT, unit, SCTRL_SYSCFG_BASE,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCSB_FRU_OP_GET_BITVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ac_slot == B_TRUE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ac_present = scsb_fru_op(scsb, ALARM, 1,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCTRL_SYSCFG_BASE,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCSB_FRU_OP_GET_BITVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((((val) && (!ac_present)) ||
193974072f41a843678abf5f61979c748687e66bSherry Moore ((!val) && (ac_present))) &&
193974072f41a843678abf5f61979c748687e66bSherry Moore (scsb->scsb_hsc_state &
193974072f41a843678abf5f61979c748687e66bSherry Moore SCSB_AC_SLOT_INTR_DONE)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "?Alarm and Slot presence "
193974072f41a843678abf5f61979c748687e66bSherry Moore "state bits do not match! (%x,%x)",
193974072f41a843678abf5f61979c748687e66bSherry Moore val, ac_present);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_hsc_state & SCSB_AC_SLOT_INTR_DONE)
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_hsc_state &= ~SCSB_AC_SLOT_INTR_DONE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_hsc_state |= SCSB_AC_SLOT_INTR_DONE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (val) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ac_present) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUG1("AC insertion on slot %d!\n", slotnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x00010000) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_intr: "
193974072f41a843678abf5f61979c748687e66bSherry Moore "AC_PRES slot %d", slotnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_hsc_state |= SCSB_ALARM_CARD_PRES;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifndef lint
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUG1("IO Insertion on slot %d!\n", slotnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) scsb_connect_slot(scsb, slotnum, B_FALSE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((ac_slot == B_TRUE) &&
193974072f41a843678abf5f61979c748687e66bSherry Moore (scsb->scsb_hsc_state & SCSB_ALARM_CARD_PRES)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUG1("AC Removal on slot %d!\n", slotnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x00010000) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_intr: "
193974072f41a843678abf5f61979c748687e66bSherry Moore "!AC_PRES slot %d",
193974072f41a843678abf5f61979c748687e66bSherry Moore slotnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_hsc_state &= ~SCSB_ALARM_CARD_PRES;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifndef lint
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUG1("IO Removal on slot %d!\n", slotnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) scsb_disconnect_slot(scsb, B_FALSE, slotnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * END INDENT CHEATING, 2 indentations
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ERROR: Did not find cause of INTSRC bit
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x00000002) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_intr: FRU type %d"
193974072f41a843678abf5f61979c748687e66bSherry Moore " not recognized", fru_type);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_event_code |= code;
03831d35f7499c87d51205817c93e9a8d42c4baestevel retval |= (SCSB_INTR_CLAIMED | SCSB_INTR_EVENT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (fru_type == SLOT)
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr = mct_system_info.fru_info_list[fru_type];
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (; fru_ptr != NULL; fru_ptr = fru_ptr->next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (unit != fru_ptr->fru_unit)
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (fru_ptr->i2c_info == NULL ||
193974072f41a843678abf5f61979c748687e66bSherry Moore (tmp_reg = fru_ptr->i2c_info->
193974072f41a843678abf5f61979c748687e66bSherry Moore ledata_reg) == 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = scsb_set_scfg_pres_leds(scsb, fru_ptr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "scsb_intr(): "
193974072f41a843678abf5f61979c748687e66bSherry Moore "I2C write error to 0x%x",
193974072f41a843678abf5f61979c748687e66bSherry Moore tmp_reg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state &
193974072f41a843678abf5f61979c748687e66bSherry Moore SCSB_DEBUG_MODE)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto intr_error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (clr_bits) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel clr_bits = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check for SCB 1.5 interrupt for SLOT HEALTHY changes
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel clr_bits = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel intr_idx = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel numregs = SCTRL_INTR_NUMREGS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel intr_addr = SCSB_REG_ADDR(SCTRL_INTSRC_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel index = SCSB_REG_INDEX(intr_addr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (IS_SCB_P15) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < SCTRL_BHLTHY_NUMREGS;
193974072f41a843678abf5f61979c748687e66bSherry Moore ++i, ++intr_idx, ++intr_addr) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_data_reg[index++] = scb_intr_regs[intr_idx];
03831d35f7499c87d51205817c93e9a8d42c4baestevel intr_reg = scb_intr_regs[i];
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (intr_reg) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel idx = event_to_index((uint32_t)intr_reg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel code = (1 << idx);
03831d35f7499c87d51205817c93e9a8d42c4baestevel clr_bits |= code;
03831d35f7499c87d51205817c93e9a8d42c4baestevel intr_reg = intr_reg & ~code;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* idx + 1 because bit 0 is for Slot 1 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel slotnum = tonga_ssl_to_psl(scsb, idx + 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_IS_TONGA) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (slotnum > TG_MAX_SLOTS ||
193974072f41a843678abf5f61979c748687e66bSherry Moore slotnum == SC_TG_CPU_SLOT) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (slotnum > MC_MAX_SLOTS ||
193974072f41a843678abf5f61979c748687e66bSherry Moore slotnum == SC_MC_CPU_SLOT ||
193974072f41a843678abf5f61979c748687e66bSherry Moore (scsb->scsb_hsc_state &
193974072f41a843678abf5f61979c748687e66bSherry Moore SCSB_HSC_CTC_PRES &&
193974072f41a843678abf5f61979c748687e66bSherry Moore slotnum == SC_MC_CTC_SLOT)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_healthy_intr(scsb, slotnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (clr_bits) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel clr_bits = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel code = scsb_event_code;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (retval & SCSB_INTR_EVENT &&
193974072f41a843678abf5f61979c748687e66bSherry Moore !(scsb->scsb_state & SCSB_P06_NOINT_KLUGE)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel check_fru_info(scsb, code);
03831d35f7499c87d51205817c93e9a8d42c4baestevel add_event_code(scsb, code);
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) scsb_queue_ops(scsb, QPUT_INT32, 1, &scsb_event_code,
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_intr");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevelintr_error:
03831d35f7499c87d51205817c93e9a8d42c4baestevel scb_post_e = gethrtime();
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x8000000)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "Summary of times in nsec: pre_time %llu, \
03831d35f7499c87d51205817c93e9a8d42c4baestevel post_time %llu", scb_pre_e - scb_pre_s,
193974072f41a843678abf5f61979c748687e66bSherry Moore scb_post_e - scb_post_s);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_in_postintr = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_broadcast(&scsb->scsb_cv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Re-enable interrupt now.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) scsb_toggle_psmint(scsb, 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state &= ~SCSB_IN_INTR;
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_polled_int(scsb_state_t *scsb, int cmd, uint32_t *set)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x4000)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_polled_int(scsb,0x%x)", cmd);
03831d35f7499c87d51205817c93e9a8d42c4baestevel *set = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cmd == SCSBIOC_SHUTDOWN_POLL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EINVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cmd != SCSBIOC_INTEVENT_POLL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EINVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_P06_NOINT_KLUGE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * scsb_intr() may modify scsb_event_code
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_event_code = SCTRL_EVENT_NONE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) scsb_intr((caddr_t)scsb);
03831d35f7499c87d51205817c93e9a8d42c4baestevel *set = scsb_event_code;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_event_code = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SCSB_P06_INTR_ON, we know there was an event
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and we're retrieving the event code from the event FIFO.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel *set = get_event_code();
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x01004000) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_polled_int: event_code = 0x%x", *set);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_leds_switch(scsb_state_t *scsb, scsb_ustate_t op)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel register int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int index;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t reg, idata, rwbuf[SCTRL_MAX_GROUP_NUMREGS];
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_FROZEN &&
193974072f41a843678abf5f61979c748687e66bSherry Moore !(scsb->scsb_state & SCSB_IN_INTR)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EAGAIN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0101) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_leds_switch(%s):",
193974072f41a843678abf5f61979c748687e66bSherry Moore op == ON ? "ON" : "OFF");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Step 1: turn ON/OFF all NOK LEDs. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0100) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb%d: turning all NOK LEDs %s",
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_instance,
193974072f41a843678abf5f61979c748687e66bSherry Moore op == ON ? "ON" : "OFF");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (op == ON)
03831d35f7499c87d51205817c93e9a8d42c4baestevel idata = 0xff;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else /* off */
03831d35f7499c87d51205817c93e9a8d42c4baestevel idata = 0x00;
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = SCSB_REG_ADDR(SCTRL_LED_NOK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel index = SCSB_REG_INDEX(reg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < SCTRL_LED_NOK_NUMREGS; ++i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel rwbuf[i] = idata;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_data_reg[index + i] = idata;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = scsb_rdwr_register(scsb, I2C_WR, reg, SCTRL_LED_NOK_NUMREGS,
193974072f41a843678abf5f61979c748687e66bSherry Moore rwbuf, 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0102)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "scsb_leds_switch(): "
193974072f41a843678abf5f61979c748687e66bSherry Moore "Failed to turn %s NOK LEDs",
193974072f41a843678abf5f61979c748687e66bSherry Moore op == ON ? "ON" : "OFF");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Step 2: turn ON/OFF all OK LEDs. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0100) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb%d: turning all OK LEDs %s",
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_instance,
193974072f41a843678abf5f61979c748687e66bSherry Moore op == ON ? "ON" : "OFF");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = SCSB_REG_ADDR(SCTRL_LED_OK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel index = SCSB_REG_INDEX(reg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < SCTRL_LED_OK_NUMREGS; ++i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel rwbuf[i] = idata;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_data_reg[index + i] = idata;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = scsb_rdwr_register(scsb, I2C_WR, reg, SCTRL_LED_OK_NUMREGS,
193974072f41a843678abf5f61979c748687e66bSherry Moore rwbuf, 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0102)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "scsb_leds_switch(): "
193974072f41a843678abf5f61979c748687e66bSherry Moore "Failed to turn %s NOK LEDs",
193974072f41a843678abf5f61979c748687e66bSherry Moore op == ON ? "ON" : "OFF");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Step 3: turn OFF all BLINK LEDs. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (op == OFF) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = SCSB_REG_ADDR(SCTRL_BLINK_OK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel index = SCSB_REG_INDEX(reg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < SCTRL_BLINK_NUMREGS; ++i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel rwbuf[i] = idata;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_data_reg[index + i] = idata;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = scsb_rdwr_register(scsb, I2C_WR, reg, SCTRL_BLINK_NUMREGS,
193974072f41a843678abf5f61979c748687e66bSherry Moore rwbuf, 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0102)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "scsb_leds_switch(): "
193974072f41a843678abf5f61979c748687e66bSherry Moore "Failed to turn %s BLINK BITs",
193974072f41a843678abf5f61979c748687e66bSherry Moore op == ON ? "ON" : "OFF");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_readall_regs(scsb_state_t *scsb)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int index;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb_debug & 0x40000000))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0005) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_readall_regs:");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_FROZEN) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EAGAIN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = SCSB_REG_ADDR_START; /* 1st register in set */
03831d35f7499c87d51205817c93e9a8d42c4baestevel index = SCSB_REG_INDEX(reg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = scsb_rdwr_register(scsb, I2C_WR_RD, reg, SCSB_DATA_REGISTERS,
193974072f41a843678abf5f61979c748687e66bSherry Moore &scsb->scsb_data_reg[index], 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_write_mask(scsb_state_t *scsb,
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t reg,
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t rmask,
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t on_mask,
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t off_mask)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2c_transfer_t *i2cxferp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int index, error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t reg_data;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0800) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_write_mask(,%x,,%x,%x):",
193974072f41a843678abf5f61979c748687e66bSherry Moore reg, on_mask, off_mask);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_FROZEN &&
193974072f41a843678abf5f61979c748687e66bSherry Moore !(scsb->scsb_state & SCSB_IN_INTR)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EAGAIN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* select the register address and read the register */
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2cxferp = (i2c_transfer_t *)scsb->scsb_i2ctp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2cxferp->i2c_flags = I2C_WR_RD;
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2cxferp->i2c_wlen = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2cxferp->i2c_rlen = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2cxferp->i2c_wbuf[0] = reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2cxferp->i2c_rbuf[0] = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_kstat_flag = B_TRUE; /* we did a i2c transaction */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error = nct_i2c_transfer(scsb->scsb_phandle, i2cxferp)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EIO;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto wm_error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_i2c_errcnt = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0800)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_write_mask() read 0x%x",
193974072f41a843678abf5f61979c748687e66bSherry Moore i2cxferp->i2c_rbuf[0]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg_data = i2cxferp->i2c_rbuf[0];
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rmask)
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg_data &= rmask;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (off_mask)
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg_data &= ~off_mask;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (on_mask)
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg_data |= on_mask;
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2cxferp->i2c_flags = I2C_WR;
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2cxferp->i2c_wlen = 2;
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2cxferp->i2c_wbuf[0] = reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2cxferp->i2c_wbuf[1] = reg_data;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error = nct_i2c_transfer(scsb->scsb_phandle, i2cxferp)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EIO;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto wm_error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* keep shadow registers updated */
03831d35f7499c87d51205817c93e9a8d42c4baestevel index = SCSB_REG_INDEX(reg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_data_reg[index] = reg_data;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0800)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_write_mask() wrote 0x%x", reg_data);
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_i2c_errcnt = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevelwm_error:
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_i2c_errcnt++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_i2c_errcnt > scsb_err_threshold)
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_err_flag = B_TRUE; /* latch error */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_SSB_PRESENT) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0802)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_write_mask(): reg %x %s error, data=%x",
193974072f41a843678abf5f61979c748687e66bSherry Moore reg,
193974072f41a843678abf5f61979c748687e66bSherry Moore i2cxferp->i2c_flags & I2C_WR ? "write" : "read",
193974072f41a843678abf5f61979c748687e66bSherry Moore i2cxferp->i2c_flags & I2C_WR ?
193974072f41a843678abf5f61979c748687e66bSherry Moore i2cxferp->i2c_wbuf[1] : i2cxferp->i2c_rbuf[0]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_i2c_errcnt >= scsb_freeze_count)
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_freeze(scsb);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EAGAIN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * read/write len consecutive single byte registers to/from rbuf
03831d35f7499c87d51205817c93e9a8d42c4baestevel * NOTE: should be called with mutex held
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_rdwr_register(scsb_state_t *scsb, int op, uchar_t reg, int len,
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t *rwbuf, int i2c_alloc)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2c_transfer_t *i2cxferp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i, rlen, wlen, index, error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0800) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_rdwr_register(scsb,%s,%x,%x,buf):",
193974072f41a843678abf5f61979c748687e66bSherry Moore (op == I2C_WR) ? "write" : "read", reg, len);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_FROZEN &&
193974072f41a843678abf5f61979c748687e66bSherry Moore !(scsb->scsb_state & SCSB_IN_INTR)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EAGAIN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (i2c_alloc) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2cxferp = scsb_alloc_i2ctx(scsb->scsb_phandle, I2C_NOSLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (i2cxferp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0042)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "scsb_rdwr_register: "
193974072f41a843678abf5f61979c748687e66bSherry Moore "i2ctx allocation failure");
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ENOMEM);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2cxferp = scsb->scsb_i2ctp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel index = SCSB_REG_INDEX(reg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (op) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case I2C_WR:
03831d35f7499c87d51205817c93e9a8d42c4baestevel wlen = len + 1; /* add the address */
03831d35f7499c87d51205817c93e9a8d42c4baestevel rlen = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2cxferp->i2c_wbuf[0] = reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < len; ++i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_data_reg[index + i] =
193974072f41a843678abf5f61979c748687e66bSherry Moore i2cxferp->i2c_wbuf[1 + i] = rwbuf[i];
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0080)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "scsb_rdwr_register: writing rwbuf[%d]=0x%x",
193974072f41a843678abf5f61979c748687e66bSherry Moore i, rwbuf[i]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case I2C_WR_RD:
03831d35f7499c87d51205817c93e9a8d42c4baestevel wlen = 1; /* for the address */
03831d35f7499c87d51205817c93e9a8d42c4baestevel rlen = len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2cxferp->i2c_wbuf[0] = reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (i2c_alloc)
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_free_i2ctx(scsb->scsb_phandle, i2cxferp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EINVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* select the register address */
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2cxferp->i2c_flags = op;
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2cxferp->i2c_rlen = rlen;
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2cxferp->i2c_wlen = wlen;
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2cxferp->i2c_wbuf[0] = reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_kstat_flag = B_TRUE; /* we did a i2c transaction */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error = nct_i2c_transfer(scsb->scsb_phandle, i2cxferp)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EIO;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (rlen) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* copy to rwbuf[] and keep shadow registers updated */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < len; ++i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_data_reg[index + i] = rwbuf[i] =
193974072f41a843678abf5f61979c748687e66bSherry Moore i2cxferp->i2c_rbuf[i];
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0080)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "scsb_rdwr_register: read rwbuf[%d]=0x%x",
193974072f41a843678abf5f61979c748687e66bSherry Moore i, rwbuf[i]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (i2c_alloc)
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_free_i2ctx(scsb->scsb_phandle, i2cxferp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_i2c_errcnt++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_i2c_errcnt > scsb_err_threshold)
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_err_flag = B_TRUE; /* latch error */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state & SCSB_SSB_PRESENT)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_i2c_errcnt >= scsb_freeze_count)
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_freeze(scsb);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EAGAIN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_rdwr_register(): I2C read error from %x",
193974072f41a843678abf5f61979c748687e66bSherry Moore reg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_i2c_errcnt = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelcheck_fru_info(scsb_state_t *scsb, int evcode)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct scsb_cb_entry *cbe_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_info_t *fru_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_id_t fru_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_fru_status_t fru_status;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i, new_evcode;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x00100001)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "check_fru_info(scsb,0x%x)", evcode);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (evcode == 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = event_to_index((uint32_t)evcode);
03831d35f7499c87d51205817c93e9a8d42c4baestevel new_evcode = evcode & ~(1 << i);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (i > MCT_MAX_FRUS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x00100000)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "check_fru_info: index %d out of range", i);
03831d35f7499c87d51205817c93e9a8d42c4baestevel check_fru_info(scsb, new_evcode);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_id = fru_id_table[i];
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr = find_fru_info(fru_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (fru_ptr == (fru_info_t *)NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel check_fru_info(scsb, new_evcode);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel update_fru_info(scsb, fru_ptr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (fru_ptr->fru_status & FRU_PRESENT) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_status = FRU_PRESENT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_status = FRU_NOT_PRESENT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (fru_ptr->fru_type == SSB) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * WARN against SCB removal if any
03831d35f7499c87d51205817c93e9a8d42c4baestevel * occupied slots are in reset
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_freeze_check(scsb);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * check for an entry in the CallBack table
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (cbe_ptr = scsb_cb_table; cbe_ptr != NULL;
193974072f41a843678abf5f61979c748687e66bSherry Moore cbe_ptr = cbe_ptr->cb_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cbe_ptr->cb_fru_id == fru_id &&
193974072f41a843678abf5f61979c748687e66bSherry Moore cbe_ptr->cb_fru_ptr == fru_ptr) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x00800000)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "check_fru_info: callback for FRU_ID "
193974072f41a843678abf5f61979c748687e66bSherry Moore "0x%x; device is %spresent",
193974072f41a843678abf5f61979c748687e66bSherry Moore (int)fru_id,
193974072f41a843678abf5f61979c748687e66bSherry Moore fru_status == FRU_PRESENT ?
193974072f41a843678abf5f61979c748687e66bSherry Moore "" : "not ");
03831d35f7499c87d51205817c93e9a8d42c4baestevel (*cbe_ptr->cb_func)(
193974072f41a843678abf5f61979c748687e66bSherry Moore cbe_ptr->cb_softstate_ptr,
193974072f41a843678abf5f61979c748687e66bSherry Moore cbe_ptr->cb_event,
193974072f41a843678abf5f61979c748687e66bSherry Moore fru_status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel check_fru_info(scsb, new_evcode);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * -----------------------------
03831d35f7499c87d51205817c93e9a8d42c4baestevel * scsb kstat support functions.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * -----------------------------
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Create and initialize the kstat data structures
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_alloc_kstats(scsb_state_t *scsb)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel kstat_named_t *kn;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * scsb_ks_leddata_t for "scsb_leddata"
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x00080001)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_alloc_kstats: create scsb_leddata: %lu bytes",
193974072f41a843678abf5f61979c748687e66bSherry Moore sizeof (scsb_ks_leddata_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((scsb->ks_leddata = kstat_create(scsb_name, scsb->scsb_instance,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCSB_KS_LEDDATA, "misc", KSTAT_TYPE_RAW,
193974072f41a843678abf5f61979c748687e66bSherry Moore sizeof (scsb_ks_leddata_t), KSTAT_FLAG_PERSISTENT))
193974072f41a843678abf5f61979c748687e66bSherry Moore == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state |= SCSB_KSTATS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_free_kstats(scsb);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->ks_leddata->ks_update = update_ks_leddata;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->ks_leddata->ks_private = (void *)scsb;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (update_ks_leddata(scsb->ks_leddata, KSTAT_READ) != DDI_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state |= SCSB_KSTATS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_free_kstats(scsb);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel kstat_install(scsb->ks_leddata);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * scsb_ks_state_t for "scsb_state"
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x00080000)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_alloc_kstats: create scsb_state: %lu bytes",
193974072f41a843678abf5f61979c748687e66bSherry Moore sizeof (scsb_ks_state_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((scsb->ks_state = kstat_create(scsb_name, scsb->scsb_instance,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCSB_KS_STATE, "misc", KSTAT_TYPE_RAW,
193974072f41a843678abf5f61979c748687e66bSherry Moore sizeof (scsb_ks_state_t), KSTAT_FLAG_PERSISTENT))
193974072f41a843678abf5f61979c748687e66bSherry Moore == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state |= SCSB_KSTATS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_free_kstats(scsb);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->ks_state->ks_update = update_ks_state;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->ks_state->ks_private = (void *)scsb;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (update_ks_state(scsb->ks_state, KSTAT_READ) != DDI_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state |= SCSB_KSTATS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_free_kstats(scsb);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel kstat_install(scsb->ks_state);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mct_topology_t for "env_topology"
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x00080000)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_alloc_kstats: create env_toploogy: %lu bytes",
193974072f41a843678abf5f61979c748687e66bSherry Moore sizeof (mct_topology_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((scsb->ks_topology = kstat_create(scsb_name, scsb->scsb_instance,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCSB_KS_TOPOLOGY, "misc", KSTAT_TYPE_RAW,
193974072f41a843678abf5f61979c748687e66bSherry Moore sizeof (mct_topology_t), KSTAT_FLAG_PERSISTENT))
193974072f41a843678abf5f61979c748687e66bSherry Moore == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state |= SCSB_KSTATS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_free_kstats(scsb);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->ks_topology->ks_update = update_ks_topology;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->ks_topology->ks_private = (void *)scsb;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (update_ks_topology(scsb->ks_topology, KSTAT_READ) != DDI_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state |= SCSB_KSTATS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_free_kstats(scsb);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel kstat_install(scsb->ks_topology);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * kstat_named_t * 2 for "scsb_evc_register"
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x00080001)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "scsb_alloc_kstats: create scsb_evc_register: %lu bytes",
193974072f41a843678abf5f61979c748687e66bSherry Moore sizeof (kstat_named_t) * 2);
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 scsb->scsb_state |= SCSB_KSTATS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_free_kstats(scsb);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->ks_evcreg->ks_update = update_ks_evcreg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->ks_evcreg->ks_private = (void *)scsb;
03831d35f7499c87d51205817c93e9a8d42c4baestevel kn = KSTAT_NAMED_PTR(scsb->ks_evcreg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel kstat_named_init(&kn[0], "pid_register", KSTAT_DATA_INT64);
03831d35f7499c87d51205817c93e9a8d42c4baestevel kstat_named_init(&kn[1], "pid_unregister", KSTAT_DATA_INT64);
03831d35f7499c87d51205817c93e9a8d42c4baestevel kstat_install(scsb->ks_evcreg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Done, set the flag for scsb_detach() and other checks
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state |= SCSB_KSTATS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelupdate_ks_leddata(kstat_t *ksp, int rw)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_state_t *scsb;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_ks_leddata_t *pks_leddata;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i, numregs, index, error = DDI_SUCCESS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb = (scsb_state_t *)ksp->ks_private;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x00080001)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "update_ks_leddata: KS_UPDATE%sset",
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_state & SCSB_KS_UPDATE ? " " : " not ");
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * if (scsb->scsb_state & SCSB_FROZEN) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * }
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rw == KSTAT_WRITE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EACCES);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (scsb->scsb_state & SCSB_KS_UPDATE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cv_wait_sig(&scsb->scsb_cv, &scsb->scsb_mutex) <= 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EINTR);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state |= SCSB_KS_UPDATE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x00080001)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "update_ks_leddata: updating data");
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_leddata = (scsb_ks_leddata_t *)ksp->ks_data;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* NOK */
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = SCSB_REG_ADDR(SCTRL_LED_NOK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel index = SCSB_REG_INDEX(reg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel numregs = SCTRL_LED_NOK_NUMREGS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (IS_SCB_P15)
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = tonga_slotnum_led_shift(scsb, scsb->scsb_data_reg[index]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = scsb->scsb_data_reg[index];
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_leddata->scb_led_regs[i] = reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (++i, ++index; i < numregs; ++i, ++index)
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_leddata->scb_led_regs[i] = scsb->scsb_data_reg[index];
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* OK */
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = SCSB_REG_ADDR(SCTRL_LED_OK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel index = SCSB_REG_INDEX(reg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel numregs += SCTRL_LED_OK_NUMREGS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (IS_SCB_P15)
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = tonga_slotnum_led_shift(scsb, scsb->scsb_data_reg[index]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = scsb->scsb_data_reg[index];
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_leddata->scb_led_regs[i] = reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (++i, ++index; i < numregs; ++i, ++index)
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_leddata->scb_led_regs[i] = scsb->scsb_data_reg[index];
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* BLINK */
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = SCSB_REG_ADDR(SCTRL_BLINK_OK_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel index = SCSB_REG_INDEX(reg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel numregs += SCTRL_BLINK_NUMREGS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (IS_SCB_P15)
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = tonga_slotnum_led_shift(scsb, scsb->scsb_data_reg[index]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = scsb->scsb_data_reg[index];
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_leddata->scb_led_regs[i] = reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (++i, ++index; i < numregs; ++i, ++index)
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_leddata->scb_led_regs[i] = scsb->scsb_data_reg[index];
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state &= ~SCSB_KS_UPDATE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_signal(&scsb->scsb_cv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x00080001)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "update_ks_leddata: returning");
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelupdate_ks_evcreg(kstat_t *ksp, int rw)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_state_t *scsb;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel kstat_named_t *kn = KSTAT_NAMED_PTR(ksp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel pid_t pid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb = (scsb_state_t *)ksp->ks_private;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x00080001)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "update_ks_evcreg: %s(%d), KS_UPDATE%sset",
193974072f41a843678abf5f61979c748687e66bSherry Moore rw == KSTAT_READ ? "read" : "write", rw,
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_state & SCSB_KS_UPDATE ? " " : " not ");
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Let this registration succeed
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * if (scsb->scsb_state & SCSB_FROZEN) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * }
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (scsb->scsb_state & SCSB_KS_UPDATE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cv_wait_sig(&scsb->scsb_cv, &scsb->scsb_mutex) <= 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EINTR);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state |= SCSB_KS_UPDATE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rw == KSTAT_READ) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel kn[0].value.i64 = (int64_t)0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel kn[1].value.i64 = (int64_t)0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (rw == KSTAT_WRITE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * kn[0] is "pid_register", kn[1] is "pid_unregister"
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (kn[0].value.i64 != 0 && kn[1].value.i64 == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel pid = (pid_t)kn[0].value.i64;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (add_event_proc(scsb, pid)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x02000002) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "update_ks_evcreg: "
193974072f41a843678abf5f61979c748687e66bSherry Moore "process add failed for %d",
193974072f41a843678abf5f61979c748687e66bSherry Moore pid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EOVERFLOW;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (kn[0].value.i64 == 0 && kn[1].value.i64 != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel pid = (pid_t)kn[1].value.i64;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (del_event_proc(scsb, pid)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x02000000) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "update_ks_evcreg: "
193974072f41a843678abf5f61979c748687e66bSherry Moore "process delete failed for %d",
193974072f41a843678abf5f61979c748687e66bSherry Moore pid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EOVERFLOW;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (kn[0].value.i64 == 0 && kn[1].value.i64 == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * rewind the pointers and counts, zero the table.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel rew_event_proc(scsb);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state &= ~SCSB_KS_UPDATE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_signal(&scsb->scsb_cv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelupdate_ks_state(kstat_t *ksp, int rw)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_state_t *scsb;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_ks_state_t *pks_state;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error = DDI_SUCCESS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t current_evc;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb = (scsb_state_t *)ksp->ks_private;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x00080001)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "update_ks_state: KS_UPDATE%sset",
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_state & SCSB_KS_UPDATE ? " " : " not ");
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Let this succeed based on last known data
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * if (scsb->scsb_state & SCSB_FROZEN) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * }
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rw == KSTAT_WRITE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EACCES);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (scsb->scsb_state & SCSB_KS_UPDATE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cv_wait_sig(&scsb->scsb_cv, &scsb->scsb_mutex) <= 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EINTR);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state |= SCSB_KS_UPDATE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state & SCSB_SSB_PRESENT) &&
193974072f41a843678abf5f61979c748687e66bSherry Moore !(scsb->scsb_state & SCSB_FROZEN)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t data;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Read the SCB PROM ID */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (data = scsb_rdwr_register(scsb, I2C_WR_RD,
193974072f41a843678abf5f61979c748687e66bSherry Moore (uchar_t)SCTRL_PROM_VERSION, 1, &data, 1))
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x00080002)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "update_ks_state: SCB/I2C "
193974072f41a843678abf5f61979c748687e66bSherry Moore "failure %d", data);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_state = (scsb_ks_state_t *)ksp->ks_data;
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->scsb_state & SCSB_DEBUG_MODE)
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_state->scsb_mode = (uint8_t)ENVC_DEBUG_MODE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else if (scsb->scsb_state & SCSB_DIAGS_MODE)
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_state->scsb_mode = (uint8_t)ENVCTRL_DIAG_MODE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_state->scsb_mode = (uint8_t)ENVCTRL_NORMAL_MODE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If scsb_attach() has not completed the kstat installs,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * then there are no event processes to check for.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_KSTATS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (check_event_procs(&current_evc)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case EVC_NO_EVENT_CODE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_state->event_code = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case EVC_NEW_EVENT_CODE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* FALLTHROUGH */
03831d35f7499c87d51205817c93e9a8d42c4baestevel case EVC_NO_CURR_PROC:
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_state->event_code = current_evc;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case EVC_OR_EVENT_CODE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_state->event_code |= current_evc;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case EVC_FAILURE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_state->event_code = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = DDI_FAILURE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_state->event_code = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state &= ~SCSB_KS_UPDATE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_signal(&scsb->scsb_cv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelupdate_ks_topology(kstat_t *ksp, int rw)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_state_t *scsb;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mct_topology_t *pks_topo;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_info_t *fru_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i, val, error = DDI_SUCCESS, slotnum;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb = (scsb_state_t *)ksp->ks_private;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x00080001)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "update_ks_topology: KS_UPDATE%sset",
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_state & SCSB_KS_UPDATE ? " " : " not ");
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Let this succeed based on last known data
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * if (scsb->scsb_state & SCSB_FROZEN) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel * return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * }
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rw == KSTAT_WRITE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EACCES);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (scsb->scsb_state & SCSB_KS_UPDATE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cv_wait_sig(&scsb->scsb_cv, &scsb->scsb_mutex) <= 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EINTR);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state |= SCSB_KS_UPDATE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state & SCSB_SSB_PRESENT) &&
193974072f41a843678abf5f61979c748687e66bSherry Moore !(scsb->scsb_state & SCSB_FROZEN)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t data;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Read the SCB PROM ID */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (data = scsb_rdwr_register(scsb, I2C_WR_RD,
193974072f41a843678abf5f61979c748687e66bSherry Moore (uchar_t)SCTRL_PROM_VERSION, 1, &data, 1))
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x00080002)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "update_ks_topology: SCB/I2C "
193974072f41a843678abf5f61979c748687e66bSherry Moore "failure %d", data);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo = (mct_topology_t *)ksp->ks_data;
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = SLOT; i < SCSB_UNIT_TYPES; ++i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->max_units[i] = mct_system_info.max_units[i];
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mid_plane.fru_status = FRU_PRESENT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mid_plane.fru_unit = (scsb_unum_t)1;
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 pks_topo->mid_plane.fru_health = MCT_HEALTH_OK;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr = mct_system_info.fru_info_list[SLOT];
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_type = fru_ptr->fru_type;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_slots[i].fru_unit = fru_ptr->fru_unit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_slots[i].fru_id = fru_ptr->fru_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_slots[i].fru_version = fru_ptr->fru_version;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * XXX: need to check healthy regs to set fru_health
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel slotnum = tonga_psl_to_ssl(scsb, i+1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel val = scsb_fru_op(scsb, SLOT, slotnum, SCTRL_BHLTHY_BASE,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCSB_FRU_OP_GET_BITVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_slots[i].fru_health = (val) ?
193974072f41a843678abf5f61979c748687e66bSherry Moore MCT_HEALTH_OK : MCT_HEALTH_NOK;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr = mct_system_info.fru_info_list[PDU];
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_type = fru_ptr->fru_type;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_pdu[i].fru_unit = fru_ptr->fru_unit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_pdu[i].fru_id = fru_ptr->fru_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_pdu[i].fru_version = fru_ptr->fru_version;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_pdu[i].fru_health = MCT_HEALTH_NA;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr = mct_system_info.fru_info_list[PS];
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_type = fru_ptr->fru_type;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_ps[i].fru_unit = fru_ptr->fru_unit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_ps[i].fru_id = fru_ptr->fru_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_ps[i].fru_version = fru_ptr->fru_version;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_ps[i].fru_health = MCT_HEALTH_NA;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr = mct_system_info.fru_info_list[DISK];
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_type = fru_ptr->fru_type;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_disk[i].fru_unit = fru_ptr->fru_unit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_disk[i].fru_id = fru_ptr->fru_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_disk[i].fru_version = fru_ptr->fru_version;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_disk[i].fru_health = MCT_HEALTH_NA;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr = mct_system_info.fru_info_list[FAN];
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_type = fru_ptr->fru_type;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_fan[i].fru_unit = fru_ptr->fru_unit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_fan[i].fru_id = fru_ptr->fru_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_fan[i].fru_version = fru_ptr->fru_version;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_fan[i].fru_health = MCT_HEALTH_NA;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr = mct_system_info.fru_info_list[SCB];
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_type = fru_ptr->fru_type;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_scb[i].fru_unit = fru_ptr->fru_unit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_scb[i].fru_id = fru_ptr->fru_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_scb[i].fru_version = fru_ptr->fru_version;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * To get the scsb health, if there was no i2c transaction
03831d35f7499c87d51205817c93e9a8d42c4baestevel * until this read, generate an i2c transaction.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_kstat_flag == B_FALSE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t data;
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) scsb_blind_read(scsb, I2C_WR_RD,
193974072f41a843678abf5f61979c748687e66bSherry Moore (uchar_t)SCTRL_PROM_VERSION, 1, &data, 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_scb[i].fru_health = ((scsb->scsb_err_flag ==
193974072f41a843678abf5f61979c748687e66bSherry Moore B_TRUE || scsb->scsb_i2c_errcnt > scsb_err_threshold)
193974072f41a843678abf5f61979c748687e66bSherry Moore ? MCT_HEALTH_NOK : MCT_HEALTH_OK);
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (pks_topo->mct_scb[i].fru_health == MCT_HEALTH_NOK)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "SCSB kstat health:%d", pks_topo->
193974072f41a843678abf5f61979c748687e66bSherry Moore mct_scb[i].fru_health);
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_err_flag = B_FALSE; /* clear error flag once read */
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_kstat_flag = B_FALSE; /* false? read from i2c */
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr = mct_system_info.fru_info_list[SSB];
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_type = fru_ptr->fru_type;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_ssb[i].fru_unit = fru_ptr->fru_unit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_ssb[i].fru_id = fru_ptr->fru_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_ssb[i].fru_version = fru_ptr->fru_version;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_ssb[i].fru_health = MCT_HEALTH_NA;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr = mct_system_info.fru_info_list[ALARM];
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_type = fru_ptr->fru_type;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_alarm[i].fru_unit = fru_ptr->fru_unit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_alarm[i].fru_id = fru_ptr->fru_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_alarm[i].fru_version = fru_ptr->fru_version;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_alarm[i].fru_health = MCT_HEALTH_NA;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr = mct_system_info.fru_info_list[CFTM];
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_type = fru_ptr->fru_type;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_cftm[i].fru_unit = fru_ptr->fru_unit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_cftm[i].fru_id = fru_ptr->fru_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_cftm[i].fru_version = fru_ptr->fru_version;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_cftm[i].fru_health = MCT_HEALTH_NA;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr = mct_system_info.fru_info_list[CRTM];
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_type = fru_ptr->fru_type;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_crtm[i].fru_unit = fru_ptr->fru_unit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_crtm[i].fru_id = fru_ptr->fru_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_crtm[i].fru_version = fru_ptr->fru_version;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_crtm[i].fru_health = MCT_HEALTH_NA;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr = mct_system_info.fru_info_list[PRTM];
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_type = fru_ptr->fru_type;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_prtm[i].fru_unit = fru_ptr->fru_unit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_prtm[i].fru_id = fru_ptr->fru_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_prtm[i].fru_version = fru_ptr->fru_version;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pks_topo->mct_prtm[i].fru_health = MCT_HEALTH_NA;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state &= ~SCSB_KS_UPDATE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_signal(&scsb->scsb_cv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_free_kstats(scsb_state_t *scsb)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state & SCSB_KSTATS))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * free the allocated kstat data
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->ks_evcreg != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel kstat_delete(scsb->ks_evcreg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->ks_topology != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel kstat_delete(scsb->ks_topology);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->ks_state != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel kstat_delete(scsb->ks_state);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->ks_leddata != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel kstat_delete(scsb->ks_leddata);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->ks_leddata = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->ks_state = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->ks_topology = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->ks_evcreg = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state &= ~SCSB_KSTATS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * --------------------------------------
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Miscellaneous scsb internal functions.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * --------------------------------------
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * allocate I2C transfer structure
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic i2c_transfer_t *
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_alloc_i2ctx(i2c_client_hdl_t phandle, uint_t sleep)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2c_transfer_t *tp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (i2c_transfer_alloc(phandle, &tp, SCSB_DATA_REGISTERS + 2,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCSB_DATA_REGISTERS + 2, sleep) == I2C_FAILURE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (tp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * free I2C transfer structure
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_free_i2ctx(i2c_client_hdl_t phandle, i2c_transfer_t *tp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2c_transfer_free(phandle, tp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelupdate_fru_info(scsb_state_t *scsb, fru_info_t *fru_ptr)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int index;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t reg, bit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_info_t *acslot_ptr = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_id_t acslot_id = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x00100001)
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki cmn_err(CE_NOTE, "update_fru_info(scsb,0x%p)", (void *)fru_ptr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (fru_ptr == (fru_info_t *)NULL ||
193974072f41a843678abf5f61979c748687e66bSherry Moore fru_ptr->i2c_info == (fru_i2c_info_t *)NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (fru_ptr->fru_id == fru_id_table[FRU_INDEX(SCTRL_EVENT_ALARM)]) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SCTRL_EVENT_SLOT1 == 0x01 so
03831d35f7499c87d51205817c93e9a8d42c4baestevel * fru_id_table[] index for Slot 1 == 0
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel acslot_id = fru_id_table[(scsb->ac_slotnum - 1)];
03831d35f7499c87d51205817c93e9a8d42c4baestevel acslot_ptr = find_fru_info(acslot_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = fru_ptr->i2c_info->syscfg_reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel bit = fru_ptr->i2c_info->syscfg_bit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (reg == 0 && fru_ptr->fru_type == SCB) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_SCB_PRESENT)
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_status = FRU_PRESENT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_status = FRU_NOT_PRESENT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (reg) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel index = SCSB_REG_INDEX(reg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_data_reg[index] & (1 << bit)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_status = FRU_PRESENT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * XXX: need to add version register, and maybe a
03831d35f7499c87d51205817c93e9a8d42c4baestevel * method, to the fru_ptr->i2c_info structure.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * fru_ptr->fru_version = (fru_version_t)0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * if (acslot_ptr != NULL && acslot_ptr->fru_status ==
03831d35f7499c87d51205817c93e9a8d42c4baestevel * FRU_PRESENT)
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (acslot_ptr != NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel acslot_ptr->fru_type = (scsb_utype_t)OC_AC;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel fru_ptr->fru_status = FRU_NOT_PRESENT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * fru_ptr->fru_version = (fru_version_t)0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (acslot_ptr != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* AC just removed, but AC Slot is occupied? */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (acslot_ptr->fru_status == FRU_PRESENT)
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* for now it's unknown */
03831d35f7499c87d51205817c93e9a8d42c4baestevel acslot_ptr->fru_type =
193974072f41a843678abf5f61979c748687e66bSherry Moore (scsb_utype_t)OC_UNKN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel acslot_ptr->fru_type =
193974072f41a843678abf5f61979c748687e66bSherry Moore (scsb_utype_t)OC_UNKN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x00100000)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "update_fru_info: type %d unit %d is %spresent",
193974072f41a843678abf5f61979c748687e66bSherry Moore fru_ptr->fru_type, fru_ptr->fru_unit,
193974072f41a843678abf5f61979c748687e66bSherry Moore fru_ptr->fru_status == FRU_PRESENT
193974072f41a843678abf5f61979c748687e66bSherry Moore ? "" : "not ");
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Convert EVENT code to FRU index
03831d35f7499c87d51205817c93e9a8d42c4baestevel * by finding the highest bit number in 32 bit word
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelevent_to_index(uint32_t evcode)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (evcode == 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (MCT_MAX_FRUS - 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (; (evcode >>= 1); i++)
03831d35f7499c87d51205817c93e9a8d42c4baestevel ;
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (i);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_debug_prnt(char *fmt, uintptr_t a1, uintptr_t a2, uintptr_t a3,
03831d35f7499c87d51205817c93e9a8d42c4baestevel uintptr_t a4, uintptr_t a5)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x8000 ||
193974072f41a843678abf5f61979c748687e66bSherry Moore (*fmt == 'X' && scsb_debug & 0x00010000)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (*fmt == 'X')
03831d35f7499c87d51205817c93e9a8d42c4baestevel ++fmt;
03831d35f7499c87d51205817c93e9a8d42c4baestevel prom_printf("scsb: ");
03831d35f7499c87d51205817c93e9a8d42c4baestevel prom_printf(fmt, a1, a2, a3, a4, a5);
03831d35f7499c87d51205817c93e9a8d42c4baestevel prom_printf("\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Send signal to processes registered for event code delivery
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelsignal_evc_procs(scsb_state_t *scsb)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i = 0, c = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (evc_proc_count == 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (; i < EVC_PROCS_MAX; ++i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (evc_procs[i] != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (proc_signal(evc_procs[i], SIGPOLL)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x02000002)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb:signal_evc_procs: "
193974072f41a843678abf5f61979c748687e66bSherry Moore "signal to %d failed",
193974072f41a843678abf5f61979c748687e66bSherry Moore ((struct pid *)
193974072f41a843678abf5f61979c748687e66bSherry Moore evc_procs[i])->pid_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) del_event_proc(scsb,
193974072f41a843678abf5f61979c748687e66bSherry Moore ((struct pid *)evc_procs[i])->pid_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (++c >= evc_proc_count) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x02000000) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "signal_evc_procs: signaled "
193974072f41a843678abf5f61979c748687e66bSherry Moore "%d/%d processes", c,
193974072f41a843678abf5f61979c748687e66bSherry Moore evc_proc_count);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * bump FIFO ptr, taking care of wrap around
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic uint32_t *
03831d35f7499c87d51205817c93e9a8d42c4baestevelinc_fifo_ptr(uint32_t *ptr)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (++ptr >= evc_fifo + EVC_FIFO_SIZE)
03831d35f7499c87d51205817c93e9a8d42c4baestevel ptr = evc_fifo;
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ptr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelreset_evc_fifo(scsb_state_t *scsb)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel evc_wptr = evc_fifo;
03831d35f7499c87d51205817c93e9a8d42c4baestevel evc_rptr = evc_fifo;
03831d35f7499c87d51205817c93e9a8d42c4baestevel evc_fifo_count = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveladd_event_code(scsb_state_t *scsb, uint32_t event_code)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (event_proc_count(scsb) == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel *evc_wptr = event_code;
03831d35f7499c87d51205817c93e9a8d42c4baestevel evc_wptr = inc_fifo_ptr(evc_wptr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (++evc_fifo_count > EVC_FIFO_SIZE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel --evc_fifo_count; /* lose the oldest event */
03831d35f7499c87d51205817c93e9a8d42c4baestevel evc_rptr = inc_fifo_ptr(evc_rptr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x01000000) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "add_event_code: 0x%x, FIFO size = %d",
193974072f41a843678abf5f61979c748687e66bSherry Moore event_code, evc_fifo_count);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel signal_evc_procs(scsb);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * called from check_event_procs() when the last registered process
03831d35f7499c87d51205817c93e9a8d42c4baestevel * retrieved the oldest event
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic uint32_t
03831d35f7499c87d51205817c93e9a8d42c4baesteveldel_event_code()
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t evc = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!evc_fifo_count)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (scsb_event_code);
03831d35f7499c87d51205817c93e9a8d42c4baestevel evc = *evc_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel evc_rptr = inc_fifo_ptr(evc_rptr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel --evc_fifo_count;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x01000000) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "del_event_code: 0x%x, FIFO size = %d",
193974072f41a843678abf5f61979c748687e66bSherry Moore evc, evc_fifo_count);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (evc);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * called from check_event_procs() to retrieve the current event code
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic uint32_t
03831d35f7499c87d51205817c93e9a8d42c4baestevelget_event_code()
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!evc_fifo_count)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (*evc_rptr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 * return:
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 0 = event_proc was added
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 1 = out of space
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveladd_event_proc(scsb_state_t *scsb, pid_t pid)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel void *curr_proc;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pid_t curr_pid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (evc_proc_count >= EVC_PROCS_MAX)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel curr_proc = proc_ref();
03831d35f7499c87d51205817c93e9a8d42c4baestevel curr_pid = (pid_t)(((struct pid *)curr_proc)->pid_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (curr_pid != pid) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x02000000) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "add_event_proc: current %d != requestor %d",
193974072f41a843678abf5f61979c748687e66bSherry Moore curr_pid, pid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel proc_unref(curr_proc);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (; i < EVC_PROCS_MAX; ++i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (evc_procs[i] == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel evc_procs[i] = curr_proc;
03831d35f7499c87d51205817c93e9a8d42c4baestevel evc_proc_count++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x02000000) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "add_event_proc: %d; evc_proc_count=%d",
193974072f41a843678abf5f61979c748687e66bSherry Moore pid, evc_proc_count);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel proc_unref(curr_proc);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * called from an application interface (ie: an ioctl command)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to unregister a process id interested in SCB events.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * return:
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 0 = event_proc was deleted
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 1 = event_proc was not found, or table was empty
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveldel_event_proc(scsb_state_t *scsb, pid_t pid)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int cnt = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel void *this_proc;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (evc_proc_count == 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (; i < EVC_PROCS_MAX; ++i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (evc_procs[i] == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel this_proc = evc_procs[i];
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (pid == ((struct pid *)this_proc)->pid_id) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel evc_procs[i] = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (--evc_proc_count == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * reset evc fifo cound and pointers
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel reset_evc_fifo(scsb);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x02000000) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "del_event_proc: %d; evc_proc_count=%d",
193974072f41a843678abf5f61979c748687e66bSherry Moore pid, evc_proc_count);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel proc_unref(this_proc);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (++cnt >= evc_proc_count)
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Can be called from an application interface
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to rewind the pointers and counters, and zero the table
03831d35f7499c87d51205817c93e9a8d42c4baestevel * return:
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelrew_event_proc(scsb_state_t *scsb)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x02000001) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "rew_event_proc: evc_proc_count=%d",
193974072f41a843678abf5f61979c748687e66bSherry Moore evc_proc_count);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (; i < EVC_PROCS_MAX; ++i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (evc_procs[i] != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel proc_unref(evc_procs[i]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel evc_procs[i] = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel evc_proc_count = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelevent_proc_count(scsb_state_t *scsb)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (evc_proc_count);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * return:
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 1 = pid was found
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 0 = pid was not found, or table was empty
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelfind_evc_proc(pid_t pid)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int cnt = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (evc_proc_count == 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (; i < EVC_PROCS_MAX; ++i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (evc_procs[i] == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (pid == ((struct pid *)evc_procs[i])->pid_id)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (++cnt >= evc_proc_count)
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 * return:
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelcheck_event_procs(uint32_t *return_evc)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel void *curr_proc;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pid_t curr_pid = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int return_val = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel static int evc_requests = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get current process handle, and check the event_procs table
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (evc_proc_count == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel *return_evc = del_event_code();
03831d35f7499c87d51205817c93e9a8d42c4baestevel return_val = EVC_NO_CURR_PROC;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel curr_proc = proc_ref();
03831d35f7499c87d51205817c93e9a8d42c4baestevel curr_pid = ((struct pid *)curr_proc)->pid_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel proc_unref(curr_proc);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!find_evc_proc(curr_pid)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel *return_evc = get_event_code();
03831d35f7499c87d51205817c93e9a8d42c4baestevel return_val = EVC_NO_CURR_PROC;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (++evc_requests >= evc_proc_count) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel evc_requests = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel *return_evc = del_event_code();
03831d35f7499c87d51205817c93e9a8d42c4baestevel return_val = EVC_NEW_EVENT_CODE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel *return_evc = get_event_code();
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!return_val)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return_val = EVC_OR_EVENT_CODE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x02000000) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "check_event_procs: pid=%d, evc=0x%x, "
193974072f41a843678abf5f61979c748687e66bSherry Moore "requests=%d, returning 0x%x", curr_pid,
193974072f41a843678abf5f61979c748687e66bSherry Moore *return_evc, evc_requests, return_val);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (return_val);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_queue_put(queue_t *rq, int count, uint32_t *data, char *caller)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel mblk_t *mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x4001) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_queue_put(0x%p, %d, 0x%x, %s)",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void *)rq, count, *data, caller);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp = allocb(sizeof (uint32_t) * count, BPRI_HI);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "%s: allocb failed",
193974072f41a843678abf5f61979c748687e66bSherry Moore caller);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (B_FALSE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (count--) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel *((uint32_t *)mp->b_wptr) = *data;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->b_wptr += sizeof (*data);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ++data;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel putnext(rq, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (B_TRUE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* CLONE */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_queue_ops(scsb_state_t *scsb,
03831d35f7499c87d51205817c93e9a8d42c4baestevel int op,
03831d35f7499c87d51205817c93e9a8d42c4baestevel int oparg,
03831d35f7499c87d51205817c93e9a8d42c4baestevel void *opdata,
03831d35f7499c87d51205817c93e9a8d42c4baestevel char *caller)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel clone_dev_t *clptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int clone, find_open, find_available, retval = QOP_FAILED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (op) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case QPUT_INT32:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_opens && scsb->scsb_rq != NULL &&
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb_queue_put(scsb->scsb_rq, oparg,
193974072f41a843678abf5f61979c748687e66bSherry Moore (uint32_t *)opdata, caller) == B_FALSE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (QOP_FAILED);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*FALLTHROUGH*/ /* to look for opened clones */
03831d35f7499c87d51205817c93e9a8d42c4baestevel case QPROCSOFF:
03831d35f7499c87d51205817c93e9a8d42c4baestevel retval = QOP_OK;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*FALLTHROUGH*/
03831d35f7499c87d51205817c93e9a8d42c4baestevel case QFIRST_OPEN:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case QFIND_QUEUE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel find_open = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel find_available = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case QFIRST_AVAILABLE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel find_available = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel find_open = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (clone = SCSB_CLONES_FIRST; clone < SCSB_CLONES_MAX; clone++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel clptr = &scsb->clone_devs[clone];
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (find_open && clptr->cl_flags & SCSB_OPEN) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (clptr->cl_rq == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "%s: Clone %d has no queue",
193974072f41a843678abf5f61979c748687e66bSherry Moore caller, clptr->cl_minor);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (QOP_FAILED);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (op) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case QPROCSOFF:
03831d35f7499c87d51205817c93e9a8d42c4baestevel qprocsoff(clptr->cl_rq);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case QPUT_INT32:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_queue_put(clptr->cl_rq, oparg,
193974072f41a843678abf5f61979c748687e66bSherry Moore (uint32_t *)opdata, caller)
193974072f41a843678abf5f61979c748687e66bSherry Moore == B_FALSE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel retval = QOP_FAILED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case QFIRST_OPEN:
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (clone);
03831d35f7499c87d51205817c93e9a8d42c4baestevel case QFIND_QUEUE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (clptr->cl_rq == (queue_t *)opdata) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (clone);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (find_available && clptr->cl_flags == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (op) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case QFIRST_AVAILABLE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (clone);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (retval);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_fru_op(scsb_state_t *scsb, scsb_utype_t fru_type, int unit, int base,
03831d35f7499c87d51205817c93e9a8d42c4baestevel int op)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rc;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int tmp, idx, code, offset;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#if 0
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = SCSB_REG_ADDR(i);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ac_mask = 1 << FRU_OFFSET(SCTRL_EVENT_ALARM, SCTRL_RESET_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ac_val = scsb->scsb_data_reg[index+1] & ac_mask;
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* get the event code based on which we get the reg and bit offsets */
03831d35f7499c87d51205817c93e9a8d42c4baestevel code = FRU_UNIT_TO_EVCODE(fru_type, unit);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* get the bit offset in the 8bit register corresponding to the event */
03831d35f7499c87d51205817c93e9a8d42c4baestevel offset = FRU_OFFSET(code, base);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* register offset from the base register, based on the event code */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((fru_type == ALARM) && (base == SCTRL_RESET_BASE))
03831d35f7499c87d51205817c93e9a8d42c4baestevel tmp = ALARM_RESET_REG_INDEX(code, base);
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel tmp = FRU_REG_INDEX(code, base);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* get the global offset of the register in the parent address space */
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = SCSB_REG_ADDR(tmp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* get the global index of the register in this SCSB's address space */
03831d35f7499c87d51205817c93e9a8d42c4baestevel idx = SCSB_REG_INDEX(reg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUG4("scsb_fru_op(start): code=%x, offset=%x, tmp=%x, reg=%x\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore code, offset, tmp, reg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (op) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCSB_FRU_OP_GET_REG:
03831d35f7499c87d51205817c93e9a8d42c4baestevel rc = reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCSB_FRU_OP_GET_BITVAL:
03831d35f7499c87d51205817c93e9a8d42c4baestevel rc = (scsb->scsb_data_reg[idx] & (1 << offset))
193974072f41a843678abf5f61979c748687e66bSherry Moore >> offset;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCSB_FRU_OP_GET_REGDATA:
03831d35f7499c87d51205817c93e9a8d42c4baestevel rc = scsb->scsb_data_reg[idx];
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCSB_FRU_OP_SET_REGBIT:
03831d35f7499c87d51205817c93e9a8d42c4baestevel rc = (1 << offset) & 0xff;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUG4("scsb_fru_op: unit=%x, base=%x, op=%d, rc=%x\n", unit, base,
193974072f41a843678abf5f61979c748687e66bSherry Moore op, rc);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (rc);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_get_slot_state(scsb_state_t *scsb, int pslotnum, int *rstate)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int slotnum, val = 0, rc;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rc = scsb_check_config_status(scsb);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* check if error is because SCB is removed */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((rc != EAGAIN) && (rc != DDI_SUCCESS))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel slotnum = tonga_psl_to_ssl(scsb, pslotnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel val = scsb_fru_op(scsb, SLOT, slotnum, SCTRL_SYSCFG_BASE,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCSB_FRU_OP_GET_BITVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (! val) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel *rstate = HPC_SLOT_EMPTY;
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * now, lets determine if it is connected or disconnected.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If reset is asserted, then the slot is disconnected.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel rc = scsb_reset_slot(scsb, pslotnum, SCSB_GET_SLOT_RESET_STATUS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* check if error is because SCB is removed */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((rc != EAGAIN) && (rc != DDI_SUCCESS))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel val = scsb_fru_op(scsb, SLOT, slotnum, SCTRL_RESET_BASE,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCSB_FRU_OP_GET_BITVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (val)
03831d35f7499c87d51205817c93e9a8d42c4baestevel *rstate = HPC_SLOT_DISCONNECTED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_fru_op(scsb, SLOT, slotnum, SCTRL_BHLTHY_BASE,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCSB_FRU_OP_GET_BITVAL)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel *rstate = HPC_SLOT_CONNECTED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "%s#%d: Reset Not Asserted on "
193974072f41a843678abf5f61979c748687e66bSherry Moore "Healthy# Failed slot %d!",
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_driver_name(scsb->scsb_dev),
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_get_instance(scsb->scsb_dev), slotnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel *rstate = HPC_SLOT_DISCONNECTED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_reset_slot(scsb_state_t *scsb, int pslotnum, int reset_flag)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int slotnum, error, val, alarm_card = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2c_transfer_t *i2cxferp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int index, condition_exists = 0, ac_val;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x8001)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_reset_slot(%d), flag %x", pslotnum,
193974072f41a843678abf5f61979c748687e66bSherry Moore reset_flag);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_FROZEN)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EAGAIN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((i2cxferp = scsb_alloc_i2ctx(scsb->scsb_phandle,
193974072f41a843678abf5f61979c748687e66bSherry Moore I2C_NOSLEEP)) == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ENOMEM);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel slotnum = tonga_psl_to_ssl(scsb, pslotnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_is_alarm_card_slot(scsb, pslotnum) == B_TRUE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUG0("alarm card reset/unreset op:\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel alarm_card = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = SCSB_REG_ADDR(SCTRL_RESET_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel index = SCSB_REG_INDEX(reg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2cxferp->i2c_flags = I2C_WR_RD;
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2cxferp->i2c_rlen = SCTRL_RESET_NUMREGS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2cxferp->i2c_wbuf[0] = reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2cxferp->i2c_wlen = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_kstat_flag = B_TRUE; /* we did an i2c transaction */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((error = nct_i2c_transfer(scsb->scsb_phandle, i2cxferp)) == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_i2c_errcnt = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * XXX: following statements assume 2 reset registers,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * which is the case for our current SCB revisions.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_data_reg[index] = i2cxferp->i2c_rbuf[0];
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_data_reg[index+1] = i2cxferp->i2c_rbuf[1];
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_i2c_errcnt++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_i2c_errcnt > scsb_err_threshold)
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_err_flag = B_TRUE; /* latch until kstat */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state & SCSB_SSB_PRESENT)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_i2c_errcnt >= scsb_freeze_count)
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_freeze(scsb);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "%s#%d: scsb_reset_slot: error"
193974072f41a843678abf5f61979c748687e66bSherry Moore " reading Reset regs\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_driver_name(scsb->scsb_dev),
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_get_instance(scsb->scsb_dev));
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = DDI_FAILURE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUG2("pre-reset regs = %x,%x\n", scsb->scsb_data_reg[index],
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_data_reg[index+1]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((reset_flag == SCSB_GET_SLOT_RESET_STATUS) || (error)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_free_i2ctx(scsb->scsb_phandle, i2cxferp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel val = scsb_fru_op(scsb, SLOT, slotnum, SCTRL_RESET_BASE,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCSB_FRU_OP_GET_BITVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (alarm_card) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ac_val = scsb_fru_op(scsb, ALARM, 1, SCTRL_RESET_BASE,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCSB_FRU_OP_GET_BITVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (val && (reset_flag == SCSB_RESET_SLOT)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (alarm_card) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ac_val) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel condition_exists = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUG0("Alarm_RST# already active.\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifndef lint
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUG1("Alarm_RST# not active! "
193974072f41a843678abf5f61979c748687e66bSherry Moore "Slot%d_RST# active!\n", pslotnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel condition_exists = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUG1("Slot%d_RST# already active!\n", pslotnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((val == 0) && (reset_flag == SCSB_UNRESET_SLOT)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (alarm_card) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!ac_val) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUG0("Alarm_RST# not active.\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel condition_exists = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifndef lint
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUG1("Alarm_RST# active"
193974072f41a843678abf5f61979c748687e66bSherry Moore " Slot%d_RST# not active!\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore pslotnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel condition_exists = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUG1("Slot%d_RST# already not active!\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore pslotnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (! condition_exists) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2cxferp->i2c_flags = I2C_WR;
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2cxferp->i2c_wlen = 2;
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2cxferp->i2c_wbuf[0] = scsb_fru_op(scsb, SLOT, slotnum,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCTRL_RESET_BASE, SCSB_FRU_OP_GET_REG);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (reset_flag == SCSB_RESET_SLOT) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2cxferp->i2c_wbuf[1] =
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb_fru_op(scsb, SLOT, slotnum,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCTRL_RESET_BASE,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCSB_FRU_OP_GET_REGDATA) |
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb_fru_op(scsb, SLOT, slotnum,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCTRL_RESET_BASE,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCSB_FRU_OP_SET_REGBIT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG /* dont reset Alarm Card line unless in debug mode */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (alarm_card)
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2cxferp->i2c_wbuf[1] |=
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb_fru_op(scsb, ALARM, 1,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCTRL_RESET_BASE,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCSB_FRU_OP_SET_REGBIT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2cxferp->i2c_wbuf[1] =
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb_fru_op(scsb, SLOT, slotnum,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCTRL_RESET_BASE,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCSB_FRU_OP_GET_REGDATA) &
193974072f41a843678abf5f61979c748687e66bSherry Moore ~(scsb_fru_op(scsb, SLOT, slotnum,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCTRL_RESET_BASE,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCSB_FRU_OP_SET_REGBIT));
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG /* dont Unreset Alarm Card line unless in debug mode */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (alarm_card)
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2cxferp->i2c_wbuf[1] &=
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb_fru_op(scsb, ALARM, 1,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCTRL_RESET_BASE,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCSB_FRU_OP_SET_REGBIT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error = nct_i2c_transfer(scsb->scsb_phandle, i2cxferp)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_i2c_errcnt++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_i2c_errcnt > scsb_err_threshold)
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_err_flag = B_TRUE; /* latch error */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state & SCSB_SSB_PRESENT)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_i2c_errcnt >= scsb_freeze_count)
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_freeze(scsb);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "%s#%d: reset_slot: error writing to"
193974072f41a843678abf5f61979c748687e66bSherry Moore " Reset regs (op=%d, data=%x)\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_driver_name(scsb->scsb_dev),
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_get_instance(scsb->scsb_dev),
193974072f41a843678abf5f61979c748687e66bSherry Moore reset_flag, i2cxferp->i2c_wbuf[1]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_free_i2ctx(scsb->scsb_phandle, i2cxferp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_i2c_errcnt = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* now read back and update our scsb structure */
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2cxferp->i2c_flags = I2C_WR_RD;
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2cxferp->i2c_rlen = SCTRL_RESET_NUMREGS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2cxferp->i2c_wbuf[0] = reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2cxferp->i2c_wlen = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((error = nct_i2c_transfer(scsb->scsb_phandle,
193974072f41a843678abf5f61979c748687e66bSherry Moore i2cxferp)) == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_i2c_errcnt = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_data_reg[index] = i2cxferp->i2c_rbuf[0];
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_data_reg[index+1] = i2cxferp->i2c_rbuf[1];
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_i2c_errcnt++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_i2c_errcnt > scsb_err_threshold)
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_err_flag = B_TRUE; /* latch error */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_state & SCSB_SSB_PRESENT)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_i2c_errcnt >= scsb_freeze_count)
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_freeze(scsb);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "%s#%d: scsb_reset_slot: error"
193974072f41a843678abf5f61979c748687e66bSherry Moore " reading Reset regs (post reset)\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_driver_name(scsb->scsb_dev),
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_get_instance(scsb->scsb_dev));
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_free_i2ctx(scsb->scsb_phandle, i2cxferp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* XXX: P1.5 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUG2("post-reset regs = %x,%x\n", scsb->scsb_data_reg[index],
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_data_reg[index+1]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel val = scsb_fru_op(scsb, SLOT, slotnum, SCTRL_RESET_BASE,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCSB_FRU_OP_GET_BITVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (alarm_card)
03831d35f7499c87d51205817c93e9a8d42c4baestevel ac_val = scsb_fru_op(scsb, ALARM, 1, SCTRL_RESET_BASE,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCSB_FRU_OP_GET_BITVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (val && (reset_flag == SCSB_UNRESET_SLOT)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "Cannot UnReset Slot %d (reg=%x)\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore pslotnum,
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb_fru_op(scsb, SLOT, slotnum,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCTRL_RESET_BASE,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCSB_FRU_OP_GET_REGDATA));
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (alarm_card) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ac_val)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "Cannot Unreset "
193974072f41a843678abf5f61979c748687e66bSherry Moore "Alarm_RST#.\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((val == 0) && (reset_flag == SCSB_RESET_SLOT)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "Cannot Reset Slot %d, "
193974072f41a843678abf5f61979c748687e66bSherry Moore "reg=%x\n", pslotnum,
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb_fru_op(scsb, SLOT, slotnum,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCTRL_RESET_BASE,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCSB_FRU_OP_GET_REGDATA));
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (alarm_card) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!ac_val)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "Cannot reset "
193974072f41a843678abf5f61979c748687e66bSherry Moore "Alarm_RST#.\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&scsb->scsb_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_free_i2ctx(scsb->scsb_phandle, i2cxferp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_connect_slot(scsb_state_t *scsb, int pslotnum, int healthy)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int slotnum, count = 0, val;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int slot_flag = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel slotnum = tonga_psl_to_ssl(scsb, pslotnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel while ((healthy == B_FALSE) && (count < scsb_healthy_poll_count)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_read_bhealthy(scsb) != 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel val = scsb_fru_op(scsb, SLOT, slotnum, SCTRL_BHLTHY_BASE,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCSB_FRU_OP_GET_BITVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (val) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel healthy = B_TRUE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel count++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drv_usecwait(100); /* cant delay(9f) in intr context */
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (healthy == B_FALSE && count == scsb_healthy_poll_count) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x00004000)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "%s#%d: no HEALTHY# signal on"
193974072f41a843678abf5f61979c748687e66bSherry Moore " slot %d", ddi_driver_name(scsb->scsb_dev),
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_get_instance(scsb->scsb_dev), pslotnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((scsb_is_alarm_card_slot(scsb, pslotnum) == B_TRUE) &&
193974072f41a843678abf5f61979c748687e66bSherry Moore (scsb->scsb_hsc_state & SCSB_ALARM_CARD_PRES))
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot_flag = ALARM_CARD_ON_SLOT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (hsc_slot_occupancy(pslotnum, 1, slot_flag, healthy));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_disconnect_slot(scsb_state_t *scsb, int occupied, int slotnum)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int slot_flag = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Reset is must at extraction. Move on even if failure. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_reset_slot(scsb, slotnum, SCSB_RESET_SLOT) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (occupied == B_TRUE)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((scsb_is_alarm_card_slot(scsb, slotnum) == B_TRUE) &&
193974072f41a843678abf5f61979c748687e66bSherry Moore (scsb->scsb_hsc_state & SCSB_ALARM_CARD_PRES))
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot_flag = ALARM_CARD_ON_SLOT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (hsc_slot_occupancy(slotnum, occupied, slot_flag, B_FALSE));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_is_alarm_card_slot(scsb_state_t *scsb, int slotnum)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel return ((scsb->ac_slotnum == slotnum)? B_TRUE:B_FALSE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_hsc_ac_op(scsb_state_t *scsb, int pslotnum, int op)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rc = B_FALSE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t event_code;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(scsb->scsb_hsc_state & SCSB_HSC_INIT &&
193974072f41a843678abf5f61979c748687e66bSherry Moore scsb->scsb_hsc_state & SCSB_ALARM_CARD_PRES)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb: HSC not initialized or AC not present!");
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (rc);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (op) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* hsc -> scsb */
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCSB_HSC_AC_BUSY:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_hsc_state & SCSB_ALARM_CARD_IN_USE)
03831d35f7499c87d51205817c93e9a8d42c4baestevel rc = B_TRUE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* API -> scsb */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * NOTE: this could be called multiple times from envmond if
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the daemon is reinitialized with SIGHUP, or stopped and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * restarted.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCSB_HSC_AC_SET_BUSY:
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUG0("AC SET BUSY\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x00010000) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_hsc_ac_op(SCSB_HSC_AC_SET_BUSY)");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_hsc_state |= SCSB_ALARM_CARD_IN_USE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel rc = B_TRUE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* hsc -> scsb */
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCSB_HSC_AC_CONFIGURED:
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUG0("AC configured\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x00010000) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "scsb_hsc_ac_op(SCSB_HSC_AC_CONFIGURED)");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * wakeup anyone waiting on AC to be configured
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Send the ALARM_CARD_CONFIGURE Event to all scsb
03831d35f7499c87d51205817c93e9a8d42c4baestevel * open streams.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel event_code = SCTRL_EVENT_ALARM_INSERTION;
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) scsb_queue_ops(scsb, QPUT_INT32, 1,
193974072f41a843678abf5f61979c748687e66bSherry Moore &event_code, "scsb_hsc_ac_op");
03831d35f7499c87d51205817c93e9a8d42c4baestevel rc = B_TRUE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* hsc -> scsb */
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCSB_HSC_AC_REMOVAL_ALERT:
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUG0("AC removal alert\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x00010000) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "scsb_hsc_ac_op(SCSB_HSC_AC_REMOVAL_ALERT)");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Inform (envmond)alarmcard.so that it should save
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the AC configuration, stop the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * heartbeat, and shutdown the RSC link.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel event_code = SCTRL_EVENT_ALARM_REMOVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) scsb_queue_ops(scsb, QPUT_INT32, 1,
193974072f41a843678abf5f61979c748687e66bSherry Moore &event_code, "scsb_hsc_ac_op");
03831d35f7499c87d51205817c93e9a8d42c4baestevel rc = B_TRUE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* API -> scsb -> hsc */
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SCSB_HSC_AC_UNCONFIGURE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUG0("AC unconfigure\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x00010000) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "scsb_hsc_ac_op(SCSB_HSC_AC_UNCONFIG"
193974072f41a843678abf5f61979c748687e66bSherry Moore "URE), AC NOT BUSY");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * send notification back to HSC to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * unconfigure the AC, now that the env monitor
03831d35f7499c87d51205817c93e9a8d42c4baestevel * has given permission to do so.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_hsc_state &= ~SCSB_ALARM_CARD_IN_USE;
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki hsc_ac_op((int)scsb->scsb_instance, pslotnum,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCSB_HSC_AC_UNCONFIGURE, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel rc = B_TRUE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (rc);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_healthy_intr(scsb_state_t *scsb, int pslotnum)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int val, slotnum;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int healthy = B_FALSE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUG1("Healthy Intr on slot %d\n", pslotnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_state & SCSB_IS_TONGA) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (pslotnum > TG_MAX_SLOTS || pslotnum == SC_TG_CPU_SLOT) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x08000000)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "Healthy interrupt bit set for"
193974072f41a843678abf5f61979c748687e66bSherry Moore " slot %d", pslotnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (pslotnum > MC_MAX_SLOTS || pslotnum == SC_MC_CPU_SLOT ||
193974072f41a843678abf5f61979c748687e66bSherry Moore (scsb->scsb_hsc_state & SCSB_HSC_CTC_PRES &&
193974072f41a843678abf5f61979c748687e66bSherry Moore pslotnum == SC_MC_CTC_SLOT)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x08000000)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "Healthy interrupt bit set for"
193974072f41a843678abf5f61979c748687e66bSherry Moore " slot %d", pslotnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The board healthy registers are already read before entering
03831d35f7499c87d51205817c93e9a8d42c4baestevel * this routine
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel slotnum = tonga_psl_to_ssl(scsb, pslotnum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * P1.5. Following works since slots 1 through 8 are in the same reg
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel val = scsb_fru_op(scsb, SLOT, slotnum, SCTRL_BHLTHY_BASE,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCSB_FRU_OP_GET_BITVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (val)
03831d35f7499c87d51205817c93e9a8d42c4baestevel healthy = B_TRUE;
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) scsb_hsc_board_healthy(pslotnum, healthy);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_blind_read(scsb_state_t *scsb, int op, uchar_t reg, int len,
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t *rwbuf, int i2c_alloc)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2c_transfer_t *i2cxferp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i, rlen, wlen, error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0800) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_rdwr_register(scsb,%s,%x,%x,buf):",
193974072f41a843678abf5f61979c748687e66bSherry Moore (op == I2C_WR) ? "write" : "read", reg, len);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (i2c_alloc) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2cxferp = scsb_alloc_i2ctx(scsb->scsb_phandle, I2C_NOSLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (i2cxferp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0042)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "scsb_rdwr_register: "
193974072f41a843678abf5f61979c748687e66bSherry Moore "i2ctx allocation failure");
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ENOMEM);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2cxferp = scsb->scsb_i2ctp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (op) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case I2C_WR:
03831d35f7499c87d51205817c93e9a8d42c4baestevel wlen = len + 1; /* add the address */
03831d35f7499c87d51205817c93e9a8d42c4baestevel rlen = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2cxferp->i2c_wbuf[0] = reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < len; ++i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2cxferp->i2c_wbuf[1 + i] = rwbuf[i];
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0080)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "scsb_rdwr_register: writing rwbuf[%d]=0x%x",
193974072f41a843678abf5f61979c748687e66bSherry Moore i, rwbuf[i]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case I2C_WR_RD:
03831d35f7499c87d51205817c93e9a8d42c4baestevel wlen = 1; /* for the address */
03831d35f7499c87d51205817c93e9a8d42c4baestevel rlen = len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2cxferp->i2c_wbuf[0] = reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (i2c_alloc)
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_free_i2ctx(scsb->scsb_phandle, i2cxferp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EINVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* select the register address */
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2cxferp->i2c_flags = op;
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2cxferp->i2c_rlen = rlen;
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2cxferp->i2c_wlen = wlen;
03831d35f7499c87d51205817c93e9a8d42c4baestevel i2cxferp->i2c_wbuf[0] = reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_kstat_flag = B_TRUE; /* we did a i2c transaction */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error = nct_i2c_transfer(scsb->scsb_phandle, i2cxferp)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EIO;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (rlen) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* copy to rwbuf[] */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < len; ++i) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel rwbuf[i] = i2cxferp->i2c_rbuf[i];
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0080)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "scsb_rdwr_register: read rwbuf[%d]=0x%x",
193974072f41a843678abf5f61979c748687e66bSherry Moore i, rwbuf[i]);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (i2c_alloc)
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb_free_i2ctx(scsb->scsb_phandle, i2cxferp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_i2c_errcnt++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb->scsb_i2c_errcnt > scsb_err_threshold)
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_err_flag = B_TRUE; /* latch error */
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_i2c_errcnt = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_quiesce_psmint(scsb_state_t *scsb)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel register int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t reg, wdata = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t tmp_reg, intr_addr, clr_bits = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error, iid, intr_idx, offset;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
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 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (IS_SCB_P15) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Read INTSRC6 and write back 0x20 in case INIT_SCB is set
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel intr_addr = SCSB_REG_ADDR(SCTRL_INTSRC_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel tmp_reg = SCSB_REG_ADDR(SCTRL_INTSRC_SCB_P15);
03831d35f7499c87d51205817c93e9a8d42c4baestevel iid = SCSB_REG_INDEX(intr_addr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel intr_idx = SCSB_REG_INDEX(tmp_reg) - iid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel offset = FRU_OFFSET(SCTRL_EVENT_SCB, SCTRL_INTPTR_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel clr_bits = 1 << offset;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = scsb_rdwr_register(scsb, I2C_WR_RD, tmp_reg,
193974072f41a843678abf5f61979c748687e66bSherry Moore 1, &scb_intr_regs[intr_idx], 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Now mask the global PSM_INT and write INIT_SCB in case
03831d35f7499c87d51205817c93e9a8d42c4baestevel * this is an INIT_SCB interrupt
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel wdata = 1 << SYS_OFFSET(SCTRL_SYS_SCB_INIT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = SYS_REG_INDEX(SCTRL_SYS_SCB_INIT, SCTRL_SYS_CMD_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = SCSB_REG_ADDR(i);
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = scsb_rdwr_register(scsb, I2C_WR, reg, 1,
193974072f41a843678abf5f61979c748687e66bSherry Moore &wdata, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scb_intr_regs[intr_idx] & clr_bits) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * There is an SCB_INIT interrupt, which we must clear
03831d35f7499c87d51205817c93e9a8d42c4baestevel * first to keep SCB_INIT from keeping PSM_INT asserted.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = scsb_rdwr_register(scsb, I2C_WR, tmp_reg,
193974072f41a843678abf5f61979c748687e66bSherry Moore 1, &clr_bits, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "scsb%d:scsb_quiesce_psmint: "
193974072f41a843678abf5f61979c748687e66bSherry Moore " I2C TRANSFER Failed", scsb->scsb_instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_debug & 0x0006) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "scsb_attach: "
193974072f41a843678abf5f61979c748687e66bSherry Moore " failed to set SCB_INIT");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state &= ~SCSB_PSM_INT_ENABLED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else { /* P1.0 or earlier */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * read the interrupt source registers, and then
03831d35f7499c87d51205817c93e9a8d42c4baestevel * write them back.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* read the interrupt register from scsb */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error = scsb_rdwr_register(scsb, I2C_WR_RD, intr_addr,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCTRL_INTR_NUMREGS, scb_intr_regs, 0)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "scsb_intr: "
193974072f41a843678abf5f61979c748687e66bSherry Moore " Failed read of interrupt registers.");
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state &= ~SCSB_IN_INTR;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Write to the interrupt source registers to stop scsb
03831d35f7499c87d51205817c93e9a8d42c4baestevel * from interrupting.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error = scsb_rdwr_register(scsb, I2C_WR, intr_addr,
193974072f41a843678abf5f61979c748687e66bSherry Moore SCTRL_INTR_NUMREGS, scb_intr_regs, 0)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "scsb_intr: Failed write to interrupt"
193974072f41a843678abf5f61979c748687e66bSherry Moore " registers.");
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state &= ~SCSB_IN_INTR;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Enables or disables the global PSM_INT interrupt for P1.5, depending
03831d35f7499c87d51205817c93e9a8d42c4baestevel * on the flag, flag = 0 => disable, else enable.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelscsb_toggle_psmint(scsb_state_t *scsb, int enable)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t reg, on = 0, rmask = 0x0, off = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (enable == B_TRUE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel on = 1 << SYS_OFFSET(SCTRL_SYS_PSM_INT_ENABLE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel off = 1 << SYS_OFFSET(SCTRL_SYS_PSM_INT_ENABLE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel i = SYS_REG_INDEX(SCTRL_SYS_PSM_INT_ENABLE, SCTRL_SYS_CMD_BASE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel reg = SCSB_REG_ADDR(i);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (scsb_write_mask(scsb, reg, rmask, on, off)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "scsb_toggle_psmint: Cannot turn %s PSM_INT",
193974072f41a843678abf5f61979c748687e66bSherry Moore enable == 1 ? "on" : "off");
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (enable == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state &= ~SCSB_PSM_INT_ENABLED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel scsb->scsb_state |= SCSB_PSM_INT_ENABLED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This routine is to be used by all the drivers using this i2c bus
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to synchronize their transfer operations.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelnct_i2c_transfer(i2c_client_hdl_t i2c_hdl, i2c_transfer_t *i2c_tran)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int retval, initmux = nct_mutex_init;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If scsb interrupt mutex is initialized, also hold the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * interrupt mutex to let the i2c_transfer() to complete
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (initmux & MUTEX_INIT) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(scb_intr_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel retval = i2c_transfer(i2c_hdl, i2c_tran);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (initmux & MUTEX_INIT) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(scb_intr_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (retval);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}