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 /* 27 * SCSI simulator. 28 * 29 * For testing purposes, we need a way to simulate arbitrary SCSI responses. A 30 * completely flexible SCSI simulation language would be a large undertaking, 31 * given the number of possible outcomes. Instead, we opt for the simpler route 32 * of using a shared object which implements versions of these functions. 33 * 34 * If a shared object doesn't implement a given function, or if the function 35 * returns non-zero, then the simulator will provide a suitable response 36 * indicating the functionality isn't supported. 37 */ 38 39 #include <libdiskstatus.h> 40 41 #include "ds_scsi.h" 42 #include "ds_scsi_sim.h" 43 44 static int 45 check_invalid_code(int ret, void *rqbuf) 46 { 47 if (ret != 0) { 48 struct scsi_extended_sense *sensep = rqbuf; 49 50 sensep->es_key = KEY_ILLEGAL_REQUEST; 51 sensep->es_add_len = 6; 52 sensep->es_code = CODE_FMT_FIXED_CURRENT; 53 sensep->es_add_code = ASC_INVALID_OPCODE; 54 sensep->es_qual_code = ASCQ_INVALID_OPCODE; 55 ret = -1; 56 } 57 58 return (ret); 59 } 60 61 typedef int (*scsi_mode_sense_f)(int, int, caddr_t, int, scsi_ms_header_t *, 62 void *, int *); 63 64 int 65 simscsi_mode_sense(void *hdl, int page_code, int page_control, 66 caddr_t page_data, int page_size, scsi_ms_header_t *header, 67 void *rqbuf, int *rqblen) 68 { 69 scsi_mode_sense_f dscsi_mode_sense; 70 int ret = -1; 71 72 dscsi_mode_sense = (scsi_mode_sense_f)dlsym(hdl, "scsi_mode_sense"); 73 74 if (dscsi_mode_sense != NULL) 75 ret = (*dscsi_mode_sense)(page_code, page_control, page_data, 76 page_size, header, rqbuf, rqblen); 77 78 return (check_invalid_code(ret, rqbuf)); 79 } 80 81 typedef int (*scsi_mode_sense_10_f)(int, int, caddr_t, int, 82 scsi_ms_header_g1_t *, void *, int *); 83 84 int 85 simscsi_mode_sense_10(void *hdl, int page_code, int page_control, 86 caddr_t page_data, int page_size, scsi_ms_header_g1_t *header, 87 void *rqbuf, int *rqblen) 88 { 89 scsi_mode_sense_10_f dscsi_mode_sense_10; 90 int ret = -1; 91 92 dscsi_mode_sense_10 = (scsi_mode_sense_10_f)dlsym(hdl, 93 "scsi_mode_sense_10"); 94 95 if (dscsi_mode_sense_10 != NULL) 96 ret = (*dscsi_mode_sense_10)(page_code, page_control, page_data, 97 page_size, header, rqbuf, rqblen); 98 99 return (check_invalid_code(ret, rqbuf)); 100 } 101 102 typedef int (*scsi_mode_select_f)(int, int, caddr_t, int, scsi_ms_header_t *, 103 void *, int *); 104 105 int 106 simscsi_mode_select(void *hdl, int page_code, int options, caddr_t page_data, 107 int page_size, scsi_ms_header_t *header, void *rqbuf, int *rqblen) 108 { 109 scsi_mode_select_f dscsi_mode_select; 110 int ret = -1; 111 112 dscsi_mode_select = (scsi_mode_select_f)(dlsym(hdl, 113 "scsi_mode_select")); 114 115 if (dscsi_mode_select != NULL) 116 ret = (*dscsi_mode_select)(page_code, options, page_data, 117 page_size, header, rqbuf, rqblen); 118 119 return (check_invalid_code(ret, rqbuf)); 120 } 121 122 typedef int (*scsi_mode_select_10_f)(int, int, caddr_t, int, 123 scsi_ms_header_g1_t *, void *, int *); 124 125 int 126 simscsi_mode_select_10(void *hdl, int page_code, int options, 127 caddr_t page_data, int page_size, scsi_ms_header_g1_t *header, 128 void *rqbuf, int *rqblen) 129 { 130 scsi_mode_select_10_f dscsi_mode_select_10; 131 int ret = -1; 132 133 dscsi_mode_select_10 = (scsi_mode_select_10_f)dlsym(hdl, 134 "scsi_mode_select_10"); 135 136 if (dscsi_mode_select_10 != NULL) 137 ret = (*dscsi_mode_select_10)(page_code, options, page_data, 138 page_size, header, rqbuf, rqblen); 139 140 return (check_invalid_code(ret, rqbuf)); 141 } 142 143 typedef int (*scsi_log_sense_f)(int, int, caddr_t, int, void *, int *); 144 145 int 146 simscsi_log_sense(void *hdl, int page_code, int page_control, 147 caddr_t page_data, int page_size, void *rqbuf, int *rqblen) 148 { 149 scsi_log_sense_f dscsi_log_sense; 150 int ret = -1; 151 152 dscsi_log_sense = (scsi_log_sense_f)dlsym(hdl, "scsi_log_sense"); 153 154 if (dscsi_log_sense != NULL) 155 ret = (*dscsi_log_sense)(page_code, page_control, page_data, 156 page_size, rqbuf, rqblen); 157 158 return (check_invalid_code(ret, rqbuf)); 159 } 160 161 typedef int (*scsi_request_sense_f)(caddr_t, int, void *, int *); 162 163 int 164 simscsi_request_sense(void *hdl, caddr_t buf, int buflen, 165 void *rqbuf, int *rqblen) 166 { 167 scsi_request_sense_f dscsi_request_sense; 168 int ret = -1; 169 170 dscsi_request_sense = (scsi_request_sense_f)dlsym(hdl, 171 "scsi_request_sense"); 172 173 if (dscsi_request_sense != NULL) 174 ret = (*dscsi_request_sense)(buf, buflen, rqbuf, rqblen); 175 176 return (check_invalid_code(ret, rqbuf)); 177 } 178