mmap: add mwrite

	* plus a test
	* plus fix some missing line number prefixes on errors

Change-Id: I0ec00987477ab118a758425f33318fc108109d77
diff --git a/cmds/mmap.c b/cmds/mmap.c
index f942117..2cbb1bd 100644
--- a/cmds/mmap.c
+++ b/cmds/mmap.c
@@ -177,6 +177,7 @@
   uint64_t fileLength = stats.st_size;
 
   if (fileAddr + length > fileLength) {
+    fprintf(stderr, "%s", posPrefix);
     fprintf(stderr, "mapped range (0x%" PRIx64 ",0x%" PRIx64 ") "
                       "is outside of size of file (0x%" PRIx64 ")\n",
             fileAddr, length, fileLength);
@@ -221,8 +222,9 @@
   case sizeof(u16):     dp = &u16; break;
   case sizeof(u8):      dp = &u8; break;
   default:
-        fprintf(stderr, "Can't find datatype for wordlen '%d'\n", wordlen);
-        return -1;
+    fprintf(stderr, "%s", posPrefix);
+    fprintf(stderr, "Can't find datatype for wordlen '%d'\n", wordlen);
+    return -1;
   }
 
   memcpy(dp, vp, wordlen);
@@ -233,8 +235,9 @@
   case sizeof(u16):     *valueP = u16; break;
   case sizeof(u8):      *valueP = u8; break;
   default:
-        fprintf(stderr, "Can't find datatype for wordlen '%d'\n", wordlen);
-        return -1;
+    fprintf(stderr, "%s", posPrefix);
+    fprintf(stderr, "Can't find datatype for wordlen '%d'\n", wordlen);
+    return -1;
   }
   return 0;
 }
@@ -338,6 +341,37 @@
   return 0;
 }
 
+// write to device on MDIO bus attached to a PCI device
+int do_mwrite(int slot, uint64_t addr_reg, uint64_t cmd_reg,
+             uint64_t port, uint64_t dev, uint64_t reg, uint64_t newVal)
+{
+  uint32_t* areg = slots[slot].map + addr_reg;
+  uint32_t* creg = slots[slot].map + cmd_reg;
+  uint32_t value = newVal;
+
+  if (wait_for_bits(creg, CMD_BUSY, 0, 1000, 100) < 0) {
+    return -1;
+  }
+
+  // remote register we want to read
+  *areg = reg;
+
+  // issue command
+  *creg = (CMD_ADDR_THEN_WRITE << 26) | (dev << 21) | (port << 16) |
+          (value & 0xffff);
+
+  if (wait_for_bits(creg, CMD_BUSY, 0, 1000, 100) < 0) {
+    return -1;
+  }
+
+  // get result
+  value = *creg;
+
+  printf("%" PRIx64 ".%" PRIx64 ".%04" PRIx64 ": %04x %04x\n",
+         port, dev, reg, value >> 16, value & 0xffff);
+  return 0;
+}
+
 int cmd_open(int ac, char* av[])
 {
   char* usage = "open slot file offset length";
@@ -550,6 +584,43 @@
   return 0;
 }
 
+// write registers on mdio devices via PCI indirection
+int cmd_mwrite(int ac, char* av[])
+{
+  char* usage = "mwrite slot addr_reg cmd_reg port dev reg value";
+
+  if (ac > 1 && strcmp(av[1], "help") == 0) {
+    printf("\t%s\n", usage);
+    return 0;
+  }
+  if (ac != 8) {
+    fprintf(stderr, "Usage: %s\n", usage);
+    return -1;
+  }
+
+  int slot;
+  uint64_t addr_reg;
+  uint64_t cmd_reg;
+  uint64_t port;
+  uint64_t dev;
+  uint64_t reg;
+  uint64_t value;
+
+  if (asSlot(&slot, av[1], 1) < 0 ||
+      asAddr(&addr_reg, av[2], slot) < 0 ||
+      asAddr(&cmd_reg, av[3], slot) < 0 ||
+      asUnsigned(&port, av[4]) < 0 ||
+      asUnsigned(&dev, av[5]) < 0 ||
+      asUnsigned(&reg, av[6]) < 0 ||
+      asUnsigned(&value, av[7]) < 0) {
+    return -1;
+  }
+  if (do_mwrite(slot, addr_reg, cmd_reg, port, dev, reg, value) < 0) {
+    return -1;
+  }
+  return 0;
+}
+
 typedef int (*cmdFunc)(int ac, char* av[]);
 
 struct commands {
@@ -566,6 +637,7 @@
   { "msleep", cmd_msleep, },
   { "echo", cmd_echo, },
   { "mread", cmd_mread, },
+  { "mwrite", cmd_mwrite, },
   { NULL, NULL },
 };
 
