fwcontrol.c revision 114217
1108441Ssimokawa/* 2108441Ssimokawa * Copyright (C) 2002 3108441Ssimokawa * Hidetoshi Shimokawa. All rights reserved. 4108441Ssimokawa * 5108441Ssimokawa * Redistribution and use in source and binary forms, with or without 6108441Ssimokawa * modification, are permitted provided that the following conditions 7108441Ssimokawa * are met: 8108441Ssimokawa * 1. Redistributions of source code must retain the above copyright 9108441Ssimokawa * notice, this list of conditions and the following disclaimer. 10108441Ssimokawa * 2. Redistributions in binary form must reproduce the above copyright 11108441Ssimokawa * notice, this list of conditions and the following disclaimer in the 12108441Ssimokawa * documentation and/or other materials provided with the distribution. 13108441Ssimokawa * 3. All advertising materials mentioning features or use of this software 14108441Ssimokawa * must display the following acknowledgement: 15108441Ssimokawa * 16108441Ssimokawa * This product includes software developed by Hidetoshi Shimokawa. 17108441Ssimokawa * 18108441Ssimokawa * 4. Neither the name of the author nor the names of its contributors 19108441Ssimokawa * may be used to endorse or promote products derived from this software 20108441Ssimokawa * without specific prior written permission. 21108441Ssimokawa * 22108441Ssimokawa * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23108441Ssimokawa * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24108441Ssimokawa * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25108441Ssimokawa * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26108441Ssimokawa * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27108441Ssimokawa * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28108441Ssimokawa * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29108441Ssimokawa * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30108441Ssimokawa * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31108441Ssimokawa * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32108441Ssimokawa * SUCH DAMAGE. 33108441Ssimokawa * 34108441Ssimokawa * $FreeBSD: head/usr.sbin/fwcontrol/fwcontrol.c 114217 2003-04-29 13:49:21Z simokawa $ 35108441Ssimokawa */ 36108441Ssimokawa 37108441Ssimokawa#include <sys/param.h> 38108441Ssimokawa#include <sys/malloc.h> 39108441Ssimokawa#include <sys/socket.h> 40108441Ssimokawa#include <sys/ioctl.h> 41108441Ssimokawa#include <sys/errno.h> 42108441Ssimokawa#include <dev/firewire/firewire.h> 43108441Ssimokawa#include <dev/firewire/iec13213.h> 44108441Ssimokawa 45108441Ssimokawa#include <netinet/in.h> 46108441Ssimokawa#include <fcntl.h> 47108441Ssimokawa#include <stdio.h> 48108441Ssimokawa#include <err.h> 49108441Ssimokawa#include <stdlib.h> 50108441Ssimokawa#include <string.h> 51108441Ssimokawa#include <unistd.h> 52108441Ssimokawa 53109737Ssimokawaextern int dvrecv(int, char *, char, int); 54109737Ssimokawaextern int dvsend(int, char *, char, int); 55109737Ssimokawa 56108657Ssimokawastatic void 57108441Ssimokawausage(void) 58108441Ssimokawa{ 59109787Ssimokawa fprintf(stderr, 60114217Ssimokawa "fwcontrol [-g gap_count] [-o node] [-b pri_req] [-c node]" 61114217Ssimokawa " [-r] [-t] [-d node] [-l file] [-R file] [-S file]\n" 62114217Ssimokawa "\t-g: broadcast gap_count by phy_config packet\n" 63114217Ssimokawa "\t-o: send link-on packet to the node\n" 64114217Ssimokawa "\t-s: write RESET_START register on the node\n" 65114217Ssimokawa "\t-b: set PRIORITY_BUDGET register on all supported nodes\n" 66114217Ssimokawa "\t-c: read configuration ROM\n" 67114217Ssimokawa "\t-r: bus reset\n" 68114217Ssimokawa "\t-t: read topology map\n" 69114217Ssimokawa "\t-d: hex dump of configuration ROM\n" 70114217Ssimokawa "\t-l: load and parse hex dump file of configuration ROM\n" 71114217Ssimokawa "\t-R: Receive DV stream\n" 72114217Ssimokawa "\t-S: Send DV stream\n"); 73108441Ssimokawa exit(0); 74108441Ssimokawa} 75108441Ssimokawa 76109814Ssimokawastatic struct fw_devlstreq * 77109814Ssimokawaget_dev(int fd) 78108441Ssimokawa{ 79109814Ssimokawa struct fw_devlstreq *data; 80109814Ssimokawa 81109814Ssimokawa data = (struct fw_devlstreq *)malloc(sizeof(struct fw_devlstreq)); 82109814Ssimokawa if (data == NULL) 83109814Ssimokawa err(1, "malloc"); 84108441Ssimokawa if( ioctl(fd, FW_GDEVLST, data) < 0) { 85108441Ssimokawa err(1, "ioctl"); 86108441Ssimokawa } 87109814Ssimokawa return data; 88108441Ssimokawa} 89108441Ssimokawa 90108657Ssimokawastatic void 91108441Ssimokawalist_dev(int fd) 92108441Ssimokawa{ 93109814Ssimokawa struct fw_devlstreq *data; 94109814Ssimokawa struct fw_devinfo *devinfo; 95108441Ssimokawa int i; 96108441Ssimokawa 97109814Ssimokawa data = get_dev(fd); 98109814Ssimokawa printf("%d devices (info_len=%d)\n", data->n, data->info_len); 99110578Ssimokawa printf("node EUI64 status\n"); 100109814Ssimokawa for (i = 0; i < data->info_len; i++) { 101109814Ssimokawa devinfo = &data->dev[i]; 102110578Ssimokawa printf("%4d %08x%08x %6d\n", 103110578Ssimokawa (devinfo->status || i == 0) ? devinfo->dst : -1, 104109814Ssimokawa devinfo->eui.hi, 105109814Ssimokawa devinfo->eui.lo, 106109814Ssimokawa devinfo->status 107108441Ssimokawa ); 108108441Ssimokawa } 109109814Ssimokawa free((void *)data); 110108441Ssimokawa} 111108441Ssimokawa 112108657Ssimokawastatic u_int32_t 113108441Ssimokawaread_write_quad(int fd, struct fw_eui64 eui, u_int32_t addr_lo, int read, u_int32_t data) 114108441Ssimokawa{ 115108441Ssimokawa struct fw_asyreq *asyreq; 116108441Ssimokawa u_int32_t *qld, res; 117108441Ssimokawa 118108441Ssimokawa asyreq = (struct fw_asyreq *)malloc(sizeof(struct fw_asyreq_t) + 16); 119108441Ssimokawa asyreq->req.len = 16; 120114217Ssimokawa#if 0 121114217Ssimokawa asyreq->req.type = FWASREQNODE; 122114217Ssimokawa asyreq->pkt.mode.rreqq.dst = FWLOCALBUS | node; 123114217Ssimokawa#else 124108441Ssimokawa asyreq->req.type = FWASREQEUI; 125108441Ssimokawa asyreq->req.dst.eui = eui; 126108441Ssimokawa#endif 127108441Ssimokawa asyreq->pkt.mode.rreqq.tlrt = 0; 128108441Ssimokawa if (read) 129108441Ssimokawa asyreq->pkt.mode.rreqq.tcode = FWTCODE_RREQQ; 130108441Ssimokawa else 131108441Ssimokawa asyreq->pkt.mode.rreqq.tcode = FWTCODE_WREQQ; 132108441Ssimokawa 133113584Ssimokawa asyreq->pkt.mode.rreqq.dest_hi = 0xffff; 134113584Ssimokawa asyreq->pkt.mode.rreqq.dest_lo = addr_lo; 135108441Ssimokawa 136108441Ssimokawa qld = (u_int32_t *)&asyreq->pkt; 137108441Ssimokawa if (!read) 138108441Ssimokawa asyreq->pkt.mode.wreqq.data = data; 139108441Ssimokawa 140108441Ssimokawa if (ioctl(fd, FW_ASYREQ, asyreq) < 0) { 141108441Ssimokawa err(1, "ioctl"); 142108441Ssimokawa } 143108441Ssimokawa res = qld[3]; 144108441Ssimokawa free(asyreq); 145108441Ssimokawa if (read) 146108441Ssimokawa return ntohl(res); 147108441Ssimokawa else 148108441Ssimokawa return 0; 149108441Ssimokawa} 150108657Ssimokawa 151108657Ssimokawastatic void 152108441Ssimokawasend_phy_config(int fd, int root_node, int gap_count) 153108441Ssimokawa{ 154108441Ssimokawa struct fw_asyreq *asyreq; 155108441Ssimokawa 156108441Ssimokawa asyreq = (struct fw_asyreq *)malloc(sizeof(struct fw_asyreq_t) + 12); 157108441Ssimokawa asyreq->req.len = 12; 158108441Ssimokawa asyreq->req.type = FWASREQNODE; 159108441Ssimokawa asyreq->pkt.mode.ld[0] = 0; 160108441Ssimokawa asyreq->pkt.mode.ld[1] = 0; 161108441Ssimokawa asyreq->pkt.mode.common.tcode = FWTCODE_PHY; 162108441Ssimokawa if (root_node >= 0) 163113584Ssimokawa asyreq->pkt.mode.ld[1] |= (root_node & 0x3f) << 24 | 1 << 23; 164108441Ssimokawa if (gap_count >= 0) 165113584Ssimokawa asyreq->pkt.mode.ld[1] |= 1 << 22 | (gap_count & 0x3f) << 16; 166108441Ssimokawa asyreq->pkt.mode.ld[2] = ~asyreq->pkt.mode.ld[1]; 167108441Ssimokawa 168108441Ssimokawa printf("send phy_config root_node=%d gap_count=%d\n", 169108441Ssimokawa root_node, gap_count); 170108441Ssimokawa 171108441Ssimokawa if (ioctl(fd, FW_ASYREQ, asyreq) < 0) { 172108441Ssimokawa err(1, "ioctl"); 173108441Ssimokawa } 174108441Ssimokawa} 175108441Ssimokawa 176108657Ssimokawastatic void 177114217Ssimokawasend_link_on(int fd, int node) 178114217Ssimokawa{ 179114217Ssimokawa struct fw_asyreq *asyreq; 180114217Ssimokawa 181114217Ssimokawa asyreq = (struct fw_asyreq *)malloc(sizeof(struct fw_asyreq_t) + 12); 182114217Ssimokawa asyreq->req.len = 12; 183114217Ssimokawa asyreq->req.type = FWASREQNODE; 184114217Ssimokawa asyreq->pkt.mode.common.tcode = FWTCODE_PHY; 185114217Ssimokawa asyreq->pkt.mode.ld[1] |= (1 << 30) | ((node & 0x3f) << 24); 186114217Ssimokawa asyreq->pkt.mode.ld[2] = ~asyreq->pkt.mode.ld[1]; 187114217Ssimokawa 188114217Ssimokawa if (ioctl(fd, FW_ASYREQ, asyreq) < 0) { 189114217Ssimokawa err(1, "ioctl"); 190114217Ssimokawa } 191114217Ssimokawa} 192114217Ssimokawa 193114217Ssimokawastatic void 194114217Ssimokawareset_start(int fd, int node) 195114217Ssimokawa{ 196114217Ssimokawa struct fw_asyreq *asyreq; 197114217Ssimokawa 198114217Ssimokawa asyreq = (struct fw_asyreq *)malloc(sizeof(struct fw_asyreq_t) + 16); 199114217Ssimokawa asyreq->req.len = 16; 200114217Ssimokawa asyreq->req.type = FWASREQNODE; 201114217Ssimokawa asyreq->pkt.mode.wreqq.dst = FWLOCALBUS | (node & 0x3f); 202114217Ssimokawa asyreq->pkt.mode.wreqq.tlrt = 0; 203114217Ssimokawa asyreq->pkt.mode.wreqq.tcode = FWTCODE_WREQQ; 204114217Ssimokawa 205114217Ssimokawa asyreq->pkt.mode.wreqq.dest_hi = 0xffff; 206114217Ssimokawa asyreq->pkt.mode.wreqq.dest_lo = 0xf0000000 | RESET_START; 207114217Ssimokawa 208114217Ssimokawa asyreq->pkt.mode.wreqq.data = htonl(0x1); 209114217Ssimokawa 210114217Ssimokawa if (ioctl(fd, FW_ASYREQ, asyreq) < 0) { 211114217Ssimokawa err(1, "ioctl"); 212114217Ssimokawa } 213114217Ssimokawa} 214114217Ssimokawa 215114217Ssimokawastatic void 216108441Ssimokawaset_pri_req(int fd, int pri_req) 217108441Ssimokawa{ 218109814Ssimokawa struct fw_devlstreq *data; 219109814Ssimokawa struct fw_devinfo *devinfo; 220108441Ssimokawa u_int32_t max, reg, old; 221108441Ssimokawa int i; 222108441Ssimokawa 223109814Ssimokawa data = get_dev(fd); 224108441Ssimokawa#define BUGET_REG 0xf0000218 225109814Ssimokawa for (i = 0; i < data->info_len; i++) { 226109814Ssimokawa devinfo = &data->dev[i]; 227109814Ssimokawa if (!devinfo->status) 228108441Ssimokawa continue; 229109814Ssimokawa reg = read_write_quad(fd, devinfo->eui, BUGET_REG, 1, 0); 230108441Ssimokawa printf("%d %08x:%08x, %08x", 231109814Ssimokawa devinfo->dst, devinfo->eui.hi, devinfo->eui.lo, reg); 232108441Ssimokawa if (reg > 0 && pri_req >= 0) { 233108441Ssimokawa old = (reg & 0x3f); 234108441Ssimokawa max = (reg & 0x3f00) >> 8; 235108441Ssimokawa if (pri_req > max) 236108441Ssimokawa pri_req = max; 237108441Ssimokawa printf(" 0x%x -> 0x%x\n", old, pri_req); 238109814Ssimokawa read_write_quad(fd, devinfo->eui, BUGET_REG, 0, pri_req); 239108441Ssimokawa } else { 240108441Ssimokawa printf("\n"); 241108441Ssimokawa } 242108441Ssimokawa } 243109814Ssimokawa free((void *)data); 244108441Ssimokawa} 245108441Ssimokawa 246108657Ssimokawastatic void 247108657Ssimokawaparse_bus_info_block(u_int32_t *p, int info_len) 248108441Ssimokawa{ 249108441Ssimokawa int i; 250108441Ssimokawa 251108441Ssimokawa for (i = 0; i < info_len; i++) { 252108441Ssimokawa printf("bus_info%d: 0x%08x\n", i, *p++); 253108441Ssimokawa } 254108441Ssimokawa} 255108441Ssimokawa 256108657Ssimokawastatic int 257108441Ssimokawaget_crom(int fd, int node, void *crom_buf, int len) 258108441Ssimokawa{ 259108441Ssimokawa struct fw_crom_buf buf; 260109991Ssimokawa int i, error; 261109814Ssimokawa struct fw_devlstreq *data; 262108441Ssimokawa 263109814Ssimokawa data = get_dev(fd); 264108441Ssimokawa 265109814Ssimokawa for (i = 0; i < data->info_len; i++) { 266109814Ssimokawa if (data->dev[i].dst == node && data->dev[i].eui.lo != 0) 267108441Ssimokawa break; 268108441Ssimokawa } 269109814Ssimokawa if (i == data->info_len) 270109814Ssimokawa errx(1, "no such node %d.", node); 271109814Ssimokawa else if (i == 0) 272109814Ssimokawa errx(1, "node %d is myself.", node); 273109814Ssimokawa else 274109814Ssimokawa buf.eui = data->dev[i].eui; 275109814Ssimokawa free((void *)data); 276108441Ssimokawa 277108441Ssimokawa buf.len = len; 278108441Ssimokawa buf.ptr = crom_buf; 279108441Ssimokawa if ((error = ioctl(fd, FW_GCROM, &buf)) < 0) { 280108441Ssimokawa err(1, "ioctl"); 281108441Ssimokawa } 282109814Ssimokawa 283108441Ssimokawa return error; 284108441Ssimokawa} 285108441Ssimokawa 286108657Ssimokawastatic void 287108441Ssimokawashow_crom(u_int32_t *crom_buf) 288108441Ssimokawa{ 289108441Ssimokawa int i; 290108441Ssimokawa struct crom_context cc; 291108441Ssimokawa char *desc, info[256]; 292108441Ssimokawa static char *key_types = "ICLD"; 293108441Ssimokawa struct csrreg *reg; 294108441Ssimokawa struct csrdirectory *dir; 295108441Ssimokawa struct csrhdr *hdr; 296113584Ssimokawa u_int16_t crc; 297108441Ssimokawa 298113584Ssimokawa printf("first quad: 0x%08x ", *crom_buf); 299108441Ssimokawa hdr = (struct csrhdr *)crom_buf; 300108441Ssimokawa if (hdr->info_len == 1) { 301108441Ssimokawa /* minimum ROM */ 302108441Ssimokawa struct csrreg *reg; 303108441Ssimokawa reg = (struct csrreg *)hdr; 304108441Ssimokawa printf("verndor ID: 0x%06x\n", reg->val); 305108441Ssimokawa return; 306108441Ssimokawa } 307113584Ssimokawa printf("info_len=%d crc_len=%d crc=0x%04x", 308113584Ssimokawa hdr->info_len, hdr->crc_len, hdr->crc); 309113584Ssimokawa crc = crom_crc(crom_buf+1, hdr->crc_len); 310113584Ssimokawa if (crc == hdr->crc) 311113584Ssimokawa printf("(OK)\n"); 312113584Ssimokawa else 313113584Ssimokawa printf("(NG)\n"); 314108441Ssimokawa parse_bus_info_block(crom_buf+1, hdr->info_len); 315108441Ssimokawa 316108441Ssimokawa crom_init_context(&cc, crom_buf); 317108441Ssimokawa dir = cc.stack[0].dir; 318113584Ssimokawa printf("root_directory: len=0x%04x(%d) crc=0x%04x", 319108441Ssimokawa dir->crc_len, dir->crc_len, dir->crc); 320113584Ssimokawa crc = crom_crc((u_int32_t *)&dir->entry[0], dir->crc_len); 321113584Ssimokawa if (crc == dir->crc) 322113584Ssimokawa printf("(OK)\n"); 323113584Ssimokawa else 324113584Ssimokawa printf("(NG)\n"); 325108657Ssimokawa if (dir->crc_len < 1) 326108657Ssimokawa return; 327108441Ssimokawa while (cc.depth >= 0) { 328108441Ssimokawa desc = crom_desc(&cc, info, sizeof(info)); 329108441Ssimokawa reg = crom_get(&cc); 330108441Ssimokawa for (i = 0; i < cc.depth; i++) 331108441Ssimokawa printf("\t"); 332108441Ssimokawa printf("%02x(%c:%02x) %06x %s: %s\n", 333108441Ssimokawa reg->key, 334108441Ssimokawa key_types[(reg->key & CSRTYPE_MASK)>>6], 335108441Ssimokawa reg->key & CSRKEY_MASK, reg->val, 336108441Ssimokawa desc, info); 337108441Ssimokawa crom_next(&cc); 338108441Ssimokawa } 339108441Ssimokawa} 340108441Ssimokawa 341108441Ssimokawa#define DUMP_FORMAT "%08x %08x %08x %08x %08x %08x %08x %08x\n" 342108441Ssimokawa 343108657Ssimokawastatic void 344108441Ssimokawadump_crom(u_int32_t *p) 345108441Ssimokawa{ 346108441Ssimokawa int len=1024, i; 347108441Ssimokawa 348108441Ssimokawa for (i = 0; i < len/(4*8); i ++) { 349108441Ssimokawa printf(DUMP_FORMAT, 350108441Ssimokawa p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); 351108441Ssimokawa p += 8; 352108441Ssimokawa } 353108441Ssimokawa} 354108441Ssimokawa 355108657Ssimokawastatic void 356108441Ssimokawaload_crom(char *filename, u_int32_t *p) 357108441Ssimokawa{ 358108441Ssimokawa FILE *file; 359108441Ssimokawa int len=1024, i; 360108441Ssimokawa 361108441Ssimokawa if ((file = fopen(filename, "r")) == NULL) 362108441Ssimokawa err(1, "load_crom"); 363108441Ssimokawa for (i = 0; i < len/(4*8); i ++) { 364108441Ssimokawa fscanf(file, DUMP_FORMAT, 365108441Ssimokawa p, p+1, p+2, p+3, p+4, p+5, p+6, p+7); 366108441Ssimokawa p += 8; 367108441Ssimokawa } 368108441Ssimokawa} 369108441Ssimokawa 370108441Ssimokawastatic void 371108441Ssimokawashow_topology_map(int fd) 372108441Ssimokawa{ 373108441Ssimokawa struct fw_topology_map *tmap; 374108441Ssimokawa union fw_self_id sid; 375108441Ssimokawa int i; 376108441Ssimokawa static char *port_status[] = {" ", "-", "P", "C"}; 377108441Ssimokawa static char *pwr_class[] = {" 0W", "15W", "30W", "45W", 378108441Ssimokawa "-1W", "-2W", "-5W", "-9W"}; 379108441Ssimokawa static char *speed[] = {"S100", "S200", "S400", "S800"}; 380108441Ssimokawa tmap = malloc(sizeof(struct fw_topology_map)); 381108441Ssimokawa if (tmap == NULL) 382108441Ssimokawa return; 383108441Ssimokawa if (ioctl(fd, FW_GTPMAP, tmap) < 0) { 384108441Ssimokawa err(1, "ioctl"); 385108441Ssimokawa } 386108441Ssimokawa printf("crc_len: %d generation:%d node_count:%d sid_count:%d\n", 387108441Ssimokawa tmap->crc_len, tmap->generation, 388108441Ssimokawa tmap->node_count, tmap->self_id_count); 389108441Ssimokawa printf("id link gap_cnt speed delay cIRM power port0 port1 port2" 390108441Ssimokawa " ini more\n"); 391108441Ssimokawa for (i = 0; i < tmap->crc_len - 2; i++) { 392108441Ssimokawa sid = tmap->self_id[i]; 393108441Ssimokawa if (sid.p0.sequel) { 394108441Ssimokawa printf("%02d sequel packet\n", sid.p0.phy_id); 395108441Ssimokawa continue; 396108441Ssimokawa } 397110070Ssimokawa printf("%02d %2d %2d %4s %d %d %3s" 398108441Ssimokawa " %s %s %s %d %d\n", 399108441Ssimokawa sid.p0.phy_id, 400108441Ssimokawa sid.p0.link_active, 401108441Ssimokawa sid.p0.gap_count, 402108441Ssimokawa speed[sid.p0.phy_speed], 403108441Ssimokawa sid.p0.phy_delay, 404108441Ssimokawa sid.p0.contender, 405108441Ssimokawa pwr_class[sid.p0.power_class], 406108441Ssimokawa port_status[sid.p0.port0], 407108441Ssimokawa port_status[sid.p0.port1], 408108441Ssimokawa port_status[sid.p0.port2], 409108441Ssimokawa sid.p0.initiated_reset, 410108441Ssimokawa sid.p0.more_packets 411108441Ssimokawa ); 412108441Ssimokawa } 413108441Ssimokawa free(tmap); 414108441Ssimokawa} 415108441Ssimokawa 416108441Ssimokawaint 417108441Ssimokawamain(int argc, char **argv) 418108441Ssimokawa{ 419109991Ssimokawa char devname[256]; 420108441Ssimokawa u_int32_t crom_buf[1024/4]; 421109991Ssimokawa int fd, i, tmp, ch, len=1024; 422108441Ssimokawa 423109991Ssimokawa for (i = 0; i < 4; i++) { 424109991Ssimokawa snprintf(devname, sizeof(devname), "/dev/fw%d", i); 425109991Ssimokawa if ((fd = open(devname, O_RDWR)) >= 0) 426109991Ssimokawa break; 427109991Ssimokawa } 428109991Ssimokawa if (fd < 0) 429108441Ssimokawa err(1, "open"); 430108441Ssimokawa 431108441Ssimokawa if (argc < 2) { 432108441Ssimokawa list_dev(fd); 433108441Ssimokawa } 434108441Ssimokawa 435114217Ssimokawa while ((ch = getopt(argc, argv, "g:o:s:b:rtc:d:l:R:S:")) != -1) 436108441Ssimokawa switch(ch) { 437108441Ssimokawa case 'g': 438108441Ssimokawa tmp = strtol(optarg, NULL, 0); 439108441Ssimokawa send_phy_config(fd, -1, tmp); 440108441Ssimokawa break; 441114217Ssimokawa case 'o': 442114217Ssimokawa tmp = strtol(optarg, NULL, 0); 443114217Ssimokawa send_link_on(fd, tmp); 444114217Ssimokawa break; 445114217Ssimokawa case 's': 446114217Ssimokawa tmp = strtol(optarg, NULL, 0); 447114217Ssimokawa reset_start(fd, tmp); 448114217Ssimokawa break; 449108441Ssimokawa case 'b': 450108441Ssimokawa tmp = strtol(optarg, NULL, 0); 451108441Ssimokawa set_pri_req(fd, tmp); 452108441Ssimokawa break; 453108441Ssimokawa case 'r': 454108441Ssimokawa if(ioctl(fd, FW_IBUSRST, &tmp) < 0) 455108441Ssimokawa err(1, "ioctl"); 456108441Ssimokawa break; 457108441Ssimokawa case 't': 458108441Ssimokawa show_topology_map(fd); 459108441Ssimokawa break; 460108441Ssimokawa case 'c': 461108441Ssimokawa tmp = strtol(optarg, NULL, 0); 462108441Ssimokawa get_crom(fd, tmp, crom_buf, len); 463108441Ssimokawa show_crom(crom_buf); 464108441Ssimokawa break; 465108441Ssimokawa case 'd': 466108441Ssimokawa tmp = strtol(optarg, NULL, 0); 467108441Ssimokawa get_crom(fd, tmp, crom_buf, len); 468108441Ssimokawa dump_crom(crom_buf); 469108441Ssimokawa break; 470108441Ssimokawa case 'l': 471108441Ssimokawa load_crom(optarg, crom_buf); 472108441Ssimokawa show_crom(crom_buf); 473108441Ssimokawa break; 474109737Ssimokawa#define TAG (1<<6) 475109737Ssimokawa#define CHANNEL 63 476109737Ssimokawa case 'R': 477109737Ssimokawa dvrecv(fd, optarg, TAG | CHANNEL, -1); 478109737Ssimokawa break; 479109737Ssimokawa case 'S': 480109737Ssimokawa dvsend(fd, optarg, TAG | CHANNEL, -1); 481109737Ssimokawa break; 482108441Ssimokawa default: 483108441Ssimokawa usage(); 484108441Ssimokawa } 485108441Ssimokawa return 0; 486108441Ssimokawa} 487