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