1 /* $NetBSD: iopctl.c,v 1.18 2008/09/17 16:03:28 mhitch Exp $ */
4 * Copyright (c) 2000 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
33 #include <sys/cdefs.h>
34 __RCSID("$NetBSD: iopctl.c,v 1.18 2008/09/17 16:03:28 mhitch Exp $");
37 #include <sys/param.h>
38 #include <sys/ioctl.h>
51 #include <dev/i2o/i2o.h>
52 #include <dev/i2o/iopio.h>
54 const char *class2str(int);
55 void getparam(int, int, void *, int);
57 int main(int, char **);
58 int show(const char *, const char *, ...)
59 __attribute__((__format__(__printf__
, 2, 3)));
60 void i2ostrvis(const u_char
*, int, char *, int);
63 void reconfig(char **);
64 void showdevid(char **);
65 void showddmid(char **);
66 void showlct(char **);
67 void showstatus(char **);
68 void showtidmap(char **);
73 } const i2oclass
[] = {
74 { I2O_CLASS_EXECUTIVE
, "executive" },
75 { I2O_CLASS_DDM
, "device driver module" },
76 { I2O_CLASS_RANDOM_BLOCK_STORAGE
, "random block storage" },
77 { I2O_CLASS_SEQUENTIAL_STORAGE
, "sequential storage" },
78 { I2O_CLASS_LAN
, "LAN port" },
79 { I2O_CLASS_WAN
, "WAN port" },
80 { I2O_CLASS_FIBRE_CHANNEL_PORT
, "fibrechannel port" },
81 { I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL
, "fibrechannel peripheral" },
82 { I2O_CLASS_SCSI_PERIPHERAL
, "SCSI peripheral" },
83 { I2O_CLASS_ATE_PORT
, "ATE port" },
84 { I2O_CLASS_ATE_PERIPHERAL
, "ATE peripheral" },
85 { I2O_CLASS_FLOPPY_CONTROLLER
, "floppy controller" },
86 { I2O_CLASS_FLOPPY_DEVICE
, "floppy device" },
87 { I2O_CLASS_BUS_ADAPTER_PORT
, "bus adapter port" },
93 void (*func
)(char **);
95 { "reconfig", 0, reconfig
},
96 { "showddmid", 1, showddmid
},
97 { "showdevid", 1, showdevid
},
98 { "showlct", 0, showlct
},
99 { "showstatus", 0, showstatus
},
100 { "showtidmap", 0, showtidmap
},
105 struct i2o_status status
;
108 main(int argc
, char **argv
)
117 while ((ch
= getopt(argc
, argv
, "f:")) != -1) {
128 if (argv
[optind
] == NULL
)
131 if ((fd
= open(dv
, O_RDWR
)) < 0)
132 err(EXIT_FAILURE
, "%s", dv
);
134 iov
.iov_base
= &status
;
135 iov
.iov_len
= sizeof(status
);
136 if (ioctl(fd
, IOPIOCGSTATUS
, &iov
) < 0)
137 err(EXIT_FAILURE
, "IOPIOCGSTATUS");
139 for (i
= 0; i
< sizeof(cmdtab
) / sizeof(cmdtab
[0]); i
++)
140 if (strcmp(argv
[optind
], cmdtab
[i
].label
) == 0) {
141 if (cmdtab
[i
].takesargs
== 0 &&
142 argv
[optind
+ 1] != NULL
)
144 (*cmdtab
[i
].func
)(argv
+ optind
+ 1);
148 if (i
== sizeof(cmdtab
) / sizeof(cmdtab
[0]))
149 errx(EXIT_FAILURE
, "unknown command ``%s''", argv
[optind
]);
160 (void)fprintf(stderr
, "usage: %s [-f dev] <command> [target]\n",
167 show(const char *hdr
, const char *fmt
, ...)
172 for (i
= printf("%s", hdr
); i
< 25; i
++)
175 i
+= vprintf(fmt
, va
);
186 for (i
= 0; i
< sizeof(i2oclass
) / sizeof(i2oclass
[0]); i
++)
187 if (class == i2oclass
[i
].class)
188 return (i2oclass
[i
].caption
);
194 getparam(int tid
, int group
, void *pbuf
, int pbufsize
)
197 struct i2o_util_params_op mb
;
198 struct i2o_reply
*rf
;
200 struct i2o_param_op_list_header olh
;
201 struct i2o_param_op_all_template oat
;
204 mb
.msgflags
= I2O_MSGFLAGS(i2o_util_params_op
);
205 mb
.msgfunc
= I2O_MSGFUNC(tid
, I2O_UTIL_PARAMS_GET
);
208 req
.olh
.count
= htole16(1);
209 req
.olh
.reserved
= htole16(0);
210 req
.oat
.operation
= htole16(I2O_PARAMS_OP_FIELD_GET
);
211 req
.oat
.fieldcount
= htole16(0xffff);
212 req
.oat
.group
= htole16(group
);
215 pt
.pt_msglen
= sizeof(mb
);
217 pt
.pt_replylen
= sizeof(buf
);
221 pt
.pt_bufs
[0].ptb_data
= &req
;
222 pt
.pt_bufs
[0].ptb_datalen
= sizeof(req
);
223 pt
.pt_bufs
[0].ptb_out
= 1;
225 pt
.pt_bufs
[1].ptb_data
= pbuf
;
226 pt
.pt_bufs
[1].ptb_datalen
= pbufsize
;
227 pt
.pt_bufs
[1].ptb_out
= 0;
229 if (ioctl(fd
, IOPIOCPT
, &pt
) < 0)
230 err(EXIT_FAILURE
, "IOPIOCPT");
232 rf
= (struct i2o_reply
*)buf
;
233 if ((rf
->msgflags
& I2O_MSGFLAGS_FAIL
) != 0)
234 errx(EXIT_FAILURE
, "I2O_UTIL_PARAMS_GET failed (FAIL)");
235 if (rf
->reqstatus
!= 0)
236 errx(EXIT_FAILURE
, "I2O_UTIL_PARAMS_GET failed (%d)",
237 ((struct i2o_reply
*)buf
)->reqstatus
);
245 struct i2o_lct_entry
*ent
;
246 u_int32_t classid
, usertid
;
248 char ident
[sizeof(ent
->identitytag
) * 4 + 1];
251 iov
.iov_len
= sizeof(buf
);
253 if (ioctl(fd
, IOPIOCGLCT
, &iov
) < 0)
254 err(EXIT_FAILURE
, "IOPIOCGLCT");
256 lct
= (struct i2o_lct
*)buf
;
258 nent
= ((le16toh(lct
->tablesize
) << 2) -
259 sizeof(struct i2o_lct
) + sizeof(struct i2o_lct_entry
)) /
260 sizeof(struct i2o_lct_entry
);
262 show("flags", "0x%x", le16toh(lct
->flags
));
263 show("iop flags", "0x%x", le32toh(lct
->iopflags
));
264 show("lct change indicator", "%d", le32toh(lct
->changeindicator
));
267 for (i
= 0; i
< nent
; i
++, ent
++) {
268 classid
= le32toh(ent
->classid
);
269 usertid
= le32toh(ent
->usertid
);
271 show("lct entry", "%d", i
);
272 show("entry size", "%d bytes", le16toh(ent
->entrysize
) << 2);
273 show("local tid", "%d", le16toh(ent
->localtid
) & 4095);
274 show("change indicator", "%d", le32toh(ent
->changeindicator
));
275 show("flags", "%x", le32toh(ent
->deviceflags
));
276 show("class id", "%x (%s)", classid
& 4095,
277 class2str(classid
& 4095));
278 show("version", "%x", (classid
>> 12) & 15);
279 show("organisation id", "%x", classid
>> 16);
280 show("subclass info", "%x", le32toh(ent
->subclassinfo
));
281 show("user tid", "%d", usertid
& 4095);
282 show("parent tid", "%d", (usertid
>> 12) & 4095);
283 show("bios info", "%d", (usertid
>> 24) & 255);
284 i2ostrvis(ent
->identitytag
, sizeof(ent
->identitytag
), ident
,
286 show("identity tag", "<%s>", ident
);
287 show("event caps", "%x", le32toh(ent
->eventcaps
));
295 showstatus(char **argv
)
297 char ident
[sizeof(status
.productid
) + 1];
300 i2ostrvis(status
.productid
, sizeof(status
.productid
),
301 ident
, sizeof(ident
));
303 segnumber
= le32toh(status
.segnumber
);
304 show("organization id", "%d", le16toh(status
.orgid
));
305 show("iop id", "%d", le32toh(status
.iopid
) & 4095);
306 show("host unit id", "%d", (le32toh(status
.iopid
) >> 16));
307 show("segment number", "%d", segnumber
& 4095);
308 show("i2o version", "%d", (segnumber
>> 12) & 15);
309 show("iop state", "%d", (segnumber
>> 16) & 255);
310 show("messenger type", "%d", segnumber
>> 24);
311 show("inbound frame sz", "%d", le16toh(status
.inboundmframesize
));
312 show("init code", "%d", status
.initcode
);
313 show("max inbound queue depth", "%d",
314 le32toh(status
.maxinboundmframes
));
315 show("inbound queue depth", "%d",
316 le32toh(status
.currentinboundmframes
));
317 show("max outbound queue depth", "%d",
318 le32toh(status
.maxoutboundmframes
));
319 show("product id string", "<%s>", ident
);
320 show("expected lct size", "%d", le32toh(status
.expectedlctsize
));
321 show("iop capabilities", "0x%08x", le32toh(status
.iopcaps
));
322 show("desired priv mem sz", "0x%08x",
323 le32toh(status
.desiredprivmemsize
));
324 show("current priv mem sz", "0x%08x",
325 le32toh(status
.currentprivmemsize
));
326 show("current priv mem base", "0x%08x",
327 le32toh(status
.currentprivmembase
));
328 show("desired priv io sz", "0x%08x",
329 le32toh(status
.desiredpriviosize
));
330 show("current priv io sz", "0x%08x",
331 le32toh(status
.currentpriviosize
));
332 show("current priv io base", "0x%08x",
333 le32toh(status
.currentpriviobase
));
337 showddmid(char **argv
)
340 struct i2o_param_op_results pr
;
341 struct i2o_param_read_results prr
;
342 struct i2o_param_ddm_identity di
;
347 getparam(gettid(argv
), I2O_PARAM_DDM_IDENTITY
, &p
, sizeof(p
));
349 show("ddm tid", "%d", le16toh(p
.di
.ddmtid
) & 4095);
350 i2ostrvis(p
.di
.name
, sizeof(p
.di
.name
), ident
, sizeof(ident
));
351 show("module name", "%s", ident
);
352 i2ostrvis(p
.di
.revlevel
, sizeof(p
.di
.revlevel
), ident
, sizeof(ident
));
353 show("module revision", "%s", ident
);
354 show("serial # format", "%d", p
.di
.snformat
);
355 show("serial #", "%08x%08x%08x", *(u_int32_t
*)&p
.di
.serialnumber
[0],
356 *(u_int32_t
*)&p
.di
.serialnumber
[4],
357 *(u_int32_t
*)&p
.di
.serialnumber
[8]);
361 showdevid(char **argv
)
364 struct i2o_param_op_results pr
;
365 struct i2o_param_read_results prr
;
366 struct i2o_param_device_identity di
;
371 getparam(gettid(argv
), I2O_PARAM_DEVICE_IDENTITY
, &p
, sizeof(p
));
373 show("class id", "%d (%s)", le32toh(p
.di
.classid
) & 4095,
374 class2str(le32toh(p
.di
.classid
) & 4095));
375 show("owner tid", "%d", le32toh(p
.di
.ownertid
) & 4095);
376 show("parent tid", "%d", le32toh(p
.di
.parenttid
) & 4095);
378 i2ostrvis(p
.di
.vendorinfo
, sizeof(p
.di
.vendorinfo
), ident
,
380 show("vendor", "<%s>", ident
);
382 i2ostrvis(p
.di
.productinfo
, sizeof(p
.di
.productinfo
), ident
,
384 show("product", "<%s>", ident
);
386 i2ostrvis(p
.di
.description
, sizeof(p
.di
.description
), ident
,
388 show("description", "<%s>", ident
);
390 i2ostrvis(p
.di
.revlevel
, sizeof(p
.di
.revlevel
), ident
, sizeof(ident
));
391 show("revision level", "<%s>", ident
);
395 reconfig(char **argv
)
398 if (ioctl(fd
, IOPIOCRECONFIG
))
399 err(EXIT_FAILURE
, "IOPIOCRECONFIG");
403 showtidmap(char **argv
)
406 struct iop_tidmap
*it
;
410 iov
.iov_len
= sizeof(buf
);
412 if (ioctl(fd
, IOPIOCGTIDMAP
, &iov
) < 0)
413 err(EXIT_FAILURE
, "IOPIOCGTIDMAP");
415 nent
= iov
.iov_len
/ sizeof(*it
);
416 it
= (struct iop_tidmap
*)buf
;
418 for (; nent
-- != 0; it
++)
419 if ((it
->it_flags
& IT_CONFIGURED
) != 0)
420 printf("%s\ttid %d\n", it
->it_dvname
, it
->it_tid
);
424 i2ostrvis(const u_char
*src
, int slen
, char *dst
, int dlen
)
434 * DPT use NUL as a space, whereas AMI use it as a terminator. The
435 * spec has nothing to say about it. Since AMI fields are usually
436 * filled with junk after the terminator, ...
438 nit
= (le16toh(status
.orgid
) != I2O_ORG_DPT
);
440 while (slen
-- != 0 && dlen
-- != 0) {
441 if (nit
&& *src
== '\0')
443 else if (*src
<= 0x20 || *src
>= 0x7f) {
466 tid
= (int)strtol(argv
[0], &argp
, 0);