16 enum Delivery { Fixed, Lowest_prio, SMI, NMI = 4, INIT, ExtINT = 7 };
17 enum Dest_mode { Physical, Logical };
18 enum Polarity { High_active, Low_active };
19 enum Trigger { Edge, Level };
22 Io_apic_entry(Unsigned8 vector, Delivery d, Dest_mode dm, Polarity p,
23 Trigger t, Unsigned8 dest)
24 : _e(vector | (d << 8) | (dm << 11) | (p << 13) | (t << 15) | (1<<16)
25 | (((Unsigned64)dest) << 56))
28 unsigned delivery() const { return (_e >> 8) & 7; }
29 void delivery(unsigned m) { _e = (_e & ~(7 << 8)) | ((m & 7) << 8); }
30 unsigned dest_mode() const { return _e & (1 << 11); }
31 void dest_mode(bool p) { _e = (_e & ~(1<<11)) | ((unsigned long)p << 11); }
32 unsigned dest() const { return _e >> 56; }
33 void dest(unsigned d) { _e = (_e & ~(0xffULL << 56)) | ((Unsigned64)d << 56); }
34 unsigned mask() const { return _e & (1U << 16); }
35 void mask(bool m) { _e = (_e & ~(1ULL << 16)) | ((Unsigned64)m << 16); }
36 unsigned trigger() const { return _e & (1 << 15); }
37 unsigned polarity() const { return _e & (1 << 13); }
38 unsigned vector() const { return _e & 0xff; }
39 void vector(Unsigned8 v) { _e = (_e & ~0xff) | v; }
40 void trigger(Mword tr) { _e = (_e & ~(1UL << 15)) | ((tr & 1) << 15); }
41 void polarity(Mword pl) { _e = (_e & ~(1UL << 13)) | ((pl & 1) << 13); }
42 } __attribute__((packed));
48 Unsigned32 volatile adr;
50 Unsigned32 volatile data;
53 static Io_apic *_apic;
54 static Acpi_madt const *_madt;
55 } __attribute__((packed));
63 #include "lock_guard.h"
65 Io_apic *Io_apic::_apic;
66 Spin_lock Io_apic::_l;
67 Acpi_madt const *Io_apic::_madt;
71 PRIVATE inline NEEDS["lock_guard.h"]
73 Io_apic::read(int reg)
75 Lock_guard<Spin_lock> g(&_l);
77 asm volatile ("": : :"memory");
81 PRIVATE inline NEEDS["lock_guard.h"]
83 Io_apic::modify(int reg, Mword set_bits, Mword del_bits)
86 Lock_guard<Spin_lock> g(&_l);
88 asm volatile ("": : :"memory");
95 PRIVATE inline NEEDS["lock_guard.h"]
97 Io_apic::write(int reg, Mword value)
99 Lock_guard<Spin_lock> g(&_l);
101 asm volatile ("": : :"memory");
107 Io_apic::num_entries()
109 return (read(1) >> 16) & 0xff;
113 PUBLIC inline NEEDS["kdb_ke.h"]
115 Io_apic::read_entry(unsigned i)
118 //assert_kdb(i <= num_entries());
119 e._e = (Unsigned64)read(0x10+2*i) | (((Unsigned64)read(0x11+2*i)) << 32);
124 PUBLIC inline NEEDS["kdb_ke.h", Io_apic::write]
126 Io_apic::write_entry(unsigned i, Io_apic_entry const &e)
128 //assert_kdb(i <= num_entries());
129 write(0x10+2*i, e._e);
130 write(0x11+2*i, e._e >> 32);
133 PUBLIC static FIASCO_INIT
137 _madt = Acpi::find<Acpi_madt const *>("APIC");
141 printf("Could not find APIC in RSDT nor XSDT, skipping init\n");
144 printf("MADT = %p\n", _madt);
146 Acpi_madt::Io_apic const *ioapic
147 = static_cast<Acpi_madt::Io_apic const *>(_madt->find(Acpi_madt::IOAPIC, 0));
151 printf("IO-APIC: Could not find IO-APIC in MADT, skip init\n");
155 printf("IO-APIC: struct: %p adr=%x\n", ioapic, ioapic->adr);
156 printf("IO-APIC: dual 8259: %s\n", _madt->apic_flags & 1 ? "yes" : "no");
161 Acpi_madt::Irq_source const *irq
162 = static_cast<Acpi_madt::Irq_source const *>(_madt->find(Acpi_madt::Irq_src_ovr, tmp));
167 printf("IO-APIC: ovr[%2u] %02x -> %x\n", tmp, irq->src, irq->irq);
171 printf("IO-APIC: NOTE IRQ overrides are ignored!\n");
174 Kmem::map_phys_page(ioapic->adr, Mem_layout::Io_apic_page,
177 Kip::k()->add_mem_region(Mem_desc(ioapic->adr, ioapic->adr + Config::PAGE_SIZE -1, Mem_desc::Reserved));
180 Io_apic *apic = (Io_apic*)(Mem_layout::Io_apic_page + offs);
183 unsigned ne = apic->num_entries();
185 for (unsigned i = 0; i <= ne; ++i)
188 Io_apic_entry e(v, Io_apic_entry::Fixed, Io_apic_entry::Physical,
189 Io_apic_entry::High_active, Io_apic_entry::Edge, 0);
190 apic->write_entry(i, e);
193 printf("IO-APIC: pins %u\n", ne);
201 Io_apic::legacy_override(unsigned i)
206 Acpi_madt::Irq_source const *irq
207 = static_cast<Acpi_madt::Irq_source const *>(_madt->find(Acpi_madt::Irq_src_ovr, tmp));
222 unsigned ne = _apic->num_entries();
223 for (unsigned i = 0; i <= ne; ++i)
225 Io_apic_entry e = _apic->read_entry(i);
226 printf(" PIN[%2u%c]: vector=%2x, del=%u, dm=%s, dest=%u (%s, %s)\n",
227 i, e.mask() ? 'm' : '.',
228 e.vector(), e.delivery(), e.dest_mode() ? "logical" : "physical",
230 e.polarity() ? "low" : "high",
231 e.trigger() ? "level" : "edge");
241 PUBLIC static inline NEEDS["kdb_ke.h", Io_apic::modify]
243 Io_apic::mask(unsigned irq)
245 //assert_kdb(irq <= _apic->num_entries());
246 _apic->modify(0x10 + irq * 2, 1UL << 16, 0);
249 PUBLIC static inline NEEDS["kdb_ke.h", Io_apic::modify]
251 Io_apic::unmask(unsigned irq)
253 //assert_kdb(irq <= _apic->num_entries());
254 _apic->modify(0x10 + irq * 2, 0, 1UL << 16);
257 PUBLIC static inline NEEDS["kdb_ke.h", Io_apic::read]
259 Io_apic::masked(unsigned irq)
261 //assert_kdb(irq <= _apic->num_entries());
262 return _apic->read(0x10 + irq * 2) & (1UL << 16);
265 PUBLIC static inline NEEDS[Io_apic::read]
272 PUBLIC static inline NEEDS["kdb_ke.h", Io_apic::modify]
274 Io_apic::set_dest(unsigned irq, Mword dst)
276 //assert_kdb(irq <= _apic->num_entries());
277 _apic->modify(0x11 + irq * 2, dst & (~0UL << 24), ~0UL << 24);
280 PUBLIC static inline NEEDS[Io_apic::num_entries]
283 { return _apic->num_entries() + 1; }