03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * CDDL HEADER START
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The contents of this file are subject to the terms of the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Common Development and Distribution License (the "License").
03831d35f7499c87d51205817c93e9a8d42c4baestevel * You may not use this file except in compliance with the License.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
03831d35f7499c87d51205817c93e9a8d42c4baestevel * or http://www.opensolaris.org/os/licensing.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * See the License for the specific language governing permissions
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and limitations under the License.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * When distributing Covered Code, include this CDDL HEADER in each
03831d35f7499c87d51205817c93e9a8d42c4baestevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If applicable, add the following below this CDDL HEADER, with the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * fields enclosed by brackets "[]" replaced with your own identifying
03831d35f7499c87d51205817c93e9a8d42c4baestevel * information: Portions Copyright [yyyy] [name of copyright owner]
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * CDDL HEADER END
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Use is subject to license terms.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This file contains the implementation of the mboxsc module, a mailbox layer
03831d35f7499c87d51205817c93e9a8d42c4baestevel * built upon the Starcat IOSRAM driver.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/types.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/systm.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/modctl.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/errno.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/ksynch.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/kmem.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/varargs.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/ddi.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sunddi.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/cmn_err.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/debug.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sysmacros.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/iosramreg.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/iosramio.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/mboxsc.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/mboxsc_impl.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Debugging facility
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DBGACT_NONE (0x00000000)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DBGACT_BREAK (0x00000001)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DBGACT_SHOWPOS (0x00000002)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DBGACT_DEFAULT DBGACT_NONE
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DBG_DEV (0x00000001)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DBG_CALLS (0x00000002)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DBG_RETS (0x00000004)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DBG_ARGS (0x00000008)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DBG_KMEM (0x00000010)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DBG_ALL (0xFFFFFFFF)
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic uint32_t mboxsc_debug_mask = 0x00000000;
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DPRINTF0(class, action, fmt) \
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_dprintf(__FILE__, __LINE__, (class), (action), (fmt))
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DPRINTF1(class, action, fmt, arg1) \
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_dprintf(__FILE__, __LINE__, (class), (action), (fmt),\
03831d35f7499c87d51205817c93e9a8d42c4baestevel (arg1))
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DPRINTF2(class, action, fmt, arg1, arg2) \
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_dprintf(__FILE__, __LINE__, (class), (action), (fmt),\
03831d35f7499c87d51205817c93e9a8d42c4baestevel (arg1), (arg2))
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DPRINTF3(class, action, fmt, arg1, arg2, arg3) \
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_dprintf(__FILE__, __LINE__, (class), (action), (fmt),\
03831d35f7499c87d51205817c93e9a8d42c4baestevel (arg1), (arg2), (arg3))
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DPRINTF4(class, action, fmt, arg1, arg2, arg3, arg4) \
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_dprintf(__FILE__, __LINE__, (class), (action), (fmt),\
03831d35f7499c87d51205817c93e9a8d42c4baestevel (arg1), (arg2), (arg3), (arg4))
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DPRINTF5(class, action, fmt, arg1, arg2, arg3, arg4, arg5) \
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_dprintf(__FILE__, __LINE__, (class), (action), (fmt),\
03831d35f7499c87d51205817c93e9a8d42c4baestevel (arg1), (arg2), (arg3), (arg4), (arg5))
03831d35f7499c87d51205817c93e9a8d42c4baestevel#else /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DPRINTF0(class, action, fmt)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DPRINTF1(class, action, fmt, arg1)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DPRINTF2(class, action, fmt, arg1, arg2)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DPRINTF3(class, action, fmt, arg1, arg2, arg3)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DPRINTF4(class, action, fmt, arg1, arg2, arg3, arg4)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define DPRINTF5(class, action, fmt, arg1, arg2, arg3, arg4, arg5)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Basic constants
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifndef TRUE
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define TRUE (1)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* TRUE */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifndef FALSE
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define FALSE (0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* FALSE */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Whenever mboxsc_init is called to create a new mailbox, an instance of
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mboxsc_mbox_t is created and inserted into a hash table to maintain
03831d35f7499c87d51205817c93e9a8d42c4baestevel * various information about the mailbox. The mbox_state, mbox_refcount, and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mbox_wait fields are all protected by the global mboxsc_lock mutex.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If lock contention between mailboxes becomes an issue, each mailbox will
03831d35f7499c87d51205817c93e9a8d42c4baestevel * need to be given its own mutex to protect the mbox_wait, mbox_state,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and mbox_update_wait fields. The mbox_refcount field will probably need to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * remain under global protection, however, since it is used to keep track of
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the number of threads sleeping inside the mailbox's various synchronization
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mechanisms and would consequently be difficult to protect using those same
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mechanisms.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baesteveltypedef struct mboxsc_mbox {
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t mbox_key;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int mbox_direction;
03831d35f7499c87d51205817c93e9a8d42c4baestevel void (*mbox_callback)(void);
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t mbox_length;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint16_t mbox_refcount;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint16_t mbox_state;
03831d35f7499c87d51205817c93e9a8d42c4baestevel kcondvar_t mbox_wait;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_msghdr_t mbox_header;
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct mboxsc_mbox *mbox_hash_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel} mboxsc_mbox_t;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Various state flags that can be set on a mailbox. Multiple states may
03831d35f7499c87d51205817c93e9a8d42c4baestevel * be active at the same time.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define STATE_IDLE (0x0000)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define STATE_WRITING (0x0001)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define STATE_READING (0x0002)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define STATE_HDRVALID (0x0004)
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Timeout periods for mboxsc_putmsg and mboxsc_getmsg, converted to ticks
03831d35f7499c87d51205817c93e9a8d42c4baestevel * from the microsecond values found in mboxsc_impl.h.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define EAGAIN_POLL (drv_usectohz(MBOXSC_EAGAIN_POLL_USECS))
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define PUTMSG_POLL (drv_usectohz(MBOXSC_PUTMSG_POLL_USECS))
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define HWLOCK_POLL (drv_usectohz(MBOXSC_HWLOCK_POLL_USECS))
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define LOOP_WARN_INTERVAL (drv_usectohz(MBOXSC_USECS_PER_SECOND * 15))
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Various tests that are performed on message header fields.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define IS_UNSOLICITED_TYPE(type) ((type) != MBOXSC_MSG_REPLY)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define MSG_TYPE_MATCHES(type, msgp) \
03831d35f7499c87d51205817c93e9a8d42c4baestevel (((type) == 0) || ((type) & (msgp)->msg_type))
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define MSG_CMD_MATCHES(cmd, msgp) \
03831d35f7499c87d51205817c93e9a8d42c4baestevel (((cmd) == 0) || ((cmd) == (msgp)->msg_cmd))
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define MSG_TRANSID_MATCHES(tid, msgp) \
03831d35f7499c87d51205817c93e9a8d42c4baestevel (((tid) == 0) || ((tid) == (msgp)->msg_transid))
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
ad9a7bd3532cf0ef931ded51a5ffe5d0496aad88Richard Lowe * This macro can be used to determine the size of any field in the message
ad9a7bd3532cf0ef931ded51a5ffe5d0496aad88Richard Lowe * header (or any other struct, for that matter).
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define FIELD_SIZE(type, field) (sizeof (((type *)0)->field))
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Mask used when generating unique transaction ID values.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This arbitrarily chosen value will be OR'd together with
03831d35f7499c87d51205817c93e9a8d42c4baestevel * a counter for each successive internally-generated transaction ID.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define TRANSID_GEN_MASK (0xFFC0000000000000)
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * All existing mailboxes are stored in a hash table with HASHTBL_SIZE
03831d35f7499c87d51205817c93e9a8d42c4baestevel * entries so they can be rapidly accessed by their key values.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define HASHTBL_SIZE (32)
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define HASH_KEY(key) ((((key) >> 24) ^ ((key) >> 16) ^ ((key) >> 9) ^\
03831d35f7499c87d51205817c93e9a8d42c4baestevel (key)) & (HASHTBL_SIZE - 1));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Unfortunately, it is necessary to calculate checksums on data split up
03831d35f7499c87d51205817c93e9a8d42c4baestevel * amongst different buffers in some cases. Consequently, mboxsc_checksum
03831d35f7499c87d51205817c93e9a8d42c4baestevel * accepts a "seed" value as one of its parameters. When first starting a
03831d35f7499c87d51205817c93e9a8d42c4baestevel * checksum calculation, the seed should be 0.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define CHKSUM_INIT (0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * local variables
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic kmutex_t mboxsc_lock;
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic mboxsc_mbox_t *mboxsc_hash_table[HASHTBL_SIZE];
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic uint32_t mboxsc_flaglock_count;
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic uint32_t mboxsc_active_version = MBOXSC_PROTOCOL_VERSION;
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic kcondvar_t mboxsc_dereference_cv;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Structures from modctl.h used for loadable module support.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The mboxsc API is a "miscellaneous" module.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern struct mod_ops mod_miscops;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct modlmisc modlmisc = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel &mod_miscops,
f500b19684bd0346ac05bec02a50af07f369da1aRichard Bean "IOSRAM Mailbox API 'mboxsc'",
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct modlinkage modlinkage = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel MODREV_1,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void *)&modlmisc,
03831d35f7499c87d51205817c93e9a8d42c4baestevel NULL
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Prototypes for local functions
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void mboxsc_iosram_callback(void *arg);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void mboxsc_hdrchange_callback(void);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int mboxsc_add_mailbox(mboxsc_mbox_t *mailboxp);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void mboxsc_close_mailbox(mboxsc_mbox_t *mailboxp);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void mboxsc_hashinsert_mailbox(mboxsc_mbox_t *mailboxp);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic mboxsc_mbox_t *mboxsc_hashfind_mailbox_by_key(uint32_t key);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic mboxsc_mbox_t *mboxsc_hashremove_mailbox_by_key(uint32_t key);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic mboxsc_chksum_t mboxsc_checksum(mboxsc_chksum_t seed, uint8_t *buf,
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t length);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int mboxsc_lock_flags(uint8_t mandatory, clock_t deadline);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int mboxsc_unlock_flags(uint8_t mandatory);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int mboxsc_timed_read(clock_t deadline, uint32_t key,
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t off, uint32_t len, caddr_t dptr);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int mboxsc_timed_write(clock_t deadline, uint32_t key,
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t off, uint32_t len, caddr_t dptr);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int mboxsc_timed_get_flag(clock_t deadline, uint32_t key,
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint8_t *data_validp, uint8_t *int_pendingp);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int mboxsc_timed_set_flag(clock_t deadline, uint32_t key,
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint8_t data_valid, uint8_t int_pending);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int mboxsc_timed_send_intr(clock_t deadline);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int mboxsc_expire_message(uint32_t key, int *resultp);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic uint64_t mboxsc_generate_transid(uint64_t prev_transid);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void mboxsc_reference_mailbox(mboxsc_mbox_t *mailboxp);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void mboxsc_dereference_mailbox(mboxsc_mbox_t *mailboxp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*PRINTFLIKE5*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void mboxsc_dprintf(const char *file, int line,
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t class, uint32_t action, const char *fmt, ...);
03831d35f7499c87d51205817c93e9a8d42c4baestevelint mboxsc_debug(int cmd, void *arg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * _init
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Loadable module support routine. Initializes global lock and hash table.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevel_init(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t sms_version;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "_init called\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Initialize all module resources.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_init(&mboxsc_lock, NULL, MUTEX_DRIVER, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_init(&mboxsc_dereference_cv, NULL, CV_DRIVER, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < HASHTBL_SIZE; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_hash_table[i] = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_flaglock_count = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mod_install(&modlinkage) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto failed;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Set the os_mbox_version field in the IOSRAM header to indicate the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * highest Mailbox Protocol version we support
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = iosram_hdr_ctrl(IOSRAM_HDRCMD_SET_OS_MBOX_VER,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void *)MBOXSC_PROTOCOL_VERSION);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto failed;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Read the sms_mbox_version field in the IOSRAM header to determine
03831d35f7499c87d51205817c93e9a8d42c4baestevel * what the greatest commonly supported version is.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = iosram_hdr_ctrl(IOSRAM_HDRCMD_GET_SMS_MBOX_VER,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void *)&sms_version);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto failed;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_active_version = MIN(MBOXSC_PROTOCOL_VERSION, sms_version);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF2(DBG_DEV, DBGACT_DEFAULT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "sms version: %d, active version: %d\n", sms_version,
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_active_version);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Register a callback with the IOSRAM driver to receive notification of
03831d35f7499c87d51205817c93e9a8d42c4baestevel * changes to the IOSRAM header, in case the sms_mbox_version field
03831d35f7499c87d51205817c93e9a8d42c4baestevel * changes.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = iosram_hdr_ctrl(IOSRAM_HDRCMD_REG_CALLBACK,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void *)mboxsc_hdrchange_callback);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto failed;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_RETS, DBGACT_DEFAULT, "_init ret: 0x%08x\n", error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If initialization fails, uninitialize resources.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelfailed:
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_destroy(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_destroy(&mboxsc_dereference_cv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_RETS, DBGACT_DEFAULT, "_init ret: 0x%08x\n", error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * _fini
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Loadable module support routine. Closes all mailboxes and releases all
03831d35f7499c87d51205817c93e9a8d42c4baestevel * resources.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevel_fini(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_mbox_t *mailboxp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "_fini called\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Attempt to remove the module. If successful, close all mailboxes
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and deallocate the global lock.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = mod_remove(&modlinkage);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) iosram_hdr_ctrl(IOSRAM_HDRCMD_REG_CALLBACK, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < HASHTBL_SIZE; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (mboxsc_hash_table[i] != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp = mboxsc_hash_table[i];
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_close_mailbox(mailboxp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_destroy(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_destroy(&mboxsc_dereference_cv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_RETS, DBGACT_DEFAULT, "_fini ret: 0x%08x\n", error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * _info
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Loadable module support routine.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevel_info(struct modinfo *modinfop)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "_info called\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = mod_info(&modlinkage, modinfop);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_RETS, DBGACT_DEFAULT, "_info ret: 0x%08x\n", error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mboxsc_init
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Attempts to create a new mailbox.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelmboxsc_init(uint32_t key, int direction, void (*event_handler)(void))
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_mbox_t *mailboxp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "mboxsc_init called\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "key = 0x%x\n", key);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "direction = %d\n", direction);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "event_handlerp = %p\n",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void *)event_handler);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check for valid direction and callback specification.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (((direction != MBOXSC_MBOX_IN) && (direction != MBOXSC_MBOX_OUT)) ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel ((event_handler != NULL) && (direction != MBOXSC_MBOX_IN))) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_RETS, DBGACT_DEFAULT, "mboxsc_init ret: 0x%08x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel EINVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EINVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Allocate memory for the mailbox structure and initialize all
03831d35f7499c87d51205817c93e9a8d42c4baestevel * caller-provided fields.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp = (mboxsc_mbox_t *)kmem_zalloc(sizeof (mboxsc_mbox_t),
03831d35f7499c87d51205817c93e9a8d42c4baestevel KM_SLEEP);
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki DPRINTF2(DBG_KMEM, DBGACT_DEFAULT, "kmem_zalloc(%lu) = %p\n",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki sizeof (mboxsc_mbox_t), (void *)mailboxp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp->mbox_key = key;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp->mbox_direction = direction;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp->mbox_callback = event_handler;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Attempt to add the mailbox. If unsuccessful, free the allocated
03831d35f7499c87d51205817c93e9a8d42c4baestevel * memory.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = mboxsc_add_mailbox(mailboxp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error != 0) {
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki DPRINTF2(DBG_KMEM, DBGACT_DEFAULT, "kmem_free(%p, %lu)\n",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void *)mailboxp, sizeof (mboxsc_mbox_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(mailboxp, sizeof (mboxsc_mbox_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_RETS, DBGACT_DEFAULT, "mboxsc_init ret: 0x%08x\n", error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mboxsc_fini
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Closes the mailbox with the indicated key, if it exists.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelmboxsc_fini(uint32_t key)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_mbox_t *mailboxp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "mboxsc_fini called\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "key = 0x%x\n", key);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Attempt to close the mailbox.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp = mboxsc_hashfind_mailbox_by_key(key);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mailboxp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EBADF;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (mailboxp->mbox_refcount != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_wait(&mboxsc_dereference_cv, &mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_close_mailbox(mailboxp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_RETS, DBGACT_DEFAULT, "mboxsc_fini ret: 0x%08x\n", error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mboxsc_putmsg
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Attempt to place a message into an outbound mailbox and signal the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * recipient. A successful return (0) indicates that the message was
03831d35f7499c87d51205817c93e9a8d42c4baestevel * successfully delivered.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelmboxsc_putmsg(uint32_t key, uint32_t type, uint32_t cmd, uint64_t *transidp,
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t length, void *datap, clock_t timeout)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int result;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int lock_held = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int unlock_err;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint8_t data_valid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel clock_t deadline;
03831d35f7499c87d51205817c93e9a8d42c4baestevel clock_t remainder;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_chksum_t checksum;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_mbox_t *mailboxp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_msghdr_t header;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG /* because lint whines about if stmts without consequents */
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "mboxsc_putmsg called\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "key = 0x%x\n", key);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "type = 0x%x\n", type);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "cmd = 0x%x\n", cmd);
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "transidp = %p\n", (void *)transidp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (transidp != NULL) {
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "*transidp = 0x%016lx\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel *transidp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "length = 0x%x\n", length);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "datap = %p\n", datap);
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "timeout = %ld\n", timeout);
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Perform some basic sanity checks on the message.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < MBOXSC_NUM_MSG_TYPES; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (type == (1 << i)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((i == MBOXSC_NUM_MSG_TYPES) || (cmd == 0) ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel ((datap == NULL) && (length != 0)) ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel (timeout < MBOXSC_PUTMSG_MIN_TIMEOUT_MSECS) ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel (timeout > MBOXSC_PUTMSG_MAX_TIMEOUT_MSECS)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "mboxsc_putmsg ret: 0x%08x\n", EINVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EINVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Initialize the header structure with values provided by the caller.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel header.msg_version = mboxsc_active_version;
03831d35f7499c87d51205817c93e9a8d42c4baestevel header.msg_type = type;
03831d35f7499c87d51205817c93e9a8d42c4baestevel header.msg_cmd = cmd;
03831d35f7499c87d51205817c93e9a8d42c4baestevel header.msg_length = MBOXSC_MSGHDR_SIZE + length;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (transidp != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel header.msg_transid = *transidp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel header.msg_transid = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Perform additional sanity checks on the mailbox and message.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Make sure that the specified mailbox really exists, that the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * given message will fit in it, and that the current message's
03831d35f7499c87d51205817c93e9a8d42c4baestevel * transaction ID isn't the same as the last message's transaction
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ID unless both messages are replies (it's okay, necessary even,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to reuse a transaction ID when resending a failed reply message,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * but that is the only case in which it is permissible).
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp = mboxsc_hashfind_mailbox_by_key(key);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mailboxp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EBADF;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if ((mailboxp->mbox_direction != MBOXSC_MBOX_OUT) ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel (length + MBOXSC_PROTOCOL_SIZE > mailboxp->mbox_length) ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel ((header.msg_transid == mailboxp->mbox_header.msg_transid) &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel ((type & mailboxp->mbox_header.msg_type) != MBOXSC_MSG_REPLY) &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel (header.msg_transid != 0))) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "mboxsc_putmsg ret: 0x%08x\n", error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If the message's transaction ID is set to 0, generate a unique
03831d35f7499c87d51205817c93e9a8d42c4baestevel * transaction ID and copy it into the message header. If the message
03831d35f7499c87d51205817c93e9a8d42c4baestevel * is successfully delivered and transidp != NULL, we'll copy this new
03831d35f7499c87d51205817c93e9a8d42c4baestevel * transid into *transidp later.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (header.msg_transid == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel header.msg_transid =
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_generate_transid(mailboxp->mbox_header.msg_transid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Don't allow mboxsc_putmsg to attempt to place a message for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * longer than the caller's timeout.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel deadline = ddi_get_lbolt() +
03831d35f7499c87d51205817c93e9a8d42c4baestevel drv_usectohz(timeout * MBOXSC_USECS_PER_MSEC);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Increment the reference count on the mailbox to keep it from being
03831d35f7499c87d51205817c93e9a8d42c4baestevel * closed, and wait for it to become available.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_reference_mailbox(mailboxp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel remainder = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel while ((mailboxp->mbox_state & STATE_WRITING) &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel (remainder > 0)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel remainder = cv_timedwait_sig(&(mailboxp->mbox_wait),
03831d35f7499c87d51205817c93e9a8d42c4baestevel &mboxsc_lock, deadline);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check to see whether or not the mailbox became available. If it
03831d35f7499c87d51205817c93e9a8d42c4baestevel * did not, decrement its reference count and return an error to the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * caller.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (remainder == -1) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = ENOSPC;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (remainder == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EINTR;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_dereference_mailbox(mailboxp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "mboxsc_putmsg ret: 0x%08x\n", error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Since the message is valid and we're going to try to write it to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * IOSRAM, record its header for future reference (e.g. to make sure the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * next message doesn't incorrectly use the same transID).
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel bcopy(&header, &(mailboxp->mbox_header), MBOXSC_MSGHDR_SIZE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Flag the mailbox as being in use and release the global lock.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp->mbox_state |= STATE_WRITING;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Calculate the message checksum using the header and the data.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel checksum = mboxsc_checksum(CHKSUM_INIT, (uint8_t *)&header,
03831d35f7499c87d51205817c93e9a8d42c4baestevel MBOXSC_MSGHDR_SIZE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel checksum = mboxsc_checksum(checksum, (uint8_t *)datap, length);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Attempt to write the message and checksum to IOSRAM until successful,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * or as long as time remains and no errors other than EAGAIN are
03831d35f7499c87d51205817c93e9a8d42c4baestevel * returned from any call to the IOSRAM driver in case there is a tunnel
03831d35f7499c87d51205817c93e9a8d42c4baestevel * switch in progress.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = mboxsc_timed_write(deadline, key, MBOXSC_MSGHDR_OFFSET,
03831d35f7499c87d51205817c93e9a8d42c4baestevel MBOXSC_MSGHDR_SIZE, (caddr_t)&header);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = mboxsc_timed_write(deadline, key, MBOXSC_DATA_OFFSET,
03831d35f7499c87d51205817c93e9a8d42c4baestevel length, (caddr_t)datap);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = mboxsc_timed_write(deadline, key, header.msg_length,
03831d35f7499c87d51205817c93e9a8d42c4baestevel MBOXSC_CHKSUM_SIZE, (caddr_t)&checksum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Lock the flags before setting data_valid. This isn't strictly
03831d35f7499c87d51205817c93e9a8d42c4baestevel * necessary for correct protocol operation, but it gives us a chance to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * verify that the flags lock is functional before we commit to sending
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the message.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = mboxsc_lock_flags(FALSE, deadline);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel lock_held = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (error == EBUSY) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EAGAIN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = mboxsc_timed_set_flag(deadline, key, IOSRAM_DATA_VALID,
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAM_INT_TO_SSC);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Unlock the flags. If an error is encountered, only return it if
03831d35f7499c87d51205817c93e9a8d42c4baestevel * another error hasn't been encountered previously.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (lock_held) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel unlock_err = mboxsc_unlock_flags(TRUE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((unlock_err != 0) && ((error == 0) || (error == EAGAIN))) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = unlock_err;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If time ran out or an IOSRAM call failed, notify other callers that
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the mailbox is available, decrement its reference count, and return
03831d35f7499c87d51205817c93e9a8d42c4baestevel * an error.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT((error != EINVAL) && (error != EMSGSIZE));
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp->mbox_state &= ~STATE_WRITING;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_broadcast(&(mailboxp->mbox_wait));
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_dereference_mailbox(mailboxp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "mboxsc_putmsg ret: 0x%08x\n", error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Send an interrupt to the remote mailbox interface to announce the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * presence of a new, valid message.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = mboxsc_timed_send_intr(deadline);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Wait until either the data_valid flag is set INVALID by the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * remote client or time runs out. Since we're calling delay as
03831d35f7499c87d51205817c93e9a8d42c4baestevel * a part of polling the flag anyway, we don't really need to do
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the usual continuous retry if iosram_get_flag returns EAGAIN.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel data_valid = IOSRAM_DATA_VALID;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error == DDI_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel do {
03831d35f7499c87d51205817c93e9a8d42c4baestevel delay(MIN(PUTMSG_POLL, deadline - ddi_get_lbolt()));
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = iosram_get_flag(key, &data_valid, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } while ((data_valid == IOSRAM_DATA_VALID) &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel ((error == EAGAIN) || (error == 0)) &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel (deadline - ddi_get_lbolt() >= 0));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If the data_valid flag was set to INVALID by the other side, the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * message was successfully transmitted. If it wasn't, but there
03831d35f7499c87d51205817c93e9a8d42c4baestevel * weren't any IOSRAM errors, the operation timed out. If there was a
03831d35f7499c87d51205817c93e9a8d42c4baestevel * problem with the IOSRAM, pass that info back to the caller.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (data_valid == IOSRAM_DATA_INVALID) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel result = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if ((error == 0) || (error == DDI_FAILURE)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel result = ETIMEDOUT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(error != EINVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel result = error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If the message has not been picked up, expire it. Note that this may
03831d35f7499c87d51205817c93e9a8d42c4baestevel * actually result in detecting successful message delivery if the SC
03831d35f7499c87d51205817c93e9a8d42c4baestevel * picks it up at the last moment. If expiration fails due to an error,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * return an error to the user even if the message appears to have
03831d35f7499c87d51205817c93e9a8d42c4baestevel * been successfully delivered.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (data_valid == IOSRAM_DATA_VALID) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = mboxsc_expire_message(key, &result);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((error != 0) && ((result == 0) || (result == ETIMEDOUT))) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel result = error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If the message was successfully delivered, and we generated a
03831d35f7499c87d51205817c93e9a8d42c4baestevel * transaction ID for the caller, and the caller wants to know what it
03831d35f7499c87d51205817c93e9a8d42c4baestevel * was, give it to them.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((result == 0) && (transidp != NULL) && (*transidp == 0)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel *transidp = header.msg_transid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Regardless of whether the message was successfully transmitted or
03831d35f7499c87d51205817c93e9a8d42c4baestevel * not, notify other callers that the mailbox is available and decrement
03831d35f7499c87d51205817c93e9a8d42c4baestevel * its reference count.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp->mbox_state &= ~STATE_WRITING;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_broadcast(&(mailboxp->mbox_wait));
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_dereference_mailbox(mailboxp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_RETS, DBGACT_DEFAULT, "mboxsc_putmsg ret: 0x%08x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel result);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (result);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mboxsc_getmsg
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Attempt to retrieve a message from the mailbox with the given key that
03831d35f7499c87d51205817c93e9a8d42c4baestevel * matches values provided in msgp. A successful return (0) indicates that
03831d35f7499c87d51205817c93e9a8d42c4baestevel * a message matching the caller's request was successfully received within
03831d35f7499c87d51205817c93e9a8d42c4baestevel * timeout milliseconds. If a message matching the caller's request is
03831d35f7499c87d51205817c93e9a8d42c4baestevel * detected, but can't be successfully read, an error will be returned even
03831d35f7499c87d51205817c93e9a8d42c4baestevel * if the caller's timeout hasn't expired.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelmboxsc_getmsg(uint32_t key, uint32_t *typep, uint32_t *cmdp, uint64_t *transidp,
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t *lengthp, void *datap, clock_t timeout)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t datalen;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint8_t data_valid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint8_t lock_held;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_chksum_t read_checksum;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_chksum_t calc_checksum;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t read_transid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel clock_t deadline;
03831d35f7499c87d51205817c93e9a8d42c4baestevel clock_t remainder;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_mbox_t *mailboxp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_msghdr_t header;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG /* because lint whines about if stmts without consequents */
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "mboxsc_getmsg called\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "key = 0x%x\n", key);
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "typep = %p\n", (void *)typep);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (typep != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "*typep = 0x%x\n", *typep);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "cmdp = %p\n", (void *)cmdp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cmdp != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "*cmdp = 0x%x\n", *cmdp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "transidp = %p\n", (void *)transidp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (transidp != NULL) {
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "*transidp = 0x%lx\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel *transidp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "lengthp = %p\n", (void *)lengthp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (lengthp != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "*lengthp = 0x%x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel *lengthp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "datap = %p\n", datap);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "timeout = %ld\n", timeout);
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Perform basic sanity checks on the caller's request.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((typep == NULL) || (*typep >= (1 << MBOXSC_NUM_MSG_TYPES)) ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel (cmdp == NULL) || (transidp == NULL) || (lengthp == NULL) ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel ((datap == NULL) && (*lengthp != 0)) ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel (timeout < MBOXSC_GETMSG_MIN_TIMEOUT_MSECS) ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel (timeout > MBOXSC_GETMSG_MAX_TIMEOUT_MSECS)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "mboxsc_getmsg ret: 0x%08x\n", EINVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EINVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Don't allow mboxsc_getmsg to attempt to receive a message for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * longer than the caller's timeout.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel deadline = ddi_get_lbolt() +
03831d35f7499c87d51205817c93e9a8d42c4baestevel drv_usectohz(timeout * MBOXSC_USECS_PER_MSEC);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Perform additional sanity checks on the client's request and the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * associated mailbox.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp = mboxsc_hashfind_mailbox_by_key(key);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mailboxp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EBADF;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (mailboxp->mbox_direction != MBOXSC_MBOX_IN) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "mboxsc_getmsg ret: 0x%08x\n", error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The request is okay, so reference the mailbox (to keep it from being
03831d35f7499c87d51205817c93e9a8d42c4baestevel * closed), and proceed with the real work.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_reference_mailbox(mailboxp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Certain failures that may occur late in the process of getting a
03831d35f7499c87d51205817c93e9a8d42c4baestevel * message (e.g. checksum error, cancellation by the sender) are
03831d35f7499c87d51205817c93e9a8d42c4baestevel * supposed to leave the recipient waiting for the next message to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * arrive rather than returning an error. To facilitate restarting
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the message acquisition process, the following label is provided
03831d35f7499c87d51205817c93e9a8d42c4baestevel * as a target for a very few judiciously-placed "goto"s.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The mboxsc_lock mutex MUST be held when jumping to this point.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelmboxsc_getmsg_retry:
03831d35f7499c87d51205817c93e9a8d42c4baestevel ;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If there is a valid message in the mailbox right now, check to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * see if it matches the caller's request. If not, or if another
03831d35f7499c87d51205817c93e9a8d42c4baestevel * caller is already reading it, wait for either the arrival of the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * next message or the expiration of the caller's specified timeout.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (!(mailboxp->mbox_state & STATE_HDRVALID) ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel (mailboxp->mbox_state & STATE_READING) ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel !MSG_TYPE_MATCHES(*typep, &(mailboxp->mbox_header)) ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel !MSG_CMD_MATCHES(*cmdp, &(mailboxp->mbox_header)) ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel !MSG_TRANSID_MATCHES(*transidp, &(mailboxp->mbox_header))) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel remainder = cv_timedwait_sig(&(mailboxp->mbox_wait),
03831d35f7499c87d51205817c93e9a8d42c4baestevel &mboxsc_lock, deadline);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (remainder == -1) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = ETIMEDOUT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (remainder == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EINTR;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_dereference_mailbox(mailboxp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "mboxsc_getmsg ret: 0x%08x\n", error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If somebody sends us a message using a Mailbox Protocol version
03831d35f7499c87d51205817c93e9a8d42c4baestevel * greater than the highest one we understand, invalidate the message,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * because we can't safely interpret anything beyond the version field.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mailboxp->mbox_header.msg_version > MBOXSC_PROTOCOL_VERSION) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_DEV, DBGACT_DEFAULT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "incoming message with unsupported version %d\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp->mbox_header.msg_version);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp->mbox_state &= ~STATE_HDRVALID;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto mboxsc_getmsg_retry;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * At this point, there is a stored message header that matches the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * caller's request, but the actual message may no longer be valid
03831d35f7499c87d51205817c93e9a8d42c4baestevel * in IOSRAM. Check the data_valid flag to see whether or not
03831d35f7499c87d51205817c93e9a8d42c4baestevel * this is the case. If the message has expired, go start over.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The global mutex is held while reading flag data from IOSRAM to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * avoid certain race conditions. One race condition is still
03831d35f7499c87d51205817c93e9a8d42c4baestevel * possible (i.e. SC-side has just set the data_valid flag for a
03831d35f7499c87d51205817c93e9a8d42c4baestevel * new message, but the stored message header hasn't been updated
03831d35f7499c87d51205817c93e9a8d42c4baestevel * yet), but it won't cause incorrect behavior (just some wasted work).
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = iosram_get_flag(key, &data_valid, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(error != EINVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (data_valid != IOSRAM_DATA_VALID) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp->mbox_state &= ~STATE_HDRVALID;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto mboxsc_getmsg_retry;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if ((error == EAGAIN) && (deadline - ddi_get_lbolt() >= 0)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel delay(MIN(EAGAIN_POLL, deadline - ddi_get_lbolt()));
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto mboxsc_getmsg_retry;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If the message is larger than the caller's buffer, provide the caller
03831d35f7499c87d51205817c93e9a8d42c4baestevel * with the length of the message and return an error.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel datalen = mailboxp->mbox_header.msg_length - MBOXSC_MSGHDR_SIZE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((error == 0) && (datalen > *lengthp)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel *lengthp = datalen;
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EMSGSIZE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Note that there's no need to check STATE_HDRVALID before broadcasting
03831d35f7499c87d51205817c93e9a8d42c4baestevel * here because the header is guaranteed to be valid at this point.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_broadcast(&(mailboxp->mbox_wait));
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_dereference_mailbox(mailboxp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "mboxsc_getmsg ret: 0x%08x\n", error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Store a copy of the current message header, flag the mailbox to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * indicate that it is being read and attempt to read the message data
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and checksum.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel bcopy(&(mailboxp->mbox_header), &header, MBOXSC_MSGHDR_SIZE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp->mbox_state |= STATE_READING;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (datalen > 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = mboxsc_timed_read(deadline, key, MBOXSC_DATA_OFFSET,
03831d35f7499c87d51205817c93e9a8d42c4baestevel datalen, (caddr_t)datap);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = mboxsc_timed_read(deadline, key, header.msg_length,
03831d35f7499c87d51205817c93e9a8d42c4baestevel MBOXSC_CHKSUM_SIZE, (caddr_t)&read_checksum);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check for errors that may have occurred while accessing IOSRAM.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT((error != EINVAL) && (error != EMSGSIZE));
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp->mbox_state &= ~STATE_READING;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mailboxp->mbox_state & STATE_HDRVALID) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_broadcast(&(mailboxp->mbox_wait));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_dereference_mailbox(mailboxp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "mboxsc_getmsg ret: 0x%08x\n", error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Calculate the checksum for the header and data that was read from
03831d35f7499c87d51205817c93e9a8d42c4baestevel * IOSRAM.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel calc_checksum = mboxsc_checksum(CHKSUM_INIT, (uint8_t *)&header,
03831d35f7499c87d51205817c93e9a8d42c4baestevel MBOXSC_MSGHDR_SIZE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel calc_checksum = mboxsc_checksum(calc_checksum, (uint8_t *)datap,
03831d35f7499c87d51205817c93e9a8d42c4baestevel datalen);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If the message header has been invalidated, note the change.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If a the checksum verification fails, invalidate the message
03831d35f7499c87d51205817c93e9a8d42c4baestevel * header. In either case, go back to the beginning and wait
03831d35f7499c87d51205817c93e9a8d42c4baestevel * for a new message.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!(mailboxp->mbox_state & STATE_HDRVALID)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = -1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF0(DBG_DEV, DBGACT_DEFAULT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "mboxsc_getmsg - message invalidated while reading\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (read_checksum != calc_checksum) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = -1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp->mbox_state &= ~STATE_HDRVALID;
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF0(DBG_DEV, DBGACT_DEFAULT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "mboxsc_getmsg - message failed checksum\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "mboxsc_getmsg - message failed checksum\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error == -1) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp->mbox_state &= ~STATE_READING;
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto mboxsc_getmsg_retry;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Acquire the hardware lock used for synchronization of data_valid flag
03831d35f7499c87d51205817c93e9a8d42c4baestevel * access to avoid race conditions. If it is acquired, try to check the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * current data_valid flag and transaction ID to verify that the message
03831d35f7499c87d51205817c93e9a8d42c4baestevel * is still valid.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((error = mboxsc_lock_flags(FALSE, deadline)) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel lock_held = FALSE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We don't "do" EBUSY here, so treat it as EAGAIN.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error == EBUSY) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EAGAIN;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel lock_held = TRUE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = mboxsc_timed_get_flag(deadline, key, &data_valid, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((error == 0) && (data_valid == IOSRAM_DATA_VALID)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = mboxsc_timed_read(deadline, key,
ad9a7bd3532cf0ef931ded51a5ffe5d0496aad88Richard Lowe offsetof(mboxsc_msghdr_t, msg_transid),
03831d35f7499c87d51205817c93e9a8d42c4baestevel FIELD_SIZE(mboxsc_msghdr_t, msg_transid),
03831d35f7499c87d51205817c93e9a8d42c4baestevel (caddr_t)&read_transid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If something failed along the way, either the error is unrecoverable
03831d35f7499c87d51205817c93e9a8d42c4baestevel * or we're just plain out of time, so unlock the flags if they were
03831d35f7499c87d51205817c93e9a8d42c4baestevel * locked, release the mailbox, wake up other potential readers if
03831d35f7499c87d51205817c93e9a8d42c4baestevel * there's still a message around, and return.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT((error != EINVAL) && (error != EMSGSIZE));
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (lock_held) {
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) mboxsc_unlock_flags(TRUE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp->mbox_state &= ~STATE_READING;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mailboxp->mbox_state & STATE_HDRVALID) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_broadcast(&(mailboxp->mbox_wait));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_dereference_mailbox(mailboxp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "mboxsc_getmsg ret: 0x%08x\n", error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If the data_valid flag isn't set to IOSRAM_DATA_VALID, or the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * message transaction ID in IOSRAM has changed, the message being
03831d35f7499c87d51205817c93e9a8d42c4baestevel * read was timed out by its sender. Since the data_valid flag can't
03831d35f7499c87d51205817c93e9a8d42c4baestevel * change as long as we have the flags locked, we can safely mark the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * stored message header invalid if either the data_valid flag isn't set
03831d35f7499c87d51205817c93e9a8d42c4baestevel * or the stored transaction ID doesn't match the one we read. (If
03831d35f7499c87d51205817c93e9a8d42c4baestevel * data_valid is set, the transaction ID shouldn't be changing
03831d35f7499c87d51205817c93e9a8d42c4baestevel * underneath us.) On the other hand, if there may still be a valid
03831d35f7499c87d51205817c93e9a8d42c4baestevel * message, wake up any pending readers.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((data_valid != IOSRAM_DATA_VALID) ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel (read_transid != header.msg_transid)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp->mbox_state &= ~STATE_READING;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((data_valid != IOSRAM_DATA_VALID) ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel (mailboxp->mbox_header.msg_transid != read_transid)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp->mbox_state &= ~STATE_HDRVALID;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (mailboxp->mbox_state & STATE_HDRVALID) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_broadcast(&(mailboxp->mbox_wait));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Unfortunately, we can't be holding mboxsc_lock when we unlock
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the flags. However, we have to hold the flags until here to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * make sure the SC doesn't change the message's state while
03831d35f7499c87d51205817c93e9a8d42c4baestevel * we're checking to see if we should invalidate our stored
03831d35f7499c87d51205817c93e9a8d42c4baestevel * header.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = mboxsc_unlock_flags(TRUE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF0(DBG_DEV, DBGACT_DEFAULT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "mboxsc_getmsg() - message invalidated by sender\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto mboxsc_getmsg_retry;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If everything has worked up to this point, all that remains is
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to set the data_valid flag to IOSRAM_DATA_INVALID, tidy up, and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * return the message. If the flag can't be set, the message can't
03831d35f7499c87d51205817c93e9a8d42c4baestevel * be received, so keep trying as long as there is time.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = mboxsc_timed_set_flag(deadline, key, IOSRAM_DATA_INVALID,
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAM_INT_NONE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) mboxsc_unlock_flags(TRUE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(error != EINVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_dereference_mailbox(mailboxp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp->mbox_state &= ~STATE_READING;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mailboxp->mbox_state & STATE_HDRVALID) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_broadcast(&(mailboxp->mbox_wait));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "mboxsc_getmsg ret: 0x%08x\n", error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If the message was read 100% successfully and the stored message
03831d35f7499c87d51205817c93e9a8d42c4baestevel * header for the mailbox still matches the message that was read,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * invalidate it to prevent other readers from trying to read it.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (bcmp(&(mailboxp->mbox_header), &header, MBOXSC_MSGHDR_SIZE) == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp->mbox_state &= ~STATE_HDRVALID;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (mailboxp->mbox_state & STATE_HDRVALID) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_broadcast(&(mailboxp->mbox_wait));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_dereference_mailbox(mailboxp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp->mbox_state &= ~STATE_READING;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Since we're successfully returning a message, we need to provide the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * caller with all of the interesting header information.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel *typep = header.msg_type;
03831d35f7499c87d51205817c93e9a8d42c4baestevel *cmdp = header.msg_cmd;
03831d35f7499c87d51205817c93e9a8d42c4baestevel *transidp = header.msg_transid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel *lengthp = datalen;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_RETS, DBGACT_DEFAULT, "mboxsc_getmsg ret: 0x%08x\n", 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mboxsc_ctrl
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This routine provides access to a variety of services not available through
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the basic API.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelmboxsc_ctrl(uint32_t key, uint32_t cmd, void *arg)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_mbox_t *mailboxp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "mboxsc_ctrl called\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "key = 0x%x\n", key);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "cmd = 0x%x\n", cmd);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "arg = %p\n", arg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp = mboxsc_hashfind_mailbox_by_key(key);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mailboxp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_RETS, DBGACT_DEFAULT, "mboxsc_ctrl ret: 0x%08x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel EBADF);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EBADF);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (cmd) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case MBOXSC_CMD_VERSION:
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Return the Protocol version currently in use. Since
03831d35f7499c87d51205817c93e9a8d42c4baestevel * there is only one version that exists right now, we
03831d35f7499c87d51205817c93e9a8d42c4baestevel * can't be using anything else.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (arg == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel *(uint32_t *)arg = MBOXSC_PROTOCOL_VERSION;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case MBOXSC_CMD_MAXVERSION:
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Return the highest Protocol version that we support.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (arg == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel *(uint32_t *)arg = MBOXSC_PROTOCOL_VERSION;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case MBOXSC_CMD_MAXDATALEN:
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Return the amount of space available for client data
03831d35f7499c87d51205817c93e9a8d42c4baestevel * in the indicated mailbox.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (arg == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel *(uint32_t *)arg = mailboxp->mbox_length -
03831d35f7499c87d51205817c93e9a8d42c4baestevel MBOXSC_PROTOCOL_SIZE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case MBOXSC_CMD_PUTMSG_TIMEOUT_RANGE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_timeout_range_t *rangep;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Return the range of acceptable timeout values for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mboxsc_putmsg, expressed in milliseconds.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (arg == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rangep = (mboxsc_timeout_range_t *)arg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel rangep->min_timeout = MBOXSC_PUTMSG_MIN_TIMEOUT_MSECS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel rangep->max_timeout = MBOXSC_PUTMSG_MAX_TIMEOUT_MSECS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case MBOXSC_CMD_GETMSG_TIMEOUT_RANGE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_timeout_range_t *rangep;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Return the range of acceptable timeout values for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mboxsc_getmsg, expressed in milliseconds.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (arg == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EINVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rangep = (mboxsc_timeout_range_t *)arg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel rangep->min_timeout = MBOXSC_GETMSG_MIN_TIMEOUT_MSECS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel rangep->max_timeout = MBOXSC_GETMSG_MAX_TIMEOUT_MSECS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = ENOTSUP;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_RETS, DBGACT_DEFAULT, "mboxsc_ctrl ret: 0x%08x\n", error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mboxsc_putmsg_def_timeout
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This routine returns the default mboxsc_putmsg timeout provided for the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * convenience of clients.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelclock_t
03831d35f7499c87d51205817c93e9a8d42c4baestevelmboxsc_putmsg_def_timeout(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (MBOXSC_PUTMSG_DEF_TIMEOUT_MSECS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mboxsc_iosram_callback
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This routine is registered with the IOSRAM driver for all inbound mailboxes,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and performs preliminary processing of all new messages.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelmboxsc_iosram_callback(void *arg)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint8_t data_valid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t key = (uint32_t)(uintptr_t)arg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_mbox_t *mailboxp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "mboxsc_iosram_callback called\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "arg = 0x%x\n", key);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp = mboxsc_hashfind_mailbox_by_key(key);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We shouldn't ever receive a callback for a mailbox that doesn't
03831d35f7499c87d51205817c93e9a8d42c4baestevel * exist or for an output mailbox.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mailboxp != NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mailboxp->mbox_direction == MBOXSC_MBOX_IN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Attempt to read the header of the mailbox. If the IOSRAM returns
03831d35f7499c87d51205817c93e9a8d42c4baestevel * EAGAIN, indicating a tunnel switch is in progress, do not retry
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the operation.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp->mbox_state &= ~STATE_HDRVALID;
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = iosram_rd(key, MBOXSC_MSGHDR_OFFSET, MBOXSC_MSGHDR_SIZE,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (caddr_t)&(mailboxp->mbox_header));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If somebody sends us a message using a Mailbox Protocol version
03831d35f7499c87d51205817c93e9a8d42c4baestevel * greater than the highest one we understand, ignore the message,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * because we can't safely interpret anything beyond the version field.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mailboxp->mbox_header.msg_version > MBOXSC_PROTOCOL_VERSION) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = -1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_DEV, DBGACT_DEFAULT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "incoming message with unsupported version %d\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp->mbox_header.msg_version);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If this message is a repeat of a previous message (which should
03831d35f7499c87d51205817c93e9a8d42c4baestevel * only happen with reply messages), it is conceivable that a client
03831d35f7499c87d51205817c93e9a8d42c4baestevel * already executing in mboxsc_getmsg for the previous message could
03831d35f7499c87d51205817c93e9a8d42c4baestevel * end up receiving the new message before this callback gets a chance
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to execute. If that happens, the data_valid flag will already have
03831d35f7499c87d51205817c93e9a8d42c4baestevel * been cleared. Call iosram_get_flag to see if that is the case, and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * do not process the message if it is.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = iosram_get_flag(key, &data_valid, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((error == 0) && (data_valid != IOSRAM_DATA_VALID)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = -1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If the iosram_rd call failed, return.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "mboxsc_iosram_callback ret (0x%08x)\n", error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If the message read from IOSRAM was unsolicited, invoke
03831d35f7499c87d51205817c93e9a8d42c4baestevel * its callback. Otherwise, wake all threads that are waiting
03831d35f7499c87d51205817c93e9a8d42c4baestevel * in mboxsc_getmsg.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp->mbox_state |= STATE_HDRVALID;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (IS_UNSOLICITED_TYPE(mailboxp->mbox_header.msg_type) &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel (mailboxp->mbox_callback != NULL)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_reference_mailbox(mailboxp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel (*(mailboxp->mbox_callback))();
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_dereference_mailbox(mailboxp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_broadcast(&(mailboxp->mbox_wait));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF0(DBG_RETS, DBGACT_DEFAULT, "mboxsc_iosram_callback ret\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mboxsc_hdrchange_callback
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This routine is registered with the IOSRAM driver to react to any changes SMS
03831d35f7499c87d51205817c93e9a8d42c4baestevel * makes to the IOSRAM header.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelmboxsc_hdrchange_callback(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t sms_version;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF0(DBG_CALLS, DBGACT_DEFAULT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "mboxsc_hdrchange_callback called\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = iosram_hdr_ctrl(IOSRAM_HDRCMD_GET_SMS_MBOX_VER,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void *)&sms_version);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_DEV, DBGACT_DEFAULT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "sms mailbox version = %d\n", sms_version);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_active_version = MIN(MBOXSC_PROTOCOL_VERSION,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sms_version);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF0(DBG_RETS, DBGACT_DEFAULT, "mboxsc_hdrchange_callback ret\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mboxsc_add_mailbox
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If no other mailbox exists with the same key as this mailbox, attempt to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * retrieve its length from the IOSRAM driver and register the mboxsc callback
03831d35f7499c87d51205817c93e9a8d42c4baestevel * for the associated IOSRAM chunk. If successful, initialize the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * non-client-supplied mailbox fields and insert it into the hash table.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * NOTE: The caller MUST hold mboxsc_lock to avoid corrupting the hash table.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelmboxsc_add_mailbox(mboxsc_mbox_t *mailboxp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t key = mailboxp->mbox_key;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "mboxsc_add_mailbox called\n");
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "mailboxp = %p\n", (void *)mailboxp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The global lock must be held by the caller.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mutex_owned(&mboxsc_lock));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Don't create the mailbox if it already exists.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mboxsc_hashfind_mailbox_by_key(key) != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "mboxsc_add_mailbox ret: 0x%08x\n", EEXIST);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EEXIST);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Obtain the mailbox length and register the mboxsc callback with the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * IOSRAM driver. If either call to the IOSRAM driver fails, or the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * chunk is too small to be used as a mailbox, return an error to the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * caller.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = iosram_ctrl(key, IOSRAM_CMD_CHUNKLEN, &(mailboxp->mbox_length));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((error == 0) && (mailboxp->mbox_length < MBOXSC_PROTOCOL_SIZE)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EFAULT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((error == 0) && (mailboxp->mbox_direction == MBOXSC_MBOX_IN)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = iosram_register(key, mboxsc_iosram_callback,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void *)(uintptr_t)(key));
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error == EBUSY) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EFAULT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "mboxsc_add_mailbox ret: 0x%08x\n", error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Initialize remaining mailbox fields and insert mailbox into
03831d35f7499c87d51205817c93e9a8d42c4baestevel * hash table.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp->mbox_state = STATE_IDLE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp->mbox_refcount = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_init(&(mailboxp->mbox_wait), NULL, CV_DRIVER, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_hashinsert_mailbox(mailboxp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_RETS, DBGACT_DEFAULT, "mboxsc_add_mailbox ret: 0x%08x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mboxsc_close_mailbox
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Remove a mailbox from the hash table, unregister its IOSRAM callback, and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * deallocate its resources.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * NOTE: The caller MUST hold mboxsc_lock to avoid corrupting the hash table.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelmboxsc_close_mailbox(mboxsc_mbox_t *mailboxp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t key = mailboxp->mbox_key;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "mboxsc_close_mailbox called\n");
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "mailboxp = %p\n", (void *)mailboxp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The global lock must be held by the caller.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mutex_owned(&mboxsc_lock));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Unregister the mboxsc callback for this particular mailbox.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mailboxp->mbox_direction == MBOXSC_MBOX_IN) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = iosram_unregister(key);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error == EINVAL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_DEV, DBGACT_DEFAULT, "invalid key (0x%08x)"
03831d35f7499c87d51205817c93e9a8d42c4baestevel " reported in mboxsc_close_mailbox.\n", key);
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Remove the mailbox from the hash table and deallocate its resources.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) mboxsc_hashremove_mailbox_by_key(key);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_destroy(&(mailboxp->mbox_wait));
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki DPRINTF2(DBG_KMEM, DBGACT_DEFAULT, "kmem_free(%p, %lu)\n",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void *)mailboxp, sizeof (mboxsc_mbox_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel kmem_free(mailboxp, sizeof (mboxsc_mbox_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF0(DBG_RETS, DBGACT_DEFAULT, "mboxsc_close_mailbox ret\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mboxsc_hashinsert_mailbox
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Insert a fully initialized mailbox into the hash table. No duplicate
03831d35f7499c87d51205817c93e9a8d42c4baestevel * checking is performed at this point, so the caller is responsible for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * duplicate prevention if it is desired.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * NOTE: The caller MUST hold mboxsc_lock to avoid corrupting the hash table.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelmboxsc_hashinsert_mailbox(mboxsc_mbox_t *mailboxp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t hash;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF0(DBG_CALLS, DBGACT_DEFAULT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "mboxsc_hashinsert_mailbox called\n");
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "mailboxp = %p\n", (void *)mailboxp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The global lock must be held by the caller.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mutex_owned(&mboxsc_lock));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel hash = HASH_KEY(mailboxp->mbox_key);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp->mbox_hash_next = mboxsc_hash_table[hash];
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_hash_table[hash] = mailboxp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF0(DBG_RETS, DBGACT_DEFAULT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "mboxsc_hashinsert_mailbox ret\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mboxsc_hashfind_mailbox_by_key
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Locate a mailbox with the given key in the hash table. Return a pointer
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to the mailbox if it exists, or NULL if no matching mailbox is found.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * NOTE: The caller MUST hold mboxsc_lock to avoid corrupting the hash table.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic mboxsc_mbox_t *
03831d35f7499c87d51205817c93e9a8d42c4baestevelmboxsc_hashfind_mailbox_by_key(uint32_t key)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t hash;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_mbox_t *mailboxp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF0(DBG_CALLS, DBGACT_DEFAULT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "mboxsc_hashfind_mailbox_by_key called\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "key = 0x%x\n", key);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The global lock must be held by the caller.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mutex_owned(&mboxsc_lock));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel hash = HASH_KEY(key);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp = mboxsc_hash_table[hash];
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (mailboxp != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mailboxp->mbox_key == key) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp = mailboxp->mbox_hash_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki "mboxsc_hashfind_mailbox_by_key ret: %p\n", (void *)mailboxp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (mailboxp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mboxsc_hashremove_mailbox_by_key
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Locate a mailbox with the given key in the hash table. If it exists,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * remove it from the hash table and return a pointer to it. Otherwise,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * return NULL.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * NOTE: The caller MUST hold mboxsc_lock to avoid corrupting the hash table.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic mboxsc_mbox_t *
03831d35f7499c87d51205817c93e9a8d42c4baestevelmboxsc_hashremove_mailbox_by_key(uint32_t key)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t hash;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_mbox_t *mailboxp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_mbox_t *last;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF0(DBG_CALLS, DBGACT_DEFAULT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "mboxsc_hashremove_mailbox_by_key called\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "key = 0x%x\n", key);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The global lock must be held by the caller.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mutex_owned(&mboxsc_lock));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel hash = HASH_KEY(key);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp = mboxsc_hash_table[hash];
03831d35f7499c87d51205817c93e9a8d42c4baestevel last = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (mailboxp != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mailboxp->mbox_key == key) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel last = mailboxp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp = mailboxp->mbox_hash_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If a mailbox was found, remove it from the hash table.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mailboxp != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (last == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_hash_table[hash] = mailboxp->mbox_hash_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel last->mbox_hash_next = mailboxp->mbox_hash_next;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp->mbox_hash_next = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki "mboxsc_hashremove_mailbox_by_key ret: %p\n", (void *)mailboxp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (mailboxp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mboxsc_checksum
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Given a pointer to a data buffer and its length, calculate the checksum of
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the data contained therein.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic mboxsc_chksum_t
03831d35f7499c87d51205817c93e9a8d42c4baestevelmboxsc_checksum(mboxsc_chksum_t seed, uint8_t *buf, uint32_t length)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "mboxsc_checksum called\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "seed = 0x%x\n", seed);
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "buf = %p\n", (void *)buf);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "length = 0x%x\n", length);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (length-- > 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel seed += *(buf++);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_RETS, DBGACT_DEFAULT, "mboxsc_checksum ret: 0x%08x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel seed);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (seed);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mboxsc_lock_flags
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Acquire the hardware lock used for data_valid flag synchronization. If the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * lock is currently held by SMS and acquisition is mandatory, just keep on
03831d35f7499c87d51205817c93e9a8d42c4baestevel * trying until it is acquired. If acquisition is not mandatory, keep trying
03831d35f7499c87d51205817c93e9a8d42c4baestevel * until the given deadline has been reached. To avoid loading the system
03831d35f7499c87d51205817c93e9a8d42c4baestevel * unreasonably on EBUSY or EAGAIN, sleep for an appropriate amount of time
03831d35f7499c87d51205817c93e9a8d42c4baestevel * before retrying. If a hardware error is encountered return it to the caller.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If the lock is held, but not by SMS, clear it and acquire it. Nobody
03831d35f7499c87d51205817c93e9a8d42c4baestevel * else should be grabbing that lock.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelmboxsc_lock_flags(uint8_t mandatory, clock_t deadline)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int warned = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t sema;
03831d35f7499c87d51205817c93e9a8d42c4baestevel clock_t pause;
03831d35f7499c87d51205817c93e9a8d42c4baestevel clock_t warning_time = ddi_get_lbolt() + LOOP_WARN_INTERVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "mboxsc_lock_flags called\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "mandatory = 0x%x\n", mandatory);
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "deadline = 0x%lx\n", deadline);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Keep trying to acquire the lock until successful or (if acquisition
03831d35f7499c87d51205817c93e9a8d42c4baestevel * is not mandatory) time runs out. If EBUSY (lock is already held) or
03831d35f7499c87d51205817c93e9a8d42c4baestevel * EAGAIN (tunnel switch in progress) is encountered, sleep for an
03831d35f7499c87d51205817c93e9a8d42c4baestevel * appropriate amount of time before retrying. Any other error is
03831d35f7499c87d51205817c93e9a8d42c4baestevel * unrecoverable.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel do {
03831d35f7499c87d51205817c93e9a8d42c4baestevel pause = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Since multiple threads could conceivably want the flag lock
03831d35f7499c87d51205817c93e9a8d42c4baestevel * at the same time, we place the lock under a mutex and keep a
03831d35f7499c87d51205817c93e9a8d42c4baestevel * counter indicating how many threads have the flags locked at
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the moment.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((mboxsc_flaglock_count > 0) ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel ((error = iosram_sema_acquire(&sema)) == 0)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_flaglock_count++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (warned) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "Flags locked");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF0(DBG_RETS, DBGACT_DEFAULT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "mboxsc_lock_flags ret: 0\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If iosram_sema_acquire returned EBUSY (lock already held),
03831d35f7499c87d51205817c93e9a8d42c4baestevel * make sure the lock is held by SMS, since nobody else should
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ever be holding it. If EBUSY or EAGAIN (tunnel switch in
03831d35f7499c87d51205817c93e9a8d42c4baestevel * progress) was returned, determine the appropriate amount of
03831d35f7499c87d51205817c93e9a8d42c4baestevel * time to sleep before trying again.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error == EBUSY) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (IOSRAM_SEMA_GET_IDX(sema) != IOSRAM_SEMA_SMS_IDX) {
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) iosram_sema_release();
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "Incorrect flag lock value read (0x%08x)",
03831d35f7499c87d51205817c93e9a8d42c4baestevel sema);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel pause = (mandatory ? HWLOCK_POLL :
03831d35f7499c87d51205817c93e9a8d42c4baestevel MIN(HWLOCK_POLL, deadline -
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_get_lbolt()));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (error == EAGAIN) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel pause = (mandatory ? EAGAIN_POLL : MIN(EAGAIN_POLL,
03831d35f7499c87d51205817c93e9a8d42c4baestevel deadline - ddi_get_lbolt()));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We had to hold the lock until now to protect the potential
03831d35f7499c87d51205817c93e9a8d42c4baestevel * iosram_sema_release call above.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If EAGAIN or EBUSY was encountered, we're looping.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((error == EAGAIN) || (error == EBUSY)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If we've been looping here for a while, something is
03831d35f7499c87d51205817c93e9a8d42c4baestevel * probably wrong, so we should generated a warning.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (warning_time - ddi_get_lbolt() <= 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!warned) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel warned = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "Unable to lock flags (0x%08x)",
03831d35f7499c87d51205817c93e9a8d42c4baestevel error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "Still unable to lock flags");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel warning_time = ddi_get_lbolt() +
03831d35f7499c87d51205817c93e9a8d42c4baestevel LOOP_WARN_INTERVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Sleep a while before trying again.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel delay(pause);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } while (((error == EAGAIN) || (error == EBUSY)) &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel (mandatory || (deadline - ddi_get_lbolt() >= 0)));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If something really bad has happened, generate a warning.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((error != EAGAIN) && (error != EBUSY)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "Flag locking failed! (%d)", error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_RETS, DBGACT_DEFAULT, "mboxsc_lock_flags ret: 0x%08x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mboxsc_unlock_flags
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Release the hardware lock used for data_valid flag synchronization.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If a hardware error is encountered, return it to the caller. If the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mandatory flag is set, loop and retry if EAGAIN is encountered.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelmboxsc_unlock_flags(uint8_t mandatory)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int warned = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel clock_t warning_time = ddi_get_lbolt() + LOOP_WARN_INTERVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mboxsc_flaglock_count != 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "mboxsc_unlock_flags called\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "mandatory = 0x%x\n", mandatory);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel do {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Since multiple threads could conceivably want the flag lock
03831d35f7499c87d51205817c93e9a8d42c4baestevel * at the same time, we place the lock under a mutex and keep a
03831d35f7499c87d51205817c93e9a8d42c4baestevel * counter indicating how many threads have the flags locked at
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the moment.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((mboxsc_flaglock_count > 1) ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel ((error = iosram_sema_release()) == 0)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_flaglock_count--;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (warned) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "Flags unlocked");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF0(DBG_RETS, DBGACT_DEFAULT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "mboxsc_unlock_flags ret: 0\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If iosram_sema_release returned EAGAIN (tunnel switch in
03831d35f7499c87d51205817c93e9a8d42c4baestevel * progress) and unlocking the flags is mandatory, sleep before
03831d35f7499c87d51205817c93e9a8d42c4baestevel * trying again. If we've been trying for a while, display a
03831d35f7499c87d51205817c93e9a8d42c4baestevel * warning message too.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((error == EAGAIN) && mandatory) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (warning_time - ddi_get_lbolt() <= 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!warned) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel warned = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "Unable to unlock "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "flags (iosram EAGAIN)");
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "Still unable to unlock flags");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel warning_time = ddi_get_lbolt() +
03831d35f7499c87d51205817c93e9a8d42c4baestevel LOOP_WARN_INTERVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel delay(EAGAIN_POLL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } while ((error == EAGAIN) && mandatory);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_RETS, DBGACT_DEFAULT, "mboxsc_unlock_flags ret: 0x%08x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mboxsc_timed_read
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This function is just a wrapper around iosram_rd that will keep sleeping
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and retrying, up to a given deadline, if iosram_rd returns EAGAIN
03831d35f7499c87d51205817c93e9a8d42c4baestevel * (presumably due to a tunnel switch).
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelmboxsc_timed_read(clock_t deadline, uint32_t key, uint32_t off, uint32_t len,
03831d35f7499c87d51205817c93e9a8d42c4baestevel caddr_t dptr)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "mboxsc_timed_read called\n");
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "deadline = 0x%lx\n", deadline);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "key = 0x%x\n", key);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "off = 0x%x\n", off);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "len = 0x%x\n", len);
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "dptr = %p\n", (void *)dptr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel do {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = iosram_rd(key, off, len, dptr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error == EAGAIN) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel delay(MIN(EAGAIN_POLL, deadline - ddi_get_lbolt()));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } while ((error == EAGAIN) && (deadline - ddi_get_lbolt() >= 0));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "mboxsc_timed_read ret: 0x%08x\n", error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mboxsc_timed_write
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This function is just a wrapper around iosram_wr that will keep sleeping
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and retrying, up to a given deadline, if iosram_wr returns EAGAIN
03831d35f7499c87d51205817c93e9a8d42c4baestevel * (presumably due to a tunnel switch).
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelmboxsc_timed_write(clock_t deadline, uint32_t key, uint32_t off, uint32_t len,
03831d35f7499c87d51205817c93e9a8d42c4baestevel caddr_t dptr)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "mboxsc_timed_write called\n");
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "deadline = 0x%lx\n", deadline);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "key = 0x%x\n", key);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "off = 0x%x\n", off);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "len = 0x%x\n", len);
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "dptr = %p\n", (void *)dptr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel do {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = iosram_wr(key, off, len, dptr);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error == EAGAIN) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel delay(MIN(EAGAIN_POLL, deadline - ddi_get_lbolt()));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } while ((error == EAGAIN) && (deadline - ddi_get_lbolt() >= 0));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "mboxsc_timed_write ret: 0x%08x\n", error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mboxsc_timed_get_flag
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This function is just a wrapper around iosram_get_flag that will keep
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sleeping and retrying, up to a given deadline, if iosram_get_flag returns
03831d35f7499c87d51205817c93e9a8d42c4baestevel * EAGAIN (presumably due to a tunnel switch).
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelmboxsc_timed_get_flag(clock_t deadline, uint32_t key, uint8_t *data_validp,
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint8_t *int_pendingp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "mboxsc_timed_get_flag called\n");
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "deadline = 0x%lx\n", deadline);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "key = 0x%x\n", key);
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "data_validp = %p\n",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void *)data_validp);
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "int_pendingp = %p\n",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void *)int_pendingp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel do {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = iosram_get_flag(key, data_validp, int_pendingp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error == EAGAIN) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel delay(MIN(EAGAIN_POLL, deadline - ddi_get_lbolt()));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } while ((error == EAGAIN) && (deadline - ddi_get_lbolt() >= 0));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "mboxsc_timed_get_flag ret: 0x%08x\n", error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mboxsc_timed_set_flag
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This function is just a wrapper around iosram_set_flag that will keep
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sleeping and retrying, up to a given deadline, if iosram_set_flag returns
03831d35f7499c87d51205817c93e9a8d42c4baestevel * EAGAIN (presumably due to a tunnel switch).
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelmboxsc_timed_set_flag(clock_t deadline, uint32_t key, uint8_t data_valid,
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint8_t int_pending)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "mboxsc_timed_set_flag called\n");
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "deadline = 0x%lx\n", deadline);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "key = 0x%x\n", key);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "data_valid = %d\n", data_valid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "int_pending = %d\n", int_pending);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel do {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = iosram_set_flag(key, data_valid, int_pending);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error == EAGAIN) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel delay(MIN(EAGAIN_POLL, deadline - ddi_get_lbolt()));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } while ((error == EAGAIN) && (deadline - ddi_get_lbolt() >= 0));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "mboxsc_timed_set_flag ret: 0x%08x\n", error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mboxsc_timed_send_intr
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This function is just a wrapper around iosram_send_intr that will keep
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sleeping and retrying, up to a given deadline, if iosram_send_intr returns
03831d35f7499c87d51205817c93e9a8d42c4baestevel * EAGAIN (presumably due to a tunnel switch).
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelmboxsc_timed_send_intr(clock_t deadline)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "mboxsc_timed_send_intr called\n");
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "deadline = 0x%lx\n", deadline);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel do {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = iosram_send_intr();
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error == DDI_FAILURE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel delay(MIN(EAGAIN_POLL, deadline - ddi_get_lbolt()));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } while ((error == DDI_FAILURE) && (deadline - ddi_get_lbolt() >= 0));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "mboxsc_timed_send_intr ret: 0x%08x\n", error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mboxsc_expire_message
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This function is called by mboxsc_putmsg to handle expiration of messages
03831d35f7499c87d51205817c93e9a8d42c4baestevel * that weren't picked up before they timed out. It will not return until the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * message has been picked up (which isn't expected), the message has been
03831d35f7499c87d51205817c93e9a8d42c4baestevel * successfully expired, or a serious error has been encountered. If the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * message is finally picked up, it will set the value pointed to by "resultp"
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to 0. Unlike other sections of code, this function will never time out on
03831d35f7499c87d51205817c93e9a8d42c4baestevel * EAGAIN from the iosram driver, since it is important that both sides of the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * IOSRAM agree on whether or not a message was delivered successfully.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelmboxsc_expire_message(uint32_t key, int *resultp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int lock_held = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int warned = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint8_t data_valid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel clock_t warning_time = ddi_get_lbolt() + LOOP_WARN_INTERVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "mboxsc_expire_message called\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "key = 0x%x\n", key);
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "resultp = %p\n", (void *)resultp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel do {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Lock the flags if they aren't locked already.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!lock_held) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = mboxsc_lock_flags(TRUE, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel lock_held = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If the flags were locked successfully, reread the data-valid
03831d35f7499c87d51205817c93e9a8d42c4baestevel * flag.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = iosram_get_flag(key, &data_valid, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If the data-valid flag was read successfully, see if it has
03831d35f7499c87d51205817c93e9a8d42c4baestevel * been cleared or not, as the other side may have finally read
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the message.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (data_valid == IOSRAM_DATA_INVALID) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Surprise! The SC finally picked up the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * message, so delivery succeeded after all.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (*resultp == ETIMEDOUT) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel *resultp = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The message still hasn't been read, so try to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * clear the data-valid flag.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = iosram_set_flag(key,
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAM_DATA_INVALID, IOSRAM_INT_NONE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If the flags were locked, unlock them, no matter what else
03831d35f7499c87d51205817c93e9a8d42c4baestevel * has or has not succeeded. Don't overwrite the existing value
03831d35f7499c87d51205817c93e9a8d42c4baestevel * of "error" unless no errors other than EAGAIN have been
03831d35f7499c87d51205817c93e9a8d42c4baestevel * encountered previously. If we hit EAGAIN at some point,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * unlocking the flags here is optional. In all other cases, it
03831d35f7499c87d51205817c93e9a8d42c4baestevel * is mandatory.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (lock_held) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel int unlock_err;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error == EAGAIN) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel unlock_err = mboxsc_unlock_flags(FALSE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel unlock_err = mboxsc_unlock_flags(TRUE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (unlock_err == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel lock_held = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if ((error == 0) || (error == EAGAIN)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = unlock_err;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Did we hit a tunnel switch? (iosram driver returns EAGAIN)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If so, sleep for a while before trying the whole process
03831d35f7499c87d51205817c93e9a8d42c4baestevel * again.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error == EAGAIN) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If we've been stuck in this loop for a while,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * something is probably wrong, and we should display a
03831d35f7499c87d51205817c93e9a8d42c4baestevel * warning.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (warning_time - ddi_get_lbolt() <= 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!warned) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel warned = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "Unable to clear flag "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "(iosram EAGAIN)");
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "Still unable to clear flag");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel warning_time = ddi_get_lbolt() +
03831d35f7499c87d51205817c93e9a8d42c4baestevel LOOP_WARN_INTERVAL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel delay(EAGAIN_POLL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } while (error == EAGAIN);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If the data-valid flag was not successfully cleared due to some sort
03831d35f7499c87d51205817c93e9a8d42c4baestevel * of problem, report it. Otherwise, if we looped for a while on EAGAIN
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and generated a warning about it, indicate that everything is okay
03831d35f7499c87d51205817c93e9a8d42c4baestevel * now.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "Message expiration failure! (%d)", error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (warned) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "Flag cleared");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "mboxsc_expire_message ret: 0x%08x\n", error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mboxsc_generate_transid
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This function generates unique transaction IDs using an incrementing counter.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The value generated is guaranteed not to be the same as the prev_transid
03831d35f7499c87d51205817c93e9a8d42c4baestevel * value passed in by the caller.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic uint64_t
03831d35f7499c87d51205817c93e9a8d42c4baestevelmboxsc_generate_transid(uint64_t prev_transid)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint64_t new_transid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel static uint64_t transid_counter = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "mboxsc_generate_transid called");
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "prev_transid = 0x%016lx\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel prev_transid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel do {
03831d35f7499c87d51205817c93e9a8d42c4baestevel new_transid = TRANSID_GEN_MASK | transid_counter++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (transid_counter & TRANSID_GEN_MASK) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel transid_counter = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } while (new_transid == prev_transid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki "mboxsc_generate_transid ret: 0x%016lx", new_transid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (new_transid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mboxsc_reference_mailbox
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Increment the mailbox's reference count to prevent it from being closed.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This really doesn't deserve to be a function, but since a dereference
03831d35f7499c87d51205817c93e9a8d42c4baestevel * function is needed, having a corresponding reference function makes the code
03831d35f7499c87d51205817c93e9a8d42c4baestevel * clearer.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelmboxsc_reference_mailbox(mboxsc_mbox_t *mailboxp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "mboxsc_reference_mailbox called");
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "mailboxp = 0x%p\n",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void *)mailboxp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mutex_owned(&mboxsc_lock));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp->mbox_refcount++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF0(DBG_RETS, DBGACT_DEFAULT, "mboxsc_reference_mailbox ret");
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mboxsc_dereference_mailbox
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Decrement the mailbox's reference count, and if the count has gone to zero,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * signal any threads waiting for mailboxes to be completely dereferenced.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelmboxsc_dereference_mailbox(mboxsc_mbox_t *mailboxp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF0(DBG_CALLS, DBGACT_DEFAULT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "mboxsc_dereference_mailbox called");
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "mailboxp = 0x%p\n",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void *)mailboxp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(mutex_owned(&mboxsc_lock));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp->mbox_refcount--;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mailboxp->mbox_refcount == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_broadcast(&mboxsc_dereference_cv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF0(DBG_RETS, DBGACT_DEFAULT, "mboxsc_dereference_mailbox ret");
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifndef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelmboxsc_debug(int cmd, void *arg)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "mboxsc_debug called");
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF0(DBG_RETS, DBGACT_DEFAULT, "mboxsc_debug ret");
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ENOTSUP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel#else /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void print_hash_table(void);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int print_mailbox_by_key(uint32_t key);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void print_mailbox(mboxsc_mbox_t *mailboxp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelmboxsc_debug(int cmd, void *arg)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "mboxsc_debug called\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (cmd) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case MBOXSC_PRNMBOX:
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = print_mailbox_by_key((uint32_t)(uintptr_t)arg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case MBOXSC_PRNHASHTBL:
03831d35f7499c87d51205817c93e9a8d42c4baestevel print_hash_table();
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case MBOXSC_SETDBGMASK:
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_debug_mask = (uint32_t)(uintptr_t)arg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_DEV, DBGACT_DEFAULT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "Error: unknown mboxsc debug cmd (%d)\n", cmd);
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = ENOTTY;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_RETS, DBGACT_DEFAULT, "mboxsc_debug ret: 0x%08x\n", error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*PRINTFLIKE5*/
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelmboxsc_dprintf(
03831d35f7499c87d51205817c93e9a8d42c4baestevel const char *file,
03831d35f7499c87d51205817c93e9a8d42c4baestevel int line,
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t class,
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint32_t action,
03831d35f7499c87d51205817c93e9a8d42c4baestevel const char *fmt,
03831d35f7499c87d51205817c93e9a8d42c4baestevel ...)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char indent_buf[64];
03831d35f7499c87d51205817c93e9a8d42c4baestevel char msg_buf[256];
03831d35f7499c87d51205817c93e9a8d42c4baestevel va_list adx;
03831d35f7499c87d51205817c93e9a8d42c4baestevel static uint32_t indent = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (action & DBGACT_SHOWPOS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_CONT, "%s at line %d:\n", file, line);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (class & DBG_RETS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel indent--;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (class & mboxsc_debug_mask) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel indent_buf[0] = '\0';
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < indent; i++) {
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) strcat(indent_buf, " ");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
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%s", indent_buf, msg_buf);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (class & DBG_CALLS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel indent++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (action & DBGACT_BREAK) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel debug_enter("");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelprint_hash_table(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int i;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_mbox_t *mailboxp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "print_hash_table called\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (i = 0; i < HASHTBL_SIZE; i++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_DEV, DBGACT_DEFAULT, "hash[%02d]:\n", i);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (mailboxp = mboxsc_hash_table[i]; mailboxp != NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp = mailboxp->mbox_hash_next) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF2(DBG_DEV, DBGACT_DEFAULT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel " key: 0x%08x, dir: %d\n", mailboxp->mbox_key,
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp->mbox_direction);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF0(DBG_RETS, DBGACT_DEFAULT, "print_hash_table ret\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelprint_mailbox_by_key(uint32_t key)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mboxsc_mbox_t *mailboxp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "print_mailbox_by_key called\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "key = 0x%08x\n", key);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp = mboxsc_hashfind_mailbox_by_key(key);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mailboxp != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel print_mailbox(mailboxp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_DEV, DBGACT_DEFAULT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "print_mailbox_by_key: no such mbox 0x%08x\n", key);
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = EBADF;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&mboxsc_lock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF1(DBG_RETS, DBGACT_DEFAULT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "print_mailbox_by_key ret: 0x%08x\n", error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelprint_mailbox(mboxsc_mbox_t *mailboxp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF0(DBG_CALLS, DBGACT_DEFAULT, "print_mailbox called\n");
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki DPRINTF1(DBG_ARGS, DBGACT_DEFAULT, "mailboxp = %p\n",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void *)mailboxp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mailboxp->mbox_direction == MBOXSC_MBOX_IN) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF3(DBG_DEV, DBGACT_DEFAULT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "key = 0x%08x, dir = %d, callback = %p\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp->mbox_key, mailboxp->mbox_direction,
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void *)mailboxp->mbox_callback);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF2(DBG_DEV, DBGACT_DEFAULT, "key = 0x%08x, dir = %d\n",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (int)mailboxp->mbox_key, mailboxp->mbox_direction);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF3(DBG_DEV, DBGACT_DEFAULT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "length = %d, refcount = %d, state = %d\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp->mbox_length, mailboxp->mbox_refcount,
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp->mbox_state);
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki /* LINTED E_BAD_FORMAT_ARG_TYPE2 */
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki DPRINTF2(DBG_DEV, DBGACT_DEFAULT, "waitcv = %p, hashnext = %p\n",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void *)&mailboxp->mbox_wait, (void *)mailboxp->mbox_hash_next);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mailboxp->mbox_direction == MBOXSC_MBOX_IN) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF3(DBG_DEV, DBGACT_DEFAULT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "hdr.type = 0x%x, hdr.cmd = 0x%x, hdr.len = 0x%x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp->mbox_header.msg_type,
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp->mbox_header.msg_cmd,
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp->mbox_header.msg_length);
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki DPRINTF1(DBG_DEV, DBGACT_DEFAULT, "hdr.tid = 0x%016lx\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel mailboxp->mbox_header.msg_transid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF0(DBG_RETS, DBGACT_DEFAULT, "print_mailbox ret\n");
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */