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 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 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 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 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 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 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 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