Re: Something broke :-( Re: fwcontrol update

Sean Bruno <[email protected]>
Newsgroups gmane.os.freebsd.devel.firewire
Message-ID <[email protected]>
Dieter wrote:
>>> I notice that it doesn't print every generation.
>>> I notice that the node_id changes.
>>>       
>> This alarms me quite a bit.  I didn't think there was anyway for the 
>> generation to change
>> without the log message being spit out.  Interesting.
>>     
>
> It also skips on dmesg, so it isn't a console problem:
>
> fwohci1: node_id=0xc000ffc0, gen=86, CYCLEMASTER mode
> firewire1: 1 nodes, maxhop <= 0, cable IRM = 0 (me)
> firewire1: bus manager 0 (me)
> got BUSRST packet!?
> got BUSRST packet!?
> got BUSRST packet!?
> fwohci1: BUS reset
> fwohci1: node_id=0xc000ffc1, gen=108, CYCLEMASTER mode
> firewire1: 2 nodes, maxhop <= 1, cable IRM = 1 (me)
> firewire1: bus manager 0 
> fwohci1: BUS reset
> fwohci1: node_id=0xc000ffc0, gen=112, CYCLEMASTER mode
> fwohci1: invalid SID len = 0	<-----------------------<<< didn't notice this line before
> fwohci1: BUS reset						only occurs twice in dmesg
> fwohci1: node_id=0xc000ffc1, gen=130, CYCLEMASTER mode
> firewire1: 2 nodes, maxhop <= 1, cable IRM = 1 (me)
> firewire1: bus manager 1 (me)
> fwohci1: BUS reset
> fwohci1: node_id=0xc000ffc0, gen=135, CYCLEMASTER mode
> firewire1: 1 nodes, maxhop <= 0, cable IRM = 0 (me)
> firewire1: bus manager 0 (me)
> got BUSRST packet!?
> got BUSRST packet!?
> fwohci1: BUS reset
> fwohci1: node_id=0xc000ffc1, gen=154, CYCLEMASTER mode
>
> Does "got BUSRST packet!?" mean that the camera is sending out
> bus reset commands?  That doesn't seem right.  BTW, shouldn't that
> line have a prefix telling where it comes from (e.g. fwohci1:
> or firewire1:) ?
>
> BTW there is just the FreeBSD box and the camera, no other nodes
> on the firewire bus.
>
>   
thanks, that's good to know.
>> I have been suspicious of a race condition for some time in the firewire 
>> stack, I see it across multiple
>> devices(sbp, sbp_targ) and now fwcontrol is acting weird.  Very interesting.
>>     
>
>   
>> Yes.  Try the attached patch.  Let me know.
>>     
>
> I don't see a patch.
>
>   
Doh!  Let me attach it this time!  :)
> Note that fwcontrol is not running when the spew happens.
> I press play on the camcorder, and the spewing starts.
> I press stop and the spewing stops.
>
> My only theories are that fwcontrol set something that
> survives a reboot, or that the fw controller chip isn't
> getting completely reset and properly initialized.  I'm
> leaning towards the chip being the more likely explaination.
>   
fwcontrol is ridiculously dangerous IMO.  It is a userland app that does 
raw direct access to registers on firewire devices.  I would think that 
some kind of safety wrapper/API is in order here.


-- 
Sean Bruno
MiraLink Corporation
6015 NE 80th Ave, Ste 100
Portland, OR 97218
Phone 503-621-5143
Fax 503-621-5199
MSN: [email protected]
Google:  [email protected]
Yahoo:  [email protected]

_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-firewire
To unsubscribe, send any mail to "[email protected]"
fwcontrol.diff (text/plain, 19.9 KB)
Index: fwcontrol.8
===================================================================
--- fwcontrol.8	(revision 5721)
+++ fwcontrol.8	(working copy)
@@ -59,7 +59,7 @@
 The following options are available:
 .Bl -tag -width indent
 .It Fl u Ar bus_num
