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