From: Drew Eckhardt (drew@ophelia.cs.colorado.edu)
Date: 03/19/93


From: drew@ophelia.cs.colorado.edu (Drew Eckhardt)
Subject: Re: [Q] How to use "outp"
Date: Fri, 19 Mar 1993 08:09:03 GMT

In article <9307816.24010@mulga.cs.mu.OZ.AU> camerond@ee.mu.OZ.AU (cameron donaldson) writes:
>G'day,
>
>I was wondering how to use "outp", the assembler command
>defined as a C function in <asm/io.h>. When I have <asm/io.h>
>as a header, ld naturally enough complains about "undefined
>symbol _outb".

Depending on how you look at it, this is the result of a bug or a feature
of gcc. When a function is declared "extern inline," GCC behaves
differently when -O is or isn't used. With -O, inline code will be
emitted for the function. Without it, a call to that function will be
generated, with the address resolved at link time.

>When I actually define the function "outp"
>as found in <asm/io.h> the program will compile, but not
>surprisingly will die with a segmentation fault.

Compiling with -O, or doing something like

#define extern
#include <asm/io.h>
#undef extern

will have the same effect.

>Can I use "outp" in a user program, or will the kernel "not allow"
>(for want of a better phrase) users to write directly to a port.

The Unix paradigm is different than the DOS paradigm that you may be
used to. Unix isolates user programs from the hardware, to insure fair
allocation of the resources and to protect the system from mallicious
or broken programs.

If you -must- do it, you can call the ioperm() system call to get direct
access to the ports, or you can write to /dev/port. Note that for
obvious reasons, this is a priveledged system call, available only to
root.

In a few *limited* instances, where you can insure that your program
is the only one tinkering with the hardware, you don't need to
handle interrupts, and don't want to block on I/O this is the way to
go. One example would be in the Xserver, where it mmap()'s the frame
buffer and twiddles the SVGA bank switching registers.

In most cases, this is not the way to go.

- At the user level, there is no way to disable interrupts during time
  critical accesses. Also, other processes may be scheduled giving you
  an unacceptable latency for event handling. The Xserver has problems
  autodetecting the dot clocks because of this.

- At the user level, race conditions in the handling of resource
  contention will be possible.

- In the kernel code, hardware interrupts can be handled in a manner
  that's almost identical to a signal. This isn't possible at all
  at the user level.

- In the kernel code, you have access to the scheduling primatives, so
  that a process can block until I/O to your device is complete. At
  the user level, you'll have to sit arround in a busy loop, hurting
  the performance of other processes.
 

>In which case is there a better solution ?

Yes. Write a device driver. This will give you full control of the
hardware, scheduling primatives, etc.

(I'm attempting to develop a hardware card, and need i/o. And of course would
much rather use >Linux.)

Good man.

-- 
Boycott USL/Novell for their absurd anti-BSDI lawsuit. | Drew Eckhardt
Condemn Colorado for Amendment Two.                    | drew@cs.Colorado.EDU
Use Linux, the fast, flexible, and free 386 unix       |