-Specify the FireWire bus number to be operated on.
+Specify the FireWire bus number to be operated on.  Default is bus 0.
 .It Fl r
 Initiate bus reset.
 .It Fl t
Index: fwcontrol.c
===================================================================
--- fwcontrol.c	(revision 5721)
+++ fwcontrol.c	(working copy)
@@ -56,6 +56,8 @@
 #include <string.h>
 #include <sysexits.h>
 #include <unistd.h>
+#include <stdint.h>
+#include <stdbool.h>
 #include "fwmethods.h"
 
 static void sysctl_set_int(const char *, int);
@@ -64,21 +66,22 @@
 usage(void)
 {
 	fprintf(stderr,
-		"fwcontrol [-u bus_num] [-rt] [-f node] [-g gap_count] "
-		    "[-o node] "
-		    "[-b pri_req] [-c node] [-d node] [-l file] "
-		    "[-R file] [-S file] [-m target]\n"
+		"fwcontrol [-u bus_num] [-prt] [-c node] [-d node] [-o node] [-s node]\n"
+		"\t  [-l file] [-g gap_count] [-f force_root ] [-b pri_req]\n"
+		"\t  [-M mode] [-R filename] [-S filename] [-m EUI64 | hostname]\n"
 		"\t-u: specify bus number\n"
-		"\t-f: broadcast force_root by phy_config packet\n"
-		"\t-g: broadcast gap_count by phy_config packet\n"
-		"\t-o: send link-on packet to the node\n"
-		"\t-s: write RESET_START register on the node\n"
-		"\t-b: set PRIORITY_BUDGET register on all supported nodes\n"
-		"\t-c: read configuration ROM\n"
+		"\t-p: Display current PHY register settings\n"
 		"\t-r: bus reset\n"
 		"\t-t: read topology map\n"
+		"\t-c: read configuration ROM\n"
 		"\t-d: hex dump of configuration ROM\n"
+		"\t-o: send link-on packet to the node\n"
+		"\t-s: write RESET_START register on the node\n"
 		"\t-l: load and parse hex dump file of configuration ROM\n"
+		"\t-g: broadcast gap_count by phy_config packet\n"
+		"\t-f: broadcast force_root by phy_config packet\n"
+		"\t-b: set PRIORITY_BUDGET register on all supported nodes\n"
+		"\t-M: specify dv or mpeg\n"
 		"\t-R: Receive DV or MPEG TS stream\n"
 		"\t-S: Send DV stream\n"
 		"\t-m: set fwmem target\n");
@@ -92,18 +95,14 @@
 	*(u_int32_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 = (struct fw_devlstreq *)malloc(sizeof(struct fw_devlstreq));
 	if (data == NULL)
-		err(1, "malloc");
+		err(EX_SOFTWARE, "%s: data malloc", __func__);
 	if( ioctl(fd, FW_GDEVLST, data) < 0) {
-       			err(1, "ioctl");
+       			err(EX_IOERR, "%s: ioctl", __func__);
 	}
-	return data;
 }
 
 static int
@@ -130,17 +129,25 @@
 	if (eui64_hostton(nodestr, &eui) != 0 && eui64_aton(nodestr, &eui) != 0)
 		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)
+	if (i >= data->info_len) {
+		if (data != NULL)
+			free(data);
 		return (-1);
+	}
 
 gotnode:
 	if (node < 0 || node > 63)
