source: branches/minix3-book/kernel/i8259.c@ 15

Last change on this file since 15 was 4, checked in by Mattia Monga, 14 years ago

Importazione sorgenti libro

File size: 4.9 KB
RevLine 
[4]1/* This file contains routines for initializing the 8259 interrupt controller:
2 * put_irq_handler: register an interrupt handler
3 * rm_irq_handler: deregister an interrupt handler
4 * intr_handle: handle a hardware interrupt
5 * intr_init: initialize the interrupt controller(s)
6 */
7
8#include "kernel.h"
9#include "proc.h"
10#include <minix/com.h>
11
12#define ICW1_AT 0x11 /* edge triggered, cascade, need ICW4 */
13#define ICW1_PC 0x13 /* edge triggered, no cascade, need ICW4 */
14#define ICW1_PS 0x19 /* level triggered, cascade, need ICW4 */
15#define ICW4_AT_SLAVE 0x01 /* not SFNM, not buffered, normal EOI, 8086 */
16#define ICW4_AT_MASTER 0x05 /* not SFNM, not buffered, normal EOI, 8086 */
17#define ICW4_PC_SLAVE 0x09 /* not SFNM, buffered, normal EOI, 8086 */
18#define ICW4_PC_MASTER 0x0D /* not SFNM, buffered, normal EOI, 8086 */
19
20#define set_vec(nr, addr) ((void)0)
21
22/*===========================================================================*
23 * intr_init *
24 *===========================================================================*/
25PUBLIC void intr_init(mine)
26int mine;
27{
28/* Initialize the 8259s, finishing with all interrupts disabled. This is
29 * only done in protected mode, in real mode we don't touch the 8259s, but
30 * use the BIOS locations instead. The flag "mine" is set if the 8259s are
31 * to be programmed for MINIX, or to be reset to what the BIOS expects.
32 */
33 int i;
34
35 intr_disable();
36
37 /* The AT and newer PS/2 have two interrupt controllers, one master,
38 * one slaved at IRQ 2. (We don't have to deal with the PC that
39 * has just one controller, because it must run in real mode.)
40 */
41 outb(INT_CTL, machine.ps_mca ? ICW1_PS : ICW1_AT);
42 outb(INT_CTLMASK, mine ? IRQ0_VECTOR : BIOS_IRQ0_VEC);
43 /* ICW2 for master */
44 outb(INT_CTLMASK, (1 << CASCADE_IRQ)); /* ICW3 tells slaves */
45 outb(INT_CTLMASK, ICW4_AT_MASTER);
46 outb(INT_CTLMASK, ~(1 << CASCADE_IRQ)); /* IRQ 0-7 mask */
47 outb(INT2_CTL, machine.ps_mca ? ICW1_PS : ICW1_AT);
48 outb(INT2_CTLMASK, mine ? IRQ8_VECTOR : BIOS_IRQ8_VEC);
49 /* ICW2 for slave */
50 outb(INT2_CTLMASK, CASCADE_IRQ); /* ICW3 is slave nr */
51 outb(INT2_CTLMASK, ICW4_AT_SLAVE);
52 outb(INT2_CTLMASK, ~0); /* IRQ 8-15 mask */
53
54 /* Copy the BIOS vectors from the BIOS to the Minix location, so we
55 * can still make BIOS calls without reprogramming the i8259s.
56 */
57 phys_copy(BIOS_VECTOR(0) * 4L, VECTOR(0) * 4L, 8 * 4L);
58}
59
60/*===========================================================================*
61 * put_irq_handler *
62 *===========================================================================*/
63PUBLIC void put_irq_handler(hook, irq, handler)
64irq_hook_t *hook;
65int irq;
66irq_handler_t handler;
67{
68/* Register an interrupt handler. */
69 int id;
70 irq_hook_t **line;
71
72 if (irq < 0 || irq >= NR_IRQ_VECTORS)
73 panic("invalid call to put_irq_handler", irq);
74
75 line = &irq_handlers[irq];
76 id = 1;
77 while (*line != NULL) {
78 if (hook == *line) return; /* extra initialization */
79 line = &(*line)->next;
80 id <<= 1;
81 }
82 if (id == 0) panic("Too many handlers for irq", irq);
83
84 hook->next = NULL;
85 hook->handler = handler;
86 hook->irq = irq;
87 hook->id = id;
88 *line = hook;
89
90 irq_use |= 1 << irq;
91}
92
93/*===========================================================================*
94 * rm_irq_handler *
95 *===========================================================================*/
96PUBLIC void rm_irq_handler(hook)
97irq_hook_t *hook;
98{
99/* Unregister an interrupt handler. */
100 int irq = hook->irq;
101 int id = hook->id;
102 irq_hook_t **line;
103
104 if (irq < 0 || irq >= NR_IRQ_VECTORS)
105 panic("invalid call to rm_irq_handler", irq);
106
107 line = &irq_handlers[irq];
108 while (*line != NULL) {
109 if ((*line)->id == id) {
110 (*line) = (*line)->next;
111 if (! irq_handlers[irq]) irq_use &= ~(1 << irq);
112 return;
113 }
114 line = &(*line)->next;
115 }
116 /* When the handler is not found, normally return here. */
117}
118
119/*===========================================================================*
120 * intr_handle *
121 *===========================================================================*/
122PUBLIC void intr_handle(hook)
123irq_hook_t *hook;
124{
125/* Call the interrupt handlers for an interrupt with the given hook list.
126 * The assembly part of the handler has already masked the IRQ, reenabled the
127 * controller(s) and enabled interrupts.
128 */
129
130 /* Call list of handlers for an IRQ. */
131 while (hook != NULL) {
132 /* For each handler in the list, mark it active by setting its ID bit,
133 * call the function, and unmark it if the function returns true.
134 */
135 irq_actids[hook->irq] |= hook->id;
136 if ((*hook->handler)(hook)) irq_actids[hook->irq] &= ~hook->id;
137 hook = hook->next;
138 }
139
140 /* The assembly code will now disable interrupts, unmask the IRQ if and only
141 * if all active ID bits are cleared, and restart a process.
142 */
143}
Note: See TracBrowser for help on using the repository browser.