diff --git a/usr.sbin/fwctl/fwcontrol.c b/usr.sbin/fwctl/fwcontrol.c index 1b69cdf999e2..54021b10c642 100644 --- a/usr.sbin/fwctl/fwcontrol.c +++ b/usr.sbin/fwctl/fwcontrol.c @@ -1,4 +1,4 @@ -/* $NetBSD: fwcontrol.c,v 1.8 2010/03/29 10:49:34 cegger Exp $ */ +/* $NetBSD: fwcontrol.c,v 1.9 2010/08/24 08:41:24 cegger Exp $ */ /* * Copyright (C) 2002 * Hidetoshi Shimokawa. All rights reserved. @@ -32,11 +32,9 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#if defined(__FreeBSD__) - #include -__FBSDID("$FreeBSD: src/usr.sbin/fwcontrol/fwcontrol.c,v 1.23 2006/10/26 22:33:38 imp Exp $"); -#endif +//__FBSDID("$FreeBSD: src/usr.sbin/fwcontrol/fwcontrol.c,v 1.23 2006/10/26 22:33:38 imp Exp $"); +__RCSID("$NetBSD: fwcontrol.c,v 1.9 2010/08/24 08:41:24 cegger Exp $"); #include #include @@ -45,19 +43,11 @@ __FBSDID("$FreeBSD: src/usr.sbin/fwcontrol/fwcontrol.c,v 1.23 2006/10/26 22:33:3 #include #include #include -#if defined(__FreeBSD__) -#include -#include -#include -#include -#include -#elif defined(__NetBSD__) #include "eui64.h" #include #include #include #include -#endif #include #include @@ -75,47 +65,44 @@ static void usage(void) { fprintf(stderr, - "%s [-prt] [-b pri_req] [-c node] [-d node]" - " [-g gap_count] [-l file]\n" - "\t[-m EUI64 | hostname] [-o node] [-R filename]" - " [-S filename]\n" - "\t[-s node] [-u bus_num]\n" - "\t-b: set PRIORITY_BUDGET register on all supported nodes\n" - "\t-c: read configuration ROM\n" - "\t-d: hex dump of configuration ROM\n" - "\t-g: broadcast gap_count by phy_config packet\n" - "\t-l: load and parse hex dump file of configuration ROM\n" - "\t-m: set fwmem target\n" - "\t-o: send link-on packet to the node\n" - "\t-p: dump PHY registers\n" - "\t-R: receive DV or MPEG TS stream\n" - "\t-r: bus reset\n" - "\t-S: send DV stream\n" - "\t-s: write RESET_START register on the node\n" - "\t-t: read topology map\n" - "\t-u: specify bus number\n", getprogname()); + "%s [-prt] [-b pri_req] [-c node] [-d node] [-f force_root ]\n" + "\t[-g gap_count] [-l file] [-M mode] [-m EUI64 | hostname]\n" + "\t[-o node] [-R filename] [-S filename] [-s node] [-u bus_num]\n" + "\n" + "\t-b: set PRIORITY_BUDGET register on all supported nodes\n" + "\t-c: read configuration ROM\n" + "\t-d: hex dump of configuration ROM\n" + "\t-f: force root node\n" + "\t-g: broadcast gap_count by phy_config packet\n" + "\t-l: load and parse hex dump file of configuration ROM\n" + "\t-M: specify dv or mpeg\n" + "\t-m: set fwmem target\n" + "\t-o: send link-on packet to the node\n" + "\t-p: dump PHY registers\n" + "\t-R: receive DV or MPEG TS stream\n" + "\t-r: bus reset\n" + "\t-S: send DV stream\n" + "\t-s: write RESET_START register on the node\n" + "\t-t: read topology map\n" + "\t-u: specify bus number\n", getprogname()); exit(EX_USAGE); } static void fweui2eui64(const struct fw_eui64 *fweui, struct eui64 *eui) { - *(u_int32_t*)&(eui->octet[0]) = htonl(fweui->hi); - *(u_int32_t*)&(eui->octet[4]) = htonl(fweui->lo); + *(uint32_t*)&(eui->octet[0]) = htonl(fweui->hi); + *(uint32_t*)&(eui->octet[4]) = htonl(fweui->lo); } -static struct fw_devlstreq * -get_dev(int fd) +static void +get_dev(int fd, struct fw_devlstreq *data) { - struct fw_devlstreq *data; - data = malloc(sizeof(*data)); if (data == NULL) - err(1, "malloc"); - if( ioctl(fd, FW_GDEVLST, data) < 0) { - err(1, "ioctl"); - } - return data; + err(EX_SOFTWARE, "%s: data malloc", __func__); + if (ioctl(fd, FW_GDEVLST, data) < 0) + err(EX_IOERR, "%s: ioctl", __func__); } static int @@ -127,7 +114,7 @@ str2node(int fd, const char *nodestr) int i, node; if (nodestr == '\0') - return (-1); + return -1; /* * Deal with classic node specifications. @@ -140,25 +127,33 @@ str2node(int fd, const char *nodestr) * Try to get an eui and match it against available nodes. */ if (eui64_hostton(nodestr, &eui) != 0 && eui64_aton(nodestr, &eui) != 0) - return (-1); + return -1; - data = get_dev(fd); + data = (struct fw_devlstreq *)malloc(sizeof(struct fw_devlstreq)); + if (data == NULL) + err(EX_SOFTWARE, "%s: data malloc", __func__); + get_dev(fd,data); for (i = 0; i < data->info_len; i++) { fweui2eui64(&data->dev[i].eui, &tmpeui); if (memcmp(&eui, &tmpeui, sizeof(struct eui64)) == 0) { node = data->dev[i].dst; + if (data != NULL) + free(data); goto gotnode; } } - if (i >= data->info_len) - return (-1); + if (i >= data->info_len) { + if (data != NULL) + free(data); + return -1; + } gotnode: if (node < 0 || node > 63) - return (-1); + return -1; else - return (node); + return node; } static void @@ -167,34 +162,38 @@ list_dev(int fd) struct fw_devlstreq *data; struct fw_devinfo *devinfo; struct eui64 eui; - char addr[EUI64_SIZ]; + char addr[EUI64_SIZ], hostname[40]; int i; - data = get_dev(fd); + data = (struct fw_devlstreq *)malloc(sizeof(struct fw_devlstreq)); + if (data == NULL) + err(EX_SOFTWARE, "%s:data malloc", __func__); + get_dev(fd, data); printf("%d devices (info_len=%d)\n", data->n, data->info_len); - printf("node EUI64 status\n"); + printf("node EUI64 status hostname\n"); for (i = 0; i < data->info_len; i++) { devinfo = &data->dev[i]; fweui2eui64(&devinfo->eui, &eui); eui64_ntoa(&eui, addr, sizeof(addr)); - printf("%4d %s %6d\n", + if (eui64_ntohost(hostname, sizeof(hostname), &eui)) + hostname[0] = 0; + printf("%4d %s %6d %s\n", (devinfo->status || i == 0) ? devinfo->dst : -1, - addr, - devinfo->status - ); + addr, devinfo->status, hostname); } free((void *)data); } -static u_int32_t -read_write_quad(int fd, struct fw_eui64 eui, u_int32_t addr_lo, int readmode, u_int32_t data) +static uint32_t +read_write_quad(int fd, struct fw_eui64 eui, uint32_t addr_lo, int readmode, + uint32_t data) { struct fw_asyreq *asyreq; - u_int32_t *qld, res; + uint32_t *qld, res; - asyreq = malloc(sizeof(*asyreq)); + asyreq = (struct fw_asyreq *)malloc(sizeof(struct fw_asyreq_t) + 16); if (asyreq == NULL) - err(1, "malloc"); + err(EX_SOFTWARE, "%s:asyreq malloc", __func__); asyreq->req.len = 16; #if 0 asyreq->req.type = FWASREQNODE; @@ -212,13 +211,12 @@ read_write_quad(int fd, struct fw_eui64 eui, u_int32_t addr_lo, int readmode, u_ asyreq->pkt.mode.rreqq.dest_hi = 0xffff; asyreq->pkt.mode.rreqq.dest_lo = addr_lo; - qld = (u_int32_t *)&asyreq->pkt; + qld = (uint32_t *)&asyreq->pkt; if (!readmode) - asyreq->pkt.mode.wreqq.data = data; + asyreq->pkt.mode.wreqq.data = htonl(data); - if (ioctl(fd, FW_ASYREQ, asyreq) < 0) { - err(1, "ioctl"); - } + if (ioctl(fd, FW_ASYREQ, asyreq) < 0) + err(EX_IOERR, "%s: ioctl", __func__); res = qld[3]; free(asyreq); if (readmode) @@ -227,41 +225,56 @@ read_write_quad(int fd, struct fw_eui64 eui, u_int32_t addr_lo, int readmode, u_ return 0; } +/* + * Send a PHY Config Packet + * ieee 1394a-2005 4.3.4.3 + * + * Message ID Root ID R T Gap Count + * 00(2 bits) (6 bits) 1 1 (6 bits) + * + * if "R" is set, then Root ID will be the next + * root node upon the next bus reset. + * if "T" is set, then Gap Count will be the + * value that all nodes use for their Gap Count + * if "R" and "T" are not set, then this message + * is either ignored or interpreted as an extended + * PHY config Packet as per 1394a-2005 4.3.4.4 + */ static void send_phy_config(int fd, int root_node, int gap_count) { struct fw_asyreq *asyreq; - asyreq = malloc(sizeof(*asyreq)); + asyreq = (struct fw_asyreq *)malloc(sizeof(struct fw_asyreq_t) + 12); if (asyreq == NULL) - err(1, "malloc"); + err(EX_SOFTWARE, "%s:asyreq malloc", __func__); asyreq->req.len = 12; asyreq->req.type = FWASREQNODE; asyreq->pkt.mode.ld[0] = 0; asyreq->pkt.mode.ld[1] = 0; asyreq->pkt.mode.common.tcode = FWTCODE_PHY; if (root_node >= 0) - asyreq->pkt.mode.ld[1] |= (root_node & 0x3f) << 24 | 1 << 23; + asyreq->pkt.mode.ld[1] |= ((root_node << 24) | (1 << 23)); if (gap_count >= 0) - asyreq->pkt.mode.ld[1] |= 1 << 22 | (gap_count & 0x3f) << 16; + asyreq->pkt.mode.ld[1] |= ((1 << 22) | (gap_count << 16)); asyreq->pkt.mode.ld[2] = ~asyreq->pkt.mode.ld[1]; printf("send phy_config root_node=%d gap_count=%d\n", root_node, gap_count); if (ioctl(fd, FW_ASYREQ, asyreq) < 0) - err(1, "ioctl"); + err(EX_IOERR, "%s: ioctl", __func__); free(asyreq); } static void -send_link_on(int fd, int node) +link_on(int fd, int node) { struct fw_asyreq *asyreq; - asyreq = malloc(sizeof(*asyreq)); + asyreq = (struct fw_asyreq *)malloc(sizeof(struct fw_asyreq_t) + 12); if (asyreq == NULL) - err(1, "malloc"); + err(EX_SOFTWARE, "%s:asyreq malloc", __func__); asyreq->req.len = 12; asyreq->req.type = FWASREQNODE; asyreq->pkt.mode.common.tcode = FWTCODE_PHY; @@ -269,7 +282,7 @@ send_link_on(int fd, int node) asyreq->pkt.mode.ld[2] = ~asyreq->pkt.mode.ld[1]; if (ioctl(fd, FW_ASYREQ, asyreq) < 0) - err(1, "ioctl"); + err(EX_IOERR, "%s: ioctl", __func__); free(asyreq); } @@ -278,9 +291,9 @@ reset_start(int fd, int node) { struct fw_asyreq *asyreq; - asyreq = malloc(sizeof(*asyreq)); + asyreq = (struct fw_asyreq *)malloc(sizeof(struct fw_asyreq_t) + 16); if (asyreq == NULL) - err(1, "malloc"); + err(EX_SOFTWARE, "%s:asyreq malloc", __func__); asyreq->req.len = 16; asyreq->req.type = FWASREQNODE; asyreq->pkt.mode.wreqq.dst = FWLOCALBUS | (node & 0x3f); @@ -293,21 +306,24 @@ reset_start(int fd, int node) asyreq->pkt.mode.wreqq.data = htonl(0x1); if (ioctl(fd, FW_ASYREQ, asyreq) < 0) - err(1, "ioctl"); + err(EX_IOERR, "%s: ioctl", __func__); free(asyreq); } static void -set_pri_req(int fd, u_int32_t pri_req) +set_pri_req(int fd, uint32_t pri_req) { struct fw_devlstreq *data; struct fw_devinfo *devinfo; struct eui64 eui; char addr[EUI64_SIZ]; - u_int32_t max, reg, old; + uint32_t max, reg, old; int i; - data = get_dev(fd); + data = (struct fw_devlstreq *)malloc(sizeof(struct fw_devlstreq)); + if (data == NULL) + err(EX_SOFTWARE, "%s:data malloc", __func__); + get_dev(fd, data); #define BUGET_REG 0xf0000218 for (i = 0; i < data->info_len; i++) { devinfo = &data->dev[i]; @@ -333,7 +349,7 @@ set_pri_req(int fd, u_int32_t pri_req) } static void -parse_bus_info_block(u_int32_t *p) +parse_bus_info_block(uint32_t *p) { char addr[EUI64_SIZ]; struct bus_info *bi; @@ -361,30 +377,31 @@ get_crom(int fd, int node, void *crom_buf, int len) int i, error; struct fw_devlstreq *data; - data = get_dev(fd); + data = (struct fw_devlstreq *)malloc(sizeof(struct fw_devlstreq)); + if (data == NULL) + err(EX_SOFTWARE, "%s:data malloc", __func__); + get_dev(fd, data); - for (i = 0; i < data->info_len; i++) { + for (i = 0; i < data->info_len; i++) if (data->dev[i].dst == node && data->dev[i].eui.lo != 0) break; - } if (i == data->info_len) errx(1, "no such node %d.", node); else buf.eui = data->dev[i].eui; - free((void *)data); + free(data); buf.len = len; buf.ptr = crom_buf; - bzero(crom_buf, len); - if ((error = ioctl(fd, FW_GCROM, &buf)) < 0) { - err(1, "ioctl"); - } + memset(crom_buf, 0, len); + if ((error = ioctl(fd, FW_GCROM, &buf)) < 0) + err(EX_IOERR, "%s: ioctl", __func__); return error; } static void -show_crom(u_int32_t *crom_buf) +show_crom(uint32_t *crom_buf) { int i; struct crom_context cc; @@ -394,7 +411,7 @@ show_crom(u_int32_t *crom_buf) struct csrreg *reg; struct csrdirectory *dir; struct csrhdr *hdr; - u_int16_t crc; + uint16_t crc; printf("first quad: 0x%08x ", *crom_buf); if (crom_buf[0] == 0) { @@ -425,7 +442,7 @@ show_crom(u_int32_t *crom_buf) } printf("root_directory: len=0x%04x(%d) crc=0x%04x", dir->crc_len, dir->crc_len, dir->crc); - crc = crom_crc((u_int32_t *)&dir->entry[0], dir->crc_len); + crc = crom_crc((uint32_t *)&dir->entry[0], dir->crc_len); if (crc == dir->crc) printf("(OK)\n"); else @@ -449,7 +466,7 @@ show_crom(u_int32_t *crom_buf) #define DUMP_FORMAT "%08x %08x %08x %08x %08x %08x %08x %08x\n" static void -dump_crom(u_int32_t *p) +dump_crom(uint32_t *p) { int len=1024, i; @@ -461,19 +478,17 @@ dump_crom(u_int32_t *p) } static void -load_crom(char *filename, u_int32_t *p) +load_crom(const char *filename, uint32_t *p) { FILE *file; int len=1024, i; if ((file = fopen(filename, "r")) == NULL) - err(1, "load_crom"); + err(EX_IOERR, "load_crom %s", filename); for (i = 0; i < len/(4*8); i ++) { - fscanf(file, DUMP_FORMAT, - p, p+1, p+2, p+3, p+4, p+5, p+6, p+7); + fscanf(file, DUMP_FORMAT, p, p+1, p+2, p+3, p+4, p+5, p+6, p+7); p += 8; } - (void)fclose(file); } static void @@ -486,12 +501,12 @@ show_topology_map(int fd) static const char *pwr_class[] = {" 0W", "15W", "30W", "45W", "-1W", "-2W", "-5W", "-9W"}; static const char *speed[] = {"S100", "S200", "S400", "S800"}; - tmap = malloc(sizeof(*tmap)); + + tmap = malloc(sizeof(struct fw_topology_map)); if (tmap == NULL) - err(1, "malloc"); - if (ioctl(fd, FW_GTPMAP, tmap) < 0) { - err(1, "ioctl"); - } + err(EX_SOFTWARE, "%s:tmap malloc", __func__); + if (ioctl(fd, FW_GTPMAP, tmap) < 0) + err(EX_IOERR, "%s: ioctl", __func__); printf("crc_len: %d generation:%d node_count:%d sid_count:%d\n", tmap->crc_len, tmap->generation, tmap->node_count, tmap->self_id_count); @@ -503,7 +518,7 @@ show_topology_map(int fd) printf("%02d sequel packet\n", sid.p0.phy_id); continue; } - printf("%02d %2d %2d %4s %d %3s" + printf("%02d %2d %2d %4s %d %3s" " %s %s %s %d %d\n", sid.p0.phy_id, sid.p0.link_active, @@ -522,7 +537,7 @@ show_topology_map(int fd) } static void -read_phy_registers(int fd, u_int8_t *buf, int offset, int len) +read_phy_registers(int fd, uint8_t *buf, int offset, int len) { struct fw_reg_req_t reg; int i; @@ -530,22 +545,22 @@ read_phy_registers(int fd, u_int8_t *buf, int offset, int len) for (i = 0; i < len; i++) { reg.addr = offset + i; if (ioctl(fd, FWOHCI_RDPHYREG, ®) < 0) - err(1, "ioctl"); - buf[i] = (u_int8_t) reg.data; + err(EX_IOERR, "%s: ioctl", __func__); + buf[i] = (uint8_t) reg.data; printf("0x%02x ", reg.data); } printf("\n"); } static void -read_phy_page(int fd, u_int8_t *buf, int page, int port) +read_phy_page(int fd, uint8_t *buf, int page, int port) { struct fw_reg_req_t reg; reg.addr = 0x7; reg.data = ((page & 7) << 5) | (port & 0xf); if (ioctl(fd, FWOHCI_WRPHYREG, ®) < 0) - err(1, "ioctl"); + err(EX_IOERR, "%s: ioctl", __func__); read_phy_registers(fd, buf, 8, 8); } @@ -558,7 +573,7 @@ dump_phy_registers(int fd) int i; printf("=== base register ===\n"); - read_phy_registers(fd, (u_int8_t *)&b, 0, 8); + read_phy_registers(fd, (uint8_t *)&b, 0, 8); printf( "Physical_ID:%d R:%d CPS:%d\n" "RHB:%d IBR:%d Gap_Count:%d\n" @@ -580,7 +595,7 @@ dump_phy_registers(int fd) for (i = 0; i < b.num_ports; i ++) { printf("\n=== page 0 port %d ===\n", i); - read_phy_page(fd, (u_int8_t *)&p, 0, i); + read_phy_page(fd, (uint8_t *)&p, 0, i); printf( "Astat:%d BStat:%d Ch:%d Con:%d RXOK:%d Dis:%d\n" "Negotiated_speed:%d PIE:%d Fault:%d Stanby_fault:%d Disscrm:%d B_Only:%d\n" @@ -597,7 +612,7 @@ dump_phy_registers(int fd) ); } printf("\n=== page 1 ===\n"); - read_phy_page(fd, (u_int8_t *)&v, 1, 0); + read_phy_page(fd, (uint8_t *)&v, 1, 0); printf( "Compliance:%d\n" "Vendor_ID:0x%06x\n" @@ -608,22 +623,16 @@ dump_phy_registers(int fd) ); } -static void -open_dev(int *fd, char *devbase) +static int +open_dev(int *fd, const char *_devname) { - char name[256]; - int i; if (*fd < 0) { - for (i = 0; i < 4; i++) { - snprintf(name, sizeof(name), "%s.%d", devbase, i); - if ((*fd = open(name, O_RDWR)) >= 0) - break; - } + *fd = open(_devname, O_RDWR); if (*fd < 0) - err(1, "open"); - + return -1; } + return 0; } static void @@ -640,43 +649,58 @@ detect_recv_fn(int fd, char ich) struct fw_isochreq isoreq; struct fw_isobufreq bufreq; int len; - u_int32_t *ptr; + uint32_t *ptr; struct ciphdr *ciph; fwmethod *retfn; +#define RECV_NUM_PACKET 16 +#define RECV_PACKET_SZ 1024 bufreq.rx.nchunk = 8; - bufreq.rx.npacket = 16; - bufreq.rx.psize = 1024; + bufreq.rx.npacket = RECV_NUM_PACKET; + bufreq.rx.psize = RECV_PACKET_SZ; bufreq.tx.nchunk = 0; bufreq.tx.npacket = 0; bufreq.tx.psize = 0; if (ioctl(fd, FW_SSTBUF, &bufreq) < 0) - err(1, "ioctl FW_SSTBUF"); + err(EX_IOERR, "%s: ioctl FW_SSTBUF", __func__); isoreq.ch = ich & 0x3f; isoreq.tag = (ich >> 6) & 3; if (ioctl(fd, FW_SRSTREAM, &isoreq) < 0) - err(1, "ioctl FW_SRSTREAM"); + err(EX_IOERR, "%s: ioctl FW_SRSTREAM", __func__); - buf = (char *)malloc(1024*16); - len = read(fd, buf, 1024*16); - ptr = (u_int32_t *) buf; + buf = (char *)malloc(RECV_NUM_PACKET * RECV_PACKET_SZ); + if (buf == NULL) + err(EX_SOFTWARE, "%s:buf malloc", __func__); + /* + * fwdev.c seems to return EIO on error and + * the return value of the last uiomove + * on success. For now, checking that the + * return is not less than zero should be + * sufficient. fwdev.c::fw_read() should + * return the total length read, not the value + * of the last uiomove(). + */ + len = read(fd, buf, RECV_NUM_PACKET * RECV_PACKET_SZ); + if (len < 0) + err(EX_IOERR, "%s: error reading from device", __func__); + ptr = (uint32_t *) buf; ciph = (struct ciphdr *)(ptr + 1); - switch(ciph->fmt) { - case CIP_FMT_DVCR: - fprintf(stderr, "Detected DV format on input.\n"); - retfn = dvrecv; - break; - case CIP_FMT_MPEG: - fprintf(stderr, "Detected MPEG TS format on input.\n"); - retfn = mpegtsrecv; - break; - default: - errx(1, "Unsupported format for receiving: fmt=0x%x", - ciph->fmt); + switch (ciph->fmt) { + case CIP_FMT_DVCR: + fprintf(stderr, "Detected DV format on input.\n"); + retfn = dvrecv; + break; + case CIP_FMT_MPEG: + fprintf(stderr, "Detected MPEG TS format on input.\n"); + retfn = mpegtsrecv; + break; + default: + errx(EXIT_FAILURE, "Unsupported format for receiving: fmt=0x%x", + ciph->fmt); } free(buf); return retfn; @@ -685,97 +709,183 @@ detect_recv_fn(int fd, char ich) int main(int argc, char **argv) { - u_int32_t crom_buf[1024/4]; - char devbase[1024] = "/dev/fw0"; - int fd, ch, len=1024; +#define MAX_BOARDS 10 + uint32_t crom_buf[1024/4]; + uint32_t crom_buf_hex[1024/4]; + char devbase[64]; + const char *device_string = "/dev/fw"; + int fd = -1, ch, len=1024; + int32_t current_board = 0; +/* + * If !command_set, then -u will display the nodes for the board. + * This emulates the previous behavior when -u is passed by itself + */ + bool command_set = false; + bool open_needed = false; long tmp; struct fw_eui64 eui; struct eui64 target; fwmethod *recvfn = NULL; - fd = -1; +/* + * Holders for which functions + * to iterate through + */ + bool display_board_only = false; + bool display_crom = false; + bool send_bus_reset = false; + bool display_crom_hex = false; + bool load_crom_from_file = false; + bool set_fwmem_target = false; + bool dump_topology = false; + bool dump_phy_reg = false; + + int32_t priority_budget = -1; + int32_t set_root_node = -1; + int32_t set_gap_count = -1; + int32_t send_link_on = -1; + int32_t send_reset_start = -1; + + char *crom_string = NULL; + char *crom_string_hex = NULL; + char *recv_data = NULL; + char *send_data = NULL; if (argc < 2) { - open_dev(&fd, devbase); - list_dev(fd); + for (current_board = 0; current_board < MAX_BOARDS; current_board++) { + snprintf(devbase, sizeof(devbase), "%s%d.0", device_string, current_board); + if (open_dev(&fd, devbase) < 0) { + if (current_board == 0) { + usage(); + err(EX_IOERR, "%s: Error opening firewire controller #%d %s", + __func__, current_board, devbase); + } + return EIO; + } + list_dev(fd); + close(fd); + fd = -1; + } } - - while ((ch = getopt(argc, argv, "M:g:m:o:s:b:prtc:d:l:u:R:S:")) != -1) - switch(ch) { + /* + * Parse all command line options, then execute requested operations. + */ + while ((ch = getopt(argc, argv, "b:c:d:f:g:l:M:m:o:pR:rS:s:tu:")) != -1) { + switch (ch) { case 'b': - tmp = strtol(optarg, NULL, 0); - if (tmp < 0 || tmp > (long)0xffffffff) - errx(EX_USAGE, "invalid number: %s", optarg); - open_dev(&fd, devbase); - set_pri_req(fd, tmp); + priority_budget = strtol(optarg, NULL, 0); + if (priority_budget < 0 || priority_budget > INT32_MAX) + errx(EX_USAGE, + "%s: priority_budget out of range: %s", + __func__, optarg); + command_set = true; + open_needed = true; + display_board_only = false; break; case 'c': - open_dev(&fd, devbase); - tmp = str2node(fd, optarg); - get_crom(fd, tmp, crom_buf, len); - show_crom(crom_buf); + crom_string = malloc(strlen(optarg)+1); + if (crom_string == NULL) + err(EX_SOFTWARE, "%s:crom_string malloc", + __func__); + if (strtol(crom_string, NULL, 0) < 0 || + strtol(crom_string, NULL, 0) > MAX_BOARDS) + errx(EX_USAGE, "%s:Invalid value for node", + __func__); + strcpy(crom_string, optarg); + display_crom = 1; + open_needed = true; + command_set = true; + display_board_only = false; break; case 'd': - open_dev(&fd, devbase); - tmp = str2node(fd, optarg); - get_crom(fd, tmp, crom_buf, len); - dump_crom(crom_buf); + crom_string_hex = malloc(strlen(optarg)+1); + if (crom_string_hex == NULL) + err(EX_SOFTWARE, "%s:crom_string_hex malloc", + __func__); + strcpy(crom_string_hex, optarg); + display_crom_hex = 1; + open_needed = true; + command_set = true; + display_board_only = false; + break; + case 'f': +#define MAX_PHY_CONFIG 0x3f + set_root_node = strtol(optarg, NULL, 0); + if (set_root_node < 0 || set_root_node > MAX_PHY_CONFIG) + errx(EX_USAGE, "%s:set_root_node out of range", + __func__); + open_needed = true; + command_set = true; + display_board_only = false; break; case 'g': - tmp = strtol(optarg, NULL, 0); - open_dev(&fd, devbase); - send_phy_config(fd, -1, tmp); + set_gap_count = strtol(optarg, NULL, 0); + if (set_gap_count < 0 || set_gap_count > MAX_PHY_CONFIG) + errx(EX_USAGE, "%s:set_gap_count out of range", + __func__); + open_needed = true; + command_set = true; + display_board_only = false; break; case 'l': + load_crom_from_file = 1; load_crom(optarg, crom_buf); - show_crom(crom_buf); + command_set = true; + display_board_only = false; break; case 'm': - if (eui64_hostton(optarg, &target) != 0 && - eui64_aton(optarg, &target) != 0) - errx(EX_USAGE, "invalid target: %s", optarg); - eui.hi = ntohl(*(u_int32_t*)&(target.octet[0])); - eui.lo = ntohl(*(u_int32_t*)&(target.octet[4])); - sysctl_set_int("hw.fwmem.eui64_hi", eui.hi); - sysctl_set_int("hw.fwmem.eui64_lo", eui.lo); + set_fwmem_target = 1; + open_needed = 0; + command_set = true; + display_board_only = false; + if (eui64_hostton(optarg, &target) != 0 && + eui64_aton(optarg, &target) != 0) + errx(EX_USAGE, "%s: invalid target: %s", + __func__, optarg); break; case 'o': - open_dev(&fd, devbase); - tmp = str2node(fd, optarg); - send_link_on(fd, tmp); + send_link_on = str2node(fd, optarg); + if (send_link_on < 0 || send_link_on > MAX_PHY_CONFIG) + errx(EX_USAGE, "%s: node out of range: %s\n", + __func__, optarg); + open_needed = true; + command_set = true; + display_board_only = false; break; case 'p': - open_dev(&fd, devbase); - dump_phy_registers(fd); + dump_phy_reg = 1; + open_needed = true; + command_set = true; + display_board_only = false; break; case 'r': - open_dev(&fd, devbase); - if(ioctl(fd, FW_IBUSRST, &tmp) < 0) - err(1, "ioctl"); + send_bus_reset = 1; + open_needed = true; + command_set = true; + display_board_only = false; break; case 's': - open_dev(&fd, devbase); - tmp = str2node(fd, optarg); - reset_start(fd, tmp); + send_reset_start = str2node(fd, optarg); + if (send_reset_start < 0 || + send_reset_start > MAX_PHY_CONFIG) + errx(EX_USAGE, "%s: node out of range: %s\n", + __func__, optarg); + open_needed = true; + command_set = true; + display_board_only = false; break; case 't': - open_dev(&fd, devbase); - show_topology_map(fd); + dump_topology = 1; + open_needed = true; + command_set = true; + display_board_only = false; break; case 'u': - tmp = strtol(optarg, NULL, 0); - snprintf(devbase, sizeof(devbase), "/dev/fw%ld", tmp); - if (fd > 0) { - close(fd); - fd = -1; - } - if (argc == optind) { - open_dev(&fd, devbase); - list_dev(fd); - } + if (!command_set) + display_board_only = true; + current_board = strtol(optarg, NULL, 0); + open_needed = true; break; -#define TAG (1<<6) -#define CHANNEL 63 case 'M': switch (optarg[0]) { case 'm': @@ -788,22 +898,186 @@ main(int argc, char **argv) errx(EX_USAGE, "unrecognized method: %s", optarg); } + command_set = true; + display_board_only = false; break; case 'R': - open_dev(&fd, devbase); - if (recvfn == NULL) /* guess... */ - recvfn = detect_recv_fn(fd, TAG | CHANNEL); - close(fd); - fd = -1; - open_dev(&fd, devbase); - (*recvfn)(fd, optarg, TAG | CHANNEL, -1); + recv_data = malloc(strlen(optarg)+1); + if (recv_data == NULL) + err(EX_SOFTWARE, "%s:recv_data malloc", + __func__); + strcpy(recv_data, optarg); + open_needed = false; + command_set = true; + display_board_only = false; break; case 'S': - open_dev(&fd, devbase); - dvsend(fd, optarg, TAG | CHANNEL, -1); + send_data = malloc(strlen(optarg)+1); + if (send_data == NULL) + err(EX_SOFTWARE, "%s:send_data malloc", + __func__); + strcpy(send_data, optarg); + open_needed = true; + command_set = true; + display_board_only = false; break; + case '?': default: usage(); + errx(EINVAL, "%s: Unknown command line arguments", + __func__); + return 0; } + } /* end while */ + + /* + * Catch the error case when the user + * executes the command with non ''-'' + * delimited arguments. + * Generate the usage() display and exit. + */ + if (!command_set && !display_board_only) { + usage(); + errx(EINVAL, "%s: Unknown command line arguments", __func__); + return 0; + } + + /* + * If -u is passed, execute + * command for that card only. + * + * If -u is not passed, execute + * command for card 0 only. + * + */ + if (open_needed) { + snprintf(devbase, sizeof(devbase), + "%s%d.0", device_string, current_board); + if (open_dev(&fd, devbase) < 0) { + err(EX_IOERR, + "%s: Error opening firewire controller #%d %s", + __func__, current_board, devbase); + } + } + /* + * display the nodes on this board "-u" only + */ + if (display_board_only) + list_dev(fd); + + /* + * dump_phy_reg "-p" + */ + if (dump_phy_reg) + dump_phy_registers(fd); + + /* + * send a BUS_RESET Event "-r" + */ + if (send_bus_reset) + if (ioctl(fd, FW_IBUSRST, &tmp) < 0) + err(EX_IOERR, "%s: Ioctl of bus reset failed for %s", + __func__, devbase); + /* + * Print out the CROM for this node "-c" + */ + if (display_crom) { + tmp = str2node(fd, crom_string); + get_crom(fd, tmp, crom_buf, len); + show_crom(crom_buf); + free(crom_string); + } + /* + * Hex Dump the CROM for this node "-d" + */ + if (display_crom_hex) { + tmp = str2node(fd, crom_string_hex); + get_crom(fd, tmp, crom_buf_hex, len); + dump_crom(crom_buf_hex); + free(crom_string_hex); + } + /* + * Set Priority Budget to value for this node "-b" + */ + if (priority_budget >= 0) + set_pri_req(fd, priority_budget); + + /* + * Explicitly set the root node of this bus to value "-f" + */ + if (set_root_node >= 0) + send_phy_config(fd, set_root_node, -1); + + /* + * Set the gap count for this card/bus "-g" + */ + if (set_gap_count >= 0) + send_phy_config(fd, -1, set_gap_count); + + /* + * Load a CROM from a file "-l" + */ + if (load_crom_from_file) + show_crom(crom_buf); + /* + * Set the fwmem target for a node to argument "-m" + */ + if (set_fwmem_target) { + eui.hi = ntohl(*(uint32_t*)&(target.octet[0])); + eui.lo = ntohl(*(uint32_t*)&(target.octet[4])); + sysctl_set_int("hw.fwmem.eui64_hi", eui.hi); + sysctl_set_int("hw.fwmem.eui64_lo", eui.lo); + } + + /* + * Send a link on to this board/bus "-o" + */ + if (send_link_on >= 0) + link_on(fd, send_link_on); + + /* + * Send a reset start to this board/bus "-s" + */ + if (send_reset_start >= 0) + reset_start(fd, send_reset_start); + + /* + * Dump the node topology for this board/bus "-t" + */ + if (dump_topology) + show_topology_map(fd); + + /* + * Recieve data file from node "-R" + */ +#define TAG (1<<6) +#define CHANNEL 63 + if (recv_data != NULL){ + if (recvfn == NULL) { /* guess... */ + recvfn = detect_recv_fn(fd, TAG | CHANNEL); + close(fd); + fd = -1; + } + snprintf(devbase, sizeof(devbase), "%s%d.0", + device_string, current_board); + if (open_dev(&fd, devbase) < 0) + err(EX_IOERR, "%s: Error opening firewire controller #%d %s in recv_data\n", + __func__, current_board, devbase); + (*recvfn)(fd, recv_data, TAG | CHANNEL, -1); + free(recv_data); + } + + /* + * Send data file to node "-S" + */ + if (send_data != NULL){ + dvsend(fd, send_data, TAG | CHANNEL, -1); + free(send_data); + } + + if (fd > 0) { + close(fd); + fd = -1; + } return 0; } diff --git a/usr.sbin/fwctl/fwctl.8 b/usr.sbin/fwctl/fwctl.8 index f54411e7634e..57030b43ffc9 100644 --- a/usr.sbin/fwctl/fwctl.8 +++ b/usr.sbin/fwctl/fwctl.8 @@ -1,4 +1,4 @@ -.\" $NetBSD: fwctl.8,v 1.14 2010/08/16 06:56:48 wiz Exp $ +.\" $NetBSD: fwctl.8,v 1.15 2010/08/24 08:41:24 cegger Exp $ .\" .\" Copyright (c) 2005 KIYOHARA Takashi .\" All rights reserved. @@ -29,7 +29,7 @@ .\" .\" $FreeBSD: src/usr.sbin/fwcontrol/fwcontrol.8,v 1.21 2007/10/31 05:59:17 brueffer Exp $ .\" -.Dd May 18, 2009 +.Dd August 24, 2010 .Dt FWCTL 8 .Os .Sh NAME @@ -71,12 +71,21 @@ register on all supported nodes. Show the configuration ROM on the node. .It Fl d Ar node Hex dump of the configuration ROM. +.It Fl f Ar node +Force specified +.Ar node +to be the root node on the next bus reset by sending a PHY config packet. +Valid values are 0 - 63. .It Fl g Ar gap_count Broadcast new .Ar gap_count by phy_config packet. By default this value is 63 on all nodes. Valid values are 0 - 63. +.It Fl i Ar pri_req +Set the +.Dv PRIORITY_BUDGET +register on all supported nodes. .It Fl l Ar file Load hex dump file of the configuration ROM and parse it. .It Fl M Ar mode diff --git a/usr.sbin/fwctl/fwdv.c b/usr.sbin/fwctl/fwdv.c index bc10486810e5..f89a33171d48 100644 --- a/usr.sbin/fwctl/fwdv.c +++ b/usr.sbin/fwctl/fwdv.c @@ -1,4 +1,4 @@ -/* $NetBSD: fwdv.c,v 1.3 2008/05/02 19:59:19 xtraeme Exp $ */ +/* $NetBSD: fwdv.c,v 1.4 2010/08/24 08:41:24 cegger Exp $ */ /* * Copyright (C) 2003 * Hidetoshi Shimokawa. All rights reserved. @@ -32,7 +32,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/usr.sbin/fwcontrol/fwdv.c,v 1.7 2007/06/17 10:20:55 simokawa Exp $ + * $FreeBSD: src/usr.sbin/fwcontrol/fwdv.c,v 1.8 2009/02/02 21:05:12 sbruno Exp $ */ #include #include @@ -40,10 +40,6 @@ #include #include -#if __FreeBSD_version >= 500000 -#include -#endif - #include #include #include @@ -53,13 +49,8 @@ #include #include -#if defined(__FreeBSD__) -#include -#include -#elif defined(__NetBSD__) #include #include -#endif #include "fwmethods.h" @@ -106,12 +97,12 @@ dvrecv(int d, const char *filename, char ich, int count) struct ciphdr *ciph; struct fw_pkt *pkt; char *pad, *buf; - u_int32_t *ptr; + uint32_t *ptr; int len, tlen, npad, fd, k, m, vec, lsystem = -1, nb; int nblocks[] = {250 /* NTSC */, 300 /* PAL */}; struct iovec wbuf[NPACKET_R]; - if(strcmp(filename, "-") == 0) { + if (strcmp(filename, "-") == 0) { fd = STDOUT_FILENO; } else { fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0660); @@ -130,13 +121,13 @@ dvrecv(int d, const char *filename, char ich, int count) bufreq.tx.npacket = 0; bufreq.tx.psize = 0; if (ioctl(d, FW_SSTBUF, &bufreq) < 0) - err(1, "ioctl FW_SSTBUF"); + err(EXIT_FAILURE, "ioctl FW_SSTBUF"); isoreq.ch = ich & 0x3f; isoreq.tag = (ich >> 6) & 3; if (ioctl(d, FW_SRSTREAM, &isoreq) < 0) - err(1, "ioctl"); + err(EXIT_FAILURE, "ioctl"); k = m = 0; while (count <= 0 || k <= count) { @@ -146,13 +137,12 @@ dvrecv(int d, const char *filename, char ich, int count) /* RBUFSIZE - tlen */)) > 0) { if (len < 0) { if (errno == EAGAIN) { - fprintf(stderr, - "(EAGAIN)- push 'Play'?\n"); + fprintf(stderr, "(EAGAIN)\n"); fflush(stderr); if (len <= 0) continue; } else - err(1, "read failed"); + err(EXIT_FAILURE, "read failed"); } tlen += len; if ((RBUFSIZE - tlen) < PSIZE) @@ -162,16 +152,16 @@ dvrecv(int d, const char *filename, char ich, int count) tlen = len = read(d, buf, RBUFSIZE); if (len < 0) { if (errno == EAGAIN) { - fprintf(stderr, "(EAGAIN)\n"); + fprintf(stderr, "(EAGAIN) - push 'Play'?\n"); fflush(stderr); if (len <= 0) continue; } else - err(1, "read failed"); + err(EXIT_FAILURE, "read failed"); } #endif vec = 0; - ptr = (u_int32_t *) buf; + ptr = (uint32_t *) buf; again: pkt = (struct fw_pkt *) ptr; #if DEBUG @@ -182,11 +172,10 @@ again: ciph = (struct ciphdr *)(ptr + 1); /* skip iso header */ if (ciph->fmt != CIP_FMT_DVCR) errx(1, "unknown format 0x%x", ciph->fmt); - ptr = (u_int32_t *) (ciph + 1); /* skip cip header */ + ptr = (uint32_t *) (ciph + 1); /* skip cip header */ #if DEBUG - if (ciph->fdf.dv.cyc != 0xffff && k == 0) { + if (ciph->fdf.dv.cyc != 0xffff && k == 0) fprintf(stderr, "0x%04x\n", ntohs(ciph->fdf.dv.cyc)); - } #endif if (pkt->mode.stream.len <= sizeof(struct ciphdr)) /* no payload */ @@ -210,15 +199,20 @@ again: (dv->payload[0] & DV_DSF_12) == 0) dv->payload[0] |= DV_DSF_12; nb = nblocks[lsystem]; - fprintf(stderr, "%d", k%10); + fprintf(stderr, "%d:%02d:%02d %d\r", + k / (3600 * frame_rate[lsystem]), + (k / (60 * frame_rate[lsystem])) % 60, + (k / frame_rate[lsystem]) % 60, + k % frame_rate[lsystem]); + #if FIX_FRAME if (m > 0 && m != nb) { /* padding bad frame */ npad = ((nb - m) % nb); if (npad < 0) npad += nb; - fprintf(stderr, "(%d blocks padded)", - npad); + fprintf(stderr, "\n%d blocks padded\n", + npad); npad *= DSIZE; wbuf[vec].iov_base = pad; wbuf[vec++].iov_len = npad; @@ -229,10 +223,6 @@ again: } #endif k++; - if (k % frame_rate[lsystem] == 0) { - /* every second */ - fprintf(stderr, "\n"); - } fflush(stderr); m = 0; } @@ -246,16 +236,15 @@ again: vec = 0; } } - ptr = (u_int32_t *)dv; + ptr = (uint32_t *)dv; next: if ((char *)ptr < buf + tlen) goto again; if (vec > 0) writev(fd, wbuf, vec); } - if(fd != STDOUT_FILENO) { + if (fd != STDOUT_FILENO) close(fd); - } fprintf(stderr, "\n"); } @@ -271,7 +260,7 @@ dvsend(int d, const char *filename, char ich, int count) int lsystem=-1, pad_acc, cycle_acc, cycle, f_cycle, f_frac; struct iovec wbuf[TNBUF*2 + NEMPTY]; char *pbuf; - u_int32_t iso_data, iso_empty, hdr[TNBUF + NEMPTY][3]; + uint32_t iso_data, iso_empty, hdr[TNBUF + NEMPTY][3]; struct ciphdr *ciph; struct timeval start, end; double rtime; @@ -292,13 +281,13 @@ dvsend(int d, const char *filename, char ich, int count) bufreq.tx.npacket = NPACKET_T; bufreq.tx.psize = PSIZE; if (ioctl(d, FW_SSTBUF, &bufreq) < 0) - err(1, "ioctl FW_SSTBUF"); + err(EXIT_FAILURE, "ioctl FW_SSTBUF"); isoreq.ch = ich & 0x3f; isoreq.tag = (ich >> 6) & 3; if (ioctl(d, FW_STSTREAM, &isoreq) < 0) - err(1, "ioctl FW_STSTREAM"); + err(EXIT_FAILURE, "ioctl FW_STSTREAM"); iso_data = 0; pkt = (struct fw_pkt *) &iso_data; @@ -414,7 +403,7 @@ again: fprintf(stderr, "(EAGAIN) - push 'Play'?\n"); goto again; } - err(1, "write failed"); + err(EXIT_FAILURE, "write failed"); } } close(fd); diff --git a/usr.sbin/fwctl/fwmpegts.c b/usr.sbin/fwctl/fwmpegts.c index 7e121d1e662f..5272bebbda5a 100644 --- a/usr.sbin/fwctl/fwmpegts.c +++ b/usr.sbin/fwctl/fwmpegts.c @@ -1,3 +1,4 @@ +/* $NetBSD: fwmpegts.c,v 1.2 2010/08/24 08:41:24 cegger Exp $ */ /* * Copyright (C) 2005 * Petr Holub, Hidetoshi Shimokawa. All rights reserved. @@ -31,7 +32,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/usr.sbin/fwcontrol/fwmpegts.c,v 1.1 2006/10/26 22:33:38 imp Exp $ + * $FreeBSD: src/usr.sbin/fwcontrol/fwmpegts.c,v 1.3 2009/02/02 21:05:12 sbruno Exp $ */ #include #include @@ -39,10 +40,6 @@ #include #include -#if __FreeBSD_version >= 500000 -#include -#endif - #include #include #include @@ -52,13 +49,8 @@ #include #include -#if defined(__FreeBSD__) -#include -#include -#elif defined(__NetBSD__) #include #include -#endif #include "fwmethods.h" @@ -175,13 +167,13 @@ mpegtsrecv(int d, const char *filename, char ich, int count) bufreq.tx.npacket = 0; bufreq.tx.psize = 0; if (ioctl(d, FW_SSTBUF, &bufreq) < 0) - err(1, "ioctl"); + err(EXIT_FAILURE, "ioctl"); isoreq.ch = ich & 0x3f; isoreq.tag = (ich >> 6) & 3; if (ioctl(d, FW_SRSTREAM, &isoreq) < 0) - err(1, "ioctl"); + err(EXIT_FAILURE, "ioctl"); k = m = 0; while (count <= 0 || k <= count) { @@ -192,10 +184,9 @@ mpegtsrecv(int d, const char *filename, char ich, int count) if (len < 0) { if (errno == EAGAIN) { fprintf(stderr, "(EAGAIN) - push 'Play'?\n"); - if (len <= 0) - continue; - } else - err(1, "read failed"); + continue; + } + err(EXIT_FAILURE, "read failed"); } ptr = (uint32_t *) buf;