@@ -158,7 +165,10 @@
 	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    hostname\n");
 	for (i = 0; i < data->info_len; i++) {
@@ -184,6 +194,8 @@
 	u_int32_t *qld, res;
 
         asyreq = (struct fw_asyreq *)malloc(sizeof(struct fw_asyreq_t) + 16);
+	if (asyreq == NULL)
+		err(EX_SOFTWARE, "%s:asyreq malloc", __func__);
 	asyreq->req.len = 16;
 #if 0
 	asyreq->req.type = FWASREQNODE;
@@ -206,7 +218,7 @@
 		asyreq->pkt.mode.wreqq.data = htonl(data);
 
 	if (ioctl(fd, FW_ASYREQ, asyreq) < 0) {
-       		err(1, "ioctl");
+       		err(EX_IOERR, "%s: ioctl", __func__);
 	}
 	res = qld[3];
 	free(asyreq);
@@ -222,6 +234,8 @@
         struct fw_asyreq *asyreq;
 
 	asyreq = (struct fw_asyreq *)malloc(sizeof(struct fw_asyreq_t) + 12);
+	if (asyreq == NULL)
+		err(EX_SOFTWARE, "%s:asyreq malloc", __func__);
 	asyreq->req.len = 12;
 	asyreq->req.type = FWASREQNODE;
 	asyreq->pkt.mode.ld[0] = 0;
@@ -237,16 +251,18 @@
 						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 = (struct fw_asyreq *)malloc(sizeof(struct fw_asyreq_t) + 12);
+	if (asyreq == NULL)
+		err(EX_SOFTWARE, "%s:asyreq malloc", __func__);
 	asyreq->req.len = 12;
 	asyreq->req.type = FWASREQNODE;
 	asyreq->pkt.mode.common.tcode = FWTCODE_PHY;
@@ -254,7 +270,7 @@
 	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);
 }
 
@@ -264,6 +280,8 @@
         struct fw_asyreq *asyreq;
 
 	asyreq = (struct fw_asyreq *)malloc(sizeof(struct fw_asyreq_t) + 16);
+	if (asyreq == NULL)
+		err(EX_SOFTWARE, "%s:asyreq malloc", __func__);
 	asyreq->req.len = 16;
 	asyreq->req.type = FWASREQNODE;
 	asyreq->pkt.mode.wreqq.dst = FWLOCALBUS | (node & 0x3f);
@@ -276,7 +294,7 @@
 	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);
 }
 
@@ -290,7 +308,10 @@
 	u_int32_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];
@@ -344,7 +365,10 @@
 	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++) {
 		if (data->dev[i].dst == node && data->dev[i].eui.lo != 0)
@@ -360,7 +384,7 @@
 	buf.ptr = crom_buf;
 	bzero(crom_buf, len);
 	if ((error = ioctl(fd, FW_GCROM, &buf)) < 0) {
-       		err(1, "ioctl");
+       		err(EX_IOERR, "%s: ioctl", __func__);
 	}
 
 	return error;
@@ -469,9 +493,9 @@
 	static const char *speed[] = {"S100", "S200", "S400", "S800"};
 	tmap = malloc(sizeof(struct fw_topology_map));
 	if (tmap == NULL)
-		return;
+		err(EX_SOFTWARE, "%s:tmap malloc", __func__);
 	if (ioctl(fd, FW_GTPMAP, tmap) < 0) {
-       		err(1, "ioctl");
+       		err(EX_IOERR, "%s: ioctl", __func__);
 	}
 	printf("crc_len: %d generation:%d node_count:%d sid_count:%d\n",
 		tmap->crc_len, tmap->generation,
@@ -512,7 +536,7 @@
 	for (i = 0; i < len; i++) {
 		reg.addr = offset + i;
 		if (ioctl(fd, FWOHCI_RDPHYREG, &reg) < 0)
-       			err(1, "ioctl");
+       			err(EX_IOERR, "%s: ioctl", __func__);
 		buf[i] = (u_int8_t) reg.data;
 		printf("0x%02x ",  reg.data);
 	}
@@ -527,7 +551,7 @@
 	reg.addr = 0x7;
 	reg.data = ((page & 7) << 5) | (port & 0xf);
 	if (ioctl(fd, FWOHCI_WRPHYREG, &reg) < 0)
-       		err(1, "ioctl");
+       		err(EX_IOERR, "%s: ioctl", __func__);
 	read_phy_registers(fd, buf, 8, 8);
 }
 
@@ -590,22 +614,16 @@
 	);
 }
 
