Intel® Quark™ Microcontroller Software Interface  1.4.0
Intel® Quark™ Microcontroller BSP
idt.h
1 /*
2  * {% copyright %}
3  */
4 #ifndef __IDT_H__
5 #define __IDT_H__
6 
7 #include <stdint.h>
8 #include <string.h>
9 #include "qm_common.h"
10 #include "qm_soc_regs.h"
11 
12 #if (QUARK_SE)
13 #define IDT_NUM_GATES (68)
14 #elif(QUARK_D2000)
15 #define IDT_NUM_GATES (52)
16 #endif
17 
18 #define IDT_SIZE (sizeof(intr_gate_desc_t) * IDT_NUM_GATES)
19 
20 typedef struct idtr {
21  uint16_t limit;
22  uint32_t base;
23 } __attribute__((packed)) idtr_t;
24 
25 typedef struct intr_gate_desc {
26  uint16_t isr_low;
27  uint16_t selector; /* Segment selector */
28 
29  /* The format of conf is the following:
30 
31  15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
32  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
33  |p |dpl |ss|d |type | unused |
34 
35  type: Gate type
36  d: size of Gate
37  ss: Storage Segment
38  dpl: Descriptor Privilege level
39  p: Segment present level
40  */
41  uint16_t conf;
42  uint16_t isr_high;
43 } __attribute__((packed)) intr_gate_desc_t;
44 
45 extern intr_gate_desc_t __idt_start[];
46 
47 /*
48  * Setup IDT gate as an interrupt descriptor and assing the ISR entry point
49  */
50 static __inline__ void idt_set_intr_gate_desc(uint32_t vector, uint32_t isr)
51 {
52  intr_gate_desc_t *desc;
53  idtr_t idtr;
54 
55  desc = __idt_start + vector;
56 
57  desc->isr_low = isr & 0xFFFF;
58  desc->selector = 0x08; /* Code segment offset in GDT */
59 
60  desc->conf = 0x8E00; /* type: 0b11 (Interrupt)
61  d: 1 (32 bits)
62  ss: 0
63  dpl: 0
64  p: 1
65  */
66  desc->isr_high = (isr >> 16) & 0xFFFF;
67 
68  /* The following reloads the IDTR register. If a lookaside buffer is
69  * being used this will invalidate it. This is required as it's possible
70  * for an application to change the registered ISR. */
71  idtr.limit = IDT_SIZE - 1;
72  idtr.base = (uint32_t)__idt_start;
73  __asm__ __volatile__("lidt %0\n\t" ::"m"(idtr));
74 }
75 
76 /*
77  * Initialize Interrupt Descriptor Table.
78  * The IDT is initialized with null descriptors: any interrupt at this stage
79  * will cause a triple fault.
80  */
81 static __inline__ void idt_init(void)
82 {
83  idtr_t idtr;
84 
85  memset(__idt_start, 0x00, IDT_SIZE);
86 
87  /* Initialize idtr structure */
88  idtr.limit = IDT_SIZE - 1;
89  idtr.base = (uint32_t)__idt_start;
90 
91  /* Load IDTR register */
92  __asm__ __volatile__("lidt %0\n\t" ::"m"(idtr));
93 }
94 #endif /* __IDT_H__ */