scsi_base.c revision 1.63 1 /* $NetBSD: scsi_base.c,v 1.63 1998/07/15 20:13:30 mjacob 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 (at) 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 != SCSIRET_CONTINUE)
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 SKEY_NO_SENSE:
212 case SKEY_RECOVERED_ERROR:
213 if (xs->resid == xs->datalen && xs->datalen) {
214 /*
215 * Why is this here?
216 */
217 xs->resid = 0; /* not short read */
218 }
219 case SKEY_EQUAL:
220 error = 0;
221 break;
222 case SKEY_NOT_READY:
223 if ((sc_link->flags & SDEV_REMOVABLE) != 0)
224 sc_link->flags &= ~SDEV_MEDIA_LOADED;
225 if ((xs->flags & SCSI_IGNORE_NOT_READY) != 0)
226 return (0);
227 if ((xs->flags & SCSI_SILENT) != 0)
228 return (EIO);
229 error = EIO;
230 break;
231 case SKEY_ILLEGAL_REQUEST:
232 if ((xs->flags & SCSI_IGNORE_ILLEGAL_REQUEST) != 0)
233 return (0);
234 if ((xs->flags & SCSI_SILENT) != 0)
235 return (EIO);
236 error = EINVAL;
237 break;
238 case SKEY_UNIT_ATTENTION:
239 if ((sc_link->flags & SDEV_REMOVABLE) != 0)
240 sc_link->flags &= ~SDEV_MEDIA_LOADED;
241 if ((xs->flags & SCSI_IGNORE_MEDIA_CHANGE) != 0 ||
242 /* XXX Should reupload any transient state. */
243 (sc_link->flags & SDEV_REMOVABLE) == 0)
244 return (ERESTART);
245 if ((xs->flags & SCSI_SILENT) != 0)
246 return (EIO);
247 error = EIO;
248 break;
249 case SKEY_WRITE_PROTECT:
250 error = EROFS;
251 break;
252 case SKEY_BLANK_CHECK:
253 error = 0;
254 break;
255 case SKEY_ABORTED_COMMAND:
256 error = ERESTART;
257 break;
258 case SKEY_VOLUME_OVERFLOW:
259 error = ENOSPC;
260 break;
261 default:
262 error = EIO;
263 break;
264 }
265
266 #ifdef SCSIVERBOSE
267 if ((xs->flags & SCSI_SILENT) == 0)
268 scsi_print_sense(xs, 0);
269 #else
270 if (key) {
271 sc_link->sc_print_addr(sc_link);
272 printf("%s", error_mes[key - 1]);
273 if ((sense->error_code & SSD_ERRCODE_VALID) != 0) {
274 switch (key) {
275 case SKEY_NOT_READY:
276 case SKEY_ILLEGAL_REQUEST:
277 case SKEY_UNIT_ATTENTION:
278 case SKEY_WRITE_PROTECT:
279 break;
280 case SKEY_BLANK_CHECK:
281 printf(", requested size: %d (decimal)",
282 info);
283 break;
284 case SKEY_ABORTED_COMMAND:
285 if (xs->retries)
286 printf(", retrying");
287 printf(", cmd 0x%x, info 0x%x",
288 xs->cmd->opcode, info);
289 break;
290 default:
291 printf(", info = %d (decimal)", info);
292 }
293 }
294 if (sense->extra_len != 0) {
295 int n;
296 printf(", data =");
297 for (n = 0; n < sense->extra_len; n++)
298 printf(" %02x",
299 sense->cmd_spec_info[n]);
300 }
301 printf("\n");
302 }
303 #endif
304 return (error);
305
306 /*
307 * Not code 70, just report it
308 */
309 default:
310 sc_link->sc_print_addr(sc_link);
311 printf("error code %d", sense->error_code & SSD_ERRCODE);
312 if ((sense->error_code & SSD_ERRCODE_VALID) != 0) {
313 struct scsipi_sense_data_unextended *usense =
314 (struct scsipi_sense_data_unextended *)sense;
315 printf(" at block no. %d (decimal)",
316 _3btol(usense->block));
317 }
318 printf("\n");
319 return (EIO);
320 }
321 }
322
323 /*
324 * Utility routines often used in SCSI stuff
325 */
326
327
328 /*
329 * Print out the scsi_link structure's address info.
330 */
331 void
332 scsi_print_addr(sc_link)
333 struct scsipi_link *sc_link;
334 {
335
336 printf("%s(%s:%d:%d): ",
337 sc_link->device_softc ?
338 ((struct device *)sc_link->device_softc)->dv_xname : "probe",
339 ((struct device *)sc_link->adapter_softc)->dv_xname,
340 sc_link->scsipi_scsi.target, sc_link->scsipi_scsi.lun);
341 }
342