Interrupt Controller Ports

  Ports 20H-21H are decoded by the PC's 8259A Interrupt Controller chip.
  This controller is initialized by the BIOS and there is rarely any need to
  perform I/O to these ports in application programs.

  The only common exception is seen when a program intercepts an IRQ
  interrupt (INT 08H-0fH) and does not pass control on to the normal INT
  handler.  For instance, when a TSR traps a keystroke via INT 09H, you may
  need to send an "End-of-Interrupt" to the 8259.  In most cases, it is wise
  to simply pass control down the line to the original interrupt handler and
  let it handle such housekeeping chores.

  In the following, the ICWs are Initialization Control Words.  These are
  output in a particular order during system startup by the BIOS.  The OCWs
  are Operation Control Words which may be output by IRQ handlers.

Port  Description
▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
 20H  ICW1  First control word initialization sequence
      ╓7┬6┬5┬4┬3┬2┬1┬0╖
      ║0 0 0│1│ │ │ │ ║
      ╙─┴─┴─┴╥┴╥┴╥┴╥┴╥╜ bits mask
             ║ ║ ║ ║ ╚═►  0:  01H (IC4) 1=init sequences will include ICW4
             ║ ║ ║ ╚═══►  1:  02H (SNGL) 0=cascaded ctrlrs; 1=single ctrlr
             ║ ║ ╚═════►  2:  04H (ADI) not used; set to 0 on PC
             ║ ╚═══════►  3:  08H (LTIM) 0=edge-triggered; 1=level-triggered
             ╚═════════►  4:  10H must be 1 (indicates this is ICW1)

 21H  ICW2 Second control word in initialization sequence
      ╓7┬6┬5┬4┬3┬2┬1┬0╖
      ║         │0 0 0║
      ╙─┴─┴─┴─┴─┴─┴─┴─╜ bits mask
       └───╥───┘
           ╚══════════► 3-7: f8H  high-order bits of interrupt table addr

 21H  ICW3 Third control word in initialization sequence; not actually
           used since bit 4 is set in ICW1.

 21H  ICW4  Fourth control word initialization sequence (actually 3rd in PC)
      ╓7┬6┬5┬4┬3┬2┬1┬0╖
      ║0 0 0│1│ │ │ │ ║
      ╙─┴─┴─┴╥┴╥┴╥┴╥┴╥╜ bits mask
             ║ ║ ║ ║ ╚═►  0:  01H (uPM)  1=PC/8088 mode
             ║ ║ ║ ╚═══►  1:  02H (AEIO) 1=automatic EOI
             ║ ║ ║                        0=must send EOI at end of int
             ║ ║ ╚═════►  2:  04H (M/S)  0=master mode; 1=slave/cascade mode
             ║ ╚═══════►  3:  08H (BUF)  1=this is a buffered bus
             ╚═════════►  4:  10H (SFNM) 1=ctrlrs are nested in this system
──── ───────────────────────────────────────────────────────────────────────
 21H  OCW1  Read/Write: Get/Set Interrupt Mask
            Each bit corresponds to an IRQ; a 1-enables that IRQ and a
            0 masks it.

 20H  OCW2  Write: Change IRQ priority; set EOI mode
      ╓7┬6┬5┬4┬3┬2┬1┬0╖
      ║ cmd │0 0│level║
      ╙─┴─┴─┴─┴─┴─┴─┴─╜ bits mask
       └─╥─┘     ╚═══╩═►  0:  07H specifies level (0-7) to be acted upon
         ║                        by command in bits 5-7
         ╚═════════════►  4:  e0H one of the commands:
                                  000 = rotate in automatic EOI (clear)
                                  001 = non-specific End Of Interrupt
                                  010 = no operation
                                  011 = specific End Of Interrupt
                                  100 = rotate in automatic EOI (set)
                                  101 = rotate on non-specific EOI
                                  110 = set priority
                                  111 = rotate on specific EOI command
      Note: The command most commonly sent is 20H to port 20H (that is, the
            non-specific End of Interrupt command).  You would use this
            after assuming control of an IRQ such as INT 09H (kybd int).

 20H  OCW3  Write: Select Status Read Mode
      ╓7┬6┬5┬4┬3┬2┬1┬0╖
      ║0│   │0 1│ │rmd║
      ╙─┴─┴─┴─┴─┴╥┴─┴─╜ bits mask
         └╥┘     ║  ╚═╩═►0-1:  03H selects register read mode:
          ║      ║                 00=nop; 01=nop
          ║      ║                 10=read IR register on next read cmd
          ║      ║                 11=read IS register on next read cmd
          ║      ╚══════►  2:  04H 1=poll command; 0=no poll command
          ╚═════════════►5-6:  60H special mask mode:
                                   00=nop; 01=nop
                                   10=reset special mask
                                   11=set special mask

 20H or
 21H Read: A read of either of these ports returns the status of the
           controller.

See Also: I/O Port Map
                                    -♦-