1 /* $NetBSD: scsi_base.c,v 1.60 1998/03/28 21:57:09 christos Exp $ */ 2 3 /* 4 * Copyright (c) 1994, 1995, 1997 Charles M. Hannum. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by Charles M. Hannum. 17 * 4. The name of the author may not be used to endorse or promote products 18 * derived from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * Originally written by Julian Elischer (julian@dialix.oz.au) 34 */ 35 36 #include "opt_scsiverbose.h" 37 38 #include <sys/types.h> 39 #include <sys/param.h> 40 #include <sys/systm.h> 41 #include <sys/kernel.h> 42 #include <sys/buf.h> 43 #include <sys/uio.h> 44 #include <sys/malloc.h> 45 #include <sys/errno.h> 46 #include <sys/device.h> 47 #include <sys/proc.h> 48 49 #include <dev/scsipi/scsipi_all.h> 50 #include <dev/scsipi/scsi_all.h> 51 #include <dev/scsipi/scsi_disk.h> 52 #include <dev/scsipi/scsiconf.h> 53 #include <dev/scsipi/scsipi_base.h> 54 55 /* 56 * Do a scsi operation, asking a device to run as SCSI-II if it can. 57 */ 58 int 59 scsi_change_def(sc_link, flags) 60 struct scsipi_link *sc_link; 61 int flags; 62 { 63 struct scsi_changedef scsipi_cmd; 64 65 bzero(&scsipi_cmd, sizeof(scsipi_cmd)); 66 scsipi_cmd.opcode = SCSI_CHANGE_DEFINITION; 67 scsipi_cmd.how = SC_SCSI_2; 68 69 return (scsipi_command(sc_link, 70 (struct scsipi_generic *) &scsipi_cmd, sizeof(scsipi_cmd), 71 0, 0, 2, 100000, NULL, flags)); 72 } 73 74 /* 75 * ask the scsi driver to perform a command for us. 76 * tell it where to read/write the data, and how 77 * long the data is supposed to be. If we have a buf 78 * to associate with the transfer, we need that too. 79 */ 80 int 81 scsi_scsipi_cmd(sc_link, scsipi_cmd, cmdlen, data_addr, datalen, 82 retries, timeout, bp, flags) 83 struct scsipi_link *sc_link; 84 struct scsipi_generic *scsipi_cmd; 85 int cmdlen; 86 u_char *data_addr; 87 int datalen; 88 int retries; 89 int timeout; 90 struct buf *bp; 91 int flags; 92 { 93 struct scsipi_xfer *xs; 94 int error; 95 96 SC_DEBUG(sc_link, SDEV_DB2, ("scsi_scsipi_cmd\n")); 97 98 #ifdef DIAGNOSTIC 99 if (bp != 0 && (flags & SCSI_NOSLEEP) == 0) 100 panic("scsi_scsipi_cmd: buffer without nosleep"); 101 #endif 102 103 if ((xs = scsipi_make_xs(sc_link, scsipi_cmd, cmdlen, data_addr, 104 datalen, retries, timeout, bp, flags)) == NULL) 105 return (ENOMEM); 106 107 /* 108 * Set the LUN in the CDB if we have an older device. We also 109 * set it for more modern SCSI-II devices "just in case". 110 */ 111 if ((sc_link->scsipi_scsi.scsi_version & SID_ANSII) <= 2) 112 xs->cmd->bytes[0] |= 113 ((sc_link->scsipi_scsi.lun << SCSI_CMD_LUN_SHIFT) & 114 SCSI_CMD_LUN_MASK); 115 116 if ((error = scsipi_execute_xs(xs)) == EJUSTRETURN) 117 return (0); 118 119 /* 120 * we have finished with the xfer stuct, free it and 121 * check if anyone else needs to be started up. 122 */ 123 scsipi_free_xs(xs, flags); 124 return (error); 125 } 126 127 /* 128 * Look at the returned sense and act on the error, determining 129 * the unix error number to pass back. (0 = report no error) 130 * 131 * THIS IS THE DEFAULT ERROR HANDLER FOR SCSI DEVICES 132 */ 133 int 134 scsi_interpret_sense(xs) 135 struct scsipi_xfer *xs; 136 { 137 struct scsipi_sense_data *sense; 138 struct scsipi_link *sc_link = xs->sc_link; 139 u_int8_t key; 140 u_int32_t info; 141 int error; 142 #ifndef SCSIVERBOSE 143 static char *error_mes[] = { 144 "soft error (corrected)", 145 "not ready", "medium error", 146 "non-media hardware failure", "illegal request", 147 "unit attention", "readonly device", 148 "no data found", "vendor unique", 149 "copy aborted", "command aborted", 150 "search returned equal", "volume overflow", 151 "verify miscompare", "unknown error key" 152 }; 153 #endif 154 155 sense = &xs->sense.scsi_sense; 156 #ifdef SCSIDEBUG 157 if ((sc_link->flags & SDEV_DB1) != 0) { 158 int count; 159 printf("code 0x%x valid 0x%x ", 160 sense->error_code & SSD_ERRCODE, 161 sense->error_code & SSD_ERRCODE_VALID ? 1 : 0); 162 printf("seg 0x%x key 0x%x ili 0x%x eom 0x%x fmark 0x%x\n", 163 sense->segment, 164 sense->flags & SSD_KEY, 165 sense->flags & SSD_ILI ? 1 : 0, 166 sense->flags & SSD_EOM ? 1 : 0, 167 sense->flags & SSD_FILEMARK ? 1 : 0); 168 printf("info: 0x%x 0x%x 0x%x 0x%x followed by %d extra bytes\n", 169 sense->info[0], 170 sense->info[1], 171 sense->info[2], 172 sense->info[3], 173 sense->extra_len); 174 printf("extra: "); 175 for (count = 0; count < ADD_BYTES_LIM(sense); count++) 176 printf("0x%x ", sense->cmd_spec_info[count]); 177 printf("\n"); 178 } 179 #endif /* SCSIDEBUG */ 180 /* 181 * If the device has it's own error handler, call it first. 182 * If it returns a legit error value, return that, otherwise 183 * it wants us to continue with normal error processing. 184 */ 185 if (sc_link->device->err_handler) { 186 SC_DEBUG(sc_link, SDEV_DB2, 187 ("calling private err_handler()\n")); 188 error = (*sc_link->device->err_handler)(xs); 189 if (error != -1) 190 return (error); /* error >= 0 better ? */ 191 } 192 /* otherwise use the default */ 193 switch (sense->error_code & SSD_ERRCODE) { 194 /* 195 * If it's code 70, use the extended stuff and 196 * interpret the key 197 */ 198 case 0x71: /* delayed error */ 199 sc_link->sc_print_addr(sc_link); 200 key = sense->flags & SSD_KEY; 201 printf(" DEFERRED ERROR, key = 0x%x\n", key); 202 /* FALLTHROUGH */ 203 case 0x70: 204 if ((sense->error_code & SSD_ERRCODE_VALID) != 0) 205 info = _4btol(sense->info); 206 else 207 info = 0; 208 key = sense->flags & SSD_KEY; 209 210 switch (key) { 211 case 0x0: /* NO SENSE */ 212 case 0x1: /* RECOVERED ERROR */ 213 if (xs->resid == xs->datalen) 214 xs->resid = 0; /* not short read */ 215 case 0xc: /* EQUAL */ 216 error = 0; 217 break; 218 case 0x2: /* NOT READY */ 219 if ((sc_link->flags & SDEV_REMOVABLE) != 0) 220 sc_link->flags &= ~SDEV_MEDIA_LOADED; 221 if ((xs->flags & SCSI_IGNORE_NOT_READY) != 0) 222 return (0); 223 if ((xs->flags & SCSI_SILENT) != 0) 224 return (EIO); 225 error = EIO; 226 break; 227 case 0x5: /* ILLEGAL REQUEST */ 228 if ((xs->flags & SCSI_IGNORE_ILLEGAL_REQUEST) != 0) 229 return (0); 230 if ((xs->flags & SCSI_SILENT) != 0) 231 return (EIO); 232 error = EINVAL; 233 break; 234 case 0x6: /* UNIT ATTENTION */ 235 if ((sc_link->flags & SDEV_REMOVABLE) != 0) 236 sc_link->flags &= ~SDEV_MEDIA_LOADED; 237 if ((xs->flags & SCSI_IGNORE_MEDIA_CHANGE) != 0 || 238 /* XXX Should reupload any transient state. */ 239 (sc_link->flags & SDEV_REMOVABLE) == 0) 240 return (ERESTART); 241 if ((xs->flags & SCSI_SILENT) != 0) 242 return (EIO); 243 error = EIO; 244 break; 245 case 0x7: /* DATA PROTECT */ 246 error = EROFS; 247 break; 248 case 0x8: /* BLANK CHECK */ 249 error = 0; 250 break; 251 case 0xb: /* COMMAND ABORTED */ 252 error = ERESTART; 253 break; 254 case 0xd: /* VOLUME OVERFLOW */ 255 error = ENOSPC; 256 break; 257 default: 258 error = EIO; 259 break; 260 } 261 262 #ifdef SCSIVERBOSE 263 if ((xs->flags & SCSI_SILENT) == 0) 264 scsi_print_sense(xs, 0); 265 #else 266 if (key) { 267 sc_link->sc_print_addr(sc_link); 268 printf("%s", error_mes[key - 1]); 269 if ((sense->error_code & SSD_ERRCODE_VALID) != 0) { 270 switch (key) { 271 case 0x2: /* NOT READY */ 272 case 0x5: /* ILLEGAL REQUEST */ 273 case 0x6: /* UNIT ATTENTION */ 274 case 0x7: /* DATA PROTECT */ 275 break; 276 case 0x8: /* BLANK CHECK */ 277 printf(", requested size: %d (decimal)", 278 info); 279 break; 280 case 0xb: 281 if (xs->retries) 282 printf(", retrying"); 283 printf(", cmd 0x%x, info 0x%x", 284 xs->cmd->opcode, info); 285 break; 286 default: 287 printf(", info = %d (decimal)", info); 288 } 289 } 290 if (sense->extra_len != 0) { 291 int n; 292 printf(", data ="); 293 for (n = 0; n < sense->extra_len; n++) 294 printf(" %02x", 295 sense->cmd_spec_info[n]); 296 } 297 printf("\n"); 298 } 299 #endif 300 return (error); 301 302 /* 303 * Not code 70, just report it 304 */ 305 default: 306 sc_link->sc_print_addr(sc_link); 307 printf("error code %d", sense->error_code & SSD_ERRCODE); 308 if ((sense->error_code & SSD_ERRCODE_VALID) != 0) { 309 struct scsipi_sense_data_unextended *usense = 310 (struct scsipi_sense_data_unextended *)sense; 311 printf(" at block no. %d (decimal)", 312 _3btol(usense->block)); 313 } 314 printf("\n"); 315 return (EIO); 316 } 317 } 318 319 /* 320 * Utility routines often used in SCSI stuff 321 */ 322 323 324 /* 325 * Print out the scsi_link structure's address info. 326 */ 327 void 328 scsi_print_addr(sc_link) 329 struct scsipi_link *sc_link; 330 { 331 332 printf("%s(%s:%d:%d): ", 333 sc_link->device_softc ? 334 ((struct device *)sc_link->device_softc)->dv_xname : "probe", 335 ((struct device *)sc_link->adapter_softc)->dv_xname, 336 sc_link->scsipi_scsi.target, sc_link->scsipi_scsi.lun); 337 } 338