inp/outp vs in8/out8

I don’t know anything about hardware device I/O, but I’m trying to
learn. The code I’m porting to QRTP from QNX4.2x, uses calls to inp and
outp.

The code defines:

TOGGLE_BASE 0x378
STATUS_BASE 0x379

I guess this is the hardware addresses for the parallel port. (I seem to
remember 2f8 and 3f8 as standard addresses for the serial ports, from
looking at bios settings before).

It then does

status = inp(STATUS_BASE) & STAT_MASK;
if (status & ONLINE)
and so on

and

previous_output = ~previous_output;
outp(TOGGLE_BASE, previous_output);

I’ve read the migration doc’s and I’ve changed the code to do a
ThreadCtl(_NTO_TCTL_IO, 0);

and it says I should add an mmap_device_io() but I am unsure of the
parameters. Should it be
mmap_device_io(1,TOGGLE_BASE); ?

Do I need to do this only once for the whole process at the beginning of
main? Why use two addresses to access this parallel port?

and then it says I should use in8 and out8. They don’t use plain int
parameters anymore. Will the same parameters I use in inp and outp
work?

I’ve changed the outp occurence and it compiles, but I’m now working on
chaning Trigger and Receive (gotta learn how pulses differ from proxies
and how to implemnt) calls that come up in the link of this same
process, so I’m not sure yet if the out8 call is working.

Scott

J. Scott Franko <jsfranko@switch.com> wrote:

I’ve read the migration doc’s and I’ve changed the code to do a
ThreadCtl(_NTO_TCTL_IO, 0);

Good…

and it says I should add an mmap_device_io() but I am unsure of the
parameters. Should it be
mmap_device_io(1,TOGGLE_BASE); ?

Yes, but you should probably map both ports at the same time since
they are right next to each other.

You should also use the uintptr_t that mmap_device_io() returns to
actually pass in to the in*() calls.

Do I need to do this only once for the whole process at the beginning of
main? Why use two addresses to access this parallel port?

Yes… just do this once.

You need two addresses because the port occupies two I/O locations. You
could just get a mmap_device_io() return for the first address, and then
add an offset to it to access the second, providing the size you passed
into mmap_device_io spanned both port locations.

and then it says I should use in8 and out8. They don’t use plain int
parameters anymore. Will the same parameters I use in inp and outp
work?

You should actually use the number returned bu mmap_device_io for the port
location in in* and out*

The reason it’s done this way is so that if you ever port your code to
another processor, all the in and out stuff will just work, even though the
other processors don’t actually have real in and out instructions. On other
platforms, in and out instructions are usually simulated by doing memory
mapped accesses to a special address range. You’ll notice that the numbers
returned by mmap_device_io and in*() and out*() are big enough now to
hold a pointer :slight_smile:

I’ve changed the outp occurence and it compiles, but I’m now working on
chaning Trigger and Receive (gotta learn how pulses differ from proxies
and how to implemnt) calls that come up in the link of this same
process, so I’m not sure yet if the out8 call is working.

Don’t use port numbers directly in in and out calls. Use the number
returned from the mmap_device_io call.

I’ll add an example to the migration guide to make it clearer.

pete@qnx.com wrote:

J. Scott Franko <> jsfranko@switch.com> > wrote:

I’ve read the migration doc’s and I’ve changed the code to do a
ThreadCtl(_NTO_TCTL_IO, 0);

Good…

and it says I should add an mmap_device_io() but I am unsure of the
parameters. Should it be
mmap_device_io(1,TOGGLE_BASE); ?

Yes, but you should probably map both ports at the same time since
they are right next to each other.

You should also use the uintptr_t that mmap_device_io() returns to
actually pass in to the in*() calls.

Do I need to do this only once for the whole process at the beginning of
main? Why use two addresses to access this parallel port?

Yes… just do this once.

You need two addresses because the port occupies two I/O locations. You
could just get a mmap_device_io() return for the first address, and then
add an offset to it to access the second, providing the size you passed
into mmap_device_io spanned both port locations.

and then it says I should use in8 and out8. They don’t use plain int
parameters anymore. Will the same parameters I use in inp and outp
work?

You should actually use the number returned bu mmap_device_io for the port
location in in* and out*

