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