1 /*
2  * Copyright (c) 2006-2021, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  */
8 #ifndef __I386_H_
9 #define __I386_H_
10 
11 #ifdef __cplusplus
12 extern "C" {
13 #endif
14 
inb(int port)15 static __inline unsigned char inb(int port)
16 {
17     unsigned char data;
18     __asm __volatile("inb %w1,%0" : "=a" (data) : "d" (port));
19     return data;
20 }
inb_p(unsigned short port)21 static __inline unsigned char inb_p(unsigned short port)
22 {
23     unsigned char _v;
24     __asm__ __volatile__ ("inb %1, %0\n\t"
25                           "outb %0,$0x80"
26                           :"=a" (_v)
27                           :"d" ((unsigned short) port));
28     return _v;
29 }
30 
inw(int port)31 static __inline unsigned short inw(int port)
32 {
33     unsigned short data;
34     __asm __volatile("inw %w1,%0" : "=a" (data) : "d" (port));
35     return data;
36 }
37 
inl(int port)38 static __inline unsigned int inl(int port)
39 {
40     unsigned int data;
41     __asm __volatile("inl %w1,%0" : "=a" (data) : "d" (port));
42     return data;
43 }
44 
insl(int port,void * addr,int cnt)45 static __inline void insl(int port, void *addr, int cnt)
46 {
47     __asm __volatile("cld\n\trepne\n\tinsl"         :
48              "=D" (addr), "=c" (cnt)        :
49              "d" (port), "0" (addr), "1" (cnt)  :
50              "memory", "cc");
51 }
52 
outb(int port,unsigned char data)53 static __inline void outb(int port, unsigned char data)
54 {
55     __asm __volatile("outb %0,%w1" : : "a" (data), "d" (port));
56 }
57 
58 
outb_p(char value,unsigned short port)59 static __inline void outb_p(char value, unsigned short port)
60 {
61     __asm__ __volatile__ ("outb %0,%1\n\t"
62                           "outb %0,$0x80"
63                           ::"a" ((char) value),"d" ((unsigned short) port));
64 }
65 
outw(int port,unsigned short data)66 static __inline void outw(int port, unsigned short data)
67 {
68     __asm __volatile("outw %0,%w1" : : "a" (data), "d" (port));
69 }
70 
readcmos(int reg)71 static __inline unsigned char readcmos(int reg)
72 {
73     outb(0x70,reg);
74     return (unsigned char) inb(0x71);
75 }
76 
77 #define io_delay()                      \
78     __asm__ __volatile__ ("pushal \n\t" \
79             "mov $0x3F6, %dx \n\t"      \
80             "inb %dx, %al \n\t"         \
81             "inb %dx, %al \n\t"         \
82             "inb %dx, %al \n\t"         \
83             "inb %dx, %al \n\t"         \
84                           "popal")
85 
86 /* Gate descriptors are slightly different*/
87 struct Gatedesc {
88     unsigned gd_off_15_0 : 16;   // low 16 bits of offset in segment
89     unsigned gd_ss : 16;         // segment selector
90     unsigned gd_args : 5;        // # args, 0 for interrupt/trap gates
91     unsigned gd_rsv1 : 3;        // reserved(should be zero I guess)
92     unsigned gd_type :4;         // type(STS_{TG,IG32,TG32})
93     unsigned gd_s : 1;           // must be 0 (system)
94     unsigned gd_dpl : 2;         // descriptor(meaning new) privilege level
95     unsigned gd_p : 1;           // Present
96     unsigned gd_off_31_16 : 16;  // high bits of offset in segment
97 };
98 
99 /* Pseudo-descriptors used for LGDT, LLDT and LIDT instructions*/
100 struct Pseudodesc {
101     rt_uint16_t pd__garbage;         // LGDT supposed to be from address 4N+2
102     rt_uint16_t pd_lim;              // Limit
103     rt_uint32_t pd_base __attribute__ ((packed));       // Base address
104 };
105 
106 #define SETGATE(gate, istrap, sel, off, dpl)             \
107     {                                                    \
108         (gate).gd_off_15_0 = (rt_uint32_t)(off)&0xffff;  \
109         (gate).gd_ss = (sel);                            \
110         (gate).gd_args = 0;                              \
111         (gate).gd_rsv1 = 0;                              \
112         (gate).gd_type = (istrap) ? STS_TG32 : STS_IG32; \
113         (gate).gd_s = 0;                                 \
114         (gate).gd_dpl = dpl;                             \
115         (gate).gd_p = 1;                                 \
116         (gate).gd_off_31_16 = (rt_uint32_t)(off) >> 16;  \
117     }
118 
119 /* Global descriptor numbers*/
120 #define GD_KT 0x08 // kernel text
121 #define GD_KD 0x10 // kernel data
122 #define GD_UT 0x18 // user text
123 #define GD_UD 0x20 // user data
124 
125 /* Application segment type bits*/
126 #define STA_X 0x8 // Executable segment
127 #define STA_E 0x4 // Expand down(non-executable segments)
128 #define STA_C 0x4 // Conforming code segment(executable only)
129 #define STA_W 0x2 // Writeable(non-executable segments)
130 #define STA_R 0x2 // Readable(executable segments)
131 #define STA_A 0x1 // Accessed
132 
133 /* System segment type bits*/
134 #define STS_T16A 0x1 // Available 16-bit TSS
135 #define STS_LDT  0x2 // Local Descriptor Table
136 #define STS_T16B 0x3 // Busy 16-bit TSS
137 #define STS_CG16 0x4 // 16-bit Call Gate
138 #define STS_TG   0x5 // Task Gate / Coum Transmitions
139 #define STS_IG16 0x6 // 16-bit Interrupt Gate
140 #define STS_TG16 0x7 // 16-bit Trap Gate
141 #define STS_T32A 0x9 // Available 32-bit TSS
142 #define STS_T32B 0xb // Busy 32-bit TSS
143 #define STS_CG32 0xc // 32-bit Call Gate
144 #define STS_IG32 0xe // 32-bit Interrupt Gate
145 #define STS_TG32 0xf // 32-bit Trap Gate
146 
147 #ifdef __cplusplus
148  }
149 #endif
150 
151 #endif
152