i386.h 4.6 KB

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