1df57947fSPedro F. Giffuni /*- 2df57947fSPedro F. Giffuni * SPDX-License-Identifier: BSD-4-Clause 3df57947fSPedro F. Giffuni * 4a7a73b95SHidetoshi Shimokawa * Copyright (C) 2002 5a7a73b95SHidetoshi Shimokawa * Hidetoshi Shimokawa. All rights reserved. 6a7a73b95SHidetoshi Shimokawa * 7a7a73b95SHidetoshi Shimokawa * Redistribution and use in source and binary forms, with or without 8a7a73b95SHidetoshi Shimokawa * modification, are permitted provided that the following conditions 9a7a73b95SHidetoshi Shimokawa * are met: 10a7a73b95SHidetoshi Shimokawa * 1. Redistributions of source code must retain the above copyright 11a7a73b95SHidetoshi Shimokawa * notice, this list of conditions and the following disclaimer. 12a7a73b95SHidetoshi Shimokawa * 2. Redistributions in binary form must reproduce the above copyright 13a7a73b95SHidetoshi Shimokawa * notice, this list of conditions and the following disclaimer in the 14a7a73b95SHidetoshi Shimokawa * documentation and/or other materials provided with the distribution. 15a7a73b95SHidetoshi Shimokawa * 3. All advertising materials mentioning features or use of this software 16a7a73b95SHidetoshi Shimokawa * must display the following acknowledgement: 17a7a73b95SHidetoshi Shimokawa * 18a7a73b95SHidetoshi Shimokawa * This product includes software developed by Hidetoshi Shimokawa. 19a7a73b95SHidetoshi Shimokawa * 20a7a73b95SHidetoshi Shimokawa * 4. Neither the name of the author nor the names of its contributors 21a7a73b95SHidetoshi Shimokawa * may be used to endorse or promote products derived from this software 22a7a73b95SHidetoshi Shimokawa * without specific prior written permission. 23a7a73b95SHidetoshi Shimokawa * 24a7a73b95SHidetoshi Shimokawa * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25a7a73b95SHidetoshi Shimokawa * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26a7a73b95SHidetoshi Shimokawa * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27a7a73b95SHidetoshi Shimokawa * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28a7a73b95SHidetoshi Shimokawa * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29a7a73b95SHidetoshi Shimokawa * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30a7a73b95SHidetoshi Shimokawa * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31a7a73b95SHidetoshi Shimokawa * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32a7a73b95SHidetoshi Shimokawa * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33a7a73b95SHidetoshi Shimokawa * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34a7a73b95SHidetoshi Shimokawa * SUCH DAMAGE. 35a7a73b95SHidetoshi Shimokawa */ 36a7a73b95SHidetoshi Shimokawa 37c1de48a3SSean Bruno #if defined(__FreeBSD__) 383fe9d89aSPhilippe Charnier #include <sys/cdefs.h> 39c1de48a3SSean Bruno #endif 403fe9d89aSPhilippe Charnier 41a7a73b95SHidetoshi Shimokawa #include <sys/param.h> 42a7a73b95SHidetoshi Shimokawa #include <sys/malloc.h> 433fe9d89aSPhilippe Charnier #include <sys/types.h> 443fe9d89aSPhilippe Charnier #include <sys/sysctl.h> 45a7a73b95SHidetoshi Shimokawa #include <sys/socket.h> 46a7a73b95SHidetoshi Shimokawa #include <sys/ioctl.h> 47a7a73b95SHidetoshi Shimokawa #include <sys/errno.h> 48c1de48a3SSean Bruno #if defined(__FreeBSD__) 49cb5df0b2SBrooks Davis #include <sys/eui64.h> 50a7a73b95SHidetoshi Shimokawa #include <dev/firewire/firewire.h> 51a7a73b95SHidetoshi Shimokawa #include <dev/firewire/iec13213.h> 52a8587980SHidetoshi Shimokawa #include <dev/firewire/fwphyreg.h> 536d815a7dSWarner Losh #include <dev/firewire/iec68113.h> 54c1de48a3SSean Bruno #elif defined(__NetBSD__) 55c1de48a3SSean Bruno #include "eui64.h" 56c1de48a3SSean Bruno #include <dev/ieee1394/firewire.h> 57c1de48a3SSean Bruno #include <dev/ieee1394/iec13213.h> 58c1de48a3SSean Bruno #include <dev/ieee1394/fwphyreg.h> 59c1de48a3SSean Bruno #include <dev/ieee1394/iec68113.h> 60c1de48a3SSean Bruno #else 61c1de48a3SSean Bruno #warning "You need to add support for your OS" 62c1de48a3SSean Bruno #endif 63c1de48a3SSean Bruno 64a7a73b95SHidetoshi Shimokawa 65a7a73b95SHidetoshi Shimokawa #include <netinet/in.h> 66a7a73b95SHidetoshi Shimokawa #include <fcntl.h> 67a7a73b95SHidetoshi Shimokawa #include <stdio.h> 68a7a73b95SHidetoshi Shimokawa #include <err.h> 69a7a73b95SHidetoshi Shimokawa #include <stdlib.h> 70a7a73b95SHidetoshi Shimokawa #include <string.h> 716d815a7dSWarner Losh #include <sysexits.h> 72a7a73b95SHidetoshi Shimokawa #include <unistd.h> 737f1b527cSSean Bruno #include <stdint.h> 747f1b527cSSean Bruno #include <stdbool.h> 756d815a7dSWarner Losh #include "fwmethods.h" 76a7a73b95SHidetoshi Shimokawa 776d815a7dSWarner Losh static void sysctl_set_int(const char *, int); 783fe9d89aSPhilippe Charnier 797ddbf617SHidetoshi Shimokawa static void 80a7a73b95SHidetoshi Shimokawa usage(void) 81a7a73b95SHidetoshi Shimokawa { 828604e72aSHidetoshi Shimokawa fprintf(stderr, 83c1de48a3SSean Bruno "%s [-u bus_num] [-prt] [-c node] [-d node] [-o node] [-s node]\n" 847f1b527cSSean Bruno "\t [-l file] [-g gap_count] [-f force_root ] [-b pri_req]\n" 857f1b527cSSean Bruno "\t [-M mode] [-R filename] [-S filename] [-m EUI64 | hostname]\n" 86abd538f2SHidetoshi Shimokawa "\t-u: specify bus number\n" 877f1b527cSSean Bruno "\t-p: Display current PHY register settings\n" 88d1f7bcb5SHidetoshi Shimokawa "\t-r: bus reset\n" 89d1f7bcb5SHidetoshi Shimokawa "\t-t: read topology map\n" 907f1b527cSSean Bruno "\t-c: read configuration ROM\n" 91d1f7bcb5SHidetoshi Shimokawa "\t-d: hex dump of configuration ROM\n" 927f1b527cSSean Bruno "\t-o: send link-on packet to the node\n" 937f1b527cSSean Bruno "\t-s: write RESET_START register on the node\n" 94d1f7bcb5SHidetoshi Shimokawa "\t-l: load and parse hex dump file of configuration ROM\n" 95c1de48a3SSean Bruno "\t-g: set gap count\n" 96c1de48a3SSean Bruno "\t-f: force root node\n" 977f1b527cSSean Bruno "\t-b: set PRIORITY_BUDGET register on all supported nodes\n" 987f1b527cSSean Bruno "\t-M: specify dv or mpeg\n" 996d815a7dSWarner Losh "\t-R: Receive DV or MPEG TS stream\n" 100f6248231SHidetoshi Shimokawa "\t-S: Send DV stream\n" 101c1de48a3SSean Bruno "\t-m: set fwmem target\n" 102c1de48a3SSean Bruno , getprogname() ); 103c1de48a3SSean Bruno fprintf(stderr, "\n"); 104a7a73b95SHidetoshi Shimokawa } 105a7a73b95SHidetoshi Shimokawa 106cb5df0b2SBrooks Davis static void 107cb5df0b2SBrooks Davis fweui2eui64(const struct fw_eui64 *fweui, struct eui64 *eui) 108cb5df0b2SBrooks Davis { 109cb5df0b2SBrooks Davis *(u_int32_t*)&(eui->octet[0]) = htonl(fweui->hi); 110cb5df0b2SBrooks Davis *(u_int32_t*)&(eui->octet[4]) = htonl(fweui->lo); 111cb5df0b2SBrooks Davis } 112cb5df0b2SBrooks Davis 1137f1b527cSSean Bruno static void 1147f1b527cSSean Bruno get_dev(int fd, struct fw_devlstreq *data) 115a7a73b95SHidetoshi Shimokawa { 116c547b896SHidetoshi Shimokawa if (data == NULL) 1177f1b527cSSean Bruno err(EX_SOFTWARE, "%s: data malloc", __func__); 118a7a73b95SHidetoshi Shimokawa if( ioctl(fd, FW_GDEVLST, data) < 0) { 1197f1b527cSSean Bruno err(EX_IOERR, "%s: ioctl", __func__); 120a7a73b95SHidetoshi Shimokawa } 121a7a73b95SHidetoshi Shimokawa } 122a7a73b95SHidetoshi Shimokawa 123cb5df0b2SBrooks Davis static int 124cb5df0b2SBrooks Davis str2node(int fd, const char *nodestr) 125cb5df0b2SBrooks Davis { 126cb5df0b2SBrooks Davis struct eui64 eui, tmpeui; 127cb5df0b2SBrooks Davis struct fw_devlstreq *data; 128cb5df0b2SBrooks Davis char *endptr; 129cb5df0b2SBrooks Davis int i, node; 130cb5df0b2SBrooks Davis 131f1897613SBrooks Davis if (nodestr == NULL || *nodestr == '\0') 132cb5df0b2SBrooks Davis return (-1); 133cb5df0b2SBrooks Davis 134cb5df0b2SBrooks Davis /* 135cb5df0b2SBrooks Davis * Deal with classic node specifications. 136cb5df0b2SBrooks Davis */ 137cb5df0b2SBrooks Davis node = strtol(nodestr, &endptr, 0); 138cb5df0b2SBrooks Davis if (*endptr == '\0') 139cb5df0b2SBrooks Davis goto gotnode; 140cb5df0b2SBrooks Davis 141cb5df0b2SBrooks Davis /* 142cb5df0b2SBrooks Davis * Try to get an eui and match it against available nodes. 143cb5df0b2SBrooks Davis */ 144cb5df0b2SBrooks Davis if (eui64_hostton(nodestr, &eui) != 0 && eui64_aton(nodestr, &eui) != 0) 145cb5df0b2SBrooks Davis return (-1); 146cb5df0b2SBrooks Davis 1477f1b527cSSean Bruno data = (struct fw_devlstreq *)malloc(sizeof(struct fw_devlstreq)); 1487f1b527cSSean Bruno if (data == NULL) 1497f1b527cSSean Bruno err(EX_SOFTWARE, "%s: data malloc", __func__); 1507f1b527cSSean Bruno get_dev(fd,data); 151cb5df0b2SBrooks Davis 152cb5df0b2SBrooks Davis for (i = 0; i < data->info_len; i++) { 153cb5df0b2SBrooks Davis fweui2eui64(&data->dev[i].eui, &tmpeui); 154cb5df0b2SBrooks Davis if (memcmp(&eui, &tmpeui, sizeof(struct eui64)) == 0) { 155cb5df0b2SBrooks Davis node = data->dev[i].dst; 1567f1b527cSSean Bruno free(data); 157cb5df0b2SBrooks Davis goto gotnode; 158cb5df0b2SBrooks Davis } 159cb5df0b2SBrooks Davis } 1607f1b527cSSean Bruno if (i >= data->info_len) { 1617f1b527cSSean Bruno if (data != NULL) 1627f1b527cSSean Bruno free(data); 163cb5df0b2SBrooks Davis return (-1); 1647f1b527cSSean Bruno } 165cb5df0b2SBrooks Davis 166cb5df0b2SBrooks Davis gotnode: 167cb5df0b2SBrooks Davis if (node < 0 || node > 63) 168cb5df0b2SBrooks Davis return (-1); 169cb5df0b2SBrooks Davis else 170cb5df0b2SBrooks Davis return (node); 171cb5df0b2SBrooks Davis } 172cb5df0b2SBrooks Davis 1737ddbf617SHidetoshi Shimokawa static void 174a7a73b95SHidetoshi Shimokawa list_dev(int fd) 175a7a73b95SHidetoshi Shimokawa { 176c547b896SHidetoshi Shimokawa struct fw_devlstreq *data; 177c547b896SHidetoshi Shimokawa struct fw_devinfo *devinfo; 178cb5df0b2SBrooks Davis struct eui64 eui; 179302176c7SHidetoshi Shimokawa char addr[EUI64_SIZ], hostname[40]; 180a7a73b95SHidetoshi Shimokawa int i; 181a7a73b95SHidetoshi Shimokawa 1827f1b527cSSean Bruno data = (struct fw_devlstreq *)malloc(sizeof(struct fw_devlstreq)); 1837f1b527cSSean Bruno if (data == NULL) 1847f1b527cSSean Bruno err(EX_SOFTWARE, "%s:data malloc", __func__); 1857f1b527cSSean Bruno get_dev(fd, data); 186c547b896SHidetoshi Shimokawa printf("%d devices (info_len=%d)\n", data->n, data->info_len); 187302176c7SHidetoshi Shimokawa printf("node EUI64 status hostname\n"); 188c547b896SHidetoshi Shimokawa for (i = 0; i < data->info_len; i++) { 189c547b896SHidetoshi Shimokawa devinfo = &data->dev[i]; 190cb5df0b2SBrooks Davis fweui2eui64(&devinfo->eui, &eui); 191cb5df0b2SBrooks Davis eui64_ntoa(&eui, addr, sizeof(addr)); 192302176c7SHidetoshi Shimokawa if (eui64_ntohost(hostname, sizeof(hostname), &eui)) 193302176c7SHidetoshi Shimokawa hostname[0] = 0; 194302176c7SHidetoshi Shimokawa printf("%4d %s %6d %s\n", 195e6aaafcdSHidetoshi Shimokawa (devinfo->status || i == 0) ? devinfo->dst : -1, 196cb5df0b2SBrooks Davis addr, 197302176c7SHidetoshi Shimokawa devinfo->status, 198302176c7SHidetoshi Shimokawa hostname 199a7a73b95SHidetoshi Shimokawa ); 200a7a73b95SHidetoshi Shimokawa } 201c547b896SHidetoshi Shimokawa free((void *)data); 202a7a73b95SHidetoshi Shimokawa } 203a7a73b95SHidetoshi Shimokawa 2047ddbf617SHidetoshi Shimokawa static u_int32_t 2053fe9d89aSPhilippe Charnier read_write_quad(int fd, struct fw_eui64 eui, u_int32_t addr_lo, int readmode, u_int32_t data) 206a7a73b95SHidetoshi Shimokawa { 207a7a73b95SHidetoshi Shimokawa struct fw_asyreq *asyreq; 208a7a73b95SHidetoshi Shimokawa u_int32_t *qld, res; 209a7a73b95SHidetoshi Shimokawa 210*9494dfe1SJohn Baldwin asyreq = malloc(sizeof(*asyreq)); 2117f1b527cSSean Bruno if (asyreq == NULL) 2127f1b527cSSean Bruno err(EX_SOFTWARE, "%s:asyreq malloc", __func__); 213a7a73b95SHidetoshi Shimokawa asyreq->req.len = 16; 214d1f7bcb5SHidetoshi Shimokawa #if 0 215d1f7bcb5SHidetoshi Shimokawa asyreq->req.type = FWASREQNODE; 216d1f7bcb5SHidetoshi Shimokawa asyreq->pkt.mode.rreqq.dst = FWLOCALBUS | node; 217d1f7bcb5SHidetoshi Shimokawa #else 218a7a73b95SHidetoshi Shimokawa asyreq->req.type = FWASREQEUI; 219a7a73b95SHidetoshi Shimokawa asyreq->req.dst.eui = eui; 220a7a73b95SHidetoshi Shimokawa #endif 221a7a73b95SHidetoshi Shimokawa asyreq->pkt.mode.rreqq.tlrt = 0; 2223fe9d89aSPhilippe Charnier if (readmode) 223a7a73b95SHidetoshi Shimokawa asyreq->pkt.mode.rreqq.tcode = FWTCODE_RREQQ; 224a7a73b95SHidetoshi Shimokawa else 225a7a73b95SHidetoshi Shimokawa asyreq->pkt.mode.rreqq.tcode = FWTCODE_WREQQ; 226a7a73b95SHidetoshi Shimokawa 22777ee030bSHidetoshi Shimokawa asyreq->pkt.mode.rreqq.dest_hi = 0xffff; 22877ee030bSHidetoshi Shimokawa asyreq->pkt.mode.rreqq.dest_lo = addr_lo; 229a7a73b95SHidetoshi Shimokawa 230a7a73b95SHidetoshi Shimokawa qld = (u_int32_t *)&asyreq->pkt; 2313fe9d89aSPhilippe Charnier if (!readmode) 232302176c7SHidetoshi Shimokawa asyreq->pkt.mode.wreqq.data = htonl(data); 233a7a73b95SHidetoshi Shimokawa 234a7a73b95SHidetoshi Shimokawa if (ioctl(fd, FW_ASYREQ, asyreq) < 0) { 2357f1b527cSSean Bruno err(EX_IOERR, "%s: ioctl", __func__); 236a7a73b95SHidetoshi Shimokawa } 237a7a73b95SHidetoshi Shimokawa res = qld[3]; 238a7a73b95SHidetoshi Shimokawa free(asyreq); 2393fe9d89aSPhilippe Charnier if (readmode) 240a7a73b95SHidetoshi Shimokawa return ntohl(res); 241a7a73b95SHidetoshi Shimokawa else 242a7a73b95SHidetoshi Shimokawa return 0; 243a7a73b95SHidetoshi Shimokawa } 2447ddbf617SHidetoshi Shimokawa 2457f1b527cSSean Bruno /* 2467f1b527cSSean Bruno * Send a PHY Config Packet 2477f1b527cSSean Bruno * ieee 1394a-2005 4.3.4.3 2487f1b527cSSean Bruno * 2497f1b527cSSean Bruno * Message ID Root ID R T Gap Count 2507f1b527cSSean Bruno * 00(2 bits) (6 bits) 1 1 (6 bits) 2517f1b527cSSean Bruno * 2527f1b527cSSean Bruno * if "R" is set, then Root ID will be the next 2537f1b527cSSean Bruno * root node upon the next bus reset. 2547f1b527cSSean Bruno * if "T" is set, then Gap Count will be the 2557f1b527cSSean Bruno * value that all nodes use for their Gap Count 2567f1b527cSSean Bruno * if "R" and "T" are not set, then this message 2577f1b527cSSean Bruno * is either ignored or interpreted as an extended 2587f1b527cSSean Bruno * PHY config Packet as per 1394a-2005 4.3.4.4 2597f1b527cSSean Bruno */ 2607ddbf617SHidetoshi Shimokawa static void 261a7a73b95SHidetoshi Shimokawa send_phy_config(int fd, int root_node, int gap_count) 262a7a73b95SHidetoshi Shimokawa { 263a7a73b95SHidetoshi Shimokawa struct fw_asyreq *asyreq; 264a7a73b95SHidetoshi Shimokawa 265*9494dfe1SJohn Baldwin asyreq = malloc(sizeof(*asyreq)); 2667f1b527cSSean Bruno if (asyreq == NULL) 2677f1b527cSSean Bruno err(EX_SOFTWARE, "%s:asyreq malloc", __func__); 268a7a73b95SHidetoshi Shimokawa asyreq->req.len = 12; 269a7a73b95SHidetoshi Shimokawa asyreq->req.type = FWASREQNODE; 270a7a73b95SHidetoshi Shimokawa asyreq->pkt.mode.ld[0] = 0; 271a7a73b95SHidetoshi Shimokawa asyreq->pkt.mode.ld[1] = 0; 272a7a73b95SHidetoshi Shimokawa asyreq->pkt.mode.common.tcode = FWTCODE_PHY; 273a7a73b95SHidetoshi Shimokawa if (root_node >= 0) 2747f1b527cSSean Bruno asyreq->pkt.mode.ld[1] |= ((root_node << 24) | (1 << 23)); 275a7a73b95SHidetoshi Shimokawa if (gap_count >= 0) 2767f1b527cSSean Bruno asyreq->pkt.mode.ld[1] |= ((1 << 22) | (gap_count << 16)); 277a7a73b95SHidetoshi Shimokawa asyreq->pkt.mode.ld[2] = ~asyreq->pkt.mode.ld[1]; 278a7a73b95SHidetoshi Shimokawa 279a7a73b95SHidetoshi Shimokawa printf("send phy_config root_node=%d gap_count=%d\n", 280a7a73b95SHidetoshi Shimokawa root_node, gap_count); 281a7a73b95SHidetoshi Shimokawa 2825193feb6SHidetoshi Shimokawa if (ioctl(fd, FW_ASYREQ, asyreq) < 0) 2837f1b527cSSean Bruno err(EX_IOERR, "%s: ioctl", __func__); 2845193feb6SHidetoshi Shimokawa free(asyreq); 285a7a73b95SHidetoshi Shimokawa } 286a7a73b95SHidetoshi Shimokawa 2877ddbf617SHidetoshi Shimokawa static void 2887f1b527cSSean Bruno link_on(int fd, int node) 289d1f7bcb5SHidetoshi Shimokawa { 290d1f7bcb5SHidetoshi Shimokawa struct fw_asyreq *asyreq; 291d1f7bcb5SHidetoshi Shimokawa 292*9494dfe1SJohn Baldwin asyreq = malloc(sizeof(*asyreq)); 2937f1b527cSSean Bruno if (asyreq == NULL) 2947f1b527cSSean Bruno err(EX_SOFTWARE, "%s:asyreq malloc", __func__); 295d1f7bcb5SHidetoshi Shimokawa asyreq->req.len = 12; 296d1f7bcb5SHidetoshi Shimokawa asyreq->req.type = FWASREQNODE; 297d1f7bcb5SHidetoshi Shimokawa asyreq->pkt.mode.common.tcode = FWTCODE_PHY; 298d1f7bcb5SHidetoshi Shimokawa asyreq->pkt.mode.ld[1] |= (1 << 30) | ((node & 0x3f) << 24); 299d1f7bcb5SHidetoshi Shimokawa asyreq->pkt.mode.ld[2] = ~asyreq->pkt.mode.ld[1]; 300d1f7bcb5SHidetoshi Shimokawa 3015193feb6SHidetoshi Shimokawa if (ioctl(fd, FW_ASYREQ, asyreq) < 0) 3027f1b527cSSean Bruno err(EX_IOERR, "%s: ioctl", __func__); 3035193feb6SHidetoshi Shimokawa free(asyreq); 304d1f7bcb5SHidetoshi Shimokawa } 305d1f7bcb5SHidetoshi Shimokawa 306d1f7bcb5SHidetoshi Shimokawa static void 307d1f7bcb5SHidetoshi Shimokawa reset_start(int fd, int node) 308d1f7bcb5SHidetoshi Shimokawa { 309d1f7bcb5SHidetoshi Shimokawa struct fw_asyreq *asyreq; 310d1f7bcb5SHidetoshi Shimokawa 311*9494dfe1SJohn Baldwin asyreq = malloc(sizeof(*asyreq)); 3127f1b527cSSean Bruno if (asyreq == NULL) 3137f1b527cSSean Bruno err(EX_SOFTWARE, "%s:asyreq malloc", __func__); 314d1f7bcb5SHidetoshi Shimokawa asyreq->req.len = 16; 315d1f7bcb5SHidetoshi Shimokawa asyreq->req.type = FWASREQNODE; 316d1f7bcb5SHidetoshi Shimokawa asyreq->pkt.mode.wreqq.dst = FWLOCALBUS | (node & 0x3f); 317d1f7bcb5SHidetoshi Shimokawa asyreq->pkt.mode.wreqq.tlrt = 0; 318d1f7bcb5SHidetoshi Shimokawa asyreq->pkt.mode.wreqq.tcode = FWTCODE_WREQQ; 319d1f7bcb5SHidetoshi Shimokawa 320d1f7bcb5SHidetoshi Shimokawa asyreq->pkt.mode.wreqq.dest_hi = 0xffff; 321d1f7bcb5SHidetoshi Shimokawa asyreq->pkt.mode.wreqq.dest_lo = 0xf0000000 | RESET_START; 322d1f7bcb5SHidetoshi Shimokawa 323d1f7bcb5SHidetoshi Shimokawa asyreq->pkt.mode.wreqq.data = htonl(0x1); 324d1f7bcb5SHidetoshi Shimokawa 3255193feb6SHidetoshi Shimokawa if (ioctl(fd, FW_ASYREQ, asyreq) < 0) 3267f1b527cSSean Bruno err(EX_IOERR, "%s: ioctl", __func__); 3275193feb6SHidetoshi Shimokawa free(asyreq); 328d1f7bcb5SHidetoshi Shimokawa } 329d1f7bcb5SHidetoshi Shimokawa 330d1f7bcb5SHidetoshi Shimokawa static void 3316d815a7dSWarner Losh set_pri_req(int fd, u_int32_t pri_req) 332a7a73b95SHidetoshi Shimokawa { 333c547b896SHidetoshi Shimokawa struct fw_devlstreq *data; 334c547b896SHidetoshi Shimokawa struct fw_devinfo *devinfo; 335cb5df0b2SBrooks Davis struct eui64 eui; 336cb5df0b2SBrooks Davis char addr[EUI64_SIZ]; 337a7a73b95SHidetoshi Shimokawa u_int32_t max, reg, old; 338a7a73b95SHidetoshi Shimokawa int i; 339a7a73b95SHidetoshi Shimokawa 3407f1b527cSSean Bruno data = (struct fw_devlstreq *)malloc(sizeof(struct fw_devlstreq)); 3417f1b527cSSean Bruno if (data == NULL) 3427f1b527cSSean Bruno err(EX_SOFTWARE, "%s:data malloc", __func__); 3437f1b527cSSean Bruno get_dev(fd, data); 344a7a73b95SHidetoshi Shimokawa #define BUGET_REG 0xf0000218 345c547b896SHidetoshi Shimokawa for (i = 0; i < data->info_len; i++) { 346c547b896SHidetoshi Shimokawa devinfo = &data->dev[i]; 347c547b896SHidetoshi Shimokawa if (!devinfo->status) 348a7a73b95SHidetoshi Shimokawa continue; 349c547b896SHidetoshi Shimokawa reg = read_write_quad(fd, devinfo->eui, BUGET_REG, 1, 0); 350cb5df0b2SBrooks Davis fweui2eui64(&devinfo->eui, &eui); 351cb5df0b2SBrooks Davis eui64_ntoa(&eui, addr, sizeof(addr)); 352cb5df0b2SBrooks Davis printf("%d %s, %08x", 353cb5df0b2SBrooks Davis devinfo->dst, addr, reg); 3546d815a7dSWarner Losh if (reg > 0) { 355a7a73b95SHidetoshi Shimokawa old = (reg & 0x3f); 356a7a73b95SHidetoshi Shimokawa max = (reg & 0x3f00) >> 8; 357a7a73b95SHidetoshi Shimokawa if (pri_req > max) 358a7a73b95SHidetoshi Shimokawa pri_req = max; 359a7a73b95SHidetoshi Shimokawa printf(" 0x%x -> 0x%x\n", old, pri_req); 360c547b896SHidetoshi Shimokawa read_write_quad(fd, devinfo->eui, BUGET_REG, 0, pri_req); 361a7a73b95SHidetoshi Shimokawa } else { 362a7a73b95SHidetoshi Shimokawa printf("\n"); 363a7a73b95SHidetoshi Shimokawa } 364a7a73b95SHidetoshi Shimokawa } 365c547b896SHidetoshi Shimokawa free((void *)data); 366a7a73b95SHidetoshi Shimokawa } 367a7a73b95SHidetoshi Shimokawa 3687ddbf617SHidetoshi Shimokawa static void 3696d815a7dSWarner Losh parse_bus_info_block(u_int32_t *p) 370a7a73b95SHidetoshi Shimokawa { 371cb5df0b2SBrooks Davis char addr[EUI64_SIZ]; 372c6747f0fSHidetoshi Shimokawa struct bus_info *bi; 373cb5df0b2SBrooks Davis struct eui64 eui; 374a7a73b95SHidetoshi Shimokawa 375c6747f0fSHidetoshi Shimokawa bi = (struct bus_info *)p; 376cb5df0b2SBrooks Davis fweui2eui64(&bi->eui64, &eui); 377cb5df0b2SBrooks Davis eui64_ntoa(&eui, addr, sizeof(addr)); 378c6747f0fSHidetoshi Shimokawa printf("bus_name: 0x%04x\n" 379c6747f0fSHidetoshi Shimokawa "irmc:%d cmc:%d isc:%d bmc:%d pmc:%d\n" 380c6747f0fSHidetoshi Shimokawa "cyc_clk_acc:%d max_rec:%d max_rom:%d\n" 381c6747f0fSHidetoshi Shimokawa "generation:%d link_spd:%d\n" 382cb5df0b2SBrooks Davis "EUI64: %s\n", 383c6747f0fSHidetoshi Shimokawa bi->bus_name, 384c6747f0fSHidetoshi Shimokawa bi->irmc, bi->cmc, bi->isc, bi->bmc, bi->pmc, 385c6747f0fSHidetoshi Shimokawa bi->cyc_clk_acc, bi->max_rec, bi->max_rom, 386c6747f0fSHidetoshi Shimokawa bi->generation, bi->link_spd, 387cb5df0b2SBrooks Davis addr); 388a7a73b95SHidetoshi Shimokawa } 389a7a73b95SHidetoshi Shimokawa 3907ddbf617SHidetoshi Shimokawa static int 391a7a73b95SHidetoshi Shimokawa get_crom(int fd, int node, void *crom_buf, int len) 392a7a73b95SHidetoshi Shimokawa { 393a7a73b95SHidetoshi Shimokawa struct fw_crom_buf buf; 394013490c5SHidetoshi Shimokawa int i, error; 395c547b896SHidetoshi Shimokawa struct fw_devlstreq *data; 396a7a73b95SHidetoshi Shimokawa 3977f1b527cSSean Bruno data = (struct fw_devlstreq *)malloc(sizeof(struct fw_devlstreq)); 3987f1b527cSSean Bruno if (data == NULL) 3997f1b527cSSean Bruno err(EX_SOFTWARE, "%s:data malloc", __func__); 4007f1b527cSSean Bruno get_dev(fd, data); 401a7a73b95SHidetoshi Shimokawa 402c547b896SHidetoshi Shimokawa for (i = 0; i < data->info_len; i++) { 403c547b896SHidetoshi Shimokawa if (data->dev[i].dst == node && data->dev[i].eui.lo != 0) 404a7a73b95SHidetoshi Shimokawa break; 405a7a73b95SHidetoshi Shimokawa } 406c547b896SHidetoshi Shimokawa if (i == data->info_len) 407c547b896SHidetoshi Shimokawa errx(1, "no such node %d.", node); 408c547b896SHidetoshi Shimokawa else 409c547b896SHidetoshi Shimokawa buf.eui = data->dev[i].eui; 410c547b896SHidetoshi Shimokawa free((void *)data); 411a7a73b95SHidetoshi Shimokawa 412a7a73b95SHidetoshi Shimokawa buf.len = len; 413a7a73b95SHidetoshi Shimokawa buf.ptr = crom_buf; 414cf00a0daSHidetoshi Shimokawa bzero(crom_buf, len); 415a7a73b95SHidetoshi Shimokawa if ((error = ioctl(fd, FW_GCROM, &buf)) < 0) { 4167f1b527cSSean Bruno err(EX_IOERR, "%s: ioctl", __func__); 417a7a73b95SHidetoshi Shimokawa } 418c547b896SHidetoshi Shimokawa 419a7a73b95SHidetoshi Shimokawa return error; 420a7a73b95SHidetoshi Shimokawa } 421a7a73b95SHidetoshi Shimokawa 4227ddbf617SHidetoshi Shimokawa static void 423a7a73b95SHidetoshi Shimokawa show_crom(u_int32_t *crom_buf) 424a7a73b95SHidetoshi Shimokawa { 425a7a73b95SHidetoshi Shimokawa int i; 426a7a73b95SHidetoshi Shimokawa struct crom_context cc; 427a7a73b95SHidetoshi Shimokawa char *desc, info[256]; 4283fe9d89aSPhilippe Charnier static const char *key_types = "ICLD"; 429a7a73b95SHidetoshi Shimokawa struct csrreg *reg; 430a7a73b95SHidetoshi Shimokawa struct csrdirectory *dir; 431a7a73b95SHidetoshi Shimokawa struct csrhdr *hdr; 43277ee030bSHidetoshi Shimokawa u_int16_t crc; 433a7a73b95SHidetoshi Shimokawa 43477ee030bSHidetoshi Shimokawa printf("first quad: 0x%08x ", *crom_buf); 4351be7387cSHidetoshi Shimokawa if (crom_buf[0] == 0) { 4361be7387cSHidetoshi Shimokawa printf("(Invalid Configuration ROM)\n"); 4371be7387cSHidetoshi Shimokawa return; 4381be7387cSHidetoshi Shimokawa } 439a7a73b95SHidetoshi Shimokawa hdr = (struct csrhdr *)crom_buf; 440a7a73b95SHidetoshi Shimokawa if (hdr->info_len == 1) { 441a7a73b95SHidetoshi Shimokawa /* minimum ROM */ 442a7a73b95SHidetoshi Shimokawa reg = (struct csrreg *)hdr; 443a7a73b95SHidetoshi Shimokawa printf("verndor ID: 0x%06x\n", reg->val); 444a7a73b95SHidetoshi Shimokawa return; 445a7a73b95SHidetoshi Shimokawa } 44677ee030bSHidetoshi Shimokawa printf("info_len=%d crc_len=%d crc=0x%04x", 44777ee030bSHidetoshi Shimokawa hdr->info_len, hdr->crc_len, hdr->crc); 44877ee030bSHidetoshi Shimokawa crc = crom_crc(crom_buf+1, hdr->crc_len); 44977ee030bSHidetoshi Shimokawa if (crc == hdr->crc) 45077ee030bSHidetoshi Shimokawa printf("(OK)\n"); 45177ee030bSHidetoshi Shimokawa else 45277ee030bSHidetoshi Shimokawa printf("(NG)\n"); 4536d815a7dSWarner Losh parse_bus_info_block(crom_buf+1); 454a7a73b95SHidetoshi Shimokawa 455a7a73b95SHidetoshi Shimokawa crom_init_context(&cc, crom_buf); 456a7a73b95SHidetoshi Shimokawa dir = cc.stack[0].dir; 4573d7b1b41SDoug Rabson if (!dir) { 4583d7b1b41SDoug Rabson printf("no root directory - giving up\n"); 4593d7b1b41SDoug Rabson return; 4603d7b1b41SDoug Rabson } 46177ee030bSHidetoshi Shimokawa printf("root_directory: len=0x%04x(%d) crc=0x%04x", 462a7a73b95SHidetoshi Shimokawa dir->crc_len, dir->crc_len, dir->crc); 46377ee030bSHidetoshi Shimokawa crc = crom_crc((u_int32_t *)&dir->entry[0], dir->crc_len); 46477ee030bSHidetoshi Shimokawa if (crc == dir->crc) 46577ee030bSHidetoshi Shimokawa printf("(OK)\n"); 46677ee030bSHidetoshi Shimokawa else 46777ee030bSHidetoshi Shimokawa printf("(NG)\n"); 4687ddbf617SHidetoshi Shimokawa if (dir->crc_len < 1) 4697ddbf617SHidetoshi Shimokawa return; 470a7a73b95SHidetoshi Shimokawa while (cc.depth >= 0) { 471a7a73b95SHidetoshi Shimokawa desc = crom_desc(&cc, info, sizeof(info)); 472a7a73b95SHidetoshi Shimokawa reg = crom_get(&cc); 473a7a73b95SHidetoshi Shimokawa for (i = 0; i < cc.depth; i++) 474a7a73b95SHidetoshi Shimokawa printf("\t"); 475a7a73b95SHidetoshi Shimokawa printf("%02x(%c:%02x) %06x %s: %s\n", 476a7a73b95SHidetoshi Shimokawa reg->key, 477a7a73b95SHidetoshi Shimokawa key_types[(reg->key & CSRTYPE_MASK)>>6], 478a7a73b95SHidetoshi Shimokawa reg->key & CSRKEY_MASK, reg->val, 479a7a73b95SHidetoshi Shimokawa desc, info); 480a7a73b95SHidetoshi Shimokawa crom_next(&cc); 481a7a73b95SHidetoshi Shimokawa } 482a7a73b95SHidetoshi Shimokawa } 483a7a73b95SHidetoshi Shimokawa 484a7a73b95SHidetoshi Shimokawa #define DUMP_FORMAT "%08x %08x %08x %08x %08x %08x %08x %08x\n" 485a7a73b95SHidetoshi Shimokawa 4867ddbf617SHidetoshi Shimokawa static void 487a7a73b95SHidetoshi Shimokawa dump_crom(u_int32_t *p) 488a7a73b95SHidetoshi Shimokawa { 489a7a73b95SHidetoshi Shimokawa int len=1024, i; 490a7a73b95SHidetoshi Shimokawa 491a7a73b95SHidetoshi Shimokawa for (i = 0; i < len/(4*8); i ++) { 492a7a73b95SHidetoshi Shimokawa printf(DUMP_FORMAT, 493a7a73b95SHidetoshi Shimokawa p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); 494a7a73b95SHidetoshi Shimokawa p += 8; 495a7a73b95SHidetoshi Shimokawa } 496a7a73b95SHidetoshi Shimokawa } 497a7a73b95SHidetoshi Shimokawa 4987ddbf617SHidetoshi Shimokawa static void 499a7a73b95SHidetoshi Shimokawa load_crom(char *filename, u_int32_t *p) 500a7a73b95SHidetoshi Shimokawa { 501a7a73b95SHidetoshi Shimokawa FILE *file; 502a7a73b95SHidetoshi Shimokawa int len=1024, i; 503a7a73b95SHidetoshi Shimokawa 504a7a73b95SHidetoshi Shimokawa if ((file = fopen(filename, "r")) == NULL) 505c1de48a3SSean Bruno err(1, "load_crom %s", filename); 506a7a73b95SHidetoshi Shimokawa for (i = 0; i < len/(4*8); i ++) { 507a7a73b95SHidetoshi Shimokawa fscanf(file, DUMP_FORMAT, 508a7a73b95SHidetoshi Shimokawa p, p+1, p+2, p+3, p+4, p+5, p+6, p+7); 509a7a73b95SHidetoshi Shimokawa p += 8; 510a7a73b95SHidetoshi Shimokawa } 511f55df2a2SKevin Lo fclose(file); 512a7a73b95SHidetoshi Shimokawa } 513a7a73b95SHidetoshi Shimokawa 514a7a73b95SHidetoshi Shimokawa static void 515a7a73b95SHidetoshi Shimokawa show_topology_map(int fd) 516a7a73b95SHidetoshi Shimokawa { 517a7a73b95SHidetoshi Shimokawa struct fw_topology_map *tmap; 518a7a73b95SHidetoshi Shimokawa union fw_self_id sid; 519a7a73b95SHidetoshi Shimokawa int i; 5203fe9d89aSPhilippe Charnier static const char *port_status[] = {" ", "-", "P", "C"}; 5213fe9d89aSPhilippe Charnier static const char *pwr_class[] = {" 0W", "15W", "30W", "45W", 522a7a73b95SHidetoshi Shimokawa "-1W", "-2W", "-5W", "-9W"}; 5233fe9d89aSPhilippe Charnier static const char *speed[] = {"S100", "S200", "S400", "S800"}; 524a7a73b95SHidetoshi Shimokawa tmap = malloc(sizeof(struct fw_topology_map)); 525a7a73b95SHidetoshi Shimokawa if (tmap == NULL) 5267f1b527cSSean Bruno err(EX_SOFTWARE, "%s:tmap malloc", __func__); 527a7a73b95SHidetoshi Shimokawa if (ioctl(fd, FW_GTPMAP, tmap) < 0) { 5287f1b527cSSean Bruno err(EX_IOERR, "%s: ioctl", __func__); 529a7a73b95SHidetoshi Shimokawa } 530a7a73b95SHidetoshi Shimokawa printf("crc_len: %d generation:%d node_count:%d sid_count:%d\n", 531a7a73b95SHidetoshi Shimokawa tmap->crc_len, tmap->generation, 532a7a73b95SHidetoshi Shimokawa tmap->node_count, tmap->self_id_count); 533a7a73b95SHidetoshi Shimokawa printf("id link gap_cnt speed delay cIRM power port0 port1 port2" 534a7a73b95SHidetoshi Shimokawa " ini more\n"); 535a7a73b95SHidetoshi Shimokawa for (i = 0; i < tmap->crc_len - 2; i++) { 536a7a73b95SHidetoshi Shimokawa sid = tmap->self_id[i]; 537a7a73b95SHidetoshi Shimokawa if (sid.p0.sequel) { 538a7a73b95SHidetoshi Shimokawa printf("%02d sequel packet\n", sid.p0.phy_id); 539a7a73b95SHidetoshi Shimokawa continue; 540a7a73b95SHidetoshi Shimokawa } 541cde9186fSSean Bruno printf("%02d %2d %2d %4s %d %3s" 542a7a73b95SHidetoshi Shimokawa " %s %s %s %d %d\n", 543a7a73b95SHidetoshi Shimokawa sid.p0.phy_id, 544a7a73b95SHidetoshi Shimokawa sid.p0.link_active, 545a7a73b95SHidetoshi Shimokawa sid.p0.gap_count, 546a7a73b95SHidetoshi Shimokawa speed[sid.p0.phy_speed], 547a7a73b95SHidetoshi Shimokawa sid.p0.contender, 548a7a73b95SHidetoshi Shimokawa pwr_class[sid.p0.power_class], 549a7a73b95SHidetoshi Shimokawa port_status[sid.p0.port0], 550a7a73b95SHidetoshi Shimokawa port_status[sid.p0.port1], 551a7a73b95SHidetoshi Shimokawa port_status[sid.p0.port2], 552a7a73b95SHidetoshi Shimokawa sid.p0.initiated_reset, 553a7a73b95SHidetoshi Shimokawa sid.p0.more_packets 554a7a73b95SHidetoshi Shimokawa ); 555a7a73b95SHidetoshi Shimokawa } 556a7a73b95SHidetoshi Shimokawa free(tmap); 557a7a73b95SHidetoshi Shimokawa } 558a7a73b95SHidetoshi Shimokawa 559abd538f2SHidetoshi Shimokawa static void 560a8587980SHidetoshi Shimokawa read_phy_registers(int fd, u_int8_t *buf, int offset, int len) 561a8587980SHidetoshi Shimokawa { 562a8587980SHidetoshi Shimokawa struct fw_reg_req_t reg; 563a8587980SHidetoshi Shimokawa int i; 564a8587980SHidetoshi Shimokawa 565a8587980SHidetoshi Shimokawa for (i = 0; i < len; i++) { 566a8587980SHidetoshi Shimokawa reg.addr = offset + i; 567a8587980SHidetoshi Shimokawa if (ioctl(fd, FWOHCI_RDPHYREG, ®) < 0) 5687f1b527cSSean Bruno err(EX_IOERR, "%s: ioctl", __func__); 569a8587980SHidetoshi Shimokawa buf[i] = (u_int8_t) reg.data; 570a8587980SHidetoshi Shimokawa printf("0x%02x ", reg.data); 571a8587980SHidetoshi Shimokawa } 572a8587980SHidetoshi Shimokawa printf("\n"); 573a8587980SHidetoshi Shimokawa } 574a8587980SHidetoshi Shimokawa 575a8587980SHidetoshi Shimokawa static void 576a8587980SHidetoshi Shimokawa read_phy_page(int fd, u_int8_t *buf, int page, int port) 577a8587980SHidetoshi Shimokawa { 578a8587980SHidetoshi Shimokawa struct fw_reg_req_t reg; 579a8587980SHidetoshi Shimokawa 580a8587980SHidetoshi Shimokawa reg.addr = 0x7; 581a8587980SHidetoshi Shimokawa reg.data = ((page & 7) << 5) | (port & 0xf); 582a8587980SHidetoshi Shimokawa if (ioctl(fd, FWOHCI_WRPHYREG, ®) < 0) 5837f1b527cSSean Bruno err(EX_IOERR, "%s: ioctl", __func__); 584a8587980SHidetoshi Shimokawa read_phy_registers(fd, buf, 8, 8); 585a8587980SHidetoshi Shimokawa } 586a8587980SHidetoshi Shimokawa 587a8587980SHidetoshi Shimokawa static void 588a8587980SHidetoshi Shimokawa dump_phy_registers(int fd) 589a8587980SHidetoshi Shimokawa { 590a8587980SHidetoshi Shimokawa struct phyreg_base b; 591a8587980SHidetoshi Shimokawa struct phyreg_page0 p; 592a8587980SHidetoshi Shimokawa struct phyreg_page1 v; 593a8587980SHidetoshi Shimokawa int i; 594a8587980SHidetoshi Shimokawa 595a8587980SHidetoshi Shimokawa printf("=== base register ===\n"); 596a8587980SHidetoshi Shimokawa read_phy_registers(fd, (u_int8_t *)&b, 0, 8); 597a8587980SHidetoshi Shimokawa printf( 598a8587980SHidetoshi Shimokawa "Physical_ID:%d R:%d CPS:%d\n" 599a8587980SHidetoshi Shimokawa "RHB:%d IBR:%d Gap_Count:%d\n" 600a8587980SHidetoshi Shimokawa "Extended:%d Num_Ports:%d\n" 601a8587980SHidetoshi Shimokawa "PHY_Speed:%d Delay:%d\n" 602a8587980SHidetoshi Shimokawa "LCtrl:%d C:%d Jitter:%d Pwr_Class:%d\n" 603a8587980SHidetoshi Shimokawa "WDIE:%d ISBR:%d CTOI:%d CPSI:%d STOI:%d PEI:%d EAA:%d EMC:%d\n" 604a8587980SHidetoshi Shimokawa "Max_Legacy_SPD:%d BLINK:%d Bridge:%d\n" 605a8587980SHidetoshi Shimokawa "Page_Select:%d Port_Select%d\n", 606a8587980SHidetoshi Shimokawa b.phy_id, b.r, b.cps, 607a8587980SHidetoshi Shimokawa b.rhb, b.ibr, b.gap_count, 608a8587980SHidetoshi Shimokawa b.extended, b.num_ports, 609a8587980SHidetoshi Shimokawa b.phy_speed, b.delay, 610a8587980SHidetoshi Shimokawa b.lctrl, b.c, b.jitter, b.pwr_class, 611a8587980SHidetoshi Shimokawa b.wdie, b.isbr, b.ctoi, b.cpsi, b.stoi, b.pei, b.eaa, b.emc, 612a8587980SHidetoshi Shimokawa b.legacy_spd, b.blink, b.bridge, 613a8587980SHidetoshi Shimokawa b.page_select, b.port_select 614a8587980SHidetoshi Shimokawa ); 615a8587980SHidetoshi Shimokawa 616a8587980SHidetoshi Shimokawa for (i = 0; i < b.num_ports; i ++) { 617a8587980SHidetoshi Shimokawa printf("\n=== page 0 port %d ===\n", i); 618a8587980SHidetoshi Shimokawa read_phy_page(fd, (u_int8_t *)&p, 0, i); 619a8587980SHidetoshi Shimokawa printf( 620a8587980SHidetoshi Shimokawa "Astat:%d BStat:%d Ch:%d Con:%d RXOK:%d Dis:%d\n" 621a8587980SHidetoshi Shimokawa "Negotiated_speed:%d PIE:%d Fault:%d Stanby_fault:%d Disscrm:%d B_Only:%d\n" 622a8587980SHidetoshi Shimokawa "DC_connected:%d Max_port_speed:%d LPP:%d Cable_speed:%d\n" 623a8587980SHidetoshi Shimokawa "Connection_unreliable:%d Beta_mode:%d\n" 624a8587980SHidetoshi Shimokawa "Port_error:0x%x\n" 625a8587980SHidetoshi Shimokawa "Loop_disable:%d In_standby:%d Hard_disable:%d\n", 626a8587980SHidetoshi Shimokawa p.astat, p.bstat, p.ch, p.con, p.rxok, p.dis, 627a8587980SHidetoshi Shimokawa p.negotiated_speed, p.pie, p.fault, p.stanby_fault, p.disscrm, p.b_only, 628a8587980SHidetoshi Shimokawa p.dc_connected, p.max_port_speed, p.lpp, p.cable_speed, 629a8587980SHidetoshi Shimokawa p.connection_unreliable, p.beta_mode, 630a8587980SHidetoshi Shimokawa p.port_error, 631a8587980SHidetoshi Shimokawa p.loop_disable, p.in_standby, p.hard_disable 632a8587980SHidetoshi Shimokawa ); 633a8587980SHidetoshi Shimokawa } 634a8587980SHidetoshi Shimokawa printf("\n=== page 1 ===\n"); 635a8587980SHidetoshi Shimokawa read_phy_page(fd, (u_int8_t *)&v, 1, 0); 636a8587980SHidetoshi Shimokawa printf( 637a8587980SHidetoshi Shimokawa "Compliance:%d\n" 638a8587980SHidetoshi Shimokawa "Vendor_ID:0x%06x\n" 639a8587980SHidetoshi Shimokawa "Product_ID:0x%06x\n", 640a8587980SHidetoshi Shimokawa v.compliance, 641a8587980SHidetoshi Shimokawa (v.vendor_id[0] << 16) | (v.vendor_id[1] << 8) | v.vendor_id[2], 642a8587980SHidetoshi Shimokawa (v.product_id[0] << 16) | (v.product_id[1] << 8) | v.product_id[2] 643a8587980SHidetoshi Shimokawa ); 644a8587980SHidetoshi Shimokawa } 645a8587980SHidetoshi Shimokawa 6467f1b527cSSean Bruno static int 6477f1b527cSSean Bruno open_dev(int *fd, char *devname) 648abd538f2SHidetoshi Shimokawa { 649abd538f2SHidetoshi Shimokawa if (*fd < 0) { 6507f1b527cSSean Bruno *fd = open(devname, O_RDWR); 651abd538f2SHidetoshi Shimokawa if (*fd < 0) 6527f1b527cSSean Bruno return(-1); 653abd538f2SHidetoshi Shimokawa 654abd538f2SHidetoshi Shimokawa } 6557f1b527cSSean Bruno return(0); 656abd538f2SHidetoshi Shimokawa } 657abd538f2SHidetoshi Shimokawa 6586d815a7dSWarner Losh static void 6593fe9d89aSPhilippe Charnier sysctl_set_int(const char *name, int val) 6601be7387cSHidetoshi Shimokawa { 6611be7387cSHidetoshi Shimokawa if (sysctlbyname(name, NULL, NULL, &val, sizeof(int)) < 0) 6621be7387cSHidetoshi Shimokawa err(1, "sysctl %s failed.", name); 6631be7387cSHidetoshi Shimokawa } 6641be7387cSHidetoshi Shimokawa 6656d815a7dSWarner Losh static fwmethod * 6666d815a7dSWarner Losh detect_recv_fn(int fd, char ich) 6676d815a7dSWarner Losh { 6686d815a7dSWarner Losh char *buf; 6696d815a7dSWarner Losh struct fw_isochreq isoreq; 6706d815a7dSWarner Losh struct fw_isobufreq bufreq; 6716d815a7dSWarner Losh int len; 6726d815a7dSWarner Losh u_int32_t *ptr; 6736d815a7dSWarner Losh struct ciphdr *ciph; 6746d815a7dSWarner Losh fwmethod *retfn; 6757f1b527cSSean Bruno #define RECV_NUM_PACKET 16 6767f1b527cSSean Bruno #define RECV_PACKET_SZ 1024 6776d815a7dSWarner Losh 6786d815a7dSWarner Losh bufreq.rx.nchunk = 8; 6797f1b527cSSean Bruno bufreq.rx.npacket = RECV_NUM_PACKET; 6807f1b527cSSean Bruno bufreq.rx.psize = RECV_PACKET_SZ; 6816d815a7dSWarner Losh bufreq.tx.nchunk = 0; 6826d815a7dSWarner Losh bufreq.tx.npacket = 0; 6836d815a7dSWarner Losh bufreq.tx.psize = 0; 6846d815a7dSWarner Losh 6856d815a7dSWarner Losh if (ioctl(fd, FW_SSTBUF, &bufreq) < 0) 6867f1b527cSSean Bruno err(EX_IOERR, "%s: ioctl FW_SSTBUF", __func__); 6876d815a7dSWarner Losh 6886d815a7dSWarner Losh isoreq.ch = ich & 0x3f; 6896d815a7dSWarner Losh isoreq.tag = (ich >> 6) & 3; 6906d815a7dSWarner Losh 6916d815a7dSWarner Losh if (ioctl(fd, FW_SRSTREAM, &isoreq) < 0) 6927f1b527cSSean Bruno err(EX_IOERR, "%s: ioctl FW_SRSTREAM", __func__); 6936d815a7dSWarner Losh 6947f1b527cSSean Bruno buf = (char *)malloc(RECV_NUM_PACKET * RECV_PACKET_SZ); 6957f1b527cSSean Bruno if (buf == NULL) 6967f1b527cSSean Bruno err(EX_SOFTWARE, "%s:buf malloc", __func__); 6977f1b527cSSean Bruno /* 6987f1b527cSSean Bruno * fwdev.c seems to return EIO on error and 6997f1b527cSSean Bruno * the return value of the last uiomove 7007f1b527cSSean Bruno * on success. For now, checking that the 7017f1b527cSSean Bruno * return is not less than zero should be 7027f1b527cSSean Bruno * sufficient. fwdev.c::fw_read() should 7037f1b527cSSean Bruno * return the total length read, not the value 7047f1b527cSSean Bruno * of the last uiomove(). 7057f1b527cSSean Bruno */ 7067f1b527cSSean Bruno len = read(fd, buf, RECV_NUM_PACKET * RECV_PACKET_SZ); 7077f1b527cSSean Bruno if (len < 0) 708c1de48a3SSean Bruno err(EX_IOERR, "%s: error reading from device", __func__); 7096d815a7dSWarner Losh ptr = (u_int32_t *) buf; 7106d815a7dSWarner Losh ciph = (struct ciphdr *)(ptr + 1); 7116d815a7dSWarner Losh 7126d815a7dSWarner Losh switch(ciph->fmt) { 7136d815a7dSWarner Losh case CIP_FMT_DVCR: 7146d815a7dSWarner Losh fprintf(stderr, "Detected DV format on input.\n"); 7156d815a7dSWarner Losh retfn = dvrecv; 7166d815a7dSWarner Losh break; 7176d815a7dSWarner Losh case CIP_FMT_MPEG: 7186d815a7dSWarner Losh fprintf(stderr, "Detected MPEG TS format on input.\n"); 7196d815a7dSWarner Losh retfn = mpegtsrecv; 7206d815a7dSWarner Losh break; 7216d815a7dSWarner Losh default: 7226d815a7dSWarner Losh errx(1, "Unsupported format for receiving: fmt=0x%x", ciph->fmt); 7236d815a7dSWarner Losh } 7246d815a7dSWarner Losh free(buf); 7256d815a7dSWarner Losh return retfn; 7266d815a7dSWarner Losh } 7276d815a7dSWarner Losh 7281be7387cSHidetoshi Shimokawa int 729a7a73b95SHidetoshi Shimokawa main(int argc, char **argv) 730a7a73b95SHidetoshi Shimokawa { 7317f1b527cSSean Bruno #define MAX_BOARDS 10 732a7a73b95SHidetoshi Shimokawa u_int32_t crom_buf[1024/4]; 7337f1b527cSSean Bruno u_int32_t crom_buf_hex[1024/4]; 7347f1b527cSSean Bruno char devbase[64]; 7357f1b527cSSean Bruno const char *device_string = "/dev/fw"; 7367f1b527cSSean Bruno int fd = -1, ch, len=1024; 7377f1b527cSSean Bruno int32_t current_board = 0; 7387f1b527cSSean Bruno /* 7397f1b527cSSean Bruno * If !command_set, then -u will display the nodes for the board. 7407f1b527cSSean Bruno * This emulates the previous behavior when -u is passed by itself 7417f1b527cSSean Bruno */ 7427f1b527cSSean Bruno bool command_set = false; 7437f1b527cSSean Bruno bool open_needed = false; 7446d815a7dSWarner Losh long tmp; 7451be7387cSHidetoshi Shimokawa struct fw_eui64 eui; 7461be7387cSHidetoshi Shimokawa struct eui64 target; 7476d815a7dSWarner Losh fwmethod *recvfn = NULL; 7487f1b527cSSean Bruno /* 7497f1b527cSSean Bruno * Holders for which functions 7507f1b527cSSean Bruno * to iterate through 7517f1b527cSSean Bruno */ 7527f1b527cSSean Bruno bool display_board_only = false; 7537f1b527cSSean Bruno bool display_crom = false; 7547f1b527cSSean Bruno bool send_bus_reset = false; 7557f1b527cSSean Bruno bool display_crom_hex = false; 7567f1b527cSSean Bruno bool load_crom_from_file = false; 7577f1b527cSSean Bruno bool set_fwmem_target = false; 7587f1b527cSSean Bruno bool dump_topology = false; 7597f1b527cSSean Bruno bool dump_phy_reg = false; 760a7a73b95SHidetoshi Shimokawa 7617f1b527cSSean Bruno int32_t priority_budget = -1; 7627f1b527cSSean Bruno int32_t set_root_node = -1; 7637f1b527cSSean Bruno int32_t set_gap_count = -1; 7647f1b527cSSean Bruno int32_t send_link_on = -1; 7657f1b527cSSean Bruno int32_t send_reset_start = -1; 7667f1b527cSSean Bruno 7677f1b527cSSean Bruno char *crom_string = NULL; 7687f1b527cSSean Bruno char *crom_string_hex = NULL; 7697f1b527cSSean Bruno char *recv_data = NULL; 7707f1b527cSSean Bruno char *send_data = NULL; 771a7a73b95SHidetoshi Shimokawa 772a7a73b95SHidetoshi Shimokawa if (argc < 2) { 7737f1b527cSSean Bruno for (current_board = 0; current_board < MAX_BOARDS; current_board++) { 774c1de48a3SSean Bruno snprintf(devbase, sizeof(devbase), "%s%d.0", device_string, current_board); 7757f1b527cSSean Bruno if (open_dev(&fd, devbase) < 0) { 7767f1b527cSSean Bruno if (current_board == 0) { 7777f1b527cSSean Bruno usage(); 778c1de48a3SSean Bruno err(EX_IOERR, "%s: Error opening firewire controller #%d %s", 779c1de48a3SSean Bruno __func__, current_board, devbase); 780a7a73b95SHidetoshi Shimokawa } 7817f1b527cSSean Bruno return(EIO); 7827f1b527cSSean Bruno } 7837f1b527cSSean Bruno list_dev(fd); 784abd538f2SHidetoshi Shimokawa close(fd); 785abd538f2SHidetoshi Shimokawa fd = -1; 786abd538f2SHidetoshi Shimokawa } 787abd538f2SHidetoshi Shimokawa } 7887f1b527cSSean Bruno /* 7897f1b527cSSean Bruno * Parse all command line options, then execute requested operations. 7907f1b527cSSean Bruno */ 7917f1b527cSSean Bruno while ((ch = getopt(argc, argv, "M:f:g:m:o:s:b:prtc:d:l:u:R:S:")) != -1) { 7927f1b527cSSean Bruno switch(ch) { 7937f1b527cSSean Bruno case 'b': 7947f1b527cSSean Bruno priority_budget = strtol(optarg, NULL, 0); 7957f1b527cSSean Bruno if (priority_budget < 0 || priority_budget > INT32_MAX) 796c1de48a3SSean Bruno errx(EX_USAGE, "%s: priority_budget out of range: %s", __func__, optarg); 7977f1b527cSSean Bruno command_set = true; 7987f1b527cSSean Bruno open_needed = true; 7997f1b527cSSean Bruno display_board_only = false; 800abd538f2SHidetoshi Shimokawa break; 8017f1b527cSSean Bruno case 'c': 8027f1b527cSSean Bruno crom_string = malloc(strlen(optarg)+1); 8037f1b527cSSean Bruno if (crom_string == NULL) 8047f1b527cSSean Bruno err(EX_SOFTWARE, "%s:crom_string malloc", __func__); 8057f1b527cSSean Bruno if ( (strtol(crom_string, NULL, 0) < 0) || strtol(crom_string, NULL, 0) > MAX_BOARDS) 806c1de48a3SSean Bruno errx(EX_USAGE, "%s:Invalid value for node", __func__); 8077f1b527cSSean Bruno strcpy(crom_string, optarg); 8087f1b527cSSean Bruno display_crom = 1; 8097f1b527cSSean Bruno open_needed = true; 8107f1b527cSSean Bruno command_set = true; 8117f1b527cSSean Bruno display_board_only = false; 8127f1b527cSSean Bruno break; 8137f1b527cSSean Bruno case 'd': 8147f1b527cSSean Bruno crom_string_hex = malloc(strlen(optarg)+1); 8157f1b527cSSean Bruno if (crom_string_hex == NULL) 8167f1b527cSSean Bruno err(EX_SOFTWARE, "%s:crom_string_hex malloc", __func__); 8177f1b527cSSean Bruno strcpy(crom_string_hex, optarg); 8187f1b527cSSean Bruno display_crom_hex = 1; 8197f1b527cSSean Bruno open_needed = true; 8207f1b527cSSean Bruno command_set = true; 8217f1b527cSSean Bruno display_board_only = false; 8227f1b527cSSean Bruno break; 8237f1b527cSSean Bruno case 'f': 8247f1b527cSSean Bruno #define MAX_PHY_CONFIG 0x3f 8257f1b527cSSean Bruno set_root_node = strtol(optarg, NULL, 0); 8267f1b527cSSean Bruno if ( (set_root_node < 0) || (set_root_node > MAX_PHY_CONFIG) ) 827c1de48a3SSean Bruno errx(EX_USAGE, "%s:set_root_node out of range", __func__); 8287f1b527cSSean Bruno open_needed = true; 8297f1b527cSSean Bruno command_set = true; 8307f1b527cSSean Bruno display_board_only = false; 8317f1b527cSSean Bruno break; 8327f1b527cSSean Bruno case 'g': 8337f1b527cSSean Bruno set_gap_count = strtol(optarg, NULL, 0); 8347f1b527cSSean Bruno if ( (set_gap_count < 0) || (set_gap_count > MAX_PHY_CONFIG) ) 835c1de48a3SSean Bruno errx(EX_USAGE, "%s:set_gap_count out of range", __func__); 8367f1b527cSSean Bruno open_needed = true; 8377f1b527cSSean Bruno command_set = true; 8387f1b527cSSean Bruno display_board_only = false; 8397f1b527cSSean Bruno break; 8407f1b527cSSean Bruno case 'l': 8417f1b527cSSean Bruno load_crom_from_file = 1; 8427f1b527cSSean Bruno load_crom(optarg, crom_buf); 8437f1b527cSSean Bruno command_set = true; 8447f1b527cSSean Bruno display_board_only = false; 8457f1b527cSSean Bruno break; 8467f1b527cSSean Bruno case 'm': 8477f1b527cSSean Bruno set_fwmem_target = 1; 8487f1b527cSSean Bruno open_needed = 0; 8497f1b527cSSean Bruno command_set = true; 8507f1b527cSSean Bruno display_board_only = false; 8517f1b527cSSean Bruno if (eui64_hostton(optarg, &target) != 0 && 8527f1b527cSSean Bruno eui64_aton(optarg, &target) != 0) 853c1de48a3SSean Bruno errx(EX_USAGE, "%s: invalid target: %s", __func__, optarg); 8547f1b527cSSean Bruno break; 8557f1b527cSSean Bruno case 'o': 8567f1b527cSSean Bruno send_link_on = str2node(fd, optarg); 857c1de48a3SSean Bruno if ( (send_link_on < 0) || (send_link_on > MAX_PHY_CONFIG) ) 858c1de48a3SSean Bruno errx(EX_USAGE, "%s: node out of range: %s\n",__func__, optarg); 8597f1b527cSSean Bruno open_needed = true; 8607f1b527cSSean Bruno command_set = true; 8617f1b527cSSean Bruno display_board_only = false; 8627f1b527cSSean Bruno break; 8637f1b527cSSean Bruno case 'p': 8647f1b527cSSean Bruno dump_phy_reg = 1; 8657f1b527cSSean Bruno open_needed = true; 8667f1b527cSSean Bruno command_set = true; 8677f1b527cSSean Bruno display_board_only = false; 8687f1b527cSSean Bruno break; 8697f1b527cSSean Bruno case 'r': 8707f1b527cSSean Bruno send_bus_reset = 1; 8717f1b527cSSean Bruno open_needed = true; 8727f1b527cSSean Bruno command_set = true; 8737f1b527cSSean Bruno display_board_only = false; 8747f1b527cSSean Bruno break; 8757f1b527cSSean Bruno case 's': 8767f1b527cSSean Bruno send_reset_start = str2node(fd, optarg); 877c1de48a3SSean Bruno if ( (send_reset_start < 0) || (send_reset_start > MAX_PHY_CONFIG) ) 878c1de48a3SSean Bruno errx(EX_USAGE, "%s: node out of range: %s\n", __func__, optarg); 8797f1b527cSSean Bruno open_needed = true; 8807f1b527cSSean Bruno command_set = true; 8817f1b527cSSean Bruno display_board_only = false; 8827f1b527cSSean Bruno break; 8837f1b527cSSean Bruno case 't': 8847f1b527cSSean Bruno dump_topology = 1; 8857f1b527cSSean Bruno open_needed = true; 8867f1b527cSSean Bruno command_set = true; 8877f1b527cSSean Bruno display_board_only = false; 8887f1b527cSSean Bruno break; 8897f1b527cSSean Bruno case 'u': 8907f1b527cSSean Bruno if(!command_set) 8917f1b527cSSean Bruno display_board_only = true; 8927f1b527cSSean Bruno current_board = strtol(optarg, NULL, 0); 8937f1b527cSSean Bruno open_needed = true; 8947f1b527cSSean Bruno break; 8956d815a7dSWarner Losh case 'M': 8966d815a7dSWarner Losh switch (optarg[0]) { 8976d815a7dSWarner Losh case 'm': 8986d815a7dSWarner Losh recvfn = mpegtsrecv; 8996d815a7dSWarner Losh break; 9006d815a7dSWarner Losh case 'd': 9016d815a7dSWarner Losh recvfn = dvrecv; 9026d815a7dSWarner Losh break; 9036d815a7dSWarner Losh default: 9046d815a7dSWarner Losh errx(EX_USAGE, "unrecognized method: %s", 9056d815a7dSWarner Losh optarg); 9066d815a7dSWarner Losh } 9077f1b527cSSean Bruno command_set = true; 9087f1b527cSSean Bruno display_board_only = false; 9096d815a7dSWarner Losh break; 910937bcaa8SHidetoshi Shimokawa case 'R': 9117f1b527cSSean Bruno recv_data = malloc(strlen(optarg)+1); 9127f1b527cSSean Bruno if (recv_data == NULL) 9137f1b527cSSean Bruno err(EX_SOFTWARE, "%s:recv_data malloc", __func__); 9147f1b527cSSean Bruno strcpy(recv_data, optarg); 9157f1b527cSSean Bruno open_needed = false; 9167f1b527cSSean Bruno command_set = true; 9177f1b527cSSean Bruno display_board_only = false; 918937bcaa8SHidetoshi Shimokawa break; 919937bcaa8SHidetoshi Shimokawa case 'S': 9207f1b527cSSean Bruno send_data = malloc(strlen(optarg)+1); 9217f1b527cSSean Bruno if (send_data == NULL) 9227f1b527cSSean Bruno err(EX_SOFTWARE, "%s:send_data malloc", __func__); 9237f1b527cSSean Bruno strcpy(send_data, optarg); 9247f1b527cSSean Bruno open_needed = true; 9257f1b527cSSean Bruno command_set = true; 9267f1b527cSSean Bruno display_board_only = false; 927937bcaa8SHidetoshi Shimokawa break; 928c1de48a3SSean Bruno case '?': 929a7a73b95SHidetoshi Shimokawa default: 930a7a73b95SHidetoshi Shimokawa usage(); 931c1de48a3SSean Bruno warnc(EINVAL, "%s: Unknown command line arguments", __func__); 9327f1b527cSSean Bruno return 0; 9337f1b527cSSean Bruno } 9347f1b527cSSean Bruno } /* end while */ 9357f1b527cSSean Bruno 9367f1b527cSSean Bruno /* 937c1de48a3SSean Bruno * Catch the error case when the user 938c1de48a3SSean Bruno * executes the command with non ''-'' 939c1de48a3SSean Bruno * delimited arguments. 940c1de48a3SSean Bruno * Generate the usage() display and exit. 941c1de48a3SSean Bruno */ 942c1de48a3SSean Bruno if (!command_set && !display_board_only) { 943c1de48a3SSean Bruno usage(); 944c1de48a3SSean Bruno warnc(EINVAL, "%s: Unknown command line arguments", __func__); 945c1de48a3SSean Bruno return 0; 946c1de48a3SSean Bruno } 947c1de48a3SSean Bruno 948c1de48a3SSean Bruno /* 9497f1b527cSSean Bruno * If -u <bus_number> is passed, execute 9507f1b527cSSean Bruno * command for that card only. 9517f1b527cSSean Bruno * 9527f1b527cSSean Bruno * If -u <bus_number> is not passed, execute 9537f1b527cSSean Bruno * command for card 0 only. 9547f1b527cSSean Bruno * 9557f1b527cSSean Bruno */ 9567f1b527cSSean Bruno if(open_needed){ 957c1de48a3SSean Bruno snprintf(devbase, sizeof(devbase), "%s%d.0", device_string, current_board); 9587f1b527cSSean Bruno if (open_dev(&fd, devbase) < 0) { 959c1de48a3SSean Bruno err(EX_IOERR, "%s: Error opening firewire controller #%d %s", __func__, current_board, devbase); 9607f1b527cSSean Bruno } 9617f1b527cSSean Bruno } 9627f1b527cSSean Bruno /* 9637f1b527cSSean Bruno * display the nodes on this board "-u" 9647f1b527cSSean Bruno * only 9657f1b527cSSean Bruno */ 9667f1b527cSSean Bruno if (display_board_only) 9677f1b527cSSean Bruno list_dev(fd); 9687f1b527cSSean Bruno 9697f1b527cSSean Bruno /* 9707f1b527cSSean Bruno * dump_phy_reg "-p" 9717f1b527cSSean Bruno */ 9727f1b527cSSean Bruno if (dump_phy_reg) 9737f1b527cSSean Bruno dump_phy_registers(fd); 9747f1b527cSSean Bruno 9757f1b527cSSean Bruno /* 9767f1b527cSSean Bruno * send a BUS_RESET Event "-r" 9777f1b527cSSean Bruno */ 9787f1b527cSSean Bruno if (send_bus_reset) { 9797f1b527cSSean Bruno if(ioctl(fd, FW_IBUSRST, &tmp) < 0) 980c1de48a3SSean Bruno err(EX_IOERR, "%s: Ioctl of bus reset failed for %s", __func__, devbase); 9817f1b527cSSean Bruno } 9827f1b527cSSean Bruno /* 9837f1b527cSSean Bruno * Print out the CROM for this node "-c" 9847f1b527cSSean Bruno */ 9857f1b527cSSean Bruno if (display_crom) { 9867f1b527cSSean Bruno tmp = str2node(fd, crom_string); 9877f1b527cSSean Bruno get_crom(fd, tmp, crom_buf, len); 9887f1b527cSSean Bruno show_crom(crom_buf); 9897f1b527cSSean Bruno free(crom_string); 9907f1b527cSSean Bruno } 9917f1b527cSSean Bruno /* 9927f1b527cSSean Bruno * Hex Dump the CROM for this node "-d" 9937f1b527cSSean Bruno */ 9947f1b527cSSean Bruno if (display_crom_hex) { 9957f1b527cSSean Bruno tmp = str2node(fd, crom_string_hex); 9967f1b527cSSean Bruno get_crom(fd, tmp, crom_buf_hex, len); 9977f1b527cSSean Bruno dump_crom(crom_buf_hex); 9987f1b527cSSean Bruno free(crom_string_hex); 9997f1b527cSSean Bruno } 10007f1b527cSSean Bruno /* 10017f1b527cSSean Bruno * Set Priority Budget to value for this node "-b" 10027f1b527cSSean Bruno */ 10037f1b527cSSean Bruno if (priority_budget >= 0) 10047f1b527cSSean Bruno set_pri_req(fd, priority_budget); 10057f1b527cSSean Bruno 10067f1b527cSSean Bruno /* 10077f1b527cSSean Bruno * Explicitly set the root node of this bus to value "-f" 10087f1b527cSSean Bruno */ 10097f1b527cSSean Bruno if (set_root_node >= 0) 10107f1b527cSSean Bruno send_phy_config(fd, set_root_node, -1); 10117f1b527cSSean Bruno 10127f1b527cSSean Bruno /* 10137f1b527cSSean Bruno * Set the gap count for this card/bus "-g" 10147f1b527cSSean Bruno */ 10157f1b527cSSean Bruno if (set_gap_count >= 0) 10167f1b527cSSean Bruno send_phy_config(fd, -1, set_gap_count); 10177f1b527cSSean Bruno 10187f1b527cSSean Bruno /* 10197f1b527cSSean Bruno * Load a CROM from a file "-l" 10207f1b527cSSean Bruno */ 10217f1b527cSSean Bruno if (load_crom_from_file) 10227f1b527cSSean Bruno show_crom(crom_buf); 10237f1b527cSSean Bruno /* 10247f1b527cSSean Bruno * Set the fwmem target for a node to argument "-m" 10257f1b527cSSean Bruno */ 10267f1b527cSSean Bruno if (set_fwmem_target) { 10277f1b527cSSean Bruno eui.hi = ntohl(*(u_int32_t*)&(target.octet[0])); 10287f1b527cSSean Bruno eui.lo = ntohl(*(u_int32_t*)&(target.octet[4])); 1029c1de48a3SSean Bruno #if defined(__FreeBSD__) 10307f1b527cSSean Bruno sysctl_set_int("hw.firewire.fwmem.eui64_hi", eui.hi); 10317f1b527cSSean Bruno sysctl_set_int("hw.firewire.fwmem.eui64_lo", eui.lo); 1032c1de48a3SSean Bruno #elif defined(__NetBSD__) 1033c1de48a3SSean Bruno sysctl_set_int("hw.fwmem.eui64_hi", eui.hi); 1034c1de48a3SSean Bruno sysctl_set_int("hw.fwmem.eui64_lo", eui.lo); 1035c1de48a3SSean Bruno #else 1036c1de48a3SSean Bruno #warning "You need to add support for your OS" 1037c1de48a3SSean Bruno #endif 1038c1de48a3SSean Bruno 10397f1b527cSSean Bruno } 10407f1b527cSSean Bruno 10417f1b527cSSean Bruno /* 10427f1b527cSSean Bruno * Send a link on to this board/bus "-o" 10437f1b527cSSean Bruno */ 10447f1b527cSSean Bruno if (send_link_on >= 0) 10457f1b527cSSean Bruno link_on(fd, send_link_on); 10467f1b527cSSean Bruno 10477f1b527cSSean Bruno /* 10487f1b527cSSean Bruno * Send a reset start to this board/bus "-s" 10497f1b527cSSean Bruno */ 10507f1b527cSSean Bruno if (send_reset_start >= 0) 10517f1b527cSSean Bruno reset_start(fd, send_reset_start); 10527f1b527cSSean Bruno 10537f1b527cSSean Bruno /* 10547f1b527cSSean Bruno * Dump the node topology for this board/bus "-t" 10557f1b527cSSean Bruno */ 10567f1b527cSSean Bruno if (dump_topology) 10577f1b527cSSean Bruno show_topology_map(fd); 10587f1b527cSSean Bruno 10597f1b527cSSean Bruno /* 10603df5ecacSUlrich Spörlein * Receive data file from node "-R" 10617f1b527cSSean Bruno */ 10627f1b527cSSean Bruno #define TAG (1<<6) 10637f1b527cSSean Bruno #define CHANNEL 63 10647f1b527cSSean Bruno if (recv_data != NULL){ 10657f1b527cSSean Bruno if (recvfn == NULL) { /* guess... */ 10667f1b527cSSean Bruno recvfn = detect_recv_fn(fd, TAG | CHANNEL); 10677f1b527cSSean Bruno close(fd); 106896747dc0SWarner Losh fd = -1; 10697f1b527cSSean Bruno } 1070c1de48a3SSean Bruno snprintf(devbase, sizeof(devbase), "%s%d.0", device_string, current_board); 10717f1b527cSSean Bruno if (open_dev(&fd, devbase) < 0) 1072c1de48a3SSean Bruno err(EX_IOERR, "%s: Error opening firewire controller #%d %s in recv_data\n", __func__, current_board, devbase); 10737f1b527cSSean Bruno (*recvfn)(fd, recv_data, TAG | CHANNEL, -1); 10747f1b527cSSean Bruno free(recv_data); 10757f1b527cSSean Bruno } 10767f1b527cSSean Bruno 10777f1b527cSSean Bruno /* 10787f1b527cSSean Bruno * Send data file to node "-S" 10797f1b527cSSean Bruno */ 10807f1b527cSSean Bruno if (send_data != NULL){ 10817f1b527cSSean Bruno dvsend(fd, send_data, TAG | CHANNEL, -1); 10827f1b527cSSean Bruno free(send_data); 10837f1b527cSSean Bruno } 10847f1b527cSSean Bruno 10857f1b527cSSean Bruno if (fd > 0) { 10867f1b527cSSean Bruno close(fd); 10877f1b527cSSean Bruno fd = -1; 1088a7a73b95SHidetoshi Shimokawa } 1089a7a73b95SHidetoshi Shimokawa return 0; 1090a7a73b95SHidetoshi Shimokawa } 1091