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::write(int reg, Mword value)
85 Lock_guard<Spin_lock> g(&_l);
87 asm volatile ("": : :"memory");
93 Io_apic::num_entries()
95 return (read(1) >> 16) & 0xff;
99 PUBLIC inline NEEDS["kdb_ke.h"]
101 Io_apic::read_entry(unsigned i)
104 //assert_kdb(i <= num_entries());
105 e._e = (Unsigned64)read(0x10+2*i) | (((Unsigned64)read(0x11+2*i)) << 32);
110 PUBLIC inline NEEDS["kdb_ke.h"]
112 Io_apic::write_entry(unsigned i, Io_apic_entry const &e)
114 //assert_kdb(i <= num_entries());
115 write(0x10+2*i, e._e);
116 write(0x11+2*i, e._e >> 32);
119 PUBLIC static FIASCO_INIT
123 _madt = Acpi::find<Acpi_madt const *>("APIC");
127 printf("Could not find APIC in RSDT nor XSDT, skipping init\n");
130 printf("MADT = %p\n", _madt);
132 Acpi_madt::Io_apic const *ioapic
133 = static_cast<Acpi_madt::Io_apic const *>(_madt->find(Acpi_madt::IOAPIC, 0));
137 printf("IO-APIC: Could not find IO-APIC in MADT, skip init\n");
141 printf("IO-APIC: struct: %p adr=%x\n", ioapic, ioapic->adr);
142 printf("IO-APIC: dual 8259: %s\n", _madt->apic_flags & 1 ? "yes" : "no");
147 Acpi_madt::Irq_source const *irq
148 = static_cast<Acpi_madt::Irq_source const *>(_madt->find(Acpi_madt::Irq_src_ovr, tmp));
153 printf("IO-APIC: ovr[%2u] %02x -> %x\n", tmp, irq->src, irq->irq);
157 printf("IO-APIC: NOTE IRQ overrides are ignored!\n");
160 Kmem::map_phys_page(ioapic->adr, Mem_layout::Io_apic_page,
163 Kip::k()->add_mem_region(Mem_desc(ioapic->adr, ioapic->adr + Config::PAGE_SIZE -1, Mem_desc::Reserved));
166 Io_apic *apic = (Io_apic*)(Mem_layout::Io_apic_page + offs);
169 unsigned ne = apic->num_entries();
171 for (unsigned i = 0; i <= ne; ++i)
174 Io_apic_entry e(v, Io_apic_entry::Fixed, Io_apic_entry::Physical,
175 Io_apic_entry::High_active, Io_apic_entry::Edge, 0);
176 apic->write_entry(i, e);
179 printf("IO-APIC: pins %u\n", ne);
187 Io_apic::legacy_override(unsigned i)
192 Acpi_madt::Irq_source const *irq
193 = static_cast<Acpi_madt::Irq_source const *>(_madt->find(Acpi_madt::Irq_src_ovr, tmp));
208 unsigned ne = _apic->num_entries();
209 for (unsigned i = 0; i <= ne; ++i)
211 Io_apic_entry e = _apic->read_entry(i);
212 printf(" PIN[%2u%c]: vector=%2x, del=%u, dm=%s, dest=%u (%s, %s)\n",
213 i, e.mask() ? 'm' : '.',
214 e.vector(), e.delivery(), e.dest_mode() ? "logical" : "physical",
216 e.polarity() ? "low" : "high",
217 e.trigger() ? "level" : "edge");
227 PUBLIC static inline NEEDS["kdb_ke.h", Io_apic::read,Io_apic::write]
229 Io_apic::mask(unsigned irq)
231 //assert_kdb(irq <= _apic->num_entries());
232 _apic->write(0x10 + irq * 2, _apic->read(0x10 + irq * 2) | (1UL << 16));
235 PUBLIC static inline NEEDS["kdb_ke.h", Io_apic::read,Io_apic::write]
237 Io_apic::unmask(unsigned irq)
239 //assert_kdb(irq <= _apic->num_entries());
240 _apic->write(0x10 + irq * 2, _apic->read(0x10 + irq * 2) & ~(1UL << 16));
243 PUBLIC static inline NEEDS["kdb_ke.h", Io_apic::read]
245 Io_apic::masked(unsigned irq)
247 //assert_kdb(irq <= _apic->num_entries());
248 return _apic->read(0x10 + irq * 2) & (1UL << 16);
251 PUBLIC static inline NEEDS["kdb_ke.h", Io_apic::read,Io_apic::write]
253 Io_apic::set_dest(unsigned irq, Mword dst)
255 //assert_kdb(irq <= _apic->num_entries());
256 _apic->write(0x11 + irq * 2, (_apic->read(0x11 + irq * 2) & ~(~0UL << 24)) | (dst & (~0UL << 24)));
259 PUBLIC static inline NEEDS[Io_apic::num_entries]
262 { return _apic->num_entries() + 1; }