1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #pragma ident "%Z%%M% %I% %E% SMI"
27
28 /*
29 * SCSI simulator.
30 *
31 * For testing purposes, we need a way to simulate arbitrary SCSI responses. A
32 * completely flexible SCSI simulation language would be a large undertaking,
33 * given the number of possible outcomes. Instead, we opt for the simpler route
34 * of using a shared object which implements versions of these functions.
35 *
36 * If a shared object doesn't implement a given function, or if the function
37 * returns non-zero, then the simulator will provide a suitable response
38 * indicating the functionality isn't supported.
39 */
40
41 #include <libdiskstatus.h>
42
43 #include "ds_scsi.h"
44 #include "ds_scsi_sim.h"
45
46 static int
check_invalid_code(int ret,void * rqbuf)47 check_invalid_code(int ret, void *rqbuf)
48 {
49 if (ret != 0) {
50 struct scsi_extended_sense *sensep = rqbuf;
51
52 sensep->es_key = KEY_ILLEGAL_REQUEST;
53 sensep->es_add_len = 6;
54 sensep->es_code = CODE_FMT_FIXED_CURRENT;
55 sensep->es_add_code = ASC_INVALID_OPCODE;
56 sensep->es_qual_code = ASCQ_INVALID_OPCODE;
57 ret = -1;
58 }
59
60 return (ret);
61 }
62
63 typedef int (*scsi_mode_sense_f)(int, int, caddr_t, int, scsi_ms_header_t *,
64 void *, int *);
65
66 int
simscsi_mode_sense(void * hdl,int page_code,int page_control,caddr_t page_data,int page_size,scsi_ms_header_t * header,void * rqbuf,int * rqblen)67 simscsi_mode_sense(void *hdl, int page_code, int page_control,
68 caddr_t page_data, int page_size, scsi_ms_header_t *header,
69 void *rqbuf, int *rqblen)
70 {
71 scsi_mode_sense_f dscsi_mode_sense;
72 int ret = -1;
73
74 dscsi_mode_sense = (scsi_mode_sense_f)dlsym(hdl, "scsi_mode_sense");
75
76 if (dscsi_mode_sense != NULL)
77 ret = (*dscsi_mode_sense)(page_code, page_control, page_data,
78 page_size, header, rqbuf, rqblen);
79
80 return (check_invalid_code(ret, rqbuf));
81 }
82
83 typedef int (*scsi_mode_sense_10_f)(int, int, caddr_t, int,
84 scsi_ms_header_g1_t *, void *, int *);
85
86 int
simscsi_mode_sense_10(void * hdl,int page_code,int page_control,caddr_t page_data,int page_size,scsi_ms_header_g1_t * header,void * rqbuf,int * rqblen)87 simscsi_mode_sense_10(void *hdl, int page_code, int page_control,
88 caddr_t page_data, int page_size, scsi_ms_header_g1_t *header,
89 void *rqbuf, int *rqblen)
90 {
91 scsi_mode_sense_10_f dscsi_mode_sense_10;
92 int ret = -1;
93
94 dscsi_mode_sense_10 = (scsi_mode_sense_10_f)dlsym(hdl,
95 "scsi_mode_sense_10");
96
97 if (dscsi_mode_sense_10 != NULL)
98 ret = (*dscsi_mode_sense_10)(page_code, page_control, page_data,
99 page_size, header, rqbuf, rqblen);
100
101 return (check_invalid_code(ret, rqbuf));
102 }
103
104 typedef int (*scsi_mode_select_f)(int, int, caddr_t, int, scsi_ms_header_t *,
105 void *, int *);
106
107 int
simscsi_mode_select(void * hdl,int page_code,int options,caddr_t page_data,int page_size,scsi_ms_header_t * header,void * rqbuf,int * rqblen)108 simscsi_mode_select(void *hdl, int page_code, int options, caddr_t page_data,
109 int page_size, scsi_ms_header_t *header, void *rqbuf, int *rqblen)
110 {
111 scsi_mode_select_f dscsi_mode_select;
112 int ret = -1;
113
114 dscsi_mode_select = (scsi_mode_select_f)(dlsym(hdl,
115 "scsi_mode_select"));
116
117 if (dscsi_mode_select != NULL)
118 ret = (*dscsi_mode_select)(page_code, options, page_data,
119 page_size, header, rqbuf, rqblen);
120
121 return (check_invalid_code(ret, rqbuf));
122 }
123
124 typedef int (*scsi_mode_select_10_f)(int, int, caddr_t, int,
125 scsi_ms_header_g1_t *, void *, int *);
126
127 int
simscsi_mode_select_10(void * hdl,int page_code,int options,caddr_t page_data,int page_size,scsi_ms_header_g1_t * header,void * rqbuf,int * rqblen)128 simscsi_mode_select_10(void *hdl, int page_code, int options,
129 caddr_t page_data, int page_size, scsi_ms_header_g1_t *header,
130 void *rqbuf, int *rqblen)
131 {
132 scsi_mode_select_10_f dscsi_mode_select_10;
133 int ret = -1;
134
135 dscsi_mode_select_10 = (scsi_mode_select_10_f)dlsym(hdl,
136 "scsi_mode_select_10");
137
138 if (dscsi_mode_select_10 != NULL)
139 ret = (*dscsi_mode_select_10)(page_code, options, page_data,
140 page_size, header, rqbuf, rqblen);
141
142 return (check_invalid_code(ret, rqbuf));
143 }
144
145 typedef int (*scsi_log_sense_f)(int, int, caddr_t, int, void *, int *);
146
147 int
simscsi_log_sense(void * hdl,int page_code,int page_control,caddr_t page_data,int page_size,void * rqbuf,int * rqblen)148 simscsi_log_sense(void *hdl, int page_code, int page_control,
149 caddr_t page_data, int page_size, void *rqbuf, int *rqblen)
150 {
151 scsi_log_sense_f dscsi_log_sense;
152 int ret = -1;
153
154 dscsi_log_sense = (scsi_log_sense_f)dlsym(hdl, "scsi_log_sense");
155
156 if (dscsi_log_sense != NULL)
157 ret = (*dscsi_log_sense)(page_code, page_control, page_data,
158 page_size, rqbuf, rqblen);
159
160 return (check_invalid_code(ret, rqbuf));
161 }
162
163 typedef int (*scsi_request_sense_f)(caddr_t, int, void *, int *);
164
165 int
simscsi_request_sense(void * hdl,caddr_t buf,int buflen,void * rqbuf,int * rqblen)166 simscsi_request_sense(void *hdl, caddr_t buf, int buflen,
167 void *rqbuf, int *rqblen)
168 {
169 scsi_request_sense_f dscsi_request_sense;
170 int ret = -1;
171
172 dscsi_request_sense = (scsi_request_sense_f)dlsym(hdl,
173 "scsi_request_sense");
174
175 if (dscsi_request_sense != NULL)
176 ret = (*dscsi_request_sense)(buf, buflen, rqbuf, rqblen);
177
178 return (check_invalid_code(ret, rqbuf));
179 }
180