diff --git a/cmds/tests.mmap/help.test b/cmds/tests.mmap/help.test
index b7b54d0..5466693 100644
--- a/cmds/tests.mmap/help.test
+++ b/cmds/tests.mmap/help.test
@@ -10,6 +10,7 @@
 msleep help
 echo help
 mread help
+mwrite help
 '
 
 OUTPUT='# 
@@ -22,6 +23,7 @@
 	msleep msecs
 	echo text ...
 	mread slot addr_reg cmd_reg port dev reg count
+	mwrite slot addr_reg cmd_reg port dev reg value
 # open help
 	open slot file offset length
 # close help
@@ -38,4 +40,6 @@
 	echo text ...
 # mread help
 	mread slot addr_reg cmd_reg port dev reg count
+# mwrite help
+	mwrite slot addr_reg cmd_reg port dev reg value
 '
diff --git a/cmds/tests.mmap/map_fail.test b/cmds/tests.mmap/map_fail.test
index afb04de..4bc305a 100644
--- a/cmds/tests.mmap/map_fail.test
+++ b/cmds/tests.mmap/map_fail.test
@@ -12,7 +12,7 @@
 
 OUTPUT="# 
 # open 0 A 0 41
-mapped range (0x0,0x29) is outside of size of file (0x28)
+stdin:2: mapped range (0x0,0x29) is outside of size of file (0x28)
 stdin:2: command 'open' failed
 # close 0
 stdin:3: slot '0' is not open
diff --git a/cmds/tests.mmap/mread.test b/cmds/tests.mmap/mread.test
index 6abd99b..fd17c9e 100644
--- a/cmds/tests.mmap/mread.test
+++ b/cmds/tests.mmap/mread.test
@@ -3,18 +3,19 @@
 FILES="A B"
 
 A_1='0123456789012345678901234567890123456789'
-A_2='0123\x03\x00\x00\x00\x00\x00\x41\x1c2345678901234567890123456789'
+A_2='0123\x04\x00\x00\x00\x00\x00\x41\x1c2345678901234567890123456789'
 
 
 INPUT='
 open 0 A 0 40
-mread 0 4 8 1 2 3 1
+mread 0 4 8 1 2 3 2
 close 0
 '
 
 OUTPUT="# 
 # open 0 A 0 40
-# mread 0 4 8 1 2 3 1
+# mread 0 4 8 1 2 3 2
 1.2.0003: 1c41 0000
+1.2.0004: 1c41 0000
 # close 0
 "
diff --git a/cmds/tests.mmap/mwrite.mmap b/cmds/tests.mmap/mwrite.mmap
new file mode 100644
index 0000000..0de296e
--- /dev/null
+++ b/cmds/tests.mmap/mwrite.mmap
@@ -0,0 +1,20 @@
+EXIT=0
+
+FILES="A B"
+
+A_1='0123456789012345678901234567890123456789'
+A_2='0123\x03\x00\x00\x00\x00\x00\x41\x1c2345678901234567890123456789'
+
+
+INPUT='
+open 0 A 0 40
+mwrite 0 4 8 1 2 3 0x1234
+close 0
+'
+
+OUTPUT="# 
+# open 0 A 0 40
+# mwrite 0 4 8 1 2 3 0x1234
+1.2.0003: 1c41 0000
+# close 0
+"
diff --git a/cmds/tests.mmap/quiet.test b/cmds/tests.mmap/quiet.test
index 93ee5fc..83e057b 100644
--- a/cmds/tests.mmap/quiet.test
+++ b/cmds/tests.mmap/quiet.test
@@ -11,6 +11,7 @@
 msleep help
 echo help
 mread help
+mwrite help
 '
 
 OUTPUT=\
@@ -22,6 +23,7 @@
 	msleep msecs
 	echo text ...
 	mread slot addr_reg cmd_reg port dev reg count
+	mwrite slot addr_reg cmd_reg port dev reg value
 	open slot file offset length
 	close slot
 	read slot addr wordlen
@@ -30,4 +32,5 @@
 	msleep msecs
 	echo text ...
 	mread slot addr_reg cmd_reg port dev reg count
+	mwrite slot addr_reg cmd_reg port dev reg value
 '
diff --git a/cmds/tests.mmap/signed.test b/cmds/tests.mmap/signed.test
index 0ba44aa..080378f 100644
--- a/cmds/tests.mmap/signed.test
+++ b/cmds/tests.mmap/signed.test
@@ -12,7 +12,7 @@
 
 OUTPUT="# 
 # open 0 A 0 -1
-mapped range (0x0,0xffffffffffffffff) is outside of size of file (0x28)
+stdin:2: mapped range (0x0,0xffffffffffffffff) is outside of size of file (0x28)
 stdin:2: command 'open' failed
 # close 0
 stdin:3: slot '0' is not open