The reason it’s done this way is so that if you ever port your code to
another processor, all the in and out stuff will just work, even though the
other processors don’t actually have real in and out instructions. On other
platforms, in and out instructions are usually simulated by doing memory
mapped accesses to a special address range. You’ll notice that the numbers
returned by mmap_device_io and in*() and out*() are big enough now to
hold a pointer > :slight_smile:

I’ve changed the outp occurence and it compiles, but I’m now working on
chaning Trigger and Receive (gotta learn how pulses differ from proxies
and how to implemnt) calls that come up in the link of this same
process, so I’m not sure yet if the out8 call is working.

Don’t use port numbers directly in in and out calls. Use the number
returned from the mmap_device_io call.

Heres an example of an hw i/o output although note that I’ve wrapped up the
in/out macros into a wrapper class (Reg0_m is just a 16bit private class
member variable)

Am I being paranoid then by mapping the io address in and unmapping it as
part of the function - I noticed that pete said just map it in once in main
or is this down to the individuals taste…


***/
void CNonVolGateArray::ResetExternalModules(void)
{
int port,a;

a=ThreadCtl(_NTO_TCTL_IO,0); // need these two lines here to inform
neutrino that we are going to access something outside of this process’s
address space
port = mmap_device_io(1,NON_VOL_GATE_ARRAY_BASE_ADDR+0); // so we remap the
physical addr into this processes addr space

Reg0_m &= ~EXTERNAL_RESET_BIT;
OIoClass.OutputWord (port, Reg0_m);
munmap_device_io(port,1); // free access to the mapped io area
}


pete@qnx.com wrote in message <8s2atn$3ms$1@nntp.qnx.com>…

J. Scott Franko <> jsfranko@switch.com> > wrote:

I’ve read the migration doc’s and I’ve changed the code to do a
ThreadCtl(_NTO_TCTL_IO, 0);

Good…

and it says I should add an mmap_device_io() but I am unsure of the
parameters. Should it be
mmap_device_io(1,TOGGLE_BASE); ?

Yes, but you should probably map both ports at the same time since
they are right next to each other.

You should also use the uintptr_t that mmap_device_io() returns to
actually pass in to the in*() calls.

Do I need to do this only once for the whole process at the beginning of
main? Why use two addresses to access this parallel port?

Yes… just do this once.

You need two addresses because the port occupies two I/O locations. You
could just get a mmap_device_io() return for the first address, and then
add an offset to it to access the second, providing the size you passed
into mmap_device_io spanned both port locations.

and then it says I should use in8 and out8. They don’t use plain int
parameters anymore. Will the same parameters I use in inp and outp
work?

You should actually use the number returned bu mmap_device_io for the port
location in in* and out*

The reason it’s done this way is so that if you ever port your code to
another processor, all the in and out stuff will just work, even though the
other processors don’t actually have real in and out instructions. On other
platforms, in and out instructions are usually simulated by doing memory
mapped accesses to a special address range. You’ll notice that the numbers
returned by mmap_device_io and in*() and out*() are big enough now to
hold a pointer > :slight_smile:

I’ve changed the outp occurence and it compiles, but I’m now working on
chaning Trigger and Receive (gotta learn how pulses differ from proxies
and how to implemnt) calls that come up in the link of this same
process, so I’m not sure yet if the out8 call is working.

Don’t use port numbers directly in in and out calls. Use the number
returned from the mmap_device_io call.

Sorry - there was a deliberate mistake in that code frag.

As I’m only mapping in 1 byte in mmap_device_io I should have used -
OIoClass.OutputByte (port, Reg0_m);

And Reg0_m is a byte not a 16 bit word…

Ho hum - its still early, I need more caffeine - heres a corrected version:

void CNonVolGateArray::EnableSramOutput(void)
{
int port,a;

a=ThreadCtl(_NTO_TCTL_IO,0); // need these two lines here to inform
neutrino that we are going to access something outside of this process’s
address space
port = mmap_device_io(sizeof(Reg0_m),NON_VOL_GATE_ARRAY_BASE_ADDR+0);

Reg0_m |= SRAM_OUTPUT_ENABLE_BIT; // set the required bit
OIoClass.OutputByte (port, Reg0_m);
munmap_device_io(port,1); // free access to the mapped io area
}


