johnk@opel.uu.net (John Kennedy) (01/14/90)
This is a description of the way interrupts are masked out and enabled in Sys V/AT. This posting is as a result of mail I've received requesting this information. This is the way I have come to understand the mask tables. This information may not be infallible, so temper it with your own experiences. Thanks to mike@kc5n.UUCP (Mike Barnes), for information that led me to understand how this all works. _____ Whenever the system wishes to enable or disable a group of interrupts, it does so by entering a new spl() level. In V/AT, the levels that are used are 0, 4, 5, 6 and 7. Each level has associated with it an interrupt mask which is used to disable and enable interrupts upon entering that and leaving that level. The specific interrupts are designated by two arrays, named mastbl and slavtbl, corresponding to the masks to be applied to the master interrupt controller (PIC) and slave PIC, respectively. The default settings are: mastbl[0] [1] [2] [3] [4] [5] [6] [7] 00 xx xx xx 41 E1 E3 FF slavtbl[0] [1] [2] [3] [4] [5] [6] [7] 00 xx xx xx 61 61 61 61 The xx's represent a don't care value, as levels 1,2 and 3 are not used (to the best of my knowledge). For each byte of either table, a 1 indicates that an interrupt is disabled, and a 0 represents that the interrupt is enabled. On the master interrupt controller, the interrupts are allocated as: bit [0 = low order bit] bit 0 IRQ0 (Clock) 4 IRQ4 Serial (tty0) 1 IRQ1 Console Keyboard 5 IRQ5 Parallel Port 2 2 IRQ2 Slave PIC 6 IRQ6 Floppy Controller 3 IRQ3 Serial (tty1) 7 IRQ7 Parallel Port 1 On the slave interrupt controller, the interrupts are allocated as: bit bit 0 IRQ8 Real time clock 4 IRQ12 Spare 1 IRQ9 PC/XT IRQ2 5 IRQ13 Math Coprocessor 2 IRQ10 Spare 6 IRQ14 Spare Hard Disk Controller 3 IRQ11 Spare 7 IRQ15 Spare From the 'Adding Devices Drivers' section of TFM, we see that Microport allocates each of the spl() levels as follows: SPL Value Interrupt(s) Disables mastbl slavtbl masked interrupts on: spl0 none none 00 01 spl4 0,6,8,13,14 clock, floppy disk, 41 61 math coproc., hard disk spl5 0,6,8,13,14,5,7 above plus parallel ports E1 61 spl6 0,6,8,13,14,5,7,1 above plus keyboard E3 61 spl7 0,6,8,13,14, above plus serial ports FF 61 5,7,1,3,4,2 and slave PIC The kernel (/unix.lk.hd) that was shipped with my 2.4.0L system had these locations set to: SPL Value Interrupt(s) mastbl slavtbl masked spl0 8,9,10,11,12 00 1F spl4 0,6,8,9,10,11,12,13,14 41 7F spl5 0,6,5,7,8,9,10,11,12,13,14 E1 7F spl6 0,6,5,7,1,8,9,10,11,12,13,14 E3 7F spl7 0,6,5,7,1,3,4,2,8,9,10,11,12,13,14,15 FF FF This is contrary to the documentation, but shows that Microport had liked to keep the unused IRQs 9,10, 11 and 12 disabled some of the time and disable IRQ15 with the serial ports. This is and should be of no consequence, as Microport didn't use the interrupts on the slave PIC. Now, let's assume that you've build a new kernel that uses 5 serial ports. Let's assume that tty0, tty1, tty2, tty3, and tty4 use interrupts 4, 3, 7, 9, and 10, respectively. Let's assume that our serial card has the capability to access these interrupts. In my personal case, I have cut and jumpered cards to use new interrupts. In the case of an 8-bit serial card needing to access IRQs 8-15, jumpers can run to a nearby memory card, or any other containing the extended bus connectors. Notice that tty2 uses IRQ7, which is normally used by the first parallel port. In this example, let's assume the system has no parallel ports. Thus, the interrupt is available for use, but must be enabled when the other serial ports are enabled, and not with the parallel ports. The new, previously spare interrupts must be enabled with the serial interrupts. The new values for the master and slave tables look like: SPL Value Interrupt(s) Disables mastbl slavtbl masked interrupts on: spl0 none none 00 01 spl4 0,6,8,13,14 clock, floppy disk, 41 61 math coproc., hard disk spl5 0,6,8,13,14 *above plus parallel ports 41 61 spl6 0,6,8,13,14,1 above plus keyboard 43 61 spl7 0,6,8,13,14,1, 4,3,7,9,10,2 above plus serial ports DF 67 and slave PIC *(no change, as no parallel ports exist in this example) /etc/patch is used to change the values. The kernel is patched for the above example by: /etc/patch kernelname -b +0 mastbl 0x00 # nothing /etc/patch kernelname -b +0 slavtbl 0x01 # clock timer /etc/patch kernelname -b +4 mastbl 0x41 # + floppy, clock /etc/patch kernelname -b +4 slavtbl 0x61 # + winch, math /etc/patch kernelname -b +5 mastbl 0x41 # + parallel (none) /etc/patch kernelname -b +5 slavtbl 0x61 # /etc/patch kernelname -b +6 mastbl 0x43 # + keyboard /etc/patch kernelname -b +6 slavtbl 0x61 # /etc/patch kernelname -b +7 mastbl 0xdf # + slave pic & int 3, 4, 7 (serial) /etc/patch kernelname -b +7 slavtbl 0x67 # + int 9 & 10 Other combinations are left as an exercise for the reader :-). Before building the kernel, don't forget that /usr/linkkit/cf/master must be edited to reflect what device uses each interrupt and the total count of each kind of device, and /usr/linkkit/cf/dfile.wini must be edited to reflect the total count of each kind of device. Don't forget, too, that any card that allows IRQ2 gets that interrupt serviced by IRQ9 on the software end. The bus line for IRQ2 is rerouted to IRQ9 on the slave PIC, and IRQ2 is unusable on the AT bus. John -- John Kennedy johnk@opel.uu.uunet Second Source, Inc. Annapolis, MD