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