My question still stands though - if I have to access loads of different
physical locations (i/o mapped registers on a gate array in my case) is it
better to do what I’ve done here or just ‘map them all in’ in main as pete
suggested? Is what I’ve done here ok?

Jim Atkins <jamesa@tsd.serco.com> wrote:

My question still stands though - if I have to access loads of different
physical locations (i/o mapped registers on a gate array in my case) is it
better to do what I’ve done here or just ‘map them all in’ in main as pete
suggested? Is what I’ve done here ok?

It really depends on how paranoid you want to be.

If you `trust’ all the code in all the othe modules you’re going to link
together, then you should really just do it all once (including the
ThreadCtl). If you’re doing a library that other people could link in and
use, you may want to up the paranoia level. You might do the mmap in an init
routine, and then stuff the result into a private member of your class or
something.

It seems to me that QNX4 had a lot more example code at the end of each page that
described a function. There seem to be less of that in the QRTP help files. And
in the tutorial sections, some pages describe multiple ways of doing things, but
only show and example code section for one of the ways. I learn well by reading
a turorial section and then seeing example code. I’m hoping you will added an
example code section to the end of all function descriptions and liberaly spread
through the tutorial sections. What’s there is good, but I want more, more,
more! ;O)

Scott

Steven Dufresne wrote:

I’ll add an example to the migration guide to make it clearer.

pete@qnx.com > wrote:
J. Scott Franko <> jsfranko@switch.com> > wrote:

I’ve read the migration doc’s and I’ve changed the code to do a
ThreadCtl(_NTO_TCTL_IO, 0);

Good…

and it says I should add an mmap_device_io() but I am unsure of the
parameters. Should it be
mmap_device_io(1,TOGGLE_BASE); ?

Yes, but you should probably map both ports at the same time since
they are right next to each other.

You should also use the uintptr_t that mmap_device_io() returns to
actually pass in to the in*() calls.

Do I need to do this only once for the whole process at the beginning of
main? Why use two addresses to access this parallel port?

Yes… just do this once.

You need two addresses because the port occupies two I/O locations. You
could just get a mmap_device_io() return for the first address, and then
add an offset to it to access the second, providing the size you passed
into mmap_device_io spanned both port locations.

and then it says I should use in8 and out8. They don’t use plain int
parameters anymore. Will the same parameters I use in inp and outp
work?

You should actually use the number returned bu mmap_device_io for the port
location in in* and out*

The reason it’s done this way is so that if you ever port your code to
another processor, all the in and out stuff will just work, even though the
other processors don’t actually have real in and out instructions. On other
platforms, in and out instructions are usually simulated by doing memory
mapped accesses to a special address range. You’ll notice that the numbers
returned by mmap_device_io and in*() and out*() are big enough now to
hold a pointer > :slight_smile:

I’ve changed the outp occurence and it compiles, but I’m now working on
chaning Trigger and Receive (gotta learn how pulses differ from proxies
and how to implemnt) calls that come up in the link of this same
process, so I’m not sure yet if the out8 call is working.

Don’t use port numbers directly in in and out calls. Use the number
returned from the mmap_device_io call.

Shouldn’t you be using and uintptr_t type for port instead of an int? Or is
that type the same as an int. By the way, uintptr_t is not in any of the
includes that the function descriptions in helpviewer say to use. I got an
undefined reference when I built my code. I had to include <inttypes.h>.

Jim Atkins wrote:

Heres an example of an hw i/o output although note that I’ve wrapped up the
in/out macros into a wrapper class (Reg0_m is just a 16bit private class
member variable)

Am I being paranoid then by mapping the io address in and unmapping it as
part of the function - I noticed that pete said just map it in once in main
or is this down to the individuals taste…


***/
void CNonVolGateArray::ResetExternalModules(void)
{
int port,a;

a=ThreadCtl(_NTO_TCTL_IO,0); // need these two lines here to inform
neutrino that we are going to access something outside of this process’s
address space
port = mmap_device_io(1,NON_VOL_GATE_ARRAY_BASE_ADDR+0); // so we remap the
physical addr into this processes addr space

Reg0_m &= ~EXTERNAL_RESET_BIT;
OIoClass.OutputWord (port, Reg0_m);
munmap_device_io(port,1); // free access to the mapped io area
}

pete@qnx.com > wrote in message <8s2atn$3ms$> 1@nntp.qnx.com> >…
J. Scott Franko <> jsfranko@switch.com> > wrote:

I’ve read the migration doc’s and I’ve changed the code to do a
ThreadCtl(_NTO_TCTL_IO, 0);

Good…

and it says I should add an mmap_device_io() but I am unsure of the
parameters. Should it be
mmap_device_io(1,TOGGLE_BASE); ?

Yes, but you should probably map both ports at the same time since
they are right next to each other.

You should also use the uintptr_t that mmap_device_io() returns to
actually pass in to the in*() calls.

Do I need to do this only once for the whole process at the beginning of
main? Why use two addresses to access this parallel port?

Yes… just do this once.

You need two addresses because the port occupies two I/O locations. You
could just get a mmap_device_io() return for the first address, and then
add an offset to it to access the second, providing the size you passed
into mmap_device_io spanned both port locations.

and then it says I should use in8 and out8. They don’t use plain int
parameters anymore. Will the same parameters I use in inp and outp
work?

You should actually use the number returned bu mmap_device_io for the port
location in in* and out*

The reason it’s done this way is so that if you ever port your code to
another processor, all the in and out stuff will just work, even though the
other processors don’t actually have real in and out instructions. On other
platforms, in and out instructions are usually simulated by doing memory
mapped accesses to a special address range. You’ll notice that the numbers
returned by mmap_device_io and in*() and out*() are big enough now to
hold a pointer > :slight_smile:

I’ve changed the outp occurence and it compiles, but I’m now working on
chaning Trigger and Receive (gotta learn how pulses differ from proxies
and how to implemnt) calls that come up in the link of this same
process, so I’m not sure yet if the out8 call is working.

Don’t use port numbers directly in in and out calls. Use the number
returned from the mmap_device_io call.

Jim Atkins <jamesa@tsd.serco.com> wrote:

Am I being paranoid then by mapping the io address in and unmapping it as
part of the function - I noticed that pete said just map it in once in main
or is this down to the individuals taste…

That this is really, really going to slow down port access on
non-X86 systems. Don’t do it if you’re going to be continually banging on
the ports.


Brian Stecher (bstecher@qnx.com) QNX Software Systems, Ltd.
phone: +1 (613) 591-0931 (voice) 175 Terence Matthews Cr.
+1 (613) 591-3579 (fax) Kanata, Ontario, Canada K2M 1W8

Thanks - I won’t be so paranoid - I’ll just map in the areas I’m going to be
fiddling with on startup…

and yes I should use uintptr_t instead of int…

Thanks for the input - see I said I needed more caffeine :slight_smile:

Brian Stecher wrote in message <8s4h4e$6b4$1@nntp.qnx.com>…

Jim Atkins <> jamesa@tsd.serco.com> > wrote:
Am I being paranoid then by mapping the io address in and unmapping it as
part of the function - I noticed that pete said just map it in once in
main
or is this down to the individuals taste…

That this is really, really going to slow down port access on
non-X86 systems. Don’t do it if you’re going to be continually banging on
the ports.


Brian Stecher (> bstecher@qnx.com> ) QNX Software Systems, Ltd.
phone: +1 (613) 591-0931 (voice) 175 Terence Matthews Cr.
+1 (613) 591-3579 (fax) Kanata, Ontario, Canada K2M 1W8

J. Scott Franko <jsfranko@switch.com> wrote:

It seems to me that QNX4 had a lot more example code at the end of each page that
described a function. There seem to be less of that in the QRTP help files.

It will get more complete over time. QRTP has added a LOT of functions
to the library, and the docs department is having a hard time just getting
correct descriptions for the different functions. As they get time, and
as they get examples, more examples will be included.

-David

That’s good to hear! I look forward to that because as an up and comer on QNX, and
Unix in general, I’ve got so much to learn. The examples really help.

Scott

David Gibbs wrote:

J. Scott Franko <> jsfranko@switch.com> > wrote:
It seems to me that QNX4 had a lot more example code at the end of each page that
described a function. There seem to be less of that in the QRTP help files.

It will get more complete over time. QRTP has added a LOT of functions
to the library, and the docs department is having a hard time just getting
correct descriptions for the different functions. As they get time, and
as they get examples, more examples will be included.

-David

I’m just learning this stuff,

So what would I if I wanted to map a series of bytes.

a = ThreadCtl(_NTO_TCTL_IO,0);
port = mmap_device_io(sizeof(byte) * 16, BASE_IO);

//Now I’ve got some memory
How do I write to just the 3rd Byte? Can I do something like this…
out8(mybyte, port + 2);

\

//***********************************************************************
//Chris McCann |The woods are lovely, dark and deep. //
//cst98037Acamosun.bc.ca |But I have promises to keep, //
//cwmccannAhome.com |And miles to go before I sleep, //
// |And miles to go before I sleep. //
// | R.Frost //
//***********************************************************************

Is that the cause of appear same ramdom number when I write and read the
parallel port addres without mmap_device_io() ??

“Ricardo Az” <ricardoaz74@hotmail.com> wrote in message
news:a50a9k$kds$1@inn.qnx.com

Is that the cause of appear same ramdom number when I write and read the
parallel port addres without mmap_device_io() ??

Random number on the parallel port you mean?

On x86 mmap_device_io currently does nothing.

Make sure devc-par isn’t running (it handles the parallel port)

Previously, Mario Charest wrote in qdn.public.qnxrtp.os:

On x86 mmap_device_io currently does nothing.

Are you sure Mario. The 386 architecture can protect I/O
space per task. I thought that QSSL had implemented this
in QNX 6.


Mitchell Schoenbrun --------- maschoen@pobox.com

Mitchell Schoenbrun <maschoen@pobox.com> wrote:

Previously, Mario Charest wrote in qdn.public.qnxrtp.os:

On x86 mmap_device_io currently does nothing.

Are you sure Mario. The 386 architecture can protect I/O
space per task. I thought that QSSL had implemented this
in QNX 6.

That is what the ThreadCtl() is for (privs). The reason that mmap_device_io()
does nothing is that the x86 has instructions for doing I/O and so it
doesn’t need to map the device into the virtual address space. However,
using mmap_device_io() means your code will be portable to CPU systems
that don’t have dedicated inp/outp instructions.

chris


Chris McKillop <cdm@qnx.com> “The faster I go, the behinder I get.”
Software Engineer, QSSL – Lewis Carroll –
http://qnx.wox.org/

“Mitchell Schoenbrun” <maschoen@pobox.com> wrote in message
news:Voyager.020220182129.198C@schoenbrun.com

Previously, Mario Charest wrote in qdn.public.qnxrtp.os:

On x86 mmap_device_io currently does nothing.

Are you sure Mario.

Yes :wink:

The 386 architecture can protect I/O
space per task. I thought that QSSL had implemented this
in QNX 6.


Mitchell Schoenbrun --------- > maschoen@pobox.com

“Mario Charest” <goto@nothingness.com> wrote in message
news:a531c0$kbe$1@inn.qnx.com

“Mitchell Schoenbrun” <> maschoen@pobox.com> > wrote in message
news:> Voyager.020220182129.198C@schoenbrun.com> …
Previously, Mario Charest wrote in qdn.public.qnxrtp.os:

On x86 mmap_device_io currently does nothing.

Are you sure Mario.

Yes > :wink:

I’m always hoping one day they will use this to keep a record
of what process is using what io space. Something like “pidin io” :wink:

Of course on x86 that info wouldn’t be reliable because not everybody
use mmap_device_io()

The 386 architecture can protect I/O
space per task. I thought that QSSL had implemented this
in QNX 6.


Mitchell Schoenbrun --------- > maschoen@pobox.com

\

Previously, Mario Charest wrote in qdn.public.qnxrtp.os:

Of course on x86 that info wouldn’t be reliable because not everybody
use mmap_device_io()

Well, if the I/O map feature of 386x was implemented, everyone would
have to use mmap_device_io().

Mitchell Schoenbrun --------- maschoen@pobox.com