1 /* $NetBSD: scsipiconf.c,v 1.16 2001/11/15 09:48:17 lukem Exp $ */ 2 3 /*- 4 * Copyright (c) 1998, 1999 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; by Jason R. Thorpe of the Numerical Aerospace 9 * Simulation Facility, NASA Ames Research Center. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 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. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the NetBSD 22 * Foundation, Inc. and its contributors. 23 * 4. Neither the name of The NetBSD Foundation nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40 /* 41 * Originally written by Julian Elischer (julian@tfs.com) 42 * for TRW Financial Systems for use under the MACH(2.5) operating system. 43 * 44 * TRW Financial Systems, in accordance with their agreement with Carnegie 45 * Mellon University, makes this software available to CMU to distribute 46 * or use in any manner that they see fit as long as this message is kept with 47 * the software. For this reason TFS also grants any other persons or 48 * organisations permission to use or modify this software. 49 * 50 * TFS supplies this software to be publicly redistributed 51 * on the understanding that TFS is not responsible for the correct 52 * functioning of this software in any circumstances. 53 * 54 * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992 55 */ 56 57 #include <sys/cdefs.h> 58 __KERNEL_RCSID(0, "$NetBSD: scsipiconf.c,v 1.16 2001/11/15 09:48:17 lukem Exp $"); 59 60 #include <sys/param.h> 61 #include <sys/systm.h> 62 #include <sys/malloc.h> 63 #include <sys/device.h> 64 #include <sys/proc.h> 65 66 #include <uvm/uvm_extern.h> 67 68 #include <dev/scsipi/scsipi_all.h> 69 #include <dev/scsipi/scsipiconf.h> 70 71 #define STRVIS_ISWHITE(x) ((x) == ' ' || (x) == '\0' || (x) == (u_char)'\377') 72 73 int 74 scsipi_command(periph, cmd, cmdlen, data_addr, datalen, retries, timeout, bp, 75 flags) 76 struct scsipi_periph *periph; 77 struct scsipi_generic *cmd; 78 int cmdlen; 79 u_char *data_addr; 80 int datalen; 81 int retries; 82 int timeout; 83 struct buf *bp; 84 int flags; 85 { 86 int error; 87 88 if ((flags & XS_CTL_DATA_ONSTACK) != 0) { 89 /* 90 * If the I/O buffer is allocated on stack, the 91 * process must NOT be swapped out, as the device will 92 * be accessing the stack. 93 */ 94 PHOLD(curproc); 95 } 96 error = (*periph->periph_channel->chan_bustype->bustype_cmd)(periph, 97 cmd, cmdlen, data_addr, datalen, retries, timeout, bp, flags); 98 if ((flags & XS_CTL_DATA_ONSTACK) != 0) 99 PRELE(curproc); 100 return (error); 101 } 102 103 /* 104 * allocate and init a scsipi_periph structure for a new device. 105 */ 106 struct scsipi_periph * 107 scsipi_alloc_periph(malloc_flag) 108 int malloc_flag; 109 { 110 struct scsipi_periph *periph; 111 int i; 112 113 periph = malloc(sizeof(*periph), M_DEVBUF, malloc_flag); 114 if (periph == NULL) 115 return NULL; 116 memset(periph, 0, sizeof(*periph)); 117 118 periph->periph_dev = NULL; 119 120 /* 121 * Start with one command opening. The periph driver 122 * will grow this if it knows it can take advantage of it. 123 */ 124 periph->periph_openings = 1; 125 periph->periph_active = 0; 126 127 for (i = 0; i < PERIPH_NTAGWORDS; i++) 128 periph->periph_freetags[i] = 0xffffffff; 129 130 TAILQ_INIT(&periph->periph_xferq); 131 callout_init(&periph->periph_callout); 132 133 return periph; 134 } 135 136 /* 137 * Return a priority based on how much of the inquiry data matches 138 * the patterns for the particular driver. 139 */ 140 caddr_t 141 scsipi_inqmatch(inqbuf, base, nmatches, matchsize, bestpriority) 142 struct scsipi_inquiry_pattern *inqbuf; 143 caddr_t base; 144 int nmatches, matchsize; 145 int *bestpriority; 146 { 147 u_int8_t type; 148 caddr_t bestmatch; 149 150 /* Include the qualifier to catch vendor-unique types. */ 151 type = inqbuf->type; 152 153 for (*bestpriority = 0, bestmatch = 0; nmatches--; base += matchsize) { 154 struct scsipi_inquiry_pattern *match = (void *)base; 155 int priority, len; 156 157 if (type != match->type) 158 continue; 159 if (inqbuf->removable != match->removable) 160 continue; 161 priority = 2; 162 len = strlen(match->vendor); 163 if (memcmp(inqbuf->vendor, match->vendor, len)) 164 continue; 165 priority += len; 166 len = strlen(match->product); 167 if (memcmp(inqbuf->product, match->product, len)) 168 continue; 169 priority += len; 170 len = strlen(match->revision); 171 if (memcmp(inqbuf->revision, match->revision, len)) 172 continue; 173 priority += len; 174 175 #ifdef SCSIPI_DEBUG 176 printf("scsipi_inqmatch: %d/%d/%d <%s, %s, %s>\n", 177 priority, match->type, match->removable, 178 match->vendor, match->product, match->revision); 179 #endif 180 if (priority > *bestpriority) { 181 *bestpriority = priority; 182 bestmatch = base; 183 } 184 } 185 186 return (bestmatch); 187 } 188 189 char * 190 scsipi_dtype(type) 191 int type; 192 { 193 char *dtype; 194 195 switch (type) { 196 case T_DIRECT: 197 dtype = "direct"; 198 break; 199 case T_SEQUENTIAL: 200 dtype = "sequential"; 201 break; 202 case T_PRINTER: 203 dtype = "printer"; 204 break; 205 case T_PROCESSOR: 206 dtype = "processor"; 207 break; 208 case T_WORM: 209 dtype = "worm"; 210 break; 211 case T_CDROM: 212 dtype = "cdrom"; 213 break; 214 case T_SCANNER: 215 dtype = "scanner"; 216 break; 217 case T_OPTICAL: 218 dtype = "optical"; 219 break; 220 case T_CHANGER: 221 dtype = "changer"; 222 break; 223 case T_COMM: 224 dtype = "communication"; 225 break; 226 case T_IT8_1: 227 case T_IT8_2: 228 dtype = "graphic arts pre-press"; 229 break; 230 case T_STORARRAY: 231 dtype = "storage array"; 232 break; 233 case T_ENCLOSURE: 234 dtype = "enclosure services"; 235 break; 236 case T_SIMPLE_DIRECT: 237 dtype = "simplified direct"; 238 break; 239 case T_OPTIC_CARD_RW: 240 dtype = "optical card r/w"; 241 break; 242 case T_OBJECT_STORED: 243 dtype = "object-based storage"; 244 break; 245 case T_NODEVICE: 246 panic("scsipi_dtype: impossible device type"); 247 default: 248 dtype = "unknown"; 249 break; 250 } 251 return (dtype); 252 } 253 254 void 255 scsipi_strvis(dst, dlen, src, slen) 256 u_char *dst, *src; 257 int dlen, slen; 258 { 259 260 /* Trim leading and trailing blanks and NULs. */ 261 while (slen > 0 && STRVIS_ISWHITE(src[0])) 262 ++src, --slen; 263 while (slen > 0 && STRVIS_ISWHITE(src[slen - 1])) 264 --slen; 265 266 while (slen > 0) { 267 if (*src < 0x20 || *src >= 0x80) { 268 /* non-printable characters */ 269 dlen -= 4; 270 if (dlen < 1) 271 break; 272 *dst++ = '\\'; 273 *dst++ = ((*src & 0300) >> 6) + '0'; 274 *dst++ = ((*src & 0070) >> 3) + '0'; 275 *dst++ = ((*src & 0007) >> 0) + '0'; 276 } else if (*src == '\\') { 277 /* quote characters */ 278 dlen -= 2; 279 if (dlen < 1) 280 break; 281 *dst++ = '\\'; 282 *dst++ = '\\'; 283 } else { 284 /* normal characters */ 285 if (--dlen < 1) 286 break; 287 *dst++ = *src; 288 } 289 ++src, --slen; 290 } 291 292 *dst++ = 0; 293 } 294