Page 1 of 1

x86 - 16bit and 32bit IO port accesses

Posted: Sat Apr 29, 2017 9:43 am
by Mario92
Hello,

I need a short clarification, of how multibyte IO port accesses are handled on hardware level.

What does an

Code: Select all

outw(port, data);
do exactly (assuming data is an 16 bit variable)?

1.)

Code: Select all

outb(port, LOBYTE(data));
outb(port, HIBYTE(data));
2.)

Code: Select all

outb(port, LOBYTE(data));
outb(port+1, HIBYTE(data));
3.) Or does every single IO port has it's own size (0x70 is byte; 0xCF8 is dword and 0xCF9 to 0xCFB do not exist or maybe are anything completly different; ...) and it depends on the hardware connected to an IO port.

To understand the behaviour, I tried to read an word from port 0x70, assuming it will return the CMOS address (0x70) in AL and CMOS data (0x71) in AH but it returned 0xFFFF. (Of couse I set the CMOS address to a valid value before).

So I think 1.) and 2.) are wrong. But this differs from the text I read in the Intel manuals:
Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 1: Basic Architecture, 16.3 I/O ADDRESS SPACE, page 16-1 wrote:Any two consecutive 8-bit ports can be treated as a 16-bit port, and any four consecutive ports can be a 32-bit port. In this manner, the processor can transfer 8, 16, or 32 bits to or from a device in the I/O address space. Like words in memory, 16-bit ports should be aligned to even addresses (0, 2, 4, ...) so that all 16 bits can be transferred in a single bus cycle. Likewise, 32-bit ports should be aligned to addresses that are multiples of four (0, 4, 8, ...). The processor supports data transfers to unaligned ports, but there is a performance penalty because one or more
extra bus cycle must be used.

Re: x86 - 16bit and 32bit IO port accesses

Posted: Sat Apr 29, 2017 10:07 am
by iansjack
I think your quote from the Intel manual answers your question.

Re: x86 - 16bit and 32bit IO port accesses

Posted: Sat Apr 29, 2017 10:30 am
by Mario92
That is what I would expect.

But why an "in ax, 0x70" does return 0xFFFF instead of the CMOS register and data in Bochs and VirtualBox? VirtualPC returns the CMOS register in AX with the high byte cleared.

The reason I'm asking is because I'm playing around with ATA PIO at the moment and instead of reading the sector with "rep insw" I try to read with "rep insb", but this does not work. Bochs gives me the message "read from port 0x01f0 with len 1 returns 0xff".

My understanding from the Intel manual is that an "rep insw" would copy one byte of the sector into memory (0x1F0), then the error byte (0x1F1), then the next byte of the sector, and so on.

Re: x86 - 16bit and 32bit IO port accesses

Posted: Sat Apr 29, 2017 11:41 am
by Korona
The Intel SDM talks about I/O addresses here; it does not specify how devices react to I/O reads/writes. When you do an {in,out}{b,w,l} the CPU posts a read/write of a certain size on its I/O bus (i.e. it submits a transaction to the PCI bus). Devices that listen on this bus may or may not respond to a 16-bit operation in the same way they respond to two consecutive 8-bit operations. They might even map an 8-bit and a 16-bit register to the same I/O address and use the operation size to distinguish those registers. This is also true for memory mapped I/O.

Re: x86 - 16bit and 32bit IO port accesses

Posted: Sun Apr 30, 2017 4:06 pm
by Geri
the 2. the formula also applies on 32 bit. also applies on IN and OUT. but its basically pretty much an unpredictable behaviour if you call it on ports those are expecting to be called on 8, 16 or 32 bit (you will get either the expected value on the &255 range, the rest is the same value, or 0, or garbage, or the whole result is garbage depending on the hardware).