1 /* Copyright (C) 1994, 1997 Free Software Foundation, Inc.
2 Contributed by Joel Sherrill (jsherril@redstone-emh2.army.mil),
3 On-Line Applications Research Corporation.
4 This file is part of the GNU C Library.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, write to the Free
18 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
23 * This file contains macros which are used to access i80386
24 * registers which are not addressable by C. This file contains
25 * functions which are useful to those developing target
26 * specific support routines.
32 typedef unsigned char unsigned8
;
33 typedef unsigned short unsigned16
;
34 typedef unsigned int unsigned32
;
36 #define disable_intr( isrlevel ) \
38 asm volatile ( "pushf ; \
41 : "=r" ((isrlevel)) : "0" ((isrlevel)) ); \
45 #define enable_intr( isrlevel ) \
46 { asm volatile ( "push %0 ; \
48 : "=r" ((isrlevel)) : "0" ((isrlevel)) ); \
51 #define delay( _microseconds ) \
53 unsigned32 _counter; \
55 _counter = (_microseconds); \
57 asm volatile ( "0: nop;" \
59 " loop 0" : "=c" (_counter) \
65 /* segment access functions */
67 static inline unsigned16
get_cs()
69 register unsigned16 segment
= 0;
71 asm volatile ( "movw %%cs,%0" : "=r" (segment
) : "0" (segment
) );
76 static inline unsigned16
get_ds()
78 register unsigned16 segment
= 0;
80 asm volatile ( "movw %%ds,%0" : "=r" (segment
) : "0" (segment
) );
85 static inline unsigned16
get_es()
87 register unsigned16 segment
= 0;
89 asm volatile ( "movw %%es,%0" : "=r" (segment
) : "0" (segment
) );
94 static inline unsigned16
get_ss()
96 register unsigned16 segment
= 0;
98 asm volatile ( "movw %%ss,%0" : "=r" (segment
) : "0" (segment
) );
103 static inline unsigned16
get_fs()
105 register unsigned16 segment
= 0;
107 asm volatile ( "movw %%fs,%0" : "=r" (segment
) : "0" (segment
) );
112 static inline unsigned16
get_gs()
114 register unsigned16 segment
= 0;
116 asm volatile ( "movw %%gs,%0" : "=r" (segment
) : "0" (segment
) );
121 /* i80x86 I/O instructions */
123 #define outport_byte( _port, _value ) \
124 { register unsigned16 __port = _port; \
125 register unsigned8 __value = _value; \
127 asm volatile ( "outb %0,%1" : "=a" (__value), "=d" (__port) \
128 : "0" (__value), "1" (__port) \
132 #define outport_word( _port, _value ) \
133 { register unsigned16 __port = _port; \
134 register unsigned16 __value = _value; \
136 asm volatile ( "outw %0,%1" : "=a" (__value), "=d" (__port) \
137 : "0" (__value), "1" (__port) \
141 #define outport_long( _port, _value ) \
142 { register unsigned16 __port = _port; \
143 register unsigned32 __value = _value; \
145 asm volatile ( "outl %0,%1" : "=a" (__value), "=d" (__port) \
146 : "0" (__value), "1" (__port) \
150 #define inport_byte( _port, _value ) \
151 { register unsigned16 __port = _port; \
152 register unsigned8 __value = 0; \
154 asm volatile ( "inb %1,%0" : "=a" (__value), "=d" (__port) \
155 : "0" (__value), "1" (__port) \
160 #define inport_word( _port, _value ) \
161 { register unsigned16 __port = _port; \
162 register unsigned16 __value = 0; \
164 asm volatile ( "inw %1,%0" : "=a" (__value), "=d" (__port) \
165 : "0" (__value), "1" (__port) \
170 #define inport_long( _port, _value ) \
171 { register unsigned16 __port = _port; \
172 register unsigned32 __value = 0; \
174 asm volatile ( "inl %1,%0" : "=a" (__value), "=d" (__port) \
175 : "0" (__value), "1" (__port) \
182 /* See Chapter 5 - Memory Management in i386 manual */
185 unsigned16 limit_0_15
;
186 unsigned16 base_0_15
;
187 unsigned8 base_16_23
;
188 unsigned8 type_dt_dpl_p
;
189 unsigned8 limit_16_19_granularity
;
190 unsigned8 base_24_31
;
193 /* See Chapter 9 - Exceptions and Interrupts in i386 manual
195 * NOTE: This is the IDT entry for interrupt gates ONLY.
199 unsigned16 offset_0_15
;
200 unsigned16 segment_selector
;
203 unsigned16 offset_16_31
;
206 struct DTR_load_save_format
{
208 unsigned32 physical_address
;
213 extern struct IDT_slot Interrupt_descriptor_table
[ 256 ];
214 extern struct GDT_slot Global_descriptor_table
[ 8192 ];
218 #ifdef CPU_INITIALIZE
222 #define EXTERN extern
225 void *Logical_to_physical(
230 void *Physical_to_logical(
235 /* complicated static inline functions */
237 #define get_GDTR( _gdtr_address ) \
239 void *_gdtr = (_gdtr_address); \
241 asm volatile( "sgdt (%0)" : "=r" (_gdtr) : "0" (_gdtr) ); \
244 #define get_GDT_slot( _gdtr_base, _segment, _slot_address ) \
246 register unsigned32 _gdt_slot = (_gdtr_base) + (_segment); \
247 register volatile void *_slot = (_slot_address); \
248 register unsigned32 _temporary = 0; \
250 asm volatile( "movl %%gs:(%0),%1 ; \
252 movl %%gs:4(%0),%1 ; \
254 : "=r" (_gdt_slot), "=r" (_temporary), "=r" (_slot) \
255 : "0" (_gdt_slot), "1" (_temporary), "2" (_slot) \
259 #define set_GDT_slot( _gdtr_base, _segment, _slot_address ) \
261 register unsigned32 _gdt_slot = (_gdtr_base) + (_segment); \
262 register volatile void *_slot = (_slot_address); \
263 register unsigned32 _temporary = 0; \
265 asm volatile( "movl (%2),%1 ; \
266 movl %1,%%gs:(%0) ; \
270 : "=r" (_gdt_slot), "=r" (_temporary), "=r" (_slot) \
271 : "0" (_gdt_slot), "1" (_temporary), "2" (_slot) \
275 static inline void set_segment(
281 struct DTR_load_save_format gdtr
;
282 volatile struct GDT_slot Gdt_slot
;
283 volatile struct GDT_slot
*gdt_slot
= &Gdt_slot
;
284 unsigned16 tmp_segment
= 0;
285 unsigned32 limit_adjusted
;
288 /* load physical address of the GDT */
292 gdt_slot
->type_dt_dpl_p
= 0x92; /* present, dpl=0, */
294 /* type=data read/write */
295 gdt_slot
->limit_16_19_granularity
= 0x40; /* 32 bit segment */
297 limit_adjusted
= limit
;
298 if ( limit
> 4095 ) {
299 gdt_slot
->limit_16_19_granularity
|= 0x80; /* set granularity bit */
300 limit_adjusted
/= 4096;
303 gdt_slot
->limit_16_19_granularity
|= (limit_adjusted
>> 16) & 0xff;
304 gdt_slot
->limit_0_15
= limit_adjusted
& 0xffff;
306 gdt_slot
->base_0_15
= base
& 0xffff;
307 gdt_slot
->base_16_23
= (base
>> 16) & 0xff;
308 gdt_slot
->base_24_31
= (base
>> 24);
310 set_GDT_slot( gdtr
.physical_address
, segment
, gdt_slot
);
312 /* Now, reload all segment registers so the limit takes effect. */
314 asm volatile( "movw %%ds,%0 ; movw %0,%%ds\n"
315 "movw %%es,%0 ; movw %0,%%es\n"
316 "movw %%fs,%0 ; movw %0,%%fs\n"
317 "movw %%gs,%0 ; movw %0,%%gs\n"
318 "movw %%ss,%0 ; movw %0,%%ss"
326 /* end of include file */