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