source: mainline/kernel/genarch/src/drivers/i8259/i8259.c

Last change on this file was c48de91, checked in by Jakub Jermar <jakub@…>, 6 years ago

Hide macros used internally by the i8259 driver

  • Property mode set to 100644
File size: 4.9 KB
RevLine 
[f761f1eb]1/*
[df4ed85]2 * Copyright (c) 2001-2004 Jakub Jermar
[f761f1eb]3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
[87a5796]29/** @addtogroup kernel_genarch
[b45c443]30 * @{
31 */
[3c5006a0]32/**
33 * @file
[c48de91]34 * @brief i8259 driver.
[3c5006a0]35 *
36 * Programmable Interrupt Controller for UP systems based on i8259 chip.
[b45c443]37 */
38
[87a5796]39#include <genarch/drivers/i8259/i8259.h>
[a773b8b]40#include <typedefs.h>
[83dab11]41#include <stdint.h>
[b2fa1204]42#include <log.h>
[fcfac420]43#include <interrupt.h>
[f761f1eb]44
[c48de91]45/* ICW1 bits */
46#define I8259_ICW1 (1 << 4)
47#define I8259_ICW1_NEEDICW4 (1 << 0)
48
49/* OCW3 bits */
50#define I8259_OCW3 (1 << 3)
51#define I8259_OCW3_READ_ISR (3 << 0)
52
53/* OCW4 bits */
54#define I8259_OCW4 (0 << 3)
55#define I8259_OCW4_NSEOI (1 << 5)
56
57#define I8259_IRQ_COUNT 8
58
59#define I8259_IRQ_SLAVE 2
60
[2a103b5]61static const char *i8259_get_name(void);
62
63pic_ops_t i8259_pic_ops = {
64 .get_name = i8259_get_name,
65 .enable_irqs = i8259_enable_irqs,
66 .disable_irqs = i8259_disable_irqs,
67 .eoi = i8259_eoi,
68 .is_spurious = i8259_is_spurious,
69 .handle_spurious = i8259_handle_spurious
70};
71
[d1cbad5]72// XXX: need to change pic_* API to get rid of these
73static i8259_t *saved_pic0;
74static i8259_t *saved_pic1;
75
[3daba42e]76void i8259_init(i8259_t *pic0, i8259_t *pic1, unsigned int irq0_vec)
[f761f1eb]77{
[d1cbad5]78 saved_pic0 = pic0;
79 saved_pic1 = pic1;
80
[f761f1eb]81 /* ICW1: this is ICW1, ICW4 to follow */
[c48de91]82 pio_write_8(&pic0->port1, I8259_ICW1 | I8259_ICW1_NEEDICW4);
[f761f1eb]83
[534bcdf]84 /* ICW2: IRQ 0 maps to interrupt vector address irq0_vec */
85 pio_write_8(&pic0->port2, irq0_vec);
[76cec1e]86
[c48de91]87 /* ICW3: pic1 using IRQ I8259_IRQ_SLAVE */
88 pio_write_8(&pic0->port2, 1 << I8259_IRQ_SLAVE);
[76cec1e]89
90 /* ICW4: i8086 mode */
[d1cbad5]91 pio_write_8(&pic0->port2, 1);
[f761f1eb]92
93 /* ICW1: ICW1, ICW4 to follow */
[c48de91]94 pio_write_8(&pic1->port1, I8259_ICW1 | I8259_ICW1_NEEDICW4);
[f761f1eb]95
[534bcdf]96 /* ICW2: IRQ 8 maps to interrupt vector address irq0_vec + 8 */
[c48de91]97 pio_write_8(&pic1->port2, irq0_vec + I8259_IRQ_COUNT);
[f761f1eb]98
[c48de91]99 /* ICW3: pic1 is known as I8259_IRQ_SLAVE */
100 pio_write_8(&pic1->port2, I8259_IRQ_SLAVE);
[f761f1eb]101
[76cec1e]102 /* ICW4: i8086 mode */
[d1cbad5]103 pio_write_8(&pic1->port2, 1);
[f761f1eb]104
[c48de91]105 /* disable all irq's */
106 i8259_disable_irqs(0xffff);
107 /* but enable I8259_IRQ_SLAVE */
108 i8259_enable_irqs(1 << I8259_IRQ_SLAVE);
[2a103b5]109}
110
111const char *i8259_get_name(void)
112{
113 return "i8259";
[f761f1eb]114}
115
[2a103b5]116void i8259_enable_irqs(uint16_t irqmask)
[f761f1eb]117{
[7f1c620]118 uint8_t x;
[76cec1e]119
[f761f1eb]120 if (irqmask & 0xff) {
[d1cbad5]121 x = pio_read_8(&saved_pic0->port2);
122 pio_write_8(&saved_pic0->port2,
123 (uint8_t) (x & (~(irqmask & 0xff))));
[f761f1eb]124 }
[c48de91]125 if (irqmask >> I8259_IRQ_COUNT) {
[d1cbad5]126 x = pio_read_8(&saved_pic1->port2);
127 pio_write_8(&saved_pic1->port2,
[c48de91]128 (uint8_t) (x & (~(irqmask >> I8259_IRQ_COUNT))));
[f761f1eb]129 }
130}
131
[2a103b5]132void i8259_disable_irqs(uint16_t irqmask)
[f761f1eb]133{
[7f1c620]134 uint8_t x;
[76cec1e]135
[f761f1eb]136 if (irqmask & 0xff) {
[d1cbad5]137 x = pio_read_8(&saved_pic0->port2);
138 pio_write_8(&saved_pic0->port2,
139 (uint8_t) (x | (irqmask & 0xff)));
[f761f1eb]140 }
[c48de91]141 if (irqmask >> I8259_IRQ_COUNT) {
[d1cbad5]142 x = pio_read_8(&saved_pic1->port2);
[fd67c9f]143 pio_write_8(&saved_pic1->port2,
[c48de91]144 (uint8_t) (x | (irqmask >> I8259_IRQ_COUNT)));
[f761f1eb]145 }
146}
147
[2a103b5]148void i8259_eoi(unsigned int irq)
[f761f1eb]149{
[c48de91]150 if (irq >= I8259_IRQ_COUNT)
151 pio_write_8(&saved_pic1->port1, I8259_OCW4 | I8259_OCW4_NSEOI);
152 pio_write_8(&saved_pic0->port1, I8259_OCW4 | I8259_OCW4_NSEOI);
[f761f1eb]153}
154
[2a103b5]155bool i8259_is_spurious(unsigned int irq)
[fd67c9f]156{
[c48de91]157 pio_write_8(&saved_pic0->port1, I8259_OCW3 | I8259_OCW3_READ_ISR);
158 pio_write_8(&saved_pic1->port1, I8259_OCW3 | I8259_OCW3_READ_ISR);
[fd67c9f]159 uint8_t isr_lo = pio_read_8(&saved_pic0->port1);
160 uint8_t isr_hi = pio_read_8(&saved_pic1->port1);
[c48de91]161 return !(((isr_hi << I8259_IRQ_COUNT) | isr_lo) & (1 << irq));
[fd67c9f]162}
163
[2a103b5]164void i8259_handle_spurious(unsigned int irq)
[fd67c9f]165{
166 /* For spurious IRQs from pic1, we need to isssue an EOI to pic0 */
[c48de91]167 if (irq >= I8259_IRQ_COUNT)
168 pio_write_8(&saved_pic0->port1, I8259_OCW4 | I8259_OCW4_NSEOI);
[fd67c9f]169}
170
[3c5006a0]171/** @}
[b45c443]172 */
Note: See TracBrowser for help on using the repository browser.