Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


SEABIOS updates to support reset and to simplify
[palacios.git] / bios / seabios / src / farptr.h
1 // Code to access multiple segments within gcc.
2 //
3 // Copyright (C) 2008,2009  Kevin O'Connor <kevin@koconnor.net>
4 //
5 // This file may be distributed under the terms of the GNU LGPLv3 license.
6 #ifndef __FARPTR_H
7 #define __FARPTR_H
8
9 #include "ioport.h" // insb
10
11 // Dummy definitions used to make sure gcc understands dependencies
12 // between SET_SEG and GET/READ/WRITE_SEG macros.
13 extern u16 __segment_ES, __segment_CS, __segment_DS, __segment_SS;
14 extern u16 __segment_FS, __segment_GS;
15
16 // Low level macros for reading/writing memory via a segment selector.
17 #define READ8_SEG(prefix, SEG, value, var)                      \
18     __asm__(prefix "movb %%" #SEG ":%1, %b0" : "=Qi"(value)     \
19             : "m"(var), "m"(__segment_ ## SEG))
20 #define READ16_SEG(prefix, SEG, value, var)                     \
21     __asm__(prefix "movw %%" #SEG ":%1, %w0" : "=ri"(value)     \
22             : "m"(var), "m"(__segment_ ## SEG))
23 #define READ32_SEG(prefix, SEG, value, var)                     \
24     __asm__(prefix "movl %%" #SEG ":%1, %0" : "=ri"(value)      \
25             : "m"(var), "m"(__segment_ ## SEG))
26 #define READ64_SEG(prefix, SEG, value, var) do {                \
27         union u64_u32_u __value;                                \
28         union u64_u32_u *__r64_ptr = (union u64_u32_u *)&(var); \
29         READ32_SEG(prefix, SEG, __value.hi, __r64_ptr->hi);     \
30         READ32_SEG(prefix, SEG, __value.lo, __r64_ptr->lo);     \
31         *(u64*)&(value) = __value.val;                          \
32     } while (0)
33 #define WRITE8_SEG(prefix, SEG, var, value)                     \
34     __asm__(prefix "movb %b1, %%" #SEG ":%0" : "=m"(var)        \
35             : "Q"(value), "m"(__segment_ ## SEG))
36 #define WRITE16_SEG(prefix, SEG, var, value)                    \
37     __asm__(prefix "movw %w1, %%" #SEG ":%0" : "=m"(var)        \
38             : "r"(value), "m"(__segment_ ## SEG))
39 #define WRITE32_SEG(prefix, SEG, var, value)                    \
40     __asm__(prefix "movl %1, %%" #SEG ":%0" : "=m"(var)         \
41             : "r"(value), "m"(__segment_ ## SEG))
42 #define WRITE64_SEG(prefix, SEG, var, value) do {               \
43         union u64_u32_u __value;                                \
44         union u64_u32_u *__w64_ptr = (union u64_u32_u *)&(var); \
45         typeof(var) __value_tmp = (value);                      \
46         __value.val = *(u64*)&__value_tmp;                      \
47         WRITE32_SEG(prefix, SEG, __w64_ptr->hi, __value.hi);    \
48         WRITE32_SEG(prefix, SEG, __w64_ptr->lo, __value.lo);    \
49     } while (0)
50
51 // Macros for automatically choosing the appropriate memory size
52 // access method.
53 extern void __force_link_error__unknown_type(void);
54
55 #define __GET_VAR(prefix, seg, var) ({          \
56     typeof(var) __val;                          \
57     if (sizeof(__val) == 1)                     \
58         READ8_SEG(prefix, seg, __val, var);     \
59     else if (sizeof(__val) == 2)                \
60         READ16_SEG(prefix, seg, __val, var);    \
61     else if (sizeof(__val) == 4)                \
62         READ32_SEG(prefix, seg, __val, var);    \
63     else if (sizeof(__val) == 8)                \
64         READ64_SEG(prefix, seg, __val, var);    \
65     else                                        \
66         __force_link_error__unknown_type();     \
67     __val; })
68
69 #define __SET_VAR(prefix, seg, var, val) do {           \
70         if (sizeof(var) == 1)                           \
71             WRITE8_SEG(prefix, seg, var, (val));        \
72         else if (sizeof(var) == 2)                      \
73             WRITE16_SEG(prefix, seg, var, (val));       \
74         else if (sizeof(var) == 4)                      \
75             WRITE32_SEG(prefix, seg, var, (val));       \
76         else if (sizeof(var) == 8)                      \
77             WRITE64_SEG(prefix, seg, var, (val));       \
78         else                                            \
79             __force_link_error__unknown_type();         \
80     } while (0)
81
82 // Low level macros for getting/setting a segment register.
83 #define __SET_SEG(SEG, value)                                   \
84     __asm__("movw %w1, %%" #SEG : "=m"(__segment_ ## SEG)       \
85             : "rm"(value))
86 #define __GET_SEG(SEG) ({                                       \
87     u16 __seg;                                                  \
88     __asm__("movw %%" #SEG ", %w0" : "=rm"(__seg)               \
89             : "m"(__segment_ ## SEG));                          \
90     __seg;})
91
92 // Macros for accessing a variable in another segment.  (They
93 // automatically update the %es segment and then make the appropriate
94 // access.)
95 #define __GET_FARVAR(seg, var) ({               \
96     SET_SEG(ES, (seg));                         \
97     GET_VAR(ES, (var)); })
98 #define __SET_FARVAR(seg, var, val) do {        \
99         typeof(var) __sfv_val = (val);          \
100         SET_SEG(ES, (seg));                     \
101         SET_VAR(ES, (var), __sfv_val);          \
102     } while (0)
103
104 // Macros for accesssing a 32bit flat mode pointer from 16bit real
105 // mode.  (They automatically update the %es segment, break the
106 // pointer into segment/offset, and then make the access.)
107 #define __GET_FLATPTR(ptr) ({                                   \
108     typeof(&(ptr)) __ptr = &(ptr);                              \
109     GET_FARVAR(FLATPTR_TO_SEG(__ptr)                            \
110                , *(typeof(__ptr))FLATPTR_TO_OFFSET(__ptr)); })
111 #define __SET_FLATPTR(ptr, val) do {                            \
112         typeof (&(ptr)) __ptr = &(ptr);                         \
113         SET_FARVAR(FLATPTR_TO_SEG(__ptr)                        \
114                    , *(typeof(__ptr))FLATPTR_TO_OFFSET(__ptr)   \
115                    , (val));                                    \
116     } while (0)
117
118 // Macros for converting to/from 32bit flat mode pointers to their
119 // equivalent 16bit segment/offset values.
120 #define FLATPTR_TO_SEG(p) (((u32)(p)) >> 4)
121 #define FLATPTR_TO_OFFSET(p) (((u32)(p)) & 0xf)
122 #define MAKE_FLATPTR(seg,off) ((void*)(((u32)(seg)<<4)+(u32)(off)))
123
124
125 #if MODESEGMENT == 1
126
127 // Definitions when using segmented mode.
128 #define GET_FARVAR(seg, var) __GET_FARVAR((seg), (var))
129 #define SET_FARVAR(seg, var, val) __SET_FARVAR((seg), (var), (val))
130 #define GET_VAR(seg, var) __GET_VAR("", seg, (var))
131 #define SET_VAR(seg, var, val) __SET_VAR("", seg, (var), (val))
132 #define SET_SEG(SEG, value) __SET_SEG(SEG, (value))
133 #define GET_SEG(SEG) __GET_SEG(SEG)
134 #define GET_FLATPTR(ptr) __GET_FLATPTR(ptr)
135 #define SET_FLATPTR(ptr, val) __SET_FLATPTR((ptr), (val))
136
137 static inline void insb_fl(u16 port, void *ptr_fl, u16 count) {
138     SET_SEG(ES, FLATPTR_TO_SEG(ptr_fl));
139     insb(port, (u8*)FLATPTR_TO_OFFSET(ptr_fl), count);
140 }
141 static inline void insw_fl(u16 port, void *ptr_fl, u16 count) {
142     SET_SEG(ES, FLATPTR_TO_SEG(ptr_fl));
143     insw(port, (u16*)FLATPTR_TO_OFFSET(ptr_fl), count);
144 }
145 static inline void insl_fl(u16 port, void *ptr_fl, u16 count) {
146     SET_SEG(ES, FLATPTR_TO_SEG(ptr_fl));
147     insl(port, (u32*)FLATPTR_TO_OFFSET(ptr_fl), count);
148 }
149 static inline void outsb_fl(u16 port, void *ptr_fl, u16 count) {
150     SET_SEG(ES, FLATPTR_TO_SEG(ptr_fl));
151     outsb(port, (u8*)FLATPTR_TO_OFFSET(ptr_fl), count);
152 }
153 static inline void outsw_fl(u16 port, void *ptr_fl, u16 count) {
154     SET_SEG(ES, FLATPTR_TO_SEG(ptr_fl));
155     outsw(port, (u16*)FLATPTR_TO_OFFSET(ptr_fl), count);
156 }
157 static inline void outsl_fl(u16 port, void *ptr_fl, u16 count) {
158     SET_SEG(ES, FLATPTR_TO_SEG(ptr_fl));
159     outsl(port, (u32*)FLATPTR_TO_OFFSET(ptr_fl), count);
160 }
161
162 #else
163
164 // In 32-bit flat mode there is no need to mess with the segments.
165 #define GET_FARVAR(seg, var) \
166     (*((typeof(&(var)))MAKE_FLATPTR((seg), &(var))))
167 #define SET_FARVAR(seg, var, val) \
168     do { GET_FARVAR((seg), (var)) = (val); } while (0)
169 #define GET_VAR(seg, var) (var)
170 #define SET_VAR(seg, var, val) do { (var) = (val); } while (0)
171 #define SET_SEG(SEG, value) ((void)(value))
172 #define GET_SEG(SEG) 0
173 #define GET_FLATPTR(ptr) (ptr)
174 #define SET_FLATPTR(ptr, val) do { (ptr) = (val); } while (0)
175
176 #define insb_fl(port, ptr_fl, count) insb(port, ptr_fl, count)
177 #define insw_fl(port, ptr_fl, count) insw(port, ptr_fl, count)
178 #define insl_fl(port, ptr_fl, count) insl(port, ptr_fl, count)
179 #define outsb_fl(port, ptr_fl, count) outsb(port, ptr_fl, count)
180 #define outsw_fl(port, ptr_fl, count) outsw(port, ptr_fl, count)
181 #define outsl_fl(port, ptr_fl, count) outsl(port, ptr_fl, count)
182
183 #endif
184
185 // Definition for common 16bit segment/offset pointers.
186 struct segoff_s {
187     union {
188         struct {
189             u16 offset;
190             u16 seg;
191         };
192         u32 segoff;
193     };
194 };
195 #define SEGOFF(s,o) ({struct segoff_s __so; __so.offset=(o); __so.seg=(s); __so;})
196
197 static inline struct segoff_s FLATPTR_TO_SEGOFF(void *p) {
198     return SEGOFF(FLATPTR_TO_SEG(p), FLATPTR_TO_OFFSET(p));
199 }
200 static inline void *SEGOFF_TO_FLATPTR(struct segoff_s so) {
201     return MAKE_FLATPTR(so.seg, so.offset);
202 }
203
204 #endif // farptr.h