Skip to content
Snippets Groups Projects
picirq.c 2.3 KiB
Newer Older
rsc's avatar
rsc committed
// Intel 8259A programmable interrupt controllers.

rtm's avatar
rtm committed
#include "types.h"
#include "x86.h"
kaashoek's avatar
kaashoek committed
#include "traps.h"
rtm's avatar
rtm committed

rsc's avatar
rsc committed
// I/O Addresses of the two programmable interrupt controllers
#define IO_PIC1         0x20    // Master (IRQs 0-7)
#define IO_PIC2         0xA0    // Slave (IRQs 8-15)
kaashoek's avatar
kaashoek committed

#define IRQ_SLAVE       2       // IRQ at which slave connects to master
kaashoek's avatar
kaashoek committed

rtm's avatar
rtm committed
// Current IRQ mask.
// Initial IRQ mask has interrupt 2 enabled (for slave 8259A).
rsc's avatar
rsc committed
static ushort irqmask = 0xFFFF & ~(1<<IRQ_SLAVE);
kaashoek's avatar
kaashoek committed

rsc's avatar
rsc committed
static void
picsetmask(ushort mask)
kaashoek's avatar
kaashoek committed
{
rsc's avatar
rsc committed
  irqmask = mask;
  outb(IO_PIC1+1, mask);
  outb(IO_PIC2+1, mask >> 8);
kaashoek's avatar
kaashoek committed
}
rtm's avatar
rtm committed

rsc's avatar
rsc committed
void
picenable(int irq)
rsc's avatar
rsc committed
{
  picsetmask(irqmask & ~(1<<irq));
rsc's avatar
rsc committed
}

rsc's avatar
rsc committed
// Initialize the 8259A interrupt controllers.
rtm's avatar
rtm committed
void
picinit(void)
rtm's avatar
rtm committed
{
kaashoek's avatar
kaashoek committed
  // mask all interrupts
  outb(IO_PIC1+1, 0xFF);
  outb(IO_PIC2+1, 0xFF);

  // Set up master (8259A-1)

  // ICW1:  0001g0hi
  //    g:  0 = edge triggering, 1 = level triggering
  //    h:  0 = cascaded PICs, 1 = master only
  //    i:  0 = no ICW4, 1 = ICW4 required
  outb(IO_PIC1, 0x11);

  // ICW2:  Vector offset
Russ Cox's avatar
Russ Cox committed
  outb(IO_PIC1+1, T_IRQ0);
kaashoek's avatar
kaashoek committed

rsc's avatar
rsc committed
  // ICW3:  (master PIC) bit mask of IR lines connected to slaves
  //        (slave PIC) 3-bit # of slave's connection to master
kaashoek's avatar
kaashoek committed
  outb(IO_PIC1+1, 1<<IRQ_SLAVE);

  // ICW4:  000nbmap
  //    n:  1 = special fully nested mode
  //    b:  1 = buffered mode
  //    m:  0 = slave PIC, 1 = master PIC
  //      (ignored when b is 0, as the master/slave role
  //      can be hardwired).
kaashoek's avatar
kaashoek committed
  //    a:  1 = Automatic EOI mode
  //    p:  0 = MCS-80/85 mode, 1 = intel x86 mode
  outb(IO_PIC1+1, 0x3);

  // Set up slave (8259A-2)
  outb(IO_PIC2, 0x11);                  // ICW1
Russ Cox's avatar
Russ Cox committed
  outb(IO_PIC2+1, T_IRQ0 + 8);      // ICW2
  outb(IO_PIC2+1, IRQ_SLAVE);           // ICW3
kaashoek's avatar
kaashoek committed
  // NB Automatic EOI mode doesn't tend to work on the slave.
  // Linux source code says it's "to be investigated".
  outb(IO_PIC2+1, 0x3);                 // ICW4
kaashoek's avatar
kaashoek committed

  // OCW3:  0ef01prs
  //   ef:  0x = NOP, 10 = clear specific mask, 11 = set specific mask
  //    p:  0 = no polling, 1 = polling mode
  //   rs:  0x = NOP, 10 = read IRR, 11 = read ISR
rsc's avatar
rsc committed
  outb(IO_PIC1, 0x68);             // clear specific mask
  outb(IO_PIC1, 0x0a);             // read IRR by default
kaashoek's avatar
kaashoek committed

rsc's avatar
rsc committed
  outb(IO_PIC2, 0x68);             // OCW3
  outb(IO_PIC2, 0x0a);             // OCW3
kaashoek's avatar
kaashoek committed

rsc's avatar
rsc committed
  if(irqmask != 0xFFFF)
    picsetmask(irqmask);
rtm's avatar
rtm committed
}