atapi_base.c revision 1.29 1 1.29 snj /* $NetBSD: atapi_base.c,v 1.29 2014/10/18 08:33:28 snj 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.29 snj __KERNEL_RCSID(0, "$NetBSD: atapi_base.c,v 1.29 2014/10/18 08:33:28 snj 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.6 mjacob case SKEY_NO_SENSE:
88 1.2 bouyer if (xs->resid == xs->datalen)
89 1.2 bouyer xs->resid = 0; /* not short read */
90 1.6 mjacob error = 0;
91 1.6 mjacob break;
92 1.6 mjacob case SKEY_NOT_READY:
93 1.15 bouyer if ((periph->periph_flags & PERIPH_REMOVABLE) != 0)
94 1.15 bouyer periph->periph_flags &= ~PERIPH_MEDIA_LOADED;
95 1.14 thorpej if ((xs->xs_control & XS_CTL_IGNORE_NOT_READY) != 0)
96 1.3 enami return (0);
97 1.14 thorpej if ((xs->xs_control & XS_CTL_SILENT) != 0)
98 1.3 enami return (EIO);
99 1.2 bouyer msg = "not ready";
100 1.2 bouyer error = EIO;
101 1.2 bouyer break;
102 1.6 mjacob case SKEY_MEDIUM_ERROR: /* MEDIUM ERROR */
103 1.2 bouyer msg = "medium error";
104 1.2 bouyer error = EIO;
105 1.2 bouyer break;
106 1.6 mjacob case SKEY_HARDWARE_ERROR:
107 1.2 bouyer msg = "non-media hardware failure";
108 1.2 bouyer error = EIO;
109 1.2 bouyer break;
110 1.6 mjacob case SKEY_ILLEGAL_REQUEST:
111 1.14 thorpej if ((xs->xs_control &
112 1.14 thorpej XS_CTL_IGNORE_ILLEGAL_REQUEST) != 0)
113 1.3 enami return (0);
114 1.14 thorpej if ((xs->xs_control & XS_CTL_SILENT) != 0)
115 1.3 enami return (EIO);
116 1.2 bouyer msg = "illegal request";
117 1.2 bouyer error = EINVAL;
118 1.2 bouyer break;
119 1.6 mjacob case SKEY_UNIT_ATTENTION:
120 1.15 bouyer if ((periph->periph_flags & PERIPH_REMOVABLE) != 0)
121 1.15 bouyer periph->periph_flags &= ~PERIPH_MEDIA_LOADED;
122 1.14 thorpej if ((xs->xs_control &
123 1.14 thorpej XS_CTL_IGNORE_MEDIA_CHANGE) != 0 ||
124 1.2 bouyer /* XXX Should reupload any transient state. */
125 1.15 bouyer (periph->periph_flags & PERIPH_REMOVABLE) == 0)
126 1.3 enami return (ERESTART);
127 1.14 thorpej if ((xs->xs_control & XS_CTL_SILENT) != 0)
128 1.3 enami return (EIO);
129 1.2 bouyer msg = "unit attention";
130 1.2 bouyer error = EIO;
131 1.2 bouyer break;
132 1.24 thorpej case SKEY_DATA_PROTECT:
133 1.2 bouyer msg = "readonly device";
134 1.4 is error = EROFS;
135 1.2 bouyer break;
136 1.6 mjacob case SKEY_ABORTED_COMMAND:
137 1.2 bouyer msg = "command aborted";
138 1.19 bouyer if (xs->xs_retries != 0) {
139 1.19 bouyer xs->xs_retries--;
140 1.19 bouyer error = ERESTART;
141 1.19 bouyer } else
142 1.19 bouyer error = EIO;
143 1.2 bouyer break;
144 1.2 bouyer default:
145 1.2 bouyer error = EIO;
146 1.2 bouyer break;
147 1.2 bouyer }
148 1.2 bouyer
149 1.2 bouyer if (!key) {
150 1.2 bouyer if (xs->sense.atapi_sense & 0x01) {
151 1.2 bouyer /* Illegal length indication */
152 1.2 bouyer msg = "ATA illegal length indication";
153 1.2 bouyer error = EIO;
154 1.2 bouyer }
155 1.2 bouyer if (xs->sense.atapi_sense & 0x02) { /* vol overflow */
156 1.2 bouyer msg = "ATA volume overflow";
157 1.2 bouyer error = ENOSPC;
158 1.2 bouyer }
159 1.2 bouyer if (xs->sense.atapi_sense & 0x04) { /* Aborted command */
160 1.2 bouyer msg = "ATA command aborted";
161 1.19 bouyer if (xs->xs_retries != 0) {
162 1.19 bouyer xs->xs_retries--;
163 1.19 bouyer error = ERESTART;
164 1.19 bouyer } else
165 1.19 bouyer error = EIO;
166 1.2 bouyer }
167 1.2 bouyer }
168 1.2 bouyer if (msg) {
169 1.15 bouyer scsipi_printaddr(periph);
170 1.2 bouyer printf("%s\n", msg);
171 1.2 bouyer } else {
172 1.2 bouyer if (error) {
173 1.15 bouyer scsipi_printaddr(periph);
174 1.2 bouyer printf("unknown error code %d\n",
175 1.2 bouyer xs->sense.atapi_sense);
176 1.2 bouyer }
177 1.2 bouyer }
178 1.2 bouyer
179 1.3 enami return (error);
180 1.2 bouyer }
181 1.2 bouyer
182 1.2 bouyer /*
183 1.2 bouyer * Utility routines often used in SCSI stuff
184 1.2 bouyer */
185 1.2 bouyer
186 1.2 bouyer
187 1.2 bouyer /*
188 1.2 bouyer * Print out the scsi_link structure's address info.
189 1.2 bouyer */
190 1.2 bouyer void
191 1.20 thorpej atapi_print_addr(struct scsipi_periph *periph)
192 1.2 bouyer {
193 1.15 bouyer struct scsipi_channel *chan = periph->periph_channel;
194 1.15 bouyer struct scsipi_adapter *adapt = chan->chan_adapter;
195 1.2 bouyer
196 1.15 bouyer printf("%s(%s:%d:%d): ", periph->periph_dev != NULL ?
197 1.27 cegger device_xname(periph->periph_dev) : "probe",
198 1.27 cegger device_xname(adapt->adapt_dev),
199 1.15 bouyer chan->chan_channel, periph->periph_target);
200 1.2 bouyer }
201 1.2 bouyer
202 1.2 bouyer /*
203 1.2 bouyer * ask the atapi driver to perform a command for us.
204 1.2 bouyer * tell it where to read/write the data, and how
205 1.2 bouyer * long the data is supposed to be. If we have a buf
206 1.2 bouyer * to associate with the transfer, we need that too.
207 1.2 bouyer */
208 1.23 mycroft void
209 1.23 mycroft atapi_scsipi_cmd(struct scsipi_xfer *xs)
210 1.2 bouyer {
211 1.23 mycroft struct scsipi_periph *periph = xs->xs_periph;
212 1.2 bouyer
213 1.15 bouyer SC_DEBUG(periph, SCSIPI_DB2, ("atapi_cmd\n"));
214 1.2 bouyer
215 1.15 bouyer xs->cmdlen = (periph->periph_cap & PERIPH_CAP_CMD16) ? 16 : 12;
216 1.2 bouyer }
217