1 // Memory access to BIOS variables.
2 //
3 // Copyright (C) 2008-2013 Kevin O'Connor <kevin@koconnor.net>
4 //
5 // This file may be distributed under the terms of the GNU LGPLv3 license.
6 #ifndef __BIOSVAR_H
7 #define __BIOSVAR_H
8
9 #include "autoconf.h" // CONFIG_*
10 #include "config.h" // SEG_BDA
11 #include "farptr.h" // GET_FARVAR
12 #include "memmap.h" // SYMBOL
13 #include "std/bda.h" // struct bios_data_area_s
14
15
16 /****************************************************************
17 * Interrupt vector table
18 ****************************************************************/
19
20 #if CONFIG_X86
21 #define GET_IVT(vector) \
22 GET_FARVAR(SEG_IVT, ((struct rmode_IVT *)0)->ivec[vector])
23 #define SET_IVT(vector, segoff) \
24 SET_FARVAR(SEG_IVT, ((struct rmode_IVT *)0)->ivec[vector], segoff)
25
26 #define FUNC16(func) ({ \
27 ASSERT32FLAT(); \
28 extern void func (void); \
29 SEGOFF(SEG_BIOS, (u32)func - BUILD_BIOS_ADDR); \
30 })
31 #elif CONFIG_PARISC
32 extern struct segoff_s ivt_table[256];
33
34 #define GET_IVT(vector) ivt_table[vector]
35 #define SET_IVT(vector, segoff) ivt_table[vector] = (segoff)
36
37 #define FUNC16(func) ({ SEGOFF(0, 0); })
38 #endif
39
40
41 /****************************************************************
42 * Bios Data Area (BDA)
43 ****************************************************************/
44
45 static inline struct bios_data_area_s *
get_bda_ptr(void)46 get_bda_ptr(void)
47 {
48 #if CONFIG_PARISC
49 extern struct bios_data_area_s bios_data_area;
50 return &bios_data_area;
51 #else
52 return MAKE_FLATPTR(SEG_BDA, 0);
53 #endif
54 }
55
56 // Accessor functions
57 #if CONFIG_X86
58 #define GET_BDA(var) \
59 GET_FARVAR(SEG_BDA, ((struct bios_data_area_s *)0)->var)
60 #define SET_BDA(var, val) \
61 SET_FARVAR(SEG_BDA, ((struct bios_data_area_s *)0)->var, (val))
62 #elif CONFIG_PARISC
63 #define GET_BDA(var) get_bda_ptr()->var
64 #define SET_BDA(var, val) get_bda_ptr()->var = (val)
65 #endif
66
67 // Helper function to set the bits of the equipment_list_flags variable.
set_equipment_flags(u16 clear,u16 set)68 static inline void set_equipment_flags(u16 clear, u16 set) {
69 u16 eqf = GET_BDA(equipment_list_flags);
70 SET_BDA(equipment_list_flags, (eqf & ~clear) | set);
71 }
72
73
74 /****************************************************************
75 * Extended Bios Data Area (EBDA)
76 ****************************************************************/
77
78 // The initial size and location of EBDA
79 #define EBDA_SIZE_START \
80 DIV_ROUND_UP(sizeof(struct extended_bios_data_area_s), 1024)
81 #define EBDA_SEGMENT_START \
82 FLATPTR_TO_SEG(BUILD_LOWRAM_END - EBDA_SIZE_START*1024)
83
84 // Accessor functions
get_ebda_seg(void)85 static inline u16 get_ebda_seg(void) {
86 return GET_BDA(ebda_seg);
87 }
88 static inline struct extended_bios_data_area_s *
get_ebda_ptr(void)89 get_ebda_ptr(void)
90 {
91 ASSERT32FLAT();
92 return MAKE_FLATPTR(get_ebda_seg(), 0);
93 }
94 #define GET_EBDA(eseg, var) \
95 GET_FARVAR(eseg, ((struct extended_bios_data_area_s *)0)->var)
96 #define SET_EBDA(eseg, var, val) \
97 SET_FARVAR(eseg, ((struct extended_bios_data_area_s *)0)->var, (val))
98
99
100 /****************************************************************
101 * Global variables
102 ****************************************************************/
103
104 #if MODE16 == 0 && MODESEGMENT == 1
105 // In 32bit segmented mode %cs may not be readable and the code may be
106 // relocated. The entry code sets up %gs with a readable segment and
107 // the code offset can be determined by get_global_offset().
108 #define GLOBAL_SEGREG GS
get_global_offset(void)109 static inline u32 __attribute_const get_global_offset(void) {
110 u32 ret;
111 asm(" calll 1f\n"
112 "1:popl %0\n"
113 " subl $1b, %0"
114 : "=r"(ret));
115 return ret;
116 }
117 #else
118 #define GLOBAL_SEGREG CS
get_global_offset(void)119 static inline u32 __attribute_const get_global_offset(void) {
120 return 0;
121 }
122 #endif
get_global_seg(void)123 static inline u16 get_global_seg(void) {
124 return GET_SEG(GLOBAL_SEGREG);
125 }
126 #if CONFIG_X86
127 #define GET_GLOBAL(var) \
128 GET_VAR(GLOBAL_SEGREG, *(typeof(&(var)))((void*)&(var) \
129 + get_global_offset()))
130 #elif CONFIG_PARISC
131 #define GET_GLOBAL(var) (var)
132 #endif
133
134 #if MODESEGMENT
135 #define GLOBALFLAT2GLOBAL(var) ((typeof(var))((void*)(var) - BUILD_BIOS_ADDR))
136 #else
137 #define GLOBALFLAT2GLOBAL(var) (var)
138 #endif
139 // Access a "flat" pointer known to point to the f-segment.
140 #define GET_GLOBALFLAT(var) GET_GLOBAL(*GLOBALFLAT2GLOBAL(&(var)))
141
142
143 /****************************************************************
144 * "Low" memory variables
145 ****************************************************************/
146
147 #define SEG_LOW SYMBOL(_zonelow_seg)
148
149 #if MODESEGMENT
150 #define GET_LOW(var) GET_FARVAR(SEG_LOW, (var))
151 #define SET_LOW(var, val) SET_FARVAR(SEG_LOW, (var), (val))
152 #define LOWFLAT2LOW(var) ((typeof(var))((void*)(var) - SYMBOL(zonelow_base)))
153 #else
154 #define GET_LOW(var) (var)
155 #define SET_LOW(var, val) do { (var) = (val); } while (0)
156 #define LOWFLAT2LOW(var) (var)
157 #endif
158 #define GET_LOWFLAT(var) GET_LOW(*LOWFLAT2LOW(&(var)))
159 #define SET_LOWFLAT(var, val) SET_LOW(*LOWFLAT2LOW(&(var)), (val))
160
161 #endif // __BIOSVAR_H
162