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