03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * CDDL HEADER START
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The contents of this file are subject to the terms of the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Common Development and Distribution License (the "License").
03831d35f7499c87d51205817c93e9a8d42c4baestevel * You may not use this file except in compliance with the License.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
03831d35f7499c87d51205817c93e9a8d42c4baestevel * or http://www.opensolaris.org/os/licensing.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * See the License for the specific language governing permissions
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and limitations under the License.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * When distributing Covered Code, include this CDDL HEADER in each
03831d35f7499c87d51205817c93e9a8d42c4baestevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If applicable, add the following below this CDDL HEADER, with the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * fields enclosed by brackets "[]" replaced with your own identifying
03831d35f7499c87d51205817c93e9a8d42c4baestevel * information: Portions Copyright [yyyy] [name of copyright owner]
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * CDDL HEADER END
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Use is subject to license terms.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * provide the interface to the layered drivers (send request/receive
03831d35f7499c87d51205817c93e9a8d42c4baestevel * response to the RMC
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Header files
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/conf.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/callb.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/cyclic.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/membar.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/modctl.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/strlog.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sunddi.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/ddi.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/types.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/disp.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/rmc_comm_dp.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/rmc_comm_dp_boot.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/rmc_comm_drvintf.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/rmc_comm.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid dp_reset(struct rmc_comm_state *, uint8_t, boolean_t, boolean_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid dp_wake_up_waiter(struct rmc_comm_state *, uint8_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int rmc_comm_send_req_resp(struct rmc_comm_state *rcs,
03831d35f7499c87d51205817c93e9a8d42c4baestevel rmc_comm_msg_t *request, rmc_comm_msg_t *response, uint32_t wait_time);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int rmc_comm_wait_bp_reply(struct rmc_comm_state *,
03831d35f7499c87d51205817c93e9a8d42c4baestevel rmc_comm_dp_state_t *, dp_req_resp_t *, clock_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void rmc_comm_wait_enable_to_send(struct rmc_comm_state *,
03831d35f7499c87d51205817c93e9a8d42c4baestevel rmc_comm_dp_state_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void rmc_comm_wake_up_next(struct rmc_comm_state *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void rmc_comm_send_pend_req(caddr_t arg);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int rmc_comm_dreq_thread_start(struct rmc_comm_state *rcs);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void rmc_comm_dreq_thread_kill(struct rmc_comm_state *rcs);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * leaf driver to use this function to send a request to the remote side (RMC)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and wait for a reply
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelrmc_comm_request_response(rmc_comm_msg_t *request,
03831d35f7499c87d51205817c93e9a8d42c4baestevel rmc_comm_msg_t *response, uint32_t wait_time)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct rmc_comm_state *rcs;
52f4394b704526bb3aa41e8729fd03e754732822jfrank int err;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the soft state struct (instance 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((rcs = rmc_comm_getstate(NULL, 0,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni "rmc_comm_request_response")) == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (RCENOSOFTSTATE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
52f4394b704526bb3aa41e8729fd03e754732822jfrank do {
52f4394b704526bb3aa41e8729fd03e754732822jfrank err = rmc_comm_send_req_resp(rcs, request, response, wait_time);
52f4394b704526bb3aa41e8729fd03e754732822jfrank } while (err == RCEGENERIC);
52f4394b704526bb3aa41e8729fd03e754732822jfrank return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * leaf driver to use this function to send a request to the remote side (RMC)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * without waiting for a reply. If flag is RMC_COMM_DREQ_URGENT, the request
03831d35f7499c87d51205817c93e9a8d42c4baestevel * message is sent once-off (an eventual pending request is aborted). This
03831d35f7499c87d51205817c93e9a8d42c4baestevel * flag must only be used when try to send a request in critical condition
03831d35f7499c87d51205817c93e9a8d42c4baestevel * (while the system is shutting down for instance and the CPU signature
03831d35f7499c87d51205817c93e9a8d42c4baestevel * has to be sent). Otherwise, the request is stored in a temporary location
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and delivered by a thread.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelrmc_comm_request_nowait(rmc_comm_msg_t *request, uint8_t flag)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct rmc_comm_state *rcs;
03831d35f7499c87d51205817c93e9a8d42c4baestevel rmc_comm_dp_state_t *dps;
03831d35f7499c87d51205817c93e9a8d42c4baestevel rmc_comm_drvintf_state_t *dis;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dp_message_t req;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int err = RCNOERR;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint8_t flags = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the soft state struct (instance 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((rcs = rmc_comm_getstate(NULL, 0,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni "rmc_comm_request_response")) == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (RCENOSOFTSTATE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * just a sanity check...
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (request == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(rcs, DAPI, (CE_CONT, "reqnowait, invalid args\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (RCEINVARG);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!IS_NUMBERED_MSG(request->msg_type)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(rcs, DAPI, (CE_CONT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "reqnowait, ctrl msg not allowed! req type=%x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel request->msg_type));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (RCEINVARG);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (flag == RMC_COMM_DREQ_URGENT) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Send this request with high priority i.e. abort eventual
03831d35f7499c87d51205817c93e9a8d42c4baestevel * request/response pending sessions.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dps = &rcs->dp_state;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(rcs, DAPI, (CE_CONT, "going to send request=%x (URG)\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel request->msg_type));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
6fa6856ee31afb8f296ddb9f5201cfc9cc5ad729arutz /*
6fa6856ee31afb8f296ddb9f5201cfc9cc5ad729arutz * Handle the case where we are called during panic
6fa6856ee31afb8f296ddb9f5201cfc9cc5ad729arutz * processing. If that occurs, then another thread in
6fa6856ee31afb8f296ddb9f5201cfc9cc5ad729arutz * rmc_comm might have been idled by panic() while
6fa6856ee31afb8f296ddb9f5201cfc9cc5ad729arutz * holding dp_mutex. As a result, do not unconditionally
6fa6856ee31afb8f296ddb9f5201cfc9cc5ad729arutz * grab dp_mutex.
6fa6856ee31afb8f296ddb9f5201cfc9cc5ad729arutz */
6fa6856ee31afb8f296ddb9f5201cfc9cc5ad729arutz if (ddi_in_panic() != 0) {
6fa6856ee31afb8f296ddb9f5201cfc9cc5ad729arutz if (mutex_tryenter(dps->dp_mutex) == 0) {
6fa6856ee31afb8f296ddb9f5201cfc9cc5ad729arutz return (RCENODATALINK);
6fa6856ee31afb8f296ddb9f5201cfc9cc5ad729arutz }
6fa6856ee31afb8f296ddb9f5201cfc9cc5ad729arutz } else {
6fa6856ee31afb8f296ddb9f5201cfc9cc5ad729arutz mutex_enter(dps->dp_mutex);
6fa6856ee31afb8f296ddb9f5201cfc9cc5ad729arutz }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * send the request only if the protocol data link is up.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * it is pointless to send it in the other case.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (dps->data_link_ok) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * clean up an eventual pending request/response session
03831d35f7499c87d51205817c93e9a8d42c4baestevel * (save its current status)
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (dps->pending_request) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel flags = dps->req_resp.flags;
03831d35f7499c87d51205817c93e9a8d42c4baestevel rmc_comm_dp_mcleanup(rcs);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * send the request message
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel req.msg_type = request->msg_type;
03831d35f7499c87d51205817c93e9a8d42c4baestevel req.msg_buf = (uint8_t *)request->msg_buf;
03831d35f7499c87d51205817c93e9a8d42c4baestevel req.msg_msglen = (uint16_t)request->msg_len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(rcs, DAPI, (CE_CONT, "send request=%x (URG)\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel request->msg_type));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = rmc_comm_dp_msend(rcs, &req);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * wait for fifos to drain
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel rmc_comm_serdev_drain(rcs);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * clean up the current session
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel rmc_comm_dp_mcleanup(rcs);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * abort an old session (if any)
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (dps->pending_request) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dps->req_resp.flags = flags;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dp_wake_up_waiter(rcs, MSG_ERROR);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(dps->dp_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Get an 'independent' thread (rmc_comm_send_pend_req)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to send this request (since the calling thread does not
03831d35f7499c87d51205817c93e9a8d42c4baestevel * want to wait). Copy the request in the drvintf state
03831d35f7499c87d51205817c93e9a8d42c4baestevel * structure and signal the thread.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dis = &rcs->drvi_state;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(dis->dreq_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (dis->dreq_state == RMC_COMM_DREQ_ST_WAIT) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(rcs, DAPI, (CE_CONT, "get to send request=%x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel request->msg_type));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * copy the request in a temporary location
03831d35f7499c87d51205817c93e9a8d42c4baestevel * (drvinf_state structure) and signal the thread
03831d35f7499c87d51205817c93e9a8d42c4baestevel * that a request message has to be delivered
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (request->msg_len < DP_MAX_MSGLEN) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dis->dreq_request.msg_type = request->msg_type;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dis->dreq_request.msg_len = request->msg_len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dis->dreq_request.msg_buf =
03831d35f7499c87d51205817c93e9a8d42c4baestevel dis->dreq_request_buf;
03831d35f7499c87d51205817c93e9a8d42c4baestevel bcopy(request->msg_buf,
03831d35f7499c87d51205817c93e9a8d42c4baestevel dis->dreq_request.msg_buf,
03831d35f7499c87d51205817c93e9a8d42c4baestevel request->msg_len);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dis->dreq_state = RMC_COMM_DREQ_ST_PROCESS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_signal(dis->dreq_sig_cv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * not enough space to hold the request
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = RCEREPTOOBIG;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(rcs, DAPI, (CE_CONT, "cannot get to send "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "request=%x (busy)\n", request->msg_type));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * only one request per time can be processed.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the thread is either busy (RMC_COMM_DREQ_ST_PROCESS)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * or terminating (RMC_COMM_DREQ_ST_EXIT)
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = RCEGENERIC;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(dis->dreq_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Function used to send a request and (eventually) wait for a response.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * It can be called from a leaf driver (via rmc_comm_request_response) or
03831d35f7499c87d51205817c93e9a8d42c4baestevel * from the thread in charge of sending 'no-wait' requests
03831d35f7499c87d51205817c93e9a8d42c4baestevel * (rmc_comm_send_pend_req).
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelrmc_comm_send_req_resp(struct rmc_comm_state *rcs, rmc_comm_msg_t *request,
03831d35f7499c87d51205817c93e9a8d42c4baestevel rmc_comm_msg_t *response, uint32_t wait_time)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel rmc_comm_dp_state_t *dps;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dp_req_resp_t *drr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dp_message_t *exp_resp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dp_message_t req;
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni clock_t resend_clockt, delta;
03831d35f7499c87d51205817c93e9a8d42c4baestevel clock_t stop_clockt;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int err;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * just a sanity check...
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (request == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(rcs, DAPI, (CE_CONT, "reqresp, invalid args\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (RCEINVARG);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * drivers cannot send control messages at all. They are meant to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * be used at low level only.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!IS_NUMBERED_MSG(request->msg_type)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(rcs, DAPI, (CE_CONT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "reqresp, ctrl msg not allowed! req type=%x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel request->msg_type));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (RCEINVARG);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dps = &rcs->dp_state;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drr = &dps->req_resp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel exp_resp = &drr->response;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
6fa6856ee31afb8f296ddb9f5201cfc9cc5ad729arutz /*
6fa6856ee31afb8f296ddb9f5201cfc9cc5ad729arutz * Handle the case where we are called during panic
6fa6856ee31afb8f296ddb9f5201cfc9cc5ad729arutz * processing. If that occurs, then another thread in
6fa6856ee31afb8f296ddb9f5201cfc9cc5ad729arutz * rmc_comm might have been idled by panic() while
6fa6856ee31afb8f296ddb9f5201cfc9cc5ad729arutz * holding dp_mutex. As a result, do not unconditionally
6fa6856ee31afb8f296ddb9f5201cfc9cc5ad729arutz * grab dp_mutex.
6fa6856ee31afb8f296ddb9f5201cfc9cc5ad729arutz */
6fa6856ee31afb8f296ddb9f5201cfc9cc5ad729arutz if (ddi_in_panic() != 0) {
6fa6856ee31afb8f296ddb9f5201cfc9cc5ad729arutz if (mutex_tryenter(dps->dp_mutex) == 0) {
6fa6856ee31afb8f296ddb9f5201cfc9cc5ad729arutz return (RCENODATALINK);
6fa6856ee31afb8f296ddb9f5201cfc9cc5ad729arutz }
6fa6856ee31afb8f296ddb9f5201cfc9cc5ad729arutz } else {
6fa6856ee31afb8f296ddb9f5201cfc9cc5ad729arutz mutex_enter(dps->dp_mutex);
6fa6856ee31afb8f296ddb9f5201cfc9cc5ad729arutz }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * if the data link set up is suspended, just return.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the only time that this can happen is during firmware download
03831d35f7499c87d51205817c93e9a8d42c4baestevel * (see rmc_comm_request_response_bp). Basically, the data link is
03831d35f7499c87d51205817c93e9a8d42c4baestevel * down and the timer for setting up the data link is not running.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!dps->data_link_ok &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel dps->timer_link_setup == (timeout_id_t)0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(dps->dp_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (RCENODATALINK);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(rcs, DAPI, (CE_CONT, "pending request=%d, req type=%x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel dps->pending_request, request->msg_type));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rmc_comm_wait_enable_to_send(rcs, dps);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We now have control of the RMC.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Place a lower limit on the shortest amount of time to be
03831d35f7499c87d51205817c93e9a8d42c4baestevel * waited before timing out while communicating with the RMC
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (wait_time < DP_MIN_TIMEOUT)
03831d35f7499c87d51205817c93e9a8d42c4baestevel wait_time = DP_MIN_TIMEOUT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel stop_clockt = ddi_get_lbolt() + drv_usectohz(wait_time * 1000);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * initialization of the request/response data structure
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel drr->flags = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drr->error_status = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * set the 'expected reply' buffer: get the buffer already allocated
03831d35f7499c87d51205817c93e9a8d42c4baestevel * for the response (if a reply is expected!)
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (response != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel exp_resp->msg_type = response->msg_type;
03831d35f7499c87d51205817c93e9a8d42c4baestevel exp_resp->msg_buf = (uint8_t *)response->msg_buf;
03831d35f7499c87d51205817c93e9a8d42c4baestevel exp_resp->msg_msglen = (uint16_t)response->msg_bytes;
03831d35f7499c87d51205817c93e9a8d42c4baestevel exp_resp->msg_bufsiz = (uint16_t)response->msg_len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel exp_resp->msg_type = DP_NULL_MSG;
03831d35f7499c87d51205817c93e9a8d42c4baestevel exp_resp->msg_buf = (uint8_t)NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel exp_resp->msg_bufsiz = (uint16_t)0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel exp_resp->msg_msglen = (uint16_t)0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * send the request message
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel req.msg_type = request->msg_type;
03831d35f7499c87d51205817c93e9a8d42c4baestevel req.msg_buf = (uint8_t *)request->msg_buf;
03831d35f7499c87d51205817c93e9a8d42c4baestevel req.msg_msglen = (uint16_t)request->msg_len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * send the message and wait for the reply or ACKnowledgment
03831d35f7499c87d51205817c93e9a8d42c4baestevel * re-send the message if reply/ACK is not received in the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * timeframe defined
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(rcs, DAPI, (CE_CONT, "send request=%x\n", request->msg_type));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni delta = drv_usectohz(TX_RETRY_TIME * 1000);
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni
03831d35f7499c87d51205817c93e9a8d42c4baestevel while ((err = rmc_comm_dp_msend(rcs, &req)) == RCNOERR) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni resend_clockt = ddi_get_lbolt() + delta;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * wait for a reply or an acknowledgement
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni (void) cv_reltimedwait(drr->cv_wait_reply, dps->dp_mutex,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni delta, TR_CLOCK_TICK);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(rcs, DAPI, (CE_CONT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "reqresp send status: flags=%02x req=%x resp=%x tick=%ld\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel drr->flags, request->msg_type,
03831d35f7499c87d51205817c93e9a8d42c4baestevel response ? response->msg_type : -1,
03831d35f7499c87d51205817c93e9a8d42c4baestevel stop_clockt - resend_clockt));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check for error condition first
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Then, check if the command has been replied/ACKed
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Then, check if it has timeout and if there is any
03831d35f7499c87d51205817c93e9a8d42c4baestevel * time left to resend the message.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((drr->flags & MSG_ERROR) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (drr->error_status == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = RCEGENERIC;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = drr->error_status;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (response != NULL &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel (drr->flags & MSG_REPLY_RXED) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * yes! here is the reply
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the actual length of the msg
03831d35f7499c87d51205817c93e9a8d42c4baestevel * a negative value means that the reply message
03831d35f7499c87d51205817c93e9a8d42c4baestevel * was too big for the receiver buffer
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel response->msg_bytes = exp_resp->msg_msglen;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (response->msg_bytes < 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = RCEREPTOOBIG;
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = RCNOERR;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (response == NULL && (drr->flags & MSG_ACKED) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * yes! message has been acknowledged
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = RCNOERR;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if ((stop_clockt - resend_clockt) <= 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * no more time left. set the error code,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * exit the loop
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = RCETIMEOUT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rmc_comm_dp_mcleanup(rcs);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rmc_comm_wake_up_next(rcs);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(dps->dp_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(rcs, DAPI, (CE_CONT, "reqresp end: err=%d, request=%x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel err, request->msg_type));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Function used to send a BP (Boot Prom) message and get the reply.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * BP protocol is provided only to support firmware download.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This function will look for the following key BP protocol commands:
03831d35f7499c87d51205817c93e9a8d42c4baestevel * BP_OBP_BOOTINIT: the data link is brought down so that request/response
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sessions cannot be started. The reason why is that this command will cause
03831d35f7499c87d51205817c93e9a8d42c4baestevel * RMC fw to jump to the boot monitor (BOOTMON_FLASH) and data protocol is not
03831d35f7499c87d51205817c93e9a8d42c4baestevel * operational. In this context, RMC fw will only be using the BP protocol.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * BP_OBP_RESET: data link setup timer is resumed. This command cause the RMC
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to reboot and hence become operational.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelrmc_comm_request_response_bp(rmc_comm_msg_t *request_bp,
03831d35f7499c87d51205817c93e9a8d42c4baestevel rmc_comm_msg_t *response_bp, uint32_t wait_time)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct rmc_comm_state *rcs;
03831d35f7499c87d51205817c93e9a8d42c4baestevel rmc_comm_dp_state_t *dps;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dp_req_resp_t *drr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dp_message_t *resp_bp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp_msg_t *bp_msg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel clock_t stop_clockt;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int err = RCNOERR;
03831d35f7499c87d51205817c93e9a8d42c4baestevel boolean_t bootinit_sent = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the soft state struct (instance 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((rcs = rmc_comm_getstate(NULL, 0,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni "rmc_comm_request_response_bp")) == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (RCENOSOFTSTATE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sanity check: request_bp buffer must always be provided
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (request_bp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(rcs, DAPI, (CE_CONT, "reqresp_bp, invalid args\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (RCEINVARG);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp_msg = (bp_msg_t *)request_bp->msg_buf;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(rcs, DAPI, (CE_CONT, "send request_bp=%x\n", bp_msg->cmd));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * only BP message can be sent
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!IS_BOOT_MSG(bp_msg->cmd)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(rcs, DAPI, (CE_CONT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "reqresp_bp, only BP msg are allowed! type=%x\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp_msg->cmd));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (RCEINVARG);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dps = &rcs->dp_state;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drr = &dps->req_resp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel resp_bp = &drr->response;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(dps->dp_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rmc_comm_wait_enable_to_send(rcs, dps);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Now, before sending the message, just check what it is being sent
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and take action accordingly.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * is it BP_OBP_BOOTINIT or BP_OBP_RESET command?
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (bp_msg->cmd == BP_OBP_BOOTINIT) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * bring down the protocol data link
03831d35f7499c87d51205817c93e9a8d42c4baestevel * (must be done before aborting a request/response session)
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel dps->data_link_ok = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dps->timer_link_setup = (timeout_id_t)0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel bootinit_sent = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (bp_msg->cmd == BP_OBP_RESET) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * restart the data link set up timer. RMC is coming up...
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dp_reset(rcs, INITIAL_SEQID, 0, 1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * initialization of the request/response data structure
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel drr->flags = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drr->error_status = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * set the reply buffer: get the buffer already allocated
03831d35f7499c87d51205817c93e9a8d42c4baestevel * for the response
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (response_bp != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(rcs, DAPI, (CE_CONT, "expect BP reply. len=%d\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel response_bp->msg_len));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel resp_bp->msg_buf = (uint8_t *)response_bp->msg_buf;
03831d35f7499c87d51205817c93e9a8d42c4baestevel resp_bp->msg_bufsiz = (uint16_t)response_bp->msg_len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * send the BP message and wait for the reply
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rmc_comm_bp_msend(rcs, bp_msg);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (response_bp != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * place a lower limit on the shortest amount of time to be
03831d35f7499c87d51205817c93e9a8d42c4baestevel * waited before timing out while communicating with the RMC
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (wait_time < DP_MIN_TIMEOUT)
03831d35f7499c87d51205817c93e9a8d42c4baestevel wait_time = DP_MIN_TIMEOUT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel stop_clockt = ddi_get_lbolt() + drv_usectohz(wait_time * 1000);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((err = rmc_comm_wait_bp_reply(rcs, dps, drr,
03831d35f7499c87d51205817c93e9a8d42c4baestevel stop_clockt)) == RCNOERR) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the actual length of the msg
03831d35f7499c87d51205817c93e9a8d42c4baestevel * a negative value means that the reply message
03831d35f7499c87d51205817c93e9a8d42c4baestevel * was too big for the receiver buffer
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel response_bp->msg_bytes = resp_bp->msg_msglen;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (response_bp->msg_bytes < 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = RCEREPTOOBIG;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (bootinit_sent) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * BOOTINIT cmd may fail. In this is the case,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the RMC is still operational. Hence, we
03831d35f7499c87d51205817c93e9a8d42c4baestevel * try (once) to set up the data link
03831d35f7499c87d51205817c93e9a8d42c4baestevel * protocol.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp_msg = (bp_msg_t *)response_bp->msg_buf;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (bp_msg->cmd == BP_RSC_BOOTFAIL &&
03831d35f7499c87d51205817c93e9a8d42c4baestevel bp_msg->dat1 == BP_DAT1_REJECTED) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) rmc_comm_dp_ctlsend(rcs,
03831d35f7499c87d51205817c93e9a8d42c4baestevel DP_CTL_START);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rmc_comm_dp_mcleanup(rcs);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rmc_comm_wake_up_next(rcs);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(dps->dp_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to register for an asynchronous (via soft interrupt) notification
03831d35f7499c87d51205817c93e9a8d42c4baestevel * of a message from the remote side (RMC)
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelrmc_comm_reg_intr(uint8_t msg_type, rmc_comm_intrfunc_t intr_handler,
03831d35f7499c87d51205817c93e9a8d42c4baestevel rmc_comm_msg_t *msgbuf, uint_t *state, kmutex_t *lock)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct rmc_comm_state *rcs;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dp_msg_intr_t *msgintr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int err = RCNOERR;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((rcs = rmc_comm_getstate(NULL, 0, "rmc_comm_reg_intr")) == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (RCENOSOFTSTATE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(rcs->dp_state.dp_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgintr = &rcs->dp_state.msg_intr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * lock is required. If it is not defined, the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * interrupt handler routine cannot be registered.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (lock == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(rcs->dp_state.dp_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (RCEINVARG);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * only one interrupt handler can be registered.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (msgintr->intr_handler == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_add_softintr(rcs->dip, DDI_SOFTINT_HIGH,
03831d35f7499c87d51205817c93e9a8d42c4baestevel &msgintr->intr_id, NULL, NULL, intr_handler,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (caddr_t)msgbuf) == DDI_SUCCESS) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgintr->intr_handler = intr_handler;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgintr->intr_lock = lock;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgintr->intr_state = state;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgintr->intr_msg_type = msg_type;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgintr->intr_arg = (caddr_t)msgbuf;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = RCECANTREGINTR;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = RCEALREADYREG;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(rcs->dp_state.dp_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * To unregister for asynchronous notifications
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelrmc_comm_unreg_intr(uint8_t msg_type, rmc_comm_intrfunc_t intr_handler)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct rmc_comm_state *rcs;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dp_msg_intr_t *msgintr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int err = RCNOERR;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((rcs = rmc_comm_getstate(NULL, 0, "rmc_comm_unreg_intr")) == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (RCENOSOFTSTATE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(rcs->dp_state.dp_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgintr = &rcs->dp_state.msg_intr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (msgintr->intr_handler != NULL &&
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni msgintr->intr_msg_type == msg_type &&
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni msgintr->intr_handler == intr_handler) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_remove_softintr(msgintr->intr_id);
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgintr->intr_handler = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgintr->intr_id = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgintr->intr_msg_type = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgintr->intr_arg = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgintr->intr_lock = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel msgintr->intr_state = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = RCEGENERIC;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(rcs->dp_state.dp_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * To send raw data (firmware s-records) down to the RMC.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * It is provided only to support firmware download.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelrmc_comm_send_srecord_bp(caddr_t buf, int buflen,
03831d35f7499c87d51205817c93e9a8d42c4baestevel rmc_comm_msg_t *response_bp, uint32_t wait_time)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct rmc_comm_state *rcs;
03831d35f7499c87d51205817c93e9a8d42c4baestevel rmc_comm_dp_state_t *dps;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dp_req_resp_t *drr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dp_message_t *resp_bp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel clock_t stop_clockt;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int err;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the soft state struct (instance 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((rcs = rmc_comm_getstate(NULL, 0,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni "rmc_comm_request_response_bp")) == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (RCENOSOFTSTATE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sanity check: response_bp buffer must always be provided
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (buf == NULL || response_bp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(rcs, DAPI, (CE_CONT, "send_srecord_bp,invalid args\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (RCEINVARG);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(rcs, DAPI, (CE_CONT, "send_srecord_bp, buflen=%d\n", buflen));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel dps = &rcs->dp_state;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drr = &dps->req_resp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel resp_bp = &drr->response;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(dps->dp_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rmc_comm_wait_enable_to_send(rcs, dps);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * initialization of the request/response data structure
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel drr->flags = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel drr->error_status = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * set the reply buffer: get the buffer already allocated
03831d35f7499c87d51205817c93e9a8d42c4baestevel * for the response
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel resp_bp->msg_buf = (uint8_t *)response_bp->msg_buf;
03831d35f7499c87d51205817c93e9a8d42c4baestevel resp_bp->msg_bufsiz = (uint16_t)response_bp->msg_len;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * send raw data (s-record) and wait for the reply (BP message)
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rmc_comm_bp_srecsend(rcs, (char *)buf, buflen);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * place a lower limit on the shortest amount of time to be
03831d35f7499c87d51205817c93e9a8d42c4baestevel * waited before timing out while communicating with the RMC
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (wait_time < DP_MIN_TIMEOUT)
03831d35f7499c87d51205817c93e9a8d42c4baestevel wait_time = DP_MIN_TIMEOUT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel stop_clockt = ddi_get_lbolt() + drv_usectohz(wait_time * 1000);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((err = rmc_comm_wait_bp_reply(rcs, dps, drr,
03831d35f7499c87d51205817c93e9a8d42c4baestevel stop_clockt)) == RCNOERR) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * get the actual length of the msg
03831d35f7499c87d51205817c93e9a8d42c4baestevel * a negative value means that the reply message
03831d35f7499c87d51205817c93e9a8d42c4baestevel * was too big for the receiver buffer
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel response_bp->msg_bytes = resp_bp->msg_msglen;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (response_bp->msg_bytes < 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = RCEREPTOOBIG;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rmc_comm_dp_mcleanup(rcs);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rmc_comm_wake_up_next(rcs);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(dps->dp_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * To wait for (any) BP message to be received.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * (dp_mutex must be held)
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelrmc_comm_wait_bp_reply(struct rmc_comm_state *rcs, rmc_comm_dp_state_t *dps,
03831d35f7499c87d51205817c93e9a8d42c4baestevel dp_req_resp_t *drr, clock_t stop_clockt)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel clock_t clockleft = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int err = RCNOERR;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel clockleft = cv_timedwait(drr->cv_wait_reply, dps->dp_mutex,
03831d35f7499c87d51205817c93e9a8d42c4baestevel stop_clockt);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(rcs, DAPI, (CE_CONT,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "reqresp_bp, send: flags=%02x, clktick left=%ld\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel drr->flags, clockleft));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check for error condition first.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Then, check if it has timeout.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Then, check if the command has been replied.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((drr->flags & MSG_ERROR) != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = RCEGENERIC;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (clockleft <= 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * timeout
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = RCETIMEOUT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if ((drr->flags & MSG_RXED_BP) == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = RCEGENERIC;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Wait for the pending_request flag to be cleared and acquire it for our
03831d35f7499c87d51205817c93e9a8d42c4baestevel * own use. The caller is then allowed to start a new request/response
03831d35f7499c87d51205817c93e9a8d42c4baestevel * session with the RMC.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Note that all send-receive actions to the RMC include a time-out, so
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the pending-request must eventually go away - even if the RMC is down.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Hence there is no need to timeout the wait action of this function.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * (dp_mutex must be held on entry).
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelrmc_comm_wait_enable_to_send(struct rmc_comm_state *rcs,
03831d35f7499c87d51205817c93e9a8d42c4baestevel rmc_comm_dp_state_t *dps)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(rcs, DAPI, (CE_CONT, "pending request=%d\n",
03831d35f7499c87d51205817c93e9a8d42c4baestevel dps->pending_request));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * A new message can actually grab the lock before the thread
03831d35f7499c87d51205817c93e9a8d42c4baestevel * that has just been signaled. Therefore, we need to double
03831d35f7499c87d51205817c93e9a8d42c4baestevel * check to make sure that pending_request is not already set
03831d35f7499c87d51205817c93e9a8d42c4baestevel * after we wake up.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Potentially this could mean starvation for certain unfortunate
03831d35f7499c87d51205817c93e9a8d42c4baestevel * threads that keep getting woken up and putting back to sleep.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * But the window of such contention is very small to begin with.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (dps->pending_request) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * just 'sit and wait' until there are no pending requests
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_wait(dps->cv_ok_to_send, dps->dp_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * now a request/response can be started. Set the flag so that nobody
03831d35f7499c87d51205817c93e9a8d42c4baestevel * else will be able to send anything.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel dps->pending_request = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * To wake up one of the threads (if any) waiting for starting a
03831d35f7499c87d51205817c93e9a8d42c4baestevel * request/response session.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * (dp_mutex must be held)
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelrmc_comm_wake_up_next(struct rmc_comm_state *rcs)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * wake up eventual waiting threads...
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rcs->dp_state.pending_request = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_signal(rcs->dp_state.cv_ok_to_send);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * thread which delivers pending request message to the rmc. Some leaf drivers
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cannot afford to wait for a request to be replied/ACKed. Hence, a request
03831d35f7499c87d51205817c93e9a8d42c4baestevel * message is stored temporarily in the state structure and this thread
03831d35f7499c87d51205817c93e9a8d42c4baestevel * gets woken up to deliver it.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelrmc_comm_send_pend_req(caddr_t arg)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct rmc_comm_state *rcs;
03831d35f7499c87d51205817c93e9a8d42c4baestevel rmc_comm_drvintf_state_t *dis;
03831d35f7499c87d51205817c93e9a8d42c4baestevel callb_cpr_t cprinfo;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (arg == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel thread_exit();
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* NOTREACHED */
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rcs = (struct rmc_comm_state *)arg;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dis = &rcs->drvi_state;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel CALLB_CPR_INIT(&cprinfo, dis->dreq_mutex, callb_generic_cpr,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "rmc_comm_send_pend_req");
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(dis->dreq_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (dis->dreq_state <= RMC_COMM_DREQ_ST_READY)
03831d35f7499c87d51205817c93e9a8d42c4baestevel dis->dreq_state = RMC_COMM_DREQ_ST_WAIT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (;;) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Wait for someone to tell me to continue.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (dis->dreq_state == RMC_COMM_DREQ_ST_WAIT) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel CALLB_CPR_SAFE_BEGIN(&cprinfo);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_wait(dis->dreq_sig_cv, dis->dreq_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel CALLB_CPR_SAFE_END(&cprinfo, dis->dreq_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* RMC_COMM_DREQ_ST_EXIT implies signal by _detach(). */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (dis->dreq_state == RMC_COMM_DREQ_ST_EXIT) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dis->dreq_state = RMC_COMM_DREQ_ST_NOTSTARTED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dis->dreq_tid = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* dis->dreq_mutex is held at this point! */
03831d35f7499c87d51205817c93e9a8d42c4baestevel CALLB_CPR_EXIT(&cprinfo);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel thread_exit();
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* NOTREACHED */
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(dis->dreq_state == RMC_COMM_DREQ_ST_PROCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(dis->dreq_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * deliver the request (and wait...)
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
52f4394b704526bb3aa41e8729fd03e754732822jfrank while (rmc_comm_send_req_resp(rcs, &dis->dreq_request, NULL,
52f4394b704526bb3aa41e8729fd03e754732822jfrank RMC_COMM_DREQ_DEFAULT_TIME) == RCEGENERIC) {
52f4394b704526bb3aa41e8729fd03e754732822jfrank }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(dis->dreq_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (dis->dreq_state != RMC_COMM_DREQ_ST_EXIT)
03831d35f7499c87d51205817c93e9a8d42c4baestevel dis->dreq_state = RMC_COMM_DREQ_ST_WAIT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * start thread to deal with pending requests to be delivered asynchronously
03831d35f7499c87d51205817c93e9a8d42c4baestevel * (i.e. leaf driver do not have to/cannot wait for a reply/ACk of a request)
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelrmc_comm_dreq_thread_start(struct rmc_comm_state *rcs)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel rmc_comm_drvintf_state_t *dis = &rcs->drvi_state;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int err = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel kthread_t *tp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(dis->dreq_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (dis->dreq_state == RMC_COMM_DREQ_ST_NOTSTARTED) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel tp = thread_create(NULL, 0, rmc_comm_send_pend_req,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (caddr_t)rcs, 0, &p0, TS_RUN, maxclsyspri);
03831d35f7499c87d51205817c93e9a8d42c4baestevel dis->dreq_state = RMC_COMM_DREQ_ST_READY;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dis->dreq_tid = tp->t_did;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(dis->dreq_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * stop the thread (to deliver pending request messages)
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelrmc_comm_dreq_thread_kill(struct rmc_comm_state *rcs)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel rmc_comm_drvintf_state_t *dis = &rcs->drvi_state;
03831d35f7499c87d51205817c93e9a8d42c4baestevel kt_did_t tid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(dis->dreq_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel tid = dis->dreq_tid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (tid != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel dis->dreq_state = RMC_COMM_DREQ_ST_EXIT;
03831d35f7499c87d51205817c93e9a8d42c4baestevel dis->dreq_tid = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_signal(dis->dreq_sig_cv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(dis->dreq_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Wait for rmc_comm_send_pend_req() to finish
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (tid != 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel thread_join(tid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * init function - start thread to deal with pending requests (no-wait requests)
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelrmc_comm_drvintf_init(struct rmc_comm_state *rcs)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int err = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(rcs, DGEN, (CE_CONT, "rmc_comm_drvintf_init\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel rcs->drvi_state.dreq_state = RMC_COMM_DREQ_ST_NOTSTARTED;
03831d35f7499c87d51205817c93e9a8d42c4baestevel rcs->drvi_state.dreq_tid = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_init(rcs->drvi_state.dreq_mutex, NULL, MUTEX_DRIVER, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_init(rcs->drvi_state.dreq_sig_cv, NULL, CV_DRIVER, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel err = rmc_comm_dreq_thread_start(rcs);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (err != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_destroy(rcs->drvi_state.dreq_sig_cv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_destroy(rcs->drvi_state.dreq_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(rcs, DGEN, (CE_CONT, "thread started? err=%d\n", err));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * fini function - kill thread to deal with pending requests (no-wait requests)
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelrmc_comm_drvintf_fini(struct rmc_comm_state *rcs)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(rcs, DGEN, (CE_CONT, "rmc_comm_drvintf_fini:stop thread\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rmc_comm_dreq_thread_kill(rcs);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel DPRINTF(rcs, DGEN, (CE_CONT, "rmc_comm_drvintf_fini:destroy Mx/CVs\n"));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cv_destroy(rcs->drvi_state.dreq_sig_cv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_destroy(rcs->drvi_state.dreq_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}