1 INTERFACE[ia32,amd64,ux]:
7 EXTENSION class Dirq_pic_pin
10 class Chip : public Irq_chip
13 static unsigned vector(unsigned irq)
15 return (irq < 0x10) ? irq + 0x20 : irq + 0x30;
18 bool reserve(unsigned irq);
19 void reset(unsigned irq);
20 Irq_base *irq(unsigned irq);
21 bool is_free(unsigned irq);
22 bool alloc(Irq_base *irq, unsigned irqnum);
23 bool free(Irq_base *irq, unsigned irqnum);
24 void setup(Irq_base *irq, unsigned irqnum);
26 unsigned nr_irqs() const { return 16; }
28 bool valloc(Irq_base *irq, unsigned vector);
29 static bool vfree(Irq_base *irq, unsigned vector, void *handler);
30 virtual void disable_irq(unsigned vector);
33 Irq_base *virq(unsigned v);
38 IMPLEMENTATION [ia32,ux]:
39 enum { Register_arg0 = 0 }; // eax
41 IMPLEMENTATION [amd64]:
42 enum { Register_arg0 = 7 }; // rdi
44 IMPLEMENTATION[ia32,amd64,ux]:
49 #include "globalconfig.h"
68 } __attribute__((packed)) _d;
71 void irq(Irq_base *irq)
73 _d.irq_adr = (Address)irq;
77 { return nonull_static_cast<Irq*>((Irq_base*)((Smword)(_d.irq_adr))); }
89 static Entry_code _entry_code[256-0x20];
95 extern char __generic_irq_entry[];
97 _d.push = 0x50 + Register_arg0;
99 // mov imm32, %eax/%rdi
100 _d.mov = 0xb8 + Register_arg0;
103 // jmp __generic_irq_entry
105 _d.jmp_adr = (Address)__generic_irq_entry - (Address)&_d - 11;
108 /** The corresponding hardware interrupt occurred -- handle it.
109 This method checks whether the attached receiver is ready to receive
110 an IRQ message, and if so, restarts it so that it can pick up the IRQ
111 message using ipc_receiver_ready().
115 ".global __irq_entry_template \n"
116 ".global __irq_entry_template_end \n"
118 "__irq_entry_template: \n"
122 // " mov $0, %eax \n"
123 " jmp __generic_irq_entry \n"
124 "__irq_entry_template_end: \n"
130 Dirq_pic_pin::Chip::is_free(unsigned irqn)
132 if (irqn >= Config::Max_num_dirqs)
135 unsigned v = vector(irqn);
136 return _entry_code[v -0x20].is_free();
141 Dirq_pic_pin::Chip::virq(unsigned v)
143 return _entry_code[v -0x20].irq();
148 Dirq_pic_pin::Chip::irq(unsigned irqn)
150 if (irqn >= Config::Max_num_dirqs)
153 unsigned v = vector(irqn);
161 Dirq_pic_pin::Chip::disable_irq(unsigned vector)
163 extern char entry_int_pic_ignore[];
164 Idt::set_entry(vector, Address(&entry_int_pic_ignore), false);
169 Dirq_pic_pin::Chip::alloc(Irq_base *irq, unsigned irqn)
171 if (irqn >= Config::Max_num_dirqs)
174 unsigned v = vector(irqn);
186 Dirq_pic_pin::Chip::valloc(Irq_base *irq, unsigned v)
188 if (v >= APIC_IRQ_BASE - 0x10)
191 if (!_entry_code[v -0x20].is_free())
194 _entry_code[v -0x20].setup();
195 _entry_code[v -0x20].irq(irq);
198 // force code to memory before setting IDT entry
199 asm volatile ( "" : : : "memory" );
201 Idt::set_entry(v, (Address)&_entry_code[v -0x20], false);
207 Dirq_pic_pin::Chip::free(Irq_base *irq, unsigned irqn)
209 if (irqn >= Config::Max_num_dirqs)
212 unsigned v = vector(irqn);
213 return vfree(irq, v, 0);
218 Dirq_pic_pin::Chip::vfree(Irq_base *irq, unsigned v, void *handler)
220 if (v >= APIC_IRQ_BASE - 0x10)
223 if (_entry_code[v -0x20].is_free())
226 if (_entry_code[v-0x20].irq() != irq)
229 _entry_code[v-0x20].free();
231 Idt::set_entry(v, (Address)handler, false);
237 Dirq_pic_pin::Chip::reset(unsigned irqn)
239 unsigned v = vector(irqn);
240 Idt::set_entry(v, (Address)&_entry_code[v -0x20], false);
245 Dirq_pic_pin::Chip::setup(Irq_base *irq, unsigned irqnum)
247 irq->pin()->replace<Dirq_pic_pin>(irqnum);
252 Dirq_pic_pin::Chip::reserve(unsigned irqn)
254 if (irqn >= Config::Max_num_dirqs)
257 unsigned v = vector(irqn);
258 if (!_entry_code[v -0x20].is_free())
261 _entry_code[v -0x20].setup();
267 Dirq_pic_pin::vector() const
268 { return irq() < 0x10 ? irq() + 0x20 : irq() + 0x30; }
270 extern "C" void entry_int_pic_ignore(void);
275 Dirq_pic_pin::disable_vector()
277 unsigned vector = this->vector();
278 _entry_code[vector -0x20].free();
282 Dirq_pic_pin::disable()
284 unsigned vector = this->vector();
285 Idt::set_entry(vector, Address(&entry_int_pic_ignore), false);
286 _entry_code[vector -0x20].free();
290 IMPLEMENT FIASCO_INIT
295 Irq_chip::hw_chip = &_ia;