]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/dirq_io_apic.cpp
f5108362c639acfc137321f14561047c54440452
[l4.git] / kernel / fiasco / src / kern / dirq_io_apic.cpp
1 INTERFACE:
2
3 #include "dirq_pic_pin.h"
4 #include "initcalls.h"
5
6 class Dirq_io_apic : public Dirq_pic_pin
7 {
8 protected:
9   class Chip : public Dirq_pic_pin::Chip
10   {
11   public:
12     bool alloc(Irq_base *irq, unsigned irqnum);
13     void setup(Irq_base *irq, unsigned irqnum);
14     unsigned legacy_override(unsigned irq);
15     unsigned nr_irqs() const;
16     void disable_irq(unsigned irqnum);
17   };
18 };
19
20
21
22 IMPLEMENTATION:
23
24 #include "apic.h"
25 #include "io_apic.h"
26 #include "receiver.h"
27 #include "idt.h"
28 #include "irq.h"
29
30 enum
31 {
32   Default_mode = Irq::Trigger_edge | Irq::Polarity_high,
33   //Default_mode = Irq::Trigger_level | Irq::Polarity_high,
34 };
35
36
37 IMPLEMENT
38 unsigned
39 Dirq_io_apic::Chip::legacy_override(unsigned irq)
40 {
41   return Io_apic::legacy_override(irq);
42 }
43
44
45
46 IMPLEMENT
47 unsigned
48 Dirq_io_apic::Chip::nr_irqs() const
49 { return Io_apic::nr_irqs(); }
50
51
52 IMPLEMENT
53 void
54 Dirq_io_apic::Chip::setup(Irq_base *irq, unsigned irqnum)
55 {
56   //irq->pin()->set_mode(Default_mode);
57   if (irq->pin()->get_mode() & Irq::Trigger_level)
58     irq->pin()->replace<Pin_io_apic_level>(irqnum);
59   else
60     irq->pin()->replace<Pin_io_apic_edge>(irqnum);
61 }
62
63 IMPLEMENT
64 bool
65 Dirq_io_apic::Chip::alloc(Irq_base *irq, unsigned irqnum)
66 {
67   if (!Dirq_pic_pin::Chip::alloc(irq, irqnum))
68     return false;
69
70   Io_apic_entry e = Io_apic::apic()->read_entry(irqnum);
71   e.vector(vector(irqnum));
72   Io_apic::apic()->write_entry(irqnum, e);
73   return true;
74 }
75
76 IMPLEMENT
77 void
78 Dirq_io_apic::Chip::disable_irq(unsigned vector)
79 {
80   extern char entry_int_apic_ignore[];
81   Idt::set_entry(vector, Address(&entry_int_apic_ignore), false);
82 }
83
84 static inline
85 Mword to_io_apic_trigger(unsigned mode)
86 {
87   return (mode & Irq::Trigger_level)
88             ? Io_apic_entry::Level
89             : Io_apic_entry::Edge;
90 }
91
92 static inline
93 Mword to_io_apic_polarity(unsigned mode)
94 {
95   return (mode & Irq::Polarity_low)
96              ? Io_apic_entry::Low_active
97              : Io_apic_entry::High_active;
98 }
99
100 class Pin_io_apic_level : public Dirq_pic_pin
101 {
102 public:
103   explicit Pin_io_apic_level(unsigned irq) : Dirq_pic_pin(irq) {}
104 };
105
106 class Pin_io_apic_edge : public Pin_io_apic_level
107 {
108 public:
109   explicit Pin_io_apic_edge(unsigned irq) : Pin_io_apic_level(irq) {}
110 };
111
112
113
114 PUBLIC
115 void
116 Pin_io_apic_level::disable()
117 {
118   extern char entry_int_apic_ignore[];
119   unsigned vector = this->vector();
120   Idt::set_entry(vector, Address(&entry_int_apic_ignore), false);
121   disable_vector();
122 }
123
124 PUBLIC void
125 Pin_io_apic_edge::do_mask_and_ack()
126 {
127   assert (cpu_lock.test());
128   Apic::irq_ack();
129 }
130
131
132 PUBLIC void
133 Pin_io_apic_edge::do_set_mode(unsigned mode)
134 {
135   Io_apic_entry e = Io_apic::apic()->read_entry(irq());
136   e.polarity(to_io_apic_polarity(mode));
137   e.trigger(to_io_apic_trigger(mode));
138   Io_apic::apic()->write_entry(irq(), e);
139   if (mode & Irq::Trigger_level)
140     new (this) Pin_io_apic_level(irq());
141 }
142
143
144 PUBLIC void
145 Pin_io_apic_level::do_mask()
146 {
147   assert (cpu_lock.test());
148   Io_apic::mask(irq());
149   Io_apic::sync();
150 }
151
152
153 PUBLIC
154 void
155 Pin_io_apic_level::ack()
156 {
157   assert (cpu_lock.test());
158   Apic::irq_ack();
159 }
160
161
162
163 PUBLIC void
164 Pin_io_apic_level::do_mask_and_ack()
165 {
166   assert (cpu_lock.test());
167   __mask();
168   Io_apic::mask(irq());
169   Io_apic::sync();
170   Apic::irq_ack();
171 }
172
173
174 PUBLIC void
175 Pin_io_apic_level::do_unmask()
176 {
177   assert (cpu_lock.test());
178   Io_apic::unmask(irq());
179 }
180
181 PUBLIC void
182 Pin_io_apic_level::set_cpu(unsigned cpu)
183 {
184   Io_apic::set_dest(irq(), Cpu::cpus.cpu(cpu).phys_id());
185 }
186
187
188 PUBLIC void
189 Pin_io_apic_level::do_set_mode(unsigned mode)
190 {
191   Io_apic_entry e = Io_apic::apic()->read_entry(irq());
192   e.polarity(to_io_apic_polarity(mode));
193   e.trigger(to_io_apic_trigger(mode));
194   Io_apic::apic()->write_entry(irq(), e);
195   if (!(mode & Irq::Trigger_level))
196     new (this) Pin_io_apic_edge(irq());
197 }
198
199
200 PUBLIC static FIASCO_INIT
201 void
202 Dirq_io_apic::init()
203 {
204   static Chip _ia;
205   Irq_chip::hw_chip = &_ia;
206 }
207
208 // --------------------------------------------------------------------------
209 IMPLEMENTATION [debug]:
210
211 PUBLIC
212 char const *
213 Pin_io_apic_level::pin_type() const
214 { return "HW IRQ (IOAPIC level)"; }
215
216 PUBLIC
217 char const *
218 Pin_io_apic_edge::pin_type() const
219 { return "HW IRQ (IOAPIC edge)"; }