Ignore:
Timestamp:
2019-09-23T12:49:29Z (7 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
9be2358
Parents:
9259d20 (diff), 1a4ec93f (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
git-author:
Jiri Svoboda <jiri@…> (2019-09-22 12:49:07)
git-committer:
Jiri Svoboda <jiri@…> (2019-09-23 12:49:29)
Message:

Merge changes from master, especially Meson build

File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/genarch/src/drivers/i8259/i8259.c

    r9259d20 r3e828ea  
    3232/**
    3333 * @file
    34  * @brief PIC driver.
     34 * @brief i8259 driver.
    3535 *
    3636 * Programmable Interrupt Controller for UP systems based on i8259 chip.
     
    4343#include <interrupt.h>
    4444
    45 static void pic_spurious(unsigned int n, istate_t *istate);
     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
     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};
    4671
    4772// XXX: need to change pic_* API to get rid of these
     
    4974static i8259_t *saved_pic1;
    5075
    51 void i8259_init(i8259_t *pic0, i8259_t *pic1, inr_t pic1_irq,
    52     unsigned int irq0_int, unsigned int irq8_int)
     76void i8259_init(i8259_t *pic0, i8259_t *pic1, unsigned int irq0_vec)
    5377{
    5478        saved_pic0 = pic0;
     
    5680
    5781        /* ICW1: this is ICW1, ICW4 to follow */
    58         pio_write_8(&pic0->port1, PIC_ICW1 | PIC_ICW1_NEEDICW4);
     82        pio_write_8(&pic0->port1, I8259_ICW1 | I8259_ICW1_NEEDICW4);
    5983
    60         /* ICW2: IRQ 0 maps to INT irq0_int */
    61         pio_write_8(&pic0->port2, irq0_int);
     84        /* ICW2: IRQ 0 maps to interrupt vector address irq0_vec */
     85        pio_write_8(&pic0->port2, irq0_vec);
    6286
    63         /* ICW3: pic1 using IRQ IRQ_PIC1 */
    64         pio_write_8(&pic0->port2, 1 << pic1_irq);
     87        /* ICW3: pic1 using IRQ I8259_IRQ_SLAVE */
     88        pio_write_8(&pic0->port2, 1 << I8259_IRQ_SLAVE);
    6589
    6690        /* ICW4: i8086 mode */
     
    6892
    6993        /* ICW1: ICW1, ICW4 to follow */
    70         pio_write_8(&pic1->port1, PIC_ICW1 | PIC_ICW1_NEEDICW4);
     94        pio_write_8(&pic1->port1, I8259_ICW1 | I8259_ICW1_NEEDICW4);
    7195
    72         /* ICW2: IRQ 8 maps to INT irq8_int */
    73         pio_write_8(&pic1->port2, irq8_int);
     96        /* ICW2: IRQ 8 maps to interrupt vector address irq0_vec + 8 */
     97        pio_write_8(&pic1->port2, irq0_vec + I8259_IRQ_COUNT);
    7498
    75         /* ICW3: pic1 is known as IRQ_PIC1 */
    76         pio_write_8(&pic1->port2, pic1_irq);
     99        /* ICW3: pic1 is known as I8259_IRQ_SLAVE */
     100        pio_write_8(&pic1->port2, I8259_IRQ_SLAVE);
    77101
    78102        /* ICW4: i8086 mode */
    79103        pio_write_8(&pic1->port2, 1);
    80104
    81         /*
    82          * Register interrupt handler for the PIC spurious interrupt.
    83          *
    84          * XXX: This is currently broken. Both IRQ 7 and IRQ 15 can be spurious
    85          *      or can be actual interrupts. This needs to be detected when
    86          *      the interrupt happens by inspecting ISR.
    87          */
    88         exc_register(irq0_int + 7, "pic_spurious", false,
    89             (iroutine_t) pic_spurious);
    90 
    91         pic_disable_irqs(0xffff);               /* disable all irq's */
    92         pic_enable_irqs(1 << pic1_irq);         /* but enable pic1_irq */
     105        /* disable all irq's */
     106        i8259_disable_irqs(0xffff);
     107        /* but enable I8259_IRQ_SLAVE */
     108        i8259_enable_irqs(1 << I8259_IRQ_SLAVE);
    93109}
    94110
    95 void pic_enable_irqs(uint16_t irqmask)
     111const char *i8259_get_name(void)
     112{
     113        return "i8259";
     114}
     115
     116void i8259_enable_irqs(uint16_t irqmask)
    96117{
    97118        uint8_t x;
     
    102123                    (uint8_t) (x & (~(irqmask & 0xff))));
    103124        }
    104         if (irqmask >> 8) {
     125        if (irqmask >> I8259_IRQ_COUNT) {
    105126                x = pio_read_8(&saved_pic1->port2);
    106127                pio_write_8(&saved_pic1->port2,
    107                     (uint8_t) (x & (~(irqmask >> 8))));
     128                    (uint8_t) (x & (~(irqmask >> I8259_IRQ_COUNT))));
    108129        }
    109130}
    110131
    111 void pic_disable_irqs(uint16_t irqmask)
     132void i8259_disable_irqs(uint16_t irqmask)
    112133{
    113134        uint8_t x;
     
    118139                    (uint8_t) (x | (irqmask & 0xff)));
    119140        }
    120         if (irqmask >> 8) {
     141        if (irqmask >> I8259_IRQ_COUNT) {
    121142                x = pio_read_8(&saved_pic1->port2);
    122                 pio_write_8(&saved_pic1->port2, (uint8_t) (x | (irqmask >> 8)));
     143                pio_write_8(&saved_pic1->port2,
     144                    (uint8_t) (x | (irqmask >> I8259_IRQ_COUNT)));
    123145        }
    124146}
    125147
    126 void pic_eoi(void)
     148void i8259_eoi(unsigned int irq)
    127149{
    128         pio_write_8(&saved_pic0->port1, PIC_OCW4 | PIC_OCW4_NSEOI);
    129         pio_write_8(&saved_pic1->port1, PIC_OCW4 | PIC_OCW4_NSEOI);
     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);
    130153}
    131154
    132 void pic_spurious(unsigned int n __attribute__((unused)), istate_t *istate __attribute__((unused)))
     155bool i8259_is_spurious(unsigned int irq)
    133156{
    134 #ifdef CONFIG_DEBUG
    135         log(LF_ARCH, LVL_DEBUG, "cpu%u: PIC spurious interrupt", CPU->id);
    136 #endif
     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);
     159        uint8_t isr_lo = pio_read_8(&saved_pic0->port1);
     160        uint8_t isr_hi = pio_read_8(&saved_pic1->port1);
     161        return !(((isr_hi << I8259_IRQ_COUNT) | isr_lo) & (1 << irq));
     162}
     163
     164void i8259_handle_spurious(unsigned int irq)
     165{
     166        /* For spurious IRQs from pic1, we need to isssue an EOI to pic0 */
     167        if (irq >= I8259_IRQ_COUNT)
     168                pio_write_8(&saved_pic0->port1, I8259_OCW4 | I8259_OCW4_NSEOI);
    137169}
    138170
Note: See TracChangeset for help on using the changeset viewer.