[67a2288] | 1 | /* |
---|
[42e243e] | 2 | * cpu.h - This file contains definitions for data structure related |
---|
[67a2288] | 3 | * to Intel system programming. More information can be found |
---|
| 4 | * on Intel site and more precisely in the following book : |
---|
| 5 | * |
---|
| 6 | * Pentium Processor familly |
---|
| 7 | * Developper's Manual |
---|
| 8 | * |
---|
| 9 | * Volume 3 : Architecture and Programming Manual |
---|
| 10 | * |
---|
| 11 | * Copyright (C) 1998 Eric Valette (valette@crf.canon.fr) |
---|
| 12 | * Canon Centre Recherche France. |
---|
| 13 | * |
---|
| 14 | * The license and distribution terms for this file may be |
---|
[3f4598e] | 15 | * found in the file LICENSE in this distribution or at |
---|
[c499856] | 16 | * http://www.rtems.org/license/LICENSE. |
---|
[67a2288] | 17 | */ |
---|
| 18 | |
---|
[ab0df696] | 19 | #ifndef _LIBCPU_i386_CPU_H |
---|
| 20 | #define _LIBCPU_i386_CPU_H |
---|
| 21 | |
---|
[43f67aa4] | 22 | #include <rtems/score/registers.h> |
---|
[67a2288] | 23 | |
---|
| 24 | #ifndef ASM |
---|
| 25 | |
---|
| 26 | /* |
---|
| 27 | * Interrupt Level Macros |
---|
| 28 | */ |
---|
[43f67aa4] | 29 | #include <rtems/score/interrupts.h> |
---|
[67a2288] | 30 | |
---|
| 31 | /* |
---|
| 32 | * Segment Access Routines |
---|
| 33 | * |
---|
| 34 | * NOTE: Unfortunately, these are still static inlines even when the |
---|
| 35 | * "macro" implementation of the generic code is used. |
---|
| 36 | */ |
---|
| 37 | |
---|
[550c1b23] | 38 | static __inline__ unsigned short i386_get_cs(void) |
---|
[67a2288] | 39 | { |
---|
| 40 | register unsigned short segment = 0; |
---|
| 41 | |
---|
[550c1b23] | 42 | __asm__ volatile ( "movw %%cs,%0" : "=r" (segment) : "0" (segment) ); |
---|
[67a2288] | 43 | |
---|
| 44 | return segment; |
---|
| 45 | } |
---|
| 46 | |
---|
[550c1b23] | 47 | static __inline__ unsigned short i386_get_ds(void) |
---|
[67a2288] | 48 | { |
---|
| 49 | register unsigned short segment = 0; |
---|
| 50 | |
---|
[550c1b23] | 51 | __asm__ volatile ( "movw %%ds,%0" : "=r" (segment) : "0" (segment) ); |
---|
[67a2288] | 52 | |
---|
| 53 | return segment; |
---|
| 54 | } |
---|
| 55 | |
---|
[550c1b23] | 56 | static __inline__ unsigned short i386_get_es(void) |
---|
[67a2288] | 57 | { |
---|
| 58 | register unsigned short segment = 0; |
---|
| 59 | |
---|
[550c1b23] | 60 | __asm__ volatile ( "movw %%es,%0" : "=r" (segment) : "0" (segment) ); |
---|
[67a2288] | 61 | |
---|
| 62 | return segment; |
---|
| 63 | } |
---|
| 64 | |
---|
[550c1b23] | 65 | static __inline__ unsigned short i386_get_ss(void) |
---|
[67a2288] | 66 | { |
---|
| 67 | register unsigned short segment = 0; |
---|
| 68 | |
---|
[550c1b23] | 69 | __asm__ volatile ( "movw %%ss,%0" : "=r" (segment) : "0" (segment) ); |
---|
[67a2288] | 70 | |
---|
| 71 | return segment; |
---|
| 72 | } |
---|
| 73 | |
---|
[550c1b23] | 74 | static __inline__ unsigned short i386_get_fs(void) |
---|
[67a2288] | 75 | { |
---|
| 76 | register unsigned short segment = 0; |
---|
| 77 | |
---|
[550c1b23] | 78 | __asm__ volatile ( "movw %%fs,%0" : "=r" (segment) : "0" (segment) ); |
---|
[67a2288] | 79 | |
---|
| 80 | return segment; |
---|
| 81 | } |
---|
| 82 | |
---|
[550c1b23] | 83 | static __inline__ unsigned short i386_get_gs(void) |
---|
[67a2288] | 84 | { |
---|
| 85 | register unsigned short segment = 0; |
---|
| 86 | |
---|
[550c1b23] | 87 | __asm__ volatile ( "movw %%gs,%0" : "=r" (segment) : "0" (segment) ); |
---|
[67a2288] | 88 | |
---|
| 89 | return segment; |
---|
| 90 | } |
---|
| 91 | |
---|
| 92 | /* |
---|
| 93 | * IO Port Access Routines |
---|
| 94 | */ |
---|
| 95 | |
---|
| 96 | #define i386_outport_byte( _port, _value ) \ |
---|
[3772e2c] | 97 | do { register unsigned short __port = _port; \ |
---|
[67a2288] | 98 | register unsigned char __value = _value; \ |
---|
| 99 | \ |
---|
[550c1b23] | 100 | __asm__ volatile ( "outb %0,%1" : : "a" (__value), "d" (__port) ); \ |
---|
[3772e2c] | 101 | } while (0) |
---|
[67a2288] | 102 | |
---|
| 103 | #define i386_outport_word( _port, _value ) \ |
---|
[3772e2c] | 104 | do { register unsigned short __port = _port; \ |
---|
[67a2288] | 105 | register unsigned short __value = _value; \ |
---|
| 106 | \ |
---|
[550c1b23] | 107 | __asm__ volatile ( "outw %0,%1" : : "a" (__value), "d" (__port) ); \ |
---|
[3772e2c] | 108 | } while (0) |
---|
[67a2288] | 109 | |
---|
| 110 | #define i386_outport_long( _port, _value ) \ |
---|
[3772e2c] | 111 | do { register unsigned short __port = _port; \ |
---|
[67a2288] | 112 | register unsigned int __value = _value; \ |
---|
| 113 | \ |
---|
[550c1b23] | 114 | __asm__ volatile ( "outl %0,%1" : : "a" (__value), "d" (__port) ); \ |
---|
[3772e2c] | 115 | } while (0) |
---|
[67a2288] | 116 | |
---|
| 117 | #define i386_inport_byte( _port, _value ) \ |
---|
[3772e2c] | 118 | do { register unsigned short __port = _port; \ |
---|
[67a2288] | 119 | register unsigned char __value = 0; \ |
---|
| 120 | \ |
---|
[550c1b23] | 121 | __asm__ volatile ( "inb %1,%0" : "=a" (__value) \ |
---|
[3772e2c] | 122 | : "d" (__port) \ |
---|
[67a2288] | 123 | ); \ |
---|
| 124 | _value = __value; \ |
---|
[3772e2c] | 125 | } while (0) |
---|
[67a2288] | 126 | |
---|
| 127 | #define i386_inport_word( _port, _value ) \ |
---|
[3772e2c] | 128 | do { register unsigned short __port = _port; \ |
---|
[67a2288] | 129 | register unsigned short __value = 0; \ |
---|
| 130 | \ |
---|
[550c1b23] | 131 | __asm__ volatile ( "inw %1,%0" : "=a" (__value) \ |
---|
[3772e2c] | 132 | : "d" (__port) \ |
---|
[67a2288] | 133 | ); \ |
---|
| 134 | _value = __value; \ |
---|
[3772e2c] | 135 | } while (0) |
---|
[67a2288] | 136 | |
---|
| 137 | #define i386_inport_long( _port, _value ) \ |
---|
[3772e2c] | 138 | do { register unsigned short __port = _port; \ |
---|
[67a2288] | 139 | register unsigned int __value = 0; \ |
---|
| 140 | \ |
---|
[550c1b23] | 141 | __asm__ volatile ( "inl %1,%0" : "=a" (__value) \ |
---|
[3772e2c] | 142 | : "d" (__port) \ |
---|
[67a2288] | 143 | ); \ |
---|
| 144 | _value = __value; \ |
---|
[3772e2c] | 145 | } while (0) |
---|
[67a2288] | 146 | |
---|
| 147 | /* |
---|
[42e243e] | 148 | * Type definition for raw interrupts. |
---|
[67a2288] | 149 | */ |
---|
| 150 | |
---|
| 151 | typedef unsigned char rtems_vector_offset; |
---|
| 152 | |
---|
| 153 | typedef struct __rtems_raw_irq_connect_data__{ |
---|
| 154 | /* |
---|
| 155 | * IDT vector offset (IRQ line + PC386_IRQ_VECTOR_BASE) |
---|
| 156 | */ |
---|
| 157 | rtems_vector_offset idtIndex; |
---|
| 158 | /* |
---|
| 159 | * IDT raw handler. See comment on handler properties below in function prototype. |
---|
| 160 | */ |
---|
| 161 | rtems_raw_irq_hdl hdl; |
---|
| 162 | /* |
---|
| 163 | * function for enabling raw interrupts. In order to be consistent |
---|
| 164 | * with the fact that the raw connexion can defined in the |
---|
| 165 | * libcpu library, this library should have no knowledge of |
---|
| 166 | * board specific hardware to manage interrupts and thus the |
---|
| 167 | * "on" routine must enable the irq both at device and PIC level. |
---|
[42e243e] | 168 | * |
---|
[67a2288] | 169 | */ |
---|
[42e243e] | 170 | rtems_raw_irq_enable on; |
---|
[67a2288] | 171 | /* |
---|
| 172 | * function for disabling raw interrupts. In order to be consistent |
---|
| 173 | * with the fact that the raw connexion can defined in the |
---|
| 174 | * libcpu library, this library should have no knowledge of |
---|
| 175 | * board specific hardware to manage interrupts and thus the |
---|
| 176 | * "on" routine must disable the irq both at device and PIC level. |
---|
[42e243e] | 177 | * |
---|
[67a2288] | 178 | */ |
---|
| 179 | rtems_raw_irq_disable off; |
---|
| 180 | /* |
---|
| 181 | * function enabling to know what interrupt may currently occur |
---|
| 182 | */ |
---|
| 183 | rtems_raw_irq_is_enabled isOn; |
---|
| 184 | }rtems_raw_irq_connect_data; |
---|
| 185 | |
---|
| 186 | typedef struct { |
---|
| 187 | /* |
---|
| 188 | * size of all the table fields (*Tbl) described below. |
---|
| 189 | */ |
---|
| 190 | unsigned int idtSize; |
---|
| 191 | /* |
---|
| 192 | * Default handler used when disconnecting interrupts. |
---|
| 193 | */ |
---|
| 194 | rtems_raw_irq_connect_data defaultRawEntry; |
---|
| 195 | /* |
---|
| 196 | * Table containing initials/current value. |
---|
| 197 | */ |
---|
| 198 | rtems_raw_irq_connect_data* rawIrqHdlTbl; |
---|
| 199 | }rtems_raw_irq_global_settings; |
---|
| 200 | |
---|
[43f67aa4] | 201 | #include <rtems/score/idtr.h> |
---|
[67a2288] | 202 | |
---|
| 203 | /* |
---|
| 204 | * C callable function enabling to get handler currently connected to a vector |
---|
[42e243e] | 205 | * |
---|
[67a2288] | 206 | */ |
---|
| 207 | rtems_raw_irq_hdl get_hdl_from_vector(rtems_vector_offset); |
---|
| 208 | |
---|
| 209 | /* |
---|
| 210 | * C callable function enabling to set up one raw idt entry |
---|
| 211 | */ |
---|
| 212 | extern int i386_set_idt_entry (const rtems_raw_irq_connect_data*); |
---|
| 213 | |
---|
| 214 | /* |
---|
| 215 | * C callable function enabling to get one current raw idt entry |
---|
| 216 | */ |
---|
| 217 | extern int i386_get_current_idt_entry (rtems_raw_irq_connect_data*); |
---|
| 218 | |
---|
| 219 | /* |
---|
| 220 | * C callable function enabling to remove one current raw idt entry |
---|
| 221 | */ |
---|
| 222 | extern int i386_delete_idt_entry (const rtems_raw_irq_connect_data*); |
---|
| 223 | |
---|
| 224 | /* |
---|
| 225 | * C callable function enabling to init idt. |
---|
| 226 | * |
---|
| 227 | * CAUTION : this function assumes that the IDTR register |
---|
| 228 | * has been already set. |
---|
| 229 | */ |
---|
| 230 | extern int i386_init_idt (rtems_raw_irq_global_settings* config); |
---|
| 231 | |
---|
| 232 | /* |
---|
| 233 | * C callable function enabling to get actual idt configuration |
---|
| 234 | */ |
---|
| 235 | extern int i386_get_idt_config (rtems_raw_irq_global_settings** config); |
---|
| 236 | |
---|
| 237 | |
---|
| 238 | /* |
---|
| 239 | * See page 11.12 Figure 11-8. |
---|
| 240 | * |
---|
| 241 | */ |
---|
| 242 | |
---|
| 243 | typedef struct { |
---|
| 244 | unsigned int limit_15_0 : 16; |
---|
| 245 | unsigned int base_address_15_0 : 16; |
---|
| 246 | unsigned int base_address_23_16 : 8; |
---|
| 247 | unsigned int type : 4; |
---|
| 248 | unsigned int descriptor_type : 1; |
---|
| 249 | unsigned int privilege : 2; |
---|
| 250 | unsigned int present : 1; |
---|
| 251 | unsigned int limit_19_16 : 4; |
---|
| 252 | unsigned int available : 1; |
---|
| 253 | unsigned int fixed_value_bits : 1; |
---|
| 254 | unsigned int operation_size : 1; |
---|
| 255 | unsigned int granularity : 1; |
---|
| 256 | unsigned int base_address_31_24 : 8; |
---|
| 257 | }segment_descriptors; |
---|
| 258 | |
---|
| 259 | /* |
---|
| 260 | * C callable function enabling to get easilly usable info from |
---|
| 261 | * the actual value of GDT register. |
---|
| 262 | */ |
---|
| 263 | extern void i386_get_info_from_GDTR (segment_descriptors** table, |
---|
| 264 | unsigned* limit); |
---|
| 265 | /* |
---|
| 266 | * C callable function enabling to change the value of GDT register. Must be called |
---|
| 267 | * with interrupts masked at processor level!!!. |
---|
| 268 | */ |
---|
| 269 | extern void i386_set_GDTR (segment_descriptors*, |
---|
| 270 | unsigned limit); |
---|
| 271 | |
---|
| 272 | /* |
---|
| 273 | * C callable function enabling to set up one raw interrupt handler |
---|
| 274 | */ |
---|
| 275 | extern int i386_set_gdt_entry (unsigned short segment_selector, unsigned base, |
---|
| 276 | unsigned limit); |
---|
| 277 | |
---|
[e029467] | 278 | /* |
---|
| 279 | * See page 11.18 Figure 11-12. |
---|
| 280 | * |
---|
| 281 | */ |
---|
| 282 | |
---|
| 283 | typedef struct { |
---|
| 284 | unsigned int offset : 12; |
---|
| 285 | unsigned int page : 10; |
---|
| 286 | unsigned int directory : 10; |
---|
| 287 | }la_bits; |
---|
| 288 | |
---|
| 289 | typedef union { |
---|
| 290 | la_bits bits; |
---|
| 291 | unsigned int address; |
---|
| 292 | }linear_address; |
---|
| 293 | |
---|
| 294 | |
---|
| 295 | /* |
---|
| 296 | * See page 11.20 Figure 11-14. |
---|
| 297 | * |
---|
| 298 | */ |
---|
| 299 | |
---|
| 300 | typedef struct { |
---|
| 301 | unsigned int present : 1; |
---|
| 302 | unsigned int writable : 1; |
---|
| 303 | unsigned int user : 1; |
---|
| 304 | unsigned int write_through : 1; |
---|
| 305 | unsigned int cache_disable : 1; |
---|
| 306 | unsigned int accessed : 1; |
---|
| 307 | unsigned int reserved1 : 1; |
---|
| 308 | unsigned int page_size : 1; |
---|
| 309 | unsigned int reserved2 : 1; |
---|
| 310 | unsigned int available : 3; |
---|
| 311 | unsigned int page_frame_address : 20; |
---|
| 312 | }page_dir_bits; |
---|
| 313 | |
---|
| 314 | typedef union { |
---|
| 315 | page_dir_bits bits; |
---|
| 316 | unsigned int dir_entry; |
---|
| 317 | }page_dir_entry; |
---|
| 318 | |
---|
| 319 | typedef struct { |
---|
| 320 | unsigned int present : 1; |
---|
| 321 | unsigned int writable : 1; |
---|
| 322 | unsigned int user : 1; |
---|
| 323 | unsigned int write_through : 1; |
---|
| 324 | unsigned int cache_disable : 1; |
---|
| 325 | unsigned int accessed : 1; |
---|
| 326 | unsigned int dirty : 1; |
---|
| 327 | unsigned int reserved2 : 2; |
---|
| 328 | unsigned int available : 3; |
---|
| 329 | unsigned int page_frame_address : 20; |
---|
| 330 | }page_table_bits; |
---|
| 331 | |
---|
| 332 | typedef union { |
---|
| 333 | page_table_bits bits; |
---|
| 334 | unsigned int table_entry; |
---|
[60e6a0f] | 335 | } page_table_entry; |
---|
[42e243e] | 336 | |
---|
[e029467] | 337 | /* |
---|
| 338 | * definitions related to page table entry |
---|
| 339 | */ |
---|
| 340 | #define PG_SIZE 0x1000 |
---|
| 341 | #define MASK_OFFSET 0xFFF |
---|
| 342 | #define MAX_ENTRY (PG_SIZE/sizeof(page_dir_entry)) |
---|
| 343 | #define FOUR_MB 0x400000 |
---|
| 344 | #define MASK_FLAGS 0x1A |
---|
| 345 | |
---|
| 346 | #define PTE_PRESENT 0x01 |
---|
| 347 | #define PTE_WRITABLE 0x02 |
---|
| 348 | #define PTE_USER 0x04 |
---|
| 349 | #define PTE_WRITE_THROUGH 0x08 |
---|
| 350 | #define PTE_CACHE_DISABLE 0x10 |
---|
| 351 | |
---|
| 352 | typedef struct { |
---|
| 353 | page_dir_entry pageDirEntry[MAX_ENTRY]; |
---|
[60e6a0f] | 354 | } page_directory; |
---|
[e029467] | 355 | |
---|
| 356 | typedef struct { |
---|
| 357 | page_table_entry pageTableEntry[MAX_ENTRY]; |
---|
[60e6a0f] | 358 | } page_table; |
---|
[e029467] | 359 | |
---|
| 360 | |
---|
| 361 | /* C declaration for paging management */ |
---|
| 362 | |
---|
[7d0e7021] | 363 | extern int _CPU_is_cache_enabled(void); |
---|
| 364 | extern int _CPU_is_paging_enabled(void); |
---|
| 365 | extern int init_paging(void); |
---|
| 366 | extern void _CPU_enable_paging(void); |
---|
| 367 | extern void _CPU_disable_paging(void); |
---|
| 368 | extern void _CPU_disable_cache(void); |
---|
| 369 | extern void _CPU_enable_cache(void); |
---|
[e029467] | 370 | extern int _CPU_map_phys_address |
---|
| 371 | (void **mappedAddress, void *physAddress, |
---|
[42e243e] | 372 | int size, int flag); |
---|
| 373 | extern int _CPU_unmap_virt_address (void *mappedAddress, int size); |
---|
[e029467] | 374 | extern int _CPU_change_memory_mapping_attribute |
---|
| 375 | (void **newAddress, void *mappedAddress, |
---|
| 376 | unsigned int size, unsigned int flag); |
---|
[7d0e7021] | 377 | extern int _CPU_display_memory_attribute(void); |
---|
[e029467] | 378 | |
---|
[67a2288] | 379 | # endif /* ASM */ |
---|
| 380 | |
---|
| 381 | #endif |
---|