1 /* $NetBSD: atapi_base.c,v 1.27 2008/04/05 15:47:00 cegger Exp $ */
4 * Copyright (c) 1998, 1999, 2004 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Charles M. Hannum; by Jason R. Thorpe of the Numerical Aerospace
9 * Simulation Facility, NASA Ames Research Center.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: atapi_base.c,v 1.27 2008/04/05 15:47:00 cegger Exp $");
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/kernel.h>
41 #include <sys/malloc.h>
42 #include <sys/errno.h>
43 #include <sys/device.h>
46 #include <dev/scsipi/scsipi_all.h>
47 #include <dev/scsipi/scsipiconf.h>
48 #include <dev/scsipi/atapiconf.h>
49 #include <dev/scsipi/scsipi_base.h>
52 * Look at the returned sense and act on the error, determining
53 * the unix error number to pass back. (0 = report no error)
55 * THIS IS THE DEFAULT ERROR HANDLER
58 atapi_interpret_sense(struct scsipi_xfer
*xs
)
60 struct scsipi_periph
*periph
= xs
->xs_periph
;
62 const char *msg
= NULL
;
65 * If the device has it's own error handler, call it first.
66 * If it returns a legit error value, return that, otherwise
67 * it wants us to continue with normal error processing.
69 if (periph
->periph_switch
->psw_error
!= NULL
) {
70 SC_DEBUG(periph
, SCSIPI_DB2
,
71 ("calling private err_handler()\n"));
72 error
= (*periph
->periph_switch
->psw_error
)(xs
);
73 if (error
!= EJUSTRETURN
)
77 * otherwise use the default, call the generic sense handler if we have
78 * more than the sense key
80 if (xs
->error
== XS_SENSE
)
81 return (scsipi_interpret_sense(xs
));
83 key
= (xs
->sense
.atapi_sense
& 0xf0) >> 4;
85 case SKEY_RECOVERED_ERROR
:
86 msg
= "soft error (corrected)";
88 if (xs
->resid
== xs
->datalen
)
89 xs
->resid
= 0; /* not short read */
93 if ((periph
->periph_flags
& PERIPH_REMOVABLE
) != 0)
94 periph
->periph_flags
&= ~PERIPH_MEDIA_LOADED
;
95 if ((xs
->xs_control
& XS_CTL_IGNORE_NOT_READY
) != 0)
97 if ((xs
->xs_control
& XS_CTL_SILENT
) != 0)
102 case SKEY_MEDIUM_ERROR
: /* MEDIUM ERROR */
103 msg
= "medium error";
106 case SKEY_HARDWARE_ERROR
:
107 msg
= "non-media hardware failure";
110 case SKEY_ILLEGAL_REQUEST
:
111 if ((xs
->xs_control
&
112 XS_CTL_IGNORE_ILLEGAL_REQUEST
) != 0)
114 if ((xs
->xs_control
& XS_CTL_SILENT
) != 0)
116 msg
= "illegal request";
119 case SKEY_UNIT_ATTENTION
:
120 if ((periph
->periph_flags
& PERIPH_REMOVABLE
) != 0)
121 periph
->periph_flags
&= ~PERIPH_MEDIA_LOADED
;
122 if ((xs
->xs_control
&
123 XS_CTL_IGNORE_MEDIA_CHANGE
) != 0 ||
124 /* XXX Should reupload any transient state. */
125 (periph
->periph_flags
& PERIPH_REMOVABLE
) == 0)
127 if ((xs
->xs_control
& XS_CTL_SILENT
) != 0)
129 msg
= "unit attention";
132 case SKEY_DATA_PROTECT
:
133 msg
= "readonly device";
136 case SKEY_ABORTED_COMMAND
:
137 msg
= "command aborted";
138 if (xs
->xs_retries
!= 0) {
150 if (xs
->sense
.atapi_sense
& 0x01) {
151 /* Illegal length indication */
152 msg
= "ATA illegal length indication";
155 if (xs
->sense
.atapi_sense
& 0x02) { /* vol overflow */
156 msg
= "ATA volume overflow";
159 if (xs
->sense
.atapi_sense
& 0x04) { /* Aborted command */
160 msg
= "ATA command aborted";
161 if (xs
->xs_retries
!= 0) {
169 scsipi_printaddr(periph
);
173 scsipi_printaddr(periph
);
174 printf("unknown error code %d\n",
175 xs
->sense
.atapi_sense
);
183 * Utility routines often used in SCSI stuff
188 * Print out the scsi_link structure's address info.
191 atapi_print_addr(struct scsipi_periph
*periph
)
193 struct scsipi_channel
*chan
= periph
->periph_channel
;
194 struct scsipi_adapter
*adapt
= chan
->chan_adapter
;
196 printf("%s(%s:%d:%d): ", periph
->periph_dev
!= NULL
?
197 device_xname(periph
->periph_dev
) : "probe",
198 device_xname(adapt
->adapt_dev
),
199 chan
->chan_channel
, periph
->periph_target
);
203 * ask the atapi driver to perform a command for us.
204 * tell it where to read/write the data, and how
205 * long the data is supposed to be. If we have a buf
206 * to associate with the transfer, we need that too.
209 atapi_scsipi_cmd(struct scsipi_xfer
*xs
)
211 struct scsipi_periph
*periph
= xs
->xs_periph
;
213 SC_DEBUG(periph
, SCSIPI_DB2
, ("atapi_cmd\n"));
215 xs
->cmdlen
= (periph
->periph_cap
& PERIPH_CAP_CMD16
) ? 16 : 12;