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