source: trunk/kernel/drivers/ibmpc/pic.c @ 278

Last change on this file since 278 was 4, checked in by alain, 8 years ago

Introduce the chdev_t structure in place of device_t.

File size: 4.4 KB
Line 
1/*
2 * pic.h - Programmable Interrupt Controller driver implementation
3 *
4 * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless
5 * Copyright (c) 2011,2012 UPMC Sorbonne Universites
6 *
7 * This file is part of ALMOS-kernel.
8 *
9 * ALMOS-kernel is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; version 2.0 of the License.
12 *
13 * ALMOS-kernel is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with ALMOS-kernel; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23#include <types.h>
24#include <cpu.h>
25#include <chdev.h>
26#include <driver.h>
27#include <cpu-io.h>
28#include <kmem.h>
29#include <string.h>
30#include <kdmsg.h>
31#include <pic.h>
32
33#define PIC_PRIMARY_PIO    0x20
34#define PIC_SECONDARY_PIO  0xA0
35
36struct irq_action_s *irq_vector[PIC_IRQ_MAX];
37
38static void pic_set_mask(struct device_s *pic, uint_t mask, uint_t type, uint_t output_irq)
39{
40        switch(type)
41        {
42        case 0:
43                cpu_io_out8(PIC_PRIMARY_PIO + PIC_IMR_REG, ~(mask & 0xFF));
44                break;
45        case 1:
46                cpu_io_out8(PIC_SECONDARY_PIO + PIC_IMR_REG, ~(mask & 0xFF));
47                break;
48        default:
49                printk(ERROR, "ERROR: Un expected mask value, PIC has 16 IRQ line only [ type 0 & 1 ]");
50        }
51}
52
53static uint_t pic_get_mask(struct device_s *icu, uint_t type, uint_t output_irq)
54{
55        register uint_t mask = ~0;
56 
57        switch(type)
58        {
59        case 0:
60                mask = cpu_io_in8(PIC_PRIMARY_PIO + PIC_IMR_REG);
61                break;
62        case 1:
63                mask = cpu_io_in8(PIC_SECONDARY_PIO + PIC_IMR_REG);
64                break;
65        default:
66                printk(ERROR, "ERROR: Un expected mask value, PIC has 16 IRQ line only [ type 0 & 1 ]");
67        }
68 
69        return ((~mask) & 0xFF);
70}
71
72static sint_t pic_get_highest_irq(struct device_s *icu, uint_t type, uint_t output_irq)
73{
74        return -1;
75}
76
77static void pic_default_irq_handler(struct irq_action_s *action)
78{
79        register unsigned int irq_num = (unsigned int) action->data;
80        register unsigned int cpu_id  = cpu_get_id();
81 
82        isr_dmsg(WARNING, "WARNING: No ISR registered handler for IRQ %d on CPU %d\n",irq_num, cpu_id);
83}
84
85static void pic_ICWs()
86{
87        /* ICW1 */
88        cpu_io_out8(PIC_PRIMARY_PIO + PIC_CMD_REG, 0x11); /* Put Primary PIC in Initialization mode with ICW4 enabled */
89        cpu_io_out8(PIC_SECONDARY_PIO + PIC_CMD_REG, 0x11); /* Same ICW1 as Primary */
90
91        /* ICW2 */
92        cpu_io_out8(PIC_PRIMARY_PIO + PIC_DATA_REG, 0x20); /* Set Primary PIC's interrupt vector base number */
93        cpu_io_out8(PIC_SECONDARY_PIO + PIC_DATA_REG, 0x28); /* Set Secondary PIC's interrupt vector base number */
94
95        /* ICW3 */
96        cpu_io_out8(PIC_PRIMARY_PIO + PIC_DATA_REG, 0x4); /* Informe Primary that Secondary is connected to line 2 */
97        cpu_io_out8(PIC_SECONDARY_PIO + PIC_DATA_REG, 0x2); /* Inform Secondary of it's identification */
98
99        /* ICW4 */
100        cpu_io_out8(PIC_PRIMARY_PIO + PIC_DATA_REG, 0x1); /* Put Primary in x86 mode */
101        cpu_io_out8(PIC_SECONDARY_PIO + PIC_DATA_REG, 0x1); /* Put Primary in x86 mode */
102
103        /* CLEAR DATA REGISTERS */
104        cpu_io_out8(PIC_PRIMARY_PIO + PIC_DATA_REG, 0);
105        cpu_io_out8(PIC_SECONDARY_PIO + PIC_DATA_REG, 0);
106}
107
108
109void pic_irq_handler(struct irq_action_s *action)
110{
111        register uint_t irq = (uint_t)action->data;
112        irq_vector[irq]->data = (void*)irq;
113        irq_vector[irq]->irq_handler(irq_vector[irq]);
114}
115
116void ibmpc_pic_init(struct device_s *pic, void *base, uint_t irq)
117{
118        register uint_t _irq;
119        struct irq_action_s *action_ptr;
120
121        pic->base = base;
122        pic->type = DEV_ICU;
123        pic->action.irq_handler = &pic_irq_handler;
124
125        strcpy(pic->name, "PIC");
126        metafs_init(&pic->node, pic->name);
127 
128        pic->op.icu.set_mask = &pic_set_mask;
129        pic->op.icu.get_mask = &pic_get_mask;
130        pic->op.icu.get_highest_irq = &pic_get_highest_irq;
131
132        for(_irq=0; _irq < PIC_IRQ_MAX; _irq++)
133        {
134                action_ptr = kbootMem_calloc(sizeof(*action_ptr));
135                action_ptr->dev = pic;
136                action_ptr->irq_handler = &pic_default_irq_handler;
137                action_ptr->data = (void*) _irq;   
138                irq_vector[_irq] = action_ptr;
139        }
140 
141        pic_ICWs();
142}
143
144void ibmpc_pic_bind(struct device_s *pic, struct device_s *dev)
145{
146        assert(dev->irq < PIC_IRQ_MAX && "Unexpected IRQ, connot bind this device");
147
148        if(dev->irq < PIC_IRQ_MAX)
149        {
150                irq_vector[dev->irq] = &dev->action;
151                metafs_register(&pic->node, &dev->node);
152        }
153}
Note: See TracBrowser for help on using the repository browser.