From: joe2@vnet.ibm.com
Date: Mon, 9 Nov 92 19:45:32 FWT
Newsgroups: comp.os.os2.programmer
Subject: Re: CSet/2 and port access.
Reply-To: <joe2@vnet.ibm.com>
Disclaimer: This posting represents the poster's views, not those of IBM
News-Software: UReply 3.0

In <1dij4sINNmek@flop.ENGR.ORST.EDU> the Dodger writes:
>Alright, I'm starting to get frustrated here. I've been using CSet/2 for a
>couple of days now and I love it. However, there are no hardware port access
>functions such as outp and inp. I really need these functions to do what I
>am trying to do. So I thought that I would just write the port functions in
>assembler, assemble them with TASM 3.0, and then link it all together. Well,
>it all goes fine until I run the program. The program just exits. I have no
>idea what the exit codes are (it is a full screen graphics program) and I
>get no access violations or anything like that.
>
>Someone hinted at the fact that the hardware ports cannot be accessed from
>32bit protected mode. Is this true? Am I going to have to try to write a
>ring 0 dll to get this done? And if so, what will be the performance benefits
>of this. My program will eventually be doing a LOT of port access, and if it
>has to call a dll a few million times, then won't that slow things down a lot?
>
>Thanks for any help.
>

   Several solutions:

1) Write a device driver. Ok, I know, you don't want to... but it is not
   that difficult, and from a device driver you can control CPU
   scheduling, etc.

2) Use the services of the TESTCFG$ driver, through DosDevIOCtl.
   I am not sure if this is really documented/supported though!

3) Include a RING2 segment in your code, and check that IOPL=YES in your
   config.sys. This RING2 segment has to be 16bit (32bit segments
   are RING3 only). The easiest way to write such a code is to use
   MASM.

4) Use C Set/2 version 2.0 (beta version included in the PDK CDROM).
   It does include _inp and _outp. *BUT* beware: I understand it is
   implemented using a 16bit RING2 segment, so each time you
   call inp or outp, a ring transition will occur. So it's not going
   to be fast. With method 3, you can put more than just one I/O
   in the RING2 code.

  Now some more details about method 3. Let me show you how to
implement inp with a MASM RING2 segment. First the .ASM file:

------------------------------------
        PUBLIC  MYINP                   ; UPPERCASE (Pascal calling convention)


R2SEG   SEGMENT BYTE PUBLIC 'CODE'
        ASSUME  CS:R2SEG, DS:NOTHING

MYINP   PROC    FAR

        push    bp
        mov     bp, sp

        mov     dx, bp+6Y              ; One arg: port
        in      al, dx                  ; Get value
        sub     ah, ah                  ; Return value in ax

        pop     bp
        ret     2                       ; Remove one word from stack
MYINP   ENDP

  Now, very important, things to include in the .DEF file:

--------------------------------------------




SEGMENTS
        R2SEG   CLASS 'CODE' IOPL

EXPORTS
        MYINP   1                -> To tell the CPU how many word to
                                    copy from the RING3 stack to the
                                    RING2 stack...


 That's it! Now you can call MYINP with the followin C Set/2 prototype:

extern USHORT _Far16 _Pascal MyInp  (USHORT port) ;


Hope this helps!     -Joel Armengaud