3 #include "dirq_pic_pin.h"
6 class Dirq_io_apic : public Dirq_pic_pin
9 class Chip : public Dirq_pic_pin::Chip
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);
33 Default_mode = Irq::Trigger_edge | Irq::Polarity_high,
34 //Default_mode = Irq::Trigger_level | Irq::Polarity_high,
40 Dirq_io_apic::Chip::legacy_override(unsigned irq)
42 return Io_apic::legacy_override(irq);
49 Dirq_io_apic::Chip::nr_irqs() const
50 { return Io_apic::total_irqs(); }
55 Dirq_io_apic::Chip::setup(Irq_base *irq, unsigned irqnum)
57 unsigned apic_idx = Io_apic::find_apic(irqnum);
58 irqnum -= Io_apic::apic(apic_idx)->gsi_offset();
60 //irq->pin()->set_mode(Default_mode);
61 if (irq->pin()->get_mode() & Irq::Trigger_level)
62 irq->pin()->replace<Pin_io_apic_level>(apic_idx, irqnum);
64 irq->pin()->replace<Pin_io_apic_edge>(apic_idx, irqnum);
69 Dirq_io_apic::Chip::alloc(Irq_base *irq, unsigned irqnum)
71 if (!Dirq_pic_pin::Chip::alloc(irq, irqnum))
75 unsigned apic_idx = Io_apic::find_apic(irqnum);
76 Io_apic *a = Io_apic::apic(apic_idx);
77 unsigned lirqn = irqnum - a->gsi_offset();
80 Io_apic_entry e = a->read_entry(lirqn);
81 e.vector(vector(irqnum));
82 a->write_entry(lirqn, e);
88 Dirq_io_apic::Chip::disable_irq(unsigned vector)
90 extern char entry_int_apic_ignore[];
91 Idt::set_entry(vector, Address(&entry_int_apic_ignore), false);
95 Mword to_io_apic_trigger(unsigned mode)
97 return (mode & Irq::Trigger_level)
98 ? Io_apic_entry::Level
99 : Io_apic_entry::Edge;
103 Mword to_io_apic_polarity(unsigned mode)
105 return (mode & Irq::Polarity_low)
106 ? Io_apic_entry::Low_active
107 : Io_apic_entry::High_active;
110 class Pin_io_apic_level : public Irq_pin
113 explicit Pin_io_apic_level(unsigned apic, unsigned irq)
114 { payload()[0] = apic + (irq << 16); }
116 unsigned irq() const { return payload()[0] >> 16; }
117 unsigned apic_idx() const { return payload()[0] & 0xffff; }
118 Io_apic *apic() const { return Io_apic::apic(apic_idx()); }
119 unsigned gsi() const { return apic()->gsi_offset() + irq(); }
122 class Pin_io_apic_edge : public Pin_io_apic_level
125 explicit Pin_io_apic_edge(unsigned apic, unsigned irq)
126 : Pin_io_apic_level(apic, irq) {}
131 Pin_io_apic_level::check_debug_irq()
133 return !Vkey::check_(gsi());
138 Pin_io_apic_level::unbind_irq()
142 Irq_chip::hw_chip->free(Irq::self(this), gsi());
143 replace<Sw_irq_pin>();
148 Pin_io_apic_level::disable()
150 extern char entry_int_apic_ignore[];
151 unsigned vector = Dirq_pic_pin::Chip::vector(gsi());
152 Dirq_pic_pin::Chip::vfree(Irq_base::self(this), vector, &entry_int_apic_ignore);
156 Pin_io_apic_edge::do_mask_and_ack()
158 assert (cpu_lock.test());
164 Pin_io_apic_edge::do_set_mode(unsigned mode)
166 Io_apic_entry e = apic()->read_entry(irq());
167 e.polarity(to_io_apic_polarity(mode));
168 e.trigger(to_io_apic_trigger(mode));
169 apic()->write_entry(irq(), e);
170 if (mode & Irq::Trigger_level)
171 new (this) Pin_io_apic_level(apic_idx(), irq());
176 Pin_io_apic_level::do_mask()
178 assert (cpu_lock.test());
186 Pin_io_apic_level::ack()
188 assert (cpu_lock.test());
195 Pin_io_apic_level::do_mask_and_ack()
197 assert (cpu_lock.test());
206 Pin_io_apic_level::do_unmask()
208 assert (cpu_lock.test());
209 apic()->unmask(irq());
213 Pin_io_apic_level::set_cpu(unsigned cpu)
215 apic()->set_dest(irq(), Cpu::cpus.cpu(cpu).phys_id());
220 Pin_io_apic_level::do_set_mode(unsigned mode)
222 Io_apic_entry e = apic()->read_entry(irq());
223 e.polarity(to_io_apic_polarity(mode));
224 e.trigger(to_io_apic_trigger(mode));
225 apic()->write_entry(irq(), e);
226 if (!(mode & Irq::Trigger_level))
227 new (this) Pin_io_apic_edge(apic_idx(), irq());
231 PUBLIC static FIASCO_INIT
236 Irq_chip::hw_chip = &_ia;
239 // --------------------------------------------------------------------------
240 IMPLEMENTATION [debug]:
244 Pin_io_apic_level::pin_type() const
245 { return "HW IRQ (IOAPIC level)"; }
249 Pin_io_apic_edge::pin_type() const
250 { return "HW IRQ (IOAPIC edge)"; }