views:

542

answers:

3

I'm following several tutorials and references trying to get my kernel set up, and I've come across voodoo code in a tutorial that isn't explained at all. Its code that I'm told maps the 16 IRQs (0-15) to ISR locations 32-47:

void irq_remap(void)
{
    outportb(0x20, 0x11);
    outportb(0xA0, 0x11);
    outportb(0x21, 0x20);
    outportb(0xA1, 0x28);
    outportb(0x21, 0x04);
    outportb(0xA1, 0x02);
    outportb(0x21, 0x01);
    outportb(0xA1, 0x01);
    outportb(0x21, 0x0);
    outportb(0xA1, 0x0);
}

The code for outportb() is as follows, but I already have a clear grasp of what its doing:

void outPortB(unsigned short port, unsigned char data)
{
    __asm__ __volatile__ ("outb %1, %0" : : "dN" (port), "a" (data));
}

I should mention that this is on x86 architecture in protected mode. This code works fine, and I understand what it does, but I don't understand how on earth it does it. Can someone explain to me what's going on here, so that in case I need to expand on this I will know what I'm doing somewhat?

Thanks

+5  A: 

outb and similar write to hardware IO ports. Basically, there are 2 primary options for communicating with a device. You can have the device mapped to memory or IO ports.

As for how this code works, i'll comment it for you:

IWC stands for "Initialization Commands Words"

outportb(0x20, 0x11); /* write ICW1 to PICM, we are gonna write commands to PICM */
outportb(0xA0, 0x11); /* write ICW1 to PICS, we are gonna write commands to PICS */

outportb(0x21, 0x20); /* remap PICM to 0x20 (32 decimal) */
outportb(0xA1, 0x28); /* remap PICS to 0x28 (40 decimal) */

outportb(0x21, 0x04); /* IRQ2 -> connection to slave */ 
outportb(0xA1, 0x02);

outportb(0x21, 0x01); /* write ICW4 to PICM, we are gonna write commands to PICM */
outportb(0xA1, 0x01); /* write ICW4 to PICS, we are gonna write commands to PICS */

outportb(0x21, 0x0); /* enable all IRQs on PICM */
outportb(0xA1, 0x0); /* enable all IRQs on PICS */

hope this helps

Welcome to the world of OS dev :) I also recommend that you visit: http://forum.osdev.org/, it is an invaluable resource for a new hobby OS developer.

Evan Teran
Wow, that's exactly what I needed. Thanks bunches!
Nicholas Flynt
A: 

http://www.faqs.org/docs/Linux-mini/IO-Port-Programming.html

HTH

plan9assembler
your link refers to writing code which runs in another operating system, the context of the question was in writing your OWN operating system.
Evan Teran
A: 

The simple answer is that in protected mode the interrupts used by the 1st Programmable Interrupt Controller are protected mode exceptions, which means that they have to be remapped.

The happy answer is that only the first PIC needs to be remapped ( the remapping of the second is only for convenience since it begins at int 70h). Here's a quote from the original AT BIOS.

INTA00    equ  020h        ; 8259 port
INTA01    equ  021h        ; 8259 port
INTB00    equ  0A0h        ; 2nd 8259
INTB01    equ  0A1h
INT_TYPE  equ  070h        ; start of 8259 interrupt table location

;---------------------------------------------------------
;    re-initialize the 8259 interrupt #1 controller chip :
;---------------------------------------------------------
  mov  al, 11h             ; icw1 - edge, master, icw4
  out  INTA00,al
  jmp  $+2                 ; wait state for i/o
  mov  al, 8               ; setup icw2 - int type 8 (8-f)
  out  INTA01, al
  jmp  $+2
  mov  al, 4               ; setup icw3 - master lv 2
  out  INTA01, al
  jmp  $+2
  mov  al, 1               ; setup icw4 - master, 8086 mode
  out  INTA01, al
  jmp  $+2
  mov  al, 0FFh            ; mask all ints. off
  out  INTA01, al          ; (video routine enables interrupts)
;---------------------------------------------------------
;    re-initialize the 8259 interrupt #2 controller chip  :
;---------------------------------------------------------
  mov  al, 11h             ; icw1 - edge, slave icw4
  out  INTB00, al
  jmp  $+2
  mov  al, INT_TYPE        ; setup icw2 - int type 70 (70-7f)
  out  INTB01, al
  mov  al, 2               ; setup icw3 - slave lv 2
  jmp  $+2
  out  INTB01, al
  jmp  $+2
  mov  al, 1               ; setup icw4 - 8086 mode, slave
  out  INTB01, al
  jmp  $+2
  mov  al, 0FFh            ; mask all ints. off
  out  INTB01, al
;--------------------------------------------------------------------------------

Technical Reference AT BIOS (c) 1984 IBM

Note:

The jmp $+2 ; wait state for i/o is not required on a current PC.

The icw1 clears the interrupt mask register, which enables the interrupts on that PIC.

The 8259A chip is long since gone but the programming interface is still used. 8259A Programmable Interrupt Controller

Mike Gonta