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/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Serengeti CompactPCI Hot Swap Controller Driver.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/types.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/cmn_err.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/kmem.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/errno.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/cpuvar.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/open.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/stat.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/conf.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/ddi.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sunddi.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/modctl.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/ksynch.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/pci.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/serengeti.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sghsc.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/promif.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Debug flags
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint sghsc_configure_ack = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevelint cpci_enable = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define SGHSC_DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef SGHSC_DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevelint sghsc_debug = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DEBUGF(level, args) \
03831d35f7499c87d51205817c93e9a8d42c4baestevel { if (sghsc_debug >= (level)) cmn_err args; }
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DEBUGON sghsc_debug = 3
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DEBUGOFF sghsc_debug = 0
03831d35f7499c87d51205817c93e9a8d42c4baestevel#else
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DEBUGF(level, args) /* nothing */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DEBUGON
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DEBUGOFF
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Global data
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void *sghsc_state; /* soft state */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sghsc_rb_head_t sghsc_rb_header; /* ring buffer header */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Definitions for events thread (outside interrupt context), mutex and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * condition variable.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic kthread_t *sghsc_event_thread;
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic kmutex_t sghsc_event_thread_mutex;
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic kcondvar_t sghsc_event_thread_cv;
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic boolean_t sghsc_event_thread_exit = B_FALSE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct cb_ops sghsc_cb_ops = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodev, /* open */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodev, /* 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, /* prop_op */
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0, /* streamtab */
03831d35f7499c87d51205817c93e9a8d42c4baestevel D_NEW | D_MP, /* Driver compatibility flag */
03831d35f7499c87d51205817c93e9a8d42c4baestevel CB_REV, /* rev */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodev, /* int (*cb_aread)() */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodev /* int (*cb_awrite)() */
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Function prototype for dev_ops
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int sghsc_attach(dev_info_t *, ddi_attach_cmd_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int sghsc_detach(dev_info_t *, ddi_detach_cmd_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct dev_ops sghsc_dev_ops = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEVO_REV, /* devo_rev, */
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0, /* refcnt */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nulldev, /* get_dev_info */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nulldev, /* identify */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nulldev, /* probe */
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc_attach, /* attach */
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc_detach, /* detach */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodev, /* reset */
03831d35f7499c87d51205817c93e9a8d42c4baestevel &sghsc_cb_ops, /* driver operations */
193974072f41a843678abf5f61979c748687e66bSherry Moore (struct bus_ops *)0, /* no bus operations */
193974072f41a843678abf5f61979c748687e66bSherry Moore NULL, /* power */
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_quiesce_not_needed, /* quiesce */
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct modldrv modldrv = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel &mod_driverops,
193974072f41a843678abf5f61979c748687e66bSherry Moore "Serengeti CompactPCI HSC",
03831d35f7499c87d51205817c93e9a8d42c4baestevel &sghsc_dev_ops,
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct modlinkage modlinkage = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel MODREV_1,
03831d35f7499c87d51205817c93e9a8d42c4baestevel &modldrv,
03831d35f7499c87d51205817c93e9a8d42c4baestevel NULL
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Function prototype for HP support
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int sghsc_connect(caddr_t, hpc_slot_t slot, void *, uint_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int sghsc_disconnect(caddr_t, hpc_slot_t, void *, uint_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int sghsc_control(caddr_t, hpc_slot_t, int, caddr_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Function prototypes for internal functions
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int sghsc_register_slots(sghsc_t *, int);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int sghsc_get_slotnum(sghsc_t *, hpc_slot_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int sghsc_scctl(int, int, int, int, int *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void sghsc_freemem(sghsc_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic hpc_slot_t sghsc_find_sloth(int, int, int);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sghsc_t *sghsc_find_softstate(int, int, int);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int sghsc_led_state(sghsc_t *, hpc_slot_t, int, hpc_led_info_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void sghsc_rb_setup(sghsc_rb_head_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void sghsc_rb_teardown(sghsc_rb_head_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int sghsc_rb_get(sghsc_rb_head_t *, sghsc_event_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int sghsc_rb_put(sghsc_rb_head_t *, sghsc_event_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Patchable timeout value
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint sghsc_mbx_timeout = SGHSC_MBX_TIMEOUT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Data for self-identification. This will help enumerate all soft states.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int sghsc_maxinst;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Six slot boat and four slot boats are different in topology (slot to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * bus assignment) and here we should have 2 separate maps (the first 3
03831d35f7499c87d51205817c93e9a8d42c4baestevel * slots have the same topology). The map is in the "delta" form. Logical
03831d35f7499c87d51205817c93e9a8d42c4baestevel * slots correspond to indexes in the map.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sdesc_t four_slot_wib_bd[] = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0, 6, 1, HPC_SLOT_TYPE_CPCI, /* logical/physical slot 0 - Schizo0/A */
03831d35f7499c87d51205817c93e9a8d42c4baestevel 1, 0, 2, 0, /* logical/physical slot 1 - paroli2 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel 1, 0, 0, 0, /* logical/physical slot 2 - paroli0 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0, 7, 1, HPC_SLOT_TYPE_CPCI /* logical/physical slot 3 - Schizo0/B */
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sdesc_t four_slot_bd[] = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0, 6, 1, HPC_SLOT_TYPE_CPCI, /* logical/physical slot 0 - Schizo0/A */
03831d35f7499c87d51205817c93e9a8d42c4baestevel 1, 6, 1, HPC_SLOT_TYPE_CPCI, /* logical/physical slot 1 - Schizo1/A */
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0, 7, 1, HPC_SLOT_TYPE_CPCI, /* logical/physical slot 2 - Schizo0/B */
03831d35f7499c87d51205817c93e9a8d42c4baestevel 1, 7, 1, HPC_SLOT_TYPE_CPCI /* logical/physical slot 3 - Schizo1/B */
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sdesc_t six_slot_wib_bd[] = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0, 6, 1, HPC_SLOT_TYPE_CPCI, /* logical/physical slot 0 - Schizo0/A */
03831d35f7499c87d51205817c93e9a8d42c4baestevel 1, 0, 2, 0, /* logical/physical slot 1 - paroli2 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel 1, 0, 0, 0, /* logical/physical slot 2 - paroli0 */
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0, 7, 1, HPC_SLOT_TYPE_CPCI, /* logical/physical slot 3 - Schizo0/B */
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0, 7, 2, HPC_SLOT_TYPE_CPCI, /* logical/physical slot 4 - Schizo0/B */
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0, 7, 3, HPC_SLOT_TYPE_CPCI /* logical/physical slot 5 - Schizo0/B */
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sdesc_t six_slot_bd[] = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0, 6, 1, HPC_SLOT_TYPE_CPCI, /* logical/physical slot 0 - Schizo0/A */
03831d35f7499c87d51205817c93e9a8d42c4baestevel 1, 6, 1, HPC_SLOT_TYPE_CPCI, /* logical/physical slot 1 - Schizo1/A */
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0, 7, 1, HPC_SLOT_TYPE_CPCI, /* logical/physical slot 2 - Schizo0/B */
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0, 7, 2, HPC_SLOT_TYPE_CPCI, /* logical/physical slot 3 - Schizo0/B */
03831d35f7499c87d51205817c93e9a8d42c4baestevel 1, 7, 1, HPC_SLOT_TYPE_CPCI, /* logical/physical slot 4 - Schizo1/B */
03831d35f7499c87d51205817c93e9a8d42c4baestevel 1, 7, 2, HPC_SLOT_TYPE_CPCI /* logical/physical slot 5 - Schizo1/B */
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * DR event handlers
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We want to register the event handlers once for all instances. In the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * other hand we have register them after the sghsc has been attached.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * event_initialize gives us the logic of only registering the events only
03831d35f7499c87d51205817c93e9a8d42c4baestevel * once. The event thread will do all the work when called from interrupts.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint sghsc_event_init = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic uint_t sghsc_event_handler(char *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void sghsc_event_thread_code(void);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * DR event msg and payload
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sbbc_msg_t event_msg;
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sghsc_event_t payload;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Event lock and state
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic kmutex_t sghsc_event_lock;
03831d35f7499c87d51205817c93e9a8d42c4baestevelint sghsc_event_state;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevel_init(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc_maxinst = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((error = ddi_soft_state_init(&sghsc_state,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sizeof (sghsc_t), 1)) != 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((error = mod_install(&modlinkage)) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_soft_state_fini(&sghsc_state);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc_rb_header.buf = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_init(&sghsc_event_thread_mutex, NULL, MUTEX_DRIVER, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_init(&sghsc_event_thread_cv, NULL, CV_DRIVER, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevel_fini(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((error = mod_remove(&modlinkage)) != 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Unregister the event handler
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) sbbc_mbox_unreg_intr(MBOX_EVENT_CPCI_ENUM, sghsc_event_handler);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_destroy(&sghsc_event_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Kill the event thread if it is running.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sghsc_event_thread != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&sghsc_event_thread_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc_event_thread_exit = B_TRUE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Goes to the thread at once.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_signal(&sghsc_event_thread_cv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Waiting for the response from the thread.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_wait(&sghsc_event_thread_cv, &sghsc_event_thread_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&sghsc_event_thread_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc_event_thread = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_destroy(&sghsc_event_thread_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_destroy(&sghsc_event_thread_cv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * tear down shared, global ring buffer now that it is safe to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * do so because sghsc_event_handler has been unregistered and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sghsc_event_thread_code has exited
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc_rb_teardown(&sghsc_rb_header);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc_maxinst = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_soft_state_fini(&sghsc_state);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevel_info(struct modinfo *modinfop)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (mod_info(&modlinkage, modinfop));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sghsc_attach()
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelsghsc_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc_t *sghsc;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint_t instance;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint_t portid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rc;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int board_type = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance = ddi_get_instance(dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (cmd) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DDI_RESUME:
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DDI_ATTACH:
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "sghsc%d: unsupported cmd %d",
193974072f41a843678abf5f61979c748687e66bSherry Moore instance, cmd);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "attach sghsc driver. "));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Fetch Safari Extended Agent ID of this device. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel portid = (uint_t)ddi_getprop(DDI_DEV_T_ANY, dip,
03831d35f7499c87d51205817c93e9a8d42c4baestevel DDI_PROP_DONTPASS, "portid", -1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!SG_PORTID_IS_IO_TYPE(portid)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "sghsc%d: property %s out of bounds %d\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance, "portid", portid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_soft_state_zalloc(sghsc_state, instance) != DDI_SUCCESS)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc = (sghsc_t *)ddi_get_soft_state(sghsc_state, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_dip = dip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_instance = instance;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_board = SG_PORTID_TO_BOARD_NUM(portid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_node_id = SG_PORTID_TO_NODEID(portid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_portid = portid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_set_driver_private(dip, sghsc);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_init(SGHSC_MUTEX(sghsc), NULL, MUTEX_DRIVER, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rc = sghsc_scctl(SGHSC_GET_NUM_SLOTS, sghsc->sghsc_node_id,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_board, 0, (int *)&sghsc->sghsc_num_slots);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rc) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "sghsc%d: unable to size node %d / board %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance, sghsc->sghsc_node_id, sghsc->sghsc_board);
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto cleanup_stage2;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc%d: node %d / board %d has %d slots",
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance, sghsc->sghsc_node_id, sghsc->sghsc_board,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_num_slots));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (sghsc->sghsc_num_slots) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case 4:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case 6:
03831d35f7499c87d51205817c93e9a8d42c4baestevel rc = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel rc = -1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rc) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "sghsc%d: wrong num of slots %d for node %d"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " / board %d", instance, sghsc->sghsc_num_slots,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_node_id, sghsc->sghsc_board);
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto cleanup_stage2;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rc = sghsc_scctl(SGHSC_GET_CPCI_BOARD_TYPE, sghsc->sghsc_node_id,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_board, 0, &board_type);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc%d: node %d / board %d is type %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance, sghsc->sghsc_node_id, sghsc->sghsc_board, board_type));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_slot_table = (sghsc_slot_t *)kmem_zalloc((size_t)
03831d35f7499c87d51205817c93e9a8d42c4baestevel (sghsc->sghsc_num_slots * sizeof (sghsc_slot_t)), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sghsc_register_slots(sghsc, board_type) != DDI_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc%d: sghsc_register_slots"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " failed for node %d / board %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance, sghsc->sghsc_node_id, sghsc->sghsc_board));
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto cleanup;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sghsc_connect((caddr_t)sghsc, 0, 0, SGHSC_ALL_SLOTS_ENABLE)
03831d35f7499c87d51205817c93e9a8d42c4baestevel != HPC_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc%d: sghsc_connect failed for"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " node %d / board %d", instance, sghsc->sghsc_node_id,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_board));
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto cleanup;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sghsc_event_init == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * allocate shared, global ring buffer before registering
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sghsc_event_handler and before starting
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sghsc_event_thread_code
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc_rb_setup(&sghsc_rb_header);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Regiter cpci DR event handler
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_init(&sghsc_event_lock, NULL, MUTEX_DRIVER, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel event_msg.msg_buf = (caddr_t)&payload;
03831d35f7499c87d51205817c93e9a8d42c4baestevel event_msg.msg_len = sizeof (payload);
03831d35f7499c87d51205817c93e9a8d42c4baestevel rc = sbbc_mbox_reg_intr(MBOX_EVENT_CPCI_ENUM,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc_event_handler, &event_msg,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (uint_t *)&sghsc_event_state, &sghsc_event_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rc != 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "sghsc%d: failed to register events"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " for node %d", instance, sghsc->sghsc_node_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc_event_init = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Create the event thread if it is not already created.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sghsc_event_thread == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc: creating event thread"
03831d35f7499c87d51205817c93e9a8d42c4baestevel "for node %d", sghsc->sghsc_node_id));
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc_event_thread = thread_create(NULL, 0,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc_event_thread_code, NULL, 0, &p0,
03831d35f7499c87d51205817c93e9a8d42c4baestevel TS_RUN, minclsyspri);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_report_dev(dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Grossly bump up the instance counter. We may have holes inside.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc_maxinst++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_valid = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelcleanup:
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Free up allocated resources and return error
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sghsc_register_slots => unregister all slots
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc_freemem(sghsc);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelcleanup_stage2:
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc%d: attach failed for node %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance, sghsc->sghsc_node_id));
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_destroy(SGHSC_MUTEX(sghsc));
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_set_driver_private(dip, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_soft_state_free(sghsc_state, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * detach(9E)
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelsghsc_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc_t *sghsc;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int instance;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance = ddi_get_instance(dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc = (sghsc_t *)ddi_get_soft_state(sghsc_state, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sghsc == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (cmd) {
193974072f41a843678abf5f61979c748687e66bSherry Moore case DDI_DETACH:
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We don't allow to detach in case the pci nexus
03831d35f7499c87d51205817c93e9a8d42c4baestevel * didn't run pcihp_uninit(). The buses should be
03831d35f7499c87d51205817c93e9a8d42c4baestevel * unregistered by now, otherwise slot info will be
03831d35f7499c87d51205817c93e9a8d42c4baestevel * corrupted on the next 'cfgadm'.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < sghsc->sghsc_num_slots; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sghsc->sghsc_slot_table[i].handle &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel hpc_bus_registered(
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_slot_table[i].handle)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "sghsc: must detach buses first");
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mutex_tryenter(&sghsc_event_thread_mutex) == 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EBUSY);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_valid = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc_freemem(sghsc);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_destroy(SGHSC_MUTEX(sghsc));
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_set_driver_private(dip, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_soft_state_free(sghsc_state, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Grossly decrement the counter. We may have holes inside.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (instance == (sghsc_maxinst - 1))
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc_maxinst--;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&sghsc_event_thread_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
193974072f41a843678abf5f61979c748687e66bSherry Moore case DDI_SUSPEND:
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
193974072f41a843678abf5f61979c748687e66bSherry Moore default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Set up and register slot 0 to num_slots with hotplug
03831d35f7499c87d51205817c93e9a8d42c4baestevel * framework
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Assume SGHSC_MUTEX is held
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Return val: DDI_SUCCESS
03831d35f7499c87d51205817c93e9a8d42c4baestevel * DDI_FAILURE
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelsghsc_register_slots(sghsc_t *sghsc, int board_type)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev_info_t *dip = sghsc->sghsc_dip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel hpc_slot_ops_t *slot_ops = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sdesc_t *slot2bus;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc%d: slot table has %d entries for "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "node %d / board %d", sghsc->sghsc_instance, sghsc->sghsc_num_slots,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_node_id, sghsc->sghsc_board));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((cpci_enable == 0) || (sg_prom_cpci_dr_check() != 0))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sghsc->sghsc_slot_table == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (board_type) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If the GET_CPCI_BOARD_TYPE request failed, board type
03831d35f7499c87d51205817c93e9a8d42c4baestevel * will be NO_BOARD_TYPE. In that case, assume it is an
03831d35f7499c87d51205817c93e9a8d42c4baestevel * io boat and make board type determination based on the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * number of slots.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel case NO_BOARD_TYPE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case CPCI_BOARD:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SP_CPCI_BOARD:
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (sghsc->sghsc_num_slots) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case 4:
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot2bus = four_slot_bd;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case 6:
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot2bus = six_slot_bd;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "sghsc%d: unknown size %d for"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " node %d / board %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_instance,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_num_slots,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_node_id, sghsc->sghsc_board);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case WCI_CPCI_BOARD:
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot2bus = four_slot_wib_bd;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case WCI_SP_CPCI_BOARD:
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot2bus = six_slot_wib_bd;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "sghsc%d: unknown type %d for"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " node %d / board %d", sghsc->sghsc_instance,
03831d35f7499c87d51205817c93e9a8d42c4baestevel board_type, sghsc->sghsc_node_id,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_board);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * constructing the slot table array and register the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * slot with the HPS
03831d35f7499c87d51205817c93e9a8d42c4baestevel * we don't depend on the .conf file
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < sghsc->sghsc_num_slots; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel char *nexuspath;
03831d35f7499c87d51205817c93e9a8d42c4baestevel hpc_slot_info_t *slot_info;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t base_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Some kind of black list may be needed
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Need to talk to SC and get slot info and set slot state:
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 1. slot status
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 2. slot capabilities
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 3. LED status
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 4. get bus num
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * fill up nexuspath, extended id is used instead of the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * local one, the node id is encoded in the path twice.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel base_id = sghsc->sghsc_portid & SGHSC_SAFARI_ID_EVEN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel nexuspath = sghsc->sghsc_slot_table[i].nexus_path;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) sprintf(nexuspath, SGHSC_PATH, sghsc->sghsc_node_id,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (base_id + slot2bus[i].agent_delta), slot2bus[i].off);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_slot_table[i].pci_device_num =
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot2bus[i].pcidev;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * fill up slot_info
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot_info = &sghsc->sghsc_slot_table[i].slot_info;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot_info->version = HPC_SLOT_INFO_VERSION;
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot_info->slot_type = slot2bus[i].slot_type;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* capabilities need to be discovered via SC */
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot_info->pci_slot_capabilities = HPC_SLOT_64BITS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot_info->pci_dev_num = slot2bus[i].pcidev;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) sprintf(slot_info->pci_slot_name,
193974072f41a843678abf5f61979c748687e66bSherry Moore "sg%dslot%d", sghsc->sghsc_board, i);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "pci_slot_name is %s at pci_dev_num %d"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " on node %d / board %d", slot_info->pci_slot_name,
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot_info->pci_dev_num, sghsc->sghsc_node_id,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_board));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * allocate and fill up slot_ops
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot_ops = hpc_alloc_slot_ops(KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_slot_table[i].slot_ops = slot_ops;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* assign slot ops for HPS */
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot_ops->hpc_version = HPC_SLOT_OPS_VERSION;
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot_ops->hpc_op_connect = sghsc_connect;
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot_ops->hpc_op_disconnect = sghsc_disconnect;
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot_ops->hpc_op_insert = nodev;
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot_ops->hpc_op_remove = nodev;
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot_ops->hpc_op_control = sghsc_control;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * HA (Full Hot Swap) is the default mode of operation
03831d35f7499c87d51205817c93e9a8d42c4baestevel * but the type of the board is set conservstively as
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sghsc has no way of knowing it. The HP Framwork will
03831d35f7499c87d51205817c93e9a8d42c4baestevel * overwrite the value set at boot time.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_slot_table[i].flags = SGHSC_SLOT_AUTO_CFG_EN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_slot_table[i].board_type = HPC_BOARD_UNKNOWN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Only register CPCI slots */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (slot_info->slot_type != HPC_SLOT_TYPE_CPCI) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc_register_slots: "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "slot %d is non-cpci", i));
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * register slots
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((hpc_slot_register(dip, nexuspath, slot_info,
03831d35f7499c87d51205817c93e9a8d42c4baestevel &sghsc->sghsc_slot_table[i].handle,
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot_ops, (caddr_t)sghsc, 0)) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * return failure and let attach()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * do the cleanup
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "sghsc%d: Slot <%s> failed during HPS"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " registration process for node %d / board %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_instance, slot_info->pci_slot_name,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_node_id, sghsc->sghsc_board);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc registered successfully for"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " node %d / board %d", sghsc->sghsc_node_id, sghsc->sghsc_board));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Connecting a slot or all slots
03831d35f7499c87d51205817c93e9a8d42c4baestevel * State Diagram:
03831d35f7499c87d51205817c93e9a8d42c4baestevel * states
03831d35f7499c87d51205817c93e9a8d42c4baestevel * hw bits EMPTY DISCONNECT CONNECT
03831d35f7499c87d51205817c93e9a8d42c4baestevel * slot_enable NO NO YES
03831d35f7499c87d51205817c93e9a8d42c4baestevel * card_present NO YES YES
03831d35f7499c87d51205817c93e9a8d42c4baestevel * slot_switch N/A NO/YES YES
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Return val: HPC_SUCCESS if the slot(s) are enabled
03831d35f7499c87d51205817c93e9a8d42c4baestevel * HPC_ERR_FAILED if the slot can't be enabled
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelsghsc_connect(caddr_t op_arg, hpc_slot_t sloth, void *data,
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint_t flag)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc_t *sghsc = (sghsc_t *)op_arg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rc;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int result;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int slot_num = sghsc_get_slotnum(sghsc, sloth);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (flag) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
193974072f41a843678abf5f61979c748687e66bSherry Moore case SGHSC_ALL_SLOTS_ENABLE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < sghsc->sghsc_num_slots; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * All slots will be marked 'empty' as HP Framework
03831d35f7499c87d51205817c93e9a8d42c4baestevel * will try to connect those which have no kernel node.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_slot_table[i].slot_status =
03831d35f7499c87d51205817c93e9a8d42c4baestevel HPC_SLOT_EMPTY;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (HPC_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (slot_num == -1)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (HPC_ERR_INVALID);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel SGHSC_MUTEX_ENTER(sghsc);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc%d: connecting logical slot%d for"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " node %d / board %d", sghsc->sghsc_instance, slot_num,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_node_id, sghsc->sghsc_board));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Powering an empty slot is highly illegal so far
03831d35f7499c87d51205817c93e9a8d42c4baestevel * (before SC implemented a constant poll). Otherwise
03831d35f7499c87d51205817c93e9a8d42c4baestevel * it breaks ddi framework and HP. The workaround
03831d35f7499c87d51205817c93e9a8d42c4baestevel * is to check for a card first.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel rc = sghsc_scctl(SGHSC_GET_SLOT_STATUS, sghsc->sghsc_node_id,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_board, slot_num, &result);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rc == ETIMEDOUT) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel SGHSC_MUTEX_EXIT(sghsc);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (HPC_ERR_FAILED);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rc) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "sghsc%d: unable to stat slot %d for"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " node %d / board %d", sghsc->sghsc_instance, slot_num,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_node_id, sghsc->sghsc_board);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_slot_table[i].slot_status = HPC_SLOT_UNKNOWN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel SGHSC_MUTEX_EXIT(sghsc);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (HPC_ERR_FAILED);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((result >> CPCI_STAT_SLOT_EMPTY_SHIFT) & ONE_BIT) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_slot_table[i].slot_status = HPC_SLOT_EMPTY;
03831d35f7499c87d51205817c93e9a8d42c4baestevel SGHSC_MUTEX_EXIT(sghsc);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (HPC_ERR_FAILED);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rc = sghsc_scctl(SGHSC_SET_SLOT_POWER_ON, sghsc->sghsc_node_id,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_board, slot_num, &result);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rc) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "sghsc%d: unable to poweron slot %d for"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " node %d / board %d", sghsc->sghsc_instance,
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot_num, sghsc->sghsc_node_id, sghsc->sghsc_board);
03831d35f7499c87d51205817c93e9a8d42c4baestevel SGHSC_MUTEX_EXIT(sghsc);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (HPC_ERR_FAILED);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_slot_table[slot_num].slot_status =
03831d35f7499c87d51205817c93e9a8d42c4baestevel HPC_SLOT_CONNECTED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel SGHSC_MUTEX_EXIT(sghsc);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (HPC_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Disconnecting a slot or slots
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * return: HPC_SUCCESS if slot(s) are successfully disconnected
03831d35f7499c87d51205817c93e9a8d42c4baestevel * HPC_ERR_FAILED if slot(s) can't be disconnected
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelsghsc_disconnect(caddr_t op_arg, hpc_slot_t sloth, void *data,
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint_t flag)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc_t *sghsc = (sghsc_t *)op_arg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rc;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int result;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int slot_num = sghsc_get_slotnum(sghsc, sloth);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (flag) {
193974072f41a843678abf5f61979c748687e66bSherry Moore case SGHSC_ALL_SLOTS_DISABLE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (HPC_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (slot_num == -1)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (HPC_ERR_INVALID);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel SGHSC_MUTEX_ENTER(sghsc);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Disconnecting an empty or disconnected slot
03831d35f7499c87d51205817c93e9a8d42c4baestevel * does't make sense.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sghsc->sghsc_slot_table[slot_num].slot_status !=
03831d35f7499c87d51205817c93e9a8d42c4baestevel HPC_SLOT_CONNECTED) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel SGHSC_MUTEX_EXIT(sghsc);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (HPC_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rc = sghsc_scctl(SGHSC_SET_SLOT_POWER_OFF, sghsc->sghsc_node_id,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_board, slot_num, &result);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rc) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "sghsc%d: unable to poweroff slot %d for"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " node %d / board %d", sghsc->sghsc_instance,
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot_num, sghsc->sghsc_node_id, sghsc->sghsc_board);
03831d35f7499c87d51205817c93e9a8d42c4baestevel SGHSC_MUTEX_EXIT(sghsc);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (HPC_ERR_FAILED);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_slot_table[slot_num].slot_status =
03831d35f7499c87d51205817c93e9a8d42c4baestevel HPC_SLOT_DISCONNECTED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel SGHSC_MUTEX_EXIT(sghsc);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (HPC_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Entry point from the hotplug framework to do
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the main hotplug operations
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Return val: HPC_SUCCESS success on ops
03831d35f7499c87d51205817c93e9a8d42c4baestevel * HPC_NOT_SUPPORTED not supported feature
03831d35f7499c87d51205817c93e9a8d42c4baestevel * HPC_ERR_FAILED ops failed
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelsghsc_control(caddr_t op_arg, hpc_slot_t sloth, int request,
03831d35f7499c87d51205817c93e9a8d42c4baestevel caddr_t arg)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc_t *sghsc = (sghsc_t *)op_arg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int slot = sghsc_get_slotnum(sghsc, sloth);
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error = HPC_SUCCESS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rc;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int result;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((sghsc == NULL) || (slot < 0) ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel (slot >= sghsc->sghsc_num_slots)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "sghsc%d: sghsc_control fails with slot = %d"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " max = %d, sloth = 0x%p for node %d / board %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_instance, slot, sghsc->sghsc_num_slots,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sloth, sghsc->sghsc_node_id, sghsc->sghsc_board);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (HPC_ERR_INVALID);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel SGHSC_MUTEX_ENTER(sghsc);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (request) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case HPC_CTRL_GET_LED_STATE: {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* arg == hpc_led_info_t */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel hpc_led_info_t *ledinfo;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ledinfo = (hpc_led_info_t *)arg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc%d: sghsc_control"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " HPC_CTRL_GET_LED_STATE for node %d / board %d slot %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_instance, sghsc->sghsc_node_id,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_board, slot));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (ledinfo->led) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case HPC_POWER_LED:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case HPC_ATTN_LED:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case HPC_FAULT_LED:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case HPC_ACTIVE_LED:
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = sghsc_led_state(sghsc, sloth,
03831d35f7499c87d51205817c93e9a8d42c4baestevel HPC_CTRL_GET_LED_STATE, ledinfo);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "sghsc%d: sghsc_control"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " HPC_CTRL_GET_LED_STATE "
03831d35f7499c87d51205817c93e9a8d42c4baestevel " unknown led state %d for node %d / board %d"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " slot handle 0x%p", sghsc->sghsc_instance,
03831d35f7499c87d51205817c93e9a8d42c4baestevel ledinfo->led, sghsc->sghsc_node_id,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_board, sloth);
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = HPC_ERR_NOTSUPPORTED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case HPC_CTRL_SET_LED_STATE: {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* arg == hpc_led_info_t */
03831d35f7499c87d51205817c93e9a8d42c4baestevel hpc_led_info_t *ledinfo;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ledinfo = (hpc_led_info_t *)arg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc%d: sghsc_control"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " HPC_CTRL_SET_LED_STATE for node %d / board %d slot %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_instance, sghsc->sghsc_node_id,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_board, slot));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (ledinfo->led) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case HPC_POWER_LED:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case HPC_ATTN_LED:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case HPC_FAULT_LED:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case HPC_ACTIVE_LED:
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc:"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " LED writing not supported "));
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc:"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " LED not supported "));
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = HPC_ERR_NOTSUPPORTED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case HPC_CTRL_GET_SLOT_STATE: {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc%d: sghsc_control"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " HPC_CTRL_GET_SLOT_STATE for node %d / board %d slot %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_instance, sghsc->sghsc_node_id,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_board, slot));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Send mailbox cmd to SC to query the latest state
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel rc = sghsc_scctl(SGHSC_GET_SLOT_STATUS, sghsc->sghsc_node_id,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_board, slot, &result);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rc == ETIMEDOUT) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = HPC_ERR_FAILED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rc) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "sghsc%d: unable to stat slot %d for "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "node %d / board %d", sghsc->sghsc_instance, slot,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_node_id, sghsc->sghsc_board);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_slot_table[slot].slot_status =
03831d35f7499c87d51205817c93e9a8d42c4baestevel HPC_SLOT_UNKNOWN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel *(hpc_slot_state_t *)arg = HPC_SLOT_UNKNOWN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Update the cached state if needed. Initally all
03831d35f7499c87d51205817c93e9a8d42c4baestevel * slots are marked as empty for the Hot Plug Framwork.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((result >> CPCI_STAT_SLOT_EMPTY_SHIFT) & ONE_BIT) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_slot_table[slot].slot_status =
03831d35f7499c87d51205817c93e9a8d42c4baestevel HPC_SLOT_EMPTY;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if ((result >> CPCI_STAT_POWER_ON_SHIFT) & ONE_BIT) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_slot_table[slot].slot_status =
03831d35f7499c87d51205817c93e9a8d42c4baestevel HPC_SLOT_CONNECTED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (sghsc->sghsc_slot_table[slot].slot_status ==
193974072f41a843678abf5f61979c748687e66bSherry Moore HPC_SLOT_EMPTY ||
193974072f41a843678abf5f61979c748687e66bSherry Moore sghsc->sghsc_slot_table[slot].slot_status ==
193974072f41a843678abf5f61979c748687e66bSherry Moore HPC_SLOT_UNKNOWN) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_slot_table[slot].slot_status =
03831d35f7499c87d51205817c93e9a8d42c4baestevel HPC_SLOT_DISCONNECTED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * No change
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel *(hpc_slot_state_t *)arg =
193974072f41a843678abf5f61979c748687e66bSherry Moore sghsc->sghsc_slot_table[slot].slot_status;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case HPC_CTRL_DEV_CONFIGURED:
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc%d: sghsc_control"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " HPC_CTRL_DEV_CONFIGURED for node %d / board %d slot %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_instance, sghsc->sghsc_node_id,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_board, slot));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sghsc_configure_ack)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "sghsc%d:"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " node %d / board %d slot %d configured",
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_instance, sghsc->sghsc_node_id,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_board, slot);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This is important to tell SC:
03831d35f7499c87d51205817c93e9a8d42c4baestevel * "start looking for ENUMs"
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sghsc->sghsc_slot_table[slot].flags &
03831d35f7499c87d51205817c93e9a8d42c4baestevel SGHSC_SLOT_AUTO_CFG_EN)
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) sghsc_scctl(SGHSC_SET_ENUM_CLEARED,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_node_id, sghsc->sghsc_board,
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot, &result);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case HPC_CTRL_DEV_UNCONFIGURED:
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * due to unclean drivers, unconfigure may leave
03831d35f7499c87d51205817c93e9a8d42c4baestevel * some state on card, configure may actually
03831d35f7499c87d51205817c93e9a8d42c4baestevel * use these invalid values. therefore, may force
03831d35f7499c87d51205817c93e9a8d42c4baestevel * disconnect.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc%d: sghsc_control "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "HPC_CTRL_DEV_UNCONFIGURED for node %d / board %d slot %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_instance, sghsc->sghsc_node_id,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_board, slot));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel SGHSC_MUTEX_EXIT(sghsc);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sghsc_disconnect(op_arg, sloth, 0,
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0) != HPC_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc_control: "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "disconnect failed"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = HPC_ERR_FAILED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "sghsc%d: node %d / board %d "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "slot %d unconfigured", sghsc->sghsc_instance,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_node_id, sghsc->sghsc_board, slot);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case HPC_CTRL_GET_BOARD_TYPE: {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* arg = hpc_board_type_t */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc%d: sghsc_control"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " HPC_CTRL_GET_BOARD_TYPE for node %d / board %d slot %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_instance, sghsc->sghsc_node_id,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_board, slot));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel *(hpc_board_type_t *)arg =
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_slot_table[slot].board_type;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case HPC_CTRL_ENABLE_AUTOCFG:
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc%d: sghsc_control"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " HPC_CTRL_ENABLE_AUTOCFG for node %d / board %d slot %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_instance, sghsc->sghsc_node_id,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_board, slot));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_slot_table[slot].flags |= SGHSC_SLOT_AUTO_CFG_EN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) hpc_slot_event_notify(sloth, HPC_EVENT_ENABLE_ENUM,
03831d35f7499c87d51205817c93e9a8d42c4baestevel HPC_EVENT_NORMAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Tell SC to start looking for ENUMs on this slot.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel rc = sghsc_scctl(SGHSC_SET_ENUM_CLEARED, sghsc->sghsc_node_id,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_board, slot, &result);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rc)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "sghsc%d: unable to arm ENUM for"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " node %d / board %d, slot %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_instance, sghsc->sghsc_node_id,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_board, slot);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case HPC_CTRL_DISABLE_AUTOCFG:
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc%d: sghsc_control"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " HPC_CTRL_DISABLE_AUTOCFG for node %d / board %d slot %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_instance, sghsc->sghsc_node_id,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_board, slot));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_slot_table[slot].flags &= ~SGHSC_SLOT_AUTO_CFG_EN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) hpc_slot_event_notify(sloth, HPC_EVENT_DISABLE_ENUM,
03831d35f7499c87d51205817c93e9a8d42c4baestevel HPC_EVENT_NORMAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case HPC_CTRL_DISABLE_SLOT:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case HPC_CTRL_ENABLE_SLOT:
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* need to add support for enable/disable_ENUM */
03831d35f7499c87d51205817c93e9a8d42c4baestevel case HPC_CTRL_DISABLE_ENUM:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case HPC_CTRL_ENABLE_ENUM:
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_CONT, "sghsc%d: sghsc_control "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "request (0x%x) not supported", sghsc->sghsc_instance,
03831d35f7499c87d51205817c93e9a8d42c4baestevel request));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* invalid request */
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = HPC_ERR_NOTSUPPORTED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel SGHSC_MUTEX_EXIT(sghsc);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Read/write slot's led
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Assume MUTEX_HELD
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * return: HPC_SUCCESS if the led's status is avaiable,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SC return status otherwise.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelsghsc_led_state(sghsc_t *sghsc, hpc_slot_t sloth, int op,
03831d35f7499c87d51205817c93e9a8d42c4baestevel hpc_led_info_t *ledinfo)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rval;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int slot_num;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int result;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel slot_num = sghsc_get_slotnum(sghsc, sloth);
03831d35f7499c87d51205817c93e9a8d42c4baestevel rval = sghsc_scctl(SGHSC_GET_SLOT_STATUS, sghsc->sghsc_node_id,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_board, slot_num, &result);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rval != HPC_SUCCESS)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (rval);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (op) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case HPC_CTRL_GET_LED_STATE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (ledinfo->led) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case HPC_POWER_LED:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((result >> CPCI_STAT_LED_POWER_SHIFT) & ONE_BIT)
03831d35f7499c87d51205817c93e9a8d42c4baestevel ledinfo->state = HPC_LED_ON;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel ledinfo->state = HPC_LED_OFF;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case HPC_ATTN_LED:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case HPC_FAULT_LED:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((result >> CPCI_STAT_LED_FAULT_SHIFT) & ONE_BIT)
03831d35f7499c87d51205817c93e9a8d42c4baestevel ledinfo->state = HPC_LED_ON;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel ledinfo->state = HPC_LED_OFF;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case HPC_ACTIVE_LED:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((result >> CPCI_STAT_LED_HP_SHIFT) & ONE_BIT)
03831d35f7499c87d51205817c93e9a8d42c4baestevel ledinfo->state = HPC_LED_ON;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel ledinfo->state = HPC_LED_OFF;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case HPC_CTRL_SET_LED_STATE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (HPC_ERR_NOTSUPPORTED);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (HPC_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sghsc_get_slotnum()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get slot number from the slot handle
03831d35f7499c87d51205817c93e9a8d42c4baestevel * returns non-negative value to indicate slot number
03831d35f7499c87d51205817c93e9a8d42c4baestevel * -1 for failure
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelsghsc_get_slotnum(sghsc_t *sghsc, hpc_slot_t sloth)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sloth == NULL || sghsc == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < sghsc->sghsc_num_slots; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sghsc->sghsc_slot_table[i].handle == sloth)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (i);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sghsc_scctl()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mailbox interface
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * return result code from mailbox operation
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelsghsc_scctl(int cmd, int node_id, int board, int slot, int *resultp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int ret = 0xbee;
03831d35f7499c87d51205817c93e9a8d42c4baestevel bitcmd_info_t cmd_info, *cmd_infop = &cmd_info;
03831d35f7499c87d51205817c93e9a8d42c4baestevel bitcmd_resp_t cmd_info_r, *cmd_info_r_p = &cmd_info_r;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbbc_msg_t request, *reqp = &request;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbbc_msg_t response, *resp = &response;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmd_infop->cmd_id = 0x01234567;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmd_infop->node_id = node_id;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmd_infop->board = board;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmd_infop->slot = slot;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel reqp->msg_type.type = CPCI_MBOX;
03831d35f7499c87d51205817c93e9a8d42c4baestevel reqp->msg_status = 0xeeeeffff;
03831d35f7499c87d51205817c93e9a8d42c4baestevel reqp->msg_len = sizeof (cmd_info);
03831d35f7499c87d51205817c93e9a8d42c4baestevel reqp->msg_bytes = 8;
03831d35f7499c87d51205817c93e9a8d42c4baestevel reqp->msg_buf = (caddr_t)cmd_infop;
03831d35f7499c87d51205817c93e9a8d42c4baestevel reqp->msg_data[0] = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel reqp->msg_data[1] = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel bzero(resp, sizeof (*resp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel bzero(cmd_info_r_p, sizeof (*cmd_info_r_p));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel resp->msg_buf = (caddr_t)cmd_info_r_p;
03831d35f7499c87d51205817c93e9a8d42c4baestevel resp->msg_len = sizeof (cmd_info_r);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel resp->msg_type.type = CPCI_MBOX;
03831d35f7499c87d51205817c93e9a8d42c4baestevel resp->msg_bytes = 8;
03831d35f7499c87d51205817c93e9a8d42c4baestevel resp->msg_status = 0xddddffff;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (cmd) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SGHSC_GET_SLOT_STATUS:
03831d35f7499c87d51205817c93e9a8d42c4baestevel reqp->msg_type.sub_type = CPCI_GET_SLOT_STATUS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel resp->msg_type.sub_type = CPCI_GET_SLOT_STATUS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel reqp->msg_len -= 4;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SGHSC_GET_NUM_SLOTS:
03831d35f7499c87d51205817c93e9a8d42c4baestevel reqp->msg_type.sub_type = CPCI_GET_NUM_SLOTS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel resp->msg_type.sub_type = CPCI_GET_NUM_SLOTS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel reqp->msg_len -= 8;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SGHSC_SET_SLOT_STATUS_RESET:
03831d35f7499c87d51205817c93e9a8d42c4baestevel reqp->msg_type.sub_type = CPCI_SET_SLOT_STATUS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel resp->msg_type.sub_type = CPCI_SET_SLOT_STATUS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmd_infop->info = CPCI_SET_STATUS_SLOT_RESET;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SGHSC_SET_SLOT_STATUS_READY:
03831d35f7499c87d51205817c93e9a8d42c4baestevel reqp->msg_type.sub_type = CPCI_SET_SLOT_STATUS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel resp->msg_type.sub_type = CPCI_SET_SLOT_STATUS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmd_infop->info = CPCI_SET_STATUS_SLOT_READY;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SGHSC_SET_SLOT_FAULT_LED_ON:
03831d35f7499c87d51205817c93e9a8d42c4baestevel reqp->msg_type.sub_type = CPCI_SET_SLOT_FAULT_LED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel resp->msg_type.sub_type = CPCI_SET_SLOT_FAULT_LED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmd_infop->info = CPCI_SET_FAULT_LED_ON;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SGHSC_SET_SLOT_FAULT_LED_OFF:
03831d35f7499c87d51205817c93e9a8d42c4baestevel reqp->msg_type.sub_type = CPCI_SET_SLOT_FAULT_LED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel resp->msg_type.sub_type = CPCI_SET_SLOT_FAULT_LED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmd_infop->info = CPCI_SET_FAULT_LED_OFF;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SGHSC_SET_SLOT_FAULT_LED_KEEP:
03831d35f7499c87d51205817c93e9a8d42c4baestevel reqp->msg_type.sub_type = CPCI_SET_SLOT_FAULT_LED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel resp->msg_type.sub_type = CPCI_SET_SLOT_FAULT_LED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmd_infop->info = CPCI_SET_FAULT_LED_KEEP;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SGHSC_SET_SLOT_FAULT_LED_TOGGLE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel reqp->msg_type.sub_type = CPCI_SET_SLOT_FAULT_LED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel resp->msg_type.sub_type = CPCI_SET_SLOT_FAULT_LED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmd_infop->info = CPCI_SET_FAULT_LED_TOGGLE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SGHSC_SET_SLOT_POWER_OFF:
03831d35f7499c87d51205817c93e9a8d42c4baestevel reqp->msg_type.sub_type = CPCI_SET_SLOT_POWER;
03831d35f7499c87d51205817c93e9a8d42c4baestevel resp->msg_type.sub_type = CPCI_SET_SLOT_POWER;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmd_infop->info = CPCI_POWER_OFF;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SGHSC_SET_SLOT_POWER_ON:
03831d35f7499c87d51205817c93e9a8d42c4baestevel reqp->msg_type.sub_type = CPCI_SET_SLOT_POWER;
03831d35f7499c87d51205817c93e9a8d42c4baestevel resp->msg_type.sub_type = CPCI_SET_SLOT_POWER;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmd_infop->info = CPCI_POWER_ON;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SGHSC_GET_CPCI_BOARD_TYPE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel reqp->msg_type.sub_type = CPCI_BOARD_TYPE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel resp->msg_type.sub_type = CPCI_BOARD_TYPE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel reqp->msg_len -= 8;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SGHSC_SET_ENUM_CLEARED:
03831d35f7499c87d51205817c93e9a8d42c4baestevel reqp->msg_type.sub_type = CPCI_SET_ENUM_CLEARED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel resp->msg_type.sub_type = CPCI_SET_ENUM_CLEARED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "sghsc: unrecognized action code 0x%x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmd);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "sghsc: sending mbox command type=%d subtype=0x%x size=%d buf=%p",
03831d35f7499c87d51205817c93e9a8d42c4baestevel reqp->msg_type.type, reqp->msg_type.sub_type,
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki reqp->msg_len, (void *)reqp->msg_buf));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "sghsc: sending buf cmd_id=0x%x node_id=0x%x board=0x%x "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "slot=0x%x info=0x%x", cmd_infop->cmd_id, cmd_infop->node_id,
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmd_infop->board, cmd_infop->slot, cmd_infop->info));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ret = sbbc_mbox_request_response(reqp, resp, sghsc_mbx_timeout);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The resp->msg_status field may contain an SC error or a common
03831d35f7499c87d51205817c93e9a8d42c4baestevel * error such as ETIMEDOUT.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((ret != 0) || (resp->msg_status != SG_MBOX_STATUS_SUCCESS)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc: mailbox command error = 0x%x, "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "status = 0x%x", ret, resp->msg_status));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc: reply request status=0x%x",
03831d35f7499c87d51205817c93e9a8d42c4baestevel reqp->msg_status));
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc: reply resp status=0x%x",
03831d35f7499c87d51205817c93e9a8d42c4baestevel resp->msg_status));
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc: reply buf cmd_id=0x%x result=0x%x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmd_info_r_p->cmd_id, cmd_info_r_p->result));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG_EXTENDED
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cmd == SGHSC_GET_NUM_SLOTS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc: node %d / board %d has %d slots",
193974072f41a843678abf5f61979c748687e66bSherry Moore cmd_infop->node_id, cmd_infop->board,
193974072f41a843678abf5f61979c748687e66bSherry Moore cmd_info_r_p->result));
03831d35f7499c87d51205817c93e9a8d42c4baestevel *resultp = cmd_info_r_p->result;
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((cmd_info_r_p->result >> CPCI_STAT_POWER_ON_SHIFT) & ONE_BIT)
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc: cpower on"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((cmd_info_r_p->result >> CPCI_STAT_LED_POWER_SHIFT) & ONE_BIT)
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc: power led on"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((cmd_info_r_p->result >> CPCI_STAT_LED_FAULT_SHIFT) & ONE_BIT)
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc: fault led on"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((cmd_info_r_p->result >> CPCI_STAT_LED_HP_SHIFT) & ONE_BIT)
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc: remove(hp) led on"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((cmd_info_r_p->result >> CPCI_STAT_SLOT_EMPTY_SHIFT) & ONE_BIT)
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc: slot empty"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel tmp = ((cmd_info_r_p->result >> CPCI_STAT_HOT_SWAP_STATUS_SHIFT) &
03831d35f7499c87d51205817c93e9a8d42c4baestevel THREE_BITS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (tmp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "sghsc: slot condition(hot swap status) is 0x%x", tmp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cmd_info_r_p->result & CPCI_GET_STAT_SLOT_HZ_CAP)
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "sghsc: freq cap %x", cmd_info_r_p->result &
03831d35f7499c87d51205817c93e9a8d42c4baestevel CPCI_GET_STAT_SLOT_HZ_CAP));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cmd_info_r_p->result & CPCI_GET_STAT_SLOT_HZ_SET)
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "sghsc: freq setting %x", cmd_info_r_p->result &
03831d35f7499c87d51205817c93e9a8d42c4baestevel CPCI_GET_STAT_SLOT_HZ_SET));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((cmd_info_r_p->result >> CPCI_STAT_HEALTHY_SHIFT) & ONE_BIT)
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc: healthy"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((cmd_info_r_p->result >> CPCI_STAT_RESET_SHIFT) & ONE_BIT)
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc: in reset"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cmd_info_r_p->result & CPCI_GET_STAT_POWER_GOOD)
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc: power good"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cmd_info_r_p->result & CPCI_GET_STAT_POWER_FAULT)
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc: power fault"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cmd_info_r_p->result & CPCI_GET_STAT_PCI_PRESENT)
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc: pci present"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel *resultp = cmd_info_r_p->result;
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sghsc_freemem()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * deallocates memory resources
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelsghsc_freemem(sghsc_t *sghsc)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Free up allocated resources
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sghsc_register_slots => unregister all slots
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < sghsc->sghsc_num_slots; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sghsc->sghsc_slot_table[i].slot_ops)
193974072f41a843678abf5f61979c748687e66bSherry Moore hpc_free_slot_ops(sghsc->sghsc_slot_table[i].slot_ops);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sghsc->sghsc_slot_table[i].handle)
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) hpc_slot_unregister(
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki &sghsc->sghsc_slot_table[i].handle);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* finally free up slot_table */
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(sghsc->sghsc_slot_table,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (size_t)(sghsc->sghsc_num_slots * sizeof (sghsc_slot_t)));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sghsc_find_sloth()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Find slot handle by node id, board number and slot numbert
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Returns slot handle or 0 if slot not found.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic hpc_slot_t
03831d35f7499c87d51205817c93e9a8d42c4baestevelsghsc_find_sloth(int node_id, int board, int slot)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int instance;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc_t *sghsc;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (instance = 0; instance < sghsc_maxinst; instance++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc = (sghsc_t *)ddi_get_soft_state(sghsc_state, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sghsc == NULL || sghsc->sghsc_node_id != node_id ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_board != board)
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc_find_sloth on board %d at node %d"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " slot %d", board, node_id, slot))
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sghsc->sghsc_num_slots < (slot + 1)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "sghsc%d: slot data corruption at"
03831d35f7499c87d51205817c93e9a8d42c4baestevel "node %d / board %d", instance, node_id, board);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sghsc->sghsc_valid == 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Found matching slot, return handle.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (sghsc->sghsc_slot_table[slot].handle);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_WARN, "sghsc_find_sloth: slot %d not found for node %d"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " / board %d", slot, node_id, board));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sghsc_event_handler()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Event Handler. This is what for other platforms was an interrupt
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Handler servicing events. It accepts an event and signals it to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * non-interrupt thread.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baesteveluint_t
03831d35f7499c87d51205817c93e9a8d42c4baestevelsghsc_event_handler(char *arg)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc_event_t *rsp_data;
03831d35f7499c87d51205817c93e9a8d42c4baestevel hpc_slot_t sloth;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc_t *enum_state;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc: sghsc_event_handler called"))
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rsp_data = (sghsc_event_t *)(((sbbc_msg_t *)arg)->msg_buf);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rsp_data == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
03831d35f7499c87d51205817c93e9a8d42c4baestevel ("sghsc: sghsc_event_handler argument is null\n"));
055d7c804dc8f1263f0b3166ba459c65996b8697carlsonj return (DDI_INTR_CLAIMED);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel sloth = sghsc_find_sloth(rsp_data->node_id, rsp_data->board,
03831d35f7499c87d51205817c93e9a8d42c4baestevel rsp_data->slot);
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * On a board disconnect sghsc soft state may not exist
03831d35f7499c87d51205817c93e9a8d42c4baestevel * when the interrupt occurs. We should treat these
03831d35f7499c87d51205817c93e9a8d42c4baestevel * interrupts as noise and but them.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sloth == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_WARN, "sghsc: slot info not available for"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " node %d / board %d slot %d. CPCI event rejected",
03831d35f7499c87d51205817c93e9a8d42c4baestevel rsp_data->node_id, rsp_data->board, rsp_data->slot));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_INTR_CLAIMED);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel enum_state = sghsc_find_softstate(rsp_data->node_id, rsp_data->board,
03831d35f7499c87d51205817c93e9a8d42c4baestevel rsp_data->slot);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (enum_state == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "sghsc: soft state not available for"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " node %d / board %d slot %d", rsp_data->node_id,
03831d35f7499c87d51205817c93e9a8d42c4baestevel rsp_data->board, rsp_data->slot);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_INTR_UNCLAIMED);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc: node %d", rsp_data->node_id));
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc: board %d", rsp_data->board));
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc: slot %d", rsp_data->slot));
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc: event info %d", rsp_data->info));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (rsp_data->info) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SGHSC_EVENT_CARD_INSERT:
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc: card inserted node %d / board %d"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " slot %d", rsp_data->node_id, rsp_data->board,
03831d35f7499c87d51205817c93e9a8d42c4baestevel rsp_data->slot));
03831d35f7499c87d51205817c93e9a8d42c4baestevel enum_state->sghsc_slot_table[rsp_data->slot].board_type =
03831d35f7499c87d51205817c93e9a8d42c4baestevel HPC_BOARD_CPCI_HS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel enum_state->sghsc_slot_table[rsp_data->slot].slot_status =
03831d35f7499c87d51205817c93e9a8d42c4baestevel HPC_SLOT_DISCONNECTED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SGHSC_EVENT_CARD_REMOVE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc: card removed node %d / board %d"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " slot %d", rsp_data->node_id, rsp_data->board,
03831d35f7499c87d51205817c93e9a8d42c4baestevel rsp_data->slot));
03831d35f7499c87d51205817c93e9a8d42c4baestevel enum_state->sghsc_slot_table[rsp_data->slot].board_type =
03831d35f7499c87d51205817c93e9a8d42c4baestevel HPC_BOARD_UNKNOWN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel enum_state->sghsc_slot_table[rsp_data->slot].slot_status =
03831d35f7499c87d51205817c93e9a8d42c4baestevel HPC_SLOT_EMPTY;
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_INTR_CLAIMED);
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SGHSC_EVENT_POWER_ON:
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc: power on node %d / board %d"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " slot %d", rsp_data->node_id, rsp_data->board,
03831d35f7499c87d51205817c93e9a8d42c4baestevel rsp_data->slot));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_INTR_CLAIMED);
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SGHSC_EVENT_POWER_OFF:
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc: power off node %d / board %d"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " slot %d", rsp_data->node_id, rsp_data->board,
03831d35f7499c87d51205817c93e9a8d42c4baestevel rsp_data->slot));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_INTR_CLAIMED);
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SGHSC_EVENT_HEALTHY_LOST:
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc: healthy lost node %d / board %d"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " slot %d", rsp_data->node_id, rsp_data->board,
03831d35f7499c87d51205817c93e9a8d42c4baestevel rsp_data->slot));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_INTR_CLAIMED);
03831d35f7499c87d51205817c93e9a8d42c4baestevel case SGHSC_EVENT_LEVER_ACTION:
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc: ENUM generated for node %d /"
03831d35f7499c87d51205817c93e9a8d42c4baestevel "board %d slot %d", rsp_data->node_id, rsp_data->board,
03831d35f7499c87d51205817c93e9a8d42c4baestevel rsp_data->slot));
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc: unrecognized event info for"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " node %d / board %d slot %d", rsp_data->node_id,
03831d35f7499c87d51205817c93e9a8d42c4baestevel rsp_data->board, rsp_data->slot));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_INTR_CLAIMED);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Signal the ENUM event to the non-interrupt thread as the Hot
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Plug Framework will eventually call sghsc_control() but all
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the mailbox messages are not allowed from interrupt context.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sghsc_rb_put(&sghsc_rb_header, rsp_data) != DDI_SUCCESS) {
193974072f41a843678abf5f61979c748687e66bSherry Moore cmn_err(CE_WARN, "sghsc: no space to store #ENUM info");
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_INTR_UNCLAIMED);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_signal(&sghsc_event_thread_cv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_INTR_CLAIMED);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sghsc_event_thread_code()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Event Thread. This is non-interrupt thread servicing #ENUM, Insert,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Remove, Power on/off, Healthy lost events.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelsghsc_event_thread_code(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rc;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int result;
03831d35f7499c87d51205817c93e9a8d42c4baestevel hpc_slot_t sloth;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc_t *sghsc;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc_event_t rsp_data;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&sghsc_event_thread_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (;;) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Wait for Event handler to signal event or self destruction.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Assuming the mutex will be automatically reaccuired.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_wait(&sghsc_event_thread_cv, &sghsc_event_thread_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sghsc_event_thread_exit)
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Pick up all the relevant events from the ring buffer.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (sghsc_rb_get(&sghsc_rb_header, &rsp_data) ==
03831d35f7499c87d51205817c93e9a8d42c4baestevel DDI_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc = sghsc_find_softstate(rsp_data.node_id,
03831d35f7499c87d51205817c93e9a8d42c4baestevel rsp_data.board, rsp_data.slot);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sghsc == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sloth = sghsc_find_sloth(rsp_data.node_id,
03831d35f7499c87d51205817c93e9a8d42c4baestevel rsp_data.board, rsp_data.slot);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sloth == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(sghsc->sghsc_slot_table[rsp_data.slot].flags &
03831d35f7499c87d51205817c93e9a8d42c4baestevel SGHSC_SLOT_AUTO_CFG_EN))
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Insert event leads only to the electrical
03831d35f7499c87d51205817c93e9a8d42c4baestevel * connection.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rsp_data.info == SGHSC_EVENT_CARD_INSERT) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel rc = sghsc_connect((caddr_t)sghsc, sloth,
03831d35f7499c87d51205817c93e9a8d42c4baestevel NULL, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rc != HPC_SUCCESS)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "sghsc:"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " could not connect inserted card,"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " node %d / board %d slot %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel rsp_data.node_id, rsp_data.board,
03831d35f7499c87d51205817c93e9a8d42c4baestevel rsp_data.slot);
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ENUM event received.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Reset ENUM and notify SC to poll for the next one.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel rc = hpc_slot_event_notify(sloth, HPC_EVENT_CLEAR_ENUM,
03831d35f7499c87d51205817c93e9a8d42c4baestevel HPC_EVENT_SYNCHRONOUS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rc == HPC_EVENT_UNCLAIMED) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_WARN,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "sghsc: unable to clear ENUM"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rc = sghsc_scctl(SGHSC_SET_ENUM_CLEARED,
03831d35f7499c87d51205817c93e9a8d42c4baestevel rsp_data.node_id, rsp_data.board,
03831d35f7499c87d51205817c93e9a8d42c4baestevel rsp_data.slot, &result);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rc) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_WARN,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "sghsc: unable to ACK cleared ENUM"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * process the ENUM.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel rc = hpc_slot_event_notify(sloth,
03831d35f7499c87d51205817c93e9a8d42c4baestevel HPC_EVENT_PROCESS_ENUM, HPC_EVENT_SYNCHRONOUS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rc == HPC_EVENT_UNCLAIMED) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_WARN,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "sghsc: could not process ENUM"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEBUGF(1, (CE_NOTE, "sghsc: thread_exit"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_signal(&sghsc_event_thread_cv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&sghsc_event_thread_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel thread_exit();
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sghsc_find_softstate()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Find softstate by node id and board number. Slot number is used for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * verification.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Returns board's softstate or 0 if not found.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic sghsc_t *
03831d35f7499c87d51205817c93e9a8d42c4baestevelsghsc_find_softstate(int node_id, int board, int slot)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int instance;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc_t *sghsc;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (instance = 0; instance < sghsc_maxinst; instance++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc = (sghsc_t *)ddi_get_soft_state(sghsc_state, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sghsc == NULL || sghsc->sghsc_node_id != node_id ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel sghsc->sghsc_board != board)
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sghsc->sghsc_num_slots < (slot + 1)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "sghsc%d: "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "slot data corruption", instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sghsc->sghsc_valid == 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Found matching data, return soft state.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (sghsc);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "sghsc: soft state not found");
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sghsc_rb_setup()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Initialize the event ring buffer with a fixed size. It may require
03831d35f7499c87d51205817c93e9a8d42c4baestevel * a more elaborate scheme with buffer extension
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelsghsc_rb_setup(sghsc_rb_head_t *rb_head)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rb_head->buf == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel rb_head->put_idx = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel rb_head->get_idx = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel rb_head->size = SGHSC_RING_BUFFER_SZ;
03831d35f7499c87d51205817c93e9a8d42c4baestevel rb_head->state = SGHSC_RB_EMPTY;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Allocate space for event ring buffer
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel rb_head->buf = (sghsc_event_t *)kmem_zalloc(
03831d35f7499c87d51205817c93e9a8d42c4baestevel sizeof (sghsc_event_t) * rb_head->size, KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sghsc_rb_teardown()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Free event ring buffer resources.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelsghsc_rb_teardown(sghsc_rb_head_t *rb_head)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rb_head->buf != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Deallocate space for event ring buffer
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(rb_head->buf,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (size_t)(sizeof (sghsc_event_t) * rb_head->size));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rb_head->buf = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel rb_head->put_idx = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel rb_head->get_idx = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel rb_head->size = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel rb_head->state = SGHSC_RB_EMPTY;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sghsc_rb_put()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Insert an event info into the event ring buffer.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Returns DDI_FAILURE if the buffer is full, DDI_SUCCESS otherwise
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelsghsc_rb_put(sghsc_rb_head_t *rb_head, sghsc_event_t *event)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rb_head->state == SGHSC_RB_FULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rb_head->buf[rb_head->put_idx] = *event;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
2bc987325e3ded1865bff043128661815c4690b9Richard Lowe rb_head->put_idx = (rb_head->put_idx + 1) & (rb_head->size - 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rb_head->put_idx == rb_head->get_idx)
03831d35f7499c87d51205817c93e9a8d42c4baestevel rb_head->state = SGHSC_RB_FULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel rb_head->state = SGHSC_RB_FLOAT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sghsc_rb_get()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Remove an event info from the event ring buffer.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Returns DDI_FAILURE if the buffer is empty, DDI_SUCCESS otherwise.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelsghsc_rb_get(sghsc_rb_head_t *rb_head, sghsc_event_t *event)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rb_head->state == SGHSC_RB_EMPTY)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel *event = rb_head->buf[rb_head->get_idx];
03831d35f7499c87d51205817c93e9a8d42c4baestevel
2bc987325e3ded1865bff043128661815c4690b9Richard Lowe rb_head->get_idx = (rb_head->get_idx + 1) & (rb_head->size - 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rb_head->get_idx == rb_head->put_idx)
03831d35f7499c87d51205817c93e9a8d42c4baestevel rb_head->state = SGHSC_RB_EMPTY;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel rb_head->state = SGHSC_RB_FLOAT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}