shithub: riscv

Download patch

ref: edaac09f58050103fe7cb60b23aabc423155a210
parent: bec856ac010318bc911e62d729088f0b6e4b8441
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sat May 17 20:24:08 EDT 2025

io: add bitmask argument

--- a/sys/man/1/io
+++ b/sys/man/1/io
@@ -16,6 +16,8 @@
 .I address
 [
 .I value
+] [
+.I mask
 ]
 .SH DESCRIPTION
 .I io
@@ -25,6 +27,18 @@
 or
 .B -w
 for reading or writing, respectively.
+When a
+.I mask
+is provided for a read,
+it is applied with a logical
+.B AND
+operation to the value.
+When a
+.I mask
+is provided for a write,
+the set bits in the mask select the bits from
+.I value
+to be modified.
 The default operation size is a byte.
 C style notation for integers (e.g.
 .B 0x42
@@ -31,9 +45,10 @@
 or
 .BR 023 )
 is accepted for the
-.I address
-and
+.IR address ,
 .I value
+and
+.I mask
 parameters.
 .PP
 .TP
--- a/sys/src/cmd/io.c
+++ b/sys/src/cmd/io.c
@@ -7,7 +7,7 @@
 void
 usage(void)
 {
-	fprint(2, "%s: [-f file] [ -WLME ] [-r | -w] address [ value ]\n", argv0);
+	fprint(2, "%s: [-f file] [ -WLME ] [-r | -w] address [ value ] [ mask ]\n", argv0);
 	exits("usage");
 }
 
@@ -15,10 +15,10 @@
 main(int argc, char** argv) {
 	int fd, size, op;
 	ulong port;
-	uvlong data;
+	uvlong data, value, mask;
 	uchar datab[8];
 	
-	data = 0;
+	data = value = mask = 0;
 	size = 1;
 	op = -1;
 	ARGBEGIN {
@@ -33,14 +33,39 @@
 	} ARGEND;
 	if(op == -1) usage();
 	if(argc < 1) usage();
-	if(op == OWRITE && argc < 2) usage();
-	port = strtoul(argv[0], 0, 0);
-	if(op == OWRITE) data = strtoull(argv[1], 0, 0);
-	
+	port = strtoul(*argv, 0, 0);
+	argv++, argc--;
+	if(op == OWRITE) {
+		if(argc < 1) usage();
+		value = strtoull(*argv, 0, 0);
+		argv++, argc--;
+	}
+	if(argc > 0){
+		mask = ~strtoull(*argv, 0, 0);
+		argv++, argc--;
+		if(op == OWRITE){
+			op = ORDWR;
+			value &= ~mask;
+		}
+	}  
+	if(op == OREAD)
+		mask = ~mask;
+	USED(argv);
+	if(argc != 0) usage();
 	fd = open(file==nil?datac[size]:file, op);
 	if(fd == -1) sysfatal("open: %r");
-	
-	if(op == OWRITE) {
+	if(op == OREAD || op == ORDWR) {
+		memset(datab, 0, 8);
+		if(pread(fd, datab, size, port) != size)
+			sysfatal("pread: %r");
+		data = datab[0] | (datab[1] << 8) | (datab[2] << 16) |
+			(datab[3] << 24) | ((uvlong)datab[4] << 32) |
+			((uvlong)datab[5] << 40) | ((uvlong)datab[6] << 48) | 
+			((uvlong)datab[7] << 56);
+		data &= mask;
+	}
+	if(op == OWRITE || op == ORDWR) {
+		data |= value;
 		datab[0] = data;
 		datab[1] = data >> 8;
 		datab[2] = data >> 16;
@@ -52,15 +77,6 @@
 		if(pwrite(fd, datab, size, port) != size)
 			sysfatal("pwrite: %r");
 	}
-	else {
-		memset(datab, 0, 8);
-		if(pread(fd, datab, size, port) != size)
-			sysfatal("pread: %r");
-		data = datab[0] | (datab[1] << 8) | (datab[2] << 16) |
-			(datab[3] << 24) | ((vlong)datab[4] << 32) |
-			((vlong)datab[5] << 40) | ((vlong)datab[6] << 48) | 
-			((vlong)datab[7] << 56);
-		print("0x%ullx\n", data);
-	}
+	print("0x%ullx\n", data);
 	exits(nil);
 }
--