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/*
193974072f41a843678abf5f61979c748687e66bSherry Moore * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Use is subject to license terms.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * PCI SBBC Device Driver that provides interfaces into
03831d35f7499c87d51205817c93e9a8d42c4baestevel * EPLD and IO-SRAM
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/types.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/param.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/errno.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/file.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/cmn_err.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/stropts.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/kmem.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sunndi.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/conf.h> /* req. by dev_ops flags MTSAFE etc. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/modctl.h> /* for modldrv */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/promif.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/stat.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/ddi.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/serengeti.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sgsbbc_priv.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sgsbbc_iosram_priv.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sgsbbc_mailbox_priv.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* debug flag */
03831d35f7499c87d51205817c93e9a8d42c4baesteveluint_t sgsbbc_debug = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* driver entry point fn definitions */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int sbbc_attach(dev_info_t *, ddi_attach_cmd_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int sbbc_detach(dev_info_t *, ddi_detach_cmd_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SBBC soft state hook
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void *sbbcp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Chosen IOSRAM
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstruct chosen_iosram *master_iosram = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * define new iosram's sbbc and liked list of sbbc.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstruct sbbc_softstate *sgsbbc_instances = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * At attach time, check if the device is the 'chosen' node
03831d35f7499c87d51205817c93e9a8d42c4baestevel * if it is, set up the IOSRAM Solaris<->SC Comm tunnel
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Its like 'Highlander' - there can be only one !
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int master_chosen = FALSE;
03831d35f7499c87d51205817c93e9a8d42c4baestevelkmutex_t chosen_lock;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Local variable to save intr_in_enabled when the driver is suspended
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic uint32_t intr_in_enabled;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Local declarations
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void softsp_init(sbbc_softstate_t *, dev_info_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void sbbc_chosen_init(sbbc_softstate_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void sbbc_add_instance(sbbc_softstate_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void sbbc_remove_instance(sbbc_softstate_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int sbbc_find_dip(dev_info_t *, void *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void sbbc_unmap_regs(sbbc_softstate_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ops stuff.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct cb_ops sbbc_cb_ops = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodev, /* cb_open */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodev, /* cb_close */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodev, /* cb_strategy */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodev, /* cb_print */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodev, /* cb_dump */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodev, /* cb_read */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodev, /* cb_write */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodev, /* cb_ioctl */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodev, /* cb_devmap */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodev, /* cb_mmap */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodev, /* cb_segmap */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nochpoll, /* cb_chpoll */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_prop_op, /* cb_prop_op */
03831d35f7499c87d51205817c93e9a8d42c4baestevel NULL, /* cb_stream */
03831d35f7499c87d51205817c93e9a8d42c4baestevel D_NEW | D_MP /* cb_flag */
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Declare ops vectors for auto configuration.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstruct dev_ops sbbc_ops = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEVO_REV, /* devo_rev */
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0, /* devo_refcnt */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_getinfo_1to1, /* devo_getinfo */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nulldev, /* devo_identify */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nulldev, /* devo_probe */
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbbc_attach, /* devo_attach */
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbbc_detach, /* devo_detach */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodev, /* devo_reset */
03831d35f7499c87d51205817c93e9a8d42c4baestevel &sbbc_cb_ops, /* devo_cb_ops */
03831d35f7499c87d51205817c93e9a8d42c4baestevel (struct bus_ops *)NULL, /* devo_bus_ops */
193974072f41a843678abf5f61979c748687e66bSherry Moore nulldev, /* devo_power */
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_quiesce_not_supported, /* devo_quiesce */
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Loadable module support.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern struct mod_ops mod_driverops;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct modldrv modldrv = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel &mod_driverops, /* type of module - driver */
193974072f41a843678abf5f61979c748687e66bSherry Moore "PCI SBBC",
03831d35f7499c87d51205817c93e9a8d42c4baestevel &sbbc_ops,
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct modlinkage modlinkage = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel MODREV_1,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void *)&modldrv,
03831d35f7499c87d51205817c93e9a8d42c4baestevel NULL
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevel_init(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((error = ddi_soft_state_init(&sbbcp,
193974072f41a843678abf5f61979c748687e66bSherry Moore sizeof (sbbc_softstate_t), 1)) != 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((error = mod_install(&modlinkage)) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_soft_state_fini(&sbbcp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Initialise the global 'chosen' IOSRAM mutex
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_init(&chosen_lock, NULL, MUTEX_DEFAULT, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Initialise the iosram driver
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_init();
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Initialize the mailbox
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbbc_mbox_init();
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevel_fini(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((error = mod_remove(&modlinkage)) == 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_soft_state_fini(&sbbcp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel master_chosen = FALSE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_destroy(&chosen_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * remove the mailbox
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbbc_mbox_fini();
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * remove the iosram driver
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_fini();
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevel_info(struct modinfo *modinfop)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (mod_info(&modlinkage, modinfop));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbbc_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int instance;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbbc_softstate_t *softsp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t *pci_intr_enable_reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel char name[8];
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance = ddi_get_instance(devi);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (cmd) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DDI_ATTACH:
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_soft_state_zalloc(sbbcp, instance) != 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel softsp = ddi_get_soft_state(sbbcp, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel softsp->sbbc_instance = instance;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Set the dip in the soft state
03831d35f7499c87d51205817c93e9a8d42c4baestevel * And get interrupt cookies and initialize the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * per instance mutex.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel softsp_init(softsp, devi);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Verify that an 'interrupts' property exists for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * this device. If not, this instance will be ignored.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_getproplen(DDI_DEV_T_ANY, softsp->dip,
193974072f41a843678abf5f61979c748687e66bSherry Moore DDI_PROP_DONTPASS, "interrupts",
193974072f41a843678abf5f61979c748687e66bSherry Moore &len) != DDI_PROP_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBBC_ERR1(CE_WARN, "No 'interrupts' property for the "
193974072f41a843678abf5f61979c748687e66bSherry Moore "SBBC instance %d\n", instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Add this instance to the sbbc chosen iosram list
03831d35f7499c87d51205817c93e9a8d42c4baestevel * so that it can be used for tunnel switch.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&chosen_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel softsp->sbbc_state = SBBC_STATE_INIT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbbc_add_instance(softsp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If this is the chosen IOSRAM and there is no master IOSRAM
03831d35f7499c87d51205817c93e9a8d42c4baestevel * yet, then let's set this instance as the master.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * if there is a master alreay due to the previous tunnel switch
03831d35f7499c87d51205817c93e9a8d42c4baestevel * then keep as is even though this is the chosen.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sgsbbc_iosram_is_chosen(softsp)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(master_iosram);
03831d35f7499c87d51205817c93e9a8d42c4baestevel softsp->iosram = master_iosram;
03831d35f7499c87d51205817c93e9a8d42c4baestevel master_iosram->sgsbbc = softsp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Do 'chosen' init only */
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbbc_chosen_init(softsp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&chosen_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) sprintf(name, "sbbc%d", instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_create_minor_node(devi, name, S_IFCHR, instance,
193974072f41a843678abf5f61979c748687e66bSherry Moore NULL, NULL) == DDI_FAILURE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_destroy(&softsp->sbbc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_remove_minor_node(devi, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_soft_state_free(sbbcp, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_report_dev(devi);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DDI_RESUME:
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(softsp = ddi_get_soft_state(sbbcp, instance)))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&softsp->sbbc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((softsp->suspended == TRUE) && (softsp->chosen == TRUE)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Enable Interrupts now, turn on both INT#A lines
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel pci_intr_enable_reg = (uint32_t *)
193974072f41a843678abf5f61979c748687e66bSherry Moore ((char *)softsp->sbbc_regs +
193974072f41a843678abf5f61979c748687e66bSherry Moore SBBC_PCI_INT_ENABLE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_put32(softsp->sbbc_reg_handle1,
193974072f41a843678abf5f61979c748687e66bSherry Moore pci_intr_enable_reg,
193974072f41a843678abf5f61979c748687e66bSherry Moore (uint32_t)SBBC_PCI_ENABLE_INT_A);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Reset intr_in_enabled to the original value
03831d35f7499c87d51205817c93e9a8d42c4baestevel * so the SC can send us interrupt.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iosram_write(SBBC_SC_INTR_ENABLED_KEY,
193974072f41a843678abf5f61979c748687e66bSherry Moore 0, (caddr_t)&intr_in_enabled,
193974072f41a843678abf5f61979c748687e66bSherry Moore sizeof (intr_in_enabled))) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&softsp->sbbc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel softsp->suspended = FALSE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&softsp->sbbc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbbc_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbbc_softstate_t *softsp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int instance;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t *pci_intr_enable_reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rc = DDI_SUCCESS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance = ddi_get_instance(devi);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(softsp = ddi_get_soft_state(sbbcp, instance)))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (cmd) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DDI_DETACH:
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&chosen_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel softsp->sbbc_state |= SBBC_STATE_DETACH;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&chosen_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* only tunnel switch the instance with iosram chosen */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (softsp->chosen == TRUE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sgsbbc_iosram_switchfrom(softsp) == DDI_FAILURE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBBC_ERR(CE_WARN, "Cannot unconfigure: "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "tunnel switch failed\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Adjust linked list */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&chosen_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbbc_remove_instance(softsp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&chosen_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbbc_unmap_regs(softsp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_destroy(&softsp->sbbc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_soft_state_free(sbbcp, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DDI_SUSPEND:
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&softsp->sbbc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((softsp->suspended == FALSE) && (softsp->chosen == TRUE)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t tmp_intr_enabled = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Disable Interrupts now, turn OFF both INT#A lines
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel pci_intr_enable_reg = (uint32_t *)
193974072f41a843678abf5f61979c748687e66bSherry Moore ((char *)softsp->sbbc_regs +
193974072f41a843678abf5f61979c748687e66bSherry Moore SBBC_PCI_INT_ENABLE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_put32(softsp->sbbc_reg_handle1,
193974072f41a843678abf5f61979c748687e66bSherry Moore pci_intr_enable_reg, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Set intr_in_enabled to 0 so the SC won't send
03831d35f7499c87d51205817c93e9a8d42c4baestevel * us interrupt.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel rc = iosram_read(SBBC_SC_INTR_ENABLED_KEY,
193974072f41a843678abf5f61979c748687e66bSherry Moore 0, (caddr_t)&intr_in_enabled,
193974072f41a843678abf5f61979c748687e66bSherry Moore sizeof (intr_in_enabled));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rc) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&softsp->sbbc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rc = iosram_write(SBBC_SC_INTR_ENABLED_KEY,
193974072f41a843678abf5f61979c748687e66bSherry Moore 0, (caddr_t)&tmp_intr_enabled,
193974072f41a843678abf5f61979c748687e66bSherry Moore sizeof (tmp_intr_enabled));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rc) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&softsp->sbbc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel softsp->suspended = TRUE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&softsp->sbbc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelsoftsp_init(sbbc_softstate_t *softsp, dev_info_t *devi)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel softsp->dip = devi;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * XXXX
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ddi_get_iblock_cookie() here because we need
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to initialise the mutex regardless of whether
03831d35f7499c87d51205817c93e9a8d42c4baestevel * or not this SBBC will eventually
03831d35f7499c87d51205817c93e9a8d42c4baestevel * register an interrupt handler
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) ddi_get_iblock_cookie(devi, 0, &softsp->iblock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_init(&softsp->sbbc_lock, NULL, MUTEX_DRIVER,
193974072f41a843678abf5f61979c748687e66bSherry Moore (void *)softsp->iblock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel softsp->suspended = FALSE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel softsp->chosen = FALSE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbbc_find_dip(dev_info_t *dip, void *arg)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel char *node_name;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbbc_find_dip_t *dip_struct = (sbbc_find_dip_t *)arg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char status[OBP_MAXPROPNAME];
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Need to find a node named "bootbus-controller" that is neither
03831d35f7499c87d51205817c93e9a8d42c4baestevel * disabled nor failed. If a node is not ok, there will be an
03831d35f7499c87d51205817c93e9a8d42c4baestevel * OBP status property. Therefore, we will look for a node
03831d35f7499c87d51205817c93e9a8d42c4baestevel * without the status property.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel node_name = ddi_node_name(dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (strcmp(node_name, "bootbus-controller") == 0 && DDI_CF2(dip) &&
193974072f41a843678abf5f61979c748687e66bSherry Moore (prom_getprop(ddi_get_nodeid(dip),
193974072f41a843678abf5f61979c748687e66bSherry Moore "status", (caddr_t)status) == -1) &&
193974072f41a843678abf5f61979c748687e66bSherry Moore (prom_getprop(ddi_get_nodeid(ddi_get_parent(dip)),
193974072f41a843678abf5f61979c748687e66bSherry Moore "status", (caddr_t)status) == -1)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (dip != dip_struct->cur_dip) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dip_struct->new_dip = (void *)dip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_WALK_TERMINATE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_WALK_CONTINUE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SBBC Interrupt Handler
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check the SBBC Port Interrupt Status
03831d35f7499c87d51205817c93e9a8d42c4baestevel * register to verify that its our interrupt.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If yes, clear the register.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Then read the 'interrupt reason' field from SRAM,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * this triggers the appropriate soft_intr handler
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baesteveluint_t
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbbc_intr_handler(caddr_t arg)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbbc_softstate_t *softsp = (sbbc_softstate_t *)arg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t *port_int_reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel volatile uint32_t port_int_status;
03831d35f7499c87d51205817c93e9a8d42c4baestevel volatile uint32_t intr_reason;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t intr_enabled;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbbc_intrs_t *intr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i, intr_mask;
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct tunnel_key tunnel_key;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_acc_handle_t intr_in_handle;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t *intr_in_reason;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (softsp == (sbbc_softstate_t *)NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_INTR_UNCLAIMED);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&softsp->sbbc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (softsp->port_int_regs == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&softsp->sbbc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_INTR_UNCLAIMED);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Normally if port_int_status is 0, we assume it is not
03831d35f7499c87d51205817c93e9a8d42c4baestevel * our interrupt. However, we don't want to miss the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ones that come in during tunnel switch. Therefore,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * we always check the interrupt reason bits in IOSRAM
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to be sure.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel port_int_reg = softsp->port_int_regs;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel port_int_status = ddi_get32(softsp->sbbc_reg_handle1, port_int_reg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Generate a softint for each interrupt
03831d35f7499c87d51205817c93e9a8d42c4baestevel * bit set in the intr_in_reason field in SRAM
03831d35f7499c87d51205817c93e9a8d42c4baestevel * that has a corresponding bit set in the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * intr_in_enabled field in SRAM
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iosram_read(SBBC_SC_INTR_ENABLED_KEY, 0,
193974072f41a843678abf5f61979c748687e66bSherry Moore (caddr_t)&intr_enabled, sizeof (intr_enabled))) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto intr_handler_exit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel tunnel_key = master_iosram->tunnel->tunnel_keys[SBBC_SC_INTR_KEY];
03831d35f7499c87d51205817c93e9a8d42c4baestevel intr_in_reason = (uint32_t *)tunnel_key.base;
03831d35f7499c87d51205817c93e9a8d42c4baestevel intr_in_handle = tunnel_key.reg_handle;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel intr_reason = ddi_get32(intr_in_handle, intr_in_reason);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel SGSBBC_DBG_INTR(CE_CONT, "intr_reason = %x\n", intr_reason);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel intr_reason &= intr_enabled;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < SBBC_MAX_INTRS; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel intr_mask = (1 << i);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (intr_reason & intr_mask) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel intr = &softsp->intr_hdlrs[i];
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((intr != NULL) &&
193974072f41a843678abf5f61979c748687e66bSherry Moore (intr->sbbc_intr_id != 0)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * XXXX
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The model we agree with a handler
03831d35f7499c87d51205817c93e9a8d42c4baestevel * is that they run until they have
03831d35f7499c87d51205817c93e9a8d42c4baestevel * exhausted all work. To avoid
03831d35f7499c87d51205817c93e9a8d42c4baestevel * triggering them again, they pass
03831d35f7499c87d51205817c93e9a8d42c4baestevel * a state flag and lock when registering.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We check the flag, if they are idle,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * we trigger.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The interrupt handler should so
03831d35f7499c87d51205817c93e9a8d42c4baestevel * intr_func()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mutex_enter(sbbc_intr_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sbbc_intr_state = RUNNING;
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mutex_exit(sbbc_intr_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ..........
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ..........
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ..........
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mutex_enter(sbbc_intr_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sbbc_intr_state = IDLE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mutex_exit(sbbc_intr_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * XXXX
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(intr->sbbc_intr_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (*(intr->sbbc_intr_state) ==
193974072f41a843678abf5f61979c748687e66bSherry Moore SBBC_INTR_IDLE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(intr->sbbc_intr_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_trigger_softintr(
193974072f41a843678abf5f61979c748687e66bSherry Moore intr->sbbc_intr_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The handler is running
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(intr->sbbc_intr_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel intr_reason &= ~intr_mask;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Clear the corresponding reason bit in SRAM
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Since there is no interlocking between
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Solaris and the SC when writing to SRAM,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * it is possible for the SC to set another
03831d35f7499c87d51205817c93e9a8d42c4baestevel * bit in the interrupt reason field while
03831d35f7499c87d51205817c93e9a8d42c4baestevel * we are handling the current interrupt.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * To minimize the window in which an
03831d35f7499c87d51205817c93e9a8d42c4baestevel * additional bit can be set, reading
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and writing the interrupt reason
03831d35f7499c87d51205817c93e9a8d42c4baestevel * in SRAM must be as close as possible.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_put32(intr_in_handle, intr_in_reason,
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_get32(intr_in_handle,
193974072f41a843678abf5f61979c748687e66bSherry Moore intr_in_reason) & ~intr_mask);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (intr_reason == 0) /* No more interrupts to be processed */
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Clear the Interrupt Status Register (RW1C)
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_put32(softsp->sbbc_reg_handle1, port_int_reg, port_int_status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel port_int_status = ddi_get32(softsp->sbbc_reg_handle1, port_int_reg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelintr_handler_exit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&softsp->sbbc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_INTR_CLAIMED);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If we don't already have a master SBBC selected,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the <sbbc> property from the /chosen node. If
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the pathname matches, this is the master SBBC and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * we set up the console/TOD SRAM mapping here.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbbc_chosen_init(sbbc_softstate_t *softsp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel char master_sbbc[MAXNAMELEN];
03831d35f7499c87d51205817c93e9a8d42c4baestevel char pn[MAXNAMELEN];
03831d35f7499c87d51205817c93e9a8d42c4baestevel int nodeid, len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pnode_t dnode;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (master_chosen != FALSE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We've got one already
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Get /chosen node info. prom interface will handle errors.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel dnode = prom_chosennode();
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Look for the "iosram" property on the chosen node with a prom
03831d35f7499c87d51205817c93e9a8d42c4baestevel * interface as ddi_find_devinfo() couldn't be used (calls
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ddi_walk_devs() that creates one extra lock on the device tree).
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (prom_getprop(dnode, IOSRAM_CHOSEN_PROP, (caddr_t)&nodeid) <= 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * No I/O Board SBBC set up as console, what to do ?
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBBC_ERR(CE_PANIC, "No SBBC found for Console/TOD \n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (prom_getprop(dnode, IOSRAM_TOC_PROP,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (caddr_t)&softsp->sram_toc) <= 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SRAM TOC Offset defaults to 0
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBBC_ERR(CE_WARN, "No SBBC TOC Offset found\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel softsp->sram_toc = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the full OBP pathname of this node
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (prom_phandle_to_path((phandle_t)nodeid, master_sbbc,
193974072f41a843678abf5f61979c748687e66bSherry Moore sizeof (master_sbbc)) < 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBBC_ERR1(CE_PANIC, "prom_phandle_to_path(%d) failed\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodeid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel SGSBBC_DBG_ALL("chosen pathname : %s\n", master_sbbc);
03831d35f7499c87d51205817c93e9a8d42c4baestevel SGSBBC_DBG_ALL("device pathname : %s\n", ddi_pathname(softsp->dip, pn));
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (strcmp(master_sbbc, ddi_pathname(softsp->dip, pn)) == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * map in the SBBC regs
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sbbc_map_regs(softsp) != DDI_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBBC_ERR(CE_PANIC, "Can't map the SBBC regs \n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Only the 'chosen' node is used for iosram_read()/_write()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Must initialise the tunnel before the console/tod
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iosram_tunnel_init(softsp) == DDI_FAILURE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBBC_ERR(CE_PANIC, "Can't create the SRAM <-> SC "
193974072f41a843678abf5f61979c748687e66bSherry Moore "comm. tunnel \n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel master_chosen = TRUE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Verify that an 'interrupts' property
03831d35f7499c87d51205817c93e9a8d42c4baestevel * exists for this device
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_getproplen(DDI_DEV_T_ANY, softsp->dip,
193974072f41a843678abf5f61979c748687e66bSherry Moore DDI_PROP_DONTPASS, "interrupts",
193974072f41a843678abf5f61979c748687e66bSherry Moore &len) != DDI_PROP_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBBC_ERR(CE_PANIC, "No 'interrupts' property for the "
193974072f41a843678abf5f61979c748687e66bSherry Moore "'chosen' SBBC \n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * add the interrupt handler
03831d35f7499c87d51205817c93e9a8d42c4baestevel * NB
03831d35f7499c87d51205817c93e9a8d42c4baestevel * should this be a high-level interrupt ?
03831d35f7499c87d51205817c93e9a8d42c4baestevel * NB
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sbbc_add_intr(softsp) == DDI_FAILURE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel SBBC_ERR(CE_PANIC, "Can't add interrupt handler for "
193974072f41a843678abf5f61979c748687e66bSherry Moore "'chosen' SBBC \n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel sbbc_enable_intr(softsp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Create the mailbox
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sbbc_mbox_create(softsp) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "No IOSRAM MailBox created!\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sbbc_add_instance
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Must be called to hold chosen_lock.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbbc_add_instance(sbbc_softstate_t *softsp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct sbbc_softstate *sp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mutex_owned(&chosen_lock));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#if defined(DEBUG)
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Verify that this instance is not in the list yet */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (sp = sgsbbc_instances; sp != NULL; sp = sp->next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(sp != softsp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Add this instance to the front of the list.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sgsbbc_instances != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel sgsbbc_instances->prev = softsp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel softsp->next = sgsbbc_instances;
03831d35f7499c87d51205817c93e9a8d42c4baestevel softsp->prev = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel sgsbbc_instances = softsp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbbc_remove_instance(sbbc_softstate_t *softsp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct sbbc_softstate *sp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (sp = sgsbbc_instances; sp != NULL; sp = sp->next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sp == softsp) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sp->next != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel sp->next->prev = sp->prev;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sp->prev != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel sp->prev->next = sp->next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (sgsbbc_instances == softsp) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel sgsbbc_instances = sp->next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Generate an SBBC interrupt to the SC
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Called from iosram_send_intr()
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * send_intr == 0, check if EPLD register clear
03831d35f7499c87d51205817c93e9a8d42c4baestevel * for sync'ing SC/OS
03831d35f7499c87d51205817c93e9a8d42c4baestevel * send_intr == 1, send the interrupt
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbbc_send_intr(sbbc_softstate_t *softsp, int send_intr)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t *epld_int;
03831d35f7499c87d51205817c93e9a8d42c4baestevel volatile uchar_t epld_status;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(MUTEX_HELD(&master_iosram->iosram_lock));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((softsp == (sbbc_softstate_t *)NULL) ||
193974072f41a843678abf5f61979c748687e66bSherry Moore (softsp->epld_regs == (struct sbbc_epld_regs *)NULL))
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ENXIO);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check the L1 EPLD Interrupt register. If the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * interrupt bit is set, theres an interrupt outstanding
03831d35f7499c87d51205817c93e9a8d42c4baestevel * (we assume) so return (EBUSY).
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel epld_int = &softsp->epld_regs->epld_reg[EPLD_INTERRUPT];
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel epld_status = ddi_get8(softsp->sbbc_reg_handle2, epld_int);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (epld_status & INTERRUPT_ON)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EBUSY);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (send_intr == TRUE)
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_put8(softsp->sbbc_reg_handle2, epld_int,
193974072f41a843678abf5f61979c748687e66bSherry Moore (epld_status | INTERRUPT_ON));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Map SBBC Internal registers
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The call to function should be protected by
03831d35f7499c87d51205817c93e9a8d42c4baestevel * chosen_lock or master_iosram->iosram_lock
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to make sure a tunnel switch will not occur
03831d35f7499c87d51205817c93e9a8d42c4baestevel * in a middle of mapping.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbbc_map_regs(sbbc_softstate_t *softsp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct ddi_device_acc_attr attr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel attr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC;
03831d35f7499c87d51205817c93e9a8d42c4baestevel attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Map in register set 1, Common Device Regs
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SBCC offset 0x0
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_regs_map_setup(softsp->dip, RNUM_SBBC_REGS,
193974072f41a843678abf5f61979c748687e66bSherry Moore (caddr_t *)&softsp->sbbc_regs,
193974072f41a843678abf5f61979c748687e66bSherry Moore SBBC_REGS_OFFSET, SBBC_REGS_SIZE,
193974072f41a843678abf5f61979c748687e66bSherry Moore &attr, &softsp->sbbc_reg_handle1) != DDI_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "sbbc%d: unable to map interrupt "
193974072f41a843678abf5f61979c748687e66bSherry Moore "registers", ddi_get_instance(softsp->dip));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Map in using register set 1, EPLD
03831d35f7499c87d51205817c93e9a8d42c4baestevel * SBCC offset 0xe000
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_regs_map_setup(softsp->dip, RNUM_SBBC_REGS,
193974072f41a843678abf5f61979c748687e66bSherry Moore (caddr_t *)&softsp->epld_regs,
193974072f41a843678abf5f61979c748687e66bSherry Moore SBBC_EPLD_OFFSET, SBBC_EPLD_SIZE,
193974072f41a843678abf5f61979c748687e66bSherry Moore &attr, &softsp->sbbc_reg_handle2) != DDI_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "sbbc%d: unable to map EPLD "
193974072f41a843678abf5f61979c748687e66bSherry Moore "registers", ddi_get_instance(softsp->dip));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Set up pointers for registers
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel softsp->port_int_regs = (uint32_t *)((char *)softsp->sbbc_regs +
193974072f41a843678abf5f61979c748687e66bSherry Moore SBBC_PCI_INT_STATUS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelmap_regs_exit:
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Unmap SBBC Internal registers
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbbc_unmap_regs(sbbc_softstate_t *softsp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (softsp == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&master_iosram->iosram_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (softsp->sbbc_regs) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_regs_map_free(&softsp->sbbc_reg_handle1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel softsp->sbbc_regs = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel softsp->port_int_regs = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (softsp->epld_regs) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_regs_map_free(&softsp->sbbc_reg_handle2);
03831d35f7499c87d51205817c93e9a8d42c4baestevel softsp->epld_regs = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&master_iosram->iosram_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This is here to allow the IOSRAM driver get the softstate
03831d35f7499c87d51205817c93e9a8d42c4baestevel * for a chosen node when doing a tunnel switch. Just enables
03831d35f7499c87d51205817c93e9a8d42c4baestevel * us to avoid exporting the sbbcp softstate hook
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbbc_softstate_t *
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbbc_get_soft_state(int instance)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ddi_get_soft_state(sbbcp, instance));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Add interrupt handlers
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbbc_add_intr(sbbc_softstate_t *softsp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rc = DDI_SUCCESS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * map in the SBBC interrupts
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Note that the iblock_cookie was initialised
03831d35f7499c87d51205817c93e9a8d42c4baestevel * in the 'attach' routine
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_add_intr(softsp->dip, 0, &softsp->iblock,
193974072f41a843678abf5f61979c748687e66bSherry Moore &softsp->idevice, sbbc_intr_handler,
193974072f41a843678abf5f61979c748687e66bSherry Moore (caddr_t)softsp) != DDI_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "Can't register SBBC "
193974072f41a843678abf5f61979c748687e66bSherry Moore " interrupt handler\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel rc = DDI_FAILURE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (rc);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbbc_enable_intr(sbbc_softstate_t *softsp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t *pci_intr_enable_reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Enable Interrupts now, turn on both INT#A lines
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel pci_intr_enable_reg = (uint32_t *)((char *)softsp->sbbc_regs +
193974072f41a843678abf5f61979c748687e66bSherry Moore SBBC_PCI_INT_ENABLE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_put32(softsp->sbbc_reg_handle1, pci_intr_enable_reg,
193974072f41a843678abf5f61979c748687e66bSherry Moore (uint32_t)SBBC_PCI_ENABLE_INT_A);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelsbbc_disable_intr(sbbc_softstate_t *softsp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t *pci_intr_enable_reg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Disable Interrupts now, turn off both INT#A lines
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel pci_intr_enable_reg = (uint32_t *)((char *)softsp->sbbc_regs +
193974072f41a843678abf5f61979c748687e66bSherry Moore SBBC_PCI_INT_ENABLE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_put32(softsp->sbbc_reg_handle1, pci_intr_enable_reg, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}