source: rtems/c/src/lib/libcpu/i386/cpu.h @ e029467

4.104.114.84.95
Last change on this file since e029467 was e029467, checked in by Joel Sherrill <joel.sherrill@…>, on Feb 18, 1999 at 3:16:37 PM

Patch from Emmanuel Raguet <raguet@…>:

You will find enclosed a patch which contains, for Intel PC386 target :

  • an Ethernet driver for DEC21140 device based boards.
  • a simple cache management with paging mechanism.
  • Property mode set to 100644
File size: 12.9 KB
Line 
1/*
2 * cpu.h  - This file contains definitions for data structure related
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
15 *  found in found in the file LICENSE in this distribution or at
16 *  http://www.OARcorp.com/rtems/license.html.
17 *
18 * $Id$
19 */
20
21#ifndef _LIBCPU_i386_CPU_H
22#define _LIBCPU_i386_CPU_H
23
24#include <libcpu/registers.h>
25
26
27#ifndef ASM
28
29/*
30 *  Interrupt Level Macros
31 */
32
33#define i386_disable_interrupts( _level ) \
34  { \
35    _level = 0;   /* avoids warnings */ \
36    asm volatile ( "pushf ; \
37                    cli ; \
38                    pop %0" \
39                    : "=r" ((_level)) : "0" ((_level)) \
40    ); \
41  }
42
43#define i386_enable_interrupts( _level )  \
44  { \
45    asm volatile ( "push %0 ; \
46                    popf" \
47                    : "=r" ((_level)) : "0" ((_level)) \
48    ); \
49  }
50
51#define i386_flash_interrupts( _level ) \
52  { \
53    asm volatile ( "push %0 ; \
54                    popf ; \
55                    cli" \
56                    : "=r" ((_level)) : "0" ((_level)) \
57    ); \
58  }
59
60#define i386_get_interrupt_level( _level ) \
61  do { \
62    register unsigned32 _eflags = 0; \
63    \
64    asm volatile ( "pushf ; \
65                    pop %0" \
66                    : "=r" ((_eflags)) : "0" ((_eflags)) \
67    ); \
68    \
69    _level = (_eflags &  EFLAGS_INTR_ENABLE) ? 0 : 1; \
70  } while (0)
71
72#define _CPU_ISR_Disable( _level ) i386_disable_interrupts( _level )
73#define _CPU_ISR_Enable( _level ) i386_enable_interrupts( _level )
74     
75/*
76 *  Segment Access Routines
77 *
78 *  NOTE:  Unfortunately, these are still static inlines even when the
79 *         "macro" implementation of the generic code is used.
80 */
81
82static inline unsigned short i386_get_cs()
83{
84  register unsigned short segment = 0;
85
86  asm volatile ( "movw %%cs,%0" : "=r" (segment) : "0" (segment) );
87
88  return segment;
89}
90
91static inline unsigned short i386_get_ds()
92{
93  register unsigned short segment = 0;
94
95  asm volatile ( "movw %%ds,%0" : "=r" (segment) : "0" (segment) );
96
97  return segment;
98}
99
100static inline unsigned short i386_get_es()
101{
102  register unsigned short segment = 0;
103
104  asm volatile ( "movw %%es,%0" : "=r" (segment) : "0" (segment) );
105
106  return segment;
107}
108
109static inline unsigned short i386_get_ss()
110{
111  register unsigned short segment = 0;
112
113  asm volatile ( "movw %%ss,%0" : "=r" (segment) : "0" (segment) );
114
115  return segment;
116}
117
118static inline unsigned short i386_get_fs()
119{
120  register unsigned short segment = 0;
121
122  asm volatile ( "movw %%fs,%0" : "=r" (segment) : "0" (segment) );
123
124  return segment;
125}
126
127static inline unsigned short i386_get_gs()
128{
129  register unsigned short segment = 0;
130
131  asm volatile ( "movw %%gs,%0" : "=r" (segment) : "0" (segment) );
132
133  return segment;
134}
135
136/*
137 * Added for pagination management
138 */
139
140static inline unsigned int i386_get_cr0()
141{
142  register unsigned int segment = 0;
143
144  asm volatile ( "movl %%cr0,%0" : "=r" (segment) : "0" (segment) );
145
146  return segment;
147}
148
149static inline void i386_set_cr0(unsigned int segment)
150{
151  asm volatile ( "movl %0,%%cr0" : "=r" (segment) : "0" (segment) );
152}
153
154static inline unsigned int i386_get_cr2()
155{
156  register unsigned int segment = 0;
157
158  asm volatile ( "movl %%cr2,%0" : "=r" (segment) : "0" (segment) );
159
160  return segment;
161}
162
163static inline unsigned int i386_get_cr3()
164{
165  register unsigned int segment = 0;
166
167  asm volatile ( "movl %%cr3,%0" : "=r" (segment) : "0" (segment) );
168
169  return segment;
170}
171
172static inline void i386_set_cr3(unsigned int segment)
173{
174  asm volatile ( "movl %0,%%cr3" : "=r" (segment) : "0" (segment) );
175}
176
177/*
178 *  IO Port Access Routines
179 */
180
181#define i386_outport_byte( _port, _value ) \
182   { register unsigned short __port  = _port; \
183     register unsigned char  __value = _value; \
184     \
185     asm volatile ( "outb %0,%1" : "=a" (__value), "=d" (__port) \
186                                 : "0"   (__value), "1"  (__port) \
187                  ); \
188   }
189
190#define i386_outport_word( _port, _value ) \
191   { register unsigned short __port  = _port; \
192     register unsigned short __value = _value; \
193     \
194     asm volatile ( "outw %0,%1" : "=a" (__value), "=d" (__port) \
195                                 : "0"   (__value), "1"  (__port) \
196                  ); \
197   }
198
199#define i386_outport_long( _port, _value ) \
200   { register unsigned short __port  = _port; \
201     register unsigned int  __value = _value; \
202     \
203     asm volatile ( "outl %0,%1" : "=a" (__value), "=d" (__port) \
204                                 : "0"   (__value), "1"  (__port) \
205                  ); \
206   }
207
208#define i386_inport_byte( _port, _value ) \
209   { register unsigned short __port  = _port; \
210     register unsigned char  __value = 0; \
211     \
212     asm volatile ( "inb %1,%0" : "=a" (__value), "=d" (__port) \
213                                : "0"   (__value), "1"  (__port) \
214                  ); \
215     _value = __value; \
216   }
217
218#define i386_inport_word( _port, _value ) \
219   { register unsigned short __port  = _port; \
220     register unsigned short __value = 0; \
221     \
222     asm volatile ( "inw %1,%0" : "=a" (__value), "=d" (__port) \
223                                : "0"   (__value), "1"  (__port) \
224                  ); \
225     _value = __value; \
226   }
227
228#define i386_inport_long( _port, _value ) \
229   { register unsigned short __port  = _port; \
230     register unsigned int  __value = 0; \
231     \
232     asm volatile ( "inl %1,%0" : "=a" (__value), "=d" (__port) \
233                                : "0"   (__value), "1"  (__port) \
234                  ); \
235     _value = __value; \
236   }
237
238/*
239 * Type definition for raw interrupts.
240 */
241
242typedef unsigned char  rtems_vector_offset;
243
244struct  __rtems_raw_irq_connect_data__;
245
246typedef void (*rtems_raw_irq_hdl)               (void);
247typedef void (*rtems_raw_irq_enable)            (const struct __rtems_raw_irq_connect_data__*);
248typedef void (*rtems_raw_irq_disable)           (const struct __rtems_raw_irq_connect_data__*);
249typedef int  (*rtems_raw_irq_is_enabled)        (const struct __rtems_raw_irq_connect_data__*);
250
251typedef struct __rtems_raw_irq_connect_data__{
252 /*
253  * IDT vector offset (IRQ line + PC386_IRQ_VECTOR_BASE)
254  */
255  rtems_vector_offset           idtIndex;
256  /*
257   * IDT raw handler. See comment on handler properties below in function prototype.
258   */
259  rtems_raw_irq_hdl             hdl;
260  /*
261   * function for enabling raw interrupts. In order to be consistent
262   * with the fact that the raw connexion can defined in the
263   * libcpu library, this library should have no knowledge of
264   * board specific hardware to manage interrupts and thus the
265   * "on" routine must enable the irq both at device and PIC level.
266   *
267   */
268    rtems_raw_irq_enable        on;     
269  /*
270   * function for disabling raw interrupts. In order to be consistent
271   * with the fact that the raw connexion can defined in the
272   * libcpu library, this library should have no knowledge of
273   * board specific hardware to manage interrupts and thus the
274   * "on" routine must disable the irq both at device and PIC level.
275   *
276   */
277  rtems_raw_irq_disable         off;
278  /*
279   * function enabling to know what interrupt may currently occur
280   */
281  rtems_raw_irq_is_enabled      isOn;
282}rtems_raw_irq_connect_data;
283
284typedef struct {
285  /*
286   * size of all the table fields (*Tbl) described below.
287   */
288  unsigned int                  idtSize;
289  /*
290   * Default handler used when disconnecting interrupts.
291   */
292  rtems_raw_irq_connect_data    defaultRawEntry;
293  /*
294   * Table containing initials/current value.
295   */
296  rtems_raw_irq_connect_data*   rawIrqHdlTbl;
297}rtems_raw_irq_global_settings;
298
299/*
300 * See page 14.9 Figure 14-2.
301 *
302 */
303typedef struct {
304  unsigned int low_offsets_bits : 16;
305  unsigned int segment_selector : 16;
306  unsigned int fixed_value_bits : 8;
307  unsigned int gate_type        : 5;
308  unsigned int privilege        : 2;
309  unsigned int present          : 1;
310  unsigned int high_offsets_bits: 16;
311}interrupt_gate_descriptor;
312
313
314/*
315 * C callable function enabling to create a interrupt_gate_descriptor
316 */
317void create_interrupt_gate_descriptor (interrupt_gate_descriptor*, rtems_raw_irq_hdl);
318
319/*
320 * C callable function enabling to get handler currently connected to a vector
321 *
322 */
323rtems_raw_irq_hdl get_hdl_from_vector(rtems_vector_offset);
324
325/*
326 * C callable function enabling to get easilly usable info from
327 * the actual value of IDT register.
328 */
329extern void i386_get_info_from_IDTR (interrupt_gate_descriptor** table,
330                                unsigned* limit);
331/*
332 * C callable function enabling to change the value of IDT register. Must be called
333 * with interrupts masked at processor level!!!.
334 */
335extern void i386_set_IDTR (interrupt_gate_descriptor* table,
336                      unsigned limit);
337
338/*
339 * C callable function enabling to set up one raw idt entry
340 */
341extern int i386_set_idt_entry (const rtems_raw_irq_connect_data*);
342
343/*
344 * C callable function enabling to get one current raw idt entry
345 */
346extern int i386_get_current_idt_entry (rtems_raw_irq_connect_data*);
347
348/*
349 * C callable function enabling to remove one current raw idt entry
350 */
351extern int i386_delete_idt_entry (const rtems_raw_irq_connect_data*);
352
353/*
354 * C callable function enabling to init idt.
355 *
356 * CAUTION : this function assumes that the IDTR register
357 * has been already set.
358 */
359extern int i386_init_idt (rtems_raw_irq_global_settings* config);
360
361/*
362 * C callable function enabling to get actual idt configuration
363 */
364extern int i386_get_idt_config (rtems_raw_irq_global_settings** config);
365
366
367/*
368 * See page 11.12 Figure 11-8.
369 *
370 */
371
372typedef struct {
373  unsigned int limit_15_0               : 16;
374  unsigned int base_address_15_0        : 16;
375  unsigned int base_address_23_16       : 8;
376  unsigned int type                     : 4;
377  unsigned int descriptor_type          : 1;
378  unsigned int privilege                : 2;
379  unsigned int present                  : 1;
380  unsigned int limit_19_16              : 4;
381  unsigned int available                : 1;
382  unsigned int fixed_value_bits         : 1;
383  unsigned int operation_size           : 1;
384  unsigned int granularity              : 1;
385  unsigned int base_address_31_24       : 8;
386}segment_descriptors;
387
388/*
389 * C callable function enabling to get easilly usable info from
390 * the actual value of GDT register.
391 */
392extern void i386_get_info_from_GDTR (segment_descriptors** table,
393                                     unsigned* limit);
394/*
395 * C callable function enabling to change the value of GDT register. Must be called
396 * with interrupts masked at processor level!!!.
397 */
398extern void i386_set_GDTR (segment_descriptors*,
399                           unsigned limit);
400
401/*
402 * C callable function enabling to set up one raw interrupt handler
403 */
404extern int i386_set_gdt_entry (unsigned short segment_selector, unsigned base,
405                                             unsigned limit);
406
407/*
408 * See page 11.18 Figure 11-12.
409 *
410 */
411
412typedef struct {
413  unsigned int offset                   : 12;
414  unsigned int page                     : 10;
415  unsigned int directory                : 10;
416}la_bits;
417
418typedef union {
419  la_bits       bits;
420  unsigned int  address;
421}linear_address;
422
423
424/*
425 * See page 11.20 Figure 11-14.
426 *
427 */
428
429typedef struct {
430  unsigned int present                  : 1;
431  unsigned int writable                 : 1;
432  unsigned int user                     : 1;
433  unsigned int write_through            : 1;
434  unsigned int cache_disable            : 1;
435  unsigned int accessed                 : 1;
436  unsigned int reserved1                : 1;
437  unsigned int page_size                : 1;
438  unsigned int reserved2                : 1;
439  unsigned int available                : 3;
440  unsigned int page_frame_address       : 20;
441}page_dir_bits;
442
443typedef union {
444  page_dir_bits bits;
445  unsigned int  dir_entry;
446}page_dir_entry;
447
448typedef struct {
449  unsigned int present                  : 1;
450  unsigned int writable                 : 1;
451  unsigned int user                     : 1;
452  unsigned int write_through            : 1;
453  unsigned int cache_disable            : 1;
454  unsigned int accessed                 : 1;
455  unsigned int dirty                    : 1;
456  unsigned int reserved2                : 2;
457  unsigned int available                : 3;
458  unsigned int page_frame_address       : 20;
459}page_table_bits;
460
461typedef union {
462  page_table_bits       bits;
463  unsigned int          table_entry;
464}page_table_entry;
465 
466/*
467 * definitions related to page table entry
468 */
469#define PG_SIZE 0x1000
470#define MASK_OFFSET 0xFFF
471#define MAX_ENTRY (PG_SIZE/sizeof(page_dir_entry))
472#define FOUR_MB       0x400000
473#define MASK_FLAGS 0x1A
474
475#define PTE_PRESENT             0x01
476#define PTE_WRITABLE            0x02
477#define PTE_USER                0x04
478#define PTE_WRITE_THROUGH       0x08
479#define PTE_CACHE_DISABLE       0x10
480
481typedef struct {
482  page_dir_entry pageDirEntry[MAX_ENTRY];
483}page_directory;
484
485typedef struct {
486  page_table_entry pageTableEntry[MAX_ENTRY];
487}page_table;
488
489static inline void flush_cache(){
490  asm volatile ("wbinvd");
491}
492
493
494/* C declaration for paging management */
495
496extern int      _CPU_is_cache_enabled();
497extern int      _CPU_is_paging_enabled();
498extern int      init_paging();
499extern void     _CPU_enable_paging();
500extern void     _CPU_disable_paging();
501extern void     _CPU_disable_cache();
502extern void     _CPU_enable_cache();
503extern int      _CPU_map_phys_address
504                      (void **mappedAddress, void *physAddress,
505                       int size, int flag); 
506extern int      _CPU_unmap_virt_address (void *mappedAddress, int size); 
507extern int      _CPU_change_memory_mapping_attribute
508                         (void **newAddress, void *mappedAddress,
509                          unsigned int size, unsigned int flag);
510extern int      _CPU_display_memory_attribute(); 
511
512# endif /* ASM */
513
514#endif
515
Note: See TracBrowser for help on using the repository browser.