IOrd and IOwr

I am making a GUI based environment for testing the Parilux device. I do this with the Tcl/Tk language. In essence, Tcl/Tk is the modern day BASIC for X Windows. But a very fine and flexible kind of BASIC with which you can make a fully graphical program within hours, without prior experience with the language.

Parilux lives on the printer port so I cannot do without port I/O operations and the Tcl language in itself lacks I/O instructions. And it cannot easily be expanded to do so afterwards.
But Tcl is extremely extensible. So there are two methods to get the job done after all:

  1. The 'exec' function allows execution of external commands (i.e. executables) whereby the options for that command are supplied in the command tail. And the output of the external command is read in into the Tcl application again via StdIn.
  2. You can open a chain of pipes from within a Tcl application with the 'open' command. Options are supplied to the external command via its StdIn and results must be read via a file handle.
Method 1 is by far the easiest way to get the job done. So I wrote some small Modula-2 programs that do the required things. IOrd will read what's on an I/O port number and IOwr will write a value to an I/O port.

IOrd2

IOrd2 needs to be run with a port address in hexadecimal as its only command line option. The program will just take the first argument, convert it to decimal, request I/O permission and then issue an InPort instruction to get to the required data. The value retrieved is then printed to StdOut via InOut.WriteCard. Just see it, read it and grab it.

MODULE IOrd2;

IMPORT  IOport, InOut, NumConv, Arguments, Strings;


VAR	word, n, port			: CARDINAL;
	ok				: BOOLEAN;
	portnr				: ARRAY [0..7] OF CHAR;
	args				: Arguments.ArgTable;
	count		       		: SHORTCARD;


BEGIN
   Arguments.GetArgs (count, args);
   Strings.Assign (portnr, args^[1]^);
   NumConv.Str2Num (port, 16, portnr, ok);
   IF  NOT ok  THEN
      InOut.WriteString ("--This is not a number.");
      InOut.WriteLn;
      HALT
   END;
   IF  IOport.IOperm (port, port, TRUE) = FALSE  THEN
      InOut.WriteString ("--Could not get IO permission.")
   ELSE
      word := IOport.InPort (port);
      InOut.WriteCard (word, 2);
      IF  IOport.IOperm (port, port, FALSE) = FALSE  THEN
	 InOut.WriteString ("--Could not release IO permission.")
      END;
   END;
   InOut.WriteLn
END IOrd2.
   
Compile the program and then issue the commands:
 $ su
 # chown root IOrd2
 # chmod 4755 IOrd2
 # cp IOrd2 /usr/local/bin
 # exit
 $
   
Now you can use the program in your scripts.

IOwr2

IOwr2 is for writing data to an I/O address. It takes two arguments in its command tail (address and value to be written) and returns nothing to the caller.

MODULE IOwr2;

IMPORT  IOport, InOut, NumConv, Strings, Arguments;

VAR	val, port		: CARDINAL;
	portnr, value		: ARRAY [0..7] OF CHAR;
	ok1, ok2		: BOOLEAN;
	args			: Arguments.ArgTable;
	count			: SHORTCARD;


BEGIN
   Arguments.GetArgs (count, args);
   Strings.Assign (portnr, args^[1]^);
   Strings.Assign (value, args^[2]^);
   NumConv.Str2Num (port, 16, portnr, ok1);
   NumConv.Str2Num (val, 10, value, ok2);
   IF  (ok1 = FALSE) OR (ok2 = FALSE)  THEN
      InOut.WriteString ("-This is not a number.");
      InOut.WriteLn;
      HALT
   END;
   IF  IOport.IOperm (port, port, TRUE) = FALSE  THEN
      InOut.WriteString ("-Could not get IO permission.")
   ELSE
      IOport.OutPort (port, val);
      IF  IOport.IOperm (port, port, FALSE) = FALSE  THEN
	 InOut.WriteString ("-Could not release IO permission.");
	 InOut.WriteLn
      END;
   END;
END IOwr2.
   

Some caution

You won't be able to do malicious things with IOrd2. So it doesn't matter that it runs with root privileges. But IOwr2 is another story. You can write any value to any IO port so you CAN bring down the system. I am working on a way to circumvent this problem but for the time being take care what you do.

Page created 8 August 2007,