1 /* $NetBSD: atapi_base.c,v 1.10 1998/10/12 16:09:23 bouyer Exp $ */ 2 3 /*- 4 * Copyright (c) 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Charles M. Hannum. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 #include <sys/types.h> 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/kernel.h> 43 #include <sys/buf.h> 44 #include <sys/uio.h> 45 #include <sys/malloc.h> 46 #include <sys/errno.h> 47 #include <sys/device.h> 48 #include <sys/proc.h> 49 50 #include <dev/scsipi/scsipi_all.h> 51 #include <dev/scsipi/atapi_all.h> 52 #include <dev/scsipi/scsipiconf.h> 53 #include <dev/scsipi/atapiconf.h> 54 #include <dev/scsipi/scsipi_base.h> 55 56 /* 57 * Look at the returned sense and act on the error, determining 58 * the unix error number to pass back. (0 = report no error) 59 * 60 * THIS IS THE DEFAULT ERROR HANDLER 61 */ 62 int 63 atapi_interpret_sense(xs) 64 struct scsipi_xfer *xs; 65 { 66 int key, error; 67 struct scsipi_link *sc_link = xs->sc_link; 68 char *msg = NULL; 69 70 key = (xs->sense.atapi_sense & 0xf0) >> 4; 71 /* 72 * If the device has it's own error handler, call it first. 73 * If it returns a legit error value, return that, otherwise 74 * it wants us to continue with normal error processing. 75 */ 76 if (sc_link->device->err_handler) { 77 SC_DEBUG(sc_link, SDEV_DB2, 78 ("calling private err_handler()\n")); 79 error = (*sc_link->device->err_handler) (xs); 80 if (error != SCSIRET_CONTINUE) 81 return (error); /* error >= 0 better ? */ 82 } 83 /* otherwise use the default */ 84 switch (key) { 85 case SKEY_RECOVERED_ERROR: 86 msg = "soft error (corrected)"; 87 case SKEY_NO_SENSE: 88 if (xs->resid == xs->datalen) 89 xs->resid = 0; /* not short read */ 90 error = 0; 91 break; 92 case SKEY_NOT_READY: 93 if ((sc_link->flags & SDEV_REMOVABLE) != 0) 94 sc_link->flags &= ~SDEV_MEDIA_LOADED; 95 if ((xs->flags & SCSI_IGNORE_NOT_READY) != 0) 96 return (0); 97 if ((xs->flags & SCSI_SILENT) != 0) 98 return (EIO); 99 msg = "not ready"; 100 error = EIO; 101 break; 102 case SKEY_MEDIUM_ERROR: /* MEDIUM ERROR */ 103 msg = "medium error"; 104 error = EIO; 105 break; 106 case SKEY_HARDWARE_ERROR: 107 msg = "non-media hardware failure"; 108 error = EIO; 109 break; 110 case SKEY_ILLEGAL_REQUEST: 111 if ((xs->flags & SCSI_IGNORE_ILLEGAL_REQUEST) != 0) 112 return (0); 113 if ((xs->flags & SCSI_SILENT) != 0) 114 return (EIO); 115 msg = "illegal request"; 116 error = EINVAL; 117 break; 118 case SKEY_UNIT_ATTENTION: 119 if ((sc_link->flags & SDEV_REMOVABLE) != 0) 120 sc_link->flags &= ~SDEV_MEDIA_LOADED; 121 if ((xs->flags & SCSI_IGNORE_MEDIA_CHANGE) != 0 || 122 /* XXX Should reupload any transient state. */ 123 (sc_link->flags & SDEV_REMOVABLE) == 0) 124 return (ERESTART); 125 if ((xs->flags & SCSI_SILENT) != 0) 126 return (EIO); 127 msg = "unit attention"; 128 error = EIO; 129 break; 130 case SKEY_WRITE_PROTECT: 131 msg = "readonly device"; 132 error = EROFS; 133 break; 134 case SKEY_ABORTED_COMMAND: 135 msg = "command aborted"; 136 error = ERESTART; 137 break; 138 default: 139 error = EIO; 140 break; 141 } 142 143 if (!key) { 144 if (xs->sense.atapi_sense & 0x01) { 145 /* Illegal length indication */ 146 msg = "ATA illegal length indication"; 147 error = EIO; 148 } 149 if (xs->sense.atapi_sense & 0x02) { /* vol overflow */ 150 msg = "ATA volume overflow"; 151 error = ENOSPC; 152 } 153 if (xs->sense.atapi_sense & 0x04) { /* Aborted command */ 154 msg = "ATA command aborted"; 155 error = ERESTART; 156 } 157 } 158 if (msg) { 159 sc_link->sc_print_addr(sc_link); 160 printf("%s\n", msg); 161 } else { 162 if (error) { 163 sc_link->sc_print_addr(sc_link); 164 printf("unknown error code %d\n", 165 xs->sense.atapi_sense); 166 } 167 } 168 169 return (error); 170 171 } 172 173 /* 174 * Utility routines often used in SCSI stuff 175 */ 176 177 178 /* 179 * Print out the scsi_link structure's address info. 180 */ 181 void 182 atapi_print_addr(sc_link) 183 struct scsipi_link *sc_link; 184 { 185 186 printf("%s(%s:%d:%d): ", 187 sc_link->device_softc ? 188 ((struct device *)sc_link->device_softc)->dv_xname : "probe", 189 ((struct device *)sc_link->adapter_softc)->dv_xname, 190 sc_link->scsipi_atapi.channel, sc_link->scsipi_atapi.drive); 191 } 192 193 /* 194 * ask the atapi driver to perform a command for us. 195 * tell it where to read/write the data, and how 196 * long the data is supposed to be. If we have a buf 197 * to associate with the transfer, we need that too. 198 */ 199 int 200 atapi_scsipi_cmd(sc_link, scsipi_cmd, cmdlen, data_addr, datalen, 201 retries, timeout, bp, flags) 202 struct scsipi_link *sc_link; 203 struct scsipi_generic *scsipi_cmd; 204 int cmdlen; 205 u_char *data_addr; 206 int datalen; 207 int retries; 208 int timeout; 209 struct buf *bp; 210 int flags; 211 { 212 struct scsipi_xfer *xs; 213 int error; 214 215 SC_DEBUG(sc_link, SDEV_DB2, ("atapi_cmd\n")); 216 217 #ifdef DIAGNOSTIC 218 if (bp != 0 && (flags & SCSI_NOSLEEP) == 0) 219 panic("atapi_scsipi_cmd: buffer without nosleep"); 220 #endif 221 222 if ((xs = scsipi_make_xs(sc_link, scsipi_cmd, cmdlen, data_addr, 223 datalen, retries, timeout, bp, flags)) == NULL) 224 return (ENOMEM); 225 226 xs->cmdlen = (sc_link->scsipi_atapi.cap & ACAP_LEN) ? 16 : 12; 227 228 if ((error = scsipi_execute_xs(xs)) == EJUSTRETURN) 229 return (0); 230 231 /* 232 * we have finished with the xfer stuct, free it and 233 * check if anyone else needs to be started up. 234 */ 235 scsipi_free_xs(xs, flags); 236 return (error); 237 } 238 239 int 240 atapi_mode_select(l, data, len, flags, retries, timeout) 241 struct scsipi_link *l; 242 struct atapi_mode_header *data; 243 int len, flags, retries, timeout; 244 { 245 struct atapi_mode_select scsipi_cmd; 246 int error; 247 248 bzero(&scsipi_cmd, sizeof(scsipi_cmd)); 249 scsipi_cmd.opcode = ATAPI_MODE_SELECT; 250 scsipi_cmd.byte2 = AMS_PF; 251 _lto2b(len, scsipi_cmd.length); 252 253 /* length is reserved when doing mode select; zero it */ 254 _lto2l(0, data->length); 255 256 error = scsipi_command(l, (struct scsipi_generic *)&scsipi_cmd, 257 sizeof(scsipi_cmd), (void *)data, len, retries, timeout, NULL, 258 flags | SCSI_DATA_OUT); 259 SC_DEBUG(l, SDEV_DB2, ("atapi_mode_select: error=%d\n", error)); 260 return (error); 261 } 262 263 int 264 atapi_mode_sense(l, page, data, len, flags, retries, timeout) 265 struct scsipi_link *l; 266 int page, len, flags, retries, timeout; 267 struct atapi_mode_header *data; 268 { 269 struct atapi_mode_sense scsipi_cmd; 270 int error; 271 272 bzero(&scsipi_cmd, sizeof(scsipi_cmd)); 273 scsipi_cmd.opcode = ATAPI_MODE_SENSE; 274 scsipi_cmd.page = page; 275 _lto2b(len, scsipi_cmd.length); 276 277 error = scsipi_command(l, (struct scsipi_generic *)&scsipi_cmd, 278 sizeof(scsipi_cmd), (void *)data, len, retries, timeout, NULL, 279 flags | SCSI_DATA_IN); 280 SC_DEBUG(l, SDEV_DB2, ("atapi_mode_sense: error=%d\n", error)); 281 return (error); 282 } 283