📄 i8259.c
字号:
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/kernel/i8259.c
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
07600 /* This file contains routines for initializing the 8259 interrupt controller:
07601 * get_irq_handler: address of handler for a given interrupt
07602 * put_irq_handler: register an interrupt handler
07603 * intr_init: initialize the interrupt controller(s)
07604 */
07605
07606 #include "kernel.h"
07607
07608 #define ICW1_AT 0x11 /* edge triggered, cascade, need ICW4 */
07609 #define ICW1_PC 0x13 /* edge triggered, no cascade, need ICW4 */
07610 #define ICW1_PS 0x19 /* level triggered, cascade, need ICW4 */
07611 #define ICW4_AT 0x01 /* not SFNM, not buffered, normal EOI, 8086 */
07612 #define ICW4_PC 0x09 /* not SFNM, buffered, normal EOI, 8086 */
07613
07614 FORWARD _PROTOTYPE( int spurious_irq, (int irq) );
07615
07616 #define set_vec(nr, addr) ((void)0) /* kluge for protected mode */
07617
07618 /*==========================================================================*
07619 * intr_init *
07620 *==========================================================================*/
07621 PUBLIC void intr_init(mine)
07622 int mine;
07623 {
07624 /* Initialize the 8259s, finishing with all interrupts disabled. This is
07625 * only done in protected mode, in real mode we don't touch the 8259s, but
07626 * use the BIOS locations instead. The flag "mine" is set if the 8259s are
07627 * to be programmed for Minix, or to be reset to what the BIOS expects.
07628 */
07629
07630 int i;
07631
07632 lock();
07633 /* The AT and newer PS/2 have two interrupt controllers, one master,
07634 * one slaved at IRQ 2. (We don't have to deal with the PC that
07635 * has just one controller, because it must run in real mode.)
07636 */
07637 out_byte(INT_CTL, ps_mca ? ICW1_PS : ICW1_AT);
07638 out_byte(INT_CTLMASK, mine ? IRQ0_VECTOR : BIOS_IRQ0_VEC);
07639 /* ICW2 for master */
07640 out_byte(INT_CTLMASK, (1 << CASCADE_IRQ)); /* ICW3 tells slaves */
07641 out_byte(INT_CTLMASK, ICW4_AT);
07642 out_byte(INT_CTLMASK, ~(1 << CASCADE_IRQ)); /* IRQ 0-7 mask */
07643 out_byte(INT2_CTL, ps_mca ? ICW1_PS : ICW1_AT);
07644 out_byte(INT2_CTLMASK, mine ? IRQ8_VECTOR : BIOS_IRQ8_VEC);
07645 /* ICW2 for slave */
07646 out_byte(INT2_CTLMASK, CASCADE_IRQ); /* ICW3 is slave nr */
07647 out_byte(INT2_CTLMASK, ICW4_AT);
07648 out_byte(INT2_CTLMASK, ~0); /* IRQ 8-15 mask */
07649
07650 /* Initialize the table of interrupt handlers. */
07651 for (i = 0; i < NR_IRQ_VECTORS; i++) irq_table[i] = spurious_irq;
07652 }
07654 /*=========================================================================*
07655 * spurious_irq *
07656 *=========================================================================*/
07657 PRIVATE int spurious_irq(irq)
07658 int irq;
07659 {
07660 /* Default interrupt handler. It complains a lot. */
07661
07662 if (irq < 0 || irq >= NR_IRQ_VECTORS)
07663 panic("invalid call to spurious_irq", irq);
07664
07665 printf("spurious irq %d\n", irq);
07666
07667 return 1; /* Reenable interrupt */
07668 }
07670 /*=========================================================================*
07671 * put_irq_handler *
07672 *=========================================================================*/
07673 PUBLIC void put_irq_handler(irq, handler)
07674 int irq;
07675 irq_handler_t handler;
07676 {
07677 /* Register an interrupt handler. */
07678
07679 if (irq < 0 || irq >= NR_IRQ_VECTORS)
07680 panic("invalid call to put_irq_handler", irq);
07681
07682 if (irq_table[irq] == handler)
07683 return; /* extra initialization */
07684
07685 if (irq_table[irq] != spurious_irq)
07686 panic("attempt to register second irq handler for irq", irq);
07687
07688 disable_irq(irq);
07689 if (!protected_mode) set_vec(BIOS_VECTOR(irq), irq_vec[irq]);
07690 irq_table[irq]= handler;
07691 irq_use |= 1 << irq;
07692 }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -