util.c revision 1.3.2.2 1 1.3.2.2 he /* $NetBSD: util.c,v 1.3.2.2 2001/12/09 19:38:21 he Exp $ */
2 1.3.2.2 he
3 1.3.2.2 he /*-
4 1.3.2.2 he * Copyright (c) 2001 The NetBSD Foundation, Inc.
5 1.3.2.2 he * All rights reserved.
6 1.3.2.2 he *
7 1.3.2.2 he * This code is derived from software contributed to The NetBSD Foundation
8 1.3.2.2 he * by Andrew Doran.
9 1.3.2.2 he *
10 1.3.2.2 he * Redistribution and use in source and binary forms, with or without
11 1.3.2.2 he * modification, are permitted provided that the following conditions
12 1.3.2.2 he * are met:
13 1.3.2.2 he * 1. Redistributions of source code must retain the above copyright
14 1.3.2.2 he * notice, this list of conditions and the following disclaimer.
15 1.3.2.2 he * 2. Redistributions in binary form must reproduce the above copyright
16 1.3.2.2 he * notice, this list of conditions and the following disclaimer in the
17 1.3.2.2 he * documentation and/or other materials provided with the distribution.
18 1.3.2.2 he * 3. All advertising materials mentioning features or use of this software
19 1.3.2.2 he * must display the following acknowledgement:
20 1.3.2.2 he * This product includes software developed by the NetBSD
21 1.3.2.2 he * Foundation, Inc. and its contributors.
22 1.3.2.2 he * 4. Neither the name of The NetBSD Foundation nor the names of its
23 1.3.2.2 he * contributors may be used to endorse or promote products derived
24 1.3.2.2 he * from this software without specific prior written permission.
25 1.3.2.2 he *
26 1.3.2.2 he * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 1.3.2.2 he * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 1.3.2.2 he * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 1.3.2.2 he * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 1.3.2.2 he * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 1.3.2.2 he * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 1.3.2.2 he * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 1.3.2.2 he * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 1.3.2.2 he * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 1.3.2.2 he * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 1.3.2.2 he * POSSIBILITY OF SUCH DAMAGE.
37 1.3.2.2 he */
38 1.3.2.2 he
39 1.3.2.2 he /*-
40 1.3.2.2 he * Copyright (c) 1999 Michael Smith
41 1.3.2.2 he * All rights reserved.
42 1.3.2.2 he *
43 1.3.2.2 he * Redistribution and use in source and binary forms, with or without
44 1.3.2.2 he * modification, are permitted provided that the following conditions
45 1.3.2.2 he * are met:
46 1.3.2.2 he * 1. Redistributions of source code must retain the above copyright
47 1.3.2.2 he * notice, this list of conditions and the following disclaimer.
48 1.3.2.2 he * 2. Redistributions in binary form must reproduce the above copyright
49 1.3.2.2 he * notice, this list of conditions and the following disclaimer in the
50 1.3.2.2 he * documentation and/or other materials provided with the distribution.
51 1.3.2.2 he *
52 1.3.2.2 he * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
53 1.3.2.2 he * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54 1.3.2.2 he * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55 1.3.2.2 he * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
56 1.3.2.2 he * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57 1.3.2.2 he * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58 1.3.2.2 he * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59 1.3.2.2 he * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 1.3.2.2 he * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 1.3.2.2 he * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 1.3.2.2 he * SUCH DAMAGE.
63 1.3.2.2 he */
64 1.3.2.2 he
65 1.3.2.2 he #ifndef lint
66 1.3.2.2 he #include <sys/cdefs.h>
67 1.3.2.2 he __RCSID("$NetBSD: util.c,v 1.3.2.2 2001/12/09 19:38:21 he Exp $");
68 1.3.2.2 he #endif /* not lint */
69 1.3.2.2 he
70 1.3.2.2 he #include <sys/types.h>
71 1.3.2.2 he #include <sys/ioctl.h>
72 1.3.2.2 he #include <sys/queue.h>
73 1.3.2.2 he
74 1.3.2.2 he #include <dev/ic/mlxreg.h>
75 1.3.2.2 he #include <dev/ic/mlxio.h>
76 1.3.2.2 he
77 1.3.2.2 he #include <dev/scsipi/scsipi_all.h>
78 1.3.2.2 he
79 1.3.2.2 he #include <stdio.h>
80 1.3.2.2 he #include <stdlib.h>
81 1.3.2.2 he #include <string.h>
82 1.3.2.2 he #include <unistd.h>
83 1.3.2.2 he #include <err.h>
84 1.3.2.2 he
85 1.3.2.2 he #include "extern.h"
86 1.3.2.2 he
87 1.3.2.2 he int
88 1.3.2.2 he mlx_command(struct mlx_usercommand *mu, int bomb)
89 1.3.2.2 he {
90 1.3.2.2 he int rv;
91 1.3.2.2 he
92 1.3.2.2 he if ((rv = ioctl(mlxfd, MLX_COMMAND, mu)) != 0 && bomb)
93 1.3.2.2 he err(EXIT_FAILURE, "cmd 0x%02x failed",
94 1.3.2.2 he mu->mu_command[0]);
95 1.3.2.2 he
96 1.3.2.2 he return (rv);
97 1.3.2.2 he }
98 1.3.2.2 he
99 1.3.2.2 he void
100 1.3.2.2 he mlx_enquiry(struct mlx_enquiry2 *enq)
101 1.3.2.2 he {
102 1.3.2.2 he struct mlx_usercommand mu;
103 1.3.2.2 he struct mlx_enquiry_old meo;
104 1.3.2.2 he
105 1.3.2.2 he memset(&mu, 0, sizeof(mu));
106 1.3.2.2 he
107 1.3.2.2 he mu.mu_datasize = sizeof(*enq);
108 1.3.2.2 he mu.mu_buf = enq;
109 1.3.2.2 he mu.mu_bufptr = 8;
110 1.3.2.2 he mu.mu_bufdir = MU_XFER_IN;
111 1.3.2.2 he mu.mu_command[0] = MLX_CMD_ENQUIRY2;
112 1.3.2.2 he
113 1.3.2.2 he mlx_command(&mu, 1);
114 1.3.2.2 he
115 1.3.2.2 he /*
116 1.3.2.2 he * If we get back a firmware major of 0, this is (probably) an old
117 1.3.2.2 he * controller, so we need to pull the firmware version from the old
118 1.3.2.2 he * enquiry structure.
119 1.3.2.2 he */
120 1.3.2.2 he if (enq->me_firmware_id[0] == 0) {
121 1.3.2.2 he memset(&mu, 0, sizeof(mu));
122 1.3.2.2 he
123 1.3.2.2 he mu.mu_datasize = sizeof(meo);
124 1.3.2.2 he mu.mu_buf = &meo;
125 1.3.2.2 he mu.mu_bufptr = 8;
126 1.3.2.2 he mu.mu_bufdir = MU_XFER_IN;
127 1.3.2.2 he mu.mu_command[0] = MLX_CMD_ENQUIRY_OLD;
128 1.3.2.2 he
129 1.3.2.2 he mlx_command(&mu, 1);
130 1.3.2.2 he
131 1.3.2.2 he enq->me_firmware_id[0] = meo.me_fwmajor;
132 1.3.2.2 he enq->me_firmware_id[1] = meo.me_fwminor;
133 1.3.2.2 he enq->me_firmware_id[2] = '0';
134 1.3.2.2 he enq->me_firmware_id[3] = 0;
135 1.3.2.2 he }
136 1.3.2.2 he }
137 1.3.2.2 he
138 1.3.2.2 he void
139 1.3.2.2 he mlx_configuration(struct mlx_core_cfg *cfg, int wr)
140 1.3.2.2 he {
141 1.3.2.2 he struct mlx_usercommand mu;
142 1.3.2.2 he
143 1.3.2.2 he memset(&mu, 0, sizeof(mu));
144 1.3.2.2 he
145 1.3.2.2 he mu.mu_datasize = sizeof(*cfg);
146 1.3.2.2 he mu.mu_buf = cfg;
147 1.3.2.2 he mu.mu_bufptr = 8;
148 1.3.2.2 he mu.mu_bufdir = (wr ? MU_XFER_OUT : MU_XFER_IN);
149 1.3.2.2 he mu.mu_command[0] = (wr ? MLX_CMD_WRITE_CONFIG : MLX_CMD_READ_CONFIG);
150 1.3.2.2 he
151 1.3.2.2 he mlx_command(&mu, 1);
152 1.3.2.2 he }
153 1.3.2.2 he
154 1.3.2.2 he int
155 1.3.2.2 he mlx_get_device_state(int chan, int targ, struct mlx_phys_drv *pd)
156 1.3.2.2 he {
157 1.3.2.2 he struct mlx_usercommand mu;
158 1.3.2.2 he
159 1.3.2.2 he memset(&mu, 0, sizeof(mu));
160 1.3.2.2 he
161 1.3.2.2 he mu.mu_datasize = sizeof(*pd);
162 1.3.2.2 he mu.mu_buf = pd;
163 1.3.2.2 he mu.mu_bufptr = 8;
164 1.3.2.2 he mu.mu_bufdir = MU_XFER_IN;
165 1.3.2.2 he mu.mu_command[0] = MLX_CMD_DEVICE_STATE;
166 1.3.2.2 he mu.mu_command[2] = chan;
167 1.3.2.2 he mu.mu_command[3] = targ;
168 1.3.2.2 he
169 1.3.2.2 he return (mlx_command(&mu, 0));
170 1.3.2.2 he }
171 1.3.2.2 he
172 1.3.2.2 he int
173 1.3.2.2 he mlx_scsi_inquiry(int chan, int targ, char **vendor, char **device,
174 1.3.2.2 he char **revision)
175 1.3.2.2 he {
176 1.3.2.2 he struct mlx_usercommand mu;
177 1.3.2.2 he static struct {
178 1.3.2.2 he struct mlx_dcdb dcdb;
179 1.3.2.2 he struct scsipi_inquiry_data inq;
180 1.3.2.2 he } __attribute__ ((__packed__)) dcdb_cmd;
181 1.3.2.2 he struct scsipi_inquiry *inq_cmd;
182 1.3.2.2 he int rv;
183 1.3.2.2 he
184 1.3.2.2 he inq_cmd = (struct scsipi_inquiry *)&dcdb_cmd.dcdb.dcdb_cdb[0];
185 1.3.2.2 he
186 1.3.2.2 he memset(&mu, 0, sizeof(mu));
187 1.3.2.2 he mu.mu_datasize = sizeof(dcdb_cmd);
188 1.3.2.2 he mu.mu_buf = &dcdb_cmd;
189 1.3.2.2 he mu.mu_command[0] = MLX_CMD_DIRECT_CDB;
190 1.3.2.2 he mu.mu_bufdir = MU_XFER_IN | MU_XFER_OUT;
191 1.3.2.2 he
192 1.3.2.2 he memset(&dcdb_cmd, 0, sizeof(dcdb_cmd));
193 1.3.2.2 he dcdb_cmd.dcdb.dcdb_target = (chan << 4) | targ;
194 1.3.2.2 he dcdb_cmd.dcdb.dcdb_flags = MLX_DCDB_DATA_IN | MLX_DCDB_TIMEOUT_10S;
195 1.3.2.2 he dcdb_cmd.dcdb.dcdb_datasize = sizeof(dcdb_cmd.inq);
196 1.3.2.2 he dcdb_cmd.dcdb.dcdb_length = 6;
197 1.3.2.2 he dcdb_cmd.dcdb.dcdb_sense_length = 40;
198 1.3.2.2 he
199 1.3.2.2 he inq_cmd->opcode = INQUIRY;
200 1.3.2.2 he inq_cmd->length = sizeof(dcdb_cmd.inq);
201 1.3.2.2 he
202 1.3.2.2 he if ((rv = mlx_command(&mu, 0)) == 0) {
203 1.3.2.2 he *vendor = &dcdb_cmd.inq.vendor[0];
204 1.3.2.2 he *device = &dcdb_cmd.inq.product[0];
205 1.3.2.2 he *revision = &dcdb_cmd.inq.revision[0];
206 1.3.2.2 he }
207 1.3.2.2 he
208 1.3.2.2 he return (rv);
209 1.3.2.2 he }
210 1.3.2.2 he
211 1.3.2.2 he void
212 1.3.2.2 he mlx_print_phys_drv(struct mlx_phys_drv *pd, int chn, int targ,
213 1.3.2.2 he const char *prefix)
214 1.3.2.2 he {
215 1.3.2.2 he char *type, *device, *vendor, *revision;
216 1.3.2.2 he
217 1.3.2.2 he switch (pd->pd_flags2 & 0x03) {
218 1.3.2.2 he case MLX_PHYS_DRV_DISK:
219 1.3.2.2 he type = "disk";
220 1.3.2.2 he break;
221 1.3.2.2 he
222 1.3.2.2 he case MLX_PHYS_DRV_SEQUENTIAL:
223 1.3.2.2 he type = "tape";
224 1.3.2.2 he break;
225 1.3.2.2 he
226 1.3.2.2 he case MLX_PHYS_DRV_CDROM:
227 1.3.2.2 he type= "cdrom";
228 1.3.2.2 he break;
229 1.3.2.2 he
230 1.3.2.2 he case MLX_PHYS_DRV_OTHER:
231 1.3.2.2 he default:
232 1.3.2.2 he type = "unknown";
233 1.3.2.2 he break;
234 1.3.2.2 he }
235 1.3.2.2 he
236 1.3.2.2 he printf("%s%s%02d%02d ", prefix, type, chn, targ);
237 1.3.2.2 he
238 1.3.2.2 he switch (pd->pd_status) {
239 1.3.2.2 he case MLX_PHYS_DRV_DEAD:
240 1.3.2.2 he printf(" (dead) ");
241 1.3.2.2 he break;
242 1.3.2.2 he
243 1.3.2.2 he case MLX_PHYS_DRV_WRONLY:
244 1.3.2.2 he printf(" (write-only) ");
245 1.3.2.2 he break;
246 1.3.2.2 he
247 1.3.2.2 he case MLX_PHYS_DRV_ONLINE:
248 1.3.2.2 he printf(" (online) ");
249 1.3.2.2 he break;
250 1.3.2.2 he
251 1.3.2.2 he case MLX_PHYS_DRV_STANDBY:
252 1.3.2.2 he printf(" (standby) ");
253 1.3.2.2 he break;
254 1.3.2.2 he
255 1.3.2.2 he default:
256 1.3.2.2 he printf(" (0x%02x) ", pd->pd_status);
257 1.3.2.2 he break;
258 1.3.2.2 he }
259 1.3.2.2 he
260 1.3.2.2 he printf("\n");
261 1.3.2.2 he if (verbosity == 0)
262 1.3.2.2 he return;
263 1.3.2.2 he
264 1.3.2.2 he printf("%s ", prefix);
265 1.3.2.2 he if (!mlx_scsi_inquiry(chn, targ, &vendor, &device, &revision))
266 1.3.2.2 he printf("'%8.8s' '%16.16s' '%4.4s'", vendor, device, revision);
267 1.3.2.2 he else
268 1.3.2.2 he printf("<IDENTIFY FAILED>");
269 1.3.2.2 he
270 1.3.2.2 he printf(" %dMB ", pd->pd_config_size / 2048);
271 1.3.2.2 he
272 1.3.2.2 he if ((pd->pd_flags2 & MLX_PHYS_DRV_FAST20) != 0)
273 1.3.2.2 he printf(" ultra");
274 1.3.2.2 he else if ((pd->pd_flags2 & MLX_PHYS_DRV_FAST) != 0)
275 1.3.2.2 he printf(" fast");
276 1.3.2.2 he
277 1.3.2.2 he if ((pd->pd_flags2 & MLX_PHYS_DRV_WIDE) != 0)
278 1.3.2.2 he printf(" wide");
279 1.3.2.2 he
280 1.3.2.2 he if ((pd->pd_flags2 & MLX_PHYS_DRV_SYNC) != 0)
281 1.3.2.2 he printf(" sync");
282 1.3.2.2 he
283 1.3.2.2 he if ((pd->pd_flags2 & MLX_PHYS_DRV_TAG) != 0)
284 1.3.2.2 he printf(" tag-enabled");
285 1.3.2.2 he
286 1.3.2.2 he printf("\n");
287 1.3.2.2 he }
288