atapi_base.c revision 1.30 1 1.30 mrg /* $NetBSD: atapi_base.c,v 1.30 2019/02/03 03:19:28 mrg Exp $ */
2 1.2 bouyer
3 1.9 mycroft /*-
4 1.23 mycroft * Copyright (c) 1998, 1999, 2004 The NetBSD Foundation, Inc.
5 1.9 mycroft * All rights reserved.
6 1.9 mycroft *
7 1.9 mycroft * This code is derived from software contributed to The NetBSD Foundation
8 1.15 bouyer * by Charles M. Hannum; by Jason R. Thorpe of the Numerical Aerospace
9 1.15 bouyer * Simulation Facility, NASA Ames Research Center.
10 1.2 bouyer *
11 1.2 bouyer * Redistribution and use in source and binary forms, with or without
12 1.2 bouyer * modification, are permitted provided that the following conditions
13 1.2 bouyer * are met:
14 1.2 bouyer * 1. Redistributions of source code must retain the above copyright
15 1.2 bouyer * notice, this list of conditions and the following disclaimer.
16 1.2 bouyer * 2. Redistributions in binary form must reproduce the above copyright
17 1.2 bouyer * notice, this list of conditions and the following disclaimer in the
18 1.2 bouyer * documentation and/or other materials provided with the distribution.
19 1.2 bouyer *
20 1.9 mycroft * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 1.9 mycroft * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 1.9 mycroft * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 1.9 mycroft * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 1.9 mycroft * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 1.9 mycroft * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 1.9 mycroft * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 1.9 mycroft * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 1.9 mycroft * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 1.9 mycroft * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 1.9 mycroft * POSSIBILITY OF SUCH DAMAGE.
31 1.2 bouyer */
32 1.17 lukem
33 1.17 lukem #include <sys/cdefs.h>
34 1.30 mrg __KERNEL_RCSID(0, "$NetBSD: atapi_base.c,v 1.30 2019/02/03 03:19:28 mrg Exp $");
35 1.2 bouyer
36 1.2 bouyer #include <sys/param.h>
37 1.2 bouyer #include <sys/systm.h>
38 1.2 bouyer #include <sys/kernel.h>
39 1.2 bouyer #include <sys/buf.h>
40 1.2 bouyer #include <sys/uio.h>
41 1.2 bouyer #include <sys/malloc.h>
42 1.2 bouyer #include <sys/errno.h>
43 1.2 bouyer #include <sys/device.h>
44 1.2 bouyer #include <sys/proc.h>
45 1.2 bouyer
46 1.2 bouyer #include <dev/scsipi/scsipi_all.h>
47 1.5 cgd #include <dev/scsipi/scsipiconf.h>
48 1.2 bouyer #include <dev/scsipi/atapiconf.h>
49 1.2 bouyer #include <dev/scsipi/scsipi_base.h>
50 1.2 bouyer
51 1.2 bouyer /*
52 1.2 bouyer * Look at the returned sense and act on the error, determining
53 1.2 bouyer * the unix error number to pass back. (0 = report no error)
54 1.2 bouyer *
55 1.2 bouyer * THIS IS THE DEFAULT ERROR HANDLER
56 1.2 bouyer */
57 1.3 enami int
58 1.20 thorpej atapi_interpret_sense(struct scsipi_xfer *xs)
59 1.2 bouyer {
60 1.15 bouyer struct scsipi_periph *periph = xs->xs_periph;
61 1.2 bouyer int key, error;
62 1.25 christos const char *msg = NULL;
63 1.2 bouyer
64 1.2 bouyer /*
65 1.29 snj * If the device has its own error handler, call it first.
66 1.2 bouyer * If it returns a legit error value, return that, otherwise
67 1.2 bouyer * it wants us to continue with normal error processing.
68 1.2 bouyer */
69 1.15 bouyer if (periph->periph_switch->psw_error != NULL) {
70 1.15 bouyer SC_DEBUG(periph, SCSIPI_DB2,
71 1.2 bouyer ("calling private err_handler()\n"));
72 1.15 bouyer error = (*periph->periph_switch->psw_error)(xs);
73 1.15 bouyer if (error != EJUSTRETURN)
74 1.15 bouyer return (error);
75 1.2 bouyer }
76 1.11 bouyer /*
77 1.11 bouyer * otherwise use the default, call the generic sense handler if we have
78 1.11 bouyer * more than the sense key
79 1.11 bouyer */
80 1.11 bouyer if (xs->error == XS_SENSE)
81 1.11 bouyer return (scsipi_interpret_sense(xs));
82 1.11 bouyer
83 1.11 bouyer key = (xs->sense.atapi_sense & 0xf0) >> 4;
84 1.2 bouyer switch (key) {
85 1.7 mjacob case SKEY_RECOVERED_ERROR:
86 1.2 bouyer msg = "soft error (corrected)";
87 1.30 mrg /* FALLTHROUGH */
88 1.6 mjacob case SKEY_NO_SENSE:
89 1.2 bouyer if (xs->resid == xs->datalen)
90 1.2 bouyer xs->resid = 0; /* not short read */
91 1.6 mjacob error = 0;
92 1.6 mjacob break;
93 1.6 mjacob case SKEY_NOT_READY:
94 1.15 bouyer if ((periph->periph_flags & PERIPH_REMOVABLE) != 0)
95 1.15 bouyer periph->periph_flags &= ~PERIPH_MEDIA_LOADED;
96 1.14 thorpej if ((xs->xs_control & XS_CTL_IGNORE_NOT_READY) != 0)
97 1.3 enami return (0);
98 1.14 thorpej if ((xs->xs_control & XS_CTL_SILENT) != 0)
99 1.3 enami return (EIO);
100 1.2 bouyer msg = "not ready";
101 1.2 bouyer error = EIO;
102 1.2 bouyer break;
103 1.6 mjacob case SKEY_MEDIUM_ERROR: /* MEDIUM ERROR */
104 1.2 bouyer msg = "medium error";
105 1.2 bouyer error = EIO;
106 1.2 bouyer break;
107 1.6 mjacob case SKEY_HARDWARE_ERROR:
108 1.2 bouyer msg = "non-media hardware failure";
109 1.2 bouyer error = EIO;
110 1.2 bouyer break;
111 1.6 mjacob case SKEY_ILLEGAL_REQUEST:
112 1.14 thorpej if ((xs->xs_control &
113 1.14 thorpej XS_CTL_IGNORE_ILLEGAL_REQUEST) != 0)
114 1.3 enami return (0);
115 1.14 thorpej if ((xs->xs_control & XS_CTL_SILENT) != 0)
116 1.3 enami return (EIO);
117 1.2 bouyer msg = "illegal request";
118 1.2 bouyer error = EINVAL;
119 1.2 bouyer break;
120 1.6 mjacob case SKEY_UNIT_ATTENTION:
121 1.15 bouyer if ((periph->periph_flags & PERIPH_REMOVABLE) != 0)
122 1.15 bouyer periph->periph_flags &= ~PERIPH_MEDIA_LOADED;
123 1.14 thorpej if ((xs->xs_control &
124 1.14 thorpej XS_CTL_IGNORE_MEDIA_CHANGE) != 0 ||
125 1.2 bouyer /* XXX Should reupload any transient state. */
126 1.15 bouyer (periph->periph_flags & PERIPH_REMOVABLE) == 0)
127 1.3 enami return (ERESTART);
128 1.14 thorpej if ((xs->xs_control & XS_CTL_SILENT) != 0)
129 1.3 enami return (EIO);
130 1.2 bouyer msg = "unit attention";
131 1.2 bouyer error = EIO;
132 1.2 bouyer break;
133 1.24 thorpej case SKEY_DATA_PROTECT:
134 1.2 bouyer msg = "readonly device";
135 1.4 is error = EROFS;
136 1.2 bouyer break;
137 1.6 mjacob case SKEY_ABORTED_COMMAND:
138 1.2 bouyer msg = "command aborted";
139 1.19 bouyer if (xs->xs_retries != 0) {
140 1.19 bouyer xs->xs_retries--;
141 1.19 bouyer error = ERESTART;
142 1.19 bouyer } else
143 1.19 bouyer error = EIO;
144 1.2 bouyer break;
145 1.2 bouyer default:
146 1.2 bouyer error = EIO;
147 1.2 bouyer break;
148 1.2 bouyer }
149 1.2 bouyer
150 1.2 bouyer if (!key) {
151 1.2 bouyer if (xs->sense.atapi_sense & 0x01) {
152 1.2 bouyer /* Illegal length indication */
153 1.2 bouyer msg = "ATA illegal length indication";
154 1.2 bouyer error = EIO;
155 1.2 bouyer }
156 1.2 bouyer if (xs->sense.atapi_sense & 0x02) { /* vol overflow */
157 1.2 bouyer msg = "ATA volume overflow";
158 1.2 bouyer error = ENOSPC;
159 1.2 bouyer }
160 1.2 bouyer if (xs->sense.atapi_sense & 0x04) { /* Aborted command */
161 1.2 bouyer msg = "ATA command aborted";
162 1.19 bouyer if (xs->xs_retries != 0) {
163 1.19 bouyer xs->xs_retries--;
164 1.19 bouyer error = ERESTART;
165 1.19 bouyer } else
166 1.19 bouyer error = EIO;
167 1.2 bouyer }
168 1.2 bouyer }
169 1.2 bouyer if (msg) {
170 1.15 bouyer scsipi_printaddr(periph);
171 1.2 bouyer printf("%s\n", msg);
172 1.2 bouyer } else {
173 1.2 bouyer if (error) {
174 1.15 bouyer scsipi_printaddr(periph);
175 1.2 bouyer printf("unknown error code %d\n",
176 1.2 bouyer xs->sense.atapi_sense);
177 1.2 bouyer }
178 1.2 bouyer }
179 1.2 bouyer
180 1.3 enami return (error);
181 1.2 bouyer }
182 1.2 bouyer
183 1.2 bouyer /*
184 1.2 bouyer * Utility routines often used in SCSI stuff
185 1.2 bouyer */
186 1.2 bouyer
187 1.2 bouyer
188 1.2 bouyer /*
189 1.2 bouyer * Print out the scsi_link structure's address info.
190 1.2 bouyer */
191 1.2 bouyer void
192 1.20 thorpej atapi_print_addr(struct scsipi_periph *periph)
193 1.2 bouyer {
194 1.15 bouyer struct scsipi_channel *chan = periph->periph_channel;
195 1.15 bouyer struct scsipi_adapter *adapt = chan->chan_adapter;
196 1.2 bouyer
197 1.15 bouyer printf("%s(%s:%d:%d): ", periph->periph_dev != NULL ?
198 1.27 cegger device_xname(periph->periph_dev) : "probe",
199 1.27 cegger device_xname(adapt->adapt_dev),
200 1.15 bouyer chan->chan_channel, periph->periph_target);
201 1.2 bouyer }
202 1.2 bouyer
203 1.2 bouyer /*
204 1.2 bouyer * ask the atapi driver to perform a command for us.
205 1.2 bouyer * tell it where to read/write the data, and how
206 1.2 bouyer * long the data is supposed to be. If we have a buf
207 1.2 bouyer * to associate with the transfer, we need that too.
208 1.2 bouyer */
209 1.23 mycroft void
210 1.23 mycroft atapi_scsipi_cmd(struct scsipi_xfer *xs)
211 1.2 bouyer {
212 1.23 mycroft struct scsipi_periph *periph = xs->xs_periph;
213 1.2 bouyer
214 1.15 bouyer SC_DEBUG(periph, SCSIPI_DB2, ("atapi_cmd\n"));
215 1.2 bouyer
216 1.15 bouyer xs->cmdlen = (periph->periph_cap & PERIPH_CAP_CMD16) ? 16 : 12;
217 1.2 bouyer }
218