scsi_subr.c revision 1.7 1 /* $NetBSD: scsi_subr.c,v 1.7 2002/10/08 20:17:06 soren 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; 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 * SCSI support subroutines.
42 *
43 * XXX THESE SHOULD BE IN A LIBRARY!
44 */
45
46 #include <sys/param.h>
47 #include <sys/ioctl.h>
48 #include <sys/scsiio.h>
49 #include <err.h>
50 #include <errno.h>
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <string.h>
54 #include <unistd.h>
55
56 #include <dev/scsipi/scsipi_all.h>
57
58 #include "extern.h"
59
60 #define STRVIS_ISWHITE(x) ((x) == ' ' || (x) == '\0' || (x) == (u_char)'\377')
61
62 void
63 scsi_command(fd, cmd, cmdlen, data, datalen, timeout, flags)
64 int fd;
65 void *cmd;
66 size_t cmdlen;
67 void *data;
68 size_t datalen;
69 int timeout, flags;
70 {
71 scsireq_t req;
72
73 memset(&req, 0, sizeof(req));
74
75 memcpy(req.cmd, cmd, cmdlen);
76 req.cmdlen = cmdlen;
77 req.databuf = data;
78 req.datalen = datalen;
79 req.timeout = timeout;
80 req.flags = flags;
81 req.senselen = SENSEBUFLEN;
82
83 if (ioctl(fd, SCIOCCOMMAND, &req) == -1)
84 err(1, "SCIOCCOMMAND");
85
86 if (req.retsts == SCCMD_OK)
87 return;
88
89 /* Some problem; report it and exit. */
90 if (req.retsts == SCCMD_TIMEOUT)
91 fprintf(stderr, "%s: SCSI command timed out\n", dvname);
92 else if (req.retsts == SCCMD_BUSY)
93 fprintf(stderr, "%s: device is busy\n", dvname);
94 else if (req.retsts == SCCMD_SENSE)
95 scsi_print_sense(dvname, &req, 1);
96 else
97 fprintf(stderr, "%s: device had unknown status %x\n", dvname,
98 req.retsts);
99
100 exit(1);
101 }
102
103 void
104 scsi_mode_sense(fd, pgcode, pctl, buf, len)
105 int fd;
106 u_int8_t pgcode, pctl;
107 void *buf;
108 size_t len;
109 {
110 struct scsipi_mode_sense cmd;
111
112 memset(&cmd, 0, sizeof(cmd));
113 memset(buf, 0, len);
114
115 cmd.opcode = MODE_SENSE;
116 cmd.page = pgcode | pctl;
117 cmd.u_len.scsi.length = len;
118
119 scsi_command(fd, &cmd, sizeof(cmd), buf, len, 10000, SCCMD_READ);
120 }
121
122 void
123 scsi_mode_select(fd, byte2, buf, len)
124 int fd;
125 u_int8_t byte2;
126 void *buf;
127 size_t len;
128 {
129 struct scsipi_mode_select cmd;
130
131 memset(&cmd, 0, sizeof(cmd));
132
133 cmd.opcode = MODE_SELECT;
134 cmd.byte2 = SMS_PF | byte2;
135 cmd.u_len.scsi.length = len;
136
137 scsi_command(fd, &cmd, sizeof(cmd), buf, len, 10000, SCCMD_WRITE);
138 }
139
140 void
141 scsi_request_sense(fd, buf, len)
142 int fd;
143 void *buf;
144 size_t len;
145 {
146 struct scsipi_sense cmd;
147
148 memset(&cmd, 0, sizeof(cmd));
149 memset(buf, 0, len);
150
151 cmd.opcode = REQUEST_SENSE;
152 cmd.length = len;
153 scsi_command(fd, &cmd, sizeof(cmd), buf, len, 10000, SCCMD_READ);
154 }
155
156 void
157 scsi_strvis(sdst, dlen, ssrc, slen)
158 char *sdst;
159 size_t dlen;
160 const char *ssrc;
161 size_t slen;
162 {
163 u_char *dst = (u_char *)sdst;
164 const u_char *src = (const u_char *)ssrc;
165
166 /* Trim leading and trailing blanks and NULs. */
167 while (slen > 0 && STRVIS_ISWHITE(src[0]))
168 ++src, --slen;
169 while (slen > 0 && STRVIS_ISWHITE(src[slen - 1]))
170 --slen;
171
172 while (slen > 0) {
173 if (*src < 0x20 || *src >= 0x80) {
174 /* non-printable characters */
175 dlen -= 4;
176 if (dlen < 1)
177 break;
178 *dst++ = '\\';
179 *dst++ = ((*src & 0300) >> 6) + '0';
180 *dst++ = ((*src & 0070) >> 3) + '0';
181 *dst++ = ((*src & 0007) >> 0) + '0';
182 } else if (*src == '\\') {
183 /* quote characters */
184 dlen -= 2;
185 if (dlen < 1)
186 break;
187 *dst++ = '\\';
188 *dst++ = '\\';
189 } else {
190 /* normal characters */
191 if (--dlen < 1)
192 break;
193 *dst++ = *src;
194 }
195 ++src, --slen;
196 }
197
198 *dst++ = 0;
199 }
200