Low level I/O access using outb and inb
Asked Answered
P

3

7

i'm having hard time trying to understand how interrupts work.

the code below initialize the Programmable Interrupt Controller

  #define PIC0_CTRL 0x20    /* Master PIC control register address. */
  #define PIC0_DATA 0x21    /* Master PIC data register address. */

  /* Mask all interrupts*/
  outb (PIC0_DATA, 0xff);

  /* Initialize master. */
  outb (PIC0_CTRL, 0x11); /* ICW1: single mode, edge triggered, expect ICW4. */
  outb (PIC0_DATA, 0x20); /* ICW2: line IR0...7 -> irq 0x20...0x27. */
  outb (PIC0_DATA, 0x04); /* ICW3: slave PIC on line IR2. */
  outb (PIC0_DATA, 0x01); /* ICW4: 8086 mode, normal EOI, non-buffered. */

  /* Unmask all interrupts. */
  outb (PIC0_DATA, 0x00);

can someone explain to me how it works:

-the role of outb (i didn't understand the linux man)

-the addresses and their meaning

another unrelated question,i read that outb and inb are for port-mapped I/O, can we use memory-mapped I/o for doing Input/output communication?

thanks.

Pressmark answered 22/1, 2012 at 11:9 Comment(2)
For hardware which is controlled by memory mapped IO (which the PIC is not) you can of course do memory mapped IO.Gilding
The 8086 inherited these instructions from its predecessors 8080 and 8085, where a separate I/O space was very useful in order not to waste any of the 64k memory address space.Pictogram
I
10

outb() writes the byte specified by its second argument to the I/O port specified by its first argument. In this context, a "port" is a means for the CPU to communication with another chip.

The specific C code that you present relates to the 8259A Programmable Interrupt Controller (PIC).

You can read about the PIC here and here.

If that doesn't provide enough details to understand the commands and the bit masks, you could always refer to the chip's datasheet.

Infectious answered 22/1, 2012 at 11:18 Comment(1)
according to man7.org outb, the port is the second argument and the value is the first argument. But this is incongruent with the OP's code snippet above where these two appears to be switched around. What gives?Doone
T
1

Device specific code is best read in conjunction with the corresponding datasheet. For example, the "8259A Programmable Interrupt Controller" datasheet (http://pdos.csail.mit.edu/6.828/2005/readings/hardware/8259A.pdf) clearly (but concisely) explains almost everything.

However, this datasheet will only explain how the chip can be used (in any system), and won't explain how the chip is used in a specific system (e.g. in "PC compatible" 80x86 systems). For that you need to rely on "implied de facto standards" (as a lot of the features of the PIC chips aren't used on "PC compatible" 80x86 systems, and may not be supported on modern/integrated chipsets).

Normally (for historical reasons) the PIC chip's IRQs are mapped to interrupts in a strange/bad way. For example, IRQ 0 is mapped to interrupt 8 and conflicts with the CPU's double fault exception. The specific code you've posted remaps the PIC chips so that IRQ0 is mapped to interrupt 0x20 (and IRQ1 to interrupt 0x21, ..., IRQ 15 mapped to IRQ 0x2F). It's something an OS typically does to avoid the conflicts (e.g. so that each interrupt is used for an IRQ or an exception and never both).

To understand "outb()", look at the "OUT" instruction in Intel's manuals. It's like there's 2 address spaces - one for normal physical addresses and a completely separate one for IO ports, where normal instructions (indirectly) access normal physical memory; and the IO port instructions (IN, OUT, INSB/W/D, OUTSB/W/D) access the separate "IO address space".

Tremble answered 22/1, 2012 at 11:32 Comment(0)
M
1

The traditional 8088/86 had/has a memory control signal that is essentially another address bit tied directly to the instruction. The control signal separating the accesses into I/O and Memory, creating two separate address spaces. Not unlike CS, DS, etc creating separate memory spaces inside the chip (before hitting the external memory space). Other processor families use what is called memory mapped I/O.

These days the memory controllers/system is chopped up inside and outside the chip in all different ways, sometimes for example with many control signals that indicate instruction vs data, cache line fills, write through vs write back, etc. To save on external circuitry the memory mapping happens inside the chip and for example dedicated rom interfaces, separate from ram, etc are found on the edge, far more complicated and separate than I/O space vs Memory space of the old 8088/86.

the out and in instruction and a few family members change whether you are doing an I/O access or memory access, and traditinally the interrupt controller was a chip that decoded the memory bus looking for I/O access with the address allocated for that device. Decades of reverse compatibility later and you have the present code you are looking at.

If you really want to understand it you need to find the datasheets for the device that contains the interrupt controller, likely to be combined with a bunch of other logic on a big support chip. Other datasheets may be required as well.

Muscadel answered 22/1, 2012 at 14:51 Comment(3)
sorry,i don't get it, does this mean that x86 use port mapped rather than memory mapped access?Pressmark
Yes, I am trying to explain what I/O mapped vs memory mapped means, it traditionally, for x86, means a single control line. Other architectures used one or more of the address bits to do the same thing. very little difference other than x86 that control signal was tied to special instructions.Muscadel
pci added to the complication by allowing some items to be addressable in either address space. sticking with in/out possibly makes it easier to control and virtualize compared to memory. There is an IOPM I/O protection map, I think per VM (in this case even a simple app on a linux machine) you have a separate IOPM. Look up the giveio driver for windows to learn a little more about this and how to get around it.Muscadel

© 2022 - 2024 — McMap. All rights reserved.