30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * CDDL HEADER START
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen *
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * The contents of this file are subject to the terms of the
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Common Development and Distribution License (the "License").
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * You may not use this file except in compliance with the License.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen *
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * or http://www.opensolaris.org/os/licensing.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * See the License for the specific language governing permissions
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * and limitations under the License.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen *
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * When distributing Covered Code, include this CDDL HEADER in each
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * If applicable, add the following below this CDDL HEADER, with the
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * fields enclosed by brackets "[]" replaced with your own identifying
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * information: Portions Copyright [yyyy] [name of copyright owner]
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen *
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * CDDL HEADER END
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/*
e9406929914976efdccb875f94e90e85cdb076e3Mike Christensen * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Domain Services Module Common Code.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen *
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * This module is intended to be used by both Solaris and the VBSC
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * module.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#include <sys/modctl.h>
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#include <sys/ksynch.h>
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#include <sys/taskq.h>
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#include <sys/disp.h>
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#include <sys/cmn_err.h>
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#include <sys/note.h>
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#include <sys/mach_descrip.h>
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#include <sys/mdesc.h>
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#include <sys/ldc.h>
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#include <sys/ds.h>
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#include <sys/ds_impl.h>
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#ifndef MIN
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#define MIN(a, b) ((a) < (b) ? (a) : (b))
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#endif
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#define DS_DECODE_BUF_LEN 30
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * All DS ports in the system
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen *
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * The list of DS ports is read in from the MD when the DS module is
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * initialized and is never modified. This eliminates the need for
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * locking to access the port array itself. Access to the individual
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * ports are synchronized at the port level.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_port_t ds_ports[DS_MAX_PORTS];
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_portset_t ds_allports; /* all DS ports in the system */
3ef557bf6acbaf0905479800b87d010f8715a11eMike Christensends_portset_t ds_nullport; /* allows test against null portset */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
40c61268017ed628fcfb89162250c59130d14824Mike Christensen/* DS SP port id */
40c61268017ed628fcfb89162250c59130d14824Mike Christensenuint64_t ds_sp_port_id = DS_PORTID_INVALID;
40c61268017ed628fcfb89162250c59130d14824Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Table of registered services
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen *
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Locking: Accesses to the table of services are synchronized using
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * a mutex lock. The reader lock must be held when looking up service
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * information in the table. The writer lock must be held when any
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * service information is being modified.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_svcs_t ds_svcs;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Flag to prevent callbacks while in the middle of DS teardown.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenboolean_t ds_enabled = B_FALSE; /* enable/disable taskq processing */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Retry count and delay for LDC reads and writes
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#ifndef DS_DEFAULT_RETRIES
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#define DS_DEFAULT_RETRIES 10000 /* number of times to retry */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#endif
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#ifndef DS_DEFAULT_DELAY
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#define DS_DEFAULT_DELAY 1000 /* usecs to wait between retries */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#endif
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic int ds_retries = DS_DEFAULT_RETRIES;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic clock_t ds_delay = DS_DEFAULT_DELAY;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Supported versions of the DS message protocol
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen *
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * The version array must be sorted in order from the highest
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * supported version to the lowest. Support for a particular
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * <major>.<minor> version implies all lower minor versions of
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * that same major version are supported as well.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic ds_ver_t ds_vers[] = { { 1, 0 } };
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#define DS_NUM_VER (sizeof (ds_vers) / sizeof (ds_vers[0]))
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/* incoming message handling functions */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensentypedef void (*ds_msg_handler_t)(ds_port_t *port, caddr_t buf, size_t len);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void ds_handle_init_req(ds_port_t *port, caddr_t buf, size_t len);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void ds_handle_init_ack(ds_port_t *port, caddr_t buf, size_t len);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void ds_handle_init_nack(ds_port_t *port, caddr_t buf, size_t len);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void ds_handle_reg_req(ds_port_t *port, caddr_t buf, size_t len);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void ds_handle_reg_ack(ds_port_t *port, caddr_t buf, size_t len);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void ds_handle_reg_nack(ds_port_t *port, caddr_t buf, size_t len);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void ds_handle_unreg_req(ds_port_t *port, caddr_t buf, size_t len);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void ds_handle_unreg_ack(ds_port_t *port, caddr_t buf, size_t len);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void ds_handle_unreg_nack(ds_port_t *port, caddr_t buf, size_t len);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void ds_handle_data(ds_port_t *port, caddr_t buf, size_t len);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void ds_handle_nack(ds_port_t *port, caddr_t buf, size_t len);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * DS Message Handler Dispatch Table
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen *
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * A table used to dispatch all incoming messages. This table
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * contains handlers for all the fixed message types, as well as
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * the the messages defined in the 1.0 version of the DS protocol.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * The handlers are indexed based on the DS header msg_type values
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic const ds_msg_handler_t ds_msg_handlers[] = {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_handle_init_req, /* DS_INIT_REQ */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_handle_init_ack, /* DS_INIT_ACK */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_handle_init_nack, /* DS_INIT_NACK */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_handle_reg_req, /* DS_REG_REQ */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_handle_reg_ack, /* DS_REG_ACK */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_handle_reg_nack, /* DS_REG_NACK */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_handle_unreg_req, /* DS_UNREG */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_handle_unreg_ack, /* DS_UNREG_ACK */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_handle_unreg_nack, /* DS_UNREG_NACK */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_handle_data, /* DS_DATA */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_handle_nack /* DS_NACK */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen};
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/* initialization functions */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic int ds_ldc_init(ds_port_t *port);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/* event processing functions */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic uint_t ds_ldc_cb(uint64_t event, caddr_t arg);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic int ds_recv_msg(ds_port_t *port, caddr_t msgp, size_t *sizep);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void ds_handle_up_event(ds_port_t *port);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void ds_handle_down_reset_events(ds_port_t *port);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void ds_handle_recv(void *arg);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void ds_dispatch_event(void *arg);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/* message sending functions */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic int ds_send_msg(ds_port_t *port, caddr_t msg, size_t msglen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic int ds_send_reg_req(ds_svc_t *svc, ds_port_t *port);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void ds_send_unreg_nack(ds_port_t *port, ds_svc_hdl_t bad_hdl);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void ds_send_data_nack(ds_port_t *port, ds_svc_hdl_t bad_hdl);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/* walker functions */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic int ds_svc_isfree(ds_svc_t *svc, void *arg);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic int ds_svc_unregister(ds_svc_t *svc, void *arg);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic int ds_svc_port_up(ds_svc_t *svc, void *arg);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/* service utilities */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void ds_reset_svc(ds_svc_t *svc, ds_port_t *port);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic int ds_svc_register_onport(ds_svc_t *svc, ds_port_t *port);
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensenstatic int ds_svc_register_onport_walker(ds_svc_t *svc, void *arg);
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensenstatic void ds_set_port_ready(ds_port_t *port, uint16_t major, uint16_t minor);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/* port utilities */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void ds_port_reset(ds_port_t *port);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic ldc_status_t ds_update_ldc_state(ds_port_t *port);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/* misc utilities */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void min_max_versions(int num_versions, ds_ver_t *sup_versionsp,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen uint16_t *min_major, uint16_t *max_major);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/* debug */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic char *decode_ldc_events(uint64_t event, char *buf);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/* loopback */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void ds_loopback_register(ds_svc_hdl_t hdl);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void ds_loopback_unregister(ds_svc_hdl_t hdl);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void ds_loopback_send(ds_svc_hdl_t hdl, void *buf, size_t buflen);
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensenstatic int ds_loopback_set_svc(ds_svc_t *svc, ds_capability_t *cap,
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen ds_svc_hdl_t *lb_hdlp);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/* client handling */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic int i_ds_hdl_lookup(char *service, uint_t is_client, ds_svc_hdl_t *hdlp,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen uint_t maxhdls);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic ds_svc_t *ds_find_clnt_svc_by_hdl_port(ds_svc_hdl_t hdl,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_port_t *port);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic ds_svc_t *ds_find_svc_by_id_port(char *svc_id, int is_client,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_port_t *port);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic ds_svc_t *ds_svc_clone(ds_svc_t *svc);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void ds_check_for_dup_services(ds_svc_t *svc);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void ds_delete_svc_entry(ds_svc_t *svc);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenchar *
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_strdup(char *str)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen char *newstr;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen newstr = DS_MALLOC(strlen(str) + 1);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (void) strcpy(newstr, str);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (newstr);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenvoid
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_common_init(void)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* Validate version table */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ASSERT(ds_vers_isvalid(ds_vers, DS_NUM_VER) == DS_VERS_OK);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* Initialize services table */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_init_svcs_tbl(DS_MAXSVCS_INIT);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* enable callback processing */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_enabled = B_TRUE;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/* BEGIN LDC SUPPORT FUNCTIONS */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic char *
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensendecode_ldc_events(uint64_t event, char *buf)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen buf[0] = 0;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (event & LDC_EVT_DOWN) (void) strcat(buf, " DOWN");
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (event & LDC_EVT_RESET) (void) strcat(buf, " RESET");
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (event & LDC_EVT_UP) (void) strcat(buf, " UP");
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (event & LDC_EVT_READ) (void) strcat(buf, " READ");
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (event & LDC_EVT_WRITE) (void) strcat(buf, " WRITE");
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (buf);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic ldc_status_t
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_update_ldc_state(ds_port_t *port)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ldc_status_t ldc_state;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen int rv;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen char ebuf[DS_EBUFSIZE];
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ASSERT(MUTEX_HELD(&port->lock));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Read status and update ldc state info in port structure.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((rv = ldc_status(port->ldc.hdl, &ldc_state)) != 0) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_WARN, "ds@%lx: %s: ldc_status error: %s" DS_EOL,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen PORTID(port), __func__, ds_errno_to_str(rv, ebuf));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ldc_state = port->ldc.state;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen } else {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen port->ldc.state = ldc_state;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (ldc_state);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_handle_down_reset_events(ds_port_t *port)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_LDC(CE_NOTE, "ds@%lx: %s: entered" DS_EOL, PORTID(port),
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen __func__);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_enter(&ds_svcs.lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_enter(&port->lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_sys_drain_events(port);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (void) ds_update_ldc_state(port);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* reset the port state */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_port_reset(port);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* acknowledge the reset */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (void) ldc_up(port->ldc.hdl);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&port->lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&ds_svcs.lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_handle_up_event(port);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_LDC(CE_NOTE, "ds@%lx: %s: exit" DS_EOL, PORTID(port), __func__);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_handle_up_event(ds_port_t *port)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ldc_status_t ldc_state;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_LDC(CE_NOTE, "ds@%lx: %s: entered" DS_EOL, PORTID(port),
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen __func__);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_enter(&port->lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ldc_state = ds_update_ldc_state(port);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&port->lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((ldc_state == LDC_UP) && IS_DS_PORT(port)) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Initiate the handshake.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_send_init_req(port);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_LDC(CE_NOTE, "ds@%lx: %s: exit" DS_EOL, PORTID(port), __func__);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic uint_t
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_ldc_cb(uint64_t event, caddr_t arg)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_port_t *port = (ds_port_t *)arg;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen char evstring[DS_DECODE_BUF_LEN];
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_LDC(CE_NOTE, "ds@%lx: %s: %s event (%llx) received" DS_EOL,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen PORTID(port), __func__, decode_ldc_events(event, evstring),
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (u_longlong_t)event);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (!ds_enabled) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_LDC(CE_NOTE, "ds@%lx: %s: callback handling is disabled"
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_EOL, PORTID(port), __func__);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (LDC_SUCCESS);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (event & (LDC_EVT_DOWN | LDC_EVT_RESET)) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_handle_down_reset_events(port);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen goto done;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (event & LDC_EVT_UP) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_handle_up_event(port);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (event & LDC_EVT_READ) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (port->ldc.state != LDC_UP) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_WARN, "ds@%lx: %s: LDC READ event while "
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen "port not up" DS_EOL, PORTID(port), __func__);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen goto done;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (ds_sys_dispatch_func(ds_handle_recv, port)) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_WARN, "ds@%lx: error initiating LDC READ "
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen " event", PORTID(port));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (event & LDC_EVT_WRITE) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_LDC(CE_NOTE, "ds@%lx: %s: LDC WRITE event received, "
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen "not supported" DS_EOL, PORTID(port), __func__);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (event & ~(LDC_EVT_UP | LDC_EVT_READ)) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_WARN, "ds@%lx: %s: Unexpected LDC event received: "
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen "0x%llx" DS_EOL, PORTID(port), __func__,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (u_longlong_t)event);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensendone:
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_LDC(CE_NOTE, "ds@%lx: %s: exit" DS_EOL, PORTID(port), __func__);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (LDC_SUCCESS);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic int
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_ldc_init(ds_port_t *port)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen int rv;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ldc_attr_t ldc_attr;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen caddr_t ldc_cb_arg = (caddr_t)port;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen char ebuf[DS_EBUFSIZE];
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ASSERT(MUTEX_HELD(&port->lock));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_LDC(CE_NOTE, "ds@%lx: %s: ldc_id=%lld" DS_EOL,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen PORTID(port), __func__, (u_longlong_t)port->ldc.id);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ldc_attr.devclass = LDC_DEV_GENERIC;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ldc_attr.instance = 0;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ldc_attr.mode = LDC_MODE_RELIABLE;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ldc_attr.mtu = DS_STREAM_MTU;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((rv = ldc_init(port->ldc.id, &ldc_attr, &port->ldc.hdl)) != 0) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_WARN, "ds@%lx: %s: ldc_id: %lx, ldc_init error: %s"
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_EOL, PORTID(port), __func__, port->ldc.id,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_errno_to_str(rv, ebuf));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (rv);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen rv = ldc_reg_callback(port->ldc.hdl, ds_ldc_cb, ldc_cb_arg);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (rv != 0) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_WARN, "ds@%lx: %s: ldc_reg_callback error: %s"
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_EOL, PORTID(port), __func__, ds_errno_to_str(rv, ebuf));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (rv);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_sys_ldc_init(port);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (0);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenint
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_ldc_fini(ds_port_t *port)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen int rv;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen char ebuf[DS_EBUFSIZE];
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ASSERT(port->state >= DS_PORT_LDC_INIT);
beba1dd881728e806abb8621851ae851da168a08Mike Christensen ASSERT(MUTEX_HELD(&port->lock));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_LDC(CE_NOTE, "ds@%lx: %s: ldc_id=%ld" DS_EOL, PORTID(port),
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen __func__, port->ldc.id);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((rv = ldc_close(port->ldc.hdl)) != 0) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_WARN, "ds@%lx: %s: ldc_close error: %s" DS_EOL,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen PORTID(port), __func__, ds_errno_to_str(rv, ebuf));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (rv);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((rv = ldc_unreg_callback(port->ldc.hdl)) != 0) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_WARN, "ds@%lx: %s: ldc_unreg_callback error: %s"
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_EOL, PORTID(port), __func__, ds_errno_to_str(rv, ebuf));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (rv);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((rv = ldc_fini(port->ldc.hdl)) != 0) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_WARN, "ds@%lx: %s: ldc_fini error: %s" DS_EOL,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen PORTID(port), __func__, ds_errno_to_str(rv, ebuf));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (rv);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
beba1dd881728e806abb8621851ae851da168a08Mike Christensen port->ldc.id = (uint64_t)-1;
beba1dd881728e806abb8621851ae851da168a08Mike Christensen port->ldc.hdl = NULL;
beba1dd881728e806abb8621851ae851da168a08Mike Christensen port->ldc.state = 0;
beba1dd881728e806abb8621851ae851da168a08Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (rv);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Attempt to read a specified number of bytes from a particular LDC.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Returns zero for success or the return code from the LDC read on
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * failure. The actual number of bytes read from the LDC is returned
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * in the size parameter.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic int
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_recv_msg(ds_port_t *port, caddr_t msgp, size_t *sizep)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen int rv = 0;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen size_t bytes_req = *sizep;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen size_t bytes_left = bytes_req;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen size_t nbytes;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen int retry_count = 0;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen char ebuf[DS_EBUFSIZE];
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ASSERT(MUTEX_HELD(&port->rcv_lock));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen *sizep = 0;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_LDC(CE_NOTE, "ds@%lx: attempting to read %ld bytes" DS_EOL,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen PORTID(port), bytes_req);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen while (bytes_left > 0) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen nbytes = bytes_left;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
beba1dd881728e806abb8621851ae851da168a08Mike Christensen mutex_enter(&port->lock);
beba1dd881728e806abb8621851ae851da168a08Mike Christensen if (port->ldc.state == LDC_UP) {
beba1dd881728e806abb8621851ae851da168a08Mike Christensen rv = ldc_read(port->ldc.hdl, msgp, &nbytes);
beba1dd881728e806abb8621851ae851da168a08Mike Christensen } else
beba1dd881728e806abb8621851ae851da168a08Mike Christensen rv = ENXIO;
beba1dd881728e806abb8621851ae851da168a08Mike Christensen mutex_exit(&port->lock);
beba1dd881728e806abb8621851ae851da168a08Mike Christensen if (rv != 0) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (rv == ECONNRESET) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen break;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen } else if (rv != EAGAIN) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_NOTE, "ds@%lx: %s: %s" DS_EOL,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen PORTID(port), __func__,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_errno_to_str(rv, ebuf));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen break;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen } else {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (nbytes != 0) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_LDC(CE_NOTE, "ds@%lx: "
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen "read %ld bytes, %d retries" DS_EOL,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen PORTID(port), nbytes, retry_count);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen *sizep += nbytes;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen msgp += nbytes;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen bytes_left -= nbytes;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* reset counter on a successful read */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen retry_count = 0;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen continue;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * No data was read. Check if this is the
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * first attempt. If so, just return since
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * nothing has been read yet.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (bytes_left == bytes_req) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_LDC(CE_NOTE, "ds@%lx: read zero bytes, "
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen " no data available" DS_EOL, PORTID(port));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen break;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * A retry is necessary because the read returned
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * EAGAIN, or a zero length read occurred after
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * reading a partial message.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (retry_count++ >= ds_retries) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_LDC(CE_NOTE, "ds@%lx: timed out waiting for "
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen "message" DS_EOL, PORTID(port));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen break;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen drv_usecwait(ds_delay);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (rv);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_handle_recv(void *arg)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_port_t *port = (ds_port_t *)arg;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen char *hbuf;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen size_t msglen;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen size_t read_size;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen boolean_t hasdata;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_hdr_t hdr;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen uint8_t *msg;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen char *currp;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen int rv;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_event_t *devent;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_LDC(CE_NOTE, "ds@%lx: %s..." DS_EOL, PORTID(port), __func__);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Read messages from the channel until there are none
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * pending. Valid messages are dispatched to be handled
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * by a separate thread while any malformed messages are
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * dropped.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_enter(&port->rcv_lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
beba1dd881728e806abb8621851ae851da168a08Mike Christensen for (;;) {
beba1dd881728e806abb8621851ae851da168a08Mike Christensen mutex_enter(&port->lock);
beba1dd881728e806abb8621851ae851da168a08Mike Christensen if (port->ldc.state == LDC_UP) {
beba1dd881728e806abb8621851ae851da168a08Mike Christensen rv = ldc_chkq(port->ldc.hdl, &hasdata);
beba1dd881728e806abb8621851ae851da168a08Mike Christensen } else
beba1dd881728e806abb8621851ae851da168a08Mike Christensen rv = ENXIO;
beba1dd881728e806abb8621851ae851da168a08Mike Christensen mutex_exit(&port->lock);
beba1dd881728e806abb8621851ae851da168a08Mike Christensen if (rv != 0 || !hasdata)
beba1dd881728e806abb8621851ae851da168a08Mike Christensen break;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG(CE_NOTE, "ds@%lx: %s: reading next message" DS_EOL,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen PORTID(port), __func__);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Read in the next message.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen hbuf = (char *)&hdr;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen bzero(hbuf, DS_HDR_SZ);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen read_size = DS_HDR_SZ;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen currp = hbuf;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* read in the message header */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((rv = ds_recv_msg(port, currp, &read_size)) != 0) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen break;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (read_size < DS_HDR_SZ) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * A zero length read is a valid signal that
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * there is no data left on the channel.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (read_size != 0) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_WARN, "ds@%lx: invalid message "
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen "length, received %ld bytes, expected %ld"
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_EOL, PORTID(port), read_size, DS_HDR_SZ);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen continue;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* get payload size and allocate a buffer */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen read_size = ((ds_hdr_t *)hbuf)->payload_len;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen msglen = DS_HDR_SZ + read_size;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen msg = DS_MALLOC(msglen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (!msg) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_WARN, "Memory allocation failed attempting "
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen " to allocate %d bytes." DS_EOL, (int)msglen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen continue;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG(CE_NOTE, "ds@%lx: %s: message payload len %d" DS_EOL,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen PORTID(port), __func__, (int)read_size);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* move message header into buffer */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (void) memcpy(msg, hbuf, DS_HDR_SZ);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen currp = (char *)(msg) + DS_HDR_SZ;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* read in the message body */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((rv = ds_recv_msg(port, currp, &read_size)) != 0) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_FREE(msg, msglen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen break;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* validate the size of the message */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((DS_HDR_SZ + read_size) != msglen) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_WARN, "ds@%lx: %s: invalid message length, "
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen "received %ld bytes, expected %ld" DS_EOL,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen PORTID(port), __func__, (DS_HDR_SZ + read_size),
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen msglen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_FREE(msg, msglen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen continue;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DUMP_MSG(DS_DBG_FLAG_LDC, msg, msglen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Send the message for processing, and store it
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * in the log. The memory is deallocated only when
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * the message is removed from the log.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen devent = DS_MALLOC(sizeof (ds_event_t));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen devent->port = port;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen devent->buf = (char *)msg;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen devent->buflen = msglen;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* log the message */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (void) ds_log_add_msg(DS_LOG_IN(port->id), msg, msglen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (ds_sys_dispatch_func(ds_dispatch_event, devent)) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_WARN, "ds@%lx: error initiating "
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen "event handler", PORTID(port));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_FREE(devent, sizeof (ds_event_t));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&port->rcv_lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* handle connection reset errors returned from ds_recv_msg */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (rv == ECONNRESET) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_handle_down_reset_events(port);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_LDC(CE_NOTE, "ds@%lx: %s done" DS_EOL, PORTID(port), __func__);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_dispatch_event(void *arg)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_event_t *event = (ds_event_t *)arg;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_hdr_t *hdr;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_port_t *port;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen port = event->port;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen hdr = (ds_hdr_t *)event->buf;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (DS_MSG_TYPE_VALID(hdr->msg_type)) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG(CE_NOTE, "ds@%lx: dispatch_event: msg_type=%d" DS_EOL,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen PORTID(port), hdr->msg_type);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (*ds_msg_handlers[hdr->msg_type])(port, event->buf,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen event->buflen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen } else {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_WARN, "ds@%lx: dispatch_event: invalid msg "
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen "type (%d)" DS_EOL, PORTID(port), hdr->msg_type);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_FREE(event->buf, event->buflen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_FREE(event, sizeof (ds_event_t));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenint
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_send_msg(ds_port_t *port, caddr_t msg, size_t msglen)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen int rv;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen caddr_t currp = msg;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen size_t amt_left = msglen;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen int loopcnt = 0;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_LDC(CE_NOTE, "ds@%lx: %s msglen: %ld" DS_EOL, PORTID(port),
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen __func__, msglen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DUMP_MSG(DS_DBG_FLAG_LDC, msg, msglen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen (void) ds_log_add_msg(DS_LOG_OUT(port->id), (uint8_t *)msg, msglen);
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Ensure that no other messages can be sent on this port by holding
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * the tx_lock mutex in case the write doesn't get sent with one write.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * This guarantees that the message doesn't become fragmented.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_enter(&port->tx_lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen do {
beba1dd881728e806abb8621851ae851da168a08Mike Christensen mutex_enter(&port->lock);
beba1dd881728e806abb8621851ae851da168a08Mike Christensen if (port->ldc.state == LDC_UP) {
beba1dd881728e806abb8621851ae851da168a08Mike Christensen rv = ldc_write(port->ldc.hdl, currp, &msglen);
beba1dd881728e806abb8621851ae851da168a08Mike Christensen } else
beba1dd881728e806abb8621851ae851da168a08Mike Christensen rv = ENXIO;
beba1dd881728e806abb8621851ae851da168a08Mike Christensen mutex_exit(&port->lock);
beba1dd881728e806abb8621851ae851da168a08Mike Christensen if (rv != 0) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (rv == ECONNRESET) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&port->tx_lock);
da42b56a9a91df0c475186f2afad543f96a05019Mike Christensen (void) ds_sys_dispatch_func((void (*)(void *))
da42b56a9a91df0c475186f2afad543f96a05019Mike Christensen ds_handle_down_reset_events, port);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (rv);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen } else if ((rv == EWOULDBLOCK) &&
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (loopcnt++ < ds_retries)) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen drv_usecwait(ds_delay);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen } else {
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen DS_DBG_PRCL(CE_NOTE, "ds@%lx: send_msg: "
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen "ldc_write failed (%d), %d bytes "
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen "remaining" DS_EOL, PORTID(port), rv,
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen (int)amt_left);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen goto error;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen } else {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen amt_left -= msglen;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen currp += msglen;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen msglen = amt_left;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen loopcnt = 0;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen } while (amt_left > 0);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenerror:
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&port->tx_lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (rv);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/* END LDC SUPPORT FUNCTIONS */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/* BEGIN DS PROTOCOL SUPPORT FUNCTIONS */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_handle_init_req(ds_port_t *port, caddr_t buf, size_t len)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_hdr_t *hdr;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_init_ack_t *ack;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_init_nack_t *nack;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen char *msg;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen size_t msglen;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_init_req_t *req;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen size_t explen = DS_MSG_LEN(ds_init_req_t);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen uint16_t new_major;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen uint16_t new_minor;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen boolean_t match;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* sanity check the incoming message */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (len != explen) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_WARN, "ds@%lx: <init_req: invalid message "
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen "length (%ld), expected %ld" DS_EOL, PORTID(port), len,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen explen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen req = (ds_init_req_t *)(buf + DS_HDR_SZ);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_PRCL(CE_NOTE, "ds@%lx: <init_req: ver=%d.%d" DS_EOL,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen PORTID(port), req->major_vers, req->minor_vers);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen match = negotiate_version(DS_NUM_VER, &ds_vers[0],
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen req->major_vers, &new_major, &new_minor);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Check version info. ACK only if the major numbers exactly
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * match. The service entity can retry with a new minor
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * based on the response sent as part of the NACK.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (match) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen msglen = DS_MSG_LEN(ds_init_ack_t);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen msg = DS_MALLOC(msglen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen hdr = (ds_hdr_t *)msg;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen hdr->msg_type = DS_INIT_ACK;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen hdr->payload_len = sizeof (ds_init_ack_t);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ack = (ds_init_ack_t *)(msg + DS_HDR_SZ);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ack->minor_vers = MIN(new_minor, req->minor_vers);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_PRCL(CE_NOTE, "ds@%lx: init_ack>: minor=0x%04X" DS_EOL,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen PORTID(port), MIN(new_minor, req->minor_vers));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen } else {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen msglen = DS_MSG_LEN(ds_init_nack_t);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen msg = DS_MALLOC(msglen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen hdr = (ds_hdr_t *)msg;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen hdr->msg_type = DS_INIT_NACK;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen hdr->payload_len = sizeof (ds_init_nack_t);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen nack = (ds_init_nack_t *)(msg + DS_HDR_SZ);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen nack->major_vers = new_major;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_PRCL(CE_NOTE, "ds@%lx: init_nack>: major=0x%04X" DS_EOL,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen PORTID(port), new_major);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Send the response
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (void) ds_send_msg(port, msg, msglen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_FREE(msg, msglen);
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen if (match) {
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen ds_set_port_ready(port, req->major_vers, ack->minor_vers);
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_handle_init_ack(ds_port_t *port, caddr_t buf, size_t len)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_init_ack_t *ack;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_ver_t *ver;
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen uint16_t major;
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen uint16_t minor;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen size_t explen = DS_MSG_LEN(ds_init_ack_t);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* sanity check the incoming message */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (len != explen) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_WARN, "ds@%lx: <init_ack: invalid message "
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen "length (%ld), expected %ld" DS_EOL, PORTID(port), len,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen explen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ack = (ds_init_ack_t *)(buf + DS_HDR_SZ);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_enter(&port->lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen if (port->state == DS_PORT_READY) {
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen DS_DBG_PRCL(CE_NOTE, "ds@%lx: <init_ack: port ready" DS_EOL,
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen PORTID(port));
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen mutex_exit(&port->lock);
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen return;
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen }
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (port->state != DS_PORT_INIT_REQ) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_PRCL(CE_NOTE, "ds@%lx: <init_ack: invalid state: %d"
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_EOL, PORTID(port), port->state);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&port->lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ver = &(ds_vers[port->ver_idx]);
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen major = ver->major;
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen minor = MIN(ver->minor, ack->minor_vers);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&port->lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen DS_DBG_PRCL(CE_NOTE, "ds@%lx: <init_ack: port ready v%d.%d" DS_EOL,
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen PORTID(port), major, minor);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen ds_set_port_ready(port, major, minor);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_handle_init_nack(ds_port_t *port, caddr_t buf, size_t len)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen int idx;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_init_nack_t *nack;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_ver_t *ver;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen size_t explen = DS_MSG_LEN(ds_init_nack_t);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* sanity check the incoming message */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (len != explen) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_PRCL(CE_WARN, "ds@%lx: <init_nack: invalid message "
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen "length (%ld), expected %ld" DS_EOL, PORTID(port), len,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen explen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen nack = (ds_init_nack_t *)(buf + DS_HDR_SZ);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_enter(&port->lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (port->state != DS_PORT_INIT_REQ) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_PRCL(CE_NOTE, "ds@%lx: <init_nack: invalid state: %d"
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_EOL, PORTID(port), port->state);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&port->lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ver = &(ds_vers[port->ver_idx]);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_PRCL(CE_NOTE, "ds@%lx: <init_nack: req=v%d.%d, nack=v%d.x"
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_EOL, PORTID(port), ver->major, ver->minor, nack->major_vers);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (nack->major_vers == 0) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* no supported protocol version */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_PRCL(CE_WARN, "ds@%lx: <init_nack: DS not supported"
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_EOL, PORTID(port));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&port->lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Walk the version list, looking for a major version
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * that is as close to the requested major version as
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * possible.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen for (idx = port->ver_idx; idx < DS_NUM_VER; idx++) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (ds_vers[idx].major <= nack->major_vers) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* found a version to try */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen goto done;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (idx == DS_NUM_VER) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* no supported version */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_PRCL(CE_WARN, "ds@%lx: <init_nack: DS v%d.x not "
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen "supported" DS_EOL, PORTID(port), nack->major_vers);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&port->lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensendone:
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* start the handshake again */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen port->ver_idx = idx;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen port->state = DS_PORT_LDC_INIT;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&port->lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_send_init_req(port);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic ds_svc_t *
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_find_svc_by_id_port(char *svc_id, int is_client, ds_port_t *port)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen int idx;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_svc_t *svc, *found_svc = 0;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen uint32_t flag_match = is_client ? DSSF_ISCLIENT : 0;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ASSERT(MUTEX_HELD(&ds_svcs.lock));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* walk every table entry */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen for (idx = 0; idx < ds_svcs.maxsvcs; idx++) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc = ds_svcs.tbl[idx];
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (DS_SVC_ISFREE(svc))
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen continue;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (strcmp(svc->cap.svc_id, svc_id) != 0)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen continue;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((svc->flags & DSSF_ISCLIENT) != flag_match)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen continue;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (port != NULL && svc->port == port) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (svc);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen } else if (svc->state == DS_SVC_INACTIVE) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen found_svc = svc;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen } else if (!found_svc) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen found_svc = svc;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (found_svc);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_handle_reg_req(ds_port_t *port, caddr_t buf, size_t len)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_reg_req_t *req;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_hdr_t *hdr;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_reg_ack_t *ack;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_reg_nack_t *nack;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen char *msg;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen size_t msglen;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen size_t explen = DS_MSG_LEN(ds_reg_req_t);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_svc_t *svc = NULL;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_ver_t version;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen uint16_t new_major;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen uint16_t new_minor;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen boolean_t match;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* sanity check the incoming message */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (len < explen) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_WARN, "ds@%lx: <reg_req: invalid message "
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen "length (%ld), expected at least %ld" DS_EOL,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen PORTID(port), len, explen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen req = (ds_reg_req_t *)(buf + DS_HDR_SZ);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_PRCL(CE_NOTE, "ds@%lx: <reg_req: '%s' ver=%d.%d, hdl=0x%llx"
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_EOL, PORTID(port), req->svc_id, req->major_vers, req->minor_vers,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (u_longlong_t)req->svc_handle);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_enter(&ds_svcs.lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc = ds_find_svc_by_id_port(req->svc_id,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_HDL_ISCLIENT(req->svc_handle) == 0, port);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (svc == NULL) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensendo_reg_nack:
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&ds_svcs.lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen msglen = DS_MSG_LEN(ds_reg_nack_t);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen msg = DS_MALLOC(msglen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen hdr = (ds_hdr_t *)msg;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen hdr->msg_type = DS_REG_NACK;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen hdr->payload_len = sizeof (ds_reg_nack_t);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen nack = (ds_reg_nack_t *)(msg + DS_HDR_SZ);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen nack->svc_handle = req->svc_handle;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen nack->result = DS_REG_VER_NACK;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen nack->major_vers = 0;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_PRCL(CE_NOTE, "ds@%lx: reg_nack>: '%s'" DS_EOL,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen PORTID(port), req->svc_id);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Send the response
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (void) ds_send_msg(port, msg, msglen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_FREE(msg, msglen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_PRCL(CE_NOTE, "ds@%lx: <reg_req: '%s' found, hdl: 0x%llx" DS_EOL,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen PORTID(port), req->svc_id, (u_longlong_t)svc->hdl);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * A client sends out a reg req in order to force service providers to
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen * initiate a reg req from their end (limitation in the protocol). We
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen * expect the service provider to be in the inactive (DS_SVC_INACTIVE)
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen * state. If the service provider has already sent out a reg req (the
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen * state is DS_SVC_REG_PENDING) or has already handshaken (the
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen * state is DS_SVC_ACTIVE), then we can simply ignore this reg
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen * req. For any other state, we force an unregister before initiating
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen * a reg req.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (DS_HDL_ISCLIENT(req->svc_handle)) {
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen switch (svc->state) {
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen case DS_SVC_REG_PENDING:
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen case DS_SVC_ACTIVE:
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen DS_DBG_PRCL(CE_NOTE, "ds@%lx: <reg_req: '%s' pinging "
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen "client, state (%x)" DS_EOL, PORTID(port),
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen req->svc_id, svc->state);
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen mutex_exit(&ds_svcs.lock);
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen return;
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen case DS_SVC_INACTIVE:
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen DS_DBG_PRCL(CE_NOTE, "ds@%lx: <reg_req: '%s' pinging "
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen "client" DS_EOL, PORTID(port), req->svc_id);
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen break;
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen default:
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen DS_DBG_PRCL(CE_NOTE, "ds@%lx: <reg_req: '%s' pinging "
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen "client forced unreg, state (%x)" DS_EOL,
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen PORTID(port), req->svc_id, svc->state);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (void) ds_svc_unregister(svc, port);
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen break;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (void) ds_svc_port_up(svc, port);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (void) ds_svc_register_onport(svc, port);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&ds_svcs.lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Only remote service providers can initiate a registration. The
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * local sevice from here must be a client service.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen match = negotiate_version(svc->cap.nvers, svc->cap.vers,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen req->major_vers, &new_major, &new_minor);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Check version info. ACK only if the major numbers exactly
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * match. The service entity can retry with a new minor
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * based on the response sent as part of the NACK.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (match) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_PRCL(CE_NOTE, "ds@%lx: <reg_req: '%s' svc%d: state: %x "
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen "svc_portid: %d" DS_EOL, PORTID(port), req->svc_id,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (int)DS_HDL2IDX(svc->hdl), svc->state,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (int)(svc->port == NULL ? -1 : PORTID(svc->port)));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * If the current local service is already in use and
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * it's not on this port, clone it.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (svc->state != DS_SVC_INACTIVE) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (svc->port != NULL && port == svc->port) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Someone probably dropped an unreg req
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * somewhere. Force a local unreg.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (void) ds_svc_unregister(svc, port);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen } else if (!DS_HDL_ISCLIENT(svc->hdl)) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Can't clone a non-client (service provider)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * handle. This is because old in-kernel
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * service providers can't deal with multiple
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * handles.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen goto do_reg_nack;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen } else {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc = ds_svc_clone(svc);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc->port = port;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc->svc_hdl = req->svc_handle;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc->state = DS_SVC_ACTIVE;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen msglen = DS_MSG_LEN(ds_reg_ack_t);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen msg = DS_MALLOC(msglen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen hdr = (ds_hdr_t *)msg;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen hdr->msg_type = DS_REG_ACK;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen hdr->payload_len = sizeof (ds_reg_ack_t);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ack = (ds_reg_ack_t *)(msg + DS_HDR_SZ);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ack->svc_handle = req->svc_handle;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ack->minor_vers = MIN(new_minor, req->minor_vers);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (svc->ops.ds_reg_cb) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* Call the registration callback */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen version.major = req->major_vers;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen version.minor = ack->minor_vers;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (*svc->ops.ds_reg_cb)(svc->ops.cb_arg, &version,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc->hdl);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&ds_svcs.lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_PRCL(CE_NOTE, "ds@%lx: reg_ack>: '%s' minor=0x%04X"
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_EOL, PORTID(port), svc->cap.svc_id,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen MIN(new_minor, req->minor_vers));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen } else {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&ds_svcs.lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen msglen = DS_MSG_LEN(ds_reg_nack_t);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen msg = DS_MALLOC(msglen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen hdr = (ds_hdr_t *)msg;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen hdr->msg_type = DS_REG_NACK;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen hdr->payload_len = sizeof (ds_reg_nack_t);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen nack = (ds_reg_nack_t *)(msg + DS_HDR_SZ);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen nack->svc_handle = req->svc_handle;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen nack->result = DS_REG_VER_NACK;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen nack->major_vers = new_major;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_PRCL(CE_NOTE, "ds@%lx: reg_nack>: '%s' major=0x%04X"
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_EOL, PORTID(port), svc->cap.svc_id, new_major);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* send message */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (void) ds_send_msg(port, msg, msglen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_FREE(msg, msglen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_handle_reg_ack(ds_port_t *port, caddr_t buf, size_t len)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_reg_ack_t *ack;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_ver_t *ver;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_ver_t tmpver;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_svc_t *svc;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen size_t explen = DS_MSG_LEN(ds_reg_ack_t);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* sanity check the incoming message */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (len != explen) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_WARN, "ds@%lx: <reg_ack: invalid message "
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen "length (%ld), expected %ld" DS_EOL, PORTID(port), len,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen explen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ack = (ds_reg_ack_t *)(buf + DS_HDR_SZ);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_enter(&ds_svcs.lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * This searches for service based on how we generate handles
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * and so only works because this is a reg ack.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (DS_HDL_ISCLIENT(ack->svc_handle) ||
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (svc = ds_get_svc(ack->svc_handle)) == NULL) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_WARN, "ds@%lx: <reg_ack: invalid handle 0x%llx"
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_EOL, PORTID(port), (u_longlong_t)ack->svc_handle);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen goto done;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* make sure the message makes sense */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (svc->state != DS_SVC_REG_PENDING) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_WARN, "ds@%lx: <reg_ack: invalid state (%d)" DS_EOL,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen PORTID(port), svc->state);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen goto done;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ver = &(svc->cap.vers[svc->ver_idx]);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* major version has been agreed upon */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc->ver.major = ver->major;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (ack->minor_vers >= ver->minor) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Use the minor version specified in the
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * original request.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc->ver.minor = ver->minor;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen } else {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Use the lower minor version returned in
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * the ack. By defninition, all lower minor
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * versions must be supported.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc->ver.minor = ack->minor_vers;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc->state = DS_SVC_ACTIVE;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc->port = port;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_PRCL(CE_NOTE, "ds@%lx: <reg_ack: '%s' v%d.%d ready, hdl=0x%llx"
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_EOL, PORTID(port), svc->cap.svc_id, svc->ver.major,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc->ver.minor, (u_longlong_t)svc->hdl);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* notify the client that registration is complete */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (svc->ops.ds_reg_cb) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Use a temporary version structure so that
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * the copy in the svc structure cannot be
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * modified by the client.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tmpver.major = svc->ver.major;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tmpver.minor = svc->ver.minor;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (*svc->ops.ds_reg_cb)(svc->ops.cb_arg, &tmpver, svc->hdl);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensendone:
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&ds_svcs.lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
e9406929914976efdccb875f94e90e85cdb076e3Mike Christensenstatic boolean_t
e9406929914976efdccb875f94e90e85cdb076e3Mike Christensends_port_is_ready(ds_port_t *port)
e9406929914976efdccb875f94e90e85cdb076e3Mike Christensen{
e9406929914976efdccb875f94e90e85cdb076e3Mike Christensen boolean_t is_ready;
e9406929914976efdccb875f94e90e85cdb076e3Mike Christensen
e9406929914976efdccb875f94e90e85cdb076e3Mike Christensen mutex_enter(&port->lock);
e9406929914976efdccb875f94e90e85cdb076e3Mike Christensen is_ready = (port->ldc.state == LDC_UP) &&
e9406929914976efdccb875f94e90e85cdb076e3Mike Christensen (port->state == DS_PORT_READY);
e9406929914976efdccb875f94e90e85cdb076e3Mike Christensen mutex_exit(&port->lock);
e9406929914976efdccb875f94e90e85cdb076e3Mike Christensen return (is_ready);
e9406929914976efdccb875f94e90e85cdb076e3Mike Christensen}
e9406929914976efdccb875f94e90e85cdb076e3Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_try_next_port(ds_svc_t *svc, int portid)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_port_t *port;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_portset_t totry;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen int i;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_LDC(CE_NOTE, "ds@%x %s" DS_EOL, portid, __func__);
3ef557bf6acbaf0905479800b87d010f8715a11eMike Christensen
3ef557bf6acbaf0905479800b87d010f8715a11eMike Christensen /*
3ef557bf6acbaf0905479800b87d010f8715a11eMike Christensen * Get the ports that haven't been tried yet and are available to try.
3ef557bf6acbaf0905479800b87d010f8715a11eMike Christensen */
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen DS_PORTSET_DUP(totry, svc->avail);
3ef557bf6acbaf0905479800b87d010f8715a11eMike Christensen for (i = 0; i < DS_MAX_PORTS; i++) {
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen if (DS_PORT_IN_SET(svc->tried, i))
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen DS_PORTSET_DEL(totry, i);
3ef557bf6acbaf0905479800b87d010f8715a11eMike Christensen }
3ef557bf6acbaf0905479800b87d010f8715a11eMike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (DS_PORTSET_ISNULL(totry))
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen for (i = 0; i < DS_MAX_PORTS; i++, portid++) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (portid >= DS_MAX_PORTS) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen portid = 0;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * If the port is not in the available list,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * it is not a candidate for registration.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (!DS_PORT_IN_SET(totry, portid)) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen continue;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen port = &ds_ports[portid];
e9406929914976efdccb875f94e90e85cdb076e3Mike Christensen
e9406929914976efdccb875f94e90e85cdb076e3Mike Christensen if (!ds_port_is_ready(port))
e9406929914976efdccb875f94e90e85cdb076e3Mike Christensen continue;
e9406929914976efdccb875f94e90e85cdb076e3Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_LDC(CE_NOTE, "ds@%x: %s trying ldc.id: %d" DS_EOL,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen portid, __func__, (uint_t)(port->ldc.id));
e9406929914976efdccb875f94e90e85cdb076e3Mike Christensen
e9406929914976efdccb875f94e90e85cdb076e3Mike Christensen DS_PORTSET_ADD(svc->tried, portid);
e9406929914976efdccb875f94e90e85cdb076e3Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (ds_send_reg_req(svc, port) == 0) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_LDC(CE_NOTE, "ds@%x: %s reg msg send OK" DS_EOL,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen portid, __func__);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* register sent successfully */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen break;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_LDC(CE_NOTE, "ds@%x: %s reg msg send FAIL" DS_EOL,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen portid, __func__);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* reset the service to try the next port */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_reset_svc(svc, port);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_handle_reg_nack(ds_port_t *port, caddr_t buf, size_t len)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_reg_nack_t *nack;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_svc_t *svc;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen int idx;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen size_t explen = DS_MSG_LEN(ds_reg_nack_t);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* sanity check the incoming message */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (len != explen) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_WARN, "ds@%lx: <reg_nack: invalid message "
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen "length (%ld), expected %ld" DS_EOL, PORTID(port), len,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen explen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen nack = (ds_reg_nack_t *)(buf + DS_HDR_SZ);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_enter(&ds_svcs.lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * We expect a reg_nack for a client ping.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (DS_HDL_ISCLIENT(nack->svc_handle)) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_PRCL(CE_NOTE, "ds@%lx: <reg_nack: ping hdl: 0x%llx"
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_EOL, PORTID(port), (u_longlong_t)nack->svc_handle);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen goto done;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * This searches for service based on how we generate handles
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * and so only works because this is a reg nack.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((svc = ds_get_svc(nack->svc_handle)) == NULL) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_WARN, "ds@%lx: <reg_nack: invalid handle 0x%llx"
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_EOL, PORTID(port), (u_longlong_t)nack->svc_handle);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen goto done;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* make sure the message makes sense */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (svc->state != DS_SVC_REG_PENDING) {
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen DS_DBG_PRCL(CE_NOTE, "ds@%lx: <reg_nack: '%s' handle: 0x%llx "
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen "invalid state (%d)" DS_EOL, PORTID(port), svc->cap.svc_id,
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen (u_longlong_t)nack->svc_handle, svc->state);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen goto done;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (nack->result == DS_REG_DUP) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_WARN, "ds@%lx: <reg_nack: duplicate registration "
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen " for %s" DS_EOL, PORTID(port), svc->cap.svc_id);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_reset_svc(svc, port);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen goto done;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * A major version of zero indicates that the
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * service is not supported at all.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (nack->major_vers == 0) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_PRCL(CE_NOTE, "ds@%lx: <reg_nack: '%s' not supported"
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_EOL, PORTID(port), svc->cap.svc_id);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_reset_svc(svc, port);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((svc->flags & DSSF_ISCLIENT) == 0)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_try_next_port(svc, PORTID(port) + 1);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen goto done;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_PRCL(CE_NOTE, "ds@%lx: <reg_nack: '%s' hdl=0x%llx, nack=%d.x"
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_EOL, PORTID(port), svc->cap.svc_id,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (u_longlong_t)nack->svc_handle, nack->major_vers);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Walk the version list for the service, looking for
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * a major version that is as close to the requested
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * major version as possible.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen for (idx = svc->ver_idx; idx < svc->cap.nvers; idx++) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (svc->cap.vers[idx].major <= nack->major_vers) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* found a version to try */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen break;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (idx == svc->cap.nvers) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* no supported version */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_PRCL(CE_NOTE, "ds@%lx: <reg_nack: %s v%d.x not supported"
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_EOL, PORTID(port), svc->cap.svc_id, nack->major_vers);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_reset_svc(svc, port);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((svc->flags & DSSF_ISCLIENT) == 0)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_try_next_port(svc, PORTID(port) + 1);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen goto done;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* start the handshake again */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc->state = DS_SVC_INACTIVE;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc->ver_idx = idx;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (void) ds_svc_register(svc, NULL);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensendone:
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&ds_svcs.lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_handle_unreg_req(ds_port_t *port, caddr_t buf, size_t len)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_hdr_t *hdr;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_unreg_req_t *req;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_unreg_ack_t *ack;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_svc_t *svc;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen char *msg;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen size_t msglen;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen size_t explen = DS_MSG_LEN(ds_unreg_req_t);
beba1dd881728e806abb8621851ae851da168a08Mike Christensen boolean_t is_up;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* sanity check the incoming message */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (len != explen) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_WARN, "ds@%lx: <unreg_req: invalid message "
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen "length (%ld), expected %ld" DS_EOL, PORTID(port), len,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen explen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen req = (ds_unreg_req_t *)(buf + DS_HDR_SZ);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_enter(&ds_svcs.lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* lookup appropriate client or service */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (DS_HDL_ISCLIENT(req->svc_handle) ||
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ((svc = ds_find_clnt_svc_by_hdl_port(req->svc_handle, port))
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen == NULL && ((svc = ds_get_svc(req->svc_handle)) == NULL ||
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc->port != port))) {
beba1dd881728e806abb8621851ae851da168a08Mike Christensen mutex_exit(&ds_svcs.lock);
beba1dd881728e806abb8621851ae851da168a08Mike Christensen mutex_enter(&port->lock);
beba1dd881728e806abb8621851ae851da168a08Mike Christensen is_up = (port->ldc.state == LDC_UP);
beba1dd881728e806abb8621851ae851da168a08Mike Christensen mutex_exit(&port->lock);
beba1dd881728e806abb8621851ae851da168a08Mike Christensen if (!is_up)
beba1dd881728e806abb8621851ae851da168a08Mike Christensen return;
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen DS_DBG_PRCL(CE_NOTE, "ds@%lx: <unreg_req: invalid handle 0x%llx"
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_EOL, PORTID(port), (u_longlong_t)req->svc_handle);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_send_unreg_nack(port, req->svc_handle);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_PRCL(CE_NOTE, "ds@%lx: <unreg_req: '%s' handle 0x%llx" DS_EOL,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen PORTID(port), svc->cap.svc_id, (u_longlong_t)req->svc_handle);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (void) ds_svc_unregister(svc, svc->port);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_PRCL(CE_NOTE, "ds@%lx: unreg_ack>: '%s' hdl=0x%llx" DS_EOL,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen PORTID(port), svc->cap.svc_id, (u_longlong_t)req->svc_handle);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_check_for_dup_services(svc);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&ds_svcs.lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen msglen = DS_HDR_SZ + sizeof (ds_unreg_ack_t);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen msg = DS_MALLOC(msglen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen hdr = (ds_hdr_t *)msg;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen hdr->msg_type = DS_UNREG_ACK;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen hdr->payload_len = sizeof (ds_unreg_ack_t);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ack = (ds_unreg_ack_t *)(msg + DS_HDR_SZ);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ack->svc_handle = req->svc_handle;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* send message */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (void) ds_send_msg(port, msg, msglen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_FREE(msg, msglen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_handle_unreg_ack(ds_port_t *port, caddr_t buf, size_t len)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_unreg_ack_t *ack;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen size_t explen = DS_MSG_LEN(ds_unreg_ack_t);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* sanity check the incoming message */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (len != explen) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_WARN, "ds@%lx: <unreg_ack: invalid message "
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen "length (%ld), expected %ld" DS_EOL, PORTID(port), len,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen explen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ack = (ds_unreg_ack_t *)(buf + DS_HDR_SZ);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_PRCL(CE_NOTE, "ds@%lx: <unreg_ack: hdl=0x%llx" DS_EOL,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen PORTID(port), (u_longlong_t)ack->svc_handle);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
b1ad746c0fd685d32c55d17a53c097d8eefbfd11Mike Christensen#ifdef DEBUG
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_enter(&ds_svcs.lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Since the unregister request was initiated locally,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * the service structure has already been torn down.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Just perform a sanity check to make sure the message
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * is appropriate.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (ds_get_svc(ack->svc_handle) != NULL) {
b1ad746c0fd685d32c55d17a53c097d8eefbfd11Mike Christensen DS_DBG_PRCL(CE_NOTE, "ds@%lx: <unreg_ack: handle 0x%llx in use"
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_EOL, PORTID(port), (u_longlong_t)ack->svc_handle);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&ds_svcs.lock);
b1ad746c0fd685d32c55d17a53c097d8eefbfd11Mike Christensen#endif /* DEBUG */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_handle_unreg_nack(ds_port_t *port, caddr_t buf, size_t len)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_unreg_nack_t *nack;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen size_t explen = DS_MSG_LEN(ds_unreg_nack_t);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* sanity check the incoming message */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (len != explen) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_WARN, "ds@%lx: <unreg_nack: invalid message "
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen "length (%ld), expected %ld" DS_EOL, PORTID(port), len,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen explen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen nack = (ds_unreg_nack_t *)(buf + DS_HDR_SZ);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_PRCL(CE_NOTE, "ds@%lx: <unreg_nack: hdl=0x%llx" DS_EOL,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen PORTID(port), (u_longlong_t)nack->svc_handle);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
b1ad746c0fd685d32c55d17a53c097d8eefbfd11Mike Christensen#ifdef DEBUG
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_enter(&ds_svcs.lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Since the unregister request was initiated locally,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * the service structure has already been torn down.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Just perform a sanity check to make sure the message
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * is appropriate.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (ds_get_svc(nack->svc_handle) != NULL) {
b1ad746c0fd685d32c55d17a53c097d8eefbfd11Mike Christensen DS_DBG_PRCL(CE_NOTE, "ds@%lx: <unreg_nack: handle 0x%llx in use"
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_EOL, PORTID(port), (u_longlong_t)nack->svc_handle);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&ds_svcs.lock);
b1ad746c0fd685d32c55d17a53c097d8eefbfd11Mike Christensen#endif /* DEBUG */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_handle_data(ds_port_t *port, caddr_t buf, size_t len)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_data_handle_t *data;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_svc_t *svc;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen char *msg;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen int msgsz;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen int hdrsz;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen size_t explen = DS_MSG_LEN(ds_data_handle_t);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* sanity check the incoming message */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (len < explen) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_WARN, "ds@%lx: <data: invalid message length "
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen "(%ld), expected at least %ld" DS_EOL, PORTID(port), len,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen explen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen data = (ds_data_handle_t *)(buf + DS_HDR_SZ);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen hdrsz = DS_HDR_SZ + sizeof (ds_data_handle_t);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen msgsz = len - hdrsz;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* strip off the header for the client */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen msg = (msgsz) ? (buf + hdrsz) : NULL;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_enter(&ds_svcs.lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((svc = ds_find_clnt_svc_by_hdl_port(data->svc_handle, port))
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen == NULL) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((svc = ds_get_svc(data->svc_handle)) == NULL) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&ds_svcs.lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_WARN, "ds@%lx: <data: invalid handle 0x%llx"
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_EOL, PORTID(port),
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (u_longlong_t)data->svc_handle);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_send_data_nack(port, data->svc_handle);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&ds_svcs.lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_PRCL(CE_NOTE, "ds@%lx: <data: '%s' hdl=0x%llx" DS_EOL,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen PORTID(port), svc->cap.svc_id, (u_longlong_t)svc->hdl);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DUMP_MSG(DS_DBG_FLAG_PRCL, msg, msgsz);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* dispatch this message to the client */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (*svc->ops.ds_data_cb)(svc->ops.cb_arg, msg, msgsz);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_handle_nack(ds_port_t *port, caddr_t buf, size_t len)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_svc_t *svc;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_data_nack_t *nack;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen size_t explen = DS_MSG_LEN(ds_data_nack_t);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* sanity check the incoming message */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (len != explen) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_WARN, "ds@%lx: <data_nack: invalid message "
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen "length (%ld), expected %ld" DS_EOL, PORTID(port), len,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen explen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen nack = (ds_data_nack_t *)(buf + DS_HDR_SZ);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_PRCL(CE_NOTE, "ds@%lx: data_nack: hdl=0x%llx, result=0x%llx"
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_EOL, PORTID(port), (u_longlong_t)nack->svc_handle,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (u_longlong_t)nack->result);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (nack->result == DS_INV_HDL) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_enter(&ds_svcs.lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((svc = ds_find_clnt_svc_by_hdl_port(nack->svc_handle,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen port)) == NULL) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((svc = ds_get_svc(nack->svc_handle)) == NULL) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&ds_svcs.lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_WARN, "ds@%lx: <data_nack: handle 0x%llx reported "
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen " as invalid" DS_EOL, PORTID(port),
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (u_longlong_t)nack->svc_handle);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (void) ds_svc_unregister(svc, svc->port);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&ds_svcs.lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/* Initialize the port */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenvoid
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_send_init_req(ds_port_t *port)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_hdr_t *hdr;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_init_req_t *init_req;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen size_t msglen;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_ver_t *vers = &ds_vers[port->ver_idx];
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_enter(&port->lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (port->state != DS_PORT_LDC_INIT) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_PRCL(CE_NOTE, "ds@%lx: init_req>: invalid state: %d"
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_EOL, PORTID(port), port->state);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&port->lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&port->lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_PRCL(CE_NOTE, "ds@%lx: init_req>: req=v%d.%d" DS_EOL,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen PORTID(port), vers->major, vers->minor);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen msglen = DS_HDR_SZ + sizeof (ds_init_req_t);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen hdr = DS_MALLOC(msglen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen hdr->msg_type = DS_INIT_REQ;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen hdr->payload_len = sizeof (ds_init_req_t);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen init_req = (ds_init_req_t *)((caddr_t)hdr + DS_HDR_SZ);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen init_req->major_vers = vers->major;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen init_req->minor_vers = vers->minor;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (ds_send_msg(port, (caddr_t)hdr, msglen) == 0) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * We've left the port state unlocked over the malloc/send,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * make sure no one has changed the state under us before
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * we update the state.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_enter(&port->lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (port->state == DS_PORT_LDC_INIT)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen port->state = DS_PORT_INIT_REQ;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&port->lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_FREE(hdr, msglen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic int
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_send_reg_req(ds_svc_t *svc, ds_port_t *port)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_ver_t *ver;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_hdr_t *hdr;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen caddr_t msg;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen size_t msglen;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_reg_req_t *req;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen size_t idlen;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen int rv;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen if ((svc->state != DS_SVC_INACTIVE) &&
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen ((svc->flags & DSSF_ISCLIENT) == 0)) {
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen DS_DBG_PRCL(CE_NOTE, "ds@%lx: reg_req>: invalid svc state (%d) "
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen "for svc '%s'" DS_EOL, PORTID(port), svc->state,
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen svc->cap.svc_id);
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen return (-1);
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_enter(&port->lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* check on the LDC to Zeus */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (port->ldc.state != LDC_UP) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* can not send message */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_PRCL(CE_NOTE, "ds@%lx: reg_req>: channel %ld is not up"
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_EOL, PORTID(port), port->ldc.id);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&port->lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (-1);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* make sure port is ready */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (port->state != DS_PORT_READY) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* can not send message */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_PRCL(CE_NOTE, "ds@%lx: reg_req>: port is not ready"
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_EOL, PORTID(port));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&port->lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (-1);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&port->lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* allocate the message buffer */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen idlen = strlen(svc->cap.svc_id);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen msglen = DS_HDR_SZ + sizeof (ds_reg_req_t) + idlen;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen msg = DS_MALLOC(msglen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* copy in the header data */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen hdr = (ds_hdr_t *)msg;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen hdr->msg_type = DS_REG_REQ;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen hdr->payload_len = sizeof (ds_reg_req_t) + idlen;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen req = (ds_reg_req_t *)(msg + DS_HDR_SZ);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen req->svc_handle = svc->hdl;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ver = &(svc->cap.vers[svc->ver_idx]);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen req->major_vers = ver->major;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen req->minor_vers = ver->minor;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* copy in the service id */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (void) memcpy(req->svc_id, svc->cap.svc_id, idlen + 1);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* send the message */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_PRCL(CE_NOTE, "ds@%lx: reg_req>: '%s' ver=%d.%d, hdl=0x%llx"
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_EOL, PORTID(port), svc->cap.svc_id, ver->major, ver->minor,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (u_longlong_t)svc->hdl);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((rv = ds_send_msg(port, msg, msglen)) != 0) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc->port = port;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen rv = -1;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen } else if ((svc->flags & DSSF_ISCLIENT) == 0) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc->state = DS_SVC_REG_PENDING;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_FREE(msg, msglen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (rv);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Keep around in case we want this later
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenint
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_send_unreg_req(ds_svc_t *svc)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen caddr_t msg;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen size_t msglen;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_hdr_t *hdr;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_unreg_req_t *req;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_port_t *port = svc->port;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen int rv;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (port == NULL) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG(CE_NOTE, "send_unreg_req: service '%s' not "
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen "associated with a port" DS_EOL, svc->cap.svc_id);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (-1);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_enter(&port->lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* check on the LDC to Zeus */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (port->ldc.state != LDC_UP) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* can not send message */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_WARN, "ds@%lx: unreg_req>: channel %ld is not up"
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_EOL, PORTID(port), port->ldc.id);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&port->lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (-1);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* make sure port is ready */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (port->state != DS_PORT_READY) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* can not send message */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_WARN, "ds@%lx: unreg_req>: port is not ready" DS_EOL,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen PORTID(port));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&port->lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (-1);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&port->lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen msglen = DS_HDR_SZ + sizeof (ds_unreg_req_t);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen msg = DS_MALLOC(msglen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* copy in the header data */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen hdr = (ds_hdr_t *)msg;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen hdr->msg_type = DS_UNREG;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen hdr->payload_len = sizeof (ds_unreg_req_t);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen req = (ds_unreg_req_t *)(msg + DS_HDR_SZ);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (svc->flags & DSSF_ISCLIENT) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen req->svc_handle = svc->svc_hdl;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen } else {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen req->svc_handle = svc->hdl;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* send the message */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_PRCL(CE_NOTE, "ds@%lx: unreg_req>: '%s' hdl=0x%llx" DS_EOL,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen PORTID(port), (svc->cap.svc_id) ? svc->cap.svc_id : "NULL",
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (u_longlong_t)svc->hdl);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((rv = ds_send_msg(port, msg, msglen)) != 0) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen rv = -1;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_FREE(msg, msglen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (rv);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_send_unreg_nack(ds_port_t *port, ds_svc_hdl_t bad_hdl)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen caddr_t msg;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen size_t msglen;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_hdr_t *hdr;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_unreg_nack_t *nack;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_enter(&port->lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* check on the LDC to Zeus */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (port->ldc.state != LDC_UP) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* can not send message */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_WARN, "ds@%lx: unreg_nack>: channel %ld is not up"
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_EOL, PORTID(port), port->ldc.id);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&port->lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* make sure port is ready */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (port->state != DS_PORT_READY) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* can not send message */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_WARN, "ds@%lx: unreg_nack>: port is not ready"
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_EOL, PORTID(port));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&port->lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&port->lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen msglen = DS_HDR_SZ + sizeof (ds_unreg_nack_t);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen msg = DS_MALLOC(msglen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* copy in the header data */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen hdr = (ds_hdr_t *)msg;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen hdr->msg_type = DS_UNREG_NACK;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen hdr->payload_len = sizeof (ds_unreg_nack_t);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen nack = (ds_unreg_nack_t *)(msg + DS_HDR_SZ);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen nack->svc_handle = bad_hdl;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* send the message */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_PRCL(CE_NOTE, "ds@%lx: unreg_nack>: hdl=0x%llx" DS_EOL,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen PORTID(port), (u_longlong_t)bad_hdl);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (void) ds_send_msg(port, msg, msglen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_FREE(msg, msglen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_send_data_nack(ds_port_t *port, ds_svc_hdl_t bad_hdl)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen caddr_t msg;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen size_t msglen;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_hdr_t *hdr;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_data_nack_t *nack;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_enter(&port->lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* check on the LDC to Zeus */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (port->ldc.state != LDC_UP) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* can not send message */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_WARN, "ds@%lx: data_nack>: channel %ld is not up"
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_EOL, PORTID(port), port->ldc.id);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&port->lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* make sure port is ready */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (port->state != DS_PORT_READY) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* can not send message */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_WARN, "ds@%lx: data_nack>: port is not ready" DS_EOL,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen PORTID(port));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&port->lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&port->lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen msglen = DS_HDR_SZ + sizeof (ds_data_nack_t);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen msg = DS_MALLOC(msglen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* copy in the header data */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen hdr = (ds_hdr_t *)msg;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen hdr->msg_type = DS_NACK;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen hdr->payload_len = sizeof (ds_data_nack_t);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen nack = (ds_data_nack_t *)(msg + DS_HDR_SZ);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen nack->svc_handle = bad_hdl;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen nack->result = DS_INV_HDL;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* send the message */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_PRCL(CE_NOTE, "ds@%lx: data_nack>: hdl=0x%llx" DS_EOL,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen PORTID(port), (u_longlong_t)bad_hdl);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (void) ds_send_msg(port, msg, msglen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_FREE(msg, msglen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/* END DS PROTOCOL SUPPORT FUNCTIONS */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#ifdef DEBUG
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#define BYTESPERLINE 8
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#define LINEWIDTH ((BYTESPERLINE * 3) + (BYTESPERLINE + 2) + 1)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#define ASCIIOFFSET ((BYTESPERLINE * 3) + 2)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#define ISPRINT(c) ((c >= ' ') && (c <= '~'))
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Output a buffer formatted with a set number of bytes on
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * each line. Append each line with the ASCII equivalent of
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * each byte if it falls within the printable ASCII range,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * and '.' otherwise.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenvoid
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_dump_msg(void *vbuf, size_t len)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen int i, j;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen char *curr;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen char *aoff;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen char line[LINEWIDTH];
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen uint8_t *buf = vbuf;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (len > 128)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen len = 128;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* walk the buffer one line at a time */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen for (i = 0; i < len; i += BYTESPERLINE) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen bzero(line, LINEWIDTH);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen curr = line;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen aoff = line + ASCIIOFFSET;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Walk the bytes in the current line, storing
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * the hex value for the byte as well as the
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * ASCII representation in a temporary buffer.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * All ASCII values are placed at the end of
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * the line.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen for (j = 0; (j < BYTESPERLINE) && ((i + j) < len); j++) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (void) sprintf(curr, " %02x", buf[i + j]);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen *aoff = (ISPRINT(buf[i + j])) ? buf[i + j] : '.';
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen curr += 3;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen aoff++;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Fill in to the start of the ASCII translation
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * with spaces. This will only be necessary if
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * this is the last line and there are not enough
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * bytes to fill the whole line.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen while (curr != (line + ASCIIOFFSET))
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen *curr++ = ' ';
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_NOTE, "%s" DS_EOL, line);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#endif /* DEBUG */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Walk the table of registered services, executing the specified callback
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * function for each service on a port. A non-zero return value from the
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * callback is used to terminate the walk, not to indicate an error. Returns
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * the index of the last service visited.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenint
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_walk_svcs(svc_cb_t svc_cb, void *arg)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen int idx;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_svc_t *svc;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ASSERT(MUTEX_HELD(&ds_svcs.lock));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* walk every table entry */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen for (idx = 0; idx < ds_svcs.maxsvcs; idx++) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc = ds_svcs.tbl[idx];
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* execute the callback */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((*svc_cb)(svc, arg) != 0)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen break;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (idx);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic int
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_svc_isfree(ds_svc_t *svc, void *arg)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen _NOTE(ARGUNUSED(arg))
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Looking for a free service. This may be a NULL entry
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * in the table, or an unused structure that could be
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * reused.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (DS_SVC_ISFREE(svc)) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* yes, it is free */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (1);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* not a candidate */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (0);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenint
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_svc_ismatch(ds_svc_t *svc, void *arg)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (DS_SVC_ISFREE(svc)) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (0);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (strcmp(svc->cap.svc_id, arg) == 0 &&
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (svc->flags & DSSF_ISCLIENT) == 0) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* found a match */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (1);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (0);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenint
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_svc_clnt_ismatch(ds_svc_t *svc, void *arg)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (DS_SVC_ISFREE(svc)) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (0);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (strcmp(svc->cap.svc_id, arg) == 0 &&
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (svc->flags & DSSF_ISCLIENT) != 0) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* found a match */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (1);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (0);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenint
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_svc_free(ds_svc_t *svc, void *arg)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen _NOTE(ARGUNUSED(arg))
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (svc == NULL) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (0);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (svc->cap.svc_id) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_FREE(svc->cap.svc_id, strlen(svc->cap.svc_id) + 1);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc->cap.svc_id = NULL;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (svc->cap.vers) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_FREE(svc->cap.vers, svc->cap.nvers * sizeof (ds_ver_t));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc->cap.vers = NULL;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_FREE(svc, sizeof (ds_svc_t));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (0);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensenstatic void
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensends_set_svc_port_tried(char *svc_id, ds_port_t *port)
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen{
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen int idx;
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen ds_svc_t *svc;
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen ASSERT(MUTEX_HELD(&ds_svcs.lock));
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen /* walk every table entry */
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen for (idx = 0; idx < ds_svcs.maxsvcs; idx++) {
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen svc = ds_svcs.tbl[idx];
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen if (!DS_SVC_ISFREE(svc) && (svc->flags & DSSF_ISCLIENT) != 0 &&
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen strcmp(svc_id, svc->cap.svc_id) == 0)
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen DS_PORTSET_ADD(svc->tried, PORTID(port));
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen }
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen}
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic int
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_svc_register_onport(ds_svc_t *svc, ds_port_t *port)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ASSERT(MUTEX_HELD(&ds_svcs.lock));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (DS_SVC_ISFREE(svc))
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (0);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (!DS_PORT_IN_SET(svc->avail, PORTID(port)))
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (0);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen if (DS_PORT_IN_SET(svc->tried, PORTID(port)))
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen return (0);
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen
e9406929914976efdccb875f94e90e85cdb076e3Mike Christensen if (!ds_port_is_ready(port))
e9406929914976efdccb875f94e90e85cdb076e3Mike Christensen return (0);
e9406929914976efdccb875f94e90e85cdb076e3Mike Christensen
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen if ((svc->flags & DSSF_ISCLIENT) == 0) {
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen if (svc->state != DS_SVC_INACTIVE)
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen return (0);
e9406929914976efdccb875f94e90e85cdb076e3Mike Christensen DS_PORTSET_ADD(svc->tried, PORTID(port));
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen } else {
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen ds_set_svc_port_tried(svc->cap.svc_id, port);
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen /*
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen * Never send a client reg req to the SP.
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen */
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen if (PORTID(port) == ds_sp_port_id) {
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen return (0);
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen }
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (ds_send_reg_req(svc, port) == 0) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* register sent successfully */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (1);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((svc->flags & DSSF_ISCLIENT) == 0) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* reset the service */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_reset_svc(svc, port);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (0);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensenstatic int
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensends_svc_register_onport_walker(ds_svc_t *svc, void *arg)
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen{
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen ASSERT(MUTEX_HELD(&ds_svcs.lock));
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen if (DS_SVC_ISFREE(svc))
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen return (0);
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen (void) ds_svc_register_onport(svc, arg);
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen return (0);
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen}
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenint
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_svc_register(ds_svc_t *svc, void *arg)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen _NOTE(ARGUNUSED(arg))
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_portset_t ports;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_port_t *port;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen int idx;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ASSERT(MUTEX_HELD(&ds_svcs.lock));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (DS_SVC_ISFREE(svc))
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (0);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
3ef557bf6acbaf0905479800b87d010f8715a11eMike Christensen DS_PORTSET_DUP(ports, svc->avail);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (svc->flags & DSSF_ISCLIENT) {
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen for (idx = 0; idx < DS_MAX_PORTS; idx++) {
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen if (DS_PORT_IN_SET(svc->tried, idx))
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen DS_PORTSET_DEL(ports, idx);
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen } else if (svc->state != DS_SVC_INACTIVE)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (0);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (DS_PORTSET_ISNULL(ports))
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (0);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Attempt to register the service. Start with the lowest
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * numbered port and continue until a registration message
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * is sent successfully, or there are no ports left to try.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen for (idx = 0; idx < DS_MAX_PORTS; idx++) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * If the port is not in the available list,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * it is not a candidate for registration.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (!DS_PORT_IN_SET(ports, idx)) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen continue;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen port = &ds_ports[idx];
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (ds_svc_register_onport(svc, port)) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((svc->flags & DSSF_ISCLIENT) == 0)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen break;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (0);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic int
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_svc_unregister(ds_svc_t *svc, void *arg)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_port_t *port = (ds_port_t *)arg;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_svc_hdl_t hdl;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ASSERT(MUTEX_HELD(&ds_svcs.lock));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (DS_SVC_ISFREE(svc)) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (0);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* make sure the service is using this port */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (svc->port != port) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (0);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (port) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG(CE_NOTE, "ds@%lx: svc_unreg: id='%s', ver=%d.%d, "
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen " hdl=0x%09lx" DS_EOL, PORTID(port), svc->cap.svc_id,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc->ver.major, svc->ver.minor, svc->hdl);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen } else {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG(CE_NOTE, "port=NULL: svc_unreg: id='%s', ver=%d.%d, "
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen " hdl=0x%09lx" DS_EOL, svc->cap.svc_id, svc->ver.major,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc->ver.minor, svc->hdl);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* reset the service structure */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_reset_svc(svc, port);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* call the client unregister callback */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (svc->ops.ds_unreg_cb) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (*svc->ops.ds_unreg_cb)(svc->ops.cb_arg);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* increment the count in the handle to prevent reuse */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen hdl = DS_ALLOC_HDL(DS_HDL2IDX(svc->hdl), DS_HDL2COUNT(svc->hdl));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (DS_HDL_ISCLIENT(svc->hdl)) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_HDL_SET_ISCLIENT(hdl);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc->hdl = hdl;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (svc->state != DS_SVC_UNREG_PENDING) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* try to initiate a new registration */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (void) ds_svc_register(svc, NULL);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (0);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic int
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_svc_port_up(ds_svc_t *svc, void *arg)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_port_t *port = (ds_port_t *)arg;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (DS_SVC_ISFREE(svc)) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* nothing to do */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (0);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_PORTSET_ADD(svc->avail, port->id);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_PORTSET_DEL(svc->tried, port->id);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (0);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensenstatic void
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensends_set_port_ready(ds_port_t *port, uint16_t major, uint16_t minor)
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen{
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen boolean_t was_ready;
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen mutex_enter(&port->lock);
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen was_ready = (port->state == DS_PORT_READY);
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen if (!was_ready) {
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen port->state = DS_PORT_READY;
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen port->ver.major = major;
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen port->ver.minor = minor;
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen }
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen mutex_exit(&port->lock);
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen if (!was_ready) {
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen /*
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen * The port came up, so update all the services
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen * with this information. Follow that up with an
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen * attempt to register any service that is not
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen * already registered.
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen */
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen mutex_enter(&ds_svcs.lock);
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen (void) ds_walk_svcs(ds_svc_port_up, port);
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen (void) ds_walk_svcs(ds_svc_register_onport_walker, port);
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen mutex_exit(&ds_svcs.lock);
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen }
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen}
ffc2bef081c0f7e604532873017ff27025cd46aeMike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_svc_t *
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_alloc_svc(void)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen int idx;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen uint_t newmaxsvcs;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_svc_t **newtbl;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_svc_t *newsvc;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ASSERT(MUTEX_HELD(&ds_svcs.lock));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen idx = ds_walk_svcs(ds_svc_isfree, NULL);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (idx != ds_svcs.maxsvcs) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen goto found;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * There was no free space in the table. Grow
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * the table to double its current size.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen newmaxsvcs = ds_svcs.maxsvcs * 2;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen newtbl = DS_MALLOC(newmaxsvcs * sizeof (ds_svc_t *));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* copy old table data to the new table */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (void) memcpy(newtbl, ds_svcs.tbl,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_svcs.maxsvcs * sizeof (ds_svc_t *));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* clean up the old table */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_FREE(ds_svcs.tbl, ds_svcs.maxsvcs * sizeof (ds_svc_t *));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_svcs.tbl = newtbl;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_svcs.maxsvcs = newmaxsvcs;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* search for a free space again */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen idx = ds_walk_svcs(ds_svc_isfree, NULL);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* the table is locked so should find a free slot */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ASSERT(idx != ds_svcs.maxsvcs);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenfound:
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* allocate a new svc structure if necessary */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((newsvc = ds_svcs.tbl[idx]) == NULL) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* allocate a new service */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen newsvc = DS_MALLOC(sizeof (ds_svc_t));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_svcs.tbl[idx] = newsvc;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* fill in the handle */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen newsvc->hdl = DS_ALLOC_HDL(idx, DS_HDL2COUNT(newsvc->hdl));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen newsvc->state = DS_SVC_FREE; /* Mark as free temporarily */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (newsvc);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_reset_svc(ds_svc_t *svc, ds_port_t *port)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ASSERT(MUTEX_HELD(&ds_svcs.lock));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (svc->state != DS_SVC_UNREG_PENDING)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc->state = DS_SVC_INACTIVE;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc->ver_idx = 0;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc->ver.major = 0;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc->ver.minor = 0;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc->port = NULL;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (port) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_PORTSET_DEL(svc->avail, port->id);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_svc_t *
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_get_svc(ds_svc_hdl_t hdl)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen int idx;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_svc_t *svc;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ASSERT(MUTEX_HELD(&ds_svcs.lock));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (hdl == DS_INVALID_HDL)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (NULL);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen idx = DS_HDL2IDX(hdl);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* check if index is out of bounds */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((idx < 0) || (idx >= ds_svcs.maxsvcs))
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (NULL);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc = ds_svcs.tbl[idx];
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* check for a valid service */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (DS_SVC_ISFREE(svc))
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (NULL);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* make sure the handle is an exact match */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (svc->hdl != hdl)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (NULL);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (svc);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_port_reset(ds_port_t *port)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ASSERT(MUTEX_HELD(&ds_svcs.lock));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ASSERT(MUTEX_HELD(&port->lock));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* connection went down, mark everything inactive */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (void) ds_walk_svcs(ds_svc_unregister, port);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen port->ver_idx = 0;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen port->ver.major = 0;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen port->ver.minor = 0;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen port->state = DS_PORT_LDC_INIT;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Verify that a version array is sorted as expected for the
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * version negotiation to work correctly.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_vers_check_t
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_vers_isvalid(ds_ver_t *vers, int nvers)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen uint16_t curr_major;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen uint16_t curr_minor;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen int idx;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen curr_major = vers[0].major;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen curr_minor = vers[0].minor;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Walk the version array, verifying correct ordering.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * The array must be sorted from highest supported
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * version to lowest supported version.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen for (idx = 0; idx < nvers; idx++) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (vers[idx].major > curr_major) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG(CE_NOTE, "ds_vers_isvalid: version array has "
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen " increasing major versions" DS_EOL);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (DS_VERS_INCREASING_MAJOR_ERR);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (vers[idx].major < curr_major) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen curr_major = vers[idx].major;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen curr_minor = vers[idx].minor;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen continue;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (vers[idx].minor > curr_minor) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG(CE_NOTE, "ds_vers_isvalid: version array has "
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen " increasing minor versions" DS_EOL);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (DS_VERS_INCREASING_MINOR_ERR);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen curr_minor = vers[idx].minor;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (DS_VERS_OK);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Extended user capability init.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenint
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_ucap_init(ds_capability_t *cap, ds_clnt_ops_t *ops, uint32_t flags,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen int instance, ds_svc_hdl_t *hdlp)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_vers_check_t status;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_svc_t *svc;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen int rv = 0;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_svc_hdl_t lb_hdl, hdl;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen int is_loopback;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen int is_client;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* sanity check the args */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((cap == NULL) || (ops == NULL)) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_NOTE, "%s: invalid arguments" DS_EOL, __func__);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (EINVAL);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* sanity check the capability specifier */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((cap->svc_id == NULL) || (cap->vers == NULL) || (cap->nvers == 0)) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_NOTE, "%s: invalid capability specifier" DS_EOL,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen __func__);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (EINVAL);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* sanity check the version array */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((status = ds_vers_isvalid(cap->vers, cap->nvers)) != DS_VERS_OK) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_NOTE, "%s: invalid capability version array "
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen "for %s service: %s" DS_EOL, __func__, cap->svc_id,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (status == DS_VERS_INCREASING_MAJOR_ERR) ?
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen "increasing major versions" :
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen "increasing minor versions");
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (EINVAL);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* data and register callbacks are required */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((ops->ds_data_cb == NULL) || (ops->ds_reg_cb == NULL)) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_NOTE, "%s: invalid ops specifier for %s service"
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_EOL, __func__, cap->svc_id);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (EINVAL);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen flags &= DSSF_USERFLAGS;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen is_client = flags & DSSF_ISCLIENT;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_USR(CE_NOTE, "%s: svc_id='%s', data_cb=0x%lx, cb_arg=0x%lx"
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_EOL, __func__, cap->svc_id, PTR_TO_LONG(ops->ds_data_cb),
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen PTR_TO_LONG(ops->cb_arg));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_enter(&ds_svcs.lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* check if the service is already registered */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (i_ds_hdl_lookup(cap->svc_id, is_client, NULL, 1) == 1) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* already registered */
e9406929914976efdccb875f94e90e85cdb076e3Mike Christensen DS_DBG_USR(CE_NOTE, "Service '%s'/%s already registered" DS_EOL,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cap->svc_id,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (flags & DSSF_ISCLIENT) ? "client" : "service");
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&ds_svcs.lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (EALREADY);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc = ds_alloc_svc();
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (is_client) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_HDL_SET_ISCLIENT(svc->hdl);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc->state = DS_SVC_FREE;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc->svc_hdl = DS_BADHDL1;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc->flags = flags;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc->drvi = instance;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc->drv_psp = NULL;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
f4b11d030c994c1de099f1a482ffc7c709a0aaa1Mike Christensen * Check for loopback. "pri" is a legacy service that assumes it
f4b11d030c994c1de099f1a482ffc7c709a0aaa1Mike Christensen * will never use loopback mode.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
f4b11d030c994c1de099f1a482ffc7c709a0aaa1Mike Christensen if (strcmp(cap->svc_id, "pri") == 0) {
f4b11d030c994c1de099f1a482ffc7c709a0aaa1Mike Christensen is_loopback = 0;
f4b11d030c994c1de099f1a482ffc7c709a0aaa1Mike Christensen } else if (i_ds_hdl_lookup(cap->svc_id, is_client == 0, &lb_hdl, 1)
f4b11d030c994c1de099f1a482ffc7c709a0aaa1Mike Christensen == 1) {
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen if ((rv = ds_loopback_set_svc(svc, cap, &lb_hdl)) != 0) {
f4b11d030c994c1de099f1a482ffc7c709a0aaa1Mike Christensen DS_DBG_USR(CE_NOTE, "%s: ds_loopback_set_svc '%s' err "
f4b11d030c994c1de099f1a482ffc7c709a0aaa1Mike Christensen " (%d)" DS_EOL, __func__, cap->svc_id, rv);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&ds_svcs.lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (rv);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen is_loopback = 1;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen } else
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen is_loopback = 0;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* copy over all the client information */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (void) memcpy(&svc->cap, cap, sizeof (ds_capability_t));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* make a copy of the service name */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc->cap.svc_id = ds_strdup(cap->svc_id);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* make a copy of the version array */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc->cap.vers = DS_MALLOC(cap->nvers * sizeof (ds_ver_t));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (void) memcpy(svc->cap.vers, cap->vers, cap->nvers * sizeof (ds_ver_t));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* copy the client ops vector */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (void) memcpy(&svc->ops, ops, sizeof (ds_clnt_ops_t));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc->state = DS_SVC_INACTIVE;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc->ver_idx = 0;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_PORTSET_DUP(svc->avail, ds_allports);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_PORTSET_SETNULL(svc->tried);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_svcs.nsvcs++;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen hdl = svc->hdl;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * kludge to allow user callback code to get handle and user args.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Make sure the callback arg points to the svc structure.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((flags & DSSF_ISUSER) != 0) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_cbarg_set_cookie(svc);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (is_loopback) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_loopback_register(hdl);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_loopback_register(lb_hdl);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * If this is a client or a non-loopback service provider, send
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * out register requests.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (!is_loopback || (flags & DSSF_ISCLIENT) != 0)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (void) ds_svc_register(svc, NULL);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (hdlp) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen *hdlp = hdl;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&ds_svcs.lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_USR(CE_NOTE, "%s: service '%s' assigned handle 0x%09lx" DS_EOL,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen __func__, svc->cap.svc_id, hdl);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (0);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * ds_cap_init interface for previous revision.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenint
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_cap_init(ds_capability_t *cap, ds_clnt_ops_t *ops)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (ds_ucap_init(cap, ops, 0, DS_INVALID_INSTANCE, NULL));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Interface for ds_unreg_hdl in lds driver.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenint
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_unreg_hdl(ds_svc_hdl_t hdl)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_svc_t *svc;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen int is_loopback;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_svc_hdl_t lb_hdl;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_USR(CE_NOTE, "%s: hdl=0x%09lx" DS_EOL, __func__, hdl);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_enter(&ds_svcs.lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((svc = ds_get_svc(hdl)) == NULL) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&ds_svcs.lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_USR(CE_NOTE, "%s: unknown hdl: 0x%llx" DS_EOL, __func__,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (u_longlong_t)hdl);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (ENXIO);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_USR(CE_NOTE, "%s: svcid='%s', hdl=0x%llx" DS_EOL, __func__,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc->cap.svc_id, (u_longlong_t)svc->hdl);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc->state = DS_SVC_UNREG_PENDING;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen is_loopback = ((svc->flags & DSSF_LOOPBACK) != 0);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen lb_hdl = svc->svc_hdl;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (svc->port) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (void) ds_send_unreg_req(svc);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (void) ds_svc_unregister(svc, svc->port);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_delete_svc_entry(svc);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (is_loopback) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_loopback_unregister(lb_hdl);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&ds_svcs.lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (0);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenint
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_cap_fini(ds_capability_t *cap)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_svc_hdl_t hdl;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen int rv;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen uint_t nhdls = 0;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG(CE_NOTE, "%s: '%s'" DS_EOL, __func__, cap->svc_id);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((rv = ds_hdl_lookup(cap->svc_id, 0, &hdl, 1, &nhdls)) != 0) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG(CE_NOTE, "%s: ds_hdl_lookup '%s' err (%d)" DS_EOL,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen __func__, cap->svc_id, rv);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (rv);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (nhdls == 0) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG(CE_NOTE, "%s: no such service '%s'" DS_EOL,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen __func__, cap->svc_id);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (ENXIO);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((rv = ds_is_my_hdl(hdl, DS_INVALID_INSTANCE)) != 0) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG(CE_NOTE, "%s: ds_is_my_handle err (%d)" DS_EOL, __func__,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen rv);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (rv);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((rv = ds_unreg_hdl(hdl)) != 0) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG(CE_NOTE, "%s: ds_unreg_hdl err (%d)" DS_EOL, __func__,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen rv);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (rv);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (0);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenint
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_cap_send(ds_svc_hdl_t hdl, void *buf, size_t len)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen int rv;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_hdr_t *hdr;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen caddr_t msg;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen size_t msglen;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen size_t hdrlen;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen caddr_t payload;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_svc_t *svc;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_port_t *port;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_data_handle_t *data;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_svc_hdl_t svc_hdl;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen int is_client = 0;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG(CE_NOTE, "%s: hdl: 0x%llx, buf: %lx, len: %ld" DS_EOL, __func__,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (u_longlong_t)hdl, (ulong_t)buf, len);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_enter(&ds_svcs.lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((svc = ds_get_svc(hdl)) == NULL) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen cmn_err(CE_WARN, "%s: invalid handle 0x%llx" DS_EOL, __func__,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (u_longlong_t)hdl);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&ds_svcs.lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (ENXIO);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (svc->state != DS_SVC_ACTIVE) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* channel is up, but svc is not registered */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG(CE_NOTE, "%s: invalid service state 0x%x" DS_EOL,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen __func__, svc->state);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&ds_svcs.lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (ENOTCONN);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (svc->flags & DSSF_LOOPBACK) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen hdl = svc->svc_hdl;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&ds_svcs.lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_loopback_send(hdl, buf, len);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (0);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((port = svc->port) == NULL) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG(CE_NOTE, "%s: service '%s' not associated with a port"
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_EOL, __func__, svc->cap.svc_id);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&ds_svcs.lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (ECONNRESET);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (svc->flags & DSSF_ISCLIENT) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen is_client = 1;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc_hdl = svc->svc_hdl;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&ds_svcs.lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* check that the LDC channel is ready */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (port->ldc.state != LDC_UP) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG(CE_NOTE, "%s: LDC channel is not up" DS_EOL, __func__);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (ECONNRESET);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen hdrlen = DS_HDR_SZ + sizeof (ds_data_handle_t);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen msg = DS_MALLOC(len + hdrlen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen hdr = (ds_hdr_t *)msg;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen payload = msg + hdrlen;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen msglen = len + hdrlen;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen hdr->payload_len = len + sizeof (ds_data_handle_t);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen hdr->msg_type = DS_DATA;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen data = (ds_data_handle_t *)(msg + DS_HDR_SZ);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (is_client) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen data->svc_handle = svc_hdl;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen } else {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen data->svc_handle = hdl;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((buf != NULL) && (len != 0)) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (void) memcpy(payload, buf, len);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_PRCL(CE_NOTE, "ds@%lx: data>: hdl=0x%llx, len=%ld, "
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen " payload_len=%d" DS_EOL, PORTID(port), (u_longlong_t)svc->hdl,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen msglen, hdr->payload_len);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DUMP_MSG(DS_DBG_FLAG_PRCL, msg, msglen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((rv = ds_send_msg(port, msg, msglen)) != 0) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen rv = (rv == EIO) ? ECONNRESET : rv;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_FREE(msg, msglen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (rv);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenvoid
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_port_common_init(ds_port_t *port)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen int rv;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((port->flags & DS_PORT_MUTEX_INITED) == 0) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_init(&port->lock, NULL, MUTEX_DRIVER, NULL);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_init(&port->tx_lock, NULL, MUTEX_DRIVER, NULL);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_init(&port->rcv_lock, NULL, MUTEX_DRIVER, NULL);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen port->flags |= DS_PORT_MUTEX_INITED;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen port->state = DS_PORT_INIT;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_PORTSET_ADD(ds_allports, port->id);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_sys_port_init(port);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_enter(&port->lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen rv = ds_ldc_init(port);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&port->lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * If LDC successfully init'ed, try to kick off protocol for this port.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (rv == 0) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_handle_up_event(port);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenvoid
beba1dd881728e806abb8621851ae851da168a08Mike Christensends_port_common_fini(ds_port_t *port)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
beba1dd881728e806abb8621851ae851da168a08Mike Christensen ASSERT(MUTEX_HELD(&port->lock));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
beba1dd881728e806abb8621851ae851da168a08Mike Christensen port->state = DS_PORT_FREE;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_PORTSET_DEL(ds_allports, port->id);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_sys_port_fini(port);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Initialize table of registered service classes
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenvoid
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_init_svcs_tbl(uint_t nentries)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen int tblsz;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_svcs.maxsvcs = nentries;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tblsz = ds_svcs.maxsvcs * sizeof (ds_svc_t *);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_svcs.tbl = (ds_svc_t **)DS_MALLOC(tblsz);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_svcs.nsvcs = 0;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Find the max and min version supported.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Hacked from zeus workspace, support.c
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenmin_max_versions(int num_versions, ds_ver_t *sup_versionsp,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen uint16_t *min_major, uint16_t *max_major)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen int i;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen *min_major = sup_versionsp[0].major;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen *max_major = *min_major;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen for (i = 1; i < num_versions; i++) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (sup_versionsp[i].major < *min_major)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen *min_major = sup_versionsp[i].major;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (sup_versionsp[i].major > *max_major)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen *max_major = sup_versionsp[i].major;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Check whether the major and minor numbers requested by the peer can be
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * satisfied. If the requested major is supported, true is returned, and the
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * agreed minor is returned in new_minor. If the requested major is not
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * supported, the routine returns false, and the closest major is returned in
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * *new_major, upon which the peer should re-negotiate. The closest major is
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * the just lower that the requested major number.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen *
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Hacked from zeus workspace, support.c
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenboolean_t
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensennegotiate_version(int num_versions, ds_ver_t *sup_versionsp,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen uint16_t req_major, uint16_t *new_majorp, uint16_t *new_minorp)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen int i;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen uint16_t major, lower_major;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen uint16_t min_major = 0, max_major;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen boolean_t found_match = B_FALSE;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen min_max_versions(num_versions, sup_versionsp, &min_major, &max_major);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG(CE_NOTE, "negotiate_version: req_major = %u, min = %u, max = %u"
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_EOL, req_major, min_major, max_major);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * If the minimum version supported is greater than
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * the version requested, return the lowest version
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * supported
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (min_major > req_major) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen *new_majorp = min_major;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (B_FALSE);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * If the largest version supported is lower than
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * the version requested, return the largest version
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * supported
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (max_major < req_major) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen *new_majorp = max_major;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (B_FALSE);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Now we know that the requested version lies between the
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * min and max versions supported. Check if the requested
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * major can be found in supported versions.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen lower_major = min_major;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen for (i = 0; i < num_versions; i++) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen major = sup_versionsp[i].major;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (major == req_major) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen found_match = B_TRUE;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen *new_majorp = req_major;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen *new_minorp = sup_versionsp[i].minor;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen break;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen } else {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((major < req_major) && (major > lower_major))
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen lower_major = major;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * If no match is found, return the closest available number
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (!found_match)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen *new_majorp = lower_major;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (found_match);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Specific errno's that are used by ds.c and ldc.c
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic struct {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen int ds_errno;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen char *estr;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen} ds_errno_to_str_tab[] = {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen { EIO, "I/O error" },
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen { ENXIO, "No such device or address" },
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen { EAGAIN, "Resource temporarily unavailable" },
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen { ENOMEM, "Not enough space" },
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen { EACCES, "Permission denied" },
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen { EFAULT, "Bad address" },
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen { EBUSY, "Device busy" },
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen { EINVAL, "Invalid argument" },
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen { ENOSPC, "No space left on device" },
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen { ENOMSG, "No message of desired type" },
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#ifdef ECHRNG
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen { ECHRNG, "Channel number out of range" },
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen#endif
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen { ENOTSUP, "Operation not supported" },
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen { EMSGSIZE, "Message too long" },
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen { EADDRINUSE, "Address already in use" },
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen { ECONNRESET, "Connection reset by peer" },
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen { ENOBUFS, "No buffer space available" },
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen { ENOTCONN, "Socket is not connected" },
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen { ECONNREFUSED, "Connection refused" },
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen { EALREADY, "Operation already in progress" },
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen { 0, NULL },
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen};
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenchar *
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_errno_to_str(int ds_errno, char *ebuf)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen int i, en;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen for (i = 0; (en = ds_errno_to_str_tab[i].ds_errno) != 0; i++) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (en == ds_errno) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (void) strcpy(ebuf, ds_errno_to_str_tab[i].estr);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (ebuf);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (void) sprintf(ebuf, "ds_errno (%d)", ds_errno);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (ebuf);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_loopback_register(ds_svc_hdl_t hdl)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen ds_ver_t ds_ver;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_svc_t *svc;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ASSERT(MUTEX_HELD(&ds_svcs.lock));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_LOOP(CE_NOTE, "%s: entered hdl: 0x%llx" DS_EOL, __func__,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (u_longlong_t)hdl);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((svc = ds_get_svc(hdl)) == NULL) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_LOOP(CE_NOTE, "%s: invalid hdl: 0x%llx" DS_EOL, __func__,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (u_longlong_t)hdl);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc->state = DS_SVC_ACTIVE;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (svc->ops.ds_reg_cb) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_LOOP(CE_NOTE, "%s: loopback regcb: hdl: 0x%llx" DS_EOL,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen __func__, (u_longlong_t)hdl);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_ver.major = svc->ver.major;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_ver.minor = svc->ver.minor;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (*svc->ops.ds_reg_cb)(svc->ops.cb_arg, &ds_ver, hdl);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_loopback_unregister(ds_svc_hdl_t hdl)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_svc_t *svc;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ASSERT(MUTEX_HELD(&ds_svcs.lock));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((svc = ds_get_svc(hdl)) == NULL) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_LOOP(CE_NOTE, "%s: invalid hdl: 0x%llx" DS_EOL, __func__,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (u_longlong_t)hdl);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_LOOP(CE_NOTE, "%s: entered hdl: 0x%llx" DS_EOL, __func__,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (u_longlong_t)hdl);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc->flags &= ~DSSF_LOOPBACK;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc->svc_hdl = DS_BADHDL2;
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen svc->state = DS_SVC_INACTIVE;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (svc->ops.ds_unreg_cb) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_LOOP(CE_NOTE, "%s: loopback unregcb: hdl: 0x%llx" DS_EOL,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen __func__, (u_longlong_t)hdl);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (*svc->ops.ds_unreg_cb)(svc->ops.cb_arg);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_loopback_send(ds_svc_hdl_t hdl, void *buf, size_t buflen)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_svc_t *svc;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_enter(&ds_svcs.lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((svc = ds_get_svc(hdl)) == NULL) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&ds_svcs.lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_LOOP(CE_NOTE, "%s: invalid hdl: 0x%llx" DS_EOL, __func__,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (u_longlong_t)hdl);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&ds_svcs.lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_LOOP(CE_NOTE, "%s: entered hdl: 0x%llx" DS_EOL, __func__,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (u_longlong_t)hdl);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (svc->ops.ds_data_cb) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_LOOP(CE_NOTE, "%s: loopback datacb hdl: 0x%llx" DS_EOL,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen __func__, (u_longlong_t)hdl);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (*svc->ops.ds_data_cb)(svc->ops.cb_arg, buf, buflen);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic int
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensends_loopback_set_svc(ds_svc_t *svc, ds_capability_t *cap, ds_svc_hdl_t *lb_hdlp)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_svc_t *lb_svc;
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen ds_svc_hdl_t lb_hdl = *lb_hdlp;
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen int i;
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen int match = 0;
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen uint16_t new_major;
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen uint16_t new_minor;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((lb_svc = ds_get_svc(lb_hdl)) == NULL) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_LOOP(CE_NOTE, "%s: loopback: hdl: 0x%llx invalid" DS_EOL,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen __func__, (u_longlong_t)lb_hdl);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (ENXIO);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen /* negotiate a version between loopback services, if possible */
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen for (i = 0; i < lb_svc->cap.nvers && match == 0; i++) {
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen match = negotiate_version(cap->nvers, cap->vers,
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen lb_svc->cap.vers[i].major, &new_major, &new_minor);
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen }
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen if (!match) {
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen DS_DBG_LOOP(CE_NOTE, "%s: loopback version negotiate failed"
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen DS_EOL, __func__);
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen return (ENOTSUP);
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen }
bca70f54b47e1896668cd05d64cdf448a9582d74Mike Christensen
bca70f54b47e1896668cd05d64cdf448a9582d74Mike Christensen /*
bca70f54b47e1896668cd05d64cdf448a9582d74Mike Christensen * If a client service is not inactive, clone it. If the service is
bca70f54b47e1896668cd05d64cdf448a9582d74Mike Christensen * not a client service and has a reg req pending (usually from OBP
bca70f54b47e1896668cd05d64cdf448a9582d74Mike Christensen * in boot state not acking/nacking reg req's), it's OK to ignore that,
bca70f54b47e1896668cd05d64cdf448a9582d74Mike Christensen * since there are never multiple service clients. Also reg req pending
bca70f54b47e1896668cd05d64cdf448a9582d74Mike Christensen * only happens for non-client services, so it's OK to skip
bca70f54b47e1896668cd05d64cdf448a9582d74Mike Christensen * this block that does client service cloning.
bca70f54b47e1896668cd05d64cdf448a9582d74Mike Christensen */
bca70f54b47e1896668cd05d64cdf448a9582d74Mike Christensen if (lb_svc->state != DS_SVC_INACTIVE &&
bca70f54b47e1896668cd05d64cdf448a9582d74Mike Christensen lb_svc->state != DS_SVC_REG_PENDING) {
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen DS_DBG_LOOP(CE_NOTE, "%s: loopback active: hdl: 0x%llx"
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_EOL, __func__, (u_longlong_t)lb_hdl);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((lb_svc->flags & DSSF_ISCLIENT) == 0) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_LOOP(CE_NOTE, "%s: loopback busy hdl: 0x%llx"
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_EOL, __func__, (u_longlong_t)lb_hdl);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (EBUSY);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen svc->state = DS_SVC_INACTIVE; /* prevent alloc'ing svc */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen lb_svc = ds_svc_clone(lb_svc);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_LOOP(CE_NOTE, "%s: loopback clone: ohdl: 0x%llx "
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen "nhdl: 0x%llx" DS_EOL, __func__, (u_longlong_t)lb_hdl,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (u_longlong_t)lb_svc->hdl);
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen *lb_hdlp = lb_svc->hdl;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc->flags |= DSSF_LOOPBACK;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc->svc_hdl = lb_svc->hdl;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc->port = NULL;
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen svc->ver.major = new_major;
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen svc->ver.minor = new_minor;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen lb_svc->flags |= DSSF_LOOPBACK;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen lb_svc->svc_hdl = svc->hdl;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen lb_svc->port = NULL;
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen lb_svc->ver.major = new_major;
a600f50d43405fe4fd9ab16cc92b28df19656392Mike Christensen lb_svc->ver.minor = new_minor;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_LOOP(CE_NOTE, "%s: setting loopback between: 0x%llx and 0x%llx"
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_EOL, __func__, (u_longlong_t)svc->hdl,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (u_longlong_t)lb_svc->hdl);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (0);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic ds_svc_t *
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_find_clnt_svc_by_hdl_port(ds_svc_hdl_t hdl, ds_port_t *port)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen int idx;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_svc_t *svc;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_PRCL(CE_NOTE, "ds@%lx: %s looking up clnt hdl: 0x%llx" DS_EOL,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen PORTID(port), __func__, (u_longlong_t)hdl);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ASSERT(MUTEX_HELD(&ds_svcs.lock));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* walk every table entry */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen for (idx = 0; idx < ds_svcs.maxsvcs; idx++) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc = ds_svcs.tbl[idx];
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (DS_SVC_ISFREE(svc))
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen continue;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((svc->flags & DSSF_ISCLIENT) != 0 &&
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc->svc_hdl == hdl && svc->port == port) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_PRCL(CE_NOTE, "ds@%lx: %s found clnt hdl "
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen "0x%llx: svc%d" DS_EOL, PORTID(port), __func__,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (u_longlong_t)hdl, (uint_t)DS_HDL2IDX(svc->hdl));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (svc);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_PRCL(CE_NOTE, "ds@%lx: %s clnt hdl: 0x%llx not found" DS_EOL,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen PORTID(port), __func__, (u_longlong_t)hdl);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (NULL);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic ds_svc_t *
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_svc_clone(ds_svc_t *svc)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_svc_t *newsvc;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_svc_hdl_t hdl;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ASSERT(svc->flags & DSSF_ISCLIENT);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen newsvc = ds_alloc_svc();
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* Can only clone clients for now */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen hdl = newsvc->hdl | DS_HDL_ISCLIENT_BIT;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_DBG_USR(CE_NOTE, "%s: cloning client: old hdl: 0x%llx new hdl: "
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen "0x%llx" DS_EOL, __func__, (u_longlong_t)svc->hdl,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (u_longlong_t)hdl);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (void) memcpy(newsvc, svc, sizeof (ds_svc_t));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen newsvc->hdl = hdl;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen newsvc->flags &= ~DSSF_LOOPBACK;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen newsvc->port = NULL;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen newsvc->svc_hdl = DS_BADHDL2;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen newsvc->cap.svc_id = ds_strdup(svc->cap.svc_id);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen newsvc->cap.vers = DS_MALLOC(svc->cap.nvers * sizeof (ds_ver_t));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (void) memcpy(newsvc->cap.vers, svc->cap.vers,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc->cap.nvers * sizeof (ds_ver_t));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Kludge to allow lds driver user callbacks to get access to current
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * svc structure. Arg could be index to svc table or some other piece
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * of info to get to the svc table entry.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (newsvc->flags & DSSF_ISUSER) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen newsvc->ops.cb_arg = (ds_cb_arg_t)(newsvc);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (newsvc);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Internal handle lookup function.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic int
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christenseni_ds_hdl_lookup(char *service, uint_t is_client, ds_svc_hdl_t *hdlp,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen uint_t maxhdls)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen int idx;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen int nhdls = 0;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_svc_t *svc;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen uint32_t client_flag = is_client ? DSSF_ISCLIENT : 0;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ASSERT(MUTEX_HELD(&ds_svcs.lock));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen for (idx = 0; idx < ds_svcs.maxsvcs && nhdls < maxhdls; idx++) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc = ds_svcs.tbl[idx];
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (DS_SVC_ISFREE(svc))
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen continue;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (strcmp(svc->cap.svc_id, service) == 0 &&
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen (svc->flags & DSSF_ISCLIENT) == client_flag) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if (hdlp != NULL && nhdls < maxhdls) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen hdlp[nhdls] = svc->hdl;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen nhdls++;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen } else {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen nhdls++;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (nhdls);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Interface for ds_hdl_lookup in lds driver.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenint
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_hdl_lookup(char *service, uint_t is_client, ds_svc_hdl_t *hdlp,
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen uint_t maxhdls, uint_t *nhdlsp)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_enter(&ds_svcs.lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen *nhdlsp = i_ds_hdl_lookup(service, is_client, hdlp, maxhdls);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen mutex_exit(&ds_svcs.lock);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen return (0);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen/*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * After an UNREG REQ, check if this is a client service with multiple
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * handles. If it is, then we can eliminate this entry.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_check_for_dup_services(ds_svc_t *svc)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen if ((svc->flags & DSSF_ISCLIENT) != 0 &&
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc->state == DS_SVC_INACTIVE &&
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen i_ds_hdl_lookup(svc->cap.svc_id, 1, NULL, 2) == 2) {
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_delete_svc_entry(svc);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen }
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensenstatic void
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensends_delete_svc_entry(ds_svc_t *svc)
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen{
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_svc_hdl_t tmp_hdl;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ASSERT(MUTEX_HELD(&ds_svcs.lock));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /*
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * Clear out the structure, but do not deallocate the
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen * memory. It can be reused for the next registration.
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_FREE(svc->cap.svc_id, strlen(svc->cap.svc_id) + 1);
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen DS_FREE(svc->cap.vers, svc->cap.nvers * sizeof (ds_ver_t));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* save the handle to prevent reuse */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen tmp_hdl = svc->hdl;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen bzero((void *)svc, sizeof (ds_svc_t));
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen /* initialize for next use */
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc->hdl = tmp_hdl;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen svc->state = DS_SVC_FREE;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen ds_svcs.nsvcs--;
30588217a56ff2c9137248fb2e5065c4f0101459Mike Christensen}