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/*
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Use is subject to license terms.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * IOSRAM leaf driver to SBBC nexus driver. This driver is used
03831d35f7499c87d51205817c93e9a8d42c4baestevel * by Starcat Domain SW to read/write from/to the IO sram.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/types.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/conf.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/ddi.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sunddi.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/ddi_impldefs.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/obpdefs.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/promif.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/prom_plat.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/cmn_err.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/conf.h> /* req. by dev_ops flags MTSAFE etc. */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/modctl.h> /* for modldrv */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/stat.h> /* ddi_create_minor_node S_IFCHR */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/errno.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/kmem.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/kstat.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/debug.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/axq.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/iosramreg.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/iosramio.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/iosramvar.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#if defined(DEBUG)
03831d35f7499c87d51205817c93e9a8d42c4baestevelint iosram_debug = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void iosram_dprintf(const char *fmt, ...);
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DPRINTF(level, arg) \
03831d35f7499c87d51205817c93e9a8d42c4baestevel { if (iosram_debug >= level) iosram_dprintf arg; }
03831d35f7499c87d51205817c93e9a8d42c4baestevel#else /* !DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DPRINTF(level, arg)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* !DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * IOSRAM module global state
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void *iosramsoft_statep; /* IOSRAM state pointer */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic kmutex_t iosram_mutex; /* mutex lock */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic iosram_chunk_t *chunks = NULL; /* array of TOC entries */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int nchunks = 0; /* # of TOC entries */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic iosram_chunk_t *iosram_hashtab[IOSRAM_HASHSZ]; /* key hash table */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic kcondvar_t iosram_tswitch_wait; /* tunnel switch wait cv */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int iosram_tswitch_wakeup = 0; /* flag indicationg one or */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* more threads waiting on */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* iosram_tswitch_wait cv */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int iosram_tswitch_active = 0; /* tunnel switch active flag */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int iosram_tswitch_aborted = 0; /* tunnel switch abort flag */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic clock_t iosram_tswitch_tstamp = 0; /* lbolt of last tswitch end */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic kcondvar_t iosram_rw_wait; /* read/write wait cv */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int iosram_rw_wakeup = 0; /* flag indicationg one or */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* more threads waiting on */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* iosram_rw_wait cv */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int iosram_rw_active = 0; /* # threads accessing IOSRAM */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#if defined(DEBUG)
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int iosram_rw_active_max = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct iosramsoft *iosram_new_master = NULL; /* new tunnel target */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct iosramsoft *iosram_master = NULL; /* master tunnel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct iosramsoft *iosram_instances = NULL; /* list of softstates */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic ddi_acc_handle_t iosram_handle = NULL; /* master IOSRAM map handle */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void (*iosram_hdrchange_handler)() = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#if IOSRAM_STATS
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct iosram_stat iosram_stats; /* IOSRAM statistics */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void iosram_print_stats(); /* forward declaration */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* IOSRAM_STATS */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#if IOSRAM_LOG
03831d35f7499c87d51205817c93e9a8d42c4baestevelkmutex_t iosram_log_mutex;
03831d35f7499c87d51205817c93e9a8d42c4baestevelint iosram_log_level = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevelint iosram_log_print = 0; /* print log when recorded */
03831d35f7499c87d51205817c93e9a8d42c4baesteveluint32_t iosram_logseq;
03831d35f7499c87d51205817c93e9a8d42c4baesteveliosram_log_t iosram_logbuf[IOSRAM_MAXLOG];
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void iosram_print_log(int cnt); /* forward declaration */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* IOSRAM_LOG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* driver entry point fn definitions */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int iosram_open(dev_t *, int, int, cred_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int iosram_close(dev_t, int, int, cred_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int iosram_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* configuration entry point fn definitions */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int iosram_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int iosram_attach(dev_info_t *, ddi_attach_cmd_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int iosram_detach(dev_info_t *, ddi_detach_cmd_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* forward declaractions */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic iosram_chunk_t *iosram_find_chunk(uint32_t key);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void iosram_set_master(struct iosramsoft *softp);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int iosram_is_chosen(struct iosramsoft *softp);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int iosram_tunnel_capable(struct iosramsoft *softp);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int iosram_read_toc(struct iosramsoft *softp);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void iosram_init_hashtab(void);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void iosram_update_addrs(struct iosramsoft *softp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int iosram_setup_map(struct iosramsoft *softp);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void iosram_remove_map(struct iosramsoft *softp);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int iosram_add_intr(iosramsoft_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int iosram_remove_intr(iosramsoft_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void iosram_add_instance(struct iosramsoft *softp);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void iosram_remove_instance(int instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int iosram_switch_tunnel(iosramsoft_t *softp);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void iosram_abort_tswitch();
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#if defined(DEBUG)
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* forward declaractions for debugging */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int iosram_get_keys(iosram_toc_entry_t *buf, uint32_t *len);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void iosram_print_cback();
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void iosram_print_state(int);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void iosram_print_flags();
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cb_ops
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct cb_ops iosram_cb_ops = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_open, /* cb_open */
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_close, /* cb_close */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodev, /* cb_strategy */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodev, /* cb_print */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodev, /* cb_dump */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodev, /* cb_read */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodev, /* cb_write */
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_ioctl, /* 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 (int)(D_NEW | D_MP | D_HOTPLUG) /* cb_flag */
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Declare ops vectors for auto configuration.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstruct dev_ops iosram_ops = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DEVO_REV, /* devo_rev */
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0, /* devo_refcnt */
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_getinfo, /* devo_getinfo */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nulldev, /* devo_identify */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nulldev, /* devo_probe */
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_attach, /* devo_attach */
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_detach, /* devo_detach */
03831d35f7499c87d51205817c93e9a8d42c4baestevel nodev, /* devo_reset */
03831d35f7499c87d51205817c93e9a8d42c4baestevel &iosram_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 iosrammodldrv = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel &mod_driverops, /* type of module - driver */
193974072f41a843678abf5f61979c748687e66bSherry Moore "IOSRAM Leaf driver",
03831d35f7499c87d51205817c93e9a8d42c4baestevel &iosram_ops,
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct modlinkage iosrammodlinkage = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel MODREV_1,
03831d35f7499c87d51205817c93e9a8d42c4baestevel &iosrammodldrv,
03831d35f7499c87d51205817c93e9a8d42c4baestevel NULL
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevel_init(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_init(&iosram_mutex, NULL, MUTEX_DRIVER, (void *)NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_init(&iosram_tswitch_wait, NULL, CV_DRIVER, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_init(&iosram_rw_wait, NULL, CV_DRIVER, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel#if defined(IOSRAM_LOG)
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_init(&iosram_log_mutex, NULL, MUTEX_DRIVER, (void *)NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("_init:IOSRAM\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < IOSRAM_HASHSZ; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_hashtab[i] = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((error = ddi_soft_state_init(&iosramsoft_statep,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sizeof (struct iosramsoft), 1)) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto failed;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((error = mod_install(&iosrammodlinkage)) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_soft_state_fini(&iosramsoft_statep);
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto failed;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(0, "_init:IOSRAM ... error:%d statep:%p\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel error, iosramsoft_statep, NULL, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelfailed:
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_destroy(&iosram_tswitch_wait);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_destroy(&iosram_rw_wait);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_destroy(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel#if defined(IOSRAM_LOG)
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_destroy(&iosram_log_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(0, "_init:IOSRAM ... error:%d statep:%p\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel error, iosramsoft_statep, NULL, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevel_fini(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifndef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EBUSY);
03831d35f7499c87d51205817c93e9a8d42c4baestevel#else /* !DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((error = mod_remove(&iosrammodlinkage)) == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_soft_state_fini(&iosramsoft_statep);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_destroy(&iosram_tswitch_wait);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_destroy(&iosram_rw_wait);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_destroy(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel#if defined(IOSRAM_LOG)
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_destroy(&iosram_log_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("_fini:IOSRAM error:%d\n", error));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* !DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevel_info(struct modinfo *modinfop)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (mod_info(&iosrammodlinkage, modinfop));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveliosram_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int instance;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int propval;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int length;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char name[32];
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct iosramsoft *softp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance = ddi_get_instance(dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki DPRINTF(1, ("iosram(%d): attach dip:%p\n", instance, (void *)dip));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(1, "ATTACH: dip:%p instance %d ... start\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel dip, instance, NULL, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (cmd) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DDI_ATTACH:
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DDI_RESUME:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(softp = ddi_get_soft_state(iosramsoft_statep,
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance))) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&softp->intr_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!softp->suspended) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&softp->intr_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->suspended = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * enable SBBC interrupts if SBBC is mapped in
03831d35f7499c87d51205817c93e9a8d42c4baestevel * restore the value saved during detach
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (softp->sbbc_region) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_put32(softp->sbbc_handle,
03831d35f7499c87d51205817c93e9a8d42c4baestevel &(softp->sbbc_region->int_enable.reg),
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->int_enable_sav);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Trigger soft interrupt handler to process any pending
03831d35f7499c87d51205817c93e9a8d42c4baestevel * interrupts.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (softp->intr_pending && !softp->intr_busy &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel (softp->softintr_id != NULL)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_trigger_softintr(softp->softintr_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&softp->intr_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_soft_state_zalloc(iosramsoft_statep, instance) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((softp = ddi_get_soft_state(iosramsoft_statep, instance)) == NULL) {
193974072f41a843678abf5f61979c748687e66bSherry Moore return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->dip = dip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->instance = instance;
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->sbbc_region = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If this instance is not tunnel capable, we don't attach it.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iosram_tunnel_capable(softp) == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("iosram(%d): not tunnel_capable\n", instance));
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(1, "ATTACH(%d): not tunnel_capable\n", instance, NULL,
03831d35f7499c87d51205817c93e9a8d42c4baestevel NULL, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto attach_fail;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Need to create an "interrupt-priorities" property to define the PIL
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to be used with the interrupt service routine.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_getproplen(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "interrupt-priorities", &length) == DDI_PROP_NOT_FOUND) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("iosram(%d): creating interrupt priority property",
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance));
03831d35f7499c87d51205817c93e9a8d42c4baestevel propval = IOSRAM_PIL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_prop_create(DDI_DEV_T_NONE, dip, 0,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "interrupt-priorities", (caddr_t)&propval, sizeof (propval))
03831d35f7499c87d51205817c93e9a8d42c4baestevel != DDI_PROP_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "iosram_attach: failed to create property");
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto attach_fail;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Get interrupts cookies and initialize per-instance mutexes
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_get_iblock_cookie(softp->dip, 0, &softp->real_iblk)
03831d35f7499c87d51205817c93e9a8d42c4baestevel != DDI_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(1, "ATTACH(%d): cannot get soft intr cookie\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance, NULL, NULL, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto attach_fail;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_init(&softp->intr_mutex, NULL, MUTEX_DRIVER,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void *)softp->real_iblk);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Add this instance to the iosram_instances list so that it can be used
03831d35f7499c87d51205817c93e9a8d42c4baestevel * for tunnel in future.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->state = IOSRAM_STATE_INIT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_add_instance(softp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If this is the chosen IOSRAM and there is no master IOSRAM yet, then
03831d35f7499c87d51205817c93e9a8d42c4baestevel * let's set this instance as the master.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iosram_master == NULL && iosram_is_chosen(softp)) {
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) iosram_switch_tunnel(softp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * XXX Do we need to panic if unable to setup master IOSRAM?
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iosram_master == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "iosram(%d): can't setup master tunnel\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->state = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_remove_instance(softp->instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_destroy(&softp->intr_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto attach_fail;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Create minor node
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) sprintf(name, "iosram%d", instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_create_minor_node(dip, name, S_IFCHR, instance, NULL, NULL) ==
03831d35f7499c87d51205817c93e9a8d42c4baestevel DDI_FAILURE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Minor node seems to be needed only for debugging purposes.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Therefore, there is no need to fail this attach request.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Simply print a message out.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "!iosram(%d): can't create minor node\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_report_dev(dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("iosram_attach(%d): success.\n", instance));
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(1, "ATTACH: dip:%p instance:%d ... success softp:%p\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel dip, instance, softp, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelattach_fail:
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("iosram_attach(%d):failed.\n", instance));
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(1, "ATTACH: dip:%p instance:%d ... failed.\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel dip, instance, NULL, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_soft_state_free(iosramsoft_statep, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveliosram_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int instance;
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct iosramsoft *softp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance = ddi_get_instance(dip);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(softp = ddi_get_soft_state(iosramsoft_statep, instance))) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(1, "DETACH: dip:%p instance %d softp:%p\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel dip, instance, softp, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (cmd) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DDI_DETACH:
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DDI_SUSPEND:
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&softp->intr_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (softp->suspended) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&softp->intr_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->suspended = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Disable SBBC interrupts if SBBC is mapped in
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (softp->sbbc_region) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* save current interrupt enable register */
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->int_enable_sav = ddi_get32(softp->sbbc_handle,
03831d35f7499c87d51205817c93e9a8d42c4baestevel &(softp->sbbc_region->int_enable.reg));
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_put32(softp->sbbc_handle,
03831d35f7499c87d51205817c93e9a8d42c4baestevel &(softp->sbbc_region->int_enable.reg), 0x0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&softp->intr_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Indicate that this instance is being detached so that this instance
03831d35f7499c87d51205817c93e9a8d42c4baestevel * does not become a target for tunnel switch in future.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->state |= IOSRAM_STATE_DETACH;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If this instance is currently the master or the target of the tunnel
03831d35f7499c87d51205817c93e9a8d42c4baestevel * switch, then we need to wait and switch tunnel, if necessary.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iosram_master == softp || (softp->state & IOSRAM_STATE_TSWITCH)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) iosram_switchfrom(instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If the tunnel switch is in progress and we are the master or target
03831d35f7499c87d51205817c93e9a8d42c4baestevel * of tunnel relocation, then we can't detach this instance right now.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (softp->state & IOSRAM_STATE_TSWITCH) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->state &= ~IOSRAM_STATE_DETACH;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We can't allow master IOSRAM to be detached as we won't be able to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * communicate otherwise.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iosram_master == softp) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->state &= ~IOSRAM_STATE_DETACH;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Now remove our instance from the iosram_instances list.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_remove_instance(instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Instances should only ever be mapped if they are the master and/or
03831d35f7499c87d51205817c93e9a8d42c4baestevel * participating in a tunnel switch. Neither should be the case here.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT((softp->state & IOSRAM_STATE_MAPPED) == 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Destroy per-instance mutexes
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_destroy(&softp->intr_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_remove_minor_node(dip, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Finally remove our soft state structure
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_soft_state_free(iosramsoft_statep, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED0 */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveliosram_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
03831d35f7499c87d51205817c93e9a8d42c4baestevel void **result)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev_t dev = (dev_t)arg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct iosramsoft *softp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int instance, ret;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance = getminor(dev);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(2, "GETINFO: dip:%x instance %d dev:%x infocmd:%x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel dip, instance, dev, infocmd);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (infocmd) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DDI_INFO_DEVT2DEVINFO:
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp = ddi_get_soft_state(iosramsoft_statep, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (softp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel *result = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ret = DDI_FAILURE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel *result = softp->dip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ret = DDI_SUCCESS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DDI_INFO_DEVT2INSTANCE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel *result = (void *)(uintptr_t)instance;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ret = DDI_SUCCESS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel ret = DDI_FAILURE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ret);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED1*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveliosram_open(dev_t *dev, int flag, int otype, cred_t *credp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct iosramsoft *softp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int instance;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance = getminor(*dev);
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp = ddi_get_soft_state(iosramsoft_statep, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (softp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ENXIO);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(1, "OPEN: dev:%p otype:%x ... instance:%d softp:%p\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel *dev, otype, softp->instance, softp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED1*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveliosram_close(dev_t dev, int flag, int otype, cred_t *credp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct iosramsoft *softp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int instance;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance = getminor(dev);
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp = ddi_get_soft_state(iosramsoft_statep, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (softp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ENXIO);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(1, "CLOSE: dev:%p otype:%x ... instance:%d softp:%p\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev, otype, softp->instance, softp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baesteveliosram_rd(uint32_t key, uint32_t off, uint32_t len, caddr_t dptr)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_chunk_t *chunkp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t chunk_len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint8_t *iosramp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_acc_handle_t handle;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int boff;
03831d35f7499c87d51205817c93e9a8d42c4baestevel union {
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t cbuf[UINT32SZ];
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t data;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } word;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint8_t *buf = (uint8_t *)dptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We try to read from the IOSRAM using double word or word access
03831d35f7499c87d51205817c93e9a8d42c4baestevel * provided both "off" and "buf" are (or can be) double word or word
03831d35f7499c87d51205817c93e9a8d42c4baestevel * aligned. Othewise, we try to align the "off" to a word boundary and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * then try to read data from the IOSRAM using word access, but store it
03831d35f7499c87d51205817c93e9a8d42c4baestevel * into buf buffer using byte access.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If the leading/trailing portion of the IOSRAM data is not word
03831d35f7499c87d51205817c93e9a8d42c4baestevel * aligned, it will always be copied using byte access.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(1, "RD: key: 0x%x off:%x len:%x buf:%p\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel key, off, len, buf);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Acquire lock and look for the requested chunk. If it exists, make
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sure the requested read is within the chunk's bounds and no tunnel
03831d35f7499c87d51205817c93e9a8d42c4baestevel * switch is active.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel chunkp = iosram_find_chunk(key);
03831d35f7499c87d51205817c93e9a8d42c4baestevel chunk_len = (chunkp != NULL) ? chunkp->toc_data.len : 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iosram_master == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EIO;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (chunkp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if ((off >= chunk_len) || (len > chunk_len) ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel ((off + len) > chunk_len)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EMSGSIZE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (iosram_tswitch_active) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EAGAIN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Bump reference count to indicate #thread accessing IOSRAM and release
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the lock.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_rw_active++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel#if defined(DEBUG)
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iosram_rw_active > iosram_rw_active_max) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_rw_active_max = iosram_rw_active;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAM_STAT(read);
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAM_STAT_ADD(bread, len);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Get starting address and map handle */
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosramp = chunkp->basep + off;
03831d35f7499c87d51205817c93e9a8d42c4baestevel handle = iosram_handle;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Align the off to word boundary and then try reading/writing data
03831d35f7499c87d51205817c93e9a8d42c4baestevel * using double word or word access.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((boff = ((uintptr_t)iosramp & (UINT32SZ - 1))) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int cnt = UINT32SZ - boff;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cnt > len) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cnt = len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(2,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "RD: align rep_get8(buf:%p sramp:%p cnt:%x) len:%x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel buf, iosramp, cnt, len);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_rep_get8(handle, buf, iosramp, cnt, DDI_DEV_AUTOINCR);
03831d35f7499c87d51205817c93e9a8d42c4baestevel buf += cnt;
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosramp += cnt;
03831d35f7499c87d51205817c93e9a8d42c4baestevel len -= cnt;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((len >= UINT64SZ) &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel ((((uintptr_t)iosramp | (uintptr_t)buf) & (UINT64SZ - 1)) == 0)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Both source and destination are double word aligned
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel int cnt = len/UINT64SZ;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(2,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "RD: rep_get64(buf:%p sramp:%p cnt:%x) len:%x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel buf, iosramp, cnt, len);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_rep_get64(handle, (uint64_t *)buf, (uint64_t *)iosramp,
03831d35f7499c87d51205817c93e9a8d42c4baestevel cnt, DDI_DEV_AUTOINCR);
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosramp += cnt * UINT64SZ;
03831d35f7499c87d51205817c93e9a8d42c4baestevel buf += cnt * UINT64SZ;
03831d35f7499c87d51205817c93e9a8d42c4baestevel len -= cnt * UINT64SZ;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * read remaining data using word and byte access
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (len >= UINT32SZ) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(2,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "RD: get32(buf:%p sramp:%p) len:%x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel buf, iosramp, len, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel *(uint32_t *)buf = ddi_get32(handle,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (uint32_t *)iosramp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosramp += UINT32SZ;
03831d35f7499c87d51205817c93e9a8d42c4baestevel buf += UINT32SZ;
03831d35f7499c87d51205817c93e9a8d42c4baestevel len -= UINT32SZ;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (len != 0) {
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_rep_get8(handle, buf, iosramp, len,
193974072f41a843678abf5f61979c748687e66bSherry Moore DDI_DEV_AUTOINCR);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if ((len >= UINT32SZ) &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel ((((uintptr_t)iosramp | (uintptr_t)buf) & (UINT32SZ - 1)) == 0)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Both source and destination are word aligned
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel int cnt = len/UINT32SZ;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(2,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "RD: rep_get32(buf:%p sramp:%p cnt:%x) len:%x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel buf, iosramp, cnt, len);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_rep_get32(handle, (uint32_t *)buf, (uint32_t *)iosramp,
03831d35f7499c87d51205817c93e9a8d42c4baestevel cnt, DDI_DEV_AUTOINCR);
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosramp += cnt * UINT32SZ;
03831d35f7499c87d51205817c93e9a8d42c4baestevel buf += cnt * UINT32SZ;
03831d35f7499c87d51205817c93e9a8d42c4baestevel len -= cnt * UINT32SZ;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * copy the remainder using byte access
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (len != 0) {
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_rep_get8(handle, buf, iosramp, len,
193974072f41a843678abf5f61979c748687e66bSherry Moore DDI_DEV_AUTOINCR);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (len != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We know that the "off" (i.e. iosramp) is at least word
03831d35f7499c87d51205817c93e9a8d42c4baestevel * aligned. We need to read IOSRAM word at a time and copy it
03831d35f7499c87d51205817c93e9a8d42c4baestevel * byte at a time.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(((uintptr_t)iosramp & (UINT32SZ - 1)) == 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(2,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "RD: unaligned get32(buf:%p sramp:%p) len:%x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel buf, iosramp, len, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (; len >= UINT32SZ; len -= UINT32SZ, iosramp += UINT32SZ) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel word.data = ddi_get32(handle, (uint32_t *)iosramp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel *buf++ = word.cbuf[0];
03831d35f7499c87d51205817c93e9a8d42c4baestevel *buf++ = word.cbuf[1];
03831d35f7499c87d51205817c93e9a8d42c4baestevel *buf++ = word.cbuf[2];
03831d35f7499c87d51205817c93e9a8d42c4baestevel *buf++ = word.cbuf[3];
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * copy the remaining data using byte access
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (len != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_rep_get8(handle, buf, iosramp, len,
03831d35f7499c87d51205817c93e9a8d42c4baestevel DDI_DEV_AUTOINCR);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Reacquire mutex lock, decrement refcnt and if refcnt is 0 and any
03831d35f7499c87d51205817c93e9a8d42c4baestevel * threads are waiting for r/w activity to complete, wake them up.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(iosram_rw_active > 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((--iosram_rw_active == 0) && iosram_rw_wakeup) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_rw_wakeup = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_broadcast(&iosram_rw_wait);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * _iosram_write(key, off, len, dptr, force)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Internal common routine to write to the IOSRAM.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevel_iosram_write(uint32_t key, uint32_t off, uint32_t len, caddr_t dptr, int force)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_chunk_t *chunkp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t chunk_len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint8_t *iosramp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_acc_handle_t handle;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int boff;
03831d35f7499c87d51205817c93e9a8d42c4baestevel union {
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint8_t cbuf[UINT32SZ];
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t data;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } word;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint8_t *buf = (uint8_t *)dptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We try to write to the IOSRAM using double word or word access
03831d35f7499c87d51205817c93e9a8d42c4baestevel * provided both "off" and "buf" are (or can be) double word or word
03831d35f7499c87d51205817c93e9a8d42c4baestevel * aligned. Othewise, we try to align the "off" to a word boundary and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * then try to write data to the IOSRAM using word access, but read data
03831d35f7499c87d51205817c93e9a8d42c4baestevel * from the buf buffer using byte access.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If the leading/trailing portion of the IOSRAM data is not word
03831d35f7499c87d51205817c93e9a8d42c4baestevel * aligned, it will always be written using byte access.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(1, "WR: key: 0x%x off:%x len:%x buf:%p\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel key, off, len, buf);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Acquire lock and look for the requested chunk. If it exists, make
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sure the requested write is within the chunk's bounds and no tunnel
03831d35f7499c87d51205817c93e9a8d42c4baestevel * switch is active.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel chunkp = iosram_find_chunk(key);
03831d35f7499c87d51205817c93e9a8d42c4baestevel chunk_len = (chunkp != NULL) ? chunkp->toc_data.len : 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iosram_master == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EIO;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (chunkp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if ((off >= chunk_len) || (len > chunk_len) ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel ((off+len) > chunk_len)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EMSGSIZE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (iosram_tswitch_active && !force) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EAGAIN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If this is a forced write and there's a tunnel switch in progress,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * abort the switch.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iosram_tswitch_active && force) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "!iosram: Aborting tswitch on force_write");
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_abort_tswitch();
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Bump reference count to indicate #thread accessing IOSRAM
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and release the lock.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_rw_active++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel#if defined(DEBUG)
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iosram_rw_active > iosram_rw_active_max) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_rw_active_max = iosram_rw_active;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAM_STAT(write);
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAM_STAT_ADD(bwrite, len);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Get starting address and map handle */
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosramp = chunkp->basep + off;
03831d35f7499c87d51205817c93e9a8d42c4baestevel handle = iosram_handle;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Align the off to word boundary and then try reading/writing
03831d35f7499c87d51205817c93e9a8d42c4baestevel * data using double word or word access.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((boff = ((uintptr_t)iosramp & (UINT32SZ - 1))) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int cnt = UINT32SZ - boff;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cnt > len) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cnt = len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(2,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "WR: align rep_put8(buf:%p sramp:%p cnt:%x) len:%x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel buf, iosramp, cnt, len);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_rep_put8(handle, buf, iosramp, cnt, DDI_DEV_AUTOINCR);
03831d35f7499c87d51205817c93e9a8d42c4baestevel buf += cnt;
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosramp += cnt;
03831d35f7499c87d51205817c93e9a8d42c4baestevel len -= cnt;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((len >= UINT64SZ) &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel ((((uintptr_t)iosramp | (uintptr_t)buf) & (UINT64SZ - 1)) == 0)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Both source and destination are double word aligned
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel int cnt = len/UINT64SZ;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(2,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "WR: rep_put64(buf:%p sramp:%p cnt:%x) len:%x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel buf, iosramp, cnt, len);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_rep_put64(handle, (uint64_t *)buf, (uint64_t *)iosramp,
03831d35f7499c87d51205817c93e9a8d42c4baestevel cnt, DDI_DEV_AUTOINCR);
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosramp += cnt * UINT64SZ;
03831d35f7499c87d51205817c93e9a8d42c4baestevel buf += cnt * UINT64SZ;
03831d35f7499c87d51205817c93e9a8d42c4baestevel len -= cnt * UINT64SZ;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Copy the remaining data using word & byte access
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (len >= UINT32SZ) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(2,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "WR: put32(buf:%p sramp:%p) len:%x\n", buf, iosramp,
03831d35f7499c87d51205817c93e9a8d42c4baestevel len, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_put32(handle, (uint32_t *)iosramp,
03831d35f7499c87d51205817c93e9a8d42c4baestevel *(uint32_t *)buf);
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosramp += UINT32SZ;
03831d35f7499c87d51205817c93e9a8d42c4baestevel buf += UINT32SZ;
03831d35f7499c87d51205817c93e9a8d42c4baestevel len -= UINT32SZ;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (len != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_rep_put8(handle, buf, iosramp, len,
03831d35f7499c87d51205817c93e9a8d42c4baestevel DDI_DEV_AUTOINCR);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if ((len >= UINT32SZ) &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel ((((uintptr_t)iosramp | (uintptr_t)buf) & (UINT32SZ - 1)) == 0)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Both source and destination are word aligned
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel int cnt = len/UINT32SZ;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(2,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "WR: rep_put32(buf:%p sramp:%p cnt:%x) len:%x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel buf, iosramp, cnt, len);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_rep_put32(handle, (uint32_t *)buf, (uint32_t *)iosramp,
03831d35f7499c87d51205817c93e9a8d42c4baestevel cnt, DDI_DEV_AUTOINCR);
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosramp += cnt * UINT32SZ;
03831d35f7499c87d51205817c93e9a8d42c4baestevel buf += cnt * UINT32SZ;
03831d35f7499c87d51205817c93e9a8d42c4baestevel len -= cnt * UINT32SZ;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * copy the remainder using byte access
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (len != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_rep_put8(handle, buf, iosramp, len,
03831d35f7499c87d51205817c93e9a8d42c4baestevel DDI_DEV_AUTOINCR);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (len != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We know that the "off" is at least word aligned. We
03831d35f7499c87d51205817c93e9a8d42c4baestevel * need to read data from buf buffer byte at a time, and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * write it to the IOSRAM word at a time.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(((uintptr_t)iosramp & (UINT32SZ - 1)) == 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(2,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "WR: unaligned put32(buf:%p sramp:%p) len:%x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel buf, iosramp, len, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (; len >= UINT32SZ; len -= UINT32SZ, iosramp += UINT32SZ) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel word.cbuf[0] = *buf++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel word.cbuf[1] = *buf++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel word.cbuf[2] = *buf++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel word.cbuf[3] = *buf++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_put32(handle, (uint32_t *)iosramp, word.data);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * copy the remaining data using byte access
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (len != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_rep_put8(handle, buf, iosramp,
03831d35f7499c87d51205817c93e9a8d42c4baestevel len, DDI_DEV_AUTOINCR);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Reacquire mutex lock, decrement refcnt and if refcnt is 0 and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * any threads are waiting for r/w activity to complete, wake them up.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(iosram_rw_active > 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((--iosram_rw_active == 0) && iosram_rw_wakeup) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_rw_wakeup = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_broadcast(&iosram_rw_wait);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baesteveliosram_force_write(uint32_t key, uint32_t off, uint32_t len, caddr_t dptr)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (_iosram_write(key, off, len, dptr, 1 /* force */));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baesteveliosram_wr(uint32_t key, uint32_t off, uint32_t len, caddr_t dptr)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (_iosram_write(key, off, len, dptr, 0));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * iosram_register(key, handler, arg)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Register a handler and an arg for the specified chunk. This handler
03831d35f7499c87d51205817c93e9a8d42c4baestevel * will be invoked when an interrupt is received from the other side and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the int_pending flag for the corresponding key is marked
03831d35f7499c87d51205817c93e9a8d42c4baestevel * IOSRAM_INT_TO_DOM.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baesteveliosram_register(uint32_t key, void (*handler)(), void *arg)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct iosram_chunk *chunkp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Acquire lock and look for the requested chunk. If it exists, and no
03831d35f7499c87d51205817c93e9a8d42c4baestevel * other callback is registered, proceed with the registration.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel chunkp = iosram_find_chunk(key);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iosram_master == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EIO;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (chunkp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (chunkp->cback.handler != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EBUSY;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel chunkp->cback.busy = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel chunkp->cback.unregister = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel chunkp->cback.handler = handler;
03831d35f7499c87d51205817c93e9a8d42c4baestevel chunkp->cback.arg = arg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(1, "REG: key: 0x%x hdlr:%p arg:%p error:%d\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel key, handler, arg, error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * iosram_unregister()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Unregister handler associated with the specified chunk.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baesteveliosram_unregister(uint32_t key)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct iosram_chunk *chunkp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Acquire lock and look for the requested chunk. If it exists and has
03831d35f7499c87d51205817c93e9a8d42c4baestevel * a callback registered, unregister it.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel chunkp = iosram_find_chunk(key);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iosram_master == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EIO;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (chunkp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (chunkp->cback.busy) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If the handler is already busy (being invoked), then we flag
03831d35f7499c87d51205817c93e9a8d42c4baestevel * it so it will be unregistered after the invocation completes.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("IOSRAM(%d): unregister: delaying unreg k:0x%08x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_master->instance, key));
03831d35f7499c87d51205817c93e9a8d42c4baestevel chunkp->cback.unregister = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (chunkp->cback.handler != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel chunkp->cback.handler = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel chunkp->cback.arg = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(1, "UNREG: key:%x error:%d\n", key, error, NULL, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * iosram_get_flag():
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Get data_valid and/or int_pending flags associated with the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * specified key.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baesteveliosram_get_flag(uint32_t key, uint8_t *data_valid, uint8_t *int_pending)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_chunk_t *chunkp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_flags_t flags;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Acquire lock and look for the requested chunk. If it exists, and no
03831d35f7499c87d51205817c93e9a8d42c4baestevel * tunnel switch is in progress, read the chunk's flags.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel chunkp = iosram_find_chunk(key);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iosram_master == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EIO;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (chunkp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (iosram_tswitch_active) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EAGAIN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAM_STAT(getflag);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Read the flags
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_rep_get8(iosram_handle, (uint8_t *)&flags,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (uint8_t *)(chunkp->flagsp), sizeof (iosram_flags_t),
03831d35f7499c87d51205817c93e9a8d42c4baestevel DDI_DEV_AUTOINCR);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Get each flag value that the caller is interested in.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (data_valid != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel *data_valid = flags.data_valid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (int_pending != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel *int_pending = flags.int_pending;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(1, "GetFlag key:%x data_valid:%x int_pending:%x error:%d\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel key, flags.data_valid, flags.int_pending, error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * iosram_set_flag():
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Set data_valid and int_pending flags associated with the specified key.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baesteveliosram_set_flag(uint32_t key, uint8_t data_valid, uint8_t int_pending)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_chunk_t *chunkp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_flags_t flags;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Acquire lock and look for the requested chunk. If it exists, and no
03831d35f7499c87d51205817c93e9a8d42c4baestevel * tunnel switch is in progress, write the chunk's flags.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel chunkp = iosram_find_chunk(key);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iosram_master == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EIO;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if ((chunkp == NULL) ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel ((data_valid != IOSRAM_DATA_INVALID) &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel (data_valid != IOSRAM_DATA_VALID)) ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel ((int_pending != IOSRAM_INT_NONE) &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel (int_pending != IOSRAM_INT_TO_SSC) &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel (int_pending != IOSRAM_INT_TO_DOM))) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (iosram_tswitch_active) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EAGAIN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAM_STAT(setflag);
03831d35f7499c87d51205817c93e9a8d42c4baestevel flags.data_valid = data_valid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel flags.int_pending = int_pending;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_rep_put8(iosram_handle, (uint8_t *)&flags,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (uint8_t *)(chunkp->flagsp), sizeof (iosram_flags_t),
03831d35f7499c87d51205817c93e9a8d42c4baestevel DDI_DEV_AUTOINCR);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(1, "SetFlag key:%x data_valid:%x int_pending:%x error:%d\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel key, flags.data_valid, flags.int_pending, error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * iosram_ctrl()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This function provides access to a variety of services not available
03831d35f7499c87d51205817c93e9a8d42c4baestevel * through the basic API.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baesteveliosram_ctrl(uint32_t key, uint32_t cmd, void *arg)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct iosram_chunk *chunkp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Acquire lock and do some argument sanity checking.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel chunkp = iosram_find_chunk(key);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iosram_master == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EIO;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (chunkp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Arguments seem okay so far, so process the command.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (cmd) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case IOSRAM_CMD_CHUNKLEN:
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Return the length of the chunk indicated by the key.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (arg == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel *(uint32_t *)arg = chunkp->toc_data.len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = ENOTSUP;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * iosram_hdr_ctrl()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This function provides an interface for the Mailbox Protocol
03831d35f7499c87d51205817c93e9a8d42c4baestevel * implementation to use when interacting with the IOSRAM header.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baesteveliosram_hdr_ctrl(uint32_t cmd, void *arg)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Acquire lock and do some argument sanity checking.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iosram_master == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EIO;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (cmd) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case IOSRAM_HDRCMD_GET_SMS_MBOX_VER:
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Return the value of the sms_mbox_version field.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (arg == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel *(uint32_t *)arg = IOSRAM_GET_HDRFIELD32(iosram_master,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sms_mbox_version);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case IOSRAM_HDRCMD_SET_OS_MBOX_VER:
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Set the value of the os_mbox_version field.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAM_SET_HDRFIELD32(iosram_master, os_mbox_version,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (uint32_t)(uintptr_t)arg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAM_SET_HDRFIELD32(iosram_master, os_change_mask,
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAM_HDRFIELD_OS_MBOX_VER);
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) iosram_send_intr();
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case IOSRAM_HDRCMD_REG_CALLBACK:
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_hdrchange_handler = (void (*)())arg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = ENOTSUP;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * iosram_softintr()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * IOSRAM soft interrupt handler
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic uint_t
03831d35f7499c87d51205817c93e9a8d42c4baesteveliosram_softintr(caddr_t arg)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t hdr_changes;
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosramsoft_t *softp = (iosramsoft_t *)arg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_chunk_t *chunkp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel void (*handler)();
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint8_t flag;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("iosram(%d): in iosram_softintr\n", softp->instance));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(2, "SINTR arg/softp:%p pending:%d busy:%d\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel arg, softp->intr_pending, softp->intr_busy, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&softp->intr_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Do not process interrupt if interrupt handler is already running or
03831d35f7499c87d51205817c93e9a8d42c4baestevel * no interrupts are pending.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (softp->intr_busy || !softp->intr_pending) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&softp->intr_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("IOSRAM(%d): softintr: busy=%d pending=%d\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->instance, softp->intr_busy, softp->intr_pending));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (softp->intr_pending ? DDI_INTR_CLAIMED :
03831d35f7499c87d51205817c93e9a8d42c4baestevel DDI_INTR_UNCLAIMED);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * It's possible for the SC to send an interrupt on the new master
03831d35f7499c87d51205817c93e9a8d42c4baestevel * before we are able to set our internal state. If so, we'll retrigger
03831d35f7499c87d51205817c93e9a8d42c4baestevel * soft interrupt right after tunnel switch completion.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (softp->state & IOSRAM_STATE_TSWITCH) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&softp->intr_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("IOSRAM(%d): softintr: doing switch "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "state=0x%x\n", softp->instance, softp->state));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_INTR_CLAIMED);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Do not process interrupt if we are not the master.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(softp->state & IOSRAM_STATE_MASTER)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&softp->intr_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("IOSRAM(%d): softintr: no master state=0x%x\n ",
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->instance, softp->state));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_INTR_CLAIMED);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAM_STAT(sintr_recv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If the driver is suspended, then we should not process any
03831d35f7499c87d51205817c93e9a8d42c4baestevel * interrupts. Instead, we trigger a soft interrupt when the driver
03831d35f7499c87d51205817c93e9a8d42c4baestevel * resumes.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (softp->suspended) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&softp->intr_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("IOSRAM(%d): softintr: suspended\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->instance));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_INTR_CLAIMED);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Indicate that the IOSRAM interrupt handler is busy. Note that this
03831d35f7499c87d51205817c93e9a8d42c4baestevel * includes incrementing the reader/writer count, since we don't want
03831d35f7499c87d51205817c93e9a8d42c4baestevel * any tunnel switches to start up while we're processing callbacks.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->intr_busy = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_rw_active++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel#if defined(DEBUG)
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iosram_rw_active > iosram_rw_active_max) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_rw_active_max = iosram_rw_active;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel do {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("IOSRAM(%d): softintr: processing interrupt\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->instance));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->intr_pending = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&softp->intr_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Process changes to the IOSRAM header.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel hdr_changes = IOSRAM_GET_HDRFIELD32(iosram_master,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sms_change_mask);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (hdr_changes != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAM_SET_HDRFIELD32(iosram_master, sms_change_mask,
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (hdr_changes & IOSRAM_HDRFIELD_TOC_INDEX) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * XXX is it safe to temporarily release the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * iosram_mutex here?
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = iosram_read_toc(iosram_master);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "iosram_read_toc: new"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " TOC invalid; using old TOC.");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_update_addrs(iosram_master);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iosram_hdrchange_handler != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_hdrchange_handler();
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Get data_valid/int_pending flags and generate a callback if
03831d35f7499c87d51205817c93e9a8d42c4baestevel * applicable. For now, we read only those flags for which a
03831d35f7499c87d51205817c93e9a8d42c4baestevel * callback has been registered. We can optimize reading of
03831d35f7499c87d51205817c93e9a8d42c4baestevel * flags by reading them all at once and then process them
03831d35f7499c87d51205817c93e9a8d42c4baestevel * later.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0, chunkp = chunks; i < nchunks; i++,
03831d35f7499c87d51205817c93e9a8d42c4baestevel chunkp++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel#if DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel flag = ddi_get8(iosram_handle,
03831d35f7499c87d51205817c93e9a8d42c4baestevel &(chunkp->flagsp->int_pending));
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("IOSRAM(%d): softintr chunk #%d "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "flag=0x%x handler=%p\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->instance, i, (int)flag,
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void *)chunkp->cback.handler));
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((handler = chunkp->cback.handler) == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel flag = ddi_get8(iosram_handle,
03831d35f7499c87d51205817c93e9a8d42c4baestevel &(chunkp->flagsp->int_pending));
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (flag == IOSRAM_INT_TO_DOM) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1,
03831d35f7499c87d51205817c93e9a8d42c4baestevel ("IOSRAM(%d): softintr: invoking handler\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->instance));
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(1,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "SINTR invoking hdlr:%p arg:%p index:%d\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel handler, chunkp->cback.arg, i, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAM_STAT(callbacks);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_put8(iosram_handle,
03831d35f7499c87d51205817c93e9a8d42c4baestevel &(chunkp->flagsp->int_pending),
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAM_INT_NONE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel chunkp->cback.busy = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel (*handler)(chunkp->cback.arg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel chunkp->cback.busy = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If iosram_unregister was called while the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * callback was being invoked, complete the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * unregistration here.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (chunkp->cback.unregister) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("IOSRAM(%d): softintr: "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "delayed unreg k:0x%08x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->instance,
03831d35f7499c87d51205817c93e9a8d42c4baestevel chunkp->toc_data.key));
03831d35f7499c87d51205817c93e9a8d42c4baestevel chunkp->cback.handler = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel chunkp->cback.arg = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel chunkp->cback.unregister = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If there's a tunnel switch waiting to run, give it
03831d35f7499c87d51205817c93e9a8d42c4baestevel * higher priority than these callbacks by bailing out.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * They'll still be invoked on the new master iosram
03831d35f7499c87d51205817c93e9a8d42c4baestevel * when the tunnel switch is done.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iosram_tswitch_active) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&softp->intr_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel } while (softp->intr_pending && !softp->suspended &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel !iosram_tswitch_active);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Indicate IOSRAM interrupt handler is not BUSY any more
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->intr_busy = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(iosram_rw_active > 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((--iosram_rw_active == 0) && iosram_rw_wakeup) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_rw_wakeup = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_broadcast(&iosram_rw_wait);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&softp->intr_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("iosram(%d): softintr exit\n", softp->instance));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_INTR_CLAIMED);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * iosram_intr()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * IOSRAM real interrupt handler
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic uint_t
03831d35f7499c87d51205817c93e9a8d42c4baesteveliosram_intr(caddr_t arg)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosramsoft_t *softp = (iosramsoft_t *)arg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int result = DDI_INTR_UNCLAIMED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t int_status;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(2, ("iosram(%d): in iosram_intr\n", softp->instance));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&softp->intr_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (softp->sbbc_handle == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The SBBC registers region is not mapped in.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Set the interrupt pending flag here, and process the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * interrupt after the tunnel switch.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("IOSRAM(%d): iosram_intr: SBBC not mapped\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->instance));
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->intr_pending = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&softp->intr_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_INTR_UNCLAIMED);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel int_status = ddi_get32(softp->sbbc_handle,
03831d35f7499c87d51205817c93e9a8d42c4baestevel &(softp->sbbc_region->int_status.reg));
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("iosram_intr: int_status = 0x%08x\n", int_status));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (int_status & IOSRAM_SBBC_INT0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel result = DDI_INTR_CLAIMED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("iosram_intr: int0 detected!\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (int_status & IOSRAM_SBBC_INT1) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel result = DDI_INTR_CLAIMED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("iosram_intr: int1 detected!\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (result == DDI_INTR_CLAIMED) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_put32(softp->sbbc_handle,
03831d35f7499c87d51205817c93e9a8d42c4baestevel &(softp->sbbc_region->int_status.reg), int_status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel int_status = ddi_get32(softp->sbbc_handle,
03831d35f7499c87d51205817c93e9a8d42c4baestevel &(softp->sbbc_region->int_status.reg));
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("iosram_intr: int_status = 0x%08x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel int_status));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->intr_pending = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Trigger soft interrupt if not executing and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * not suspended.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!softp->intr_busy && !softp->suspended &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel (softp->softintr_id != NULL)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("iosram(%d): trigger softint\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->instance));
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_trigger_softintr(softp->softintr_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAM_STAT(intr_recv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&softp->intr_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(2, "INTR arg/softp:%p pending:%d busy:%d\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel arg, softp->intr_pending, softp->intr_busy, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("iosram(%d): iosram_intr exit\n", softp->instance));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (result);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * iosram_send_intr()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Send an interrupt to the SSP side via AXQ driver
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baesteveliosram_send_intr()
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(1, "SendIntr called\n", NULL, NULL, NULL, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAM_STAT(intr_send);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("iosram iosram_send_intr invoked\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (axq_cpu2ssc_intr(0));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#if defined(DEBUG)
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveliosram_dummy_cback(void *arg)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("iosram_dummy_cback invoked arg:%p\n", arg));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED1*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveliosram_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
03831d35f7499c87d51205817c93e9a8d42c4baestevel int *rvalp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct iosramsoft *softp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error = DDI_SUCCESS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp = ddi_get_soft_state(iosramsoft_statep, getminor(dev));
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (softp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ENXIO);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(1, "IOCTL: dev:%p cmd:%x arg:%p ... instance %d\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev, cmd, arg, softp->instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (cmd) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel#if defined(DEBUG)
03831d35f7499c87d51205817c93e9a8d42c4baestevel case IOSRAM_GET_FLAG:
193974072f41a843678abf5f61979c748687e66bSherry Moore {
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_io_t req;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint8_t data_valid, int_pending;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_copyin((void *)arg, &req, sizeof (req), mode)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EFAULT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(2, ("IOSRAM_GET_FLAG(key:%x\n", req.key));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel req.retval = iosram_get_flag(req.key, &data_valid,
03831d35f7499c87d51205817c93e9a8d42c4baestevel &int_pending);
03831d35f7499c87d51205817c93e9a8d42c4baestevel req.data_valid = (uint32_t)data_valid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel req.int_pending = (uint32_t)int_pending;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_copyout(&req, (void *)arg, sizeof (req), mode)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1,
03831d35f7499c87d51205817c93e9a8d42c4baestevel ("IOSRAM_GET_FLAG: can't copyout req.retval (%x)",
03831d35f7499c87d51205817c93e9a8d42c4baestevel req.retval));
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EFAULT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
193974072f41a843678abf5f61979c748687e66bSherry Moore }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case IOSRAM_SET_FLAG:
193974072f41a843678abf5f61979c748687e66bSherry Moore {
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_io_t req;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_copyin((void *)arg, &req, sizeof (req), mode)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EFAULT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(2, ("IOSRAM_SET_FLAG(key:%x data_valid:%x "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "int_pending:%x\n", req.key, req.data_valid,
03831d35f7499c87d51205817c93e9a8d42c4baestevel req.int_pending));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel req.retval = iosram_set_flag(req.key, req.data_valid,
03831d35f7499c87d51205817c93e9a8d42c4baestevel req.int_pending);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_copyout(&req, (void *)arg, sizeof (req), mode)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("IOSRAM_SET_FLAG: can't copyout req.retval"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " (%x)\n", req.retval));
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EFAULT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
193974072f41a843678abf5f61979c748687e66bSherry Moore }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case IOSRAM_RD:
193974072f41a843678abf5f61979c748687e66bSherry Moore {
03831d35f7499c87d51205817c93e9a8d42c4baestevel caddr_t bufp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_io_t req;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_copyin((void *)arg, &req, sizeof (req), mode)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EFAULT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(2, ("IOSRAM_RD(k:%x o:%x len:%x bufp:%p\n", req.key,
03831d35f7499c87d51205817c93e9a8d42c4baestevel req.off, req.len, (void *)(uintptr_t)req.bufp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel len = req.len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel bufp = kmem_alloc(len, KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel req.retval = iosram_rd(req.key, req.off, req.len, bufp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_copyout(bufp, (void *)(uintptr_t)req.bufp, len, mode)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("IOSRAM_RD: copyout(%p, %p,%x,%x) failed\n",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void *)bufp, (void *)(uintptr_t)req.bufp, len,
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki mode));
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EFAULT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (ddi_copyout(&req, (void *)arg, sizeof (req), mode)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("IOSRAM_RD: can't copyout retval (%x)\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel req.retval));
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EFAULT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(bufp, len);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
193974072f41a843678abf5f61979c748687e66bSherry Moore }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case IOSRAM_WR:
193974072f41a843678abf5f61979c748687e66bSherry Moore {
03831d35f7499c87d51205817c93e9a8d42c4baestevel caddr_t bufp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_io_t req;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_copyin((void *)arg, &req, sizeof (req), mode)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EFAULT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(2, ("IOSRAM_WR(k:%x o:%x len:%x bufp:%p\n",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki req.key, req.off, req.len, (void *)(uintptr_t)req.bufp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel len = req.len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel bufp = kmem_alloc(len, KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_copyin((void *)(uintptr_t)req.bufp, bufp, len, mode)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EFAULT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel req.retval = iosram_wr(req.key, req.off, req.len,
03831d35f7499c87d51205817c93e9a8d42c4baestevel bufp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_copyout(&req, (void *)arg, sizeof (req),
03831d35f7499c87d51205817c93e9a8d42c4baestevel mode)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EFAULT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(bufp, len);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
193974072f41a843678abf5f61979c748687e66bSherry Moore }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case IOSRAM_TOC:
193974072f41a843678abf5f61979c748687e66bSherry Moore {
03831d35f7499c87d51205817c93e9a8d42c4baestevel caddr_t bufp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_io_t req;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_copyin((void *)arg, &req, sizeof (req), mode)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EFAULT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(2, ("IOSRAM_TOC (req.bufp:%x req.len:%x) \n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel req.bufp, req.len));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel len = req.len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel bufp = kmem_alloc(len, KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel req.retval = iosram_get_keys((iosram_toc_entry_t *)bufp,
03831d35f7499c87d51205817c93e9a8d42c4baestevel &req.len);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_copyout(bufp, (void *)(uintptr_t)req.bufp, req.len,
03831d35f7499c87d51205817c93e9a8d42c4baestevel mode)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1,
03831d35f7499c87d51205817c93e9a8d42c4baestevel ("IOSRAM_TOC: copyout(%p, %p,%x,%x) failed\n",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void *)bufp, (void *)(uintptr_t)req.bufp, req.len,
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki mode));
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EFAULT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (ddi_copyout(&req, (void *)arg, sizeof (req), mode)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("IOSRAM_TOC: can't copyout retval (%x)\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel req.retval));
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EFAULT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(bufp, len);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
193974072f41a843678abf5f61979c748687e66bSherry Moore }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case IOSRAM_SEND_INTR:
193974072f41a843678abf5f61979c748687e66bSherry Moore {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(2, ("IOSRAM_SEND_INTR\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch ((int)arg) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case 0x11:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case 0x22:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case 0x44:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case 0x88:
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_put32(softp->sbbc_handle,
03831d35f7499c87d51205817c93e9a8d42c4baestevel &(softp->sbbc_region->int_enable.reg), (int)arg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("Wrote 0x%x to int_enable.reg\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel (int)arg));
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case 0xBB:
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_put32(softp->sbbc_handle,
03831d35f7499c87d51205817c93e9a8d42c4baestevel &(softp->sbbc_region->p0_int_gen.reg), 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("Wrote 1 to p0_int_gen.reg\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = iosram_send_intr();
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
193974072f41a843678abf5f61979c748687e66bSherry Moore }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case IOSRAM_PRINT_CBACK:
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_print_cback();
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case IOSRAM_PRINT_STATE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_print_state((int)arg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#if IOSRAM_STATS
03831d35f7499c87d51205817c93e9a8d42c4baestevel case IOSRAM_PRINT_STATS:
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_print_stats();
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#if IOSRAM_LOG
03831d35f7499c87d51205817c93e9a8d42c4baestevel case IOSRAM_PRINT_LOG:
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_print_log((int)arg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case IOSRAM_TUNNEL_SWITCH:
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = iosram_switchfrom((int)arg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case IOSRAM_PRINT_FLAGS:
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_print_flags();
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case IOSRAM_REG_CBACK:
193974072f41a843678abf5f61979c748687e66bSherry Moore {
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_io_t req;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_copyin((void *)arg, &req, sizeof (req), mode)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EFAULT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(2, ("IOSRAM_REG_CBACK(k:%x)\n", req.key));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel req.retval = iosram_register(req.key, iosram_dummy_cback,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void *)(uintptr_t)req.key);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_copyout(&req, (void *)arg, sizeof (req), mode)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EFAULT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
193974072f41a843678abf5f61979c748687e66bSherry Moore }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case IOSRAM_UNREG_CBACK:
193974072f41a843678abf5f61979c748687e66bSherry Moore {
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_io_t req;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_copyin((void *)arg, &req, sizeof (req), mode)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EFAULT);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(2, ("IOSRAM_REG_CBACK(k:%x)\n", req.key));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel req.retval = iosram_unregister(req.key);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_copyout(&req, (void *)arg, sizeof (req), mode)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EFAULT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
193974072f41a843678abf5f61979c748687e66bSherry Moore }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case IOSRAM_SEMA_ACQUIRE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("IOSRAM_SEMA_ACQUIRE\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = iosram_sema_acquire(NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case IOSRAM_SEMA_RELEASE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("IOSRAM_SEMA_RELEASE\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = iosram_sema_release();
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("iosram_ioctl: Illegal command %x\n", cmd));
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = ENOTTY;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * iosram_switch_tunnel(softp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Switch master tunnel to the specified instance
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Must be called while holding iosram_mutex
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveliosram_switch_tunnel(iosramsoft_t *softp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel int instance = softp->instance;
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosramsoft_t *prev_master;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mutex_owned(&iosram_mutex));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("tunnel switch new master:%p (%d) current master:%p (%d)\n",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void *)softp, instance, (void *)iosram_master,
03831d35f7499c87d51205817c93e9a8d42c4baestevel ((iosram_master) ? iosram_master->instance : -1)));
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(1, "TSWTCH: new_master:%p (%p) iosram_master:%p (%d)\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp, instance, iosram_master,
03831d35f7499c87d51205817c93e9a8d42c4baestevel ((iosram_master) ? iosram_master->instance : -1));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (softp == NULL || (softp->state & IOSRAM_STATE_DETACH)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ENXIO);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iosram_master == softp) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We protect against the softp structure being deallocated by setting
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the IOSRAM_STATE_TSWITCH state flag. The detach routine will check
03831d35f7499c87d51205817c93e9a8d42c4baestevel * for this flag and if set, it will wait for this flag to be reset or
03831d35f7499c87d51205817c93e9a8d42c4baestevel * refuse the detach operation.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_new_master = softp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->state |= IOSRAM_STATE_TSWITCH;
03831d35f7499c87d51205817c93e9a8d42c4baestevel prev_master = iosram_master;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (prev_master) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel prev_master->state |= IOSRAM_STATE_TSWITCH;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Map the target IOSRAM, read the TOC, and register interrupts if not
03831d35f7499c87d51205817c93e9a8d42c4baestevel * already done.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("iosram(%d): mapping IOSRAM and SBBC\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->instance));
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(1, "TSWTCH: mapping instance:%d softp:%p\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance, softp, NULL, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iosram_setup_map(softp) != DDI_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = ENXIO;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if ((chunks == NULL) && (iosram_read_toc(softp) != 0)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_remove_map(softp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (iosram_add_intr(softp) != DDI_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If there was no previous master, purge the TOC data that
03831d35f7499c87d51205817c93e9a8d42c4baestevel * iosram_read_toc() created.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((prev_master == NULL) && (chunks != NULL)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(chunks, nchunks * sizeof (iosram_chunk_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel chunks = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel nchunks = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_init_hashtab();
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_remove_map(softp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = ENXIO;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If we are asked to abort tunnel switch, do so now, before invoking
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the OBP callback.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iosram_tswitch_aborted) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Once the tunnel switch is aborted, this thread should not
03831d35f7499c87d51205817c93e9a8d42c4baestevel * resume. If it does, we simply log a message. We can't unmap
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the new master IOSRAM as it may be accessed in
03831d35f7499c87d51205817c93e9a8d42c4baestevel * iosram_abort_tswitch(). It will be unmapped when it is
03831d35f7499c87d51205817c93e9a8d42c4baestevel * detached.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(1,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "TSWTCH: aborted (pre OBP cback). Thread resumed.\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel NULL, NULL, NULL, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EIO;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(1,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "TSWTCH: map failed instance:%d softp:%p error:%x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance, softp, error, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto done;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (prev_master != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int result;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Now invoke the OBP interface to do the tunnel switch.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel result = prom_starcat_switch_tunnel(softp->portid,
03831d35f7499c87d51205817c93e9a8d42c4baestevel OBP_TSWITCH_REQREPLY);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (result != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EIO;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(1,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "TSWTCH: OBP tswitch portid:%x result:%x error:%x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->portid, result, error, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAM_STAT(tswitch);
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_tswitch_tstamp = ddi_get_lbolt();
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iosram_tswitch_aborted) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Tunnel switch aborted. This thread should not resume.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * For now, we simply log a message, but don't unmap any
03831d35f7499c87d51205817c93e9a8d42c4baestevel * IOSRAM at this stage as it may be accessed within the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * isoram_abort_tswitch(). The IOSRAM will be unmapped
03831d35f7499c87d51205817c93e9a8d42c4baestevel * when that instance is detached.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iosram_tswitch_aborted) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(1,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "TSWTCH: aborted (post OBP cback). Thread"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " resumed.\n", NULL, NULL, NULL, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EIO;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (error) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Tunnel switch failed. Continue using previous tunnel.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * However, unmap new (target) IOSRAM.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_new_master = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) iosram_remove_intr(softp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_remove_map(softp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Tunnel switch was successful. Set the new master.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Also unmap old master IOSRAM and remove any interrupts
03831d35f7499c87d51205817c93e9a8d42c4baestevel * associated with that.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Note that a call to iosram_force_write() allows access
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to the IOSRAM while tunnel switch is in progress. That
03831d35f7499c87d51205817c93e9a8d42c4baestevel * means we need to set the new master before unmapping
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the old master.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_set_master(softp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_new_master = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (prev_master) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(1, "TSWTCH: unmapping prev_master:%p (%d)\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel prev_master, prev_master->instance, NULL, NULL);
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) iosram_remove_intr(prev_master);
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_remove_map(prev_master);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baesteveldone:
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Clear the tunnel switch flag on the source and destination
03831d35f7499c87d51205817c93e9a8d42c4baestevel * instances.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (prev_master) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel prev_master->state &= ~IOSRAM_STATE_TSWITCH;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->state &= ~IOSRAM_STATE_TSWITCH;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Since incoming interrupts could get lost during a tunnel switch,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * trigger a soft interrupt just in case. No harm other than a bit
03831d35f7499c87d51205817c93e9a8d42c4baestevel * of wasted effort will be caused if no interrupts were dropped.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&softp->intr_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_master->intr_pending = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((iosram_master->softintr_id != NULL) &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel (iosram_master->intr_busy == 0)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_trigger_softintr(iosram_master->softintr_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&softp->intr_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(1, "TSWTCH: done error:%d iosram_master:%p instance:%d\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel error, iosram_master,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (iosram_master) ? iosram_master->instance : -1, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * iosram_abort_tswitch()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Must be called while holding iosram_mutex.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveliosram_abort_tswitch()
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t master_valid, new_master_valid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mutex_owned(&iosram_mutex));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((!iosram_tswitch_active) || iosram_tswitch_aborted) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(iosram_master != NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(1, "ABORT: iosram_master:%p (%d) iosram_new_master:%p (%d)\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_master, iosram_master->instance, iosram_new_master,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (iosram_new_master == NULL) ? -1 : iosram_new_master->instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The first call to iosram_force_write() in the middle of tunnel switch
03831d35f7499c87d51205817c93e9a8d42c4baestevel * will get here. We lookup IOSRAM VALID location and setup appropriate
03831d35f7499c87d51205817c93e9a8d42c4baestevel * master, if one is still valid. We also set iosram_tswitch_aborted to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * prevent reentering this code and to catch if the OBP callback thread
03831d35f7499c87d51205817c93e9a8d42c4baestevel * somehow resumes.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_tswitch_aborted = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((iosram_new_master == NULL) ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel (iosram_new_master = iosram_master)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * New master hasn't been selected yet, or OBP callback
03831d35f7499c87d51205817c93e9a8d42c4baestevel * succeeded and we already selected new IOSRAM as master, but
03831d35f7499c87d51205817c93e9a8d42c4baestevel * system crashed in the middle of unmapping previous master or
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cleaning up state. Use the existing master.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(iosram_master->iosramp != NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(IOSRAM_GET_HDRFIELD32(iosram_master, status) ==
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAM_VALID);
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(1, "ABORT: master (%d) already determined.\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_master->instance, NULL, NULL, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * System crashed in the middle of tunnel switch and we know that the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * new target has not been marked master yet. That means, the old
03831d35f7499c87d51205817c93e9a8d42c4baestevel * master should still be mapped. We need to abort the tunnel switch
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and setup a valid master, if possible, so that we can write to the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * IOSRAM.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We select a new master based upon the IOSRAM header status fields in
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the previous master IOSRAM and the target IOSRAM as follows:
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * iosram_master iosram-tswitch
03831d35f7499c87d51205817c93e9a8d42c4baestevel * (Prev Master) (New Target) Decision
03831d35f7499c87d51205817c93e9a8d42c4baestevel * --------------- --------------- -----------
03831d35f7499c87d51205817c93e9a8d42c4baestevel * VALID don't care prev master
03831d35f7499c87d51205817c93e9a8d42c4baestevel * INTRANSIT INVALID prev master
03831d35f7499c87d51205817c93e9a8d42c4baestevel * INTRANSIT INTRANSIT prev master
03831d35f7499c87d51205817c93e9a8d42c4baestevel * INTRANSIT VALID new target
03831d35f7499c87d51205817c93e9a8d42c4baestevel * INVALID INVALID shouldn't ever happen
03831d35f7499c87d51205817c93e9a8d42c4baestevel * INVALID INTRANSIT shouldn't ever happen
03831d35f7499c87d51205817c93e9a8d42c4baestevel * INVALID VALID new target
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel master_valid = (iosram_master->iosramp != NULL) ?
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAM_GET_HDRFIELD32(iosram_master, status) : IOSRAM_INVALID;
03831d35f7499c87d51205817c93e9a8d42c4baestevel new_master_valid = (iosram_new_master->iosramp != NULL) ?
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAM_GET_HDRFIELD32(iosram_new_master, status) : IOSRAM_INVALID;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (master_valid == IOSRAM_VALID) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* EMPTY */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * OBP hasn't been called yet or, if it has, it hasn't started
03831d35f7499c87d51205817c93e9a8d42c4baestevel * copying yet. Use the existing master. Note that the new
03831d35f7499c87d51205817c93e9a8d42c4baestevel * master may not be mapped yet.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(1, "ABORT: prev master(%d) is VALID\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_master->instance, NULL, NULL, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (master_valid == IOSRAM_INTRANSIT) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The system crashed after OBP started processing the tunnel
03831d35f7499c87d51205817c93e9a8d42c4baestevel * switch but before the iosram driver determined that it was
03831d35f7499c87d51205817c93e9a8d42c4baestevel * complete. Use the new master if it has been marked valid,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * meaning that OBP finished copying data to it, or the old
03831d35f7499c87d51205817c93e9a8d42c4baestevel * master otherwise.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(1, "ABORT: prev master(%d) is INTRANSIT\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_master->instance, NULL, NULL, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (new_master_valid == IOSRAM_VALID) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_set_master(iosram_new_master);
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(1, "ABORT: new master(%d) is VALID\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_new_master->instance, NULL, NULL,
03831d35f7499c87d51205817c93e9a8d42c4baestevel NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) prom_starcat_switch_tunnel(iosram_master->portid,
03831d35f7499c87d51205817c93e9a8d42c4baestevel OBP_TSWITCH_NOREPLY);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(1, "ABORT: new master(%d) is INVALID\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_new_master->instance, NULL, NULL,
03831d35f7499c87d51205817c93e9a8d42c4baestevel NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The system crashed after OBP marked the old master INVALID,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * which means the new master is the way to go.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(1, "ABORT: prev master(%d) is INVALID\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_master->instance, NULL, NULL, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(new_master_valid == IOSRAM_VALID);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_set_master(iosram_new_master);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(1, "ABORT: Instance %d selected as master\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore iosram_master->instance, NULL, NULL, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * iosram_switchfrom(instance)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Switch master tunnel away from the specified instance
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*ARGSUSED*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baesteveliosram_switchfrom(int instance)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct iosramsoft *softp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int count;
03831d35f7499c87d51205817c93e9a8d42c4baestevel clock_t current_tstamp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel clock_t tstamp_interval;
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct iosramsoft *last_master = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel static int last_master_instance = -1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(1, "SwtchFrom: instance:%d iosram_master:%p (%d)\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance, iosram_master,
03831d35f7499c87d51205817c93e9a8d42c4baestevel ((iosram_master) ? iosram_master->instance : -1), NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Wait if another tunnel switch is in progress
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (count = 0; iosram_tswitch_active && count < IOSRAM_TSWITCH_RETRY;
03831d35f7499c87d51205817c93e9a8d42c4baestevel count++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_tswitch_wakeup = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_wait(&iosram_tswitch_wait, &iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iosram_tswitch_active) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EAGAIN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check if the specified instance holds the tunnel. If not,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * then we are done.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((iosram_master == NULL) || (iosram_master->instance != instance)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Before beginning the tunnel switch process, wait for any outstanding
03831d35f7499c87d51205817c93e9a8d42c4baestevel * read/write activity to complete.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_tswitch_active = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (iosram_rw_active) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_rw_wakeup = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_wait(&iosram_rw_wait, &iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If a previous tunnel switch just completed, we have to make sure
03831d35f7499c87d51205817c93e9a8d42c4baestevel * HWAD has enough time to find the new tunnel before we switch
03831d35f7499c87d51205817c93e9a8d42c4baestevel * away from it. Otherwise, OBP's mailbox message to OSD will never
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get through. Just to be paranoid about synchronization of lbolt
03831d35f7499c87d51205817c93e9a8d42c4baestevel * across different CPUs, make sure the current attempt isn't noted
03831d35f7499c87d51205817c93e9a8d42c4baestevel * as starting _before_ the last tunnel switch completed.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel current_tstamp = ddi_get_lbolt();
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (current_tstamp > iosram_tswitch_tstamp) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel tstamp_interval = current_tstamp - iosram_tswitch_tstamp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel tstamp_interval = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drv_hztousec(tstamp_interval) < IOSRAM_TSWITCH_DELAY_US) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel delay(drv_usectohz(IOSRAM_TSWITCH_DELAY_US) - tstamp_interval);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The specified instance holds the tunnel. We need to move it to some
03831d35f7499c87d51205817c93e9a8d42c4baestevel * other IOSRAM. Try out all possible IOSRAMs listed in
03831d35f7499c87d51205817c93e9a8d42c4baestevel * iosram_instances. For now, we always search from the first entry.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * In future, it may be desirable to start where we left off.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (softp = iosram_instances; softp != NULL; softp = softp->next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iosram_tswitch_aborted) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* we can't switch _to_ the instance we're switching _from_ */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (softp->instance == instance) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* skip over instances being detached */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (softp->state & IOSRAM_STATE_DETACH) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Try to avoid reverting to the last instance we switched away
03831d35f7499c87d51205817c93e9a8d42c4baestevel * from, as we expect that one to be detached eventually. Keep
03831d35f7499c87d51205817c93e9a8d42c4baestevel * track of it, though, so we can go ahead and try switching to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * it if no other viable candidates are found.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (softp->instance == last_master_instance) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel last_master = softp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Do the tunnel switch. If successful, record the instance of
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the master we just left behind so we can try to avoid
03831d35f7499c87d51205817c93e9a8d42c4baestevel * reverting to it next time.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iosram_switch_tunnel(softp) == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel last_master_instance = instance;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If we failed to switch the tunnel, but we skipped over an instance
03831d35f7499c87d51205817c93e9a8d42c4baestevel * that had previously been switched out of because we expected it to be
03831d35f7499c87d51205817c93e9a8d42c4baestevel * detached, go ahead and try it anyway (unless the tswitch was aborted
03831d35f7499c87d51205817c93e9a8d42c4baestevel * or the instance we skipped is finally being detached).
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((softp == NULL) && (last_master != NULL) &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel !iosram_tswitch_aborted &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel !(last_master->state & IOSRAM_STATE_DETACH)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iosram_switch_tunnel(last_master) == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp = last_master;
03831d35f7499c87d51205817c93e9a8d42c4baestevel last_master_instance = instance;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((softp == NULL) || (iosram_tswitch_aborted)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EIO;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If there are additional tunnel switches queued up waiting for this
03831d35f7499c87d51205817c93e9a8d42c4baestevel * one to complete, wake them up.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iosram_tswitch_wakeup) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_tswitch_wakeup = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_broadcast(&iosram_tswitch_wait);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_tswitch_active = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * iosram_tunnel_capable(softp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check if this IOSRAM instance is tunnel-capable by looing at
03831d35f7499c87d51205817c93e9a8d42c4baestevel * "tunnel-capable" property.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveliosram_tunnel_capable(struct iosramsoft *softp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int proplen;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int tunnel_capable;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Look up IOSRAM_TUNNELOK_PROP property, if any.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel proplen = sizeof (tunnel_capable);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_getlongprop_buf(DDI_DEV_T_ANY, softp->dip,
03831d35f7499c87d51205817c93e9a8d42c4baestevel DDI_PROP_DONTPASS, IOSRAM_TUNNELOK_PROP, (caddr_t)&tunnel_capable,
03831d35f7499c87d51205817c93e9a8d42c4baestevel &proplen) != DDI_PROP_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel tunnel_capable = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (tunnel_capable);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveliosram_sbbc_setup_map(struct iosramsoft *softp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rv;
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct ddi_device_acc_attr attr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev_info_t *dip = softp->dip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t sema_val;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
03831d35f7499c87d51205817c93e9a8d42c4baestevel attr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&softp->intr_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Map SBBC region in
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((rv = ddi_regs_map_setup(dip, IOSRAM_SBBC_MAP_INDEX,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (caddr_t *)&softp->sbbc_region,
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAM_SBBC_MAP_OFFSET, sizeof (iosram_sbbc_region_t),
03831d35f7499c87d51205817c93e9a8d42c4baestevel &attr, &softp->sbbc_handle)) != DDI_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("Failed to map SBBC region.\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&softp->intr_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (rv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Disable SBBC interrupts. SBBC interrupts are enabled
03831d35f7499c87d51205817c93e9a8d42c4baestevel * once the interrupt handler is registered.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_put32(softp->sbbc_handle,
03831d35f7499c87d51205817c93e9a8d42c4baestevel &(softp->sbbc_region->int_enable.reg), 0x0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Clear hardware semaphore value if appropriate.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * When the first SBBC is mapped in by the IOSRAM driver,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the value of the semaphore should be initialized only
03831d35f7499c87d51205817c93e9a8d42c4baestevel * if it is not held by SMS. For subsequent SBBC's, the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * semaphore will be always initialized.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel sema_val = IOSRAM_SEMA_RD(softp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!iosram_master) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* the first SBBC is being mapped in */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(IOSRAM_SEMA_IS_HELD(sema_val) &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAM_SEMA_GET_IDX(sema_val) == IOSRAM_SEMA_SMS_IDX)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* not held by SMS, we clear the semaphore */
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAM_SEMA_WR(softp, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* not the first SBBC, we clear the semaphore */
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAM_SEMA_WR(softp, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&softp->intr_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveliosram_setup_map(struct iosramsoft *softp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int instance = softp->instance;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dev_info_t *dip = softp->dip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int portid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int proplen;
03831d35f7499c87d51205817c93e9a8d42c4baestevel caddr_t propvalue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct ddi_device_acc_attr attr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
03831d35f7499c87d51205817c93e9a8d42c4baestevel attr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Lookup IOSRAM_REG_PROP property to find out our IOSRAM length
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_getlongprop(DDI_DEV_T_ANY, dip,
03831d35f7499c87d51205817c93e9a8d42c4baestevel DDI_PROP_DONTPASS, IOSRAM_REG_PROP, (caddr_t)&propvalue,
03831d35f7499c87d51205817c93e9a8d42c4baestevel &proplen) != DDI_PROP_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "iosram(%d): can't find register property.\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_reg_t *regprop = (iosram_reg_t *)propvalue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("SetupMap(%d): Got reg prop: %x %x %x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance, regprop->addr_hi,
03831d35f7499c87d51205817c93e9a8d42c4baestevel regprop->addr_lo, regprop->size));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->iosramlen = regprop->size;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(propvalue, proplen);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("SetupMap(%d): IOSRAM length: 0x%x\n", instance,
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->iosramlen));
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->handle = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * To minimize boot time, we map the entire IOSRAM as opposed to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mapping individual chunk via ddi_regs_map_setup() call.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_regs_map_setup(dip, 0, (caddr_t *)&softp->iosramp,
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0x0, softp->iosramlen, &attr, &softp->handle) != DDI_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "iosram(%d): failed to map IOSRAM len:%x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance, softp->iosramlen);
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_remove_map(softp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Lookup PORTID property on my parent hierarchy
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel proplen = sizeof (portid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip,
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0, IOSRAM_PORTID_PROP, (caddr_t)&portid,
03831d35f7499c87d51205817c93e9a8d42c4baestevel &proplen) != DDI_PROP_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "iosram(%d): can't find portid property.\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_remove_map(softp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->portid = portid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iosram_sbbc_setup_map(softp) != DDI_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "iosram(%d): can't map SBBC region.\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_remove_map(softp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->state |= IOSRAM_STATE_MAPPED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveliosram_remove_map(struct iosramsoft *softp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT((softp->state & IOSRAM_STATE_MASTER) == 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (softp->handle) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_regs_map_free(&softp->handle);
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->handle = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->iosramp = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Umap SBBC registers region. Shared with handler for SBBC
03831d35f7499c87d51205817c93e9a8d42c4baestevel * interrupts, take intr_mutex.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&softp->intr_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (softp->sbbc_region) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_regs_map_free(&softp->sbbc_handle);
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->sbbc_region = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&softp->intr_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->state &= ~IOSRAM_STATE_MAPPED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * iosram_is_chosen(struct iosramsoft *softp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Looks up "chosen" node property to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * determine if it is the chosen IOSRAM.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveliosram_is_chosen(struct iosramsoft *softp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel char chosen_iosram[MAXNAMELEN];
03831d35f7499c87d51205817c93e9a8d42c4baestevel char pn[MAXNAMELEN];
03831d35f7499c87d51205817c93e9a8d42c4baestevel int nodeid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int chosen;
03831d35f7499c87d51205817c93e9a8d42c4baestevel pnode_t dnode;
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 * Can't find IOSRAM_CHOSEN_PROP property under chosen node
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "iosram(%d): can't find chosen iosram property\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("iosram(%d): Got '%x' for chosen '%s' property\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->instance, nodeid, IOSRAM_CHOSEN_PROP));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the full OBP pathname of this node
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (prom_phandle_to_path((phandle_t)nodeid, chosen_iosram,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sizeof (chosen_iosram)) < 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, "prom_phandle_to_path(%x) failed\n", nodeid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("iosram(%d): prom_phandle_to_path(%x) is '%s'\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->instance, nodeid, chosen_iosram));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) ddi_pathname(softp->dip, pn);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("iosram(%d): ddi_pathname(%p) is '%s'\n",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki softp->instance, (void *)softp->dip, pn));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel chosen = (strcmp(chosen_iosram, pn) == 0) ? 1 : 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("iosram(%d): ... %s\n", softp->instance,
03831d35f7499c87d51205817c93e9a8d42c4baestevel chosen ? "MASTER" : "SLAVE"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(1, "iosram(%d): ... %s\n", softp->instance,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (chosen ? "MASTER" : "SLAVE"), NULL, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (chosen);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * iosram_set_master(struct iosramsoft *softp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Set master tunnel to the specified IOSRAM
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Must be called while holding iosram_mutex.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveliosram_set_master(struct iosramsoft *softp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mutex_owned(&iosram_mutex));
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(softp != NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(softp->state & IOSRAM_STATE_MAPPED);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(IOSRAM_GET_HDRFIELD32(softp, status) == IOSRAM_VALID);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Clear MASTER flag on any previous IOSRAM master, if any
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iosram_master && (iosram_master != softp)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_master->state &= ~IOSRAM_STATE_MASTER;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Setup new IOSRAM master
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_update_addrs(softp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_handle = softp->handle;
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->state |= IOSRAM_STATE_MASTER;
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->tswitch_ok++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_master = softp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(1, "SETMASTER: softp:%p instance:%d\n", softp,
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->instance, NULL, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * iosram_read_toc()
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Read the TOC from an IOSRAM instance that has been mapped in.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If the TOC is flawed or the IOSRAM isn't valid, return an error.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveliosram_read_toc(struct iosramsoft *softp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int instance = softp->instance;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint8_t *toc_entryp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_flags_t *flagsp = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int new_nchunks;
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_chunk_t *new_chunks;
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_chunk_t *chunkp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_chunk_t *old_chunkp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_toc_entry_t index;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Never try to read the TOC out of an unmapped IOSRAM.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(softp->state & IOSRAM_STATE_MAPPED);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check to make sure this IOSRAM is marked valid. Return
03831d35f7499c87d51205817c93e9a8d42c4baestevel * an error if it isn't.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (IOSRAM_GET_HDRFIELD32(softp, status) != IOSRAM_VALID) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("iosram_read_toc(%d): IOSRAM not flagged valid\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance));
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EINVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Get the location of the TOC.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel toc_entryp = softp->iosramp + IOSRAM_GET_HDRFIELD32(softp, toc_offset);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Read the index entry from the TOC and make sure it looks correct.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_rep_get8(softp->handle, (uint8_t *)&index, toc_entryp,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sizeof (iosram_toc_entry_t), DDI_DEV_AUTOINCR);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((index.key != IOSRAM_INDEX_KEY) ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel (index.off != IOSRAM_INDEX_OFF)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "iosram(%d): invalid TOC index.\n", instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EINVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Allocate storage for the new chunks array and initialize it with data
03831d35f7499c87d51205817c93e9a8d42c4baestevel * from the TOC and callback data from the corresponding old chunk, if
03831d35f7499c87d51205817c93e9a8d42c4baestevel * it exists.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel new_nchunks = index.len - 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel new_chunks = (iosram_chunk_t *)kmem_zalloc(new_nchunks *
03831d35f7499c87d51205817c93e9a8d42c4baestevel sizeof (iosram_chunk_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0, chunkp = new_chunks; i < new_nchunks; i++, chunkp++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel toc_entryp += sizeof (iosram_toc_entry_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_rep_get8(softp->handle, (uint8_t *)&(chunkp->toc_data),
03831d35f7499c87d51205817c93e9a8d42c4baestevel toc_entryp, sizeof (iosram_toc_entry_t), DDI_DEV_AUTOINCR);
03831d35f7499c87d51205817c93e9a8d42c4baestevel chunkp->hash = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((chunkp->toc_data.off < softp->iosramlen) &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel (chunkp->toc_data.len <= softp->iosramlen) &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel ((chunkp->toc_data.off + chunkp->toc_data.len) <=
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->iosramlen)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel chunkp->basep = softp->iosramp + chunkp->toc_data.off;
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1,
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki ("iosram_read_toc(%d): k:%x o:%x l:%x p:%p\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance, chunkp->toc_data.key,
03831d35f7499c87d51205817c93e9a8d42c4baestevel chunkp->toc_data.off, chunkp->toc_data.len,
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void *)chunkp->basep));
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "iosram(%d): TOC entry %d"
03831d35f7499c87d51205817c93e9a8d42c4baestevel "out of range... off:%x len:%x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance, i + 1, chunkp->toc_data.off,
03831d35f7499c87d51205817c93e9a8d42c4baestevel chunkp->toc_data.len);
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(new_chunks, new_nchunks *
03831d35f7499c87d51205817c93e9a8d42c4baestevel sizeof (iosram_chunk_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EINVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Note the existence of the flags chunk, which is required in
03831d35f7499c87d51205817c93e9a8d42c4baestevel * a correct TOC.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (chunkp->toc_data.key == IOSRAM_FLAGS_KEY) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel flagsp = (iosram_flags_t *)chunkp->basep;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If there was an entry for this chunk in the old list, copy
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the callback data from old to new storage.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((nchunks > 0) &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel ((old_chunkp = iosram_find_chunk(chunkp->toc_data.key)) !=
03831d35f7499c87d51205817c93e9a8d42c4baestevel NULL)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel bcopy(&(old_chunkp->cback), &(chunkp->cback),
03831d35f7499c87d51205817c93e9a8d42c4baestevel sizeof (iosram_cback_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The TOC is malformed if there is no entry for the flags chunk.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (flagsp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(new_chunks, new_nchunks * sizeof (iosram_chunk_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EINVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Free any memory that is no longer needed and install the new data
03831d35f7499c87d51205817c93e9a8d42c4baestevel * as current data.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (chunks != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(chunks, nchunks * sizeof (iosram_chunk_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel chunks = new_chunks;
03831d35f7499c87d51205817c93e9a8d42c4baestevel nchunks = new_nchunks;
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_init_hashtab();
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * iosram_init_hashtab()
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Initialize the hash table and populate it with the IOSRAM
03831d35f7499c87d51205817c93e9a8d42c4baestevel * chunks previously read from the TOC. The caller must hold the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ioram_mutex lock.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveliosram_init_hashtab(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i, bucket;
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_chunk_t *chunkp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mutex_owned(&iosram_mutex));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < IOSRAM_HASHSZ; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_hashtab[i] = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (chunks) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0, chunkp = chunks; i < nchunks; i++, chunkp++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Hide the flags chunk by leaving it out of the hash
03831d35f7499c87d51205817c93e9a8d42c4baestevel * table.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (chunkp->toc_data.key == IOSRAM_FLAGS_KEY) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Add the current chunk to the hash table.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel bucket = IOSRAM_HASH(chunkp->toc_data.key);
03831d35f7499c87d51205817c93e9a8d42c4baestevel chunkp->hash = iosram_hashtab[bucket];
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_hashtab[bucket] = chunkp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * iosram_update_addrs()
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Process the chunk list, updating each chunk's basep, which is a pointer
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to the beginning of the chunk's memory in kvaddr space. Record the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * basep value of the flags chunk to speed up flag access. The caller
03831d35f7499c87d51205817c93e9a8d42c4baestevel * must hold the iosram_mutex lock.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveliosram_update_addrs(struct iosramsoft *softp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_flags_t *flagsp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_chunk_t *chunkp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mutex_owned(&iosram_mutex));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * First go through all of the chunks updating their base pointers and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * looking for the flags chunk.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0, chunkp = chunks; i < nchunks; i++, chunkp++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel chunkp->basep = softp->iosramp + chunkp->toc_data.off;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (chunkp->toc_data.key == IOSRAM_FLAGS_KEY) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel flagsp = (iosram_flags_t *)(chunkp->basep);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1,
03831d35f7499c87d51205817c93e9a8d42c4baestevel ("iosram_update_addrs flags: o:0x%08x p:%p",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki chunkp->toc_data.off, (void *)flagsp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Now, go through and update each chunk's flags pointer. This can't be
03831d35f7499c87d51205817c93e9a8d42c4baestevel * done in the first loop because we don't have the address of the flags
03831d35f7499c87d51205817c93e9a8d42c4baestevel * chunk yet.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0, chunkp = chunks; i < nchunks; i++, chunkp++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel chunkp->flagsp = flagsp++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("iosram_update_addrs: k:0x%x f:%p\n",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki chunkp->toc_data.key, (void *)chunkp->flagsp));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * iosram_find_chunk(key)
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Return a pointer to iosram_chunk structure corresponding to the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * "key" IOSRAM chunk. The caller must hold the iosram_mutex lock.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic iosram_chunk_t *
03831d35f7499c87d51205817c93e9a8d42c4baesteveliosram_find_chunk(uint32_t key)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_chunk_t *chunkp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int index = IOSRAM_HASH(key);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mutex_owned(&iosram_mutex));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (chunkp = iosram_hashtab[index]; chunkp; chunkp = chunkp->hash) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (chunkp->toc_data.key == key) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (chunkp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * iosram_add_intr(iosramsoft_t *)
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveliosram_add_intr(iosramsoft_t *softp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(2, "ADDINTR: softp:%p instance:%d\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp, softp->instance, NULL, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_add_softintr(softp->dip, DDI_SOFTINT_MED,
03831d35f7499c87d51205817c93e9a8d42c4baestevel &softp->softintr_id, &softp->soft_iblk, NULL,
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_softintr, (caddr_t)softp) != DDI_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "iosram(%d): Can't register softintr.\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_add_intr(softp->dip, 0, &softp->real_iblk, NULL,
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_intr, (caddr_t)softp) != DDI_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "iosram(%d): Can't register intr"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " handler.\n", softp->instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_remove_softintr(softp->softintr_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Enable SBBC interrupts
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_put32(softp->sbbc_handle, &(softp->sbbc_region->int_enable.reg),
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAM_SBBC_INT0|IOSRAM_SBBC_INT1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * iosram_remove_intr(iosramsoft_t *)
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveliosram_remove_intr(iosramsoft_t *softp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(2, "REMINTR: softp:%p instance:%d\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp, softp->instance, NULL, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Disable SBBC interrupts if SBBC is mapped in
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (softp->sbbc_region) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_put32(softp->sbbc_handle,
03831d35f7499c87d51205817c93e9a8d42c4baestevel &(softp->sbbc_region->int_enable.reg), 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Remove SBBC interrupt handler
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_remove_intr(softp->dip, 0, softp->real_iblk);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Remove soft interrupt handler
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (softp->softintr_id != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_remove_softintr(softp->softintr_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->softintr_id = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * iosram_add_instance(iosramsoft_t *)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Must be called while holding iosram_mutex
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveliosram_add_instance(iosramsoft_t *new_softp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel int instance = new_softp->instance;
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosramsoft_t *softp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mutex_owned(&iosram_mutex));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#if defined(DEBUG)
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Verify that this instance is not in the list */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (softp = iosram_instances; softp != NULL; softp = softp->next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(softp->instance != instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Add this instance to the list
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iosram_instances != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_instances->prev = new_softp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel new_softp->next = iosram_instances;
03831d35f7499c87d51205817c93e9a8d42c4baestevel new_softp->prev = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_instances = new_softp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * iosram_remove_instance(int instance)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Must be called while holding iosram_mutex
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveliosram_remove_instance(int instance)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosramsoft_t *softp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Remove specified instance from the iosram_instances list so that
03831d35f7499c87d51205817c93e9a8d42c4baestevel * it can't be chosen for tunnel in future.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mutex_owned(&iosram_mutex));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (softp = iosram_instances; softp != NULL; softp = softp->next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (softp->instance == instance) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (softp->next != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->next->prev = softp->prev;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (softp->prev != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->prev->next = softp->next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iosram_instances == softp) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_instances = softp->next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * iosram_sema_acquire: Acquire hardware semaphore.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Return 0 if the semaphore could be acquired, or one of the following
03831d35f7499c87d51205817c93e9a8d42c4baestevel * possible values:
03831d35f7499c87d51205817c93e9a8d42c4baestevel * EAGAIN: there is a tunnel switch in progress
03831d35f7499c87d51205817c93e9a8d42c4baestevel * EBUSY: the semaphore was already "held"
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ENXIO: an IO error occured (e.g. SBBC not mapped)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If old_value is not NULL, the location it points to will be updated
03831d35f7499c87d51205817c93e9a8d42c4baestevel * with the semaphore value read when attempting to acquire it.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baesteveliosram_sema_acquire(uint32_t *old_value)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct iosramsoft *softp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rv;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t sema_val;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(2, ("IOSRAM: in iosram_sema_acquire\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Disallow access if there is a tunnel switch in progress.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iosram_tswitch_active) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EAGAIN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Use current master IOSRAM for operation, fail if none is
03831d35f7499c87d51205817c93e9a8d42c4baestevel * currently active.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((softp = iosram_master) == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("IOSRAM: iosram_sema_acquire: no master\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ENXIO);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&softp->intr_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Fail if SBBC region has not been mapped. This shouldn't
03831d35f7499c87d51205817c93e9a8d42c4baestevel * happen if we have a master IOSRAM, but we double-check.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (softp->sbbc_region == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&softp->intr_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("IOSRAM(%d): iosram_sema_acquire: "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "SBBC not mapped\n", softp->instance));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ENXIO);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* read semaphore value */
03831d35f7499c87d51205817c93e9a8d42c4baestevel sema_val = IOSRAM_SEMA_RD(softp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (old_value != NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel *old_value = sema_val;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (IOSRAM_SEMA_IS_HELD(sema_val)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* semaphore was held by someone else */
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = EBUSY;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* semaphore was not held, we just acquired it */
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&softp->intr_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("IOSRAM(%d): iosram_sema_acquire: "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "old value=0x%x rv=%d\n", softp->instance, sema_val, rv));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (rv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * iosram_sema_release: Release hardware semaphore.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This function will "release" the hardware semaphore, and return 0 on
03831d35f7499c87d51205817c93e9a8d42c4baestevel * success. If an error occured, one of the following values will be
03831d35f7499c87d51205817c93e9a8d42c4baestevel * returned:
03831d35f7499c87d51205817c93e9a8d42c4baestevel * EAGAIN: there is a tunnel switch in progress
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ENXIO: an IO error occured (e.g. SBBC not mapped)
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baesteveliosram_sema_release(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct iosramsoft *softp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(2, ("IOSRAM: in iosram_sema_release\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Disallow access if there is a tunnel switch in progress.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iosram_tswitch_active) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EAGAIN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Use current master IOSRAM for operation, fail if none is
03831d35f7499c87d51205817c93e9a8d42c4baestevel * currently active.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((softp = iosram_master) == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("IOSRAM: iosram_sema_release: no master\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ENXIO);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&softp->intr_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Fail if SBBC region has not been mapped in. This shouldn't
03831d35f7499c87d51205817c93e9a8d42c4baestevel * happen if we have a master IOSRAM, but we double-check.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (softp->sbbc_region == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&softp->intr_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("IOSRAM(%d): iosram_sema_release: "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "SBBC not mapped\n", softp->instance));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ENXIO);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* Release semaphore by clearing our semaphore register */
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAM_SEMA_WR(softp, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&softp->intr_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(1, ("IOSRAM(%d): iosram_sema_release: success\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->instance));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#if defined(IOSRAM_LOG)
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baesteveliosram_log(caddr_t fmt, intptr_t a1, intptr_t a2, intptr_t a3, intptr_t a4)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t seq;
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_log_t *logp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&iosram_log_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel seq = iosram_logseq++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel logp = &iosram_logbuf[seq % IOSRAM_MAXLOG];
03831d35f7499c87d51205817c93e9a8d42c4baestevel logp->seq = seq;
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni logp->tstamp = ddi_get_lbolt();
03831d35f7499c87d51205817c93e9a8d42c4baestevel logp->fmt = fmt;
03831d35f7499c87d51205817c93e9a8d42c4baestevel logp->arg1 = a1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel logp->arg2 = a2;
03831d35f7499c87d51205817c93e9a8d42c4baestevel logp->arg3 = a3;
03831d35f7499c87d51205817c93e9a8d42c4baestevel logp->arg4 = a4;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_log_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iosram_log_print) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "#%x @%lx ", logp->seq, logp->tstamp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (logp->fmt) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, logp->fmt, logp->arg1, logp->arg2,
03831d35f7499c87d51205817c93e9a8d42c4baestevel logp->arg3, logp->arg4);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (logp->fmt[strlen(logp->fmt)-1] != '\n') {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "fmt:%p args: %lx %lx %lx %lx\n",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void *)logp->fmt, logp->arg1, logp->arg2,
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki logp->arg3, logp->arg4);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* IOSRAM_LOG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#if defined(DEBUG)
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * iosram_get_keys(buf, len)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Return IOSRAM TOC in the specified buffer
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baesteveliosram_get_keys(iosram_toc_entry_t *bufp, uint32_t *len)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct iosram_chunk *chunkp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int cnt = (*len) / sizeof (iosram_toc_entry_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAMLOG(2, "iosram_get_keys(bufp:%p *len:%x)\n", bufp, *len, NULL,
03831d35f7499c87d51205817c93e9a8d42c4baestevel NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Copy data while holding the lock to prevent any data
03831d35f7499c87d51205817c93e9a8d42c4baestevel * corruption or invalid pointer dereferencing.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iosram_master == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EIO;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0, chunkp = chunks; i < nchunks && i < cnt;
03831d35f7499c87d51205817c93e9a8d42c4baestevel i++, chunkp++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel bufp[i].key = chunkp->toc_data.key;
03831d35f7499c87d51205817c93e9a8d42c4baestevel bufp[i].off = chunkp->toc_data.off;
03831d35f7499c87d51205817c93e9a8d42c4baestevel bufp[i].len = chunkp->toc_data.len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel bufp[i].unused = chunkp->toc_data.unused;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel *len = i * sizeof (iosram_toc_entry_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * iosram_print_state(instance)
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveliosram_print_state(int instance)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct iosramsoft *softp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char pn[MAXNAMELEN];
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (instance < 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp = iosram_master;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp = ddi_get_soft_state(iosramsoft_statep, instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (softp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "iosram_print_state: Can't find instance %d\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel instance = softp->instance;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&softp->intr_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "iosram_print_state(%d): ... %s\n", instance,
03831d35f7499c87d51205817c93e9a8d42c4baestevel ((softp == iosram_master) ? "MASTER" : "SLAVE"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) ddi_pathname(softp->dip, pn);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, " pathname:%s\n", pn);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, " instance:%d portid:%d iosramlen:0x%x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->instance, softp->portid, softp->iosramlen);
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki cmn_err(CE_CONT, " softp:%p handle:%p iosramp:%p\n", (void *)softp,
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void *)softp->handle, (void *)softp->iosramp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, " state:0x%x tswitch_ok:%x tswitch_fail:%x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel softp->state, softp->tswitch_ok, softp->tswitch_fail);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, " softintr_id:%p intr_busy:%x intr_pending:%x\n",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void *)softp->softintr_id, softp->intr_busy, softp->intr_pending);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&softp->intr_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * iosram_print_stats()
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveliosram_print_stats()
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t calls;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "iosram_stats:\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel calls = iosram_stats.read;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, " read ... calls:%x bytes:%lx avg_sz:%x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel calls, iosram_stats.bread,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (uint32_t)((calls != 0) ? (iosram_stats.bread/calls) : 0));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel calls = iosram_stats.write;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, " write ... calls:%x bytes:%lx avg_sz:%x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel calls, iosram_stats.bwrite,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (uint32_t)((calls != 0) ? (iosram_stats.bwrite/calls) : 0));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, " intr recv (real:%x soft:%x) sent:%x cback:%x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_stats.intr_recv, iosram_stats.sintr_recv,
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_stats.intr_send, iosram_stats.callbacks);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, " tswitch: %x getflag:%x setflag:%x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_stats.tswitch, iosram_stats.getflag,
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_stats.setflag);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, " iosram_rw_active_max: %x\n", iosram_rw_active_max);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveliosram_print_cback()
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_chunk_t *chunkp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Print callback handlers
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "IOSRAM callbacks:\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0, chunkp = chunks; i < nchunks; i++, chunkp++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (chunkp->cback.handler) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, " %2d: key:0x%x hdlr:%p arg:%p "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "busy:%d unreg:%d\n", i, chunkp->toc_data.key,
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void *)chunkp->cback.handler,
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void *)chunkp->cback.arg,
03831d35f7499c87d51205817c93e9a8d42c4baestevel chunkp->cback.busy, chunkp->cback.unregister);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveliosram_print_flags()
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t *keys;
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_flags_t *flags;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iosram_master == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "IOSRAM Flags: not accessible\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel keys = kmem_alloc(nchunks * sizeof (uint32_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel flags = kmem_alloc(nchunks * sizeof (iosram_flags_t), KM_SLEEP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < nchunks; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel keys[i] = chunks[i].toc_data.key;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_rep_get8(iosram_handle, (uint8_t *)&(flags[i]),
03831d35f7499c87d51205817c93e9a8d42c4baestevel (uint8_t *)(chunks[i].flagsp), sizeof (iosram_flags_t),
03831d35f7499c87d51205817c93e9a8d42c4baestevel DDI_DEV_AUTOINCR);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "IOSRAM Flags:\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < nchunks; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel " %2d: key: 0x%x data_valid:%x int_pending:%x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel i, keys[i], flags[i].data_valid, flags[i].int_pending);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(keys, nchunks * sizeof (uint32_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(flags, nchunks * sizeof (iosram_flags_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*PRINTFLIKE1*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveliosram_dprintf(const char *fmt, ...)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel char msg_buf[256];
03831d35f7499c87d51205817c93e9a8d42c4baestevel va_list adx;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel va_start(adx, fmt);
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) vsprintf(msg_buf, fmt, adx);
03831d35f7499c87d51205817c93e9a8d42c4baestevel va_end(adx);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "%s", msg_buf);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#if IOSRAM_LOG
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * iosram_print_log(int cnt)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Print last few entries of the IOSRAM log in reverse order
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baesteveliosram_print_log(int cnt)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cnt <= 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cnt = 20;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (cnt > IOSRAM_MAXLOG) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cnt = IOSRAM_MAXLOG;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "\niosram_logseq: 0x%x lbolt: %lx iosram_log_level:%x\n",
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni iosram_logseq, ddi_get_lbolt(), iosram_log_level);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "iosram_logbuf: %p max entries:0x%x\n",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void *)iosram_logbuf, IOSRAM_MAXLOG);
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = iosram_logseq; --i >= 0 && --cnt >= 0; ) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel iosram_log_t *logp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&iosram_log_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel logp = &iosram_logbuf[i %IOSRAM_MAXLOG];
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "#%x @%lx ", logp->seq, logp->tstamp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (logp->fmt) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, logp->fmt, logp->arg1, logp->arg2,
03831d35f7499c87d51205817c93e9a8d42c4baestevel logp->arg3, logp->arg4);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (logp->fmt[strlen(logp->fmt)-1] != '\n') {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "fmt:%p args: %lx %lx %lx %lx\n",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void *)logp->fmt, logp->arg1, logp->arg2,
03831d35f7499c87d51205817c93e9a8d42c4baestevel logp->arg3, logp->arg4);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&iosram_log_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* IOSRAM_LOG */