xref: /titanic_44/usr/src/cmd/ndmpd/ndmp/ndmpd_scsi.c (revision 2654012f83cec5dc15b61dfe3e4a4915f186e7a6)
1*2654012fSReza Sabdar /*
2*2654012fSReza Sabdar  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
3*2654012fSReza Sabdar  * Use is subject to license terms.
4*2654012fSReza Sabdar  */
5*2654012fSReza Sabdar 
6*2654012fSReza Sabdar /*
7*2654012fSReza Sabdar  * BSD 3 Clause License
8*2654012fSReza Sabdar  *
9*2654012fSReza Sabdar  * Copyright (c) 2007, The Storage Networking Industry Association.
10*2654012fSReza Sabdar  *
11*2654012fSReza Sabdar  * Redistribution and use in source and binary forms, with or without
12*2654012fSReza Sabdar  * modification, are permitted provided that the following conditions
13*2654012fSReza Sabdar  * are met:
14*2654012fSReza Sabdar  * 	- Redistributions of source code must retain the above copyright
15*2654012fSReza Sabdar  *	  notice, this list of conditions and the following disclaimer.
16*2654012fSReza Sabdar  *
17*2654012fSReza Sabdar  * 	- Redistributions in binary form must reproduce the above copyright
18*2654012fSReza Sabdar  *	  notice, this list of conditions and the following disclaimer in
19*2654012fSReza Sabdar  *	  the documentation and/or other materials provided with the
20*2654012fSReza Sabdar  *	  distribution.
21*2654012fSReza Sabdar  *
22*2654012fSReza Sabdar  *	- Neither the name of The Storage Networking Industry Association (SNIA)
23*2654012fSReza Sabdar  *	  nor the names of its contributors may be used to endorse or promote
24*2654012fSReza Sabdar  *	  products derived from this software without specific prior written
25*2654012fSReza Sabdar  *	  permission.
26*2654012fSReza Sabdar  *
27*2654012fSReza Sabdar  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
28*2654012fSReza Sabdar  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29*2654012fSReza Sabdar  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30*2654012fSReza Sabdar  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
31*2654012fSReza Sabdar  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32*2654012fSReza Sabdar  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33*2654012fSReza Sabdar  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34*2654012fSReza Sabdar  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35*2654012fSReza Sabdar  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36*2654012fSReza Sabdar  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37*2654012fSReza Sabdar  * POSSIBILITY OF SUCH DAMAGE.
38*2654012fSReza Sabdar  */
39*2654012fSReza Sabdar /* Copyright (c) 2007, The Storage Networking Industry Association. */
40*2654012fSReza Sabdar /* Copyright (c) 1996, 1997 PDC, Network Appliance. All Rights Reserved */
41*2654012fSReza Sabdar 
42*2654012fSReza Sabdar #include <sys/types.h>
43*2654012fSReza Sabdar #include <ctype.h>
44*2654012fSReza Sabdar #include <errno.h>
45*2654012fSReza Sabdar #include <fcntl.h>
46*2654012fSReza Sabdar #include <stdlib.h>
47*2654012fSReza Sabdar #include "ndmpd_common.h"
48*2654012fSReza Sabdar #include "ndmpd.h"
49*2654012fSReza Sabdar #include <string.h>
50*2654012fSReza Sabdar #include <sys/scsi/impl/uscsi.h>
51*2654012fSReza Sabdar #include <sys/scsi/scsi.h>
52*2654012fSReza Sabdar 
53*2654012fSReza Sabdar static void scsi_open_send_reply(ndmp_connection_t *connection, int err);
54*2654012fSReza Sabdar static void common_open(ndmp_connection_t *connection, char *devname);
55*2654012fSReza Sabdar static void common_set_target(ndmp_connection_t *connection, char *device,
56*2654012fSReza Sabdar     ushort_t controller, ushort_t sid, ushort_t lun);
57*2654012fSReza Sabdar 
58*2654012fSReza Sabdar 
59*2654012fSReza Sabdar /*
60*2654012fSReza Sabdar  * ************************************************************************
61*2654012fSReza Sabdar  * NDMP V2 HANDLERS
62*2654012fSReza Sabdar  * ************************************************************************
63*2654012fSReza Sabdar  */
64*2654012fSReza Sabdar 
65*2654012fSReza Sabdar /*
66*2654012fSReza Sabdar  * ndmpd_scsi_open_v2
67*2654012fSReza Sabdar  *
68*2654012fSReza Sabdar  * This handler opens the specified SCSI device.
69*2654012fSReza Sabdar  *
70*2654012fSReza Sabdar  * Parameters:
71*2654012fSReza Sabdar  *   connection (input) - connection handle.
72*2654012fSReza Sabdar  *   body       (input) - request message body.
73*2654012fSReza Sabdar  *
74*2654012fSReza Sabdar  * Returns:
75*2654012fSReza Sabdar  *   void
76*2654012fSReza Sabdar  */
77*2654012fSReza Sabdar void
ndmpd_scsi_open_v2(ndmp_connection_t * connection,void * body)78*2654012fSReza Sabdar ndmpd_scsi_open_v2(ndmp_connection_t *connection, void *body)
79*2654012fSReza Sabdar {
80*2654012fSReza Sabdar 	ndmp_scsi_open_request_v2 *request = (ndmp_scsi_open_request_v2 *)body;
81*2654012fSReza Sabdar 
82*2654012fSReza Sabdar 	common_open(connection, request->device.name);
83*2654012fSReza Sabdar }
84*2654012fSReza Sabdar 
85*2654012fSReza Sabdar 
86*2654012fSReza Sabdar /*
87*2654012fSReza Sabdar  * ndmpd_scsi_close_v2
88*2654012fSReza Sabdar  *
89*2654012fSReza Sabdar  * This handler closes the currently open SCSI device.
90*2654012fSReza Sabdar  *
91*2654012fSReza Sabdar  * Parameters:
92*2654012fSReza Sabdar  *   connection (input) - connection handle.
93*2654012fSReza Sabdar  *   body       (input) - request message body.
94*2654012fSReza Sabdar  *
95*2654012fSReza Sabdar  * Returns:
96*2654012fSReza Sabdar  *   void
97*2654012fSReza Sabdar  */
98*2654012fSReza Sabdar /*ARGSUSED*/
99*2654012fSReza Sabdar void
ndmpd_scsi_close_v2(ndmp_connection_t * connection,void * body)100*2654012fSReza Sabdar ndmpd_scsi_close_v2(ndmp_connection_t *connection, void *body)
101*2654012fSReza Sabdar {
102*2654012fSReza Sabdar 	ndmp_scsi_close_reply reply;
103*2654012fSReza Sabdar 	ndmpd_session_t *session = ndmp_get_client_data(connection);
104*2654012fSReza Sabdar 
105*2654012fSReza Sabdar 	if (session->ns_scsi.sd_is_open == -1) {
106*2654012fSReza Sabdar 		NDMP_LOG(LOG_ERR, "SCSI device is not open.");
107*2654012fSReza Sabdar 		reply.error = NDMP_DEV_NOT_OPEN_ERR;
108*2654012fSReza Sabdar 		ndmp_send_reply(connection, (void *) &reply,
109*2654012fSReza Sabdar 		    "sending scsi_close reply");
110*2654012fSReza Sabdar 		return;
111*2654012fSReza Sabdar 	}
112*2654012fSReza Sabdar 	(void) ndmp_open_list_del(session->ns_scsi.sd_adapter_name,
113*2654012fSReza Sabdar 	    session->ns_scsi.sd_sid,
114*2654012fSReza Sabdar 	    session->ns_scsi.sd_lun);
115*2654012fSReza Sabdar 	(void) close(session->ns_scsi.sd_devid);
116*2654012fSReza Sabdar 
117*2654012fSReza Sabdar 	session->ns_scsi.sd_is_open = -1;
118*2654012fSReza Sabdar 	session->ns_scsi.sd_devid = -1;
119*2654012fSReza Sabdar 	session->ns_scsi.sd_sid = 0;
120*2654012fSReza Sabdar 	session->ns_scsi.sd_lun = 0;
121*2654012fSReza Sabdar 	session->ns_scsi.sd_valid_target_set = FALSE;
122*2654012fSReza Sabdar 	(void) memset(session->ns_scsi.sd_adapter_name, 0,
123*2654012fSReza Sabdar 	    sizeof (session->ns_scsi.sd_adapter_name));
124*2654012fSReza Sabdar 
125*2654012fSReza Sabdar 	reply.error = NDMP_NO_ERR;
126*2654012fSReza Sabdar 	ndmp_send_reply(connection, (void *) &reply,
127*2654012fSReza Sabdar 	    "sending scsi_close reply");
128*2654012fSReza Sabdar }
129*2654012fSReza Sabdar 
130*2654012fSReza Sabdar 
131*2654012fSReza Sabdar /*
132*2654012fSReza Sabdar  * ndmpd_scsi_get_state_v2
133*2654012fSReza Sabdar  *
134*2654012fSReza Sabdar  * This handler returns state information for the currently open SCSI device.
135*2654012fSReza Sabdar  * Since the implementation only supports the opening of a specific SCSI
136*2654012fSReza Sabdar  * device, as opposed to a device that can talk to multiple SCSI targets,
137*2654012fSReza Sabdar  * this request is not supported. This request is only appropriate for
138*2654012fSReza Sabdar  * implementations that support device files that can target multiple
139*2654012fSReza Sabdar  * SCSI devices.
140*2654012fSReza Sabdar  *
141*2654012fSReza Sabdar  * Parameters:
142*2654012fSReza Sabdar  *   connection (input) - connection handle.
143*2654012fSReza Sabdar  *   body       (input) - request message body.
144*2654012fSReza Sabdar  *
145*2654012fSReza Sabdar  * Returns:
146*2654012fSReza Sabdar  *   void
147*2654012fSReza Sabdar  */
148*2654012fSReza Sabdar /*ARGSUSED*/
149*2654012fSReza Sabdar void
ndmpd_scsi_get_state_v2(ndmp_connection_t * connection,void * body)150*2654012fSReza Sabdar ndmpd_scsi_get_state_v2(ndmp_connection_t *connection, void *body)
151*2654012fSReza Sabdar {
152*2654012fSReza Sabdar 	ndmp_scsi_get_state_reply reply;
153*2654012fSReza Sabdar 	ndmpd_session_t *session = ndmp_get_client_data(connection);
154*2654012fSReza Sabdar 
155*2654012fSReza Sabdar 	if (session->ns_scsi.sd_is_open == -1)
156*2654012fSReza Sabdar 		reply.error = NDMP_DEV_NOT_OPEN_ERR;
157*2654012fSReza Sabdar 	else if (!session->ns_scsi.sd_valid_target_set) {
158*2654012fSReza Sabdar 		reply.error = NDMP_NO_ERR;
159*2654012fSReza Sabdar 		reply.target_controller = -1;
160*2654012fSReza Sabdar 		reply.target_id = -1;
161*2654012fSReza Sabdar 		reply.target_lun = -1;
162*2654012fSReza Sabdar 	} else {
163*2654012fSReza Sabdar 		reply.error = NDMP_NO_ERR;
164*2654012fSReza Sabdar 		reply.target_controller = 0;
165*2654012fSReza Sabdar 		reply.target_id = session->ns_scsi.sd_sid;
166*2654012fSReza Sabdar 		reply.target_lun = session->ns_scsi.sd_lun;
167*2654012fSReza Sabdar 	}
168*2654012fSReza Sabdar 
169*2654012fSReza Sabdar 	ndmp_send_reply(connection, (void *) &reply,
170*2654012fSReza Sabdar 	    "sending scsi_get_state reply");
171*2654012fSReza Sabdar }
172*2654012fSReza Sabdar 
173*2654012fSReza Sabdar 
174*2654012fSReza Sabdar /*
175*2654012fSReza Sabdar  * ndmpd_scsi_set_target_v2
176*2654012fSReza Sabdar  *
177*2654012fSReza Sabdar  * This handler sets the SCSI target of the SCSI device.
178*2654012fSReza Sabdar  * It is only valid to use this request if the opened SCSI device
179*2654012fSReza Sabdar  * is capable of talking to multiple SCSI targets.
180*2654012fSReza Sabdar  * Since the implementation only supports the opening of a specific SCSI
181*2654012fSReza Sabdar  * device, as opposed to a device that can talk to multiple SCSI targets,
182*2654012fSReza Sabdar  * this request is not supported. This request is only appropriate for
183*2654012fSReza Sabdar  * implementations that support device files that can target multiple
184*2654012fSReza Sabdar  * SCSI devices.
185*2654012fSReza Sabdar  *
186*2654012fSReza Sabdar  * Parameters:
187*2654012fSReza Sabdar  *   connection (input) - connection handle.
188*2654012fSReza Sabdar  *   body       (input) - request message body.
189*2654012fSReza Sabdar  *
190*2654012fSReza Sabdar  * Returns:
191*2654012fSReza Sabdar  *   void
192*2654012fSReza Sabdar  */
193*2654012fSReza Sabdar void
ndmpd_scsi_set_target_v2(ndmp_connection_t * connection,void * body)194*2654012fSReza Sabdar ndmpd_scsi_set_target_v2(ndmp_connection_t *connection, void *body)
195*2654012fSReza Sabdar {
196*2654012fSReza Sabdar 	ndmp_scsi_set_target_request_v2 *request;
197*2654012fSReza Sabdar 
198*2654012fSReza Sabdar 	request = (ndmp_scsi_set_target_request_v2 *) body;
199*2654012fSReza Sabdar 
200*2654012fSReza Sabdar 	common_set_target(connection, request->device.name,
201*2654012fSReza Sabdar 	    request->target_controller, request->target_id,
202*2654012fSReza Sabdar 	    request->target_lun);
203*2654012fSReza Sabdar }
204*2654012fSReza Sabdar 
205*2654012fSReza Sabdar 
206*2654012fSReza Sabdar /*
207*2654012fSReza Sabdar  * ndmpd_scsi_reset_device_v2
208*2654012fSReza Sabdar  *
209*2654012fSReza Sabdar  * This handler resets the currently targeted SCSI device.
210*2654012fSReza Sabdar  *
211*2654012fSReza Sabdar  * Parameters:
212*2654012fSReza Sabdar  *   connection (input) - connection handle.
213*2654012fSReza Sabdar  *   body       (input) - request message body.
214*2654012fSReza Sabdar  *
215*2654012fSReza Sabdar  * Returns:
216*2654012fSReza Sabdar  *   void
217*2654012fSReza Sabdar  */
218*2654012fSReza Sabdar /*ARGSUSED*/
219*2654012fSReza Sabdar void
ndmpd_scsi_reset_device_v2(ndmp_connection_t * connection,void * body)220*2654012fSReza Sabdar ndmpd_scsi_reset_device_v2(ndmp_connection_t *connection, void *body)
221*2654012fSReza Sabdar {
222*2654012fSReza Sabdar 	ndmp_scsi_reset_device_reply reply;
223*2654012fSReza Sabdar 
224*2654012fSReza Sabdar 
225*2654012fSReza Sabdar 	ndmpd_session_t *session = ndmp_get_client_data(connection);
226*2654012fSReza Sabdar 	struct uscsi_cmd  cmd;
227*2654012fSReza Sabdar 
228*2654012fSReza Sabdar 	if (session->ns_scsi.sd_devid == -1) {
229*2654012fSReza Sabdar 		NDMP_LOG(LOG_ERR, "SCSI device is not open.");
230*2654012fSReza Sabdar 		reply.error = NDMP_DEV_NOT_OPEN_ERR;
231*2654012fSReza Sabdar 	} else {
232*2654012fSReza Sabdar 		reply.error = NDMP_NO_ERR;
233*2654012fSReza Sabdar 		(void) memset((void*)&cmd, 0, sizeof (cmd));
234*2654012fSReza Sabdar 		cmd.uscsi_flags |= USCSI_RESET;
235*2654012fSReza Sabdar 		if (ioctl(session->ns_scsi.sd_devid, USCSICMD, &cmd) < 0) {
236*2654012fSReza Sabdar 			NDMP_LOG(LOG_ERR, "USCSI reset failed: %m.");
237*2654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG,
238*2654012fSReza Sabdar 			    "ioctl(USCSICMD) USCSI_RESET failed: %m.");
239*2654012fSReza Sabdar 			reply.error = NDMP_IO_ERR;
240*2654012fSReza Sabdar 		}
241*2654012fSReza Sabdar 	}
242*2654012fSReza Sabdar 
243*2654012fSReza Sabdar 	ndmp_send_reply(connection, (void *) &reply,
244*2654012fSReza Sabdar 	    "sending scsi_reset_device reply");
245*2654012fSReza Sabdar }
246*2654012fSReza Sabdar 
247*2654012fSReza Sabdar 
248*2654012fSReza Sabdar /*
249*2654012fSReza Sabdar  * ndmpd_scsi_reset_bus_v2
250*2654012fSReza Sabdar  *
251*2654012fSReza Sabdar  * This handler resets the currently targeted SCSI bus.
252*2654012fSReza Sabdar  *
253*2654012fSReza Sabdar  * Request not yet supported.
254*2654012fSReza Sabdar  *
255*2654012fSReza Sabdar  * Parameters:
256*2654012fSReza Sabdar  *   connection (input) - connection handle.
257*2654012fSReza Sabdar  *   body       (input) - request message body.
258*2654012fSReza Sabdar  *
259*2654012fSReza Sabdar  * Returns:
260*2654012fSReza Sabdar  *   void
261*2654012fSReza Sabdar  */
262*2654012fSReza Sabdar /*ARGSUSED*/
263*2654012fSReza Sabdar void
ndmpd_scsi_reset_bus_v2(ndmp_connection_t * connection,void * body)264*2654012fSReza Sabdar ndmpd_scsi_reset_bus_v2(ndmp_connection_t *connection, void *body)
265*2654012fSReza Sabdar {
266*2654012fSReza Sabdar 	ndmp_scsi_reset_bus_reply reply;
267*2654012fSReza Sabdar 
268*2654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "request not supported");
269*2654012fSReza Sabdar 	reply.error = NDMP_NOT_SUPPORTED_ERR;
270*2654012fSReza Sabdar 
271*2654012fSReza Sabdar 	ndmp_send_reply(connection, (void *) &reply,
272*2654012fSReza Sabdar 	    "sending scsi_reset_bus reply");
273*2654012fSReza Sabdar }
274*2654012fSReza Sabdar 
275*2654012fSReza Sabdar 
276*2654012fSReza Sabdar /*
277*2654012fSReza Sabdar  * ndmpd_scsi_execute_cdb_v2
278*2654012fSReza Sabdar  *
279*2654012fSReza Sabdar  * This handler sends the CDB to the currently targeted SCSI device.
280*2654012fSReza Sabdar  *
281*2654012fSReza Sabdar  * Parameters:
282*2654012fSReza Sabdar  *   connection (input) - connection handle.
283*2654012fSReza Sabdar  *   body       (input) - request message body.
284*2654012fSReza Sabdar  *
285*2654012fSReza Sabdar  * Returns:
286*2654012fSReza Sabdar  *   void
287*2654012fSReza Sabdar  */
288*2654012fSReza Sabdar void
ndmpd_scsi_execute_cdb_v2(ndmp_connection_t * connection,void * body)289*2654012fSReza Sabdar ndmpd_scsi_execute_cdb_v2(ndmp_connection_t *connection, void *body)
290*2654012fSReza Sabdar {
291*2654012fSReza Sabdar 	ndmp_execute_cdb_request *request = (ndmp_execute_cdb_request *) body;
292*2654012fSReza Sabdar 	ndmp_execute_cdb_reply reply;
293*2654012fSReza Sabdar 	ndmpd_session_t *session = ndmp_get_client_data(connection);
294*2654012fSReza Sabdar 
295*2654012fSReza Sabdar 	if (session->ns_scsi.sd_is_open == -1 ||
296*2654012fSReza Sabdar 	    !session->ns_scsi.sd_valid_target_set) {
297*2654012fSReza Sabdar 		(void) memset((void *) &reply, 0, sizeof (reply));
298*2654012fSReza Sabdar 
299*2654012fSReza Sabdar 		NDMP_LOG(LOG_ERR, "SCSI device is not open.");
300*2654012fSReza Sabdar 		reply.error = NDMP_DEV_NOT_OPEN_ERR;
301*2654012fSReza Sabdar 		ndmp_send_reply(connection, (void *) &reply,
302*2654012fSReza Sabdar 		    "sending scsi_execute_cdb reply");
303*2654012fSReza Sabdar 	} else {
304*2654012fSReza Sabdar 		ndmp_execute_cdb(session, session->ns_scsi.sd_adapter_name,
305*2654012fSReza Sabdar 		    session->ns_scsi.sd_sid, session->ns_scsi.sd_lun, request);
306*2654012fSReza Sabdar 	}
307*2654012fSReza Sabdar }
308*2654012fSReza Sabdar 
309*2654012fSReza Sabdar 
310*2654012fSReza Sabdar /*
311*2654012fSReza Sabdar  * ************************************************************************
312*2654012fSReza Sabdar  * NDMP V3 HANDLERS
313*2654012fSReza Sabdar  * ************************************************************************
314*2654012fSReza Sabdar  */
315*2654012fSReza Sabdar 
316*2654012fSReza Sabdar /*
317*2654012fSReza Sabdar  * ndmpd_scsi_open_v3
318*2654012fSReza Sabdar  *
319*2654012fSReza Sabdar  * This handler opens the specified SCSI device.
320*2654012fSReza Sabdar  *
321*2654012fSReza Sabdar  * Parameters:
322*2654012fSReza Sabdar  *   connection (input) - connection handle.
323*2654012fSReza Sabdar  *   body       (input) - request message body.
324*2654012fSReza Sabdar  *
325*2654012fSReza Sabdar  * Returns:
326*2654012fSReza Sabdar  *   void
327*2654012fSReza Sabdar  */
328*2654012fSReza Sabdar void
ndmpd_scsi_open_v3(ndmp_connection_t * connection,void * body)329*2654012fSReza Sabdar ndmpd_scsi_open_v3(ndmp_connection_t *connection, void *body)
330*2654012fSReza Sabdar {
331*2654012fSReza Sabdar 	ndmp_scsi_open_request_v3 *request = (ndmp_scsi_open_request_v3 *)body;
332*2654012fSReza Sabdar 
333*2654012fSReza Sabdar 	common_open(connection, request->device);
334*2654012fSReza Sabdar }
335*2654012fSReza Sabdar 
336*2654012fSReza Sabdar 
337*2654012fSReza Sabdar /*
338*2654012fSReza Sabdar  * ndmpd_scsi_set_target_v3
339*2654012fSReza Sabdar  *
340*2654012fSReza Sabdar  * This handler sets the SCSI target of the SCSI device.
341*2654012fSReza Sabdar  * It is only valid to use this request if the opened SCSI device
342*2654012fSReza Sabdar  * is capable of talking to multiple SCSI targets.
343*2654012fSReza Sabdar  *
344*2654012fSReza Sabdar  * Parameters:
345*2654012fSReza Sabdar  *   connection (input) - connection handle.
346*2654012fSReza Sabdar  *   body       (input) - request message body.
347*2654012fSReza Sabdar  *
348*2654012fSReza Sabdar  * Returns:
349*2654012fSReza Sabdar  *   void
350*2654012fSReza Sabdar  */
351*2654012fSReza Sabdar void
ndmpd_scsi_set_target_v3(ndmp_connection_t * connection,void * body)352*2654012fSReza Sabdar ndmpd_scsi_set_target_v3(ndmp_connection_t *connection, void *body)
353*2654012fSReza Sabdar {
354*2654012fSReza Sabdar 	ndmp_scsi_set_target_request_v3 *request;
355*2654012fSReza Sabdar 
356*2654012fSReza Sabdar 	request = (ndmp_scsi_set_target_request_v3 *) body;
357*2654012fSReza Sabdar 
358*2654012fSReza Sabdar 	common_set_target(connection, request->device,
359*2654012fSReza Sabdar 	    request->target_controller, request->target_id,
360*2654012fSReza Sabdar 	    request->target_lun);
361*2654012fSReza Sabdar }
362*2654012fSReza Sabdar 
363*2654012fSReza Sabdar 
364*2654012fSReza Sabdar /*
365*2654012fSReza Sabdar  * ************************************************************************
366*2654012fSReza Sabdar  * NDMP V4 HANDLERS
367*2654012fSReza Sabdar  * ************************************************************************
368*2654012fSReza Sabdar  */
369*2654012fSReza Sabdar 
370*2654012fSReza Sabdar /*
371*2654012fSReza Sabdar  * ************************************************************************
372*2654012fSReza Sabdar  * LOCALS
373*2654012fSReza Sabdar  * ************************************************************************
374*2654012fSReza Sabdar  */
375*2654012fSReza Sabdar 
376*2654012fSReza Sabdar 
377*2654012fSReza Sabdar /*
378*2654012fSReza Sabdar  * scsi_open_send_reply
379*2654012fSReza Sabdar  *
380*2654012fSReza Sabdar  * Send a reply for SCSI open command
381*2654012fSReza Sabdar  *
382*2654012fSReza Sabdar  * Parameters:
383*2654012fSReza Sabdar  *   connection (input) - connection handle.
384*2654012fSReza Sabdar  *   err        (input) - ndmp error code
385*2654012fSReza Sabdar  *
386*2654012fSReza Sabdar  * Returns:
387*2654012fSReza Sabdar  *   void
388*2654012fSReza Sabdar  */
389*2654012fSReza Sabdar static void
scsi_open_send_reply(ndmp_connection_t * connection,int err)390*2654012fSReza Sabdar scsi_open_send_reply(ndmp_connection_t *connection, int err)
391*2654012fSReza Sabdar {
392*2654012fSReza Sabdar 	ndmp_scsi_open_reply reply;
393*2654012fSReza Sabdar 
394*2654012fSReza Sabdar 	reply.error = err;
395*2654012fSReza Sabdar 	ndmp_send_reply(connection, (void *) &reply, "sending scsi_open reply");
396*2654012fSReza Sabdar }
397*2654012fSReza Sabdar 
398*2654012fSReza Sabdar 
399*2654012fSReza Sabdar /*
400*2654012fSReza Sabdar  * common_open
401*2654012fSReza Sabdar  *
402*2654012fSReza Sabdar  * Common SCSI open function for all NDMP versions
403*2654012fSReza Sabdar  *
404*2654012fSReza Sabdar  * Parameters:
405*2654012fSReza Sabdar  *   connection (input) - connection handle.
406*2654012fSReza Sabdar  *   devname (input) - device name to open.
407*2654012fSReza Sabdar  *
408*2654012fSReza Sabdar  * Returns:
409*2654012fSReza Sabdar  *   void
410*2654012fSReza Sabdar  */
411*2654012fSReza Sabdar static void
common_open(ndmp_connection_t * connection,char * devname)412*2654012fSReza Sabdar common_open(ndmp_connection_t *connection, char *devname)
413*2654012fSReza Sabdar {
414*2654012fSReza Sabdar 	ndmpd_session_t *session = ndmp_get_client_data(connection);
415*2654012fSReza Sabdar 	char adptnm[SCSI_MAX_NAME];
416*2654012fSReza Sabdar 	int sid, lun;
417*2654012fSReza Sabdar 	int err;
418*2654012fSReza Sabdar 	scsi_adapter_t *sa;
419*2654012fSReza Sabdar 	int devid;
420*2654012fSReza Sabdar 
421*2654012fSReza Sabdar 	err = NDMP_NO_ERR;
422*2654012fSReza Sabdar 
423*2654012fSReza Sabdar 	if (session->ns_tape.td_fd != -1 || session->ns_scsi.sd_is_open != -1) {
424*2654012fSReza Sabdar 		NDMP_LOG(LOG_ERR,
425*2654012fSReza Sabdar 		    "Session already has a tape or scsi device open.");
426*2654012fSReza Sabdar 		err = NDMP_DEVICE_OPENED_ERR;
427*2654012fSReza Sabdar 	} else if ((sa = scsi_get_adapter(0)) != NULL) {
428*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Adapter device found: %s", devname);
429*2654012fSReza Sabdar 		(void) strlcpy(adptnm, devname, SCSI_MAX_NAME-2);
430*2654012fSReza Sabdar 		adptnm[SCSI_MAX_NAME-1] = '\0';
431*2654012fSReza Sabdar 		sid = lun = -1;
432*2654012fSReza Sabdar 
433*2654012fSReza Sabdar 		scsi_find_sid_lun(sa, devname, &sid, &lun);
434*2654012fSReza Sabdar 		if (ndmp_open_list_find(devname, sid, lun) == NULL &&
435*2654012fSReza Sabdar 		    (devid = open(devname, O_RDWR | O_NDELAY)) < 0) {
436*2654012fSReza Sabdar 			NDMP_LOG(LOG_ERR, "Failed to open device %s: %m.",
437*2654012fSReza Sabdar 			    devname);
438*2654012fSReza Sabdar 			err = NDMP_NO_DEVICE_ERR;
439*2654012fSReza Sabdar 		}
440*2654012fSReza Sabdar 	} else {
441*2654012fSReza Sabdar 		NDMP_LOG(LOG_ERR, "%s: No such SCSI adapter.", devname);
442*2654012fSReza Sabdar 		err = NDMP_NO_DEVICE_ERR;
443*2654012fSReza Sabdar 	}
444*2654012fSReza Sabdar 
445*2654012fSReza Sabdar 	if (err != NDMP_NO_ERR) {
446*2654012fSReza Sabdar 		scsi_open_send_reply(connection, err);
447*2654012fSReza Sabdar 		return;
448*2654012fSReza Sabdar 	}
449*2654012fSReza Sabdar 
450*2654012fSReza Sabdar 	switch (ndmp_open_list_add(connection, adptnm, sid, lun, devid)) {
451*2654012fSReza Sabdar 	case 0:
452*2654012fSReza Sabdar 		/* OK */
453*2654012fSReza Sabdar 		break;
454*2654012fSReza Sabdar 	case EBUSY:
455*2654012fSReza Sabdar 		err = NDMP_DEVICE_BUSY_ERR;
456*2654012fSReza Sabdar 		break;
457*2654012fSReza Sabdar 	case ENOMEM:
458*2654012fSReza Sabdar 		err = NDMP_NO_MEM_ERR;
459*2654012fSReza Sabdar 		break;
460*2654012fSReza Sabdar 	default:
461*2654012fSReza Sabdar 		err = NDMP_IO_ERR;
462*2654012fSReza Sabdar 	}
463*2654012fSReza Sabdar 	if (err != NDMP_NO_ERR) {
464*2654012fSReza Sabdar 		scsi_open_send_reply(connection, err);
465*2654012fSReza Sabdar 		return;
466*2654012fSReza Sabdar 	}
467*2654012fSReza Sabdar 
468*2654012fSReza Sabdar 	(void) strlcpy(session->ns_scsi.sd_adapter_name, adptnm, SCSI_MAX_NAME);
469*2654012fSReza Sabdar 	session->ns_scsi.sd_is_open = 1;
470*2654012fSReza Sabdar 	session->ns_scsi.sd_devid = devid;
471*2654012fSReza Sabdar 	if (sid != -1) {
472*2654012fSReza Sabdar 		session->ns_scsi.sd_sid = sid;
473*2654012fSReza Sabdar 		session->ns_scsi.sd_lun = lun;
474*2654012fSReza Sabdar 		session->ns_scsi.sd_valid_target_set = TRUE;
475*2654012fSReza Sabdar 	} else {
476*2654012fSReza Sabdar 		session->ns_scsi.sd_sid = session->ns_scsi.sd_lun = -1;
477*2654012fSReza Sabdar 		session->ns_scsi.sd_valid_target_set = FALSE;
478*2654012fSReza Sabdar 	}
479*2654012fSReza Sabdar 
480*2654012fSReza Sabdar 	scsi_open_send_reply(connection, err);
481*2654012fSReza Sabdar }
482*2654012fSReza Sabdar 
483*2654012fSReza Sabdar 
484*2654012fSReza Sabdar /*
485*2654012fSReza Sabdar  * common_set_target
486*2654012fSReza Sabdar  *
487*2654012fSReza Sabdar  * Set the SCSI target (SCSI number, LUN number, controller number)
488*2654012fSReza Sabdar  *
489*2654012fSReza Sabdar  * Parameters:
490*2654012fSReza Sabdar  *   connection (input) - connection handle.
491*2654012fSReza Sabdar  *   device (input) - device name.
492*2654012fSReza Sabdar  *   controller (input) - controller number.
493*2654012fSReza Sabdar  *   sid (input) - SCSI target ID.
494*2654012fSReza Sabdar  *   lun (input) - LUN number.
495*2654012fSReza Sabdar  *
496*2654012fSReza Sabdar  * Returns:
497*2654012fSReza Sabdar  *   0: on success
498*2654012fSReza Sabdar  *  -1: otherwise
499*2654012fSReza Sabdar  */
500*2654012fSReza Sabdar /*ARGSUSED*/
501*2654012fSReza Sabdar static void
common_set_target(ndmp_connection_t * connection,char * device,ushort_t controller,ushort_t sid,ushort_t lun)502*2654012fSReza Sabdar common_set_target(ndmp_connection_t *connection, char *device,
503*2654012fSReza Sabdar     ushort_t controller, ushort_t sid, ushort_t lun)
504*2654012fSReza Sabdar {
505*2654012fSReza Sabdar 	ndmp_scsi_set_target_reply reply;
506*2654012fSReza Sabdar 	ndmpd_session_t *session = ndmp_get_client_data(connection);
507*2654012fSReza Sabdar 	int type;
508*2654012fSReza Sabdar 
509*2654012fSReza Sabdar 	reply.error = NDMP_NO_ERR;
510*2654012fSReza Sabdar 
511*2654012fSReza Sabdar 	if (session->ns_scsi.sd_is_open == -1) {
512*2654012fSReza Sabdar 		reply.error = NDMP_DEV_NOT_OPEN_ERR;
513*2654012fSReza Sabdar 	} else if (!scsi_dev_exists(session->ns_scsi.sd_adapter_name, sid,
514*2654012fSReza Sabdar 	    lun)) {
515*2654012fSReza Sabdar 		NDMP_LOG(LOG_ERR, "No such SCSI device: target %d lun %d.",
516*2654012fSReza Sabdar 		    sid, lun);
517*2654012fSReza Sabdar 		reply.error = NDMP_NO_DEVICE_ERR;
518*2654012fSReza Sabdar 	} else {
519*2654012fSReza Sabdar 		type = scsi_get_devtype(session->ns_scsi.sd_adapter_name, sid,
520*2654012fSReza Sabdar 		    lun);
521*2654012fSReza Sabdar 		if (type != DTYPE_SEQUENTIAL && type != DTYPE_CHANGER) {
522*2654012fSReza Sabdar 			NDMP_LOG(LOG_ERR,
523*2654012fSReza Sabdar 			    "Not a tape or robot device: target %d lun %d.",
524*2654012fSReza Sabdar 			    sid, lun);
525*2654012fSReza Sabdar 			reply.error = NDMP_ILLEGAL_ARGS_ERR;
526*2654012fSReza Sabdar 		}
527*2654012fSReza Sabdar 	}
528*2654012fSReza Sabdar 
529*2654012fSReza Sabdar 	if (reply.error != NDMP_NO_ERR) {
530*2654012fSReza Sabdar 		ndmp_send_reply(connection, (void *) &reply,
531*2654012fSReza Sabdar 		    "sending scsi_set_target reply");
532*2654012fSReza Sabdar 		return;
533*2654012fSReza Sabdar 	}
534*2654012fSReza Sabdar 
535*2654012fSReza Sabdar 	/*
536*2654012fSReza Sabdar 	 * The open_list must be updated if the SID or LUN are going to be
537*2654012fSReza Sabdar 	 * changed.  Close uses the same SID & LUN for removing the entry
538*2654012fSReza Sabdar 	 * from the open_list.
539*2654012fSReza Sabdar 	 */
540*2654012fSReza Sabdar 	if (sid != session->ns_scsi.sd_sid || lun != session->ns_scsi.sd_lun) {
541*2654012fSReza Sabdar 		switch (ndmp_open_list_add(connection,
542*2654012fSReza Sabdar 		    session->ns_scsi.sd_adapter_name, sid, lun, 0)) {
543*2654012fSReza Sabdar 		case 0:
544*2654012fSReza Sabdar 			(void) ndmp_open_list_del(session->
545*2654012fSReza Sabdar 			    ns_scsi.sd_adapter_name, session->ns_scsi.sd_sid,
546*2654012fSReza Sabdar 			    session->ns_scsi.sd_lun);
547*2654012fSReza Sabdar 			break;
548*2654012fSReza Sabdar 		case EBUSY:
549*2654012fSReza Sabdar 			reply.error = NDMP_DEVICE_BUSY_ERR;
550*2654012fSReza Sabdar 			break;
551*2654012fSReza Sabdar 		case ENOMEM:
552*2654012fSReza Sabdar 			reply.error = NDMP_NO_MEM_ERR;
553*2654012fSReza Sabdar 			break;
554*2654012fSReza Sabdar 		default:
555*2654012fSReza Sabdar 			reply.error = NDMP_IO_ERR;
556*2654012fSReza Sabdar 		}
557*2654012fSReza Sabdar 	}
558*2654012fSReza Sabdar 
559*2654012fSReza Sabdar 	if (reply.error == NDMP_NO_ERR) {
560*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Updated sid %d lun %d", sid, lun);
561*2654012fSReza Sabdar 		session->ns_scsi.sd_sid = sid;
562*2654012fSReza Sabdar 		session->ns_scsi.sd_lun = lun;
563*2654012fSReza Sabdar 		session->ns_scsi.sd_valid_target_set = TRUE;
564*2654012fSReza Sabdar 	}
565*2654012fSReza Sabdar 
566*2654012fSReza Sabdar 	ndmp_send_reply(connection, (void *) &reply,
567*2654012fSReza Sabdar 	    "sending scsi_set_target reply");
568*2654012fSReza Sabdar }
569*2654012fSReza Sabdar 
570*2654012fSReza Sabdar /*
571*2654012fSReza Sabdar  * scsi_find_sid_lun
572*2654012fSReza Sabdar  *
573*2654012fSReza Sabdar  * gets the adapter, and returns the sid and lun number
574*2654012fSReza Sabdar  */
575*2654012fSReza Sabdar void
scsi_find_sid_lun(scsi_adapter_t * sa,char * devname,int * sid,int * lun)576*2654012fSReza Sabdar scsi_find_sid_lun(scsi_adapter_t *sa, char *devname, int *sid, int *lun)
577*2654012fSReza Sabdar {
578*2654012fSReza Sabdar 	scsi_link_t *sl;
579*2654012fSReza Sabdar 	char *name;
580*2654012fSReza Sabdar 
581*2654012fSReza Sabdar 	for (sl = sa->sa_link_head.sl_next; sl && sl != &sa->sa_link_head;
582*2654012fSReza Sabdar 	    sl = sl->sl_next) {
583*2654012fSReza Sabdar 		name = sasd_slink_name(sl);
584*2654012fSReza Sabdar 		if (strcmp(devname, name) == 0) {
585*2654012fSReza Sabdar 			*sid = sl->sl_sid;
586*2654012fSReza Sabdar 			*lun = sl->sl_lun;
587*2654012fSReza Sabdar 			return;
588*2654012fSReza Sabdar 		}
589*2654012fSReza Sabdar 	}
590*2654012fSReza Sabdar 
591*2654012fSReza Sabdar 	*sid = -1;
592*2654012fSReza Sabdar 	*lun = -1;
593*2654012fSReza Sabdar }
594