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