[GAP] Low level port access?

Jorge Real jorge at disca.upv.es
Wed Sep 20 20:47:56 CEST 2006


Hi Peter.

In windows, you need a DLL to access the port address map. I found one 
on the web when I needed it. There's info in the gnat manual on how to 
generate the DLL's corresponding ".a" file - I can't remember the 
details now.

Then you have to write an Ada program to interface with the DLL.
In our case, we used the following code:
--------------------------------------
with Byte_Operations; use Byte_Operations;

package Port_IO is
pragma linker_options("-linput_output32");

    procedure Out32(Port:in word; Value: in Byte);
    pragma Import(StdCall, Out32, "Out32");

    function Inp32(Port: word) return Byte;
    pragma Import(StdCall, Inp32, "Inp32");

end Port_IO;
----------------------------------------

The imported package Byte_Operations simply defines the subtypes used:
    subtype Word is Unsigned_16;
    subtype Byte is Unsigned_8;

The DLL is "input_output32.dll" and the names of the functions are those 
exported by the DLL. We did the Windows experiment just to compare with 
the Linux/RTLinux performance, so we abandoned this platform immediately :-)



For Linux, you'll need the following 4 files:


common_types.ads
--------------------------------------
-- Common Types
-- Defines types common to Port_IO and Pendulum_IO
--
-- Jorge Real.- September 2005

with Interfaces; use Interfaces;

package Common_Types is

   subtype Word is Unsigned_16;
   subtype Byte is Unsigned_8;

end Common_Types;
--------------------------------------


port_io_linux.ads
--------------------------------------
with Common_Types; use Common_Types;

package Port_IO_Linux is
    procedure PortOut(Port : in Word; Data : in Byte);
    function PortIn(Port : in Word) return Byte;
end Port_IO_Linux;
--------------------------------------


port_io_linux.adb
--------------------------------------
with System.Machine_Code; use System.Machine_Code;

package body Port_Io_Linux is

    function PortIn(Port : in Word) return Byte is
       Tmp : Byte;
    begin
       Asm ("inb %%dx, %0",
            Byte'Asm_Output ("=a", Tmp),
            Word'Asm_Input  ("d",  Port),
            "edx",
            True);
       return Tmp;
    end PortIn;
    pragma Inline (PortIn);

    procedure PortOut(Port : in Word; Data : in Byte) is
    begin
       Asm ("outb %0, %%dx",
            No_Output_Operands,
            (Byte'Asm_Input ("a", Data),
             Word'Asm_Input ("d", Port)),
            "edx", True);
    end PortOut;
    pragma Inline (PortOut);

    -- This one is only for initialisation of the pakage
    procedure Get_IOPL;
    pragma Import(C,Get_IOPL,"get_iopl_3");
    pragma Linker_Options("get_iopl_3.o");

   begin
    Get_IOPL;
end Port_Io_Linux;
--------------------------------


get_iopl.c
--------------------------------
void get_iopl_3 (void) {
	iopl(3);
}
--------------------------------

You must be root to execute code using the Port_IO_Linux package.


In RTLinux, you don't need to acquire iopl(3) since you run in the 
kernel space. The rest is the same as for Linux.


I hope this helps.

Jorge.

Peter C. Chapin escribió:
> On Wed, 20 Sep 2006, Jorge Real wrote:
> 
> 
>>it depends on your underlying OS. I have three different versions for
>>Linux, RTLinux and Windows. What's your case?
> 
> 
> Sorry, I should have mentioned that before. I'm interested primarily in
> Windows right now... although perhaps Linux in the future. Thanks for your
> reply!
> 
> Peter
> 
> _______________________________________________
> GAP mailing list
> GAP at gnat.info
> /no-more-mailman.html
> To unsubscribe from this list, please contact the GAP GNAT Tracker administrator
> within your organization.
> 


More information about the GAP mailing list