fwcontrol.c revision 1.1 1 /* $NetBSD: fwcontrol.c,v 1.1 2005/07/11 15:35:25 kiyohara Exp $ */
2 /*
3 * Copyright (C) 2002
4 * Hidetoshi Shimokawa. 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 *
17 * This product includes software developed by Hidetoshi Shimokawa.
18 *
19 * 4. Neither the name of the author nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35 #if defined(__FreeBSD__)
36
37 #include <sys/cdefs.h>
38 __FBSDID("$FreeBSD: /repoman/r/ncvs/src/usr.sbin/fwcontrol/fwcontrol.c,v 1.22 2005/05/20 12:50:47 charnier Exp $");
39 #endif
40
41 #include <sys/param.h>
42 #include <sys/malloc.h>
43 #include <sys/types.h>
44 #include <sys/sysctl.h>
45 #include <sys/socket.h>
46 #include <sys/ioctl.h>
47 #include <sys/errno.h>
48 #if defined(__FreeBSD__)
49 #include <sys/eui64.h>
50 #include <dev/firewire/firewire.h>
51 #include <dev/firewire/iec13213.h>
52 #include <dev/firewire/fwphyreg.h>
53 #elif defined(__NetBSD__)
54 #include "eui64.h"
55 #include <dev/ieee1394/firewire.h>
56 #include <dev/ieee1394/iec13213.h>
57 #include <dev/ieee1394/fwphyreg.h>
58 #endif
59
60 #include <netinet/in.h>
61 #include <fcntl.h>
62 #include <stdio.h>
63 #include <err.h>
64 #include <stdlib.h>
65 #include <string.h>
66 #include <unistd.h>
67
68 extern int dvrecv(int, char *, char, int);
69 extern int dvsend(int, char *, char, int);
70
71 int sysctl_set_int(const char *, int);
72
73 static void
74 usage(void)
75 {
76 fprintf(stderr,
77 "fwctl [-u bus_num] [-rt] [-g gap_count] [-o node] "
78 "[-b pri_req] [-c node] [-d node] [-l file] "
79 "[-R file] [-S file] [-m target]\n"
80 "\t-u: specify bus number\n"
81 "\t-g: broadcast gap_count by phy_config packet\n"
82 "\t-o: send link-on packet to the node\n"
83 "\t-s: write RESET_START register on the node\n"
84 "\t-b: set PRIORITY_BUDGET register on all supported nodes\n"
85 "\t-c: read configuration ROM\n"
86 "\t-r: bus reset\n"
87 "\t-t: read topology map\n"
88 "\t-d: hex dump of configuration ROM\n"
89 "\t-l: load and parse hex dump file of configuration ROM\n"
90 "\t-R: Receive DV stream\n"
91 "\t-S: Send DV stream\n"
92 "\t-m: set fwmem target\n");
93 exit(0);
94 }
95
96 static void
97 fweui2eui64(const struct fw_eui64 *fweui, struct eui64 *eui)
98 {
99 *(u_int32_t*)&(eui->octet[0]) = htonl(fweui->hi);
100 *(u_int32_t*)&(eui->octet[4]) = htonl(fweui->lo);
101 }
102
103 static struct fw_devlstreq *
104 get_dev(int fd)
105 {
106 struct fw_devlstreq *data;
107
108 data = (struct fw_devlstreq *)malloc(sizeof(struct fw_devlstreq));
109 if (data == NULL)
110 err(1, "malloc");
111 if( ioctl(fd, FW_GDEVLST, data) < 0) {
112 err(1, "ioctl");
113 }
114 return data;
115 }
116
117 static int
118 str2node(int fd, const char *nodestr)
119 {
120 struct eui64 eui, tmpeui;
121 struct fw_devlstreq *data;
122 char *endptr;
123 int i, node;
124
125 if (nodestr == '\0')
126 return (-1);
127
128 /*
129 * Deal with classic node specifications.
130 */
131 node = strtol(nodestr, &endptr, 0);
132 if (*endptr == '\0')
133 goto gotnode;
134
135 /*
136 * Try to get an eui and match it against available nodes.
137 */
138 if (eui64_hostton(nodestr, &eui) != 0 && eui64_aton(nodestr, &eui) != 0)
139 return (-1);
140
141 data = get_dev(fd);
142
143 for (i = 0; i < data->info_len; i++) {
144 fweui2eui64(&data->dev[i].eui, &tmpeui);
145 if (memcmp(&eui, &tmpeui, sizeof(struct eui64)) == 0) {
146 node = data->dev[i].dst;
147 goto gotnode;
148 }
149 }
150 if (i >= data->info_len)
151 return (-1);
152
153 gotnode:
154 if (node < 0 || node > 63)
155 return (-1);
156 else
157 return (node);
158 }
159
160 static void
161 list_dev(int fd)
162 {
163 struct fw_devlstreq *data;
164 struct fw_devinfo *devinfo;
165 struct eui64 eui;
166 char addr[EUI64_SIZ];
167 int i;
168
169 data = get_dev(fd);
170 printf("%d devices (info_len=%d)\n", data->n, data->info_len);
171 printf("node EUI64 status\n");
172 for (i = 0; i < data->info_len; i++) {
173 devinfo = &data->dev[i];
174 fweui2eui64(&devinfo->eui, &eui);
175 eui64_ntoa(&eui, addr, sizeof(addr));
176 printf("%4d %s %6d\n",
177 (devinfo->status || i == 0) ? devinfo->dst : -1,
178 addr,
179 devinfo->status
180 );
181 }
182 free((void *)data);
183 }
184
185 static u_int32_t
186 read_write_quad(int fd, struct fw_eui64 eui, u_int32_t addr_lo, int readmode, u_int32_t data)
187 {
188 struct fw_asyreq *asyreq;
189 u_int32_t *qld, res;
190
191 asyreq = (struct fw_asyreq *)malloc(sizeof(struct fw_asyreq_t) + 16);
192 asyreq->req.len = 16;
193 #if 0
194 asyreq->req.type = FWASREQNODE;
195 asyreq->pkt.mode.rreqq.dst = FWLOCALBUS | node;
196 #else
197 asyreq->req.type = FWASREQEUI;
198 asyreq->req.dst.eui = eui;
199 #endif
200 asyreq->pkt.mode.rreqq.tlrt = 0;
201 if (readmode)
202 asyreq->pkt.mode.rreqq.tcode = FWTCODE_RREQQ;
203 else
204 asyreq->pkt.mode.rreqq.tcode = FWTCODE_WREQQ;
205
206 asyreq->pkt.mode.rreqq.dest_hi = 0xffff;
207 asyreq->pkt.mode.rreqq.dest_lo = addr_lo;
208
209 qld = (u_int32_t *)&asyreq->pkt;
210 if (!readmode)
211 asyreq->pkt.mode.wreqq.data = data;
212
213 if (ioctl(fd, FW_ASYREQ, asyreq) < 0) {
214 err(1, "ioctl");
215 }
216 res = qld[3];
217 free(asyreq);
218 if (readmode)
219 return ntohl(res);
220 else
221 return 0;
222 }
223
224 static void
225 send_phy_config(int fd, int root_node, int gap_count)
226 {
227 struct fw_asyreq *asyreq;
228
229 asyreq = (struct fw_asyreq *)malloc(sizeof(struct fw_asyreq_t) + 12);
230 asyreq->req.len = 12;
231 asyreq->req.type = FWASREQNODE;
232 asyreq->pkt.mode.ld[0] = 0;
233 asyreq->pkt.mode.ld[1] = 0;
234 asyreq->pkt.mode.common.tcode = FWTCODE_PHY;
235 if (root_node >= 0)
236 asyreq->pkt.mode.ld[1] |= (root_node & 0x3f) << 24 | 1 << 23;
237 if (gap_count >= 0)
238 asyreq->pkt.mode.ld[1] |= 1 << 22 | (gap_count & 0x3f) << 16;
239 asyreq->pkt.mode.ld[2] = ~asyreq->pkt.mode.ld[1];
240
241 printf("send phy_config root_node=%d gap_count=%d\n",
242 root_node, gap_count);
243
244 if (ioctl(fd, FW_ASYREQ, asyreq) < 0)
245 err(1, "ioctl");
246 free(asyreq);
247 }
248
249 static void
250 send_link_on(int fd, int node)
251 {
252 struct fw_asyreq *asyreq;
253
254 asyreq = (struct fw_asyreq *)malloc(sizeof(struct fw_asyreq_t) + 12);
255 asyreq->req.len = 12;
256 asyreq->req.type = FWASREQNODE;
257 asyreq->pkt.mode.common.tcode = FWTCODE_PHY;
258 asyreq->pkt.mode.ld[1] |= (1 << 30) | ((node & 0x3f) << 24);
259 asyreq->pkt.mode.ld[2] = ~asyreq->pkt.mode.ld[1];
260
261 if (ioctl(fd, FW_ASYREQ, asyreq) < 0)
262 err(1, "ioctl");
263 free(asyreq);
264 }
265
266 static void
267 reset_start(int fd, int node)
268 {
269 struct fw_asyreq *asyreq;
270
271 asyreq = (struct fw_asyreq *)malloc(sizeof(struct fw_asyreq_t) + 16);
272 asyreq->req.len = 16;
273 asyreq->req.type = FWASREQNODE;
274 asyreq->pkt.mode.wreqq.dst = FWLOCALBUS | (node & 0x3f);
275 asyreq->pkt.mode.wreqq.tlrt = 0;
276 asyreq->pkt.mode.wreqq.tcode = FWTCODE_WREQQ;
277
278 asyreq->pkt.mode.wreqq.dest_hi = 0xffff;
279 asyreq->pkt.mode.wreqq.dest_lo = 0xf0000000 | RESET_START;
280
281 asyreq->pkt.mode.wreqq.data = htonl(0x1);
282
283 if (ioctl(fd, FW_ASYREQ, asyreq) < 0)
284 err(1, "ioctl");
285 free(asyreq);
286 }
287
288 static void
289 set_pri_req(int fd, int pri_req)
290 {
291 struct fw_devlstreq *data;
292 struct fw_devinfo *devinfo;
293 struct eui64 eui;
294 char addr[EUI64_SIZ];
295 u_int32_t max, reg, old;
296 int i;
297
298 data = get_dev(fd);
299 #define BUGET_REG 0xf0000218
300 for (i = 0; i < data->info_len; i++) {
301 devinfo = &data->dev[i];
302 if (!devinfo->status)
303 continue;
304 reg = read_write_quad(fd, devinfo->eui, BUGET_REG, 1, 0);
305 fweui2eui64(&devinfo->eui, &eui);
306 eui64_ntoa(&eui, addr, sizeof(addr));
307 printf("%d %s, %08x",
308 devinfo->dst, addr, reg);
309 if (reg > 0 && pri_req >= 0) {
310 old = (reg & 0x3f);
311 max = (reg & 0x3f00) >> 8;
312 if (pri_req > max)
313 pri_req = max;
314 printf(" 0x%x -> 0x%x\n", old, pri_req);
315 read_write_quad(fd, devinfo->eui, BUGET_REG, 0, pri_req);
316 } else {
317 printf("\n");
318 }
319 }
320 free((void *)data);
321 }
322
323 static void
324 parse_bus_info_block(u_int32_t *p, int info_len)
325 {
326 char addr[EUI64_SIZ];
327 struct bus_info *bi;
328 struct eui64 eui;
329
330 bi = (struct bus_info *)p;
331 fweui2eui64(&bi->eui64, &eui);
332 eui64_ntoa(&eui, addr, sizeof(addr));
333 printf("bus_name: 0x%04x\n"
334 "irmc:%d cmc:%d isc:%d bmc:%d pmc:%d\n"
335 "cyc_clk_acc:%d max_rec:%d max_rom:%d\n"
336 "generation:%d link_spd:%d\n"
337 "EUI64: %s\n",
338 bi->bus_name,
339 bi->irmc, bi->cmc, bi->isc, bi->bmc, bi->pmc,
340 bi->cyc_clk_acc, bi->max_rec, bi->max_rom,
341 bi->generation, bi->link_spd,
342 addr);
343 }
344
345 static int
346 get_crom(int fd, int node, void *crom_buf, int len)
347 {
348 struct fw_crom_buf buf;
349 int i, error;
350 struct fw_devlstreq *data;
351
352 data = get_dev(fd);
353
354 for (i = 0; i < data->info_len; i++) {
355 if (data->dev[i].dst == node && data->dev[i].eui.lo != 0)
356 break;
357 }
358 if (i == data->info_len)
359 errx(1, "no such node %d.", node);
360 else
361 buf.eui = data->dev[i].eui;
362 free((void *)data);
363
364 buf.len = len;
365 buf.ptr = crom_buf;
366 bzero(crom_buf, len);
367 if ((error = ioctl(fd, FW_GCROM, &buf)) < 0) {
368 err(1, "ioctl");
369 }
370
371 return error;
372 }
373
374 static void
375 show_crom(u_int32_t *crom_buf)
376 {
377 int i;
378 struct crom_context cc;
379 char *desc, info[256];
380 static const char *key_types = "ICLD";
381 struct csrreg *reg;
382 struct csrdirectory *dir;
383 struct csrhdr *hdr;
384 u_int16_t crc;
385
386 printf("first quad: 0x%08x ", *crom_buf);
387 if (crom_buf[0] == 0) {
388 printf("(Invalid Configuration ROM)\n");
389 return;
390 }
391 hdr = (struct csrhdr *)crom_buf;
392 if (hdr->info_len == 1) {
393 /* minimum ROM */
394 reg = (struct csrreg *)hdr;
395 printf("verndor ID: 0x%06x\n", reg->val);
396 return;
397 }
398 printf("info_len=%d crc_len=%d crc=0x%04x",
399 hdr->info_len, hdr->crc_len, hdr->crc);
400 crc = crom_crc(crom_buf+1, hdr->crc_len);
401 if (crc == hdr->crc)
402 printf("(OK)\n");
403 else
404 printf("(NG)\n");
405 parse_bus_info_block(crom_buf+1, hdr->info_len);
406
407 crom_init_context(&cc, crom_buf);
408 dir = cc.stack[0].dir;
409 if (!dir) {
410 printf("no root directory - giving up\n");
411 return;
412 }
413 printf("root_directory: len=0x%04x(%d) crc=0x%04x",
414 dir->crc_len, dir->crc_len, dir->crc);
415 crc = crom_crc((u_int32_t *)&dir->entry[0], dir->crc_len);
416 if (crc == dir->crc)
417 printf("(OK)\n");
418 else
419 printf("(NG)\n");
420 if (dir->crc_len < 1)
421 return;
422 while (cc.depth >= 0) {
423 desc = crom_desc(&cc, info, sizeof(info));
424 reg = crom_get(&cc);
425 for (i = 0; i < cc.depth; i++)
426 printf("\t");
427 printf("%02x(%c:%02x) %06x %s: %s\n",
428 reg->key,
429 key_types[(reg->key & CSRTYPE_MASK)>>6],
430 reg->key & CSRKEY_MASK, reg->val,
431 desc, info);
432 crom_next(&cc);
433 }
434 }
435
436 #define DUMP_FORMAT "%08x %08x %08x %08x %08x %08x %08x %08x\n"
437
438 static void
439 dump_crom(u_int32_t *p)
440 {
441 int len=1024, i;
442
443 for (i = 0; i < len/(4*8); i ++) {
444 printf(DUMP_FORMAT,
445 p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
446 p += 8;
447 }
448 }
449
450 static void
451 load_crom(char *filename, u_int32_t *p)
452 {
453 FILE *file;
454 int len=1024, i;
455
456 if ((file = fopen(filename, "r")) == NULL)
457 err(1, "load_crom");
458 for (i = 0; i < len/(4*8); i ++) {
459 fscanf(file, DUMP_FORMAT,
460 p, p+1, p+2, p+3, p+4, p+5, p+6, p+7);
461 p += 8;
462 }
463 }
464
465 static void
466 show_topology_map(int fd)
467 {
468 struct fw_topology_map *tmap;
469 union fw_self_id sid;
470 int i;
471 static const char *port_status[] = {" ", "-", "P", "C"};
472 static const char *pwr_class[] = {" 0W", "15W", "30W", "45W",
473 "-1W", "-2W", "-5W", "-9W"};
474 static const char *speed[] = {"S100", "S200", "S400", "S800"};
475 tmap = malloc(sizeof(struct fw_topology_map));
476 if (tmap == NULL)
477 return;
478 if (ioctl(fd, FW_GTPMAP, tmap) < 0) {
479 err(1, "ioctl");
480 }
481 printf("crc_len: %d generation:%d node_count:%d sid_count:%d\n",
482 tmap->crc_len, tmap->generation,
483 tmap->node_count, tmap->self_id_count);
484 printf("id link gap_cnt speed delay cIRM power port0 port1 port2"
485 " ini more\n");
486 for (i = 0; i < tmap->crc_len - 2; i++) {
487 sid = tmap->self_id[i];
488 if (sid.p0.sequel) {
489 printf("%02d sequel packet\n", sid.p0.phy_id);
490 continue;
491 }
492 printf("%02d %2d %2d %4s %d %d %3s"
493 " %s %s %s %d %d\n",
494 sid.p0.phy_id,
495 sid.p0.link_active,
496 sid.p0.gap_count,
497 speed[sid.p0.phy_speed],
498 sid.p0.phy_delay,
499 sid.p0.contender,
500 pwr_class[sid.p0.power_class],
501 port_status[sid.p0.port0],
502 port_status[sid.p0.port1],
503 port_status[sid.p0.port2],
504 sid.p0.initiated_reset,
505 sid.p0.more_packets
506 );
507 }
508 free(tmap);
509 }
510
511 static void
512 read_phy_registers(int fd, u_int8_t *buf, int offset, int len)
513 {
514 struct fw_reg_req_t reg;
515 int i;
516
517 for (i = 0; i < len; i++) {
518 reg.addr = offset + i;
519 if (ioctl(fd, FWOHCI_RDPHYREG, ®) < 0)
520 err(1, "ioctl");
521 buf[i] = (u_int8_t) reg.data;
522 printf("0x%02x ", reg.data);
523 }
524 printf("\n");
525 }
526
527 static void
528 read_phy_page(int fd, u_int8_t *buf, int page, int port)
529 {
530 struct fw_reg_req_t reg;
531
532 reg.addr = 0x7;
533 reg.data = ((page & 7) << 5) | (port & 0xf);
534 if (ioctl(fd, FWOHCI_WRPHYREG, ®) < 0)
535 err(1, "ioctl");
536 read_phy_registers(fd, buf, 8, 8);
537 }
538
539 static void
540 dump_phy_registers(int fd)
541 {
542 struct phyreg_base b;
543 struct phyreg_page0 p;
544 struct phyreg_page1 v;
545 int i;
546
547 printf("=== base register ===\n");
548 read_phy_registers(fd, (u_int8_t *)&b, 0, 8);
549 printf(
550 "Physical_ID:%d R:%d CPS:%d\n"
551 "RHB:%d IBR:%d Gap_Count:%d\n"
552 "Extended:%d Num_Ports:%d\n"
553 "PHY_Speed:%d Delay:%d\n"
554 "LCtrl:%d C:%d Jitter:%d Pwr_Class:%d\n"
555 "WDIE:%d ISBR:%d CTOI:%d CPSI:%d STOI:%d PEI:%d EAA:%d EMC:%d\n"
556 "Max_Legacy_SPD:%d BLINK:%d Bridge:%d\n"
557 "Page_Select:%d Port_Select%d\n",
558 b.phy_id, b.r, b.cps,
559 b.rhb, b.ibr, b.gap_count,
560 b.extended, b.num_ports,
561 b.phy_speed, b.delay,
562 b.lctrl, b.c, b.jitter, b.pwr_class,
563 b.wdie, b.isbr, b.ctoi, b.cpsi, b.stoi, b.pei, b.eaa, b.emc,
564 b.legacy_spd, b.blink, b.bridge,
565 b.page_select, b.port_select
566 );
567
568 for (i = 0; i < b.num_ports; i ++) {
569 printf("\n=== page 0 port %d ===\n", i);
570 read_phy_page(fd, (u_int8_t *)&p, 0, i);
571 printf(
572 "Astat:%d BStat:%d Ch:%d Con:%d RXOK:%d Dis:%d\n"
573 "Negotiated_speed:%d PIE:%d Fault:%d Stanby_fault:%d Disscrm:%d B_Only:%d\n"
574 "DC_connected:%d Max_port_speed:%d LPP:%d Cable_speed:%d\n"
575 "Connection_unreliable:%d Beta_mode:%d\n"
576 "Port_error:0x%x\n"
577 "Loop_disable:%d In_standby:%d Hard_disable:%d\n",
578 p.astat, p.bstat, p.ch, p.con, p.rxok, p.dis,
579 p.negotiated_speed, p.pie, p.fault, p.stanby_fault, p.disscrm, p.b_only,
580 p.dc_connected, p.max_port_speed, p.lpp, p.cable_speed,
581 p.connection_unreliable, p.beta_mode,
582 p.port_error,
583 p.loop_disable, p.in_standby, p.hard_disable
584 );
585 }
586 printf("\n=== page 1 ===\n");
587 read_phy_page(fd, (u_int8_t *)&v, 1, 0);
588 printf(
589 "Compliance:%d\n"
590 "Vendor_ID:0x%06x\n"
591 "Product_ID:0x%06x\n",
592 v.compliance,
593 (v.vendor_id[0] << 16) | (v.vendor_id[1] << 8) | v.vendor_id[2],
594 (v.product_id[0] << 16) | (v.product_id[1] << 8) | v.product_id[2]
595 );
596 }
597
598 static void
599 open_dev(int *fd, char *devbase)
600 {
601 char name[256];
602 int i;
603
604 if (*fd < 0) {
605 for (i = 0; i < 4; i++) {
606 snprintf(name, sizeof(name), "%s.%d", devbase, i);
607 if ((*fd = open(name, O_RDWR)) >= 0)
608 break;
609 }
610 if (*fd < 0)
611 err(1, "open");
612
613 }
614 }
615
616 int
617 sysctl_set_int(const char *name, int val)
618 {
619 if (sysctlbyname(name, NULL, NULL, &val, sizeof(int)) < 0)
620 err(1, "sysctl %s failed.", name);
621 return (0);
622 }
623
624 int
625 main(int argc, char **argv)
626 {
627 u_int32_t crom_buf[1024/4];
628 char devbase[1024] = "/dev/fw0";
629 int fd, tmp, ch, len=1024;
630 struct fw_eui64 eui;
631 struct eui64 target;
632
633 fd = -1;
634
635 if (argc < 2) {
636 open_dev(&fd, devbase);
637 list_dev(fd);
638 }
639
640 while ((ch = getopt(argc, argv, "g:m:o:s:b:prtc:d:l:u:R:S:")) != -1)
641 switch(ch) {
642 case 'b':
643 tmp = strtol(optarg, NULL, 0);
644 open_dev(&fd, devbase);
645 set_pri_req(fd, tmp);
646 break;
647 case 'c':
648 open_dev(&fd, devbase);
649 tmp = str2node(fd, optarg);
650 get_crom(fd, tmp, crom_buf, len);
651 show_crom(crom_buf);
652 break;
653 case 'd':
654 open_dev(&fd, devbase);
655 tmp = str2node(fd, optarg);
656 get_crom(fd, tmp, crom_buf, len);
657 dump_crom(crom_buf);
658 break;
659 case 'g':
660 tmp = strtol(optarg, NULL, 0);
661 open_dev(&fd, devbase);
662 send_phy_config(fd, -1, tmp);
663 break;
664 case 'l':
665 load_crom(optarg, crom_buf);
666 show_crom(crom_buf);
667 break;
668 case 'm':
669 if (eui64_hostton(optarg, &target) != 0 &&
670 eui64_aton(optarg, &target) != 0)
671 errx(1, "invalid target: %s", optarg);
672 eui.hi = ntohl(*(u_int32_t*)&(target.octet[0]));
673 eui.lo = ntohl(*(u_int32_t*)&(target.octet[4]));
674 sysctl_set_int("hw.firewire.fwmem.eui64_hi", eui.hi);
675 sysctl_set_int("hw.firewire.fwmem.eui64_lo", eui.lo);
676 break;
677 case 'o':
678 open_dev(&fd, devbase);
679 tmp = str2node(fd, optarg);
680 send_link_on(fd, tmp);
681 break;
682 case 'p':
683 open_dev(&fd, devbase);
684 dump_phy_registers(fd);
685 break;
686 case 'r':
687 open_dev(&fd, devbase);
688 if(ioctl(fd, FW_IBUSRST, &tmp) < 0)
689 err(1, "ioctl");
690 break;
691 case 's':
692 open_dev(&fd, devbase);
693 tmp = str2node(fd, optarg);
694 reset_start(fd, tmp);
695 break;
696 case 't':
697 open_dev(&fd, devbase);
698 show_topology_map(fd);
699 break;
700 case 'u':
701 tmp = strtol(optarg, NULL, 0);
702 snprintf(devbase, sizeof(devbase), "/dev/fw%d", tmp);
703 if (fd > 0) {
704 close(fd);
705 fd = -1;
706 }
707 if (argc == optind) {
708 open_dev(&fd, devbase);
709 list_dev(fd);
710 }
711 break;
712 #define TAG (1<<6)
713 #define CHANNEL 63
714 case 'R':
715 open_dev(&fd, devbase);
716 dvrecv(fd, optarg, TAG | CHANNEL, -1);
717 break;
718 case 'S':
719 open_dev(&fd, devbase);
720 dvsend(fd, optarg, TAG | CHANNEL, -1);
721 break;
722 default:
723 usage();
724 }
725 return 0;
726 }
727