-static void
-open_dev(int *fd, char *devbase)
+static int
+open_dev(int *fd, 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
@@ -625,25 +643,40 @@
 	u_int32_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);
+	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\n", __func__);
 	ptr = (u_int32_t *) buf;
 	ciph = (struct ciphdr *)(ptr + 1);
 
@@ -666,102 +699,167 @@
 int
 main(int argc, char **argv)
 {
+#define MAX_BOARDS 10
 	u_int32_t crom_buf[1024/4];
-	char devbase[1024] = "/dev/fw0";
-	int fd, ch, len=1024;
+	u_int32_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;
+/*
+ * 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;
 
-	fd = -1;
+	int32_t priority_budget = -1;
+	int32_t adjust_gap_count = -1;
+	int32_t reset_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", device_string, current_board);
+			if (open_dev(&fd, devbase) < 0) {
+				if (current_board == 0) {
+					usage();
+				}
+				return(EIO);
+			}
+			list_dev(fd);
+			close(fd);
+			fd = -1;
+		}
 	}
-
-	while ((ch = getopt(argc, argv, "M:f:g:m:o:s:b:prtc:d:l:u:R:S:")) != -1)
+       /*
+	* Parse all command line options, then execute requested operations.
+	*/
+	while ((ch = getopt(argc, argv, "M:f:g:m:o:s:b:prtc:d:l:u:R:S:")) != -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: invalid number: %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)
+				err(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':
-			tmp = strtol(optarg, NULL, 0);
-			open_dev(&fd, devbase);
-			send_phy_config(fd, tmp, -1);
+			adjust_gap_count = strtol(optarg, NULL, 0);
+			if ( (adjust_gap_count < 0) || (adjust_gap_count > INT32_MAX) )
+				err(EX_USAGE, "%s:adjust_gap_count 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);
+			reset_gap_count = strtol(optarg, NULL, 0);
+			if ( (reset_gap_count < 0) || (reset_gap_count > INT32_MAX) )
+				err(EX_USAGE, "%s:reset_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.firewire.fwmem.eui64_hi", eui.hi);
-			sysctl_set_int("hw.firewire.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)
+				err(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 > INT32_MAX) )
+				err(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 > INT32_MAX) )
+				err(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':
@@ -774,22 +872,164 @@
 				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;
 		default:
 			usage();
+			return 0;
 		}
+	} /* end while */
+
+       /*
+	* If -u <bus_number> is passed, execute 
+	* command for that card only.
+	*
+	* If -u <bus_number> is not passed, execute
+	* command for card 0 only. 
+	*
+	*/
+	if(open_needed){
+		snprintf(devbase, sizeof(devbase), "%s%d", device_string, current_board);
+		if (open_dev(&fd, devbase) < 0) {
+			errx(EX_IOERR, "%s: Error opening board #%d\n", __func__, current_board);
+		}
+	}
+	/*
+	 * 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", __func__);
+	}
+	/*
+	 * 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);
+
+	/*
+	 * Adjust the gap count for this card/bus to value "-f"
+	 */
+	if (adjust_gap_count >= 0)
+		send_phy_config(fd, adjust_gap_count, -1);
+
+	/*
+	 * Reset the gap count for this card/bus  "-g"
+	 */
+	if (reset_gap_count >= 0)
+		send_phy_config(fd, -1, reset_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(*(u_int32_t*)&(target.octet[0]));
+		eui.lo = ntohl(*(u_int32_t*)&(target.octet[4]));
+		sysctl_set_int("hw.firewire.fwmem.eui64_hi", eui.hi);
+		sysctl_set_int("hw.firewire.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);
+		}
+		snprintf(devbase, sizeof(devbase), "%s%d", device_string, current_board);
+		if (open_dev(&fd, devbase) < 0)
+			errx(EX_IOERR, "%s: Error opening board #%d in recv_data\n", __func__, current_board);
+		(*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;
 }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.