1229997Sken/*-
2229997Sken * Copyright (c) 2003 Silicon Graphics International Corp.
3229997Sken * All rights reserved.
4229997Sken *
5229997Sken * Redistribution and use in source and binary forms, with or without
6229997Sken * modification, are permitted provided that the following conditions
7229997Sken * are met:
8229997Sken * 1. Redistributions of source code must retain the above copyright
9229997Sken *    notice, this list of conditions, and the following disclaimer,
10229997Sken *    without modification.
11229997Sken * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12229997Sken *    substantially similar to the "NO WARRANTY" disclaimer below
13229997Sken *    ("Disclaimer") and any redistribution must be conditioned upon
14229997Sken *    including a substantially similar Disclaimer requirement for further
15229997Sken *    binary redistribution.
16229997Sken *
17229997Sken * NO WARRANTY
18229997Sken * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19229997Sken * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20229997Sken * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
21229997Sken * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22229997Sken * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23229997Sken * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24229997Sken * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25229997Sken * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26229997Sken * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
27229997Sken * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28229997Sken * POSSIBILITY OF SUCH DAMAGES.
29229997Sken *
30229997Sken * $Id: //depot/users/kenm/FreeBSD-test2/sys/cam/ctl/ctl_backend.c#3 $
31229997Sken */
32229997Sken/*
33229997Sken * CTL backend driver registration routines
34229997Sken *
35229997Sken * Author: Ken Merry <ken@FreeBSD.org>
36229997Sken */
37229997Sken
38229997Sken#include <sys/cdefs.h>
39229997Sken__FBSDID("$FreeBSD: stable/10/sys/cam/ctl/ctl_backend.c 313369 2017-02-07 01:56:26Z mav $");
40229997Sken
41229997Sken#include <sys/param.h>
42229997Sken#include <sys/systm.h>
43229997Sken#include <sys/kernel.h>
44229997Sken#include <sys/types.h>
45229997Sken#include <sys/malloc.h>
46229997Sken#include <sys/lock.h>
47229997Sken#include <sys/mutex.h>
48229997Sken#include <sys/condvar.h>
49229997Sken#include <sys/queue.h>
50233963Sken#include <sys/sysctl.h>
51229997Sken
52229997Sken#include <cam/scsi/scsi_all.h>
53229997Sken#include <cam/scsi/scsi_da.h>
54229997Sken#include <cam/ctl/ctl_io.h>
55229997Sken#include <cam/ctl/ctl.h>
56229997Sken#include <cam/ctl/ctl_frontend.h>
57229997Sken#include <cam/ctl/ctl_backend.h>
58229997Sken#include <cam/ctl/ctl_ioctl.h>
59229997Sken#include <cam/ctl/ctl_ha.h>
60229997Sken#include <cam/ctl/ctl_private.h>
61229997Sken#include <cam/ctl/ctl_debug.h>
62229997Sken
63229997Skenextern struct ctl_softc *control_softc;
64229997Sken
65229997Skenint
66229997Skenctl_backend_register(struct ctl_backend_driver *be)
67229997Sken{
68288795Smav	struct ctl_softc *softc = control_softc;
69229997Sken	struct ctl_backend_driver *be_tmp;
70313369Smav	int error;
71229997Sken
72313369Smav	/* Sanity check, make sure this isn't a duplicate registration. */
73276614Smav	mtx_lock(&softc->ctl_lock);
74276614Smav	STAILQ_FOREACH(be_tmp, &softc->be_list, links) {
75229997Sken		if (strcmp(be_tmp->name, be->name) == 0) {
76276614Smav			mtx_unlock(&softc->ctl_lock);
77229997Sken			return (-1);
78229997Sken		}
79229997Sken	}
80276614Smav	mtx_unlock(&softc->ctl_lock);
81313369Smav#ifdef CS_BE_CONFIG_MOVE_DONE_IS_NOT_USED
82313369Smav	be->config_move_done = ctl_config_move_done;
83313369Smav#endif
84313369Smav	be->num_luns = 0;
85229997Sken
86313369Smav	/* Call the backend's initialization routine. */
87313369Smav	if (be->init != NULL) {
88313369Smav		if ((error = be->init()) != 0) {
89313369Smav			printf("%s backend init error: %d\n",
90313369Smav			    be->name, error);
91313369Smav			return (error);
92313369Smav		}
93313369Smav	}
94229997Sken
95276614Smav	mtx_lock(&softc->ctl_lock);
96276614Smav	STAILQ_INSERT_TAIL(&softc->be_list, be, links);
97276614Smav	softc->num_backends++;
98276614Smav	mtx_unlock(&softc->ctl_lock);
99229997Sken	return (0);
100229997Sken}
101229997Sken
102229997Skenint
103229997Skenctl_backend_deregister(struct ctl_backend_driver *be)
104229997Sken{
105288795Smav	struct ctl_softc *softc = control_softc;
106313369Smav	int error;
107229997Sken
108313369Smav	/* Call the backend's shutdown routine. */
109313369Smav	if (be->shutdown != NULL) {
110313369Smav		if ((error = be->shutdown()) != 0) {
111313369Smav			printf("%s backend shutdown error: %d\n",
112313369Smav			    be->name, error);
113313369Smav			return (error);
114313369Smav		}
115229997Sken	}
116229997Sken
117313369Smav	mtx_lock(&softc->ctl_lock);
118276614Smav	STAILQ_REMOVE(&softc->be_list, be, ctl_backend_driver, links);
119276614Smav	softc->num_backends--;
120276614Smav	mtx_unlock(&softc->ctl_lock);
121229997Sken	return (0);
122229997Sken}
123229997Sken
124229997Skenstruct ctl_backend_driver *
125229997Skenctl_backend_find(char *backend_name)
126229997Sken{
127288795Smav	struct ctl_softc *softc = control_softc;
128229997Sken	struct ctl_backend_driver *be_tmp;
129229997Sken
130276614Smav	mtx_lock(&softc->ctl_lock);
131276614Smav	STAILQ_FOREACH(be_tmp, &softc->be_list, links) {
132229997Sken		if (strcmp(be_tmp->name, backend_name) == 0) {
133276614Smav			mtx_unlock(&softc->ctl_lock);
134229997Sken			return (be_tmp);
135229997Sken		}
136229997Sken	}
137276614Smav	mtx_unlock(&softc->ctl_lock);
138229997Sken
139229997Sken	return (NULL);
140229997Sken}
141229997Sken
142268143Smavvoid
143268678Smavctl_init_opts(ctl_options_t *opts, int num_args, struct ctl_be_arg *args)
144268143Smav{
145268678Smav	struct ctl_option *opt;
146268143Smav	int i;
147268143Smav
148268678Smav	STAILQ_INIT(opts);
149268678Smav	for (i = 0; i < num_args; i++) {
150268681Smav		if ((args[i].flags & CTL_BEARG_RD) == 0)
151268681Smav			continue;
152268681Smav		if ((args[i].flags & CTL_BEARG_ASCII) == 0)
153268681Smav			continue;
154268143Smav		opt = malloc(sizeof(*opt), M_CTL, M_WAITOK);
155288728Smav		opt->name = strdup(args[i].kname, M_CTL);
156288728Smav		opt->value = strdup(args[i].kvalue, M_CTL);
157268678Smav		STAILQ_INSERT_TAIL(opts, opt, links);
158268143Smav	}
159268143Smav}
160268143Smav
161268143Smavvoid
162288728Smavctl_update_opts(ctl_options_t *opts, int num_args, struct ctl_be_arg *args)
163288728Smav{
164288728Smav	struct ctl_option *opt;
165288728Smav	int i;
166288728Smav
167288728Smav	for (i = 0; i < num_args; i++) {
168288728Smav		if ((args[i].flags & CTL_BEARG_RD) == 0)
169288728Smav			continue;
170288728Smav		if ((args[i].flags & CTL_BEARG_ASCII) == 0)
171288728Smav			continue;
172288728Smav		STAILQ_FOREACH(opt, opts, links) {
173288728Smav			if (strcmp(opt->name, args[i].kname) == 0)
174288728Smav				break;
175288728Smav		}
176288728Smav		if (args[i].kvalue != NULL &&
177288728Smav		    ((char *)args[i].kvalue)[0] != 0) {
178288728Smav			if (opt) {
179288728Smav				free(opt->value, M_CTL);
180288728Smav				opt->value = strdup(args[i].kvalue, M_CTL);
181288728Smav			} else {
182288728Smav				opt = malloc(sizeof(*opt), M_CTL, M_WAITOK);
183288728Smav				opt->name = strdup(args[i].kname, M_CTL);
184288728Smav				opt->value = strdup(args[i].kvalue, M_CTL);
185288728Smav				STAILQ_INSERT_TAIL(opts, opt, links);
186288728Smav			}
187288728Smav		} else if (opt) {
188288728Smav			STAILQ_REMOVE(opts, opt, ctl_option, links);
189288728Smav			free(opt->name, M_CTL);
190288728Smav			free(opt->value, M_CTL);
191288728Smav			free(opt, M_CTL);
192288728Smav		}
193288728Smav	}
194288728Smav}
195288728Smav
196288728Smavvoid
197268678Smavctl_free_opts(ctl_options_t *opts)
198268143Smav{
199268678Smav	struct ctl_option *opt;
200268143Smav
201268678Smav	while ((opt = STAILQ_FIRST(opts)) != NULL) {
202268678Smav		STAILQ_REMOVE_HEAD(opts, links);
203268143Smav		free(opt->name, M_CTL);
204268143Smav		free(opt->value, M_CTL);
205268143Smav		free(opt, M_CTL);
206268143Smav	}
207268143Smav}
208268143Smav
209268143Smavchar *
210268678Smavctl_get_opt(ctl_options_t *opts, const char *name)
211268143Smav{
212268678Smav	struct ctl_option *opt;
213268143Smav
214268678Smav	STAILQ_FOREACH(opt, opts, links) {
215268143Smav		if (strcmp(opt->name, name) == 0) {
216268143Smav			return (opt->value);
217268143Smav		}
218268143Smav	}
219268143Smav	return (NULL);
220268143Smav}
221308078Smav
222308078Smavint
223308078Smavctl_get_opt_number(ctl_options_t *opts, const char *name, uint64_t *val)
224308078Smav{
225308078Smav	const char *value;
226308078Smav
227308078Smav	value = ctl_get_opt(opts, name);
228308078Smav	if (value == NULL)
229308078Smav		return (-2);
230308078Smav	return (ctl_expand_number(value, val));
231308078Smav}
232